Skip to content

Commit

Permalink
#4449 use setting-change message for ibus layouts
Browse files Browse the repository at this point in the history
this prevents the hello packet from growing too large
  • Loading branch information
totaam committed Jan 14, 2025
1 parent 73ab86e commit e783fb1
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 18 deletions.
26 changes: 16 additions & 10 deletions xpra/client/gtk3/tray_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -1176,19 +1176,21 @@ def make_keyboardmenuitem(self) -> Gtk.Menu:
def make_layoutsmenuitem(self) -> Gtk.ImageMenuItem:
keyboard = self.menuitem("Layout", "keyboard.png", "Select your keyboard layout")
set_sensitive(keyboard, False)
self.layout_submenu = Gtk.Menu()
keyboard.set_submenu(self.layout_submenu)
self.keyboard_layout_item = keyboard
self.after_handshake(self.populate_keyboard_layouts)
return keyboard

def populate_keyboard_layouts(self) -> None:
# by default, use keyboard helper values:
self.populate_keyboard_helper_layouts()
set_sensitive(self.keyboard_layout_item, True)
kh = self.client.keyboard_helper
if kh.server_ibus and kh.layout and PREFER_IBUS_LAYOUTS:
self.populate_ibus_keyboard_layouts()
else:
self.populate_keyboard_helper_layouts()

if PREFER_IBUS_LAYOUTS:
def got_ibus_layouts(setting: str, ibus_layouts) -> None:
kh = self.client.keyboard_helper
if ibus_layouts and kh.layout and PREFER_IBUS_LAYOUTS:
self.populate_ibus_keyboard_layouts(ibus_layouts)
self.client.on_server_setting_changed("ibus-layouts", got_ibus_layouts)

def kbitem(self, title: str, layout: str, variant: str, backend="", name="", active=False) -> Gtk.CheckMenuItem:

Expand Down Expand Up @@ -1225,14 +1227,16 @@ def set_layout(item) -> None:
l.keyboard_variant = variant
return l

def populate_ibus_keyboard_layouts(self) -> None:
def populate_ibus_keyboard_layouts(self, ibus_layouts: dict) -> None:
self.layout_submenu = Gtk.Menu()
self.keyboard_layout_item.set_submenu(self.layout_submenu)
kh = self.client.keyboard_helper
# use csv and back to get every single layout string:
layouts = uniq((kh.layout_option or csv(kh.layouts)).split(","))
log(f"populate_ibus_keyboard_layouts() {layouts}")
# find the "engines" matching the layouts:
engines = {}
for i, engine in enumerate(kh.server_ibus.get("engines", ())):
for i, engine in enumerate(ibus_layouts.get("engines", ())):
layout = engine.get("layout", "")
if not layout or layout not in layouts:
continue
Expand All @@ -1242,11 +1246,13 @@ def populate_ibus_keyboard_layouts(self) -> None:
engine = engines[rank]
layout = engine.get("layout", "")
name = engine.get("name", layout)
descr = engine.get("description", layout)
descr = engine.get("description", layout).split("\n")[0]
variant = engine.get("variant", "")
self.layout_submenu.append(self.kbitem(descr, layout, variant, "ibus", name))

def populate_keyboard_helper_layouts(self) -> None:
self.layout_submenu = Gtk.Menu()
self.keyboard_layout_item.set_submenu(self.layout_submenu)

def disable(message: str) -> None:
self.keyboard_layout_item.set_tooltip_text(message)
Expand Down
1 change: 0 additions & 1 deletion xpra/client/gui/keyboard_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ def __init__(self, net_send: Callable, keyboard_sync=True,
self.shortcut_modifiers: list[str] = []
self.key_shortcuts_strs = key_shortcuts
self.key_shortcuts: dict[str, list[str]] = {}
self.server_ibus = {}
# command line overrides:
self.raw = raw
self.model_option = model
Expand Down
3 changes: 2 additions & 1 deletion xpra/client/gui/ui_client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,6 @@ def process_ui_capabilities(self, caps: typedict) -> None:
modifier_keycodes = caps.dictget("modifier_keycodes", {})
if modifier_keycodes:
self.keyboard_helper.set_modifier_mappings(modifier_keycodes)
self.keyboard_helper.server_ibus = caps.dictget("ibus")
self.key_repeat_delay, self.key_repeat_interval = caps.intpair("key_repeat", (-1, -1))
self.handshake_complete()

Expand Down Expand Up @@ -599,6 +598,7 @@ def _process_setting_change(self, packet: PacketType) -> None:
"start-new-commands", "client-shutdown", "webcam",
"bandwidth-limit", "clipboard-limits",
"xdg-menu", "monitors",
"ibus-layouts",
):
setattr(self, "server_%s" % setting.replace("-", "_"), value)
else:
Expand Down Expand Up @@ -679,6 +679,7 @@ def get_keyboard_caps(self) -> dict[str, Any]:
caps["keyboard"] = False
else:
caps["keyboard"] = True
caps["ibus"] = True
caps["modifiers"] = self.get_current_modifiers()
skip = ("keycodes", "x11_keycodes") if DELAY_KEYBOARD_DATA else ()
caps["keymap"] = kh.get_keymap_properties(skip)
Expand Down
21 changes: 21 additions & 0 deletions xpra/server/mixins/input.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# later version. See the file COPYING for details.
# pylint: disable-msg=E1101

import threading
from time import monotonic
from typing import Any

Expand All @@ -23,6 +24,8 @@

INPUT_SEQ_NO = envbool("XPRA_INPUT_SEQ_NO", False)

EXPOSE_IBUS_LAYOUTS = envbool("XPRA_EXPOSE_IBUS_LAYOUTS", True)


class InputServer(StubServerMixin):
"""
Expand Down Expand Up @@ -51,6 +54,14 @@ def __init__(self):
self.key_repeat_timer = 0

self.last_mouse_user = None
self.ibus_layouts = {}

def get_ibus_layouts(self):
if EXPOSE_IBUS_LAYOUTS and not self.ibus_layouts:
from xpra.keyboard.ibus import query_ibus
self.ibus_layouts = dict((k, v) for k, v in query_ibus().items() if k.startswith("engine"))
keylog.info("loaded ibus layouts from %s: %s", threading.current_thread(), self.ibus_layouts)
return self.ibus_layouts

def init(self, opts) -> None:
props = typedict()
Expand Down Expand Up @@ -95,6 +106,14 @@ def parse_hello(self, ss, caps: typedict, send_ui: bool) -> None:
if send_ui:
self.parse_hello_ui_keyboard(ss, caps)

def send_initial_data(self, ss, caps, send_ui: bool, share_count: int) -> None:
if not send_ui:
return
ibus_layouts = self.get_ibus_layouts()
if ibus_layouts and hasattr(ss, "send_ibus_layouts"):
keylog("calling %s", ss.send_ibus_layouts)
ss.send_ibus_layouts(ibus_layouts)

def watch_keymap_changes(self) -> None:
""" GTK servers will start listening for the 'keys-changed' signal """

Expand Down Expand Up @@ -130,6 +149,8 @@ def get_keyboard_info(self) -> dict[str, Any]:
kc = self.keyboard_config
if kc:
info.update(kc.get_info())
if EXPOSE_IBUS_LAYOUTS:
info["ibus"] = self.get_ibus_layouts()
keylog("get_keyboard_info took %ims", (monotonic() - start) * 1000)
return info

Expand Down
14 changes: 8 additions & 6 deletions xpra/server/source/input.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,14 @@

from typing import Any

from xpra.util.env import envbool
from xpra.util.str_fn import Ellipsizer
from xpra.server.source.stub_source_mixin import StubSourceMixin
from xpra.keyboard.mask import DEFAULT_MODIFIER_MEANINGS
from xpra.util.objects import typedict
from xpra.log import Logger

log = Logger("keyboard")

EXPOSE_IBUS_LAYOUTS = envbool("XPRA_EXPOSE_IBUS_LAYOUTS", True)


class InputMixin(StubSourceMixin):
"""
Expand All @@ -32,6 +30,7 @@ def is_needed(cls, caps: typedict) -> bool:

def init_state(self) -> None:
self.keyboard_config = None
self.ibus = False
self.double_click_time: int = -1
self.double_click_distance: tuple[int, int] | None = None
# mouse echo:
Expand All @@ -51,6 +50,7 @@ def parse_client_caps(self, c: typedict):
self.double_click_time = c.intget("double_click.time")
self.double_click_distance = c.intpair("double_click.distance")
self.mouse_last_position = c.intpair("mouse.initial-position")
self.ibus = c.boolget("ibus")

def get_info(self) -> dict[str, Any]:
dc_info: dict[str, Any] = {}
Expand All @@ -75,11 +75,13 @@ def get_caps(self) -> dict[str, Any]:
mck = getattr(self.keyboard_config, "modifier_client_keycodes", None)
if mck:
caps["modifier_keycodes"] = mck
if EXPOSE_IBUS_LAYOUTS:
from xpra.keyboard.ibus import query_ibus
caps["ibus"] = dict((k, v) for k, v in query_ibus().items() if k.startswith("engine"))
return caps

def send_ibus_layouts(self, ibus_layouts: dict) -> None:
log(f"send_ibus_layouts(%s) {self.ibus=}", Ellipsizer(ibus_layouts))
if self.ibus and ibus_layouts:
self.send_setting_change("ibus-layouts", ibus_layouts)

def set_layout(self, layout: str, variant: str, options):
if not self.keyboard_config:
return
Expand Down

0 comments on commit e783fb1

Please sign in to comment.