workspace: Simplify detecting added dialogs after closing a window

When trying to close a window in the overview by clicking the close
button and the window doesn't get closed but a dialog is added to the
window afterwards, we close the overview and show the dialog.

Instead of adding a separate listener for the window-added signal to the
WindowOverlay, let the WindowClones remember that the close button was
pressed and activate themselves if a dialog is added after that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/180
This commit is contained in:
verdre 2018-06-19 12:45:18 +02:00
parent 52cbc299a7
commit da2fc2c9d3

View File

@ -179,6 +179,7 @@ var WindowClone = new Lang.Class({
this.inDrag = false; this.inDrag = false;
this._selected = false; this._selected = false;
this._closeRequested = false;
}, },
set slot(slot) { set slot(slot) {
@ -194,7 +195,6 @@ var WindowClone = new Lang.Class({
deleteAll() { deleteAll() {
// Delete all windows, starting from the bottom-most (most-modal) one // Delete all windows, starting from the bottom-most (most-modal) one
let windows = this.actor.get_children(); let windows = this.actor.get_children();
for (let i = windows.length - 1; i >= 1; i--) { for (let i = windows.length - 1; i >= 1; i--) {
let realWindow = windows[i].source; let realWindow = windows[i].source;
@ -204,11 +204,24 @@ var WindowClone = new Lang.Class({
} }
this.metaWindow.delete(global.get_current_time()); this.metaWindow.delete(global.get_current_time());
this._closeRequested = true;
}, },
addAttachedDialog(win) { addDialog(win) {
this._doAddAttachedDialog(win, win.get_compositor_private()); let parent = win.get_transient_for();
this._onMetaWindowSizeChanged(); while (parent.is_attached_dialog())
parent = parent.get_transient_for();
// Display dialog if it is attached to our metaWindow
if (win.is_attached_dialog() && parent == this.metaWindow) {
this._doAddAttachedDialog(win, win.get_compositor_private());
this._onMetaWindowSizeChanged();
}
// The dialog popped up after the user tried to close the window,
// assume it's a close confirmation and leave the overview
if (this._closeRequested)
this._activate();
}, },
hasAttachedDialogs() { hasAttachedDialogs() {
@ -462,14 +475,12 @@ var WindowOverlay = new Lang.Class({
button._overlap = 0; button._overlap = 0;
this._idleToggleCloseId = 0; this._idleToggleCloseId = 0;
button.connect('clicked', this._closeWindow.bind(this)); button.connect('clicked', () => this._windowClone.deleteAll());
windowClone.actor.connect('destroy', this._onDestroy.bind(this)); windowClone.actor.connect('destroy', this._onDestroy.bind(this));
windowClone.connect('show-chrome', this._onShowChrome.bind(this)); windowClone.connect('show-chrome', this._onShowChrome.bind(this));
windowClone.connect('hide-chrome', this._onHideChrome.bind(this)); windowClone.connect('hide-chrome', this._onHideChrome.bind(this));
this._windowAddedId = 0;
button.hide(); button.hide();
title.hide(); title.hide();
@ -590,43 +601,12 @@ var WindowOverlay = new Lang.Class({
Tweener.addTween(actor, params); Tweener.addTween(actor, params);
}, },
_closeWindow(actor) {
let metaWindow = this._windowClone.metaWindow;
this._workspace = metaWindow.get_workspace();
this._windowAddedId = this._workspace.connect('window-added',
this._onWindowAdded.bind(this));
this._windowClone.deleteAll();
},
_windowCanClose() { _windowCanClose() {
return this._windowClone.metaWindow.can_close() && return this._windowClone.metaWindow.can_close() &&
!this._windowClone.hasAttachedDialogs(); !this._windowClone.hasAttachedDialogs();
}, },
_onWindowAdded(workspace, win) {
let metaWindow = this._windowClone.metaWindow;
if (win.get_transient_for() == metaWindow) {
workspace.disconnect(this._windowAddedId);
this._windowAddedId = 0;
// use an idle handler to avoid mapping problems -
// see comment in Workspace._windowAdded
let id = Mainloop.idle_add(() => {
this._windowClone.emit('selected');
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(id, '[gnome-shell] this._windowClone.emit');
}
},
_onDestroy() { _onDestroy() {
if (this._windowAddedId > 0) {
this._workspace.disconnect(this._windowAddedId);
this._windowAddedId = 0;
}
if (this._idleToggleCloseId > 0) { if (this._idleToggleCloseId > 0) {
Mainloop.source_remove(this._idleToggleCloseId); Mainloop.source_remove(this._idleToggleCloseId);
this._idleToggleCloseId = 0; this._idleToggleCloseId = 0;
@ -1516,21 +1496,17 @@ var Workspace = new Lang.Class({
return; return;
if (!this._isOverviewWindow(win)) { if (!this._isOverviewWindow(win)) {
if (metaWin.is_attached_dialog()) { if (metaWin.get_transient_for() == null)
let parent = metaWin.get_transient_for(); return;
while (parent.is_attached_dialog())
parent = parent.get_transient_for();
let idx = this._lookupIndex (parent); // Let the top-most ancestor handle all transients
if (idx < 0) { let parent = metaWin.find_root_ancestor();
// parent was not created yet, it will take care let clone = this._windows.find(c => c.metaWindow == parent);
// of the dialog when created
return;
}
let clone = this._windows[idx]; // If no clone was found, the parent hasn't been created yet
clone.addAttachedDialog(metaWin); // and will take care of the dialog when added
} if (clone)
clone.addDialog(metaWin);
return; return;
} }