Phase 80k: clean X11 from startup.c

- getOffendingModifiers (XGetModifierMapping/XFreeModifiermap) ->
  setup_modifier_lock_masks vtable slot
- wHackedGrabKey (XGrabKey with NumLock/ScrollLock combos) ->
  key_grab_hacked vtable slot
- wHackedGrabButton (XGrabButton with lock combos) ->
  button_grab_hacked vtable slot
- XUniqueContext calls -> context_init vtable slot
- XQueryTree/XFree in wManageAllWindows -> query_tree vtable slot
  (returns wfree-able array)
- XGetWindowAttributes in wScreenForWindow -> screen_for_window vtable
- _NumLockMask/_ScrollLockMask made non-static (needed by x11_backend)

New vtable slots: setup_modifier_lock_masks, key_grab_hacked,
button_grab_hacked, context_init, query_tree, screen_for_window.
startup.o verified X11-free with nm.
This commit is contained in:
Levi Neely 2026-05-13 11:24:45 +02:00
parent 6d4fc32b28
commit 6f1c499b03
5 changed files with 177 additions and 109 deletions

View File

@ -1709,6 +1709,16 @@ typedef struct WMBackend {
WNativeWindow (*prop_get_client_leader)(WNativeWindow window);
int (*prop_get_window_state)(WNativeWindow window);
void (*setup_modifier_lock_masks)(void);
void (*key_grab_hacked)(WNativeWindow window, int keycode, unsigned int modifiers);
void (*button_grab_hacked)(unsigned int button, unsigned int modifiers,
WNativeWindow window, int owner_events,
unsigned int event_mask);
void (*context_init)(void);
void (*query_tree)(WNativeWindow root, WNativeWindow **children_out,
unsigned int *nchildren_out);
WScreen *(*screen_for_window)(WNativeWindow window);
} WMBackend;
/*

View File

@ -6214,6 +6214,26 @@ static void wl_noop_frame_paint_titlebar(WFrameWindow *fwin, int state) { (void)
static WNativeWindow wl_noop_prop_get_client_leader(WNativeWindow window) { (void)window; return WNATIVE_NONE; }
static int wl_noop_prop_get_window_state(WNativeWindow window) { (void)window; return -1; }
static void wl_noop_setup_modifier_lock_masks(void) { }
static void wl_noop_key_grab_hacked(WNativeWindow window, int keycode, unsigned int modifiers)
{ (void)window; (void)keycode; (void)modifiers; }
static void wl_noop_button_grab_hacked(unsigned int button, unsigned int modifiers,
WNativeWindow window, int owner_events, unsigned int event_mask)
{ (void)button; (void)modifiers; (void)window; (void)owner_events; (void)event_mask; }
static void wl_context_init(void)
{
/* Wayland uses a hash table instead of X11 contexts */
w_global.context.client_win = 1;
w_global.context.app_win = 2;
w_global.context.stack = 3;
}
static void wl_noop_query_tree(WNativeWindow root, WNativeWindow **children_out,
unsigned int *nchildren_out)
{ (void)root; *children_out = NULL; *nchildren_out = 0; }
static WScreen *wl_noop_screen_for_window(WNativeWindow window)
{ (void)window; return wScreenWithNumber(0); }
/* ------------------------------------------------------------------ */
/* vtable */
/* ------------------------------------------------------------------ */
@ -6435,4 +6455,10 @@ const WMBackend wl_backend = {
.frame_paint_titlebar = wl_noop_frame_paint_titlebar,
.prop_get_client_leader = wl_noop_prop_get_client_leader,
.prop_get_window_state = wl_noop_prop_get_window_state,
.setup_modifier_lock_masks = wl_noop_setup_modifier_lock_masks,
.key_grab_hacked = wl_noop_key_grab_hacked,
.button_grab_hacked = wl_noop_button_grab_hacked,
.context_init = wl_context_init,
.query_tree = wl_noop_query_tree,
.screen_for_window = wl_noop_screen_for_window,
};

View File

@ -17,6 +17,8 @@
#include <unistd.h>
#include <fcntl.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/Xresource.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/Xproto.h>
@ -2921,6 +2923,123 @@ static int x11_prop_get_window_state(WNativeWindow window)
return state;
}
static void x11_setup_modifier_lock_masks(void)
{
int i;
XModifierKeymap *modmap;
KeyCode nlock, slock;
static int mask_table[8] = {
ShiftMask, LockMask, ControlMask, Mod1Mask,
Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
};
nlock = XKeysymToKeycode(dpy, XK_Num_Lock);
slock = XKeysymToKeycode(dpy, XK_Scroll_Lock);
modmap = XGetModifierMapping(dpy);
if (modmap != NULL && modmap->max_keypermod > 0) {
for (i = 0; i < 8 * modmap->max_keypermod; i++) {
if (modmap->modifiermap[i] == nlock && nlock != 0)
_NumLockMask = mask_table[i / modmap->max_keypermod];
else if (modmap->modifiermap[i] == slock && slock != 0)
_ScrollLockMask = mask_table[i / modmap->max_keypermod];
}
}
if (modmap)
XFreeModifiermap(modmap);
}
static void x11_key_grab_hacked(WNativeWindow window, int keycode, unsigned int modifiers)
{
if (modifiers == AnyModifier)
return;
if (_NumLockMask)
XGrabKey(dpy, keycode, modifiers | _NumLockMask,
(Window)window, True, GrabModeAsync, GrabModeAsync);
if (_ScrollLockMask)
XGrabKey(dpy, keycode, modifiers | _ScrollLockMask,
(Window)window, True, GrabModeAsync, GrabModeAsync);
if (_NumLockMask && _ScrollLockMask)
XGrabKey(dpy, keycode, modifiers | _NumLockMask | _ScrollLockMask,
(Window)window, True, GrabModeAsync, GrabModeAsync);
if (_NumLockMask)
XGrabKey(dpy, keycode, modifiers | _NumLockMask | LockMask,
(Window)window, True, GrabModeAsync, GrabModeAsync);
if (_ScrollLockMask)
XGrabKey(dpy, keycode, modifiers | _ScrollLockMask | LockMask,
(Window)window, True, GrabModeAsync, GrabModeAsync);
if (_NumLockMask && _ScrollLockMask)
XGrabKey(dpy, keycode, modifiers | _NumLockMask | _ScrollLockMask | LockMask,
(Window)window, True, GrabModeAsync, GrabModeAsync);
}
static void x11_button_grab_hacked(unsigned int button, unsigned int modifiers,
WNativeWindow window, int owner_events,
unsigned int event_mask)
{
XGrabButton(dpy, button, modifiers, (Window)window, owner_events,
event_mask, GrabModeAsync, GrabModeAsync, None, None);
if (modifiers == AnyModifier)
return;
XGrabButton(dpy, button, modifiers | LockMask, (Window)window, owner_events,
event_mask, GrabModeAsync, GrabModeAsync, None, None);
if (_NumLockMask)
XGrabButton(dpy, button, modifiers | _NumLockMask, (Window)window,
owner_events, event_mask, GrabModeAsync, GrabModeAsync, None, None);
if (_ScrollLockMask)
XGrabButton(dpy, button, modifiers | _ScrollLockMask, (Window)window,
owner_events, event_mask, GrabModeAsync, GrabModeAsync, None, None);
if (_NumLockMask && _ScrollLockMask)
XGrabButton(dpy, button, modifiers | _NumLockMask | _ScrollLockMask, (Window)window,
owner_events, event_mask, GrabModeAsync, GrabModeAsync, None, None);
if (_NumLockMask)
XGrabButton(dpy, button, modifiers | _NumLockMask | LockMask, (Window)window,
owner_events, event_mask, GrabModeAsync, GrabModeAsync, None, None);
if (_ScrollLockMask)
XGrabButton(dpy, button, modifiers | _ScrollLockMask | LockMask, (Window)window,
owner_events, event_mask, GrabModeAsync, GrabModeAsync, None, None);
if (_NumLockMask && _ScrollLockMask)
XGrabButton(dpy, button, modifiers | _NumLockMask | _ScrollLockMask | LockMask, (Window)window,
owner_events, event_mask, GrabModeAsync, GrabModeAsync, None, None);
}
static void x11_context_init(void)
{
w_global.context.client_win = XUniqueContext();
w_global.context.app_win = XUniqueContext();
w_global.context.stack = XUniqueContext();
}
static void x11_query_tree(WNativeWindow root, WNativeWindow **children_out,
unsigned int *nchildren_out)
{
Window xroot, parent;
Window *children = NULL;
unsigned int n = 0;
XQueryTree(dpy, (Window)root, &xroot, &parent, &children, &n);
/* Copy to wfree-able memory */
if (children && n > 0) {
WNativeWindow *out = wmalloc(n * sizeof(WNativeWindow));
unsigned int i;
for (i = 0; i < n; i++)
out[i] = (WNativeWindow)children[i];
XFree(children);
*children_out = out;
} else {
if (children) XFree(children);
*children_out = NULL;
}
*nchildren_out = n;
}
static WScreen *x11_screen_for_window(WNativeWindow window)
{
XWindowAttributes attr;
if (XGetWindowAttributes(dpy, (Window)window, &attr))
return wScreenForRootWindow(attr.root);
return NULL;
}
/* -------------------------------------------------------------------- */
/* Client operations (Phase 80) */
/* -------------------------------------------------------------------- */
@ -3625,6 +3744,12 @@ const WMBackend x11_backend = {
.frame_paint_titlebar = x11_frame_paint_titlebar,
.prop_get_client_leader = x11_prop_get_client_leader,
.prop_get_window_state = x11_prop_get_window_state,
.setup_modifier_lock_masks = x11_setup_modifier_lock_masks,
.key_grab_hacked = x11_key_grab_hacked,
.button_grab_hacked = x11_button_grab_hacked,
.context_init = x11_context_init,
.query_tree = x11_query_tree,
.screen_for_window = x11_screen_for_window,
};
/*

View File

@ -33,7 +33,6 @@
#endif
#include <X11/Xresource.h> /* XrmUniqueQuark — needed by XUniqueContext() */
#include "WindowMaker.h"
#include "GNUstep.h"
#include "texture.h"
@ -73,8 +72,8 @@
/***** Local *****/
static WScreen **wScreen = NULL;
static unsigned int _NumLockMask = 0;
static unsigned int _ScrollLockMask = 0;
unsigned int _NumLockMask = 0;
unsigned int _ScrollLockMask = 0;
/* catchXError and handleXIO moved to x11_backend.c (Phase 25) */
@ -169,37 +168,7 @@ static RETSIGTYPE buryChild(int foo)
static void getOffendingModifiers(void)
{
int i;
XModifierKeymap *modmap;
KeyCode nlock, slock;
static int mask_table[8] = {
ShiftMask, LockMask, ControlMask, Mod1Mask,
Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
};
if (!dpy || wm_backend->is_wayland)
return; /* Wayland: modifier mapping handled by wlroots/XKB */
nlock = wm_backend->keysym_to_keycode(WM_KEY_NUM_LOCK);
slock = wm_backend->keysym_to_keycode(WM_KEY_SCROLL_LOCK);
/*
* Find out the masks for the NumLock and ScrollLock modifiers,
* so that we can bind the grabs for when they are enabled too.
*/
modmap = XGetModifierMapping(dpy);
if (modmap != NULL && modmap->max_keypermod > 0) {
for (i = 0; i < 8 * modmap->max_keypermod; i++) {
if (modmap->modifiermap[i] == nlock && nlock != 0)
_NumLockMask = mask_table[i / modmap->max_keypermod];
else if (modmap->modifiermap[i] == slock && slock != 0)
_ScrollLockMask = mask_table[i / modmap->max_keypermod];
}
}
if (modmap)
XFreeModifiermap(modmap);
wm_backend->setup_modifier_lock_masks();
}
#ifdef NUMLOCK_HACK
@ -207,32 +176,8 @@ void
wHackedGrabKey(int keycode, unsigned int modifiers,
Window grab_window, Bool owner_events, int pointer_mode, int keyboard_mode)
{
if (modifiers == AnyModifier)
return;
/* grab all combinations of the modifier with CapsLock, NumLock and
* ScrollLock. How much memory/CPU does such a monstrosity consume
* in the server?
*/
if (_NumLockMask)
XGrabKey(dpy, keycode, modifiers | _NumLockMask,
grab_window, owner_events, pointer_mode, keyboard_mode);
if (_ScrollLockMask)
XGrabKey(dpy, keycode, modifiers | _ScrollLockMask,
grab_window, owner_events, pointer_mode, keyboard_mode);
if (_NumLockMask && _ScrollLockMask)
XGrabKey(dpy, keycode, modifiers | _NumLockMask | _ScrollLockMask,
grab_window, owner_events, pointer_mode, keyboard_mode);
if (_NumLockMask)
XGrabKey(dpy, keycode, modifiers | _NumLockMask | LockMask,
grab_window, owner_events, pointer_mode, keyboard_mode);
if (_ScrollLockMask)
XGrabKey(dpy, keycode, modifiers | _ScrollLockMask | LockMask,
grab_window, owner_events, pointer_mode, keyboard_mode);
if (_NumLockMask && _ScrollLockMask)
XGrabKey(dpy, keycode, modifiers | _NumLockMask | _ScrollLockMask | LockMask,
grab_window, owner_events, pointer_mode, keyboard_mode);
/* phew, I guess that's all, right? */
(void)owner_events; (void)pointer_mode; (void)keyboard_mode;
wm_backend->key_grab_hacked((WNativeWindow)grab_window, keycode, modifiers);
}
#endif
@ -241,42 +186,9 @@ wHackedGrabButton(unsigned int button, unsigned int modifiers,
Window grab_window, Bool owner_events,
unsigned int event_mask, int pointer_mode, int keyboard_mode, Window confine_to, Cursor cursor)
{
XGrabButton(dpy, button, modifiers, grab_window, owner_events,
event_mask, pointer_mode, keyboard_mode, confine_to, cursor);
if (modifiers == AnyModifier)
return;
XGrabButton(dpy, button, modifiers | LockMask, grab_window, owner_events,
event_mask, pointer_mode, keyboard_mode, confine_to, cursor);
#ifdef NUMLOCK_HACK
/* same as above, but for mouse buttons */
if (_NumLockMask)
XGrabButton(dpy, button, modifiers | _NumLockMask,
grab_window, owner_events, event_mask, pointer_mode,
keyboard_mode, confine_to, cursor);
if (_ScrollLockMask)
XGrabButton(dpy, button, modifiers | _ScrollLockMask,
grab_window, owner_events, event_mask, pointer_mode,
keyboard_mode, confine_to, cursor);
if (_NumLockMask && _ScrollLockMask)
XGrabButton(dpy, button, modifiers | _ScrollLockMask | _NumLockMask,
grab_window, owner_events, event_mask, pointer_mode,
keyboard_mode, confine_to, cursor);
if (_NumLockMask)
XGrabButton(dpy, button, modifiers | _NumLockMask | LockMask,
grab_window, owner_events, event_mask, pointer_mode,
keyboard_mode, confine_to, cursor);
if (_ScrollLockMask)
XGrabButton(dpy, button, modifiers | _ScrollLockMask | LockMask,
grab_window, owner_events, event_mask, pointer_mode,
keyboard_mode, confine_to, cursor);
if (_NumLockMask && _ScrollLockMask)
XGrabButton(dpy, button, modifiers | _ScrollLockMask | _NumLockMask | LockMask,
grab_window, owner_events, event_mask, pointer_mode,
keyboard_mode, confine_to, cursor);
#endif /* NUMLOCK_HACK */
(void)pointer_mode; (void)keyboard_mode; (void)confine_to; (void)cursor;
wm_backend->button_grab_hacked(button, modifiers, (WNativeWindow)grab_window,
owner_events, event_mask);
}
WScreen *wScreenWithNumber(int i)
@ -305,15 +217,10 @@ WScreen *wScreenForRootWindow(WNativeWindow window)
WScreen *wScreenForWindow(WNativeWindow window)
{
XWindowAttributes attr;
if (w_global.screen_count == 1)
return wScreen[0];
if (XGetWindowAttributes(dpy, window, &attr))
return wScreenForRootWindow(attr.root);
return NULL;
return wm_backend->screen_for_window(window);
}
static char *atomNames[] = {
@ -375,9 +282,7 @@ void StartUp(Bool defaultScreenOnly)
memset(&wKeyBindings, 0, sizeof(wKeyBindings));
w_global.context.client_win = XUniqueContext();
w_global.context.app_win = XUniqueContext();
w_global.context.stack = XUniqueContext();
wm_backend->context_init();
{
int ai;
@ -647,14 +552,14 @@ static Bool windowInList(Window window, Window * list, int count)
*/
void wManageAllWindows(WScreen * scr, int crashRecovery)
{
Window root, parent;
Window *children;
WNativeWindow *children;
unsigned int nchildren;
unsigned int i, j;
WWindow *wwin;
wm_backend->server_grab();
XQueryTree(dpy, scr->root_win, &root, &parent, &children, &nchildren);
wm_backend->query_tree((WNativeWindow)scr->root_win, &children, &nchildren);
scr->flags.startup = 1;
@ -733,7 +638,7 @@ void wManageAllWindows(WScreen * scr, int crashRecovery)
wwin = wwin->prev;
}
XFree(children);
wfree(children);
scr->flags.startup = 0;
scr->flags.startup2 = 1;

View File

@ -37,3 +37,5 @@ void wHackedGrabKey(int keycode, unsigned int modifiers,
#endif
#endif /* WMSTARTUP_H */
extern unsigned int _NumLockMask;
extern unsigned int _ScrollLockMask;