From 3ca166e5a18ba6502b0f331140ab2a0b9287ae5f Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Fri, 17 Jul 2026 13:26:21 -0400 Subject: [PATCH] Report locked status to cthulhu. Should prevent some of the weirdness with the screen reader thinking it's in a different window. --- accessibility_feedback.c | 118 +++++++++++++++++++++++++++++-- i3lock.c | 4 +- include/accessibility_feedback.h | 4 +- 3 files changed, 118 insertions(+), 8 deletions(-) diff --git a/accessibility_feedback.c b/accessibility_feedback.c index 748758c..d99279f 100644 --- a/accessibility_feedback.c +++ b/accessibility_feedback.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,14 @@ static int feedback_fd = -1; +#define I38LOCK_SECURE_INPUT_BUS_NAME "org.stormux.I38Lock1" +#define DBUS_REQUEST_NAME_FLAG_DO_NOT_QUEUE 4 +#define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1 +#define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4 +#define ACCESSIBILITY_READY_OK '1' +#define ACCESSIBILITY_READY_FAILED '0' +#define ACCESSIBILITY_READY_TIMEOUT_MS 2000 + struct screen_reader { const char *service; const char *path; @@ -96,6 +105,72 @@ static bool service_has_owner(GDBusConnection *connection, const char *service) return has_owner; } +static bool own_secure_input_name(GDBusConnection *connection) { + GError *error = NULL; + GVariant *result = g_dbus_connection_call_sync( + connection, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "RequestName", + g_variant_new( + "(su)", + I38LOCK_SECURE_INPUT_BUS_NAME, + (guint32)DBUS_REQUEST_NAME_FLAG_DO_NOT_QUEUE), + G_VARIANT_TYPE("(u)"), + G_DBUS_CALL_FLAGS_NONE, + 500, + NULL, + &error); + + if (result == NULL) { + g_clear_error(&error); + return false; + } + + guint32 reply = 0; + g_variant_get(result, "(u)", &reply); + g_variant_unref(result); + return reply == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER || + reply == DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER; +} + +static void report_worker_ready(int ready_fd, bool is_ready) { + char status = is_ready ? ACCESSIBILITY_READY_OK : ACCESSIBILITY_READY_FAILED; + ssize_t result; + do { + result = write(ready_fd, &status, sizeof(status)); + } while (result == -1 && errno == EINTR); + + close(ready_fd); +} + +static bool wait_for_worker_ready(int ready_fd) { + struct pollfd poll_fd = { + .fd = ready_fd, + .events = POLLIN, + }; + + int poll_result; + do { + poll_result = poll(&poll_fd, 1, ACCESSIBILITY_READY_TIMEOUT_MS); + } while (poll_result == -1 && errno == EINTR); + + if (poll_result <= 0) { + close(ready_fd); + return false; + } + + char status = ACCESSIBILITY_READY_FAILED; + ssize_t read_result; + do { + read_result = read(ready_fd, &status, sizeof(status)); + } while (read_result == -1 && errno == EINTR); + + close(ready_fd); + return read_result == sizeof(status) && status == ACCESSIBILITY_READY_OK; +} + static void present_message(GDBusConnection *connection, const char *message) { for (size_t i = 0; i < sizeof(screen_readers) / sizeof(screen_readers[0]); i++) { const struct screen_reader *reader = &screen_readers[i]; @@ -150,7 +225,7 @@ static void close_sleep_lock_fd(void) { } } -static void feedback_worker(int read_fd, int inherited_xcb_fd) { +static void feedback_worker(int read_fd, int inherited_xcb_fd, int ready_fd) { if (inherited_xcb_fd >= 0) { close(inherited_xcb_fd); } @@ -158,8 +233,20 @@ static void feedback_worker(int read_fd, int inherited_xcb_fd) { GError *error = NULL; GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error); + bool secure_input_ready = false; if (connection == NULL) { g_clear_error(&error); + } else { + secure_input_ready = own_secure_input_name(connection); + } + + report_worker_ready(ready_fd, secure_input_ready); + if (!secure_input_ready) { + if (connection != NULL) { + g_object_unref(connection); + } + close(read_fd); + return; } accessibility_feedback_t feedback[128]; @@ -202,17 +289,26 @@ static void feedback_worker(int read_fd, int inherited_xcb_fd) { close(read_fd); } -void accessibility_feedback_start(int inherited_xcb_fd) { +bool accessibility_feedback_start(int inherited_xcb_fd) { int pipe_fds[2]; if (pipe(pipe_fds) != 0) { - return; + return false; + } + + int ready_fds[2]; + if (pipe(ready_fds) != 0) { + close(pipe_fds[0]); + close(pipe_fds[1]); + return false; } int flags = fcntl(pipe_fds[1], F_GETFL); if (flags == -1 || fcntl(pipe_fds[1], F_SETFL, flags | O_NONBLOCK) == -1) { close(pipe_fds[0]); close(pipe_fds[1]); - return; + close(ready_fds[0]); + close(ready_fds[1]); + return false; } signal(SIGPIPE, SIG_IGN); @@ -221,17 +317,27 @@ void accessibility_feedback_start(int inherited_xcb_fd) { if (pid == -1) { close(pipe_fds[0]); close(pipe_fds[1]); - return; + close(ready_fds[0]); + close(ready_fds[1]); + return false; } if (pid == 0) { close(pipe_fds[1]); - feedback_worker(pipe_fds[0], inherited_xcb_fd); + close(ready_fds[0]); + feedback_worker(pipe_fds[0], inherited_xcb_fd, ready_fds[1]); _exit(EXIT_SUCCESS); } close(pipe_fds[0]); + close(ready_fds[1]); + if (!wait_for_worker_ready(ready_fds[0])) { + close(pipe_fds[1]); + return false; + } + feedback_fd = pipe_fds[1]; + return true; } void accessibility_feedback_notify(accessibility_feedback_t feedback) { diff --git a/i3lock.c b/i3lock.c index 1415674..f0bfe7d 100644 --- a/i3lock.c +++ b/i3lock.c @@ -1335,7 +1335,9 @@ int main(int argc, char *argv[]) { * keyboard. */ (void)load_keymap(); - accessibility_feedback_start(xcb_get_file_descriptor(conn)); + if (!accessibility_feedback_start(xcb_get_file_descriptor(conn))) { + errx(EXIT_FAILURE, "Could not initialize secure accessibility feedback"); + } accessibility_feedback_notify(ACCESSIBILITY_SCREEN_LOCKED); update_modifier_feedback(true); diff --git a/include/accessibility_feedback.h b/include/accessibility_feedback.h index 268206e..0dadffd 100644 --- a/include/accessibility_feedback.h +++ b/include/accessibility_feedback.h @@ -1,6 +1,8 @@ #ifndef _ACCESSIBILITY_FEEDBACK_H #define _ACCESSIBILITY_FEEDBACK_H +#include + typedef enum { ACCESSIBILITY_SCREEN_LOCKED = 0, ACCESSIBILITY_ENTER_PASSWORD, @@ -17,7 +19,7 @@ typedef enum { ACCESSIBILITY_NUM_LOCK_OFF, } accessibility_feedback_t; -void accessibility_feedback_start(int inherited_xcb_fd); +bool accessibility_feedback_start(int inherited_xcb_fd); void accessibility_feedback_notify(accessibility_feedback_t feedback); #endif