diff options
| -rw-r--r-- | include/sway/commands.h | 2 | ||||
| -rw-r--r-- | include/sway/config.h | 10 | ||||
| -rw-r--r-- | include/sway/input/seat.h | 6 | ||||
| -rw-r--r-- | sway/commands/seat.c | 2 | ||||
| -rw-r--r-- | sway/commands/seat/idle.c | 73 | ||||
| -rw-r--r-- | sway/config/seat.c | 11 | ||||
| -rw-r--r-- | sway/input/cursor.c | 16 | ||||
| -rw-r--r-- | sway/input/keyboard.c | 2 | ||||
| -rw-r--r-- | sway/input/seat.c | 31 | ||||
| -rw-r--r-- | sway/input/switch.c | 4 | ||||
| -rw-r--r-- | sway/meson.build | 1 | ||||
| -rw-r--r-- | sway/sway-input.5.scd | 12 | 
12 files changed, 159 insertions, 11 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index 5f249980..982125c1 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -285,6 +285,8 @@ sway_cmd seat_cmd_attach;  sway_cmd seat_cmd_cursor;  sway_cmd seat_cmd_fallback;  sway_cmd seat_cmd_hide_cursor; +sway_cmd seat_cmd_idle_inhibit; +sway_cmd seat_cmd_idle_wake;  sway_cmd seat_cmd_keyboard_grouping;  sway_cmd seat_cmd_pointer_constraint;  sway_cmd seat_cmd_xcursor_theme; diff --git a/include/sway/config.h b/include/sway/config.h index 9a00ccb5..3e3d2725 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -182,6 +182,15 @@ enum seat_keyboard_grouping {  	KEYBOARD_GROUP_KEYMAP  }; +enum sway_input_idle_source { +	IDLE_SOURCE_KEYBOARD = 1 << 0, +	IDLE_SOURCE_POINTER = 1 << 1, +	IDLE_SOURCE_TOUCH = 1 << 2, +	IDLE_SOURCE_TABLET_PAD = 1 << 3, +	IDLE_SOURCE_TABLET_TOOL = 1 << 4, +	IDLE_SOURCE_SWITCH = 1 << 5, +}; +  /**   * Options for multiseat and other misc device configurations   */ @@ -192,6 +201,7 @@ struct seat_config {  	int hide_cursor_timeout;  	enum seat_config_allow_constrain allow_constrain;  	enum seat_keyboard_grouping keyboard_grouping; +	uint32_t idle_inhibit_sources, idle_wake_sources;  	struct {  		char *name;  		int size; diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 32795b03..9c3028c5 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -4,6 +4,7 @@  #include <wlr/types/wlr_layer_shell_v1.h>  #include <wlr/types/wlr_seat.h>  #include <wlr/util/edges.h> +#include "sway/config.h"  #include "sway/input/input-manager.h"  struct sway_seat; @@ -80,6 +81,8 @@ struct sway_seat {  	uint32_t last_button_serial; +	uint32_t idle_inhibit_sources, idle_wake_sources; +  	list_t *deferred_bindings; // struct sway_binding  	struct wl_listener focus_destroy; @@ -196,6 +199,9 @@ struct seat_config *seat_get_config(struct sway_seat *seat);  struct seat_config *seat_get_config_by_name(const char *name); +void seat_idle_notify_activity(struct sway_seat *seat, +		enum sway_input_idle_source source); +  bool seat_is_input_allowed(struct sway_seat *seat, struct wlr_surface *surface);  void drag_icon_update_position(struct sway_drag_icon *icon); diff --git a/sway/commands/seat.c b/sway/commands/seat.c index a2a3fbc4..eba28cac 100644 --- a/sway/commands/seat.c +++ b/sway/commands/seat.c @@ -18,6 +18,8 @@ static struct cmd_handler seat_handlers[] = {  	{ "attach", seat_cmd_attach },  	{ "fallback", seat_cmd_fallback },  	{ "hide_cursor", seat_cmd_hide_cursor }, +	{ "idle_inhibit", seat_cmd_idle_inhibit }, +	{ "idle_wake", seat_cmd_idle_wake },  	{ "keyboard_grouping", seat_cmd_keyboard_grouping },  	{ "pointer_constraint", seat_cmd_pointer_constraint },  	{ "xcursor_theme", seat_cmd_xcursor_theme }, diff --git a/sway/commands/seat/idle.c b/sway/commands/seat/idle.c new file mode 100644 index 00000000..82428f2c --- /dev/null +++ b/sway/commands/seat/idle.c @@ -0,0 +1,73 @@ +#define _POSIX_C_SOURCE 200809L +#include <limits.h> +#include <string.h> +#include <strings.h> +#include <stdint.h> +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/input/seat.h" + +static const struct { +	const char *name; +	uint32_t value; +} idle_source_strings[] = { +	{ "keyboard", IDLE_SOURCE_KEYBOARD }, +	{ "pointer", IDLE_SOURCE_POINTER }, +	{ "touch", IDLE_SOURCE_TOUCH }, +	{ "tablet_pad", IDLE_SOURCE_TABLET_PAD }, +	{ "tablet_tool", IDLE_SOURCE_TABLET_TOOL }, +	{ "switch", IDLE_SOURCE_SWITCH }, +}; + +static uint32_t parse_sources(int argc, char **argv) { +	uint32_t sources = 0; +	for (int i = 0; i < argc; ++i) { +		uint32_t value = 0; +		for (size_t j = 0; j < sizeof(idle_source_strings) +				/ sizeof(idle_source_strings[0]); ++j) { +			if (strcasecmp(idle_source_strings[j].name, argv[i]) == 0) { +				value = idle_source_strings[j].value; +				break; +			} +		} +		if (value == 0) { +			return UINT32_MAX; +		} +		sources |= value; +	} +	return sources; +} + +struct cmd_results *seat_cmd_idle_inhibit(int argc, char **argv) { +	struct cmd_results *error = NULL; +	if ((error = checkarg(argc, "idle_inhibit", EXPECTED_AT_LEAST, 1))) { +		return error; +	} +	if (!config->handler_context.seat_config) { +		return cmd_results_new(CMD_FAILURE, "No seat defined"); +	} + +	uint32_t sources = parse_sources(argc, argv); +	if (sources == UINT32_MAX) { +		return cmd_results_new(CMD_FAILURE, "Invalid idle source"); +	} +	config->handler_context.seat_config->idle_inhibit_sources = sources; +	return cmd_results_new(CMD_SUCCESS, NULL); +} + +struct cmd_results *seat_cmd_idle_wake(int argc, char **argv) { +	struct cmd_results *error = NULL; +	if ((error = checkarg(argc, "idle_wake", EXPECTED_AT_LEAST, 1))) { +		return error; +	} +	if (!config->handler_context.seat_config) { +		return cmd_results_new(CMD_FAILURE, "No seat defined"); +	} + +	uint32_t sources = parse_sources(argc, argv); +	if (sources == UINT32_MAX) { +		return cmd_results_new(CMD_FAILURE, "Invalid idle source"); +	} +	config->handler_context.seat_config->idle_wake_sources = sources; +	return cmd_results_new(CMD_SUCCESS, NULL); +} diff --git a/sway/config/seat.c b/sway/config/seat.c index d2401162..6c916727 100644 --- a/sway/config/seat.c +++ b/sway/config/seat.c @@ -1,4 +1,5 @@  #define _POSIX_C_SOURCE 200809L +#include <limits.h>  #include <stdlib.h>  #include <string.h>  #include "sway/config.h" @@ -17,6 +18,8 @@ struct seat_config *new_seat_config(const char* name) {  		return NULL;  	} +	seat->idle_inhibit_sources = seat->idle_wake_sources = UINT32_MAX; +  	seat->fallback = -1;  	seat->attachments = create_list();  	if (!sway_assert(seat->attachments, @@ -160,6 +163,14 @@ void merge_seat_config(struct seat_config *dest, struct seat_config *source) {  		dest->xcursor_theme.name = strdup(source->xcursor_theme.name);  		dest->xcursor_theme.size = source->xcursor_theme.size;  	} + +	if (source->idle_inhibit_sources != UINT32_MAX) { +		dest->idle_inhibit_sources = source->idle_inhibit_sources; +	} + +	if (source->idle_wake_sources != UINT32_MAX) { +		dest->idle_wake_sources = source->idle_wake_sources; +	}  }  struct seat_config *copy_seat_config(struct seat_config *seat) { diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 83b5212d..680fe39e 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -206,7 +206,7 @@ void cursor_handle_activity(struct sway_cursor *cursor) {  	wl_event_source_timer_update(  			cursor->hide_source, cursor_get_timeout(cursor)); -	wlr_idle_notify_activity(server.idle, cursor->seat->wlr_seat); +	seat_idle_notify_activity(cursor->seat, IDLE_SOURCE_POINTER);  	if (cursor->hidden) {  		cursor_unhide(cursor);  	} @@ -341,7 +341,7 @@ static void handle_cursor_frame(struct wl_listener *listener, void *data) {  static void handle_touch_down(struct wl_listener *listener, void *data) {  	struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); -	wlr_idle_notify_activity(server.idle, cursor->seat->wlr_seat); +	seat_idle_notify_activity(cursor->seat, IDLE_SOURCE_TOUCH);  	struct wlr_event_touch_down *event = data;  	struct sway_seat *seat = cursor->seat; @@ -372,7 +372,7 @@ static void handle_touch_down(struct wl_listener *listener, void *data) {  static void handle_touch_up(struct wl_listener *listener, void *data) {  	struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); -	wlr_idle_notify_activity(server.idle, cursor->seat->wlr_seat); +	seat_idle_notify_activity(cursor->seat, IDLE_SOURCE_TOUCH);  	struct wlr_event_touch_up *event = data;  	struct wlr_seat *seat = cursor->seat->wlr_seat;  	// TODO: fall back to cursor simulation if client has not bound to touch @@ -382,7 +382,7 @@ static void handle_touch_up(struct wl_listener *listener, void *data) {  static void handle_touch_motion(struct wl_listener *listener, void *data) {  	struct sway_cursor *cursor =  		wl_container_of(listener, cursor, touch_motion); -	wlr_idle_notify_activity(server.idle, cursor->seat->wlr_seat); +	seat_idle_notify_activity(cursor->seat, IDLE_SOURCE_TOUCH);  	struct wlr_event_touch_motion *event = data;  	struct sway_seat *seat = cursor->seat; @@ -492,7 +492,7 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor,  static void handle_tool_axis(struct wl_listener *listener, void *data) {  	struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); -	wlr_idle_notify_activity(server.idle, cursor->seat->wlr_seat); +	seat_idle_notify_activity(cursor->seat, IDLE_SOURCE_TABLET_TOOL);  	struct wlr_event_tablet_tool_axis *event = data;  	struct sway_tablet_tool *sway_tool = event->tool->data; @@ -548,7 +548,7 @@ static void handle_tool_axis(struct wl_listener *listener, void *data) {  static void handle_tool_tip(struct wl_listener *listener, void *data) {  	struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); -	wlr_idle_notify_activity(server.idle, cursor->seat->wlr_seat); +	seat_idle_notify_activity(cursor->seat, IDLE_SOURCE_TABLET_TOOL);  	struct wlr_event_tablet_tool_tip *event = data;  	struct sway_tablet_tool *sway_tool = event->tool->data;  	struct wlr_tablet_v2_tablet *tablet_v2 = sway_tool->tablet->tablet_v2; @@ -589,7 +589,7 @@ static struct sway_tablet *get_tablet_for_device(struct sway_cursor *cursor,  static void handle_tool_proximity(struct wl_listener *listener, void *data) {  	struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_proximity); -	wlr_idle_notify_activity(server.idle, cursor->seat->wlr_seat); +	seat_idle_notify_activity(cursor->seat, IDLE_SOURCE_TABLET_TOOL);  	struct wlr_event_tablet_tool_proximity *event = data;  	struct wlr_tablet_tool *tool = event->tool; @@ -619,7 +619,7 @@ static void handle_tool_proximity(struct wl_listener *listener, void *data) {  static void handle_tool_button(struct wl_listener *listener, void *data) {  	struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button); -	wlr_idle_notify_activity(server.idle, cursor->seat->wlr_seat); +	seat_idle_notify_activity(cursor->seat, IDLE_SOURCE_TABLET_TOOL);  	struct wlr_event_tablet_tool_button *event = data;  	struct sway_tablet_tool *sway_tool = event->tool->data;  	struct wlr_tablet_v2_tablet *tablet_v2 = sway_tool->tablet->tablet_v2; diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index c4ce8246..1d55c165 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -326,7 +326,7 @@ static void handle_key_event(struct sway_keyboard *keyboard,  		keyboard->seat_device->input_device->wlr_device;  	char *device_identifier = input_device_get_identifier(wlr_device);  	bool exact_identifier = wlr_device->keyboard->group != NULL; -	wlr_idle_notify_activity(server.idle, wlr_seat); +	seat_idle_notify_activity(seat, IDLE_SOURCE_KEYBOARD);  	bool input_inhibited = seat->exclusive_client != NULL;  	// Identify new keycode, raw keysym(s), and translated keysym(s) diff --git a/sway/input/seat.c b/sway/input/seat.c index bc72ff0c..371de56e 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -6,6 +6,7 @@  #include <time.h>  #include <wlr/types/wlr_cursor.h>  #include <wlr/types/wlr_data_device.h> +#include <wlr/types/wlr_idle.h>  #include <wlr/types/wlr_output_layout.h>  #include <wlr/types/wlr_primary_selection.h>  #include <wlr/types/wlr_tablet_v2.h> @@ -71,6 +72,25 @@ static void seat_node_destroy(struct sway_seat_node *seat_node) {  	free(seat_node);  } +void seat_idle_notify_activity(struct sway_seat *seat, +		enum sway_input_idle_source source) { +	uint32_t mask = seat->idle_inhibit_sources; +	struct wlr_idle_timeout *timeout; +	int ntimers = 0, nidle = 0; +	wl_list_for_each(timeout, &server.idle->idle_timers, link) { +		++ntimers; +		if (timeout->idle_state) { +			++nidle; +		} +	} +	if (nidle == ntimers) { +		mask = seat->idle_wake_sources; +	} +	if ((source & mask) > 0) { +		wlr_idle_notify_activity(server.idle, seat->wlr_seat); +	} +} +  /**   * Activate all views within this container recursively.   */ @@ -491,6 +511,14 @@ struct sway_seat *seat_create(const char *seat_name) {  		return NULL;  	} +	seat->idle_inhibit_sources = seat->idle_wake_sources = +		IDLE_SOURCE_KEYBOARD | +		IDLE_SOURCE_POINTER | +		IDLE_SOURCE_TOUCH | +		IDLE_SOURCE_TABLET_PAD | +		IDLE_SOURCE_TABLET_TOOL | +		IDLE_SOURCE_SWITCH; +  	// init the focus stack  	wl_list_init(&seat->focus_stack); @@ -1325,6 +1353,9 @@ void seat_apply_config(struct sway_seat *seat,  		return;  	} +	seat->idle_inhibit_sources = seat_config->idle_inhibit_sources; +	seat->idle_wake_sources = seat_config->idle_wake_sources; +  	wl_list_for_each(seat_device, &seat->devices, link) {  		seat_configure_device(seat, seat_device->input_device);  	} diff --git a/sway/input/switch.c b/sway/input/switch.c index 72d1245f..b7c28df1 100644 --- a/sway/input/switch.c +++ b/sway/input/switch.c @@ -70,8 +70,8 @@ static void handle_switch_toggle(struct wl_listener *listener, void *data) {  	struct sway_switch *sway_switch =  			wl_container_of(listener, sway_switch, switch_toggle);  	struct wlr_event_switch_toggle *event = data; -	struct wlr_seat* wlr_seat = sway_switch->seat_device->sway_seat->wlr_seat; -	wlr_idle_notify_activity(server.idle, wlr_seat); +	struct sway_seat *seat = sway_switch->seat_device->sway_seat; +	seat_idle_notify_activity(seat, IDLE_SOURCE_SWITCH);  	struct wlr_input_device *wlr_device =  		sway_switch->seat_device->input_device->wlr_device; diff --git a/sway/meson.build b/sway/meson.build index 3e6e4da6..20fe02fb 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -91,6 +91,7 @@ sway_sources = files(  	'commands/seat/cursor.c',  	'commands/seat/fallback.c',  	'commands/seat/hide_cursor.c', +	'commands/seat/idle.c',  	'commands/seat/keyboard_grouping.c',  	'commands/seat/pointer_constraint.c',  	'commands/seat/xcursor_theme.c', diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index 5631293c..e1ae6781 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -218,6 +218,18 @@ correct seat.  	disables hiding the cursor. The minimal timeout is 100 and any value less  	than that (aside from 0), will be increased to 100. +*seat* <name> idle_inhibit <sources...> +	Sets the set of input event sources which can prevent the seat from +	becoming idle, as a space separated list of source names. Valid names are +	"keyboard", "pointer", "touchpad", "touch", "tablet_pad", "tablet_tool", +	and "switch". The default behavior is to prevent idle on any event. + +*seat* <name> idle_wake <sources...> +	Sets the set of input event sources which can wake the seat from +	its idle state, as a space separated list of source names. Valid names are +	"keyboard", "pointer", "touchpad", "touch", "tablet pad", "tablet tool", +	and "switch". The default behavior is to wake from idle on any event. +  *seat* <name> keyboard_grouping none|keymap  	Set how the keyboards in the seat are grouped together. Currently, there  	are two options. _none_ will disable all keyboard grouping. This will make  | 
