From a78342b1826a7961bb36260cbd91e9a484f25165 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Wed, 20 Nov 2024 13:15:39 +0000 Subject: [PATCH] import RHEL 10 Beta gnome-shell-47~alpha-4.el10 --- .gitignore | 2 +- .gnome-shell.metadata | 1 - ...-to-window-title-instead-of-WM_CLASS.patch | 8 +- 0001-data-Update-generated-stylesheets.patch | 56 + ...der-Refuse-to-override-system-extens.patch | 37 + ...Work-around-failing-fingerprint-auth.patch | 67 + ...n-Dump-stack-on-segfaults-by-default.patch | 12 +- ...el-Use-branding-in-activities-button.patch | 51 + ...eld-unblank-when-inserting-smartcard.patch | 33 + ...001-st-texture-cache-purge-on-resume.patch | 22 +- 0001-theme-Welcome-Illustration.patch | 1099 +++++ ...-back-workspaces-submenu-for-static-.patch | 8 +- ...-not-change-Wacom-LEDs-through-g-s-d.patch | 25 - ...0001-a11y-Change-HC-icon-theme-first.patch | 58 - ...intentional-loop-while-polkit-dialog.patch | 40 - ...pDisplay-Show-full-app-name-on-hover.patch | 111 - ...und-refresh-after-suspend-on-wayland.patch | 29 - ...ll-process-working.svg-to-filesystem.patch | 37 - ...educe-calls-to-g_time_zone_new_local.patch | 65 - ...Handle-added-or-removed-sessionMode-.patch | 87 - ...ns-Add-a-SESSION_MODE-extension-type.patch | 42 - SOURCES/0001-gdm-add-AuthList-control.patch | 237 - ...able-keyboard-if-ClutterDeviceManage.patch | 39 - ...t-Initialize-regions-unconditionally.patch | 51 - ...-layout-Make-the-hot-corner-optional.patch | 56 - ...t-auth-prompt-on-vt-switch-before-fa.patch | 49 - ...oginDialog-make-info-messages-themed.patch | 32 - ...ight-prevFocus-actor-after-the-focus.patch | 49 - ...orkAgent-add-support-for-SAE-secrets.patch | 29 - ...e-overview-on-session-mode-hasOvervi.patch | 38 - ...ry-action-labels-after-mode-switches.patch | 80 - ...-add-an-icon-to-the-ActivitiesButton.patch | 54 - ...andle-keypress-if-numlock-is-enabled.patch | 36 - ...eld-unblank-when-inserting-smartcard.patch | 33 - ...recording-when-screen-size-or-resour.patch | 253 -- ...-workspace-from-startup-notification.patch | 78 - ...ll-recorder-Restore-cursor-recording.patch | 28 - ...DBus-method-to-load-a-single-extensi.patch | 66 - ...mine-if-password-entry-from-content-.patch | 91 - ...lEntry-Disconnect-handler-on-destroy.patch | 36 - ...st_bin_set_child-with-already-parent.patch | 59 - ...-Cancel-pending-requests-on-icon-the.patch | 94 - ...status-volume-Hide-sliders-initially.patch | 30 - ...01-theme-Update-window-preview-style.patch | 76 - SOURCES/0001-windowMenu-Ignore-release.patch | 26 - ...1-workspace-Pass-device-to-startDrag.patch | 31 - ...ork-around-spurious-allocation-chang.patch | 37 - ...ld-background-not-just-animation-on-.patch | 31 - ...0002-environment-Fix-date-conversion.patch | 33 - ...Get-rid-of-_enabled-boolean-optimiza.patch | 237 - ...upport-for-GDM-s-ChoiceList-PAM-exte.patch | 267 -- ...password-menu-item-text-when-it-s-cr.patch | 92 - ...Allow-extensions-to-run-on-the-login.patch | 393 -- ...ystem-Monitor-for-icon-theme-changes.patch | 152 - ...e-password-item-from-dedication-func.patch | 119 - ...sh-background-on-gl-video-memory-pur.patch | 115 - ...nc-to-worker-thread-when-saving-stat.patch | 124 - ...w-extensions-at-the-login-and-unlock.patch | 116 - ...rt-lockdown-of-Show-Text-menu-in-pas.patch | 116 - ...d-ShellAppCache-for-GAppInfo-caching.patch | 674 --- ...y-Only-mask-text-in-password-entries.patch | 36 - ...-Always-use-AppSystem-to-lookup-apps.patch | 66 - .../allow-timed-login-with-no-user-list.patch | 159 - SOURCES/caps-lock-warning.patch | 488 --- ...defend-against-corrupt-notifications.patch | 145 - SOURCES/extension-updates.patch | 3810 ----------------- SOURCES/fix-app-view-leaks.patch | 421 -- SOURCES/fix-double-disposed-backgrounds.patch | 101 - SOURCES/fix-invalid-access-warnings.patch | 224 - SOURCES/fix-login-lock-screen.patch | 161 - SOURCES/fix-nm-device-settings.patch | 131 - SOURCES/fix-some-js-warnings.patch | 223 - SOURCES/gdm-networking.patch | 246 -- SOURCES/gnome-shell-favourite-apps-yelp.patch | 26 - SOURCES/horizontal-workspace-support.patch | 399 -- SOURCES/introspect-backports.patch | 643 --- .../more-spurious-allocation-warnings.patch | 176 - SOURCES/osk-fixes.patch | 117 - SOURCES/owe-support.patch | 107 - SOURCES/perf-tool-wayland.patch | 399 -- SOURCES/root-warning.patch | 71 - SOURCES/wake-up-on-deactivate.patch | 79 - SOURCES/warn-less.patch | 279 -- ... disable-unlock-entry-until-question.patch | 135 +- ...patch => enforce-smartcard-at-unlock.patch | 65 +- fix-some-js-warnings.patch | 62 + ...-enabled-extensions-background-logos.patch | 29 + ...> gnome-shell-favourite-apps-firefox.patch | 22 +- ... gnome-shell-favourite-apps-terminal.patch | 12 +- SPECS/gnome-shell.spec => gnome-shell.spec | 1238 ++++-- ...portal-notify.patch => portal-notify.patch | 349 +- sources | 1 + 92 files changed, 2570 insertions(+), 13897 deletions(-) delete mode 100644 .gnome-shell.metadata rename SOURCES/0001-app-Fall-back-to-window-title-instead-of-WM_CLASS.patch => 0001-app-Fall-back-to-window-title-instead-of-WM_CLASS.patch (81%) create mode 100644 0001-data-Update-generated-stylesheets.patch create mode 100644 0001-extensionDownloader-Refuse-to-override-system-extens.patch create mode 100644 0001-gdm-Work-around-failing-fingerprint-auth.patch rename SOURCES/0001-main-Dump-stack-on-segfaults-by-default.patch => 0001-main-Dump-stack-on-segfaults-by-default.patch (79%) create mode 100644 0001-panel-Use-branding-in-activities-button.patch create mode 100644 0001-screenShield-unblank-when-inserting-smartcard.patch rename SOURCES/0003-st-texture-cache-purge-on-resume.patch => 0001-st-texture-cache-purge-on-resume.patch (77%) create mode 100644 0001-theme-Welcome-Illustration.patch rename SOURCES/0001-windowMenu-Bring-back-workspaces-submenu-for-static-.patch => 0001-windowMenu-Bring-back-workspaces-submenu-for-static-.patch (90%) delete mode 100644 SOURCES/0001-Do-not-change-Wacom-LEDs-through-g-s-d.patch delete mode 100644 SOURCES/0001-a11y-Change-HC-icon-theme-first.patch delete mode 100644 SOURCES/0001-animation-fix-unintentional-loop-while-polkit-dialog.patch delete mode 100644 SOURCES/0001-appDisplay-Show-full-app-name-on-hover.patch delete mode 100644 SOURCES/0001-background-refresh-after-suspend-on-wayland.patch delete mode 100644 SOURCES/0001-data-install-process-working.svg-to-filesystem.patch delete mode 100644 SOURCES/0001-environment-reduce-calls-to-g_time_zone_new_local.patch delete mode 100644 SOURCES/0001-extensionSystem-Handle-added-or-removed-sessionMode-.patch delete mode 100644 SOURCES/0001-extensions-Add-a-SESSION_MODE-extension-type.patch delete mode 100644 SOURCES/0001-gdm-add-AuthList-control.patch delete mode 100644 SOURCES/0001-keyboard-Only-enable-keyboard-if-ClutterDeviceManage.patch delete mode 100644 SOURCES/0001-layout-Initialize-regions-unconditionally.patch delete mode 100644 SOURCES/0001-layout-Make-the-hot-corner-optional.patch delete mode 100644 SOURCES/0001-loginDialog-Reset-auth-prompt-on-vt-switch-before-fa.patch delete mode 100644 SOURCES/0001-loginDialog-make-info-messages-themed.patch delete mode 100644 SOURCES/0001-main-Unset-the-right-prevFocus-actor-after-the-focus.patch delete mode 100644 SOURCES/0001-networkAgent-add-support-for-SAE-secrets.patch delete mode 100644 SOURCES/0001-overview-Hide-the-overview-on-session-mode-hasOvervi.patch delete mode 100644 SOURCES/0001-padOsd-Re-query-action-labels-after-mode-switches.patch delete mode 100644 SOURCES/0001-panel-add-an-icon-to-the-ActivitiesButton.patch delete mode 100644 SOURCES/0001-popupMenu-Handle-keypress-if-numlock-is-enabled.patch delete mode 100644 SOURCES/0001-screenShield-unblank-when-inserting-smartcard.patch delete mode 100644 SOURCES/0001-screencast-Stop-recording-when-screen-size-or-resour.patch delete mode 100644 SOURCES/0001-shell-app-Handle-workspace-from-startup-notification.patch delete mode 100644 SOURCES/0001-shell-recorder-Restore-cursor-recording.patch delete mode 100644 SOURCES/0001-shellDBus-Add-a-DBus-method-to-load-a-single-extensi.patch delete mode 100644 SOURCES/0001-shellEntry-Determine-if-password-entry-from-content-.patch delete mode 100644 SOURCES/0001-shellEntry-Disconnect-handler-on-destroy.patch delete mode 100644 SOURCES/0001-st-bin-Disallow-st_bin_set_child-with-already-parent.patch delete mode 100644 SOURCES/0001-st-texture-cache-Cancel-pending-requests-on-icon-the.patch delete mode 100644 SOURCES/0001-status-volume-Hide-sliders-initially.patch delete mode 100644 SOURCES/0001-theme-Update-window-preview-style.patch delete mode 100644 SOURCES/0001-windowMenu-Ignore-release.patch delete mode 100644 SOURCES/0001-workspace-Pass-device-to-startDrag.patch delete mode 100644 SOURCES/0001-workspacesView-Work-around-spurious-allocation-chang.patch delete mode 100644 SOURCES/0002-background-rebuild-background-not-just-animation-on-.patch delete mode 100644 SOURCES/0002-environment-Fix-date-conversion.patch delete mode 100644 SOURCES/0002-extensionSystem-Get-rid-of-_enabled-boolean-optimiza.patch delete mode 100644 SOURCES/0002-gdmUtil-enable-support-for-GDM-s-ChoiceList-PAM-exte.patch delete mode 100644 SOURCES/0002-shellEntry-Give-password-menu-item-text-when-it-s-cr.patch delete mode 100644 SOURCES/0003-extensionSystem-Allow-extensions-to-run-on-the-login.patch delete mode 100644 SOURCES/0003-shell-app-system-Monitor-for-icon-theme-changes.patch delete mode 100644 SOURCES/0003-shellEntry-Handle-password-item-from-dedication-func.patch delete mode 100644 SOURCES/0004-background-refresh-background-on-gl-video-memory-pur.patch delete mode 100644 SOURCES/0004-global-force-fsync-to-worker-thread-when-saving-stat.patch delete mode 100644 SOURCES/0004-sessionMode-Allow-extensions-at-the-login-and-unlock.patch delete mode 100644 SOURCES/0004-shellEntry-Support-lockdown-of-Show-Text-menu-in-pas.patch delete mode 100644 SOURCES/0005-app-cache-add-ShellAppCache-for-GAppInfo-caching.patch delete mode 100644 SOURCES/0005-shellEntry-Only-mask-text-in-password-entries.patch delete mode 100644 SOURCES/0006-js-Always-use-AppSystem-to-lookup-apps.patch delete mode 100644 SOURCES/allow-timed-login-with-no-user-list.patch delete mode 100644 SOURCES/caps-lock-warning.patch delete mode 100644 SOURCES/defend-against-corrupt-notifications.patch delete mode 100644 SOURCES/extension-updates.patch delete mode 100644 SOURCES/fix-app-view-leaks.patch delete mode 100644 SOURCES/fix-double-disposed-backgrounds.patch delete mode 100644 SOURCES/fix-invalid-access-warnings.patch delete mode 100644 SOURCES/fix-login-lock-screen.patch delete mode 100644 SOURCES/fix-nm-device-settings.patch delete mode 100644 SOURCES/fix-some-js-warnings.patch delete mode 100644 SOURCES/gdm-networking.patch delete mode 100644 SOURCES/gnome-shell-favourite-apps-yelp.patch delete mode 100644 SOURCES/horizontal-workspace-support.patch delete mode 100644 SOURCES/introspect-backports.patch delete mode 100644 SOURCES/more-spurious-allocation-warnings.patch delete mode 100644 SOURCES/osk-fixes.patch delete mode 100644 SOURCES/owe-support.patch delete mode 100644 SOURCES/perf-tool-wayland.patch delete mode 100644 SOURCES/root-warning.patch delete mode 100644 SOURCES/wake-up-on-deactivate.patch delete mode 100644 SOURCES/warn-less.patch rename SOURCES/disable-unlock-entry-until-question.patch => disable-unlock-entry-until-question.patch (50%) rename SOURCES/enforce-smartcard-at-unlock.patch => enforce-smartcard-at-unlock.patch (54%) create mode 100644 fix-some-js-warnings.patch create mode 100644 gnome-shell-enabled-extensions-background-logos.patch rename SOURCES/gnome-shell-favourite-apps-firefox.patch => gnome-shell-favourite-apps-firefox.patch (58%) rename SOURCES/gnome-shell-favourite-apps-terminal.patch => gnome-shell-favourite-apps-terminal.patch (53%) rename SPECS/gnome-shell.spec => gnome-shell.spec (54%) rename SOURCES/portal-notify.patch => portal-notify.patch (54%) create mode 100644 sources diff --git a/.gitignore b/.gitignore index e984bcc..6f214a1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/gnome-shell-3.32.2.tar.xz +gnome-shell-47.alpha.tar.xz diff --git a/.gnome-shell.metadata b/.gnome-shell.metadata deleted file mode 100644 index 06e249f..0000000 --- a/.gnome-shell.metadata +++ /dev/null @@ -1 +0,0 @@ -331e9cf71cd1d2a4e9238d87d216da4c6f3a400e SOURCES/gnome-shell-3.32.2.tar.xz diff --git a/SOURCES/0001-app-Fall-back-to-window-title-instead-of-WM_CLASS.patch b/0001-app-Fall-back-to-window-title-instead-of-WM_CLASS.patch similarity index 81% rename from SOURCES/0001-app-Fall-back-to-window-title-instead-of-WM_CLASS.patch rename to 0001-app-Fall-back-to-window-title-instead-of-WM_CLASS.patch index 77f7cb1..cdee8c9 100644 --- a/SOURCES/0001-app-Fall-back-to-window-title-instead-of-WM_CLASS.patch +++ b/0001-app-Fall-back-to-window-title-instead-of-WM_CLASS.patch @@ -1,4 +1,4 @@ -From 23755cc20f3c05b97f769e27553f2ab482d60137 Mon Sep 17 00:00:00 2001 +From 55c1dfed04084e9dbaf034263172bc745f905718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Wed, 20 May 2015 16:44:00 +0200 Subject: [PATCH] app: Fall back to window title instead of WM_CLASS @@ -11,10 +11,10 @@ a .desktop file ... 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shell-app.c b/src/shell-app.c -index 10efa9135..7d40186c9 100644 +index 04d0ab508b..4a55daf809 100644 --- a/src/shell-app.c +++ b/src/shell-app.c -@@ -259,7 +259,7 @@ shell_app_get_name (ShellApp *app) +@@ -247,7 +247,7 @@ shell_app_get_name (ShellApp *app) const char *name = NULL; if (window) @@ -24,5 +24,5 @@ index 10efa9135..7d40186c9 100644 name = C_("program", "Unknown"); return name; -- -2.21.0 +2.45.2 diff --git a/0001-data-Update-generated-stylesheets.patch b/0001-data-Update-generated-stylesheets.patch new file mode 100644 index 0000000..69c870f --- /dev/null +++ b/0001-data-Update-generated-stylesheets.patch @@ -0,0 +1,56 @@ +From 170ccbd3d237bf980f46ae87e3da8238df9f8a3c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 16 Apr 2024 20:49:40 +0200 +Subject: [PATCH] data: Update generated stylesheets + +--- + data/theme/gnome-shell-dark.css | 3 +++ + data/theme/gnome-shell-high-contrast.css | 3 +++ + data/theme/gnome-shell-light.css | 3 +++ + 3 files changed, 9 insertions(+) + +diff --git a/data/theme/gnome-shell-dark.css b/data/theme/gnome-shell-dark.css +index 339adf7e7b..5dd7d29a3a 100644 +--- a/data/theme/gnome-shell-dark.css ++++ b/data/theme/gnome-shell-dark.css +@@ -1720,6 +1720,9 @@ StScrollBar { + min-width: 0.5455em; + min-height: 0.5455em; + background-color: #ffffff; } ++ #panel .panel-button#panelActivities .activities-logo { ++ icon-size: 1.36375em; ++ padding: 0 6px; } + #panel .panel-button.screen-recording-indicator StBoxLayout, #panel .panel-button.screen-sharing-indicator StBoxLayout { + spacing: 0.409em; } + #panel .panel-button.screen-recording-indicator StIcon, #panel .panel-button.screen-sharing-indicator StIcon { +diff --git a/data/theme/gnome-shell-high-contrast.css b/data/theme/gnome-shell-high-contrast.css +index 4bb622aa26..8f94fa4101 100644 +--- a/data/theme/gnome-shell-high-contrast.css ++++ b/data/theme/gnome-shell-high-contrast.css +@@ -1897,6 +1897,9 @@ StScrollBar { + min-width: 0.5455em; + min-height: 0.5455em; + background-color: #ffffff; } ++ #panel .panel-button#panelActivities .activities-logo { ++ icon-size: 1.36375em; ++ padding: 0 6px; } + #panel .panel-button.screen-recording-indicator StBoxLayout, #panel .panel-button.screen-sharing-indicator StBoxLayout { + spacing: 0.409em; } + #panel .panel-button.screen-recording-indicator StIcon, #panel .panel-button.screen-sharing-indicator StIcon { +diff --git a/data/theme/gnome-shell-light.css b/data/theme/gnome-shell-light.css +index 82a5b0bc18..128aa93dea 100644 +--- a/data/theme/gnome-shell-light.css ++++ b/data/theme/gnome-shell-light.css +@@ -1720,6 +1720,9 @@ StScrollBar { + min-width: 0.5455em; + min-height: 0.5455em; + background-color: #282828; } ++ #panel .panel-button#panelActivities .activities-logo { ++ icon-size: 1.36375em; ++ padding: 0 6px; } + #panel .panel-button.screen-recording-indicator StBoxLayout, #panel .panel-button.screen-sharing-indicator StBoxLayout { + spacing: 0.409em; } + #panel .panel-button.screen-recording-indicator StIcon, #panel .panel-button.screen-sharing-indicator StIcon { +-- +2.45.2 + diff --git a/0001-extensionDownloader-Refuse-to-override-system-extens.patch b/0001-extensionDownloader-Refuse-to-override-system-extens.patch new file mode 100644 index 0000000..ae5a764 --- /dev/null +++ b/0001-extensionDownloader-Refuse-to-override-system-extens.patch @@ -0,0 +1,37 @@ +From 7e82f0a73a1d1576e94b17e21d07fd3978ba7c33 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Mon, 1 Feb 2021 18:26:00 +0100 +Subject: [PATCH] extensionDownloader: Refuse to override system extensions + +The website allows to "update" system extensions by installing the +upstream version into the user's home directory. + +Prevent that by refusing to download and install extensions that are +already installed system-wide. +--- + js/ui/extensionDownloader.js | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js +index 0366c5dfa8..5b27543aa6 100644 +--- a/js/ui/extensionDownloader.js ++++ b/js/ui/extensionDownloader.js +@@ -39,6 +39,15 @@ export async function installExtension(uuid, invocation) { + return; + } + ++ const oldExt = Main.extensionManager.lookup(uuid); ++ if (oldExt && oldExt.type === ExtensionUtils.ExtensionType.SYSTEM) { ++ log('extensionDownloader: Trying to replace system extension %s'.format(uuid)); ++ invocation.return_error_literal( ++ ExtensionErrors, ExtensionError.NOT_ALLOWED, ++ 'System extensions cannot be replaced'); ++ return; ++ } ++ + const params = { + uuid, + shell_version: Config.PACKAGE_VERSION, +-- +2.45.2 + diff --git a/0001-gdm-Work-around-failing-fingerprint-auth.patch b/0001-gdm-Work-around-failing-fingerprint-auth.patch new file mode 100644 index 0000000..2baa7b6 --- /dev/null +++ b/0001-gdm-Work-around-failing-fingerprint-auth.patch @@ -0,0 +1,67 @@ +From ff73f820b1398e5d60b8984b0003db46ad70b8ec Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 28 Apr 2021 16:50:03 +0200 +Subject: [PATCH] gdm: Work around failing fingerprint auth + +On Fedora we have the problem that fingerprint auth fails immediately if +the PAM configuration has not been updated and no prints are enrolled. + +So, consider a verification failure within one second to be a service +failure instead. +--- + js/gdm/util.js | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/js/gdm/util.js b/js/gdm/util.js +index 97df6d687e..371953cb25 100644 +--- a/js/gdm/util.js ++++ b/js/gdm/util.js +@@ -109,6 +109,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { + this._defaultService = null; + this._preemptingService = null; + this._fingerprintReaderType = FingerprintReaderType.NONE; ++ this._fprintStartTime = -1; + + this._messageQueue = []; + this._messageQueueTimeoutId = 0; +@@ -669,6 +670,10 @@ export class ShellUserVerifier extends Signals.EventEmitter { + this._hold.acquire(); + try { + this._activeServices.add(serviceName); ++ ++ if (serviceName == FINGERPRINT_SERVICE_NAME) ++ this._fprintStartTime = GLib.get_monotonic_time(); ++ + if (this._userName) { + await this._userVerifier.call_begin_verification_for_user( + serviceName, this._userName, this._cancellable); +@@ -763,6 +768,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { + const cancellable = this._cancellable; + this._fingerprintFailedId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, + FINGERPRINT_ERROR_TIMEOUT_WAIT, () => { ++ log("Generating _verificationFailed!"); + this._fingerprintFailedId = 0; + if (!cancellable.is_cancelled()) + this._verificationFailed(serviceName, false); +@@ -829,6 +835,18 @@ export class ShellUserVerifier extends Signals.EventEmitter { + if (serviceName === FINGERPRINT_SERVICE_NAME) { + if (this._fingerprintFailedId) + GLib.source_remove(this._fingerprintFailedId); ++ ++ // On Fedora we have the problem that fingerprint auth fails ++ // immediately if the PAM configuration has not been updated and no ++ // prints are enrolled. ++ // So, consider a verification failure within one second to be a service ++ // failure instead. ++ if (this._fprintStartTime > GLib.get_monotonic_time() - GLib.USEC_PER_SEC) { ++ log("Fingerprint service failed almost immediately, considering it unavailable."); ++ log("Please fix your configuration by running: authselect select --force sssd with-fingerprint with-silent-lastlog"); ++ this._onServiceUnavailable(this._client, serviceName, null); ++ return; ++ } + } + + // For Not Listed / enterprise logins, immediately reset +-- +2.43.2 + diff --git a/SOURCES/0001-main-Dump-stack-on-segfaults-by-default.patch b/0001-main-Dump-stack-on-segfaults-by-default.patch similarity index 79% rename from SOURCES/0001-main-Dump-stack-on-segfaults-by-default.patch rename to 0001-main-Dump-stack-on-segfaults-by-default.patch index 75b9b1a..a18c992 100644 --- a/SOURCES/0001-main-Dump-stack-on-segfaults-by-default.patch +++ b/0001-main-Dump-stack-on-segfaults-by-default.patch @@ -1,4 +1,4 @@ -From ba3ce64fbbce20192a55f9d438d1032c0bac0557 Mon Sep 17 00:00:00 2001 +From 2060b040f91c3751861a1c1b985c5fe8cc891d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Thu, 29 Oct 2020 18:21:06 +0100 Subject: [PATCH] main: Dump stack on segfaults by default @@ -8,10 +8,10 @@ Subject: [PATCH] main: Dump stack on segfaults by default 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main.c b/src/main.c -index 245837783..788309de7 100644 +index 4be47258eb..b324b6b96a 100644 --- a/src/main.c +++ b/src/main.c -@@ -39,6 +39,7 @@ static int caught_signal = 0; +@@ -47,6 +47,7 @@ static char *script_path = NULL; #define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1 #define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4 @@ -19,7 +19,7 @@ index 245837783..788309de7 100644 enum { SHELL_DEBUG_BACKTRACE_WARNINGS = 1, SHELL_DEBUG_BACKTRACE_SEGFAULTS = 2, -@@ -268,8 +269,11 @@ shell_init_debug (const char *debug_env) +@@ -381,8 +382,11 @@ shell_init_debug (const char *debug_env) { "backtrace-segfaults", SHELL_DEBUG_BACKTRACE_SEGFAULTS }, }; @@ -32,7 +32,7 @@ index 245837783..788309de7 100644 + _shell_debug = DEFAULT_SHELL_DEBUG; } - static void + static GLogWriterOutput -- -2.29.2 +2.45.2 diff --git a/0001-panel-Use-branding-in-activities-button.patch b/0001-panel-Use-branding-in-activities-button.patch new file mode 100644 index 0000000..fb3ce1c --- /dev/null +++ b/0001-panel-Use-branding-in-activities-button.patch @@ -0,0 +1,51 @@ +From c0b2f60108e7b8cffa10306ef54c620fe71a6735 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 22 May 2024 18:42:06 +0200 +Subject: [PATCH] panel: Use branding in activities button + +Replace the upstream workspace dots with a red hat. +--- + data/theme/gnome-shell-sass/widgets/_panel.scss | 5 +++++ + js/ui/panel.js | 10 +++++++++- + 2 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/data/theme/gnome-shell-sass/widgets/_panel.scss b/data/theme/gnome-shell-sass/widgets/_panel.scss +index 2a29eee9da..02f8232de6 100644 +--- a/data/theme/gnome-shell-sass/widgets/_panel.scss ++++ b/data/theme/gnome-shell-sass/widgets/_panel.scss +@@ -58,6 +58,11 @@ $panel_transition_duration: 250ms; // same as the overview transition duration + min-height: $scalable_icon_size * 0.5; + background-color: $panel_fg_color; + } ++ ++ & .activities-logo { ++ icon-size: $scalable_icon_size * 1.25; ++ padding: 0 $base_padding; ++ } + } + + // screen activity indicators +diff --git a/js/ui/panel.js b/js/ui/panel.js +index 62c8ebb31a..1d11cc1b5f 100644 +--- a/js/ui/panel.js ++++ b/js/ui/panel.js +@@ -425,7 +425,15 @@ class ActivitiesButton extends PanelMenu.Button { + accessible_name: _('Activities'), + }); + +- this.add_child(new WorkspaceIndicators()); ++ if (GLib.get_os_info('ID') === 'rhel') { ++ const logoIcon = new St.Icon({ ++ icon_name: 'fedora-logo-icon', ++ style_class: 'activities-logo', ++ }); ++ this.add_child(logoIcon); ++ } else { ++ this.add_child(new WorkspaceIndicators()); ++ } + + Main.overview.connectObject('showing', + () => this.add_style_pseudo_class('checked'), +-- +2.45.2 + diff --git a/0001-screenShield-unblank-when-inserting-smartcard.patch b/0001-screenShield-unblank-when-inserting-smartcard.patch new file mode 100644 index 0000000..6b1d735 --- /dev/null +++ b/0001-screenShield-unblank-when-inserting-smartcard.patch @@ -0,0 +1,33 @@ +From 17e77f1729b8542c46d5020d55edce4daf7ab24a Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 3 Jul 2015 13:54:36 -0400 +Subject: [PATCH] screenShield: unblank when inserting smartcard + +If a user inserts the smartcard when the screen is locked/blanked +we should ask them their pin right away. + +At the moment they have to wiggle the mouse or do some other +action to get the screen to unblank. +--- + js/ui/screenShield.js | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js +index d2236fb900..b62440dff6 100644 +--- a/js/ui/screenShield.js ++++ b/js/ui/screenShield.js +@@ -94,8 +94,10 @@ export class ScreenShield extends Signals.EventEmitter { + this._smartcardManager = SmartcardManager.getSmartcardManager(); + this._smartcardManager.connect('smartcard-inserted', + (manager, token) => { +- if (this._isLocked && token.UsedToLogin) ++ if (this._isLocked && token.UsedToLogin) { ++ this._wakeUpScreen(); + this._activateDialog(); ++ } + }); + + this._credentialManagers = {}; +-- +2.45.2 + diff --git a/SOURCES/0003-st-texture-cache-purge-on-resume.patch b/0001-st-texture-cache-purge-on-resume.patch similarity index 77% rename from SOURCES/0003-st-texture-cache-purge-on-resume.patch rename to 0001-st-texture-cache-purge-on-resume.patch index 41c288d..2a13594 100644 --- a/SOURCES/0003-st-texture-cache-purge-on-resume.patch +++ b/0001-st-texture-cache-purge-on-resume.patch @@ -1,7 +1,7 @@ -From 2ebeda3385fb679df4bc13ba4b80bdeba5e2ad13 Mon Sep 17 00:00:00 2001 +From 5ddabd342d8016b5b1c8a56ecca7de21e91feb3c Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 15 Jan 2019 12:54:32 -0500 -Subject: [PATCH 3/4] st-texture-cache: purge on resume +Subject: [PATCH] st-texture-cache: purge on resume With the proprietary nvidia driver, textures get garbled on suspend, so the texture cache needs to evict all textures in that situation. @@ -12,10 +12,10 @@ so the texture cache needs to evict all textures in that situation. 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/js/ui/main.js b/js/ui/main.js -index 061303cf3..8d1755cf1 100644 +index ad0ea962f1..d9646fea52 100644 --- a/js/ui/main.js +++ b/js/ui/main.js -@@ -200,7 +200,11 @@ function _initializeUI() { +@@ -265,7 +265,11 @@ async function _initializeUI() { return true; }); @@ -26,13 +26,13 @@ index 061303cf3..8d1755cf1 100644 + loadTheme(); + }); - // Provide the bus object for gnome-session to - // initiate logouts. + global.context.connect('notify::unsafe-mode', () => { + if (!global.context.unsafe_mode) diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c -index cbe3afaba..40a11dd6d 100644 +index a137480ad1..2e5c6c689a 100644 --- a/src/st/st-texture-cache.c +++ b/src/st/st-texture-cache.c -@@ -113,6 +113,16 @@ st_texture_cache_class_init (StTextureCacheClass *klass) +@@ -129,6 +129,16 @@ st_texture_cache_class_init (StTextureCacheClass *klass) G_TYPE_NONE, 1, G_TYPE_FILE); } @@ -50,10 +50,10 @@ index cbe3afaba..40a11dd6d 100644 static void st_texture_cache_evict_icons (StTextureCache *cache) diff --git a/src/st/st-texture-cache.h b/src/st/st-texture-cache.h -index 11d1c4e64..9079d1fda 100644 +index 1c5be957c4..1a4bfde73f 100644 --- a/src/st/st-texture-cache.h +++ b/src/st/st-texture-cache.h -@@ -53,6 +53,7 @@ typedef enum { +@@ -52,6 +52,7 @@ typedef enum { } StTextureCachePolicy; StTextureCache* st_texture_cache_get_default (void); @@ -62,5 +62,5 @@ index 11d1c4e64..9079d1fda 100644 ClutterActor * st_texture_cache_load_sliced_image (StTextureCache *cache, -- -2.21.0 +2.45.2 diff --git a/0001-theme-Welcome-Illustration.patch b/0001-theme-Welcome-Illustration.patch new file mode 100644 index 0000000..5d2a1ee --- /dev/null +++ b/0001-theme-Welcome-Illustration.patch @@ -0,0 +1,1099 @@ +From acc68ed78070643a7adb8354cbd42e2ca58fb655 Mon Sep 17 00:00:00 2001 +From: Jakub Steiner +Date: Tue, 20 Aug 2024 09:30:36 +0200 +Subject: [PATCH] theme: Welcome Illustration + +- RHEL10 branded welcome illustration for Tour. +--- + data/theme/gnome-shell-start.svg | 914 +++++++++++++++++++++++++------ + 1 file changed, 746 insertions(+), 168 deletions(-) + +diff --git a/data/theme/gnome-shell-start.svg b/data/theme/gnome-shell-start.svg +index af139cf0d..7b039799e 100644 +--- a/data/theme/gnome-shell-start.svg ++++ b/data/theme/gnome-shell-start.svg +@@ -1,35 +1,30 @@ + + +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ style="fill:url(#linearGradient23);fill-opacity:1;stroke-width:0.999999" /> +-- +2.45.2 + diff --git a/SOURCES/0001-windowMenu-Bring-back-workspaces-submenu-for-static-.patch b/0001-windowMenu-Bring-back-workspaces-submenu-for-static-.patch similarity index 90% rename from SOURCES/0001-windowMenu-Bring-back-workspaces-submenu-for-static-.patch rename to 0001-windowMenu-Bring-back-workspaces-submenu-for-static-.patch index 810a27a..f7ece9e 100644 --- a/SOURCES/0001-windowMenu-Bring-back-workspaces-submenu-for-static-.patch +++ b/0001-windowMenu-Bring-back-workspaces-submenu-for-static-.patch @@ -1,4 +1,4 @@ -From 20640a92f98e2145b9b6581209c978e9f6f78801 Mon Sep 17 00:00:00 2001 +From 15df1086028087e5a81830323137a8730d2c5888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Tue, 14 Mar 2017 17:04:36 +0100 Subject: [PATCH] windowMenu: Bring back workspaces submenu for static @@ -13,10 +13,10 @@ are used. 1 file changed, 17 insertions(+) diff --git a/js/ui/windowMenu.js b/js/ui/windowMenu.js -index 628f145ea..f8eb4398c 100644 +index c69c183d7c..2db3962012 100644 --- a/js/ui/windowMenu.js +++ b/js/ui/windowMenu.js -@@ -115,6 +115,23 @@ var WindowMenu = class extends PopupMenu.PopupMenu { +@@ -153,6 +153,23 @@ export class WindowMenu extends PopupMenu.PopupMenu { window.change_workspace(workspace.get_neighbor(dir)); }); } @@ -41,5 +41,5 @@ index 628f145ea..f8eb4398c 100644 } -- -2.21.0 +2.45.2 diff --git a/SOURCES/0001-Do-not-change-Wacom-LEDs-through-g-s-d.patch b/SOURCES/0001-Do-not-change-Wacom-LEDs-through-g-s-d.patch deleted file mode 100644 index 9eb76be..0000000 --- a/SOURCES/0001-Do-not-change-Wacom-LEDs-through-g-s-d.patch +++ /dev/null @@ -1,25 +0,0 @@ -From f5ddd0fc02e99597e4b8506ac35523a6fa8ac22f Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Wed, 4 Mar 2020 16:08:31 +0100 -Subject: [PATCH] Do not change Wacom LEDs through g-s-d - -Let the wacom kernel driver sort it out by itself. ---- - js/ui/windowManager.js | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js -index dfe1b44..b2e938c 100644 ---- a/js/ui/windowManager.js -+++ b/js/ui/windowManager.js -@@ -1037,7 +1037,6 @@ var WindowManager = class { - - if (this._gsdWacomProxy) { - this._gsdWacomProxy.SetOLEDLabelsRemote(pad.get_device_node(), labels); -- this._gsdWacomProxy.SetGroupModeLEDRemote(pad.get_device_node(), group, mode); - } - }); - --- -2.24.1 - diff --git a/SOURCES/0001-a11y-Change-HC-icon-theme-first.patch b/SOURCES/0001-a11y-Change-HC-icon-theme-first.patch deleted file mode 100644 index f5eebd6..0000000 --- a/SOURCES/0001-a11y-Change-HC-icon-theme-first.patch +++ /dev/null @@ -1,58 +0,0 @@ -From a94260b4f2f72ea9328a0194b8656f1fb3e98675 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Sat, 14 Dec 2019 19:15:53 +0100 -Subject: [PATCH] a11y: Change HC icon theme first - -There are two ways for applications to provide a high contrast icon: - - 1. install an icon into the HighContrast theme - 2. install a symbolic icon into the default hicolor theme - -The latter is preferred nowadays, and implemented in the high-contrast -CSS variant by enforcing the symbolic icon style. - -However together with the way we currently enable/disable high-contrast, -this can lead to the following race: - 1. the GTK theme is changed from HighContrast - 2. we reload the default stylesheet - 3. the icon style changes to "regular", so we request a - new icon from the HighContrast icon theme - 4. the icon theme is changed from HighContrast - 5. we evict existing icons from the cache - 6. we reload icons for the new icon theme; however as we - find a pending request (from 3), we re-use it - 7. the request from 3 finishes, and we end up with a - wrong icon in the cache - -The simplest fix is to change the icon theme before the GTK theme: Unlike the -theme name, the icon style is encoded in the cache key, so we won't re-use -an old (and incorrect) request in that case. ---- - js/ui/status/accessibility.js | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/js/ui/status/accessibility.js b/js/ui/status/accessibility.js -index 10223ec84..90948d465 100644 ---- a/js/ui/status/accessibility.js -+++ b/js/ui/status/accessibility.js -@@ -154,14 +154,14 @@ class ATIndicator extends PanelMenu.Button { - interfaceSettings.is_writable(KEY_ICON_THEME), - enabled => { - if (enabled) { -- interfaceSettings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME); - interfaceSettings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME); -+ interfaceSettings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME); - } else if(!hasHC) { -- interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme); - interfaceSettings.set_string(KEY_ICON_THEME, iconTheme); -+ interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme); - } else { -- interfaceSettings.reset(KEY_GTK_THEME); - interfaceSettings.reset(KEY_ICON_THEME); -+ interfaceSettings.reset(KEY_GTK_THEME); - } - }); - return highContrast; --- -2.23.0 - diff --git a/SOURCES/0001-animation-fix-unintentional-loop-while-polkit-dialog.patch b/SOURCES/0001-animation-fix-unintentional-loop-while-polkit-dialog.patch deleted file mode 100644 index 748b73f..0000000 --- a/SOURCES/0001-animation-fix-unintentional-loop-while-polkit-dialog.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 34e6bbeebef37ae688ca0527bde03fa26b143bb7 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 27 Jun 2019 14:27:34 -0400 -Subject: [PATCH] animation: fix unintentional loop while polkit dialog is - active - -The polkit password dialog has a spinner that gets displayed -while the users password is being verified. - -Unfortunately, the spinner stop method unintentionally calls -back into itself after the stop fade out animation is complete. -The stop method is called at startup, so the looping begins as -soon as the dialog is visible and continues until the dialog is -dismissed. - -This commit fixes the loop by having the stop method cease -calling itself, and instead having it call the stop method on the -superclass. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/602 ---- - js/ui/animation.js | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/js/ui/animation.js b/js/ui/animation.js -index c21b22565..58d7f4018 100644 ---- a/js/ui/animation.js -+++ b/js/ui/animation.js -@@ -162,7 +162,7 @@ var Spinner = class extends AnimatedIcon { - time: SPINNER_ANIMATION_TIME, - transition: 'linear', - onComplete: () => { -- this.stop(false); -+ super.stop(); - } - }); - } else { --- -2.21.0 - diff --git a/SOURCES/0001-appDisplay-Show-full-app-name-on-hover.patch b/SOURCES/0001-appDisplay-Show-full-app-name-on-hover.patch deleted file mode 100644 index ddd3d97..0000000 --- a/SOURCES/0001-appDisplay-Show-full-app-name-on-hover.patch +++ /dev/null @@ -1,111 +0,0 @@ -From a1c35ebb8f29103035526e6f48eba4ff37551964 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Thu, 21 Jun 2018 18:03:31 +0200 -Subject: [PATCH] appDisplay: Show full app name on hover - ---- - data/theme/gnome-shell-sass/_common.scss | 8 ++++ - js/ui/appDisplay.js | 48 ++++++++++++++++++++++++ - 2 files changed, 56 insertions(+) - -diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss -index 3b0d2bf04..293ea2ab9 100644 ---- a/data/theme/gnome-shell-sass/_common.scss -+++ b/data/theme/gnome-shell-sass/_common.scss -@@ -1411,6 +1411,14 @@ StScrollBar { - - } - -+ .app-well-hover-text { -+ text-align: center; -+ color: $osd_fg_color; -+ background-color: $osd_bg_color; -+ border-radius: 5px; -+ padding: 3px; -+ } -+ - .app-well-app-running-dot { //running apps indicator - width: 10px; height: 3px; - background-color: $selected_bg_color; -diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js -index adaefa7dd..a07db6573 100644 ---- a/js/ui/appDisplay.js -+++ b/js/ui/appDisplay.js -@@ -1478,6 +1478,20 @@ var AppIcon = class AppIcon { - this.actor.connect('clicked', this._onClicked.bind(this)); - this.actor.connect('popup-menu', this._onKeyboardPopupMenu.bind(this)); - -+ this._hoverText = null; -+ this._hoverTimeoutId = 0; -+ -+ if (this.icon.label) { -+ this._hoverText = new St.Label({ style_class: 'app-well-hover-text', -+ text: this.icon.label.text, -+ visible: false }); -+ this._hoverText.clutter_text.line_wrap = true; -+ Main.layoutManager.addChrome(this._hoverText); -+ -+ this.actor.connect('notify::hover', this._syncHoverText.bind(this)); -+ this.connect('sync-tooltip', this._syncHoverText.bind(this)); -+ } -+ - this._menu = null; - this._menuManager = new PopupMenu.PopupMenuManager(this); - -@@ -1509,12 +1523,39 @@ var AppIcon = class AppIcon { - this.app.disconnect(this._stateChangedId); - this._stateChangedId = 0; - this._removeMenuTimeout(); -+ this._removeHoverTimeout(); -+ if (this._hoverText) -+ this._hoverText.destroy(); -+ this._hoverText = null; - } - - _createIcon(iconSize) { - return this.app.create_icon_texture(iconSize); - } - -+ _syncHoverText() { -+ if (this.shouldShowTooltip()) { -+ if (this._hoverTimeoutId) -+ return; -+ -+ this._hoverTimeoutId = Mainloop.timeout_add(300, () => { -+ this._hoverText.style = `max-width: ${2 * this.icon.iconSize}px;`; -+ this._hoverText.ensure_style(); -+ -+ let [x, y] = this.icon.label.get_transformed_position(); -+ let offset = (this._hoverText.width - this.icon.label.width) / 2; -+ this._hoverText.set_position(Math.floor(x - offset), Math.floor(y)); -+ this._hoverText.show(); -+ -+ this._hoverTimeoutId = 0; -+ return GLib.SOURCE_REMOVE; -+ }); -+ } else { -+ this._removeHoverTimeout(); -+ this._hoverText.hide(); -+ } -+ } -+ - _removeMenuTimeout() { - if (this._menuTimeoutId > 0) { - Mainloop.source_remove(this._menuTimeoutId); -@@ -1522,6 +1563,13 @@ var AppIcon = class AppIcon { - } - } - -+ _removeHoverTimeout() { -+ if (this._hoverTimeoutId > 0) { -+ Mainloop.source_remove(this._hoverTimeoutId); -+ this._hoverTimeoutId = 0; -+ } -+ } -+ - _updateRunningStyle() { - if (this.app.state != Shell.AppState.STOPPED) - this._dot.show(); --- -2.21.0 - diff --git a/SOURCES/0001-background-refresh-after-suspend-on-wayland.patch b/SOURCES/0001-background-refresh-after-suspend-on-wayland.patch deleted file mode 100644 index ffcbca0..0000000 --- a/SOURCES/0001-background-refresh-after-suspend-on-wayland.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 165fc5147cd2c9bf4bc10a1c5a9a940ec4ddd8d9 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 15 Jan 2019 12:51:16 -0500 -Subject: [PATCH 1/4] background: refresh after suspend on wayland - -At the moment we only refresh after suspend on Xorg. - -We need to do it on wayland, too. ---- - src/shell-util.c | 3 --- - 1 file changed, 3 deletions(-) - -diff --git a/src/shell-util.c b/src/shell-util.c -index 31bb18e70..c6e5abed6 100644 ---- a/src/shell-util.c -+++ b/src/shell-util.c -@@ -395,9 +395,6 @@ get_gl_vendor (void) - gboolean - shell_util_need_background_refresh (void) - { -- if (!clutter_check_windowing_backend (CLUTTER_WINDOWING_X11)) -- return FALSE; -- - if (g_strcmp0 (get_gl_vendor (), "NVIDIA Corporation") == 0) - return TRUE; - --- -2.21.0 - diff --git a/SOURCES/0001-data-install-process-working.svg-to-filesystem.patch b/SOURCES/0001-data-install-process-working.svg-to-filesystem.patch deleted file mode 100644 index 9782372..0000000 --- a/SOURCES/0001-data-install-process-working.svg-to-filesystem.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 1dcae7bbba222a1c8bdfc2d76a9f716e638b0334 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 8 Jun 2017 12:04:31 -0400 -Subject: [PATCH] data: install process-working.svg to filesystem - -This helps prevent unlock failure on inplace upgrades between -7.3 and 7.4 ---- - data/theme/meson.build | 2 ++ - meson.build | 1 + - 2 files changed, 3 insertions(+) - -diff --git a/data/theme/meson.build b/data/theme/meson.build -index 22bae3dd2..d5acb8d10 100644 ---- a/data/theme/meson.build -+++ b/data/theme/meson.build -@@ -23,3 +23,5 @@ foreach style: styles - ], - depend_files: theme_sources) - endforeach -+ -+install_data('process-working.svg', install_dir: themedir) -diff --git a/meson.build b/meson.build -index 21a80bcc8..0acaba705 100644 ---- a/meson.build -+++ b/meson.build -@@ -57,6 +57,7 @@ localedir = join_paths(datadir, 'locale') - portaldir = join_paths(datadir, 'xdg-desktop-portal', 'portals') - schemadir = join_paths(datadir, 'glib-2.0', 'schemas') - servicedir = join_paths(datadir, 'dbus-1', 'services') -+themedir = join_paths(pkgdatadir, 'theme') - - # XXX: Once https://github.com/systemd/systemd/issues/9595 is fixed and we can - # depend on this version, replace with something like: --- -2.21.0 - diff --git a/SOURCES/0001-environment-reduce-calls-to-g_time_zone_new_local.patch b/SOURCES/0001-environment-reduce-calls-to-g_time_zone_new_local.patch deleted file mode 100644 index 3528e9d..0000000 --- a/SOURCES/0001-environment-reduce-calls-to-g_time_zone_new_local.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 6e80934456f0b4cc48da6a7201700dc4386a3474 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Thu, 27 Feb 2020 13:46:44 -0800 -Subject: [PATCH] environment: reduce calls to g_time_zone_new_local() - -Creating a new GTimeZone for the local timezone can be quite expensive if -done repeatedly. It requires an open(), mmap(), and parsing of -/etc/localtime. - -This patch was provided by Florian, and I've tested it as far back as -3.28.4 to ensure that we are really reducing the number of open() calls -on the compositor thread. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1051 - -Signed-off-by: Christian Hergert ---- - js/ui/environment.js | 22 +++++++++++++++++++++- - 1 file changed, 21 insertions(+), 1 deletion(-) - -diff --git a/js/ui/environment.js b/js/ui/environment.js -index 9c125d3eb..809b48e45 100644 ---- a/js/ui/environment.js -+++ b/js/ui/environment.js -@@ -11,6 +11,9 @@ imports.gi.versions.TelepathyLogger = '0.2'; - - const { Clutter, Gio, GLib, Shell, St } = imports.gi; - const Gettext = imports.gettext; -+const System = imports.system; -+ -+let _localTimeZone = null; - - // We can't import shell JS modules yet, because they may have - // variable initializations, etc, that depend on init() already having -@@ -117,9 +120,26 @@ function init() { - } - }; - -+ // Override to clear our own timezone cache as well -+ const origClearDateCaches = System.clearDateCaches; -+ System.clearDateCaches = function () { -+ _localTimeZone = null; -+ origClearDateCaches(); -+ }; -+ - // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783 - Date.prototype.toLocaleFormat = function(format) { -- return Shell.util_format_date(format, this.getTime()); -+ if (_localTimeZone === null) -+ _localTimeZone = GLib.TimeZone.new_local(); -+ -+ let dt = GLib.DateTime.new(_localTimeZone, -+ this.getYear(), -+ this.getMonth() + 1, -+ this.getDate(), -+ this.getHours(), -+ this.getMinutes(), -+ this.getSeconds()); -+ return dt ? dt.format(format) : ''; - }; - - let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR'); --- -2.31.1 - diff --git a/SOURCES/0001-extensionSystem-Handle-added-or-removed-sessionMode-.patch b/SOURCES/0001-extensionSystem-Handle-added-or-removed-sessionMode-.patch deleted file mode 100644 index 2a8ff21..0000000 --- a/SOURCES/0001-extensionSystem-Handle-added-or-removed-sessionMode-.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 1b6eb29ade832647510b36ddc13c9b88a25036df Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= -Date: Wed, 11 Sep 2019 20:18:20 +0200 -Subject: [PATCH 1/4] extensionSystem: Handle added or removed sessionMode - extensions - -Right now we're only handling added sessionMode extensions correctly on -sessionMode updates, also handle the other case and disable removed -sessionMode extensions on sessionMode updates. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96 ---- - js/ui/extensionSystem.js | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index 81804ea5e..77929f2a6 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -515,62 +515,62 @@ var ExtensionManager = class { - if (!this._initted) { - this._loadExtensions(); - this._initted = true; - } else { - this._enabledExtensions.forEach(uuid => { - this._callExtensionEnable(uuid); - }); - } - this._enabled = true; - } - - _disableAllExtensions() { - if (!this._enabled) - return; - - if (this._initted) { - this._extensionOrder.slice().reverse().forEach(uuid => { - this._callExtensionDisable(uuid); - }); - } - - this._enabled = false; - } - - _sessionUpdated() { - // For now sessionMode.allowExtensions controls extensions from both the - // 'enabled-extensions' preference and the sessionMode.enabledExtensions - // property; it might make sense to make enabledExtensions independent - // from allowExtensions in the future - if (Main.sessionMode.allowExtensions) { -- if (this._initted) -- this._enabledExtensions = this._getEnabledExtensions(); -+ // Take care of added or removed sessionMode extensions -+ this._onEnabledExtensionsChanged(); - this._enableAllExtensions(); - } else { - this._disableAllExtensions(); - } - } - }; - Signals.addSignalMethods(ExtensionManager.prototype); - - class ExtensionUpdateSource extends MessageTray.Source { - constructor() { - const appSys = Shell.AppSystem.get_default(); - this._app = appSys.lookup_app('gnome-shell-extension-prefs.desktop'); - - super(this._app.get_name()); - } - - getIcon() { - return this._app.app_info.get_icon(); - } - - _createPolicy() { - return new MessageTray.NotificationApplicationPolicy(this._app.id); - } - - open() { - this._app.activate(); - Main.overview.hide(); - Main.panel.closeCalendar(); - } - } --- -2.27.0 - diff --git a/SOURCES/0001-extensions-Add-a-SESSION_MODE-extension-type.patch b/SOURCES/0001-extensions-Add-a-SESSION_MODE-extension-type.patch deleted file mode 100644 index dc7619b..0000000 --- a/SOURCES/0001-extensions-Add-a-SESSION_MODE-extension-type.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 720eb83ba0b0e5e37185d7e7ed86fe9175cf18f4 Mon Sep 17 00:00:00 2001 -From: Rui Matos -Date: Fri, 8 Nov 2013 13:58:09 +0100 -Subject: [PATCH] extensions: Add a SESSION_MODE extension type - -This allows e.g. gnome-tweak-tool to present these extensions in a -different way since they can't be disabled. ---- - js/misc/extensionUtils.js | 3 ++- - js/ui/extensionSystem.js | 2 ++ - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/js/misc/extensionUtils.js b/js/misc/extensionUtils.js -index cf308b31f..fb1e2b506 100644 ---- a/js/misc/extensionUtils.js -+++ b/js/misc/extensionUtils.js -@@ -13,7 +13,8 @@ const FileUtils = imports.misc.fileUtils; - - var ExtensionType = { - SYSTEM: 1, -- PER_USER: 2 -+ PER_USER: 2, -+ SESSION_MODE: 3 - }; - - // Maps uuid -> metadata object -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index 6244c39b4..9ffdb4f3d 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -322,6 +322,8 @@ function _loadExtensions() { - let finder = new ExtensionUtils.ExtensionFinder(); - finder.connect('extension-found', (finder, extension) => { - loadExtension(extension); -+ if (Main.sessionMode.enabledExtensions.indexOf(extension.uuid) != -1) -+ extension.type = ExtensionUtils.ExtensionType.SESSION_MODE; - }); - finder.scanExtensions(); - } --- -2.21.0 - diff --git a/SOURCES/0001-gdm-add-AuthList-control.patch b/SOURCES/0001-gdm-add-AuthList-control.patch deleted file mode 100644 index 2bd503b..0000000 --- a/SOURCES/0001-gdm-add-AuthList-control.patch +++ /dev/null @@ -1,237 +0,0 @@ -From 592bf9b4ba879a365375a7edcb6c48258386e413 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 18 Jul 2017 12:58:14 -0400 -Subject: [PATCH 1/2] gdm: add AuthList control - -Ultimately, we want to add support for GDM's new ChoiceList -PAM extension. That extension allows PAM modules to present -a list of choices to the user. Before we can support that -extension, however, we need to have a list control in the -login-screen/unlock screen. This commit adds that control. - -For the most part, it's a copy-and-paste of the gdm userlist, -but with less features. It lacks API specific to the users, -lacks the built in timed login indicator, etc. It does feature -a label heading. ---- - js/gdm/authList.js | 195 ++++++++++++++++++++++++++++++++++ - js/js-resources.gresource.xml | 1 + - 2 files changed, 196 insertions(+) - create mode 100644 js/gdm/authList.js - -diff --git a/js/gdm/authList.js b/js/gdm/authList.js -new file mode 100644 -index 000000000..fc1c3d6e4 ---- /dev/null -+++ b/js/gdm/authList.js -@@ -0,0 +1,195 @@ -+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- -+/* -+ * Copyright 2017 Red Hat, Inc -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+const Clutter = imports.gi.Clutter; -+const GObject = imports.gi.GObject; -+const Gtk = imports.gi.Gtk; -+const Lang = imports.lang; -+const Meta = imports.gi.Meta; -+const Signals = imports.signals; -+const St = imports.gi.St; -+ -+const Tweener = imports.ui.tweener; -+ -+const _SCROLL_ANIMATION_TIME = 0.5; -+ -+const AuthListItem = new Lang.Class({ -+ Name: 'AuthListItem', -+ -+ _init(key, text) { -+ this.key = key; -+ let label = new St.Label({ style_class: 'auth-list-item-label', -+ y_align: Clutter.ActorAlign.CENTER }); -+ label.text = text; -+ -+ this.actor = new St.Button({ style_class: 'login-dialog-user-list-item', -+ button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, -+ can_focus: true, -+ child: label, -+ reactive: true, -+ x_align: St.Align.START, -+ x_fill: true }); -+ -+ this.actor.connect('key-focus-in', () => { -+ this._setSelected(true); -+ }); -+ this.actor.connect('key-focus-out', () => { -+ this._setSelected(false); -+ }); -+ this.actor.connect('notify::hover', () => { -+ this._setSelected(this.actor.hover); -+ }); -+ -+ this.actor.connect('clicked', this._onClicked.bind(this)); -+ }, -+ -+ _onClicked() { -+ this.emit('activate'); -+ }, -+ -+ _setSelected(selected) { -+ if (selected) { -+ this.actor.add_style_pseudo_class('selected'); -+ this.actor.grab_key_focus(); -+ } else { -+ this.actor.remove_style_pseudo_class('selected'); -+ } -+ } -+}); -+Signals.addSignalMethods(AuthListItem.prototype); -+ -+var AuthList = new Lang.Class({ -+ Name: 'AuthList', -+ -+ _init() { -+ this.actor = new St.BoxLayout({ vertical: true, -+ style_class: 'login-dialog-auth-list-layout' }); -+ -+ this.label = new St.Label({ style_class: 'prompt-dialog-headline' }); -+ this.actor.add_actor(this.label); -+ -+ this._scrollView = new St.ScrollView({ style_class: 'login-dialog-user-list-view'}); -+ this._scrollView.set_policy(Gtk.PolicyType.NEVER, -+ Gtk.PolicyType.AUTOMATIC); -+ this.actor.add_actor(this._scrollView); -+ -+ this._box = new St.BoxLayout({ vertical: true, -+ style_class: 'login-dialog-user-list', -+ pseudo_class: 'expanded' }); -+ -+ this._scrollView.add_actor(this._box); -+ this._items = {}; -+ -+ this.actor.connect('key-focus-in', this._moveFocusToItems.bind(this)); -+ }, -+ -+ _moveFocusToItems() { -+ let hasItems = Object.keys(this._items).length > 0; -+ -+ if (!hasItems) -+ return; -+ -+ if (global.stage.get_key_focus() != this.actor) -+ return; -+ -+ let focusSet = this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); -+ if (!focusSet) { -+ Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { -+ this._moveFocusToItems(); -+ return false; -+ }); -+ } -+ }, -+ -+ _onItemActivated(activatedItem) { -+ this.emit('activate', activatedItem.key); -+ }, -+ -+ scrollToItem(item) { -+ let box = item.actor.get_allocation_box(); -+ -+ let adjustment = this._scrollView.get_vscroll_bar().get_adjustment(); -+ -+ let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0); -+ Tweener.removeTweens(adjustment); -+ Tweener.addTween (adjustment, -+ { value: value, -+ time: _SCROLL_ANIMATION_TIME, -+ transition: 'easeOutQuad' }); -+ }, -+ -+ jumpToItem(item) { -+ let box = item.actor.get_allocation_box(); -+ -+ let adjustment = this._scrollView.get_vscroll_bar().get_adjustment(); -+ -+ let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0); -+ -+ adjustment.set_value(value); -+ }, -+ -+ getItem(key) { -+ let item = this._items[key]; -+ -+ if (!item) -+ return null; -+ -+ return item; -+ }, -+ -+ addItem(key, text) { -+ this.removeItem(key); -+ -+ let item = new AuthListItem(key, text); -+ this._box.add(item.actor, { x_fill: true }); -+ -+ this._items[key] = item; -+ -+ item.connect('activate', -+ this._onItemActivated.bind(this)); -+ -+ // Try to keep the focused item front-and-center -+ item.actor.connect('key-focus-in', -+ () => { this.scrollToItem(item); }); -+ -+ this._moveFocusToItems(); -+ -+ this.emit('item-added', item); -+ }, -+ -+ removeItem(key) { -+ let item = this._items[key]; -+ -+ if (!item) -+ return; -+ -+ item.actor.destroy(); -+ delete this._items[key]; -+ }, -+ -+ numItems() { -+ return Object.keys(this._items).length; -+ }, -+ -+ clear() { -+ this.label.text = ""; -+ this._box.destroy_all_children(); -+ this._items = {}; -+ } -+}); -+Signals.addSignalMethods(AuthList.prototype); -diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml -index 836d1c674..002b202f8 100644 ---- a/js/js-resources.gresource.xml -+++ b/js/js-resources.gresource.xml -@@ -1,6 +1,7 @@ - - - -+ gdm/authList.js - gdm/authPrompt.js - gdm/batch.js - gdm/fingerprint.js --- -2.21.0 - diff --git a/SOURCES/0001-keyboard-Only-enable-keyboard-if-ClutterDeviceManage.patch b/SOURCES/0001-keyboard-Only-enable-keyboard-if-ClutterDeviceManage.patch deleted file mode 100644 index a781d43..0000000 --- a/SOURCES/0001-keyboard-Only-enable-keyboard-if-ClutterDeviceManage.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 2acede02f30833c3fb891db8483f933f7b41508c Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Wed, 21 Oct 2020 21:32:03 +0200 -Subject: [PATCH] keyboard: Only enable keyboard if - ClutterDeviceManager::touch-mode is enabled - ---- - js/ui/keyboard.js | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js -index 94b5325..b1ee270 100644 ---- a/js/ui/keyboard.js -+++ b/js/ui/keyboard.js -@@ -1051,6 +1051,9 @@ var Keyboard = class Keyboard { - this._suggestions = null; - this._emojiKeyVisible = true; - -+ let manager = Clutter.DeviceManager.get_default(); -+ manager.connect('notify::touch-mode', this._syncEnabled.bind(this)); -+ - this._focusTracker = new FocusTracker(); - this._focusTracker.connect('position-changed', this._onFocusPositionChanged.bind(this)); - this._focusTracker.connect('reset', () => { -@@ -1120,8 +1123,10 @@ var Keyboard = class Keyboard { - - _syncEnabled() { - let wasEnabled = this._enabled; -+ let manager = Clutter.DeviceManager.get_default(); -+ let autoEnabled = manager.get_touch_mode() && this._lastDeviceIsTouchscreen(); - this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD); -- this._enabled = this._enableKeyboard || this._lastDeviceIsTouchscreen(); -+ this._enabled = this._enableKeyboard || autoEnabled; - if (!this._enabled && !this._keyboardController) - return; - --- -2.26.2 - diff --git a/SOURCES/0001-layout-Initialize-regions-unconditionally.patch b/SOURCES/0001-layout-Initialize-regions-unconditionally.patch deleted file mode 100644 index 3f6f065..0000000 --- a/SOURCES/0001-layout-Initialize-regions-unconditionally.patch +++ /dev/null @@ -1,51 +0,0 @@ -From d2661753076a60a7981836e4a85e88c4588fb1b2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Thu, 17 Nov 2022 15:21:42 +0100 -Subject: [PATCH] layout: Initialize regions unconditionally - -We currently initialize regions in all code paths except for the -greeter. But while there are no windows on the login screen, the -work area can still be used for positioning, for example for -notifications. - -Part-of: - ---- - js/ui/layout.js | 15 +++++++-------- - 1 file changed, 7 insertions(+), 8 deletions(-) - -diff --git a/js/ui/layout.js b/js/ui/layout.js -index beb4c0a5d..bb51946b7 100644 ---- a/js/ui/layout.js -+++ b/js/ui/layout.js -@@ -624,20 +624,19 @@ var LayoutManager = GObject.registerClass({ - reactive: true }); - this.addChrome(this._coverPane); - -+ // Force an update of the regions before we scale the UI group to -+ // get the correct allocation for the struts. -+ // Do this even when we don't animate on restart, so that maximized -+ // windows restore to the right size. -+ this._updateRegions(); -+ - if (Meta.is_restart()) { -- // On restart, we don't do an animation. Force an update of the -- // regions immediately so that maximized windows restore to the -- // right size taking struts into account. -- this._updateRegions(); -+ // On restart, we don't do an animation. - } else if (Main.sessionMode.isGreeter) { - this.panelBox.translation_y = -this.panelBox.height; - } else { - this._updateBackgrounds(); - -- // We need to force an update of the regions now before we scale -- // the UI group to get the correct allocation for the struts. -- this._updateRegions(); -- - this.keyboardBox.hide(); - - let monitor = this.primaryMonitor; --- -2.38.1 - diff --git a/SOURCES/0001-layout-Make-the-hot-corner-optional.patch b/SOURCES/0001-layout-Make-the-hot-corner-optional.patch deleted file mode 100644 index c77310c..0000000 --- a/SOURCES/0001-layout-Make-the-hot-corner-optional.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 35cbad572120125d3b823f37d2100b2beee4c1d8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Thu, 8 Jun 2017 17:07:56 +0200 -Subject: [PATCH] layout: Make the hot corner optional - -Whether people love or hate the hot corner depends in large extents -on hardware sensitivity and habits, which is hard to get right -universally. So bite the bullet and support an option to enable or -disable hot corners ... - -https://bugzilla.gnome.org/show_bug.cgi?id=688320 ---- - js/ui/layout.js | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) - -diff --git a/js/ui/layout.js b/js/ui/layout.js -index 2b3bb7442..beb4c0a5d 100644 ---- a/js/ui/layout.js -+++ b/js/ui/layout.js -@@ -1,6 +1,6 @@ - // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - --const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi; -+const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; - const Signals = imports.signals; - - const Background = imports.ui.background; -@@ -267,6 +267,13 @@ var LayoutManager = GObject.registerClass({ - this._backgroundGroup.lower_bottom(); - this._bgManagers = []; - -+ this._interfaceSettings = new Gio.Settings({ -+ schema_id: 'org.gnome.desktop.interface' -+ }); -+ -+ this._interfaceSettings.connect('changed::enable-hot-corners', -+ this._updateHotCorners.bind(this)); -+ - // Need to update struts on new workspaces when they are added - let workspaceManager = global.workspace_manager; - workspaceManager.connect('notify::n-workspaces', -@@ -358,6 +365,11 @@ var LayoutManager = GObject.registerClass({ - }); - this.hotCorners = []; - -+ if (!this._interfaceSettings.get_boolean('enable-hot-corners')) { -+ this.emit('hot-corners-changed'); -+ return; -+ } -+ - let size = this.panelBox.height; - - // build new hot corners --- -2.21.0 - diff --git a/SOURCES/0001-loginDialog-Reset-auth-prompt-on-vt-switch-before-fa.patch b/SOURCES/0001-loginDialog-Reset-auth-prompt-on-vt-switch-before-fa.patch deleted file mode 100644 index 85cdbbb..0000000 --- a/SOURCES/0001-loginDialog-Reset-auth-prompt-on-vt-switch-before-fa.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 6d26b6f9f66e14843f175305441a2464dd255fd1 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 27 Jul 2020 10:58:49 -0400 -Subject: [PATCH] loginDialog: Reset auth prompt on vt switch before fade in - -At the moment, if a user switches to the login screen vt, -the login screen fades in whatever was on screen prior, and -then does a reset. - -It makes more sense to reset first, so we fade in what the -user is going to interact with instead of what they interacted -with before. - -Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2997 ---- - js/gdm/loginDialog.js | 10 ++++------ - 1 file changed, 4 insertions(+), 6 deletions(-) - -diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js -index 214c2f512..eb6846d5c 100644 ---- a/js/gdm/loginDialog.js -+++ b/js/gdm/loginDialog.js -@@ -923,6 +923,9 @@ var LoginDialog = GObject.registerClass({ - if (this.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING) - return; - -+ if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING) -+ this._authPrompt.reset(); -+ - Tweener.addTween(this, - { opacity: 255, - time: _FADE_ANIMATION_TIME, -@@ -935,12 +938,7 @@ var LoginDialog = GObject.registerClass({ - children[i].opacity = this.opacity; - } - }, -- onUpdateScope: this, -- onComplete() { -- if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING) -- this._authPrompt.reset(); -- }, -- onCompleteScope: this }); -+ onUpdateScope: this }); - } - - _gotGreeterSessionProxy(proxy) { --- -2.32.0 - diff --git a/SOURCES/0001-loginDialog-make-info-messages-themed.patch b/SOURCES/0001-loginDialog-make-info-messages-themed.patch deleted file mode 100644 index 483f615..0000000 --- a/SOURCES/0001-loginDialog-make-info-messages-themed.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 9cfa56d4f3c5fe513630c58c09bd2421f3ca580b Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 26 Jun 2017 14:35:05 -0400 -Subject: [PATCH] loginDialog: make info messages themed - -They were lacking a definition before leading them to -show up invisible. ---- - data/theme/gnome-shell-sass/_common.scss | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss -index c2df28279..a382ce561 100644 ---- a/data/theme/gnome-shell-sass/_common.scss -+++ b/data/theme/gnome-shell-sass/_common.scss -@@ -1801,7 +1801,12 @@ StScrollBar { - .login-dialog-banner { color: darken($osd_fg_color,10%); } - .login-dialog-button-box { spacing: 5px; } - .login-dialog-message-warning { color: $warning_color; } -- .login-dialog-message-hint { padding-top: 0; padding-bottom: 20px; } -+ .login-dialog-message-hint, .login-dialog-message { -+ color: darken($osd_fg_color, 20%); -+ padding-top: 0; -+ padding-bottom: 20px; -+ min-height: 2.75em; -+ } - .login-dialog-user-selection-box { padding: 100px 0px; } - .login-dialog-not-listed-label { - padding-left: 2px; --- -2.21.0 - diff --git a/SOURCES/0001-main-Unset-the-right-prevFocus-actor-after-the-focus.patch b/SOURCES/0001-main-Unset-the-right-prevFocus-actor-after-the-focus.patch deleted file mode 100644 index c052297..0000000 --- a/SOURCES/0001-main-Unset-the-right-prevFocus-actor-after-the-focus.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0d95c2087aba7f0b07cb303c1f15d097b45f1b09 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= -Date: Tue, 28 Apr 2020 23:26:11 +0200 -Subject: [PATCH] main: Unset the right prevFocus actor after the focus stack - got shifted -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When a modal that's not on top of the modalActorFocusStack gets popped, -we shift the focus stack as described in popModal() to ensure the chain -remains correct. That however destroys the association of a modal actor -and its prevFocus actor on the focus stack, because the prevFocus actors -are now moved to different entries of the stack. - -Now when a prevFocus actor gets destroyed, we don't handle that case -correctly and search for the modal actor that was associated with the -prevFocus actor before the stack was shifted, which means we end up -unsetting the wrong prevFocus actor. - -So fix that and search the stack for the prevFocus actor which is being -destroyed instead to unset the correct entry. - -Thanks to Florian Müllner for figuring out the actual issue and -proposing this fix. - -Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2446 ---- - js/ui/main.js | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/js/ui/main.js b/js/ui/main.js -index dd1d8463d..ca3dcaa3c 100644 ---- a/js/ui/main.js -+++ b/js/ui/main.js -@@ -486,7 +486,9 @@ function pushModal(actor, params) { - let prevFocusDestroyId; - if (prevFocus != null) { - prevFocusDestroyId = prevFocus.connect('destroy', () => { -- let index = _findModal(actor); -+ const index = modalActorFocusStack.findIndex( -+ record => record.prevFocus === prevFocus); -+ - if (index >= 0) - modalActorFocusStack[index].prevFocus = null; - }); --- -2.35.1 - diff --git a/SOURCES/0001-networkAgent-add-support-for-SAE-secrets.patch b/SOURCES/0001-networkAgent-add-support-for-SAE-secrets.patch deleted file mode 100644 index dd05d56..0000000 --- a/SOURCES/0001-networkAgent-add-support-for-SAE-secrets.patch +++ /dev/null @@ -1,29 +0,0 @@ -From bd4a3186dc21f2c8d3e0f851cf262a34ddb6b625 Mon Sep 17 00:00:00 2001 -From: Lubomir Rintel -Date: Fri, 4 Oct 2019 14:21:25 +0200 -Subject: [PATCH] networkAgent: add support for SAE secrets - -NetworkManager supports "WPA3 Personal" networks for some time now, they -use the SAE authentication. Add support for it alongside other -password-based mechanisms. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/751 ---- - js/ui/components/networkAgent.js | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/js/ui/components/networkAgent.js b/js/ui/components/networkAgent.js -index 32d40fb2b..3ff957bf6 100644 ---- a/js/ui/components/networkAgent.js -+++ b/js/ui/components/networkAgent.js -@@ -216,6 +216,7 @@ var NetworkSecretDialog = class extends ModalDialog.ModalDialog { - // First the easy ones - case 'wpa-none': - case 'wpa-psk': -+ case 'sae': - secrets.push({ label: _("Password: "), key: 'psk', - value: wirelessSecuritySetting.psk || '', - validate: this._validateWpaPsk, password: true }); --- -2.32.0 - diff --git a/SOURCES/0001-overview-Hide-the-overview-on-session-mode-hasOvervi.patch b/SOURCES/0001-overview-Hide-the-overview-on-session-mode-hasOvervi.patch deleted file mode 100644 index 2fe001a..0000000 --- a/SOURCES/0001-overview-Hide-the-overview-on-session-mode-hasOvervi.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 2ddb51234ca69c0e637b35071b4e760d1b72527a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= -Date: Mon, 24 Feb 2020 11:19:28 +0100 -Subject: [PATCH] overview: Hide the overview on session mode hasOverview - changes - -If the sessionMode does not allow to show the overview, we should also -hide an already visible overview. - -This fixes a bug where, if the lockscreen was shown while the overview -was visible, the Ctrl+Alt+Tab popup would allow navigating inside the -overview because the overview actor is still mapped. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1043 ---- - js/ui/overview.js | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/js/ui/overview.js b/js/ui/overview.js -index 5bad4cbd62..03cecb6dbc 100644 ---- a/js/ui/overview.js -+++ b/js/ui/overview.js -@@ -196,7 +196,11 @@ var Overview = class { - } - - _sessionUpdated() { -- this.isDummy = !Main.sessionMode.hasOverview; -+ const { hasOverview } = Main.sessionMode; -+ if (!hasOverview) -+ this.hide(); -+ -+ this.isDummy = !hasOverview; - this._createOverview(); - } - --- -2.43.0 - diff --git a/SOURCES/0001-padOsd-Re-query-action-labels-after-mode-switches.patch b/SOURCES/0001-padOsd-Re-query-action-labels-after-mode-switches.patch deleted file mode 100644 index bdbfc65..0000000 --- a/SOURCES/0001-padOsd-Re-query-action-labels-after-mode-switches.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 2bb826291c420dd1b601758c7a686ac48e1086a6 Mon Sep 17 00:00:00 2001 -From: Carlos Garnacho -Date: Mon, 16 Dec 2019 12:39:49 +0100 -Subject: [PATCH] padOsd: Re-query action labels after mode switches - -Do this so the pad OSD is able to update dynamically to mode changes, -showing immediately the new actions for the current mode(s). - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/898 ---- - js/ui/padOsd.js | 31 ++++++++++++++++++++++++++++--- - 1 file changed, 28 insertions(+), 3 deletions(-) - -diff --git a/js/ui/padOsd.js b/js/ui/padOsd.js -index a4af47297..b4b3fe453 100644 ---- a/js/ui/padOsd.js -+++ b/js/ui/padOsd.js -@@ -555,6 +555,14 @@ var PadDiagram = GObject.registerClass({ - this.add_actor(label); - } - -+ updateLabels(callback) { -+ for (let i = 0; i < this._labels.length; i++) { -+ let [label, action, idx, dir] = this._labels[i]; -+ let str = callback(action, idx, dir); -+ label.set_text(str); -+ } -+ } -+ - _applyLabel(label, action, idx, dir, str) { - if (str != null) { - label.set_text(str); -@@ -758,17 +766,29 @@ var PadOsd = class { - global.display.request_pad_osd(pad, editionMode); - } - -- _createLabel(type, number, dir) { -+ _getActionText(type, number) { - let str = global.display.get_pad_action_label(this.padDevice, type, number); -- let label = new St.Label({ text: str ? str : _("None") }); -+ return str ? str : _("None"); -+ } -+ -+ _createLabel(type, number, dir) { -+ let label = new St.Label({ text: this._getActionText(type, number) }); - this._padDiagram.addLabel(label, type, number, dir); - } - -+ _updateActionLabels() { -+ this._padDiagram.updateLabels(this._getActionText.bind(this)); -+ } -+ - _onCapturedEvent(actor, event) { -+ let isModeSwitch = -+ (event.type() == Clutter.EventType.PAD_BUTTON_PRESS || -+ event.type() == Clutter.EventType.PAD_BUTTON_RELEASE) && -+ this.padDevice.get_mode_switch_button_group(event.get_button()) >= 0; -+ - if (event.type() == Clutter.EventType.PAD_BUTTON_PRESS && - event.get_source_device() == this.padDevice) { - this._padDiagram.activateButton(event.get_button()); -- let isModeSwitch = this.padDevice.get_mode_switch_button_group(event.get_button()) >= 0; - - /* Buttons that switch between modes cannot be edited */ - if (this._editionMode && !isModeSwitch) -@@ -777,6 +797,11 @@ var PadOsd = class { - } else if (event.type() == Clutter.EventType.PAD_BUTTON_RELEASE && - event.get_source_device() == this.padDevice) { - this._padDiagram.deactivateButton(event.get_button()); -+ -+ if (isModeSwitch) { -+ this._endActionEdition(); -+ this._updateActionLabels(); -+ } - return Clutter.EVENT_STOP; - } else if (event.type() == Clutter.EventType.KEY_PRESS && - (!this._editionMode || event.get_key_symbol() == Clutter.Escape)) { --- -2.24.0 - diff --git a/SOURCES/0001-panel-add-an-icon-to-the-ActivitiesButton.patch b/SOURCES/0001-panel-add-an-icon-to-the-ActivitiesButton.patch deleted file mode 100644 index 24c0d81..0000000 --- a/SOURCES/0001-panel-add-an-icon-to-the-ActivitiesButton.patch +++ /dev/null @@ -1,54 +0,0 @@ -From aadb0e19999c339ac1d6501a2e52b363e57e26ef Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 15 Jan 2014 16:45:34 -0500 -Subject: [PATCH] panel: add an icon to the ActivitiesButton - -Requested by brand ---- - data/theme/gnome-shell-sass/_common.scss | 5 +++++ - js/ui/panel.js | 9 ++++++++- - 2 files changed, 13 insertions(+), 1 deletion(-) - -diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss -index a382ce561..3b0d2bf04 100644 ---- a/data/theme/gnome-shell-sass/_common.scss -+++ b/data/theme/gnome-shell-sass/_common.scss -@@ -769,6 +769,11 @@ StScrollBar { - //dimensions of the icon are hardcoded - } - -+ .panel-logo-icon { -+ padding-right: .4em; -+ icon-size: 1em; -+ } -+ - &:hover { - color: lighten($fg_color, 10%); - } -diff --git a/js/ui/panel.js b/js/ui/panel.js -index 16484850a..ede1c2b82 100644 ---- a/js/ui/panel.js -+++ b/js/ui/panel.js -@@ -465,11 +465,18 @@ class ActivitiesButton extends PanelMenu.Button { - - this.actor.name = 'panelActivities'; - -+ let box = new St.BoxLayout(); -+ this.actor.add_actor(box); -+ let iconFile = Gio.File.new_for_path('/usr/share/icons/hicolor/scalable/apps/start-here.svg'); -+ this._icon = new St.Icon({ gicon: new Gio.FileIcon({ file: iconFile }), -+ style_class: 'panel-logo-icon' }); -+ box.add_actor(this._icon); -+ - /* Translators: If there is no suitable word for "Activities" - in your language, you can use the word for "Overview". */ - this._label = new St.Label({ text: _("Activities"), - y_align: Clutter.ActorAlign.CENTER }); -- this.actor.add_actor(this._label); -+ box.add_actor(this._label); - - this.actor.label_actor = this._label; - --- -2.21.0 - diff --git a/SOURCES/0001-popupMenu-Handle-keypress-if-numlock-is-enabled.patch b/SOURCES/0001-popupMenu-Handle-keypress-if-numlock-is-enabled.patch deleted file mode 100644 index e6fed23..0000000 --- a/SOURCES/0001-popupMenu-Handle-keypress-if-numlock-is-enabled.patch +++ /dev/null @@ -1,36 +0,0 @@ -From fb0a9a60ab8f1c0dd96e789969ab9b6e48a9fce4 Mon Sep 17 00:00:00 2001 -From: Olivier Fourdan -Date: Tue, 21 Jul 2020 16:33:04 +0200 -Subject: [PATCH] popupMenu: Handle keypress if numlock is enabled - -On Wayland, navigating menus with the keyboard would not open drop-down -menus when NumLock is enabled. - -That's old issue (gnome-shell#550) that was not completely fixed with -commit 88556226 because the lock mask needs to be filtered out in -_onKeyPress() as well. - -Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/550 ---- - js/ui/popupMenu.js | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js -index 6de081ce81..9835face19 100644 ---- a/js/ui/popupMenu.js -+++ b/js/ui/popupMenu.js -@@ -801,9 +801,10 @@ var PopupMenu = class extends PopupMenuBase { - - let state = event.get_state(); - -- // if user has a modifier down (except capslock) -+ // if user has a modifier down (except capslock and numlock) - // then don't handle the key press here - state &= ~Clutter.ModifierType.LOCK_MASK; -+ state &= ~Clutter.ModifierType.MOD2_MASK; - state &= Clutter.ModifierType.MODIFIER_MASK; - - if (state) --- -2.26.2 - diff --git a/SOURCES/0001-screenShield-unblank-when-inserting-smartcard.patch b/SOURCES/0001-screenShield-unblank-when-inserting-smartcard.patch deleted file mode 100644 index 3dc3cb9..0000000 --- a/SOURCES/0001-screenShield-unblank-when-inserting-smartcard.patch +++ /dev/null @@ -1,33 +0,0 @@ -From cacce594f07295bb1b9e0685913a287e3cea2453 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 3 Jul 2015 13:54:36 -0400 -Subject: [PATCH] screenShield: unblank when inserting smartcard - -If a user inserts the smartcard when the screen is locked/blanked -we should ask them their pin right away. - -At the moment they have to wiggle the mouse or do some other -action to get the screen to unblank. ---- - js/ui/screenShield.js | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js -index a005a206b..cd38f11fc 100644 ---- a/js/ui/screenShield.js -+++ b/js/ui/screenShield.js -@@ -513,8 +513,10 @@ var ScreenShield = class { - this._smartcardManager = SmartcardManager.getSmartcardManager(); - this._smartcardManager.connect('smartcard-inserted', - (manager, token) => { -- if (this._isLocked && token.UsedToLogin) -+ if (this._isLocked && token.UsedToLogin) { -+ this._wakeUpScreen(); - this._liftShield(true, 0); -+ } - }); - - this._oVirtCredentialsManager = OVirt.getOVirtCredentialsManager(); --- -2.21.0 - diff --git a/SOURCES/0001-screencast-Stop-recording-when-screen-size-or-resour.patch b/SOURCES/0001-screencast-Stop-recording-when-screen-size-or-resour.patch deleted file mode 100644 index 582ff4e..0000000 --- a/SOURCES/0001-screencast-Stop-recording-when-screen-size-or-resour.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 67a4506d4d8a0cbbaca5df4adfc309e54e557aee Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Tue, 5 Jan 2021 12:04:23 +0100 -Subject: [PATCH] screencast: Stop recording when screen size or resource scale - change - -Video encoders don't really handle changing the size of the video, and if -we'd e.g. change resolution while recording, we would end up with a corrupt -video file. Handle this more gracefully by stopping the recording if the -conditions change. ---- - js/ui/screencast.js | 92 +++++++++++++++++++++++++++++++++++++++++--- - src/shell-recorder.c | 50 ++++++++++++------------ - src/shell-recorder.h | 1 + - 3 files changed, 114 insertions(+), 29 deletions(-) - -diff --git a/js/ui/screencast.js b/js/ui/screencast.js -index 0b0b14a8e..54f8fb5ae 100644 ---- a/js/ui/screencast.js -+++ b/js/ui/screencast.js -@@ -1,6 +1,6 @@ - // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - --const { Gio, GLib, Shell } = imports.gi; -+const { Gio, GLib, Meta, Shell } = imports.gi; - const Signals = imports.signals; - - const Main = imports.ui.main; -@@ -53,16 +53,27 @@ var ScreencastService = class { - this._stopRecordingForSender(name); - } - -- _stopRecordingForSender(sender) { -+ _stopRecordingForSender(sender, closeNow=false) { - let recorder = this._recorders.get(sender); - if (!recorder) - return false; - - Gio.bus_unwatch_name(recorder._watchNameId); -- recorder.close(); -+ if (closeNow) -+ recorder.close_now(); -+ else -+ recorder.close(); - this._recorders.delete(sender); - this.emit('updated'); - -+ let connection = this._dbusImpl.get_connection(); -+ let info = this._dbusImpl.get_info(); -+ connection.emit_signal(sender, -+ this._dbusImpl.get_object_path(), -+ info ? info.name : null, -+ 'Stopped', -+ null); -+ - return true; - } - -@@ -78,6 +89,53 @@ var ScreencastService = class { - recorder.set_draw_cursor(options['draw-cursor']); - } - -+ _ensureResourceScaleChangedHandler() { -+ if (this._resourceScaleChangedHandlerId) -+ return; -+ -+ this._resourceScaleChangedHandlerId = -+ global.stage.connect('notify::resource-scale', -+ () => { -+ for (let sender of this._recorders.keys()) { -+ let recorder = this._recorders.get(sender); -+ -+ if (!recorder.is_recording()) -+ continue; -+ -+ this._stopRecordingForSender(sender, true); -+ } -+ }); -+ } -+ -+ _ensureMonitorsChangedHandler() { -+ if (this._monitorsChangedHandlerId) -+ return; -+ -+ this._monitorsChangedHandlerId = Main.layoutManager.connect('monitors-changed', -+ () => { -+ for (let sender of this._recorders.keys()) { -+ let recorder = this._recorders.get(sender); -+ -+ if (!recorder.is_recording()) -+ continue; -+ -+ let geometry = recorder._geometry; -+ let screenWidth = global.screen_width; -+ let screenHeight = global.screen_height; -+ -+ if (recorder._isAreaScreecast) { -+ if (geometry.x + geometry.width > screenWidth || -+ geometry.y + geometry.height > screenHeight) -+ this._stopRecordingForSender(sender, true); -+ } else { -+ if (geometry.width != screenWidth || -+ geometry.height != screenHeight) -+ this._stopRecordingForSender(sender, true); -+ } -+ } -+ }); -+ } -+ - ScreencastAsync(params, invocation) { - let returnValue = [false, '']; - if (!Main.sessionMode.allowScreencast || -@@ -95,8 +153,20 @@ var ScreencastService = class { - this._applyOptionalParameters(recorder, options); - let [success, fileName] = recorder.record(); - returnValue = [success, fileName ? fileName : '']; -- if (!success) -+ if (success) { -+ recorder._isAreaScreecast = false; -+ recorder._geometry = -+ new Meta.Rectangle({ -+ x: 0, -+ y: 0, -+ width: global.screen_width, -+ height: global.screen_height -+ }); -+ this._ensureResourceScaleChangedHandler(); -+ this._ensureMonitorsChangedHandler(); -+ } else { - this._stopRecordingForSender(sender); -+ } - } - - invocation.return_value(GLib.Variant.new('(bs)', returnValue)); -@@ -131,8 +201,20 @@ var ScreencastService = class { - this._applyOptionalParameters(recorder, options); - let [success, fileName] = recorder.record(); - returnValue = [success, fileName ? fileName : '']; -- if (!success) -+ if (success) { -+ recorder._isAreaScreecast = true; -+ recorder._geometry = -+ new Meta.Rectangle({ -+ x: x, -+ y: y, -+ width: width, -+ height: height -+ }); -+ this._ensureResourceScaleChangedHandler(); -+ this._ensureMonitorsChangedHandler(); -+ } else { - this._stopRecordingForSender(sender); -+ } - } - - invocation.return_value(GLib.Variant.new('(bs)', returnValue)); -diff --git a/src/shell-recorder.c b/src/shell-recorder.c -index 0203ecf1c..e561a0152 100644 ---- a/src/shell-recorder.c -+++ b/src/shell-recorder.c -@@ -511,21 +511,6 @@ recorder_update_size (ShellRecorder *recorder) - } - } - --static void --recorder_on_stage_notify_size (GObject *object, -- GParamSpec *pspec, -- ShellRecorder *recorder) --{ -- recorder_update_size (recorder); -- -- /* This breaks the recording but tweaking the GStreamer pipeline a bit -- * might make it work, at least if the codec can handle a stream where -- * the frame size changes in the middle. -- */ -- if (recorder->current_pipeline) -- recorder_pipeline_set_caps (recorder->current_pipeline); --} -- - static gboolean - recorder_idle_redraw (gpointer data) - { -@@ -622,12 +607,6 @@ recorder_connect_stage_callbacks (ShellRecorder *recorder) - G_CALLBACK (recorder_on_stage_destroy), recorder); - g_signal_connect_after (recorder->stage, "paint", - G_CALLBACK (recorder_on_stage_paint), recorder); -- g_signal_connect (recorder->stage, "notify::width", -- G_CALLBACK (recorder_on_stage_notify_size), recorder); -- g_signal_connect (recorder->stage, "notify::height", -- G_CALLBACK (recorder_on_stage_notify_size), recorder); -- g_signal_connect (recorder->stage, "notify::resource-scale", -- G_CALLBACK (recorder_on_stage_notify_size), recorder); - } - - static void -@@ -639,9 +618,6 @@ recorder_disconnect_stage_callbacks (ShellRecorder *recorder) - g_signal_handlers_disconnect_by_func (recorder->stage, - (void *)recorder_on_stage_paint, - recorder); -- g_signal_handlers_disconnect_by_func (recorder->stage, -- (void *)recorder_on_stage_notify_size, -- recorder); - - /* We don't don't deselect for cursor changes in case someone else just - * happened to be selecting for cursor events on the same window; sending -@@ -1578,6 +1554,32 @@ shell_recorder_record (ShellRecorder *recorder, - return TRUE; - } - -+/** -+ * shell_recorder_close_now: -+ * @recorder: the #ShellRecorder -+ * -+ * Stops recording immediately. It's possible to call shell_recorder_record() -+ * again to reopen a new recording stream, but unless change the recording -+ * filename, this may result in the old recording being overwritten. -+ */ -+void -+shell_recorder_close_now (ShellRecorder *recorder) -+{ -+ g_return_if_fail (SHELL_IS_RECORDER (recorder)); -+ g_return_if_fail (recorder->state != RECORDER_STATE_CLOSED); -+ -+ recorder_remove_update_pointer_timeout (recorder); -+ recorder_close_pipeline (recorder); -+ -+ recorder->state = RECORDER_STATE_CLOSED; -+ -+ /* Reenable after the recording */ -+ meta_enable_unredirect_for_display (shell_global_get_display (shell_global_get ())); -+ -+ /* Release the refcount we took when we started recording */ -+ g_object_unref (recorder); -+} -+ - /** - * shell_recorder_close: - * @recorder: the #ShellRecorder -diff --git a/src/shell-recorder.h b/src/shell-recorder.h -index c1e0e6368..1c3e6aab4 100644 ---- a/src/shell-recorder.h -+++ b/src/shell-recorder.h -@@ -37,6 +37,7 @@ void shell_recorder_set_area (ShellRecorder *recorder, - gboolean shell_recorder_record (ShellRecorder *recorder, - char **filename_used); - void shell_recorder_close (ShellRecorder *recorder); -+void shell_recorder_close_now (ShellRecorder *recorder); - void shell_recorder_pause (ShellRecorder *recorder); - gboolean shell_recorder_is_recording (ShellRecorder *recorder); - --- -2.27.0 - diff --git a/SOURCES/0001-shell-app-Handle-workspace-from-startup-notification.patch b/SOURCES/0001-shell-app-Handle-workspace-from-startup-notification.patch deleted file mode 100644 index e7f0db8..0000000 --- a/SOURCES/0001-shell-app-Handle-workspace-from-startup-notification.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 391f262aee82ac12fcf99951d6b2df362f734b31 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 15 Jun 2020 20:41:45 +0200 -Subject: [PATCH] shell/app: Handle workspace from startup notifications - -Launching applications on a particular workspace works through -launch contexts and startup notifications. While this is no -longer required by a launcher/WM split, in theory this allows -us to reliably identify the correct window to apply startup -properties to. - -However in practice we fail more often than not: Missing support in -toolkits, differences between display protocols, D-Bus activation -and single-instance applications all provide their own pitfalls. - -So instead, take advantage of the fact that launcher and WM live in -the same process, and go with the unsophisticated approach: Just -remember the last workspace that was requested when launching an -app, then move the next window that is associated with the app to -that workspace. - -This will break X11 applications that set an initial workspace, but -that's legacy functionality anyway (given that there's no wayland -protocol for that functionality), and seems a price worth paying -for making launching apps on workspaces more reliable. ---- - src/shell-app.c | 19 +++++++++++-------- - 1 file changed, 11 insertions(+), 8 deletions(-) - -diff --git a/src/shell-app.c b/src/shell-app.c -index 7d40186c9..f716bc5f8 100644 ---- a/src/shell-app.c -+++ b/src/shell-app.c -@@ -1067,6 +1067,10 @@ _shell_app_add_window (ShellApp *app, - if (!app->running_state) - create_running_state (app); - -+ if (app->started_on_workspace >= 0) -+ meta_window_change_workspace_by_index (window, app->started_on_workspace, FALSE); -+ app->started_on_workspace = -1; -+ - app->running_state->window_sort_stale = TRUE; - app->running_state->windows = g_slist_prepend (app->running_state->windows, g_object_ref (window)); - g_signal_connect_object (window, "unmanaged", G_CALLBACK(shell_app_on_unmanaged), app, 0); -@@ -1156,16 +1160,14 @@ _shell_app_handle_startup_sequence (ShellApp *app, - shell_app_state_transition (app, SHELL_APP_STATE_STARTING); - meta_x11_display_focus_the_no_focus_window (x11_display, - meta_startup_sequence_get_timestamp (sequence)); -- app->started_on_workspace = meta_startup_sequence_get_workspace (sequence); - } - -- if (!starting) -- { -- if (app->running_state && app->running_state->windows) -- shell_app_state_transition (app, SHELL_APP_STATE_RUNNING); -- else /* application have > 1 .desktop file */ -- shell_app_state_transition (app, SHELL_APP_STATE_STOPPED); -- } -+ if (starting) -+ app->started_on_workspace = meta_startup_sequence_get_workspace (sequence); -+ else if (app->running_state && app->running_state->windows) -+ shell_app_state_transition (app, SHELL_APP_STATE_RUNNING); -+ else /* application have > 1 .desktop file */ -+ shell_app_state_transition (app, SHELL_APP_STATE_STOPPED); - } - - /** -@@ -1473,6 +1475,7 @@ static void - shell_app_init (ShellApp *self) - { - self->state = SHELL_APP_STATE_STOPPED; -+ self->started_on_workspace = -1; - } - - static void --- -2.29.2 - diff --git a/SOURCES/0001-shell-recorder-Restore-cursor-recording.patch b/SOURCES/0001-shell-recorder-Restore-cursor-recording.patch deleted file mode 100644 index ffd31d1..0000000 --- a/SOURCES/0001-shell-recorder-Restore-cursor-recording.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 3182ad73c8f88628cb51a96feba0fc32ce7f01c9 Mon Sep 17 00:00:00 2001 -From: Illya Klymov -Date: Mon, 8 Jul 2019 03:29:36 +0000 -Subject: [PATCH] shell-recorder: Restore cursor recording - -Due to changes introduced in 5357e0a1 cursor recording interaction with -magnifier was reversed. This fix restores original correct behavior -Related issue: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1208 ---- - src/shell-recorder.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/shell-recorder.c b/src/shell-recorder.c -index 0203ecf1c..cf1cc336f 100644 ---- a/src/shell-recorder.c -+++ b/src/shell-recorder.c -@@ -465,7 +465,7 @@ recorder_record_frame (ShellRecorder *recorder, - - g_object_get (settings, "magnifier-active", &magnifier_active, NULL); - -- if (magnifier_active) -+ if (!magnifier_active) - recorder_draw_cursor (recorder, buffer); - } - --- -2.35.1 - diff --git a/SOURCES/0001-shellDBus-Add-a-DBus-method-to-load-a-single-extensi.patch b/SOURCES/0001-shellDBus-Add-a-DBus-method-to-load-a-single-extensi.patch deleted file mode 100644 index 5649937..0000000 --- a/SOURCES/0001-shellDBus-Add-a-DBus-method-to-load-a-single-extensi.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 660ebe0125b591355116934ee57b08010e05246c Mon Sep 17 00:00:00 2001 -From: Rui Matos -Date: Fri, 8 Nov 2013 11:36:04 +0100 -Subject: [PATCH] shellDBus: Add a DBus method to load a single extension - -This allows e.g. gnome-tweak-tool to install an extension from a zip -file and load it into the running shell. ---- - .../org.gnome.Shell.Extensions.xml | 13 +++++++++++++ - js/ui/shellDBus.js | 16 ++++++++++++++++ - 2 files changed, 29 insertions(+) - -diff --git a/data/dbus-interfaces/org.gnome.Shell.Extensions.xml b/data/dbus-interfaces/org.gnome.Shell.Extensions.xml -index 34a65af44..ce69439fc 100644 ---- a/data/dbus-interfaces/org.gnome.Shell.Extensions.xml -+++ b/data/dbus-interfaces/org.gnome.Shell.Extensions.xml -@@ -189,6 +189,19 @@ - --> - - -+ -+ -+ -+ -+ -+ -+ - - - -diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js -index 19d07acce..112d60feb 100644 ---- a/js/ui/shellDBus.js -+++ b/js/ui/shellDBus.js -@@ -341,6 +341,22 @@ var GnomeShellExtensions = class { - ExtensionDownloader.checkForUpdates(); - } - -+ LoadUserExtension(uuid) { -+ let extension = ExtensionUtils.extensions[uuid]; -+ if (extension) -+ return true; -+ -+ let dir = Gio.File.new_for_path(GLib.build_filenamev([global.userdatadir, 'extensions', uuid])); -+ try { -+ extension = ExtensionUtils.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER); -+ ExtensionSystem.loadExtension(extension); -+ } catch (e) { -+ log('Could not load user extension from %s'.format(dir.get_path())); -+ return false; -+ } -+ return true; -+ } -+ - get ShellVersion() { - return Config.PACKAGE_VERSION; - } --- -2.21.0 - diff --git a/SOURCES/0001-shellEntry-Determine-if-password-entry-from-content-.patch b/SOURCES/0001-shellEntry-Determine-if-password-entry-from-content-.patch deleted file mode 100644 index 4d5bbe1..0000000 --- a/SOURCES/0001-shellEntry-Determine-if-password-entry-from-content-.patch +++ /dev/null @@ -1,91 +0,0 @@ -From e6cd96a9f6a89f77ca0fab72aff8c56354b59f38 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 21 Aug 2019 15:01:34 -0400 -Subject: [PATCH 1/4] shellEntry: Determine if password entry from content - purpose not menu item - -Right now shellEntry decides whether or not it's a password entry based -on whether or not it has a "Show Text" context menu. - -That's a little roundabout, and gets in the way off providing lockdown -that disables the menu. - -This commit changes shellEntry to base whether or not it's a password -entry from it's input content purpose instead of from the presence -or absence of a context menu. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/687 ---- - js/ui/shellEntry.js | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js -index 53bd1daa1..cac4ec9c2 100644 ---- a/js/ui/shellEntry.js -+++ b/js/ui/shellEntry.js -@@ -14,61 +14,61 @@ var EntryMenu = class extends PopupMenu.PopupMenu { - - this._entry = entry; - this._clipboard = St.Clipboard.get_default(); - - // Populate menu - let item; - item = new PopupMenu.PopupMenuItem(_("Copy")); - item.connect('activate', this._onCopyActivated.bind(this)); - this.addMenuItem(item); - this._copyItem = item; - - item = new PopupMenu.PopupMenuItem(_("Paste")); - item.connect('activate', this._onPasteActivated.bind(this)); - this.addMenuItem(item); - this._pasteItem = item; - - this._passwordItem = null; - - Main.uiGroup.add_actor(this.actor); - this.actor.hide(); - } - - _makePasswordItem() { - let item = new PopupMenu.PopupMenuItem(''); - item.connect('activate', this._onPasswordActivated.bind(this)); - this.addMenuItem(item); - this._passwordItem = item; - } - - get isPassword() { -- return this._passwordItem != null; -+ return this._entry.input_purpose == Clutter.InputContentPurpose.PASSWORD; - } - - set isPassword(v) { - if (v == this.isPassword) - return; - - if (v) { - this._makePasswordItem(); - this._entry.input_purpose = Clutter.InputContentPurpose.PASSWORD; - } else { - this._passwordItem.destroy(); - this._passwordItem = null; - this._entry.input_purpose = Clutter.InputContentPurpose.NORMAL; - } - } - - open(animate) { - this._updatePasteItem(); - this._updateCopyItem(); - if (this._passwordItem) - this._updatePasswordItem(); - - super.open(animate); - this._entry.add_style_pseudo_class('focus'); - - let direction = St.DirectionType.TAB_FORWARD; - if (!this.actor.navigate_focus(null, direction, false)) - this.actor.grab_key_focus(); - } - --- -2.27.0 - diff --git a/SOURCES/0001-shellEntry-Disconnect-handler-on-destroy.patch b/SOURCES/0001-shellEntry-Disconnect-handler-on-destroy.patch deleted file mode 100644 index abf32bd..0000000 --- a/SOURCES/0001-shellEntry-Disconnect-handler-on-destroy.patch +++ /dev/null @@ -1,36 +0,0 @@ -From fd8c4dc073b121b1093d68472cac3292d2c6605c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 14 Jun 2021 17:59:39 +0200 -Subject: [PATCH] shellEntry: Disconnect handler on destroy - -Actors will get unmapped on destroy, so unless we disconnect from -the notify::mapped signal, the handler will run one last time and -try to access methods/properties on the invalidated actor. ---- - js/ui/shellEntry.js | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js -index 4a30b22f7..53bd1daa1 100644 ---- a/js/ui/shellEntry.js -+++ b/js/ui/shellEntry.js -@@ -186,7 +186,7 @@ class CapsLockWarning extends St.Label { - this._keymap = Clutter.get_default_backend().get_keymap(); - this._stateChangedId = 0; - -- this.connect('notify::mapped', () => { -+ const mappedId = this.connect('notify::mapped', () => { - if (this.is_mapped()) { - this._stateChangedId = this._keymap.connect('state-changed', - () => this._sync(true)); -@@ -201,6 +201,7 @@ class CapsLockWarning extends St.Label { - this.connect('destroy', () => { - if (this._stateChangedId) - this._keymap.disconnect(this._stateChangedId); -+ this.disconnect(mappedId); - }); - } - --- -2.31.1 - diff --git a/SOURCES/0001-st-bin-Disallow-st_bin_set_child-with-already-parent.patch b/SOURCES/0001-st-bin-Disallow-st_bin_set_child-with-already-parent.patch deleted file mode 100644 index 23c2606..0000000 --- a/SOURCES/0001-st-bin-Disallow-st_bin_set_child-with-already-parent.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 96404287bc4269dea7b037e7b178e54ebf616d47 Mon Sep 17 00:00:00 2001 -From: Daniel van Vugt -Date: Tue, 24 Nov 2020 17:34:08 +0800 -Subject: [PATCH] st-bin: Disallow st_bin_set_child with already-parented - children - -Not checking for this would result in `clutter_actor_add_child` -failing, but StBin keeping a copy in `priv->child`. So later on, -`st_bin_remove` would never be called on it and this assertion -would fail and crash the whole shell: - -``` -static void -st_bin_destroy (ClutterActor *actor) -{ - StBinPrivate *priv = st_bin_get_instance_private (ST_BIN (actor)); - - if (priv->child) - clutter_actor_destroy (priv->child); - g_assert (priv->child == NULL); - -``` - -By disallowing spurious `st_bin_set_child` calls we now prevent StBin -from entering such a corrupt state and the above assertion won't fail -anymore. - -Part-of: ---- - src/st/st-bin.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/src/st/st-bin.c b/src/st/st-bin.c -index f013909e8..7959a4e95 100644 ---- a/src/st/st-bin.c -+++ b/src/st/st-bin.c -@@ -434,6 +434,19 @@ st_bin_set_child (StBin *bin, - if (priv->child == child) - return; - -+ if (child) -+ { -+ ClutterActor *parent = clutter_actor_get_parent (child); -+ -+ if (parent) -+ { -+ g_warning ("%s: The provided 'child' actor %p already has a " -+ "(different) parent %p and can't be made a child of %p.", -+ G_STRFUNC, child, parent, bin); -+ return; -+ } -+ } -+ - if (priv->child) - clutter_actor_remove_child (CLUTTER_ACTOR (bin), priv->child); - --- -2.38.1 - diff --git a/SOURCES/0001-st-texture-cache-Cancel-pending-requests-on-icon-the.patch b/SOURCES/0001-st-texture-cache-Cancel-pending-requests-on-icon-the.patch deleted file mode 100644 index a6f6fdc..0000000 --- a/SOURCES/0001-st-texture-cache-Cancel-pending-requests-on-icon-the.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 1bf28eea64056846547ec33d783c7f2e0dad78a4 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Fri, 22 May 2020 22:53:39 +0200 -Subject: [PATCH] st/texture-cache: Cancel pending requests on icon-theme - changes - -As outlined in commit 36b8dcbe07, we can end up with wrong icons -if the icon theme changes right after a GTK theme change to/from -HighContrast triggered a theme reload. - -That's because when we reload icons for the new icon theme, there -are already pending requests due to the icon-style change; those -requests are simply re-used for the new icons, with the existing -icon infos from the old theme. - -The above commit applied a simple work-around by changing the -icon theme before the GTK theme, but that only works for the -HighContrast switch in our own UI. - -It turns out that Settings also uses the "wrong" order, so the -issue still reproduces with the Universal Access panel. - -So instead of relying on everything changing the settings in the -order we expect, cancel all ongoing requests on icon-theme changes. - -https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1277 ---- - src/st/st-texture-cache.c | 17 +++++++++++++++-- - 1 file changed, 15 insertions(+), 2 deletions(-) - -diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c -index 35e9d036f..6dc351282 100644 ---- a/src/st/st-texture-cache.c -+++ b/src/st/st-texture-cache.c -@@ -48,6 +48,8 @@ struct _StTextureCachePrivate - - /* File monitors to evict cache data on changes */ - GHashTable *file_monitors; /* char * -> GFileMonitor * */ -+ -+ GCancellable *cancellable; - }; - - static void st_texture_cache_dispose (GObject *object); -@@ -152,6 +154,9 @@ on_icon_theme_changed (StSettings *settings, - { - g_autofree gchar *theme; - -+ g_cancellable_cancel (cache->priv->cancellable); -+ g_cancellable_reset (cache->priv->cancellable); -+ - st_texture_cache_evict_icons (cache); - - g_object_get (settings, "gtk-icon-theme", &theme, NULL); -@@ -186,6 +191,8 @@ st_texture_cache_init (StTextureCache *self) - self->priv->file_monitors = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, - g_object_unref, g_object_unref); - -+ self->priv->cancellable = g_cancellable_new (); -+ - on_icon_theme_changed (settings, NULL, self); - } - -@@ -194,8 +201,11 @@ st_texture_cache_dispose (GObject *object) - { - StTextureCache *self = (StTextureCache*)object; - -+ g_cancellable_cancel (self->priv->cancellable); -+ - g_clear_object (&self->priv->settings); - g_clear_object (&self->priv->icon_theme); -+ g_clear_object (&self->priv->cancellable); - - g_clear_pointer (&self->priv->keyed_cache, g_hash_table_destroy); - g_clear_pointer (&self->priv->keyed_surface_cache, g_hash_table_destroy); -@@ -675,11 +685,14 @@ load_texture_async (StTextureCache *cache, - gtk_icon_info_load_symbolic_async (data->icon_info, - &foreground_color, &success_color, - &warning_color, &error_color, -- NULL, on_symbolic_icon_loaded, data); -+ cache->priv->cancellable, -+ on_symbolic_icon_loaded, data); - } - else - { -- gtk_icon_info_load_icon_async (data->icon_info, NULL, on_icon_loaded, data); -+ gtk_icon_info_load_icon_async (data->icon_info, -+ cache->priv->cancellable, -+ on_icon_loaded, data); - } - } - else --- -2.26.2 - diff --git a/SOURCES/0001-status-volume-Hide-sliders-initially.patch b/SOURCES/0001-status-volume-Hide-sliders-initially.patch deleted file mode 100644 index ab5a86e..0000000 --- a/SOURCES/0001-status-volume-Hide-sliders-initially.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 4e555e0efeb4b31918e199d29bee99b2a4ed1c8e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 11 May 2022 02:34:21 +0200 -Subject: [PATCH] status/volume: Hide sliders initially - -We update the visibility on state or stream changes, but those -changes may never happen if pipewire-pulse/pulseaudio isn't -available (for example when running as root). - -Hiding the sliders is preferable in that case to showing non-working -controls. ---- - js/ui/status/volume.js | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/js/ui/status/volume.js b/js/ui/status/volume.js -index d555b426e..ab5065683 100644 ---- a/js/ui/status/volume.js -+++ b/js/ui/status/volume.js -@@ -30,6 +30,7 @@ var StreamSlider = class { - this._control = control; - - this.item = new PopupMenu.PopupBaseMenuItem({ activate: false }); -+ this.item.actor.hide(); - - this._slider = new Slider.Slider(0); - --- -2.35.1 - diff --git a/SOURCES/0001-theme-Update-window-preview-style.patch b/SOURCES/0001-theme-Update-window-preview-style.patch deleted file mode 100644 index 2871e60..0000000 --- a/SOURCES/0001-theme-Update-window-preview-style.patch +++ /dev/null @@ -1,76 +0,0 @@ -From c68fd3c94c6debdbf11020940c5a6aaee8bc230d Mon Sep 17 00:00:00 2001 -From: Feichtmeier -Date: Fri, 15 Mar 2019 14:41:55 +0100 -Subject: [PATCH] theme: Update window preview style - - - simplify the close button to use blue, lighter blue and darker blue - solid disks for normal, hover and active states - - - use a milky, transparent white border for the hover effect of the border - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/461 ---- - data/theme/gnome-shell-sass/_common.scss | 29 ++++++++++++------------ - 1 file changed, 14 insertions(+), 15 deletions(-) - -diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss -index 9e0751c8c..8bf368f6e 100644 ---- a/data/theme/gnome-shell-sass/_common.scss -+++ b/data/theme/gnome-shell-sass/_common.scss -@@ -1164,25 +1164,23 @@ StScrollBar { - //close buttons - - .window-close { -- background-color: white; -+ background-color: $selected_bg_color; -+ color: white; - border-radius: 24px; -- border: 4px solid $selected_bg_color; -- box-shadow: inset 0 -4px 0 0 transparentize($selected_bg_color, 0.5); -- color: $selected_bg_color; -+ border: 2px solid $selected_bg_color; - height: 24px; - width: 24px; -- -shell-close-overlap: 14px; -+ -shell-close-overlap: 11px; -+ box-shadow: -1px 1px 5px 0px transparentize(black, 0.5); - - &:hover { -- background-color: $selected_bg_color; -- border-color: white; -- color: white; -+ background-color: lighten($selected_bg_color, 5%); -+ border-color: lighten($selected_bg_color, 5%); - } - - &:active { -- background-color: mix(white, $selected_bg_color, 75%); -- border-color: $selected_bg_color; -- color: $selected_bg_color; -+ background-color: darken($selected_bg_color, 5%); -+ border-color: darken($selected_bg_color, 5%); - } - } - -@@ -1247,13 +1245,14 @@ StScrollBar { - } - - .window-clone-border { -- border: 4px solid $selected_bg_color; -- border-radius: 4px; -+ $_bg: transparentize(white, 0.65); -+ border: 5px solid $_bg; -+ border-radius: 6px; - // For window decorations with round corners we can't match - // the exact shape when the window is scaled. So apply a shadow - // to fix that case -- box-shadow: inset 0px 0px 0px 1px $selected_bg_color; -- } -+ box-shadow: inset 0 0 0 1px $_bg; -+} - .window-caption { - spacing: 25px; - color: $selected_fg_color; --- -2.31.1 - diff --git a/SOURCES/0001-windowMenu-Ignore-release.patch b/SOURCES/0001-windowMenu-Ignore-release.patch deleted file mode 100644 index 6eedee2..0000000 --- a/SOURCES/0001-windowMenu-Ignore-release.patch +++ /dev/null @@ -1,26 +0,0 @@ -From e1eb24fdf731af8736cdb76dc28aa2b10679aa5f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Thu, 28 Sep 2023 14:34:24 +0200 -Subject: [PATCH] windowMenu: Ignore release - -If the menu was open on button-press, make sure it is kept open -until explicitly dismissed, regardless of the pointer position. ---- - js/ui/windowMenu.js | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/js/ui/windowMenu.js b/js/ui/windowMenu.js -index f8eb4398c3..2ec11c7879 100644 ---- a/js/ui/windowMenu.js -+++ b/js/ui/windowMenu.js -@@ -205,6 +205,7 @@ var WindowMenuManager = class { - let menu = new WindowMenu(window, this._sourceActor); - - this._manager.addMenu(menu); -+ this._manager.ignoreRelease(); - - menu.connect('activate', () => { - window.check_alive(global.get_current_time()); --- -2.41.0 - diff --git a/SOURCES/0001-workspace-Pass-device-to-startDrag.patch b/SOURCES/0001-workspace-Pass-device-to-startDrag.patch deleted file mode 100644 index 7b4afba..0000000 --- a/SOURCES/0001-workspace-Pass-device-to-startDrag.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 9115f6e7962b97c3ee2fbef7b195b7116e62c070 Mon Sep 17 00:00:00 2001 -From: Carlos Garnacho -Date: Fri, 13 Dec 2019 18:14:51 +0100 -Subject: [PATCH] workspace: Pass device to startDrag() - -This is necessary to make DnD operations work from tablet devices on -wayland, as it's not the same onscreen pointer sprite than mice. Fixes -window DnD in the overview on tablet devices, no longer having them stick -to the wrong pointer. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/897 ---- - js/ui/workspace.js | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/js/ui/workspace.js b/js/ui/workspace.js -index 1e9bedc28..d470f7f40 100644 ---- a/js/ui/workspace.js -+++ b/js/ui/workspace.js -@@ -431,7 +431,7 @@ var WindowClone = GObject.registerClass({ - return; - let [x, y] = action.get_coords(); - action.release(); -- this._draggable.startDrag(x, y, global.get_current_time(), this._dragTouchSequence); -+ this._draggable.startDrag(x, y, global.get_current_time(), this._dragTouchSequence, event.get_device()); - }); - } else { - this.emit('show-chrome'); --- -2.23.0 - diff --git a/SOURCES/0001-workspacesView-Work-around-spurious-allocation-chang.patch b/SOURCES/0001-workspacesView-Work-around-spurious-allocation-chang.patch deleted file mode 100644 index f51e8e2..0000000 --- a/SOURCES/0001-workspacesView-Work-around-spurious-allocation-chang.patch +++ /dev/null @@ -1,37 +0,0 @@ -From b69b404118852f7955f60d1814f5e19ad61ce449 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Fri, 12 Jul 2019 03:26:51 +0000 -Subject: [PATCH] workspacesView: Work around spurious allocation changes - -For some reason, people are still seeing those after commit d5ebd8c8. -While this is something we really should figure out, we can work around -the issue by keeping the view actors hidden until the update is complete. - -https://gitlab.gnome.org/GNOME/gnome-shell/issues/1065 ---- - js/ui/workspacesView.js | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js -index 069937d5a..e302296a6 100644 ---- a/js/ui/workspacesView.js -+++ b/js/ui/workspacesView.js -@@ -666,10 +666,15 @@ var WorkspacesDisplay = class { - this._scrollValueChanged.bind(this)); - } - -+ // HACK: Avoid spurious allocation changes while updating views -+ view.actor.hide(); -+ - this._workspacesViews.push(view); - Main.layoutManager.overviewGroup.add_actor(view.actor); - } - -+ this._workspacesViews.forEach(v => v.actor.show()); -+ - this._updateWorkspacesFullGeometry(); - this._updateWorkspacesActualGeometry(); - } --- -2.21.0 - diff --git a/SOURCES/0002-background-rebuild-background-not-just-animation-on-.patch b/SOURCES/0002-background-rebuild-background-not-just-animation-on-.patch deleted file mode 100644 index 3b436cb..0000000 --- a/SOURCES/0002-background-rebuild-background-not-just-animation-on-.patch +++ /dev/null @@ -1,31 +0,0 @@ -From f27c4224aa96975ae44641612f5fff3772f5c294 Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Mon, 22 Aug 2022 13:06:05 +0200 -Subject: [PATCH] [PATCH 2/4] background: rebuild background, not just - animation on resume - -Previously, we would only refresh the animation on resume -(to handle clock skew). - -But we actually need to rebuild the background, too, on nvidia, -so we should just do a full background change. ---- - js/ui/background.js | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/js/ui/background.js b/js/ui/background.js -index 2a404ae..dd11e3e 100644 ---- a/js/ui/background.js -+++ b/js/ui/background.js -@@ -254,7 +254,7 @@ var Background = class Background { - (lm, aboutToSuspend) => { - if (aboutToSuspend) - return; -- this._refreshAnimation(); -+ this.emit('changed'); - }); - - this._settingsChangedSignalId = --- -2.35.3 - diff --git a/SOURCES/0002-environment-Fix-date-conversion.patch b/SOURCES/0002-environment-Fix-date-conversion.patch deleted file mode 100644 index 2f6b5bd..0000000 --- a/SOURCES/0002-environment-Fix-date-conversion.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 189add05c07fe9d9bed6c1399b30e51a4a934bd3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 2 Mar 2020 13:46:04 +0100 -Subject: [PATCH 2/6] environment: Fix date conversion - -This is a regression from commit 06b690ff21204: - -GLib.DateTime.new() expects the full four-digit year, so passing -the abbreviated year from Date() will result in a bogus datetime. - -Today is *not* Saturday March 2nd, 120 ... - -https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1061 ---- - js/ui/environment.js | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/js/ui/environment.js b/js/ui/environment.js -index f3f2d17c7..a9cc16dee 100644 ---- a/js/ui/environment.js -+++ b/js/ui/environment.js -@@ -126,7 +126,7 @@ function init() { - _localTimeZone = GLib.TimeZone.new_local(); - - let dt = GLib.DateTime.new(_localTimeZone, -- this.getYear(), -+ this.getFullYear(), - this.getMonth() + 1, - this.getDate(), - this.getHours(), --- -2.26.2 - diff --git a/SOURCES/0002-extensionSystem-Get-rid-of-_enabled-boolean-optimiza.patch b/SOURCES/0002-extensionSystem-Get-rid-of-_enabled-boolean-optimiza.patch deleted file mode 100644 index 5dba07a..0000000 --- a/SOURCES/0002-extensionSystem-Get-rid-of-_enabled-boolean-optimiza.patch +++ /dev/null @@ -1,237 +0,0 @@ -From b70cf463e08bff43b242b851fc7c79244f54e76b Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 10 Aug 2021 13:25:57 -0400 -Subject: [PATCH 2/4] extensionSystem: Get rid of _enabled boolean optimization - -At the moment a session mode either allows extensions or it doesn't. -If it allows extensions, then the entire available list of -configured extensions get enabled as soon as the session mode is -entered. - -Since enabling or disabling extensions is an all or nothing situation, -the code tracks whether extensions are already enabled when entering -the session mode, and if so, avoids iterating through the extension list -needlessly. It does this using a boolean named _enabled. - -In the future, the extensions themselves will be given some say on -whether or not they should be enabled in a given session mode. This -means, the configured extension list may contain extensions that -shouldn't be enabled for a given session mode, and the _enabled boolean -will no longer be appropriated. - -This commit drops the _enabled boolean optimization. ---- - js/ui/extensionSystem.js | 13 ------------- - 1 file changed, 13 deletions(-) - -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index 77929f2a6..05630ed54 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -1,53 +1,52 @@ - // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - - const { GLib, Gio, GObject, St } = imports.gi; - const Signals = imports.signals; - - const ExtensionDownloader = imports.ui.extensionDownloader; - const ExtensionUtils = imports.misc.extensionUtils; - const FileUtils = imports.misc.fileUtils; - const Main = imports.ui.main; - const MessageTray = imports.ui.messageTray; - - const { ExtensionState, ExtensionType } = ExtensionUtils; - - const ENABLED_EXTENSIONS_KEY = 'enabled-extensions'; - const DISABLE_USER_EXTENSIONS_KEY = 'disable-user-extensions'; - const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validation'; - - const UPDATE_CHECK_TIMEOUT = 24 * 60 * 60; // 1 day in seconds - - var ExtensionManager = class { - constructor() { - this._initted = false; -- this._enabled = false; - this._updateNotified = false; - - this._extensions = new Map(); - this._enabledExtensions = []; - this._extensionOrder = []; - - Main.sessionMode.connect('updated', this._sessionUpdated.bind(this)); - } - - init() { - this._installExtensionUpdates(); - this._sessionUpdated(); - - GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, UPDATE_CHECK_TIMEOUT, () => { - ExtensionDownloader.checkForUpdates(); - return GLib.SOURCE_CONTINUE; - }); - ExtensionDownloader.checkForUpdates(); - } - - lookup(uuid) { - return this._extensions.get(uuid); - } - - getUuids() { - return [...this._extensions.keys()]; - } - - _callExtensionDisable(uuid) { - let extension = this.lookup(uuid); -@@ -375,63 +374,60 @@ var ExtensionManager = class { - let hasError = - extension.state == ExtensionState.ERROR || - extension.state == ExtensionState.OUT_OF_DATE; - - let isMode = this._getModeExtensions().includes(extension.uuid); - let modeOnly = global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY); - - extension.canChange = - !hasError && - global.settings.is_writable(ENABLED_EXTENSIONS_KEY) && - (isMode || !modeOnly); - } - - _getEnabledExtensions() { - let extensions = this._getModeExtensions(); - - if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY)) - return extensions; - - return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY)); - } - - _onUserExtensionsEnabledChanged() { - this._onEnabledExtensionsChanged(); - this._onSettingsWritableChanged(); - } - - _onEnabledExtensionsChanged() { - let newEnabledExtensions = this._getEnabledExtensions(); - -- if (!this._enabled) -- return; -- - // Find and enable all the newly enabled extensions: UUIDs found in the - // new setting, but not in the old one. - newEnabledExtensions.filter( - uuid => !this._enabledExtensions.includes(uuid) - ).forEach(uuid => { - this._callExtensionEnable(uuid); - }); - - // Find and disable all the newly disabled extensions: UUIDs found in the - // old setting, but not in the new one. - this._enabledExtensions.filter( - item => !newEnabledExtensions.includes(item) - ).forEach(uuid => { - this._callExtensionDisable(uuid); - }); - - this._enabledExtensions = newEnabledExtensions; - } - - _onSettingsWritableChanged() { - for (let extension of this._extensions.values()) { - this._updateCanChange(extension); - this.emit('extension-state-changed', extension); - } - } - - _onVersionValidationChanged() { - // we want to reload all extensions, but only enable - // extensions when allowed by the sessionMode, so - // temporarily disable them all -@@ -482,85 +478,76 @@ var ExtensionManager = class { - - this._enabledExtensions = this._getEnabledExtensions(); - - let perUserDir = Gio.File.new_for_path(global.userdatadir); - FileUtils.collectFromDatadirs('extensions', true, (dir, info) => { - let fileType = info.get_file_type(); - if (fileType != Gio.FileType.DIRECTORY) - return; - let uuid = info.get_name(); - let existing = this.lookup(uuid); - if (existing) { - log(`Extension ${uuid} already installed in ${existing.path}. ${dir.get_path()} will not be loaded`); - return; - } - - let extension; - let type = dir.has_prefix(perUserDir) - ? ExtensionType.PER_USER - : ExtensionType.SYSTEM; - try { - extension = this.createExtensionObject(uuid, dir, type); - } catch (e) { - logError(e, `Could not load extension ${uuid}`); - return; - } - this.loadExtension(extension); - }); - } - - _enableAllExtensions() { -- if (this._enabled) -- return; -- - if (!this._initted) { - this._loadExtensions(); - this._initted = true; - } else { - this._enabledExtensions.forEach(uuid => { - this._callExtensionEnable(uuid); - }); - } -- this._enabled = true; - } - - _disableAllExtensions() { -- if (!this._enabled) -- return; -- - if (this._initted) { - this._extensionOrder.slice().reverse().forEach(uuid => { - this._callExtensionDisable(uuid); - }); - } -- -- this._enabled = false; - } - - _sessionUpdated() { - // For now sessionMode.allowExtensions controls extensions from both the - // 'enabled-extensions' preference and the sessionMode.enabledExtensions - // property; it might make sense to make enabledExtensions independent - // from allowExtensions in the future - if (Main.sessionMode.allowExtensions) { - // Take care of added or removed sessionMode extensions - this._onEnabledExtensionsChanged(); - this._enableAllExtensions(); - } else { - this._disableAllExtensions(); - } - } - }; - Signals.addSignalMethods(ExtensionManager.prototype); - - class ExtensionUpdateSource extends MessageTray.Source { - constructor() { - const appSys = Shell.AppSystem.get_default(); - this._app = appSys.lookup_app('gnome-shell-extension-prefs.desktop'); - - super(this._app.get_name()); - } - - getIcon() { - return this._app.app_info.get_icon(); - } - --- -2.27.0 - diff --git a/SOURCES/0002-gdmUtil-enable-support-for-GDM-s-ChoiceList-PAM-exte.patch b/SOURCES/0002-gdmUtil-enable-support-for-GDM-s-ChoiceList-PAM-exte.patch deleted file mode 100644 index b396e1c..0000000 --- a/SOURCES/0002-gdmUtil-enable-support-for-GDM-s-ChoiceList-PAM-exte.patch +++ /dev/null @@ -1,267 +0,0 @@ -From c3ab03f8721ea96df6ac91c0393ed13ba750ab7e Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 17 Jul 2017 16:48:03 -0400 -Subject: [PATCH 2/2] gdmUtil: enable support for GDM's ChoiceList PAM - extension - -This commit hooks up support for GDM's ChoiceList PAM extension. ---- - js/gdm/authPrompt.js | 74 ++++++++++++++++++++++++++++++++++++++++++- - js/gdm/loginDialog.js | 5 +++ - js/gdm/util.js | 28 ++++++++++++++++ - js/ui/unlockDialog.js | 9 +++++- - 4 files changed, 114 insertions(+), 2 deletions(-) - -diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index cf77b3f26..71069e93b 100644 ---- a/js/gdm/authPrompt.js -+++ b/js/gdm/authPrompt.js -@@ -4,6 +4,7 @@ const { Clutter, GLib, Pango, Shell, St } = imports.gi; - const Signals = imports.signals; - - const Animation = imports.ui.animation; -+const AuthList = imports.gdm.authList; - const Batch = imports.gdm.batch; - const GdmUtil = imports.gdm.util; - const Meta = imports.gi.Meta; -@@ -54,6 +55,7 @@ var AuthPrompt = class { - - this._userVerifier.connect('ask-question', this._onAskQuestion.bind(this)); - this._userVerifier.connect('show-message', this._onShowMessage.bind(this)); -+ this._userVerifier.connect('show-choice-list', this._onShowChoiceList.bind(this)); - this._userVerifier.connect('verification-failed', this._onVerificationFailed.bind(this)); - this._userVerifier.connect('verification-complete', this._onVerificationComplete.bind(this)); - this._userVerifier.connect('reset', this._onReset.bind(this)); -@@ -116,6 +118,28 @@ var AuthPrompt = class { - - this.actor.add(this._timedLoginIndicator); - -+ this._authList = new AuthList.AuthList(); -+ this._authList.connect('activate', (list, key) => { -+ this._authList.actor.reactive = false; -+ Tweener.addTween(this._authList.actor, -+ { opacity: 0, -+ time: MESSAGE_FADE_OUT_ANIMATION_TIME, -+ transition: 'easeOutQuad', -+ onComplete: () => { -+ this._authList.clear(); -+ this._authList.actor.hide(); -+ this._userVerifier.selectChoice(this._queryingService, key); -+ -+ } -+ }); -+ }); -+ this._authList.actor.hide(); -+ this.actor.add(this._authList.actor, -+ { expand: true, -+ x_fill: true, -+ y_fill: false, -+ x_align: St.Align.START }); -+ - this._message = new St.Label({ opacity: 0, - styleClass: 'login-dialog-message' }); - this._message.clutter_text.line_wrap = true; -@@ -258,6 +282,21 @@ var AuthPrompt = class { - this.emit('prompted'); - } - -+ _onShowChoiceList(userVerifier, serviceName, promptMessage, choiceList) { -+ if (this._queryingService) -+ this.clear(); -+ -+ this._queryingService = serviceName; -+ -+ if (this._preemptiveAnswer) -+ this._preemptiveAnswer = null; -+ -+ this.nextButton.label = _("Next"); -+ this.setChoiceList(promptMessage, choiceList); -+ this.updateSensitivity(true); -+ this.emit('prompted'); -+ } -+ - _onOVirtUserAuthenticated() { - if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED) - this.reset(); -@@ -386,6 +425,8 @@ var AuthPrompt = class { - clear() { - this._entry.text = ''; - this.stopSpinning(); -+ this._authList.clear(); -+ this._authList.actor.hide(); - } - - setPasswordChar(passwordChar) { -@@ -401,12 +442,42 @@ var AuthPrompt = class { - - this._label.set_text(question); - -+ this._authList.actor.hide(); - this._label.show(); - this._entry.show(); - - this._entry.grab_key_focus(); - } - -+ _fadeInChoiceList() { -+ this._authList.actor.opacity = 0; -+ this._authList.actor.show(); -+ this._authList.actor.reactive = false; -+ Tweener.addTween(this._authList.actor, -+ { opacity: 255, -+ time: MESSAGE_FADE_OUT_ANIMATION_TIME, -+ transition: 'easeOutQuad', -+ onComplete: () => { -+ this._authList.actor.reactive = true; -+ } -+ }); -+ } -+ -+ setChoiceList(promptMessage, choiceList) { -+ this._authList.clear(); -+ this._authList.label.text = promptMessage; -+ for (let key in choiceList) { -+ let text = choiceList[key]; -+ this._authList.addItem(key, text); -+ } -+ -+ this._label.hide(); -+ this._entry.hide(); -+ if (this._message.text == "") -+ this._message.hide(); -+ this._fadeInChoiceList(); -+ } -+ - getAnswer() { - let text; - -@@ -442,6 +513,7 @@ var AuthPrompt = class { - else - this._message.remove_style_class_name('login-dialog-message-hint'); - -+ this._message.show(); - if (message) { - Tweener.removeTweens(this._message); - this._message.text = message; -@@ -457,7 +529,7 @@ var AuthPrompt = class { - } - - updateSensitivity(sensitive) { -- this._updateNextButtonSensitivity(sensitive && (this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING)); -+ this._updateNextButtonSensitivity(sensitive && !this._authList.actor.visible && (this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING)); - this._entry.reactive = sensitive; - this._entry.clutter_text.editable = sensitive; - } -diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js -index 9aaa013d8..942f5a0e5 100644 ---- a/js/gdm/loginDialog.js -+++ b/js/gdm/loginDialog.js -@@ -406,6 +406,11 @@ var LoginDialog = GObject.registerClass({ - this._userManager = AccountsService.UserManager.get_default() - this._gdmClient = new Gdm.Client(); - -+ try { -+ this._gdmClient.set_enabled_extensions([Gdm.UserVerifierChoiceList.interface_info().name]); -+ } catch(e) { -+ } -+ - this._settings = new Gio.Settings({ schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA }); - - this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY, -diff --git a/js/gdm/util.js b/js/gdm/util.js -index 6e940d2ab..9e249139d 100644 ---- a/js/gdm/util.js -+++ b/js/gdm/util.js -@@ -192,6 +192,10 @@ var ShellUserVerifier = class { - if (this._userVerifier) { - this._userVerifier.run_dispose(); - this._userVerifier = null; -+ if (this._userVerifierChoiceList) { -+ this._userVerifierChoiceList.run_dispose(); -+ this._userVerifierChoiceList = null; -+ } - } - } - -@@ -219,6 +223,10 @@ var ShellUserVerifier = class { - this._oVirtCredentialsManager = null; - } - -+ selectChoice(serviceName, key) { -+ this._userVerifierChoiceList.call_select_choice(serviceName, key, this._cancellable, null); -+ } -+ - answerQuery(serviceName, answer) { - if (!this.hasPendingMessages) { - this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null); -@@ -362,6 +370,11 @@ var ShellUserVerifier = class { - return; - } - -+ if (client.get_user_verifier_choice_list) -+ this._userVerifierChoiceList = client.get_user_verifier_choice_list(); -+ else -+ this._userVerifierChoiceList = null; -+ - this.reauthenticating = true; - this._connectSignals(); - this._beginVerification(); -@@ -379,6 +392,11 @@ var ShellUserVerifier = class { - return; - } - -+ if (client.get_user_verifier_choice_list) -+ this._userVerifierChoiceList = client.get_user_verifier_choice_list(); -+ else -+ this._userVerifierChoiceList = null; -+ - this._connectSignals(); - this._beginVerification(); - this._hold.release(); -@@ -392,6 +410,9 @@ var ShellUserVerifier = class { - this._userVerifier.connect('conversation-stopped', this._onConversationStopped.bind(this)); - this._userVerifier.connect('reset', this._onReset.bind(this)); - this._userVerifier.connect('verification-complete', this._onVerificationComplete.bind(this)); -+ -+ if (this._userVerifierChoiceList) -+ this._userVerifierChoiceList.connect('choice-query', this._onChoiceListQuery.bind(this)); - } - - _getForegroundService() { -@@ -468,6 +489,13 @@ var ShellUserVerifier = class { - this._startService(FINGERPRINT_SERVICE_NAME); - } - -+ _onChoiceListQuery(client, serviceName, promptMessage, list) { -+ if (!this.serviceIsForeground(serviceName)) -+ return; -+ -+ this.emit('show-choice-list', serviceName, promptMessage, list.deep_unpack()); -+ } -+ - _onInfo(client, serviceName, info) { - if (this.serviceIsForeground(serviceName)) { - this._queueMessage(info, MessageType.INFO); -diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js -index 5c9d46021..4b0470f4b 100644 ---- a/js/ui/unlockDialog.js -+++ b/js/ui/unlockDialog.js -@@ -33,7 +33,14 @@ var UnlockDialog = class { - y_expand: true }); - this.actor.add_child(this._promptBox); - -- this._authPrompt = new AuthPrompt.AuthPrompt(new Gdm.Client(), AuthPrompt.AuthPromptMode.UNLOCK_ONLY); -+ this._gdmClient = new Gdm.Client(); -+ -+ try { -+ this._gdmClient.set_enabled_extensions([Gdm.UserVerifierChoiceList.interface_info().name]); -+ } catch(e) { -+ } -+ -+ this._authPrompt = new AuthPrompt.AuthPrompt(this._gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_ONLY); - this._authPrompt.connect('failed', this._fail.bind(this)); - this._authPrompt.connect('cancelled', this._fail.bind(this)); - this._authPrompt.connect('reset', this._onReset.bind(this)); --- -2.21.0 - diff --git a/SOURCES/0002-shellEntry-Give-password-menu-item-text-when-it-s-cr.patch b/SOURCES/0002-shellEntry-Give-password-menu-item-text-when-it-s-cr.patch deleted file mode 100644 index 55b3c6f..0000000 --- a/SOURCES/0002-shellEntry-Give-password-menu-item-text-when-it-s-cr.patch +++ /dev/null @@ -1,92 +0,0 @@ -From de7df6c7248c39d7cce1c70485df72a398da92a3 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 21 Aug 2019 15:48:33 -0400 -Subject: [PATCH 2/4] shellEntry: Give password menu item text when it's - created - -At the moment, the "Show Text" menu item is only given its text -at the time the menu is opened. This is because the text might -be "Hide Text" or "Show Text" depending on state, so the text -is set up lazily. - -That behavior means the menu item can't get added after the -menu is already shown, which is something we'ree going to need -in the future to support lockdown of the "Show Text" item. - -This commit ensures the menu item is given text when it's first -created, in addition to when the menu is opened. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/687 ---- - js/ui/shellEntry.js | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js -index cac4ec9c2..603a9c64a 100644 ---- a/js/ui/shellEntry.js -+++ b/js/ui/shellEntry.js -@@ -11,60 +11,61 @@ const Tweener = imports.ui.tweener; - var EntryMenu = class extends PopupMenu.PopupMenu { - constructor(entry) { - super(entry, 0, St.Side.TOP); - - this._entry = entry; - this._clipboard = St.Clipboard.get_default(); - - // Populate menu - let item; - item = new PopupMenu.PopupMenuItem(_("Copy")); - item.connect('activate', this._onCopyActivated.bind(this)); - this.addMenuItem(item); - this._copyItem = item; - - item = new PopupMenu.PopupMenuItem(_("Paste")); - item.connect('activate', this._onPasteActivated.bind(this)); - this.addMenuItem(item); - this._pasteItem = item; - - this._passwordItem = null; - - Main.uiGroup.add_actor(this.actor); - this.actor.hide(); - } - - _makePasswordItem() { - let item = new PopupMenu.PopupMenuItem(''); - item.connect('activate', this._onPasswordActivated.bind(this)); - this.addMenuItem(item); - this._passwordItem = item; -+ this._updatePasswordItem(); - } - - get isPassword() { - return this._entry.input_purpose == Clutter.InputContentPurpose.PASSWORD; - } - - set isPassword(v) { - if (v == this.isPassword) - return; - - if (v) { - this._makePasswordItem(); - this._entry.input_purpose = Clutter.InputContentPurpose.PASSWORD; - } else { - this._passwordItem.destroy(); - this._passwordItem = null; - this._entry.input_purpose = Clutter.InputContentPurpose.NORMAL; - } - } - - open(animate) { - this._updatePasteItem(); - this._updateCopyItem(); - if (this._passwordItem) - this._updatePasswordItem(); - - super.open(animate); - this._entry.add_style_pseudo_class('focus'); - - let direction = St.DirectionType.TAB_FORWARD; --- -2.27.0 - diff --git a/SOURCES/0003-extensionSystem-Allow-extensions-to-run-on-the-login.patch b/SOURCES/0003-extensionSystem-Allow-extensions-to-run-on-the-login.patch deleted file mode 100644 index c2dcedb..0000000 --- a/SOURCES/0003-extensionSystem-Allow-extensions-to-run-on-the-login.patch +++ /dev/null @@ -1,393 +0,0 @@ -From 7300ae2eac743fa06f40f6459ac8fbf739ab28ea Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 10 Aug 2021 15:03:50 -0400 -Subject: [PATCH 3/4] extensionSystem: Allow extensions to run on the login - screen - -At the moment it's not realy possible to extend the login screen to do -things it doesn't have built-in support for. This means in order -to support niche use cases, those cases have to change the main -code base. For instance, oVirt and Vmware deployments want to be able -to automaticaly log in guest VMs when a user pre-authenticates through a -console on a management host. To support those use cases, we added -code to the login screen directly, even though most machines will never -be associated with oVirt or Vmware management hosts. - -We also get requests from e.g. government users that need certain features -at the login screen that wouldn't get used much outside of government -deployments. For instance, we've gotten requests that a machine contains -prominently displays that it has "Top Secret" information. - -All of these use cases seem like they would better handled via -extensions that could be installed in the specific deployments. The -problem is extensions only run in the user session, and get -disabled at the login screen automatically. - -This commit changes that. Now extensions can specify in their metadata -via a new sessionModes property, which modes that want to run in. For -backward compatibility, if an extension doesn't specify which session -modes it works in, its assumed the extension only works in the user -session. ---- - js/ui/extensionSystem.js | 43 ++++++++++++++++++++++++++++++++++++---- - 1 file changed, 39 insertions(+), 4 deletions(-) - -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index 05630ed54..dfe82821e 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -21,119 +21,147 @@ var ExtensionManager = class { - constructor() { - this._initted = false; - this._updateNotified = false; - - this._extensions = new Map(); - this._enabledExtensions = []; - this._extensionOrder = []; - - Main.sessionMode.connect('updated', this._sessionUpdated.bind(this)); - } - - init() { - this._installExtensionUpdates(); - this._sessionUpdated(); - - GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, UPDATE_CHECK_TIMEOUT, () => { - ExtensionDownloader.checkForUpdates(); - return GLib.SOURCE_CONTINUE; - }); - ExtensionDownloader.checkForUpdates(); - } - - lookup(uuid) { - return this._extensions.get(uuid); - } - - getUuids() { - return [...this._extensions.keys()]; - } - -+ _extensionSupportsSessionMode(uuid) { -+ let extension = this.lookup(uuid); -+ -+ if (!extension) -+ return false; -+ -+ if (extension.sessionModes.includes(Main.sessionMode.currentMode)) -+ return true; -+ -+ if (extension.sessionModes.includes(Main.sessionMode.parentMode)) -+ return true; -+ -+ return false; -+ } -+ -+ _sessionModeCanUseExtension(uuid) { -+ if (!Main.sessionMode.allowExtensions) -+ return false; -+ -+ if (!this._extensionSupportsSessionMode(uuid)) -+ return false; -+ -+ return true; -+ } -+ - _callExtensionDisable(uuid) { - let extension = this.lookup(uuid); - if (!extension) - return; - - if (extension.state != ExtensionState.ENABLED) - return; - - // "Rebase" the extension order by disabling and then enabling extensions - // in order to help prevent conflicts. - - // Example: - // order = [A, B, C, D, E] - // user disables C - // this should: disable E, disable D, disable C, enable D, enable E - - let orderIdx = this._extensionOrder.indexOf(uuid); - let order = this._extensionOrder.slice(orderIdx + 1); - let orderReversed = order.slice().reverse(); - - for (let i = 0; i < orderReversed.length; i++) { - let uuid = orderReversed[i]; - try { - this.lookup(uuid).stateObj.disable(); - } catch (e) { - this.logExtensionError(uuid, e); - } - } - - if (extension.stylesheet) { - let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); - theme.unload_stylesheet(extension.stylesheet); - delete extension.stylesheet; - } - - try { - extension.stateObj.disable(); - } catch(e) { - this.logExtensionError(uuid, e); - } - - for (let i = 0; i < order.length; i++) { - let uuid = order[i]; - try { - this.lookup(uuid).stateObj.enable(); - } catch (e) { - this.logExtensionError(uuid, e); - } - } - - this._extensionOrder.splice(orderIdx, 1); - - if (extension.state != ExtensionState.ERROR) { - extension.state = ExtensionState.DISABLED; - this.emit('extension-state-changed', extension); - } - } - - _callExtensionEnable(uuid) { -+ if (!this._sessionModeCanUseExtension(uuid)) -+ return; -+ - let extension = this.lookup(uuid); - if (!extension) - return; - - if (extension.state == ExtensionState.INITIALIZED) - this._callExtensionInit(uuid); - - if (extension.state != ExtensionState.DISABLED) - return; - - this._extensionOrder.push(uuid); - - let stylesheetNames = [global.session_mode + '.css', 'stylesheet.css']; - let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); - for (let i = 0; i < stylesheetNames.length; i++) { - try { - let stylesheetFile = extension.dir.get_child(stylesheetNames[i]); - theme.load_stylesheet(stylesheetFile); - extension.stylesheet = stylesheetFile; - break; - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) - continue; // not an error - log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`); - return; - } - } - - try { - extension.stateObj.enable(); -@@ -231,61 +259,62 @@ var ExtensionManager = class { - throw new Error(`Failed to load metadata.json: ${e}`); - } - let meta; - try { - meta = JSON.parse(metadataContents); - } catch (e) { - throw new Error(`Failed to parse metadata.json: ${e}`); - } - - let requiredProperties = ['uuid', 'name', 'description', 'shell-version']; - for (let i = 0; i < requiredProperties.length; i++) { - let prop = requiredProperties[i]; - if (!meta[prop]) { - throw new Error(`missing "${prop}" property in metadata.json`); - } - } - - if (uuid != meta.uuid) { - throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name "${uuid}"`); - } - - let extension = { - metadata: meta, - uuid: meta.uuid, - type, - dir, - path: dir.get_path(), - error: '', - hasPrefs: dir.get_child('prefs.js').query_exists(null), - hasUpdate: false, -- canChange: false -+ canChange: false, -+ sessionModes: meta['session-modes'] ? meta['session-modes'] : [ 'user' ], - }; - this._extensions.set(uuid, extension); - - return extension; - } - - loadExtension(extension) { - // Default to error, we set success as the last step - extension.state = ExtensionState.ERROR; - - let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY); - - if (checkVersion && ExtensionUtils.isOutOfDate(extension)) { - extension.state = ExtensionState.OUT_OF_DATE; - } else { - let enabled = this._enabledExtensions.includes(extension.uuid); - if (enabled) { - if (!this._callExtensionInit(extension.uuid)) - return; - if (extension.state == ExtensionState.DISABLED) - this._callExtensionEnable(extension.uuid); - } else { - extension.state = ExtensionState.INITIALIZED; - } - } - - this._updateCanChange(extension); - this.emit('extension-state-changed', extension); - } - -@@ -296,60 +325,63 @@ var ExtensionManager = class { - this._callExtensionDisable(extension.uuid); - - extension.state = ExtensionState.UNINSTALLED; - this.emit('extension-state-changed', extension); - - this._extensions.delete(extension.uuid); - return true; - } - - reloadExtension(oldExtension) { - // Grab the things we'll need to pass to createExtensionObject - // to reload it. - let { uuid: uuid, dir: dir, type: type } = oldExtension; - - // Then unload the old extension. - this.unloadExtension(oldExtension); - - // Now, recreate the extension and load it. - let newExtension; - try { - newExtension = this.createExtensionObject(uuid, dir, type); - } catch (e) { - this.logExtensionError(uuid, e); - return; - } - - this.loadExtension(newExtension); - } - - _callExtensionInit(uuid) { -+ if (!this._sessionModeCanUseExtension(uuid)) -+ return false; -+ - let extension = this.lookup(uuid); - let dir = extension.dir; - - if (!extension) - throw new Error("Extension was not properly created. Call loadExtension first"); - - let extensionJs = dir.get_child('extension.js'); - if (!extensionJs.query_exists(null)) { - this.logExtensionError(uuid, new Error('Missing extension.js')); - return false; - } - - let extensionModule; - let extensionState = null; - - ExtensionUtils.installImporter(extension); - try { - extensionModule = extension.imports.extension; - } catch(e) { - this.logExtensionError(uuid, e); - return false; - } - - if (extensionModule.init) { - try { - extensionState = extensionModule.init(extension); - } catch (e) { - this.logExtensionError(uuid, e); - return false; - } -@@ -377,69 +409,72 @@ var ExtensionManager = class { - - let isMode = this._getModeExtensions().includes(extension.uuid); - let modeOnly = global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY); - - extension.canChange = - !hasError && - global.settings.is_writable(ENABLED_EXTENSIONS_KEY) && - (isMode || !modeOnly); - } - - _getEnabledExtensions() { - let extensions = this._getModeExtensions(); - - if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY)) - return extensions; - - return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY)); - } - - _onUserExtensionsEnabledChanged() { - this._onEnabledExtensionsChanged(); - this._onSettingsWritableChanged(); - } - - _onEnabledExtensionsChanged() { - let newEnabledExtensions = this._getEnabledExtensions(); - - // Find and enable all the newly enabled extensions: UUIDs found in the - // new setting, but not in the old one. - newEnabledExtensions.filter( -- uuid => !this._enabledExtensions.includes(uuid) -+ uuid => !this._enabledExtensions.includes(uuid) && -+ this._extensionSupportsSessionMode(uuid) - ).forEach(uuid => { - this._callExtensionEnable(uuid); - }); - - // Find and disable all the newly disabled extensions: UUIDs found in the -- // old setting, but not in the new one. -+ // old setting, but not in the new one, and extensions that don't work with -+ // the current session mode. - this._enabledExtensions.filter( -- item => !newEnabledExtensions.includes(item) -+ item => !newEnabledExtensions.includes(item) || -+ !this._extensionSupportsSessionMode(item) - ).forEach(uuid => { - this._callExtensionDisable(uuid); - }); - - this._enabledExtensions = newEnabledExtensions; - } - - _onSettingsWritableChanged() { - for (let extension of this._extensions.values()) { - this._updateCanChange(extension); - this.emit('extension-state-changed', extension); - } - } - - _onVersionValidationChanged() { - // we want to reload all extensions, but only enable - // extensions when allowed by the sessionMode, so - // temporarily disable them all - this._enabledExtensions = []; - - // The loop modifies the extensions map, so iterate over a copy - let extensions = [...this._extensions.values()]; - for (let extension of extensions) - this.reloadExtension(extension); - this._enabledExtensions = this._getEnabledExtensions(); - - if (Main.sessionMode.allowExtensions) { - this._enabledExtensions.forEach(uuid => { - this._callExtensionEnable(uuid); - }); --- -2.27.0 - diff --git a/SOURCES/0003-shell-app-system-Monitor-for-icon-theme-changes.patch b/SOURCES/0003-shell-app-system-Monitor-for-icon-theme-changes.patch deleted file mode 100644 index 89a3a80..0000000 --- a/SOURCES/0003-shell-app-system-Monitor-for-icon-theme-changes.patch +++ /dev/null @@ -1,152 +0,0 @@ -From c9277326055c96185a80b68d4228eee360bb0e7c Mon Sep 17 00:00:00 2001 -From: Georges Basile Stavracas Neto -Date: Thu, 1 Aug 2019 20:58:20 -0300 -Subject: [PATCH 3/6] shell/app-system: Monitor for icon theme changes - -Whenever an app is installed, the usual routine is -to run 'gtk-update-icon-cache' after installing all -of the app's files. - -The side effect of that is that the .desktop file of -the application is installed before the icon theme -is updated. By the time GAppInfoMonitor emits the -'changed' signal, the icon theme is not yet updated, -leading to StIcon use the fallback icon. - -Under some circumstances (e.g. on very slow spinning -disks) the app icon is never actually loaded, and we -see the fallback icon forever. - -Monitor the icon theme for changes when an app is -installed. Try as many as 6 times before giving up -on detecting an icon theme update. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/661 ---- - src/shell-app-system.c | 54 +++++++++++++++++++++++++++++++++++++++ - src/st/st-texture-cache.c | 8 ++++++ - src/st/st-texture-cache.h | 2 ++ - 3 files changed, 64 insertions(+) - -diff --git a/src/shell-app-system.c b/src/shell-app-system.c -index f632cbe54..127f29ef0 100644 ---- a/src/shell-app-system.c -+++ b/src/shell-app-system.c -@@ -14,6 +14,14 @@ - #include "shell-app-system-private.h" - #include "shell-global.h" - #include "shell-util.h" -+#include "st.h" -+ -+/* Rescan for at most RESCAN_TIMEOUT_MS * MAX_RESCAN_RETRIES. That -+ * should be plenty of time for even a slow spinning drive to update -+ * the icon cache. -+ */ -+#define RESCAN_TIMEOUT_MS 2500 -+#define MAX_RESCAN_RETRIES 6 - - /* Vendor prefixes are something that can be preprended to a .desktop - * file name. Undo this. -@@ -51,6 +59,9 @@ struct _ShellAppSystemPrivate { - GHashTable *id_to_app; - GHashTable *startup_wm_class_to_id; - GList *installed_apps; -+ -+ guint rescan_icons_timeout_id; -+ guint n_rescan_retries; - }; - - static void shell_app_system_finalize (GObject *object); -@@ -157,12 +168,54 @@ stale_app_remove_func (gpointer key, - return app_is_stale (value); - } - -+static gboolean -+rescan_icon_theme_cb (gpointer user_data) -+{ -+ ShellAppSystemPrivate *priv; -+ ShellAppSystem *self; -+ StTextureCache *texture_cache; -+ gboolean rescanned; -+ -+ self = (ShellAppSystem *) user_data; -+ priv = self->priv; -+ -+ texture_cache = st_texture_cache_get_default (); -+ rescanned = st_texture_cache_rescan_icon_theme (texture_cache); -+ -+ priv->n_rescan_retries++; -+ -+ if (rescanned || priv->n_rescan_retries >= MAX_RESCAN_RETRIES) -+ { -+ priv->n_rescan_retries = 0; -+ priv->rescan_icons_timeout_id = 0; -+ return G_SOURCE_REMOVE; -+ } -+ -+ return G_SOURCE_CONTINUE; -+} -+ -+static void -+rescan_icon_theme (ShellAppSystem *self) -+{ -+ ShellAppSystemPrivate *priv = self->priv; -+ -+ priv->n_rescan_retries = 0; -+ -+ if (priv->rescan_icons_timeout_id > 0) -+ return; -+ -+ priv->rescan_icons_timeout_id = g_timeout_add (RESCAN_TIMEOUT_MS, -+ rescan_icon_theme_cb, -+ self); -+} -+ - static void - installed_changed (GAppInfoMonitor *monitor, - gpointer user_data) - { - ShellAppSystem *self = user_data; - -+ rescan_icon_theme (self); - scan_startup_wm_class_to_id (self); - - g_hash_table_foreach_remove (self->priv->id_to_app, stale_app_remove_func, NULL); -@@ -200,6 +253,7 @@ shell_app_system_finalize (GObject *object) - g_hash_table_destroy (priv->id_to_app); - g_hash_table_destroy (priv->startup_wm_class_to_id); - g_list_free_full (priv->installed_apps, g_object_unref); -+ g_clear_handle_id (&priv->rescan_icons_timeout_id, g_source_remove); - - G_OBJECT_CLASS (shell_app_system_parent_class)->finalize (object); - } -diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c -index c1331747f..4d0d617c4 100644 ---- a/src/st/st-texture-cache.c -+++ b/src/st/st-texture-cache.c -@@ -1554,3 +1554,11 @@ st_texture_cache_get_default (void) - instance = g_object_new (ST_TYPE_TEXTURE_CACHE, NULL); - return instance; - } -+ -+gboolean -+st_texture_cache_rescan_icon_theme (StTextureCache *cache) -+{ -+ StTextureCachePrivate *priv = cache->priv; -+ -+ return gtk_icon_theme_rescan_if_needed (priv->icon_theme); -+} -diff --git a/src/st/st-texture-cache.h b/src/st/st-texture-cache.h -index 11d1c4e64..a99316da8 100644 ---- a/src/st/st-texture-cache.h -+++ b/src/st/st-texture-cache.h -@@ -113,4 +113,6 @@ CoglTexture * st_texture_cache_load (StTextureCache *cache, - void *data, - GError **error); - -+gboolean st_texture_cache_rescan_icon_theme (StTextureCache *cache); -+ - #endif /* __ST_TEXTURE_CACHE_H__ */ --- -2.26.2 - diff --git a/SOURCES/0003-shellEntry-Handle-password-item-from-dedication-func.patch b/SOURCES/0003-shellEntry-Handle-password-item-from-dedication-func.patch deleted file mode 100644 index 46afc47..0000000 --- a/SOURCES/0003-shellEntry-Handle-password-item-from-dedication-func.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 39cf97176e2a92506081ee151ea546e2c6cf213a Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 21 Aug 2019 15:06:46 -0400 -Subject: [PATCH 3/4] shellEntry: Handle password item from dedication function - -At the moment, shellEntry handles creating and destroying its -"Show Text" password menu item directly from its isPassword -setter function. - -This commit moves that handling to a dedicated _resetPasswordItem -function, as prep work for adding lockdown support of the "Show Text" -menu item. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/687 ---- - js/ui/shellEntry.js | 23 +++++++++++++++++------ - 1 file changed, 17 insertions(+), 6 deletions(-) - -diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js -index 603a9c64a..765cede06 100644 ---- a/js/ui/shellEntry.js -+++ b/js/ui/shellEntry.js -@@ -14,76 +14,87 @@ var EntryMenu = class extends PopupMenu.PopupMenu { - - this._entry = entry; - this._clipboard = St.Clipboard.get_default(); - - // Populate menu - let item; - item = new PopupMenu.PopupMenuItem(_("Copy")); - item.connect('activate', this._onCopyActivated.bind(this)); - this.addMenuItem(item); - this._copyItem = item; - - item = new PopupMenu.PopupMenuItem(_("Paste")); - item.connect('activate', this._onPasteActivated.bind(this)); - this.addMenuItem(item); - this._pasteItem = item; - - this._passwordItem = null; - - Main.uiGroup.add_actor(this.actor); - this.actor.hide(); - } - - _makePasswordItem() { - let item = new PopupMenu.PopupMenuItem(''); - item.connect('activate', this._onPasswordActivated.bind(this)); - this.addMenuItem(item); - this._passwordItem = item; - this._updatePasswordItem(); - } - -+ _resetPasswordItem() { -+ if (!this.isPassword) { -+ if (this._passwordItem) { -+ this._passwordItem.destroy(); -+ this._passwordItem = null; -+ } -+ this._entry.clutter_text.set_password_char('\u25cf'); -+ } else { -+ if (!this._passwordItem) -+ this._makePasswordItem(); -+ } -+ } -+ - get isPassword() { - return this._entry.input_purpose == Clutter.InputContentPurpose.PASSWORD; - } - - set isPassword(v) { - if (v == this.isPassword) - return; - -- if (v) { -- this._makePasswordItem(); -+ if (v) - this._entry.input_purpose = Clutter.InputContentPurpose.PASSWORD; -- } else { -- this._passwordItem.destroy(); -- this._passwordItem = null; -+ else - this._entry.input_purpose = Clutter.InputContentPurpose.NORMAL; -- } -+ -+ this._resetPasswordItem(); - } - - open(animate) { - this._updatePasteItem(); - this._updateCopyItem(); - if (this._passwordItem) - this._updatePasswordItem(); - - super.open(animate); - this._entry.add_style_pseudo_class('focus'); - - let direction = St.DirectionType.TAB_FORWARD; - if (!this.actor.navigate_focus(null, direction, false)) - this.actor.grab_key_focus(); - } - - _updateCopyItem() { - let selection = this._entry.clutter_text.get_selection(); - this._copyItem.setSensitive(!this._entry.clutter_text.password_char && - selection && selection != ''); - } - - _updatePasteItem() { - this._clipboard.get_text(St.ClipboardType.CLIPBOARD, - (clipboard, text) => { - this._pasteItem.setSensitive(text && text != ''); - }); - } - - _updatePasswordItem() { --- -2.27.0 - diff --git a/SOURCES/0004-background-refresh-background-on-gl-video-memory-pur.patch b/SOURCES/0004-background-refresh-background-on-gl-video-memory-pur.patch deleted file mode 100644 index 0f81f47..0000000 --- a/SOURCES/0004-background-refresh-background-on-gl-video-memory-pur.patch +++ /dev/null @@ -1,115 +0,0 @@ -From 055bc14c70af66fe1893dcd4c42c65662ae1f9d0 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 21 Jan 2019 15:07:15 -0500 -Subject: [PATCH 4/4] background: refresh background on gl-video-memory-purged - signal - -Right now we refresh the background when resuming and when NVIDIA. -But mutter has a signal to tell us specifically when to refresh, -and the signal is only emitted for NVIDIA, so use that instead. ---- - js/ui/background.js | 9 +++++++-- - js/ui/layout.js | 12 ------------ - src/shell-util.c | 27 --------------------------- - src/shell-util.h | 2 -- - 4 files changed, 7 insertions(+), 43 deletions(-) - -diff --git a/js/ui/background.js b/js/ui/background.js -index 75b76a57e..466cc4de7 100644 ---- a/js/ui/background.js -+++ b/js/ui/background.js -@@ -527,10 +527,15 @@ var BackgroundSource = class BackgroundSource { - let monitorManager = Meta.MonitorManager.get(); - this._monitorsChangedId = - monitorManager.connect('monitors-changed', -- this._onMonitorsChanged.bind(this)); -+ this._refresh.bind(this)); -+ -+ global.display.connect('gl-video-memory-purged', () => { -+ Meta.Background.refresh_all(); -+ this._refresh(); -+ }); - } - -- _onMonitorsChanged() { -+ _refresh() { - for (let monitorIndex in this._backgrounds) { - let background = this._backgrounds[monitorIndex]; - -diff --git a/js/ui/layout.js b/js/ui/layout.js -index 30e750dc5..2b3bb7442 100644 ---- a/js/ui/layout.js -+++ b/js/ui/layout.js -@@ -282,18 +282,6 @@ var LayoutManager = GObject.registerClass({ - monitorManager.connect('monitors-changed', - this._monitorsChanged.bind(this)); - this._monitorsChanged(); -- -- // NVIDIA drivers don't preserve FBO contents across -- // suspend/resume, see -- // https://bugzilla.gnome.org/show_bug.cgi?id=739178 -- if (Shell.util_need_background_refresh()) { -- LoginManager.getLoginManager().connect('prepare-for-sleep', -- (lm, suspending) => { -- if (suspending) -- return; -- Meta.Background.refresh_all(); -- }); -- } - } - - // This is called by Main after everything else is constructed -diff --git a/src/shell-util.c b/src/shell-util.c -index c6e5abed6..9c25643c6 100644 ---- a/src/shell-util.c -+++ b/src/shell-util.c -@@ -374,33 +374,6 @@ shell_util_create_pixbuf_from_data (const guchar *data, - (GdkPixbufDestroyNotify) g_free, NULL); - } - --typedef const gchar *(*ShellGLGetString) (GLenum); -- --static const gchar * --get_gl_vendor (void) --{ -- static const gchar *vendor = NULL; -- -- if (!vendor) -- { -- ShellGLGetString gl_get_string; -- gl_get_string = (ShellGLGetString) cogl_get_proc_address ("glGetString"); -- if (gl_get_string) -- vendor = gl_get_string (GL_VENDOR); -- } -- -- return vendor; --} -- --gboolean --shell_util_need_background_refresh (void) --{ -- if (g_strcmp0 (get_gl_vendor (), "NVIDIA Corporation") == 0) -- return TRUE; -- -- return FALSE; --} -- - static gboolean - canvas_draw_cb (ClutterContent *content, - cairo_t *cr, -diff --git a/src/shell-util.h b/src/shell-util.h -index 6904f43bc..049c3fe18 100644 ---- a/src/shell-util.h -+++ b/src/shell-util.h -@@ -44,8 +44,6 @@ GdkPixbuf *shell_util_create_pixbuf_from_data (const guchar *data, - int height, - int rowstride); - --gboolean shell_util_need_background_refresh (void); -- - ClutterContent * shell_util_get_content_for_window_actor (MetaWindowActor *window_actor, - MetaRectangle *window_rect); - --- -2.21.0 - diff --git a/SOURCES/0004-global-force-fsync-to-worker-thread-when-saving-stat.patch b/SOURCES/0004-global-force-fsync-to-worker-thread-when-saving-stat.patch deleted file mode 100644 index 2271311..0000000 --- a/SOURCES/0004-global-force-fsync-to-worker-thread-when-saving-stat.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 2a4f33df723d4b9ce68e5948b568a89675d37411 Mon Sep 17 00:00:00 2001 -From: Christian Hergert -Date: Wed, 26 Feb 2020 14:46:20 -0800 -Subject: [PATCH 4/6] global: force fsync() to worker thread when saving state - -The g_file_replace_contents_async() API can potentially call fsync() from -the thread calling into it upon completion. This can have disasterous -effects when run from the compositor main thread such as complete stalls. - -This is a followup to 86a00b6872375a266449beee1ea6d5e94f1ebbcb which -assumed (like the rest of us) that the fsync() would be performed on the -thread that was doing the I/O operations. - -You can verify this with an strace -e fsync and cause terminal to display -a command completed notification (eg: from a backdrop window). - -This also fixes a lifecycle bug for the variant, as -g_file_replace_contents_async() does not copy the data during the operation -as that is the responsibility of the caller. Instead, we just use a GBytes -variant and reference the variant there. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1050 ---- - src/shell-global.c | 70 +++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 63 insertions(+), 7 deletions(-) - -diff --git a/src/shell-global.c b/src/shell-global.c -index df84b6b0d..4b33778e0 100644 ---- a/src/shell-global.c -+++ b/src/shell-global.c -@@ -1572,6 +1572,55 @@ delete_variant_cb (GObject *object, - g_hash_table_remove (global->save_ops, object); - } - -+static void -+replace_contents_worker (GTask *task, -+ gpointer source_object, -+ gpointer task_data, -+ GCancellable *cancellable) -+{ -+ GFile *file = source_object; -+ GBytes *bytes = task_data; -+ GError *error = NULL; -+ const gchar *data; -+ gsize len; -+ -+ data = g_bytes_get_data (bytes, &len); -+ -+ if (!g_file_replace_contents (file, data, len, NULL, FALSE, -+ G_FILE_CREATE_REPLACE_DESTINATION, -+ NULL, cancellable, &error)) -+ g_task_return_error (task, g_steal_pointer (&error)); -+ else -+ g_task_return_boolean (task, TRUE); -+} -+ -+static void -+replace_contents_async (GFile *path, -+ GBytes *bytes, -+ GCancellable *cancellable, -+ GAsyncReadyCallback callback, -+ gpointer user_data) -+{ -+ g_autoptr(GTask) task = NULL; -+ -+ g_assert (G_IS_FILE (path)); -+ g_assert (bytes != NULL); -+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); -+ -+ task = g_task_new (path, cancellable, callback, user_data); -+ g_task_set_source_tag (task, replace_contents_async); -+ g_task_set_task_data (task, g_bytes_ref (bytes), (GDestroyNotify)g_bytes_unref); -+ g_task_run_in_thread (task, replace_contents_worker); -+} -+ -+static gboolean -+replace_contents_finish (GFile *file, -+ GAsyncResult *result, -+ GError **error) -+{ -+ return g_task_propagate_boolean (G_TASK (result), error); -+} -+ - static void - replace_variant_cb (GObject *object, - GAsyncResult *result, -@@ -1580,7 +1629,7 @@ replace_variant_cb (GObject *object, - ShellGlobal *global = user_data; - GError *error = NULL; - -- if (!g_file_replace_contents_finish (G_FILE (object), result, NULL, &error)) -+ if (!replace_contents_finish (G_FILE (object), result, &error)) - { - if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - { -@@ -1616,12 +1665,19 @@ save_variant (ShellGlobal *global, - } - else - { -- g_file_replace_contents_async (path, -- g_variant_get_data (variant), -- g_variant_get_size (variant), -- NULL, FALSE, -- G_FILE_CREATE_REPLACE_DESTINATION, -- cancellable, replace_variant_cb, global); -+ g_autoptr(GBytes) bytes = NULL; -+ -+ bytes = g_bytes_new_with_free_func (g_variant_get_data (variant), -+ g_variant_get_size (variant), -+ (GDestroyNotify)g_variant_unref, -+ g_variant_ref (variant)); -+ /* g_file_replace_contents_async() can potentially fsync() from the -+ * calling thread when completing the asynchronous task. Instead, we -+ * want to force that fsync() to a thread to avoid blocking the -+ * compository main loop. Using our own replace_contents_async() -+ * simply executes the operation synchronously from a thread. -+ */ -+ replace_contents_async (path, bytes, cancellable, replace_variant_cb, global); - } - - g_object_unref (path); --- -2.26.2 - diff --git a/SOURCES/0004-sessionMode-Allow-extensions-at-the-login-and-unlock.patch b/SOURCES/0004-sessionMode-Allow-extensions-at-the-login-and-unlock.patch deleted file mode 100644 index f19fecd..0000000 --- a/SOURCES/0004-sessionMode-Allow-extensions-at-the-login-and-unlock.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 5fad989ca773f9e0ff6fdbeb0cb7c9cb70cc6148 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 10 Aug 2021 15:31:00 -0400 -Subject: [PATCH 4/4] sessionMode: Allow extensions at the login and unlock - screens - -Now extensions can specify which session modes they work in, -but specifying the login screen or unlock screen session modes in -an extensions metadata still won't work, because those session -modes disallow extensions. - -This commit fixes that. ---- - js/ui/sessionMode.js | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/js/ui/sessionMode.js b/js/ui/sessionMode.js -index fa7f83416..8d8ce1a64 100644 ---- a/js/ui/sessionMode.js -+++ b/js/ui/sessionMode.js -@@ -12,89 +12,92 @@ const Config = imports.misc.config; - const DEFAULT_MODE = 'restrictive'; - - const _modes = { - 'restrictive': { - parentMode: null, - stylesheetName: 'gnome-shell.css', - hasOverview: false, - showCalendarEvents: false, - allowSettings: false, - allowExtensions: false, - allowScreencast: false, - enabledExtensions: [], - hasRunDialog: false, - hasWorkspaces: false, - hasWindows: false, - hasNotifications: false, - isLocked: false, - isGreeter: false, - isPrimary: false, - unlockDialog: null, - components: [], - panel: { - left: [], - center: [], - right: [] - }, - panelStyle: null - }, - - 'gdm': { -+ allowExtensions: true, - hasNotifications: true, - isGreeter: true, - isPrimary: true, - unlockDialog: imports.gdm.loginDialog.LoginDialog, - components: Config.HAVE_NETWORKMANAGER - ? ['networkAgent', 'polkitAgent'] - : ['polkitAgent'], - panel: { - left: [], - center: ['dateMenu'], - right: ['a11y', 'keyboard', 'aggregateMenu'] - }, - panelStyle: 'login-screen' - }, - - 'lock-screen': { -+ allowExtensions: true, - isLocked: true, - isGreeter: undefined, - unlockDialog: undefined, - components: ['polkitAgent', 'telepathyClient'], - panel: { - left: [], - center: [], - right: ['aggregateMenu'] - }, - panelStyle: 'lock-screen' - }, - - 'unlock-dialog': { -+ allowExtensions: true, - isLocked: true, - unlockDialog: undefined, - components: ['polkitAgent', 'telepathyClient'], - panel: { - left: [], - center: [], - right: ['a11y', 'keyboard', 'aggregateMenu'] - }, - panelStyle: 'unlock-screen' - }, - - 'user': { - hasOverview: true, - showCalendarEvents: true, - allowSettings: true, - allowExtensions: true, - allowScreencast: true, - hasRunDialog: true, - hasWorkspaces: true, - hasWindows: true, - hasNotifications: true, - isLocked: false, - isPrimary: true, - unlockDialog: imports.ui.unlockDialog.UnlockDialog, - components: Config.HAVE_NETWORKMANAGER ? - ['networkAgent', 'polkitAgent', 'telepathyClient', - 'keyring', 'autorunManager', 'automountManager'] : - ['polkitAgent', 'telepathyClient', - 'keyring', 'autorunManager', 'automountManager'], - --- -2.27.0 - diff --git a/SOURCES/0004-shellEntry-Support-lockdown-of-Show-Text-menu-in-pas.patch b/SOURCES/0004-shellEntry-Support-lockdown-of-Show-Text-menu-in-pas.patch deleted file mode 100644 index 8d8a7d7..0000000 --- a/SOURCES/0004-shellEntry-Support-lockdown-of-Show-Text-menu-in-pas.patch +++ /dev/null @@ -1,116 +0,0 @@ -From ee64cd773bdeef845d02dc84063f926d77090dec Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 21 Aug 2019 15:06:46 -0400 -Subject: [PATCH 4/4] shellEntry: Support lockdown of "Show Text" menu in - password entries - -Some deployments require being able to prevent users from showing -the password they're currently typing. - -This commit adds support for that kind of lockdown. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/687 ---- - js/ui/shellEntry.js | 14 +++++++++++--- - 1 file changed, 11 insertions(+), 3 deletions(-) - -diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js -index 765cede06..c45e4545a 100644 ---- a/js/ui/shellEntry.js -+++ b/js/ui/shellEntry.js -@@ -1,81 +1,89 @@ - // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - --const { Clutter, GObject, Pango, Shell, St } = imports.gi; -+const { Clutter, Gio, GObject, Pango, Shell, St } = imports.gi; - - const BoxPointer = imports.ui.boxpointer; - const Main = imports.ui.main; - const Params = imports.misc.params; - const PopupMenu = imports.ui.popupMenu; - const Tweener = imports.ui.tweener; - -+const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown'; -+const DISABLE_SHOW_PASSWORD_KEY = 'disable-show-password'; -+ - var EntryMenu = class extends PopupMenu.PopupMenu { - constructor(entry) { - super(entry, 0, St.Side.TOP); - -+ this._lockdownSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA }); -+ this._lockdownSettings.connect('changed::' + DISABLE_SHOW_PASSWORD_KEY, this._resetPasswordItem.bind(this)); -+ - this._entry = entry; - this._clipboard = St.Clipboard.get_default(); - - // Populate menu - let item; - item = new PopupMenu.PopupMenuItem(_("Copy")); - item.connect('activate', this._onCopyActivated.bind(this)); - this.addMenuItem(item); - this._copyItem = item; - - item = new PopupMenu.PopupMenuItem(_("Paste")); - item.connect('activate', this._onPasteActivated.bind(this)); - this.addMenuItem(item); - this._pasteItem = item; - - this._passwordItem = null; - - Main.uiGroup.add_actor(this.actor); - this.actor.hide(); - } - - _makePasswordItem() { - let item = new PopupMenu.PopupMenuItem(''); - item.connect('activate', this._onPasswordActivated.bind(this)); - this.addMenuItem(item); - this._passwordItem = item; - this._updatePasswordItem(); - } - - _resetPasswordItem() { -- if (!this.isPassword) { -+ let passwordDisabled = this._lockdownSettings.get_boolean(DISABLE_SHOW_PASSWORD_KEY); -+ -+ if (!this.isPassword || passwordDisabled) { - if (this._passwordItem) { - this._passwordItem.destroy(); - this._passwordItem = null; - } - this._entry.clutter_text.set_password_char('\u25cf'); -- } else { -+ } else if (this.isPassword && !passwordDisabled) { - if (!this._passwordItem) - this._makePasswordItem(); - } - } - - get isPassword() { - return this._entry.input_purpose == Clutter.InputContentPurpose.PASSWORD; - } - - set isPassword(v) { - if (v == this.isPassword) - return; - - if (v) - this._entry.input_purpose = Clutter.InputContentPurpose.PASSWORD; - else - this._entry.input_purpose = Clutter.InputContentPurpose.NORMAL; - - this._resetPasswordItem(); - } - - open(animate) { - this._updatePasteItem(); - this._updateCopyItem(); - if (this._passwordItem) - this._updatePasswordItem(); - - super.open(animate); - this._entry.add_style_pseudo_class('focus'); - --- -2.27.0 - diff --git a/SOURCES/0005-app-cache-add-ShellAppCache-for-GAppInfo-caching.patch b/SOURCES/0005-app-cache-add-ShellAppCache-for-GAppInfo-caching.patch deleted file mode 100644 index 1f19cb0..0000000 --- a/SOURCES/0005-app-cache-add-ShellAppCache-for-GAppInfo-caching.patch +++ /dev/null @@ -1,674 +0,0 @@ -From a3fc35a2b452855d004549afbec57d1b4f36c917 Mon Sep 17 00:00:00 2001 -From: Christian Hergert -Date: Thu, 27 Feb 2020 19:36:14 -0800 -Subject: [PATCH 5/6] app-cache: add ShellAppCache for GAppInfo caching - -This caches GAppInfo so that the compositor thread does not have to perform -costly disk access to load them. Instead, they are loaded from a worker -thread and the ShellAppCache notifies of changes. - -To simplify maintenance, ShellAppCache manages this directly and the -existing ShellAppSystem wraps the cache. We may want to graft these -together in the future, but now it provides the easiest way to backport -changes to older Shell releases. - -Another source of compositor thread disk access was in determining the -name for an application directory. Translations are provided via GKeyFile -installed in "desktop-directories". Each time we would build the name -for a label (or update it) we would have to load all of these files. - -Instead, the ShellAppCache caches that information and updates the cache -in bulk when those change. We can reduce this in the future to do less -work, but chances are these will come together anyway so that is probably -worth fixing if we ever come across it. - -https://gitlab.gnome.org/GNOME/gnome-shell/issues/2282 ---- - js/ui/appDisplay.js | 12 +- - src/meson.build | 5 +- - src/shell-app-cache-private.h | 19 ++ - src/shell-app-cache.c | 404 ++++++++++++++++++++++++++++++++++ - src/shell-app-system.c | 34 ++- - src/shell-util.c | 16 ++ - src/shell-util.h | 2 + - 7 files changed, 463 insertions(+), 29 deletions(-) - create mode 100644 src/shell-app-cache-private.h - create mode 100644 src/shell-app-cache.c - -diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js -index 7fad02cd0..a2d691085 100644 ---- a/js/ui/appDisplay.js -+++ b/js/ui/appDisplay.js -@@ -78,15 +78,9 @@ function _getFolderName(folder) { - let name = folder.get_string('name'); - - if (folder.get_boolean('translate')) { -- let keyfile = new GLib.KeyFile(); -- let path = 'desktop-directories/' + name; -- -- try { -- keyfile.load_from_data_dirs(path, GLib.KeyFileFlags.NONE); -- name = keyfile.get_locale_string('Desktop Entry', 'Name', null); -- } catch(e) { -- return name; -- } -+ let translated = Shell.util_get_translated_folder_name(name); -+ if (translated !== null) -+ return translated; - } - - return name; -diff --git a/src/meson.build b/src/meson.build -index 97a5a796c..2b911d347 100644 ---- a/src/meson.build -+++ b/src/meson.build -@@ -108,6 +108,7 @@ endif - - libshell_private_headers = [ - 'shell-app-private.h', -+ 'shell-app-cache-private.h', - 'shell-app-system-private.h', - 'shell-global-private.h', - 'shell-window-tracker-private.h', -@@ -146,7 +147,9 @@ if have_networkmanager - libshell_sources += 'shell-network-agent.c' - endif - --libshell_private_sources = [] -+libshell_private_sources = [ -+ 'shell-app-cache.c', -+] - - if enable_recorder - libshell_sources += ['shell-recorder.c'] -diff --git a/src/shell-app-cache-private.h b/src/shell-app-cache-private.h -new file mode 100644 -index 000000000..b73094ab1 ---- /dev/null -+++ b/src/shell-app-cache-private.h -@@ -0,0 +1,19 @@ -+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -+#ifndef __SHELL_APP_CACHE_PRIVATE_H__ -+#define __SHELL_APP_CACHE_PRIVATE_H__ -+ -+#include -+#include -+ -+#define SHELL_TYPE_APP_CACHE (shell_app_cache_get_type()) -+ -+G_DECLARE_FINAL_TYPE (ShellAppCache, shell_app_cache, SHELL, APP_CACHE, GObject) -+ -+ShellAppCache *shell_app_cache_get_default (void); -+GList *shell_app_cache_get_all (ShellAppCache *cache); -+GDesktopAppInfo *shell_app_cache_get_info (ShellAppCache *cache, -+ const char *id); -+char *shell_app_cache_translate_folder (ShellAppCache *cache, -+ const char *name); -+ -+#endif /* __SHELL_APP_CACHE_PRIVATE_H__ */ -diff --git a/src/shell-app-cache.c b/src/shell-app-cache.c -new file mode 100644 -index 000000000..15d4734d0 ---- /dev/null -+++ b/src/shell-app-cache.c -@@ -0,0 +1,404 @@ -+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -+ -+#include "config.h" -+ -+#include "shell-app-cache-private.h" -+ -+/** -+ * SECTION:shell-app-cache -+ * @title: ShellAppCache -+ * @short_description: application information cache -+ * -+ * The #ShellAppCache is responsible for caching information about #GAppInfo -+ * to ensure that the compositor thread never needs to perform disk reads to -+ * access them. All of the work is done off-thread. When the new data has -+ * been loaded, a #ShellAppCache::changed signal is emitted. -+ * -+ * Additionally, the #ShellAppCache caches information about translations for -+ * directories. This allows translation provided in [Desktop Entry] GKeyFiles -+ * to be available when building StLabel and other elements without performing -+ * costly disk reads. -+ * -+ * Various monitors are used to keep this information up to date while the -+ * Shell is running. -+ */ -+ -+#define DEFAULT_TIMEOUT_SECONDS 5 -+ -+struct _ShellAppCache -+{ -+ GObject parent_instance; -+ -+ GAppInfoMonitor *monitor; -+ GPtrArray *dir_monitors; -+ GHashTable *folders; -+ GCancellable *cancellable; -+ GList *app_infos; -+ -+ guint queued_update; -+}; -+ -+typedef struct -+{ -+ GList *app_infos; -+ GHashTable *folders; -+} CacheState; -+ -+G_DEFINE_TYPE (ShellAppCache, shell_app_cache, G_TYPE_OBJECT) -+ -+enum { -+ CHANGED, -+ N_SIGNALS -+}; -+ -+static guint signals [N_SIGNALS]; -+ -+static void -+cache_state_free (CacheState *state) -+{ -+ g_clear_pointer (&state->folders, g_hash_table_unref); -+ g_list_free_full (state->app_infos, g_object_unref); -+ g_slice_free (CacheState, state); -+} -+ -+static CacheState * -+cache_state_new (void) -+{ -+ CacheState *state; -+ -+ state = g_slice_new0 (CacheState); -+ state->folders = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); -+ -+ return g_steal_pointer (&state); -+} -+ -+/** -+ * shell_app_cache_get_default: -+ * -+ * Gets the default #ShellAppCache. -+ * -+ * Returns: (transfer none): a #ShellAppCache -+ */ -+ShellAppCache * -+shell_app_cache_get_default (void) -+{ -+ static ShellAppCache *instance; -+ -+ if (instance == NULL) -+ { -+ instance = g_object_new (SHELL_TYPE_APP_CACHE, NULL); -+ g_object_add_weak_pointer (G_OBJECT (instance), (gpointer *)&instance); -+ } -+ -+ return instance; -+} -+ -+static void -+load_folder (GHashTable *folders, -+ const char *path) -+{ -+ g_autoptr(GDir) dir = NULL; -+ const char *name; -+ -+ g_assert (folders != NULL); -+ g_assert (path != NULL); -+ -+ dir = g_dir_open (path, 0, NULL); -+ if (dir == NULL) -+ return; -+ -+ while ((name = g_dir_read_name (dir))) -+ { -+ g_autofree gchar *filename = NULL; -+ g_autoptr(GKeyFile) keyfile = NULL; -+ -+ /* First added wins */ -+ if (g_hash_table_contains (folders, name)) -+ continue; -+ -+ filename = g_build_filename (path, name, NULL); -+ keyfile = g_key_file_new (); -+ -+ if (g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, NULL)) -+ { -+ gchar *translated; -+ -+ translated = g_key_file_get_locale_string (keyfile, -+ "Desktop Entry", "Name", -+ NULL, NULL); -+ -+ if (translated != NULL) -+ g_hash_table_insert (folders, g_strdup (name), translated); -+ } -+ } -+} -+ -+static void -+load_folders (GHashTable *folders) -+{ -+ const char * const *dirs; -+ g_autofree gchar *userdir = NULL; -+ guint i; -+ -+ g_assert (folders != NULL); -+ -+ userdir = g_build_filename (g_get_user_data_dir (), "desktop-directories", NULL); -+ load_folder (folders, userdir); -+ -+ dirs = g_get_system_data_dirs (); -+ for (i = 0; dirs[i] != NULL; i++) -+ { -+ g_autofree gchar *sysdir = g_build_filename (dirs[i], "desktop-directories", NULL); -+ load_folder (folders, sysdir); -+ } -+} -+ -+static void -+shell_app_cache_worker (GTask *task, -+ gpointer source_object, -+ gpointer task_data, -+ GCancellable *cancellable) -+{ -+ CacheState *state; -+ -+ g_assert (G_IS_TASK (task)); -+ g_assert (SHELL_IS_APP_CACHE (source_object)); -+ -+ state = cache_state_new (); -+ state->app_infos = g_app_info_get_all (); -+ load_folders (state->folders); -+ -+ g_task_return_pointer (task, state, (GDestroyNotify) cache_state_free); -+} -+ -+static void -+apply_update_cb (GObject *object, -+ GAsyncResult *result, -+ gpointer user_data) -+{ -+ ShellAppCache *cache = (ShellAppCache *)object; -+ g_autoptr(GError) error = NULL; -+ CacheState *state; -+ -+ g_assert (SHELL_IS_APP_CACHE (cache)); -+ g_assert (G_IS_TASK (result)); -+ g_assert (user_data == NULL); -+ -+ state = g_task_propagate_pointer (G_TASK (result), &error); -+ -+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) -+ return; -+ -+ g_list_free_full (cache->app_infos, g_object_unref); -+ cache->app_infos = g_steal_pointer (&state->app_infos); -+ -+ g_clear_pointer (&cache->folders, g_hash_table_unref); -+ cache->folders = g_steal_pointer (&state->folders); -+ -+ g_signal_emit (cache, signals[CHANGED], 0); -+ -+ cache_state_free (state); -+} -+ -+static gboolean -+shell_app_cache_do_update (gpointer user_data) -+{ -+ ShellAppCache *cache = user_data; -+ g_autoptr(GTask) task = NULL; -+ -+ cache->queued_update = 0; -+ -+ /* Reset the cancellable state so we don't race with -+ * two updates coming back overlapped and applying the -+ * information in the wrong order. -+ */ -+ g_cancellable_cancel (cache->cancellable); -+ g_clear_object (&cache->cancellable); -+ cache->cancellable = g_cancellable_new (); -+ -+ task = g_task_new (cache, cache->cancellable, apply_update_cb, NULL); -+ g_task_set_source_tag (task, shell_app_cache_do_update); -+ g_task_run_in_thread (task, shell_app_cache_worker); -+ -+ return G_SOURCE_REMOVE; -+} -+ -+static void -+shell_app_cache_queue_update (ShellAppCache *self) -+{ -+ g_assert (SHELL_IS_APP_CACHE (self)); -+ -+ if (self->queued_update != 0) -+ g_source_remove (self->queued_update); -+ -+ self->queued_update = g_timeout_add_seconds (DEFAULT_TIMEOUT_SECONDS, -+ shell_app_cache_do_update, -+ self); -+} -+ -+static void -+monitor_desktop_directories_for_data_dir (ShellAppCache *self, -+ const gchar *directory) -+{ -+ g_autofree gchar *subdir = NULL; -+ g_autoptr(GFile) file = NULL; -+ g_autoptr(GFileMonitor) monitor = NULL; -+ -+ g_assert (SHELL_IS_APP_CACHE (self)); -+ -+ if (directory == NULL) -+ return; -+ -+ subdir = g_build_filename (directory, "desktop-directories", NULL); -+ file = g_file_new_for_path (subdir); -+ monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL); -+ -+ if (monitor != NULL) -+ { -+ g_file_monitor_set_rate_limit (monitor, DEFAULT_TIMEOUT_SECONDS * 1000); -+ g_signal_connect_object (monitor, -+ "changed", -+ G_CALLBACK (shell_app_cache_queue_update), -+ self, -+ G_CONNECT_SWAPPED); -+ g_ptr_array_add (self->dir_monitors, g_steal_pointer (&monitor)); -+ } -+} -+ -+static void -+shell_app_cache_finalize (GObject *object) -+{ -+ ShellAppCache *self = (ShellAppCache *)object; -+ -+ g_clear_object (&self->monitor); -+ -+ if (self->queued_update) -+ { -+ g_source_remove (self->queued_update); -+ self->queued_update = 0; -+ } -+ -+ g_clear_pointer (&self->dir_monitors, g_ptr_array_unref); -+ g_clear_pointer (&self->folders, g_hash_table_unref); -+ g_list_free_full (self->app_infos, g_object_unref); -+ -+ G_OBJECT_CLASS (shell_app_cache_parent_class)->finalize (object); -+} -+ -+static void -+shell_app_cache_class_init (ShellAppCacheClass *klass) -+{ -+ GObjectClass *object_class = G_OBJECT_CLASS (klass); -+ -+ object_class->finalize = shell_app_cache_finalize; -+ -+ /** -+ * ShellAppCache::changed: -+ * -+ * The "changed" signal is emitted when the cache has updated -+ * information about installed applications. -+ */ -+ signals [CHANGED] = -+ g_signal_new ("changed", -+ G_TYPE_FROM_CLASS (klass), -+ G_SIGNAL_RUN_LAST, -+ 0, NULL, NULL, NULL, -+ G_TYPE_NONE, 0); -+} -+ -+static void -+shell_app_cache_init (ShellAppCache *self) -+{ -+ const gchar * const *sysdirs; -+ guint i; -+ -+ /* Monitor directories for translation changes */ -+ self->dir_monitors = g_ptr_array_new_with_free_func (g_object_unref); -+ monitor_desktop_directories_for_data_dir (self, g_get_user_data_dir ()); -+ sysdirs = g_get_system_data_dirs (); -+ for (i = 0; sysdirs[i] != NULL; i++) -+ monitor_desktop_directories_for_data_dir (self, sysdirs[i]); -+ -+ /* Load translated directory names immediately */ -+ self->folders = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); -+ load_folders (self->folders); -+ -+ /* Setup AppMonitor to track changes */ -+ self->monitor = g_app_info_monitor_get (); -+ g_signal_connect_object (self->monitor, -+ "changed", -+ G_CALLBACK (shell_app_cache_queue_update), -+ self, -+ G_CONNECT_SWAPPED); -+ self->app_infos = g_app_info_get_all (); -+} -+ -+/** -+ * shell_app_cache_get_all: -+ * @cache: (nullable): a #ShellAppCache or %NULL -+ * -+ * Like g_app_info_get_all() but always returns a -+ * cached set of application info so the caller can be -+ * sure that I/O will not happen on the current thread. -+ * -+ * Returns: (transfer none) (element-type GAppInfo): -+ * a #GList of references to #GAppInfo. -+ */ -+GList * -+shell_app_cache_get_all (ShellAppCache *cache) -+{ -+ g_return_val_if_fail (SHELL_IS_APP_CACHE (cache), NULL); -+ -+ return cache->app_infos; -+} -+ -+/** -+ * shell_app_cache_get_info: -+ * @cache: (nullable): a #ShellAppCache or %NULL -+ * @id: the application id -+ * -+ * A replacement for g_desktop_app_info_new() that will lookup the -+ * information from the cache instead of (re)loading from disk. -+ * -+ * Returns: (nullable) (transfer none): a #GDesktopAppInfo or %NULL -+ */ -+GDesktopAppInfo * -+shell_app_cache_get_info (ShellAppCache *cache, -+ const char *id) -+{ -+ const GList *iter; -+ -+ g_return_val_if_fail (SHELL_IS_APP_CACHE (cache), NULL); -+ -+ for (iter = cache->app_infos; iter != NULL; iter = iter->next) -+ { -+ GAppInfo *info = iter->data; -+ -+ if (g_strcmp0 (id, g_app_info_get_id (info)) == 0) -+ return G_DESKTOP_APP_INFO (info); -+ } -+ -+ return NULL; -+} -+ -+/** -+ * shell_app_cache_translate_folder: -+ * @cache: (nullable): a #ShellAppCache or %NULL -+ * @name: the folder name -+ * -+ * Gets the translated folder name for @name if any exists. -+ * -+ * Returns: (nullable): the translated string or %NULL if there is no -+ * translation. -+ */ -+char * -+shell_app_cache_translate_folder (ShellAppCache *cache, -+ const char *name) -+{ -+ g_return_val_if_fail (SHELL_IS_APP_CACHE (cache), NULL); -+ -+ if (name == NULL) -+ return NULL; -+ -+ return g_strdup (g_hash_table_lookup (cache->folders, name)); -+} -diff --git a/src/shell-app-system.c b/src/shell-app-system.c -index 127f29ef0..828fa726a 100644 ---- a/src/shell-app-system.c -+++ b/src/shell-app-system.c -@@ -9,6 +9,7 @@ - #include - #include - -+#include "shell-app-cache-private.h" - #include "shell-app-private.h" - #include "shell-window-tracker-private.h" - #include "shell-app-system-private.h" -@@ -94,14 +95,14 @@ static void - scan_startup_wm_class_to_id (ShellAppSystem *self) - { - ShellAppSystemPrivate *priv = self->priv; -- GList *l; -+ const GList *l; -+ GList *all; - - g_hash_table_remove_all (priv->startup_wm_class_to_id); - -- g_list_free_full (priv->installed_apps, g_object_unref); -- priv->installed_apps = g_app_info_get_all (); -+ all = shell_app_cache_get_all (shell_app_cache_get_default ()); - -- for (l = priv->installed_apps; l != NULL; l = l->next) -+ for (l = all; l != NULL; l = l->next) - { - GAppInfo *info = l->data; - const char *startup_wm_class, *id, *old_id; -@@ -131,7 +132,8 @@ app_is_stale (ShellApp *app) - if (shell_app_is_window_backed (app)) - return FALSE; - -- info = g_desktop_app_info_new (shell_app_get_id (app)); -+ info = shell_app_cache_get_info (shell_app_cache_get_default (), -+ shell_app_get_id (app)); - if (!info) - return TRUE; - -@@ -156,7 +158,6 @@ app_is_stale (ShellApp *app) - g_icon_equal (g_app_info_get_icon (old_info), - g_app_info_get_icon (new_info)); - -- g_object_unref (info); - return !is_unchanged; - } - -@@ -210,11 +211,9 @@ rescan_icon_theme (ShellAppSystem *self) - } - - static void --installed_changed (GAppInfoMonitor *monitor, -- gpointer user_data) -+installed_changed (ShellAppCache *cache, -+ ShellAppSystem *self) - { -- ShellAppSystem *self = user_data; -- - rescan_icon_theme (self); - scan_startup_wm_class_to_id (self); - -@@ -227,7 +226,7 @@ static void - shell_app_system_init (ShellAppSystem *self) - { - ShellAppSystemPrivate *priv; -- GAppInfoMonitor *monitor; -+ ShellAppCache *cache; - - self->priv = priv = shell_app_system_get_instance_private (self); - -@@ -238,9 +237,9 @@ shell_app_system_init (ShellAppSystem *self) - - priv->startup_wm_class_to_id = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - -- monitor = g_app_info_monitor_get (); -- g_signal_connect (monitor, "changed", G_CALLBACK (installed_changed), self); -- installed_changed (monitor, self); -+ cache = shell_app_cache_get_default (); -+ g_signal_connect (cache, "changed", G_CALLBACK (installed_changed), self); -+ installed_changed (cache, self); - } - - static void -@@ -293,13 +292,12 @@ shell_app_system_lookup_app (ShellAppSystem *self, - if (app) - return app; - -- info = g_desktop_app_info_new (id); -+ info = shell_app_cache_get_info (shell_app_cache_get_default (), id); - if (!info) - return NULL; - - app = _shell_app_new (info); - g_hash_table_insert (priv->id_to_app, (char *) shell_app_get_id (app), app); -- g_object_unref (info); - return app; - } - -@@ -506,7 +504,5 @@ shell_app_system_search (const char *search_string) - GList * - shell_app_system_get_installed (ShellAppSystem *self) - { -- ShellAppSystemPrivate *priv = self->priv; -- -- return priv->installed_apps; -+ return shell_app_cache_get_all (shell_app_cache_get_default ()); - } -diff --git a/src/shell-util.c b/src/shell-util.c -index fa3fc08c8..370784523 100644 ---- a/src/shell-util.c -+++ b/src/shell-util.c -@@ -16,6 +16,7 @@ - #include - #include - -+#include "shell-app-cache-private.h" - #include "shell-util.h" - #include - #include -@@ -639,3 +640,18 @@ shell_util_has_x11_display_extension (MetaDisplay *display, - xdisplay = meta_x11_display_get_xdisplay (x11_display); - return XQueryExtension (xdisplay, extension, &op, &event, &error); - } -+ -+/** -+ * shell_util_get_translated_folder_name: -+ * @name: the untranslated folder name -+ * -+ * Attempts to translate the folder @name using translations provided -+ * by .directory files. -+ * -+ * Returns: (nullable): a translated string or %NULL -+ */ -+char * -+shell_util_get_translated_folder_name (const char *name) -+{ -+ return shell_app_cache_translate_folder (shell_app_cache_get_default (), name); -+} -diff --git a/src/shell-util.h b/src/shell-util.h -index 02b8404e9..843a1253d 100644 ---- a/src/shell-util.h -+++ b/src/shell-util.h -@@ -62,6 +62,8 @@ void shell_util_check_cloexec_fds (void); - gboolean shell_util_has_x11_display_extension (MetaDisplay *display, - const char *extension); - -+char *shell_util_get_translated_folder_name (const char *name); -+ - G_END_DECLS - - #endif /* __SHELL_UTIL_H__ */ --- -2.26.2 - diff --git a/SOURCES/0005-shellEntry-Only-mask-text-in-password-entries.patch b/SOURCES/0005-shellEntry-Only-mask-text-in-password-entries.patch deleted file mode 100644 index a87a327..0000000 --- a/SOURCES/0005-shellEntry-Only-mask-text-in-password-entries.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 7a264550c5f3a98b1786b1a75cff01cde1d084eb Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Thu, 29 Jul 2021 17:17:43 +0200 -Subject: [PATCH 5/5] shellEntry: Only mask text in password entries - -When "Show Text" is locked down, we not only remove the corresponding -menu item, but also make sure the password is masked. - -Except that the current code is too eager, and masks the text in -any entries. ---- - js/ui/shellEntry.js | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js -index c45e4545a..64b389050 100644 ---- a/js/ui/shellEntry.js -+++ b/js/ui/shellEntry.js -@@ -55,11 +55,13 @@ var EntryMenu = class extends PopupMenu.PopupMenu { - this._passwordItem.destroy(); - this._passwordItem = null; - } -- this._entry.clutter_text.set_password_char('\u25cf'); - } else if (this.isPassword && !passwordDisabled) { - if (!this._passwordItem) - this._makePasswordItem(); - } -+ -+ if (this.isPassword && passwordDisabled) -+ this._entry.clutter_text.set_password_char('\u25cf'); - } - - get isPassword() { --- -2.31.1 - diff --git a/SOURCES/0006-js-Always-use-AppSystem-to-lookup-apps.patch b/SOURCES/0006-js-Always-use-AppSystem-to-lookup-apps.patch deleted file mode 100644 index 73080e8..0000000 --- a/SOURCES/0006-js-Always-use-AppSystem-to-lookup-apps.patch +++ /dev/null @@ -1,66 +0,0 @@ -From a0df79f8de4c13c36ed3b22cfdbb78e324424ef1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Sat, 14 Mar 2020 14:45:42 +0100 -Subject: [PATCH 6/6] js: Always use AppSystem to lookup apps - -There is no good reason for bypassing the application cache in -AppSystem and loading .desktop files again. - -https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1093 ---- - js/ui/appDisplay.js | 4 ++-- - js/ui/calendar.js | 16 ++++++++++------ - 2 files changed, 12 insertions(+), 8 deletions(-) - -diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js -index a2d691085..cb2be7d3c 100644 ---- a/js/ui/appDisplay.js -+++ b/js/ui/appDisplay.js -@@ -1001,8 +1001,8 @@ var AppSearchProvider = class AppSearchProvider { - let results = []; - groups.forEach(group => { - group = group.filter(appID => { -- let app = Gio.DesktopAppInfo.new(appID); -- return app && app.should_show(); -+ const app = this._appSys.lookup_app(appID); -+ return app && app.app_info.should_show(); - }); - results = results.concat(group.sort( - (a, b) => usage.compare(a, b) -diff --git a/js/ui/calendar.js b/js/ui/calendar.js -index cd3e879c4..3ae2e44f8 100644 ---- a/js/ui/calendar.js -+++ b/js/ui/calendar.js -@@ -791,8 +791,9 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection { - this._title.connect('clicked', this._onTitleClicked.bind(this)); - this._title.connect('key-focus-in', this._onKeyFocusIn.bind(this)); - -- Shell.AppSystem.get_default().connect('installed-changed', -- this._appInstalledChanged.bind(this)); -+ this._appSys = Shell.AppSystem.get_default(); -+ this._appSys.connect('installed-changed', -+ this._appInstalledChanged.bind(this)); - this._appInstalledChanged(); - } - -@@ -883,10 +884,13 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection { - Main.overview.hide(); - Main.panel.closeCalendar(); - -- let app = this._getCalendarApp(); -- if (app.get_id() == 'evolution.desktop') -- app = Gio.DesktopAppInfo.new('evolution-calendar.desktop'); -- app.launch([], global.create_app_launch_context(0, -1)); -+ let appInfo = this._getCalendarApp(); -+ if (app.get_id() == 'evolution.desktop') { -+ let app = this._appSys.lookup_app('evolution-calendar.desktop'); -+ if (app) -+ appInfo = app.app_info; -+ } -+ appInfo.launch([], global.create_app_launch_context(0, -1)); - } - - setDate(date) { --- -2.26.2 - diff --git a/SOURCES/allow-timed-login-with-no-user-list.patch b/SOURCES/allow-timed-login-with-no-user-list.patch deleted file mode 100644 index 040e507..0000000 --- a/SOURCES/allow-timed-login-with-no-user-list.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 3252f05b8745a5d3118986474793fe3ecc2b041c Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 19 Apr 2016 13:12:46 -0400 -Subject: [PATCH] loginDialog: allow timed login with disabled user list - -At the moment the timed login feature is implemented in the user list. -If there's no user list, we don't show the indicator anywhere and -don't proceed with timed login. - -This commit allows timed login to work when the user list is disabled. -It accomplishes this by putting the timed login indicator on the -auth prompt, in that scenario. ---- - data/theme/gnome-shell-sass/_common.scss | 4 +++ - js/gdm/authPrompt.js | 41 +++++++++++++++++++++++- - js/gdm/loginDialog.js | 25 +++++++++++++-- - 3 files changed, 67 insertions(+), 3 deletions(-) - -diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss -index a6357baad..c2df28279 100644 ---- a/data/theme/gnome-shell-sass/_common.scss -+++ b/data/theme/gnome-shell-sass/_common.scss -@@ -1856,6 +1856,10 @@ StScrollBar { - padding-bottom: 12px; - spacing: 8px; - width: 23em; -+ .login-dialog-timed-login-indicator { -+ height: 2px; -+ background-color: darken($fg_color,40%); -+ } - } - - .login-dialog-prompt-label { -diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 27eb31a89..cf77b3f26 100644 ---- a/js/gdm/authPrompt.js -+++ b/js/gdm/authPrompt.js -@@ -1,6 +1,6 @@ - // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - --const { Clutter, Pango, Shell, St } = imports.gi; -+const { Clutter, GLib, Pango, Shell, St } = imports.gi; - const Signals = imports.signals; - - const Animation = imports.ui.animation; -@@ -111,6 +111,11 @@ var AuthPrompt = class { - - this._entry.grab_key_focus(); - -+ this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator', -+ scale_x: 0 }); -+ -+ this.actor.add(this._timedLoginIndicator); -+ - this._message = new St.Label({ opacity: 0, - styleClass: 'login-dialog-message' }); - this._message.clutter_text.line_wrap = true; -@@ -135,6 +140,40 @@ var AuthPrompt = class { - this._defaultButtonWell.add_child(this._spinner.actor); - } - -+ showTimedLoginIndicator(time) { -+ let hold = new Batch.Hold(); -+ -+ this.hideTimedLoginIndicator(); -+ -+ let startTime = GLib.get_monotonic_time(); -+ -+ this._timedLoginTimeoutId = GLib.timeout_add (GLib.PRIORITY_DEFAULT, 33, -+ () => { -+ let currentTime = GLib.get_monotonic_time(); -+ let elapsedTime = (currentTime - startTime) / GLib.USEC_PER_SEC; -+ this._timedLoginIndicator.scale_x = elapsedTime / time; -+ if (elapsedTime >= time) { -+ this._timedLoginTimeoutId = 0; -+ hold.release(); -+ return GLib.SOURCE_REMOVE; -+ } -+ -+ return GLib.SOURCE_CONTINUE; -+ }); -+ -+ GLib.Source.set_name_by_id(this._timedLoginTimeoutId, '[gnome-shell] this._timedLoginTimeoutId'); -+ -+ return hold; -+ } -+ -+ hideTimedLoginIndicator() { -+ if (this._timedLoginTimeoutId) { -+ GLib.source_remove(this._timedLoginTimeoutId); -+ this._timedLoginTimeoutId = 0; -+ } -+ this._timedLoginIndicator.scale_x = 0.; -+ } -+ - _onDestroy() { - if (this._preemptiveAnswerWatchId) { - this._idleMonitor.remove_watch(this._preemptiveAnswerWatchId); -diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js -index 6c4d1357d..b4df6e959 100644 ---- a/js/gdm/loginDialog.js -+++ b/js/gdm/loginDialog.js -@@ -734,6 +734,9 @@ var LoginDialog = GObject.registerClass({ - - if (this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING) - this._authPrompt.reset(); -+ -+ if (this._disableUserList && this._timedLoginUserListHold) -+ this._timedLoginUserListHold.release(); - } - } - -@@ -1020,16 +1023,31 @@ var LoginDialog = GObject.registerClass({ - let loginItem = null; - let animationTime; - -- let tasks = [() => this._waitForItemForUser(userName), -+ let tasks = [() => { -+ if (this._disableUserList) -+ return; -+ -+ this._timedLoginUserListHold = this._waitForItemForUser(userName); -+ -+ return this._timedLoginUserListHold; -+ }, - - () => { -- loginItem = this._userList.getItemFromUserName(userName); -+ this._timedLoginUserListHold = null; -+ -+ -+ loginItem = this._disableUserList -+ ? this._authPrompt -+ : this._userList.getItemFromUserName(userName); - - // If there is an animation running on the item, reset it. - loginItem.hideTimedLoginIndicator(); - }, - - () => { -+ if (this._disableUserList) -+ return; -+ - // If we're just starting out, start on the right item. - if (!this._userManager.is_loaded) { - this._userList.jumpToItem(loginItem); -@@ -1051,6 +1069,9 @@ var LoginDialog = GObject.registerClass({ - }, - - () => { -+ if (this._disableUserList) -+ return; -+ - // If idle timeout is done, make sure the timed login indicator is shown - if (delay > _TIMED_LOGIN_IDLE_THRESHOLD && - this._authPrompt.actor.visible) --- -2.26.2 - diff --git a/SOURCES/caps-lock-warning.patch b/SOURCES/caps-lock-warning.patch deleted file mode 100644 index d3c2daa..0000000 --- a/SOURCES/caps-lock-warning.patch +++ /dev/null @@ -1,488 +0,0 @@ -From 7b514e637837e00372e20fa52f841e993966b734 Mon Sep 17 00:00:00 2001 -From: Umang Jain -Date: Fri, 13 Dec 2019 13:36:14 +0530 -Subject: [PATCH 1/7] shellEntry: Add CapsLockWarning class - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/619 ---- - data/theme/gnome-shell-sass/_common.scss | 5 +++ - js/ui/shellEntry.js | 39 +++++++++++++++++++++++- - 2 files changed, 43 insertions(+), 1 deletion(-) - -diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss -index b1eeb0ce97..19a736ab7d 100644 ---- a/data/theme/gnome-shell-sass/_common.scss -+++ b/data/theme/gnome-shell-sass/_common.scss -@@ -391,6 +391,11 @@ StScrollBar { - padding-bottom: 8px; - } - -+ .prompt-dialog-caps-lock-warning { -+ @extend .prompt-dialog-error-label; -+ padding-left: 6.2em; -+ } -+ - .prompt-dialog-info-label { - font-size: 10pt; - padding-bottom: 8px; -diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js -index 79f1aad3e7..c1738c4064 100644 ---- a/js/ui/shellEntry.js -+++ b/js/ui/shellEntry.js -@@ -1,6 +1,6 @@ - // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - --const { Clutter, Shell, St } = imports.gi; -+const { Clutter, GObject, Pango, Shell, St } = imports.gi; - - const BoxPointer = imports.ui.boxpointer; - const Main = imports.ui.main; -@@ -170,3 +170,40 @@ function addContextMenu(entry, params) { - entry._menuManager = null; - }); - } -+ -+var CapsLockWarning = GObject.registerClass( -+class CapsLockWarning extends St.Label { -+ _init(params) { -+ let defaultParams = { style_class: 'prompt-dialog-error-label' }; -+ super._init(Object.assign(defaultParams, params)); -+ -+ this.text = _('Caps lock is on.'); -+ -+ this._keymap = Clutter.get_default_backend().get_keymap(); -+ -+ this.connect('notify::mapped', () => { -+ if (this.is_mapped()) { -+ this.stateChangedId = this._keymap.connect('state-changed', -+ this._updateCapsLockWarningOpacity.bind(this)); -+ } else { -+ this._keymap.disconnect(this.stateChangedId); -+ this.stateChangedId = 0; -+ } -+ -+ this._updateCapsLockWarningOpacity(); -+ }); -+ -+ this.connect('destroy', () => { -+ if (this.stateChangedId > 0) -+ this._keymap.disconnect(this.stateChangedId); -+ }); -+ -+ this.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; -+ this.clutter_text.line_wrap = true; -+ } -+ -+ _updateCapsLockWarningOpacity() { -+ let capsLockOn = this._keymap.get_caps_lock_state(); -+ this.opacity = capsLockOn ? 255 : 0; -+ } -+}); --- -2.21.1 - - -From aa4938f261454f85c782e59e40d4e5a9e1a01dbc Mon Sep 17 00:00:00 2001 -From: Umang Jain -Date: Wed, 18 Dec 2019 01:33:45 +0530 -Subject: [PATCH 2/7] js: Add caps-lock Warning to the dialogs - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/619 ---- - js/gdm/authPrompt.js | 4 ++++ - js/ui/components/keyring.js | 6 ++++++ - js/ui/components/networkAgent.js | 8 ++++++++ - js/ui/components/polkitAgent.js | 2 ++ - js/ui/shellMountOperation.js | 3 +++ - 5 files changed, 23 insertions(+) - -diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 71069e93b8..3ce9fd0d01 100644 ---- a/js/gdm/authPrompt.js -+++ b/js/gdm/authPrompt.js -@@ -113,6 +113,9 @@ var AuthPrompt = class { - - this._entry.grab_key_focus(); - -+ this._capsLockWarningLabel = new ShellEntry.CapsLockWarning(); -+ this.actor.add_child(this._capsLockWarningLabel); -+ - this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator', - scale_x: 0 }); - -@@ -432,6 +435,7 @@ var AuthPrompt = class { - setPasswordChar(passwordChar) { - this._entry.clutter_text.set_password_char(passwordChar); - this._entry.menu.isPassword = passwordChar != ''; -+ this._capsLockWarningLabel.visible = passwordChar !== ''; - } - - setQuestion(question) { -diff --git a/js/ui/components/keyring.js b/js/ui/components/keyring.js -index 0d9f1e4663..3512fb63b1 100644 ---- a/js/ui/components/keyring.js -+++ b/js/ui/components/keyring.js -@@ -128,6 +128,12 @@ var KeyringDialog = class extends ModalDialog.ModalDialog { - this.prompt.set_password_actor(this._passwordEntry ? this._passwordEntry.clutter_text : null); - this.prompt.set_confirm_actor(this._confirmEntry ? this._confirmEntry.clutter_text : null); - -+ if (this._passwordEntry || this._confirmEntry) { -+ this._capsLockWarningLabel = new ShellEntry.CapsLockWarning(); -+ layout.attach(this._capsLockWarningLabel, 1, row, 1, 1); -+ row++; -+ } -+ - if (this.prompt.choice_visible) { - let choice = new CheckBox.CheckBox(); - this.prompt.bind_property('choice-label', choice.getLabelActor(), 'text', GObject.BindingFlags.SYNC_CREATE); -diff --git a/js/ui/components/networkAgent.js b/js/ui/components/networkAgent.js -index f871c732d9..32d40fb2b9 100644 ---- a/js/ui/components/networkAgent.js -+++ b/js/ui/components/networkAgent.js -@@ -95,6 +95,14 @@ var NetworkSecretDialog = class extends ModalDialog.ModalDialog { - secret.entry.clutter_text.set_password_char('\u25cf'); - } - -+ if (this._content.secrets.some(s => s.password)) { -+ this._capsLockWarningLabel = new ShellEntry.CapsLockWarning(); -+ if (rtl) -+ layout.attach(this._capsLockWarningLabel, 0, pos, 1, 1); -+ else -+ layout.attach(this._capsLockWarningLabel, 1, pos, 1, 1); -+ } -+ - contentBox.messageBox.add(secretTable); - - if (flags & NM.SecretAgentGetSecretsFlags.WPS_PBC_ACTIVE) { -diff --git a/js/ui/components/polkitAgent.js b/js/ui/components/polkitAgent.js -index 21feb40903..734a217335 100644 ---- a/js/ui/components/polkitAgent.js -+++ b/js/ui/components/polkitAgent.js -@@ -108,6 +108,8 @@ var AuthenticationDialog = class extends ModalDialog.ModalDialog { - - this.setInitialKeyFocus(this._passwordEntry); - this._passwordBox.hide(); -+ this._capsLockWarningLabel = new ShellEntry.CapsLockWarning({ style_class: 'prompt-dialog-caps-lock-warning' }); -+ content.messageBox.add(this._capsLockWarningLabel); - - this._errorMessageLabel = new St.Label({ style_class: 'prompt-dialog-error-label' }); - this._errorMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; -diff --git a/js/ui/shellMountOperation.js b/js/ui/shellMountOperation.js -index f976f400f4..3a2377ddaf 100644 ---- a/js/ui/shellMountOperation.js -+++ b/js/ui/shellMountOperation.js -@@ -305,6 +305,9 @@ var ShellMountPasswordDialog = class extends ModalDialog.ModalDialog { - this._passwordBox.add(this._passwordEntry, {expand: true }); - this.setInitialKeyFocus(this._passwordEntry); - -+ this._capsLockWarningLabel = new ShellEntry.CapsLockWarning(); -+ content.messageBox.add(this._capsLockWarningLabel); -+ - this._errorMessageLabel = new St.Label({ style_class: 'prompt-dialog-error-label', - text: _("Sorry, that didn’t work. Please try again.") }); - this._errorMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; --- -2.21.1 - - -From 016cbd971711665844d40ec678d2779c160f791b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= -Date: Thu, 23 Jan 2020 22:37:06 +0100 -Subject: [PATCH 3/7] shellEntry: Make signal id variable private - -Signal connection IDs should be private variables, so make this one -private. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/952 ---- - js/ui/shellEntry.js | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js -index c1738c4064..cd7c9a6c88 100644 ---- a/js/ui/shellEntry.js -+++ b/js/ui/shellEntry.js -@@ -183,19 +183,19 @@ class CapsLockWarning extends St.Label { - - this.connect('notify::mapped', () => { - if (this.is_mapped()) { -- this.stateChangedId = this._keymap.connect('state-changed', -+ this._stateChangedId = this._keymap.connect('state-changed', - this._updateCapsLockWarningOpacity.bind(this)); - } else { -- this._keymap.disconnect(this.stateChangedId); -- this.stateChangedId = 0; -+ this._keymap.disconnect(this._stateChangedId); -+ this._stateChangedId = 0; - } - - this._updateCapsLockWarningOpacity(); - }); - - this.connect('destroy', () => { -- if (this.stateChangedId > 0) -- this._keymap.disconnect(this.stateChangedId); -+ if (this._stateChangedId > 0) -+ this._keymap.disconnect(this._stateChangedId); - }); - - this.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; --- -2.21.1 - - -From ba65f9066d72731e345a5aced61f35d39c1c1376 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= -Date: Thu, 23 Jan 2020 23:26:45 +0100 -Subject: [PATCH 4/7] theme: Move caps-lock warning to entry widget stylesheet - -The caps-lock warning is more related to entries than dialogs and is -also used in gdm, which is not realated to dialogs at all. Rename the -css class to caps-lock-warning-label and move it to the entry -stylesheet. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/952 ---- - data/theme/gnome-shell-sass/_common.scss | 12 +++++++----- - js/ui/shellEntry.js | 2 +- - 2 files changed, 8 insertions(+), 6 deletions(-) - -diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss -index 19a736ab7d..4661533de2 100644 ---- a/data/theme/gnome-shell-sass/_common.scss -+++ b/data/theme/gnome-shell-sass/_common.scss -@@ -94,6 +94,13 @@ StEntry { - } - } - -+.caps-lock-warning-label { -+ padding-left: 6.2em; -+ @include fontsize($font-size - 1); -+ color: $warning_color; -+} -+ -+ - - /* Scrollbars */ - -@@ -391,11 +398,6 @@ StScrollBar { - padding-bottom: 8px; - } - -- .prompt-dialog-caps-lock-warning { -- @extend .prompt-dialog-error-label; -- padding-left: 6.2em; -- } -- - .prompt-dialog-info-label { - font-size: 10pt; - padding-bottom: 8px; -diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js -index cd7c9a6c88..46eba88d54 100644 ---- a/js/ui/shellEntry.js -+++ b/js/ui/shellEntry.js -@@ -174,7 +174,7 @@ function addContextMenu(entry, params) { - var CapsLockWarning = GObject.registerClass( - class CapsLockWarning extends St.Label { - _init(params) { -- let defaultParams = { style_class: 'prompt-dialog-error-label' }; -+ let defaultParams = { style_class: 'caps-lock-warning-label' }; - super._init(Object.assign(defaultParams, params)); - - this.text = _('Caps lock is on.'); --- -2.21.1 - - -From afd764c82febe21aec70bdfc19d256f3401530e1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= -Date: Thu, 23 Jan 2020 22:36:09 +0100 -Subject: [PATCH 5/7] shellEntry: Hide caps lock warning and use animation to - show it - -Since the caps-lock warning adds a lot of spacing to dialogs and the -lock screen, hide it by default and only show it when necessary. To make -the transition smooth instead of just showing the label, animate it in -using the height and opacity. - -Also add some bottom padding to the label so we can show or hide that -padding, too. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/952 ---- - data/theme/gnome-shell-sass/_common.scss | 1 + - js/ui/shellEntry.js | 33 ++++++++++++++++++------ - 2 files changed, 26 insertions(+), 8 deletions(-) - -diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss -index 4661533de2..9e0751c8c5 100644 ---- a/data/theme/gnome-shell-sass/_common.scss -+++ b/data/theme/gnome-shell-sass/_common.scss -@@ -95,6 +95,7 @@ StEntry { - } - - .caps-lock-warning-label { -+ padding-bottom: 8px; - padding-left: 6.2em; - @include fontsize($font-size - 1); - color: $warning_color; -diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js -index 46eba88d54..fc8ee37a9a 100644 ---- a/js/ui/shellEntry.js -+++ b/js/ui/shellEntry.js -@@ -6,6 +6,7 @@ const BoxPointer = imports.ui.boxpointer; - const Main = imports.ui.main; - const Params = imports.misc.params; - const PopupMenu = imports.ui.popupMenu; -+const Tweener = imports.ui.tweener; - - var EntryMenu = class extends PopupMenu.PopupMenu { - constructor(entry) { -@@ -179,31 +180,47 @@ class CapsLockWarning extends St.Label { - - this.text = _('Caps lock is on.'); - -+ this.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; -+ this.clutter_text.line_wrap = true; -+ - this._keymap = Clutter.get_default_backend().get_keymap(); - - this.connect('notify::mapped', () => { - if (this.is_mapped()) { - this._stateChangedId = this._keymap.connect('state-changed', -- this._updateCapsLockWarningOpacity.bind(this)); -+ () => this._sync(true)); - } else { - this._keymap.disconnect(this._stateChangedId); - this._stateChangedId = 0; - } - -- this._updateCapsLockWarningOpacity(); -+ this._sync(false); - }); - - this.connect('destroy', () => { -- if (this._stateChangedId > 0) -+ if (this._stateChangedId) - this._keymap.disconnect(this._stateChangedId); - }); -- -- this.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; -- this.clutter_text.line_wrap = true; - } - -- _updateCapsLockWarningOpacity() { -+ _sync(animate) { - let capsLockOn = this._keymap.get_caps_lock_state(); -- this.opacity = capsLockOn ? 255 : 0; -+ -+ Tweener.removeTweens(this); -+ -+ this.natural_height_set = false; -+ let [, height] = this.get_preferred_height(-1); -+ this.natural_height_set = true; -+ -+ Tweener.addTween(this, { -+ height: capsLockOn ? height : 0, -+ opacity: capsLockOn ? 255 : 0, -+ time: animate ? 0.2 : 0, -+ transition: 'easeOutQuad', -+ onComplete: () => { -+ if (capsLockOn) -+ this.height = -1; -+ }, -+ }); - } - }); --- -2.21.1 - - -From 1ef3dafb51da380c54635d0565dc098e40bbb3e1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 29 Jan 2020 17:48:57 +0100 -Subject: [PATCH 6/7] js: Initialize some properties - -Otherwise those can result in the (harmless) "reference to undefined -property" warnings. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/970 ---- - js/ui/overview.js | 1 + - js/ui/shellEntry.js | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/js/ui/overview.js b/js/ui/overview.js -index dc6ad1821b..5bad4cbd62 100644 ---- a/js/ui/overview.js -+++ b/js/ui/overview.js -@@ -80,6 +80,7 @@ var Overview = class { - constructor() { - this._overviewCreated = false; - this._initCalled = false; -+ this._visible = false; - - Main.sessionMode.connect('updated', this._sessionUpdated.bind(this)); - this._sessionUpdated(); -diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js -index fc8ee37a9a..55267e7c87 100644 ---- a/js/ui/shellEntry.js -+++ b/js/ui/shellEntry.js -@@ -184,6 +184,7 @@ class CapsLockWarning extends St.Label { - this.clutter_text.line_wrap = true; - - this._keymap = Clutter.get_default_backend().get_keymap(); -+ this._stateChangedId = 0; - - this.connect('notify::mapped', () => { - if (this.is_mapped()) { --- -2.21.1 - - -From 273f7adb43cfee907342d017e1454ea90d42d262 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Fri, 21 Feb 2020 19:38:53 +0100 -Subject: [PATCH 7/7] shellEntry: Restore natural-height-set instead of forcing - it - -If we are transitioning the label from 0 to its natural height, we -must set natural-height-set again after querying the preferred height, -otherwise Clutter would skip the transition. - -However when transitioning in the opposite direction, setting the -property to true can go horribly wrong: -If the actor hasn't been allocated before, it will store a fixed -natural height of 0. But as there is no fixed min-height, we can -end up with min-height > natural-height, which is a fatal error. - -(This isn't an issue when *actually* setting a fixed height, as -that will set both natural and minimum height) - -So instead of always setting natural-height-set to true, restore -its previous value to fix the issue. - -https://gitlab.gnome.org/GNOME/gnome-shell/issues/2255 ---- - js/ui/shellEntry.js | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js -index 55267e7c87..4a30b22f7a 100644 ---- a/js/ui/shellEntry.js -+++ b/js/ui/shellEntry.js -@@ -209,9 +209,10 @@ class CapsLockWarning extends St.Label { - - Tweener.removeTweens(this); - -+ const naturalHeightSet = this.natural_height_set; - this.natural_height_set = false; - let [, height] = this.get_preferred_height(-1); -- this.natural_height_set = true; -+ this.natural_height_set = naturalHeightSet; - - Tweener.addTween(this, { - height: capsLockOn ? height : 0, --- -2.21.1 - diff --git a/SOURCES/defend-against-corrupt-notifications.patch b/SOURCES/defend-against-corrupt-notifications.patch deleted file mode 100644 index 9957a7b..0000000 --- a/SOURCES/defend-against-corrupt-notifications.patch +++ /dev/null @@ -1,145 +0,0 @@ -From 7bdd1962213a37f6218fe15ea1a4062dd318672a Mon Sep 17 00:00:00 2001 -From: Will Thompson -Date: Wed, 28 Aug 2019 15:39:44 +0100 -Subject: [PATCH 1/2] global: Don't trust persistent/runtime state data - -An Endless OS system was found in the wild with a malformed -.local/share/gnome-shell/notifications. When deserialized in Python, -after passing trusted=True to g_variant_new_from_bytes(), the first -element of the first struct in the array looks like this: - - In [41]: _38.get_child_value(0).get_child_value(0) - Out[41]: GLib.Variant('s', '\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff') - -When deserialised in GJS, we get: - - gjs> v.get_child_value(0).get_child_value(0) - [object variant of type "s"] - gjs> v.get_child_value(0).get_child_value(0).get_string() - typein:43:1 malformed UTF-8 character sequence at offset 0 - @typein:43:1 - @:1:34 - -While g_variant_new_from_bytes() doesn't have much to say about its -'trusted' parameter, g_variant_new_from_data() does: - -> If data is trusted to be serialised data in normal form then trusted -> should be TRUE. This applies to serialised data created within this -> process or read from a trusted location on the disk (such as a file -> installed in /usr/lib alongside your application). You should set -> trusted to FALSE if data is read from the network, a file in the -> user's home directory, etc. - -Persistent state is read from the user's home directory, so it should -not be trusted. With trusted=False, the string value above comes out as -"". - -I don't have an explanation for how this file ended up being malformed. -I also don't have an explanation for when this started crashing: my -guess is that recent GJS became stricter about validating UTF-8 but I -could be wrong! - -https://gitlab.gnome.org/GNOME/gnome-shell/issues/1552 ---- - src/shell-global.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/shell-global.c b/src/shell-global.c -index 4b33778e0..33046f614 100644 ---- a/src/shell-global.c -+++ b/src/shell-global.c -@@ -1707,7 +1707,7 @@ load_variant (GFile *dir, - else - { - GBytes *bytes = g_mapped_file_get_bytes (mfile); -- res = g_variant_new_from_bytes (G_VARIANT_TYPE (property_type), bytes, TRUE); -+ res = g_variant_new_from_bytes (G_VARIANT_TYPE (property_type), bytes, FALSE); - g_bytes_unref (bytes); - g_mapped_file_unref (mfile); - } --- -2.35.1 - - -From 13dcb3e4400b92a0d2f548e88b70b358240d462c Mon Sep 17 00:00:00 2001 -From: Will Thompson -Date: Wed, 28 Aug 2019 15:38:03 +0100 -Subject: [PATCH 2/2] notificationDaemon: Catch exceptions while loading - notifications - -An Endless OS system was found in the wild with a malformed -.local/share/gnome-shell/notifications which causes _loadNotifications() -to raise an exception. This exception was not previously handled and -bubbles all the way out to gnome_shell_plugin_start(), whereupon the -shell exit(1)s. The user could no longer log into their computer. - -Handle exceptions from _loadNotifications(), log them, and attempt to -continue. Ensure that this._isLoading is set to 'false' even on error, -so that future calls to _saveNotifications() can overwrite the (corrupt) -state file. - -https://gitlab.gnome.org/GNOME/gnome-shell/issues/1552 ---- - js/ui/notificationDaemon.js | 42 ++++++++++++++++++++----------------- - 1 file changed, 23 insertions(+), 19 deletions(-) - -diff --git a/js/ui/notificationDaemon.js b/js/ui/notificationDaemon.js -index 4bdede841..dbe673b88 100644 ---- a/js/ui/notificationDaemon.js -+++ b/js/ui/notificationDaemon.js -@@ -749,29 +749,33 @@ var GtkNotificationDaemon = class GtkNotificationDaemon { - _loadNotifications() { - this._isLoading = true; - -- let value = global.get_persistent_state('a(sa(sv))', 'notifications'); -- if (value) { -- let sources = value.deep_unpack(); -- sources.forEach(([appId, notifications]) => { -- if (notifications.length == 0) -- return; -- -- let source; -- try { -- source = this._ensureAppSource(appId); -- } catch(e) { -- if (e instanceof InvalidAppError) -+ try { -+ let value = global.get_persistent_state('a(sa(sv))', 'notifications'); -+ if (value) { -+ let sources = value.deep_unpack(); -+ sources.forEach(([appId, notifications]) => { -+ if (notifications.length == 0) - return; -- throw e; -- } - -- notifications.forEach(([notificationId, notification]) => { -- source.addNotification(notificationId, notification.deep_unpack(), false); -+ let source; -+ try { -+ source = this._ensureAppSource(appId); -+ } catch (e) { -+ if (e instanceof InvalidAppError) -+ return; -+ throw e; -+ } -+ -+ notifications.forEach(([notificationId, notification]) => { -+ source.addNotification(notificationId, notification.deep_unpack(), false); -+ }); - }); -- }); -+ } -+ } catch (e) { -+ logError(e, 'Failed to load saved notifications'); -+ } finally { -+ this._isLoading = false; - } -- -- this._isLoading = false; - } - - _saveNotifications() { --- -2.35.1 - diff --git a/SOURCES/extension-updates.patch b/SOURCES/extension-updates.patch deleted file mode 100644 index acc7826..0000000 --- a/SOURCES/extension-updates.patch +++ /dev/null @@ -1,3810 +0,0 @@ -From ab3a275e20c36cc21e529bb2c4328ea36024ecba Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Sat, 6 Jul 2019 15:31:57 +0200 -Subject: [PATCH 01/26] extensionUtils: Move ExtensionState definition here - -It makes sense to keep extension-related enums in the same module instead -of spreading them between ExtensionSystem and ExtensionUtils. - -More importantly, this will make the type available to the extensions-prefs -tool (which runs in a different process and therefore only has access to -a limited set of modules). - -https://bugzilla.gnome.org/show_bug.cgi?id=789852 ---- - js/misc/extensionUtils.js | 13 +++++++++++++ - js/ui/extensionSystem.js | 13 +------------ - js/ui/lookingGlass.js | 14 ++++++++------ - 3 files changed, 22 insertions(+), 18 deletions(-) - -diff --git a/js/misc/extensionUtils.js b/js/misc/extensionUtils.js -index fb1e2b506..dc6e74cf8 100644 ---- a/js/misc/extensionUtils.js -+++ b/js/misc/extensionUtils.js -@@ -17,6 +17,19 @@ var ExtensionType = { - SESSION_MODE: 3 - }; - -+var ExtensionState = { -+ ENABLED: 1, -+ DISABLED: 2, -+ ERROR: 3, -+ OUT_OF_DATE: 4, -+ DOWNLOADING: 5, -+ INITIALIZED: 6, -+ -+ // Used as an error state for operations on unknown extensions, -+ // should never be in a real extensionMeta object. -+ UNINSTALLED: 99 -+}; -+ - // Maps uuid -> metadata object - var extensions = {}; - -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index 9ffdb4f3d..3091af2ba 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -6,18 +6,7 @@ const Signals = imports.signals; - const ExtensionUtils = imports.misc.extensionUtils; - const Main = imports.ui.main; - --var ExtensionState = { -- ENABLED: 1, -- DISABLED: 2, -- ERROR: 3, -- OUT_OF_DATE: 4, -- DOWNLOADING: 5, -- INITIALIZED: 6, -- -- // Used as an error state for operations on unknown extensions, -- // should never be in a real extensionMeta object. -- UNINSTALLED: 99 --}; -+const { ExtensionState } = ExtensionUtils; - - // Arrays of uuids - var enabledExtensions; -diff --git a/js/ui/lookingGlass.js b/js/ui/lookingGlass.js -index 958211df0..fefb3f731 100644 ---- a/js/ui/lookingGlass.js -+++ b/js/ui/lookingGlass.js -@@ -14,6 +14,8 @@ const Tweener = imports.ui.tweener; - const Main = imports.ui.main; - const JsParse = imports.misc.jsParse; - -+const { ExtensionState } = ExtensionUtils; -+ - const CHEVRON = '>>> '; - - /* Imports...feel free to add here as needed */ -@@ -684,16 +686,16 @@ var Extensions = class Extensions { - - _stateToString(extensionState) { - switch (extensionState) { -- case ExtensionSystem.ExtensionState.ENABLED: -+ case ExtensionState.ENABLED: - return _("Enabled"); -- case ExtensionSystem.ExtensionState.DISABLED: -- case ExtensionSystem.ExtensionState.INITIALIZED: -+ case ExtensionState.DISABLED: -+ case ExtensionState.INITIALIZED: - return _("Disabled"); -- case ExtensionSystem.ExtensionState.ERROR: -+ case ExtensionState.ERROR: - return _("Error"); -- case ExtensionSystem.ExtensionState.OUT_OF_DATE: -+ case ExtensionState.OUT_OF_DATE: - return _("Out of date"); -- case ExtensionSystem.ExtensionState.DOWNLOADING: -+ case ExtensionState.DOWNLOADING: - return _("Downloading"); - } - return 'Unknown'; // Not translated, shouldn't appear --- -2.29.2 - - -From c16d1589d093dac4e0efe21c7f1aeb635afabd0f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Thu, 7 Mar 2019 01:45:45 +0100 -Subject: [PATCH 02/26] extensionSystem: Turn into a class - -The extension system started out as a set of simple functions, but -gained more state later, and even some hacks to emit signals without -having an object to emit them on. - -There is no good reason for that weirdness, so rather than imitating an -object, wrap the existing system into a real ExtensionManager object. - -https://bugzilla.gnome.org/show_bug.cgi?id=789852 ---- - js/ui/extensionDownloader.js | 17 +- - js/ui/extensionSystem.js | 569 +++++++++++++++++------------------ - js/ui/lookingGlass.js | 5 +- - js/ui/main.js | 3 +- - js/ui/shellDBus.js | 7 +- - 5 files changed, 297 insertions(+), 304 deletions(-) - -diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js -index 9aed29c69..fe37463f2 100644 ---- a/js/ui/extensionDownloader.js -+++ b/js/ui/extensionDownloader.js -@@ -6,6 +6,7 @@ const Config = imports.misc.config; - const ExtensionUtils = imports.misc.extensionUtils; - const ExtensionSystem = imports.ui.extensionSystem; - const FileUtils = imports.misc.fileUtils; -+const Main = imports.ui.main; - const ModalDialog = imports.ui.modalDialog; - - const _signals = ExtensionSystem._signals; -@@ -25,7 +26,7 @@ function installExtension(uuid, invocation) { - - _httpSession.queue_message(message, (session, message) => { - if (message.status_code != Soup.KnownStatusCode.OK) { -- ExtensionSystem.logExtensionError(uuid, 'downloading info: ' + message.status_code); -+ Main.extensionManager.logExtensionError(uuid, 'downloading info: ' + message.status_code); - invocation.return_dbus_error('org.gnome.Shell.DownloadInfoError', message.status_code.toString()); - return; - } -@@ -34,7 +35,7 @@ function installExtension(uuid, invocation) { - try { - info = JSON.parse(message.response_body.data); - } catch (e) { -- ExtensionSystem.logExtensionError(uuid, 'parsing info: ' + e); -+ Main.extensionManager.logExtensionError(uuid, 'parsing info: ' + e); - invocation.return_dbus_error('org.gnome.Shell.ParseInfoError', e.toString()); - return; - } -@@ -53,7 +54,7 @@ function uninstallExtension(uuid) { - if (extension.type != ExtensionUtils.ExtensionType.PER_USER) - return false; - -- if (!ExtensionSystem.unloadExtension(extension)) -+ if (!Main.extensionManager.unloadExtension(extension)) - return false; - - FileUtils.recursivelyDeleteDir(extension.dir, true); -@@ -117,7 +118,7 @@ function updateExtension(uuid) { - let oldExtension = ExtensionUtils.extensions[uuid]; - let extensionDir = oldExtension.dir; - -- if (!ExtensionSystem.unloadExtension(oldExtension)) -+ if (!Main.extensionManager.unloadExtension(oldExtension)) - return; - - FileUtils.recursivelyMoveDir(extensionDir, oldExtensionTmpDir); -@@ -127,10 +128,10 @@ function updateExtension(uuid) { - - try { - extension = ExtensionUtils.createExtensionObject(uuid, extensionDir, ExtensionUtils.ExtensionType.PER_USER); -- ExtensionSystem.loadExtension(extension); -+ Main.extensionManager.loadExtension(extension); - } catch(e) { - if (extension) -- ExtensionSystem.unloadExtension(extension); -+ Main.extensionManager.unloadExtension(extension); - - logError(e, 'Error loading extension %s'.format(uuid)); - -@@ -139,7 +140,7 @@ function updateExtension(uuid) { - - // Restore what was there before. We can't do much if we - // fail here. -- ExtensionSystem.loadExtension(oldExtension); -+ Main.extensionManager.loadExtension(oldExtension); - return; - } - -@@ -239,7 +240,7 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog { - - try { - let extension = ExtensionUtils.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER); -- ExtensionSystem.loadExtension(extension); -+ Main.extensionManager.loadExtension(extension); - } catch(e) { - uninstallExtension(uuid); - errback('LoadExtensionError', e); -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index 3091af2ba..b7e908223 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -8,358 +8,351 @@ const Main = imports.ui.main; - - const { ExtensionState } = ExtensionUtils; - --// Arrays of uuids --var enabledExtensions; --// Contains the order that extensions were enabled in. --var extensionOrder = []; -- --// We don't really have a class to add signals on. So, create --// a simple dummy object, add the signal methods, and export those --// publically. --var _signals = {}; --Signals.addSignalMethods(_signals); -- --var connect = _signals.connect.bind(_signals); --var disconnect = _signals.disconnect.bind(_signals); -- - const ENABLED_EXTENSIONS_KEY = 'enabled-extensions'; - const DISABLE_USER_EXTENSIONS_KEY = 'disable-user-extensions'; - const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validation'; - --var initted = false; --var enabled; -+var ExtensionManager = class { -+ constructor() { -+ this._initted = false; -+ this._enabled = false; - --function disableExtension(uuid) { -- let extension = ExtensionUtils.extensions[uuid]; -- if (!extension) -- return; -+ this._enabledExtensions = []; -+ this._extensionOrder = []; - -- if (extension.state != ExtensionState.ENABLED) -- return; -+ Main.sessionMode.connect('updated', this._sessionUpdated.bind(this)); -+ this._sessionUpdated(); -+ } - -- // "Rebase" the extension order by disabling and then enabling extensions -- // in order to help prevent conflicts. -+ disableExtension(uuid) { -+ let extension = ExtensionUtils.extensions[uuid]; -+ if (!extension) -+ return; - -- // Example: -- // order = [A, B, C, D, E] -- // user disables C -- // this should: disable E, disable D, disable C, enable D, enable E -+ if (extension.state != ExtensionState.ENABLED) -+ return; - -- let orderIdx = extensionOrder.indexOf(uuid); -- let order = extensionOrder.slice(orderIdx + 1); -- let orderReversed = order.slice().reverse(); -+ // "Rebase" the extension order by disabling and then enabling extensions -+ // in order to help prevent conflicts. -+ -+ // Example: -+ // order = [A, B, C, D, E] -+ // user disables C -+ // this should: disable E, disable D, disable C, enable D, enable E -+ -+ let orderIdx = this._extensionOrder.indexOf(uuid); -+ let order = this._extensionOrder.slice(orderIdx + 1); -+ let orderReversed = order.slice().reverse(); -+ -+ for (let i = 0; i < orderReversed.length; i++) { -+ let uuid = orderReversed[i]; -+ try { -+ ExtensionUtils.extensions[uuid].stateObj.disable(); -+ } catch (e) { -+ this.logExtensionError(uuid, e); -+ } -+ } -+ -+ if (extension.stylesheet) { -+ let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); -+ theme.unload_stylesheet(extension.stylesheet); -+ delete extension.stylesheet; -+ } - -- for (let i = 0; i < orderReversed.length; i++) { -- let uuid = orderReversed[i]; - try { -- ExtensionUtils.extensions[uuid].stateObj.disable(); -+ extension.stateObj.disable(); - } catch(e) { -- logExtensionError(uuid, e); -+ this.logExtensionError(uuid, e); - } -- } - -- if (extension.stylesheet) { -- let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); -- theme.unload_stylesheet(extension.stylesheet); -- delete extension.stylesheet; -- } -+ for (let i = 0; i < order.length; i++) { -+ let uuid = order[i]; -+ try { -+ ExtensionUtils.extensions[uuid].stateObj.enable(); -+ } catch (e) { -+ this.logExtensionError(uuid, e); -+ } -+ } - -- try { -- extension.stateObj.disable(); -- } catch(e) { -- logExtensionError(uuid, e); -- } -+ this._extensionOrder.splice(orderIdx, 1); - -- for (let i = 0; i < order.length; i++) { -- let uuid = order[i]; -- try { -- ExtensionUtils.extensions[uuid].stateObj.enable(); -- } catch(e) { -- logExtensionError(uuid, e); -+ if (extension.state != ExtensionState.ERROR) { -+ extension.state = ExtensionState.DISABLED; -+ this.emit('extension-state-changed', extension); - } - } - -- extensionOrder.splice(orderIdx, 1); -- -- if ( extension.state != ExtensionState.ERROR ) { -- extension.state = ExtensionState.DISABLED; -- _signals.emit('extension-state-changed', extension); -- } --} -+ enableExtension(uuid) { -+ let extension = ExtensionUtils.extensions[uuid]; -+ if (!extension) -+ return; - --function enableExtension(uuid) { -- let extension = ExtensionUtils.extensions[uuid]; -- if (!extension) -- return; -+ if (extension.state == ExtensionState.INITIALIZED) -+ this.initExtension(uuid); - -- if (extension.state == ExtensionState.INITIALIZED) -- initExtension(uuid); -+ if (extension.state != ExtensionState.DISABLED) -+ return; - -- if (extension.state != ExtensionState.DISABLED) -- return; -+ this._extensionOrder.push(uuid); - -- extensionOrder.push(uuid); -+ let stylesheetNames = [global.session_mode + '.css', 'stylesheet.css']; -+ let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); -+ for (let i = 0; i < stylesheetNames.length; i++) { -+ try { -+ let stylesheetFile = extension.dir.get_child(stylesheetNames[i]); -+ theme.load_stylesheet(stylesheetFile); -+ extension.stylesheet = stylesheetFile; -+ break; -+ } catch (e) { -+ if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) -+ continue; // not an error -+ log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`); -+ return; -+ } -+ } - -- let stylesheetNames = [global.session_mode + '.css', 'stylesheet.css']; -- let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); -- for (let i = 0; i < stylesheetNames.length; i++) { - try { -- let stylesheetFile = extension.dir.get_child(stylesheetNames[i]); -- theme.load_stylesheet(stylesheetFile); -- extension.stylesheet = stylesheetFile; -- break; -+ extension.stateObj.enable(); -+ extension.state = ExtensionState.ENABLED; -+ this.emit('extension-state-changed', extension); -+ return; - } catch (e) { -- if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) -- continue; // not an error -- log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`); -+ if (extension.stylesheet) { -+ theme.unload_stylesheet(extension.stylesheet); -+ delete extension.stylesheet; -+ } -+ this.logExtensionError(uuid, e); - return; - } - } - -- try { -- extension.stateObj.enable(); -- extension.state = ExtensionState.ENABLED; -- _signals.emit('extension-state-changed', extension); -- return; -- } catch(e) { -- if (extension.stylesheet) { -- theme.unload_stylesheet(extension.stylesheet); -- delete extension.stylesheet; -- } -- logExtensionError(uuid, e); -- return; -- } --} -- --function logExtensionError(uuid, error) { -- let extension = ExtensionUtils.extensions[uuid]; -- if (!extension) -- return; -+ logExtensionError(uuid, error) { -+ let extension = ExtensionUtils.extensions[uuid]; -+ if (!extension) -+ return; - -- let message = '' + error; -+ let message = '' + error; - -- extension.state = ExtensionState.ERROR; -- if (!extension.errors) -- extension.errors = []; -- extension.errors.push(message); -+ extension.state = ExtensionState.ERROR; -+ if (!extension.errors) -+ extension.errors = []; -+ extension.errors.push(message); - -- log('Extension "%s" had error: %s'.format(uuid, message)); -- _signals.emit('extension-state-changed', { uuid: uuid, -+ log('Extension "%s" had error: %s'.format(uuid, message)); -+ this.emit('extension-state-changed', { uuid: uuid, - error: message, - state: extension.state }); --} -+ } - --function loadExtension(extension) { -- // Default to error, we set success as the last step -- extension.state = ExtensionState.ERROR; -+ loadExtension(extension) { -+ // Default to error, we set success as the last step -+ extension.state = ExtensionState.ERROR; - -- let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY); -+ let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY); - -- if (checkVersion && ExtensionUtils.isOutOfDate(extension)) { -- extension.state = ExtensionState.OUT_OF_DATE; -- } else { -- let enabled = enabledExtensions.indexOf(extension.uuid) != -1; -- if (enabled) { -- if (!initExtension(extension.uuid)) -- return; -- if (extension.state == ExtensionState.DISABLED) -- enableExtension(extension.uuid); -+ if (checkVersion && ExtensionUtils.isOutOfDate(extension)) { -+ extension.state = ExtensionState.OUT_OF_DATE; - } else { -- extension.state = ExtensionState.INITIALIZED; -+ let enabled = this._enabledExtensions.includes(extension.uuid); -+ if (enabled) { -+ if (!this.initExtension(extension.uuid)) -+ return; -+ if (extension.state == ExtensionState.DISABLED) -+ this.enableExtension(extension.uuid); -+ } else { -+ extension.state = ExtensionState.INITIALIZED; -+ } - } -+ -+ this.emit('extension-state-changed', extension); - } - -- _signals.emit('extension-state-changed', extension); --} -- --function unloadExtension(extension) { -- // Try to disable it -- if it's ERROR'd, we can't guarantee that, -- // but it will be removed on next reboot, and hopefully nothing -- // broke too much. -- disableExtension(extension.uuid); -- -- extension.state = ExtensionState.UNINSTALLED; -- _signals.emit('extension-state-changed', extension); -- -- delete ExtensionUtils.extensions[extension.uuid]; -- return true; --} -- --function reloadExtension(oldExtension) { -- // Grab the things we'll need to pass to createExtensionObject -- // to reload it. -- let { uuid: uuid, dir: dir, type: type } = oldExtension; -- -- // Then unload the old extension. -- unloadExtension(oldExtension); -- -- // Now, recreate the extension and load it. -- let newExtension; -- try { -- newExtension = ExtensionUtils.createExtensionObject(uuid, dir, type); -- } catch(e) { -- logExtensionError(uuid, e); -- return; -+ unloadExtension(extension) { -+ // Try to disable it -- if it's ERROR'd, we can't guarantee that, -+ // but it will be removed on next reboot, and hopefully nothing -+ // broke too much. -+ this.disableExtension(extension.uuid); -+ -+ extension.state = ExtensionState.UNINSTALLED; -+ this.emit('extension-state-changed', extension); -+ -+ delete ExtensionUtils.extensions[extension.uuid]; -+ return true; - } - -- loadExtension(newExtension); --} -+ reloadExtension(oldExtension) { -+ // Grab the things we'll need to pass to createExtensionObject -+ // to reload it. -+ let { uuid: uuid, dir: dir, type: type } = oldExtension; - --function initExtension(uuid) { -- let extension = ExtensionUtils.extensions[uuid]; -- let dir = extension.dir; -+ // Then unload the old extension. -+ this.unloadExtension(oldExtension); - -- if (!extension) -- throw new Error("Extension was not properly created. Call loadExtension first"); -+ // Now, recreate the extension and load it. -+ let newExtension; -+ try { -+ newExtension = ExtensionUtils.createExtensionObject(uuid, dir, type); -+ } catch (e) { -+ this.logExtensionError(uuid, e); -+ return; -+ } - -- let extensionJs = dir.get_child('extension.js'); -- if (!extensionJs.query_exists(null)) { -- logExtensionError(uuid, new Error('Missing extension.js')); -- return false; -+ this.loadExtension(newExtension); - } - -- let extensionModule; -- let extensionState = null; -+ initExtension(uuid) { -+ let extension = ExtensionUtils.extensions[uuid]; -+ let dir = extension.dir; - -- ExtensionUtils.installImporter(extension); -- try { -- extensionModule = extension.imports.extension; -- } catch(e) { -- logExtensionError(uuid, e); -- return false; -- } -+ if (!extension) -+ throw new Error("Extension was not properly created. Call loadExtension first"); -+ -+ let extensionJs = dir.get_child('extension.js'); -+ if (!extensionJs.query_exists(null)) { -+ this.logExtensionError(uuid, new Error('Missing extension.js')); -+ return false; -+ } -+ -+ let extensionModule; -+ let extensionState = null; - -- if (extensionModule.init) { -+ ExtensionUtils.installImporter(extension); - try { -- extensionState = extensionModule.init(extension); -+ extensionModule = extension.imports.extension; - } catch(e) { -- logExtensionError(uuid, e); -+ this.logExtensionError(uuid, e); - return false; - } -+ -+ if (extensionModule.init) { -+ try { -+ extensionState = extensionModule.init(extension); -+ } catch (e) { -+ this.logExtensionError(uuid, e); -+ return false; -+ } -+ } -+ -+ if (!extensionState) -+ extensionState = extensionModule; -+ extension.stateObj = extensionState; -+ -+ extension.state = ExtensionState.DISABLED; -+ this.emit('extension-loaded', uuid); -+ return true; - } - -- if (!extensionState) -- extensionState = extensionModule; -- extension.stateObj = extensionState; -- -- extension.state = ExtensionState.DISABLED; -- _signals.emit('extension-loaded', uuid); -- return true; --} -- --function getEnabledExtensions() { -- let extensions; -- if (Array.isArray(Main.sessionMode.enabledExtensions)) -- extensions = Main.sessionMode.enabledExtensions; -- else -- extensions = []; -- -- if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY)) -- return extensions; -- -- return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY)); --} -- --function onEnabledExtensionsChanged() { -- let newEnabledExtensions = getEnabledExtensions(); -- -- if (!enabled) -- return; -- -- // Find and enable all the newly enabled extensions: UUIDs found in the -- // new setting, but not in the old one. -- newEnabledExtensions.filter( -- uuid => !enabledExtensions.includes(uuid) -- ).forEach(uuid => { -- enableExtension(uuid); -- }); -- -- // Find and disable all the newly disabled extensions: UUIDs found in the -- // old setting, but not in the new one. -- enabledExtensions.filter( -- item => !newEnabledExtensions.includes(item) -- ).forEach(uuid => { -- disableExtension(uuid); -- }); -- -- enabledExtensions = newEnabledExtensions; --} -- --function _onVersionValidationChanged() { -- // we want to reload all extensions, but only enable -- // extensions when allowed by the sessionMode, so -- // temporarily disable them all -- enabledExtensions = []; -- for (let uuid in ExtensionUtils.extensions) -- reloadExtension(ExtensionUtils.extensions[uuid]); -- enabledExtensions = getEnabledExtensions(); -- -- if (Main.sessionMode.allowExtensions) { -- enabledExtensions.forEach(uuid => { -- enableExtension(uuid); -- }); -+ _getEnabledExtensions() { -+ let extensions; -+ if (Array.isArray(Main.sessionMode.enabledExtensions)) -+ extensions = Main.sessionMode.enabledExtensions; -+ else -+ extensions = []; -+ -+ if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY)) -+ return extensions; -+ -+ return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY)); - } --} -- --function _loadExtensions() { -- global.settings.connect('changed::' + ENABLED_EXTENSIONS_KEY, onEnabledExtensionsChanged); -- global.settings.connect('changed::' + DISABLE_USER_EXTENSIONS_KEY, onEnabledExtensionsChanged); -- global.settings.connect('changed::' + EXTENSION_DISABLE_VERSION_CHECK_KEY, _onVersionValidationChanged); -- -- enabledExtensions = getEnabledExtensions(); -- -- let finder = new ExtensionUtils.ExtensionFinder(); -- finder.connect('extension-found', (finder, extension) => { -- loadExtension(extension); -- if (Main.sessionMode.enabledExtensions.indexOf(extension.uuid) != -1) -- extension.type = ExtensionUtils.ExtensionType.SESSION_MODE; -- }); -- finder.scanExtensions(); --} -- --function enableAllExtensions() { -- if (enabled) -- return; -- -- if (!initted) { -- _loadExtensions(); -- initted = true; -- } else { -- enabledExtensions.forEach(uuid => { -- enableExtension(uuid); -+ -+ _onEnabledExtensionsChanged() { -+ let newEnabledExtensions = this._getEnabledExtensions(); -+ -+ if (!this._enabled) -+ return; -+ -+ // Find and enable all the newly enabled extensions: UUIDs found in the -+ // new setting, but not in the old one. -+ newEnabledExtensions.filter( -+ uuid => !this._enabledExtensions.includes(uuid) -+ ).forEach(uuid => { -+ this.enableExtension(uuid); - }); -+ -+ // Find and disable all the newly disabled extensions: UUIDs found in the -+ // old setting, but not in the new one. -+ this._enabledExtensions.filter( -+ item => !newEnabledExtensions.includes(item) -+ ).forEach(uuid => { -+ this.disableExtension(uuid); -+ }); -+ -+ this._enabledExtensions = newEnabledExtensions; -+ } -+ -+ _onVersionValidationChanged() { -+ // we want to reload all extensions, but only enable -+ // extensions when allowed by the sessionMode, so -+ // temporarily disable them all -+ this._enabledExtensions = []; -+ for (let uuid in ExtensionUtils.extensions) -+ this.reloadExtension(ExtensionUtils.extensions[uuid]); -+ this._enabledExtensions = this._getEnabledExtensions(); -+ -+ if (Main.sessionMode.allowExtensions) { -+ this._enabledExtensions.forEach(uuid => { -+ this.enableExtension(uuid); -+ }); -+ } - } -- enabled = true; --} - --function disableAllExtensions() { -- if (!enabled) -- return; -+ _loadExtensions() { -+ global.settings.connect(`changed::${ENABLED_EXTENSIONS_KEY}`, -+ this._onEnabledExtensionsChanged.bind(this)); -+ global.settings.connect(`changed::${DISABLE_USER_EXTENSIONS_KEY}`, -+ this._onEnabledExtensionsChanged.bind(this)); -+ global.settings.connect(`changed::${EXTENSION_DISABLE_VERSION_CHECK_KEY}`, -+ this._onVersionValidationChanged.bind(this)); -+ -+ this._enabledExtensions = this._getEnabledExtensions(); - -- if (initted) { -- extensionOrder.slice().reverse().forEach(uuid => { -- disableExtension(uuid); -+ let finder = new ExtensionUtils.ExtensionFinder(); -+ finder.connect('extension-found', (finder, extension) => { -+ this.loadExtension(extension); - }); -+ finder.scanExtensions(); -+ } -+ -+ enableAllExtensions() { -+ if (this._enabled) -+ return; -+ -+ if (!this._initted) { -+ this._loadExtensions(); -+ this._initted = true; -+ } else { -+ this._enabledExtensions.forEach(uuid => { -+ this.enableExtension(uuid); -+ }); -+ } -+ this._enabled = true; - } - -- enabled = false; --} -- --function _sessionUpdated() { -- // For now sessionMode.allowExtensions controls extensions from both the -- // 'enabled-extensions' preference and the sessionMode.enabledExtensions -- // property; it might make sense to make enabledExtensions independent -- // from allowExtensions in the future -- if (Main.sessionMode.allowExtensions) { -- if (initted) -- enabledExtensions = getEnabledExtensions(); -- enableAllExtensions(); -- } else { -- disableAllExtensions(); -+ disableAllExtensions() { -+ if (!this._enabled) -+ return; -+ -+ if (this._initted) { -+ this._extensionOrder.slice().reverse().forEach(uuid => { -+ this.disableExtension(uuid); -+ }); -+ } -+ -+ this._enabled = false; - } --} - --function init() { -- Main.sessionMode.connect('updated', _sessionUpdated); -- _sessionUpdated(); --} -+ _sessionUpdated() { -+ // For now sessionMode.allowExtensions controls extensions from both the -+ // 'enabled-extensions' preference and the sessionMode.enabledExtensions -+ // property; it might make sense to make enabledExtensions independent -+ // from allowExtensions in the future -+ if (Main.sessionMode.allowExtensions) { -+ if (this._initted) -+ this._enabledExtensions = this._getEnabledExtensions(); -+ this.enableAllExtensions(); -+ } else { -+ this.disableAllExtensions(); -+ } -+ } -+}; -+Signals.addSignalMethods(ExtensionManager.prototype); -diff --git a/js/ui/lookingGlass.js b/js/ui/lookingGlass.js -index fefb3f731..e947574f2 100644 ---- a/js/ui/lookingGlass.js -+++ b/js/ui/lookingGlass.js -@@ -7,7 +7,6 @@ const Signals = imports.signals; - const System = imports.system; - - const History = imports.misc.history; --const ExtensionSystem = imports.ui.extensionSystem; - const ExtensionUtils = imports.misc.extensionUtils; - const ShellEntry = imports.ui.shellEntry; - const Tweener = imports.ui.tweener; -@@ -624,8 +623,8 @@ var Extensions = class Extensions { - for (let uuid in ExtensionUtils.extensions) - this._loadExtension(null, uuid); - -- ExtensionSystem.connect('extension-loaded', -- this._loadExtension.bind(this)); -+ Main.extensionManager.connect('extension-loaded', -+ this._loadExtension.bind(this)); - } - - _loadExtension(o, uuid) { -diff --git a/js/ui/main.js b/js/ui/main.js -index 8dde95bf9..7bfbce497 100644 ---- a/js/ui/main.js -+++ b/js/ui/main.js -@@ -43,6 +43,7 @@ const STICKY_KEYS_ENABLE = 'stickykeys-enable'; - const GNOMESHELL_STARTED_MESSAGE_ID = 'f3ea493c22934e26811cd62abe8e203a'; - - var componentManager = null; -+var extensionManager = null; - var panel = null; - var overview = null; - var runDialog = null; -@@ -218,7 +219,7 @@ function _initializeUI() { - _startDate = new Date(); - - ExtensionDownloader.init(); -- ExtensionSystem.init(); -+ extensionManager = new ExtensionSystem.ExtensionManager(); - - if (sessionMode.isGreeter && screenShield) { - layoutManager.connect('startup-prepared', () => { -diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js -index 112d60feb..4b04e68ac 100644 ---- a/js/ui/shellDBus.js -+++ b/js/ui/shellDBus.js -@@ -4,7 +4,6 @@ const { Gio, GLib, Meta, Shell } = imports.gi; - const Lang = imports.lang; - - const Config = imports.misc.config; --const ExtensionSystem = imports.ui.extensionSystem; - const ExtensionDownloader = imports.ui.extensionDownloader; - const ExtensionUtils = imports.misc.extensionUtils; - const Main = imports.ui.main; -@@ -250,8 +249,8 @@ var GnomeShellExtensions = class { - constructor() { - this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellExtensionsIface, this); - this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell'); -- ExtensionSystem.connect('extension-state-changed', -- this._extensionStateChanged.bind(this)); -+ Main.extensionManager.connect('extension-state-changed', -+ this._extensionStateChanged.bind(this)); - } - - ListExtensions() { -@@ -334,7 +333,7 @@ var GnomeShellExtensions = class { - if (!extension) - return; - -- ExtensionSystem.reloadExtension(extension); -+ Main.extensionManager.reloadExtension(extension); - } - - CheckForUpdates() { --- -2.29.2 - - -From 7419ee28b5b568dd4478db7f3c890ff01678637a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 8 Jul 2019 02:53:32 +0200 -Subject: [PATCH 03/26] extensionSystem: Make methods to call extension - functions private - -While public methods to enable/disable extensions make sense for an -extension manager, the existing ones are only used internally. Make -them private and rename them, so that we can re-use the current -names for more useful public methods. - -https://bugzilla.gnome.org/show_bug.cgi?id=789852 ---- - js/ui/extensionSystem.js | 32 ++++++++++++++++---------------- - 1 file changed, 16 insertions(+), 16 deletions(-) - -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index b7e908223..c5fb007ae 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -24,7 +24,7 @@ var ExtensionManager = class { - this._sessionUpdated(); - } - -- disableExtension(uuid) { -+ _callExtensionDisable(uuid) { - let extension = ExtensionUtils.extensions[uuid]; - if (!extension) - return; -@@ -82,13 +82,13 @@ var ExtensionManager = class { - } - } - -- enableExtension(uuid) { -+ _callExtensionEnable(uuid) { - let extension = ExtensionUtils.extensions[uuid]; - if (!extension) - return; - - if (extension.state == ExtensionState.INITIALIZED) -- this.initExtension(uuid); -+ this._callExtensionInit(uuid); - - if (extension.state != ExtensionState.DISABLED) - return; -@@ -155,10 +155,10 @@ var ExtensionManager = class { - } else { - let enabled = this._enabledExtensions.includes(extension.uuid); - if (enabled) { -- if (!this.initExtension(extension.uuid)) -+ if (!this._callExtensionInit(extension.uuid)) - return; - if (extension.state == ExtensionState.DISABLED) -- this.enableExtension(extension.uuid); -+ this._callExtensionEnable(extension.uuid); - } else { - extension.state = ExtensionState.INITIALIZED; - } -@@ -171,7 +171,7 @@ var ExtensionManager = class { - // Try to disable it -- if it's ERROR'd, we can't guarantee that, - // but it will be removed on next reboot, and hopefully nothing - // broke too much. -- this.disableExtension(extension.uuid); -+ this._callExtensionDisable(extension.uuid); - - extension.state = ExtensionState.UNINSTALLED; - this.emit('extension-state-changed', extension); -@@ -200,7 +200,7 @@ var ExtensionManager = class { - this.loadExtension(newExtension); - } - -- initExtension(uuid) { -+ _callExtensionInit(uuid) { - let extension = ExtensionUtils.extensions[uuid]; - let dir = extension.dir; - -@@ -266,7 +266,7 @@ var ExtensionManager = class { - newEnabledExtensions.filter( - uuid => !this._enabledExtensions.includes(uuid) - ).forEach(uuid => { -- this.enableExtension(uuid); -+ this._callExtensionEnable(uuid); - }); - - // Find and disable all the newly disabled extensions: UUIDs found in the -@@ -274,7 +274,7 @@ var ExtensionManager = class { - this._enabledExtensions.filter( - item => !newEnabledExtensions.includes(item) - ).forEach(uuid => { -- this.disableExtension(uuid); -+ this._callExtensionDisable(uuid); - }); - - this._enabledExtensions = newEnabledExtensions; -@@ -291,7 +291,7 @@ var ExtensionManager = class { - - if (Main.sessionMode.allowExtensions) { - this._enabledExtensions.forEach(uuid => { -- this.enableExtension(uuid); -+ this._callExtensionEnable(uuid); - }); - } - } -@@ -313,7 +313,7 @@ var ExtensionManager = class { - finder.scanExtensions(); - } - -- enableAllExtensions() { -+ _enableAllExtensions() { - if (this._enabled) - return; - -@@ -322,19 +322,19 @@ var ExtensionManager = class { - this._initted = true; - } else { - this._enabledExtensions.forEach(uuid => { -- this.enableExtension(uuid); -+ this._callExtensionEnable(uuid); - }); - } - this._enabled = true; - } - -- disableAllExtensions() { -+ _disableAllExtensions() { - if (!this._enabled) - return; - - if (this._initted) { - this._extensionOrder.slice().reverse().forEach(uuid => { -- this.disableExtension(uuid); -+ this._callExtensionDisable(uuid); - }); - } - -@@ -349,9 +349,9 @@ var ExtensionManager = class { - if (Main.sessionMode.allowExtensions) { - if (this._initted) - this._enabledExtensions = this._getEnabledExtensions(); -- this.enableAllExtensions(); -+ this._enableAllExtensions(); - } else { -- this.disableAllExtensions(); -+ this._disableAllExtensions(); - } - } - }; --- -2.29.2 - - -From e88419278531b136984f9f05a8c056145d03edba Mon Sep 17 00:00:00 2001 -From: Didier Roche -Date: Wed, 17 Jan 2018 13:43:11 +0100 -Subject: [PATCH 04/26] extensionSystem: Add methods to enable/disable - extensions - -Extensions are currently enabled or disabled by directly changing the -list in the 'enabled-extensions' GSettings key. As we will soon add -an overriding 'disabled-extensions' key as well, it makes sense to -offer explicit API for enabling/disabling to avoid duplicating the -logic. - -For the corresponding D-Bus API, the methods were even mentioned in -the GSettings schema, albeit unimplemented until now. - -https://bugzilla.gnome.org/show_bug.cgi?id=789852 ---- - .../org.gnome.Shell.Extensions.xml | 24 +++++++++++++++++ - js/ui/extensionDownloader.js | 12 ++------- - js/ui/extensionSystem.js | 26 +++++++++++++++++++ - js/ui/shellDBus.js | 8 ++++++ - 4 files changed, 60 insertions(+), 10 deletions(-) - -diff --git a/data/dbus-interfaces/org.gnome.Shell.Extensions.xml b/data/dbus-interfaces/org.gnome.Shell.Extensions.xml -index ce69439fc..22273f889 100644 ---- a/data/dbus-interfaces/org.gnome.Shell.Extensions.xml -+++ b/data/dbus-interfaces/org.gnome.Shell.Extensions.xml -@@ -173,6 +173,30 @@ - - - -+ -+ \ -+ \ -+ \ -+ \ -+ -+ -+ \ -+ \ -+ \ -+ \ -+ - - - - -diff --git a/js/extensionPrefs/main.js b/js/extensionPrefs/main.js -index 43efa95e9..2b4ce5753 100644 ---- a/js/extensionPrefs/main.js -+++ b/js/extensionPrefs/main.js -@@ -241,7 +241,7 @@ var Application = class { - this._mainStack.add_named(new EmptyPlaceholder(), 'placeholder'); - - this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell'); -- this._shellProxy.connectSignal('ExtensionStatusChanged', (proxy, senderName, [uuid, state, error]) => { -+ this._shellProxy.connectSignal('ExtensionStateChanged', (proxy, senderName, [uuid, state]) => { - if (ExtensionUtils.extensions[uuid] !== undefined) - this._scanExtensions(); - }); -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index 8ff0fa56f..98eaf5259 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -159,15 +159,14 @@ var ExtensionManager = class { - - let message = '' + error; - -+ extension.error = message; - extension.state = ExtensionState.ERROR; - if (!extension.errors) - extension.errors = []; - extension.errors.push(message); - - log('Extension "%s" had error: %s'.format(uuid, message)); -- this.emit('extension-state-changed', { uuid: uuid, -- error: message, -- state: extension.state }); -+ this.emit('extension-state-changed', extension); - } - - loadExtension(extension) { -diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js -index af5889789..23274c0a3 100644 ---- a/js/ui/shellDBus.js -+++ b/js/ui/shellDBus.js -@@ -335,6 +335,10 @@ var GnomeShellExtensions = class { - } - - _extensionStateChanged(_, newState) { -+ let state = ExtensionUtils.serializeExtension(newState); -+ this._dbusImpl.emit_signal('ExtensionStateChanged', -+ new GLib.Variant('(sa{sv})', [newState.uuid, state])); -+ - this._dbusImpl.emit_signal('ExtensionStatusChanged', - GLib.Variant.new('(sis)', [newState.uuid, newState.state, newState.error])); - } --- -2.29.2 - - -From 47d185f8964f9e04430f4ef97d6d712faaf32078 Mon Sep 17 00:00:00 2001 -From: Didier Roche -Date: Tue, 4 Dec 2018 09:31:27 +0100 -Subject: [PATCH 07/26] extensionSystem: Add canChange property to extensions - -Whether or not an extension can be enabled/disabled depends on various -factors: Whether the extension is in error state, whether user extensions -are disabled and whether the underlying GSettings keys are writable. - -This is complex enough to share the logic, so add it to the extension -properties that are exposed over D-Bus. - -https://bugzilla.gnome.org/show_bug.cgi?id=789852 ---- - js/misc/extensionUtils.js | 3 ++- - js/ui/extensionSystem.js | 44 +++++++++++++++++++++++++++++++++------ - 2 files changed, 40 insertions(+), 7 deletions(-) - -diff --git a/js/misc/extensionUtils.js b/js/misc/extensionUtils.js -index bc9c36f4e..025cd042e 100644 ---- a/js/misc/extensionUtils.js -+++ b/js/misc/extensionUtils.js -@@ -31,7 +31,7 @@ var ExtensionState = { - UNINSTALLED: 99 - }; - --const SERIALIZED_PROPERTIES = ['type', 'state', 'path', 'error', 'hasPrefs']; -+const SERIALIZED_PROPERTIES = ['type', 'state', 'path', 'error', 'hasPrefs', 'canChange']; - - // Maps uuid -> metadata object - var extensions = {}; -@@ -222,6 +222,7 @@ function createExtensionObject(uuid, dir, type) { - extension.path = dir.get_path(); - extension.error = ''; - extension.hasPrefs = dir.get_child('prefs.js').query_exists(null); -+ extension.canChange = false; - - extensions[uuid] = extension; - -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index 98eaf5259..a83e53c83 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -189,6 +189,7 @@ var ExtensionManager = class { - } - } - -+ this._updateCanChange(extension); - this.emit('extension-state-changed', extension); - } - -@@ -267,12 +268,28 @@ var ExtensionManager = class { - return true; - } - -- _getEnabledExtensions() { -- let extensions; -+ _getModeExtensions() { - if (Array.isArray(Main.sessionMode.enabledExtensions)) -- extensions = Main.sessionMode.enabledExtensions; -- else -- extensions = []; -+ return Main.sessionMode.enabledExtensions; -+ return []; -+ } -+ -+ _updateCanChange(extension) { -+ let hasError = -+ extension.state == ExtensionState.ERROR || -+ extension.state == ExtensionState.OUT_OF_DATE; -+ -+ let isMode = this._getModeExtensions().includes(extension.uuid); -+ let modeOnly = global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY); -+ -+ extension.canChange = -+ !hasError && -+ global.settings.is_writable(ENABLED_EXTENSIONS_KEY) && -+ (isMode || !modeOnly); -+ } -+ -+ _getEnabledExtensions() { -+ let extensions = this._getModeExtensions(); - - if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY)) - return extensions; -@@ -280,6 +297,11 @@ var ExtensionManager = class { - return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY)); - } - -+ _onUserExtensionsEnabledChanged() { -+ this._onEnabledExtensionsChanged(); -+ this._onSettingsWritableChanged(); -+ } -+ - _onEnabledExtensionsChanged() { - let newEnabledExtensions = this._getEnabledExtensions(); - -@@ -305,6 +327,14 @@ var ExtensionManager = class { - this._enabledExtensions = newEnabledExtensions; - } - -+ _onSettingsWritableChanged() { -+ for (let uuid in ExtensionUtils.extensions) { -+ let extension = ExtensionUtils.extensions[uuid]; -+ this._updateCanChange(extension); -+ this.emit('extension-state-changed', extension); -+ } -+ } -+ - _onVersionValidationChanged() { - // we want to reload all extensions, but only enable - // extensions when allowed by the sessionMode, so -@@ -325,9 +355,11 @@ var ExtensionManager = class { - global.settings.connect(`changed::${ENABLED_EXTENSIONS_KEY}`, - this._onEnabledExtensionsChanged.bind(this)); - global.settings.connect(`changed::${DISABLE_USER_EXTENSIONS_KEY}`, -- this._onEnabledExtensionsChanged.bind(this)); -+ this._onUserExtensionsEnabledChanged.bind(this)); - global.settings.connect(`changed::${EXTENSION_DISABLE_VERSION_CHECK_KEY}`, - this._onVersionValidationChanged.bind(this)); -+ global.settings.connect(`writable-changed::${ENABLED_EXTENSIONS_KEY}`, -+ this._onSettingsWritableChanged.bind(this)); - - this._enabledExtensions = this._getEnabledExtensions(); - --- -2.29.2 - - -From ce14c00ca0707c78dc920ede3a157b7c9d55fff5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= -Date: Tue, 28 May 2019 23:22:37 +0200 -Subject: [PATCH 08/26] extensionPrefs: Inherit from Gtk.Application - -Extension preferences Application class is just a container for a GtkApplication -so instead of using composition we can inherit from the base GObject class. - -Also replace signal connections with vfunc's. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/631 ---- - js/extensionPrefs/main.js | 35 +++++++++++++++++------------------ - 1 file changed, 17 insertions(+), 18 deletions(-) - -diff --git a/js/extensionPrefs/main.js b/js/extensionPrefs/main.js -index 2b4ce5753..94a5b12fe 100644 ---- a/js/extensionPrefs/main.js -+++ b/js/extensionPrefs/main.js -@@ -17,18 +17,16 @@ function stripPrefix(string, prefix) { - return string; - } - --var Application = class { -- constructor() { -+var Application = GObject.registerClass({ -+ GTypeName: 'ExtensionPrefs_Application' -+}, class Application extends Gtk.Application { -+ _init() { - GLib.set_prgname('gnome-shell-extension-prefs'); -- this.application = new Gtk.Application({ -+ super._init({ - application_id: 'org.gnome.shell.ExtensionPrefs', - flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE - }); - -- this.application.connect('activate', this._onActivate.bind(this)); -- this.application.connect('command-line', this._onCommandLine.bind(this)); -- this.application.connect('startup', this._onStartup.bind(this)); -- - this._extensionPrefsModules = {}; - - this._startupUuid = null; -@@ -84,7 +82,7 @@ var Application = class { - visible: true })); - - if (this._skipMainWindow) { -- this.application.add_window(dialog); -+ this.add_window(dialog); - if (this._window) - this._window.destroy(); - this._window = dialog; -@@ -206,8 +204,8 @@ var Application = class { - return scroll; - } - -- _buildUI(app) { -- this._window = new Gtk.ApplicationWindow({ application: app, -+ _buildUI() { -+ this._window = new Gtk.ApplicationWindow({ application: this, - window_position: Gtk.WindowPosition.CENTER }); - - this._window.set_default_size(800, 500); -@@ -295,17 +293,19 @@ var Application = class { - this._loaded = true; - } - -- _onActivate() { -+ vfunc_activate() { - this._window.present(); - } - -- _onStartup(app) { -- this._buildUI(app); -+ vfunc_startup() { -+ super.vfunc_startup(); -+ -+ this._buildUI(); - this._scanExtensions(); - } - -- _onCommandLine(app, commandLine) { -- app.activate(); -+ vfunc_command_line(commandLine) { -+ this.activate(); - let args = commandLine.get_arguments(); - - if (args.length) { -@@ -325,7 +325,7 @@ var Application = class { - } - return 0; - } --}; -+}); - - var Expander = GObject.registerClass({ - Properties: { -@@ -631,6 +631,5 @@ function main(argv) { - Gettext.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR); - Gettext.textdomain(Config.GETTEXT_PACKAGE); - -- let app = new Application(); -- app.application.run(argv); -+ new Application().run(argv); - } --- -2.29.2 - - -From ea202d21b65c027db03e773a51bd8fecf4a2fb0a Mon Sep 17 00:00:00 2001 -From: Didier Roche -Date: Thu, 1 Nov 2018 13:50:30 +0100 -Subject: [PATCH 09/26] extensionPrefs: Attach extension object to each row - -Each row represents an extension, so it makes sense to associate the -rows with the actual extensions instead of linking rows and extensions -by looking up the UUID in the external extensions map in ExtensionUtils. - -This will also make it much easier to stop using the shared extension -loading / map in favor of the extension D-Bus API. - -https://bugzilla.gnome.org/show_bug.cgi?id=789852 ---- - js/extensionPrefs/main.js | 120 +++++++++++++++++++------------------- - 1 file changed, 60 insertions(+), 60 deletions(-) - -diff --git a/js/extensionPrefs/main.js b/js/extensionPrefs/main.js -index 94a5b12fe..7e7b2dcc7 100644 ---- a/js/extensionPrefs/main.js -+++ b/js/extensionPrefs/main.js -@@ -34,52 +34,31 @@ var Application = GObject.registerClass({ - this._skipMainWindow = false; - } - -- _extensionAvailable(uuid) { -- let extension = ExtensionUtils.extensions[uuid]; -- -- if (!extension) -- return false; -+ _showPrefs(uuid) { -+ let row = this._extensionSelector.get_children().find(c => { -+ return c.uuid === uuid && c.hasPrefs; -+ }); - -- if (!extension.dir.get_child('prefs.js').query_exists(null)) -+ if (!row) - return false; - -- return true; -- } -- -- _getExtensionPrefsModule(extension) { -- let uuid = extension.metadata.uuid; -- -- if (this._extensionPrefsModules.hasOwnProperty(uuid)) -- return this._extensionPrefsModules[uuid]; -- -- ExtensionUtils.installImporter(extension); -- -- let prefsModule = extension.imports.prefs; -- prefsModule.init(extension.metadata); -- -- this._extensionPrefsModules[uuid] = prefsModule; -- return prefsModule; -- } -- -- _selectExtension(uuid) { -- if (!this._extensionAvailable(uuid)) -- return; -- -- let extension = ExtensionUtils.extensions[uuid]; - let widget; - - try { -- let prefsModule = this._getExtensionPrefsModule(extension); -- widget = prefsModule.buildPrefsWidget(); -+ widget = row.prefsModule.buildPrefsWidget(); - } catch (e) { -- widget = this._buildErrorUI(extension, e); -+ widget = this._buildErrorUI(row, e); - } - -- let dialog = new Gtk.Window({ modal: !this._skipMainWindow, -- type_hint: Gdk.WindowTypeHint.DIALOG }); -- dialog.set_titlebar(new Gtk.HeaderBar({ show_close_button: true, -- title: extension.metadata.name, -- visible: true })); -+ let dialog = new Gtk.Window({ -+ modal: !this._skipMainWindow, -+ type_hint: Gdk.WindowTypeHint.DIALOG -+ }); -+ dialog.set_titlebar(new Gtk.HeaderBar({ -+ show_close_button: true, -+ title: row.name, -+ visible: true -+ })); - - if (this._skipMainWindow) { - this.add_window(dialog); -@@ -96,7 +75,7 @@ var Application = GObject.registerClass({ - dialog.show(); - } - -- _buildErrorUI(extension, exc) { -+ _buildErrorUI(row, exc) { - let scroll = new Gtk.ScrolledWindow({ - hscrollbar_policy: Gtk.PolicyType.NEVER, - propagate_natural_height: true -@@ -183,13 +162,13 @@ var Application = GObject.registerClass({ - label: _("Homepage"), - tooltip_text: _("Visit extension homepage"), - no_show_all: true, -- visible: extension.metadata.url != null -+ visible: row.url != null - }); - toolbar.add(urlButton); - - urlButton.connect('clicked', w => { - let context = w.get_display().get_app_launch_context(); -- Gio.AppInfo.launch_default_for_uri(extension.metadata.url, context); -+ Gio.AppInfo.launch_default_for_uri(row.url, context); - }); - - let expandedBox = new Gtk.Box({ -@@ -248,9 +227,7 @@ var Application = GObject.registerClass({ - } - - _sortList(row1, row2) { -- let name1 = ExtensionUtils.extensions[row1.uuid].metadata.name; -- let name2 = ExtensionUtils.extensions[row2.uuid].metadata.name; -- return name1.localeCompare(name2); -+ return row1.name.localeCompare(row2.name); - } - - _updateHeader(row, before) { -@@ -269,11 +246,10 @@ var Application = GObject.registerClass({ - } - - _extensionFound(finder, extension) { -- let row = new ExtensionRow(extension.uuid); -+ let row = new ExtensionRow(extension); - -- row.prefsButton.visible = this._extensionAvailable(row.uuid); - row.prefsButton.connect('clicked', () => { -- this._selectExtension(row.uuid); -+ this._showPrefs(row.uuid); - }); - - row.show_all(); -@@ -286,8 +262,8 @@ var Application = GObject.registerClass({ - else - this._mainStack.visible_child_name = 'placeholder'; - -- if (this._startupUuid && this._extensionAvailable(this._startupUuid)) -- this._selectExtension(this._startupUuid); -+ if (this._startupUuid) -+ this._showPrefs(this._startupUuid); - this._startupUuid = null; - this._skipMainWindow = false; - this._loaded = true; -@@ -316,11 +292,9 @@ var Application = GObject.registerClass({ - // Strip off "extension:///" prefix which fakes a URI, if it exists - uuid = stripPrefix(uuid, "extension:///"); - -- if (this._extensionAvailable(uuid)) -- this._selectExtension(uuid); -- else if (!this._loaded) -+ if (!this._loaded) - this._startupUuid = uuid; -- else -+ else if (!this._showPrefs(uuid)) - this._skipMainWindow = false; - } - return 0; -@@ -504,10 +478,11 @@ class DescriptionLabel extends Gtk.Label { - - var ExtensionRow = GObject.registerClass( - class ExtensionRow extends Gtk.ListBoxRow { -- _init(uuid) { -+ _init(extension) { - super._init(); - -- this.uuid = uuid; -+ this._extension = extension; -+ this._prefsModule = null; - - this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' }); - this._settings.connect('changed::enabled-extensions', () => { -@@ -525,9 +500,23 @@ class ExtensionRow extends Gtk.ListBoxRow { - this._buildUI(); - } - -- _buildUI() { -- let extension = ExtensionUtils.extensions[this.uuid]; -+ get uuid() { -+ return this._extension.uuid; -+ } -+ -+ get name() { -+ return this._extension.metadata.name; -+ } -+ -+ get hasPrefs() { -+ return this._extension.hasPrefs; -+ } - -+ get url() { -+ return this._extension.metadata.url; -+ } -+ -+ _buildUI() { - let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, - hexpand: true, margin_end: 24, spacing: 24, - margin: 12 }); -@@ -537,19 +526,20 @@ class ExtensionRow extends Gtk.ListBoxRow { - spacing: 6, hexpand: true }); - hbox.add(vbox); - -- let name = GLib.markup_escape_text(extension.metadata.name, -1); -+ let name = GLib.markup_escape_text(this.name, -1); - let label = new Gtk.Label({ label: '' + name + '', - use_markup: true, - halign: Gtk.Align.START }); - vbox.add(label); - -- let desc = extension.metadata.description.split('\n')[0]; -+ let desc = this._extension.metadata.description.split('\n')[0]; - label = new DescriptionLabel({ label: desc, wrap: true, lines: 2, - ellipsize: Pango.EllipsizeMode.END, - xalign: 0, yalign: 0 }); - vbox.add(label); - - let button = new Gtk.Button({ valign: Gtk.Align.CENTER, -+ visible: this.hasPrefs, - no_show_all: true }); - button.set_image(new Gtk.Image({ icon_name: 'emblem-system-symbolic', - icon_size: Gtk.IconSize.BUTTON, -@@ -573,11 +563,10 @@ class ExtensionRow extends Gtk.ListBoxRow { - } - - _canEnable() { -- let extension = ExtensionUtils.extensions[this.uuid]; - let checkVersion = !this._settings.get_boolean('disable-extension-version-validation'); - - return !this._settings.get_boolean('disable-user-extensions') && -- !(checkVersion && ExtensionUtils.isOutOfDate(extension)); -+ !(checkVersion && ExtensionUtils.isOutOfDate(this._extension)); - } - - _isEnabled() { -@@ -605,6 +594,17 @@ class ExtensionRow extends Gtk.ListBoxRow { - } while (pos != -1); - this._settings.set_strv('enabled-extensions', extensions); - } -+ -+ get prefsModule() { -+ if (!this._prefsModule) { -+ ExtensionUtils.installImporter(this._extension); -+ -+ this._prefsModule = this._extension.imports.prefs; -+ this._prefsModule.init(this._extension.metadata); -+ } -+ -+ return this._prefsModule; -+ } - }); - - function initEnvironment() { --- -2.29.2 - - -From 8d80e6667ded38dac53fe245a10191b5d4a3150b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Sat, 6 Jul 2019 01:48:05 +0200 -Subject: [PATCH 10/26] extensionPrefs: Override getCurrentExtension() for - extensions - -Extensions are used to calling the getCurrentExtension() utility function, -both from the extension itself and from its preferences. For the latter, -that relies on the extensions map in ExtensionUtils being populated from -the separated extension-prefs process just like from gnome-shell. - -This won't be the case anymore when we switch to the extensions D-Bus API, -but as we know which extension we are showing the prefs dialog for, we -can patch in a simple replacement that gives extensions the expected API. - -https://bugzilla.gnome.org/show_bug.cgi?id=789852 ---- - js/extensionPrefs/main.js | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/js/extensionPrefs/main.js b/js/extensionPrefs/main.js -index 7e7b2dcc7..29de8202a 100644 ---- a/js/extensionPrefs/main.js -+++ b/js/extensionPrefs/main.js -@@ -599,6 +599,9 @@ class ExtensionRow extends Gtk.ListBoxRow { - if (!this._prefsModule) { - ExtensionUtils.installImporter(this._extension); - -+ // give extension prefs access to their own extension object -+ ExtensionUtils.getCurrentExtension = () => this._extension; -+ - this._prefsModule = this._extension.imports.prefs; - this._prefsModule.init(this._extension.metadata); - } --- -2.29.2 - - -From e03a21b1f768405050bbfda1eb2bbf2ffcf7b4ca Mon Sep 17 00:00:00 2001 -From: Didier Roche -Date: Thu, 1 Nov 2018 13:55:17 +0100 -Subject: [PATCH 11/26] extensionPrefs: Switch to D-Bus API to get extension - live state - -By direclty using the underlying GSetting, whether or not an extension -appears as enabled or disabled currently depends only on whether it is -included in the 'enabled-extensions' list or not. - -However this doesn't necessarily reflect the real extension state, as an -extension may be in error state, or enabled via the session mode. - -Switch to the extensions D-Bus API to ensure that the list of extensions -and each extension's state correctly reflects the state in gnome-shell. - -https://bugzilla.gnome.org/show_bug.cgi?id=789852 ---- - js/extensionPrefs/main.js | 166 +++++++++++++++++++++++++------------- - 1 file changed, 110 insertions(+), 56 deletions(-) - -diff --git a/js/extensionPrefs/main.js b/js/extensionPrefs/main.js -index 29de8202a..f1b732e85 100644 ---- a/js/extensionPrefs/main.js -+++ b/js/extensionPrefs/main.js -@@ -8,6 +8,8 @@ const Config = imports.misc.config; - const ExtensionUtils = imports.misc.extensionUtils; - const { loadInterfaceXML } = imports.misc.fileUtils; - -+const { ExtensionState } = ExtensionUtils; -+ - const GnomeShellIface = loadInterfaceXML('org.gnome.Shell.Extensions'); - const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface); - -@@ -32,6 +34,11 @@ var Application = GObject.registerClass({ - this._startupUuid = null; - this._loaded = false; - this._skipMainWindow = false; -+ this._shellProxy = null; -+ } -+ -+ get shellProxy() { -+ return this._shellProxy; - } - - _showPrefs(uuid) { -@@ -218,10 +225,8 @@ var Application = GObject.registerClass({ - this._mainStack.add_named(new EmptyPlaceholder(), 'placeholder'); - - this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell'); -- this._shellProxy.connectSignal('ExtensionStateChanged', (proxy, senderName, [uuid, state]) => { -- if (ExtensionUtils.extensions[uuid] !== undefined) -- this._scanExtensions(); -- }); -+ this._shellProxy.connectSignal('ExtensionStateChanged', -+ this._onExtensionStateChanged.bind(this)); - - this._window.show_all(); - } -@@ -238,14 +243,51 @@ var Application = GObject.registerClass({ - row.set_header(sep); - } - -+ _findExtensionRow(uuid) { -+ return this._extensionSelector.get_children().find(c => c.uuid === uuid); -+ } -+ -+ _onExtensionStateChanged(proxy, senderName, [uuid, newState]) { -+ let row = this._findExtensionRow(uuid); -+ if (row) { -+ let { state } = ExtensionUtils.deserializeExtension(newState); -+ if (state == ExtensionState.UNINSTALLED) -+ row.destroy(); -+ return; // we only deal with new and deleted extensions here -+ } -+ -+ this._shellProxy.GetExtensionInfoRemote(uuid, ([serialized]) => { -+ let extension = ExtensionUtils.deserializeExtension(serialized); -+ if (!extension) -+ return; -+ // check the extension wasn't added in between -+ if (this._findExtensionRow(uuid) != null) -+ return; -+ this._addExtensionRow(extension); -+ }); -+ } -+ - _scanExtensions() { -- let finder = new ExtensionUtils.ExtensionFinder(); -- finder.connect('extension-found', this._extensionFound.bind(this)); -- finder.scanExtensions(); -- this._extensionsLoaded(); -+ this._shellProxy.ListExtensionsRemote(([extensionsMap], e) => { -+ if (e) { -+ if (e instanceof Gio.DBusError) { -+ log(`Failed to connect to shell proxy: ${e}`); -+ this._mainStack.add_named(new NoShellPlaceholder(), 'noshell'); -+ this._mainStack.visible_child_name = 'noshell'; -+ } else -+ throw e; -+ return; -+ } -+ -+ for (let uuid in extensionsMap) { -+ let extension = ExtensionUtils.deserializeExtension(extensionsMap[uuid]); -+ this._addExtensionRow(extension); -+ } -+ this._extensionsLoaded(); -+ }); - } - -- _extensionFound(finder, extension) { -+ _addExtensionRow(extension) { - let row = new ExtensionRow(extension); - - row.prefsButton.connect('clicked', () => { -@@ -466,6 +508,35 @@ class EmptyPlaceholder extends Gtk.Box { - } - }); - -+var NoShellPlaceholder = GObject.registerClass( -+class NoShellPlaceholder extends Gtk.Box { -+ _init() { -+ super._init({ -+ orientation: Gtk.Orientation.VERTICAL, -+ spacing: 12, -+ margin: 100, -+ margin_bottom: 60 -+ }); -+ -+ let label = new Gtk.Label({ -+ label: '%s'.format( -+ _("Something’s gone wrong")), -+ use_markup: true -+ }); -+ label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL); -+ this.add(label); -+ -+ label = new Gtk.Label({ -+ label: _("We’re very sorry, but it was not possible to get the list of installed extensions. Make sure you are logged into GNOME and try again."), -+ justify: Gtk.Justification.CENTER, -+ wrap: true -+ }); -+ this.add(label); -+ -+ this.show_all(); -+ } -+}); -+ - var DescriptionLabel = GObject.registerClass( - class DescriptionLabel extends Gtk.Label { - vfunc_get_preferred_height_for_width(width) { -@@ -481,22 +552,23 @@ class ExtensionRow extends Gtk.ListBoxRow { - _init(extension) { - super._init(); - -+ this._app = Gio.Application.get_default(); - this._extension = extension; - this._prefsModule = null; - -- this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' }); -- this._settings.connect('changed::enabled-extensions', () => { -- this._switch.state = this._isEnabled(); -- }); -- this._settings.connect('changed::disable-extension-version-validation', -- () => { -- this._switch.sensitive = this._canEnable(); -- }); -- this._settings.connect('changed::disable-user-extensions', -- () => { -- this._switch.sensitive = this._canEnable(); -+ this._extensionStateChangedId = this._app.shellProxy.connectSignal( -+ 'ExtensionStateChanged', (p, sender, [uuid, newState]) => { -+ if (this.uuid !== uuid) -+ return; -+ -+ this._extension = ExtensionUtils.deserializeExtension(newState); -+ let state = (this._extension.state == ExtensionState.ENABLED); -+ this._switch.state = state; -+ this._switch.sensitive = this._canToggle(); - }); - -+ this.connect('destroy', this._onDestroy.bind(this)); -+ - this._buildUI(); - } - -@@ -516,6 +588,15 @@ class ExtensionRow extends Gtk.ListBoxRow { - return this._extension.metadata.url; - } - -+ _onDestroy() { -+ if (!this._app.shellProxy) -+ return; -+ -+ if (this._extensionStateChangedId) -+ this._app.shellProxy.disconnectSignal(this._extensionStateChangedId); -+ this._extensionStateChangedId = 0; -+ } -+ - _buildUI() { - let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, - hexpand: true, margin_end: 24, spacing: 24, -@@ -549,50 +630,23 @@ class ExtensionRow extends Gtk.ListBoxRow { - - this.prefsButton = button; - -- this._switch = new Gtk.Switch({ valign: Gtk.Align.CENTER, -- sensitive: this._canEnable(), -- state: this._isEnabled() }); -+ this._switch = new Gtk.Switch({ -+ valign: Gtk.Align.CENTER, -+ sensitive: this._canToggle(), -+ state: this._extension.state === ExtensionState.ENABLED -+ }); - this._switch.connect('notify::active', () => { - if (this._switch.active) -- this._enable(); -+ this._app.shellProxy.EnableExtensionRemote(this.uuid); - else -- this._disable(); -+ this._app.shellProxy.DisableExtensionRemote(this.uuid); - }); - this._switch.connect('state-set', () => true); - hbox.add(this._switch); - } - -- _canEnable() { -- let checkVersion = !this._settings.get_boolean('disable-extension-version-validation'); -- -- return !this._settings.get_boolean('disable-user-extensions') && -- !(checkVersion && ExtensionUtils.isOutOfDate(this._extension)); -- } -- -- _isEnabled() { -- let extensions = this._settings.get_strv('enabled-extensions'); -- return extensions.indexOf(this.uuid) != -1; -- } -- -- _enable() { -- let extensions = this._settings.get_strv('enabled-extensions'); -- if (extensions.indexOf(this.uuid) != -1) -- return; -- -- extensions.push(this.uuid); -- this._settings.set_strv('enabled-extensions', extensions); -- } -- -- _disable() { -- let extensions = this._settings.get_strv('enabled-extensions'); -- let pos = extensions.indexOf(this.uuid); -- if (pos == -1) -- return; -- do { -- extensions.splice(pos, 1); -- pos = extensions.indexOf(this.uuid); -- } while (pos != -1); -- this._settings.set_strv('enabled-extensions', extensions); -+ _canToggle() { -+ return this._extension.canChange; - } - - get prefsModule() { --- -2.29.2 - - -From 9baf77dcae765618902d958549801276156f1255 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Sun, 7 Jul 2019 23:38:27 +0200 -Subject: [PATCH 12/26] extensionSystem: Move extension loading into - ExtensionManager - -Now that extension loading and the extensions map are no longer shared -between the gnome-shell and gnome-shell-extension-prefs processes, we -can move both into the ExtensionManager which makes much more sense -conceptually. - -https://bugzilla.gnome.org/show_bug.cgi?id=789852 ---- - js/misc/extensionUtils.js | 95 ++---------------------------- - js/ui/extensionDownloader.js | 12 ++-- - js/ui/extensionSystem.js | 110 +++++++++++++++++++++++++++++------ - js/ui/lookingGlass.js | 4 +- - js/ui/main.js | 1 + - js/ui/shellDBus.js | 8 +-- - 6 files changed, 111 insertions(+), 119 deletions(-) - -diff --git a/js/misc/extensionUtils.js b/js/misc/extensionUtils.js -index 025cd042e..c513ebc06 100644 ---- a/js/misc/extensionUtils.js -+++ b/js/misc/extensionUtils.js -@@ -7,10 +7,8 @@ const { Gio, GLib } = imports.gi; - - const Gettext = imports.gettext; - const Lang = imports.lang; --const Signals = imports.signals; - - const Config = imports.misc.config; --const FileUtils = imports.misc.fileUtils; - - var ExtensionType = { - SYSTEM: 1, -@@ -33,9 +31,6 @@ var ExtensionState = { - - const SERIALIZED_PROPERTIES = ['type', 'state', 'path', 'error', 'hasPrefs', 'canChange']; - --// Maps uuid -> metadata object --var extensions = {}; -- - /** - * getCurrentExtension: - * -@@ -66,13 +61,17 @@ function getCurrentExtension() { - if (!match) - return null; - -+ // local import, as the module is used from outside the gnome-shell process -+ // as well (not this function though) -+ let extensionManager = imports.ui.main.extensionManager; -+ - let path = match[1]; - let file = Gio.File.new_for_path(path); - - // Walk up the directory tree, looking for an extension with - // the same UUID as a directory name. - while (file != null) { -- let extension = extensions[file.get_basename()]; -+ let extension = extensionManager.extensions[file.get_basename()]; - if (extension !== undefined) - return extension; - file = file.get_parent(); -@@ -178,57 +177,6 @@ function isOutOfDate(extension) { - return false; - } - --function createExtensionObject(uuid, dir, type) { -- let info; -- -- let metadataFile = dir.get_child('metadata.json'); -- if (!metadataFile.query_exists(null)) { -- throw new Error('Missing metadata.json'); -- } -- -- let metadataContents, success, tag; -- try { -- [success, metadataContents, tag] = metadataFile.load_contents(null); -- if (metadataContents instanceof Uint8Array) -- metadataContents = imports.byteArray.toString(metadataContents); -- } catch (e) { -- throw new Error('Failed to load metadata.json: ' + e); -- } -- let meta; -- try { -- meta = JSON.parse(metadataContents); -- } catch (e) { -- throw new Error('Failed to parse metadata.json: ' + e); -- } -- -- let requiredProperties = ['uuid', 'name', 'description', 'shell-version']; -- for (let i = 0; i < requiredProperties.length; i++) { -- let prop = requiredProperties[i]; -- if (!meta[prop]) { -- throw new Error('missing "' + prop + '" property in metadata.json'); -- } -- } -- -- if (uuid != meta.uuid) { -- throw new Error('uuid "' + meta.uuid + '" from metadata.json does not match directory name "' + uuid + '"'); -- } -- -- let extension = {}; -- -- extension.metadata = meta; -- extension.uuid = meta.uuid; -- extension.type = type; -- extension.dir = dir; -- extension.path = dir.get_path(); -- extension.error = ''; -- extension.hasPrefs = dir.get_child('prefs.js').query_exists(null); -- extension.canChange = false; -- -- extensions[uuid] = extension; -- -- return extension; --} -- - function serializeExtension(extension) { - let obj = {}; - Lang.copyProperties(extension.metadata, obj); -@@ -283,36 +231,3 @@ function installImporter(extension) { - extension.imports = imports[extension.uuid]; - imports.searchPath = oldSearchPath; - } -- --var ExtensionFinder = class { -- _loadExtension(extensionDir, info, perUserDir) { -- let fileType = info.get_file_type(); -- if (fileType != Gio.FileType.DIRECTORY) -- return; -- let uuid = info.get_name(); -- let existing = extensions[uuid]; -- if (existing) { -- log('Extension %s already installed in %s. %s will not be loaded'.format(uuid, existing.path, extensionDir.get_path())); -- return; -- } -- -- let extension; -- let type = extensionDir.has_prefix(perUserDir) ? ExtensionType.PER_USER -- : ExtensionType.SYSTEM; -- try { -- extension = createExtensionObject(uuid, extensionDir, type); -- } catch(e) { -- logError(e, 'Could not load extension %s'.format(uuid)); -- return; -- } -- this.emit('extension-found', extension); -- } -- -- scanExtensions() { -- let perUserDir = Gio.File.new_for_path(global.userdatadir); -- FileUtils.collectFromDatadirs('extensions', true, (dir, info) => { -- this._loadExtension(dir, info, perUserDir); -- }); -- } --}; --Signals.addSignalMethods(ExtensionFinder.prototype); -diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js -index de52edfa6..1d92a5740 100644 ---- a/js/ui/extensionDownloader.js -+++ b/js/ui/extensionDownloader.js -@@ -43,7 +43,7 @@ function installExtension(uuid, invocation) { - } - - function uninstallExtension(uuid) { -- let extension = ExtensionUtils.extensions[uuid]; -+ let extension = Main.extensionManager.extensions[uuid]; - if (!extension) - return false; - -@@ -112,7 +112,7 @@ function updateExtension(uuid) { - - _httpSession.queue_message(message, (session, message) => { - gotExtensionZipFile(session, message, uuid, newExtensionTmpDir, () => { -- let oldExtension = ExtensionUtils.extensions[uuid]; -+ let oldExtension = Main.extensionManager.extensions[uuid]; - let extensionDir = oldExtension.dir; - - if (!Main.extensionManager.unloadExtension(oldExtension)) -@@ -124,7 +124,7 @@ function updateExtension(uuid) { - let extension = null; - - try { -- extension = ExtensionUtils.createExtensionObject(uuid, extensionDir, ExtensionUtils.ExtensionType.PER_USER); -+ extension = Main.extensionManager.createExtensionObject(uuid, extensionDir, ExtensionUtils.ExtensionType.PER_USER); - Main.extensionManager.loadExtension(extension); - } catch(e) { - if (extension) -@@ -150,8 +150,8 @@ function updateExtension(uuid) { - - function checkForUpdates() { - let metadatas = {}; -- for (let uuid in ExtensionUtils.extensions) { -- metadatas[uuid] = ExtensionUtils.extensions[uuid].metadata; -+ for (let uuid in Main.extensionManager.extensions) { -+ metadatas[uuid] = Main.extensionManager.extensions[uuid].metadata; - } - - let params = { shell_version: Config.PACKAGE_VERSION, -@@ -229,7 +229,7 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog { - - function callback() { - try { -- let extension = ExtensionUtils.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER); -+ let extension = Main.extensionManager.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER); - Main.extensionManager.loadExtension(extension); - if (!Main.extensionManager.enableExtension(uuid)) - throw new Error(`Cannot add ${uuid} to enabled extensions gsettings key`); -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index a83e53c83..0fd49c5ca 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -4,9 +4,10 @@ const { Gio, St } = imports.gi; - const Signals = imports.signals; - - const ExtensionUtils = imports.misc.extensionUtils; -+const FileUtils = imports.misc.fileUtils; - const Main = imports.ui.main; - --const { ExtensionState } = ExtensionUtils; -+const { ExtensionState, ExtensionType } = ExtensionUtils; - - const ENABLED_EXTENSIONS_KEY = 'enabled-extensions'; - const DISABLE_USER_EXTENSIONS_KEY = 'disable-user-extensions'; -@@ -17,15 +18,23 @@ var ExtensionManager = class { - this._initted = false; - this._enabled = false; - -+ this._extensions = {}; - this._enabledExtensions = []; - this._extensionOrder = []; - - Main.sessionMode.connect('updated', this._sessionUpdated.bind(this)); -+ } -+ -+ init() { - this._sessionUpdated(); - } - -+ get extensions() { -+ return this._extensions; -+ } -+ - _callExtensionDisable(uuid) { -- let extension = ExtensionUtils.extensions[uuid]; -+ let extension = this._extensions[uuid]; - if (!extension) - return; - -@@ -47,7 +56,7 @@ var ExtensionManager = class { - for (let i = 0; i < orderReversed.length; i++) { - let uuid = orderReversed[i]; - try { -- ExtensionUtils.extensions[uuid].stateObj.disable(); -+ this._extensions[uuid].stateObj.disable(); - } catch (e) { - this.logExtensionError(uuid, e); - } -@@ -68,7 +77,7 @@ var ExtensionManager = class { - for (let i = 0; i < order.length; i++) { - let uuid = order[i]; - try { -- ExtensionUtils.extensions[uuid].stateObj.enable(); -+ this._extensions[uuid].stateObj.enable(); - } catch (e) { - this.logExtensionError(uuid, e); - } -@@ -83,7 +92,7 @@ var ExtensionManager = class { - } - - _callExtensionEnable(uuid) { -- let extension = ExtensionUtils.extensions[uuid]; -+ let extension = this._extensions[uuid]; - if (!extension) - return; - -@@ -127,7 +136,7 @@ var ExtensionManager = class { - } - - enableExtension(uuid) { -- if (!ExtensionUtils.extensions[uuid]) -+ if (!this._extensions[uuid]) - return false; - - let enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY); -@@ -140,7 +149,7 @@ var ExtensionManager = class { - } - - disableExtension(uuid) { -- if (!ExtensionUtils.extensions[uuid]) -+ if (!this._extensions[uuid]) - return false; - - let enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY); -@@ -153,7 +162,7 @@ var ExtensionManager = class { - } - - logExtensionError(uuid, error) { -- let extension = ExtensionUtils.extensions[uuid]; -+ let extension = this._extensions[uuid]; - if (!extension) - return; - -@@ -169,6 +178,54 @@ var ExtensionManager = class { - this.emit('extension-state-changed', extension); - } - -+ createExtensionObject(uuid, dir, type) { -+ let metadataFile = dir.get_child('metadata.json'); -+ if (!metadataFile.query_exists(null)) { -+ throw new Error('Missing metadata.json'); -+ } -+ -+ let metadataContents, success; -+ try { -+ [success, metadataContents] = metadataFile.load_contents(null); -+ if (metadataContents instanceof Uint8Array) -+ metadataContents = imports.byteArray.toString(metadataContents); -+ } catch (e) { -+ throw new Error(`Failed to load metadata.json: ${e}`); -+ } -+ let meta; -+ try { -+ meta = JSON.parse(metadataContents); -+ } catch (e) { -+ throw new Error(`Failed to parse metadata.json: ${e}`); -+ } -+ -+ let requiredProperties = ['uuid', 'name', 'description', 'shell-version']; -+ for (let i = 0; i < requiredProperties.length; i++) { -+ let prop = requiredProperties[i]; -+ if (!meta[prop]) { -+ throw new Error(`missing "${prop}" property in metadata.json`); -+ } -+ } -+ -+ if (uuid != meta.uuid) { -+ throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name "${uuid}"`); -+ } -+ -+ let extension = { -+ metadata: meta, -+ uuid: meta.uuid, -+ type, -+ dir, -+ path: dir.get_path(), -+ error: '', -+ hasPrefs: dir.get_child('prefs.js').query_exists(null), -+ canChange: false -+ }; -+ this._extensions[uuid] = extension; -+ -+ return extension; -+ } -+ - loadExtension(extension) { - // Default to error, we set success as the last step - extension.state = ExtensionState.ERROR; -@@ -202,7 +259,7 @@ var ExtensionManager = class { - extension.state = ExtensionState.UNINSTALLED; - this.emit('extension-state-changed', extension); - -- delete ExtensionUtils.extensions[extension.uuid]; -+ delete this._extensions[extension.uuid]; - return true; - } - -@@ -217,7 +274,7 @@ var ExtensionManager = class { - // Now, recreate the extension and load it. - let newExtension; - try { -- newExtension = ExtensionUtils.createExtensionObject(uuid, dir, type); -+ newExtension = this.createExtensionObject(uuid, dir, type); - } catch (e) { - this.logExtensionError(uuid, e); - return; -@@ -227,7 +284,7 @@ var ExtensionManager = class { - } - - _callExtensionInit(uuid) { -- let extension = ExtensionUtils.extensions[uuid]; -+ let extension = this._extensions[uuid]; - let dir = extension.dir; - - if (!extension) -@@ -328,7 +385,7 @@ var ExtensionManager = class { - } - - _onSettingsWritableChanged() { -- for (let uuid in ExtensionUtils.extensions) { -+ for (let uuid in this._extensions) { - let extension = ExtensionUtils.extensions[uuid]; - this._updateCanChange(extension); - this.emit('extension-state-changed', extension); -@@ -340,8 +397,8 @@ var ExtensionManager = class { - // extensions when allowed by the sessionMode, so - // temporarily disable them all - this._enabledExtensions = []; -- for (let uuid in ExtensionUtils.extensions) -- this.reloadExtension(ExtensionUtils.extensions[uuid]); -+ for (let uuid in this._extensions) -+ this.reloadExtension(this._extensions[uuid]); - this._enabledExtensions = this._getEnabledExtensions(); - - if (Main.sessionMode.allowExtensions) { -@@ -363,11 +420,30 @@ var ExtensionManager = class { - - this._enabledExtensions = this._getEnabledExtensions(); - -- let finder = new ExtensionUtils.ExtensionFinder(); -- finder.connect('extension-found', (finder, extension) => { -+ let perUserDir = Gio.File.new_for_path(global.userdatadir); -+ FileUtils.collectFromDatadirs('extensions', true, (dir, info) => { -+ let fileType = info.get_file_type(); -+ if (fileType != Gio.FileType.DIRECTORY) -+ return; -+ let uuid = info.get_name(); -+ let existing = this._extensions[uuid]; -+ if (existing) { -+ log(`Extension ${uuid} already installed in ${existing.path}. ${dir.get_path()} will not be loaded`); -+ return; -+ } -+ -+ let extension; -+ let type = dir.has_prefix(perUserDir) -+ ? ExtensionType.PER_USER -+ : ExtensionType.SYSTEM; -+ try { -+ extension = this.createExtensionObject(uuid, dir, type); -+ } catch (e) { -+ logError(e, `Could not load extension ${uuid}`); -+ return; -+ } - this.loadExtension(extension); - }); -- finder.scanExtensions(); - } - - _enableAllExtensions() { -diff --git a/js/ui/lookingGlass.js b/js/ui/lookingGlass.js -index e947574f2..b8f8b14c9 100644 ---- a/js/ui/lookingGlass.js -+++ b/js/ui/lookingGlass.js -@@ -620,7 +620,7 @@ var Extensions = class Extensions { - this._extensionsList.add(this._noExtensions); - this.actor.add(this._extensionsList); - -- for (let uuid in ExtensionUtils.extensions) -+ for (let uuid in Main.extensionManager.extensions) - this._loadExtension(null, uuid); - - Main.extensionManager.connect('extension-loaded', -@@ -628,7 +628,7 @@ var Extensions = class Extensions { - } - - _loadExtension(o, uuid) { -- let extension = ExtensionUtils.extensions[uuid]; -+ let extension = Main.extensionManager.extensions[uuid]; - // There can be cases where we create dummy extension metadata - // that's not really a proper extension. Don't bother with these. - if (!extension.metadata.name) -diff --git a/js/ui/main.js b/js/ui/main.js -index 7bfbce497..5fa5a8077 100644 ---- a/js/ui/main.js -+++ b/js/ui/main.js -@@ -220,6 +220,7 @@ function _initializeUI() { - - ExtensionDownloader.init(); - extensionManager = new ExtensionSystem.ExtensionManager(); -+ extensionManager.init(); - - if (sessionMode.isGreeter && screenShield) { - layoutManager.connect('startup-prepared', () => { -diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js -index 23274c0a3..dc3a61df6 100644 ---- a/js/ui/shellDBus.js -+++ b/js/ui/shellDBus.js -@@ -254,7 +254,7 @@ var GnomeShellExtensions = class { - - ListExtensions() { - let out = {}; -- for (let uuid in ExtensionUtils.extensions) { -+ for (let uuid in Main.extensionManager.extensions) { - let dbusObj = this.GetExtensionInfo(uuid); - out[uuid] = dbusObj; - } -@@ -262,12 +262,12 @@ var GnomeShellExtensions = class { - } - - GetExtensionInfo(uuid) { -- let extension = ExtensionUtils.extensions[uuid] || {}; -+ let extension = Main.extensionManager.extensions[uuid] || {}; - return ExtensionUtils.serializeExtension(extension); - } - - GetExtensionErrors(uuid) { -- let extension = ExtensionUtils.extensions[uuid]; -+ let extension = Main.extensionManager.extensions[uuid]; - if (!extension) - return []; - -@@ -303,7 +303,7 @@ var GnomeShellExtensions = class { - } - - ReloadExtension(uuid) { -- let extension = ExtensionUtils.extensions[uuid]; -+ let extension = Main.extensionManager.extensions[uuid]; - if (!extension) - return; - --- -2.29.2 - - -From 776b82542aa705ea527dfbdd1a6d3fb1588092e2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 8 Jul 2019 00:01:11 +0200 -Subject: [PATCH 13/26] extensionSystem: Store extensions in a Map - -After making the extensions map private to the ExtensionManager, we can -switch it to a proper hash table which is more appropriate. - -https://bugzilla.gnome.org/show_bug.cgi?id=789852 ---- - js/misc/extensionUtils.js | 2 +- - js/ui/extensionDownloader.js | 8 +++---- - js/ui/extensionSystem.js | 42 ++++++++++++++++++++---------------- - js/ui/lookingGlass.js | 5 +++-- - js/ui/shellDBus.js | 10 ++++----- - 5 files changed, 37 insertions(+), 30 deletions(-) - -diff --git a/js/misc/extensionUtils.js b/js/misc/extensionUtils.js -index c513ebc06..62b25d46c 100644 ---- a/js/misc/extensionUtils.js -+++ b/js/misc/extensionUtils.js -@@ -71,7 +71,7 @@ function getCurrentExtension() { - // Walk up the directory tree, looking for an extension with - // the same UUID as a directory name. - while (file != null) { -- let extension = extensionManager.extensions[file.get_basename()]; -+ let extension = extensionManager.lookup(file.get_basename()); - if (extension !== undefined) - return extension; - file = file.get_parent(); -diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js -index 1d92a5740..77d013ffb 100644 ---- a/js/ui/extensionDownloader.js -+++ b/js/ui/extensionDownloader.js -@@ -43,7 +43,7 @@ function installExtension(uuid, invocation) { - } - - function uninstallExtension(uuid) { -- let extension = Main.extensionManager.extensions[uuid]; -+ let extension = Main.extensionManager.lookup(uuid); - if (!extension) - return false; - -@@ -112,7 +112,7 @@ function updateExtension(uuid) { - - _httpSession.queue_message(message, (session, message) => { - gotExtensionZipFile(session, message, uuid, newExtensionTmpDir, () => { -- let oldExtension = Main.extensionManager.extensions[uuid]; -+ let oldExtension = Main.extensionManager.lookup(uuid); - let extensionDir = oldExtension.dir; - - if (!Main.extensionManager.unloadExtension(oldExtension)) -@@ -150,9 +150,9 @@ function updateExtension(uuid) { - - function checkForUpdates() { - let metadatas = {}; -- for (let uuid in Main.extensionManager.extensions) { -+ Main.extensionManager.getUuids().forEach(uuid => { - metadatas[uuid] = Main.extensionManager.extensions[uuid].metadata; -- } -+ }); - - let params = { shell_version: Config.PACKAGE_VERSION, - installed: JSON.stringify(metadatas) }; -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index 0fd49c5ca..cd3e78301 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -18,7 +18,7 @@ var ExtensionManager = class { - this._initted = false; - this._enabled = false; - -- this._extensions = {}; -+ this._extensions = new Map(); - this._enabledExtensions = []; - this._extensionOrder = []; - -@@ -29,12 +29,16 @@ var ExtensionManager = class { - this._sessionUpdated(); - } - -- get extensions() { -- return this._extensions; -+ lookup(uuid) { -+ return this._extensions.get(uuid); -+ } -+ -+ getUuids() { -+ return [...this._extensions.keys()]; - } - - _callExtensionDisable(uuid) { -- let extension = this._extensions[uuid]; -+ let extension = this.lookup(uuid); - if (!extension) - return; - -@@ -56,7 +60,7 @@ var ExtensionManager = class { - for (let i = 0; i < orderReversed.length; i++) { - let uuid = orderReversed[i]; - try { -- this._extensions[uuid].stateObj.disable(); -+ this.lookup(uuid).stateObj.disable(); - } catch (e) { - this.logExtensionError(uuid, e); - } -@@ -77,7 +81,7 @@ var ExtensionManager = class { - for (let i = 0; i < order.length; i++) { - let uuid = order[i]; - try { -- this._extensions[uuid].stateObj.enable(); -+ this.lookup(uuid).stateObj.enable(); - } catch (e) { - this.logExtensionError(uuid, e); - } -@@ -92,7 +96,7 @@ var ExtensionManager = class { - } - - _callExtensionEnable(uuid) { -- let extension = this._extensions[uuid]; -+ let extension = this.lookup(uuid); - if (!extension) - return; - -@@ -136,7 +140,7 @@ var ExtensionManager = class { - } - - enableExtension(uuid) { -- if (!this._extensions[uuid]) -+ if (!this._extensions.has(uuid)) - return false; - - let enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY); -@@ -149,7 +153,7 @@ var ExtensionManager = class { - } - - disableExtension(uuid) { -- if (!this._extensions[uuid]) -+ if (!this._extensions.has(uuid)) - return false; - - let enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY); -@@ -162,7 +166,7 @@ var ExtensionManager = class { - } - - logExtensionError(uuid, error) { -- let extension = this._extensions[uuid]; -+ let extension = this.lookup(uuid); - if (!extension) - return; - -@@ -221,7 +225,7 @@ var ExtensionManager = class { - hasPrefs: dir.get_child('prefs.js').query_exists(null), - canChange: false - }; -- this._extensions[uuid] = extension; -+ this._extensions.set(uuid, extension); - - return extension; - } -@@ -259,7 +263,7 @@ var ExtensionManager = class { - extension.state = ExtensionState.UNINSTALLED; - this.emit('extension-state-changed', extension); - -- delete this._extensions[extension.uuid]; -+ this._extensions.delete(extension.uuid); - return true; - } - -@@ -284,7 +288,7 @@ var ExtensionManager = class { - } - - _callExtensionInit(uuid) { -- let extension = this._extensions[uuid]; -+ let extension = this.lookup(uuid); - let dir = extension.dir; - - if (!extension) -@@ -385,8 +389,7 @@ var ExtensionManager = class { - } - - _onSettingsWritableChanged() { -- for (let uuid in this._extensions) { -- let extension = ExtensionUtils.extensions[uuid]; -+ for (let extension of this._extensions.values()) { - this._updateCanChange(extension); - this.emit('extension-state-changed', extension); - } -@@ -397,8 +400,11 @@ var ExtensionManager = class { - // extensions when allowed by the sessionMode, so - // temporarily disable them all - this._enabledExtensions = []; -- for (let uuid in this._extensions) -- this.reloadExtension(this._extensions[uuid]); -+ -+ // The loop modifies the extensions map, so iterate over a copy -+ let extensions = [...this._extensions.values()]; -+ for (let extension of extensions) -+ this.reloadExtension(extension); - this._enabledExtensions = this._getEnabledExtensions(); - - if (Main.sessionMode.allowExtensions) { -@@ -426,7 +432,7 @@ var ExtensionManager = class { - if (fileType != Gio.FileType.DIRECTORY) - return; - let uuid = info.get_name(); -- let existing = this._extensions[uuid]; -+ let existing = this.lookup(uuid); - if (existing) { - log(`Extension ${uuid} already installed in ${existing.path}. ${dir.get_path()} will not be loaded`); - return; -diff --git a/js/ui/lookingGlass.js b/js/ui/lookingGlass.js -index b8f8b14c9..9196959bd 100644 ---- a/js/ui/lookingGlass.js -+++ b/js/ui/lookingGlass.js -@@ -620,15 +620,16 @@ var Extensions = class Extensions { - this._extensionsList.add(this._noExtensions); - this.actor.add(this._extensionsList); - -- for (let uuid in Main.extensionManager.extensions) -+ Main.extensionManager.getUuids().forEach(uuid => { - this._loadExtension(null, uuid); -+ }); - - Main.extensionManager.connect('extension-loaded', - this._loadExtension.bind(this)); - } - - _loadExtension(o, uuid) { -- let extension = Main.extensionManager.extensions[uuid]; -+ let extension = Main.extensionManager.lookup(uuid); - // There can be cases where we create dummy extension metadata - // that's not really a proper extension. Don't bother with these. - if (!extension.metadata.name) -diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js -index dc3a61df6..be9b10491 100644 ---- a/js/ui/shellDBus.js -+++ b/js/ui/shellDBus.js -@@ -254,20 +254,20 @@ var GnomeShellExtensions = class { - - ListExtensions() { - let out = {}; -- for (let uuid in Main.extensionManager.extensions) { -+ Main.extensionManager.getUuids().forEach(uuid => { - let dbusObj = this.GetExtensionInfo(uuid); - out[uuid] = dbusObj; -- } -+ }); - return out; - } - - GetExtensionInfo(uuid) { -- let extension = Main.extensionManager.extensions[uuid] || {}; -+ let extension = Main.extensionManager.lookup(uuid) || {}; - return ExtensionUtils.serializeExtension(extension); - } - - GetExtensionErrors(uuid) { -- let extension = Main.extensionManager.extensions[uuid]; -+ let extension = Main.extensionManager.lookup(uuid); - if (!extension) - return []; - -@@ -303,7 +303,7 @@ var GnomeShellExtensions = class { - } - - ReloadExtension(uuid) { -- let extension = Main.extensionManager.extensions[uuid]; -+ let extension = Main.extensionManager.lookup(uuid); - if (!extension) - return; - --- -2.29.2 - - -From 2cc95ba7c93c04bae0006b7d018928600d9cbb13 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 22 Jan 2020 14:45:15 +0100 -Subject: [PATCH 14/26] extensionSystem: Add hasUpdate state - -The current support for extension updates is half-baked at best. -We are about to change that, and implement offline updates similar -to gnome-software. - -As a first step, add a hasUpdate property to the extension state -which will communicate available updates. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/945 ---- - js/misc/extensionUtils.js | 10 +++++++++- - js/ui/extensionSystem.js | 10 ++++++++++ - 2 files changed, 19 insertions(+), 1 deletion(-) - -diff --git a/js/misc/extensionUtils.js b/js/misc/extensionUtils.js -index 62b25d46c..a812acdb1 100644 ---- a/js/misc/extensionUtils.js -+++ b/js/misc/extensionUtils.js -@@ -29,7 +29,15 @@ var ExtensionState = { - UNINSTALLED: 99 - }; - --const SERIALIZED_PROPERTIES = ['type', 'state', 'path', 'error', 'hasPrefs', 'canChange']; -+const SERIALIZED_PROPERTIES = [ -+ 'type', -+ 'state', -+ 'path', -+ 'error', -+ 'hasPrefs', -+ 'hasUpdate', -+ 'canChange', -+]; - - /** - * getCurrentExtension: -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index cd3e78301..93faf48d4 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -165,6 +165,15 @@ var ExtensionManager = class { - return true; - } - -+ notifyExtensionUpdate(uuid) { -+ let extension = this.lookup(uuid); -+ if (!extension) -+ return; -+ -+ extension.hasUpdate = true; -+ this.emit('extension-state-changed', extension); -+ } -+ - logExtensionError(uuid, error) { - let extension = this.lookup(uuid); - if (!extension) -@@ -223,6 +232,7 @@ var ExtensionManager = class { - path: dir.get_path(), - error: '', - hasPrefs: dir.get_child('prefs.js').query_exists(null), -+ hasUpdate: false, - canChange: false - }; - this._extensions.set(uuid, extension); --- -2.29.2 - - -From 07330eaac64fc115851ec9d5a0969bd046599e12 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 22 Jan 2020 15:07:45 +0100 -Subject: [PATCH 15/26] extensionDownloader: Make checkForUpdates() check for - updates - -Currently the method installs updates instead of merely checking for -them (or it would do, if it actually worked). - -This is not just surprising considering the method name, the whole idea -of live updates is problematic and will not work properly more often -than not: - - imports are cached, so any local modules will stay at their - original version until a shell restart - - GTypes cannot be unregistered - -So change the method to only download available updates, and set the -extensions' hasUpdate state accordingly. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/945 ---- - js/ui/extensionDownloader.js | 51 +++++++----------------------------- - 1 file changed, 9 insertions(+), 42 deletions(-) - -diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js -index 77d013ffb..66cb13d56 100644 ---- a/js/ui/extensionDownloader.js -+++ b/js/ui/extensionDownloader.js -@@ -97,53 +97,20 @@ function gotExtensionZipFile(session, message, uuid, dir, callback, errback) { - }); - } - --function updateExtension(uuid) { -- // This gets a bit tricky. We want the update to be seamless - -- // if we have any error during downloading or extracting, we -- // want to not unload the current version. -- -- let oldExtensionTmpDir = GLib.Dir.make_tmp('XXXXXX-shell-extension'); -- let newExtensionTmpDir = GLib.Dir.make_tmp('XXXXXX-shell-extension'); -+function downloadExtensionUpdate(uuid) { -+ let dir = Gio.File.new_for_path( -+ GLib.build_filenamev([global.userdatadir, 'extension-updates', uuid])); - - let params = { shell_version: Config.PACKAGE_VERSION }; - - let url = REPOSITORY_URL_DOWNLOAD.format(uuid); - let message = Soup.form_request_new_from_hash('GET', url, params); - -- _httpSession.queue_message(message, (session, message) => { -- gotExtensionZipFile(session, message, uuid, newExtensionTmpDir, () => { -- let oldExtension = Main.extensionManager.lookup(uuid); -- let extensionDir = oldExtension.dir; -- -- if (!Main.extensionManager.unloadExtension(oldExtension)) -- return; -- -- FileUtils.recursivelyMoveDir(extensionDir, oldExtensionTmpDir); -- FileUtils.recursivelyMoveDir(newExtensionTmpDir, extensionDir); -- -- let extension = null; -- -- try { -- extension = Main.extensionManager.createExtensionObject(uuid, extensionDir, ExtensionUtils.ExtensionType.PER_USER); -- Main.extensionManager.loadExtension(extension); -- } catch(e) { -- if (extension) -- Main.extensionManager.unloadExtension(extension); -- -- logError(e, 'Error loading extension %s'.format(uuid)); -- -- FileUtils.recursivelyDeleteDir(extensionDir, false); -- FileUtils.recursivelyMoveDir(oldExtensionTmpDir, extensionDir); -- -- // Restore what was there before. We can't do much if we -- // fail here. -- Main.extensionManager.loadExtension(oldExtension); -- return; -- } -- -- FileUtils.recursivelyDeleteDir(oldExtensionTmpDir, true); -- }, (code, message) => { -- log('Error while updating extension %s: %s (%s)'.format(uuid, code, message ? message : '')); -+ _httpSession.queue_message(message, session => { -+ gotExtensionZipFile(session, message, uuid, dir, () => { -+ Main.extensionManager.notifyExtensionUpdate(uuid); -+ }, (code, msg) => { -+ log(`Error while downloading update for extension ${uuid}: ${code} (${msg})`); - }); - }); - } -@@ -169,7 +136,7 @@ function checkForUpdates() { - if (operation == 'blacklist') - uninstallExtension(uuid); - else if (operation == 'upgrade' || operation == 'downgrade') -- updateExtension(uuid); -+ downloadExtensionUpdate(uuid); - } - }); - } --- -2.29.2 - - -From 49eaf28202787f0802663aa609ee9f87eb548b03 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 22 Jan 2020 15:42:06 +0100 -Subject: [PATCH 16/26] extensionDownloader: Only check updates for user - extensions - -System extensions cannot be updated through the website, so don't -even try. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/945 ---- - js/ui/extensionDownloader.js | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js -index 66cb13d56..c8f6735c5 100644 ---- a/js/ui/extensionDownloader.js -+++ b/js/ui/extensionDownloader.js -@@ -118,7 +118,10 @@ function downloadExtensionUpdate(uuid) { - function checkForUpdates() { - let metadatas = {}; - Main.extensionManager.getUuids().forEach(uuid => { -- metadatas[uuid] = Main.extensionManager.extensions[uuid].metadata; -+ let extension = Main.extensionManager.lookup(uuid); -+ if (extension.type !== ExtensionUtils.ExtensionType.PER_USER) -+ return; -+ metadatas[uuid] = extension.metadata; - }); - - let params = { shell_version: Config.PACKAGE_VERSION, --- -2.29.2 - - -From 67d709de14b083a013b3b1160e5cc451cf96bfde Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 27 Jan 2020 01:13:49 +0100 -Subject: [PATCH 17/26] extensionDownloader: Exclude extensions with pending - updates from check - -While it is possible that an extension has a newer version available -than the previously downloaded update, it's more likely that we end up -downloading the same archive again. That would be a bit silly despite -the usually small size, so we can either use the metadata from the -update, or exclude the extension from the check. - -The latter is much easier, so let's go with that for now. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/945 ---- - js/ui/extensionDownloader.js | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js -index c8f6735c5..ede276c37 100644 ---- a/js/ui/extensionDownloader.js -+++ b/js/ui/extensionDownloader.js -@@ -121,6 +121,8 @@ function checkForUpdates() { - let extension = Main.extensionManager.lookup(uuid); - if (extension.type !== ExtensionUtils.ExtensionType.PER_USER) - return; -+ if (extension.hasUpdate) -+ return; - metadatas[uuid] = extension.metadata; - }); - --- -2.29.2 - - -From 2fa19162c71787fbb9aa9af1d35e0e9cab11c1d1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 22 Jan 2020 16:53:32 +0100 -Subject: [PATCH 18/26] extensionDownloader: Include version validation in - update check - -The extensions website will consider the setting to find the best suitable -extension version, so we should transmit the parameter for better results. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/945 ---- - js/ui/extensionDownloader.js | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js -index ede276c37..f957c6c62 100644 ---- a/js/ui/extensionDownloader.js -+++ b/js/ui/extensionDownloader.js -@@ -126,8 +126,13 @@ function checkForUpdates() { - metadatas[uuid] = extension.metadata; - }); - -- let params = { shell_version: Config.PACKAGE_VERSION, -- installed: JSON.stringify(metadatas) }; -+ let versionCheck = global.settings.get_boolean( -+ 'disable-extension-version-validation'); -+ let params = { -+ shell_version: Config.PACKAGE_VERSION, -+ installed: JSON.stringify(metadatas), -+ disable_version_validation: `${versionCheck}`, -+ }; - - let url = REPOSITORY_URL_UPDATE; - let message = Soup.form_request_new_from_hash('GET', url, params); --- -2.29.2 - - -From ccb0095b1981233ca980d44c260c0d36eef910bd Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 22 Jan 2020 15:09:05 +0100 -Subject: [PATCH 19/26] extensionSystem: Install pending updates on startup - -Now that we have a way to check for updates and download them, we -should actually apply them as well. Do this on startup before any -extensions are initialized, to make sure we don't run into any -conflicts with a previously loaded version. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/945 ---- - js/ui/extensionSystem.js | 18 +++++++++++++++++- - 1 file changed, 17 insertions(+), 1 deletion(-) - -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index 93faf48d4..36a248dc1 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -1,6 +1,6 @@ - // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - --const { Gio, St } = imports.gi; -+const { GLib, Gio, St } = imports.gi; - const Signals = imports.signals; - - const ExtensionUtils = imports.misc.extensionUtils; -@@ -26,6 +26,7 @@ var ExtensionManager = class { - } - - init() { -+ this._installExtensionUpdates(); - this._sessionUpdated(); - } - -@@ -424,6 +425,21 @@ var ExtensionManager = class { - } - } - -+ _installExtensionUpdates() { -+ FileUtils.collectFromDatadirs('extension-updates', true, (dir, info) => { -+ let fileType = info.get_file_type(); -+ if (fileType !== Gio.FileType.DIRECTORY) -+ return; -+ let uuid = info.get_name(); -+ let extensionDir = Gio.File.new_for_path( -+ GLib.build_filenamev([global.userdatadir, 'extensions', uuid])); -+ -+ FileUtils.recursivelyDeleteDir(extensionDir, false); -+ FileUtils.recursivelyMoveDir(dir, extensionDir); -+ FileUtils.recursivelyDeleteDir(dir, true); -+ }); -+ } -+ - _loadExtensions() { - global.settings.connect(`changed::${ENABLED_EXTENSIONS_KEY}`, - this._onEnabledExtensionsChanged.bind(this)); --- -2.29.2 - - -From e377b16ffb667be40a850ff03e092f2f9dfe8fe8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Fri, 24 Jan 2020 18:09:34 +0100 -Subject: [PATCH 20/26] extensionPrefs: Add application icon - -We are about to make the tool a user-visible application, so we -need an icon. Add one (plus its symbolic variant). - -https://gitlab.gnome.org/GNOME/gnome-shell/issues/1968 ---- - data/gnome-shell-extension-prefs.desktop.in.in | 1 + - data/icons/hicolor/scalable/apps/org.gnome.Extensions.svg | 7 +++++++ - .../symbolic/apps/org.gnome.Extensions-symbolic.svg | 1 + - data/icons/meson.build | 1 + - data/meson.build | 1 + - meson.build | 1 + - 6 files changed, 12 insertions(+) - create mode 100644 data/icons/hicolor/scalable/apps/org.gnome.Extensions.svg - create mode 100644 data/icons/hicolor/symbolic/apps/org.gnome.Extensions-symbolic.svg - create mode 100644 data/icons/meson.build - -diff --git a/data/gnome-shell-extension-prefs.desktop.in.in b/data/gnome-shell-extension-prefs.desktop.in.in -index 1b144c5bd..1b58c424e 100644 ---- a/data/gnome-shell-extension-prefs.desktop.in.in -+++ b/data/gnome-shell-extension-prefs.desktop.in.in -@@ -1,6 +1,7 @@ - [Desktop Entry] - Type=Application - Name=Shell Extensions -+Icon=org.gnome.Extensions - Comment=Configure GNOME Shell Extensions - Exec=@bindir@/gnome-shell-extension-prefs %u - X-GNOME-Bugzilla-Bugzilla=GNOME -diff --git a/data/icons/hicolor/scalable/apps/org.gnome.Extensions.svg b/data/icons/hicolor/scalable/apps/org.gnome.Extensions.svg -new file mode 100644 -index 000000000..49d63888b ---- /dev/null -+++ b/data/icons/hicolor/scalable/apps/org.gnome.Extensions.svg -@@ -0,0 +1,7 @@ -+ -+ -+ -+ -+ -+ -+ -diff --git a/data/icons/hicolor/symbolic/apps/org.gnome.Extensions-symbolic.svg b/data/icons/hicolor/symbolic/apps/org.gnome.Extensions-symbolic.svg -new file mode 100644 -index 000000000..43786ff4a ---- /dev/null -+++ b/data/icons/hicolor/symbolic/apps/org.gnome.Extensions-symbolic.svg -@@ -0,0 +1 @@ -+ -\ No newline at end of file -diff --git a/data/icons/meson.build b/data/icons/meson.build -new file mode 100644 -index 000000000..eff6e4b53 ---- /dev/null -+++ b/data/icons/meson.build -@@ -0,0 +1 @@ -+install_subdir('hicolor', install_dir: icondir) -diff --git a/data/meson.build b/data/meson.build -index 31ac4514e..33edb58c4 100644 ---- a/data/meson.build -+++ b/data/meson.build -@@ -42,6 +42,7 @@ endforeach - - - subdir('dbus-interfaces') -+subdir('icons') - subdir('theme') - - data_resources = [ -diff --git a/meson.build b/meson.build -index 0acaba705..2dd1bbc7a 100644 ---- a/meson.build -+++ b/meson.build -@@ -52,6 +52,7 @@ pkglibdir = join_paths(libdir, meson.project_name()) - autostartdir = join_paths(sysconfdir, 'xdg', 'autostart') - convertdir = join_paths(datadir, 'GConf', 'gsettings') - desktopdir = join_paths(datadir, 'applications') -+icondir = join_paths(datadir, 'icons') - ifacedir = join_paths(datadir, 'dbus-1', 'interfaces') - localedir = join_paths(datadir, 'locale') - portaldir = join_paths(datadir, 'xdg-desktop-portal', 'portals') --- -2.29.2 - - -From 6b3fa1549f9682f54f55cdd963a242cd279ff17c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Sun, 26 Jan 2020 23:47:24 +0100 -Subject: [PATCH 21/26] extensionSystem: Show notification when updates are - available - -Now that the extensions app has the ability to handle updates, we -can use it as source of updates notifications. - -https://gitlab.gnome.org/GNOME/gnome-shell/issues/1968 ---- - js/ui/extensionSystem.js | 39 ++++++++++++++++++++++++++++++++++++++- - 1 file changed, 38 insertions(+), 1 deletion(-) - -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index 36a248dc1..805e08cae 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -1,11 +1,12 @@ - // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - --const { GLib, Gio, St } = imports.gi; -+const { GLib, Gio, GObject, St } = imports.gi; - const Signals = imports.signals; - - const ExtensionUtils = imports.misc.extensionUtils; - const FileUtils = imports.misc.fileUtils; - const Main = imports.ui.main; -+const MessageTray = imports.ui.messageTray; - - const { ExtensionState, ExtensionType } = ExtensionUtils; - -@@ -17,6 +18,7 @@ var ExtensionManager = class { - constructor() { - this._initted = false; - this._enabled = false; -+ this._updateNotified = false; - - this._extensions = new Map(); - this._enabledExtensions = []; -@@ -173,6 +175,18 @@ var ExtensionManager = class { - - extension.hasUpdate = true; - this.emit('extension-state-changed', extension); -+ -+ if (!this._updateNotified) { -+ this._updateNotified = true; -+ -+ let source = new ExtensionUpdateSource(); -+ Main.messageTray.add(source); -+ -+ let notification = new MessageTray.Notification(source, -+ _('Extension Updates Available'), -+ _('Extension updates are ready to be installed.')); -+ source.notify(notification); -+ } - } - - logExtensionError(uuid, error) { -@@ -521,3 +535,26 @@ var ExtensionManager = class { - } - }; - Signals.addSignalMethods(ExtensionManager.prototype); -+ -+class ExtensionUpdateSource extends MessageTray.Source { -+ constructor() { -+ const appSys = Shell.AppSystem.get_default(); -+ this._app = appSys.lookup_app('gnome-shell-extension-prefs.desktop'); -+ -+ super(this._app.get_name()); -+ } -+ -+ getIcon() { -+ return this._app.app_info.get_icon(); -+ } -+ -+ _createPolicy() { -+ return new MessageTray.NotificationApplicationPolicy(this._app.id); -+ } -+ -+ open() { -+ this._app.activate(); -+ Main.overview.hide(); -+ Main.panel.closeCalendar(); -+ } -+} --- -2.29.2 - - -From f6a5e2731f487d7a0ac088aff53ca1e76006c118 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 27 Jan 2020 00:59:19 +0100 -Subject: [PATCH 22/26] extensionSystem: Periodically check for extension - updates - -Now that we can download, apply and display extension updates, it is time -to actually check for updates. Schedule an update check right on startup, -then every 24 hours. - -https://gitlab.gnome.org/GNOME/gnome-shell/issues/1968 ---- - js/ui/extensionSystem.js | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index 805e08cae..914abb309 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -3,6 +3,7 @@ - const { GLib, Gio, GObject, St } = imports.gi; - const Signals = imports.signals; - -+const ExtensionDownloader = imports.ui.extensionDownloader; - const ExtensionUtils = imports.misc.extensionUtils; - const FileUtils = imports.misc.fileUtils; - const Main = imports.ui.main; -@@ -14,6 +15,8 @@ const ENABLED_EXTENSIONS_KEY = 'enabled-extensions'; - const DISABLE_USER_EXTENSIONS_KEY = 'disable-user-extensions'; - const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validation'; - -+const UPDATE_CHECK_TIMEOUT = 24 * 60 * 60; // 1 day in seconds -+ - var ExtensionManager = class { - constructor() { - this._initted = false; -@@ -30,6 +33,12 @@ var ExtensionManager = class { - init() { - this._installExtensionUpdates(); - this._sessionUpdated(); -+ -+ GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, UPDATE_CHECK_TIMEOUT, () => { -+ ExtensionDownloader.checkForUpdates(); -+ return GLib.SOURCE_CONTINUE; -+ }); -+ ExtensionDownloader.checkForUpdates(); - } - - lookup(uuid) { --- -2.29.2 - - -From cb3ed33a72fea3ae6b8df031abca48b99dba75a5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 9 Mar 2020 16:49:34 +0100 -Subject: [PATCH 23/26] extensionDownloader: Remove pending updates with - extension - -When an extension is uninstalled, there is no point in keeping -a pending update: If the update didn't fail (which it currently -does), we would end up sneakily reinstalling the extension. - -https://gitlab.gnome.org/GNOME/gnome-shell/issues/2343 ---- - js/ui/extensionDownloader.js | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js -index f957c6c62..0bd77e125 100644 ---- a/js/ui/extensionDownloader.js -+++ b/js/ui/extensionDownloader.js -@@ -55,6 +55,15 @@ function uninstallExtension(uuid) { - return false; - - FileUtils.recursivelyDeleteDir(extension.dir, true); -+ -+ try { -+ const updatesDir = Gio.File.new_for_path(GLib.build_filenamev( -+ [global.userdatadir, 'extension-updates', extension.uuid])); -+ FileUtils.recursivelyDeleteDir(updatesDir, true); -+ } catch (e) { -+ // not an error -+ } -+ - return true; - } - --- -2.29.2 - - -From 6abb5a189a7c97de8c0ed28c40f34fb625363223 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 9 Mar 2020 16:45:22 +0100 -Subject: [PATCH 24/26] extensionSystem: Catch errors when updating extensions - -Extension updates are installed at startup, so any errors that bubble -up uncaught will prevent the startup to complete. - -While the most likely error reason was addressed in the previous commit -(pending update for a no-longer exitent extension), it makes sense to -catch any kind of corrupt updates to not interfere with shell startup. - -https://gitlab.gnome.org/GNOME/gnome-shell/issues/2343 ---- - js/ui/extensionSystem.js | 11 ++++++++--- - 1 file changed, 8 insertions(+), 3 deletions(-) - -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index 914abb309..320af54e4 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -457,9 +457,14 @@ var ExtensionManager = class { - let extensionDir = Gio.File.new_for_path( - GLib.build_filenamev([global.userdatadir, 'extensions', uuid])); - -- FileUtils.recursivelyDeleteDir(extensionDir, false); -- FileUtils.recursivelyMoveDir(dir, extensionDir); -- FileUtils.recursivelyDeleteDir(dir, true); -+ try { -+ FileUtils.recursivelyDeleteDir(extensionDir, false); -+ FileUtils.recursivelyMoveDir(dir, extensionDir); -+ } catch (e) { -+ log('Failed to install extension updates for %s'.format(uuid)); -+ } finally { -+ FileUtils.recursivelyDeleteDir(dir, true); -+ } - }); - } - --- -2.29.2 - - -From 405897a9930362dad590eb8bd425c130dc636083 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Tue, 26 Jan 2021 17:12:04 +0100 -Subject: [PATCH 25/26] extensionSystem: Fix opening Extensions app from - notification - -Launching the app is implemented by the source's open() method, but -only external notifications are hooked up to call into the source -when no default action was provided. ---- - js/ui/extensionSystem.js | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js -index 320af54e4..81804ea5e 100644 ---- a/js/ui/extensionSystem.js -+++ b/js/ui/extensionSystem.js -@@ -194,6 +194,8 @@ var ExtensionManager = class { - let notification = new MessageTray.Notification(source, - _('Extension Updates Available'), - _('Extension updates are ready to be installed.')); -+ notification.connect('activated', -+ () => source.open()); - source.notify(notification); - } - } --- -2.29.2 - - -From 8d50b96701eefa7f9bff4af8c855087eee35739a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 1 Feb 2021 18:26:00 +0100 -Subject: [PATCH 26/26] extensionDownloader: Refuse to override system - extensions - -The website allows to "update" system extensions by installing the -upstream version into the user's home directory. - -Prevent that by refusing to download and install extensions that are -already installed system-wide. ---- - js/ui/extensionDownloader.js | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js -index 0bd77e125..1e6f5340a 100644 ---- a/js/ui/extensionDownloader.js -+++ b/js/ui/extensionDownloader.js -@@ -16,6 +16,14 @@ var REPOSITORY_URL_UPDATE = REPOSITORY_URL_BASE + '/update-info/'; - let _httpSession; - - function installExtension(uuid, invocation) { -+ const oldExt = Main.extensionManager.lookup(uuid); -+ if (oldExt && oldExt.type === ExtensionUtils.ExtensionType.SYSTEM) { -+ log('extensionDownloader: Trying to replace system extension %s'.format(uuid)); -+ invocation.return_dbus_error('org.gnome.Shell.InstallError', -+ 'System extensions cannot be replaced'); -+ return; -+ } -+ - let params = { uuid: uuid, - shell_version: Config.PACKAGE_VERSION }; - --- -2.29.2 diff --git a/SOURCES/fix-app-view-leaks.patch b/SOURCES/fix-app-view-leaks.patch deleted file mode 100644 index b74b9b2..0000000 --- a/SOURCES/fix-app-view-leaks.patch +++ /dev/null @@ -1,421 +0,0 @@ -From a518c9f57e5fe9c6b5ece5c6cb0534a83f0b2f2d Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 15 Jul 2019 13:52:58 -0400 -Subject: [PATCH 1/8] appDisplay: Don't leak duplicate items in AppView - -If an icon already exists in an app view with the same id, the -duplicate is not added on a call to addItem. Unfortunately, -since it's not added, the icon actor gets orphaned and leaked. - -This commit address the problem by introducing a new hasItem -method and disallowing callers to call addItem with a duplicate -in the first place. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628 ---- - js/ui/appDisplay.js | 15 ++++++++++++--- - 1 file changed, 12 insertions(+), 3 deletions(-) - -diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js -index a07db6573..fa22f47e0 100644 ---- a/js/ui/appDisplay.js -+++ b/js/ui/appDisplay.js -@@ -143,10 +143,14 @@ class BaseAppView { - return this._allItems; - } - -+ hasItem(id) { -+ return this._items[id] !== undefined; -+ } -+ - addItem(icon) { - let id = icon.id; -- if (this._items[id] !== undefined) -- return; -+ if (this.hasItem(id)) -+ throw new Error(`icon with id ${id} already added to view`) - - this._allItems.push(icon); - this._items[id] = icon; -@@ -386,6 +390,8 @@ var AllView = class AllView extends BaseAppView { - - let folders = this._folderSettings.get_strv('folder-children'); - folders.forEach(id => { -+ if (this.hasItem(id)) -+ return; - let path = this._folderSettings.path + 'folders/' + id + '/'; - let icon = new FolderIcon(id, path, this); - icon.connect('name-changed', this._itemNameChanged.bind(this)); -@@ -1165,7 +1171,10 @@ var FolderIcon = class FolderIcon { - let excludedApps = this._folder.get_strv('excluded-apps'); - let appSys = Shell.AppSystem.get_default(); - let addAppId = appId => { -- if (excludedApps.indexOf(appId) >= 0) -+ if (this.view.hasItem(appId)) -+ return; -+ -+ if (excludedApps.includes(appId)) - return; - - let app = appSys.lookup_app(appId); --- -2.23.0 - - -From 2b6aa9aed98c4854c2ad015879ddcb8d2bf91e9e Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 22 Jul 2019 11:06:30 -0400 -Subject: [PATCH 2/8] iconGrid: Clear meta_later callback on destruction - -The IconGrid code sometimes sets up a callback to be invoked -later right before being destroyed. - -This commit adds a destroy handler to cancel the callback. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628 ---- - js/ui/iconGrid.js | 16 ++++++++++++++-- - 1 file changed, 14 insertions(+), 2 deletions(-) - -diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js -index d51a443e8..1f05e67f3 100644 ---- a/js/ui/iconGrid.js -+++ b/js/ui/iconGrid.js -@@ -210,6 +210,8 @@ var IconGrid = GObject.registerClass({ - this.rightPadding = 0; - this.leftPadding = 0; - -+ this._updateIconSizesLaterId = 0; -+ - this._items = []; - this._clonesAnimating = []; - // Pulled from CSS, but hardcode some defaults here -@@ -227,6 +229,14 @@ var IconGrid = GObject.registerClass({ - - this.connect('actor-added', this._childAdded.bind(this)); - this.connect('actor-removed', this._childRemoved.bind(this)); -+ this.connect('destroy', this._onDestroy.bind(this)); -+ } -+ -+ _onDestroy() { -+ if (this._updateIconSizesLaterId) { -+ Meta.later_remove (this._updateIconSizesLaterId); -+ this._updateIconSizesLaterId = 0; -+ } - } - - _keyFocusIn(actor) { -@@ -757,12 +767,14 @@ var IconGrid = GObject.registerClass({ - - this._updateSpacingForSize(availWidth, availHeight); - } -- Meta.later_add(Meta.LaterType.BEFORE_REDRAW, -- this._updateIconSizes.bind(this)); -+ if (!this._updateIconSizesLaterId) -+ this._updateIconSizesLaterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, -+ this._updateIconSizes.bind(this)); - } - - // Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up - _updateIconSizes() { -+ this._updateIconSizesLaterId = 0; - let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize); - let newIconSize = Math.floor(ICON_SIZE * scale); - for (let i in this._items) { --- -2.23.0 - - -From 14a2650548a5104d6a3ec7a1174a23264d79030a Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 22 Jul 2019 11:02:10 -0400 -Subject: [PATCH 3/8] appDisplay: Add AppFolderPopup destroy handler - -At the moment AppFolderPopup calls popdown on destruction, -which leads to open-state-changed getting emitted after -the actor associated with the popup is destroyed. - -This commit handles ungrabbing and closing from an -actor destroy handler to side-step the open-state-changed -signal. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628 ---- - js/ui/appDisplay.js | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js -index fa22f47e0..b75d095d5 100644 ---- a/js/ui/appDisplay.js -+++ b/js/ui/appDisplay.js -@@ -1329,6 +1329,15 @@ var AppFolderPopup = class AppFolderPopup { - }); - this._grabHelper.addActor(Main.layoutManager.overviewGroup); - this.actor.connect('key-press-event', this._onKeyPress.bind(this)); -+ this.actor.connect('destroy', this._onDestroy.bind(this)); -+ } -+ -+ _onDestroy() { -+ if (this._isOpen) { -+ this._isOpen = false; -+ this._grabHelper.ungrab({ actor: this.actor }); -+ this._grabHelper = null; -+ } - } - - _onKeyPress(actor, event) { --- -2.23.0 - - -From c9fcb2d23141694ffa2182df20ba75687b01dacc Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 18 Jul 2019 10:06:38 -0400 -Subject: [PATCH 4/8] appDisplay: Clear AllView reference to current popup when - destroyed - -AllView contains a reference to the current popup that lingers after -the popup is destroyed. - -This commit fixes that, by explicitly nullifying when appropriate. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628 ---- - js/ui/appDisplay.js | 18 +++++++++++++++++- - 1 file changed, 17 insertions(+), 1 deletion(-) - -diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js -index b75d095d5..dabf63bfd 100644 ---- a/js/ui/appDisplay.js -+++ b/js/ui/appDisplay.js -@@ -300,6 +300,7 @@ var AllView = class AllView extends BaseAppView { - this._eventBlocker.add_action(this._clickAction); - - this._displayingPopup = false; -+ this._currentPopupDestroyId = 0; - - this._availWidth = 0; - this._availHeight = 0; -@@ -589,7 +590,22 @@ var AllView = class AllView extends BaseAppView { - this._stack.add_actor(popup.actor); - popup.connect('open-state-changed', (popup, isOpen) => { - this._eventBlocker.reactive = isOpen; -- this._currentPopup = isOpen ? popup : null; -+ -+ if (this._currentPopup) { -+ this._currentPopup.actor.disconnect(this._currentPopupDestroyId); -+ this._currentPopupDestroyId = 0; -+ } -+ -+ this._currentPopup = null; -+ -+ if (isOpen) { -+ this._currentPopup = popup; -+ this._currentPopupDestroyId = popup.actor.connect('destroy', () => { -+ this._currentPopup = null; -+ this._currentPopupDestroyId = 0; -+ this._eventBlocker.reactive = false; -+ }); -+ } - this._updateIconOpacities(isOpen); - if(!isOpen) - this._closeSpaceForPopup(); --- -2.23.0 - - -From b7a3fd7fa4527ba9411dcd18debe6ccf88c34dc0 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 22 Jul 2019 10:57:57 -0400 -Subject: [PATCH 5/8] appDisplay: Add destroy handler for FolderIcon - -It is important that the FolderView of a FolderIcon always -gets destroyed before the AppFolderPopup, since the view -may or may not be in the popup, and the view should -get cleaned up exactly once in either case. - -This commit adds a destroy handler on FolderIcon to ensure -things get taken down in the right order, and to make sure -the view isn't leaked if it's not yet part of the popup. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628 ---- - js/ui/appDisplay.js | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js -index dabf63bfd..5a8f4f1bf 100644 ---- a/js/ui/appDisplay.js -+++ b/js/ui/appDisplay.js -@@ -1156,6 +1156,7 @@ var FolderIcon = class FolderIcon { - this.view.actor.vscroll.adjustment.value = 0; - this._openSpaceForPopup(); - }); -+ this.actor.connect('destroy', this.onDestroy.bind(this)); - this.actor.connect('notify::mapped', () => { - if (!this.actor.mapped && this._popup) - this._popup.popdown(); -@@ -1165,6 +1166,13 @@ var FolderIcon = class FolderIcon { - this._redisplay(); - } - -+ onDestroy() { -+ this.view.actor.destroy(); -+ -+ if (this._popup) -+ this._popup.actor.destroy(); -+ } -+ - getAppIds() { - return this.view.getAllItems().map(item => item.id); - } --- -2.23.0 - - -From a90d7a97d21ffa596747cc8ecd0e3f500cb8a77c Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 18 Jul 2019 14:49:30 -0400 -Subject: [PATCH 6/8] appDisplay: Stop watching FolderIcon parent view when - destroyed - -When a FolderIcon is opened, it asks the parent view to allocate -space for it, which takes time. Eventually, the space-ready -signal is emitted on the view and the icon can make use of the new -space with its popup. If the icon gets destroyed in the -interim, though, space-ready signal handler still fires. - -This commit disconnects the signal handler so it doesn't get called -on a destroyed icon. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628 ---- - js/ui/appDisplay.js | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js -index 5a8f4f1bf..062ff222c 100644 ---- a/js/ui/appDisplay.js -+++ b/js/ui/appDisplay.js -@@ -1169,6 +1169,11 @@ var FolderIcon = class FolderIcon { - onDestroy() { - this.view.actor.destroy(); - -+ if (this._spaceReadySignalId) { -+ this._parentView.disconnect(this._spaceReadySignalId); -+ this._spaceReadySignalId = 0; -+ } -+ - if (this._popup) - this._popup.actor.destroy(); - } -@@ -1240,8 +1245,9 @@ var FolderIcon = class FolderIcon { - } - - _openSpaceForPopup() { -- let id = this._parentView.connect('space-ready', () => { -- this._parentView.disconnect(id); -+ this._spaceReadySignalId = this._parentView.connect('space-ready', () => { -+ this._parentView.disconnect(this._spaceReadySignalId); -+ this._spaceReadySignalId = 0; - this._popup.popup(); - this._updatePopupPosition(); - }); --- -2.23.0 - - -From b57ab33dadf0f31c5bf2c800806593e94784050c Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 18 Jul 2019 10:19:13 -0400 -Subject: [PATCH 7/8] appDisplay: Add open method to FolderIcon - -At the moment the only way to open a folder icon is to click on it; -there's no API to open the icon programmatically. - -This commits adds an open method and makes the click handler use -it. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628 ---- - js/ui/appDisplay.js | 12 +++++++----- - 1 file changed, 7 insertions(+), 5 deletions(-) - -diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js -index 062ff222c..c0c6e3663 100644 ---- a/js/ui/appDisplay.js -+++ b/js/ui/appDisplay.js -@@ -1151,11 +1151,7 @@ var FolderIcon = class FolderIcon { - - this.view = new FolderView(); - -- this.actor.connect('clicked', () => { -- this._ensurePopup(); -- this.view.actor.vscroll.adjustment.value = 0; -- this._openSpaceForPopup(); -- }); -+ this.actor.connect('clicked', this.open.bind(this)); - this.actor.connect('destroy', this.onDestroy.bind(this)); - this.actor.connect('notify::mapped', () => { - if (!this.actor.mapped && this._popup) -@@ -1178,6 +1174,12 @@ var FolderIcon = class FolderIcon { - this._popup.actor.destroy(); - } - -+ open() { -+ this._ensurePopup(); -+ this.view.actor.vscroll.adjustment.value = 0; -+ this._openSpaceForPopup(); -+ } -+ - getAppIds() { - return this.view.getAllItems().map(item => item.id); - } --- -2.23.0 - - -From baacab7922a56957d041aa59944c419b82e7a7e1 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 18 Jul 2019 11:13:27 -0400 -Subject: [PATCH 8/8] appDisplay: Keep popup open on refresh - -If the list of applications is refreshed we currently close -the open app folder. - -This commit adds logic to reopen the app folder on reload. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628 ---- - js/ui/appDisplay.js | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - -diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js -index c0c6e3663..7fad02cd0 100644 ---- a/js/ui/appDisplay.js -+++ b/js/ui/appDisplay.js -@@ -345,6 +345,21 @@ var AllView = class AllView extends BaseAppView { - super.removeAll(); - } - -+ _redisplay() { -+ let openFolderId = null; -+ if (this._displayingPopup && this._currentPopup) -+ openFolderId = this._currentPopup._source.id; -+ -+ super._redisplay(); -+ -+ if (openFolderId) { -+ let [folderToReopen] = this.folderIcons.filter(folder => folder.id == openFolderId); -+ -+ if (folderToReopen) -+ folderToReopen.open(); -+ } -+ } -+ - _itemNameChanged(item) { - // If an item's name changed, we can pluck it out of where it's - // supposed to be and reinsert it where it's sorted. --- -2.23.0 - diff --git a/SOURCES/fix-double-disposed-backgrounds.patch b/SOURCES/fix-double-disposed-backgrounds.patch deleted file mode 100644 index 7eebf77..0000000 --- a/SOURCES/fix-double-disposed-backgrounds.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 49d066234f9f528122bb40c5144b40d8b19a0071 Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Mon, 22 Aug 2022 12:52:19 +0200 -Subject: [PATCH] Background: Avoid double dispose and actors recreations - -Subject: [PATCH 1/2] background: Use Garbage Collector to dispose background: - -The same Meta.Background could be used by multiple instances of background -actors, and so should not be disposed when the actor using it is destroyed. - -Instead of calling `run_dispose` directly on it, just nullify the reference -on destroy method, leaving the job of doing the proper disposition to the -gabage collector that keeps the proper reference count on the Meta.Background. - -Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/501 - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/558 - -Subject: [PATCH 2/2] background: Group 'changed' signal emission - -Background is monitoring the whole `org.gnome.desktop.background` gsettings keys -for changes connecting to the non-specialized 'changed' signal and re-emitting -this as-is. -This means that when the background is changed via control-center, we get -multiple 'changed' signal events from GSettings, and for each one of this we -recreate a Background and a BackgroundActor. - -Avoid this by using an idle to delay the emission of the 'changed' signal -grouping the events. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/558 ---- - js/ui/background.js | 26 +++++++++++++++++++++----- - 1 file changed, 21 insertions(+), 5 deletions(-) - -diff --git a/js/ui/background.js b/js/ui/background.js -index 06e0388..2a404ae 100644 ---- a/js/ui/background.js -+++ b/js/ui/background.js -@@ -257,14 +257,15 @@ var Background = class Background { - this._refreshAnimation(); - }); - -- this._settingsChangedSignalId = this._settings.connect('changed', () => { -- this.emit('changed'); -- }); -+ this._settingsChangedSignalId = -+ this._settings.connect('changed', this._emitChangedSignal.bind(this)); - - this._load(); - } - - destroy() { -+ this.background = null; -+ - this._cancellable.cancel(); - this._removeAnimationTimeout(); - -@@ -288,6 +289,22 @@ var Background = class Background { - if (this._settingsChangedSignalId != 0) - this._settings.disconnect(this._settingsChangedSignalId); - this._settingsChangedSignalId = 0; -+ -+ if (this._changedIdleId) { -+ GLib.source_remove(this._changedIdleId); -+ this._changedIdleId = 0; -+ } -+ } -+ -+ _emitChangedSignal() { -+ if (this._changedIdleId) -+ return; -+ -+ this._changedIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { -+ this._changedIdleId = 0; -+ this.emit('changed'); -+ return GLib.SOURCE_REMOVE; -+ }); - } - - updateResolution() { -@@ -343,7 +360,7 @@ var Background = class Background { - if (changedFile.equal(file)) { - let imageCache = Meta.BackgroundImageCache.get_default(); - imageCache.purge(changedFile); -- this.emit('changed'); -+ this._emitChangedSignal(); - } - }); - this._fileWatches[key] = signalId; -@@ -699,7 +716,6 @@ var BackgroundManager = class BackgroundManager { - time: FADE_ANIMATION_TIME, - transition: 'easeOutQuad', - onComplete() { -- oldBackgroundActor.background.run_dispose(); - oldBackgroundActor.destroy(); - } - }); --- -2.35.3 - diff --git a/SOURCES/fix-invalid-access-warnings.patch b/SOURCES/fix-invalid-access-warnings.patch deleted file mode 100644 index 8fbdb93..0000000 --- a/SOURCES/fix-invalid-access-warnings.patch +++ /dev/null @@ -1,224 +0,0 @@ -From 76eebb42ed4c76970a9debfc0cd41537923eccde Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= -Date: Tue, 5 Dec 2017 02:41:50 +0100 -Subject: [PATCH 1/2] tweener: Save handlers on target and remove them on - destroy - -Saving handlers we had using the wrapper as a property of the object and delete -them when resetting the object state. -Without doing this an handler could be called on a destroyed target when this -happens on the onComplete callback. - -https://bugzilla.gnome.org/show_bug.cgi?id=791233 ---- - js/ui/tweener.js | 63 ++++++++++++++++++++++++++++++++++++++---------- - 1 file changed, 50 insertions(+), 13 deletions(-) - -diff --git a/js/ui/tweener.js b/js/ui/tweener.js -index bb9ea557c..c04cede25 100644 ---- a/js/ui/tweener.js -+++ b/js/ui/tweener.js -@@ -63,30 +63,67 @@ function _getTweenState(target) { - return target.__ShellTweenerState; - } - -+function _ensureHandlers(target) { -+ if (!target.__ShellTweenerHandlers) -+ target.__ShellTweenerHandlers = {}; -+ return target.__ShellTweenerHandlers; -+} -+ - function _resetTweenState(target) { - let state = target.__ShellTweenerState; - - if (state) { -- if (state.destroyedId) -+ if (state.destroyedId) { - state.actor.disconnect(state.destroyedId); -+ delete state.destroyedId; -+ } - } - -+ _removeHandler(target, 'onComplete', _tweenCompleted); - target.__ShellTweenerState = {}; - } - - function _addHandler(target, params, name, handler) { -- if (params[name]) { -- let oldHandler = params[name]; -- let oldScope = params[name + 'Scope']; -- let oldParams = params[name + 'Params']; -- let eventScope = oldScope ? oldScope : target; -- -- params[name] = () => { -- oldHandler.apply(eventScope, oldParams); -- handler(target); -- }; -- } else -- params[name] = () => { handler(target); }; -+ let wrapperNeeded = false; -+ let tweenerHandlers = _ensureHandlers(target); -+ -+ if (!(name in tweenerHandlers)) { -+ tweenerHandlers[name] = []; -+ wrapperNeeded = true; -+ } -+ -+ let handlers = tweenerHandlers[name]; -+ handlers.push(handler); -+ -+ if (wrapperNeeded) { -+ if (params[name]) { -+ let oldHandler = params[name]; -+ let oldScope = params[name + 'Scope']; -+ let oldParams = params[name + 'Params']; -+ let eventScope = oldScope ? oldScope : target; -+ -+ params[name] = () => { -+ oldHandler.apply(eventScope, oldParams); -+ handlers.forEach((h) => h(target)); -+ }; -+ } else { -+ params[name] = () => { handlers.forEach((h) => h(target)); }; -+ } -+ } -+} -+ -+function _removeHandler(target, name, handler) { -+ let tweenerHandlers = _ensureHandlers(target); -+ -+ if (name in tweenerHandlers) { -+ let handlers = tweenerHandlers[name]; -+ let handlerIndex = handlers.indexOf(handler); -+ -+ while (handlerIndex > -1) { -+ handlers.splice(handlerIndex, 1); -+ handlerIndex = handlers.indexOf(handler); -+ } -+ } - } - - function _actorDestroyed(target) { --- -2.21.0 - - -From 730f6f7d708a0cbcfcc75e4a1fba8512ac7c4c82 Mon Sep 17 00:00:00 2001 -From: Cosimo Cecchi -Date: Sun, 26 May 2019 08:31:07 -0700 -Subject: [PATCH 2/2] windowAttentionHandler: disconnect signals before - destruction -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The 'destroy' signal is emitted at the end of the destroy() method. -However the implementation of destroy() can end up emitting one of the -signals we connect to on the window, causing us to re-enter destroy -from its callback. -That will in turn lead to some objects getting disposed twice, which -produces a stack trace like the following one. - -This commit fixes the issue by overriding the destroy() method instead -of connecting to the signal, which allows us to disconnect the signal -handlers from the window at an earlier time and avoid re-entrancy. - --- - -gnome-shell[1082]: Object Gio.Settings (0x7f0af8143f00), has been already deallocated — impossible to access it. This might be caused by the object having been destroyed from C code using something such as destroy(), dispose(), or remove() vfuncs. -org.gnome.Shell.desktop[1082]: == Stack trace for context 0x5627f7d1e220 == -org.gnome.Shell.desktop[1082]: #0 5627f9e801a8 i resource:///org/gnome/shell/ui/messageTray.js:238 (7f0aefa9eca0 @ 22) -org.gnome.Shell.desktop[1082]: #1 5627f9e80108 i resource:///org/gnome/shell/ui/messageTray.js:802 (7f0aefaa2ee0 @ 28) -org.gnome.Shell.desktop[1082]: #2 5627f9e80070 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:79 (7f0aef7b29d0 @ 62) -org.gnome.Shell.desktop[1082]: #3 7fffa69fbfc0 b self-hosted:979 (7f0aefa515e0 @ 440) -org.gnome.Shell.desktop[1082]: #4 5627f9e7ffe0 i resource:///org/gnome/shell/ui/messageTray.js:121 (7f0aefa9e1f0 @ 71) -org.gnome.Shell.desktop[1082]: #5 5627f9e7ff38 i resource:///org/gnome/shell/ui/messageTray.js:1408 (7f0aefaa58b0 @ 22) -org.gnome.Shell.desktop[1082]: #6 5627f9e7fe80 i resource:///org/gnome/shell/ui/messageTray.js:1237 (7f0aefaa51f0 @ 729) -org.gnome.Shell.desktop[1082]: #7 5627f9e7fde8 i resource:///org/gnome/shell/ui/messageTray.js:1055 (7f0aefaa3d30 @ 124) -org.gnome.Shell.desktop[1082]: #8 7fffa69ff8e0 b self-hosted:979 (7f0aefa515e0 @ 440) -org.gnome.Shell.desktop[1082]: #9 7fffa69ff9d0 b resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386) -org.gnome.Shell.desktop[1082]: #10 5627f9e7fd58 i resource:///org/gnome/shell/ui/messageTray.js:479 (7f0aefaa0940 @ 50) -org.gnome.Shell.desktop[1082]: #11 5627f9e7fcb8 i resource:///org/gnome/shell/ui/messageTray.js:808 (7f0aefaa2ee0 @ 99) -org.gnome.Shell.desktop[1082]: #12 5627f9e7fc28 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:69 (7f0aef7b28b0 @ 13) -org.gnome.Shell.desktop[1082]: #13 5627f9e7fb80 i resource:///org/gnome/shell/ui/main.js:566 (7f0aefcd8820 @ 216) -org.gnome.Shell.desktop[1082]: #14 5627f9e7fad0 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:103 (7f0aef7b2c10 @ 27) -org.gnome.Shell.desktop[1082]: #15 5627f9e7fa58 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:43 (7f0aef7b2700 @ 17) -org.gnome.Shell.desktop[1082]: #16 7fffa6a03350 b resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386) -org.gnome.Shell.desktop[1082]: #17 5627f9e7f9d0 i resource:///org/gnome/shell/ui/messageTray.js:471 (7f0aefaa08b0 @ 22) -org.gnome.Shell.desktop[1082]: #18 5627f9e7f950 i resource:///org/gnome/shell/ui/calendar.js:752 (7f0aefaabdc0 @ 22) -org.gnome.Shell.desktop[1082]: #19 7fffa6a048f0 b self-hosted:979 (7f0aefa515e0 @ 440) -org.gnome.Shell.desktop[1082]: == Stack trace for context 0x5627f7d1e220 == -org.gnome.Shell.desktop[1082]: #0 5627f9e801a8 i resource:///org/gnome/shell/ui/messageTray.js:239 (7f0aefa9eca0 @ 42) -org.gnome.Shell.desktop[1082]: #1 5627f9e80108 i resource:///org/gnome/shell/ui/messageTray.js:802 (7f0aefaa2ee0 @ 28) -org.gnome.Shell.desktop[1082]: #2 5627f9e80070 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:79 (7f0aef7b29d0 @ 62) -org.gnome.Shell.desktop[1082]: #3 7fffa69fbfc0 b self-hosted:979 (7f0aefa515e0 @ 440) -org.gnome.Shell.desktop[1082]: #4 5627f9e7ffe0 i resource:///org/gnome/shell/ui/messageTray.js:121 (7f0aefa9e1f0 @ 71) -org.gnome.Shell.desktop[1082]: #5 5627f9e7ff38 i resource:///org/gnome/shell/ui/messageTray.js:1408 (7f0aefaa58b0 @ 22) -org.gnome.Shell.desktop[1082]: #6 5627f9e7fe80 i resource:///org/gnome/shell/ui/messageTray.js:1237 (7f0aefaa51f0 @ 729) -org.gnome.Shell.desktop[1082]: #7 5627f9e7fde8 i resource:///org/gnome/shell/ui/messageTray.js:1055 (7f0aefaa3d30 @ 124) -org.gnome.Shell.desktop[1082]: #8 7fffa69ff8e0 b self-hosted:979 (7f0aefa515e0 @ 440) -org.gnome.Shell.desktop[1082]: #9 7fffa69ff9d0 b resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386) -org.gnome.Shell.desktop[1082]: #10 5627f9e7fd58 i resource:///org/gnome/shell/ui/messageTray.js:479 (7f0aefaa0940 @ 50) -org.gnome.Shell.desktop[1082]: #11 5627f9e7fcb8 i resource:///org/gnome/shell/ui/messageTray.js:808 (7f0aefaa2ee0 @ 99) -org.gnome.Shell.desktop[1082]: #12 5627f9e7fc28 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:69 (7f0aef7b28b0 @ 13) -org.gnome.Shell.desktop[1082]: #13 5627f9e7fb80 i resource:///org/gnome/shell/ui/main.js:566 (7f0aefcd8820 @ 216) -org.gnome.Shell.desktop[1082]: #14 5627f9e7fad0 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:103 (7f0aef7b2c10 @ 27) -org.gnome.Shell.desktop[1082]: #15 5627f9e7fa58 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:43 (7f0aef7b2700 @ 17) -org.gnome.Shell.desktop[1082]: #16 7fffa6a03350 b resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386) -org.gnome.Shell.desktop[1082]: #17 5627f9e7f9d0 i resource:///org/gnome/shell/ui/messageTray.js:471 (7f0aefaa08b0 @ 22) -org.gnome.Shell.desktop[1082]: #18 5627f9e7f950 i resource:///org/gnome/shell/ui/calendar.js:752 (7f0aefaabdc0 @ 22) -org.gnome.Shell.desktop[1082]: #19 7fffa6a048f0 b self-hosted:979 (7f0aefa515e0 @ 440) -gnome-shell[1082]: g_object_run_dispose: assertion 'G_IS_OBJECT (object)' failed -gnome-shell[1082]: Object Gio.Settings (0x7f0af8161750), has been already deallocated — impossible to access it. This might be caused by the object having been destroyed from C code using something such as destroy(), dispose(), or remove() vfuncs. -gnome-shell[1082]: g_object_run_dispose: assertion 'G_IS_OBJECT (object)' failed - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/555 ---- - js/ui/windowAttentionHandler.js | 17 ++++++++--------- - 1 file changed, 8 insertions(+), 9 deletions(-) - -diff --git a/js/ui/windowAttentionHandler.js b/js/ui/windowAttentionHandler.js -index abdb8a444..a9a7111ba 100644 ---- a/js/ui/windowAttentionHandler.js -+++ b/js/ui/windowAttentionHandler.js -@@ -69,8 +69,6 @@ var Source = class WindowAttentionSource extends MessageTray.Source { - () => { this.destroy(); })); - this.signalIDs.push(this._window.connect('unmanaged', - () => { this.destroy(); })); -- -- this.connect('destroy', this._onDestroy.bind(this)); - } - - _sync() { -@@ -79,13 +77,6 @@ var Source = class WindowAttentionSource extends MessageTray.Source { - this.destroy(); - } - -- _onDestroy() { -- for(let i = 0; i < this.signalIDs.length; i++) { -- this._window.disconnect(this.signalIDs[i]); -- } -- this.signalIDs = []; -- } -- - _createPolicy() { - if (this._app && this._app.get_app_info()) { - let id = this._app.get_id().replace(/\.desktop$/,''); -@@ -99,6 +90,14 @@ var Source = class WindowAttentionSource extends MessageTray.Source { - return this._app.create_icon_texture(size); - } - -+ destroy(params) { -+ for (let i = 0; i < this.signalIDs.length; i++) -+ this._window.disconnect(this.signalIDs[i]); -+ this.signalIDs = []; -+ -+ super.destroy(params); -+ } -+ - open() { - Main.activateWindow(this._window); - } --- -2.21.0 - diff --git a/SOURCES/fix-login-lock-screen.patch b/SOURCES/fix-login-lock-screen.patch deleted file mode 100644 index f714a38..0000000 --- a/SOURCES/fix-login-lock-screen.patch +++ /dev/null @@ -1,161 +0,0 @@ -From 214c4f390faa40199c03a80594313760ffe9c5a6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Fri, 20 Sep 2019 13:17:40 +0200 -Subject: [PATCH 1/2] unlockDialog: Use inheritance instead of composition - -The screen shield creates the unlock dialog based on the session mode. - -However since commit 0c0d76f7d6990 turned LoginDialog into an actor -subclass (while UnlockDialog kept using the delegate pattern), it is -no longer possible to handle both objects the same way without warnings. - -Allow this again by turning UnlockDialog into an actor subclass as well. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/736 ---- - js/ui/unlockDialog.js | 46 ++++++++++++++++++++++++------------------- - 1 file changed, 26 insertions(+), 20 deletions(-) - -diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js -index 4b0470f4b..55abb652d 100644 ---- a/js/ui/unlockDialog.js -+++ b/js/ui/unlockDialog.js -@@ -1,8 +1,7 @@ - // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - - const { AccountsService, Atk, Clutter, -- Gdm, Gio, GLib, Meta, Shell, St } = imports.gi; --const Signals = imports.signals; -+ Gdm, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; - - const Layout = imports.ui.layout; - const Main = imports.ui.main; -@@ -12,15 +11,19 @@ const AuthPrompt = imports.gdm.authPrompt; - // The timeout before going back automatically to the lock screen (in seconds) - const IDLE_TIMEOUT = 2 * 60; - --var UnlockDialog = class { -- constructor(parentActor) { -- this.actor = new St.Widget({ accessible_role: Atk.Role.WINDOW, -- style_class: 'login-dialog', -- layout_manager: new Clutter.BoxLayout(), -- visible: false }); -+var UnlockDialog = GObject.registerClass({ -+ Signals: { 'failed': {} }, -+}, class UnlockDialog extends St.Widget { -+ _init(parentActor) { -+ super._init({ -+ accessible_role: Atk.Role.WINDOW, -+ style_class: 'login-dialog', -+ layout_manager: new Clutter.BoxLayout(), -+ visible: false, -+ }); - -- this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true })); -- parentActor.add_child(this.actor); -+ this.add_constraint(new Layout.MonitorConstraint({ primary: true })); -+ parentActor.add_child(this); - - this._userManager = AccountsService.UserManager.get_default(); - this._userName = GLib.get_user_name(); -@@ -31,7 +34,7 @@ var UnlockDialog = class { - y_align: Clutter.ActorAlign.CENTER, - x_expand: true, - y_expand: true }); -- this.actor.add_child(this._promptBox); -+ this.add_child(this._promptBox); - - this._gdmClient = new Gdm.Client(); - -@@ -70,10 +73,12 @@ var UnlockDialog = class { - this._authPrompt.reset(); - this._updateSensitivity(true); - -- Main.ctrlAltTabManager.addGroup(this.actor, _("Unlock Window"), 'dialog-password-symbolic'); -+ Main.ctrlAltTabManager.addGroup(this, _("Unlock Window"), 'dialog-password-symbolic'); - - this._idleMonitor = Meta.IdleMonitor.get_core(); - this._idleWatchId = this._idleMonitor.add_idle_watch(IDLE_TIMEOUT * 1000, this._escape.bind(this)); -+ -+ this.connect('destroy', this._onDestroy.bind(this)); - } - - _updateSensitivity(sensitive) { -@@ -112,9 +117,8 @@ var UnlockDialog = class { - this._authPrompt.cancel(); - } - -- destroy() { -+ _onDestroy() { - this.popModal(); -- this.actor.destroy(); - - if (this._idleWatchId) { - this._idleMonitor.remove_watch(this._idleWatchId); -@@ -137,13 +141,16 @@ var UnlockDialog = class { - } - - open(timestamp) { -- this.actor.show(); -+ this.show(); - - if (this._isModal) - return true; - -- if (!Main.pushModal(this.actor, { timestamp: timestamp, -- actionMode: Shell.ActionMode.UNLOCK_SCREEN })) -+ let modalParams = { -+ timestamp, -+ actionMode: Shell.ActionMode.UNLOCK_SCREEN, -+ }; -+ if (!Main.pushModal(this, modalParams)) - return false; - - this._isModal = true; -@@ -153,9 +160,8 @@ var UnlockDialog = class { - - popModal(timestamp) { - if (this._isModal) { -- Main.popModal(this.actor, timestamp); -+ Main.popModal(this, timestamp); - this._isModal = false; - } - } --}; --Signals.addSignalMethods(UnlockDialog.prototype); -+}); --- -2.31.1 - - -From cddeb2f4e38928e0d5e0f3a852961f639536aff3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Fri, 20 Sep 2019 13:14:40 +0200 -Subject: [PATCH 2/2] screenShield: Stop using deprecated actor property - -Both LoginDialog and UnlockDialog are now actor subclasses, so stop -using the deprecated actor delegate that will trigger a warning. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/736 ---- - js/ui/screenShield.js | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js -index 2d0a429be..f97a9288a 100644 ---- a/js/ui/screenShield.js -+++ b/js/ui/screenShield.js -@@ -917,8 +917,8 @@ var ScreenShield = class { - this._lockScreenGroup.hide(); - - if (this._dialog) { -- this._dialog.actor.grab_key_focus(); -- this._dialog.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false); -+ this._dialog.grab_key_focus(); -+ this._dialog.navigate_focus(null, St.DirectionType.TAB_FORWARD, false); - } - } - --- -2.31.1 - diff --git a/SOURCES/fix-nm-device-settings.patch b/SOURCES/fix-nm-device-settings.patch deleted file mode 100644 index db9d80e..0000000 --- a/SOURCES/fix-nm-device-settings.patch +++ /dev/null @@ -1,131 +0,0 @@ -From e2a1b737156804e2647e5de938c3d170c11b6ba4 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Fri, 31 Jul 2020 20:40:36 +0200 -Subject: [PATCH 1/2] status/network: Use D-Bus to launch Settings panels - -For more obscure network configurations, we need to launch the -corresponding Settings panel with additional parameters, so we -cannot simply launch the .desktop file. - -However we can do better than spawning a command line: Control center -exposes an application action we can use instead, so the process is -launched with the appropriate activation environment and startup -notification support. - -https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1385 ---- - js/ui/status/network.js | 33 +++++++++++++++++++++++++++++---- - 1 file changed, 29 insertions(+), 4 deletions(-) - -diff --git a/js/ui/status/network.js b/js/ui/status/network.js -index f8991d02f..0e7e82ce0 100644 ---- a/js/ui/status/network.js -+++ b/js/ui/status/network.js -@@ -15,6 +15,8 @@ const Util = imports.misc.util; - - const { loadInterfaceXML } = imports.misc.fileUtils; - -+Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish'); -+ - const NMConnectionCategory = { - INVALID: 'invalid', - WIRED: 'wired', -@@ -75,6 +77,30 @@ function ensureActiveConnectionProps(active, client) { - } - } - -+function launchSettingsPanel(panel, ...args) { -+ const param = new GLib.Variant('(sav)', -+ [panel, args.map(s => new GLib.Variant('s', s))]); -+ const platformData = { -+ 'desktop-startup-id': new GLib.Variant('s', -+ '_TIME%s'.format(global.get_current_time())), -+ }; -+ try { -+ Gio.DBus.session.call( -+ 'org.gnome.ControlCenter', -+ '/org/gnome/ControlCenter', -+ 'org.freedesktop.Application', -+ 'ActivateAction', -+ new GLib.Variant('(sava{sv})', -+ ['launch-panel', [param], platformData]), -+ null, -+ Gio.DBusCallFlags.NONE, -+ -1, -+ null); -+ } catch (e) { -+ log('Failed to launch Settings panel: %s'.format(e.message)); -+ } -+} -+ - var NMConnectionItem = class { - constructor(section, connection) { - this._section = section; -@@ -534,8 +560,7 @@ var NMDeviceModem = class extends NMConnectionDevice { - } - - _autoConnect() { -- Util.spawn(['gnome-control-center', 'network', -- 'connect-3g', this._device.get_path()]); -+ launchSettingsPanel('network', 'connect-3g', this._device.get_path()); - } - - _sessionUpdated() { -@@ -920,8 +945,8 @@ var NMWirelessDialog = class extends ModalDialog.ModalDialog { - || (accessPoints[0]._secType == NMAccessPointSecurity.WPA_ENT)) { - // 802.1x-enabled APs require further configuration, so they're - // handled in gnome-control-center -- Util.spawn(['gnome-control-center', 'wifi', 'connect-8021x-wifi', -- this._device.get_path(), accessPoints[0].get_path()]); -+ launchSettingsPanel('wifi', 'connect-8021x-wifi', -+ this._device.get_path(), accessPoints[0].get_path()); - } else { - let connection = new NM.SimpleConnection(); - this._client.add_and_activate_connection_async(connection, this._device, accessPoints[0].get_path(), null, null) --- -2.38.1 - - -From 9ca1989fcc73157685742470c25f538d01d8df44 Mon Sep 17 00:00:00 2001 -From: Xiaoguang Wang -Date: Mon, 21 Feb 2022 09:11:23 +0800 -Subject: [PATCH 2/2] network: Get dbus path from NMDevice - -In the NetworkManager new version the NMDevice.get_path returns pci -path, we need to use NM prototype to get device dbus path. - -https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4565 - -Part-of: ---- - js/ui/status/network.js | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/js/ui/status/network.js b/js/ui/status/network.js -index 0e7e82ce0..9d6a83b73 100644 ---- a/js/ui/status/network.js -+++ b/js/ui/status/network.js -@@ -946,7 +946,7 @@ var NMWirelessDialog = class extends ModalDialog.ModalDialog { - // 802.1x-enabled APs require further configuration, so they're - // handled in gnome-control-center - launchSettingsPanel('wifi', 'connect-8021x-wifi', -- this._device.get_path(), accessPoints[0].get_path()); -+ this._getDeviceDBusPath(), accessPoints[0].get_path()); - } else { - let connection = new NM.SimpleConnection(); - this._client.add_and_activate_connection_async(connection, this._device, accessPoints[0].get_path(), null, null) -@@ -956,6 +956,11 @@ var NMWirelessDialog = class extends ModalDialog.ModalDialog { - this.close(); - } - -+ _getDeviceDBusPath() { -+ // nm_object_get_path() is shadowed by nm_device_get_path() -+ return NM.Object.prototype.get_path.call(this._device); -+ } -+ - _notifySsidCb(accessPoint) { - if (accessPoint.get_ssid() != null) { - accessPoint.disconnect(accessPoint._notifySsidId); --- -2.38.1 - diff --git a/SOURCES/fix-some-js-warnings.patch b/SOURCES/fix-some-js-warnings.patch deleted file mode 100644 index 3faa329..0000000 --- a/SOURCES/fix-some-js-warnings.patch +++ /dev/null @@ -1,223 +0,0 @@ -From 530964cc6e5db02633434853debd96069dc2b8d8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= -Date: Thu, 23 May 2019 06:12:56 +0200 -Subject: [PATCH 1/6] realmd: Set login format to null on start and update if - invalid - -We were checking an undefined property but that would lead to a a warning. -Instead we can consider the login format unset until is null, and in case -update it. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700 ---- - js/gdm/realmd.js | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/js/gdm/realmd.js b/js/gdm/realmd.js -index 50f3c5899..04cd99787 100644 ---- a/js/gdm/realmd.js -+++ b/js/gdm/realmd.js -@@ -21,6 +21,7 @@ var Manager = class { - '/org/freedesktop/realmd', - this._reloadRealms.bind(this)) - this._realms = {}; -+ this._loginFormat = null; - - this._signalId = this._aggregateProvider.connect('g-properties-changed', - (proxy, properties) => { -@@ -86,7 +87,7 @@ var Manager = class { - } - - get loginFormat() { -- if (this._loginFormat !== undefined) -+ if (this._loginFormat) - return this._loginFormat; - - this._updateLoginFormat(); --- -2.33.1 - - -From 988e4b58d64fbf87f0c497315ff2506b269ff7c9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Tue, 9 Jun 2020 19:42:21 +0200 -Subject: [PATCH 2/6] popupMenu: Guard against non-menu-item children - -This avoid a harmless but annoying warning. ---- - js/ui/popupMenu.js | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js -index 44818533a..b5115d7f7 100644 ---- a/js/ui/popupMenu.js -+++ b/js/ui/popupMenu.js -@@ -696,7 +696,8 @@ var PopupMenuBase = class { - } - - _getMenuItems() { -- return this.box.get_children().map(a => a._delegate).filter(item => { -+ const children = this.box.get_children().filter(a => a._delegate !== undefined); -+ return children.map(a => a._delegate).filter(item => { - return item instanceof PopupBaseMenuItem || item instanceof PopupMenuSection; - }); - } --- -2.33.1 - - -From 609a8e22e67b63da1e35167d8511400f22641368 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Tue, 9 Jun 2020 19:48:06 +0200 -Subject: [PATCH 3/6] st/shadow: Check pipeline when painting - -We shouldn't simply assume that st_shadow_helper_update() has been -called before paint() or that the pipeline was created successfully. ---- - src/st/st-shadow.c | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - -diff --git a/src/st/st-shadow.c b/src/st/st-shadow.c -index f3a22f034..7665de755 100644 ---- a/src/st/st-shadow.c -+++ b/src/st/st-shadow.c -@@ -289,9 +289,10 @@ st_shadow_helper_paint (StShadowHelper *helper, - ClutterActorBox *actor_box, - guint8 paint_opacity) - { -- _st_paint_shadow_with_opacity (helper->shadow, -- framebuffer, -- helper->pipeline, -- actor_box, -- paint_opacity); -+ if (helper->pipeline != NULL) -+ _st_paint_shadow_with_opacity (helper->shadow, -+ framebuffer, -+ helper->pipeline, -+ actor_box, -+ paint_opacity); - } --- -2.33.1 - - -From b57d6efccbeb139d6c7c1894f83caa7a26fd6bad Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Tue, 5 Jan 2021 21:42:24 +0100 -Subject: [PATCH 4/6] viewSelector: Don't set page parent during construction - -gjs now aggressively garbage-collects objects that fall out of scope, -sometimes too aggressively: - - - we pass a child as construct property to StBin - - as a result, the child's ::parent-set handler runs - - when calling clutter_actor_get_parent() from that - handler, the returned object is garbage-collected - *before* the constructor returns (and thus the - assignment that would keep it alive) - -This is a bug on the gjs side that should be fixed, but we can easily -work around the issue by setting the child after constructing the -parent. ---- - js/ui/viewSelector.js | 12 +++++++----- - 1 file changed, 7 insertions(+), 5 deletions(-) - -diff --git a/js/ui/viewSelector.js b/js/ui/viewSelector.js -index 77146552d..6529ac9a5 100644 ---- a/js/ui/viewSelector.js -+++ b/js/ui/viewSelector.js -@@ -301,11 +301,13 @@ var ViewSelector = class { - _addPage(actor, name, a11yIcon, params) { - params = Params.parse(params, { a11yFocus: null }); - -- let page = new St.Bin({ child: actor, -- x_align: St.Align.START, -- y_align: St.Align.START, -- x_fill: true, -- y_fill: true }); -+ let page = new St.Bin({ -+ x_align: St.Align.START, -+ y_align: St.Align.START, -+ x_fill: true, -+ y_fill: true, -+ }); -+ page.set_child(actor); - if (params.a11yFocus) - Main.ctrlAltTabManager.addGroup(params.a11yFocus, name, a11yIcon); - else --- -2.33.1 - - -From 0c76c91c3d16c8386a242daf367d66057364a5d1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Fri, 23 Oct 2020 23:44:48 +0200 -Subject: [PATCH 5/6] workspacesView: Don't set up MetaLater when unparented - -We already do the check in the later handler, but if we got -unparented because the actor is destroyed, then the call to -get_parent() itself will trigger a (harmless but annoying) -warning. ---- - js/ui/workspacesView.js | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js -index e302296a6..3270900b2 100644 ---- a/js/ui/workspacesView.js -+++ b/js/ui/workspacesView.js -@@ -715,6 +715,9 @@ var WorkspacesDisplay = class { - oldParent.disconnect(this._notifyOpacityId); - this._notifyOpacityId = 0; - -+ if (!this.actor.get_parent()) -+ return; -+ - Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { - let newParent = this.actor.get_parent(); - if (!newParent) --- -2.33.1 - - -From 4ba01f2fdada7e4b059a0f57a99dc3ff2ddfa8f8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Fri, 26 Nov 2021 17:28:54 +0100 -Subject: [PATCH 6/6] workspacesView: Remove later on destroy - -We are careful not to schedule the later when the actor is destroyed, -however it is possible that one is still pending at that point (namely -if the actor was never shown). ---- - js/ui/workspacesView.js | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js -index 3270900b2..9dc05fca7 100644 ---- a/js/ui/workspacesView.js -+++ b/js/ui/workspacesView.js -@@ -449,6 +449,11 @@ var WorkspacesDisplay = class { - this.actor._delegate = this; - this.actor.connect('notify::allocation', this._updateWorkspacesActualGeometry.bind(this)); - this.actor.connect('parent-set', this._parentSet.bind(this)); -+ this.actor.connect('destroy', () => { -+ if (this._laterId) -+ Meta.later_remove(this._laterId); -+ this._laterId = 0; -+ }); - - let clickAction = new Clutter.ClickAction(); - clickAction.connect('clicked', action => { -@@ -718,7 +723,7 @@ var WorkspacesDisplay = class { - if (!this.actor.get_parent()) - return; - -- Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { -+ this._laterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { - let newParent = this.actor.get_parent(); - if (!newParent) - return; --- -2.33.1 - diff --git a/SOURCES/gdm-networking.patch b/SOURCES/gdm-networking.patch deleted file mode 100644 index 4f5e2fc..0000000 --- a/SOURCES/gdm-networking.patch +++ /dev/null @@ -1,246 +0,0 @@ -From ed0699886f49e5dd8d6ca9ffb60ba17cd76a810f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 7 Jun 2021 17:49:57 +0200 -Subject: [PATCH 1/5] status/network: Disable modem connection when windows - aren't allowed - -The item launches the corresponding Settings panel when activated, which -doesn't work when windows are disabled by the session mode. Rather than -failing silently, turn the item insensitive. ---- - js/ui/status/network.js | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/js/ui/status/network.js b/js/ui/status/network.js -index b3bb7589c..3ad7b04dd 100644 ---- a/js/ui/status/network.js -+++ b/js/ui/status/network.js -@@ -514,6 +514,10 @@ var NMDeviceModem = class extends NMConnectionDevice { - this._iconChanged(); - }); - } -+ -+ this._sessionUpdatedId = -+ Main.sessionMode.connect('updated', this._sessionUpdated.bind(this)); -+ this._sessionUpdated(); - } - - get category() { -@@ -525,6 +529,10 @@ var NMDeviceModem = class extends NMConnectionDevice { - 'connect-3g', this._device.get_path()]); - } - -+ _sessionUpdated() { -+ this._autoConnectItem.sensitive = Main.sessionMode.hasWindows; -+ } -+ - destroy() { - if (this._operatorNameId) { - this._mobileDevice.disconnect(this._operatorNameId); -@@ -534,6 +542,10 @@ var NMDeviceModem = class extends NMConnectionDevice { - this._mobileDevice.disconnect(this._signalQualityId); - this._signalQualityId = 0; - } -+ if (this._sessionUpdatedId) { -+ Main.sessionMode.disconnect(this._sessionUpdatedId); -+ this._sessionUpdatedId = 0; -+ } - - super.destroy(); - } --- -2.31.1 - - -From 59d52e1591e1522fff22320c657496ca978a7926 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 7 Jun 2021 18:28:32 +0200 -Subject: [PATCH 2/5] status/network: Only list wifi networks that can be - activated - -Setting up a connection for an Enterprise WPA(2) encrypted wireless -network requires Settings. That's not available when windows are -disabled via the session mode, so filter out affected entries. ---- - js/ui/status/network.js | 29 ++++++++++++++++++++++++++++- - 1 file changed, 28 insertions(+), 1 deletion(-) - -diff --git a/js/ui/status/network.js b/js/ui/status/network.js -index 3ad7b04dd..c023022a7 100644 ---- a/js/ui/status/network.js -+++ b/js/ui/status/network.js -@@ -1,5 +1,5 @@ - // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- --const { Clutter, Gio, GLib, GObject, NM, St } = imports.gi; -+const { Clutter, Gio, GLib, GObject, Meta, NM, St } = imports.gi; - const Mainloop = imports.mainloop; - const Signals = imports.signals; - -@@ -751,6 +751,11 @@ var NMWirelessDialog = class extends ModalDialog.ModalDialog { - this._scanTimeoutId = 0; - } - -+ if (this._syncVisibilityId) { -+ Meta.later_remove(this._syncVisibilityId); -+ this._syncVisibilityId = 0; -+ } -+ - super.destroy(); - } - -@@ -1081,9 +1086,31 @@ var NMWirelessDialog = class extends ModalDialog.ModalDialog { - this._itemBox.insert_child_at_index(network.item.actor, newPos); - } - -+ this._queueSyncItemVisibility(); - this._syncView(); - } - -+ _queueSyncItemVisibility() { -+ if (this._syncVisibilityId) -+ return; -+ -+ this._syncVisibilityId = Meta.later_add( -+ Meta.LaterType.BEFORE_REDRAW, -+ () => { -+ const { hasWindows } = Main.sessionMode; -+ const { WPA2_ENT, WPA_ENT } = NMAccessPointSecurity; -+ -+ for (const network of this._networks) { -+ const [firstAp] = network.accessPoints; -+ network.item.visible = -+ hasWindows || -+ network.connections.length > 0 || -+ (firstAp._secType !== WPA2_ENT && firstAp._secType !== WPA_ENT); -+ } -+ return GLib.SOURCE_REMOVE; -+ }); -+ } -+ - _accessPointRemoved(device, accessPoint) { - let res = this._findExistingNetwork(accessPoint); - --- -2.31.1 - - -From 9d204cdb38bcfee214dbe0b0bf9c2073dc50fe93 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Tue, 8 Jun 2021 00:17:48 +0200 -Subject: [PATCH 3/5] status/network: Consider network-control action - -NetworkManager installs a `network-control` polkit action that can -be used to disallow network configuration, except that we happily -ignore it. Add it to the conditions that turn a network section -insensitive. ---- - js/ui/status/network.js | 20 +++++++++++++++++--- - 1 file changed, 17 insertions(+), 3 deletions(-) - -diff --git a/js/ui/status/network.js b/js/ui/status/network.js -index c023022a7..79729e01b 100644 ---- a/js/ui/status/network.js -+++ b/js/ui/status/network.js -@@ -1,5 +1,5 @@ - // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- --const { Clutter, Gio, GLib, GObject, Meta, NM, St } = imports.gi; -+const { Clutter, Gio, GLib, GObject, Meta, NM, Polkit, St } = imports.gi; - const Mainloop = imports.mainloop; - const Signals = imports.signals; - -@@ -1683,11 +1683,25 @@ var NMApplet = class extends PanelMenu.SystemIndicator { - this._client.connect('connection-removed', this._connectionRemoved.bind(this)); - - Main.sessionMode.connect('updated', this._sessionUpdated.bind(this)); -- this._sessionUpdated(); -+ -+ this._configPermission = null; -+ Polkit.Permission.new( -+ 'org.freedesktop.NetworkManager.network-control', null, null, -+ (o, res) => { -+ try { -+ this._configPermission = Polkit.Permission.new_finish(res); -+ } catch (e) { -+ log('No permission to control network connections: %s'.format(e.toString())); -+ } -+ this._sessionUpdated(); -+ }); - } - - _sessionUpdated() { -- let sensitive = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter; -+ const sensitive = -+ !Main.sessionMode.isLocked && -+ !Main.sessionMode.isGreeter && -+ this._configPermission && this._configPermission.allowed; - this.menu.setSensitive(sensitive); - } - --- -2.31.1 - - -From 7d2c8aabb86b9942c99ae9b7157dbffb875acde9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Thu, 10 Jun 2021 23:12:27 +0200 -Subject: [PATCH 4/5] sessionMode: Enable networkAgent on login screen - -We will soon enable the network sections in the status menu on the -login screen, so enable the network agent to handle authentication -requests (like wifi/VPN passwords). ---- - js/ui/sessionMode.js | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/js/ui/sessionMode.js b/js/ui/sessionMode.js -index 25aa75a3d..fa7f83416 100644 ---- a/js/ui/sessionMode.js -+++ b/js/ui/sessionMode.js -@@ -43,7 +43,9 @@ const _modes = { - isGreeter: true, - isPrimary: true, - unlockDialog: imports.gdm.loginDialog.LoginDialog, -- components: ['polkitAgent'], -+ components: Config.HAVE_NETWORKMANAGER -+ ? ['networkAgent', 'polkitAgent'] -+ : ['polkitAgent'], - panel: { - left: [], - center: ['dateMenu'], --- -2.31.1 - - -From 07ce899bcb9d30991262d6c484508e6c5fa14c85 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Tue, 8 Jun 2021 00:19:26 +0200 -Subject: [PATCH 5/5] status/network: Do not disable on login screen - -We currently disable all network items on both the lock- and login -screen. While it makes sense to be very restrictive on the lock screen, -there are some (fringe) use cases for being more permissive on the -login screen (like remote home directories only accessible via VPN). - -There's precedence with the power-off/restart actions to be less -restrictive on the login screen, and since we started respecting -the `network-control` polkit action, it's possible to restore the -old behavior if desired. ---- - js/ui/status/network.js | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/js/ui/status/network.js b/js/ui/status/network.js -index 79729e01b..914dbbd99 100644 ---- a/js/ui/status/network.js -+++ b/js/ui/status/network.js -@@ -1700,7 +1700,6 @@ var NMApplet = class extends PanelMenu.SystemIndicator { - _sessionUpdated() { - const sensitive = - !Main.sessionMode.isLocked && -- !Main.sessionMode.isGreeter && - this._configPermission && this._configPermission.allowed; - this.menu.setSensitive(sensitive); - } --- -2.31.1 - diff --git a/SOURCES/gnome-shell-favourite-apps-yelp.patch b/SOURCES/gnome-shell-favourite-apps-yelp.patch deleted file mode 100644 index d96597a..0000000 --- a/SOURCES/gnome-shell-favourite-apps-yelp.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 53eba56c29c2c3f25bdfc4b73d1b9ce74ce2504b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Thu, 9 Mar 2017 14:44:03 +0100 -Subject: [PATCH] Add 'yelp' to default favorites - -Help should be easily available, so add it to the default favorites. ---- - data/org.gnome.shell.gschema.xml.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in -index 2f50036d0..40526187e 100644 ---- a/data/org.gnome.shell.gschema.xml.in -+++ b/data/org.gnome.shell.gschema.xml.in -@@ -39,7 +39,7 @@ - - - -- [ 'firefox.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ] -+ [ 'firefox.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop', 'yelp.desktop' ] - List of desktop file IDs for favorite applications - - The applications corresponding to these identifiers --- -2.21.0 - diff --git a/SOURCES/horizontal-workspace-support.patch b/SOURCES/horizontal-workspace-support.patch deleted file mode 100644 index 8605e1d..0000000 --- a/SOURCES/horizontal-workspace-support.patch +++ /dev/null @@ -1,399 +0,0 @@ -From b42dd3f87ad5fb6c7ee139cb0de22e0fbb393ba2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Tue, 4 Jun 2019 19:22:26 +0000 -Subject: [PATCH 1/2] workspaceSwitcherPopup: Support horizontal layout - -While mutter supports a variety of different grid layouts (n columns/rows, -growing vertically or horizontally from any of the four corners), we -hardcode a fixed vertical layout of a single column. - -Now that mutter exposes the actual layout to us, add support for a more -traditional horizontal layout as well. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/575 ---- - data/theme/gnome-shell-sass/_common.scss | 3 +- - js/ui/windowManager.js | 36 ++++++++-- - js/ui/workspaceSwitcherPopup.js | 86 ++++++++++++++++++------ - 3 files changed, 98 insertions(+), 27 deletions(-) - -diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss -index 293ea2ab9..b1eeb0ce9 100644 ---- a/data/theme/gnome-shell-sass/_common.scss -+++ b/data/theme/gnome-shell-sass/_common.scss -@@ -680,7 +680,8 @@ StScrollBar { - spacing: 8px; - } - -- .ws-switcher-active-up, .ws-switcher-active-down { -+ .ws-switcher-active-up, .ws-switcher-active-down, -+ .ws-switcher-active-left, .ws-switcher-active-right { - height: 50px; - background-color: $selected_bg_color; - color: $selected_fg_color; -diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js -index b9f5fef46..dfe1b4460 100644 ---- a/js/ui/windowManager.js -+++ b/js/ui/windowManager.js -@@ -2145,6 +2145,8 @@ var WindowManager = class { - let [action,,,target] = binding.get_name().split('-'); - let newWs; - let direction; -+ let vertical = workspaceManager.layout_rows == -1; -+ let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL; - - if (action == 'move') { - // "Moving" a window to another workspace doesn't make sense when -@@ -2157,7 +2159,12 @@ var WindowManager = class { - } - - if (target == 'last') { -- direction = Meta.MotionDirection.DOWN; -+ if (vertical) -+ direction = Meta.MotionDirection.DOWN; -+ else if (rtl) -+ direction = Meta.MotionDirection.LEFT; -+ else -+ direction = Meta.MotionDirection.RIGHT; - newWs = workspaceManager.get_workspace_by_index(workspaceManager.n_workspaces - 1); - } else if (isNaN(target)) { - // Prepend a new workspace dynamically -@@ -2173,16 +2180,33 @@ var WindowManager = class { - target--; - newWs = workspaceManager.get_workspace_by_index(target); - -- if (workspaceManager.get_active_workspace().index() > target) -- direction = Meta.MotionDirection.UP; -- else -- direction = Meta.MotionDirection.DOWN; -+ if (workspaceManager.get_active_workspace().index() > target) { -+ if (vertical) -+ direction = Meta.MotionDirection.UP; -+ else if (rtl) -+ direction = Meta.MotionDirection.RIGHT; -+ else -+ direction = Meta.MotionDirection.LEFT; -+ } else { -+ if (vertical) -+ direction = Meta.MotionDirection.DOWN; -+ else if (rtl) -+ direction = Meta.MotionDirection.LEFT; -+ else -+ direction = Meta.MotionDirection.RIGHT; -+ } - } - -- if (direction != Meta.MotionDirection.UP && -+ if (workspaceManager.layout_rows == -1 && -+ direction != Meta.MotionDirection.UP && - direction != Meta.MotionDirection.DOWN) - return; - -+ if (workspaceManager.layout_columns == -1 && -+ direction != Meta.MotionDirection.LEFT && -+ direction != Meta.MotionDirection.RIGHT) -+ return; -+ - if (action == 'switch') - this.actionMoveWorkspace(newWs); - else -diff --git a/js/ui/workspaceSwitcherPopup.js b/js/ui/workspaceSwitcherPopup.js -index 26404eaab..d21c5de4d 100644 ---- a/js/ui/workspaceSwitcherPopup.js -+++ b/js/ui/workspaceSwitcherPopup.js -@@ -17,41 +17,75 @@ class WorkspaceSwitcherPopupList extends St.Widget { - this._itemSpacing = 0; - this._childHeight = 0; - this._childWidth = 0; -+ this._orientation = global.workspace_manager.layout_rows == -1 -+ ? Clutter.Orientation.VERTICAL -+ : Clutter.Orientation.HORIZONTAL; - - this.connect('style-changed', () => { - this._itemSpacing = this.get_theme_node().get_length('spacing'); - }); - } - -- vfunc_get_preferred_height(forWidth) { -+ _getPreferredSizeForOrientation(forSize) { - let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex); - let themeNode = this.get_theme_node(); - -- let availHeight = workArea.height; -- availHeight -= themeNode.get_vertical_padding(); -+ let availSize; -+ if (this._orientation == Clutter.Orientation.HORIZONTAL) -+ availSize = workArea.width - themeNode.get_horizontal_padding(); -+ else -+ availSize = workArea.height - themeNode.get_vertical_padding(); - -- let height = 0; -+ let size = 0; - for (let child of this.get_children()) { - let [childMinHeight, childNaturalHeight] = child.get_preferred_height(-1); -- let [childMinWidth, childNaturalWidth] = child.get_preferred_width(childNaturalHeight); -- height += childNaturalHeight * workArea.width / workArea.height; -+ let height = childNaturalHeight * workArea.width / workArea.height; -+ -+ if (this._orientation == Clutter.Orientation.HORIZONTAL) { -+ size += height * workArea.width / workArea.height; -+ } else { -+ size += height; -+ } - } - - let workspaceManager = global.workspace_manager; - let spacing = this._itemSpacing * (workspaceManager.n_workspaces - 1); -- height += spacing; -- height = Math.min(height, availHeight); -+ size += spacing; -+ size = Math.min(size, availSize); -+ -+ if (this._orientation == Clutter.Orientation.HORIZONTAL) { -+ this._childWidth = (size - spacing) / workspaceManager.n_workspaces; -+ return themeNode.adjust_preferred_width(size, size); -+ } else { -+ this._childHeight = (size - spacing) / workspaceManager.n_workspaces; -+ return themeNode.adjust_preferred_height(size, size); -+ } -+ } -+ -+ _getSizeForOppositeOrientation() { -+ let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex); - -- this._childHeight = (height - spacing) / workspaceManager.n_workspaces; -+ if (this._orientation == Clutter.Orientation.HORIZONTAL) { -+ this._childHeight = Math.round(this._childWidth * workArea.height / workArea.width); -+ return [this._childHeight, this._childHeight]; -+ } else { -+ this._childWidth = Math.round(this._childHeight * workArea.width / workArea.height); -+ return [this._childWidth, this._childWidth]; -+ } -+ } - -- return themeNode.adjust_preferred_height(height, height); -+ vfunc_get_preferred_height(forWidth) { -+ if (this._orientation == Clutter.Orientation.HORIZONTAL) -+ return this._getSizeForOppositeOrientation(); -+ else -+ return this._getPreferredSizeForOrientation(forWidth); - } - - vfunc_get_preferred_width(forHeight) { -- let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex); -- this._childWidth = Math.round(this._childHeight * workArea.width / workArea.height); -- -- return [this._childWidth, this._childWidth]; -+ if (this._orientation == Clutter.Orientation.HORIZONTAL) -+ return this._getPreferredSizeForOrientation(forHeight); -+ else -+ return this._getSizeForOppositeOrientation(); - } - - vfunc_allocate(box, flags) { -@@ -62,15 +96,23 @@ class WorkspaceSwitcherPopupList extends St.Widget { - - let childBox = new Clutter.ActorBox(); - -+ let rtl = this.text_direction == Clutter.TextDirection.RTL; -+ let x = rtl ? box.x2 - this._childWidth : box.x1; - let y = box.y1; -- let prevChildBoxY2 = box.y1 - this._itemSpacing; - for (let child of this.get_children()) { -- childBox.x1 = box.x1; -- childBox.x2 = box.x1 + this._childWidth; -- childBox.y1 = prevChildBoxY2 + this._itemSpacing; -+ childBox.x1 = Math.round(x); -+ childBox.x2 = Math.round(x + this._childWidth); -+ childBox.y1 = Math.round(y); - childBox.y2 = Math.round(y + this._childHeight); -- y += this._childHeight + this._itemSpacing; -- prevChildBoxY2 = childBox.y2; -+ -+ if (this._orientation == Clutter.Orientation.HORIZONTAL) { -+ if (rtl) -+ x -= this._childWidth + this._itemSpacing; -+ else -+ x += this._childWidth + this._itemSpacing; -+ } else { -+ y += this._childHeight + this._itemSpacing; -+ } - child.allocate(childBox, flags); - } - } -@@ -123,6 +165,10 @@ class WorkspaceSwitcherPopup extends St.Widget { - indicator = new St.Bin({ style_class: 'ws-switcher-active-up' }); - else if(i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.DOWN) - indicator = new St.Bin({ style_class: 'ws-switcher-active-down' }); -+ else if(i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.LEFT) -+ indicator = new St.Bin({ style_class: 'ws-switcher-active-left' }); -+ else if(i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.RIGHT) -+ indicator = new St.Bin({ style_class: 'ws-switcher-active-right' }); - else - indicator = new St.Bin({ style_class: 'ws-switcher-box' }); - --- -2.21.0 - - -From 813976ff69b15ab884d44f5f6a56ae66f407acfd Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Tue, 4 Jun 2019 19:49:23 +0000 -Subject: [PATCH 2/2] workspacesView: Support horizontal layout - -Just as we did for the workspace switcher popup, support workspaces -being laid out in a single row in the window picker. - -Note that this takes care of the various workspace switch actions in -the overview (scrolling, panning, touch(pad) gestures) as well as the -switch animation, but not of the overview's workspace switcher component. - -There are currently no plans to support other layouts there, as the -component is inherently vertical (in fact, it was the whole reason for -switching the layout in the first place). - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/575 ---- - js/ui/workspacesView.js | 81 ++++++++++++++++++++++++++++++----------- - 1 file changed, 60 insertions(+), 21 deletions(-) - -diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js -index fe06d9dae..069937d5a 100644 ---- a/js/ui/workspacesView.js -+++ b/js/ui/workspacesView.js -@@ -181,26 +181,32 @@ var WorkspacesView = class extends WorkspacesViewBase { - - Tweener.removeTweens(workspace.actor); - -- let y = (w - active) * this._fullGeometry.height; -+ let params = {}; -+ if (workspaceManager.layout_rows == -1) -+ params.y = (w - active) * this._fullGeometry.height; -+ else if (this.actor.text_direction == Clutter.TextDirection.RTL) -+ params.x = (active - w) * this._fullGeometry.width; -+ else -+ params.x = (w - active) * this._fullGeometry.width; - - if (showAnimation) { -- let params = { y: y, -- time: WORKSPACE_SWITCH_TIME, -- transition: 'easeOutQuad' -- }; -+ let tweenParams = Object.assign(params, { -+ time: WORKSPACE_SWITCH_TIME, -+ transition: 'easeOutQuad' -+ }); - // we have to call _updateVisibility() once before the - // animation and once afterwards - it does not really - // matter which tween we use, so we pick the first one ... - if (w == 0) { - this._updateVisibility(); -- params.onComplete = () => { -+ tweenParams.onComplete = () => { - this._animating = false; - this._updateVisibility(); - }; - } -- Tweener.addTween(workspace.actor, params); -+ Tweener.addTween(workspace.actor, tweenParams); - } else { -- workspace.actor.set_position(0, y); -+ workspace.actor.set(params); - if (w == 0) - this._updateVisibility(); - } -@@ -338,22 +344,39 @@ var WorkspacesView = class extends WorkspacesViewBase { - metaWorkspace.activate(global.get_current_time()); - } - -- let last = this._workspaces.length - 1; -- let firstWorkspaceY = this._workspaces[0].actor.y; -- let lastWorkspaceY = this._workspaces[last].actor.y; -- let workspacesHeight = lastWorkspaceY - firstWorkspaceY; -- - if (adj.upper == 1) - return; - -- let currentY = firstWorkspaceY; -- let newY = - adj.value / (adj.upper - 1) * workspacesHeight; -+ let last = this._workspaces.length - 1; -+ -+ if (workspaceManager.layout_rows == -1) { -+ let firstWorkspaceY = this._workspaces[0].actor.y; -+ let lastWorkspaceY = this._workspaces[last].actor.y; -+ let workspacesHeight = lastWorkspaceY - firstWorkspaceY; -+ -+ let currentY = firstWorkspaceY; -+ let newY = -adj.value / (adj.upper - 1) * workspacesHeight; - -- let dy = newY - currentY; -+ let dy = newY - currentY; -+ -+ for (let i = 0; i < this._workspaces.length; i++) { -+ this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1; -+ this._workspaces[i].actor.y += dy; -+ } -+ } else { -+ let firstWorkspaceX = this._workspaces[0].actor.x; -+ let lastWorkspaceX = this._workspaces[last].actor.x; -+ let workspacesWidth = lastWorkspaceX - firstWorkspaceX; - -- for (let i = 0; i < this._workspaces.length; i++) { -- this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1; -- this._workspaces[i].actor.y += dy; -+ let currentX = firstWorkspaceX; -+ let newX = -adj.value / (adj.upper - 1) * workspacesWidth; -+ -+ let dx = newX - currentX; -+ -+ for (let i = 0; i < this._workspaces.length; i++) { -+ this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1; -+ this._workspaces[i].actor.x += dx; -+ } - } - } - }; -@@ -504,7 +527,12 @@ var WorkspacesDisplay = class { - _onPan(action) { - let [dist, dx, dy] = action.get_motion_delta(0); - let adjustment = this._scrollAdjustment; -- adjustment.value -= (dy / this.actor.height) * adjustment.page_size; -+ if (global.workspace_manager.layout_rows == -1) -+ adjustment.value -= (dy / this.actor.height) * adjustment.page_size; -+ else if (this.actor.text_direction == Clutter.TextDirection.RTL) -+ adjustment.value += (dx / this.actor.width) * adjustment.page_size; -+ else -+ adjustment.value -= (dx / this.actor.width) * adjustment.page_size; - return false; - } - -@@ -536,7 +564,12 @@ var WorkspacesDisplay = class { - let workspaceManager = global.workspace_manager; - let active = workspaceManager.get_active_workspace_index(); - let adjustment = this._scrollAdjustment; -- adjustment.value = (active - yRel / this.actor.height) * adjustment.page_size; -+ if (workspaceManager.layout_rows == -1) -+ adjustment.value = (active - yRel / this.actor.height) * adjustment.page_size; -+ else if (this.actor.text_direction == Clutter.TextDirection.RTL) -+ adjustment.value = (active + xRel / this.actor.width) * adjustment.page_size; -+ else -+ adjustment.value = (active - xRel / this.actor.width) * adjustment.page_size; - } - - _onSwitchWorkspaceActivated(action, direction) { -@@ -755,6 +788,12 @@ var WorkspacesDisplay = class { - case Clutter.ScrollDirection.DOWN: - ws = activeWs.get_neighbor(Meta.MotionDirection.DOWN); - break; -+ case Clutter.ScrollDirection.LEFT: -+ ws = activeWs.get_neighbor(Meta.MotionDirection.LEFT); -+ break; -+ case Clutter.ScrollDirection.RIGHT: -+ ws = activeWs.get_neighbor(Meta.MotionDirection.RIGHT); -+ break; - default: - return Clutter.EVENT_PROPAGATE; - } --- -2.21.0 - diff --git a/SOURCES/introspect-backports.patch b/SOURCES/introspect-backports.patch deleted file mode 100644 index b93532c..0000000 --- a/SOURCES/introspect-backports.patch +++ /dev/null @@ -1,643 +0,0 @@ -From 781dfcf6ce7168c6b116d58df5f1c67291a7b513 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Thu, 16 May 2019 00:57:27 +0200 -Subject: [PATCH 01/11] introspect: Include `sandboxed-app-id` as well - -App IDs in gnome-shell don't match AppStream, Flatpak or Snap IDs. For the -desktop portal, the latter two are more relevant, so include it in the -returned information. - -https://gitlab.gnome.org/GNOME/gnome-shell/issues/1289 ---- - js/misc/introspect.js | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/js/misc/introspect.js b/js/misc/introspect.js -index f7a7f2fe6..1e8300d0a 100644 ---- a/js/misc/introspect.js -+++ b/js/misc/introspect.js -@@ -55,6 +55,11 @@ var IntrospectService = class { - return APP_WHITELIST.includes(sender); - } - -+ _getSandboxedAppId(app) { -+ let ids = app.get_windows().map(w => w.get_sandboxed_app_id()); -+ return ids.find(id => id != null); -+ } -+ - _syncRunningApplications() { - let tracker = Shell.WindowTracker.get_default(); - let apps = this._appSystem.get_running(); -@@ -76,6 +81,10 @@ var IntrospectService = class { - newActiveApplication = app.get_id(); - } - -+ let sandboxedAppId = this._getSandboxedAppId(app); -+ if (sandboxedAppId) -+ appInfo['sandboxed-app-id'] = new GLib.Variant('s', sandboxedAppId); -+ - newRunningApplications[app.get_id()] = appInfo; - } - -@@ -137,6 +146,7 @@ var IntrospectService = class { - let frameRect = window.get_frame_rect(); - let title = window.get_title(); - let wmClass = window.get_wm_class(); -+ let sandboxedAppId = window.get_sandboxed_app_id(); - - windowsList[windowId] = { - 'app-id': GLib.Variant.new('s', app.get_id()), -@@ -153,6 +163,10 @@ var IntrospectService = class { - - if (wmClass != null) - windowsList[windowId]['wm-class'] = GLib.Variant.new('s', wmClass); -+ -+ if (sandboxedAppId != null) -+ windowsList[windowId]['sandboxed-app-id'] = -+ GLib.Variant.new('s', sandboxedAppId); - } - } - invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList])); --- -2.26.2 - - -From b0b4fb82c058722e2171d24902ba3855ffe243f3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Wed, 18 Sep 2019 14:57:48 +0200 -Subject: [PATCH 02/11] introspect: Check whitelist also for - GetRunningWindows() - -Otherwise the xdg-desktop-portal-gtk screen cast widget won't work. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/732 ---- - js/misc/introspect.js | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/js/misc/introspect.js b/js/misc/introspect.js -index 1e8300d0a..cee6409a8 100644 ---- a/js/misc/introspect.js -+++ b/js/misc/introspect.js -@@ -128,7 +128,8 @@ var IntrospectService = class { - let apps = this._appSystem.get_running(); - let windowsList = {}; - -- if (!this._isIntrospectEnabled()) { -+ if (!this._isIntrospectEnabled() && -+ !this._isSenderWhitelisted(invocation.get_sender())) { - invocation.return_error_literal(Gio.DBusError, - Gio.DBusError.ACCESS_DENIED, - 'App introspection not allowed'); --- -2.26.2 - - -From 23556e03db3743ddf478a3c1bbb64946c687afdf Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 25 Nov 2019 19:44:10 +0100 -Subject: [PATCH 03/11] introspect: Fix whitelist check - -The whitelist is a list of well-known D-Bus names, which we then search -for the unique name we get from the method invocation - unsuccesfully. - -Fix this by watching the bus for any name in the whitelist in order -to maintain a map from wel-known to unique name that we can use for -matching. - -https://gitlab.gnome.org/GNOME/gnome-shell/issues/1916 ---- - js/misc/introspect.js | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) - -diff --git a/js/misc/introspect.js b/js/misc/introspect.js -index cee6409a8..f14eabfad 100644 ---- a/js/misc/introspect.js -+++ b/js/misc/introspect.js -@@ -39,6 +39,15 @@ var IntrospectService = class { - }); - - this._syncRunningApplications(); -+ -+ this._whitelistMap = new Map(); -+ APP_WHITELIST.forEach(appName => { -+ Gio.DBus.watch_name(Gio.BusType.SESSION, -+ appName, -+ Gio.BusNameWatcherFlags.NONE, -+ (conn, name, owner) => this._whitelistMap.set(name, owner), -+ (conn, name) => this._whitelistMap.delete(name)); -+ }); - } - - _isStandaloneApp(app) { -@@ -52,7 +61,7 @@ var IntrospectService = class { - } - - _isSenderWhitelisted(sender) { -- return APP_WHITELIST.includes(sender); -+ return [...this._whitelistMap.values()].includes(sender); - } - - _getSandboxedAppId(app) { --- -2.26.2 - - -From 1a6275add6d214df958ed8a06c097445bef021bc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Wed, 25 Sep 2019 20:36:28 +0200 -Subject: [PATCH 04/11] introspect: Add helper to check method call permission - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757 ---- - js/misc/introspect.js | 16 ++++++++++++---- - 1 file changed, 12 insertions(+), 4 deletions(-) - -diff --git a/js/misc/introspect.js b/js/misc/introspect.js -index f14eabfad..6186754cd 100644 ---- a/js/misc/introspect.js -+++ b/js/misc/introspect.js -@@ -120,9 +120,18 @@ var IntrospectService = class { - type == Meta.WindowType.UTILITY); - } - -+ _isInvocationAllowed(invocation) { -+ if (this._isIntrospectEnabled()) -+ return true; -+ -+ if (this._isSenderWhitelisted(invocation.get_sender())) -+ return true; -+ -+ return false; -+ } -+ - GetRunningApplicationsAsync(params, invocation) { -- if (!this._isIntrospectEnabled() && -- !this._isSenderWhitelisted(invocation.get_sender())) { -+ if (!this._isInvocationAllowed(invocation)) { - invocation.return_error_literal(Gio.DBusError, - Gio.DBusError.ACCESS_DENIED, - 'App introspection not allowed'); -@@ -137,8 +146,7 @@ var IntrospectService = class { - let apps = this._appSystem.get_running(); - let windowsList = {}; - -- if (!this._isIntrospectEnabled() && -- !this._isSenderWhitelisted(invocation.get_sender())) { -+ if (!this._isInvocationAllowed(invocation)) { - invocation.return_error_literal(Gio.DBusError, - Gio.DBusError.ACCESS_DENIED, - 'App introspection not allowed'); --- -2.26.2 - - -From f578dc01cf774faa4504a4d258cc0e82060d988b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Tue, 1 Oct 2019 11:55:33 +0200 -Subject: [PATCH 05/11] shell-util: Add API to check for X11 extensions - -Will be used to disable animations when running inside Xvnc. This was -done in gsd-xsettings before. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757 ---- - src/shell-util.c | 26 ++++++++++++++++++++++++++ - src/shell-util.h | 3 +++ - 2 files changed, 29 insertions(+) - -diff --git a/src/shell-util.c b/src/shell-util.c -index 31bb18e70..fa3fc08c8 100644 ---- a/src/shell-util.c -+++ b/src/shell-util.c -@@ -21,6 +21,8 @@ - #include - #include - #include -+#include -+#include - - #include - #ifdef HAVE__NL_TIME_FIRST_WEEKDAY -@@ -613,3 +615,27 @@ shell_util_check_cloexec_fds (void) - fdwalk (check_cloexec, NULL); - g_info ("Open fd CLOEXEC check complete"); - } -+ -+/** -+ * shell_util_has_x11_display_extension: -+ * @display: A #MetaDisplay -+ * @extension: An X11 extension -+ * -+ * If the corresponding X11 display provides the passed extension, return %TRUE, -+ * otherwise %FALSE. If there is no X11 display, %FALSE is passed. -+ */ -+gboolean -+shell_util_has_x11_display_extension (MetaDisplay *display, -+ const char *extension) -+{ -+ MetaX11Display *x11_display; -+ Display *xdisplay; -+ int op, event, error; -+ -+ x11_display = meta_display_get_x11_display (display); -+ if (!x11_display) -+ return FALSE; -+ -+ xdisplay = meta_x11_display_get_xdisplay (x11_display); -+ return XQueryExtension (xdisplay, extension, &op, &event, &error); -+} -diff --git a/src/shell-util.h b/src/shell-util.h -index 6904f43bc..02b8404e9 100644 ---- a/src/shell-util.h -+++ b/src/shell-util.h -@@ -59,6 +59,9 @@ cairo_surface_t * shell_util_composite_capture_images (ClutterCapture *captures - - void shell_util_check_cloexec_fds (void); - -+gboolean shell_util_has_x11_display_extension (MetaDisplay *display, -+ const char *extension); -+ - G_END_DECLS - - #endif /* __SHELL_UTIL_H__ */ --- -2.26.2 - - -From 48ee79bb7b48c7e93e77e35629f21bbdbabc253f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Tue, 1 Oct 2019 11:56:34 +0200 -Subject: [PATCH 06/11] st/settings: Add API to inhibit animations - -There may be situations where we shouldn't enable animations. Make it -possible for the Shell to decide when there are such situations and in -when needed inhibit animations. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757 ---- - src/st/st-settings.c | 38 +++++++++++++++++++++++++++++++++++++- - src/st/st-settings.h | 4 ++++ - 2 files changed, 41 insertions(+), 1 deletion(-) - -diff --git a/src/st/st-settings.c b/src/st/st-settings.c -index 17f2c466e..ebfd28480 100644 ---- a/src/st/st-settings.c -+++ b/src/st/st-settings.c -@@ -54,6 +54,7 @@ struct _StSettings - - gchar *gtk_theme; - gchar *gtk_icon_theme; -+ int inhibit_animations_count; - gboolean enable_animations; - gboolean primary_paste; - gboolean magnifier_active; -@@ -62,6 +63,41 @@ struct _StSettings - - G_DEFINE_TYPE (StSettings, st_settings, G_TYPE_OBJECT) - -+static gboolean -+get_enable_animations (StSettings *settings) -+{ -+ if (settings->inhibit_animations_count > 0) -+ return FALSE; -+ else -+ return settings->enable_animations; -+} -+ -+void -+st_settings_inhibit_animations (StSettings *settings) -+{ -+ gboolean enable_animations; -+ -+ enable_animations = get_enable_animations (settings); -+ settings->inhibit_animations_count++; -+ -+ if (enable_animations != get_enable_animations (settings)) -+ g_object_notify_by_pspec (G_OBJECT (settings), -+ props[PROP_ENABLE_ANIMATIONS]); -+} -+ -+void -+st_settings_uninhibit_animations (StSettings *settings) -+{ -+ gboolean enable_animations; -+ -+ enable_animations = get_enable_animations (settings); -+ settings->inhibit_animations_count--; -+ -+ if (enable_animations != get_enable_animations (settings)) -+ g_object_notify_by_pspec (G_OBJECT (settings), -+ props[PROP_ENABLE_ANIMATIONS]); -+} -+ - static void - st_settings_finalize (GObject *object) - { -@@ -95,7 +131,7 @@ st_settings_get_property (GObject *object, - switch (prop_id) - { - case PROP_ENABLE_ANIMATIONS: -- g_value_set_boolean (value, settings->enable_animations); -+ g_value_set_boolean (value, get_enable_animations (settings)); - break; - case PROP_PRIMARY_PASTE: - g_value_set_boolean (value, settings->primary_paste); -diff --git a/src/st/st-settings.h b/src/st/st-settings.h -index c2c4fa23e..8b2549469 100644 ---- a/src/st/st-settings.h -+++ b/src/st/st-settings.h -@@ -33,6 +33,10 @@ G_DECLARE_FINAL_TYPE (StSettings, st_settings, ST, SETTINGS, GObject) - - StSettings * st_settings_get (void); - -+void st_settings_inhibit_animations (StSettings *settings); -+ -+void st_settings_uninhibit_animations (StSettings *settings); -+ - G_END_DECLS - - #endif /* __ST_SETTINGS_H__ */ --- -2.26.2 - - -From 80025388c44296b629c8f24ea673d77ffc4efc67 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Tue, 1 Oct 2019 12:02:31 +0200 -Subject: [PATCH 07/11] main: Inhibit animations when software rendered - -This was previously decided by gsd-xsettings. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757 ---- - js/ui/main.js | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/js/ui/main.js b/js/ui/main.js -index 978f83c3f..c3230ff03 100644 ---- a/js/ui/main.js -+++ b/js/ui/main.js -@@ -147,6 +147,8 @@ function _initializeUI() { - _loadOskLayouts(); - _loadDefaultStylesheet(); - -+ new AnimationsSettings(); -+ - // Setup the stage hierarchy early - layoutManager = new Layout.LayoutManager(); - -@@ -723,3 +725,13 @@ function showRestartMessage(message) { - let restartMessage = new RestartMessage(message); - restartMessage.open(); - } -+ -+var AnimationsSettings = class { -+ constructor() { -+ let backend = Meta.get_backend(); -+ if (!backend.is_rendering_hardware_accelerated()) { -+ St.Settings.get().inhibit_animations(); -+ return; -+ } -+ } -+}; --- -2.26.2 - - -From 788ecb60e35d8a369f0747813f37e8b1ca27cb87 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Tue, 1 Oct 2019 12:03:52 +0200 -Subject: [PATCH 08/11] main: Inhibit animations if X server advertises - VNC-EXTENSION - -This was previously done by gsd-xsettings to disable animations when -running in Xvnc. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757 ---- - js/ui/main.js | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/js/ui/main.js b/js/ui/main.js -index c3230ff03..ae7c3ffd0 100644 ---- a/js/ui/main.js -+++ b/js/ui/main.js -@@ -733,5 +733,12 @@ var AnimationsSettings = class { - St.Settings.get().inhibit_animations(); - return; - } -+ -+ let isXvnc = Shell.util_has_x11_display_extension( -+ global.display, 'VNC-EXTENSION'); -+ if (isXvnc) { -+ St.Settings.get().inhibit_animations(); -+ return; -+ } - } - }; --- -2.26.2 - - -From 1da5a7ce4cf0b95b96dd50b62ac6c1380fd88cb1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Tue, 1 Oct 2019 12:04:52 +0200 -Subject: [PATCH 09/11] main: Inhibit animations when there is a remote desktop - session - -If a remote desktop session asks for animations to be disabled, inhibit -animations while the session is active. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757 ---- - js/ui/main.js | 26 ++++++++++++++++++++++++++ - 1 file changed, 26 insertions(+) - -diff --git a/js/ui/main.js b/js/ui/main.js -index ae7c3ffd0..1203b3c39 100644 ---- a/js/ui/main.js -+++ b/js/ui/main.js -@@ -740,5 +740,31 @@ var AnimationsSettings = class { - St.Settings.get().inhibit_animations(); - return; - } -+ -+ let remoteAccessController = backend.get_remote_access_controller(); -+ if (!remoteAccessController) -+ return; -+ -+ this._handles = new Set(); -+ remoteAccessController.connect('new-handle', -+ (_, handle) => this._onNewRemoteAccessHandle(handle)); -+ } -+ -+ _onRemoteAccessHandleStopped(handle) { -+ let settings = St.Settings.get(); -+ -+ settings.uninhibit_animations(); -+ this._handles.delete(handle); -+ } -+ -+ _onNewRemoteAccessHandle(handle) { -+ if (!handle.get_disable_animations()) -+ return; -+ -+ let settings = St.Settings.get(); -+ -+ settings.inhibit_animations(); -+ this._handles.add(handle); -+ handle.connect('stopped', this._onRemoteAccessHandleStopped.bind(this)); - } - }; --- -2.26.2 - - -From ebfd46341a2d7a6338386e4be4a2807a6bc6e63c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Tue, 1 Oct 2019 12:06:13 +0200 -Subject: [PATCH 10/11] introspect: Rename variable - -It was too generic, and would conflict with a StSettings variable. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757 ---- - js/misc/introspect.js | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/js/misc/introspect.js b/js/misc/introspect.js -index 6186754cd..8e68a7e4f 100644 ---- a/js/misc/introspect.js -+++ b/js/misc/introspect.js -@@ -29,7 +29,9 @@ var IntrospectService = class { - this._syncRunningApplications(); - }); - -- this._settings = new Gio.Settings({ schema_id: INTROSPECT_SCHEMA }); -+ this._introspectSettings = new Gio.Settings({ -+ schema_id: INTROSPECT_SCHEMA, -+ }); - - let tracker = Shell.WindowTracker.get_default(); - tracker.connect('notify::focus-app', -@@ -57,7 +59,7 @@ var IntrospectService = class { - } - - _isIntrospectEnabled() { -- return this._settings.get_boolean(INTROSPECT_KEY); -+ return this._introspectSettings.get_boolean(INTROSPECT_KEY); - } - - _isSenderWhitelisted(sender) { --- -2.26.2 - - -From 343e7792fc84c296b331c3fcb142ed79d2ce9bd5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Tue, 1 Oct 2019 12:07:03 +0200 -Subject: [PATCH 11/11] introspect: Add AnimationsEnabled property - -While the gsetting is available for all who needs it, the Shell might -override it given various hueristics. Expose the decision made by the -Shell via a new property. - -Intended to be used by gsd-xsettings as well as xdg-desktop-portal-gtk. - -This also add a version property to the API, so that semi external -services (xdg-desktop-portal-gtk) can detect what API is expected to be -present. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757 ---- - .../org.gnome.Shell.Introspect.xml | 14 ++++++++++ - js/misc/introspect.js | 27 ++++++++++++++++++- - 2 files changed, 40 insertions(+), 1 deletion(-) - -diff --git a/data/dbus-interfaces/org.gnome.Shell.Introspect.xml b/data/dbus-interfaces/org.gnome.Shell.Introspect.xml -index 9508681af..d71f2414b 100644 ---- a/data/dbus-interfaces/org.gnome.Shell.Introspect.xml -+++ b/data/dbus-interfaces/org.gnome.Shell.Introspect.xml -@@ -57,5 +57,19 @@ - - - -+ -+ -+ -+ -+ - - -diff --git a/js/misc/introspect.js b/js/misc/introspect.js -index 8e68a7e4f..7c62113e5 100644 ---- a/js/misc/introspect.js -+++ b/js/misc/introspect.js -@@ -1,9 +1,11 @@ --const { Gio, GLib, Meta, Shell } = imports.gi; -+const { Gio, GLib, Meta, Shell, St } = imports.gi; - - const INTROSPECT_SCHEMA = 'org.gnome.shell'; - const INTROSPECT_KEY = 'introspect'; - const APP_WHITELIST = ['org.freedesktop.impl.portal.desktop.gtk']; - -+const INTROSPECT_DBUS_API_VERSION = 2; -+ - const { loadInterfaceXML } = imports.misc.fileUtils; - - const IntrospectDBusIface = loadInterfaceXML('org.gnome.Shell.Introspect'); -@@ -21,6 +23,7 @@ var IntrospectService = class { - this._runningApplicationsDirty = true; - this._activeApplication = null; - this._activeApplicationDirty = true; -+ this._animationsEnabled = true; - - this._appSystem = Shell.AppSystem.get_default(); - this._appSystem.connect('app-state-changed', -@@ -50,6 +53,11 @@ var IntrospectService = class { - (conn, name, owner) => this._whitelistMap.set(name, owner), - (conn, name) => this._whitelistMap.delete(name)); - }); -+ -+ this._settings = St.Settings.get(); -+ this._settings.connect('notify::enable-animations', -+ this._syncAnimationsEnabled.bind(this)); -+ this._syncAnimationsEnabled(); - } - - _isStandaloneApp(app) { -@@ -191,4 +199,21 @@ var IntrospectService = class { - } - invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList])); - } -+ -+ _syncAnimationsEnabled() { -+ let wasAnimationsEnabled = this._animationsEnabled; -+ this._animationsEnabled = this._settings.enable_animations; -+ if (wasAnimationsEnabled !== this._animationsEnabled) { -+ let variant = new GLib.Variant('b', this._animationsEnabled); -+ this._dbusImpl.emit_property_changed('AnimationsEnabled', variant); -+ } -+ } -+ -+ get AnimationsEnabled() { -+ return this._animationsEnabled; -+ } -+ -+ get version() { -+ return INTROSPECT_DBUS_API_VERSION; -+ } - }; --- -2.26.2 - diff --git a/SOURCES/more-spurious-allocation-warnings.patch b/SOURCES/more-spurious-allocation-warnings.patch deleted file mode 100644 index 16acc8f..0000000 --- a/SOURCES/more-spurious-allocation-warnings.patch +++ /dev/null @@ -1,176 +0,0 @@ -From 4926a9b8f958617d67d603622b1382c17fe4037c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= -Date: Wed, 20 May 2020 12:05:04 +0200 -Subject: [PATCH 1/2] workspacesView: Avoid setting invalid geometries on views - -The fullGeometry and the actualGeometry of the WorkspacesDisplay are set -from the allocation of the overviews ControlsManager and the -WorkspacesDisplay, that means they're only valid after those actors got -their allocations during Clutters allocation cycle. - -Since WorkspacesDisplay._updateWorkspacesViews() is already called while -showing/mapping the WorkspacesDisplay, that allocation cycle didn't -happen yet and we end up either setting the geometries of the views to -null (in case of the fullGeometry) or to something wrong (a 0-sized -allocation in case of the actualGeometry). - -So avoid setting invalid geometries on the views by initializing both -the fullGeometry and the actualGeometry to null, and then only updating -the geometries of the views after they're set to a correct value. - -Note that this means we won't correctly animate the overview the first -time we open it since the animation depends on the geometries being set, -but is being started from show(), which means no allocations have -happened yet. In practice this introduces no regression though since -before this change we simply used incorrect geometries (see the 0-sized -allocation mentioned above) on the initial opening and the animation -didn't work either. - -https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1119 ---- - js/ui/workspacesView.js | 28 +++++++++++++++++----------- - 1 file changed, 17 insertions(+), 11 deletions(-) - -diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js -index e302296a6..02baddc6e 100644 ---- a/js/ui/workspacesView.js -+++ b/js/ui/workspacesView.js -@@ -521,6 +521,7 @@ var WorkspacesDisplay = class { - this._scrollEventId = 0; - this._keyPressEventId = 0; - -+ this._actualGeometry = null; - this._fullGeometry = null; - } - -@@ -675,8 +676,10 @@ var WorkspacesDisplay = class { - - this._workspacesViews.forEach(v => v.actor.show()); - -- this._updateWorkspacesFullGeometry(); -- this._updateWorkspacesActualGeometry(); -+ if (this._fullGeometry) -+ this._syncWorkspacesFullGeometry(); -+ if (this._actualGeometry) -+ this._syncWorkspacesActualGeometry(); - } - - _scrollValueChanged() { -@@ -739,10 +742,10 @@ var WorkspacesDisplay = class { - // the sliding controls were never slid in at all. - setWorkspacesFullGeometry(geom) { - this._fullGeometry = geom; -- this._updateWorkspacesFullGeometry(); -+ this._syncWorkspacesFullGeometry(); - } - -- _updateWorkspacesFullGeometry() { -+ _syncWorkspacesFullGeometry() { - if (!this._workspacesViews.length) - return; - -@@ -754,18 +757,21 @@ var WorkspacesDisplay = class { - } - - _updateWorkspacesActualGeometry() { -+ const [x, y] = this.actor.get_transformed_position(); -+ const width = this.actor.allocation.get_width(); -+ const height = this.actor.allocation.get_height(); -+ -+ this._actualGeometry = { x, y, width, height }; -+ this._syncWorkspacesActualGeometry(); -+ } -+ -+ _syncWorkspacesActualGeometry() { - if (!this._workspacesViews.length) - return; - -- let [x, y] = this.actor.get_transformed_position(); -- let allocation = this.actor.allocation; -- let width = allocation.x2 - allocation.x1; -- let height = allocation.y2 - allocation.y1; -- let primaryGeometry = { x: x, y: y, width: width, height: height }; -- - let monitors = Main.layoutManager.monitors; - for (let i = 0; i < monitors.length; i++) { -- let geometry = (i == this._primaryIndex) ? primaryGeometry : monitors[i]; -+ let geometry = i === this._primaryIndex ? this._actualGeometry : monitors[i]; - this._workspacesViews[i].setActualGeometry(geometry); - } - } --- -2.26.2 - - -From 4671eebccf4e6afce8c0a869d63095b39aa7e163 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= -Date: Wed, 20 May 2020 13:39:11 +0200 -Subject: [PATCH 2/2] workspacesView: Only animate on show() when geometries - are already set - -Animating the window clones of the overview requires the fullGeometry -and the actualGeometry to be set, which they won't be when showing the -overview for the first time. So don't even try to animate the window -clones in that case because the geometries will still be null and -accessing them in workspace.js will throw errors. - -The workspace views will still get the correct layout as soon as the -allocations happen because syncing the geometries will trigger updating -the window positions. Since animations are disabled for position changes -when syncing the geometry though, we won't get an animation and the -clones will jump into place. That's not a regression though since before -this change we also didn't animate in that case because the geometries -used were simply wrong (the actualGeometry was 0-sized as explained in -the last commit). - -If we wanted to fix the initial animation of the overview, we'd have to -always enable animations of the window clones when syncing geometries, -but that would break the animation of the workspace when hovering the -workspaceThumbnail slider, because right now those animations are "glued -together" using the actualGeometry, so they would get out of sync. - -The reason there are no errors happening in workspace.js with the -existing code is that due to a bug in Clutter the fullGeometry of -WorkspacesDisplay gets set very early while mapping the WorkspacesViews -(because the overviews ControlsManager gets an allocation during the -resource scale calculation of a ClutterClone, see -https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1181), so it -won't be set to null anymore when calling -WorkspacesView.animateToOverview(). - -https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1119 ---- - js/ui/workspacesView.js | 17 ++++++++++------- - 1 file changed, 10 insertions(+), 7 deletions(-) - -diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js -index 02baddc6e..3e9d77655 100644 ---- a/js/ui/workspacesView.js -+++ b/js/ui/workspacesView.js -@@ -589,13 +589,16 @@ var WorkspacesDisplay = class { - - show(fadeOnPrimary) { - this._updateWorkspacesViews(); -- for (let i = 0; i < this._workspacesViews.length; i++) { -- let animationType; -- if (fadeOnPrimary && i == this._primaryIndex) -- animationType = AnimationType.FADE; -- else -- animationType = AnimationType.ZOOM; -- this._workspacesViews[i].animateToOverview(animationType); -+ -+ if (this._actualGeometry && this._fullGeometry) { -+ for (let i = 0; i < this._workspacesViews.length; i++) { -+ let animationType; -+ if (fadeOnPrimary && i == this._primaryIndex) -+ animationType = AnimationType.FADE; -+ else -+ animationType = AnimationType.ZOOM; -+ this._workspacesViews[i].animateToOverview(animationType); -+ } - } - - this._restackedNotifyId = --- -2.26.2 - diff --git a/SOURCES/osk-fixes.patch b/SOURCES/osk-fixes.patch deleted file mode 100644 index 6c5648d..0000000 --- a/SOURCES/osk-fixes.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 96ccb155bbe6ce570832a9f3d27a0a08698127ea Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= -Date: Sat, 28 Mar 2020 14:15:09 +0100 -Subject: [PATCH 1/3] keyboard: Don't include keyboard devices when updating - lastDevice - -We're dealing with attached keyboards now using the touch_mode property -of ClutterSeat: If a device has a keyboard attached, the touch-mode is -FALSE and we won't automatically show the OSK on touches, also the -touch-mode gets set to FALSE when an external keyboard is being plugged -in, so that also hides the OSK automatically. - -With that, we can now ignore keyboard devices when updating the last -used device and no longer have to special-case our own virtual devices. - -Because there was no special-case for the virtual device we use on -Wayland now, this fixes a bug where the keyboard disappeared after -touching keys like Enter or Backspace. - -Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2287 - -https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1142 ---- - js/ui/keyboard.js | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js -index c4ac72d..94b5325 100644 ---- a/js/ui/keyboard.js -+++ b/js/ui/keyboard.js -@@ -1075,6 +1075,9 @@ var Keyboard = class Keyboard { - let device = manager.get_device(deviceId); - - if (device.get_device_name().indexOf('XTEST') < 0) { -+ if (device.device_type == Clutter.InputDeviceType.KEYBOARD_DEVICE) -+ return; -+ - this._lastDeviceId = deviceId; - this._syncEnabled(); - } --- -2.26.2 - - -From 3106746ae424287d8644643a2ef46d565e4cd7ed Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= -Date: Sat, 28 Mar 2020 14:34:24 +0100 -Subject: [PATCH 2/3] layout: Use translation_y of 0 to hide keyboard - -Since we show the keyboard using a translation_y of -keyboardHeight, the -keyboard will be moved down far enough to be out of sight by setting -translation_y to 0. - -https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1142 ---- - js/ui/layout.js | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/js/ui/layout.js b/js/ui/layout.js -index beb4c0a..4382f6e 100644 ---- a/js/ui/layout.js -+++ b/js/ui/layout.js -@@ -719,7 +719,7 @@ var LayoutManager = GObject.registerClass({ - showKeyboard() { - this.keyboardBox.show(); - Tweener.addTween(this.keyboardBox, -- { anchor_y: this.keyboardBox.height, -+ { translation_y: -this.keyboardBox.height, - opacity: 255, - time: KEYBOARD_ANIMATION_TIME, - transition: 'easeOutQuad', -@@ -735,7 +735,7 @@ var LayoutManager = GObject.registerClass({ - this._updateRegions(); - - this._keyboardHeightNotifyId = this.keyboardBox.connect('notify::height', () => { -- this.keyboardBox.anchor_y = this.keyboardBox.height; -+ this.keyboardBox.translation_y = -this.keyboardBox.height; - }); - } - -@@ -745,7 +745,7 @@ var LayoutManager = GObject.registerClass({ - this._keyboardHeightNotifyId = 0; - } - Tweener.addTween(this.keyboardBox, -- { anchor_y: 0, -+ { translation_y: 0, - opacity: 0, - time: immediate ? 0 : KEYBOARD_ANIMATION_TIME, - transition: 'easeInQuad', --- -2.26.2 - - -From 642822308a72be6a47f4eb285f32539499f0d3e4 Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Wed, 21 Oct 2020 20:29:34 +0200 -Subject: [PATCH 3/3] layout: queue redraw after hiding keyboard - ---- - js/ui/layout.js | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/js/ui/layout.js b/js/ui/layout.js -index 4382f6e..1824313 100644 ---- a/js/ui/layout.js -+++ b/js/ui/layout.js -@@ -759,6 +759,7 @@ var LayoutManager = GObject.registerClass({ - _hideKeyboardComplete() { - this.keyboardBox.hide(); - this._updateRegions(); -+ global.stage.queue_redraw(); - } - - // setDummyCursorGeometry: --- -2.26.2 - diff --git a/SOURCES/owe-support.patch b/SOURCES/owe-support.patch deleted file mode 100644 index c3fdefb..0000000 --- a/SOURCES/owe-support.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 9a5bf8df37490de4472699c235236dc73a637ac7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 11 Sep 2023 19:20:14 +0200 -Subject: [PATCH 1/2] status/network: Fix fallback SSID label - -We currently only return the fallback label if the string returned -from the ssid was invalid or couldn't be transformed to UTF-8. - -If the ssid parameter itself is empty, we throw an error. - -Handle this case as well, as callers otherwise would need to duplicate -the existing error path themselves. ---- - js/ui/status/network.js | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/js/ui/status/network.js b/js/ui/status/network.js -index 9d6a83b733..bd823384da 100644 ---- a/js/ui/status/network.js -+++ b/js/ui/status/network.js -@@ -63,7 +63,9 @@ function signalToIcon(value) { - } - - function ssidToLabel(ssid) { -- let label = NM.utils_ssid_to_utf8(ssid.get_data()); -+ let label; -+ if (ssid) -+ label = NM.utils_ssid_to_utf8(ssid.get_data()); - if (!label) - label = _(""); - return label; --- -2.41.0 - - -From ffc6c744810a902a0aac2a562c9e410336dfdb57 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 30 Aug 2023 01:47:00 +0200 -Subject: [PATCH 2/2] status/network: Use connection name with hidden AP - -When connected to an OWE transition network, NetworkManager -reports the connected API with a hidden SSID. - -Handle this by using the active connection's name before -ultimately falling back to the device name. - -https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6918 - -Part-of: - ---- - js/ui/status/network.js | 28 +++++++++++++++++++--------- - 1 file changed, 19 insertions(+), 9 deletions(-) - -diff --git a/js/ui/status/network.js b/js/ui/status/network.js -index bd823384da..ef04f7f3dd 100644 ---- a/js/ui/status/network.js -+++ b/js/ui/status/network.js -@@ -1346,26 +1346,36 @@ var NMDeviceWireless = class { - _getStatus() { - let ap = this._device.active_access_point; - -- if (this._isHotSpotMaster()) -+ if (this._isHotSpotMaster()) { - /* Translators: %s is a network identifier */ - return _("%s Hotspot Active").format(this._description); -- else if (this._device.state >= NM.DeviceState.PREPARE && -- this._device.state < NM.DeviceState.ACTIVATED) -+ } else if (this._device.state >= NM.DeviceState.PREPARE && -+ this._device.state < NM.DeviceState.ACTIVATED) { - /* Translators: %s is a network identifier */ - return _("%s Connecting").format(this._description); -- else if (ap) -- return ssidToLabel(ap.get_ssid()); -- else if (!this._client.wireless_hardware_enabled) -+ } else if (ap) { -+ const ssid = ap.get_ssid(); -+ if (ssid) -+ return ssidToLabel(ssid); -+ -+ // Use connection name when connected to hidden AP -+ const activeConnection = this._device.get_active_connection(); -+ if (activeConnection) -+ return activeConnection.connection.get_id(); -+ -+ return ssidToLabel(null); -+ } else if (!this._client.wireless_hardware_enabled) { - /* Translators: %s is a network identifier */ - return _("%s Hardware Disabled").format(this._description); -- else if (!this._client.wireless_enabled) -+ } else if (!this._client.wireless_enabled) { - /* Translators: %s is a network identifier */ - return _("%s Off").format(this._description); -- else if (this._device.state == NM.DeviceState.DISCONNECTED) -+ } else if (this._device.state == NM.DeviceState.DISCONNECTED) { - /* Translators: %s is a network identifier */ - return _("%s Not Connected").format(this._description); -- else -+ } else { - return ''; -+ } - } - - _getMenuIcon() { --- -2.41.0 - diff --git a/SOURCES/perf-tool-wayland.patch b/SOURCES/perf-tool-wayland.patch deleted file mode 100644 index be4b625..0000000 --- a/SOURCES/perf-tool-wayland.patch +++ /dev/null @@ -1,399 +0,0 @@ -From 119ec213b8f9a9e55ca340dbde10b0d19becab41 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Thu, 5 Dec 2019 14:12:47 +0100 -Subject: [PATCH 1/4] perf-helper: Add content for custom drawing - -Drawing windows got a lot more involved with the advent of client-side -decorations. Instead of accounting for visible and invisible borders, -titlebar and shadows when necessary, just add an empty child for the -custom drawing. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/887 ---- - src/shell-perf-helper.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - -diff --git a/src/shell-perf-helper.c b/src/shell-perf-helper.c -index e5eab208b..55bdbef02 100644 ---- a/src/shell-perf-helper.c -+++ b/src/shell-perf-helper.c -@@ -120,9 +120,9 @@ on_window_map_event (GtkWidget *window, - } - - static gboolean --on_window_draw (GtkWidget *window, -- cairo_t *cr, -- WindowInfo *info) -+on_child_draw (GtkWidget *window, -+ cairo_t *cr, -+ WindowInfo *info) - { - cairo_rectangle_int_t allocation; - double x_offset, y_offset; -@@ -204,6 +204,7 @@ create_window (int width, - gboolean redraws) - { - WindowInfo *info; -+ GtkWidget *child; - - info = g_new0 (WindowInfo, 1); - info->width = width; -@@ -219,10 +220,13 @@ create_window (int width, - info->pending = TRUE; - info->start_time = -1; - -+ child = g_object_new (GTK_TYPE_BOX, "visible", TRUE, "app-paintable", TRUE, NULL); -+ gtk_container_add (GTK_CONTAINER (info->window), child); -+ - gtk_widget_set_size_request (info->window, width, height); - gtk_widget_set_app_paintable (info->window, TRUE); - g_signal_connect (info->window, "map-event", G_CALLBACK (on_window_map_event), info); -- g_signal_connect (info->window, "draw", G_CALLBACK (on_window_draw), info); -+ g_signal_connect (child, "draw", G_CALLBACK (on_child_draw), info); - gtk_widget_show (info->window); - - if (info->redraws) --- -2.26.2 - - -From bb4c2acaef4d8fdea50915030c221e1190f704a4 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Thu, 5 Dec 2019 13:29:38 +0100 -Subject: [PATCH 2/4] perf-helper: Remove unused atoms - -Those aren't used for anything, but make the helper dependent on X11. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/887 ---- - src/shell-perf-helper.c | 18 ------------------ - 1 file changed, 18 deletions(-) - -diff --git a/src/shell-perf-helper.c b/src/shell-perf-helper.c -index 55bdbef02..d3280de96 100644 ---- a/src/shell-perf-helper.c -+++ b/src/shell-perf-helper.c -@@ -12,7 +12,6 @@ - #include - - #include --#include - - #define BUS_NAME "org.gnome.Shell.PerfHelper" - -@@ -60,12 +59,6 @@ static GOptionEntry opt_entries[] = - { NULL } - }; - --static Display *xdisplay; --static Window xroot; --static Atom atom_wm_state; --static Atom atom__net_wm_name; --static Atom atom_utf8_string; -- - static guint timeout_id; - static GList *our_windows; - static GList *wait_windows_invocations; -@@ -351,8 +344,6 @@ on_name_lost (GDBusConnection *connection, - int - main (int argc, char **argv) - { -- GdkDisplay *display; -- GdkScreen *screen; - GOptionContext *context; - GError *error = NULL; - -@@ -368,15 +359,6 @@ main (int argc, char **argv) - return 1; - } - -- display = gdk_display_get_default (); -- screen = gdk_screen_get_default (); -- -- xdisplay = gdk_x11_display_get_xdisplay (display); -- xroot = gdk_x11_window_get_xid (gdk_screen_get_root_window (screen)); -- atom_wm_state = gdk_x11_get_xatom_by_name_for_display (display, "WM_STATE"); -- atom__net_wm_name = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"); -- atom_utf8_string = gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"); -- - g_bus_own_name (G_BUS_TYPE_SESSION, - BUS_NAME, - G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | --- -2.26.2 - - -From d8b4d72b89340dab46bdcb92ee54bde18dbb9ba9 Mon Sep 17 00:00:00 2001 -From: Olivier Fourdan -Date: Fri, 24 Jan 2020 10:59:31 +0100 -Subject: [PATCH 3/4] perf-tool: Spawn perf-tool-helper from gnome-shell - -On Wayland, the display server is the Wayland compositor, i.e. -`gnome-shell` itself. - -As a result, we cannot spawn `gnome-shell-perf-helper` before -`gnome-shell` is started, as `gnome-shell-perf-helper` needs to connect -to the display server. - -So, instead of spawning `gnome-shell-perf-helper` from the perf tool, -start it from `gnome-shell` itself. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/941 ---- - js/ui/scripting.js | 51 ++++++++++++++++++++++------------ - src/gnome-shell-perf-tool.in | 53 ------------------------------------ - 2 files changed, 34 insertions(+), 70 deletions(-) - -diff --git a/js/ui/scripting.js b/js/ui/scripting.js -index d227b9ef4..eef8f3887 100644 ---- a/js/ui/scripting.js -+++ b/js/ui/scripting.js -@@ -3,8 +3,10 @@ - const { Gio, GLib, Meta, Shell } = imports.gi; - const Mainloop = imports.mainloop; - -+const Config = imports.misc.config; - const Main = imports.ui.main; - const Params = imports.misc.params; -+const Util = imports.misc.util; - - const { loadInterfaceXML } = imports.misc.fileUtils; - -@@ -73,6 +75,12 @@ function _getPerfHelper() { - return _perfHelper; - } - -+function _spawnPerfHelper() { -+ let path = Config.LIBEXECDIR; -+ let command = `${path}/gnome-shell-perf-helper`; -+ Util.trySpawnCommandLine(command); -+} -+ - function _callRemote(obj, method, ...args) { - return new Promise((resolve, reject) => { - args.push((result, excp) => { -@@ -270,6 +278,25 @@ function _collect(scriptModule, outputFile) { - } - } - -+async function _runPerfScript(scriptModule, outputFile) { -+ for (let step of scriptModule.run()) { -+ try { -+ await step; // eslint-disable-line no-await-in-loop -+ } catch (err) { -+ log(`Script failed: ${err}\n${err.stack}`); -+ Meta.exit(Meta.ExitCode.ERROR); -+ } -+ } -+ -+ try { -+ _collect(scriptModule, outputFile); -+ } catch (err) { -+ log(`Script failed: ${err}\n${err.stack}`); -+ Meta.exit(Meta.ExitCode.ERROR); -+ } -+ Meta.exit(Meta.ExitCode.SUCCESS); -+} -+ - /** - * runPerfScript - * @scriptModule: module object with run and finish functions -@@ -310,23 +337,13 @@ function _collect(scriptModule, outputFile) { - * After running the script and collecting statistics from the - * event log, GNOME Shell will exit. - **/ --async function runPerfScript(scriptModule, outputFile) { -+function runPerfScript(scriptModule, outputFile) { - Shell.PerfLog.get_default().set_enabled(true); -+ _spawnPerfHelper(); - -- for (let step of scriptModule.run()) { -- try { -- await step; -- } catch (err) { -- log(`Script failed: ${err}\n${err.stack}`); -- Meta.exit(Meta.ExitCode.ERROR); -- } -- } -- -- try { -- _collect(scriptModule, outputFile); -- } catch (err) { -- log(`Script failed: ${err}\n${err.stack}`); -- Meta.exit(Meta.ExitCode.ERROR); -- } -- Meta.exit(Meta.ExitCode.SUCCESS); -+ Gio.bus_watch_name(Gio.BusType.SESSION, -+ 'org.gnome.Shell.PerfHelper', -+ Gio.BusNameWatcherFlags.NONE, -+ () => _runPerfScript(scriptModule, outputFile), -+ null); - } -diff --git a/src/gnome-shell-perf-tool.in b/src/gnome-shell-perf-tool.in -index f4b48f730..050c66b30 100755 ---- a/src/gnome-shell-perf-tool.in -+++ b/src/gnome-shell-perf-tool.in -@@ -24,52 +24,6 @@ def show_version(option, opt_str, value, parser): - print("GNOME Shell Performance Test @VERSION@") - sys.exit() - --def wait_for_dbus_name(wait_name): -- loop = GLib.MainLoop() -- -- def on_name_appeared(connection, name, new_owner, *args): -- if not (name == wait_name and new_owner != ''): -- return -- loop.quit() -- return -- -- watch_id = Gio.bus_watch_name(Gio.BusType.SESSION, -- wait_name, -- Gio.BusNameWatcherFlags.NONE, -- on_name_appeared, -- None) -- -- def on_timeout(): -- print("\nFailed to start %s: timed out" % (wait_name,)) -- sys.exit(1) -- GLib.timeout_add_seconds(7, on_timeout) -- -- loop.run() -- Gio.bus_unwatch_name(watch_id) -- --PERF_HELPER_NAME = "org.gnome.Shell.PerfHelper" --PERF_HELPER_IFACE = "org.gnome.Shell.PerfHelper" --PERF_HELPER_PATH = "/org/gnome/Shell/PerfHelper" -- --def start_perf_helper(): -- self_dir = os.path.dirname(os.path.abspath(sys.argv[0])) -- perf_helper_path = "@libexecdir@/gnome-shell-perf-helper" -- -- subprocess.Popen([perf_helper_path]) -- wait_for_dbus_name (PERF_HELPER_NAME) -- --def stop_perf_helper(): -- bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) -- -- proxy = Gio.DBusProxy.new_sync(bus, -- Gio.DBusProxyFlags.NONE, -- None, -- PERF_HELPER_NAME, -- PERF_HELPER_PATH, -- PERF_HELPER_IFACE, -- None) -- proxy.Exit() -- - def start_shell(perf_output=None): - # Set up environment - env = dict(os.environ) -@@ -204,8 +158,6 @@ def run_performance_test(): - logs = [] - metric_summaries = {} - -- start_perf_helper() -- - for i in range(0, iters): - # We create an empty temporary file that the shell will overwrite - # with the contents. -@@ -217,14 +169,12 @@ def run_performance_test(): - try: - normal_exit = run_shell(perf_output=output_file) - except: -- stop_perf_helper() - raise - finally: - if not normal_exit: - os.remove(output_file) - - if not normal_exit: -- stop_perf_helper() - return False - - try: -@@ -232,7 +182,6 @@ def run_performance_test(): - output = json.load(f) - f.close() - except: -- stop_perf_helper() - raise - finally: - os.remove(output_file) -@@ -260,8 +209,6 @@ def run_performance_test(): - - logs.append(output['log']) - -- stop_perf_helper() -- - if options.perf_output or options.perf_upload: - # Write a complete report, formatted as JSON. The Javascript/C code that - # generates the individual reports we are summarizing here is very careful --- -2.26.2 - - -From 8090db0f29dc72e602be341d43b3113373404b21 Mon Sep 17 00:00:00 2001 -From: Olivier Fourdan -Date: Tue, 21 Jan 2020 11:05:58 +0100 -Subject: [PATCH 4/4] perf-tool: Allow to run as a Wayland compositor - -`gnome-shell-perf-tool` is initially designed to run on X11, using the -`--replace` option which does not work when gnome-shell is a Wayland -compositor. - -A solution would be to run `gnome-shell-perf-tool` in place of just -`gnome-shell` to run the entire perf session under Wayland, but the -script `gnome-shell-perf-tool` does not spawn `gnome-shell` as a Wayladn -compositor, so that fails as well. - -Add a `--wayland` option to `gnome-shell-perf-tool` so that it can -optionally spawn gnome-shell as a Wayland compositor so the whole perf -tool can be starred from a console with: - -``` - $ dbus-run-session -- gnome-shell-perf-tool --wayland -``` - -Alternatively, for testing purposes, it can also be started nested with: - -``` - $ dbus-run-session -- gnome-shell-perf-tool --nested -``` - -Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/2139 -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/941 ---- - src/gnome-shell-perf-tool.in | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/src/gnome-shell-perf-tool.in b/src/gnome-shell-perf-tool.in -index 050c66b30..04072c4cd 100755 ---- a/src/gnome-shell-perf-tool.in -+++ b/src/gnome-shell-perf-tool.in -@@ -45,6 +45,13 @@ def start_shell(perf_output=None): - if options.replace: - args.append('--replace') - -+ if options.wayland or options.nested: -+ args.append('--wayland') -+ if options.nested: -+ args.append('--nested') -+ else: -+ args.append('--display-server') -+ - return subprocess.Popen(args, env=env) - - def run_shell(perf_output=None): -@@ -284,6 +291,10 @@ parser.add_option("", "--version", action="callback", callback=show_version, - - parser.add_option("-r", "--replace", action="store_true", - help="Replace the running window manager") -+parser.add_option("-w", "--wayland", action="store_true", -+ help="Run as a Wayland compositor") -+parser.add_option("-n", "--nested", action="store_true", -+ help="Run as a Wayland nested compositor") - - options, args = parser.parse_args() - --- -2.26.2 - diff --git a/SOURCES/root-warning.patch b/SOURCES/root-warning.patch deleted file mode 100644 index 35b2c44..0000000 --- a/SOURCES/root-warning.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 45ddeeaa317fb0ffd045600d9e4b95143c9ca8b8 Mon Sep 17 00:00:00 2001 -From: Matthias Clasen -Date: Sat, 8 Jun 2013 13:32:35 -0400 -Subject: [PATCH 1/2] main: Show a warning when running as root - -gnome-session used to show a dialog in this case, but a -notification is more natural nowadays. Doing it in gnome-shell -avoids complicated synchronization between gnome-session and -gnome-shell. - -https://bugzilla.gnome.org/show_bug.cgi?id=701212 ---- - js/ui/main.js | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/js/ui/main.js b/js/ui/main.js -index 8d1755cf1..abf8a8765 100644 ---- a/js/ui/main.js -+++ b/js/ui/main.js -@@ -237,6 +237,12 @@ function _initializeUI() { - ['MESSAGE_ID=' + GNOMESHELL_STARTED_MESSAGE_ID]); - } - -+ let credentials = new Gio.Credentials(); -+ if (credentials.get_unix_user() === 0) { -+ notify(_('Logged in as a privileged user'), -+ _('Running a session as a privileged user should be avoided for security reasons. If possible, you should log in as a normal user.')); -+ } -+ - let perfModuleName = GLib.getenv("SHELL_PERF_MODULE"); - if (perfModuleName) { - let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT"); --- -2.23.0 - - -From 8e82907909b6a2e5af5da3f93b087df4b7eb48b5 Mon Sep 17 00:00:00 2001 -From: Matthias Clasen -Date: Sat, 8 Jun 2013 13:33:58 -0400 -Subject: [PATCH 2/2] main: Show a warning when gdm is missing - -If we are not running under gdm, some functionaliy (such as -the lock screen) does not work, and we should inform the -user about this. - -https://bugzilla.gnome.org/show_bug.cgi?id=701212 ---- - js/ui/main.js | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/js/ui/main.js b/js/ui/main.js -index abf8a8765..be49c750e 100644 ---- a/js/ui/main.js -+++ b/js/ui/main.js -@@ -243,6 +243,13 @@ function _initializeUI() { - _('Running a session as a privileged user should be avoided for security reasons. If possible, you should log in as a normal user.')); - } - -+ if (sessionMode.currentMode !== 'gdm' && -+ sessionMode.currentMode !== 'initial-setup' && -+ screenShield === null) { -+ notify(_('Screen Lock disabled'), -+ _('Screen Locking requires the GNOME display manager.')); -+ } -+ - let perfModuleName = GLib.getenv("SHELL_PERF_MODULE"); - if (perfModuleName) { - let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT"); --- -2.23.0 - diff --git a/SOURCES/wake-up-on-deactivate.patch b/SOURCES/wake-up-on-deactivate.patch deleted file mode 100644 index b20cbbd..0000000 --- a/SOURCES/wake-up-on-deactivate.patch +++ /dev/null @@ -1,79 +0,0 @@ -From d6ead50fe230df58ddab822966d69760b00ec920 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 1 Apr 2020 14:48:10 +0200 -Subject: [PATCH 1/2] screenShield: Switch lightboxes off before unlock - transition - -There is no point in animating a transition with fullscreen black -rectangles stacked on top, so switch them off before rather than -after the transition. - -https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1158 ---- - js/ui/screenShield.js | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js -index cd38f11fc8..282f29fa30 100644 ---- a/js/ui/screenShield.js -+++ b/js/ui/screenShield.js -@@ -1221,6 +1221,9 @@ var ScreenShield = class { - this._isModal = false; - } - -+ this._longLightbox.hide(); -+ this._shortLightbox.hide(); -+ - Tweener.addTween(this._lockDialogGroup, { - scale_x: 0, - scale_y: 0, -@@ -1237,8 +1240,6 @@ var ScreenShield = class { - this._dialog = null; - } - -- this._longLightbox.hide(); -- this._shortLightbox.hide(); - this.actor.hide(); - - if (this._becameActiveId != 0) { --- -2.28.0 - - -From 39ac7cad68d8c00d98c900b35add637b01eddbbf Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Tue, 31 Mar 2020 21:07:59 +0200 -Subject: [PATCH 2/2] screenShield: Wake up on deactivate() - -Usually the screen is woken up before the shield is deactivated, but -it is also possible to unlock the session programmatically via the -org.gnome.ScreenSaver D-Bus API. - -The intention is very likely not to unlock a turned off screen in -that case. Nor does it seem like a good idea to change the lock -state without any indication. - -Waking up the screen is more likely to meet expectations and is -more reasonable too, so do that. - -https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1158 ---- - js/ui/screenShield.js | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js -index 282f29fa30..2d0a429bee 100644 ---- a/js/ui/screenShield.js -+++ b/js/ui/screenShield.js -@@ -1200,6 +1200,8 @@ var ScreenShield = class { - if (Main.sessionMode.currentMode == 'unlock-dialog') - Main.sessionMode.popMode('unlock-dialog'); - -+ this.emit('wake-up-screen'); -+ - if (this._isGreeter) { - // We don't want to "deactivate" any more than - // this. In particular, we don't want to drop --- -2.28.0 - diff --git a/SOURCES/warn-less.patch b/SOURCES/warn-less.patch deleted file mode 100644 index f5dd837..0000000 --- a/SOURCES/warn-less.patch +++ /dev/null @@ -1,279 +0,0 @@ -From 37bbb9175bbd061d4ae14e86c35e4211602dbeaa Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 23 Mar 2020 17:57:38 +0100 -Subject: [PATCH 1/4] shell/util: Add touch_file_async() helper - -Add a small helper method to asynchronously "touch" a file and return -whether the file was created or not. - -As g_file_make_directory_with_parents() doesn't have an async variant, -we need a C helper to make the entire operation non-blocking. - -https://gitlab.gnome.org/GNOME/gnome-shell/issues/2432 ---- - src/shell-util.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ - src/shell-util.h | 7 ++++++ - 2 files changed, 69 insertions(+) - -diff --git a/src/shell-util.c b/src/shell-util.c -index fa3fc08c8..eec67f3d7 100644 ---- a/src/shell-util.c -+++ b/src/shell-util.c -@@ -323,6 +323,68 @@ shell_get_file_contents_utf8_sync (const char *path, - return contents; - } - -+static void -+touch_file (GTask *task, -+ gpointer object, -+ gpointer task_data, -+ GCancellable *cancellable) -+{ -+ GFile *file = object; -+ g_autoptr (GFile) parent = NULL; -+ g_autoptr (GFileOutputStream) stream = NULL; -+ GError *error = NULL; -+ -+ parent = g_file_get_parent (file); -+ g_file_make_directory_with_parents (parent, cancellable, &error); -+ -+ if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) -+ { -+ g_task_return_error (task, error); -+ return; -+ } -+ g_clear_error (&error); -+ -+ stream = g_file_create (file, G_FILE_CREATE_NONE, cancellable, &error); -+ -+ if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) -+ { -+ g_task_return_error (task, error); -+ return; -+ } -+ g_clear_error (&error); -+ -+ if (stream) -+ g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, NULL); -+ -+ g_task_return_boolean (task, stream != NULL); -+} -+ -+void -+shell_util_touch_file_async (GFile *file, -+ GAsyncReadyCallback callback, -+ gpointer user_data) -+{ -+ g_autoptr (GTask) task = NULL; -+ -+ g_return_if_fail (G_IS_FILE (file)); -+ -+ task = g_task_new (file, NULL, callback, user_data); -+ g_task_set_source_tag (task, shell_util_touch_file_async); -+ -+ g_task_run_in_thread (task, touch_file); -+} -+ -+gboolean -+shell_util_touch_file_finish (GFile *file, -+ GAsyncResult *res, -+ GError **error) -+{ -+ g_return_val_if_fail (G_IS_FILE (file), FALSE); -+ g_return_val_if_fail (G_IS_TASK (res), FALSE); -+ -+ return g_task_propagate_boolean (G_TASK (res), error); -+} -+ - /** - * shell_util_wifexited: - * @status: the status returned by wait() or waitpid() -diff --git a/src/shell-util.h b/src/shell-util.h -index 02b8404e9..bedf516ba 100644 ---- a/src/shell-util.h -+++ b/src/shell-util.h -@@ -32,6 +32,13 @@ gboolean shell_write_string_to_stream (GOutputStream *stream, - char *shell_get_file_contents_utf8_sync (const char *path, - GError **error); - -+void shell_util_touch_file_async (GFile *file, -+ GAsyncReadyCallback callback, -+ gpointer user_data); -+gboolean shell_util_touch_file_finish (GFile *file, -+ GAsyncResult *res, -+ GError **error); -+ - gboolean shell_util_wifexited (int status, - int *exit); - --- -2.31.1 - - -From 1f75494bea1ef7017d50d77cf5c7ad6b9668d4f5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Mon, 23 Mar 2020 18:00:27 +0100 -Subject: [PATCH 2/4] environment: Hook up touch_file to GFile prototype - -We don't usually extend introspected types with our own API, but in -this case it's too tempting to make the helper functions usable with -Gio._promisify() ... - -https://gitlab.gnome.org/GNOME/gnome-shell/issues/2432 ---- - js/ui/environment.js | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/js/ui/environment.js b/js/ui/environment.js -index e22ec7402..9c125d3eb 100644 ---- a/js/ui/environment.js -+++ b/js/ui/environment.js -@@ -9,7 +9,7 @@ imports.gi.versions.Gtk = '3.0'; - imports.gi.versions.TelepathyGLib = '0.12'; - imports.gi.versions.TelepathyLogger = '0.2'; - --const { Clutter, GLib, Shell, St } = imports.gi; -+const { Clutter, Gio, GLib, Shell, St } = imports.gi; - const Gettext = imports.gettext; - - // We can't import shell JS modules yet, because they may have -@@ -97,6 +97,13 @@ function init() { - return St.describe_actor(this); - }; - -+ Gio._LocalFilePrototype.touch_async = function (callback) { -+ Shell.util_touch_file_async(this, callback); -+ }; -+ Gio._LocalFilePrototype.touch_finish = function (result) { -+ return Shell.util_touch_file_finish(this, result); -+ }; -+ - let origToString = Object.prototype.toString; - Object.prototype.toString = function() { - let base = origToString.call(this); --- -2.31.1 - - -From 4bef23c7176a43f4dcf146e70bbb8aaa701b8cd2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Fri, 20 Mar 2020 12:42:04 +0100 -Subject: [PATCH 3/4] main: Do not warn about missing GDM on each login - -We now warn on startup if screen locking isn't available, however for -users who choose not to use GDM or logind, repeating the warning on -each login is more annoying than helpful. - -Instead, limit the warning to the first login on which the screen lock -became unavailable. That way the notification will still serve the -intended purpose of informing the user, but without being perceived -as nagging. - -https://gitlab.gnome.org/GNOME/gnome-shell/issues/2432 ---- - js/ui/main.js | 36 +++++++++++++++++++++++++++++++----- - 1 file changed, 31 insertions(+), 5 deletions(-) - -diff --git a/js/ui/main.js b/js/ui/main.js -index 1203b3c39..a3fad158c 100644 ---- a/js/ui/main.js -+++ b/js/ui/main.js -@@ -81,6 +81,9 @@ let _a11ySettings = null; - let _themeResource = null; - let _oskResource = null; - -+Gio._promisify(Gio._LocalFilePrototype, 'delete_async', 'delete_finish'); -+Gio._promisify(Gio._LocalFilePrototype, 'touch_async', 'touch_finish'); -+ - function _sessionUpdated() { - if (sessionMode.isPrimary) - _loadDefaultStylesheet(); -@@ -242,11 +245,8 @@ function _initializeUI() { - } - - if (sessionMode.currentMode !== 'gdm' && -- sessionMode.currentMode !== 'initial-setup' && -- screenShield === null) { -- notify(_('Screen Lock disabled'), -- _('Screen Locking requires the GNOME display manager.')); -- } -+ sessionMode.currentMode !== 'initial-setup') -+ _handleLockScreenWarning(); - - let perfModuleName = GLib.getenv("SHELL_PERF_MODULE"); - if (perfModuleName) { -@@ -257,6 +257,32 @@ function _initializeUI() { - }); - } - -+async function _handleLockScreenWarning() { -+ const path = '%s/lock-warning-shown'.format(global.userdatadir); -+ const file = Gio.File.new_for_path(path); -+ -+ const hasLockScreen = screenShield !== null; -+ if (hasLockScreen) { -+ try { -+ await file.delete_async(0, null); -+ } catch (e) { -+ if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) -+ logError(e); -+ } -+ } else { -+ try { -+ if (!await file.touch_async()) -+ return; -+ } catch (e) { -+ logError(e); -+ } -+ -+ notify( -+ _('Screen Lock disabled'), -+ _('Screen Locking requires the GNOME display manager.')); -+ } -+} -+ - function _getStylesheet(name) { - let stylesheet; - --- -2.31.1 - - -From c3f34e786826d0ed1af4150190159fed50d9fb87 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Thu, 22 Oct 2020 20:11:14 +0200 -Subject: [PATCH 4/4] messageTray: Default to generic policy - -How and if notifications are shown is controlled by NotificationPolicy -objects. But ever since 098bd45, only notification daemon sources or -notifications associated with an app are hooked up to GSettings. - -The hardcoded default policy for built-in notifications (including -those provided by extensions) arguably made sense back then, but -now that the main setting has been rebranded as "Do Not Disturb" -and is exposed prominently in the calendar drop-down, following -GSettings is a better default. - -https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3291 - -Part-of: ---- - js/ui/messageTray.js | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js -index 8f8130451..f6bdae8e4 100644 ---- a/js/ui/messageTray.js -+++ b/js/ui/messageTray.js -@@ -731,7 +731,7 @@ var Source = class Source { - } - - _createPolicy() { -- return new NotificationPolicy(); -+ return new NotificationGenericPolicy(); - } - - get narrowestPrivacyScope() { --- -2.31.1 - diff --git a/SOURCES/disable-unlock-entry-until-question.patch b/disable-unlock-entry-until-question.patch similarity index 50% rename from SOURCES/disable-unlock-entry-until-question.patch rename to disable-unlock-entry-until-question.patch index d238ae8..28f1a9e 100644 --- a/SOURCES/disable-unlock-entry-until-question.patch +++ b/disable-unlock-entry-until-question.patch @@ -1,4 +1,4 @@ -From a57132816ac7bd93d6875fee0a6c5b273177ac8d Mon Sep 17 00:00:00 2001 +From 8a4efef39a0f48371c632d449688f29d06b9eed7 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 30 Sep 2015 12:51:24 -0400 Subject: [PATCH 1/3] authPrompt: don't fade out auth messages if user types @@ -12,50 +12,59 @@ front, before a password is asked. 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index d7f53a92e..d421a8856 100644 +index 8a46559d90..9309f60886 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js -@@ -169,7 +169,7 @@ var AuthPrompt = class { - this._updateNextButtonSensitivity(this._entry.text.length > 0); +@@ -211,7 +211,7 @@ export const AuthPrompt = GObject.registerClass({ - this._entry.clutter_text.connect('text-changed', () => { -- if (!this._userVerifier.hasPendingMessages) -+ if (!this._userVerifier.hasPendingMessages && this._queryingService && !this._preemptiveAnswer) - this._fadeOutMessage(); + [this._textEntry, this._passwordEntry].forEach(entry => { + entry.clutter_text.connect('text-changed', () => { +- if (!this._userVerifier.hasPendingMessages) ++ if (!this._userVerifier.hasPendingMessages && this._queryingService && !this._preemptiveAnswer) + this._fadeOutMessage(); + }); - this._updateNextButtonSensitivity(this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING); -- -2.21.0 +2.45.2 -From 50af703ea95f2b73733c38e66c9c251663a51744 Mon Sep 17 00:00:00 2001 +From 007bbb694d4f30175caecbc9ada91515634bfd0b Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 30 Sep 2015 14:36:33 -0400 Subject: [PATCH 2/3] authPrompt: don't spin unless answering question --- - js/gdm/authPrompt.js | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) + js/gdm/authPrompt.js | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index d421a8856..62c5bd078 100644 +index 9309f60886..3e72668967 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js -@@ -60,8 +60,8 @@ var AuthPrompt = class { +@@ -275,13 +275,14 @@ export const AuthPrompt = GObject.registerClass({ + this.verificationStatus = AuthPromptStatus.VERIFICATION_IN_PROGRESS; + this.updateSensitivity(false); - this.connect('next', () => { - this.updateSensitivity(false); -- this.startSpinning(); - if (this._queryingService) { -+ this.startSpinning(); - this._userVerifier.answerQuery(this._queryingService, this._entry.text); - } else { - this._preemptiveAnswer = this._entry.text; +- if (shouldSpin) +- this.startSpinning(); ++ if (this._queryingService) { ++ if (shouldSpin) ++ this.startSpinning(); + +- if (this._queryingService) + this._userVerifier.answerQuery(this._queryingService, this._entry.text); +- else ++ } else { + this._preemptiveAnswer = this._entry.text; ++ } + + this.emit('next'); + } -- -2.21.0 +2.45.2 -From b89be880936ad9dd145eb43890ac72d03c37785d Mon Sep 17 00:00:00 2001 +From 92f66a5ff91e47d46a48d7ee51c0808f7ce1eaf9 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 5 Oct 2015 15:26:18 -0400 Subject: [PATCH 3/3] authPrompt: stop accepting preemptive answer if user @@ -69,43 +78,23 @@ Typing ahead the password is just a convenience for users who don't want to manually lift the shift before typing their passwords, after all. --- - js/gdm/authPrompt.js | 37 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 37 insertions(+) + js/gdm/authPrompt.js | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 62c5bd078..27eb31a89 100644 +index 3e72668967..254b4dbb88 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js -@@ -6,6 +6,7 @@ const Signals = imports.signals; - const Animation = imports.ui.animation; - const Batch = imports.gdm.batch; - const GdmUtil = imports.gdm.util; -+const Meta = imports.gi.Meta; - const Params = imports.misc.params; - const ShellEntry = imports.ui.shellEntry; - const Tweener = imports.ui.tweener; -@@ -41,6 +42,8 @@ var AuthPrompt = class { - this._gdmClient = gdmClient; - this._mode = mode; +@@ -70,6 +70,8 @@ export const AuthPrompt = GObject.registerClass({ + this._defaultButtonWellActor = null; + this._cancelledRetries = 0; -+ this._idleMonitor = Meta.IdleMonitor.get_core(); ++ this._idleMonitor = global.backend.get_core_idle_monitor(); + let reauthenticationOnly; - if (this._mode == AuthPromptMode.UNLOCK_ONLY) + if (this._mode === AuthPromptMode.UNLOCK_ONLY) reauthenticationOnly = true; -@@ -65,6 +68,11 @@ var AuthPrompt = class { - this._userVerifier.answerQuery(this._queryingService, this._entry.text); - } else { - this._preemptiveAnswer = this._entry.text; -+ -+ if (this._preemptiveAnswerWatchId) { -+ this._idleMonitor.remove_watch(this._preemptiveAnswerWatchId); -+ this._preemptiveAnswerWatchId = 0; -+ } - } - }); - -@@ -128,6 +136,11 @@ var AuthPrompt = class { +@@ -127,8 +129,14 @@ export const AuthPrompt = GObject.registerClass({ } _onDestroy() { @@ -113,11 +102,26 @@ index 62c5bd078..27eb31a89 100644 + this._idleMonitor.remove_watch(this._preemptiveAnswerWatchId); + this._preemptiveAnswerWatchId = 0; + } ++ + this._inactiveEntry.destroy(); + this._inactiveEntry = null; + this._userVerifier.destroy(); this._userVerifier = null; } -@@ -342,6 +355,11 @@ var AuthPrompt = class { +@@ -282,6 +290,11 @@ export const AuthPrompt = GObject.registerClass({ + this._userVerifier.answerQuery(this._queryingService, this._entry.text); + } else { + this._preemptiveAnswer = this._entry.text; ++ ++ if (this._preemptiveAnswerWatchId) { ++ this._idleMonitor.remove_watch(this._preemptiveAnswerWatchId); ++ this._preemptiveAnswerWatchId = 0; ++ } + } + + this.emit('next'); +@@ -493,6 +506,11 @@ export const AuthPrompt = GObject.registerClass({ } setQuestion(question) { @@ -126,11 +130,11 @@ index 62c5bd078..27eb31a89 100644 + this._preemptiveAnswerWatchId = 0; + } + - this._label.set_text(question); + this._entry.hint_text = question; - this._label.show(); -@@ -427,6 +445,19 @@ var AuthPrompt = class { - } + this._authList.hide(); +@@ -614,6 +632,19 @@ export const AuthPrompt = GObject.registerClass({ + this._updateEntry(false); } + _onUserStoppedTypePreemptiveAnswer() { @@ -149,19 +153,18 @@ index 62c5bd078..27eb31a89 100644 reset() { let oldStatus = this.verificationStatus; this.verificationStatus = AuthPromptStatus.NOT_VERIFYING; -@@ -434,6 +465,12 @@ var AuthPrompt = class { - this.nextButton.label = _("Next"); +@@ -621,6 +652,11 @@ export const AuthPrompt = GObject.registerClass({ + this.cancelButton.can_focus = this._hasCancelButton; this._preemptiveAnswer = null; -+ if (this._preemptiveAnswerWatchId) { ++ if (this._preemptiveAnswerWatchId) + this._idleMonitor.remove_watch(this._preemptiveAnswerWatchId); -+ } -+ this._preemptiveAnswerWatchId = this._idleMonitor.add_idle_watch (500, -+ this._onUserStoppedTypePreemptiveAnswer.bind(this)); ++ this._preemptiveAnswerWatchId = this._idleMonitor.add_idle_watch(500, ++ this._onUserStoppedTypePreemptiveAnswer.bind(this)); + if (this._userVerifier) this._userVerifier.cancel(); -- -2.21.0 +2.45.2 diff --git a/SOURCES/enforce-smartcard-at-unlock.patch b/enforce-smartcard-at-unlock.patch similarity index 54% rename from SOURCES/enforce-smartcard-at-unlock.patch rename to enforce-smartcard-at-unlock.patch index 60274e5..289bf3c 100644 --- a/SOURCES/enforce-smartcard-at-unlock.patch +++ b/enforce-smartcard-at-unlock.patch @@ -1,4 +1,4 @@ -From 8ce91c85fe052d1a9f4fed0743bceae7d9654aa0 Mon Sep 17 00:00:00 2001 +From eaa7217db15a28e88ce0b5a84827c306148561ca Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 28 Sep 2015 10:57:02 -0400 Subject: [PATCH 1/3] smartcardManager: add way to detect if user logged using @@ -16,27 +16,26 @@ This commit adds the necessary api to detect that case. 1 file changed, 7 insertions(+) diff --git a/js/misc/smartcardManager.js b/js/misc/smartcardManager.js -index fda782d1e..bb43c96e7 100644 +index 32573cd384..6c48c80a19 100644 --- a/js/misc/smartcardManager.js +++ b/js/misc/smartcardManager.js -@@ -112,5 +112,12 @@ var SmartcardManager = class { +@@ -118,4 +118,11 @@ class SmartcardManager extends Signals.EventEmitter { + return true; } - ++ + loggedInWithToken() { + if (this._loginToken) + return true; + + return false; + } -+ - }; - Signals.addSignalMethods(SmartcardManager.prototype); + } -- -2.21.0 +2.45.2 -From 6decf5560d309579760e10048533d3bd9bc56c3c Mon Sep 17 00:00:00 2001 +From d7ef26d7b9d352232c9e0a24a04bcfcf6eee7d9a Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 28 Sep 2015 19:56:53 -0400 Subject: [PATCH 2/3] gdm: only unlock with smartcard, if smartcard used for @@ -45,46 +44,38 @@ Subject: [PATCH 2/3] gdm: only unlock with smartcard, if smartcard used for If a smartcard is used for login, we need to make sure the smartcard gets used for unlock, too. --- - js/gdm/util.js | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) + js/gdm/util.js | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/gdm/util.js b/js/gdm/util.js -index 2e9935250..2b80e1dd9 100644 +index c9c040beb7..c0d8852880 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js -@@ -126,7 +126,6 @@ var ShellUserVerifier = class { - this._settings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA }); - this._settings.connect('changed', - this._updateDefaultService.bind(this)); -- this._updateDefaultService(); - - this._fprintManager = Fprint.FprintManager(); - this._smartcardManager = SmartcardManager.getSmartcardManager(); -@@ -138,6 +137,8 @@ var ShellUserVerifier = class { +@@ -465,6 +465,8 @@ export class ShellUserVerifier extends Signals.EventEmitter { this.smartcardDetected = false; this._checkForSmartcard(); + this._updateDefaultService(); + - this._smartcardInsertedId = this._smartcardManager.connect('smartcard-inserted', - this._checkForSmartcard.bind(this)); - this._smartcardRemovedId = this._smartcardManager.connect('smartcard-removed', -@@ -407,7 +408,9 @@ var ShellUserVerifier = class { + this._smartcardManager.connectObject( + 'smartcard-inserted', () => this._checkForSmartcard(), + 'smartcard-removed', () => this._checkForSmartcard(), this); +@@ -643,7 +645,9 @@ export class ShellUserVerifier extends Signals.EventEmitter { } - _updateDefaultService() { + _getDetectedDefaultService() { - if (this._settings.get_boolean(PASSWORD_AUTHENTICATION_KEY)) -+ if (this._smartcardManager.loggedInWithToken()) -+ this._defaultService = SMARTCARD_SERVICE_NAME; ++ if (this._smartcardManager?.loggedInWithToken()) ++ return SMARTCARD_SERVICE_NAME; + else if (this._settings.get_boolean(PASSWORD_AUTHENTICATION_KEY)) - this._defaultService = PASSWORD_SERVICE_NAME; - else if (this._settings.get_boolean(SMARTCARD_AUTHENTICATION_KEY)) - this._defaultService = SMARTCARD_SERVICE_NAME; + return PASSWORD_SERVICE_NAME; + else if (this._smartcardManager) + return SMARTCARD_SERVICE_NAME; -- -2.21.0 +2.45.2 -From dd844c98c3450dd1b21bcc580b51162c1b00ed2a Mon Sep 17 00:00:00 2001 +From 9bff98c2757e4591035e408aa9cee703cec74bdf Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 28 Sep 2015 19:57:36 -0400 Subject: [PATCH 3/3] gdm: update default service when smartcard inserted @@ -97,11 +88,11 @@ after we get a smartcard insertion event. 1 file changed, 2 insertions(+) diff --git a/js/gdm/util.js b/js/gdm/util.js -index 2b80e1dd9..6e940d2ab 100644 +index c0d8852880..430af4d8ef 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js -@@ -327,6 +327,8 @@ var ShellUserVerifier = class { - else if (this._preemptingService == SMARTCARD_SERVICE_NAME) +@@ -490,6 +490,8 @@ export class ShellUserVerifier extends Signals.EventEmitter { + else if (this._preemptingService === SMARTCARD_SERVICE_NAME) this._preemptingService = null; + this._updateDefaultService(); @@ -110,5 +101,5 @@ index 2b80e1dd9..6e940d2ab 100644 } } -- -2.21.0 +2.45.2 diff --git a/fix-some-js-warnings.patch b/fix-some-js-warnings.patch new file mode 100644 index 0000000..9c313a2 --- /dev/null +++ b/fix-some-js-warnings.patch @@ -0,0 +1,62 @@ +From 04bf0729ed6ae75736e297a10603bcb0a564cb28 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 9 Jun 2020 19:42:21 +0200 +Subject: [PATCH 1/2] popupMenu: Guard against non-menu-item children + +This avoid a harmless but annoying warning. +--- + js/ui/popupMenu.js | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js +index b6ad545087..cbbcfea1ff 100644 +--- a/js/ui/popupMenu.js ++++ b/js/ui/popupMenu.js +@@ -951,7 +951,8 @@ export class PopupMenuBase extends Signals.EventEmitter { + } + + _getMenuItems() { +- return this.box.get_children().map(a => a._delegate).filter(item => { ++ const children = this.box.get_children().filter(a => a._delegate !== undefined); ++ return children.map(a => a._delegate).filter(item => { + return item instanceof PopupBaseMenuItem || item instanceof PopupMenuSection; + }); + } +-- +2.45.2 + + +From cffe984d9b85494fcf34500e78875b66c1cec534 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 9 Jun 2020 19:48:06 +0200 +Subject: [PATCH 2/2] st/shadow: Check pipeline when painting + +We shouldn't simply assume that st_shadow_helper_update() has been +called before paint() or that the pipeline was created successfully. +--- + src/st/st-shadow.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/src/st/st-shadow.c b/src/st/st-shadow.c +index a406b61532..574445aeac 100644 +--- a/src/st/st-shadow.c ++++ b/src/st/st-shadow.c +@@ -294,9 +294,10 @@ st_shadow_helper_paint (StShadowHelper *helper, + ClutterActorBox *actor_box, + uint8_t paint_opacity) + { +- _st_paint_shadow_with_opacity (helper->shadow, +- node, +- helper->pipeline, +- actor_box, +- paint_opacity); ++ if (helper->pipeline != NULL) ++ _st_paint_shadow_with_opacity (helper->shadow, ++ node, ++ helper->pipeline, ++ actor_box, ++ paint_opacity); + } +-- +2.45.2 + diff --git a/gnome-shell-enabled-extensions-background-logos.patch b/gnome-shell-enabled-extensions-background-logos.patch new file mode 100644 index 0000000..759f383 --- /dev/null +++ b/gnome-shell-enabled-extensions-background-logos.patch @@ -0,0 +1,29 @@ +From 8fcaf1708fee86b1c16c9749dc1794be5a2a86fd Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Mon, 28 Feb 2022 10:27:09 -0500 +Subject: [PATCH] data: Enable logo extension out of the box + +Our brand team would like the logo extension to be used on new +installs. + +This commit makes sure it gets enabled out of the box. +--- + data/org.gnome.shell.gschema.xml.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in +index 3dd9d2d86b..fe1e266f8c 100644 +--- a/data/org.gnome.shell.gschema.xml.in ++++ b/data/org.gnome.shell.gschema.xml.in +@@ -12,7 +12,7 @@ + + + +- [] ++ ['background-logo@fedorahosted.org'] + UUIDs of extensions to enable + + GNOME Shell extensions have a UUID property; this key lists extensions +-- +2.45.2 + diff --git a/SOURCES/gnome-shell-favourite-apps-firefox.patch b/gnome-shell-favourite-apps-firefox.patch similarity index 58% rename from SOURCES/gnome-shell-favourite-apps-firefox.patch rename to gnome-shell-favourite-apps-firefox.patch index 888491e..af91439 100644 --- a/SOURCES/gnome-shell-favourite-apps-firefox.patch +++ b/gnome-shell-favourite-apps-firefox.patch @@ -1,7 +1,7 @@ -From 87104647f061892525236a71f304b63609960626 Mon Sep 17 00:00:00 2001 +From 9bb33b1c8d0dba0d5c9e98d98b1063a1d0408414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Thu, 9 Mar 2017 14:43:30 +0100 -Subject: [PATCH] appFavorites: Make firefox the default browser +Date: Wed, 17 Sep 2014 07:11:12 +0200 +Subject: [PATCH] Replace Web with Firefox in default favorites --- data/org.gnome.shell.gschema.xml.in | 2 +- @@ -9,30 +9,30 @@ Subject: [PATCH] appFavorites: Make firefox the default browser 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in -index 24e2a75b0..2f50036d0 100644 +index 3cd37692a7..bd2bd5ead8 100644 --- a/data/org.gnome.shell.gschema.xml.in +++ b/data/org.gnome.shell.gschema.xml.in -@@ -39,7 +39,7 @@ +@@ -61,7 +61,7 @@ -- [ 'epiphany.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ] -+ [ 'firefox.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ] +- [ 'org.gnome.Epiphany.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Music.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop', 'org.gnome.TextEditor.desktop'] ++ [ 'org.mozilla.firefox.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Music.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop', 'org.gnome.TextEditor.desktop'] List of desktop file IDs for favorite applications The applications corresponding to these identifiers diff --git a/js/ui/appFavorites.js b/js/ui/appFavorites.js -index 657e15965..1e44a1655 100644 +index 576df3800d..a1deabde37 100644 --- a/js/ui/appFavorites.js +++ b/js/ui/appFavorites.js -@@ -49,6 +49,7 @@ const RENAMED_DESKTOP_IDS = { +@@ -51,6 +51,7 @@ const RENAMED_DESKTOP_IDS = { 'gnotski.desktop': 'org.gnome.Klotski.desktop', 'gtali.desktop': 'org.gnome.Tali.desktop', 'iagno.desktop': 'org.gnome.Reversi.desktop', -+ 'mozilla-firefox.desktop': 'firefox.desktop', ++ 'firefox.desktop': 'org.mozilla.firefox.desktop', 'nautilus.desktop': 'org.gnome.Nautilus.desktop', 'org.gnome.gnome-2048.desktop': 'org.gnome.TwentyFortyEight.desktop', 'org.gnome.taquin.desktop': 'org.gnome.Taquin.desktop', -- -2.21.0 +2.45.2 diff --git a/SOURCES/gnome-shell-favourite-apps-terminal.patch b/gnome-shell-favourite-apps-terminal.patch similarity index 53% rename from SOURCES/gnome-shell-favourite-apps-terminal.patch rename to gnome-shell-favourite-apps-terminal.patch index d3f0377..1cdee69 100644 --- a/SOURCES/gnome-shell-favourite-apps-terminal.patch +++ b/gnome-shell-favourite-apps-terminal.patch @@ -1,4 +1,4 @@ -From d15a92aeaa075230f711921f4bcd929c49bfc97d Mon Sep 17 00:00:00 2001 +From d4d39560f1694f06c3594f8d34eaa4b038804920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Thu, 9 Mar 2017 14:44:32 +0100 Subject: [PATCH] appFavorites: Add terminal @@ -8,18 +8,18 @@ Subject: [PATCH] appFavorites: Add terminal 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in -index 40526187e..9d7e011fc 100644 +index bd2bd5ead8..4827fa5b79 100644 --- a/data/org.gnome.shell.gschema.xml.in +++ b/data/org.gnome.shell.gschema.xml.in -@@ -39,7 +39,7 @@ +@@ -61,7 +61,7 @@ -- [ 'firefox.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop', 'yelp.desktop' ] -+ [ 'firefox.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop', 'yelp.desktop', 'gnome-terminal.desktop' ] +- [ 'org.mozilla.firefox.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Music.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop', 'org.gnome.TextEditor.desktop'] ++ [ 'org.mozilla.firefox.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Music.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop', 'org.gnome.Ptyxis.desktop', 'org.gnome.TextEditor.desktop'] List of desktop file IDs for favorite applications The applications corresponding to these identifiers -- -2.21.0 +2.45.2 diff --git a/SPECS/gnome-shell.spec b/gnome-shell.spec similarity index 54% rename from SPECS/gnome-shell.spec rename to gnome-shell.spec index 4fa2652..f62b83b 100644 --- a/SPECS/gnome-shell.spec +++ b/gnome-shell.spec @@ -1,3 +1,16 @@ +## START: Set by rpmautospec +## (rpmautospec version 0.6.5) +## RPMAUTOSPEC: autorelease, autochangelog +%define autorelease(e:s:pb:n) %{?-p:0.}%{lua: + release_number = 4; + base_release_number = tonumber(rpm.expand("%{?-b*}%{!?-b:1}")); + print(release_number + base_release_number - 1); +}%{?-e:.%{-e*}}%{?-s:.%{-s*}}%{!?-n:%{?dist}} +## END: Set by rpmautospec + +%global tarball_version %%(echo %{version} | tr '~' '.') +%global major_version %%(cut -d "." -f 1 <<<%{tarball_version}) + %if 0%{?rhel} %global portal_helper 0 %else @@ -5,158 +18,83 @@ %endif Name: gnome-shell -Version: 3.32.2 -Release: 56%{?dist} +Version: 47~alpha +Release: %autorelease Summary: Window management and application launching for GNOME -Group: User Interface/Desktops -License: GPLv2+ -Provides: desktop-notification-daemon +License: GPL-2.0-or-later URL: https://wiki.gnome.org/Projects/GnomeShell -#VCS: git:git://git.gnome.org/gnome-shell -Source0: http://download.gnome.org/sources/gnome-shell/3.32/%{name}-%{version}.tar.xz +Source0: https://download.gnome.org/sources/gnome-shell/%{major_version}/%{name}-%{tarball_version}.tar.xz -# Replace Epiphany with Firefox in the default favourite apps list -Patch1: gnome-shell-favourite-apps-firefox.patch -Patch2: gnome-shell-favourite-apps-yelp.patch -Patch3: gnome-shell-favourite-apps-terminal.patch +# Replace Epiphany with Firefox in the default favourite apps list, etc +# and enable background extension by default +Patch: gnome-shell-favourite-apps-firefox.patch +Patch: gnome-shell-favourite-apps-terminal.patch +Patch: gnome-shell-enabled-extensions-background-logos.patch + +# Some users might have a broken PAM config, so we really need this +# downstream patch to stop trying on configuration errors. +Patch: 0001-gdm-Work-around-failing-fingerprint-auth.patch # GDM/Lock stuff -Patch12: 0001-screenShield-unblank-when-inserting-smartcard.patch -Patch13: enforce-smartcard-at-unlock.patch -Patch14: disable-unlock-entry-until-question.patch -Patch15: allow-timed-login-with-no-user-list.patch -Patch16: 0001-data-install-process-working.svg-to-filesystem.patch -Patch17: 0001-loginDialog-make-info-messages-themed.patch -Patch18: 0001-gdm-add-AuthList-control.patch -Patch19: 0002-gdmUtil-enable-support-for-GDM-s-ChoiceList-PAM-exte.patch -Patch20: wake-up-on-deactivate.patch -Patch21: caps-lock-warning.patch -Patch22: gdm-networking.patch -Patch23: 0001-shellEntry-Disconnect-handler-on-destroy.patch -Patch24: fix-login-lock-screen.patch -Patch25: 0001-shellEntry-Determine-if-password-entry-from-content-.patch -Patch26: 0002-shellEntry-Give-password-menu-item-text-when-it-s-cr.patch -Patch27: 0003-shellEntry-Handle-password-item-from-dedication-func.patch -Patch28: 0004-shellEntry-Support-lockdown-of-Show-Text-menu-in-pas.patch -Patch29: 0005-shellEntry-Only-mask-text-in-password-entries.patch +Patch: 0001-screenShield-unblank-when-inserting-smartcard.patch +Patch: enforce-smartcard-at-unlock.patch +Patch: disable-unlock-entry-until-question.patch + +# Extensions +Patch: 0001-extensionDownloader-Refuse-to-override-system-extens.patch # Misc. -Patch30: 0001-shellDBus-Add-a-DBus-method-to-load-a-single-extensi.patch -Patch31: 0001-extensions-Add-a-SESSION_MODE-extension-type.patch -Patch32: extension-updates.patch -Patch33: 0001-panel-add-an-icon-to-the-ActivitiesButton.patch -Patch34: 0001-app-Fall-back-to-window-title-instead-of-WM_CLASS.patch -Patch35: 0001-windowMenu-Bring-back-workspaces-submenu-for-static-.patch -Patch36: 0001-shell-app-Handle-workspace-from-startup-notification.patch -Patch37: 0001-main-Dump-stack-on-segfaults-by-default.patch -Patch38: 0001-appDisplay-Show-full-app-name-on-hover.patch -Patch39: horizontal-workspace-support.patch -Patch40: 0001-animation-fix-unintentional-loop-while-polkit-dialog.patch -Patch41: 0001-workspacesView-Work-around-spurious-allocation-chang.patch -Patch42: 0001-layout-Make-the-hot-corner-optional.patch -Patch43: fix-app-view-leaks.patch -Patch44: root-warning.patch -Patch45: 0001-workspace-Pass-device-to-startDrag.patch -Patch46: 0001-a11y-Change-HC-icon-theme-first.patch -Patch47: perf-tool-wayland.patch -Patch48: 0001-padOsd-Re-query-action-labels-after-mode-switches.patch -Patch49: 0001-Do-not-change-Wacom-LEDs-through-g-s-d.patch -Patch50: 0001-st-texture-cache-Cancel-pending-requests-on-icon-the.patch -Patch51: introspect-backports.patch -Patch52: 0001-popupMenu-Handle-keypress-if-numlock-is-enabled.patch -Patch53: 0001-theme-Update-window-preview-style.patch -Patch54: warn-less.patch -Patch55: 0001-networkAgent-add-support-for-SAE-secrets.patch -Patch56: 0001-main-Unset-the-right-prevFocus-actor-after-the-focus.patch -Patch57: defend-against-corrupt-notifications.patch -Patch58: 0001-status-volume-Hide-sliders-initially.patch -Patch59: 0001-shell-recorder-Restore-cursor-recording.patch -Patch60: 0001-st-bin-Disallow-st_bin_set_child-with-already-parent.patch -Patch61: 0001-layout-Initialize-regions-unconditionally.patch -Patch62: fix-nm-device-settings.patch -Patch63: owe-support.patch -Patch64: 0001-windowMenu-Ignore-release.patch -Patch65: 0001-overview-Hide-the-overview-on-session-mode-hasOvervi.patch +Patch: 0001-panel-Use-branding-in-activities-button.patch +Patch: 0001-app-Fall-back-to-window-title-instead-of-WM_CLASS.patch +Patch: 0001-windowMenu-Bring-back-workspaces-submenu-for-static-.patch +Patch: 0001-main-Dump-stack-on-segfaults-by-default.patch +Patch: 0001-st-texture-cache-purge-on-resume.patch +Patch: fix-some-js-warnings.patch +Patch: 0001-data-Update-generated-stylesheets.patch +Patch: portal-notify.patch +Patch: 0001-theme-Welcome-Illustration.patch -# Backport JS invalid access warnings (#1651894, #1663171, #1642482, #1637622) -Patch70: fix-invalid-access-warnings.patch -Patch71: more-spurious-allocation-warnings.patch -Patch72: fix-some-js-warnings.patch -Patch73: fix-double-disposed-backgrounds.patch - -# Backport performance fixes under load (#1820760) -Patch80: 0001-environment-reduce-calls-to-g_time_zone_new_local.patch -Patch81: 0002-environment-Fix-date-conversion.patch -Patch82: 0003-shell-app-system-Monitor-for-icon-theme-changes.patch -Patch83: 0004-global-force-fsync-to-worker-thread-when-saving-stat.patch -Patch84: 0005-app-cache-add-ShellAppCache-for-GAppInfo-caching.patch -Patch85: 0006-js-Always-use-AppSystem-to-lookup-apps.patch - -# Stop screen recording on monitor changes (#1705392) -Patch90: 0001-screencast-Stop-recording-when-screen-size-or-resour.patch - -# Backport OSK fixes (#1871041) -Patch95: osk-fixes.patch -Patch96: 0001-keyboard-Only-enable-keyboard-if-ClutterDeviceManage.patch - -# suspend/resume fix on nvidia (#1663440) -Patch10001: 0001-background-refresh-after-suspend-on-wayland.patch -Patch10002: 0002-background-rebuild-background-not-just-animation-on-.patch -Patch10003: 0003-st-texture-cache-purge-on-resume.patch -Patch10004: 0004-background-refresh-background-on-gl-video-memory-pur.patch - -# Allow login screen extensions (#1651378) -Patch20001: 0001-extensionSystem-Handle-added-or-removed-sessionMode-.patch -Patch20002: 0002-extensionSystem-Get-rid-of-_enabled-boolean-optimiza.patch -Patch20003: 0003-extensionSystem-Allow-extensions-to-run-on-the-login.patch -Patch20004: 0004-sessionMode-Allow-extensions-at-the-login-and-unlock.patch - -# CVE-2020-17489 -Patch30001: 0001-loginDialog-Reset-auth-prompt-on-vt-switch-before-fa.patch - -# Disable captive portal helper if WebKitGTK is not installed (RHEL-10488) -Patch40001: portal-notify.patch - -%define libcroco_version 0.6.8 -%define eds_version 3.17.2 -%define gnome_desktop_version 3.7.90 -%define glib2_version 2.56.0 +%define eds_version 3.45.1 +%define gnome_desktop_version 44.0-7 +%define glib2_version 2.79.2 %define gobject_introspection_version 1.49.1 -%define gjs_version 1.54.0 -%define gtk3_version 3.15.0 -%define mutter_version 3.32.2-57 +%define gjs_version 1.73.1 +%define gtk4_version 4.0.0 +%define adwaita_version 1.5.0 +%define mutter_version 47~alpha %define polkit_version 0.100 -%define gsettings_desktop_schemas_version 3.32.0-6 +%define gsettings_desktop_schemas_version 47~alpha %define ibus_version 1.5.2 -%define gnome_bluetooth_version 1:3.9.0 +%define gnome_bluetooth_version 1:42.3 %define gstreamer_version 1.4.5 +%define pipewire_version 0.3.0 +%define gnome_settings_daemon_version 3.37.1 +BuildRequires: bash-completion BuildRequires: gcc BuildRequires: meson BuildRequires: git -BuildRequires: ibus-devel >= %{ibus_version} -BuildRequires: chrpath +BuildRequires: pkgconfig(ibus-1.0) >= %{ibus_version} BuildRequires: desktop-file-utils -BuildRequires: evolution-data-server-devel >= %{eds_version} -BuildRequires: gcr-devel -BuildRequires: gjs-devel >= %{gjs_version} -BuildRequires: glib2-devel >= %{glib2_version} -BuildRequires: gobject-introspection >= %{gobject_introspection_version} +BuildRequires: pkgconfig(libedataserver-1.2) >= %{eds_version} +BuildRequires: pkgconfig(gcr-4) +BuildRequires: pkgconfig(gjs-1.0) >= %{gjs_version} +BuildRequires: pkgconfig(gio-2.0) >= %{glib2_version} +BuildRequires: pkgconfig(gnome-autoar-0) +BuildRequires: pkgconfig(gnome-desktop-4) >= %{gnome_desktop_version} +BuildRequires: pkgconfig(gobject-introspection-1.0) >= %{gobject_introspection_version} BuildRequires: mesa-libGL-devel BuildRequires: mesa-libEGL-devel -BuildRequires: NetworkManager-libnm-devel -BuildRequires: polkit-devel >= %{polkit_version} -BuildRequires: startup-notification-devel -# for theme generation -BuildRequires: sassc -# for screencast recorder functionality -BuildRequires: gstreamer1-devel >= %{gstreamer_version} -BuildRequires: gtk3-devel >= %{gtk3_version} -BuildRequires: gettext >= 0.19.6 -BuildRequires: libcanberra-devel -BuildRequires: libcroco-devel >= %{libcroco_version} +BuildRequires: pkgconfig(libnm) +BuildRequires: pkgconfig(polkit-agent-1) >= %{polkit_version} +BuildRequires: pkgconfig(libstartup-notification-1.0) BuildRequires: pkgconfig(libsystemd) +# for screencast recorder functionality +BuildRequires: pkgconfig(gstreamer-base-1.0) >= %{gstreamer_version} +BuildRequires: pkgconfig(libpipewire-0.3) >= %{pipewire_version} +BuildRequires: pkgconfig(gtk4) >= %{gtk4_version} +BuildRequires: gettext >= 0.19.6 BuildRequires: python3 # for barriers @@ -164,59 +102,98 @@ BuildRequires: libXfixes-devel >= 5.0 # used in unused BigThemeImage BuildRequires: librsvg2-devel BuildRequires: mutter-devel >= %{mutter_version} -BuildRequires: pulseaudio-libs-devel +BuildRequires: pkgconfig(libpulse) %ifnarch s390 s390x ppc ppc64 ppc64p7 BuildRequires: gnome-bluetooth-libs-devel >= %{gnome_bluetooth_version} %endif -#BuildRequires: control-center # Bootstrap requirements BuildRequires: gtk-doc %ifnarch s390 s390x -Requires: gnome-bluetooth%{?_isa} >= %{gnome_bluetooth_version} +Recommends: gnome-bluetooth%{?_isa} >= %{gnome_bluetooth_version} %endif Requires: gnome-desktop3%{?_isa} >= %{gnome_desktop_version} %if 0%{?rhel} != 7 # Disabled on RHEL 7 to allow logging into KDE session by default -Requires: gnome-session-xsession +Recommends: gnome-session-xsession %endif -# wrapper script uses to restart old GNOME session if run --replace -# from the command line +Requires: gcr%{?_isa} Requires: gobject-introspection%{?_isa} >= %{gobject_introspection_version} Requires: gjs%{?_isa} >= %{gjs_version} -Requires: gtk3%{?_isa} >= %{gtk3_version} -Requires: libnma%{?_isa} +Requires: gtk4%{?_isa} >= %{gtk4_version} +Requires: libadwaita%{_isa} >= %{adwaita_version} +Requires: libnma-gtk4%{?_isa} # needed for loading SVG's via gdk-pixbuf Requires: librsvg2%{?_isa} Requires: mutter%{?_isa} >= %{mutter_version} Requires: upower%{?_isa} Requires: polkit%{?_isa} >= %{polkit_version} -Requires: gnome-desktop3%{?_isa} >= %{gnome_desktop_version} +Requires: gnome-desktop4%{?_isa} >= %{gnome_desktop_version} Requires: glib2%{?_isa} >= %{glib2_version} Requires: gsettings-desktop-schemas%{?_isa} >= %{gsettings_desktop_schemas_version} -Requires: libcroco%{?_isa} >= %{libcroco_version} +Requires: gnome-settings-daemon%{?_isa} >= %{gnome_settings_daemon_version} Requires: gstreamer1%{?_isa} >= %{gstreamer_version} +# needed for screen recorder +Requires: gstreamer1-plugins-good%{?_isa} +Requires: pipewire-gstreamer%{?_isa} +Requires: xdg-user-dirs-gtk # needed for schemas Requires: at-spi2-atk%{?_isa} # needed for on-screen keyboard Requires: ibus%{?_isa} >= %{ibus_version} +# needed for "show keyboard layout" +Requires: tecla # needed for the user menu Requires: accountsservice-libs%{?_isa} Requires: gdm-libs%{?_isa} # needed for settings items in menus -Requires: control-center +Requires: gnome-control-center # needed by some utilities Requires: python3%{_isa} # needed for the dual-GPU launch menu Requires: switcheroo-control # needed for clocks/weather integration Requires: geoclue2-libs%{?_isa} -Requires: libgweather%{?_isa} +Requires: libgweather4%{?_isa} +# for gnome-extensions CLI tool +Requires: gettext # needed for thunderbolt support -Requires: bolt%{?_isa} +Recommends: bolt%{?_isa} # Needed for launching flatpak apps etc -Requires: xdg-desktop-portal-gtk +# 1.8.0 is needed for source type support in the screencast portal. +Requires: xdg-desktop-portal-gtk >= 1.8.0 +Requires: xdg-desktop-portal-gnome +# needed by the welcome dialog +Recommends: gnome-tour +%if %{portal_helper} +# needed for captive portal helper +Requires: webkitgtk6.0%{?_isa} +%endif + +# https://github.com/containers/composefs/pull/229#issuecomment-1838735764 +%if 0%{?rhel} >= 10 +ExcludeArch: %{ix86} +%endif + +Provides: desktop-notification-daemon = %{version}-%{release} Provides: PolicyKit-authentication-agent = %{version}-%{release} +Provides: bundled(gvc) +Provides: bundled(libcroco) = 0.6.13 + +%if 0%{?rhel} +# In Fedora, fedora-obsolete-packages obsoletes caribou +Obsoletes: caribou < 0.4.21-10 +Obsoletes: caribou-antler < 0.4.21-10 +Obsoletes: caribou-devel < 0.4.21-10 +Obsoletes: caribou-gtk2-module < 0.4.21-10 +Obsoletes: caribou-gtk3-module < 0.4.21-10 +Obsoletes: python-caribou < 0.4.21-10 +Obsoletes: python2-caribou < 0.4.21-10 +Obsoletes: python3-caribou < 0.4.21-10 +%endif + +# https://bugzilla.redhat.com/show_bug.cgi?id=1740897 +Conflicts: gnome-shell-extension-background-logo < 3.34.0 %description GNOME Shell provides core user interface functions for the GNOME 3 desktop, @@ -226,12 +203,13 @@ innovative user interface concepts to provide a visually attractive and easy to use experience. %prep -%autosetup -S git +%autosetup -S git -n %{name}-%{tarball_version} %build %meson \ + -Dextensions_app=false \ %if %{portal_helper} - -Dportal_helper=true \ + -Dportal_helper=true \ %else -Dportal_helper=false \ %endif @@ -249,25 +227,35 @@ mkdir -p %{buildroot}%{_datadir}/gnome-shell/search-providers %check desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Shell.desktop -desktop-file-validate %{buildroot}%{_datadir}/applications/gnome-shell-extension-prefs.desktop -desktop-file-validate %{buildroot}%{_datadir}/applications/evolution-calendar.desktop +desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Shell.Extensions.desktop + +%if %{portal_helper} +desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Shell.PortalHelper.desktop +%endif %files -f %{name}.lang %license COPYING -%doc README.md +%doc NEWS README.md %{_bindir}/gnome-shell -%{_bindir}/gnome-shell-extension-tool -%{_bindir}/gnome-shell-perf-tool +%{_bindir}/gnome-extensions %{_bindir}/gnome-shell-extension-prefs +%{_bindir}/gnome-shell-extension-tool +%{_bindir}/gnome-shell-test-tool %{_datadir}/glib-2.0/schemas/*.xml %{_datadir}/glib-2.0/schemas/00_org.gnome.shell.gschema.override +%{_datadir}/applications/org.gnome.Shell.Extensions.desktop %{_datadir}/applications/org.gnome.Shell.desktop -%{_datadir}/applications/gnome-shell-extension-prefs.desktop -%{_datadir}/applications/evolution-calendar.desktop +%{_datadir}/bash-completion/completions/gnome-extensions +%{_datadir}/gnome-control-center/keybindings/50-gnome-shell-launchers.xml +%{_datadir}/gnome-control-center/keybindings/50-gnome-shell-screenshots.xml %{_datadir}/gnome-control-center/keybindings/50-gnome-shell-system.xml %{_datadir}/gnome-shell/ +%{_datadir}/dbus-1/services/org.gnome.ScreenSaver.service %{_datadir}/dbus-1/services/org.gnome.Shell.CalendarServer.service +%{_datadir}/dbus-1/services/org.gnome.Shell.Extensions.service %{_datadir}/dbus-1/services/org.gnome.Shell.HotplugSniffer.service +%{_datadir}/dbus-1/services/org.gnome.Shell.Notifications.service +%{_datadir}/dbus-1/services/org.gnome.Shell.Screencast.service %{_datadir}/dbus-1/interfaces/org.gnome.Shell.Extensions.xml %{_datadir}/dbus-1/interfaces/org.gnome.Shell.Introspect.xml %{_datadir}/dbus-1/interfaces/org.gnome.Shell.PadOsd.xml @@ -275,322 +263,723 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/evolution-calendar.de %{_datadir}/dbus-1/interfaces/org.gnome.Shell.Screenshot.xml %{_datadir}/dbus-1/interfaces/org.gnome.ShellSearchProvider.xml %{_datadir}/dbus-1/interfaces/org.gnome.ShellSearchProvider2.xml -%{_datadir}/icons/hicolor/scalable/apps/org.gnome.Extensions.svg -%{_datadir}/icons/hicolor/symbolic/apps/org.gnome.Extensions-symbolic.svg -%{_userunitdir}/gnome-shell.service -%{_userunitdir}/gnome-shell-wayland.target -%{_userunitdir}/gnome-shell-x11.target -%{_sysconfdir}/xdg/autostart/gnome-shell-overrides-migration.desktop -# Co own directory instead of pulling in xdg-desktop-portal - we -# are providing a backend to the portal, not depending on it -%dir %{_datadir}/xdg-desktop-portal/portals/ -%{_datadir}/xdg-desktop-portal/portals/gnome-shell.portal +%{_datadir}/icons/hicolor/scalable/apps/org.gnome.Shell.Extensions.svg +%{_datadir}/icons/hicolor/symbolic/apps/org.gnome.Shell.Extensions-symbolic.svg +%{_userunitdir}/org.gnome.Shell-disable-extensions.service +%{_userunitdir}/org.gnome.Shell.target +%{_userunitdir}/org.gnome.Shell@wayland.service +%{_userunitdir}/org.gnome.Shell@x11.service %{_libdir}/gnome-shell/ %{_libexecdir}/gnome-shell-calendar-server %{_libexecdir}/gnome-shell-perf-helper %{_libexecdir}/gnome-shell-hotplug-sniffer -%{_libexecdir}/gnome-shell-overrides-migration.sh -# Co own these directories instead of pulling in GConf -# after all, we are trying to get rid of GConf with these files -%dir %{_datadir}/GConf -%dir %{_datadir}/GConf/gsettings -%{_datadir}/GConf/gsettings/gnome-shell-overrides.convert -%{_mandir}/man1/%{name}.1.gz +%{_mandir}/man1/gnome-extensions.1* +%{_mandir}/man1/gnome-shell.1* %if %{portal_helper} %{_datadir}/applications/org.gnome.Shell.PortalHelper.desktop %{_datadir}/dbus-1/services/org.gnome.Shell.PortalHelper.service +%{_datadir}/icons/hicolor/scalable/apps/org.gnome.Shell.CaptivePortal.svg +%{_datadir}/icons/hicolor/symbolic/apps/org.gnome.Shell.CaptivePortal-symbolic.svg %{_libexecdir}/gnome-shell-portal-helper %endif %changelog -* Wed Jul 10 2024 Florian Müllner - 3.32.2-56 -- Only open portal login in response to user action - Resolves: RHEL-39097 +## START: Generated by rpmautospec +* Tue Aug 20 2024 Tomas Popela - 47~alpha-4 +- Use branded illustrations -* Thu Dec 21 2023 Florian Müllner - 3.32.2-55 -- Hide the overview on lock - Resolves: RHEL-17349 +* Mon Aug 05 2024 Florian Müllner - 47~alpha-3 +- rpminspect: Use correct paths in runpath exception -* Wed Nov 01 2023 Michael Catanzaro - 3.32.2-54 -- Disable captive portal helper if WebKitGTK is not installed - Resolves: RHEL-10488 +* Mon Jul 29 2024 Florian Müllner - 47~alpha-2 +- Switch default terminal -* Wed Oct 18 2023 Florian Müllner - 3.32.2-53 -- Fix window-menu closing immediately on open - Resolves: RHEL-2662 +* Tue Jul 23 2024 Florian Müllner - 47~alpha-1 +- Update to 47.alpha -* Mon Sep 18 2023 Florian Müllner - 3.32.2-52 -- Bump release to avoid conflict with z-stream +* Tue Jul 09 2024 Florian Müllner - 46.3.1-3 +- Only open captive portal login in response to user action -* Mon Sep 11 2023 Florian Müllner - 3.32.2-51 -- Support OWE networks - Resolves: #2033620 +* Tue Jul 02 2024 Florian Müllner - 46.3.1-2 +- Only use RH branding on RHEL and use the system icon instead of a custom + asset to avoid including trademarked assets on non-RHEL installs. -* Thu Dec 01 2022 Florian Müllner - 3.32.2-50 -- Fix struts on login screen - Resolves: #2138941 -- Fix launching network device settings - Resolves: #1879405 +* Mon Jul 01 2024 Florian Müllner - 46.3.1-1 +- Update to 46.3.1 -* Mon Nov 21 2022 Florian Müllner - 3.32.2-49 -- Fix assert durin StBin destruction - Resolves: #2130131 +* Mon Jun 24 2024 Troy Dawson - 46.2-4 +- Bump release for June 2024 mass rebuild -* Fri Aug 12 2022 Florian Müllner - 3.32.2-48 -- Fix warnings on double-disposed backgrounds - Resolves: #2116555 +* Wed Jun 05 2024 Florian Müllner - 46.2-3 +- Use dedicated icon for captive portal -* Wed May 11 2022 Phil Wyett - 3.32.2-47 -- Restore missing cursor to screencast recordings - Resolves: #1993420 +* Tue May 28 2024 Florian Müllner - 46.2-2 +- Add (back) rpminspect configuration -* Wed May 11 2022 Florian Müllner - 3.32.2-46 -- Hide volume sliders initially - Resolves: #1982779 +* Mon May 27 2024 Florian Müllner - 46.2-1 +- Update to 46.2 -* Thu Apr 21 2022 Florian Müllner - 3.32.2-45 -- Fix lock up when previous focus actor is destroyed during modal - Resolves: #2075231 -- Defend against corrupt notifications file - Resolves: #2078564 +* Thu May 23 2024 Florian Müllner - 46.1-9 +- Add downstream branding -* Fri Nov 26 2021 Florian Müllner - 3.32.2-44 -- Fix more JS warnings - Resolves: #2025940 +* Wed May 15 2024 Ray Strode - 46.1-8 +- Fix error handling in fingerprint code -* Thu Oct 21 2021 Florian Müllner - 3.32.2-43 -- Backport fix for CVE-2020-17489 - Resolves: #1874259 +* Wed May 15 2024 Florian Müllner - 46.1-7 +- Fix unlock prompt when animations are disabled -* Wed Oct 20 2021 Florian Müllner - 3.32.2-42 -- Backport WPA3 support - Resolves: #1924593 +* Mon May 13 2024 Michael Catanzaro - 46.1-6 +- Fix screencast proxy bus name -* Tue Aug 31 2021 Ray Strode - 3.32.2-41 -- Add bugs introduced in backport for #1651378 - Related: #2000918 -- Tidy up patch list a bit +* Fri May 10 2024 Florian Müllner - 46.1-5 +- Fix auth regression in downstream patches -* Wed Aug 25 2021 Ray Strode - 3.32.2-39 -- Allow extensions on the login screen - Related: #1651378 - -* Thu Jul 29 2021 Florian Müllner - 3.32.2-38 -- Only mask text in password entries - Resolves: #1987233 - -* Wed Jul 28 2021 Florian Müllner - 3.32.2-37 -- Only warn once when not running under GDM - Resolves: #1980661 - -* Tue Jul 20 2021 Ray Strode - 3.32.2-36 -- Add ability to lock down password showing - Resolves: #1770302 -- Add requires on newer mutter version - Related: #1937866 - -* Tue Jul 13 2021 Florian Müllner - 3.32.2-35 -- Improve style of window preview close buttons - Resolves: #1981420 - -* Mon Jul 12 2021 Florian Müllner - 3.32.2-34 -- Add PolicyKit-authentication-agent virtual provides - Resolves: #1978287 - -* Mon Jun 14 2021 Florian Müllner - 3.32.2-33 -- Fix warnings on unlock - Resolves: #1971534 -- Fix gdm lock screen - Resolves: #1971507 - -* Thu Jun 10 2021 Florian Müllner - 3.32.2-32 -- Fix network secret requests on login screen - Related: #1935261 - -* Wed Jun 09 2021 Florian Müllner - 3.32.2-31 -- Backport of touch mode - Resolves: #1937866 - -* Tue Jun 08 2021 Florian Müllner - 3.32.2-30 -- Do not disable network actions on login screen - Resolves: #1935261 - -* Mon Feb 01 2021 Florian Müllner - 3.32.2-29 -- Refuse to override system extensions - Related: #1802105 - -* Mon Jan 25 2021 Florian Müllner - 3.32.2-28 -- Backport extension updates support - Related: #1802105 - -* Thu Jan 14 2021 Florian Müllner - 3.32.2-27 -- Default to printing JS backtrace on segfaults - Resolves: #1883868 - -* Wed Jan 13 2021 Carlos Garnacho - 3.32.2-26 -- Backport OSK fixes - Resolves: #1871041 - -* Tue Jan 12 2021 Jonas Ådahl - 3.32.2-25 -- Stop screen recording on monitor changes - Resolves: #1705392 - -* Thu Jan 07 2021 Florian Müllner - 3.32.2-24 -- Handle workspace from startup notification - Resolves: #1671761 - -* Tue Jan 05 2021 Florian Müllner - 3.32.2-23 -- Work around aggressive garbage collection - Related: #1881312 - -* Fri Oct 23 2020 Florian Müllner - 3.32.2-22 -- Wake up lock screen when deactivated programmatically - Resolves: #1854290 -- Backport better caps-lock warning - Resolves: #1861357 -- Fix more (harmless) JS warnings - Resolves: #1881312 - -* Thu Oct 01 2020 Michael Catanzaro - 3.32.2-21 -- Fix JS warning in AuthList downstream patch - Resolves: #1860946 - -* Thu Jul 30 2020 Florian Müllner - 3.32.2-20 -- Fix popupMenu keynav when NumLock is active - Resolves: #1840080 - -* Mon Jun 15 2020 Florian Müllner - 3.32.2-19 -- Fix last backport - Resolves: #1847051 - -* Sun Jun 14 2020 Florian Müllner - 3.32.2-18 -- Fix more spurious allocation warnings - Resolves: #1715845 - -* Fri May 22 2020 Florian Müllner - 3.32.2-17 -- Really allow using perf-tool on wayland - Resolves: #1652178 -- Fix timed login without user list - Resolves: #1668895 -- Fix HighContrast/symbolic icon mixup - Resolves: #1794045 -- Backport introspect API changes - Resolves: #1837413 - -* Fri Apr 17 2020 Florian Müllner - 3.32.2-16 -- Drop bad upstream patch - Resolves: #1820760 - -* Wed Apr 08 2020 Florian Müllner - 3.32.2-15 -- Improve performance under load - Resolves: #1820760 - -* Wed Mar 04 2020 Carlos Garnacho - 3.32.2-14 -- Do not set Wacom LEDs through gnome-settings-daemon, rely on kernel driver - Resolves: #1687979 - -* Mon Dec 16 2019 Carlos Garnacho - 3.32.2-13 -- Update pad OSD on mode switching - Resolves: #1716774 - -* Fri Dec 13 2019 Carlos Garnacho - 3.32.2-12 -- Fix window dragging with tablets in the overview - Resolves: #1716767 -- Fix high-contrast/symbolic race - Resolves: #1730612 -- Make perf-tool usable on wayland - Resolves: #1652178 - -* Mon Dec 02 2019 Florian Müllner - 3.32.2-11 -- Warn when logging in as root - Resolves: #1746327 - -* Wed Nov 27 2019 Florian Müllner - 3.32.2-10 -- Fix leaks in app picker - Related: #1719819 - -* Thu Aug 15 2019 Jonas Ådahl - 3.32.2-9 -- Depend on correct gsettings-desktop-schemas version - Related: #1704355 - -* Wed Aug 14 2019 Jonas Ådahl - 3.32.2-8 -- Depend on required gsettings-desktop-schemas version - Related: #1704355 - -* Tue Jul 23 2019 Florian Müllner - 3.32.2-7 -- Make the hot corner optional - Resolves: #1704355 - -* Fri Jul 12 2019 Florian Müllner - 3.32.2-6 -- Fix warnings triggered by spurious allocations - Resolves: #1719279 - -* Wed Jul 10 2019 Florian Müllner - 3.32.2-5 -- Fix infinite loop in spinner animation - Resolves: #1725555 - -* Tue Jun 18 2019 Florian Müllner - 3.32.2-4 -- Adjust more shortcut handlers for horizontal workspaces - Related: #1704360 - -* Wed Jun 12 2019 Florian Müllner - 3.32.2-3 -- Support horizontal workspaces in gestures/keybindings/animations - Related: #1704360 - -* Fri May 31 2019 Florian Müllner - 3.32.2-2 +* Fri May 03 2024 Florian Müllner - 46.1-4 - Adjust downstream patch to mutter changes - Resolves: #1715738 -* Thu May 23 2019 Florian Müllner - 3.32.2-1 -- Update to 3.32.2 - Resolves: #1698520 +* Thu May 02 2024 Florian Müllner - 46.1-3 +- Don't use window icons in overview -* Mon Feb 11 2019 Florian Müllner - 3.28.3-10 -- Backport another IM fix (#1668979) +* Thu May 02 2024 Tomas Pelka - 46.1-2 +- Add gating.yaml via API -* Mon Feb 11 2019 Florian Müllner - 3.28.3-9 -- Fix JS "invalid access" warnings (#1642482, #1637622) -- Fix new input sources only working after re-login (#1628154) -- Backport IM support fixes (#1668979) +* Mon Apr 22 2024 Florian Müllner - 46.1-1 +- Pick up F40 changes -* Fri Feb 08 2019 Florian Müllner - 3.28.3-8 -- Re-add dropped downstream patches (rhbz#1668884) +* Tue Apr 16 2024 Florian Müllner - 46.0-2 +- Re-apply downstream patches -* Tue Feb 05 2019 Jonas Ådahl - 3.28.3-7 -- Backport dnd crash fix (#1663171) +* Wed Apr 10 2024 Florian Müllner - 46.0-1 +- Backport F40 changes -* Thu Jan 31 2019 Ray Strode - 3.28.3-6 -- Fix suspend and resume corruption on NVidia - Resolves: #1663440 +* Wed Jan 24 2024 Fedora Release Engineering - 46~alpha-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild -* Wed Jan 16 2019 Jonas Ådahl - 3.28.3-5 -- Backport dnd fix (#1651894) +* Fri Jan 19 2024 Fedora Release Engineering - 46~alpha-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild -* Fri Jan 11 2019 Olivier Fourdan - 3.28.3-4 -- Backport Introspection D-BUS API (rhbz#1658967) +* Thu Jan 18 2024 Troy Dawson - 46~alpha-6 +- Make i686 exclusion for RHEL only -* Tue Sep 18 2018 David King - 3.28.3-3 -- Improve Python 3 dependency (#1630148) +* Thu Jan 18 2024 Troy Dawson - 46~alpha-5 +- Re-enable i686 This is not a leaf package. Removing i686 affects too many + other packages. -* Fri Aug 10 2018 Jonas Ådahl - 3.28.3-2 -- Backport remote access control UI (rhbz#1613749) +* Mon Jan 15 2024 Michael Catanzaro - 46~alpha-4 +- Don't recommend WebKitGTK in RHEL -* Fri Aug 10 2018 Kalev Lember - 3.28.3-1 -- Update to 3.28.3 +* Tue Jan 09 2024 Troy Dawson - 46~alpha-3 +- Exclude i686 -* Mon Aug 06 2018 Charalampos Stratakis - 3.28.1-6 +* Tue Jan 09 2024 František Zatloukal - 46~alpha-2 +- Rebuilt for evolution-data-server soname version bump + +* Tue Jan 09 2024 Florian Müllner - 46~alpha-1 +- Update to 46.alpha + +* Mon Jan 08 2024 Milan Crha - 45.2-6 +- Rebuilt for evolution-data-server soname version bump + +* Mon Jan 08 2024 Yanko Kaneti - 45.2-5 +- Add NEWS + +* Thu Jan 04 2024 Florian Müllner - 45.2-4 +- Add missing dependency of gnome-extensions CLI tool + +* Thu Dec 21 2023 Martin Stransky - 45.2-3 +- Rename firefox.desktop to org.mozilla.firefox.desktop at + RENAMED_DESKTOP_IDS + +* Wed Dec 20 2023 Martin Stransky - 45.2-2 +- Renamed Firefox desktop file from firefox.desktop to + org.mozilla.firefox.desktop + +* Sat Dec 02 2023 Florian Müllner - 45.2-1 +- Update to 45.2 + +* Mon Nov 27 2023 Milan Crha - 45.1-5 +- Update License tag to SPDX + +* Wed Nov 15 2023 Dominik 'Rathann' Mierzejewski - 45.1-4 +- Recommend bolt instead of requiring it (#2192253) + +* Thu Nov 09 2023 Michael Catanzaro - 45.1-3 +- Add patch to make portal helper optional + +* Thu Nov 09 2023 Michael Catanzaro - 45.1-2 +- Add missing Recommends: webkitgtk6.0%%{?_isa} + +* Tue Oct 31 2023 Florian Müllner - 45.1-1 +- Update to 45.1 + +* Sat Sep 16 2023 Florian Müllner - 45.0-1 +- Update to 45.0 + +* Wed Sep 06 2023 Florian Müllner - 45~rc-2 +- Bump mutter requirement + +* Wed Sep 06 2023 Florian Müllner - 45~rc-1 +- Update to 45.rc + +* Wed Sep 06 2023 Ray Strode - 45~beta.1-7 +- Add back -b to autorelease because it oddly seems to be needed + +* Wed Sep 06 2023 Ray Strode - 45~beta.1-3 +- Fix JS Error in log about background apps + +* Tue Aug 29 2023 Ray Strode - 45~beta.1-3 +- Rev release + +* Tue Aug 29 2023 Ray Strode - 45~beta.1-1 +- Eek, drop the Epoch I just had for testing + +* Tue Aug 29 2023 Ray Strode - 1:45~beta.1-1 +- Use input source defaults if not configured in gsettings + +* Fri Aug 11 2023 Florian Müllner - 45~beta.1-1 +- Update to 45.beta.1 + +* Thu Aug 10 2023 Adam Williamson - 45~beta-2 +- Backport MRs #2871 and #2872 to help fix broken alt-tab behavior + +* Tue Aug 08 2023 Florian Müllner - 45~beta-1 +- Update to 45.beta + +* Wed Jul 19 2023 Fedora Release Engineering - 45~alpha-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Thu Jul 06 2023 Florian Müllner - 45~alpha-1 +- Update to 45.alpha + +* Mon Jun 19 2023 Kalev Lember - 44.2-2 +- Rebuilt for gcr soname bump + +* Sat Jun 03 2023 Florian Müllner - 44.2-1 +- Update to 44.2 + +* Sat Mar 25 2023 Adam Williamson - 44.0-4 +- Backport MR #2725 - *another* fix for screenshot notifications + +* Fri Mar 24 2023 Adam Williamson - 44.0-3 +- Backport a fix for screenshot notifications + +* Sun Mar 19 2023 Florian Müllner - 44.0-2 +- Fix timed logout + Resolves: #2177853 + +* Sun Mar 19 2023 Florian Müllner - 44.0-1 +- Update to 44.0 + +* Tue Mar 14 2023 Dominik Mierzejewski - 44~rc-2 +- Recommend gnome-bluetooth instead of requiring it + Resolves rhbz#2172653 + +* Mon Mar 06 2023 Florian Müllner - 44~rc-1 +- Update to 44.rc + +* Sun Mar 05 2023 Ray Strode - 44~beta-3 +- Fix slowdown in at shutdown + Resolves: #2174753 + +* Mon Feb 20 2023 Adam Williamson - 44~beta-2 +- Rebuild without changes for Bodhi reasons + +* Tue Feb 14 2023 Florian Müllner - 44~beta-1 +- Update to 44.beta + +* Thu Jan 19 2023 Fedora Release Engineering - 43.1-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Mon Nov 21 2022 Adam Williamson - 43.1-4 +- Backport MR #2548 to fix keyboard shortcut inhibiting + +* Thu Nov 17 2022 Jonas Ådahl - 43.1-3 +- Backport missing screencast if gstreamer1-vaapi is installed + +* Wed Nov 16 2022 Adam Williamson - 43.1-2 +- Backport MR #2534 to fix layout switching in password entries + +* Fri Nov 04 2022 Florian Müllner - 43.1-1 +- Update to 43.1 + +* Tue Oct 11 2022 Adam Williamson - 43.0-3 +- Backport MR2508 to fix OSK space entry (#2131837) + +* Thu Sep 22 2022 Kalev Lember - 43.0-2 +- Backport MR2487 and MR2495 to fix input sources sorting (#2121110) + +* Sat Sep 17 2022 Florian Müllner - 43.0-1 +- Update to 43.0 + +* Thu Sep 15 2022 Kalev Lember - 43~rc-3 +- Backport a fix for initial setup session input sources sorting (#2121110) + +* Tue Sep 06 2022 Kalev Lember - 43~rc-2 +- Backport upstream fix to fix boot options (#2124043) + +* Sun Sep 04 2022 Florian Müllner - 43~rc-1 +- Update to 43.rc + +* Fri Sep 02 2022 Kalev Lember - 43~beta-3 +- Add missing dep on gcr + +* Thu Aug 11 2022 Kalev Lember - 43~beta-2 +- Bump minimum required gjs version + +* Wed Aug 10 2022 Florian Müllner - 43~beta-1 +- Update to 43.beta + +* Thu Jul 21 2022 Fedora Release Engineering - 43~alpha-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Tue Jul 19 2022 Milan Crha - 43~alpha-2 +- Rebuilt for evolution-data-server soname version bump +- Add patch to port to gcr4 + +* Sun Jul 10 2022 Florian Müllner - 43~alpha-1 +- Update to 43.alpha + +* Sat May 28 2022 Florian Müllner - 42.2-1 +- Update to 42.2 + +* Fri May 06 2022 Florian Müllner - 42.1-1 +- Update to 42.1 + +* Mon Apr 18 2022 Florian Müllner - 42.0-3 +- Fix monitor config switches with p (#2073406) +- Fix stuck cover pane after startup animation (#2063156) + +* Tue Mar 15 2022 Adam Williamson - 42.0-2 +- Backport MR #2242 to fix new user default folder creation (#2064473) + +* Sun Mar 13 2022 Florian Müllner - 42.0-1 +- Update to 42.0 + +* Wed Mar 09 2022 Adam Williamson - 42~rc-2 +- Backport MR #2238 to fix crashes on first login + +* Mon Mar 07 2022 Florian Müllner - 42~rc-1 +- Update to 42.rc + +* Tue Mar 01 2022 Adam Williamson - 42~beta-4 +- Update the MR #2185 backport + +* Tue Mar 01 2022 Adam Williamson - 42~beta-3 +- Backport MR #2185 to fix some styling issues at lower resolutions + +* Wed Feb 16 2022 David King - 42~beta-2 +- Update some dependency versions + +* Tue Feb 15 2022 Florian Müllner - 42~beta-1 +- Update to 42.beta + +* Thu Jan 20 2022 Fedora Release Engineering - 42~alpha-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Fri Jan 14 2022 David King - 42~alpha-2 +- Fix gweather4 dependency + +* Fri Jan 14 2022 David King - 42~alpha-1 +- Update to 42.alpha +- Use pkgconfig for BuildRequires + +* Fri Oct 29 2021 Adam Williamson - 41.0-8 +- Backport MR #2011 to further fix unexpected scrolling (#2017192) + +* Wed Oct 27 2021 Ray Strode - 41.0-7 +- Use correct patch for fixing unlock screen confusion + +* Tue Oct 26 2021 Jonas Ådahl - 41.0-6 +- Work around crashy tear down + +* Tue Oct 26 2021 Ray Strode - 41.0-5 +- Fix unlock screen confusion when hitting escape too much + +* Tue Oct 12 2021 Ray Strode - 41.0-4 +- Fix StPasswordEntry crash + Resolves: #2009637 + +* Thu Oct 07 2021 Adam Williamson - 41.0-3 +- Backport MR #1983 to fix wrong OSD icons (#2011872) + +* Tue Oct 05 2021 Kalev Lember - 41.0-2 +- Backport upstream patch to fix scrolling to incorrect positions + +* Sun Sep 19 2021 Florian Müllner - 41.0-1 +- Update to 41.0 + +* Tue Sep 14 2021 Ray Strode - 41~rc.1-2 +- Drop extra capabilities from gnome-shell. They're optional and they break shutdown from the login screen with new glibs. + Resolves: #1996998 + +* Tue Sep 07 2021 Florian Müllner - 41~rc.1-1 +- Update to 41.rc.1 + +* Sun Sep 05 2021 Florian Müllner - 41~rc-1 +- Update to 41.rc + +* Wed Aug 18 2021 Florian Müllner - 41~beta-1 +- Update to 41.beta + +* Thu Jul 22 2021 Fedora Release Engineering - 40.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Mon Jul 12 2021 Florian Müllner - 40.3-1 +- Update to 40.3 + +* Thu Jun 10 2021 Florian Müllner - 40.2-1 +- Update to 40.2 + +* Thu May 13 2021 Florian Müllner - 40.1-1 +- Update to 40.1 + +* Fri Apr 30 2021 Kalev Lember - 40.0-6 +- Move gnome-tour dep here from gnome-initial-setup (#1955179) + +* Wed Apr 28 2021 Benjamin Berg - 40.0-5 +- Update fix for password auth after background service failure + Related: #1942443 + +* Fri Apr 23 2021 Benjamin Berg - 40.0-4 +- Fix password auth after secondary service failure + Related: #1942443 + +* Tue Apr 13 2021 Adam Williamson - 40.0-3 +- Fix scrolling between workspaces/app grid pages with PgUp/PgDn + +* Tue Apr 13 2021 Ray Strode - 40.0-2 +- Fix timed login when user list is disabled + Resolves: #1940618 + +* Sat Mar 20 2021 Florian Müllner - 40.0-1 +- Update to 40.0 + +* Mon Mar 15 2021 Florian Müllner - 40.0~rc-1 +- Update to 40.rc + +* Thu Mar 11 2021 Kalev Lember - 40.0~beta-4.20210304git7a57528bd +- Recommend gnome-session-xsession rather than hard-require it + +* Mon Mar 08 2021 Florian Müllner - 40.0~beta-3.20210304git40.7a57528bd +- Fix crash after launching apps via drag-and-drop + +* Thu Mar 04 2021 Florian Müllner - 40.0~beta-2.20210304git40.7a57528bd +- Build snapshot of current upstream + +* Tue Feb 23 2021 Florian Müllner - 40.0~beta-1 +- Update to 40.beta + +* Mon Feb 22 2021 Kalev Lember - 40.0~alpha.1.1-9.20210212git829a096ba +- Add missing requires on gstreamer1-plugins-good and xdg-user-dirs-gtk (#1931342) + +* Sun Feb 14 2021 Florian Müllner - 40.0~alpha.1.1-8.20210212git829a096ba +- Only open app picker on left-click/touch + +* Sun Feb 14 2021 Florian Müllner - 40.0~alpha.1.1-7.20210212git829a096ba +- Don't open app picker when clicking minimap + +* Fri Feb 12 2021 Florian Müllner - 40.0~alpha.1.1-6.20210212git829a096ba +- Update snapshot to current upstream +- Allow opening app picker by clicking overview background + +* Fri Feb 12 2021 Milan Crha - 40.0~alpha.1.1-5.20210202git9ce666ac1 +- Rebuilt for evolution-data-server soname version bump + +* Tue Feb 02 2021 Florian Müllner - 40.0~alpha.1.1-4.20210202git9ce666ac1 +- Build snapshot of current upstream + +* Tue Jan 26 2021 Fedora Release Engineering - 40.0~alpha.1.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Tue Jan 19 2021 Kalev Lember - 40.0~alpha.1.1-2 +- Require libgweather >= 40~alpha for new application_id property + +* Mon Jan 18 2021 Florian Müllner - 40.alpha.1.1-1 +- Update to 40.alpha.1.1 + +* Fri Jan 15 2021 Florian Müllner - 40.alpha.1-1 +- Update to 40.alpha.1 + +* Wed Dec 02 2020 Florian Müllner - 40.alpha-1 +- Update to 40.alpha + +* Tue Oct 13 2020 Florian Müllner - 3.38.1-2 +- Fix crash on size change (non-)transitions + +* Mon Oct 05 2020 Florian Müllner - 3.38.1-1 +- Update to 3.38.1 + +* Tue Sep 29 2020 David King - 3.38.0-2 +- Better specify xdg-desktop-portal-gtk dependency (#1882894) + +* Mon Sep 14 2020 Florian Müllner - 3.38.0-1 +- Update to 3.38.0 + +* Thu Sep 10 2020 Kalev Lember - 3.37.92-5 +- Set minimum gnome-settings-daemon version for Screencast proxy changes + +* Wed Sep 09 2020 Kalev Lember - 3.37.92-4 +- Add missing pipewire-gstreamer dependency for screen recorder + +* Sun Sep 06 2020 Florian Müllner - 3.37.92-1 +- Update to 3.37.92 + +* Wed Sep 02 2020 Florian Müllner - 3.37.91-3 +- Add missing pipewire dependency for screen recorder + +* Wed Aug 26 2020 Kalev Lember - 3.37.91-2 +- Add PolicyKit-authentication-agent virtual provides + +* Mon Aug 24 2020 Florian Müllner - 3.37.91-1 +- Update to 3.37.91 + +* Sun Aug 23 2020 Kalev Lember - 3.37.90-2 +- Backport a fix for launching apps under X11 (#1870234) + +* Fri Aug 14 2020 Florian Müllner - 3.37.90-1 +- Update to 3.37.90 + +* Sat Aug 01 2020 Fedora Release Engineering - 3.37.3-4 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Jul 27 2020 Fedora Release Engineering - 3.37.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Jul 13 2020 Milan Crha - 3.37.3-2 +- Rebuilt for evolution-data-server soname version bump + +* Tue Jul 07 2020 Florian Müllner - 3.37.3-1 +- Update to 3.37.3 + +* Fri Jul 03 2020 Milan Crha - 3.37.2-2 +- Rebuilt for evolution-data-server soname version bump + +* Wed Jun 03 2020 Florian Müllner - 3.37.2-1 +- Update to 3.37.2 + +* Wed May 20 2020 Stephen Gallagher - 3.37.1-3 +- Fix crashes when locking the screen while certain extensions are active +- Resolves: rhbz#1817082 + +* Mon May 04 2020 Adam Williamson - 3.37.1-2 +- Fix panel to show input methods (MR #1235) + +* Thu Apr 30 2020 Florian Müllner - 3.36.1-2 +- Backport fixup for spring animation fix + +* Tue Mar 31 2020 Florian Müllner - 3.36.1-1 +- Update to 3.36.1 +- Remove gnome-extensions-app subpackage (will move to a separate .spec) + +* Wed Mar 25 2020 Ray Strode - 3.36.0-4 +- Clear environment on logout + Fixes log in to Xorg right after log out from wayland + Resolves: #1815487 + +* Wed Mar 11 2020 Adam Williamson - 3.36.0-3 +- Backport fix for input method preedit issue (MR #1084) + +* Tue Mar 10 2020 Adam Williamson - 3.36.0-2 +- Backport fix for ibus failing to start automatically (MR #1080) + +* Sat Mar 07 2020 Florian Müllner - 3.36.0-1 +- Update to 3.36.0 + +* Sun Mar 01 2020 Florian Müllner - 3.35.92-1 +- Update to 3.35.92 + +* Tue Feb 18 2020 Florian Müllner - 3.35.91-1 +- Update to 3.35.91 + +* Fri Feb 07 2020 Kalev Lember - 3.35.90-2 +- Adjust the favorites patch to include the apps we install by default + +* Thu Feb 06 2020 Florian Müllner - 3.35.90-1 +- Update to 3.35.90 + +* Tue Jan 28 2020 Fedora Release Engineering - 3.35.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Jan 16 2020 Kalev Lember - 3.35.3-2 +- Rebuilt for libgnome-desktop soname bump + +* Sun Jan 05 2020 Florian Müllner - 3.35.3-2 +- Update to 3.35.3 + +* Wed Dec 11 2019 Florian Müllner - 3.35.2-1 +- Udpate to 3.35.2 + +* Sat Oct 12 2019 Florian Müllner - 3.35.1-1 +- Update to 3.35.1 + +* Sat Oct 12 2019 Adam Williamson - 3.34.1-2 +- Backport MR #754 to fix #1749433 + +* Wed Oct 09 2019 Florian Müllner - 3.34.1-1 +- Update to 3.34.1 + +* Tue Sep 24 2019 Debarshi Ray - 3.34.0-3 +- Stop NOTIFY_SOCKET from leaking into the GNOME environment + +* Fri Sep 20 2019 Florian Müllner - 3.34.0-2 +- Fix disappearing icons in frequent view + +* Mon Sep 09 2019 Florian Müllner - 3.34.0-1 +- Update to 3.34.0 + +* Thu Sep 05 2019 Kalev Lember - 3.33.92-1 +- Update to 3.33.92 + +* Mon Aug 26 2019 Kalev Lember - 3.33.91-1 +- Update to 3.33.91 + +* Fri Aug 23 2019 Adam Williamson - 3.33.90-2 +- Revert commit that causes #1740897 (overview type-to-search bug) + Resolves: #1740897 + +* Sat Aug 10 2019 Florian Müllner - 3.33.90-1 +- Update to 3.33.90 + +* Thu Jul 25 2019 Fedora Release Engineering - 3.33.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Sat Jul 20 2019 Florian Müllner - 3.33.4-1 +- Update to 3.33.4 + +* Mon Jun 24 2019 Florian Mülllner - 3.33.3-1 +- Update to 3.33.3 + +* Wed May 22 2019 Florian Müllner - 3.33.2-1 +- Update to 3.33.2 + +* Wed May 22 2019 Kalev Lember - 3.33.1-2 +- Rebuild for libecal-2.0 + +* Tue May 14 2019 Florian Müllner - 3.33.1-1 +- Update to 3.33.1 + +* Wed Apr 17 2019 Florian Müllner - 3.32.1-1 +- Update to 3.32.1 + +* Wed Apr 17 2019 Adam Williamson - 3.32.0-3 +- Backport MR #463 and MR #494 to fix a couple of bugs + Resolves: #1696270 + Resolves: #1690429 + +* Sat Mar 23 2019 Phil Wyett - 3.32.0-2 +- Update source URL +- Add gcc BuildRequires +- Update versions required for gjs and mutter + +* Tue Mar 12 2019 Florian Müllner - 3.32.0-1 +- Update to 3.32.0 + +* Tue Mar 05 2019 Florian Müllner - 3.31.92-1 +- Update to 3.31.92 + +* Thu Feb 21 2019 Florian Müllner - 3.31.91-1 +- Update to 3.31.91 + +* Mon Feb 11 2019 Adam Williamson - 3.31.90-2 +- Backport MR #402 to fix missing logo on login screen + +* Thu Feb 07 2019 Florian Müllner - 3.31.90-1 +- Update to 3.31.90 + +* Thu Jan 31 2019 Fedora Release Engineering - 3.31.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Thu Jan 10 2019 Florian Müllner - 3.31.4-1 +- Update to 3.31.4 + +* Fri Dec 14 2018 Adam Williamson - 3.31.2-3 +- Backport several bugfix commits from current git master + +* Fri Nov 30 2018 Adam Williamson - 3.31.2-2 +- Backport PR #293 to fix 'empty input method indicator' bug + +* Wed Nov 14 2018 Florian Müllner - 3.31.2-1 +- Update to 3.31.2 + +* Mon Nov 12 2018 Mohan Boddu - 3.30.1-3 +- Rebuilt for evolution-data-server soname bump + +* Tue Oct 23 2018 Jonas Ådahl - 3.30.1-2 +- Backport keyboard layout change fixes (rhbz#1637418) + +* Mon Oct 08 2018 Florian Müllner - 3.30.1-1 +- Update to 3.30.1 + +* Thu Sep 27 2018 Hans de Goede - 3.30.0-9 +- Add downstream patches implementing the "Boot Options" menu from: + https://wiki.gnome.org/Design/OS/BootOptions + +* Sat Sep 22 2018 Adam Williamson - 3.30.0-8 +- Backport fix for IBus type issue (GGO MR #228) + +* Wed Sep 19 2018 Adam Williamson - 3.30.0-7 +- Replace dnd fix from -5 with upstream version (GGO MR #209) +- Fix a window destroy crash which can occur with new gjs (GGO #539) +- Fix a window menu issue on multi-monitor systems (GGO MR #227) +- Fix hover and active states for some buttons (GGO #523) + +* Wed Sep 19 2018 Adam Williamson - 3.30.0-6 +- Fix missing key description in ssh key unlock prompt (GGO #574) + +* Wed Sep 19 2018 Ray Strode - 3.30.0-5 +- Fix lock up when dropping icon on dash + Resolves: #1630134 + +* Tue Sep 18 2018 Adam Williamson - 3.30.0-4 +- Fix connecting to wifi from user menu (RHBZ #1628263) + +* Sat Sep 15 2018 Adam Williamson - 3.30.0-3 +- Backport fix for GGO #140 from upstream master + +* Thu Sep 13 2018 Kalev Lember - 3.30.0-2 +- Require xdg-desktop-portal-gtk + +* Tue Sep 04 2018 Florian Müllner - 3.30.0-1 +- Update to 3.30.0 + +* Wed Aug 29 2018 Florian Müllner - 3.29.92-1 +- Update to 3.29.92 + +* Mon Aug 20 2018 Florian Müllner - 3.29.91-1 +- Update to 3.29.91 + +* Thu Aug 09 2018 Debarshi Ray - 3.29.90-2 - Remove telepathy-logger and telepathy-glib runtime dependencies -* Wed Aug 01 2018 Stef Walter - 3.28.1-5 -- Remove unneeded libgnome-keyring dependency (#1589078) +* Wed Aug 01 2018 Florian Müllner - 3.29.90-1 +- Update to 3.29.90 -* Wed Aug 01 2018 Charalampos Stratakis - 3.28.1-4 -- BuildRequire python3-devel +* Wed Jul 18 2018 Florian Müllner - 3.29.4-1 +- Update to 3.29.4 -* Sun Apr 29 2018 Adam Williamson - 3.28.1-3 +* Fri Jul 13 2018 Fedora Release Engineering - 3.29.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Thu May 24 2018 Florian Müllner - 3.29.2-1 +- Update to 3.29.2 + +* Wed May 09 2018 Florian Müllner - 3.29.1-3 +- Fix automatic connection to wireless networks without stored secrets + +* Sun Apr 29 2018 Adam Williamson - 3.29.1-2 - Backport fix for password entry modifier key issues (#1569211) +* Wed Apr 25 2018 Florian Müllner - 3.29.1-1 +- Update to 3.29.1 + * Tue Apr 24 2018 Ray Strode - 3.28.1-2 - pull polkit cancel lock up from upstream Resolves: #1568213 @@ -1552,3 +1941,6 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/evolution-calendar.de * Mon Aug 10 2009 Owen Taylor - 2.27.0-1 - Initial version + + +## END: Generated by rpmautospec diff --git a/SOURCES/portal-notify.patch b/portal-notify.patch similarity index 54% rename from SOURCES/portal-notify.patch rename to portal-notify.patch index 98a40a4..33b27ad 100644 --- a/SOURCES/portal-notify.patch +++ b/portal-notify.patch @@ -1,4 +1,4 @@ -From 6238062c4be992e64c9aa227c8cb3b9385a9778f Mon Sep 17 00:00:00 2001 +From d77ed9ad5fdadcdefcc41fecf8200bd2bf47282d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Wed, 12 Jun 2024 13:13:41 +0200 Subject: [PATCH 1/3] network: Split out CaptivePortalHandler class @@ -7,19 +7,29 @@ The handling of captive portals is going to be extended a bit, so split out a proper class instead of mixing it in with the indicator code. --- - js/ui/status/network.js | 154 ++++++++++++++++++++++------------------ - 1 file changed, 84 insertions(+), 70 deletions(-) + js/ui/status/network.js | 151 +++++++++++++++++++++++----------------- + 1 file changed, 87 insertions(+), 64 deletions(-) diff --git a/js/ui/status/network.js b/js/ui/status/network.js -index ef04f7f3dd..67e8f36397 100644 +index 404733b74c..d34e947073 100644 --- a/js/ui/status/network.js +++ b/js/ui/status/network.js -@@ -1658,6 +1658,78 @@ var DeviceCategory = class extends PopupMenu.PopupMenuSection { - } - }; +@@ -14,6 +14,7 @@ import * as Main from '../main.js'; + import * as PopupMenu from '../popupMenu.js'; + import * as MessageTray from '../messageTray.js'; + import * as ModemManager from '../../misc/modemManager.js'; ++import * as Signals from '../../misc/signals.js'; + import * as Util from '../../misc/util.js'; -+class CaptivePortalHandler { + import {Spinner} from '../animation.js'; +@@ -1944,12 +1945,84 @@ class NMModemToggle extends NMDeviceToggle { + } + }); + ++class CaptivePortalHandler extends Signals.EventEmitter { + constructor(checkUri) { ++ super(); ++ + this._checkUri = checkUri; + this._connectivityQueue = new Set(); + this._portalHelperProxy = null; @@ -29,12 +39,12 @@ index ef04f7f3dd..67e8f36397 100644 + if (this._connectivityQueue.has(path)) + return; + -+ this._launchPortalHelper(path); ++ this._launchPortalHelper(path).catch(logError); + } + + removeConnection(path) { -+ if (this._connectivityQueue.delete(path) && this._portalHelperProxy) -+ this._portalHelperProxy.CloseRemote(path); ++ if (this._connectivityQueue.delete(path)) ++ this._portalHelperProxy?.CloseAsync(path); + } + + _portalHelperDone(parameters) { @@ -54,48 +64,53 @@ index ef04f7f3dd..67e8f36397 100644 + } + } + -+ _launchPortalHelper(path) { ++ async _launchPortalHelper(path) { + const timestamp = global.get_current_time(); -+ if (this._portalHelperProxy) { -+ this._portalHelperProxy.AuthenticateRemote(path, this._checkUri, timestamp); -+ } else { -+ new PortalHelperProxy(Gio.DBus.session, -+ 'org.gnome.Shell.PortalHelper', -+ '/org/gnome/Shell/PortalHelper', -+ (proxy, error) => { -+ if (error) { -+ log(`Error launching the portal helper: ${e.message}`); -+ return; -+ } -+ -+ this._portalHelperProxy = proxy; -+ this._portalHelperProxy.connectSignal('Done', -+ (proxy, emitter, params) => { -+ this._portalHelperDone(params); -+ }); -+ this._portalHelperProxy.AuthenticateRemote(path, this._checkUri, timestamp); ++ if (!this._portalHelperProxy) { ++ this._portalHelperProxy = new Gio.DBusProxy({ ++ g_connection: Gio.DBus.session, ++ g_name: 'org.gnome.Shell.PortalHelper', ++ g_object_path: '/org/gnome/Shell/PortalHelper', ++ g_interface_name: PortalHelperInfo.name, ++ g_interface_info: PortalHelperInfo, ++ }); ++ this._portalHelperProxy.connectSignal('Done', ++ (proxy, emitter, params) => { ++ this._portalHelperDone(params); + }); ++ ++ try { ++ await this._portalHelperProxy.init_async( ++ GLib.PRIORITY_DEFAULT, null); ++ } catch (e) { ++ console.error(`Error launching the portal helper: ${e.message}`); ++ } + } + ++ this._portalHelperProxy?.AuthenticateAsync(path, this._checkUri, timestamp).catch(logError); + this._connectivityQueue.add(path); + } + + clear() { -+ if (this._portalHelperProxy) { -+ for (const item of this._connectivityQueue) -+ this._portalHelperProxy.CloseRemote(item); -+ } ++ for (const item of this._connectivityQueue) ++ this._portalHelperProxy?.CloseAsync(item); + this._connectivityQueue.clear(); + } +} -+Signals.addSignalMethods(CaptivePortalHandler.prototype); + - var NMApplet = class extends PanelMenu.SystemIndicator { - constructor() { - super(); -@@ -1713,6 +1785,16 @@ var NMApplet = class extends PanelMenu.SystemIndicator { - this._vpnSection.connect('icon-changed', this._updateIcon.bind(this)); - this.menu.addMenuItem(this._vpnSection.item); + export const Indicator = GObject.registerClass( + class Indicator extends SystemIndicator { + _init() { + super._init(); + +- this._connectivityQueue = new Set(); ++ this._portalHandler = null; + + this._mainConnection = null; + +@@ -2004,6 +2077,16 @@ class Indicator extends SystemIndicator { + this, 'visible', + GObject.BindingFlags.SYNC_CREATE); + const {connectivityCheckUri} = this._client; + this._portalHandler = new CaptivePortalHandler(connectivityCheckUri); @@ -107,94 +122,87 @@ index ef04f7f3dd..67e8f36397 100644 + } catch (e) { } + }); + - this._readConnections(); - this._readDevices(); - this._syncNMState(); -@@ -2029,54 +2111,10 @@ var NMApplet = class extends PanelMenu.SystemIndicator { - this._syncConnectivity(); + this._client.connectObject( + 'notify::primary-connection', () => this._syncMainConnection(), + 'notify::activating-connection', () => this._syncMainConnection(), +@@ -2066,42 +2149,10 @@ class Indicator extends SystemIndicator { + this._notification?.destroy(); } - _flushConnectivityQueue() { -- if (this._portalHelperProxy) { -- for (let item of this._connectivityQueue) -- this._portalHelperProxy.CloseRemote(item); -- } -- -- this._connectivityQueue = []; +- for (let item of this._connectivityQueue) +- this._portalHelperProxy?.CloseAsync(item); +- this._connectivityQueue.clear(); - } - - _closeConnectivityCheck(path) { -- let index = this._connectivityQueue.indexOf(path); -- -- if (index >= 0) { -- if (this._portalHelperProxy) -- this._portalHelperProxy.CloseRemote(path); -- -- this._connectivityQueue.splice(index, 1); -- } +- if (this._connectivityQueue.delete(path)) +- this._portalHelperProxy?.CloseAsync(path); - } - -- _portalHelperDone(proxy, emitter, parameters) { +- async _portalHelperDone(parameters) { - let [path, result] = parameters; - -- if (result == PortalHelperResult.CANCELLED) { +- if (result === PortalHelperResult.CANCELLED) { - // Keep the connection in the queue, so the user is not - // spammed with more logins until we next flush the queue, -- // which will happen once he chooses a better connection +- // which will happen once they choose a better connection - // or we get to full connectivity through other means -- } else if (result == PortalHelperResult.COMPLETED) { +- } else if (result === PortalHelperResult.COMPLETED) { - this._closeConnectivityCheck(path); -- return; -- } else if (result == PortalHelperResult.RECHECK) { -- this._client.check_connectivity_async(null, (client, result) => { -- try { -- let state = client.check_connectivity_finish(result); -- if (state >= NM.ConnectivityState.FULL) -- this._closeConnectivityCheck(path); -- } catch(e) { } -- }); +- } else if (result === PortalHelperResult.RECHECK) { +- try { +- const state = await this._client.check_connectivity_async(null); +- if (state >= NM.ConnectivityState.FULL) +- this._closeConnectivityCheck(path); +- } catch (e) { } - } else { -- log('Invalid result from portal helper: ' + result); +- log(`Invalid result from portal helper: ${result}`); - } - } - - _syncConnectivity() { +- async _syncConnectivity() { ++ _syncConnectivity() { if (this._mainConnection == null || - this._mainConnection.state != NM.ActiveConnectionState.ACTIVATED) { + this._mainConnection.state !== NM.ActiveConnectionState.ACTIVATED) { - this._flushConnectivityQueue(); + this._portalHandler.clear(); return; } -@@ -2091,31 +2129,7 @@ var NMApplet = class extends PanelMenu.SystemIndicator { +@@ -2116,35 +2167,7 @@ class Indicator extends SystemIndicator { if (!isPortal || Main.sessionMode.isGreeter) return; - let path = this._mainConnection.get_path(); -- for (let item of this._connectivityQueue) { -- if (item == path) -- return; -- } +- if (this._connectivityQueue.has(path)) +- return; - - let timestamp = global.get_current_time(); -- if (this._portalHelperProxy) { -- this._portalHelperProxy.AuthenticateRemote(path, '', timestamp); -- } else { -- new PortalHelperProxy(Gio.DBus.session, 'org.gnome.Shell.PortalHelper', -- '/org/gnome/Shell/PortalHelper', (proxy, error) => { -- if (error) { -- log('Error launching the portal helper: ' + error); -- return; -- } +- if (!this._portalHelperProxy) { +- this._portalHelperProxy = new Gio.DBusProxy({ +- g_connection: Gio.DBus.session, +- g_name: 'org.gnome.Shell.PortalHelper', +- g_object_path: '/org/gnome/Shell/PortalHelper', +- g_interface_name: PortalHelperInfo.name, +- g_interface_info: PortalHelperInfo, +- }); +- this._portalHelperProxy.connectSignal('Done', +- (proxy, emitter, params) => { +- this._portalHelperDone(params).catch(logError); +- }); - -- this._portalHelperProxy = proxy; -- proxy.connectSignal('Done', this._portalHelperDone.bind(this)); -- -- proxy.AuthenticateRemote(path, '', timestamp); -- }); +- try { +- await this._portalHelperProxy.init_async( +- GLib.PRIORITY_DEFAULT, null); +- } catch (e) { +- console.error(`Error launching the portal helper: ${e.message}`); +- } - } - -- this._connectivityQueue.push(path); +- this._portalHelperProxy?.AuthenticateAsync(path, this._client.connectivity_check_uri, timestamp).catch(logError); +- +- this._connectivityQueue.add(path); + this._portalHandler.addConnection(this._mainConnection.get_path()); } @@ -203,7 +211,7 @@ index ef04f7f3dd..67e8f36397 100644 2.45.2 -From c4cc99ff934e17b9c267022e6f4db25bb666df39 Mon Sep 17 00:00:00 2001 +From cd489e54948e3f2900a1f4e354fd4bb43c62db6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Wed, 12 Jun 2024 13:13:41 +0200 Subject: [PATCH 2/3] status/network: Show notification when detecting captive @@ -220,15 +228,15 @@ launches the portal window when activated. Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/7688 --- - js/ui/status/network.js | 39 +++++++++++++++++++++++++++++++++++---- - 1 file changed, 35 insertions(+), 4 deletions(-) + js/ui/status/network.js | 38 ++++++++++++++++++++++++++++++++++---- + 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/js/ui/status/network.js b/js/ui/status/network.js -index 67e8f36397..3f3158aff8 100644 +index d34e947073..5d1e168fb5 100644 --- a/js/ui/status/network.js +++ b/js/ui/status/network.js -@@ -1662,19 +1662,44 @@ class CaptivePortalHandler { - constructor(checkUri) { +@@ -1951,19 +1951,43 @@ class CaptivePortalHandler extends Signals.EventEmitter { + this._checkUri = checkUri; this._connectivityQueue = new Set(); + this._notifications = new Map(); @@ -241,43 +249,42 @@ index 67e8f36397..3f3158aff8 100644 + if (this._connectivityQueue.has(path) || this._notifications.has(path)) return; -- this._launchPortalHelper(path); -+ const source = new MessageTray.Source( -+ _('System'), -+ 'emblem-system-symbolic'); -+ Main.messageTray.add(source); +- this._launchPortalHelper(path).catch(logError); ++ const source = MessageTray.getSystemSource(); + -+ const notification = new MessageTray.Notification( -+ source, _('Sign Into Wi–Fi Network'), name); ++ const notification = new MessageTray.Notification({ ++ title: _('Sign Into Wi–Fi Network'), ++ body: name, ++ source, ++ }); + notification.connect('activated', + () => this._onNotificationActivated(path).catch(logError)); + notification.connect('destroy', + () => this._notifications.delete(path)); + this._notifications.set(path, notification); -+ source.notify(notification); ++ source.addNotification(notification); } + removeConnection(path) { - if (this._connectivityQueue.delete(path) && this._portalHelperProxy) - this._portalHelperProxy.CloseRemote(path); -+ const notification = this._notifications.get(path); -+ if (notification) -+ notification.destroy(MessageTray.NotificationDestroyedReason.SOURCE_CLOSED); + if (this._connectivityQueue.delete(path)) + this._portalHelperProxy?.CloseAsync(path); ++ this._notifications.get(path)?.destroy( ++ MessageTray.NotificationDestroyedReason.SOURCE_CLOSED); + this._notifications.delete(path); + } + + _onNotificationActivated(path) { -+ this._launchPortalHelper(path); ++ this._launchPortalHelper(path).catch(logError); + + Main.overview.hide(); + Main.panel.closeCalendar(); } _portalHelperDone(parameters) { -@@ -1726,6 +1751,10 @@ class CaptivePortalHandler { - this._portalHelperProxy.CloseRemote(item); - } +@@ -2014,6 +2038,10 @@ class CaptivePortalHandler extends Signals.EventEmitter { + for (const item of this._connectivityQueue) + this._portalHelperProxy?.CloseAsync(item); this._connectivityQueue.clear(); + + for (const n of this._notifications.values()) @@ -285,8 +292,8 @@ index 67e8f36397..3f3158aff8 100644 + this._notifications.clear(); } } - Signals.addSignalMethods(CaptivePortalHandler.prototype); -@@ -2129,7 +2158,9 @@ var NMApplet = class extends PanelMenu.SystemIndicator { + +@@ -2167,7 +2195,9 @@ class Indicator extends SystemIndicator { if (!isPortal || Main.sessionMode.isGreeter) return; @@ -301,7 +308,7 @@ index 67e8f36397..3f3158aff8 100644 2.45.2 -From 3928c3ba5cd79bdcd9092d699af6b086cf00e76f Mon Sep 17 00:00:00 2001 +From 52b8a150dd96086a48ba2ac7668b22e6429767fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Wed, 12 Jun 2024 13:13:41 +0200 Subject: [PATCH 3/3] build: Add option to disable portal-helper @@ -340,10 +347,10 @@ index eff6e4b530..277df017b2 100644 +install_subdir('hicolor', + install_dir: icondir, exclude_files: excluded_icons) diff --git a/data/meson.build b/data/meson.build -index 33edb58c44..decc9fe091 100644 +index 8654dfeca7..ed13b6baea 100644 --- a/data/meson.build +++ b/data/meson.build -@@ -4,7 +4,7 @@ desktop_files = [ +@@ -6,7 +6,7 @@ desktop_files = [ ] service_files = [] @@ -353,10 +360,10 @@ index 33edb58c44..decc9fe091 100644 service_files += 'org.gnome.Shell.PortalHelper.service' endif diff --git a/js/meson.build b/js/meson.build -index 4a572c53ff..ced1311805 100644 +index 4809f82b83..e594e23627 100644 --- a/js/meson.build +++ b/js/meson.build -@@ -7,12 +7,14 @@ js_resources = gnome.compile_resources( +@@ -8,9 +8,11 @@ js_resources = gnome.compile_resources( dependencies: [config_js] ) @@ -374,86 +381,90 @@ index 4a572c53ff..ced1311805 100644 + dependencies: [config_js] + ) +endif - - prefs_resources = gnome.compile_resources( - 'prefs-resources', 'prefs-resources.gresource.xml', diff --git a/js/misc/config.js.in b/js/misc/config.js.in -index 065d7a0a2a..dc14d6d095 100644 +index ad8d46d841..ce319e0f84 100644 --- a/js/misc/config.js.in +++ b/js/misc/config.js.in -@@ -8,6 +8,8 @@ var PACKAGE_VERSION = '@PACKAGE_VERSION@'; - var HAVE_BLUETOOTH = @HAVE_BLUETOOTH@; +@@ -7,6 +7,8 @@ export const PACKAGE_NAME = '@PACKAGE_NAME@'; + export const PACKAGE_VERSION = '@PACKAGE_VERSION@'; /* 1 if networkmanager is available, 0 otherwise */ - var HAVE_NETWORKMANAGER = @HAVE_NETWORKMANAGER@; + export const HAVE_NETWORKMANAGER = @HAVE_NETWORKMANAGER@; +/* 1 if portal helper is enabled, 0 otherwise */ -+var HAVE_PORTAL_HELPER = @HAVE_PORTAL_HELPER@; ++export const HAVE_PORTAL_HELPER = @HAVE_PORTAL_HELPER@; /* gettext package */ - var GETTEXT_PACKAGE = '@GETTEXT_PACKAGE@'; + export const GETTEXT_PACKAGE = '@GETTEXT_PACKAGE@'; /* locale dir */ diff --git a/js/misc/meson.build b/js/misc/meson.build -index 5a4871762a..448a61556b 100644 +index 5aceefac42..5fc8ca433f 100644 --- a/js/misc/meson.build +++ b/js/misc/meson.build -@@ -5,6 +5,7 @@ jsconf.set('GETTEXT_PACKAGE', meson.project_name()) +@@ -4,6 +4,7 @@ jsconf.set('PACKAGE_VERSION', meson.project_version()) + jsconf.set('GETTEXT_PACKAGE', meson.project_name()) jsconf.set('LIBMUTTER_API_VERSION', mutter_api_version) - jsconf.set10('HAVE_BLUETOOTH', bt_dep.found()) jsconf.set10('HAVE_NETWORKMANAGER', have_networkmanager) +jsconf.set10('HAVE_PORTAL_HELPER', have_portal_helper) jsconf.set('datadir', datadir) jsconf.set('libexecdir', libexecdir) - jsconf.set('vpndir', vpndir) + diff --git a/js/ui/status/network.js b/js/ui/status/network.js -index 3f3158aff8..b2c6679119 100644 +index 5d1e168fb5..cdc9ba8928 100644 --- a/js/ui/status/network.js +++ b/js/ui/status/network.js -@@ -4,6 +4,7 @@ const Mainloop = imports.mainloop; - const Signals = imports.signals; +@@ -10,6 +10,7 @@ import Polkit from 'gi://Polkit'; + import Shell from 'gi://Shell'; + import St from 'gi://St'; - const Animation = imports.ui.animation; -+const Config = imports.misc.config; - const Main = imports.ui.main; - const PanelMenu = imports.ui.panelMenu; - const PopupMenu = imports.ui.popupMenu; -@@ -1678,7 +1679,7 @@ class CaptivePortalHandler { - const notification = new MessageTray.Notification( - source, _('Sign Into Wi–Fi Network'), name); ++import * as Config from '../../misc/config.js'; + import * as Main from '../main.js'; + import * as PopupMenu from '../popupMenu.js'; + import * as MessageTray from '../messageTray.js'; +@@ -1967,7 +1968,7 @@ class CaptivePortalHandler extends Signals.EventEmitter { + source, + }); notification.connect('activated', - () => this._onNotificationActivated(path).catch(logError)); + () => this._onNotificationActivated(path)); notification.connect('destroy', () => this._notifications.delete(path)); this._notifications.set(path, notification); -@@ -1696,7 +1697,13 @@ class CaptivePortalHandler { +@@ -1984,7 +1985,13 @@ class CaptivePortalHandler extends Signals.EventEmitter { } _onNotificationActivated(path) { -- this._launchPortalHelper(path); +- this._launchPortalHelper(path).catch(logError); + const context = global.create_app_launch_context( + global.get_current_time(), -1); + + if (Config.HAVE_PORTAL_HELPER) -+ this._launchPortalHelper(path, context); ++ this._launchPortalHelper(path, context).catch(logError); + else + Gio.AppInfo.launch_default_for_uri(this._checkUri, context); Main.overview.hide(); Main.panel.closeCalendar(); -@@ -1719,8 +1726,8 @@ class CaptivePortalHandler { +@@ -2007,8 +2014,7 @@ class CaptivePortalHandler extends Signals.EventEmitter { } } -- _launchPortalHelper(path) { +- async _launchPortalHelper(path) { - const timestamp = global.get_current_time(); -+ _launchPortalHelper(path, context) { ++ async _launchPortalHelper(path, context) { + if (!this._portalHelperProxy) { + this._portalHelperProxy = new Gio.DBusProxy({ + g_connection: Gio.DBus.session, +@@ -2030,6 +2036,7 @@ class CaptivePortalHandler extends Signals.EventEmitter { + } + } + + const {timestamp} = context; - if (this._portalHelperProxy) { - this._portalHelperProxy.AuthenticateRemote(path, this._checkUri, timestamp); - } else { + this._portalHelperProxy?.AuthenticateAsync(path, this._checkUri, timestamp).catch(logError); + this._connectivityQueue.add(path); + } diff --git a/meson.build b/meson.build -index 2dd1bbc7a3..7a5e4eb603 100644 +index 035f54732a..4721bd6017 100644 --- a/meson.build +++ b/meson.build -@@ -121,6 +121,11 @@ else +@@ -107,6 +107,11 @@ else have_networkmanager = false endif @@ -462,14 +473,14 @@ index 2dd1bbc7a3..7a5e4eb603 100644 + error('Portal helper requires networkmanager support') +endif + - if get_option('systemd') - libsystemd_dep = dependency('libsystemd') - # XXX: see systemduserunitdir + if get_option('camera_monitor') + libpipewire_dep = dependency('libpipewire-0.3', version: pipewire_req) + have_pipewire = true diff --git a/meson_options.txt b/meson_options.txt -index 853ca98dce..1b8cd778ad 100644 +index 6e83d92f2e..01e0d5803b 100644 --- a/meson_options.txt +++ b/meson_options.txt -@@ -16,6 +16,12 @@ option('networkmanager', +@@ -40,6 +40,12 @@ option('networkmanager', description: 'Enable NetworkManager support' ) @@ -483,13 +494,13 @@ index 853ca98dce..1b8cd778ad 100644 type: 'boolean', value: true, diff --git a/src/meson.build b/src/meson.build -index 2b911d3476..83037af1f8 100644 +index 752104e120..a3bf542480 100644 --- a/src/meson.build +++ b/src/meson.build -@@ -245,7 +245,7 @@ executable('gnome-shell-extension-prefs', +@@ -286,7 +286,7 @@ executable('gnome-shell', 'main.c', + install: true ) - -if have_networkmanager +if have_portal_helper executable('gnome-shell-portal-helper', diff --git a/sources b/sources new file mode 100644 index 0000000..ccc9297 --- /dev/null +++ b/sources @@ -0,0 +1 @@ +SHA512 (gnome-shell-47.alpha.tar.xz) = 72fbd6be1115f7130a0eefaef526181e5bef1a26ef815f4c005606a77e0c50e001e76db588abcea625dccf0eec455e54f88afed76f60e134a3172106790d87fc