Files
cthulhu/tests/xorg_suspension_probe.c

85 lines
3.6 KiB
C

// Deterministic native queue boundary: a key was captured before suspension,
// but remains in Xlib's queue when the Go owner gives the keyboard back.
#include "commands_native.h"
#include <X11/keysym.h>
#include <X11/XKBlib.h>
#include <X11/extensions/XTest.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
int error = 0, failed = 0;
int capsHandoff = argc == 2 && strcmp(argv[1], "caps-handoff") == 0;
CommandDevice *device = open_commands(1, 0, capsHandoff, &error);
if (!device) { fprintf(stderr, "open: %d\n", error); return 1; }
if (capsHandoff) {
set_command_keys(device, 0);
// A terminal reader changes the real lock while Cthulhu is suspended.
XkbLockModifiers(device->display, XkbUseCoreKbd, LockMask, LockMask);
XSync(device->display, False);
if (!(command_lock_state(device) & 1)) {
fprintf(stderr, "suspended lock read used stale reader state\n");
failed = 1;
}
set_command_keys(device, 1);
if (!device->capsLocked) {
fprintf(stderr, "resumed reader did not adopt external Caps Lock state\n");
failed = 1;
}
XkbLockModifiers(device->display, XkbUseCoreKbd, LockMask, 0);
XSync(device->display, False);
} else if (argc == 2 && strcmp(argv[1], "queued") == 0) {
if (XGrabKeyboard(device->display, device->root, False,
GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) return 1;
device->active = 1;
XEvent event = {0};
event.xkey.type = KeyPress;
event.xkey.display = device->display;
event.xkey.window = device->root;
event.xkey.keycode = XKeysymToKeycode(device->display, XK_q);
XPutBackEvent(device->display, &event);
release_command_keyboard(device);
set_command_keys(device, 0);
CommandKey key = {0};
int result = next_command_key(device, &key);
if (result != 0 || device->active) {
fprintf(stderr, "suspended queued key: result=%d active=%d\n", result, device->active);
failed = 1;
}
} else if (argc == 2 && strcmp(argv[1], "passive") == 0) {
Display *sender = XOpenDisplay(NULL);
int code = XKeysymToKeycode(sender, XK_Insert);
XTestFakeKeyEvent(sender, code, True, CurrentTime);
XSync(sender, False); // The synchronous passive grab is now active.
set_command_keys(device, 0);
CommandKey key = {0};
next_command_key(device, &key);
int status = XGrabKeyboard(sender, DefaultRootWindow(sender), False,
GrabModeAsync, GrabModeAsync, CurrentTime);
if (status != GrabSuccess) {
fprintf(stderr, "suspension left activated passive grab: %d\n", status);
failed = 1;
}
XUngrabKeyboard(sender, CurrentTime);
close_commands(device);
device = NULL;
XTestFakeKeyEvent(sender, code, False, CurrentTime);
XSync(sender, False);
XCloseDisplay(sender);
} else {
set_command_keys(device, 0);
CommandKey keys[2] = {{.pressed = 1}, {.pressed = 0}};
keys[0].code = keys[1].code = XKeysymToKeycode(device->display, XK_q);
if (replay_command_keys(device, keys, 2) != 0) return 1;
CommandDevice *competitor = open_commands(1, 0, 0, &error);
if (!competitor) {
fprintf(stderr, "replay restored disabled passive grabs: %d\n", error);
failed = 1;
} else {
close_commands(competitor);
}
}
if (device) close_commands(device);
return failed;
}