2013-02-14 19:41:38 +00:00
|
|
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
2019-01-31 14:07:06 +00:00
|
|
|
/* exported ControlsManager */
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2019-02-09 03:21:36 +00:00
|
|
|
const { Clutter, GObject, Meta, St } = imports.gi;
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2013-02-25 23:05:45 +00:00
|
|
|
const Dash = imports.ui.dash;
|
2013-02-14 19:41:38 +00:00
|
|
|
const Main = imports.ui.main;
|
2013-02-19 03:35:04 +00:00
|
|
|
const Params = imports.misc.params;
|
2013-02-15 23:25:36 +00:00
|
|
|
const ViewSelector = imports.ui.viewSelector;
|
2013-02-25 23:05:45 +00:00
|
|
|
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2019-08-01 23:13:10 +00:00
|
|
|
var SIDE_CONTROLS_ANIMATION_TIME = 160;
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2013-02-16 01:43:01 +00:00
|
|
|
function getRtlSlideDirection(direction, actor) {
|
2019-08-19 19:38:51 +00:00
|
|
|
let rtl = actor.text_direction == Clutter.TextDirection.RTL;
|
2019-08-20 00:51:42 +00:00
|
|
|
if (rtl) {
|
2019-08-19 19:38:51 +00:00
|
|
|
direction = direction == SlideDirection.LEFT
|
2019-08-19 19:33:15 +00:00
|
|
|
? SlideDirection.RIGHT : SlideDirection.LEFT;
|
2019-08-20 00:51:42 +00:00
|
|
|
}
|
2013-02-16 01:43:01 +00:00
|
|
|
return direction;
|
2019-01-29 01:18:52 +00:00
|
|
|
}
|
2013-02-16 01:43:01 +00:00
|
|
|
|
2017-07-18 17:47:27 +00:00
|
|
|
var SlideDirection = {
|
2013-02-14 19:41:38 +00:00
|
|
|
LEFT: 0,
|
2019-08-20 21:43:54 +00:00
|
|
|
RIGHT: 1,
|
2013-02-14 19:41:38 +00:00
|
|
|
};
|
|
|
|
|
2019-07-25 22:13:19 +00:00
|
|
|
var SlideLayout = GObject.registerClass({
|
|
|
|
Properties: {
|
|
|
|
'slide-x': GObject.ParamSpec.double(
|
|
|
|
'slide-x', 'slide-x', 'slide-x',
|
|
|
|
GObject.ParamFlags.READWRITE,
|
|
|
|
0, 1, 1),
|
|
|
|
'translation-x': GObject.ParamSpec.double(
|
|
|
|
'translation-x', 'translation-x', 'translation-x',
|
|
|
|
GObject.ParamFlags.READWRITE,
|
2019-08-20 21:43:54 +00:00
|
|
|
-Infinity, Infinity, 0),
|
|
|
|
},
|
2019-07-25 22:13:19 +00:00
|
|
|
}, class SlideLayout extends Clutter.FixedLayout {
|
2017-10-31 00:03:21 +00:00
|
|
|
_init(params) {
|
2013-02-14 19:41:38 +00:00
|
|
|
this._slideX = 1;
|
2019-07-25 22:13:19 +00:00
|
|
|
this._translationX = 0;
|
2013-02-14 19:41:38 +00:00
|
|
|
this._direction = SlideDirection.LEFT;
|
|
|
|
|
2017-10-31 01:23:39 +00:00
|
|
|
super._init(params);
|
|
|
|
}
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
vfunc_get_preferred_width(container, forHeight) {
|
2013-02-14 19:41:38 +00:00
|
|
|
let child = container.get_first_child();
|
|
|
|
|
|
|
|
let [minWidth, natWidth] = child.get_preferred_width(forHeight);
|
|
|
|
|
|
|
|
minWidth *= this._slideX;
|
|
|
|
natWidth *= this._slideX;
|
|
|
|
|
|
|
|
return [minWidth, natWidth];
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
vfunc_allocate(container, box, flags) {
|
2013-02-14 19:41:38 +00:00
|
|
|
let child = container.get_first_child();
|
|
|
|
|
|
|
|
let availWidth = Math.round(box.x2 - box.x1);
|
|
|
|
let availHeight = Math.round(box.y2 - box.y1);
|
2013-10-12 02:36:49 +00:00
|
|
|
let [, natWidth] = child.get_preferred_width(availHeight);
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2013-09-18 23:48:22 +00:00
|
|
|
// Align the actor inside the clipped box, as the actor's alignment
|
|
|
|
// flags only determine what to do if the allocated box is bigger
|
|
|
|
// than the actor's box.
|
2013-02-16 01:43:01 +00:00
|
|
|
let realDirection = getRtlSlideDirection(this._direction, child);
|
2019-08-19 19:38:51 +00:00
|
|
|
let alignX = realDirection == SlideDirection.LEFT
|
2019-08-19 19:33:15 +00:00
|
|
|
? availWidth - natWidth
|
|
|
|
: availWidth - natWidth * this._slideX;
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2013-09-18 23:42:41 +00:00
|
|
|
let actorBox = new Clutter.ActorBox();
|
2013-09-18 23:59:02 +00:00
|
|
|
actorBox.x1 = box.x1 + alignX + this._translationX;
|
2013-11-03 00:06:29 +00:00
|
|
|
actorBox.x2 = actorBox.x1 + (child.x_expand ? availWidth : natWidth);
|
2013-10-21 21:51:50 +00:00
|
|
|
actorBox.y1 = box.y1;
|
2013-10-12 02:36:49 +00:00
|
|
|
actorBox.y2 = actorBox.y1 + availHeight;
|
2013-02-14 19:41:38 +00:00
|
|
|
|
|
|
|
child.allocate(actorBox, flags);
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2019-07-25 22:13:19 +00:00
|
|
|
// eslint-disable-next-line camelcase
|
|
|
|
set slide_x(value) {
|
|
|
|
if (this._slideX == value)
|
|
|
|
return;
|
2013-02-14 19:41:38 +00:00
|
|
|
this._slideX = value;
|
2019-07-25 22:13:19 +00:00
|
|
|
this.notify('slide-x');
|
2013-02-14 19:41:38 +00:00
|
|
|
this.layout_changed();
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2019-07-25 22:13:19 +00:00
|
|
|
// eslint-disable-next-line camelcase
|
|
|
|
get slide_x() {
|
2013-02-14 19:41:38 +00:00
|
|
|
return this._slideX;
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2013-02-14 19:41:38 +00:00
|
|
|
|
|
|
|
set slideDirection(direction) {
|
|
|
|
this._direction = direction;
|
|
|
|
this.layout_changed();
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2013-02-14 19:41:38 +00:00
|
|
|
|
|
|
|
get slideDirection() {
|
|
|
|
return this._direction;
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2013-09-18 23:59:02 +00:00
|
|
|
|
2019-07-25 22:13:19 +00:00
|
|
|
// eslint-disable-next-line camelcase
|
|
|
|
set translation_x(value) {
|
|
|
|
if (this._translationX == value)
|
|
|
|
return;
|
2013-09-18 23:59:02 +00:00
|
|
|
this._translationX = value;
|
2019-07-25 22:13:19 +00:00
|
|
|
this.notify('translation-x');
|
2013-09-18 23:59:02 +00:00
|
|
|
this.layout_changed();
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2013-09-18 23:59:02 +00:00
|
|
|
|
2019-07-25 22:13:19 +00:00
|
|
|
// eslint-disable-next-line camelcase
|
|
|
|
get translation_x() {
|
2013-09-18 23:59:02 +00:00
|
|
|
return this._translationX;
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2013-02-14 19:41:38 +00:00
|
|
|
});
|
|
|
|
|
2019-07-16 09:24:13 +00:00
|
|
|
var SlidingControl = GObject.registerClass(
|
|
|
|
class SlidingControl extends St.Widget {
|
|
|
|
_init(params) {
|
2013-02-19 03:35:04 +00:00
|
|
|
params = Params.parse(params, { slideDirection: SlideDirection.LEFT });
|
|
|
|
|
2013-02-14 19:41:38 +00:00
|
|
|
this.layout = new SlideLayout();
|
2013-02-19 03:35:04 +00:00
|
|
|
this.layout.slideDirection = params.slideDirection;
|
2019-07-16 09:24:13 +00:00
|
|
|
super._init({
|
|
|
|
layout_manager: this.layout,
|
|
|
|
style_class: 'overview-controls',
|
2019-08-20 21:43:54 +00:00
|
|
|
clip_to_allocation: true,
|
2019-07-16 09:24:13 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
this._visible = true;
|
|
|
|
this._inDrag = false;
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2017-12-02 00:27:35 +00:00
|
|
|
Main.overview.connect('hiding', this._onOverviewHiding.bind(this));
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2017-12-02 00:27:35 +00:00
|
|
|
Main.overview.connect('item-drag-begin', this._onDragBegin.bind(this));
|
|
|
|
Main.overview.connect('item-drag-end', this._onDragEnd.bind(this));
|
|
|
|
Main.overview.connect('item-drag-cancelled', this._onDragEnd.bind(this));
|
2013-02-19 03:34:27 +00:00
|
|
|
|
2017-12-02 00:27:35 +00:00
|
|
|
Main.overview.connect('window-drag-begin', this._onWindowDragBegin.bind(this));
|
|
|
|
Main.overview.connect('window-drag-cancelled', this._onWindowDragEnd.bind(this));
|
|
|
|
Main.overview.connect('window-drag-end', this._onWindowDragEnd.bind(this));
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_getSlide() {
|
2019-05-21 20:28:07 +00:00
|
|
|
throw new GObject.NotImplementedError(`_getSlide in ${this.constructor.name}`);
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_updateSlide() {
|
2019-07-16 09:24:13 +00:00
|
|
|
this.ease_property('@layout.slide-x', this._getSlide(), {
|
2019-07-25 00:06:05 +00:00
|
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
|
|
|
duration: SIDE_CONTROLS_ANIMATION_TIME,
|
|
|
|
});
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
getVisibleWidth() {
|
2019-07-16 09:24:13 +00:00
|
|
|
let child = this.get_first_child();
|
2019-01-29 19:20:09 +00:00
|
|
|
let [, , natWidth] = child.get_preferred_size();
|
2013-02-16 01:50:26 +00:00
|
|
|
return natWidth;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-16 01:50:26 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_getTranslation() {
|
2019-07-16 09:24:13 +00:00
|
|
|
let child = this.get_first_child();
|
2013-02-16 01:50:26 +00:00
|
|
|
let direction = getRtlSlideDirection(this.layout.slideDirection, child);
|
|
|
|
let visibleWidth = this.getVisibleWidth();
|
|
|
|
|
|
|
|
if (direction == SlideDirection.LEFT)
|
2019-08-19 17:55:49 +00:00
|
|
|
return -visibleWidth;
|
2013-02-16 01:50:26 +00:00
|
|
|
else
|
2013-02-18 06:24:40 +00:00
|
|
|
return visibleWidth;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-16 01:50:26 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_updateTranslation() {
|
2013-02-16 01:50:26 +00:00
|
|
|
let translationStart = 0;
|
|
|
|
let translationEnd = 0;
|
|
|
|
let translation = this._getTranslation();
|
|
|
|
|
2019-08-19 19:38:51 +00:00
|
|
|
let shouldShow = this._getSlide() > 0;
|
2019-08-20 00:51:42 +00:00
|
|
|
if (shouldShow)
|
2013-02-16 01:50:26 +00:00
|
|
|
translationStart = translation;
|
2019-08-20 00:51:42 +00:00
|
|
|
else
|
2013-02-16 01:50:26 +00:00
|
|
|
translationEnd = translation;
|
|
|
|
|
2019-07-25 22:13:19 +00:00
|
|
|
if (this.layout.translation_x == translationEnd)
|
2013-02-18 19:17:29 +00:00
|
|
|
return;
|
|
|
|
|
2019-07-25 22:13:19 +00:00
|
|
|
this.layout.translation_x = translationStart;
|
2019-07-16 09:24:13 +00:00
|
|
|
this.ease_property('@layout.translation-x', translationEnd, {
|
2019-07-25 00:06:05 +00:00
|
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
|
|
|
duration: SIDE_CONTROLS_ANIMATION_TIME,
|
|
|
|
});
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-16 01:50:26 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onOverviewHiding() {
|
2014-08-31 01:30:48 +00:00
|
|
|
// We need to explicitly slideOut since showing pages
|
|
|
|
// doesn't imply sliding out, instead, hiding the overview does.
|
2013-09-18 23:13:35 +00:00
|
|
|
this.slideOut();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-09-18 23:13:35 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onWindowDragBegin() {
|
2013-02-19 03:34:27 +00:00
|
|
|
this._onDragBegin();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-19 03:34:27 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onWindowDragEnd() {
|
2013-02-19 03:34:27 +00:00
|
|
|
this._onDragEnd();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-19 03:34:27 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onDragBegin() {
|
2013-09-18 23:06:56 +00:00
|
|
|
this._inDrag = true;
|
2014-08-31 00:20:43 +00:00
|
|
|
this._updateTranslation();
|
2013-09-18 23:22:54 +00:00
|
|
|
this._updateSlide();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onDragEnd() {
|
2013-09-18 23:06:56 +00:00
|
|
|
this._inDrag = false;
|
2013-09-18 23:22:54 +00:00
|
|
|
this._updateSlide();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
fadeIn() {
|
2019-07-16 09:24:13 +00:00
|
|
|
this.ease({
|
2018-07-20 19:46:19 +00:00
|
|
|
opacity: 255,
|
|
|
|
duration: SIDE_CONTROLS_ANIMATION_TIME / 2,
|
2019-08-20 21:43:54 +00:00
|
|
|
mode: Clutter.AnimationMode.EASE_IN_QUAD,
|
2018-07-20 19:46:19 +00:00
|
|
|
});
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-19 03:34:27 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
fadeHalf() {
|
2019-07-16 09:24:13 +00:00
|
|
|
this.ease({
|
2018-07-20 19:46:19 +00:00
|
|
|
opacity: 128,
|
|
|
|
duration: SIDE_CONTROLS_ANIMATION_TIME / 2,
|
2019-08-20 21:43:54 +00:00
|
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
2018-07-20 19:46:19 +00:00
|
|
|
});
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-19 03:34:27 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
slideIn() {
|
2013-09-18 23:06:56 +00:00
|
|
|
this._visible = true;
|
2019-07-25 22:13:19 +00:00
|
|
|
// we will update slide_x and the translation from pageEmpty
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-14 19:41:38 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
slideOut() {
|
2013-09-18 23:06:56 +00:00
|
|
|
this._visible = false;
|
2013-02-18 06:25:54 +00:00
|
|
|
this._updateTranslation();
|
2019-07-25 22:13:19 +00:00
|
|
|
// we will update slide_x from pageEmpty
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-09-26 20:20:06 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
pageEmpty() {
|
2013-09-26 20:20:06 +00:00
|
|
|
// When pageEmpty is received, there's no visible view in the
|
|
|
|
// selector; this means we can now safely set the full slide for
|
|
|
|
// the next page, since slideIn or slideOut might have been called,
|
|
|
|
// changing the visiblity
|
2019-07-16 09:24:13 +00:00
|
|
|
this.remove_transition('@layout.slide-x');
|
2019-07-25 22:13:19 +00:00
|
|
|
this.layout.slide_x = this._getSlide();
|
2013-09-26 20:20:06 +00:00
|
|
|
this._updateTranslation();
|
|
|
|
}
|
2019-07-16 09:24:13 +00:00
|
|
|
});
|
2012-12-11 22:26:09 +00:00
|
|
|
|
2019-07-16 09:24:13 +00:00
|
|
|
var ThumbnailsSlider = GObject.registerClass(
|
|
|
|
class ThumbnailsSlider extends SlidingControl {
|
|
|
|
_init(thumbnailsBox) {
|
|
|
|
super._init({ slideDirection: SlideDirection.RIGHT });
|
2012-12-11 22:26:09 +00:00
|
|
|
|
|
|
|
this._thumbnailsBox = thumbnailsBox;
|
|
|
|
|
2019-07-16 09:24:13 +00:00
|
|
|
this.request_mode = Clutter.RequestMode.WIDTH_FOR_HEIGHT;
|
|
|
|
this.reactive = true;
|
|
|
|
this.track_hover = true;
|
|
|
|
this.add_actor(this._thumbnailsBox);
|
2012-12-11 22:26:09 +00:00
|
|
|
|
2017-12-02 00:27:35 +00:00
|
|
|
Main.layoutManager.connect('monitors-changed', this._updateSlide.bind(this));
|
2018-07-20 18:35:54 +00:00
|
|
|
global.workspace_manager.connect('active-workspace-changed',
|
|
|
|
this._updateSlide.bind(this));
|
|
|
|
global.workspace_manager.connect('notify::n-workspaces',
|
|
|
|
this._updateSlide.bind(this));
|
2019-07-16 09:24:13 +00:00
|
|
|
this.connect('notify::hover', this._updateSlide.bind(this));
|
|
|
|
this._thumbnailsBox.bind_property('visible', this, 'visible', GObject.BindingFlags.SYNC_CREATE);
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2012-12-11 22:26:09 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_getAlwaysZoomOut() {
|
2018-07-20 18:35:54 +00:00
|
|
|
// Always show the pager on hover, during a drag, or if workspaces are
|
|
|
|
// actually used, e.g. there are windows on any non-active workspace
|
|
|
|
let workspaceManager = global.workspace_manager;
|
2019-07-16 09:24:13 +00:00
|
|
|
let alwaysZoomOut = this.hover ||
|
2018-07-20 18:35:54 +00:00
|
|
|
this._inDrag ||
|
|
|
|
!Meta.prefs_get_dynamic_workspaces() ||
|
|
|
|
workspaceManager.n_workspaces > 2 ||
|
|
|
|
workspaceManager.get_active_workspace_index() != 0;
|
2012-12-11 22:26:09 +00:00
|
|
|
|
|
|
|
if (!alwaysZoomOut) {
|
|
|
|
let monitors = Main.layoutManager.monitors;
|
|
|
|
let primary = Main.layoutManager.primaryMonitor;
|
|
|
|
|
|
|
|
/* Look for any monitor to the right of the primary, if there is
|
|
|
|
* one, we always keep zoom out, otherwise its hard to reach
|
|
|
|
* the thumbnail area without passing into the next monitor. */
|
|
|
|
for (let i = 0; i < monitors.length; i++) {
|
|
|
|
if (monitors[i].x >= primary.x + primary.width) {
|
|
|
|
alwaysZoomOut = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-16 01:50:26 +00:00
|
|
|
return alwaysZoomOut;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-16 01:50:26 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
getNonExpandedWidth() {
|
2019-07-16 09:24:13 +00:00
|
|
|
let child = this.get_first_child();
|
2013-04-20 16:29:58 +00:00
|
|
|
return child.get_theme_node().get_length('visible-width');
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-04-20 16:29:58 +00:00
|
|
|
|
2018-07-20 18:51:40 +00:00
|
|
|
_onDragEnd() {
|
2019-07-16 09:24:13 +00:00
|
|
|
this.sync_hover();
|
2017-10-31 01:19:44 +00:00
|
|
|
super._onDragEnd();
|
|
|
|
}
|
2018-07-20 18:51:40 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_getSlide() {
|
2013-09-18 23:06:56 +00:00
|
|
|
if (!this._visible)
|
2013-02-16 01:50:26 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
let alwaysZoomOut = this._getAlwaysZoomOut();
|
2012-12-11 22:26:09 +00:00
|
|
|
if (alwaysZoomOut)
|
|
|
|
return 1;
|
|
|
|
|
2019-07-16 09:24:13 +00:00
|
|
|
let child = this.get_first_child();
|
2012-12-11 22:26:09 +00:00
|
|
|
let preferredHeight = child.get_preferred_height(-1)[1];
|
|
|
|
let expandedWidth = child.get_preferred_width(preferredHeight)[1];
|
|
|
|
|
2013-04-20 16:29:58 +00:00
|
|
|
return this.getNonExpandedWidth() / expandedWidth;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-16 01:50:26 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
getVisibleWidth() {
|
2013-02-16 01:50:26 +00:00
|
|
|
let alwaysZoomOut = this._getAlwaysZoomOut();
|
|
|
|
if (alwaysZoomOut)
|
2017-10-31 01:19:44 +00:00
|
|
|
return super.getVisibleWidth();
|
2013-04-20 16:29:58 +00:00
|
|
|
else
|
|
|
|
return this.getNonExpandedWidth();
|
2012-12-11 22:26:09 +00:00
|
|
|
}
|
2019-07-16 09:24:13 +00:00
|
|
|
});
|
2013-01-24 04:11:23 +00:00
|
|
|
|
2019-07-16 09:24:13 +00:00
|
|
|
var DashSlider = GObject.registerClass(
|
|
|
|
class DashSlider extends SlidingControl {
|
|
|
|
_init(dash) {
|
|
|
|
super._init({ slideDirection: SlideDirection.LEFT });
|
2013-01-24 04:11:23 +00:00
|
|
|
|
2013-02-15 23:26:24 +00:00
|
|
|
this._dash = dash;
|
2013-01-24 04:11:23 +00:00
|
|
|
|
2013-10-30 22:32:26 +00:00
|
|
|
// SlideLayout reads the actor's expand flags to decide
|
|
|
|
// whether to allocate the natural size to its child, or the whole
|
|
|
|
// available allocation
|
2019-07-16 09:24:13 +00:00
|
|
|
this._dash.x_expand = true;
|
2013-10-30 22:32:26 +00:00
|
|
|
|
2019-07-16 09:24:13 +00:00
|
|
|
this.x_expand = true;
|
|
|
|
this.x_align = Clutter.ActorAlign.START;
|
|
|
|
this.y_expand = true;
|
2013-02-25 23:05:45 +00:00
|
|
|
|
2019-07-16 09:24:13 +00:00
|
|
|
this.add_actor(this._dash);
|
2013-01-24 04:11:23 +00:00
|
|
|
|
2017-12-02 00:27:35 +00:00
|
|
|
this._dash.connect('icon-size-changed', this._updateSlide.bind(this));
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-01-24 04:11:23 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_getSlide() {
|
2013-09-18 23:06:56 +00:00
|
|
|
if (this._visible || this._inDrag)
|
2013-01-24 04:11:23 +00:00
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-19 03:34:27 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onWindowDragBegin() {
|
2013-02-19 03:34:27 +00:00
|
|
|
this.fadeHalf();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-19 03:34:27 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onWindowDragEnd() {
|
2013-02-19 03:34:27 +00:00
|
|
|
this.fadeIn();
|
2013-01-24 04:11:23 +00:00
|
|
|
}
|
2019-07-16 09:24:13 +00:00
|
|
|
});
|
2013-02-15 23:25:36 +00:00
|
|
|
|
2017-10-31 01:23:39 +00:00
|
|
|
var DashSpacer = GObject.registerClass(
|
|
|
|
class DashSpacer extends St.Widget {
|
2017-10-31 00:03:21 +00:00
|
|
|
_init(params) {
|
2017-10-31 01:23:39 +00:00
|
|
|
super._init(params);
|
2013-02-21 17:48:09 +00:00
|
|
|
|
|
|
|
this._bindConstraint = null;
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2013-02-21 17:48:09 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
setDashActor(dashActor) {
|
2013-02-21 17:48:09 +00:00
|
|
|
if (this._bindConstraint) {
|
|
|
|
this.remove_constraint(this._bindConstraint);
|
|
|
|
this._bindConstraint = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dashActor) {
|
|
|
|
this._bindConstraint = new Clutter.BindConstraint({ source: dashActor,
|
|
|
|
coordinate: Clutter.BindCoordinate.SIZE });
|
|
|
|
this.add_constraint(this._bindConstraint);
|
|
|
|
}
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2013-02-21 17:48:09 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
vfunc_get_preferred_width(forHeight) {
|
2019-04-30 11:31:51 +00:00
|
|
|
if (this._bindConstraint)
|
|
|
|
return this._bindConstraint.source.get_preferred_width(forHeight);
|
|
|
|
return super.vfunc_get_preferred_width(forHeight);
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2013-02-21 17:48:09 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
vfunc_get_preferred_height(forWidth) {
|
2019-04-30 11:31:51 +00:00
|
|
|
if (this._bindConstraint)
|
|
|
|
return this._bindConstraint.source.get_preferred_height(forWidth);
|
|
|
|
return super.vfunc_get_preferred_height(forWidth);
|
2013-02-21 17:48:09 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-10-31 01:23:39 +00:00
|
|
|
var ControlsLayout = GObject.registerClass({
|
2013-09-13 07:34:13 +00:00
|
|
|
Signals: { 'allocation-changed': { flags: GObject.SignalFlags.RUN_LAST } },
|
2017-10-31 01:23:39 +00:00
|
|
|
}, class ControlsLayout extends Clutter.BinLayout {
|
2017-10-31 00:03:21 +00:00
|
|
|
vfunc_allocate(container, box, flags) {
|
2017-10-31 01:23:39 +00:00
|
|
|
super.vfunc_allocate(container, box, flags);
|
2013-09-13 07:34:13 +00:00
|
|
|
this.emit('allocation-changed');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-07-16 09:24:13 +00:00
|
|
|
var ControlsManager = GObject.registerClass(
|
|
|
|
class ControlsManager extends St.Widget {
|
|
|
|
_init(searchEntry) {
|
|
|
|
let layout = new ControlsLayout();
|
|
|
|
super._init({
|
|
|
|
layout_manager: layout,
|
|
|
|
x_expand: true,
|
|
|
|
y_expand: true,
|
2019-08-20 21:43:54 +00:00
|
|
|
clip_to_allocation: true,
|
2019-07-16 09:24:13 +00:00
|
|
|
});
|
|
|
|
|
2013-02-25 23:05:45 +00:00
|
|
|
this.dash = new Dash.Dash();
|
|
|
|
this._dashSlider = new DashSlider(this.dash);
|
|
|
|
this._dashSpacer = new DashSpacer();
|
2019-07-16 09:24:13 +00:00
|
|
|
this._dashSpacer.setDashActor(this._dashSlider);
|
2013-02-25 23:05:45 +00:00
|
|
|
|
|
|
|
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
|
|
|
|
this._thumbnailsSlider = new ThumbnailsSlider(this._thumbnailsBox);
|
2013-02-15 23:25:36 +00:00
|
|
|
|
2013-02-25 23:05:45 +00:00
|
|
|
this.viewSelector = new ViewSelector.ViewSelector(searchEntry,
|
|
|
|
this.dash.showAppsButton);
|
2017-12-02 00:27:35 +00:00
|
|
|
this.viewSelector.connect('page-changed', this._setVisibility.bind(this));
|
|
|
|
this.viewSelector.connect('page-empty', this._onPageEmpty.bind(this));
|
2013-02-15 23:25:36 +00:00
|
|
|
|
2013-02-25 23:05:45 +00:00
|
|
|
this._group = new St.BoxLayout({ name: 'overview-group',
|
2019-01-29 19:36:54 +00:00
|
|
|
x_expand: true, y_expand: true });
|
2019-07-16 09:24:13 +00:00
|
|
|
this.add_actor(this._group);
|
2013-02-25 23:05:45 +00:00
|
|
|
|
2019-07-16 09:24:13 +00:00
|
|
|
this.add_actor(this._dashSlider);
|
2013-02-25 23:05:45 +00:00
|
|
|
|
|
|
|
this._group.add_actor(this._dashSpacer);
|
2019-10-21 18:44:00 +00:00
|
|
|
this._group.add_child(this.viewSelector);
|
2019-07-16 09:24:13 +00:00
|
|
|
this._group.add_actor(this._thumbnailsSlider);
|
2013-02-18 04:45:24 +00:00
|
|
|
|
2017-12-02 00:27:35 +00:00
|
|
|
layout.connect('allocation-changed', this._updateWorkspacesGeometry.bind(this));
|
2013-02-25 23:11:59 +00:00
|
|
|
|
2017-12-02 00:27:35 +00:00
|
|
|
Main.overview.connect('showing', this._updateSpacerVisibility.bind(this));
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-15 23:25:36 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_updateWorkspacesGeometry() {
|
2019-07-16 09:24:13 +00:00
|
|
|
let [x, y] = this.get_transformed_position();
|
|
|
|
let [width, height] = this.get_transformed_size();
|
2019-08-19 19:06:04 +00:00
|
|
|
let geometry = { x, y, width, height };
|
2013-02-25 23:11:59 +00:00
|
|
|
|
2019-07-16 09:24:13 +00:00
|
|
|
let spacing = this.get_theme_node().get_length('spacing');
|
2013-02-25 23:11:59 +00:00
|
|
|
let dashWidth = this._dashSlider.getVisibleWidth() + spacing;
|
|
|
|
let thumbnailsWidth = this._thumbnailsSlider.getNonExpandedWidth() + spacing;
|
|
|
|
|
|
|
|
geometry.width -= dashWidth;
|
|
|
|
geometry.width -= thumbnailsWidth;
|
|
|
|
|
2019-07-16 09:24:13 +00:00
|
|
|
if (this.get_text_direction() == Clutter.TextDirection.LTR)
|
2013-02-25 23:11:59 +00:00
|
|
|
geometry.x += dashWidth;
|
|
|
|
else
|
|
|
|
geometry.x += thumbnailsWidth;
|
|
|
|
|
2013-02-25 23:25:27 +00:00
|
|
|
this.viewSelector.setWorkspacesFullGeometry(geometry);
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-25 23:11:59 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_setVisibility() {
|
2013-02-15 23:25:36 +00:00
|
|
|
// Ignore the case when we're leaving the overview, since
|
|
|
|
// actors will be made visible again when entering the overview
|
|
|
|
// next time, and animating them while doing so is just
|
|
|
|
// unnecessary noise
|
2013-02-16 17:45:10 +00:00
|
|
|
if (!Main.overview.visible ||
|
|
|
|
(Main.overview.animationInProgress && !Main.overview.visibleTarget))
|
2013-02-15 23:25:36 +00:00
|
|
|
return;
|
|
|
|
|
2013-02-25 23:05:45 +00:00
|
|
|
let activePage = this.viewSelector.getActivePage();
|
2019-08-19 19:38:51 +00:00
|
|
|
let dashVisible = activePage == ViewSelector.ViewPage.WINDOWS ||
|
|
|
|
activePage == ViewSelector.ViewPage.APPS;
|
|
|
|
let thumbnailsVisible = activePage == ViewSelector.ViewPage.WINDOWS;
|
2013-09-26 20:20:06 +00:00
|
|
|
|
|
|
|
if (dashVisible)
|
|
|
|
this._dashSlider.slideIn();
|
|
|
|
else
|
2013-02-15 23:25:36 +00:00
|
|
|
this._dashSlider.slideOut();
|
|
|
|
|
2013-09-26 20:20:06 +00:00
|
|
|
if (thumbnailsVisible)
|
|
|
|
this._thumbnailsSlider.slideIn();
|
|
|
|
else
|
2013-02-15 23:25:36 +00:00
|
|
|
this._thumbnailsSlider.slideOut();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-16 01:50:26 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_updateSpacerVisibility() {
|
2013-02-21 17:48:09 +00:00
|
|
|
if (Main.overview.animationInProgress && !Main.overview.visibleTarget)
|
|
|
|
return;
|
|
|
|
|
2013-02-25 23:05:45 +00:00
|
|
|
let activePage = this.viewSelector.getActivePage();
|
2019-08-19 19:38:51 +00:00
|
|
|
this._dashSpacer.visible = activePage == ViewSelector.ViewPage.WINDOWS;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-02-21 17:48:09 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onPageEmpty() {
|
2013-09-26 20:20:06 +00:00
|
|
|
this._dashSlider.pageEmpty();
|
|
|
|
this._thumbnailsSlider.pageEmpty();
|
2013-02-21 17:48:09 +00:00
|
|
|
|
|
|
|
this._updateSpacerVisibility();
|
2013-02-15 23:25:36 +00:00
|
|
|
}
|
2019-07-16 09:24:13 +00:00
|
|
|
});
|