From b5c46870aaf90b81978082d9f0de8e74ff88bb42 Mon Sep 17 00:00:00 2001 From: Window Maker Date: Sun, 24 May 2026 10:55:30 +0200 Subject: [PATCH] =?UTF-8?q?wings:=20phase=20=CE=B3=20(widgets.c)=20?= =?UTF-8?q?=E2=80=94=20split=20Xlib=20calls=20into=20widgets=5Fx11.c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WINGs/widgets.c is now Xlib-call-free. All Xlib code moved to a new WINGs/widgets_x11.c: * W_X11PlatformInit (~178 lines): GC creation, modifier-mask probe, cut-buffer setup, cursor/atom/IM init. Hooked from W_ViewBackendX11.platform_init exactly as before. * W_X11OpenDisplay: XOpenDisplay + WMCreateSimpleApplicationScreen. WMOpenScreen() in widgets.c now calls this for the X11 path. Dead code removed: the static renderPixmap that nothing called and that was the last X11-direct-draw path in widgets.c. X11 includes dropped from widgets.c. Display * typedef still resolves through WINGsP.h transitively until phase ε removes that. Build verified clean, wmaker still links and runs. --- WINGs/Makefile.am | 1 + WINGs/WINGs/WINGsP.h.in | 10 ++ WINGs/widgets.c | 240 +--------------------------------------- WINGs/widgets_x11.c | 231 ++++++++++++++++++++++++++++++++++++++ src/wconfig.h | 2 +- 5 files changed, 249 insertions(+), 235 deletions(-) create mode 100644 WINGs/widgets_x11.c diff --git a/WINGs/Makefile.am b/WINGs/Makefile.am index e5488e0..1021508 100644 --- a/WINGs/Makefile.am +++ b/WINGs/Makefile.am @@ -53,6 +53,7 @@ libWINGs_la_SOURCES = \ wfont_wl.c \ wfontpanel.c \ widgets.c \ + widgets_x11.c \ winputmethod.c \ wlabel.c \ wlist.c \ diff --git a/WINGs/WINGs/WINGsP.h.in b/WINGs/WINGs/WINGsP.h.in index 12f6149..d9bb8c6 100644 --- a/WINGs/WINGs/WINGsP.h.in +++ b/WINGs/WINGs/WINGsP.h.in @@ -738,6 +738,16 @@ W_Class W_RegisterUserWidget(void); void W_InitIM(WMScreen *scr); +/* + * X11-only entry points exposed by widgets_x11.c. + * + * Kept declared at all times even in Wayland builds so the X11 view + * backend's platform_init slot can resolve at link time. Actual X11 + * calls only fire when the X11 backend is the active one. + */ +WMScreen *W_X11OpenDisplay(const char *display); +void W_X11PlatformInit(W_Screen *scrPtr); + void W_CreateIC(WMView *view); void W_DestroyIC(WMView *view); diff --git a/WINGs/widgets.c b/WINGs/widgets.c index a19f870..be2b7aa 100644 --- a/WINGs/widgets.c +++ b/WINGs/widgets.c @@ -2,12 +2,10 @@ #include "WINGsP.h" #include "wconfig.h" -#include -#include -#include -#include - -#include +/* widgets.c is now backend-neutral. Every Xlib call has moved to + * widgets_x11.c. WINGsP.h still pulls Xlib in transitively (will be + * fixed in phase ε), so the Display * typedef in WMCreate* signatures + * resolves through that. */ /********** data ************/ @@ -360,50 +358,6 @@ static int userWidgetCount = 0; /***** end data ******/ -static void renderPixmap(W_Screen * screen, WMNativePixmap d, WMNativePixmap mask, char **data, int width, int height) -{ - int x, y; - GC whiteGC = WMColorGC(screen->white); - GC blackGC = WMColorGC(screen->black); - GC lightGC = WMColorGC(screen->gray); - GC darkGC = WMColorGC(screen->darkGray); - - if (mask) - XSetForeground(screen->display, screen->monoGC, 0); - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - switch (data[y][x]) { - case ' ': - case 'w': - XDrawPoint(screen->display, d, whiteGC, x, y); - break; - - case '=': - if (mask) - XDrawPoint(screen->display, mask, screen->monoGC, x, y); - - /* FALLTHRU */ - case '.': - case 'l': - XDrawPoint(screen->display, d, lightGC, x, y); - break; - - case '%': - case 'd': - XDrawPoint(screen->display, d, darkGC, x, y); - break; - - case '#': - case 'b': - default: - XDrawPoint(screen->display, d, blackGC, x, y); - break; - } - } - } -} - static WMPixmap *makePixmap(W_Screen * sPtr, char **data, int width, int height, int masked) { RImage *img; @@ -624,12 +578,8 @@ WMScreen *WMOpenScreen(const char *display) (void)wl_disp; #endif - Display *dpy = XOpenDisplay(display); - if (!dpy) { - wwarning(_("WINGs: could not open display %s"), XDisplayName(display)); - return NULL; - } - return WMCreateSimpleApplicationScreen(dpy); + /* X11 path lives in widgets_x11.c so this file stays Xlib-free. */ + return W_X11OpenDisplay(display); } WMScreen *WMCreateSimpleApplicationScreen(Display * display) @@ -649,184 +599,6 @@ WMScreen *WMCreateScreen(Display * display, int screen) return WMCreateScreenWithRContext(display, screen, RCreateContext(display, screen, NULL)); } -void W_X11PlatformInit(W_Screen *scrPtr) -{ - Display *display = scrPtr->display; - XGCValues gcv; - WMNativePixmap stipple; - int i; - static char *atomNames[] = { - "_GNUSTEP_WM_ATTR", - "WM_DELETE_WINDOW", - "WM_PROTOCOLS", - "CLIPBOARD", - "XdndAware", - "XdndSelection", - "XdndEnter", - "XdndLeave", - "XdndPosition", - "XdndDrop", - "XdndFinished", - "XdndTypeList", - "XdndActionList", - "XdndActionDescription", - "XdndStatus", - "XdndActionCopy", - "XdndActionMove", - "XdndActionLink", - "XdndActionAsk", - "XdndActionPrivate", - "_WINGS_DND_MOUSE_OFFSET", - "WM_STATE", - "UTF8_STRING", - "_NET_WM_NAME", - "_NET_WM_ICON_NAME", - "_NET_WM_ICON", - }; - WMNativeAtom atoms[wlengthof(atomNames)]; - - /* Create missing CUT_BUFFERs */ - { - WMNativeAtom *rootWinProps; - int exists[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - int count; - - rootWinProps = XListProperties(display, scrPtr->rootWin, &count); - for (i = 0; i < count; i++) { - switch (rootWinProps[i]) { - case XA_CUT_BUFFER0: exists[0] = 1; break; - case XA_CUT_BUFFER1: exists[1] = 1; break; - case XA_CUT_BUFFER2: exists[2] = 1; break; - case XA_CUT_BUFFER3: exists[3] = 1; break; - case XA_CUT_BUFFER4: exists[4] = 1; break; - case XA_CUT_BUFFER5: exists[5] = 1; break; - case XA_CUT_BUFFER6: exists[6] = 1; break; - case XA_CUT_BUFFER7: exists[7] = 1; break; - default: break; - } - } - if (rootWinProps) - XFree(rootWinProps); - for (i = 0; i < 8; i++) { - if (!exists[i]) - XStoreBuffer(display, "", 0, i); - } - } - - /* Modifier mask detection */ - scrPtr->ignoredModifierMask = 0; - { - XModifierKeymap *modmap; - KeyCode nlock, slock; - static int mask_table[8] = { - WM_MOD_SHIFT, WM_MOD_LOCK, WM_MOD_CONTROL, WM_MOD_MOD1, - WM_MOD_MOD2, WM_MOD_MOD3, WM_MOD_MOD4, WM_MOD_MOD5 - }; - unsigned int numLockMask = 0, scrollLockMask = 0; - - nlock = XKeysymToKeycode(display, XK_Num_Lock); - slock = XKeysymToKeycode(display, XK_Scroll_Lock); - modmap = XGetModifierMapping(display); - 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); - scrPtr->ignoredModifierMask = numLockMask | scrollLockMask | WM_MOD_LOCK; - } - - /* GCs */ - gcv.graphics_exposures = False; - gcv.function = GXxor; - gcv.foreground = W_PIXEL(scrPtr->white); - if (gcv.foreground == 0) - gcv.foreground = 1; - scrPtr->xorGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCFunction - | GCGraphicsExposures | GCForeground, &gcv); - - gcv.function = GXxor; - gcv.foreground = W_PIXEL(scrPtr->gray); - gcv.subwindow_mode = IncludeInferiors; - scrPtr->ixorGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCFunction - | GCGraphicsExposures | GCForeground | GCSubwindowMode, &gcv); - - gcv.function = GXcopy; - scrPtr->copyGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCFunction | GCGraphicsExposures, &gcv); - scrPtr->clipGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCFunction | GCGraphicsExposures, &gcv); - - stipple = XCreateBitmapFromData(display, W_DRAWABLE(scrPtr), STIPPLE_BITS, STIPPLE_WIDTH, STIPPLE_HEIGHT); - gcv.foreground = W_PIXEL(scrPtr->darkGray); - gcv.background = W_PIXEL(scrPtr->gray); - gcv.fill_style = FillStippled; - gcv.stipple = stipple; - scrPtr->stippleGC = XCreateGC(display, W_DRAWABLE(scrPtr), - GCForeground | GCBackground | GCStipple - | GCFillStyle | GCGraphicsExposures, &gcv); - scrPtr->drawStringGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCGraphicsExposures, &gcv); - scrPtr->drawImStringGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCGraphicsExposures, &gcv); - scrPtr->monoGC = XCreateGC(display, stipple, 0, NULL); - scrPtr->stipple = stipple; - - /* Input method */ - W_InitIM(scrPtr); - - /* Cursors */ - scrPtr->defaultCursor = XCreateFontCursor(display, XC_left_ptr); - scrPtr->textCursor = XCreateFontCursor(display, XC_xterm); - { - XColor bla; - WMNativePixmap blank; - blank = XCreatePixmap(display, scrPtr->stipple, 1, 1, 1); - XSetForeground(display, scrPtr->monoGC, 0); - XFillRectangle(display, blank, scrPtr->monoGC, 0, 0, 1, 1); - scrPtr->invisibleCursor = XCreatePixmapCursor(display, blank, blank, &bla, &bla, 0, 0); - XFreePixmap(display, blank); - } - - /* Atoms */ -#ifdef HAVE_XINTERNATOMS - XInternAtoms(display, atomNames, wlengthof(atomNames), False, atoms); -#else - for (i = 0; i < wlengthof(atomNames); i++) - atoms[i] = XInternAtom(display, atomNames[i], False); -#endif - i = 0; - scrPtr->attribsAtom = atoms[i++]; - scrPtr->deleteWindowAtom = atoms[i++]; - scrPtr->protocolsAtom = atoms[i++]; - scrPtr->clipboardAtom = atoms[i++]; - scrPtr->xdndAwareAtom = atoms[i++]; - scrPtr->xdndSelectionAtom = atoms[i++]; - scrPtr->xdndEnterAtom = atoms[i++]; - scrPtr->xdndLeaveAtom = atoms[i++]; - scrPtr->xdndPositionAtom = atoms[i++]; - scrPtr->xdndDropAtom = atoms[i++]; - scrPtr->xdndFinishedAtom = atoms[i++]; - scrPtr->xdndTypeListAtom = atoms[i++]; - scrPtr->xdndActionListAtom = atoms[i++]; - scrPtr->xdndActionDescriptionAtom = atoms[i++]; - scrPtr->xdndStatusAtom = atoms[i++]; - scrPtr->xdndActionCopy = atoms[i++]; - scrPtr->xdndActionMove = atoms[i++]; - scrPtr->xdndActionLink = atoms[i++]; - scrPtr->xdndActionAsk = atoms[i++]; - scrPtr->xdndActionPrivate = atoms[i++]; - scrPtr->wmIconDragOffsetAtom = atoms[i++]; - scrPtr->wmStateAtom = atoms[i++]; - scrPtr->utf8String = atoms[i++]; - scrPtr->netwmName = atoms[i++]; - scrPtr->netwmIconName = atoms[i++]; - scrPtr->netwmIcon = atoms[i++]; - - /* Application group leader */ - W_InitApplication(scrPtr); -} - WMScreen *WMCreateScreenWithRContext(Display * display, int screen, RContext * context) { W_Screen *scrPtr; diff --git a/WINGs/widgets_x11.c b/WINGs/widgets_x11.c new file mode 100644 index 0000000..81e3a8f --- /dev/null +++ b/WINGs/widgets_x11.c @@ -0,0 +1,231 @@ +/* + * widgets_x11.c — X11-specific WINGs platform init. + * + * Owns every Xlib call that used to live in widgets.c. The shared + * widgets.c is now backend-neutral and dispatches to this file (via + * direct function calls — ZZ TODO: vtable when adding more backends) + * for X11-specific setup. + * + * This file is the X11 counterpart to wclient_wl.c (Wayland client) + * and to the compositor-internal wl_backend.c paths. + */ + +#include "WINGsP.h" +#include "wconfig.h" + +#include +#include +#include +#include +#include + +#include +#include + +/* These match the static stipple data in widgets.c (kept as fallback). */ +#define STIPPLE_WIDTH 8 +#define STIPPLE_HEIGHT 8 +static char STIPPLE_BITS[] = { + 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 +}; + +/* + * W_X11PlatformInit — the GCs/cursors/atoms/IM init that the X11 view + * backend hooks via W_ViewBackendX11.platform_init. Moved from + * widgets.c so the shared file stops linking against Xlib. + */ +void W_X11PlatformInit(W_Screen *scrPtr) +{ + Display *display = scrPtr->display; + XGCValues gcv; + Pixmap stipple; + int i; + static char *atomNames[] = { + "_GNUSTEP_WM_ATTR", + "WM_DELETE_WINDOW", + "WM_PROTOCOLS", + "CLIPBOARD", + "XdndAware", + "XdndSelection", + "XdndEnter", + "XdndLeave", + "XdndPosition", + "XdndDrop", + "XdndFinished", + "XdndTypeList", + "XdndActionList", + "XdndActionDescription", + "XdndStatus", + "XdndActionCopy", + "XdndActionMove", + "XdndActionLink", + "XdndActionAsk", + "XdndActionPrivate", + "_WINGS_DND_MOUSE_OFFSET", + "WM_STATE", + "UTF8_STRING", + "_NET_WM_NAME", + "_NET_WM_ICON_NAME", + "_NET_WM_ICON", + }; + Atom atoms[wlengthof(atomNames)]; + + /* Create missing CUT_BUFFERs */ + { + Atom *rootWinProps; + int exists[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + int count; + + rootWinProps = XListProperties(display, scrPtr->rootWin, &count); + for (i = 0; i < count; i++) { + switch (rootWinProps[i]) { + case XA_CUT_BUFFER0: exists[0] = 1; break; + case XA_CUT_BUFFER1: exists[1] = 1; break; + case XA_CUT_BUFFER2: exists[2] = 1; break; + case XA_CUT_BUFFER3: exists[3] = 1; break; + case XA_CUT_BUFFER4: exists[4] = 1; break; + case XA_CUT_BUFFER5: exists[5] = 1; break; + case XA_CUT_BUFFER6: exists[6] = 1; break; + case XA_CUT_BUFFER7: exists[7] = 1; break; + default: break; + } + } + if (rootWinProps) + XFree(rootWinProps); + for (i = 0; i < 8; i++) { + if (!exists[i]) + XStoreBuffer(display, "", 0, i); + } + } + + /* Modifier mask detection */ + scrPtr->ignoredModifierMask = 0; + { + XModifierKeymap *modmap; + KeyCode nlock, slock; + static int mask_table[8] = { + WM_MOD_SHIFT, WM_MOD_LOCK, WM_MOD_CONTROL, WM_MOD_MOD1, + WM_MOD_MOD2, WM_MOD_MOD3, WM_MOD_MOD4, WM_MOD_MOD5 + }; + unsigned int numLockMask = 0, scrollLockMask = 0; + + nlock = XKeysymToKeycode(display, XK_Num_Lock); + slock = XKeysymToKeycode(display, XK_Scroll_Lock); + modmap = XGetModifierMapping(display); + 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); + scrPtr->ignoredModifierMask = numLockMask | scrollLockMask | WM_MOD_LOCK; + } + + /* GCs */ + gcv.graphics_exposures = False; + gcv.function = GXxor; + gcv.foreground = W_PIXEL(scrPtr->white); + if (gcv.foreground == 0) + gcv.foreground = 1; + scrPtr->xorGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCFunction + | GCGraphicsExposures | GCForeground, &gcv); + + gcv.function = GXxor; + gcv.foreground = W_PIXEL(scrPtr->gray); + gcv.subwindow_mode = IncludeInferiors; + scrPtr->ixorGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCFunction + | GCGraphicsExposures | GCForeground | GCSubwindowMode, &gcv); + + gcv.function = GXcopy; + scrPtr->copyGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCFunction | GCGraphicsExposures, &gcv); + scrPtr->clipGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCFunction | GCGraphicsExposures, &gcv); + + stipple = XCreateBitmapFromData(display, W_DRAWABLE(scrPtr), STIPPLE_BITS, STIPPLE_WIDTH, STIPPLE_HEIGHT); + gcv.foreground = W_PIXEL(scrPtr->darkGray); + gcv.background = W_PIXEL(scrPtr->gray); + gcv.fill_style = FillStippled; + gcv.stipple = stipple; + scrPtr->stippleGC = XCreateGC(display, W_DRAWABLE(scrPtr), + GCForeground | GCBackground | GCStipple + | GCFillStyle | GCGraphicsExposures, &gcv); + scrPtr->drawStringGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCGraphicsExposures, &gcv); + scrPtr->drawImStringGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCGraphicsExposures, &gcv); + scrPtr->monoGC = XCreateGC(display, stipple, 0, NULL); + scrPtr->stipple = stipple; + + /* Input method */ + W_InitIM(scrPtr); + + /* Cursors */ + scrPtr->defaultCursor = XCreateFontCursor(display, XC_left_ptr); + scrPtr->textCursor = XCreateFontCursor(display, XC_xterm); + { + XColor bla; + Pixmap blank; + blank = XCreatePixmap(display, scrPtr->stipple, 1, 1, 1); + XSetForeground(display, scrPtr->monoGC, 0); + XFillRectangle(display, blank, scrPtr->monoGC, 0, 0, 1, 1); + scrPtr->invisibleCursor = XCreatePixmapCursor(display, blank, blank, &bla, &bla, 0, 0); + XFreePixmap(display, blank); + } + + /* Atoms */ +#ifdef HAVE_XINTERNATOMS + XInternAtoms(display, atomNames, wlengthof(atomNames), False, atoms); +#else + for (i = 0; i < wlengthof(atomNames); i++) + atoms[i] = XInternAtom(display, atomNames[i], False); +#endif + i = 0; + scrPtr->attribsAtom = atoms[i++]; + scrPtr->deleteWindowAtom = atoms[i++]; + scrPtr->protocolsAtom = atoms[i++]; + scrPtr->clipboardAtom = atoms[i++]; + scrPtr->xdndAwareAtom = atoms[i++]; + scrPtr->xdndSelectionAtom = atoms[i++]; + scrPtr->xdndEnterAtom = atoms[i++]; + scrPtr->xdndLeaveAtom = atoms[i++]; + scrPtr->xdndPositionAtom = atoms[i++]; + scrPtr->xdndDropAtom = atoms[i++]; + scrPtr->xdndFinishedAtom = atoms[i++]; + scrPtr->xdndTypeListAtom = atoms[i++]; + scrPtr->xdndActionListAtom = atoms[i++]; + scrPtr->xdndActionDescriptionAtom = atoms[i++]; + scrPtr->xdndStatusAtom = atoms[i++]; + scrPtr->xdndActionCopy = atoms[i++]; + scrPtr->xdndActionMove = atoms[i++]; + scrPtr->xdndActionLink = atoms[i++]; + scrPtr->xdndActionAsk = atoms[i++]; + scrPtr->xdndActionPrivate = atoms[i++]; + scrPtr->wmIconDragOffsetAtom = atoms[i++]; + scrPtr->wmStateAtom = atoms[i++]; + scrPtr->utf8String = atoms[i++]; + scrPtr->netwmName = atoms[i++]; + scrPtr->netwmIconName = atoms[i++]; + scrPtr->netwmIcon = atoms[i++]; + + /* Application group leader */ + W_InitApplication(scrPtr); +} + +/* + * W_X11OpenDisplay — open the X11 display and return a populated WMScreen. + * + * Called by WMOpenScreen() from widgets.c when the autodetect logic + * decides this should be an X11 connection (no WAYLAND_DISPLAY env, no + * "wayland" prefix in the display string, etc.). Extracting this here + * lets widgets.c be free of XOpenDisplay. + */ +WMScreen *W_X11OpenDisplay(const char *display) +{ + Display *dpy = XOpenDisplay(display); + if (!dpy) { + wwarning(_("WINGs: could not open display %s"), XDisplayName(display)); + return NULL; + } + return WMCreateSimpleApplicationScreen(dpy); +} diff --git a/src/wconfig.h b/src/wconfig.h index 96e292f..46af069 100644 --- a/src/wconfig.h +++ b/src/wconfig.h @@ -195,7 +195,7 @@ /* calculate window edge resistance from edge resistance */ #define WIN_RESISTANCE(x) (((x)*20)/30) -/* WNativeWindow level where icons reside */ +/* Window level where icons reside */ #define NORMAL_ICON_LEVEL WMNormalLevel /* do not divide main menu and submenu in different tiers,