summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoruint23 <[email protected]>2025-04-20 01:28:31 +0100
committeruint23 <[email protected]>2025-04-20 01:28:31 +0100
commit87179f825fd1c46b59cce38aafd8b4102fca2685 (patch)
treeb384c15d41ffdc48a1427244daf16d90b9bd75f3
parent29a67d193e8dbbb8985fbef4cc6f24589947b869 (diff)
added workspaces
whoops, forgot to commit for a whiiilllleee
-rw-r--r--src/defs.h47
-rw-r--r--src/sxwm.c147
-rw-r--r--src/usercfg.h70
3 files changed, 222 insertions, 42 deletions
diff --git a/src/defs.h b/src/defs.h
index ec4ab25..b7b2d20 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -15,11 +15,50 @@
#define MARGIN (gaps + BORDER_WIDTH)
#define OUT_IN (2 * BORDER_WIDTH)
#define LENGTH(X) (sizeof X / sizeof X[0])
-#define BIND(mod, key, cmdstr) { (mod), XK_##key, { cmdstr }, 0 }
-#define CALL(mod, key, fnptr) { (mod), XK_##key, { .fn = fnptr }, 1 }
-#define CMD(name, ...) \
+#define BIND(mod, key, cmdstr) { (mod), XK_##key, { cmdstr }, False }
+#define CALL(mod, key, fnptr) { (mod), XK_##key, { .fn = fnptr }, True }
+#define CMD(name, ...) \
static const char *name[] = { __VA_ARGS__, NULL }
+static void change_ws1(void);
+static void moveto_ws1(void);
+static void change_ws2(void);
+static void moveto_ws2(void);
+static void change_ws3(void);
+static void moveto_ws3(void);
+static void change_ws4(void);
+static void moveto_ws4(void);
+static void change_ws5(void);
+static void moveto_ws5(void);
+static void change_ws6(void);
+static void moveto_ws6(void);
+static void change_ws7(void);
+static void moveto_ws7(void);
+static void change_ws8(void);
+static void moveto_ws8(void);
+static void change_ws9(void);
+static void moveto_ws9(void);
+
+#define INIT_WORKSPACE \
+static void change_ws1(void) { change_workspace(0); } \
+static void moveto_ws1(void) { move_to_workspace(0); } \
+static void change_ws2(void) { change_workspace(1); } \
+static void moveto_ws2(void) { move_to_workspace(1); } \
+static void change_ws3(void) { change_workspace(2); } \
+static void moveto_ws3(void) { move_to_workspace(2); } \
+static void change_ws4(void) { change_workspace(3); } \
+static void moveto_ws4(void) { move_to_workspace(3); } \
+static void change_ws5(void) { change_workspace(4); } \
+static void moveto_ws5(void) { move_to_workspace(4); } \
+static void moveto_ws6(void) { move_to_workspace(5); } \
+static void change_ws6(void) { change_workspace(5); } \
+static void moveto_ws7(void) { move_to_workspace(6); } \
+static void change_ws7(void) { change_workspace(6); } \
+static void moveto_ws8(void) { move_to_workspace(7); } \
+static void change_ws8(void) { change_workspace(7); } \
+static void moveto_ws9(void) { move_to_workspace(8); } \
+static void change_ws9(void) { change_workspace(8); } \
+
#define UDIST(a,b) abs((int)(a) - (int)(b))
#define MAXCLIENTS 99
#define MAXGAPS 100
@@ -36,7 +75,7 @@ typedef struct {
unsigned int mods;
KeySym keysym;
Action action;
- int is_func;
+ Bool is_func;
} Binding;
typedef struct Client{
diff --git a/src/sxwm.c b/src/sxwm.c
index 48af7ae..f55523e 100644
--- a/src/sxwm.c
+++ b/src/sxwm.c
@@ -29,6 +29,7 @@
#include "defs.h"
static void add_client(Window w);
+static void change_workspace(uint ws);
static uint clean_mask(uint mask);
static void close_focused(void);
static void dec_gaps(void);
@@ -46,6 +47,7 @@ static void hdl_motion(XEvent *xev);
static void inc_gaps(void);
static void move_master_next(void);
static void move_master_prev(void);
+static void move_to_workspace(uint ws);
static void other_wm(void);
static int other_wm_err(Display *dpy, XErrorEvent *ee);
static ulong parse_col(const char *hex);
@@ -71,7 +73,6 @@ static Atom atom_net_workarea;
static Cursor c_normal, c_move, c_resize;
static Client *workspaces[NUM_WORKSPACES] = { NULL };
static uint current_ws = 0;
-static Client *clients = NULL; // TO BE REMOVED TODO
static Client *drag_client = NULL;
static Client *focused = NULL;
static EventHandler evtable[LASTEvent];
@@ -93,6 +94,7 @@ static uint reserve_left = 0;
static uint reserve_right = 0;
static uint reserve_top = 0;
static uint reserve_bottom = 0;
+INIT_WORKSPACE
static void
add_client(Window w)
@@ -103,8 +105,8 @@ add_client(Window w)
return;
}
c->win = w;
- c->next = clients;
- clients = c;
+ c->next = workspaces[current_ws];
+ workspaces[current_ws] = c;
if (!focused)
focused = c;
++open_windows;
@@ -138,7 +140,7 @@ clean_mask(uint mask)
static void
close_focused(void)
{
- if (!clients)
+ if (!workspaces[current_ws])
return;
Window w = focused->win;
@@ -161,7 +163,7 @@ focus_next(void)
if (!focused)
return;
- focused = (focused->next ? focused->next : clients);
+ focused = (focused->next ? focused->next : workspaces[current_ws]);
XSetInputFocus(dpy, focused->win, RevertToPointerRoot, CurrentTime);
XRaiseWindow(dpy, focused->win);
update_borders();
@@ -173,7 +175,7 @@ focus_prev(void)
if (!focused)
return;
- Client *p = clients, *prev = NULL;
+ Client *p = workspaces[current_ws], *prev = NULL;
while (p && p != focused) {
prev = p;
p = p->next;
@@ -217,7 +219,8 @@ hdl_button(XEvent *xev)
Window w = e->subwindow;
if (!w) return;
- for (Client *c = clients; c; c = c->next) {
+ Client *head = workspaces[current_ws];
+ for (Client *c = head; c; c = c->next) {
if (c->win != w)
continue;
@@ -272,7 +275,7 @@ hdl_destroy_ntf(XEvent *xev)
{
Window w = xev->xdestroywindow.window;
- Client *prev = NULL, *c = clients;
+ Client *prev = NULL, *c = workspaces[current_ws];
while (c && c->win != w) {
prev = c;
c = c->next;
@@ -287,7 +290,7 @@ hdl_destroy_ntf(XEvent *xev)
focused = NULL;
}
if (!prev)
- clients = c->next;
+ workspaces[current_ws] = c->next;
else
prev->next = c->next;
free(c);
@@ -309,7 +312,8 @@ hdl_enter(XEvent *xev)
{
Window w = xev->xcrossing.window;
- for (Client *c = clients; c; c = c->next) {
+ Client *head = workspaces[current_ws];
+ for (Client *c = head; c; c = c->next) {
if (c->win == w) {
focused = c;
XSetInputFocus(dpy, w, RevertToPointerRoot, CurrentTime);
@@ -464,12 +468,12 @@ inc_gaps(void)
static void
move_master_next(void)
{
- if (!clients || !clients->next)
+ if (!workspaces[current_ws] || !workspaces[current_ws]->next)
return;
- Client *first = clients;
- clients = first->next;
+ Client *first = workspaces[current_ws];
+ workspaces[current_ws] = first->next;
first->next = NULL;
- Client *tail = clients;
+ Client *tail = workspaces[current_ws];
while (tail->next)
tail = tail->next;
tail->next = first;
@@ -480,21 +484,46 @@ move_master_next(void)
static void
move_master_prev(void)
{
- if (!clients || !clients->next)
+ if (!workspaces[current_ws] || !workspaces[current_ws]->next)
return;
- Client *prev = NULL, *cur = clients;
+ Client *prev = NULL, *cur = workspaces[current_ws];
while (cur->next) {
prev = cur;
cur = cur->next;
}
prev->next = NULL;
- cur->next = clients;
- clients = cur;
+ cur->next = workspaces[current_ws];
+ workspaces[current_ws] = cur;
tile();
update_borders();
}
static void
+move_to_workspace(uint ws)
+{
+ if (!focused || ws >= NUM_WORKSPACES || ws == current_ws)
+ return;
+
+ /* remove from current list */
+ Client **pp = &workspaces[current_ws];
+ while (*pp && *pp != focused) pp = &(*pp)->next;
+ if (*pp) *pp = focused->next;
+
+ /* push to target list */
+ focused->next = workspaces[ws];
+ workspaces[ws] = focused;
+
+ /* unmap it here if switching away */
+ XUnmapWindow(dpy, focused->win);
+
+ /* tile current ws */
+ tile();
+ focused = workspaces[current_ws];
+ if (focused)
+ XSetInputFocus(dpy, focused->win, RevertToPointerRoot, CurrentTime);
+}
+
+static void
other_wm(void)
{
XSetErrorHandler(other_wm_err);
@@ -537,9 +566,11 @@ parse_col(const char *hex)
static void
quit(void)
{
- for (Client *c = clients; c; c = c->next) {
- XUnmapWindow(dpy, c->win);
- XKillClient(dpy, c->win);
+ for (uint ws = 0; ws < NUM_WORKSPACES; ++ws) {
+ for (Client *c = workspaces[ws]; c; c = c->next) {
+ XUnmapWindow(dpy, c->win);
+ XKillClient(dpy, c->win);
+ }
}
XSync(dpy, False);
XCloseDisplay(dpy);
@@ -601,27 +632,51 @@ setup(void)
static void
setup_atoms(void)
{
- /* intern the atoms we need */
+ /* bar atoms */
atom_net_supported = XInternAtom(dpy, "_NET_SUPPORTED", False);
atom_wm_strut_partial = XInternAtom(dpy, "_NET_WM_STRUT_PARTIAL", False);
atom_wm_window_type = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
atom_net_wm_window_type_dock = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
atom_net_workarea = XInternAtom(dpy, "_NET_WORKAREA", False);
- /* advertise which EWMH hints we support on the root window */
Atom support_list[] = {
XInternAtom(dpy, "_NET_WM_STRUT_PARTIAL", False),
XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False),
XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK",False),
XInternAtom(dpy, "_NET_WORKAREA", False),
- /* you can add more here as you implement them: */
- /* _NET_CLIENT_LIST, _NET_ACTIVE_WINDOW, etc. */
};
+
XChangeProperty(dpy, root,
atom_net_supported,
XA_ATOM, 32, PropModeReplace,
(unsigned char*)support_list,
sizeof(support_list)/sizeof(Atom));
+
+ /* workspace atoms */
+ Atom a_num = XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False);
+ Atom a_names= XInternAtom(dpy, "_NET_DESKTOP_NAMES", False);
+
+ long num = NUM_WORKSPACES;
+ XChangeProperty(dpy, root, a_num, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)&num, 1);
+
+ const char names[] = WORKSPACE_NAMES;
+ uint names_len = sizeof(names);
+
+ XChangeProperty(dpy, root,
+ a_names,
+ XInternAtom(dpy, "UTF8_STRING", False),
+ 8,
+ PropModeReplace,
+ (unsigned char*)names,
+ names_len);
+
+ ulong initial = current_ws;
+ XChangeProperty(dpy, root,
+ XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False),
+ XA_CARDINAL, 32,
+ PropModeReplace,
+ (unsigned char*)&initial, 1);
}
static void
@@ -646,7 +701,8 @@ static void
tile(void)
{
uint total_windows = 0;
- for (Client *c = clients; c; c = c->next)
+ Client *head = workspaces[current_ws];
+ for (Client *c = head; c; c = c->next)
if (!c->floating)
++total_windows;
if (total_windows == 0)
@@ -684,7 +740,7 @@ tile(void)
: workarea_height;
uint index = 0;
- for (Client *c = clients; c; c = c->next) {
+ for (Client *c = workspaces[current_ws]; c; c = c->next) {
if (c->floating)
continue;
@@ -757,14 +813,14 @@ toggle_floating_global(void)
{
global_floating = !global_floating;
Bool any_tiled = False;
- for (Client *c = clients; c; c = c->next) {
+ for (Client *c = workspaces[current_ws]; c; c = c->next) {
if (!c->floating) {
any_tiled = True;
break;
}
}
- for (Client *c = clients; c; c = c->next) {
+ for (Client *c = workspaces[current_ws]; c; c = c->next) {
c->floating = any_tiled;
if (c->floating) {
XWindowAttributes wa;
@@ -793,12 +849,43 @@ toggle_floating_global(void)
static void
update_borders(void)
{
- for (Client *c = clients; c; c = c->next) {
+ for (Client *c = workspaces[current_ws]; c; c = c->next) {
XSetWindowBorder(dpy, c->win,
(c == focused ? border_foc_col : border_ufoc_col));
}
}
+static void
+change_workspace(uint ws)
+{
+ if (ws >= NUM_WORKSPACES || ws == current_ws)
+ return;
+
+ /* unmap old desktop */
+ for (Client *c = workspaces[current_ws]; c; c=c->next)
+ XUnmapWindow(dpy, c->win);
+
+ current_ws = ws;
+
+ /* map new desktop */
+ for (Client *c = workspaces[current_ws]; c; c=c->next)
+ XMapWindow(dpy, c->win);
+
+ /* retile & refocus */
+ tile();
+ if (workspaces[current_ws]) {
+ focused = workspaces[current_ws];
+ XSetInputFocus(dpy, focused->win, RevertToPointerRoot, CurrentTime);
+ }
+
+ /* update atom */
+ ulong cd = current_ws;
+ XChangeProperty(dpy, root,
+ XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False),
+ XA_CARDINAL, 32, PropModeReplace,
+ (u_char*)&cd, 1);
+}
+
static int
xerr(Display *dpy, XErrorEvent *ee)
{
diff --git a/src/usercfg.h b/src/usercfg.h
index f7cdb69..1059ce5 100644
--- a/src/usercfg.h
+++ b/src/usercfg.h
@@ -1,6 +1,5 @@
/*< You can ignore this >*/
#include <X11/keysym.h>
-#include "defs.h"
/*
* ——————————————< Appearance >—————————————— *
@@ -39,9 +38,17 @@
* until the window *snaps* to the edge
*
* NUM_WORKSPACES (int):
- * This is how many workspaces you want
- * in this window manager. Best to leave
- * it default (9).
+ * This is how many workspaces you want in
+ * this window manager. Best to leave it
+ * default (9).
+ *
+ * WORKSPACE_NAMES (char[]):
+ * This is just the label that will appear
+ * on your status bar. Doesn't have to be
+ * a number, it can be anything. Ignore
+ * the "\0", this is just a NULL that says
+ * to start again, otherwise it would be
+ * all of them concatenated together.
*
* ———————————————————————————————————————————*
*/
@@ -57,6 +64,16 @@
#define SNAP_DISTANCE 5
#define NUM_WORKSPACES 9
+#define WORKSPACE_NAMES \
+ "1" "\0"\
+ "2" "\0"\
+ "3" "\0"\
+ "4" "\0"\
+ "5" "\0"\
+ "6" "\0"\
+ "7" "\0"\
+ "8" "\0"\
+ "9" "\0"\
/*
* ————————————< Keys & Bindins >—————————————*
@@ -92,10 +109,16 @@ CMD(browser, "firefox");
* perform some actions.
*
* How do you bind keys? In sxwm, there is
- * two ways to bind keys to perform tasks,
- * BIND, or CALL. CALL, calls a function
- * whereas BIND, executes a specified
+ * three ways to bind keys to perform
+ * tasks:
+ *
+ * BIND, CALL or WORKSPACE.
+ * CALL, calls a function,
+ * BIND, executes a specified
* program.
+ * WORKSPACE, sets the bind to move
+ * and item to said workspace or to
+ * change to that workspace.
*
* USEAGE:
* BIND(MODIFIERS, KEY, FUNCTION)
@@ -136,9 +159,10 @@ CMD(browser, "firefox");
static const Binding binds[] =
{
-/*——< MODIFIER(S) >—————< KEY >—————< FUNCTION >——*/
+/*————< MODIFIER(S) >< KEY >—————< FUNCTION >——*/
/*———————< Here are your functions calls >————— — */
+
CALL(MOD|SHIFT, e, quit),
CALL(MOD|SHIFT, q, close_focused),
@@ -155,6 +179,36 @@ static const Binding binds[] =
CALL(MOD|SHIFT, space, toggle_floating_global),
/*—————< Here are your executable functions >—————*/
+
BIND(MOD, Return, terminal),
BIND(MOD, b, browser),
+
+/*—————< This is for workspaces >—————————————————*/
+
+ CALL(MOD, 1, change_ws1),
+ CALL(MOD|SHIFT, 1, moveto_ws1),
+
+ CALL(MOD, 2, change_ws2),
+ CALL(MOD|SHIFT, 2, moveto_ws2),
+
+ CALL(MOD, 3, change_ws3),
+ CALL(MOD|SHIFT, 3, moveto_ws3),
+
+ CALL(MOD, 4, change_ws4),
+ CALL(MOD|SHIFT, 4, moveto_ws4),
+
+ CALL(MOD, 5, change_ws5),
+ CALL(MOD|SHIFT, 5, moveto_ws5),
+
+ CALL(MOD, 6, change_ws6),
+ CALL(MOD|SHIFT, 6, moveto_ws6),
+
+ CALL(MOD, 7, change_ws7),
+ CALL(MOD|SHIFT, 7, moveto_ws7),
+
+ CALL(MOD, 8, change_ws8),
+ CALL(MOD|SHIFT, 8, moveto_ws8),
+
+ CALL(MOD, 9, change_ws9),
+ CALL(MOD|SHIFT, 9, moveto_ws9),
};