[gnome-shell/T27795: 37/138] sideComponent: Add SideComponent back
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/T27795: 37/138] sideComponent: Add SideComponent back
- Date: Tue, 1 Oct 2019 23:32:26 +0000 (UTC)
commit aca373dd4837d0fe1b9a9a36fde02aec2c1c14d0
Author: Sam Spilsbury <sam endlessm com>
Date: Sun May 28 04:59:48 2017 +0800
sideComponent: Add SideComponent back
This is used by the website panel, the discovery feed and Hack.
2019-09-23: replace Tweener by Clutter implicit animations
https://phabricator.endlessm.com/T2519
https://phabricator.endlessm.com/T16876
https://phabricator.endlessm.com/T18137
https://phabricator.endlessm.com/T18601
js/js-resources.gresource.xml | 1 +
js/ui/layout.js | 23 ++-
js/ui/overview.js | 12 ++
js/ui/sideComponent.js | 148 +++++++++++++++
js/ui/windowManager.js | 429 +++++++++++++++++++++++++++++++++++++++++-
src/shell-window-tracker.c | 8 +
6 files changed, 619 insertions(+), 2 deletions(-)
---
diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
index b59be3806b..36a909d497 100644
--- a/js/js-resources.gresource.xml
+++ b/js/js-resources.gresource.xml
@@ -147,5 +147,6 @@
<file>ui/forceAppExitDialog.js</file>
<file>ui/hotCorner.js</file>
<file>ui/monitor.js</file>
+ <file>ui/sideComponent.js</file>
</gresource>
</gresources>
diff --git a/js/ui/layout.js b/js/ui/layout.js
index f507cb0deb..cfbb0234ca 100644
--- a/js/ui/layout.js
+++ b/js/ui/layout.js
@@ -63,7 +63,8 @@ const defaultParams = {
};
var LayoutManager = GObject.registerClass({
- Signals: { 'hot-corners-changed': {},
+ Signals: { 'background-clicked': {},
+ 'hot-corners-changed': {},
'startup-complete': {},
'startup-prepared': {},
'monitors-changed': {},
@@ -84,6 +85,7 @@ var LayoutManager = GObject.registerClass({
this._inOverview = false;
this._updateRegionIdle = 0;
+ this._overlayRegion = null;
this._trackedActors = [];
this._topActors = [];
this._isPopupWindowVisible = false;
@@ -730,6 +732,11 @@ var LayoutManager = GObject.registerClass({
this._trackActor(actor, params);
}
+ setOverlayRegion(region) {
+ this._overlayRegion = region;
+ this._queueUpdateRegions();
+ }
+
// addTopChrome:
// @actor: an actor to add to the chrome
// @params: (optional) additional params
@@ -991,6 +998,20 @@ var LayoutManager = GObject.registerClass({
}
}
+ if (this._overlayRegion != null) {
+ let numOverlayRects = this._overlayRegion.numRectangles();
+ for (let idx = 0; idx < numOverlayRects; idx++) {
+ let rect = this._overlayRegion.getRectangle(idx);
+ let metaRect = new Meta.Rectangle({
+ x: rect.x,
+ y: rect.y,
+ width: rect.width,
+ height: rect.height,
+ });
+ rects.push(metaRect);
+ }
+ }
+
global.set_stage_input_region(rects);
this._isPopupWindowVisible = isPopupMenuVisible;
diff --git a/js/ui/overview.js b/js/ui/overview.js
index 97e5d58207..492c3e7315 100644
--- a/js/ui/overview.js
+++ b/js/ui/overview.js
@@ -250,6 +250,7 @@ var Overview = class {
this.dashIconSize = this._dash.iconSize;
});
+ this.viewSelector.connect('page-changed', this._onPageChanged.bind(this));
Main.layoutManager.connect('monitors-changed', this._relayout.bind(this));
this._relayout();
}
@@ -274,6 +275,13 @@ var Overview = class {
this._shellInfo.setMessage(text, options);
}
+ _onPageChanged() {
+ // SideComponent hooks on this signal but can't connect directly to
+ // viewSelector since it won't be created at the time the component
+ // is enabled, so rely on the overview and re-issue it from here.
+ this.emit('page-changed');
+ }
+
_onDragBegin() {
this._inXdndDrag = true;
@@ -641,6 +649,10 @@ var Overview = class {
this.show();
}
+ getActivePage() {
+ return this.viewSelector.getActivePage();
+ }
+
getShowAppsButton() {
return this._dash.showAppsButton;
}
diff --git a/js/ui/sideComponent.js b/js/ui/sideComponent.js
new file mode 100644
index 0000000000..97f3fb5b54
--- /dev/null
+++ b/js/ui/sideComponent.js
@@ -0,0 +1,148 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+const { Gio, GLib, GObject, Meta } = imports.gi;
+
+const Main = imports.ui.main;
+const ViewSelector = imports.ui.viewSelector;
+
+const SIDE_COMPONENT_ROLE = 'eos-side-component';
+
+/**
+ * isSideComponentWindow:
+ * @metaWindow: an instance of #Meta.Window
+ * @return: whether the #Meta.Window belongs to a #SideComponent
+ */
+function isSideComponentWindow (metaWindow) {
+ return metaWindow && (metaWindow.get_role() == SIDE_COMPONENT_ROLE);
+};
+
+/**
+ * shouldHideOtherWindows:
+ * @metaWindow: an instance of #Meta.Window
+ * @return: whether other windows should be hidden while this one is open
+ */
+function shouldHideOtherWindows (metaWindow) {
+ return isSideComponentWindow(metaWindow);
+};
+
+/**
+ * launchedFromDesktop:
+ * @metaWindow: an instance of #Meta.Window
+ * @return: whether the side component was launched from the desktop
+ */
+function launchedFromDesktop (metaWindow) {
+ return false;
+};
+
+var SideComponent = GObject.registerClass(
+class SideComponent extends GObject.Object {
+ _init(proxyIface, proxyName, proxyPath) {
+ super._init();
+ this._propertiesChangedId = 0;
+ this._desktopShownId = 0;
+
+ this._proxyIface = proxyIface;
+ this._proxyInfo = Gio.DBusInterfaceInfo.new_for_xml(this._proxyIface);
+ this._proxyName = proxyName;
+ this._proxyPath = proxyPath;
+
+ this._visible = false;
+ this._launchedFromDesktop = false;
+ }
+
+ enable() {
+ if (!this.proxy) {
+ this.proxy = new Gio.DBusProxy({ g_connection: Gio.DBus.session,
+ g_interface_name: this._proxyInfo.name,
+ g_interface_info: this._proxyInfo,
+ g_name: this._proxyName,
+ g_object_path: this._proxyPath,
+ g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START_AT_CONSTRUCTION
});
+ this.proxy.init_async(GLib.PRIORITY_DEFAULT, null, this._onProxyConstructed.bind(this));
+ }
+
+ this._propertiesChangedId =
+ this.proxy.connect('g-properties-changed', this._onPropertiesChanged.bind(this));
+
+ // Clicking the background (which calls overview.showApps) hides the component,
+ // so trying to open it again will call WindowManager._mapWindow(),
+ // which will hide the overview and animate the window.
+ // Note that this is not the case when opening the window picker.
+ this._desktopShownId = Main.layoutManager.connect('background-clicked', () => {
+ if (this._visible)
+ this.hide(global.get_current_time());
+ });
+
+ // Same when clicking the background from the window picker.
+ this._overviewPageChangedId = Main.overview.connect('page-changed', () => {
+ if (this._visible && Main.overview.visible &&
+ Main.overview.getActivePage() == ViewSelector.ViewPage.APPS)
+ this.hide(global.get_current_time());
+ });
+ }
+
+ disable() {
+ if (this._propertiesChangedId > 0) {
+ this.proxy.disconnect(this._propertiesChangedId);
+ this._propertiesChangedId = 0;
+ }
+
+ if (this._desktopShownId > 0) {
+ Main.layoutManager.disconnect(this._desktopShownId);
+ this._desktopShownId = 0;
+ }
+
+ if (this._overviewPageChangedId > 0) {
+ Main.overview.disconnect(this._overviewPageChangedId);
+ this._overviewPageChangedId = 0;
+ }
+ }
+
+ _onProxyConstructed(object, res) {
+ try {
+ object.init_finish(res);
+ } catch (e) {
+ logError(e, 'Error while constructing the DBus proxy for ' + this._proxyName);
+ }
+ }
+
+ _onPropertiesChanged(proxy, changedProps, invalidatedProps) {
+ let propsDict = changedProps.deep_unpack();
+ if (propsDict.hasOwnProperty('Visible'))
+ this._onVisibilityChanged();
+ }
+
+ _onVisibilityChanged() {
+ if (this._visible == this.proxy.Visible)
+ return;
+
+ // resync visibility
+ this._visible = this.proxy.Visible;
+ }
+
+ toggle(timestamp, params) {
+ if (this._visible)
+ this.hide(timestamp, params);
+ else
+ this.show(timestamp, params);
+ }
+
+ show(timestamp, params) {
+ this._launchedFromDesktop = Main.overview.visible &&
+ Main.overview.getActivePage() == ViewSelector.ViewPage.APPS;
+
+ if (this._visible && Main.overview.visible)
+ // the component is already open, but obscured by the overview
+ Main.overview.hide();
+ else
+ this.callShow(timestamp, params);
+ }
+
+ hide(timestamp, params) {
+ this.callHide(timestamp, params);
+ }
+
+ get launchedFromDesktop() {
+ return this._launchedFromDesktop;
+ }
+});
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index d0917f61fa..58707c155a 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -1,7 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported WindowManager */
-const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
+const { Clutter, Gdk, Gio, GLib,
+ GObject, Meta, Shell, St } = imports.gi;
+const Cairo = imports.cairo;
const Signals = imports.signals;
const AltTab = imports.ui.altTab;
@@ -18,6 +20,8 @@ const EdgeDragAction = imports.ui.edgeDragAction;
const CloseDialog = imports.ui.closeDialog;
const SwitchMonitor = imports.ui.switchMonitor;
const IBusManager = imports.misc.ibusManager;
+const SideComponent = imports.ui.sideComponent;
+const BackgroundMenu = imports.ui.backgroundMenu;
const { loadInterfaceXML } = imports.misc.fileUtils;
@@ -694,6 +698,264 @@ var ResizePopup = class {
}
};
+var DesktopOverlay = GObject.registerClass({
+ Signals: { 'clicked': {} },
+}, class DesktopOverlay extends St.Widget {
+ _init() {
+ super._init({ reactive: true });
+
+ this._shellwm = global.window_manager;
+
+ this._actorDestroyId = 0;
+ this._allocationId = 0;
+ this._destroyId = 0;
+ this._mapId = 0;
+ this._visibleId = 0;
+ this._showing = false;
+
+ this._overlayActor = null;
+ this._transientActors = [];
+
+ let action = new Clutter.ClickAction();
+ action.connect('clicked', action => {
+ if (action.get_button() != Gdk.BUTTON_PRIMARY)
+ return;
+
+ if (this._showing && this._overlayActor)
+ this.emit('clicked');
+ });
+ this.add_action(action);
+ BackgroundMenu.addBackgroundMenu(this, Main.layoutManager);
+
+ Main.overview.connect('showing', () => {
+ // hide the overlay so it doesn't conflict with the desktop
+ if (this._showing)
+ this.hide();
+ });
+ Main.overview.connect('hiding', () => {
+ // show the overlay if needed
+ if (this._showing)
+ this.show();
+ });
+
+ Main.uiGroup.add_actor(this);
+ if (Main.uiGroup.contains(global.top_window_group))
+ Main.uiGroup.set_child_below_sibling(this, global.top_window_group);
+ }
+
+ _rebuildRegion() {
+ if (!this._overlayActor.get_paint_visibility()) {
+ Main.layoutManager.setOverlayRegion(null);
+ return;
+ }
+
+ let overlayWindow = this._overlayActor.meta_window;
+ let monitorIdx = overlayWindow.get_monitor();
+ let monitor = Main.layoutManager.monitors[monitorIdx];
+ if (!monitor)
+ return;
+
+ let workArea = Main.layoutManager.getWorkAreaForMonitor(overlayWindow.get_monitor());
+ let region = new Cairo.Region();
+ region.unionRectangle(workArea);
+
+ let [x, y] = this._overlayActor.get_transformed_position();
+ let [width, height] = this._overlayActor.get_transformed_size();
+ let rect = {
+ x: Math.round(x),
+ y: Math.round(y),
+ width: Math.round(width),
+ height: Math.round(height),
+ };
+
+ region.subtractRectangle(rect);
+
+ this._transientActors.forEach(actorData => {
+ let transientActor = actorData.actor;
+
+ let [x, y] = transientActor.get_transformed_position();
+ let [width, height] = transientActor.get_transformed_size();
+ let rect = {
+ x: Math.round(x),
+ y: Math.round(y),
+ width: Math.round(width),
+ height: Math.round(height),
+ };
+
+ region.subtractRectangle(rect);
+ });
+
+ Main.layoutManager.setOverlayRegion(region);
+ }
+
+ _repositionOverlay() {
+ let overlayWindow = this._overlayActor.meta_window;
+ let monitorIdx = overlayWindow.get_monitor();
+ let monitor = Main.layoutManager.monitors[monitorIdx];
+ if (!monitor)
+ return;
+
+ // The width and height of the overlay need to be the width and height
+ // of the workArea. We already capture inputs correctly
+ // outside the overlay window by setting the region of the
+ // layoutManager overlay, so it is safe to just take up the
+ // entire workArea.
+ let workArea = Main.layoutManager.getWorkAreaForMonitor(monitorIdx);
+ this.width = workArea.width;
+ this.height = workArea.height;
+ this.y = this._overlayActor.y;
+
+ if (this._overlayActor.x <= monitor.x)
+ this.x = monitor.x + monitor.width - this.width;
+ else
+ this.x = monitor.x;
+ }
+
+ _recalculateOverlay() {
+ this._repositionOverlay();
+ this._rebuildRegion();
+ }
+
+ _findTransientActor(actor) {
+ for (let i = 0; i < this._transientActors.length; i++) {
+ let actorData = this._transientActors[i];
+ if (actorData.actor == actor)
+ return i;
+ }
+ return -1;
+ }
+
+ _untrackTransientActor(actor) {
+ let idx = this._findTransientActor(actor);
+ if (idx == -1) {
+ log('Trying to untrack a non-tracked transient actor!');
+ return;
+ }
+
+ let actorData = this._transientActors[idx];
+ this._transientActors.splice(idx, 1);
+
+ actor.disconnect(actorData.visibleId);
+ actor.disconnect(actorData.allocationId);
+ actor.disconnect(actorData.destroyId);
+
+ this._rebuildRegion();
+ }
+
+ _trackTransientActor(actor) {
+ if (this._findTransientActor(actor) != -1) {
+ log('Trying to track twice the same transient actor!');
+ return;
+ }
+
+ let actorData = {};
+ actorData.actor = actor;
+ actorData.visibleId = actor.connect(
+ 'notify::visible', this._recalculateOverlay.bind(this));
+ actorData.allocationId = actor.connect(
+ 'notify::allocation', this._recalculateOverlay.bind(this));
+ actorData.destroyId = actor.connect(
+ 'destroy', this._untrackTransientActor.bind(this));
+
+ this._transientActors.push(actorData);
+ this._recalculateOverlay();
+ }
+
+ _untrackActor() {
+ this._transientActors.forEach((actorData) => {
+ this._untrackTransientActor(actorData.actor);
+ });
+ this._transientActors = [];
+
+ if (this._visibleId > 0) {
+ this._overlayActor.disconnect(this._visibleId);
+ this._visibleId = 0;
+ }
+
+ if (this._allocationId > 0) {
+ this._overlayActor.disconnect(this._allocationId);
+ this._allocationId = 0;
+ }
+
+ if (this._actorDestroyId > 0) {
+ this._overlayActor.disconnect(this._actorDestroyId);
+ this._actorDestroyId = 0;
+ }
+
+ if (this._destroyId > 0) {
+ this._shellwm.disconnect(this._destroyId);
+ this._destroyId = 0;
+ }
+
+ if (this._mapId > 0) {
+ this._shellwm.disconnect(this._mapId);
+ this._mapId = 0;
+ }
+
+ Main.layoutManager.setOverlayRegion(null);
+ }
+
+ _trackActor() {
+ let overlayWindow = this._overlayActor.meta_window;
+
+ this._visibleId = this._overlayActor.connect(
+ 'notify::visible', this._recalculateOverlay.bind(this));
+ this._allocationId = this._overlayActor.connect(
+ 'notify::allocation', this._recalculateOverlay.bind(this));
+ this._actorDestroyId = this._overlayActor.connect(
+ 'destroy', this._untrackActor.bind(this));
+
+ this._mapId = this._shellwm.connect('map', (shellwm, actor) => {
+ let newWindow = actor.meta_window;
+ if (overlayWindow.is_ancestor_of_transient(newWindow))
+ this._trackTransientActor(actor);
+ });
+ this._destroyId = this._shellwm.connect('destroy', (shellwm, actor) => {
+ let destroyedWindow = actor.meta_window;
+ if (overlayWindow.is_ancestor_of_transient(destroyedWindow))
+ this._untrackTransientActor(actor);
+ });
+
+ // seed the transient actors
+ overlayWindow.foreach_transient((transientWindow) => {
+ let transientActor = overlayWindow.get_compositor_private();
+ if (transientActor != null)
+ this._trackTransientActor(transientActor);
+ });
+
+ this._recalculateOverlay();
+ }
+
+ _setOverlayActor(actor) {
+ if (actor == this._overlayActor)
+ return;
+
+ this._untrackActor();
+ this._overlayActor = actor;
+
+ if (this._overlayActor)
+ this._trackActor();
+ }
+
+ get overlayActor() {
+ return this._overlayActor;
+ }
+
+ showOverlay(actor) {
+ this._setOverlayActor(actor);
+
+ this._showing = true;
+ this.show();
+ }
+
+ hideOverlay() {
+ this._setOverlayActor(null);
+
+ this._showing = false;
+ this.hide();
+ }
+});
+
var WindowManager = class {
constructor() {
this._shellwm = global.window_manager;
@@ -711,6 +973,17 @@ var WindowManager = class {
this._allowedKeybindings = {};
+ this._desktopOverlay = new DesktopOverlay();
+ this._showDesktopOnDestroyDone = false;
+
+ // The desktop overlay needs to replicate the background's functionality;
+ // when clicked, we animate the side component out before emitting "background-clicked".
+ this._desktopOverlay.connect('clicked', () => {
+ this._slideSideComponentOut(this._shellwm,
+ this._desktopOverlay.overlayActor,
+ () => Main.layoutManager.emit('background-clicked'));
+ });
+
this._isWorkspacePrepended = false;
this._switchData = null;
@@ -1262,6 +1535,11 @@ var WindowManager = class {
if (this._removeEffect(this._skippedActors, actor))
return false;
+ // We should always animate side component windows in, even
+ // if the overview is visible
+ if (SideComponent.isSideComponentWindow(actor.meta_window))
+ return true;
+
if (!this._shouldAnimate())
return false;
@@ -1281,6 +1559,30 @@ var WindowManager = class {
return false;
}
+ _slideSideComponentOut(shellwm, actor, onComplete) {
+ let monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()];
+ if (!monitor) {
+ onComplete.apply(this, [shellwm, actor]);
+ return;
+ }
+
+ actor.opacity = 255;
+ actor.show();
+
+ let endX;
+ if (actor.x <= monitor.x)
+ endX = monitor.x - actor.width;
+ else
+ endX = monitor.x + monitor.width;
+
+ actor.ease({
+ x: endX,
+ duration: WINDOW_ANIMATION_TIME,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ onComplete: () => onComplete(shellwm, actor),
+ });
+ }
+
_minimizeWindow(shellwm, actor) {
let types = [Meta.WindowType.NORMAL,
Meta.WindowType.MODAL_DIALOG,
@@ -1609,6 +1911,86 @@ var WindowManager = class {
dimmer.setDimmed(false, this._shouldAnimate());
}
+ _hideOtherWindows(actor, animate) {
+ let winActors = global.get_window_actors();
+ for (let winActor of winActors) {
+ if (!winActor.get_meta_window().showing_on_its_workspace())
+ continue;
+
+ if (SideComponent.isSideComponentWindow(winActor.meta_window))
+ continue;
+
+ if (animate) {
+ winActor.ease({
+ opacity: 0,
+ duration: WINDOW_ANIMATION_TIME,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ onComplete: winActor => winActor.hide(),
+ });
+ } else {
+ winActor.opacity = 0;
+ winActor.hide();
+ }
+ }
+
+ this._desktopOverlay.showOverlay(actor);
+ }
+
+ _showOtherWindows(actor, animate) {
+ let winActors = global.get_window_actors();
+ for (let winActor of winActors) {
+ if (!winActor.get_meta_window().showing_on_its_workspace())
+ continue;
+
+ if (SideComponent.isSideComponentWindow(winActor.meta_window))
+ continue;
+
+ if (animate && winActor.opacity != 255) {
+ winActor.show();
+ winActor.ease({
+ opacity: 255,
+ duration: WINDOW_ANIMATION_TIME,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ });
+ } else {
+ winActor.opacity = 255;
+ winActor.show();
+ }
+ }
+
+ this._desktopOverlay.hideOverlay();
+ }
+
+ _mapSideComponent(shellwm, actor, animateFade) {
+ let monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()];
+ if (!monitor) {
+ this._mapWindowDone(shellwm, actor);
+ return;
+ }
+
+ let origX = actor.x;
+ if (origX == monitor.x) {
+ // the side bar will appear from the left side
+ actor.set_position(monitor.x - actor.width, actor.y);
+ } else {
+ // ... from the right side
+ actor.set_position(monitor.x + monitor.width, actor.y);
+ }
+
+ actor.ease({
+ x: origX,
+ duration: WINDOW_ANIMATION_TIME,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ onComplete: this._mapWindowDone.bind(this),
+ });
+
+ actor.opacity = 255;
+ actor.show();
+
+ if (SideComponent.shouldHideOtherWindows(actor.meta_window))
+ this._hideOtherWindows(actor, animateFade);
+ }
+
_mapWindow(shellwm, actor) {
actor._windowType = actor.meta_window.get_window_type();
actor._notifyWindowTypeSignalId =
@@ -1654,10 +2036,28 @@ var WindowManager = class {
Meta.WindowType.DIALOG,
Meta.WindowType.MODAL_DIALOG];
if (!this._shouldAnimateActor(actor, types)) {
+ if (SideComponent.shouldHideOtherWindows(actor.meta_window))
+ this._showOtherWindows(actor, false);
+
shellwm.completed_map(actor);
return;
}
+ if (SideComponent.isSideComponentWindow(actor.meta_window)) {
+ this._mapping.push(actor);
+
+ if (Main.overview.visible) {
+ let overviewHiddenId = Main.overview.connect('hidden', () => {
+ Main.overview.disconnect(overviewHiddenId);
+ this._mapSideComponent(shellwm, actor, false);
+ });
+ Main.overview.hide();
+ } else {
+ this._mapSideComponent(shellwm, actor, true);
+ }
+ return;
+ }
+
switch (actor._windowType) {
case Meta.WindowType.NORMAL:
actor.set_pivot_point(0.5, 1.0);
@@ -1749,6 +2149,25 @@ var WindowManager = class {
return;
}
+ if (SideComponent.isSideComponentWindow(actor.meta_window)) {
+ this._destroying.push(actor);
+ this._slideSideComponentOut(shellwm, actor,
+ this._destroyWindowDone.bind(this));
+
+ // if the side component does not have the focus at this point,
+ // that means that it is closing because another window has gotten it
+ // and therefore we should not try to show the desktop
+ this._showDesktopOnDestroyDone = actor.meta_window.has_focus() &&
+ SideComponent.launchedFromDesktop(actor.meta_window);
+
+ if (!this._showDesktopOnDestroyDone && SideComponent.shouldHideOtherWindows(actor.meta_window)) {
+ // reveal other windows while we slide out the side component
+ this._showOtherWindows(actor, true);
+ }
+
+ return;
+ }
+
switch (actor.meta_window.window_type) {
case Meta.WindowType.NORMAL:
actor.set_pivot_point(0.5, 0.5);
@@ -1795,6 +2214,14 @@ var WindowManager = class {
parent.disconnect(actor._parentDestroyId);
actor._parentDestroyId = 0;
}
+
+ if (SideComponent.isSideComponentWindow(actor.meta_window) && this._showDesktopOnDestroyDone) {
+ Main.overview.showApps();
+
+ if (SideComponent.shouldHideOtherWindows(actor.meta_window))
+ this._showOtherWindows(actor, false);
+ }
+
shellwm.completed_destroy(actor);
}
}
diff --git a/src/shell-window-tracker.c b/src/shell-window-tracker.c
index 16abd42673..a75e728ebb 100644
--- a/src/shell-window-tracker.c
+++ b/src/shell-window-tracker.c
@@ -24,6 +24,7 @@
* Copyright Red Hat, Inc. 2006-2008
*/
+#define SIDE_COMPONENT_ROLE "eos-side-component"
#define SPEEDWAGON_ROLE "eos-speedwagon"
/**
@@ -372,6 +373,10 @@ get_app_for_window (ShellWindowTracker *tracker,
MetaWindow *transient_for;
const char *startup_id;
+ /* Side components don't have an associated app */
+ if (g_strcmp0 (meta_window_get_role (window), SIDE_COMPONENT_ROLE) == 0)
+ return NULL;
+
transient_for = meta_window_get_transient_for (window);
if (transient_for != NULL)
return get_app_for_window (tracker, transient_for);
@@ -821,6 +826,9 @@ shell_window_tracker_get_startup_sequences (ShellWindowTracker *self)
gboolean
shell_window_tracker_is_window_interesting (MetaWindow *window)
{
+ if (g_strcmp0 (meta_window_get_role (window), SIDE_COMPONENT_ROLE) == 0)
+ return TRUE;
+
if (meta_window_is_skip_taskbar (window))
return FALSE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]