From 6fda26395749bfabab8a86fc517d595f01a4bf4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Hedin=20Br=C3=B8nner?= Date: Wed, 27 Jun 2018 11:48:52 +0200 Subject: [PATCH] Update the minimap through signals from the space A space now emits four signals (supplying these arguments): 1. `select`, which runs on `ensureViewport` 2. `window-added` (metaWindow, index, row) 3. `window-removed` (metaWindow, index, row) 4. `monitor-changed`, currently not used The minimap hooks into these signals updating as necessary. This is a lot cleaner and goes a long way untangling the minimap from the navigator. One nice effect is proper support of adding and removing windows when the minimap is active. It also works better on wayland as there's less reliance on synchronous updates. --- minimap.js | 68 ++++++++++++++++++++++++++++++++++++++++------------ navigator.js | 10 +------- tiling.js | 6 ++++- 3 files changed, 59 insertions(+), 25 deletions(-) diff --git a/minimap.js b/minimap.js index de71c3c..11cbcca 100644 --- a/minimap.js +++ b/minimap.js @@ -25,8 +25,9 @@ var WindowCloneLayout = new Lang.Class({ Name: 'PaperWindowCloneLayout', Extends: Clutter.LayoutManager, - _init: function() { + _init: function(minimap) { this.parent(); + this.minimap = minimap; }, _makeBoxForWindow: function(window) { @@ -71,6 +72,7 @@ var WindowCloneLayout = new Lang.Class({ child.allocate(this._makeBoxForWindow(realWindow.meta_window), flags); + this.minimap.layout(); } }); @@ -102,6 +104,32 @@ class Minimap { clip.add_actor(container); clip.set_position(12 + prefs.window_gap, 15 + 10); highlight.y = clip.y - 10; + this.signals = [ + space.connect('select', this.select.bind(this)), + space.connect('window-added', this.addWindow.bind(this)), + space.connect('window-removed', this.removeWindow.bind(this)), + ]; + } + + addWindow(space, metaWindow, index, row) { + let clone = this.createClone(metaWindow); + if (row !== undefined && this.clones[index]) { + let column = this.clones[index]; + column.splice(row, 0, clone); + } else { + row = row || 0; + this.clones.splice(index, 0, [clone]); + } + this.container.add_actor(clone); + } + + removeWindow(space, metaWindow, index, row) { + let clone = this.clones[index][row]; + let column = this.clones[index]; + column.splice(row, 1); + if (column.length === 0) + this.clones.splice(index, 1); + this.container.remove_child(clone); } show() { @@ -111,19 +139,21 @@ class Minimap { } createClones() { - return this.space.map(column => column.map((mw) => { - let windowActor = mw.get_compositor_private(); - let clone = new Clutter.Clone({ source: windowActor }); - let container = new Clutter.Actor({ - layout_manager: new WindowCloneLayout(), - name: "window-clone-container" - }); - clone.meta_window = mw; - container.meta_window = mw; - container.add_actor(clone); + return this.space.map(column => + column.map(this.createClone.bind(this))); + } - return container; - })); + createClone(mw) { + let windowActor = mw.get_compositor_private(); + let clone = new Clutter.Clone({ source: windowActor }); + let container = new Clutter.Actor({ + layout_manager: new WindowCloneLayout(this), + name: "window-clone-container" + }); + clone.meta_window = mw; + container.meta_window = mw; + container.add_actor(clone); + return container; } layout(animate = true) { @@ -149,6 +179,7 @@ class Minimap { this.actor.width = this.clip.width + this.clip.x*2; this.clip.set_clip(0, 0, this.clip.width, this.clip.height); this.label.set_style(`max-width: ${this.clip.width}px;`); + this.select(); } restack() { @@ -175,12 +206,14 @@ class Minimap { } select() { + let position = this.space.positionOf(); + if (!position) + return; + let [index, row] = position; let clip = this.clip; let container = this.container; let highlight = this.highlight; let label = this.label; - let index = this.space.selectedIndex(); - let row = this.space[index].indexOf(this.space.selectedWindow); let selected = this.clones[index][row]; if (!selected) return; @@ -225,4 +258,9 @@ class Minimap { this.actor.height = this.label.y + this.label.height + 12; } + + destroy() { + this.actor.destroy(); + this.signals.forEach(id => this.space.disconnect(id)); + } } diff --git a/navigator.js b/navigator.js index f3249ed..8370a72 100644 --- a/navigator.js +++ b/navigator.js @@ -192,7 +192,6 @@ var PreviewedWindowNavigator = new Lang.Class({ swapArray(column, row, targetRow); this.minimap.show(); Tiling.ensureViewport(metaWindow, space, true); - this.minimap.select(); }, _initSpaceMru(move) { @@ -409,11 +408,6 @@ var PreviewedWindowNavigator = new Lang.Class({ && action.name !== 'toggle-scratch') { let metaWindow = this.space.selectedWindow; action.handler(null, null, metaWindow); - this.windows = this.space.getWindows(); - this._selectedIndex = this.windows.indexOf(this.space.selectedWindow); - let minimap = this.minimap; - minimap.show(); - minimap.select(); return true; } } @@ -475,8 +469,6 @@ var PreviewedWindowNavigator = new Lang.Class({ if (metaWindow) { Tiling.ensureViewport(metaWindow, this.space); } - if (!workspaceMru) - this.minimap.select(); }, _finish: function(timestamp) { @@ -497,7 +489,7 @@ var PreviewedWindowNavigator = new Lang.Class({ destroy: function() { debug('#preview', 'destroy', this.space.actor); - this.minimap.actor.destroy(); + this.minimap.destroy(); if (Main.panel.statusArea.appMenu) Main.panel.statusArea.appMenu.container.show(); diff --git a/tiling.js b/tiling.js index 0647ef5..773857d 100644 --- a/tiling.js +++ b/tiling.js @@ -161,10 +161,10 @@ class Space extends Array { let column = this[index]; column.splice(row, 0, metaWindow); } else { - row = row || 0; this.splice(index, 0, [metaWindow]); } metaWindow.clone.reparent(this.cloneContainer); + this.emit('window-added', metaWindow, index, row); } removeWindow(metaWindow) { @@ -188,6 +188,7 @@ class Space extends Array { Tweener.removeTweens(this.selection); this.selection.width = 0; this.visible = []; + this.emit('window-removed', metaWindow, index, row); return true; } @@ -264,6 +265,8 @@ class Space extends Array { cloneContainer.set_size(monitor.width, monitor.height); cloneContainer.set_clip(-Math.round(prefs.window_gap/2), 0, monitor.width + prefs.window_gap, monitor.height); + + this.emit('monitor-changed'); } /** @@ -1100,6 +1103,7 @@ function ensureViewport(meta_window, space, force) { }, }); } + space.emit('select'); updateSelection(space, noAnimate); }