wayland: Phase 30 — native Wayland dock panel via wm_shm_surface
Replace the Phase 29 test square with a proper dock panel anchored to the
right edge of the primary output. The panel is rendered entirely via
pixman into a wm_shm_surface and uploaded to the wlroots scene graph — no
X11 drawing resources needed.
Visual design:
- Dark charcoal background (0xFF1C1C1C)
- 1-px left-edge highlight (0xFF404040) separating dock from desktop
- 1-px top separator (0xFF303030)
- Column of bevelled icon-slot placeholders (top/left highlight +
bottom/right shadow) at icon_size × icon_size spacing
Layout and sizing:
- Width = icon_size + 4 px (default 68 px for 64-px icons)
- Height = full output height
- X position = output_width - dock_width (flush to right edge)
- n_slots = (height - 4) / (icon_size + 2) (16 slots @ 1080p)
Usable area:
- head-0 x2 shrunk by dock_width so window placement never overlaps
The WDock X11 code path remains disabled (nodock=1) — icon population
and click handling come in later phases.
Smoke test: PASS ("dock panel created at 1852,0 (68x1080, 16 slots)")
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4f0273e5e6
commit
8fe783e304
|
|
@ -393,6 +393,9 @@ struct wl_compositor_state {
|
|||
/* Phase 29 axis listeners (headless pointer + real nested pointer). */
|
||||
struct wl_listener pointer_axis_listener;
|
||||
struct wl_listener real_pointer_axis_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 */
|
||||
};
|
||||
|
||||
static struct wl_compositor_state wl_state;
|
||||
|
|
@ -2556,6 +2559,127 @@ wm_shm_surface_destroy(struct wm_shm_surface *s)
|
|||
wlr_buffer_drop(&s->wlr_buf); /* producer done; shm_buf_destroy frees s */
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
/* Phase 30: WM dock panel (layer-anchored, pixman-rendered) */
|
||||
/* ================================================================== */
|
||||
|
||||
/*
|
||||
* The dock is a vertical strip anchored to the right edge of the primary
|
||||
* output. It is rendered into a wm_shm_surface whose pixels flow through
|
||||
* the wlroots scene graph, exactly like any other WM UI element.
|
||||
*
|
||||
* Layout (right edge, full screen height):
|
||||
*
|
||||
* ┌──────────────────────────────────────────────────┬────────┐
|
||||
* │ │ ██████ │
|
||||
* │ desktop / client windows │ ██████ │
|
||||
* │ (constrained to usable area) │ ██████ │
|
||||
* │ │ dock │
|
||||
* └──────────────────────────────────────────────────┴────────┘
|
||||
* ← dw →
|
||||
*
|
||||
* The usable area (where windows are placed) is shrunk by dock_width so
|
||||
* clients never overlap the panel.
|
||||
*/
|
||||
|
||||
/* Default width when wPreferences.icon_size is not yet set. */
|
||||
#define WM_DOCK_DEFAULT_WIDTH 68 /* 64 px icon + 4 px border */
|
||||
|
||||
/* Colours (ARGB8888, fully opaque) */
|
||||
#define WM_DOCK_BG 0xFF1C1C1C /* dark charcoal background */
|
||||
#define WM_DOCK_HIGHLIGHT 0xFF404040 /* 1-px highlight on left edge */
|
||||
#define WM_DOCK_TOPSEP 0xFF303030 /* 1-px separator at top */
|
||||
#define WM_DOCK_TILE_BG 0xFF252525 /* icon-slot background */
|
||||
#define WM_DOCK_TILE_HI 0xFF353535 /* icon-slot top/left highlight */
|
||||
#define WM_DOCK_TILE_SH 0xFF151515 /* icon-slot bottom/right shadow */
|
||||
|
||||
/* wm_dock_render_tile — paint one icon slot starting at (x, y).
|
||||
* Slots are icon_size × icon_size with a 1-px inset bevel. */
|
||||
static void
|
||||
wm_dock_render_tile(struct wm_shm_surface *s,
|
||||
int x, int y, int tile_sz)
|
||||
{
|
||||
/* Background */
|
||||
wm_shm_surface_fill(s, x, y, tile_sz, tile_sz, WM_DOCK_TILE_BG);
|
||||
/* Top highlight */
|
||||
wm_shm_surface_fill(s, x, y, tile_sz, 1, WM_DOCK_TILE_HI);
|
||||
/* Left highlight */
|
||||
wm_shm_surface_fill(s, x, y, 1, tile_sz, WM_DOCK_TILE_HI);
|
||||
/* Bottom shadow */
|
||||
wm_shm_surface_fill(s, x, y + tile_sz - 1, tile_sz, 1, WM_DOCK_TILE_SH);
|
||||
/* Right shadow */
|
||||
wm_shm_surface_fill(s, x + tile_sz - 1, y, 1, tile_sz, WM_DOCK_TILE_SH);
|
||||
}
|
||||
|
||||
/* wm_dock_render — paint the full dock panel.
|
||||
* Draws the background, left-edge highlight, top separator, and a column
|
||||
* of empty icon slots to give visual structure before real icons arrive. */
|
||||
static void
|
||||
wm_dock_render(struct wm_shm_surface *s, int icon_sz, int n_slots)
|
||||
{
|
||||
int w = s->width;
|
||||
int h = s->height;
|
||||
int tile_sz = icon_sz;
|
||||
int pad = (w - tile_sz) / 2; /* horizontal centering margin */
|
||||
|
||||
/* Background */
|
||||
wm_shm_surface_fill(s, 0, 0, w, h, WM_DOCK_BG);
|
||||
|
||||
/* Left-edge highlight (the dock's inner border with the desktop) */
|
||||
wm_shm_surface_fill(s, 0, 0, 1, h, WM_DOCK_HIGHLIGHT);
|
||||
|
||||
/* Top separator */
|
||||
wm_shm_surface_fill(s, 0, 0, w, 1, WM_DOCK_TOPSEP);
|
||||
|
||||
/* Icon-slot placeholders */
|
||||
for (int i = 0; i < n_slots; i++) {
|
||||
int ty = 2 + i * (tile_sz + 2);
|
||||
if (ty + tile_sz > h)
|
||||
break;
|
||||
wm_dock_render_tile(s, pad, ty, tile_sz);
|
||||
}
|
||||
}
|
||||
|
||||
/* wm_dock_create — allocate the dock surface, render it, attach to scene,
|
||||
* and shrink the head-0 usable area by dock_width pixels on the right. */
|
||||
static void
|
||||
wm_dock_create(WScreen *scr)
|
||||
{
|
||||
if (!wl_state.scene || !wl_state.output)
|
||||
return;
|
||||
|
||||
int sw = (int)wl_state.output->width;
|
||||
int sh = (int)wl_state.output->height;
|
||||
int icon_sz = (wPreferences.icon_size > 0)
|
||||
? wPreferences.icon_size : 64;
|
||||
int dw = icon_sz + 4; /* dock width = icon + 2px pad each side */
|
||||
int n_slots = (sh - 4) / (icon_sz + 2); /* how many slots fit */
|
||||
|
||||
struct wm_shm_surface *s = wm_shm_surface_create(dw, sh);
|
||||
if (!s) {
|
||||
wwarning("wl_backend: wm_dock_create: failed to allocate surface");
|
||||
return;
|
||||
}
|
||||
|
||||
wm_dock_render(s, icon_sz, n_slots);
|
||||
wm_shm_surface_commit(s, &wl_state.scene->node, sw - dw, 0);
|
||||
|
||||
wl_state.dock_surface = s;
|
||||
wl_state.dock_width = dw;
|
||||
|
||||
/* Shrink head-0 usable area so window placement avoids the dock. */
|
||||
if (scr->usableArea) {
|
||||
int right = scr->usableArea[0].x2 - dw;
|
||||
if (right < scr->usableArea[0].x1)
|
||||
right = scr->usableArea[0].x1;
|
||||
scr->usableArea[0].x2 = right;
|
||||
scr->totalUsableArea[0].x2 = right;
|
||||
}
|
||||
|
||||
wwarning("wl_backend: dock panel created at %d,0 (%dx%d, %d slots)",
|
||||
sw - dw, dw, sh, n_slots);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Screen open/close */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
|
@ -4056,22 +4180,15 @@ wl_screen_create_internals(WScreen *scr)
|
|||
|
||||
wSetModifierMasks(Mod1Mask, Mod1Mask, Mod4Mask, 0);
|
||||
|
||||
/* Dock/clip require X11 rendering resources not yet available in Wayland
|
||||
* mode. Disable until native Wayland dock rendering is implemented. */
|
||||
/* Phase 30: the WDock X11 code path is still disabled (it needs X11 GCs /
|
||||
* pixmaps we don't have in pure Wayland mode). The visual dock panel is
|
||||
* created below via wm_dock_create() which uses wm_shm_surface directly. */
|
||||
wPreferences.flags.noclip = 1;
|
||||
wPreferences.flags.nodock = 1;
|
||||
wwarning("wl_backend: dock/clip disabled pending native Wayland rendering");
|
||||
|
||||
/* Phase 29 smoke test: create a 64×64 steel-blue surface at (16,16) to
|
||||
* verify the pixman → wlr_scene_buffer pipeline produces visible pixels. */
|
||||
if (wl_state.scene) {
|
||||
struct wm_shm_surface *test_surf = wm_shm_surface_create(64, 64);
|
||||
if (test_surf) {
|
||||
wm_shm_surface_fill(test_surf, 0, 0, 64, 64, 0xFF4080C0); /* steel-blue */
|
||||
wm_shm_surface_commit(test_surf, &wl_state.scene->node, 16, 16);
|
||||
wwarning("wl_backend: Phase 29 test surface committed (64x64 steel-blue at 16,16)");
|
||||
}
|
||||
}
|
||||
/* Phase 30: create the native Wayland dock panel. */
|
||||
wm_dock_create(scr);
|
||||
}
|
||||
static void wl_screen_create_pixmaps(WScreen *scr) { (void)scr; }
|
||||
static void wl_screen_load_tech_font(WScreen *scr) { (void)scr; }
|
||||
|
|
|
|||
|
|
@ -320,13 +320,17 @@ grep -q 'pointer motion/button/frame listeners wired' /tmp/wl-smoke-stderr \
|
|||
|| die "compositor did not log pointer listeners wired"
|
||||
echo " ptr listener check: pointer motion/button/frame listeners wired"
|
||||
|
||||
# -- 4f. Phase 11: dock/clip disabled in Wayland mode --------------------
|
||||
# -- 4f. Phase 30: dock panel rendered via wm_shm_surface ----------------
|
||||
#
|
||||
# wl_screen_create_internals always sets noclip=1 nodock=1 until native
|
||||
# Wayland dock rendering is implemented.
|
||||
# wl_screen_create_internals calls wm_dock_create() which logs
|
||||
# "dock panel created at X,0 (WxH, N slots)".
|
||||
# WDock X11 code path is still disabled (noclip/nodock=1).
|
||||
grep -q 'dock/clip disabled' /tmp/wl-smoke-stderr \
|
||||
|| die "compositor did not log dock/clip disabled (wl_screen_create_internals broken?)"
|
||||
echo " nodock check: dock/clip disabled pending native Wayland rendering"
|
||||
grep -q 'dock panel created' /tmp/wl-smoke-stderr \
|
||||
|| die "compositor did not log dock panel creation (wm_dock_create failed?)"
|
||||
DOCK_INFO=$(grep -o 'dock panel created at [0-9]*,0 ([^)]*)' /tmp/wl-smoke-stderr | head -1)
|
||||
echo " nodock check: dock/clip disabled; ${DOCK_INFO:-dock panel created}"
|
||||
|
||||
# -- 4f2b. Phase 25: clipboard selection wired ----------------------------
|
||||
grep -q 'clipboard selection wired' /tmp/wl-smoke-stderr \
|
||||
|
|
|
|||
Loading…
Reference in New Issue