Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable input method in specific apps #328

Closed
PROxZIMA opened this issue Jun 29, 2022 · 17 comments
Closed

Disable input method in specific apps #328

PROxZIMA opened this issue Jun 29, 2022 · 17 comments

Comments

@PROxZIMA
Copy link

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is.

Disable typing suggestions (input method) in some specific apps. I looked up ibus docs but didn't find anything relevant.

Describe the solution you'd like
A clear and concise description of what you want to happen.

An option to disable typing suggestions (input method) in some specific apps like for example VSCode. I don't want the suggestions to show up because VSCode has its own auto completion.

The only way to achieve this is toggling on/off input mode which is not suitable when switching apps.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots or videos about the feature request here.

@PROxZIMA PROxZIMA changed the title [ENHANCEMENT] Disable input method in specific apps Disable input method in specific apps Jun 29, 2022
@mike-fabian mike-fabian added this to To do in Mike’s github project board via automation Jun 30, 2022
@mike-fabian
Copy link
Owner

Right now this is not possible because at the moment the input method has no information about which app is being typed into.

But this will become possible very soon, ibus >= 1.5.27 will have a new feature which makes it possible for an input method like ibus-typing-booster to get information about which app just got focus.

ibus-typing-booster already checks whether this feature is available in ibus:

https://github.com/mike-fabian/ibus-typing-booster/blob/main/engine/hunspell_table.py#L122

        LOGGER.info('ibus version = %s', '.'.join(map(str, IBUS_VERSION)))
        try:
            super().__init__(
                connection=bus.get_connection(),
                object_path=obj_path,
                has_focus_id=True)
            LOGGER.info('This ibus version has focus id.')
        except TypeError as error:
            super().__init__(
                connection=bus.get_connection(),
                object_path=obj_path)
            LOGGER.info('This ibus version does *not* have focus id: %s: %s',
                        error.__class__.__name__, error)

i.e. it checks whether the used version of ibus supports the has_focus_id parameter in the __init__() function.

If this is available, the do_focus_in_id() function is called when a window gets focus instead of the old do_focus_in() function.
The new function has a new parameter client:

https://github.com/mike-fabian/ibus-typing-booster/blob/main/engine/hunspell_table.py#L6126

    def do_focus_in_id(self, object_path: str, client: str) -> None:
        '''
        Called for ibus >= 1.5.27 when a window gets focus while
        this input engine is enabled
        '''

and this client contains strings like gtk3:firefox. So if this feature is available, ibus-typing-booster can know which application got focus.

@mike-fabian
Copy link
Owner

mike-fabian commented Jun 30, 2022

Currently, even if this feature is available, ibus-typing-booster doesn’t use it yet, it just shows in the debug log which client got focus.

But I plan to use this new feature for exactly what you want.

Even a bit more, I think I want to offer not only turning the input on/off but changing any setting.
My idea is something like this:

Setting                Value           Regular expression
---------------------------------------------------------
inputmode              false           firefox|chrome
dictionary             fr_FR,it_IT     gedit
...

I.e. I want to make it possible to change any setting available in gsettings to any of its possible values when the client id matches a certain regular expression.

In the first example above, inputmode would be switched to false when firefox or chrome get focus (Setting inputmode to false disables input, which is what you want for VSCode). In the second example above, dictionary would be set to French and Italian dictionaries when gedit gets focus.

My current idea is to make Setting a combobox where you can select the setting you want to change and Value and Regular expression text entry fields where you can enter which value should be set when a regular expression matches a client id.

@mike-fabian
Copy link
Owner

Using 1.5.26-12.1.fc36 from https://copr.fedorainfracloud.org/coprs/fujiwara/ibus/builds/ and ibus-typing-booster-2.16.7 I can see this line in ~/.local/share/ibus-typing-booster/debug.log when the focus gets on VScode:

2022-06-30 16:44:09,441 hunspell_table.py line 6137 do_focus_in_id DEBUG: object_path=/org/freedesktop/IBus/InputContext_86 client=gtk3-im:code

I.e. with ibus and ibus-typing-booster new enough, I can detect when VScode gets focus and I can implement the idea from my last comment.

@PROxZIMA
Copy link
Author

PROxZIMA commented Jul 1, 2022

This is actually super informative to me too. Getting focused app name will open a whole lot of customisation to typing booster. Thanks for the details.

@mike-fabian mike-fabian moved this from To do to In progress in Mike’s github project board Jul 13, 2022
@businessBoris
Copy link

[Sorry to butt-in, I came here to request the same thing for the terminal apps. Gnome-terminal and the like.
Thank you both for thinking about it too.
I'm super-spacing back and forth like crazy at the moment as I document, test and code.]

@mike-fabian
Copy link
Owner

When a new enough ibus version is used so that focus id is available and focus gets to a gtk program and the gtk input module is used, I get something like this from focus id:

gtk3-im:gnome-terminal-server

But I found that even when a new enough ibus version is used so that focus id is available, the name of the currently focused app was still not given in a the following cases:

  • Qt applications: I get only 'Qt' or 'QIBusInputContext' from ibus focus id, not the program name
  • XIM applications like xterm, urxvt, ...: I get only 'xim' from ibus focus id, not the program name
  • When wayland input is used on Gnome (I.e. when using Gnome Wayland with GTK_IM_MODULE unset): I get only 'gnome-shell' from ibus focus id, not the program name
  • When wayland input is used on KDE Plasma Wayland
  • sometimes, when a window first gets focus, the focus id support in ibus seems to fail to get the information, it usually starts working when the window gets focus for the second time

Before starting to implement support for specific settings in specific windows, I wanted to make sure that I can get the necessary information more reliably and can also get it for XIM apps and also for Wayland.

So now I check whether the information I get from focus id contains a :, if yes I leave it as it is, the program name should be after the : then.

But when there is no : this means that either focus id support is not available in this version of ibus at all or it can only give the input module used but not the program name.

In that case I try to figure out the program name on my own using xprop or AT-SPI.

  • On Wayland desktops: Tries AT-SPI first and falls back to xprop
  • On X11 desktops: Uses only xprop

ibus-typing-booster >= 2.18.6 has this fallback mechanism to figure out the program name of the active window included:

https://github.com/mike-fabian/ibus-typing-booster/blob/main/engine/itb_active_window.py

and this is used in do_focus_in_id like this:

https://github.com/mike-fabian/ibus-typing-booster/blob/main/engine/hunspell_table.py#L6225

        self._im_client = client
        if ':' not in self._im_client:
            (program_name,
             _window_title) = itb_active_window.get_active_window()
            if program_name:
                self._im_client += ':' + program_name
            if DEBUG_LEVEL > 1:
                LOGGER.debug('self._im_client=%s\n', self._im_client)

i.e. I try to append the program name to `self._im_client if it is missing.

This seems to work very reliably on X11 desktops and mostly reliably on Wayland desktops.

On Wayland desktops one needs to set some environment variables to make AT-SPI work with Qt programs as well:

export QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1
export QT_ACCESSIBILITY=1

and AT-SPI may also fail when the needed daemons are not running, see https://www.freedesktop.org/wiki/Accessibility/AT-SPI2/

Even then AT-SPI may still fail if something crashed very badly the loop iterating over all the windows of the desktop may hang for a long time at a defunt window:

        for application in desktop:
            if application.getState().contains(pyatspi.STATE_DEFUNCT):
                continue
            for window in application:
                if window.get_state_set().contains(pyatspi.STATE_ACTIVE):
                    _ACTIVE_WINDOW = (application.name, window.name)
                    return

So I start that iteration in a different thread and if it cannot finish after a timeout of 0.5 seconds I give up and try to fall back to xprop.

But this is quite rare, usually AT-SPI seems to work fine on Gnome and KDE Wayland.

So I think I can start implementing specific settings for specific apps now.

@mike-fabian
Copy link
Owner

If you already have ibus-typing-booster >= 2.18.6, you can already test whether the detection of the program name of the active window works reliably. If you set the debug level in the setup tool to 1, you can see the detected program name above the candidate list.

For example in this screenshot, I got nothing from ibus but my fallback found “gnome-terminal”:

Screenshot

@mike-fabian
Copy link
Owner

When I tried again after moving the focus to the setup tool and back to the terminal I got:

Screenshot

@mike-fabian
Copy link
Owner

In case of the second screenshot I got the information gtk3-im:gnome-terminal-server from ibus and left it as is, in case of the first screenshot I got nothing from ibus and tried my fallback.

@mike-fabian
Copy link
Owner

The information gotten by ibus and by my fallback may sometimes differ slightly, my fallback got :gnome-terminal and ibus got gtk3-im:gnome-terminal-server but for my idea making the matching work using regular expressions as explained in

#328 (comment)

this should be good enough, one can easily match both with a regular expression.

mike-fabian added a commit that referenced this issue Feb 6, 2023
Useful for: #328

It can already be used to solve this issue, but only by setting the
autosettings option using the command line.  I have not yet added code
to do this graphically to the setup tool.
@mike-fabian
Copy link
Owner

[Sorry to butt-in, I came here to request the same thing for the terminal apps. Gnome-terminal and the like. Thank you both for thinking about it too. I'm super-spacing back and forth like crazy at the moment as I document, test and code.]

https://github.com/mike-fabian/ibus-typing-booster/releases/tag/2.21.0

has a checkbox option now to disable Typing Booster in terminals.

See: #414

Works for Gtk based terminals like gnome-terminal, gnome-console, xfce4-terminal, …

Should also work for xterm, konsole, rxvt, and urxvt. For these non-gtk terminals it relies on getting the right information about the program name, but that seems to work reliably.

@mike-fabian
Copy link
Owner

@PROxZIMA @businessBoris

Release 2.21.0 also contains an experimental feature to change options automatically based on regular expressions matching the information in self._im_client.

There is no GUI for this yet, but one can try this option already by setting it from the command line.

The contents of self._im_client can be shown by setting the debug level to 1 using the setup tool, then using typing booster in the window one is interested in and displaying a candidate list. In the auxiliary text on top of he candidate list, the contents of self._im_client are shown. As in this screenshot:

Screenshot

@mike-fabian
Copy link
Owner

In the screenshot one sees that the client id is:

gtk3-im:firefox:Beaver - Wikipedia — Mozilla Firefox

The client id has the format

toolkit:program:window-title

One can now match this using regular expressions and change Typing Booster settings when such a regular expression matches.

For example if one sets this using the command line:

dconf write /org/freedesktop/ibus/engine/typing-booster/autosettings "[['inputmode', 'false', 'gtk3-im:firefox:']]"

This has the effect of switching Typing Booster to direct input mode (i.e. bascially off) in Firefox.

One could also do that only in Wikipedia tabs matching like this:

dconf write /org/freedesktop/ibus/engine/typing-booster/autosettings "[['inputmode', 'false', 'gtk3-im:firefox:.*Wikipedia']]"

That example might be a bit silly, but while testing I found it useful to automatically switch the dictionaries used by Typing Booster to a different set if I am on an input field in a firefox tab matching "gtk3-im:firefox:Duolingo".

The value of autosettings which can be set is a list of lists of 3 strings each. Each list consists of

setting, value, regular expression

When the regular expression matches, the setting is set to the specified value.

This could also be used to switch Typing Booster off in terminals using something like:

dconf write /org/freedesktop/ibus/engine/typing-booster/autosettings "[['inputmode', 'false', ':.*terminal.*:']]"

The effect is slightly different then using the checkbox option

☑️ Disable in terminals

When the checkbox option is used, Typing Booster is permanently off in terminals and cannot be switched on (Only the compose support of Typing Booster keeps working then even in terminals).

When switching Typing Booster off in terminals using something like:

dconf write /org/freedesktop/ibus/engine/typing-booster/autosettings "[['inputmode', 'false', ':.*terminal.*:']]"

The inputmode is set to false when the terminal gets the focus,, but it is still possible to switch the inputmode to true if one has a keybinding set to Toggle_input_mode_on_off.

Personally I prefer that for terminals, I also like it when Typing Booster switches off in terminals by default but I like to keep the option switching it on.

The simpler option

☑️ Disable in terminals

is useful when one never wants to use Typing Booster in terminals and wants just a very simple way to switch it off.

One can do more complicated stuff with the autosettings options, but this is more for advanced users who have special needs.

@mike-fabian
Copy link
Owner

@PROxZIMA

An option to disable typing suggestions (input method) in some specific apps like for example VSCode. I don't want the suggestions to show up because VSCode has its own auto completion.

This is now possible with the autosettings option.

@mike-fabian
Copy link
Owner

@PROxZIMA

Screenshot

@mike-fabian
Copy link
Owner

This video shows how one can now disable Typing Booster automatically when Visual Studio gets focus.

In the terminal one sees that I did set

dconf write /org/freedesktop/ibus/engine/typing-booster/autosettings "[['inputmode', 'false', 'gtk3-im:code'

When I click with the mouse to change the focus between the terminal (where Typing Booster is not disabled) and the Visual Studio Code, one can see that the Typing Booster icon in the panel changes between 🚀 (on) when the focus goes to the terminal and 🐌 (off) when the focus goes to Visual Studio. When the focus is on Visual Studio, I can still enable Typing Booster with the keybinding Control+Tab I have bound to toogle_input_mode_on_off:

Peek.2023-02-06.19-39.mp4

@mike-fabian
Copy link
Owner

New release:

https://github.com/mike-fabian/ibus-typing-booster/releases/tag/2.22.0

There is a GUI now for the “Autosettings” options.

And because the new options are rather complicated, especially “Autosettings”, there are two new chapters in the online documentation:

Disabling in terminals: https://mike-fabian.github.io/ibus-typing-booster/docs/user/#2_2_6

Autosettings: https://mike-fabian.github.io/ibus-typing-booster/docs/user/#2_2_7

With “Autosettings”, disabling in “VSCode” as originally requested in this issue is now easily possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants