diff --git a/engine/hunspell_table.py b/engine/hunspell_table.py
index 152364ad..02c053d6 100644
--- a/engine/hunspell_table.py
+++ b/engine/hunspell_table.py
@@ -219,6 +219,9 @@ def __init__(
'ibuseventsleepseconds']['user']
LOGGER.info('self._ibus_event_sleep_seconds=%s', self._ibus_event_sleep_seconds)
+ self._ibus_us_keymap = IBus.Keymap('us')
+ self._use_us_layout: bool = self._settings_dict['useuslayout']['user']
+
self._emoji_predictions: bool = self._settings_dict[
'emojipredictions']['user']
@@ -748,6 +751,9 @@ def _init_settings_dict(self) -> Dict[str, Any]:
'ibuseventsleepseconds': {
'set': self.set_ibus_event_sleep_seconds,
'get': self.get_ibus_event_sleep_seconds},
+ 'useuslayout': {
+ 'set': self.set_use_us_layout,
+ 'get': self.get_use_us_layout},
'errorsound': {
'set': self.set_error_sound,
'get': self.get_error_sound},
@@ -5251,6 +5257,32 @@ def get_ibus_event_sleep_seconds(self) -> float:
'''Returns the current value ibus event sleep seconds '''
return self._ibus_event_sleep_seconds
+ def set_use_us_layout(
+ self, mode: bool, update_gsettings: bool = True) -> None:
+ '''Sets whether the use of the US keyboard is forced
+
+ :param mode: True if the use of the US keyboard is forced, False if not
+ :param update_gsettings: Whether to write the change to Gsettings.
+ Set this to False if this method is
+ called because the Gsettings key changed
+ to avoid endless loops when the Gsettings
+ key is changed twice in a short time.
+ '''
+ if self._debug_level > 1:
+ LOGGER.debug(
+ '(%s, update_gsettings = %s)', mode, update_gsettings)
+ if mode == self._use_us_layout:
+ return
+ self._use_us_layout = mode
+ if update_gsettings:
+ self._gsettings.set_value(
+ 'useuslayout',
+ GLib.Variant.new_boolean(mode))
+
+ def get_use_us_layout(self) -> bool:
+ '''Returns whether the use of the US keyboard layout is forced'''
+ return self._use_us_layout
+
def set_error_sound(
self, error_sound: bool, update_gsettings: bool = True) -> None:
'''Sets whether a sound is played on error or not
@@ -6968,6 +7000,21 @@ def do_process_key_event( # pylint: disable=arguments-differ
key = itb_util.KeyEvent(keyval, keycode, state)
if self._debug_level > 1:
LOGGER.debug('KeyEvent object: %s', key)
+ if self._use_us_layout and key.name != 'Multi_key':
+ # Do not translate the Multi_key: If the non-US layout as
+ # a Multi_key, trying to translate it to US layout just
+ # takes it away. Skipping the translation keeps the
+ # Multi_key around which is more useful, it can still be
+ # used for Compose then.
+ key = itb_util.KeyEvent(
+ IBus.Keymap.lookup_keysym(
+ self._ibus_us_keymap,
+ keycode,
+ state),
+ keycode, state)
+ if self._debug_level > 1:
+ LOGGER.debug('Forcing US layout...')
+ LOGGER.debug('KeyEvent object: %s', key)
disabled = False
if not self._input_mode:
diff --git a/org.freedesktop.ibus.engine.typing-booster.gschema.xml b/org.freedesktop.ibus.engine.typing-booster.gschema.xml
index dd6fd308..a9c30b13 100644
--- a/org.freedesktop.ibus.engine.typing-booster.gschema.xml
+++ b/org.freedesktop.ibus.engine.typing-booster.gschema.xml
@@ -399,6 +399,9 @@
have been typed.
+
+ false
+
false
diff --git a/setup/main.py b/setup/main.py
index efa66718..5f7510fb 100644
--- a/setup/main.py
+++ b/setup/main.py
@@ -789,6 +789,22 @@ def __init__( # pylint: disable=too-many-statements
self._ascii_digits_checkbutton,
0, _options_grid_row, 2, 1)
+ self._use_us_layout_checkbutton = Gtk.CheckButton(
+ # Translators: Whether the use of the US keyboard layout is
+ # forced while Typing Booster is active
+ label=_('Use US keyboard layout'))
+ self._use_us_layout_checkbutton.set_tooltip_text(
+ _('Whether the use of the US keyboard layout is forced '
+ 'while Typing Booster is active.'))
+ self._use_us_layout_checkbutton.connect(
+ 'clicked', self._on_use_us_layout_checkbutton)
+ self._use_us_layout_checkbutton.set_active(
+ self._settings_dict['useuslayout']['user'])
+ _options_grid_row += 1
+ self._options_grid.attach(
+ self._use_us_layout_checkbutton,
+ 0, _options_grid_row, 2, 1)
+
self._emoji_trigger_characters_label = Gtk.Label()
self._emoji_trigger_characters_label.set_text(
# Translators: The characters in this list trigger an
@@ -2304,6 +2320,7 @@ def _init_settings_dict(self) -> Dict[str, Any]:
'preeditstyleonlywhenlookup':
self.set_preedit_style_only_when_lookup,
'mincharcomplete': self.set_min_char_complete,
+ 'useuslayout': self.set_use_us_layout,
'errorsound': self.set_error_sound,
'errorsoundfile': self.set_error_sound_file,
'soundbackend': self.set_sound_backend,
@@ -3187,6 +3204,15 @@ def _on_ascii_digits_checkbutton(
self.set_ascii_digits(
widget.get_active(), update_gsettings=True)
+ def _on_use_us_layout_checkbutton(
+ self, widget: Gtk.CheckButton) -> None:
+ '''
+ The checkbutton whether to force the use of the US
+ keyboard layout has been clicked.
+ '''
+ self.set_use_us_layout(
+ widget.get_active(), update_gsettings=True)
+
def _on_emoji_trigger_characters_entry(
self, widget: Gtk.Entry, _property_spec: Any) -> None:
'''
@@ -6099,6 +6125,30 @@ def set_min_char_complete(
self._min_char_complete_adjustment.set_value(
int(min_char_complete))
+ def set_use_us_layout(
+ self,
+ mode: bool,
+ update_gsettings: bool = True) -> None:
+ '''Sets whether the use of the US keyboard is forced
+
+ :param mode: True if the use of the US keyboard is forced, False if not
+ :param update_gsettings: Whether to write the change to Gsettings.
+ Set this to False if this method is
+ called because the Gsettings key changed
+ to avoid endless loops when the Gsettings
+ key is changed twice in a short time.
+ '''
+ LOGGER.info(
+ '(%s, update_gsettings = %s)', mode, update_gsettings)
+ mode = bool(mode)
+ self._settings_dict['useuslayout']['user'] = mode
+ if update_gsettings:
+ self._gsettings.set_value(
+ 'useuslayout',
+ GLib.Variant.new_boolean(mode))
+ else:
+ self._use_us_layout_checkbutton.set_active(mode)
+
def set_error_sound(
self,
error_sound: bool,