diff options
author | B. Bergeron <[email protected]> | 2025-05-17 09:07:28 -0400 |
---|---|---|
committer | B. Bergeron <[email protected]> | 2025-05-17 09:07:28 -0400 |
commit | 32723114e2ddcf4ac6d647635b38a572c2459271 (patch) | |
tree | 6cde6e4e2e3d2a2afa80c4b5298895631804d0e5 | |
parent | 11bfcf4291bb0b72fd94b8bb69b7fabd3c3fea35 (diff) |
Functions:
- add_client
- update_struts
- main
- setup
- close_focused
- change_workspace
- and some variables
-rw-r--r-- | src/sxwm.c | 72 |
1 files changed, 72 insertions, 0 deletions
@@ -102,13 +102,16 @@ Atom atom_net_wm_name; Atom atom_utf8_string; Cursor c_normal, c_move, c_resize; +/* List of client for each workspace (linked list) */ Client *workspaces[NUM_WORKSPACES] = {NULL}; Config default_config; Config user_config; +/* The current workspace */ int current_ws = 0; DragMode drag_mode = DRAG_NONE; Client *drag_client = NULL; Client *swap_target = NULL; +/* The currently focused client */ Client *focused = NULL; EventHandler evtable[LASTEvent]; Display *dpy; @@ -119,7 +122,9 @@ int monsn = 0; Bool global_floating = False; long last_motion_time = 0; +/* The full X11 screen width */ int scr_width; +/* The full X11 screen height */ int scr_height; int open_windows = 0; int drag_start_x, drag_start_y; @@ -130,18 +135,28 @@ int reserve_right = 0; int reserve_top = 0; int reserve_bottom = 0; +/** + * Create a client, add it to a workspace, focus it under certain conditions, + * and link the window object to the client object. + * + * w - An X11 window object + * ws - The workspace in which to add the client + */ Client *add_client(Window w, int ws) { + // Allocate a new client Client *c = malloc(sizeof(Client)); if (!c) { fprintf(stderr, "sxwm: could not alloc memory for client\n"); return NULL; } + // Attribute some misc. values c->win = w; c->next = NULL; c->ws = ws; + // Add client to current workspace (linked list) if (!workspaces[ws]) { workspaces[ws] = c; } @@ -152,17 +167,30 @@ Client *add_client(Window w, int ws) tail->next = c; } + // Focus on the new client if it's being added to the focused workspace and + // no other client is currently focused if (ws == current_ws && !focused) { focused = c; } open_windows++; + + // Ask X11 to report these input even for window `w`: + // - EnterWindowMask Pointer enters windows + // - LeaveWindowMask Pointer leaves windows + // - FocusChangeMask Focus changes (???) + // - PropertyChangeMask Window properties change + // - StructureNotifyMask Window structure change XSelectInput(dpy, w, EnterWindowMask | LeaveWindowMask | FocusChangeMask | PropertyChangeMask | StructureNotifyMask); + // Tell X11 that the window `w` is willing to participate in the + // "WM_DELETE_WINDOW" protocol. (In other words, this re-defined the + // window's WM_PROTOCOLS property) Atom protos[] = {atom_wm_delete}; XSetWMProtocols(dpy, w, protos, 1); + // Copy the window's geometry value into the client struct XWindowAttributes wa; XGetWindowAttributes(dpy, w, &wa); c->x = wa.x; @@ -170,10 +198,20 @@ Client *add_client(Window w, int ws) c->w = wa.width; c->h = wa.height; + // If a client is focused, put the new client under the focused client's + // monitor... + // + // REVIEW: I think it would be best to put it inside the monitor occupied by + // the pointer. if (focused) { c->mon = focused->mon; } else { + // ...Otherwise, put it in the monitor in which the center of the client + // is currently in (Fallback: first monitor). + // + // cx = client h center, cy = client v center + /* need better way to determine mon */ int cx = c->x + c->w / 2, cy = c->y + c->h / 2; c->mon = 0; @@ -185,41 +223,58 @@ Client *add_client(Window w, int ws) } } + // Set default display value for client c->fixed = False; c->floating = False; c->fullscreen = False; + // Follow globa_floating rule if (global_floating) { c->floating = True; } + // Bring window to the front. Usefull only if the client was spawned in + // floating mode XRaiseWindow(dpy, w); return c; } +/** + * Change the current workspace. + * + * ws - the new workspace index + */ void change_workspace(int ws) { + // Do nothing if the workspace doesn't exist or is already in view if (ws >= NUM_WORKSPACES || ws == current_ws) { return; } XGrabServer(dpy); + // Hide current workspace's windows for (Client *c = workspaces[current_ws]; c; c = c->next) { XUnmapWindow(dpy, c->win); } + // Change the current workspace current_ws = ws; + // Display the windows of the new workspace for (Client *c = workspaces[current_ws]; c; c = c->next) { XMapWindow(dpy, c->win); } + // Probably tile windows back into workspace? tile(); + + // If the new workspace is not empty, focus on its first window. if (workspaces[current_ws]) { focused = workspaces[current_ws]; XSetInputFocus(dpy, focused->win, RevertToPointerRoot, CurrentTime); } + // Change the root window's _NET_CURRENT_DESKTOP property to the new one long cd = current_ws; XChangeProperty(dpy, root, XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&cd, 1); @@ -232,8 +287,12 @@ int clean_mask(int mask) return mask & ~(LockMask | Mod2Mask | Mod3Mask); } +/** + * Close the currently focused window + */ void close_focused(void) { + // Do nothing if no window is focused if (!focused) { return; } @@ -859,10 +918,16 @@ void hdl_root_property(XEvent *xev) } } +/** + * Update reserve_left, reserve_right, reserve_top, and reserve_bottom to + * encompase every (visible?) windows, excluding docks. + */ void update_struts(void) { + // Reset the "reserve" values reserve_left = reserve_right = reserve_top = reserve_bottom = 0; + // Get a list of every window and the window count Window root_ret, parent_ret, *children; unsigned int nchildren; if (!XQueryTree(dpy, root, &root_ret, &parent_ret, &children, &nchildren)) @@ -881,6 +946,7 @@ void update_struts(void) !types) continue; + // Skip this window if it's a dock Bool is_dock = False; for (unsigned long j = 0; j < nitems; j++) { if (types[j] == atom_net_wm_window_type_dock) { @@ -892,6 +958,8 @@ void update_struts(void) if (!is_dock) continue; + // Using each window's _NET_WM_STRUT_PARTIAL (or _NET_WM_STRUT), update + // the reserve_ variables to encompase every (visible?) window long *str = NULL; Atom actual; int sfmt; @@ -1179,9 +1247,12 @@ void send_wm_take_focus(Window w) void setup(void) { + // Connect to X11 if ((dpy = XOpenDisplay(NULL)) == 0) { errx(0, "can't open display. quitting..."); } + + // Get the root window root = XDefaultRootWindow(dpy); setup_atoms(); @@ -1681,6 +1752,7 @@ void xev_case(XEvent *xev) int main(int ac, char **av) { + // Handle argument. Only -v/--version is supported. if (ac > 1) { if (strcmp(av[1], "-v") == 0 || strcmp(av[1], "--version") == 0) { printf("%s\n%s\n%s", SXWM_VERSION, SXWM_AUTHOR, SXWM_LICINFO); |