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.
This commit is contained in:
Tor Hedin Brønner
2018-06-29 13:17:50 +02:00
parent 69decf9f12
commit 6fda263957
3 changed files with 59 additions and 25 deletions
+53 -15
View File
@@ -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));
}
}
+1 -9
View File
@@ -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();
+5 -1
View File
@@ -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);
}