From 0dea553428c8c534ea8bbb914b1ec775cf36e4d5 Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Sun, 20 Mar 2022 19:09:28 -0600 Subject: destroy scene_output in cleanupmon() --- dwl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index 01f51ad..74f8549 100644 --- a/dwl.c +++ b/dwl.c @@ -703,6 +703,7 @@ cleanupmon(struct wl_listener *listener, void *data) wl_list_remove(&m->frame.link); wl_list_remove(&m->link); wlr_output_layout_remove(output_layout, m->wlr_output); + wlr_scene_output_destroy(m->scene_output); if ((nmons = wl_list_length(&mons))) do /* don't switch to disabled mons */ -- cgit v1.2.3 From 2bc01debdcf2c6cf13583c6a67f8a6a824446408 Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Mon, 21 Mar 2022 13:28:44 -0600 Subject: remove a useless resize in mapnotify() applyrules() calls setmon() which calls resize() --- dwl.c | 1 - 1 file changed, 1 deletion(-) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index 74f8549..0b82e42 100644 --- a/dwl.c +++ b/dwl.c @@ -1359,7 +1359,6 @@ mapnotify(struct wl_listener *listener, void *data) /* Set initial monitor, tags, floating status, and focus */ applyrules(c); - resize(c, c->geom.x, c->geom.y, c->geom.width, c->geom.height, 0); printstatus(); if (c->isfullscreen) -- cgit v1.2.3 From ee1a72211d066de3766980d0452945df0a50334c Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Mon, 21 Mar 2022 21:17:58 -0600 Subject: only skip frames if there are visible clients that have a resize --- dwl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index 0b82e42..cd9e8d5 100644 --- a/dwl.c +++ b/dwl.c @@ -1624,9 +1624,11 @@ rendermon(struct wl_listener *listener, void *data) int skip = 0; struct timespec now; - /* Render if no XDG clients have an outstanding resize. */ + /* Render if no XDG clients have an outstanding resize and are visible on + * this monitor. + */ wl_list_for_each(c, &clients, link) - skip = skip || c->resize; + skip = skip || (c->resize && VISIBLEON(c, m)); if (!skip && !wlr_scene_output_commit(m->scene_output)) return; -- cgit v1.2.3 From 330792b1fc37db86743d7c186577776e05295e00 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Mon, 21 Mar 2022 23:03:52 +0100 Subject: implement drag and drop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For brevity, only a single drag icon at a time is supported. Co-authored-by: Leonardo Hernández Hernández --- dwl.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index cd9e8d5..22287fb 100644 --- a/dwl.c +++ b/dwl.c @@ -227,6 +227,7 @@ static void cursorframe(struct wl_listener *listener, void *data); static void destroylayersurfacenotify(struct wl_listener *listener, void *data); static void destroynotify(struct wl_listener *listener, void *data); static Monitor *dirtomon(enum wlr_direction dir); +static void dragicondestroy(struct wl_listener *listener, void *data); static void focusclient(Client *c, int lift); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); @@ -254,6 +255,7 @@ static void printstatus(void); static void quit(const Arg *arg); static void quitsignal(int signo); static void rendermon(struct wl_listener *listener, void *data); +static void requeststartdrag(struct wl_listener *listener, void *data); static void resize(Client *c, int x, int y, int w, int h, int interact); static void run(char *startup_cmd); static Client *selclient(void); @@ -268,6 +270,7 @@ static void setmon(Client *c, Monitor *m, unsigned int newtags); static void setup(void); static void sigchld(int unused); static void spawn(const Arg *arg); +static void startdrag(struct wl_listener *listener, void *data); static void tag(const Arg *arg); static void tagmon(const Arg *arg); static void tile(Monitor *m); @@ -340,6 +343,9 @@ 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}; +static struct wl_listener request_start_drag = {.notify = requeststartdrag}; +static struct wl_listener start_drag = {.notify = startdrag}; +static struct wl_listener drag_icon_destroy = {.notify = dragicondestroy}; #ifdef XWAYLAND static void activatex11(struct wl_listener *listener, void *data); @@ -1023,6 +1029,16 @@ destroynotify(struct wl_listener *listener, void *data) free(c); } +void +dragicondestroy(struct wl_listener *listener, void *data) +{ + struct wlr_drag_icon *icon = data; + wlr_scene_node_destroy(icon->data); + // Focus enter isn't sent during drag, so refocus the focused node. + focusclient(selclient(), 1); + motionnotify(0); +} + void togglefullscreen(const Arg *arg) { @@ -1400,11 +1416,16 @@ motionnotify(uint32_t time) /* time is 0 in internal calls meant to restore pointer focus. */ if (time) { + struct wlr_drag_icon *icon; wlr_idle_notify_activity(idle, seat); /* Update selmon (even while dragging a window) */ if (sloppyfocus) selmon = xytomon(cursor->x, cursor->y); + + if (seat->drag && (icon = seat->drag->icon)) + wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->sx, + cursor->y + icon->surface->sy); } /* If we are currently grabbing the mouse, handle and return */ @@ -1665,6 +1686,18 @@ resize(Client *c, int x, int y, int w, int h, int interact) c->geom.height - 2 * c->bw); } +void +requeststartdrag(struct wl_listener *listener, void *data) +{ + struct wlr_seat_request_start_drag_event *event = data; + + if (wlr_seat_validate_pointer_grab_serial(seat, event->origin, + event->serial)) + wlr_seat_start_pointer_drag(seat, event->drag, event->serial); + else + wlr_data_source_destroy(event->drag->source); +} + void run(char *startup_cmd) { @@ -1976,6 +2009,8 @@ setup(void) wl_signal_add(&seat->events.request_set_cursor, &request_cursor); wl_signal_add(&seat->events.request_set_selection, &request_set_sel); wl_signal_add(&seat->events.request_set_primary_selection, &request_set_psel); + wl_signal_add(&seat->events.request_start_drag, &request_start_drag); + wl_signal_add(&seat->events.start_drag, &start_drag); output_mgr = wlr_output_manager_v1_create(dpy); wl_signal_add(&output_mgr->events.apply, &output_mgr_apply); @@ -2026,6 +2061,19 @@ spawn(const Arg *arg) } } +void +startdrag(struct wl_listener *listener, void *data) +{ + struct wlr_drag *drag = data; + + if (!drag->icon) + return; + + drag->icon->data = wlr_scene_subsurface_tree_create(layers[LyrTop], drag->icon->surface); + wlr_scene_node_raise_to_top(drag->icon->data); + wl_signal_add(&drag->icon->events.destroy, &drag_icon_destroy); +} + void tag(const Arg *arg) { -- cgit v1.2.3 From 9aec6049ecbefe3618f34002d2239cc9462c07e9 Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Tue, 22 Mar 2022 15:02:02 -0600 Subject: clients now works as expected in drag motion --- dwl.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index 22287fb..f8d01f2 100644 --- a/dwl.c +++ b/dwl.c @@ -1416,16 +1416,11 @@ motionnotify(uint32_t time) /* time is 0 in internal calls meant to restore pointer focus. */ if (time) { - struct wlr_drag_icon *icon; wlr_idle_notify_activity(idle, seat); /* Update selmon (even while dragging a window) */ if (sloppyfocus) selmon = xytomon(cursor->x, cursor->y); - - if (seat->drag && (icon = seat->drag->icon)) - wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->sx, - cursor->y + icon->surface->sy); } /* If we are currently grabbing the mouse, handle and return */ @@ -1564,6 +1559,7 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, { struct timespec now; int internal_call = !time; + struct wlr_drag_icon *icon; if (sloppyfocus && !internal_call && c && !client_is_unmanaged(c)) focusclient(c, 0); @@ -1585,6 +1581,13 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); + /* If there are is a drag icon, update its position */ + /* For anyone who wants to change this function: for some reason + * (maybe a wlroots bug?, or is it intended?) if we change the node position + * before telling the seat for a motion, the clients don't recognize the drag */ + if (seat->drag && (icon = seat->drag->icon)) + wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->sx, + cursor->y + icon->surface->sy); } void -- cgit v1.2.3 From 326eee14445f8a2c08e80c30778445630c75d3bb Mon Sep 17 00:00:00 2001 From: Quentin Rameau Date: Mon, 12 Jul 2021 23:44:16 +0200 Subject: Add a configuration option for fullscreen locking Some people are annoyed to have this new behaviour forced for some application which use fake fullscreen. --- config.def.h | 1 + dwl.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'dwl.c') diff --git a/config.def.h b/config.def.h index 8408659..539dba6 100644 --- a/config.def.h +++ b/config.def.h @@ -1,6 +1,7 @@ /* appearance */ static const int sloppyfocus = 1; /* focus follows mouse */ static const unsigned int borderpx = 1; /* border pixel of windows */ +static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ static const float rootcolor[] = {0.3, 0.3, 0.3, 1.0}; static const float bordercolor[] = {0.5, 0.5, 0.5, 1.0}; static const float focuscolor[] = {1.0, 0.0, 0.0, 1.0}; diff --git a/dwl.c b/dwl.c index f8d01f2..9ea44e2 100644 --- a/dwl.c +++ b/dwl.c @@ -1177,7 +1177,7 @@ focusstack(const Arg *arg) { /* Focus the next or previous client (in tiling order) on selmon */ Client *c, *sel = selclient(); - if (!sel) + if (!sel || (sel->isfullscreen && lockfullscreen)) return; if (arg->i > 0) { wl_list_for_each(c, &sel->link, link) { -- cgit v1.2.3 From 7d724dc7f34561e7a6d4ab97ff24b07805593f63 Mon Sep 17 00:00:00 2001 From: Palanix Date: Mon, 28 Feb 2022 23:46:24 +0100 Subject: Fix dwl freezing when resizing --- dwl.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index 9ea44e2..3185062 100644 --- a/dwl.c +++ b/dwl.c @@ -178,6 +178,7 @@ struct Monitor { unsigned int tagset[2]; double mfact; int nmaster; + int un_map; /* If a map/unmap happened on this monitor, then this should be true */ }; typedef struct { @@ -1379,6 +1380,8 @@ mapnotify(struct wl_listener *listener, void *data) if (c->isfullscreen) setfullscreen(c, 1); + + c->mon->un_map = 1; } void @@ -1648,17 +1651,27 @@ rendermon(struct wl_listener *listener, void *data) int skip = 0; struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + /* Render if no XDG clients have an outstanding resize and are visible on - * this monitor. - */ - wl_list_for_each(c, &clients, link) - skip = skip || (c->resize && VISIBLEON(c, m)); + * this monitor. */ + /* Checking m->un_map for every client is not optimal but works */ + wl_list_for_each(c, &clients, link) { + if ((c->resize && m->un_map) || (c->type == XDGShell + && (c->surface.xdg->pending.geometry.width != + c->surface.xdg->current.geometry.width + || c->surface.xdg->pending.geometry.height != + c->surface.xdg->current.geometry.height))) { + /* Lie */ + wlr_surface_send_frame_done(client_surface(c), &now); + skip = 1; + } + } if (!skip && !wlr_scene_output_commit(m->scene_output)) return; - /* Let clients know a frame has been rendered */ - clock_gettime(CLOCK_MONOTONIC, &now); wlr_scene_output_send_frame_done(m->scene_output, &now); + m->un_map = 0; } void @@ -2196,6 +2209,9 @@ unmapnotify(struct wl_listener *listener, void *data) grabc = NULL; } + if (c->mon) + c->mon->un_map = 1; + if (client_is_unmanaged(c)) { wlr_scene_node_destroy(c->scene); return; -- cgit v1.2.3 From 3bace9ce6b9d5fa7c8871a414ed97976e44ecb9c Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Wed, 23 Mar 2022 22:01:04 +0100 Subject: inline the presentation variable This variable can be removed since with scene-graph wlr_presentation_surface_sampled_on_output no longer needs to be called. --- dwl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index 3185062..65d1381 100644 --- a/dwl.c +++ b/dwl.c @@ -309,7 +309,6 @@ static struct wl_list fstack; /* focus order */ static struct wlr_idle *idle; static struct wlr_layer_shell_v1 *layer_shell; static struct wlr_output_manager_v1 *output_mgr; -static struct wlr_presentation *presentation; static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; static struct wlr_cursor *cursor; @@ -2032,8 +2031,7 @@ setup(void) wl_signal_add(&output_mgr->events.apply, &output_mgr_apply); wl_signal_add(&output_mgr->events.test, &output_mgr_test); - presentation = wlr_presentation_create(dpy, backend); - wlr_scene_set_presentation(scene, presentation); + wlr_scene_set_presentation(scene, wlr_presentation_create(dpy, backend)); #ifdef XWAYLAND /* -- cgit v1.2.3 From 7a2e0eef746950f6ac0863dcbb5c957836a6d8fc Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Wed, 23 Mar 2022 12:13:49 -0600 Subject: Revert "clients now works as expected in drag motion" This reverts commit 9aec6049ecbefe3618f34002d2239cc9462c07e9. this problem is caused because xytonode() returns the surface of the drag icon --- dwl.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index 65d1381..ce53dfa 100644 --- a/dwl.c +++ b/dwl.c @@ -1418,11 +1418,16 @@ motionnotify(uint32_t time) /* time is 0 in internal calls meant to restore pointer focus. */ if (time) { + struct wlr_drag_icon *icon; wlr_idle_notify_activity(idle, seat); /* Update selmon (even while dragging a window) */ if (sloppyfocus) selmon = xytomon(cursor->x, cursor->y); + + if (seat->drag && (icon = seat->drag->icon)) + wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->sx, + cursor->y + icon->surface->sy); } /* If we are currently grabbing the mouse, handle and return */ @@ -1561,7 +1566,6 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, { struct timespec now; int internal_call = !time; - struct wlr_drag_icon *icon; if (sloppyfocus && !internal_call && c && !client_is_unmanaged(c)) focusclient(c, 0); @@ -1583,13 +1587,6 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); - /* If there are is a drag icon, update its position */ - /* For anyone who wants to change this function: for some reason - * (maybe a wlroots bug?, or is it intended?) if we change the node position - * before telling the seat for a motion, the clients don't recognize the drag */ - if (seat->drag && (icon = seat->drag->icon)) - wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->sx, - cursor->y + icon->surface->sy); } void -- cgit v1.2.3 From bf8cc526deab39e269da219667ae24b6f8adecc7 Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Wed, 23 Mar 2022 14:18:38 -0600 Subject: set position of the drag icon in startdrag() --- dwl.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index ce53dfa..536b4d6 100644 --- a/dwl.c +++ b/dwl.c @@ -1415,21 +1415,20 @@ motionnotify(uint32_t time) double sx = 0, sy = 0; Client *c = NULL; struct wlr_surface *surface = NULL; + struct wlr_drag_icon *icon; /* time is 0 in internal calls meant to restore pointer focus. */ if (time) { - struct wlr_drag_icon *icon; wlr_idle_notify_activity(idle, seat); /* Update selmon (even while dragging a window) */ if (sloppyfocus) selmon = xytomon(cursor->x, cursor->y); - - if (seat->drag && (icon = seat->drag->icon)) - wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->sx, - cursor->y + icon->surface->sy); } + if (seat->drag && (icon = seat->drag->icon)) + wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->sx, + cursor->y + icon->surface->sy); /* If we are currently grabbing the mouse, handle and return */ if (cursor_mode == CurMove) { /* Move the grabbed client to the new position. */ @@ -2081,7 +2080,7 @@ startdrag(struct wl_listener *listener, void *data) return; drag->icon->data = wlr_scene_subsurface_tree_create(layers[LyrTop], drag->icon->surface); - wlr_scene_node_raise_to_top(drag->icon->data); + motionnotify(0); wl_signal_add(&drag->icon->events.destroy, &drag_icon_destroy); } -- cgit v1.2.3 From feb972acd0ea130bc3af0f0f7072a70fa3c786bc Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Wed, 23 Mar 2022 13:50:08 -0600 Subject: fix drag icon's surface returned by xytonode --- dwl.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index 536b4d6..f8c2264 100644 --- a/dwl.c +++ b/dwl.c @@ -67,7 +67,7 @@ /* enums */ enum { CurNormal, CurMove, CurResize }; /* cursor */ enum { XDGShell, LayerShell, X11Managed, X11Unmanaged }; /* client types */ -enum { LyrBg, LyrBottom, LyrTop, LyrOverlay, LyrTile, LyrFloat, NUM_LAYERS }; /* scene layers */ +enum { LyrBg, LyrBottom, LyrTop, LyrOverlay, LyrTile, LyrFloat, LyrNoFocus, NUM_LAYERS }; /* scene layers */ #ifdef XWAYLAND enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ @@ -1911,6 +1911,7 @@ setup(void) layers[LyrFloat] = &wlr_scene_tree_create(&scene->node)->node; layers[LyrTop] = &wlr_scene_tree_create(&scene->node)->node; layers[LyrOverlay] = &wlr_scene_tree_create(&scene->node)->node; + layers[LyrNoFocus] = &wlr_scene_tree_create(&scene->node)->node; /* Create a renderer with the default implementation */ if (!(drw = wlr_renderer_autocreate(backend))) @@ -2079,7 +2080,7 @@ startdrag(struct wl_listener *listener, void *data) if (!drag->icon) return; - drag->icon->data = wlr_scene_subsurface_tree_create(layers[LyrTop], drag->icon->surface); + drag->icon->data = wlr_scene_subsurface_tree_create(layers[LyrNoFocus], drag->icon->surface); motionnotify(0); wl_signal_add(&drag->icon->events.destroy, &drag_icon_destroy); } @@ -2308,17 +2309,23 @@ xytonode(double x, double y, struct wlr_surface **psurface, struct wlr_surface *surface = NULL; Client *c = NULL; LayerSurface *l = NULL; - - if ((node = wlr_scene_node_at(&scene->node, x, y, nx, ny))) { - if (node->type == WLR_SCENE_NODE_SURFACE) - surface = wlr_scene_surface_from_node(node)->surface; - /* Walk the tree to find a node that knows the client */ - for (pnode = node; pnode && !c; pnode = pnode->parent) - c = pnode->data; - if (c && c->type == LayerShell) { - c = NULL; - l = pnode->data; + int i; + int focus_order[] = { LyrOverlay, LyrTop, LyrFloat, LyrTile, LyrBottom, LyrBg }; + + for (i = 0; i < LENGTH(focus_order); i++) { + if ((node = wlr_scene_node_at(layers[focus_order[i]], x, y, nx, ny))) { + if (node->type == WLR_SCENE_NODE_SURFACE) + surface = wlr_scene_surface_from_node(node)->surface; + /* Walk the tree to find a node that knows the client */ + for (pnode = node; pnode && !c; pnode = pnode->parent) + c = pnode->data; + if (c && c->type == LayerShell) { + c = NULL; + l = pnode->data; + } } + if (surface) + break; } if (psurface) *psurface = surface; -- cgit v1.2.3 From ae614ee5125891a4d75fac97c754207f97834a7d Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Mon, 12 Jul 2021 19:58:55 -0500 Subject: implement idle-inhibitor protocol This allows clients to disable idle monitoring --- README.md | 2 +- dwl.c | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) (limited to 'dwl.c') diff --git a/README.md b/README.md index 13a0000..22172d5 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ dwl is not meant to provide every feature under the sun. Instead, like dwm, it s - Any features provided by dwm/Xlib: simple window borders, tags, keybindings, client rules, mouse move/resize. Providing a built-in status bar is an exception to this goal, to avoid dependencies on font rendering and/or drawing libraries when an external bar could work well. - Configurable multi-monitor layout support, including position and rotation - Configurable HiDPI/multi-DPI support +- Idle-inhibit protocol which lets applications such as mpv disable idle monitoring - Provide information to external status bars via stdout/stdin - Urgency hints via xdg-activate protocol - Various Wayland protocols @@ -26,7 +27,6 @@ Features under consideration (possibly as patches) are: - Protocols made trivial by wlroots - Implement the input-inhibitor protocol to support screen lockers (see https://github.com/djpohly/dwl/pull/132) -- Implement the idle-inhibit protocol which lets applications such as mpv disable idle monitoring (see https://github.com/djpohly/dwl/pull/133) - Implement the text-input and input-method protocols to support IME once ibus implements input-method v2 (see https://github.com/ibus/ibus/pull/2256 and https://github.com/djpohly/dwl/pull/12) Feature *non-goals* for the main codebase include: diff --git a/dwl.c b/dwl.c index f8c2264..01d165b 100644 --- a/dwl.c +++ b/dwl.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -219,12 +220,14 @@ static void cleanupmon(struct wl_listener *listener, void *data); static void closemon(Monitor *m); static void commitlayersurfacenotify(struct wl_listener *listener, void *data); static void commitnotify(struct wl_listener *listener, void *data); +static void createidleinhibitor(struct wl_listener *listener, void *data); static void createkeyboard(struct wlr_input_device *device); static void createmon(struct wl_listener *listener, void *data); static void createnotify(struct wl_listener *listener, void *data); static void createlayersurface(struct wl_listener *listener, void *data); static void createpointer(struct wlr_input_device *device); static void cursorframe(struct wl_listener *listener, void *data); +static void destroyidleinhibitor(struct wl_listener *listener, void *data); static void destroylayersurfacenotify(struct wl_listener *listener, void *data); static void destroynotify(struct wl_listener *listener, void *data); static Monitor *dirtomon(enum wlr_direction dir); @@ -307,6 +310,7 @@ static struct wlr_xdg_activation_v1 *activation; static struct wl_list clients; /* tiling order */ static struct wl_list fstack; /* focus order */ static struct wlr_idle *idle; +static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr; static struct wlr_layer_shell_v1 *layer_shell; static struct wlr_output_manager_v1 *output_mgr; static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; @@ -331,6 +335,8 @@ static struct wl_listener cursor_button = {.notify = buttonpress}; static struct wl_listener cursor_frame = {.notify = cursorframe}; static struct wl_listener cursor_motion = {.notify = motionrelative}; static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute}; +static struct wl_listener idle_inhibitor_create = {.notify = createidleinhibitor}; +static struct wl_listener idle_inhibitor_destroy = {.notify = destroyidleinhibitor}; static struct wl_listener layout_change = {.notify = updatemons}; static struct wl_listener new_input = {.notify = inputdevice}; static struct wl_listener new_virtual_keyboard = {.notify = virtualkeyboard}; @@ -769,6 +775,15 @@ commitnotify(struct wl_listener *listener, void *data) c->resize = 0; } +void +createidleinhibitor(struct wl_listener *listener, void *data) +{ + struct wlr_idle_inhibitor_v1 *idle_inhibitor = data; + wl_signal_add(&idle_inhibitor->events.destroy, &idle_inhibitor_destroy); + + wlr_idle_set_enabled(idle, seat, 0); +} + void createkeyboard(struct wlr_input_device *device) { @@ -988,6 +1003,14 @@ cursorframe(struct wl_listener *listener, void *data) wlr_seat_pointer_notify_frame(seat); } +void +destroyidleinhibitor(struct wl_listener *listener, void *data) +{ + /* I've been testing and at this point the inhibitor has not yet been + * removed from the list, checking if it has at least one item. */ + wlr_idle_set_enabled(idle, seat, wl_list_length(&idle_inhibit_mgr->inhibitors) <= 1); +} + void destroylayersurfacenotify(struct wl_listener *listener, void *data) { @@ -1147,6 +1170,7 @@ focusclient(Client *c, int lift) } printstatus(); + wlr_idle_set_enabled(idle, seat, wl_list_empty(&idle_inhibit_mgr->inhibitors)); if (!c) { /* With no client, all we have left is to clear focus */ @@ -1963,6 +1987,9 @@ setup(void) idle = wlr_idle_create(dpy); + idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy); + wl_signal_add(&idle_inhibit_mgr->events.new_inhibitor, &idle_inhibitor_create); + layer_shell = wlr_layer_shell_v1_create(dpy); wl_signal_add(&layer_shell->events.new_surface, &new_layer_shell_surface); -- cgit v1.2.3 From a95338ca43c7b979ef81fb9d6b0c561beda93be2 Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Sat, 3 Jul 2021 15:48:40 -0500 Subject: implement input-inhibitor protocol --- README.md | 2 +- dwl.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'dwl.c') diff --git a/README.md b/README.md index 22172d5..72488e3 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ dwl is not meant to provide every feature under the sun. Instead, like dwm, it s - Idle-inhibit protocol which lets applications such as mpv disable idle monitoring - Provide information to external status bars via stdout/stdin - Urgency hints via xdg-activate protocol +- Support screen lockers via input-inhibitor 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" @@ -26,7 +27,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 the input-inhibitor protocol to support screen lockers (see https://github.com/djpohly/dwl/pull/132) - Implement the text-input and input-method protocols to support IME once ibus implements input-method v2 (see https://github.com/ibus/ibus/pull/2256 and https://github.com/djpohly/dwl/pull/12) Feature *non-goals* for the main codebase include: diff --git a/dwl.c b/dwl.c index 01d165b..1bee09c 100644 --- a/dwl.c +++ b/dwl.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -311,6 +312,7 @@ static struct wl_list clients; /* tiling order */ static struct wl_list fstack; /* focus order */ static struct wlr_idle *idle; static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr; +static struct wlr_input_inhibit_manager *input_inhibit_mgr; static struct wlr_layer_shell_v1 *layer_shell; static struct wlr_output_manager_v1 *output_mgr; static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; @@ -1309,8 +1311,10 @@ keypress(struct wl_listener *listener, void *data) wlr_idle_notify_activity(idle, seat); - /* On _press_, attempt to process a compositor keybinding. */ - if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) + /* On _press_ if there is no active screen locker, + * attempt to process a compositor keybinding. */ + if (!input_inhibit_mgr->active_inhibitor + && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) for (i = 0; i < nsyms; i++) handled = keybinding(mods, syms[i]) || handled; @@ -1996,6 +2000,8 @@ setup(void) xdg_shell = wlr_xdg_shell_create(dpy); wl_signal_add(&xdg_shell->events.new_surface, &new_xdg_surface); + input_inhibit_mgr = wlr_input_inhibit_manager_create(dpy); + /* Use decoration protocols to negotiate server-side decorations */ wlr_server_decoration_manager_set_default_mode( wlr_server_decoration_manager_create(dpy), -- cgit v1.2.3 From cb4265ac8c48faeac385b038b59ac53a736d142d Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Thu, 24 Mar 2022 14:19:08 -0600 Subject: check `m` in commitlayersurfacenotify() --- dwl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index 1bee09c..529dbf8 100644 --- a/dwl.c +++ b/dwl.c @@ -755,9 +755,8 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data) wlr_scene_node_reparent(layersurface->scene, layers[wlr_layer_surface->current.layer]); - if (!wlr_output) + if (!wlr_output || !(m = wlr_output->data)) return; - m = wlr_output->data; if (layers[wlr_layer_surface->current.layer] != layersurface->scene) { wl_list_remove(&layersurface->link); -- cgit v1.2.3 From aab397c30b9b9e4223a4f408431eb3aa5521cb92 Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Tue, 15 Mar 2022 15:52:26 -0600 Subject: new functions ecalloc() and die() die() replaces EBARF and BARF and allow us to add `-pedantic` to CFLAGS --- Makefile | 4 ++-- config.mk | 2 +- dwl.c | 46 ++++++++++++++++++---------------------------- util.c | 35 +++++++++++++++++++++++++++++++++++ util.h | 4 ++++ 5 files changed, 60 insertions(+), 31 deletions(-) create mode 100644 util.c create mode 100644 util.h (limited to 'dwl.c') diff --git a/Makefile b/Makefile index 536454f..bba8c9f 100644 --- a/Makefile +++ b/Makefile @@ -59,6 +59,6 @@ idle-protocol.o: idle-protocol.h config.h: | config.def.h cp config.def.h $@ -dwl.o: config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h idle-protocol.h +dwl.o: config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h idle-protocol.h util.h -dwl: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o idle-protocol.o +dwl: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o idle-protocol.o util.o diff --git a/config.mk b/config.mk index 960fc8a..ab61185 100644 --- a/config.mk +++ b/config.mk @@ -3,7 +3,7 @@ PREFIX = /usr/local MANDIR = $(PREFIX)/share/man # Default compile flags (overridable by environment) -CFLAGS ?= -g -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-unused-function -Wno-unused-variable -Wno-unused-result -Wdeclaration-after-statement +CFLAGS ?= -g -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-unused-function -Wno-unused-variable -Wno-unused-result -Wdeclaration-after-statement -pedantic # Uncomment to build XWayland support #CFLAGS += -DXWAYLAND diff --git a/dwl.c b/dwl.c index 529dbf8..a3b33aa 100644 --- a/dwl.c +++ b/dwl.c @@ -54,9 +54,9 @@ #include #endif +#include "util.h" + /* macros */ -#define BARF(fmt, ...) do { fprintf(stderr, fmt "\n", ##__VA_ARGS__); exit(EXIT_FAILURE); } while (0) -#define EBARF(fmt, ...) BARF(fmt ": %s", ##__VA_ARGS__, strerror(errno)) #define MAX(A, B) ((A) > (B) ? (A) : (B)) #define MIN(A, B) ((A) < (B) ? (A) : (B)) #define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) @@ -790,9 +790,7 @@ createkeyboard(struct wlr_input_device *device) { struct xkb_context *context; struct xkb_keymap *keymap; - Keyboard *kb = device->data = calloc(1, sizeof(*kb)); - if (!kb) - EBARF("createkeyboard: calloc"); + Keyboard *kb = device->data = ecalloc(1, sizeof(*kb)); kb->device = device; /* Prepare an XKB keymap and assign it to the keyboard. */ @@ -823,9 +821,7 @@ createmon(struct wl_listener *listener, void *data) * monitor) becomes available. */ struct wlr_output *wlr_output = data; const MonitorRule *r; - Monitor *m = wlr_output->data = calloc(1, sizeof(*m)); - if (!m) - EBARF("createmon: calloc"); + Monitor *m = wlr_output->data = ecalloc(1, sizeof(*m)); m->wlr_output = wlr_output; wlr_output_init_render(wlr_output, alloc, drw); @@ -910,9 +906,7 @@ createnotify(struct wl_listener *listener, void *data) return; /* Allocate a Client for this surface */ - c = xdg_surface->data = calloc(1, sizeof(*c)); - if (!c) - EBARF("createnotify: calloc"); + c = xdg_surface->data = ecalloc(1, sizeof(*c)); c->surface.xdg = xdg_surface; c->bw = borderpx; @@ -938,9 +932,7 @@ createlayersurface(struct wl_listener *listener, void *data) wlr_layer_surface->output = selmon->wlr_output; } - layersurface = calloc(1, sizeof(LayerSurface)); - if (!layersurface) - EBARF("layersurface: calloc"); + layersurface = ecalloc(1, sizeof(LayerSurface)); layersurface->type = LayerShell; LISTEN(&wlr_layer_surface->surface->events.commit, &layersurface->surface_commit, commitlayersurfacenotify); @@ -1744,7 +1736,7 @@ run(char *startup_cmd) /* Add a Unix socket to the Wayland display. */ const char *socket = wl_display_add_socket_auto(dpy); if (!socket) - BARF("startup: display_add_socket_auto"); + die("startup: display_add_socket_auto"); setenv("WAYLAND_DISPLAY", socket, 1); /* Now that the socket exists, run the startup command */ @@ -1753,13 +1745,13 @@ run(char *startup_cmd) pipe(piperw); startup_pid = fork(); if (startup_pid < 0) - EBARF("startup: fork"); + die("startup: fork:"); if (startup_pid == 0) { dup2(piperw[0], STDIN_FILENO); close(piperw[0]); close(piperw[1]); execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL); - EBARF("startup: execl"); + die("startup: execl:"); } dup2(piperw[1], STDOUT_FILENO); close(piperw[1]); @@ -1772,7 +1764,7 @@ run(char *startup_cmd) /* Start the backend. This will enumerate outputs and inputs, become the DRM * master, etc */ if (!wlr_backend_start(backend)) - BARF("startup: backend_start"); + die("startup: backend_start"); /* Now that outputs are initialized, choose initial selmon based on * cursor position, and set default cursor image */ @@ -1928,7 +1920,7 @@ setup(void) * if the backend does not support hardware cursors (some older GPUs * don't). */ if (!(backend = wlr_backend_autocreate(dpy))) - BARF("couldn't create backend"); + die("couldn't create backend"); /* Initialize the scene graph used to lay out windows */ scene = wlr_scene_create(); @@ -1942,12 +1934,12 @@ setup(void) /* Create a renderer with the default implementation */ if (!(drw = wlr_renderer_autocreate(backend))) - BARF("couldn't create renderer"); + die("couldn't create renderer"); wlr_renderer_init_wl_display(drw, dpy); /* Create a default allocator */ if (!(alloc = wlr_allocator_autocreate(backend, drw))) - BARF("couldn't create allocator"); + die("couldn't create allocator"); /* This creates some hands-off wlroots interfaces. The compositor is * necessary for clients to allocate surfaces and the data device manager @@ -2088,7 +2080,7 @@ sigchld(int unused) * setting our own disposition for SIGCHLD. */ if (signal(SIGCHLD, sigchld) == SIG_ERR) - EBARF("can't install SIGCHLD handler"); + die("can't install SIGCHLD handler:"); while (0 < waitpid(-1, NULL, WNOHANG)) ; } @@ -2100,7 +2092,7 @@ spawn(const Arg *arg) dup2(STDERR_FILENO, STDOUT_FILENO); setsid(); execvp(((char **)arg->v)[0], (char **)arg->v); - EBARF("dwl: execvp %s failed", ((char **)arg->v)[0]); + die("dwl: execvp %s failed:", ((char **)arg->v)[0]); } } @@ -2435,9 +2427,7 @@ createnotifyx11(struct wl_listener *listener, void *data) setfullscreen(c, 0); /* Allocate a Client for this surface */ - c = xwayland_surface->data = calloc(1, sizeof(*c)); - if (!c) - EBARF("createnotifyx11: calloc"); + c = xwayland_surface->data = ecalloc(1, sizeof(*c)); c->surface.xwayland = xwayland_surface; c->type = xwayland_surface->override_redirect ? X11Unmanaged : X11Managed; c->bw = borderpx; @@ -2517,12 +2507,12 @@ main(int argc, char *argv[]) /* Wayland requires XDG_RUNTIME_DIR for creating its communications socket */ if (!getenv("XDG_RUNTIME_DIR")) - BARF("XDG_RUNTIME_DIR must be set"); + die("XDG_RUNTIME_DIR must be set"); setup(); run(startup_cmd); cleanup(); return EXIT_SUCCESS; usage: - BARF("Usage: %s [-s startup command]", argv[0]); + die("Usage: %s [-s startup command]", argv[0]); } diff --git a/util.c b/util.c new file mode 100644 index 0000000..932f89b --- /dev/null +++ b/util.c @@ -0,0 +1,35 @@ +/* See LICENSE.dwm file for copyright and license details. */ +#include +#include +#include +#include + +#include "util.h" + +void * +ecalloc(size_t nmemb, size_t size) +{ + void *p; + + if (!(p = calloc(nmemb, size))) + die("calloc:"); + return p; +} + +void +die(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else { + fputc('\n', stderr); + } + + exit(1); +} diff --git a/util.h b/util.h new file mode 100644 index 0000000..4c94117 --- /dev/null +++ b/util.h @@ -0,0 +1,4 @@ +/* See LICENSE.dwm file for copyright and license details. */ + +void die(const char *fmt, ...); +void *ecalloc(size_t nmemb, size_t size); -- cgit v1.2.3 From 79b7e755b010fc1486a89a46251a404cb97a341a Mon Sep 17 00:00:00 2001 From: Raphael Robatsch Date: Sat, 6 Nov 2021 19:51:17 +0100 Subject: Layer shell: Prevent infinte configure/commit loop Check the wlr_layer_surface_v1_state.committed bitmask to see if we need to rearrange. This is also what sway does. Without this check, every commit request (even if only the attached buffer changed) will lead to another configure event, which will lead to another commit, etc. This loop results in swaybg consuming 100% CPU. Co-authored-by: Owen Rafferty --- dwl.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index a3b33aa..bc74c96 100644 --- a/dwl.c +++ b/dwl.c @@ -140,6 +140,7 @@ typedef struct { typedef struct { /* Must be first */ unsigned int type; /* LayerShell */ + int mapped; struct wlr_scene_node *scene; struct wl_list link; struct wlr_layer_surface_v1 *layer_surface; @@ -758,6 +759,12 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data) if (!wlr_output || !(m = wlr_output->data)) return; + if (wlr_layer_surface->current.committed == 0 + && layersurface->mapped == wlr_layer_surface->mapped) + return; + + layersurface->mapped = wlr_layer_surface->mapped; + if (layers[wlr_layer_surface->current.layer] != layersurface->scene) { wl_list_remove(&layersurface->link); wl_list_insert(&m->layers[wlr_layer_surface->current.layer], -- cgit v1.2.3 From 4d3adea68325b70eafbd56a31023f96b92532b8d Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Thu, 31 Mar 2022 12:24:09 -0600 Subject: die on pipe failure --- dwl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index bc74c96..ac62120 100644 --- a/dwl.c +++ b/dwl.c @@ -1749,9 +1749,9 @@ run(char *startup_cmd) /* Now that the socket exists, run the startup command */ if (startup_cmd) { int piperw[2]; - pipe(piperw); - startup_pid = fork(); - if (startup_pid < 0) + if (pipe(piperw) < 0) + die("startup: pipe:"); + if ((startup_pid = fork()) < 0) die("startup: fork:"); if (startup_pid == 0) { dup2(piperw[0], STDIN_FILENO); -- cgit v1.2.3 From 720f56161e5401afc1526d1ebfb977b191ca10f5 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sun, 3 Apr 2022 00:01:52 -0500 Subject: Remove vestigial monitor configuration info The x/y fields in monitor rules are unused and were meant to be deleted. Also removes the outdated comment in config.h. --- config.def.h | 4 +--- dwl.c | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'dwl.c') diff --git a/config.def.h b/config.def.h index 00f6a85..7e61695 100644 --- a/config.def.h +++ b/config.def.h @@ -25,9 +25,7 @@ static const Layout layouts[] = { { "[M]", monocle }, }; -/* monitors - * The order in which monitors are defined determines their position. - * Non-configured monitors are always added to the left. */ +/* monitors */ static const MonitorRule monrules[] = { /* name mfact nmaster scale layout rotate/reflect x y */ /* example of a HiDPI laptop monitor: diff --git a/dwl.c b/dwl.c index ac62120..24d015f 100644 --- a/dwl.c +++ b/dwl.c @@ -191,8 +191,6 @@ typedef struct { float scale; const Layout *lt; enum wl_output_transform rr; - int x; - int y; } MonitorRule; typedef struct { -- cgit v1.2.3 From 02ac9378c4fb40969db6e897605016bbaf422961 Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Tue, 5 Apr 2022 22:07:20 -0500 Subject: includes: abc --- dwl.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index 24d015f..816eaa5 100644 --- a/dwl.c +++ b/dwl.c @@ -3,6 +3,7 @@ */ #define _POSIX_C_SOURCE 200809L #include +#include #include #include #include @@ -10,9 +11,9 @@ #include #include #include -#include #include #include +#include #include #include #include @@ -21,13 +22,12 @@ #include #include #include -#include -#include #include #include -#include +#include +#include #include -#include +#include #include #include #include @@ -35,10 +35,10 @@ #include #include #include -#include #include -#include +#include #include +#include #include #include #include @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #ifdef XWAYLAND -- cgit v1.2.3 From af741e586b80440b59b61e8fdc22c69fb7e8a457 Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Tue, 5 Apr 2022 22:15:46 -0500 Subject: typedefs: abc --- dwl.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index 816eaa5..424485f 100644 --- a/dwl.c +++ b/dwl.c @@ -120,6 +120,14 @@ typedef struct { int isfullscreen; } Client; +typedef struct { + uint32_t singular_anchor; + uint32_t anchor_triplet; + int *positive_axis; + int *negative_axis; + int margin; +} Edge; + typedef struct { uint32_t mod; xkb_keysym_t keysym; @@ -152,14 +160,6 @@ typedef struct { struct wlr_box geo; } LayerSurface; -typedef struct { - uint32_t singular_anchor; - uint32_t anchor_triplet; - int *positive_axis; - int *negative_axis; - int margin; -} Edge; - typedef struct { const char *symbol; void (*arrange)(Monitor *); -- cgit v1.2.3 From c00697e6438164e08baacc309b3dcdb727053aeb Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Tue, 5 Apr 2022 23:04:04 -0500 Subject: abc --- dwl.c | 238 +++++++++++++++++++++++++++++++++--------------------------------- 1 file changed, 119 insertions(+), 119 deletions(-) (limited to 'dwl.c') diff --git a/dwl.c b/dwl.c index 424485f..b09fc6f 100644 --- a/dwl.c +++ b/dwl.c @@ -221,9 +221,9 @@ static void commitlayersurfacenotify(struct wl_listener *listener, void *data); static void commitnotify(struct wl_listener *listener, void *data); static void createidleinhibitor(struct wl_listener *listener, void *data); static void createkeyboard(struct wlr_input_device *device); +static void createlayersurface(struct wl_listener *listener, void *data); static void createmon(struct wl_listener *listener, void *data); static void createnotify(struct wl_listener *listener, void *data); -static void createlayersurface(struct wl_listener *listener, void *data); static void createpointer(struct wlr_input_device *device); static void cursorframe(struct wl_listener *listener, void *data); static void destroyidleinhibitor(struct wl_listener *listener, void *data); @@ -234,8 +234,8 @@ static void dragicondestroy(struct wl_listener *listener, void *data); static void focusclient(Client *c, int lift); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); -static void fullscreennotify(struct wl_listener *listener, void *data); static Client *focustop(Monitor *m); +static void fullscreennotify(struct wl_listener *listener, void *data); static void incnmaster(const Arg *arg); static void inputdevice(struct wl_listener *listener, void *data); static int keybinding(uint32_t mods, xkb_keysym_t sym); @@ -263,13 +263,13 @@ static void resize(Client *c, int x, int y, int w, int h, int interact); static void run(char *startup_cmd); static Client *selclient(void); static void setcursor(struct wl_listener *listener, void *data); -static void setpsel(struct wl_listener *listener, void *data); -static void setsel(struct wl_listener *listener, void *data); static void setfloating(Client *c, int floating); static void setfullscreen(Client *c, int fullscreen); static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setmon(Client *c, Monitor *m, unsigned int newtags); +static void setpsel(struct wl_listener *listener, void *data); +static void setsel(struct wl_listener *listener, void *data); static void setup(void); static void sigchld(int unused); static void spawn(const Arg *arg); @@ -289,9 +289,9 @@ 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 Monitor *xytomon(double x, double y); static struct wlr_scene_node *xytonode(double x, double y, struct wlr_surface **psurface, Client **pc, LayerSurface **pl, double *nx, double *ny); -static Monitor *xytomon(double x, double y); static void zoom(const Arg *arg); /* variables */ @@ -818,6 +818,50 @@ createkeyboard(struct wlr_input_device *device) wl_list_insert(&keyboards, &kb->link); } +void +createlayersurface(struct wl_listener *listener, void *data) +{ + struct wlr_layer_surface_v1 *wlr_layer_surface = data; + LayerSurface *layersurface; + Monitor *m; + struct wlr_layer_surface_v1_state old_state; + + if (!wlr_layer_surface->output) { + wlr_layer_surface->output = selmon->wlr_output; + } + + layersurface = ecalloc(1, sizeof(LayerSurface)); + layersurface->type = LayerShell; + LISTEN(&wlr_layer_surface->surface->events.commit, + &layersurface->surface_commit, commitlayersurfacenotify); + LISTEN(&wlr_layer_surface->events.destroy, &layersurface->destroy, + destroylayersurfacenotify); + LISTEN(&wlr_layer_surface->events.map, &layersurface->map, + maplayersurfacenotify); + LISTEN(&wlr_layer_surface->events.unmap, &layersurface->unmap, + unmaplayersurfacenotify); + + layersurface->layer_surface = wlr_layer_surface; + wlr_layer_surface->data = layersurface; + m = wlr_layer_surface->output->data; + + layersurface->scene = wlr_layer_surface->surface->data = + wlr_scene_subsurface_tree_create(layers[wlr_layer_surface->pending.layer], + wlr_layer_surface->surface); + layersurface->scene->data = layersurface; + + wl_list_insert(&m->layers[wlr_layer_surface->pending.layer], + &layersurface->link); + + /* Temporarily set the layer's current state to pending + * so that we can easily arrange it + */ + old_state = wlr_layer_surface->current; + wlr_layer_surface->current = wlr_layer_surface->pending; + arrangelayers(m); + wlr_layer_surface->current = old_state; +} + void createmon(struct wl_listener *listener, void *data) { @@ -924,50 +968,6 @@ createnotify(struct wl_listener *listener, void *data) c->isfullscreen = 0; } -void -createlayersurface(struct wl_listener *listener, void *data) -{ - struct wlr_layer_surface_v1 *wlr_layer_surface = data; - LayerSurface *layersurface; - Monitor *m; - struct wlr_layer_surface_v1_state old_state; - - if (!wlr_layer_surface->output) { - wlr_layer_surface->output = selmon->wlr_output; - } - - layersurface = ecalloc(1, sizeof(LayerSurface)); - layersurface->type = LayerShell; - LISTEN(&wlr_layer_surface->surface->events.commit, - &layersurface->surface_commit, commitlayersurfacenotify); - LISTEN(&wlr_layer_surface->events.destroy, &layersurface->destroy, - destroylayersurfacenotify); - LISTEN(&wlr_layer_surface->events.map, &layersurface->map, - maplayersurfacenotify); - LISTEN(&wlr_layer_surface->events.unmap, &layersurface->unmap, - unmaplayersurfacenotify); - - layersurface->layer_surface = wlr_layer_surface; - wlr_layer_surface->data = layersurface; - m = wlr_layer_surface->output->data; - - layersurface->scene = wlr_layer_surface->surface->data = - wlr_scene_subsurface_tree_create(layers[wlr_layer_surface->pending.layer], - wlr_layer_surface->surface); - layersurface->scene->data = layersurface; - - wl_list_insert(&m->layers[wlr_layer_surface->pending.layer], - &layersurface->link); - - /* Temporarily set the layer's current state to pending - * so that we can easily arrange it - */ - old_state = wlr_layer_surface->current; - wlr_layer_surface->current = wlr_layer_surface->pending; - arrangelayers(m); - wlr_layer_surface->current = old_state; -} - void createpointer(struct wlr_input_device *device) { @@ -1049,57 +1049,6 @@ destroynotify(struct wl_listener *listener, void *data) free(c); } -void -dragicondestroy(struct wl_listener *listener, void *data) -{ - struct wlr_drag_icon *icon = data; - wlr_scene_node_destroy(icon->data); - // Focus enter isn't sent during drag, so refocus the focused node. - focusclient(selclient(), 1); - motionnotify(0); -} - -void -togglefullscreen(const Arg *arg) -{ - Client *sel = selclient(); - if (sel) - setfullscreen(sel, !sel->isfullscreen); -} - -void -setfullscreen(Client *c, int fullscreen) -{ - c->isfullscreen = fullscreen; - c->bw = fullscreen ? 0 : borderpx; - client_set_fullscreen(c, fullscreen); - - if (fullscreen) { - c->prev = c->geom; - resize(c, c->mon->m.x, c->mon->m.y, c->mon->m.width, c->mon->m.height, 0); - } else { - /* restore previous size instead of arrange for floating windows since - * client positions are set by the user and cannot be recalculated */ - resize(c, c->prev.x, c->prev.y, c->prev.width, c->prev.height, 0); - } - arrange(c->mon); - printstatus(); -} - -void -fullscreennotify(struct wl_listener *listener, void *data) -{ - Client *c = wl_container_of(listener, c, fullscreen); - int fullscreen = client_wants_fullscreen(c); - - if (!c->mon) { - /* if the client is not mapped yet, let mapnotify() call setfullscreen() */ - c->isfullscreen = fullscreen; - return; - } - setfullscreen(c, fullscreen); -} - Monitor * dirtomon(enum wlr_direction dir) { @@ -1114,6 +1063,16 @@ dirtomon(enum wlr_direction dir) return selmon; } +void +dragicondestroy(struct wl_listener *listener, void *data) +{ + struct wlr_drag_icon *icon = data; + wlr_scene_node_destroy(icon->data); + // Focus enter isn't sent during drag, so refocus the focused node. + focusclient(selclient(), 1); + motionnotify(0); +} + void focusclient(Client *c, int lift) { @@ -1229,6 +1188,20 @@ focustop(Monitor *m) return NULL; } +void +fullscreennotify(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, fullscreen); + int fullscreen = client_wants_fullscreen(c); + + if (!c->mon) { + /* if the client is not mapped yet, let mapnotify() call setfullscreen() */ + c->isfullscreen = fullscreen; + return; + } + setfullscreen(c, fullscreen); +} + void incnmaster(const Arg *arg) { @@ -1692,6 +1665,18 @@ rendermon(struct wl_listener *listener, void *data) m->un_map = 0; } +void +requeststartdrag(struct wl_listener *listener, void *data) +{ + struct wlr_seat_request_start_drag_event *event = data; + + if (wlr_seat_validate_pointer_grab_serial(seat, event->origin, + event->serial)) + wlr_seat_start_pointer_drag(seat, event->drag, event->serial); + else + wlr_data_source_destroy(event->drag->source); +} + void resize(Client *c, int x, int y, int w, int h, int interact) { @@ -1720,18 +1705,6 @@ resize(Client *c, int x, int y, int w, int h, int interact) c->geom.height - 2 * c->bw); } -void -requeststartdrag(struct wl_listener *listener, void *data) -{ - struct wlr_seat_request_start_drag_event *event = data; - - if (wlr_seat_validate_pointer_grab_serial(seat, event->origin, - event->serial)) - wlr_seat_start_pointer_drag(seat, event->drag, event->serial); - else - wlr_data_source_destroy(event->drag->source); -} - void run(char *startup_cmd) { @@ -1830,6 +1803,25 @@ setfloating(Client *c, int floating) printstatus(); } +void +setfullscreen(Client *c, int fullscreen) +{ + c->isfullscreen = fullscreen; + c->bw = fullscreen ? 0 : borderpx; + client_set_fullscreen(c, fullscreen); + + if (fullscreen) { + c->prev = c->geom; + resize(c, c->mon->m.x, c->mon->m.y, c->mon->m.width, c->mon->m.height, 0); + } else { + /* restore previous size instead of arrange for floating windows since + * client positions are set by the user and cannot be recalculated */ + resize(c, c->prev.x, c->prev.y, c->prev.width, c->prev.height, 0); + } + arrange(c->mon); + printstatus(); +} + void setlayout(const Arg *arg) { @@ -2176,6 +2168,14 @@ togglefloating(const Arg *arg) setfloating(sel, !sel->isfloating); } +void +togglefullscreen(const Arg *arg) +{ + Client *sel = selclient(); + if (sel) + setfullscreen(sel, !sel->isfullscreen); +} + void toggletag(const Arg *arg) { @@ -2329,6 +2329,13 @@ virtualkeyboard(struct wl_listener *listener, void *data) createkeyboard(device); } +Monitor * +xytomon(double x, double y) +{ + struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y); + return o ? o->data : NULL; +} + struct wlr_scene_node * xytonode(double x, double y, struct wlr_surface **psurface, Client **pc, LayerSurface **pl, double *nx, double *ny) @@ -2362,13 +2369,6 @@ xytonode(double x, double y, struct wlr_surface **psurface, return node; } -Monitor * -xytomon(double x, double y) -{ - struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y); - return o ? o->data : NULL; -} - void zoom(const Arg *arg) { -- cgit v1.2.3