summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuido Cella <guido@guidocella.xyz>2020-12-19 06:57:14 +0100
committerGuido Cella <guido@guidocella.xyz>2020-12-19 12:34:31 +0100
commit1024928c15cebbeb1c652a6ba4a243f1c330bac8 (patch)
treedce21864e2f00480c290f315a230906058b450ed
parent64faad7cb6dfc59832ef3249b606df89c23327f8 (diff)
deactivate focused client when spawning a new one
Because maprequest immediately calls wl_list_insert(&fstack, &c->flink), in the following call to setmon(), the selclient() which is passed to focusclient() as the old client is actually the newly mapped client, and the real old one is never deactivated. You can see this by, for example, opening Chromium's devtools, then spawning a terminal. The background of the focused line in the devtools doesn't change from light blue to grey. We can't just remove wl_list_insert(&fstack, &c->flink) from maprequest, because calling wl_list_remove in focusclient() with a client that has not been added to the list causes a segmentation fault. Therefore we fix the focusclient call by not passing it the old client every time, but instead using the wlroots function that gets the focused surface and deactivate that, like in TinyWL. This also avoids getting the selected client and passing it to focusclient() on every call unnecessarily, and will allow removing shouldfocusclients in a future commit by checking if old is a layer surface instead.
-rw-r--r--dwl.c50
1 files changed, 24 insertions, 26 deletions
diff --git a/dwl.c b/dwl.c
index 1b92a3e..cb5341a 100644
--- a/dwl.c
+++ b/dwl.c
@@ -220,7 +220,7 @@ static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
static void destroynotify(struct wl_listener *listener, void *data);
static void destroyxdeco(struct wl_listener *listener, void *data);
static Monitor *dirtomon(int dir);
-static void focusclient(Client *old, Client *c, int lift);
+static void focusclient(Client *c, int lift);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
static Client *focustop(Monitor *m);
@@ -630,7 +630,7 @@ buttonpress(struct wl_listener *listener, void *data)
case WLR_BUTTON_PRESSED:;
/* Change focus if the button was _pressed_ over a client */
if ((c = xytoclient(cursor->x, cursor->y)))
- focusclient(selclient(), c, 1);
+ focusclient(c, 1);
keyboard = wlr_seat_get_keyboard(seat);
mods = wlr_keyboard_get_modifiers(keyboard);
@@ -708,7 +708,7 @@ cleanupmon(struct wl_listener *listener, void *data)
do // don't switch to disabled mons
selmon = wl_container_of(mons.prev, selmon, link);
while (!selmon->wlr_output->enabled && i++ < nmons);
- focusclient(selclient(), focustop(selmon), 1);
+ focusclient(focustop(selmon), 1);
closemon(m);
free(m);
}
@@ -1039,9 +1039,10 @@ dirtomon(int dir)
}
void
-focusclient(Client *old, Client *c, int lift)
+focusclient(Client *c, int lift)
{
struct wlr_keyboard *kb = wlr_seat_get_keyboard(seat);
+ struct wlr_surface *old = seat->keyboard_state.focused_surface;
/* Raise client in stacking order if requested */
if (c && lift) {
@@ -1050,17 +1051,19 @@ focusclient(Client *old, Client *c, int lift)
}
/* Nothing else to do? */
- if (c == old)
+ if (c && WLR_SURFACE(c) == old)
return;
/* Deactivate old client if focus is changing */
- if (c != old && old) {
+ if (old && (!c || WLR_SURFACE(c) != old)) {
+ if (wlr_surface_is_xdg_surface(old))
+ wlr_xdg_toplevel_set_activated(
+ wlr_xdg_surface_from_wlr_surface(old), false);
#ifdef XWAYLAND
- if (old->type != XDGShell)
- wlr_xwayland_surface_activate(old->surface.xwayland, 0);
- else
+ else if (wlr_surface_is_xwayland_surface(old))
+ wlr_xwayland_surface_activate(
+ wlr_xwayland_surface_from_wlr_surface(old), false);
#endif
- wlr_xdg_toplevel_set_activated(old->surface.xdg, 0);
}
/* Update wlroots' keyboard focus */
@@ -1092,12 +1095,10 @@ focusclient(Client *old, Client *c, int lift)
void
focusmon(const Arg *arg)
{
- Client *sel;
do
selmon = dirtomon(arg->i);
while (!selmon->wlr_output->enabled);
- sel = selclient();
- focusclient(sel, focustop(selmon), 1);
+ focusclient(focustop(selmon), 1);
}
void
@@ -1123,7 +1124,7 @@ focusstack(const Arg *arg)
}
}
/* If only one client is visible on selmon, then c == sel */
- focusclient(sel, c, 1);
+ focusclient(c, 1);
}
Client *
@@ -1549,7 +1550,7 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
#endif
if (sloppyfocus)
- focusclient(selclient(), c, 0);
+ focusclient(c, 0);
}
void
@@ -1893,7 +1894,6 @@ void
setmon(Client *c, Monitor *m, unsigned int newtags)
{
Monitor *oldmon = c->mon;
- Client *oldsel = selclient();
if (oldmon == m)
return;
@@ -1911,7 +1911,7 @@ setmon(Client *c, Monitor *m, unsigned int newtags)
c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */
arrange(m);
}
- focusclient(oldsel, focustop(selmon), 1);
+ focusclient(focustop(selmon), 1);
}
void
@@ -2119,7 +2119,7 @@ tag(const Arg *arg)
Client *sel = selclient();
if (sel && arg->ui & TAGMASK) {
sel->tags = arg->ui & TAGMASK;
- focusclient(sel, focustop(selmon), 1);
+ focusclient(focustop(selmon), 1);
arrange(selmon);
}
}
@@ -2186,7 +2186,7 @@ toggletag(const Arg *arg)
newtags = sel->tags ^ (arg->ui & TAGMASK);
if (newtags) {
sel->tags = newtags;
- focusclient(sel, focustop(selmon), 1);
+ focusclient(focustop(selmon), 1);
arrange(selmon);
}
}
@@ -2194,12 +2194,11 @@ toggletag(const Arg *arg)
void
toggleview(const Arg *arg)
{
- Client *sel = selclient();
unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
if (newtagset) {
selmon->tagset[selmon->seltags] = newtagset;
- focusclient(sel, focustop(selmon), 1);
+ focusclient(focustop(selmon), 1);
arrange(selmon);
}
}
@@ -2210,7 +2209,7 @@ unmaplayersurface(LayerSurface *layersurface)
layersurface->layer_surface->mapped = false;
if (layersurface->layer_surface->surface ==
seat->keyboard_state.focused_surface)
- focusclient(NULL, selclient(), 1);
+ focusclient(selclient(), 1);
motionnotify(0);
}
@@ -2266,13 +2265,12 @@ updatemons()
void
view(const Arg *arg)
{
- Client *sel = selclient();
if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
return;
selmon->seltags ^= 1; /* toggle sel tagset */
if (arg->ui & TAGMASK)
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
- focusclient(sel, focustop(selmon), 1);
+ focusclient(focustop(selmon), 1);
arrange(selmon);
}
@@ -2319,7 +2317,7 @@ xytomon(double x, double y)
void
zoom(const Arg *arg)
{
- Client *c, *sel = selclient(), *oldsel = sel;
+ Client *c, *sel = selclient();
if (!sel || !selmon->lt[selmon->sellt]->arrange || sel->isfloating)
return;
@@ -2344,7 +2342,7 @@ zoom(const Arg *arg)
wl_list_remove(&sel->link);
wl_list_insert(&clients, &sel->link);
- focusclient(oldsel, sel, 1);
+ focusclient(sel, 1);
arrange(selmon);
}