2011-09-28 13:16:26 +00:00
|
|
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
2008-10-31 23:09:46 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
import Clutter from 'gi://Clutter';
|
|
|
|
import Gio from 'gi://Gio';
|
|
|
|
import GLib from 'gi://GLib';
|
|
|
|
import GObject from 'gi://GObject';
|
|
|
|
import Meta from 'gi://Meta';
|
|
|
|
import Shell from 'gi://Shell';
|
|
|
|
import St from 'gi://St';
|
|
|
|
import * as Signals from '../misc/signals.js';
|
2009-02-02 23:02:16 +00:00
|
|
|
|
2020-06-24 13:28:53 +00:00
|
|
|
// Time for initial animation going into Overview mode;
|
|
|
|
// this is defined here to make it available in imports.
|
2023-07-10 09:53:00 +00:00
|
|
|
export const ANIMATION_TIME = 250;
|
2020-06-24 13:28:53 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
import * as DND from './dnd.js';
|
|
|
|
import * as LayoutManager from './layout.js';
|
|
|
|
import * as Main from './main.js';
|
|
|
|
import * as MessageTray from './messageTray.js';
|
|
|
|
import * as OverviewControls from './overviewControls.js';
|
|
|
|
import * as Params from '../misc/params.js';
|
|
|
|
import * as SwipeTracker from './swipeTracker.js';
|
|
|
|
import * as WindowManager from './windowManager.js';
|
|
|
|
import * as WorkspaceThumbnail from './workspaceThumbnail.js';
|
2008-10-31 23:09:46 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
const DND_WINDOW_SWITCH_TIMEOUT = 750;
|
2012-08-30 00:22:39 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
const OVERVIEW_ACTIVATION_TIMEOUT = 0.5;
|
2013-03-01 21:00:37 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
class ShellInfo {
|
2017-10-31 01:19:44 +00:00
|
|
|
constructor() {
|
2010-07-22 15:49:43 +00:00
|
|
|
this._source = null;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2010-02-08 22:50:50 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
setMessage(text, options) {
|
2019-02-12 14:02:09 +00:00
|
|
|
options = Params.parse(options, {
|
|
|
|
undoCallback: null,
|
|
|
|
forFeedback: false,
|
|
|
|
});
|
2012-11-02 17:06:40 +00:00
|
|
|
|
|
|
|
let undoCallback = options.undoCallback;
|
|
|
|
let forFeedback = options.forFeedback;
|
|
|
|
|
2010-07-22 15:49:43 +00:00
|
|
|
if (this._source == null) {
|
2010-11-30 15:47:28 +00:00
|
|
|
this._source = new MessageTray.SystemNotificationSource();
|
2017-10-31 00:38:18 +00:00
|
|
|
this._source.connect('destroy', () => {
|
|
|
|
this._source = null;
|
|
|
|
});
|
2010-07-22 15:49:43 +00:00
|
|
|
Main.messageTray.add(this._source);
|
|
|
|
}
|
2010-02-08 22:50:50 +00:00
|
|
|
|
2011-03-21 21:43:34 +00:00
|
|
|
let notification = null;
|
2023-08-07 00:51:19 +00:00
|
|
|
if (this._source.notifications.length === 0) {
|
2010-07-22 15:49:43 +00:00
|
|
|
notification = new MessageTray.Notification(this._source, text, null);
|
2012-08-20 14:14:22 +00:00
|
|
|
notification.setTransient(true);
|
2012-11-02 17:06:40 +00:00
|
|
|
notification.setForFeedback(forFeedback);
|
2011-03-21 21:43:34 +00:00
|
|
|
} else {
|
|
|
|
notification = this._source.notifications[0];
|
2023-08-06 22:40:20 +00:00
|
|
|
notification.update(text, null, {clear: true});
|
2011-03-21 21:43:34 +00:00
|
|
|
}
|
2010-03-10 14:14:56 +00:00
|
|
|
|
2013-10-14 03:06:09 +00:00
|
|
|
if (undoCallback)
|
2021-07-08 17:23:38 +00:00
|
|
|
notification.addAction(_('Undo'), () => undoCallback());
|
2010-07-22 15:49:43 +00:00
|
|
|
|
2019-05-13 21:32:31 +00:00
|
|
|
this._source.showNotification(notification);
|
2010-02-08 22:50:50 +00:00
|
|
|
}
|
2023-07-10 09:53:00 +00:00
|
|
|
}
|
2010-02-08 22:50:50 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
const OverviewActor = GObject.registerClass(
|
2019-08-31 01:51:02 +00:00
|
|
|
class OverviewActor extends St.BoxLayout {
|
|
|
|
_init() {
|
|
|
|
super._init({
|
|
|
|
name: 'overview',
|
|
|
|
/* Translators: This is the main view to select
|
|
|
|
activities. See also note for "Activities" string. */
|
2023-08-06 22:34:20 +00:00
|
|
|
accessible_name: _('Overview'),
|
2019-08-20 21:43:54 +00:00
|
|
|
vertical: true,
|
2019-08-31 01:51:02 +00:00
|
|
|
});
|
|
|
|
|
2023-08-06 22:40:20 +00:00
|
|
|
this.add_constraint(new LayoutManager.MonitorConstraint({primary: true}));
|
2019-08-31 01:51:02 +00:00
|
|
|
|
2020-12-30 20:02:14 +00:00
|
|
|
this._controls = new OverviewControls.ControlsManager();
|
2019-10-21 18:44:00 +00:00
|
|
|
this.add_child(this._controls);
|
2019-08-31 01:51:02 +00:00
|
|
|
}
|
|
|
|
|
2022-11-21 11:39:19 +00:00
|
|
|
prepareToEnterOverview() {
|
|
|
|
this._controls.prepareToEnterOverview();
|
|
|
|
}
|
|
|
|
|
|
|
|
prepareToLeaveOverview() {
|
|
|
|
this._controls.prepareToLeaveOverview();
|
|
|
|
}
|
|
|
|
|
2021-01-02 20:19:37 +00:00
|
|
|
animateToOverview(state, callback) {
|
|
|
|
this._controls.animateToOverview(state, callback);
|
2021-01-01 16:39:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
animateFromOverview(callback) {
|
2021-01-01 17:18:18 +00:00
|
|
|
this._controls.animateFromOverview(callback);
|
2021-01-01 16:39:07 +00:00
|
|
|
}
|
|
|
|
|
2021-02-15 20:39:14 +00:00
|
|
|
runStartupAnimation(callback) {
|
|
|
|
this._controls.runStartupAnimation(callback);
|
|
|
|
}
|
|
|
|
|
2019-08-31 01:51:02 +00:00
|
|
|
get dash() {
|
|
|
|
return this._controls.dash;
|
|
|
|
}
|
|
|
|
|
2023-06-01 22:54:59 +00:00
|
|
|
get searchController() {
|
|
|
|
return this._controls.searchController;
|
|
|
|
}
|
|
|
|
|
2019-08-31 01:51:02 +00:00
|
|
|
get searchEntry() {
|
2020-12-30 20:02:14 +00:00
|
|
|
return this._controls.searchEntry;
|
2019-08-31 01:51:02 +00:00
|
|
|
}
|
|
|
|
|
2021-01-04 15:23:45 +00:00
|
|
|
get controls() {
|
|
|
|
return this._controls;
|
|
|
|
}
|
2019-08-31 01:51:02 +00:00
|
|
|
});
|
|
|
|
|
2022-03-16 21:36:49 +00:00
|
|
|
const OverviewShownState = {
|
|
|
|
HIDDEN: 'HIDDEN',
|
|
|
|
HIDING: 'HIDING',
|
|
|
|
SHOWING: 'SHOWING',
|
|
|
|
SHOWN: 'SHOWN',
|
|
|
|
};
|
|
|
|
|
|
|
|
const OVERVIEW_SHOWN_TRANSITIONS = {
|
|
|
|
[OverviewShownState.HIDDEN]: {
|
|
|
|
signal: 'hidden',
|
|
|
|
allowedTransitions: [OverviewShownState.SHOWING],
|
|
|
|
},
|
|
|
|
[OverviewShownState.HIDING]: {
|
|
|
|
signal: 'hiding',
|
|
|
|
allowedTransitions:
|
|
|
|
[OverviewShownState.HIDDEN, OverviewShownState.SHOWING],
|
|
|
|
},
|
|
|
|
[OverviewShownState.SHOWING]: {
|
|
|
|
signal: 'showing',
|
|
|
|
allowedTransitions:
|
|
|
|
[OverviewShownState.SHOWN, OverviewShownState.HIDING],
|
|
|
|
},
|
|
|
|
[OverviewShownState.SHOWN]: {
|
|
|
|
signal: 'shown',
|
|
|
|
allowedTransitions: [OverviewShownState.HIDING],
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
export class Overview extends Signals.EventEmitter {
|
2017-10-31 01:19:44 +00:00
|
|
|
constructor() {
|
2022-07-04 22:30:44 +00:00
|
|
|
super();
|
|
|
|
|
2012-11-29 16:58:31 +00:00
|
|
|
this._initCalled = false;
|
2020-01-29 16:48:57 +00:00
|
|
|
this._visible = false;
|
2012-09-01 12:42:53 +00:00
|
|
|
|
2017-12-02 00:27:35 +00:00
|
|
|
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
|
2012-09-01 12:42:53 +00:00
|
|
|
this._sessionUpdated();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-08-28 14:24:48 +00:00
|
|
|
|
2019-08-31 01:51:02 +00:00
|
|
|
get dash() {
|
|
|
|
return this._overview.dash;
|
|
|
|
}
|
|
|
|
|
|
|
|
get dashIconSize() {
|
|
|
|
logError(new Error('Usage of Overview.\'dashIconSize\' is deprecated, ' +
|
|
|
|
'use \'dash.iconSize\' property instead'));
|
|
|
|
return this.dash.iconSize;
|
|
|
|
}
|
|
|
|
|
2019-08-31 02:04:34 +00:00
|
|
|
get animationInProgress() {
|
|
|
|
return this._animationInProgress;
|
|
|
|
}
|
|
|
|
|
|
|
|
get visible() {
|
|
|
|
return this._visible;
|
|
|
|
}
|
|
|
|
|
|
|
|
get visibleTarget() {
|
|
|
|
return this._visibleTarget;
|
|
|
|
}
|
|
|
|
|
2020-09-16 06:52:19 +00:00
|
|
|
get closing() {
|
|
|
|
return this._animationInProgress && !this._visibleTarget;
|
|
|
|
}
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_createOverview() {
|
2019-08-31 01:51:02 +00:00
|
|
|
if (this._overview)
|
2011-08-28 14:24:48 +00:00
|
|
|
return;
|
2012-09-01 12:42:53 +00:00
|
|
|
|
|
|
|
if (this.isDummy)
|
|
|
|
return;
|
|
|
|
|
2013-03-01 21:00:37 +00:00
|
|
|
this._activationTime = 0;
|
|
|
|
|
2019-08-31 02:04:34 +00:00
|
|
|
this._visible = false; // animating to overview, in overview, animating out
|
2011-01-05 14:39:36 +00:00
|
|
|
this._shown = false; // show() and not hide()
|
|
|
|
this._modal = false; // have a modal grab
|
2019-08-31 02:04:34 +00:00
|
|
|
this._animationInProgress = false;
|
|
|
|
this._visibleTarget = false;
|
2022-03-16 21:36:49 +00:00
|
|
|
this._shownState = OverviewShownState.HIDDEN;
|
2009-06-24 22:24:48 +00:00
|
|
|
|
2009-09-13 18:54:56 +00:00
|
|
|
// During transitions, we raise this to the top to avoid having the overview
|
|
|
|
// area be reactive; it causes too many issues such as double clicks on
|
|
|
|
// Dash elements, or mouseover handlers in the workspaces.
|
2020-03-29 21:51:13 +00:00
|
|
|
this._coverPane = new Clutter.Actor({
|
|
|
|
opacity: 0,
|
|
|
|
reactive: true,
|
|
|
|
});
|
2013-09-29 21:20:27 +00:00
|
|
|
Main.layoutManager.overviewGroup.add_child(this._coverPane);
|
2022-01-12 16:19:53 +00:00
|
|
|
this._coverPane.connect('event', (_actor, event) => {
|
|
|
|
return event.type() === Clutter.EventType.ENTER ||
|
|
|
|
event.type() === Clutter.EventType.LEAVE
|
|
|
|
? Clutter.EVENT_PROPAGATE : Clutter.EVENT_STOP;
|
|
|
|
});
|
2011-02-11 22:53:27 +00:00
|
|
|
this._coverPane.hide();
|
|
|
|
|
|
|
|
// XDND
|
|
|
|
this._dragMonitor = {
|
2019-08-20 21:43:54 +00:00
|
|
|
dragMotion: this._onDragMotion.bind(this),
|
2011-02-11 22:53:27 +00:00
|
|
|
};
|
|
|
|
|
2016-07-02 09:16:22 +00:00
|
|
|
|
|
|
|
Main.layoutManager.overviewGroup.connect('scroll-event',
|
2023-08-06 23:45:22 +00:00
|
|
|
this._onScrollEvent.bind(this));
|
2017-12-02 00:27:35 +00:00
|
|
|
Main.xdndHandler.connect('drag-begin', this._onDragBegin.bind(this));
|
|
|
|
Main.xdndHandler.connect('drag-end', this._onDragEnd.bind(this));
|
2011-02-11 22:53:27 +00:00
|
|
|
|
2018-01-03 07:55:38 +00:00
|
|
|
global.display.connect('restacked', this._onRestacked.bind(this));
|
2012-12-13 16:00:30 +00:00
|
|
|
|
2011-02-11 22:53:27 +00:00
|
|
|
this._windowSwitchTimeoutId = 0;
|
|
|
|
this._windowSwitchTimestamp = 0;
|
|
|
|
this._lastActiveWorkspaceIndex = -1;
|
|
|
|
this._lastHoveredWindow = null;
|
2012-11-29 16:58:31 +00:00
|
|
|
|
|
|
|
if (this._initCalled)
|
|
|
|
this.init();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-02-11 22:53:27 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_sessionUpdated() {
|
2023-08-06 22:40:20 +00:00
|
|
|
const {hasOverview} = Main.sessionMode;
|
2020-02-24 10:19:28 +00:00
|
|
|
if (!hasOverview)
|
|
|
|
this.hide();
|
|
|
|
|
|
|
|
this.isDummy = !hasOverview;
|
2012-09-01 12:42:53 +00:00
|
|
|
this._createOverview();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2012-09-01 12:42:53 +00:00
|
|
|
|
2011-02-11 22:53:27 +00:00
|
|
|
// The members we construct that are implemented in JS might
|
|
|
|
// want to access the overview as Main.overview to connect
|
|
|
|
// signal handlers and so forth. So we create them after
|
|
|
|
// construction in this init() method.
|
2017-10-31 00:03:21 +00:00
|
|
|
init() {
|
2012-11-29 16:58:31 +00:00
|
|
|
this._initCalled = true;
|
|
|
|
|
2011-08-28 14:24:48 +00:00
|
|
|
if (this.isDummy)
|
|
|
|
return;
|
|
|
|
|
2019-08-31 01:51:02 +00:00
|
|
|
this._overview = new OverviewActor();
|
|
|
|
this._overview._delegate = this;
|
|
|
|
Main.layoutManager.overviewGroup.add_child(this._overview);
|
2012-12-10 20:39:15 +00:00
|
|
|
|
2019-08-31 01:51:02 +00:00
|
|
|
this._shellInfo = new ShellInfo();
|
2013-01-24 21:34:06 +00:00
|
|
|
|
2017-12-02 00:27:35 +00:00
|
|
|
Main.layoutManager.connect('monitors-changed', this._relayout.bind(this));
|
2011-06-13 13:54:05 +00:00
|
|
|
this._relayout();
|
2021-01-02 20:10:36 +00:00
|
|
|
|
|
|
|
Main.wm.addKeybinding(
|
|
|
|
'toggle-overview',
|
2023-08-06 22:40:20 +00:00
|
|
|
new Gio.Settings({schema_id: WindowManager.SHELL_KEYBINDINGS_SCHEMA}),
|
2021-01-02 20:10:36 +00:00
|
|
|
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
|
|
|
|
Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW,
|
|
|
|
this.toggle.bind(this));
|
2021-01-04 15:23:45 +00:00
|
|
|
|
|
|
|
const swipeTracker = new SwipeTracker.SwipeTracker(global.stage,
|
2021-03-01 16:53:55 +00:00
|
|
|
Clutter.Orientation.VERTICAL,
|
2021-01-04 15:23:45 +00:00
|
|
|
Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW,
|
2023-08-06 22:40:20 +00:00
|
|
|
{allowDrag: false, allowScroll: false});
|
2021-01-04 15:23:45 +00:00
|
|
|
swipeTracker.orientation = Clutter.Orientation.VERTICAL;
|
|
|
|
swipeTracker.connect('begin', this._gestureBegin.bind(this));
|
|
|
|
swipeTracker.connect('update', this._gestureUpdate.bind(this));
|
|
|
|
swipeTracker.connect('end', this._gestureEnd.bind(this));
|
|
|
|
this._swipeTracker = swipeTracker;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2009-06-24 22:24:48 +00:00
|
|
|
|
2012-11-02 17:06:40 +00:00
|
|
|
//
|
|
|
|
// options:
|
|
|
|
// - undoCallback (function): the callback to be called if undo support is needed
|
|
|
|
// - forFeedback (boolean): whether the message is for direct feedback of a user action
|
|
|
|
//
|
2017-10-31 00:03:21 +00:00
|
|
|
setMessage(text, options) {
|
2011-08-28 14:24:48 +00:00
|
|
|
if (this.isDummy)
|
|
|
|
return;
|
|
|
|
|
2012-11-02 17:06:40 +00:00
|
|
|
this._shellInfo.setMessage(text, options);
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-08-28 14:07:44 +00:00
|
|
|
|
2022-03-16 21:36:49 +00:00
|
|
|
_changeShownState(state) {
|
|
|
|
const {allowedTransitions} =
|
|
|
|
OVERVIEW_SHOWN_TRANSITIONS[this._shownState];
|
|
|
|
|
|
|
|
if (!allowedTransitions.includes(state)) {
|
|
|
|
throw new Error('Invalid overview shown transition from ' +
|
|
|
|
`${this._shownState} to ${state}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
this._shownState = state;
|
|
|
|
this.emit(OVERVIEW_SHOWN_TRANSITIONS[state].signal);
|
|
|
|
}
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onDragBegin() {
|
2013-03-04 22:02:02 +00:00
|
|
|
this._inXdndDrag = true;
|
|
|
|
|
2011-01-05 14:47:27 +00:00
|
|
|
DND.addDragMonitor(this._dragMonitor);
|
|
|
|
// Remember the workspace we started from
|
2018-01-03 07:55:38 +00:00
|
|
|
let workspaceManager = global.workspace_manager;
|
2021-12-03 19:04:05 +00:00
|
|
|
this._lastActiveWorkspaceIndex = workspaceManager.get_active_workspace_id();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-01-05 14:47:27 +00:00
|
|
|
|
2022-02-23 15:23:02 +00:00
|
|
|
_onDragEnd() {
|
2013-03-04 22:02:02 +00:00
|
|
|
this._inXdndDrag = false;
|
|
|
|
|
2011-01-05 14:47:27 +00:00
|
|
|
// In case the drag was canceled while in the overview
|
|
|
|
// we have to go back to where we started and hide
|
|
|
|
// the overview
|
2013-03-04 22:02:02 +00:00
|
|
|
if (this._shown) {
|
2018-01-03 07:55:38 +00:00
|
|
|
let workspaceManager = global.workspace_manager;
|
2022-02-23 15:23:02 +00:00
|
|
|
workspaceManager.get_workspace_by_index(this._lastActiveWorkspaceIndex)
|
|
|
|
.activate(global.get_current_time());
|
2013-03-04 22:02:02 +00:00
|
|
|
this.hide();
|
2011-01-05 14:47:27 +00:00
|
|
|
}
|
2011-02-24 10:30:46 +00:00
|
|
|
this._resetWindowSwitchTimeout();
|
2011-01-07 10:12:00 +00:00
|
|
|
this._lastHoveredWindow = null;
|
2011-06-27 16:59:56 +00:00
|
|
|
DND.removeDragMonitor(this._dragMonitor);
|
2011-03-13 18:34:47 +00:00
|
|
|
this.endItemDrag();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-01-05 14:47:27 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_resetWindowSwitchTimeout() {
|
2023-08-07 00:51:19 +00:00
|
|
|
if (this._windowSwitchTimeoutId !== 0) {
|
2019-08-19 18:50:33 +00:00
|
|
|
GLib.source_remove(this._windowSwitchTimeoutId);
|
2011-02-24 10:30:46 +00:00
|
|
|
this._windowSwitchTimeoutId = 0;
|
|
|
|
}
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-02-24 10:30:46 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onDragMotion(dragEvent) {
|
2011-01-07 10:12:00 +00:00
|
|
|
let targetIsWindow = dragEvent.targetActor &&
|
|
|
|
dragEvent.targetActor._delegate &&
|
2011-03-21 22:20:36 +00:00
|
|
|
dragEvent.targetActor._delegate.metaWindow &&
|
|
|
|
!(dragEvent.targetActor._delegate instanceof WorkspaceThumbnail.WindowClone);
|
2011-01-07 10:12:00 +00:00
|
|
|
|
2011-02-24 10:25:29 +00:00
|
|
|
this._windowSwitchTimestamp = global.get_current_time();
|
|
|
|
|
2011-01-07 10:12:00 +00:00
|
|
|
if (targetIsWindow &&
|
2023-08-07 00:51:19 +00:00
|
|
|
dragEvent.targetActor._delegate.metaWindow === this._lastHoveredWindow)
|
2011-01-20 15:46:55 +00:00
|
|
|
return DND.DragMotionResult.CONTINUE;
|
|
|
|
|
|
|
|
this._lastHoveredWindow = null;
|
2011-01-07 10:12:00 +00:00
|
|
|
|
2011-02-24 10:30:46 +00:00
|
|
|
this._resetWindowSwitchTimeout();
|
2011-01-05 14:47:27 +00:00
|
|
|
|
2011-01-07 10:12:00 +00:00
|
|
|
if (targetIsWindow) {
|
|
|
|
this._lastHoveredWindow = dragEvent.targetActor._delegate.metaWindow;
|
2019-08-19 18:50:33 +00:00
|
|
|
this._windowSwitchTimeoutId = GLib.timeout_add(
|
|
|
|
GLib.PRIORITY_DEFAULT,
|
|
|
|
DND_WINDOW_SWITCH_TIMEOUT,
|
2017-10-31 00:38:18 +00:00
|
|
|
() => {
|
|
|
|
this._windowSwitchTimeoutId = 0;
|
|
|
|
Main.activateWindow(dragEvent.targetActor._delegate.metaWindow,
|
2023-08-06 23:45:22 +00:00
|
|
|
this._windowSwitchTimestamp);
|
2017-10-31 00:38:18 +00:00
|
|
|
this.hide();
|
|
|
|
this._lastHoveredWindow = null;
|
|
|
|
return GLib.SOURCE_REMOVE;
|
|
|
|
});
|
2014-04-10 17:26:52 +00:00
|
|
|
GLib.Source.set_name_by_id(this._windowSwitchTimeoutId, '[gnome-shell] Main.activateWindow');
|
2011-01-05 14:47:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return DND.DragMotionResult.CONTINUE;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-01-05 14:47:27 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onScrollEvent(actor, event) {
|
2012-10-22 15:39:19 +00:00
|
|
|
this.emit('scroll-event', event);
|
2013-11-29 18:17:34 +00:00
|
|
|
return Clutter.EVENT_PROPAGATE;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2012-10-22 15:39:19 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_relayout() {
|
2011-06-13 13:54:05 +00:00
|
|
|
// To avoid updating the position and size of the workspaces
|
|
|
|
// we just hide the overview. The positions will be updated
|
|
|
|
// when it is next shown.
|
|
|
|
this.hide();
|
|
|
|
|
2018-07-24 12:45:03 +00:00
|
|
|
this._coverPane.set_position(0, 0);
|
|
|
|
this._coverPane.set_size(global.screen_width, global.screen_height);
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2008-12-01 19:51:43 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onRestacked() {
|
2012-12-13 16:00:30 +00:00
|
|
|
let stack = global.get_window_actors();
|
|
|
|
let stackIndices = {};
|
|
|
|
|
|
|
|
for (let i = 0; i < stack.length; i++) {
|
|
|
|
// Use the stable sequence for an integer to use as a hash key
|
|
|
|
stackIndices[stack[i].get_meta_window().get_stable_sequence()] = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.emit('windows-restacked', stackIndices);
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2012-12-13 16:00:30 +00:00
|
|
|
|
2021-01-04 15:23:45 +00:00
|
|
|
_gestureBegin(tracker) {
|
|
|
|
this._overview.controls.gestureBegin(tracker);
|
|
|
|
}
|
|
|
|
|
|
|
|
_gestureUpdate(tracker, progress) {
|
|
|
|
if (!this._shown) {
|
|
|
|
Meta.disable_unredirect_for_display(global.display);
|
|
|
|
|
|
|
|
this._shown = true;
|
|
|
|
this._visible = true;
|
|
|
|
this._visibleTarget = true;
|
|
|
|
this._animationInProgress = true;
|
|
|
|
|
|
|
|
Main.layoutManager.overviewGroup.set_child_above_sibling(
|
|
|
|
this._coverPane, null);
|
|
|
|
this._coverPane.show();
|
2022-03-16 21:36:49 +00:00
|
|
|
this._changeShownState(OverviewShownState.SHOWING);
|
2021-01-04 15:23:45 +00:00
|
|
|
|
|
|
|
Main.layoutManager.showOverview();
|
|
|
|
this._syncGrab();
|
|
|
|
}
|
|
|
|
|
|
|
|
this._overview.controls.gestureProgress(progress);
|
|
|
|
}
|
|
|
|
|
|
|
|
_gestureEnd(tracker, duration, endProgress) {
|
|
|
|
let onComplete;
|
|
|
|
if (endProgress === 0) {
|
|
|
|
this._shown = false;
|
2021-02-26 21:55:57 +00:00
|
|
|
this._visibleTarget = false;
|
2022-03-16 21:36:49 +00:00
|
|
|
this._changeShownState(OverviewShownState.HIDING);
|
2022-02-07 14:14:06 +00:00
|
|
|
Main.panel.style = `transition-duration: ${duration}ms;`;
|
2021-01-04 15:23:45 +00:00
|
|
|
onComplete = () => this._hideDone();
|
|
|
|
} else {
|
|
|
|
onComplete = () => this._showDone();
|
|
|
|
}
|
|
|
|
|
|
|
|
this._overview.controls.gestureEnd(endProgress, duration, onComplete);
|
|
|
|
}
|
|
|
|
|
2020-06-23 13:30:33 +00:00
|
|
|
beginItemDrag(source) {
|
|
|
|
this.emit('item-drag-begin', source);
|
2017-11-16 16:27:12 +00:00
|
|
|
this._inItemDrag = true;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2009-03-11 19:21:45 +00:00
|
|
|
|
2020-06-23 13:30:33 +00:00
|
|
|
cancelledItemDrag(source) {
|
|
|
|
this.emit('item-drag-cancelled', source);
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-03-09 15:40:48 +00:00
|
|
|
|
2020-06-23 13:30:33 +00:00
|
|
|
endItemDrag(source) {
|
2017-11-16 16:27:12 +00:00
|
|
|
if (!this._inItemDrag)
|
|
|
|
return;
|
2020-06-23 13:30:33 +00:00
|
|
|
this.emit('item-drag-end', source);
|
2017-11-16 16:27:12 +00:00
|
|
|
this._inItemDrag = false;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2009-03-11 19:21:45 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
beginWindowDrag(window) {
|
2014-09-03 19:55:05 +00:00
|
|
|
this.emit('window-drag-begin', window);
|
2017-11-16 16:27:12 +00:00
|
|
|
this._inWindowDrag = true;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2010-11-15 20:58:27 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
cancelledWindowDrag(window) {
|
2014-09-03 19:55:05 +00:00
|
|
|
this.emit('window-drag-cancelled', window);
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-03-08 13:44:47 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
endWindowDrag(window) {
|
2017-11-16 16:27:12 +00:00
|
|
|
if (!this._inWindowDrag)
|
|
|
|
return;
|
2014-09-03 19:55:05 +00:00
|
|
|
this.emit('window-drag-end', window);
|
2017-11-16 16:27:12 +00:00
|
|
|
this._inWindowDrag = false;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2010-11-15 20:58:27 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
focusSearch() {
|
2013-05-17 15:31:27 +00:00
|
|
|
this.show();
|
2019-08-31 01:51:02 +00:00
|
|
|
this._overview.searchEntry.grab_key_focus();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2013-05-17 15:31:27 +00:00
|
|
|
|
2014-07-03 13:33:09 +00:00
|
|
|
// Checks if the Activities button is currently sensitive to
|
|
|
|
// clicks. The first call to this function within the
|
|
|
|
// OVERVIEW_ACTIVATION_TIMEOUT time of the hot corner being
|
|
|
|
// triggered will return false. This avoids opening and closing
|
|
|
|
// the overview if the user both triggered the hot corner and
|
|
|
|
// clicked the Activities button.
|
2017-10-31 00:03:21 +00:00
|
|
|
shouldToggleByCornerOrButton() {
|
2019-08-31 02:04:34 +00:00
|
|
|
if (this._animationInProgress)
|
2014-07-03 13:33:09 +00:00
|
|
|
return false;
|
2017-11-16 16:27:12 +00:00
|
|
|
if (this._inItemDrag || this._inWindowDrag)
|
2014-07-03 13:33:09 +00:00
|
|
|
return false;
|
2019-08-31 01:51:02 +00:00
|
|
|
if (!this._activationTime ||
|
2018-01-15 14:36:44 +00:00
|
|
|
GLib.get_monotonic_time() / GLib.USEC_PER_SEC - this._activationTime > OVERVIEW_ACTIVATION_TIMEOUT)
|
2014-07-03 13:33:09 +00:00
|
|
|
return true;
|
|
|
|
return false;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-07-03 13:33:09 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_syncGrab() {
|
2014-07-03 13:33:09 +00:00
|
|
|
// We delay grab changes during animation so that when removing the
|
|
|
|
// overview we don't have a problem with the release of a press/release
|
|
|
|
// going to an application.
|
2019-08-31 02:04:34 +00:00
|
|
|
if (this._animationInProgress)
|
2014-07-03 13:33:09 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
if (this._shown) {
|
|
|
|
let shouldBeModal = !this._inXdndDrag;
|
2019-08-20 02:25:24 +00:00
|
|
|
if (shouldBeModal && !this._modal) {
|
2022-09-29 12:23:31 +00:00
|
|
|
if (global.display.is_grabbed()) {
|
2022-04-26 11:09:01 +00:00
|
|
|
this.hide();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const grab = Main.pushModal(global.stage, {
|
|
|
|
actionMode: Shell.ActionMode.OVERVIEW,
|
|
|
|
});
|
2022-04-30 06:18:39 +00:00
|
|
|
if (grab.get_seat_state() !== Clutter.GrabState.ALL) {
|
2021-11-25 09:49:42 +00:00
|
|
|
Main.popModal(grab);
|
2019-08-20 02:25:24 +00:00
|
|
|
this.hide();
|
|
|
|
return false;
|
2014-07-03 13:33:09 +00:00
|
|
|
}
|
2022-04-30 06:18:39 +00:00
|
|
|
|
|
|
|
this._grab = grab;
|
|
|
|
this._modal = true;
|
2014-07-03 13:33:09 +00:00
|
|
|
}
|
|
|
|
} else {
|
2019-08-20 02:24:37 +00:00
|
|
|
// eslint-disable-next-line no-lonely-if
|
2014-07-03 13:33:09 +00:00
|
|
|
if (this._modal) {
|
2021-11-25 09:49:42 +00:00
|
|
|
Main.popModal(this._grab);
|
|
|
|
this._grab = false;
|
2014-07-03 13:33:09 +00:00
|
|
|
this._modal = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-07-03 13:33:09 +00:00
|
|
|
|
|
|
|
// show:
|
|
|
|
//
|
|
|
|
// Animates the overview visible and grabs mouse and keyboard input
|
2021-01-02 20:19:37 +00:00
|
|
|
show(state = OverviewControls.ControlsState.WINDOW_PICKER) {
|
|
|
|
if (state === OverviewControls.ControlsState.HIDDEN)
|
|
|
|
throw new Error('Invalid state, use hide() to hide');
|
|
|
|
|
2014-07-03 13:33:09 +00:00
|
|
|
if (this.isDummy)
|
|
|
|
return;
|
|
|
|
if (this._shown)
|
|
|
|
return;
|
|
|
|
this._shown = true;
|
|
|
|
|
|
|
|
if (!this._syncGrab())
|
|
|
|
return;
|
|
|
|
|
|
|
|
Main.layoutManager.showOverview();
|
2021-01-02 20:19:37 +00:00
|
|
|
this._animateVisible(state);
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-07-03 13:33:09 +00:00
|
|
|
|
|
|
|
|
2021-01-02 20:19:37 +00:00
|
|
|
_animateVisible(state) {
|
2019-08-31 02:04:34 +00:00
|
|
|
if (this._visible || this._animationInProgress)
|
2011-01-05 14:39:36 +00:00
|
|
|
return;
|
2008-11-28 20:12:20 +00:00
|
|
|
|
2019-08-31 02:04:34 +00:00
|
|
|
this._visible = true;
|
|
|
|
this._animationInProgress = true;
|
|
|
|
this._visibleTarget = true;
|
2018-01-15 14:36:44 +00:00
|
|
|
this._activationTime = GLib.get_monotonic_time() / GLib.USEC_PER_SEC;
|
2008-11-28 20:12:20 +00:00
|
|
|
|
2018-01-03 07:55:38 +00:00
|
|
|
Meta.disable_unredirect_for_display(global.display);
|
2010-07-15 14:21:32 +00:00
|
|
|
|
2019-11-05 19:17:19 +00:00
|
|
|
Main.layoutManager.overviewGroup.set_child_above_sibling(
|
|
|
|
this._coverPane, null);
|
2011-01-21 13:08:42 +00:00
|
|
|
this._coverPane.show();
|
2022-11-06 11:17:15 +00:00
|
|
|
|
|
|
|
this._overview.prepareToEnterOverview();
|
2022-03-16 21:36:49 +00:00
|
|
|
this._changeShownState(OverviewShownState.SHOWING);
|
2022-11-06 11:17:15 +00:00
|
|
|
this._overview.animateToOverview(state, () => this._showDone());
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2008-12-01 19:51:43 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_showDone() {
|
2019-08-31 02:04:34 +00:00
|
|
|
this._animationInProgress = false;
|
2014-07-03 13:33:09 +00:00
|
|
|
this._coverPane.hide();
|
|
|
|
|
2022-12-20 12:49:59 +00:00
|
|
|
if (this._shownState !== OverviewShownState.SHOWN)
|
|
|
|
this._changeShownState(OverviewShownState.SHOWN);
|
|
|
|
|
2014-07-03 13:33:09 +00:00
|
|
|
// Handle any calls to hide* while we were showing
|
|
|
|
if (!this._shown)
|
|
|
|
this._animateNotVisible();
|
|
|
|
|
|
|
|
this._syncGrab();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-07-03 13:33:09 +00:00
|
|
|
|
2011-01-05 14:39:36 +00:00
|
|
|
// hide:
|
|
|
|
//
|
|
|
|
// Reverses the effect of show()
|
2017-10-31 00:03:21 +00:00
|
|
|
hide() {
|
2011-08-28 14:24:48 +00:00
|
|
|
if (this.isDummy)
|
|
|
|
return;
|
|
|
|
|
2011-01-05 14:39:36 +00:00
|
|
|
if (!this._shown)
|
|
|
|
return;
|
|
|
|
|
2013-03-04 22:54:02 +00:00
|
|
|
let event = Clutter.get_current_event();
|
2013-03-14 15:34:09 +00:00
|
|
|
if (event) {
|
|
|
|
let type = event.type();
|
2023-08-07 00:51:19 +00:00
|
|
|
const button =
|
|
|
|
type === Clutter.EventType.BUTTON_PRESS ||
|
|
|
|
type === Clutter.EventType.BUTTON_RELEASE;
|
|
|
|
let ctrl = (event.get_state() & Clutter.ModifierType.CONTROL_MASK) !== 0;
|
2013-03-14 15:34:09 +00:00
|
|
|
if (button && ctrl)
|
|
|
|
return;
|
|
|
|
}
|
2013-02-21 14:57:00 +00:00
|
|
|
|
2011-01-05 14:39:36 +00:00
|
|
|
this._shown = false;
|
2014-11-27 02:05:36 +00:00
|
|
|
|
|
|
|
this._animateNotVisible();
|
2013-05-22 16:05:24 +00:00
|
|
|
this._syncGrab();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-01-05 14:39:36 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_animateNotVisible() {
|
2019-08-31 02:04:34 +00:00
|
|
|
if (!this._visible || this._animationInProgress)
|
2008-12-01 19:51:43 +00:00
|
|
|
return;
|
|
|
|
|
2019-08-31 02:04:34 +00:00
|
|
|
this._animationInProgress = true;
|
|
|
|
this._visibleTarget = false;
|
2010-07-15 14:21:32 +00:00
|
|
|
|
2019-11-05 19:17:19 +00:00
|
|
|
Main.layoutManager.overviewGroup.set_child_above_sibling(
|
|
|
|
this._coverPane, null);
|
2011-01-21 13:08:42 +00:00
|
|
|
this._coverPane.show();
|
2022-11-06 11:17:15 +00:00
|
|
|
|
|
|
|
this._overview.prepareToLeaveOverview();
|
2022-03-16 21:36:49 +00:00
|
|
|
this._changeShownState(OverviewShownState.HIDING);
|
2022-11-06 11:17:15 +00:00
|
|
|
this._overview.animateFromOverview(() => this._hideDone());
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2009-05-07 13:47:48 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_hideDone() {
|
2011-08-29 21:55:42 +00:00
|
|
|
// Re-enable unredirection
|
2018-01-03 07:55:38 +00:00
|
|
|
Meta.enable_unredirect_for_display(global.display);
|
2011-08-29 21:55:42 +00:00
|
|
|
|
2013-05-22 16:05:24 +00:00
|
|
|
this._coverPane.hide();
|
2009-03-20 16:06:34 +00:00
|
|
|
|
2019-08-31 02:04:34 +00:00
|
|
|
this._visible = false;
|
|
|
|
this._animationInProgress = false;
|
2008-12-01 19:51:43 +00:00
|
|
|
|
2011-01-05 14:39:36 +00:00
|
|
|
// Handle any calls to show* while we were hiding
|
2020-09-17 07:24:12 +00:00
|
|
|
if (this._shown) {
|
2022-03-16 21:36:49 +00:00
|
|
|
this._changeShownState(OverviewShownState.HIDDEN);
|
2021-03-16 12:51:05 +00:00
|
|
|
this._animateVisible(OverviewControls.ControlsState.WINDOW_PICKER);
|
2020-09-17 07:24:12 +00:00
|
|
|
} else {
|
2013-05-22 16:05:24 +00:00
|
|
|
Main.layoutManager.hideOverview();
|
2022-03-16 21:36:49 +00:00
|
|
|
this._changeShownState(OverviewShownState.HIDDEN);
|
2020-09-17 07:24:12 +00:00
|
|
|
}
|
2011-01-05 14:39:36 +00:00
|
|
|
|
2021-02-16 23:57:13 +00:00
|
|
|
Main.panel.style = null;
|
|
|
|
|
2013-05-22 16:05:24 +00:00
|
|
|
this._syncGrab();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-07-03 13:33:09 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
toggle() {
|
2014-07-03 13:33:09 +00:00
|
|
|
if (this.isDummy)
|
|
|
|
return;
|
|
|
|
|
2019-08-31 02:04:34 +00:00
|
|
|
if (this._visible)
|
2014-07-03 13:33:09 +00:00
|
|
|
this.hide();
|
|
|
|
else
|
|
|
|
this.show();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-06-17 17:10:54 +00:00
|
|
|
|
2021-01-02 20:28:44 +00:00
|
|
|
showApps() {
|
2021-03-14 11:07:31 +00:00
|
|
|
this.show(OverviewControls.ControlsState.APP_GRID);
|
2021-01-02 20:28:44 +00:00
|
|
|
}
|
|
|
|
|
2021-06-17 20:09:14 +00:00
|
|
|
selectApp(id) {
|
|
|
|
this.showApps();
|
|
|
|
this._overview.controls.appDisplay.selectApp(id);
|
|
|
|
}
|
|
|
|
|
2021-02-15 20:39:14 +00:00
|
|
|
runStartupAnimation(callback) {
|
2021-03-02 22:52:26 +00:00
|
|
|
Main.panel.style = 'transition-duration: 0ms;';
|
|
|
|
|
2021-02-15 20:39:14 +00:00
|
|
|
this._shown = true;
|
|
|
|
this._visible = true;
|
|
|
|
this._visibleTarget = true;
|
|
|
|
Main.layoutManager.showOverview();
|
2021-04-15 14:58:17 +00:00
|
|
|
// We should call this._syncGrab() here, but moved it to happen after
|
|
|
|
// the animation because of a race in the xserver where the grab
|
|
|
|
// fails when requested very early during startup.
|
2021-02-15 20:39:14 +00:00
|
|
|
|
|
|
|
Meta.disable_unredirect_for_display(global.display);
|
|
|
|
|
2022-03-16 21:36:49 +00:00
|
|
|
this._changeShownState(OverviewShownState.SHOWING);
|
2021-02-15 20:39:14 +00:00
|
|
|
|
|
|
|
this._overview.runStartupAnimation(() => {
|
2023-03-01 20:43:15 +00:00
|
|
|
// Overview got hidden during startup animation
|
|
|
|
if (this._shownState !== OverviewShownState.SHOWING) {
|
|
|
|
callback();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-15 14:58:17 +00:00
|
|
|
if (!this._syncGrab()) {
|
|
|
|
callback();
|
2023-03-01 20:48:45 +00:00
|
|
|
this.hide();
|
2021-04-15 14:58:17 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-02 22:52:26 +00:00
|
|
|
Main.panel.style = null;
|
2022-03-16 21:36:49 +00:00
|
|
|
this._changeShownState(OverviewShownState.SHOWN);
|
2021-02-15 20:39:14 +00:00
|
|
|
callback();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
getShowAppsButton() {
|
2019-08-31 01:51:02 +00:00
|
|
|
logError(new Error('Usage of Overview.\'getShowAppsButton\' is deprecated, ' +
|
|
|
|
'use \'dash.showAppsButton\' property instead'));
|
|
|
|
|
|
|
|
return this.dash.showAppsButton;
|
2008-12-01 19:51:43 +00:00
|
|
|
}
|
2020-01-09 20:44:22 +00:00
|
|
|
|
2023-06-01 22:54:59 +00:00
|
|
|
get searchController() {
|
|
|
|
return this._overview.searchController;
|
|
|
|
}
|
|
|
|
|
2020-01-09 20:44:22 +00:00
|
|
|
get searchEntry() {
|
|
|
|
return this._overview.searchEntry;
|
|
|
|
}
|
2023-07-10 09:53:00 +00:00
|
|
|
}
|