67 lines
2.0 KiB
Python
67 lines
2.0 KiB
Python
"""Live Fcitx state for the existing keyboard layout widget."""
|
|
|
|
import json
|
|
import sys
|
|
|
|
from gi.repository import Gio, GLib
|
|
|
|
|
|
BUS = "org.fcitx.Fcitx5"
|
|
INTERFACE = "org.fcitx.Fcitx.Controller1"
|
|
|
|
|
|
def call(bus, method, args=None):
|
|
# Reading the bar must neither activate a stopped service nor wait indefinitely.
|
|
return bus.call_sync(BUS, "/controller", INTERFACE, method, args, None,
|
|
Gio.DBusCallFlags.NO_AUTO_START, 1000, None).unpack()
|
|
|
|
|
|
def snapshot(bus):
|
|
group = call(bus, "CurrentInputMethodGroup")[0]
|
|
methods = list(dict.fromkeys(item[0] for item in
|
|
call(bus, "InputMethodGroupInfo", GLib.Variant("(s)", (group,)))[1]))
|
|
info = call(bus, "CurrentInputMethodInfo")
|
|
return {"methods": methods, "current": info[0], "name": info[1], "label": info[4], "language": info[5]}
|
|
|
|
|
|
def cycle(bus):
|
|
state = snapshot(bus)
|
|
methods = state["methods"]
|
|
if len(methods) > 1 and state["current"] in methods:
|
|
following = methods[(methods.index(state["current"]) + 1) % len(methods)]
|
|
call(bus, "SetCurrentIM", GLib.Variant("(s)", (following,)))
|
|
|
|
|
|
def watch(bus):
|
|
previous = None
|
|
|
|
def refresh():
|
|
nonlocal previous
|
|
try:
|
|
state = snapshot(bus)
|
|
except GLib.Error:
|
|
state = {"methods": [], "current": "", "name": "", "language": ""}
|
|
line = json.dumps(state, ensure_ascii=False)
|
|
if line != previous:
|
|
print(line, flush=True)
|
|
previous = line
|
|
return GLib.SOURCE_CONTINUE
|
|
|
|
# Fcitx's controller has no current-method-changed signal. Keep one bus
|
|
# connection open instead of spawning a command on every poll. Polling also
|
|
# follows per-application input contexts and recovers after service restarts.
|
|
refresh()
|
|
GLib.timeout_add(500, refresh)
|
|
GLib.MainLoop().run()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
|
|
if sys.argv[1:] == ["cycle"]:
|
|
cycle(bus)
|
|
else:
|
|
watch(bus)
|
|
except GLib.Error as error:
|
|
raise SystemExit(str(error))
|