From 833dba4476760afde264f71aaa6a758ad4b87c2c Mon Sep 17 00:00:00 2001 From: jasper-clarke Date: Mon, 11 Nov 2024 14:52:21 +1100 Subject: [PATCH] feat: properly implemented EWMH for workspaces and desktops --- Makefile | 2 +- actions.c | 3 +++ atlas.c | 28 +++++++++++++++++++++++----- atlas.h | 12 +++++++++--- configurer.c | 6 ++++++ ewmh.c | 41 ----------------------------------------- test.sh | 17 ----------------- windows.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 85 insertions(+), 67 deletions(-) delete mode 100644 ewmh.c delete mode 100755 test.sh diff --git a/Makefile b/Makefile index f4e50d0..045d241 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ include config.mk -SRC = draw.c atlas.c util.c layouts.c configurer.c ipc.c windows.c events.c ewmh.c input.c focus.c monitor.c client.c actions.c +SRC = draw.c atlas.c util.c layouts.c configurer.c ipc.c windows.c events.c input.c focus.c monitor.c client.c actions.c OBJ = ${SRC:.c=.o} all: atlaswm diff --git a/actions.c b/actions.c index 1cb83be..88c3d5b 100644 --- a/actions.c +++ b/actions.c @@ -140,6 +140,7 @@ void toggletag(const Arg *arg) { focus(NULL); arrange(selectedMonitor); } + updateCurrentDesktop(); } void toggleview(const Arg *arg) { @@ -153,6 +154,7 @@ void toggleview(const Arg *arg) { focus(NULL); arrange(selectedMonitor); } + updateCurrentDesktop(); } void view(const Arg *arg) { @@ -165,6 +167,7 @@ void view(const Arg *arg) { arg->ui & WORKSPACEMASK; focus(NULL); arrange(selectedMonitor); + updateCurrentDesktop(); } void zoom(const Arg *arg) { diff --git a/atlas.c b/atlas.c index 99b4989..c2e2474 100644 --- a/atlas.c +++ b/atlas.c @@ -234,6 +234,7 @@ void startupPrograms() { void setup(void) { XSetWindowAttributes wa; struct sigaction sa; + Atom utf8string; // Load configuration char config_path[256]; @@ -283,14 +284,21 @@ void setup(void) { netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); + netatom[NetDesktopViewport] = + XInternAtom(dpy, "_NET_DESKTOP_VIEWPORT", False); + netatom[NetNumberOfDesktops] = + XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False); + netatom[NetCurrentDesktop] = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False); + netatom[NetDesktopNames] = XInternAtom(dpy, "_NET_DESKTOP_NAMES", False); /* init cursors */ cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); cursor[CurResize] = drw_cur_create(drw, XC_sizing); cursor[CurMove] = drw_cur_create(drw, XC_fleur); setup_ipc(dpy); Window check = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); - XChangeProperty(dpy, check, netatom[NetWMName], XA_STRING, 8, PropModeReplace, - (unsigned char *)"AtlasWM", 7); + utf8string = XInternAtom(dpy, "UTF8_STRING", False); + XChangeProperty(dpy, check, netatom[NetWMName], utf8string, 8, + PropModeReplace, (unsigned char *)"AtlasWM", 7); XChangeProperty(dpy, check, netatom[NetWMCheck], XA_WINDOW, 32, PropModeReplace, (unsigned char *)&check, 1); XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, @@ -298,6 +306,10 @@ void setup(void) { XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, PropModeReplace, (unsigned char *)netatom, NetLast); + setNumDesktops(); + setCurrentDesktop(); + setDesktopNames(); + setViewport(); XDeleteProperty(dpy, root, netatom[NetClientList]); /* select events */ wa.cursor = cursor[CurNormal]->cursor; @@ -344,9 +356,15 @@ int xerror(Display *dpy, XErrorEvent *ee) { (ee->request_code == X_GrabKey && ee->error_code == BadAccess) || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) return 0; - LOG_ERROR("Xerror: request_code=%d, error_code=%d", ee->request_code, - ee->error_code); - return xerrorxlib(dpy, ee); /* may call exit */ + + char error_text[1024]; + XGetErrorText(dpy, ee->error_code, error_text, sizeof(error_text)); + + LOG_ERROR("X Error: request=%d error=%d (%s) resourceid=%lu serial=%lu", + ee->request_code, ee->error_code, error_text, ee->resourceid, + ee->serial); + + return xerrorxlib(dpy, ee); } int xerrordummy(Display *dpy, XErrorEvent *ee) { return 0; } diff --git a/atlas.h b/atlas.h index 9b3c72e..b4c25cc 100644 --- a/atlas.h +++ b/atlas.h @@ -29,6 +29,10 @@ enum { NetWMWindowType, NetWMWindowTypeDialog, NetClientList, + NetDesktopNames, + NetDesktopViewport, + NetNumberOfDesktops, + NetCurrentDesktop, NetLast }; @@ -325,9 +329,11 @@ int xerror(Display *dpy, XErrorEvent *ee); int xerrordummy(Display *dpy, XErrorEvent *ee); int xerrorstart(Display *dpy, XErrorEvent *ee); -/* EWMH Functions */ -void ewmh_update_client_list(void); -void ewmh_update_active_window(void); +void setCurrentDesktop(void); +void setDesktopNames(void); +void setNumDesktops(void); +void setViewport(void); +void updateCurrentDesktop(void); /* External Variables */ extern Display *dpy; diff --git a/configurer.c b/configurer.c index 6f14bff..6bde600 100644 --- a/configurer.c +++ b/configurer.c @@ -1,4 +1,5 @@ #include "configurer.h" // Includes "atlas.h" +#include "atlas.h" #include "util.h" #include #include @@ -358,6 +359,11 @@ void update_window_manager_state(void) { m->numMasterWindows = cfg.numMasterWindows; } + setNumDesktops(); + setCurrentDesktop(); + setDesktopNames(); + setViewport(); + // Rearrange all monitors to apply gap changes and new layouts arrange(NULL); diff --git a/ewmh.c b/ewmh.c deleted file mode 100644 index 8212779..0000000 --- a/ewmh.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "atlas.h" -#include "util.h" -#include - -static Atom net_atoms[NetLast]; - -void ewmh_update_client_list(void) { - // Count total clients - unsigned int num_clients = 0; - Monitor *m; - Client *c; - - for (m = monitors; m; m = m->next) - for (c = m->clients; c; c = c->next) - num_clients++; - - // Allocate array for window IDs - Window *windows = malloc(sizeof(Window) * num_clients); - if (!windows) { - LOG_ERROR("Failed to allocate memory for client list"); - return; - } - - // Fill window array - unsigned int i = 0; - for (m = monitors; m; m = m->next) - for (c = m->clients; c; c = c->next) - windows[i++] = c->win; - - // Set property - XChangeProperty(dpy, root, net_atoms[NetClientList], XA_WINDOW, 32, - PropModeReplace, (unsigned char *)windows, num_clients); - - free(windows); -} - -void ewmh_update_active_window(void) { - Window active = selectedMonitor->active ? selectedMonitor->active->win : None; - XChangeProperty(dpy, root, net_atoms[NetActiveWindow], XA_WINDOW, 32, - PropModeReplace, (unsigned char *)&active, 1); -} diff --git a/test.sh b/test.sh deleted file mode 100755 index 55c52e0..0000000 --- a/test.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -# Start Xephyr -Xephyr :100 -ac -screen 1280x720 & - -# Wait a moment for Xephyr to start -sleep 1 - -# Set the DISPLAY to Xephyr -export DISPLAY=:100 - -# Start your window manager -./result/bin/atlaswm & - -# Start a terminal (assuming you have xterm installed) -xterm & -xterm & diff --git a/windows.c b/windows.c index 3899e62..ab328fe 100644 --- a/windows.c +++ b/windows.c @@ -515,3 +515,46 @@ int gettextprop(Window w, Atom atom, char *text, unsigned int size) { XFree(name.value); return 1; } + +void setCurrentDesktop(void) { + long data[] = {0}; + XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)data, 1); +} +void setDesktopNames(void) { + XTextProperty text; + // Create list of workspace names + char **list = ecalloc(cfg.workspaceCount, sizeof(char *)); + for (size_t i = 0; i < cfg.workspaceCount; i++) { + list[i] = strdup(cfg.workspaces[i].name); + } + + // Convert list to text property + Xutf8TextListToTextProperty(dpy, list, cfg.workspaceCount, XUTF8StringStyle, + &text); + XSetTextProperty(dpy, root, &text, netatom[NetDesktopNames]); +} + +void setNumDesktops(void) { + long data[] = {cfg.workspaceCount}; + XChangeProperty(dpy, root, netatom[NetNumberOfDesktops], XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)data, 1); +} + +void setViewport(void) { + long data[] = {0, 0}; + XChangeProperty(dpy, root, netatom[NetDesktopViewport], XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)data, 2); +} + +void updateCurrentDesktop(void) { + long rawdata[] = { + selectedMonitor->workspaceset[selectedMonitor->selectedWorkspaces]}; + int i = 0; + while (*rawdata >> (i + 1)) { + i++; + } + long data[] = {i}; + XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)data, 1); +}