aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sway/commands.h2
-rw-r--r--include/sway/config.h10
-rw-r--r--include/sway/input/seat.h6
-rw-r--r--sway/commands/seat.c2
-rw-r--r--sway/commands/seat/idle.c73
-rw-r--r--sway/config/seat.c11
-rw-r--r--sway/input/cursor.c16
-rw-r--r--sway/input/keyboard.c2
-rw-r--r--sway/input/seat.c31
-rw-r--r--sway/input/switch.c4
-rw-r--r--sway/meson.build1
-rw-r--r--sway/sway-input.5.scd12
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