diff --git a/Makefile b/Makefile index d7b0a66..014f7ec 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ dwl: dwl.o util.o $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ dwl.o: dwl.c client.h config.h config.mk patches.h cursor-shape-v1-protocol.h \ pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ + wlr-foreign-toplevel-management-unstable-v1-protocol.h \ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h util.o: util.c util.h @@ -45,6 +46,9 @@ wlr-output-power-management-unstable-v1-protocol.h: xdg-shell-protocol.h: $(WAYLAND_SCANNER) server-header \ $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ +wlr-foreign-toplevel-management-unstable-v1-protocol.h: + $(WAYLAND_SCANNER) server-header \ + protocols/wlr-foreign-toplevel-management-unstable-v1.xml $@ config.h: cp config.def.h $@ diff --git a/README.org b/README.org index 1e9f24c..ce1518f 100644 --- a/README.org +++ b/README.org @@ -9,6 +9,7 @@ - [[#patches][Patches]] - [[#attach-top][Attach Top]] - [[#auto-start][Auto Start]] + - [[#foreign-toplevel-management][Foreign Toplevel Management]] - [[#natural-scroll-trackpad][Natural Scroll Trackpad]] - [[#per-tag][Per Tag]] - [[#restore-monitor][Restore Monitor]] @@ -74,6 +75,14 @@ Note: Commands from array are executed using execvp(). So if you need to execute #define AUTOSTART_PATCH 1 #+END_SRC +** [[https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/foreign-toplevel-management][Foreign Toplevel Management]] + +Implement ~foreign-toplevel-management~, it add handlers for activate, close, fullscreen and destroy request events, it's missing minimize and maximize request handlers. + +#+BEGIN_SRC c :tangle patches.def.h +#define FOREIGN_TOPLEVEL_MANAGEMENT_PATCH 1 +#+END_SRC + ** [[https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/naturalscrolltrackpad][Natural Scroll Trackpad]] Set natural scrolling only for trackpads. diff --git a/dwl.c b/dwl.c index 1fcac5b..9624bee 100644 --- a/dwl.c +++ b/dwl.c @@ -1,6 +1,7 @@ /* * See LICENSE file for copyright and license details. */ +#include "patches.h" #include #include #include @@ -24,6 +25,9 @@ #include #include #include +#if FOREIGN_TOPLEVEL_MANAGEMENT_PATCH +#include +#endif // FOREIGN_TOPLEVEL_MANAGEMENT_PATCH #include #include #include @@ -67,7 +71,6 @@ #include #endif // XWAYLAND -#include "patches.h" #include "util.h" /* macros */ @@ -135,6 +138,13 @@ typedef struct { struct wl_listener fullscreen; struct wl_listener set_decoration_mode; struct wl_listener destroy_decoration; +#if FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel; + struct wl_listener factivate; + struct wl_listener fclose; + struct wl_listener ffullscreen; + struct wl_listener fdestroy; +#endif // FOREIGN_TOPLEVEL_MANAGEMENT_PATCH struct wlr_box prev; /* layout-relative, includes border */ struct wlr_box bounds; #ifdef XWAYLAND @@ -395,6 +405,13 @@ static Monitor *xytomon(double x, double y); static void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc, LayerSurface **pl, double *nx, double *ny); static void zoom(const Arg *arg); +#if FOREIGN_TOPLEVEL_MANAGEMENT_PATCH +static void createforeigntoplevel(Client *c); +static void factivatenotify(struct wl_listener *listener, void *data); +static void fclosenotify(struct wl_listener *listener, void *data); +static void fdestroynotify(struct wl_listener *listener, void *data); +static void ffullscreennotify(struct wl_listener *listener, void *data); +#endif // FOREIGN_TOPLEVEL_MANAGEMENT_PATCH /* variables */ static const char broken[] = "broken"; @@ -442,6 +459,10 @@ static struct wlr_scene_rect *locked_bg; static struct wlr_session_lock_v1 *cur_lock; static struct wl_listener lock_listener = {.notify = locksession}; +#if FOREIGN_TOPLEVEL_MANAGEMENT_PATCH +static struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_mgr; +#endif // FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + static struct wlr_seat *seat; static KeyboardGroup *kb_group; static unsigned int cursor_mode; @@ -525,6 +546,13 @@ applyrules(Client *c) if (!(title = client_get_title(c))) title = broken; +#if FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + if (c->foreign_toplevel) { + wlr_foreign_toplevel_handle_v1_set_app_id(c->foreign_toplevel, appid); + wlr_foreign_toplevel_handle_v1_set_title(c->foreign_toplevel, title); + } +#endif // FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + for (r = rules; r < END(rules); r++) { if ((!r->title || strstr(title, r->title)) && (!r->id || strstr(appid, r->id))) { @@ -1551,6 +1579,10 @@ focusclient(Client *c, int lift) client_set_border_color(old_c, bordercolor); client_activate_surface(old, 0); +#if FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + if (old_c->foreign_toplevel) + wlr_foreign_toplevel_handle_v1_set_activated(old_c->foreign_toplevel, 0); +#endif // FOREIGN_TOPLEVEL_MANAGEMENT_PATCH } } printstatus(); @@ -1569,6 +1601,10 @@ focusclient(Client *c, int lift) /* Activate the new client */ client_activate_surface(client_surface(c), 1); +#if FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + if (c->foreign_toplevel) + wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, 1); +#endif // FOREIGN_TOPLEVEL_MANAGEMENT_PATCH } void @@ -1990,6 +2026,10 @@ mapnotify(struct wl_listener *listener, void *data) c->border[i]->node.data = c; } +#if FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + createforeigntoplevel(c); +#endif // FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + /* Initialize client geometry with room for border */ client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); c->geom.width += 2 * c->bw; @@ -2720,12 +2760,24 @@ setmon(Client *c, Monitor *m, uint32_t newtags) c->prev = c->geom; /* Scene graph sends surface leave/enter events on move and resize */ +#if !FOREIGN_TOPLEVEL_MANAGEMENT_PATCH if (oldmon) arrange(oldmon); +#else // FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + if (oldmon) { + if (c->foreign_toplevel) + wlr_foreign_toplevel_handle_v1_output_leave(c->foreign_toplevel, oldmon->wlr_output); + arrange(oldmon); + } +#endif // FOREIGN_TOPLEVEL_MANAGEMENT_PATCH if (m) { /* Make sure window actually overlaps with the monitor */ resize(c, c->geom, 0); c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ +#if FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + if (c->foreign_toplevel) + wlr_foreign_toplevel_handle_v1_output_enter(c->foreign_toplevel, m->wlr_output); +#endif // FOREIGN_TOPLEVEL_MANAGEMENT_PATCH setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ setfloating(c, c->isfloating); } @@ -2843,6 +2895,11 @@ setup(void) power_mgr = wlr_output_power_manager_v1_create(dpy); LISTEN_STATIC(&power_mgr->events.set_mode, powermgrsetmode); +#if FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + /* Initializes foreign toplevel management */ + foreign_toplevel_mgr = wlr_foreign_toplevel_manager_v1_create(dpy); +#endif // FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + /* Creates an output layout, which a wlroots utility for working with an * arrangement of screens in a physical layout. */ output_layout = wlr_output_layout_create(dpy); @@ -3218,6 +3275,13 @@ unmapnotify(struct wl_listener *listener, void *data) wl_list_remove(&c->flink); } +#if FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + if (c->foreign_toplevel) { + wlr_foreign_toplevel_handle_v1_destroy(c->foreign_toplevel); + c->foreign_toplevel = NULL; + } +#endif // FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + wlr_scene_node_destroy(&c->scene->node); printstatus(); motionnotify(0, NULL, 0, 0, 0, 0); @@ -3333,6 +3397,14 @@ void updatetitle(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, set_title); +#if FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + if (c->foreign_toplevel) { + const char *title; + if (!(title = client_get_title(c))) + title = broken; + wlr_foreign_toplevel_handle_v1_set_title(c->foreign_toplevel, title); + } +#endif // FOREIGN_TOPLEVEL_MANAGEMENT_PATCH if (c == focustop(c->mon)) printstatus(); } @@ -3514,6 +3586,56 @@ zoom(const Arg *arg) arrange(selmon); } +#if FOREIGN_TOPLEVEL_MANAGEMENT_PATCH +void +createforeigntoplevel(Client *c) +{ + c->foreign_toplevel = wlr_foreign_toplevel_handle_v1_create(foreign_toplevel_mgr); + + LISTEN(&c->foreign_toplevel->events.request_activate, &c->factivate, factivatenotify); + LISTEN(&c->foreign_toplevel->events.request_close, &c->fclose, fclosenotify); + LISTEN(&c->foreign_toplevel->events.request_fullscreen, &c->ffullscreen, ffullscreennotify); + LISTEN(&c->foreign_toplevel->events.destroy, &c->fdestroy, fdestroynotify); +} + +void +factivatenotify(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, factivate); + if (c->mon == selmon) { + c->tags = c->mon->tagset[c->mon->seltags]; + } else { + setmon(c, selmon, 0); + } + focusclient(c, 1); + arrange(c->mon); +} + +void +fclosenotify(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, fclose); + client_send_close(c); +} + +void +ffullscreennotify(struct wl_listener *listener, void *data) { + Client *c = wl_container_of(listener, c, ffullscreen); + struct wlr_foreign_toplevel_handle_v1_fullscreen_event *event = data; + setfullscreen(c, event->fullscreen); +} + +void +fdestroynotify(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, fdestroy); + wl_list_remove(&c->factivate.link); + wl_list_remove(&c->fclose.link); + wl_list_remove(&c->ffullscreen.link); + wl_list_remove(&c->fdestroy.link); +} +#endif // FOREIGN_TOPLEVEL_MANAGEMENT_PATCH + #ifdef XWAYLAND void activatex11(struct wl_listener *listener, void *data) diff --git a/patches.def.h b/patches.def.h index 13e1a9b..6143c6f 100644 --- a/patches.def.h +++ b/patches.def.h @@ -2,6 +2,8 @@ #define AUTOSTART_PATCH 1 +#define FOREIGN_TOPLEVEL_MANAGEMENT_PATCH 1 + #define NATURALSCROLLTRACKPAD_PATCH 1 #define PERTAG_PATCH 1 diff --git a/patches/foreign-toplevel-management-20240502.patch b/patches/foreign-toplevel-management-20240502.patch new file mode 100644 index 0000000..3dfa14f --- /dev/null +++ b/patches/foreign-toplevel-management-20240502.patch @@ -0,0 +1,507 @@ +From dc63d64cd69f515013464b3feb8acb411f5a348f Mon Sep 17 00:00:00 2001 +From: wochap +Date: Thu, 2 May 2024 17:25:45 -0500 +Subject: [PATCH] implement foreign toplevel management + +--- + Makefile | 5 +- + dwl.c | 93 +++++- + ...oreign-toplevel-management-unstable-v1.xml | 270 ++++++++++++++++++ + 3 files changed, 366 insertions(+), 2 deletions(-) + create mode 100644 protocols/wlr-foreign-toplevel-management-unstable-v1.xml + +diff --git a/Makefile b/Makefile +index a67fdd3..e0e1260 100644 +--- a/Makefile ++++ b/Makefile +@@ -16,7 +16,7 @@ LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(LIBS) + all: dwl + dwl: dwl.o util.o + $(CC) dwl.o util.o $(LDLIBS) $(LDFLAGS) $(DWLCFLAGS) -o $@ +-dwl.o: dwl.c config.mk config.h client.h cursor-shape-v1-protocol.h pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h xdg-shell-protocol.h ++dwl.o: dwl.c config.mk config.h client.h cursor-shape-v1-protocol.h pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h xdg-shell-protocol.h wlr-foreign-toplevel-management-unstable-v1-protocol.h + util.o: util.c util.h + + # wayland-scanner is a tool which generates C headers and rigging for Wayland +@@ -37,6 +37,9 @@ wlr-layer-shell-unstable-v1-protocol.h: + xdg-shell-protocol.h: + $(WAYLAND_SCANNER) server-header \ + $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ ++wlr-foreign-toplevel-management-unstable-v1-protocol.h: ++ $(WAYLAND_SCANNER) server-header \ ++ protocols/wlr-foreign-toplevel-management-unstable-v1.xml $@ + + config.h: + cp config.def.h $@ +diff --git a/dwl.c b/dwl.c +index bf763df..648616d 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -126,6 +127,11 @@ typedef struct { + struct wl_listener fullscreen; + struct wl_listener set_decoration_mode; + struct wl_listener destroy_decoration; ++ struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel; ++ struct wl_listener factivate; ++ struct wl_listener fclose; ++ struct wl_listener ffullscreen; ++ struct wl_listener fdestroy; + struct wlr_box prev; /* layout-relative, includes border */ + struct wlr_box bounds; + #ifdef XWAYLAND +@@ -347,6 +353,11 @@ static Monitor *xytomon(double x, double y); + static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); + static void zoom(const Arg *arg); ++static void createforeigntoplevel(Client *c); ++static void factivatenotify(struct wl_listener *listener, void *data); ++static void fclosenotify(struct wl_listener *listener, void *data); ++static void fdestroynotify(struct wl_listener *listener, void *data); ++static void ffullscreennotify(struct wl_listener *listener, void *data); + + /* variables */ + static const char broken[] = "broken"; +@@ -392,6 +403,8 @@ static struct wlr_scene_rect *locked_bg; + static struct wlr_session_lock_v1 *cur_lock; + static struct wl_listener lock_listener = {.notify = locksession}; + ++static struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_mgr; ++ + static struct wlr_seat *seat; + static KeyboardGroup kb_group = {0}; + static KeyboardGroup vkb_group = {0}; +@@ -458,6 +471,11 @@ applyrules(Client *c) + if (!(title = client_get_title(c))) + title = broken; + ++ if (c->foreign_toplevel) { ++ wlr_foreign_toplevel_handle_v1_set_app_id(c->foreign_toplevel, appid); ++ wlr_foreign_toplevel_handle_v1_set_title(c->foreign_toplevel, title); ++ } ++ + for (r = rules; r < END(rules); r++) { + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { +@@ -1288,6 +1306,8 @@ focusclient(Client *c, int lift) + client_set_border_color(old_c, bordercolor); + + client_activate_surface(old, 0); ++ if (old_c->foreign_toplevel) ++ wlr_foreign_toplevel_handle_v1_set_activated(old_c->foreign_toplevel, 0); + } + } + printstatus(); +@@ -1306,6 +1326,8 @@ focusclient(Client *c, int lift) + + /* Activate the new client */ + client_activate_surface(client_surface(c), 1); ++ if (c->foreign_toplevel) ++ wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, 1); + } + + void +@@ -1599,6 +1621,8 @@ mapnotify(struct wl_listener *listener, void *data) + c->border[i]->node.data = c; + } + ++ createforeigntoplevel(c); ++ + /* Initialize client geometry with room for border */ + client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); + c->geom.width += 2 * c->bw; +@@ -2232,12 +2256,17 @@ setmon(Client *c, Monitor *m, uint32_t newtags) + c->prev = c->geom; + + /* Scene graph sends surface leave/enter events on move and resize */ +- if (oldmon) ++ if (oldmon) { ++ if (c->foreign_toplevel) ++ wlr_foreign_toplevel_handle_v1_output_leave(c->foreign_toplevel, oldmon->wlr_output); + arrange(oldmon); ++ } + if (m) { + /* Make sure window actually overlaps with the monitor */ + resize(c, c->geom, 0); + c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ ++ if (c->foreign_toplevel) ++ wlr_foreign_toplevel_handle_v1_output_enter(c->foreign_toplevel, m->wlr_output); + setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ + setfloating(c, c->isfloating); + } +@@ -2351,6 +2380,9 @@ setup(void) + gamma_control_mgr = wlr_gamma_control_manager_v1_create(dpy); + LISTEN_STATIC(&gamma_control_mgr->events.set_gamma, setgamma); + ++ /* Initializes foreign toplevel management */ ++ foreign_toplevel_mgr = wlr_foreign_toplevel_manager_v1_create(dpy); ++ + /* Creates an output layout, which a wlroots utility for working with an + * arrangement of screens in a physical layout. */ + output_layout = wlr_output_layout_create(); +@@ -2691,6 +2723,11 @@ unmapnotify(struct wl_listener *listener, void *data) + wl_list_remove(&c->flink); + } + ++ if (c->foreign_toplevel) { ++ wlr_foreign_toplevel_handle_v1_destroy(c->foreign_toplevel); ++ c->foreign_toplevel = NULL; ++ } ++ + wlr_scene_node_destroy(&c->scene->node); + printstatus(); + motionnotify(0, NULL, 0, 0, 0, 0); +@@ -2802,6 +2839,12 @@ void + updatetitle(struct wl_listener *listener, void *data) + { + Client *c = wl_container_of(listener, c, set_title); ++ if (c->foreign_toplevel) { ++ const char *title; ++ if (!(title = client_get_title(c))) ++ title = broken; ++ wlr_foreign_toplevel_handle_v1_set_title(c->foreign_toplevel, title); ++ } + if (c == focustop(c->mon)) + printstatus(); + } +@@ -2929,6 +2972,54 @@ zoom(const Arg *arg) + arrange(selmon); + } + ++void ++createforeigntoplevel(Client *c) ++{ ++ c->foreign_toplevel = wlr_foreign_toplevel_handle_v1_create(foreign_toplevel_mgr); ++ ++ LISTEN(&c->foreign_toplevel->events.request_activate, &c->factivate, factivatenotify); ++ LISTEN(&c->foreign_toplevel->events.request_close, &c->fclose, fclosenotify); ++ LISTEN(&c->foreign_toplevel->events.request_fullscreen, &c->ffullscreen, ffullscreennotify); ++ LISTEN(&c->foreign_toplevel->events.destroy, &c->fdestroy, fdestroynotify); ++} ++ ++void ++factivatenotify(struct wl_listener *listener, void *data) ++{ ++ Client *c = wl_container_of(listener, c, factivate); ++ if (c->mon == selmon) { ++ c->tags = c->mon->tagset[c->mon->seltags]; ++ } else { ++ setmon(c, selmon, 0); ++ } ++ focusclient(c, 1); ++ arrange(c->mon); ++} ++ ++void ++fclosenotify(struct wl_listener *listener, void *data) ++{ ++ Client *c = wl_container_of(listener, c, fclose); ++ client_send_close(c); ++} ++ ++void ++ffullscreennotify(struct wl_listener *listener, void *data) { ++ Client *c = wl_container_of(listener, c, ffullscreen); ++ struct wlr_foreign_toplevel_handle_v1_fullscreen_event *event = data; ++ setfullscreen(c, event->fullscreen); ++} ++ ++void ++fdestroynotify(struct wl_listener *listener, void *data) ++{ ++ Client *c = wl_container_of(listener, c, fdestroy); ++ wl_list_remove(&c->factivate.link); ++ wl_list_remove(&c->fclose.link); ++ wl_list_remove(&c->ffullscreen.link); ++ wl_list_remove(&c->fdestroy.link); ++} ++ + #ifdef XWAYLAND + void + activatex11(struct wl_listener *listener, void *data) +diff --git a/protocols/wlr-foreign-toplevel-management-unstable-v1.xml b/protocols/wlr-foreign-toplevel-management-unstable-v1.xml +new file mode 100644 +index 0000000..44505bb +--- /dev/null ++++ b/protocols/wlr-foreign-toplevel-management-unstable-v1.xml +@@ -0,0 +1,270 @@ ++ ++ ++ ++ Copyright © 2018 Ilia Bozhinov ++ ++ Permission to use, copy, modify, distribute, and sell this ++ software and its documentation for any purpose is hereby granted ++ without fee, provided that the above copyright notice appear in ++ all copies and that both that copyright notice and this permission ++ notice appear in supporting documentation, and that the name of ++ the copyright holders not be used in advertising or publicity ++ pertaining to distribution of the software without specific, ++ written prior permission. The copyright holders make no ++ representations about the suitability of this software for any ++ purpose. It is provided "as is" without express or implied ++ warranty. ++ ++ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS ++ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY ++ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN ++ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ++ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF ++ THIS SOFTWARE. ++ ++ ++ ++ ++ The purpose of this protocol is to enable the creation of taskbars ++ and docks by providing them with a list of opened applications and ++ letting them request certain actions on them, like maximizing, etc. ++ ++ After a client binds the zwlr_foreign_toplevel_manager_v1, each opened ++ toplevel window will be sent via the toplevel event ++ ++ ++ ++ ++ This event is emitted whenever a new toplevel window is created. It ++ is emitted for all toplevels, regardless of the app that has created ++ them. ++ ++ All initial details of the toplevel(title, app_id, states, etc.) will ++ be sent immediately after this event via the corresponding events in ++ zwlr_foreign_toplevel_handle_v1. ++ ++ ++ ++ ++ ++ ++ Indicates the client no longer wishes to receive events for new toplevels. ++ However the compositor may emit further toplevel_created events, until ++ the finished event is emitted. ++ ++ The client must not send any more requests after this one. ++ ++ ++ ++ ++ ++ This event indicates that the compositor is done sending events to the ++ zwlr_foreign_toplevel_manager_v1. The server will destroy the object ++ immediately after sending this request, so it will become invalid and ++ the client should free any resources associated with it. ++ ++ ++ ++ ++ ++ ++ A zwlr_foreign_toplevel_handle_v1 object represents an opened toplevel ++ window. Each app may have multiple opened toplevels. ++ ++ Each toplevel has a list of outputs it is visible on, conveyed to the ++ client with the output_enter and output_leave events. ++ ++ ++ ++ ++ This event is emitted whenever the title of the toplevel changes. ++ ++ ++ ++ ++ ++ ++ This event is emitted whenever the app-id of the toplevel changes. ++ ++ ++ ++ ++ ++ ++ This event is emitted whenever the toplevel becomes visible on ++ the given output. A toplevel may be visible on multiple outputs. ++ ++ ++ ++ ++ ++ ++ This event is emitted whenever the toplevel stops being visible on ++ the given output. It is guaranteed that an entered-output event ++ with the same output has been emitted before this event. ++ ++ ++ ++ ++ ++ ++ Requests that the toplevel be maximized. If the maximized state actually ++ changes, this will be indicated by the state event. ++ ++ ++ ++ ++ ++ Requests that the toplevel be unmaximized. If the maximized state actually ++ changes, this will be indicated by the state event. ++ ++ ++ ++ ++ ++ Requests that the toplevel be minimized. If the minimized state actually ++ changes, this will be indicated by the state event. ++ ++ ++ ++ ++ ++ Requests that the toplevel be unminimized. If the minimized state actually ++ changes, this will be indicated by the state event. ++ ++ ++ ++ ++ ++ Request that this toplevel be activated on the given seat. ++ There is no guarantee the toplevel will be actually activated. ++ ++ ++ ++ ++ ++ ++ The different states that a toplevel can have. These have the same meaning ++ as the states with the same names defined in xdg-toplevel ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ This event is emitted immediately after the zlw_foreign_toplevel_handle_v1 ++ is created and each time the toplevel state changes, either because of a ++ compositor action or because of a request in this protocol. ++ ++ ++ ++ ++ ++ ++ ++ This event is sent after all changes in the toplevel state have been ++ sent. ++ ++ This allows changes to the zwlr_foreign_toplevel_handle_v1 properties ++ to be seen as atomic, even if they happen via multiple events. ++ ++ ++ ++ ++ ++ Send a request to the toplevel to close itself. The compositor would ++ typically use a shell-specific method to carry out this request, for ++ example by sending the xdg_toplevel.close event. However, this gives ++ no guarantees the toplevel will actually be destroyed. If and when ++ this happens, the zwlr_foreign_toplevel_handle_v1.closed event will ++ be emitted. ++ ++ ++ ++ ++ ++ The rectangle of the surface specified in this request corresponds to ++ the place where the app using this protocol represents the given toplevel. ++ It can be used by the compositor as a hint for some operations, e.g ++ minimizing. The client is however not required to set this, in which ++ case the compositor is free to decide some default value. ++ ++ If the client specifies more than one rectangle, only the last one is ++ considered. ++ ++ The dimensions are given in surface-local coordinates. ++ Setting width=height=0 removes the already-set rectangle. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ This event means the toplevel has been destroyed. It is guaranteed there ++ won't be any more events for this zwlr_foreign_toplevel_handle_v1. The ++ toplevel itself becomes inert so any requests will be ignored except the ++ destroy request. ++ ++ ++ ++ ++ ++ Destroys the zwlr_foreign_toplevel_handle_v1 object. ++ ++ This request should be called either when the client does not want to ++ use the toplevel anymore or after the closed event to finalize the ++ destruction of the object. ++ ++ ++ ++ ++ ++ ++ ++ Requests that the toplevel be fullscreened on the given output. If the ++ fullscreen state and/or the outputs the toplevel is visible on actually ++ change, this will be indicated by the state and output_enter/leave ++ events. ++ ++ The output parameter is only a hint to the compositor. Also, if output ++ is NULL, the compositor should decide which output the toplevel will be ++ fullscreened on, if at all. ++ ++ ++ ++ ++ ++ ++ Requests that the toplevel be unfullscreened. If the fullscreen state ++ actually changes, this will be indicated by the state event. ++ ++ ++ ++ ++ ++ ++ ++ This event is emitted whenever the parent of the toplevel changes. ++ ++ No event is emitted when the parent handle is destroyed by the client. ++ ++ ++ ++ ++ +-- +2.43.2 + diff --git a/protocols/wlr-foreign-toplevel-management-unstable-v1.xml b/protocols/wlr-foreign-toplevel-management-unstable-v1.xml new file mode 100644 index 0000000..44505bb --- /dev/null +++ b/protocols/wlr-foreign-toplevel-management-unstable-v1.xml @@ -0,0 +1,270 @@ + + + + Copyright © 2018 Ilia Bozhinov + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + THIS SOFTWARE. + + + + + The purpose of this protocol is to enable the creation of taskbars + and docks by providing them with a list of opened applications and + letting them request certain actions on them, like maximizing, etc. + + After a client binds the zwlr_foreign_toplevel_manager_v1, each opened + toplevel window will be sent via the toplevel event + + + + + This event is emitted whenever a new toplevel window is created. It + is emitted for all toplevels, regardless of the app that has created + them. + + All initial details of the toplevel(title, app_id, states, etc.) will + be sent immediately after this event via the corresponding events in + zwlr_foreign_toplevel_handle_v1. + + + + + + + Indicates the client no longer wishes to receive events for new toplevels. + However the compositor may emit further toplevel_created events, until + the finished event is emitted. + + The client must not send any more requests after this one. + + + + + + This event indicates that the compositor is done sending events to the + zwlr_foreign_toplevel_manager_v1. The server will destroy the object + immediately after sending this request, so it will become invalid and + the client should free any resources associated with it. + + + + + + + A zwlr_foreign_toplevel_handle_v1 object represents an opened toplevel + window. Each app may have multiple opened toplevels. + + Each toplevel has a list of outputs it is visible on, conveyed to the + client with the output_enter and output_leave events. + + + + + This event is emitted whenever the title of the toplevel changes. + + + + + + + This event is emitted whenever the app-id of the toplevel changes. + + + + + + + This event is emitted whenever the toplevel becomes visible on + the given output. A toplevel may be visible on multiple outputs. + + + + + + + This event is emitted whenever the toplevel stops being visible on + the given output. It is guaranteed that an entered-output event + with the same output has been emitted before this event. + + + + + + + Requests that the toplevel be maximized. If the maximized state actually + changes, this will be indicated by the state event. + + + + + + Requests that the toplevel be unmaximized. If the maximized state actually + changes, this will be indicated by the state event. + + + + + + Requests that the toplevel be minimized. If the minimized state actually + changes, this will be indicated by the state event. + + + + + + Requests that the toplevel be unminimized. If the minimized state actually + changes, this will be indicated by the state event. + + + + + + Request that this toplevel be activated on the given seat. + There is no guarantee the toplevel will be actually activated. + + + + + + + The different states that a toplevel can have. These have the same meaning + as the states with the same names defined in xdg-toplevel + + + + + + + + + + + This event is emitted immediately after the zlw_foreign_toplevel_handle_v1 + is created and each time the toplevel state changes, either because of a + compositor action or because of a request in this protocol. + + + + + + + + This event is sent after all changes in the toplevel state have been + sent. + + This allows changes to the zwlr_foreign_toplevel_handle_v1 properties + to be seen as atomic, even if they happen via multiple events. + + + + + + Send a request to the toplevel to close itself. The compositor would + typically use a shell-specific method to carry out this request, for + example by sending the xdg_toplevel.close event. However, this gives + no guarantees the toplevel will actually be destroyed. If and when + this happens, the zwlr_foreign_toplevel_handle_v1.closed event will + be emitted. + + + + + + The rectangle of the surface specified in this request corresponds to + the place where the app using this protocol represents the given toplevel. + It can be used by the compositor as a hint for some operations, e.g + minimizing. The client is however not required to set this, in which + case the compositor is free to decide some default value. + + If the client specifies more than one rectangle, only the last one is + considered. + + The dimensions are given in surface-local coordinates. + Setting width=height=0 removes the already-set rectangle. + + + + + + + + + + + + + + + + This event means the toplevel has been destroyed. It is guaranteed there + won't be any more events for this zwlr_foreign_toplevel_handle_v1. The + toplevel itself becomes inert so any requests will be ignored except the + destroy request. + + + + + + Destroys the zwlr_foreign_toplevel_handle_v1 object. + + This request should be called either when the client does not want to + use the toplevel anymore or after the closed event to finalize the + destruction of the object. + + + + + + + + Requests that the toplevel be fullscreened on the given output. If the + fullscreen state and/or the outputs the toplevel is visible on actually + change, this will be indicated by the state and output_enter/leave + events. + + The output parameter is only a hint to the compositor. Also, if output + is NULL, the compositor should decide which output the toplevel will be + fullscreened on, if at all. + + + + + + + Requests that the toplevel be unfullscreened. If the fullscreen state + actually changes, this will be indicated by the state event. + + + + + + + + This event is emitted whenever the parent of the toplevel changes. + + No event is emitted when the parent handle is destroyed by the client. + + + + +