WorkspaceSwitcherPopup: fix for dynamic workspace changes

Changing the number of workspaces while the popup was visible (which
happens when moving windows on the last non empty workspace) resulted
in a wrong layout. Fix that, by listening to workspace-added and
workspace-removed signals, and by always requesting an updated size
from the actor.

https://bugzilla.gnome.org/show_bug.cgi?id=679005
This commit is contained in:
Giovanni Campagna 2012-06-27 21:13:32 +02:00
parent be2f1001a5
commit f0e03b5e82
2 changed files with 50 additions and 23 deletions

View File

@ -521,7 +521,7 @@ const WindowManager = new Lang.Class({
_startAppSwitcher : function(display, screen, window, binding) { _startAppSwitcher : function(display, screen, window, binding) {
/* prevent a corner case where both popups show up at once */ /* prevent a corner case where both popups show up at once */
if (this._workspaceSwitcherPopup != null) if (this._workspaceSwitcherPopup != null)
this._workspaceSwitcherPopup.actor.hide(); this._workspaceSwitcherPopup.destroy();
let tabPopup = new AltTab.AltTabPopup(); let tabPopup = new AltTab.AltTabPopup();
@ -545,20 +545,29 @@ const WindowManager = new Lang.Class({
if (screen.n_workspaces == 1) if (screen.n_workspaces == 1)
return; return;
if (this._workspaceSwitcherPopup == null)
this._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
let [action,,,direction] = binding.get_name().split('-'); let [action,,,direction] = binding.get_name().split('-');
let direction = Meta.MotionDirection[direction.toUpperCase()]; let direction = Meta.MotionDirection[direction.toUpperCase()];
let newWs;
if (direction != Meta.MotionDirection.UP && if (direction != Meta.MotionDirection.UP &&
direction != Meta.MotionDirection.DOWN) direction != Meta.MotionDirection.DOWN)
return; return;
if (action == 'switch') if (action == 'switch')
this.actionMoveWorkspace(direction); newWs = this.actionMoveWorkspace(direction);
else else
this.actionMoveWindow(window, direction); newWs = this.actionMoveWindow(window, direction);
if (!Main.overview.visible) {
if (this._workspaceSwitcherPopup == null) {
this._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
this._workspaceSwitcherPopup.connect('destroy', Lang.bind(this, function() {
this._workspaceSwitcherPopup = null;
}));
}
this._workspaceSwitcherPopup.display(direction, newWs.index());
}
}, },
actionMoveWorkspace: function(direction) { actionMoveWorkspace: function(direction) {
@ -567,8 +576,8 @@ const WindowManager = new Lang.Class({
if (activeWorkspace != toActivate) if (activeWorkspace != toActivate)
toActivate.activate(global.get_current_time()); toActivate.activate(global.get_current_time());
if (!Main.overview.visible)
this._workspaceSwitcherPopup.display(direction, toActivate.index()); return toActivate;
}, },
actionMoveWindow: function(window, direction) { actionMoveWindow: function(window, direction) {
@ -586,7 +595,6 @@ const WindowManager = new Lang.Class({
toActivate.activate_with_focus (window, global.get_current_time()); toActivate.activate_with_focus (window, global.get_current_time());
} }
if (!Main.overview.visible) return toActivate;
this._workspaceSwitcherPopup.display(direction, toActivate.index());
}, },
}); });

View File

@ -5,6 +5,7 @@ const Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta; const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St; const St = imports.gi.St;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -41,12 +42,14 @@ const WorkspaceSwitcherPopup = new Lang.Class({
this.actor.add_actor(this._container); this.actor.add_actor(this._container);
this._redraw(); this._redisplay();
this._position();
this.actor.hide(); this.actor.hide();
this._globalSignals = [];
this._globalSignals.push(global.screen.connect('workspace-added', Lang.bind(this, this._redisplay)));
this._globalSignals.push(global.screen.connect('workspace-removed', Lang.bind(this, this._redisplay)));
this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout)); this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout));
}, },
@ -102,15 +105,15 @@ const WorkspaceSwitcherPopup = new Lang.Class({
} }
}, },
_redraw : function(direction, activeWorkspaceIndex) { _redisplay: function() {
this._list.destroy_all_children(); this._list.destroy_all_children();
for (let i = 0; i < global.screen.n_workspaces; i++) { for (let i = 0; i < global.screen.n_workspaces; i++) {
let indicator = null; let indicator = null;
if (i == activeWorkspaceIndex && direction == Meta.MotionDirection.UP) if (i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.UP)
indicator = new St.Bin({ style_class: 'ws-switcher-active-up' }); indicator = new St.Bin({ style_class: 'ws-switcher-active-up' });
else if(i == activeWorkspaceIndex && direction == Meta.MotionDirection.DOWN) else if(i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.DOWN)
indicator = new St.Bin({ style_class: 'ws-switcher-active-down' }); indicator = new St.Bin({ style_class: 'ws-switcher-active-down' });
else else
indicator = new St.Bin({ style_class: 'ws-switcher-box' }); indicator = new St.Bin({ style_class: 'ws-switcher-box' });
@ -118,13 +121,13 @@ const WorkspaceSwitcherPopup = new Lang.Class({
this._list.add_actor(indicator); this._list.add_actor(indicator);
} }
},
_position: function() {
let primary = Main.layoutManager.primaryMonitor; let primary = Main.layoutManager.primaryMonitor;
this._container.x = primary.x + Math.floor((primary.width - this._container.width) / 2); let [containerMinHeight, containerNatHeight] = this._container.get_preferred_height(global.screen_width);
let [containerMinWidth, containerNatWidth] = this._container.get_preferred_width(containerNatHeight);
this._container.x = primary.x + Math.floor((primary.width - containerNatWidth) / 2);
this._container.y = primary.y + Main.panel.actor.height + this._container.y = primary.y + Main.panel.actor.height +
Math.floor(((primary.height - Main.panel.actor.height) - this._container.height) / 2); Math.floor(((primary.height - Main.panel.actor.height) - containerNatHeight) / 2);
}, },
_show : function() { _show : function() {
@ -132,12 +135,14 @@ const WorkspaceSwitcherPopup = new Lang.Class({
time: ANIMATION_TIME, time: ANIMATION_TIME,
transition: 'easeOutQuad' transition: 'easeOutQuad'
}); });
this._position();
this.actor.show(); this.actor.show();
}, },
display : function(direction, activeWorkspaceIndex) { display : function(direction, activeWorkspaceIndex) {
this._redraw(direction, activeWorkspaceIndex); this._direction = direction;
this._activeWorkspaceIndex = activeWorkspaceIndex;
this._redisplay();
if (this._timeoutId != 0) if (this._timeoutId != 0)
Mainloop.source_remove(this._timeoutId); Mainloop.source_remove(this._timeoutId);
this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout)); this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout));
@ -150,8 +155,22 @@ const WorkspaceSwitcherPopup = new Lang.Class({
Tweener.addTween(this._container, { opacity: 0.0, Tweener.addTween(this._container, { opacity: 0.0,
time: ANIMATION_TIME, time: ANIMATION_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
onComplete: function() { this.actor.hide(); }, onComplete: function() { this.destroy(); },
onCompleteScope: this onCompleteScope: this
}); });
},
destroy: function() {
if (this._timeoutId)
Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0;
for (let i = 0; i < this._globalSignals.length; i++)
global.screen.disconnect(this._globalSignals[i]);
this.actor.destroy();
this.emit('destroy');
} }
}); });
Signals.addSignalMethods(WorkspaceSwitcherPopup.prototype);