Fix Wayland startup: compositor window appears and event loop runs
Three root causes fixed: 1. RCreateContext crash: wScreenInit called RCreateContext(dpy=NULL). Fix: add RCreateContextWayland() to wrlib — creates a minimal 32-bit ARGB context without X11. Wayland path in screen.c now always taken when is_wayland (removed incorrect XWayland fallthrough). 2. Color parsing: parse_color and get_color_for_colormap were no-ops. Fix: implement real color parser in wl_backend supporting #RGB, #RRGGBB, #RRRRGGGGBBBB, rgb:RR/GG/BB, and common named colors. Texture creation (solid, gradient) now works in Wayland mode. 3. RConvertImage crash: wrlib tried XCreateImage with NULL display. Fix: RConvertImage/RConvertImageMask return success with pixmap=0 when context->dpy is NULL. Callers don't use pixmaps in Wayland mode (rendering goes through vtable slots to pixman buffers). 4. Workspace crash: Wayland path skipped wWorkspaceNew(), so workspace_count=0 when menu tried to access workspace entries. Fix: add wWorkspaceNew + netwm_init to Wayland screen init path. Result: compositor starts, event loop runs, window is visible. WMAKER_USE_WAYLAND=1 wmaker now shows a compositor window.
This commit is contained in:
parent
9c48a0c841
commit
b4484e05bc
|
|
@ -1764,6 +1764,9 @@ typedef struct WMBackend {
|
|||
void (*netwm_position_splash)(WWindow *wwin, int *x, int *y, int width, int height);
|
||||
void (*netwm_check_initial_frame_state)(WWindow *wwin);
|
||||
|
||||
/* wrlib context creation */
|
||||
RContext *(*create_rcontext)(int screen_number, RContextAttributes *attribs);
|
||||
|
||||
} WMBackend;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -6142,9 +6142,109 @@ static void wl_noop_appicon_paint(WAppIcon *aicon) { (void)aicon; }
|
|||
static void wl_noop_restore_desktop(WScreen *scr) { (void)scr; }
|
||||
static void wl_noop_wipe_desktop(WScreen *scr) { (void)scr; }
|
||||
|
||||
static int wl_noop_get_color_for_colormap(unsigned long colormap,
|
||||
static int wl_get_color_for_colormap(unsigned long colormap,
|
||||
const char *color_name, XColor *color)
|
||||
{ (void)colormap; (void)color_name; (void)color; return 0; }
|
||||
{
|
||||
unsigned int r, g, b;
|
||||
(void)colormap;
|
||||
|
||||
if (!color_name || !color)
|
||||
return 0;
|
||||
|
||||
/* Parse #RGB, #RRGGBB, #RRRRGGGGBBBB */
|
||||
if (color_name[0] == '#') {
|
||||
int len = strlen(color_name + 1);
|
||||
if (len == 6) {
|
||||
if (sscanf(color_name, "#%2x%2x%2x", &r, &g, &b) == 3) {
|
||||
color->red = r << 8 | r;
|
||||
color->green = g << 8 | g;
|
||||
color->blue = b << 8 | b;
|
||||
color->pixel = (0xFF << 24) | (r << 16) | (g << 8) | b;
|
||||
return 1;
|
||||
}
|
||||
} else if (len == 12) {
|
||||
if (sscanf(color_name, "#%4hx%4hx%4hx",
|
||||
&color->red, &color->green, &color->blue) == 3) {
|
||||
color->pixel = (0xFF << 24) |
|
||||
((color->red >> 8) << 16) |
|
||||
((color->green >> 8) << 8) |
|
||||
(color->blue >> 8);
|
||||
return 1;
|
||||
}
|
||||
} else if (len == 3) {
|
||||
if (sscanf(color_name, "#%1x%1x%1x", &r, &g, &b) == 3) {
|
||||
color->red = r << 12 | r << 8 | r << 4 | r;
|
||||
color->green = g << 12 | g << 8 | g << 4 | g;
|
||||
color->blue = b << 12 | b << 8 | b << 4 | b;
|
||||
color->pixel = (0xFF << 24) | (r*17 << 16) | (g*17 << 8) | b*17;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* X11 rgb:RR/GG/BB or rgb:RRRR/GGGG/BBBB format */
|
||||
if (strncasecmp(color_name, "rgb:", 4) == 0) {
|
||||
unsigned int rv, gv, bv;
|
||||
const char *p = color_name + 4;
|
||||
int n = sscanf(p, "%x/%x/%x", &rv, &gv, &bv);
|
||||
if (n == 3) {
|
||||
/* Determine component width from first component */
|
||||
const char *slash = strchr(p, '/');
|
||||
int width = slash ? (int)(slash - p) : 2;
|
||||
if (width == 1) {
|
||||
color->red = rv << 12 | rv << 8 | rv << 4 | rv;
|
||||
color->green = gv << 12 | gv << 8 | gv << 4 | gv;
|
||||
color->blue = bv << 12 | bv << 8 | bv << 4 | bv;
|
||||
} else if (width == 2) {
|
||||
color->red = rv << 8 | rv;
|
||||
color->green = gv << 8 | gv;
|
||||
color->blue = bv << 8 | bv;
|
||||
} else {
|
||||
color->red = rv;
|
||||
color->green = gv;
|
||||
color->blue = bv;
|
||||
}
|
||||
color->pixel = (0xFF << 24) |
|
||||
((color->red >> 8) << 16) |
|
||||
((color->green >> 8) << 8) |
|
||||
(color->blue >> 8);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Named colors — common ones */
|
||||
struct { const char *name; unsigned short r, g, b; } named[] = {
|
||||
{"black", 0x0000, 0x0000, 0x0000},
|
||||
{"white", 0xFFFF, 0xFFFF, 0xFFFF},
|
||||
{"red", 0xFFFF, 0x0000, 0x0000},
|
||||
{"green", 0x0000, 0xFFFF, 0x0000},
|
||||
{"blue", 0x0000, 0x0000, 0xFFFF},
|
||||
{"gray", 0xBEBE, 0xBEBE, 0xBEBE},
|
||||
{"grey", 0xBEBE, 0xBEBE, 0xBEBE},
|
||||
{"gray50", 0x7F7F, 0x7F7F, 0x7F7F},
|
||||
{"gray80", 0xCCCC, 0xCCCC, 0xCCCC},
|
||||
{"darkgray",0xA9A9, 0xA9A9, 0xA9A9},
|
||||
{"darkgrey",0xA9A9, 0xA9A9, 0xA9A9},
|
||||
{"lightgray",0xD3D3, 0xD3D3, 0xD3D3},
|
||||
{"lightgrey",0xD3D3, 0xD3D3, 0xD3D3},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
for (int i = 0; named[i].name; i++) {
|
||||
if (strcasecmp(color_name, named[i].name) == 0) {
|
||||
color->red = named[i].r;
|
||||
color->green = named[i].g;
|
||||
color->blue = named[i].b;
|
||||
color->pixel = (0xFF << 24) |
|
||||
((color->red >> 8) << 16) |
|
||||
((color->green >> 8) << 8) |
|
||||
(color->blue >> 8);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
wwarning(_("could not parse color \"%s\" (Wayland)"), color_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wl_noop_free_color(WScreen *scr, unsigned long pixel)
|
||||
{ (void)scr; (void)pixel; }
|
||||
|
|
@ -6234,8 +6334,8 @@ static void wl_noop_query_tree(WNativeWindow root, WNativeWindow **children_out,
|
|||
static WScreen *wl_noop_screen_for_window(WNativeWindow window)
|
||||
{ (void)window; return wScreenWithNumber(0); }
|
||||
|
||||
static int wl_noop_parse_color(WScreen *scr, const char *name, XColor *color_out)
|
||||
{ (void)scr; (void)name; (void)color_out; return 0; }
|
||||
static int wl_parse_color(WScreen *scr, const char *name, XColor *color_out)
|
||||
{ (void)scr; return wl_get_color_for_colormap(0, name, color_out); }
|
||||
static int wl_noop_cursor_create_from_files(WScreen *scr, const char *bitmap_path,
|
||||
const char *mask_path, Cursor *cursor_out)
|
||||
{ (void)scr; (void)bitmap_path; (void)mask_path; (void)cursor_out; return 0; }
|
||||
|
|
@ -6282,6 +6382,12 @@ static void wl_noop_netwm_check_client_hint_change(WWindow *w, void *e) { (void)
|
|||
static void wl_noop_netwm_position_splash(WWindow *w, int *x, int *y, int ww, int h) { (void)w;(void)x;(void)y;(void)ww;(void)h; }
|
||||
static void wl_noop_netwm_check_initial_frame_state(WWindow *w) { (void)w; }
|
||||
|
||||
static RContext *wl_create_rcontext(int screen_number, RContextAttributes *attribs)
|
||||
{
|
||||
(void)screen_number;
|
||||
return RCreateContextWayland(1920, 1080, attribs);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* vtable */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
|
@ -6475,7 +6581,7 @@ const WMBackend wl_backend = {
|
|||
.appicon_paint = wl_noop_appicon_paint,
|
||||
.restore_desktop = wl_noop_restore_desktop,
|
||||
.wipe_desktop = wl_noop_wipe_desktop,
|
||||
.get_color_for_colormap = wl_noop_get_color_for_colormap,
|
||||
.get_color_for_colormap = wl_get_color_for_colormap,
|
||||
.free_color = wl_noop_free_color,
|
||||
.colormap_install = wl_noop_colormap_install,
|
||||
.xdnd_init = wl_noop_xdnd_init,
|
||||
|
|
@ -6509,7 +6615,7 @@ const WMBackend wl_backend = {
|
|||
.context_init = wl_context_init,
|
||||
.query_tree = wl_noop_query_tree,
|
||||
.screen_for_window = wl_noop_screen_for_window,
|
||||
.parse_color = wl_noop_parse_color,
|
||||
.parse_color = wl_parse_color,
|
||||
.cursor_create_from_files = wl_noop_cursor_create_from_files,
|
||||
.cursor_free = wl_noop_cursor_free,
|
||||
.cursor_set = wl_noop_cursor_set,
|
||||
|
|
@ -6544,4 +6650,5 @@ const WMBackend wl_backend = {
|
|||
.netwm_check_client_hint_change = wl_noop_netwm_check_client_hint_change,
|
||||
.netwm_position_splash = wl_noop_netwm_position_splash,
|
||||
.netwm_check_initial_frame_state = wl_noop_netwm_check_initial_frame_state,
|
||||
.create_rcontext = wl_create_rcontext,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3381,6 +3381,11 @@ static void x11_netwm_check_initial_frame_state(WWindow *wwin)
|
|||
{
|
||||
wNETWMCheckInitialFrameState(wwin);
|
||||
}
|
||||
|
||||
static RContext *x11_create_rcontext(int screen_number, RContextAttributes *attribs)
|
||||
{
|
||||
return RCreateContext(dpy, screen_number, attribs);
|
||||
}
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Client operations (Phase 80) */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
@ -4260,6 +4265,7 @@ const WMBackend x11_backend = {
|
|||
.netwm_check_client_hint_change = x11_netwm_check_client_hint_change,
|
||||
.netwm_position_splash = x11_netwm_position_splash,
|
||||
.netwm_check_initial_frame_state = x11_netwm_check_initial_frame_state,
|
||||
.create_rcontext = x11_create_rcontext,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
51
src/screen.c
51
src/screen.c
|
|
@ -158,18 +158,49 @@ WScreen *wScreenInit(int screen_number)
|
|||
wm_backend->monitors_select_events(scr);
|
||||
wm_backend->screen_set_root_cursor(scr, WCUR_ROOT);
|
||||
|
||||
/* Pure Wayland path (no XWayland display): skip X11/wrlib context setup
|
||||
* and allocate workspace 0 directly. When XWayland is available (dpy is
|
||||
* set, Path 1), fall through to the full X11 init so WINGs, RContext,
|
||||
* GCs, and menus work correctly on the XWayland display. */
|
||||
if (wm_backend->is_wayland && scr->root_win == 0) {
|
||||
scr->w_depth = 24;
|
||||
scr->rcontext = NULL;
|
||||
/* Wayland path: WM UI is pure Wayland (pixman + wlr_scene).
|
||||
* XWayland exists only for X11 client apps, not for the WM itself. */
|
||||
if (wm_backend->is_wayland) {
|
||||
scr->w_depth = 32;
|
||||
scr->rcontext = RCreateContextWayland(scr->scr_width, scr->scr_height, NULL);
|
||||
|
||||
/* WINGs screen — pure Wayland, no X11. */
|
||||
scr->wmscreen = WMCreateScreenWithRContext(NULL, 0, NULL);
|
||||
scr->wmscreen = WMCreateScreenWithRContext(NULL, 0, scr->rcontext);
|
||||
|
||||
if (!scr->wmscreen) {
|
||||
wfatal(_("could not initialize WINGs widget set"));
|
||||
wfree(scr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
scr->black = WMBlackColor(scr->wmscreen);
|
||||
scr->white = WMWhiteColor(scr->wmscreen);
|
||||
scr->gray = WMGrayColor(scr->wmscreen);
|
||||
scr->darkGray = WMDarkGrayColor(scr->wmscreen);
|
||||
|
||||
scr->black_pixel = scr->black ? WMColorPixel(scr->black) : 0xFF000000;
|
||||
scr->white_pixel = scr->white ? WMColorPixel(scr->white) : 0xFFFFFFFF;
|
||||
scr->light_pixel = scr->gray ? WMColorPixel(scr->gray) : 0xFFAAAAAA;
|
||||
scr->dark_pixel = scr->darkGray ? WMColorPixel(scr->darkGray) : 0xFF555555;
|
||||
|
||||
wm_backend->screen_alloc_gcs(scr);
|
||||
wReadDefaults(scr, w_global.domain.wmaker->dictionary);
|
||||
|
||||
if (scr->frame_border_color)
|
||||
scr->frame_border_pixel = WMColorPixel(scr->frame_border_color);
|
||||
if (scr->frame_focused_border_color)
|
||||
scr->frame_focused_border_pixel = WMColorPixel(scr->frame_focused_border_color);
|
||||
if (scr->frame_selected_border_color)
|
||||
scr->frame_selected_border_pixel = WMColorPixel(scr->frame_selected_border_color);
|
||||
|
||||
wm_backend->screen_create_internals(scr);
|
||||
|
||||
scr->info_text_font = WMBoldSystemFontOfSize(scr->wmscreen, 12);
|
||||
|
||||
wm_backend->netwm_init(scr);
|
||||
wWorkspaceNew(scr);
|
||||
wm_backend->screen_create_pixmaps(scr);
|
||||
|
||||
goto screen_done;
|
||||
}
|
||||
|
||||
|
|
@ -190,7 +221,7 @@ WScreen *wScreenInit(int screen_number)
|
|||
rattr.visualid = getWVisualID(screen_number);
|
||||
}
|
||||
|
||||
scr->rcontext = RCreateContext(dpy, screen_number, &rattr);
|
||||
scr->rcontext = wm_backend->create_rcontext(screen_number, &rattr);
|
||||
|
||||
if (!scr->rcontext && RErrorCode == RERR_STDCMAPFAIL) {
|
||||
wwarning("%s", RMessageForError(RErrorCode));
|
||||
|
|
@ -198,7 +229,7 @@ WScreen *wScreenInit(int screen_number)
|
|||
rattr.flags &= ~RC_StandardColormap;
|
||||
rattr.standard_colormap_mode = RUseStdColormap;
|
||||
|
||||
scr->rcontext = RCreateContext(dpy, screen_number, &rattr);
|
||||
scr->rcontext = wm_backend->create_rcontext(screen_number, &rattr);
|
||||
}
|
||||
if (scr->rcontext == NULL) {
|
||||
wfatal(_("can't create Context on screen %d, %s"),
|
||||
|
|
|
|||
|
|
@ -716,3 +716,50 @@ static Bool bestContext(Display * dpy, int screen_number, RContext * context)
|
|||
else
|
||||
return True;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a minimal RContext for Wayland mode.
|
||||
* No X11 connection needed — just sets up 32-bit TrueColor parameters
|
||||
* so that RImage operations (load, scale, combine) work.
|
||||
* RConvertImage will not work (returns 0) since there's no X11 drawable.
|
||||
*/
|
||||
RContext *RCreateContextWayland(int width, int height,
|
||||
const RContextAttributes *attribs)
|
||||
{
|
||||
RContext *context;
|
||||
RContextAttributes *attr;
|
||||
|
||||
context = malloc(sizeof(RContext));
|
||||
if (!context) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
return NULL;
|
||||
}
|
||||
memset(context, 0, sizeof(RContext));
|
||||
|
||||
attr = malloc(sizeof(RContextAttributes));
|
||||
if (!attr) {
|
||||
free(context);
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
return NULL;
|
||||
}
|
||||
if (attribs)
|
||||
*attr = *attribs;
|
||||
else
|
||||
memset(attr, 0, sizeof(RContextAttributes));
|
||||
|
||||
context->attribs = attr;
|
||||
|
||||
/* 32-bit ARGB TrueColor — matches pixman ARGB32 */
|
||||
context->depth = 32;
|
||||
context->vclass = TrueColor;
|
||||
context->red_offset = 16;
|
||||
context->green_offset = 8;
|
||||
context->blue_offset = 0;
|
||||
context->black = 0xFF000000;
|
||||
context->white = 0xFFFFFFFF;
|
||||
|
||||
(void)width;
|
||||
(void)height;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -871,6 +871,12 @@ int RConvertImage(RContext * context, RImage * image, Pixmap * pixmap)
|
|||
assert(image != NULL);
|
||||
assert(pixmap != NULL);
|
||||
|
||||
/* Wayland mode: no X11 display, pixmaps are not used */
|
||||
if (!context->dpy) {
|
||||
*pixmap = (Pixmap)0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (context->vclass) {
|
||||
case TrueColor:
|
||||
ximg = image2TrueColor(context, image);
|
||||
|
|
@ -940,6 +946,12 @@ int RConvertImageMask(RContext * context, RImage * image, Pixmap * pixmap, Pixma
|
|||
assert(pixmap != NULL);
|
||||
assert(mask != NULL);
|
||||
|
||||
if (!context->dpy) {
|
||||
*pixmap = (Pixmap)0;
|
||||
*mask = (Pixmap)0;
|
||||
return True;
|
||||
}
|
||||
|
||||
if (!RConvertImage(context, image, pixmap))
|
||||
return False;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue