aboutsummaryrefslogtreecommitdiff
path: root/dwl.c
diff options
context:
space:
mode:
authorDevin J. Pohly <djpohly@gmail.com>2020-04-24 00:12:11 -0500
committerDevin J. Pohly <djpohly@gmail.com>2020-04-24 00:12:58 -0500
commitc00da5eeb00eefc62a531386bcf8df0e7f0f572f (patch)
tree8af9bc4c1f17158c912eaaed708f40286e65b4bd /dwl.c
parent60f2c0b7de50c7b680730a1a75922acb329ccf25 (diff)
clarify keyboardfocus vs pointerfocus
Diffstat (limited to 'dwl.c')
-rw-r--r--dwl.c156
1 files changed, 76 insertions, 80 deletions
diff --git a/dwl.c b/dwl.c
index 5f24226..8144922 100644
--- a/dwl.c
+++ b/dwl.c
@@ -135,12 +135,12 @@ static void createpointer(struct wlr_input_device *device);
static void cursorframe(struct wl_listener *listener, void *data);
static void destroynotify(struct wl_listener *listener, void *data);
static Monitor *dirtomon(int dir);
-static void focus(Client *c, struct wlr_surface *surface);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
static void incnmaster(const Arg *arg);
static void inputdevice(struct wl_listener *listener, void *data);
static bool keybinding(uint32_t mods, xkb_keysym_t sym);
+static void keyboardfocus(Client *c, struct wlr_surface *surface);
static void keypress(struct wl_listener *listener, void *data);
static void keypressmod(struct wl_listener *listener, void *data);
static void maprequest(struct wl_listener *listener, void *data);
@@ -148,6 +148,8 @@ static void motionabsolute(struct wl_listener *listener, void *data);
static void motionnotify(uint32_t time);
static void motionrelative(struct wl_listener *listener, void *data);
static void movemouse(const Arg *arg);
+static void pointerfocus(Client *c, struct wlr_surface *surface,
+ double sx, double sy);
static void quit(const Arg *arg);
static void raiseclient(Client *c);
static void refocus(void);
@@ -267,7 +269,7 @@ buttonpress(struct wl_listener *listener, void *data)
struct wlr_surface *surface;
Client *c = xytoclient(cursor->x, cursor->y, &surface, &sx, &sy);
if (c) {
- focus(c, surface);
+ keyboardfocus(c, surface);
raiseclient(c);
}
@@ -433,56 +435,6 @@ dirtomon(int dir)
}
void
-focus(Client *c, struct wlr_surface *surface)
-{
- if (c) {
- /* assert(VISIBLEON(c, c->mon)); ? */
- /* Default surface is the client's main xdg_surface */
- if (!surface)
- surface = c->xdg_surface->surface;
- /* Focus the correct monitor as well */
- selmon = c->mon;
- }
-
- /* XXX Need to understand xdg toplevel/popups to know if there's more
- * simplification that can be done in this function */
- struct wlr_surface *prev_surface = seat->keyboard_state.focused_surface;
- /* Don't re-focus an already focused surface. */
- if (prev_surface == surface)
- return;
- if (prev_surface) {
- /*
- * Deactivate the previously focused surface. This lets the
- * client know it no longer has focus and the client will
- * repaint accordingly, e.g. stop displaying a caret.
- */
- struct wlr_xdg_surface *previous = wlr_xdg_surface_from_wlr_surface(
- seat->keyboard_state.focused_surface);
- wlr_xdg_toplevel_set_activated(previous, false);
- }
- if (!c) {
- wlr_seat_keyboard_clear_focus(seat);
- return;
- }
-
- struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat);
- /* Move the client to the front of the focus stack */
- wl_list_remove(&c->flink);
- wl_list_insert(&fstack, &c->flink);
- /* Activate the new surface */
- wlr_xdg_toplevel_set_activated(c->xdg_surface, true);
- /*
- * Tell the seat to have the keyboard enter this surface.
- * wlroots will keep track of this and automatically send key
- * events to the appropriate clients without additional work on
- * your part.
- */
- wlr_seat_keyboard_notify_enter(seat, c->xdg_surface->surface,
- keyboard->keycodes, keyboard->num_keycodes,
- &keyboard->modifiers);
-}
-
-void
focusmon(const Arg *arg)
{
Monitor *m = dirtomon(arg->i);
@@ -517,7 +469,7 @@ focusstack(const Arg *arg)
}
}
/* If only one client is visible on selmon, then c == sel */
- focus(c, NULL);
+ keyboardfocus(c, NULL);
raiseclient(c);
}
@@ -574,6 +526,55 @@ keybinding(uint32_t mods, xkb_keysym_t sym)
}
void
+keyboardfocus(Client *c, struct wlr_surface *surface)
+{
+ if (c) {
+ /* assert(VISIBLEON(c, c->mon)); ? */
+ /* If no surface provided, use the client's xdg_surface */
+ if (!surface)
+ surface = c->xdg_surface->surface;
+ /* Focus the correct monitor as well */
+ selmon = c->mon;
+ }
+
+ /* XXX Need to understand xdg toplevel/popups to know if there's more
+ * simplification that can be done in this function */
+ struct wlr_surface *prev_surface = seat->keyboard_state.focused_surface;
+ /* Don't re-focus an already focused surface. */
+ if (prev_surface == surface)
+ return;
+ if (prev_surface) {
+ /*
+ * Deactivate the previously focused surface. This lets the
+ * client know it no longer has focus and the client will
+ * repaint accordingly, e.g. stop displaying a caret.
+ */
+ struct wlr_xdg_surface *previous = wlr_xdg_surface_from_wlr_surface(
+ seat->keyboard_state.focused_surface);
+ wlr_xdg_toplevel_set_activated(previous, false);
+ }
+ if (!c) {
+ wlr_seat_keyboard_clear_focus(seat);
+ return;
+ }
+
+ /* Move the client to the front of the focus stack */
+ wl_list_remove(&c->flink);
+ wl_list_insert(&fstack, &c->flink);
+ /* Activate the new surface */
+ wlr_xdg_toplevel_set_activated(c->xdg_surface, true);
+ /*
+ * Tell the seat to have the keyboard enter this surface.
+ * wlroots will keep track of this and automatically send key
+ * events to the appropriate clients without additional work on
+ * your part.
+ */
+ struct wlr_keyboard *kb = wlr_seat_get_keyboard(seat);
+ wlr_seat_keyboard_notify_enter(seat, c->xdg_surface->surface,
+ kb->keycodes, kb->num_keycodes, &kb->modifiers);
+}
+
+void
keypress(struct wl_listener *listener, void *data)
{
/* This event is raised when a key is pressed or released. */
@@ -632,7 +633,7 @@ maprequest(struct wl_listener *listener, void *data)
wl_list_insert(&clients, &c->link);
wl_list_insert(&fstack, &c->flink);
wl_list_insert(&stack, &c->slink);
- focus(c, NULL);
+ keyboardfocus(c, NULL);
}
void
@@ -684,33 +685,13 @@ motionnotify(uint32_t time)
if (!c)
wlr_xcursor_manager_set_cursor_image(cursor_mgr,
"left_ptr", cursor);
- if (!surface) {
- /* Clear pointer focus so future button events and such are not sent to
- * the last client to have the cursor over it. */
- wlr_seat_pointer_clear_focus(seat);
- /* If keyboard focus follows mouse, clear that too */
- if (sloppyfocus)
- focus(NULL, NULL);
- return;
- }
- /*
- * "Enter" the surface if necessary. This lets the client know that the
- * cursor has entered one of its surfaces.
- *
- * Note that this gives the surface "pointer focus", which is distinct
- * from keyboard focus. You get pointer focus by moving the pointer over
- * a window.
- */
- if (surface != seat->pointer_state.focused_surface) {
- wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
- if (sloppyfocus)
- focus(c, surface);
- } else {
- /* The enter event contains coordinates, so we only need to notify
- * on motion if the focus did not change. */
+ /* If surface is already focused, only notify of motion, otherwise give
+ * surface the pointer focus */
+ if (surface && surface == seat->pointer_state.focused_surface)
wlr_seat_pointer_notify_motion(seat, time, sx, sy);
- }
+ else
+ pointerfocus(c, surface, sx, sy);
}
void
@@ -745,6 +726,21 @@ movemouse(const Arg *arg)
}
void
+pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy)
+{
+ /* 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_clear_focus(seat);
+ else
+ wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
+
+ /* If keyboard focus follows mouse, enforce that */
+ if (sloppyfocus)
+ keyboardfocus(c, surface);
+}
+
+void
quit(const Arg *arg)
{
wl_display_terminate(dpy);
@@ -761,7 +757,7 @@ refocus(void)
}
}
/* XXX consider: should this ever? always? raise the client? */
- focus(c, NULL);
+ keyboardfocus(c, NULL);
}
void