diff --git a/js/ui/layout.js b/js/ui/layout.js index 8244a86d2..9756813ef 100644 --- a/js/ui/layout.js +++ b/js/ui/layout.js @@ -17,6 +17,7 @@ const Tweener = imports.ui.tweener; const HOT_CORNER_ACTIVATION_TIMEOUT = 0.5; const STARTUP_ANIMATION_TIME = 0.2; const KEYBOARD_ANIMATION_TIME = 0.5; +const PLYMOUTH_TRANSITION_TIME = 1; const MonitorConstraint = new Lang.Class({ Name: 'MonitorConstraint', @@ -100,6 +101,7 @@ const LayoutManager = new Lang.Class({ this.primaryMonitor = null; this.primaryIndex = -1; this._hotCorners = []; + this._rootPixmap = null; this._leftPanelBarrier = 0; this._rightPanelBarrier = 0; this._trayBarrier = 0; @@ -319,10 +321,41 @@ const LayoutManager = new Lang.Class({ }, _startupAnimation: function() { + this.panelBox.anchor_y = this.panelBox.height; + + let plymouthTransitionRunning = false; + + // If we're the greeter, put up the xrootpmap actor + // and fade it out to have a nice transition from plymouth + // to the greeter. Otherwise, we'll just animate the panel, + // as usual. + if (Main.sessionMode.isGreeter) { + this._rootPixmap = global.create_xrootpmap_texture(); + if (this._rootPixmap != null) { + Main.uiGroup.add_actor(this._rootPixmap); + Tweener.addTween(this._rootPixmap, + { opacity: 0, + time: PLYMOUTH_TRANSITION_TIME, + transition: 'linear', + onComplete: this._fadeRootpmapComplete, + onCompleteScope: this }); + plymouthTransitionRunning = true; + } + } + + if (!plymouthTransitionRunning) + this._fadeRootpmapComplete(); + }, + + _fadeRootpmapComplete: function() { // Don't animate the strut this._chrome.freezeUpdateRegions(); - this.panelBox.anchor_y = this.panelBox.height; + if (this._rootPixmap != null) { + this._rootPixmap.destroy(); + this._rootPixmap = null; + } + Tweener.addTween(this.panelBox, { anchor_y: 0, time: STARTUP_ANIMATION_TIME, diff --git a/src/shell-global.c b/src/shell-global.c index c95f07803..d82885da3 100644 --- a/src/shell-global.c +++ b/src/shell-global.c @@ -1693,3 +1693,43 @@ shell_global_get_session_mode (ShellGlobal *global) return global->session_mode; } + +/** + * shell_global_create_xrootpmap_texture: + * @global: The #ShellGlobal + * + * This returns the _XROOTPMAP_ID pixmap that gdm should have stuffed + * in the root window. The goal here is to allow a smooth fade between + * plymouth and the shell greeter. This is also a workaround for gjs not + * supporting raw xlib types. + * + * Returns: (transfer floating): A #ClutterActor that represents the + * _XROOTPMAP_ID pixmap property from the root window. + */ +ClutterActor * +shell_global_create_xrootpmap_texture (ShellGlobal *global) +{ + Atom res_type; + int res_format; + unsigned long res_nitems, bytesafter; + unsigned char *data; + Pixmap root_pixmap_id = None; + + g_return_val_if_fail (SHELL_IS_GLOBAL (global), NULL); + + if (XGetWindowProperty (global->xdisplay, + DefaultRootWindow (global->xdisplay), + XInternAtom (global->xdisplay, "_XROOTPMAP_ID", False), + 0, G_MAXLONG, False, XA_PIXMAP, + &res_type, &res_format, &res_nitems, &bytesafter, &data) == Success) + { + if (res_type == XA_PIXMAP && res_format == 32 && res_nitems == 1) + root_pixmap_id = * (Pixmap *) data; + XFree (data); + } + + if (root_pixmap_id != None) + return clutter_x11_texture_pixmap_new_with_pixmap (root_pixmap_id); + else + return NULL; +} diff --git a/src/shell-global.h b/src/shell-global.h index 95c18e095..693cb41fa 100644 --- a/src/shell-global.h +++ b/src/shell-global.h @@ -136,6 +136,8 @@ void shell_global_reexec_self (ShellGlobal *global); const char * shell_global_get_session_mode (ShellGlobal *global); +ClutterActor * shell_global_create_xrootpmap_texture (ShellGlobal *global); + G_END_DECLS #endif /* __SHELL_GLOBAL_H__ */