Add seat <seat> idle_{inhibit,wake} <sources...>

This adds seat configuration options which can be used to configure what
events affect the idle behavior of sway.

An example use-case is mobile devices: you would remove touch from the
list of idle_wake events. This allows the phone to stay on while you're
actively using it, but doesn't wake from idle on touch events while it's
sleeping in your pocket.
This commit is contained in:
Drew DeVault 2019-12-11 11:00:39 -05:00
parent f645f8efd6
commit 2f3c6cccf5
12 changed files with 159 additions and 11 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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 },

73
sway/commands/seat/idle.c Normal file
View file

@ -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);
}

View file

@ -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) {

View file

@ -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;

View file

@ -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)

View file

@ -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);
}

View file

@ -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;

View file

@ -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',

View file

@ -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