wayland: Phase 16 — handle request_maximize, request_fullscreen, request_minimize, set_app_id

Wire xdg-toplevel event listeners for the remaining lifecycle events:
- request_maximize: toggles wMaximizeWindow / wUnmaximizeWindow
- request_fullscreen: calls wFullscreenWindow
- request_minimize: calls wIconifyWindow
- set_app_id: updates wwin->wm_class when the app changes its app_id

Include actions.h and xinerama.h for the WM action function declarations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Levi Neely 2026-03-28 21:08:34 +01:00
parent 9ca0bdcdf1
commit c2c5027610
1 changed files with 94 additions and 10 deletions

View File

@ -94,6 +94,8 @@
#include "../../WindowMaker.h"
#include "../../screen.h"
#include "../../window.h"
#include "../../actions.h" /* Phase 16: wMaximizeWindow, wIconifyWindow, etc. */
#include "../../xinerama.h" /* Phase 16: wGetHeadForWindow */
#include "../../xmodifier.h" /* Phase 77: wSetModifierMasks */
#include "../../event.h" /* Phase 78: wWaylandKeyPress */
#include "../backend.h"
@ -114,8 +116,12 @@ struct wl_toplevel_view {
struct wl_listener unmap_listener;
struct wl_listener destroy_listener;
struct wl_listener title_listener; /* Phase 46: xdg_toplevel set_title */
struct wl_listener request_move_listener; /* Phase 15 */
struct wl_listener request_resize_listener; /* Phase 15 */
struct wl_listener request_move_listener; /* Phase 15 */
struct wl_listener request_resize_listener; /* Phase 15 */
struct wl_listener request_maximize_listener; /* Phase 16 */
struct wl_listener request_fullscreen_listener;/* Phase 16 */
struct wl_listener request_minimize_listener; /* Phase 16 */
struct wl_listener set_app_id_listener; /* Phase 16 */
WNativeWindow id; /* synthetic handle, >= 0x10000000 */
int x, y; /* Phase 55: WM-assigned position */
long *wm_state; /* Phase 56: saved WM state or NULL */
@ -293,6 +299,76 @@ handle_toplevel_request_resize(struct wl_listener *listener, void *data)
wwarning("wl_backend: request_resize id=0x%lx (no-op in headless mode)", view->id);
}
/*
* Phase 16: xdg_toplevel request_maximize — toggle maximize state.
*/
static void
handle_toplevel_request_maximize(struct wl_listener *listener, void *data)
{
struct wl_toplevel_view *view = VIEW_FROM_LISTENER(listener, request_maximize_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 (wwin->flags.maximized)
wUnmaximizeWindow(wwin);
else
wMaximizeWindow(wwin, MAX_VERTICAL | MAX_HORIZONTAL, wGetHeadForWindow(wwin));
}
/*
* Phase 16: xdg_toplevel request_fullscreen.
*/
static void
handle_toplevel_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 (!wwin->flags.fullscreen)
wFullscreenWindow(wwin);
}
/*
* Phase 16: xdg_toplevel request_minimize — iconify the window.
*/
static void
handle_toplevel_request_minimize(struct wl_listener *listener, void *data)
{
struct wl_toplevel_view *view = VIEW_FROM_LISTENER(listener, request_minimize_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 (!wwin->flags.miniaturized)
wIconifyWindow(wwin);
}
/*
* Phase 16: xdg_toplevel set_app_id — update wm_class.
*/
static void
handle_toplevel_set_app_id(struct wl_listener *listener, void *data)
{
struct wl_toplevel_view *view = VIEW_FROM_LISTENER(listener, set_app_id_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;
const char *app_id = view->xdg_surface->toplevel->app_id;
if (!app_id)
return;
if (wwin->wm_class)
wfree(wwin->wm_class);
wwin->wm_class = strdup(app_id);
}
/*
* Phase 38: toplevel map — surface is ready to be managed.
*/
@ -435,15 +511,23 @@ handle_xdg_new_surface(struct wl_listener *listener, void *data)
view->unmap_listener.notify = handle_toplevel_unmap;
view->destroy_listener.notify = handle_toplevel_destroy;
view->title_listener.notify = handle_toplevel_title;
view->request_move_listener.notify = handle_toplevel_request_move; /* Phase 15 */
view->request_resize_listener.notify = handle_toplevel_request_resize; /* Phase 15 */
view->request_move_listener.notify = handle_toplevel_request_move; /* Phase 15 */
view->request_resize_listener.notify = handle_toplevel_request_resize; /* Phase 15 */
view->request_maximize_listener.notify = handle_toplevel_request_maximize; /* Phase 16 */
view->request_fullscreen_listener.notify = handle_toplevel_request_fullscreen; /* Phase 16 */
view->request_minimize_listener.notify = handle_toplevel_request_minimize; /* Phase 16 */
view->set_app_id_listener.notify = handle_toplevel_set_app_id; /* Phase 16 */
wl_signal_add(&xdg_surface->events.map, &view->map_listener);
wl_signal_add(&xdg_surface->events.unmap, &view->unmap_listener);
wl_signal_add(&xdg_surface->events.destroy, &view->destroy_listener);
wl_signal_add(&xdg_surface->toplevel->events.set_title, &view->title_listener);
wl_signal_add(&xdg_surface->toplevel->events.request_move, &view->request_move_listener);
wl_signal_add(&xdg_surface->toplevel->events.request_resize, &view->request_resize_listener);
wl_signal_add(&xdg_surface->events.map, &view->map_listener);
wl_signal_add(&xdg_surface->events.unmap, &view->unmap_listener);
wl_signal_add(&xdg_surface->events.destroy, &view->destroy_listener);
wl_signal_add(&xdg_surface->toplevel->events.set_title, &view->title_listener);
wl_signal_add(&xdg_surface->toplevel->events.request_move, &view->request_move_listener);
wl_signal_add(&xdg_surface->toplevel->events.request_resize, &view->request_resize_listener);
wl_signal_add(&xdg_surface->toplevel->events.request_maximize, &view->request_maximize_listener);
wl_signal_add(&xdg_surface->toplevel->events.request_fullscreen, &view->request_fullscreen_listener);
wl_signal_add(&xdg_surface->toplevel->events.request_minimize, &view->request_minimize_listener);
wl_signal_add(&xdg_surface->toplevel->events.set_app_id, &view->set_app_id_listener);
wl_list_insert(&wl_state.toplevel_list, &view->link);
wl_state.managed_surface_count++;