diff options
Diffstat (limited to 'dwl.c')
| -rw-r--r-- | dwl.c | 156 | 
1 files changed, 76 insertions, 80 deletions
@@ -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  | 
