We have made good progress with transitioning to the new style,
to the point where we can complete it with a final push.
Start with changing the remaining places that still use double
quotes.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2866>
We sometimes obtained the current event through the general machinery
just so we could pass it along as a ClutterEvent instead of a specialized
subtype.
We now get that out of the box, so may avoid getting the current event
which is just a cast of the same current event we already have.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2872>
These traditionally got the various ClutterEvent subtype structs as their
argument, so it was not allowed to use ClutterEvent generic getter methods
in these vfuncs. These methods used direct access to struct fields instead.
This got spoiled with the move to make ClutterEvent opaque types, since
these are no longer public structs so GNOME Shell most silently failed to
fetch the expected values from event fields. But since they are not
ClutterEvents either, the getters could not be used on them.
Mutter is changing so that these vmethods all contain an alias to the
one and only Clutter.Event type, thus lifting those barriers, and making
it possible to use the ClutterEvent methods in these vfuncs.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2950
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2872>
Commit 17d9ec5788 made the input method call update() more eagerly,
but also at times that it does not have a cursor position yet. Make
it bail out correctly in that situation.
Fixes: 17d9ec5788 ("inputMethod: Keep Capabilite.FOCUS before context.focus_in/focus_out")
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2876>
If context.focus_out() is called *after* context.set_capabilities(0),
The FocusOut D-Bus method is ignored because of no FOCUS capability.
If context.focus_out() is called *before* context.set_capabilities(0),
The 0 capability is set to the next focused context and the
FocusIn D-Bus method is ignored because of no FOCUS capability.
So context.set_capabilities(0) should not be called.
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6415
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2666>
The module is shared between the various D-Bus services and the
main gnome-shell process, so it was originally left out to allow
porting different bits at their own speed.
Now that everything has been ported to ESM, there is no reason
to not move that particular module as well.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2868>
Overriding vfuncs can be useful, in particular when we convert
to ES modules, and exported symbols cannot easily be swapped out.
Adapt overrideMethod() to work correctly in that case as well.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2809>
The custom setter used by the slider item isn't emitting change
notifications, so the property binding that uses it as source
never propagates the new value.
Fix this by emitting proper change notifications.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2856>
We have always defaults to an empty ornament, so that menu items
are always aligned, even when radio items are used.
However radio items are fairly rare, so most of the time we end
up with an extra margin with no purpose. The design team now
prefers radio items to only align with each other, so that regular
items get the expected margin.
Change the defaults accordingly.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2843>
Soon only radio items should use a visible ornament, to avoid
unnecessary extra margins in regular items.
Network items can act as both radio- and regular items, so
update the ornament accordingly.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2843>
Layout items use the ornament to indicate the active layout, so
their ornament should always be NONE or DOT.
The default is about to change to HIDDEN, so explicitly initialize
the ornament to NONE to keep the current radio item appearance.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2843>
Settings no longer exposes a slider for the keyboard brightness,
leaving keyboard shortcuts as the only way of adjusting it.
This is good enough in most cases, because devices with keyboard
backlight usually include corresponding keys on their keyboard.
However for devices without those keys, it would be good for the
settings to be exposed somewhere again. Quick settings seems like
a more appropriate place than "proper" Settings, since it gives
quick access that doesn't require a major focus change.
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6765
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2820>
Extensions must now export a class with a fillPreferencesWindow()
method in their prefs. That is less convenient for extensions
with simple preferences than the old buildPrefsWidget() hook, as
they must wrap their widget in page/group widgets.
Address this by adding a default fillPreferencesWindow() implementation
that calls a getPreferencesWidget() method and wraps it as necessary.
This is flexible enough to support different cases fairly conveniently,
from simple single-widget prefs over tweaking the window to complex
multi-page prefs:
```js
class SimplePreferences extends ExtensionPreferences {
getPreferencesWidget() {
return new SimplePrefsWidget();
}
}
class TinkerPreferences extends ExtensionPreferences {
getPreferencesWidget() {
return new SimplePrefsWidget();
}
fillPreferencesWindow(window) {
super.fillPreferencesWindow(window);
window.set_default_size(123, 456);
}
}
class FullPreferences extends ExtensionPreferences {
fillPreferencesWindow(window) {
const page1 = new GeneralPage();
window.add(page1);
const page2 = new FoobarPage();
window.add(page2);
}
}
```
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2838>
Use the new defineTranslationFunctions() method from the previous
commit to create gettext functions for the module, instead of
re-exporting from the shared module.
It is now up to extension developers to use the more effective
```js
import {Extension} from 'etensions/extension.js';
const {gettext: _} =
Extension.defineTranslationFunctions(import.meta.url);
```
or the more convenient
```js
import {Extension, gettext} from 'extensions/extension.js';
const _ = gettext;
```
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2838>
The method can be used to define a set of gettext functions that
call the corresponding method of an extension.
Those functions are very similar to the gettext functions we are
exporting, except that:
- looking up the extension is delegated to the
Extension/Preferences class
- it is possible to avoid examining the stack
when called with `import.meta.url`
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2838>
With convenience API like getSettings() now being provided by
the ExtensionObject subclass, extensions will need to access
their entry point more often.
Having to pass a pointer through the hierarchy can be annoying,
so add a static method that allows them to look it up:
```js
const ext = Extension.lookupByURL(import.meta.url);
this._settings = ext.getSettings();
```
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2838>
Extensions now must export a class that conforms to a particular
interface both for the actual extension as well as for prefs:
enable()/disable() methods for the former, fillPreferencesWindow()
for the latter.
This is quite similar to the previous method-based entry points,
but it also gives us a more structured way of providing convenience
API in form of base classes.
Do that in form of Extension and ExtensionPreferences classes on
top of a common ExtensionBase base class.
getSettings(), initTranslations() and the gettext wrappers are
now methods of the common base, while openPreferences() moves
to the Extension class.
Based on an original suggestion from Evan Welsh.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2838>
Extensions often need to set up additional resources from their
directory, like settings, translations or image assets.
So far extensions have used getCurrentExtension() to access the
shell's internal extension object which contains path and dir
properties. That's far from ideal, first because it requires
generating a stack to figure out the current extension, and
second because the internal object also contains state that
extensions shouldn't meddle with.
Just include those properties in the metadata we pass to the
extension constructor.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2838>
Use the new privacy indicator class for the input one and move it next
to the other privacy indicators.
While on it move all privacy indicators to the front, following the
system-status-indicators mockup.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2840>
We unified most code paths earlier, but the common code will still
import Main locally if no extension manager was injected before.
Now that the old extensionUtils was split between extension and
preferences, each of those modules can simply import the manager
from its corresponding environment, and then inject it into the
shared module.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2837>
For the time being this mostly means re-exporting functions
from the shared module. However openPrefs() is now only
available to extensions, and we stop exporting both
getCurrentExtension() and setExtensionManager() to either
extensions or prefs.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2837>
We got rid of all uses of extension utils code in the gnome-shell
process itself, and everything that is now using it - including
extensions - is already loaded as module.
We can therefore quickly move the file to ESM, which will help
a bit with upcoming changes.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2837>
ExtensionUtils was originally used for shared functions between
the extension system and the (old) prefs-tool, but then gained
useful API meant for extensions themselves.
It's a bit weird to mix the two, so split out the extension convenience
API into a separate module.
We will soon split up the module further, and add specific "flavors"
for extensions and preferences, with the current code providing a
shared base for both.
That should explain both the new location and the odd module name. :-)
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2837>
Now that we always have an extension manager object, we can use
the same code path for use from extensions and prefs.
For that, inject the D-Bus service's extensionManager instead
of the current extension.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2832>
ExtensionUtils' getCurrentExtension() method currently either
returns the extension that was injected with setCurrentExtension(),
or imports Main locally to access the extensionManager.
But local imports won't work anymore when we convert to ESM,
and setCurrentExtension() is only an option for prefs.
Instead of diverging the code paths even further, we'll unify
the two cases as much as possible.
As a first step, add a basic extension manager in the Extensions
D-Bus service that exposes the same lookup() API as the "real"
extension manager.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2832>
When looking for a directory name that matches the extension UUID,
we can just as well use GLib's dirname()/basename() functions
instead of wrapping the path in a GFile.
We also know that the original path corresponds to a regular file
and not a directory, so rearrange the loop to avoid a lookup that
is guaranteed to fail.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2832>
We currently use a regular expression to extract the exact file path
from a stack line. That RE is no longer accurate:
- we assume a line number at the end, but at one point the column
number was added as well
- stacks from ES modules use file:// URIs instead of plain paths
Luckily that doesn't matter: We don't want to access any actual
files, so all we need is a path that can be traversed and that
contains the UUID.
We can get that with simple string manipulation, so avoid the regex
overhead.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2832>
gi modules are always loaded (there is no API for "set version without
loading"), so
we need to break dependencies.js into three sections:
- Required
- Compile-time optional
- Runtime optional
Required dependencies are always imported, compile-time optional
dependencies
are loaded if gnome-shell is compiled with support for them, and for
runtime optional dependencies we catch any errors when attempting to
load them.
If runtime optional dependencies fail to load we log a debug-level
message.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2822>
Removes the init() function in favor of executing all environment
changes when the file is imported.
Additionally ports all unit tests using imports.gi.environment.init() to
use the updated module.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2822>
We started to version them last cycle, so docs can be differentiated
between versions. It is not *expected* that two versions show up
on the same system, but then it also doesn't hurt handling it.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2822>
Once environment.js is an ES module we need to ensure we can dynamically
specify the version for required GI dependencies such as Clutter.
Moving dependency version setup to dependencies.js ensures gi.require
calls are done before environment.js imports any utilities.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2822>
The environment module is used to initialize the environment, yet it
currently also defines the adjustAnimationTime() function.
Ideally it should not export any utility functions, in particular
once converted to ESM.
The function cannot be moved to the existing Utils module, as that
depends on an initialized environment, and can therefore not be
imported from environment.js, so use that opportunity to group
together several animation helpers in a new animationUtils module.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2822>
This allows using await in the command (or the header we
add to it), for example when handling Promises or importing
a module dynamically.
The latter will be crucial when porting to ESM.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2842>
Part of the possible completions involves evaluating the part
of the passed in text that looks like an object, so that we
can query it for properties.
Using a Function or eval() for that means that we can only
complete text that does not use `await`. To get over that
limitation, evaluate the text in an AsyncFunction instead.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2842>
We currently throw an error when encountering a result that cannot
be represented as string, with the prompt appearing somewhat stuck
(the input cannot be committed).
Showing a lame fallback instead at least avoids that issue. When
the object has a typeof 'object' but is not an instanceof Object,
we are likely dealing with an ES module, and can show a slightly
less lame fallback.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2842>
console.log() is implemented with structured logging, and as we
set an appropriate log domain, it's identical to the custom function
bar the custom fields with extension data.
Few people know about those custom fields, and adding them comes
at a cost, as we end up producing and parsing a stacktrace on
every log() call.
It therefore seems appropriate to drop the custom function, and
turn the global log() symbol into a simple convenience alias for
console.log().
If it turns out that people do miss the custom fields, we can add
an alternative to ExtensionUtils.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2830>
`toLocaleFormat` is now `formatDateWithCFormatString` and formatTime and
formatTimeSpan are moved into dateUtils.
Instead of overriding system.clearDateCaches, add a helper in dateUtils.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2827>
Now that scripts are loaded as external modules, there's no reason
anymore for bundling them with the gnome-shell executable. Just
move the scripts into a dedicated folder in tests/ and run them
from there.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2812>
Environment variables aren't the best option to pass parameters
to a process (wouldn't it be "fun" if SHELL_PERF_MODULE appeared
in a regular user session?).
Instead, use a (hidden) --automation-script command line flag to
specify a script file that should be used to drive an automated
session.
As a side effect, the script no longer has to be relative to the
main module itself, so it will be possible to run scripts that
aren't bundled with the shell sources.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2812>
The perf scripts that can be used to script the gnome-shell UI
for testing are sufficiently separate from the rest of the code
base to allow porting them to ESM modules before the rest of
the code base.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2812>
The file indicates to the systemd shutdown scripts that extensions
should be disabled, so that extensions that crash the shell on
startup cannot lock out the user indefinitely.
For that purpose, we create the file before initializing extensions,
and remove it after 60 seconds. That generally works, because it's
highly unlikely that a session genuinely ends within the first minute.
It's possible though (for example during developments or when running
tests), so also remove the file when shutting down cleanly before
the timeout.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2807>
Now that extensions themselves are imported as modules, do the
same for their preference dialogs.
Extensions must now export a class with a `fillPreferencesWindow()`
method as default.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2795>
Continue the move to ESM by loading modules dynamically with
the standard import() expression, rather than by installing a
custom (legacy) importer.
This is a breaking change that affects all extensions, as they
now need to explicitly export the expected symbols.
As we are already breaking all extensions, take that opportunity
and remove support for the individual entry points: Using a
class with enable()/disable() methods has been the recommended
pattern for a long time, it is now the only entry point.
Instead of instantiating the class from an `init()` function,
the class must now be exported as default to be recognized.
Additionally, we no longer install an importer on the extension
object, so extensions that consist of more than one file MUST
import those files as modules now.
There will be a second breaking change for extensions when
gnome-shell's own code is ported to ESM, so most extension
developers will likely want to wait until the port is complete
before starting to port their extensions.
Based on a commit from Evan Welsh.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2795>
We want to replace gjs' custom (and now legacy) imports system
with standard EcmaScript modules: JS developers are already
familiar with them, they have better tooling support and using
standard features over non-standard ones is generally the right
thing to do.
Our D-Bus services are separate from the main process, and thus
can be ported separately (except for the few imports that are
shared with the main process' code base).
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2786>
- spin out all the panel button styling into a drawing mixin
- clean up the styles generally
- make special cases for the clock and non-flat buttons
- contrast fixes for non-flat buttons, fixes#6768
- new stop icon for the screen recording/cast indicators
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2804>
We currently special-case the DISABLED error when initializing
filtering, but not on app filter changes.
While it seems reasonable that Malcontent.Manager wouldn't emit
the signal while disabled, that's not actually true: It is emitted
when any user account information tracked by AccountsServices
changes.
Even if the signal were limited to changes of the ParentalControls
extension, it would still get emitted when app filtering *becomes*
disabled.
So regardless of potential improvements in libmalcontent itself,
we should filter out the DISABLED consistently, both when creating
the initial filter and when updating it.
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6749
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2796>
Commit c449058d44 changed the pointer clone to use a single
actor. However that broke applying the hotspot translation to the
position, so the magnified cursor is now displayed with a shift.
Undo the change to restore the old behavior.
This reverts commit c449058d44.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2780>
gjs now has an internal mainloop that it can spin to resolve
module imports. That loop uses the thread default context,
so its possible that other sources, namely from mutter, get
dispatched when iterating the context. If that happens before
mutter is properly initialized, this will lead to a crash.
GjsContext needs to iterate its internal mainloop when initializing
to resolve internal modules, to avoid iterating Meta's mainloop and
triggering events before Meta is ready we will initialize the Shell
global and thus the GjsContext (js_context) before Meta.
Once GjsContext is initialized, we can call meta_context_setup().
Once Meta is setup and started, we'll run init.js which uses GJS'
internal promises API to set a "mainloop hook". The mainloop hook
is run immediately after the module returns so GJS will not attempt
to iterate the main loop again before exiting.
Also adjust the 'headlessStart' test to not wait for the
MetaContext::started signal, as that signal has now already
been emitted when the code is executed.
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6691
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2781>