2011-09-28 13:16:26 +00:00
|
|
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
2010-02-12 22:52:15 +00:00
|
|
|
|
|
|
|
const Clutter = imports.gi.Clutter;
|
|
|
|
const Lang = imports.lang;
|
|
|
|
const Mainloop = imports.mainloop;
|
2012-04-14 12:40:30 +00:00
|
|
|
const Meta = imports.gi.Meta;
|
2010-02-12 22:52:15 +00:00
|
|
|
const Shell = imports.gi.Shell;
|
2012-06-27 19:13:32 +00:00
|
|
|
const Signals = imports.signals;
|
2010-02-12 22:52:15 +00:00
|
|
|
const St = imports.gi.St;
|
|
|
|
|
2012-04-14 12:40:30 +00:00
|
|
|
const Main = imports.ui.main;
|
2010-02-12 22:52:15 +00:00
|
|
|
const Tweener = imports.ui.tweener;
|
|
|
|
|
2010-06-10 15:22:23 +00:00
|
|
|
const ANIMATION_TIME = 0.1;
|
2010-02-12 22:52:15 +00:00
|
|
|
const DISPLAY_TIMEOUT = 600;
|
|
|
|
|
2011-11-20 17:56:27 +00:00
|
|
|
const WorkspaceSwitcherPopup = new Lang.Class({
|
|
|
|
Name: 'WorkspaceSwitcherPopup',
|
2010-02-12 22:52:15 +00:00
|
|
|
|
|
|
|
_init : function() {
|
2012-02-14 16:33:26 +00:00
|
|
|
this.actor = new St.Widget({ reactive: true,
|
|
|
|
x: 0,
|
|
|
|
y: 0,
|
|
|
|
width: global.screen_width,
|
|
|
|
height: global.screen_height,
|
|
|
|
style_class: 'workspace-switcher-group' });
|
2010-05-06 21:18:10 +00:00
|
|
|
Main.uiGroup.add_actor(this.actor);
|
2010-02-12 22:52:15 +00:00
|
|
|
|
2010-05-13 19:46:04 +00:00
|
|
|
this._container = new St.BoxLayout({ style_class: 'workspace-switcher-container' });
|
2010-06-09 17:09:48 +00:00
|
|
|
this._list = new Shell.GenericContainer({ style_class: 'workspace-switcher' });
|
|
|
|
this._itemSpacing = 0;
|
2011-02-09 15:00:29 +00:00
|
|
|
this._childHeight = 0;
|
|
|
|
this._childWidth = 0;
|
2010-06-09 17:09:48 +00:00
|
|
|
this._list.connect('style-changed', Lang.bind(this, function() {
|
StThemeNode: simplify use of get_color/get_double/get_length
Although within St itself there are situations where the semantics of
these functions (return TRUE or FALSE and return the actual value in
an out parameter) is useful, it's mostly just annoying at the
application level, where you generally know that the CSS property is
going to specified, and there is no especially sane fallback if it's
not.
So rename the current methods to lookup_color, lookup_double, and
lookup_length, and add new get_color, get_double, and get_length
methods that don't take an "inherit" parameter, and return their
values directly. (Well, except for get_color, due to the lack of (out
caller-allocates) in gjs.)
And update the code to use either the old or new methods as appropriate.
https://bugzilla.gnome.org/show_bug.cgi?id=632590
2010-09-26 21:38:36 +00:00
|
|
|
this._itemSpacing = this._list.get_theme_node().get_length('spacing');
|
2010-06-09 17:09:48 +00:00
|
|
|
}));
|
|
|
|
|
|
|
|
this._list.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
|
|
|
this._list.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
|
|
|
this._list.connect('allocate', Lang.bind(this, this._allocate));
|
2010-02-12 22:52:15 +00:00
|
|
|
this._container.add(this._list);
|
2010-02-16 21:34:57 +00:00
|
|
|
|
2010-02-12 22:52:15 +00:00
|
|
|
this.actor.add_actor(this._container);
|
|
|
|
|
2012-06-27 19:13:32 +00:00
|
|
|
this._redisplay();
|
2010-02-12 22:52:15 +00:00
|
|
|
|
2011-02-09 22:57:23 +00:00
|
|
|
this.actor.hide();
|
|
|
|
|
2012-06-27 19:13:32 +00:00
|
|
|
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)));
|
|
|
|
|
2010-02-12 22:52:15 +00:00
|
|
|
this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout));
|
|
|
|
},
|
|
|
|
|
2011-02-09 15:00:29 +00:00
|
|
|
_getPreferredHeight : function (actor, forWidth, alloc) {
|
2010-06-09 17:09:48 +00:00
|
|
|
let children = this._list.get_children();
|
2013-01-28 05:09:12 +00:00
|
|
|
let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
|
2010-06-09 17:09:48 +00:00
|
|
|
|
2013-01-28 05:09:12 +00:00
|
|
|
let availHeight = workArea.height;
|
2011-02-09 15:00:29 +00:00
|
|
|
availHeight -= this.actor.get_theme_node().get_vertical_padding();
|
|
|
|
availHeight -= this._container.get_theme_node().get_vertical_padding();
|
|
|
|
availHeight -= this._list.get_theme_node().get_vertical_padding();
|
2010-06-09 17:09:48 +00:00
|
|
|
|
2011-02-09 15:00:29 +00:00
|
|
|
let height = 0;
|
2010-06-09 17:09:48 +00:00
|
|
|
for (let i = 0; i < children.length; i++) {
|
2011-02-09 15:00:29 +00:00
|
|
|
let [childMinHeight, childNaturalHeight] = children[i].get_preferred_height(-1);
|
|
|
|
let [childMinWidth, childNaturalWidth] = children[i].get_preferred_width(childNaturalHeight);
|
2013-01-28 05:09:12 +00:00
|
|
|
height += childNaturalHeight * workArea.width / workArea.height;
|
2010-06-09 17:09:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let spacing = this._itemSpacing * (global.screen.n_workspaces - 1);
|
2011-02-09 15:00:29 +00:00
|
|
|
height += spacing;
|
|
|
|
height = Math.min(height, availHeight);
|
2010-06-09 17:09:48 +00:00
|
|
|
|
2011-02-09 15:00:29 +00:00
|
|
|
this._childHeight = (height - spacing) / global.screen.n_workspaces;
|
2010-06-09 17:09:48 +00:00
|
|
|
|
2011-02-09 15:00:29 +00:00
|
|
|
alloc.min_size = height;
|
|
|
|
alloc.natural_size = height;
|
2010-06-09 17:09:48 +00:00
|
|
|
},
|
|
|
|
|
2011-02-09 15:00:29 +00:00
|
|
|
_getPreferredWidth : function (actor, forHeight, alloc) {
|
2013-01-28 05:09:12 +00:00
|
|
|
let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
|
|
|
|
this._childWidth = Math.round(this._childHeight * workArea.width / workArea.height);
|
2010-06-09 17:09:48 +00:00
|
|
|
|
2011-02-09 15:00:29 +00:00
|
|
|
alloc.min_size = this._childWidth;
|
|
|
|
alloc.natural_size = this._childWidth;
|
2010-06-09 17:09:48 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_allocate : function (actor, box, flags) {
|
|
|
|
let children = this._list.get_children();
|
|
|
|
let childBox = new Clutter.ActorBox();
|
|
|
|
|
2011-02-09 15:00:29 +00:00
|
|
|
let y = box.y1;
|
|
|
|
let prevChildBoxY2 = box.y1 - this._itemSpacing;
|
2010-06-09 17:09:48 +00:00
|
|
|
for (let i = 0; i < children.length; i++) {
|
2011-02-09 15:00:29 +00:00
|
|
|
childBox.x1 = box.x1;
|
|
|
|
childBox.x2 = box.x1 + this._childWidth;
|
|
|
|
childBox.y1 = prevChildBoxY2 + this._itemSpacing;
|
|
|
|
childBox.y2 = Math.round(y + this._childHeight);
|
|
|
|
y += this._childHeight + this._itemSpacing;
|
|
|
|
prevChildBoxY2 = childBox.y2;
|
2010-06-09 17:09:48 +00:00
|
|
|
children[i].allocate(childBox, flags);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2012-06-27 19:13:32 +00:00
|
|
|
_redisplay: function() {
|
2012-02-16 18:27:09 +00:00
|
|
|
this._list.destroy_all_children();
|
2010-02-12 22:52:15 +00:00
|
|
|
|
|
|
|
for (let i = 0; i < global.screen.n_workspaces; i++) {
|
|
|
|
let indicator = null;
|
|
|
|
|
2012-06-27 19:13:32 +00:00
|
|
|
if (i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.UP)
|
2011-02-09 15:00:29 +00:00
|
|
|
indicator = new St.Bin({ style_class: 'ws-switcher-active-up' });
|
2012-06-27 19:13:32 +00:00
|
|
|
else if(i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.DOWN)
|
2011-02-09 15:00:29 +00:00
|
|
|
indicator = new St.Bin({ style_class: 'ws-switcher-active-down' });
|
2010-02-12 22:52:15 +00:00
|
|
|
else
|
|
|
|
indicator = new St.Bin({ style_class: 'ws-switcher-box' });
|
|
|
|
|
2010-06-09 17:09:48 +00:00
|
|
|
this._list.add_actor(indicator);
|
2010-02-12 22:52:15 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-01-28 05:09:12 +00:00
|
|
|
let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
|
2012-06-27 19:13:32 +00:00
|
|
|
let [containerMinHeight, containerNatHeight] = this._container.get_preferred_height(global.screen_width);
|
|
|
|
let [containerMinWidth, containerNatWidth] = this._container.get_preferred_width(containerNatHeight);
|
2013-01-28 05:09:12 +00:00
|
|
|
this._container.x = workArea.x + Math.floor((workArea.width - containerNatWidth) / 2);
|
|
|
|
this._container.y = workArea.y + Math.floor((workArea.height - containerNatHeight) / 2);
|
2010-02-12 22:52:15 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_show : function() {
|
|
|
|
Tweener.addTween(this._container, { opacity: 255,
|
|
|
|
time: ANIMATION_TIME,
|
2010-05-13 19:46:04 +00:00
|
|
|
transition: 'easeOutQuad'
|
2010-02-12 22:52:15 +00:00
|
|
|
});
|
|
|
|
this.actor.show();
|
|
|
|
},
|
|
|
|
|
|
|
|
display : function(direction, activeWorkspaceIndex) {
|
2012-06-27 19:13:32 +00:00
|
|
|
this._direction = direction;
|
|
|
|
this._activeWorkspaceIndex = activeWorkspaceIndex;
|
|
|
|
|
|
|
|
this._redisplay();
|
2010-02-12 22:52:15 +00:00
|
|
|
if (this._timeoutId != 0)
|
|
|
|
Mainloop.source_remove(this._timeoutId);
|
|
|
|
this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout));
|
|
|
|
this._show();
|
|
|
|
},
|
|
|
|
|
|
|
|
_onTimeout : function() {
|
|
|
|
Mainloop.source_remove(this._timeoutId);
|
|
|
|
this._timeoutId = 0;
|
|
|
|
Tweener.addTween(this._container, { opacity: 0.0,
|
|
|
|
time: ANIMATION_TIME,
|
2010-05-13 19:46:04 +00:00
|
|
|
transition: 'easeOutQuad',
|
2012-06-27 19:13:32 +00:00
|
|
|
onComplete: function() { this.destroy(); },
|
2010-02-12 22:52:15 +00:00
|
|
|
onCompleteScope: this
|
|
|
|
});
|
2012-06-27 19:13:32 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
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');
|
2010-02-12 22:52:15 +00:00
|
|
|
}
|
2011-11-20 17:56:27 +00:00
|
|
|
});
|
2012-06-27 19:13:32 +00:00
|
|
|
Signals.addSignalMethods(WorkspaceSwitcherPopup.prototype);
|