Skip to content

Commit

Permalink
Idle handling for dpms/lockscreen et al
Browse files Browse the repository at this point in the history
Swayidle handles idle events and allows
for dpms and lockscreen handling. It also
handles systemd sleep events, and can
raise a lockscreen on sleep

Fixes swaywm#541
  • Loading branch information
snaggen committed May 10, 2018
1 parent 3bab378 commit 87ad12c
Show file tree
Hide file tree
Showing 15 changed files with 623 additions and 2 deletions.
8 changes: 8 additions & 0 deletions config.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
#
# Read `man 5 sway` for a complete reference.

### Session setup
#
# Power off screen on idle and raise lockscreen
#exec swayidle before-sleep exec 'swaylock -c 000000' \
# timeout 300 exec 'swaylock -c 000000' \
# timeout 600 exec 'swaymsg "output * dpms off"' \
# resume exec 'swaymsg "output * dpms on"'

### Variables
#
# Logo key. Use Mod1 for Alt.
Expand Down
7 changes: 7 additions & 0 deletions include/sway/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ struct seat_config {
list_t *attachments; // list of seat_attachment configs
};

enum config_dpms {
DPMS_IGNORE,
DPMS_ON,
DPMS_OFF
};

/**
* Size and position configuration for a particular output.
*
Expand All @@ -123,6 +129,7 @@ struct output_config {

char *background;
char *background_option;
enum config_dpms dpms_state;
};

/**
Expand Down
1 change: 1 addition & 0 deletions include/sway/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct sway_server {

struct wlr_compositor *compositor;
struct wlr_data_device_manager *data_device_manager;
struct wlr_idle *idle;

struct sway_input_manager *input;

Expand Down
16 changes: 16 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ datadir = get_option('datadir')
sysconfdir = get_option('sysconfdir')
prefix = get_option('prefix')

swayidle_deps = []

jsonc = dependency('json-c', version: '>=0.13')
pcre = dependency('libpcre')
wlroots = dependency('wlroots', fallback: ['wlroots', 'wlroots'])
Expand All @@ -37,6 +39,8 @@ pixman = dependency('pixman-1')
libcap = dependency('libcap')
libinput = dependency('libinput', version: '>=1.6.0')
libpam = cc.find_library('pam')
systemd = dependency('libsystemd', required: false)
elogind = dependency('libelogind', required: false)
math = cc.find_library('m')
rt = cc.find_library('rt')
git = find_program('git', required: false)
Expand All @@ -48,6 +52,16 @@ if gdk_pixbuf.found()
conf_data.set('HAVE_GDK_PIXBUF', true)
endif

if systemd.found()
conf_data.set('SWAY_IDLE_HAS_SYSTEMD', true)
swayidle_deps += systemd
endif

if elogind.found()
conf_data.set('SWAY_IDLE_HAS_ELOGIND', true)
swayidle_deps += elogind
endif

if a2x.found()
mandir = get_option('mandir')
man_files = [
Expand All @@ -57,6 +71,7 @@ if a2x.found()
'sway/sway-input.5.txt',
'sway/sway-security.7.txt',
'swaymsg/swaymsg.1.txt',
'swayidle/swayidle.1.txt',
]
foreach filename : man_files
topic = filename.split('.')[-3].split('/')[-1]
Expand Down Expand Up @@ -108,6 +123,7 @@ subdir('client')
subdir('swaybg')
subdir('swaybar')
subdir('swaylock')
subdir('swayidle')

config = configuration_data()
config.set('sysconfdir', join_paths(prefix, sysconfdir))
Expand Down
49 changes: 49 additions & 0 deletions protocols/idle.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="idle">
<copyright><![CDATA[
Copyright (C) 2015 Martin Gräßlin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
]]></copyright>
<interface name="org_kde_kwin_idle" version="1">
<description summary="User idle time manager">
This interface allows to monitor user idle time on a given seat. The interface
allows to register timers which trigger after no user activity was registered
on the seat for a given interval. It notifies when user activity resumes.

This is useful for applications wanting to perform actions when the user is not
interacting with the system, e.g. chat applications setting the user as away, power
management features to dim screen, etc..
</description>
<request name="get_idle_timeout">
<arg name="id" type="new_id" interface="org_kde_kwin_idle_timeout"/>
<arg name="seat" type="object" interface="wl_seat"/>
<arg name="timeout" type="uint" summary="The idle timeout in msec"/>
</request>
</interface>
<interface name="org_kde_kwin_idle_timeout" version="1">
<request name="release" type="destructor">
<description summary="release the timeout object"/>
</request>
<request name="simulate_user_activity">
<description summary="Simulates user activity for this timeout, behaves just like real user activity on the seat"/>
</request>
<event name="idle">
<description summary="Triggered when there has not been any user activity in the requested idle time interval"/>
</event>
<event name="resumed">
<description summary="Triggered on the first user activity after an idle event"/>
</event>
</interface>
</protocol>
1 change: 1 addition & 0 deletions protocols/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ wayland_scanner_server = generator(
client_protocols = [
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
['wlr-layer-shell-unstable-v1.xml'],
['idle.xml'],
['wlr-input-inhibitor-unstable-v1.xml']
]

Expand Down
22 changes: 20 additions & 2 deletions sway/commands/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@ static char *bg_options[] = {
"tile",
};

static struct cmd_results *cmd_output_dpms(struct output_config *output,
int *i, int argc, char **argv) {

if (++*i >= argc) {
return cmd_results_new(CMD_INVALID, "output", "Missing dpms argument.");
}

char *value = argv[*i];
if (strcmp(value, "on") == 0) {
output->dpms_state = DPMS_ON;
} else if (strcmp(value, "off") == 0) {
output->dpms_state = DPMS_OFF;
}
return NULL;
}

static struct cmd_results *cmd_output_mode(struct output_config *output,
int *i, int argc, char **argv) {
if (++*i >= argc) {
Expand Down Expand Up @@ -263,6 +279,8 @@ struct cmd_results *cmd_output(int argc, char **argv) {
} else if (strcasecmp(command, "background") == 0 ||
strcasecmp(command, "bg") == 0) {
error = cmd_output_background(output, &i, argc, argv);
} else if (strcasecmp(command, "dpms") == 0) {
error = cmd_output_dpms(output, &i, argc, argv);
} else {
error = cmd_results_new(CMD_INVALID, "output",
"Invalid output subcommand: %s.", command);
Expand All @@ -285,10 +303,10 @@ struct cmd_results *cmd_output(int argc, char **argv) {
}

wlr_log(L_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz "
"position %d,%d scale %f transform %d) (bg %s %s)",
"position %d,%d scale %f transform %d) (bg %s %s) (dpms %d)",
output->name, output->enabled, output->width, output->height,
output->refresh_rate, output->x, output->y, output->scale,
output->transform, output->background, output->background_option);
output->transform, output->background, output->background_option, output->dpms_state);

// Try to find the output container and apply configuration now. If
// this is during startup then there will be no container and config
Expand Down
1 change: 1 addition & 0 deletions sway/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ static void config_defaults(struct sway_config *config) {
config->floating_mod = 0;
config->dragging_key = BTN_LEFT;
config->resizing_key = BTN_RIGHT;

if (!(config->floating_scroll_up_cmd = strdup(""))) goto cleanup;
if (!(config->floating_scroll_down_cmd = strdup(""))) goto cleanup;
if (!(config->floating_scroll_left_cmd = strdup(""))) goto cleanup;
Expand Down
17 changes: 17 additions & 0 deletions sway/config/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ void merge_output_config(struct output_config *dst, struct output_config *src) {
free(dst->background_option);
dst->background_option = strdup(src->background_option);
}
if (src->dpms_state != 0) {
dst->dpms_state = src->dpms_state;
}
}

static void set_mode(struct wlr_output *output, int width, int height,
Expand Down Expand Up @@ -204,6 +207,20 @@ void apply_output_config(struct output_config *oc, struct sway_container *output
execvp(cmd[0], cmd);
}
}
if (oc && oc->dpms_state != DPMS_IGNORE) {
switch(oc->dpms_state) {
case DPMS_ON:
wlr_log(L_DEBUG, "Turning on screen");
wlr_output_enable(wlr_output, true);
break;
case DPMS_OFF:
wlr_log(L_DEBUG, "Turning off screen");
wlr_output_enable(wlr_output, false);
break;
case DPMS_IGNORE:
break;
}
}
}

void free_output_config(struct output_config *oc) {
Expand Down
11 changes: 11 additions & 0 deletions sway/input/cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#endif
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/types/wlr_idle.h>
#include "list.h"
#include "log.h"
#include "sway/input/cursor.h"
Expand Down Expand Up @@ -172,6 +173,7 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec)

static void handle_cursor_motion(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, motion);
wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
struct wlr_event_pointer_motion *event = data;
wlr_cursor_move(cursor->cursor, event->device,
event->delta_x, event->delta_y);
Expand All @@ -182,6 +184,7 @@ static void handle_cursor_motion_absolute(
struct wl_listener *listener, void *data) {
struct sway_cursor *cursor =
wl_container_of(listener, cursor, motion_absolute);
wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
struct wlr_event_pointer_motion_absolute *event = data;
wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, event->y);
cursor_send_pointer_motion(cursor, event->time_msec);
Expand Down Expand Up @@ -231,20 +234,23 @@ void dispatch_cursor_button(struct sway_cursor *cursor,

static void handle_cursor_button(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, button);
wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
struct wlr_event_pointer_button *event = data;
dispatch_cursor_button(cursor,
event->time_msec, event->button, event->state);
}

static void handle_cursor_axis(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, axis);
wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
struct wlr_event_pointer_axis *event = data;
wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec,
event->orientation, event->delta);
}

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(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
struct wlr_event_touch_down *event = data;

struct wlr_seat *seat = cursor->seat->wlr_seat;
Expand All @@ -271,6 +277,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(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
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
Expand All @@ -280,6 +287,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(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
struct wlr_event_touch_motion *event = data;

struct wlr_seat *seat = cursor->seat->wlr_seat;
Expand Down Expand Up @@ -331,6 +339,7 @@ static void apply_mapping_from_region(struct wlr_input_device *device,

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(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
struct wlr_event_tablet_tool_axis *event = data;
struct sway_input_device *input_device = event->device->data;

Expand All @@ -353,6 +362,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(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
struct wlr_event_tablet_tool_tip *event = data;
dispatch_cursor_button(cursor, event->time_msec,
BTN_LEFT, event->state == WLR_TABLET_TOOL_TIP_DOWN ?
Expand All @@ -361,6 +371,7 @@ static void handle_tool_tip(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(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
struct wlr_event_tablet_tool_button *event = data;
// TODO: the user may want to configure which tool buttons are mapped to
// which simulated pointer buttons
Expand Down
2 changes: 2 additions & 0 deletions sway/input/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <limits.h>
#include <wlr/backend/multi.h>
#include <wlr/backend/session.h>
#include <wlr/types/wlr_idle.h>
#include "sway/input/seat.h"
#include "sway/input/keyboard.h"
#include "sway/input/input-manager.h"
Expand Down Expand Up @@ -330,6 +331,7 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat;
struct wlr_input_device *wlr_device =
keyboard->seat_device->input_device->wlr_device;
wlr_idle_notify_activity(keyboard->seat_device->sway_seat->input->server->idle, wlr_seat);
struct wlr_event_keyboard_key *event = data;

xkb_keycode_t keycode = event->keycode + 8;
Expand Down
2 changes: 2 additions & 0 deletions sway/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/types/wlr_xdg_output.h>
#include <wlr/types/wlr_wl_shell.h>
#include <wlr/types/wlr_idle.h>
#include <wlr/util/log.h>
// TODO WLR: make Xwayland optional
#include <wlr/xwayland.h>
Expand Down Expand Up @@ -61,6 +62,7 @@ bool server_init(struct sway_server *server) {
server->data_device_manager =
wlr_data_device_manager_create(server->wl_display);

server->idle = wlr_idle_create(server->wl_display);
wlr_screenshooter_create(server->wl_display);
wlr_gamma_control_manager_create(server->wl_display);
wlr_primary_selection_device_manager_create(server->wl_display);
Expand Down
Loading

0 comments on commit 87ad12c

Please sign in to comment.