diff --git a/ROADMAP.md b/ROADMAP.md index 421df66..5911a20 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -63,15 +63,13 @@ XWayland bridge auto-syncs. Needs verification. ### 1.4 Remaining Vtable Stubs -These vtable slots are stubs or partial implementations: - -| Slot | Purpose | Needed For | -|------|---------|------------| -| `overlay_draw_*` | Pixman animation buffer | Iconify zoom animation | -| `client_snapshot` | Window thumbnail capture | Switch panel thumbnails, icon preview | -| `window_set_border` | Scene rect border nodes | Window borders | -| `client_synth_configure` | XDG configure scheduling | Resize negotiation | -| `pointer_change_grab` | Grab parameter update | Menu tracking | +| Slot | Status | +|------|--------| +| `overlay_draw_*` | ✅ Done — real pixman overlay implementation | +| `client_snapshot` | ❌ Stub — needs last-committed texture → RImage | +| `window_set_border` | ✅ No-op (borders drawn into frame buffer) | +| `client_synth_configure` | ✅ Done — XDG configure + XWayland configure | +| `pointer_change_grab` | ⚠️ No-op — menu tracking may need this | --- diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 25862a1..1470785 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -7882,7 +7882,65 @@ static int wl_client_get_pid(WNativeWindow win) static RImage * wl_client_snapshot(WScreen *scr, WNativeWindow client_win, WNativeWindow frame_win) -{ (void)scr; (void)client_win; (void)frame_win; return NULL; } +{ + (void)frame_win; + struct wl_toplevel_view *v = wl_find_view_by_id(client_win); + if (!v) return NULL; + + /* XWayland: capture via XGetImage on the WM's X display */ + if (v->xw_surface && wl_state.x_display) { + Window xid = (Window)v->xw_surface->window_id; + XWindowAttributes attr; + if (!XGetWindowAttributes(wl_state.x_display, xid, &attr)) + return NULL; + XImage *img = XGetImage(wl_state.x_display, xid, + 0, 0, attr.width, attr.height, + AllPlanes, ZPixmap); + if (!img) return NULL; + RImage *res = RCreateImageFromXImage(scr->rcontext, img, NULL); + XDestroyImage(img); + return res; + } + + /* Native Wayland: read pixels from last committed surface buffer */ + if (!v->xdg_surface || !v->xdg_surface->surface) return NULL; + struct wlr_surface *s = v->xdg_surface->surface; + if (!s->buffer) return NULL; + struct wlr_buffer *buf = &s->buffer->base; + + uint32_t fmt; + void *data; + size_t stride; + if (!wlr_buffer_begin_data_ptr_access(buf, WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &fmt, &stride)) + return NULL; + + int w = s->current.width; + int h = s->current.height; + if (w <= 0 || h <= 0) { + wlr_buffer_end_data_ptr_access(buf); + return NULL; + } + + /* Create RImage and copy pixels (ARGB32 → RGBA byte order swap) */ + RImage *res = RCreateImage(w, h, True); + if (res) { + unsigned char *src = (unsigned char *)data; + unsigned char *dst = res->data; + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + int si = y * stride + x * 4; + int di = (y * w + x) * 4; + dst[di + 0] = src[si + 2]; /* B → R */ + dst[di + 1] = src[si + 1]; /* G → G */ + dst[di + 2] = src[si + 0]; /* R → B */ + dst[di + 3] = src[si + 3]; /* A → A */ + } + } + } + + wlr_buffer_end_data_ptr_access(buf); + return res; +} static int wl_coords_translate(WNativeWindow src, WNativeWindow dst,