fix(xdotool): preserve input focus after injection (#564)

This commit is contained in:
Anay Garodia
2026-07-23 21:44:49 -07:00
committed by GitHub
parent 89f2227478
commit 513e4749e3
2 changed files with 41 additions and 2 deletions
+15 -2
View File
@@ -1004,10 +1004,23 @@ class TextInjector:
logger.error("Text injection timed out on final attempt")
raise
# Try to reset any stuck modifiers
# Release modifiers without sending Escape, which applications may
# interpret as a request to cancel or leave the focused input.
try:
subprocess.run(
["xdotool", "key", "--clearmodifiers", "Escape"],
[
"xdotool",
"keyup",
"--clearmodifiers",
"Control_L",
"Control_R",
"Shift_L",
"Shift_R",
"Alt_L",
"Alt_R",
"Super_L",
"Super_R",
],
env=env,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
+26
View File
@@ -1141,6 +1141,32 @@ class TestTextInjectorEdgeCases(unittest.TestCase):
if env_backup is not None:
os.environ["DISPLAY"] = env_backup
def test_inject_with_xdotool_releases_modifiers_without_escape(self):
"""The xdotool path must keep the target input focused after injection."""
injector = TextInjector.__new__(TextInjector)
injector.environment = DesktopEnvironment.X11
injector._inject_with_xdotool("test")
commands = [call.args[0] for call in self.mock_subprocess.call_args_list]
self.assertIn(
[
"xdotool",
"keyup",
"--clearmodifiers",
"Control_L",
"Control_R",
"Shift_L",
"Shift_R",
"Alt_L",
"Alt_R",
"Super_L",
"Super_R",
],
commands,
)
self.assertFalse(any("Escape" in command for command in commands))
def test_inject_with_wayland_tool_ydotool(self):
"""Test text injection with ydotool."""
with patch.dict("os.environ", {"XDG_SESSION_TYPE": "wayland"}):