summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiovanni Campagna <gcampagna@src.gnome.org>2012-11-24 18:49:59 +0100
committerGiovanni Campagna <gcampagna@src.gnome.org>2013-03-04 17:50:18 +0100
commit6d4ca1fcc81739830933bff941cb5e108302ea68 (patch)
tree539d99904df37f1f1a285f6ddb44d58078f037e0
parent93b1af401f19e944d370347059cfed86935e43e6 (diff)
downloadgnome-shell-wip/gcampax/modal-dialogs.tar.gz
WorkspaceThumbnails: show attached modal dialogs togheter with their parentswip/gcampax/modal-dialogs
The window clones in the central part of the overview are showing modal dialogs now, and this creates an inconsistency if the thumbnail doesn't too. Code is intentionally similar in the two places. https://bugzilla.gnome.org/show_bug.cgi?id=650843
-rw-r--r--js/ui/workspaceThumbnail.js130
1 files changed, 113 insertions, 17 deletions
diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js
index 540f3d30d..ccdb96b05 100644
--- a/js/ui/workspaceThumbnail.js
+++ b/js/ui/workspaceThumbnail.js
@@ -13,6 +13,7 @@ const Background = imports.ui.background;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
+const WindowManager = imports.ui.windowManager;
const Workspace = imports.ui.workspace;
const WorkspacesView = imports.ui.workspacesView;
@@ -31,20 +32,49 @@ const WORKSPACE_KEEP_ALIVE_TIME = 100;
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
+/* A layout manager that requests size only for primary_actor, but then allocates
+ all using a fixed layout */
+const PrimaryActorLayout = new Lang.Class({
+ Name: 'PrimaryActorLayout',
+ Extends: Clutter.FixedLayout,
+
+ _init: function(primaryActor) {
+ this.parent();
+
+ this.primaryActor = primaryActor;
+ },
+
+ vfunc_get_preferred_width: function(forHeight) {
+ return this.primaryActor.get_preferred_width(forHeight);
+ },
+
+ vfunc_get_preferred_height: function(forWidth) {
+ return this.primaryActor.get_preferred_height(forWidth);
+ },
+});
+
const WindowClone = new Lang.Class({
Name: 'WindowClone',
_init : function(realWindow) {
- this.actor = new Clutter.Clone({ source: realWindow.get_texture(),
+ this.clone = new Clutter.Clone({ source: realWindow });
+
+ /* Can't use a Shell.GenericContainer because of DND and reparenting... */
+ this.actor = new Clutter.Actor({ layout_manager: new PrimaryActorLayout(this.clone),
reactive: true });
this.actor._delegate = this;
+ this.actor.add_child(this.clone);
this.realWindow = realWindow;
this.metaWindow = realWindow.meta_window;
- this._positionChangedId = this.realWindow.connect('position-changed',
- Lang.bind(this, this._onPositionChanged));
- this._realWindowDestroyedId = this.realWindow.connect('destroy',
- Lang.bind(this, this._disconnectRealWindowSignals));
+ this.clone._updateId = this.realWindow.connect('position-changed',
+ Lang.bind(this, this._onPositionChanged));
+ this.clone._destroyId = this.realWindow.connect('destroy', Lang.bind(this, function() {
+ // First destroy the clone and then destroy everything
+ // This will ensure that we never see it in the _disconnectSignals loop
+ this.clone.destroy();
+ this.destroy();
+ }));
this._onPositionChanged();
this.actor.connect('button-release-event',
@@ -60,6 +90,24 @@ const WindowClone = new Lang.Class({
this._draggable.connect('drag-cancelled', Lang.bind(this, this._onDragCancelled));
this._draggable.connect('drag-end', Lang.bind(this, this._onDragEnd));
this.inDrag = false;
+
+ let iter = Lang.bind(this, function(win) {
+ let actor = win.get_compositor_private();
+
+ if (!actor)
+ return false;
+ if (!win.is_attached_dialog())
+ return false;
+
+ this._doAddAttachedDialog(win, actor);
+ win.foreach_transient(iter);
+
+ return true;
+ });
+ this.metaWindow.foreach_transient(iter);
+
+ this._dimmer = new WindowManager.WindowDimmer(this.clone);
+ this._updateDimmer();
},
setStackAbove: function (actor) {
@@ -74,25 +122,57 @@ const WindowClone = new Lang.Class({
this.actor.destroy();
},
+ addAttachedDialog: function(win) {
+ this._doAddAttachedDialog(win, win.get_compositor_private());
+ this._updateDimmer();
+ },
+
+ _doAddAttachedDialog: function(metaDialog, realDialog) {
+ let clone = new Clutter.Clone({ source: realDialog });
+ this._updateDialogPosition(realDialog, clone);
+
+ clone._updateId = realDialog.connect('position-changed',
+ Lang.bind(this, this._updateDialogPosition, clone));
+ clone._destroyId = realDialog.connect('destroy', Lang.bind(this, function() {
+ clone.destroy();
+ this._updateDimmer();
+ }));
+ this.actor.add_child(clone);
+ },
+
+ _updateDimmer: function() {
+ if (this.actor.get_n_children() > 1) {
+ this._dimmer.setEnabled(true);
+ this._dimmer.dimFactor = 1.0;
+ } else {
+ this._dimmer.setEnabled(false);
+ }
+ },
+
+ _updateDialogPosition: function(realDialog, cloneDialog) {
+ let metaDialog = realDialog.meta_window;
+ let dialogRect = metaDialog.get_outer_rect();
+ let rect = this.metaWindow.get_outer_rect();
+
+ cloneDialog.set_position(dialogRect.x - rect.x, dialogRect.y - rect.y);
+ },
+
_onPositionChanged: function() {
let rect = this.metaWindow.get_outer_rect();
this.actor.set_position(this.realWindow.x, this.realWindow.y);
},
- _disconnectRealWindowSignals: function() {
- if (this._positionChangedId != 0) {
- this.realWindow.disconnect(this._positionChangedId);
- this._positionChangedId = 0;
- }
+ _disconnectSignals: function() {
+ this.actor.get_children().forEach(function(child) {
+ let realWindow = child.source;
- if (this._realWindowDestroyedId != 0) {
- this.realWindow.disconnect(this._realWindowDestroyedId);
- this._realWindowDestroyedId = 0;
- }
+ realWindow.disconnect(child._updateId);
+ realWindow.disconnect(child._destroyId);
+ });
},
_onDestroy: function() {
- this._disconnectRealWindowSignals();
+ this._disconnectSignals();
this.actor._delegate = null;
@@ -320,10 +400,26 @@ const WorkspaceThumbnail = new Lang.Class({
if (this._lookupIndex (metaWin) != -1)
return;
- if (!this._isMyWindow(win) || !this._isOverviewWindow(win))
+ if (!this._isMyWindow(win))
return;
- let clone = this._addWindowClone(win);
+ if (this._isOverviewWindow(win)) {
+ this._addWindowClone(win);
+ } else if (metaWin.is_attached_dialog()) {
+ let parent = metaWin.get_transient_for();
+ while (parent.is_attached_dialog())
+ parent = metaWin.get_transient_for();
+
+ let idx = this._lookupIndex (parent);
+ if (idx < 0) {
+ // parent was not created yet, it will take care
+ // of the dialog when created
+ return;
+ }
+
+ let clone = this._windows[idx];
+ clone.addAttachedDialog(metaWin);
+ }
},
_windowAdded : function(metaWorkspace, metaWin) {