Skip to content

Commit 6eb3f73

Browse files
authored
Merge pull request #44 from mzur/workspace-overview
Workspace overview
2 parents 78da901 + c8cc4cc commit 6eb3f73

7 files changed

+244
-56
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ This is a clone of the [Workspace Grid](https://github.com/zakkak/workspace-grid
1616
- Configurable timeout of the workspace switcher popup.
1717
- Two wraparound modes for navigating workspaces (optional).
1818
- Workspace labels in the workspace switcher popup (optional).
19+
- Workspace overview on <kbd>Super</kbd>+<kbd>W</kbd>.
1920

2021
## Installation
2122

[email protected]/BaseWorkspaceSwitcherPopup.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,14 @@ class BaseWorkspaceSwitcherPopup extends WorkspaceSwitcherPopup {
1212
display(direction, activeWorkspaceIndex) {
1313
super.display(direction, activeWorkspaceIndex);
1414

15-
Mainloop.source_remove(this._timeoutId);
16-
this._timeoutId = Mainloop.timeout_add(this._popupTimeout, this._onTimeout.bind(this));
17-
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._onTimeout');
15+
if (this._timeoutId !== 0) {
16+
Mainloop.source_remove(this._timeoutId);
17+
this._timeoutId = 0;
18+
}
19+
20+
if (this._popupTimeout > 0) {
21+
this._timeoutId = Mainloop.timeout_add(this._popupTimeout, this._onTimeout.bind(this));
22+
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._onTimeout');
23+
}
1824
}
1925
});

[email protected]/WmOverride.js

Lines changed: 185 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ const WraparoundMode = {
1414
};
1515

1616
var WmOverride = class {
17-
constructor(settings) {
17+
constructor(settings, keybindings) {
1818
this.wm = Main.wm;
1919
this.settings = settings;
2020
this._mutterSettings = new Gio.Settings({ schema_id: 'org.gnome.mutter' });
2121
this.wsManager = DisplayWrapper.getWorkspaceManager();
2222
this.originalDynamicWorkspaces = this._mutterSettings.get_boolean('dynamic-workspaces');
2323
this.originalAllowedKeybindings = {};
24+
this._keybindings = keybindings;
2425

2526
this._overrideDynamicWorkspaces();
2627
this._overrideKeybindingHandlers();
@@ -33,6 +34,8 @@ var WmOverride = class {
3334
this._handleWraparoundModeChanged();
3435
this._connectSettings();
3536
this._notify();
37+
this._addKeybindings();
38+
this._connectOverview();
3639
}
3740

3841
destroy() {
@@ -42,6 +45,8 @@ var WmOverride = class {
4245
this._restoreLayout();
4346
this._restoreDynamicWorkspaces();
4447
this._notify();
48+
this._removeKeybindings();
49+
this._disconnectOverview();
4550
}
4651

4752
_connectSettings() {
@@ -97,6 +102,81 @@ var WmOverride = class {
97102
this.settings.disconnect(this.settingsHandlerCachePopup);
98103
}
99104

105+
_connectOverview() {
106+
this.overviewHandlerShown = Main.overview.connect(
107+
'showing',
108+
this._destroyWorkspaceSwitcherPopup.bind(this)
109+
);
110+
}
111+
112+
_disconnectOverview() {
113+
Main.overview.disconnect(this.overviewHandlerShown);
114+
}
115+
116+
_addKeybindings() {
117+
this.wm.addKeybinding(
118+
'workspace-overview-toggle',
119+
this._keybindings,
120+
Meta.KeyBindingFlags.NONE,
121+
Shell.ActionMode.NORMAL,
122+
this._toggleWorkspaceOverview.bind(this)
123+
);
124+
}
125+
126+
_removeKeybindings() {
127+
this.wm.removeKeybinding('workspace-overview-toggle');
128+
}
129+
130+
_addWsOverviewKeybindings(keybindings) {
131+
this.wm.addKeybinding(
132+
'workspace-overview-right',
133+
this._keybindings,
134+
Meta.KeyBindingFlags.NONE,
135+
Shell.ActionMode.NORMAL,
136+
this._workspaceOverviewMoveRight.bind(this)
137+
);
138+
139+
this.wm.addKeybinding(
140+
'workspace-overview-left',
141+
this._keybindings,
142+
Meta.KeyBindingFlags.NONE,
143+
Shell.ActionMode.NORMAL,
144+
this._workspaceOverviewMoveLeft.bind(this)
145+
);
146+
147+
this.wm.addKeybinding(
148+
'workspace-overview-up',
149+
this._keybindings,
150+
Meta.KeyBindingFlags.NONE,
151+
Shell.ActionMode.NORMAL,
152+
this._workspaceOverviewMoveUp.bind(this)
153+
);
154+
155+
this.wm.addKeybinding(
156+
'workspace-overview-down',
157+
this._keybindings,
158+
Meta.KeyBindingFlags.NONE,
159+
Shell.ActionMode.NORMAL,
160+
this._workspaceOverviewMoveDown.bind(this)
161+
);
162+
163+
this.wm.addKeybinding(
164+
'workspace-overview-confirm',
165+
this._keybindings,
166+
Meta.KeyBindingFlags.NONE,
167+
Shell.ActionMode.NORMAL,
168+
this._workspaceOverviewConfirm.bind(this)
169+
);
170+
}
171+
172+
_removeWsOverviewKeybindings() {
173+
this.wm.removeKeybinding('workspace-overview-right');
174+
this.wm.removeKeybinding('workspace-overview-left');
175+
this.wm.removeKeybinding('workspace-overview-up');
176+
this.wm.removeKeybinding('workspace-overview-down');
177+
this.wm.removeKeybinding('workspace-overview-confirm');
178+
}
179+
100180
_handleNumberOfWorkspacesChanged() {
101181
this.rows = this.settings.get_int('num-rows');
102182
this.columns = this.settings.get_int('num-columns');
@@ -250,39 +330,7 @@ var WmOverride = class {
250330
}
251331

252332
direction = Meta.MotionDirection[target.toUpperCase()];
253-
newWs = workspaceManager.get_active_workspace().get_neighbor(direction);
254-
255-
let currentIndex = workspaceManager.get_active_workspace_index();
256-
if (this.wraparoundMode !== WraparoundMode.NONE && currentIndex === newWs.index()) {
257-
// Given a direction input the workspace has not changed, so do wraparound.
258-
let targetRow = Math.floor(currentIndex / this.columns);
259-
let targetColumn = currentIndex % this.columns;
260-
261-
let offset = 0;
262-
if (direction === Meta.MotionDirection.UP || direction === Meta.MotionDirection.LEFT) {
263-
offset = -1;
264-
} else if (direction === Meta.MotionDirection.DOWN || direction === Meta.MotionDirection.RIGHT) {
265-
offset = 1;
266-
}
267-
268-
if (this.wraparoundMode === WraparoundMode.NEXT_PREV) {
269-
targetRow += offset;
270-
targetColumn += offset;
271-
} else if (this.wraparoundMode === WraparoundMode.ROW_COL) {
272-
if (direction === Meta.MotionDirection.UP || direction === Meta.MotionDirection.DOWN) {
273-
targetRow += offset;
274-
} else if (direction === Meta.MotionDirection.LEFT || direction === Meta.MotionDirection.RIGHT) {
275-
targetColumn += offset;
276-
}
277-
}
278-
279-
// Handle negative targets.
280-
targetColumn = (targetColumn + this.columns) % this.columns;
281-
targetRow = (targetRow + this.rows) % this.rows;
282-
283-
target = targetRow * this.columns + targetColumn;
284-
newWs = workspaceManager.get_workspace_by_index(target);
285-
}
333+
newWs = this._getTargetWorkspace(direction);
286334
} else if (target > 0) {
287335
target--;
288336
newWs = workspaceManager.get_workspace_by_index(target);
@@ -301,22 +349,7 @@ var WmOverride = class {
301349
if (!Main.overview.visible && this.popupTimeout > 0) {
302350
if (this.wm._workspaceSwitcherPopup == null) {
303351
this.wm._workspaceTracker.blockUpdates();
304-
if (this.showThumbnails) {
305-
this.wm._workspaceSwitcherPopup = new ThumbnailWsmatrixPopup(
306-
this.rows,
307-
this.columns,
308-
this.scale,
309-
this.popupTimeout,
310-
this.cachePopup
311-
);
312-
} else {
313-
this.wm._workspaceSwitcherPopup = new IndicatorWsmatrixPopup(
314-
this.rows,
315-
this.columns,
316-
this.popupTimeout,
317-
this.showWorkspaceNames
318-
);
319-
}
352+
this.wm._workspaceSwitcherPopup = this._createNewPopup();
320353
this.wm._workspaceSwitcherPopup.connect('destroy', () => {
321354
this.wm._workspaceTracker.unblockUpdates();
322355
this.wm._workspaceSwitcherPopup = null;
@@ -336,4 +369,106 @@ var WmOverride = class {
336369
}
337370
}
338371
}
372+
373+
_getTargetWorkspace(direction) {
374+
let newWs = this.wsManager.get_active_workspace().get_neighbor(direction);
375+
let currentIndex = this.wsManager.get_active_workspace_index();
376+
if (this.wraparoundMode !== WraparoundMode.NONE && currentIndex === newWs.index()) {
377+
// Given a direction input the workspace has not changed, so do wraparound.
378+
let targetRow = Math.floor(currentIndex / this.columns);
379+
let targetColumn = currentIndex % this.columns;
380+
381+
let offset = 0;
382+
if (direction === Meta.MotionDirection.UP || direction === Meta.MotionDirection.LEFT) {
383+
offset = -1;
384+
} else if (direction === Meta.MotionDirection.DOWN || direction === Meta.MotionDirection.RIGHT) {
385+
offset = 1;
386+
}
387+
388+
if (this.wraparoundMode === WraparoundMode.NEXT_PREV) {
389+
targetRow += offset;
390+
targetColumn += offset;
391+
} else if (this.wraparoundMode === WraparoundMode.ROW_COL) {
392+
if (direction === Meta.MotionDirection.UP || direction === Meta.MotionDirection.DOWN) {
393+
targetRow += offset;
394+
} else if (direction === Meta.MotionDirection.LEFT || direction === Meta.MotionDirection.RIGHT) {
395+
targetColumn += offset;
396+
}
397+
}
398+
399+
// Handle negative targets.
400+
targetColumn = (targetColumn + this.columns) % this.columns;
401+
targetRow = (targetRow + this.rows) % this.rows;
402+
403+
target = targetRow * this.columns + targetColumn;
404+
newWs = this.wsManager.get_workspace_by_index(target);
405+
}
406+
407+
return newWs;
408+
}
409+
410+
_createNewPopup(timeout) {
411+
timeout = timeout === undefined ? this.popupTimeout : timeout;
412+
413+
if (this.showThumbnails) {
414+
return new ThumbnailWsmatrixPopup(
415+
this.rows,
416+
this.columns,
417+
this.scale,
418+
timeout,
419+
this.cachePopup
420+
);
421+
}
422+
423+
return new IndicatorWsmatrixPopup(
424+
this.rows,
425+
this.columns,
426+
timeout,
427+
this.showWorkspaceNames
428+
);
429+
}
430+
431+
_toggleWorkspaceOverview() {
432+
if (this.wm._workspaceSwitcherPopup === null) {
433+
this.wm._workspaceSwitcherPopup = this._createNewPopup(0);
434+
this.wm._workspaceSwitcherPopup.connect('destroy', () => {
435+
this.wm._workspaceTracker.unblockUpdates();
436+
this.wm._workspaceSwitcherPopup = null;
437+
this.wm._isWorkspacePrepended = false;
438+
this._removeWsOverviewKeybindings();
439+
});
440+
this.wm._workspaceSwitcherPopup.display(null, this.wsManager.get_active_workspace_index());
441+
this._addWsOverviewKeybindings();
442+
} else {
443+
this._destroyWorkspaceSwitcherPopup();
444+
}
445+
}
446+
447+
_moveToWorkspace(direction) {
448+
let workspace = this._getTargetWorkspace(direction);
449+
this.wm.actionMoveWorkspace(workspace);
450+
if (this.wm._workspaceSwitcherPopup) {
451+
this.wm._workspaceSwitcherPopup.display(direction, workspace.index());
452+
}
453+
}
454+
455+
_workspaceOverviewMoveRight() {
456+
this._moveToWorkspace(Meta.MotionDirection.RIGHT);
457+
}
458+
459+
_workspaceOverviewMoveLeft() {
460+
this._moveToWorkspace(Meta.MotionDirection.LEFT);
461+
}
462+
463+
_workspaceOverviewMoveUp() {
464+
this._moveToWorkspace(Meta.MotionDirection.UP);
465+
}
466+
467+
_workspaceOverviewMoveDown() {
468+
this._moveToWorkspace(Meta.MotionDirection.DOWN);
469+
}
470+
471+
_workspaceOverviewConfirm() {
472+
this._destroyWorkspaceSwitcherPopup();
473+
}
339474
}

[email protected]/extension.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ const WmOverride = WsMatrix.imports.WmOverride.WmOverride;
77
class WsMatrixExtension {
88
constructor() {
99
let settings = new Settings(WsMatrix.metadata['settings-schema']);
10-
this.override = new WmOverride(settings);
10+
let keybindings = new Settings(WsMatrix.metadata['keybindings-schema']);
11+
this.override = new WmOverride(settings, keybindings);
1112
}
1213
destroy() {
1314
this.override.destroy();

[email protected]/metadata.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
"shell-version": ["3.32"],
44
"uuid": "[email protected]",
55
"url": "https://github.com/mzur/gnome-shell-wsmatrix",
6-
"settings-schema": "org.gnome.shell.extensions.wsmatrix",
6+
"settings-schema": "org.gnome.shell.extensions.wsmatrix-settings",
7+
"keybindings-schema": "org.gnome.shell.extensions.wsmatrix-keybindings",
78
"gettext-domain": "wsmatrix",
89
"version": -1,
910
"name": "Workspace Matrix",
636 Bytes
Binary file not shown.

[email protected]/schemas/org.gnome.shell.extensions.wsmatrix.gschema.xml

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<value value='1' nick='next-previous'/>
55
<value value='2' nick='rows-columns'/>
66
</enum>
7-
<schema id="org.gnome.shell.extensions.wsmatrix" path="/org/gnome/shell/extensions/wsmatrix/">
7+
<schema id="org.gnome.shell.extensions.wsmatrix-settings" path="/org/gnome/shell/extensions/wsmatrix/">
88
<key type="i" name="num-columns">
99
<default>3</default>
1010
<range min="1" max="36" />
@@ -42,4 +42,48 @@
4242
<summary>Wraparound workspaces while navigating</summary>
4343
</key>
4444
</schema>
45+
<schema id="org.gnome.shell.extensions.wsmatrix-keybindings" path="/org/gnome/shell/extensions/wsmatrix/">
46+
<key name="workspace-overview-toggle" type="as">
47+
<default>["&lt;Super&gt;w"]</default>
48+
<summary>Keybinding to open the workspace overview</summary>
49+
<description>
50+
Keybinding to open the workspace overview.
51+
</description>
52+
</key>
53+
<key name="workspace-overview-right" type="as">
54+
<default>["Right"]</default>
55+
<summary>Keybinding to move to the right in the workspace overview</summary>
56+
<description>
57+
Keybinding to move to the right in the workspace overview
58+
</description>
59+
</key>
60+
<key name="workspace-overview-left" type="as">
61+
<default>["Left"]</default>
62+
<summary>Keybinding to move to the left in the workspace overview</summary>
63+
<description>
64+
Keybinding to move to the left in the workspace overview
65+
</description>
66+
</key>
67+
<key name="workspace-overview-up" type="as">
68+
<default>["Up"]</default>
69+
<summary>Keybinding to move up in the workspace overview</summary>
70+
<description>
71+
Keybinding to move up in the workspace overview
72+
</description>
73+
</key>
74+
<key name="workspace-overview-down" type="as">
75+
<default>["Down"]</default>
76+
<summary>Keybinding to move down in the workspace overview</summary>
77+
<description>
78+
Keybinding to move down in the workspace overview
79+
</description>
80+
</key>
81+
<key name="workspace-overview-confirm" type="as">
82+
<default>["Return","Escape"]</default>
83+
<summary>Keybinding to confirm and close the workspace overview</summary>
84+
<description>
85+
Keybinding to confirm and close the workspace overview
86+
</description>
87+
</key>
88+
</schema>
4589
</schemalist>

0 commit comments

Comments
 (0)