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:
+112
-6
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user