login: Add a new SecureAttentionKey dbus signal when Ctrl+Alt+Shift+Esc is pressed

This commit is contained in:
nerdopolis 2024-03-11 22:09:07 -04:00 committed by Luca Boccassi
parent f8f06462e5
commit 952b26c75d
14 changed files with 250 additions and 42 deletions

View file

@ -119,6 +119,16 @@ Documentation: sd-login(3)
A seat @SEAT_ID@ has been removed and is no longer available. A seat @SEAT_ID@ has been removed and is no longer available.
-- b2bcbaf5edf948e093ce50bbea0e81ec
Subject: The Secure Attention Key (SAK) was pressed on @SEAT_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
Documentation: man:systemd-logind.service(8)
The Secure Attention Key (SAK), Ctrl+Alt+Shift+Esc, was pressed on @SEAT_ID@.
Pressing the SAK indicates an explicit request by the user for the system to display a secure login dialog or greeter.
-- c7a787079b354eaaa9e77b371893cd27 -- c7a787079b354eaaa9e77b371893cd27
Subject: Time change Subject: Time change
Defined-By: systemd Defined-By: systemd

View file

@ -224,13 +224,14 @@
<term><varname>HandleLidSwitch=</varname></term> <term><varname>HandleLidSwitch=</varname></term>
<term><varname>HandleLidSwitchExternalPower=</varname></term> <term><varname>HandleLidSwitchExternalPower=</varname></term>
<term><varname>HandleLidSwitchDocked=</varname></term> <term><varname>HandleLidSwitchDocked=</varname></term>
<term><varname>HandleSecureAttentionKey=</varname></term>
<listitem><para>Controls how logind shall handle the system power, reboot and sleep keys and the lid <listitem><para>Controls how logind shall handle the system power, reboot and sleep keys and the lid
switch to trigger actions such as system power-off, reboot or suspend. Can be one of switch to trigger actions such as system power-off, reboot or suspend. Can be one of
<literal>ignore</literal>, <literal>poweroff</literal>, <literal>reboot</literal>, <literal>halt</literal>, <literal>ignore</literal>, <literal>poweroff</literal>, <literal>reboot</literal>, <literal>halt</literal>,
<literal>kexec</literal>, <literal>suspend</literal>, <literal>hibernate</literal>, <literal>hybrid-sleep</literal>, <literal>kexec</literal>, <literal>suspend</literal>, <literal>hibernate</literal>, <literal>hybrid-sleep</literal>,
<literal>suspend-then-hibernate</literal>, <literal>sleep</literal>, <literal>lock</literal>, and <literal>suspend-then-hibernate</literal>, <literal>sleep</literal>, <literal>lock</literal>, and
<literal>factory-reset</literal>. If <literal>ignore</literal>, <command>systemd-logind</command> <literal>factory-reset</literal>, <literal>secure-attention-key</literal>. If <literal>ignore</literal>, <command>systemd-logind</command>
will never handle these keys. If <literal>lock</literal>, all running sessions will be screen-locked; will never handle these keys. If <literal>lock</literal>, all running sessions will be screen-locked;
otherwise, the specified action will be taken in the respective event. Only input devices with the otherwise, the specified action will be taken in the respective event. Only input devices with the
<literal>power-switch</literal> udev tag will be watched for key/lid switch <literal>power-switch</literal> udev tag will be watched for key/lid switch
@ -251,7 +252,8 @@
system is inserted in a docking station, or if more than one display is connected, the action system is inserted in a docking station, or if more than one display is connected, the action
specified by <varname>HandleLidSwitchDocked=</varname> occurs; if the system is on external power the specified by <varname>HandleLidSwitchDocked=</varname> occurs; if the system is on external power the
action (if any) specified by <varname>HandleLidSwitchExternalPower=</varname> occurs; otherwise the action (if any) specified by <varname>HandleLidSwitchExternalPower=</varname> occurs; otherwise the
<varname>HandleLidSwitch=</varname> action occurs.</para> <varname>HandleLidSwitch=</varname> action occurs.
<varname>HandleSecureAttentionKey=</varname> defaults to <literal>secure-attention-key</literal></para>
<para>A different application may disable logind's handling of system power and <para>A different application may disable logind's handling of system power and
sleep keys and the lid switch by taking a low-level inhibitor lock sleep keys and the lid switch by taking a low-level inhibitor lock
@ -262,7 +264,7 @@
to take over suspend and hibernation handling, and to use their own configuration to take over suspend and hibernation handling, and to use their own configuration
mechanisms. If a low-level inhibitor lock is taken, logind will not take any mechanisms. If a low-level inhibitor lock is taken, logind will not take any
action when that key or switch is triggered and the <varname>Handle*=</varname> action when that key or switch is triggered and the <varname>Handle*=</varname>
settings are irrelevant.</para> settings are irrelevant, except for <varname>HandleSecureAttentionKey=</varname>, which is always handled since its addition in v257.</para>
<xi:include href="version-info.xml" xpointer="v184"/></listitem> <xi:include href="version-info.xml" xpointer="v184"/></listitem>
</varlistentry> </varlistentry>

View file

@ -169,6 +169,8 @@ node /org/freedesktop/login1 {
SetWallMessage(in s wall_message, SetWallMessage(in s wall_message,
in b enable); in b enable);
signals: signals:
SecureAttentionKey(s seat_id,
o object_path);
SessionNew(s session_id, SessionNew(s session_id,
o object_path); o object_path);
SessionRemoved(s session_id, SessionRemoved(s session_id,
@ -244,6 +246,8 @@ node /org/freedesktop/login1 {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s HandleLidSwitchDocked = '...'; readonly s HandleLidSwitchDocked = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s HandleSecureAttentionKey = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t HoldoffTimeoutUSec = ...; readonly t HoldoffTimeoutUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s IdleAction = '...'; readonly s IdleAction = '...';
@ -296,6 +300,8 @@ node /org/freedesktop/login1 {
<!--property HandleHibernateKeyLongPress is not documented!--> <!--property HandleHibernateKeyLongPress is not documented!-->
<!--property HandleSecureAttentionKey is not documented!-->
<!--property DesignatedMaintenanceTime is not documented!--> <!--property DesignatedMaintenanceTime is not documented!-->
<!--property StopIdleSessionUSec is not documented!--> <!--property StopIdleSessionUSec is not documented!-->
@ -430,6 +436,8 @@ node /org/freedesktop/login1 {
<variablelist class="dbus-method" generated="True" extra-ref="SetWallMessage()"/> <variablelist class="dbus-method" generated="True" extra-ref="SetWallMessage()"/>
<variablelist class="dbus-signal" generated="True" extra-ref="SecureAttentionKey()"/>
<variablelist class="dbus-signal" generated="True" extra-ref="SessionNew()"/> <variablelist class="dbus-signal" generated="True" extra-ref="SessionNew()"/>
<variablelist class="dbus-signal" generated="True" extra-ref="SessionRemoved()"/> <variablelist class="dbus-signal" generated="True" extra-ref="SessionRemoved()"/>
@ -508,6 +516,8 @@ node /org/freedesktop/login1 {
<variablelist class="dbus-property" generated="True" extra-ref="HandleLidSwitchDocked"/> <variablelist class="dbus-property" generated="True" extra-ref="HandleLidSwitchDocked"/>
<variablelist class="dbus-property" generated="True" extra-ref="HandleSecureAttentionKey"/>
<variablelist class="dbus-property" generated="True" extra-ref="HoldoffTimeoutUSec"/> <variablelist class="dbus-property" generated="True" extra-ref="HoldoffTimeoutUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="IdleAction"/> <variablelist class="dbus-property" generated="True" extra-ref="IdleAction"/>
@ -733,6 +743,10 @@ node /org/freedesktop/login1 {
<para>Whenever the inhibition state or idle hint changes, <function>PropertyChanged</function> <para>Whenever the inhibition state or idle hint changes, <function>PropertyChanged</function>
signals are sent out to which clients can subscribe.</para> signals are sent out to which clients can subscribe.</para>
<para>The <function>SecureAttentionKey()</function> signal is sent when the user presses Ctrl+Alt+Shift+Esc to
request the login manager to display the greeter, for instance in the case of a deadlocked compositor.
</para>
<para>The <function>SessionNew()</function>, <function>SessionRemoved()</function>, <para>The <function>SessionNew()</function>, <function>SessionRemoved()</function>,
<function>UserNew()</function>, <function>UserRemoved()</function>, <function>SeatNew()</function>, and <function>UserNew()</function>, <function>UserRemoved()</function>, <function>SeatNew()</function>, and
<function>SeatRemoved()</function> signals are sent each time a session is created or removed, a user <function>SeatRemoved()</function> signals are sent each time a session is created or removed, a user
@ -1590,6 +1604,8 @@ node /org/freedesktop/login1/session/1 {
<varname>SleepOperation</varname>, <varname>SleepOperation</varname>,
<varname>DesignatedMaintenanceTime</varname>, and <varname>DesignatedMaintenanceTime</varname>, and
<function>ListSessionsEx()</function> were added in version 256.</para> <function>ListSessionsEx()</function> were added in version 256.</para>
<para><varname>HandleSecureAttentionKey</varname>, and
<function>SecureAttentionKey()</function> were added in version 257.</para>
</refsect2> </refsect2>
<refsect2> <refsect2>
<title>Session Objects</title> <title>Session Objects</title>

View file

@ -12,6 +12,7 @@
#include "format-util.h" #include "format-util.h"
#include "logind-action.h" #include "logind-action.h"
#include "logind-dbus.h" #include "logind-dbus.h"
#include "logind-seat-dbus.h"
#include "logind-session-dbus.h" #include "logind-session-dbus.h"
#include "process-util.h" #include "process-util.h"
#include "special.h" #include "special.h"
@ -299,12 +300,55 @@ static int handle_action_sleep_execute(
return handle_action_execute(m, handle, ignore_inhibited, is_edge); return handle_action_execute(m, handle, ignore_inhibited, is_edge);
} }
static int manager_handle_action_secure_attention_key(
Manager *m,
bool is_edge,
const char *seat) {
int r;
Seat *o;
_cleanup_free_ char *p = NULL;
assert(m);
if (!is_edge)
return 0;
if (!seat)
return 0;
o = hashmap_get(m->seats, seat);
if (!o)
return 0;
p = seat_bus_path(o);
if (!p)
return log_oom();
log_struct(LOG_INFO,
LOG_MESSAGE("Secure Attention Key sequence pressed on seat %s", seat),
"MESSAGE_ID=" SD_MESSAGE_SECURE_ATTENTION_KEY_PRESS_STR,
"SEAT_ID=%s", seat);
r = sd_bus_emit_signal(
m->bus,
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"SecureAttentionKey",
"so", seat, p);
if (r < 0)
log_warning_errno(r, "Failed to emit SecureAttentionKey signal, ignoring: %m");
return 0;
}
int manager_handle_action( int manager_handle_action(
Manager *m, Manager *m,
InhibitWhat inhibit_key, InhibitWhat inhibit_key,
HandleAction handle, HandleAction handle,
bool ignore_inhibited, bool ignore_inhibited,
bool is_edge) { bool is_edge,
const char *action_seat) {
assert(m); assert(m);
assert(handle_action_valid(handle)); assert(handle_action_valid(handle));
@ -336,7 +380,7 @@ int manager_handle_action(
} }
} }
/* Locking is handled differently from the rest. */ /* Locking and greeter activation is handled differently from the rest. */
if (handle == HANDLE_LOCK) { if (handle == HANDLE_LOCK) {
if (!is_edge) if (!is_edge)
return 0; return 0;
@ -346,6 +390,9 @@ int manager_handle_action(
return 1; return 1;
} }
if (handle == HANDLE_SECURE_ATTENTION_KEY)
return manager_handle_action_secure_attention_key(m, is_edge, action_seat);
if (HANDLE_ACTION_IS_SLEEP(handle)) if (HANDLE_ACTION_IS_SLEEP(handle))
return handle_action_sleep_execute(m, handle, ignore_inhibited, is_edge); return handle_action_sleep_execute(m, handle, ignore_inhibited, is_edge);
@ -366,6 +413,7 @@ static const char* const handle_action_verb_table[_HANDLE_ACTION_MAX] = {
[HANDLE_SLEEP] = "sleep", [HANDLE_SLEEP] = "sleep",
[HANDLE_FACTORY_RESET] = "perform a factory reset", [HANDLE_FACTORY_RESET] = "perform a factory reset",
[HANDLE_LOCK] = "be locked", [HANDLE_LOCK] = "be locked",
[HANDLE_SECURE_ATTENTION_KEY] = "handle the secure attention key",
}; };
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(handle_action_verb, HandleAction); DEFINE_STRING_TABLE_LOOKUP_TO_STRING(handle_action_verb, HandleAction);
@ -386,6 +434,7 @@ static const char* const handle_action_table[_HANDLE_ACTION_MAX] = {
[HANDLE_SLEEP] = "sleep", [HANDLE_SLEEP] = "sleep",
[HANDLE_FACTORY_RESET] = "factory-reset", [HANDLE_FACTORY_RESET] = "factory-reset",
[HANDLE_LOCK] = "lock", [HANDLE_LOCK] = "lock",
[HANDLE_SECURE_ATTENTION_KEY] = "secure-attention-key",
}; };
DEFINE_STRING_TABLE_LOOKUP(handle_action, HandleAction); DEFINE_STRING_TABLE_LOOKUP(handle_action, HandleAction);

View file

@ -22,6 +22,7 @@ typedef enum HandleAction {
HANDLE_SLEEP, /* A "high-level" action that automatically choose an appropriate low-level sleep action */ HANDLE_SLEEP, /* A "high-level" action that automatically choose an appropriate low-level sleep action */
_HANDLE_ACTION_SLEEP_LAST = HANDLE_SLEEP, _HANDLE_ACTION_SLEEP_LAST = HANDLE_SLEEP,
HANDLE_SECURE_ATTENTION_KEY,
HANDLE_LOCK, HANDLE_LOCK,
HANDLE_FACTORY_RESET, HANDLE_FACTORY_RESET,
@ -77,7 +78,8 @@ int manager_handle_action(
InhibitWhat inhibit_key, InhibitWhat inhibit_key,
HandleAction handle, HandleAction handle,
bool ignore_inhibited, bool ignore_inhibited,
bool is_edge); bool is_edge,
const char *action_seat);
const char* handle_action_verb_to_string(HandleAction h) _const_; const char* handle_action_verb_to_string(HandleAction h) _const_;

View file

@ -15,7 +15,36 @@
#include "missing_input.h" #include "missing_input.h"
#include "string-util.h" #include "string-util.h"
#define CONST_MAX5(a, b, c, d, e) CONST_MAX(CONST_MAX(a, b), CONST_MAX(CONST_MAX(c, d), e)) /* KEY_RESTART is the highest value key in keys_interested. */
#define _KEY_MAX_INTERESTED KEY_RESTART
/* Adding more values here may require _KEY_MAX_INTERESTED to be updated, this array must be sorted by key value. */
static const int keys_interested[] = {
KEY_ESC,
KEY_LEFTCTRL,
KEY_LEFTSHIFT,
KEY_RIGHTSHIFT,
KEY_LEFTALT,
KEY_RIGHTCTRL,
KEY_RIGHTALT,
KEY_POWER,
KEY_SLEEP,
KEY_SUSPEND,
KEY_POWER2,
KEY_RESTART,
};
static const struct {
int keycode;
ButtonModifierMask modifier_mask;
} keycode_modifier_table[] = {
{ KEY_LEFTSHIFT, BUTTON_MODIFIER_LEFT_SHIFT },
{ KEY_RIGHTSHIFT, BUTTON_MODIFIER_RIGHT_SHIFT },
{ KEY_LEFTCTRL, BUTTON_MODIFIER_LEFT_CTRL },
{ KEY_RIGHTCTRL, BUTTON_MODIFIER_RIGHT_CTRL },
{ KEY_LEFTALT, BUTTON_MODIFIER_LEFT_ALT },
{ KEY_RIGHTALT, BUTTON_MODIFIER_RIGHT_ALT },
};
#define ULONG_BITS (sizeof(unsigned long)*8) #define ULONG_BITS (sizeof(unsigned long)*8)
@ -48,6 +77,8 @@ Button* button_new(Manager *m, const char *name) {
return mfree(b); return mfree(b);
} }
b->button_modifier_mask = BUTTON_MODIFIER_NONE;
b->manager = m; b->manager = m;
b->fd = -EBADF; b->fd = -EBADF;
@ -77,7 +108,18 @@ int button_set_seat(Button *b, const char *sn) {
return free_and_strdup(&b->seat, sn); return free_and_strdup(&b->seat, sn);
} }
static void button_lid_switch_handle_action(Manager *manager, bool is_edge) { static ButtonModifierMask button_get_keycode_modifier_mask(int keycode) {
assert(keycode > 0);
FOREACH_ELEMENT(i, keycode_modifier_table)
if (i->keycode == keycode)
return i->modifier_mask;
return BUTTON_MODIFIER_NONE;
}
static void button_lid_switch_handle_action(Manager *manager, bool is_edge, const char* seat) {
HandleAction handle_action; HandleAction handle_action;
assert(manager); assert(manager);
@ -91,7 +133,7 @@ static void button_lid_switch_handle_action(Manager *manager, bool is_edge) {
else else
handle_action = manager->handle_lid_switch; handle_action = manager->handle_lid_switch;
manager_handle_action(manager, INHIBIT_HANDLE_LID_SWITCH, handle_action, manager->lid_switch_ignore_inhibited, is_edge); manager_handle_action(manager, INHIBIT_HANDLE_LID_SWITCH, handle_action, manager->lid_switch_ignore_inhibited, is_edge, seat);
} }
static int button_recheck(sd_event_source *e, void *userdata) { static int button_recheck(sd_event_source *e, void *userdata) {
@ -99,7 +141,7 @@ static int button_recheck(sd_event_source *e, void *userdata) {
assert(b->lid_closed); assert(b->lid_closed);
button_lid_switch_handle_action(b->manager, false); button_lid_switch_handle_action(b->manager, /* is_edge= */ false, b->seat);
return 1; return 1;
} }
@ -120,7 +162,8 @@ static int button_install_check_event_source(Button *b) {
} }
static int long_press_of_power_key_handler(sd_event_source *e, uint64_t usec, void *userdata) { static int long_press_of_power_key_handler(sd_event_source *e, uint64_t usec, void *userdata) {
Manager *m = ASSERT_PTR(userdata); Button *b = ASSERT_PTR(userdata);
Manager *m = ASSERT_PTR(b->manager);
assert(e); assert(e);
@ -130,12 +173,13 @@ static int long_press_of_power_key_handler(sd_event_source *e, uint64_t usec, vo
LOG_MESSAGE("Power key pressed long."), LOG_MESSAGE("Power key pressed long."),
"MESSAGE_ID=" SD_MESSAGE_POWER_KEY_LONG_PRESS_STR); "MESSAGE_ID=" SD_MESSAGE_POWER_KEY_LONG_PRESS_STR);
manager_handle_action(m, INHIBIT_HANDLE_POWER_KEY, m->handle_power_key_long_press, m->power_key_ignore_inhibited, true); manager_handle_action(m, INHIBIT_HANDLE_POWER_KEY, m->handle_power_key_long_press, m->power_key_ignore_inhibited, /* is_edge= */ true, b->seat);
return 0; return 0;
} }
static int long_press_of_reboot_key_handler(sd_event_source *e, uint64_t usec, void *userdata) { static int long_press_of_reboot_key_handler(sd_event_source *e, uint64_t usec, void *userdata) {
Manager *m = ASSERT_PTR(userdata); Button *b = ASSERT_PTR(userdata);
Manager *m = ASSERT_PTR(b->manager);
assert(e); assert(e);
@ -145,12 +189,13 @@ static int long_press_of_reboot_key_handler(sd_event_source *e, uint64_t usec, v
LOG_MESSAGE("Reboot key pressed long."), LOG_MESSAGE("Reboot key pressed long."),
"MESSAGE_ID=" SD_MESSAGE_REBOOT_KEY_LONG_PRESS_STR); "MESSAGE_ID=" SD_MESSAGE_REBOOT_KEY_LONG_PRESS_STR);
manager_handle_action(m, INHIBIT_HANDLE_REBOOT_KEY, m->handle_reboot_key_long_press, m->reboot_key_ignore_inhibited, true); manager_handle_action(m, INHIBIT_HANDLE_REBOOT_KEY, m->handle_reboot_key_long_press, m->reboot_key_ignore_inhibited, /* is_edge= */ true, b->seat);
return 0; return 0;
} }
static int long_press_of_suspend_key_handler(sd_event_source *e, uint64_t usec, void *userdata) { static int long_press_of_suspend_key_handler(sd_event_source *e, uint64_t usec, void *userdata) {
Manager *m = ASSERT_PTR(userdata); Button *b = ASSERT_PTR(userdata);
Manager *m = ASSERT_PTR(b->manager);
assert(e); assert(e);
@ -160,12 +205,13 @@ static int long_press_of_suspend_key_handler(sd_event_source *e, uint64_t usec,
LOG_MESSAGE("Suspend key pressed long."), LOG_MESSAGE("Suspend key pressed long."),
"MESSAGE_ID=" SD_MESSAGE_SUSPEND_KEY_LONG_PRESS_STR); "MESSAGE_ID=" SD_MESSAGE_SUSPEND_KEY_LONG_PRESS_STR);
manager_handle_action(m, INHIBIT_HANDLE_SUSPEND_KEY, m->handle_suspend_key_long_press, m->suspend_key_ignore_inhibited, true); manager_handle_action(m, INHIBIT_HANDLE_SUSPEND_KEY, m->handle_suspend_key_long_press, m->suspend_key_ignore_inhibited, /* is_edge= */ true, b->seat);
return 0; return 0;
} }
static int long_press_of_hibernate_key_handler(sd_event_source *e, uint64_t usec, void *userdata) { static int long_press_of_hibernate_key_handler(sd_event_source *e, uint64_t usec, void *userdata) {
Manager *m = ASSERT_PTR(userdata); Button *b = ASSERT_PTR(userdata);
Manager *m = ASSERT_PTR(b->manager);
assert(e); assert(e);
@ -175,15 +221,17 @@ static int long_press_of_hibernate_key_handler(sd_event_source *e, uint64_t usec
LOG_MESSAGE("Hibernate key pressed long."), LOG_MESSAGE("Hibernate key pressed long."),
"MESSAGE_ID=" SD_MESSAGE_HIBERNATE_KEY_LONG_PRESS_STR); "MESSAGE_ID=" SD_MESSAGE_HIBERNATE_KEY_LONG_PRESS_STR);
manager_handle_action(m, INHIBIT_HANDLE_HIBERNATE_KEY, m->handle_hibernate_key_long_press, m->hibernate_key_ignore_inhibited, true); manager_handle_action(m, INHIBIT_HANDLE_HIBERNATE_KEY, m->handle_hibernate_key_long_press, m->hibernate_key_ignore_inhibited, /* is_edge= */ true, b->seat);
return 0; return 0;
} }
static void start_long_press(Manager *m, sd_event_source **e, sd_event_time_handler_t callback) { static void start_long_press(Button *b, sd_event_source **e, sd_event_time_handler_t callback) {
Manager *m;
int r; int r;
assert(m); assert(b);
assert(e); assert(e);
m = ASSERT_PTR(b->manager);
if (*e) if (*e)
return; return;
@ -193,7 +241,7 @@ static void start_long_press(Manager *m, sd_event_source **e, sd_event_time_hand
e, e,
CLOCK_MONOTONIC, CLOCK_MONOTONIC,
LONG_PRESS_DURATION, 0, LONG_PRESS_DURATION, 0,
callback, m); callback, b);
if (r < 0) if (r < 0)
log_warning_errno(r, "Failed to add long press timer event, ignoring: %m"); log_warning_errno(r, "Failed to add long press timer event, ignoring: %m");
} }
@ -220,12 +268,12 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
case KEY_POWER2: case KEY_POWER2:
if (b->manager->handle_power_key_long_press != HANDLE_IGNORE && b->manager->handle_power_key_long_press != b->manager->handle_power_key) { if (b->manager->handle_power_key_long_press != HANDLE_IGNORE && b->manager->handle_power_key_long_press != b->manager->handle_power_key) {
log_debug("Power key pressed. Further action depends on the key press duration."); log_debug("Power key pressed. Further action depends on the key press duration.");
start_long_press(b->manager, &b->manager->power_key_long_press_event_source, long_press_of_power_key_handler); start_long_press(b, &b->manager->power_key_long_press_event_source, long_press_of_power_key_handler);
} else { } else {
log_struct(LOG_INFO, log_struct(LOG_INFO,
LOG_MESSAGE("Power key pressed short."), LOG_MESSAGE("Power key pressed short."),
"MESSAGE_ID=" SD_MESSAGE_POWER_KEY_STR); "MESSAGE_ID=" SD_MESSAGE_POWER_KEY_STR);
manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true); manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, /* is_edge= */ true, b->seat);
} }
break; break;
@ -237,12 +285,12 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
case KEY_RESTART: case KEY_RESTART:
if (b->manager->handle_reboot_key_long_press != HANDLE_IGNORE && b->manager->handle_reboot_key_long_press != b->manager->handle_reboot_key) { if (b->manager->handle_reboot_key_long_press != HANDLE_IGNORE && b->manager->handle_reboot_key_long_press != b->manager->handle_reboot_key) {
log_debug("Reboot key pressed. Further action depends on the key press duration."); log_debug("Reboot key pressed. Further action depends on the key press duration.");
start_long_press(b->manager, &b->manager->reboot_key_long_press_event_source, long_press_of_reboot_key_handler); start_long_press(b, &b->manager->reboot_key_long_press_event_source, long_press_of_reboot_key_handler);
} else { } else {
log_struct(LOG_INFO, log_struct(LOG_INFO,
LOG_MESSAGE("Reboot key pressed short."), LOG_MESSAGE("Reboot key pressed short."),
"MESSAGE_ID=" SD_MESSAGE_REBOOT_KEY_STR); "MESSAGE_ID=" SD_MESSAGE_REBOOT_KEY_STR);
manager_handle_action(b->manager, INHIBIT_HANDLE_REBOOT_KEY, b->manager->handle_reboot_key, b->manager->reboot_key_ignore_inhibited, true); manager_handle_action(b->manager, INHIBIT_HANDLE_REBOOT_KEY, b->manager->handle_reboot_key, b->manager->reboot_key_ignore_inhibited, /* is_edge= */ true, b->seat);
} }
break; break;
@ -255,26 +303,42 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
case KEY_SLEEP: case KEY_SLEEP:
if (b->manager->handle_suspend_key_long_press != HANDLE_IGNORE && b->manager->handle_suspend_key_long_press != b->manager->handle_suspend_key) { if (b->manager->handle_suspend_key_long_press != HANDLE_IGNORE && b->manager->handle_suspend_key_long_press != b->manager->handle_suspend_key) {
log_debug("Suspend key pressed. Further action depends on the key press duration."); log_debug("Suspend key pressed. Further action depends on the key press duration.");
start_long_press(b->manager, &b->manager->suspend_key_long_press_event_source, long_press_of_suspend_key_handler); start_long_press(b, &b->manager->suspend_key_long_press_event_source, long_press_of_suspend_key_handler);
} else { } else {
log_struct(LOG_INFO, log_struct(LOG_INFO,
LOG_MESSAGE("Suspend key pressed short."), LOG_MESSAGE("Suspend key pressed short."),
"MESSAGE_ID=" SD_MESSAGE_SUSPEND_KEY_STR); "MESSAGE_ID=" SD_MESSAGE_SUSPEND_KEY_STR);
manager_handle_action(b->manager, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, true); manager_handle_action(b->manager, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, /* is_edge= */ true, b->seat);
} }
break; break;
case KEY_SUSPEND: case KEY_SUSPEND:
if (b->manager->handle_hibernate_key_long_press != HANDLE_IGNORE && b->manager->handle_hibernate_key_long_press != b->manager->handle_hibernate_key) { if (b->manager->handle_hibernate_key_long_press != HANDLE_IGNORE && b->manager->handle_hibernate_key_long_press != b->manager->handle_hibernate_key) {
log_debug("Hibernate key pressed. Further action depends on the key press duration."); log_debug("Hibernate key pressed. Further action depends on the key press duration.");
start_long_press(b->manager, &b->manager->hibernate_key_long_press_event_source, long_press_of_hibernate_key_handler); start_long_press(b, &b->manager->hibernate_key_long_press_event_source, long_press_of_hibernate_key_handler);
} else { } else {
log_struct(LOG_INFO, log_struct(LOG_INFO,
LOG_MESSAGE("Hibernate key pressed short."), LOG_MESSAGE("Hibernate key pressed short."),
"MESSAGE_ID=" SD_MESSAGE_HIBERNATE_KEY_STR); "MESSAGE_ID=" SD_MESSAGE_HIBERNATE_KEY_STR);
manager_handle_action(b->manager, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, true); manager_handle_action(b->manager, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, /* is_edge= */ true, b->seat);
} }
break; break;
case KEY_ESC:
if (b->manager->handle_secure_attention_key == HANDLE_IGNORE)
break;
if (!BUTTON_MODIFIER_HAS_SHIFT(b->button_modifier_mask) ||
!BUTTON_MODIFIER_HAS_CTRL(b->button_modifier_mask) ||
!BUTTON_MODIFIER_HAS_ALT(b->button_modifier_mask))
break;
log_debug("Secure Attention Key sequence pressed.");
manager_handle_action(b->manager, /* inhibit_key= */ 0, b->manager->handle_secure_attention_key, /* ignore_inhibited= */ true, /* is_edge= */ true, b->seat);
break;
default:
b->button_modifier_mask |= button_get_keycode_modifier_mask(ev.code);
break;
} }
} else if (ev.type == EV_KEY && ev.value == 0) { } else if (ev.type == EV_KEY && ev.value == 0) {
@ -294,7 +358,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
b->manager->power_key_long_press_event_source = sd_event_source_unref(b->manager->power_key_long_press_event_source); b->manager->power_key_long_press_event_source = sd_event_source_unref(b->manager->power_key_long_press_event_source);
manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true); manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, /* is_edge= */ true, b->seat);
} }
break; break;
@ -306,7 +370,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
b->manager->reboot_key_long_press_event_source = sd_event_source_unref(b->manager->reboot_key_long_press_event_source); b->manager->reboot_key_long_press_event_source = sd_event_source_unref(b->manager->reboot_key_long_press_event_source);
manager_handle_action(b->manager, INHIBIT_HANDLE_REBOOT_KEY, b->manager->handle_reboot_key, b->manager->reboot_key_ignore_inhibited, true); manager_handle_action(b->manager, INHIBIT_HANDLE_REBOOT_KEY, b->manager->handle_reboot_key, b->manager->reboot_key_ignore_inhibited, /* is_edge= */ true, b->seat);
} }
break; break;
@ -318,7 +382,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
b->manager->suspend_key_long_press_event_source = sd_event_source_unref(b->manager->suspend_key_long_press_event_source); b->manager->suspend_key_long_press_event_source = sd_event_source_unref(b->manager->suspend_key_long_press_event_source);
manager_handle_action(b->manager, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, true); manager_handle_action(b->manager, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, /* is_edge= */ true, b->seat);
} }
break; break;
case KEY_SUSPEND: case KEY_SUSPEND:
@ -329,9 +393,16 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
b->manager->hibernate_key_long_press_event_source = sd_event_source_unref(b->manager->hibernate_key_long_press_event_source); b->manager->hibernate_key_long_press_event_source = sd_event_source_unref(b->manager->hibernate_key_long_press_event_source);
manager_handle_action(b->manager, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, true); manager_handle_action(b->manager, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, /* is_edge= */ true, b->seat);
} }
break; break;
case KEY_ESC:
break;
default:
b->button_modifier_mask &= ~button_get_keycode_modifier_mask(ev.code);
break;
} }
} else if (ev.type == EV_SW && ev.value > 0) { } else if (ev.type == EV_SW && ev.value > 0) {
@ -342,7 +413,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
"MESSAGE_ID=" SD_MESSAGE_LID_CLOSED_STR); "MESSAGE_ID=" SD_MESSAGE_LID_CLOSED_STR);
b->lid_closed = true; b->lid_closed = true;
button_lid_switch_handle_action(b->manager, true); button_lid_switch_handle_action(b->manager, /* is_edge= */ true, b->seat);
button_install_check_event_source(b); button_install_check_event_source(b);
manager_send_changed(b->manager, "LidClosed", NULL); manager_send_changed(b->manager, "LidClosed", NULL);
@ -386,17 +457,25 @@ static int button_suitable(int fd) {
return -errno; return -errno;
if (bitset_get(types, EV_KEY)) { if (bitset_get(types, EV_KEY)) {
unsigned long keys[CONST_MAX5(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND, KEY_RESTART)/ULONG_BITS+1]; unsigned long keys[_KEY_MAX_INTERESTED/ULONG_BITS+1];
if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof keys), keys) < 0) if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof keys), keys) < 0)
return -errno; return -errno;
/* If the device has power related keys, then accept the device. */
if (bitset_get(keys, KEY_POWER) || if (bitset_get(keys, KEY_POWER) ||
bitset_get(keys, KEY_POWER2) || bitset_get(keys, KEY_POWER2) ||
bitset_get(keys, KEY_SLEEP) || bitset_get(keys, KEY_SLEEP) ||
bitset_get(keys, KEY_SUSPEND) || bitset_get(keys, KEY_SUSPEND) ||
bitset_get(keys, KEY_RESTART)) bitset_get(keys, KEY_RESTART))
return true; return true;
/* If the device has keys for the Secure Attention Key sequence, then accept the device. */
if ((bitset_get(keys, KEY_LEFTSHIFT) || bitset_get(keys, KEY_RIGHTSHIFT)) &&
(bitset_get(keys, KEY_LEFTCTRL) || bitset_get(keys, KEY_RIGHTCTRL)) &&
(bitset_get(keys, KEY_LEFTALT) || bitset_get(keys, KEY_RIGHTALT)) &&
bitset_get(keys, KEY_ESC))
return true;
} }
if (bitset_get(types, EV_SW)) { if (bitset_get(types, EV_SW)) {
@ -413,10 +492,27 @@ static int button_suitable(int fd) {
return false; return false;
} }
static int button_initialize_modifier_mask(Button *b) {
unsigned long keys[KEY_MAX/ULONG_BITS+1];
assert(b);
if (ioctl(b->fd, EVIOCGKEY(sizeof(keys)), keys) < 0)
return log_error_errno(errno, "Failed to initialize modifier mask on /dev/input/%s: %m", b->name);
b->button_modifier_mask = BUTTON_MODIFIER_NONE;
FOREACH_ELEMENT(i, keycode_modifier_table)
if (bitset_get(keys, i->keycode))
b->button_modifier_mask |= i->modifier_mask;
return 0;
}
static int button_set_mask(const char *name, int fd) { static int button_set_mask(const char *name, int fd) {
unsigned long unsigned long
types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1] = {}, types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1] = {},
keys[CONST_MAX5(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND, KEY_RESTART)/ULONG_BITS+1] = {}, keys[_KEY_MAX_INTERESTED/ULONG_BITS+1] = {},
switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1] = {}; switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1] = {};
struct input_mask mask; struct input_mask mask;
@ -437,11 +533,11 @@ static int button_set_mask(const char *name, int fd) {
return log_full_errno(IN_SET(errno, ENOTTY, EOPNOTSUPP, EINVAL) ? LOG_DEBUG : LOG_WARNING, return log_full_errno(IN_SET(errno, ENOTTY, EOPNOTSUPP, EINVAL) ? LOG_DEBUG : LOG_WARNING,
errno, "Failed to set EV_SYN event mask on /dev/input/%s: %m", name); errno, "Failed to set EV_SYN event mask on /dev/input/%s: %m", name);
bitset_put(keys, KEY_POWER); FOREACH_ELEMENT(key, keys_interested) {
bitset_put(keys, KEY_POWER2); assert(*key <= _KEY_MAX_INTERESTED);
bitset_put(keys, KEY_SLEEP);
bitset_put(keys, KEY_SUSPEND); bitset_put(keys, *key);
bitset_put(keys, KEY_RESTART); }
mask = (struct input_mask) { mask = (struct input_mask) {
.type = EV_KEY, .type = EV_KEY,
@ -502,6 +598,11 @@ int button_open(Button *b) {
b->fd = TAKE_FD(fd); b->fd = TAKE_FD(fd);
log_info("Watching system buttons on %s (%s)", p, name); log_info("Watching system buttons on %s (%s)", p, name);
r = button_initialize_modifier_mask(b);
if (r < 0)
return r;
return 0; return 0;
} }

View file

@ -5,6 +5,20 @@ typedef struct Button Button;
#include "logind.h" #include "logind.h"
typedef enum ButtonModifierMask {
BUTTON_MODIFIER_NONE = 0,
BUTTON_MODIFIER_LEFT_SHIFT = 1 << 0,
BUTTON_MODIFIER_RIGHT_SHIFT = 1 << 1,
BUTTON_MODIFIER_LEFT_CTRL = 1 << 2,
BUTTON_MODIFIER_RIGHT_CTRL = 1 << 3,
BUTTON_MODIFIER_LEFT_ALT = 1 << 4,
BUTTON_MODIFIER_RIGHT_ALT = 1 << 5,
} ButtonModifierMask;
#define BUTTON_MODIFIER_HAS_SHIFT(modifier) (((modifier) & (BUTTON_MODIFIER_LEFT_SHIFT|BUTTON_MODIFIER_RIGHT_SHIFT)) != 0)
#define BUTTON_MODIFIER_HAS_CTRL(modifier) (((modifier) & (BUTTON_MODIFIER_LEFT_CTRL|BUTTON_MODIFIER_RIGHT_CTRL)) != 0)
#define BUTTON_MODIFIER_HAS_ALT(modifier) (((modifier) & (BUTTON_MODIFIER_LEFT_ALT|BUTTON_MODIFIER_RIGHT_ALT)) != 0)
struct Button { struct Button {
Manager *manager; Manager *manager;
@ -15,6 +29,8 @@ struct Button {
char *seat; char *seat;
int fd; int fd;
ButtonModifierMask button_modifier_mask;
bool lid_closed; bool lid_closed;
bool docked; bool docked;
}; };

View file

@ -50,6 +50,7 @@ void manager_reset_config(Manager *m) {
m->handle_suspend_key_long_press = HANDLE_HIBERNATE; m->handle_suspend_key_long_press = HANDLE_HIBERNATE;
m->handle_hibernate_key = HANDLE_HIBERNATE; m->handle_hibernate_key = HANDLE_HIBERNATE;
m->handle_hibernate_key_long_press = HANDLE_IGNORE; m->handle_hibernate_key_long_press = HANDLE_IGNORE;
m->handle_secure_attention_key = HANDLE_SECURE_ATTENTION_KEY;
m->handle_lid_switch = HANDLE_SUSPEND; m->handle_lid_switch = HANDLE_SUSPEND;
m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID; m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID;
@ -696,6 +697,8 @@ bool manager_all_buttons_ignored(Manager *m) {
return false; return false;
if (m->handle_lid_switch_docked != HANDLE_IGNORE) if (m->handle_lid_switch_docked != HANDLE_IGNORE)
return false; return false;
if (m->handle_secure_attention_key != HANDLE_IGNORE)
return false;
return true; return true;
} }

View file

@ -3699,6 +3699,7 @@ static const sd_bus_vtable manager_vtable[] = {
SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_ep), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_ep), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleSecureAttentionKey", "s", property_get_handle_action, offsetof(Manager, handle_secure_attention_key), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
@ -4071,6 +4072,9 @@ static const sd_bus_vtable manager_vtable[] = {
method_set_wall_message, method_set_wall_message,
SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_SIGNAL_WITH_ARGS("SecureAttentionKey",
SD_BUS_ARGS("s", seat_id, "o", object_path),
0),
SD_BUS_SIGNAL_WITH_ARGS("SessionNew", SD_BUS_SIGNAL_WITH_ARGS("SessionNew",
SD_BUS_ARGS("s", session_id, "o", object_path), SD_BUS_ARGS("s", session_id, "o", object_path),
0), 0),

View file

@ -37,6 +37,7 @@ Login.HandleHibernateKeyLongPress, config_parse_handle_action, 0, offse
Login.HandleLidSwitch, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch) Login.HandleLidSwitch, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch)
Login.HandleLidSwitchExternalPower, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_ep) Login.HandleLidSwitchExternalPower, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_ep)
Login.HandleLidSwitchDocked, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_docked) Login.HandleLidSwitchDocked, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_docked)
Login.HandleSecureAttentionKey, config_parse_handle_action, 0, offsetof(Manager, handle_secure_attention_key)
Login.PowerKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, power_key_ignore_inhibited) Login.PowerKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, power_key_ignore_inhibited)
Login.SuspendKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, suspend_key_ignore_inhibited) Login.SuspendKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, suspend_key_ignore_inhibited)
Login.HibernateKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, hibernate_key_ignore_inhibited) Login.HibernateKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, hibernate_key_ignore_inhibited)

View file

@ -1036,7 +1036,7 @@ static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *us
else else
log_info("System idle. Will %s now.", handle_action_verb_to_string(m->idle_action)); log_info("System idle. Will %s now.", handle_action_verb_to_string(m->idle_action));
manager_handle_action(m, 0, m->idle_action, false, is_edge); manager_handle_action(m, /* inhibit_key= */ 0, m->idle_action, /* ignore_inhibited= */ false, is_edge, /* action_seat= */ NULL);
m->idle_action_not_before_usec = n; m->idle_action_not_before_usec = n;
} }

View file

@ -36,6 +36,7 @@
#HandleLidSwitch=suspend #HandleLidSwitch=suspend
#HandleLidSwitchExternalPower=suspend #HandleLidSwitchExternalPower=suspend
#HandleLidSwitchDocked=ignore #HandleLidSwitchDocked=ignore
#HandleSecureAttentionKey=secure-attention-key
#PowerKeyIgnoreInhibited=no #PowerKeyIgnoreInhibited=no
#SuspendKeyIgnoreInhibited=no #SuspendKeyIgnoreInhibited=no
#HibernateKeyIgnoreInhibited=no #HibernateKeyIgnoreInhibited=no

View file

@ -109,6 +109,7 @@ struct Manager {
HandleAction handle_suspend_key_long_press; HandleAction handle_suspend_key_long_press;
HandleAction handle_hibernate_key; HandleAction handle_hibernate_key;
HandleAction handle_hibernate_key_long_press; HandleAction handle_hibernate_key_long_press;
HandleAction handle_secure_attention_key;
HandleAction handle_lid_switch; HandleAction handle_lid_switch;
HandleAction handle_lid_switch_ep; HandleAction handle_lid_switch_ep;

View file

@ -209,6 +209,8 @@ _SD_BEGIN_DECLARATIONS;
#define SD_MESSAGE_POWER_KEY_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,71) #define SD_MESSAGE_POWER_KEY_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,71)
#define SD_MESSAGE_POWER_KEY_LONG_PRESS SD_ID128_MAKE(3e,01,17,10,1e,b2,43,c1,b9,a5,0d,b3,49,4a,b1,0b) #define SD_MESSAGE_POWER_KEY_LONG_PRESS SD_ID128_MAKE(3e,01,17,10,1e,b2,43,c1,b9,a5,0d,b3,49,4a,b1,0b)
#define SD_MESSAGE_POWER_KEY_LONG_PRESS_STR SD_ID128_MAKE_STR(3e,01,17,10,1e,b2,43,c1,b9,a5,0d,b3,49,4a,b1,0b) #define SD_MESSAGE_POWER_KEY_LONG_PRESS_STR SD_ID128_MAKE_STR(3e,01,17,10,1e,b2,43,c1,b9,a5,0d,b3,49,4a,b1,0b)
#define SD_MESSAGE_SECURE_ATTENTION_KEY_PRESS SD_ID128_MAKE(b2,bc,ba,f5,ed,f9,48,e0,93,ce,50,bb,ea,0e,81,ec)
#define SD_MESSAGE_SECURE_ATTENTION_KEY_PRESS_STR SD_ID128_MAKE_STR(b2,bc,ba,f5,ed,f9,48,e0,93,ce,50,bb,ea,0e,81,ec)
#define SD_MESSAGE_REBOOT_KEY SD_ID128_MAKE(9f,a9,d2,c0,12,13,4e,c3,85,45,1f,fe,31,6f,97,d0) #define SD_MESSAGE_REBOOT_KEY SD_ID128_MAKE(9f,a9,d2,c0,12,13,4e,c3,85,45,1f,fe,31,6f,97,d0)
#define SD_MESSAGE_REBOOT_KEY_STR SD_ID128_MAKE_STR(9f,a9,d2,c0,12,13,4e,c3,85,45,1f,fe,31,6f,97,d0) #define SD_MESSAGE_REBOOT_KEY_STR SD_ID128_MAKE_STR(9f,a9,d2,c0,12,13,4e,c3,85,45,1f,fe,31,6f,97,d0)
#define SD_MESSAGE_REBOOT_KEY_LONG_PRESS SD_ID128_MAKE(f1,c5,9a,58,c9,d9,43,66,89,65,c3,37,ca,ec,59,75) #define SD_MESSAGE_REBOOT_KEY_LONG_PRESS SD_ID128_MAKE(f1,c5,9a,58,c9,d9,43,66,89,65,c3,37,ca,ec,59,75)