diff options
author | uint23 <[email protected]> | 2025-04-20 01:28:31 +0100 |
---|---|---|
committer | uint23 <[email protected]> | 2025-04-20 01:28:31 +0100 |
commit | 87179f825fd1c46b59cce38aafd8b4102fca2685 (patch) | |
tree | b384c15d41ffdc48a1427244daf16d90b9bd75f3 | |
parent | 29a67d193e8dbbb8985fbef4cc6f24589947b869 (diff) |
added workspaces
whoops, forgot to commit for a whiiilllleee
-rw-r--r-- | src/defs.h | 47 | ||||
-rw-r--r-- | src/sxwm.c | 147 | ||||
-rw-r--r-- | src/usercfg.h | 70 |
3 files changed, 222 insertions, 42 deletions
@@ -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{ @@ -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), }; |