The IBusInputContext currently seems to be a bit sloppy wrt propagating
the current state to engines after those are changed, this results in
engines possibly ending with purpose/hint/etc that do not actually
correspond to the current state.
Ensure this state is cleared on unfocus of our IBusInputContext, so
that the next time the input method receives an input focus, the new
state makes it all the way to the currently active engine.
Fixes situations in the GDM/lock screen password entry that IBus
would miss the PASSWORD hint set on the StEntry, and let passwords
be fed to engines.
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5966
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2512>
Besides user interaction, there's two users of IBusManager.setEngine():
- The code that toggles all IBus engines off on entries with PASSWORD
purpose.
- The code that toggles completion support on OSK presence.
These are currently pretty oblivious to each other. Make this
interaction more resilient by making all external IBusManager changes
more cautious about directly changing the engine, and revoke properly
the completion mode if it needs be (e.g. changing to a non-XKB engine).
But another notable change is that ibus-typing-booster is now preferred
always, over PASSWORD purpose hints. This is done to avoid possible
doubled attempts to change the current engine (and ensuing IBusInputContext
confusion).
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2512>
When propagating keys from the OSK, we usually feed these directly to
the IBusInputContext and let the IM handle the effects of this virtual
key event (which may also include feeding a key event back to us).
But these functions may also return a FALSE value if the key was "let
through" by the IM, which means the ball is in our yard again, and
we are responsible of letting this event get to its destination.
If that happens, just fall through, so the string is committed to
the client as an UTF-8 string, or propagated through keyboard events.
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5930
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2508>
The object the SignalTracker belongs to is stored in a map managed by
the SignalManager which keeps a reference to that object. This map is
never destroyed nor is any entry ever removed. This leads to all objects
that ever had SignalTrackers used on them being kept alive even after
all references outside of the SignalTracker are long gone. This then
also extends to other objects which are leaked indirectly through
reference chains from these objects.
And if some of those objects are GObjects, this will prevent them from
being finalized, leaking further resources. A StWidget for example will
not release its shadow textures.
Fix this by destroying the SignalTracker and removing it from the
SignalManager once the last signal it was tracking has been untracked.
A WeakMap could have been used as well, but we need the Map to be
iterable in some of the following changes.
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5807
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5796
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2466>
After the next commit, when some classes, such as PopupMenuManager try
to disconnect via a destroy handler, the SignalTracker might have
already been destroyed, so trying to get it from the SignalManager will
cause it to create a new one, which will then try to connect to the
destroy signal of the already destroyed object.
This could for example be triggered by changing backgrounds.
Fix this by not doing anything in disconnectObject if there is no
SignalTracker for that object.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2466>
This reverts commit 085102be74.
We need the SignalManager map top be iterable at shutdown for some of
the following changes. A WeakMap is not iterable. This revert changes it
back to a regular Map, which re-introduces the leaks caused by this.
Those will be fixed differently by the two followup commits.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2466>
The object the SignalTracker belongs to is stored in a map managed by
the SignalManager which keeps a reference to that object. This map is
never destroyed nor is any entry ever removed. This leads to all objects
that ever had SignalTrackers used on them being kept alive even after
all references outside of the SignalTracker are long gone. This then
also extends to other objects which are leaked indirectly through
reference chains from these objects.
And if some of those objects are GObjects, this will prevent them from
being finalized, leaking further resources. A StWidget for example will
not release its shadow textures.
Fix this by using a WeakMap in SignalManager.
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5807
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5796
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2450>
This mode changes the current IBus engine to ibus-typing-booster
under the rug (i.e. no changes in keyboard status menu) for any
XKB engine selected.
In order to make it useful for the currently selected language,
the typing-booster dictionary is changed to the current XKB
layout language. And since the OSK has its own emoji panel,
typing-boosters own emoji completion is disabled.
These changes only apply as long as the OSK panel is shown,
reverting to the original engine and typing-booster configuration
after it is hidden. This in theory also caters for users that
do have ibus-typing-booster enabled as an input source.
The final effect is text prediction for the language that is
being typed, according to the OSK layout, given that
ibus-typing-booster and the relevant hunspell dictionaries are
used.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2278>
This action will replace CLUTTER_KEY_Backspace emission for
the OSK backspace key. Following the available mockups, implement
different modes of operation:
- Single tap deletes a single character
- Long tap starts deleting characters one by one
- Longer tap switches to word-by-word deletion
This is made possible via the input method surrounding text,
inspecting the string to look the previous char/word position
backwards, and relies on IM focus providing enough context.
Since deleting text and getting surrounding text are both
async operations, we make one happen after the other, until
the button is released.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2278>
Newer versions of IBus (> 1.5.26) have the IBUS_CAP_OSK capability
which can be used to hint the active IM about an OSK driving input as
opposed to a physical keyboard. This may be used by IMs to tweak their
behavior to suit OSKs better.
Add the GNOME Shell side handling for this capability, and toggle it
on whenever the OSK is visible.
Since this is a far too new enum value and we don't want such new
IBus dependency, this change plays fast and loose with JS guarantees,
since a logical OR with an undefined value results in the other operand
unmodified it will work for older versions where the capability does not
exist and thus we want nothing extra enabled.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2415>
Multiple booleans - both in arguments and return values - are almost
always problematic API, because people have to memorize (or more likely
look up) the meaning of each position.
Instead, return a JS object so each value has a name attached to it.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2370>
After porting the more complex cases - in particular those that
affect a module's API - we are left with straight-forward D-Bus
method calls that can be moved to promise-based wrappers in one
go.
For consistency, this also switches from Remote to Async where
the call result is ignored.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2344>
The LoginManager abstraction is still mostly callback-based, not
least because the methods are thin wrappers around logind D-Bus
calls.
However as gjs' dbus wrapper now generates promised-based wrappers
as well, we can implement a proper async API just as naturally.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2344>
There are a couple of places left where we still use the old
indentation style, update them before making code changes.
After that, there are only a couple of non-type-safe comparisons
left of legacy style, so change those as well while we're at it.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2344>
Since IBus does not provide this information right away, we
so far cannot do much about providing a truthful anchor position
for the preedit text. But with the Mutter API in place it will
be up to this object to do so in the future.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2384>
ES modules do not allow exports to be overriden, in anticipation
of the ESM port add a `setCurrentExtension` utility which will
throw if used in the shell. This is tested using a conditional
import of Main.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2363>
We considered any ConnectFlag value major than SWAPPED as invalid, while
it's technically not fully true as we need to ensure that the passed
value is respecting the whole flags mask.
In fact, per se SWAPPED|AFTER (> SWAPPED) is a valid value (even if we
don't support the AFTER value).
But this makes the check more future-proof.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2366>
While untracking an object we used to compute it's proto for each signal
we were disconnecting from, while this is not needed when we're just
iterating over all the same owner signals, so let's add few more
functions to compute an object prototype, and repeat the disconnections
in the simplest way we can.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2366>
We used to create a temporary array of signal tracker keys and then to
iterate through them in order to untrack the objects, but the Map's can
be iterated directly so let's just use their native forEach.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2366>
Introduce a new class, EventEmitter, which implements signal
handling for pure JavaScript classes. EventEmitter still
utilizes GJS' addSignalMethods internally.
EventEmitter allows static typechecking to understand the
structure of event-emitting JS classes and makes creating
child classes simpler.
The name 'EventEmitter' mirrors a common name for this pattern
in Node and in JS libraries.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2043>
Both bluetooth and screencast support are based on build checks
right now. However in both cases, the dependency is only consumed
at runtime via the typelib, so let's actually check for that.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2297>
The screencast portal supports recording a single window,
and presents a list of open windows when that option is
selected. To allow updating that list when windows are
opened or closed, add a new "WindowsChanged" signal that
the portal can listen to.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2229>
We currently assume that any '::destroy' signal on a GObject type
has the semantics of the ClutterActor/GtkWidget signal, and should
therefore result in all signals being disconnected.
But we already have a case where the assumption doesn't hold: ShellWM
uses '::destroy' for the closing animation of windows, and the ShellWM
object itself remains very valid after the emission.
So rather than making assumptions about '::destroy', check objects
against a list of destroyable types that are explicitly registered
as such.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2226>
There are cases where we want to connect to a number of signals
for the lifetime of an object, but also other signals for a
limited period (say: between show and hide).
It is currently not possible to use disconnectObject() for the
latter, because it will disconnect all signals.
To address this use case, add a small class that can be used as
a transient signal holder, while still benefiting from autocleanup
by proxying the real owner.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2221>
The 'destroy' signal currently doesn't work with connectObject(),
because the handler is only connected after the signal tracker's
own destroy handler, which disconnects all handlers.
Address this by using connect_after for the cleanup handler, so
that other destroy handlers run before it (unless they also use
ConnectFlags.AFTER, but well *shrug*).
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2221>
Start using the new methods to simplify signal cleanup. For now,
focus on replacing existing cleanups; in most cases this means
signals connected in the constructor and disconnected on destroy,
but also other cases with a similarly defined lifetime (say: from
show to hide).
This doesn't change signal connections that only exist for a short
time (say: once), handlers that are connected on-demand (say: the
first time a particular method is called), or connections that
aren't tracked (read: disconnected) at all.
We will eventually replace the latter with connectObject() as
well - especially from actor subclasses - but the changeset is
already big enough as-is :-)
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1953>
The module exports a `addObjectSignalMethods()` method that extends
the provided prototype with `connectObject()` and `disconnectObject()`
methods.
In its simplest form, `connectObject()` looks like the regular
`connect()` method, except for an additional parameter:
```js
this._button.connectObject('clicked',
() => this._onButtonClicked(), this);
```
The additional object can be used to disconnect all handlers on the
instance that were connected with that object, similar to
`g_signal_handlers_disconnect_by_data()` (which cannot be used
from introspection).
For objects that are subclasses of Clutter.Actor, that will happen
automatically when the actor is destroyed, similar to
`g_signal_connect_object()`.
Finally, `connectObject()` allows to conveniently connect multiple
signals at once, similar to `g_object_connect()`:
```js
this._toggleButton.connect(
'clicked', () => this._onClicked(),
'notify::checked', () => this._onChecked(), this);
```
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1953>