2019-04-17 14:56:20 +02:00
|
|
|
diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css
|
|
|
|
index f3c44a3..8096d27 100644
|
|
|
|
--- a/extensions/window-list/classic.css
|
|
|
|
+++ b/extensions/window-list/classic.css
|
2016-09-01 12:12:54 +02:00
|
|
|
@@ -6,7 +6,7 @@
|
|
|
|
height: 2.25em ;
|
|
|
|
}
|
|
|
|
|
|
|
|
- .bottom-panel .window-button > StWidget {
|
|
|
|
+ .window-button > StWidget {
|
|
|
|
background-gradient-drection: vertical;
|
|
|
|
background-color: #fff;
|
|
|
|
background-gradient-start: #fff;
|
2017-08-05 14:05:19 +02:00
|
|
|
@@ -22,25 +22,25 @@
|
2016-09-01 12:12:54 +02:00
|
|
|
text-shadow: 0 0 transparent;
|
|
|
|
}
|
|
|
|
|
|
|
|
- .bottom-panel .window-button:hover > StWidget {
|
2017-08-05 14:05:19 +02:00
|
|
|
+ .window-button:hover > StWidget {
|
2016-09-01 12:12:54 +02:00
|
|
|
background-color: #f9f9f9;
|
|
|
|
}
|
|
|
|
|
|
|
|
- .bottom-panel .window-button:active > StWidget,
|
|
|
|
- .bottom-panel .window-button:focus > StWidget {
|
2017-08-05 14:05:19 +02:00
|
|
|
+ .window-button:active > StWidget,
|
|
|
|
+ .window-button:focus > StWidget {
|
2016-09-01 12:12:54 +02:00
|
|
|
box-shadow: inset 1px 1px 2px rgba(0,0,0,0.5);
|
|
|
|
}
|
|
|
|
|
|
|
|
- .bottom-panel .window-button.focused > StWidget {
|
2017-08-05 14:05:19 +02:00
|
|
|
+ .window-button.focused > StWidget {
|
2016-09-01 12:12:54 +02:00
|
|
|
background-color: #ddd;
|
|
|
|
box-shadow: inset 1px 1px 1px rgba(0,0,0,0.5);
|
|
|
|
}
|
|
|
|
|
|
|
|
- .bottom-panel .window-button.focused:hover > StWidget {
|
2017-08-05 14:05:19 +02:00
|
|
|
+ .window-button.focused:hover > StWidget {
|
2016-09-01 12:12:54 +02:00
|
|
|
background-color: #e9e9e9;
|
|
|
|
}
|
|
|
|
|
|
|
|
- .bottom-panel .window-button.minimized > StWidget {
|
2017-08-05 14:05:19 +02:00
|
|
|
+ .window-button.minimized > StWidget {
|
2016-09-01 12:12:54 +02:00
|
|
|
color: #888;
|
|
|
|
box-shadow: inset -1px -1px 1px rgba(0,0,0,0.5);
|
|
|
|
}
|
2019-04-17 14:56:20 +02:00
|
|
|
diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js
|
|
|
|
index e1ea742..9764745 100644
|
|
|
|
--- a/extensions/window-list/extension.js
|
|
|
|
+++ b/extensions/window-list/extension.js
|
|
|
|
@@ -21,6 +21,398 @@ const GroupingMode = {
|
2017-11-07 10:42:17 +01:00
|
|
|
ALWAYS: 2
|
|
|
|
};
|
|
|
|
|
|
|
|
+function isSLEClassicMode() {
|
|
|
|
+ return Main.sessionMode.currentMode == "sle-classic" ? true : false;
|
|
|
|
+}
|
2016-09-01 12:12:54 +02:00
|
|
|
+
|
|
|
|
+// NOTE: call `initializeWindowList` explicitly to finish initialization.
|
2018-03-09 11:02:15 +01:00
|
|
|
+class PureWinList {
|
|
|
|
+ constructor(perMonitor, monitor, maxWidthFunc) {
|
2016-09-01 12:12:54 +02:00
|
|
|
+ // NOTE: in SLE Classic `PureWinList` will NOT use any multiple monitor
|
|
|
|
+ // support, the following is kept for use in GNOME Classic as we try to
|
|
|
|
+ // unify code for two sides.
|
2017-11-07 10:42:17 +01:00
|
|
|
+ this._perMonitor = perMonitor;
|
|
|
|
+ this._monitor = monitor;
|
2016-09-01 12:12:54 +02:00
|
|
|
+ // NOTE: callback function given by the employer of this PureWinList.
|
|
|
|
+ // Since PureWinList can be used various widgets hierarchy, we have to
|
|
|
|
+ // leave the calculation of max available width to the employer.
|
|
|
|
+ this._getMaxWindowListWidth = maxWidthFunc;
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2016-09-01 12:12:54 +02:00
|
|
|
+ let layout = new Clutter.BoxLayout({ homogeneous: true });
|
|
|
|
+ this.actor = new St.Widget({ style_class: 'window-list',
|
2017-11-07 10:42:17 +01:00
|
|
|
+ reactive: true,
|
2016-09-01 12:12:54 +02:00
|
|
|
+ layout_manager: layout,
|
|
|
|
+ x_align: Clutter.ActorAlign.START,
|
|
|
|
+ x_expand: true,
|
|
|
|
+ y_expand: true });
|
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+ this.actor.connect('style-changed', () => {
|
2016-09-01 12:12:54 +02:00
|
|
|
+ let node = this.actor.get_theme_node();
|
|
|
|
+ let spacing = node.get_length('spacing');
|
|
|
|
+ this.actor.layout_manager.spacing = spacing;
|
2018-03-09 11:02:15 +01:00
|
|
|
+ });
|
|
|
|
+ this.actor.connect('scroll-event', this._onScrollEvent.bind(this));
|
|
|
|
+ this.actor.connect('destroy', this._onDestroy.bind(this));
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
|
|
|
+ this._appSystem = Shell.AppSystem.get_default();
|
|
|
|
+ this._appStateChangedId =
|
|
|
|
+ this._appSystem.connect('app-state-changed',
|
2018-03-09 11:02:15 +01:00
|
|
|
+ this._onAppStateChanged.bind(this));
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2019-07-11 20:37:00 +02:00
|
|
|
+ this._settings = ExtensionUtils.getSettings();
|
2017-10-30 11:36:30 +01:00
|
|
|
+
|
2016-09-01 12:12:54 +02:00
|
|
|
+ // Grouping
|
|
|
|
+ this._groupingModeChangedId =
|
|
|
|
+ this._settings.connect('changed::grouping-mode',
|
2018-03-09 11:02:15 +01:00
|
|
|
+ this._groupingModeChanged.bind(this));
|
2016-09-01 12:12:54 +02:00
|
|
|
+ this._grouped = undefined;
|
|
|
|
+ // NOTE: do NOT `_checkGrouping` here
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2018-09-24 09:19:06 +02:00
|
|
|
+ let workspaceManager = global.workspace_manager;
|
|
|
|
+
|
2016-09-01 12:12:54 +02:00
|
|
|
+ // workspace related
|
2017-11-07 10:42:17 +01:00
|
|
|
+ this._workspaceSignals = new Map();
|
|
|
|
+ this._nWorkspacesChangedId =
|
2018-09-24 09:19:06 +02:00
|
|
|
+ workspaceManager.connect('notify::n-workspaces',
|
|
|
|
+ this._onWorkspacesChanged.bind(this));
|
2017-11-07 10:42:17 +01:00
|
|
|
+ this._onWorkspacesChanged();
|
|
|
|
+
|
|
|
|
+ this._switchWorkspaceId =
|
|
|
|
+ global.window_manager.connect('switch-workspace',
|
2018-03-09 11:02:15 +01:00
|
|
|
+ this._checkGrouping.bind(this));
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2016-09-01 12:12:54 +02:00
|
|
|
+ // Hide and Show with Overview
|
2017-11-07 10:42:17 +01:00
|
|
|
+ this._overviewShowingId =
|
2018-03-09 11:02:15 +01:00
|
|
|
+ Main.overview.connect('showing', () => {
|
2017-11-07 10:42:17 +01:00
|
|
|
+ this.actor.hide();
|
2018-03-09 11:02:15 +01:00
|
|
|
+ });
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
|
|
|
+ this._overviewHidingId =
|
2018-03-09 11:02:15 +01:00
|
|
|
+ Main.overview.connect('hiding', () => {
|
2017-08-05 14:05:19 +02:00
|
|
|
+ this.actor.show();
|
2018-03-09 11:02:15 +01:00
|
|
|
+ });
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2017-08-05 14:05:19 +02:00
|
|
|
+ this._groupingMode = this._settings.get_enum('grouping-mode');
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+ _getDynamicWorkspacesSettings() {
|
2017-11-07 10:42:17 +01:00
|
|
|
+ if (this._workspaceSettings.list_keys().indexOf('dynamic-workspaces') > -1)
|
|
|
|
+ return this._workspaceSettings;
|
|
|
|
+ return this._mutterSettings;
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2016-09-01 12:12:54 +02:00
|
|
|
+ // NOTE: an API for parent panel to refresh the window list. This is
|
|
|
|
+ // necessary as window/app buttons require its parents having allocation and
|
|
|
|
+ // positioning *completed* before being properly allocated and positioned
|
2018-03-09 11:02:15 +01:00
|
|
|
+ initializeWindowList() {
|
2016-09-01 12:12:54 +02:00
|
|
|
+ this._groupingModeChanged();
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2016-09-01 12:12:54 +02:00
|
|
|
+ // NOTE: support scrolling in window list s.t. scrolling activate window
|
|
|
|
+ // buttons sequentially.
|
|
|
|
+ //
|
|
|
|
+ // *Code is rewritten*.
|
2018-03-09 11:02:15 +01:00
|
|
|
+ _onScrollEvent(actor, event) {
|
2017-11-07 10:42:17 +01:00
|
|
|
+ let direction = event.get_scroll_direction();
|
|
|
|
+ let diff = 0;
|
2016-09-01 12:12:54 +02:00
|
|
|
+ if (direction === Clutter.ScrollDirection.DOWN)
|
2017-11-07 10:42:17 +01:00
|
|
|
+ diff = 1;
|
2016-09-01 12:12:54 +02:00
|
|
|
+ else if (direction === Clutter.ScrollDirection.UP)
|
2017-11-07 10:42:17 +01:00
|
|
|
+ diff = -1;
|
|
|
|
+ else
|
|
|
|
+ return;
|
|
|
|
+
|
2016-09-01 12:12:54 +02:00
|
|
|
+ let buttons = this.actor.get_children().map(function(actor) {
|
2017-11-07 10:42:17 +01:00
|
|
|
+ return actor._delegate;
|
|
|
|
+ });
|
2016-09-01 12:12:54 +02:00
|
|
|
+ let totalBtnNum = buttons.length;
|
|
|
|
+
|
2017-08-05 14:05:19 +02:00
|
|
|
+ let activeBtnIdx = 0
|
2016-09-01 12:12:54 +02:00
|
|
|
+ for (let i = 0; i < totalBtnNum; i++) {
|
|
|
|
+ if (buttons[i].active) {
|
2017-08-05 14:05:19 +02:00
|
|
|
+ activeBtnIdx = i
|
2017-11-07 10:42:17 +01:00
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
2016-09-01 12:12:54 +02:00
|
|
|
+ // NOTE: bound by `0` and `totalBtnNum - 1`, no wrapping for
|
|
|
|
+ // scrolling.
|
|
|
|
+ activeBtnIdx = activeBtnIdx + diff;
|
|
|
|
+ let noScrollActionNeeded = ( (activeBtnIdx < 0) || (activeBtnIdx >= totalBtnNum) );
|
|
|
|
+ if (noScrollActionNeeded)
|
|
|
|
+ return;
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2016-09-01 12:12:54 +02:00
|
|
|
+ // TODO: no need to call `deactivate` for old `active button` ?
|
|
|
|
+ buttons[activeBtnIdx].activate();
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+ _onAppStateChanged(appSys, app) {
|
2017-08-05 14:05:19 +02:00
|
|
|
+ if (!this._grouped)
|
|
|
|
+ return;
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2017-08-05 14:05:19 +02:00
|
|
|
+ if (app.state == Shell.AppState.RUNNING)
|
|
|
|
+ this._addApp(app);
|
|
|
|
+ else if (app.state == Shell.AppState.STOPPED)
|
|
|
|
+ this._removeApp(app);
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+ _addApp(app) {
|
2016-09-01 12:12:54 +02:00
|
|
|
+ let button = new AppButton(app, this._perMonitor, this._monitor.index);
|
|
|
|
+ this.actor.layout_manager.pack(button.actor,
|
|
|
|
+ true, true, true,
|
|
|
|
+ Clutter.BoxAlignment.START,
|
2017-08-05 14:05:19 +02:00
|
|
|
+ Clutter.BoxAlignment.START)
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+ _removeApp(app) {
|
2016-09-01 12:12:54 +02:00
|
|
|
+ let children = this.actor.get_children();
|
|
|
|
+ for (let i = 0; i < children.length; i++) {
|
|
|
|
+ if (children[i]._delegate.app === app) {
|
|
|
|
+ children[i].destroy();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+ _groupingModeChanged() {
|
2017-11-07 10:42:17 +01:00
|
|
|
+ this._groupingMode = this._settings.get_enum('grouping-mode');
|
|
|
|
+
|
|
|
|
+ if (this._groupingMode == GroupingMode.AUTO) {
|
|
|
|
+ this._checkGrouping();
|
|
|
|
+ } else {
|
2016-09-01 12:12:54 +02:00
|
|
|
+ this._grouped = ( this._groupingMode === GroupingMode.ALWAYS );
|
2017-11-07 10:42:17 +01:00
|
|
|
+ this._populateWindowList();
|
|
|
|
+ }
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+ _checkGrouping() {
|
2017-11-07 10:42:17 +01:00
|
|
|
+ if (this._groupingMode != GroupingMode.AUTO)
|
|
|
|
+ return;
|
|
|
|
+
|
2016-09-01 12:12:54 +02:00
|
|
|
+ // TODO `_getMaxWindowListWidth` is known to depend on parent
|
|
|
|
+ // conditions. However the following call seems to get the right parent
|
|
|
|
+ // value. So an option to avoid timing issue is to use the following
|
|
|
|
+ // callback.
|
|
|
|
+ //
|
|
|
|
+ // this.actor.connect('allocation-changed', () => {
|
|
|
|
+ // log('parent width: ' + this.actor.get_parent().width);
|
|
|
|
+ // });
|
|
|
|
+ //
|
|
|
|
+ // The legitimacy can be explained in the (guessed) algorithm of
|
|
|
|
+ // allocation: Bubble up then propagate down (like DOM Events?). In
|
|
|
|
+ // details: changes that would alter the geometric properties of a
|
|
|
|
+ // widget would trigger a re-allocation to its parent AFTER some initial
|
|
|
|
+ // allocation calculation of its own (for queries like
|
|
|
|
+ // `_get_preferred_width` work for its parents). The `re-allocation`
|
|
|
|
+ // would bubble up the widget hierarchy till one widget stops it (e.g. a
|
|
|
|
+ // widget that has fixed size and absolute positioning and thus it does
|
|
|
|
+ // not need to send re-allocation request up.). Then the re-allocation
|
|
|
|
+ // signal is sent down to its origin. (downward propagation is necessary
|
|
|
|
+ // as much of the positioning and allocation depends on one's parent)
|
2017-11-07 10:42:17 +01:00
|
|
|
+ let maxWidth = this._getMaxWindowListWidth();
|
|
|
|
+ let natWidth = this._getPreferredUngroupedWindowListWidth();
|
|
|
|
+
|
|
|
|
+ let grouped = (maxWidth < natWidth);
|
|
|
|
+ if (this._grouped !== grouped) {
|
|
|
|
+ this._grouped = grouped;
|
|
|
|
+ this._populateWindowList();
|
|
|
|
+ }
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+ _populateWindowList() {
|
2016-09-01 12:12:54 +02:00
|
|
|
+ this.actor.destroy_all_children();
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
|
|
|
+ if (!this._grouped) {
|
|
|
|
+ let windows = global.get_window_actors().sort(
|
|
|
|
+ function(w1, w2) {
|
|
|
|
+ return w1.metaWindow.get_stable_sequence() -
|
|
|
|
+ w2.metaWindow.get_stable_sequence();
|
|
|
|
+ });
|
|
|
|
+ for (let i = 0; i < windows.length; i++)
|
|
|
|
+ this._onWindowAdded(null, windows[i].metaWindow);
|
|
|
|
+ } else {
|
|
|
|
+ let apps = this._appSystem.get_running().sort(
|
|
|
|
+ function(a1, a2) {
|
|
|
|
+ return _getAppStableSequence(a1) -
|
|
|
|
+ _getAppStableSequence(a2);
|
|
|
|
+ });
|
|
|
|
+ for (let i = 0; i < apps.length; i++)
|
|
|
|
+ this._addApp(apps[i]);
|
|
|
|
+ }
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2016-09-01 12:12:54 +02:00
|
|
|
+ // NOTE the `ws` params in the following two are not used (necessarily be
|
|
|
|
+ // here as the event handler Interface dictates).
|
2018-03-09 11:02:15 +01:00
|
|
|
+ _onWindowAdded(ws, win) {
|
2017-11-07 10:42:17 +01:00
|
|
|
+ if (win.skip_taskbar)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (!this._grouped)
|
|
|
|
+ this._checkGrouping();
|
|
|
|
+
|
|
|
|
+ if (this._grouped)
|
|
|
|
+ return;
|
|
|
|
+
|
2016-09-01 12:12:54 +02:00
|
|
|
+ let children = this.actor.get_children();
|
2017-11-07 10:42:17 +01:00
|
|
|
+ for (let i = 0; i < children.length; i++) {
|
|
|
|
+ if (children[i]._delegate.metaWindow == win)
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ let button = new WindowButton(win, this._perMonitor, this._monitor.index);
|
2016-09-01 12:12:54 +02:00
|
|
|
+ this.actor.layout_manager.pack(button.actor,
|
|
|
|
+ true, true, true,
|
|
|
|
+ Clutter.BoxAlignment.START,
|
|
|
|
+ Clutter.BoxAlignment.START);
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+ _onWindowRemoved(ws, win) {
|
2017-11-07 10:42:17 +01:00
|
|
|
+ if (this._grouped)
|
|
|
|
+ this._checkGrouping();
|
|
|
|
+
|
2016-09-01 12:12:54 +02:00
|
|
|
+ // NOTE: if it's still grouped after `checking`, do nothing, window
|
|
|
|
+ // removal is managed by `AppButton` anyway.
|
2017-11-07 10:42:17 +01:00
|
|
|
+ if (this._grouped)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (win.get_compositor_private())
|
|
|
|
+ return; // not actually removed, just moved to another workspace
|
|
|
|
+
|
2016-09-01 12:12:54 +02:00
|
|
|
+ let children = this.actor.get_children();
|
2017-11-07 10:42:17 +01:00
|
|
|
+ for (let i = 0; i < children.length; i++) {
|
|
|
|
+ if (children[i]._delegate.metaWindow == win) {
|
|
|
|
+ children[i].destroy();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+ _getPreferredUngroupedWindowListWidth() {
|
2016-09-01 12:12:54 +02:00
|
|
|
+ if (this.actor.get_n_children() == 0)
|
|
|
|
+ return this.actor.get_preferred_width(-1)[1];
|
|
|
|
+
|
|
|
|
+ let children = this.actor.get_children();
|
|
|
|
+ let [, childWidth] = children[0].get_preferred_width(-1);
|
|
|
|
+ let spacing = this.actor.layout_manager.spacing;
|
|
|
|
+
|
2019-04-17 14:56:20 +02:00
|
|
|
+ let workspace = global.workspace_manager.get_active_workspace();
|
2016-09-01 12:12:54 +02:00
|
|
|
+ let windows = global.display.get_tab_list(Meta.TabList.NORMAL, workspace);
|
2018-03-09 11:02:15 +01:00
|
|
|
+ if (this._perMonitor)
|
|
|
|
+ windows = windows.filter(w => w.get_monitor() == this._monitor.index);
|
2016-09-01 12:12:54 +02:00
|
|
|
+ let nWindows = windows.length;
|
|
|
|
+ if (nWindows == 0)
|
|
|
|
+ return this.actor.get_preferred_width(-1)[1];
|
|
|
|
+
|
|
|
|
+ return nWindows * childWidth + (nWindows - 1) * spacing;
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2016-09-01 12:12:54 +02:00
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+ _onWorkspacesChanged() {
|
2018-09-24 09:19:06 +02:00
|
|
|
+ let workspaceManager = global.workspace_manager;
|
|
|
|
+ let numWorkspaces = workspaceManager.n_workspaces;
|
2017-11-07 10:42:17 +01:00
|
|
|
+ for (let i = 0; i < numWorkspaces; i++) {
|
2018-09-24 09:19:06 +02:00
|
|
|
+ let workspace = workspaceManager.get_workspace_by_index(i);
|
2017-11-07 10:42:17 +01:00
|
|
|
+ if (this._workspaceSignals.has(workspace))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ let signals = { windowAddedId: 0, windowRemovedId: 0 };
|
|
|
|
+ signals._windowAddedId =
|
|
|
|
+ workspace.connect_after('window-added',
|
2018-03-09 11:02:15 +01:00
|
|
|
+ this._onWindowAdded.bind(this));
|
2017-11-07 10:42:17 +01:00
|
|
|
+ signals._windowRemovedId =
|
|
|
|
+ workspace.connect('window-removed',
|
2018-03-09 11:02:15 +01:00
|
|
|
+ this._onWindowRemoved.bind(this));
|
2017-11-07 10:42:17 +01:00
|
|
|
+ this._workspaceSignals.set(workspace, signals);
|
|
|
|
+ }
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+ _disconnectWorkspaceSignals() {
|
2019-04-17 14:56:20 +02:00
|
|
|
+ let numWorkspaces = global.workspace_manager.n_workspaces;
|
2017-11-07 10:42:17 +01:00
|
|
|
+ for (let i = 0; i < numWorkspaces; i++) {
|
2019-04-17 14:56:20 +02:00
|
|
|
+ let workspace = global.workspace_manager.get_workspace_by_index(i);
|
2017-11-07 10:42:17 +01:00
|
|
|
+ let signals = this._workspaceSignals.get(workspace);
|
|
|
|
+ this._workspaceSignals.delete(workspace);
|
|
|
|
+ workspace.disconnect(signals._windowAddedId);
|
|
|
|
+ workspace.disconnect(signals._windowRemovedId);
|
|
|
|
+ }
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2017-11-07 10:42:17 +01:00
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+ _onDestroy() {
|
2016-09-01 12:12:54 +02:00
|
|
|
+ Main.overview.disconnect(this._overviewHidingId);
|
|
|
|
+ this._overviewHidingId = 0;
|
|
|
|
+ Main.overview.disconnect(this._overviewShowingId);
|
|
|
|
+ this._overviewShowingId = 0;
|
|
|
|
+
|
2019-04-17 14:56:20 +02:00
|
|
|
+ global.workspace_manager.disconnect(this._nWorkspacesChangedId);
|
2016-09-01 12:12:54 +02:00
|
|
|
+ this._nWorkspacesChangedId = 0;
|
|
|
|
+ global.window_manager.disconnect(this._switchWorkspaceId);
|
|
|
|
+ this._switchWorkspaceId = 0;
|
|
|
|
+ this._disconnectWorkspaceSignals();
|
|
|
|
+
|
|
|
|
+ this._settings.disconnect(this._groupingModeChangedId);
|
|
|
|
+ this._groupingModeChangedId = 0;
|
|
|
|
+
|
|
|
|
+ this._appSystem.disconnect(this._appStateChangedId);
|
|
|
|
+ this._appStateChangedId = 0;
|
|
|
|
+
|
|
|
|
+ let windows = global.get_window_actors();
|
|
|
|
+ for (let i = 0; i < windows.length; i++)
|
|
|
|
+ windows[i].metaWindow.set_icon_geometry(null);
|
|
|
|
+ }
|
2018-03-09 11:02:15 +01:00
|
|
|
+};
|
2016-09-01 12:12:54 +02:00
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+class SCExtension {
|
|
|
|
+ constructor() {
|
2016-09-01 12:12:54 +02:00
|
|
|
+ this._pureWinList = null;
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2016-09-01 12:12:54 +02:00
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+ enable() {
|
2016-09-01 12:12:54 +02:00
|
|
|
+ // NOTE For SLE Classic, a window list is shown on Main panel ONLY
|
|
|
|
+ let showOnAllMonitors = false;
|
|
|
|
+ // NOTE Use a guessed value passed to `PureWinList` as `checkGrouping`
|
|
|
|
+ // is run at a time the allocation of the panel boxes might not complete
|
|
|
|
+ // yet (and thus we get almost random width value). The other options
|
|
|
|
+ // are to duplicate the centerbox width calculation or change the order
|
|
|
|
+ // of grouping check code (way more complicated).
|
|
|
|
+ //
|
|
|
|
+ // This value is guessed *conservatively*. Further this value is used by
|
|
|
|
+ // AUTO grouping only.
|
|
|
|
+ //
|
|
|
|
+ // NOTE: no Promise is available
|
|
|
|
+ let panelCenterBoxWidth = Main.panel.actor.width * 0.8;
|
|
|
|
+
|
|
|
|
+ this._pureWinList = new PureWinList(showOnAllMonitors,
|
|
|
|
+ Main.layoutManager.primaryMonitor,
|
|
|
|
+ () => panelCenterBoxWidth );
|
|
|
|
+ Main.panel._centerBox.add(this._pureWinList.actor, {expand: true});
|
|
|
|
+ let _winListRefreshId = Main.panel._centerBox.connect(
|
|
|
|
+ 'allocation-changed',
|
|
|
|
+ () => {
|
2017-08-24 18:46:42 +02:00
|
|
|
+ if (this._pureWinList == null)
|
|
|
|
+ return;
|
|
|
|
+
|
2016-09-01 12:12:54 +02:00
|
|
|
+ this._pureWinList.initializeWindowList();
|
|
|
|
+ Main.panel._centerBox.disconnect(_winListRefreshId);
|
|
|
|
+ });
|
|
|
|
+ // NOTE: IMO, no need to rebuild `_pureWinList` when monitors changed.
|
|
|
|
+ // No need for `showOnAllMonitors` change either even this option
|
|
|
|
+ // changes.
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2016-09-01 12:12:54 +02:00
|
|
|
+
|
2018-03-09 11:02:15 +01:00
|
|
|
+ disable() {
|
2016-09-01 12:12:54 +02:00
|
|
|
+ if (!this._pureWinList)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ this._pureWinList.actor.hide();
|
|
|
|
+ this._pureWinList.actor.destroy();
|
|
|
|
+
|
|
|
|
+ this._pureWinList = null;
|
2018-03-09 11:02:15 +01:00
|
|
|
+ }
|
2016-09-01 12:12:54 +02:00
|
|
|
+
|
|
|
|
+ // NOTE: this function is used for multiple window list situations, invalid for SCExtension case, let's return false.
|
2018-03-09 11:02:15 +01:00
|
|
|
+ someWindowListContains(actor) {
|
2016-09-01 12:12:54 +02:00
|
|
|
+ return false;
|
|
|
|
+ }
|
2018-03-09 11:02:15 +01:00
|
|
|
+};
|
2017-11-07 10:42:17 +01:00
|
|
|
|
|
|
|
function _minimizeOrActivateWindow(window) {
|
2019-04-17 14:56:20 +02:00
|
|
|
let focusWindow = global.display.focus_window;
|
|
|
|
@@ -644,8 +1036,8 @@ class AppButton extends BaseButton {
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-let WorkspaceIndicator = GObject.registerClass(
|
|
|
|
-class WorkspaceIndicator extends PanelMenu.Button {
|
|
|
|
+let WorkspaceIndicatorWList = GObject.registerClass(
|
|
|
|
+class WorkspaceIndicatorWList extends PanelMenu.Button {
|
|
|
|
_init() {
|
|
|
|
super._init(0.0, _('Workspace Indicator'), true);
|
|
|
|
this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM));
|
|
|
|
@@ -808,7 +1200,7 @@ class WindowList {
|
|
|
|
let indicatorsBox = new St.BoxLayout({ x_align: Clutter.ActorAlign.END });
|
|
|
|
box.add(indicatorsBox);
|
|
|
|
|
|
|
|
- this._workspaceIndicator = new WorkspaceIndicator();
|
|
|
|
+ this._workspaceIndicator = new WorkspaceIndicatorWList();
|
|
|
|
indicatorsBox.add(this._workspaceIndicator.container, { expand: false, y_fill: true });
|
|
|
|
|
|
|
|
this._mutterSettings = new Gio.Settings({ schema_id: 'org.gnome.mutter' });
|
|
|
|
@@ -1259,5 +1651,10 @@ class Extension {
|
|
|
|
}
|
2017-11-07 10:42:17 +01:00
|
|
|
|
2016-09-01 12:12:54 +02:00
|
|
|
function init() {
|
|
|
|
- return new Extension();
|
2017-11-07 10:42:17 +01:00
|
|
|
+ if ( isSLEClassicMode() ){
|
2016-09-01 12:12:54 +02:00
|
|
|
+ return new SCExtension();
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ return new Extension();
|
|
|
|
+ }
|
|
|
|
}
|
2019-04-17 14:56:20 +02:00
|
|
|
diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css
|
|
|
|
index f5285cb..c207078 100644
|
|
|
|
--- a/extensions/window-list/stylesheet.css
|
|
|
|
+++ b/extensions/window-list/stylesheet.css
|
2016-09-01 12:12:54 +02:00
|
|
|
@@ -79,6 +79,10 @@
|
|
|
|
border: 1px solid #cccccc;
|
|
|
|
}
|
|
|
|
|
|
|
|
+.bottom-panel-menu {
|
|
|
|
+ -boxpointer-gap: 4px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
.notification {
|
|
|
|
font-weight: normal;
|
|
|
|
}
|
2019-04-17 14:56:20 +02:00
|
|
|
diff --git a/data/gnome-classic.scss b/data/gnome-classic.scss
|
|
|
|
index 9e23506..be56527 100644
|
|
|
|
--- a/data/gnome-classic.scss
|
|
|
|
+++ b/data/gnome-classic.scss
|
2018-08-05 02:46:21 +02:00
|
|
|
@@ -103,3 +103,15 @@ $variant: 'light';
|
|
|
|
&:hover, &focus { background-color: darken($bg_color,2%); }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
+
|
|
|
|
+.popup-menu {
|
|
|
|
+ &.panel-menu {
|
|
|
|
+ -boxpointer-gap: 4px;
|
|
|
|
+ /* TODO was 1.75em, no idea of its use */
|
|
|
|
+ /* NOTE: the following creates an ugly gap between menu and its source actor
|
|
|
|
+ when the PanelMenu's source actor is at the bottom. Preferrably for
|
|
|
|
+ bottom menu, `margin-top` might be a better choice. However, since we
|
|
|
|
+ have no idea about its use so reset to 0 for now. */
|
|
|
|
+ margin-bottom: 0em;
|
|
|
|
+ }
|
|
|
|
+}
|