Keep input clicks working through controller and compositor failures

This commit is contained in:
David Heinemeier Hansson committed 2026-10-09 17:02:46 +02:00
1 parent f28a652347
commit 4152f0320c
3 files changed
+21 -3

No files matched your search

+3 -2
View File
@@ -114,7 +114,8 @@ class Indicator:
def select_next(self):
state = snapshot(self.bus)
methods = state["methods"]
state["current"] = self.pending or state["current"] or self.last or next(iter(methods), "")
current = self.pending or state["current"] or self.last
state["current"] = current if current in methods else next(iter(methods), "")
devices = subprocess.run(["hyprctl", "-j", "devices"], check=True, text=True, capture_output=True)
keyboards = json.loads(devices.stdout).get("keyboards", [])
following, index = cycle_choice(state, keyboards)
@@ -187,7 +188,7 @@ def watch(bus):
if line == "cycle":
try:
indicator.select_next()
except GLib.Error:
except (GLib.Error, OSError, ValueError, subprocess.CalledProcessError):
indicator.pending = ""
refresh()
GLib.source_remove(timer)
+1 -1
View File
@@ -244,7 +244,7 @@ BarWidget {
horizontalMargin: 6
tooltipText: KeyboardLayoutModel.inputTooltip(root.inputState, root.layoutFull, root.multipleLayouts)
onPressed: function(button) {
if ((root.multipleInputs || root.multipleLayouts) && button === Qt.LeftButton) {
if (root.multipleInputs && button === Qt.LeftButton) {
InputMethodState.cycle()
} else if (root.multipleLayouts) {
root.cycleLayout()
+17
View File
@@ -140,6 +140,7 @@ def fake_process(command, **kwargs):
return subprocess.CompletedProcess(command, 0, stdout="")
with patch.object(indicator, "snapshot", side_effect=lambda bus: dict(live)), patch.object(indicator, "call", side_effect=fake_call), patch.object(indicator.subprocess, "run", side_effect=fake_process):
reader = indicator.Indicator(None)
reader.last = "removed-engine"
reader.select_next()
assert keyboards[0]["active_layout_index"] == 1
reader.select_next()
@@ -153,4 +154,20 @@ with patch.object(indicator, "snapshot", side_effect=lambda bus: dict(live)), pa
assert selected[-1] == "keyboard-us"
print("ok - mixed-layout bar clicks queue an engine without focus and apply it when a text field gains focus")
from unittest.mock import Mock
callback = {}
def register(source, flags, fn):
callback["read"] = fn
return 1
def exercise():
assert callback["read"](None, None) == indicator.GLib.SOURCE_CONTINUE
assert callback["read"](None, None) == indicator.GLib.SOURCE_CONTINUE
state = {"methods": ["keyboard-us", "pinyin"], "current": "keyboard-us", "name": "English", "label": "en", "language": "en"}
loop = Mock()
loop.run.side_effect = exercise
with patch.object(indicator.GLib, "MainLoop", return_value=loop), patch.object(indicator.GLib, "io_add_watch", side_effect=register), patch.object(indicator.GLib, "timeout_add", return_value=1), patch.object(indicator.GLib, "source_remove"), patch.object(indicator.os, "read", return_value=b"cycle\n"), patch.object(indicator, "snapshot", return_value=state), patch.object(indicator.subprocess, "run", side_effect=[subprocess.CalledProcessError(1, "hyprctl"), subprocess.CompletedProcess([], 0, stdout='{"keyboards": []}')]), patch.object(indicator, "call") as call, patch("builtins.print"):
indicator.watch(None)
assert call.call_args.args[1] == "SetCurrentIM"
print("ok - a failed compositor query leaves the bar click reader alive for the next request")
PY