wl_backend: fix unshade — re-enable and raise client surface and frame

On shade, the client scene node was lowered and disabled, and the
frame_buf scene node was disabled. On unshade, the frame_buf node
was not re-enabled, and the client node was enabled but remained
behind the frame (at bottom of Z-order from stacking_lower).

Fix: re-enable frame_buf node when show_resizebar is true, and
raise the client scene node to top on window_map so it's above
the frame background.
This commit is contained in:
lkn 2026-05-14 22:26:07 +02:00
parent 34ed9fc1b2
commit 859c4d8e78
8 changed files with 58 additions and 19 deletions

3
+cmd
View File

@ -1,3 +1,6 @@
Xwayland :1
DISPLAY=':1' wmaker --for-real
WMAKER_USE_WAYLAND='1' WMAKER_WAYLAND_NESTED='1' LD_LIBRARY_PATH='/usr/local/lib' gdb -batch -ex 'set confirm off' -ex 'set filename-display absolute' -ex run -ex bt -ex quit --args src/.libs/wmaker --for-real >[2=1]
WAYLAND_DISPLAY=wayland-0 foot

View File

@ -257,6 +257,10 @@ x11_fetch(void *ectx, WMEvent *ev)
xev_to_wme(slot, ev);
ev->_view_target = W_GetViewForXWindow(ctx->dpy, slot->xany.window);
if (slot->type == Expose && ev->_view_target)
wwarning("FETCH: expose for 0x%lx -> view %p", slot->xany.window, ev->_view_target);
if (slot->type == Expose && !ev->_view_target)
wwarning("FETCH: expose for 0x%lx -> NO VIEW", slot->xany.window);
}
static Bool

View File

@ -1079,6 +1079,8 @@ void WMRunModalLoop(WMScreen * scr, WMView * view)
/*WMScreen *scr = view->screen; */
int oldModalLoop = scr->modalLoop;
WMView *oldModalView = scr->modalView;
W_View *ptr;
int needsRedisplay = 1;
scr->modalView = view;
@ -1089,6 +1091,12 @@ void WMRunModalLoop(WMScreen * scr, WMView * view)
WMNextEvent(scr, &event);
WMHandleEvent(&event);
if (needsRedisplay) {
needsRedisplay = 0;
for (ptr = view->childrenList; ptr; ptr = ptr->nextSister)
W_RedisplayView(ptr);
}
/* Wayland: re-composite and commit after each event */
if (!scr->display) {
const W_ViewBackend *vb = scr->viewBackend;

View File

@ -53,6 +53,27 @@ static void adoptChildView(W_View * view, W_View * child)
child->parent = view;
}
static const XSetWindowAttributes defAtts = {
None, /* background_pixmap */
0, /* background_pixel */
None, /* border_pixmap */
0, /* border_pixel */
NorthWestGravity, /* bit_gravity */
NorthWestGravity, /* win_gravity */
NotUseful, /* backing_store */
(unsigned)~0, /* backing_planes */
0, /* backing_pixel */
False, /* save_under */
KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|
EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask|
VisibilityChangeMask|FocusChangeMask|PropertyChangeMask|
SubstructureNotifyMask, /* event_mask */
0, /* do_not_propagate_mask */
False, /* override_redirect */
None, /* colormap */
None /* cursor */
};
static W_View *createView(W_Screen * screen, W_View * parent)
{
W_View *view;
@ -61,6 +82,15 @@ static W_View *createView(W_Screen * screen, W_View * parent)
view->screen = screen;
if (parent != NULL) {
view->attribFlags = CWEventMask | CWBitGravity;
view->attribs = defAtts;
view->attribFlags |= CWBackPixel | CWColormap | CWBorderPixel | CWBackPixmap;
view->attribs.background_pixmap = None;
view->attribs.background_pixel = W_PIXEL(screen->gray);
view->attribs.border_pixel = W_PIXEL(screen->black);
view->attribs.colormap = screen->colormap;
view->backColor = WMRetainColor(screen->gray);
adoptChildView(parent, view);
}

View File

@ -40,7 +40,7 @@ W_View *W_GetViewForWindow(Window id)
if (view_table[slot].id == id)
return view_table[slot].view;
if (view_table[slot].id == 0) {
wwarning("W_GetViewForWindow: id=0x%lx NOT FOUND (slot %u empty)", (unsigned long)id, slot);
//wwarning("W_GetViewForWindow: id=0x%lx NOT FOUND (slot %u empty)", (unsigned long)id, slot);
return NULL;
}
}

View File

@ -241,11 +241,10 @@ void wSetFocusTo(WScreen *scr, WWindow *wwin)
void wShadeWindow(WWindow *wwin)
{
wwarning("wShadeWindow");
if (wwin->flags.shaded)
return;
if (!wwin->frame)
return; /* Phase 71: Wayland — no frame to shade */
wm_backend->stacking_lower(wwin->client_win);
shade_animate(wwin, SHADE);
@ -284,12 +283,9 @@ void wShadeWindow(WWindow *wwin)
void wUnshadeWindow(WWindow *wwin)
{
wwarning("wUnshadeWindow");
if (!wwin->flags.shaded)
return;
if (!wwin->frame)
return; /* Phase 71: Wayland — no frame to unshade */
wwin->flags.shaded = 0;
wwin->flags.mapped = 1;
wm_backend->window_map(wwin->client_win);
@ -2271,6 +2267,7 @@ void movePointerToWindowCenter(WWindow *wwin)
#ifdef USE_ANIMATIONS
static void shade_animate(WWindow *wwin, Bool what)
{
wwarning("shade_animate");
int y, s, w, h;
time_t time0 = time(NULL);

View File

@ -989,13 +989,6 @@ handle_toplevel_map(struct wl_listener *listener, void *data)
WWindow *wwin = wManageWindow(scr, view->id);
if (wwin) {
int pid = wl_client_get_pid(view->id);
wwarning("wl_backend: wManageWindow succeeded id=0x%lx "
"class=%s name=%s geo=%dx%d pid=%d kill_close=%d",
view->id,
wwin->wm_class ? wwin->wm_class : "(none)",
wwin->wm_instance ? wwin->wm_instance : "(none)",
wwin->client.width, wwin->client.height, pid,
wwin->client_flags.kill_close);
/* Phase 62: focus delivered by wManageWindow via wSetFocusTo
* (auto_focus=1 set in wl_screen_create_internals); the
* direct wl_focus_set() call is no longer needed here. */
@ -4177,10 +4170,12 @@ wl_frame_paint(struct WFrameWindow *fwin)
/* Commit the buffer to the scene graph only if it has content (resizebar). */
if (fb->scene_buf) {
if (show_resizebar)
if (show_resizebar) {
wlr_scene_node_set_enabled(&fb->scene_buf->node, true);
wlr_scene_buffer_set_buffer(fb->scene_buf, &fb->base);
else
} else {
wlr_scene_node_set_enabled(&fb->scene_buf->node, false);
}
}
return 1;
@ -4275,7 +4270,6 @@ wl_focus_set(WNativeWindow win, int revert_to, unsigned long timestamp)
wlr_seat_keyboard_notify_enter(wl_state.seat,
v->xdg_surface->surface,
NULL, 0, NULL);
wwarning("wl_backend: focus_set id=0x%lx", win);
}
/* ------------------------------------------------------------------ */
@ -4909,7 +4903,6 @@ handle_pointer_button(struct wl_listener *listener, void *data)
* returns it first on subsequent hits. */
wl_list_remove(&view->link);
wl_list_insert(&wl_state.toplevel_list, &view->link);
wwarning("wl_backend: click focus id=0x%lx", view->id);
}
}
}
@ -5751,8 +5744,11 @@ wl_window_map(WNativeWindow win)
struct wl_toplevel_view *v = wl_find_view_by_id(win);
if (v && v->scene_node) {
wlr_scene_node_set_enabled(&v->scene_node->node, true);
wlr_scene_node_raise_to_top(&v->scene_node->node);
return;
}
if (v)
return;
/* Frame buffer: enable its scene node and children. */
struct wl_frame_buf *fb = frame_buf_find(win);
if (fb && fb->scene_buf) {

View File

@ -1079,7 +1079,7 @@ static void updateStateHint(WWindow *wwin, Bool changedWorkspace, Bool del)
if (wwin->flags.fullscreen)
state[i++] = net_wm_state_fullscreen;
if (wwin->flags.focused)
state[i++] = net_wm_state_focused;
state[i++] = net_wm_state_focused;
XChangeProperty(dpy, wwin->client_win, net_wm_state, WA_ATOM, 32,
PropModeReplace, (unsigned char *)state, i);
@ -1232,6 +1232,7 @@ static int getWindowLayer(WWindow *wwin)
static void doStateAtom(WWindow *wwin, Atom state, int set, Bool init)
{
wwarning("doStateAtom");
if (state == net_wm_state_sticky) {
if (set == _NET_WM_STATE_TOGGLE)
set = !IS_OMNIPRESENT(wwin);