Blame SOURCES/more-classic-classic-mode.patch

7d7a48
From a19128ef885d8a933af364651b21e519f583f82a Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Wed, 29 May 2019 10:17:20 +0000
7d7a48
Subject: [PATCH 01/22] places-menu: Don't hardcode position
7d7a48
7d7a48
The extension currently assumes that we have the "Activities" button
7d7a48
at the left of the top bar. This is currently true, not only in the
7d7a48
regular session, but also in GNOME classic where the button is hidden
7d7a48
(but still present).
7d7a48
7d7a48
However this is about to change: We will stop taking over the button
7d7a48
from the apps-menu extension, and instead disable "Activities" from
7d7a48
the session mode definition.
7d7a48
7d7a48
Prepare for this by adding the places menu before the application menu
7d7a48
instead of assuming a hardcoded position.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69
7d7a48
---
7d7a48
 extensions/places-menu/extension.js | 4 ++--
7d7a48
 1 file changed, 2 insertions(+), 2 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/places-menu/extension.js b/extensions/places-menu/extension.js
7d7a48
index c477a4a..5c038ae 100644
7d7a48
--- a/extensions/places-menu/extension.js
7d7a48
+++ b/extensions/places-menu/extension.js
7d7a48
@@ -135,9 +135,9 @@ let _indicator;
7d7a48
 function enable() {
7d7a48
     _indicator = new PlacesMenu;
7d7a48
 
7d7a48
-    let pos = 1;
7d7a48
+    let pos = Main.sessionMode.panel.left.indexOf('appMenu');
7d7a48
     if ('apps-menu' in Main.panel.statusArea)
7d7a48
-        pos = 2;
7d7a48
+        pos++;
7d7a48
     Main.panel.addToStatusArea('places-menu', _indicator, pos, 'left');
7d7a48
 }
7d7a48
 
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From 075f6d45b242061be774ba5d3d8c2236cacd64c5 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Wed, 29 May 2019 08:32:03 +0000
7d7a48
Subject: [PATCH 02/22] apps-menu: Stop taking over Activities button
7d7a48
7d7a48
We don't want the "Activities" button in GNOME Classic, but the current
7d7a48
way of handling it is confusing:
7d7a48
7d7a48
 - the button is hidden, but the corresponding hot corner
7d7a48
   sometimes works (when the application menu isn't open)
7d7a48
7d7a48
 - the button is effectively moved inside the menu, although
7d7a48
   it's clearly not an app or category
7d7a48
7d7a48
 - the apps-menu can be used independent from classic mode, in
7d7a48
   which case removing the "Activities" button may not be wanted
7d7a48
7d7a48
Address those points by removing any handling of the activities button
7d7a48
from the apps-menu extension. We will remove it again from the classic
7d7a48
session via a session mode tweak.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69
7d7a48
---
7d7a48
 extensions/apps-menu/extension.js | 67 +++----------------------------
7d7a48
 1 file changed, 6 insertions(+), 61 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js
7d7a48
index cc399c6..d6c9c8b 100644
7d7a48
--- a/extensions/apps-menu/extension.js
7d7a48
+++ b/extensions/apps-menu/extension.js
7d7a48
@@ -25,22 +25,6 @@ const NAVIGATION_REGION_OVERSHOOT = 50;
7d7a48
 Gio._promisify(Gio._LocalFilePrototype, 'query_info_async', 'query_info_finish');
7d7a48
 Gio._promisify(Gio._LocalFilePrototype, 'set_attributes_async', 'set_attributes_finish');
7d7a48
 
7d7a48
-class ActivitiesMenuItem extends PopupMenu.PopupBaseMenuItem {
7d7a48
-    constructor(button) {
7d7a48
-        super();
7d7a48
-        this._button = button;
7d7a48
-        let label = new St.Label({ text: _('Activities Overview') });
7d7a48
-        this.actor.add_child(label);
7d7a48
-        this.actor.label_actor = label;
7d7a48
-    }
7d7a48
-
7d7a48
-    activate(event) {
7d7a48
-        this._button.menu.toggle();
7d7a48
-        Main.overview.toggle();
7d7a48
-        super.activate(event);
7d7a48
-    }
7d7a48
-}
7d7a48
-
7d7a48
 class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem {
7d7a48
     constructor(button, app) {
7d7a48
         super();
7d7a48
@@ -233,21 +217,6 @@ class ApplicationsMenu extends PopupMenu.PopupMenu {
7d7a48
         return false;
7d7a48
     }
7d7a48
 
7d7a48
-    open(animate) {
7d7a48
-        this._button.hotCorner.setBarrierSize(0);
7d7a48
-        if (this._button.hotCorner.actor) // fallback corner
7d7a48
-            this._button.hotCorner.actor.hide();
7d7a48
-        super.open(animate);
7d7a48
-    }
7d7a48
-
7d7a48
-    close(animate) {
7d7a48
-        let size = Main.layoutManager.panelBox.height;
7d7a48
-        this._button.hotCorner.setBarrierSize(size);
7d7a48
-        if (this._button.hotCorner.actor) // fallback corner
7d7a48
-            this._button.hotCorner.actor.show();
7d7a48
-        super.close(animate);
7d7a48
-    }
7d7a48
-
7d7a48
     toggle() {
7d7a48
         if (this.isOpen) {
7d7a48
             this._button.selectCategory(null);
7d7a48
@@ -381,7 +350,7 @@ Signals.addSignalMethods(DesktopTarget.prototype);
7d7a48
 
7d7a48
 let ApplicationsButton = GObject.registerClass(
7d7a48
 class ApplicationsButton extends PanelMenu.Button {
7d7a48
-    _init() {
7d7a48
+    _init(includeIcon) {
7d7a48
         super._init(1.0, null, false);
7d7a48
 
7d7a48
         this.setMenu(new ApplicationsMenu(this, 1.0, St.Side.TOP, this));
7d7a48
@@ -398,7 +367,8 @@ class ApplicationsButton extends PanelMenu.Button {
7d7a48
             '/usr/share/icons/hicolor/scalable/apps/start-here.svg');
7d7a48
         this._icon = new St.Icon({
7d7a48
             gicon: new Gio.FileIcon({ file: iconFile }),
7d7a48
-            style_class: 'panel-logo-icon'
7d7a48
+            style_class: 'panel-logo-icon',
7d7a48
+            visible: includeIcon
7d7a48
         });
7d7a48
         hbox.add_actor(this._icon);
7d7a48
 
7d7a48
@@ -414,8 +384,6 @@ class ApplicationsButton extends PanelMenu.Button {
7d7a48
         this.name = 'panelApplications';
7d7a48
         this.label_actor = this._label;
7d7a48
 
7d7a48
-        this.connect('captured-event', this._onCapturedEvent.bind(this));
7d7a48
-
7d7a48
         this._showingId = Main.overview.connect('showing', () => {
7d7a48
             this.add_accessible_state (Atk.StateType.CHECKED);
7d7a48
         });
7d7a48
@@ -457,10 +425,6 @@ class ApplicationsButton extends PanelMenu.Button {
7d7a48
         }
7d7a48
     }
7d7a48
 
7d7a48
-    get hotCorner() {
7d7a48
-        return Main.layoutManager.hotCorners[Main.layoutManager.primaryIndex];
7d7a48
-    }
7d7a48
-
7d7a48
     _createVertSeparator() {
7d7a48
         let separator = new St.DrawingArea({
7d7a48
             style_class: 'calendar-vertical-separator',
7d7a48
@@ -487,14 +451,6 @@ class ApplicationsButton extends PanelMenu.Button {
7d7a48
         this._desktopTarget.destroy();
7d7a48
     }
7d7a48
 
7d7a48
-    _onCapturedEvent(actor, event) {
7d7a48
-        if (event.type() == Clutter.EventType.BUTTON_PRESS) {
7d7a48
-            if (!Main.overview.shouldToggleByCornerOrButton())
7d7a48
-                return true;
7d7a48
-        }
7d7a48
-        return false;
7d7a48
-    }
7d7a48
-
7d7a48
     _onMenuKeyPress(actor, event) {
7d7a48
         let symbol = event.get_key_symbol();
7d7a48
         if (symbol == Clutter.KEY_Left || symbol == Clutter.KEY_Right) {
7d7a48
@@ -638,14 +594,6 @@ class ApplicationsButton extends PanelMenu.Button {
7d7a48
             y_align: St.Align.START
7d7a48
         });
7d7a48
 
7d7a48
-        let activities = new ActivitiesMenuItem(this);
7d7a48
-        this.leftBox.add(activities.actor, {
7d7a48
-            expand: false,
7d7a48
-            x_fill: true,
7d7a48
-            y_fill: false,
7d7a48
-            y_align: St.Align.START
7d7a48
-        });
7d7a48
-
7d7a48
         this.applicationsBox = new St.BoxLayout({ vertical: true });
7d7a48
         this.applicationsScrollBox.add_actor(this.applicationsBox);
7d7a48
         this.categoriesBox = new St.BoxLayout({ vertical: true });
7d7a48
@@ -757,19 +705,16 @@ class ApplicationsButton extends PanelMenu.Button {
7d7a48
 });
7d7a48
 
7d7a48
 let appsMenuButton;
7d7a48
-let activitiesButton;
7d7a48
 
7d7a48
 function enable() {
7d7a48
-    activitiesButton = Main.panel.statusArea['activities'];
7d7a48
-    activitiesButton.container.hide();
7d7a48
-    appsMenuButton = new ApplicationsButton();
7d7a48
-    Main.panel.addToStatusArea('apps-menu', appsMenuButton, 1, 'left');
7d7a48
+    let index = Main.sessionMode.panel.left.indexOf('activities') + 1;
7d7a48
+    appsMenuButton = new ApplicationsButton(index == 0);
7d7a48
+    Main.panel.addToStatusArea('apps-menu', appsMenuButton, index, 'left');
7d7a48
 }
7d7a48
 
7d7a48
 function disable() {
7d7a48
     Main.panel.menuManager.removeMenu(appsMenuButton.menu);
7d7a48
     appsMenuButton.destroy();
7d7a48
-    activitiesButton.container.show();
7d7a48
 }
7d7a48
 
7d7a48
 function init() {
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From e8b2f5206b659398931cfc961954b5d744d52728 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Fri, 7 Jun 2019 14:30:16 +0000
7d7a48
Subject: [PATCH 03/22] apps-menu: Stop hiding the overview when toggled
7d7a48
7d7a48
Now that the extension no longer doubles as the "Activities" button,
7d7a48
that behavior is confusing.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69
7d7a48
---
7d7a48
 extensions/apps-menu/extension.js | 6 +-----
7d7a48
 1 file changed, 1 insertion(+), 5 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js
7d7a48
index d6c9c8b..76bcd1a 100644
7d7a48
--- a/extensions/apps-menu/extension.js
7d7a48
+++ b/extensions/apps-menu/extension.js
7d7a48
@@ -218,12 +218,8 @@ class ApplicationsMenu extends PopupMenu.PopupMenu {
7d7a48
     }
7d7a48
 
7d7a48
     toggle() {
7d7a48
-        if (this.isOpen) {
7d7a48
+        if (this.isOpen)
7d7a48
             this._button.selectCategory(null);
7d7a48
-        } else {
7d7a48
-            if (Main.overview.visible)
7d7a48
-                Main.overview.hide();
7d7a48
-        }
7d7a48
         super.toggle();
7d7a48
     }
7d7a48
 }
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From bcd2c97e89bc90675525dbd05207ae25a91d39df Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Fri, 7 Jun 2019 20:07:19 +0000
7d7a48
Subject: [PATCH 04/22] apps-menu: Hide overview when launching app
7d7a48
7d7a48
Now that we no longer hide the overview when the menu is opened,
7d7a48
it is possible to activate menu entries from the overview. Start
7d7a48
hiding the overview in that case, which is consistent with app
7d7a48
launching elsewhere.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69
7d7a48
---
7d7a48
 extensions/apps-menu/extension.js | 2 ++
7d7a48
 1 file changed, 2 insertions(+)
7d7a48
7d7a48
diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js
7d7a48
index 76bcd1a..b9e7111 100644
7d7a48
--- a/extensions/apps-menu/extension.js
7d7a48
+++ b/extensions/apps-menu/extension.js
7d7a48
@@ -66,6 +66,8 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem {
7d7a48
         this._button.selectCategory(null);
7d7a48
         this._button.menu.toggle();
7d7a48
         super.activate(event);
7d7a48
+
7d7a48
+        Main.overview.hide();
7d7a48
     }
7d7a48
 
7d7a48
     setActive(active, params) {
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From c118895cff4cedfb43f0ae875d5cd355f66f0db7 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Wed, 29 May 2019 09:44:30 +0000
7d7a48
Subject: [PATCH 05/22] classic: Disable overview
7d7a48
7d7a48
The overview is one of the defining features of GNOME 3, and thus
7d7a48
almost by definition at odds with the classic session, which
7d7a48
emulates a traditional GNOME 2 desktop.
7d7a48
7d7a48
Even with the less prominent placement inside the application menu
7d7a48
it never quite fit in - it doesn't help that besides the different
7d7a48
UI paradigma, the overview keeps its "normal" styling which differs
7d7a48
greatly with classic's normal mode.
7d7a48
7d7a48
So besides removing the "Activities" button via the session mode
7d7a48
definition, now that the apps-menu extension doesn't replace it anymore,
7d7a48
disable the overview completely in the classic session.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69
7d7a48
---
7d7a48
 data/classic.json.in | 3 ++-
7d7a48
 1 file changed, 2 insertions(+), 1 deletion(-)
7d7a48
7d7a48
diff --git a/data/classic.json.in b/data/classic.json.in
7d7a48
index fdb3762..c1c0544 100644
7d7a48
--- a/data/classic.json.in
7d7a48
+++ b/data/classic.json.in
7d7a48
@@ -1,8 +1,9 @@
7d7a48
 {
7d7a48
     "parentMode": "user",
7d7a48
     "stylesheetName": "gnome-classic.css",
7d7a48
+    "hasOverview": false,
7d7a48
     "enabledExtensions": [@CLASSIC_EXTENSIONS@],
7d7a48
-    "panel": { "left": ["activities", "appMenu"],
7d7a48
+    "panel": { "left": ["appMenu"],
7d7a48
                "center": [],
7d7a48
                "right": ["a11y", "keyboard", "dateMenu", "aggregateMenu"]
7d7a48
              }
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From 004affc147579e2b1a11614cd0c8faf99e307999 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Wed, 5 Jun 2019 00:23:13 +0000
7d7a48
Subject: [PATCH 06/22] window-list: Split out workspaceIndicator
7d7a48
7d7a48
The extension has grown unwieldily big, so before starting to improve
7d7a48
on the workspace indicator, move it to its own source file.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
7d7a48
---
7d7a48
 extensions/window-list/extension.js          | 130 +-----------------
7d7a48
 extensions/window-list/meson.build           |   2 +-
7d7a48
 extensions/window-list/workspaceIndicator.js | 135 +++++++++++++++++++
7d7a48
 3 files changed, 138 insertions(+), 129 deletions(-)
7d7a48
 create mode 100644 extensions/window-list/workspaceIndicator.js
7d7a48
7d7a48
diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js
7d7a48
index e1ea742..5275d9c 100644
7d7a48
--- a/extensions/window-list/extension.js
7d7a48
+++ b/extensions/window-list/extension.js
7d7a48
@@ -1,13 +1,13 @@
7d7a48
 /* exported init */
7d7a48
-const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell, St } = imports.gi;
7d7a48
+const { Clutter, Gio, GLib, Gtk, Meta, Shell, St } = imports.gi;
7d7a48
 
7d7a48
 const DND = imports.ui.dnd;
7d7a48
 const Main = imports.ui.main;
7d7a48
-const PanelMenu = imports.ui.panelMenu;
7d7a48
 const PopupMenu = imports.ui.popupMenu;
7d7a48
 
7d7a48
 const ExtensionUtils = imports.misc.extensionUtils;
7d7a48
 const Me = ExtensionUtils.getCurrentExtension();
7d7a48
+const { WorkspaceIndicator } = Me.imports.workspaceIndicator;
7d7a48
 
7d7a48
 const Gettext = imports.gettext.domain('gnome-shell-extensions');
7d7a48
 const _ = Gettext.gettext;
7d7a48
@@ -644,132 +644,6 @@ class AppButton extends BaseButton {
7d7a48
 }
7d7a48
 
7d7a48
 
7d7a48
-let WorkspaceIndicator = GObject.registerClass(
7d7a48
-class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
-    _init() {
7d7a48
-        super._init(0.0, _('Workspace Indicator'), true);
7d7a48
-        this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM));
7d7a48
-        this.add_style_class_name('window-list-workspace-indicator');
7d7a48
-        this.menu.actor.remove_style_class_name('panel-menu');
7d7a48
-
7d7a48
-        let container = new St.Widget({
7d7a48
-            layout_manager: new Clutter.BinLayout(),
7d7a48
-            x_expand: true,
7d7a48
-            y_expand: true
7d7a48
-        });
7d7a48
-        this.add_actor(container);
7d7a48
-
7d7a48
-        let workspaceManager = global.workspace_manager;
7d7a48
-
7d7a48
-        this._currentWorkspace = workspaceManager.get_active_workspace().index();
7d7a48
-        this.statusLabel = new St.Label({
7d7a48
-            text: this._getStatusText(),
7d7a48
-            x_align: Clutter.ActorAlign.CENTER,
7d7a48
-            y_align: Clutter.ActorAlign.CENTER
7d7a48
-        });
7d7a48
-        container.add_actor(this.statusLabel);
7d7a48
-
7d7a48
-        this.workspacesItems = [];
7d7a48
-
7d7a48
-        this._workspaceManagerSignals = [];
7d7a48
-        this._workspaceManagerSignals.push(workspaceManager.connect('notify::n-workspaces',
7d7a48
-                                                                    this._updateMenu.bind(this)));
7d7a48
-        this._workspaceManagerSignals.push(workspaceManager.connect_after('workspace-switched',
7d7a48
-                                                                          this._updateIndicator.bind(this)));
7d7a48
-
7d7a48
-        this.connect('scroll-event', this._onScrollEvent.bind(this));
7d7a48
-        this._updateMenu();
7d7a48
-
7d7a48
-        this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' });
7d7a48
-        this._settingsChangedId =
7d7a48
-            this._settings.connect('changed::workspace-names',
7d7a48
-                                   this._updateMenu.bind(this));
7d7a48
-    }
7d7a48
-
7d7a48
-    _onDestroy() {
7d7a48
-        for (let i = 0; i < this._workspaceManagerSignals.length; i++)
7d7a48
-            global.workspace_manager.disconnect(this._workspaceManagerSignals[i]);
7d7a48
-
7d7a48
-        if (this._settingsChangedId) {
7d7a48
-            this._settings.disconnect(this._settingsChangedId);
7d7a48
-            this._settingsChangedId = 0;
7d7a48
-        }
7d7a48
-
7d7a48
-        super._onDestroy();
7d7a48
-    }
7d7a48
-
7d7a48
-    _updateIndicator() {
7d7a48
-        this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE);
7d7a48
-        this._currentWorkspace = global.workspace_manager.get_active_workspace().index();
7d7a48
-        this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT);
7d7a48
-
7d7a48
-        this.statusLabel.set_text(this._getStatusText());
7d7a48
-    }
7d7a48
-
7d7a48
-    _getStatusText() {
7d7a48
-        let workspaceManager = global.workspace_manager;
7d7a48
-        let current = workspaceManager.get_active_workspace().index();
7d7a48
-        let total = workspaceManager.n_workspaces;
7d7a48
-
7d7a48
-        return '%d / %d'.format(current + 1, total);
7d7a48
-    }
7d7a48
-
7d7a48
-    _updateMenu() {
7d7a48
-        let workspaceManager = global.workspace_manager;
7d7a48
-
7d7a48
-        this.menu.removeAll();
7d7a48
-        this.workspacesItems = [];
7d7a48
-        this._currentWorkspace = workspaceManager.get_active_workspace().index();
7d7a48
-
7d7a48
-        for (let i = 0; i < workspaceManager.n_workspaces; i++) {
7d7a48
-            let name = Meta.prefs_get_workspace_name(i);
7d7a48
-            let item = new PopupMenu.PopupMenuItem(name);
7d7a48
-            item.workspaceId = i;
7d7a48
-
7d7a48
-            item.connect('activate', (item, _event) => {
7d7a48
-                this._activate(item.workspaceId);
7d7a48
-            });
7d7a48
-
7d7a48
-            if (i == this._currentWorkspace)
7d7a48
-                item.setOrnament(PopupMenu.Ornament.DOT);
7d7a48
-
7d7a48
-            this.menu.addMenuItem(item);
7d7a48
-            this.workspacesItems[i] = item;
7d7a48
-        }
7d7a48
-
7d7a48
-        this.statusLabel.set_text(this._getStatusText());
7d7a48
-    }
7d7a48
-
7d7a48
-    _activate(index) {
7d7a48
-        let workspaceManager = global.workspace_manager;
7d7a48
-
7d7a48
-        if (index >= 0 && index < workspaceManager.n_workspaces) {
7d7a48
-            let metaWorkspace = workspaceManager.get_workspace_by_index(index);
7d7a48
-            metaWorkspace.activate(global.get_current_time());
7d7a48
-        }
7d7a48
-    }
7d7a48
-
7d7a48
-    _onScrollEvent(actor, event) {
7d7a48
-        let direction = event.get_scroll_direction();
7d7a48
-        let diff = 0;
7d7a48
-        if (direction == Clutter.ScrollDirection.DOWN) {
7d7a48
-            diff = 1;
7d7a48
-        } else if (direction == Clutter.ScrollDirection.UP) {
7d7a48
-            diff = -1;
7d7a48
-        } else {
7d7a48
-            return;
7d7a48
-        }
7d7a48
-
7d7a48
-        let newIndex = this._currentWorkspace + diff;
7d7a48
-        this._activate(newIndex);
7d7a48
-    }
7d7a48
-
7d7a48
-    _allocate(actor, box, flags) {
7d7a48
-        if (actor.get_n_children() > 0)
7d7a48
-            actor.get_first_child().allocate(box, flags);
7d7a48
-    }
7d7a48
-});
7d7a48
-
7d7a48
 class WindowList {
7d7a48
     constructor(perMonitor, monitor) {
7d7a48
         this._perMonitor = perMonitor;
7d7a48
diff --git a/extensions/window-list/meson.build b/extensions/window-list/meson.build
7d7a48
index b4aa4db..74025f9 100644
7d7a48
--- a/extensions/window-list/meson.build
7d7a48
+++ b/extensions/window-list/meson.build
7d7a48
@@ -4,7 +4,7 @@ extension_data += configure_file(
7d7a48
   configuration: metadata_conf
7d7a48
 )
7d7a48
 
7d7a48
-extension_sources += files('prefs.js')
7d7a48
+extension_sources += files('prefs.js', 'workspaceIndicator.js')
7d7a48
 extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')
7d7a48
 
7d7a48
 if classic_mode_enabled
7d7a48
diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js
7d7a48
new file mode 100644
7d7a48
index 0000000..fb3ffe7
7d7a48
--- /dev/null
7d7a48
+++ b/extensions/window-list/workspaceIndicator.js
7d7a48
@@ -0,0 +1,135 @@
7d7a48
+/* exported WorkspaceIndicator */
7d7a48
+const { Clutter, Gio, GObject, Meta, St } = imports.gi;
7d7a48
+
7d7a48
+const PanelMenu = imports.ui.panelMenu;
7d7a48
+const PopupMenu = imports.ui.popupMenu;
7d7a48
+
7d7a48
+const Gettext = imports.gettext.domain('gnome-shell-extensions');
7d7a48
+const _ = Gettext.gettext;
7d7a48
+
7d7a48
+var WorkspaceIndicator = GObject.registerClass(
7d7a48
+class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
+    _init() {
7d7a48
+        super._init(0.0, _('Workspace Indicator'), true);
7d7a48
+        this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM));
7d7a48
+        this.add_style_class_name('window-list-workspace-indicator');
7d7a48
+        this.menu.actor.remove_style_class_name('panel-menu');
7d7a48
+
7d7a48
+        let container = new St.Widget({
7d7a48
+            layout_manager: new Clutter.BinLayout(),
7d7a48
+            x_expand: true,
7d7a48
+            y_expand: true
7d7a48
+        });
7d7a48
+        this.add_actor(container);
7d7a48
+
7d7a48
+        let workspaceManager = global.workspace_manager;
7d7a48
+
7d7a48
+        this._currentWorkspace = workspaceManager.get_active_workspace().index();
7d7a48
+        this.statusLabel = new St.Label({
7d7a48
+            text: this._getStatusText(),
7d7a48
+            x_align: Clutter.ActorAlign.CENTER,
7d7a48
+            y_align: Clutter.ActorAlign.CENTER
7d7a48
+        });
7d7a48
+        container.add_actor(this.statusLabel);
7d7a48
+
7d7a48
+        this.workspacesItems = [];
7d7a48
+
7d7a48
+        this._workspaceManagerSignals = [
7d7a48
+            workspaceManager.connect('notify::n-workspaces',
7d7a48
+                this._updateMenu.bind(this)),
7d7a48
+            workspaceManager.connect_after('workspace-switched',
7d7a48
+                this._updateIndicator.bind(this))
7d7a48
+        ];
7d7a48
+
7d7a48
+        this.connect('scroll-event', this._onScrollEvent.bind(this));
7d7a48
+        this._updateMenu();
7d7a48
+
7d7a48
+        this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' });
7d7a48
+        this._settingsChangedId = this._settings.connect(
7d7a48
+            'changed::workspace-names', this._updateMenu.bind(this));
7d7a48
+    }
7d7a48
+
7d7a48
+    _onDestroy() {
7d7a48
+        for (let i = 0; i < this._workspaceManagerSignals.length; i++)
7d7a48
+            global.workspace_manager.disconnect(this._workspaceManagerSignals[i]);
7d7a48
+
7d7a48
+        if (this._settingsChangedId) {
7d7a48
+            this._settings.disconnect(this._settingsChangedId);
7d7a48
+            this._settingsChangedId = 0;
7d7a48
+        }
7d7a48
+
7d7a48
+        super._onDestroy();
7d7a48
+    }
7d7a48
+
7d7a48
+    _updateIndicator() {
7d7a48
+        this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE);
7d7a48
+        this._currentWorkspace = global.workspace_manager.get_active_workspace().index();
7d7a48
+        this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT);
7d7a48
+
7d7a48
+        this.statusLabel.set_text(this._getStatusText());
7d7a48
+    }
7d7a48
+
7d7a48
+    _getStatusText() {
7d7a48
+        let workspaceManager = global.workspace_manager;
7d7a48
+        let current = workspaceManager.get_active_workspace().index();
7d7a48
+        let total = workspaceManager.n_workspaces;
7d7a48
+
7d7a48
+        return '%d / %d'.format(current + 1, total);
7d7a48
+    }
7d7a48
+
7d7a48
+    _updateMenu() {
7d7a48
+        let workspaceManager = global.workspace_manager;
7d7a48
+
7d7a48
+        this.menu.removeAll();
7d7a48
+        this.workspacesItems = [];
7d7a48
+        this._currentWorkspace = workspaceManager.get_active_workspace().index();
7d7a48
+
7d7a48
+        for (let i = 0; i < workspaceManager.n_workspaces; i++) {
7d7a48
+            let name = Meta.prefs_get_workspace_name(i);
7d7a48
+            let item = new PopupMenu.PopupMenuItem(name);
7d7a48
+            item.workspaceId = i;
7d7a48
+
7d7a48
+            item.connect('activate', (item, _event) => {
7d7a48
+                this._activate(item.workspaceId);
7d7a48
+            });
7d7a48
+
7d7a48
+            if (i == this._currentWorkspace)
7d7a48
+                item.setOrnament(PopupMenu.Ornament.DOT);
7d7a48
+
7d7a48
+            this.menu.addMenuItem(item);
7d7a48
+            this.workspacesItems[i] = item;
7d7a48
+        }
7d7a48
+
7d7a48
+        this.statusLabel.set_text(this._getStatusText());
7d7a48
+    }
7d7a48
+
7d7a48
+    _activate(index) {
7d7a48
+        let workspaceManager = global.workspace_manager;
7d7a48
+
7d7a48
+        if (index >= 0 && index < workspaceManager.n_workspaces) {
7d7a48
+            let metaWorkspace = workspaceManager.get_workspace_by_index(index);
7d7a48
+            metaWorkspace.activate(global.get_current_time());
7d7a48
+        }
7d7a48
+    }
7d7a48
+
7d7a48
+    _onScrollEvent(actor, event) {
7d7a48
+        let direction = event.get_scroll_direction();
7d7a48
+        let diff = 0;
7d7a48
+        if (direction == Clutter.ScrollDirection.DOWN) {
7d7a48
+            diff = 1;
7d7a48
+        } else if (direction == Clutter.ScrollDirection.UP) {
7d7a48
+            diff = -1;
7d7a48
+        } else {
7d7a48
+            return;
7d7a48
+        }
7d7a48
+
7d7a48
+        let newIndex = this._currentWorkspace + diff;
7d7a48
+        this._activate(newIndex);
7d7a48
+    }
7d7a48
+
7d7a48
+    _allocate(actor, box, flags) {
7d7a48
+        if (actor.get_n_children() > 0)
7d7a48
+            actor.get_first_child().allocate(box, flags);
7d7a48
+    }
7d7a48
+});
7d7a48
+
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From cceda34bfcd3de806a7b72bb532e1f8a248accee Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Wed, 5 Jun 2019 17:39:53 +0000
7d7a48
Subject: [PATCH 07/22] window-list: Use a more specific GTypeName for
7d7a48
 workspace indicator
7d7a48
7d7a48
Now that the class inherits from GObject, the generic name easily
7d7a48
conflicts with other classes otherwise, for example with the one
7d7a48
from the workspace-indicator extension.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
7d7a48
---
7d7a48
 extensions/window-list/workspaceIndicator.js | 5 +++--
7d7a48
 1 file changed, 3 insertions(+), 2 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js
7d7a48
index fb3ffe7..8ac43eb 100644
7d7a48
--- a/extensions/window-list/workspaceIndicator.js
7d7a48
+++ b/extensions/window-list/workspaceIndicator.js
7d7a48
@@ -7,8 +7,9 @@ const PopupMenu = imports.ui.popupMenu;
7d7a48
 const Gettext = imports.gettext.domain('gnome-shell-extensions');
7d7a48
 const _ = Gettext.gettext;
7d7a48
 
7d7a48
-var WorkspaceIndicator = GObject.registerClass(
7d7a48
-class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
+var WorkspaceIndicator = GObject.registerClass({
7d7a48
+    GTypeName: 'WindowListWorkspaceIndicator'
7d7a48
+}, class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
     _init() {
7d7a48
         super._init(0.0, _('Workspace Indicator'), true);
7d7a48
         this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM));
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From 57a97bef2e2cfb88324e9d1540254dca8f5195e3 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Wed, 5 Jun 2019 04:54:50 +0200
7d7a48
Subject: [PATCH 08/22] window-list: Make some properties private
7d7a48
7d7a48
There's no reason why they should be public.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
7d7a48
---
7d7a48
 extensions/window-list/workspaceIndicator.js | 18 +++++++++---------
7d7a48
 1 file changed, 9 insertions(+), 9 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js
7d7a48
index 8ac43eb..7c0360a 100644
7d7a48
--- a/extensions/window-list/workspaceIndicator.js
7d7a48
+++ b/extensions/window-list/workspaceIndicator.js
7d7a48
@@ -26,14 +26,14 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
 
7d7a48
         this._currentWorkspace = workspaceManager.get_active_workspace().index();
7d7a48
-        this.statusLabel = new St.Label({
7d7a48
+        this._statusLabel = new St.Label({
7d7a48
             text: this._getStatusText(),
7d7a48
             x_align: Clutter.ActorAlign.CENTER,
7d7a48
             y_align: Clutter.ActorAlign.CENTER
7d7a48
         });
7d7a48
-        container.add_actor(this.statusLabel);
7d7a48
+        container.add_actor(this._statusLabel);
7d7a48
 
7d7a48
-        this.workspacesItems = [];
7d7a48
+        this._workspacesItems = [];
7d7a48
 
7d7a48
         this._workspaceManagerSignals = [
7d7a48
             workspaceManager.connect('notify::n-workspaces',
7d7a48
@@ -63,11 +63,11 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
     }
7d7a48
 
7d7a48
     _updateIndicator() {
7d7a48
-        this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE);
7d7a48
+        this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE);
7d7a48
         this._currentWorkspace = global.workspace_manager.get_active_workspace().index();
7d7a48
-        this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT);
7d7a48
+        this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT);
7d7a48
 
7d7a48
-        this.statusLabel.set_text(this._getStatusText());
7d7a48
+        this._statusLabel.set_text(this._getStatusText());
7d7a48
     }
7d7a48
 
7d7a48
     _getStatusText() {
7d7a48
@@ -82,7 +82,7 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
 
7d7a48
         this.menu.removeAll();
7d7a48
-        this.workspacesItems = [];
7d7a48
+        this._workspacesItems = [];
7d7a48
         this._currentWorkspace = workspaceManager.get_active_workspace().index();
7d7a48
 
7d7a48
         for (let i = 0; i < workspaceManager.n_workspaces; i++) {
7d7a48
@@ -98,10 +98,10 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
                 item.setOrnament(PopupMenu.Ornament.DOT);
7d7a48
 
7d7a48
             this.menu.addMenuItem(item);
7d7a48
-            this.workspacesItems[i] = item;
7d7a48
+            this._workspacesItems[i] = item;
7d7a48
         }
7d7a48
 
7d7a48
-        this.statusLabel.set_text(this._getStatusText());
7d7a48
+        this._statusLabel.set_text(this._getStatusText());
7d7a48
     }
7d7a48
 
7d7a48
     _activate(index) {
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From 8097536f35b9c64f24e8c1c6c8211024c4f8f01d Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Wed, 5 Jun 2019 04:57:39 +0200
7d7a48
Subject: [PATCH 09/22] window-list: Update workspace names in-place
7d7a48
7d7a48
There's no good reason to rebuild the entire menu on workspace names
7d7a48
changes, we can simply update the labels in-place.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
7d7a48
---
7d7a48
 extensions/window-list/workspaceIndicator.js | 10 +++++++++-
7d7a48
 1 file changed, 9 insertions(+), 1 deletion(-)
7d7a48
7d7a48
diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js
7d7a48
index 7c0360a..9888838 100644
7d7a48
--- a/extensions/window-list/workspaceIndicator.js
7d7a48
+++ b/extensions/window-list/workspaceIndicator.js
7d7a48
@@ -47,7 +47,7 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
 
7d7a48
         this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' });
7d7a48
         this._settingsChangedId = this._settings.connect(
7d7a48
-            'changed::workspace-names', this._updateMenu.bind(this));
7d7a48
+            'changed::workspace-names', this._updateMenuLabels.bind(this));
7d7a48
     }
7d7a48
 
7d7a48
     _onDestroy() {
7d7a48
@@ -78,6 +78,14 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
         return '%d / %d'.format(current + 1, total);
7d7a48
     }
7d7a48
 
7d7a48
+    _updateMenuLabels() {
7d7a48
+        for (let i = 0; i < this._workspacesItems.length; i++) {
7d7a48
+            let item = this._workspacesItems[i];
7d7a48
+            let name = Meta.prefs_get_workspace_name(i);
7d7a48
+            item.label.text = name;
7d7a48
+        }
7d7a48
+    }
7d7a48
+
7d7a48
     _updateMenu() {
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
 
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From c51e35e0dc9937ab19577be41654f914f1cfe894 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Wed, 5 Jun 2019 04:59:19 +0200
7d7a48
Subject: [PATCH 10/22] window-list: Minor cleanup
7d7a48
7d7a48
Mutter has a dedicated method for getting the index of the active
7d7a48
workspace, use that instead of getting first the active workspace
7d7a48
and then its index.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
7d7a48
---
7d7a48
 extensions/window-list/workspaceIndicator.js | 8 ++++----
7d7a48
 1 file changed, 4 insertions(+), 4 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js
7d7a48
index 9888838..1f2e1c1 100644
7d7a48
--- a/extensions/window-list/workspaceIndicator.js
7d7a48
+++ b/extensions/window-list/workspaceIndicator.js
7d7a48
@@ -25,7 +25,7 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
 
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
 
7d7a48
-        this._currentWorkspace = workspaceManager.get_active_workspace().index();
7d7a48
+        this._currentWorkspace = workspaceManager.get_active_workspace_index();
7d7a48
         this._statusLabel = new St.Label({
7d7a48
             text: this._getStatusText(),
7d7a48
             x_align: Clutter.ActorAlign.CENTER,
7d7a48
@@ -64,7 +64,7 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
 
7d7a48
     _updateIndicator() {
7d7a48
         this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE);
7d7a48
-        this._currentWorkspace = global.workspace_manager.get_active_workspace().index();
7d7a48
+        this._currentWorkspace = global.workspace_manager.get_active_workspace_index();
7d7a48
         this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT);
7d7a48
 
7d7a48
         this._statusLabel.set_text(this._getStatusText());
7d7a48
@@ -72,7 +72,7 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
 
7d7a48
     _getStatusText() {
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
-        let current = workspaceManager.get_active_workspace().index();
7d7a48
+        let current = workspaceManager.get_active_workspace_index();
7d7a48
         let total = workspaceManager.n_workspaces;
7d7a48
 
7d7a48
         return '%d / %d'.format(current + 1, total);
7d7a48
@@ -91,7 +91,7 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
 
7d7a48
         this.menu.removeAll();
7d7a48
         this._workspacesItems = [];
7d7a48
-        this._currentWorkspace = workspaceManager.get_active_workspace().index();
7d7a48
+        this._currentWorkspace = workspaceManager.get_active_workspace_index();
7d7a48
 
7d7a48
         for (let i = 0; i < workspaceManager.n_workspaces; i++) {
7d7a48
             let name = Meta.prefs_get_workspace_name(i);
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From 2eb09e7cc7e830bf4004a7c25a46d285e5e0bac1 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Wed, 5 Jun 2019 05:11:34 +0200
7d7a48
Subject: [PATCH 11/22] window-list: Improve workspace label styling
7d7a48
7d7a48
The border currently looks off - it extends all the way vertically
7d7a48
and leaves zero spacing to the label horizontally. Fix both issues
7d7a48
by setting appropriate padding/margins.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
7d7a48
---
7d7a48
 extensions/window-list/stylesheet.css        |  8 +++-----
7d7a48
 extensions/window-list/workspaceIndicator.js | 13 ++++++++-----
7d7a48
 2 files changed, 11 insertions(+), 10 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css
7d7a48
index f5285cb..3d3f2d7 100644
7d7a48
--- a/extensions/window-list/stylesheet.css
7d7a48
+++ b/extensions/window-list/stylesheet.css
7d7a48
@@ -70,13 +70,11 @@
7d7a48
   height: 24px;
7d7a48
 }
7d7a48
 
7d7a48
-.window-list-workspace-indicator {
7d7a48
-  padding: 3px;
7d7a48
-}
7d7a48
-
7d7a48
-.window-list-workspace-indicator > StWidget {
7d7a48
+.window-list-workspace-indicator .status-label-bin {
7d7a48
   background-color: rgba(200, 200, 200, .3);
7d7a48
   border: 1px solid #cccccc;
7d7a48
+  padding: 0 3px;
7d7a48
+  margin: 3px 0;
7d7a48
 }
7d7a48
 
7d7a48
 .notification {
7d7a48
diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js
7d7a48
index 1f2e1c1..598c516 100644
7d7a48
--- a/extensions/window-list/workspaceIndicator.js
7d7a48
+++ b/extensions/window-list/workspaceIndicator.js
7d7a48
@@ -26,12 +26,15 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
 
7d7a48
         this._currentWorkspace = workspaceManager.get_active_workspace_index();
7d7a48
-        this._statusLabel = new St.Label({
7d7a48
-            text: this._getStatusText(),
7d7a48
-            x_align: Clutter.ActorAlign.CENTER,
7d7a48
-            y_align: Clutter.ActorAlign.CENTER
7d7a48
+        this._statusLabel = new St.Label({ text: this._getStatusText() });
7d7a48
+
7d7a48
+        this._statusBin = new St.Bin({
7d7a48
+            style_class: 'status-label-bin',
7d7a48
+            x_expand: true,
7d7a48
+            y_expand: true,
7d7a48
+            child: this._statusLabel
7d7a48
         });
7d7a48
-        container.add_actor(this._statusLabel);
7d7a48
+        container.add_actor(this._statusBin);
7d7a48
 
7d7a48
         this._workspacesItems = [];
7d7a48
 
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From 477a532a5f5fb2f8a1ddcfc2277fe62fa1a7fb74 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Wed, 5 Jun 2019 05:08:31 +0200
7d7a48
Subject: [PATCH 12/22] window-list: Refactor workspace signal handlers
7d7a48
7d7a48
We are about to support a separate representation if horizontal
7d7a48
workspaces are used. To prepare for that, rename the handlers to
7d7a48
something more generic and split out menu-specific bits into a
7d7a48
dedicated help function.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
7d7a48
---
7d7a48
 extensions/window-list/workspaceIndicator.js | 25 +++++++++++++++-----
7d7a48
 1 file changed, 19 insertions(+), 6 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js
7d7a48
index 598c516..78ca97e 100644
7d7a48
--- a/extensions/window-list/workspaceIndicator.js
7d7a48
+++ b/extensions/window-list/workspaceIndicator.js
7d7a48
@@ -40,9 +40,9 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
 
7d7a48
         this._workspaceManagerSignals = [
7d7a48
             workspaceManager.connect('notify::n-workspaces',
7d7a48
-                this._updateMenu.bind(this)),
7d7a48
+                this._nWorkspacesChanged.bind(this)),
7d7a48
             workspaceManager.connect_after('workspace-switched',
7d7a48
-                this._updateIndicator.bind(this))
7d7a48
+                this._onWorkspaceSwitched.bind(this))
7d7a48
         ];
7d7a48
 
7d7a48
         this.connect('scroll-event', this._onScrollEvent.bind(this));
7d7a48
@@ -65,14 +65,27 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
         super._onDestroy();
7d7a48
     }
7d7a48
 
7d7a48
-    _updateIndicator() {
7d7a48
-        this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE);
7d7a48
-        this._currentWorkspace = global.workspace_manager.get_active_workspace_index();
7d7a48
-        this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT);
7d7a48
+    _onWorkspaceSwitched() {
7d7a48
+        let workspaceManager = global.workspace_manager;
7d7a48
+        this._currentWorkspace = workspaceManager.get_active_workspace_index();
7d7a48
+
7d7a48
+        this._updateMenuOrnament();
7d7a48
 
7d7a48
         this._statusLabel.set_text(this._getStatusText());
7d7a48
     }
7d7a48
 
7d7a48
+    _nWorkspacesChanged() {
7d7a48
+        this._updateMenu();
7d7a48
+    }
7d7a48
+
7d7a48
+    _updateMenuOrnament() {
7d7a48
+        for (let i = 0; i < this._workspacesItems.length; i++) {
7d7a48
+            this._workspacesItems[i].setOrnament(i == this._currentWorkspace
7d7a48
+                ? PopupMenu.Ornament.DOT
7d7a48
+                : PopupMenu.Ornament.NONE);
7d7a48
+        }
7d7a48
+    }
7d7a48
+
7d7a48
     _getStatusText() {
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
         let current = workspaceManager.get_active_workspace_index();
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From 8d2a00ef3a1bbd9c5bccd1542049b22a3bb2a79d Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Wed, 5 Jun 2019 02:53:38 +0000
7d7a48
Subject: [PATCH 13/22] window-list: Support horizontal workspace layout
7d7a48
7d7a48
Unlike in GNOME 2, the workspace indicator we display in the window list
7d7a48
isn't a workspace switcher, but a menu button that allows switching
7d7a48
workspaces via its menu. The reason for that is that a horizontal
7d7a48
in-place switcher would be at odds with the vertical workspace layout
7d7a48
used in GNOME 3.
7d7a48
7d7a48
However that reasoning doesn't apply when the layout is changed to a
7d7a48
horizontal one, so replace the button with a traditional workspace
7d7a48
switcher in that case.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
7d7a48
---
7d7a48
 extensions/window-list/stylesheet.css        | 24 +++++++
7d7a48
 extensions/window-list/workspaceIndicator.js | 66 +++++++++++++++++++-
7d7a48
 2 files changed, 89 insertions(+), 1 deletion(-)
7d7a48
7d7a48
diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css
7d7a48
index 3d3f2d7..b383b97 100644
7d7a48
--- a/extensions/window-list/stylesheet.css
7d7a48
+++ b/extensions/window-list/stylesheet.css
7d7a48
@@ -77,6 +77,30 @@
7d7a48
   margin: 3px 0;
7d7a48
 }
7d7a48
 
7d7a48
+.window-list-workspace-indicator .workspaces-box {
7d7a48
+  spacing: 3px;
7d7a48
+  padding: 3px;
7d7a48
+}
7d7a48
+
7d7a48
+.window-list-workspace-indicator .workspace {
7d7a48
+  border: 1px solid #cccccc;
7d7a48
+  width: 52px;
7d7a48
+}
7d7a48
+
7d7a48
+.window-list-workspace-indicator .workspace:first-child:ltr,
7d7a48
+.window-list-workspace-indicator .workspace:last-child:rtl {
7d7a48
+  border-radius: 4px 0 0 4px;
7d7a48
+}
7d7a48
+
7d7a48
+.window-list-workspace-indicator .workspace:first-child:rtl,
7d7a48
+.window-list-workspace-indicator .workspace:last-child:ltr {
7d7a48
+  border-radius: 0 4px 4px 0;
7d7a48
+}
7d7a48
+
7d7a48
+.window-list-workspace-indicator .workspace.active {
7d7a48
+  background-color: rgba(200, 200, 200, .3);
7d7a48
+}
7d7a48
+
7d7a48
 .notification {
7d7a48
   font-weight: normal;
7d7a48
 }
7d7a48
diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js
7d7a48
index 78ca97e..1258ed2 100644
7d7a48
--- a/extensions/window-list/workspaceIndicator.js
7d7a48
+++ b/extensions/window-list/workspaceIndicator.js
7d7a48
@@ -7,6 +7,25 @@ const PopupMenu = imports.ui.popupMenu;
7d7a48
 const Gettext = imports.gettext.domain('gnome-shell-extensions');
7d7a48
 const _ = Gettext.gettext;
7d7a48
 
7d7a48
+let WorkspaceThumbnail = GObject.registerClass({
7d7a48
+    GTypeName: 'WindowListWorkspaceThumbnail'
7d7a48
+}, class WorkspaceThumbnail extends St.Button {
7d7a48
+    _init(index) {
7d7a48
+        super._init({
7d7a48
+            style_class: 'workspace'
7d7a48
+        });
7d7a48
+
7d7a48
+        this._index = index;
7d7a48
+    }
7d7a48
+
7d7a48
+    // eslint-disable-next-line camelcase
7d7a48
+    on_clicked() {
7d7a48
+        let ws = global.workspace_manager.get_workspace_by_index(this._index);
7d7a48
+        if (ws)
7d7a48
+            ws.activate(global.get_current_time());
7d7a48
+    }
7d7a48
+});
7d7a48
+
7d7a48
 var WorkspaceIndicator = GObject.registerClass({
7d7a48
     GTypeName: 'WindowListWorkspaceIndicator'
7d7a48
 }, class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
@@ -36,17 +55,30 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
         });
7d7a48
         container.add_actor(this._statusBin);
7d7a48
 
7d7a48
+        this._thumbnailsBox = new St.BoxLayout({
7d7a48
+            style_class: 'workspaces-box',
7d7a48
+            y_expand: true,
7d7a48
+            reactive: true
7d7a48
+        });
7d7a48
+        this._thumbnailsBox.connect('scroll-event',
7d7a48
+            this._onScrollEvent.bind(this));
7d7a48
+        container.add_actor(this._thumbnailsBox);
7d7a48
+
7d7a48
         this._workspacesItems = [];
7d7a48
 
7d7a48
         this._workspaceManagerSignals = [
7d7a48
             workspaceManager.connect('notify::n-workspaces',
7d7a48
                 this._nWorkspacesChanged.bind(this)),
7d7a48
             workspaceManager.connect_after('workspace-switched',
7d7a48
-                this._onWorkspaceSwitched.bind(this))
7d7a48
+                this._onWorkspaceSwitched.bind(this)),
7d7a48
+            workspaceManager.connect('notify::layout-rows',
7d7a48
+                this._onWorkspaceOrientationChanged.bind(this))
7d7a48
         ];
7d7a48
 
7d7a48
         this.connect('scroll-event', this._onScrollEvent.bind(this));
7d7a48
         this._updateMenu();
7d7a48
+        this._updateThumbnails();
7d7a48
+        this._onWorkspaceOrientationChanged();
7d7a48
 
7d7a48
         this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' });
7d7a48
         this._settingsChangedId = this._settings.connect(
7d7a48
@@ -65,17 +97,27 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
         super._onDestroy();
7d7a48
     }
7d7a48
 
7d7a48
+    _onWorkspaceOrientationChanged() {
7d7a48
+        let vertical = global.workspace_manager.layout_rows == -1;
7d7a48
+        this.reactive = vertical;
7d7a48
+
7d7a48
+        this._statusBin.visible = vertical;
7d7a48
+        this._thumbnailsBox.visible = !vertical;
7d7a48
+    }
7d7a48
+
7d7a48
     _onWorkspaceSwitched() {
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
         this._currentWorkspace = workspaceManager.get_active_workspace_index();
7d7a48
 
7d7a48
         this._updateMenuOrnament();
7d7a48
+        this._updateActiveThumbnail();
7d7a48
 
7d7a48
         this._statusLabel.set_text(this._getStatusText());
7d7a48
     }
7d7a48
 
7d7a48
     _nWorkspacesChanged() {
7d7a48
         this._updateMenu();
7d7a48
+        this._updateThumbnails();
7d7a48
     }
7d7a48
 
7d7a48
     _updateMenuOrnament() {
7d7a48
@@ -86,6 +128,16 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
         }
7d7a48
     }
7d7a48
 
7d7a48
+    _updateActiveThumbnail() {
7d7a48
+        let thumbs = this._thumbnailsBox.get_children();
7d7a48
+        for (let i = 0; i < thumbs.length; i++) {
7d7a48
+            if (i == this._currentWorkspace)
7d7a48
+                thumbs[i].add_style_class_name('active');
7d7a48
+            else
7d7a48
+                thumbs[i].remove_style_class_name('active');
7d7a48
+        }
7d7a48
+    }
7d7a48
+
7d7a48
     _getStatusText() {
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
         let current = workspaceManager.get_active_workspace_index();
7d7a48
@@ -128,6 +180,18 @@ var WorkspaceIndicator = GObject.registerClass({
7d7a48
         this._statusLabel.set_text(this._getStatusText());
7d7a48
     }
7d7a48
 
7d7a48
+    _updateThumbnails() {
7d7a48
+        let workspaceManager = global.workspace_manager;
7d7a48
+
7d7a48
+        this._thumbnailsBox.destroy_all_children();
7d7a48
+
7d7a48
+        for (let i = 0; i < workspaceManager.n_workspaces; i++) {
7d7a48
+            let thumb = new WorkspaceThumbnail(i);
7d7a48
+            this._thumbnailsBox.add_actor(thumb);
7d7a48
+        }
7d7a48
+        this._updateActiveThumbnail();
7d7a48
+    }
7d7a48
+
7d7a48
     _activate(index) {
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
 
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From 09e1fab05fe622ea811f9618d7f97ca228f4c282 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Wed, 5 Jun 2019 03:31:16 +0000
7d7a48
Subject: [PATCH 14/22] classic: Add 'horizontal-workspaces' extension
7d7a48
7d7a48
Vertical workspaces are another defining characteristics of GNOME 3,
7d7a48
and thus rather un-classic. That switch was driven by the overall
7d7a48
layout of the overview, and now that we disable the overview in
7d7a48
GNOME Classic, we can just return to the traditional workspace
7d7a48
layout as well.
7d7a48
7d7a48
Add a small extension that does just that.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/72
7d7a48
---
7d7a48
 extensions/horizontal-workspaces/extension.js  | 18 ++++++++++++++++++
7d7a48
 extensions/horizontal-workspaces/meson.build   |  5 +++++
7d7a48
 .../horizontal-workspaces/metadata.json.in     | 10 ++++++++++
7d7a48
 .../horizontal-workspaces/stylesheet.css       |  1 +
7d7a48
 meson.build                                    |  1 +
7d7a48
 5 files changed, 35 insertions(+)
7d7a48
 create mode 100644 extensions/horizontal-workspaces/extension.js
7d7a48
 create mode 100644 extensions/horizontal-workspaces/meson.build
7d7a48
 create mode 100644 extensions/horizontal-workspaces/metadata.json.in
7d7a48
 create mode 100644 extensions/horizontal-workspaces/stylesheet.css
7d7a48
7d7a48
diff --git a/extensions/horizontal-workspaces/extension.js b/extensions/horizontal-workspaces/extension.js
7d7a48
new file mode 100644
7d7a48
index 0000000..b3937ce
7d7a48
--- /dev/null
7d7a48
+++ b/extensions/horizontal-workspaces/extension.js
7d7a48
@@ -0,0 +1,18 @@
7d7a48
+/* exported enable disable */
7d7a48
+const { Meta } = imports.gi;
7d7a48
+
7d7a48
+function enable() {
7d7a48
+    global.workspace_manager.override_workspace_layout(
7d7a48
+        Meta.DisplayCorner.TOPLEFT,
7d7a48
+        false,
7d7a48
+        1,
7d7a48
+        -1);
7d7a48
+}
7d7a48
+
7d7a48
+function disable() {
7d7a48
+    global.workspace_manager.override_workspace_layout(
7d7a48
+        Meta.DisplayCorner.TOPLEFT,
7d7a48
+        false,
7d7a48
+        -1,
7d7a48
+        1);
7d7a48
+}
7d7a48
diff --git a/extensions/horizontal-workspaces/meson.build b/extensions/horizontal-workspaces/meson.build
7d7a48
new file mode 100644
7d7a48
index 0000000..48504f6
7d7a48
--- /dev/null
7d7a48
+++ b/extensions/horizontal-workspaces/meson.build
7d7a48
@@ -0,0 +1,5 @@
7d7a48
+extension_data += configure_file(
7d7a48
+  input: metadata_name + '.in',
7d7a48
+  output: metadata_name,
7d7a48
+  configuration: metadata_conf
7d7a48
+)
7d7a48
diff --git a/extensions/horizontal-workspaces/metadata.json.in b/extensions/horizontal-workspaces/metadata.json.in
7d7a48
new file mode 100644
7d7a48
index 0000000..f109e06
7d7a48
--- /dev/null
7d7a48
+++ b/extensions/horizontal-workspaces/metadata.json.in
7d7a48
@@ -0,0 +1,10 @@
7d7a48
+{
7d7a48
+"extension-id": "@extension_id@",
7d7a48
+"uuid": "@uuid@",
7d7a48
+"settings-schema": "@gschemaname@",
7d7a48
+"gettext-domain": "@gettext_domain@",
7d7a48
+"name": "Horizontal workspaces",
7d7a48
+"description": "Use a horizontal workspace layout",
7d7a48
+"shell-version": [ "@shell_current@" ],
7d7a48
+"url": "@url@"
7d7a48
+}
7d7a48
diff --git a/extensions/horizontal-workspaces/stylesheet.css b/extensions/horizontal-workspaces/stylesheet.css
7d7a48
new file mode 100644
7d7a48
index 0000000..25134b6
7d7a48
--- /dev/null
7d7a48
+++ b/extensions/horizontal-workspaces/stylesheet.css
7d7a48
@@ -0,0 +1 @@
7d7a48
+/* This extensions requires no special styling */
7d7a48
diff --git a/meson.build b/meson.build
7d7a48
index 32743ed..23bd5ad 100644
7d7a48
--- a/meson.build
7d7a48
+++ b/meson.build
7d7a48
@@ -34,6 +34,7 @@ uuid_suffix = '@gnome-shell-extensions.gcampax.github.com'
7d7a48
 classic_extensions = [
7d7a48
   'apps-menu',
7d7a48
   'desktop-icons',
7d7a48
+  'horizontal-workspaces',
7d7a48
   'places-menu',
7d7a48
   'launch-new-instance',
7d7a48
   'top-icons',
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From 85a49ec1e4eb01a32f9bf9b3b8a1bde805936d7b Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Tue, 14 May 2019 19:51:22 +0200
7d7a48
Subject: [PATCH 15/22] window-list: Add window picker button
7d7a48
MIME-Version: 1.0
7d7a48
Content-Type: text/plain; charset=UTF-8
7d7a48
Content-Transfer-Encoding: 8bit
7d7a48
7d7a48
With the latest changes, GNOME Classic has become so classic that it
7d7a48
is bordering dull. Salvage at least a tiny piece of GNOME 3 in form
7d7a48
of a window-pick button which toggles an exposé-like reduced overview.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/73
7d7a48
---
7d7a48
 extensions/window-list/classic.css     |  20 +-
7d7a48
 extensions/window-list/extension.js    |  36 +++-
7d7a48
 extensions/window-list/meson.build     |   2 +-
7d7a48
 extensions/window-list/stylesheet.css  |  27 ++-
7d7a48
 extensions/window-list/windowPicker.js | 250 +++++++++++++++++++++++++
7d7a48
 5 files changed, 322 insertions(+), 13 deletions(-)
7d7a48
 create mode 100644 extensions/window-list/windowPicker.js
7d7a48
7d7a48
diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css
7d7a48
index f3c44a3..c506bea 100644
7d7a48
--- a/extensions/window-list/classic.css
7d7a48
+++ b/extensions/window-list/classic.css
7d7a48
@@ -6,14 +6,13 @@
7d7a48
     height: 2.25em ;
7d7a48
   }
7d7a48
 
7d7a48
-  .bottom-panel .window-button > StWidget {
7d7a48
+  .bottom-panel .window-button > StWidget,
7d7a48
+  .bottom-panel .window-picker-toggle > StWidget {
7d7a48
     background-gradient-drection: vertical;
7d7a48
     background-color: #fff;
7d7a48
     background-gradient-start: #fff;
7d7a48
     background-gradient-end: #eee;
7d7a48
     color: #000;
7d7a48
-    -st-natural-width: 18.7em;
7d7a48
-    max-width: 18.75em;
7d7a48
     color: #2e3436;
7d7a48
     background-color: #eee;
7d7a48
     border-radius: 2px;
7d7a48
@@ -22,7 +21,17 @@
7d7a48
     text-shadow: 0 0 transparent;
7d7a48
   }
7d7a48
 
7d7a48
-  .bottom-panel .window-button:hover > StWidget {
7d7a48
+  .bottom-panel .window-button > StWidget {
7d7a48
+    -st-natural-width: 18.7em;
7d7a48
+    max-width: 18.75em;
7d7a48
+  }
7d7a48
+
7d7a48
+  .bottom-panel .window-picker-toggle > StWidet {
7d7a48
+    border: 1px solid rgba(0,0,0,0.3);
7d7a48
+  }
7d7a48
+
7d7a48
+  .bottom-panel .window-button:hover > StWidget,
7d7a48
+  .bottom-panel .window-picker-toggle:hover > StWidget {
7d7a48
     background-color: #f9f9f9;
7d7a48
   }
7d7a48
 
7d7a48
@@ -31,7 +40,8 @@
7d7a48
     box-shadow: inset 1px 1px 2px rgba(0,0,0,0.5);
7d7a48
   }
7d7a48
 
7d7a48
-  .bottom-panel .window-button.focused > StWidget {
7d7a48
+  .bottom-panel .window-button.focused > StWidget,
7d7a48
+  .bottom-panel .window-picker-toggle:checked > StWidget {
7d7a48
     background-color: #ddd;
7d7a48
     box-shadow: inset 1px 1px 1px rgba(0,0,0,0.5);
7d7a48
   }
7d7a48
diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js
7d7a48
index 5275d9c..1f854aa 100644
7d7a48
--- a/extensions/window-list/extension.js
7d7a48
+++ b/extensions/window-list/extension.js
7d7a48
@@ -3,10 +3,13 @@ const { Clutter, Gio, GLib, Gtk, Meta, Shell, St } = imports.gi;
7d7a48
 
7d7a48
 const DND = imports.ui.dnd;
7d7a48
 const Main = imports.ui.main;
7d7a48
+const Overview = imports.ui.overview;
7d7a48
 const PopupMenu = imports.ui.popupMenu;
7d7a48
+const Tweener = imports.ui.tweener;
7d7a48
 
7d7a48
 const ExtensionUtils = imports.misc.extensionUtils;
7d7a48
 const Me = ExtensionUtils.getCurrentExtension();
7d7a48
+const { WindowPicker, WindowPickerToggle } = Me.imports.windowPicker;
7d7a48
 const { WorkspaceIndicator } = Me.imports.workspaceIndicator;
7d7a48
 
7d7a48
 const Gettext = imports.gettext.domain('gnome-shell-extensions');
7d7a48
@@ -661,6 +664,12 @@ class WindowList {
7d7a48
         let box = new St.BoxLayout({ x_expand: true, y_expand: true });
7d7a48
         this.actor.add_actor(box);
7d7a48
 
7d7a48
+        let toggle = new WindowPickerToggle();
7d7a48
+        box.add_actor(toggle);
7d7a48
+
7d7a48
+        toggle.connect('notify::checked',
7d7a48
+            this._updateWindowListVisibility.bind(this));
7d7a48
+
7d7a48
         let layout = new Clutter.BoxLayout({ homogeneous: true });
7d7a48
         this._windowList = new St.Widget({
7d7a48
             style_class: 'window-list',
7d7a48
@@ -810,6 +819,19 @@ class WindowList {
7d7a48
         this._workspaceIndicator.actor.visible = hasWorkspaces && workspacesOnMonitor;
7d7a48
     }
7d7a48
 
7d7a48
+    _updateWindowListVisibility() {
7d7a48
+        let visible = !Main.windowPicker.visible;
7d7a48
+
7d7a48
+        Tweener.addTween(this._windowList, {
7d7a48
+            opacity: visible ? 255 : 0,
7d7a48
+            transition: 'ease-out-quad',
7d7a48
+            time: Overview.ANIMATION_TIME
7d7a48
+        });
7d7a48
+
7d7a48
+        this._windowList.reactive = visible;
7d7a48
+        this._windowList.get_children().forEach(c => c.reactive = visible);
7d7a48
+    }
7d7a48
+
7d7a48
     _getPreferredUngroupedWindowListWidth() {
7d7a48
         if (this._windowList.get_n_children() == 0)
7d7a48
             return this._windowList.get_preferred_width(-1)[1];
7d7a48
@@ -1080,7 +1102,7 @@ class WindowList {
7d7a48
 class Extension {
7d7a48
     constructor() {
7d7a48
         this._windowLists = null;
7d7a48
-        this._injections = {};
7d7a48
+        this._hideOverviewOrig = Main.overview.hide;
7d7a48
     }
7d7a48
 
7d7a48
     enable() {
7d7a48
@@ -1095,6 +1117,13 @@ class Extension {
7d7a48
             Main.layoutManager.connect('monitors-changed',
7d7a48
                                        this._buildWindowLists.bind(this));
7d7a48
 
7d7a48
+        Main.windowPicker = new WindowPicker();
7d7a48
+
7d7a48
+        Main.overview.hide = () => {
7d7a48
+            Main.windowPicker.close();
7d7a48
+            this._hideOverviewOrig.call(Main.overview);
7d7a48
+        };
7d7a48
+
7d7a48
         this._buildWindowLists();
7d7a48
     }
7d7a48
 
7d7a48
@@ -1125,6 +1154,11 @@ class Extension {
7d7a48
             windowList.actor.destroy();
7d7a48
         });
7d7a48
         this._windowLists = null;
7d7a48
+
7d7a48
+        Main.windowPicker.actor.destroy();
7d7a48
+        delete Main.windowPicker;
7d7a48
+
7d7a48
+        Main.overview.hide = this._hideOverviewOrig;
7d7a48
     }
7d7a48
 
7d7a48
     someWindowListContains(actor) {
7d7a48
diff --git a/extensions/window-list/meson.build b/extensions/window-list/meson.build
7d7a48
index 74025f9..34d7c3f 100644
7d7a48
--- a/extensions/window-list/meson.build
7d7a48
+++ b/extensions/window-list/meson.build
7d7a48
@@ -4,7 +4,7 @@ extension_data += configure_file(
7d7a48
   configuration: metadata_conf
7d7a48
 )
7d7a48
 
7d7a48
-extension_sources += files('prefs.js', 'workspaceIndicator.js')
7d7a48
+extension_sources += files('prefs.js', 'windowPicker.js', 'workspaceIndicator.js')
7d7a48
 extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')
7d7a48
 
7d7a48
 if classic_mode_enabled
7d7a48
diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css
7d7a48
index b383b97..7aee64f 100644
7d7a48
--- a/extensions/window-list/stylesheet.css
7d7a48
+++ b/extensions/window-list/stylesheet.css
7d7a48
@@ -26,9 +26,8 @@
7d7a48
   spacing: 4px;
7d7a48
 }
7d7a48
 
7d7a48
-.window-button > StWidget {
7d7a48
-  -st-natural-width: 18.75em;
7d7a48
-  max-width: 18.75em;
7d7a48
+.window-button > StWidget,
7d7a48
+.window-picker-toggle > StWidget {
7d7a48
   color: #bbb;
7d7a48
   background-color: black;
7d7a48
   border-radius: 4px;
7d7a48
@@ -37,7 +36,21 @@
7d7a48
   text-shadow: 1px 1px 4px rgba(0,0,0,0.8);
7d7a48
 }
7d7a48
 
7d7a48
-.window-button:hover > StWidget {
7d7a48
+.window-picker-toggle {
7d7a48
+  padding: 3px;
7d7a48
+}
7d7a48
+
7d7a48
+.window-picker-toggle > StWidet {
7d7a48
+  border: 1px solid rgba(255,255,255,0.3);
7d7a48
+}
7d7a48
+
7d7a48
+.window-button > StWidget {
7d7a48
+  -st-natural-width: 18.75em;
7d7a48
+  max-width: 18.75em;
7d7a48
+}
7d7a48
+
7d7a48
+.window-button:hover > StWidget,
7d7a48
+.window-picker-toggle:hover > StWidget {
7d7a48
   color: white;
7d7a48
   background-color: #1f1f1f;
7d7a48
 }
7d7a48
@@ -47,12 +60,14 @@
7d7a48
   box-shadow: inset 2px 2px 4px rgba(255,255,255,0.5);
7d7a48
 }
7d7a48
 
7d7a48
-.window-button.focused > StWidget {
7d7a48
+.window-button.focused > StWidget,
7d7a48
+.window-picker-toggle:checked > StWidget {
7d7a48
   color: white;
7d7a48
   box-shadow: inset 1px 1px 4px rgba(255,255,255,0.7);
7d7a48
 }
7d7a48
 
7d7a48
-.window-button.focused:active > StWidget {
7d7a48
+.window-button.focused:active > StWidget,
7d7a48
+.window-picker-toggle:checked:active > StWidget {
7d7a48
   box-shadow: inset 2px 2px 4px rgba(255,255,255,0.7);
7d7a48
 }
7d7a48
 
7d7a48
diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js
7d7a48
new file mode 100644
7d7a48
index 0000000..484f6bb
7d7a48
--- /dev/null
7d7a48
+++ b/extensions/window-list/windowPicker.js
7d7a48
@@ -0,0 +1,250 @@
7d7a48
+/* exported WindowPicker, WindowPickerToggle */
7d7a48
+const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
7d7a48
+const Signals = imports.signals;
7d7a48
+
7d7a48
+const Layout = imports.ui.layout;
7d7a48
+const Main = imports.ui.main;
7d7a48
+const Overview = imports.ui.overview;
7d7a48
+const { WorkspacesDisplay } = imports.ui.workspacesView;
7d7a48
+
7d7a48
+let MyWorkspacesDisplay = class extends WorkspacesDisplay {
7d7a48
+    constructor() {
7d7a48
+        super();
7d7a48
+
7d7a48
+        this.actor.add_constraint(
7d7a48
+            new Layout.MonitorConstraint({
7d7a48
+                primary: true,
7d7a48
+                work_area: true
7d7a48
+            }));
7d7a48
+
7d7a48
+        this.actor.connect('destroy', this._onDestroy.bind(this));
7d7a48
+
7d7a48
+        this._workareasChangedId = global.display.connect('workareas-changed',
7d7a48
+            this._onWorkAreasChanged.bind(this));
7d7a48
+        this._onWorkAreasChanged();
7d7a48
+    }
7d7a48
+
7d7a48
+    show(...args) {
7d7a48
+        if (this._scrollEventId == 0)
7d7a48
+            this._scrollEventId = Main.windowPicker.connect('scroll-event',
7d7a48
+                this._onScrollEvent.bind(this));
7d7a48
+
7d7a48
+        super.show(...args);
7d7a48
+    }
7d7a48
+
7d7a48
+    hide(...args) {
7d7a48
+        if (this._scrollEventId > 0)
7d7a48
+            Main.windowPicker.disconnect(this._scrollEventId);
7d7a48
+        this._scrollEventId = 0;
7d7a48
+
7d7a48
+        super.hide(...args);
7d7a48
+    }
7d7a48
+
7d7a48
+    _onWorkAreasChanged() {
7d7a48
+        let { primaryIndex } = Main.layoutManager;
7d7a48
+        let workarea = Main.layoutManager.getWorkAreaForMonitor(primaryIndex);
7d7a48
+        this.setWorkspacesFullGeometry(workarea);
7d7a48
+    }
7d7a48
+
7d7a48
+    _updateWorkspacesViews() {
7d7a48
+        super._updateWorkspacesViews();
7d7a48
+
7d7a48
+        this._workspacesViews.forEach(v => {
7d7a48
+            Main.layoutManager.overviewGroup.remove_actor(v.actor);
7d7a48
+            Main.windowPicker.actor.add_actor(v.actor);
7d7a48
+        });
7d7a48
+    }
7d7a48
+
7d7a48
+    _onDestroy() {
7d7a48
+        if (this._workareasChangedId)
7d7a48
+            global.display.disconnect(this._workareasChangedId);
7d7a48
+        this._workareasChangedId = 0;
7d7a48
+    }
7d7a48
+};
7d7a48
+
7d7a48
+var WindowPicker = class {
7d7a48
+    constructor() {
7d7a48
+        this._visible = false;
7d7a48
+        this._modal = false;
7d7a48
+
7d7a48
+        this.actor = new Clutter.Actor();
7d7a48
+
7d7a48
+        this.actor.connect('destroy', this._onDestroy.bind(this));
7d7a48
+
7d7a48
+        global.bind_property('screen-width',
7d7a48
+            this.actor, 'width',
7d7a48
+            GObject.BindingFlags.SYNC_CREATE);
7d7a48
+        global.bind_property('screen-height',
7d7a48
+            this.actor, 'height',
7d7a48
+            GObject.BindingFlags.SYNC_CREATE);
7d7a48
+
7d7a48
+        this._backgroundGroup = new Meta.BackgroundGroup({ reactive: true });
7d7a48
+        this.actor.add_child(this._backgroundGroup);
7d7a48
+
7d7a48
+        this._backgroundGroup.connect('scroll-event', (a, ev) => {
7d7a48
+            this.emit('scroll-event', ev);
7d7a48
+        });
7d7a48
+
7d7a48
+        // Trick WorkspacesDisplay constructor into adding actions here
7d7a48
+        let addActionOrig = Main.overview.addAction;
7d7a48
+        Main.overview.addAction = a => this._backgroundGroup.add_action(a);
7d7a48
+
7d7a48
+        this._workspacesDisplay = new MyWorkspacesDisplay();
7d7a48
+        this.actor.add_child(this._workspacesDisplay.actor);
7d7a48
+
7d7a48
+        Main.overview.addAction = addActionOrig;
7d7a48
+
7d7a48
+        this._bgManagers = [];
7d7a48
+
7d7a48
+        this._monitorsChangedId = Main.layoutManager.connect('monitors-changed',
7d7a48
+            this._updateBackgrounds.bind(this));
7d7a48
+        this._updateBackgrounds();
7d7a48
+
7d7a48
+        Main.uiGroup.insert_child_below(this.actor, global.window_group);
7d7a48
+    }
7d7a48
+
7d7a48
+    get visible() {
7d7a48
+        return this._visible;
7d7a48
+    }
7d7a48
+
7d7a48
+    open() {
7d7a48
+        if (this._visible)
7d7a48
+            return;
7d7a48
+
7d7a48
+        this._visible = true;
7d7a48
+
7d7a48
+        if (!this._syncGrab())
7d7a48
+            return;
7d7a48
+
7d7a48
+        this._fakeOverviewVisible(true);
7d7a48
+        this._shadeBackgrounds();
7d7a48
+        this._fakeOverviewAnimation();
7d7a48
+        this._workspacesDisplay.show(false);
7d7a48
+
7d7a48
+        this.emit('open-state-changed', this._visible);
7d7a48
+    }
7d7a48
+
7d7a48
+    close() {
7d7a48
+        if (!this._visible)
7d7a48
+            return;
7d7a48
+
7d7a48
+        this._visible = false;
7d7a48
+
7d7a48
+        if (!this._syncGrab())
7d7a48
+            return;
7d7a48
+
7d7a48
+        this._workspacesDisplay.animateFromOverview(false);
7d7a48
+        this._unshadeBackgrounds();
7d7a48
+        this._fakeOverviewAnimation(() => {
7d7a48
+            this._workspacesDisplay.hide();
7d7a48
+            this._fakeOverviewVisible(false);
7d7a48
+        });
7d7a48
+
7d7a48
+        this.emit('open-state-changed', this._visible);
7d7a48
+    }
7d7a48
+
7d7a48
+    _fakeOverviewAnimation(onComplete) {
7d7a48
+        Main.overview.animationInProgress = true;
7d7a48
+        GLib.timeout_add(
7d7a48
+            GLib.PRIORITY_DEFAULT,
7d7a48
+            Overview.ANIMATION_TIME * 1000,
7d7a48
+            () => {
7d7a48
+                Main.overview.animationInProgress = false;
7d7a48
+                if (onComplete)
7d7a48
+                    onComplete();
7d7a48
+            });
7d7a48
+    }
7d7a48
+
7d7a48
+    _fakeOverviewVisible(visible) {
7d7a48
+        // Fake overview state for WorkspacesDisplay
7d7a48
+        Main.overview.visible = visible;
7d7a48
+
7d7a48
+        // Hide real windows
7d7a48
+        Main.layoutManager._inOverview = visible;
7d7a48
+        Main.layoutManager._updateVisibility();
7d7a48
+    }
7d7a48
+
7d7a48
+    _syncGrab() {
7d7a48
+        if (this._visible) {
7d7a48
+            if (this._modal)
7d7a48
+                return true;
7d7a48
+
7d7a48
+            this._modal = Main.pushModal(this.actor, {
7d7a48
+                actionMode: Shell.ActionMode.OVERVIEW
7d7a48
+            });
7d7a48
+
7d7a48
+            if (!this._modal) {
7d7a48
+                this.hide();
7d7a48
+                return false;
7d7a48
+            }
7d7a48
+        } else if (this._modal) {
7d7a48
+            Main.popModal(this.actor);
7d7a48
+            this._modal = false;
7d7a48
+        }
7d7a48
+        return true;
7d7a48
+    }
7d7a48
+
7d7a48
+    _onDestroy() {
7d7a48
+        if (this._monitorsChangedId)
7d7a48
+            Main.layoutManager.disconnect(this._monitorsChangedId);
7d7a48
+        this._monitorsChangedId = 0;
7d7a48
+    }
7d7a48
+
7d7a48
+    _updateBackgrounds() {
7d7a48
+        Main.overview._updateBackgrounds.call(this);
7d7a48
+    }
7d7a48
+
7d7a48
+    _shadeBackgrounds() {
7d7a48
+        Main.overview._shadeBackgrounds.call(this);
7d7a48
+    }
7d7a48
+
7d7a48
+    _unshadeBackgrounds() {
7d7a48
+        Main.overview._unshadeBackgrounds.call(this);
7d7a48
+    }
7d7a48
+};
7d7a48
+Signals.addSignalMethods(WindowPicker.prototype);
7d7a48
+
7d7a48
+var WindowPickerToggle = GObject.registerClass(
7d7a48
+class WindowPickerToggle extends St.Button {
7d7a48
+    _init() {
7d7a48
+        let iconBin = new St.Widget({
7d7a48
+            layout_manager: new Clutter.BinLayout()
7d7a48
+        });
7d7a48
+        iconBin.add_child(new St.Icon({
7d7a48
+            icon_name: 'focus-windows-symbolic',
7d7a48
+            icon_size: 16,
7d7a48
+            x_expand: true,
7d7a48
+            y_expand: true,
7d7a48
+            x_align: Clutter.ActorAlign.CENTER,
7d7a48
+            y_align: Clutter.ActorAlign.CENTER
7d7a48
+        }));
7d7a48
+        super._init({
7d7a48
+            style_class: 'window-picker-toggle',
7d7a48
+            child: iconBin,
7d7a48
+            visible: !Main.sessionMode.hasOverview,
7d7a48
+            x_fill: true,
7d7a48
+            y_fill: true,
7d7a48
+            toggle_mode: true
7d7a48
+        });
7d7a48
+
7d7a48
+        this.connect('notify::checked', () => {
7d7a48
+            if (this.checked)
7d7a48
+                Main.windowPicker.open();
7d7a48
+            else
7d7a48
+                Main.windowPicker.close();
7d7a48
+        });
7d7a48
+
7d7a48
+        if (!Main.sessionMode.hasOverview) {
7d7a48
+            global.display.connect('overlay-key', () => {
7d7a48
+                if (!Main.windowPicker.visible)
7d7a48
+                    Main.windowPicker.open();
7d7a48
+                else
7d7a48
+                    Main.windowPicker.close();
7d7a48
+            });
7d7a48
+        }
7d7a48
+
7d7a48
+        Main.windowPicker.connect('open-state-changed', () => {
7d7a48
+            this.checked = Main.windowPicker.visible;
7d7a48
+        });
7d7a48
+    }
7d7a48
+});
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From 36f9a7ea01eed0481572459afc81f8fb433b95d3 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Tue, 11 Jun 2019 23:01:20 +0000
7d7a48
Subject: [PATCH 16/22] window-list: Turn workspace thumbs into drop targets
7d7a48
7d7a48
It makes some sense to allow using the workspace indicator for moving
7d7a48
windows between workspaces as well as for workspace switching. This
7d7a48
applies particularly in GNOME classic after we disabled the overview
7d7a48
there, so that there is again a non-shortcut way of moving windows
7d7a48
between workspaces.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/74
7d7a48
---
7d7a48
 extensions/window-list/workspaceIndicator.js | 35 +++++++++++++++++++-
7d7a48
 1 file changed, 34 insertions(+), 1 deletion(-)
7d7a48
7d7a48
diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js
7d7a48
index 1258ed2..8a93e84 100644
7d7a48
--- a/extensions/window-list/workspaceIndicator.js
7d7a48
+++ b/extensions/window-list/workspaceIndicator.js
7d7a48
@@ -1,6 +1,7 @@
7d7a48
 /* exported WorkspaceIndicator */
7d7a48
-const { Clutter, Gio, GObject, Meta, St } = imports.gi;
7d7a48
+const { Clutter, Gio, GObject, Meta, Shell, St } = imports.gi;
7d7a48
 
7d7a48
+const Main = imports.ui.main;
7d7a48
 const PanelMenu = imports.ui.panelMenu;
7d7a48
 const PopupMenu = imports.ui.popupMenu;
7d7a48
 
7d7a48
@@ -16,6 +17,38 @@ let WorkspaceThumbnail = GObject.registerClass({
7d7a48
         });
7d7a48
 
7d7a48
         this._index = index;
7d7a48
+        this._delegate = this; // needed for DND
7d7a48
+
7d7a48
+        this._grabOpEndId = global.display.connect('grab-op-end',
7d7a48
+            (dpy, dpy_, window, grabOp) => {
7d7a48
+                if (grabOp != Meta.GrabOp.MOVING)
7d7a48
+                    return;
7d7a48
+
7d7a48
+                let [x, y] = global.get_pointer();
7d7a48
+                let alloc = Shell.util_get_transformed_allocation(this);
7d7a48
+                if (alloc.contains(x, y))
7d7a48
+                    this._moveWindow(window);
7d7a48
+            });
7d7a48
+
7d7a48
+        this.connect('destroy', () => {
7d7a48
+            global.display.disconnect(this._grabOpEndId);
7d7a48
+        });
7d7a48
+    }
7d7a48
+
7d7a48
+    acceptDrop(source) {
7d7a48
+        if (!source.realWindow)
7d7a48
+            return false;
7d7a48
+
7d7a48
+        let window = source.realWindow.get_meta_window();
7d7a48
+        this._moveWindow(window);
7d7a48
+        return true;
7d7a48
+    }
7d7a48
+
7d7a48
+    _moveWindow(window) {
7d7a48
+        let monitorIndex = Main.layoutManager.findIndexForActor(this);
7d7a48
+        if (monitorIndex != window.get_monitor())
7d7a48
+            window.move_to_monitor(monitorIndex);
7d7a48
+        window.change_workspace_by_index(this._index, false);
7d7a48
     }
7d7a48
 
7d7a48
     // eslint-disable-next-line camelcase
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From 3ac15a848809da6053c224e86c5f5c72243f6c5b Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Sun, 9 Jun 2019 22:58:29 +0000
7d7a48
Subject: [PATCH 17/22] workspace-indicator: Make some properties private
7d7a48
7d7a48
There's no reason why they should be public.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71
7d7a48
---
7d7a48
 extensions/workspace-indicator/extension.js | 30 ++++++++++-----------
7d7a48
 1 file changed, 15 insertions(+), 15 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js
7d7a48
index 3be1268..76224b9 100644
7d7a48
--- a/extensions/workspace-indicator/extension.js
7d7a48
+++ b/extensions/workspace-indicator/extension.js
7d7a48
@@ -23,14 +23,14 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
 
7d7a48
         this._currentWorkspace = workspaceManager.get_active_workspace().index();
7d7a48
-        this.statusLabel = new St.Label({
7d7a48
+        this._statusLabel = new St.Label({
7d7a48
             y_align: Clutter.ActorAlign.CENTER,
7d7a48
             text: this._labelText()
7d7a48
         });
7d7a48
 
7d7a48
-        this.add_actor(this.statusLabel);
7d7a48
+        this.add_actor(this._statusLabel);
7d7a48
 
7d7a48
-        this.workspacesItems = [];
7d7a48
+        this._workspacesItems = [];
7d7a48
         this._workspaceSection = new PopupMenu.PopupMenuSection();
7d7a48
         this.menu.addMenuItem(this._workspaceSection);
7d7a48
 
7d7a48
@@ -46,7 +46,7 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
         this._createWorkspacesSection();
7d7a48
 
7d7a48
         //styling
7d7a48
-        this.statusLabel.add_style_class_name('panel-workspace-indicator');
7d7a48
+        this._statusLabel.add_style_class_name('panel-workspace-indicator');
7d7a48
 
7d7a48
         this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA });
7d7a48
         this._settingsChangedId =
7d7a48
@@ -67,11 +67,11 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
     }
7d7a48
 
7d7a48
     _updateIndicator() {
7d7a48
-        this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE);
7d7a48
+        this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE);
7d7a48
         this._currentWorkspace = global.workspace_manager.get_active_workspace().index();
7d7a48
-        this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT);
7d7a48
+        this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT);
7d7a48
 
7d7a48
-        this.statusLabel.set_text(this._labelText());
7d7a48
+        this._statusLabel.set_text(this._labelText());
7d7a48
     }
7d7a48
 
7d7a48
     _labelText(workspaceIndex) {
7d7a48
@@ -86,24 +86,24 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
 
7d7a48
         this._workspaceSection.removeAll();
7d7a48
-        this.workspacesItems = [];
7d7a48
+        this._workspacesItems = [];
7d7a48
         this._currentWorkspace = workspaceManager.get_active_workspace().index();
7d7a48
 
7d7a48
         let i = 0;
7d7a48
         for (; i < workspaceManager.n_workspaces; i++) {
7d7a48
-            this.workspacesItems[i] = new PopupMenu.PopupMenuItem(this._labelText(i));
7d7a48
-            this._workspaceSection.addMenuItem(this.workspacesItems[i]);
7d7a48
-            this.workspacesItems[i].workspaceId = i;
7d7a48
-            this.workspacesItems[i].label_actor = this.statusLabel;
7d7a48
-            this.workspacesItems[i].connect('activate', (actor, _event) => {
7d7a48
+            this._workspacesItems[i] = new PopupMenu.PopupMenuItem(this._labelText(i));
7d7a48
+            this._workspaceSection.addMenuItem(this._workspacesItems[i]);
7d7a48
+            this._workspacesItems[i].workspaceId = i;
7d7a48
+            this._workspacesItems[i].label_actor = this._statusLabel;
7d7a48
+            this._workspacesItems[i].connect('activate', (actor, _event) => {
7d7a48
                 this._activate(actor.workspaceId);
7d7a48
             });
7d7a48
 
7d7a48
             if (i == this._currentWorkspace)
7d7a48
-                this.workspacesItems[i].setOrnament(PopupMenu.Ornament.DOT);
7d7a48
+                this._workspacesItems[i].setOrnament(PopupMenu.Ornament.DOT);
7d7a48
         }
7d7a48
 
7d7a48
-        this.statusLabel.set_text(this._labelText());
7d7a48
+        this._statusLabel.set_text(this._labelText());
7d7a48
     }
7d7a48
 
7d7a48
     _activate(index) {
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From 2b1cb8c6b27d63ed7093f4b171f0837a193061f5 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Sun, 9 Jun 2019 23:03:55 +0000
7d7a48
Subject: [PATCH 18/22] workspace-indicator: Update workspace names in-place
7d7a48
7d7a48
There's no good reason to rebuild the entire menu on workspace names
7d7a48
changes, we can simply update the labels in-place.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71
7d7a48
---
7d7a48
 extensions/workspace-indicator/extension.js | 11 ++++++++---
7d7a48
 1 file changed, 8 insertions(+), 3 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js
7d7a48
index 76224b9..6bcac0c 100644
7d7a48
--- a/extensions/workspace-indicator/extension.js
7d7a48
+++ b/extensions/workspace-indicator/extension.js
7d7a48
@@ -49,9 +49,9 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
         this._statusLabel.add_style_class_name('panel-workspace-indicator');
7d7a48
 
7d7a48
         this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA });
7d7a48
-        this._settingsChangedId =
7d7a48
-            this._settings.connect(`changed::${WORKSPACE_KEY}`,
7d7a48
-                                   this._createWorkspacesSection.bind(this));
7d7a48
+        this._settingsChangedId = this._settings.connect(
7d7a48
+            `changed::${WORKSPACE_KEY}`,
7d7a48
+            this._updateMenuLabels.bind(this));
7d7a48
     }
7d7a48
 
7d7a48
     _onDestroy() {
7d7a48
@@ -82,6 +82,11 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
         return Meta.prefs_get_workspace_name(workspaceIndex);
7d7a48
     }
7d7a48
 
7d7a48
+    _updateMenuLabels() {
7d7a48
+        for (let i = 0; i < this._workspacesItems.length; i++)
7d7a48
+            this._workspacesItems[i].label.text = this._labelText(i);
7d7a48
+    }
7d7a48
+
7d7a48
     _createWorkspacesSection() {
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
 
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From a16a7c47475a7d19da43597b810ea9224af745b4 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Sun, 9 Jun 2019 23:05:00 +0000
7d7a48
Subject: [PATCH 19/22] workspace-indicator: Minor cleanup
7d7a48
7d7a48
Mutter has a dedicated method for getting the index of the active
7d7a48
workspace, use that instead of getting first the active workspace
7d7a48
and then its index.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71
7d7a48
---
7d7a48
 extensions/workspace-indicator/extension.js | 8 ++++----
7d7a48
 1 file changed, 4 insertions(+), 4 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js
7d7a48
index 6bcac0c..dc31a5c 100644
7d7a48
--- a/extensions/workspace-indicator/extension.js
7d7a48
+++ b/extensions/workspace-indicator/extension.js
7d7a48
@@ -22,7 +22,7 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
 
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
 
7d7a48
-        this._currentWorkspace = workspaceManager.get_active_workspace().index();
7d7a48
+        this._currentWorkspace = workspaceManager.get_active_workspace_index();
7d7a48
         this._statusLabel = new St.Label({
7d7a48
             y_align: Clutter.ActorAlign.CENTER,
7d7a48
             text: this._labelText()
7d7a48
@@ -68,7 +68,7 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
 
7d7a48
     _updateIndicator() {
7d7a48
         this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE);
7d7a48
-        this._currentWorkspace = global.workspace_manager.get_active_workspace().index();
7d7a48
+        this._currentWorkspace = global.workspace_manager.get_active_workspace_index();
7d7a48
         this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT);
7d7a48
 
7d7a48
         this._statusLabel.set_text(this._labelText());
7d7a48
@@ -92,7 +92,7 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
 
7d7a48
         this._workspaceSection.removeAll();
7d7a48
         this._workspacesItems = [];
7d7a48
-        this._currentWorkspace = workspaceManager.get_active_workspace().index();
7d7a48
+        this._currentWorkspace = workspaceManager.get_active_workspace_index();
7d7a48
 
7d7a48
         let i = 0;
7d7a48
         for (; i < workspaceManager.n_workspaces; i++) {
7d7a48
@@ -131,7 +131,7 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
             return;
7d7a48
         }
7d7a48
 
7d7a48
-        let newIndex = global.workspace_manager.get_active_workspace().index() + diff;
7d7a48
+        let newIndex = global.workspace_manager.get_active_workspace_index() + diff;
7d7a48
         this._activate(newIndex);
7d7a48
     }
7d7a48
 });
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From 707dc4df33efd9779e0839c816c1bfd1efffc699 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Sun, 9 Jun 2019 23:09:12 +0000
7d7a48
Subject: [PATCH 20/22] workspace-indicator: Refactor workspace signal handlers
7d7a48
7d7a48
We are about to support a separate representation if horizontal
7d7a48
workspaces are used. To prepare for that, rename the handlers to
7d7a48
something more generic and split out menu-specific bits into a
7d7a48
dedicated help function.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71
7d7a48
---
7d7a48
 extensions/workspace-indicator/extension.js | 31 ++++++++++++++-------
7d7a48
 1 file changed, 21 insertions(+), 10 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js
7d7a48
index dc31a5c..1961b1c 100644
7d7a48
--- a/extensions/workspace-indicator/extension.js
7d7a48
+++ b/extensions/workspace-indicator/extension.js
7d7a48
@@ -34,13 +34,12 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
         this._workspaceSection = new PopupMenu.PopupMenuSection();
7d7a48
         this.menu.addMenuItem(this._workspaceSection);
7d7a48
 
7d7a48
-        this._workspaceManagerSignals = [];
7d7a48
-        this._workspaceManagerSignals.push(workspaceManager.connect_after('workspace-added',
7d7a48
-                                                                          this._createWorkspacesSection.bind(this)));
7d7a48
-        this._workspaceManagerSignals.push(workspaceManager.connect_after('workspace-removed',
7d7a48
-                                                                          this._createWorkspacesSection.bind(this)));
7d7a48
-        this._workspaceManagerSignals.push(workspaceManager.connect_after('workspace-switched',
7d7a48
-                                                                          this._updateIndicator.bind(this)));
7d7a48
+        this._workspaceManagerSignals = [
7d7a48
+            workspaceManager.connect_after('notify::n-workspaces',
7d7a48
+                this._nWorkspacesChanged.bind(this)),
7d7a48
+            workspaceManager.connect_after('workspace-switched',
7d7a48
+                this._onWorkspaceSwitched.bind(this))
7d7a48
+        ];
7d7a48
 
7d7a48
         this.connect('scroll-event', this._onScrollEvent.bind(this));
7d7a48
         this._createWorkspacesSection();
7d7a48
@@ -66,14 +65,26 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
         super._onDestroy();
7d7a48
     }
7d7a48
 
7d7a48
-    _updateIndicator() {
7d7a48
-        this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE);
7d7a48
+    _onWorkspaceSwitched() {
7d7a48
         this._currentWorkspace = global.workspace_manager.get_active_workspace_index();
7d7a48
-        this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT);
7d7a48
+
7d7a48
+        this._updateMenuOrnament();
7d7a48
 
7d7a48
         this._statusLabel.set_text(this._labelText());
7d7a48
     }
7d7a48
 
7d7a48
+    _nWorkspacesChanged() {
7d7a48
+        this._createWorkspacesSection();
7d7a48
+    }
7d7a48
+
7d7a48
+    _updateMenuOrnament() {
7d7a48
+        for (let i = 0; i < this._workspacesItems.length; i++) {
7d7a48
+            this._workspacesItems[i].setOrnament(i == this._currentWorkspace
7d7a48
+                ? PopupMenu.Ornament.DOT
7d7a48
+                : PopupMenu.Ornament.NONE);
7d7a48
+        }
7d7a48
+    }
7d7a48
+
7d7a48
     _labelText(workspaceIndex) {
7d7a48
         if (workspaceIndex == undefined) {
7d7a48
             workspaceIndex = this._currentWorkspace;
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From 83ad6a01f58ae451cc3086a01cdfd500eaa536d2 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Sun, 9 Jun 2019 23:17:35 +0000
7d7a48
Subject: [PATCH 21/22] workspace-indicator: Minor cleanup
7d7a48
7d7a48
Pass the style class at construction time instead of setting it later.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71
7d7a48
---
7d7a48
 extensions/workspace-indicator/extension.js | 4 +---
7d7a48
 1 file changed, 1 insertion(+), 3 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js
7d7a48
index 1961b1c..18f5450 100644
7d7a48
--- a/extensions/workspace-indicator/extension.js
7d7a48
+++ b/extensions/workspace-indicator/extension.js
7d7a48
@@ -24,6 +24,7 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
 
7d7a48
         this._currentWorkspace = workspaceManager.get_active_workspace_index();
7d7a48
         this._statusLabel = new St.Label({
7d7a48
+            style_class: 'panel-workspace-indicator',
7d7a48
             y_align: Clutter.ActorAlign.CENTER,
7d7a48
             text: this._labelText()
7d7a48
         });
7d7a48
@@ -44,9 +45,6 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
         this.connect('scroll-event', this._onScrollEvent.bind(this));
7d7a48
         this._createWorkspacesSection();
7d7a48
 
7d7a48
-        //styling
7d7a48
-        this._statusLabel.add_style_class_name('panel-workspace-indicator');
7d7a48
-
7d7a48
         this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA });
7d7a48
         this._settingsChangedId = this._settings.connect(
7d7a48
             `changed::${WORKSPACE_KEY}`,
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From 4e128c9cbc631fa47f9e5959212c35d9c6d53a01 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Sun, 9 Jun 2019 23:45:24 +0000
7d7a48
Subject: [PATCH 22/22] workspace-indicator: Support horizontal workspace
7d7a48
 layout
7d7a48
7d7a48
Just like we did for the workspace indicator in the window-list, improve
7d7a48
the handling of horizontal workspace layouts by showing the switcher
7d7a48
in-place instead of delegating the functionality to a menu.
7d7a48
7d7a48
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71
7d7a48
---
7d7a48
 extensions/workspace-indicator/extension.js   | 63 ++++++++++++++++++-
7d7a48
 extensions/workspace-indicator/stylesheet.css | 18 +++++-
7d7a48
 2 files changed, 77 insertions(+), 4 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js
7d7a48
index 18f5450..5f7cb7c 100644
7d7a48
--- a/extensions/workspace-indicator/extension.js
7d7a48
+++ b/extensions/workspace-indicator/extension.js
7d7a48
@@ -20,6 +20,13 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
     _init() {
7d7a48
         super._init(0.0, _('Workspace Indicator'));
7d7a48
 
7d7a48
+        let container = new St.Widget({
7d7a48
+            layout_manager: new Clutter.BinLayout(),
7d7a48
+            x_expand: true,
7d7a48
+            y_expand: true
7d7a48
+        });
7d7a48
+        this.add_actor(container);
7d7a48
+
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
 
7d7a48
         this._currentWorkspace = workspaceManager.get_active_workspace_index();
7d7a48
@@ -29,7 +36,15 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
             text: this._labelText()
7d7a48
         });
7d7a48
 
7d7a48
-        this.add_actor(this._statusLabel);
7d7a48
+        container.add_actor(this._statusLabel);
7d7a48
+
7d7a48
+        this._thumbnailsBox = new St.BoxLayout({
7d7a48
+            style_class: 'panel-workspace-indicator-box',
7d7a48
+            y_expand: true,
7d7a48
+            reactive: true
7d7a48
+        });
7d7a48
+
7d7a48
+        container.add_actor(this._thumbnailsBox);
7d7a48
 
7d7a48
         this._workspacesItems = [];
7d7a48
         this._workspaceSection = new PopupMenu.PopupMenuSection();
7d7a48
@@ -39,11 +54,16 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
             workspaceManager.connect_after('notify::n-workspaces',
7d7a48
                 this._nWorkspacesChanged.bind(this)),
7d7a48
             workspaceManager.connect_after('workspace-switched',
7d7a48
-                this._onWorkspaceSwitched.bind(this))
7d7a48
+                this._onWorkspaceSwitched.bind(this)),
7d7a48
+            workspaceManager.connect('notify::layout-rows',
7d7a48
+                this._onWorkspaceOrientationChanged.bind(this))
7d7a48
         ];
7d7a48
 
7d7a48
         this.connect('scroll-event', this._onScrollEvent.bind(this));
7d7a48
+        this._thumbnailsBox.connect('scroll-event', this._onScrollEvent.bind(this));
7d7a48
         this._createWorkspacesSection();
7d7a48
+        this._updateThumbnails();
7d7a48
+        this._onWorkspaceOrientationChanged();
7d7a48
 
7d7a48
         this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA });
7d7a48
         this._settingsChangedId = this._settings.connect(
7d7a48
@@ -63,16 +83,26 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
         super._onDestroy();
7d7a48
     }
7d7a48
 
7d7a48
+    _onWorkspaceOrientationChanged() {
7d7a48
+        let vertical = global.workspace_manager.layout_rows == -1;
7d7a48
+        this.reactive = vertical;
7d7a48
+
7d7a48
+        this._statusLabel.visible = vertical;
7d7a48
+        this._thumbnailsBox.visible = !vertical;
7d7a48
+    }
7d7a48
+
7d7a48
     _onWorkspaceSwitched() {
7d7a48
         this._currentWorkspace = global.workspace_manager.get_active_workspace_index();
7d7a48
 
7d7a48
         this._updateMenuOrnament();
7d7a48
+        this._updateActiveThumbnail();
7d7a48
 
7d7a48
         this._statusLabel.set_text(this._labelText());
7d7a48
     }
7d7a48
 
7d7a48
     _nWorkspacesChanged() {
7d7a48
         this._createWorkspacesSection();
7d7a48
+        this._updateThumbnails();
7d7a48
     }
7d7a48
 
7d7a48
     _updateMenuOrnament() {
7d7a48
@@ -83,6 +113,16 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
         }
7d7a48
     }
7d7a48
 
7d7a48
+    _updateActiveThumbnail() {
7d7a48
+        let thumbs = this._thumbnailsBox.get_children();
7d7a48
+        for (let i = 0; i < thumbs.length; i++) {
7d7a48
+            if (i == this._currentWorkspace)
7d7a48
+                thumbs[i].add_style_class_name('active');
7d7a48
+            else
7d7a48
+                thumbs[i].remove_style_class_name('active');
7d7a48
+        }
7d7a48
+    }
7d7a48
+
7d7a48
     _labelText(workspaceIndex) {
7d7a48
         if (workspaceIndex == undefined) {
7d7a48
             workspaceIndex = this._currentWorkspace;
7d7a48
@@ -120,6 +160,25 @@ class WorkspaceIndicator extends PanelMenu.Button {
7d7a48
         this._statusLabel.set_text(this._labelText());
7d7a48
     }
7d7a48
 
7d7a48
+    _updateThumbnails() {
7d7a48
+        let workspaceManager = global.workspace_manager;
7d7a48
+
7d7a48
+        this._thumbnailsBox.destroy_all_children();
7d7a48
+
7d7a48
+        for (let i = 0; i < workspaceManager.n_workspaces; i++) {
7d7a48
+            let thumb = new St.Button({
7d7a48
+                style_class: 'workspace',
7d7a48
+                child: new St.Label({ text: `${i + 1}` })
7d7a48
+            });
7d7a48
+            thumb.connect('clicked', () => {
7d7a48
+                this._activate(i);
7d7a48
+            });
7d7a48
+
7d7a48
+            this._thumbnailsBox.add_actor(thumb);
7d7a48
+        }
7d7a48
+        this._updateActiveThumbnail();
7d7a48
+    }
7d7a48
+
7d7a48
     _activate(index) {
7d7a48
         let workspaceManager = global.workspace_manager;
7d7a48
 
7d7a48
diff --git a/extensions/workspace-indicator/stylesheet.css b/extensions/workspace-indicator/stylesheet.css
7d7a48
index 1271f1c..a15081e 100644
7d7a48
--- a/extensions/workspace-indicator/stylesheet.css
7d7a48
+++ b/extensions/workspace-indicator/stylesheet.css
7d7a48
@@ -1,5 +1,19 @@
7d7a48
-.panel-workspace-indicator {
7d7a48
+.panel-workspace-indicator,
7d7a48
+.panel-workspace-indicator-box .workspace {
7d7a48
 	padding: 0 8px;
7d7a48
-	background-color: rgba(200, 200, 200, .5);
7d7a48
 	border: 1px solid #cccccc;
7d7a48
 }
7d7a48
+
7d7a48
+.panel-workspace-indicator,
7d7a48
+.panel-workspace-indicator-box .workspace.active {
7d7a48
+	background-color: rgba(200, 200, 200, .5);
7d7a48
+}
7d7a48
+
7d7a48
+.panel-workspace-indicator-box .workspace {
7d7a48
+    background-color: rgba(200, 200, 200, .3);
7d7a48
+    border-left-width: 0;
7d7a48
+}
7d7a48
+
7d7a48
+.panel-workspace-indicator-box .workspace:first-child {
7d7a48
+    border-left-width: 1px;
7d7a48
+}
7d7a48
-- 
7d7a48
2.21.0
7d7a48