Compare commits

...

7 Commits

Author SHA1 Message Date
Jasper St. Pierre
1afb04d1e4 overview: new transition 2014-01-31 17:57:57 -05:00
Jasper St. Pierre
51e63233ce viewSelector: Move to a sync() model for deciding which page to show
https://bugzilla.gnome.org/show_bug.cgi?id=722196
2014-01-31 17:57:57 -05:00
Jasper St. Pierre
a7d7f94892 screenShield: Don't hide windows until we've fully locked the shield
Revert the commit that ties hasWindows to the session mode, as we
need to do the "transition" manually. Instead, show/hide the
sessionGroup ourselves.

For optimization purposes, we also need to hide the window groups
when in the overview. Ideally, these would be culled out by Clutter,
but they are not from experimentation.
2014-01-31 17:57:57 -05:00
Jasper St. Pierre
427f516d45 layout: Replace SystemBackground with CSS on the systemGroup
This merges the implementation of the noise texture on the lockScreenDialog
and the startup animation -- they now just use the systemGroup.
2014-01-31 17:57:57 -05:00
Jasper St. Pierre
cbb88ffdbb layout: Add sessionGroup / systemGroup to better-define layers
In order to build a better transition animation from the lock screen, we
need to split the world into layers, as per this reference:

https://raw.github.com/gnome-design-team/gnome-mockups/master/system-lock-login-boot/system-layers2.png

Everything that pertains to the user's session is in the "session group",
which includes the window group, overview, message tray (for now),
keyboard, OSDs, menus, etc.

For implementation sake, we did not match this mockup exactly. The new layers
look like this, from top to bottom:

 * Stage
   * Magnifier (clones the uiGroup)
   * uiGroup
     * overlayGroup
       * menuGroup
     * panelGroup
     * screenShieldGroup
     * sessionGroup
       * top_window_group
       * other boxes (trayBox, keyboardBox, etc.)
       * other groups (osdGroup, switcherPopupGroup, etc.)
       * overviewGroup
       * window_group
     * systemGroup

The "session startup" animation now only zooms in the sessionGroup.

The panel is now outside the session, as it needs to sit above the screen
shield. This also means that it's not zoomed in as part of startup. I think
this is OK.

This also means that the lightboxes that the screen shield uses to fade out
the screen have to go in a new group, above the panel. This is known as the
overlayGroup, which has no relation to the old mutter group of the same name.

We also change the screen shield to put the lockDialogGroup in the system
group, and put the lockScreenGroup in the screenShieldGroup, which means
that the layer stacking is correct. Note that we don't hide the session
group in the lock screen yet, which is something I want to do.

Since not a lot of items need to be in the uiGroup anymore, we've removed
the Main.uiGroup fallback; others should use sessionGroup instead, when
appropriate.
2014-01-31 17:57:57 -05:00
Jasper St. Pierre
71670bad3b layout: Add different groups in the LayoutManager for discrete UI components
This helps take cruft out of the uiGroup, and ensures that components remain
stacked properly on top of each other. In the future, we'll use this group
to ensure that grabs are ordered properly, as well.
2014-01-31 17:57:57 -05:00
Jasper St. Pierre
a2e4153fa0 background: Fix cancellable issues
If we have the following sequence:

    cache.getImageContent({ filename: "foo", cancellable: cancellable1 });
    cache.getImageContent({ filename: "foo", cancellable: cancellable2 });
    cancellable1.cancel();

Then the second load will complete with "null" as its content, even though
it was never cancelled, and we'll see a blank image. Meanwhile, since the
second load simply appends to the list of callers for the second load,
cancellable2 does absolutely nothing: cancelling it won't stop the load,
and it will still receive onFinished handling.

To prevent this from happening, give the actual load operation its own
Gio.Cancellable, which is "ref-counted" -- only cancel it when all the other
possible callers cancel.

Additionally, clean up the large nested loops by splitting out duplicated
code and other stuff.

https://bugzilla.gnome.org/show_bug.cgi?id=722149
2014-01-31 17:57:57 -05:00
25 changed files with 325 additions and 277 deletions

View File

@ -2512,7 +2512,7 @@ StScrollBar StButton#vhandle:active {
box-shadow: 0px 4px 8px rgba(0,0,0,0.9);
}
#lockDialogGroup {
#systemGroup {
background: #2e3436 url(noise-texture.png);
background-repeat: repeat;
}

View File

@ -274,7 +274,7 @@ const SessionMenuButton = new Lang.Class({
this.actor = new St.Bin({ child: this._button });
this._menu = new PopupMenu.PopupMenu(this._button, 0, St.Side.TOP);
Main.uiGroup.add_actor(this._menu.actor);
Main.layoutManager.menuGroup.add_actor(this._menu.actor);
this._menu.actor.hide();
this._menu.connect('open-state-changed',

View File

@ -1525,7 +1525,7 @@ const AppIconMenu = new Lang.Class({
}));
source.actor.connect('destroy', Lang.bind(this, function () { this.actor.destroy(); }));
Main.uiGroup.add_actor(this.actor);
Main.layoutManager.menuGroup.add_actor(this.actor);
},
_redisplay: function() {

View File

@ -132,6 +132,46 @@ const BackgroundCache = new Lang.Class({
this._removeContent(this._images, content);
},
_loadImageContentInternal: function(filename, style) {
let cancellable = new Gio.Cancellable();
let content = new Meta.Background({ meta_screen: global.screen });
let info = { filename: filename,
style: style,
cancellable: cancellable,
callers: [] };
content.load_file_async(filename, style, cancellable, Lang.bind(this, function(object, result) {
if (cancellable.is_cancelled())
return;
try {
content.load_file_finish(result);
} catch(e) {
content = null;
}
if (content) {
this._monitorFile(filename);
info.callers.forEach(Lang.bind(this, function(caller) {
let newContent = content.copy(caller.monitorIndex, caller.effects);
this._images.push(newContent);
caller.onFinished(newContent);
}));
} else {
info.callers.forEach(Lang.bind(this, function(caller) {
caller.onFinished(null);
}));
}
let idx = this._pendingFileLoads.indexOf(info);
this._pendingFileLoads.splice(idx, 1);
}));
this._pendingFileLoads.push(info);
return info;
},
_loadImageContent: function(params) {
params = Params.parse(params, { monitorIndex: 0,
style: null,
@ -140,67 +180,38 @@ const BackgroundCache = new Lang.Class({
cancellable: null,
onFinished: null });
for (let i = 0; i < this._pendingFileLoads.length; i++) {
if (this._pendingFileLoads[i].filename == params.filename &&
this._pendingFileLoads[i].style == params.style) {
this._pendingFileLoads[i].callers.push({ shouldCopy: true,
monitorIndex: params.monitorIndex,
let caller = { monitorIndex: params.monitorIndex,
effects: params.effects,
onFinished: params.onFinished });
return;
}
}
this._pendingFileLoads.push({ filename: params.filename,
style: params.style,
callers: [{ shouldCopy: false,
monitorIndex: params.monitorIndex,
effects: params.effects,
onFinished: params.onFinished }] });
let content = new Meta.Background({ meta_screen: global.screen,
monitor: params.monitorIndex,
effects: params.effects });
content.load_file_async(params.filename,
params.style,
params.cancellable,
Lang.bind(this,
function(object, result) {
try {
content.load_file_finish(result);
this._monitorFile(params.filename);
this._images.push(content);
} catch(e) {
content = null;
}
cancellable: params.cancellable,
onFinished: params.onFinished };
let info = null;
for (let i = 0; i < this._pendingFileLoads.length; i++) {
let pendingLoad = this._pendingFileLoads[i];
if (pendingLoad.filename != params.filename ||
pendingLoad.style != params.style)
continue;
for (let j = 0; j < pendingLoad.callers.length; j++) {
if (pendingLoad.callers[j].onFinished) {
let newContent;
if (content && pendingLoad.callers[j].shouldCopy) {
newContent = content.copy(pendingLoad.callers[j].monitorIndex,
pendingLoad.callers[j].effects);
this._images.push(newContent);
} else {
newContent = content;
}
pendingLoad.callers[j].onFinished(newContent);
if (pendingLoad.filename == params.filename && pendingLoad.style == params.style) {
info = pendingLoad;
break;
}
}
this._pendingFileLoads.splice(i, 1);
if (!info)
info = this._loadImageContentInternal(params.filename, params.style);
info.callers.push(caller);
if (caller.cancellable) {
caller.cancellable.connect(Lang.bind(this, function() {
let idx = info.callers.indexOf(caller);
info.callers.splice(idx, 1);
if (info.callers.length == 0) {
info.cancellable.cancel();
let idx = this._pendingFileLoads.indexOf(info);
this._pendingFileLoads.splice(idx, 1);
}
}));
}
},
getImageContent: function(params) {
@ -250,7 +261,6 @@ const BackgroundCache = new Lang.Class({
monitorIndex: params.monitorIndex,
cancellable: params.cancellable,
onFinished: params.onFinished });
}
},
@ -624,31 +634,6 @@ const Background = new Lang.Class({
});
Signals.addSignalMethods(Background.prototype);
const SystemBackground = new Lang.Class({
Name: 'SystemBackground',
_init: function() {
this._cache = getBackgroundCache();
this.actor = new Meta.BackgroundActor();
this._cache.getImageContent({ style: GDesktopEnums.BackgroundStyle.WALLPAPER,
filename: global.datadir + '/theme/noise-texture.png',
effects: Meta.BackgroundEffects.NONE,
onFinished: Lang.bind(this, function(content) {
this.actor.content = content;
this.emit('loaded');
})
});
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
},
_onDestroy: function() {
this._cache.removeImageContent(this.actor.content);
},
});
Signals.addSignalMethods(SystemBackground.prototype);
const Animation = new Lang.Class({
Name: 'Animation',

View File

@ -22,7 +22,7 @@ const BackgroundMenu = new Lang.Class({
this.actor.add_style_class_name('background-menu');
layoutManager.uiGroup.add_actor(this.actor);
layoutManager.menuGroup.add_actor(this.actor);
this.actor.hide();
}
});

View File

@ -46,7 +46,7 @@ let dragMonitors = [];
function _getEventHandlerActor() {
if (!eventHandlerActor) {
eventHandlerActor = new Clutter.Actor({ width: 0, height: 0 });
Main.uiGroup.add_actor(eventHandlerActor);
Main.layoutManager.sessionGroup.add_actor(eventHandlerActor);
// We connect to 'event' rather than 'captured-event' because the capturing phase doesn't happen
// when you've grabbed the pointer.
eventHandlerActor.connect('event',
@ -236,7 +236,7 @@ const _Draggable = new Lang.Class({
if (this.actor._delegate && this.actor._delegate.getDragActor) {
this._dragActor = this.actor._delegate.getDragActor();
Main.uiGroup.add_child(this._dragActor);
Main.layoutManager.sessionGroup.add_child(this._dragActor);
this._dragActor.raise_top();
Shell.util_set_hidden_from_pick(this._dragActor, true);
@ -276,7 +276,7 @@ const _Draggable = new Lang.Class({
this._dragOrigScale = this._dragActor.scale_x;
// Set the actor's scale such that it will keep the same
// transformed size when it's reparented to the uiGroup
// transformed size when it's reparented to the sessionGroup
let [scaledWidth, scaledHeight] = this.actor.get_transformed_size();
this._dragActor.set_scale(scaledWidth / this.actor.width,
scaledHeight / this.actor.height);
@ -286,7 +286,7 @@ const _Draggable = new Lang.Class({
this._dragOffsetY = actorStageY - this._dragStartY;
this._dragOrigParent.remove_actor(this._dragActor);
Main.uiGroup.add_child(this._dragActor);
Main.layoutManager.sessionGroup.add_child(this._dragActor);
this._dragActor.raise_top();
Shell.util_set_hidden_from_pick(this._dragActor, true);
}
@ -448,7 +448,7 @@ const _Draggable = new Lang.Class({
event.get_time())) {
// If it accepted the drop without taking the actor,
// handle it ourselves.
if (this._dragActor.get_parent() == Main.uiGroup) {
if (this._dragActor.get_parent() == Main.layoutManager.sessionGroup) {
if (this._restoreOnSuccess) {
this._restoreDragActor(event.get_time());
return true;
@ -557,7 +557,7 @@ const _Draggable = new Lang.Class({
_onAnimationComplete : function (dragActor, eventTime) {
if (this._dragOrigParent) {
Main.uiGroup.remove_child(this._dragActor);
Main.layoutManager.sessionGroup.remove_child(this._dragActor);
this._dragOrigParent.add_actor(this._dragActor);
dragActor.set_scale(this._dragOrigScale, this._dragOrigScale);
dragActor.set_position(this._dragOrigX, this._dragOrigY);

View File

@ -162,9 +162,9 @@ const LayoutManager = new Lang.Class({
this._startingUp = true;
// Normally, the stage is always covered so Clutter doesn't need to clear
// it; however it becomes visible during the startup animation
// See the comment below for a longer explanation
// it; however it becomes visible when using the magnifier.
global.stage.color = DEFAULT_BACKGROUND_COLOR;
global.stage.no_clear_hint = true;
// Set up stage hierarchy to group all UI actors under one container.
this.uiGroup = new Shell.GenericContainer({ name: 'uiGroup' });
@ -184,29 +184,27 @@ const LayoutManager = new Lang.Class({
let height = global.stage.height;
[alloc.min_size, alloc.natural_size] = [height, height];
});
global.stage.add_child(this.uiGroup);
this.systemGroup = new St.Widget({ name: 'systemGroup',
layout_manager: new Clutter.BinLayout() });
this.uiGroup.add_actor(this.systemGroup);
this.sessionGroup = new St.Widget({ name: 'sessionGroup' });
this.uiGroup.add_child(this.sessionGroup);
global.stage.remove_actor(global.window_group);
this.uiGroup.add_actor(global.window_group);
global.stage.add_child(this.uiGroup);
this.sessionGroup.add_actor(global.window_group);
this.overviewGroup = new St.Widget({ name: 'overviewGroup',
visible: false });
this.addChrome(this.overviewGroup);
this.screenShieldGroup = new St.Widget({ name: 'screenShieldGroup',
visible: false,
clip_to_allocation: true,
layout_manager: new Clutter.BinLayout(),
});
this.addChrome(this.screenShieldGroup);
this.panelBox = new St.BoxLayout({ name: 'panelBox',
vertical: true });
this.addChrome(this.panelBox, { affectsStruts: true,
trackFullscreen: true });
this.panelBox.connect('allocation-changed',
Lang.bind(this, this._panelBoxChanged));
this.uiGroup.add_child(this.screenShieldGroup);
this.trayBox = new St.Widget({ name: 'trayBox',
layout_manager: new Clutter.BinLayout() });
@ -219,13 +217,39 @@ const LayoutManager = new Lang.Class({
this.addChrome(this.keyboardBox);
this._keyboardHeightNotifyId = 0;
this.osdGroup = new St.Widget();
this.sessionGroup.add_child(this.osdGroup);
this.switcherPopupGroup = new St.Widget();
this.sessionGroup.add_child(this.switcherPopupGroup);
this.dialogGroup = new St.Widget();
this.sessionGroup.add_child(this.dialogGroup);
// A dummy actor that tracks the mouse or text cursor, based on the
// position set in setDummyCursorPosition.
this.dummyCursor = new St.Widget({ width: 0, height: 0 });
this.uiGroup.add_actor(this.dummyCursor);
this.uiGroup.add_child(this.dummyCursor);
global.stage.remove_actor(global.top_window_group);
this.uiGroup.add_actor(global.top_window_group);
// The panel group isn't in the session, as it needs to go above the screen
// shield, and it isn't animated in the login animation.
this.panelGroup = new St.Widget({ name: 'panelGroup' });
this.uiGroup.add_child(this.panelGroup);
this._trackActor(this.panelGroup, { affectsStruts: true,
trackFullscreen: true });
this.panelGroup.connect('allocation-changed',
Lang.bind(this, this._panelGroupChanged));
this.overlayGroup = new St.Widget({ name: 'overlayGroup' });
this.uiGroup.add_child(this.overlayGroup);
this.menuGroup = new St.Widget();
this.overlayGroup.add_child(this.menuGroup);
this._topSessionGroup = new St.Widget();
this.overlayGroup.add_child(this._topSessionGroup);
global.stage.remove_child(global.top_window_group);
this._topSessionGroup.add_child(global.top_window_group);
this._backgroundGroup = new Meta.BackgroundGroup();
global.window_group.add_child(this._backgroundGroup);
@ -247,8 +271,7 @@ const LayoutManager = new Lang.Class({
// This is called by Main after everything else is constructed
init: function() {
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
this._loadBackground();
this._prepareStartupAnimation();
},
showOverview: function() {
@ -257,6 +280,9 @@ const LayoutManager = new Lang.Class({
this._inOverview = true;
this._updateVisibility();
this._updateRegions();
global.window_group.hide();
global.top_window_group.hide();
},
hideOverview: function() {
@ -265,6 +291,9 @@ const LayoutManager = new Lang.Class({
this._inOverview = false;
this._updateVisibility();
this._queueUpdateRegions();
global.window_group.show();
global.top_window_group.show();
},
_sessionUpdated: function() {
@ -306,7 +335,7 @@ const LayoutManager = new Lang.Class({
});
this.hotCorners = [];
let size = this.panelBox.height;
let size = this.panelGroup.height;
// build new hot corners
for (let i = 0; i < this.monitors.length; i++) {
@ -406,11 +435,11 @@ const LayoutManager = new Lang.Class({
},
_updateBoxes: function() {
this.screenShieldGroup.set_position(0, 0);
this.screenShieldGroup.set_size(global.screen_width, global.screen_height);
this.systemGroup.set_position(0, 0);
this.systemGroup.set_size(global.screen_width, global.screen_height);
this.panelBox.set_position(this.primaryMonitor.x, this.primaryMonitor.y);
this.panelBox.set_size(this.primaryMonitor.width, -1);
this.panelGroup.set_position(this.primaryMonitor.x, this.primaryMonitor.y);
this.panelGroup.set_size(this.primaryMonitor.width, -1);
if (this.keyboardIndex < 0)
this.keyboardIndex = this.primaryIndex;
@ -420,10 +449,10 @@ const LayoutManager = new Lang.Class({
this.trayBox.set_size(this.bottomMonitor.width, -1);
},
_panelBoxChanged: function() {
_panelGroupChanged: function() {
this._updatePanelBarrier();
let size = this.panelBox.height;
let size = this.panelGroup.height;
this.hotCorners.forEach(function(corner) {
if (corner)
corner.setBarrierSize(size);
@ -436,12 +465,12 @@ const LayoutManager = new Lang.Class({
this._rightPanelBarrier = null;
}
if (this.panelBox.height) {
if (this.panelGroup.height) {
let primary = this.primaryMonitor;
this._rightPanelBarrier = new Meta.Barrier({ display: global.display,
x1: primary.x + primary.width, y1: primary.y,
x2: primary.x + primary.width, y2: primary.y + this.panelBox.height,
x2: primary.x + primary.width, y2: primary.y + this.panelGroup.height,
directions: Meta.BarrierDirection.NEGATIVE_X });
}
},
@ -547,25 +576,6 @@ const LayoutManager = new Lang.Class({
return this._keyboardIndex;
},
_loadBackground: function() {
this._systemBackground = new Background.SystemBackground();
this._systemBackground.actor.hide();
global.stage.insert_child_below(this._systemBackground.actor, null);
let constraint = new Clutter.BindConstraint({ source: global.stage,
coordinate: Clutter.BindCoordinate.ALL });
this._systemBackground.actor.add_constraint(constraint);
let signalId = this._systemBackground.connect('loaded', Lang.bind(this, function() {
this._systemBackground.disconnect(signalId);
this._systemBackground.actor.show();
global.stage.show();
this._prepareStartupAnimation();
}));
},
// Startup Animations
//
// We have two different animations, depending on whether we're a greeter
@ -586,6 +596,8 @@ const LayoutManager = new Lang.Class({
// screen. So, we set no_clear_hint at the end of the animation.
_prepareStartupAnimation: function() {
global.stage.show();
// During the initial transition, add a simple actor to block all events,
// so they don't get delivered to X11 windows that have been transformed.
this._coverPane = new Clutter.Actor({ opacity: 0,
@ -595,7 +607,7 @@ const LayoutManager = new Lang.Class({
this.addChrome(this._coverPane);
if (Main.sessionMode.isGreeter) {
this.panelBox.translation_y = -this.panelBox.height;
this.panelGroup.translation_y = -this.panelGroup.height;
} else {
this._updateBackgrounds();
@ -610,10 +622,10 @@ const LayoutManager = new Lang.Class({
let x = monitor.x + monitor.width / 2.0;
let y = monitor.y + monitor.height / 2.0;
this.uiGroup.set_pivot_point(x / global.screen_width,
this.sessionGroup.set_pivot_point(x / global.screen_width,
y / global.screen_height);
this.uiGroup.scale_x = this.uiGroup.scale_y = 0.75;
this.uiGroup.opacity = 0;
this.sessionGroup.scale_x = this.sessionGroup.scale_y = 0.75;
this.sessionGroup.opacity = 0;
global.window_group.set_clip(monitor.x, monitor.y, monitor.width, monitor.height);
}
@ -639,7 +651,7 @@ const LayoutManager = new Lang.Class({
},
_startupAnimationGreeter: function() {
Tweener.addTween(this.panelBox,
Tweener.addTween(this.panelGroup,
{ translation_y: 0,
time: STARTUP_ANIMATION_TIME,
transition: 'easeOutQuad',
@ -648,7 +660,7 @@ const LayoutManager = new Lang.Class({
},
_startupAnimationSession: function() {
Tweener.addTween(this.uiGroup,
Tweener.addTween(this.sessionGroup,
{ scale_x: 1,
scale_y: 1,
opacity: 255,
@ -659,16 +671,9 @@ const LayoutManager = new Lang.Class({
},
_startupAnimationComplete: function() {
// At this point, the UI group is covering everything, so
// we no longer need to clear the stage
global.stage.no_clear_hint = true;
this._coverPane.destroy();
this._coverPane = null;
this._systemBackground.actor.destroy();
this._systemBackground = null;
this._startingUp = false;
this.trayBox.show();
@ -758,9 +763,9 @@ const LayoutManager = new Lang.Class({
// monitor (it will be hidden whenever a fullscreen window is visible,
// and shown otherwise)
addChrome: function(actor, params) {
this.uiGroup.add_actor(actor);
if (this.uiGroup.contains(global.top_window_group))
this.uiGroup.set_child_below_sibling(actor, global.top_window_group);
this.sessionGroup.add_actor(actor);
if (this.sessionGroup.contains(global.top_window_group))
this.sessionGroup.set_child_below_sibling(actor, global.top_window_group);
this._trackActor(actor, params);
},
@ -811,7 +816,7 @@ const LayoutManager = new Lang.Class({
//
// Removes @actor from the chrome
removeChrome: function(actor) {
this.uiGroup.remove_actor(actor);
this.sessionGroup.remove_actor(actor);
this._untrackActor(actor);
},
@ -859,9 +864,6 @@ const LayoutManager = new Lang.Class({
_updateVisibility: function() {
let windowsVisible = Main.sessionMode.hasWindows && !this._inOverview;
global.window_group.visible = windowsVisible;
global.top_window_group.visible = windowsVisible;
for (let i = 0; i < this._trackedActors.length; i++) {
let actorData = this._trackedActors[i], visible;
if (!actorData.trackFullscreen)
@ -1080,9 +1082,9 @@ const HotCorner = new Lang.Class({
this._ripple2 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false });
this._ripple3 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false });
layoutManager.uiGroup.add_actor(this._ripple1);
layoutManager.uiGroup.add_actor(this._ripple2);
layoutManager.uiGroup.add_actor(this._ripple3);
layoutManager.sessionGroup.add_actor(this._ripple1);
layoutManager.sessionGroup.add_actor(this._ripple2);
layoutManager.sessionGroup.add_actor(this._ripple3);
},
setBarrierSize: function(size) {

View File

@ -503,7 +503,7 @@ const Inspector = new Lang.Class({
let container = new Shell.GenericContainer({ width: 0,
height: 0 });
container.connect('allocate', Lang.bind(this, this._allocate));
Main.uiGroup.add_actor(container);
Main.layoutManager.sessionGroup.add_actor(container);
let eventHandler = new St.BoxLayout({ name: 'LookingGlassDialog',
vertical: false,
@ -801,16 +801,14 @@ const LookingGlass = new Lang.Class({
this._updateFont();
// We want it to appear to slide out from underneath the panel
Main.uiGroup.add_actor(this.actor);
Main.uiGroup.set_child_below_sibling(this.actor,
Main.layoutManager.panelBox);
Main.layoutManager.panelBox.connect('allocation-changed',
Main.layoutManager.sessionGroup.add_actor(this.actor);
Main.layoutManager.panelGroup.connect('allocation-changed',
Lang.bind(this, this._queueResize));
Main.layoutManager.keyboardBox.connect('allocation-changed',
Lang.bind(this, this._queueResize));
this._objInspector = new ObjInspector(this);
Main.uiGroup.add_actor(this._objInspector.actor);
Main.layoutManager.sessionGroup.add_actor(this._objInspector.actor);
this._objInspector.actor.hide();
let toolbar = new St.BoxLayout({ name: 'Toolbar' });
@ -1037,7 +1035,7 @@ const LookingGlass = new Lang.Class({
let availableHeight = primary.height - Main.layoutManager.keyboardBox.height;
let myHeight = Math.min(primary.height * 0.7, availableHeight * 0.9);
this.actor.x = primary.x + (primary.width - myWidth) / 2;
this._hiddenY = primary.y + Main.layoutManager.panelBox.height - myHeight - 4; // -4 to hide the top corners
this._hiddenY = primary.y + Main.layoutManager.panelGroup.height - myHeight - 4; // -4 to hide the top corners
this._targetY = this._hiddenY + myHeight;
this.actor.y = this._hiddenY;
this.actor.width = myWidth;

View File

@ -1184,7 +1184,7 @@ const ZoomRegion = new Lang.Class({
// Clone the group that contains all of UI on the screen. This is the
// chrome, the windows, etc.
this._uiGroupClone = new Clutter.Clone({ source: Main.uiGroup });
this._uiGroupClone = new Clutter.Clone({ source: Main.layoutManager.uiGroup });
mainGroup.add_actor(this._uiGroupClone);
// Add either the given mouseSourceActor to the ZoomRegion, or a clone of

View File

@ -64,7 +64,6 @@ let screencastService = null;
let modalCount = 0;
let keybindingMode = Shell.KeyBindingMode.NONE;
let modalActorFocusStack = [];
let uiGroup = null;
let magnifier = null;
let xdndHandler = null;
let keyboard = null;
@ -150,11 +149,6 @@ function _initializeUI() {
// Setup the stage hierarchy early
layoutManager = new Layout.LayoutManager();
// Various parts of the codebase still refers to Main.uiGroup
// instead using the layoutManager. This keeps that code
// working until it's updated.
uiGroup = layoutManager.uiGroup;
screencastService = new Screencast.ScreencastService();
xdndHandler = new XdndHandler.XdndHandler();
ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
@ -172,6 +166,19 @@ function _initializeUI() {
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
componentManager = new Components.ComponentManager();
if (sessionMode.isGreeter && screenShield) {
layoutManager.connect('startup-prepared', function() {
screenShield.showDialog();
});
}
layoutManager.connect('startup-complete', function() {
if (keybindingMode == Shell.KeyBindingMode.NONE)
keybindingMode = Shell.KeyBindingMode.NORMAL;
if (screenShield)
screenShield.lockIfWasLocked();
});
layoutManager.init();
overview.init();
@ -202,21 +209,6 @@ function _initializeUI() {
ExtensionDownloader.init();
ExtensionSystem.init();
if (sessionMode.isGreeter && screenShield) {
layoutManager.connect('startup-prepared', function() {
screenShield.showDialog();
});
}
layoutManager.connect('startup-complete', function() {
if (keybindingMode == Shell.KeyBindingMode.NONE) {
keybindingMode = Shell.KeyBindingMode.NORMAL;
}
if (screenShield) {
screenShield.lockIfWasLocked();
}
});
}
function _loadDefaultStylesheet() {

View File

@ -1611,7 +1611,7 @@ const MessageTrayMenu = new Lang.Class({
this._accountManager.prepare_async(null, Lang.bind(this, this._onIMPresenceChanged));
this.actor.hide();
Main.layoutManager.addChrome(this.actor);
Main.layoutManager.menuGroup.add_child(this.actor);
this._busyItem = new PopupMenu.PopupSwitchMenuItem(_("Notifications"));
this._busyItem.connect('toggled', Lang.bind(this, this._updatePresence));
@ -2512,7 +2512,7 @@ const MessageTray = new Lang.Class({
let cloneSource = Main.overview.visible ? Main.layoutManager.overviewGroup : global.window_group;
this._desktopClone = new Clutter.Clone({ source: cloneSource,
clip: new Clutter.Geometry(this._bottomMonitorGeometry) });
Main.uiGroup.insert_child_above(this._desktopClone, cloneSource);
Main.layoutManager.sessionGroup.insert_child_above(this._desktopClone, cloneSource);
this._desktopClone.x = 0;
this._desktopClone.y = 0;
this._desktopClone.show();

View File

@ -41,7 +41,7 @@ const ModalDialog = new Lang.Class({
_init: function(params) {
params = Params.parse(params, { shellReactive: false,
styleClass: null,
parentActor: Main.uiGroup,
parentActor: Main.layoutManager.dialogGroup,
keybindingMode: Shell.KeyBindingMode.SYSTEM_MODAL,
shouldFadeIn: true,
destroyOnClose: true });

View File

@ -110,7 +110,7 @@ const OsdWindow = new Lang.Class({
Lang.bind(this, this._monitorsChanged));
this._monitorsChanged();
Main.uiGroup.add_child(this.actor);
Main.layoutManager.osdGroup.add_child(this.actor);
},
setIcon: function(icon) {

View File

@ -622,7 +622,7 @@ const Overview = new Lang.Class({
this.animationInProgress = true;
this.visibleTarget = false;
this.viewSelector.zoomFromOverview();
this.viewSelector.leaveOverview();
// Make other elements fade out.
Tweener.addTween(this._stack,

View File

@ -901,7 +901,7 @@ const Panel = new Lang.Class({
this.actor.remove_style_pseudo_class('overview');
}));
Main.layoutManager.panelBox.add(this.actor);
Main.layoutManager.panelGroup.add_child(this.actor);
Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'emblem-system-symbolic',
{ sortGroup: CtrlAltTab.SortGroup.TOP });

View File

@ -130,7 +130,7 @@ const Button = new Lang.Class({
this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
this.menu.actor.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));
Main.uiGroup.add_actor(this.menu.actor);
Main.layoutManager.menuGroup.add_child(this.menu.actor);
this.menu.actor.hide();
}
},

View File

@ -456,8 +456,6 @@ const ScreenShield = new Lang.Class({
Name: 'ScreenShield',
_init: function() {
this.actor = Main.layoutManager.screenShieldGroup;
this._lockScreenState = MessageTray.State.HIDDEN;
this._lockScreenGroup = new St.Widget({ x_expand: true,
y_expand: true,
@ -466,6 +464,7 @@ const ScreenShield = new Lang.Class({
name: 'lockScreenGroup',
visible: false,
});
this._lockScreenGroup.connect('key-press-event',
Lang.bind(this, this._onLockScreenKeyPress));
this._lockScreenGroup.connect('scroll-event',
@ -516,10 +515,9 @@ const ScreenShield = new Lang.Class({
reactive: true,
pivot_point: new Clutter.Point({ x: 0.5, y: 0.5 }),
name: 'lockDialogGroup' });
Main.layoutManager.systemGroup.add_child(this._lockDialogGroup);
this.actor.add_actor(this._lockDialogGroup);
this.actor.add_actor(this._lockScreenGroup);
Main.layoutManager.screenShieldGroup.add_child(this._lockScreenGroup);
this._presence = new GnomeSession.Presence(Lang.bind(this, function(proxy, error) {
if (error) {
logError(error, 'Error while reading gnome-session presence');
@ -577,19 +575,27 @@ const ScreenShield = new Lang.Class({
// The "long" lightbox is used for the longer (20 seconds) fade from session
// to idle status, the "short" is used for quickly fading to black when locking
// manually
this._longLightbox = new Lightbox.Lightbox(Main.uiGroup,
this._longLightbox = new Lightbox.Lightbox(Main.layoutManager.overlayGroup,
{ inhibitEvents: true,
fadeFactor: 1 });
this._longLightbox.connect('shown', Lang.bind(this, this._onLongLightboxShown));
this._shortLightbox = new Lightbox.Lightbox(Main.uiGroup,
this._shortLightbox = new Lightbox.Lightbox(Main.layoutManager.overlayGroup,
{ inhibitEvents: true,
fadeFactor: 1 });
this._shortLightbox.connect('shown', Lang.bind(this, this._onShortLightboxShown));
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._monitorsChanged));
this._monitorsChanged();
this.idleMonitor = Meta.IdleMonitor.get_core();
this._cursorTracker = Meta.CursorTracker.get_for_screen(global.screen);
},
_monitorsChanged: function() {
this._longLightbox.actor.set_size(global.screen_width, global.screen_height);
this._shortLightbox.actor.set_size(global.screen_width, global.screen_height);
},
_createBackground: function(monitorIndex) {
let monitor = Main.layoutManager.monitors[monitorIndex];
let widget = new St.Widget({ style_class: 'screen-shield-background',
@ -647,13 +653,13 @@ const ScreenShield = new Lang.Class({
if (this._isModal)
return true;
this._isModal = Main.pushModal(this.actor, { keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN });
this._isModal = Main.pushModal(this._lockDialogGroup, { keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN });
if (this._isModal)
return true;
// We failed to get a pointer grab, it means that
// something else has it. Try with a keyboard grab only
this._isModal = Main.pushModal(this.actor, { options: Meta.ModalOptions.POINTER_ALREADY_GRABBED,
this._isModal = Main.pushModal(this._lockDialogGroup, { options: Meta.ModalOptions.POINTER_ALREADY_GRABBED,
keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN });
return this._isModal;
},
@ -912,7 +918,7 @@ const ScreenShield = new Lang.Class({
return false;
}));
this.actor.show();
this._lockDialogGroup.show();
this._isGreeter = Main.sessionMode.isGreeter;
this._isLocked = true;
if (this._ensureUnlockDialog(true, true))
@ -1002,6 +1008,7 @@ const ScreenShield = new Lang.Class({
return;
this._ensureLockScreen();
this._lockDialogGroup.hide();
this._lockDialogGroup.scale_x = 1;
this._lockDialogGroup.scale_y = 1;
@ -1100,8 +1107,10 @@ const ScreenShield = new Lang.Class({
}));
this._cursorTracker.set_pointer_visible(false);
this._lockScreenState = MessageTray.State.SHOWN;
this._lockDialogGroup.show();
this._lockScreenGroup.fixed_position_set = false;
this._lockScreenState = MessageTray.State.SHOWN;
Main.layoutManager.sessionGroup.hide();
this._lockScreenScrollCounter = 0;
if (params.fadeToBlack && params.animateFade) {
@ -1224,10 +1233,11 @@ const ScreenShield = new Lang.Class({
this._dialog.popModal();
if (this._isModal) {
Main.popModal(this.actor);
Main.popModal(this._lockDialogGroup);
this._isModal = false;
}
Main.layoutManager.sessionGroup.show();
Tweener.addTween(this._lockDialogGroup, {
scale_x: 0,
scale_y: 0,
@ -1246,7 +1256,7 @@ const ScreenShield = new Lang.Class({
this._longLightbox.hide();
this._shortLightbox.hide();
this.actor.hide();
this._lockScreenGroup.hide();
if (this._becameActiveId != 0) {
this.idleMonitor.remove_watch(this._becameActiveId);
@ -1270,7 +1280,7 @@ const ScreenShield = new Lang.Class({
if (this._activationTime == 0)
this._activationTime = GLib.get_monotonic_time();
this.actor.show();
this._lockScreenGroup.show();
if (Main.sessionMode.currentMode != 'unlock-dialog' &&
Main.sessionMode.currentMode != 'lock-screen') {

View File

@ -146,7 +146,7 @@ const SelectArea = new Lang.Class({
reactive: true,
x: 0,
y: 0 });
Main.uiGroup.add_actor(this._group);
Main.layoutManager.osdGroup.add_actor(this._group);
this._group.connect('button-press-event',
Lang.bind(this, this._onButtonPress));
@ -259,7 +259,7 @@ const Flashspot = new Lang.Class({
Extends: Lightbox.Lightbox,
_init: function(area) {
this.parent(Main.uiGroup, { inhibitEvents: true,
this.parent(Main.layoutManager.osdGroup, { inhibitEvents: true,
width: area.width,
height: area.height });

View File

@ -36,7 +36,7 @@ const EntryMenu = new Lang.Class({
this._passwordItem = null;
Main.uiGroup.add_actor(this.actor);
Main.layoutManager.menuGroup.add_actor(this.actor);
this.actor.hide();
},

View File

@ -54,7 +54,7 @@ const SwitcherPopup = new Lang.Class({
this.actor.connect('allocate', Lang.bind(this, this._allocate));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
Main.uiGroup.add_actor(this.actor);
Main.layoutManager.switcherPopupGroup.add_child(this.actor);
this._haveModal = false;
this._modifierMask = 0;

View File

@ -118,13 +118,11 @@ const ViewSelector = new Lang.Class({
this._stageKeyPressId = 0;
Main.overview.connect('showing', Lang.bind(this,
function () {
this._resetShowAppsButton();
this._stageKeyPressId = global.stage.connect('key-press-event',
Lang.bind(this, this._onStageKeyPress));
}));
Main.overview.connect('hiding', Lang.bind(this,
function () {
this._resetShowAppsButton();
if (this._stageKeyPressId != 0) {
global.stage.disconnect(this._stageKeyPressId);
this._stageKeyPressId = 0;
@ -160,19 +158,26 @@ const ViewSelector = new Lang.Class({
show: function() {
this.reset();
this._showAppsBlocked = true;
this._showAppsButton.checked = false;
this._showAppsBlocked = false;
this._workspacesPage.opacity = 255;
this._workspacesDisplay.show();
this._activePage = null;
this._showPage(this._workspacesPage);
this._syncActivePage();
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
Main.overview.fadeOutDesktop();
},
zoomFromOverview: function() {
this._workspacesDisplay.zoomFromOverview();
leaveOverview: function() {
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
Main.overview.fadeInDesktop();
// If we're not on the windows page, don't zoom back the primary monitor.
let zoomPrimary = (this._activePage == this._workspacesPage);
this._workspacesDisplay.leaveOverview(zoomPrimary);
},
setWorkspacesFullGeometry: function(geom) {
@ -181,6 +186,9 @@ const ViewSelector = new Lang.Class({
hide: function() {
this._workspacesDisplay.hide();
if (this._activePage)
this._activePage.hide();
this._activePage = null;
},
_addPage: function(actor, name, a11yIcon, params) {
@ -221,7 +229,7 @@ const ViewSelector = new Lang.Class({
});
},
_showPage: function(page, noFade) {
_setActivePage: function(page) {
if (page == this._activePage)
return;
@ -229,7 +237,7 @@ const ViewSelector = new Lang.Class({
this._activePage = page;
this.emit('page-changed');
if (oldPage && !noFade)
if (oldPage)
Tweener.addTween(oldPage,
{ opacity: 0,
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
@ -248,20 +256,25 @@ const ViewSelector = new Lang.Class({
page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
},
_onShowAppsButtonToggled: function() {
if (this._showAppsBlocked)
return;
this._showPage(this._showAppsButton.checked ?
this._appsPage : this._workspacesPage);
_getActivePage: function() {
if (this._searchActive)
return this._searchPage;
else if (this._showAppsButton.checked)
return this._appsPage;
else
return this._workspacesPage;
},
_resetShowAppsButton: function() {
this._showAppsBlocked = true;
this._showAppsButton.checked = false;
this._showAppsBlocked = false;
_syncActivePage: function() {
let activePage = this._getActivePage();
if (activePage == this._activePage)
return;
this._setActivePage(activePage);
},
this._showPage(this._workspacesPage, true);
_onShowAppsButtonToggled: function() {
if (!this._showAppsBlocked)
this._syncActivePage();
},
_onStageKeyPress: function(actor, event) {
@ -287,20 +300,6 @@ const ViewSelector = new Lang.Class({
return Clutter.EVENT_PROPAGATE;
},
_searchCancelled: function() {
this._showPage(this._showAppsButton.checked ? this._appsPage
: this._workspacesPage);
// Leave the entry focused when it doesn't have any text;
// when replacing a selected search term, Clutter emits
// two 'text-changed' signals, one for deleting the previous
// text and one for the new one - the second one is handled
// incorrectly when we remove focus
// (https://bugzilla.gnome.org/show_bug.cgi?id=636341) */
if (this._text.text != '')
this.reset();
},
reset: function () {
global.stage.set_key_focus(null);
@ -391,8 +390,18 @@ const ViewSelector = new Lang.Class({
}
this._entry.set_secondary_icon(null);
this._searchCancelled();
// Leave the entry focused when it doesn't have any text;
// when replacing a selected search term, Clutter emits
// two 'text-changed' signals, one for deleting the previous
// text and one for the new one - the second one is handled
// incorrectly when we remove focus
// (https://bugzilla.gnome.org/show_bug.cgi?id=636341) */
if (this._text.text != '')
this.reset();
}
this._syncActivePage();
},
_onKeyPress: function(entry, event) {
@ -459,9 +468,7 @@ const ViewSelector = new Lang.Class({
this._searchTimeoutId = 0;
let terms = getTermsForSearchString(this._entry.get_text());
this._searchResults.setTerms(terms);
this._showPage(this._searchPage);
return GLib.SOURCE_REMOVE;
},

View File

@ -1521,34 +1521,39 @@ const Workspace = new Lang.Class({
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL);
},
// Animates the return from Overview mode
zoomFromOverview : function() {
_leavingOverview: function() {
let currentWorkspace = global.screen.get_active_workspace();
if (this.metaWorkspace != null && this.metaWorkspace != currentWorkspace)
return false;
this.leavingOverview = true;
this._overviewHiddenId = Main.overview.connect('hidden', Lang.bind(this,
this._doneLeavingOverview));
for (let i = 0; i < this._windows.length; i++) {
let clone = this._windows[i];
Tweener.removeTweens(clone.actor);
let overlay = this._windowOverlays[i];
if (overlay)
overlay.hide();
}
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0;
}
this._overviewHiddenId = Main.overview.connect('hidden', Lang.bind(this,
this._doneLeavingOverview));
if (this.metaWorkspace != null && this.metaWorkspace != currentWorkspace)
return true;
},
// Animates the return from Overview mode
zoomFromOverview : function() {
if (!this._leavingOverview())
return;
// Position and scale the windows.
for (let i = 0; i < this._windows.length; i++) {
let clone = this._windows[i];
let overlay = this._windowOverlays[i];
if (overlay)
overlay.hide();
if (clone.metaWindow.showing_on_its_workspace()) {
let [origX, origY] = clone.getOriginalPosition();
@ -1575,6 +1580,31 @@ const Workspace = new Lang.Class({
}
},
fadeFromOverview: function() {
if (!this._leavingOverview())
return;
for (let i = 0; i < this._windows.length; i++) {
let clone = this._windows[i];
if (clone.metaWindow.showing_on_its_workspace()) {
clone.actor.x = clone.origX;
clone.actor.y = clone.origY;
clone.actor.scale_x = 1.0;
clone.actor.scale_y = 1.0;
clone.actor.opacity = 0;
Tweener.addTween(clone.actor,
{ opacity: 255,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad'
});
} else {
clone.actor.hide();
}
}
},
destroy : function() {
this.actor.destroy();
},

View File

@ -25,7 +25,7 @@ const WorkspaceSwitcherPopup = new Lang.Class({
width: global.screen_width,
height: global.screen_height,
style_class: 'workspace-switcher-group' });
Main.uiGroup.add_actor(this.actor);
Main.layoutManager.osdGroup.add_child(this.actor);
this._container = new St.BoxLayout({ style_class: 'workspace-switcher-container' });
this._list = new Shell.GenericContainer({ style_class: 'workspace-switcher' });

View File

@ -145,11 +145,22 @@ const WorkspacesView = new Lang.Class({
this._updateWorkspaceActors(false);
},
zoomFromOverview: function() {
_leaveOverview: function() {
this.actor.remove_clip();
},
for (let w = 0; w < this._workspaces.length; w++)
this._workspaces[w].zoomFromOverview();
zoomFromOverview: function() {
this._leaveOverview();
this._workspaces.forEach(function(w) {
w.zoomFromOverview();
});
},
fadeFromOverview: function() {
this._leaveOverview();
this._workspaces.forEach(function(w) {
w.fadeFromOverview();
});
},
syncStacking: function(stackIndices) {
@ -365,6 +376,10 @@ const ExtraWorkspaceView = new Lang.Class({
this._workspace.zoomFromOverview();
},
fadeFromOverview: function() {
this._workspace.fadeFromOverview();
},
syncStacking: function(stackIndices) {
this._workspace.syncStacking(stackIndices);
},
@ -466,9 +481,18 @@ const WorkspacesDisplay = new Lang.Class({
this._scrollEventId = Main.overview.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
},
zoomFromOverview: function() {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].zoomFromOverview();
leaveOverview: function(zoomPrimary) {
for (let i = 0; i < this._workspacesViews.length; i++) {
let view = this._workspacesViews[i];
if (i == this._primaryIndex) {
if (zoomPrimary)
view.zoomFromOverview();
else
view.fadeFromOverview();
} else {
view.zoomFromOverview();
}
}
},
hide: function() {

View File

@ -18,7 +18,7 @@ const XdndHandler = new Lang.Class({
// Used as a drag actor in case we don't have a cursor window clone
this._dummy = new Clutter.Actor({ width: 1, height: 1, opacity: 0 });
Main.uiGroup.add_actor(this._dummy);
Main.layoutManager.sessionGroup.add_actor(this._dummy);
this._dummy.hide();
if (!Meta.is_wayland_compositor())
@ -69,7 +69,7 @@ const XdndHandler = new Lang.Class({
source: cursorWindow});
this._cursorWindowClone = new Clutter.Clone({ source: cursorWindow });
Main.uiGroup.add_actor(this._cursorWindowClone);
Main.layoutManager.sessionGroup.add_actor(this._cursorWindowClone);
// Make sure that the clone has the same position as the source
this._cursorWindowClone.add_constraint(constraint_position);