From ca1c4b0f9e6ecc0f2dd4ab80264e262423d01896 Mon Sep 17 00:00:00 2001 From: Alexander Weichart Date: Tue, 16 May 2023 13:55:40 +0000 Subject: [PATCH 01/32] window-list: Improve default stylesheet Adjust colors to be more consistent with the current shell look. Part-of: --- extensions/window-list/stylesheet.css | 94 +++++++++++++-------------- 1 file changed, 46 insertions(+), 48 deletions(-) diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css index 87813a42..8950c4ff 100644 --- a/extensions/window-list/stylesheet.css +++ b/extensions/window-list/stylesheet.css @@ -1,115 +1,113 @@ .window-list { - spacing: 2px; - font-size: 10pt; + spacing: 2px; + font-size: 10pt; +} + +.bottom-panel { + background-color: #000000; + border-top-width: 0px; + padding: 2px; } .window-button { - padding: 1px; + padding: 2px, 1px; } .window-button:first-child:ltr { - padding-left: 2px; + padding-left: 2px; } .window-button:last-child:rtl { - padding-right: 2px; + padding-right: 2px; } .window-button-box { - spacing: 4px; + spacing: 4px; } .window-button > StWidget, .window-picker-toggle > StWidget { - color: #bbb; - background-color: black; - border-radius: 2px; - padding: 3px 6px 1px; - box-shadow: inset 1px 1px 4px rgba(255,255,255,0.5); - text-shadow: 1px 1px 4px rgba(0,0,0,0.8); -} - -.window-picker-toggle { - padding: 3px; -} - -.window-picker-toggle > StWidet { - border: 1px solid rgba(255,255,255,0.3); + color: #bbb; + background-color: #1d1d1d; + border-radius: 4px; + padding: 3px 6px 1px; + transition: 100ms ease; } .window-button > StWidget { - -st-natural-width: 18.75em; - max-width: 18.75em; + -st-natural-width: 18.75em; + max-width: 18.75em; } .window-button:hover > StWidget, .window-picker-toggle:hover > StWidget { - color: white; - background-color: #1f1f1f; + color: #fff; + background-color: #303030; } .window-button:active > StWidget, .window-button:focus > StWidget { - box-shadow: inset 2px 2px 4px rgba(255,255,255,0.5); + color: #fff; + background-color: #3f3f3f; } .window-button.focused > StWidget, .window-picker-toggle:checked > StWidget { - color: white; - box-shadow: inset 1px 1px 4px rgba(255,255,255,0.7); + color: #fff; + background-color: #3f3f3f; } .window-button.focused:active > StWidget, .window-picker-toggle:checked:active > StWidget { - box-shadow: inset 2px 2px 4px rgba(255,255,255,0.7); + color: #fff; + background-color: #3f3f3f; } .window-button.minimized > StWidget { - color: #666; - box-shadow: inset -1px -1px 4px rgba(255,255,255,0.5); + color: #666; + background-color: #161616; } .window-button.minimized:active > StWidget { - box-shadow: inset -2px -2px 4px rgba(255,255,255,0.5); + color: #666; + background-color: #161616; } .window-button-icon { - width: 24px; - height: 24px; + width: 24px; + height: 24px; } .window-list-workspace-indicator .status-label-bin { - background-color: rgba(200, 200, 200, .3); - border: 1px solid #cccccc; - padding: 0 3px; - margin: 3px; + background-color: rgba(200, 200, 200, 0.3); + padding: 0 3px; + margin: 3px; } .window-list-workspace-indicator .workspaces-box { - spacing: 3px; - padding: 3px; + spacing: 3px; + padding: 3px; } .window-list-workspace-indicator .workspace { - border: 2px solid #000; - width: 52px; - border-radius: 4px; - background-color: #595959; + width: 52px; + border-radius: 4px; + background-color: #1e1e1e; } .window-list-workspace-indicator .workspace.active { - border-color: #fff; + background-color: #3f3f3f; } .window-list-window-preview { - background-color: #bebebe; - border: 1px solid #828282; + background-color: #bebebe; + border-radius: 1px; } .window-list-window-preview.active { - background-color: #d4d4d4; + background-color: #d4d4d4; } .notification { - font-weight: normal; + font-weight: normal; } From f6b6049bc59137274b99d4b6d2e95b61e2720c47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Wed, 22 Mar 2023 15:25:19 +0100 Subject: [PATCH 02/32] classic: Use light color scheme instead of classic styling gnome-shell now includes a light variant, and supports switching between dark- and light styling at runtime. That means we no longer have to build our own stylesheet, and can instead just instruct gnome-shell to always use the light style in the classic session. Part-of: --- .gitlab-ci.yml | 2 - .gitmodules | 3 - data/classic.json.in | 2 +- data/gnome-classic-high-contrast.css | 5 -- data/gnome-classic.scss | 95 ---------------------------- data/gnome-shell-sass | 1 - data/meson.build | 63 ------------------ meson.build | 1 - meson/generate-stylesheets.py | 13 ---- 9 files changed, 1 insertion(+), 184 deletions(-) delete mode 100644 .gitmodules delete mode 100644 data/gnome-classic-high-contrast.css delete mode 100644 data/gnome-classic.scss delete mode 160000 data/gnome-shell-sass delete mode 100644 meson/generate-stylesheets.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a53e93fe..b1562b3b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -132,8 +132,6 @@ fedora-build: stage: build needs: - build-fedora-container - variables: - GIT_SUBMODULE_STRATEGY: normal script: - meson setup build --werror -Dextension_set=all -Dclassic_mode=true - meson compile -C build diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 8703c71d..00000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "data/gnome-shell-sass"] - path = data/gnome-shell-sass - url = https://gitlab.gnome.org/GNOME/gnome-shell-sass.git diff --git a/data/classic.json.in b/data/classic.json.in index 41976b69..601a8995 100644 --- a/data/classic.json.in +++ b/data/classic.json.in @@ -1,6 +1,6 @@ { "parentMode": "user", - "stylesheetName": "gnome-classic.css", + "colorScheme": "force-light", "hasOverview": false, "showWelcomeDialog": false, "enabledExtensions": [@CLASSIC_EXTENSIONS@], diff --git a/data/gnome-classic-high-contrast.css b/data/gnome-classic-high-contrast.css deleted file mode 100644 index 7e4e7712..00000000 --- a/data/gnome-classic-high-contrast.css +++ /dev/null @@ -1,5 +0,0 @@ -@import url("gnome-classic.css"); - -stage { - -st-icon-style: symbolic; -} diff --git a/data/gnome-classic.scss b/data/gnome-classic.scss deleted file mode 100644 index 33399f86..00000000 --- a/data/gnome-classic.scss +++ /dev/null @@ -1,95 +0,0 @@ -/* Use the gnome-shell theme, but with light colors */ -$variant: 'light'; - -@import "gnome-shell-sass/_colors"; //use gtk colors -@import "gnome-shell-sass/_drawing"; -@import "gnome-shell-sass/_common"; -@import "gnome-shell-sass/_widgets"; - -/* Overrides */ - -#panel, #panel.solid { - font-weight: normal; - background-color: $bg_color; - background-gradient-direction: vertical; - background-gradient-end: darken($bg_color,5%); - border-top-color: #666; /* we don't support non-uniform border-colors and - use the top border color for any border, so we - need to set it even if all we want is a bottom - border */ - border-bottom: 1px solid #666; - app-icon-bottom-clip: 0px; - &:overview { - background-color: #000; - background-gradient-end: #000; - border-top-color: #000; - border-bottom: 1px solid #000; - .panel-button { color: #fff; } - } - - .panel-button { - -natural-hpadding: 8px; - -minimum-hpadding: 4px; - font-weight: normal; - color: $fg_color; - text-shadow: none; - transition-duration: 0ms; - border: 0; - border-radius: 0px; - - &.clock-display { - .clock { - transition-duration: 0ms; - border: 0; - border-radius: 0px; - } - } - - &:hover { - color: lighten($fg_color,10%); - text-shadow: none; - & .system-status-icon { icon-shadow: none; } - } - &:active, &:overview, &:focus, &:checked { - // Trick due to St limitations. It needs a background to draw - // a box-shadow - background-color: $selected_bg_color; - color: $selected_fg_color; - box-shadow: none; - & > .system-status-icon { icon-shadow: none; } - } - - .app-menu-icon { width: 0; height: 0; margin: 0; } // shell's display:none; :D - - .system-status-icon { - icon-shadow: none; - } - } - - .panel-corner, - .panel-corner:active, - .panel-corner:overview, - .panel-corner:focus { - -panel-corner-radius: 0; - } - &.lock-screen, - &.unlock-screen, - &.login-screen { - background-color: transparentize($bg_color, 0.5); - background-gradient-start: transparentize($bg_color, 0.5); - background-gradient-end: transparentize($bg_color, 0.5); - border-bottom: none; - .panel-button { color: $osd_fg_color; } - } -} - -#appMenu { - spinner-image: url("classic-process-working.svg"); - .panel-status-menu-box { padding: 0; } -} -.tile-preview-left.on-primary, -.tile-preview-right.on-primary, -.tile-preview-left.tile-preview-right.on-primary { - /* keep in sync with -panel-corner-radius */ - border-radius: 0; -} diff --git a/data/gnome-shell-sass b/data/gnome-shell-sass deleted file mode 160000 index adeed6c9..00000000 --- a/data/gnome-shell-sass +++ /dev/null @@ -1 +0,0 @@ -Subproject commit adeed6c9b448521bf044bb153f0f29dc950c33ea diff --git a/data/meson.build b/data/meson.build index b8a72979..2219aa5e 100644 --- a/data/meson.build +++ b/data/meson.build @@ -46,68 +46,5 @@ configure_file( install_dir: modedir ) -theme_sources = files( - 'gnome-shell-sass/_colors.scss', - 'gnome-shell-sass/_common.scss', - 'gnome-shell-sass/_drawing.scss', - 'gnome-shell-sass/_high-contrast-colors.scss', - 'gnome-shell-sass/_widgets.scss', - 'gnome-shell-sass/widgets/_a11y.scss', - 'gnome-shell-sass/widgets/_app-grid.scss', - 'gnome-shell-sass/widgets/_base.scss', - 'gnome-shell-sass/widgets/_buttons.scss', - 'gnome-shell-sass/widgets/_calendar.scss', - 'gnome-shell-sass/widgets/_check-box.scss', - 'gnome-shell-sass/widgets/_corner-ripple.scss', - 'gnome-shell-sass/widgets/_dash.scss', - 'gnome-shell-sass/widgets/_dialogs.scss', - 'gnome-shell-sass/widgets/_entries.scss', - 'gnome-shell-sass/widgets/_hotplug.scss', - 'gnome-shell-sass/widgets/_ibus-popup.scss', - 'gnome-shell-sass/widgets/_keyboard.scss', - 'gnome-shell-sass/widgets/_login-lock.scss', - 'gnome-shell-sass/widgets/_looking-glass.scss', - 'gnome-shell-sass/widgets/_message-list.scss', - 'gnome-shell-sass/widgets/_misc.scss', - 'gnome-shell-sass/widgets/_notifications.scss', - 'gnome-shell-sass/widgets/_osd.scss', - 'gnome-shell-sass/widgets/_overview.scss', - 'gnome-shell-sass/widgets/_panel.scss', - 'gnome-shell-sass/widgets/_popovers.scss', - 'gnome-shell-sass/widgets/_quick-settings.scss', - 'gnome-shell-sass/widgets/_screenshot.scss', - 'gnome-shell-sass/widgets/_scrollbars.scss', - 'gnome-shell-sass/widgets/_search-entry.scss', - 'gnome-shell-sass/widgets/_search-results.scss', - 'gnome-shell-sass/widgets/_slider.scss', - 'gnome-shell-sass/widgets/_switcher-popup.scss', - 'gnome-shell-sass/widgets/_switches.scss', - 'gnome-shell-sass/widgets/_window-picker.scss', - 'gnome-shell-sass/widgets/_workspace-switcher.scss', - 'gnome-shell-sass/widgets/_workspace-thumbnails.scss' -) - -theme_data = [ - 'classic-process-working.svg', - 'gnome-classic-high-contrast.css' -] - -stylesheet = 'gnome-classic.css' -if fs.exists(stylesheet) - install_data(stylesheet, install_dir: themedir) -else - sassc = find_program('sassc', required: true) - custom_target(stylesheet, - input: fs.replace_suffix(stylesheet, '.scss'), - output: stylesheet, - depend_files: theme_sources, - command: [sassc, '-a', '@INPUT@', '@OUTPUT@'], - install: true, - install_dir: themedir - ) -endif - -install_data(theme_data, install_dir: themedir) - classic_override = '00_org.gnome.shell.extensions.classic.gschema.override' install_data(classic_override, install_dir: schemadir) diff --git a/meson.build b/meson.build index f3160208..2eda9e7d 100644 --- a/meson.build +++ b/meson.build @@ -97,7 +97,6 @@ gnome.post_install( glib_compile_schemas: true, ) -meson.add_dist_script('meson/generate-stylesheets.py') meson.add_dist_script('meson/check-version.py', meson.project_version(), 'NEWS') diff --git a/meson/generate-stylesheets.py b/meson/generate-stylesheets.py deleted file mode 100644 index 599d098f..00000000 --- a/meson/generate-stylesheets.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python3 - -import os -from pathlib import PurePath -import subprocess - -sourceroot = os.environ.get('MESON_SOURCE_ROOT') -distroot = os.environ.get('MESON_DIST_ROOT') - -stylesheet_path = PurePath('data/gnome-classic.css') -src = PurePath(sourceroot, stylesheet_path.with_suffix('.scss')) -dst = PurePath(distroot, stylesheet_path) -subprocess.run(['sassc', '-a', src, dst], check=True) From 904ead1fb1e89c8775349c238374a3aa67532f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Wed, 22 Mar 2023 01:30:31 +0100 Subject: [PATCH 03/32] window-list: Replace classic- with light style Now that classic styling is based on color scheme instead of a dedicated "classic" stylesheet, we should do the same for extension styling, with the bonus that it also works with the regular appearance setting outside the classic session. Part-of: --- extensions/window-list/meson.build | 9 ++++----- .../window-list/{stylesheet.css => stylesheet-dark.css} | 0 .../window-list/{classic.css => stylesheet-light.css} | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) rename extensions/window-list/{stylesheet.css => stylesheet-dark.css} (100%) rename extensions/window-list/{classic.css => stylesheet-light.css} (97%) diff --git a/extensions/window-list/meson.build b/extensions/window-list/meson.build index 599f45e1..43cf1193 100644 --- a/extensions/window-list/meson.build +++ b/extensions/window-list/meson.build @@ -3,11 +3,10 @@ extension_data += configure_file( output: metadata_name, configuration: metadata_conf ) -extension_data += files('stylesheet.css') +extension_data += files( + 'stylesheet-dark.css', + 'stylesheet-light.css' +) extension_sources += files('prefs.js', 'windowPicker.js', 'workspaceIndicator.js') extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml') - -if classic_mode_enabled - extension_data += files('classic.css') -endif diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet-dark.css similarity index 100% rename from extensions/window-list/stylesheet.css rename to extensions/window-list/stylesheet-dark.css diff --git a/extensions/window-list/classic.css b/extensions/window-list/stylesheet-light.css similarity index 97% rename from extensions/window-list/classic.css rename to extensions/window-list/stylesheet-light.css index 375a33e1..30843fc5 100644 --- a/extensions/window-list/classic.css +++ b/extensions/window-list/stylesheet-light.css @@ -1,4 +1,4 @@ -@import url("stylesheet.css"); +@import url("stylesheet-dark.css"); #panel.bottom-panel { border-top-width: 1px; From ced3c94dfa6efa82c3c2a48b25523f7c03dcbd09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Wed, 26 Apr 2023 14:44:27 +0200 Subject: [PATCH 04/32] classic: Account for removal of app menu We no longer include the app menu in the regular GNOME session, we shouldn't bring it back in Classic (not least because there never was a similar menu in GNOME 2). Part-of: --- data/classic.json.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/classic.json.in b/data/classic.json.in index 601a8995..f4cad60b 100644 --- a/data/classic.json.in +++ b/data/classic.json.in @@ -4,7 +4,7 @@ "hasOverview": false, "showWelcomeDialog": false, "enabledExtensions": [@CLASSIC_EXTENSIONS@], - "panel": { "left": ["appMenu"], + "panel": { "left": [], "center": [], "right": ["a11y", "keyboard", "dateMenu", "quickSettings"] } From 61a260bc94ce5db4c67c66d82d65aebf74a8767b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sat, 27 May 2023 00:44:26 +0200 Subject: [PATCH 05/32] places-menu: Account for app menu removal The app menu has been removed from the top bar, so we can no longer base our own indicator position on it. Part-of: --- extensions/places-menu/extension.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/places-menu/extension.js b/extensions/places-menu/extension.js index f71460c7..7024ee30 100644 --- a/extensions/places-menu/extension.js +++ b/extensions/places-menu/extension.js @@ -149,7 +149,7 @@ let _indicator; function enable() { _indicator = new PlacesMenu(); - let pos = Main.sessionMode.panel.left.indexOf('appMenu'); + let pos = Main.sessionMode.panel.left.length; if ('apps-menu' in Main.panel.statusArea) pos++; Main.panel.addToStatusArea('places-menu', _indicator, pos, 'left'); From 22b9f888fbe95fcabe04e522c5f279700105f051 Mon Sep 17 00:00:00 2001 From: Arik W Date: Fri, 21 Apr 2023 12:33:00 +0300 Subject: [PATCH 06/32] window-list: Add tooltip for long window titles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a tooltip feature to the window buttons. If a button’s label is too long to fit, a tooltip will show the complete content when the user hovers over the button. Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/170 Part-of: --- extensions/window-list/extension.js | 75 +++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js index 1f4a22f3..39bac0fc 100644 --- a/extensions/window-list/extension.js +++ b/extensions/window-list/extension.js @@ -16,6 +16,9 @@ const _ = ExtensionUtils.gettext; const ICON_TEXTURE_SIZE = 24; const DND_ACTIVATE_TIMEOUT = 500; +const TOOLTIP_OFFSET = 6; +const TOOLTIP_ANIMATION_TIME = 150; + const GroupingMode = { NEVER: 0, AUTO: 1, @@ -224,6 +227,12 @@ class BaseButton extends St.Button { 'window-left-monitor', this._windowEnteredOrLeftMonitor.bind(this)); } + + this._tooltip = new Tooltip(this, { + style_class: 'dash-label', + visible: false, + }); + Main.uiGroup.add_child(this._tooltip); } get active() { @@ -391,6 +400,8 @@ class BaseButton extends St.Button { if (this._windowLeftMonitorId) global.display.disconnect(this._windowLeftMonitorId); this._windowLeftMonitorId = 0; + + this._tooltip.destroy(); } } @@ -1205,6 +1216,70 @@ class Extension { } } +class Tooltip extends St.Label { + static { + GObject.registerClass(this); + } + + constructor(widget, params) { + super(params); + + this._widget = widget; + + this._widget.connect('notify::hover', () => { + if (this._widget.hover) + this.open(); + else + this.close(); + }); + } + + open() { + const buttonTitleWidget = this._widget.label_actor; + const [, , preferredTitleWidth] = buttonTitleWidget.get_preferred_size(); + const maxTitleWidth = buttonTitleWidget.allocation.get_width(); + const isTitleFullyShown = preferredTitleWidth <= maxTitleWidth; + + if (isTitleFullyShown) + return; + + this.set({ + text: this._widget.label_actor.get_text(), + visible: true, + opacity: 0, + }); + + const [stageX, stageY] = this._widget.get_transformed_position(); + const thumbWidth = this._widget.allocation.get_width(); + const tipWidth = this.width; + const tipHeight = this.height; + const xOffset = Math.floor((thumbWidth - tipWidth) / 2); + const monitor = Main.layoutManager.findMonitorForActor(this); + const x = Math.clamp( + stageX + xOffset, + monitor.x, + monitor.x + monitor.width - tipWidth); + const y = stageY - tipHeight - TOOLTIP_OFFSET; + this.set_position(x, y); + + this.ease({ + opacity: 255, + duration: TOOLTIP_ANIMATION_TIME, + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + onComplete: () => (this.visible = this._widget.hover), + }); + } + + close() { + this.ease({ + opacity: 0, + duration: TOOLTIP_ANIMATION_TIME, + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + onComplete: () => (this.visible = this._widget.hover), + }); + } +} + /** * @returns {Extension} - the extension's state object */ From b7895ad956248bbfb6622ed5838f8bc152401032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Fri, 2 Jun 2023 14:37:30 +0200 Subject: [PATCH 07/32] extensions: Add new light-style extension Now that gnome-shell supports a light style, people may want to use it without forcing all apps to be light. Add a small extension that switches the default to light, so the shell follows the regular "dark style" preference. Part-of: --- extensions/light-style/extension.js | 45 +++++++++++++++++++++++++ extensions/light-style/meson.build | 5 +++ extensions/light-style/metadata.json.in | 10 ++++++ meson.build | 1 + 4 files changed, 61 insertions(+) create mode 100644 extensions/light-style/extension.js create mode 100644 extensions/light-style/meson.build create mode 100644 extensions/light-style/metadata.json.in diff --git a/extensions/light-style/extension.js b/extensions/light-style/extension.js new file mode 100644 index 00000000..9aaea481 --- /dev/null +++ b/extensions/light-style/extension.js @@ -0,0 +1,45 @@ +/* exported init */ +/* + * 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 of the License, 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 . + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +const {St} = imports.gi; + +const Main = imports.ui.main; + +class Extension { + constructor() { + this._savedColorScheme = Main.sessionMode.colorScheme; + } + + _updateColorScheme(scheme) { + Main.sessionMode.colorScheme = scheme; + St.Settings.get().notify('color-scheme'); + } + + enable() { + this._updateColorScheme('prefer-light'); + } + + disable() { + this._updateColorScheme(this._savedColorScheme); + } +} + +/** */ +function init() { + return new Extension(); +} diff --git a/extensions/light-style/meson.build b/extensions/light-style/meson.build new file mode 100644 index 00000000..48504f63 --- /dev/null +++ b/extensions/light-style/meson.build @@ -0,0 +1,5 @@ +extension_data += configure_file( + input: metadata_name + '.in', + output: metadata_name, + configuration: metadata_conf +) diff --git a/extensions/light-style/metadata.json.in b/extensions/light-style/metadata.json.in new file mode 100644 index 00000000..a763a9f9 --- /dev/null +++ b/extensions/light-style/metadata.json.in @@ -0,0 +1,10 @@ +{ +"extension-id": "@extension_id@", +"uuid": "@uuid@", +"settings-schema": "@gschemaname@", +"gettext-domain": "@gettext_domain@", +"name": "Light Style", +"description": "Switch default to light style", +"shell-version": [ "@shell_current@" ], +"url": "@url@" +} diff --git a/meson.build b/meson.build index 2eda9e7d..d7a5dff0 100644 --- a/meson.build +++ b/meson.build @@ -37,6 +37,7 @@ classic_extensions = [ default_extensions = classic_extensions default_extensions += [ 'drive-menu', + 'light-style', 'screenshot-window-sizer', 'windowsNavigator', 'workspace-indicator' From b11f0f16f4cf9bf4d2b1a1c2dbdbbbe5dc879772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sun, 2 Jul 2023 23:24:33 +0200 Subject: [PATCH 08/32] light-style: Always save scheme preference on enable() Disable() should restore the scheme preference that was used when the extension was enabled, not when it was first initialized. Even if it's unlikely to be relevant in practice, let's make sure we save the correct state. Part-of: --- extensions/light-style/extension.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/extensions/light-style/extension.js b/extensions/light-style/extension.js index 9aaea481..f9d35b55 100644 --- a/extensions/light-style/extension.js +++ b/extensions/light-style/extension.js @@ -21,16 +21,13 @@ const {St} = imports.gi; const Main = imports.ui.main; class Extension { - constructor() { - this._savedColorScheme = Main.sessionMode.colorScheme; - } - _updateColorScheme(scheme) { Main.sessionMode.colorScheme = scheme; St.Settings.get().notify('color-scheme'); } enable() { + this._savedColorScheme = Main.sessionMode.colorScheme; this._updateColorScheme('prefer-light'); } From 90031432da2e432cdffdd4ecd7a495512b3092cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Mon, 3 Jul 2023 00:25:03 +0200 Subject: [PATCH 09/32] build: Remove left-over variable We no longer install a separate mode style, so the variable is now unused. Part-of: --- meson.build | 1 - 1 file changed, 1 deletion(-) diff --git a/meson.build b/meson.build index d7a5dff0..5dfe35c8 100644 --- a/meson.build +++ b/meson.build @@ -15,7 +15,6 @@ datadir = get_option('datadir') shelldir = join_paths(datadir, 'gnome-shell') extensiondir = join_paths(shelldir, 'extensions') modedir = join_paths(shelldir, 'modes') -themedir = join_paths(shelldir, 'theme') schemadir = join_paths(datadir, 'glib-2.0', 'schemas') sessiondir = join_paths(datadir, 'gnome-session', 'sessions') From 278d0afc797cd80004d1e57fcdfc61de7eb3a25e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Mon, 3 Jul 2023 00:25:31 +0200 Subject: [PATCH 10/32] Bump version to 45.alpha Update NEWS. Part-of: --- NEWS | 11 +++++++++++ meson.build | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index cab0d150..f7137653 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,14 @@ +45.alpha +======== +* window-list: Modernize default styling [Alexander; !253] +* Replace classic styling with built-in light style [Florian; !254] +* window-list: Add tooltip for long window titles [Arik; !251] +* light-style: New extension [Florian; !256] +* Misc. bug fixes and cleanups [Florian; !255, !257] + +Contributors: + Florian Müllner, Arik W, Alexander Weichart + 44.0 ==== * Bump version diff --git a/meson.build b/meson.build index 5dfe35c8..37c3f0fd 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('gnome-shell-extensions', - version: '44.0', + version: '45.alpha', meson_version: '>= 0.58.0', license: 'GPL2+' ) From 18674b2e3530ad4d1f628ecfa613d900b2dc62ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Thu, 6 Jul 2023 23:55:39 +0200 Subject: [PATCH 11/32] lint: Migrate eslint-plugin-jsdoc rule Migrate a removed jsdoc, copied from the corresponding gnome-shell change. Part-of: --- lint/eslintrc-gjs.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lint/eslintrc-gjs.yml b/lint/eslintrc-gjs.yml index 97e728f9..b1d73946 100644 --- a/lint/eslintrc-gjs.yml +++ b/lint/eslintrc-gjs.yml @@ -68,7 +68,10 @@ rules: jsdoc/check-tag-names: error jsdoc/check-types: error jsdoc/implements-on-classes: error - jsdoc/newline-after-description: error + jsdoc/tag-lines: + - error + - any + - startLines: 1 jsdoc/require-jsdoc: error jsdoc/require-param: error jsdoc/require-param-description: error From 701b14ecbfbe49e743b265894da0810bab08eb9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Fri, 2 Jun 2023 13:12:54 +0200 Subject: [PATCH 12/32] extensions: Use extension class for all extensions This will be the only supported entry point when extension loading switches to dynamic imports, so prepare for that by wrapping the remaining standalone enable()/disable() methods in Extension classes. Part-of: --- extensions/apps-menu/extension.js | 28 +- extensions/auto-move-windows/extension.js | 79 +++--- extensions/drive-menu/extension.js | 31 ++- extensions/launch-new-instance/extension.js | 28 +- .../native-window-placement/extension.js | 155 ++++++----- extensions/places-menu/extension.js | 39 +-- .../screenshot-window-sizer/extension.js | 259 +++++++++--------- extensions/workspace-indicator/extension.js | 31 ++- 8 files changed, 345 insertions(+), 305 deletions(-) diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js index 23da6c08..67ae6e97 100644 --- a/extensions/apps-menu/extension.js +++ b/extensions/apps-menu/extension.js @@ -677,22 +677,26 @@ class ApplicationsButton extends PanelMenu.Button { } } -let appsMenuButton; +class Extension { + constructor() { + ExtensionUtils.initTranslations(); + } -/** */ -function enable() { - appsMenuButton = new ApplicationsButton(); - let index = Main.sessionMode.panel.left.indexOf('activities') + 1; - Main.panel.addToStatusArea('apps-menu', appsMenuButton, index, 'left'); -} + enable() { + this._appsMenuButton = new ApplicationsButton(); + const index = Main.sessionMode.panel.left.indexOf('activities') + 1; + Main.panel.addToStatusArea( + 'apps-menu', this._appsMenuButton, index, 'left'); + } -/** */ -function disable() { - Main.panel.menuManager.removeMenu(appsMenuButton.menu); - appsMenuButton.destroy(); + disable() { + Main.panel.menuManager.removeMenu(this._appsMenuButton.menu); + this._appsMenuButton.destroy(); + delete this._appsMenuButton; + } } /** */ function init() { - ExtensionUtils.initTranslations(); + return new Extension(); } diff --git a/extensions/auto-move-windows/extension.js b/extensions/auto-move-windows/extension.js index 298de536..9362a52e 100644 --- a/extensions/auto-move-windows/extension.js +++ b/extensions/auto-move-windows/extension.js @@ -105,47 +105,46 @@ class WindowMover { } } -let prevCheckWorkspaces; -let winMover; +class Extension { + enable() { + this._prevCheckWorkspaces = Main.wm._workspaceTracker._checkWorkspaces; + Main.wm._workspaceTracker._checkWorkspaces = + this._getCheckWorkspaceOverride(this._prevCheckWorkspaces); + this._windowMover = new WindowMover(); + } + + disable() { + Main.wm._workspaceTracker._checkWorkspaces = this._prevCheckWorkspaces; + this._windowMover.destroy(); + delete this._windowMover; + } + + _getCheckWorkspaceOverride(originalMethod) { + /* eslint-disable no-invalid-this */ + return function () { + const keepAliveWorkspaces = []; + let foundNonEmpty = false; + for (let i = this._workspaces.length - 1; i >= 0; i--) { + if (!foundNonEmpty) { + foundNonEmpty = this._workspaces[i].list_windows().some( + w => !w.is_on_all_workspaces()); + } else if (!this._workspaces[i]._keepAliveId) { + keepAliveWorkspaces.push(this._workspaces[i]); + } + } + + // make sure the original method only removes empty workspaces at the end + keepAliveWorkspaces.forEach(ws => (ws._keepAliveId = 1)); + originalMethod.call(this); + keepAliveWorkspaces.forEach(ws => delete ws._keepAliveId); + + return false; + }; + /* eslint-enable no-invalid-this */ + } +} /** */ function init() { - ExtensionUtils.initTranslations(); -} - -/** - * @returns {bool} - false (used as MetaLater handler) - */ -function myCheckWorkspaces() { - let keepAliveWorkspaces = []; - let foundNonEmpty = false; - for (let i = this._workspaces.length - 1; i >= 0; i--) { - if (!foundNonEmpty) { - foundNonEmpty = this._workspaces[i].list_windows().some( - w => !w.is_on_all_workspaces()); - } else if (!this._workspaces[i]._keepAliveId) { - keepAliveWorkspaces.push(this._workspaces[i]); - } - } - - // make sure the original method only removes empty workspaces at the end - keepAliveWorkspaces.forEach(ws => (ws._keepAliveId = 1)); - prevCheckWorkspaces.call(this); - keepAliveWorkspaces.forEach(ws => delete ws._keepAliveId); - - return false; -} - -/** */ -function enable() { - prevCheckWorkspaces = Main.wm._workspaceTracker._checkWorkspaces; - Main.wm._workspaceTracker._checkWorkspaces = myCheckWorkspaces; - - winMover = new WindowMover(); -} - -/** */ -function disable() { - Main.wm._workspaceTracker._checkWorkspaces = prevCheckWorkspaces; - winMover.destroy(); + return new Extension(); } diff --git a/extensions/drive-menu/extension.js b/extensions/drive-menu/extension.js index 45c854f4..fd98d989 100644 --- a/extensions/drive-menu/extension.js +++ b/extensions/drive-menu/extension.js @@ -212,20 +212,23 @@ class DriveMenu extends PanelMenu.Button { } } +class Extension { + constructor() { + ExtensionUtils.initTranslations(); + } + + enable() { + this._indicator = new DriveMenu(); + Main.panel.addToStatusArea('drive-menu', this._indicator); + } + + disable() { + this._indicator.destroy(); + delete this._indicator; + } +} + /** */ function init() { - ExtensionUtils.initTranslations(); -} - -let _indicator; - -/** */ -function enable() { - _indicator = new DriveMenu(); - Main.panel.addToStatusArea('drive-menu', _indicator); -} - -/** */ -function disable() { - _indicator.destroy(); + return new Extension(); } diff --git a/extensions/launch-new-instance/extension.js b/extensions/launch-new-instance/extension.js index a249cd48..53f2420c 100644 --- a/extensions/launch-new-instance/extension.js +++ b/extensions/launch-new-instance/extension.js @@ -1,17 +1,25 @@ -/* exported enable disable */ +/* exported init */ const AppDisplay = imports.ui.appDisplay; -let _activateOriginal = null; +class Extension { + constructor() { + this._appIconProto = AppDisplay.AppIcon.prototype; + this._activateOriginal = this._appIconProto.activate; + } -/** */ -function enable() { - _activateOriginal = AppDisplay.AppIcon.prototype.activate; - AppDisplay.AppIcon.prototype.activate = function () { - _activateOriginal.call(this, 2); - }; + enable() { + const {_activateOriginal} = this; + this._appIconProto.activate = function () { + _activateOriginal.call(this, 2); + }; + } + + disable() { + this._appIconProto.activate = this._activateOriginal; + } } /** */ -function disable() { - AppDisplay.AppIcon.prototype.activate = _activateOriginal; +function init() { + return new Extension(); } diff --git a/extensions/native-window-placement/extension.js b/extensions/native-window-placement/extension.js index b6b662a8..839464e2 100644 --- a/extensions/native-window-placement/extension.js +++ b/extensions/native-window-placement/extension.js @@ -236,75 +236,96 @@ class NaturalLayoutStrategy extends Workspace.LayoutStrategy { } } -let winInjections, workspaceInjections; +class Extension { + constructor() { + this._savedMethods = new Map(); + } -/** */ -function resetState() { - winInjections = { }; - workspaceInjections = { }; + enable() { + const settings = ExtensionUtils.getSettings(); + + const layoutProto = Workspace.WorkspaceLayout.prototype; + const previewProto = WindowPreview.prototype; + + this._overrideMethod(layoutProto, '_createBestLayout', () => { + /* eslint-disable no-invalid-this */ + return function () { + this._layoutStrategy = new NaturalLayoutStrategy({ + monitor: Main.layoutManager.monitors[this._monitorIndex], + }, settings); + return this._layoutStrategy.computeLayout(this._sortedWindows); + }; + /* eslint-enable no-invalid-this */ + }); + + // position window titles on top of windows in overlay + this._overrideMethod(previewProto, '_init', originalMethod => { + /* eslint-disable no-invalid-this */ + return function (...args) { + originalMethod.call(this, ...args); + + if (!settings.get_boolean('window-captions-on-top')) + return; + + const alignConstraint = this._title.get_constraints().find( + c => c.align_axis && c.align_axis === Clutter.AlignAxis.Y_AXIS); + alignConstraint.factor = 0; + + const bindConstraint = this._title.get_constraints().find( + c => c.coordinate && c.coordinate === Clutter.BindCoordinate.Y); + bindConstraint.offset = 0; + }; + /* eslint-enable no-invalid-this */ + }); + + this._overrideMethod(previewProto, '_adjustOverlayOffsets', originalMethod => { + /* eslint-disable no-invalid-this */ + return function (...args) { + originalMethod.call(this, ...args); + + if (settings.get_boolean('window-captions-on-top')) + this._title.translation_y = -this._title.translation_y; + }; + /* eslint-enable no-invalid-this */ + }); + } + + disable() { + this._restoreMethods(); + global.stage.queue_relayout(); + } + + _saveMethod(prototype, methodName) { + let map = this._savedMethods.get(prototype); + if (!map) { + map = new Map(); + this._savedMethods.set(prototype, map); + } + + const originalMethod = prototype[methodName]; + map.set(methodName, originalMethod); + return originalMethod; + } + + _overrideMethod(prototype, methodName, createOverrideFunc) { + const originalMethod = this._saveMethod(prototype, methodName); + prototype[methodName] = createOverrideFunc(originalMethod); + } + + _restoreMethods() { + for (const [proto, map] of this._savedMethods) { + for (const [methodName, originalMethod] of map) { + if (originalMethod === undefined) + delete proto[methodName]; + else + proto[methodName] = originalMethod; + } + } + this._savedMethods.clear(); + } } /** */ -function enable() { - resetState(); - - let settings = ExtensionUtils.getSettings(); - - workspaceInjections['_createBestLayout'] = Workspace.WorkspaceLayout.prototype._createBestLayout; - Workspace.WorkspaceLayout.prototype._createBestLayout = function (_area) { - this._layoutStrategy = new NaturalLayoutStrategy({ - monitor: Main.layoutManager.monitors[this._monitorIndex], - }, settings); - return this._layoutStrategy.computeLayout(this._sortedWindows); - }; - - // position window titles on top of windows in overlay - winInjections['_init'] = WindowPreview.prototype._init; - WindowPreview.prototype._init = function (...args) { - winInjections['_init'].call(this, ...args); - - if (!settings.get_boolean('window-captions-on-top')) - return; - - const alignConstraint = this._title.get_constraints().find( - c => c.align_axis && c.align_axis === Clutter.AlignAxis.Y_AXIS); - alignConstraint.factor = 0; - - const bindConstraint = this._title.get_constraints().find( - c => c.coordinate && c.coordinate === Clutter.BindCoordinate.Y); - bindConstraint.offset = 0; - }; - winInjections['_adjustOverlayOffsets'] = - WindowPreview.prototype._adjustOverlayOffsets; - WindowPreview.prototype._adjustOverlayOffsets = function (...args) { - winInjections['_adjustOverlayOffsets'].call(this, ...args); - - if (settings.get_boolean('window-captions-on-top')) - this._title.translation_y = -this._title.translation_y; - }; -} - -/** - * @param {object} object - object that was modified - * @param {object} injection - the map of previous injections - * @param {string} name - the @injection key that should be removed - */ -function removeInjection(object, injection, name) { - if (injection[name] === undefined) - delete object[name]; - else - object[name] = injection[name]; -} - -/** */ -function disable() { - var i; - - for (i in workspaceInjections) - removeInjection(Workspace.WorkspaceLayout.prototype, workspaceInjections, i); - for (i in winInjections) - removeInjection(WindowPreview.prototype, winInjections, i); - - global.stage.queue_relayout(); - resetState(); +function init() { + return new Extension(); } diff --git a/extensions/places-menu/extension.js b/extensions/places-menu/extension.js index 7024ee30..d7fdab37 100644 --- a/extensions/places-menu/extension.js +++ b/extensions/places-menu/extension.js @@ -138,24 +138,27 @@ class PlacesMenu extends PanelMenu.Button { } } +class Extension { + constructor() { + ExtensionUtils.initTranslations(); + } + + enable() { + this._indicator = new PlacesMenu(); + + let pos = Main.sessionMode.panel.left.length; + if ('apps-menu' in Main.panel.statusArea) + pos++; + Main.panel.addToStatusArea('places-menu', this._indicator, pos, 'left'); + } + + disable() { + this._indicator.destroy(); + delete this._indicator; + } +} + /** */ function init() { - ExtensionUtils.initTranslations(); -} - -let _indicator; - -/** */ -function enable() { - _indicator = new PlacesMenu(); - - let pos = Main.sessionMode.panel.left.length; - if ('apps-menu' in Main.panel.statusArea) - pos++; - Main.panel.addToStatusArea('places-menu', _indicator, pos, 'left'); -} - -/** */ -function disable() { - _indicator.destroy(); + return new Extension(); } diff --git a/extensions/screenshot-window-sizer/extension.js b/extensions/screenshot-window-sizer/extension.js index d59ec3f3..97354474 100644 --- a/extensions/screenshot-window-sizer/extension.js +++ b/extensions/screenshot-window-sizer/extension.js @@ -26,146 +26,145 @@ const Main = imports.ui.main; const MESSAGE_FADE_TIME = 2000; -let text; +class Extension { + SIZES = [ + [624, 351], + [800, 450], + [1024, 576], + [1200, 675], + [1600, 900], + [360, 654], // Phone portrait maximized + [720, 360], // Phone landscape fullscreen + ]; -/** */ -function hideMessage() { - text.destroy(); - text = null; -} - -/** - * @param {string} message - the message to flash - */ -function flashMessage(message) { - if (!text) { - text = new St.Label({style_class: 'screenshot-sizer-message'}); - Main.uiGroup.add_actor(text); - } - - text.remove_all_transitions(); - text.text = message; - - text.opacity = 255; - - let monitor = Main.layoutManager.primaryMonitor; - text.set_position( - monitor.x + Math.floor(monitor.width / 2 - text.width / 2), - monitor.y + Math.floor(monitor.height / 2 - text.height / 2)); - - text.ease({ - opacity: 0, - duration: MESSAGE_FADE_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: hideMessage, - }); -} - -let SIZES = [ - [624, 351], - [800, 450], - [1024, 576], - [1200, 675], - [1600, 900], - [360, 654], // Phone portrait maximized - [720, 360], // Phone landscape fullscreen -]; - -/** - * @param {Meta.Display} display - the display - * @param {Meta.Window=} window - for per-window bindings, the window - * @param {Meta.KeyBinding} binding - the key binding - */ -function cycleScreenshotSizes(display, window, binding) { - // Probably this isn't useful with 5 sizes, but you can decrease instead - // of increase by holding down shift. - let modifiers = binding.get_modifiers(); - let backwards = (modifiers & Meta.VirtualModifier.SHIFT_MASK) !== 0; - - // Unmaximize first - if (window.get_maximized() !== 0) - window.unmaximize(Meta.MaximizeFlags.BOTH); - - let workArea = window.get_work_area_current_monitor(); - let outerRect = window.get_frame_rect(); - - // Double both axes if on a hidpi display - let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; - let scaledSizes = SIZES.map(size => size.map(wh => wh * scaleFactor)) - .filter(([w, h]) => w <= workArea.width && h <= workArea.height); - - // Find the nearest 16:9 size for the current window size - let nearestIndex; - let nearestError; - - for (let i = 0; i < scaledSizes.length; i++) { - let [width, height] = scaledSizes[i]; - - // get the best initial window size - let error = Math.abs(width - outerRect.width) + Math.abs(height - outerRect.height); - if (nearestIndex === undefined || error < nearestError) { - nearestIndex = i; - nearestError = error; + _flashMessage(message) { + if (!this._text) { + this._text = new St.Label({style_class: 'screenshot-sizer-message'}); + Main.uiGroup.add_actor(this._text); } + + this._text.remove_all_transitions(); + this._text.text = message; + + this._text.opacity = 255; + + const monitor = Main.layoutManager.primaryMonitor; + this._text.set_position( + monitor.x + Math.floor(monitor.width / 2 - this._text.width / 2), + monitor.y + Math.floor(monitor.height / 2 - this._text.height / 2)); + + this._text.ease({ + opacity: 0, + duration: MESSAGE_FADE_TIME, + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + onComplete: () => this._hideMessage(), + }); } - // get the next size up or down from ideal - let newIndex = (nearestIndex + (backwards ? -1 : 1)) % scaledSizes.length; - let [newWidth, newHeight] = scaledSizes[newIndex]; + _hideMessage() { + this._text.destroy(); + delete this._text; + } - // Push the window onscreen if it would be resized offscreen - let newX = outerRect.x; - let newY = outerRect.y; - if (newX + newWidth > workArea.x + workArea.width) - newX = Math.max(workArea.x + workArea.width - newWidth); - if (newY + newHeight > workArea.y + workArea.height) - newY = Math.max(workArea.y + workArea.height - newHeight); + /** + * @param {Meta.Display} display - the display + * @param {Meta.Window=} window - for per-window bindings, the window + * @param {Meta.KeyBinding} binding - the key binding + */ + _cycleScreenshotSizes(display, window, binding) { + // Probably this isn't useful with 5 sizes, but you can decrease instead + // of increase by holding down shift. + let modifiers = binding.get_modifiers(); + let backwards = (modifiers & Meta.VirtualModifier.SHIFT_MASK) !== 0; - const id = window.connect('size-changed', () => { - window.disconnect(id); - _notifySizeChange(window); - }); - window.move_resize_frame(true, newX, newY, newWidth, newHeight); -} + // Unmaximize first + if (window.get_maximized() !== 0) + window.unmaximize(Meta.MaximizeFlags.BOTH); -/** - * @param {Meta.Window} window - the window whose size changed - */ -function _notifySizeChange(window) { - const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); - let newOuterRect = window.get_frame_rect(); - let message = '%d×%d'.format( - newOuterRect.width / scaleFactor, - newOuterRect.height / scaleFactor); + let workArea = window.get_work_area_current_monitor(); + let outerRect = window.get_frame_rect(); - // The new size might have been constrained by geometry hints (e.g. for - // a terminal) - in that case, include the actual ratio to the message - // we flash - let actualNumerator = 9 * newOuterRect.width / newOuterRect.height; - if (Math.abs(actualNumerator - 16) > 0.01) - message += ' (%.2f:9)'.format(actualNumerator); + // Double both axes if on a hidpi display + let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; + let scaledSizes = this.SIZES.map(size => size.map(wh => wh * scaleFactor)) + .filter(([w, h]) => w <= workArea.width && h <= workArea.height); - flashMessage(message); + // Find the nearest 16:9 size for the current window size + let nearestIndex; + let nearestError; + + for (let i = 0; i < scaledSizes.length; i++) { + let [width, height] = scaledSizes[i]; + + // get the best initial window size + let error = Math.abs(width - outerRect.width) + Math.abs(height - outerRect.height); + if (nearestIndex === undefined || error < nearestError) { + nearestIndex = i; + nearestError = error; + } + } + + // get the next size up or down from ideal + let newIndex = (nearestIndex + (backwards ? -1 : 1)) % scaledSizes.length; + let [newWidth, newHeight] = scaledSizes[newIndex]; + + // Push the window onscreen if it would be resized offscreen + let newX = outerRect.x; + let newY = outerRect.y; + if (newX + newWidth > workArea.x + workArea.width) + newX = Math.max(workArea.x + workArea.width - newWidth); + if (newY + newHeight > workArea.y + workArea.height) + newY = Math.max(workArea.y + workArea.height - newHeight); + + const id = window.connect('size-changed', () => { + window.disconnect(id); + this._notifySizeChange(window); + }); + window.move_resize_frame(true, newX, newY, newWidth, newHeight); + } + + /** + * @param {Meta.Window} window - the window whose size changed + */ + _notifySizeChange(window) { + const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); + let newOuterRect = window.get_frame_rect(); + let message = '%d×%d'.format( + newOuterRect.width / scaleFactor, + newOuterRect.height / scaleFactor); + + // The new size might have been constrained by geometry hints (e.g. for + // a terminal) - in that case, include the actual ratio to the message + // we flash + let actualNumerator = 9 * newOuterRect.width / newOuterRect.height; + if (Math.abs(actualNumerator - 16) > 0.01) + message += ' (%.2f:9)'.format(actualNumerator); + + this._flashMessage(message); + } + + enable() { + Main.wm.addKeybinding( + 'cycle-screenshot-sizes', + ExtensionUtils.getSettings(), + Meta.KeyBindingFlags.PER_WINDOW, + Shell.ActionMode.NORMAL, + this._cycleScreenshotSizes.bind(this)); + Main.wm.addKeybinding( + 'cycle-screenshot-sizes-backward', + ExtensionUtils.getSettings(), + Meta.KeyBindingFlags.PER_WINDOW | Meta.KeyBindingFlags.IS_REVERSED, + Shell.ActionMode.NORMAL, + this._cycleScreenshotSizes.bind(this)); + } + + disable() { + Main.wm.removeKeybinding('cycle-screenshot-sizes'); + Main.wm.removeKeybinding('cycle-screenshot-sizes-backward'); + } } /** */ -function enable() { - Main.wm.addKeybinding( - 'cycle-screenshot-sizes', - ExtensionUtils.getSettings(), - Meta.KeyBindingFlags.PER_WINDOW, - Shell.ActionMode.NORMAL, - cycleScreenshotSizes); - Main.wm.addKeybinding( - 'cycle-screenshot-sizes-backward', - ExtensionUtils.getSettings(), - Meta.KeyBindingFlags.PER_WINDOW | Meta.KeyBindingFlags.IS_REVERSED, - Shell.ActionMode.NORMAL, - cycleScreenshotSizes); -} - -/** */ -function disable() { - Main.wm.removeKeybinding('cycle-screenshot-sizes'); - Main.wm.removeKeybinding('cycle-screenshot-sizes-backward'); +function init() { + return new Extension(); } diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js index a9b3fd46..f3f1bb4d 100644 --- a/extensions/workspace-indicator/extension.js +++ b/extensions/workspace-indicator/extension.js @@ -454,20 +454,23 @@ class WorkspaceIndicator extends PanelMenu.Button { } } +class Extension { + constructor() { + ExtensionUtils.initTranslations(); + } + + enable() { + this._indicator = new WorkspaceIndicator(); + Main.panel.addToStatusArea('workspace-indicator', this._indicator); + } + + disable() { + this._indicator.destroy(); + delete this._indicator; + } +} + /** */ function init() { - ExtensionUtils.initTranslations(); -} - -let _indicator; - -/** */ -function enable() { - _indicator = new WorkspaceIndicator(); - Main.panel.addToStatusArea('workspace-indicator', _indicator); -} - -/** */ -function disable() { - _indicator.destroy(); + return new Extension(); } From cf007dd4722c6a9d955a1e22f5dbfef3f800b142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Fri, 2 Jun 2023 12:45:30 +0200 Subject: [PATCH 13/32] extensions: Turn extensions into modules As gnome-shell is moving to ESM, it will now load extensions as standard modules instead of using legacy imports. The change boils down to exporting the Extension class as default, but we can also start using standard imports for introspected modules now, so do that at the same time. Part-of: --- extensions/apps-menu/extension.js | 22 +++++++------- extensions/auto-move-windows/extension.js | 10 ++----- extensions/auto-move-windows/prefs.js | 27 ++++++++++------- extensions/drive-menu/extension.js | 14 ++++----- extensions/launch-new-instance/extension.js | 8 +---- extensions/light-style/extension.js | 10 ++----- .../native-window-placement/extension.js | 10 ++----- extensions/places-menu/extension.js | 18 ++++-------- extensions/places-menu/placeDisplay.js | 10 +++---- .../screenshot-window-sizer/extension.js | 13 ++++----- extensions/user-theme/extension.js | 19 ++++-------- extensions/user-theme/prefs.js | 29 ++++++++++--------- extensions/user-theme/util.js | 7 ++--- extensions/window-list/extension.js | 23 +++++++-------- extensions/window-list/prefs.js | 27 ++++++++--------- extensions/window-list/windowPicker.js | 14 +++++---- extensions/window-list/workspaceIndicator.js | 11 ++++--- extensions/windowsNavigator/extension.js | 15 ++++------ extensions/workspace-indicator/extension.js | 15 ++++------ extensions/workspace-indicator/prefs.js | 29 +++++++++++-------- lint/eslintrc-shell.yml | 2 ++ 21 files changed, 149 insertions(+), 184 deletions(-) diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js index 67ae6e97..2e4738c5 100644 --- a/extensions/apps-menu/extension.js +++ b/extensions/apps-menu/extension.js @@ -1,9 +1,14 @@ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* exported init enable disable */ - -const { - Atk, Clutter, Gio, GLib, GMenu, GObject, Gtk, Meta, Shell, St, -} = imports.gi; +import Atk from 'gi://Atk'; +import Clutter from 'gi://Clutter'; +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; +import GMenu from 'gi://GMenu'; +import GObject from 'gi://GObject'; +import Gtk from 'gi://Gtk'; +import Meta from 'gi://Meta'; +import Shell from 'gi://Shell'; +import St from 'gi://St'; const {EventEmitter} = imports.misc.signals; const DND = imports.ui.dnd; @@ -677,7 +682,7 @@ class ApplicationsButton extends PanelMenu.Button { } } -class Extension { +export default class Extension { constructor() { ExtensionUtils.initTranslations(); } @@ -695,8 +700,3 @@ class Extension { delete this._appsMenuButton; } } - -/** */ -function init() { - return new Extension(); -} diff --git a/extensions/auto-move-windows/extension.js b/extensions/auto-move-windows/extension.js index 9362a52e..c97c825d 100644 --- a/extensions/auto-move-windows/extension.js +++ b/extensions/auto-move-windows/extension.js @@ -1,8 +1,7 @@ // -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- // Start apps on custom workspaces -/* exported init enable disable */ -const {Shell} = imports.gi; +import Shell from 'gi://Shell'; const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; @@ -105,7 +104,7 @@ class WindowMover { } } -class Extension { +export default class Extension { enable() { this._prevCheckWorkspaces = Main.wm._workspaceTracker._checkWorkspaces; Main.wm._workspaceTracker._checkWorkspaces = @@ -143,8 +142,3 @@ class Extension { /* eslint-enable no-invalid-this */ } } - -/** */ -function init() { - return new Extension(); -} diff --git a/extensions/auto-move-windows/prefs.js b/extensions/auto-move-windows/prefs.js index b849db7d..fb66a7f1 100644 --- a/extensions/auto-move-windows/prefs.js +++ b/extensions/auto-move-windows/prefs.js @@ -1,8 +1,11 @@ // -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- // Start apps on custom workspaces -/* exported init buildPrefsWidget */ -const {Adw, Gio, GLib, GObject, Gtk} = imports.gi; +import Adw from 'gi://Adw'; +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; +import GObject from 'gi://GObject'; +import Gtk from 'gi://Gtk'; const ExtensionUtils = imports.misc.extensionUtils; @@ -338,14 +341,16 @@ class NewRuleDialog extends Gtk.AppChooserDialog { } } -/** */ -function init() { - ExtensionUtils.initTranslations(); -} +export default class ExtensionPreferences { + constructor() { + ExtensionUtils.initTranslations(); + } -/** - * @returns {Gtk.Widget} - the prefs widget - */ -function buildPrefsWidget() { - return new AutoMoveSettingsWidget(); + fillPreferencesWindow(window) { + const page = new Adw.PreferencesPage(); + window.add(page); + + const group = new AutoMoveSettingsWidget(); + page.add(group); + } } diff --git a/extensions/drive-menu/extension.js b/extensions/drive-menu/extension.js index fd98d989..57c10a4d 100644 --- a/extensions/drive-menu/extension.js +++ b/extensions/drive-menu/extension.js @@ -1,6 +1,9 @@ -/* exported init enable disable */ // Drive menu extension -const {Clutter, Gio, GObject, Shell, St} = imports.gi; +import Clutter from 'gi://Clutter'; +import Gio from 'gi://Gio'; +import GObject from 'gi://GObject'; +import Shell from 'gi://Shell'; +import St from 'gi://St'; const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; @@ -212,7 +215,7 @@ class DriveMenu extends PanelMenu.Button { } } -class Extension { +export default class Extension { constructor() { ExtensionUtils.initTranslations(); } @@ -227,8 +230,3 @@ class Extension { delete this._indicator; } } - -/** */ -function init() { - return new Extension(); -} diff --git a/extensions/launch-new-instance/extension.js b/extensions/launch-new-instance/extension.js index 53f2420c..53d8ae25 100644 --- a/extensions/launch-new-instance/extension.js +++ b/extensions/launch-new-instance/extension.js @@ -1,7 +1,6 @@ -/* exported init */ const AppDisplay = imports.ui.appDisplay; -class Extension { +export default class Extension { constructor() { this._appIconProto = AppDisplay.AppIcon.prototype; this._activateOriginal = this._appIconProto.activate; @@ -18,8 +17,3 @@ class Extension { this._appIconProto.activate = this._activateOriginal; } } - -/** */ -function init() { - return new Extension(); -} diff --git a/extensions/light-style/extension.js b/extensions/light-style/extension.js index f9d35b55..e37b40ec 100644 --- a/extensions/light-style/extension.js +++ b/extensions/light-style/extension.js @@ -1,4 +1,3 @@ -/* exported init */ /* * 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 @@ -16,11 +15,11 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ -const {St} = imports.gi; +import St from 'gi://St'; const Main = imports.ui.main; -class Extension { +export default class Extension { _updateColorScheme(scheme) { Main.sessionMode.colorScheme = scheme; St.Settings.get().notify('color-scheme'); @@ -35,8 +34,3 @@ class Extension { this._updateColorScheme(this._savedColorScheme); } } - -/** */ -function init() { - return new Extension(); -} diff --git a/extensions/native-window-placement/extension.js b/extensions/native-window-placement/extension.js index 839464e2..e41bd23b 100644 --- a/extensions/native-window-placement/extension.js +++ b/extensions/native-window-placement/extension.js @@ -1,6 +1,5 @@ // -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- -/* exported enable disable */ -const {Clutter} = imports.gi; +import Clutter from 'gi://Clutter'; const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; @@ -236,7 +235,7 @@ class NaturalLayoutStrategy extends Workspace.LayoutStrategy { } } -class Extension { +export default class Extension { constructor() { this._savedMethods = new Map(); } @@ -324,8 +323,3 @@ class Extension { this._savedMethods.clear(); } } - -/** */ -function init() { - return new Extension(); -} diff --git a/extensions/places-menu/extension.js b/extensions/places-menu/extension.js index d7fdab37..9c526361 100644 --- a/extensions/places-menu/extension.js +++ b/extensions/places-menu/extension.js @@ -1,15 +1,14 @@ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* exported init enable disable */ - -const {Clutter, GObject, St} = imports.gi; +import Clutter from 'gi://Clutter'; +import GObject from 'gi://GObject'; +import St from 'gi://St'; const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; -const Me = ExtensionUtils.getCurrentExtension(); -const PlaceDisplay = Me.imports.placeDisplay; +import {PlacesManager} from './placeDisplay.js'; const _ = ExtensionUtils.gettext; const N_ = x => x; @@ -100,7 +99,7 @@ class PlacesMenu extends PanelMenu.Button { }); this.add_actor(label); - this.placesManager = new PlaceDisplay.PlacesManager(); + this.placesManager = new PlacesManager(); this._sections = { }; @@ -138,7 +137,7 @@ class PlacesMenu extends PanelMenu.Button { } } -class Extension { +export default class Extension { constructor() { ExtensionUtils.initTranslations(); } @@ -157,8 +156,3 @@ class Extension { delete this._indicator; } } - -/** */ -function init() { - return new Extension(); -} diff --git a/extensions/places-menu/placeDisplay.js b/extensions/places-menu/placeDisplay.js index 9b5c205f..304ccd74 100644 --- a/extensions/places-menu/placeDisplay.js +++ b/extensions/places-menu/placeDisplay.js @@ -1,7 +1,7 @@ // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- -/* exported PlacesManager */ - -const {Gio, GLib, Shell} = imports.gi; +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; +import Shell from 'gi://Shell'; const {EventEmitter} = imports.misc.signals; const ExtensionUtils = imports.misc.extensionUtils; @@ -248,7 +248,7 @@ const DEFAULT_DIRECTORIES = [ GLib.UserDirectory.DIRECTORY_VIDEOS, ]; -var PlacesManager = class extends EventEmitter { +export class PlacesManager extends EventEmitter { constructor() { super(); @@ -546,4 +546,4 @@ var PlacesManager = class extends EventEmitter { get(kind) { return this._places[kind]; } -}; +} diff --git a/extensions/screenshot-window-sizer/extension.js b/extensions/screenshot-window-sizer/extension.js index 97354474..b7777ab3 100644 --- a/extensions/screenshot-window-sizer/extension.js +++ b/extensions/screenshot-window-sizer/extension.js @@ -1,4 +1,3 @@ -/* exported enable disable */ /* Screenshot Window Sizer for Gnome Shell * * Copyright (c) 2013 Owen Taylor @@ -19,14 +18,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -const {Clutter, Meta, Shell, St} = imports.gi; +import Clutter from 'gi://Clutter'; +import Meta from 'gi://Meta'; +import Shell from 'gi://Shell'; +import St from 'gi://St'; const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; const MESSAGE_FADE_TIME = 2000; -class Extension { +export default class Extension { SIZES = [ [624, 351], [800, 450], @@ -163,8 +165,3 @@ class Extension { Main.wm.removeKeybinding('cycle-screenshot-sizes-backward'); } } - -/** */ -function init() { - return new Extension(); -} diff --git a/extensions/user-theme/extension.js b/extensions/user-theme/extension.js index 4295519c..d0f8664d 100644 --- a/extensions/user-theme/extension.js +++ b/extensions/user-theme/extension.js @@ -1,18 +1,16 @@ // -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- // Load shell theme from ~/.local/share/themes/name/gnome-shell -/* exported init */ -const {Gio} = imports.gi; +import Gio from 'gi://Gio'; const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; -const Me = ExtensionUtils.getCurrentExtension(); -const Util = Me.imports.util; +import {getThemeDirs, getModeThemeDirs} from './util.js'; const SETTINGS_KEY = 'name'; -class ThemeManager { +export default class ThemeManager { enable() { this._settings = ExtensionUtils.getSettings(); this._settings.connect(`changed::${SETTINGS_KEY}`, this._changeTheme.bind(this)); @@ -32,10 +30,10 @@ class ThemeManager { let themeName = this._settings.get_string(SETTINGS_KEY); if (themeName) { - const stylesheetPaths = Util.getThemeDirs() + const stylesheetPaths = getThemeDirs() .map(dir => `${dir}/${themeName}/gnome-shell/gnome-shell.css`); - stylesheetPaths.push(...Util.getModeThemeDirs() + stylesheetPaths.push(...getModeThemeDirs() .map(dir => `${dir}/${themeName}.css`)); stylesheet = stylesheetPaths.find(path => { @@ -52,10 +50,3 @@ class ThemeManager { Main.loadTheme(); } } - -/** - * @returns {ThemeManager} - the extension state object - */ -function init() { - return new ThemeManager(); -} diff --git a/extensions/user-theme/prefs.js b/extensions/user-theme/prefs.js index ef5c9fcb..9d42fd0a 100644 --- a/extensions/user-theme/prefs.js +++ b/extensions/user-theme/prefs.js @@ -1,15 +1,17 @@ // -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- -/* exported init buildPrefsWidget */ // we use async/await here to not block the mainloop, not to parallelize /* eslint-disable no-await-in-loop */ -const {Adw, Gio, GLib, GObject, Gtk} = imports.gi; +import Adw from 'gi://Adw'; +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; +import GObject from 'gi://GObject'; +import Gtk from 'gi://Gtk'; const ExtensionUtils = imports.misc.extensionUtils; -const Me = ExtensionUtils.getCurrentExtension(); -const Util = Me.imports.util; +import {getThemeDirs, getModeThemeDirs} from './util.js'; Gio._promisify(Gio.File.prototype, 'enumerate_children_async'); Gio._promisify(Gio.File.prototype, 'query_info_async'); @@ -39,7 +41,7 @@ class UserThemePrefsWidget extends Adw.PreferencesGroup { } async _collectThemes() { - for (const dirName of Util.getThemeDirs()) { + for (const dirName of getThemeDirs()) { const dir = Gio.File.new_for_path(dirName); for (const name of await this._enumerateDir(dir)) { if (this._rows.has(name)) @@ -60,7 +62,7 @@ class UserThemePrefsWidget extends Adw.PreferencesGroup { } } - for (const dirName of Util.getModeThemeDirs()) { + for (const dirName of getModeThemeDirs()) { const dir = Gio.File.new_for_path(dirName); for (const filename of await this._enumerateDir(dir)) { if (!filename.endsWith('.css')) @@ -125,13 +127,12 @@ class ThemeRow extends Adw.ActionRow { } } -/** */ -function init() { -} +export default class ExtensionPreferences { + fillPreferencesWindow(window) { + const page = new Adw.PreferencesPage(); + window.add(page); -/** - * @returns {Gtk.Widget} - the prefs widget - */ -function buildPrefsWidget() { - return new UserThemePrefsWidget(); + const group = new UserThemePrefsWidget(); + page.add(group); + } } diff --git a/extensions/user-theme/util.js b/extensions/user-theme/util.js index 222eb75f..6ba22b74 100644 --- a/extensions/user-theme/util.js +++ b/extensions/user-theme/util.js @@ -1,12 +1,11 @@ -/* exported getThemeDirs getModeThemeDirs */ -const {GLib} = imports.gi; +import GLib from 'gi://GLib'; const fn = (...args) => GLib.build_filenamev(args); /** * @returns {string[]} - an ordered list of theme directories */ -function getThemeDirs() { +export function getThemeDirs() { return [ fn(GLib.get_home_dir(), '.themes'), fn(GLib.get_user_data_dir(), 'themes'), @@ -17,7 +16,7 @@ function getThemeDirs() { /** * @returns {string[]} - an ordered list of mode theme directories */ -function getModeThemeDirs() { +export function getModeThemeDirs() { return GLib.get_system_data_dirs() .map(dir => fn(dir, 'gnome-shell', 'theme')); } diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js index 39bac0fc..05528396 100644 --- a/extensions/window-list/extension.js +++ b/extensions/window-list/extension.js @@ -1,5 +1,11 @@ -/* exported init */ -const {Clutter, Gio, GLib, GObject, Gtk, Meta, Shell, St} = imports.gi; +import Clutter from 'gi://Clutter'; +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; +import GObject from 'gi://GObject'; +import Gtk from 'gi://Gtk'; +import Meta from 'gi://Meta'; +import Shell from 'gi://Shell'; +import St from 'gi://St'; const DND = imports.ui.dnd; const ExtensionUtils = imports.misc.extensionUtils; @@ -8,8 +14,8 @@ const Overview = imports.ui.overview; const PopupMenu = imports.ui.popupMenu; const Me = ExtensionUtils.getCurrentExtension(); -const {WindowPicker, WindowPickerToggle} = Me.imports.windowPicker; -const {WorkspaceIndicator} = Me.imports.workspaceIndicator; +import {WindowPicker, WindowPickerToggle} from './windowPicker.js'; +import {WorkspaceIndicator} from './workspaceIndicator.js'; const _ = ExtensionUtils.gettext; @@ -1149,7 +1155,7 @@ class WindowList extends St.Widget { } } -class Extension { +export default class Extension { constructor() { ExtensionUtils.initTranslations(); @@ -1279,10 +1285,3 @@ class Tooltip extends St.Label { }); } } - -/** - * @returns {Extension} - the extension's state object - */ -function init() { - return new Extension(); -} diff --git a/extensions/window-list/prefs.js b/extensions/window-list/prefs.js index 6ef097d1..6cdd50d3 100644 --- a/extensions/window-list/prefs.js +++ b/extensions/window-list/prefs.js @@ -1,17 +1,14 @@ // -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- -/* exported init buildPrefsWidget */ - -const {Adw, Gio, GLib, GObject, Gtk} = imports.gi; +import Adw from 'gi://Adw'; +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; +import GObject from 'gi://GObject'; +import Gtk from 'gi://Gtk'; const ExtensionUtils = imports.misc.extensionUtils; const _ = ExtensionUtils.gettext; -/** */ -function init() { - ExtensionUtils.initTranslations(); -} - class WindowListPrefsWidget extends Adw.PreferencesPage { static { GObject.registerClass(this); @@ -84,9 +81,13 @@ class WindowListPrefsWidget extends Adw.PreferencesPage { } } -/** - * @returns {Gtk.Widget} - the prefs widget - */ -function buildPrefsWidget() { - return new WindowListPrefsWidget(); +export default class ExtensionPreferences { + constructor() { + ExtensionUtils.initTranslations(); + } + + fillPreferencesWindow(window) { + const page = new WindowListPrefsWidget(); + window.add(page); + } } diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js index 8da04cdf..b580ddc2 100644 --- a/extensions/window-list/windowPicker.js +++ b/extensions/window-list/windowPicker.js @@ -1,5 +1,7 @@ -/* exported WindowPicker, WindowPickerToggle */ -const {Clutter, GObject, Shell, St} = imports.gi; +import Clutter from 'gi://Clutter'; +import GObject from 'gi://GObject'; +import Shell from 'gi://Shell'; +import St from 'gi://St'; const Layout = imports.ui.layout; const Main = imports.ui.main; @@ -149,7 +151,7 @@ class MyWorkspaceBackground extends Workspace.WorkspaceBackground { } } -var WindowPicker = class WindowPicker extends Clutter.Actor { +export class WindowPicker extends Clutter.Actor { static [GObject.signals] = { 'open-state-changed': {param_types: [GObject.TYPE_BOOLEAN]}, }; @@ -324,9 +326,9 @@ var WindowPicker = class WindowPicker extends Clutter.Actor { global.stage.disconnect(this._stageKeyPressId); this._stageKeyPressId = 0; } -}; +} -var WindowPickerToggle = class WindowPickerToggle extends St.Button { +export class WindowPickerToggle extends St.Button { static { GObject.registerClass(this); } @@ -361,4 +363,4 @@ var WindowPickerToggle = class WindowPickerToggle extends St.Button { this.checked = Main.windowPicker.visible; }); } -}; +} diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js index 7fe7c07d..ff278685 100644 --- a/extensions/window-list/workspaceIndicator.js +++ b/extensions/window-list/workspaceIndicator.js @@ -1,5 +1,8 @@ -/* exported WorkspaceIndicator */ -const {Clutter, Gio, GObject, Meta, St} = imports.gi; +import Clutter from 'gi://Clutter'; +import Gio from 'gi://Gio'; +import GObject from 'gi://GObject'; +import Meta from 'gi://Meta'; +import St from 'gi://St'; const DND = imports.ui.dnd; const ExtensionUtils = imports.misc.extensionUtils; @@ -252,7 +255,7 @@ class WorkspaceThumbnail extends St.Button { } } -var WorkspaceIndicator = class WorkspaceIndicator extends PanelMenu.Button { +export class WorkspaceIndicator extends PanelMenu.Button { static { GObject.registerClass(this); } @@ -447,4 +450,4 @@ var WorkspaceIndicator = class WorkspaceIndicator extends PanelMenu.Button { let newIndex = this._currentWorkspace + diff; this._activate(newIndex); } -}; +} diff --git a/extensions/windowsNavigator/extension.js b/extensions/windowsNavigator/extension.js index 4f55a335..cd2dfd74 100644 --- a/extensions/windowsNavigator/extension.js +++ b/extensions/windowsNavigator/extension.js @@ -1,6 +1,8 @@ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* exported init */ -const {Clutter, Graphene, GObject, St} = imports.gi; +import Clutter from 'gi://Clutter'; +import Graphene from 'gi://Graphene'; +import GObject from 'gi://GObject'; +import St from 'gi://St'; const Main = imports.ui.main; const OverviewControls = imports.ui.overviewControls; @@ -251,7 +253,7 @@ class MyWorkspacesView extends WorkspacesView.WorkspacesView { } } -class Extension { +export default class Extension { constructor() { this._origWorkspace = Workspace.Workspace; this._origWorkspacesView = WorkspacesView.WorkspacesView; @@ -267,10 +269,3 @@ class Extension { WorkspacesView.WorkspacesView = this._origWorkspacesView; } } - -/** - * @returns {Extension} - the extension's state object - */ -function init() { - return new Extension(); -} diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js index f3f1bb4d..effa8f01 100644 --- a/extensions/workspace-indicator/extension.js +++ b/extensions/workspace-indicator/extension.js @@ -1,7 +1,9 @@ // -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- -/* exported init enable disable */ - -const {Clutter, Gio, GObject, Meta, St} = imports.gi; +import Clutter from 'gi://Clutter'; +import Gio from 'gi://Gio'; +import GObject from 'gi://GObject'; +import Meta from 'gi://Meta'; +import St from 'gi://St'; const DND = imports.ui.dnd; const ExtensionUtils = imports.misc.extensionUtils; @@ -454,7 +456,7 @@ class WorkspaceIndicator extends PanelMenu.Button { } } -class Extension { +export default class Extension { constructor() { ExtensionUtils.initTranslations(); } @@ -469,8 +471,3 @@ class Extension { delete this._indicator; } } - -/** */ -function init() { - return new Extension(); -} diff --git a/extensions/workspace-indicator/prefs.js b/extensions/workspace-indicator/prefs.js index 002be954..104926fe 100644 --- a/extensions/workspace-indicator/prefs.js +++ b/extensions/workspace-indicator/prefs.js @@ -1,7 +1,10 @@ // -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- -/* exported init buildPrefsWidget */ - -const {Adw, Gio, GLib, GObject, Gtk, Pango} = imports.gi; +import Adw from 'gi://Adw'; +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; +import GObject from 'gi://GObject'; +import Gtk from 'gi://Gtk'; +import Pango from 'gi://Pango'; const ExtensionUtils = imports.misc.extensionUtils; @@ -256,14 +259,16 @@ class NewWorkspaceRow extends Adw.PreferencesRow { } } -/** */ -function init() { - ExtensionUtils.initTranslations(); -} +export default class ExtensionPreferences { + constructor() { + ExtensionUtils.initTranslations(); + } -/** - * @returns {Gtk.Widget} - the prefs widget - */ -function buildPrefsWidget() { - return new WorkspaceSettingsWidget(); + fillPreferencesWindow(window) { + const page = new Adw.PreferencesPage(); + window.add(page); + + const group = new WorkspaceSettingsWidget(); + page.add(group); + } } diff --git a/lint/eslintrc-shell.yml b/lint/eslintrc-shell.yml index 75a78187..a0e2e14f 100644 --- a/lint/eslintrc-shell.yml +++ b/lint/eslintrc-shell.yml @@ -10,3 +10,5 @@ rules: prefer-arrow-callback: error globals: global: readonly +parserOptions: + sourceType: module From 4955c206690637328397398a998f29e4e00b151f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sun, 9 Jul 2023 14:27:44 +0200 Subject: [PATCH 14/32] data: Remove left-over file We no longer have a separate classic theme that could(*) use custom assets, so the file is now very officially a left-over. (*) spoiler alert: The made-up property where the image was used has been ignored by gnome-shell for years Part-of: --- data/classic-process-working.svg | 3160 ------------------------------ 1 file changed, 3160 deletions(-) delete mode 100644 data/classic-process-working.svg diff --git a/data/classic-process-working.svg b/data/classic-process-working.svg deleted file mode 100644 index ed28a5c7..00000000 --- a/data/classic-process-working.svg +++ /dev/null @@ -1,3160 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From f0865f039ec6db4762d5af6734ca0a31dd27cfeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sun, 9 Jul 2023 15:03:15 +0200 Subject: [PATCH 15/32] Clean up .gitignore Meson enforces a separate build dir, so we no longer have to care about build artifacts in the source tree. Same applies for all the generated crap autotools like to spread around. Part-of: --- .gitignore | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/.gitignore b/.gitignore index 8a6aaa06..b2f2cb30 100644 --- a/.gitignore +++ b/.gitignore @@ -1,29 +1,3 @@ -ABOUT-NLS -Makefile -Makefile.in -Makefile.in.in -aclocal.m4 -autom4te.cache/ -config/ -configure -config.log -config.status -data/*.json -m4/ -po/*.header -po/*.sed -po/*.sin -po/Makevars.template -po/POTFILES -po/Rules-quot po/gnome-shell-extensions.pot -po/stamp-it -staging/ zip-files/ - *~ -*.gmo -metadata.json -*.desktop -*.gschema.valid -*.session From f1257c4523c0e92bfdab5c3270ceff2b80d17d6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sun, 9 Jul 2023 15:03:15 +0200 Subject: [PATCH 16/32] Ignore some common patterns Ignore patches, vim session files and project configuration of GNOME Builder and VSCode. Part-of: --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index b2f2cb30..59063b78 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ po/gnome-shell-extensions.pot zip-files/ *~ +*.patch +*.sw? +.buildconfig +.vscode From 93657252466f6428f09aa389f7b97586fdb0e092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sun, 9 Jul 2023 15:34:54 +0200 Subject: [PATCH 17/32] ci: Use wrapper to run eslint The eslint job report its results as artifacts in junit format, so that gitlab can present them in its UI. However many psople miss that, and unsuccessfully check the logs instead. Address this by using a simplified version of gnome-shell's eslint wrapper, so we can report results both on stdout and in a file without re-running the linter. Part-of: --- .gitlab-ci.yml | 3 ++- .gitlab-ci/run-eslint | 54 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100755 .gitlab-ci/run-eslint diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b1562b3b..5981e068 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -107,7 +107,8 @@ eslint: stage: review <<: *prereview_req script: - - eslint -o $LINT_LOG -f junit --resolve-plugins-relative-to $(npm root -g) extensions + - export NODE_PATH=$(npm root -g) + - ./.gitlab-ci/run-eslint --output-file ${LINT_LOG} --format junit --stdout artifacts: paths: - ${LINT_LOG} diff --git a/.gitlab-ci/run-eslint b/.gitlab-ci/run-eslint new file mode 100755 index 00000000..ac0b281a --- /dev/null +++ b/.gitlab-ci/run-eslint @@ -0,0 +1,54 @@ +#!/usr/bin/env node + +const {ESLint} = require('eslint'); + +console.log(`Running ESLint version ${ESLint.version}...`); + +const fs = require('fs'); +const path = require('path'); + +function hasOption(...names) { + return process.argv.some(arg => names.includes(arg)); +} + +function getOption(...names) { + const optIndex = + process.argv.findIndex(arg => names.includes(arg)) + 1; + + if (optIndex === 0) + return undefined; + + return process.argv[optIndex]; +} + +(async function main() { + const outputOption = getOption('--output-file', '-o'); + const outputPath = outputOption ? path.resolve(outputOption) : null; + + const sourceDir = path.dirname(process.argv[1]); + process.chdir(path.resolve(sourceDir, '..')); + + const sources = ['extensions']; + const eslint = new ESLint(); + + const results = await eslint.lintFiles(sources); + const formatter = await eslint.loadFormatter(getOption('--format', '-f')); + const resultText = formatter.format(results); + + if (outputPath) { + fs.mkdirSync(path.dirname(outputPath), {recursive: true}); + fs.writeFileSync(outputPath, resultText); + + if (hasOption('--stdout')) { + const consoleFormatter = await eslint.loadFormatter(); + console.log(consoleFormatter.format(results)); + } + } else { + console.log(resultText); + } + + process.exitCode = results.some(r => r.errorCount > 0) ? 1 : 0; +})().catch((error) => { + process.exitCode = 1; + console.error(error); +}); From 37baccd9fc4449f0e167a5d48a7c6d10d334195e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sun, 9 Jul 2023 18:33:52 +0200 Subject: [PATCH 18/32] window-list: Remove some dead code The code that connected the signal was removed in 9fa522c29a1b. Part-of: --- extensions/window-list/windowPicker.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js index b580ddc2..6ca21526 100644 --- a/extensions/window-list/windowPicker.js +++ b/extensions/window-list/windowPicker.js @@ -314,10 +314,6 @@ export class WindowPicker extends Clutter.Actor { if (this._origWorkspaceBackground) Workspace.WorkspaceBackground = this._origWorkspaceBackground; - if (this._monitorsChangedId) - Main.layoutManager.disconnect(this._monitorsChangedId); - this._monitorsChangedId = 0; - if (this._overlayKeyId) global.display.disconnect(this._overlayKeyId); this._overlayKeyId = 0; From 3bfaf6f88a01e31b2be6c2c53ed98ba90f75b6de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sat, 16 Jan 2021 01:07:29 +0100 Subject: [PATCH 19/32] js: Use connectObject() gnome-shell added (dis)connectObject() methods to partially automate signal handling. It doesn't only save a significant amount of code, but also makes it harder to miss cleaning up on destroy. Part-of: --- extensions/apps-menu/extension.js | 45 ++-- extensions/auto-move-windows/extension.js | 22 +- extensions/drive-menu/extension.js | 35 +-- extensions/places-menu/extension.js | 13 +- extensions/places-menu/placeDisplay.js | 43 ++-- extensions/window-list/extension.js | 241 +++++++------------ extensions/window-list/windowPicker.js | 51 ++-- extensions/window-list/workspaceIndicator.js | 76 ++---- extensions/windowsNavigator/extension.js | 15 +- extensions/workspace-indicator/extension.js | 73 ++---- 10 files changed, 198 insertions(+), 416 deletions(-) diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js index 2e4738c5..999335cb 100644 --- a/extensions/apps-menu/extension.js +++ b/extensions/apps-menu/extension.js @@ -51,11 +51,8 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem { this.label_actor = appLabel; let textureCache = St.TextureCache.get_default(); - let iconThemeChangedId = textureCache.connect('icon-theme-changed', - this._updateIcon.bind(this)); - this.connect('destroy', () => { - textureCache.disconnect(iconThemeChangedId); - }); + textureCache.connectObject('icon-theme-changed', + () => this._updateIcon(), this); this._updateIcon(); this._delegate = this; @@ -274,9 +271,7 @@ class DesktopTarget extends EventEmitter { _setDesktop(desktop) { if (this._desktop) { - this._desktop.disconnect(this._desktopDestroyedId); - this._desktopDestroyedId = 0; - + this._desktop.disconnectObject(this); delete this._desktop._delegate; } @@ -284,9 +279,9 @@ class DesktopTarget extends EventEmitter { this.emit('desktop-changed'); if (this._desktop) { - this._desktopDestroyedId = this._desktop.connect('destroy', () => { + this._desktop.connectObject('destroy', () => { this._setDesktop(null); - }); + }, this); this._desktop._delegate = this; } } @@ -326,10 +321,7 @@ class DesktopTarget extends EventEmitter { } destroy() { - if (this._windowAddedId) - global.window_group.disconnect(this._windowAddedId); - this._windowAddedId = 0; - + global.window_group.disconnectObject(this); this._setDesktop(null); } @@ -391,12 +383,11 @@ class ApplicationsButton extends PanelMenu.Button { this.name = 'panelApplications'; this.label_actor = this._label; - this._showingId = Main.overview.connect('showing', () => { - this.add_accessible_state(Atk.StateType.CHECKED); - }); - this._hidingId = Main.overview.connect('hiding', () => { - this.remove_accessible_state(Atk.StateType.CHECKED); - }); + Main.overview.connect( + 'showing', () => this.add_accessible_state(Atk.StateType.CHECKED), + 'hiding', () => this.remove_accessible_state(Atk.StateType.CHECKED), + this); + Main.wm.addKeybinding( 'apps-menu-toggle-menu', ExtensionUtils.getSettings(), @@ -415,15 +406,15 @@ class ApplicationsButton extends PanelMenu.Button { }); this._tree = new GMenu.Tree({menu_basename: 'applications.menu'}); - this._treeChangedId = this._tree.connect('changed', - this._onTreeChanged.bind(this)); + this._tree.connectObject('changed', + () => this._onTreeChanged(), this); this._applicationsButtons = new Map(); this.reloadFlag = false; this._createLayout(); this._display(); - this._installedChangedId = appSys.connect('installed-changed', - this._onTreeChanged.bind(this)); + appSys.connectObject('installed-changed', + () => this._onTreeChanged(), this); } _onTreeChanged() { @@ -447,11 +438,7 @@ class ApplicationsButton extends PanelMenu.Button { _onDestroy() { super._onDestroy(); - Main.overview.disconnect(this._showingId); - Main.overview.disconnect(this._hidingId); - appSys.disconnect(this._installedChangedId); - this._tree.disconnect(this._treeChangedId); - this._tree = null; + delete this._tree; Main.wm.removeKeybinding('apps-menu-toggle-menu'); diff --git a/extensions/auto-move-windows/extension.js b/extensions/auto-move-windows/extension.js index c97c825d..53d614a4 100644 --- a/extensions/auto-move-windows/extension.js +++ b/extensions/auto-move-windows/extension.js @@ -13,9 +13,8 @@ class WindowMover { this._appConfigs = new Map(); this._appData = new Map(); - this._appsChangedId = - this._appSystem.connect('installed-changed', - this._updateAppData.bind(this)); + this._appSystem.connectObject('installed-changed', + () => this._updateAppData(), this); this._settings.connect('changed', this._updateAppConfigs.bind(this)); this._updateAppConfigs(); @@ -37,7 +36,7 @@ class WindowMover { let removedApps = [...this._appData.keys()] .filter(a => !ids.includes(a.id)); removedApps.forEach(app => { - app.disconnect(this._appData.get(app).windowsChangedId); + app.disconnectObject(this); this._appData.delete(app); }); @@ -45,21 +44,14 @@ class WindowMover { .map(id => this._appSystem.lookup_app(id)) .filter(app => app && !this._appData.has(app)); addedApps.forEach(app => { - let data = { - windowsChangedId: app.connect('windows-changed', - this._appWindowsChanged.bind(this)), - moveWindowsId: 0, - windows: app.get_windows(), - }; - this._appData.set(app, data); + app.connectObject('window-changed', + this._appWindowsChanged.bind(this), this); + this._appData.set(app, {windows: app.get_windows()}); }); } destroy() { - if (this._appsChangedId) { - this._appSystem.disconnect(this._appsChangedId); - this._appsChangedId = 0; - } + this._appSystem.disconnectObject(this); if (this._settings) { this._settings.run_dispose(); diff --git a/extensions/drive-menu/extension.js b/extensions/drive-menu/extension.js index 57c10a4d..8e9f479d 100644 --- a/extensions/drive-menu/extension.js +++ b/extensions/drive-menu/extension.js @@ -50,19 +50,11 @@ class MountMenuItem extends PopupMenu.PopupBaseMenuItem { this.hide(); - this._changedId = mount.connect('changed', this._syncVisibility.bind(this)); + mount.connectObject('changed', + () => this._syncVisibility(), this); this._syncVisibility(); } - _onDestroy() { - if (this._changedId) { - this.mount.disconnect(this._changedId); - this._changedId = 0; - } - - super.destroy(); - } - async _isInteresting() { if (!this.mount.can_eject() && !this.mount.can_unmount()) return false; @@ -155,12 +147,12 @@ class DriveMenu extends PanelMenu.Button { this.add_child(icon); this._monitor = Gio.VolumeMonitor.get(); - this._addedId = this._monitor.connect('mount-added', - (monitor, mount) => this._addMount(mount)); - this._removedId = this._monitor.connect('mount-removed', (monitor, mount) => { - this._removeMount(mount); - this._updateMenuVisibility(); - }); + this._monitor.connectObject( + 'mount-added', (monitor, mount) => this._addMount(mount), + 'mount-removed', (monitor, mount) => { + this._removeMount(mount); + this._updateMenuVisibility(); + }, this); this._mounts = []; @@ -202,17 +194,6 @@ class DriveMenu extends PanelMenu.Button { } log('Removing a mount that was never added to the menu'); } - - _onDestroy() { - if (this._addedId) { - this._monitor.disconnect(this._addedId); - this._monitor.disconnect(this._removedId); - this._addedId = 0; - this._removedId = 0; - } - - super._onDestroy(); - } } export default class Extension { diff --git a/extensions/places-menu/extension.js b/extensions/places-menu/extension.js index 9c526361..159e61ad 100644 --- a/extensions/places-menu/extension.js +++ b/extensions/places-menu/extension.js @@ -52,17 +52,8 @@ class PlaceMenuItem extends PopupMenu.PopupBaseMenuItem { this.add_child(this._ejectButton); } - this._changedId = info.connect('changed', - this._propertiesChanged.bind(this)); - } - - destroy() { - if (this._changedId) { - this._info.disconnect(this._changedId); - this._changedId = 0; - } - - super.destroy(); + info.connectObject('changed', + this._propertiesChanged.bind(this), this); } activate(event) { diff --git a/extensions/places-menu/placeDisplay.js b/extensions/places-menu/placeDisplay.js index 304ccd74..7fd96757 100644 --- a/extensions/places-menu/placeDisplay.js +++ b/extensions/places-menu/placeDisplay.js @@ -260,15 +260,25 @@ export class PlacesManager extends EventEmitter { }; this._settings = new Gio.Settings({schema_id: BACKGROUND_SCHEMA}); - this._showDesktopIconsChangedId = this._settings.connect( - 'changed::show-desktop-icons', this._updateSpecials.bind(this)); + this._settings.connectObject('changed::show-desktop-icons', + () => this._updateSpecials(), this); this._updateSpecials(); /* * Show devices, code more or less ported from nautilus-places-sidebar.c */ this._volumeMonitor = Gio.VolumeMonitor.get(); - this._connectVolumeMonitorSignals(); + this._volumeMonitor.connectObject( + 'volume-added', () => this._updateMounts(), + 'volume-removed', () => this._updateMounts(), + 'volume-changed', () => this._updateMounts(), + 'mount-added', () => this._updateMounts(), + 'mount-removed', () => this._updateMounts(), + 'mount-changed', () => this._updateMounts(), + 'drive-connected', () => this._updateMounts(), + 'drive-disconnected', () => this._updateMounts(), + 'drive-changed', () => this._updateMounts(), + this); this._updateMounts(); this._bookmarksFile = this._findBookmarksFile(); @@ -293,34 +303,11 @@ export class PlacesManager extends EventEmitter { } } - _connectVolumeMonitorSignals() { - const signals = [ - 'volume-added', - 'volume-removed', - 'volume-changed', - 'mount-added', - 'mount-removed', - 'mount-changed', - 'drive-connected', - 'drive-disconnected', - 'drive-changed', - ]; - - this._volumeMonitorSignals = []; - let func = this._updateMounts.bind(this); - for (let i = 0; i < signals.length; i++) { - let id = this._volumeMonitor.connect(signals[i], func); - this._volumeMonitorSignals.push(id); - } - } - destroy() { - if (this._settings) - this._settings.disconnect(this._showDesktopIconsChangedId); + this._settings?.disconnectObject(this); this._settings = null; - for (let i = 0; i < this._volumeMonitorSignals.length; i++) - this._volumeMonitor.disconnect(this._volumeMonitorSignals[i]); + this._volumeMonitor.disconnectObject(this); if (this._monitor) this._monitor.cancel(); diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js index 05528396..e233e096 100644 --- a/extensions/window-list/extension.js +++ b/extensions/window-list/extension.js @@ -57,10 +57,6 @@ class WindowContextMenu extends PopupMenu.PopupMenu { }); this.addMenuItem(this._minimizeItem); - this._notifyMinimizedId = this._metaWindow.connect( - 'notify::minimized', this._updateMinimizeItem.bind(this)); - this._updateMinimizeItem(); - this._maximizeItem = new PopupMenu.PopupMenuItem(''); this._maximizeItem.connect('activate', () => { if (this._metaWindow.get_maximized() === Meta.MaximizeFlags.BOTH) @@ -70,21 +66,20 @@ class WindowContextMenu extends PopupMenu.PopupMenu { }); this.addMenuItem(this._maximizeItem); - this._notifyMaximizedHId = this._metaWindow.connect( - 'notify::maximized-horizontally', - this._updateMaximizeItem.bind(this)); - this._notifyMaximizedVId = this._metaWindow.connect( - 'notify::maximized-vertically', - this._updateMaximizeItem.bind(this)); - this._updateMaximizeItem(); - this._closeItem = new PopupMenu.PopupMenuItem(_('Close')); this._closeItem.connect('activate', () => { this._metaWindow.delete(global.get_current_time()); }); this.addMenuItem(this._closeItem); - this.actor.connect('destroy', this._onDestroy.bind(this)); + this._metaWindow.connectObject( + 'notify::minimized', this._updateMinimizeItem.bind(this), + 'notify::maximized-horizontally', this._updateMaximizeItem.bind(this), + 'notify::maximized-vertically', this._updateMaximizeItem.bind(this), + this); + + this._updateMinimizeItem(); + this._updateMaximizeItem(); this.connect('open-state-changed', () => { if (!this.isOpen) @@ -107,12 +102,6 @@ class WindowContextMenu extends PopupMenu.PopupMenu { this._maximizeItem.label.text = maximized ? _('Unmaximize') : _('Maximize'); } - - _onDestroy() { - this._metaWindow.disconnect(this._notifyMinimizedId); - this._metaWindow.disconnect(this._notifyMaximizedHId); - this._metaWindow.disconnect(this._notifyMaximizedVId); - } } class WindowTitle extends St.BoxLayout { @@ -136,20 +125,19 @@ class WindowTitle extends St.BoxLayout { this.add(this.label_actor); this._textureCache = St.TextureCache.get_default(); - this._iconThemeChangedId = this._textureCache.connect( - 'icon-theme-changed', this._updateIcon.bind(this)); - this._notifyWmClass = this._metaWindow.connect_after( - 'notify::wm-class', this._updateIcon.bind(this)); - this._notifyAppId = this._metaWindow.connect_after( - 'notify::gtk-application-id', this._updateIcon.bind(this)); + this._textureCache.connectObject('icon-theme-changed', + () => this._updateIcon(), this); + + this._metaWindow.connectObject( + 'notify::wm-class', + () => this._updateIcon(), GObject.ConnectFlags.AFTER, + 'notify::gtk-application-id', + () => this._updateIcon(), GObject.ConnectFlags.AFTER, + 'notify::title', () => this._updateTitle(), + 'notify::minimized', () => this._minimizedChanged(), + this); + this._updateIcon(); - - this.connect('destroy', this._onDestroy.bind(this)); - - this._notifyTitleId = this._metaWindow.connect( - 'notify::title', this._updateTitle.bind(this)); - this._notifyMinimizedId = this._metaWindow.connect( - 'notify::minimized', this._minimizedChanged.bind(this)); this._minimizedChanged(); } @@ -179,14 +167,6 @@ class WindowTitle extends St.BoxLayout { }); } } - - _onDestroy() { - this._textureCache.disconnect(this._iconThemeChangedId); - this._metaWindow.disconnect(this._notifyTitleId); - this._metaWindow.disconnect(this._notifyMinimizedId); - this._metaWindow.disconnect(this._notifyWmClass); - this._metaWindow.disconnect(this._notifyAppId); - } } class BaseButton extends St.Button { @@ -222,16 +202,16 @@ class BaseButton extends St.Button { this._contextMenuManager = new PopupMenu.PopupMenuManager(this); - this._switchWorkspaceId = global.window_manager.connect( - 'switch-workspace', this._updateVisibility.bind(this)); + global.window_manager.connectObject('switch-workspace', + () => this._updateVisibility(), this); if (this._perMonitor) { - this._windowEnteredMonitorId = global.display.connect( + global.display.connectObject( 'window-entered-monitor', - this._windowEnteredOrLeftMonitor.bind(this)); - this._windowLeftMonitorId = global.display.connect( + this._windowEnteredOrLeftMonitor.bind(this), 'window-left-monitor', - this._windowEnteredOrLeftMonitor.bind(this)); + this._windowEnteredOrLeftMonitor.bind(this), + this); } this._tooltip = new Tooltip(this, { @@ -397,16 +377,6 @@ class BaseButton extends St.Button { } _onDestroy() { - global.window_manager.disconnect(this._switchWorkspaceId); - - if (this._windowEnteredMonitorId) - global.display.disconnect(this._windowEnteredMonitorId); - this._windowEnteredMonitorId = 0; - - if (this._windowLeftMonitorId) - global.display.disconnect(this._windowLeftMonitorId); - this._windowLeftMonitorId = 0; - this._tooltip.destroy(); } } @@ -420,9 +390,11 @@ class WindowButton extends BaseButton { super(perMonitor, monitorIndex); this.metaWindow = metaWindow; - this._skipTaskbarId = metaWindow.connect('notify::skip-taskbar', () => { - this._updateVisibility(); - }); + metaWindow.connectObject( + 'notify::skip-taskbar', () => this._updateVisibility(), + 'workspace-changed', () => this._updateVisibility(), + this); + this._updateVisibility(); this._windowTitle = new WindowTitle(this.metaWindow); @@ -436,11 +408,8 @@ class WindowButton extends BaseButton { this._contextMenuManager.addMenu(this._contextMenu); Main.uiGroup.add_actor(this._contextMenu.actor); - this._workspaceChangedId = this.metaWindow.connect( - 'workspace-changed', this._updateVisibility.bind(this)); - - this._notifyFocusId = global.display.connect( - 'notify::focus-window', this._updateStyle.bind(this)); + global.display.connectObject('notify::focus-window', + () => this._updateStyle(), this); this._updateStyle(); } @@ -484,9 +453,6 @@ class WindowButton extends BaseButton { _onDestroy() { super._onDestroy(); - this.metaWindow.disconnect(this._skipTaskbarId); - this.metaWindow.disconnect(this._workspaceChangedId); - global.display.disconnect(this._notifyFocusId); this._contextMenu.destroy(); } } @@ -603,18 +569,17 @@ class AppButton extends BaseButton { Main.uiGroup.add_actor(this._appContextMenu.actor); this._textureCache = St.TextureCache.get_default(); - this._iconThemeChangedId = - this._textureCache.connect('icon-theme-changed', () => { - this._icon.child = app.create_icon_texture(ICON_TEXTURE_SIZE); - }); + this._textureCache.connectObject('icon-theme-changed', () => { + this._icon.child = app.create_icon_texture(ICON_TEXTURE_SIZE); + }, this); - this._windowsChangedId = this.app.connect( - 'windows-changed', this._windowsChanged.bind(this)); + this.app.connectObject('windows-changed', + () => this._windowsChanged(), this); this._windowsChanged(); this._windowTracker = Shell.WindowTracker.get_default(); - this._notifyFocusId = this._windowTracker.connect( - 'notify::focus-app', this._updateStyle.bind(this)); + this._windowTracker.connectObject('notify::focus-app', + () => this._updateStyle(), this); this._updateStyle(); } @@ -734,9 +699,6 @@ class AppButton extends BaseButton { _onDestroy() { super._onDestroy(); - this._textureCache.disconnect(this._iconThemeChangedId); - this._windowTracker.disconnect(this._notifyFocusId); - this.app.disconnect(this._windowsChangedId); this._menu.destroy(); } } @@ -793,12 +755,12 @@ class WindowList extends St.Widget { indicatorsBox.add_child(this._workspaceIndicator.container); this._mutterSettings = new Gio.Settings({schema_id: 'org.gnome.mutter'}); - this._workspacesOnlyOnPrimaryChangedId = this._mutterSettings.connect( + this._mutterSettings.connectObject( 'changed::workspaces-only-on-primary', - this._updateWorkspaceIndicatorVisibility.bind(this)); - this._dynamicWorkspacesChangedId = this._mutterSettings.connect( + () => this._updateWorkspaceIndicatorVisibility(), 'changed::dynamic-workspaces', - this._updateWorkspaceIndicatorVisibility.bind(this)); + () => this._updateWorkspaceIndicatorVisibility(), + this); this._updateWorkspaceIndicatorVisibility(); this._menuManager = new PopupMenu.PopupMenuManager(this); @@ -816,59 +778,58 @@ class WindowList extends St.Widget { this._updatePosition(); this._appSystem = Shell.AppSystem.get_default(); - this._appStateChangedId = this._appSystem.connect( - 'app-state-changed', this._onAppStateChanged.bind(this)); + this._appSystem.connectObject('app-state-changed', + this._onAppStateChanged.bind(this), this); // Hack: OSK gesture is tied to visibility, piggy-back on that - this._keyboardVisiblechangedId = - Main.keyboard._bottomDragAction.connect('notify::enabled', - action => { - const visible = !action.enabled; - if (visible) { - Main.uiGroup.set_child_above_sibling( - this, Main.layoutManager.keyboardBox); - } else { - Main.uiGroup.set_child_above_sibling( - this, Main.layoutManager.panelBox); - } - this._updateKeyboardAnchor(); - }); + Main.keyboard._bottomDragAction.connectObject('notify::enabled', + action => { + const visible = !action.enabled; + if (visible) { + Main.uiGroup.set_child_above_sibling( + this, Main.layoutManager.keyboardBox); + } else { + Main.uiGroup.set_child_above_sibling( + this, Main.layoutManager.panelBox); + } + this._updateKeyboardAnchor(); + }, this); let workspaceManager = global.workspace_manager; - this._nWorkspacesChangedId = workspaceManager.connect( - 'notify::n-workspaces', this._updateWorkspaceIndicatorVisibility.bind(this)); + workspaceManager.connectObject('notify::n-workspaces', + () => this._updateWorkspaceIndicatorVisibility(), this); this._updateWorkspaceIndicatorVisibility(); - this._switchWorkspaceId = global.window_manager.connect( - 'switch-workspace', this._checkGrouping.bind(this)); + global.window_manager.connectObject('switch-workspace', + () => this._checkGrouping(), this); - this._overviewShowingId = Main.overview.connect('showing', () => { - this.hide(); - this._updateKeyboardAnchor(); - }); - - this._overviewHidingId = Main.overview.connect('hidden', () => { - this.visible = !this._monitor.inFullscreen; - this._updateKeyboardAnchor(); - }); - - this._fullscreenChangedId = - global.display.connect('in-fullscreen-changed', () => { - // Work-around for initial change from unknown to !fullscreen - if (Main.overview.visible) - this.hide(); + Main.overview.connectObject( + 'showing', () => { + this.hide(); this._updateKeyboardAnchor(); - }); + }, + 'hidden', () => { + this.visible = !this._monitor.inFullscreen; + this._updateKeyboardAnchor(); + }, this); + + global.display.connectObject('in-fullscreen-changed', () => { + // Work-around for initial change from unknown to !fullscreen + if (Main.overview.visible) + this.hide(); + this._updateKeyboardAnchor(); + }, this); this._windowSignals = new Map(); this._windowCreatedId = global.display.connect( 'window-created', (dsp, win) => this._addWindow(win)); - this._dragBeginId = Main.xdndHandler.connect('drag-begin', - this._monitorDrag.bind(this)); - this._dragEndId = Main.xdndHandler.connect('drag-end', - this._stopMonitoringDrag.bind(this)); + Main.xdndHandler.connectObject( + 'drag-begin', () => this._monitorDrag(), + 'drag-end', () => this._stopMonitoringDrag(), + this); + this._dragMonitor = { dragMotion: this._onDragMotion.bind(this), }; @@ -1115,37 +1076,14 @@ class WindowList extends St.Widget { } _onDestroy() { - this._mutterSettings.disconnect(this._workspacesOnlyOnPrimaryChangedId); - this._mutterSettings.disconnect(this._dynamicWorkspacesChangedId); - this._workspaceIndicator.destroy(); Main.ctrlAltTabManager.removeGroup(this); - this._appSystem.disconnect(this._appStateChangedId); - this._appStateChangedId = 0; - - Main.keyboard._bottomDragAction.disconnect(this._keyboardVisiblechangedId); - this._keyboardVisiblechangedId = 0; - - global.workspace_manager.disconnect(this._nWorkspacesChangedId); - this._nWorkspacesChangedId = 0; - - global.window_manager.disconnect(this._switchWorkspaceId); - this._switchWorkspaceId = 0; - this._windowSignals.forEach((id, win) => win.disconnect(id)); this._windowSignals.clear(); - Main.overview.disconnect(this._overviewShowingId); - Main.overview.disconnect(this._overviewHidingId); - - global.display.disconnect(this._fullscreenChangedId); - global.display.disconnect(this._windowCreatedId); - this._stopMonitoringDrag(); - Main.xdndHandler.disconnect(this._dragBeginId); - Main.xdndHandler.disconnect(this._dragEndId); this._settings.run_dispose(); @@ -1167,11 +1105,11 @@ export default class Extension { this._windowLists = []; this._settings = ExtensionUtils.getSettings(); - this._showOnAllMonitorsChangedId = this._settings.connect( - 'changed::show-on-all-monitors', this._buildWindowLists.bind(this)); + this._settings.connectObject('changed::show-on-all-monitors', + () => this._buildWindowLists(), this); - this._monitorsChangedId = Main.layoutManager.connect( - 'monitors-changed', this._buildWindowLists.bind(this)); + Main.layoutManager.connectObject('monitors-changed', + () => this._buildWindowLists(), this); Main.windowPicker = new WindowPicker(); @@ -1199,11 +1137,8 @@ export default class Extension { if (!this._windowLists) return; - this._settings.disconnect(this._showOnAllMonitorsChangedId); - this._showOnAllMonitorsChangedId = 0; - - Main.layoutManager.disconnect(this._monitorsChangedId); - this._monitorsChangedId = 0; + this._settings.disconnectObject(this); + Main.layoutManager.disconnectObject(this); this._windowLists.forEach(windowList => { windowList.hide(); diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js index 6ca21526..17802c14 100644 --- a/extensions/window-list/windowPicker.js +++ b/extensions/window-list/windowPicker.js @@ -37,9 +37,8 @@ class MyWorkspacesDisplay extends WorkspacesDisplay { this._workspaceAdjustment = workspaceAdjustment; this._workspaceAdjustment.actor = this; - this._nWorkspacesChangedId = - workspaceManager.connect('notify::n-workspaces', - this._updateAdjustment.bind(this)); + workspaceManager.connectObject('notify::n-workspaces', + () => this._updateAdjustment(), this); this.add_constraint( new Layout.MonitorConstraint({ @@ -72,14 +71,6 @@ class MyWorkspacesDisplay extends WorkspacesDisplay { value: workspaceManager.get_active_workspace_index(), }); } - - _onDestroy() { - if (this._nWorkspacesChangedId) - global.workspace_manager.disconnect(this._nWorkspacesChangedId); - this._nWorkspacesChangedId = 0; - - super._onDestroy(); - } } class MyWorkspace extends Workspace.Workspace { @@ -90,25 +81,16 @@ class MyWorkspace extends Workspace.Workspace { constructor(...args) { super(...args); - this._adjChangedId = - this._overviewAdjustment.connect('notify::value', () => { - const {value: progress} = this._overviewAdjustment; - const brightness = 1 - (1 - VIGNETTE_BRIGHTNESS) * progress; - for (const bg of this._background?._backgroundGroup ?? []) { - bg.content.set({ - vignette: true, - brightness, - }); - } - }); - } - - _onDestroy() { - super._onDestroy(); - - if (this._adjChangedId) - this._overviewAdjustment.disconnect(this._adjChangedId); - this._adjChangedId = 0; + this._overviewAdjustment.connectObject('notify::value', () => { + const {value: progress} = this._overviewAdjustment; + const brightness = 1 - (1 - VIGNETTE_BRIGHTNESS) * progress; + for (const bg of this._background?._backgroundGroup ?? []) { + bg.content.set({ + vignette: true, + brightness, + }); + } + }, this); } } @@ -166,7 +148,6 @@ export class WindowPicker extends Clutter.Actor { this._visible = false; this._modal = false; - this._overlayKeyId = 0; this._stageKeyPressId = 0; this._adjustment = new OverviewAdjustment(this); @@ -188,12 +169,12 @@ export class WindowPicker extends Clutter.Actor { if (!Main.sessionMode.hasOverview) { this._injectBackgroundShade(); - this._overlayKeyId = global.display.connect('overlay-key', () => { + global.display.connectObject('overlay-key', () => { if (!this._visible) this.open(); else this.close(); - }); + }, this); } } @@ -314,10 +295,6 @@ export class WindowPicker extends Clutter.Actor { if (this._origWorkspaceBackground) Workspace.WorkspaceBackground = this._origWorkspaceBackground; - if (this._overlayKeyId) - global.display.disconnect(this._overlayKeyId); - this._overlayKeyId = 0; - if (this._stageKeyPressId) global.stage.disconnect(this._stageKeyPressId); this._stageKeyPressId = 0; diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js index ff278685..1f78db0a 100644 --- a/extensions/window-list/workspaceIndicator.js +++ b/extensions/window-list/workspaceIndicator.js @@ -32,20 +32,17 @@ class WindowPreview extends St.Button { this._window = window; - this.connect('destroy', this._onDestroy.bind(this)); - - this._sizeChangedId = this._window.connect('size-changed', - () => this.queue_relayout()); - this._positionChangedId = this._window.connect('position-changed', - () => { + this._window.connectObject( + 'size-changed', () => this.queue_relayout(), + 'position-changed', () => { this._updateVisible(); this.queue_relayout(); - }); - this._minimizedChangedId = this._window.connect('notify::minimized', - this._updateVisible.bind(this)); + }, + 'notify::minimized', this._updateVisible.bind(this), + this); - this._focusChangedId = global.display.connect('notify::focus-window', - this._onFocusChanged.bind(this)); + global.display.connectObject('notify::focus-window', + this._onFocusChanged.bind(this), this); this._onFocusChanged(); } @@ -54,13 +51,6 @@ class WindowPreview extends St.Button { return this._window; } - _onDestroy() { - this._window.disconnect(this._sizeChangedId); - this._window.disconnect(this._positionChangedId); - this._window.disconnect(this._minimizedChangedId); - global.display.disconnect(this._focusChangedId); - } - _onFocusChanged() { if (global.display.focus_window === this._window) this.add_style_class_name('active'); @@ -141,16 +131,13 @@ class WorkspaceThumbnail extends St.Button { let workspaceManager = global.workspace_manager; this._workspace = workspaceManager.get_workspace_by_index(index); - this._windowAddedId = this._workspace.connect('window-added', - (ws, window) => { - this._addWindow(window); - }); - this._windowRemovedId = this._workspace.connect('window-removed', - (ws, window) => { - this._removeWindow(window); - }); - this._restackedId = global.display.connect('restacked', - this._onRestacked.bind(this)); + this._workspace.connectObject( + 'window-added', (ws, window) => this._addWindow(window), + 'window-removed', (ws, window) => this._removeWindow(window), + this); + + global.display.connectObject('restacked', + this._onRestacked.bind(this), this); this._workspace.list_windows().forEach(w => this._addWindow(w)); this._onRestacked(); @@ -248,10 +235,6 @@ class WorkspaceThumbnail extends St.Button { _onDestroy() { this._tooltip.destroy(); - - this._workspace.disconnect(this._windowAddedId); - this._workspace.disconnect(this._windowRemovedId); - global.display.disconnect(this._restackedId); } } @@ -298,14 +281,11 @@ export class WorkspaceIndicator extends PanelMenu.Button { this._workspacesItems = []; - this._workspaceManagerSignals = [ - workspaceManager.connect('notify::n-workspaces', - this._nWorkspacesChanged.bind(this)), - workspaceManager.connect_after('workspace-switched', - this._onWorkspaceSwitched.bind(this)), - workspaceManager.connect('notify::layout-rows', - this._updateThumbnailVisibility.bind(this)), - ]; + workspaceManager.connectObject( + 'notify::n-workspaces', this._nWorkspacesChanged.bind(this), GObject.ConnectFlags.AFTER, + 'workspace-switched', this._onWorkspaceSwitched.bind(this), GObject.ConnectFlags.AFTER, + 'notify::layout-rows', this._updateThumbnailVisibility.bind(this), + this); this.connect('scroll-event', this._onScrollEvent.bind(this)); this._updateMenu(); @@ -313,20 +293,8 @@ export class WorkspaceIndicator extends PanelMenu.Button { this._updateThumbnailVisibility(); this._settings = new Gio.Settings({schema_id: 'org.gnome.desktop.wm.preferences'}); - this._settingsChangedId = this._settings.connect( - 'changed::workspace-names', this._updateMenuLabels.bind(this)); - } - - _onDestroy() { - for (let i = 0; i < this._workspaceManagerSignals.length; i++) - global.workspace_manager.disconnect(this._workspaceManagerSignals[i]); - - if (this._settingsChangedId) { - this._settings.disconnect(this._settingsChangedId); - this._settingsChangedId = 0; - } - - super._onDestroy(); + this._settings.connectObject('changed::workspace-names', + () => this._updateMenuLabels(), this); } _updateThumbnailVisibility() { diff --git a/extensions/windowsNavigator/extension.js b/extensions/windowsNavigator/extension.js index cd2dfd74..83b933ff 100644 --- a/extensions/windowsNavigator/extension.js +++ b/extensions/windowsNavigator/extension.js @@ -132,17 +132,10 @@ class MyWorkspacesView extends WorkspacesView.WorkspacesView { this._pickWorkspace = false; this._pickWindow = false; - this._keyPressEventId = - global.stage.connect('key-press-event', this._onKeyPress.bind(this)); - this._keyReleaseEventId = - global.stage.connect('key-release-event', this._onKeyRelease.bind(this)); - } - - _onDestroy() { - super._onDestroy(); - - global.stage.disconnect(this._keyPressEventId); - global.stage.disconnect(this._keyReleaseEventId); + global.stage.connect( + 'key-press-event', this._onKeyPress.bind(this), + 'key-release-event', this._onKeyRelease.bind(this), + this); } _hideTooltips() { diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js index effa8f01..d6543599 100644 --- a/extensions/workspace-indicator/extension.js +++ b/extensions/workspace-indicator/extension.js @@ -36,20 +36,17 @@ class WindowPreview extends St.Button { this._window = window; - this.connect('destroy', this._onDestroy.bind(this)); - - this._sizeChangedId = this._window.connect('size-changed', - () => this.queue_relayout()); - this._positionChangedId = this._window.connect('position-changed', - () => { + this._window.connectObject( + 'size-changed', () => this.queue_relayout(), + 'position-changed', () => { this._updateVisible(); this.queue_relayout(); - }); - this._minimizedChangedId = this._window.connect('notify::minimized', - this._updateVisible.bind(this)); + }, + 'notify::minimized', this._updateVisible.bind(this), + this); - this._focusChangedId = global.display.connect('notify::focus-window', - this._onFocusChanged.bind(this)); + global.display.connectObject('notify::focus-window', + this._onFocusChanged.bind(this), this); this._onFocusChanged(); } @@ -58,13 +55,6 @@ class WindowPreview extends St.Button { return this._window; } - _onDestroy() { - this._window.disconnect(this._sizeChangedId); - this._window.disconnect(this._positionChangedId); - this._window.disconnect(this._minimizedChangedId); - global.display.disconnect(this._focusChangedId); - } - _onFocusChanged() { if (global.display.focus_window === this._window) this.add_style_class_name('active'); @@ -145,16 +135,13 @@ class WorkspaceThumbnail extends St.Button { let workspaceManager = global.workspace_manager; this._workspace = workspaceManager.get_workspace_by_index(index); - this._windowAddedId = this._workspace.connect('window-added', - (ws, window) => { - this._addWindow(window); - }); - this._windowRemovedId = this._workspace.connect('window-removed', - (ws, window) => { - this._removeWindow(window); - }); - this._restackedId = global.display.connect('restacked', - this._onRestacked.bind(this)); + this._workspace.connectObject( + 'window-added', (ws, window) => this._addWindow(window), + 'window-removed', (ws, window) => this._removeWindow(window), + this); + + global.display.connectObject('restacked', + this._onRestacked.bind(this), this); this._workspace.list_windows().forEach(w => this._addWindow(w)); this._onRestacked(); @@ -252,10 +239,6 @@ class WorkspaceThumbnail extends St.Button { _onDestroy() { this._tooltip.destroy(); - - this._workspace.disconnect(this._windowAddedId); - this._workspace.disconnect(this._windowRemovedId); - global.display.disconnect(this._restackedId); } } @@ -297,14 +280,11 @@ class WorkspaceIndicator extends PanelMenu.Button { this._workspaceSection = new PopupMenu.PopupMenuSection(); this.menu.addMenuItem(this._workspaceSection); - this._workspaceManagerSignals = [ - workspaceManager.connect_after('notify::n-workspaces', - this._nWorkspacesChanged.bind(this)), - workspaceManager.connect_after('workspace-switched', - this._onWorkspaceSwitched.bind(this)), - workspaceManager.connect('notify::layout-rows', - this._updateThumbnailVisibility.bind(this)), - ]; + workspaceManager.connectObject( + 'notify::n-workspaces', this._nWorkspacesChanged.bind(this), GObject.ConnectFlags.AFTER, + 'workspace-switched', this._onWorkspaceSwitched.bind(this), GObject.ConnectFlags.AFTER, + 'notify::layout-rows', this._updateThumbnailVisibility.bind(this), + this); this.connect('scroll-event', this._onScrollEvent.bind(this)); this._thumbnailsBox.connect('scroll-event', this._onScrollEvent.bind(this)); @@ -313,20 +293,11 @@ class WorkspaceIndicator extends PanelMenu.Button { this._updateThumbnailVisibility(); this._settings = new Gio.Settings({schema_id: WORKSPACE_SCHEMA}); - this._settingsChangedId = this._settings.connect( - `changed::${WORKSPACE_KEY}`, - this._updateMenuLabels.bind(this)); + this._settings.connectObject(`changed::${WORKSPACE_KEY}`, + this._updateMenuLabels.bind(this), this); } _onDestroy() { - for (let i = 0; i < this._workspaceManagerSignals.length; i++) - global.workspace_manager.disconnect(this._workspaceManagerSignals[i]); - - if (this._settingsChangedId) { - this._settings.disconnect(this._settingsChangedId); - this._settingsChangedId = 0; - } - Main.panel.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS); super._onDestroy(); From 93a2e7bdba9f39f8a191e6d2c196de23ed01e9da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Mon, 10 Jul 2023 06:51:45 +0200 Subject: [PATCH 20/32] extensions: Stop using global.log() It has been deprecated since 3.6(!) in favor of the actually global log(). Part-of: --- extensions/user-theme/extension.js | 4 ++-- extensions/windowsNavigator/extension.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/user-theme/extension.js b/extensions/user-theme/extension.js index d0f8664d..25f5a876 100644 --- a/extensions/user-theme/extension.js +++ b/extensions/user-theme/extension.js @@ -43,9 +43,9 @@ export default class ThemeManager { } if (stylesheet) - global.log(`loading user theme: ${stylesheet}`); + log(`loading user theme: ${stylesheet}`); else - global.log('loading default theme (Adwaita)'); + log('loading default theme (Adwaita)'); Main.setThemeStylesheet(stylesheet); Main.loadTheme(); } diff --git a/extensions/windowsNavigator/extension.js b/extensions/windowsNavigator/extension.js index 83b933ff..f094a158 100644 --- a/extensions/windowsNavigator/extension.js +++ b/extensions/windowsNavigator/extension.js @@ -212,7 +212,7 @@ class MyWorkspacesView extends WorkspacesView.WorkspacesView { c = o.get_key_symbol() - Clutter.KEY_0; if (c > 9 || c <= 0) { this._hideTooltips(); - global.log(c); + log(c); return false; } } From 6d8f54a20b0839de276f51a2dd2e7e6c2e091e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Mon, 10 Jul 2023 07:02:05 +0200 Subject: [PATCH 21/32] js: Really use connectObject() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I forgot in two places to change the actual connect() function to connectObject() 🤦️ Fixes commit 3bfaf6f88a01e. --- extensions/apps-menu/extension.js | 2 +- extensions/windowsNavigator/extension.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js index 999335cb..5b4347bf 100644 --- a/extensions/apps-menu/extension.js +++ b/extensions/apps-menu/extension.js @@ -383,7 +383,7 @@ class ApplicationsButton extends PanelMenu.Button { this.name = 'panelApplications'; this.label_actor = this._label; - Main.overview.connect( + Main.overview.connectObject( 'showing', () => this.add_accessible_state(Atk.StateType.CHECKED), 'hiding', () => this.remove_accessible_state(Atk.StateType.CHECKED), this); diff --git a/extensions/windowsNavigator/extension.js b/extensions/windowsNavigator/extension.js index f094a158..2ae74cf8 100644 --- a/extensions/windowsNavigator/extension.js +++ b/extensions/windowsNavigator/extension.js @@ -132,7 +132,7 @@ class MyWorkspacesView extends WorkspacesView.WorkspacesView { this._pickWorkspace = false; this._pickWindow = false; - global.stage.connect( + global.stage.connectObject( 'key-press-event', this._onKeyPress.bind(this), 'key-release-event', this._onKeyRelease.bind(this), this); From 1155170c7ca9d362ba2eb77af959cda23affe6cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sat, 15 Jul 2023 14:10:27 +0200 Subject: [PATCH 22/32] window-list: Stop using getCurrentExtension() The method is no longer exported. There will be a nicer alternative soon, in the meantime we can just keep track of our main Extension object ourselves. Part-of: --- extensions/window-list/extension.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js index e233e096..540a2d90 100644 --- a/extensions/window-list/extension.js +++ b/extensions/window-list/extension.js @@ -13,7 +13,6 @@ const Main = imports.ui.main; const Overview = imports.ui.overview; const PopupMenu = imports.ui.popupMenu; -const Me = ExtensionUtils.getCurrentExtension(); import {WindowPicker, WindowPickerToggle} from './windowPicker.js'; import {WorkspaceIndicator} from './workspaceIndicator.js'; @@ -31,6 +30,8 @@ const GroupingMode = { ALWAYS: 2, }; +let Me = null; + /** * @param {Shell.App} app - an app * @returns {number} - the smallest stable sequence of the app's windows @@ -322,7 +323,7 @@ class BaseButton extends St.Button { let [x, y] = global.get_pointer(); let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y); - if (Me.stateObj.someWindowListContains(actor)) + if (Me.someWindowListContains(actor)) actor.sync_hover(); } @@ -1097,6 +1098,8 @@ export default class Extension { constructor() { ExtensionUtils.initTranslations(); + Me = this; + this._windowLists = null; this._hideOverviewOrig = Main.overview.hide; } From e75a1a15ac35074cd787e921254959779e91b69d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sat, 15 Jul 2023 14:13:25 +0200 Subject: [PATCH 23/32] extensions: Import ExtensionUtils as module ExtensionUtils has been converted to ESM and split into two modules, for extensions and prefs respectively. Adjust to those changes. Part-of: --- extensions/apps-menu/extension.js | 3 ++- extensions/auto-move-windows/extension.js | 3 ++- extensions/auto-move-windows/prefs.js | 2 +- extensions/drive-menu/extension.js | 3 ++- extensions/native-window-placement/extension.js | 3 ++- extensions/places-menu/extension.js | 3 ++- extensions/places-menu/placeDisplay.js | 5 +++-- extensions/screenshot-window-sizer/extension.js | 3 ++- extensions/user-theme/extension.js | 3 ++- extensions/user-theme/prefs.js | 2 +- extensions/window-list/extension.js | 3 ++- extensions/window-list/prefs.js | 2 +- extensions/window-list/workspaceIndicator.js | 5 +++-- extensions/workspace-indicator/extension.js | 3 ++- extensions/workspace-indicator/prefs.js | 2 +- 15 files changed, 28 insertions(+), 17 deletions(-) diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js index 5b4347bf..76c0e270 100644 --- a/extensions/apps-menu/extension.js +++ b/extensions/apps-menu/extension.js @@ -11,8 +11,9 @@ import Shell from 'gi://Shell'; import St from 'gi://St'; const {EventEmitter} = imports.misc.signals; +import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; + const DND = imports.ui.dnd; -const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; diff --git a/extensions/auto-move-windows/extension.js b/extensions/auto-move-windows/extension.js index 53d614a4..313982a8 100644 --- a/extensions/auto-move-windows/extension.js +++ b/extensions/auto-move-windows/extension.js @@ -3,7 +3,8 @@ import Shell from 'gi://Shell'; -const ExtensionUtils = imports.misc.extensionUtils; +import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; + const Main = imports.ui.main; class WindowMover { diff --git a/extensions/auto-move-windows/prefs.js b/extensions/auto-move-windows/prefs.js index fb66a7f1..395fbd9b 100644 --- a/extensions/auto-move-windows/prefs.js +++ b/extensions/auto-move-windows/prefs.js @@ -7,7 +7,7 @@ import GLib from 'gi://GLib'; import GObject from 'gi://GObject'; import Gtk from 'gi://Gtk'; -const ExtensionUtils = imports.misc.extensionUtils; +import * as ExtensionUtils from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; const _ = ExtensionUtils.gettext; diff --git a/extensions/drive-menu/extension.js b/extensions/drive-menu/extension.js index 8e9f479d..635a19a1 100644 --- a/extensions/drive-menu/extension.js +++ b/extensions/drive-menu/extension.js @@ -5,7 +5,8 @@ import GObject from 'gi://GObject'; import Shell from 'gi://Shell'; import St from 'gi://St'; -const ExtensionUtils = imports.misc.extensionUtils; +import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; + const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; diff --git a/extensions/native-window-placement/extension.js b/extensions/native-window-placement/extension.js index e41bd23b..ce7122d7 100644 --- a/extensions/native-window-placement/extension.js +++ b/extensions/native-window-placement/extension.js @@ -1,7 +1,8 @@ // -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- import Clutter from 'gi://Clutter'; -const ExtensionUtils = imports.misc.extensionUtils; +import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; + const Main = imports.ui.main; const {WindowPreview} = imports.ui.windowPreview; const Workspace = imports.ui.workspace; diff --git a/extensions/places-menu/extension.js b/extensions/places-menu/extension.js index 159e61ad..2136fd71 100644 --- a/extensions/places-menu/extension.js +++ b/extensions/places-menu/extension.js @@ -3,7 +3,8 @@ import Clutter from 'gi://Clutter'; import GObject from 'gi://GObject'; import St from 'gi://St'; -const ExtensionUtils = imports.misc.extensionUtils; +import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; + const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; diff --git a/extensions/places-menu/placeDisplay.js b/extensions/places-menu/placeDisplay.js index 7fd96757..abbb6a8f 100644 --- a/extensions/places-menu/placeDisplay.js +++ b/extensions/places-menu/placeDisplay.js @@ -4,11 +4,12 @@ import GLib from 'gi://GLib'; import Shell from 'gi://Shell'; const {EventEmitter} = imports.misc.signals; -const ExtensionUtils = imports.misc.extensionUtils; +import {gettext} from 'resource:///org/gnome/shell/extensions/extension.js'; + const Main = imports.ui.main; const ShellMountOperation = imports.ui.shellMountOperation; -const _ = ExtensionUtils.gettext; +const _ = gettext; const N_ = x => x; Gio._promisify(Gio.AppInfo, 'launch_default_for_uri_async'); diff --git a/extensions/screenshot-window-sizer/extension.js b/extensions/screenshot-window-sizer/extension.js index b7777ab3..3dba8202 100644 --- a/extensions/screenshot-window-sizer/extension.js +++ b/extensions/screenshot-window-sizer/extension.js @@ -23,7 +23,8 @@ import Meta from 'gi://Meta'; import Shell from 'gi://Shell'; import St from 'gi://St'; -const ExtensionUtils = imports.misc.extensionUtils; +import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; + const Main = imports.ui.main; const MESSAGE_FADE_TIME = 2000; diff --git a/extensions/user-theme/extension.js b/extensions/user-theme/extension.js index 25f5a876..ea72c16c 100644 --- a/extensions/user-theme/extension.js +++ b/extensions/user-theme/extension.js @@ -3,7 +3,8 @@ import Gio from 'gi://Gio'; -const ExtensionUtils = imports.misc.extensionUtils; +import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; + const Main = imports.ui.main; import {getThemeDirs, getModeThemeDirs} from './util.js'; diff --git a/extensions/user-theme/prefs.js b/extensions/user-theme/prefs.js index 9d42fd0a..054d528a 100644 --- a/extensions/user-theme/prefs.js +++ b/extensions/user-theme/prefs.js @@ -9,7 +9,7 @@ import GLib from 'gi://GLib'; import GObject from 'gi://GObject'; import Gtk from 'gi://Gtk'; -const ExtensionUtils = imports.misc.extensionUtils; +import * as ExtensionUtils from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; import {getThemeDirs, getModeThemeDirs} from './util.js'; diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js index 540a2d90..f7dd8b60 100644 --- a/extensions/window-list/extension.js +++ b/extensions/window-list/extension.js @@ -7,8 +7,9 @@ import Meta from 'gi://Meta'; import Shell from 'gi://Shell'; import St from 'gi://St'; +import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; + const DND = imports.ui.dnd; -const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; const Overview = imports.ui.overview; const PopupMenu = imports.ui.popupMenu; diff --git a/extensions/window-list/prefs.js b/extensions/window-list/prefs.js index 6cdd50d3..68812457 100644 --- a/extensions/window-list/prefs.js +++ b/extensions/window-list/prefs.js @@ -5,7 +5,7 @@ import GLib from 'gi://GLib'; import GObject from 'gi://GObject'; import Gtk from 'gi://Gtk'; -const ExtensionUtils = imports.misc.extensionUtils; +import * as ExtensionUtils from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; const _ = ExtensionUtils.gettext; diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js index 1f78db0a..6eeea3e7 100644 --- a/extensions/window-list/workspaceIndicator.js +++ b/extensions/window-list/workspaceIndicator.js @@ -4,13 +4,14 @@ import GObject from 'gi://GObject'; import Meta from 'gi://Meta'; import St from 'gi://St'; +import {gettext} from 'resource:///org/gnome/shell/extensions/extension.js'; + const DND = imports.ui.dnd; -const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; -const _ = ExtensionUtils.gettext; +const _ = gettext; const TOOLTIP_OFFSET = 6; const TOOLTIP_ANIMATION_TIME = 150; diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js index d6543599..1c44ba74 100644 --- a/extensions/workspace-indicator/extension.js +++ b/extensions/workspace-indicator/extension.js @@ -5,8 +5,9 @@ import GObject from 'gi://GObject'; import Meta from 'gi://Meta'; import St from 'gi://St'; +import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; + const DND = imports.ui.dnd; -const ExtensionUtils = imports.misc.extensionUtils; const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; diff --git a/extensions/workspace-indicator/prefs.js b/extensions/workspace-indicator/prefs.js index 104926fe..014e7b3a 100644 --- a/extensions/workspace-indicator/prefs.js +++ b/extensions/workspace-indicator/prefs.js @@ -6,7 +6,7 @@ import GObject from 'gi://GObject'; import Gtk from 'gi://Gtk'; import Pango from 'gi://Pango'; -const ExtensionUtils = imports.misc.extensionUtils; +import * as ExtensionUtils from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; const _ = ExtensionUtils.gettext; const N_ = e => e; From ce644be96f42910aa7b246d57abe9c0908d7445d Mon Sep 17 00:00:00 2001 From: Efstathios Iosifidis Date: Tue, 1 Aug 2023 20:41:56 +0000 Subject: [PATCH 24/32] Update Greek translation --- po/el.po | 101 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 46 deletions(-) diff --git a/po/el.po b/po/el.po index 59b14dfb..11c6ad39 100644 --- a/po/el.po +++ b/po/el.po @@ -12,8 +12,8 @@ msgstr "" "Project-Id-Version: gnome-shell-extensions master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/" "issues\n" -"POT-Creation-Date: 2020-05-28 00:55+0000\n" -"PO-Revision-Date: 2020-07-14 00:40+0300\n" +"POT-Creation-Date: 2023-02-18 15:10+0000\n" +"PO-Revision-Date: 2023-08-01 23:41+0300\n" "Last-Translator: Efstathios Iosifidis \n" "Language-Team: Greek, Modern (1453-) \n" "Language: el\n" @@ -21,22 +21,31 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 1.8.7.1\n" +"X-Generator: Poedit 3.3.2\n" "X-Project-Style: gnome\n" -#: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 +#: data/gnome-classic.desktop.in:3 msgid "GNOME Classic" msgstr "GNOME Classic" -#: data/gnome-classic.desktop.in:4 +#: data/gnome-classic.desktop.in:4 data/gnome-classic-wayland.desktop.in:4 +#: data/gnome-classic-xorg.desktop.in:4 msgid "This session logs you into GNOME Classic" msgstr "Αυτή η συνεδρία σας συνδέει στο GNOME Classic" -#: extensions/apps-menu/extension.js:113 +#: data/gnome-classic-wayland.desktop.in:3 +msgid "GNOME Classic on Wayland" +msgstr "GNOME Classic σε Wayland" + +#: data/gnome-classic-xorg.desktop.in:3 +msgid "GNOME Classic on Xorg" +msgstr "GNOME Classic σε Xorg" + +#: extensions/apps-menu/extension.js:118 msgid "Favorites" msgstr "Αγαπημένα" -#: extensions/apps-menu/extension.js:369 +#: extensions/apps-menu/extension.js:380 msgid "Applications" msgstr "Εφαρμογές" @@ -53,26 +62,26 @@ msgstr "" "(όνομα αρχείου επιφάνειας εργασίας), ακολουθούμενη από άνω-κάτω τελεία και " "τον αριθμό του χώρου εργασίας" -#: extensions/auto-move-windows/prefs.js:35 +#: extensions/auto-move-windows/prefs.js:152 msgid "Workspace Rules" msgstr "Κανόνες χώρων εργασίας" -#: extensions/auto-move-windows/prefs.js:243 +#: extensions/auto-move-windows/prefs.js:306 msgid "Add Rule" msgstr "Προσθήκη κανόνα" #. TRANSLATORS: %s is the filesystem name -#: extensions/drive-menu/extension.js:112 -#: extensions/places-menu/placeDisplay.js:233 +#: extensions/drive-menu/extension.js:126 +#: extensions/places-menu/placeDisplay.js:212 #, javascript-format msgid "Ejecting drive “%s” failed:" msgstr "Αποτυχία εξαγωγής του δίσκου «%s»:" -#: extensions/drive-menu/extension.js:128 +#: extensions/drive-menu/extension.js:145 msgid "Removable devices" msgstr "Αφαιρούμενες συσκευές" -#: extensions/drive-menu/extension.js:155 +#: extensions/drive-menu/extension.js:167 msgid "Open Files" msgstr "Άνοιγμα αρχείων" @@ -106,31 +115,31 @@ msgstr "" "στο κάτω μέρος. Η αλλαγή αυτής της ρύθμισης απαιτεί επανεκκίνηση του " "κελύφους για να υπάρξει κάποιο αποτέλεσμα." -#: extensions/places-menu/extension.js:89 -#: extensions/places-menu/extension.js:93 +#: extensions/places-menu/extension.js:94 +#: extensions/places-menu/extension.js:97 msgid "Places" msgstr "Τοποθεσίες" -#: extensions/places-menu/placeDisplay.js:46 +#: extensions/places-menu/placeDisplay.js:52 #, javascript-format msgid "Failed to launch “%s”" msgstr "Αποτυχία εκκίνησης «%s»" -#: extensions/places-menu/placeDisplay.js:61 +#: extensions/places-menu/placeDisplay.js:67 #, javascript-format msgid "Failed to mount volume for “%s”" msgstr "Αποτυχία προσάρτησης τόμου για «%s»" -#: extensions/places-menu/placeDisplay.js:148 -#: extensions/places-menu/placeDisplay.js:171 +#: extensions/places-menu/placeDisplay.js:127 +#: extensions/places-menu/placeDisplay.js:150 msgid "Computer" msgstr "Υπολογιστής" -#: extensions/places-menu/placeDisplay.js:359 +#: extensions/places-menu/placeDisplay.js:340 msgid "Home" msgstr "Προσωπικός φάκελος" -#: extensions/places-menu/placeDisplay.js:404 +#: extensions/places-menu/placeDisplay.js:385 msgid "Browse Network" msgstr "Περιήγηση δικτύου" @@ -151,47 +160,47 @@ msgid "The name of the theme, to be loaded from ~/.themes/name/gnome-shell" msgstr "" "Το όνομα του θέματος που θα φορτωθεί από το ~ /.themes/name/gnome-shell" -#: extensions/window-list/extension.js:98 +#: extensions/window-list/extension.js:72 msgid "Close" msgstr "Κλείσιμο" -#: extensions/window-list/extension.js:118 +#: extensions/window-list/extension.js:92 msgid "Unminimize" msgstr "Αποελαχιστοποίηση" -#: extensions/window-list/extension.js:118 +#: extensions/window-list/extension.js:92 msgid "Minimize" msgstr "Ελαχιστοποίηση" -#: extensions/window-list/extension.js:125 +#: extensions/window-list/extension.js:99 msgid "Unmaximize" msgstr "Απομεγιστοποίηση" -#: extensions/window-list/extension.js:125 +#: extensions/window-list/extension.js:99 msgid "Maximize" msgstr "Μεγιστοποίηση" -#: extensions/window-list/extension.js:428 +#: extensions/window-list/extension.js:483 msgid "Minimize all" msgstr "Ελαχιστοποίηση όλων" -#: extensions/window-list/extension.js:434 +#: extensions/window-list/extension.js:489 msgid "Unminimize all" msgstr "Αποελαχιστοποίηση όλων" -#: extensions/window-list/extension.js:440 +#: extensions/window-list/extension.js:495 msgid "Maximize all" msgstr "Μεγιστοποίηση όλων" -#: extensions/window-list/extension.js:448 +#: extensions/window-list/extension.js:503 msgid "Unmaximize all" msgstr "Απομεγιστοποίηση όλων" -#: extensions/window-list/extension.js:456 +#: extensions/window-list/extension.js:511 msgid "Close all" msgstr "Κλείσιμο όλων" -#: extensions/window-list/extension.js:734 +#: extensions/window-list/extension.js:795 msgid "Window List" msgstr "Λίστα παραθύρου" @@ -209,7 +218,7 @@ msgstr "" "«always» (πάντα)." #: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:20 -#: extensions/window-list/prefs.js:100 +#: extensions/window-list/prefs.js:79 msgid "Show windows from all workspaces" msgstr "Εμφάνιση των παραθύρων από όλους τους χώρους εργασίας" @@ -230,41 +239,41 @@ msgstr "" "Αν θα εμφανίζεται ο κατάλογος παραθύρων όλων των συνδεμένων οθονών ή μόνο " "της κύριας οθόνης." -#: extensions/window-list/prefs.js:29 +#: extensions/window-list/prefs.js:35 msgid "Window Grouping" msgstr "Ομαδοποίηση παραθύρου" -#: extensions/window-list/prefs.js:58 +#: extensions/window-list/prefs.js:40 msgid "Never group windows" msgstr "Να μη γίνεται ποτέ ομαδοποίηση παραθύρων" -#: extensions/window-list/prefs.js:59 +#: extensions/window-list/prefs.js:41 msgid "Group windows when space is limited" msgstr "Ομαδοποίηση παραθύρων όταν ο χώρος είναι περιορισμένος" -#: extensions/window-list/prefs.js:60 +#: extensions/window-list/prefs.js:42 msgid "Always group windows" msgstr "Να γίνεται πάντα ομαδοποίηση παραθύρων" -#: extensions/window-list/prefs.js:94 +#: extensions/window-list/prefs.js:66 msgid "Show on all monitors" msgstr "Να εμφανίζεται σε όλες τις οθόνες" -#: extensions/window-list/workspaceIndicator.js:207 -#: extensions/workspace-indicator/extension.js:213 +#: extensions/window-list/workspaceIndicator.js:261 +#: extensions/workspace-indicator/extension.js:266 msgid "Workspace Indicator" msgstr "Δείκτης χώρου εργασίας" -#: extensions/workspace-indicator/prefs.js:34 -msgid "Workspace Names" -msgstr "Ονόματα χώρων εργασίας:" - -#: extensions/workspace-indicator/prefs.js:67 +#: extensions/workspace-indicator/prefs.js:62 #, javascript-format msgid "Workspace %d" msgstr "Χώρος εργασίας %d" -#: extensions/workspace-indicator/prefs.js:218 +#: extensions/workspace-indicator/prefs.js:129 +msgid "Workspace Names" +msgstr "Ονόματα χώρων εργασίας" + +#: extensions/workspace-indicator/prefs.js:255 msgid "Add Workspace" msgstr "Προσθήκη χώρου εργασίας" From f2c73329be7a362ad62e7214954344d7be208306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sat, 1 Jul 2023 02:10:49 +0200 Subject: [PATCH 25/32] extensions: Use new convenience classes Convenience APIs for extensions are now provided as Extension/Prefs base classes. Part-of: --- extensions/apps-menu/extension.js | 12 ++----- extensions/auto-move-windows/extension.js | 10 +++--- extensions/auto-move-windows/prefs.js | 34 +++++++------------ extensions/drive-menu/extension.js | 10 ++---- .../native-window-placement/extension.js | 10 +++--- extensions/places-menu/extension.js | 9 ++--- extensions/places-menu/placeDisplay.js | 3 +- .../screenshot-window-sizer/extension.js | 8 ++--- extensions/user-theme/extension.js | 6 ++-- extensions/user-theme/prefs.js | 16 ++++----- extensions/window-list/extension.js | 26 ++++++-------- extensions/window-list/prefs.js | 19 ++++------- extensions/window-list/workspaceIndicator.js | 4 +-- extensions/workspace-indicator/extension.js | 10 ++---- extensions/workspace-indicator/prefs.js | 17 +++------- 15 files changed, 69 insertions(+), 125 deletions(-) diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js index 76c0e270..b9364442 100644 --- a/extensions/apps-menu/extension.js +++ b/extensions/apps-menu/extension.js @@ -11,15 +11,13 @@ import Shell from 'gi://Shell'; import St from 'gi://St'; const {EventEmitter} = imports.misc.signals; -import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; +import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; const DND = imports.ui.dnd; const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; -const _ = ExtensionUtils.gettext; - const appSys = Shell.AppSystem.get_default(); const APPLICATION_ICON_SIZE = 32; @@ -391,7 +389,7 @@ class ApplicationsButton extends PanelMenu.Button { Main.wm.addKeybinding( 'apps-menu-toggle-menu', - ExtensionUtils.getSettings(), + Extension.lookupByURL(import.meta.url).getSettings(), Meta.KeyBindingFlags.IGNORE_AUTOREPEAT, Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW, () => this.menu.toggle()); @@ -670,11 +668,7 @@ class ApplicationsButton extends PanelMenu.Button { } } -export default class Extension { - constructor() { - ExtensionUtils.initTranslations(); - } - +export default class AppsMenuExtension extends Extension { enable() { this._appsMenuButton = new ApplicationsButton(); const index = Main.sessionMode.panel.left.indexOf('activities') + 1; diff --git a/extensions/auto-move-windows/extension.js b/extensions/auto-move-windows/extension.js index 313982a8..d439cf1e 100644 --- a/extensions/auto-move-windows/extension.js +++ b/extensions/auto-move-windows/extension.js @@ -3,13 +3,13 @@ import Shell from 'gi://Shell'; -import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; +import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; const Main = imports.ui.main; class WindowMover { - constructor() { - this._settings = ExtensionUtils.getSettings(); + constructor(settings) { + this._settings = settings; this._appSystem = Shell.AppSystem.get_default(); this._appConfigs = new Map(); this._appData = new Map(); @@ -97,12 +97,12 @@ class WindowMover { } } -export default class Extension { +export default class AutoMoveExtension extends Extension { enable() { this._prevCheckWorkspaces = Main.wm._workspaceTracker._checkWorkspaces; Main.wm._workspaceTracker._checkWorkspaces = this._getCheckWorkspaceOverride(this._prevCheckWorkspaces); - this._windowMover = new WindowMover(); + this._windowMover = new WindowMover(this.getSettings()); } disable() { diff --git a/extensions/auto-move-windows/prefs.js b/extensions/auto-move-windows/prefs.js index 395fbd9b..62be52a0 100644 --- a/extensions/auto-move-windows/prefs.js +++ b/extensions/auto-move-windows/prefs.js @@ -7,9 +7,7 @@ import GLib from 'gi://GLib'; import GObject from 'gi://GObject'; import Gtk from 'gi://Gtk'; -import * as ExtensionUtils from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -const _ = ExtensionUtils.gettext; +import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; const SETTINGS_KEY = 'application-list'; @@ -62,13 +60,14 @@ class RulesList extends GObject.Object { GObject.registerClass(this); } - #settings = ExtensionUtils.getSettings(); + #settings; #rules = []; #changedId; - constructor() { + constructor(settings) { super(); + this.#settings = settings; this.#changedId = this.#settings.connect(`changed::${SETTINGS_KEY}`, () => this.#sync()); @@ -150,12 +149,13 @@ class AutoMoveSettingsWidget extends Adw.PreferencesGroup { (self, name, param) => self._rules.changeWorkspace(...param.deepUnpack())); } - constructor() { + constructor(settings) { super({ title: _('Workspace Rules'), }); - this._rules = new RulesList(); + this._settings = settings; + this._rules = new RulesList(this._settings); const store = new Gio.ListStore({item_type: Gio.ListModel}); const listModel = new Gtk.FlattenListModel({model: store}); @@ -176,7 +176,7 @@ class AutoMoveSettingsWidget extends Adw.PreferencesGroup { } _addNewRule() { - const dialog = new NewRuleDialog(this.get_root()); + const dialog = new NewRuleDialog(this.get_root(), this._settings); dialog.connect('response', (dlg, id) => { const appInfo = id === Gtk.ResponseType.OK ? dialog.get_widget().get_app_info() : null; @@ -315,13 +315,13 @@ class NewRuleDialog extends Gtk.AppChooserDialog { GObject.registerClass(this); } - constructor(parent) { + constructor(parent, settings) { super({ transient_for: parent, modal: true, }); - this._settings = ExtensionUtils.getSettings(); + this._settings = settings; this.get_widget().set({ show_all: true, @@ -341,16 +341,8 @@ class NewRuleDialog extends Gtk.AppChooserDialog { } } -export default class ExtensionPreferences { - constructor() { - ExtensionUtils.initTranslations(); - } - - fillPreferencesWindow(window) { - const page = new Adw.PreferencesPage(); - window.add(page); - - const group = new AutoMoveSettingsWidget(); - page.add(group); +export default class AutoMovePrefs extends ExtensionPreferences { + getPreferencesWidget() { + return new AutoMoveSettingsWidget(this.getSettings()); } } diff --git a/extensions/drive-menu/extension.js b/extensions/drive-menu/extension.js index 635a19a1..cb9986fe 100644 --- a/extensions/drive-menu/extension.js +++ b/extensions/drive-menu/extension.js @@ -5,15 +5,13 @@ import GObject from 'gi://GObject'; import Shell from 'gi://Shell'; import St from 'gi://St'; -import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; +import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; const ShellMountOperation = imports.ui.shellMountOperation; -const _ = ExtensionUtils.gettext; - Gio._promisify(Gio.File.prototype, 'query_filesystem_info_async'); class MountMenuItem extends PopupMenu.PopupBaseMenuItem { @@ -197,11 +195,7 @@ class DriveMenu extends PanelMenu.Button { } } -export default class Extension { - constructor() { - ExtensionUtils.initTranslations(); - } - +export default class PlaceMenuExtension extends Extension { enable() { this._indicator = new DriveMenu(); Main.panel.addToStatusArea('drive-menu', this._indicator); diff --git a/extensions/native-window-placement/extension.js b/extensions/native-window-placement/extension.js index ce7122d7..1b30e4ac 100644 --- a/extensions/native-window-placement/extension.js +++ b/extensions/native-window-placement/extension.js @@ -1,7 +1,7 @@ // -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- import Clutter from 'gi://Clutter'; -import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; +import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; const Main = imports.ui.main; const {WindowPreview} = imports.ui.windowPreview; @@ -236,13 +236,15 @@ class NaturalLayoutStrategy extends Workspace.LayoutStrategy { } } -export default class Extension { - constructor() { +export default class NativeWindowPlacementExtension extends Extension { + constructor(metadata) { + super(metadata); + this._savedMethods = new Map(); } enable() { - const settings = ExtensionUtils.getSettings(); + const settings = this.getSettings(); const layoutProto = Workspace.WorkspaceLayout.prototype; const previewProto = WindowPreview.prototype; diff --git a/extensions/places-menu/extension.js b/extensions/places-menu/extension.js index 2136fd71..83e63dc1 100644 --- a/extensions/places-menu/extension.js +++ b/extensions/places-menu/extension.js @@ -3,7 +3,7 @@ import Clutter from 'gi://Clutter'; import GObject from 'gi://GObject'; import St from 'gi://St'; -import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; +import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; @@ -11,7 +11,6 @@ const PopupMenu = imports.ui.popupMenu; import {PlacesManager} from './placeDisplay.js'; -const _ = ExtensionUtils.gettext; const N_ = x => x; const PLACE_ICON_SIZE = 16; @@ -129,11 +128,7 @@ class PlacesMenu extends PanelMenu.Button { } } -export default class Extension { - constructor() { - ExtensionUtils.initTranslations(); - } - +export default class PlacesMenuExtension extends Extension { enable() { this._indicator = new PlacesMenu(); diff --git a/extensions/places-menu/placeDisplay.js b/extensions/places-menu/placeDisplay.js index abbb6a8f..ffd86eb3 100644 --- a/extensions/places-menu/placeDisplay.js +++ b/extensions/places-menu/placeDisplay.js @@ -4,12 +4,11 @@ import GLib from 'gi://GLib'; import Shell from 'gi://Shell'; const {EventEmitter} = imports.misc.signals; -import {gettext} from 'resource:///org/gnome/shell/extensions/extension.js'; +import {gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; const Main = imports.ui.main; const ShellMountOperation = imports.ui.shellMountOperation; -const _ = gettext; const N_ = x => x; Gio._promisify(Gio.AppInfo, 'launch_default_for_uri_async'); diff --git a/extensions/screenshot-window-sizer/extension.js b/extensions/screenshot-window-sizer/extension.js index 3dba8202..05d9dbcc 100644 --- a/extensions/screenshot-window-sizer/extension.js +++ b/extensions/screenshot-window-sizer/extension.js @@ -23,13 +23,13 @@ import Meta from 'gi://Meta'; import Shell from 'gi://Shell'; import St from 'gi://St'; -import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; +import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; const Main = imports.ui.main; const MESSAGE_FADE_TIME = 2000; -export default class Extension { +export default class ScreenshotWindowSizerExtension extends Extension { SIZES = [ [624, 351], [800, 450], @@ -149,13 +149,13 @@ export default class Extension { enable() { Main.wm.addKeybinding( 'cycle-screenshot-sizes', - ExtensionUtils.getSettings(), + this.getSettings(), Meta.KeyBindingFlags.PER_WINDOW, Shell.ActionMode.NORMAL, this._cycleScreenshotSizes.bind(this)); Main.wm.addKeybinding( 'cycle-screenshot-sizes-backward', - ExtensionUtils.getSettings(), + this.getSettings(), Meta.KeyBindingFlags.PER_WINDOW | Meta.KeyBindingFlags.IS_REVERSED, Shell.ActionMode.NORMAL, this._cycleScreenshotSizes.bind(this)); diff --git a/extensions/user-theme/extension.js b/extensions/user-theme/extension.js index ea72c16c..a2a6cbca 100644 --- a/extensions/user-theme/extension.js +++ b/extensions/user-theme/extension.js @@ -3,7 +3,7 @@ import Gio from 'gi://Gio'; -import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; +import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; const Main = imports.ui.main; @@ -11,9 +11,9 @@ import {getThemeDirs, getModeThemeDirs} from './util.js'; const SETTINGS_KEY = 'name'; -export default class ThemeManager { +export default class ThemeManager extends Extension { enable() { - this._settings = ExtensionUtils.getSettings(); + this._settings = this.getSettings(); this._settings.connect(`changed::${SETTINGS_KEY}`, this._changeTheme.bind(this)); this._changeTheme(); } diff --git a/extensions/user-theme/prefs.js b/extensions/user-theme/prefs.js index 054d528a..98a27309 100644 --- a/extensions/user-theme/prefs.js +++ b/extensions/user-theme/prefs.js @@ -9,7 +9,7 @@ import GLib from 'gi://GLib'; import GObject from 'gi://GObject'; import Gtk from 'gi://Gtk'; -import * as ExtensionUtils from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; +import {ExtensionPreferences} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; import {getThemeDirs, getModeThemeDirs} from './util.js'; @@ -22,13 +22,13 @@ class UserThemePrefsWidget extends Adw.PreferencesGroup { GObject.registerClass(this); } - constructor() { + constructor(settings) { super({title: 'Themes'}); this._actionGroup = new Gio.SimpleActionGroup(); this.insert_action_group('theme', this._actionGroup); - this._settings = ExtensionUtils.getSettings(); + this._settings = settings; this._actionGroup.add_action( this._settings.create_action('name')); @@ -127,12 +127,8 @@ class ThemeRow extends Adw.ActionRow { } } -export default class ExtensionPreferences { - fillPreferencesWindow(window) { - const page = new Adw.PreferencesPage(); - window.add(page); - - const group = new UserThemePrefsWidget(); - page.add(group); +export default class UserThemePrefs extends ExtensionPreferences { + getPreferencesWidget() { + return new UserThemePrefsWidget(this.getSettings()); } } diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js index f7dd8b60..8f7205f3 100644 --- a/extensions/window-list/extension.js +++ b/extensions/window-list/extension.js @@ -7,7 +7,7 @@ import Meta from 'gi://Meta'; import Shell from 'gi://Shell'; import St from 'gi://St'; -import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; +import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; const DND = imports.ui.dnd; const Main = imports.ui.main; @@ -17,8 +17,6 @@ const PopupMenu = imports.ui.popupMenu; import {WindowPicker, WindowPickerToggle} from './windowPicker.js'; import {WorkspaceIndicator} from './workspaceIndicator.js'; -const _ = ExtensionUtils.gettext; - const ICON_TEXTURE_SIZE = 24; const DND_ACTIVATE_TIMEOUT = 500; @@ -31,8 +29,6 @@ const GroupingMode = { ALWAYS: 2, }; -let Me = null; - /** * @param {Shell.App} app - an app * @returns {number} - the smallest stable sequence of the app's windows @@ -322,9 +318,11 @@ class BaseButton extends St.Button { if (isOpen) return; + const extension = Extension.lookupByURL(import.meta.url); + let [x, y] = global.get_pointer(); let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y); - if (Me.someWindowListContains(actor)) + if (extension.someWindowListContains(actor)) actor.sync_hover(); } @@ -710,7 +708,7 @@ class WindowList extends St.Widget { GObject.registerClass(this); } - constructor(perMonitor, monitor) { + constructor(perMonitor, monitor, settings) { super({ name: 'panel', style_class: 'bottom-panel solid', @@ -839,7 +837,7 @@ class WindowList extends St.Widget { this._dndTimeoutId = 0; this._dndWindow = null; - this._settings = ExtensionUtils.getSettings(); + this._settings = settings; this._settings.connect('changed::grouping-mode', () => this._groupingModeChanged()); this._grouped = undefined; @@ -1095,11 +1093,9 @@ class WindowList extends St.Widget { } } -export default class Extension { - constructor() { - ExtensionUtils.initTranslations(); - - Me = this; +export default class WindowListExtension extends Extension { + constructor(metadata) { + super(metadata); this._windowLists = null; this._hideOverviewOrig = Main.overview.hide; @@ -1108,7 +1104,7 @@ export default class Extension { enable() { this._windowLists = []; - this._settings = ExtensionUtils.getSettings(); + this._settings = this.getSettings(); this._settings.connectObject('changed::show-on-all-monitors', () => this._buildWindowLists(), this); @@ -1133,7 +1129,7 @@ export default class Extension { Main.layoutManager.monitors.forEach(monitor => { if (showOnAllMonitors || monitor === Main.layoutManager.primaryMonitor) - this._windowLists.push(new WindowList(showOnAllMonitors, monitor)); + this._windowLists.push(new WindowList(showOnAllMonitors, monitor, this.getSettings())); }); } diff --git a/extensions/window-list/prefs.js b/extensions/window-list/prefs.js index 68812457..2e33dfb0 100644 --- a/extensions/window-list/prefs.js +++ b/extensions/window-list/prefs.js @@ -5,22 +5,20 @@ import GLib from 'gi://GLib'; import GObject from 'gi://GObject'; import Gtk from 'gi://Gtk'; -import * as ExtensionUtils from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -const _ = ExtensionUtils.gettext; +import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; class WindowListPrefsWidget extends Adw.PreferencesPage { static { GObject.registerClass(this); } - constructor() { + constructor(settings) { super(); this._actionGroup = new Gio.SimpleActionGroup(); this.insert_action_group('window-list', this._actionGroup); - this._settings = ExtensionUtils.getSettings(); + this._settings = settings; this._actionGroup.add_action( this._settings.create_action('grouping-mode')); this._actionGroup.add_action( @@ -81,13 +79,8 @@ class WindowListPrefsWidget extends Adw.PreferencesPage { } } -export default class ExtensionPreferences { - constructor() { - ExtensionUtils.initTranslations(); - } - - fillPreferencesWindow(window) { - const page = new WindowListPrefsWidget(); - window.add(page); +export default class WindowListPrefs extends ExtensionPreferences { + getPreferencesWidget() { + return new WindowListPrefsWidget(this.getSettings()); } } diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js index 6eeea3e7..4e50c288 100644 --- a/extensions/window-list/workspaceIndicator.js +++ b/extensions/window-list/workspaceIndicator.js @@ -4,15 +4,13 @@ import GObject from 'gi://GObject'; import Meta from 'gi://Meta'; import St from 'gi://St'; -import {gettext} from 'resource:///org/gnome/shell/extensions/extension.js'; +import {gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; const DND = imports.ui.dnd; const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; -const _ = gettext; - const TOOLTIP_OFFSET = 6; const TOOLTIP_ANIMATION_TIME = 150; diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js index 1c44ba74..78037d91 100644 --- a/extensions/workspace-indicator/extension.js +++ b/extensions/workspace-indicator/extension.js @@ -5,15 +5,13 @@ import GObject from 'gi://GObject'; import Meta from 'gi://Meta'; import St from 'gi://St'; -import * as ExtensionUtils from 'resource:///org/gnome/shell/extensions/extension.js'; +import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; const DND = imports.ui.dnd; const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; -const _ = ExtensionUtils.gettext; - const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences'; const WORKSPACE_KEY = 'workspace-names'; @@ -428,11 +426,7 @@ class WorkspaceIndicator extends PanelMenu.Button { } } -export default class Extension { - constructor() { - ExtensionUtils.initTranslations(); - } - +export default class WorkspaceIndicatorExtension extends Extension { enable() { this._indicator = new WorkspaceIndicator(); Main.panel.addToStatusArea('workspace-indicator', this._indicator); diff --git a/extensions/workspace-indicator/prefs.js b/extensions/workspace-indicator/prefs.js index 014e7b3a..78e75282 100644 --- a/extensions/workspace-indicator/prefs.js +++ b/extensions/workspace-indicator/prefs.js @@ -6,9 +6,8 @@ import GObject from 'gi://GObject'; import Gtk from 'gi://Gtk'; import Pango from 'gi://Pango'; -import * as ExtensionUtils from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; +import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; -const _ = ExtensionUtils.gettext; const N_ = e => e; const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences'; @@ -259,16 +258,8 @@ class NewWorkspaceRow extends Adw.PreferencesRow { } } -export default class ExtensionPreferences { - constructor() { - ExtensionUtils.initTranslations(); - } - - fillPreferencesWindow(window) { - const page = new Adw.PreferencesPage(); - window.add(page); - - const group = new WorkspaceSettingsWidget(); - page.add(group); +export default class WorkspaceIndicatorPrefs extends ExtensionPreferences { + getPreferencesWidget() { + return new WorkspaceSettingsWidget(); } } From 017c410a6a895a08fe85af6af9d81d190c7baba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sat, 5 Aug 2023 16:13:46 +0200 Subject: [PATCH 26/32] native-window-placement: Use InjectionManager The new convenience class was modelled after the code in the extension, so it's a drop-in replacement. Part-of: --- .../native-window-placement/extension.js | 41 +++---------------- 1 file changed, 6 insertions(+), 35 deletions(-) diff --git a/extensions/native-window-placement/extension.js b/extensions/native-window-placement/extension.js index 1b30e4ac..85430479 100644 --- a/extensions/native-window-placement/extension.js +++ b/extensions/native-window-placement/extension.js @@ -1,7 +1,7 @@ // -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- import Clutter from 'gi://Clutter'; -import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; +import {Extension, InjectionManager} from 'resource:///org/gnome/shell/extensions/extension.js'; const Main = imports.ui.main; const {WindowPreview} = imports.ui.windowPreview; @@ -240,7 +240,7 @@ export default class NativeWindowPlacementExtension extends Extension { constructor(metadata) { super(metadata); - this._savedMethods = new Map(); + this._injectionManager = new InjectionManager(); } enable() { @@ -249,7 +249,7 @@ export default class NativeWindowPlacementExtension extends Extension { const layoutProto = Workspace.WorkspaceLayout.prototype; const previewProto = WindowPreview.prototype; - this._overrideMethod(layoutProto, '_createBestLayout', () => { + this._injectionManager.overrideMethod(layoutProto, '_createBestLayout', () => { /* eslint-disable no-invalid-this */ return function () { this._layoutStrategy = new NaturalLayoutStrategy({ @@ -261,7 +261,7 @@ export default class NativeWindowPlacementExtension extends Extension { }); // position window titles on top of windows in overlay - this._overrideMethod(previewProto, '_init', originalMethod => { + this._injectionManager.overrideMethod(previewProto, '_init', originalMethod => { /* eslint-disable no-invalid-this */ return function (...args) { originalMethod.call(this, ...args); @@ -280,7 +280,7 @@ export default class NativeWindowPlacementExtension extends Extension { /* eslint-enable no-invalid-this */ }); - this._overrideMethod(previewProto, '_adjustOverlayOffsets', originalMethod => { + this._injectionManager.overrideMethod(previewProto, '_adjustOverlayOffsets', originalMethod => { /* eslint-disable no-invalid-this */ return function (...args) { originalMethod.call(this, ...args); @@ -293,36 +293,7 @@ export default class NativeWindowPlacementExtension extends Extension { } disable() { - this._restoreMethods(); + this._injectionManager.clear(); global.stage.queue_relayout(); } - - _saveMethod(prototype, methodName) { - let map = this._savedMethods.get(prototype); - if (!map) { - map = new Map(); - this._savedMethods.set(prototype, map); - } - - const originalMethod = prototype[methodName]; - map.set(methodName, originalMethod); - return originalMethod; - } - - _overrideMethod(prototype, methodName, createOverrideFunc) { - const originalMethod = this._saveMethod(prototype, methodName); - prototype[methodName] = createOverrideFunc(originalMethod); - } - - _restoreMethods() { - for (const [proto, map] of this._savedMethods) { - for (const [methodName, originalMethod] of map) { - if (originalMethod === undefined) - delete proto[methodName]; - else - proto[methodName] = originalMethod; - } - } - this._savedMethods.clear(); - } } From 0544729bbaa4bea29afadc07cc8e6c595007877e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sat, 5 Aug 2023 16:17:25 +0200 Subject: [PATCH 27/32] launch-new-instance: Use InjectionManager The extension uses a straight-forward override that doesn't benefit a lot from the new InjectionManager class, but let's use the provided convenience API anyway. Part-of: --- extensions/launch-new-instance/extension.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/extensions/launch-new-instance/extension.js b/extensions/launch-new-instance/extension.js index 53d8ae25..b542fad2 100644 --- a/extensions/launch-new-instance/extension.js +++ b/extensions/launch-new-instance/extension.js @@ -1,19 +1,23 @@ -const AppDisplay = imports.ui.appDisplay; +import {InjectionManager} from 'resource:///org/gnome/shell/extensions/extension.js'; + +const {AppIcon} = imports.ui.appDisplay; export default class Extension { constructor() { - this._appIconProto = AppDisplay.AppIcon.prototype; - this._activateOriginal = this._appIconProto.activate; + this._injectionManager = new InjectionManager(); } enable() { - const {_activateOriginal} = this; - this._appIconProto.activate = function () { - _activateOriginal.call(this, 2); - }; + this._injectionManager.overrideMethod(AppIcon.prototype, 'activate', + originalMethod => { + return function () { + // eslint-disable-next-line no-invalid-this + originalMethod.call(this, 2); + }; + }); } disable() { - this._appIconProto.activate = this._activateOriginal; + this._injectionManager.clear(); } } From cb8c2eb27f408f9698abb1784f4dbb3047b73c44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sun, 6 Aug 2023 13:20:38 +0200 Subject: [PATCH 28/32] windowsNavigator: Use InjectionManager instead of custom classes Once the shell is ported to ESM, it will no longer be possible to replace entire classes (even when exported). Prepare for that by overriding methods of the regular classes, instead of creating custom subclasses. Part-of: --- extensions/windowsNavigator/extension.js | 515 ++++++++++++----------- 1 file changed, 271 insertions(+), 244 deletions(-) diff --git a/extensions/windowsNavigator/extension.js b/extensions/windowsNavigator/extension.js index 2ae74cf8..32544b9b 100644 --- a/extensions/windowsNavigator/extension.js +++ b/extensions/windowsNavigator/extension.js @@ -1,264 +1,291 @@ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ import Clutter from 'gi://Clutter'; import Graphene from 'gi://Graphene'; -import GObject from 'gi://GObject'; import St from 'gi://St'; +import {InjectionManager} from 'resource:///org/gnome/shell/extensions/extension.js'; + const Main = imports.ui.main; const OverviewControls = imports.ui.overviewControls; -const Workspace = imports.ui.workspace; -const WorkspacesView = imports.ui.workspacesView; +const {WindowPreview} = imports.ui.windowPreview; +const {Workspace} = imports.ui.workspace; +const {WorkspacesView} = imports.ui.workspacesView; const WINDOW_SLOT = 4; -class MyWorkspace extends Workspace.Workspace { - static { - GObject.registerClass(this); - } - - constructor(...args) { - super(...args); - - if (this.metaWorkspace && this.metaWorkspace.index() < 9) { - this._tip = new St.Label({ - style_class: 'extension-windowsNavigator-window-tooltip', - visible: false, - }); - this.add_actor(this._tip); - - this.connect('notify::scale-x', () => { - this._tip.set_scale(1 / this.scale_x, 1 / this.scale_x); - }); - } else { - this._tip = null; - } - } - - vfunc_allocate(box) { - super.vfunc_allocate(box); - - if (this._tip) - this._tip.allocate_preferred_size(0, 0); - } - - showTooltip() { - if (!this._tip) - return; - this._tip.text = (this.metaWorkspace.index() + 1).toString(); - this._tip.show(); - this.set_child_below_sibling(this._tip, null); - } - - hideTooltip() { - if (this._tip) - this._tip.hide(); - } - - getWindowWithTooltip(id) { - const {layoutManager} = this._container; - const slot = layoutManager._windowSlots[id - 1]; - return slot ? slot[WINDOW_SLOT].metaWindow : null; - } - - showWindowsTooltips() { - const {layoutManager} = this._container; - for (let i = 0; i < layoutManager._windowSlots.length; i++) { - if (layoutManager._windowSlots[i]) - layoutManager._windowSlots[i][WINDOW_SLOT].showTooltip(`${i + 1}`); - } - } - - hideWindowsTooltips() { - const {layoutManager} = this._container; - for (let i in layoutManager._windowSlots) { - if (layoutManager._windowSlots[i]) - layoutManager._windowSlots[i][WINDOW_SLOT].hideTooltip(); - } - } - - // overriding _addWindowClone to apply the tooltip patch on the cloned - // windowPreview - _addWindowClone(metaWindow) { - const clone = super._addWindowClone(metaWindow); - - // appling the tooltip patch - (function patchPreview() { - this._text = new St.Label({ - style_class: 'extension-windowsNavigator-window-tooltip', - visible: false, - }); - - this._text.add_constraint(new Clutter.BindConstraint({ - source: this.windowContainer, - coordinate: Clutter.BindCoordinate.POSITION, - })); - this._text.add_constraint(new Clutter.AlignConstraint({ - source: this.windowContainer, - align_axis: Clutter.AlignAxis.X_AXIS, - pivot_point: new Graphene.Point({x: 0.5, y: -1}), - factor: this._closeButtonSide === St.Side.LEFT ? 1 : 0, - })); - this._text.add_constraint(new Clutter.AlignConstraint({ - source: this.windowContainer, - align_axis: Clutter.AlignAxis.Y_AXIS, - pivot_point: new Graphene.Point({x: -1, y: 0.5}), - factor: 0, - })); - - this.add_child(this._text); - }).call(clone); - - clone.showTooltip = function (text) { - this._text.set({text}); - this._text.show(); - }; - - clone.hideTooltip = function () { - if (this._text && this._text.visible) - this._text.hide(); - }; - - return clone; - } -} - -class MyWorkspacesView extends WorkspacesView.WorkspacesView { - static { - GObject.registerClass(this); - } - - constructor(...args) { - super(...args); - - this._pickWorkspace = false; - this._pickWindow = false; - global.stage.connectObject( - 'key-press-event', this._onKeyPress.bind(this), - 'key-release-event', this._onKeyRelease.bind(this), - this); - } - - _hideTooltips() { - if (global.stage.get_key_focus() === global.stage) - global.stage.set_key_focus(this._prevFocusActor); - this._pickWindow = false; - for (let i = 0; i < this._workspaces.length; i++) - this._workspaces[i].hideWindowsTooltips(); - } - - _hideWorkspacesTooltips() { - global.stage.set_key_focus(this._prevFocusActor); - this._pickWorkspace = false; - for (let i = 0; i < this._workspaces.length; i++) - this._workspaces[i].hideTooltip(); - } - - _onKeyRelease(s, o) { - if (this._pickWindow && - (o.get_key_symbol() === Clutter.KEY_Alt_L || - o.get_key_symbol() === Clutter.KEY_Alt_R)) - this._hideTooltips(); - if (this._pickWorkspace && - (o.get_key_symbol() === Clutter.KEY_Control_L || - o.get_key_symbol() === Clutter.KEY_Control_R)) - this._hideWorkspacesTooltips(); - } - - _onKeyPress(s, o) { - const {ControlsState} = OverviewControls; - if (this._overviewAdjustment.value !== ControlsState.WINDOW_PICKER) - return false; - - let workspaceManager = global.workspace_manager; - - if ((o.get_key_symbol() === Clutter.KEY_Alt_L || - o.get_key_symbol() === Clutter.KEY_Alt_R) && - !this._pickWorkspace) { - this._prevFocusActor = global.stage.get_key_focus(); - global.stage.set_key_focus(null); - this._active = workspaceManager.get_active_workspace_index(); - this._pickWindow = true; - this._workspaces[workspaceManager.get_active_workspace_index()].showWindowsTooltips(); - return true; - } - if ((o.get_key_symbol() === Clutter.KEY_Control_L || - o.get_key_symbol() === Clutter.KEY_Control_R) && - !this._pickWindow) { - this._prevFocusActor = global.stage.get_key_focus(); - global.stage.set_key_focus(null); - this._pickWorkspace = true; - for (let i = 0; i < this._workspaces.length; i++) - this._workspaces[i].showTooltip(); - return true; - } - - if (global.stage.get_key_focus() !== global.stage) - return false; - - // ignore shift presses, they're required to get numerals in azerty keyboards - if ((this._pickWindow || this._pickWorkspace) && - (o.get_key_symbol() === Clutter.KEY_Shift_L || - o.get_key_symbol() === Clutter.KEY_Shift_R)) - return true; - - if (this._pickWindow) { - if (this._active !== workspaceManager.get_active_workspace_index()) { - this._hideTooltips(); - return false; - } - - let c = o.get_key_symbol() - Clutter.KEY_KP_0; - if (c > 9 || c <= 0) { - c = o.get_key_symbol() - Clutter.KEY_0; - if (c > 9 || c <= 0) { - this._hideTooltips(); - log(c); - return false; - } - } - - let win = this._workspaces[this._active].getWindowWithTooltip(c); - this._hideTooltips(); - - if (win) - Main.activateWindow(win, global.get_current_time()); - - return true; - } - if (this._pickWorkspace) { - let c = o.get_key_symbol() - Clutter.KEY_KP_0; - if (c > 9 || c <= 0) { - c = o.get_key_symbol() - Clutter.KEY_0; - if (c > 9 || c <= 0) { - this._hideWorkspacesTooltips(); - return false; - } - } - - let workspace = this._workspaces[c - 1]; - if (workspace !== undefined) - workspace.metaWorkspace.activate(global.get_current_time()); - - this._hideWorkspacesTooltips(); - return true; - } - return false; - } -} - export default class Extension { constructor() { - this._origWorkspace = Workspace.Workspace; - this._origWorkspacesView = WorkspacesView.WorkspacesView; + this._injectionManager = new InjectionManager(); } enable() { - Workspace.Workspace = MyWorkspace; - WorkspacesView.WorkspacesView = MyWorkspacesView; + const previewProto = WindowPreview.prototype; + + this._injectionManager.overrideMethod(previewProto, '_init', originalMethod => { + /* eslint-disable no-invalid-this */ + return function (...args) { + originalMethod.call(this, ...args); + + this._text = new St.Label({ + style_class: 'extension-windowsNavigator-window-tooltip', + visible: false, + }); + + this._text.add_constraint(new Clutter.BindConstraint({ + source: this.windowContainer, + coordinate: Clutter.BindCoordinate.POSITION, + })); + this._text.add_constraint(new Clutter.AlignConstraint({ + source: this.windowContainer, + align_axis: Clutter.AlignAxis.X_AXIS, + pivot_point: new Graphene.Point({x: 0.5, y: -1}), + factor: this._closeButtonSide === St.Side.LEFT ? 1 : 0, + })); + this._text.add_constraint(new Clutter.AlignConstraint({ + source: this.windowContainer, + align_axis: Clutter.AlignAxis.Y_AXIS, + pivot_point: new Graphene.Point({x: -1, y: 0.5}), + factor: 0, + })); + + this.add_child(this._text); + }; + /* eslint-enable */ + }); + this._injectionManager.overrideMethod(previewProto, 'showTooltip', () => { + /* eslint-disable no-invalid-this */ + return function (text) { + this._text.set({text}); + this._text.show(); + }; + /* eslint-enable */ + }); + this._injectionManager.overrideMethod(previewProto, 'hideTooltip', () => { + /* eslint-disable no-invalid-this */ + return function () { + this._text?.hide(); + }; + /* eslint-enable */ + }); + + const workspaceProto = Workspace.prototype; + this._injectionManager.overrideMethod(workspaceProto, '_init', originalMethod => { + /* eslint-disable no-invalid-this */ + return function (...args) { + originalMethod.call(this, ...args); + + if (this.metaWorkspace && this.metaWorkspace.index() < 9) { + this._tip = new St.Label({ + style_class: 'extension-windowsNavigator-window-tooltip', + visible: false, + }); + this.add_actor(this._tip); + + this.connect('notify::scale-x', () => { + this._tip.set_scale(1 / this.scale_x, 1 / this.scale_x); + }); + } else { + this._tip = null; + } + }; + /* eslint-enable */ + }); + this._injectionManager.overrideMethod(workspaceProto, 'vfunc_allocate', originalMethod => { + /* eslint-disable no-invalid-this */ + return function (box) { + originalMethod.call(this, box); + + this._tip?.allocate_preferred_size(0, 0); + }; + /* eslint-enable */ + }); + this._injectionManager.overrideMethod(workspaceProto, 'showTooltip', () => { + /* eslint-disable no-invalid-this */ + return function () { + if (!this._tip) + return; + this._tip.text = (this.metaWorkspace.index() + 1).toString(); + this._tip.show(); + this.set_child_below_sibling(this._tip, null); + }; + /* eslint-enable */ + }); + this._injectionManager.overrideMethod(workspaceProto, 'hideTooltip', () => { + /* eslint-disable no-invalid-this */ + return function () { + this._tip?.hide(); + }; + /* eslint-enable */ + }); + this._injectionManager.overrideMethod(workspaceProto, 'getWindowWithTooltip', () => { + /* eslint-disable no-invalid-this */ + return function (id) { + const {layoutManager} = this._container; + const slot = layoutManager._windowSlots[id - 1]; + return slot ? slot[WINDOW_SLOT].metaWindow : null; + }; + /* eslint-enable */ + }); + this._injectionManager.overrideMethod(workspaceProto, 'showWindowsTooltips', () => { + /* eslint-disable no-invalid-this */ + return function () { + const {layoutManager} = this._container; + for (let i = 0; i < layoutManager._windowSlots.length; i++) { + if (layoutManager._windowSlots[i]) + layoutManager._windowSlots[i][WINDOW_SLOT].showTooltip(`${i + 1}`); + } + }; + /* eslint-enable */ + }); + this._injectionManager.overrideMethod(workspaceProto, 'hideWindowsTooltips', () => { + /* eslint-disable no-invalid-this */ + return function () { + const {layoutManager} = this._container; + for (let i in layoutManager._windowSlots) { + if (layoutManager._windowSlots[i]) + layoutManager._windowSlots[i][WINDOW_SLOT].hideTooltip(); + } + }; + /* eslint-enable */ + }); + + const viewProto = WorkspacesView.prototype; + this._injectionManager.overrideMethod(viewProto, '_init', originalMethod => { + /* eslint-disable no-invalid-this */ + return function (...args) { + originalMethod.call(this, ...args); + + this._pickWorkspace = false; + this._pickWindow = false; + global.stage.connectObject( + 'key-press-event', this._onKeyPress.bind(this), + 'key-release-event', this._onKeyRelease.bind(this), + this); + }; + /* eslint-enable */ + }); + this._injectionManager.overrideMethod(viewProto, '_hideTooltips', () => { + /* eslint-disable no-invalid-this */ + return function () { + if (global.stage.get_key_focus() === global.stage) + global.stage.set_key_focus(this._prevFocusActor); + this._pickWindow = false; + for (let i = 0; i < this._workspaces.length; i++) + this._workspaces[i].hideWindowsTooltips(); + }; + /* eslint-enable */ + }); + this._injectionManager.overrideMethod(viewProto, '_hideWorkspacesTooltips', () => { + /* eslint-disable no-invalid-this */ + return function () { + global.stage.set_key_focus(this._prevFocusActor); + this._pickWorkspace = false; + for (let i = 0; i < this._workspaces.length; i++) + this._workspaces[i].hideTooltip(); + }; + /* eslint-enable */ + }); + this._injectionManager.overrideMethod(viewProto, '_onKeyRelease', () => { + /* eslint-disable no-invalid-this */ + return function (actor, event) { + if (this._pickWindow && + (event.get_key_symbol() === Clutter.KEY_Alt_L || + event.get_key_symbol() === Clutter.KEY_Alt_R)) + this._hideTooltips(); + if (this._pickWorkspace && + (event.get_key_symbol() === Clutter.KEY_Control_L || + event.get_key_symbol() === Clutter.KEY_Control_R)) + this._hideWorkspacesTooltips(); + }; + /* eslint-enable */ + }); + this._injectionManager.overrideMethod(viewProto, '_onKeyPress', () => { + /* eslint-disable no-invalid-this */ + return function (actor, event) { + const {ControlsState} = OverviewControls; + if (this._overviewAdjustment.value !== ControlsState.WINDOW_PICKER) + return false; + + let workspaceManager = global.workspace_manager; + + if ((event.get_key_symbol() === Clutter.KEY_Alt_L || + event.get_key_symbol() === Clutter.KEY_Alt_R) && + !this._pickWorkspace) { + this._prevFocusActor = global.stage.get_key_focus(); + global.stage.set_key_focus(null); + this._active = workspaceManager.get_active_workspace_index(); + this._pickWindow = true; + this._workspaces[workspaceManager.get_active_workspace_index()].showWindowsTooltips(); + return true; + } + if ((event.get_key_symbol() === Clutter.KEY_Control_L || + event.get_key_symbol() === Clutter.KEY_Control_R) && + !this._pickWindow) { + this._prevFocusActor = global.stage.get_key_focus(); + global.stage.set_key_focus(null); + this._pickWorkspace = true; + for (let i = 0; i < this._workspaces.length; i++) + this._workspaces[i].showTooltip(); + return true; + } + + if (global.stage.get_key_focus() !== global.stage) + return false; + + // ignore shift presses, they're required to get numerals in azerty keyboards + if ((this._pickWindow || this._pickWorkspace) && + (event.get_key_symbol() === Clutter.KEY_Shift_L || + event.get_key_symbol() === Clutter.KEY_Shift_R)) + return true; + + if (this._pickWindow) { + if (this._active !== workspaceManager.get_active_workspace_index()) { + this._hideTooltips(); + return false; + } + + let c = event.get_key_symbol() - Clutter.KEY_KP_0; + if (c > 9 || c <= 0) { + c = event.get_key_symbol() - Clutter.KEY_0; + if (c > 9 || c <= 0) { + this._hideTooltips(); + log(c); + return false; + } + } + + let win = this._workspaces[this._active].getWindowWithTooltip(c); + this._hideTooltips(); + + if (win) + Main.activateWindow(win, global.get_current_time()); + + return true; + } + if (this._pickWorkspace) { + let c = event.get_key_symbol() - Clutter.KEY_KP_0; + if (c > 9 || c <= 0) { + c = event.get_key_symbol() - Clutter.KEY_0; + if (c > 9 || c <= 0) { + this._hideWorkspacesTooltips(); + return false; + } + } + + let workspace = this._workspaces[c - 1]; + if (workspace !== undefined) + workspace.metaWorkspace.activate(global.get_current_time()); + + this._hideWorkspacesTooltips(); + return true; + } + return false; + }; + /* eslint-enable */ + }); } disable() { - Workspace.Workspace = this._origWorkspace; - WorkspacesView.WorkspacesView = this._origWorkspacesView; + this._injectionManager.clear(); } } From d59bc0b7f00e8814aade2b30a248b84c4e0b70f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sat, 15 Jul 2023 14:37:46 +0200 Subject: [PATCH 29/32] window-list: Do not inject WindowPicker into Main This will become impossible once Main is converted to ESM. Instead, use the Extension class itself to hold the window picker. Part-of: --- extensions/window-list/extension.js | 11 ++++++----- extensions/window-list/windowPicker.js | 17 +++++++++++------ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js index 8f7205f3..6f6417c6 100644 --- a/extensions/window-list/extension.js +++ b/extensions/window-list/extension.js @@ -878,7 +878,8 @@ class WindowList extends St.Widget { } _updateWindowListVisibility() { - let visible = !Main.windowPicker.visible; + const {windowPicker} = Extension.lookupByURL(import.meta.url); + const visible = !windowPicker.visible; this._windowList.ease({ opacity: visible ? 255 : 0, @@ -1111,10 +1112,10 @@ export default class WindowListExtension extends Extension { Main.layoutManager.connectObject('monitors-changed', () => this._buildWindowLists(), this); - Main.windowPicker = new WindowPicker(); + this.windowPicker = new WindowPicker(); Main.overview.hide = () => { - Main.windowPicker.close(); + this.windowPicker.close(); this._hideOverviewOrig.call(Main.overview); }; @@ -1146,8 +1147,8 @@ export default class WindowListExtension extends Extension { }); this._windowLists = null; - Main.windowPicker.destroy(); - delete Main.windowPicker; + this.windowPicker.destroy(); + delete this.windowPicker; Main.overview.hide = this._hideOverviewOrig; } diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js index 17802c14..02983ce0 100644 --- a/extensions/window-list/windowPicker.js +++ b/extensions/window-list/windowPicker.js @@ -3,6 +3,8 @@ import GObject from 'gi://GObject'; import Shell from 'gi://Shell'; import St from 'gi://St'; +import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; + const Layout = imports.ui.layout; const Main = imports.ui.main; const {WorkspacesDisplay} = imports.ui.workspacesView; @@ -34,6 +36,8 @@ class MyWorkspacesDisplay extends WorkspacesDisplay { super(controls, workspaceAdjustment, overviewAdjustment); + this._windowPicker = controls; + this._workspaceAdjustment = workspaceAdjustment; this._workspaceAdjustment.actor = this; @@ -49,7 +53,7 @@ class MyWorkspacesDisplay extends WorkspacesDisplay { prepareToEnterOverview(...args) { if (!this._scrollEventId) { - this._scrollEventId = Main.windowPicker.connect('scroll-event', + this._scrollEventId = this._windowPicker.connect('scroll-event', this._onScrollEvent.bind(this)); } @@ -58,7 +62,7 @@ class MyWorkspacesDisplay extends WorkspacesDisplay { vfunc_hide(...args) { if (this._scrollEventId > 0) - Main.windowPicker.disconnect(this._scrollEventId); + this._windowPicker.disconnect(this._scrollEventId); this._scrollEventId = 0; super.vfunc_hide(...args); @@ -325,15 +329,16 @@ export class WindowPickerToggle extends St.Button { toggle_mode: true, }); + const {windowPicker} = Extension.lookupByURL(import.meta.url); this.connect('notify::checked', () => { if (this.checked) - Main.windowPicker.open(); + windowPicker.open(); else - Main.windowPicker.close(); + windowPicker.close(); }); - Main.windowPicker.connect('open-state-changed', () => { - this.checked = Main.windowPicker.visible; + windowPicker.connect('open-state-changed', () => { + this.checked = windowPicker.visible; }); } } From 2d3307c657b9e90a348edef3bb1be7c8db061493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sat, 5 Aug 2023 16:48:03 +0200 Subject: [PATCH 30/32] window-list: Use InjectionManager instead of custom classes Once the shell is ported to ESM, it will no longer be possible to replace entire classes (even when imported). Prepare for that by overriding methods of the regular WorkspaceBackground class instead. Part-of: --- extensions/window-list/windowPicker.js | 134 ++++++++++++------------- 1 file changed, 64 insertions(+), 70 deletions(-) diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js index 02983ce0..907606ce 100644 --- a/extensions/window-list/windowPicker.js +++ b/extensions/window-list/windowPicker.js @@ -3,7 +3,7 @@ import GObject from 'gi://GObject'; import Shell from 'gi://Shell'; import St from 'gi://St'; -import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; +import {Extension, InjectionManager} from 'resource:///org/gnome/shell/extensions/extension.js'; const Layout = imports.ui.layout; const Main = imports.ui.main; @@ -77,66 +77,6 @@ class MyWorkspacesDisplay extends WorkspacesDisplay { } } -class MyWorkspace extends Workspace.Workspace { - static { - GObject.registerClass(this); - } - - constructor(...args) { - super(...args); - - this._overviewAdjustment.connectObject('notify::value', () => { - const {value: progress} = this._overviewAdjustment; - const brightness = 1 - (1 - VIGNETTE_BRIGHTNESS) * progress; - for (const bg of this._background?._backgroundGroup ?? []) { - bg.content.set({ - vignette: true, - brightness, - }); - } - }, this); - } -} - -class MyWorkspaceBackground extends Workspace.WorkspaceBackground { - static { - GObject.registerClass(this); - } - - _updateBorderRadius() { - } - - vfunc_allocate(box) { - this.set_allocation(box); - - const themeNode = this.get_theme_node(); - const contentBox = themeNode.get_content_box(box); - - this._bin.allocate(contentBox); - - const [contentWidth, contentHeight] = contentBox.get_size(); - const monitor = Main.layoutManager.monitors[this._monitorIndex]; - const xRatio = contentWidth / this._workarea.width; - const yRatio = contentHeight / this._workarea.height; - - const right = area => area.x + area.width; - const bottom = area => area.y + area.height; - - const offsets = { - left: xRatio * (this._workarea.x - monitor.x), - right: xRatio * (right(monitor) - right(this._workarea)), - top: yRatio * (this._workarea.y - monitor.y), - bottom: yRatio * (bottom(monitor) - bottom(this._workarea)), - }; - - contentBox.set_origin(-offsets.left, -offsets.top); - contentBox.set_size( - offsets.left + contentWidth + offsets.right, - offsets.top + contentHeight + offsets.bottom); - this._backgroundGroup.allocate(contentBox); - } -} - export class WindowPicker extends Clutter.Actor { static [GObject.signals] = { 'open-state-changed': {param_types: [GObject.TYPE_BOOLEAN]}, @@ -156,6 +96,7 @@ export class WindowPicker extends Clutter.Actor { this._adjustment = new OverviewAdjustment(this); + this._injectionManager = new InjectionManager(); this.connect('destroy', this._onDestroy.bind(this)); global.bind_property('screen-width', @@ -183,11 +124,68 @@ export class WindowPicker extends Clutter.Actor { } _injectBackgroundShade() { - this._origWorkspace = Workspace.Workspace; - this._origWorkspaceBackground = Workspace.WorkspaceBackground; + const backgroundProto = Workspace.WorkspaceBackground.prototype; + this._injectionManager.overrideMethod(backgroundProto, '_updateBorderRadius', + () => { + return function () {}; + }); + this._injectionManager.overrideMethod(backgroundProto, 'vfunc_allocate', + () => { + /* eslint-disable no-invalid-this */ + return function (box) { + this.set_allocation(box); - Workspace.Workspace = MyWorkspace; - Workspace.WorkspaceBackground = MyWorkspaceBackground; + const themeNode = this.get_theme_node(); + const contentBox = themeNode.get_content_box(box); + + this._bin.allocate(contentBox); + + const [contentWidth, contentHeight] = contentBox.get_size(); + const monitor = Main.layoutManager.monitors[this._monitorIndex]; + const xRatio = contentWidth / this._workarea.width; + const yRatio = contentHeight / this._workarea.height; + + const right = area => area.x + area.width; + const bottom = area => area.y + area.height; + + const offsets = { + left: xRatio * (this._workarea.x - monitor.x), + right: xRatio * (right(monitor) - right(this._workarea)), + top: yRatio * (this._workarea.y - monitor.y), + bottom: yRatio * (bottom(monitor) - bottom(this._workarea)), + }; + + contentBox.set_origin(-offsets.left, -offsets.top); + contentBox.set_size( + offsets.left + contentWidth + offsets.right, + offsets.top + contentHeight + offsets.bottom); + this._backgroundGroup.allocate(contentBox); + }; + /* eslint-enable */ + }); + this._injectionManager.overrideMethod(backgroundProto, 'vfunc_parent_set', + () => { + /* eslint-disable no-invalid-this */ + return function () { + setTimeout(() => { + const parent = this.get_parent(); + if (!parent) + return; + + parent._overviewAdjustment.connectObject('notify::value', () => { + const {value: progress} = parent._overviewAdjustment; + const brightness = 1 - (1 - VIGNETTE_BRIGHTNESS) * progress; + for (const bg of this._backgroundGroup ?? []) { + bg.content.set({ + vignette: true, + brightness, + }); + } + }, this); + }); + }; + /* eslint-enable */ + }); } get visible() { @@ -293,11 +291,7 @@ export class WindowPicker extends Clutter.Actor { } _onDestroy() { - if (this._origWorkspace) - Workspace.Workspace = this._origWorkspace; - - if (this._origWorkspaceBackground) - Workspace.WorkspaceBackground = this._origWorkspaceBackground; + this._injectionManager.clear(); if (this._stageKeyPressId) global.stage.disconnect(this._stageKeyPressId); From a9114473751fd022a5208618a8c9bb488651a48a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Fri, 14 Jul 2023 02:07:41 +0200 Subject: [PATCH 31/32] js: Port to ESM The shell pulled the trigger and switched to ESM for all its imports, follow suit. Part-of: --- extensions/apps-menu/extension.js | 10 +++++----- extensions/auto-move-windows/extension.js | 3 +-- extensions/drive-menu/extension.js | 8 ++++---- extensions/launch-new-instance/extension.js | 3 +-- extensions/light-style/extension.js | 2 +- extensions/native-window-placement/extension.js | 6 +++--- extensions/places-menu/extension.js | 6 +++--- extensions/places-menu/placeDisplay.js | 6 +++--- extensions/screenshot-window-sizer/extension.js | 2 +- extensions/user-theme/extension.js | 2 +- extensions/window-list/extension.js | 8 ++++---- extensions/window-list/windowPicker.js | 17 ++++++++--------- extensions/window-list/workspaceIndicator.js | 8 ++++---- extensions/windowsNavigator/extension.js | 11 +++++------ extensions/workspace-indicator/extension.js | 8 ++++---- 15 files changed, 48 insertions(+), 52 deletions(-) diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js index b9364442..b6185338 100644 --- a/extensions/apps-menu/extension.js +++ b/extensions/apps-menu/extension.js @@ -9,14 +9,14 @@ import Gtk from 'gi://Gtk'; import Meta from 'gi://Meta'; import Shell from 'gi://Shell'; import St from 'gi://St'; -const {EventEmitter} = imports.misc.signals; +import {EventEmitter} from 'resource:///org/gnome/shell/misc/signals.js'; import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; -const DND = imports.ui.dnd; -const Main = imports.ui.main; -const PanelMenu = imports.ui.panelMenu; -const PopupMenu = imports.ui.popupMenu; +import * as DND from 'resource:///org/gnome/shell/ui/dnd.js'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; +import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; const appSys = Shell.AppSystem.get_default(); diff --git a/extensions/auto-move-windows/extension.js b/extensions/auto-move-windows/extension.js index d439cf1e..1b0cb43c 100644 --- a/extensions/auto-move-windows/extension.js +++ b/extensions/auto-move-windows/extension.js @@ -4,8 +4,7 @@ import Shell from 'gi://Shell'; import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; - -const Main = imports.ui.main; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; class WindowMover { constructor(settings) { diff --git a/extensions/drive-menu/extension.js b/extensions/drive-menu/extension.js index cb9986fe..7d42ab25 100644 --- a/extensions/drive-menu/extension.js +++ b/extensions/drive-menu/extension.js @@ -7,10 +7,10 @@ import St from 'gi://St'; import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; -const Main = imports.ui.main; -const PanelMenu = imports.ui.panelMenu; -const PopupMenu = imports.ui.popupMenu; -const ShellMountOperation = imports.ui.shellMountOperation; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; +import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; +import * as ShellMountOperation from 'resource:///org/gnome/shell/ui/shellMountOperation.js'; Gio._promisify(Gio.File.prototype, 'query_filesystem_info_async'); diff --git a/extensions/launch-new-instance/extension.js b/extensions/launch-new-instance/extension.js index b542fad2..b4b0d8ae 100644 --- a/extensions/launch-new-instance/extension.js +++ b/extensions/launch-new-instance/extension.js @@ -1,7 +1,6 @@ +import {AppIcon} from 'resource:///org/gnome/shell/ui/appDisplay.js'; import {InjectionManager} from 'resource:///org/gnome/shell/extensions/extension.js'; -const {AppIcon} = imports.ui.appDisplay; - export default class Extension { constructor() { this._injectionManager = new InjectionManager(); diff --git a/extensions/light-style/extension.js b/extensions/light-style/extension.js index e37b40ec..5825093d 100644 --- a/extensions/light-style/extension.js +++ b/extensions/light-style/extension.js @@ -17,7 +17,7 @@ import St from 'gi://St'; -const Main = imports.ui.main; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; export default class Extension { _updateColorScheme(scheme) { diff --git a/extensions/native-window-placement/extension.js b/extensions/native-window-placement/extension.js index 85430479..9877a8fe 100644 --- a/extensions/native-window-placement/extension.js +++ b/extensions/native-window-placement/extension.js @@ -3,9 +3,9 @@ import Clutter from 'gi://Clutter'; import {Extension, InjectionManager} from 'resource:///org/gnome/shell/extensions/extension.js'; -const Main = imports.ui.main; -const {WindowPreview} = imports.ui.windowPreview; -const Workspace = imports.ui.workspace; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import {WindowPreview} from 'resource:///org/gnome/shell/ui/windowPreview.js'; +import * as Workspace from 'resource:///org/gnome/shell/ui/workspace.js'; // testing settings for natural window placement strategy: const WINDOW_PLACEMENT_NATURAL_ACCURACY = 20; // accuracy of window translate moves (KDE-default: 20) diff --git a/extensions/places-menu/extension.js b/extensions/places-menu/extension.js index 83e63dc1..de8593e7 100644 --- a/extensions/places-menu/extension.js +++ b/extensions/places-menu/extension.js @@ -5,9 +5,9 @@ import St from 'gi://St'; import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; -const Main = imports.ui.main; -const PanelMenu = imports.ui.panelMenu; -const PopupMenu = imports.ui.popupMenu; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; +import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; import {PlacesManager} from './placeDisplay.js'; diff --git a/extensions/places-menu/placeDisplay.js b/extensions/places-menu/placeDisplay.js index ffd86eb3..0be170fe 100644 --- a/extensions/places-menu/placeDisplay.js +++ b/extensions/places-menu/placeDisplay.js @@ -2,12 +2,12 @@ import Gio from 'gi://Gio'; import GLib from 'gi://GLib'; import Shell from 'gi://Shell'; -const {EventEmitter} = imports.misc.signals; +import {EventEmitter} from 'resource:///org/gnome/shell/misc/signals.js'; import {gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; -const Main = imports.ui.main; -const ShellMountOperation = imports.ui.shellMountOperation; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import * as ShellMountOperation from 'resource:///org/gnome/shell/ui/shellMountOperation.js'; const N_ = x => x; diff --git a/extensions/screenshot-window-sizer/extension.js b/extensions/screenshot-window-sizer/extension.js index 05d9dbcc..4312a5a5 100644 --- a/extensions/screenshot-window-sizer/extension.js +++ b/extensions/screenshot-window-sizer/extension.js @@ -25,7 +25,7 @@ import St from 'gi://St'; import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; -const Main = imports.ui.main; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; const MESSAGE_FADE_TIME = 2000; diff --git a/extensions/user-theme/extension.js b/extensions/user-theme/extension.js index a2a6cbca..f006fdfe 100644 --- a/extensions/user-theme/extension.js +++ b/extensions/user-theme/extension.js @@ -5,7 +5,7 @@ import Gio from 'gi://Gio'; import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; -const Main = imports.ui.main; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import {getThemeDirs, getModeThemeDirs} from './util.js'; diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js index 6f6417c6..71672695 100644 --- a/extensions/window-list/extension.js +++ b/extensions/window-list/extension.js @@ -9,10 +9,10 @@ import St from 'gi://St'; import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; -const DND = imports.ui.dnd; -const Main = imports.ui.main; -const Overview = imports.ui.overview; -const PopupMenu = imports.ui.popupMenu; +import * as DND from 'resource:///org/gnome/shell/ui/dnd.js'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import * as Overview from 'resource:///org/gnome/shell/ui/overview.js'; +import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; import {WindowPicker, WindowPickerToggle} from './windowPicker.js'; import {WorkspaceIndicator} from './workspaceIndicator.js'; diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js index 907606ce..6cafba61 100644 --- a/extensions/window-list/windowPicker.js +++ b/extensions/window-list/windowPicker.js @@ -4,18 +4,17 @@ import Shell from 'gi://Shell'; import St from 'gi://St'; import {Extension, InjectionManager} from 'resource:///org/gnome/shell/extensions/extension.js'; +import * as Layout from 'resource:///org/gnome/shell/ui/layout.js'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import {WorkspacesDisplay} from 'resource:///org/gnome/shell/ui/workspacesView.js'; +import * as Workspace from 'resource:///org/gnome/shell/ui/workspace.js'; -const Layout = imports.ui.layout; -const Main = imports.ui.main; -const {WorkspacesDisplay} = imports.ui.workspacesView; -const Workspace = imports.ui.workspace; - -const {VIGNETTE_BRIGHTNESS} = imports.ui.lightbox; -const { +import {VIGNETTE_BRIGHTNESS} from 'resource:///org/gnome/shell/ui/lightbox.js'; +import { SIDE_CONTROLS_ANIMATION_TIME, OverviewAdjustment, - ControlsState, -} = imports.ui.overviewControls; + ControlsState +} from 'resource:///org/gnome/shell/ui/overviewControls.js'; class MyWorkspacesDisplay extends WorkspacesDisplay { static { diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js index 4e50c288..aa2548d7 100644 --- a/extensions/window-list/workspaceIndicator.js +++ b/extensions/window-list/workspaceIndicator.js @@ -6,10 +6,10 @@ import St from 'gi://St'; import {gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; -const DND = imports.ui.dnd; -const Main = imports.ui.main; -const PanelMenu = imports.ui.panelMenu; -const PopupMenu = imports.ui.popupMenu; +import * as DND from 'resource:///org/gnome/shell/ui/dnd.js'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; +import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; const TOOLTIP_OFFSET = 6; const TOOLTIP_ANIMATION_TIME = 150; diff --git a/extensions/windowsNavigator/extension.js b/extensions/windowsNavigator/extension.js index 32544b9b..e089df22 100644 --- a/extensions/windowsNavigator/extension.js +++ b/extensions/windowsNavigator/extension.js @@ -3,13 +3,12 @@ import Clutter from 'gi://Clutter'; import Graphene from 'gi://Graphene'; import St from 'gi://St'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import * as OverviewControls from 'resource:///org/gnome/shell/ui/overviewControls.js'; import {InjectionManager} from 'resource:///org/gnome/shell/extensions/extension.js'; - -const Main = imports.ui.main; -const OverviewControls = imports.ui.overviewControls; -const {WindowPreview} = imports.ui.windowPreview; -const {Workspace} = imports.ui.workspace; -const {WorkspacesView} = imports.ui.workspacesView; +import {WindowPreview} from 'resource:///org/gnome/shell/ui/windowPreview.js'; +import {Workspace} from 'resource:///org/gnome/shell/ui/workspace.js'; +import {WorkspacesView} from 'resource:///org/gnome/shell/ui/workspacesView.js'; const WINDOW_SLOT = 4; diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js index 78037d91..dd6ed1ce 100644 --- a/extensions/workspace-indicator/extension.js +++ b/extensions/workspace-indicator/extension.js @@ -7,10 +7,10 @@ import St from 'gi://St'; import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; -const DND = imports.ui.dnd; -const Main = imports.ui.main; -const PanelMenu = imports.ui.panelMenu; -const PopupMenu = imports.ui.popupMenu; +import * as DND from 'resource:///org/gnome/shell/ui/dnd.js'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; +import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences'; const WORKSPACE_KEY = 'workspace-names'; From 4345703c2edd6b737f268d7398946a4dc67a98a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Mon, 7 Aug 2023 16:41:23 +0200 Subject: [PATCH 32/32] Bump version to 45.beta Update NEWS. --- NEWS | 11 +++++++++++ meson.build | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index f7137653..1314288a 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,14 @@ +45.beta +======= +* Port extensions to ESM [Florian; !259, !266, !268, !269] +* Misc. bug fixes and cleanups [Florian; !260, !261, !262, !263, !264] + +Contributors: + Florian Müllner + +Translators: + Efstathios Iosifidis [el] + 45.alpha ======== * window-list: Modernize default styling [Alexander; !253] diff --git a/meson.build b/meson.build index 37c3f0fd..00820b4e 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('gnome-shell-extensions', - version: '45.alpha', + version: '45.beta', meson_version: '>= 0.58.0', license: 'GPL2+' )