From 5c7f737171d9e0acbb8675fc39be6cb943e4a858 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Jan 21 2020 23:13:41 +0000 Subject: import gnome-shell-extensions-3.32.1-10.el8 --- diff --git a/SOURCES/0001-Update-style.patch b/SOURCES/0001-Update-style.patch index 4999c50..8173ded 100644 --- a/SOURCES/0001-Update-style.patch +++ b/SOURCES/0001-Update-style.patch @@ -1,4 +1,4 @@ -From 4137197669569a05d2b4f936c9e5872a8c6a96a5 Mon Sep 17 00:00:00 2001 +From e768ad73e2d68b3f1567051675ba0539a75e3105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sat, 18 May 2019 19:37:05 +0200 Subject: [PATCH] Update style @@ -7,12 +7,31 @@ Subject: [PATCH] Update style data/gnome-shell-sass | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -Submodule data/gnome-shell-sass 1a56956..0116ded: +Submodule data/gnome-shell-sass 1a56956..8842e57: diff --git a/data/gnome-shell-sass/_common.scss b/data/gnome-shell-sass/_common.scss -index a6357ba..b48f4fc 100644 +index a6357ba..62d9c82 100644 --- a/data/gnome-shell-sass/_common.scss +++ b/data/gnome-shell-sass/_common.scss -@@ -680,7 +680,8 @@ StScrollBar { +@@ -571,6 +571,18 @@ StScrollBar { + app menu inside the main app window itself rather than the top bar + */ + ++/************* ++ * App Icons * ++ *************/ ++/* Outline for low res icons */ ++.lowres-icon { ++ icon-shadow: 0 1px 2px rgba(0,0,0,0.3); ++} ++ ++/* Drapshadow for large icons */ ++.icon-dropshadow { ++ icon-shadow: 0 1px 2px rgba(0,0,0,0.4); ++} + + /* OSD */ + .osd-window { +@@ -680,7 +692,8 @@ StScrollBar { spacing: 8px; } @@ -22,7 +41,7 @@ index a6357ba..b48f4fc 100644 height: 50px; background-color: $selected_bg_color; color: $selected_fg_color; -@@ -781,6 +782,11 @@ StScrollBar { +@@ -781,6 +794,11 @@ StScrollBar { color: lighten($fg_color,10%); } @@ -34,7 +53,7 @@ index a6357ba..b48f4fc 100644 .system-status-icon { icon-size: 1.09em; padding: 0 5px; } .unlock-screen &, .login-screen &, -@@ -1406,6 +1412,14 @@ StScrollBar { +@@ -1406,6 +1424,14 @@ StScrollBar { } @@ -49,7 +68,7 @@ index a6357ba..b48f4fc 100644 .app-well-app-running-dot { //running apps indicator width: 10px; height: 3px; background-color: $selected_bg_color; -@@ -1801,7 +1815,12 @@ StScrollBar { +@@ -1801,7 +1827,12 @@ StScrollBar { .login-dialog-banner { color: darken($osd_fg_color,10%); } .login-dialog-button-box { spacing: 5px; } .login-dialog-message-warning { color: $warning_color; } @@ -63,7 +82,7 @@ index a6357ba..b48f4fc 100644 .login-dialog-user-selection-box { padding: 100px 0px; } .login-dialog-not-listed-label { padding-left: 2px; -@@ -1856,6 +1875,10 @@ StScrollBar { +@@ -1856,6 +1887,10 @@ StScrollBar { padding-bottom: 12px; spacing: 8px; width: 23em; diff --git a/SOURCES/0001-apps-menu-Add-missing-chain-up.patch b/SOURCES/0001-apps-menu-Add-missing-chain-up.patch new file mode 100644 index 0000000..35fd0f7 --- /dev/null +++ b/SOURCES/0001-apps-menu-Add-missing-chain-up.patch @@ -0,0 +1,33 @@ +From 0bbeadadc41128b2be1f2b56c60b5a7a671d40da Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 27 Jun 2019 03:57:53 +0200 +Subject: [PATCH] apps-menu: Add missing chain-up + +PanelMenu.Button is a bit weird in that it also "contains" its parent +actor. That container is supposed to be destroyed with the button, but +as we currently don't chain up to the parent class' _onDestroy(), we +leave behind an empty container every time the extension is disabled. + +Fix this by adding the missing chain-up. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/75 +--- + extensions/apps-menu/extension.js | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js +index b9e7111..9803cc1 100644 +--- a/extensions/apps-menu/extension.js ++++ b/extensions/apps-menu/extension.js +@@ -433,6 +433,8 @@ class ApplicationsButton extends PanelMenu.Button { + } + + _onDestroy() { ++ super._onDestroy(); ++ + Main.overview.disconnect(this._showingId); + Main.overview.disconnect(this._hidingId); + appSys.disconnect(this._installedChangedId); +-- +2.21.0 + diff --git a/SOURCES/0001-classic-Shade-panel-in-overview.patch b/SOURCES/0001-classic-Shade-panel-in-overview.patch deleted file mode 100644 index 348a13d..0000000 --- a/SOURCES/0001-classic-Shade-panel-in-overview.patch +++ /dev/null @@ -1,34 +0,0 @@ -From babe8815e035e3cfe99b67e4d450676e43db7353 Mon Sep 17 00:00:00 2001 -From: Jakub Steiner -Date: Tue, 14 Jan 2014 17:00:23 +0100 -Subject: [PATCH] classic: Shade panel in overview - -... rather than using the top bar styling (negative space), -base the overview panel on the classic grey and "darken" -for overview. ---- - data/gnome-classic.scss | 8 +++----- - 1 file changed, 3 insertions(+), 5 deletions(-) - -diff --git a/data/gnome-classic.scss b/data/gnome-classic.scss -index 9e23506..e8f4803 100644 ---- a/data/gnome-classic.scss -+++ b/data/gnome-classic.scss -@@ -19,11 +19,9 @@ $variant: 'light'; - border-bottom: 1px solid #666; - app-icon-bottom-clip: 0px; - &:overview { -- background-color: #000; -- background-gradient-end: #000; -- border-top-color: #000; -- border-bottom: 1px solid #000; -- .panel-button { color: #fff; } -+ background-color: darken($bg_color,5%); -+ background-gradient-end: darken($bg_color,10%); -+ .panel-button { color: darken($fg_color,5%); } - } - - .panel-button { --- -2.21.0 - diff --git a/SOURCES/more-classic-classic-mode.patch b/SOURCES/more-classic-classic-mode.patch index dde41ef..5f0d85b 100644 --- a/SOURCES/more-classic-classic-mode.patch +++ b/SOURCES/more-classic-classic-mode.patch @@ -1,7 +1,86 @@ -From a19128ef885d8a933af364651b21e519f583f82a Mon Sep 17 00:00:00 2001 +From e8425ac158bda015b09861bab4224ca2fdd2b50f Mon Sep 17 00:00:00 2001 +From: Jakub Steiner +Date: Mon, 15 Jul 2019 23:40:09 +0200 +Subject: [PATCH 01/30] classic: hover state for panel buttons + +- prelight before active +- lighten up slightly, similar to what the default does (inverted) + +Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/169 +--- + data/gnome-classic.scss | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/data/gnome-classic.scss b/data/gnome-classic.scss +index 9e23506..9c0e06e 100644 +--- a/data/gnome-classic.scss ++++ b/data/gnome-classic.scss +@@ -32,18 +32,20 @@ $variant: 'light'; + font-weight: normal; + color: $fg_color; + text-shadow: none; ++ &:hover { ++ color: lighten($fg_color,10%); ++ text-shadow: none; ++ & .system-status-icon { icon-shadow: none; } ++ } + &:active, &:overview, &:focus, &:checked { + // Trick due to St limitations. It needs a background to draw + // a box-shadow +- background-color: $selected_bg_color !important; +- color: $selected_fg_color !important; ++ background-color: $selected_bg_color; ++ color: $selected_fg_color; + box-shadow: none; + & > .system-status-icon { icon-shadow: none; } + } +- &:hover { +- text-shadow: none; +- & .system-status-icon { icon-shadow: none; } +- } ++ + .app-menu-icon { width: 0; height: 0; margin: 0; } // shell's display:none; :D + + .system-status-icon { +-- +2.21.0 + + +From fcbb1b1d8956d7447973a9d5ffaa4fede8d359ee Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 18 Jul 2019 00:39:49 +0200 +Subject: [PATCH 02/30] apps-menu: Add drop-shadow to application icons + +... to make sure they are readable on light backgrounds. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/168 +--- + extensions/apps-menu/extension.js | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js +index cc399c6..1f95c16 100644 +--- a/extensions/apps-menu/extension.js ++++ b/extensions/apps-menu/extension.js +@@ -103,7 +103,9 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem { + } + + _updateIcon() { +- this._iconBin.set_child(this.getDragActor()); ++ let icon = this.getDragActor(); ++ icon.style_class = 'icon-dropshadow'; ++ this._iconBin.set_child(icon); + } + } + +-- +2.21.0 + + +From 904e632c62aab6cd89a849a01c56b7c0f123eee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Wed, 29 May 2019 10:17:20 +0000 -Subject: [PATCH 01/22] places-menu: Don't hardcode position +Subject: [PATCH 03/30] places-menu: Don't hardcode position The extension currently assumes that we have the "Activities" button at the left of the top bar. This is currently true, not only in the @@ -40,10 +119,10 @@ index c477a4a..5c038ae 100644 2.21.0 -From 075f6d45b242061be774ba5d3d8c2236cacd64c5 Mon Sep 17 00:00:00 2001 +From 2b1eb285d0c0e113a9be2bd801e1692b48fcfd78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Wed, 29 May 2019 08:32:03 +0000 -Subject: [PATCH 02/22] apps-menu: Stop taking over Activities button +Subject: [PATCH 04/30] apps-menu: Stop taking over Activities button We don't want the "Activities" button in GNOME Classic, but the current way of handling it is confusing: @@ -67,7 +146,7 @@ https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69 1 file changed, 6 insertions(+), 61 deletions(-) diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js -index cc399c6..d6c9c8b 100644 +index 1f95c16..865a87e 100644 --- a/extensions/apps-menu/extension.js +++ b/extensions/apps-menu/extension.js @@ -25,22 +25,6 @@ const NAVIGATION_REGION_OVERSHOOT = 50; @@ -93,7 +172,7 @@ index cc399c6..d6c9c8b 100644 class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem { constructor(button, app) { super(); -@@ -233,21 +217,6 @@ class ApplicationsMenu extends PopupMenu.PopupMenu { +@@ -235,21 +219,6 @@ class ApplicationsMenu extends PopupMenu.PopupMenu { return false; } @@ -115,7 +194,7 @@ index cc399c6..d6c9c8b 100644 toggle() { if (this.isOpen) { this._button.selectCategory(null); -@@ -381,7 +350,7 @@ Signals.addSignalMethods(DesktopTarget.prototype); +@@ -383,7 +352,7 @@ Signals.addSignalMethods(DesktopTarget.prototype); let ApplicationsButton = GObject.registerClass( class ApplicationsButton extends PanelMenu.Button { @@ -124,7 +203,7 @@ index cc399c6..d6c9c8b 100644 super._init(1.0, null, false); this.setMenu(new ApplicationsMenu(this, 1.0, St.Side.TOP, this)); -@@ -398,7 +367,8 @@ class ApplicationsButton extends PanelMenu.Button { +@@ -400,7 +369,8 @@ class ApplicationsButton extends PanelMenu.Button { '/usr/share/icons/hicolor/scalable/apps/start-here.svg'); this._icon = new St.Icon({ gicon: new Gio.FileIcon({ file: iconFile }), @@ -134,7 +213,7 @@ index cc399c6..d6c9c8b 100644 }); hbox.add_actor(this._icon); -@@ -414,8 +384,6 @@ class ApplicationsButton extends PanelMenu.Button { +@@ -416,8 +386,6 @@ class ApplicationsButton extends PanelMenu.Button { this.name = 'panelApplications'; this.label_actor = this._label; @@ -143,7 +222,7 @@ index cc399c6..d6c9c8b 100644 this._showingId = Main.overview.connect('showing', () => { this.add_accessible_state (Atk.StateType.CHECKED); }); -@@ -457,10 +425,6 @@ class ApplicationsButton extends PanelMenu.Button { +@@ -459,10 +427,6 @@ class ApplicationsButton extends PanelMenu.Button { } } @@ -154,7 +233,7 @@ index cc399c6..d6c9c8b 100644 _createVertSeparator() { let separator = new St.DrawingArea({ style_class: 'calendar-vertical-separator', -@@ -487,14 +451,6 @@ class ApplicationsButton extends PanelMenu.Button { +@@ -489,14 +453,6 @@ class ApplicationsButton extends PanelMenu.Button { this._desktopTarget.destroy(); } @@ -169,7 +248,7 @@ index cc399c6..d6c9c8b 100644 _onMenuKeyPress(actor, event) { let symbol = event.get_key_symbol(); if (symbol == Clutter.KEY_Left || symbol == Clutter.KEY_Right) { -@@ -638,14 +594,6 @@ class ApplicationsButton extends PanelMenu.Button { +@@ -640,14 +596,6 @@ class ApplicationsButton extends PanelMenu.Button { y_align: St.Align.START }); @@ -184,7 +263,7 @@ index cc399c6..d6c9c8b 100644 this.applicationsBox = new St.BoxLayout({ vertical: true }); this.applicationsScrollBox.add_actor(this.applicationsBox); this.categoriesBox = new St.BoxLayout({ vertical: true }); -@@ -757,19 +705,16 @@ class ApplicationsButton extends PanelMenu.Button { +@@ -759,19 +707,16 @@ class ApplicationsButton extends PanelMenu.Button { }); let appsMenuButton; @@ -211,10 +290,10 @@ index cc399c6..d6c9c8b 100644 2.21.0 -From e8b2f5206b659398931cfc961954b5d744d52728 Mon Sep 17 00:00:00 2001 +From 45b5f9b8f73032a87017131d8f29b429a8b75ef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Fri, 7 Jun 2019 14:30:16 +0000 -Subject: [PATCH 03/22] apps-menu: Stop hiding the overview when toggled +Subject: [PATCH 05/30] apps-menu: Stop hiding the overview when toggled Now that the extension no longer doubles as the "Activities" button, that behavior is confusing. @@ -225,10 +304,10 @@ https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js -index d6c9c8b..76bcd1a 100644 +index 865a87e..1e2882b 100644 --- a/extensions/apps-menu/extension.js +++ b/extensions/apps-menu/extension.js -@@ -218,12 +218,8 @@ class ApplicationsMenu extends PopupMenu.PopupMenu { +@@ -220,12 +220,8 @@ class ApplicationsMenu extends PopupMenu.PopupMenu { } toggle() { @@ -246,10 +325,10 @@ index d6c9c8b..76bcd1a 100644 2.21.0 -From bcd2c97e89bc90675525dbd05207ae25a91d39df Mon Sep 17 00:00:00 2001 +From 0f143dc87bd501a44843aad7d0a1cd0d20ad4d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Fri, 7 Jun 2019 20:07:19 +0000 -Subject: [PATCH 04/22] apps-menu: Hide overview when launching app +Subject: [PATCH 06/30] apps-menu: Hide overview when launching app Now that we no longer hide the overview when the menu is opened, it is possible to activate menu entries from the overview. Start @@ -262,7 +341,7 @@ https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69 1 file changed, 2 insertions(+) diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js -index 76bcd1a..b9e7111 100644 +index 1e2882b..3dbe43f 100644 --- a/extensions/apps-menu/extension.js +++ b/extensions/apps-menu/extension.js @@ -66,6 +66,8 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem { @@ -278,10 +357,10 @@ index 76bcd1a..b9e7111 100644 2.21.0 -From c118895cff4cedfb43f0ae875d5cd355f66f0db7 Mon Sep 17 00:00:00 2001 +From 72f956cc589d9789ae6ad7b99c1dfd60f9a9f8e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Wed, 29 May 2019 09:44:30 +0000 -Subject: [PATCH 05/22] classic: Disable overview +Subject: [PATCH 07/30] classic: Disable overview The overview is one of the defining features of GNOME 3, and thus almost by definition at odds with the classic session, which @@ -320,1455 +399,1574 @@ index fdb3762..c1c0544 100644 2.21.0 -From 004affc147579e2b1a11614cd0c8faf99e307999 Mon Sep 17 00:00:00 2001 +From 6277f55210a2f1a3283b3eaad7ae1f2cf2f48d8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 5 Jun 2019 00:23:13 +0000 -Subject: [PATCH 06/22] window-list: Split out workspaceIndicator +Date: Tue, 14 May 2019 19:51:22 +0200 +Subject: [PATCH 08/30] window-list: Add window picker button +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit -The extension has grown unwieldily big, so before starting to improve -on the workspace indicator, move it to its own source file. +With the latest changes, GNOME Classic has become so classic that it +is bordering dull. Salvage at least a tiny piece of GNOME 3 in form +of a window-pick button which toggles an exposé-like reduced overview. -https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/73 --- - extensions/window-list/extension.js | 130 +----------------- - extensions/window-list/meson.build | 2 +- - extensions/window-list/workspaceIndicator.js | 135 +++++++++++++++++++ - 3 files changed, 138 insertions(+), 129 deletions(-) - create mode 100644 extensions/window-list/workspaceIndicator.js + extensions/window-list/classic.css | 20 +- + extensions/window-list/extension.js | 36 +++- + extensions/window-list/meson.build | 2 +- + extensions/window-list/stylesheet.css | 27 ++- + extensions/window-list/windowPicker.js | 260 +++++++++++++++++++++++++ + 5 files changed, 332 insertions(+), 13 deletions(-) + create mode 100644 extensions/window-list/windowPicker.js +diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css +index f3c44a3..c506bea 100644 +--- a/extensions/window-list/classic.css ++++ b/extensions/window-list/classic.css +@@ -6,14 +6,13 @@ + height: 2.25em ; + } + +- .bottom-panel .window-button > StWidget { ++ .bottom-panel .window-button > StWidget, ++ .bottom-panel .window-picker-toggle > StWidget { + background-gradient-drection: vertical; + background-color: #fff; + background-gradient-start: #fff; + background-gradient-end: #eee; + color: #000; +- -st-natural-width: 18.7em; +- max-width: 18.75em; + color: #2e3436; + background-color: #eee; + border-radius: 2px; +@@ -22,7 +21,17 @@ + text-shadow: 0 0 transparent; + } + +- .bottom-panel .window-button:hover > StWidget { ++ .bottom-panel .window-button > StWidget { ++ -st-natural-width: 18.7em; ++ max-width: 18.75em; ++ } ++ ++ .bottom-panel .window-picker-toggle > StWidet { ++ border: 1px solid rgba(0,0,0,0.3); ++ } ++ ++ .bottom-panel .window-button:hover > StWidget, ++ .bottom-panel .window-picker-toggle:hover > StWidget { + background-color: #f9f9f9; + } + +@@ -31,7 +40,8 @@ + box-shadow: inset 1px 1px 2px rgba(0,0,0,0.5); + } + +- .bottom-panel .window-button.focused > StWidget { ++ .bottom-panel .window-button.focused > StWidget, ++ .bottom-panel .window-picker-toggle:checked > StWidget { + background-color: #ddd; + box-shadow: inset 1px 1px 1px rgba(0,0,0,0.5); + } diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js -index e1ea742..5275d9c 100644 +index e1ea742..b2784b4 100644 --- a/extensions/window-list/extension.js +++ b/extensions/window-list/extension.js -@@ -1,13 +1,13 @@ - /* exported init */ --const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell, St } = imports.gi; -+const { Clutter, Gio, GLib, Gtk, Meta, Shell, St } = imports.gi; +@@ -3,11 +3,14 @@ const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell, St } = imports.gi; const DND = imports.ui.dnd; const Main = imports.ui.main; --const PanelMenu = imports.ui.panelMenu; ++const Overview = imports.ui.overview; + const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; ++const Tweener = imports.ui.tweener; const ExtensionUtils = imports.misc.extensionUtils; const Me = ExtensionUtils.getCurrentExtension(); -+const { WorkspaceIndicator } = Me.imports.workspaceIndicator; ++const { WindowPicker, WindowPickerToggle } = Me.imports.windowPicker; const Gettext = imports.gettext.domain('gnome-shell-extensions'); const _ = Gettext.gettext; -@@ -644,132 +644,6 @@ class AppButton extends BaseButton { +@@ -787,6 +790,12 @@ class WindowList { + let box = new St.BoxLayout({ x_expand: true, y_expand: true }); + this.actor.add_actor(box); + ++ let toggle = new WindowPickerToggle(); ++ box.add_actor(toggle); ++ ++ toggle.connect('notify::checked', ++ this._updateWindowListVisibility.bind(this)); ++ + let layout = new Clutter.BoxLayout({ homogeneous: true }); + this._windowList = new St.Widget({ + style_class: 'window-list', +@@ -936,6 +945,19 @@ class WindowList { + this._workspaceIndicator.actor.visible = hasWorkspaces && workspacesOnMonitor; + } + ++ _updateWindowListVisibility() { ++ let visible = !Main.windowPicker.visible; ++ ++ Tweener.addTween(this._windowList, { ++ opacity: visible ? 255 : 0, ++ transition: 'ease-out-quad', ++ time: Overview.ANIMATION_TIME ++ }); ++ ++ this._windowList.reactive = visible; ++ this._windowList.get_children().forEach(c => c.reactive = visible); ++ } ++ + _getPreferredUngroupedWindowListWidth() { + if (this._windowList.get_n_children() == 0) + return this._windowList.get_preferred_width(-1)[1]; +@@ -1206,7 +1228,7 @@ class WindowList { + class Extension { + constructor() { + this._windowLists = null; +- this._injections = {}; ++ this._hideOverviewOrig = Main.overview.hide; + } + + enable() { +@@ -1221,6 +1243,13 @@ class Extension { + Main.layoutManager.connect('monitors-changed', + this._buildWindowLists.bind(this)); + ++ Main.windowPicker = new WindowPicker(); ++ ++ Main.overview.hide = () => { ++ Main.windowPicker.close(); ++ this._hideOverviewOrig.call(Main.overview); ++ }; ++ + this._buildWindowLists(); + } + +@@ -1251,6 +1280,11 @@ class Extension { + windowList.actor.destroy(); + }); + this._windowLists = null; ++ ++ Main.windowPicker.actor.destroy(); ++ delete Main.windowPicker; ++ ++ Main.overview.hide = this._hideOverviewOrig; + } + + someWindowListContains(actor) { +diff --git a/extensions/window-list/meson.build b/extensions/window-list/meson.build +index b4aa4db..5b1f5f5 100644 +--- a/extensions/window-list/meson.build ++++ b/extensions/window-list/meson.build +@@ -4,7 +4,7 @@ extension_data += configure_file( + configuration: metadata_conf + ) + +-extension_sources += files('prefs.js') ++extension_sources += files('prefs.js', 'windowPicker.js') + extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml') + + if classic_mode_enabled +diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css +index f5285cb..91383ab 100644 +--- a/extensions/window-list/stylesheet.css ++++ b/extensions/window-list/stylesheet.css +@@ -26,9 +26,8 @@ + spacing: 4px; } +-.window-button > StWidget { +- -st-natural-width: 18.75em; +- max-width: 18.75em; ++.window-button > StWidget, ++.window-picker-toggle > StWidget { + color: #bbb; + background-color: black; + border-radius: 4px; +@@ -37,7 +36,21 @@ + text-shadow: 1px 1px 4px rgba(0,0,0,0.8); + } --let WorkspaceIndicator = GObject.registerClass( --class WorkspaceIndicator extends PanelMenu.Button { -- _init() { -- super._init(0.0, _('Workspace Indicator'), true); -- this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM)); -- this.add_style_class_name('window-list-workspace-indicator'); -- this.menu.actor.remove_style_class_name('panel-menu'); -- -- let container = new St.Widget({ -- layout_manager: new Clutter.BinLayout(), -- x_expand: true, -- y_expand: true -- }); -- this.add_actor(container); -- -- let workspaceManager = global.workspace_manager; -- -- this._currentWorkspace = workspaceManager.get_active_workspace().index(); -- this.statusLabel = new St.Label({ -- text: this._getStatusText(), -- x_align: Clutter.ActorAlign.CENTER, -- y_align: Clutter.ActorAlign.CENTER -- }); -- container.add_actor(this.statusLabel); -- -- this.workspacesItems = []; -- -- this._workspaceManagerSignals = []; -- this._workspaceManagerSignals.push(workspaceManager.connect('notify::n-workspaces', -- this._updateMenu.bind(this))); -- this._workspaceManagerSignals.push(workspaceManager.connect_after('workspace-switched', -- this._updateIndicator.bind(this))); -- -- this.connect('scroll-event', this._onScrollEvent.bind(this)); -- this._updateMenu(); -- -- this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' }); -- this._settingsChangedId = -- this._settings.connect('changed::workspace-names', -- this._updateMenu.bind(this)); -- } -- -- _onDestroy() { -- for (let i = 0; i < this._workspaceManagerSignals.length; i++) -- global.workspace_manager.disconnect(this._workspaceManagerSignals[i]); -- -- if (this._settingsChangedId) { -- this._settings.disconnect(this._settingsChangedId); -- this._settingsChangedId = 0; -- } -- -- super._onDestroy(); -- } -- -- _updateIndicator() { -- this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); -- this._currentWorkspace = global.workspace_manager.get_active_workspace().index(); -- this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); -- -- this.statusLabel.set_text(this._getStatusText()); -- } -- -- _getStatusText() { -- let workspaceManager = global.workspace_manager; -- let current = workspaceManager.get_active_workspace().index(); -- let total = workspaceManager.n_workspaces; -- -- return '%d / %d'.format(current + 1, total); -- } -- -- _updateMenu() { -- let workspaceManager = global.workspace_manager; -- -- this.menu.removeAll(); -- this.workspacesItems = []; -- this._currentWorkspace = workspaceManager.get_active_workspace().index(); -- -- for (let i = 0; i < workspaceManager.n_workspaces; i++) { -- let name = Meta.prefs_get_workspace_name(i); -- let item = new PopupMenu.PopupMenuItem(name); -- item.workspaceId = i; -- -- item.connect('activate', (item, _event) => { -- this._activate(item.workspaceId); -- }); -- -- if (i == this._currentWorkspace) -- item.setOrnament(PopupMenu.Ornament.DOT); -- -- this.menu.addMenuItem(item); -- this.workspacesItems[i] = item; -- } -- -- this.statusLabel.set_text(this._getStatusText()); -- } -- -- _activate(index) { -- let workspaceManager = global.workspace_manager; -- -- if (index >= 0 && index < workspaceManager.n_workspaces) { -- let metaWorkspace = workspaceManager.get_workspace_by_index(index); -- metaWorkspace.activate(global.get_current_time()); -- } -- } -- -- _onScrollEvent(actor, event) { -- let direction = event.get_scroll_direction(); -- let diff = 0; -- if (direction == Clutter.ScrollDirection.DOWN) { -- diff = 1; -- } else if (direction == Clutter.ScrollDirection.UP) { -- diff = -1; -- } else { -- return; -- } -- -- let newIndex = this._currentWorkspace + diff; -- this._activate(newIndex); -- } -- -- _allocate(actor, box, flags) { -- if (actor.get_n_children() > 0) -- actor.get_first_child().allocate(box, flags); -- } --}); -- - class WindowList { - constructor(perMonitor, monitor) { - this._perMonitor = perMonitor; -diff --git a/extensions/window-list/meson.build b/extensions/window-list/meson.build -index b4aa4db..74025f9 100644 ---- a/extensions/window-list/meson.build -+++ b/extensions/window-list/meson.build -@@ -4,7 +4,7 @@ extension_data += configure_file( - configuration: metadata_conf - ) +-.window-button:hover > StWidget { ++.window-picker-toggle { ++ padding: 3px; ++} ++ ++.window-picker-toggle > StWidet { ++ border: 1px solid rgba(255,255,255,0.3); ++} ++ ++.window-button > StWidget { ++ -st-natural-width: 18.75em; ++ max-width: 18.75em; ++} ++ ++.window-button:hover > StWidget, ++.window-picker-toggle:hover > StWidget { + color: white; + background-color: #1f1f1f; + } +@@ -47,12 +60,14 @@ + box-shadow: inset 2px 2px 4px rgba(255,255,255,0.5); + } --extension_sources += files('prefs.js') -+extension_sources += files('prefs.js', 'workspaceIndicator.js') - extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml') +-.window-button.focused > StWidget { ++.window-button.focused > StWidget, ++.window-picker-toggle:checked > StWidget { + color: white; + box-shadow: inset 1px 1px 4px rgba(255,255,255,0.7); + } - if classic_mode_enabled -diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +-.window-button.focused:active > StWidget { ++.window-button.focused:active > StWidget, ++.window-picker-toggle:checked:active > StWidget { + box-shadow: inset 2px 2px 4px rgba(255,255,255,0.7); + } + +diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js new file mode 100644 -index 0000000..fb3ffe7 +index 0000000..024fd80 --- /dev/null -+++ b/extensions/window-list/workspaceIndicator.js -@@ -0,0 +1,135 @@ -+/* exported WorkspaceIndicator */ -+const { Clutter, Gio, GObject, Meta, St } = imports.gi; -+ -+const PanelMenu = imports.ui.panelMenu; -+const PopupMenu = imports.ui.popupMenu; -+ -+const Gettext = imports.gettext.domain('gnome-shell-extensions'); -+const _ = Gettext.gettext; -+ -+var WorkspaceIndicator = GObject.registerClass( -+class WorkspaceIndicator extends PanelMenu.Button { -+ _init() { -+ super._init(0.0, _('Workspace Indicator'), true); -+ this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM)); -+ this.add_style_class_name('window-list-workspace-indicator'); -+ this.menu.actor.remove_style_class_name('panel-menu'); ++++ b/extensions/window-list/windowPicker.js +@@ -0,0 +1,260 @@ ++/* exported WindowPicker, WindowPickerToggle */ ++const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi; ++const Signals = imports.signals; + -+ let container = new St.Widget({ -+ layout_manager: new Clutter.BinLayout(), -+ x_expand: true, -+ y_expand: true -+ }); -+ this.add_actor(container); ++const Layout = imports.ui.layout; ++const Main = imports.ui.main; ++const Overview = imports.ui.overview; ++const { WorkspacesDisplay } = imports.ui.workspacesView; + -+ let workspaceManager = global.workspace_manager; ++let MyWorkspacesDisplay = class extends WorkspacesDisplay { ++ constructor() { ++ super(); + -+ this._currentWorkspace = workspaceManager.get_active_workspace().index(); -+ this.statusLabel = new St.Label({ -+ text: this._getStatusText(), -+ x_align: Clutter.ActorAlign.CENTER, -+ y_align: Clutter.ActorAlign.CENTER -+ }); -+ container.add_actor(this.statusLabel); ++ this.actor.add_constraint( ++ new Layout.MonitorConstraint({ ++ primary: true, ++ work_area: true ++ })); + -+ this.workspacesItems = []; ++ this.actor.connect('destroy', this._onDestroy.bind(this)); + -+ this._workspaceManagerSignals = [ -+ workspaceManager.connect('notify::n-workspaces', -+ this._updateMenu.bind(this)), -+ workspaceManager.connect_after('workspace-switched', -+ this._updateIndicator.bind(this)) -+ ]; ++ this._workareasChangedId = global.display.connect('workareas-changed', ++ this._onWorkAreasChanged.bind(this)); ++ this._onWorkAreasChanged(); ++ } + -+ this.connect('scroll-event', this._onScrollEvent.bind(this)); -+ this._updateMenu(); ++ show(...args) { ++ if (this._scrollEventId == 0) ++ this._scrollEventId = Main.windowPicker.connect('scroll-event', ++ this._onScrollEvent.bind(this)); + -+ this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' }); -+ this._settingsChangedId = this._settings.connect( -+ 'changed::workspace-names', this._updateMenu.bind(this)); ++ super.show(...args); + } + -+ _onDestroy() { -+ for (let i = 0; i < this._workspaceManagerSignals.length; i++) -+ global.workspace_manager.disconnect(this._workspaceManagerSignals[i]); -+ -+ if (this._settingsChangedId) { -+ this._settings.disconnect(this._settingsChangedId); -+ this._settingsChangedId = 0; -+ } ++ hide(...args) { ++ if (this._scrollEventId > 0) ++ Main.windowPicker.disconnect(this._scrollEventId); ++ this._scrollEventId = 0; + -+ super._onDestroy(); ++ super.hide(...args); + } + -+ _updateIndicator() { -+ this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); -+ this._currentWorkspace = global.workspace_manager.get_active_workspace().index(); -+ this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); -+ -+ this.statusLabel.set_text(this._getStatusText()); ++ _onWorkAreasChanged() { ++ let { primaryIndex } = Main.layoutManager; ++ let workarea = Main.layoutManager.getWorkAreaForMonitor(primaryIndex); ++ this.setWorkspacesFullGeometry(workarea); + } + -+ _getStatusText() { -+ let workspaceManager = global.workspace_manager; -+ let current = workspaceManager.get_active_workspace().index(); -+ let total = workspaceManager.n_workspaces; ++ _updateWorkspacesViews() { ++ super._updateWorkspacesViews(); + -+ return '%d / %d'.format(current + 1, total); ++ this._workspacesViews.forEach(v => { ++ Main.layoutManager.overviewGroup.remove_actor(v.actor); ++ Main.windowPicker.actor.add_actor(v.actor); ++ }); + } + -+ _updateMenu() { -+ let workspaceManager = global.workspace_manager; ++ _onDestroy() { ++ if (this._workareasChangedId) ++ global.display.disconnect(this._workareasChangedId); ++ this._workareasChangedId = 0; ++ } ++}; + -+ this.menu.removeAll(); -+ this.workspacesItems = []; -+ this._currentWorkspace = workspaceManager.get_active_workspace().index(); ++var WindowPicker = class { ++ constructor() { ++ this._visible = false; ++ this._modal = false; + -+ for (let i = 0; i < workspaceManager.n_workspaces; i++) { -+ let name = Meta.prefs_get_workspace_name(i); -+ let item = new PopupMenu.PopupMenuItem(name); -+ item.workspaceId = i; ++ this.actor = new Clutter.Actor(); + -+ item.connect('activate', (item, _event) => { -+ this._activate(item.workspaceId); -+ }); ++ this.actor.connect('destroy', this._onDestroy.bind(this)); + -+ if (i == this._currentWorkspace) -+ item.setOrnament(PopupMenu.Ornament.DOT); ++ global.bind_property('screen-width', ++ this.actor, 'width', ++ GObject.BindingFlags.SYNC_CREATE); ++ global.bind_property('screen-height', ++ this.actor, 'height', ++ GObject.BindingFlags.SYNC_CREATE); + -+ this.menu.addMenuItem(item); -+ this.workspacesItems[i] = item; -+ } ++ this._backgroundGroup = new Meta.BackgroundGroup({ reactive: true }); ++ this.actor.add_child(this._backgroundGroup); + -+ this.statusLabel.set_text(this._getStatusText()); ++ this._backgroundGroup.connect('scroll-event', (a, ev) => { ++ this.emit('scroll-event', ev); ++ }); ++ ++ // Trick WorkspacesDisplay constructor into adding actions here ++ let addActionOrig = Main.overview.addAction; ++ Main.overview.addAction = a => this._backgroundGroup.add_action(a); ++ ++ this._workspacesDisplay = new MyWorkspacesDisplay(); ++ this.actor.add_child(this._workspacesDisplay.actor); ++ ++ Main.overview.addAction = addActionOrig; ++ ++ this._bgManagers = []; ++ ++ this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', ++ this._updateBackgrounds.bind(this)); ++ this._updateBackgrounds(); ++ ++ Main.uiGroup.insert_child_below(this.actor, global.window_group); + } + -+ _activate(index) { -+ let workspaceManager = global.workspace_manager; ++ get visible() { ++ return this._visible; ++ } + -+ if (index >= 0 && index < workspaceManager.n_workspaces) { -+ let metaWorkspace = workspaceManager.get_workspace_by_index(index); -+ metaWorkspace.activate(global.get_current_time()); -+ } ++ open() { ++ if (this._visible) ++ return; ++ ++ this._visible = true; ++ ++ if (!this._syncGrab()) ++ return; ++ ++ this._fakeOverviewVisible(true); ++ this._shadeBackgrounds(); ++ this._fakeOverviewAnimation(); ++ this._workspacesDisplay.show(false); ++ ++ this.emit('open-state-changed', this._visible); + } + -+ _onScrollEvent(actor, event) { -+ let direction = event.get_scroll_direction(); -+ let diff = 0; -+ if (direction == Clutter.ScrollDirection.DOWN) { -+ diff = 1; -+ } else if (direction == Clutter.ScrollDirection.UP) { -+ diff = -1; -+ } else { ++ close() { ++ if (!this._visible) ++ return; ++ ++ this._visible = false; ++ ++ if (!this._syncGrab()) + return; ++ ++ this._workspacesDisplay.animateFromOverview(false); ++ this._unshadeBackgrounds(); ++ this._fakeOverviewAnimation(() => { ++ this._workspacesDisplay.hide(); ++ this._fakeOverviewVisible(false); ++ }); ++ ++ this.emit('open-state-changed', this._visible); ++ } ++ ++ _fakeOverviewAnimation(onComplete) { ++ Main.overview.animationInProgress = true; ++ GLib.timeout_add( ++ GLib.PRIORITY_DEFAULT, ++ Overview.ANIMATION_TIME * 1000, ++ () => { ++ Main.overview.animationInProgress = false; ++ if (onComplete) ++ onComplete(); ++ }); ++ } ++ ++ _fakeOverviewVisible(visible) { ++ // Fake overview state for WorkspacesDisplay ++ Main.overview.visible = visible; ++ ++ // Hide real windows ++ Main.layoutManager._inOverview = visible; ++ Main.layoutManager._updateVisibility(); ++ } ++ ++ _syncGrab() { ++ if (this._visible) { ++ if (this._modal) ++ return true; ++ ++ this._modal = Main.pushModal(this.actor, { ++ actionMode: Shell.ActionMode.OVERVIEW ++ }); ++ ++ if (!this._modal) { ++ this.hide(); ++ return false; ++ } ++ } else if (this._modal) { ++ Main.popModal(this.actor); ++ this._modal = false; + } ++ return true; ++ } + -+ let newIndex = this._currentWorkspace + diff; -+ this._activate(newIndex); ++ _onDestroy() { ++ if (this._monitorsChangedId) ++ Main.layoutManager.disconnect(this._monitorsChangedId); ++ this._monitorsChangedId = 0; + } + -+ _allocate(actor, box, flags) { -+ if (actor.get_n_children() > 0) -+ actor.get_first_child().allocate(box, flags); ++ _updateBackgrounds() { ++ Main.overview._updateBackgrounds.call(this); + } -+}); + ++ _shadeBackgrounds() { ++ Main.overview._shadeBackgrounds.call(this); ++ } ++ ++ _unshadeBackgrounds() { ++ Main.overview._unshadeBackgrounds.call(this); ++ } ++}; ++Signals.addSignalMethods(WindowPicker.prototype); ++ ++var WindowPickerToggle = GObject.registerClass( ++class WindowPickerToggle extends St.Button { ++ _init() { ++ let iconBin = new St.Widget({ ++ layout_manager: new Clutter.BinLayout() ++ }); ++ iconBin.add_child(new St.Icon({ ++ icon_name: 'focus-windows-symbolic', ++ icon_size: 16, ++ x_expand: true, ++ y_expand: true, ++ x_align: Clutter.ActorAlign.CENTER, ++ y_align: Clutter.ActorAlign.CENTER ++ })); ++ super._init({ ++ style_class: 'window-picker-toggle', ++ child: iconBin, ++ visible: !Main.sessionMode.hasOverview, ++ x_fill: true, ++ y_fill: true, ++ toggle_mode: true ++ }); ++ ++ this._overlayKeyId = 0; ++ ++ this.connect('destroy', this._onDestroy.bind(this)); ++ ++ this.connect('notify::checked', () => { ++ if (this.checked) ++ Main.windowPicker.open(); ++ else ++ Main.windowPicker.close(); ++ }); ++ ++ if (!Main.sessionMode.hasOverview) { ++ this._overlayKeyId = global.display.connect('overlay-key', () => { ++ if (!Main.windowPicker.visible) ++ Main.windowPicker.open(); ++ else ++ Main.windowPicker.close(); ++ }); ++ } ++ ++ Main.windowPicker.connect('open-state-changed', () => { ++ this.checked = Main.windowPicker.visible; ++ }); ++ } ++ ++ _onDestroy() { ++ if (this._overlayKeyId) ++ global.display.disconnect(this._overlayKeyId); ++ this._overlayKeyId == 0; ++ } ++}); -- 2.21.0 -From cceda34bfcd3de806a7b72bb532e1f8a248accee Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 5 Jun 2019 17:39:53 +0000 -Subject: [PATCH 07/22] window-list: Use a more specific GTypeName for - workspace indicator +From 5d82db41ac53a1c7462e1ee69b155588b3e321fc Mon Sep 17 00:00:00 2001 +From: Jakub Steiner +Date: Mon, 15 Jul 2019 23:03:41 +0200 +Subject: [PATCH 09/30] classic: Update window-list styling -Now that the class inherits from GObject, the generic name easily -conflicts with other classes otherwise, for example with the one -from the workspace-indicator extension. +Make buttons flatter, rounder to match default styling. -https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/82 --- - extensions/window-list/workspaceIndicator.js | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) + extensions/window-list/classic.css | 25 +++++++++---------------- + 1 file changed, 9 insertions(+), 16 deletions(-) -diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js -index fb3ffe7..8ac43eb 100644 ---- a/extensions/window-list/workspaceIndicator.js -+++ b/extensions/window-list/workspaceIndicator.js -@@ -7,8 +7,9 @@ const PopupMenu = imports.ui.popupMenu; - const Gettext = imports.gettext.domain('gnome-shell-extensions'); - const _ = Gettext.gettext; +diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css +index c506bea..cc967e0 100644 +--- a/extensions/window-list/classic.css ++++ b/extensions/window-list/classic.css +@@ -4,21 +4,18 @@ + border-top-width: 1px; + border-bottom-width: 0px; + height: 2.25em ; ++ padding: 2px; + } --var WorkspaceIndicator = GObject.registerClass( --class WorkspaceIndicator extends PanelMenu.Button { -+var WorkspaceIndicator = GObject.registerClass({ -+ GTypeName: 'WindowListWorkspaceIndicator' -+}, class WorkspaceIndicator extends PanelMenu.Button { - _init() { - super._init(0.0, _('Workspace Indicator'), true); - this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM)); + .bottom-panel .window-button > StWidget, + .bottom-panel .window-picker-toggle > StWidget { +- background-gradient-drection: vertical; +- background-color: #fff; +- background-gradient-start: #fff; +- background-gradient-end: #eee; +- color: #000; + color: #2e3436; + background-color: #eee; +- border-radius: 2px; ++ border-radius: 3px; + padding: 3px 6px 1px; +- box-shadow: inset -1px -1px 1px rgba(0,0,0,0.5); +- text-shadow: 0 0 transparent; ++ box-shadow: none; ++ text-shadow: none; ++ border: 1px solid rgba(0,0,0,0.2); + } + + .bottom-panel .window-button > StWidget { +@@ -26,10 +23,6 @@ + max-width: 18.75em; + } + +- .bottom-panel .window-picker-toggle > StWidet { +- border: 1px solid rgba(0,0,0,0.3); +- } +- + .bottom-panel .window-button:hover > StWidget, + .bottom-panel .window-picker-toggle:hover > StWidget { + background-color: #f9f9f9; +@@ -37,13 +30,13 @@ + + .bottom-panel .window-button:active > StWidget, + .bottom-panel .window-button:focus > StWidget { +- box-shadow: inset 1px 1px 2px rgba(0,0,0,0.5); ++ box-shadow: inset 0 1px 3px rgba(0,0,0,0.1); + } + + .bottom-panel .window-button.focused > StWidget, + .bottom-panel .window-picker-toggle:checked > StWidget { +- background-color: #ddd; +- box-shadow: inset 1px 1px 1px rgba(0,0,0,0.5); ++ background-color: #ccc; ++ box-shadow: inset 0 1px 3px rgba(0,0,0,0.1); + } + + .bottom-panel .window-button.focused:hover > StWidget { +@@ -52,5 +45,5 @@ + + .bottom-panel .window-button.minimized > StWidget { + color: #888; +- box-shadow: inset -1px -1px 1px rgba(0,0,0,0.5); ++ box-shadow: none; + } -- 2.21.0 -From 57a97bef2e2cfb88324e9d1540254dca8f5195e3 Mon Sep 17 00:00:00 2001 +From 479a8907063970fb6f7e08cea9a2cd6f2e518b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 5 Jun 2019 04:54:50 +0200 -Subject: [PATCH 08/22] window-list: Make some properties private +Date: Wed, 5 Jun 2019 00:23:13 +0000 +Subject: [PATCH 10/30] window-list: Split out workspaceIndicator -There's no reason why they should be public. +The extension has grown unwieldily big, so before starting to improve +on the workspace indicator, move it to its own source file. https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 --- - extensions/window-list/workspaceIndicator.js | 18 +++++++++--------- - 1 file changed, 9 insertions(+), 9 deletions(-) + extensions/window-list/extension.js | 130 +----------------- + extensions/window-list/meson.build | 2 +- + extensions/window-list/workspaceIndicator.js | 135 +++++++++++++++++++ + 3 files changed, 138 insertions(+), 129 deletions(-) + create mode 100644 extensions/window-list/workspaceIndicator.js -diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js -index 8ac43eb..7c0360a 100644 ---- a/extensions/window-list/workspaceIndicator.js -+++ b/extensions/window-list/workspaceIndicator.js -@@ -26,14 +26,14 @@ var WorkspaceIndicator = GObject.registerClass({ - let workspaceManager = global.workspace_manager; +diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js +index b2784b4..1f854aa 100644 +--- a/extensions/window-list/extension.js ++++ b/extensions/window-list/extension.js +@@ -1,16 +1,16 @@ + /* exported init */ +-const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell, St } = imports.gi; ++const { Clutter, Gio, GLib, Gtk, Meta, Shell, St } = imports.gi; - this._currentWorkspace = workspaceManager.get_active_workspace().index(); -- this.statusLabel = new St.Label({ -+ this._statusLabel = new St.Label({ - text: this._getStatusText(), - x_align: Clutter.ActorAlign.CENTER, - y_align: Clutter.ActorAlign.CENTER - }); -- container.add_actor(this.statusLabel); -+ container.add_actor(this._statusLabel); - -- this.workspacesItems = []; -+ this._workspacesItems = []; - - this._workspaceManagerSignals = [ - workspaceManager.connect('notify::n-workspaces', -@@ -63,11 +63,11 @@ var WorkspaceIndicator = GObject.registerClass({ - } - - _updateIndicator() { -- this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); -+ this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); - this._currentWorkspace = global.workspace_manager.get_active_workspace().index(); -- this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); -+ this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); - -- this.statusLabel.set_text(this._getStatusText()); -+ this._statusLabel.set_text(this._getStatusText()); - } - - _getStatusText() { -@@ -82,7 +82,7 @@ var WorkspaceIndicator = GObject.registerClass({ - let workspaceManager = global.workspace_manager; - - this.menu.removeAll(); -- this.workspacesItems = []; -+ this._workspacesItems = []; - this._currentWorkspace = workspaceManager.get_active_workspace().index(); - - for (let i = 0; i < workspaceManager.n_workspaces; i++) { -@@ -98,10 +98,10 @@ var WorkspaceIndicator = GObject.registerClass({ - item.setOrnament(PopupMenu.Ornament.DOT); - - this.menu.addMenuItem(item); -- this.workspacesItems[i] = item; -+ this._workspacesItems[i] = item; - } - -- this.statusLabel.set_text(this._getStatusText()); -+ this._statusLabel.set_text(this._getStatusText()); - } - - _activate(index) { --- -2.21.0 - - -From 8097536f35b9c64f24e8c1c6c8211024c4f8f01d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 5 Jun 2019 04:57:39 +0200 -Subject: [PATCH 09/22] window-list: Update workspace names in-place - -There's no good reason to rebuild the entire menu on workspace names -changes, we can simply update the labels in-place. - -https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 ---- - extensions/window-list/workspaceIndicator.js | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js -index 7c0360a..9888838 100644 ---- a/extensions/window-list/workspaceIndicator.js -+++ b/extensions/window-list/workspaceIndicator.js -@@ -47,7 +47,7 @@ var WorkspaceIndicator = GObject.registerClass({ - - this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' }); - this._settingsChangedId = this._settings.connect( -- 'changed::workspace-names', this._updateMenu.bind(this)); -+ 'changed::workspace-names', this._updateMenuLabels.bind(this)); - } - - _onDestroy() { -@@ -78,6 +78,14 @@ var WorkspaceIndicator = GObject.registerClass({ - return '%d / %d'.format(current + 1, total); - } + const DND = imports.ui.dnd; + const Main = imports.ui.main; + const Overview = imports.ui.overview; +-const PanelMenu = imports.ui.panelMenu; + const PopupMenu = imports.ui.popupMenu; + const Tweener = imports.ui.tweener; -+ _updateMenuLabels() { -+ for (let i = 0; i < this._workspacesItems.length; i++) { -+ let item = this._workspacesItems[i]; -+ let name = Meta.prefs_get_workspace_name(i); -+ item.label.text = name; -+ } -+ } -+ - _updateMenu() { - let workspaceManager = global.workspace_manager; + const ExtensionUtils = imports.misc.extensionUtils; + const Me = ExtensionUtils.getCurrentExtension(); + const { WindowPicker, WindowPickerToggle } = Me.imports.windowPicker; ++const { WorkspaceIndicator } = Me.imports.workspaceIndicator; --- -2.21.0 - - -From c51e35e0dc9937ab19577be41654f914f1cfe894 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 5 Jun 2019 04:59:19 +0200 -Subject: [PATCH 10/22] window-list: Minor cleanup - -Mutter has a dedicated method for getting the index of the active -workspace, use that instead of getting first the active workspace -and then its index. - -https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 ---- - extensions/window-list/workspaceIndicator.js | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js -index 9888838..1f2e1c1 100644 ---- a/extensions/window-list/workspaceIndicator.js -+++ b/extensions/window-list/workspaceIndicator.js -@@ -25,7 +25,7 @@ var WorkspaceIndicator = GObject.registerClass({ + const Gettext = imports.gettext.domain('gnome-shell-extensions'); + const _ = Gettext.gettext; +@@ -647,132 +647,6 @@ class AppButton extends BaseButton { + } - let workspaceManager = global.workspace_manager; +-let WorkspaceIndicator = GObject.registerClass( +-class WorkspaceIndicator extends PanelMenu.Button { +- _init() { +- super._init(0.0, _('Workspace Indicator'), true); +- this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM)); +- this.add_style_class_name('window-list-workspace-indicator'); +- this.menu.actor.remove_style_class_name('panel-menu'); +- +- let container = new St.Widget({ +- layout_manager: new Clutter.BinLayout(), +- x_expand: true, +- y_expand: true +- }); +- this.add_actor(container); +- +- let workspaceManager = global.workspace_manager; +- - this._currentWorkspace = workspaceManager.get_active_workspace().index(); -+ this._currentWorkspace = workspaceManager.get_active_workspace_index(); - this._statusLabel = new St.Label({ - text: this._getStatusText(), - x_align: Clutter.ActorAlign.CENTER, -@@ -64,7 +64,7 @@ var WorkspaceIndicator = GObject.registerClass({ - - _updateIndicator() { - this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); +- this.statusLabel = new St.Label({ +- text: this._getStatusText(), +- x_align: Clutter.ActorAlign.CENTER, +- y_align: Clutter.ActorAlign.CENTER +- }); +- container.add_actor(this.statusLabel); +- +- this.workspacesItems = []; +- +- this._workspaceManagerSignals = []; +- this._workspaceManagerSignals.push(workspaceManager.connect('notify::n-workspaces', +- this._updateMenu.bind(this))); +- this._workspaceManagerSignals.push(workspaceManager.connect_after('workspace-switched', +- this._updateIndicator.bind(this))); +- +- this.connect('scroll-event', this._onScrollEvent.bind(this)); +- this._updateMenu(); +- +- this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' }); +- this._settingsChangedId = +- this._settings.connect('changed::workspace-names', +- this._updateMenu.bind(this)); +- } +- +- _onDestroy() { +- for (let i = 0; i < this._workspaceManagerSignals.length; i++) +- global.workspace_manager.disconnect(this._workspaceManagerSignals[i]); +- +- if (this._settingsChangedId) { +- this._settings.disconnect(this._settingsChangedId); +- this._settingsChangedId = 0; +- } +- +- super._onDestroy(); +- } +- +- _updateIndicator() { +- this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); - this._currentWorkspace = global.workspace_manager.get_active_workspace().index(); -+ this._currentWorkspace = global.workspace_manager.get_active_workspace_index(); - this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); - - this._statusLabel.set_text(this._getStatusText()); -@@ -72,7 +72,7 @@ var WorkspaceIndicator = GObject.registerClass({ - - _getStatusText() { - let workspaceManager = global.workspace_manager; +- this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); +- +- this.statusLabel.set_text(this._getStatusText()); +- } +- +- _getStatusText() { +- let workspaceManager = global.workspace_manager; - let current = workspaceManager.get_active_workspace().index(); -+ let current = workspaceManager.get_active_workspace_index(); - let total = workspaceManager.n_workspaces; - - return '%d / %d'.format(current + 1, total); -@@ -91,7 +91,7 @@ var WorkspaceIndicator = GObject.registerClass({ - - this.menu.removeAll(); - this._workspacesItems = []; +- let total = workspaceManager.n_workspaces; +- +- return '%d / %d'.format(current + 1, total); +- } +- +- _updateMenu() { +- let workspaceManager = global.workspace_manager; +- +- this.menu.removeAll(); +- this.workspacesItems = []; - this._currentWorkspace = workspaceManager.get_active_workspace().index(); -+ this._currentWorkspace = workspaceManager.get_active_workspace_index(); - - for (let i = 0; i < workspaceManager.n_workspaces; i++) { - let name = Meta.prefs_get_workspace_name(i); --- -2.21.0 - - -From 2eb09e7cc7e830bf4004a7c25a46d285e5e0bac1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 5 Jun 2019 05:11:34 +0200 -Subject: [PATCH 11/22] window-list: Improve workspace label styling - -The border currently looks off - it extends all the way vertically -and leaves zero spacing to the label horizontally. Fix both issues -by setting appropriate padding/margins. - -https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 ---- - extensions/window-list/stylesheet.css | 8 +++----- - extensions/window-list/workspaceIndicator.js | 13 ++++++++----- - 2 files changed, 11 insertions(+), 10 deletions(-) - -diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css -index f5285cb..3d3f2d7 100644 ---- a/extensions/window-list/stylesheet.css -+++ b/extensions/window-list/stylesheet.css -@@ -70,13 +70,11 @@ - height: 24px; - } - --.window-list-workspace-indicator { -- padding: 3px; --} - --.window-list-workspace-indicator > StWidget { -+.window-list-workspace-indicator .status-label-bin { - background-color: rgba(200, 200, 200, .3); - border: 1px solid #cccccc; -+ padding: 0 3px; -+ margin: 3px 0; - } +- for (let i = 0; i < workspaceManager.n_workspaces; i++) { +- let name = Meta.prefs_get_workspace_name(i); +- let item = new PopupMenu.PopupMenuItem(name); +- item.workspaceId = i; +- +- item.connect('activate', (item, _event) => { +- this._activate(item.workspaceId); +- }); +- +- if (i == this._currentWorkspace) +- item.setOrnament(PopupMenu.Ornament.DOT); +- +- this.menu.addMenuItem(item); +- this.workspacesItems[i] = item; +- } +- +- this.statusLabel.set_text(this._getStatusText()); +- } +- +- _activate(index) { +- let workspaceManager = global.workspace_manager; +- +- if (index >= 0 && index < workspaceManager.n_workspaces) { +- let metaWorkspace = workspaceManager.get_workspace_by_index(index); +- metaWorkspace.activate(global.get_current_time()); +- } +- } +- +- _onScrollEvent(actor, event) { +- let direction = event.get_scroll_direction(); +- let diff = 0; +- if (direction == Clutter.ScrollDirection.DOWN) { +- diff = 1; +- } else if (direction == Clutter.ScrollDirection.UP) { +- diff = -1; +- } else { +- return; +- } +- +- let newIndex = this._currentWorkspace + diff; +- this._activate(newIndex); +- } +- +- _allocate(actor, box, flags) { +- if (actor.get_n_children() > 0) +- actor.get_first_child().allocate(box, flags); +- } +-}); +- + class WindowList { + constructor(perMonitor, monitor) { + this._perMonitor = perMonitor; +diff --git a/extensions/window-list/meson.build b/extensions/window-list/meson.build +index 5b1f5f5..34d7c3f 100644 +--- a/extensions/window-list/meson.build ++++ b/extensions/window-list/meson.build +@@ -4,7 +4,7 @@ extension_data += configure_file( + configuration: metadata_conf + ) - .notification { +-extension_sources += files('prefs.js', 'windowPicker.js') ++extension_sources += files('prefs.js', 'windowPicker.js', 'workspaceIndicator.js') + extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml') + + if classic_mode_enabled diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js -index 1f2e1c1..598c516 100644 ---- a/extensions/window-list/workspaceIndicator.js +new file mode 100644 +index 0000000..fb3ffe7 +--- /dev/null +++ b/extensions/window-list/workspaceIndicator.js -@@ -26,12 +26,15 @@ var WorkspaceIndicator = GObject.registerClass({ - let workspaceManager = global.workspace_manager; - - this._currentWorkspace = workspaceManager.get_active_workspace_index(); -- this._statusLabel = new St.Label({ -- text: this._getStatusText(), -- x_align: Clutter.ActorAlign.CENTER, -- y_align: Clutter.ActorAlign.CENTER -+ this._statusLabel = new St.Label({ text: this._getStatusText() }); +@@ -0,0 +1,135 @@ ++/* exported WorkspaceIndicator */ ++const { Clutter, Gio, GObject, Meta, St } = imports.gi; + -+ this._statusBin = new St.Bin({ -+ style_class: 'status-label-bin', ++const PanelMenu = imports.ui.panelMenu; ++const PopupMenu = imports.ui.popupMenu; ++ ++const Gettext = imports.gettext.domain('gnome-shell-extensions'); ++const _ = Gettext.gettext; ++ ++var WorkspaceIndicator = GObject.registerClass( ++class WorkspaceIndicator extends PanelMenu.Button { ++ _init() { ++ super._init(0.0, _('Workspace Indicator'), true); ++ this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM)); ++ this.add_style_class_name('window-list-workspace-indicator'); ++ this.menu.actor.remove_style_class_name('panel-menu'); ++ ++ let container = new St.Widget({ ++ layout_manager: new Clutter.BinLayout(), + x_expand: true, -+ y_expand: true, -+ child: this._statusLabel - }); -- container.add_actor(this._statusLabel); -+ container.add_actor(this._statusBin); - - this._workspacesItems = []; - --- -2.21.0 - - -From 477a532a5f5fb2f8a1ddcfc2277fe62fa1a7fb74 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 5 Jun 2019 05:08:31 +0200 -Subject: [PATCH 12/22] window-list: Refactor workspace signal handlers - -We are about to support a separate representation if horizontal -workspaces are used. To prepare for that, rename the handlers to -something more generic and split out menu-specific bits into a -dedicated help function. - -https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 ---- - extensions/window-list/workspaceIndicator.js | 25 +++++++++++++++----- - 1 file changed, 19 insertions(+), 6 deletions(-) - -diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js -index 598c516..78ca97e 100644 ---- a/extensions/window-list/workspaceIndicator.js -+++ b/extensions/window-list/workspaceIndicator.js -@@ -40,9 +40,9 @@ var WorkspaceIndicator = GObject.registerClass({ - - this._workspaceManagerSignals = [ - workspaceManager.connect('notify::n-workspaces', -- this._updateMenu.bind(this)), -+ this._nWorkspacesChanged.bind(this)), - workspaceManager.connect_after('workspace-switched', -- this._updateIndicator.bind(this)) -+ this._onWorkspaceSwitched.bind(this)) - ]; - - this.connect('scroll-event', this._onScrollEvent.bind(this)); -@@ -65,14 +65,27 @@ var WorkspaceIndicator = GObject.registerClass({ - super._onDestroy(); - } - -- _updateIndicator() { -- this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); -- this._currentWorkspace = global.workspace_manager.get_active_workspace_index(); -- this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); -+ _onWorkspaceSwitched() { ++ y_expand: true ++ }); ++ this.add_actor(container); ++ + let workspaceManager = global.workspace_manager; -+ this._currentWorkspace = workspaceManager.get_active_workspace_index(); + -+ this._updateMenuOrnament(); - - this._statusLabel.set_text(this._getStatusText()); - } - -+ _nWorkspacesChanged() { -+ this._updateMenu(); -+ } ++ this._currentWorkspace = workspaceManager.get_active_workspace().index(); ++ this.statusLabel = new St.Label({ ++ text: this._getStatusText(), ++ x_align: Clutter.ActorAlign.CENTER, ++ y_align: Clutter.ActorAlign.CENTER ++ }); ++ container.add_actor(this.statusLabel); + -+ _updateMenuOrnament() { -+ for (let i = 0; i < this._workspacesItems.length; i++) { -+ this._workspacesItems[i].setOrnament(i == this._currentWorkspace -+ ? PopupMenu.Ornament.DOT -+ : PopupMenu.Ornament.NONE); -+ } -+ } ++ this.workspacesItems = []; + - _getStatusText() { - let workspaceManager = global.workspace_manager; - let current = workspaceManager.get_active_workspace_index(); --- -2.21.0 - - -From 8d2a00ef3a1bbd9c5bccd1542049b22a3bb2a79d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 5 Jun 2019 02:53:38 +0000 -Subject: [PATCH 13/22] window-list: Support horizontal workspace layout - -Unlike in GNOME 2, the workspace indicator we display in the window list -isn't a workspace switcher, but a menu button that allows switching -workspaces via its menu. The reason for that is that a horizontal -in-place switcher would be at odds with the vertical workspace layout -used in GNOME 3. - -However that reasoning doesn't apply when the layout is changed to a -horizontal one, so replace the button with a traditional workspace -switcher in that case. - -https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 ---- - extensions/window-list/stylesheet.css | 24 +++++++ - extensions/window-list/workspaceIndicator.js | 66 +++++++++++++++++++- - 2 files changed, 89 insertions(+), 1 deletion(-) - -diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css -index 3d3f2d7..b383b97 100644 ---- a/extensions/window-list/stylesheet.css -+++ b/extensions/window-list/stylesheet.css -@@ -77,6 +77,30 @@ - margin: 3px 0; - } - -+.window-list-workspace-indicator .workspaces-box { -+ spacing: 3px; -+ padding: 3px; -+} ++ this._workspaceManagerSignals = [ ++ workspaceManager.connect('notify::n-workspaces', ++ this._updateMenu.bind(this)), ++ workspaceManager.connect_after('workspace-switched', ++ this._updateIndicator.bind(this)) ++ ]; + -+.window-list-workspace-indicator .workspace { -+ border: 1px solid #cccccc; -+ width: 52px; -+} ++ this.connect('scroll-event', this._onScrollEvent.bind(this)); ++ this._updateMenu(); + -+.window-list-workspace-indicator .workspace:first-child:ltr, -+.window-list-workspace-indicator .workspace:last-child:rtl { -+ border-radius: 4px 0 0 4px; -+} ++ this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' }); ++ this._settingsChangedId = this._settings.connect( ++ 'changed::workspace-names', this._updateMenu.bind(this)); ++ } + -+.window-list-workspace-indicator .workspace:first-child:rtl, -+.window-list-workspace-indicator .workspace:last-child:ltr { -+ border-radius: 0 4px 4px 0; -+} ++ _onDestroy() { ++ for (let i = 0; i < this._workspaceManagerSignals.length; i++) ++ global.workspace_manager.disconnect(this._workspaceManagerSignals[i]); + -+.window-list-workspace-indicator .workspace.active { -+ background-color: rgba(200, 200, 200, .3); -+} ++ if (this._settingsChangedId) { ++ this._settings.disconnect(this._settingsChangedId); ++ this._settingsChangedId = 0; ++ } + - .notification { - font-weight: normal; - } -diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js -index 78ca97e..1258ed2 100644 ---- a/extensions/window-list/workspaceIndicator.js -+++ b/extensions/window-list/workspaceIndicator.js -@@ -7,6 +7,25 @@ const PopupMenu = imports.ui.popupMenu; - const Gettext = imports.gettext.domain('gnome-shell-extensions'); - const _ = Gettext.gettext; - -+let WorkspaceThumbnail = GObject.registerClass({ -+ GTypeName: 'WindowListWorkspaceThumbnail' -+}, class WorkspaceThumbnail extends St.Button { -+ _init(index) { -+ super._init({ -+ style_class: 'workspace' -+ }); ++ super._onDestroy(); ++ } ++ ++ _updateIndicator() { ++ this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); ++ this._currentWorkspace = global.workspace_manager.get_active_workspace().index(); ++ this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); + -+ this._index = index; ++ this.statusLabel.set_text(this._getStatusText()); + } + -+ // eslint-disable-next-line camelcase -+ on_clicked() { -+ let ws = global.workspace_manager.get_workspace_by_index(this._index); -+ if (ws) -+ ws.activate(global.get_current_time()); ++ _getStatusText() { ++ let workspaceManager = global.workspace_manager; ++ let current = workspaceManager.get_active_workspace().index(); ++ let total = workspaceManager.n_workspaces; ++ ++ return '%d / %d'.format(current + 1, total); + } -+}); + - var WorkspaceIndicator = GObject.registerClass({ - GTypeName: 'WindowListWorkspaceIndicator' - }, class WorkspaceIndicator extends PanelMenu.Button { -@@ -36,17 +55,30 @@ var WorkspaceIndicator = GObject.registerClass({ - }); - container.add_actor(this._statusBin); - -+ this._thumbnailsBox = new St.BoxLayout({ -+ style_class: 'workspaces-box', -+ y_expand: true, -+ reactive: true -+ }); -+ this._thumbnailsBox.connect('scroll-event', -+ this._onScrollEvent.bind(this)); -+ container.add_actor(this._thumbnailsBox); ++ _updateMenu() { ++ let workspaceManager = global.workspace_manager; + - this._workspacesItems = []; - - this._workspaceManagerSignals = [ - workspaceManager.connect('notify::n-workspaces', - this._nWorkspacesChanged.bind(this)), - workspaceManager.connect_after('workspace-switched', -- this._onWorkspaceSwitched.bind(this)) -+ this._onWorkspaceSwitched.bind(this)), -+ workspaceManager.connect('notify::layout-rows', -+ this._onWorkspaceOrientationChanged.bind(this)) - ]; - - this.connect('scroll-event', this._onScrollEvent.bind(this)); - this._updateMenu(); -+ this._updateThumbnails(); -+ this._onWorkspaceOrientationChanged(); - - this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' }); - this._settingsChangedId = this._settings.connect( -@@ -65,17 +97,27 @@ var WorkspaceIndicator = GObject.registerClass({ - super._onDestroy(); - } - -+ _onWorkspaceOrientationChanged() { -+ let vertical = global.workspace_manager.layout_rows == -1; -+ this.reactive = vertical; ++ this.menu.removeAll(); ++ this.workspacesItems = []; ++ this._currentWorkspace = workspaceManager.get_active_workspace().index(); + -+ this._statusBin.visible = vertical; -+ this._thumbnailsBox.visible = !vertical; -+ } ++ for (let i = 0; i < workspaceManager.n_workspaces; i++) { ++ let name = Meta.prefs_get_workspace_name(i); ++ let item = new PopupMenu.PopupMenuItem(name); ++ item.workspaceId = i; ++ ++ item.connect('activate', (item, _event) => { ++ this._activate(item.workspaceId); ++ }); + - _onWorkspaceSwitched() { - let workspaceManager = global.workspace_manager; - this._currentWorkspace = workspaceManager.get_active_workspace_index(); - - this._updateMenuOrnament(); -+ this._updateActiveThumbnail(); - - this._statusLabel.set_text(this._getStatusText()); - } - - _nWorkspacesChanged() { - this._updateMenu(); -+ this._updateThumbnails(); - } - - _updateMenuOrnament() { -@@ -86,6 +128,16 @@ var WorkspaceIndicator = GObject.registerClass({ - } - } - -+ _updateActiveThumbnail() { -+ let thumbs = this._thumbnailsBox.get_children(); -+ for (let i = 0; i < thumbs.length; i++) { + if (i == this._currentWorkspace) -+ thumbs[i].add_style_class_name('active'); -+ else -+ thumbs[i].remove_style_class_name('active'); ++ item.setOrnament(PopupMenu.Ornament.DOT); ++ ++ this.menu.addMenuItem(item); ++ this.workspacesItems[i] = item; + } ++ ++ this.statusLabel.set_text(this._getStatusText()); + } + - _getStatusText() { - let workspaceManager = global.workspace_manager; - let current = workspaceManager.get_active_workspace_index(); -@@ -128,6 +180,18 @@ var WorkspaceIndicator = GObject.registerClass({ - this._statusLabel.set_text(this._getStatusText()); - } - -+ _updateThumbnails() { ++ _activate(index) { + let workspaceManager = global.workspace_manager; + -+ this._thumbnailsBox.destroy_all_children(); ++ if (index >= 0 && index < workspaceManager.n_workspaces) { ++ let metaWorkspace = workspaceManager.get_workspace_by_index(index); ++ metaWorkspace.activate(global.get_current_time()); ++ } ++ } + -+ for (let i = 0; i < workspaceManager.n_workspaces; i++) { -+ let thumb = new WorkspaceThumbnail(i); -+ this._thumbnailsBox.add_actor(thumb); ++ _onScrollEvent(actor, event) { ++ let direction = event.get_scroll_direction(); ++ let diff = 0; ++ if (direction == Clutter.ScrollDirection.DOWN) { ++ diff = 1; ++ } else if (direction == Clutter.ScrollDirection.UP) { ++ diff = -1; ++ } else { ++ return; + } -+ this._updateActiveThumbnail(); ++ ++ let newIndex = this._currentWorkspace + diff; ++ this._activate(newIndex); + } + - _activate(index) { - let workspaceManager = global.workspace_manager; - ++ _allocate(actor, box, flags) { ++ if (actor.get_n_children() > 0) ++ actor.get_first_child().allocate(box, flags); ++ } ++}); ++ -- 2.21.0 -From 09e1fab05fe622ea811f9618d7f97ca228f4c282 Mon Sep 17 00:00:00 2001 +From 3380c9ca5c85a61101bf916a2b326c478d83475e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Wed, 5 Jun 2019 03:31:16 +0000 -Subject: [PATCH 14/22] classic: Add 'horizontal-workspaces' extension - -Vertical workspaces are another defining characteristics of GNOME 3, -and thus rather un-classic. That switch was driven by the overall -layout of the overview, and now that we disable the overview in -GNOME Classic, we can just return to the traditional workspace -layout as well. +Date: Wed, 5 Jun 2019 17:39:53 +0000 +Subject: [PATCH 11/30] window-list: Use a more specific GTypeName for + workspace indicator -Add a small extension that does just that. +Now that the class inherits from GObject, the generic name easily +conflicts with other classes otherwise, for example with the one +from the workspace-indicator extension. -https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/72 +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 --- - extensions/horizontal-workspaces/extension.js | 18 ++++++++++++++++++ - extensions/horizontal-workspaces/meson.build | 5 +++++ - .../horizontal-workspaces/metadata.json.in | 10 ++++++++++ - .../horizontal-workspaces/stylesheet.css | 1 + - meson.build | 1 + - 5 files changed, 35 insertions(+) - create mode 100644 extensions/horizontal-workspaces/extension.js - create mode 100644 extensions/horizontal-workspaces/meson.build - create mode 100644 extensions/horizontal-workspaces/metadata.json.in - create mode 100644 extensions/horizontal-workspaces/stylesheet.css + extensions/window-list/workspaceIndicator.js | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) -diff --git a/extensions/horizontal-workspaces/extension.js b/extensions/horizontal-workspaces/extension.js -new file mode 100644 -index 0000000..b3937ce ---- /dev/null -+++ b/extensions/horizontal-workspaces/extension.js -@@ -0,0 +1,18 @@ -+/* exported enable disable */ -+const { Meta } = imports.gi; -+ -+function enable() { -+ global.workspace_manager.override_workspace_layout( -+ Meta.DisplayCorner.TOPLEFT, -+ false, -+ 1, -+ -1); -+} -+ -+function disable() { -+ global.workspace_manager.override_workspace_layout( -+ Meta.DisplayCorner.TOPLEFT, -+ false, -+ -1, -+ 1); -+} -diff --git a/extensions/horizontal-workspaces/meson.build b/extensions/horizontal-workspaces/meson.build -new file mode 100644 -index 0000000..48504f6 ---- /dev/null -+++ b/extensions/horizontal-workspaces/meson.build -@@ -0,0 +1,5 @@ -+extension_data += configure_file( -+ input: metadata_name + '.in', -+ output: metadata_name, -+ configuration: metadata_conf -+) -diff --git a/extensions/horizontal-workspaces/metadata.json.in b/extensions/horizontal-workspaces/metadata.json.in -new file mode 100644 -index 0000000..f109e06 ---- /dev/null -+++ b/extensions/horizontal-workspaces/metadata.json.in -@@ -0,0 +1,10 @@ -+{ -+"extension-id": "@extension_id@", -+"uuid": "@uuid@", -+"settings-schema": "@gschemaname@", -+"gettext-domain": "@gettext_domain@", -+"name": "Horizontal workspaces", -+"description": "Use a horizontal workspace layout", -+"shell-version": [ "@shell_current@" ], -+"url": "@url@" -+} -diff --git a/extensions/horizontal-workspaces/stylesheet.css b/extensions/horizontal-workspaces/stylesheet.css -new file mode 100644 -index 0000000..25134b6 ---- /dev/null -+++ b/extensions/horizontal-workspaces/stylesheet.css -@@ -0,0 +1 @@ -+/* This extensions requires no special styling */ -diff --git a/meson.build b/meson.build -index 32743ed..23bd5ad 100644 ---- a/meson.build -+++ b/meson.build -@@ -34,6 +34,7 @@ uuid_suffix = '@gnome-shell-extensions.gcampax.github.com' - classic_extensions = [ - 'apps-menu', - 'desktop-icons', -+ 'horizontal-workspaces', - 'places-menu', - 'launch-new-instance', - 'top-icons', +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index fb3ffe7..8ac43eb 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -7,8 +7,9 @@ const PopupMenu = imports.ui.popupMenu; + const Gettext = imports.gettext.domain('gnome-shell-extensions'); + const _ = Gettext.gettext; + +-var WorkspaceIndicator = GObject.registerClass( +-class WorkspaceIndicator extends PanelMenu.Button { ++var WorkspaceIndicator = GObject.registerClass({ ++ GTypeName: 'WindowListWorkspaceIndicator' ++}, class WorkspaceIndicator extends PanelMenu.Button { + _init() { + super._init(0.0, _('Workspace Indicator'), true); + this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM)); -- 2.21.0 -From 85a49ec1e4eb01a32f9bf9b3b8a1bde805936d7b Mon Sep 17 00:00:00 2001 +From ad21dfc00c53420794f940e8710b60d2dd25bb9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Tue, 14 May 2019 19:51:22 +0200 -Subject: [PATCH 15/22] window-list: Add window picker button -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit +Date: Wed, 5 Jun 2019 04:54:50 +0200 +Subject: [PATCH 12/30] window-list: Make some properties private -With the latest changes, GNOME Classic has become so classic that it -is bordering dull. Salvage at least a tiny piece of GNOME 3 in form -of a window-pick button which toggles an exposé-like reduced overview. +There's no reason why they should be public. -https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/73 +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 --- - extensions/window-list/classic.css | 20 +- - extensions/window-list/extension.js | 36 +++- - extensions/window-list/meson.build | 2 +- - extensions/window-list/stylesheet.css | 27 ++- - extensions/window-list/windowPicker.js | 250 +++++++++++++++++++++++++ - 5 files changed, 322 insertions(+), 13 deletions(-) - create mode 100644 extensions/window-list/windowPicker.js + extensions/window-list/workspaceIndicator.js | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) -diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css -index f3c44a3..c506bea 100644 ---- a/extensions/window-list/classic.css -+++ b/extensions/window-list/classic.css -@@ -6,14 +6,13 @@ - height: 2.25em ; - } +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index 8ac43eb..7c0360a 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -26,14 +26,14 @@ var WorkspaceIndicator = GObject.registerClass({ + let workspaceManager = global.workspace_manager; -- .bottom-panel .window-button > StWidget { -+ .bottom-panel .window-button > StWidget, -+ .bottom-panel .window-picker-toggle > StWidget { - background-gradient-drection: vertical; - background-color: #fff; - background-gradient-start: #fff; - background-gradient-end: #eee; - color: #000; -- -st-natural-width: 18.7em; -- max-width: 18.75em; - color: #2e3436; - background-color: #eee; - border-radius: 2px; -@@ -22,7 +21,17 @@ - text-shadow: 0 0 transparent; - } + this._currentWorkspace = workspaceManager.get_active_workspace().index(); +- this.statusLabel = new St.Label({ ++ this._statusLabel = new St.Label({ + text: this._getStatusText(), + x_align: Clutter.ActorAlign.CENTER, + y_align: Clutter.ActorAlign.CENTER + }); +- container.add_actor(this.statusLabel); ++ container.add_actor(this._statusLabel); -- .bottom-panel .window-button:hover > StWidget { -+ .bottom-panel .window-button > StWidget { -+ -st-natural-width: 18.7em; -+ max-width: 18.75em; -+ } -+ -+ .bottom-panel .window-picker-toggle > StWidet { -+ border: 1px solid rgba(0,0,0,0.3); -+ } -+ -+ .bottom-panel .window-button:hover > StWidget, -+ .bottom-panel .window-picker-toggle:hover > StWidget { - background-color: #f9f9f9; - } +- this.workspacesItems = []; ++ this._workspacesItems = []; -@@ -31,7 +40,8 @@ - box-shadow: inset 1px 1px 2px rgba(0,0,0,0.5); - } + this._workspaceManagerSignals = [ + workspaceManager.connect('notify::n-workspaces', +@@ -63,11 +63,11 @@ var WorkspaceIndicator = GObject.registerClass({ + } -- .bottom-panel .window-button.focused > StWidget { -+ .bottom-panel .window-button.focused > StWidget, -+ .bottom-panel .window-picker-toggle:checked > StWidget { - background-color: #ddd; - box-shadow: inset 1px 1px 1px rgba(0,0,0,0.5); - } -diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js -index 5275d9c..1f854aa 100644 ---- a/extensions/window-list/extension.js -+++ b/extensions/window-list/extension.js -@@ -3,10 +3,13 @@ const { Clutter, Gio, GLib, Gtk, Meta, Shell, St } = imports.gi; + _updateIndicator() { +- this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); ++ this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); + this._currentWorkspace = global.workspace_manager.get_active_workspace().index(); +- this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); ++ this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); - const DND = imports.ui.dnd; - const Main = imports.ui.main; -+const Overview = imports.ui.overview; - const PopupMenu = imports.ui.popupMenu; -+const Tweener = imports.ui.tweener; +- this.statusLabel.set_text(this._getStatusText()); ++ this._statusLabel.set_text(this._getStatusText()); + } - const ExtensionUtils = imports.misc.extensionUtils; - const Me = ExtensionUtils.getCurrentExtension(); -+const { WindowPicker, WindowPickerToggle } = Me.imports.windowPicker; - const { WorkspaceIndicator } = Me.imports.workspaceIndicator; + _getStatusText() { +@@ -82,7 +82,7 @@ var WorkspaceIndicator = GObject.registerClass({ + let workspaceManager = global.workspace_manager; - const Gettext = imports.gettext.domain('gnome-shell-extensions'); -@@ -661,6 +664,12 @@ class WindowList { - let box = new St.BoxLayout({ x_expand: true, y_expand: true }); - this.actor.add_actor(box); + this.menu.removeAll(); +- this.workspacesItems = []; ++ this._workspacesItems = []; + this._currentWorkspace = workspaceManager.get_active_workspace().index(); -+ let toggle = new WindowPickerToggle(); -+ box.add_actor(toggle); -+ -+ toggle.connect('notify::checked', -+ this._updateWindowListVisibility.bind(this)); -+ - let layout = new Clutter.BoxLayout({ homogeneous: true }); - this._windowList = new St.Widget({ - style_class: 'window-list', -@@ -810,6 +819,19 @@ class WindowList { - this._workspaceIndicator.actor.visible = hasWorkspaces && workspacesOnMonitor; - } + for (let i = 0; i < workspaceManager.n_workspaces; i++) { +@@ -98,10 +98,10 @@ var WorkspaceIndicator = GObject.registerClass({ + item.setOrnament(PopupMenu.Ornament.DOT); -+ _updateWindowListVisibility() { -+ let visible = !Main.windowPicker.visible; -+ -+ Tweener.addTween(this._windowList, { -+ opacity: visible ? 255 : 0, -+ transition: 'ease-out-quad', -+ time: Overview.ANIMATION_TIME -+ }); -+ -+ this._windowList.reactive = visible; -+ this._windowList.get_children().forEach(c => c.reactive = visible); -+ } -+ - _getPreferredUngroupedWindowListWidth() { - if (this._windowList.get_n_children() == 0) - return this._windowList.get_preferred_width(-1)[1]; -@@ -1080,7 +1102,7 @@ class WindowList { - class Extension { - constructor() { - this._windowLists = null; -- this._injections = {}; -+ this._hideOverviewOrig = Main.overview.hide; + this.menu.addMenuItem(item); +- this.workspacesItems[i] = item; ++ this._workspacesItems[i] = item; + } + +- this.statusLabel.set_text(this._getStatusText()); ++ this._statusLabel.set_text(this._getStatusText()); } - enable() { -@@ -1095,6 +1117,13 @@ class Extension { - Main.layoutManager.connect('monitors-changed', - this._buildWindowLists.bind(this)); + _activate(index) { +-- +2.21.0 + + +From 14515b02845a6fe53c9a76eefc3359183dd8076f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 5 Jun 2019 04:57:39 +0200 +Subject: [PATCH 13/30] window-list: Update workspace names in-place + +There's no good reason to rebuild the entire menu on workspace names +changes, we can simply update the labels in-place. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 +--- + extensions/window-list/workspaceIndicator.js | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index 7c0360a..9888838 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -47,7 +47,7 @@ var WorkspaceIndicator = GObject.registerClass({ -+ Main.windowPicker = new WindowPicker(); -+ -+ Main.overview.hide = () => { -+ Main.windowPicker.close(); -+ this._hideOverviewOrig.call(Main.overview); -+ }; -+ - this._buildWindowLists(); + this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' }); + this._settingsChangedId = this._settings.connect( +- 'changed::workspace-names', this._updateMenu.bind(this)); ++ 'changed::workspace-names', this._updateMenuLabels.bind(this)); } -@@ -1125,6 +1154,11 @@ class Extension { - windowList.actor.destroy(); - }); - this._windowLists = null; -+ -+ Main.windowPicker.actor.destroy(); -+ delete Main.windowPicker; -+ -+ Main.overview.hide = this._hideOverviewOrig; + _onDestroy() { +@@ -78,6 +78,14 @@ var WorkspaceIndicator = GObject.registerClass({ + return '%d / %d'.format(current + 1, total); } - someWindowListContains(actor) { -diff --git a/extensions/window-list/meson.build b/extensions/window-list/meson.build -index 74025f9..34d7c3f 100644 ---- a/extensions/window-list/meson.build -+++ b/extensions/window-list/meson.build -@@ -4,7 +4,7 @@ extension_data += configure_file( - configuration: metadata_conf - ) ++ _updateMenuLabels() { ++ for (let i = 0; i < this._workspacesItems.length; i++) { ++ let item = this._workspacesItems[i]; ++ let name = Meta.prefs_get_workspace_name(i); ++ item.label.text = name; ++ } ++ } ++ + _updateMenu() { + let workspaceManager = global.workspace_manager; + +-- +2.21.0 + + +From 7ecdd7d2c61694df8ca9f76016bd8113bfbd7b51 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 5 Jun 2019 04:59:19 +0200 +Subject: [PATCH 14/30] window-list: Minor cleanup + +Mutter has a dedicated method for getting the index of the active +workspace, use that instead of getting first the active workspace +and then its index. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 +--- + extensions/window-list/workspaceIndicator.js | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index 9888838..1f2e1c1 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -25,7 +25,7 @@ var WorkspaceIndicator = GObject.registerClass({ + + let workspaceManager = global.workspace_manager; + +- this._currentWorkspace = workspaceManager.get_active_workspace().index(); ++ this._currentWorkspace = workspaceManager.get_active_workspace_index(); + this._statusLabel = new St.Label({ + text: this._getStatusText(), + x_align: Clutter.ActorAlign.CENTER, +@@ -64,7 +64,7 @@ var WorkspaceIndicator = GObject.registerClass({ + + _updateIndicator() { + this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); +- this._currentWorkspace = global.workspace_manager.get_active_workspace().index(); ++ this._currentWorkspace = global.workspace_manager.get_active_workspace_index(); + this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); + + this._statusLabel.set_text(this._getStatusText()); +@@ -72,7 +72,7 @@ var WorkspaceIndicator = GObject.registerClass({ --extension_sources += files('prefs.js', 'workspaceIndicator.js') -+extension_sources += files('prefs.js', 'windowPicker.js', 'workspaceIndicator.js') - extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml') + _getStatusText() { + let workspaceManager = global.workspace_manager; +- let current = workspaceManager.get_active_workspace().index(); ++ let current = workspaceManager.get_active_workspace_index(); + let total = workspaceManager.n_workspaces; - if classic_mode_enabled + return '%d / %d'.format(current + 1, total); +@@ -91,7 +91,7 @@ var WorkspaceIndicator = GObject.registerClass({ + + this.menu.removeAll(); + this._workspacesItems = []; +- this._currentWorkspace = workspaceManager.get_active_workspace().index(); ++ this._currentWorkspace = workspaceManager.get_active_workspace_index(); + + for (let i = 0; i < workspaceManager.n_workspaces; i++) { + let name = Meta.prefs_get_workspace_name(i); +-- +2.21.0 + + +From 42ef09c097b297ee68207c4f439ec40e5998baa0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 5 Jun 2019 05:11:34 +0200 +Subject: [PATCH 15/30] window-list: Improve workspace label styling + +The border currently looks off - it extends all the way vertically +and leaves zero spacing to the label horizontally. Fix both issues +by setting appropriate padding/margins. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 +--- + extensions/window-list/stylesheet.css | 8 +++----- + extensions/window-list/workspaceIndicator.js | 13 ++++++++----- + 2 files changed, 11 insertions(+), 10 deletions(-) + diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css -index b383b97..7aee64f 100644 +index 91383ab..bab8f76 100644 --- a/extensions/window-list/stylesheet.css +++ b/extensions/window-list/stylesheet.css -@@ -26,9 +26,8 @@ - spacing: 4px; +@@ -85,13 +85,11 @@ + height: 24px; } --.window-button > StWidget { -- -st-natural-width: 18.75em; -- max-width: 18.75em; -+.window-button > StWidget, -+.window-picker-toggle > StWidget { - color: #bbb; - background-color: black; - border-radius: 4px; -@@ -37,7 +36,21 @@ - text-shadow: 1px 1px 4px rgba(0,0,0,0.8); +-.window-list-workspace-indicator { +- padding: 3px; +-} +- +-.window-list-workspace-indicator > StWidget { ++.window-list-workspace-indicator .status-label-bin { + background-color: rgba(200, 200, 200, .3); + border: 1px solid #cccccc; ++ padding: 0 3px; ++ margin: 3px 0; } --.window-button:hover > StWidget { -+.window-picker-toggle { -+ padding: 3px; -+} -+ -+.window-picker-toggle > StWidet { -+ border: 1px solid rgba(255,255,255,0.3); -+} -+ -+.window-button > StWidget { -+ -st-natural-width: 18.75em; -+ max-width: 18.75em; -+} + .notification { +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index 1f2e1c1..598c516 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -26,12 +26,15 @@ var WorkspaceIndicator = GObject.registerClass({ + let workspaceManager = global.workspace_manager; + + this._currentWorkspace = workspaceManager.get_active_workspace_index(); +- this._statusLabel = new St.Label({ +- text: this._getStatusText(), +- x_align: Clutter.ActorAlign.CENTER, +- y_align: Clutter.ActorAlign.CENTER ++ this._statusLabel = new St.Label({ text: this._getStatusText() }); + -+.window-button:hover > StWidget, -+.window-picker-toggle:hover > StWidget { - color: white; - background-color: #1f1f1f; - } -@@ -47,12 +60,14 @@ - box-shadow: inset 2px 2px 4px rgba(255,255,255,0.5); - } ++ this._statusBin = new St.Bin({ ++ style_class: 'status-label-bin', ++ x_expand: true, ++ y_expand: true, ++ child: this._statusLabel + }); +- container.add_actor(this._statusLabel); ++ container.add_actor(this._statusBin); --.window-button.focused > StWidget { -+.window-button.focused > StWidget, -+.window-picker-toggle:checked > StWidget { - color: white; - box-shadow: inset 1px 1px 4px rgba(255,255,255,0.7); - } + this._workspacesItems = []; --.window-button.focused:active > StWidget { -+.window-button.focused:active > StWidget, -+.window-picker-toggle:checked:active > StWidget { - box-shadow: inset 2px 2px 4px rgba(255,255,255,0.7); - } +-- +2.21.0 + + +From 0bf800b529ddfdc8663c63ff5fbf4ba5ac5d64d3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 5 Jun 2019 05:08:31 +0200 +Subject: [PATCH 16/30] window-list: Refactor workspace signal handlers + +We are about to support a separate representation if horizontal +workspaces are used. To prepare for that, rename the handlers to +something more generic and split out menu-specific bits into a +dedicated help function. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 +--- + extensions/window-list/workspaceIndicator.js | 25 +++++++++++++++----- + 1 file changed, 19 insertions(+), 6 deletions(-) + +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index 598c516..78ca97e 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -40,9 +40,9 @@ var WorkspaceIndicator = GObject.registerClass({ -diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js -new file mode 100644 -index 0000000..484f6bb ---- /dev/null -+++ b/extensions/window-list/windowPicker.js -@@ -0,0 +1,250 @@ -+/* exported WindowPicker, WindowPickerToggle */ -+const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi; -+const Signals = imports.signals; -+ -+const Layout = imports.ui.layout; -+const Main = imports.ui.main; -+const Overview = imports.ui.overview; -+const { WorkspacesDisplay } = imports.ui.workspacesView; -+ -+let MyWorkspacesDisplay = class extends WorkspacesDisplay { -+ constructor() { -+ super(); -+ -+ this.actor.add_constraint( -+ new Layout.MonitorConstraint({ -+ primary: true, -+ work_area: true -+ })); -+ -+ this.actor.connect('destroy', this._onDestroy.bind(this)); -+ -+ this._workareasChangedId = global.display.connect('workareas-changed', -+ this._onWorkAreasChanged.bind(this)); -+ this._onWorkAreasChanged(); -+ } -+ -+ show(...args) { -+ if (this._scrollEventId == 0) -+ this._scrollEventId = Main.windowPicker.connect('scroll-event', -+ this._onScrollEvent.bind(this)); -+ -+ super.show(...args); -+ } -+ -+ hide(...args) { -+ if (this._scrollEventId > 0) -+ Main.windowPicker.disconnect(this._scrollEventId); -+ this._scrollEventId = 0; -+ -+ super.hide(...args); -+ } -+ -+ _onWorkAreasChanged() { -+ let { primaryIndex } = Main.layoutManager; -+ let workarea = Main.layoutManager.getWorkAreaForMonitor(primaryIndex); -+ this.setWorkspacesFullGeometry(workarea); -+ } -+ -+ _updateWorkspacesViews() { -+ super._updateWorkspacesViews(); -+ -+ this._workspacesViews.forEach(v => { -+ Main.layoutManager.overviewGroup.remove_actor(v.actor); -+ Main.windowPicker.actor.add_actor(v.actor); -+ }); -+ } -+ -+ _onDestroy() { -+ if (this._workareasChangedId) -+ global.display.disconnect(this._workareasChangedId); -+ this._workareasChangedId = 0; -+ } -+}; -+ -+var WindowPicker = class { -+ constructor() { -+ this._visible = false; -+ this._modal = false; -+ -+ this.actor = new Clutter.Actor(); -+ -+ this.actor.connect('destroy', this._onDestroy.bind(this)); -+ -+ global.bind_property('screen-width', -+ this.actor, 'width', -+ GObject.BindingFlags.SYNC_CREATE); -+ global.bind_property('screen-height', -+ this.actor, 'height', -+ GObject.BindingFlags.SYNC_CREATE); -+ -+ this._backgroundGroup = new Meta.BackgroundGroup({ reactive: true }); -+ this.actor.add_child(this._backgroundGroup); -+ -+ this._backgroundGroup.connect('scroll-event', (a, ev) => { -+ this.emit('scroll-event', ev); -+ }); -+ -+ // Trick WorkspacesDisplay constructor into adding actions here -+ let addActionOrig = Main.overview.addAction; -+ Main.overview.addAction = a => this._backgroundGroup.add_action(a); -+ -+ this._workspacesDisplay = new MyWorkspacesDisplay(); -+ this.actor.add_child(this._workspacesDisplay.actor); -+ -+ Main.overview.addAction = addActionOrig; -+ -+ this._bgManagers = []; -+ -+ this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', -+ this._updateBackgrounds.bind(this)); -+ this._updateBackgrounds(); + this._workspaceManagerSignals = [ + workspaceManager.connect('notify::n-workspaces', +- this._updateMenu.bind(this)), ++ this._nWorkspacesChanged.bind(this)), + workspaceManager.connect_after('workspace-switched', +- this._updateIndicator.bind(this)) ++ this._onWorkspaceSwitched.bind(this)) + ]; + + this.connect('scroll-event', this._onScrollEvent.bind(this)); +@@ -65,14 +65,27 @@ var WorkspaceIndicator = GObject.registerClass({ + super._onDestroy(); + } + +- _updateIndicator() { +- this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); +- this._currentWorkspace = global.workspace_manager.get_active_workspace_index(); +- this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); ++ _onWorkspaceSwitched() { ++ let workspaceManager = global.workspace_manager; ++ this._currentWorkspace = workspaceManager.get_active_workspace_index(); + -+ Main.uiGroup.insert_child_below(this.actor, global.window_group); ++ this._updateMenuOrnament(); + + this._statusLabel.set_text(this._getStatusText()); + } + ++ _nWorkspacesChanged() { ++ this._updateMenu(); + } + -+ get visible() { -+ return this._visible; ++ _updateMenuOrnament() { ++ for (let i = 0; i < this._workspacesItems.length; i++) { ++ this._workspacesItems[i].setOrnament(i == this._currentWorkspace ++ ? PopupMenu.Ornament.DOT ++ : PopupMenu.Ornament.NONE); ++ } + } + -+ open() { -+ if (this._visible) -+ return; + _getStatusText() { + let workspaceManager = global.workspace_manager; + let current = workspaceManager.get_active_workspace_index(); +-- +2.21.0 + + +From 263aeea7be1e5bd244664bb3aefd9b81d8a80e32 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 5 Jun 2019 02:53:38 +0000 +Subject: [PATCH 17/30] window-list: Support horizontal workspace layout + +Unlike in GNOME 2, the workspace indicator we display in the window list +isn't a workspace switcher, but a menu button that allows switching +workspaces via its menu. The reason for that is that a horizontal +in-place switcher would be at odds with the vertical workspace layout +used in GNOME 3. + +However that reasoning doesn't apply when the layout is changed to a +horizontal one, so replace the button with a traditional workspace +switcher in that case. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 +--- + extensions/window-list/classic.css | 9 +++ + extensions/window-list/stylesheet.css | 29 +++++++++ + extensions/window-list/workspaceIndicator.js | 66 +++++++++++++++++++- + 3 files changed, 103 insertions(+), 1 deletion(-) + +diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css +index cc967e0..c533473 100644 +--- a/extensions/window-list/classic.css ++++ b/extensions/window-list/classic.css +@@ -47,3 +47,12 @@ + color: #888; + box-shadow: none; + } + -+ this._visible = true; ++/* workspace switcher */ ++.window-list-workspace-indicator .workspace { ++ background-color: #ddd; ++} + -+ if (!this._syncGrab()) -+ return; ++.window-list-workspace-indicator .workspace.active { ++ background-color: #ccc; ++} +diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css +index bab8f76..ad5978a 100644 +--- a/extensions/window-list/stylesheet.css ++++ b/extensions/window-list/stylesheet.css +@@ -92,6 +92,35 @@ + margin: 3px 0; + } + ++.window-list-workspace-indicator .workspaces-box { ++ spacing: 3px; ++ padding: 3px; ++} + -+ this._fakeOverviewVisible(true); -+ this._shadeBackgrounds(); -+ this._fakeOverviewAnimation(); -+ this._workspacesDisplay.show(false); ++.window-list-workspace-indicator .workspace { ++ border: 1px solid #cccccc; ++ width: 52px; ++} + -+ this.emit('open-state-changed', this._visible); -+ } ++.window-list-workspace-indicator .workspace:first-child:last-child:ltr, ++.window-list-workspace-indicator .workspace:first-child:last-child:rtl { ++ border-radius: 4px; ++} + -+ close() { -+ if (!this._visible) -+ return; ++.window-list-workspace-indicator .workspace:first-child:ltr, ++.window-list-workspace-indicator .workspace:last-child:rtl { ++ border-radius: 4px 0 0 4px; ++} + -+ this._visible = false; ++.window-list-workspace-indicator .workspace:first-child:rtl, ++.window-list-workspace-indicator .workspace:last-child:ltr { ++ border-radius: 0 4px 4px 0; ++} + -+ if (!this._syncGrab()) -+ return; ++.window-list-workspace-indicator .workspace.active { ++ background-color: rgba(200, 200, 200, .3); ++} + -+ this._workspacesDisplay.animateFromOverview(false); -+ this._unshadeBackgrounds(); -+ this._fakeOverviewAnimation(() => { -+ this._workspacesDisplay.hide(); -+ this._fakeOverviewVisible(false); + .notification { + font-weight: normal; + } +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index 78ca97e..1258ed2 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -7,6 +7,25 @@ const PopupMenu = imports.ui.popupMenu; + const Gettext = imports.gettext.domain('gnome-shell-extensions'); + const _ = Gettext.gettext; + ++let WorkspaceThumbnail = GObject.registerClass({ ++ GTypeName: 'WindowListWorkspaceThumbnail' ++}, class WorkspaceThumbnail extends St.Button { ++ _init(index) { ++ super._init({ ++ style_class: 'workspace' + }); + -+ this.emit('open-state-changed', this._visible); -+ } -+ -+ _fakeOverviewAnimation(onComplete) { -+ Main.overview.animationInProgress = true; -+ GLib.timeout_add( -+ GLib.PRIORITY_DEFAULT, -+ Overview.ANIMATION_TIME * 1000, -+ () => { -+ Main.overview.animationInProgress = false; -+ if (onComplete) -+ onComplete(); -+ }); -+ } -+ -+ _fakeOverviewVisible(visible) { -+ // Fake overview state for WorkspacesDisplay -+ Main.overview.visible = visible; -+ -+ // Hide real windows -+ Main.layoutManager._inOverview = visible; -+ Main.layoutManager._updateVisibility(); ++ this._index = index; + } + -+ _syncGrab() { -+ if (this._visible) { -+ if (this._modal) -+ return true; -+ -+ this._modal = Main.pushModal(this.actor, { -+ actionMode: Shell.ActionMode.OVERVIEW -+ }); -+ -+ if (!this._modal) { -+ this.hide(); -+ return false; -+ } -+ } else if (this._modal) { -+ Main.popModal(this.actor); -+ this._modal = false; -+ } -+ return true; ++ // eslint-disable-next-line camelcase ++ on_clicked() { ++ let ws = global.workspace_manager.get_workspace_by_index(this._index); ++ if (ws) ++ ws.activate(global.get_current_time()); + } ++}); + -+ _onDestroy() { -+ if (this._monitorsChangedId) -+ Main.layoutManager.disconnect(this._monitorsChangedId); -+ this._monitorsChangedId = 0; -+ } + var WorkspaceIndicator = GObject.registerClass({ + GTypeName: 'WindowListWorkspaceIndicator' + }, class WorkspaceIndicator extends PanelMenu.Button { +@@ -36,17 +55,30 @@ var WorkspaceIndicator = GObject.registerClass({ + }); + container.add_actor(this._statusBin); + ++ this._thumbnailsBox = new St.BoxLayout({ ++ style_class: 'workspaces-box', ++ y_expand: true, ++ reactive: true ++ }); ++ this._thumbnailsBox.connect('scroll-event', ++ this._onScrollEvent.bind(this)); ++ container.add_actor(this._thumbnailsBox); + -+ _updateBackgrounds() { -+ Main.overview._updateBackgrounds.call(this); -+ } + this._workspacesItems = []; + + this._workspaceManagerSignals = [ + workspaceManager.connect('notify::n-workspaces', + this._nWorkspacesChanged.bind(this)), + workspaceManager.connect_after('workspace-switched', +- this._onWorkspaceSwitched.bind(this)) ++ this._onWorkspaceSwitched.bind(this)), ++ workspaceManager.connect('notify::layout-rows', ++ this._onWorkspaceOrientationChanged.bind(this)) + ]; + + this.connect('scroll-event', this._onScrollEvent.bind(this)); + this._updateMenu(); ++ this._updateThumbnails(); ++ this._onWorkspaceOrientationChanged(); + + this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' }); + this._settingsChangedId = this._settings.connect( +@@ -65,17 +97,27 @@ var WorkspaceIndicator = GObject.registerClass({ + super._onDestroy(); + } + ++ _onWorkspaceOrientationChanged() { ++ let vertical = global.workspace_manager.layout_rows == -1; ++ this.reactive = vertical; + -+ _shadeBackgrounds() { -+ Main.overview._shadeBackgrounds.call(this); ++ this._statusBin.visible = vertical; ++ this._thumbnailsBox.visible = !vertical; + } + -+ _unshadeBackgrounds() { -+ Main.overview._unshadeBackgrounds.call(this); + _onWorkspaceSwitched() { + let workspaceManager = global.workspace_manager; + this._currentWorkspace = workspaceManager.get_active_workspace_index(); + + this._updateMenuOrnament(); ++ this._updateActiveThumbnail(); + + this._statusLabel.set_text(this._getStatusText()); + } + + _nWorkspacesChanged() { + this._updateMenu(); ++ this._updateThumbnails(); + } + + _updateMenuOrnament() { +@@ -86,6 +128,16 @@ var WorkspaceIndicator = GObject.registerClass({ + } + } + ++ _updateActiveThumbnail() { ++ let thumbs = this._thumbnailsBox.get_children(); ++ for (let i = 0; i < thumbs.length; i++) { ++ if (i == this._currentWorkspace) ++ thumbs[i].add_style_class_name('active'); ++ else ++ thumbs[i].remove_style_class_name('active'); ++ } + } -+}; -+Signals.addSignalMethods(WindowPicker.prototype); + -+var WindowPickerToggle = GObject.registerClass( -+class WindowPickerToggle extends St.Button { -+ _init() { -+ let iconBin = new St.Widget({ -+ layout_manager: new Clutter.BinLayout() -+ }); -+ iconBin.add_child(new St.Icon({ -+ icon_name: 'focus-windows-symbolic', -+ icon_size: 16, -+ x_expand: true, -+ y_expand: true, -+ x_align: Clutter.ActorAlign.CENTER, -+ y_align: Clutter.ActorAlign.CENTER -+ })); -+ super._init({ -+ style_class: 'window-picker-toggle', -+ child: iconBin, -+ visible: !Main.sessionMode.hasOverview, -+ x_fill: true, -+ y_fill: true, -+ toggle_mode: true -+ }); + _getStatusText() { + let workspaceManager = global.workspace_manager; + let current = workspaceManager.get_active_workspace_index(); +@@ -128,6 +180,18 @@ var WorkspaceIndicator = GObject.registerClass({ + this._statusLabel.set_text(this._getStatusText()); + } + ++ _updateThumbnails() { ++ let workspaceManager = global.workspace_manager; + -+ this.connect('notify::checked', () => { -+ if (this.checked) -+ Main.windowPicker.open(); -+ else -+ Main.windowPicker.close(); -+ }); ++ this._thumbnailsBox.destroy_all_children(); + -+ if (!Main.sessionMode.hasOverview) { -+ global.display.connect('overlay-key', () => { -+ if (!Main.windowPicker.visible) -+ Main.windowPicker.open(); -+ else -+ Main.windowPicker.close(); -+ }); ++ for (let i = 0; i < workspaceManager.n_workspaces; i++) { ++ let thumb = new WorkspaceThumbnail(i); ++ this._thumbnailsBox.add_actor(thumb); + } -+ -+ Main.windowPicker.connect('open-state-changed', () => { -+ this.checked = Main.windowPicker.visible; -+ }); ++ this._updateActiveThumbnail(); + } -+}); ++ + _activate(index) { + let workspaceManager = global.workspace_manager; + +-- +2.21.0 + + +From 2a2958831f51968089262b1e41bc908a69ef6834 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 5 Jun 2019 03:31:16 +0000 +Subject: [PATCH 18/30] classic: Add 'horizontal-workspaces' extension + +Vertical workspaces are another defining characteristics of GNOME 3, +and thus rather un-classic. That switch was driven by the overall +layout of the overview, and now that we disable the overview in +GNOME Classic, we can just return to the traditional workspace +layout as well. + +Add a small extension that does just that. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/72 +--- + extensions/horizontal-workspaces/extension.js | 18 ++++++++++++++++++ + extensions/horizontal-workspaces/meson.build | 5 +++++ + .../horizontal-workspaces/metadata.json.in | 10 ++++++++++ + .../horizontal-workspaces/stylesheet.css | 1 + + meson.build | 1 + + 5 files changed, 35 insertions(+) + create mode 100644 extensions/horizontal-workspaces/extension.js + create mode 100644 extensions/horizontal-workspaces/meson.build + create mode 100644 extensions/horizontal-workspaces/metadata.json.in + create mode 100644 extensions/horizontal-workspaces/stylesheet.css + +diff --git a/extensions/horizontal-workspaces/extension.js b/extensions/horizontal-workspaces/extension.js +new file mode 100644 +index 0000000..b3937ce +--- /dev/null ++++ b/extensions/horizontal-workspaces/extension.js +@@ -0,0 +1,18 @@ ++/* exported enable disable */ ++const { Meta } = imports.gi; ++ ++function enable() { ++ global.workspace_manager.override_workspace_layout( ++ Meta.DisplayCorner.TOPLEFT, ++ false, ++ 1, ++ -1); ++} ++ ++function disable() { ++ global.workspace_manager.override_workspace_layout( ++ Meta.DisplayCorner.TOPLEFT, ++ false, ++ -1, ++ 1); ++} +diff --git a/extensions/horizontal-workspaces/meson.build b/extensions/horizontal-workspaces/meson.build +new file mode 100644 +index 0000000..48504f6 +--- /dev/null ++++ b/extensions/horizontal-workspaces/meson.build +@@ -0,0 +1,5 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) +diff --git a/extensions/horizontal-workspaces/metadata.json.in b/extensions/horizontal-workspaces/metadata.json.in +new file mode 100644 +index 0000000..f109e06 +--- /dev/null ++++ b/extensions/horizontal-workspaces/metadata.json.in +@@ -0,0 +1,10 @@ ++{ ++"extension-id": "@extension_id@", ++"uuid": "@uuid@", ++"settings-schema": "@gschemaname@", ++"gettext-domain": "@gettext_domain@", ++"name": "Horizontal workspaces", ++"description": "Use a horizontal workspace layout", ++"shell-version": [ "@shell_current@" ], ++"url": "@url@" ++} +diff --git a/extensions/horizontal-workspaces/stylesheet.css b/extensions/horizontal-workspaces/stylesheet.css +new file mode 100644 +index 0000000..25134b6 +--- /dev/null ++++ b/extensions/horizontal-workspaces/stylesheet.css +@@ -0,0 +1 @@ ++/* This extensions requires no special styling */ +diff --git a/meson.build b/meson.build +index 32743ed..23bd5ad 100644 +--- a/meson.build ++++ b/meson.build +@@ -34,6 +34,7 @@ uuid_suffix = '@gnome-shell-extensions.gcampax.github.com' + classic_extensions = [ + 'apps-menu', + 'desktop-icons', ++ 'horizontal-workspaces', + 'places-menu', + 'launch-new-instance', + 'top-icons', -- 2.21.0 -From 36f9a7ea01eed0481572459afc81f8fb433b95d3 Mon Sep 17 00:00:00 2001 +From 6a7b057028a1e4264312974d3ca21e16f5c07776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Tue, 11 Jun 2019 23:01:20 +0000 -Subject: [PATCH 16/22] window-list: Turn workspace thumbs into drop targets +Subject: [PATCH 19/30] window-list: Turn workspace thumbs into drop targets It makes some sense to allow using the workspace indicator for moving windows between workspaces as well as for workspace switching. This @@ -1778,69 +1976,340 @@ between workspaces. https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/74 --- - extensions/window-list/workspaceIndicator.js | 35 +++++++++++++++++++- - 1 file changed, 34 insertions(+), 1 deletion(-) + extensions/window-list/workspaceIndicator.js | 27 ++++++++++++++++++++ + 1 file changed, 27 insertions(+) diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js -index 1258ed2..8a93e84 100644 +index 1258ed2..4831768 100644 --- a/extensions/window-list/workspaceIndicator.js +++ b/extensions/window-list/workspaceIndicator.js -@@ -1,6 +1,7 @@ +@@ -1,6 +1,8 @@ /* exported WorkspaceIndicator */ --const { Clutter, Gio, GObject, Meta, St } = imports.gi; -+const { Clutter, Gio, GObject, Meta, Shell, St } = imports.gi; + const { Clutter, Gio, GObject, Meta, St } = imports.gi; ++const DND = imports.ui.dnd; +const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; -@@ -16,6 +17,38 @@ let WorkspaceThumbnail = GObject.registerClass({ +@@ -16,6 +18,31 @@ let WorkspaceThumbnail = GObject.registerClass({ }); this._index = index; + this._delegate = this; // needed for DND ++ } ++ ++ acceptDrop(source) { ++ if (!source.realWindow) ++ return false; ++ ++ let window = source.realWindow.get_meta_window(); ++ this._moveWindow(window); ++ return true; ++ } ++ ++ handleDragOver(source) { ++ if (source.realWindow) ++ return DND.DragMotionResult.MOVE_DROP; ++ else ++ return DND.DragMotionResult.CONTINUE; ++ } ++ ++ ++ _moveWindow(window) { ++ let monitorIndex = Main.layoutManager.findIndexForActor(this); ++ if (monitorIndex != window.get_monitor()) ++ window.move_to_monitor(monitorIndex); ++ window.change_workspace_by_index(this._index, false); + } + + // eslint-disable-next-line camelcase +-- +2.21.0 + + +From 7dca894705ddfd73016f4d073f6fe486563ce324 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 26 Jun 2019 23:55:58 +0000 +Subject: [PATCH 20/30] window-list: Show previews in workspace switcher + +Currently the new horizontal workspace switcher only shows a series of +buttons, with no indication of the workspaces' contents. Go full GNOME 2 +and add tiny draggable preview rectangles that represent the windows +on a particular workspace. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/74 +--- + extensions/window-list/classic.css | 10 ++ + extensions/window-list/stylesheet.css | 10 ++ + extensions/window-list/workspaceIndicator.js | 154 ++++++++++++++++++- + 3 files changed, 173 insertions(+), 1 deletion(-) + +diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css +index c533473..7079d3e 100644 +--- a/extensions/window-list/classic.css ++++ b/extensions/window-list/classic.css +@@ -56,3 +56,13 @@ + .window-list-workspace-indicator .workspace.active { + background-color: #ccc; + } ++ ++.window-list-window-preview { ++ background-color: #ededed; ++ border: 1px solid #ccc; ++} ++ ++.window-list-window-preview.active { ++ background-color: #f6f5f4; ++ border: 2px solid #888; ++} +diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css +index ad5978a..79d56ba 100644 +--- a/extensions/window-list/stylesheet.css ++++ b/extensions/window-list/stylesheet.css +@@ -121,6 +121,16 @@ + background-color: rgba(200, 200, 200, .3); + } + ++.window-list-window-preview { ++ background-color: #252525; ++ border: 1px solid #ccc; ++} ++ ++.window-list-window-preview.active { ++ background-color: #353535; ++ border: 2px solid #ccc; ++} ++ + .notification { + font-weight: normal; + } +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index 4831768..ca47611 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -9,16 +9,131 @@ const PopupMenu = imports.ui.popupMenu; + const Gettext = imports.gettext.domain('gnome-shell-extensions'); + const _ = Gettext.gettext; + ++let WindowPreview = GObject.registerClass({ ++ GTypeName: 'WindowListWindowPreview' ++}, class WindowPreview extends St.Button { ++ _init(window) { ++ super._init({ ++ style_class: 'window-list-window-preview' ++ }); ++ ++ this._delegate = this; ++ DND.makeDraggable(this, { restoreOnSuccess: true }); ++ ++ this._window = window; ++ ++ this.connect('destroy', this._onDestroy.bind(this)); ++ ++ this._sizeChangedId = this._window.connect('size-changed', ++ this._relayout.bind(this)); ++ this._positionChangedId = this._window.connect('position-changed', ++ this._relayout.bind(this)); ++ this._minimizedChangedId = this._window.connect('notify::minimized', ++ this._relayout.bind(this)); ++ this._monitorEnteredId = global.display.connect('window-entered-monitor', ++ this._relayout.bind(this)); ++ this._monitorLeftId = global.display.connect('window-left-monitor', ++ this._relayout.bind(this)); ++ ++ // Do initial layout when we get a parent ++ let id = this.connect('parent-set', () => { ++ this.disconnect(id); ++ if (!this.get_parent()) ++ return; ++ this._laterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { ++ this._laterId = 0; ++ this._relayout(); ++ return false; ++ }); ++ }); ++ ++ this._focusChangedId = global.display.connect('notify::focus-window', ++ this._onFocusChanged.bind(this)); ++ this._onFocusChanged(); ++ } ++ ++ // needed for DND ++ get realWindow() { ++ return this._window.get_compositor_private(); ++ } ++ ++ _onDestroy() { ++ this._window.disconnect(this._sizeChangedId); ++ this._window.disconnect(this._positionChangedId); ++ this._window.disconnect(this._minimizedChangedId); ++ global.display.disconnect(this._monitorEnteredId); ++ global.display.disconnect(this._monitorLeftId); ++ global.display.disconnect(this._focusChangedId); ++ if (this._laterId) ++ Meta.later_remove(this._laterId); ++ } ++ ++ _onFocusChanged() { ++ if (global.display.focus_window == this._window) ++ this.add_style_class_name('active'); ++ else ++ this.remove_style_class_name('active'); ++ } ++ ++ _relayout() { ++ let monitor = Main.layoutManager.findIndexForActor(this); ++ this.visible = monitor == this._window.get_monitor() && ++ this._window.showing_on_its_workspace(); ++ ++ if (!this.visible) ++ return; ++ ++ let workArea = Main.layoutManager.getWorkAreaForMonitor(monitor); ++ let hscale = this.get_parent().allocation.get_width() / workArea.width; ++ let vscale = this.get_parent().allocation.get_height() / workArea.height; ++ ++ let frameRect = this._window.get_frame_rect(); ++ this.set_size( ++ Math.round(Math.min(frameRect.width, workArea.width) * hscale), ++ Math.round(Math.min(frameRect.height, workArea.height) * vscale)); ++ this.set_position( ++ Math.round(frameRect.x * hscale), ++ Math.round(frameRect.y * vscale)); ++ } ++}); ++ + let WorkspaceThumbnail = GObject.registerClass({ + GTypeName: 'WindowListWorkspaceThumbnail' + }, class WorkspaceThumbnail extends St.Button { + _init(index) { + super._init({ +- style_class: 'workspace' ++ style_class: 'workspace', ++ child: new Clutter.Actor({ ++ layout_manager: new Clutter.BinLayout(), ++ clip_to_allocation: true ++ }), ++ x_fill: true, ++ y_fill: true + }); + ++ this.connect('destroy', this._onDestroy.bind(this)); ++ + this._index = index; + this._delegate = this; // needed for DND ++ ++ this._windowPreviews = new Map(); ++ ++ let workspaceManager = global.workspace_manager; ++ this._workspace = workspaceManager.get_workspace_by_index(index); ++ ++ this._windowAddedId = this._workspace.connect('window-added', ++ (ws, window) => { ++ this._addWindow(window); ++ }); ++ this._windowRemovedId = this._workspace.connect('window-removed', ++ (ws, window) => { ++ this._removeWindow(window); ++ }); ++ this._restackedId = global.display.connect('restacked', ++ this._onRestacked.bind(this)); ++ ++ this._workspace.list_windows().forEach(w => this._addWindow(w)); ++ this._onRestacked(); + } + + acceptDrop(source) { +@@ -37,6 +152,37 @@ let WorkspaceThumbnail = GObject.registerClass({ + return DND.DragMotionResult.CONTINUE; + } + ++ _addWindow(window) { ++ if (this._windowPreviews.has(window)) ++ return; + -+ this._grabOpEndId = global.display.connect('grab-op-end', -+ (dpy, dpy_, window, grabOp) => { -+ if (grabOp != Meta.GrabOp.MOVING) -+ return; ++ let preview = new WindowPreview(window); ++ preview.connect('clicked', (a, btn) => this.emit('clicked', btn)); ++ this._windowPreviews.set(window, preview); ++ this.child.add_child(preview); ++ } + -+ let [x, y] = global.get_pointer(); -+ let alloc = Shell.util_get_transformed_allocation(this); -+ if (alloc.contains(x, y)) -+ this._moveWindow(window); -+ }); ++ _removeWindow(window) { ++ let preview = this._windowPreviews.get(window); ++ if (!preview) ++ return; + -+ this.connect('destroy', () => { -+ global.display.disconnect(this._grabOpEndId); -+ }); ++ this._windowPreviews.delete(window); ++ preview.destroy(); + } + -+ acceptDrop(source) { -+ if (!source.realWindow) -+ return false; ++ _onRestacked() { ++ let lastPreview = null; ++ let windows = global.get_window_actors().map(a => a.meta_window); ++ for (let i = 0; i < windows.length; i++) { ++ let preview = this._windowPreviews.get(windows[i]); ++ if (!preview) ++ continue; + -+ let window = source.realWindow.get_meta_window(); -+ this._moveWindow(window); -+ return true; ++ this.child.set_child_above_sibling(preview, lastPreview); ++ lastPreview = preview; ++ } + } -+ -+ _moveWindow(window) { -+ let monitorIndex = Main.layoutManager.findIndexForActor(this); -+ if (monitorIndex != window.get_monitor()) -+ window.move_to_monitor(monitorIndex); -+ window.change_workspace_by_index(this._index, false); + + _moveWindow(window) { + let monitorIndex = Main.layoutManager.findIndexForActor(this); +@@ -51,6 +197,12 @@ let WorkspaceThumbnail = GObject.registerClass({ + if (ws) + ws.activate(global.get_current_time()); } ++ ++ _onDestroy() { ++ this._workspace.disconnect(this._windowAddedId); ++ this._workspace.disconnect(this._windowRemovedId); ++ global.display.disconnect(this._restackedId); ++ } + }); - // eslint-disable-next-line camelcase + var WorkspaceIndicator = GObject.registerClass({ +-- +2.21.0 + + +From 77b9d4fee20d84816cb64bfa6b95fddd589b4788 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Sat, 29 Jun 2019 01:24:54 +0200 +Subject: [PATCH 21/30] workspace-indicator: Fix whitespace error + +We only want a single space before and after operators, not at least +one. Unfortunately eslint only enforces the latter ... + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71 +--- + extensions/workspace-indicator/extension.js | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js +index 3be1268..c3c4d5f 100644 +--- a/extensions/workspace-indicator/extension.js ++++ b/extensions/workspace-indicator/extension.js +@@ -109,7 +109,7 @@ class WorkspaceIndicator extends PanelMenu.Button { + _activate(index) { + let workspaceManager = global.workspace_manager; + +- if (index >= 0 && index < workspaceManager.n_workspaces) { ++ if (index >= 0 && index < workspaceManager.n_workspaces) { + let metaWorkspace = workspaceManager.get_workspace_by_index(index); + metaWorkspace.activate(global.get_current_time()); + } -- 2.21.0 -From 3ac15a848809da6053c224e86c5f5c72243f6c5b Mon Sep 17 00:00:00 2001 +From a68ef2096fed7580f7177991e354910add1ab79c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sun, 9 Jun 2019 22:58:29 +0000 -Subject: [PATCH 17/22] workspace-indicator: Make some properties private +Subject: [PATCH 22/30] workspace-indicator: Make some properties private There's no reason why they should be public. @@ -1850,7 +2319,7 @@ https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js -index 3be1268..76224b9 100644 +index c3c4d5f..e052181 100644 --- a/extensions/workspace-indicator/extension.js +++ b/extensions/workspace-indicator/extension.js @@ -23,14 +23,14 @@ class WorkspaceIndicator extends PanelMenu.Button { @@ -1932,10 +2401,10 @@ index 3be1268..76224b9 100644 2.21.0 -From 2b1cb8c6b27d63ed7093f4b171f0837a193061f5 Mon Sep 17 00:00:00 2001 +From 7e74dd6e331846564898ed220d58eb54cad83524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sun, 9 Jun 2019 23:03:55 +0000 -Subject: [PATCH 18/22] workspace-indicator: Update workspace names in-place +Subject: [PATCH 23/30] workspace-indicator: Update workspace names in-place There's no good reason to rebuild the entire menu on workspace names changes, we can simply update the labels in-place. @@ -1946,7 +2415,7 @@ https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js -index 76224b9..6bcac0c 100644 +index e052181..205ee36 100644 --- a/extensions/workspace-indicator/extension.js +++ b/extensions/workspace-indicator/extension.js @@ -49,9 +49,9 @@ class WorkspaceIndicator extends PanelMenu.Button { @@ -1978,10 +2447,10 @@ index 76224b9..6bcac0c 100644 2.21.0 -From a16a7c47475a7d19da43597b810ea9224af745b4 Mon Sep 17 00:00:00 2001 +From dfcd296cf33de8a3e739c340734332a63f2c01f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sun, 9 Jun 2019 23:05:00 +0000 -Subject: [PATCH 19/22] workspace-indicator: Minor cleanup +Subject: [PATCH 24/30] workspace-indicator: Minor cleanup Mutter has a dedicated method for getting the index of the active workspace, use that instead of getting first the active workspace @@ -1993,7 +2462,7 @@ https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js -index 6bcac0c..dc31a5c 100644 +index 205ee36..7ebc1f0 100644 --- a/extensions/workspace-indicator/extension.js +++ b/extensions/workspace-indicator/extension.js @@ -22,7 +22,7 @@ class WorkspaceIndicator extends PanelMenu.Button { @@ -2036,10 +2505,10 @@ index 6bcac0c..dc31a5c 100644 2.21.0 -From 707dc4df33efd9779e0839c816c1bfd1efffc699 Mon Sep 17 00:00:00 2001 +From 00d1e9637f0b7f51b271c384fb55ecaea673bb70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sun, 9 Jun 2019 23:09:12 +0000 -Subject: [PATCH 20/22] workspace-indicator: Refactor workspace signal handlers +Subject: [PATCH 25/30] workspace-indicator: Refactor workspace signal handlers We are about to support a separate representation if horizontal workspaces are used. To prepare for that, rename the handlers to @@ -2052,7 +2521,7 @@ https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js -index dc31a5c..1961b1c 100644 +index 7ebc1f0..34fc275 100644 --- a/extensions/workspace-indicator/extension.js +++ b/extensions/workspace-indicator/extension.js @@ -34,13 +34,12 @@ class WorkspaceIndicator extends PanelMenu.Button { @@ -2109,10 +2578,10 @@ index dc31a5c..1961b1c 100644 2.21.0 -From 83ad6a01f58ae451cc3086a01cdfd500eaa536d2 Mon Sep 17 00:00:00 2001 +From 0834d04691de28f3a216578e55335c6e9b3e4fad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sun, 9 Jun 2019 23:17:35 +0000 -Subject: [PATCH 21/22] workspace-indicator: Minor cleanup +Subject: [PATCH 26/30] workspace-indicator: Minor cleanup Pass the style class at construction time instead of setting it later. @@ -2122,7 +2591,7 @@ https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js -index 1961b1c..18f5450 100644 +index 34fc275..672b98d 100644 --- a/extensions/workspace-indicator/extension.js +++ b/extensions/workspace-indicator/extension.js @@ -24,6 +24,7 @@ class WorkspaceIndicator extends PanelMenu.Button { @@ -2147,10 +2616,10 @@ index 1961b1c..18f5450 100644 2.21.0 -From 4e128c9cbc631fa47f9e5959212c35d9c6d53a01 Mon Sep 17 00:00:00 2001 +From 07fca6b1ee27a1eaf97027e4353ab46ea9cb745e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sun, 9 Jun 2019 23:45:24 +0000 -Subject: [PATCH 22/22] workspace-indicator: Support horizontal workspace +Subject: [PATCH 27/30] workspace-indicator: Support horizontal workspace layout Just like we did for the workspace indicator in the window-list, improve @@ -2159,15 +2628,40 @@ in-place instead of delegating the functionality to a menu. https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71 --- - extensions/workspace-indicator/extension.js | 63 ++++++++++++++++++- - extensions/workspace-indicator/stylesheet.css | 18 +++++- - 2 files changed, 77 insertions(+), 4 deletions(-) + extensions/workspace-indicator/extension.js | 76 ++++++++++++++++++- + extensions/workspace-indicator/stylesheet.css | 18 ++++- + 2 files changed, 90 insertions(+), 4 deletions(-) diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js -index 18f5450..5f7cb7c 100644 +index 672b98d..48019da 100644 --- a/extensions/workspace-indicator/extension.js +++ b/extensions/workspace-indicator/extension.js -@@ -20,6 +20,13 @@ class WorkspaceIndicator extends PanelMenu.Button { +@@ -15,11 +15,38 @@ const ExtensionUtils = imports.misc.extensionUtils; + const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences'; + const WORKSPACE_KEY = 'workspace-names'; + ++let WorkspaceThumbnail = GObject.registerClass({ ++ GTypeName: 'WorkspaceIndicatorWorkspaceThumbnail' ++}, class WorkspaceThumbnail extends St.Button { ++ _init(index) { ++ super._init({ ++ style_class: 'workspace', ++ }); ++ ++ this._index = index; ++ } ++ ++ // eslint-disable-next-line camelcase ++ on_clicked() { ++ let ws = global.workspace_manager.get_workspace_by_index(this._index); ++ if (ws) ++ ws.activate(global.get_current_time()); ++ } ++}); ++ ++ + let WorkspaceIndicator = GObject.registerClass( + class WorkspaceIndicator extends PanelMenu.Button { _init() { super._init(0.0, _('Workspace Indicator')); @@ -2181,7 +2675,7 @@ index 18f5450..5f7cb7c 100644 let workspaceManager = global.workspace_manager; this._currentWorkspace = workspaceManager.get_active_workspace_index(); -@@ -29,7 +36,15 @@ class WorkspaceIndicator extends PanelMenu.Button { +@@ -29,7 +56,15 @@ class WorkspaceIndicator extends PanelMenu.Button { text: this._labelText() }); @@ -2198,7 +2692,7 @@ index 18f5450..5f7cb7c 100644 this._workspacesItems = []; this._workspaceSection = new PopupMenu.PopupMenuSection(); -@@ -39,11 +54,16 @@ class WorkspaceIndicator extends PanelMenu.Button { +@@ -39,11 +74,16 @@ class WorkspaceIndicator extends PanelMenu.Button { workspaceManager.connect_after('notify::n-workspaces', this._nWorkspacesChanged.bind(this)), workspaceManager.connect_after('workspace-switched', @@ -2216,7 +2710,7 @@ index 18f5450..5f7cb7c 100644 this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA }); this._settingsChangedId = this._settings.connect( -@@ -63,16 +83,26 @@ class WorkspaceIndicator extends PanelMenu.Button { +@@ -63,16 +103,26 @@ class WorkspaceIndicator extends PanelMenu.Button { super._onDestroy(); } @@ -2243,7 +2737,7 @@ index 18f5450..5f7cb7c 100644 } _updateMenuOrnament() { -@@ -83,6 +113,16 @@ class WorkspaceIndicator extends PanelMenu.Button { +@@ -83,6 +133,16 @@ class WorkspaceIndicator extends PanelMenu.Button { } } @@ -2260,7 +2754,7 @@ index 18f5450..5f7cb7c 100644 _labelText(workspaceIndex) { if (workspaceIndex == undefined) { workspaceIndex = this._currentWorkspace; -@@ -120,6 +160,25 @@ class WorkspaceIndicator extends PanelMenu.Button { +@@ -120,6 +180,18 @@ class WorkspaceIndicator extends PanelMenu.Button { this._statusLabel.set_text(this._labelText()); } @@ -2270,14 +2764,7 @@ index 18f5450..5f7cb7c 100644 + this._thumbnailsBox.destroy_all_children(); + + for (let i = 0; i < workspaceManager.n_workspaces; i++) { -+ let thumb = new St.Button({ -+ style_class: 'workspace', -+ child: new St.Label({ text: `${i + 1}` }) -+ }); -+ thumb.connect('clicked', () => { -+ this._activate(i); -+ }); -+ ++ let thumb = new WorkspaceThumbnail(i); + this._thumbnailsBox.add_actor(thumb); + } + this._updateActiveThumbnail(); @@ -2315,3 +2802,469 @@ index 1271f1c..a15081e 100644 -- 2.21.0 + +From 58496daaf5591e86238d7ab7f470b5ad7797b3e3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 28 Jun 2019 11:33:16 +0200 +Subject: [PATCH 28/30] workspace-indicator: Show previews in workspace + switcher + +Currently the new horizontal workspace switcher only shows a series of +buttons, with no indication of the workspaces' contents. Go full GNOME 2 +and add tiny draggable preview rectangles that represent the windows +on a particular workspace. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/77 +--- + extensions/workspace-indicator/extension.js | 194 +++++++++++++++++- + extensions/workspace-indicator/stylesheet.css | 22 +- + 2 files changed, 209 insertions(+), 7 deletions(-) + +diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js +index 48019da..69eef88 100644 +--- a/extensions/workspace-indicator/extension.js ++++ b/extensions/workspace-indicator/extension.js +@@ -2,28 +2,199 @@ + /* exported init enable disable */ + + const { Clutter, Gio, GObject, Meta, St } = imports.gi; ++ ++const DND = imports.ui.dnd; ++const ExtensionUtils = imports.misc.extensionUtils; ++const Main = imports.ui.main; + const PanelMenu = imports.ui.panelMenu; + const PopupMenu = imports.ui.popupMenu; + + const Gettext = imports.gettext.domain('gnome-shell-extensions'); + const _ = Gettext.gettext; + +-const Main = imports.ui.main; +- +-const ExtensionUtils = imports.misc.extensionUtils; +- + const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences'; + const WORKSPACE_KEY = 'workspace-names'; + ++let WindowPreview = GObject.registerClass({ ++ GTypeName: 'WorkspaceIndicatorWindowPreview' ++}, class WindowPreview extends St.Button { ++ _init(window) { ++ super._init({ ++ style_class: 'workspace-indicator-window-preview' ++ }); ++ ++ this._delegate = this; ++ DND.makeDraggable(this, { restoreOnSuccess: true }); ++ ++ this._window = window; ++ ++ this.connect('destroy', this._onDestroy.bind(this)); ++ ++ this._sizeChangedId = this._window.connect('size-changed', ++ this._relayout.bind(this)); ++ this._positionChangedId = this._window.connect('position-changed', ++ this._relayout.bind(this)); ++ this._minimizedChangedId = this._window.connect('notify::minimized', ++ this._relayout.bind(this)); ++ this._monitorEnteredId = global.display.connect('window-entered-monitor', ++ this._relayout.bind(this)); ++ this._monitorLeftId = global.display.connect('window-left-monitor', ++ this._relayout.bind(this)); ++ ++ // Do initial layout when we get a parent ++ let id = this.connect('parent-set', () => { ++ this.disconnect(id); ++ if (!this.get_parent()) ++ return; ++ this._laterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { ++ this._laterId = 0; ++ this._relayout(); ++ return false; ++ }); ++ }); ++ ++ this._focusChangedId = global.display.connect('notify::focus-window', ++ this._onFocusChanged.bind(this)); ++ this._onFocusChanged(); ++ } ++ ++ // needed for DND ++ get realWindow() { ++ return this._window.get_compositor_private(); ++ } ++ ++ _onDestroy() { ++ this._window.disconnect(this._sizeChangedId); ++ this._window.disconnect(this._positionChangedId); ++ this._window.disconnect(this._minimizedChangedId); ++ global.display.disconnect(this._monitorEnteredId); ++ global.display.disconnect(this._monitorLeftId); ++ global.display.disconnect(this._focusChangedId); ++ if (this._laterId) ++ Meta.later_remove(this._laterId); ++ } ++ ++ _onFocusChanged() { ++ if (global.display.focus_window == this._window) ++ this.add_style_class_name('active'); ++ else ++ this.remove_style_class_name('active'); ++ } ++ ++ _relayout() { ++ let monitor = Main.layoutManager.findIndexForActor(this); ++ this.visible = monitor == this._window.get_monitor() && ++ this._window.showing_on_its_workspace(); ++ ++ if (!this.visible) ++ return; ++ ++ let workArea = Main.layoutManager.getWorkAreaForMonitor(monitor); ++ let hscale = this.get_parent().allocation.get_width() / workArea.width; ++ let vscale = this.get_parent().allocation.get_height() / workArea.height; ++ ++ let frameRect = this._window.get_frame_rect(); ++ this.set_size( ++ Math.round(Math.min(frameRect.width, workArea.width) * hscale), ++ Math.round(Math.min(frameRect.height, workArea.height) * vscale)); ++ this.set_position( ++ Math.round(frameRect.x * hscale), ++ Math.round(frameRect.y * vscale)); ++ } ++}); ++ + let WorkspaceThumbnail = GObject.registerClass({ + GTypeName: 'WorkspaceIndicatorWorkspaceThumbnail' + }, class WorkspaceThumbnail extends St.Button { + _init(index) { + super._init({ + style_class: 'workspace', ++ child: new Clutter.Actor({ ++ layout_manager: new Clutter.BinLayout(), ++ clip_to_allocation: true ++ }), ++ x_fill: true, ++ y_fill: true + }); + ++ this.connect('destroy', this._onDestroy.bind(this)); ++ + this._index = index; ++ this._delegate = this; // needed for DND ++ ++ this._windowPreviews = new Map(); ++ ++ let workspaceManager = global.workspace_manager; ++ this._workspace = workspaceManager.get_workspace_by_index(index); ++ ++ this._windowAddedId = this._workspace.connect('window-added', ++ (ws, window) => { ++ this._addWindow(window); ++ }); ++ this._windowRemovedId = this._workspace.connect('window-removed', ++ (ws, window) => { ++ this._removeWindow(window); ++ }); ++ this._restackedId = global.display.connect('restacked', ++ this._onRestacked.bind(this)); ++ ++ this._workspace.list_windows().forEach(w => this._addWindow(w)); ++ this._onRestacked(); ++ } ++ ++ acceptDrop(source) { ++ if (!source.realWindow) ++ return false; ++ ++ let window = source.realWindow.get_meta_window(); ++ this._moveWindow(window); ++ return true; ++ } ++ ++ handleDragOver(source) { ++ if (source.realWindow) ++ return DND.DragMotionResult.MOVE_DROP; ++ else ++ return DND.DragMotionResult.CONTINUE; ++ } ++ ++ _addWindow(window) { ++ if (this._windowPreviews.has(window)) ++ return; ++ ++ let preview = new WindowPreview(window); ++ preview.connect('clicked', (a, btn) => this.emit('clicked', btn)); ++ this._windowPreviews.set(window, preview); ++ this.child.add_child(preview); ++ } ++ ++ _removeWindow(window) { ++ let preview = this._windowPreviews.get(window); ++ if (!preview) ++ return; ++ ++ this._windowPreviews.delete(window); ++ preview.destroy(); ++ } ++ ++ _onRestacked() { ++ let lastPreview = null; ++ let windows = global.get_window_actors().map(a => a.meta_window); ++ for (let i = 0; i < windows.length; i++) { ++ let preview = this._windowPreviews.get(windows[i]); ++ if (!preview) ++ continue; ++ ++ this.child.set_child_above_sibling(preview, lastPreview); ++ lastPreview = preview; ++ } ++ } ++ ++ _moveWindow(window) { ++ let monitorIndex = Main.layoutManager.findIndexForActor(this); ++ if (monitorIndex != window.get_monitor()) ++ window.move_to_monitor(monitorIndex); ++ window.change_workspace_by_index(this._index, false); + } + + // eslint-disable-next-line camelcase +@@ -32,8 +203,13 @@ let WorkspaceThumbnail = GObject.registerClass({ + if (ws) + ws.activate(global.get_current_time()); + } +-}); + ++ _onDestroy() { ++ this._workspace.disconnect(this._windowAddedId); ++ this._workspace.disconnect(this._windowRemovedId); ++ global.display.disconnect(this._restackedId); ++ } ++}); + + let WorkspaceIndicator = GObject.registerClass( + class WorkspaceIndicator extends PanelMenu.Button { +@@ -100,6 +276,8 @@ class WorkspaceIndicator extends PanelMenu.Button { + this._settingsChangedId = 0; + } + ++ Main.panel.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS); ++ + super._onDestroy(); + } + +@@ -109,6 +287,12 @@ class WorkspaceIndicator extends PanelMenu.Button { + + this._statusLabel.visible = vertical; + this._thumbnailsBox.visible = !vertical; ++ ++ // Disable offscreen-redirect when showing the workspace switcher ++ // so that clip-to-allocation works ++ Main.panel.set_offscreen_redirect(vertical ++ ? Clutter.OffscreenRedirect.ALWAYS ++ : Clutter.OffscreenRedirect.AUTOMATIC_FOR_OPACITY); + } + + _onWorkspaceSwitched() { +diff --git a/extensions/workspace-indicator/stylesheet.css b/extensions/workspace-indicator/stylesheet.css +index a15081e..8c101e7 100644 +--- a/extensions/workspace-indicator/stylesheet.css ++++ b/extensions/workspace-indicator/stylesheet.css +@@ -1,9 +1,17 @@ +-.panel-workspace-indicator, +-.panel-workspace-indicator-box .workspace { ++.panel-workspace-indicator { + padding: 0 8px; + border: 1px solid #cccccc; + } + ++.panel-workspace-indicator-box { ++ padding: 2px 0; ++} ++ ++.panel-workspace-indicator-box .workspace { ++ border: 1px solid #cccccc; ++ width: 48px; ++} ++ + .panel-workspace-indicator, + .panel-workspace-indicator-box .workspace.active { + background-color: rgba(200, 200, 200, .5); +@@ -17,3 +25,13 @@ + .panel-workspace-indicator-box .workspace:first-child { + border-left-width: 1px; + } ++ ++.workspace-indicator-window-preview { ++ background-color: #252525; ++ border: 1px solid #ccc; ++} ++ ++.workspace-indicator-window-preview { ++ background-color: #353535; ++ border: 2px solid #ccc; ++} +-- +2.21.0 + + +From 06674bf6aff9fb4ae2224a448ba928c1687b5f6b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 2 Jul 2019 17:39:55 +0200 +Subject: [PATCH 29/30] window-list: Move super-key handling into WindowPicker + +We have an option to put a window list on each monitor, so we may have +more than one window picker toggle. We don't want each of those try to +toggle the window picker simultanuously, so move handling of the super +key directly into the picker. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/80 +--- + extensions/window-list/windowPicker.js | 34 ++++++++++++-------------- + 1 file changed, 15 insertions(+), 19 deletions(-) + +diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js +index 024fd80..ba0a697 100644 +--- a/extensions/window-list/windowPicker.js ++++ b/extensions/window-list/windowPicker.js +@@ -67,6 +67,8 @@ var WindowPicker = class { + this._visible = false; + this._modal = false; + ++ this._overlayKeyId = 0; ++ + this.actor = new Clutter.Actor(); + + this.actor.connect('destroy', this._onDestroy.bind(this)); +@@ -101,6 +103,15 @@ var WindowPicker = class { + this._updateBackgrounds(); + + Main.uiGroup.insert_child_below(this.actor, global.window_group); ++ ++ if (!Main.sessionMode.hasOverview) { ++ this._overlayKeyId = global.display.connect('overlay-key', () => { ++ if (!this._visible) ++ this.open(); ++ else ++ this.close(); ++ }); ++ } + } + + get visible() { +@@ -188,6 +199,10 @@ var WindowPicker = class { + if (this._monitorsChangedId) + Main.layoutManager.disconnect(this._monitorsChangedId); + this._monitorsChangedId = 0; ++ ++ if (this._overlayKeyId) ++ global.display.disconnect(this._overlayKeyId); ++ this._overlayKeyId = 0; + } + + _updateBackgrounds() { +@@ -227,10 +242,6 @@ class WindowPickerToggle extends St.Button { + toggle_mode: true + }); + +- this._overlayKeyId = 0; +- +- this.connect('destroy', this._onDestroy.bind(this)); +- + this.connect('notify::checked', () => { + if (this.checked) + Main.windowPicker.open(); +@@ -238,23 +249,8 @@ class WindowPickerToggle extends St.Button { + Main.windowPicker.close(); + }); + +- if (!Main.sessionMode.hasOverview) { +- this._overlayKeyId = global.display.connect('overlay-key', () => { +- if (!Main.windowPicker.visible) +- Main.windowPicker.open(); +- else +- Main.windowPicker.close(); +- }); +- } +- + Main.windowPicker.connect('open-state-changed', () => { + this.checked = Main.windowPicker.visible; + }); + } +- +- _onDestroy() { +- if (this._overlayKeyId) +- global.display.disconnect(this._overlayKeyId); +- this._overlayKeyId == 0; +- } + }); +-- +2.21.0 + + +From c37d082487cce3548844c150d1976bf1735552c8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 2 Jul 2019 18:12:31 +0200 +Subject: [PATCH 30/30] window-list: Handle closing window picker with Escape + +Just like the overview can be closed with Escape, it makes sense to +allow the same for the window picker (in addition to pressing super +repeatedly). + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/80 +--- + extensions/window-list/windowPicker.js | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js +index ba0a697..12a7627 100644 +--- a/extensions/window-list/windowPicker.js ++++ b/extensions/window-list/windowPicker.js +@@ -68,6 +68,7 @@ var WindowPicker = class { + this._modal = false; + + this._overlayKeyId = 0; ++ this._stageKeyPressId = 0; + + this.actor = new Clutter.Actor(); + +@@ -132,6 +133,16 @@ var WindowPicker = class { + this._fakeOverviewAnimation(); + this._workspacesDisplay.show(false); + ++ this._stageKeyPressId = global.stage.connect('key-press-event', ++ (a, event) => { ++ let sym = event.get_key_symbol(); ++ if (sym == Clutter.KEY_Escape) { ++ this.close(); ++ return Clutter.EVENT_STOP; ++ } ++ return Clutter.EVENT_PROPAGATE; ++ }); ++ + this.emit('open-state-changed', this._visible); + } + +@@ -151,6 +162,9 @@ var WindowPicker = class { + this._fakeOverviewVisible(false); + }); + ++ global.stage.disconnect(this._stageKeyPressId); ++ this._stageKeyPressId = 0; ++ + this.emit('open-state-changed', this._visible); + } + +@@ -203,6 +217,10 @@ var WindowPicker = class { + if (this._overlayKeyId) + global.display.disconnect(this._overlayKeyId); + this._overlayKeyId = 0; ++ ++ if (this._stageKeyPressId) ++ global.stage.disconnect(this._stageKeyPressId); ++ this._stageKeyPressId = 0; + } + + _updateBackgrounds() { +-- +2.21.0 + diff --git a/SPECS/gnome-shell-extensions.spec b/SPECS/gnome-shell-extensions.spec index f7e22e3..17b241d 100644 --- a/SPECS/gnome-shell-extensions.spec +++ b/SPECS/gnome-shell-extensions.spec @@ -6,7 +6,7 @@ Name: gnome-shell-extensions Version: 3.32.1 -Release: 5%{?dist} +Release: 10%{?dist} Summary: Modify and extend GNOME Shell functionality and behavior Group: User Interface/Desktops @@ -27,13 +27,13 @@ Requires: gnome-shell >= %{min_gs_version} BuildArch: noarch Patch0001: 0001-Update-style.patch -Patch0002: 0001-classic-Shade-panel-in-overview.patch -Patch0003: 0001-apps-menu-add-logo-icon-to-Applications-menu.patch -Patch0004: add-extra-extensions.patch -Patch0005: 0001-apps-menu-Explicitly-set-label_actor.patch -Patch0006: resurrect-system-monitor.patch -Patch0007: 0001-Include-top-icons-in-classic-session.patch -Patch0008: more-classic-classic-mode.patch +Patch0002: 0001-apps-menu-add-logo-icon-to-Applications-menu.patch +Patch0003: add-extra-extensions.patch +Patch0004: 0001-apps-menu-Explicitly-set-label_actor.patch +Patch0005: resurrect-system-monitor.patch +Patch0006: 0001-Include-top-icons-in-classic-session.patch +Patch0007: more-classic-classic-mode.patch +Patch0008: 0001-apps-menu-Add-missing-chain-up.patch %description GNOME Shell Extensions is a collection of extensions providing additional and @@ -467,6 +467,35 @@ cp $RPM_SOURCE_DIR/gnome-classic.desktop $RPM_BUILD_ROOT%{_datadir}/xsessions %changelog +* Wed Jul 24 2019 Florian Müllner - 3.32.1-10 +- Drop obsolete downstream style patch +- Keep classic notification styling + Related: #1731372 + +* Thu Jul 18 2019 Florian Müllner - 3.32.1-9 +- Backport classic style improvements + Resolves: #1726093 + +* Thu Jul 04 2019 Florian Müllner - 3.32.1-8 +- Allow closing window picker with Escape + Resolves: #1725854 + +* Sat Jun 29 2019 Florian Müllner - 3.32-1-7 +- Add window thumbnails to workspace switcher + Resolves: #1723467 +- Fix apps-menu not disabling itself entirely + Resolves: #1722047 + +* Tue Jun 25 2019 Florian Müllner - 3.32-1-6 +- Fix new classic mode issues: + - stray signal handler with overlay key + Resolves: #1722844 + - improve DND support: + + don't consider regular windows + (it doesn't work well, and GNOME 2 didn't support it either) + + indicate that workspace thumbs are drop targets + Related: #1704360 + * Tue Jun 18 2019 Florian Müllner - 3.32.1-5 - Small refinements after design feedback: - use default icon size in picker button to avoid blurriness