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>
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>
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>
Showing multiple preference dialogs at the same time (for instance
by repeated `gnome-extensions prefs` calls) may or may not work as
expected, depending on whether any of the dialogs is modal or not
(read: opened via the Extensions app).
The easiest way to address this is to disallow more than a single
dialog at the time. It's arguably also the more predictable behavior,
and means extensions don't have to deal with inconsistent state
caused by multiple dialogs.
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4564
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2013>
GTK4 relies entirely on refcounting for cleanup (that is,
there is no longer a destroy() method that forces a dispose
run regardless of the refcount).
Unfortunately that makes cleanup harder in (some) language
bindings, where an object may be kept alive implicitly by
closures etc.
Address this by releasing the hold count when the window
is closed rather than when it is destroyed.
This isn't the most elegant, but it ensure that the service
doesn't get stuck if an extension doesn't carefully clean
up everything in its prefs widget.
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4564
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2013>
This was forgotten when porting to GTK 4, leading to the following error
when user tries to copy the error message produced by an extension:
JS ERROR: TypeError: Gtk.Clipboard is undefined
_initActions/<@resource:///org/gnome/Shell/Extensions/js/extensionsService.js:255:31
run@resource:///org/gnome/Shell/Extensions/js/dbusService.js:177:20
main@resource:///org/gnome/Shell/Extensions/js/main.js:19:13
run@resource:///org/gnome/gjs/modules/script/package.js:206:19
start@resource:///org/gnome/gjs/modules/script/package.js:190:8
@/nix/store/fwnkwvhwm3kqck4fhkc5y5z853radggg-gnome-shell-40.0/share/gnome-shell/.org.gnome.Shell.Extensions-wrapped:7:17
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1795>
Between the GTK4 port and the latest GTK4 version, calling realize()
on a newly created window to force its surface to be created stopped
working.
So instead, wait for the window to get realized regularly to set its
parent.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1574>
With the previous preparations in place, it is time to take the plunge.
As both the app and the portal use the same small library for handling
external windows, port everything at once to avoid the hassle of building
and installing two versions of the library.
With the portal using GTK4 now, all extensions must port their preference
widgets as well.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1495>
We currently use separate frames for the details expander and the
expanded details. That layout works as long as frames are boxy (as
in the default GTK3 style), but breaks down with rounded corners
(as in the default GTK4 style).
In order to work with either style, adapt the layout to use a single
surrounding frame and appropriate borders as separator.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1495>
GTK4 will remove the GtkHeaderBar:title property, so stop using it
and set the window's title property instead, as that's what headbars
use in both GTK3 and GTK4 unless explicitly overridden.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1495>
As outlined earlier, in order to turn the Extensions app into a properly
sandboxed application, we need to split out the extension prefs dialog
and move it elsewhere.
With "elsewhere" being the new Extensions D-Bus service, effectively
turning it into a shell extensions portal.
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1106
Similar to the previously added org.freedesktop.Notifications proxy,
this exposes the org.gnome.Shell.Extensions API and forwards any
request to the real implementation in gnome-shell.
The motivation differs though: We want to be able to package the
extension app as flatpak and distribute it separately, but the
extension prefs dialog is hard to impossible to sandbox:
- filenames need translating between host and sandbox, and we
can only do that in some cases (serializing/deserializing
extensions), but not others (extension settings that refer
to files)
- system extensions install their GSettings schemas in the system
path; the best we can do there is assume a host prefix of /usr
and set GSETTINGS_SCHEMA_DIR in the flatpak (eeks)
- extensions may rely on additional typelibs that are present on
the host (for example because gnome-shell itself depends on
them), but not inside the sandbox - unless we bundle all of
gnome-shell's dependencies
- if gjs/mozjs differ between host and sandbox, extensions must
handle different runtimes for the extension and its prefs
And all those issues occur despite a very permissive sandbox (full
host filesystem access, full dconf access, full org.gnome.Shell
access (including Eval()!)).
This new service will give us an alternative place for handling
the preference dialog:
- it runs outside of gnome-shell process, so can open windows
- it runs on the host, so the extension's prefs get to run
in the same namespace as the extension itself
That is, the service will provide portal-like functionality (albeit
not using the org.freedesktop.portal.* namespace, as extension
management is an inherently privileged operation).
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1106