6491 lines
218 KiB
Diff
6491 lines
218 KiB
Diff
From 7e65ba671f3fe2999a7b5a473f934879a540d734 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 23 Mar 2022 19:59:14 +0100
|
|
Subject: [PATCH 01/43] build: Remove unused stylesheets
|
|
|
|
The only reason for installing empty stylesheets is minimizing
|
|
build system differences between extensions. That's not a very
|
|
good reason and we don't do this for other optional files like
|
|
schemas.
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/223>
|
|
---
|
|
extensions/apps-menu/meson.build | 1 +
|
|
extensions/auto-move-windows/stylesheet.css | 1 -
|
|
extensions/classification-banner/meson.build | 1 +
|
|
extensions/custom-menu/stylesheet.css | 1 -
|
|
extensions/dash-to-dock/meson.build | 1 +
|
|
extensions/dash-to-panel/meson.build | 1 +
|
|
extensions/desktop-icons/meson.build | 1 +
|
|
extensions/drive-menu/meson.build | 1 +
|
|
extensions/gesture-inhibitor/stylesheet.css | 1 -
|
|
extensions/heads-up-display/meson.build | 1 +
|
|
extensions/launch-new-instance/stylesheet.css | 1 -
|
|
extensions/meson.build | 2 +-
|
|
extensions/meson.build.template | 1 +
|
|
extensions/native-window-placement/meson.build | 1 +
|
|
extensions/panel-favorites/meson.build | 1 +
|
|
extensions/places-menu/meson.build | 1 +
|
|
extensions/screenshot-window-sizer/meson.build | 1 +
|
|
extensions/top-icons/stylesheet.css | 1 -
|
|
extensions/updates-dialog/stylesheet.css | 1 -
|
|
extensions/user-theme/stylesheet.css | 1 -
|
|
extensions/window-list/meson.build | 1 +
|
|
extensions/windowsNavigator/meson.build | 1 +
|
|
extensions/workspace-indicator/meson.build | 1 +
|
|
23 files changed, 16 insertions(+), 8 deletions(-)
|
|
delete mode 100644 extensions/auto-move-windows/stylesheet.css
|
|
delete mode 100644 extensions/custom-menu/stylesheet.css
|
|
delete mode 100644 extensions/gesture-inhibitor/stylesheet.css
|
|
delete mode 100644 extensions/launch-new-instance/stylesheet.css
|
|
delete mode 100644 extensions/top-icons/stylesheet.css
|
|
delete mode 100644 extensions/updates-dialog/stylesheet.css
|
|
delete mode 100644 extensions/user-theme/stylesheet.css
|
|
|
|
diff --git a/extensions/apps-menu/meson.build b/extensions/apps-menu/meson.build
|
|
index 48504f63..6b9bb19c 100644
|
|
--- a/extensions/apps-menu/meson.build
|
|
+++ b/extensions/apps-menu/meson.build
|
|
@@ -3,3 +3,4 @@ extension_data += configure_file(
|
|
output: metadata_name,
|
|
configuration: metadata_conf
|
|
)
|
|
+extension_data += files('stylesheet.css')
|
|
diff --git a/extensions/auto-move-windows/stylesheet.css b/extensions/auto-move-windows/stylesheet.css
|
|
deleted file mode 100644
|
|
index 25134b65..00000000
|
|
--- a/extensions/auto-move-windows/stylesheet.css
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-/* This extensions requires no special styling */
|
|
diff --git a/extensions/classification-banner/meson.build b/extensions/classification-banner/meson.build
|
|
index c55a7830..aa943741 100644
|
|
--- a/extensions/classification-banner/meson.build
|
|
+++ b/extensions/classification-banner/meson.build
|
|
@@ -3,6 +3,7 @@ extension_data += configure_file(
|
|
output: metadata_name,
|
|
configuration: metadata_conf
|
|
)
|
|
+extension_data += files('stylesheet.css')
|
|
|
|
extension_sources += files('prefs.js')
|
|
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')
|
|
diff --git a/extensions/custom-menu/stylesheet.css b/extensions/custom-menu/stylesheet.css
|
|
deleted file mode 100644
|
|
index 25134b65..00000000
|
|
--- a/extensions/custom-menu/stylesheet.css
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-/* This extensions requires no special styling */
|
|
diff --git a/extensions/dash-to-dock/meson.build b/extensions/dash-to-dock/meson.build
|
|
index 290374fb..749c2723 100644
|
|
--- a/extensions/dash-to-dock/meson.build
|
|
+++ b/extensions/dash-to-dock/meson.build
|
|
@@ -3,6 +3,7 @@ extension_data += configure_file(
|
|
output: metadata_name,
|
|
configuration: metadata_conf
|
|
)
|
|
+extension_data += files('stylesheet.css')
|
|
|
|
extension_sources += files(
|
|
'appIconIndicators.js',
|
|
diff --git a/extensions/dash-to-panel/meson.build b/extensions/dash-to-panel/meson.build
|
|
index 70680479..0cae5eef 100644
|
|
--- a/extensions/dash-to-panel/meson.build
|
|
+++ b/extensions/dash-to-panel/meson.build
|
|
@@ -3,6 +3,7 @@ extension_data += configure_file(
|
|
output: metadata_name,
|
|
configuration: metadata_conf
|
|
)
|
|
+extension_data += files('stylesheet.css')
|
|
|
|
extension_sources += files(
|
|
'appIcons.js',
|
|
diff --git a/extensions/desktop-icons/meson.build b/extensions/desktop-icons/meson.build
|
|
index 8431af62..3512db2c 100644
|
|
--- a/extensions/desktop-icons/meson.build
|
|
+++ b/extensions/desktop-icons/meson.build
|
|
@@ -3,6 +3,7 @@ extension_data += configure_file(
|
|
output: metadata_name,
|
|
configuration: metadata_conf
|
|
)
|
|
+extension_data += files('stylesheet.css')
|
|
|
|
extension_schemas += files(join_paths('schemas', metadata_conf.get('gschemaname') + '.gschema.xml'))
|
|
|
|
diff --git a/extensions/drive-menu/meson.build b/extensions/drive-menu/meson.build
|
|
index 48504f63..6b9bb19c 100644
|
|
--- a/extensions/drive-menu/meson.build
|
|
+++ b/extensions/drive-menu/meson.build
|
|
@@ -3,3 +3,4 @@ extension_data += configure_file(
|
|
output: metadata_name,
|
|
configuration: metadata_conf
|
|
)
|
|
+extension_data += files('stylesheet.css')
|
|
diff --git a/extensions/gesture-inhibitor/stylesheet.css b/extensions/gesture-inhibitor/stylesheet.css
|
|
deleted file mode 100644
|
|
index 37b93f21..00000000
|
|
--- a/extensions/gesture-inhibitor/stylesheet.css
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-/* Add your custom extension styling here */
|
|
diff --git a/extensions/heads-up-display/meson.build b/extensions/heads-up-display/meson.build
|
|
index 40c3de0a..678fd325 100644
|
|
--- a/extensions/heads-up-display/meson.build
|
|
+++ b/extensions/heads-up-display/meson.build
|
|
@@ -3,6 +3,7 @@ extension_data += configure_file(
|
|
output: metadata_name,
|
|
configuration: metadata_conf
|
|
)
|
|
+extension_data += files('stylesheet.css')
|
|
|
|
extension_sources += files('headsUpMessage.js', 'prefs.js')
|
|
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')
|
|
diff --git a/extensions/launch-new-instance/stylesheet.css b/extensions/launch-new-instance/stylesheet.css
|
|
deleted file mode 100644
|
|
index 25134b65..00000000
|
|
--- a/extensions/launch-new-instance/stylesheet.css
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-/* This extensions requires no special styling */
|
|
diff --git a/extensions/meson.build b/extensions/meson.build
|
|
index d1bf92c9..e8945ed3 100644
|
|
--- a/extensions/meson.build
|
|
+++ b/extensions/meson.build
|
|
@@ -15,7 +15,7 @@ foreach e : all_extensions
|
|
metadata_conf.set('url', 'https://gitlab.gnome.org/GNOME/gnome-shell-extensions')
|
|
|
|
extension_sources = files(e + '/extension.js')
|
|
- extension_data = files(e + '/stylesheet.css')
|
|
+ extension_data = []
|
|
|
|
subdir(e)
|
|
|
|
diff --git a/extensions/meson.build.template b/extensions/meson.build.template
|
|
index e83e528b..a9915994 100644
|
|
--- a/extensions/meson.build.template
|
|
+++ b/extensions/meson.build.template
|
|
@@ -4,5 +4,6 @@ extension_data += configure_file(
|
|
configuration: metadata_conf
|
|
)
|
|
|
|
+# extension_data += files('stylesheet.css')
|
|
# extension_sources += files('prefs.js')
|
|
# extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')
|
|
diff --git a/extensions/native-window-placement/meson.build b/extensions/native-window-placement/meson.build
|
|
index 585c02da..cf73fc03 100644
|
|
--- a/extensions/native-window-placement/meson.build
|
|
+++ b/extensions/native-window-placement/meson.build
|
|
@@ -5,3 +5,4 @@ extension_data += configure_file(
|
|
)
|
|
|
|
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')
|
|
+extension_data += files('stylesheet.css')
|
|
diff --git a/extensions/panel-favorites/meson.build b/extensions/panel-favorites/meson.build
|
|
index ab6967fa..d335e362 100644
|
|
--- a/extensions/panel-favorites/meson.build
|
|
+++ b/extensions/panel-favorites/meson.build
|
|
@@ -9,3 +9,4 @@ extension_sources += files(
|
|
)
|
|
|
|
extension_schemas += files('schemas/' + metadata_conf.get('gschemaname') + '.gschema.xml')
|
|
+extension_data += files('stylesheet.css')
|
|
diff --git a/extensions/places-menu/meson.build b/extensions/places-menu/meson.build
|
|
index d9a59691..cbc2a02b 100644
|
|
--- a/extensions/places-menu/meson.build
|
|
+++ b/extensions/places-menu/meson.build
|
|
@@ -3,5 +3,6 @@ extension_data += configure_file(
|
|
output: metadata_name,
|
|
configuration: metadata_conf
|
|
)
|
|
+extension_data += files('stylesheet.css')
|
|
|
|
extension_sources += files('placeDisplay.js')
|
|
diff --git a/extensions/screenshot-window-sizer/meson.build b/extensions/screenshot-window-sizer/meson.build
|
|
index 585c02da..8257dee0 100644
|
|
--- a/extensions/screenshot-window-sizer/meson.build
|
|
+++ b/extensions/screenshot-window-sizer/meson.build
|
|
@@ -3,5 +3,6 @@ extension_data += configure_file(
|
|
output: metadata_name,
|
|
configuration: metadata_conf
|
|
)
|
|
+extension_data += files('stylesheet.css')
|
|
|
|
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')
|
|
diff --git a/extensions/top-icons/stylesheet.css b/extensions/top-icons/stylesheet.css
|
|
deleted file mode 100644
|
|
index 25134b65..00000000
|
|
--- a/extensions/top-icons/stylesheet.css
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-/* This extensions requires no special styling */
|
|
diff --git a/extensions/updates-dialog/stylesheet.css b/extensions/updates-dialog/stylesheet.css
|
|
deleted file mode 100644
|
|
index 25134b65..00000000
|
|
--- a/extensions/updates-dialog/stylesheet.css
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-/* This extensions requires no special styling */
|
|
diff --git a/extensions/user-theme/stylesheet.css b/extensions/user-theme/stylesheet.css
|
|
deleted file mode 100644
|
|
index 6d914832..00000000
|
|
--- a/extensions/user-theme/stylesheet.css
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-/* none used */
|
|
diff --git a/extensions/window-list/meson.build b/extensions/window-list/meson.build
|
|
index 34d7c3fd..599f45e1 100644
|
|
--- a/extensions/window-list/meson.build
|
|
+++ b/extensions/window-list/meson.build
|
|
@@ -3,6 +3,7 @@ extension_data += configure_file(
|
|
output: metadata_name,
|
|
configuration: metadata_conf
|
|
)
|
|
+extension_data += files('stylesheet.css')
|
|
|
|
extension_sources += files('prefs.js', 'windowPicker.js', 'workspaceIndicator.js')
|
|
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')
|
|
diff --git a/extensions/windowsNavigator/meson.build b/extensions/windowsNavigator/meson.build
|
|
index 48504f63..6b9bb19c 100644
|
|
--- a/extensions/windowsNavigator/meson.build
|
|
+++ b/extensions/windowsNavigator/meson.build
|
|
@@ -3,3 +3,4 @@ extension_data += configure_file(
|
|
output: metadata_name,
|
|
configuration: metadata_conf
|
|
)
|
|
+extension_data += files('stylesheet.css')
|
|
diff --git a/extensions/workspace-indicator/meson.build b/extensions/workspace-indicator/meson.build
|
|
index 71efa039..19858a39 100644
|
|
--- a/extensions/workspace-indicator/meson.build
|
|
+++ b/extensions/workspace-indicator/meson.build
|
|
@@ -3,5 +3,6 @@ extension_data += configure_file(
|
|
output: metadata_name,
|
|
configuration: metadata_conf
|
|
)
|
|
+extension_data += files('stylesheet.css')
|
|
|
|
extension_sources += files('prefs.js')
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From c84bfeb065d0200dee5e5ac1eb7ba30feb105360 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 21 Oct 2020 02:34:41 +0200
|
|
Subject: [PATCH 02/43] workspace-indicator: Use custom layout manager for
|
|
thumbnails
|
|
|
|
The current code positions window previews explicitly using a fixed
|
|
layout manager. For that it relies on a valid parent allocation,
|
|
which is error-prone and frequently results in warnings.
|
|
|
|
Address this by moving the positioning code into a custom layout
|
|
manager, and only update the visibility from the window preview.
|
|
|
|
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/260
|
|
---
|
|
extensions/workspace-indicator/extension.js | 71 +++++++++++----------
|
|
1 file changed, 38 insertions(+), 33 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js
|
|
index d377f288..101ef7be 100644
|
|
--- a/extensions/workspace-indicator/extension.js
|
|
+++ b/extensions/workspace-indicator/extension.js
|
|
@@ -35,27 +35,15 @@ let WindowPreview = GObject.registerClass({
|
|
this.connect('destroy', this._onDestroy.bind(this));
|
|
|
|
this._sizeChangedId = this._window.connect('size-changed',
|
|
- this._relayout.bind(this));
|
|
+ () => this.queue_relayout());
|
|
this._positionChangedId = this._window.connect('position-changed',
|
|
- this._relayout.bind(this));
|
|
+ () => this.queue_relayout());
|
|
this._minimizedChangedId = this._window.connect('notify::minimized',
|
|
- this._relayout.bind(this));
|
|
+ this._updateVisible.bind(this));
|
|
this._monitorEnteredId = global.display.connect('window-entered-monitor',
|
|
- this._relayout.bind(this));
|
|
+ this._updateVisible.bind(this));
|
|
this._monitorLeftId = global.display.connect('window-left-monitor',
|
|
- this._relayout.bind(this));
|
|
-
|
|
- // Do initial layout when we get a parent
|
|
- let id = this.connect('parent-set', () => {
|
|
- this.disconnect(id);
|
|
- if (!this.get_parent())
|
|
- return;
|
|
- this._laterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
|
|
- this._laterId = 0;
|
|
- this._relayout();
|
|
- return false;
|
|
- });
|
|
- });
|
|
+ this._updateVisible.bind(this));
|
|
|
|
this._focusChangedId = global.display.connect('notify::focus-window',
|
|
this._onFocusChanged.bind(this));
|
|
@@ -67,6 +55,10 @@ let WindowPreview = GObject.registerClass({
|
|
return this._window.get_compositor_private();
|
|
}
|
|
|
|
+ get metaWindow() {
|
|
+ return this._window;
|
|
+ }
|
|
+
|
|
_onDestroy() {
|
|
this._window.disconnect(this._sizeChangedId);
|
|
this._window.disconnect(this._positionChangedId);
|
|
@@ -74,8 +66,6 @@ let WindowPreview = GObject.registerClass({
|
|
global.display.disconnect(this._monitorEnteredId);
|
|
global.display.disconnect(this._monitorLeftId);
|
|
global.display.disconnect(this._focusChangedId);
|
|
- if (this._laterId)
|
|
- Meta.later_remove(this._laterId);
|
|
}
|
|
|
|
_onFocusChanged() {
|
|
@@ -85,25 +75,40 @@ let WindowPreview = GObject.registerClass({
|
|
this.remove_style_class_name('active');
|
|
}
|
|
|
|
- _relayout() {
|
|
+ _updateVisible() {
|
|
let monitor = Main.layoutManager.findIndexForActor(this);
|
|
this.visible = monitor == this._window.get_monitor() &&
|
|
this._window.showing_on_its_workspace();
|
|
+ }
|
|
+});
|
|
|
|
- if (!this.visible)
|
|
- return;
|
|
+let WorkspaceLayout = GObject.registerClass(
|
|
+class WorkspaceLayout extends Clutter.LayoutManager {
|
|
+ vfunc_get_preferred_width() {
|
|
+ return [0, 0];
|
|
+ }
|
|
|
|
- let workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
|
|
- let hscale = this.get_parent().allocation.get_width() / workArea.width;
|
|
- let vscale = this.get_parent().allocation.get_height() / workArea.height;
|
|
+ vfunc_get_preferred_height() {
|
|
+ return [0, 0];
|
|
+ }
|
|
|
|
- let frameRect = this._window.get_frame_rect();
|
|
- this.set_size(
|
|
- Math.round(Math.min(frameRect.width, workArea.width) * hscale),
|
|
- Math.round(Math.min(frameRect.height, workArea.height) * vscale));
|
|
- this.set_position(
|
|
- Math.round(frameRect.x * hscale),
|
|
- Math.round(frameRect.y * vscale));
|
|
+ vfunc_allocate(container, box, flags) {
|
|
+ const monitor = Main.layoutManager.findIndexForActor(container);
|
|
+ const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
|
|
+ const hscale = box.get_width() / workArea.width;
|
|
+ const vscale = box.get_height() / workArea.height;
|
|
+
|
|
+ for (const child of container.get_children()) {
|
|
+ const childBox = new Clutter.ActorBox();
|
|
+ const frameRect = child.metaWindow.get_frame_rect();
|
|
+ childBox.set_size(
|
|
+ Math.min(frameRect.width, workArea.width) * hscale,
|
|
+ Math.min(frameRect.height, workArea.height) * vscale);
|
|
+ childBox.set_origin(
|
|
+ Math.round(frameRect.x * hscale),
|
|
+ Math.round(frameRect.y * vscale));
|
|
+ child.allocate(childBox, flags);
|
|
+ }
|
|
}
|
|
});
|
|
|
|
@@ -114,7 +119,7 @@ let WorkspaceThumbnail = GObject.registerClass({
|
|
super._init({
|
|
style_class: 'workspace',
|
|
child: new Clutter.Actor({
|
|
- layout_manager: new Clutter.BinLayout(),
|
|
+ layout_manager: new WorkspaceLayout(),
|
|
clip_to_allocation: true
|
|
}),
|
|
x_fill: true,
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From e2fd7a6f4ab4f783bc475a6a9cf3156ab4ddecad Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 21 Feb 2024 12:38:33 +0100
|
|
Subject: [PATCH 03/43] workspace-indicator: Move indicator code into separate
|
|
file
|
|
|
|
Shortly after the window-list extension was added, it gained a
|
|
workspace switcher based on the workspace indicator extension.
|
|
|
|
Duplicating the code wasn't a big issue while the switcher was
|
|
a simple menu, but since it gained previews with a fair bit of
|
|
custom styling, syncing changes between the two extensions has
|
|
become tedious, in particular as the two copies have slightly
|
|
diverged over time.
|
|
|
|
In order to allow the two copies to converge again, the indicator
|
|
code needs to be separate from the extension boilerplate, so
|
|
split out the code into a separate module.
|
|
---
|
|
extensions/workspace-indicator/extension.js | 443 +-----------------
|
|
extensions/workspace-indicator/meson.build | 2 +-
|
|
.../workspace-indicator/workspaceIndicator.js | 443 ++++++++++++++++++
|
|
po/POTFILES.in | 2 +-
|
|
4 files changed, 447 insertions(+), 443 deletions(-)
|
|
create mode 100644 extensions/workspace-indicator/workspaceIndicator.js
|
|
|
|
diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js
|
|
index 101ef7be..6f7d07c5 100644
|
|
--- a/extensions/workspace-indicator/extension.js
|
|
+++ b/extensions/workspace-indicator/extension.js
|
|
@@ -1,450 +1,11 @@
|
|
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
|
|
/* exported init enable disable */
|
|
|
|
-const { Clutter, Gio, GObject, Meta, St } = imports.gi;
|
|
-
|
|
-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 Tweener = imports.ui.tweener;
|
|
-
|
|
-const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
|
-const _ = Gettext.gettext;
|
|
-
|
|
-const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
|
|
-const WORKSPACE_KEY = 'workspace-names';
|
|
-
|
|
-const TOOLTIP_OFFSET = 6;
|
|
-const TOOLTIP_ANIMATION_TIME = 150;
|
|
-
|
|
-let WindowPreview = GObject.registerClass({
|
|
- GTypeName: 'WorkspaceIndicatorWindowPreview'
|
|
-}, class WindowPreview extends St.Button {
|
|
- _init(window) {
|
|
- super._init({
|
|
- style_class: 'workspace-indicator-window-preview'
|
|
- });
|
|
-
|
|
- this._delegate = this;
|
|
- DND.makeDraggable(this, { restoreOnSuccess: true });
|
|
-
|
|
- 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.queue_relayout());
|
|
- this._minimizedChangedId = this._window.connect('notify::minimized',
|
|
- this._updateVisible.bind(this));
|
|
- this._monitorEnteredId = global.display.connect('window-entered-monitor',
|
|
- this._updateVisible.bind(this));
|
|
- this._monitorLeftId = global.display.connect('window-left-monitor',
|
|
- this._updateVisible.bind(this));
|
|
-
|
|
- this._focusChangedId = global.display.connect('notify::focus-window',
|
|
- this._onFocusChanged.bind(this));
|
|
- this._onFocusChanged();
|
|
- }
|
|
-
|
|
- // needed for DND
|
|
- get realWindow() {
|
|
- return this._window.get_compositor_private();
|
|
- }
|
|
-
|
|
- get metaWindow() {
|
|
- return this._window;
|
|
- }
|
|
-
|
|
- _onDestroy() {
|
|
- this._window.disconnect(this._sizeChangedId);
|
|
- this._window.disconnect(this._positionChangedId);
|
|
- this._window.disconnect(this._minimizedChangedId);
|
|
- global.display.disconnect(this._monitorEnteredId);
|
|
- global.display.disconnect(this._monitorLeftId);
|
|
- global.display.disconnect(this._focusChangedId);
|
|
- }
|
|
-
|
|
- _onFocusChanged() {
|
|
- if (global.display.focus_window == this._window)
|
|
- this.add_style_class_name('active');
|
|
- else
|
|
- this.remove_style_class_name('active');
|
|
- }
|
|
-
|
|
- _updateVisible() {
|
|
- let monitor = Main.layoutManager.findIndexForActor(this);
|
|
- this.visible = monitor == this._window.get_monitor() &&
|
|
- this._window.showing_on_its_workspace();
|
|
- }
|
|
-});
|
|
-
|
|
-let WorkspaceLayout = GObject.registerClass(
|
|
-class WorkspaceLayout extends Clutter.LayoutManager {
|
|
- vfunc_get_preferred_width() {
|
|
- return [0, 0];
|
|
- }
|
|
-
|
|
- vfunc_get_preferred_height() {
|
|
- return [0, 0];
|
|
- }
|
|
-
|
|
- vfunc_allocate(container, box, flags) {
|
|
- const monitor = Main.layoutManager.findIndexForActor(container);
|
|
- const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
|
|
- const hscale = box.get_width() / workArea.width;
|
|
- const vscale = box.get_height() / workArea.height;
|
|
-
|
|
- for (const child of container.get_children()) {
|
|
- const childBox = new Clutter.ActorBox();
|
|
- const frameRect = child.metaWindow.get_frame_rect();
|
|
- childBox.set_size(
|
|
- Math.min(frameRect.width, workArea.width) * hscale,
|
|
- Math.min(frameRect.height, workArea.height) * vscale);
|
|
- childBox.set_origin(
|
|
- Math.round(frameRect.x * hscale),
|
|
- Math.round(frameRect.y * vscale));
|
|
- child.allocate(childBox, flags);
|
|
- }
|
|
- }
|
|
-});
|
|
-
|
|
-let WorkspaceThumbnail = GObject.registerClass({
|
|
- GTypeName: 'WorkspaceIndicatorWorkspaceThumbnail'
|
|
-}, class WorkspaceThumbnail extends St.Button {
|
|
- _init(index) {
|
|
- super._init({
|
|
- style_class: 'workspace',
|
|
- child: new Clutter.Actor({
|
|
- layout_manager: new WorkspaceLayout(),
|
|
- clip_to_allocation: true
|
|
- }),
|
|
- x_fill: true,
|
|
- y_fill: true
|
|
- });
|
|
-
|
|
- this._tooltip = new St.Label({
|
|
- style_class: 'dash-label',
|
|
- visible: false,
|
|
- });
|
|
- Main.uiGroup.add_child(this._tooltip);
|
|
-
|
|
- this.connect('destroy', this._onDestroy.bind(this));
|
|
- this.connect('notify::hover', this._syncTooltip.bind(this));
|
|
-
|
|
- this._index = index;
|
|
- this._delegate = this; // needed for DND
|
|
-
|
|
- this._windowPreviews = new Map();
|
|
-
|
|
- 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.list_windows().forEach(w => this._addWindow(w));
|
|
- this._onRestacked();
|
|
- }
|
|
-
|
|
- acceptDrop(source) {
|
|
- if (!source.realWindow)
|
|
- return false;
|
|
-
|
|
- let window = source.realWindow.get_meta_window();
|
|
- this._moveWindow(window);
|
|
- return true;
|
|
- }
|
|
-
|
|
- handleDragOver(source) {
|
|
- if (source.realWindow)
|
|
- return DND.DragMotionResult.MOVE_DROP;
|
|
- else
|
|
- return DND.DragMotionResult.CONTINUE;
|
|
- }
|
|
-
|
|
- _addWindow(window) {
|
|
- if (this._windowPreviews.has(window))
|
|
- return;
|
|
-
|
|
- let preview = new WindowPreview(window);
|
|
- preview.connect('clicked', (a, btn) => this.emit('clicked', btn));
|
|
- this._windowPreviews.set(window, preview);
|
|
- this.child.add_child(preview);
|
|
- }
|
|
-
|
|
- _removeWindow(window) {
|
|
- let preview = this._windowPreviews.get(window);
|
|
- if (!preview)
|
|
- return;
|
|
-
|
|
- this._windowPreviews.delete(window);
|
|
- preview.destroy();
|
|
- }
|
|
-
|
|
- _onRestacked() {
|
|
- let lastPreview = null;
|
|
- let windows = global.get_window_actors().map(a => a.meta_window);
|
|
- for (let i = 0; i < windows.length; i++) {
|
|
- let preview = this._windowPreviews.get(windows[i]);
|
|
- if (!preview)
|
|
- continue;
|
|
-
|
|
- this.child.set_child_above_sibling(preview, lastPreview);
|
|
- lastPreview = preview;
|
|
- }
|
|
- }
|
|
-
|
|
- _moveWindow(window) {
|
|
- let monitorIndex = Main.layoutManager.findIndexForActor(this);
|
|
- if (monitorIndex != window.get_monitor())
|
|
- window.move_to_monitor(monitorIndex);
|
|
- window.change_workspace_by_index(this._index, false);
|
|
- }
|
|
-
|
|
- // eslint-disable-next-line camelcase
|
|
- on_clicked() {
|
|
- let ws = global.workspace_manager.get_workspace_by_index(this._index);
|
|
- if (ws)
|
|
- ws.activate(global.get_current_time());
|
|
- }
|
|
-
|
|
- _syncTooltip() {
|
|
- if (this.hover) {
|
|
- this._tooltip.text = Meta.prefs_get_workspace_name(this._index);
|
|
- this._tooltip.opacity = 0;
|
|
- this._tooltip.show();
|
|
-
|
|
- const [stageX, stageY] = this.get_transformed_position();
|
|
- const thumbWidth = this.allocation.get_width();
|
|
- const thumbHeight = this.allocation.get_height();
|
|
- const tipWidth = this._tooltip.width;
|
|
- const xOffset = Math.floor((thumbWidth - tipWidth) / 2);
|
|
- const monitor = Main.layoutManager.findMonitorForActor(this);
|
|
- const x = Math.min(
|
|
- Math.max(stageX + xOffset, monitor.x),
|
|
- monitor.x + monitor.width - tipWidth);
|
|
- const y = stageY + thumbHeight + TOOLTIP_OFFSET;
|
|
- this._tooltip.set_position(x, y);
|
|
- }
|
|
-
|
|
- Tweener.addTween(this._tooltip, {
|
|
- opacity: this.hover ? 255 : 0,
|
|
- time: TOOLTIP_ANIMATION_TIME / 1000,
|
|
- transition: 'easeOutQuad',
|
|
- onComplete: () => (this._tooltip.visible = this.hover),
|
|
- });
|
|
- }
|
|
-
|
|
- _onDestroy() {
|
|
- this._tooltip.destroy();
|
|
-
|
|
- this._workspace.disconnect(this._windowAddedId);
|
|
- this._workspace.disconnect(this._windowRemovedId);
|
|
- global.display.disconnect(this._restackedId);
|
|
- }
|
|
-});
|
|
-
|
|
-let WorkspaceIndicator = GObject.registerClass(
|
|
-class WorkspaceIndicator extends PanelMenu.Button {
|
|
- _init() {
|
|
- super._init(0.0, _('Workspace Indicator'));
|
|
-
|
|
- let container = new St.Widget({
|
|
- layout_manager: new Clutter.BinLayout(),
|
|
- x_expand: true,
|
|
- y_expand: true
|
|
- });
|
|
- this.add_actor(container);
|
|
-
|
|
- let workspaceManager = global.workspace_manager;
|
|
-
|
|
- this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
|
- this._statusLabel = new St.Label({
|
|
- style_class: 'panel-workspace-indicator',
|
|
- y_align: Clutter.ActorAlign.CENTER,
|
|
- text: this._labelText()
|
|
- });
|
|
-
|
|
- container.add_actor(this._statusLabel);
|
|
-
|
|
- this._thumbnailsBox = new St.BoxLayout({
|
|
- style_class: 'panel-workspace-indicator-box',
|
|
- y_expand: true,
|
|
- reactive: true
|
|
- });
|
|
-
|
|
- container.add_actor(this._thumbnailsBox);
|
|
-
|
|
- this._workspacesItems = [];
|
|
- 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._onWorkspaceOrientationChanged.bind(this))
|
|
- ];
|
|
-
|
|
- this.connect('scroll-event', this._onScrollEvent.bind(this));
|
|
- this._thumbnailsBox.connect('scroll-event', this._onScrollEvent.bind(this));
|
|
- this._createWorkspacesSection();
|
|
- this._updateThumbnails();
|
|
- this._onWorkspaceOrientationChanged();
|
|
-
|
|
- this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA });
|
|
- this._settingsChangedId = this._settings.connect(
|
|
- `changed::${WORKSPACE_KEY}`,
|
|
- 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;
|
|
- }
|
|
-
|
|
- Main.panel.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
|
|
-
|
|
- super._onDestroy();
|
|
- }
|
|
-
|
|
- _onWorkspaceOrientationChanged() {
|
|
- let vertical = global.workspace_manager.layout_rows == -1;
|
|
- this.reactive = vertical;
|
|
-
|
|
- this._statusLabel.visible = vertical;
|
|
- this._thumbnailsBox.visible = !vertical;
|
|
-
|
|
- // Disable offscreen-redirect when showing the workspace switcher
|
|
- // so that clip-to-allocation works
|
|
- Main.panel.set_offscreen_redirect(vertical
|
|
- ? Clutter.OffscreenRedirect.ALWAYS
|
|
- : Clutter.OffscreenRedirect.AUTOMATIC_FOR_OPACITY);
|
|
- }
|
|
-
|
|
- _onWorkspaceSwitched() {
|
|
- this._currentWorkspace = global.workspace_manager.get_active_workspace_index();
|
|
-
|
|
- this._updateMenuOrnament();
|
|
- this._updateActiveThumbnail();
|
|
-
|
|
- this._statusLabel.set_text(this._labelText());
|
|
- }
|
|
-
|
|
- _nWorkspacesChanged() {
|
|
- this._createWorkspacesSection();
|
|
- this._updateThumbnails();
|
|
- }
|
|
-
|
|
- _updateMenuOrnament() {
|
|
- for (let i = 0; i < this._workspacesItems.length; i++) {
|
|
- this._workspacesItems[i].setOrnament(i == this._currentWorkspace
|
|
- ? PopupMenu.Ornament.DOT
|
|
- : PopupMenu.Ornament.NONE);
|
|
- }
|
|
- }
|
|
-
|
|
- _updateActiveThumbnail() {
|
|
- let thumbs = this._thumbnailsBox.get_children();
|
|
- for (let i = 0; i < thumbs.length; i++) {
|
|
- if (i == this._currentWorkspace)
|
|
- thumbs[i].add_style_class_name('active');
|
|
- else
|
|
- thumbs[i].remove_style_class_name('active');
|
|
- }
|
|
- }
|
|
-
|
|
- _labelText(workspaceIndex) {
|
|
- if (workspaceIndex == undefined) {
|
|
- workspaceIndex = this._currentWorkspace;
|
|
- return (workspaceIndex + 1).toString();
|
|
- }
|
|
- return Meta.prefs_get_workspace_name(workspaceIndex);
|
|
- }
|
|
-
|
|
- _updateMenuLabels() {
|
|
- for (let i = 0; i < this._workspacesItems.length; i++)
|
|
- this._workspacesItems[i].label.text = this._labelText(i);
|
|
- }
|
|
-
|
|
- _createWorkspacesSection() {
|
|
- let workspaceManager = global.workspace_manager;
|
|
-
|
|
- this._workspaceSection.removeAll();
|
|
- this._workspacesItems = [];
|
|
- this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
|
-
|
|
- let i = 0;
|
|
- for (; i < workspaceManager.n_workspaces; i++) {
|
|
- this._workspacesItems[i] = new PopupMenu.PopupMenuItem(this._labelText(i));
|
|
- this._workspaceSection.addMenuItem(this._workspacesItems[i]);
|
|
- this._workspacesItems[i].workspaceId = i;
|
|
- this._workspacesItems[i].label_actor = this._statusLabel;
|
|
- this._workspacesItems[i].connect('activate', (actor, _event) => {
|
|
- this._activate(actor.workspaceId);
|
|
- });
|
|
-
|
|
- if (i == this._currentWorkspace)
|
|
- this._workspacesItems[i].setOrnament(PopupMenu.Ornament.DOT);
|
|
- }
|
|
-
|
|
- this._statusLabel.set_text(this._labelText());
|
|
- }
|
|
-
|
|
- _updateThumbnails() {
|
|
- let workspaceManager = global.workspace_manager;
|
|
-
|
|
- this._thumbnailsBox.destroy_all_children();
|
|
-
|
|
- for (let i = 0; i < workspaceManager.n_workspaces; i++) {
|
|
- let thumb = new WorkspaceThumbnail(i);
|
|
- this._thumbnailsBox.add_actor(thumb);
|
|
- }
|
|
- this._updateActiveThumbnail();
|
|
- }
|
|
-
|
|
- _activate(index) {
|
|
- let workspaceManager = global.workspace_manager;
|
|
-
|
|
- if (index >= 0 && index < workspaceManager.n_workspaces) {
|
|
- let metaWorkspace = workspaceManager.get_workspace_by_index(index);
|
|
- metaWorkspace.activate(global.get_current_time());
|
|
- }
|
|
- }
|
|
-
|
|
- _onScrollEvent(actor, event) {
|
|
- let direction = event.get_scroll_direction();
|
|
- let diff = 0;
|
|
- if (direction == Clutter.ScrollDirection.DOWN) {
|
|
- diff = 1;
|
|
- } else if (direction == Clutter.ScrollDirection.UP) {
|
|
- diff = -1;
|
|
- } else {
|
|
- return;
|
|
- }
|
|
|
|
- let newIndex = global.workspace_manager.get_active_workspace_index() + diff;
|
|
- this._activate(newIndex);
|
|
- }
|
|
-});
|
|
+const Me = ExtensionUtils.getCurrentExtension();
|
|
+const { WorkspaceIndicator } = Me.imports.workspaceIndicator;
|
|
|
|
function init() {
|
|
ExtensionUtils.initTranslations();
|
|
diff --git a/extensions/workspace-indicator/meson.build b/extensions/workspace-indicator/meson.build
|
|
index 19858a39..eb25b9cc 100644
|
|
--- a/extensions/workspace-indicator/meson.build
|
|
+++ b/extensions/workspace-indicator/meson.build
|
|
@@ -5,4 +5,4 @@ extension_data += configure_file(
|
|
)
|
|
extension_data += files('stylesheet.css')
|
|
|
|
-extension_sources += files('prefs.js')
|
|
+extension_sources += files('prefs.js', 'workspaceIndicator.js')
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
new file mode 100644
|
|
index 00000000..83a0dffa
|
|
--- /dev/null
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -0,0 +1,443 @@
|
|
+const { Clutter, Gio, GObject, Meta, St } = imports.gi;
|
|
+
|
|
+const DND = imports.ui.dnd;
|
|
+const Main = imports.ui.main;
|
|
+const PanelMenu = imports.ui.panelMenu;
|
|
+const PopupMenu = imports.ui.popupMenu;
|
|
+const Tweener = imports.ui.tweener;
|
|
+
|
|
+const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
|
+const _ = Gettext.gettext;
|
|
+
|
|
+const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
|
|
+const WORKSPACE_KEY = 'workspace-names';
|
|
+
|
|
+const TOOLTIP_OFFSET = 6;
|
|
+const TOOLTIP_ANIMATION_TIME = 150;
|
|
+
|
|
+let WindowPreview = GObject.registerClass({
|
|
+ GTypeName: 'WorkspaceIndicatorWindowPreview'
|
|
+}, class WindowPreview extends St.Button {
|
|
+ _init(window) {
|
|
+ super._init({
|
|
+ style_class: 'workspace-indicator-window-preview'
|
|
+ });
|
|
+
|
|
+ this._delegate = this;
|
|
+ DND.makeDraggable(this, { restoreOnSuccess: true });
|
|
+
|
|
+ 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.queue_relayout());
|
|
+ this._minimizedChangedId = this._window.connect('notify::minimized',
|
|
+ this._updateVisible.bind(this));
|
|
+ this._monitorEnteredId = global.display.connect('window-entered-monitor',
|
|
+ this._updateVisible.bind(this));
|
|
+ this._monitorLeftId = global.display.connect('window-left-monitor',
|
|
+ this._updateVisible.bind(this));
|
|
+
|
|
+ this._focusChangedId = global.display.connect('notify::focus-window',
|
|
+ this._onFocusChanged.bind(this));
|
|
+ this._onFocusChanged();
|
|
+ }
|
|
+
|
|
+ // needed for DND
|
|
+ get realWindow() {
|
|
+ return this._window.get_compositor_private();
|
|
+ }
|
|
+
|
|
+ get metaWindow() {
|
|
+ return this._window;
|
|
+ }
|
|
+
|
|
+ _onDestroy() {
|
|
+ this._window.disconnect(this._sizeChangedId);
|
|
+ this._window.disconnect(this._positionChangedId);
|
|
+ this._window.disconnect(this._minimizedChangedId);
|
|
+ global.display.disconnect(this._monitorEnteredId);
|
|
+ global.display.disconnect(this._monitorLeftId);
|
|
+ global.display.disconnect(this._focusChangedId);
|
|
+ }
|
|
+
|
|
+ _onFocusChanged() {
|
|
+ if (global.display.focus_window == this._window)
|
|
+ this.add_style_class_name('active');
|
|
+ else
|
|
+ this.remove_style_class_name('active');
|
|
+ }
|
|
+
|
|
+ _updateVisible() {
|
|
+ let monitor = Main.layoutManager.findIndexForActor(this);
|
|
+ this.visible = monitor == this._window.get_monitor() &&
|
|
+ this._window.showing_on_its_workspace();
|
|
+ }
|
|
+});
|
|
+
|
|
+let WorkspaceLayout = GObject.registerClass(
|
|
+class WorkspaceLayout extends Clutter.LayoutManager {
|
|
+ vfunc_get_preferred_width() {
|
|
+ return [0, 0];
|
|
+ }
|
|
+
|
|
+ vfunc_get_preferred_height() {
|
|
+ return [0, 0];
|
|
+ }
|
|
+
|
|
+ vfunc_allocate(container, box, flags) {
|
|
+ const monitor = Main.layoutManager.findIndexForActor(container);
|
|
+ const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
|
|
+ const hscale = box.get_width() / workArea.width;
|
|
+ const vscale = box.get_height() / workArea.height;
|
|
+
|
|
+ for (const child of container.get_children()) {
|
|
+ const childBox = new Clutter.ActorBox();
|
|
+ const frameRect = child.metaWindow.get_frame_rect();
|
|
+ childBox.set_size(
|
|
+ Math.min(frameRect.width, workArea.width) * hscale,
|
|
+ Math.min(frameRect.height, workArea.height) * vscale);
|
|
+ childBox.set_origin(
|
|
+ Math.round(frameRect.x * hscale),
|
|
+ Math.round(frameRect.y * vscale));
|
|
+ child.allocate(childBox, flags);
|
|
+ }
|
|
+ }
|
|
+});
|
|
+
|
|
+let WorkspaceThumbnail = GObject.registerClass({
|
|
+ GTypeName: 'WorkspaceIndicatorWorkspaceThumbnail'
|
|
+}, class WorkspaceThumbnail extends St.Button {
|
|
+ _init(index) {
|
|
+ super._init({
|
|
+ style_class: 'workspace',
|
|
+ child: new Clutter.Actor({
|
|
+ layout_manager: new WorkspaceLayout(),
|
|
+ clip_to_allocation: true
|
|
+ }),
|
|
+ x_fill: true,
|
|
+ y_fill: true
|
|
+ });
|
|
+
|
|
+ this._tooltip = new St.Label({
|
|
+ style_class: 'dash-label',
|
|
+ visible: false,
|
|
+ });
|
|
+ Main.uiGroup.add_child(this._tooltip);
|
|
+
|
|
+ this.connect('destroy', this._onDestroy.bind(this));
|
|
+ this.connect('notify::hover', this._syncTooltip.bind(this));
|
|
+
|
|
+ this._index = index;
|
|
+ this._delegate = this; // needed for DND
|
|
+
|
|
+ this._windowPreviews = new Map();
|
|
+
|
|
+ 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.list_windows().forEach(w => this._addWindow(w));
|
|
+ this._onRestacked();
|
|
+ }
|
|
+
|
|
+ acceptDrop(source) {
|
|
+ if (!source.realWindow)
|
|
+ return false;
|
|
+
|
|
+ let window = source.realWindow.get_meta_window();
|
|
+ this._moveWindow(window);
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ handleDragOver(source) {
|
|
+ if (source.realWindow)
|
|
+ return DND.DragMotionResult.MOVE_DROP;
|
|
+ else
|
|
+ return DND.DragMotionResult.CONTINUE;
|
|
+ }
|
|
+
|
|
+ _addWindow(window) {
|
|
+ if (this._windowPreviews.has(window))
|
|
+ return;
|
|
+
|
|
+ let preview = new WindowPreview(window);
|
|
+ preview.connect('clicked', (a, btn) => this.emit('clicked', btn));
|
|
+ this._windowPreviews.set(window, preview);
|
|
+ this.child.add_child(preview);
|
|
+ }
|
|
+
|
|
+ _removeWindow(window) {
|
|
+ let preview = this._windowPreviews.get(window);
|
|
+ if (!preview)
|
|
+ return;
|
|
+
|
|
+ this._windowPreviews.delete(window);
|
|
+ preview.destroy();
|
|
+ }
|
|
+
|
|
+ _onRestacked() {
|
|
+ let lastPreview = null;
|
|
+ let windows = global.get_window_actors().map(a => a.meta_window);
|
|
+ for (let i = 0; i < windows.length; i++) {
|
|
+ let preview = this._windowPreviews.get(windows[i]);
|
|
+ if (!preview)
|
|
+ continue;
|
|
+
|
|
+ this.child.set_child_above_sibling(preview, lastPreview);
|
|
+ lastPreview = preview;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ _moveWindow(window) {
|
|
+ let monitorIndex = Main.layoutManager.findIndexForActor(this);
|
|
+ if (monitorIndex != window.get_monitor())
|
|
+ window.move_to_monitor(monitorIndex);
|
|
+ window.change_workspace_by_index(this._index, false);
|
|
+ }
|
|
+
|
|
+ // eslint-disable-next-line camelcase
|
|
+ on_clicked() {
|
|
+ let ws = global.workspace_manager.get_workspace_by_index(this._index);
|
|
+ if (ws)
|
|
+ ws.activate(global.get_current_time());
|
|
+ }
|
|
+
|
|
+ _syncTooltip() {
|
|
+ if (this.hover) {
|
|
+ this._tooltip.text = Meta.prefs_get_workspace_name(this._index);
|
|
+ this._tooltip.opacity = 0;
|
|
+ this._tooltip.show();
|
|
+
|
|
+ const [stageX, stageY] = this.get_transformed_position();
|
|
+ const thumbWidth = this.allocation.get_width();
|
|
+ const thumbHeight = this.allocation.get_height();
|
|
+ const tipWidth = this._tooltip.width;
|
|
+ const xOffset = Math.floor((thumbWidth - tipWidth) / 2);
|
|
+ const monitor = Main.layoutManager.findMonitorForActor(this);
|
|
+ const x = Math.min(
|
|
+ Math.max(stageX + xOffset, monitor.x),
|
|
+ monitor.x + monitor.width - tipWidth);
|
|
+ const y = stageY + thumbHeight + TOOLTIP_OFFSET;
|
|
+ this._tooltip.set_position(x, y);
|
|
+ }
|
|
+
|
|
+ Tweener.addTween(this._tooltip, {
|
|
+ opacity: this.hover ? 255 : 0,
|
|
+ time: TOOLTIP_ANIMATION_TIME / 1000,
|
|
+ transition: 'easeOutQuad',
|
|
+ onComplete: () => (this._tooltip.visible = this.hover),
|
|
+ });
|
|
+ }
|
|
+
|
|
+ _onDestroy() {
|
|
+ this._tooltip.destroy();
|
|
+
|
|
+ this._workspace.disconnect(this._windowAddedId);
|
|
+ this._workspace.disconnect(this._windowRemovedId);
|
|
+ global.display.disconnect(this._restackedId);
|
|
+ }
|
|
+});
|
|
+
|
|
+let WorkspaceIndicator = GObject.registerClass(
|
|
+class WorkspaceIndicator extends PanelMenu.Button {
|
|
+ _init() {
|
|
+ super._init(0.0, _('Workspace Indicator'));
|
|
+
|
|
+ let container = new St.Widget({
|
|
+ layout_manager: new Clutter.BinLayout(),
|
|
+ x_expand: true,
|
|
+ y_expand: true
|
|
+ });
|
|
+ this.add_actor(container);
|
|
+
|
|
+ let workspaceManager = global.workspace_manager;
|
|
+
|
|
+ this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
|
+ this._statusLabel = new St.Label({
|
|
+ style_class: 'panel-workspace-indicator',
|
|
+ y_align: Clutter.ActorAlign.CENTER,
|
|
+ text: this._labelText()
|
|
+ });
|
|
+
|
|
+ container.add_actor(this._statusLabel);
|
|
+
|
|
+ this._thumbnailsBox = new St.BoxLayout({
|
|
+ style_class: 'panel-workspace-indicator-box',
|
|
+ y_expand: true,
|
|
+ reactive: true
|
|
+ });
|
|
+
|
|
+ container.add_actor(this._thumbnailsBox);
|
|
+
|
|
+ this._workspacesItems = [];
|
|
+ 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._onWorkspaceOrientationChanged.bind(this))
|
|
+ ];
|
|
+
|
|
+ this.connect('scroll-event', this._onScrollEvent.bind(this));
|
|
+ this._thumbnailsBox.connect('scroll-event', this._onScrollEvent.bind(this));
|
|
+ this._createWorkspacesSection();
|
|
+ this._updateThumbnails();
|
|
+ this._onWorkspaceOrientationChanged();
|
|
+
|
|
+ this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA });
|
|
+ this._settingsChangedId = this._settings.connect(
|
|
+ `changed::${WORKSPACE_KEY}`,
|
|
+ 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;
|
|
+ }
|
|
+
|
|
+ Main.panel.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
|
|
+
|
|
+ super._onDestroy();
|
|
+ }
|
|
+
|
|
+ _onWorkspaceOrientationChanged() {
|
|
+ let vertical = global.workspace_manager.layout_rows == -1;
|
|
+ this.reactive = vertical;
|
|
+
|
|
+ this._statusLabel.visible = vertical;
|
|
+ this._thumbnailsBox.visible = !vertical;
|
|
+
|
|
+ // Disable offscreen-redirect when showing the workspace switcher
|
|
+ // so that clip-to-allocation works
|
|
+ Main.panel.set_offscreen_redirect(vertical
|
|
+ ? Clutter.OffscreenRedirect.ALWAYS
|
|
+ : Clutter.OffscreenRedirect.AUTOMATIC_FOR_OPACITY);
|
|
+ }
|
|
+
|
|
+ _onWorkspaceSwitched() {
|
|
+ this._currentWorkspace = global.workspace_manager.get_active_workspace_index();
|
|
+
|
|
+ this._updateMenuOrnament();
|
|
+ this._updateActiveThumbnail();
|
|
+
|
|
+ this._statusLabel.set_text(this._labelText());
|
|
+ }
|
|
+
|
|
+ _nWorkspacesChanged() {
|
|
+ this._createWorkspacesSection();
|
|
+ this._updateThumbnails();
|
|
+ }
|
|
+
|
|
+ _updateMenuOrnament() {
|
|
+ for (let i = 0; i < this._workspacesItems.length; i++) {
|
|
+ this._workspacesItems[i].setOrnament(i == this._currentWorkspace
|
|
+ ? PopupMenu.Ornament.DOT
|
|
+ : PopupMenu.Ornament.NONE);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ _updateActiveThumbnail() {
|
|
+ let thumbs = this._thumbnailsBox.get_children();
|
|
+ for (let i = 0; i < thumbs.length; i++) {
|
|
+ if (i == this._currentWorkspace)
|
|
+ thumbs[i].add_style_class_name('active');
|
|
+ else
|
|
+ thumbs[i].remove_style_class_name('active');
|
|
+ }
|
|
+ }
|
|
+
|
|
+ _labelText(workspaceIndex) {
|
|
+ if (workspaceIndex == undefined) {
|
|
+ workspaceIndex = this._currentWorkspace;
|
|
+ return (workspaceIndex + 1).toString();
|
|
+ }
|
|
+ return Meta.prefs_get_workspace_name(workspaceIndex);
|
|
+ }
|
|
+
|
|
+ _updateMenuLabels() {
|
|
+ for (let i = 0; i < this._workspacesItems.length; i++)
|
|
+ this._workspacesItems[i].label.text = this._labelText(i);
|
|
+ }
|
|
+
|
|
+ _createWorkspacesSection() {
|
|
+ let workspaceManager = global.workspace_manager;
|
|
+
|
|
+ this._workspaceSection.removeAll();
|
|
+ this._workspacesItems = [];
|
|
+ this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
|
+
|
|
+ let i = 0;
|
|
+ for (; i < workspaceManager.n_workspaces; i++) {
|
|
+ this._workspacesItems[i] = new PopupMenu.PopupMenuItem(this._labelText(i));
|
|
+ this._workspaceSection.addMenuItem(this._workspacesItems[i]);
|
|
+ this._workspacesItems[i].workspaceId = i;
|
|
+ this._workspacesItems[i].label_actor = this._statusLabel;
|
|
+ this._workspacesItems[i].connect('activate', (actor, _event) => {
|
|
+ this._activate(actor.workspaceId);
|
|
+ });
|
|
+
|
|
+ if (i == this._currentWorkspace)
|
|
+ this._workspacesItems[i].setOrnament(PopupMenu.Ornament.DOT);
|
|
+ }
|
|
+
|
|
+ this._statusLabel.set_text(this._labelText());
|
|
+ }
|
|
+
|
|
+ _updateThumbnails() {
|
|
+ let workspaceManager = global.workspace_manager;
|
|
+
|
|
+ this._thumbnailsBox.destroy_all_children();
|
|
+
|
|
+ for (let i = 0; i < workspaceManager.n_workspaces; i++) {
|
|
+ let thumb = new WorkspaceThumbnail(i);
|
|
+ this._thumbnailsBox.add_actor(thumb);
|
|
+ }
|
|
+ this._updateActiveThumbnail();
|
|
+ }
|
|
+
|
|
+ _activate(index) {
|
|
+ let workspaceManager = global.workspace_manager;
|
|
+
|
|
+ if (index >= 0 && index < workspaceManager.n_workspaces) {
|
|
+ let metaWorkspace = workspaceManager.get_workspace_by_index(index);
|
|
+ metaWorkspace.activate(global.get_current_time());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ _onScrollEvent(actor, event) {
|
|
+ let direction = event.get_scroll_direction();
|
|
+ let diff = 0;
|
|
+ if (direction == Clutter.ScrollDirection.DOWN) {
|
|
+ diff = 1;
|
|
+ } else if (direction == Clutter.ScrollDirection.UP) {
|
|
+ diff = -1;
|
|
+ } else {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ let newIndex = global.workspace_manager.get_active_workspace_index() + diff;
|
|
+ this._activate(newIndex);
|
|
+ }
|
|
+});
|
|
diff --git a/po/POTFILES.in b/po/POTFILES.in
|
|
index 55f0e9aa..5cdb710f 100644
|
|
--- a/po/POTFILES.in
|
|
+++ b/po/POTFILES.in
|
|
@@ -18,5 +18,5 @@ extensions/window-list/extension.js
|
|
extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml
|
|
extensions/window-list/prefs.js
|
|
extensions/windowsNavigator/extension.js
|
|
-extensions/workspace-indicator/extension.js
|
|
extensions/workspace-indicator/prefs.js
|
|
+extensions/workspace-indicator/workspaceIndicator.js
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From dd928d44f1fbc1536c4ae30bad2130c1fc4432ac Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 21 Feb 2024 19:09:38 +0100
|
|
Subject: [PATCH 04/43] workspace-indicator: Use descendant style selectors
|
|
|
|
Add a style class to the indicator itself, and only select
|
|
descendant elements. This allows using the briefer class names
|
|
from the window-list extension without too much risk of conflicts.
|
|
---
|
|
extensions/workspace-indicator/stylesheet.css | 32 +++++++------------
|
|
.../workspace-indicator/workspaceIndicator.js | 6 ++--
|
|
2 files changed, 16 insertions(+), 22 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/stylesheet.css b/extensions/workspace-indicator/stylesheet.css
|
|
index 8c101e79..3f89359b 100644
|
|
--- a/extensions/workspace-indicator/stylesheet.css
|
|
+++ b/extensions/workspace-indicator/stylesheet.css
|
|
@@ -1,29 +1,21 @@
|
|
-.panel-workspace-indicator {
|
|
- padding: 0 8px;
|
|
- border: 1px solid #cccccc;
|
|
+.workspace-indicator .status-label {
|
|
+ padding: 0 8px;
|
|
}
|
|
|
|
-.panel-workspace-indicator-box {
|
|
- padding: 2px 0;
|
|
+.workspace-indicator .workspaces-box {
|
|
+ padding: 4px 0;
|
|
+ spacing: 4px;
|
|
}
|
|
|
|
-.panel-workspace-indicator-box .workspace {
|
|
- border: 1px solid #cccccc;
|
|
- width: 48px;
|
|
+.workspace-indicator .workspace {
|
|
+ width: 40px;
|
|
+ border: 2px solid #000;
|
|
+ border-radius: 2px;
|
|
+ background-color: #595959;
|
|
}
|
|
|
|
-.panel-workspace-indicator,
|
|
-.panel-workspace-indicator-box .workspace.active {
|
|
- background-color: rgba(200, 200, 200, .5);
|
|
-}
|
|
-
|
|
-.panel-workspace-indicator-box .workspace {
|
|
- background-color: rgba(200, 200, 200, .3);
|
|
- border-left-width: 0;
|
|
-}
|
|
-
|
|
-.panel-workspace-indicator-box .workspace:first-child {
|
|
- border-left-width: 1px;
|
|
+.workspace-indicator .workspace.active {
|
|
+ border-color: #fff;
|
|
}
|
|
|
|
.workspace-indicator-window-preview {
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 83a0dffa..2b102117 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -257,6 +257,8 @@ class WorkspaceIndicator extends PanelMenu.Button {
|
|
_init() {
|
|
super._init(0.0, _('Workspace Indicator'));
|
|
|
|
+ this.add_style_class_name('workspace-indicator');
|
|
+
|
|
let container = new St.Widget({
|
|
layout_manager: new Clutter.BinLayout(),
|
|
x_expand: true,
|
|
@@ -268,7 +270,7 @@ class WorkspaceIndicator extends PanelMenu.Button {
|
|
|
|
this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
|
this._statusLabel = new St.Label({
|
|
- style_class: 'panel-workspace-indicator',
|
|
+ style_class: 'status-label',
|
|
y_align: Clutter.ActorAlign.CENTER,
|
|
text: this._labelText()
|
|
});
|
|
@@ -276,7 +278,7 @@ class WorkspaceIndicator extends PanelMenu.Button {
|
|
container.add_actor(this._statusLabel);
|
|
|
|
this._thumbnailsBox = new St.BoxLayout({
|
|
- style_class: 'panel-workspace-indicator-box',
|
|
+ style_class: 'workspaces-box',
|
|
y_expand: true,
|
|
reactive: true
|
|
});
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 9a92b49c1835e44b5f3ddf2088f24cf3dd82b8c1 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 21 Feb 2024 12:48:43 +0100
|
|
Subject: [PATCH 05/43] window-list: Use consistent style class prefix
|
|
|
|
This will eventually allow us to re-use the workspace-indicator
|
|
extension without changing anything but the used prefix.
|
|
---
|
|
extensions/window-list/classic.css | 4 ++--
|
|
extensions/window-list/stylesheet.css | 11 +++++------
|
|
extensions/window-list/workspaceIndicator.js | 2 +-
|
|
3 files changed, 8 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css
|
|
index 7079d3ef..02286041 100644
|
|
--- a/extensions/window-list/classic.css
|
|
+++ b/extensions/window-list/classic.css
|
|
@@ -57,12 +57,12 @@
|
|
background-color: #ccc;
|
|
}
|
|
|
|
-.window-list-window-preview {
|
|
+.window-list-workspace-indicator-window-preview {
|
|
background-color: #ededed;
|
|
border: 1px solid #ccc;
|
|
}
|
|
|
|
-.window-list-window-preview.active {
|
|
+.window-list-workspace-indicator-window-preview.active {
|
|
background-color: #f6f5f4;
|
|
border: 2px solid #888;
|
|
}
|
|
diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css
|
|
index 2c98aafe..4c9ca671 100644
|
|
--- a/extensions/window-list/stylesheet.css
|
|
+++ b/extensions/window-list/stylesheet.css
|
|
@@ -121,14 +121,13 @@
|
|
background-color: rgba(200, 200, 200, .3);
|
|
}
|
|
|
|
-.window-list-window-preview {
|
|
- background-color: #252525;
|
|
- border: 1px solid #ccc;
|
|
+.window-list-workspace-indicator-window-preview {
|
|
+ background-color: #bebebe;
|
|
+ border: 1px solid #828282;
|
|
}
|
|
|
|
-.window-list-window-preview.active {
|
|
- background-color: #353535;
|
|
- border: 2px solid #ccc;
|
|
+.window-list-workspace-indicator-window-preview.active {
|
|
+ background-color: #d4d4d4;
|
|
}
|
|
|
|
.notification {
|
|
diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js
|
|
index 8ae9b288..4e8f1aff 100644
|
|
--- a/extensions/window-list/workspaceIndicator.js
|
|
+++ b/extensions/window-list/workspaceIndicator.js
|
|
@@ -18,7 +18,7 @@ let WindowPreview = GObject.registerClass({
|
|
}, class WindowPreview extends St.Button {
|
|
_init(window) {
|
|
super._init({
|
|
- style_class: 'window-list-window-preview'
|
|
+ style_class: 'window-list-workspace-indicator-window-preview',
|
|
});
|
|
|
|
this._delegate = this;
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 6db2bc97a0aba60650abff4e82a1b5683db474c5 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Fri, 23 Feb 2024 01:59:15 +0100
|
|
Subject: [PATCH 06/43] workspace-indicator: Allow overriding base style class
|
|
|
|
This will allow reusing the code from the window-list extension
|
|
without limiting the ability to specify styling that only applies
|
|
to one of the extensions.
|
|
---
|
|
.../workspace-indicator/workspaceIndicator.js | 13 ++++++++++---
|
|
1 file changed, 10 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 2b102117..57a3f7ec 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -15,12 +15,14 @@ const WORKSPACE_KEY = 'workspace-names';
|
|
const TOOLTIP_OFFSET = 6;
|
|
const TOOLTIP_ANIMATION_TIME = 150;
|
|
|
|
+let baseStyleClassName = '';
|
|
+
|
|
let WindowPreview = GObject.registerClass({
|
|
GTypeName: 'WorkspaceIndicatorWindowPreview'
|
|
}, class WindowPreview extends St.Button {
|
|
_init(window) {
|
|
super._init({
|
|
- style_class: 'workspace-indicator-window-preview'
|
|
+ style_class: `${baseStyleClassName}-window-preview`,
|
|
});
|
|
|
|
this._delegate = this;
|
|
@@ -254,10 +256,15 @@ let WorkspaceThumbnail = GObject.registerClass({
|
|
|
|
let WorkspaceIndicator = GObject.registerClass(
|
|
class WorkspaceIndicator extends PanelMenu.Button {
|
|
- _init() {
|
|
+ _init(params = {}) {
|
|
super._init(0.0, _('Workspace Indicator'));
|
|
|
|
- this.add_style_class_name('workspace-indicator');
|
|
+ const {
|
|
+ baseStyleClass = 'workspace-indicator',
|
|
+ } = params;
|
|
+
|
|
+ baseStyleClassName = baseStyleClass;
|
|
+ this.add_style_class_name(baseStyleClassName);
|
|
|
|
let container = new St.Widget({
|
|
layout_manager: new Clutter.BinLayout(),
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 8f4cc8742093a791bf64470ea2e04b18c37a59e1 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Fri, 11 Jul 2025 12:09:18 +0200
|
|
Subject: [PATCH 07/43] workspace-indicator: Support prefix for GType names
|
|
|
|
GTypes have to be unique, so to allow the code to be eventually
|
|
shared with the window-list extension, support adding a custom
|
|
prefix to type names.
|
|
---
|
|
.../workspace-indicator/workspaceIndicator.js | 16 ++++++++++------
|
|
1 file changed, 10 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 57a3f7ec..2a026c5d 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -17,8 +17,10 @@ const TOOLTIP_ANIMATION_TIME = 150;
|
|
|
|
let baseStyleClassName = '';
|
|
|
|
+const TypePrefix = window.TypePrefix || '';
|
|
+
|
|
let WindowPreview = GObject.registerClass({
|
|
- GTypeName: 'WorkspaceIndicatorWindowPreview'
|
|
+ GTypeName: `${TypePrefix}WorkspaceIndicatorWindowPreview`
|
|
}, class WindowPreview extends St.Button {
|
|
_init(window) {
|
|
super._init({
|
|
@@ -80,8 +82,9 @@ let WindowPreview = GObject.registerClass({
|
|
}
|
|
});
|
|
|
|
-let WorkspaceLayout = GObject.registerClass(
|
|
-class WorkspaceLayout extends Clutter.LayoutManager {
|
|
+let WorkspaceLayout = GObject.registerClass({
|
|
+ GTypeName: `${TypePrefix}WorkspaceIndicatorWorkspaceLayout`
|
|
+}, class WorkspaceLayout extends Clutter.LayoutManager {
|
|
vfunc_get_preferred_width() {
|
|
return [0, 0];
|
|
}
|
|
@@ -111,7 +114,7 @@ class WorkspaceLayout extends Clutter.LayoutManager {
|
|
});
|
|
|
|
let WorkspaceThumbnail = GObject.registerClass({
|
|
- GTypeName: 'WorkspaceIndicatorWorkspaceThumbnail'
|
|
+ GTypeName: `${TypePrefix}WorkspaceIndicatorWorkspaceThumbnail`
|
|
}, class WorkspaceThumbnail extends St.Button {
|
|
_init(index) {
|
|
super._init({
|
|
@@ -254,8 +257,9 @@ let WorkspaceThumbnail = GObject.registerClass({
|
|
}
|
|
});
|
|
|
|
-let WorkspaceIndicator = GObject.registerClass(
|
|
-class WorkspaceIndicator extends PanelMenu.Button {
|
|
+let WorkspaceIndicator = GObject.registerClass({
|
|
+ GTypeName: `${TypePrefix}WorkspaceIndicator`
|
|
+}, class WorkspaceIndicator extends PanelMenu.Button {
|
|
_init(params = {}) {
|
|
super._init(0.0, _('Workspace Indicator'));
|
|
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 09116b6f8e6477c4347fec0f035e74d508b08288 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Fri, 23 Feb 2024 01:58:50 +0100
|
|
Subject: [PATCH 08/43] window-list: Override base style class
|
|
|
|
Apply the changes from the last commit to the workspace-indicator
|
|
copy, and override the base style class from the extension.
|
|
|
|
This will eventually allow us to share the exact same code between
|
|
the two extensions, but still use individual styling if necessary.
|
|
---
|
|
extensions/window-list/extension.js | 4 +++-
|
|
extensions/window-list/workspaceIndicator.js | 15 ++++++++++++---
|
|
2 files changed, 15 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js
|
|
index 11ac393b..e1bbc0de 100644
|
|
--- a/extensions/window-list/extension.js
|
|
+++ b/extensions/window-list/extension.js
|
|
@@ -813,7 +813,9 @@ class WindowList {
|
|
let indicatorsBox = new St.BoxLayout({ x_align: Clutter.ActorAlign.END });
|
|
box.add(indicatorsBox);
|
|
|
|
- this._workspaceIndicator = new WorkspaceIndicator();
|
|
+ this._workspaceIndicator = new WorkspaceIndicator({
|
|
+ baseStyleClass: 'window-list-workspace-indicator',
|
|
+ });
|
|
indicatorsBox.add(this._workspaceIndicator.container, { expand: false, y_fill: true });
|
|
|
|
this._mutterSettings = new Gio.Settings({ schema_id: 'org.gnome.mutter' });
|
|
diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js
|
|
index 4e8f1aff..48a8eb22 100644
|
|
--- a/extensions/window-list/workspaceIndicator.js
|
|
+++ b/extensions/window-list/workspaceIndicator.js
|
|
@@ -13,12 +13,14 @@ const _ = Gettext.gettext;
|
|
const TOOLTIP_OFFSET = 6;
|
|
const TOOLTIP_ANIMATION_TIME = 150;
|
|
|
|
+let baseStyleClassName = '';
|
|
+
|
|
let WindowPreview = GObject.registerClass({
|
|
GTypeName: 'WindowListWindowPreview'
|
|
}, class WindowPreview extends St.Button {
|
|
_init(window) {
|
|
super._init({
|
|
- style_class: 'window-list-workspace-indicator-window-preview',
|
|
+ style_class: `${baseStyleClassName}-window-preview`,
|
|
});
|
|
|
|
this._delegate = this;
|
|
@@ -248,10 +250,17 @@ let WorkspaceThumbnail = GObject.registerClass({
|
|
var WorkspaceIndicator = GObject.registerClass({
|
|
GTypeName: 'WindowListWorkspaceIndicator'
|
|
}, class WorkspaceIndicator extends PanelMenu.Button {
|
|
- _init() {
|
|
+ _init(params = {}) {
|
|
super._init(0.0, _('Workspace Indicator'), true);
|
|
+
|
|
+ const {
|
|
+ baseStyleClass = 'workspace-indicator',
|
|
+ } = params;
|
|
+
|
|
+ baseStyleClassName = baseStyleClass;
|
|
+ this.add_style_class_name(baseStyleClassName);
|
|
+
|
|
this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM));
|
|
- this.add_style_class_name('window-list-workspace-indicator');
|
|
this.menu.actor.remove_style_class_name('panel-menu');
|
|
|
|
let container = new St.Widget({
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 86b017644c4a7cb394558f4b96785957aef480ab Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Fri, 11 Jul 2025 12:29:50 +0200
|
|
Subject: [PATCH 09/43] window-list: Set TypePrefix for GType names
|
|
|
|
Apply the changes from the last commit to the workspace-indicator
|
|
copy, and set the type prefix from the extension.
|
|
|
|
This will eventually allow us to share the exact same code between
|
|
the two extensions, without creating conflicting GTypes.
|
|
---
|
|
extensions/window-list/extension.js | 3 +++
|
|
extensions/window-list/workspaceIndicator.js | 8 +++++---
|
|
2 files changed, 8 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js
|
|
index e1bbc0de..ed886919 100644
|
|
--- a/extensions/window-list/extension.js
|
|
+++ b/extensions/window-list/extension.js
|
|
@@ -10,7 +10,10 @@ const Tweener = imports.ui.tweener;
|
|
const ExtensionUtils = imports.misc.extensionUtils;
|
|
const Me = ExtensionUtils.getCurrentExtension();
|
|
const { WindowPicker, WindowPickerToggle } = Me.imports.windowPicker;
|
|
+
|
|
+window.TypePrefix = 'WindowList';
|
|
const { WorkspaceIndicator } = Me.imports.workspaceIndicator;
|
|
+delete window.TypePrefix;
|
|
|
|
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
|
const _ = Gettext.gettext;
|
|
diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js
|
|
index 48a8eb22..c362539e 100644
|
|
--- a/extensions/window-list/workspaceIndicator.js
|
|
+++ b/extensions/window-list/workspaceIndicator.js
|
|
@@ -15,8 +15,10 @@ const TOOLTIP_ANIMATION_TIME = 150;
|
|
|
|
let baseStyleClassName = '';
|
|
|
|
+const TypePrefix = window.TypePrefix || '';
|
|
+
|
|
let WindowPreview = GObject.registerClass({
|
|
- GTypeName: 'WindowListWindowPreview'
|
|
+ GTypeName: `${TypePrefix}WorkspaceIndicatorWindowPreview`
|
|
}, class WindowPreview extends St.Button {
|
|
_init(window) {
|
|
super._init({
|
|
@@ -104,7 +106,7 @@ let WindowPreview = GObject.registerClass({
|
|
});
|
|
|
|
let WorkspaceThumbnail = GObject.registerClass({
|
|
- GTypeName: 'WindowListWorkspaceThumbnail'
|
|
+ GTypeName: `${TypePrefix}WorkspaceIndicatorWorkspaceThumbnail`
|
|
}, class WorkspaceThumbnail extends St.Button {
|
|
_init(index) {
|
|
super._init({
|
|
@@ -248,7 +250,7 @@ let WorkspaceThumbnail = GObject.registerClass({
|
|
});
|
|
|
|
var WorkspaceIndicator = GObject.registerClass({
|
|
- GTypeName: 'WindowListWorkspaceIndicator'
|
|
+ GTypeName: `${TypePrefix}WorkspaceIndicator`
|
|
}, class WorkspaceIndicator extends PanelMenu.Button {
|
|
_init(params = {}) {
|
|
super._init(0.0, _('Workspace Indicator'), true);
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From e0d18355ae3af843bc35412f4379d26af0a9ddcd Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 21 Feb 2024 12:48:43 +0100
|
|
Subject: [PATCH 10/43] window-list: Externally adjust workspace menu
|
|
|
|
In order to use a PanelMenu.Button in the bottom bar, we have
|
|
to tweak its menu a bit.
|
|
|
|
We currently handle this inside the indicator, but that means the
|
|
code diverges from the original code in the workspace-indicator
|
|
extension.
|
|
|
|
Avoid this by using a small subclass that handles the adjustments.
|
|
---
|
|
extensions/window-list/extension.js | 23 ++++++++++++++++++--
|
|
extensions/window-list/workspaceIndicator.js | 5 +----
|
|
2 files changed, 22 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js
|
|
index ed886919..394fec1f 100644
|
|
--- a/extensions/window-list/extension.js
|
|
+++ b/extensions/window-list/extension.js
|
|
@@ -1,5 +1,5 @@
|
|
/* exported init */
|
|
-const { Clutter, Gio, GLib, Gtk, Meta, Shell, St } = imports.gi;
|
|
+const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell, St } = imports.gi;
|
|
|
|
const DND = imports.ui.dnd;
|
|
const Main = imports.ui.main;
|
|
@@ -816,7 +816,7 @@ class WindowList {
|
|
let indicatorsBox = new St.BoxLayout({ x_align: Clutter.ActorAlign.END });
|
|
box.add(indicatorsBox);
|
|
|
|
- this._workspaceIndicator = new WorkspaceIndicator({
|
|
+ this._workspaceIndicator = new BottomWorkspaceIndicator({
|
|
baseStyleClass: 'window-list-workspace-indicator',
|
|
});
|
|
indicatorsBox.add(this._workspaceIndicator.container, { expand: false, y_fill: true });
|
|
@@ -1226,6 +1226,25 @@ class WindowList {
|
|
}
|
|
}
|
|
|
|
+const BottomWorkspaceIndicator = GObject.registerClass(
|
|
+class BottomWorkspaceIndicator extends WorkspaceIndicator {
|
|
+ _init(params) {
|
|
+ super._init(params);
|
|
+
|
|
+ this.remove_style_class_name('panel-button');
|
|
+ }
|
|
+
|
|
+ setMenu(menu) {
|
|
+ super.setMenu(menu);
|
|
+
|
|
+ if (!menu)
|
|
+ return;
|
|
+
|
|
+ this.menu.actor.updateArrowSide(St.Side.BOTTOM);
|
|
+ this.menu.actor.remove_style_class_name('panel-menu');
|
|
+ }
|
|
+});
|
|
+
|
|
class Extension {
|
|
constructor() {
|
|
this._windowLists = null;
|
|
diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js
|
|
index c362539e..574ebdca 100644
|
|
--- a/extensions/window-list/workspaceIndicator.js
|
|
+++ b/extensions/window-list/workspaceIndicator.js
|
|
@@ -253,7 +253,7 @@ var WorkspaceIndicator = GObject.registerClass({
|
|
GTypeName: `${TypePrefix}WorkspaceIndicator`
|
|
}, class WorkspaceIndicator extends PanelMenu.Button {
|
|
_init(params = {}) {
|
|
- super._init(0.0, _('Workspace Indicator'), true);
|
|
+ super._init(0.0, _('Workspace Indicator'));
|
|
|
|
const {
|
|
baseStyleClass = 'workspace-indicator',
|
|
@@ -262,9 +262,6 @@ var WorkspaceIndicator = GObject.registerClass({
|
|
baseStyleClassName = baseStyleClass;
|
|
this.add_style_class_name(baseStyleClassName);
|
|
|
|
- this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM));
|
|
- this.menu.actor.remove_style_class_name('panel-menu');
|
|
-
|
|
let container = new St.Widget({
|
|
layout_manager: new Clutter.BinLayout(),
|
|
x_expand: true,
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From e3b79e9d113570a89227cd7cb598e20fe61c9bd0 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Thu, 21 Mar 2024 16:49:35 +0100
|
|
Subject: [PATCH 11/43] window-list: Handle changes to workspace menu
|
|
|
|
For now the menu is always set at construction time, however this
|
|
will change in the future. Prepare for that by handling the
|
|
`menu-set` signal, similar to the top bar.
|
|
---
|
|
extensions/window-list/extension.js | 9 ++++++++-
|
|
1 file changed, 8 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js
|
|
index 394fec1f..aada9525 100644
|
|
--- a/extensions/window-list/extension.js
|
|
+++ b/extensions/window-list/extension.js
|
|
@@ -831,7 +831,9 @@ class WindowList {
|
|
this._updateWorkspaceIndicatorVisibility();
|
|
|
|
this._menuManager = new PopupMenu.PopupMenuManager(this);
|
|
- this._menuManager.addMenu(this._workspaceIndicator.menu);
|
|
+ this._workspaceIndicator.connect('menu-set',
|
|
+ () => this._onWorkspaceMenuSet());
|
|
+ this._onWorkspaceMenuSet();
|
|
|
|
Main.layoutManager.addChrome(this.actor, {
|
|
affectsStruts: true,
|
|
@@ -931,6 +933,11 @@ class WindowList {
|
|
children[newActive].activate();
|
|
}
|
|
|
|
+ _onWorkspaceMenuSet() {
|
|
+ if (this._workspaceIndicator.menu)
|
|
+ this._menuManager.addMenu(this._workspaceIndicator.menu);
|
|
+ }
|
|
+
|
|
_updatePosition() {
|
|
this.actor.set_position(this._monitor.x,
|
|
this._monitor.y + this._monitor.height - this.actor.height);
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From c8bf13f4e85c1e90535588234a68e66068d02805 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 21 Feb 2024 15:58:39 +0100
|
|
Subject: [PATCH 12/43] workspace-indicator: Don't use SCHEMA/KEY constants
|
|
|
|
Each constant is only used once, so all they do is disconnect
|
|
the actual value from the code that uses it.
|
|
|
|
The copy in the window-list extension just uses the strings directly,
|
|
do the same here.
|
|
---
|
|
extensions/workspace-indicator/workspaceIndicator.js | 7 ++-----
|
|
1 file changed, 2 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 2a026c5d..b1dfc970 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -9,9 +9,6 @@ const Tweener = imports.ui.tweener;
|
|
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
|
const _ = Gettext.gettext;
|
|
|
|
-const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
|
|
-const WORKSPACE_KEY = 'workspace-names';
|
|
-
|
|
const TOOLTIP_OFFSET = 6;
|
|
const TOOLTIP_ANIMATION_TIME = 150;
|
|
|
|
@@ -315,9 +312,9 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._updateThumbnails();
|
|
this._onWorkspaceOrientationChanged();
|
|
|
|
- this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA });
|
|
+ this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' });
|
|
this._settingsChangedId = this._settings.connect(
|
|
- `changed::${WORKSPACE_KEY}`,
|
|
+ 'changed::workspace-names',
|
|
this._updateMenuLabels.bind(this));
|
|
}
|
|
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From dbb82cf4778e324defa564584badc136c4f54448 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 21 Feb 2024 18:59:23 +0100
|
|
Subject: [PATCH 13/43] workspace-indicator: Use existing property
|
|
|
|
We already track the current workspace index, use that
|
|
instead of getting it from the workspace manager again.
|
|
---
|
|
extensions/workspace-indicator/workspaceIndicator.js | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index b1dfc970..7177a810 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -447,7 +447,7 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
return;
|
|
}
|
|
|
|
- let newIndex = global.workspace_manager.get_active_workspace_index() + diff;
|
|
+ const newIndex = this._currentWorkspace + diff;
|
|
this._activate(newIndex);
|
|
}
|
|
});
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From c929efb231745e4e66182a9ee08c5cef2725e9d9 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 21 Feb 2024 16:14:24 +0100
|
|
Subject: [PATCH 14/43] workspace-indicator: Don't use menu section
|
|
|
|
We never added anything else to the menu, so we can just operate
|
|
on the entire menu instead of an intermediate section.
|
|
|
|
This removes another difference with the window-list copy.
|
|
---
|
|
extensions/workspace-indicator/workspaceIndicator.js | 12 +++++-------
|
|
1 file changed, 5 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 7177a810..9563bbc1 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -294,8 +294,6 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
container.add_actor(this._thumbnailsBox);
|
|
|
|
this._workspacesItems = [];
|
|
- this._workspaceSection = new PopupMenu.PopupMenuSection();
|
|
- this.menu.addMenuItem(this._workspaceSection);
|
|
|
|
this._workspaceManagerSignals = [
|
|
workspaceManager.connect_after('notify::n-workspaces',
|
|
@@ -308,7 +306,7 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
|
|
this.connect('scroll-event', this._onScrollEvent.bind(this));
|
|
this._thumbnailsBox.connect('scroll-event', this._onScrollEvent.bind(this));
|
|
- this._createWorkspacesSection();
|
|
+ this._updateMenu();
|
|
this._updateThumbnails();
|
|
this._onWorkspaceOrientationChanged();
|
|
|
|
@@ -356,7 +354,7 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
}
|
|
|
|
_nWorkspacesChanged() {
|
|
- this._createWorkspacesSection();
|
|
+ this._updateMenu();
|
|
this._updateThumbnails();
|
|
}
|
|
|
|
@@ -391,17 +389,17 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._workspacesItems[i].label.text = this._labelText(i);
|
|
}
|
|
|
|
- _createWorkspacesSection() {
|
|
+ _updateMenu() {
|
|
let workspaceManager = global.workspace_manager;
|
|
|
|
- this._workspaceSection.removeAll();
|
|
+ this.menu.removeAll();
|
|
this._workspacesItems = [];
|
|
this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
|
|
|
let i = 0;
|
|
for (; i < workspaceManager.n_workspaces; i++) {
|
|
this._workspacesItems[i] = new PopupMenu.PopupMenuItem(this._labelText(i));
|
|
- this._workspaceSection.addMenuItem(this._workspacesItems[i]);
|
|
+ this.menu.addMenuItem(this._workspacesItems[i]);
|
|
this._workspacesItems[i].workspaceId = i;
|
|
this._workspacesItems[i].label_actor = this._statusLabel;
|
|
this._workspacesItems[i].connect('activate', (actor, _event) => {
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 8d38e180ac3a6832185820589f5f4afa450f4cf1 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 21 Feb 2024 13:05:15 +0100
|
|
Subject: [PATCH 15/43] workspace-indicator: Support showing tooltips above
|
|
|
|
The indicator is located in the top bar, so tooltips are always
|
|
shown below the previews. However supporting showing tooltips
|
|
above previews when space permits allows the same code to be
|
|
used in the copy that is included with the window-list extension.
|
|
---
|
|
extensions/workspace-indicator/workspaceIndicator.js | 9 +++++----
|
|
1 file changed, 5 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 9563bbc1..b87420ac 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -225,15 +225,16 @@ let WorkspaceThumbnail = GObject.registerClass({
|
|
this._tooltip.show();
|
|
|
|
const [stageX, stageY] = this.get_transformed_position();
|
|
- const thumbWidth = this.allocation.get_width();
|
|
- const thumbHeight = this.allocation.get_height();
|
|
- const tipWidth = this._tooltip.width;
|
|
+ const [thumbWidth, thumbHeight] = this.allocation.get_size();
|
|
+ const [tipWidth, tipHeight] = this._tooltip.get_size();
|
|
const xOffset = Math.floor((thumbWidth - tipWidth) / 2);
|
|
const monitor = Main.layoutManager.findMonitorForActor(this);
|
|
const x = Math.min(
|
|
Math.max(stageX + xOffset, monitor.x),
|
|
monitor.x + monitor.width - tipWidth);
|
|
- const y = stageY + thumbHeight + TOOLTIP_OFFSET;
|
|
+ const y = stageY - monitor.y > thumbHeight + TOOLTIP_OFFSET
|
|
+ ? stageY - tipHeight - TOOLTIP_OFFSET // show above
|
|
+ : stageY + thumbHeight + TOOLTIP_OFFSET; // show below
|
|
this._tooltip.set_position(x, y);
|
|
}
|
|
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From a7d7412b8683e843db154c10fe9ffcd01b38d544 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 21 Feb 2024 17:37:16 +0100
|
|
Subject: [PATCH 16/43] workspace-indicator: Only change top bar redirect when
|
|
in top bar
|
|
|
|
While this is always the case for the workspace indicator, adding
|
|
the check will allow to use the same code in the window list.
|
|
---
|
|
.../workspace-indicator/workspaceIndicator.js | 23 +++++++++++++++++--
|
|
1 file changed, 21 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index b87420ac..b772b66d 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -307,6 +307,16 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
|
|
this.connect('scroll-event', this._onScrollEvent.bind(this));
|
|
this._thumbnailsBox.connect('scroll-event', this._onScrollEvent.bind(this));
|
|
+
|
|
+ this._inTopBar = false;
|
|
+ this.connect('notify::realized', () => {
|
|
+ if (!this.realized)
|
|
+ return;
|
|
+
|
|
+ this._inTopBar = Main.panel.contains(this);
|
|
+ this._updateTopBarRedirect();
|
|
+ });
|
|
+
|
|
this._updateMenu();
|
|
this._updateThumbnails();
|
|
this._onWorkspaceOrientationChanged();
|
|
@@ -326,7 +336,9 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._settingsChangedId = 0;
|
|
}
|
|
|
|
- Main.panel.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
|
|
+ if (this._inTopBar)
|
|
+ Main.panel.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
|
|
+ this._inTopBar = false;
|
|
|
|
super._onDestroy();
|
|
}
|
|
@@ -338,9 +350,16 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._statusLabel.visible = vertical;
|
|
this._thumbnailsBox.visible = !vertical;
|
|
|
|
+ this._updateTopBarRedirect();
|
|
+ }
|
|
+
|
|
+ _updateTopBarRedirect() {
|
|
+ if (!this._inTopBar)
|
|
+ return;
|
|
+
|
|
// Disable offscreen-redirect when showing the workspace switcher
|
|
// so that clip-to-allocation works
|
|
- Main.panel.set_offscreen_redirect(vertical
|
|
+ Main.panel.set_offscreen_redirect(this._thumbnailsBox.visible
|
|
? Clutter.OffscreenRedirect.ALWAYS
|
|
: Clutter.OffscreenRedirect.AUTOMATIC_FOR_OPACITY);
|
|
}
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From e654fa6be51139099f6eaa13f28130a3da0fd556 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 21 Feb 2024 16:13:00 +0100
|
|
Subject: [PATCH 17/43] workspace-indicator: Small cleanup
|
|
|
|
The code to update the menu labels is a bit cleaner in the
|
|
window-list extension, so use that.
|
|
---
|
|
.../workspace-indicator/workspaceIndicator.js | 22 +++++++++----------
|
|
1 file changed, 11 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index b772b66d..f707be79 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -416,18 +416,18 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._workspacesItems = [];
|
|
this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
|
|
|
- let i = 0;
|
|
- for (; i < workspaceManager.n_workspaces; i++) {
|
|
- this._workspacesItems[i] = new PopupMenu.PopupMenuItem(this._labelText(i));
|
|
- this.menu.addMenuItem(this._workspacesItems[i]);
|
|
- this._workspacesItems[i].workspaceId = i;
|
|
- this._workspacesItems[i].label_actor = this._statusLabel;
|
|
- this._workspacesItems[i].connect('activate', (actor, _event) => {
|
|
- this._activate(actor.workspaceId);
|
|
- });
|
|
+ for (let i = 0; i < workspaceManager.n_workspaces; i++) {
|
|
+ const item = new PopupMenu.PopupMenuItem(this._labelText(i));
|
|
|
|
- if (i == this._currentWorkspace)
|
|
- this._workspacesItems[i].setOrnament(PopupMenu.Ornament.DOT);
|
|
+ item.connect('activate',
|
|
+ () => this._activate(i));
|
|
+
|
|
+ item.setOrnament(i === this._currentWorkspace
|
|
+ ? PopupMenu.Ornament.DOT
|
|
+ : PopupMenu.Ornament.NONE);
|
|
+
|
|
+ this.menu.addMenuItem(item);
|
|
+ this._workspacesItems[i] = item;
|
|
}
|
|
|
|
this._statusLabel.set_text(this._labelText());
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 3db67516e6bc00f2b9c85aa59b28d9521028fbc9 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 21 Feb 2024 16:13:00 +0100
|
|
Subject: [PATCH 18/43] workspace-indicator: Simplify getting status text
|
|
|
|
Currently the same method is used to get the label text for the
|
|
indicator itself and for the menu items.
|
|
|
|
A method that behaves significantly different depending on whether
|
|
a parameter is passed is confusing, so only deal with the indicator
|
|
label and directly use the mutter API to get the workspace names
|
|
for menu items.
|
|
---
|
|
.../workspace-indicator/workspaceIndicator.js | 24 +++++++++----------
|
|
1 file changed, 12 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index f707be79..6783b315 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -281,7 +281,7 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._statusLabel = new St.Label({
|
|
style_class: 'status-label',
|
|
y_align: Clutter.ActorAlign.CENTER,
|
|
- text: this._labelText()
|
|
+ text: this._getStatusText(),
|
|
});
|
|
|
|
container.add_actor(this._statusLabel);
|
|
@@ -370,7 +370,7 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._updateMenuOrnament();
|
|
this._updateActiveThumbnail();
|
|
|
|
- this._statusLabel.set_text(this._labelText());
|
|
+ this._statusLabel.set_text(this._getStatusText());
|
|
}
|
|
|
|
_nWorkspacesChanged() {
|
|
@@ -396,17 +396,16 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
}
|
|
}
|
|
|
|
- _labelText(workspaceIndex) {
|
|
- if (workspaceIndex == undefined) {
|
|
- workspaceIndex = this._currentWorkspace;
|
|
- return (workspaceIndex + 1).toString();
|
|
- }
|
|
- return Meta.prefs_get_workspace_name(workspaceIndex);
|
|
+ _getStatusText() {
|
|
+ const current = this._currentWorkspace + 1;
|
|
+ return `${current}`;
|
|
}
|
|
|
|
_updateMenuLabels() {
|
|
- for (let i = 0; i < this._workspacesItems.length; i++)
|
|
- this._workspacesItems[i].label.text = this._labelText(i);
|
|
+ for (let i = 0; i < this._workspacesItems.length; i++) {
|
|
+ const item = this._workspacesItems[i];
|
|
+ item.label.text = Meta.prefs_get_workspace_name(i);
|
|
+ }
|
|
}
|
|
|
|
_updateMenu() {
|
|
@@ -417,7 +416,8 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
|
|
|
for (let i = 0; i < workspaceManager.n_workspaces; i++) {
|
|
- const item = new PopupMenu.PopupMenuItem(this._labelText(i));
|
|
+ const name = Meta.prefs_get_workspace_name(i);
|
|
+ const item = new PopupMenu.PopupMenuItem(name);
|
|
|
|
item.connect('activate',
|
|
() => this._activate(i));
|
|
@@ -430,7 +430,7 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._workspacesItems[i] = item;
|
|
}
|
|
|
|
- this._statusLabel.set_text(this._labelText());
|
|
+ this._statusLabel.set_text(this._getStatusText());
|
|
}
|
|
|
|
_updateThumbnails() {
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 6ae80e3c952f4fb2e557dbd4dc4ab304f9e82eae Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Thu, 22 Feb 2024 04:45:23 +0100
|
|
Subject: [PATCH 19/43] workspace-indicator: Tweak preview style
|
|
|
|
Sync sizes and padding with the window-list previews.
|
|
|
|
Tone down the colors a bit, but less then the current window-list
|
|
style where workspaces blend too much into the background and
|
|
the selection is unclear.
|
|
---
|
|
extensions/workspace-indicator/stylesheet.css | 19 ++++++++++---------
|
|
1 file changed, 10 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/stylesheet.css b/extensions/workspace-indicator/stylesheet.css
|
|
index 3f89359b..c8c2370f 100644
|
|
--- a/extensions/workspace-indicator/stylesheet.css
|
|
+++ b/extensions/workspace-indicator/stylesheet.css
|
|
@@ -3,24 +3,25 @@
|
|
}
|
|
|
|
.workspace-indicator .workspaces-box {
|
|
- padding: 4px 0;
|
|
- spacing: 4px;
|
|
+ padding: 5px;
|
|
+ spacing: 3px;
|
|
}
|
|
|
|
.workspace-indicator .workspace {
|
|
- width: 40px;
|
|
- border: 2px solid #000;
|
|
- border-radius: 2px;
|
|
- background-color: #595959;
|
|
+ width: 52px;
|
|
+ border: 2px solid transparent;
|
|
+ border-radius: 4px;
|
|
+ background-color: #3f3f3f;
|
|
}
|
|
|
|
.workspace-indicator .workspace.active {
|
|
- border-color: #fff;
|
|
+ border-color: #9f9f9f;
|
|
}
|
|
|
|
.workspace-indicator-window-preview {
|
|
- background-color: #252525;
|
|
- border: 1px solid #ccc;
|
|
+ background-color: #bebebe;
|
|
+ border: 1px solid #828282;
|
|
+ border-radius: 1px;
|
|
}
|
|
|
|
.workspace-indicator-window-preview {
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From a034be112b74ea09bfa53840ab3c85ce6593bd88 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 21 Feb 2024 23:22:58 +0100
|
|
Subject: [PATCH 20/43] workspace-indicator: Support light style
|
|
|
|
The window-list extension already includes light styling for
|
|
its copy of the workspace indicator. Just copy that over to
|
|
support the light variant here as well.
|
|
---
|
|
extensions/workspace-indicator/meson.build | 6 +++-
|
|
.../workspace-indicator/stylesheet-dark.css | 29 +++++++++++++++++
|
|
.../workspace-indicator/stylesheet-light.css | 25 +++++++++++++++
|
|
extensions/workspace-indicator/stylesheet.css | 31 +------------------
|
|
4 files changed, 60 insertions(+), 31 deletions(-)
|
|
create mode 100644 extensions/workspace-indicator/stylesheet-dark.css
|
|
create mode 100644 extensions/workspace-indicator/stylesheet-light.css
|
|
|
|
diff --git a/extensions/workspace-indicator/meson.build b/extensions/workspace-indicator/meson.build
|
|
index eb25b9cc..0bf9f023 100644
|
|
--- a/extensions/workspace-indicator/meson.build
|
|
+++ b/extensions/workspace-indicator/meson.build
|
|
@@ -3,6 +3,10 @@ extension_data += configure_file(
|
|
output: metadata_name,
|
|
configuration: metadata_conf
|
|
)
|
|
-extension_data += files('stylesheet.css')
|
|
+extension_data += files(
|
|
+ 'stylesheet.css',
|
|
+ 'stylesheet-dark.css',
|
|
+ 'stylesheet-light.css',
|
|
+)
|
|
|
|
extension_sources += files('prefs.js', 'workspaceIndicator.js')
|
|
diff --git a/extensions/workspace-indicator/stylesheet-dark.css b/extensions/workspace-indicator/stylesheet-dark.css
|
|
new file mode 100644
|
|
index 00000000..f74f7e88
|
|
--- /dev/null
|
|
+++ b/extensions/workspace-indicator/stylesheet-dark.css
|
|
@@ -0,0 +1,29 @@
|
|
+.workspace-indicator .status-label {
|
|
+ padding: 0 8px;
|
|
+}
|
|
+
|
|
+.workspace-indicator .workspaces-box {
|
|
+ padding: 5px;
|
|
+ spacing: 3px;
|
|
+}
|
|
+
|
|
+.workspace-indicator .workspace {
|
|
+ width: 52px;
|
|
+ border: 2px solid transparent;
|
|
+ border-radius: 4px;
|
|
+ background-color: #3f3f3f;
|
|
+}
|
|
+
|
|
+.workspace-indicator .workspace.active {
|
|
+ border-color: #9f9f9f;
|
|
+}
|
|
+
|
|
+.workspace-indicator-window-preview {
|
|
+ background-color: #bebebe;
|
|
+ border: 1px solid #828282;
|
|
+ border-radius: 1px;
|
|
+}
|
|
+
|
|
+.workspace-indicator-window-preview.active {
|
|
+ background-color: #d4d4d4;
|
|
+}
|
|
diff --git a/extensions/workspace-indicator/stylesheet-light.css b/extensions/workspace-indicator/stylesheet-light.css
|
|
new file mode 100644
|
|
index 00000000..049b6a38
|
|
--- /dev/null
|
|
+++ b/extensions/workspace-indicator/stylesheet-light.css
|
|
@@ -0,0 +1,25 @@
|
|
+/*
|
|
+ * SPDX-FileCopyrightText: 2013 Florian Müllner <fmuellner@gnome.org>
|
|
+ * SPDX-FileCopyrightText: 2015 Jakub Steiner <jimmac@gmail.com>
|
|
+ *
|
|
+ * SPDX-License-Identifier: GPL-2.0-or-later
|
|
+ */
|
|
+
|
|
+@import url("stylesheet-dark.css");
|
|
+
|
|
+.workspace-indicator .workspace {
|
|
+ background-color: #ccc;
|
|
+}
|
|
+
|
|
+.workspace-indicator .workspace.active {
|
|
+ border-color: #888;
|
|
+}
|
|
+
|
|
+.workspace-indicator-window-preview {
|
|
+ background-color: #ededed;
|
|
+ border: 1px solid #ccc;
|
|
+}
|
|
+
|
|
+.workspace-indicator-window-preview.active {
|
|
+ background-color: #f6f5f4;
|
|
+}
|
|
diff --git a/extensions/workspace-indicator/stylesheet.css b/extensions/workspace-indicator/stylesheet.css
|
|
index c8c2370f..b0f7d171 100644
|
|
--- a/extensions/workspace-indicator/stylesheet.css
|
|
+++ b/extensions/workspace-indicator/stylesheet.css
|
|
@@ -1,30 +1 @@
|
|
-.workspace-indicator .status-label {
|
|
- padding: 0 8px;
|
|
-}
|
|
-
|
|
-.workspace-indicator .workspaces-box {
|
|
- padding: 5px;
|
|
- spacing: 3px;
|
|
-}
|
|
-
|
|
-.workspace-indicator .workspace {
|
|
- width: 52px;
|
|
- border: 2px solid transparent;
|
|
- border-radius: 4px;
|
|
- background-color: #3f3f3f;
|
|
-}
|
|
-
|
|
-.workspace-indicator .workspace.active {
|
|
- border-color: #9f9f9f;
|
|
-}
|
|
-
|
|
-.workspace-indicator-window-preview {
|
|
- background-color: #bebebe;
|
|
- border: 1px solid #828282;
|
|
- border-radius: 1px;
|
|
-}
|
|
-
|
|
-.workspace-indicator-window-preview {
|
|
- background-color: #353535;
|
|
- border: 2px solid #ccc;
|
|
-}
|
|
+@import url("stylesheet-dark.css");
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 7bad2503adfbdcf5dfa67288fd7a5abcdd299fb0 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 21 Feb 2024 13:08:52 +0100
|
|
Subject: [PATCH 21/43] window-list: Use actual copy of workspace-indicator
|
|
|
|
We are now at a point where the code from the workspace-indicator
|
|
extension is usable from the window-list.
|
|
|
|
However instead of updating the copy, go one step further and
|
|
remove it altogether, and copy the required files at build time.
|
|
|
|
This ensures that future changes are picked up by both extensions
|
|
without duplicating any work.
|
|
---
|
|
extensions/window-list/classic.css | 20 +-
|
|
extensions/window-list/meson.build | 29 +-
|
|
extensions/window-list/stylesheet.css | 2 +
|
|
extensions/window-list/workspaceIndicator.js | 451 -------------------
|
|
4 files changed, 31 insertions(+), 471 deletions(-)
|
|
delete mode 100644 extensions/window-list/workspaceIndicator.js
|
|
|
|
diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css
|
|
index 02286041..d7ceb062 100644
|
|
--- a/extensions/window-list/classic.css
|
|
+++ b/extensions/window-list/classic.css
|
|
@@ -1,4 +1,5 @@
|
|
@import url("stylesheet.css");
|
|
+@import url("stylesheet-workspace-switcher-light.css");
|
|
|
|
#panel.bottom-panel {
|
|
border-top-width: 1px;
|
|
@@ -47,22 +48,3 @@
|
|
color: #888;
|
|
box-shadow: none;
|
|
}
|
|
-
|
|
-/* workspace switcher */
|
|
-.window-list-workspace-indicator .workspace {
|
|
- background-color: #ddd;
|
|
-}
|
|
-
|
|
-.window-list-workspace-indicator .workspace.active {
|
|
- background-color: #ccc;
|
|
-}
|
|
-
|
|
-.window-list-workspace-indicator-window-preview {
|
|
- background-color: #ededed;
|
|
- border: 1px solid #ccc;
|
|
-}
|
|
-
|
|
-.window-list-workspace-indicator-window-preview.active {
|
|
- background-color: #f6f5f4;
|
|
- border: 2px solid #888;
|
|
-}
|
|
diff --git a/extensions/window-list/meson.build b/extensions/window-list/meson.build
|
|
index 599f45e1..12d2b174 100644
|
|
--- a/extensions/window-list/meson.build
|
|
+++ b/extensions/window-list/meson.build
|
|
@@ -5,7 +5,34 @@ extension_data += configure_file(
|
|
)
|
|
extension_data += files('stylesheet.css')
|
|
|
|
-extension_sources += files('prefs.js', 'windowPicker.js', 'workspaceIndicator.js')
|
|
+transform_stylesheet = [
|
|
+ 'sed', '-E',
|
|
+ '-e', 's:^\.(workspace-indicator):.window-list-\\1:',
|
|
+ '-e', '/^@import/d',
|
|
+ '@INPUT@',
|
|
+ ]
|
|
+
|
|
+workspaceIndicatorSources = [
|
|
+ configure_file(
|
|
+ input: '../workspace-indicator/workspaceIndicator.js',
|
|
+ output: '@PLAINNAME@',
|
|
+ copy: true,
|
|
+ ),
|
|
+ configure_file(
|
|
+ input: '../workspace-indicator/stylesheet-dark.css',
|
|
+ output: 'stylesheet-workspace-switcher-dark.css',
|
|
+ command: transform_stylesheet,
|
|
+ capture: true,
|
|
+ ),
|
|
+ configure_file(
|
|
+ input: '../workspace-indicator/stylesheet-light.css',
|
|
+ output: 'stylesheet-workspace-switcher-light.css',
|
|
+ command: transform_stylesheet,
|
|
+ capture: true,
|
|
+ ),
|
|
+]
|
|
+
|
|
+extension_sources += files('prefs.js', 'windowPicker.js') + workspaceIndicatorSources
|
|
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')
|
|
|
|
if classic_mode_enabled
|
|
diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css
|
|
index 4c9ca671..2aa35922 100644
|
|
--- a/extensions/window-list/stylesheet.css
|
|
+++ b/extensions/window-list/stylesheet.css
|
|
@@ -1,3 +1,5 @@
|
|
+@import url("stylesheet-workspace-switcher-dark.css");
|
|
+
|
|
.bottom-panel {
|
|
/* .window-button-icon height +
|
|
.window-button vertical padding +
|
|
diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js
|
|
deleted file mode 100644
|
|
index 574ebdca..00000000
|
|
--- a/extensions/window-list/workspaceIndicator.js
|
|
+++ /dev/null
|
|
@@ -1,451 +0,0 @@
|
|
-/* exported WorkspaceIndicator */
|
|
-const { Clutter, Gio, GObject, Meta, St } = imports.gi;
|
|
-
|
|
-const DND = imports.ui.dnd;
|
|
-const Main = imports.ui.main;
|
|
-const PanelMenu = imports.ui.panelMenu;
|
|
-const PopupMenu = imports.ui.popupMenu;
|
|
-const Tweener = imports.ui.tweener;
|
|
-
|
|
-const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
|
-const _ = Gettext.gettext;
|
|
-
|
|
-const TOOLTIP_OFFSET = 6;
|
|
-const TOOLTIP_ANIMATION_TIME = 150;
|
|
-
|
|
-let baseStyleClassName = '';
|
|
-
|
|
-const TypePrefix = window.TypePrefix || '';
|
|
-
|
|
-let WindowPreview = GObject.registerClass({
|
|
- GTypeName: `${TypePrefix}WorkspaceIndicatorWindowPreview`
|
|
-}, class WindowPreview extends St.Button {
|
|
- _init(window) {
|
|
- super._init({
|
|
- style_class: `${baseStyleClassName}-window-preview`,
|
|
- });
|
|
-
|
|
- this._delegate = this;
|
|
- DND.makeDraggable(this, { restoreOnSuccess: true });
|
|
-
|
|
- this._window = window;
|
|
-
|
|
- this.connect('destroy', this._onDestroy.bind(this));
|
|
-
|
|
- this._sizeChangedId = this._window.connect('size-changed',
|
|
- this._relayout.bind(this));
|
|
- this._positionChangedId = this._window.connect('position-changed',
|
|
- this._relayout.bind(this));
|
|
- this._minimizedChangedId = this._window.connect('notify::minimized',
|
|
- this._relayout.bind(this));
|
|
- this._monitorEnteredId = global.display.connect('window-entered-monitor',
|
|
- this._relayout.bind(this));
|
|
- this._monitorLeftId = global.display.connect('window-left-monitor',
|
|
- this._relayout.bind(this));
|
|
-
|
|
- // Do initial layout when we get a parent
|
|
- let id = this.connect('parent-set', () => {
|
|
- this.disconnect(id);
|
|
- if (!this.get_parent())
|
|
- return;
|
|
- this._laterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
|
|
- this._laterId = 0;
|
|
- this._relayout();
|
|
- return false;
|
|
- });
|
|
- });
|
|
-
|
|
- this._focusChangedId = global.display.connect('notify::focus-window',
|
|
- this._onFocusChanged.bind(this));
|
|
- this._onFocusChanged();
|
|
- }
|
|
-
|
|
- // needed for DND
|
|
- get realWindow() {
|
|
- return this._window.get_compositor_private();
|
|
- }
|
|
-
|
|
- _onDestroy() {
|
|
- this._window.disconnect(this._sizeChangedId);
|
|
- this._window.disconnect(this._positionChangedId);
|
|
- this._window.disconnect(this._minimizedChangedId);
|
|
- global.display.disconnect(this._monitorEnteredId);
|
|
- global.display.disconnect(this._monitorLeftId);
|
|
- global.display.disconnect(this._focusChangedId);
|
|
- if (this._laterId)
|
|
- Meta.later_remove(this._laterId);
|
|
- }
|
|
-
|
|
- _onFocusChanged() {
|
|
- if (global.display.focus_window == this._window)
|
|
- this.add_style_class_name('active');
|
|
- else
|
|
- this.remove_style_class_name('active');
|
|
- }
|
|
-
|
|
- _relayout() {
|
|
- let monitor = Main.layoutManager.findIndexForActor(this);
|
|
- this.visible = monitor == this._window.get_monitor() &&
|
|
- this._window.showing_on_its_workspace();
|
|
-
|
|
- if (!this.visible)
|
|
- return;
|
|
-
|
|
- let workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
|
|
- let hscale = this.get_parent().allocation.get_width() / workArea.width;
|
|
- let vscale = this.get_parent().allocation.get_height() / workArea.height;
|
|
-
|
|
- let frameRect = this._window.get_frame_rect();
|
|
- this.set_size(
|
|
- Math.round(Math.min(frameRect.width, workArea.width) * hscale),
|
|
- Math.round(Math.min(frameRect.height, workArea.height) * vscale));
|
|
- this.set_position(
|
|
- Math.round(frameRect.x * hscale),
|
|
- Math.round(frameRect.y * vscale));
|
|
- }
|
|
-});
|
|
-
|
|
-let WorkspaceThumbnail = GObject.registerClass({
|
|
- GTypeName: `${TypePrefix}WorkspaceIndicatorWorkspaceThumbnail`
|
|
-}, class WorkspaceThumbnail extends St.Button {
|
|
- _init(index) {
|
|
- super._init({
|
|
- style_class: 'workspace',
|
|
- child: new Clutter.Actor({
|
|
- layout_manager: new Clutter.BinLayout(),
|
|
- clip_to_allocation: true
|
|
- }),
|
|
- x_fill: true,
|
|
- y_fill: true
|
|
- });
|
|
-
|
|
- this._tooltip = new St.Label({
|
|
- style_class: 'dash-label',
|
|
- visible: false,
|
|
- });
|
|
- Main.uiGroup.add_child(this._tooltip);
|
|
-
|
|
- this.connect('destroy', this._onDestroy.bind(this));
|
|
- this.connect('notify::hover', this._syncTooltip.bind(this));
|
|
-
|
|
- this._index = index;
|
|
- this._delegate = this; // needed for DND
|
|
-
|
|
- this._windowPreviews = new Map();
|
|
-
|
|
- 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.list_windows().forEach(w => this._addWindow(w));
|
|
- this._onRestacked();
|
|
- }
|
|
-
|
|
- acceptDrop(source) {
|
|
- if (!source.realWindow)
|
|
- return false;
|
|
-
|
|
- let window = source.realWindow.get_meta_window();
|
|
- this._moveWindow(window);
|
|
- return true;
|
|
- }
|
|
-
|
|
- handleDragOver(source) {
|
|
- if (source.realWindow)
|
|
- return DND.DragMotionResult.MOVE_DROP;
|
|
- else
|
|
- return DND.DragMotionResult.CONTINUE;
|
|
- }
|
|
-
|
|
- _addWindow(window) {
|
|
- if (this._windowPreviews.has(window))
|
|
- return;
|
|
-
|
|
- let preview = new WindowPreview(window);
|
|
- preview.connect('clicked', (a, btn) => this.emit('clicked', btn));
|
|
- this._windowPreviews.set(window, preview);
|
|
- this.child.add_child(preview);
|
|
- }
|
|
-
|
|
- _removeWindow(window) {
|
|
- let preview = this._windowPreviews.get(window);
|
|
- if (!preview)
|
|
- return;
|
|
-
|
|
- this._windowPreviews.delete(window);
|
|
- preview.destroy();
|
|
- }
|
|
-
|
|
- _onRestacked() {
|
|
- let lastPreview = null;
|
|
- let windows = global.get_window_actors().map(a => a.meta_window);
|
|
- for (let i = 0; i < windows.length; i++) {
|
|
- let preview = this._windowPreviews.get(windows[i]);
|
|
- if (!preview)
|
|
- continue;
|
|
-
|
|
- this.child.set_child_above_sibling(preview, lastPreview);
|
|
- lastPreview = preview;
|
|
- }
|
|
- }
|
|
-
|
|
- _moveWindow(window) {
|
|
- let monitorIndex = Main.layoutManager.findIndexForActor(this);
|
|
- if (monitorIndex != window.get_monitor())
|
|
- window.move_to_monitor(monitorIndex);
|
|
- window.change_workspace_by_index(this._index, false);
|
|
- }
|
|
-
|
|
- // eslint-disable-next-line camelcase
|
|
- on_clicked() {
|
|
- let ws = global.workspace_manager.get_workspace_by_index(this._index);
|
|
- if (ws)
|
|
- ws.activate(global.get_current_time());
|
|
- }
|
|
-
|
|
- _syncTooltip() {
|
|
- if (this.hover) {
|
|
- this._tooltip.text = Meta.prefs_get_workspace_name(this._index);
|
|
- this._tooltip.opacity = 0;
|
|
- this._tooltip.show();
|
|
-
|
|
- const [stageX, stageY] = this.get_transformed_position();
|
|
- const thumbWidth = this.allocation.get_width();
|
|
- const tipWidth = this._tooltip.width;
|
|
- const tipHeight = this._tooltip.height;
|
|
- const xOffset = Math.floor((thumbWidth - tipWidth) / 2);
|
|
- const monitor = Main.layoutManager.findMonitorForActor(this);
|
|
- const x = Math.min(
|
|
- Math.max(stageX + xOffset, monitor.x),
|
|
- monitor.x + monitor.width - tipWidth);
|
|
- const y = stageY - tipHeight - TOOLTIP_OFFSET;
|
|
- this._tooltip.set_position(x, y);
|
|
- }
|
|
-
|
|
- Tweener.addTween(this._tooltip, {
|
|
- opacity: this.hover ? 255 : 0,
|
|
- time: TOOLTIP_ANIMATION_TIME / 1000,
|
|
- transition: 'easeOutQuad',
|
|
- onComplete: () => (this._tooltip.visible = this.hover),
|
|
- });
|
|
- }
|
|
-
|
|
- _onDestroy() {
|
|
- this._tooltip.destroy();
|
|
-
|
|
- this._workspace.disconnect(this._windowAddedId);
|
|
- this._workspace.disconnect(this._windowRemovedId);
|
|
- global.display.disconnect(this._restackedId);
|
|
- }
|
|
-});
|
|
-
|
|
-var WorkspaceIndicator = GObject.registerClass({
|
|
- GTypeName: `${TypePrefix}WorkspaceIndicator`
|
|
-}, class WorkspaceIndicator extends PanelMenu.Button {
|
|
- _init(params = {}) {
|
|
- super._init(0.0, _('Workspace Indicator'));
|
|
-
|
|
- const {
|
|
- baseStyleClass = 'workspace-indicator',
|
|
- } = params;
|
|
-
|
|
- baseStyleClassName = baseStyleClass;
|
|
- this.add_style_class_name(baseStyleClassName);
|
|
-
|
|
- let container = new St.Widget({
|
|
- layout_manager: new Clutter.BinLayout(),
|
|
- x_expand: true,
|
|
- y_expand: true
|
|
- });
|
|
- this.add_actor(container);
|
|
-
|
|
- let workspaceManager = global.workspace_manager;
|
|
-
|
|
- this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
|
- this._statusLabel = new St.Label({ text: this._getStatusText() });
|
|
-
|
|
- this._statusBin = new St.Bin({
|
|
- style_class: 'status-label-bin',
|
|
- x_expand: true,
|
|
- y_expand: true,
|
|
- child: this._statusLabel
|
|
- });
|
|
- container.add_actor(this._statusBin);
|
|
-
|
|
- this._thumbnailsBox = new St.BoxLayout({
|
|
- style_class: 'workspaces-box',
|
|
- y_expand: true,
|
|
- reactive: true
|
|
- });
|
|
- this._thumbnailsBox.connect('scroll-event',
|
|
- this._onScrollEvent.bind(this));
|
|
- container.add_actor(this._thumbnailsBox);
|
|
-
|
|
- 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._onWorkspaceOrientationChanged.bind(this))
|
|
- ];
|
|
-
|
|
- this.connect('scroll-event', this._onScrollEvent.bind(this));
|
|
- this._updateMenu();
|
|
- this._updateThumbnails();
|
|
- this._onWorkspaceOrientationChanged();
|
|
-
|
|
- 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();
|
|
- }
|
|
-
|
|
- _onWorkspaceOrientationChanged() {
|
|
- let vertical = global.workspace_manager.layout_rows == -1;
|
|
- this.reactive = vertical;
|
|
-
|
|
- this._statusBin.visible = vertical;
|
|
- this._thumbnailsBox.visible = !vertical;
|
|
- }
|
|
-
|
|
- _onWorkspaceSwitched() {
|
|
- let workspaceManager = global.workspace_manager;
|
|
- this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
|
-
|
|
- this._updateMenuOrnament();
|
|
- this._updateActiveThumbnail();
|
|
-
|
|
- this._statusLabel.set_text(this._getStatusText());
|
|
- }
|
|
-
|
|
- _nWorkspacesChanged() {
|
|
- this._updateMenu();
|
|
- this._updateThumbnails();
|
|
- }
|
|
-
|
|
- _updateMenuOrnament() {
|
|
- for (let i = 0; i < this._workspacesItems.length; i++) {
|
|
- this._workspacesItems[i].setOrnament(i == this._currentWorkspace
|
|
- ? PopupMenu.Ornament.DOT
|
|
- : PopupMenu.Ornament.NONE);
|
|
- }
|
|
- }
|
|
-
|
|
- _updateActiveThumbnail() {
|
|
- let thumbs = this._thumbnailsBox.get_children();
|
|
- for (let i = 0; i < thumbs.length; i++) {
|
|
- if (i == this._currentWorkspace)
|
|
- thumbs[i].add_style_class_name('active');
|
|
- else
|
|
- thumbs[i].remove_style_class_name('active');
|
|
- }
|
|
- }
|
|
-
|
|
- _getStatusText() {
|
|
- let workspaceManager = global.workspace_manager;
|
|
- let current = workspaceManager.get_active_workspace_index();
|
|
- let total = workspaceManager.n_workspaces;
|
|
-
|
|
- return '%d / %d'.format(current + 1, total);
|
|
- }
|
|
-
|
|
- _updateMenuLabels() {
|
|
- for (let i = 0; i < this._workspacesItems.length; i++) {
|
|
- let item = this._workspacesItems[i];
|
|
- let name = Meta.prefs_get_workspace_name(i);
|
|
- item.label.text = name;
|
|
- }
|
|
- }
|
|
-
|
|
- _updateMenu() {
|
|
- let workspaceManager = global.workspace_manager;
|
|
-
|
|
- this.menu.removeAll();
|
|
- this._workspacesItems = [];
|
|
- this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
|
-
|
|
- for (let i = 0; i < workspaceManager.n_workspaces; i++) {
|
|
- let name = Meta.prefs_get_workspace_name(i);
|
|
- let item = new PopupMenu.PopupMenuItem(name);
|
|
- item.workspaceId = i;
|
|
-
|
|
- item.connect('activate', (item, _event) => {
|
|
- this._activate(item.workspaceId);
|
|
- });
|
|
-
|
|
- if (i == this._currentWorkspace)
|
|
- item.setOrnament(PopupMenu.Ornament.DOT);
|
|
-
|
|
- this.menu.addMenuItem(item);
|
|
- this._workspacesItems[i] = item;
|
|
- }
|
|
-
|
|
- this._statusLabel.set_text(this._getStatusText());
|
|
- }
|
|
-
|
|
- _updateThumbnails() {
|
|
- let workspaceManager = global.workspace_manager;
|
|
-
|
|
- this._thumbnailsBox.destroy_all_children();
|
|
-
|
|
- for (let i = 0; i < workspaceManager.n_workspaces; i++) {
|
|
- let thumb = new WorkspaceThumbnail(i);
|
|
- this._thumbnailsBox.add_actor(thumb);
|
|
- }
|
|
- this._updateActiveThumbnail();
|
|
- }
|
|
-
|
|
- _activate(index) {
|
|
- let workspaceManager = global.workspace_manager;
|
|
-
|
|
- if (index >= 0 && index < workspaceManager.n_workspaces) {
|
|
- let metaWorkspace = workspaceManager.get_workspace_by_index(index);
|
|
- metaWorkspace.activate(global.get_current_time());
|
|
- }
|
|
- }
|
|
-
|
|
- _onScrollEvent(actor, event) {
|
|
- let direction = event.get_scroll_direction();
|
|
- let diff = 0;
|
|
- if (direction == Clutter.ScrollDirection.DOWN) {
|
|
- diff = 1;
|
|
- } else if (direction == Clutter.ScrollDirection.UP) {
|
|
- diff = -1;
|
|
- } else {
|
|
- return;
|
|
- }
|
|
-
|
|
- let newIndex = this._currentWorkspace + diff;
|
|
- this._activate(newIndex);
|
|
- }
|
|
-
|
|
- _allocate(actor, box, flags) {
|
|
- if (actor.get_n_children() > 0)
|
|
- actor.get_first_child().allocate(box, flags);
|
|
- }
|
|
-});
|
|
-
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 08c0fab926838cb4f3dcf5c3b1b9356c0f0e9f57 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Tue, 20 Feb 2024 17:27:57 +0100
|
|
Subject: [PATCH 22/43] workspace-indicator: Split out WorkspacePreviews
|
|
|
|
The previews will become a bit more complex soon, so spit them out
|
|
into a dedicated class.
|
|
---
|
|
.../workspace-indicator/workspaceIndicator.js | 139 +++++++++++-------
|
|
1 file changed, 88 insertions(+), 51 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 6783b315..0a5e7b26 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -255,6 +255,88 @@ let WorkspaceThumbnail = GObject.registerClass({
|
|
}
|
|
});
|
|
|
|
+const WorkspacePreviews = GObject.registerClass({
|
|
+ GTypeName: `${TypePrefix}WorkspaceIndicatorWorkspacePreviews`
|
|
+}, class WorkspacePreviews extends Clutter.Actor {
|
|
+ _init() {
|
|
+ super._init({
|
|
+ layout_manager: new Clutter.BinLayout(),
|
|
+ reactive: true,
|
|
+ y_expand: true,
|
|
+ });
|
|
+
|
|
+ this.connect('scroll-event',
|
|
+ (a, event) => this.handleScrollEvent(event));
|
|
+ this.connect('destroy', () => this._onDestroy());
|
|
+
|
|
+ const {workspaceManager} = global;
|
|
+
|
|
+ this._workspaceManagerSignals = [
|
|
+ workspaceManager.connect_after('notify::n-workspaces',
|
|
+ () => this._updateThumbnails()),
|
|
+ workspaceManager.connect_after('workspace-switched',
|
|
+ () => this._updateActiveThumbnail()),
|
|
+ ];
|
|
+
|
|
+ this._thumbnailsBox = new St.BoxLayout({
|
|
+ style_class: 'workspaces-box',
|
|
+ y_expand: true,
|
|
+ });
|
|
+ this.add_child(this._thumbnailsBox);
|
|
+
|
|
+ this._updateThumbnails();
|
|
+ }
|
|
+
|
|
+ handleScrollEvent(event) {
|
|
+ const direction = event.get_scroll_direction();
|
|
+ let diff = 0;
|
|
+ if (direction == Clutter.ScrollDirection.DOWN)
|
|
+ diff = 1;
|
|
+ else if (direction == Clutter.ScrollDirection.UP)
|
|
+ diff = -1;
|
|
+ else
|
|
+ return;
|
|
+
|
|
+ const {workspaceManager} = global;
|
|
+ const currentIndex = workspaceManager.get_active_workspace_index();
|
|
+ const newIndex = currentIndex + diff;
|
|
+ const workspace = workspaceManager.get_workspace_by_index(newIndex);
|
|
+ if (workspace)
|
|
+ workspace.activate(global.get_current_time());
|
|
+ }
|
|
+
|
|
+ _updateThumbnails() {
|
|
+ const {nWorkspaces} = global.workspace_manager;
|
|
+
|
|
+ this._thumbnailsBox.destroy_all_children();
|
|
+
|
|
+ for (let i = 0; i < nWorkspaces; i++) {
|
|
+ const thumb = new WorkspaceThumbnail(i);
|
|
+ this._thumbnailsBox.add_child(thumb);
|
|
+ }
|
|
+ this._updateActiveThumbnail();
|
|
+ }
|
|
+
|
|
+ _updateActiveThumbnail() {
|
|
+ const {workspaceManager} = global;
|
|
+ const activeIndex = workspaceManager.get_active_workspace_index();
|
|
+ let thumbs = this._thumbnailsBox.get_children();
|
|
+ for (let i = 0; i < thumbs.length; i++) {
|
|
+ if (i == activeIndex)
|
|
+ thumbs[i].add_style_class_name('active');
|
|
+ else
|
|
+ thumbs[i].remove_style_class_name('active');
|
|
+ }
|
|
+ }
|
|
+
|
|
+ _onDestroy() {
|
|
+ global.workspace_manager.disconnect(this._nWorkspacesChanged);
|
|
+ for (let i = 0; i < this._workspaceManagerSignals.length; i++)
|
|
+ global.workspace_manager.disconnect(this._workspaceManagerSignals[i]);
|
|
+ this._workspaceManagerSignals = [];
|
|
+ }
|
|
+});
|
|
+
|
|
let WorkspaceIndicator = GObject.registerClass({
|
|
GTypeName: `${TypePrefix}WorkspaceIndicator`
|
|
}, class WorkspaceIndicator extends PanelMenu.Button {
|
|
@@ -286,13 +368,8 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
|
|
container.add_actor(this._statusLabel);
|
|
|
|
- this._thumbnailsBox = new St.BoxLayout({
|
|
- style_class: 'workspaces-box',
|
|
- y_expand: true,
|
|
- reactive: true
|
|
- });
|
|
-
|
|
- container.add_actor(this._thumbnailsBox);
|
|
+ this._thumbnails = new WorkspacePreviews();
|
|
+ container.add_child(this._thumbnails);
|
|
|
|
this._workspacesItems = [];
|
|
|
|
@@ -305,8 +382,8 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._onWorkspaceOrientationChanged.bind(this))
|
|
];
|
|
|
|
- this.connect('scroll-event', this._onScrollEvent.bind(this));
|
|
- this._thumbnailsBox.connect('scroll-event', this._onScrollEvent.bind(this));
|
|
+ this.connect('scroll-event',
|
|
+ (o, event) => this._thumbnails.handleScrollEvent(event));
|
|
|
|
this._inTopBar = false;
|
|
this.connect('notify::realized', () => {
|
|
@@ -318,7 +395,6 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
});
|
|
|
|
this._updateMenu();
|
|
- this._updateThumbnails();
|
|
this._onWorkspaceOrientationChanged();
|
|
|
|
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' });
|
|
@@ -348,7 +424,7 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this.reactive = vertical;
|
|
|
|
this._statusLabel.visible = vertical;
|
|
- this._thumbnailsBox.visible = !vertical;
|
|
+ this._thumbnails.visible = !vertical;
|
|
|
|
this._updateTopBarRedirect();
|
|
}
|
|
@@ -359,7 +435,7 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
|
|
// Disable offscreen-redirect when showing the workspace switcher
|
|
// so that clip-to-allocation works
|
|
- Main.panel.set_offscreen_redirect(this._thumbnailsBox.visible
|
|
+ Main.panel.set_offscreen_redirect(this._thumbnails.visible
|
|
? Clutter.OffscreenRedirect.ALWAYS
|
|
: Clutter.OffscreenRedirect.AUTOMATIC_FOR_OPACITY);
|
|
}
|
|
@@ -368,14 +444,12 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._currentWorkspace = global.workspace_manager.get_active_workspace_index();
|
|
|
|
this._updateMenuOrnament();
|
|
- this._updateActiveThumbnail();
|
|
|
|
this._statusLabel.set_text(this._getStatusText());
|
|
}
|
|
|
|
_nWorkspacesChanged() {
|
|
this._updateMenu();
|
|
- this._updateThumbnails();
|
|
}
|
|
|
|
_updateMenuOrnament() {
|
|
@@ -386,16 +460,6 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
}
|
|
}
|
|
|
|
- _updateActiveThumbnail() {
|
|
- let thumbs = this._thumbnailsBox.get_children();
|
|
- for (let i = 0; i < thumbs.length; i++) {
|
|
- if (i == this._currentWorkspace)
|
|
- thumbs[i].add_style_class_name('active');
|
|
- else
|
|
- thumbs[i].remove_style_class_name('active');
|
|
- }
|
|
- }
|
|
-
|
|
_getStatusText() {
|
|
const current = this._currentWorkspace + 1;
|
|
return `${current}`;
|
|
@@ -433,18 +497,6 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._statusLabel.set_text(this._getStatusText());
|
|
}
|
|
|
|
- _updateThumbnails() {
|
|
- let workspaceManager = global.workspace_manager;
|
|
-
|
|
- this._thumbnailsBox.destroy_all_children();
|
|
-
|
|
- for (let i = 0; i < workspaceManager.n_workspaces; i++) {
|
|
- let thumb = new WorkspaceThumbnail(i);
|
|
- this._thumbnailsBox.add_actor(thumb);
|
|
- }
|
|
- this._updateActiveThumbnail();
|
|
- }
|
|
-
|
|
_activate(index) {
|
|
let workspaceManager = global.workspace_manager;
|
|
|
|
@@ -453,19 +505,4 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
metaWorkspace.activate(global.get_current_time());
|
|
}
|
|
}
|
|
-
|
|
- _onScrollEvent(actor, event) {
|
|
- let direction = event.get_scroll_direction();
|
|
- let diff = 0;
|
|
- if (direction == Clutter.ScrollDirection.DOWN) {
|
|
- diff = 1;
|
|
- } else if (direction == Clutter.ScrollDirection.UP) {
|
|
- diff = -1;
|
|
- } else {
|
|
- return;
|
|
- }
|
|
-
|
|
- const newIndex = this._currentWorkspace + diff;
|
|
- this._activate(newIndex);
|
|
- }
|
|
});
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 6e8c0b128350d4d8555e2f4750bd551654596917 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Mon, 19 Feb 2024 14:42:04 +0100
|
|
Subject: [PATCH 23/43] workspace-indicator: Handle preview overflow
|
|
|
|
We currently avoid previews from overflowing in most setups by
|
|
artificially limiting them to a maximum of six workspaces.
|
|
|
|
Add some proper handling to also cover cases where space is more
|
|
limited, and to allow removing the restriction in the future.
|
|
|
|
For that, wrap the previews in an auto-scrolling scroll view
|
|
and add overflow indicators on each side.
|
|
---
|
|
.../workspace-indicator/stylesheet-dark.css | 4 ++
|
|
.../workspace-indicator/workspaceIndicator.js | 68 ++++++++++++++++++-
|
|
2 files changed, 71 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/stylesheet-dark.css b/extensions/workspace-indicator/stylesheet-dark.css
|
|
index f74f7e88..61d1e982 100644
|
|
--- a/extensions/workspace-indicator/stylesheet-dark.css
|
|
+++ b/extensions/workspace-indicator/stylesheet-dark.css
|
|
@@ -2,6 +2,10 @@
|
|
padding: 0 8px;
|
|
}
|
|
|
|
+.workspace-indicator .workspaces-view.hfade {
|
|
+ -st-hfade-offset: 20px;
|
|
+}
|
|
+
|
|
.workspace-indicator .workspaces-box {
|
|
padding: 5px;
|
|
spacing: 3px;
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 0a5e7b26..1e3db810 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -12,6 +12,8 @@ const _ = Gettext.gettext;
|
|
const TOOLTIP_OFFSET = 6;
|
|
const TOOLTIP_ANIMATION_TIME = 150;
|
|
|
|
+const SCROLL_TIME = 100;
|
|
+
|
|
let baseStyleClassName = '';
|
|
|
|
const TypePrefix = window.TypePrefix || '';
|
|
@@ -276,13 +278,30 @@ const WorkspacePreviews = GObject.registerClass({
|
|
() => this._updateThumbnails()),
|
|
workspaceManager.connect_after('workspace-switched',
|
|
() => this._updateActiveThumbnail()),
|
|
+ workspaceManager.connect('workspace-switched',
|
|
+ () => this._updateScrollPosition()),
|
|
];
|
|
|
|
+ this.connect('notify::mapped', () => {
|
|
+ if (this.mapped)
|
|
+ this._updateScrollPosition();
|
|
+ });
|
|
+
|
|
this._thumbnailsBox = new St.BoxLayout({
|
|
style_class: 'workspaces-box',
|
|
y_expand: true,
|
|
});
|
|
- this.add_child(this._thumbnailsBox);
|
|
+
|
|
+ this._scrollView = new St.ScrollView({
|
|
+ style_class: 'workspaces-view hfade',
|
|
+ enable_mouse_scrolling: false,
|
|
+ hscrollbar_policy: St.PolicyType.EXTERNAL,
|
|
+ vscrollbar_policy: St.PolicyType.NEVER,
|
|
+ y_expand: true,
|
|
+ });
|
|
+ this._scrollView.add_actor(this._thumbnailsBox);
|
|
+
|
|
+ this.add_child(this._scrollView);
|
|
|
|
this._updateThumbnails();
|
|
}
|
|
@@ -315,6 +334,9 @@ const WorkspacePreviews = GObject.registerClass({
|
|
this._thumbnailsBox.add_child(thumb);
|
|
}
|
|
this._updateActiveThumbnail();
|
|
+
|
|
+ if (this.mapped)
|
|
+ this._updateScrollPosition();
|
|
}
|
|
|
|
_updateActiveThumbnail() {
|
|
@@ -329,6 +351,50 @@ const WorkspacePreviews = GObject.registerClass({
|
|
}
|
|
}
|
|
|
|
+ _updateScrollPosition() {
|
|
+ const adjustment = this._scrollView.hscroll.adjustment;
|
|
+ const {upper, pageSize} = adjustment;
|
|
+ let {value} = adjustment;
|
|
+
|
|
+ const {workspaceManager} = global;
|
|
+ const activeIndex = workspaceManager.get_active_workspace_index();
|
|
+ const activeWorkspace =
|
|
+ this._thumbnailsBox.get_child_at_index(activeIndex);
|
|
+
|
|
+ if (!activeWorkspace)
|
|
+ return;
|
|
+
|
|
+ let offset = 0;
|
|
+ const hfade = this._scrollView.get_effect('fade');
|
|
+ if (hfade)
|
|
+ offset = this._scrollView.get_theme_node().get_length('-st-hfade-offset');
|
|
+
|
|
+ let {x1, x2} = activeWorkspace.get_allocation_box();
|
|
+ let parent = activeWorkspace.get_parent();
|
|
+ while (parent !== this._scrollView) {
|
|
+ if (!parent)
|
|
+ throw new Error('actor not in scroll view');
|
|
+
|
|
+ const box = parent.get_allocation_box();
|
|
+ x1 += box.x1;
|
|
+ x2 += box.x1;
|
|
+ parent = parent.get_parent();
|
|
+ }
|
|
+
|
|
+ if (x1 < value + offset)
|
|
+ value = Math.max(0, x1 - offset);
|
|
+ else if (x2 > value + pageSize - offset)
|
|
+ value = Math.min(upper, x2 + offset - pageSize);
|
|
+ else
|
|
+ return;
|
|
+
|
|
+ Tweener.addTween(adjustment, {
|
|
+ value,
|
|
+ time: SCROLL_TIME / 1000,
|
|
+ transition: 'easeOutQuad',
|
|
+ });
|
|
+ }
|
|
+
|
|
_onDestroy() {
|
|
global.workspace_manager.disconnect(this._nWorkspacesChanged);
|
|
for (let i = 0; i < this._workspaceManagerSignals.length; i++)
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 355a224ca85344c876784bcebc119f6dbf657693 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Tue, 20 Feb 2024 22:00:57 +0100
|
|
Subject: [PATCH 24/43] workspace-indicator: Make previews configurable
|
|
|
|
Now that previews scroll when there are too many workspaces,
|
|
there is no longer a reason for the 6-workspace limit.
|
|
|
|
However some users do prefer the menu, so rather than drop it,
|
|
turn it into a proper preference.
|
|
|
|
Closes
|
|
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/336
|
|
---
|
|
....shell.extensions.classic.gschema.override | 3 ++
|
|
extensions/window-list/extension.js | 1 +
|
|
...e.shell.extensions.window-list.gschema.xml | 4 ++
|
|
extensions/workspace-indicator/extension.js | 4 +-
|
|
extensions/workspace-indicator/meson.build | 1 +
|
|
extensions/workspace-indicator/prefs.js | 43 ++++++++++++++++++-
|
|
...extensions.workspace-indicator.gschema.xml | 15 +++++++
|
|
.../workspace-indicator/workspaceIndicator.js | 20 +++++----
|
|
po/POTFILES.in | 1 +
|
|
9 files changed, 82 insertions(+), 10 deletions(-)
|
|
create mode 100644 extensions/workspace-indicator/schemas/org.gnome.shell.extensions.workspace-indicator.gschema.xml
|
|
|
|
diff --git a/data/00_org.gnome.shell.extensions.classic.gschema.override b/data/00_org.gnome.shell.extensions.classic.gschema.override
|
|
index c6701074..04155bfe 100644
|
|
--- a/data/00_org.gnome.shell.extensions.classic.gschema.override
|
|
+++ b/data/00_org.gnome.shell.extensions.classic.gschema.override
|
|
@@ -7,3 +7,6 @@ button-layout='appmenu:minimize,maximize,close'
|
|
[org.gnome.desktop.wm.keybindings:GNOME-Classic]
|
|
switch-applications=[]
|
|
switch-windows=['<Super>Tab','<Alt>Tab']
|
|
+
|
|
+[org.gnome.shell.extensions.window-list:GNOME-Classic]
|
|
+embed-previews=true
|
|
diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js
|
|
index aada9525..b2357939 100644
|
|
--- a/extensions/window-list/extension.js
|
|
+++ b/extensions/window-list/extension.js
|
|
@@ -818,6 +818,7 @@ class WindowList {
|
|
|
|
this._workspaceIndicator = new BottomWorkspaceIndicator({
|
|
baseStyleClass: 'window-list-workspace-indicator',
|
|
+ settings: ExtensionUtils.getSettings(),
|
|
});
|
|
indicatorsBox.add(this._workspaceIndicator.container, { expand: false, y_fill: true });
|
|
|
|
diff --git a/extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml b/extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml
|
|
index b7459417..a9174494 100644
|
|
--- a/extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml
|
|
+++ b/extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml
|
|
@@ -23,5 +23,9 @@
|
|
only on the primary one.
|
|
</description>
|
|
</key>
|
|
+ <key name="embed-previews" type="b">
|
|
+ <default>false</default>
|
|
+ <summary>Show workspace previews in window list</summary>
|
|
+ </key>
|
|
</schema>
|
|
</schemalist>
|
|
diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js
|
|
index 6f7d07c5..ec991993 100644
|
|
--- a/extensions/workspace-indicator/extension.js
|
|
+++ b/extensions/workspace-indicator/extension.js
|
|
@@ -14,7 +14,9 @@ function init() {
|
|
let _indicator;
|
|
|
|
function enable() {
|
|
- _indicator = new WorkspaceIndicator;
|
|
+ _indicator = new WorkspaceIndicator({
|
|
+ settings: ExtensionUtils.getSettings(),
|
|
+ });
|
|
Main.panel.addToStatusArea('workspace-indicator', _indicator);
|
|
}
|
|
|
|
diff --git a/extensions/workspace-indicator/meson.build b/extensions/workspace-indicator/meson.build
|
|
index 0bf9f023..a88db78a 100644
|
|
--- a/extensions/workspace-indicator/meson.build
|
|
+++ b/extensions/workspace-indicator/meson.build
|
|
@@ -8,5 +8,6 @@ extension_data += files(
|
|
'stylesheet-dark.css',
|
|
'stylesheet-light.css',
|
|
)
|
|
+extension_schemas += files('schemas/' + metadata_conf.get('gschemaname') + '.gschema.xml')
|
|
|
|
extension_sources += files('prefs.js', 'workspaceIndicator.js')
|
|
diff --git a/extensions/workspace-indicator/prefs.js b/extensions/workspace-indicator/prefs.js
|
|
index d8640559..d787f481 100644
|
|
--- a/extensions/workspace-indicator/prefs.js
|
|
+++ b/extensions/workspace-indicator/prefs.js
|
|
@@ -12,6 +12,34 @@ const ExtensionUtils = imports.misc.extensionUtils;
|
|
const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
|
|
const WORKSPACE_KEY = 'workspace-names';
|
|
|
|
+const GeneralGroup = GObject.registerClass(
|
|
+class GeneralGroup extends Gtk.Box {
|
|
+ _init() {
|
|
+ super._init({
|
|
+ orientation: Gtk.Orientation.VERTICAL,
|
|
+ });
|
|
+
|
|
+ const row = new Gtk.Box();
|
|
+ this.add(row);
|
|
+
|
|
+ row.add(new Gtk.Label({
|
|
+ label: _('Show Previews In Top Bar'),
|
|
+ }));
|
|
+
|
|
+ const sw = new Gtk.Switch({
|
|
+ hexpand: true,
|
|
+ halign: Gtk.Align.END,
|
|
+ });
|
|
+ row.add(sw);
|
|
+
|
|
+ const settings = ExtensionUtils.getSettings();
|
|
+
|
|
+ settings.bind('embed-previews',
|
|
+ sw, 'active',
|
|
+ Gio.SettingsBindFlags.DEFAULT);
|
|
+ }
|
|
+});
|
|
+
|
|
const WorkspaceNameModel = GObject.registerClass(
|
|
class WorkspaceNameModel extends Gtk.ListStore {
|
|
_init(params) {
|
|
@@ -127,7 +155,20 @@ class WorkspaceSettingsWidget extends Gtk.Grid {
|
|
this.margin = 12;
|
|
this.orientation = Gtk.Orientation.VERTICAL;
|
|
|
|
- this.add(new Gtk.Label({
|
|
+ const box = new Gtk.Box({
|
|
+ orientation: Gtk.Orientation.VERTICAL,
|
|
+ halign: Gtk.Align.CENTER,
|
|
+ spacing: 12,
|
|
+ margin_top: 36,
|
|
+ margin_bottom: 36,
|
|
+ margin_start: 36,
|
|
+ margin_end: 36,
|
|
+ });
|
|
+ this.add(box);
|
|
+
|
|
+ box.add(new GeneralGroup());
|
|
+
|
|
+ box.add(new Gtk.Label({
|
|
label: '<b>%s</b>'.format(_('Workspace Names')),
|
|
use_markup: true,
|
|
margin_bottom: 6,
|
|
diff --git a/extensions/workspace-indicator/schemas/org.gnome.shell.extensions.workspace-indicator.gschema.xml b/extensions/workspace-indicator/schemas/org.gnome.shell.extensions.workspace-indicator.gschema.xml
|
|
new file mode 100644
|
|
index 00000000..e5059849
|
|
--- /dev/null
|
|
+++ b/extensions/workspace-indicator/schemas/org.gnome.shell.extensions.workspace-indicator.gschema.xml
|
|
@@ -0,0 +1,15 @@
|
|
+<!--
|
|
+SPDX-FileCopyrightText: 2024 Florian Müllner <fmuellner@gnome.org>
|
|
+
|
|
+SPDX-License-Identifier: GPL-2.0-or-later
|
|
+-->
|
|
+
|
|
+<schemalist gettext-domain="gnome-shell-extensions">
|
|
+ <schema id="org.gnome.shell.extensions.workspace-indicator"
|
|
+ path="/org/gnome/shell/extensions/workspace-indicator/">
|
|
+ <key name="embed-previews" type="b">
|
|
+ <default>false</default>
|
|
+ <summary>Show workspace previews in top bar</summary>
|
|
+ </key>
|
|
+ </schema>
|
|
+</schemalist>
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 1e3db810..fd497dc9 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -411,8 +411,11 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
|
|
const {
|
|
baseStyleClass = 'workspace-indicator',
|
|
+ settings,
|
|
} = params;
|
|
|
|
+ this._settings = settings;
|
|
+
|
|
baseStyleClassName = baseStyleClass;
|
|
this.add_style_class_name(baseStyleClassName);
|
|
|
|
@@ -444,8 +447,6 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._nWorkspacesChanged.bind(this)),
|
|
workspaceManager.connect_after('workspace-switched',
|
|
this._onWorkspaceSwitched.bind(this)),
|
|
- workspaceManager.connect('notify::layout-rows',
|
|
- this._onWorkspaceOrientationChanged.bind(this))
|
|
];
|
|
|
|
this.connect('scroll-event',
|
|
@@ -461,12 +462,15 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
});
|
|
|
|
this._updateMenu();
|
|
- this._onWorkspaceOrientationChanged();
|
|
|
|
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' });
|
|
this._settingsChangedId = this._settings.connect(
|
|
'changed::workspace-names',
|
|
this._updateMenuLabels.bind(this));
|
|
+
|
|
+ this._settings.connect('changed::embed-previews',
|
|
+ () => this._updateThumbnailVisibility());
|
|
+ this._updateThumbnailVisibility();
|
|
}
|
|
|
|
_onDestroy() {
|
|
@@ -485,12 +489,12 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
super._onDestroy();
|
|
}
|
|
|
|
- _onWorkspaceOrientationChanged() {
|
|
- let vertical = global.workspace_manager.layout_rows == -1;
|
|
- this.reactive = vertical;
|
|
+ _updateThumbnailVisibility() {
|
|
+ const useMenu = !this._settings.get_boolean('embed-previews');
|
|
+ this.reactive = useMenu;
|
|
|
|
- this._statusLabel.visible = vertical;
|
|
- this._thumbnails.visible = !vertical;
|
|
+ this._statusLabel.visible = useMenu;
|
|
+ this._thumbnails.visible = !useMenu;
|
|
|
|
this._updateTopBarRedirect();
|
|
}
|
|
diff --git a/po/POTFILES.in b/po/POTFILES.in
|
|
index 5cdb710f..eeb36fab 100644
|
|
--- a/po/POTFILES.in
|
|
+++ b/po/POTFILES.in
|
|
@@ -19,4 +19,5 @@ extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml
|
|
extensions/window-list/prefs.js
|
|
extensions/windowsNavigator/extension.js
|
|
extensions/workspace-indicator/prefs.js
|
|
+extensions/workspace-indicator/schemas/org.gnome.shell.extensions.workspace-indicator.gschema.xml
|
|
extensions/workspace-indicator/workspaceIndicator.js
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From ecadaca214f2a7d2154d968bcdd7db927cfc8503 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Thu, 21 Mar 2024 17:27:09 +0100
|
|
Subject: [PATCH 25/43] window-list: Expose workspace preview option
|
|
|
|
Now that we have the option, the window-list should expose it
|
|
in its preference window like the workspace-indicator.
|
|
---
|
|
extensions/window-list/prefs.js | 6 ++++++
|
|
extensions/workspace-indicator/workspaceIndicator.js | 6 +++---
|
|
2 files changed, 9 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/extensions/window-list/prefs.js b/extensions/window-list/prefs.js
|
|
index 17e97990..2c4f9e49 100644
|
|
--- a/extensions/window-list/prefs.js
|
|
+++ b/extensions/window-list/prefs.js
|
|
@@ -84,6 +84,12 @@ class WindowListPrefsWidget extends Gtk.Grid {
|
|
});
|
|
this._settings.bind('show-on-all-monitors', check, 'active', Gio.SettingsBindFlags.DEFAULT);
|
|
this.add(check);
|
|
+
|
|
+ check = new Gtk.CheckButton({
|
|
+ label: _('Show workspace previews'),
|
|
+ });
|
|
+ this._settings.bind('embed-previews', check, 'active', Gio.SettingsBindFlags.DEFAULT);
|
|
+ this.add(check);
|
|
}
|
|
});
|
|
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index fd497dc9..3c1d5724 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -463,8 +463,8 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
|
|
this._updateMenu();
|
|
|
|
- this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' });
|
|
- this._settingsChangedId = this._settings.connect(
|
|
+ this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' });
|
|
+ this._settingsChangedId = this._desktopSettings.connect(
|
|
'changed::workspace-names',
|
|
this._updateMenuLabels.bind(this));
|
|
|
|
@@ -478,7 +478,7 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
global.workspace_manager.disconnect(this._workspaceManagerSignals[i]);
|
|
|
|
if (this._settingsChangedId) {
|
|
- this._settings.disconnect(this._settingsChangedId);
|
|
+ this._desktopSettings.disconnect(this._settingsChangedId);
|
|
this._settingsChangedId = 0;
|
|
}
|
|
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 1748cb00834f7167d9e642a93240ec5f3518a344 Mon Sep 17 00:00:00 2001
|
|
From: Jakub Steiner <jimmac@gmail.com>
|
|
Date: Tue, 16 Jul 2024 09:40:53 +0200
|
|
Subject: [PATCH 26/43] window-list: Update styling
|
|
|
|
- Contemporary look. Fewer borders, thinner outlines for workspace indicators
|
|
- Lacks the designed unfocused window separators.
|
|
- Relies on https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/328
|
|
|
|
Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/421
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/330>
|
|
---
|
|
extensions/window-list/classic.css | 68 +++++++-----
|
|
extensions/window-list/stylesheet.css | 104 ++++++------------
|
|
.../workspace-indicator/stylesheet-dark.css | 4 +-
|
|
3 files changed, 76 insertions(+), 100 deletions(-)
|
|
|
|
diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css
|
|
index d7ceb062..1d9b82f0 100644
|
|
--- a/extensions/window-list/classic.css
|
|
+++ b/extensions/window-list/classic.css
|
|
@@ -1,22 +1,24 @@
|
|
+/*
|
|
+ * SPDX-FileCopyrightText: 2013 Florian Müllner <fmuellner@gnome.org>
|
|
+ * SPDX-FileCopyrightText: 2015 Jakub Steiner <jimmac@gmail.com>
|
|
+ *
|
|
+ * SPDX-License-Identifier: GPL-2.0-or-later
|
|
+ */
|
|
+
|
|
@import url("stylesheet.css");
|
|
@import url("stylesheet-workspace-switcher-light.css");
|
|
|
|
#panel.bottom-panel {
|
|
border-top-width: 1px;
|
|
border-bottom-width: 0px;
|
|
- height: 2.25em ;
|
|
- padding: 2px;
|
|
+ height: 2.5em;
|
|
}
|
|
|
|
- .bottom-panel .window-button > StWidget,
|
|
- .bottom-panel .window-picker-toggle > StWidget {
|
|
- color: #2e3436;
|
|
- background-color: #eee;
|
|
+ .bottom-panel .window-button > StWidget {
|
|
border-radius: 3px;
|
|
padding: 3px 6px 1px;
|
|
box-shadow: none;
|
|
text-shadow: none;
|
|
- border: 1px solid rgba(0,0,0,0.2);
|
|
}
|
|
|
|
.bottom-panel .window-button > StWidget {
|
|
@@ -24,27 +26,43 @@
|
|
max-width: 18.75em;
|
|
}
|
|
|
|
- .bottom-panel .window-button:hover > StWidget,
|
|
- .bottom-panel .window-picker-toggle:hover > StWidget {
|
|
- background-color: #f9f9f9;
|
|
- }
|
|
+ .window-button > StWidget {
|
|
+ color: #000;
|
|
+ background-color: transparent;
|
|
+}
|
|
|
|
- .bottom-panel .window-button:active > StWidget,
|
|
- .bottom-panel .window-button:focus > StWidget {
|
|
- box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
|
|
- }
|
|
+.window-button > StWidget {
|
|
+ -st-natural-width: 18.75em;
|
|
+ max-width: 18.75em;
|
|
+}
|
|
|
|
- .bottom-panel .window-button.focused > StWidget,
|
|
- .bottom-panel .window-picker-toggle:checked > StWidget {
|
|
- background-color: #ccc;
|
|
- box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
|
|
- }
|
|
+.window-button:hover > StWidget {
|
|
+ background-color: #e1e1e1;
|
|
+}
|
|
|
|
- .bottom-panel .window-button.focused:hover > StWidget {
|
|
- background-color: #e9e9e9;
|
|
+.window-button:active > StWidget,
|
|
+.window-button:focus > StWidget {
|
|
+ background-color: #d4d4d4;
|
|
+}
|
|
+
|
|
+.window-button.focused > StWidget {
|
|
+ background-color: #c7c7c7;
|
|
+}
|
|
+
|
|
+ .window-button.focused:hover > StWidget {
|
|
+ background-color: #bbb;
|
|
}
|
|
|
|
- .bottom-panel .window-button.minimized > StWidget {
|
|
- color: #888;
|
|
- box-shadow: none;
|
|
+ .window-button.focused:active > StWidget {
|
|
+ background-color: #aeaeae;
|
|
}
|
|
+
|
|
+.window-button.minimized > StWidget {
|
|
+ color: #aaa;
|
|
+ background-color: #f9f9f9;
|
|
+}
|
|
+
|
|
+.window-button.minimized:active > StWidget {
|
|
+ color: #aaa;
|
|
+ background-color: #f9f9f9;
|
|
+}
|
|
diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css
|
|
index 2aa35922..349404c5 100644
|
|
--- a/extensions/window-list/stylesheet.css
|
|
+++ b/extensions/window-list/stylesheet.css
|
|
@@ -1,3 +1,9 @@
|
|
+/*
|
|
+ * SPDX-FileCopyrightText: 2012 Florian Müllner <fmuellner@gnome.org>
|
|
+ * SPDX-FileCopyrightText: 2013 Giovanni Campagna <gcampagna@src.gnome.org>
|
|
+ *
|
|
+ * SPDX-License-Identifier: GPL-2.0-or-later
|
|
+ */
|
|
@import url("stylesheet-workspace-switcher-dark.css");
|
|
|
|
.bottom-panel {
|
|
@@ -12,8 +18,14 @@
|
|
font-size: 10pt;
|
|
}
|
|
|
|
+.bottom-panel {
|
|
+ background-color: #000000;
|
|
+ border-top-width: 0px;
|
|
+ height: 2.45em;
|
|
+}
|
|
+
|
|
.window-button {
|
|
- padding: 1px;
|
|
+ padding: 4px, 3px;
|
|
}
|
|
|
|
.window-button:first-child:ltr {
|
|
@@ -30,20 +42,11 @@
|
|
|
|
.window-button > StWidget,
|
|
.window-picker-toggle > StWidget {
|
|
- color: #bbb;
|
|
- background-color: black;
|
|
+ color: #fff;
|
|
+ background-color: transparent;
|
|
border-radius: 4px;
|
|
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);
|
|
+ transition: 100ms ease;
|
|
}
|
|
|
|
.window-button > StWidget {
|
|
@@ -51,35 +54,35 @@
|
|
max-width: 18.75em;
|
|
}
|
|
|
|
-.window-button:hover > StWidget,
|
|
-.window-picker-toggle:hover > StWidget {
|
|
- color: white;
|
|
- background-color: #1f1f1f;
|
|
+.window-button:hover > StWidget {
|
|
+ background-color: #303030;
|
|
}
|
|
|
|
.window-button:active > StWidget,
|
|
.window-button:focus > StWidget {
|
|
- box-shadow: inset 2px 2px 4px rgba(255,255,255,0.5);
|
|
+ background-color: #3c3c3c;
|
|
}
|
|
|
|
-.window-button.focused > StWidget,
|
|
-.window-picker-toggle:checked > StWidget {
|
|
- color: white;
|
|
- box-shadow: inset 1px 1px 4px rgba(255,255,255,0.7);
|
|
+.window-button.focused > StWidget {
|
|
+ background-color: #5b5b5b;
|
|
}
|
|
|
|
-.window-button.focused:active > StWidget,
|
|
-.window-picker-toggle:checked:active > StWidget {
|
|
- box-shadow: inset 2px 2px 4px rgba(255,255,255,0.7);
|
|
-}
|
|
+ .window-button.focused:hover > StWidget {
|
|
+ background-color: #676767;
|
|
+ }
|
|
+
|
|
+ .window-button.focused:active > StWidget {
|
|
+ background-color: #747474;
|
|
+ }
|
|
|
|
.window-button.minimized > StWidget {
|
|
color: #666;
|
|
- box-shadow: inset -1px -1px 4px rgba(255,255,255,0.5);
|
|
+ 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 {
|
|
@@ -87,51 +90,6 @@
|
|
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 0;
|
|
-}
|
|
-
|
|
-.window-list-workspace-indicator .workspaces-box {
|
|
- spacing: 3px;
|
|
- padding: 3px;
|
|
-}
|
|
-
|
|
-.window-list-workspace-indicator .workspace {
|
|
- border: 1px solid #cccccc;
|
|
- width: 52px;
|
|
-}
|
|
-
|
|
-.window-list-workspace-indicator .workspace:first-child:last-child:ltr,
|
|
-.window-list-workspace-indicator .workspace:first-child:last-child:rtl {
|
|
- border-radius: 4px;
|
|
-}
|
|
-
|
|
-.window-list-workspace-indicator .workspace:first-child:ltr,
|
|
-.window-list-workspace-indicator .workspace:last-child:rtl {
|
|
- border-radius: 4px 0 0 4px;
|
|
-}
|
|
-
|
|
-.window-list-workspace-indicator .workspace:first-child:rtl,
|
|
-.window-list-workspace-indicator .workspace:last-child:ltr {
|
|
- border-radius: 0 4px 4px 0;
|
|
-}
|
|
-
|
|
-.window-list-workspace-indicator .workspace.active {
|
|
- background-color: rgba(200, 200, 200, .3);
|
|
-}
|
|
-
|
|
-.window-list-workspace-indicator-window-preview {
|
|
- background-color: #bebebe;
|
|
- border: 1px solid #828282;
|
|
-}
|
|
-
|
|
-.window-list-workspace-indicator-window-preview.active {
|
|
- background-color: #d4d4d4;
|
|
-}
|
|
-
|
|
.notification {
|
|
font-weight: normal;
|
|
}
|
|
diff --git a/extensions/workspace-indicator/stylesheet-dark.css b/extensions/workspace-indicator/stylesheet-dark.css
|
|
index 61d1e982..5663b422 100644
|
|
--- a/extensions/workspace-indicator/stylesheet-dark.css
|
|
+++ b/extensions/workspace-indicator/stylesheet-dark.css
|
|
@@ -13,13 +13,13 @@
|
|
|
|
.workspace-indicator .workspace {
|
|
width: 52px;
|
|
- border: 2px solid transparent;
|
|
+ border: 1px solid transparent;
|
|
border-radius: 4px;
|
|
background-color: #3f3f3f;
|
|
}
|
|
|
|
.workspace-indicator .workspace.active {
|
|
- border-color: #9f9f9f;
|
|
+ border-color: #fff;
|
|
}
|
|
|
|
.workspace-indicator-window-preview {
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From c98e22e9b33a1a584eef04c25500e65d7423e676 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 25 Sep 2024 03:36:08 +0200
|
|
Subject: [PATCH 27/43] window-list: Small stylesheet cleanup
|
|
|
|
The light stylesheet duplicates some declarations, and the
|
|
last occurrence matches what we already inherit from the
|
|
dark stylesheet.
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/337>
|
|
---
|
|
extensions/window-list/classic.css | 10 ----------
|
|
1 file changed, 10 deletions(-)
|
|
|
|
diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css
|
|
index 1d9b82f0..63e5e48c 100644
|
|
--- a/extensions/window-list/classic.css
|
|
+++ b/extensions/window-list/classic.css
|
|
@@ -21,21 +21,11 @@
|
|
text-shadow: none;
|
|
}
|
|
|
|
- .bottom-panel .window-button > StWidget {
|
|
- -st-natural-width: 18.7em;
|
|
- max-width: 18.75em;
|
|
- }
|
|
-
|
|
.window-button > StWidget {
|
|
color: #000;
|
|
background-color: transparent;
|
|
}
|
|
|
|
-.window-button > StWidget {
|
|
- -st-natural-width: 18.75em;
|
|
- max-width: 18.75em;
|
|
-}
|
|
-
|
|
.window-button:hover > StWidget {
|
|
background-color: #e1e1e1;
|
|
}
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From f2e31221bbd114bedc1d95d3b49afb1af14d5735 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Fri, 11 Oct 2024 12:10:36 +0200
|
|
Subject: [PATCH 28/43] workspace-indicator: Split out workspaces prefs page
|
|
|
|
The window-list extension already uses the extension code for
|
|
its embedded workspace indicator, this will allow it to do the
|
|
same for the preference page.
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/344>
|
|
---
|
|
extensions/workspace-indicator/meson.build | 2 +-
|
|
extensions/workspace-indicator/prefs.js | 244 +----------------
|
|
.../workspace-indicator/workspacePrefs.js | 245 ++++++++++++++++++
|
|
po/POTFILES.in | 2 +-
|
|
4 files changed, 250 insertions(+), 243 deletions(-)
|
|
create mode 100644 extensions/workspace-indicator/workspacePrefs.js
|
|
|
|
diff --git a/extensions/workspace-indicator/meson.build b/extensions/workspace-indicator/meson.build
|
|
index a88db78a..52ab5334 100644
|
|
--- a/extensions/workspace-indicator/meson.build
|
|
+++ b/extensions/workspace-indicator/meson.build
|
|
@@ -10,4 +10,4 @@ extension_data += files(
|
|
)
|
|
extension_schemas += files('schemas/' + metadata_conf.get('gschemaname') + '.gschema.xml')
|
|
|
|
-extension_sources += files('prefs.js', 'workspaceIndicator.js')
|
|
+extension_sources += files('prefs.js', 'workspaceIndicator.js', 'workspacePrefs.js')
|
|
diff --git a/extensions/workspace-indicator/prefs.js b/extensions/workspace-indicator/prefs.js
|
|
index d787f481..2d90e198 100644
|
|
--- a/extensions/workspace-indicator/prefs.js
|
|
+++ b/extensions/workspace-indicator/prefs.js
|
|
@@ -1,253 +1,15 @@
|
|
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
|
|
/* exported init buildPrefsWidget */
|
|
|
|
-const { Gio, GObject, Gtk } = imports.gi;
|
|
-
|
|
-const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
|
-const _ = Gettext.gettext;
|
|
-const N_ = e => e;
|
|
-
|
|
const ExtensionUtils = imports.misc.extensionUtils;
|
|
+const Me = ExtensionUtils.getCurrentExtension();
|
|
|
|
-const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
|
|
-const WORKSPACE_KEY = 'workspace-names';
|
|
-
|
|
-const GeneralGroup = GObject.registerClass(
|
|
-class GeneralGroup extends Gtk.Box {
|
|
- _init() {
|
|
- super._init({
|
|
- orientation: Gtk.Orientation.VERTICAL,
|
|
- });
|
|
-
|
|
- const row = new Gtk.Box();
|
|
- this.add(row);
|
|
-
|
|
- row.add(new Gtk.Label({
|
|
- label: _('Show Previews In Top Bar'),
|
|
- }));
|
|
-
|
|
- const sw = new Gtk.Switch({
|
|
- hexpand: true,
|
|
- halign: Gtk.Align.END,
|
|
- });
|
|
- row.add(sw);
|
|
-
|
|
- const settings = ExtensionUtils.getSettings();
|
|
-
|
|
- settings.bind('embed-previews',
|
|
- sw, 'active',
|
|
- Gio.SettingsBindFlags.DEFAULT);
|
|
- }
|
|
-});
|
|
-
|
|
-const WorkspaceNameModel = GObject.registerClass(
|
|
-class WorkspaceNameModel extends Gtk.ListStore {
|
|
- _init(params) {
|
|
- super._init(params);
|
|
- this.set_column_types([GObject.TYPE_STRING]);
|
|
-
|
|
- this.Columns = {
|
|
- LABEL: 0,
|
|
- };
|
|
-
|
|
- this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA });
|
|
- //this._settings.connect('changed::workspace-names', this._reloadFromSettings.bind(this));
|
|
-
|
|
- this._reloadFromSettings();
|
|
-
|
|
- // overriding class closure doesn't work, because GtkTreeModel
|
|
- // plays tricks with marshallers and class closures
|
|
- this.connect('row-changed', this._onRowChanged.bind(this));
|
|
- this.connect('row-inserted', this._onRowInserted.bind(this));
|
|
- this.connect('row-deleted', this._onRowDeleted.bind(this));
|
|
- }
|
|
-
|
|
- _reloadFromSettings() {
|
|
- if (this._preventChanges)
|
|
- return;
|
|
- this._preventChanges = true;
|
|
-
|
|
- let newNames = this._settings.get_strv(WORKSPACE_KEY);
|
|
-
|
|
- let i = 0;
|
|
- let [ok, iter] = this.get_iter_first();
|
|
- while (ok && i < newNames.length) {
|
|
- this.set(iter, [this.Columns.LABEL], [newNames[i]]);
|
|
-
|
|
- ok = this.iter_next(iter);
|
|
- i++;
|
|
- }
|
|
-
|
|
- while (ok)
|
|
- ok = this.remove(iter);
|
|
-
|
|
- for ( ; i < newNames.length; i++) {
|
|
- iter = this.append();
|
|
- this.set(iter, [this.Columns.LABEL], [newNames[i]]);
|
|
- }
|
|
-
|
|
- this._preventChanges = false;
|
|
- }
|
|
-
|
|
- _onRowChanged(self, path, iter) {
|
|
- if (this._preventChanges)
|
|
- return;
|
|
- this._preventChanges = true;
|
|
-
|
|
- let index = path.get_indices()[0];
|
|
- let names = this._settings.get_strv(WORKSPACE_KEY);
|
|
-
|
|
- if (index >= names.length) {
|
|
- // fill with blanks
|
|
- for (let i = names.length; i <= index; i++)
|
|
- names[i] = '';
|
|
- }
|
|
-
|
|
- names[index] = this.get_value(iter, this.Columns.LABEL);
|
|
-
|
|
- this._settings.set_strv(WORKSPACE_KEY, names);
|
|
-
|
|
- this._preventChanges = false;
|
|
- }
|
|
-
|
|
- _onRowInserted(self, path, iter) {
|
|
- if (this._preventChanges)
|
|
- return;
|
|
- this._preventChanges = true;
|
|
-
|
|
- let index = path.get_indices()[0];
|
|
- let names = this._settings.get_strv(WORKSPACE_KEY);
|
|
- let label = this.get_value(iter, this.Columns.LABEL) || '';
|
|
- names.splice(index, 0, label);
|
|
-
|
|
- this._settings.set_strv(WORKSPACE_KEY, names);
|
|
-
|
|
- this._preventChanges = false;
|
|
- }
|
|
-
|
|
- _onRowDeleted(self, path) {
|
|
- if (this._preventChanges)
|
|
- return;
|
|
- this._preventChanges = true;
|
|
-
|
|
- let index = path.get_indices()[0];
|
|
- let names = this._settings.get_strv(WORKSPACE_KEY);
|
|
-
|
|
- if (index >= names.length)
|
|
- return;
|
|
-
|
|
- names.splice(index, 1);
|
|
-
|
|
- // compact the array
|
|
- for (let i = names.length - 1; i >= 0 && !names[i]; i++)
|
|
- names.pop();
|
|
-
|
|
- this._settings.set_strv(WORKSPACE_KEY, names);
|
|
-
|
|
- this._preventChanges = false;
|
|
- }
|
|
-});
|
|
-
|
|
-const WorkspaceSettingsWidget = GObject.registerClass(
|
|
-class WorkspaceSettingsWidget extends Gtk.Grid {
|
|
- _init(params) {
|
|
- super._init(params);
|
|
- this.margin = 12;
|
|
- this.orientation = Gtk.Orientation.VERTICAL;
|
|
-
|
|
- const box = new Gtk.Box({
|
|
- orientation: Gtk.Orientation.VERTICAL,
|
|
- halign: Gtk.Align.CENTER,
|
|
- spacing: 12,
|
|
- margin_top: 36,
|
|
- margin_bottom: 36,
|
|
- margin_start: 36,
|
|
- margin_end: 36,
|
|
- });
|
|
- this.add(box);
|
|
-
|
|
- box.add(new GeneralGroup());
|
|
-
|
|
- box.add(new Gtk.Label({
|
|
- label: '<b>%s</b>'.format(_('Workspace Names')),
|
|
- use_markup: true,
|
|
- margin_bottom: 6,
|
|
- hexpand: true,
|
|
- halign: Gtk.Align.START
|
|
- }));
|
|
-
|
|
- let scrolled = new Gtk.ScrolledWindow({ shadow_type: Gtk.ShadowType.IN });
|
|
- scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
|
- this.add(scrolled);
|
|
-
|
|
- this._store = new WorkspaceNameModel();
|
|
- this._treeView = new Gtk.TreeView({
|
|
- model: this._store,
|
|
- headers_visible: false,
|
|
- reorderable: true,
|
|
- hexpand: true,
|
|
- vexpand: true
|
|
- });
|
|
-
|
|
- let column = new Gtk.TreeViewColumn({ title: _('Name') });
|
|
- let renderer = new Gtk.CellRendererText({ editable: true });
|
|
- renderer.connect('edited', this._cellEdited.bind(this));
|
|
- column.pack_start(renderer, true);
|
|
- column.add_attribute(renderer, 'text', this._store.Columns.LABEL);
|
|
- this._treeView.append_column(column);
|
|
-
|
|
- scrolled.add(this._treeView);
|
|
-
|
|
- let toolbar = new Gtk.Toolbar({ icon_size: Gtk.IconSize.SMALL_TOOLBAR });
|
|
- toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR);
|
|
-
|
|
- let newButton = new Gtk.ToolButton({ icon_name: 'list-add-symbolic' });
|
|
- newButton.connect('clicked', this._newClicked.bind(this));
|
|
- toolbar.add(newButton);
|
|
-
|
|
- let delButton = new Gtk.ToolButton({ icon_name: 'list-remove-symbolic' });
|
|
- delButton.connect('clicked', this._delClicked.bind(this));
|
|
- toolbar.add(delButton);
|
|
-
|
|
- let selection = this._treeView.get_selection();
|
|
- selection.connect('changed', () => {
|
|
- delButton.sensitive = selection.count_selected_rows() > 0;
|
|
- });
|
|
- delButton.sensitive = selection.count_selected_rows() > 0;
|
|
-
|
|
- this.add(toolbar);
|
|
- }
|
|
-
|
|
- _cellEdited(renderer, path, newText) {
|
|
- let [ok, iter] = this._store.get_iter_from_string(path);
|
|
-
|
|
- if (ok)
|
|
- this._store.set(iter, [this._store.Columns.LABEL], [newText]);
|
|
- }
|
|
-
|
|
- _newClicked() {
|
|
- let iter = this._store.append();
|
|
- let index = this._store.get_path(iter).get_indices()[0];
|
|
-
|
|
- let label = _('Workspace %d').format(index + 1);
|
|
- this._store.set(iter, [this._store.Columns.LABEL], [label]);
|
|
- }
|
|
-
|
|
- _delClicked() {
|
|
- let [any, model_, iter] = this._treeView.get_selection().get_selected();
|
|
-
|
|
- if (any)
|
|
- this._store.remove(iter);
|
|
- }
|
|
-});
|
|
+const { WorkspacesPage } = Me.imports.workspacePrefs;
|
|
|
|
function init() {
|
|
ExtensionUtils.initTranslations();
|
|
}
|
|
|
|
function buildPrefsWidget() {
|
|
- let widget = new WorkspaceSettingsWidget();
|
|
- widget.show_all();
|
|
-
|
|
- return widget;
|
|
+ return new WorkspacesPage();
|
|
}
|
|
diff --git a/extensions/workspace-indicator/workspacePrefs.js b/extensions/workspace-indicator/workspacePrefs.js
|
|
new file mode 100644
|
|
index 00000000..1c65ff6b
|
|
--- /dev/null
|
|
+++ b/extensions/workspace-indicator/workspacePrefs.js
|
|
@@ -0,0 +1,245 @@
|
|
+// SPDX-FileCopyrightText: 2012 Giovanni Campagna <gcampagna@src.gnome.org>
|
|
+// SPDX-FileCopyrightText: 2014 Florian Müllner <fmuellner@gnome.org>
|
|
+//
|
|
+// SPDX-License-Identifier: GPL-2.0-or-later
|
|
+
|
|
+/* exported WorkspacesPage */
|
|
+const { Gio, GLib, GObject, Gtk, Pango } = imports.gi;
|
|
+
|
|
+const ExtensionUtils = imports.misc.extensionUtils;
|
|
+const Me = ExtensionUtils.getCurrentExtension();
|
|
+
|
|
+const Gettext = imports.gettext.domain(Me.metadata['gettext-domain']);
|
|
+const _ = Gettext.gettext;
|
|
+const N_ = e => e;
|
|
+
|
|
+const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
|
|
+const WORKSPACE_KEY = 'workspace-names';
|
|
+
|
|
+const GeneralGroup = GObject.registerClass(
|
|
+class GeneralGroup extends Gtk.Box {
|
|
+ _init() {
|
|
+ super._init({
|
|
+ orientation: Gtk.Orientation.VERTICAL,
|
|
+ });
|
|
+
|
|
+ const row = new Gtk.Box();
|
|
+ this.add(row);
|
|
+
|
|
+ row.add(new Gtk.Label({
|
|
+ label: _('Show Previews In Top Bar'),
|
|
+ }));
|
|
+
|
|
+ const sw = new Gtk.Switch({
|
|
+ hexpand: true,
|
|
+ halign: Gtk.Align.END,
|
|
+ });
|
|
+ row.add(sw);
|
|
+
|
|
+ const settings = ExtensionUtils.getSettings();
|
|
+
|
|
+ settings.bind('embed-previews',
|
|
+ sw, 'active',
|
|
+ Gio.SettingsBindFlags.DEFAULT);
|
|
+ }
|
|
+});
|
|
+
|
|
+const WorkspaceNameModel = GObject.registerClass(
|
|
+class WorkspaceNameModel extends Gtk.ListStore {
|
|
+ _init(params) {
|
|
+ super._init(params);
|
|
+ this.set_column_types([GObject.TYPE_STRING]);
|
|
+
|
|
+ this.Columns = {
|
|
+ LABEL: 0,
|
|
+ };
|
|
+
|
|
+ this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA });
|
|
+ //this._settings.connect('changed::workspace-names', this._reloadFromSettings.bind(this));
|
|
+
|
|
+ this._reloadFromSettings();
|
|
+
|
|
+ // overriding class closure doesn't work, because GtkTreeModel
|
|
+ // plays tricks with marshallers and class closures
|
|
+ this.connect('row-changed', this._onRowChanged.bind(this));
|
|
+ this.connect('row-inserted', this._onRowInserted.bind(this));
|
|
+ this.connect('row-deleted', this._onRowDeleted.bind(this));
|
|
+ }
|
|
+
|
|
+ _reloadFromSettings() {
|
|
+ if (this._preventChanges)
|
|
+ return;
|
|
+ this._preventChanges = true;
|
|
+
|
|
+ let newNames = this._settings.get_strv(WORKSPACE_KEY);
|
|
+
|
|
+ let i = 0;
|
|
+ let [ok, iter] = this.get_iter_first();
|
|
+ while (ok && i < newNames.length) {
|
|
+ this.set(iter, [this.Columns.LABEL], [newNames[i]]);
|
|
+
|
|
+ ok = this.iter_next(iter);
|
|
+ i++;
|
|
+ }
|
|
+
|
|
+ while (ok)
|
|
+ ok = this.remove(iter);
|
|
+
|
|
+ for ( ; i < newNames.length; i++) {
|
|
+ iter = this.append();
|
|
+ this.set(iter, [this.Columns.LABEL], [newNames[i]]);
|
|
+ }
|
|
+
|
|
+ this._preventChanges = false;
|
|
+ }
|
|
+
|
|
+ _onRowChanged(self, path, iter) {
|
|
+ if (this._preventChanges)
|
|
+ return;
|
|
+ this._preventChanges = true;
|
|
+
|
|
+ let index = path.get_indices()[0];
|
|
+ let names = this._settings.get_strv(WORKSPACE_KEY);
|
|
+
|
|
+ if (index >= names.length) {
|
|
+ // fill with blanks
|
|
+ for (let i = names.length; i <= index; i++)
|
|
+ names[i] = '';
|
|
+ }
|
|
+
|
|
+ names[index] = this.get_value(iter, this.Columns.LABEL);
|
|
+
|
|
+ this._settings.set_strv(WORKSPACE_KEY, names);
|
|
+
|
|
+ this._preventChanges = false;
|
|
+ }
|
|
+
|
|
+ _onRowInserted(self, path, iter) {
|
|
+ if (this._preventChanges)
|
|
+ return;
|
|
+ this._preventChanges = true;
|
|
+
|
|
+ let index = path.get_indices()[0];
|
|
+ let names = this._settings.get_strv(WORKSPACE_KEY);
|
|
+ let label = this.get_value(iter, this.Columns.LABEL) || '';
|
|
+ names.splice(index, 0, label);
|
|
+
|
|
+ this._settings.set_strv(WORKSPACE_KEY, names);
|
|
+
|
|
+ this._preventChanges = false;
|
|
+ }
|
|
+
|
|
+ _onRowDeleted(self, path) {
|
|
+ if (this._preventChanges)
|
|
+ return;
|
|
+ this._preventChanges = true;
|
|
+
|
|
+ let index = path.get_indices()[0];
|
|
+ let names = this._settings.get_strv(WORKSPACE_KEY);
|
|
+
|
|
+ if (index >= names.length)
|
|
+ return;
|
|
+
|
|
+ names.splice(index, 1);
|
|
+
|
|
+ // compact the array
|
|
+ for (let i = names.length - 1; i >= 0 && !names[i]; i++)
|
|
+ names.pop();
|
|
+
|
|
+ this._settings.set_strv(WORKSPACE_KEY, names);
|
|
+
|
|
+ this._preventChanges = false;
|
|
+ }
|
|
+});
|
|
+
|
|
+var WorkspacesPage = GObject.registerClass(
|
|
+class WorkspacesPage extends Gtk.ScrolledWindow {
|
|
+ _init() {
|
|
+ super._init({
|
|
+ hscrollbar_policy: Gtk.PolicyType.NEVER,
|
|
+ vexpand:true,
|
|
+ });
|
|
+
|
|
+ const box = new Gtk.Box({
|
|
+ orientation: Gtk.Orientation.VERTICAL,
|
|
+ halign: Gtk.Align.CENTER,
|
|
+ spacing: 12,
|
|
+ margin_top: 36,
|
|
+ margin_bottom: 36,
|
|
+ margin_start: 36,
|
|
+ margin_end: 36,
|
|
+ });
|
|
+ this.add(box);
|
|
+
|
|
+ box.add(new GeneralGroup());
|
|
+
|
|
+ box.add(new Gtk.Label({
|
|
+ label: '<b>%s</b>'.format(_('Workspace Names')),
|
|
+ use_markup: true,
|
|
+ margin_bottom: 6,
|
|
+ hexpand: true,
|
|
+ halign: Gtk.Align.START
|
|
+ }));
|
|
+
|
|
+ this._store = new WorkspaceNameModel();
|
|
+ this._treeView = new Gtk.TreeView({
|
|
+ model: this._store,
|
|
+ headers_visible: false,
|
|
+ reorderable: true,
|
|
+ hexpand: true,
|
|
+ vexpand: true
|
|
+ });
|
|
+
|
|
+ let column = new Gtk.TreeViewColumn({ title: _('Name') });
|
|
+ let renderer = new Gtk.CellRendererText({ editable: true });
|
|
+ renderer.connect('edited', this._cellEdited.bind(this));
|
|
+ column.pack_start(renderer, true);
|
|
+ column.add_attribute(renderer, 'text', this._store.Columns.LABEL);
|
|
+ this._treeView.append_column(column);
|
|
+
|
|
+ box.add(this._treeView);
|
|
+
|
|
+ let toolbar = new Gtk.Toolbar({ icon_size: Gtk.IconSize.SMALL_TOOLBAR });
|
|
+ toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR);
|
|
+
|
|
+ let newButton = new Gtk.ToolButton({ icon_name: 'list-add-symbolic' });
|
|
+ newButton.connect('clicked', this._newClicked.bind(this));
|
|
+ toolbar.add(newButton);
|
|
+
|
|
+ let delButton = new Gtk.ToolButton({ icon_name: 'list-remove-symbolic' });
|
|
+ delButton.connect('clicked', this._delClicked.bind(this));
|
|
+ toolbar.add(delButton);
|
|
+
|
|
+ let selection = this._treeView.get_selection();
|
|
+ selection.connect('changed', () => {
|
|
+ delButton.sensitive = selection.count_selected_rows() > 0;
|
|
+ });
|
|
+ delButton.sensitive = selection.count_selected_rows() > 0;
|
|
+
|
|
+ box.add(toolbar);
|
|
+
|
|
+ this.show_all();
|
|
+ }
|
|
+
|
|
+ _cellEdited(renderer, path, newText) {
|
|
+ let [ok, iter] = this._store.get_iter_from_string(path);
|
|
+
|
|
+ if (ok)
|
|
+ this._store.set(iter, [this._store.Columns.LABEL], [newText]);
|
|
+ }
|
|
+
|
|
+ _newClicked() {
|
|
+ let iter = this._store.append();
|
|
+ let index = this._store.get_path(iter).get_indices()[0];
|
|
+
|
|
+ let label = _('Workspace %d').format(index + 1);
|
|
+ this._store.set(iter, [this._store.Columns.LABEL], [label]);
|
|
+ }
|
|
+
|
|
+ _delClicked() {
|
|
+ let [any, model_, iter] = this._treeView.get_selection().get_selected();
|
|
+
|
|
+ if (any)
|
|
+ this._store.remove(iter);
|
|
+ }
|
|
+});
|
|
diff --git a/po/POTFILES.in b/po/POTFILES.in
|
|
index eeb36fab..ba4c5a46 100644
|
|
--- a/po/POTFILES.in
|
|
+++ b/po/POTFILES.in
|
|
@@ -18,6 +18,6 @@ extensions/window-list/extension.js
|
|
extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml
|
|
extensions/window-list/prefs.js
|
|
extensions/windowsNavigator/extension.js
|
|
-extensions/workspace-indicator/prefs.js
|
|
extensions/workspace-indicator/schemas/org.gnome.shell.extensions.workspace-indicator.gschema.xml
|
|
extensions/workspace-indicator/workspaceIndicator.js
|
|
+extensions/workspace-indicator/workspacePrefs.js
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 24d307c6cfa14b766f44e8bcba09b3b1dc741056 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Fri, 11 Oct 2024 12:13:05 +0200
|
|
Subject: [PATCH 29/43] workspace-indicator: Don't mention "top bar" in prefs
|
|
|
|
The preferences will be shared with the window-list extension,
|
|
so avoid mentioning a specific placement.
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/344>
|
|
---
|
|
extensions/workspace-indicator/workspacePrefs.js | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspacePrefs.js b/extensions/workspace-indicator/workspacePrefs.js
|
|
index 1c65ff6b..0bd4a58b 100644
|
|
--- a/extensions/workspace-indicator/workspacePrefs.js
|
|
+++ b/extensions/workspace-indicator/workspacePrefs.js
|
|
@@ -27,7 +27,7 @@ class GeneralGroup extends Gtk.Box {
|
|
this.add(row);
|
|
|
|
row.add(new Gtk.Label({
|
|
- label: _('Show Previews In Top Bar'),
|
|
+ label: _('Show Previews'),
|
|
}));
|
|
|
|
const sw = new Gtk.Switch({
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 025580ecd9a522c3d68debbd9e7a9d0464db268e Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Fri, 11 Oct 2024 12:45:54 +0200
|
|
Subject: [PATCH 30/43] window-list: Remove workspace-previews setting from
|
|
prefs
|
|
|
|
We are about to include the workspace prefs page from the
|
|
workspace-indicator extension, which already includes
|
|
the setting.
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/344>
|
|
---
|
|
extensions/window-list/prefs.js | 6 ------
|
|
1 file changed, 6 deletions(-)
|
|
|
|
diff --git a/extensions/window-list/prefs.js b/extensions/window-list/prefs.js
|
|
index 2c4f9e49..17e97990 100644
|
|
--- a/extensions/window-list/prefs.js
|
|
+++ b/extensions/window-list/prefs.js
|
|
@@ -84,12 +84,6 @@ class WindowListPrefsWidget extends Gtk.Grid {
|
|
});
|
|
this._settings.bind('show-on-all-monitors', check, 'active', Gio.SettingsBindFlags.DEFAULT);
|
|
this.add(check);
|
|
-
|
|
- check = new Gtk.CheckButton({
|
|
- label: _('Show workspace previews'),
|
|
- });
|
|
- this._settings.bind('embed-previews', check, 'active', Gio.SettingsBindFlags.DEFAULT);
|
|
- this.add(check);
|
|
}
|
|
});
|
|
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 232fa86f0ef5e833d1f7fb83812381afdaf3e1d2 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Sun, 29 Jun 2025 23:49:15 +0200
|
|
Subject: [PATCH 31/43] window-list: Add workspaces page to prefs
|
|
|
|
This brings back the workspace-previews setting, and adds the
|
|
ability to change the workspace names.
|
|
|
|
Given that those names are used as tooltips or preview titles,
|
|
it makes sense to allow editing them from the extension prefs
|
|
rather than relying on external tools (like dconf-editor).
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/344>
|
|
---
|
|
extensions/window-list/meson.build | 1 +
|
|
extensions/window-list/prefs.js | 49 +++++++++++++++++++++++++-----
|
|
2 files changed, 42 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/extensions/window-list/meson.build b/extensions/window-list/meson.build
|
|
index 12d2b174..c4485965 100644
|
|
--- a/extensions/window-list/meson.build
|
|
+++ b/extensions/window-list/meson.build
|
|
@@ -30,6 +30,7 @@ workspaceIndicatorSources = [
|
|
command: transform_stylesheet,
|
|
capture: true,
|
|
),
|
|
+ files('../workspace-indicator/workspacePrefs.js'),
|
|
]
|
|
|
|
extension_sources += files('prefs.js', 'windowPicker.js') + workspaceIndicatorSources
|
|
diff --git a/extensions/window-list/prefs.js b/extensions/window-list/prefs.js
|
|
index 17e97990..936767c8 100644
|
|
--- a/extensions/window-list/prefs.js
|
|
+++ b/extensions/window-list/prefs.js
|
|
@@ -7,20 +7,26 @@ const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
|
const _ = Gettext.gettext;
|
|
|
|
const ExtensionUtils = imports.misc.extensionUtils;
|
|
+const Me = ExtensionUtils.getCurrentExtension();
|
|
|
|
+const { WorkspacesPage } = Me.imports.workspacePrefs;
|
|
|
|
function init() {
|
|
ExtensionUtils.initTranslations();
|
|
}
|
|
|
|
-const WindowListPrefsWidget = GObject.registerClass(
|
|
-class WindowListPrefsWidget extends Gtk.Grid {
|
|
- _init(params) {
|
|
- super._init(params);
|
|
-
|
|
- this.margin = 24;
|
|
- this.row_spacing = 6;
|
|
- this.orientation = Gtk.Orientation.VERTICAL;
|
|
+const WindowListPage = GObject.registerClass(
|
|
+class WindowListPage extends Gtk.Box {
|
|
+ _init() {
|
|
+ super._init({
|
|
+ orientation: Gtk.Orientation.VERTICAL,
|
|
+ spacing: 6,
|
|
+ margin_top: 36,
|
|
+ margin_bottom: 36,
|
|
+ margin_start: 36,
|
|
+ margin_end: 36,
|
|
+ halign: Gtk.Align.CENTER,
|
|
+ });
|
|
|
|
let groupingLabel = '<b>%s</b>'.format(_('Window Grouping'));
|
|
this.add(new Gtk.Label({
|
|
@@ -84,6 +90,33 @@ class WindowListPrefsWidget extends Gtk.Grid {
|
|
});
|
|
this._settings.bind('show-on-all-monitors', check, 'active', Gio.SettingsBindFlags.DEFAULT);
|
|
this.add(check);
|
|
+
|
|
+ this.show_all();
|
|
+ }
|
|
+});
|
|
+
|
|
+const WindowListPrefsWidget = GObject.registerClass(
|
|
+class WindowListPrefsWidget extends Gtk.Box {
|
|
+ _init() {
|
|
+ super._init({
|
|
+ orientation: Gtk.Orientation.VERTICAL,
|
|
+ spacing: 6,
|
|
+ });
|
|
+
|
|
+ const stack = new Gtk.Stack();
|
|
+ const stackSwitcher = new Gtk.StackSwitcher({
|
|
+ stack,
|
|
+ margin_top: 12,
|
|
+ halign: Gtk.Align.CENTER,
|
|
+ });
|
|
+
|
|
+ this.add(stackSwitcher);
|
|
+ this.add(stack);
|
|
+
|
|
+ this.show_all();
|
|
+
|
|
+ stack.add_titled(new WindowListPage(), 'window-list', _('Window List'));
|
|
+ stack.add_titled(new WorkspacesPage(), 'workspaces', _('Workspaces'));
|
|
}
|
|
});
|
|
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 7722bfec6e5f388c2bf0330b603a9728643c0248 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Thu, 22 May 2025 16:31:57 +0200
|
|
Subject: [PATCH 32/43] workspace-indicator: Remove left-over variable
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/405>
|
|
---
|
|
extensions/workspace-indicator/workspaceIndicator.js | 2 --
|
|
1 file changed, 2 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 3c1d5724..3207e87c 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -440,8 +440,6 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._thumbnails = new WorkspacePreviews();
|
|
container.add_child(this._thumbnails);
|
|
|
|
- this._workspacesItems = [];
|
|
-
|
|
this._workspaceManagerSignals = [
|
|
workspaceManager.connect_after('notify::n-workspaces',
|
|
this._nWorkspacesChanged.bind(this)),
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 3d5f527d2215f49670df7d078910a3144da0f95e Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Thu, 22 May 2025 16:27:57 +0200
|
|
Subject: [PATCH 33/43] workspace-indicator: Split out WorkspacesMenu
|
|
|
|
The menu currently only contains the previews without any logic
|
|
on its own. This is about to change, so split the menu into a
|
|
separate class.
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/405>
|
|
---
|
|
.../workspace-indicator/workspaceIndicator.js | 181 +++++++++++-------
|
|
1 file changed, 110 insertions(+), 71 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 3207e87c..9bb7cb60 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -1,6 +1,7 @@
|
|
-const { Clutter, Gio, GObject, Meta, St } = imports.gi;
|
|
+const { Clutter, Gio, GLib, GObject, Meta, St } = imports.gi;
|
|
|
|
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;
|
|
@@ -403,6 +404,110 @@ const WorkspacePreviews = GObject.registerClass({
|
|
}
|
|
});
|
|
|
|
+class WorkspacesMenu extends PopupMenu.PopupMenu {
|
|
+ constructor(sourceActor) {
|
|
+ super(sourceActor, 0.5, St.Side.TOP);
|
|
+
|
|
+ this.actor.add_style_class_name(`${baseStyleClassName}-menu`);
|
|
+ this.actor.connect('destroy', () => this._onDestroy());
|
|
+
|
|
+ this._workspacesSection = new PopupMenu.PopupMenuSection();
|
|
+ this.addMenuItem(this._workspacesSection);
|
|
+
|
|
+ this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
+
|
|
+ this.addAction(_('Settings'), () => {
|
|
+ const extension = ExtensionUtils.getCurrentExtension();
|
|
+
|
|
+ Gio.DBus.session.call(
|
|
+ 'org.gnome.Shell',
|
|
+ '/org/gnome/Shell',
|
|
+ 'org.gnome.Shell.Extensions',
|
|
+ 'LaunchExtensionPrefs',
|
|
+ new GLib.Variant('(s)', [extension.uuid]),
|
|
+ null,
|
|
+ Gio.DBusCallFlags.NONE,
|
|
+ -1,
|
|
+ null);
|
|
+ });
|
|
+
|
|
+ this._desktopSettings =
|
|
+ new Gio.Settings({schema_id: 'org.gnome.desktop.wm.preferences'});
|
|
+ this._workspaceNamesChangedId =
|
|
+ this._desktopSettings.connect('changed::workspace-names', () => {
|
|
+ this._updateWorkspaceLabels();
|
|
+ this.emit('active-name-changed');
|
|
+ });
|
|
+
|
|
+ const {workspaceManager} = global;
|
|
+ this._workspaceManagerSignals = [
|
|
+ workspaceManager.connect('notify::n-workspaces',
|
|
+ () => this._updateWorkspaceItems()),
|
|
+ workspaceManager.connect('workspace-switched',
|
|
+ () => this._updateActiveIndicator()),
|
|
+ ];
|
|
+ this._updateWorkspaceItems();
|
|
+ }
|
|
+
|
|
+ get activeName() {
|
|
+ const {workspaceManager} = global;
|
|
+ const active = workspaceManager.get_active_workspace_index();
|
|
+ return Meta.prefs_get_workspace_name(active);
|
|
+ }
|
|
+
|
|
+ _updateWorkspaceItems() {
|
|
+ const {workspaceManager} = global;
|
|
+ const {nWorkspaces} = workspaceManager;
|
|
+
|
|
+ const section = this._workspacesSection.actor;
|
|
+ while (section.get_n_children() < nWorkspaces) {
|
|
+ const item = new PopupMenu.PopupMenuItem('');
|
|
+ item.connect('activate', (o, event) => {
|
|
+ const index = section.get_children().indexOf(item.actor);
|
|
+ const workspace = workspaceManager.get_workspace_by_index(index);
|
|
+ if (workspace)
|
|
+ workspace.activate(event.get_time());
|
|
+ });
|
|
+ this._workspacesSection.addMenuItem(item);
|
|
+ }
|
|
+
|
|
+ const items = section.get_children();
|
|
+ items.splice(nWorkspaces).forEach(item => item.destroy());
|
|
+
|
|
+ this._updateWorkspaceLabels();
|
|
+ this._updateActiveIndicator();
|
|
+ }
|
|
+
|
|
+ _updateWorkspaceLabels() {
|
|
+ const items =
|
|
+ this._workspacesSection.actor.get_children().map(c => c._delegate);
|
|
+ items.forEach(
|
|
+ (item, i) => (item.label.text = Meta.prefs_get_workspace_name(i)));
|
|
+ }
|
|
+
|
|
+ _updateActiveIndicator() {
|
|
+ const {workspaceManager} = global;
|
|
+ const active = workspaceManager.get_active_workspace_index();
|
|
+
|
|
+ const items =
|
|
+ this._workspacesSection.actor.get_children().map(c => c._delegate);
|
|
+ items.forEach((item, i) => {
|
|
+ item.setOrnament(i === active
|
|
+ ? PopupMenu.Ornament.CHECK
|
|
+ : PopupMenu.Ornament.NONE);
|
|
+ });
|
|
+ this.emit('active-name-changed');
|
|
+ }
|
|
+
|
|
+ _onDestroy() {
|
|
+ for (const id of this._workspaceManagerSignals)
|
|
+ global.workspace_manager.disconnect(id);
|
|
+
|
|
+ this._desktopSettings.disconnect(this._workspaceNamesChangedId);
|
|
+ this._desktopSettings = null;
|
|
+ }
|
|
+}
|
|
+
|
|
let WorkspaceIndicator = GObject.registerClass({
|
|
GTypeName: `${TypePrefix}WorkspaceIndicator`
|
|
}, class WorkspaceIndicator extends PanelMenu.Button {
|
|
@@ -441,8 +546,6 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
container.add_child(this._thumbnails);
|
|
|
|
this._workspaceManagerSignals = [
|
|
- workspaceManager.connect_after('notify::n-workspaces',
|
|
- this._nWorkspacesChanged.bind(this)),
|
|
workspaceManager.connect_after('workspace-switched',
|
|
this._onWorkspaceSwitched.bind(this)),
|
|
];
|
|
@@ -459,13 +562,6 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._updateTopBarRedirect();
|
|
});
|
|
|
|
- this._updateMenu();
|
|
-
|
|
- this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' });
|
|
- this._settingsChangedId = this._desktopSettings.connect(
|
|
- 'changed::workspace-names',
|
|
- this._updateMenuLabels.bind(this));
|
|
-
|
|
this._settings.connect('changed::embed-previews',
|
|
() => this._updateThumbnailVisibility());
|
|
this._updateThumbnailVisibility();
|
|
@@ -475,11 +571,6 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
for (let i = 0; i < this._workspaceManagerSignals.length; i++)
|
|
global.workspace_manager.disconnect(this._workspaceManagerSignals[i]);
|
|
|
|
- if (this._settingsChangedId) {
|
|
- this._desktopSettings.disconnect(this._settingsChangedId);
|
|
- this._settingsChangedId = 0;
|
|
- }
|
|
-
|
|
if (this._inTopBar)
|
|
Main.panel.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
|
|
this._inTopBar = false;
|
|
@@ -494,6 +585,10 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._statusLabel.visible = useMenu;
|
|
this._thumbnails.visible = !useMenu;
|
|
|
|
+ this.setMenu(useMenu
|
|
+ ? new WorkspacesMenu(this)
|
|
+ : null);
|
|
+
|
|
this._updateTopBarRedirect();
|
|
}
|
|
|
|
@@ -510,67 +605,11 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
|
|
_onWorkspaceSwitched() {
|
|
this._currentWorkspace = global.workspace_manager.get_active_workspace_index();
|
|
-
|
|
- this._updateMenuOrnament();
|
|
-
|
|
this._statusLabel.set_text(this._getStatusText());
|
|
}
|
|
|
|
- _nWorkspacesChanged() {
|
|
- this._updateMenu();
|
|
- }
|
|
-
|
|
- _updateMenuOrnament() {
|
|
- for (let i = 0; i < this._workspacesItems.length; i++) {
|
|
- this._workspacesItems[i].setOrnament(i == this._currentWorkspace
|
|
- ? PopupMenu.Ornament.DOT
|
|
- : PopupMenu.Ornament.NONE);
|
|
- }
|
|
- }
|
|
-
|
|
_getStatusText() {
|
|
const current = this._currentWorkspace + 1;
|
|
return `${current}`;
|
|
}
|
|
-
|
|
- _updateMenuLabels() {
|
|
- for (let i = 0; i < this._workspacesItems.length; i++) {
|
|
- const item = this._workspacesItems[i];
|
|
- item.label.text = Meta.prefs_get_workspace_name(i);
|
|
- }
|
|
- }
|
|
-
|
|
- _updateMenu() {
|
|
- let workspaceManager = global.workspace_manager;
|
|
-
|
|
- this.menu.removeAll();
|
|
- this._workspacesItems = [];
|
|
- this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
|
-
|
|
- for (let i = 0; i < workspaceManager.n_workspaces; i++) {
|
|
- const name = Meta.prefs_get_workspace_name(i);
|
|
- const item = new PopupMenu.PopupMenuItem(name);
|
|
-
|
|
- item.connect('activate',
|
|
- () => this._activate(i));
|
|
-
|
|
- item.setOrnament(i === this._currentWorkspace
|
|
- ? PopupMenu.Ornament.DOT
|
|
- : PopupMenu.Ornament.NONE);
|
|
-
|
|
- this.menu.addMenuItem(item);
|
|
- this._workspacesItems[i] = item;
|
|
- }
|
|
-
|
|
- this._statusLabel.set_text(this._getStatusText());
|
|
- }
|
|
-
|
|
- _activate(index) {
|
|
- let workspaceManager = global.workspace_manager;
|
|
-
|
|
- if (index >= 0 && index < workspaceManager.n_workspaces) {
|
|
- let metaWorkspace = workspaceManager.get_workspace_by_index(index);
|
|
- metaWorkspace.activate(global.get_current_time());
|
|
- }
|
|
- }
|
|
});
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From ce6bbf7ba28a0a24045e460b3eeb47aabbeeebe6 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 28 May 2025 02:16:33 +0200
|
|
Subject: [PATCH 34/43] workspace-indicator: Include menu with previews
|
|
|
|
The menu is currently only used when previews are disabled. But
|
|
as we are going to use the menu for changing workspace names, it
|
|
should be always available. So add it unconditionally, and show
|
|
it on right-click when using previews.
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/405>
|
|
---
|
|
.../workspace-indicator/stylesheet-dark.css | 5 ++++
|
|
.../workspace-indicator/workspaceIndicator.js | 25 +++++++++++++------
|
|
2 files changed, 23 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/stylesheet-dark.css b/extensions/workspace-indicator/stylesheet-dark.css
|
|
index 5663b422..6719c05a 100644
|
|
--- a/extensions/workspace-indicator/stylesheet-dark.css
|
|
+++ b/extensions/workspace-indicator/stylesheet-dark.css
|
|
@@ -1,3 +1,8 @@
|
|
+.workspace-indicator.previews:active {
|
|
+ background-color: none !important;
|
|
+ box-shadow: none !important;
|
|
+}
|
|
+
|
|
.workspace-indicator .status-label {
|
|
padding: 0 8px;
|
|
}
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 9bb7cb60..8184efbb 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -524,6 +524,8 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
baseStyleClassName = baseStyleClass;
|
|
this.add_style_class_name(baseStyleClassName);
|
|
|
|
+ this.setMenu(new WorkspacesMenu(this));
|
|
+
|
|
let container = new St.Widget({
|
|
layout_manager: new Clutter.BinLayout(),
|
|
x_expand: true,
|
|
@@ -545,6 +547,14 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._thumbnails = new WorkspacePreviews();
|
|
container.add_child(this._thumbnails);
|
|
|
|
+ this._thumbnails.connect('button-press-event', (a, event) => {
|
|
+ if (event.get_button() !== Clutter.BUTTON_SECONDARY)
|
|
+ return Clutter.EVENT_PROPAGATE;
|
|
+
|
|
+ this.menu.toggle();
|
|
+ return Clutter.EVENT_STOP;
|
|
+ });
|
|
+
|
|
this._workspaceManagerSignals = [
|
|
workspaceManager.connect_after('workspace-switched',
|
|
this._onWorkspaceSwitched.bind(this)),
|
|
@@ -579,15 +589,16 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
}
|
|
|
|
_updateThumbnailVisibility() {
|
|
- const useMenu = !this._settings.get_boolean('embed-previews');
|
|
- this.reactive = useMenu;
|
|
+ const usePreviews = this._settings.get_boolean('embed-previews');
|
|
+ this.reactive = !usePreviews;
|
|
|
|
- this._statusLabel.visible = useMenu;
|
|
- this._thumbnails.visible = !useMenu;
|
|
+ this._thumbnails.visible = usePreviews;
|
|
+ this._statusLabel.visible = !usePreviews;
|
|
|
|
- this.setMenu(useMenu
|
|
- ? new WorkspacesMenu(this)
|
|
- : null);
|
|
+ if (usePreviews)
|
|
+ this.add_style_class_name('previews');
|
|
+ else
|
|
+ this.remove_style_class_name('previews');
|
|
|
|
this._updateTopBarRedirect();
|
|
}
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From d79cb50745803a7e6e7dc663580f1fb233b9130a Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Thu, 22 May 2025 20:59:58 +0200
|
|
Subject: [PATCH 35/43] workspace-indicator: Show full name when using menu
|
|
|
|
With workspace names becoming a more prominent feature, it makes
|
|
sense to expose them without opening the menu.
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/405>
|
|
---
|
|
.../workspace-indicator/stylesheet-dark.css | 8 +++++
|
|
.../workspace-indicator/workspaceIndicator.js | 32 +++++++------------
|
|
2 files changed, 20 insertions(+), 20 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/stylesheet-dark.css b/extensions/workspace-indicator/stylesheet-dark.css
|
|
index 6719c05a..cb0c6e62 100644
|
|
--- a/extensions/workspace-indicator/stylesheet-dark.css
|
|
+++ b/extensions/workspace-indicator/stylesheet-dark.css
|
|
@@ -4,8 +4,16 @@
|
|
}
|
|
|
|
.workspace-indicator .status-label {
|
|
+ width: 8em;
|
|
padding: 0 8px;
|
|
}
|
|
+.workspace-indicator .status-label:ltr { padding-right: 4px; }
|
|
+.workspace-indicator .status-label:rtl { padding-left: 4px; }
|
|
+
|
|
+.workspace-indicator .system-status-icon {
|
|
+ padding: 0 !important;
|
|
+ margin: 0 !important;
|
|
+}
|
|
|
|
.workspace-indicator .workspaces-view.hfade {
|
|
-st-hfade-offset: 20px;
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 8184efbb..2cd3de5f 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -533,16 +533,23 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
});
|
|
this.add_actor(container);
|
|
|
|
- let workspaceManager = global.workspace_manager;
|
|
+ this._statusBox = new St.BoxLayout();
|
|
+ container.add_child(this._statusBox);
|
|
|
|
- this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
|
this._statusLabel = new St.Label({
|
|
style_class: 'status-label',
|
|
+ x_expand: true,
|
|
y_align: Clutter.ActorAlign.CENTER,
|
|
- text: this._getStatusText(),
|
|
+ text: this.menu.activeName,
|
|
});
|
|
+ this._statusBox.add_child(this._statusLabel);
|
|
+ this._statusBox.add_child(new St.Icon({
|
|
+ icon_name: 'pan-down-symbolic',
|
|
+ style_class: 'system-status-icon',
|
|
+ }));
|
|
|
|
- container.add_actor(this._statusLabel);
|
|
+ this.menu.connect('active-name-changed',
|
|
+ () => this._statusLabel.set_text(this.menu.activeName));
|
|
|
|
this._thumbnails = new WorkspacePreviews();
|
|
container.add_child(this._thumbnails);
|
|
@@ -555,11 +562,6 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
return Clutter.EVENT_STOP;
|
|
});
|
|
|
|
- this._workspaceManagerSignals = [
|
|
- workspaceManager.connect_after('workspace-switched',
|
|
- this._onWorkspaceSwitched.bind(this)),
|
|
- ];
|
|
-
|
|
this.connect('scroll-event',
|
|
(o, event) => this._thumbnails.handleScrollEvent(event));
|
|
|
|
@@ -593,7 +595,7 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this.reactive = !usePreviews;
|
|
|
|
this._thumbnails.visible = usePreviews;
|
|
- this._statusLabel.visible = !usePreviews;
|
|
+ this._statusBox.visible = !usePreviews;
|
|
|
|
if (usePreviews)
|
|
this.add_style_class_name('previews');
|
|
@@ -613,14 +615,4 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
? Clutter.OffscreenRedirect.ALWAYS
|
|
: Clutter.OffscreenRedirect.AUTOMATIC_FOR_OPACITY);
|
|
}
|
|
-
|
|
- _onWorkspaceSwitched() {
|
|
- this._currentWorkspace = global.workspace_manager.get_active_workspace_index();
|
|
- this._statusLabel.set_text(this._getStatusText());
|
|
- }
|
|
-
|
|
- _getStatusText() {
|
|
- const current = this._currentWorkspace + 1;
|
|
- return `${current}`;
|
|
- }
|
|
});
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From bbcbd818726d387a5720686d483c2c79463d84b6 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Mon, 9 Jun 2025 18:10:14 +0200
|
|
Subject: [PATCH 36/43] workspace-indicator: Add background when using name
|
|
label
|
|
|
|
Panel buttons are flat, so the name+arrow are not immediately
|
|
recognizable as a single control. Address this by adding a
|
|
background to the button when using the name label.
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/405>
|
|
---
|
|
extensions/workspace-indicator/stylesheet-dark.css | 14 ++++++++++++++
|
|
.../workspace-indicator/stylesheet-light.css | 14 ++++++++++++++
|
|
.../workspace-indicator/workspaceIndicator.js | 7 +++++--
|
|
3 files changed, 33 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/stylesheet-dark.css b/extensions/workspace-indicator/stylesheet-dark.css
|
|
index cb0c6e62..7a40664d 100644
|
|
--- a/extensions/workspace-indicator/stylesheet-dark.css
|
|
+++ b/extensions/workspace-indicator/stylesheet-dark.css
|
|
@@ -3,6 +3,20 @@
|
|
box-shadow: none !important;
|
|
}
|
|
|
|
+.workspace-indicator.name-label {
|
|
+ box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.17) !important;
|
|
+}
|
|
+.workspace-indicator.name-label:hover,
|
|
+.workspace-indicator.name-label:focus {
|
|
+ box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.28) !important;
|
|
+}
|
|
+.workspace-indicator.name-label:active {
|
|
+ box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.32) !important;
|
|
+}
|
|
+.workspace-indicator.name-label:active:hover {
|
|
+ box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.36) !important;
|
|
+}
|
|
+
|
|
.workspace-indicator .status-label {
|
|
width: 8em;
|
|
padding: 0 8px;
|
|
diff --git a/extensions/workspace-indicator/stylesheet-light.css b/extensions/workspace-indicator/stylesheet-light.css
|
|
index 049b6a38..5191923c 100644
|
|
--- a/extensions/workspace-indicator/stylesheet-light.css
|
|
+++ b/extensions/workspace-indicator/stylesheet-light.css
|
|
@@ -7,6 +7,20 @@
|
|
|
|
@import url("stylesheet-dark.css");
|
|
|
|
+.workspace-indicator.name-label {
|
|
+ box-shadow: inset 0 0 0 100px rgba(34, 34, 38, 0.17) !important;
|
|
+}
|
|
+.workspace-indicator.name-label:hover,
|
|
+.workspace-indicator.name-label:focus {
|
|
+ box-shadow: inset 0 0 0 100px rgba(34, 34, 38, 0.28) !important;
|
|
+}
|
|
+.workspace-indicator.name-label:active {
|
|
+ box-shadow: inset 0 0 0 100px rgba(34, 34, 38, 0.32) !important;
|
|
+}
|
|
+.workspace-indicator.name-label:active:hover {
|
|
+ box-shadow: inset 0 0 0 100px rgba(34, 34, 38, 0.36) !important;
|
|
+}
|
|
+
|
|
.workspace-indicator .workspace {
|
|
background-color: #ccc;
|
|
}
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 2cd3de5f..0a4f33bf 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -597,10 +597,13 @@ let WorkspaceIndicator = GObject.registerClass({
|
|
this._thumbnails.visible = usePreviews;
|
|
this._statusBox.visible = !usePreviews;
|
|
|
|
- if (usePreviews)
|
|
+ if (usePreviews) {
|
|
this.add_style_class_name('previews');
|
|
- else
|
|
+ this.remove_style_class_name('name-label');
|
|
+ } else {
|
|
this.remove_style_class_name('previews');
|
|
+ this.add_style_class_name('name-label');
|
|
+ }
|
|
|
|
this._updateTopBarRedirect();
|
|
}
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 98db3fef2833ced71efe41de14ffd81780b304e6 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Thu, 22 May 2025 21:07:08 +0200
|
|
Subject: [PATCH 37/43] workspace-indicator: Reimplement some libadwaita prefs
|
|
widgets
|
|
|
|
Upstream now makes more use of libawaita, so reimplement the API we
|
|
need to make backporting a bit less painful.
|
|
---
|
|
.../workspace-indicator/workspacePrefs.js | 239 ++++++++++++++++++
|
|
1 file changed, 239 insertions(+)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspacePrefs.js b/extensions/workspace-indicator/workspacePrefs.js
|
|
index 0bd4a58b..11155f8a 100644
|
|
--- a/extensions/workspace-indicator/workspacePrefs.js
|
|
+++ b/extensions/workspace-indicator/workspacePrefs.js
|
|
@@ -16,6 +16,245 @@ const N_ = e => e;
|
|
const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
|
|
const WORKSPACE_KEY = 'workspace-names';
|
|
|
|
+const PreferencesGroup = GObject.registerClass({
|
|
+ Properties: {
|
|
+ 'title': GObject.ParamSpec.string(
|
|
+ 'title', '', '',
|
|
+ GObject.ParamFlags.READWRITE,
|
|
+ null),
|
|
+ },
|
|
+}, class PreferencesGroup extends Gtk.Box {
|
|
+ _init(params) {
|
|
+ super._init({
|
|
+ ...params,
|
|
+ orientation: Gtk.Orientation.VERTICAL,
|
|
+ });
|
|
+
|
|
+ const titleLabel = new Gtk.Label({
|
|
+ halign: Gtk.Align.START,
|
|
+ });
|
|
+ titleLabel.get_style_context().add_class('heading');
|
|
+
|
|
+ this.bind_property('title',
|
|
+ titleLabel, 'label',
|
|
+ GObject.BindingFlags.SYNC_CREATE);
|
|
+ this.add(titleLabel);
|
|
+
|
|
+ this._list = new Gtk.ListBox({
|
|
+ selection_mode: Gtk.SelectionMode.NONE,
|
|
+ valign: Gtk.Align.START,
|
|
+ //show_separators: true,
|
|
+ });
|
|
+ this._list.get_style_context().add_class('boxed-list');
|
|
+ this.add(this._list);
|
|
+
|
|
+ this._list.connect('row-activated',
|
|
+ (l, row) => row.activate());
|
|
+ }
|
|
+
|
|
+ get title() {
|
|
+ return this._title || '';
|
|
+ }
|
|
+
|
|
+ set title(title) {
|
|
+ if (this._title === title)
|
|
+ return;
|
|
+
|
|
+ this._title = title;
|
|
+ this.notify('title');
|
|
+ }
|
|
+
|
|
+ append(child) {
|
|
+ this._list.add(child);
|
|
+ }
|
|
+
|
|
+ remove(child) {
|
|
+ this._list.remove(child);
|
|
+ }
|
|
+});
|
|
+
|
|
+const ActionRow = GObject.registerClass({
|
|
+ Properties: {
|
|
+ 'title': GObject.ParamSpec.string(
|
|
+ 'title', '', '',
|
|
+ GObject.ParamFlags.READWRITE,
|
|
+ null),
|
|
+ 'subtitle': GObject.ParamSpec.string(
|
|
+ 'subtitle', '', '',
|
|
+ GObject.ParamFlags.READWRITE,
|
|
+ null),
|
|
+ 'activatable-widget': GObject.ParamSpec.object(
|
|
+ 'activatable-widget', '', '',
|
|
+ GObject.ParamFlags.READWRITE,
|
|
+ Gtk.Widget),
|
|
+ },
|
|
+}, class ActionRow extends Gtk.ListBoxRow {
|
|
+ _init(params) {
|
|
+ super._init(params);
|
|
+
|
|
+ const provider = new Gtk.CssProvider();
|
|
+ provider.load_from_data(`* {
|
|
+ /*border-spacing: 6px 6px;*/
|
|
+ min-height: 40px;
|
|
+ margin-left: 12px;
|
|
+ margin-right: 12px;
|
|
+ }`);
|
|
+
|
|
+ const mainBox = new Gtk.Box({
|
|
+ valign: Gtk.Align.CENTER,
|
|
+ hexpand: false,
|
|
+ });
|
|
+ mainBox.get_style_context().add_provider(provider,
|
|
+ Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
|
|
+ this.add(mainBox);
|
|
+
|
|
+ this._prefixes = new Gtk.Box({
|
|
+ visible: false,
|
|
+ });
|
|
+ mainBox.add(this._prefixes);
|
|
+
|
|
+ const titleBox = new Gtk.Box({
|
|
+ orientation: Gtk.Orientation.VERTICAL,
|
|
+ valign: Gtk.Align.CENTER,
|
|
+ hexpand: true,
|
|
+ });
|
|
+ mainBox.add(titleBox);
|
|
+
|
|
+ this._suffixes = new Gtk.Box({
|
|
+ visible: false,
|
|
+ });
|
|
+ mainBox.add(this._suffixes);
|
|
+
|
|
+ const titleLabel = new Gtk.Label({
|
|
+ lines: 0,
|
|
+ wrap: true,
|
|
+ wrap_mode: Pango.WrapMode.WORD_CHAR,
|
|
+ xalign: 0,
|
|
+ });
|
|
+
|
|
+ this.bind_property('title',
|
|
+ titleLabel, 'label',
|
|
+ GObject.BindingFlags.SYNC_CREATE);
|
|
+ titleBox.add(titleLabel);
|
|
+
|
|
+ const subtitleLabel = new Gtk.Label({
|
|
+ ellipsize: Pango.EllipsizeMode.NONE,
|
|
+ lines: 0,
|
|
+ wrap: true,
|
|
+ wrap_mode: Pango.WrapMode.WORD_CHAR,
|
|
+ xalign: 0,
|
|
+ no_show_all: true,
|
|
+ visible: this.subtitle.length > 0,
|
|
+ });
|
|
+ subtitleLabel.get_style_context().add_class('dim-label');
|
|
+
|
|
+ this.bind_property('subtitle',
|
|
+ subtitleLabel, 'label',
|
|
+ GObject.BindingFlags.SYNC_CREATE);
|
|
+ titleBox.add(subtitleLabel);
|
|
+ }
|
|
+
|
|
+ get title() {
|
|
+ return this._title || '';
|
|
+ }
|
|
+
|
|
+ set title(title) {
|
|
+ if (this._title === title)
|
|
+ return;
|
|
+
|
|
+ this._title = title;
|
|
+ this.notify('title');
|
|
+ }
|
|
+
|
|
+ get subtitle() {
|
|
+ return this._subtitle || '';
|
|
+ }
|
|
+
|
|
+ set subtitle(subtitle) {
|
|
+ if (this._subtitle === subtitle)
|
|
+ return;
|
|
+
|
|
+ this._subtitle = subtitle;
|
|
+ this.notify('subtitle');
|
|
+ }
|
|
+
|
|
+ get activitable_widget() {
|
|
+ return this._activatableWidget;
|
|
+ }
|
|
+
|
|
+ set activatable_widget(widget) {
|
|
+ if (this._activatableWidget === widget)
|
|
+ return;
|
|
+
|
|
+ this._activatableWidget = widget;
|
|
+ this.notify('activatable-widget');
|
|
+ }
|
|
+
|
|
+ add_prefix(child) {
|
|
+ this._prefixes.add(child);
|
|
+ this._prefixes.set_visible(true);
|
|
+ }
|
|
+
|
|
+ add_suffix(child) {
|
|
+ this._suffixes.add(child);
|
|
+ this._suffixes.set_visible(true);
|
|
+ }
|
|
+
|
|
+ activate() {
|
|
+ if (this._activatableWidget)
|
|
+ this._activatableWidget.mnemonic_activate(false);
|
|
+ }
|
|
+});
|
|
+
|
|
+const SpinRow = GObject.registerClass({
|
|
+ Properties: {
|
|
+ 'adjustment': GObject.ParamSpec.object(
|
|
+ 'adjustment', '', '',
|
|
+ GObject.ParamFlags.READWRITE,
|
|
+ Gtk.Adjustment),
|
|
+ 'value': GObject.ParamSpec.double(
|
|
+ 'value', '', '',
|
|
+ GObject.ParamFlags.READWRITE,
|
|
+ -Infinity, Infinity, 0),
|
|
+ },
|
|
+}, class SpinRow extends ActionRow {
|
|
+ _init(params) {
|
|
+ this._spinButton = new Gtk.SpinButton({
|
|
+ valign: Gtk.Align.CENTER,
|
|
+ hexpand: true,
|
|
+ xalign: 1,
|
|
+ });
|
|
+ super._init(params);
|
|
+ this.add_suffix(this._spinButton);
|
|
+ }
|
|
+
|
|
+ get adjustment() {
|
|
+ return this._spinButton.get_adjustment();
|
|
+ }
|
|
+
|
|
+ set adjustment(adj) {
|
|
+ if (this.adjustment === adj)
|
|
+ return;
|
|
+
|
|
+ this._spinButton.set_adjustment(adj);
|
|
+ this.notify('adjustment');
|
|
+ }
|
|
+
|
|
+ get value() {
|
|
+ return this._spinButton.get_value();
|
|
+ }
|
|
+
|
|
+ set value(value) {
|
|
+ const EPSILON = 0.005;
|
|
+
|
|
+ if (Math.abs(this.value, value) < EPSILON)
|
|
+ return;
|
|
+
|
|
+ this._spinButton.set_value(value);
|
|
+ this.notify('value');
|
|
+ }
|
|
+});
|
|
+
|
|
const GeneralGroup = GObject.registerClass(
|
|
class GeneralGroup extends Gtk.Box {
|
|
_init() {
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From c3d54e0e0c120ad09f15f9c95d215e14e8f0334d Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Sun, 29 Jun 2025 21:26:40 +0200
|
|
Subject: [PATCH 38/43] workspace-indicator: Refine preview settings
|
|
|
|
Add a group title, and change the single switch row to radio rows
|
|
to explicitly choose between "Previews" and "Workspace Name".
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/405>
|
|
---
|
|
.../workspace-indicator/workspacePrefs.js | 35 ++++++++++++-------
|
|
1 file changed, 22 insertions(+), 13 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspacePrefs.js b/extensions/workspace-indicator/workspacePrefs.js
|
|
index 11155f8a..e33d4716 100644
|
|
--- a/extensions/workspace-indicator/workspacePrefs.js
|
|
+++ b/extensions/workspace-indicator/workspacePrefs.js
|
|
@@ -256,29 +256,38 @@ const SpinRow = GObject.registerClass({
|
|
});
|
|
|
|
const GeneralGroup = GObject.registerClass(
|
|
-class GeneralGroup extends Gtk.Box {
|
|
+class GeneralGroup extends PreferencesGroup {
|
|
_init() {
|
|
super._init({
|
|
- orientation: Gtk.Orientation.VERTICAL,
|
|
+ title: _('Indicator'),
|
|
});
|
|
|
|
- const row = new Gtk.Box();
|
|
- this.add(row);
|
|
-
|
|
- row.add(new Gtk.Label({
|
|
- label: _('Show Previews'),
|
|
- }));
|
|
+ const previewCheck = new Gtk.RadioButton();
|
|
+ const previewRow = new ActionRow({
|
|
+ title: _('Previews'),
|
|
+ activatable_widget: previewCheck,
|
|
+ });
|
|
+ previewRow.add_prefix(previewCheck);
|
|
+ this.append(previewRow);
|
|
|
|
- const sw = new Gtk.Switch({
|
|
- hexpand: true,
|
|
- halign: Gtk.Align.END,
|
|
+ const nameCheck = new Gtk.RadioButton({
|
|
+ group: previewCheck,
|
|
+ });
|
|
+ const nameRow = new ActionRow({
|
|
+ title: _('Workspace Name'),
|
|
+ activatable_widget: nameCheck,
|
|
});
|
|
- row.add(sw);
|
|
+ nameRow.add_prefix(nameCheck);
|
|
+ this.append(nameRow);
|
|
|
|
const settings = ExtensionUtils.getSettings();
|
|
+ if (settings.get_boolean('embed-previews'))
|
|
+ previewCheck.active = true;
|
|
+ else
|
|
+ nameCheck.active = true;
|
|
|
|
settings.bind('embed-previews',
|
|
- sw, 'active',
|
|
+ previewCheck, 'active',
|
|
Gio.SettingsBindFlags.DEFAULT);
|
|
}
|
|
});
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 2ce2e4439e13d1fa48502fdda7cff7dd41302482 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Thu, 22 May 2025 16:20:05 +0200
|
|
Subject: [PATCH 39/43] workspace-indicator: Include workspace settings
|
|
|
|
While the "Multitasking" panel in Settings already exposes workspace
|
|
settings, it makes sense to expose them in our prefs dialog as well
|
|
where they are more in context.
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/405>
|
|
---
|
|
.../workspace-indicator/workspacePrefs.js | 67 +++++++++++++++++++
|
|
1 file changed, 67 insertions(+)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspacePrefs.js b/extensions/workspace-indicator/workspacePrefs.js
|
|
index e33d4716..316666ed 100644
|
|
--- a/extensions/workspace-indicator/workspacePrefs.js
|
|
+++ b/extensions/workspace-indicator/workspacePrefs.js
|
|
@@ -292,6 +292,72 @@ class GeneralGroup extends PreferencesGroup {
|
|
}
|
|
});
|
|
|
|
+const BehaviorGroup = GObject.registerClass(
|
|
+class BehaviorGroup extends PreferencesGroup {
|
|
+ _init() {
|
|
+ super._init({
|
|
+ title: _('Behavior'),
|
|
+ });
|
|
+
|
|
+ const dynamicCheck = new Gtk.RadioButton();
|
|
+ const dynamicRow = new ActionRow({
|
|
+ title: _('Dynamic'),
|
|
+ subtitle: _('Automatically removes empty workspaces.'),
|
|
+ activatable_widget: dynamicCheck,
|
|
+ });
|
|
+ dynamicRow.add_prefix(dynamicCheck);
|
|
+ this.append(dynamicRow);
|
|
+
|
|
+ const fixedCheck = new Gtk.RadioButton({
|
|
+ group: dynamicCheck,
|
|
+ });
|
|
+ const fixedRow = new ActionRow({
|
|
+ title: _('Fixed Number'),
|
|
+ subtitle: _('Specify a number of permanent workspaces.'),
|
|
+ activatable_widget: fixedCheck,
|
|
+ });
|
|
+ fixedRow.add_prefix(fixedCheck);
|
|
+ this.append(fixedRow);
|
|
+
|
|
+ const adjustment = new Gtk.Adjustment({
|
|
+ lower: 1,
|
|
+ step_increment: 1,
|
|
+ value: 4,
|
|
+ upper: 36, // hard limit in mutter
|
|
+ });
|
|
+ const numRow = new SpinRow({
|
|
+ title: _('Number of Workspaces'),
|
|
+ adjustment,
|
|
+ });
|
|
+ this.append(numRow);
|
|
+
|
|
+ const mutterSettings = new Gio.Settings({
|
|
+ schema_id: 'org.gnome.mutter',
|
|
+ });
|
|
+
|
|
+ if (mutterSettings.get_boolean('dynamic-workspaces'))
|
|
+ dynamicCheck.active = true;
|
|
+ else
|
|
+ fixedCheck.active = true;
|
|
+
|
|
+ mutterSettings.bind('dynamic-workspaces',
|
|
+ dynamicCheck, 'active',
|
|
+ Gio.SettingsBindFlags.DEFAULT);
|
|
+
|
|
+ const desktopSettings = new Gio.Settings({
|
|
+ schema_id: 'org.gnome.desktop.wm.preferences',
|
|
+ });
|
|
+
|
|
+ desktopSettings.bind('num-workspaces',
|
|
+ numRow, 'value',
|
|
+ Gio.SettingsBindFlags.DEFAULT);
|
|
+
|
|
+ fixedCheck.bind_property('active',
|
|
+ numRow, 'sensitive',
|
|
+ GObject.BindingFlags.SYNC_CREATE);
|
|
+ }
|
|
+});
|
|
+
|
|
const WorkspaceNameModel = GObject.registerClass(
|
|
class WorkspaceNameModel extends Gtk.ListStore {
|
|
_init(params) {
|
|
@@ -420,6 +486,7 @@ class WorkspacesPage extends Gtk.ScrolledWindow {
|
|
this.add(box);
|
|
|
|
box.add(new GeneralGroup());
|
|
+ box.add(new BehaviorGroup());
|
|
|
|
box.add(new Gtk.Label({
|
|
label: '<b>%s</b>'.format(_('Workspace Names')),
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 55746c9d3ef546feed2e473382c42f11245ea82f Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 28 May 2025 21:01:08 +0200
|
|
Subject: [PATCH 40/43] workspace-indicator: Allow changing workspace names
|
|
from menu
|
|
|
|
Instead of requiring the user to open the prefs dialog to change
|
|
workspace names, make the menu items themselves editable.
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/405>
|
|
---
|
|
.../workspace-indicator/stylesheet-dark.css | 48 +++++++
|
|
.../workspace-indicator/stylesheet-light.css | 16 +++
|
|
.../workspace-indicator/workspaceIndicator.js | 130 +++++++++++++++++-
|
|
3 files changed, 192 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/stylesheet-dark.css b/extensions/workspace-indicator/stylesheet-dark.css
|
|
index 7a40664d..a74d25b5 100644
|
|
--- a/extensions/workspace-indicator/stylesheet-dark.css
|
|
+++ b/extensions/workspace-indicator/stylesheet-dark.css
|
|
@@ -58,3 +58,51 @@
|
|
.workspace-indicator-window-preview.active {
|
|
background-color: #d4d4d4;
|
|
}
|
|
+
|
|
+.workspace-indicator-menu {
|
|
+ min-width: 17em;
|
|
+}
|
|
+
|
|
+.workspace-indicator-menu .editable-menu-item.popup-menu-item {
|
|
+ padding: 3px 12px;
|
|
+}
|
|
+
|
|
+.workspace-indicator-menu .editable-menu-item .icon-button {
|
|
+ border-radius: 99px;
|
|
+ padding: 6px;
|
|
+}
|
|
+
|
|
+.workspace-indicator-menu .editable-menu-item .icon-button.flat {
|
|
+ background-color: transparent;
|
|
+}
|
|
+
|
|
+.workspace-indicator-menu .editable-menu-item .icon-button.flat:hover {
|
|
+ background-color: rgba(255, 255, 255, 0.1);
|
|
+}
|
|
+
|
|
+.workspace-indicator-menu .editable-menu-item .icon-button.flat:active {
|
|
+ background-color: rgba(255, 255, 255, 0.15);
|
|
+}
|
|
+
|
|
+.workspace-indicator-menu .editable-menu-item .icon-button.flat:checked {
|
|
+ color: white;
|
|
+ background-color: #3584e4;
|
|
+}
|
|
+
|
|
+.workspace-indicator-menu .editable-menu-item .icon-button.flat:checked:hover {
|
|
+ background-color: #629fea;
|
|
+}
|
|
+
|
|
+.workspace-indicator-menu .editable-menu-item .icon-button.flat:checked:active {
|
|
+ background-color: #78aded;
|
|
+}
|
|
+
|
|
+.workspace-indicator-menu .editable-menu-item .label {
|
|
+ padding: 0 11px;
|
|
+ width: 6.5em;
|
|
+}
|
|
+
|
|
+.workspace-indicator-menu .editable-menu-item .entry {
|
|
+ padding: 9px 9px;
|
|
+ width: 6.5em;
|
|
+}
|
|
diff --git a/extensions/workspace-indicator/stylesheet-light.css b/extensions/workspace-indicator/stylesheet-light.css
|
|
index 5191923c..e4f2b45a 100644
|
|
--- a/extensions/workspace-indicator/stylesheet-light.css
|
|
+++ b/extensions/workspace-indicator/stylesheet-light.css
|
|
@@ -37,3 +37,19 @@
|
|
.workspace-indicator-window-preview.active {
|
|
background-color: #f6f5f4;
|
|
}
|
|
+
|
|
+.workspace-indicator-menu .editable-menu-item .icon-button.flat:hover {
|
|
+ background-color: rgba(0, 0, 0, 0.1);
|
|
+}
|
|
+
|
|
+.workspace-indicator-menu .editable-menu-item .icon-button.flat:active {
|
|
+ background-color: rgba(0, 0, 0, 0.15);
|
|
+}
|
|
+
|
|
+.workspace-indicator-menu .editable-menu-item .icon-button.flat:checked:hover {
|
|
+ background-color: #1b6acb;
|
|
+}
|
|
+
|
|
+.workspace-indicator-menu .editable-menu-item .icon-button.flat:checked:active {
|
|
+ background-color: #185fb4;
|
|
+}
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 0a4f33bf..5a8a819c 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -1,4 +1,4 @@
|
|
-const { Clutter, Gio, GLib, GObject, Meta, St } = imports.gi;
|
|
+const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
|
|
|
|
const DND = imports.ui.dnd;
|
|
const ExtensionUtils = imports.misc.extensionUtils;
|
|
@@ -7,6 +7,8 @@ const PanelMenu = imports.ui.panelMenu;
|
|
const PopupMenu = imports.ui.popupMenu;
|
|
const Tweener = imports.ui.tweener;
|
|
|
|
+const Signals = imports.signals;
|
|
+
|
|
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
|
const _ = Gettext.gettext;
|
|
|
|
@@ -404,6 +406,122 @@ const WorkspacePreviews = GObject.registerClass({
|
|
}
|
|
});
|
|
|
|
+class EditableMenuItem extends PopupMenu.PopupBaseMenuItem {
|
|
+ constructor() {
|
|
+ super({
|
|
+ style_class: 'editable-menu-item',
|
|
+ });
|
|
+ this.actor.get_accessible().set_description(0,
|
|
+ _('Press %s to edit').format('e'));
|
|
+
|
|
+ this._ornamentLabel.y_align = Clutter.ActorAlign.CENTER;
|
|
+
|
|
+ const stack = new Shell.Stack({
|
|
+ x_expand: true,
|
|
+ x_align: Clutter.ActorAlign.START,
|
|
+ });
|
|
+ this.actor.add_child(stack);
|
|
+
|
|
+ this.label = new St.Label({
|
|
+ style_class: 'label',
|
|
+ y_align: Clutter.ActorAlign.CENTER,
|
|
+ });
|
|
+ stack.add_child(this.label);
|
|
+ this.actor.label_actor = this.label;
|
|
+
|
|
+ this._entry = new St.Entry({
|
|
+ style_class: 'entry',
|
|
+ opacity: 0,
|
|
+ reactive: false,
|
|
+ });
|
|
+ stack.add_child(this._entry);
|
|
+
|
|
+ this.label.bind_property('text',
|
|
+ this._entry, 'text',
|
|
+ GObject.BindingFlags.DEFAULT);
|
|
+
|
|
+ this._entry.clutter_text.connect('activate',
|
|
+ () => this._stopEditing());
|
|
+
|
|
+ this._editButton = new St.Button({
|
|
+ style_class: 'icon-button flat',
|
|
+ child: new St.Icon({
|
|
+ icon_name: 'document-edit-symbolic',
|
|
+ icon_size: 16,
|
|
+ }),
|
|
+ button_mask: St.ButtonMask.ONE,
|
|
+ toggle_mode: true,
|
|
+ });
|
|
+ this._editButton.set_x_align(Clutter.ActorAlign.END);
|
|
+ this._editButton.set_y_align(Clutter.ActorAlign.CENTER);
|
|
+ this.actor.add_child(this._editButton);
|
|
+
|
|
+ this._editButton.connect('notify::checked', () => {
|
|
+ if (this._editButton.checked) {
|
|
+ this._editButton.child.icon_name = 'object-select-symbolic';
|
|
+ this._startEditing();
|
|
+ } else {
|
|
+ this._editButton.child.icon_name = 'document-edit-symbolic';
|
|
+ this._stopEditing();
|
|
+ }
|
|
+ });
|
|
+ this.actor.connect('key-release-event', (o, event) => {
|
|
+ if (event.get_key_symbol() === Clutter.KEY_e)
|
|
+ this._editButton.checked = true;
|
|
+ });
|
|
+
|
|
+ this._keyFocusId = global.stage.connect('notify::key-focus', () => {
|
|
+ const {keyFocus} = global.stage;
|
|
+ if (!keyFocus || !this.actor.contains(keyFocus))
|
|
+ this._stopEditing();
|
|
+ });
|
|
+
|
|
+ this.actor.connect('destroy', () => {
|
|
+ global.stage.disconnect(this._keyFocusId);
|
|
+ delete this._keyFocusId;
|
|
+ });
|
|
+ }
|
|
+
|
|
+ _switchActor(from, to) {
|
|
+ to.reactive = true;
|
|
+ Tweener.addTween(to, {
|
|
+ opacity: 255,
|
|
+ time: 0.3,
|
|
+ transition: 'easeOutQuad',
|
|
+ });
|
|
+
|
|
+ Tweener.addTween(from, {
|
|
+ opacity: 0,
|
|
+ time: 0.3,
|
|
+ transition: 'easeOutQuad',
|
|
+ onComplete: () => {
|
|
+ from.reactive = false;
|
|
+ },
|
|
+ });
|
|
+ }
|
|
+
|
|
+ _startEditing() {
|
|
+ this._switchActor(this.label, this._entry);
|
|
+
|
|
+ this._entry.clutter_text.set_selection(0, -1);
|
|
+ this._entry.clutter_text.grab_key_focus();
|
|
+ }
|
|
+
|
|
+ _stopEditing() {
|
|
+ if (this.label.text !== this._entry.text) {
|
|
+ this.label.text = this._entry.text;
|
|
+ this.emit('edited');
|
|
+ }
|
|
+
|
|
+ if (this._editButton.checked)
|
|
+ this._editButton.checked = false;
|
|
+
|
|
+ this._switchActor(this._entry, this.label);
|
|
+ this.actor.navigate_focus(this.actor, St.DirectionType.TAB_FORWARD, false);
|
|
+ }
|
|
+}
|
|
+Signals.addSignalMethods(EditableMenuItem.prototype);
|
|
+
|
|
class WorkspacesMenu extends PopupMenu.PopupMenu {
|
|
constructor(sourceActor) {
|
|
super(sourceActor, 0.5, St.Side.TOP);
|
|
@@ -461,13 +579,21 @@ class WorkspacesMenu extends PopupMenu.PopupMenu {
|
|
|
|
const section = this._workspacesSection.actor;
|
|
while (section.get_n_children() < nWorkspaces) {
|
|
- const item = new PopupMenu.PopupMenuItem('');
|
|
+ const item = new EditableMenuItem();
|
|
item.connect('activate', (o, event) => {
|
|
const index = section.get_children().indexOf(item.actor);
|
|
const workspace = workspaceManager.get_workspace_by_index(index);
|
|
if (workspace)
|
|
workspace.activate(event.get_time());
|
|
});
|
|
+ item.connect('edited', () => {
|
|
+ const nLabels = section.get_n_children();
|
|
+ const oldNames = this._desktopSettings.get_strv('workspace-names');
|
|
+ const newNames =
|
|
+ section.get_children().map(c => c._delegate.label.text);
|
|
+ this._desktopSettings.set_strv('workspace-names',
|
|
+ [...newNames, ...oldNames.slice(nLabels)]);
|
|
+ });
|
|
this._workspacesSection.addMenuItem(item);
|
|
}
|
|
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From 9fd65412c1ebdb6c4c4f1026f95de72e985dcd1d Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Wed, 28 May 2025 21:04:36 +0200
|
|
Subject: [PATCH 41/43] workspace-indicator: Remove workspace names from prefs
|
|
|
|
Now that names can be changed from the extension itself, we no
|
|
longer need to expose them in the prefs dialog.
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/405>
|
|
---
|
|
.../workspace-indicator/workspacePrefs.js | 181 +-----------------
|
|
1 file changed, 1 insertion(+), 180 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/workspacePrefs.js b/extensions/workspace-indicator/workspacePrefs.js
|
|
index 316666ed..bc4b3d01 100644
|
|
--- a/extensions/workspace-indicator/workspacePrefs.js
|
|
+++ b/extensions/workspace-indicator/workspacePrefs.js
|
|
@@ -4,17 +4,13 @@
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
/* exported WorkspacesPage */
|
|
-const { Gio, GLib, GObject, Gtk, Pango } = imports.gi;
|
|
+const { Gio, GObject, Gtk, Pango } = imports.gi;
|
|
|
|
const ExtensionUtils = imports.misc.extensionUtils;
|
|
const Me = ExtensionUtils.getCurrentExtension();
|
|
|
|
const Gettext = imports.gettext.domain(Me.metadata['gettext-domain']);
|
|
const _ = Gettext.gettext;
|
|
-const N_ = e => e;
|
|
-
|
|
-const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
|
|
-const WORKSPACE_KEY = 'workspace-names';
|
|
|
|
const PreferencesGroup = GObject.registerClass({
|
|
Properties: {
|
|
@@ -358,114 +354,6 @@ class BehaviorGroup extends PreferencesGroup {
|
|
}
|
|
});
|
|
|
|
-const WorkspaceNameModel = GObject.registerClass(
|
|
-class WorkspaceNameModel extends Gtk.ListStore {
|
|
- _init(params) {
|
|
- super._init(params);
|
|
- this.set_column_types([GObject.TYPE_STRING]);
|
|
-
|
|
- this.Columns = {
|
|
- LABEL: 0,
|
|
- };
|
|
-
|
|
- this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA });
|
|
- //this._settings.connect('changed::workspace-names', this._reloadFromSettings.bind(this));
|
|
-
|
|
- this._reloadFromSettings();
|
|
-
|
|
- // overriding class closure doesn't work, because GtkTreeModel
|
|
- // plays tricks with marshallers and class closures
|
|
- this.connect('row-changed', this._onRowChanged.bind(this));
|
|
- this.connect('row-inserted', this._onRowInserted.bind(this));
|
|
- this.connect('row-deleted', this._onRowDeleted.bind(this));
|
|
- }
|
|
-
|
|
- _reloadFromSettings() {
|
|
- if (this._preventChanges)
|
|
- return;
|
|
- this._preventChanges = true;
|
|
-
|
|
- let newNames = this._settings.get_strv(WORKSPACE_KEY);
|
|
-
|
|
- let i = 0;
|
|
- let [ok, iter] = this.get_iter_first();
|
|
- while (ok && i < newNames.length) {
|
|
- this.set(iter, [this.Columns.LABEL], [newNames[i]]);
|
|
-
|
|
- ok = this.iter_next(iter);
|
|
- i++;
|
|
- }
|
|
-
|
|
- while (ok)
|
|
- ok = this.remove(iter);
|
|
-
|
|
- for ( ; i < newNames.length; i++) {
|
|
- iter = this.append();
|
|
- this.set(iter, [this.Columns.LABEL], [newNames[i]]);
|
|
- }
|
|
-
|
|
- this._preventChanges = false;
|
|
- }
|
|
-
|
|
- _onRowChanged(self, path, iter) {
|
|
- if (this._preventChanges)
|
|
- return;
|
|
- this._preventChanges = true;
|
|
-
|
|
- let index = path.get_indices()[0];
|
|
- let names = this._settings.get_strv(WORKSPACE_KEY);
|
|
-
|
|
- if (index >= names.length) {
|
|
- // fill with blanks
|
|
- for (let i = names.length; i <= index; i++)
|
|
- names[i] = '';
|
|
- }
|
|
-
|
|
- names[index] = this.get_value(iter, this.Columns.LABEL);
|
|
-
|
|
- this._settings.set_strv(WORKSPACE_KEY, names);
|
|
-
|
|
- this._preventChanges = false;
|
|
- }
|
|
-
|
|
- _onRowInserted(self, path, iter) {
|
|
- if (this._preventChanges)
|
|
- return;
|
|
- this._preventChanges = true;
|
|
-
|
|
- let index = path.get_indices()[0];
|
|
- let names = this._settings.get_strv(WORKSPACE_KEY);
|
|
- let label = this.get_value(iter, this.Columns.LABEL) || '';
|
|
- names.splice(index, 0, label);
|
|
-
|
|
- this._settings.set_strv(WORKSPACE_KEY, names);
|
|
-
|
|
- this._preventChanges = false;
|
|
- }
|
|
-
|
|
- _onRowDeleted(self, path) {
|
|
- if (this._preventChanges)
|
|
- return;
|
|
- this._preventChanges = true;
|
|
-
|
|
- let index = path.get_indices()[0];
|
|
- let names = this._settings.get_strv(WORKSPACE_KEY);
|
|
-
|
|
- if (index >= names.length)
|
|
- return;
|
|
-
|
|
- names.splice(index, 1);
|
|
-
|
|
- // compact the array
|
|
- for (let i = names.length - 1; i >= 0 && !names[i]; i++)
|
|
- names.pop();
|
|
-
|
|
- this._settings.set_strv(WORKSPACE_KEY, names);
|
|
-
|
|
- this._preventChanges = false;
|
|
- }
|
|
-});
|
|
-
|
|
var WorkspacesPage = GObject.registerClass(
|
|
class WorkspacesPage extends Gtk.ScrolledWindow {
|
|
_init() {
|
|
@@ -488,73 +376,6 @@ class WorkspacesPage extends Gtk.ScrolledWindow {
|
|
box.add(new GeneralGroup());
|
|
box.add(new BehaviorGroup());
|
|
|
|
- box.add(new Gtk.Label({
|
|
- label: '<b>%s</b>'.format(_('Workspace Names')),
|
|
- use_markup: true,
|
|
- margin_bottom: 6,
|
|
- hexpand: true,
|
|
- halign: Gtk.Align.START
|
|
- }));
|
|
-
|
|
- this._store = new WorkspaceNameModel();
|
|
- this._treeView = new Gtk.TreeView({
|
|
- model: this._store,
|
|
- headers_visible: false,
|
|
- reorderable: true,
|
|
- hexpand: true,
|
|
- vexpand: true
|
|
- });
|
|
-
|
|
- let column = new Gtk.TreeViewColumn({ title: _('Name') });
|
|
- let renderer = new Gtk.CellRendererText({ editable: true });
|
|
- renderer.connect('edited', this._cellEdited.bind(this));
|
|
- column.pack_start(renderer, true);
|
|
- column.add_attribute(renderer, 'text', this._store.Columns.LABEL);
|
|
- this._treeView.append_column(column);
|
|
-
|
|
- box.add(this._treeView);
|
|
-
|
|
- let toolbar = new Gtk.Toolbar({ icon_size: Gtk.IconSize.SMALL_TOOLBAR });
|
|
- toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR);
|
|
-
|
|
- let newButton = new Gtk.ToolButton({ icon_name: 'list-add-symbolic' });
|
|
- newButton.connect('clicked', this._newClicked.bind(this));
|
|
- toolbar.add(newButton);
|
|
-
|
|
- let delButton = new Gtk.ToolButton({ icon_name: 'list-remove-symbolic' });
|
|
- delButton.connect('clicked', this._delClicked.bind(this));
|
|
- toolbar.add(delButton);
|
|
-
|
|
- let selection = this._treeView.get_selection();
|
|
- selection.connect('changed', () => {
|
|
- delButton.sensitive = selection.count_selected_rows() > 0;
|
|
- });
|
|
- delButton.sensitive = selection.count_selected_rows() > 0;
|
|
-
|
|
- box.add(toolbar);
|
|
-
|
|
this.show_all();
|
|
}
|
|
-
|
|
- _cellEdited(renderer, path, newText) {
|
|
- let [ok, iter] = this._store.get_iter_from_string(path);
|
|
-
|
|
- if (ok)
|
|
- this._store.set(iter, [this._store.Columns.LABEL], [newText]);
|
|
- }
|
|
-
|
|
- _newClicked() {
|
|
- let iter = this._store.append();
|
|
- let index = this._store.get_path(iter).get_indices()[0];
|
|
-
|
|
- let label = _('Workspace %d').format(index + 1);
|
|
- this._store.set(iter, [this._store.Columns.LABEL], [label]);
|
|
- }
|
|
-
|
|
- _delClicked() {
|
|
- let [any, model_, iter] = this._treeView.get_selection().get_selected();
|
|
-
|
|
- if (any)
|
|
- this._store.remove(iter);
|
|
- }
|
|
});
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From f6520c27519ae3bf7a9aa9c52eeaa2a908cbe44f Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Fri, 30 May 2025 16:39:22 +0200
|
|
Subject: [PATCH 42/43] window-list: Adjust to workspace-indicator changes
|
|
|
|
Keep the `.panel-button` class to get the expected hover/focus/active
|
|
styling when using a regular menu button, but remove the horizontal
|
|
padding when using previews for fittsability.
|
|
|
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/405>
|
|
---
|
|
extensions/window-list/extension.js | 6 ------
|
|
extensions/window-list/stylesheet.css | 5 +++++
|
|
2 files changed, 5 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js
|
|
index b2357939..37b5ea09 100644
|
|
--- a/extensions/window-list/extension.js
|
|
+++ b/extensions/window-list/extension.js
|
|
@@ -1236,12 +1236,6 @@ class WindowList {
|
|
|
|
const BottomWorkspaceIndicator = GObject.registerClass(
|
|
class BottomWorkspaceIndicator extends WorkspaceIndicator {
|
|
- _init(params) {
|
|
- super._init(params);
|
|
-
|
|
- this.remove_style_class_name('panel-button');
|
|
- }
|
|
-
|
|
setMenu(menu) {
|
|
super.setMenu(menu);
|
|
|
|
diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css
|
|
index 349404c5..7da8ac7a 100644
|
|
--- a/extensions/window-list/stylesheet.css
|
|
+++ b/extensions/window-list/stylesheet.css
|
|
@@ -13,6 +13,11 @@
|
|
height: 2.25em;
|
|
}
|
|
|
|
+.window-list-workspace-indicator.previews {
|
|
+ -natural-hpadding: 0 !important;
|
|
+ -minimum-hpadding: 0 !important;
|
|
+}
|
|
+
|
|
.window-list {
|
|
spacing: 2px;
|
|
font-size: 10pt;
|
|
--
|
|
2.50.0
|
|
|
|
|
|
From cea785875ba9f155031ab94cbb3a61abba546252 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
Date: Tue, 2 Jul 2024 19:04:10 +0200
|
|
Subject: [PATCH 43/43] workspace-indicator: Re-fittsify workspace previews
|
|
|
|
For the window-list extension, it is important that the workspace
|
|
previews extend to the bottom edge for easier click targets.
|
|
|
|
That broke while merging the code with the workspace-indicator,
|
|
fix it again by moving the padding from the parent box into the
|
|
thumbnail children.
|
|
---
|
|
.../workspace-indicator/stylesheet-dark.css | 16 ++++++++++++-
|
|
.../workspace-indicator/workspaceIndicator.js | 23 +++++++++++++++----
|
|
2 files changed, 33 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/extensions/workspace-indicator/stylesheet-dark.css b/extensions/workspace-indicator/stylesheet-dark.css
|
|
index a74d25b5..acf63524 100644
|
|
--- a/extensions/workspace-indicator/stylesheet-dark.css
|
|
+++ b/extensions/workspace-indicator/stylesheet-dark.css
|
|
@@ -34,10 +34,24 @@
|
|
}
|
|
|
|
.workspace-indicator .workspaces-box {
|
|
- padding: 5px;
|
|
spacing: 3px;
|
|
}
|
|
|
|
+.workspace-indicator .workspace-box {
|
|
+ padding-top: 5px;
|
|
+ padding-bottom: 5px;
|
|
+}
|
|
+
|
|
+.workspace-indicator StButton:first-child:ltr > .workspace-box,
|
|
+.workspace-indicator StButton:last-child:rtl > .workspace-box {
|
|
+ padding-left: 5px;
|
|
+}
|
|
+
|
|
+.workspace-indicator StButton:last-child:ltr > .workspace-box,
|
|
+.workspace-indicator StButton:first-child:rtl > .workspace-box {
|
|
+ padding-right: 5px;
|
|
+}
|
|
+
|
|
.workspace-indicator .workspace {
|
|
width: 52px;
|
|
border: 1px solid transparent;
|
|
diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js
|
|
index 5a8a819c..89099b31 100644
|
|
--- a/extensions/workspace-indicator/workspaceIndicator.js
|
|
+++ b/extensions/workspace-indicator/workspaceIndicator.js
|
|
@@ -120,14 +120,27 @@ let WorkspaceThumbnail = GObject.registerClass({
|
|
}, class WorkspaceThumbnail extends St.Button {
|
|
_init(index) {
|
|
super._init({
|
|
+ y_fill: true,
|
|
+ });
|
|
+
|
|
+ const box = new St.BoxLayout({
|
|
+ style_class: 'workspace-box',
|
|
+ y_expand: true,
|
|
+ vertical: true,
|
|
+ });
|
|
+ this.set_child(box);
|
|
+
|
|
+ this._preview = new St.Bin({
|
|
style_class: 'workspace',
|
|
child: new Clutter.Actor({
|
|
layout_manager: new WorkspaceLayout(),
|
|
clip_to_allocation: true
|
|
}),
|
|
x_fill: true,
|
|
- y_fill: true
|
|
+ y_fill: true,
|
|
+ y_expand: true,
|
|
});
|
|
+ box.add_child(this._preview);
|
|
|
|
this._tooltip = new St.Label({
|
|
style_class: 'dash-label',
|
|
@@ -184,7 +197,7 @@ let WorkspaceThumbnail = GObject.registerClass({
|
|
let preview = new WindowPreview(window);
|
|
preview.connect('clicked', (a, btn) => this.emit('clicked', btn));
|
|
this._windowPreviews.set(window, preview);
|
|
- this.child.add_child(preview);
|
|
+ this._preview.child.add_child(preview);
|
|
}
|
|
|
|
_removeWindow(window) {
|
|
@@ -204,7 +217,7 @@ let WorkspaceThumbnail = GObject.registerClass({
|
|
if (!preview)
|
|
continue;
|
|
|
|
- this.child.set_child_above_sibling(preview, lastPreview);
|
|
+ this._preview.child.set_child_above_sibling(preview, lastPreview);
|
|
lastPreview = preview;
|
|
}
|
|
}
|
|
@@ -348,9 +361,9 @@ const WorkspacePreviews = GObject.registerClass({
|
|
let thumbs = this._thumbnailsBox.get_children();
|
|
for (let i = 0; i < thumbs.length; i++) {
|
|
if (i == activeIndex)
|
|
- thumbs[i].add_style_class_name('active');
|
|
+ thumbs[i]._preview.add_style_class_name('active');
|
|
else
|
|
- thumbs[i].remove_style_class_name('active');
|
|
+ thumbs[i]._preview.remove_style_class_name('active');
|
|
}
|
|
}
|
|
|
|
--
|
|
2.50.0
|
|
|