Report locked status to cthulhu. Should prevent some of the weirdness with the screen reader thinking it's in a different window.

This commit is contained in:
Storm Dragon
2026-07-17 13:26:21 -04:00
parent db522d7d66
commit 3ca166e5a1
3 changed files with 118 additions and 8 deletions
+112 -6
View File
@@ -7,6 +7,7 @@
#include <errno.h>
#include <fcntl.h>
#include <gio/gio.h>
#include <poll.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
@@ -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) {
+3 -1
View File
@@ -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);
+3 -1
View File
@@ -1,6 +1,8 @@
#ifndef _ACCESSIBILITY_FEEDBACK_H
#define _ACCESSIBILITY_FEEDBACK_H
#include <stdbool.h>
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