Merged changes from hunter. Attempt to fix cthulhu announcing modifiers when suspended for xterm.
This commit is contained in:
1 parent
27867a48cb
commit
f2cc47c8a0
24 files changed
+679
-67
No files matched your search
@@ -381,6 +381,13 @@ static void grab_command_keys(CommandDevice *device) {
|
||||
}
|
||||
}
|
||||
int set_command_keys(CommandDevice *device, int enabled) {
|
||||
// Another reader may have changed Caps Lock while command input was
|
||||
// delegated. Adopt that state before treating Caps as our modifier again.
|
||||
if (enabled && !device->commands && device->capsCode) {
|
||||
XkbStateRec state;
|
||||
if (XkbGetState(device->display, XkbUseCoreKbd, &state) != Success) return -7;
|
||||
device->capsLocked = (state.locked_mods & LockMask) != 0;
|
||||
}
|
||||
pthread_mutex_lock(&error_mutex);
|
||||
XSync(device->display,False);
|
||||
error_display=device->display; grab_error=0;
|
||||
@@ -491,6 +498,7 @@ CommandDevice *open_commands(int useInsert, int useKeypad, int useCaps, int *err
|
||||
*error=set_command_keys(device,1);
|
||||
if (*error) { XCloseDisplay(device->display); free(device); return NULL; }
|
||||
if (device->capsCode) {
|
||||
device->capsLocked=0;
|
||||
XkbLockModifiers(device->display,XkbUseCoreKbd,LockMask,0);
|
||||
XSync(device->display,False);
|
||||
}
|
||||
@@ -502,7 +510,7 @@ int command_lock_state(CommandDevice *device) {
|
||||
int locks=0;
|
||||
for (int i=0;i<3;i++) if (indicators & device->lockIndicators[i]) locks |= 1<<i;
|
||||
// Ignore the transient XKB lock action on a grabbed reader modifier.
|
||||
if (device->capsCode) locks=(locks & ~1) | device->capsLocked;
|
||||
if (device->commands && device->capsCode) locks=(locks & ~1) | device->capsLocked;
|
||||
return locks;
|
||||
}
|
||||
void toggle_command_caps_lock(CommandDevice *device) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -23,7 +24,7 @@ func TestNativeSuspendedQueuedKey(t *testing.T) {
|
||||
if out, err := exec.CommandContext(ctx, "cc", "-I.", "../../../tests/xorg_suspension_probe.c", "commands_native.c", "-o", probe, "-lX11", "-lXtst", "-lxkbcommon", "-lpthread").CombinedOutput(); err != nil {
|
||||
t.Fatalf("compile native probe: %v: %s", err, out)
|
||||
}
|
||||
for _, mode := range []string{"queued", "replay", "passive"} {
|
||||
for _, mode := range []string{"queued", "replay", "passive", "caps-handoff"} {
|
||||
t.Run(mode, func(t *testing.T) {
|
||||
if out, err := exec.CommandContext(ctx, probe, mode).CombinedOutput(); err != nil {
|
||||
t.Fatalf("native suspension: %v: %s", err, out)
|
||||
@@ -39,12 +40,13 @@ func TestNativeXTermHandoffKeepsKeypadReleased(t *testing.T) {
|
||||
t.Skip("requires isolated X11 display")
|
||||
}
|
||||
for _, scenario := range []struct {
|
||||
name string
|
||||
learn, held bool
|
||||
name string
|
||||
learn, held, caps bool
|
||||
}{
|
||||
{name: "delayed_focus"},
|
||||
{name: "held_command", held: true},
|
||||
{name: "learn_mode", learn: true},
|
||||
{name: "caps_modifier", caps: true},
|
||||
} {
|
||||
t.Run(scenario.name, func(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 8*time.Second)
|
||||
@@ -86,7 +88,13 @@ func TestNativeXTermHandoffKeepsKeypadReleased(t *testing.T) {
|
||||
}
|
||||
return state.Keys
|
||||
}
|
||||
listener := NewCommands([]string{"Insert", "KP_Insert"}, input.DesktopKeyboardLayout)
|
||||
modifiers, layout := []string{"Insert", "KP_Insert"}, input.DesktopKeyboardLayout
|
||||
reviewChord, reviewCommand := "KP_Begin", input.ReviewCurrentWord
|
||||
if scenario.caps {
|
||||
modifiers, layout = []string{"Caps_Lock"}, input.LaptopKeyboardLayout
|
||||
reviewChord, reviewCommand = "Caps_Lock+i", input.ReviewCurrentLine
|
||||
}
|
||||
listener := NewCommands(modifiers, layout)
|
||||
if err := listener.Start(ctx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -140,9 +148,9 @@ func TestNativeXTermHandoffKeepsKeypadReleased(t *testing.T) {
|
||||
defer exec.Command("xdotool", "keyup", "KP_Begin").Run()
|
||||
key("keydown", "KP_Begin")
|
||||
} else {
|
||||
key("key", "KP_Begin")
|
||||
key("key", reviewChord)
|
||||
}
|
||||
command(input.ReviewCurrentWord)
|
||||
command(reviewCommand)
|
||||
if !scenario.held {
|
||||
wait(func() bool { return !listener.CommandGrabActive() })
|
||||
}
|
||||
@@ -168,10 +176,14 @@ func TestNativeXTermHandoffKeepsKeypadReleased(t *testing.T) {
|
||||
time.Sleep(2 * xtermFocusCheckInterval)
|
||||
}
|
||||
action(map[string]string{"action": "clear"})
|
||||
key("key", "KP_Begin")
|
||||
key("key", reviewChord)
|
||||
keys := action(map[string]string{"action": "state"})
|
||||
if len(keys) != 2 || keys[0].Symbol != 0xff9d || !keys[0].Pressed || keys[1].Symbol != 0xff9d || keys[1].Pressed {
|
||||
t.Fatalf("xterm keypad press/release = %+v; unknown=%t, grabs=%t, active=%t", keys, unknown, listener.CommandGrabsEnabled(), listener.CommandGrabActive())
|
||||
expected := []deliveredKey{{Pressed: true, Symbol: 0xff9d}, {Pressed: false, Symbol: 0xff9d}}
|
||||
if scenario.caps {
|
||||
expected = []deliveredKey{{Pressed: true, Symbol: 0xffe5}, {Pressed: true, Symbol: 0x69}, {Pressed: false, Symbol: 0xffe5}, {Pressed: false, Symbol: 0x69}}
|
||||
}
|
||||
if !slices.Equal(keys, expected) {
|
||||
t.Fatalf("xterm key press/release = %+v, want %+v; unknown=%t, grabs=%t, active=%t", keys, expected, unknown, listener.CommandGrabsEnabled(), listener.CommandGrabActive())
|
||||
}
|
||||
select {
|
||||
case got := <-listener.Commands():
|
||||
@@ -183,8 +195,8 @@ func TestNativeXTermHandoffKeepsKeypadReleased(t *testing.T) {
|
||||
action(map[string]string{"action": "activate"})
|
||||
focus(false)
|
||||
wait(listener.CommandGrabsEnabled)
|
||||
key("key", "KP_Begin")
|
||||
command(input.ReviewCurrentWord)
|
||||
key("key", reviewChord)
|
||||
command(reviewCommand)
|
||||
wait(func() bool { return !listener.CommandGrabActive() })
|
||||
})
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user