wings: phase γ (widgets.c) — split Xlib calls into widgets_x11.c

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.
This commit is contained in:
Window Maker 2026-05-24 10:55:30 +02:00
parent 0f839a9c6d
commit b5c46870aa
5 changed files with 249 additions and 235 deletions

View File

@ -53,6 +53,7 @@ libWINGs_la_SOURCES = \
wfont_wl.c \
wfontpanel.c \
widgets.c \
widgets_x11.c \
winputmethod.c \
wlabel.c \
wlist.c \

View File

@ -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);

View File

@ -2,12 +2,10 @@
#include "WINGsP.h"
#include "wconfig.h"
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <X11/cursorfont.h>
#include <X11/Xlocale.h>
/* 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;

231
WINGs/widgets_x11.c Normal file
View File

@ -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 <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <X11/cursorfont.h>
#include <X11/Xlocale.h>
#include <stdlib.h>
#include <string.h>
/* 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);
}

View File

@ -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,