aboutsummaryrefslogtreecommitdiff
path: root/dwl.c
diff options
context:
space:
mode:
Diffstat (limited to 'dwl.c')
-rw-r--r--dwl.c343
1 files changed, 172 insertions, 171 deletions
diff --git a/dwl.c b/dwl.c
index 30a45f1..af0faa0 100644
--- a/dwl.c
+++ b/dwl.c
@@ -43,7 +43,7 @@
#define LENGTH(X) (sizeof X / sizeof X[0])
#define END(A) ((A) + LENGTH(A))
#define TAGMASK ((1 << LENGTH(tags)) - 1)
-#define WLR_SURFACE(C) ((C)->type != XDGShell ? (C)->xwayland_surface->surface : (C)->xdg_surface->surface)
+#define WLR_SURFACE(C) ((C)->type != XDGShell ? (C)->surface.xwayland->surface : (C)->surface.xdg->surface)
/* enums */
enum { CurNormal, CurMove, CurResize }; /* cursor */
@@ -71,10 +71,11 @@ typedef struct {
struct wl_list flink;
struct wl_list slink;
union {
- struct wlr_xdg_surface *xdg_surface;
- struct wlr_xwayland_surface *xwayland_surface;
- };
+ struct wlr_xdg_surface *xdg;
+ struct wlr_xwayland_surface *xwayland;
+ } surface;
struct wl_listener activate;
+ struct wl_listener commit;
struct wl_listener map;
struct wl_listener unmap;
struct wl_listener destroy;
@@ -84,6 +85,7 @@ typedef struct {
int bw;
unsigned int tags;
int isfloating;
+ uint32_t resize; /* configure serial of a pending resize */
} Client;
typedef struct {
@@ -172,9 +174,10 @@ static void cursorframe(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 *c, struct wlr_surface *surface, int lift);
+static void focusclient(Client *old, Client *c, int lift);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
+static Client *focustop(Monitor *m);
static Atom getatom(xcb_connection_t *xc, const char *name);
static void getxdecomode(struct wl_listener *listener, void *data);
static void incnmaster(const Arg *arg);
@@ -183,7 +186,6 @@ static int keybinding(uint32_t mods, xkb_keysym_t sym);
static void keypress(struct wl_listener *listener, void *data);
static void keypressmod(struct wl_listener *listener, void *data);
static void killclient(const Arg *arg);
-static Client *lastfocused(void);
static void maprequest(struct wl_listener *listener, void *data);
static void motionabsolute(struct wl_listener *listener, void *data);
static void motionnotify(uint32_t time);
@@ -272,6 +274,9 @@ static struct wl_listener xwayland_ready = {.notify = xwaylandready};
/* configuration, allows nested code to access above variables */
#include "config.h"
+/* compile-time check if all tags fit into an unsigned int bit array. */
+struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
+
/* function implementations */
void
activatex11(struct wl_listener *listener, void *data)
@@ -280,7 +285,7 @@ activatex11(struct wl_listener *listener, void *data)
/* Only "managed" windows can be activated */
if (c->type == X11Managed)
- wlr_xwayland_surface_activate(c->xwayland_surface, 1);
+ wlr_xwayland_surface_activate(c->surface.xwayland, 1);
}
void
@@ -310,10 +315,10 @@ applyrules(Client *c)
/* rule matching */
c->isfloating = 0;
- appid = c->type != XDGShell ? c->xwayland_surface->class :
- c->xdg_surface->toplevel->app_id;
- title = c->type != XDGShell ? c->xwayland_surface->title :
- c->xdg_surface->toplevel->title;
+ appid = c->type != XDGShell ? c->surface.xwayland->class :
+ c->surface.xdg->toplevel->app_id;
+ title = c->type != XDGShell ? c->surface.xwayland->title :
+ c->surface.xdg->toplevel->title;
if (!appid)
appid = broken;
if (!title)
@@ -321,8 +326,7 @@ applyrules(Client *c)
for (r = rules; r < END(rules); r++) {
if ((!r->title || strstr(title, r->title))
- && (!r->id || strstr(appid, r->id)))
- {
+ && (!r->id || strstr(appid, r->id))) {
c->isfloating = r->isfloating;
newtags |= r->tags;
i = 0;
@@ -362,7 +366,6 @@ void
buttonpress(struct wl_listener *listener, void *data)
{
struct wlr_event_pointer_button *event = data;
- struct wlr_surface *surface;
struct wlr_keyboard *keyboard;
uint32_t mods;
Client *c;
@@ -371,17 +374,8 @@ buttonpress(struct wl_listener *listener, void *data)
switch (event->state) {
case WLR_BUTTON_PRESSED:;
/* Change focus if the button was _pressed_ over a client */
- if ((c = xytoclient(cursor->x, cursor->y))) {
- if (c->type != XDGShell)
- surface = wlr_surface_surface_at(c->xwayland_surface->surface,
- cursor->x - c->geom.x - c->bw,
- cursor->y - c->geom.y - c->bw, NULL, NULL);
- else
- surface = wlr_xdg_surface_surface_at(c->xdg_surface,
- cursor->x - c->geom.x - c->bw,
- cursor->y - c->geom.y - c->bw, NULL, NULL);
- focusclient(c, surface, 1);
- }
+ if ((c = xytoclient(cursor->x, cursor->y)))
+ focusclient(selclient(), c, 1);
keyboard = wlr_seat_get_keyboard(seat);
mods = wlr_keyboard_get_modifiers(keyboard);
@@ -443,6 +437,16 @@ cleanupmon(struct wl_listener *listener, void *data)
}
void
+commitnotify(struct wl_listener *listener, void *data)
+{
+ Client *c = wl_container_of(listener, c, commit);
+
+ /* mark a pending resize as completed */
+ if (c->resize && c->resize <= c->surface.xdg->configure_serial)
+ c->resize = 0;
+}
+
+void
createkeyboard(struct wlr_input_device *device)
{
struct xkb_context *context;
@@ -544,15 +548,17 @@ createnotify(struct wl_listener *listener, void *data)
/* Allocate a Client for this surface */
c = xdg_surface->data = calloc(1, sizeof(*c));
- c->xdg_surface = xdg_surface;
+ c->surface.xdg = xdg_surface;
c->type = XDGShell;
c->bw = borderpx;
/* Tell the client not to try anything fancy */
- wlr_xdg_toplevel_set_tiled(c->xdg_surface, WLR_EDGE_TOP |
+ wlr_xdg_toplevel_set_tiled(c->surface.xdg, WLR_EDGE_TOP |
WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
/* Listen to the various events it can emit */
+ c->commit.notify = commitnotify;
+ wl_signal_add(&xdg_surface->surface->events.commit, &c->commit);
c->map.notify = maprequest;
wl_signal_add(&xdg_surface->events.map, &c->map);
c->unmap.notify = unmapnotify;
@@ -569,7 +575,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
/* Allocate a Client for this surface */
c = xwayland_surface->data = calloc(1, sizeof(*c));
- c->xwayland_surface = xwayland_surface;
+ c->surface.xwayland = xwayland_surface;
c->type = xwayland_surface->override_redirect ? X11Unmanaged : X11Managed;
c->bw = borderpx;
@@ -628,6 +634,10 @@ destroynotify(struct wl_listener *listener, void *data)
wl_list_remove(&c->map.link);
wl_list_remove(&c->unmap.link);
wl_list_remove(&c->destroy.link);
+ if (c->type == XDGShell)
+ wl_list_remove(&c->commit.link);
+ if (c->type == X11Managed)
+ wl_list_remove(&c->activate.link);
free(c);
}
@@ -659,78 +669,58 @@ dirtomon(int dir)
}
void
-focusclient(Client *c, struct wlr_surface *surface, int lift)
+focusclient(Client *old, Client *c, int lift)
{
- Client *sel = selclient();
- struct wlr_keyboard *kb;
- /* Previous and new xdg toplevel surfaces */
- Client *ptl = sel;
- Client *tl = c;
- /* Previously focused surface */
- struct wlr_surface *psurface = seat->keyboard_state.focused_surface;
-
- if (c) {
- /* assert(VISIBLEON(c, c->mon)); ? */
- /* Use top-level wlr_surface if nothing more specific given */
- if (!surface)
- surface = WLR_SURFACE(c);
-
- /* Focus the correct monitor (must come after selclient!) */
- selmon = c->mon;
-
- /* Move the client to the front of the focus stack */
- wl_list_remove(&c->flink);
- wl_list_insert(&fstack, &c->flink);
-
- /* Also raise client in stacking order if requested */
- if (lift) {
- wl_list_remove(&c->slink);
- wl_list_insert(&stack, &c->slink);
- }
- }
+ struct wlr_keyboard *kb = wlr_seat_get_keyboard(seat);
- /*
- * If the focused surface has changed, tell the seat to have the
- * keyboard enter the new surface. wlroots will keep track of this and
- * automatically send key events to the appropriate clients. If surface
- * is NULL, we clear the focus instead.
- */
- if (!surface) {
- wlr_seat_keyboard_notify_clear_focus(seat);
- } else if (surface != psurface) {
- kb = wlr_seat_get_keyboard(seat);
- wlr_seat_keyboard_notify_enter(seat, surface,
- kb->keycodes, kb->num_keycodes, &kb->modifiers);
+ /* Raise client in stacking order if requested */
+ if (c && lift) {
+ wl_list_remove(&c->slink);
+ wl_list_insert(&stack, &c->slink);
}
- /*
- * If the focused toplevel has changed, deactivate the old one. Always
- * activate the current one. This lets the clients know to repaint
- * accordingly, e.g. show/hide a caret.
- */
- if (tl != ptl && ptl) {
- if (ptl->type != XDGShell)
- wlr_xwayland_surface_activate(ptl->xwayland_surface, 0);
+ /* Nothing else to do? */
+ if (c == old)
+ return;
+
+ /* Deactivate old client if focus is changing */
+ if (c != old && old) {
+ if (old->type != XDGShell)
+ wlr_xwayland_surface_activate(old->surface.xwayland, 0);
else
- wlr_xdg_toplevel_set_activated(ptl->xdg_surface, 0);
+ wlr_xdg_toplevel_set_activated(old->surface.xdg, 0);
}
- if (tl) {
- if (tl->type != XDGShell)
- wlr_xwayland_surface_activate(tl->xwayland_surface, 1);
- else
- wlr_xdg_toplevel_set_activated(tl->xdg_surface, 1);
+
+ /* Update wlroots' keyboard focus */
+ if (!c) {
+ /* With no client, all we have left is to clear focus */
+ wlr_seat_keyboard_notify_clear_focus(seat);
+ return;
}
+
+ /* Have a client, so focus its top-level wlr_surface */
+ wlr_seat_keyboard_notify_enter(seat, WLR_SURFACE(c),
+ kb->keycodes, kb->num_keycodes, &kb->modifiers);
+
+ /* Put the new client atop the focus stack and select its monitor */
+ wl_list_remove(&c->flink);
+ wl_list_insert(&fstack, &c->flink);
+ selmon = c->mon;
+
+ /* Activate the new client */
+ if (c->type != XDGShell)
+ wlr_xwayland_surface_activate(c->surface.xwayland, 1);
+ else
+ wlr_xdg_toplevel_set_activated(c->surface.xdg, 1);
}
void
focusmon(const Arg *arg)
{
- Monitor *m = dirtomon(arg->i);
+ Client *sel = selclient();
- if (m == selmon)
- return;
- selmon = m;
- focusclient(lastfocused(), NULL, 1);
+ selmon = dirtomon(arg->i);
+ focusclient(sel, focustop(selmon), 1);
}
void
@@ -756,7 +746,17 @@ focusstack(const Arg *arg)
}
}
/* If only one client is visible on selmon, then c == sel */
- focusclient(c, NULL, 1);
+ focusclient(sel, c, 1);
+}
+
+Client *
+focustop(Monitor *m)
+{
+ Client *c;
+ wl_list_for_each(c, &fstack, flink)
+ if (VISIBLEON(c, m))
+ return c;
+ return NULL;
}
Atom
@@ -895,19 +895,9 @@ killclient(const Arg *arg)
return;
if (sel->type != XDGShell)
- wlr_xwayland_surface_close(sel->xwayland_surface);
+ wlr_xwayland_surface_close(sel->surface.xwayland);
else
- wlr_xdg_toplevel_send_close(sel->xdg_surface);
-}
-
-Client *
-lastfocused(void)
-{
- Client *c;
- wl_list_for_each(c, &fstack, flink)
- if (VISIBLEON(c, selmon))
- return c;
- return NULL;
+ wlr_xdg_toplevel_send_close(sel->surface.xdg);
}
void
@@ -928,12 +918,12 @@ maprequest(struct wl_listener *listener, void *data)
wl_list_insert(&stack, &c->slink);
if (c->type != XDGShell) {
- c->geom.x = c->xwayland_surface->x;
- c->geom.y = c->xwayland_surface->y;
- c->geom.width = c->xwayland_surface->width + 2 * c->bw;
- c->geom.height = c->xwayland_surface->height + 2 * c->bw;
+ c->geom.x = c->surface.xwayland->x;
+ c->geom.y = c->surface.xwayland->y;
+ c->geom.width = c->surface.xwayland->width + 2 * c->bw;
+ c->geom.height = c->surface.xwayland->height + 2 * c->bw;
} else {
- wlr_xdg_surface_get_geometry(c->xdg_surface, &c->geom);
+ wlr_xdg_surface_get_geometry(c->surface.xdg, &c->geom);
c->geom.width += 2 * c->bw;
c->geom.height += 2 * c->bw;
}
@@ -983,11 +973,11 @@ motionnotify(uint32_t time)
/* Otherwise, find the client under the pointer and send the event along. */
if ((c = xytoclient(cursor->x, cursor->y))) {
if (c->type != XDGShell)
- surface = wlr_surface_surface_at(c->xwayland_surface->surface,
+ surface = wlr_surface_surface_at(c->surface.xwayland->surface,
cursor->x - c->geom.x - c->bw,
cursor->y - c->geom.y - c->bw, &sx, &sy);
else
- surface = wlr_xdg_surface_surface_at(c->xdg_surface,
+ surface = wlr_xdg_surface_surface_at(c->surface.xdg,
cursor->x - c->geom.x - c->bw,
cursor->y - c->geom.y - c->bw, &sx, &sy);
}
@@ -1052,23 +1042,23 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
if (c && !surface)
surface = WLR_SURFACE(c);
- /* If surface is already focused, only notify of motion */
- if (surface && surface == seat->pointer_state.focused_surface) {
- wlr_seat_pointer_notify_motion(seat, time, sx, sy);
+ /* If surface is NULL, clear pointer focus */
+ if (!surface) {
+ wlr_seat_pointer_notify_clear_focus(seat);
return;
}
- /* If surface is NULL, clear pointer focus, otherwise let the client
- * know that the mouse cursor has entered one of its surfaces. */
- if (!surface) {
- wlr_seat_pointer_notify_clear_focus(seat);
+ /* If surface is already focused, only notify of motion */
+ if (surface == seat->pointer_state.focused_surface) {
+ wlr_seat_pointer_notify_motion(seat, time, sx, sy);
return;
}
+ /* Otherwise, let the client know that the mouse cursor has entered one
+ * of its surfaces, and make keyboard focus follow if desired. */
wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
- /* If keyboard focus follows mouse, enforce that */
if (sloppyfocus)
- focusclient(c, surface, 0);
+ focusclient(selclient(), c, 0);
}
void
@@ -1176,14 +1166,14 @@ renderclients(Monitor *m, struct timespec *now)
/* This calls our render function for each surface among the
* xdg_surface's toplevel and popups. */
- rdata.output = m->wlr_output,
- rdata.when = now,
- rdata.x = c->geom.x + c->bw,
+ rdata.output = m->wlr_output;
+ rdata.when = now;
+ rdata.x = c->geom.x + c->bw;
rdata.y = c->geom.y + c->bw;
if (c->type != XDGShell)
- wlr_surface_for_each_surface(c->xwayland_surface->surface, render, &rdata);
+ wlr_surface_for_each_surface(c->surface.xwayland->surface, render, &rdata);
else
- wlr_xdg_surface_for_each_surface(c->xdg_surface, render, &rdata);
+ wlr_xdg_surface_for_each_surface(c->surface.xdg, render, &rdata);
}
}
@@ -1194,30 +1184,30 @@ renderindependents(struct wlr_output *output, struct timespec *now)
struct render_data rdata;
struct wlr_box geom;
- wl_list_for_each_reverse(c, &independents, link)
- {
- geom.x = c->xwayland_surface->x;
- geom.y = c->xwayland_surface->y;
- geom.width = c->xwayland_surface->width;
- geom.height = c->xwayland_surface->height;
+ wl_list_for_each_reverse(c, &independents, link) {
+ geom.x = c->surface.xwayland->x;
+ geom.y = c->surface.xwayland->y;
+ geom.width = c->surface.xwayland->width;
+ geom.height = c->surface.xwayland->height;
/* Only render visible clients which show on this output */
if (!wlr_output_layout_intersects(output_layout, output, &geom))
continue;
- rdata.output = output,
- rdata.when = now,
- rdata.x = c->xwayland_surface->x;
- rdata.y = c->xwayland_surface->y;
+ rdata.output = output;
+ rdata.when = now;
+ rdata.x = c->surface.xwayland->x;
+ rdata.y = c->surface.xwayland->y;
- wlr_surface_for_each_surface(c->xwayland_surface->surface, render, &rdata);
+ wlr_surface_for_each_surface(c->surface.xwayland->surface, render, &rdata);
}
}
void
rendermon(struct wl_listener *listener, void *data)
{
- struct wlr_output *output = data;
+ Client *c;
+ int render = 1;
/* This function is called every time an output is ready to display a frame,
* generally at the output's refresh rate (e.g. 60Hz). */
@@ -1226,28 +1216,39 @@ rendermon(struct wl_listener *listener, void *data)
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
+ /* Do not render if any XDG clients have an outstanding resize. */
+ wl_list_for_each(c, &stack, slink) {
+ if (c->resize) {
+ wlr_surface_send_frame_done(WLR_SURFACE(c), &now);
+ render = 0;
+ }
+ }
+
/* wlr_output_attach_render makes the OpenGL context current. */
if (!wlr_output_attach_render(m->wlr_output, NULL))
return;
- /* Begin the renderer (calls glViewport and some other GL sanity checks) */
- wlr_renderer_begin(drw, m->wlr_output->width, m->wlr_output->height);
- wlr_renderer_clear(drw, rootcolor);
-
- renderclients(m, &now);
- renderindependents(output, &now);
-
- /* Hardware cursors are rendered by the GPU on a separate plane, and can be
- * moved around without re-rendering what's beneath them - which is more
- * efficient. However, not all hardware supports hardware cursors. For this
- * reason, wlroots provides a software fallback, which we ask it to render
- * here. wlr_cursor handles configuring hardware vs software cursors for you,
- * and this function is a no-op when hardware cursors are in use. */
- wlr_output_render_software_cursors(m->wlr_output, NULL);
+ if (render) {
+ /* Begin the renderer (calls glViewport and some other GL sanity checks) */
+ wlr_renderer_begin(drw, m->wlr_output->width, m->wlr_output->height);
+ wlr_renderer_clear(drw, rootcolor);
+
+ renderclients(m, &now);
+ renderindependents(m->wlr_output, &now);
+
+ /* Hardware cursors are rendered by the GPU on a separate plane, and can be
+ * moved around without re-rendering what's beneath them - which is more
+ * efficient. However, not all hardware supports hardware cursors. For this
+ * reason, wlroots provides a software fallback, which we ask it to render
+ * here. wlr_cursor handles configuring hardware vs software cursors for you,
+ * and this function is a no-op when hardware cursors are in use. */
+ wlr_output_render_software_cursors(m->wlr_output, NULL);
+
+ /* Conclude rendering and swap the buffers, showing the final frame
+ * on-screen. */
+ wlr_renderer_end(drw);
+ }
- /* Conclude rendering and swap the buffers, showing the final frame
- * on-screen. */
- wlr_renderer_end(drw);
wlr_output_commit(m->wlr_output);
}
@@ -1267,11 +1268,11 @@ resize(Client *c, int x, int y, int w, int h, int interact)
applybounds(c, bbox);
/* wlroots makes this a no-op if size hasn't changed */
if (c->type != XDGShell)
- wlr_xwayland_surface_configure(c->xwayland_surface,
+ wlr_xwayland_surface_configure(c->surface.xwayland,
c->geom.x, c->geom.y,
c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw);
else
- wlr_xdg_toplevel_set_size(c->xdg_surface,
+ c->resize = wlr_xdg_toplevel_set_size(c->surface.xdg,
c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw);
}
@@ -1414,28 +1415,26 @@ setmfact(const Arg *arg)
void
setmon(Client *c, Monitor *m, unsigned int newtags)
{
- int hadfocus;
Monitor *oldmon = c->mon;
- struct wlr_surface *surface = WLR_SURFACE(c);
+ Client *oldsel = selclient();
+
if (oldmon == m)
return;
- hadfocus = (c == selclient());
c->mon = m;
+
/* XXX leave/enter is not optimal but works */
if (oldmon) {
- wlr_surface_send_leave(surface, oldmon->wlr_output);
+ wlr_surface_send_leave(WLR_SURFACE(c), oldmon->wlr_output);
arrange(oldmon);
}
if (m) {
/* Make sure window actually overlaps with the monitor */
applybounds(c, &m->m);
- wlr_surface_send_enter(surface, m->wlr_output);
+ wlr_surface_send_enter(WLR_SURFACE(c), m->wlr_output);
c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */
arrange(m);
}
- /* Focus can change if c is the top of selmon before or after */
- if (hadfocus || c == selclient())
- focusclient(lastfocused(), NULL, 1);
+ focusclient(oldsel, focustop(selmon), 1);
}
void
@@ -1598,7 +1597,7 @@ tag(const Arg *arg)
Client *sel = selclient();
if (sel && arg->ui & TAGMASK) {
sel->tags = arg->ui & TAGMASK;
- focusclient(lastfocused(), NULL, 1);
+ focusclient(sel, focustop(selmon), 1);
arrange(selmon);
}
}
@@ -1665,7 +1664,7 @@ toggletag(const Arg *arg)
newtags = sel->tags ^ (arg->ui & TAGMASK);
if (newtags) {
sel->tags = newtags;
- focusclient(lastfocused(), NULL, 1);
+ focusclient(sel, focustop(selmon), 1);
arrange(selmon);
}
}
@@ -1673,11 +1672,12 @@ 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(lastfocused(), NULL, 1);
+ focusclient(sel, focustop(selmon), 1);
arrange(selmon);
}
}
@@ -1701,11 +1701,11 @@ updatewindowtype(Client *c)
size_t i;
if (c->type != XDGShell)
- for (i = 0; i < c->xwayland_surface->window_type_len; i++)
- if (c->xwayland_surface->window_type[i] == netatom[NetWMWindowTypeDialog] ||
- c->xwayland_surface->window_type[i] == netatom[NetWMWindowTypeSplash] ||
- c->xwayland_surface->window_type[i] == netatom[NetWMWindowTypeToolbar] ||
- c->xwayland_surface->window_type[i] == netatom[NetWMWindowTypeUtility])
+ for (i = 0; i < c->surface.xwayland->window_type_len; i++)
+ if (c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeDialog] ||
+ c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeSplash] ||
+ c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeToolbar] ||
+ c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeUtility])
c->isfloating = 1;
}
@@ -1733,12 +1733,13 @@ xwaylandready(struct wl_listener *listener, void *data) {
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(lastfocused(), NULL, 1);
+ focusclient(sel, focustop(selmon), 1);
arrange(selmon);
}
@@ -1764,7 +1765,7 @@ xytomon(double x, double y)
void
zoom(const Arg *arg)
{
- Client *c, *sel = selclient();
+ Client *c, *sel = selclient(), *oldsel = sel;
if (!sel || !selmon->lt[selmon->sellt]->arrange || sel->isfloating)
return;
@@ -1789,7 +1790,7 @@ zoom(const Arg *arg)
wl_list_remove(&sel->link);
wl_list_insert(&clients, &sel->link);
- focusclient(sel, NULL, 1);
+ focusclient(oldsel, sel, 1);
arrange(selmon);
}