WINGs: move updateDisabledMask to render backend vtable

Add create_disabled_mask to W_RenderBackend. X11 backend uses
XCreatePixmap + stippled GC fill. Wayland backend creates a
pixman a8 checkerboard mask. Middle layer (wbutton.c) dispatches
through vtable — zero X11 code remains.
This commit is contained in:
Levi Neely 2026-05-14 17:58:33 +02:00
parent 2910e73878
commit 213f5a6528
4 changed files with 71 additions and 28 deletions

View File

@ -564,6 +564,9 @@ typedef struct W_RenderBackend {
void (*fill_arc)(void *rctx, WMDrawable d, WMColor *color,
int x, int y, unsigned int w, unsigned int h,
int angle1, int angle2);
/* Create a stippled disabled mask from a source mask pixmap */
Pixmap (*create_disabled_mask)(void *rctx, Pixmap src_mask,
unsigned int width, unsigned int height);
} W_RenderBackend;
extern const W_RenderBackend W_RenderBackendX11;

View File

@ -219,41 +219,19 @@ WMButton *WMCreateButton(WMWidget * parent, WMButtonType type)
static void updateDisabledMask(WMButton * bPtr)
{
WMScreen *scr = WMWidgetScreen(bPtr);
Display *dpy = scr->display;
const W_RenderBackend *R = scr->renderBackend;
void *rctx = scr->renderBackendCtx;
if (bPtr->image) {
XGCValues gcv;
if (bPtr->dimage->mask) {
XFreePixmap(dpy, bPtr->dimage->mask);
R->pixmap_free(rctx, (WMDrawable)bPtr->dimage->mask);
bPtr->dimage->mask = None;
}
if (bPtr->flags.dimsWhenDisabled) {
bPtr->dimage->mask = XCreatePixmap(dpy, scr->stipple,
bPtr->dimage->width, bPtr->dimage->height, 1);
XSetForeground(dpy, scr->monoGC, 0);
XFillRectangle(dpy, bPtr->dimage->mask, scr->monoGC, 0, 0,
bPtr->dimage->width, bPtr->dimage->height);
gcv.foreground = 1;
gcv.background = 0;
gcv.stipple = scr->stipple;
gcv.fill_style = FillStippled;
gcv.clip_mask = bPtr->image->mask;
gcv.clip_x_origin = 0;
gcv.clip_y_origin = 0;
XChangeGC(dpy, scr->monoGC, GCForeground | GCBackground | GCStipple
| GCFillStyle | GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
XFillRectangle(dpy, bPtr->dimage->mask, scr->monoGC, 0, 0,
bPtr->dimage->width, bPtr->dimage->height);
gcv.fill_style = FillSolid;
gcv.clip_mask = None;
XChangeGC(dpy, scr->monoGC, GCFillStyle | GCClipMask, &gcv);
bPtr->dimage->mask = R->create_disabled_mask(rctx,
bPtr->image->mask,
bPtr->dimage->width, bPtr->dimage->height);
}
}
}

View File

@ -235,6 +235,31 @@ render_wl_fill_arc(void *rctx, WMDrawable d, WMColor *color,
}
}
static Pixmap
render_wl_create_disabled_mask(void *rctx, Pixmap src_mask,
unsigned int width, unsigned int height)
{
(void)rctx;
pixman_image_t *mask = pixman_image_create_bits(PIXMAN_a8, width, height, NULL, 0);
pixman_image_t *src = src_mask ? (pixman_image_t *)(uintptr_t)src_mask : NULL;
uint8_t *mdata = (uint8_t *)pixman_image_get_data(mask);
int stride = pixman_image_get_stride(mask);
uint8_t *sdata = src ? (uint8_t *)pixman_image_get_data(src) : NULL;
int sstride = src ? pixman_image_get_stride(src) : 0;
for (unsigned int y = 0; y < height; y++) {
for (unsigned int x = 0; x < width; x++) {
int stipple = ((x + y) & 1);
int src_opaque = 1;
if (sdata)
src_opaque = sdata[y * sstride + x] > 0;
mdata[y * stride + x] = (stipple && src_opaque) ? 0xFF : 0x00;
}
}
return (Pixmap)(uintptr_t)mask;
}
const W_RenderBackend W_RenderBackendWL = {
.screen_init = render_wl_screen_init,
.screen_fini = render_wl_screen_fini,
@ -248,4 +273,5 @@ const W_RenderBackend W_RenderBackendWL = {
.composite_pixmap = render_wl_composite_pixmap,
.fill_polygon = render_wl_fill_polygon,
.fill_arc = render_wl_fill_arc,
.create_disabled_mask = render_wl_create_disabled_mask,
};

View File

@ -123,6 +123,41 @@ render_x11_fill_arc(void *rctx, WMDrawable d, WMColor *color,
x, y, w, h, angle1, angle2);
}
static Pixmap
render_x11_create_disabled_mask(void *rctx, Pixmap src_mask,
unsigned int width, unsigned int height)
{
RenderCtxX11 *ctx = rctx;
W_Screen *scr = ctx->scr;
Display *dpy = scr->display;
XGCValues gcv;
Pixmap mask;
mask = XCreatePixmap(dpy, scr->stipple, width, height, 1);
XSetForeground(dpy, scr->monoGC, 0);
XFillRectangle(dpy, mask, scr->monoGC, 0, 0, width, height);
gcv.foreground = 1;
gcv.background = 0;
gcv.stipple = scr->stipple;
gcv.fill_style = FillStippled;
gcv.clip_mask = src_mask;
gcv.clip_x_origin = 0;
gcv.clip_y_origin = 0;
XChangeGC(dpy, scr->monoGC, GCForeground | GCBackground | GCStipple
| GCFillStyle | GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
XFillRectangle(dpy, mask, scr->monoGC, 0, 0, width, height);
gcv.fill_style = FillSolid;
gcv.clip_mask = None;
XChangeGC(dpy, scr->monoGC, GCFillStyle | GCClipMask, &gcv);
return mask;
}
const W_RenderBackend W_RenderBackendX11 = {
.screen_init = render_x11_screen_init,
.screen_fini = render_x11_screen_fini,
@ -136,4 +171,5 @@ const W_RenderBackend W_RenderBackendX11 = {
.composite_pixmap = render_x11_composite_pixmap,
.fill_polygon = render_x11_fill_polygon,
.fill_arc = render_x11_fill_arc,
.create_disabled_mask = render_x11_create_disabled_mask,
};