diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 5ed8926..18b5333 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -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++;