step 3: move screen internals from wl_backend.c to wl_screen.c (alloc_gcs, create_internals, monitors_query, 293 lines)
This commit is contained in:
parent
9178f8a903
commit
3b3ab96597
|
|
@ -1544,299 +1544,6 @@ handle_new_shortcuts_inhibitor(struct wl_listener *listener, void *data)
|
|||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Screen internals */
|
||||
|
||||
int wl_screen_select_input(WScreen *scr, long mask) { (void)scr; (void)mask; return 1; }
|
||||
void wl_screen_set_root_cursor(WScreen *scr, int cursor_id) { (void)scr; (void)cursor_id; }
|
||||
void wl_screen_set_icon_sizes(WScreen *scr, int min_size, int max_size) { (void)scr; (void)min_size; (void)max_size; }
|
||||
void wl_screen_setup_noticeboard(WScreen *scr) { (void)scr; }
|
||||
#if USE_XWAYLAND
|
||||
void
|
||||
wl_screen_alloc_gcs(WScreen *scr)
|
||||
{
|
||||
XGCValues gcv;
|
||||
int gcm;
|
||||
static const char stipple_data[] = { 0x02, 0x01 };
|
||||
|
||||
/* Pre-initialise menu text colors to black so that setMenuTextColor /
|
||||
* setMenuDisabledColor in wReadDefaults can safely compare them before
|
||||
* both have been set from the defaults DB. */
|
||||
scr->menu_title_color[0] = WMRetainColor(scr->white);
|
||||
scr->mtext_color = WMCreateRGBColor(scr->wmscreen, 0, 0, 0, True);
|
||||
scr->dtext_color = WMCreateRGBColor(scr->wmscreen, 0, 0, 0, True);
|
||||
|
||||
/* Create X11 GCs on the XWayland connection. wmaker's rendering code
|
||||
* (framewin, icon, menu) uses these regardless of the display backend.
|
||||
* Mirrors x11_screen_alloc_gcs exactly; without these, CopyArea and
|
||||
* XRender calls use GC/drawable 0 → BadDrawable → XWayland broken pipe. */
|
||||
if (!wl_state.x_display)
|
||||
return;
|
||||
|
||||
/* Mark the wrlib drawable as override_redirect so XWayland's XWM does not
|
||||
* manage it as a client window. XWM reads override_redirect from the
|
||||
* CreateNotify event (already gone), but any subsequent ConfigureNotify
|
||||
* updates the flag on the wlr_xwayland_surface it created. Combined with
|
||||
* the explicit window-ID filter in handle_xwayland_new_surface, this
|
||||
* prevents BadDrawable/RenderBadPicture cascade and the resulting broken
|
||||
* pipe from the nested Wayland backend. */
|
||||
#if USE_XWAYLAND
|
||||
if (scr->w_win) {
|
||||
wl_state.rcontext_xwin = (WNativeWindow)scr->w_win;
|
||||
XSetWindowAttributes or_attr;
|
||||
or_attr.override_redirect = True;
|
||||
XChangeWindowAttributes(wl_state.x_display, (WNativeWindow)scr->w_win, CWOverrideRedirect, &or_attr);
|
||||
XFlush(wl_state.x_display);
|
||||
}
|
||||
#endif
|
||||
|
||||
scr->stipple_bitmap = XCreateBitmapFromData(wl_state.x_display, (WNativeWindow)scr->w_win,
|
||||
stipple_data, 2, 2);
|
||||
|
||||
gcv.stipple = scr->stipple_bitmap;
|
||||
gcv.foreground = scr->white_pixel;
|
||||
gcv.fill_style = FillStippled;
|
||||
gcv.graphics_exposures = False;
|
||||
gcm = GCForeground | GCStipple | GCFillStyle | GCGraphicsExposures;
|
||||
scr->stipple_gc = XCreateGC(wl_state.x_display, (WNativeWindow)scr->w_win, gcm, &gcv);
|
||||
|
||||
gcv.function = GXcopy;
|
||||
gcv.foreground = scr->white_pixel;
|
||||
gcv.background = scr->black_pixel;
|
||||
gcv.line_width = 1;
|
||||
gcv.line_style = LineDoubleDash;
|
||||
gcv.fill_style = FillSolid;
|
||||
gcv.dash_offset = 0;
|
||||
gcv.dashes = 4;
|
||||
gcv.graphics_exposures = False;
|
||||
gcm = GCFunction | GCGraphicsExposures | GCForeground | GCBackground
|
||||
| GCLineWidth | GCLineStyle | GCFillStyle | GCDashOffset | GCDashList;
|
||||
scr->icon_select_gc = XCreateGC(wl_state.x_display, (WNativeWindow)scr->w_win, gcm, &gcv);
|
||||
|
||||
gcv.function = GXxor;
|
||||
gcv.plane_mask = AllPlanes;
|
||||
gcv.foreground = scr->white_pixel;
|
||||
if (gcv.foreground == 0)
|
||||
gcv.foreground = 1;
|
||||
gcv.line_width = DEF_FRAME_THICKNESS;
|
||||
gcv.subwindow_mode = IncludeInferiors;
|
||||
gcv.graphics_exposures = False;
|
||||
scr->frame_gc = XCreateGC(wl_state.x_display, (WNativeWindow)scr->root_win,
|
||||
GCForeground | GCGraphicsExposures | GCFunction
|
||||
| GCSubwindowMode | GCLineWidth | GCPlaneMask, &gcv);
|
||||
|
||||
gcv.foreground = scr->white_pixel;
|
||||
if (gcv.foreground == 0)
|
||||
gcv.foreground = 17;
|
||||
gcv.function = GXxor;
|
||||
gcv.subwindow_mode = IncludeInferiors;
|
||||
gcv.line_width = 1;
|
||||
gcv.cap_style = CapRound;
|
||||
gcv.graphics_exposures = False;
|
||||
gcm = GCForeground | GCFunction | GCSubwindowMode | GCLineWidth
|
||||
| GCCapStyle | GCGraphicsExposures;
|
||||
scr->line_gc = XCreateGC(wl_state.x_display, (WNativeWindow)scr->root_win, gcm, &gcv);
|
||||
scr->line_pixel = gcv.foreground;
|
||||
|
||||
gcv.foreground = scr->white_pixel;
|
||||
gcv.background = scr->black_pixel;
|
||||
gcv.graphics_exposures = False;
|
||||
scr->copy_gc = XCreateGC(wl_state.x_display, (WNativeWindow)scr->w_win,
|
||||
GCForeground | GCBackground | GCGraphicsExposures, &gcv);
|
||||
|
||||
gcv.graphics_exposures = False;
|
||||
scr->draw_gc = XCreateGC(wl_state.x_display, (WNativeWindow)scr->w_win, GCGraphicsExposures, &gcv);
|
||||
|
||||
scr->mono_gc = XCreateGC(wl_state.x_display, scr->stipple_bitmap, GCGraphicsExposures, &gcv);
|
||||
}
|
||||
#else
|
||||
void wl_screen_alloc_gcs(WScreen *scr) { (void)scr; }
|
||||
#endif
|
||||
|
||||
void
|
||||
wl_screen_create_internals(WScreen *scr)
|
||||
{
|
||||
wl_state.scr = scr;
|
||||
{
|
||||
FILE *fp = fopen("/tmp/wl_backend_trace.log", "a");
|
||||
if (fp) { fprintf(fp, "wl_screen_create_internals: scr=%p\n", (void*)scr); fclose(fp); }
|
||||
}
|
||||
#if USE_XWAYLAND
|
||||
/* Create off-screen InputOnly X window as focus sink */
|
||||
if (wl_state.x_display) {
|
||||
XSetWindowAttributes attribs;
|
||||
int vmask = CWEventMask | CWOverrideRedirect;
|
||||
attribs.event_mask = WM_EVMASK_KEY_PRESS | WM_EVMASK_FOCUS_CHANGE;
|
||||
attribs.override_redirect = True;
|
||||
WNativeWindow xwin = XCreateWindow(wl_state.x_display, DefaultRootWindow(wl_state.x_display),
|
||||
-10, -10, 4, 4, 0,
|
||||
0, InputOnly, CopyFromParent, vmask, &attribs);
|
||||
if (xwin) {
|
||||
XSelectInput(wl_state.x_display, xwin, WM_EVMASK_KEY_PRESS | WM_EVMASK_KEY_RELEASE);
|
||||
XMapWindow(wl_state.x_display, xwin);
|
||||
/* Do NOT call XSetInputFocus here: the window may not be viewable
|
||||
* yet in XWayland (map is async), triggering BadMatch that perturbs
|
||||
* XWayland state and causes a Wayland broken-pipe cascade.
|
||||
* wl_focus_set() will clear Wayland seat focus via
|
||||
* wlr_seat_keyboard_clear_focus when this window is the target. */
|
||||
wl_state.no_focus_xwin = xwin;
|
||||
scr->no_focus_win = (WNativeWindow)xwin;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
wPreferences.auto_focus = 1;
|
||||
if (wl_state.seat)
|
||||
wlr_seat_keyboard_clear_focus(wl_state.seat);
|
||||
|
||||
wSetModifierMasks(WM_MOD_MOD1, WM_MOD_MOD1, WM_MOD_MOD4, 0);
|
||||
|
||||
#if USE_XWAYLAND
|
||||
/* XWayland bridge: create X11 helper window for EWMH */
|
||||
if (wl_state.x_display) {
|
||||
XSetWindowAttributes iattr;
|
||||
iattr.override_redirect = True;
|
||||
WNativeWindow xwin = XCreateWindow(wl_state.x_display, DefaultRootWindow(wl_state.x_display),
|
||||
-2, -2, 1, 1, 0,
|
||||
0, InputOutput, CopyFromParent,
|
||||
CWOverrideRedirect, &iattr);
|
||||
if (xwin)
|
||||
scr->info_window = (WNativeWindow)xwin;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create dock_shadow: scene_buffer used as ghost overlay during icon drag */
|
||||
if (wl_state.scene) {
|
||||
int sz = wPreferences.icon_size;
|
||||
struct wl_frame_buf *dsfb = wmalloc(sizeof(*dsfb));
|
||||
memset(dsfb, 0, sizeof(*dsfb));
|
||||
dsfb->image = pixman_image_create_bits(PIXMAN_a8r8g8b8, sz, sz, NULL, sz * 4);
|
||||
if (dsfb->image) {
|
||||
wlr_buffer_init(&dsfb->base, &frame_buf_impl, sz, sz);
|
||||
dsfb->id = wl_state.next_synthetic_id++;
|
||||
dsfb->width = sz;
|
||||
dsfb->height = sz;
|
||||
struct wlr_scene_tree *ds_parent = wl_state.level_trees[WL_LAYER_OVERLAY]
|
||||
? wl_state.level_trees[WL_LAYER_OVERLAY] : &wl_state.scene->tree;
|
||||
dsfb->tree = wlr_scene_tree_create(ds_parent);
|
||||
if (dsfb->tree) {
|
||||
dsfb->scene_buf = wlr_scene_buffer_create(dsfb->tree, &dsfb->base);
|
||||
if (dsfb->scene_buf)
|
||||
wlr_scene_node_set_enabled(&dsfb->scene_buf->node, false);
|
||||
wlr_scene_node_set_enabled(&dsfb->tree->node, false);
|
||||
}
|
||||
wl_list_insert(&wl_state.frame_list, &dsfb->link);
|
||||
scr->dock_shadow = dsfb->id;
|
||||
} else {
|
||||
wfree(dsfb);
|
||||
}
|
||||
}
|
||||
|
||||
/* dock/clip now uses XWayland windows for rendering.
|
||||
* The WM's dock logic (dock.c) creates X11 windows on the XWayland
|
||||
* Display* and draws on them with Xlib — the compositor composites
|
||||
* them like any other XWayland surface. */
|
||||
/* wPreferences.flags.noclip = 1; */
|
||||
/* wPreferences.flags.nodock = 1; */
|
||||
|
||||
/* dock creation is deferred to wl_event_loop_run() (after the
|
||||
* startup pump thread stops). wm_dock_create() calls wlr_scene_buffer_create
|
||||
* which is not thread-safe — calling it here races with the pump thread's
|
||||
* frame-timer callback that calls wlr_scene_output_commit on the same scene.
|
||||
* The dock_scr pointer tells wl_event_loop_run() to create the dock once the
|
||||
* compositor's single-threaded event loop is running.
|
||||
* NOTE: native dock panel disabled — WM dock uses XWayland windows now. */
|
||||
/* wl_state.dock_pending_scr = scr; */
|
||||
|
||||
/* Wayland has no X11-style window border; force to 0 so policy code
|
||||
* does not offset client positions by a non-existent border. */
|
||||
scr->frame_border_width = 0;
|
||||
|
||||
/* Create workspace name badge overlay (initially 10x10, resized on use) */
|
||||
if (wl_state.scene) {
|
||||
struct wl_frame_buf *fb = wmalloc(sizeof(*fb));
|
||||
memset(fb, 0, sizeof(*fb));
|
||||
fb->image = pixman_image_create_bits(PIXMAN_a8r8g8b8, 10, 10, NULL, 0);
|
||||
if (fb->image) {
|
||||
wlr_buffer_init(&fb->base, &frame_buf_impl, 10, 10);
|
||||
fb->id = wl_state.next_synthetic_id++;
|
||||
fb->width = 10;
|
||||
fb->height = 10;
|
||||
struct wlr_scene_tree *parent = wl_state.level_trees[WL_LAYER_OVERLAY]
|
||||
? wl_state.level_trees[WL_LAYER_OVERLAY] : &wl_state.scene->tree;
|
||||
fb->tree = wlr_scene_tree_create(parent);
|
||||
if (fb->tree) {
|
||||
fb_attach_tree_listener(fb);
|
||||
fb->scene_buf = wlr_scene_buffer_create(fb->tree, &fb->base);
|
||||
if (fb->scene_buf) {
|
||||
fb_attach_scene_buf_listener(fb);
|
||||
wlr_scene_node_set_enabled(&fb->scene_buf->node, false);
|
||||
}
|
||||
wlr_scene_node_set_enabled(&fb->tree->node, false);
|
||||
}
|
||||
wl_list_insert(&wl_state.frame_list, &fb->link);
|
||||
W_RegisterBacking(fb->id, fb->image);
|
||||
scr->workspace_name = fb->id;
|
||||
} else {
|
||||
wfree(fb);
|
||||
}
|
||||
}
|
||||
}
|
||||
void wl_screen_create_pixmaps(WScreen *scr) { (void)scr; }
|
||||
void
|
||||
wl_screen_load_tech_font(WScreen *scr)
|
||||
{
|
||||
if (!scr) return;
|
||||
/* Wayland mode has no native font handle (overlay text is drawn via
|
||||
* the embedded 5×9 bitmap font in wl_overlay_draw_string). We just
|
||||
* publish the metric fields so moveres.c gets correct geometry. */
|
||||
scr->tech_draw_font = NULL;
|
||||
scr->tech_draw_font_ascent = OVL_GH - 2; /* 7 */
|
||||
scr->tech_draw_font_descent = 2;
|
||||
}
|
||||
void wl_screen_show_mini_screenshot(WScreen *scr, RImage *img) { (void)scr; (void)img; }
|
||||
RImage *wl_screen_capture_area(WScreen *scr) { (void)scr; return NULL; }
|
||||
RImage *wl_screen_capture_window(WScreen *scr, WWindow *wwin) { (void)scr; (void)wwin; return NULL; }
|
||||
void wl_refresh_desktop(WScreen *scr) { (void)scr; }
|
||||
|
||||
|
||||
void
|
||||
wl_monitors_query(WScreen *scr, WHeadGeometry **heads_out, int *count_out)
|
||||
{
|
||||
(void)scr;
|
||||
|
||||
if (!wl_state.output) {
|
||||
*heads_out = NULL;
|
||||
*count_out = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
WHeadGeometry *heads = wmalloc(sizeof(WHeadGeometry));
|
||||
|
||||
if (wl_state.output_layout) {
|
||||
struct wlr_box box = {0};
|
||||
wlr_output_layout_get_box(wl_state.output_layout, wl_state.output, &box);
|
||||
if (box.width > 0 || box.height > 0) {
|
||||
heads[0].x = box.x;
|
||||
heads[0].y = box.y;
|
||||
heads[0].width = box.width;
|
||||
heads[0].height = box.height;
|
||||
} else {
|
||||
heads[0].x = heads[0].y = 0;
|
||||
heads[0].width = (int)wl_state.output->width;
|
||||
heads[0].height = (int)wl_state.output->height;
|
||||
}
|
||||
} else {
|
||||
heads[0].x = heads[0].y = 0;
|
||||
heads[0].width = (int)wl_state.output->width;
|
||||
heads[0].height = (int)wl_state.output->height;
|
||||
}
|
||||
|
||||
*heads_out = heads;
|
||||
*count_out = 1;
|
||||
}
|
||||
|
||||
void wl_monitors_select_events(WScreen *scr) { (void)scr; }
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,22 @@
|
|||
#include "../../dialog.h"
|
||||
#include <WINGs/WINGsP.h>
|
||||
#include "wl_types.h"
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/types/wlr_buffer.h>
|
||||
#include <wlr/interfaces/wlr_buffer.h>
|
||||
#include <pixman.h>
|
||||
#include "../../framewin.h"
|
||||
#include <wlr/types/wlr_seat.h>
|
||||
#include "../../xmodifier.h"
|
||||
#include "../../WindowMaker.h"
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
|
||||
/* Externs from other wayland backend modules */
|
||||
extern const struct wlr_buffer_impl frame_buf_impl;
|
||||
extern void fb_attach_tree_listener(struct wl_frame_buf *fb);
|
||||
extern void fb_attach_scene_buf_listener(struct wl_frame_buf *fb);
|
||||
|
||||
void *W_RegisterBacking(unsigned long id, void *img);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Screen open/close */
|
||||
|
|
@ -242,3 +258,297 @@ int wl_get_color_for_colormap(unsigned long colormap,
|
|||
int wl_parse_color(WScreen *scr, const char *name, WMColorRGB *color_out)
|
||||
{ (void)scr; return wl_get_color_for_colormap(0, name, color_out); }
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Screen internals */
|
||||
|
||||
int wl_screen_select_input(WScreen *scr, long mask) { (void)scr; (void)mask; return 1; }
|
||||
void wl_screen_set_root_cursor(WScreen *scr, int cursor_id) { (void)scr; (void)cursor_id; }
|
||||
void wl_screen_set_icon_sizes(WScreen *scr, int min_size, int max_size) { (void)scr; (void)min_size; (void)max_size; }
|
||||
void wl_screen_setup_noticeboard(WScreen *scr) { (void)scr; }
|
||||
#if USE_XWAYLAND
|
||||
void
|
||||
wl_screen_alloc_gcs(WScreen *scr)
|
||||
{
|
||||
XGCValues gcv;
|
||||
int gcm;
|
||||
static const char stipple_data[] = { 0x02, 0x01 };
|
||||
|
||||
/* Pre-initialise menu text colors to black so that setMenuTextColor /
|
||||
* setMenuDisabledColor in wReadDefaults can safely compare them before
|
||||
* both have been set from the defaults DB. */
|
||||
scr->menu_title_color[0] = WMRetainColor(scr->white);
|
||||
scr->mtext_color = WMCreateRGBColor(scr->wmscreen, 0, 0, 0, True);
|
||||
scr->dtext_color = WMCreateRGBColor(scr->wmscreen, 0, 0, 0, True);
|
||||
|
||||
/* Create X11 GCs on the XWayland connection. wmaker's rendering code
|
||||
* (framewin, icon, menu) uses these regardless of the display backend.
|
||||
* Mirrors x11_screen_alloc_gcs exactly; without these, CopyArea and
|
||||
* XRender calls use GC/drawable 0 → BadDrawable → XWayland broken pipe. */
|
||||
if (!wl_state.x_display)
|
||||
return;
|
||||
|
||||
/* Mark the wrlib drawable as override_redirect so XWayland's XWM does not
|
||||
* manage it as a client window. XWM reads override_redirect from the
|
||||
* CreateNotify event (already gone), but any subsequent ConfigureNotify
|
||||
* updates the flag on the wlr_xwayland_surface it created. Combined with
|
||||
* the explicit window-ID filter in handle_xwayland_new_surface, this
|
||||
* prevents BadDrawable/RenderBadPicture cascade and the resulting broken
|
||||
* pipe from the nested Wayland backend. */
|
||||
#if USE_XWAYLAND
|
||||
if (scr->w_win) {
|
||||
wl_state.rcontext_xwin = (WNativeWindow)scr->w_win;
|
||||
XSetWindowAttributes or_attr;
|
||||
or_attr.override_redirect = True;
|
||||
XChangeWindowAttributes(wl_state.x_display, (WNativeWindow)scr->w_win, CWOverrideRedirect, &or_attr);
|
||||
XFlush(wl_state.x_display);
|
||||
}
|
||||
#endif
|
||||
|
||||
scr->stipple_bitmap = XCreateBitmapFromData(wl_state.x_display, (WNativeWindow)scr->w_win,
|
||||
stipple_data, 2, 2);
|
||||
|
||||
gcv.stipple = scr->stipple_bitmap;
|
||||
gcv.foreground = scr->white_pixel;
|
||||
gcv.fill_style = FillStippled;
|
||||
gcv.graphics_exposures = False;
|
||||
gcm = GCForeground | GCStipple | GCFillStyle | GCGraphicsExposures;
|
||||
scr->stipple_gc = XCreateGC(wl_state.x_display, (WNativeWindow)scr->w_win, gcm, &gcv);
|
||||
|
||||
gcv.function = GXcopy;
|
||||
gcv.foreground = scr->white_pixel;
|
||||
gcv.background = scr->black_pixel;
|
||||
gcv.line_width = 1;
|
||||
gcv.line_style = LineDoubleDash;
|
||||
gcv.fill_style = FillSolid;
|
||||
gcv.dash_offset = 0;
|
||||
gcv.dashes = 4;
|
||||
gcv.graphics_exposures = False;
|
||||
gcm = GCFunction | GCGraphicsExposures | GCForeground | GCBackground
|
||||
| GCLineWidth | GCLineStyle | GCFillStyle | GCDashOffset | GCDashList;
|
||||
scr->icon_select_gc = XCreateGC(wl_state.x_display, (WNativeWindow)scr->w_win, gcm, &gcv);
|
||||
|
||||
gcv.function = GXxor;
|
||||
gcv.plane_mask = AllPlanes;
|
||||
gcv.foreground = scr->white_pixel;
|
||||
if (gcv.foreground == 0)
|
||||
gcv.foreground = 1;
|
||||
gcv.line_width = DEF_FRAME_THICKNESS;
|
||||
gcv.subwindow_mode = IncludeInferiors;
|
||||
gcv.graphics_exposures = False;
|
||||
scr->frame_gc = XCreateGC(wl_state.x_display, (WNativeWindow)scr->root_win,
|
||||
GCForeground | GCGraphicsExposures | GCFunction
|
||||
| GCSubwindowMode | GCLineWidth | GCPlaneMask, &gcv);
|
||||
|
||||
gcv.foreground = scr->white_pixel;
|
||||
if (gcv.foreground == 0)
|
||||
gcv.foreground = 17;
|
||||
gcv.function = GXxor;
|
||||
gcv.subwindow_mode = IncludeInferiors;
|
||||
gcv.line_width = 1;
|
||||
gcv.cap_style = CapRound;
|
||||
gcv.graphics_exposures = False;
|
||||
gcm = GCForeground | GCFunction | GCSubwindowMode | GCLineWidth
|
||||
| GCCapStyle | GCGraphicsExposures;
|
||||
scr->line_gc = XCreateGC(wl_state.x_display, (WNativeWindow)scr->root_win, gcm, &gcv);
|
||||
scr->line_pixel = gcv.foreground;
|
||||
|
||||
gcv.foreground = scr->white_pixel;
|
||||
gcv.background = scr->black_pixel;
|
||||
gcv.graphics_exposures = False;
|
||||
scr->copy_gc = XCreateGC(wl_state.x_display, (WNativeWindow)scr->w_win,
|
||||
GCForeground | GCBackground | GCGraphicsExposures, &gcv);
|
||||
|
||||
gcv.graphics_exposures = False;
|
||||
scr->draw_gc = XCreateGC(wl_state.x_display, (WNativeWindow)scr->w_win, GCGraphicsExposures, &gcv);
|
||||
|
||||
scr->mono_gc = XCreateGC(wl_state.x_display, scr->stipple_bitmap, GCGraphicsExposures, &gcv);
|
||||
}
|
||||
#else
|
||||
void wl_screen_alloc_gcs(WScreen *scr) { (void)scr; }
|
||||
#endif
|
||||
|
||||
void
|
||||
wl_screen_create_internals(WScreen *scr)
|
||||
{
|
||||
wl_state.scr = scr;
|
||||
{
|
||||
FILE *fp = fopen("/tmp/wl_backend_trace.log", "a");
|
||||
if (fp) { fprintf(fp, "wl_screen_create_internals: scr=%p\n", (void*)scr); fclose(fp); }
|
||||
}
|
||||
#if USE_XWAYLAND
|
||||
/* Create off-screen InputOnly X window as focus sink */
|
||||
if (wl_state.x_display) {
|
||||
XSetWindowAttributes attribs;
|
||||
int vmask = CWEventMask | CWOverrideRedirect;
|
||||
attribs.event_mask = WM_EVMASK_KEY_PRESS | WM_EVMASK_FOCUS_CHANGE;
|
||||
attribs.override_redirect = True;
|
||||
WNativeWindow xwin = XCreateWindow(wl_state.x_display, DefaultRootWindow(wl_state.x_display),
|
||||
-10, -10, 4, 4, 0,
|
||||
0, InputOnly, CopyFromParent, vmask, &attribs);
|
||||
if (xwin) {
|
||||
XSelectInput(wl_state.x_display, xwin, WM_EVMASK_KEY_PRESS | WM_EVMASK_KEY_RELEASE);
|
||||
XMapWindow(wl_state.x_display, xwin);
|
||||
/* Do NOT call XSetInputFocus here: the window may not be viewable
|
||||
* yet in XWayland (map is async), triggering BadMatch that perturbs
|
||||
* XWayland state and causes a Wayland broken-pipe cascade.
|
||||
* wl_focus_set() will clear Wayland seat focus via
|
||||
* wlr_seat_keyboard_clear_focus when this window is the target. */
|
||||
wl_state.no_focus_xwin = xwin;
|
||||
scr->no_focus_win = (WNativeWindow)xwin;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
wPreferences.auto_focus = 1;
|
||||
if (wl_state.seat)
|
||||
wlr_seat_keyboard_clear_focus(wl_state.seat);
|
||||
|
||||
wSetModifierMasks(WM_MOD_MOD1, WM_MOD_MOD1, WM_MOD_MOD4, 0);
|
||||
|
||||
#if USE_XWAYLAND
|
||||
/* XWayland bridge: create X11 helper window for EWMH */
|
||||
if (wl_state.x_display) {
|
||||
XSetWindowAttributes iattr;
|
||||
iattr.override_redirect = True;
|
||||
WNativeWindow xwin = XCreateWindow(wl_state.x_display, DefaultRootWindow(wl_state.x_display),
|
||||
-2, -2, 1, 1, 0,
|
||||
0, InputOutput, CopyFromParent,
|
||||
CWOverrideRedirect, &iattr);
|
||||
if (xwin)
|
||||
scr->info_window = (WNativeWindow)xwin;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create dock_shadow: scene_buffer used as ghost overlay during icon drag */
|
||||
if (wl_state.scene) {
|
||||
int sz = wPreferences.icon_size;
|
||||
struct wl_frame_buf *dsfb = wmalloc(sizeof(*dsfb));
|
||||
memset(dsfb, 0, sizeof(*dsfb));
|
||||
dsfb->image = pixman_image_create_bits(PIXMAN_a8r8g8b8, sz, sz, NULL, sz * 4);
|
||||
if (dsfb->image) {
|
||||
wlr_buffer_init(&dsfb->base, &frame_buf_impl, sz, sz);
|
||||
dsfb->id = wl_state.next_synthetic_id++;
|
||||
dsfb->width = sz;
|
||||
dsfb->height = sz;
|
||||
struct wlr_scene_tree *ds_parent = wl_state.level_trees[WL_LAYER_OVERLAY]
|
||||
? wl_state.level_trees[WL_LAYER_OVERLAY] : &wl_state.scene->tree;
|
||||
dsfb->tree = wlr_scene_tree_create(ds_parent);
|
||||
if (dsfb->tree) {
|
||||
dsfb->scene_buf = wlr_scene_buffer_create(dsfb->tree, &dsfb->base);
|
||||
if (dsfb->scene_buf)
|
||||
wlr_scene_node_set_enabled(&dsfb->scene_buf->node, false);
|
||||
wlr_scene_node_set_enabled(&dsfb->tree->node, false);
|
||||
}
|
||||
wl_list_insert(&wl_state.frame_list, &dsfb->link);
|
||||
scr->dock_shadow = dsfb->id;
|
||||
} else {
|
||||
wfree(dsfb);
|
||||
}
|
||||
}
|
||||
|
||||
/* dock/clip now uses XWayland windows for rendering.
|
||||
* The WM's dock logic (dock.c) creates X11 windows on the XWayland
|
||||
* Display* and draws on them with Xlib — the compositor composites
|
||||
* them like any other XWayland surface. */
|
||||
/* wPreferences.flags.noclip = 1; */
|
||||
/* wPreferences.flags.nodock = 1; */
|
||||
|
||||
/* dock creation is deferred to wl_event_loop_run() (after the
|
||||
* startup pump thread stops). wm_dock_create() calls wlr_scene_buffer_create
|
||||
* which is not thread-safe — calling it here races with the pump thread's
|
||||
* frame-timer callback that calls wlr_scene_output_commit on the same scene.
|
||||
* The dock_scr pointer tells wl_event_loop_run() to create the dock once the
|
||||
* compositor's single-threaded event loop is running.
|
||||
* NOTE: native dock panel disabled — WM dock uses XWayland windows now. */
|
||||
/* wl_state.dock_pending_scr = scr; */
|
||||
|
||||
/* Wayland has no X11-style window border; force to 0 so policy code
|
||||
* does not offset client positions by a non-existent border. */
|
||||
scr->frame_border_width = 0;
|
||||
|
||||
/* Create workspace name badge overlay (initially 10x10, resized on use) */
|
||||
if (wl_state.scene) {
|
||||
struct wl_frame_buf *fb = wmalloc(sizeof(*fb));
|
||||
memset(fb, 0, sizeof(*fb));
|
||||
fb->image = pixman_image_create_bits(PIXMAN_a8r8g8b8, 10, 10, NULL, 0);
|
||||
if (fb->image) {
|
||||
wlr_buffer_init(&fb->base, &frame_buf_impl, 10, 10);
|
||||
fb->id = wl_state.next_synthetic_id++;
|
||||
fb->width = 10;
|
||||
fb->height = 10;
|
||||
struct wlr_scene_tree *parent = wl_state.level_trees[WL_LAYER_OVERLAY]
|
||||
? wl_state.level_trees[WL_LAYER_OVERLAY] : &wl_state.scene->tree;
|
||||
fb->tree = wlr_scene_tree_create(parent);
|
||||
if (fb->tree) {
|
||||
fb_attach_tree_listener(fb);
|
||||
fb->scene_buf = wlr_scene_buffer_create(fb->tree, &fb->base);
|
||||
if (fb->scene_buf) {
|
||||
fb_attach_scene_buf_listener(fb);
|
||||
wlr_scene_node_set_enabled(&fb->scene_buf->node, false);
|
||||
}
|
||||
wlr_scene_node_set_enabled(&fb->tree->node, false);
|
||||
}
|
||||
wl_list_insert(&wl_state.frame_list, &fb->link);
|
||||
W_RegisterBacking(fb->id, fb->image);
|
||||
scr->workspace_name = fb->id;
|
||||
} else {
|
||||
wfree(fb);
|
||||
}
|
||||
}
|
||||
}
|
||||
void wl_screen_create_pixmaps(WScreen *scr) { (void)scr; }
|
||||
void
|
||||
wl_screen_load_tech_font(WScreen *scr)
|
||||
{
|
||||
if (!scr) return;
|
||||
/* Wayland mode has no native font handle (overlay text is drawn via
|
||||
* the embedded 5×9 bitmap font in wl_overlay_draw_string). We just
|
||||
* publish the metric fields so moveres.c gets correct geometry. */
|
||||
scr->tech_draw_font = NULL;
|
||||
scr->tech_draw_font_ascent = OVL_GH - 2; /* 7 */
|
||||
scr->tech_draw_font_descent = 2;
|
||||
}
|
||||
void wl_screen_show_mini_screenshot(WScreen *scr, RImage *img) { (void)scr; (void)img; }
|
||||
RImage *wl_screen_capture_area(WScreen *scr) { (void)scr; return NULL; }
|
||||
RImage *wl_screen_capture_window(WScreen *scr, WWindow *wwin) { (void)scr; (void)wwin; return NULL; }
|
||||
void wl_refresh_desktop(WScreen *scr) { (void)scr; }
|
||||
|
||||
|
||||
void
|
||||
wl_monitors_query(WScreen *scr, WHeadGeometry **heads_out, int *count_out)
|
||||
{
|
||||
(void)scr;
|
||||
|
||||
if (!wl_state.output) {
|
||||
*heads_out = NULL;
|
||||
*count_out = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
WHeadGeometry *heads = wmalloc(sizeof(WHeadGeometry));
|
||||
|
||||
if (wl_state.output_layout) {
|
||||
struct wlr_box box = {0};
|
||||
wlr_output_layout_get_box(wl_state.output_layout, wl_state.output, &box);
|
||||
if (box.width > 0 || box.height > 0) {
|
||||
heads[0].x = box.x;
|
||||
heads[0].y = box.y;
|
||||
heads[0].width = box.width;
|
||||
heads[0].height = box.height;
|
||||
} else {
|
||||
heads[0].x = heads[0].y = 0;
|
||||
heads[0].width = (int)wl_state.output->width;
|
||||
heads[0].height = (int)wl_state.output->height;
|
||||
}
|
||||
} else {
|
||||
heads[0].x = heads[0].y = 0;
|
||||
heads[0].width = (int)wl_state.output->width;
|
||||
heads[0].height = (int)wl_state.output->height;
|
||||
}
|
||||
|
||||
*heads_out = heads;
|
||||
*count_out = 1;
|
||||
}
|
||||
|
||||
void wl_monitors_select_events(WScreen *scr) { (void)scr; }
|
||||
|
|
|
|||
Loading…
Reference in New Issue