commit - ac5b7bb7f2b6a4fa8bb0dc85e94f181feeac1886
commit + 66bbd5426a0538e0a9b8bb43bb50204ef13fdc41
blob - 3ba07a044fb7c4f06008b9e9195aabc1a5fa1b74
blob + 600e835e7dbe1e8824b3cca52d858609b5fa586e
--- bxwm.c
+++ bxwm.c
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include <X11/keysym.h>
+#include <X11/Xatom.h>
#include "config.h"
static int curws = INITIAL_WORKSPACE;
static int ws_focus_idx[NUM_WORKSPACES] = {-1}; /* Index of last focused per WS */
+/* EWMH atoms */
+static Atom net_supported, net_number_of_desktops, net_current_desktop;
+static Atom net_client_list, net_active_window, net_wm_desktop;
+
+/* ICCCM atoms */
+static Atom wm_protocols, wm_delete_window;
+
/* Function declarations */
static void run(void);
static void cleanup(int status);
static void view(int ws);
static void movetows(int ws);
static void unmanage(Window w);
+static void update_client_list(void);
int main(void) {
signal(SIGTERM, cleanup);
root, True, GrabModeAsync, GrabModeAsync); /* Super+Shift+N: move */
}
+ /* Intern EWMH/ICCCM atoms */
+ net_supported = XInternAtom(dpy, "_NET_SUPPORTED", False);
+ net_number_of_desktops = XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False);
+ net_current_desktop = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False);
+ net_client_list = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
+ net_active_window = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
+ net_wm_desktop = XInternAtom(dpy, "_NET_WM_DESKTOP", False);
+ wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
+ wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+
+ /* Set EWMH properties on root window */
+ Atom supported[] = {
+ net_supported, net_number_of_desktops, net_current_desktop,
+ net_client_list, net_active_window, net_wm_desktop
+ };
+ XChangeProperty(dpy, root, net_supported, XA_ATOM, 32,
+ PropModeReplace, (unsigned char *)supported,
+ sizeof(supported) / sizeof(Atom));
+
+ long ndesktops = NUM_WORKSPACES;
+ XChangeProperty(dpy, root, net_number_of_desktops, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char *)&ndesktops, 1);
+
+ long current_desktop = INITIAL_WORKSPACE;
+ XChangeProperty(dpy, root, net_current_desktop, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char *)¤t_desktop, 1);
+
+ XChangeProperty(dpy, root, net_client_list, XA_WINDOW, 32,
+ PropModeReplace, NULL, 0);
+
+ long active = None;
+ XChangeProperty(dpy, root, net_active_window, XA_WINDOW, 32,
+ PropModeReplace, (unsigned char *)&active, 1);
+
#ifdef DEBUG
fprintf(stderr, "bxwm: setup complete\n");
#endif
XMapWindow(dpy, w); /* Now map (configure already applied) */
focus_client(c); /* Border color + XRaise redundant (already Above), but keeps focus/input */
+
+ long ws = curws;
+ XChangeProperty(dpy, w, net_wm_desktop, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char *)&ws, 1);
+ update_client_list();
}
static void focus_client(Client *c) {
XSetWindowBorder(dpy, c->win, focus_pixel);
XSetInputFocus(dpy, c->win, RevertToParent, CurrentTime);
XRaiseWindow(dpy, c->win);
+ long active = c->win;
+ XChangeProperty(dpy, root, net_active_window, XA_WINDOW, 32,
+ PropModeReplace, (unsigned char *)&active, 1);
#ifdef DEBUG
fprintf(stderr, "bxwm: focused 0x%lx\n", c->win);
#endif
static void close_window(Client *c) {
if (!c) return;
- #ifdef DEBUG
- fprintf(stderr, "bxwm: close 0x%lx\n", c->win);
- #endif
-
+ int n;
+ Atom *protocols;
+ if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
+ for (int i = 0; i < n; i++) {
+ if (protocols[i] == wm_delete_window) {
+ XEvent ev;
+ ev.type = ClientMessage;
+ ev.xclient.window = c->win;
+ ev.xclient.message_type = wm_protocols;
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = wm_delete_window;
+ ev.xclient.data.l[1] = CurrentTime;
+ XSendEvent(dpy, c->win, False, NoEventMask, &ev);
+ XFree(protocols);
+ return;
+ }
+ }
+ XFree(protocols);
+ }
XKillClient(dpy, c->win);
}
curws = ws;
+ long current_desktop = curws;
+ XChangeProperty(dpy, root, net_current_desktop, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char *)¤t_desktop, 1);
+
+
/* Map new workspace windows */
for (i = 0; i < num_clients; i++) {
if (clients[i].ws == curws)
old_ws = c->ws;
c->ws = ws;
-
+
+ long new_ws = ws;
+ XChangeProperty(dpy, c->win, net_wm_desktop, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char *)&new_ws, 1);
+
if (old_ws == curws) {
/* Moving away from visible workspace */
XUnmapWindow(dpy, c->win);
if (!focused_client && num_clients)
focus_client(&clients[num_clients - 1]);
+
+ update_client_list();
+
+ if (!focused_client) {
+ long active = None;
+ XChangeProperty(dpy, root, net_active_window, XA_WINDOW, 32,
+ PropModeReplace, (unsigned char *)&active, 1);
+ }
}
static void spawn(const char *cmd) {
}
}
+static void update_client_list(void) {
+ Window *wins = NULL;
+ unsigned int i;
+
+ if (num_clients > 0) {
+ wins = malloc(num_clients * sizeof(Window));
+ for (i = 0; i < num_clients; i++)
+ wins[i] = clients[i].win;
+ }
+ XChangeProperty(dpy, root, net_client_list, XA_WINDOW, 32,
+ PropModeReplace, (unsigned char *)wins, num_clients);
+ if (wins)
+ free(wins);
+}
+
static void cleanup(int status) {
if (dpy) {
if (clients)