#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "../../screen.h" #include "../../shutdown.h" #include "../../dialog.h" #include #include "wl_types.h" /* ------------------------------------------------------------------ */ /* Screen open/close */ void wl_screen_open(WScreen *scr) { /* Set geometry from the headless output created in display_open(). */ scr->scr_width = wl_state.output ? (int)wl_state.output->width : 1920; scr->scr_height = wl_state.output ? (int)wl_state.output->height : 1080; scr->depth = 24; scr->root_win = (WNativeWindow)0x0FFFFFFF; /* synthetic root window ID */ scr->colormap = 0; /* Wayland has no X11-style window border; the frame_buf renders the * full decoration. Set border width to 0 so policy code does not * offset the client position by a non-existent border. */ scr->frame_border_width = 0; /* XWayland bridge: fill in real X11 screen values so RCreateContext * and WINGs can use the display connection for drawing and fonts. */ if (wl_state.x_display) { int snum = DefaultScreen(wl_state.x_display); scr->root_win = DefaultRootWindow(wl_state.x_display); scr->depth = DefaultDepth(wl_state.x_display, snum); scr->colormap = DefaultColormap(wl_state.x_display, snum); } } void wl_screen_close(WScreen *scr) { (void)scr; } int wl_screen_init_display(WScreen *scr, int screen_number) { (void)screen_number; scr->w_depth = 32; scr->rcontext = RCreateContextWayland(scr->scr_width, scr->scr_height, NULL); /* WINGs widget backends are selected via W_SetNextScreenKind — the * compositor uses the Wayland-mode set even though wmaker itself is * the compositor (rendering goes through pixman → wlroots scenes). */ W_SetNextScreenKind(WM_SCREEN_KIND_WAYLAND); scr->wmscreen = WMCreateScreenWithRContext(NULL, 0, scr->rcontext); if (!scr->wmscreen) { wfatal(_("could not initialize WINGs widget set")); return 0; } 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; return 1; } int wl_show_crash_dialog(int sig) { /* Wayland: showing a UI from a crashed compositor's child process is * not possible (the child would need to connect to the dead parent * for its compositor). Default to auto-restart, which is the most * useful behavior for a daily-driver compositor — the user's session * recovers on its own. The crash signal is logged separately by * the monitor parent. */ (void)sig; return WMRestart; } int wl_get_color_for_colormap(unsigned long colormap, const char *color_name, WMColorRGB *color) { 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}, {"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; } } /* grayNN / greyNN (0-100) */ if ((strncasecmp(color_name, "gray", 4) == 0 || strncasecmp(color_name, "grey", 4) == 0) && color_name[4] >= '0' && color_name[4] <= '9') { int pct = atoi(color_name + 4); if (pct >= 0 && pct <= 100) { unsigned int v = (pct * 255 + 50) / 100; color->red = color->green = color->blue = v << 8 | v; color->pixel = (0xFF << 24) | (v << 16) | (v << 8) | v; return 1; } } /* Look up in X11 rgb.txt database */ { const char *rgb_paths[] = { "/usr/share/X11/rgb.txt", "/usr/lib/X11/rgb.txt", "/etc/X11/rgb.txt", NULL }; FILE *f = NULL; for (int i = 0; rgb_paths[i] && !f; i++) f = fopen(rgb_paths[i], "r"); if (f) { char line[256]; while (fgets(line, sizeof(line), f)) { unsigned int rv, gv, bv; char name[128]; if (line[0] == '!' || line[0] == '#') continue; if (sscanf(line, "%u %u %u %127[^\n]", &rv, &gv, &bv, name) == 4) { /* Trim leading whitespace/tabs from name */ char *n = name; while (*n == ' ' || *n == '\t') n++; if (strcasecmp(n, color_name) == 0) { color->red = rv << 8 | rv; color->green = gv << 8 | gv; color->blue = bv << 8 | bv; color->pixel = (0xFF << 24) | (rv << 16) | (gv << 8) | bv; fclose(f); return 1; } } } fclose(f); } } wwarning(_("could not parse color \"%s\" (Wayland)"), color_name); return 0; } int wl_parse_color(WScreen *scr, const char *name, WMColorRGB *color_out) { (void)scr; return wl_get_color_for_colormap(0, name, color_out); }