logind: rework power key/suspend key/lid switch handling

http://lists.freedesktop.org/archives/systemd-devel/2012-September/006604.html
https://bugzilla.gnome.org/show_bug.cgi?id=680689

This changes the meaning of the
HandlePowerKey=/HandleSleepKey=/HandleLidSwitch= setting of logind.conf
This commit is contained in:
Lennart Poettering 2012-09-19 13:10:10 +02:00
parent 468b21de7c
commit beaafb2ea6
11 changed files with 250 additions and 227 deletions

View file

@ -204,49 +204,57 @@
<listitem><para>Controls whether <listitem><para>Controls whether
logind shall handle the system power logind shall handle the system power
and sleep keys and the lid switch to and sleep keys and the lid switch to
trigger system power-off or trigger actions such as system
suspend. Can be one of power-off or suspend. Can be one of
<literal>off</literal>, <literal>ignore</literal>,
<literal>no-session</literal>, <literal>poweroff</literal>,
<literal>tty-session</literal>, <literal>reboot</literal>,
<literal>any-session</literal> and <literal>halt</literal>,
<literal>always</literal>. If <literal>kexec</literal> and
<literal>off</literal> logind will <literal>hibernate</literal>. If
never handle these keys. If <literal>ignore</literal> logind will
<literal>no-session</literal> logind never handle these keys. Otherwise the
will handle these keys when no user is specified action will be taken in the
logged in and no inhibitor lock is respective event. Only input devices
taken, and trigger a warning beep with the
otherwise. If set to
<literal>tty-session</literal> logind
will handle these keys if no inhibitor
lock is taken, and either no user is
logged in or the foreground session is
a text login and the only one
existing. If
<literal>any-session</literal> is set
logind will handle these keys if no
inhibitor lock is taken, and either no
user is logged in or the foreground
session is the only one existing
(regardless whether graphical or
text). If set to
<literal>always</literal> logind will
handle these keys in any case, even if
one or more users are logged in or an
inhibitor lock is taken. Only input
devices with the
<literal>power-switch</literal> udev <literal>power-switch</literal> udev
tag will be watched for key tag will be watched for key/lid switch
events. <varname>HandlePowerKey=</varname> events. <varname>HandlePowerKey=</varname>
defaults to defaults to
<literal>no-session</literal>. <literal>poweroff</literal>.
<varname>HandleSleepKey=</varname> <varname>HandleSleepKey=</varname> and
defaults to
<literal>tty-session</literal>,
<varname>HandleLidSwitch=</varname> <varname>HandleLidSwitch=</varname>
default to
<literal>suspend</literal>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>PowerKeyIgnoreInhibited=</varname></term>
<term><varname>SleepKeyIgnoreInhibited=</varname></term>
<term><varname>LidSwitchIgnoreInhibited=</varname></term>
<listitem><para>Controls whether
actions triggered by the power and
sleep keys and the lid switch are
subject to inhibitor locks. These
settings take boolean arguments. If
<literal>off</literal> the inhibitor
locks taken by applications in order
to block the requested operation are
respected, if <literal>on</literal>
the requested operation is executed in
any
case. <varname>PowerKeyIgnoreInhibited=</varname>
and
<varname>SleepKeyIgnoreInhibited=</varname>
defaults to <literal>off</literal>,
<varname>LidSwitchIgnoreInhibited=</varname>
defaults to defaults to
<literal>off</literal>.</para></listitem> <literal>yes</literal>. This means
that the lid switch does not respect
suspend blockers by default, but the
power and sleep keys do.
</para></listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>

View file

@ -150,127 +150,60 @@ fail:
return r; return r;
} }
static Session *button_get_session(Button *b) { static int button_handle(Button *b, InhibitWhat inhibit_key, HandleButton handle, bool ignore_inhibited) {
Seat *seat;
assert(b);
if (!b->seat) static const char * const message_table[_HANDLE_BUTTON_MAX] = {
return NULL; [HANDLE_POWEROFF] = "Powering Off...",
[HANDLE_REBOOT] = "Rebooting...",
[HANDLE_HALT] = "Halting...",
[HANDLE_KEXEC] = "Rebooting via kexec...",
[HANDLE_SUSPEND] = "Suspending...",
[HANDLE_HIBERNATE] = "Hibernating..."
};
seat = hashmap_get(b->manager->seats, b->seat); static const char * const target_table[_HANDLE_BUTTON_MAX] = {
if (!seat) [HANDLE_POWEROFF] = "poweroff.target",
return NULL; [HANDLE_REBOOT] = "reboot.target",
[HANDLE_HALT] = "halt.target",
[HANDLE_KEXEC] = "kexec.target",
[HANDLE_SUSPEND] = "suspend.target",
[HANDLE_HIBERNATE] = "hibernate.target"
};
return seat->active;
}
static int button_power_off(Button *b, HandleButton handle) {
DBusError error; DBusError error;
int r; int r;
InhibitWhat inhibit_operation;
assert(b); assert(b);
if (handle == HANDLE_OFF) /* If the key handling is turned off, don't do anything */
if (handle == HANDLE_IGNORE) {
log_debug("Refusing key handling, as it is turned off.");
return 0; return 0;
if (handle == HANDLE_NO_SESSION) {
if (hashmap_size(b->manager->sessions) > 0) {
log_error("Refusing power-off, user is logged in.");
warn_melody();
return -EPERM;
}
} else if (handle == HANDLE_TTY_SESSION ||
handle == HANDLE_ANY_SESSION) {
unsigned n;
Session *s;
n = hashmap_size(b->manager->sessions);
s = button_get_session(b);
/* Silently ignore events of graphical sessions */
if (handle == HANDLE_TTY_SESSION &&
s && s->type == SESSION_X11)
return 0;
if (n > 1 || (n == 1 && !s)) {
log_error("Refusing power-off, other user is logged in.");
warn_melody();
return -EPERM;
}
} }
if (handle != HANDLE_ALWAYS) { /* If the key handling is inhibited, don't do anything */
if (manager_is_inhibited(b->manager, INHIBIT_SHUTDOWN, INHIBIT_BLOCK, NULL)) { if (manager_is_inhibited(b->manager, inhibit_key, INHIBIT_BLOCK, NULL, true)) {
log_error("Refusing power-off, shutdown is inhibited."); log_debug("Refusing key handling, %s is inhibited.", inhibit_what_to_string(inhibit_key));
warn_melody(); return 0;
return -EPERM;
}
} }
log_info("Powering off..."); inhibit_operation = handle == HANDLE_SUSPEND || handle == HANDLE_HIBERNATE ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN;
/* If the actual operation is inhibited, warn and fail */
if (!ignore_inhibited &&
manager_is_inhibited(b->manager, inhibit_operation, INHIBIT_BLOCK, NULL, false)) {
log_error("Refusing operation, %s is inhibited.", inhibit_what_to_string(inhibit_operation));
warn_melody();
return -EPERM;
}
log_info("%s", message_table[handle]);
dbus_error_init(&error); dbus_error_init(&error);
r = bus_manager_shutdown_or_sleep_now_or_later(b->manager, SPECIAL_POWEROFF_TARGET, INHIBIT_SHUTDOWN, &error); r = bus_manager_shutdown_or_sleep_now_or_later(b->manager, target_table[handle], inhibit_operation, &error);
if (r < 0) { if (r < 0) {
log_error("Failed to power off: %s", bus_error_message(&error)); log_error("Failed to execute operation: %s", bus_error_message(&error));
dbus_error_free(&error);
}
return r;
}
static int button_suspend(Button *b, HandleButton handle) {
DBusError error;
int r;
assert(b);
if (handle == HANDLE_OFF)
return 0;
if (handle == HANDLE_NO_SESSION) {
if (hashmap_size(b->manager->sessions) > 0) {
log_error("Refusing suspend, user is logged in.");
warn_melody();
return -EPERM;
}
} else if (handle == HANDLE_TTY_SESSION ||
handle == HANDLE_ANY_SESSION) {
unsigned n;
Session *s;
n = hashmap_size(b->manager->sessions);
s = button_get_session(b);
/* Silently ignore events of graphical sessions */
if (handle == HANDLE_TTY_SESSION &&
s && s->type == SESSION_X11)
return 0;
if (n > 1 || (n == 1 && !s)) {
log_error("Refusing suspend, other user is logged in.");
warn_melody();
return -EPERM;
}
}
if (handle != HANDLE_ALWAYS) {
if (manager_is_inhibited(b->manager, INHIBIT_SLEEP, INHIBIT_BLOCK, NULL)) {
log_error("Refusing suspend, sleeping is inhibited.");
warn_melody();
return -EPERM;
}
}
log_info("Suspending...");
dbus_error_init(&error);
r = bus_manager_shutdown_or_sleep_now_or_later(b->manager, SPECIAL_SUSPEND_TARGET, INHIBIT_SLEEP, &error);
if (r < 0) {
log_error("Failed to suspend: %s", bus_error_message(&error));
dbus_error_free(&error); dbus_error_free(&error);
} }
@ -296,12 +229,12 @@ int button_process(Button *b) {
case KEY_POWER: case KEY_POWER:
case KEY_POWER2: case KEY_POWER2:
log_info("Power key pressed."); log_info("Power key pressed.");
return button_power_off(b, b->manager->handle_power_key); return button_handle(b, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited);
case KEY_SLEEP: case KEY_SLEEP:
case KEY_SUSPEND: case KEY_SUSPEND:
log_info("Sleep key pressed."); log_info("Sleep key pressed.");
return button_suspend(b, b->manager->handle_sleep_key); return button_handle(b, INHIBIT_HANDLE_SLEEP_KEY, b->manager->handle_sleep_key, b->manager->sleep_key_ignore_inhibited);
} }
} else if (ev.type == EV_SW && ev.value > 0) { } else if (ev.type == EV_SW && ev.value > 0) {
@ -310,7 +243,7 @@ int button_process(Button *b) {
case SW_LID: case SW_LID:
log_info("Lid closed."); log_info("Lid closed.");
return button_suspend(b, b->manager->handle_lid_switch); return button_handle(b, INHIBIT_HANDLE_LID_SWITCH, b->manager->handle_lid_switch, b->manager->lid_switch_ignore_inhibited);
} }
} }
@ -318,11 +251,13 @@ int button_process(Button *b) {
} }
static const char* const handle_button_table[_HANDLE_BUTTON_MAX] = { static const char* const handle_button_table[_HANDLE_BUTTON_MAX] = {
[HANDLE_OFF] = "off", [HANDLE_IGNORE] = "ignore",
[HANDLE_NO_SESSION] = "no-session", [HANDLE_POWEROFF] = "poweroff",
[HANDLE_TTY_SESSION] = "tty-session", [HANDLE_REBOOT] = "reboot",
[HANDLE_ANY_SESSION] = "any-session", [HANDLE_HALT] = "halt",
[HANDLE_ALWAYS] = "always" [HANDLE_KEXEC] = "kexec",
[HANDLE_SUSPEND] = "suspend",
[HANDLE_HIBERNATE] = "hibernate"
}; };
DEFINE_STRING_TABLE_LOOKUP(handle_button, HandleButton); DEFINE_STRING_TABLE_LOOKUP(handle_button, HandleButton);
DEFINE_CONFIG_PARSE_ENUM(config_parse_handle_button, handle_button, HandleButton, "Failed to parse handle button setting"); DEFINE_CONFIG_PARSE_ENUM(config_parse_handle_button, handle_button, HandleButton, "Failed to parse handle button setting");

View file

@ -25,11 +25,13 @@
typedef struct Button Button; typedef struct Button Button;
typedef enum HandleButton { typedef enum HandleButton {
HANDLE_OFF, HANDLE_IGNORE,
HANDLE_NO_SESSION, /* Only handle key when nobody is logged in; honour inhibitors */ HANDLE_POWEROFF,
HANDLE_TTY_SESSION, /* Only handle key when nobody is logged in, or the fg session is the only one and non-graphical; honour inhibitors */ HANDLE_REBOOT,
HANDLE_ANY_SESSION, /* Only handle key when nobody is logged in, or the fg session is the only one; honour inhibtors */ HANDLE_HALT,
HANDLE_ALWAYS, /* Always handle, ignore sessions; ignore inhibitors */ HANDLE_KEXEC,
HANDLE_SUSPEND,
HANDLE_HIBERNATE,
_HANDLE_BUTTON_MAX, _HANDLE_BUTTON_MAX,
_HANDLE_BUTTON_INVALID = -1 _HANDLE_BUTTON_INVALID = -1
} HandleButton; } HandleButton;

View file

@ -722,10 +722,19 @@ static int bus_manager_inhibit(Manager *m, DBusConnection *connection, DBusMessa
goto fail; goto fail;
} }
/* Delay is only supported for shutdown/sleep */
if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP))) {
r = -EINVAL;
goto fail;
}
r = verify_polkit(connection, message, r = verify_polkit(connection, message,
w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") : w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") : w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
(mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-idle" : "org.freedesktop.login1.inhibit-delay-idle"), w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
w == INHIBIT_HANDLE_SLEEP_KEY ? "org.freedesktop.login1.inhibit-handle-sleep-key" :
"org.freedesktop.login1.inhibit-handle-lid-switch",
false, NULL, error); false, NULL, error);
if (r < 0) if (r < 0)
goto fail; goto fail;
@ -1079,7 +1088,7 @@ static int bus_manager_can_shutdown_or_sleep(
return r; return r;
multiple_sessions = r > 0; multiple_sessions = r > 0;
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL); blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false);
if (multiple_sessions) { if (multiple_sessions) {
r = verify_polkit(connection, message, action_multiple_sessions, false, &challenge, error); r = verify_polkit(connection, message, action_multiple_sessions, false, &challenge, error);
@ -1193,7 +1202,7 @@ int bus_manager_shutdown_or_sleep_now_or_later(
delayed = delayed =
m->inhibit_delay_max > 0 && m->inhibit_delay_max > 0 &&
manager_is_inhibited(m, w, INHIBIT_DELAY, NULL); manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false);
if (delayed) if (delayed)
/* Shutdown is delayed, keep in mind what we /* Shutdown is delayed, keep in mind what we
@ -1261,7 +1270,7 @@ static int bus_manager_do_shutdown_or_sleep(
return r; return r;
multiple_sessions = r > 0; multiple_sessions = r > 0;
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL); blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false);
if (multiple_sessions) { if (multiple_sessions) {
r = verify_polkit(connection, message, action_multiple_sessions, interactive, NULL, error); r = verify_polkit(connection, message, action_multiple_sessions, interactive, NULL, error);
@ -2294,7 +2303,7 @@ int manager_dispatch_delayed(Manager *manager) {
/* Continue delay? */ /* Continue delay? */
delayed = delayed =
manager->delayed_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC) && manager->delayed_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC) &&
manager_is_inhibited(manager, manager->delayed_what, INHIBIT_DELAY, NULL); manager_is_inhibited(manager, manager->delayed_what, INHIBIT_DELAY, NULL, false);
if (delayed) if (delayed)
return 0; return 0;

View file

@ -14,14 +14,17 @@ struct ConfigPerfItem;
%struct-type %struct-type
%includes %includes
%% %%
Login.NAutoVTs, config_parse_unsigned, 0, offsetof(Manager, n_autovts) Login.NAutoVTs, config_parse_unsigned, 0, offsetof(Manager, n_autovts)
Login.ReserveVT, config_parse_unsigned, 0, offsetof(Manager, reserve_vt) Login.ReserveVT, config_parse_unsigned, 0, offsetof(Manager, reserve_vt)
Login.KillUserProcesses, config_parse_bool, 0, offsetof(Manager, kill_user_processes) Login.KillUserProcesses, config_parse_bool, 0, offsetof(Manager, kill_user_processes)
Login.KillOnlyUsers, config_parse_strv, 0, offsetof(Manager, kill_only_users) Login.KillOnlyUsers, config_parse_strv, 0, offsetof(Manager, kill_only_users)
Login.KillExcludeUsers, config_parse_strv, 0, offsetof(Manager, kill_exclude_users) Login.KillExcludeUsers, config_parse_strv, 0, offsetof(Manager, kill_exclude_users)
Login.Controllers, config_parse_strv, 0, offsetof(Manager, controllers) Login.Controllers, config_parse_strv, 0, offsetof(Manager, controllers)
Login.ResetControllers, config_parse_strv, 0, offsetof(Manager, reset_controllers) Login.ResetControllers, config_parse_strv, 0, offsetof(Manager, reset_controllers)
Login.InhibitDelayMaxSec,config_parse_usec, 0, offsetof(Manager, inhibit_delay_max) Login.InhibitDelayMaxSec, config_parse_usec, 0, offsetof(Manager, inhibit_delay_max)
Login.HandlePowerKey, config_parse_handle_button, 0, offsetof(Manager, handle_power_key) Login.HandlePowerKey, config_parse_handle_button, 0, offsetof(Manager, handle_power_key)
Login.HandleSleepKey, config_parse_handle_button, 0, offsetof(Manager, handle_sleep_key) Login.HandleSleepKey, config_parse_handle_button, 0, offsetof(Manager, handle_sleep_key)
Login.HandleLidSwitch, config_parse_handle_button, 0, offsetof(Manager, handle_lid_switch) Login.HandleLidSwitch, config_parse_handle_button, 0, offsetof(Manager, handle_lid_switch)
Login.PowerKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, power_key_ignore_inhibited)
Login.SleepKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, sleep_key_ignore_inhibited)
Login.LidSwitchIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, lid_switch_ignore_inhibited)

View file

@ -348,7 +348,24 @@ InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm) {
return what; return what;
} }
bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timestamp *since) { static int pid_is_active(Manager *m, pid_t pid) {
Session *s;
int r;
r = manager_get_session_by_pid(m, pid, &s);
if (r <= 0)
return r;
return session_is_active(s);
}
bool manager_is_inhibited(
Manager *m,
InhibitWhat w,
InhibitMode mm,
dual_timestamp *since,
bool only_active) {
Inhibitor *i; Inhibitor *i;
Iterator j; Iterator j;
struct dual_timestamp ts = { 0, 0 }; struct dual_timestamp ts = { 0, 0 };
@ -364,6 +381,9 @@ bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timest
if (i->mode != mm) if (i->mode != mm)
continue; continue;
if (only_active && pid_is_active(m, i->pid) <= 0)
continue;
if (!inhibited || if (!inhibited ||
i->since.monotonic < ts.monotonic) i->since.monotonic < ts.monotonic)
ts = i->since; ts = i->since;
@ -378,22 +398,32 @@ bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timest
} }
const char *inhibit_what_to_string(InhibitWhat w) { const char *inhibit_what_to_string(InhibitWhat w) {
static __thread char buffer[73];
static const char* const table[_INHIBIT_WHAT_MAX] = { char *p;
[0] = "",
[INHIBIT_SHUTDOWN] = "shutdown",
[INHIBIT_SLEEP] = "sleep",
[INHIBIT_IDLE] = "idle",
[INHIBIT_SHUTDOWN|INHIBIT_SLEEP] = "shutdown:sleep",
[INHIBIT_SHUTDOWN|INHIBIT_IDLE] = "shutdown:idle",
[INHIBIT_SHUTDOWN|INHIBIT_SLEEP|INHIBIT_IDLE] = "shutdown:sleep:idle",
[INHIBIT_SLEEP|INHIBIT_IDLE] = "sleep:idle"
};
if (w < 0 || w >= _INHIBIT_WHAT_MAX) if (w < 0 || w >= _INHIBIT_WHAT_MAX)
return NULL; return NULL;
return table[w]; p = buffer;
if (w & INHIBIT_SHUTDOWN)
p = stpcpy(p, "shutdown:");
if (w & INHIBIT_SLEEP)
p = stpcpy(p, "sleep:");
if (w & INHIBIT_IDLE)
p = stpcpy(p, "idle:");
if (w & INHIBIT_HANDLE_POWER_KEY)
p = stpcpy(p, "handle-power-key:");
if (w & INHIBIT_HANDLE_SLEEP_KEY)
p = stpcpy(p, "handle-sleep-key:");
if (w & INHIBIT_HANDLE_LID_SWITCH)
p = stpcpy(p, "handle-lid-switch:");
if (p > buffer)
*(p-1) = 0;
else
*p = 0;
return buffer;
} }
InhibitWhat inhibit_what_from_string(const char *s) { InhibitWhat inhibit_what_from_string(const char *s) {
@ -408,12 +438,17 @@ InhibitWhat inhibit_what_from_string(const char *s) {
what |= INHIBIT_SLEEP; what |= INHIBIT_SLEEP;
else if (l == 4 && strncmp(w, "idle", l) == 0) else if (l == 4 && strncmp(w, "idle", l) == 0)
what |= INHIBIT_IDLE; what |= INHIBIT_IDLE;
else if (l == 16 && strncmp(w, "handle-power-key", l) == 0)
what |= INHIBIT_HANDLE_POWER_KEY;
else if (l == 16 && strncmp(w, "handle-sleep-key", l) == 0)
what |= INHIBIT_HANDLE_SLEEP_KEY;
else if (l == 16 && strncmp(w, "handle-lid-switch", l) == 0)
what |= INHIBIT_HANDLE_LID_SWITCH;
else else
return _INHIBIT_WHAT_INVALID; return _INHIBIT_WHAT_INVALID;
} }
return what; return what;
} }
static const char* const inhibit_mode_table[_INHIBIT_MODE_MAX] = { static const char* const inhibit_mode_table[_INHIBIT_MODE_MAX] = {

View file

@ -31,7 +31,10 @@ typedef enum InhibitWhat {
INHIBIT_SHUTDOWN = 1, INHIBIT_SHUTDOWN = 1,
INHIBIT_SLEEP = 2, INHIBIT_SLEEP = 2,
INHIBIT_IDLE = 4, INHIBIT_IDLE = 4,
_INHIBIT_WHAT_MAX = 8, INHIBIT_HANDLE_POWER_KEY = 8,
INHIBIT_HANDLE_SLEEP_KEY = 16,
INHIBIT_HANDLE_LID_SWITCH = 32,
_INHIBIT_WHAT_MAX = 64,
_INHIBIT_WHAT_INVALID = -1 _INHIBIT_WHAT_INVALID = -1
} InhibitWhat; } InhibitWhat;
@ -80,7 +83,7 @@ int inhibitor_create_fifo(Inhibitor *i);
void inhibitor_remove_fifo(Inhibitor *i); void inhibitor_remove_fifo(Inhibitor *i);
InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm); InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm);
bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timestamp *since); bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timestamp *since, bool only_active);
const char *inhibit_what_to_string(InhibitWhat k); const char *inhibit_what_to_string(InhibitWhat k);
InhibitWhat inhibit_what_from_string(const char *s); InhibitWhat inhibit_what_from_string(const char *s);

View file

@ -55,9 +55,10 @@ Manager *manager_new(void) {
m->n_autovts = 6; m->n_autovts = 6;
m->reserve_vt = 6; m->reserve_vt = 6;
m->inhibit_delay_max = 5 * USEC_PER_SEC; m->inhibit_delay_max = 5 * USEC_PER_SEC;
m->handle_power_key = HANDLE_NO_SESSION; m->handle_power_key = HANDLE_POWEROFF;
m->handle_sleep_key = HANDLE_TTY_SESSION; m->handle_sleep_key = HANDLE_SUSPEND;
m->handle_lid_switch = HANDLE_OFF; m->handle_lid_switch = HANDLE_SUSPEND;
m->lid_switch_ignore_inhibited = true;
m->devices = hashmap_new(string_hash_func, string_compare_func); m->devices = hashmap_new(string_hash_func, string_compare_func);
m->seats = hashmap_new(string_hash_func, string_compare_func); m->seats = hashmap_new(string_hash_func, string_compare_func);
@ -494,9 +495,9 @@ int manager_enumerate_buttons(Manager *m) {
/* Loads buttons from udev */ /* Loads buttons from udev */
if (m->handle_power_key == HANDLE_OFF && if (m->handle_power_key == HANDLE_IGNORE &&
m->handle_sleep_key == HANDLE_OFF && m->handle_sleep_key == HANDLE_IGNORE &&
m->handle_lid_switch == HANDLE_OFF) m->handle_lid_switch == HANDLE_IGNORE)
return 0; return 0;
e = udev_enumerate_new(m->udev); e = udev_enumerate_new(m->udev);
@ -1304,9 +1305,9 @@ static int manager_connect_udev(Manager *m) {
return -errno; return -errno;
/* Don't watch keys if nobody cares */ /* Don't watch keys if nobody cares */
if (m->handle_power_key != HANDLE_OFF || if (m->handle_power_key != HANDLE_IGNORE ||
m->handle_sleep_key != HANDLE_OFF || m->handle_sleep_key != HANDLE_IGNORE ||
m->handle_lid_switch != HANDLE_OFF) { m->handle_lid_switch != HANDLE_IGNORE) {
m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev"); m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
if (!m->udev_button_monitor) if (!m->udev_button_monitor)
@ -1406,7 +1407,7 @@ int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
assert(m); assert(m);
idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t); idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false);
HASHMAP_FOREACH(s, m->sessions, i) { HASHMAP_FOREACH(s, m->sessions, i) {
dual_timestamp k; dual_timestamp k;

View file

@ -16,6 +16,9 @@
#Controllers= #Controllers=
#ResetControllers=cpu #ResetControllers=cpu
#InhibitDelayMaxSec=5 #InhibitDelayMaxSec=5
#HandlePowerKey=no-session #HandlePowerKey=poweroff
#HandleSleepKey=tty-session #HandleSleepKey=suspend
#HandleLidSwitch=off #HandleLidSwitch=suspend
#PowerKeyIgnoreInhibited=no
#SleepKeyIgnoreInhibited=no
#LidSwitchIgnoreInhibited=yes

View file

@ -102,6 +102,10 @@ struct Manager {
HandleButton handle_power_key; HandleButton handle_power_key;
HandleButton handle_sleep_key; HandleButton handle_sleep_key;
HandleButton handle_lid_switch; HandleButton handle_lid_switch;
bool power_key_ignore_inhibited;
bool sleep_key_ignore_inhibited;
bool lid_switch_ignore_inhibited;
}; };
enum { enum {

View file

@ -20,27 +20,7 @@
<_description>Allow applications to inhibit system shutdown</_description> <_description>Allow applications to inhibit system shutdown</_description>
<_message>Authentication is required to allow an application to inhibit system shutdown.</_message> <_message>Authentication is required to allow an application to inhibit system shutdown.</_message>
<defaults> <defaults>
<allow_any>auth_admin_keep</allow_any> <allow_any>no</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.freedesktop.login1.inhibit-block-sleep">
<_description>Allow applications to inhibit system sleep</_description>
<_message>Authentication is required to allow an application to inhibit system sleep.</_message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.freedesktop.login1.inhibit-block-idle">
<_description>Allow applications to inhibit automatic system suspend</_description>
<_message>Authentication is required to allow an application to inhibit automatic system suspend.</_message>
<defaults>
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive> <allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active> <allow_active>yes</allow_active>
</defaults> </defaults>
@ -56,6 +36,16 @@
</defaults> </defaults>
</action> </action>
<action id="org.freedesktop.login1.inhibit-block-sleep">
<_description>Allow applications to inhibit system sleep</_description>
<_message>Authentication is required to allow an application to inhibit system sleep.</_message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.freedesktop.login1.inhibit-delay-sleep"> <action id="org.freedesktop.login1.inhibit-delay-sleep">
<_description>Allow applications to delay system sleep</_description> <_description>Allow applications to delay system sleep</_description>
<_message>Authentication is required to allow an application to delay system sleep.</_message> <_message>Authentication is required to allow an application to delay system sleep.</_message>
@ -66,9 +56,9 @@
</defaults> </defaults>
</action> </action>
<action id="org.freedesktop.login1.inhibit-delay-idle"> <action id="org.freedesktop.login1.inhibit-block-idle">
<_description>Allow applications to delay automatic system suspend</_description> <_description>Allow applications to inhibit automatic system suspend</_description>
<_message>Authentication is required to allow an application to delay automatic system suspend.</_message> <_message>Authentication is required to allow an application to inhibit automatic system suspend.</_message>
<defaults> <defaults>
<allow_any>yes</allow_any> <allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive> <allow_inactive>yes</allow_inactive>
@ -76,6 +66,36 @@
</defaults> </defaults>
</action> </action>
<action id="org.freedesktop.login1.inhibit-handle-power-key">
<_description>Allow applications to inhibit system handling of the power key</_description>
<_message>Authentication is required to allow an application to inhibit system handling of the power key.</_message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.freedesktop.login1.inhibit-handle-sleep-key">
<_description>Allow applications to inhibit system handling of the sleep key</_description>
<_message>Authentication is required to allow an application to inhibit system handling of the sleep key.</_message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.freedesktop.login1.inhibit-handle-lid-switch">
<_description>Allow applications to inhibit system handling of the lid switch</_description>
<_message>Authentication is required to allow an application to inhibit system handling of the lid switch.</_message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.freedesktop.login1.set-user-linger"> <action id="org.freedesktop.login1.set-user-linger">
<_description>Allow non-logged-in users to run programs</_description> <_description>Allow non-logged-in users to run programs</_description>
<_message>Authentication is required to allow a non-logged-in user to run programs.</_message> <_message>Authentication is required to allow a non-logged-in user to run programs.</_message>