Add X11 terminal input mode
This commit is contained in:
@@ -137,6 +137,7 @@ class TestDriverValidation:
|
||||
# Valid drivers
|
||||
self.manager._validate_setting_value("keyboard", "driver", "evdevDriver")
|
||||
self.manager._validate_setting_value("keyboard", "driver", "ptyDriver")
|
||||
self.manager._validate_setting_value("keyboard", "driver", "x11Driver")
|
||||
self.manager._validate_setting_value("keyboard", "driver", "atspiDriver")
|
||||
self.manager._validate_setting_value("keyboard", "driver", "dummyDriver")
|
||||
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
import importlib.machinery
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from fenrirscreenreader.inputDriver.x11Driver import X
|
||||
from fenrirscreenreader.inputDriver.x11Driver import XK
|
||||
from fenrirscreenreader.inputDriver.x11Driver import driver as X11Driver
|
||||
|
||||
|
||||
def load_fenrir_entrypoint():
|
||||
fenrir_path = Path(__file__).parents[2] / "src" / "fenrir"
|
||||
loader = importlib.machinery.SourceFileLoader(
|
||||
"fenrir_entrypoint_x11", str(fenrir_path)
|
||||
)
|
||||
spec = importlib.util.spec_from_loader(loader.name, loader)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_x11_mode_runs_in_foreground():
|
||||
fenrir = load_fenrir_entrypoint()
|
||||
args = fenrir.create_argument_parser().parse_args(["-x"])
|
||||
|
||||
assert fenrir.should_run_foreground(args) is True
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_x11_mode_rejects_other_emulated_modes():
|
||||
fenrir = load_fenrir_entrypoint()
|
||||
args = fenrir.create_argument_parser().parse_args(["-x", "-e"])
|
||||
|
||||
is_valid, error = fenrir.validate_arguments(args)
|
||||
|
||||
assert is_valid is False
|
||||
assert "--x11" in error
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_x11_cli_accepts_window_id():
|
||||
fenrir = load_fenrir_entrypoint()
|
||||
args = fenrir.create_argument_parser().parse_args(
|
||||
["-x", "--x11-window-id", "0x123"]
|
||||
)
|
||||
|
||||
assert args.x11_window_id == "0x123"
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_x11_key_name_mapping_for_keypad_and_capslock():
|
||||
x11 = X11Driver()
|
||||
|
||||
assert x11.keysym_name_to_key_name("KP_0") == "KEY_KP0"
|
||||
assert x11.keysym_name_to_key_name("KP_Insert") == "KEY_KP0"
|
||||
assert x11.keysym_name_to_key_name("Caps_Lock") == "KEY_CAPSLOCK"
|
||||
assert x11.keysym_name_to_key_name("Super_L") == "KEY_LEFTMETA"
|
||||
assert x11.keysym_name_to_key_name("Multi_key") == "KEY_COMPOSE"
|
||||
assert x11.keysym_name_to_key_name("a") == "KEY_A"
|
||||
assert x11.keysym_name_to_key_name("F10") == "KEY_F10"
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_x11_keycode_mapping_prefers_keypad_aliases():
|
||||
x11 = X11Driver()
|
||||
x11.display = Mock()
|
||||
keysyms = {
|
||||
0: XK.string_to_keysym("Up"),
|
||||
1: XK.string_to_keysym("KP_8"),
|
||||
2: 0,
|
||||
3: 0,
|
||||
4: 0,
|
||||
5: 0,
|
||||
6: 0,
|
||||
7: 0,
|
||||
}
|
||||
x11.display.keycode_to_keysym.side_effect = lambda keycode, column: keysyms[column]
|
||||
|
||||
assert x11.keycode_to_key_name(80) == "KEY_KP8"
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_x11_keycode_mapping_preserves_plain_insert():
|
||||
x11 = X11Driver()
|
||||
x11.display = Mock()
|
||||
keysyms = {
|
||||
0: XK.string_to_keysym("Insert"),
|
||||
1: 0,
|
||||
2: 0,
|
||||
3: 0,
|
||||
4: 0,
|
||||
5: 0,
|
||||
6: 0,
|
||||
7: 0,
|
||||
}
|
||||
x11.display.keycode_to_keysym.side_effect = lambda keycode, column: keysyms[column]
|
||||
|
||||
assert x11.keycode_to_key_name(118) == "KEY_INSERT"
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_x11_keycode_mapping_detects_keypad_insert():
|
||||
x11 = X11Driver()
|
||||
x11.display = Mock()
|
||||
keysyms = {
|
||||
0: XK.string_to_keysym("Insert"),
|
||||
1: XK.string_to_keysym("KP_Insert"),
|
||||
2: 0,
|
||||
3: 0,
|
||||
4: 0,
|
||||
5: 0,
|
||||
6: 0,
|
||||
7: 0,
|
||||
}
|
||||
x11.display.keycode_to_keysym.side_effect = lambda keycode, column: keysyms[column]
|
||||
|
||||
assert x11.keycode_to_key_name(90) == "KEY_KP0"
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_x11_key_name_to_keysym_names_includes_numlock_aliases():
|
||||
x11 = X11Driver()
|
||||
|
||||
assert x11.key_name_to_keysym_names("KEY_KP0") == ["KP_0", "KP_Insert"]
|
||||
assert "KP_Delete" in x11.key_name_to_keysym_names("KEY_KPDOT")
|
||||
assert "Caps_Lock" in x11.key_name_to_keysym_names("KEY_CAPSLOCK")
|
||||
assert "Super_L" in x11.key_name_to_keysym_names("KEY_META")
|
||||
assert "Meta_R" in x11.key_name_to_keysym_names("KEY_META")
|
||||
assert x11.key_name_to_keysym_names("KEY_COMPOSE") == ["Multi_key"]
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_x11_build_passive_grabs_for_fenrir_keys_and_shortcuts():
|
||||
x11 = X11Driver()
|
||||
input_manager = Mock(convert_event_name=lambda key: key)
|
||||
x11.env = {
|
||||
"input": {
|
||||
"fenrir_key": ["KEY_KP0", "KEY_CAPSLOCK"],
|
||||
"script_key": [],
|
||||
},
|
||||
"rawBindings": {
|
||||
"fenrir_combo": [1, ["KEY_FENRIR", "KEY_KP8"]],
|
||||
"bare_keypad": [1, ["KEY_KP5"]],
|
||||
"ctrl_keypad": [1, ["KEY_CTRL", "KEY_KP2"]],
|
||||
},
|
||||
"runtime": {"InputManager": input_manager},
|
||||
}
|
||||
|
||||
grabs = x11.build_passive_grabs()
|
||||
|
||||
assert ("KEY_KP0", 0) in grabs
|
||||
assert ("KEY_CAPSLOCK", 0) in grabs
|
||||
assert ("KEY_KP5", 0) in grabs
|
||||
assert ("KEY_KP2", X.ControlMask) in grabs
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_x11_parse_window_id_accepts_decimal_and_hex():
|
||||
x11 = X11Driver()
|
||||
|
||||
assert x11.parse_window_id("123") == 123
|
||||
assert x11.parse_window_id("0x123") == 0x123
|
||||
assert x11.parse_window_id("") is None
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_x11_write_event_buffer_clears_buffer():
|
||||
x11 = X11Driver()
|
||||
x11._initialized = True
|
||||
x11.env = {"input": {"event_buffer": ["KEY_KP0"]}}
|
||||
|
||||
x11.write_event_buffer()
|
||||
|
||||
assert x11.env["input"]["event_buffer"] == []
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_x11_find_num_lock_mask_uses_modifier_mapping():
|
||||
x11 = X11Driver()
|
||||
x11.display = Mock()
|
||||
x11.display.keysym_to_keycode.return_value = 77
|
||||
x11.display.get_modifier_mapping.return_value = [
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[77],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
]
|
||||
|
||||
assert x11.find_num_lock_mask() == X.Mod2Mask
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_x11_handle_key_event_keeps_event_buffer_for_input_manager():
|
||||
x11 = X11Driver()
|
||||
x11.active = True
|
||||
x11.interesting_keys = {"KEY_KP0"}
|
||||
x11.env = {
|
||||
"input": {
|
||||
"curr_input": [],
|
||||
"event_buffer": [],
|
||||
},
|
||||
"runtime": {
|
||||
"InputManager": Mock(convert_event_name=lambda key: key),
|
||||
"DebugManager": Mock(),
|
||||
},
|
||||
}
|
||||
event_queue = Mock()
|
||||
event = Mock(type=X.KeyPress, detail=90, state=0)
|
||||
x11.keycode_to_key_name = Mock(return_value="KEY_KP0")
|
||||
|
||||
x11.handle_x_event(event, event_queue)
|
||||
|
||||
assert x11.env["input"]["event_buffer"][0]["event_name"] == "KEY_KP0"
|
||||
event_queue.put.assert_called_once()
|
||||
Reference in New Issue
Block a user