14 KiB
wl_backend.c Decomposition Plan
Overview
src/backend/wayland/wl_backend.c is 2329 lines containing 6 unrelated functional
areas that have accumulated in a single file. This plan decomposes it into
focused modules, each of which can be carried out as an independent commit.
The target is to reduce wl_backend.c to ~900 lines containing only the
compositor lifecycle (open/close/run/terminate) and the small protocol handlers
that are tightly coupled to it.
Pre-requisites
- Build system:
src/Makefile.am(lines 164-209) lists allbackend/wayland/*.cfiles underwmaker_SOURCES. Any new.cfile must be added there. - After editing
Makefile.am, runautoreconf -fi && ./configure <flags>to regenerateMakefile.inandMakefile. - All wayland backend files share state through the global
wl_statestruct declared inwl_types.hand defined inwl_backend.c. - Forward declarations use
externfor functions defined in other.cfiles. Functions that become file-local after extraction should be markedstatic.
Step 1 — Remove duplicate layer shell code (delete ~180 lines)
Problem: wl_backend.c lines 1539-1720 contain a static copy of the
layer shell implementation. An identical non-static copy exists in
wl_layer_shell.c (196 lines, already in Makefile.am). The static
qualifier on the wl_backend.c copy means it shadows the wl_layer_shell.c
version within this translation unit — the wl_layer_shell.c version is
effectively dead code.
Functions to delete from wl_backend.c:
| Function | Lines | Status in wl_backend.c |
|---|---|---|
layer_surface_compute_geometry |
1546-1568 | static — duplicate |
layer_surface_compute_position |
1574-1608 | static — duplicate |
handle_layer_surface_map |
1610-1618 | static — duplicate |
handle_layer_surface_unmap |
1620-1630 | static — duplicate |
handle_layer_surface_destroy |
1632-1646 | static — duplicate |
handle_layer_shell_new_surface |
1653-1720 | static — duplicate |
LAYER_VIEW_FROM macro |
1539-1540 | duplicate of wl_layer_shell.c:14 |
Changes:
-
In
wl_backend.c, delete lines 1539-1720 (theLAYER_VIEW_FROMmacro through the end ofhandle_layer_shell_new_surface). -
In
wl_backend.c, change the forward declaration at line 222 from:static void handle_layer_shell_new_surface(struct wl_listener *listener, void *data);to:
extern void handle_layer_shell_new_surface(struct wl_listener *listener, void *data); -
No
Makefile.amchange needed —wl_layer_shell.cis already listed.
Verification: make clean && make — the linker resolves
handle_layer_shell_new_surface from wl_layer_shell.o. Run the compositor
and verify a layer-shell client (e.g. waybar, wlr-randr) still works.
Step 2 — Extract desktop background to wl_background.c (~300 lines)
Problem: wl_set_desktop_background() (lines 2034-2287) plus its helper
types and functions (lines 1984-2032) form a self-contained 300-line module
for rendering wallpapers. It has no callers within wl_backend.c — it is
called from defaults.c via the backend vtable.
Functions/types to move:
| Symbol | Lines | Visibility |
|---|---|---|
struct wl_bg_buffer |
1987-1990 | file-local struct |
bg_buffer_destroy |
1992-1998 | static |
bg_buffer_begin_data_ptr_access |
2000-2009 | static |
bg_buffer_end_data_ptr_access |
2011-2014 | static |
bg_buffer_impl |
2016-2020 | static const |
parse_color_to_rcolor |
2022-2032 | static |
wl_set_desktop_background |
2034-2287 | extern (vtable) |
Steps:
-
Create
src/backend/wayland/wl_background.cwith these includes:#ifdef HAVE_CONFIG_H #include "config.h" #endif #include <string.h> #include <stdlib.h> #include <limits.h> #include <wayland-server-core.h> #include <wlr/types/wlr_output.h> #include <wlr/types/wlr_scene.h> #include <wlr/types/wlr_buffer.h> #include <wlr/interfaces/wlr_buffer.h> #include <libdrm/drm_fourcc.h> #include <pixman.h> #include "../../screen.h" #include "../../resources.h" #include "wl_types.h" -
Move all 7 symbols listed above into the new file. Keep
staticon the helpers;wl_set_desktop_backgroundstays non-static. -
Delete lines 1984-2287 from
wl_backend.c. -
In
wl_backend.c, the#includelist does not need changes — the function is resolved at link time. -
Add to
src/Makefile.aminside theif USE_WAYLAND_BACKENDblock:backend/wayland/wl_background.c \ -
Run
autoreconf -fi && ./configure <flags> && make.
Verification: Set a gradient or pixmap background in
~/GNUstep/Defaults/WindowMaker and confirm it renders.
Step 3 — Move screen internals to wl_screen.c (~235 lines)
Problem: wl_screen.c already contains wl_screen_open,
wl_screen_close, wl_screen_init_display, wl_show_crash_dialog,
wl_get_color_for_colormap, and wl_parse_color (244 lines). But the
screen setup functions wl_screen_alloc_gcs, wl_screen_create_internals,
wl_screen_create_pixmaps, wl_screen_load_tech_font, and the one-liner
stubs remain in wl_backend.c.
Functions to move:
| Function | Lines | Notes |
|---|---|---|
wl_screen_select_input |
1732 | one-liner stub |
wl_screen_set_root_cursor |
1733 | one-liner stub |
wl_screen_set_icon_sizes |
1734 | one-liner stub |
wl_screen_setup_noticeboard |
1735 | one-liner stub |
wl_screen_alloc_gcs |
1737-1836 | ~100 lines, X11 GC creation |
wl_screen_create_internals |
1838-1966 | ~130 lines, scene setup |
wl_screen_create_pixmaps |
1967 | one-liner stub |
wl_screen_load_tech_font |
1968-1978 | small |
wl_screen_show_mini_screenshot |
1979 | one-liner stub |
wl_screen_capture_area |
1980 | one-liner stub |
wl_screen_capture_window |
1981 | one-liner stub |
wl_refresh_desktop |
1982 | one-liner stub |
wl_monitors_query |
2289-2323 | ~35 lines |
wl_monitors_select_events |
2325 | one-liner stub |
Steps:
-
Add required includes to
wl_screen.c(some may already be present):#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 "../../defaults.h" #include "../../xmodifier.h" #include "../../def_pixmaps.h" -
wl_screen_create_internalsreferences these external symbols that must be declared (viaexternor header include) inwl_screen.c:frame_buf_impl— defined inwl_framebuf.c; addextern const struct wlr_buffer_impl frame_buf_impl;fb_attach_tree_listener,fb_attach_scene_buf_listener— defined inwl_framebuf.cW_RegisterBacking,W_UnregisterBacking— WINGs internalsOVL_GH— defined inwl_overlay.corwl_types.h
-
wl_screen_alloc_gcsreferencesDEF_FRAME_THICKNESS(fromframewin.h) andWM_EVMASK_*macros. Ensure these headers are included. -
Move all 14 functions listed above from
wl_backend.cintowl_screen.c. -
Delete lines 1732-1982 and 2289-2329 from
wl_backend.c. -
No
Makefile.amchange needed —wl_screen.cis already listed.
Verification: make succeeds. Launch compositor, verify screen
initialization (GCs created, workspace badge visible, dock shadow works).
Step 4 — Extract X11 event bridge to wl_xwayland.c (~55 lines)
Problem: wl_handle_x11_events() (lines 269-326) translates XEvents from
the XWayland connection into WMEvents. It belongs with the other XWayland
code in wl_xwayland.c (429 lines, already in Makefile.am under
USE_XWAYLAND).
Functions to move:
| Function | Lines | Notes |
|---|---|---|
wl_handle_x11_events |
269-326 | static in wl_backend.c |
Steps:
-
Move
wl_handle_x11_eventstowl_xwayland.c. Removestaticso it can be called fromwl_backend.c. -
In
wl_backend.c, replace the function body with:extern int wl_handle_x11_events(int fd, uint32_t mask, void *data);(The non-XWAYLAND stub at lines 323-325 stays in
wl_backend.c.) -
Ensure
wl_xwayland.cincludes<WINGs/WMEvent.h>and"../../event.h"forWMHandleEvent.
Verification: Launch with XWayland enabled, open an X11 app (e.g.
xterm), verify keyboard/mouse events work.
Step 5 — Extract protocol global init from wl_display_open() (~240 lines)
Problem: wl_display_open() is 670 lines. Lines 578-818 are a linear
sequence of ~25 protocol global creation calls (wlr_*_create +
wl_signal_add). This block has no control flow dependencies on the
surrounding code beyond wl_state.display and wl_state.seat being set.
Approach: Extract into a helper function wl_protocols_init() in
wl_extensions.c (which currently contains only stubs and error handlers —
172 lines).
Steps:
-
In
wl_extensions.c, add a new function:void wl_protocols_init(void)that contains the protocol global creation block (lines 578-818 of
wl_backend.c). This includes creation of:wlr_compositor,wlr_subcompositorwlr_seat,wlr_data_device_manager- seat event wiring (request_set_cursor, request_set_selection, request_start_drag, request_set_primary_selection)
wlr_primary_selection_v1_device_managerwlr_xdg_output_manager_v1wlr_idle_inhibit_v1wlr_viewporterwlr_relative_pointer_manager_v1wlr_pointer_constraints_v1wlr_keyboard_shortcuts_inhibit_v1wlr_linux_dmabuf_v1wlr_screencopy_manager_v1wlr_export_dmabuf_manager_v1wlr_output_manager_v1wlr_output_power_manager_v1wlr_gamma_control_manager_v1wlr_presentationwlr_text_input_manager_v3wlr_input_method_manager_v2wlr_virtual_keyboard_manager_v1wlr_foreign_toplevel_manager_v1wlr_xdg_activation_v1wlr_layer_shell_v1wlr_data_control_manager_v1wlr_virtual_pointer_manager_v1wlr_xdg_foreign_registry+wlr_xdg_foreign_v2wlr_xdg_shellwmaker_popup_manager_v1(custom protocol)wlr_xdg_decoration_manager_v1wlr_renderer_init_wl_shm
-
The function needs these
externhandler declarations (move fromwl_backend.cforward-declaration block):handle_seat_request_cursorhandle_seat_request_set_selection— currentlystaticin wl_backend.c; must become non-static and move towl_extensions.cor stay in wl_backend.c with anexterndeclarationhandle_seat_request_start_drag— already inwl_dnd.chandle_seat_request_primary_selection— currentlystatic; same treatmenthandle_idle_new_inhibitor— currentlystatic; same treatmenthandle_new_pointer_constraint— currentlystatic; same treatmenthandle_new_shortcuts_inhibitor— currentlystatic; same treatment- All the
externhandlers already in other files (output_mgr, text_input, etc.)
-
Move the 5 small
statichandler functions that are only used by protocol init intowl_extensions.cas well (removestatic):handle_seat_request_set_selection(lines 1451-1459)handle_seat_request_primary_selection(lines 1467-1475)handle_idle_new_inhibitor(lines 1484-1491)handle_new_pointer_constraint(lines 1507-1517)handle_new_shortcuts_inhibitor(lines 1528-1535)
-
In
wl_display_open(), replace lines 578-821 with:wl_protocols_init(); -
Add required
#includedirectives towl_extensions.cfor the wlroots protocol types used. The full list is long — copy the relevant subset fromwl_backend.c's include block. -
No
Makefile.amchange needed —wl_extensions.cis already listed.
Verification: make succeeds. Launch compositor, verify all protocol
globals are advertised (wayland-info or wlr-randr should list them).
Execution order
Steps are ordered by risk (lowest first) and independence:
| Step | Risk | Reason |
|---|---|---|
| 1 (layer shell dedup) | Lowest | Pure deletion of shadowed static code |
| 2 (background) | Low | Self-contained, no cross-references |
| 3 (screen internals) | Medium | Many extern references to resolve |
| 4 (X11 bridge) | Low | Small, single function |
| 5 (protocol init) | Medium | Touches the critical init path; many handler relocations |
Each step should be a separate commit. Build and smoke-test after each.
Expected result
| File | Before | After |
|---|---|---|
wl_backend.c |
2329 lines | ~900 lines |
wl_layer_shell.c |
196 lines (dead) | 196 lines (live) |
wl_background.c |
— (new) | ~310 lines |
wl_screen.c |
244 lines | ~480 lines |
wl_xwayland.c |
429 lines | ~485 lines |
wl_extensions.c |
172 lines | ~450 lines |
The remaining wl_backend.c contains:
wl_display_open()(~430 lines) — backend/renderer/allocator/scene/cursor creation, XKB keymap, XWayland setup, frame timer, shutdown pipe, pump threadwl_display_close()(~210 lines) — teardown and listener removalwl_display_post_open(),wl_display_screen_count(),wl_display_default_screen()— trivial stubswl_event_loop_run()(~190 lines) — signalfd, main dispatch loopwl_event_loop_terminate()— shutdown pipe writewl_startup_pump_thread()— startup helperwl_shutdown_pipe_handler(),frame_timer_cb()— event loop callbacks- Global
wl_statedefinition
This is a coherent "compositor lifecycle" module at a manageable size.