extract context from wl_backend

This commit is contained in:
Window Maker 2026-05-31 12:34:04 +02:00
parent 5173cbbdd5
commit 758623269b
4 changed files with 446 additions and 418 deletions

View File

@ -157,7 +157,8 @@ endif
if USE_WAYLAND_BACKEND
wmaker_SOURCES += \
backend/wayland/wl_backend.h \
backend/wayland/wl_backend.c
backend/wayland/wl_backend.c \
backend/wayland/wl_context.c
endif
if USE_NESTED_FUNC

View File

@ -231,377 +231,11 @@ void W_UnregisterBacking(unsigned long id);
/* Forward declarations */
/* ------------------------------------------------------------------ */
struct wl_toplevel_view; /* defined below */
#include "wl_types.h"
static void wm_dock_app_add(struct wl_toplevel_view *v);
static void wm_dock_app_remove(WNativeWindow id);
/* ------------------------------------------------------------------ */
/* Phase 38: per-toplevel view and context store */
/* ------------------------------------------------------------------ */
/*
* wl_toplevel_view -- one entry per XDG toplevel managed by the compositor.
* Holds the wlroots surface pointer, three lifecycle listeners, and a
* synthetic Window ID used as the policy-layer window handle.
*/
struct wl_toplevel_view {
struct wlr_xdg_surface *xdg_surface;
struct wl_listener map_listener;
struct wl_listener unmap_listener;
struct wl_listener destroy_listener;
struct wl_listener title_listener; /* Phase 46: xdg_toplevel set_title */
struct wl_listener request_move_listener; /* Phase 15 */
struct wl_listener request_resize_listener; /* Phase 15 */
struct wl_listener request_maximize_listener; /* Phase 16 */
struct wl_listener request_fullscreen_listener;/* Phase 16 */
struct wl_listener request_minimize_listener; /* Phase 16 */
struct wl_listener set_app_id_listener; /* Phase 16 */
struct wl_listener commit_listener; /* initial configure */
struct wl_listener surface_commit_listener; /* permanent commit listener */
/* Phase 17: XWayland — set for X11 windows, NULL for XDG toplevels. */
struct wlr_xwayland_surface *xw_surface;
/* Path 1: geometry listener — keeps scene node in sync when X11 window moves. */
struct wl_listener xw_geometry_listener;
struct wl_listener xw_surface_map_listener; /* fires when wlr_surface maps */
/* Phase 18: scene graph tree for this surface (NULL if scene unavailable). */
struct wlr_scene_tree *scene_node;
/* Listener fires when scene_node is destroyed (e.g. when a parent
* tree is destroyed by wl_frame_destroy as part of unmanage).
* Without it, view->scene_node becomes a dangling pointer and the
* later handle_toplevel_destroy crashes calling wlr_scene_node_destroy
* a second time. */
struct wl_listener scene_destroy_listener;
WNativeWindow id; /* synthetic handle, >= 0x10000000 */
WNativeWindow frame_id; /* frame_buf that owns this view (0 = none) */
int frame_rel_x, frame_rel_y; /* offset within frame */
int x, y; /* Phase 55: WM-assigned position */
/* wmaker-popup-v1: client-driven popup position (only valid if popup != NULL) */
struct wl_resource *popup; /* wmaker_popup_v1 resource or NULL */
int popup_x, popup_y;
struct wlr_xdg_toplevel *popup_parent; /* parent toplevel or NULL */
long *wm_state; /* Phase 56: saved WM state or NULL */
int wm_state_n; /* Phase 56: element count */
char **wm_command; /* Phase 57: WM_COMMAND argv or NULL */
int wm_command_n; /* Phase 57: argument count */
/* Phase 35: foreign toplevel handle — exposes this window to taskbars. */
struct wlr_foreign_toplevel_handle_v1 *ft_handle;
struct wl_list link; /* wl_state.toplevel_list */
};
/*
* wl_or_view — tracks an override_redirect XWayland surface (WM frames,
* dock icons, menus, tooltips). These are not "managed" by the WM in the
* ICCCM sense but must be composited by the scene graph.
*/
struct wl_or_view {
struct wlr_xwayland_surface *xw_surface;
struct wlr_scene_tree *scene_node;
struct wl_listener map_listener;
struct wl_listener unmap_listener;
struct wl_listener destroy_listener;
struct wl_listener set_geometry_listener;
struct wl_list link; /* wl_state.or_list */
};
/*
* wl_frame_buf — a pixman-backed scene buffer for WM frame windows.
* Each frame (titlebar + buttons + resizebar) is rendered into a single
* ARGB pixman image and displayed via a wlr_scene_buffer node.
*/
struct wl_frame_buf {
struct wlr_buffer base; /* wlr_buffer (must be first) */
pixman_image_t *image; /* ARGB32 pixel data */
struct wlr_scene_buffer *scene_buf; /* scene graph node */
struct wlr_scene_tree *tree; /* grouping tree (top-level frames only) */
/* Destroy listeners on scene_buf and tree so they get NULL'd when
* wlroots auto-destroys them (e.g. via cascade from parent tree
* destruction during wl_frame_destroy). Without these, code that
* later tries to wlr_scene_node_destroy them again segfaults inside
* wl_list_remove on already-zeroed list links. */
struct wl_listener scene_buf_destroy;
struct wl_listener tree_destroy;
WNativeWindow id; /* synthetic ID (>= 0x10000000) */
WNativeWindow parent_id; /* parent frame_buf ID (0 = root) */
int x, y; /* position in output coords */
int rel_x, rel_y; /* position relative to parent */
int width, height;
pixman_image_t *bg_pixmap; /* background pixmap for window_clear */
struct wl_list link; /* wl_state.frame_list */
};
/*
* Phase 36: wl_layer_view — one entry per mapped zwlr_layer_shell_v1 surface.
* Tracks the wlroots layer surface, its scene node, and lifecycle listeners.
*/
struct wl_layer_view {
struct wlr_layer_surface_v1 *layer_surface;
struct wlr_scene_tree *scene_node;
struct wl_listener map_listener;
struct wl_listener unmap_listener;
struct wl_listener destroy_listener;
struct wl_list link; /* wl_state.layer_list */
};
/*
* Context store: three per-key linked lists keyed by WNativeWindow.
* Backed by a flat list of (win, data) pairs — fine for the small
* number of windows a typical user has open.
*/
struct wl_ctx_entry {
WNativeWindow win;
void *data;
struct wl_list link;
};
/* ------------------------------------------------------------------ */
/* Global compositor state */
/* ------------------------------------------------------------------ */
struct wl_compositor_state {
struct wl_display *display;
struct wlr_backend *backend;
struct wlr_renderer *renderer;
struct wlr_output *output; /* headless output (screen 0) */
struct wlr_output_layout *output_layout; /* Phase 34 */
/* Phase 35: core Wayland protocol globals */
struct wlr_compositor *compositor;
struct wlr_seat *seat;
struct wlr_data_device_manager *data_device_mgr;
struct wlr_xdg_shell *xdg_shell;
/* wmaker-popup-v1 protocol global — client-driven popup positioning */
struct wl_global *wmaker_popup_manager;
/* Phase 64: XDG decoration manager — tell clients to use CSD */
struct wlr_xdg_decoration_manager_v1 *decoration_manager;
struct wl_listener decoration_new_listener;
/* Phase 36: XDG toplevel tracking */
struct wl_listener xdg_new_surface_listener;
int managed_surface_count; /* surfaces seen */
/* Phase 37: periodic timer that drives client frame callbacks */
struct wl_event_source *frame_timer;
/* Phase 38: per-toplevel view list and context store */
struct wl_list toplevel_list; /* wl_toplevel_view.link */
struct wl_list or_list; /* wl_or_view.link */
struct wl_list frame_list; /* wl_frame_buf.link */
struct wl_list layer_list; /* wl_layer_view.link */
struct wl_list ctx_lists[3]; /* one per WContextKey */
unsigned long next_synthetic_id; /* >= 0x10000000 */
/* Phase 43: first real keyboard device (set by handle_backend_new_input) */
struct wlr_input_device *keyboard_dev;
struct xkb_keymap *xkb_keymap; /* default keymap for keysym lookup */
struct wl_listener keyboard_key_listener; /* Phase 78 */
struct wl_listener keyboard_modifiers_listener; /* Phase 78 */
/* Phase 53: first real pointer device (set by handle_backend_new_input) */
struct wlr_input_device *pointer_dev;
/* Phase 54: virtual pointer position (screen coordinates) */
int pointer_x, pointer_y;
/* Phase 14: pointer event listeners wired to pointer_dev->pointer */
struct wl_listener pointer_motion_listener;
struct wl_listener pointer_motion_abs_listener;
struct wl_listener pointer_button_listener;
struct wl_listener pointer_frame_listener;
/* Phase 17: XWayland server for X11 client support */
struct wlr_xwayland *xwayland;
struct wl_listener xwayland_new_surface_listener;
struct wl_listener xwayland_ready_listener;
struct wl_listener xwayland_server_destroy_listener;
bool xwayland_ready; /* set by handle_xwayland_ready */
Display *x_display; /* WM's Xlib connection to own XWayland */
struct wl_event_source *x11_event_source; /* wl_event_loop fd watcher for x_display */
pthread_t startup_pump_thread; /* pumps Wayland event loop during StartUp() */
volatile int startup_pump_running; /* 1 while pump thread is active */
volatile int terminate; /* set to exit main loop */
/* Phase 20: real input devices from nested backend + their listeners */
struct wlr_input_device *real_keyboard_dev;
struct wlr_input_device *real_pointer_dev;
struct wl_listener backend_new_input_listener;
struct wl_listener real_keyboard_key_listener;
struct wl_listener real_keyboard_modifiers_listener;
struct wl_listener real_keyboard_destroy_listener;
struct wl_listener real_pointer_motion_abs_listener;
struct wl_listener real_pointer_button_listener;
struct wl_listener real_pointer_frame_listener;
/* Phase 18: nested Wayland + wlr_scene */
int is_nested; /* 1 if using wlr_wl_backend */
struct wlr_backend *headless_inner; /* headless backend (always) */
struct wlr_backend *wl_backend_inner; /* wl backend (nested only) */
struct wlr_session *session; /* DRM session (standalone only) */
struct wlr_allocator *allocator;
struct wlr_scene *scene;
struct wlr_scene_output *scene_output;
struct wl_listener backend_new_output_listener;
struct wl_listener output_frame_listener;
char socket_name[64]; /* Phase 34: e.g. "wayland-0" */
int started; /* non-zero after successful display_open */
/* Self-pipe for async-signal-safe shutdown: signal handler writes to [1],
* event loop reads [0] and calls wl_display_terminate(). */
int shutdown_pipe[2];
struct wl_event_source *shutdown_source;
/* signalfd-based signal handling: primary mechanism for catching
* SIGTERM/SIGINT/SIGHUP from within the event loop (avoids async-signal-
* safety issues with the traditional signal handler path). */
int sigfd;
struct wl_event_source *sigfd_source;
/* Phase 22: interactive move/resize grab state.
* grab_type: 0=none, 1=move, 2=resize, 3=WM policy grab.
* Type 3 is used by wl_pointer_grab for WM-internal drags (dock icons,
* app icons, menus). It suppresses wl_update_pointer_focus (so client
* surfaces don't steal pointer events) but does NOT intercept motion —
* WME_MOTION events flow normally to the WMMaskEvent loop.
* grab_view: the toplevel being moved/resized (NULL when grab_type==0 or 3).
* grab_start_ptr_{x,y}: pointer position when grab started.
* grab_start_win_{x,y,w,h}: window geometry when grab started.
* grab_resize_edges: WL_SHELL_SURFACE_RESIZE_* bitmask (resize only). */
int grab_type;
struct wl_toplevel_view *grab_view;
int grab_start_ptr_x, grab_start_ptr_y;
int grab_start_win_x, grab_start_win_y;
int grab_start_win_w, grab_start_win_h;
uint32_t grab_resize_edges;
/* Phase 23: hardware cursor and xcursor theme. */
struct wlr_cursor *cursor;
struct wlr_xcursor_manager *xcursor_mgr;
/* Phase 24: seat cursor-surface request listener. */
struct wl_listener seat_request_cursor_listener;
/* Phase 25: clipboard — seat selection request listener. */
struct wl_listener seat_request_set_selection_listener;
/* Phase 25b: drag-and-drop — seat request_start_drag listener. */
struct wl_listener seat_request_start_drag_listener;
/* Phase 26: primary selection (middle-click paste). */
struct wlr_primary_selection_v1_device_manager *primary_selection_mgr;
struct wl_listener seat_request_primary_selection_listener;
/* Phase 27: xdg-output manager for logical output geometry. */
struct wlr_xdg_output_manager_v1 *xdg_output_mgr;
/* Phase 28: idle-inhibit manager for video players / fullscreen apps. */
struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr;
struct wl_listener idle_new_inhibitor_listener;
/* Phase 29: wp_viewporter for hardware video scaling / subsurface damage. */
struct wlr_viewporter *viewporter;
/* Phase 30: relative pointer + pointer constraints for games. */
struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr;
struct wlr_pointer_constraints_v1 *pointer_constraints;
struct wl_listener new_constraint_listener;
/* Phase 31: keyboard shortcuts inhibitor for fullscreen / remote desktop. */
struct wlr_keyboard_shortcuts_inhibit_manager_v1 *shortcuts_inhibit_mgr;
struct wl_listener new_shortcuts_inhibitor_listener;
/* Phase 32: GPU zero-copy buffer import, screencopy, GPU framebuffer export. */
struct wlr_linux_dmabuf_v1 *linux_dmabuf;
struct wlr_screencopy_manager_v1 *screencopy_mgr;
struct wlr_export_dmabuf_manager_v1 *export_dmabuf_mgr;
/* Phase 33: output management (randr), output power (DPMS), gamma control, presentation time. */
struct wlr_output_manager_v1 *output_mgr;
struct wl_listener output_mgr_apply_listener;
struct wl_listener output_mgr_test_listener;
struct wlr_output_power_manager_v1 *output_power_mgr;
struct wl_listener output_power_set_mode_listener;
struct wlr_gamma_control_manager_v1 *gamma_control_mgr;
struct wlr_presentation *presentation;
/* Phase 34: text input (IME client side), input method (IME server side), virtual keyboard. */
struct wlr_text_input_manager_v3 *text_input_mgr;
struct wl_listener text_input_new_listener;
struct wlr_input_method_manager_v2 *input_method_mgr;
struct wl_listener input_method_new_listener;
struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr;
struct wl_listener virtual_keyboard_new_listener;
/* Phase 35: foreign toplevel management + xdg_activation (focus tokens). */
struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_mgr;
struct wlr_xdg_activation_v1 *xdg_activation;
struct wl_listener xdg_activation_request_listener;
/* Phase 36: layer shell — panels, docks, wallpapers, overlays. */
struct wlr_layer_shell_v1 *layer_shell;
struct wl_listener layer_shell_new_surface_listener;
/* Phase 37: clipboard manager, input inhibitor, virtual pointer, idle, xdg-foreign. */
struct wlr_data_control_manager_v1 *data_control_mgr;
struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr;
struct wl_listener virtual_pointer_new_listener;
struct wlr_xdg_foreign_registry *xdg_foreign_registry;
struct wlr_xdg_foreign_v2 *xdg_foreign_v2;
/* Phase 29 axis listeners (headless pointer + real nested pointer). */
struct wl_listener pointer_axis_listener;
struct wl_listener real_pointer_axis_listener;
struct wl_listener real_pointer_destroy_listener;
/* Phase 30: WM dock panel (native Wayland rendering via wm_shm_surface). */
struct wm_shm_surface *dock_surface; /* NULL until screen_create_internals */
int dock_width; /* pixels reserved on right edge */
int dock_icon_sz; /* icon_sz saved by wm_dock_create */
int dock_n_slots; /* slot count saved by wm_dock_create */
/* Phase 30+: managed app list for dock icon rendering */
#define WM_DOCK_MAX_APPS 32
struct {
WNativeWindow id;
uint32_t *icon_argb; /* heap ARGB8888, or NULL */
int icon_w, icon_h;
} dock_apps[WM_DOCK_MAX_APPS];
int dock_app_count;
/* Stacking level trees — one wlr_scene_tree per layer, ordered
* bottom-to-top (index 0 rendered first = furthest back).
*
* Every scene node that participates in the compositor output is
* assigned to exactly one bucket so that creation order within the
* root tree never matters and there are no Z-order surprises.
*
* Named constants (WL_LAYER_*) map to bucket indices:
*
* 0 WL_LAYER_BACKGROUND background rect / wallpaper
* 1 WL_LAYER_DESKTOP WMDesktopLevel (level < -1)
* 2 WL_LAYER_SUNKEN WMSunkenLevel (level == -1)
* 3 WL_LAYER_NORMAL WMNormalLevel (0 <= level < 3)
* 4 WL_LAYER_FLOATING WMFloatingLevel (3 <= level < 20)
* 5 WL_LAYER_MENU WMMainMenuWindowLevel (20), OR-redirect
* 6 WL_LAYER_DOCK WMStatusWindowLevel / WMDockWindowLevel (21-49)
* also the dock panel wm_shm_surface
* 7 WL_LAYER_FULLSCREEN WMFullscreenLevel (50-99)
* 8 WL_LAYER_OVERLAY WMModalPanel / WMPopUp (>=100)
* also the XOR animation overlay surface
*/
#define WL_LAYER_BACKGROUND 0
#define WL_LAYER_DESKTOP 1
#define WL_LAYER_SUNKEN 2
#define WL_LAYER_NORMAL 3
#define WL_LAYER_FLOATING 4
#define WL_LAYER_MENU 5
#define WL_LAYER_DOCK 6
#define WL_LAYER_FULLSCREEN 7
#define WL_LAYER_OVERLAY 8
#define WL_NUM_LEVEL_BUCKETS 9
struct wlr_scene_tree *level_trees[WL_NUM_LEVEL_BUCKETS];
struct wlr_scene_rect *bg_rect; /* default solid background */
struct wlr_scene_buffer *bg_image; /* wallpaper image (if set) */
struct wlr_buffer *bg_wlr_buf; /* backing buffer for bg_image */
/* Phase 81: full-screen overlay surface for XOR animation drawing */
struct wm_shm_surface *overlay_surf; /* NULL until first draw */
/* Focus sink: small off-screen InputOnly X window that receives focus
* when no application window is focused. Mirrors what x11_backend does
* for no_focus_win so that XSetInputFocus calls on this window succeed. */
WNativeWindow no_focus_xwin; /* 0 until screen_create_internals */
/* wrlib RContext drawable — an ordinary InputOutput window that XWM must
* not manage (no WM_CLASS, no backing wl_surface). Stored here so
* handle_xwayland_new_surface can filter it before allocating a view. */
WNativeWindow rcontext_xwin; /* 0 until screen_alloc_gcs */
/* Deferred dock creation: set in screen_create_internals, consumed in
* wl_event_loop_run() after the startup pump thread stops (to avoid racing
* with the pump thread's frame-timer callback on the scene graph). */
WScreen *dock_pending_scr;
/* Button icon RImages (parsed from XPM on first use) */
RImage *btn_close_img;
RImage *btn_iconify_img;
RImage *btn_kill_img;
/* Tracks the frame_buf the pointer was last over (after button resolution),
* so motion handlers can emit synthetic WME_LEAVE/WME_ENTER events when
* the pointer crosses between WM frame sub-windows (titlebar, resizebar,
* buttons). buttonMouseDown's inner press-track loop depends on these. */
WNativeWindow last_hovered_id;
/* Focus guard: when true, the next focus-follows-pointer event is suppressed.
* Set by switchpanel_send_enter (called twice in wSwitchPanelDestroy) to prevent
* spurious focus changes when the Alt-Tab overlay is destroyed and the pointer
* re-enters the root window or a client surface underneath. */
bool ignore_focus_ffp;
/* Keyboard grab: when true, key events are queued for WMMaskEvent but not
* forwarded to Wayland clients (used by Alt-Tab cycling). */
bool keyboard_grabbed;
};
static struct wl_compositor_state wl_state;
struct wl_compositor_state wl_state;
/* Forward declarations for helpers used before their definition. */
static int level_to_bucket(int level);
@ -5058,55 +4692,6 @@ wl_frame_paint(struct WFrameWindow *fwin)
return 1;
}
/* ------------------------------------------------------------------ */
/* Context (window → object lookup table) — Phase 38 */
/* ------------------------------------------------------------------ */
static void
wl_context_save(WNativeWindow win, WContextKey key, void *data)
{
struct wl_list *list = &wl_state.ctx_lists[(int)key];
struct wl_ctx_entry *e;
/* update existing entry if present */
wl_list_for_each(e, list, link) {
if (e->win == win) { e->data = data; return; }
}
/* new entry */
e = wmalloc(sizeof(*e));
e->win = win;
e->data = data;
wl_list_insert(list, &e->link);
}
static void *
wl_context_find(WNativeWindow win, WContextKey key)
{
struct wl_list *list = &wl_state.ctx_lists[(int)key];
struct wl_ctx_entry *e;
wl_list_for_each(e, list, link) {
if (e->win == win) return e->data;
}
return NULL;
}
static int
wl_context_delete(WNativeWindow win, WContextKey key)
{
struct wl_list *list = &wl_state.ctx_lists[(int)key];
struct wl_ctx_entry *e, *tmp;
wl_list_for_each_safe(e, tmp, list, link) {
if (e->win == win) {
wl_list_remove(&e->link);
wfree(e);
return 1;
}
}
return 0; /* not found */
}
/* ------------------------------------------------------------------ */
/* Focus */
/* ------------------------------------------------------------------ */

View File

@ -0,0 +1,60 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <stdlib.h>
#include <wayland-server-core.h>
#include "wl_types.h"
/* ------------------------------------------------------------------ */
/* Context (window → object lookup table) — Phase 38 */
/* ------------------------------------------------------------------ */
void
wl_context_save(WNativeWindow win, WContextKey key, void *data)
{
struct wl_list *list = &wl_state.ctx_lists[(int)key];
struct wl_ctx_entry *e;
/* update existing entry if present */
wl_list_for_each(e, list, link) {
if (e->win == win) { e->data = data; return; }
}
/* new entry */
e = wmalloc(sizeof(*e));
e->win = win;
e->data = data;
wl_list_insert(list, &e->link);
}
void *
wl_context_find(WNativeWindow win, WContextKey key)
{
struct wl_list *list = &wl_state.ctx_lists[(int)key];
struct wl_ctx_entry *e;
wl_list_for_each(e, list, link) {
if (e->win == win) return e->data;
}
return NULL;
}
int
wl_context_delete(WNativeWindow win, WContextKey key)
{
struct wl_list *list = &wl_state.ctx_lists[(int)key];
struct wl_ctx_entry *e, *tmp;
wl_list_for_each_safe(e, tmp, list, link) {
if (e->win == win) {
wl_list_remove(&e->link);
wfree(e);
return 1;
}
}
return 0; /* not found */
}

View File

@ -0,0 +1,382 @@
#ifndef WL_TYPES_H
#define WL_TYPES_H
/* wl_types.h -- shared structs and global state for the Wayland backend */
#include <pixman.h>
#include <wlr/types/wlr_buffer.h> /* Phase 29+: WM-owned SHM surface buffers */
#include "wl_backend.h"
/* ------------------------------------------------------------------ */
/* Phase 38: per-toplevel view and context store */
/* ------------------------------------------------------------------ */
/*
* wl_toplevel_view -- one entry per XDG toplevel managed by the compositor.
* Holds the wlroots surface pointer, three lifecycle listeners, and a
* synthetic Window ID used as the policy-layer window handle.
*/
struct wl_toplevel_view {
struct wlr_xdg_surface *xdg_surface;
struct wl_listener map_listener;
struct wl_listener unmap_listener;
struct wl_listener destroy_listener;
struct wl_listener title_listener; /* Phase 46: xdg_toplevel set_title */
struct wl_listener request_move_listener; /* Phase 15 */
struct wl_listener request_resize_listener; /* Phase 15 */
struct wl_listener request_maximize_listener; /* Phase 16 */
struct wl_listener request_fullscreen_listener;/* Phase 16 */
struct wl_listener request_minimize_listener; /* Phase 16 */
struct wl_listener set_app_id_listener; /* Phase 16 */
struct wl_listener commit_listener; /* initial configure */
struct wl_listener surface_commit_listener; /* permanent commit listener */
/* Phase 17: XWayland — set for X11 windows, NULL for XDG toplevels. */
struct wlr_xwayland_surface *xw_surface;
/* Path 1: geometry listener — keeps scene node in sync when X11 window moves. */
struct wl_listener xw_geometry_listener;
struct wl_listener xw_surface_map_listener; /* fires when wlr_surface maps */
/* Phase 18: scene graph tree for this surface (NULL if scene unavailable). */
struct wlr_scene_tree *scene_node;
/* Listener fires when scene_node is destroyed (e.g. when a parent
* tree is destroyed by wl_frame_destroy as part of unmanage).
* Without it, view->scene_node becomes a dangling pointer and the
* later handle_toplevel_destroy crashes calling wlr_scene_node_destroy
* a second time. */
struct wl_listener scene_destroy_listener;
WNativeWindow id; /* synthetic handle, >= 0x10000000 */
WNativeWindow frame_id; /* frame_buf that owns this view (0 = none) */
int frame_rel_x, frame_rel_y; /* offset within frame */
int x, y; /* Phase 55: WM-assigned position */
/* wmaker-popup-v1: client-driven popup position (only valid if popup != NULL) */
struct wl_resource *popup; /* wmaker_popup_v1 resource or NULL */
int popup_x, popup_y;
struct wlr_xdg_toplevel *popup_parent; /* parent toplevel or NULL */
long *wm_state; /* Phase 56: saved WM state or NULL */
int wm_state_n; /* Phase 56: element count */
char **wm_command; /* Phase 57: WM_COMMAND argv or NULL */
int wm_command_n; /* Phase 57: argument count */
/* Phase 35: foreign toplevel handle — exposes this window to taskbars. */
struct wlr_foreign_toplevel_handle_v1 *ft_handle;
struct wl_list link; /* wl_state.toplevel_list */
};
/*
* wl_or_view — tracks an override_redirect XWayland surface (WM frames,
* dock icons, menus, tooltips). These are not "managed" by the WM in the
* ICCCM sense but must be composited by the scene graph.
*/
struct wl_or_view {
struct wlr_xwayland_surface *xw_surface;
struct wlr_scene_tree *scene_node;
struct wl_listener map_listener;
struct wl_listener unmap_listener;
struct wl_listener destroy_listener;
struct wl_listener set_geometry_listener;
struct wl_list link; /* wl_state.or_list */
};
/*
* wl_frame_buf — a pixman-backed scene buffer for WM frame windows.
* Each frame (titlebar + buttons + resizebar) is rendered into a single
* ARGB pixman image and displayed via a wlr_scene_buffer node.
*/
struct wl_frame_buf {
struct wlr_buffer base; /* wlr_buffer (must be first) */
pixman_image_t *image; /* ARGB32 pixel data */
struct wlr_scene_buffer *scene_buf; /* scene graph node */
struct wlr_scene_tree *tree; /* grouping tree (top-level frames only) */
/* Destroy listeners on scene_buf and tree so they get NULL'd when
* wlroots auto-destroys them (e.g. via cascade from parent tree
* destruction during wl_frame_destroy). Without these, code that
* later tries to wlr_scene_node_destroy them again segfaults inside
* wl_list_remove on already-zeroed list links. */
struct wl_listener scene_buf_destroy;
struct wl_listener tree_destroy;
WNativeWindow id; /* synthetic ID (>= 0x10000000) */
WNativeWindow parent_id; /* parent frame_buf ID (0 = root) */
int x, y; /* position in output coords */
int rel_x, rel_y; /* position relative to parent */
int width, height;
pixman_image_t *bg_pixmap; /* background pixmap for window_clear */
struct wl_list link; /* wl_state.frame_list */
};
/*
* Phase 36: wl_layer_view — one entry per mapped zwlr_layer_shell_v1 surface.
* Tracks the wlroots layer surface, its scene node, and lifecycle listeners.
*/
struct wl_layer_view {
struct wlr_layer_surface_v1 *layer_surface;
struct wlr_scene_tree *scene_node;
struct wl_listener map_listener;
struct wl_listener unmap_listener;
struct wl_listener destroy_listener;
struct wl_list link; /* wl_state.layer_list */
};
/*
* Context store: three per-key linked lists keyed by WNativeWindow.
* Backed by a flat list of (win, data) pairs — fine for the small
* number of windows a typical user has open.
*/
struct wl_ctx_entry {
WNativeWindow win;
void *data;
struct wl_list link;
};
/* ------------------------------------------------------------------ */
/* Global compositor state */
/* ------------------------------------------------------------------ */
struct wl_compositor_state {
struct wl_display *display;
struct wlr_backend *backend;
struct wlr_renderer *renderer;
struct wlr_output *output; /* headless output (screen 0) */
struct wlr_output_layout *output_layout; /* Phase 34 */
/* Phase 35: core Wayland protocol globals */
struct wlr_compositor *compositor;
struct wlr_seat *seat;
struct wlr_data_device_manager *data_device_mgr;
struct wlr_xdg_shell *xdg_shell;
/* wmaker-popup-v1 protocol global — client-driven popup positioning */
struct wl_global *wmaker_popup_manager;
/* Phase 64: XDG decoration manager — tell clients to use CSD */
struct wlr_xdg_decoration_manager_v1 *decoration_manager;
struct wl_listener decoration_new_listener;
/* Phase 36: XDG toplevel tracking */
struct wl_listener xdg_new_surface_listener;
int managed_surface_count; /* surfaces seen */
/* Phase 37: periodic timer that drives client frame callbacks */
struct wl_event_source *frame_timer;
/* Phase 38: per-toplevel view list and context store */
struct wl_list toplevel_list; /* wl_toplevel_view.link */
struct wl_list or_list; /* wl_or_view.link */
struct wl_list frame_list; /* wl_frame_buf.link */
struct wl_list layer_list; /* wl_layer_view.link */
struct wl_list ctx_lists[3]; /* one per WContextKey */
unsigned long next_synthetic_id; /* >= 0x10000000 */
/* Phase 43: first real keyboard device (set by handle_backend_new_input) */
struct wlr_input_device *keyboard_dev;
struct xkb_keymap *xkb_keymap; /* default keymap for keysym lookup */
struct wl_listener keyboard_key_listener; /* Phase 78 */
struct wl_listener keyboard_modifiers_listener; /* Phase 78 */
/* Phase 53: first real pointer device (set by handle_backend_new_input) */
struct wlr_input_device *pointer_dev;
/* Phase 54: virtual pointer position (screen coordinates) */
int pointer_x, pointer_y;
/* Phase 14: pointer event listeners wired to pointer_dev->pointer */
struct wl_listener pointer_motion_listener;
struct wl_listener pointer_motion_abs_listener;
struct wl_listener pointer_button_listener;
struct wl_listener pointer_frame_listener;
/* Phase 17: XWayland server for X11 client support */
struct wlr_xwayland *xwayland;
struct wl_listener xwayland_new_surface_listener;
struct wl_listener xwayland_ready_listener;
struct wl_listener xwayland_server_destroy_listener;
bool xwayland_ready; /* set by handle_xwayland_ready */
Display *x_display; /* WM's Xlib connection to own XWayland */
struct wl_event_source *x11_event_source; /* wl_event_loop fd watcher for x_display */
pthread_t startup_pump_thread; /* pumps Wayland event loop during StartUp() */
volatile int startup_pump_running; /* 1 while pump thread is active */
volatile int terminate; /* set to exit main loop */
/* Phase 20: real input devices from nested backend + their listeners */
struct wlr_input_device *real_keyboard_dev;
struct wlr_input_device *real_pointer_dev;
struct wl_listener backend_new_input_listener;
struct wl_listener real_keyboard_key_listener;
struct wl_listener real_keyboard_modifiers_listener;
struct wl_listener real_keyboard_destroy_listener;
struct wl_listener real_pointer_motion_abs_listener;
struct wl_listener real_pointer_button_listener;
struct wl_listener real_pointer_frame_listener;
/* Phase 18: nested Wayland + wlr_scene */
int is_nested; /* 1 if using wlr_wl_backend */
struct wlr_backend *headless_inner; /* headless backend (always) */
struct wlr_backend *wl_backend_inner; /* wl backend (nested only) */
struct wlr_session *session; /* DRM session (standalone only) */
struct wlr_allocator *allocator;
struct wlr_scene *scene;
struct wlr_scene_output *scene_output;
struct wl_listener backend_new_output_listener;
struct wl_listener output_frame_listener;
char socket_name[64]; /* Phase 34: e.g. "wayland-0" */
int started; /* non-zero after successful display_open */
/* Self-pipe for async-signal-safe shutdown: signal handler writes to [1],
* event loop reads [0] and calls wl_display_terminate(). */
int shutdown_pipe[2];
struct wl_event_source *shutdown_source;
/* signalfd-based signal handling: primary mechanism for catching
* SIGTERM/SIGINT/SIGHUP from within the event loop (avoids async-signal-
* safety issues with the traditional signal handler path). */
int sigfd;
struct wl_event_source *sigfd_source;
/* Phase 22: interactive move/resize grab state.
* grab_type: 0=none, 1=move, 2=resize, 3=WM policy grab.
* Type 3 is used by wl_pointer_grab for WM-internal drags (dock icons,
* app icons, menus). It suppresses wl_update_pointer_focus (so client
* surfaces don't steal pointer events) but does NOT intercept motion —
* WME_MOTION events flow normally to the WMMaskEvent loop.
* grab_view: the toplevel being moved/resized (NULL when grab_type==0 or 3).
* grab_start_ptr_{x,y}: pointer position when grab started.
* grab_start_win_{x,y,w,h}: window geometry when grab started.
* grab_resize_edges: WL_SHELL_SURFACE_RESIZE_* bitmask (resize only). */
int grab_type;
struct wl_toplevel_view *grab_view;
int grab_start_ptr_x, grab_start_ptr_y;
int grab_start_win_x, grab_start_win_y;
int grab_start_win_w, grab_start_win_h;
uint32_t grab_resize_edges;
/* Phase 23: hardware cursor and xcursor theme. */
struct wlr_cursor *cursor;
struct wlr_xcursor_manager *xcursor_mgr;
/* Phase 24: seat cursor-surface request listener. */
struct wl_listener seat_request_cursor_listener;
/* Phase 25: clipboard — seat selection request listener. */
struct wl_listener seat_request_set_selection_listener;
/* Phase 25b: drag-and-drop — seat request_start_drag listener. */
struct wl_listener seat_request_start_drag_listener;
/* Phase 26: primary selection (middle-click paste). */
struct wlr_primary_selection_v1_device_manager *primary_selection_mgr;
struct wl_listener seat_request_primary_selection_listener;
/* Phase 27: xdg-output manager for logical output geometry. */
struct wlr_xdg_output_manager_v1 *xdg_output_mgr;
/* Phase 28: idle-inhibit manager for video players / fullscreen apps. */
struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr;
struct wl_listener idle_new_inhibitor_listener;
/* Phase 29: wp_viewporter for hardware video scaling / subsurface damage. */
struct wlr_viewporter *viewporter;
/* Phase 30: relative pointer + pointer constraints for games. */
struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr;
struct wlr_pointer_constraints_v1 *pointer_constraints;
struct wl_listener new_constraint_listener;
/* Phase 31: keyboard shortcuts inhibitor for fullscreen / remote desktop. */
struct wlr_keyboard_shortcuts_inhibit_manager_v1 *shortcuts_inhibit_mgr;
struct wl_listener new_shortcuts_inhibitor_listener;
/* Phase 32: GPU zero-copy buffer import, screencopy, GPU framebuffer export. */
struct wlr_linux_dmabuf_v1 *linux_dmabuf;
struct wlr_screencopy_manager_v1 *screencopy_mgr;
struct wlr_export_dmabuf_manager_v1 *export_dmabuf_mgr;
/* Phase 33: output management (randr), output power (DPMS), gamma control, presentation time. */
struct wlr_output_manager_v1 *output_mgr;
struct wl_listener output_mgr_apply_listener;
struct wl_listener output_mgr_test_listener;
struct wlr_output_power_manager_v1 *output_power_mgr;
struct wl_listener output_power_set_mode_listener;
struct wlr_gamma_control_manager_v1 *gamma_control_mgr;
struct wlr_presentation *presentation;
/* Phase 34: text input (IME client side), input method (IME server side), virtual keyboard. */
struct wlr_text_input_manager_v3 *text_input_mgr;
struct wl_listener text_input_new_listener;
struct wlr_input_method_manager_v2 *input_method_mgr;
struct wl_listener input_method_new_listener;
struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr;
struct wl_listener virtual_keyboard_new_listener;
/* Phase 35: foreign toplevel management + xdg_activation (focus tokens). */
struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_mgr;
struct wlr_xdg_activation_v1 *xdg_activation;
struct wl_listener xdg_activation_request_listener;
/* Phase 36: layer shell — panels, docks, wallpapers, overlays. */
struct wlr_layer_shell_v1 *layer_shell;
struct wl_listener layer_shell_new_surface_listener;
/* Phase 37: clipboard manager, input inhibitor, virtual pointer, idle, xdg-foreign. */
struct wlr_data_control_manager_v1 *data_control_mgr;
struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr;
struct wl_listener virtual_pointer_new_listener;
struct wlr_xdg_foreign_registry *xdg_foreign_registry;
struct wlr_xdg_foreign_v2 *xdg_foreign_v2;
/* Phase 29 axis listeners (headless pointer + real nested pointer). */
struct wl_listener pointer_axis_listener;
struct wl_listener real_pointer_axis_listener;
struct wl_listener real_pointer_destroy_listener;
/* Phase 30: WM dock panel (native Wayland rendering via wm_shm_surface). */
struct wm_shm_surface *dock_surface; /* NULL until screen_create_internals */
int dock_width; /* pixels reserved on right edge */
int dock_icon_sz; /* icon_sz saved by wm_dock_create */
int dock_n_slots; /* slot count saved by wm_dock_create */
/* Phase 30+: managed app list for dock icon rendering */
#define WM_DOCK_MAX_APPS 32
struct {
WNativeWindow id;
uint32_t *icon_argb; /* heap ARGB8888, or NULL */
int icon_w, icon_h;
} dock_apps[WM_DOCK_MAX_APPS];
int dock_app_count;
/* Stacking level trees — one wlr_scene_tree per layer, ordered
* bottom-to-top (index 0 rendered first = furthest back).
*
* Every scene node that participates in the compositor output is
* assigned to exactly one bucket so that creation order within the
* root tree never matters and there are no Z-order surprises.
*
* Named constants (WL_LAYER_*) map to bucket indices:
*
* 0 WL_LAYER_BACKGROUND background rect / wallpaper
* 1 WL_LAYER_DESKTOP WMDesktopLevel (level < -1)
* 2 WL_LAYER_SUNKEN WMSunkenLevel (level == -1)
* 3 WL_LAYER_NORMAL WMNormalLevel (0 <= level < 3)
* 4 WL_LAYER_FLOATING WMFloatingLevel (3 <= level < 20)
* 5 WL_LAYER_MENU WMMainMenuWindowLevel (20), OR-redirect
* 6 WL_LAYER_DOCK WMStatusWindowLevel / WMDockWindowLevel (21-49)
* also the dock panel wm_shm_surface
* 7 WL_LAYER_FULLSCREEN WMFullscreenLevel (50-99)
* 8 WL_LAYER_OVERLAY WMModalPanel / WMPopUp (>=100)
* also the XOR animation overlay surface
*/
#define WL_LAYER_BACKGROUND 0
#define WL_LAYER_DESKTOP 1
#define WL_LAYER_SUNKEN 2
#define WL_LAYER_NORMAL 3
#define WL_LAYER_FLOATING 4
#define WL_LAYER_MENU 5
#define WL_LAYER_DOCK 6
#define WL_LAYER_FULLSCREEN 7
#define WL_LAYER_OVERLAY 8
#define WL_NUM_LEVEL_BUCKETS 9
struct wlr_scene_tree *level_trees[WL_NUM_LEVEL_BUCKETS];
struct wlr_scene_rect *bg_rect; /* default solid background */
struct wlr_scene_buffer *bg_image; /* wallpaper image (if set) */
struct wlr_buffer *bg_wlr_buf; /* backing buffer for bg_image */
/* Phase 81: full-screen overlay surface for XOR animation drawing */
struct wm_shm_surface *overlay_surf; /* NULL until first draw */
/* Focus sink: small off-screen InputOnly X window that receives focus
* when no application window is focused. Mirrors what x11_backend does
* for no_focus_win so that XSetInputFocus calls on this window succeed. */
WNativeWindow no_focus_xwin; /* 0 until screen_create_internals */
/* wrlib RContext drawable — an ordinary InputOutput window that XWM must
* not manage (no WM_CLASS, no backing wl_surface). Stored here so
* handle_xwayland_new_surface can filter it before allocating a view. */
WNativeWindow rcontext_xwin; /* 0 until screen_alloc_gcs */
/* Deferred dock creation: set in screen_create_internals, consumed in
* wl_event_loop_run() after the startup pump thread stops (to avoid racing
* with the pump thread's frame-timer callback on the scene graph). */
WScreen *dock_pending_scr;
/* Button icon RImages (parsed from XPM on first use) */
RImage *btn_close_img;
RImage *btn_iconify_img;
RImage *btn_kill_img;
/* Tracks the frame_buf the pointer was last over (after button resolution),
* so motion handlers can emit synthetic WME_LEAVE/WME_ENTER events when
* the pointer crosses between WM frame sub-windows (titlebar, resizebar,
* buttons). buttonMouseDown's inner press-track loop depends on these. */
WNativeWindow last_hovered_id;
/* Focus guard: when true, the next focus-follows-pointer event is suppressed.
* Set by switchpanel_send_enter (called twice in wSwitchPanelDestroy) to prevent
* spurious focus changes when the Alt-Tab overlay is destroyed and the pointer
* re-enters the root window or a client surface underneath. */
bool ignore_focus_ffp;
/* Keyboard grab: when true, key events are queued for WMMaskEvent but not
* forwarded to Wayland clients (used by Alt-Tab cycling). */
bool keyboard_grabbed;
};
extern struct wl_compositor_state wl_state;
void wl_context_save(WNativeWindow win, WContextKey key, void *data);
void * wl_context_find(WNativeWindow win, WContextKey key);
int wl_context_delete(WNativeWindow win, WContextKey key);
#endif /* WL_TYPES_H */