wayland: Phase 19 — guard framewin.c X11 rendering against dpy==NULL

When the Wayland backend is active dpy is NULL; all X11 drawing calls
in framewin.c (XMapRaised, XSetWindowBackground, XSetWindowBorder,
XSetWindowBorderWidth, XSetWindowBackgroundPixmap, XClearWindow,
XDrawLine) must be skipped to prevent SIGSEGV when managing XWayland
or synthetic frame windows.

Changes:
- allocFrameBorderPixel: early return when !dpy (no X11 colormap)
- wFrameWindowUpdateBorders: guard XSetWindowBorderWidth and
  XSetWindowBorder blocks; guard XMapRaised/XSetWindowBackground in
  button-creation branches; guard XMapWindow/XLowerWindow for resizebar
- wFrameWindowChangeState: guard XSetWindowBorder block
- wFrameWindowHideButton: guard XUnmapWindow calls
- wFrameWindowShowButton: guard XMapWindow and XClearWindow calls
- updateTexture: early return when !dpy
- remakeTexture: guard resizebar XSetWindowBackgroundPixmap/XClearWindow
- wFrameWindowPaint: guard entire resizebar XDrawLine section

Frame window structure (wCoreCreate, descriptor setup, stacking) still
runs normally; only the visual rendering is skipped in Wayland mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Levi Neely 2026-03-28 22:00:42 +01:00
parent 8c211e1a33
commit f86d294223
1 changed files with 77 additions and 55 deletions

View File

@ -62,6 +62,10 @@ static void allocFrameBorderPixel(Colormap colormap, const char *color_name, uns
*pixel = NULL;
/* Phase 19: Wayland — no X11 colormap to query */
if (!dpy)
return;
if (! wGetColorForColormap(colormap, color_name, &xcol))
return;
@ -237,19 +241,20 @@ void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
if (width < theight * 4)
fwin->flags.lbutton_dont_fit = 1;
else
else if (dpy)
XMapRaised(dpy, fwin->left_button->window);
} else if (wPreferences.new_style == TS_OLD) {
fwin->left_button =
wCoreCreate(fwin->titlebar, 3, (theight - bsize) / 2, bsize, bsize);
XSetWindowBackground(dpy, fwin->left_button->window,
scr->widget_texture->normal.pixel);
if (dpy)
XSetWindowBackground(dpy, fwin->left_button->window,
scr->widget_texture->normal.pixel);
if (width < theight * 3)
fwin->flags.lbutton_dont_fit = 1;
else
else if (dpy)
XMapRaised(dpy, fwin->left_button->window);
} else {
@ -257,12 +262,13 @@ void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
wCoreCreate(fwin->titlebar, 3, (theight-bsize)/2,
bsize, bsize);
XSetWindowBackground(dpy, fwin->left_button->window,
scr->widget_texture->dark.pixel);
if (dpy)
XSetWindowBackground(dpy, fwin->left_button->window,
scr->widget_texture->dark.pixel);
if (width < theight * 3)
fwin->flags.lbutton_dont_fit = 1;
else
else if (dpy)
XMapRaised(dpy, fwin->left_button->window);
}
@ -275,19 +281,20 @@ void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
if (width < theight * 4)
fwin->flags.languagebutton_dont_fit = 1;
else
else if (dpy)
XMapRaised(dpy, fwin->language_button->window);
} else {
fwin->language_button =
wCoreCreate(fwin->titlebar, bsize + 6, (theight - bsize) / 2,
bsize, bsize);
XSetWindowBackground(dpy, fwin->language_button->window,
scr->widget_texture->normal.pixel);
if (dpy)
XSetWindowBackground(dpy, fwin->language_button->window,
scr->widget_texture->normal.pixel);
if (width < theight * 3)
fwin->flags.languagebutton_dont_fit = 1;
else
else if (dpy)
XMapRaised(dpy, fwin->language_button->window);
}
}
@ -302,26 +309,29 @@ void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
fwin->right_button =
wCoreCreate(fwin->titlebar, width - bsize - 3,
(theight - bsize) / 2, bsize, bsize);
XSetWindowBackground(dpy, fwin->right_button->window,
scr->widget_texture->normal.pixel);
if (dpy)
XSetWindowBackground(dpy, fwin->right_button->window,
scr->widget_texture->normal.pixel);
} else {
fwin->right_button =
wCoreCreate(fwin->titlebar, width-bsize-3,
(theight-bsize)/2, bsize, bsize);
XSetWindowBackground(dpy, fwin->right_button->window,
scr->widget_texture->dark.pixel);
if (dpy)
XSetWindowBackground(dpy, fwin->right_button->window,
scr->widget_texture->dark.pixel);
}
if (width < theight * 2)
fwin->flags.rbutton_dont_fit = 1;
else
else if (dpy)
XMapRaised(dpy, fwin->right_button->window);
}
if (wPreferences.new_style == TS_NEW)
updateTitlebar(fwin);
XMapRaised(dpy, fwin->titlebar->window);
if (dpy)
XMapRaised(dpy, fwin->titlebar->window);
fwin->flags.need_texture_remake = 1;
}
@ -342,8 +352,10 @@ void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
fwin->resizebar_corner_width = 0;
}
XMapWindow(dpy, fwin->resizebar->window);
XLowerWindow(dpy, fwin->resizebar->window);
if (dpy) {
XMapWindow(dpy, fwin->resizebar->window);
XLowerWindow(dpy, fwin->resizebar->window);
}
fwin->flags.need_texture_remake = 1;
} else {
@ -364,10 +376,12 @@ void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
if (height + fwin->top_width + fwin->bottom_width != fwin->core->height && !(flags & WFF_IS_SHADED))
wFrameWindowResize(fwin, width, height + fwin->top_width + fwin->bottom_width);
if (flags & WFF_BORDER)
XSetWindowBorderWidth(dpy, fwin->core->window, scr->frame_border_width);
else
XSetWindowBorderWidth(dpy, fwin->core->window, 0);
if (dpy) {
if (flags & WFF_BORDER)
XSetWindowBorderWidth(dpy, fwin->core->window, scr->frame_border_width);
else
XSetWindowBorderWidth(dpy, fwin->core->window, 0);
}
/* setup object descriptors */
if (fwin->titlebar) {
@ -413,17 +427,18 @@ void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
allocFrameBorderPixel(fwin->colormap, WMGetColorRGBDescription(scr->frame_focused_border_color), &fwin->focused_border_pixel);
allocFrameBorderPixel(fwin->colormap, WMGetColorRGBDescription(scr->frame_selected_border_color), &fwin->selected_border_pixel);
if (flags & WFF_SELECTED) {
if (fwin->selected_border_pixel)
XSetWindowBorder(dpy, fwin->core->window, *fwin->selected_border_pixel);
}
else {
if (fwin->flags.state == WS_FOCUSED) {
if (fwin->focused_border_pixel)
XSetWindowBorder(dpy, fwin->core->window, *fwin->focused_border_pixel);
if (dpy) {
if (flags & WFF_SELECTED) {
if (fwin->selected_border_pixel)
XSetWindowBorder(dpy, fwin->core->window, *fwin->selected_border_pixel);
} else {
if (fwin->border_pixel)
XSetWindowBorder(dpy, fwin->core->window, *fwin->border_pixel);
if (fwin->flags.state == WS_FOCUSED) {
if (fwin->focused_border_pixel)
XSetWindowBorder(dpy, fwin->core->window, *fwin->focused_border_pixel);
} else {
if (fwin->border_pixel)
XSetWindowBorder(dpy, fwin->core->window, *fwin->border_pixel);
}
}
}
}
@ -478,12 +493,14 @@ void wFrameWindowChangeState(WFrameWindow * fwin, int state)
fwin->flags.state = state;
fwin->flags.need_texture_change = 1;
if (fwin->flags.state == WS_FOCUSED) {
if (fwin->focused_border_pixel)
XSetWindowBorder(dpy, fwin->core->window, *fwin->focused_border_pixel);
} else {
if (fwin->border_pixel)
XSetWindowBorder(dpy, fwin->core->window, *fwin->border_pixel);
if (dpy) {
if (fwin->flags.state == WS_FOCUSED) {
if (fwin->focused_border_pixel)
XSetWindowBorder(dpy, fwin->core->window, *fwin->focused_border_pixel);
} else {
if (fwin->border_pixel)
XSetWindowBorder(dpy, fwin->core->window, *fwin->border_pixel);
}
}
wFrameWindowPaint(fwin);
}
@ -560,17 +577,17 @@ static void updateTitlebar(WFrameWindow * fwin)
void wFrameWindowHideButton(WFrameWindow * fwin, int flags)
{
if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
XUnmapWindow(dpy, fwin->right_button->window);
if (dpy) XUnmapWindow(dpy, fwin->right_button->window);
fwin->flags.hide_right_button = 1;
}
if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
XUnmapWindow(dpy, fwin->left_button->window);
if (dpy) XUnmapWindow(dpy, fwin->left_button->window);
fwin->flags.hide_left_button = 1;
}
#ifdef XKB_BUTTON_HINT
if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
XUnmapWindow(dpy, fwin->language_button->window);
if (dpy) XUnmapWindow(dpy, fwin->language_button->window);
fwin->flags.hide_language_button = 1;
}
#endif
@ -582,7 +599,7 @@ void wFrameWindowHideButton(WFrameWindow * fwin, int flags)
#ifdef XKB_BUTTON_HINT
updateTitlebar(fwin);
#else
XClearWindow(dpy, fwin->titlebar->window);
if (dpy) XClearWindow(dpy, fwin->titlebar->window);
wFrameWindowPaint(fwin);
#endif
}
@ -594,7 +611,7 @@ void wFrameWindowShowButton(WFrameWindow * fwin, int flags)
{
if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button && fwin->flags.hide_right_button) {
if (!fwin->flags.rbutton_dont_fit)
if (!fwin->flags.rbutton_dont_fit && dpy)
XMapWindow(dpy, fwin->right_button->window);
fwin->flags.hide_right_button = 0;
@ -602,7 +619,7 @@ void wFrameWindowShowButton(WFrameWindow * fwin, int flags)
#ifdef XKB_BUTTON_HINT
if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button && fwin->flags.hide_language_button) {
if (!fwin->flags.languagebutton_dont_fit)
if (!fwin->flags.languagebutton_dont_fit && dpy)
XMapWindow(dpy, fwin->language_button->window);
fwin->flags.hide_language_button = 0;
@ -611,7 +628,7 @@ void wFrameWindowShowButton(WFrameWindow * fwin, int flags)
if ((flags & WFF_LEFT_BUTTON) && fwin->left_button && fwin->flags.hide_left_button) {
if (!fwin->flags.lbutton_dont_fit)
if (!fwin->flags.lbutton_dont_fit && dpy)
XMapWindow(dpy, fwin->left_button->window);
fwin->flags.hide_left_button = 0;
@ -621,7 +638,7 @@ void wFrameWindowShowButton(WFrameWindow * fwin, int flags)
if (wPreferences.new_style == TS_NEW) {
updateTitlebar(fwin);
} else {
XClearWindow(dpy, fwin->titlebar->window);
if (dpy) XClearWindow(dpy, fwin->titlebar->window);
wFrameWindowPaint(fwin);
}
checkTitleSize(fwin);
@ -782,6 +799,10 @@ static void updateTexture(WFrameWindow * fwin)
int i;
unsigned long pixel;
/* Phase 19: Wayland — no X11 connection to update window backgrounds */
if (!dpy)
return;
i = fwin->flags.state;
if (fwin->titlebar) {
if (fwin->title_texture[i]->any.type != WTEX_SOLID) {
@ -907,13 +928,14 @@ static void remakeTexture(WFrameWindow * fwin, int state)
}
/* this part should be in updateTexture() */
if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID)
XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window, fwin->resizebar_back[0]);
else
XSetWindowBackground(dpy, fwin->resizebar->window,
fwin->resizebar_texture[0]->solid.normal.pixel);
XClearWindow(dpy, fwin->resizebar->window);
if (dpy) {
if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID)
XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window, fwin->resizebar_back[0]);
else
XSetWindowBackground(dpy, fwin->resizebar->window,
fwin->resizebar_texture[0]->solid.normal.pixel);
XClearWindow(dpy, fwin->resizebar->window);
}
}
}
@ -961,7 +983,7 @@ void wFrameWindowPaint(WFrameWindow * fwin)
fwin->titlebar->height, (WTexSolid *) fwin->title_texture[state], WREL_RAISED);
}
if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
if (dpy && fwin->resizebar && !fwin->flags.repaint_only_titlebar
&& fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
Window win;
int w, h;