From d8cf65c74f3b7132302027cfbf940de8548d7d17 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sat, 22 May 2021 21:18:48 -0500 Subject: [PATCH] implement urgency hint --- README.md | 2 +- dwl.c | 50 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 51aecf8..dc75cef 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ dwl is not meant to provide every feature under the sun. Instead, like dwm, it s - Configurable multi-monitor layout support, including position and rotation - Configurable HiDPI/multi-DPI support - Provide information to external status bars via stdout/stdin +- Urgency hints via xdg-activate protocol - Various Wayland protocols - XWayland support as provided by wlroots (can be enabled in `config.mk`) - Zero flickering - Wayland users naturally expect that "every frame is perfect" @@ -22,7 +23,6 @@ dwl is not meant to provide every feature under the sun. Instead, like dwm, it s Features under consideration (possibly as patches) are: - Protocols made trivial by wlroots -- Implement urgent/focus-request once the xdg-activation protocol [hits wlroots](https://github.com/swaywm/wlroots/pull/2718) - Implement the input-inhibitor protocol to support screen lockers - Implement the idle-inhibit protocol which lets applications such as mpv disable idle monitoring - Layer shell popups (used by Waybar) diff --git a/dwl.c b/dwl.c index d7e798b..4d0bc84 100644 --- a/dwl.c +++ b/dwl.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -107,7 +108,7 @@ typedef struct { #endif int bw; unsigned int tags; - int isfloating; + int isfloating, isurgent; uint32_t resize; /* configure serial of a pending resize */ int prevx; int prevy; @@ -290,6 +291,7 @@ static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); static void unmapnotify(struct wl_listener *listener, void *data); static void updatemons(struct wl_listener *listener, void *data); static void updatetitle(struct wl_listener *listener, void *data); +static void urgent(struct wl_listener *listener, void *data); static void view(const Arg *arg); static void virtualkeyboard(struct wl_listener *listener, void *data); static Client *xytoclient(double x, double y); @@ -306,6 +308,7 @@ static struct wlr_renderer *drw; static struct wlr_compositor *compositor; static struct wlr_xdg_shell *xdg_shell; +static struct wlr_xdg_activation_v1 *activation; static struct wl_list clients; /* tiling order */ static struct wl_list fstack; /* focus order */ static struct wl_list stack; /* stacking z-order */ @@ -347,6 +350,7 @@ static struct wl_listener new_xdg_surface = {.notify = createnotify}; static struct wl_listener new_layer_shell_surface = {.notify = createlayersurface}; static struct wl_listener output_mgr_apply = {.notify = outputmgrapply}; static struct wl_listener output_mgr_test = {.notify = outputmgrtest}; +static struct wl_listener request_activate = {.notify = urgent}; static struct wl_listener request_cursor = {.notify = setcursor}; static struct wl_listener request_set_psel = {.notify = setpsel}; static struct wl_listener request_set_sel = {.notify = setsel}; @@ -1078,6 +1082,7 @@ focusclient(Client *c, int lift) wl_list_remove(&c->flink); wl_list_insert(&fstack, &c->flink); selmon = c->mon; + c->isurgent = 0; } printstatus(); @@ -1550,22 +1555,29 @@ void printstatus(void) { Monitor *m = NULL; - Client *c = NULL; - unsigned int activetags; + Client *c; + unsigned int occ, urg, sel; wl_list_for_each(m, &mons, link) { - activetags=0; + occ = urg = 0; wl_list_for_each(c, &clients, link) { - if (c->mon == m) - activetags |= c->tags; + if (c->mon != m) + continue; + occ |= c->tags; + if (c->isurgent) + urg |= c->tags; } - if (focustop(m)) + if ((c = focustop(m))) { printf("%s title %s\n", m->wlr_output->name, client_get_title(focustop(m))); - else + sel = c->tags; + } else { printf("%s title \n", m->wlr_output->name); + sel = 0; + } printf("%s selmon %u\n", m->wlr_output->name, m == selmon); - printf("%s tags %u %u\n", m->wlr_output->name, activetags, m->tagset[m->seltags]); + printf("%s tags %u %u %u %u\n", m->wlr_output->name, occ, m->tagset[m->seltags], + sel, urg); printf("%s layout %s\n", m->wlr_output->name, m->lt[m->sellt]->symbol); } fflush(stdout); @@ -1825,6 +1837,7 @@ run(char *startup_cmd) } /* If nobody is reading the status output, don't terminate */ signal(SIGPIPE, SIG_IGN); + printstatus(); /* Run the Wayland event loop. This does not return until you exit the * compositor. Starting the backend rigged up all of the necessary event @@ -1997,6 +2010,10 @@ setup(void) wlr_primary_selection_v1_device_manager_create(dpy); wlr_viewporter_create(dpy); + /* Initializes the interface used to implement urgency hints */ + activation = wlr_xdg_activation_v1_create(dpy); + wl_signal_add(&activation->events.request_activate, &request_activate); + /* 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(); @@ -2310,6 +2327,21 @@ updatetitle(struct wl_listener *listener, void *data) printstatus(); } +void +urgent(struct wl_listener *listener, void *data) +{ + struct wlr_xdg_activation_v1_request_activate_event *event = data; + Client *c; + + if (!wlr_surface_is_xdg_surface(event->surface)) + return; + c = wlr_xdg_surface_from_wlr_surface(event->surface)->data; + if (c != selclient()) { + c->isurgent = 1; + printstatus(); + } +} + void view(const Arg *arg) {