gnome-shell-extensions/gse-sle-classic-ext.patch

878 lines
35 KiB
Diff
Raw Normal View History

Index: gnome-shell-extensions-3.24.2/data/gnome-classic.css
===================================================================
--- gnome-shell-extensions-3.24.2.orig/data/gnome-classic.css
+++ gnome-shell-extensions-3.24.2/data/gnome-classic.css
@@ -512,7 +512,12 @@ StScrollBar {
color: rgba(46, 52, 54, 0.5); }
.popup-menu.panel-menu {
-boxpointer-gap: 4px;
- margin-bottom: 1.75em; }
+ /* 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; }
.popup-menu-ornament {
text-align: right;
@@ -877,6 +882,7 @@ StScrollBar {
width: 31.5em; }
.message-list-clear-button.button {
+ color: black;
background-color: transparent;
margin: 1.5em 1.5em 0; }
.message-list-clear-button.button:hover, .message-list-clear-button.button:focus {
@@ -900,7 +906,6 @@ StScrollBar {
padding: 10px 10px 10px 3px; }
.message-icon-bin > StIcon {
- color: black;
icon-size: 16px;
-st-icon-style: symbolic; }
@@ -917,11 +922,9 @@ StScrollBar {
.message-secondary-bin > StIcon {
icon-size: 16px; }
-.message-title {
- color: #222728; }
+.message-title {}
.message-content {
- color: black;
padding: 10px; }
.message-media-control {
Index: gnome-shell-extensions-3.24.2/extensions/window-list/classic.css
===================================================================
--- gnome-shell-extensions-3.24.2.orig/extensions/window-list/classic.css
+++ gnome-shell-extensions-3.24.2/extensions/window-list/classic.css
@@ -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;
@@ -22,25 +22,25 @@
text-shadow: 0 0 transparent;
}
- .bottom-panel .window-button:hover > StWidget {
+ .window-button:hover > StWidget {
background-color: #f9f9f9;
}
- .bottom-panel .window-button:active > StWidget,
- .bottom-panel .window-button:focus > StWidget {
+ .window-button:active > StWidget,
+ .window-button:focus > StWidget {
box-shadow: inset 1px 1px 2px rgba(0,0,0,0.5);
}
- .bottom-panel .window-button.focused > StWidget {
+ .window-button.focused > StWidget {
background-color: #ddd;
box-shadow: inset 1px 1px 1px rgba(0,0,0,0.5);
}
- .bottom-panel .window-button.focused:hover > StWidget {
+ .window-button.focused:hover > StWidget {
background-color: #e9e9e9;
}
- .bottom-panel .window-button.minimized > StWidget {
+ .window-button.minimized > StWidget {
color: #888;
box-shadow: inset -1px -1px 1px rgba(0,0,0,0.5);
}
Index: gnome-shell-extensions-3.24.2/extensions/window-list/extension.js
===================================================================
--- gnome-shell-extensions-3.24.2.orig/extensions/window-list/extension.js
+++ gnome-shell-extensions-3.24.2/extensions/window-list/extension.js
@@ -22,6 +22,8 @@ const _ = Gettext.gettext;
const ICON_TEXTURE_SIZE = 24;
const DND_ACTIVATE_TIMEOUT = 500;
+const SLEClassicExt = imports.ui.SLEClassicExt;
+
const GroupingMode = {
NEVER: 0,
AUTO: 1,
@@ -64,6 +66,9 @@ function _getAppStableSequence(app) {
}
+// TODO: not critical, but with `gnome-shell -r` there are `St-CRITICAL` errors
+// shown in stdout, 3 warnings for each existing window. Wrong initialization
+// order?
const WindowContextMenu = new Lang.Class({
Name: 'WindowContextMenu',
Extends: PopupMenu.PopupMenu,
@@ -113,6 +118,9 @@ const WindowContextMenu = new Lang.Class
}));
this.addMenuItem(item);
+ // NOTE add `-boxpointer-gap` to the menu, to align with `PanelMenu`,
+ // totally optional.
+ this.actor.add_style_class_name('bottom-panel-menu');
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
},
@@ -669,6 +677,8 @@ const WorkspaceIndicator = new Lang.Clas
this.parent(0.0, _("Workspace Indicator"), true);
this.setMenu(new PopupMenu.PopupMenu(this.actor, 0.0, St.Side.BOTTOM));
this.actor.add_style_class_name('window-list-workspace-indicator');
+ // NOTE: add `-boxpointer-gap`, totally optional
+ this.menu.actor.add_style_class_name('bottom-panel-menu');
this.menu.actor.remove_style_class_name('panel-menu');
let container = new St.Widget({ layout_manager: new Clutter.BinLayout(),
@@ -773,88 +783,53 @@ const WorkspaceIndicator = new Lang.Clas
}
});
-const WindowList = new Lang.Class({
- Name: 'WindowList',
-
- _init: function(perMonitor, monitor) {
+// NOTE: call `initializeWindowList` explicitly to finish initialization.
+const PureWinList = new Lang.Class({
+ Name: 'PureWinList',
+
+ _init: function(perMonitor, monitor, maxWidthFunc) {
+ // 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.
this._perMonitor = perMonitor;
this._monitor = monitor;
+ // 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;
- this.actor = new St.Widget({ name: 'panel',
- style_class: 'bottom-panel',
+ let layout = new Clutter.BoxLayout({ homogeneous: true });
+ this.actor = new St.Widget({ style_class: 'window-list',
reactive: true,
- track_hover: true,
- layout_manager: new Clutter.BinLayout()});
+ layout_manager: layout,
+ x_align: Clutter.ActorAlign.START,
+ x_expand: true,
+ y_expand: true });
+
+ this.actor.connect('style-changed', Lang.bind(this, function() {
+ let node = this.actor.get_theme_node();
+ let spacing = node.get_length('spacing');
+ this.actor.layout_manager.spacing = spacing;
+ }));
+ this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
- let box = new St.BoxLayout({ x_expand: true, y_expand: true });
- this.actor.add_actor(box);
-
- let layout = new Clutter.BoxLayout({ homogeneous: true });
- this._windowList = new St.Widget({ style_class: 'window-list',
- reactive: true,
- layout_manager: layout,
- x_align: Clutter.ActorAlign.START,
- x_expand: true,
- y_expand: true });
- box.add(this._windowList, { expand: true });
-
- this._windowList.connect('style-changed', Lang.bind(this,
- function() {
- let node = this._windowList.get_theme_node();
- let spacing = node.get_length('spacing');
- this._windowList.layout_manager.spacing = spacing;
- }));
- this._windowList.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
-
- let indicatorsBox = new St.BoxLayout({ x_align: Clutter.ActorAlign.END });
- box.add(indicatorsBox);
-
- this._workspaceIndicator = new WorkspaceIndicator();
- indicatorsBox.add(this._workspaceIndicator.container, { expand: false, y_fill: true });
-
- this._mutterSettings = new Gio.Settings({ schema_id: 'org.gnome.mutter' });
- this._workspaceSettings = this._getWorkspaceSettings();
- this._workspacesOnlyOnPrimaryChangedId =
- this._workspaceSettings.connect('changed::workspaces-only-on-primary',
- Lang.bind(this, this._updateWorkspaceIndicatorVisibility));
- this._dynamicWorkspacesSettings = this._getDynamicWorkspacesSettings();
- this._dynamicWorkspacesChangedId =
- this._dynamicWorkspacesSettings.connect('changed::dynamic-workspaces',
- Lang.bind(this, this._updateWorkspaceIndicatorVisibility));
- this._updateWorkspaceIndicatorVisibility();
-
- this._menuManager = new PopupMenu.PopupMenuManager(this);
- this._menuManager.addMenu(this._workspaceIndicator.menu);
-
- Main.layoutManager.addChrome(this.actor, { affectsStruts: true,
- trackFullscreen: true });
- Main.uiGroup.set_child_above_sibling(this.actor, Main.layoutManager.panelBox);
- Main.ctrlAltTabManager.addGroup(this.actor, _("Window List"), 'start-here-symbolic');
-
- this.actor.width = this._monitor.width;
- this.actor.connect('notify::height', Lang.bind(this, this._updatePosition));
- this._updatePosition();
this._appSystem = Shell.AppSystem.get_default();
this._appStateChangedId =
this._appSystem.connect('app-state-changed',
Lang.bind(this, this._onAppStateChanged));
- this._keyboardVisiblechangedId =
- Main.layoutManager.connect('keyboard-visible-changed',
- Lang.bind(this, function(o, state) {
- Main.layoutManager.keyboardBox.visible = state;
- let keyboardBox = Main.layoutManager.keyboardBox;
- keyboardBox.visible = state;
- if (state)
- Main.uiGroup.set_child_above_sibling(this.actor, keyboardBox);
- else
- Main.uiGroup.set_child_above_sibling(this.actor,
- Main.layoutManager.panelBox);
- this._updateKeyboardAnchor();
- }));
+ this._settings = Convenience.getSettings();
+ // Grouping
+ this._groupingModeChangedId =
+ this._settings.connect('changed::grouping-mode',
+ Lang.bind(this, this._groupingModeChanged));
+ this._grouped = undefined;
+ // NOTE: do NOT `_checkGrouping` here
+
+ // workspace related
this._workspaceSignals = new Map();
this._nWorkspacesChangedId =
global.screen.connect('notify::n-workspaces',
@@ -865,42 +840,18 @@ const WindowList = new Lang.Class({
global.window_manager.connect('switch-workspace',
Lang.bind(this, this._checkGrouping));
+ // Hide and Show with Overview
this._overviewShowingId =
Main.overview.connect('showing', Lang.bind(this, function() {
this.actor.hide();
- this._updateKeyboardAnchor();
}));
this._overviewHidingId =
Main.overview.connect('hiding', Lang.bind(this, function() {
- this.actor.visible = !Main.layoutManager.primaryMonitor.inFullscreen;
- this._updateKeyboardAnchor();
- }));
-
- this._fullscreenChangedId =
- global.screen.connect('in-fullscreen-changed', Lang.bind(this, function() {
- this._updateKeyboardAnchor();
+ this.actor.show();
}));
- this._dragBeginId =
- Main.xdndHandler.connect('drag-begin',
- Lang.bind(this, this._onDragBegin));
- this._dragEndId =
- Main.xdndHandler.connect('drag-end',
- Lang.bind(this, this._onDragEnd));
- this._dragMonitor = {
- dragMotion: Lang.bind(this, this._onDragMotion)
- };
-
- this._dndTimeoutId = 0;
- this._dndWindow = null;
-
- this._settings = Convenience.getSettings();
- this._groupingModeChangedId =
- this._settings.connect('changed::grouping-mode',
- Lang.bind(this, this._groupingModeChanged));
- this._grouped = undefined;
- this._groupingModeChanged();
+ this._groupingMode = this._settings.get_enum('grouping-mode');
},
_getDynamicWorkspacesSettings: function() {
@@ -909,77 +860,77 @@ const WindowList = new Lang.Class({
return this._mutterSettings;
},
- _getWorkspaceSettings: function() {
- let settings = global.get_overrides_settings();
- if (settings.list_keys().indexOf('workspaces-only-on-primary') > -1)
- return settings;
- return this._mutterSettings;
+ // 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
+ initializeWindowList: function() {
+ this._groupingModeChanged();
},
+ // NOTE: support scrolling in window list s.t. scrolling activate window
+ // buttons sequentially.
+ //
+ // *Code is rewritten*.
_onScrollEvent: function(actor, event) {
let direction = event.get_scroll_direction();
let diff = 0;
- if (direction == Clutter.ScrollDirection.DOWN)
+ if (direction === Clutter.ScrollDirection.DOWN)
diff = 1;
- else if (direction == Clutter.ScrollDirection.UP)
+ else if (direction === Clutter.ScrollDirection.UP)
diff = -1;
else
return;
- let children = this._windowList.get_children().map(function(actor) {
+ let buttons = this.actor.get_children().map(function(actor) {
return actor._delegate;
});
- let active = 0;
- for (let i = 0; i < children.length; i++) {
- if (children[i].active) {
- active = i;
+ let totalBtnNum = buttons.length;
+
+ let activeBtnIdx = 0
+ for (let i = 0; i < totalBtnNum; i++) {
+ if (buttons[i].active) {
+ activeBtnIdx = i
break;
}
}
- active = Math.max(0, Math.min(active + diff, children.length-1));
- children[active].activate();
- },
+ // NOTE: bound by `0` and `totalBtnNum - 1`, no wrapping for
+ // scrolling.
+ activeBtnIdx = activeBtnIdx + diff;
+ let noScrollActionNeeded = ( (activeBtnIdx < 0) || (activeBtnIdx >= totalBtnNum) );
+ if (noScrollActionNeeded)
+ return;
- _updatePosition: function() {
- this.actor.set_position(this._monitor.x,
- this._monitor.y + this._monitor.height - this.actor.height);
+ // TODO: no need to call `deactivate` for old `active button` ?
+ buttons[activeBtnIdx].activate();
},
- _updateWorkspaceIndicatorVisibility: function() {
- let hasWorkspaces = this._dynamicWorkspacesSettings.get_boolean('dynamic-workspaces') ||
- global.screen.n_workspaces > 1;
- let workspacesOnMonitor = this._monitor == Main.layoutManager.primaryMonitor ||
- !this._workspaceSettings.get_boolean('workspaces-only-on-primary');
+ _onAppStateChanged: function(appSys, app) {
+ if (!this._grouped)
+ return;
- this._workspaceIndicator.actor.visible = hasWorkspaces && workspacesOnMonitor;
+ if (app.state == Shell.AppState.RUNNING)
+ this._addApp(app);
+ else if (app.state == Shell.AppState.STOPPED)
+ this._removeApp(app);
},
- _getPreferredUngroupedWindowListWidth: function() {
- if (this._windowList.get_n_children() == 0)
- return this._windowList.get_preferred_width(-1)[1];
-
- let children = this._windowList.get_children();
- let [, childWidth] = children[0].get_preferred_width(-1);
- let spacing = this._windowList.layout_manager.spacing;
-
- let workspace = global.screen.get_active_workspace();
- let windows = global.display.get_tab_list(Meta.TabList.NORMAL, workspace);
- if (this._perMonitor) {
- windows = windows.filter(Lang.bind(this, function(window) {
- return window.get_monitor() == this._monitor.index;
- }));
- }
- let nWindows = windows.length;
- if (nWindows == 0)
- return this._windowList.get_preferred_width(-1)[1];
-
- return nWindows * childWidth + (nWindows - 1) * spacing;
+ _addApp: function(app) {
+ let button = new AppButton(app, this._perMonitor, this._monitor.index);
+ this.actor.layout_manager.pack(button.actor,
+ true, true, true,
+ Clutter.BoxAlignment.START,
+ Clutter.BoxAlignment.START)
},
- _getMaxWindowListWidth: function() {
- let indicatorsBox = this._workspaceIndicator.actor.get_parent();
- return this.actor.width - indicatorsBox.get_preferred_width(-1)[1];
+ _removeApp: function(app) {
+ let children = this.actor.get_children();
+ for (let i = 0; i < children.length; i++) {
+ if (children[i]._delegate.app === app) {
+ children[i].destroy();
+ return;
+ }
+ }
},
_groupingModeChanged: function() {
@@ -988,7 +939,7 @@ const WindowList = new Lang.Class({
if (this._groupingMode == GroupingMode.AUTO) {
this._checkGrouping();
} else {
- this._grouped = this._groupingMode == GroupingMode.ALWAYS;
+ this._grouped = ( this._groupingMode === GroupingMode.ALWAYS );
this._populateWindowList();
}
},
@@ -997,6 +948,26 @@ const WindowList = new Lang.Class({
if (this._groupingMode != GroupingMode.AUTO)
return;
+ // 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)
let maxWidth = this._getMaxWindowListWidth();
let natWidth = this._getPreferredUngroupedWindowListWidth();
@@ -1008,7 +979,7 @@ const WindowList = new Lang.Class({
},
_populateWindowList: function() {
- this._windowList.destroy_all_children();
+ this.actor.destroy_all_children();
if (!this._grouped) {
let windows = global.get_window_actors().sort(
@@ -1029,42 +1000,8 @@ const WindowList = new Lang.Class({
}
},
- _updateKeyboardAnchor: function() {
- if (!Main.keyboard.actor)
- return;
-
- let anchorY = Main.overview.visible ? 0 : this.actor.height;
- Main.keyboard.actor.anchor_y = anchorY;
- },
-
- _onAppStateChanged: function(appSys, app) {
- if (!this._grouped)
- return;
-
- if (app.state == Shell.AppState.RUNNING)
- this._addApp(app);
- else if (app.state == Shell.AppState.STOPPED)
- this._removeApp(app);
- },
-
- _addApp: function(app) {
- let button = new AppButton(app, this._perMonitor, this._monitor.index);
- this._windowList.layout_manager.pack(button.actor,
- true, true, true,
- Clutter.BoxAlignment.START,
- Clutter.BoxAlignment.START);
- },
-
- _removeApp: function(app) {
- let children = this._windowList.get_children();
- for (let i = 0; i < children.length; i++) {
- if (children[i]._delegate.app == app) {
- children[i].destroy();
- return;
- }
- }
- },
-
+ // NOTE the `ws` params in the following two are not used (necessarily be
+ // here as the event handler Interface dictates).
_onWindowAdded: function(ws, win) {
if (win.skip_taskbar)
return;
@@ -1075,30 +1012,32 @@ const WindowList = new Lang.Class({
if (this._grouped)
return;
- let children = this._windowList.get_children();
+ let children = this.actor.get_children();
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);
- this._windowList.layout_manager.pack(button.actor,
- true, true, true,
- Clutter.BoxAlignment.START,
- Clutter.BoxAlignment.START);
+ this.actor.layout_manager.pack(button.actor,
+ true, true, true,
+ Clutter.BoxAlignment.START,
+ Clutter.BoxAlignment.START);
},
_onWindowRemoved: function(ws, win) {
if (this._grouped)
this._checkGrouping();
+ // NOTE: if it's still grouped after `checking`, do nothing, window
+ // removal is managed by `AppButton` anyway.
if (this._grouped)
return;
if (win.get_compositor_private())
return; // not actually removed, just moved to another workspace
- let children = this._windowList.get_children();
+ let children = this.actor.get_children();
for (let i = 0; i < children.length; i++) {
if (children[i]._delegate.metaWindow == win) {
children[i].destroy();
@@ -1107,6 +1046,28 @@ const WindowList = new Lang.Class({
}
},
+ _getPreferredUngroupedWindowListWidth: function() {
+ 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;
+
+ let workspace = global.screen.get_active_workspace();
+ let windows = global.display.get_tab_list(Meta.TabList.NORMAL, workspace);
+ if (this._perMonitor) {
+ windows = windows.filter(Lang.bind(this, function(window) {
+ return window.get_monitor() == this._monitor.index;
+ }));
+ }
+ let nWindows = windows.length;
+ if (nWindows == 0)
+ return this.actor.get_preferred_width(-1)[1];
+
+ return nWindows * childWidth + (nWindows - 1) * spacing;
+ },
+
_onWorkspacesChanged: function() {
let numWorkspaces = global.screen.n_workspaces;
for (let i = 0; i < numWorkspaces; i++) {
@@ -1123,8 +1084,6 @@ const WindowList = new Lang.Class({
Lang.bind(this, this._onWindowRemoved));
this._workspaceSignals.set(workspace, signals);
}
-
- this._updateWorkspaceIndicatorVisibility();
},
_disconnectWorkspaceSignals: function() {
@@ -1138,6 +1097,157 @@ const WindowList = new Lang.Class({
}
},
+ _onDestroy: function() {
+ Main.overview.disconnect(this._overviewHidingId);
+ this._overviewHidingId = 0;
+ Main.overview.disconnect(this._overviewShowingId);
+ this._overviewShowingId = 0;
+
+ global.screen.disconnect(this._nWorkspacesChangedId);
+ 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);
+ }
+});
+
+// NOTE: the following so-called `WindowList` is actually a bottom panel. The
+// "list of windows" part is going to be factored out into `PureWinList`,
+// specially designed to adapt this extension for use with `SLE-Classic` mode.
+const WindowList = new Lang.Class({
+ Name: 'WindowList',
+
+ _init: function(perMonitor, monitor) {
+ this._perMonitor = perMonitor;
+ this._monitor = monitor;
+
+ this.actor = new St.Widget({ name: 'panel',
+ style_class: 'bottom-panel',
+ reactive: true,
+ track_hover: true,
+ layout_manager: new Clutter.BinLayout()});
+ this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
+
+ let box = new St.BoxLayout({ x_expand: true, y_expand: true });
+ this.actor.add_actor(box);
+
+ let maxWinListWidthFunc = () => {
+ let indicatorsBox = this._workspaceIndicator.actor.get_parent();
+ return this.actor.width - indicatorsBox.get_preferred_width(-1)[1];
+ };
+ this._windowList = new PureWinList(perMonitor, monitor, maxWinListWidthFunc);
+ box.add(this._windowList.actor, { expand: true });
+ let _windowListInitId = this.actor.connect('allocation-changed',
+ () => {
+ this._windowList.initializeWindowList();
+ this.actor.disconnect(_windowListInitId);
+ });
+
+ let indicatorsBox = new St.BoxLayout({ x_align: Clutter.ActorAlign.END });
+ box.add(indicatorsBox);
+ this._workspaceIndicator = new WorkspaceIndicator();
+ indicatorsBox.add(this._workspaceIndicator.container, { expand: false, y_fill: true });
+
+ this._workspaceSettings = this._getWorkspaceSettings();
+ this._workspacesOnlyOnPrimaryChangedId =
+ this._workspaceSettings.connect('changed::workspaces-only-on-primary',
+ Lang.bind(this, this._updateWorkspaceIndicatorVisibility));
+ this._updateWorkspaceIndicatorVisibility();
+
+ this._menuManager = new PopupMenu.PopupMenuManager(this);
+ this._menuManager.addMenu(this._workspaceIndicator.menu);
+
+ Main.layoutManager.addChrome(this.actor, { affectsStruts: true,
+ trackFullscreen: true });
+ Main.uiGroup.set_child_above_sibling(this.actor, Main.layoutManager.panelBox);
+ Main.ctrlAltTabManager.addGroup(this.actor, _("Window List"), 'start-here-symbolic');
+
+ this.actor.width = this._monitor.width;
+ this.actor.connect('notify::height', Lang.bind(this, this._updatePosition));
+ this._updatePosition();
+
+ this._keyboardVisiblechangedId =
+ Main.layoutManager.connect('keyboard-visible-changed',
+ Lang.bind(this, function(o, state) {
+ Main.layoutManager.keyboardBox.visible = state;
+ let keyboardBox = Main.layoutManager.keyboardBox;
+ keyboardBox.visible = state;
+ if (state)
+ Main.uiGroup.set_child_above_sibling(this.actor, keyboardBox);
+ else
+ Main.uiGroup.set_child_above_sibling(this.actor,
+ Main.layoutManager.panelBox);
+ this._updateKeyboardAnchor();
+ }));
+
+ this._overviewShowingId =
+ Main.overview.connect('showing', Lang.bind(this, function() {
+ this.actor.hide();
+ this._updateKeyboardAnchor();
+ }));
+
+ this._overviewHidingId =
+ Main.overview.connect('hiding', Lang.bind(this, function() {
+ this.actor.visible = !Main.layoutManager.primaryMonitor.inFullscreen;
+ this._updateKeyboardAnchor();
+ }));
+
+ this._fullscreenChangedId =
+ global.screen.connect('in-fullscreen-changed', Lang.bind(this, function() {
+ this._updateKeyboardAnchor();
+ }));
+
+ this._dragBeginId =
+ Main.xdndHandler.connect('drag-begin',
+ Lang.bind(this, this._onDragBegin));
+ this._dragEndId =
+ Main.xdndHandler.connect('drag-end',
+ Lang.bind(this, this._onDragEnd));
+ this._dragMonitor = {
+ dragMotion: Lang.bind(this, this._onDragMotion)
+ };
+
+ this._dndTimeoutId = 0;
+ this._dndWindow = null;
+ },
+
+ _getWorkspaceSettings: function() {
+ let settings = global.get_overrides_settings();
+ if (settings.list_keys().indexOf('workspaces-only-on-primary') > -1)
+ return settings;
+ return new Gio.Settings({ schema_id: 'org.gnome.mutter' });
+ },
+
+ _updatePosition: function() {
+ this.actor.set_position(this._monitor.x,
+ this._monitor.y + this._monitor.height - this.actor.height);
+ },
+
+ _updateWorkspaceIndicatorVisibility: function() {
+ this._workspaceIndicator.actor.visible =
+ this._monitor == Main.layoutManager.primaryMonitor ||
+ !this._workspaceSettings.get_boolean('workspaces-only-on-primary');
+ },
+
+
+ _updateKeyboardAnchor: function() {
+ if (!Main.keyboard.actor)
+ return;
+
+ let anchorY = Main.overview.visible ? 0 : this.actor.height;
+ Main.keyboard.actor.anchor_y = anchorY;
+ },
+
_onDragBegin: function() {
DND.addDragMonitor(this._dragMonitor);
},
@@ -1199,22 +1309,11 @@ const WindowList = new Lang.Class({
Main.ctrlAltTabManager.removeGroup(this.actor);
- this._appSystem.disconnect(this._appStateChangedId);
- this._appStateChangedId = 0;
-
Main.layoutManager.disconnect(this._keyboardVisiblechangedId);
this._keyboardVisiblechangedId = 0;
Main.layoutManager.hideKeyboard();
- this._disconnectWorkspaceSignals();
- global.screen.disconnect(this._nWorkspacesChangedId);
- this._nWorkspacesChangedId = 0;
-
- global.window_manager.disconnect(this._switchWorkspaceId);
- this._switchWorkspaceId = 0;
-
-
Main.overview.disconnect(this._overviewShowingId);
Main.overview.disconnect(this._overviewHidingId);
@@ -1222,12 +1321,6 @@ const WindowList = new Lang.Class({
Main.xdndHandler.disconnect(this._dragBeginId);
Main.xdndHandler.disconnect(this._dragEndId);
-
- this._settings.disconnect(this._groupingModeChangedId);
-
- let windows = global.get_window_actors();
- for (let i = 0; i < windows.length; i++)
- windows[i].metaWindow.set_icon_geometry(null);
}
});
@@ -1236,7 +1329,6 @@ const Extension = new Lang.Class({
_init: function() {
this._windowLists = null;
- this._injections = {};
},
enable: function() {
@@ -1292,6 +1384,63 @@ const Extension = new Lang.Class({
}
});
+const SCExtension = new Lang.Class({
+ Name: 'SCExtension',
+ _init: function() {
+ this._pureWinList = null;
+ },
+
+ enable: function() {
+ // 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',
+ () => {
+ 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.
+ },
+
+ disable: function() {
+ if (!this._pureWinList)
+ return;
+
+ this._pureWinList.actor.hide();
+ this._pureWinList.actor.destroy();
+
+ this._pureWinList = null;
+ },
+
+ // NOTE: this function is used for multiple window list situations, invalid for SCExtension case, let's return false.
+ someWindowListContains: function(actor) {
+ return false;
+ }
+});
+
function init() {
- return new Extension();
+ if ( SLEClassicExt.isSLEClassicMode() ){
+ return new SCExtension();
+ }
+ else {
+ return new Extension();
+ }
}
Index: gnome-shell-extensions-3.24.2/extensions/window-list/stylesheet.css
===================================================================
--- gnome-shell-extensions-3.24.2.orig/extensions/window-list/stylesheet.css
+++ gnome-shell-extensions-3.24.2/extensions/window-list/stylesheet.css
@@ -79,6 +79,10 @@
border: 1px solid #cccccc;
}
+.bottom-panel-menu {
+ -boxpointer-gap: 4px;
+}
+
.notification {
font-weight: normal;
}