wayland: handle XWayland fullscreen requests

The XWayland backend was not listening for request_fullscreen events
from wlr_xwayland_surface. Wine/Proton games that request fullscreen
via _NET_WM_STATE_FULLSCREEN had the signal silently ignored, leaving
them in a tiny window.

Add handle_xwayland_request_fullscreen listener that calls
wFullscreenWindow/wUnfullscreenWindow, matching the XDG toplevel path.
This commit is contained in:
lkn 2026-06-27 14:45:07 +02:00
parent 53d8d82e3a
commit 5b5617844a
8 changed files with 62 additions and 10 deletions

View File

@ -503,7 +503,7 @@ AUTOMAKE = ${SHELL} '/home/lkn/src/wmaker/missing' automake-1.18
AWK = gawk
CC = gcc
CCDEPMODE = depmode=gcc3
CFLAGS = -g -O2 -Wall -Wextra -Wno-sign-compare -Werror=trampolines -Wno-deprecated -Wno-deprecated-declarations
CFLAGS = -O0 -g -fsanitize=address -fno-omit-frame-pointer -Wall -Wextra -Wno-sign-compare -Werror=trampolines -Wno-deprecated -Wno-deprecated-declarations
CPP = gcc -E
CPPFLAGS = -DNDEBUG -D_XOPEN_SOURCE=700 -D_GNU_SOURCE
CSCOPE = cscope
@ -535,7 +535,7 @@ INSTALL_SCRIPT = ${INSTALL}
INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
INTLIBS =
LD = /usr/x86_64-pc-linux-gnu/bin/ld -m elf_x86_64
LDFLAGS =
LDFLAGS = -fsanitize=address
LIBBSD =
LIBEXIF =
LIBM = -lm

View File

@ -243,7 +243,8 @@ void paint_app_icon(WApplication *wapp)
wapp->app_icon->next == NULL && wapp->app_icon->prev == NULL)
add_to_appicon_list(scr, wapp->app_icon);
if (!attracting_dock || !wapp->app_icon->attracted || !attracting_dock->collapsed)
if (!WFLAGP(wapp->main_window_desc, no_appicon) &&
(!attracting_dock || !wapp->app_icon->attracted || !attracting_dock->collapsed))
wm_backend->window_map((WNativeWindow)icon->core->window);
if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)

View File

@ -149,6 +149,13 @@ WApplication *wApplicationCreate(WWindow * wwin)
/* application descriptor */
wm_backend->context_save(main_window, WM_CTX_APP_WIN, wapp);
/* add to the per-screen application list */
wapp->next = scr->wapp_list;
wapp->prev = NULL;
if (scr->wapp_list)
scr->wapp_list->prev = wapp;
scr->wapp_list = wapp;
create_appicon_for_application(wapp, wwin);
return wapp;

View File

@ -16,8 +16,6 @@ void wl_event_flush(void)
(!wl_state.session || wl_state.session->active)) {
wlr_scene_output_commit(wl_state.scene_output, NULL);
wl_display_flush_clients(wl_state.display);
struct wl_event_loop *loop = wl_display_get_event_loop(wl_state.display);
wl_event_loop_dispatch(loop, 0);
}
}
void wl_event_flush_expose(void) {}

View File

@ -291,6 +291,7 @@ handle_toplevel_map(struct wl_listener *listener, void *data)
wwin->client_flags.no_close_button = 1;
wwin->client_flags.no_miniaturize_button = 1;
wwin->client_flags.no_resizebar = 1;
wwin->client_flags.no_appicon = 1;
wwin->client_flags.skip_window_list = 1;
wwin->client_flags.skip_switchpanel = 1;
wwin->user_flags = wwin->client_flags;

View File

@ -30,6 +30,8 @@ void wm_dock_app_remove(WNativeWindow id);
void wl_pointer_warp_to(int x, int y);
extern void W_UnregisterBacking(unsigned long id);
struct wl_frame_buf *frame_buf_find(WNativeWindow id);
void wFullscreenWindow(WWindow *wwin);
void wUnfullscreenWindow(WWindow *wwin);
#define VIEW_FROM_LISTENER(ptr, field) \
((struct wl_toplevel_view *)((char *)(ptr) - offsetof(struct wl_toplevel_view, field)))
@ -96,6 +98,24 @@ handle_or_set_geometry(struct wl_listener *listener, void *data)
/* --- Managed XWayland surface handlers --- */
static void
handle_xwayland_request_fullscreen(struct wl_listener *listener, void *data)
{
struct wl_toplevel_view *view = VIEW_FROM_LISTENER(listener, request_fullscreen_listener);
(void)data;
WObjDescriptor *desc = wm_backend->context_find(view->id, WM_CTX_CLIENT_WIN);
if (!desc || desc->parent_type != WCLASS_WINDOW)
return;
WWindow *wwin = (WWindow *)desc->parent;
if (view->xw_surface->fullscreen) {
if (!wwin->flags.fullscreen)
wFullscreenWindow(wwin);
} else {
if (wwin->flags.fullscreen)
wUnfullscreenWindow(wwin);
}
}
static void
handle_xwayland_set_geometry(struct wl_listener *listener, void *data)
{
@ -152,6 +172,9 @@ handle_xwayland_surface_map(struct wl_listener *listener, void *data)
int cy = view->y + wwin->client.height / 2;
wl_pointer_warp_to(cx, cy);
wm_dock_app_add(view);
if (xw->fullscreen && !wwin->flags.fullscreen)
wFullscreenWindow(wwin);
}
}
}
@ -221,6 +244,7 @@ handle_xwayland_destroy(struct wl_listener *listener, void *data)
wl_list_remove(&view->unmap_listener.link);
wl_list_remove(&view->destroy_listener.link);
wl_list_remove(&view->title_listener.link);
wl_list_remove(&view->request_fullscreen_listener.link);
if (view->xw_surface_map_listener.link.next &&
view->xw_surface_map_listener.link.next != &view->xw_surface_map_listener.link)
wl_list_remove(&view->xw_surface_map_listener.link);
@ -384,12 +408,14 @@ handle_xwayland_new_surface(struct wl_listener *listener, void *data)
view->destroy_listener.notify = handle_xwayland_destroy;
view->title_listener.notify = handle_xwayland_set_class;
view->xw_geometry_listener.notify = handle_xwayland_set_geometry;
view->request_fullscreen_listener.notify = handle_xwayland_request_fullscreen;
wl_signal_add(&xw->events.associate, &view->map_listener);
wl_signal_add(&xw->events.dissociate, &view->unmap_listener);
wl_signal_add(&xw->events.destroy, &view->destroy_listener);
wl_signal_add(&xw->events.set_class, &view->title_listener);
wl_signal_add(&xw->events.set_geometry, &view->xw_geometry_listener);
wl_signal_add(&xw->events.request_fullscreen, &view->request_fullscreen_listener);
wl_list_insert(&wl_state.toplevel_list, &view->link);
wl_state.managed_surface_count++;

View File

@ -1587,6 +1587,8 @@ int wKeyboardMoveResizeWindow(WWindow * wwin)
}
}
wm_backend->server_ungrab();
if (ctrlmode) {
showGeometry(wwin, src_x + off_x, src_y + off_y, src_x + off_x + ww, src_y + off_y + wh,
0);
@ -1594,12 +1596,12 @@ int wKeyboardMoveResizeWindow(WWindow * wwin)
showPosition(wwin, src_x + off_x, src_y + off_y);
if (opaqueMoveResize) {
wm_backend->server_ungrab();
wWindowConfigure(wwin, src_x + off_x, src_y + off_y, ww, wh - vert_border);
};
if (done) {
if (!opaqueMoveResize) { /* ctrlmode => resize */
wm_backend->server_grab();
if (wwin->flags.shaded || scr->selected_windows) {
if (scr->selected_windows)
drawFrames(wwin, scr->selected_windows, off_x, off_y);
@ -1608,6 +1610,7 @@ int wKeyboardMoveResizeWindow(WWindow * wwin)
} else {
drawTransparentFrame(wwin, src_x + off_x, src_y + off_y, ww, wh);
}
wm_backend->server_ungrab();
}
if (ctrlmode) {
@ -1619,7 +1622,6 @@ int wKeyboardMoveResizeWindow(WWindow * wwin)
wm_backend->keyboard_ungrab();
wm_backend->pointer_ungrab(0);
wm_backend->server_ungrab();
if (done == 2) {
if (wwin->flags.shaded || scr->selected_windows) {
@ -1754,8 +1756,8 @@ int wMouseMoveWindow(WWindow * wwin, WMEvent * ev)
moveData.winWidth, moveData.winHeight);
if (wPreferences.move_display == WDIS_NEW && !scr->selected_windows) {
wm_backend->server_grab();
showPosition(wwin, moveData.realX, moveData.realY);
wm_backend->server_grab();
}
if (!opaqueMove) {
@ -1871,11 +1873,12 @@ int wMouseMoveWindow(WWindow * wwin, WMEvent * ev)
if (started && !opaqueMove)
drawFrames(wwin, scr->selected_windows, 0, 0);
if (wPreferences.move_display == WDIS_NEW
&& !scr->selected_windows)
showPosition(wwin, moveData.realX, moveData.realY);
if (!opaqueMove || (wPreferences.move_display == WDIS_NEW
&& !scr->selected_windows)) {
wm_backend->server_grab();
if (wPreferences.move_display == WDIS_NEW)
showPosition(wwin, moveData.realX, moveData.realY);
}
}

View File

@ -767,6 +767,19 @@ WWindow *wManageWindow(WScreen *scr, WNativeWindow window)
break;
}
}
/* Also search existing WApplications: catches peers that mapped
* before this window is in focused_window (startup ordering). */
if (wwin->main_window == wwin->client_win) {
WApplication *wapp;
for (wapp = scr->wapp_list; wapp; wapp = wapp->next) {
WWindow *leader = wWindowFor(wapp->main_window);
if (leader && leader->wm_class
&& strcmp(leader->wm_class, wwin->wm_class) == 0) {
wwin->main_window = wapp->main_window;
break;
}
}
}
}
}
@ -1200,6 +1213,9 @@ WWindow *wManageWindow(WScreen *scr, WNativeWindow window)
wWindowSynthConfigureNotify(wwin);
}
/* Wayland popup windows must not get an appicon. */
if (wwin->wm_class && strcmp(wwin->wm_class, "wings-popup") == 0)
wwin->client_flags.no_appicon = 1;
/* Setup descriptors and save window to internal lists */
if (wwin->main_window != WM_NATIVE_NONE) {
WApplication *app;