From ca04f20fecec7ef64f840f4302aa521dc5ce04be Mon Sep 17 00:00:00 2001 From: Lucas de Sena Date: Thu, 19 Feb 2026 20:22:50 +0000 Subject: [PATCH] implement a table of atoms defined only once Previously, adding a new atom into the code required: 1. In , add the line `extern Atom my_new_atom;` declaring the new atom. 2. In , add the line `Atom my_new_atom;` defining the new atom. 3. In , add the line `my_new_atom = XInternAtom(dpy, "MY_NEW_ATOM", False);` interning this new atom, and assigning the interned value to the variable. Now, just add a line with the atom's name in the X-MACRO in , and a XInternAtoms(3) and a set of macros will do the rest. All new atoms will be referred to as an entry in the ATOMS[] array. For example: ATOMS[MY_NEW_ATOM] The exception are for those REALLY OLD atoms that have already a dedicated compile-time-known value defined at . Those do not need to be interned; and are referred to with a constant beginning with the `XA_` prefix. For example: XA_WM_CLASS --- client.c | 6 ++-- frame.c | 6 ++-- icc.c | 107 +++++++++++++++++++++++-------------------------------- icc.h | 32 +++++++++++++++-- main.c | 6 ++-- screen.c | 4 +-- 6 files changed, 84 insertions(+), 77 deletions(-) diff --git a/client.c b/client.c index b152df1..d47e981 100644 --- a/client.c +++ b/client.c @@ -200,7 +200,7 @@ void setclientstate(Client *c, int state) } } c->state = state; - XChangeProperty(dpy, c->window, wm_state, wm_state, 32, + XChangeProperty(dpy, c->window, ATOMS[WM_STATE], ATOMS[WM_STATE], 32, PropModeReplace, (unsigned char *)data, 2); } @@ -208,7 +208,7 @@ void getstate(Client *c) { long *data=NULL; - if(_getprop(c->window, wm_state, wm_state, 2l, (char **)&data)>0) { + if(_getprop(c->window, ATOMS[WM_STATE], ATOMS[WM_STATE], 2l, (char **)&data)>0) { c->state=*data; XFree((char *)data); } @@ -442,7 +442,7 @@ reparent_client(Scrn *s, Client *client) if(client->parent != client->scr->root) XReparentWindow(dpy, client->parent, s->back, client->x, client->y); if (s->deftitle != NULL) - setstringprop(client->window, amiwm_screen, s->deftitle); + setstringprop(client->window, ATOMS[AMIWM_SCREEN], s->deftitle); sendconfig(client); } diff --git a/frame.c b/frame.c index fd2a609..98330c6 100644 --- a/frame.c +++ b/frame.c @@ -190,7 +190,7 @@ void reparent(Client *c) c->scr = lc->fsscr; else c->scr = lc->scr; - } else if(XGetTextProperty(dpy, c->window, &screen_prop, amiwm_screen)) { + } else if(XGetTextProperty(dpy, c->window, &screen_prop, ATOMS[AMIWM_SCREEN])) { do { if(s->root == scr->root && (!s->deftitle[screen_prop.nitems])&&!strncmp(s->deftitle, @@ -329,7 +329,7 @@ void reparent(Client *c) XMapSubwindows(dpy, c->parent); sendconfig(c); if (scr->deftitle != NULL) - setstringprop(c->window, amiwm_screen, scr->deftitle); + setstringprop(c->window, ATOMS[AMIWM_SCREEN], scr->deftitle); if(prefs.focus == FOC_CLICKTOTYPE) XGrabButton(dpy, Button1, AnyModifier, c->parent, True, ButtonPressMask, GrabModeSync, GrabModeAsync, None, wm_curs); @@ -737,7 +737,7 @@ void gadgetunclicked(Client *c, XEvent *e) redraw(c, w); if(w==c->close) { if((c->proto & Pdelete)&&!(e->xbutton.state&ShiftMask)) - sendcmessage(c->window, wm_protocols, wm_delete); + sendcmessage(c->window, ATOMS[WM_PROTOCOLS], ATOMS[WM_DELETE_WINDOW]); else XKillClient(dpy, c->window); } else if(w==c->depth) diff --git a/icc.c b/icc.c index 7e9c62d..f5c5084 100644 --- a/icc.c +++ b/icc.c @@ -1,3 +1,5 @@ +#include + #include "drawinfo.h" #include "screen.h" #include "icc.h" @@ -5,7 +7,7 @@ #include "style.h" #include "prefs.h" -#include +#include #include #include @@ -16,54 +18,37 @@ extern struct Library *XLibBase; extern void redraw(Client *, Window); -Atom utf8_string, net_wm_name; -Atom wm_state, wm_change_state, wm_protocols, wm_delete, wm_take_focus; -Atom wm_colormaps, wm_name, wm_normal_hints, wm_hints, wm_icon_name, wm_class; -Atom net_supporting_wm_check, net_supported, net_wm_state, net_wm_state_fullscreen; -Atom amiwm_screen, swm_vroot, amiwm_wflags, amiwm_appiconmsg, amiwm_appwindowmsg; +Atom ATOMS[NATOMS]; extern Display *dpy; +extern char *progname; void init_atoms() { - utf8_string = XInternAtom(dpy, "UTF8_STRING", False); - wm_state = XInternAtom(dpy, "WM_STATE", False); - wm_change_state = XInternAtom(dpy, "WM_CHANGE_STATE", False); - wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False); - wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - wm_take_focus = XInternAtom(dpy, "WM_TAKE_FOCUS", False); - wm_colormaps = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False); - wm_name = XInternAtom(dpy, "WM_NAME", False); - wm_normal_hints = XInternAtom(dpy, "WM_NORMAL_HINTS", False); - wm_hints = XInternAtom(dpy, "WM_HINTS", False); - wm_icon_name = XInternAtom(dpy, "WM_ICON_NAME", False); - wm_class = XInternAtom(dpy, "WM_CLASS", False); - net_supported = XInternAtom(dpy, "_NET_SUPPORTED", False); - net_supporting_wm_check = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); - net_wm_name = XInternAtom(dpy, "_NET_WM_NAME", False); - net_wm_state = XInternAtom(dpy, "_NET_WM_STATE", False); - net_wm_state_fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); - amiwm_screen = XInternAtom(dpy, "AMIWM_SCREEN", False); - swm_vroot = XInternAtom(dpy, "__SWM_VROOT", False); - amiwm_wflags = XInternAtom(dpy, "AMIWM_WFLAGS", False); - amiwm_appiconmsg = XInternAtom(dpy, "AMIWM_APPICONMSG", False); - amiwm_appwindowmsg = XInternAtom(dpy, "AMIWM_APPWINDOWMSG", False); + static char *atom_names[NATOMS] = { +#define X(atom) [atom] = #atom, + ATOMS_TABLE(X) +#undef X + }; + + if (!XInternAtoms(dpy, atom_names, NATOMS, False, ATOMS)) { + fprintf(stderr, "%s: cannot intern atoms\n", progname); + exit(1); + } } void setsupports(Window root, Window checkwin) { - Atom atoms[] = { - net_wm_state, - net_wm_state_fullscreen, - }; - XChangeProperty(dpy, root, net_supported, XA_ATOM, 32, - PropModeReplace, (unsigned char *)atoms, - sizeof(atoms)/sizeof(atoms[0])); - XChangeProperty(dpy, root, net_supporting_wm_check, XA_WINDOW, 32, + XChangeProperty(dpy, root, ATOMS[_NET_SUPPORTED], XA_ATOM, 32, + PropModeReplace, (void *)(Atom[]){ + ATOMS[_NET_WM_STATE], + ATOMS[_NET_WM_STATE_FULLSCREEN], + }, 2); + XChangeProperty(dpy, root, ATOMS[_NET_SUPPORTING_WM_CHECK], XA_WINDOW, 32, PropModeReplace, (void *)(Window[]){checkwin}, 1); - XChangeProperty(dpy, checkwin, net_supporting_wm_check, XA_WINDOW, 32, + XChangeProperty(dpy, checkwin, ATOMS[_NET_SUPPORTING_WM_CHECK], XA_WINDOW, 32, PropModeReplace, (void *)(Window[]){checkwin}, 1); - XChangeProperty(dpy, checkwin, net_wm_name, utf8_string, 8, + XChangeProperty(dpy, checkwin, ATOMS[_NET_WM_NAME], ATOMS[UTF8_STRING], 8, PropModeReplace, (void *)"AmiWM", 5); } @@ -86,13 +71,13 @@ void getwmstate(Client *c) Window w; w = c->window; - if ((n = _getprop(w, net_wm_state, XA_ATOM, 20L, (char**)&p)) < 0) + if ((n = _getprop(w, ATOMS[_NET_WM_STATE], XA_ATOM, 20L, (char**)&p)) < 0) return; c->fullscreen = 0; if (!n) return; for (i = 0; i < n; i++) - if (p[i] == net_wm_state_fullscreen) + if (p[i] == ATOMS[_NET_WM_STATE_FULLSCREEN]) c->fullscreen = 1; XFree((char *) p); } @@ -100,13 +85,11 @@ void getwmstate(Client *c) void setwmstate(Client *c) { if (c->fullscreen) { - Atom data[] = { - net_wm_state_fullscreen - }; - XChangeProperty(dpy, c->window, net_wm_state, XA_ATOM, 32, PropModeReplace, - (unsigned char *)data, 1); - } else - XDeleteProperty(dpy, c->window, net_wm_state); + XChangeProperty(dpy, c->window, ATOMS[_NET_WM_STATE], XA_ATOM, 32, PropModeReplace, + (void *)&ATOMS[_NET_WM_STATE_FULLSCREEN], 1); + } else { + XDeleteProperty(dpy, c->window, ATOMS[_NET_WM_STATE]); + } } @@ -139,7 +122,7 @@ void getwflags(Client *c) long n; c->wflags = 0; - if ((n = _getprop(c->window, amiwm_wflags, amiwm_wflags, 1L, (char**)&p)) <= 0) + if ((n = _getprop(c->window, ATOMS[AMIWM_WFLAGS], ATOMS[AMIWM_WFLAGS], 1L, (char**)&p)) <= 0) return; c->wflags = p[0]; @@ -156,13 +139,13 @@ void getproto(Client *c) w = c->window; c->proto &= ~(Pdelete|Ptakefocus); - if ((n = _getprop(w, wm_protocols, XA_ATOM, 20L, (char**)&p)) <= 0) + if ((n = _getprop(w, ATOMS[WM_PROTOCOLS], XA_ATOM, 20L, (char**)&p)) <= 0) return; for (i = 0; i < n; i++) - if (p[i] == wm_delete) + if (p[i] == ATOMS[WM_DELETE_WINDOW]) c->proto |= Pdelete; - else if (p[i] == wm_take_focus) + else if (p[i] == ATOMS[WM_TAKE_FOCUS]) c->proto |= Ptakefocus; XFree((char *) p); @@ -202,7 +185,7 @@ void checkstyle(Client *c) if(prefs.firststyle==NULL) return; - if(!XGetTextProperty(dpy, c->window, &class_name, wm_class)) + if(!XGetTextProperty(dpy, c->window, &class_name, XA_WM_CLASS)) class_name.value=NULL; else /* This value seems to be 2x it's correct value always... */ @@ -237,7 +220,7 @@ void propertychange(Client *c, Atom a) extern void checksizehints(Client *); extern void newicontitle(Client *); - if(a==wm_name) { + if(a==XA_WM_NAME) { #ifdef USE_FONTSETS XTextProperty prop; if(c->title) { @@ -265,9 +248,9 @@ void propertychange(Client *c, Atom a) XClearWindow(dpy, c->drag); redraw(c, c->drag); } - } else if(a==wm_normal_hints) { + } else if(a==XA_WM_NORMAL_HINTS) { checksizehints(c); - } else if(a==wm_hints) { + } else if(a==XA_WM_HINTS) { XWMHints *xwmh; if((xwmh=XGetWMHints(dpy, c->window))) { if((xwmh->flags&(IconWindowHint|IconPixmapHint))&&c->icon) { @@ -281,25 +264,25 @@ void propertychange(Client *c, Atom a) } XFree(xwmh); } - } else if(a==wm_protocols) { + } else if(a==ATOMS[WM_PROTOCOLS]) { getproto(c); - } else if(a==wm_icon_name) { + } else if(a==XA_WM_ICON_NAME) { if(c->style==NULL) checkstyle(c); if(c->icon) newicontitle(c); - } else if(a==wm_state) { + } else if(a==ATOMS[WM_STATE]) { if(c->parent==c->scr->root) { getstate(c); if(c->state==NormalState) c->state=WithdrawnState; } - } else if(a==wm_class && c->style==NULL) + } else if(a==XA_WM_CLASS && c->style==NULL) checkstyle(c); } void handle_client_message(Client *c, XClientMessageEvent *xcme) { - if(xcme->message_type == wm_change_state) { + if(xcme->message_type == ATOMS[WM_CHANGE_STATE]) { int state=xcme->data.l[0]; if(state==IconicState) if(c->state!=IconicState) { @@ -328,10 +311,10 @@ void handle_client_message(Client *c, XClientMessageEvent *xcme) XMapRaised(dpy, c->parent); setclientstate(c, NormalState); } - } else if (xcme->message_type == net_wm_state) { + } else if (xcme->message_type == ATOMS[_NET_WM_STATE]) { int action=xcme->data.l[0]; Atom prop=xcme->data.l[1]; - if (prop == net_wm_state_fullscreen) + if (prop == ATOMS[_NET_WM_STATE_FULLSCREEN]) switch (action) { case 0: fullscreen(c, 0); break; /* _NET_WM_STATE_REMOVE */ case 1: fullscreen(c, 1); break; /* _NET_WM_STATE_ADD */ diff --git a/icc.h b/icc.h index 745fd18..60b573b 100644 --- a/icc.h +++ b/icc.h @@ -17,15 +17,12 @@ extern long _getprop(Window, Atom, Atom, long, char **); extern void getwflags(Client *); extern Window get_transient_for(Window); -extern Atom wm_state, wm_change_state, wm_protocols, wm_delete, wm_take_focus, wm_colormaps, wm_hints, amiwm_screen, swm_vroot; - #define Pdelete 1 #define Ptakefocus 2 #define Psizebottom 4 #define Psizeright 8 #define Psizetrans 16 - #define mkcmessage(w, a, x, ...) (&(XEvent){.xclient = { \ .type = ClientMessage, \ .window = (w), \ @@ -34,4 +31,33 @@ extern Atom wm_state, wm_change_state, wm_protocols, wm_delete, wm_take_focus, w .data.l = {(long)(x), CurrentTime, __VA_ARGS__}, \ }}) +#define ATOMS_TABLE(X) \ + X(AMIWM_APPICONMSG) \ + X(AMIWM_APPWINDOWMSG) \ + X(AMIWM_SCREEN) \ + X(AMIWM_WFLAGS) \ + X(UTF8_STRING) \ + X(WM_CHANGE_STATE) \ + X(WM_CLASS) \ + X(WM_COLORMAP_WINDOWS) \ + X(WM_DELETE_WINDOW) \ + X(WM_PROTOCOLS) \ + X(WM_STATE) \ + X(WM_TAKE_FOCUS) \ + X(_NET_SUPPORTED) \ + X(_NET_SUPPORTING_WM_CHECK) \ + X(_NET_WM_NAME) \ + X(_NET_WM_STATE) \ + X(_NET_WM_STATE_FULLSCREEN) \ + X(__SWM_VROOT) + +enum { +#define X(atom) atom, + ATOMS_TABLE(X) + NATOMS +#undef X +}; + +extern Atom ATOMS[NATOMS]; + #endif diff --git a/main.c b/main.c index f17bae4..937ede7 100644 --- a/main.c +++ b/main.c @@ -758,11 +758,10 @@ static void drag_icon(Scrn *s, Time time, int x_root, int y_root) if (c != NULL) { if (c->module != NULL) { - extern Atom amiwm_appwindowmsg; XTranslateCoordinates(dpy, s->back, c->window, -4, -4, &wx, &wy, &ch); for (int n = 0; n < nicons; n++) { dispatch_event_to_broker(mkcmessage( - c->window, amiwm_appwindowmsg,dragging[n].icon->window, + c->window, ATOMS[AMIWM_APPWINDOWMSG],dragging[n].icon->window, dragging[n].x + wx, dragging[n].y + wy ), 0, c->module); } @@ -878,13 +877,12 @@ static void drag_resize(Client *c, Time time, int x_root, int y_root) static void do_icon_double_click(Scrn *scr) { - extern Atom amiwm_appiconmsg; Icon *i, *next; for(i=scr->firstselected; i; i=next) { next=i->nextselected; if(i->module) { - dispatch_event_to_broker(mkcmessage(i->window, amiwm_appiconmsg, 0), + dispatch_event_to_broker(mkcmessage(i->window, ATOMS[AMIWM_APPICONMSG], 0), 0, i->module); } else { deiconify(i); diff --git a/screen.c b/screen.c index 6d8933b..c17a251 100644 --- a/screen.c +++ b/screen.c @@ -61,9 +61,9 @@ void setvirtualroot(Scrn *s) if(s==old_vroot) return; if(old_vroot) - XDeleteProperty(dpy, old_vroot->back, swm_vroot); + XDeleteProperty(dpy, old_vroot->back, ATOMS[__SWM_VROOT]); setvroot(s->root, s); - XChangeProperty(dpy, s->back, swm_vroot, XA_WINDOW, 32, PropModeReplace, + XChangeProperty(dpy, s->back, ATOMS[__SWM_VROOT], XA_WINDOW, 32, PropModeReplace, (unsigned char *)&(s->back), 1); } }