Blame SOURCES/login-banner-fixes.patch

13bb5b
From b0f59711785d43d0d3dd76e09064e36bea516e1b Mon Sep 17 00:00:00 2001
13bb5b
From: Ray Strode <rstrode@redhat.com>
13bb5b
Date: Wed, 12 Nov 2014 11:27:50 -0500
13bb5b
Subject: [PATCH 1/5] Revert "loginDialog: make banner message more prominent."
13bb5b
13bb5b
This reverts commit 1f00c48feb75a8749b80a7cace94f622df825f7c.
13bb5b
---
13bb5b
 data/theme/gnome-shell.css | 13 ++++++++-----
13bb5b
 js/gdm/loginDialog.js      | 44 ++++++++++++++++++++++----------------------
13bb5b
 2 files changed, 30 insertions(+), 27 deletions(-)
13bb5b
13bb5b
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
13bb5b
index e12c78d..0db9d1e 100644
13bb5b
--- a/data/theme/gnome-shell.css
13bb5b
+++ b/data/theme/gnome-shell.css
13bb5b
@@ -2188,65 +2188,68 @@ StScrollBar StButton#vhandle:active {
13bb5b
     border-radius: 4px;
13bb5b
     background-color: rgba(255,255,255,0.1);
13bb5b
 }
13bb5b
 .candidate-page-button-box {
13bb5b
     height: 2em;
13bb5b
     width: 80px;
13bb5b
 }
13bb5b
 
13bb5b
 .vertical .candidate-page-button-box {
13bb5b
     padding-top: 0.5em;
13bb5b
 }
13bb5b
 
13bb5b
 .horizontal .candidate-page-button-box {
13bb5b
     padding-left: 0.5em;
13bb5b
 }
13bb5b
 
13bb5b
 .candidate-page-button-previous {
13bb5b
     border-radius: 4px 0px 0px 4px;
13bb5b
 }
13bb5b
 
13bb5b
 .candidate-page-button-next {
13bb5b
     border-radius: 0px 4px 4px 0px;
13bb5b
 }
13bb5b
 
13bb5b
 .candidate-page-button-icon {
13bb5b
     icon-size: 1em;
13bb5b
 }
13bb5b
 
13bb5b
 /* Login Dialog */
13bb5b
 .login-dialog-banner-view {
13bb5b
-    padding-top: 96px;
13bb5b
-    padding-left: 1em;
13bb5b
-    height: 14em;
13bb5b
-    max-width: 42em;
13bb5b
-    min-width: 25em;
13bb5b
+    padding-top: 10em;
13bb5b
+    height: 10em;
13bb5b
+}
13bb5b
+
13bb5b
+.login-dialog-banner {
13bb5b
+    font-size: 9pt;
13bb5b
+    color: #666666;
13bb5b
+    width: 30em;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog-title {
13bb5b
     font-size: 14pt;
13bb5b
     font-weight: bold;
13bb5b
     color: #666666;
13bb5b
     padding-bottom: 2em;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog {
13bb5b
     /* Reset border and background */
13bb5b
     border: none;
13bb5b
     background-color: transparent;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog-button-box {
13bb5b
     spacing: 5px;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog-user-list-view {
13bb5b
     -st-vfade-offset: 1em;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog-user-list {
13bb5b
     spacing: 12px;
13bb5b
     padding: .2em;
13bb5b
     width: 23em;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog-user-list-item {
13bb5b
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
13bb5b
index 8f5044f..aadc5a9 100644
13bb5b
--- a/js/gdm/loginDialog.js
13bb5b
+++ b/js/gdm/loginDialog.js
13bb5b
@@ -407,136 +407,136 @@ const LoginDialog = new Lang.Class({
13bb5b
         this._userManager = AccountsService.UserManager.get_default()
13bb5b
         let gdmClient = new Gdm.Client();
13bb5b
 
13bb5b
         if (GLib.getenv('GDM_GREETER_TEST') != '1') {
13bb5b
             this._greeter = gdmClient.get_greeter_sync(null);
13bb5b
 
13bb5b
             this._greeter.connect('default-session-name-changed',
13bb5b
                                   Lang.bind(this, this._onDefaultSessionChanged));
13bb5b
 
13bb5b
             this._greeter.connect('session-opened',
13bb5b
                                   Lang.bind(this, this._onSessionOpened));
13bb5b
             this._greeter.connect('timed-login-requested',
13bb5b
                                   Lang.bind(this, this._onTimedLoginRequested));
13bb5b
         }
13bb5b
 
13bb5b
         this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
13bb5b
 
13bb5b
         this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY,
13bb5b
                                Lang.bind(this, this._updateBanner));
13bb5b
         this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_TEXT_KEY,
13bb5b
                                Lang.bind(this, this._updateBanner));
13bb5b
         this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY,
13bb5b
                                Lang.bind(this, this._updateDisableUserList));
13bb5b
         this._settings.connect('changed::' + GdmUtil.LOGO_KEY,
13bb5b
                                Lang.bind(this, this._updateLogo));
13bb5b
 
13bb5b
         this._textureCache = St.TextureCache.get_default();
13bb5b
         this._textureCache.connect('texture-file-changed',
13bb5b
                                    Lang.bind(this, this._updateLogoTexture));
13bb5b
 
13bb5b
-        let outerBox = new St.BoxLayout({ x_align: Clutter.ActorAlign.CENTER,
13bb5b
-                                          y_align: Clutter.ActorAlign.START,
13bb5b
-                                          y_expand: true,
13bb5b
-                                          vertical: true });
13bb5b
-        table.pack(outerBox, 0, 0);
13bb5b
-        this._bannerView = new St.ScrollView({ style_class: 'login-dialog-banner-view',
13bb5b
-                                               opacity: 0,
13bb5b
-                                               vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
13bb5b
-                                               hscrollbar_policy: Gtk.PolicyType.NEVER });
13bb5b
-        outerBox.add_actor(this._bannerView);
13bb5b
-
13bb5b
-        let innerBox = new St.BoxLayout({ vertical: true });
13bb5b
-
13bb5b
-        this._bannerView.add_actor(innerBox);
13bb5b
-        this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
13bb5b
-                                           text: '' });
13bb5b
-        this._bannerLabel.clutter_text.line_wrap = true;
13bb5b
-        this._bannerLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
13bb5b
-        innerBox.add_child(this._bannerLabel);
13bb5b
-        this._updateBanner();
13bb5b
-
13bb5b
         this._userSelectionBox = new St.BoxLayout({ style_class: 'login-dialog-user-selection-box',
13bb5b
                                                     x_align: Clutter.ActorAlign.CENTER,
13bb5b
                                                     y_align: Clutter.ActorAlign.CENTER,
13bb5b
                                                     x_expand: true,
13bb5b
                                                     y_expand: true,
13bb5b
                                                     vertical: true,
13bb5b
                                                     visible: false });
13bb5b
         this._userList = new UserList();
13bb5b
         this._userSelectionBox.add(this._userList.actor,
13bb5b
                                    { expand: true,
13bb5b
                                      x_fill: true,
13bb5b
                                      y_fill: true });
13bb5b
 
13bb5b
         this._authPrompt = new AuthPrompt.AuthPrompt(gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_OR_LOG_IN);
13bb5b
         this._authPrompt.connect('prompted', Lang.bind(this, this._onPrompted));
13bb5b
         this._authPrompt.connect('reset', Lang.bind(this, this._onReset));
13bb5b
         this._authPrompt.hide();
13bb5b
         this._authPrompt.actor.x_align = Clutter.ActorAlign.CENTER;
13bb5b
         this._authPrompt.actor.y_align = Clutter.ActorAlign.CENTER;
13bb5b
         this._authPrompt.actor.x_expand = false;
13bb5b
         this._authPrompt.actor.y_expand = false;
13bb5b
         table.pack(this._authPrompt.actor, 0, 0);
13bb5b
         table.set_span(this._authPrompt.actor, 1, 3);
13bb5b
 
13bb5b
         // translators: this message is shown below the user list on the
13bb5b
         // login screen. It can be activated to reveal an entry for
13bb5b
         // manually entering the username.
13bb5b
         let notListedLabel = new St.Label({ text: _("Not listed?"),
13bb5b
                                             style_class: 'login-dialog-not-listed-label' });
13bb5b
         this._notListedButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
13bb5b
                                                 button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
13bb5b
                                                 can_focus: true,
13bb5b
                                                 child: notListedLabel,
13bb5b
                                                 reactive: true,
13bb5b
                                                 x_align: St.Align.START,
13bb5b
                                                 x_fill: true });
13bb5b
 
13bb5b
         this._notListedButton.connect('clicked', Lang.bind(this, this._hideUserListAskForUsernameAndBeginVerification));
13bb5b
 
13bb5b
         this._notListedButton.hide();
13bb5b
 
13bb5b
         this._userSelectionBox.add(this._notListedButton,
13bb5b
                                    { expand: false,
13bb5b
                                      x_align: St.Align.START,
13bb5b
                                      x_fill: true });
13bb5b
 
13bb5b
         this._logoBin = new St.Widget({ style_class: 'login-dialog-logo-bin',
13bb5b
                                         x_align: Clutter.ActorAlign.CENTER,
13bb5b
                                         y_align: Clutter.ActorAlign.END,
13bb5b
                                         x_expand: true,
13bb5b
                                         y_expand: true });
13bb5b
 
13bb5b
         table.pack(this._userSelectionBox, 0, 0);
13bb5b
         table.set_span(this._userSelectionBox, 1, 3);
13bb5b
 
13bb5b
+        let outerBox = new St.BoxLayout({ x_align: Clutter.ActorAlign.CENTER,
13bb5b
+                                          y_align: Clutter.ActorAlign.CENTER,
13bb5b
+                                          vertical: true });
13bb5b
+        table.pack(outerBox, 0, 2);
13bb5b
+        table.set_span(outerBox, 1, 1);
13bb5b
+        this._bannerView = new St.ScrollView({ style_class: 'login-dialog-banner-view',
13bb5b
+                                               opacity: 0,
13bb5b
+                                               vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
13bb5b
+                                               hscrollbar_policy: Gtk.PolicyType.NEVER });
13bb5b
+        outerBox.add_actor(this._bannerView);
13bb5b
+
13bb5b
+        let innerBox = new St.BoxLayout({ vertical: true });
13bb5b
+
13bb5b
+        this._bannerView.add_actor(innerBox);
13bb5b
+        this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
13bb5b
+                                           text: '' });
13bb5b
+        this._bannerLabel.clutter_text.line_wrap = true;
13bb5b
+        this._bannerLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
13bb5b
+        innerBox.add_child(this._bannerLabel);
13bb5b
+        this._updateBanner();
13bb5b
+
13bb5b
         table.pack(this._logoBin, 0, 2);
13bb5b
         table.set_span(this._logoBin, 1, 1);
13bb5b
         this._updateLogo();
13bb5b
 
13bb5b
         // We have overlapping widgets to obtain the kind of centering we want.
13bb5b
         // We need to make sure the widgets that take input are on top of the
13bb5b
         // stack.
13bb5b
         this.actor.set_child_above_sibling(this._userSelectionBox, null);
13bb5b
         this.actor.set_child_above_sibling(this._authPrompt.actor, null);
13bb5b
 
13bb5b
         this._userList.connect('activate',
13bb5b
                                Lang.bind(this, function(userList, item) {
13bb5b
                                    this._onUserListActivated(item);
13bb5b
                                }));
13bb5b
 
13bb5b
 
13bb5b
         this._sessionMenuButton = new SessionMenuButton();
13bb5b
         this._sessionMenuButton.connect('session-activated',
13bb5b
                                   Lang.bind(this, function(list, sessionId) {
13bb5b
                                                 this._greeter.call_select_session_sync (sessionId, null);
13bb5b
                                             }));
13bb5b
         this._sessionMenuButton.actor.opacity = 0;
13bb5b
         this._sessionMenuButton.actor.show();
13bb5b
         this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton.actor);
13bb5b
 
13bb5b
         this._disableUserList = undefined;
13bb5b
         this._userListLoaded = false;
13bb5b
 
13bb5b
         // If the user list is enabled, it should take key focus; make sure the
13bb5b
         // screen shield is initialized first to prevent it from stealing the
13bb5b
@@ -599,107 +599,107 @@ const LoginDialog = new Lang.Class({
13bb5b
         Tweener.addTween(this._bannerView,
13bb5b
                          { opacity: 255,
13bb5b
                            time: _FADE_ANIMATION_TIME,
13bb5b
                            transition: 'easeOutQuad' });
13bb5b
     },
13bb5b
 
13bb5b
     _hideBannerView: function() {
13bb5b
         Tweener.removeTweens(this._bannerView);
13bb5b
         this._bannerView.opacity = 0;
13bb5b
     },
13bb5b
 
13bb5b
     _updateLogoTexture: function(cache, uri) {
13bb5b
         if (this._logoFileUri != uri)
13bb5b
             return;
13bb5b
 
13bb5b
         this._logoBin.destroy_all_children();
13bb5b
         if (this._logoFileUri)
13bb5b
             this._logoBin.add_child(this._textureCache.load_uri_async(this._logoFileUri,
13bb5b
                                                                       -1, _LOGO_ICON_HEIGHT));
13bb5b
     },
13bb5b
 
13bb5b
     _updateLogo: function() {
13bb5b
         let path = this._settings.get_string(GdmUtil.LOGO_KEY);
13bb5b
 
13bb5b
         this._logoFileUri = path ? Gio.file_new_for_path(path).get_uri() : null;
13bb5b
         this._updateLogoTexture(this._textureCache, this._logoFileUri);
13bb5b
     },
13bb5b
 
13bb5b
     _onPrompted: function() {
13bb5b
         this._sessionMenuButton.updateSensitivity(true);
13bb5b
+        this._fadeInBannerView();
13bb5b
 
13bb5b
         if (this._shouldShowSessionMenuButton())
13bb5b
             this._authPrompt.setActorInDefaultButtonWell(this._sessionMenuButton.actor);
13bb5b
         this._showPrompt();
13bb5b
     },
13bb5b
 
13bb5b
     _onReset: function(authPrompt, beginRequest) {
13bb5b
         this._sessionMenuButton.updateSensitivity(true);
13bb5b
         this._hideBannerView();
13bb5b
 
13bb5b
         this._user = null;
13bb5b
 
13bb5b
         if (beginRequest == AuthPrompt.BeginRequestType.PROVIDE_USERNAME) {
13bb5b
             if (!this._disableUserList)
13bb5b
                 this._showUserList();
13bb5b
             else
13bb5b
                 this._hideUserListAskForUsernameAndBeginVerification();
13bb5b
         } else {
13bb5b
             this._hideUserListAndBeginVerification();
13bb5b
         }
13bb5b
     },
13bb5b
 
13bb5b
     _onDefaultSessionChanged: function(client, sessionId) {
13bb5b
         this._sessionMenuButton.setActiveSession(sessionId);
13bb5b
     },
13bb5b
 
13bb5b
     _shouldShowSessionMenuButton: function() {
13bb5b
         if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFYING &&
13bb5b
             this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFICATION_FAILED)
13bb5b
           return false;
13bb5b
 
13bb5b
         if (this._user && this._user.is_loaded && this._user.is_logged_in())
13bb5b
           return false;
13bb5b
 
13bb5b
         return true;
13bb5b
     },
13bb5b
 
13bb5b
     _showPrompt: function() {
13bb5b
         if (this._authPrompt.actor.visible)
13bb5b
             return;
13bb5b
         this._authPrompt.actor.opacity = 0;
13bb5b
         this._authPrompt.actor.show();
13bb5b
         Tweener.addTween(this._authPrompt.actor,
13bb5b
                          { opacity: 255,
13bb5b
                            time: _FADE_ANIMATION_TIME,
13bb5b
                            transition: 'easeOutQuad' });
13bb5b
-        this._fadeInBannerView();
13bb5b
     },
13bb5b
 
13bb5b
     _showRealmLoginHint: function(realmManager, hint) {
13bb5b
         if (!hint)
13bb5b
             return;
13bb5b
 
13bb5b
         hint = hint.replace(/%U/g, 'user');
13bb5b
         hint = hint.replace(/%D/g, 'DOMAIN');
13bb5b
         hint = hint.replace(/%[^UD]/g, '');
13bb5b
 
13bb5b
         // Translators: this message is shown below the username entry field
13bb5b
         // to clue the user in on how to login to the local network realm
13bb5b
         this._authPrompt.setMessage(_("(e.g., user or %s)").format(hint), GdmUtil.MessageType.HINT);
13bb5b
     },
13bb5b
 
13bb5b
     _askForUsernameAndBeginVerification: function() {
13bb5b
         this._authPrompt.setPasswordChar('');
13bb5b
         this._authPrompt.setQuestion(_("Username: "));
13bb5b
 
13bb5b
         let realmManager = new Realmd.Manager();
13bb5b
         let realmSignalId = realmManager.connect('login-format-changed',
13bb5b
                                                  Lang.bind(this, this._showRealmLoginHint));
13bb5b
         this._showRealmLoginHint(realmManager.loginFormat);
13bb5b
 
13bb5b
         let nextSignalId = this._authPrompt.connect('next',
13bb5b
                                                     Lang.bind(this, function() {
13bb5b
                                                         this._authPrompt.disconnect(nextSignalId);
13bb5b
                                                         this._authPrompt.updateSensitivity(false);
13bb5b
                                                         let answer = this._authPrompt.getAnswer();
13bb5b
                                                         this._user = this._userManager.get_user(answer);
13bb5b
-- 
13bb5b
2.1.0
13bb5b
13bb5b
13bb5b
From c5ef28f7ccc96bf6ed57c80fe98cd5fe31f4004d Mon Sep 17 00:00:00 2001
13bb5b
From: Ray Strode <rstrode@redhat.com>
13bb5b
Date: Wed, 12 Nov 2014 11:29:22 -0500
13bb5b
Subject: [PATCH 2/5] Revert "loginDialog: display banner message when
13bb5b
 disable-user-list=true"
13bb5b
13bb5b
This reverts commit b94289671424068d973a553fb610398830d25e21.
13bb5b
13bb5b
Conflicts:
13bb5b
	js/gdm/loginDialog.js
13bb5b
---
13bb5b
 data/theme/gnome-shell.css | 10 +++---
13bb5b
 js/gdm/loginDialog.js      | 76 +++++++++++++---------------------------------
13bb5b
 2 files changed, 25 insertions(+), 61 deletions(-)
13bb5b
13bb5b
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
13bb5b
index 0db9d1e..aa82632 100644
13bb5b
--- a/data/theme/gnome-shell.css
13bb5b
+++ b/data/theme/gnome-shell.css
13bb5b
@@ -2187,69 +2187,67 @@ StScrollBar StButton#vhandle:active {
13bb5b
 .candidate-box:hover {
13bb5b
     border-radius: 4px;
13bb5b
     background-color: rgba(255,255,255,0.1);
13bb5b
 }
13bb5b
 .candidate-page-button-box {
13bb5b
     height: 2em;
13bb5b
     width: 80px;
13bb5b
 }
13bb5b
 
13bb5b
 .vertical .candidate-page-button-box {
13bb5b
     padding-top: 0.5em;
13bb5b
 }
13bb5b
 
13bb5b
 .horizontal .candidate-page-button-box {
13bb5b
     padding-left: 0.5em;
13bb5b
 }
13bb5b
 
13bb5b
 .candidate-page-button-previous {
13bb5b
     border-radius: 4px 0px 0px 4px;
13bb5b
 }
13bb5b
 
13bb5b
 .candidate-page-button-next {
13bb5b
     border-radius: 0px 4px 4px 0px;
13bb5b
 }
13bb5b
 
13bb5b
 .candidate-page-button-icon {
13bb5b
     icon-size: 1em;
13bb5b
 }
13bb5b
 
13bb5b
 /* Login Dialog */
13bb5b
-.login-dialog-banner-view {
13bb5b
-    padding-top: 10em;
13bb5b
-    height: 10em;
13bb5b
-}
13bb5b
 
13bb5b
 .login-dialog-banner {
13bb5b
-    font-size: 9pt;
13bb5b
+    font-size: 10pt;
13bb5b
+    font-weight: bold;
13bb5b
+    text-align: center;
13bb5b
     color: #666666;
13bb5b
-    width: 30em;
13bb5b
+    padding-bottom: 1em;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog-title {
13bb5b
     font-size: 14pt;
13bb5b
     font-weight: bold;
13bb5b
     color: #666666;
13bb5b
     padding-bottom: 2em;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog {
13bb5b
     /* Reset border and background */
13bb5b
     border: none;
13bb5b
     background-color: transparent;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog-button-box {
13bb5b
     spacing: 5px;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog-user-list-view {
13bb5b
     -st-vfade-offset: 1em;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog-user-list {
13bb5b
     spacing: 12px;
13bb5b
     padding: .2em;
13bb5b
     width: 23em;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog-user-list-item {
13bb5b
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
13bb5b
index aadc5a9..f35921c 100644
13bb5b
--- a/js/gdm/loginDialog.js
13bb5b
+++ b/js/gdm/loginDialog.js
13bb5b
@@ -1,61 +1,60 @@
13bb5b
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
13bb5b
 /*
13bb5b
  * Copyright 2011 Red Hat, Inc
13bb5b
  *
13bb5b
  * This program is free software; you can redistribute it and/or modify
13bb5b
  * it under the terms of the GNU General Public License as published by
13bb5b
  * the Free Software Foundation; either version 2, or (at your option)
13bb5b
  * any later version.
13bb5b
  *
13bb5b
  * This program is distributed in the hope that it will be useful,
13bb5b
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13bb5b
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13bb5b
  * GNU General Public License for more details.
13bb5b
  *
13bb5b
  * You should have received a copy of the GNU General Public License
13bb5b
  * along with this program; if not, write to the Free Software
13bb5b
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
13bb5b
  * 02111-1307, USA.
13bb5b
  */
13bb5b
 
13bb5b
 const AccountsService = imports.gi.AccountsService;
13bb5b
 const Atk = imports.gi.Atk;
13bb5b
 const Clutter = imports.gi.Clutter;
13bb5b
 const Gdm = imports.gi.Gdm;
13bb5b
 const Gio = imports.gi.Gio;
13bb5b
 const GLib = imports.gi.GLib;
13bb5b
 const Gtk = imports.gi.Gtk;
13bb5b
 const Lang = imports.lang;
13bb5b
 const Mainloop = imports.mainloop;
13bb5b
 const Meta = imports.gi.Meta;
13bb5b
-const Pango = imports.gi.Pango;
13bb5b
 const Shell = imports.gi.Shell;
13bb5b
 const Signals = imports.signals;
13bb5b
 const St = imports.gi.St;
13bb5b
 
13bb5b
 const AuthPrompt = imports.gdm.authPrompt;
13bb5b
 const Batch = imports.gdm.batch;
13bb5b
 const BoxPointer = imports.ui.boxpointer;
13bb5b
 const CtrlAltTab = imports.ui.ctrlAltTab;
13bb5b
 const GdmUtil = imports.gdm.util;
13bb5b
 const Layout = imports.ui.layout;
13bb5b
 const Main = imports.ui.main;
13bb5b
 const PopupMenu = imports.ui.popupMenu;
13bb5b
 const Realmd = imports.gdm.realmd;
13bb5b
 const Tweener = imports.ui.tweener;
13bb5b
 const UserMenu = imports.ui.userMenu;
13bb5b
 const UserWidget = imports.ui.userWidget;
13bb5b
 
13bb5b
 const _FADE_ANIMATION_TIME = 0.25;
13bb5b
 const _SCROLL_ANIMATION_TIME = 0.5;
13bb5b
 const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
13bb5b
 const _LOGO_ICON_HEIGHT = 48;
13bb5b
 
13bb5b
 let _loginDialog = null;
13bb5b
 
13bb5b
 const UserListItem = new Lang.Class({
13bb5b
     Name: 'UserListItem',
13bb5b
 
13bb5b
     _init: function(user) {
13bb5b
         this.user = user;
13bb5b
         this._userChangedId = this.user.connect('changed',
13bb5b
@@ -367,185 +366,166 @@ const SessionMenuButton = new Lang.Class({
13bb5b
         ids.sort();
13bb5b
 
13bb5b
         if (ids.length <= 1) {
13bb5b
             this._button.hide();
13bb5b
             return;
13bb5b
         }
13bb5b
 
13bb5b
         for (let i = 0; i < ids.length; i++) {
13bb5b
             let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]);
13bb5b
 
13bb5b
             let id = ids[i];
13bb5b
             let item = new PopupMenu.PopupMenuItem(sessionName);
13bb5b
             this._menu.addMenuItem(item);
13bb5b
             this._items[id] = item;
13bb5b
 
13bb5b
             if (!this._activeSessionId)
13bb5b
                 this.setActiveSession(id);
13bb5b
 
13bb5b
             item.connect('activate', Lang.bind(this, function() {
13bb5b
                 this.setActiveSession(id);
13bb5b
             }));
13bb5b
         }
13bb5b
     }
13bb5b
 });
13bb5b
 Signals.addSignalMethods(SessionMenuButton.prototype);
13bb5b
 
13bb5b
 const LoginDialog = new Lang.Class({
13bb5b
     Name: 'LoginDialog',
13bb5b
 
13bb5b
     _init: function(parentActor) {
13bb5b
-        let table = new Clutter.TableLayout();
13bb5b
         this.actor = new St.Widget({ accessible_role: Atk.Role.WINDOW,
13bb5b
-                                     layout_manager: table,
13bb5b
+                                     layout_manager: new Clutter.BinLayout(),
13bb5b
                                      style_class: 'login-dialog',
13bb5b
                                      visible: false });
13bb5b
 
13bb5b
         this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true }));
13bb5b
         this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
13bb5b
         parentActor.add_child(this.actor);
13bb5b
 
13bb5b
         this._userManager = AccountsService.UserManager.get_default()
13bb5b
         let gdmClient = new Gdm.Client();
13bb5b
 
13bb5b
         if (GLib.getenv('GDM_GREETER_TEST') != '1') {
13bb5b
             this._greeter = gdmClient.get_greeter_sync(null);
13bb5b
 
13bb5b
             this._greeter.connect('default-session-name-changed',
13bb5b
                                   Lang.bind(this, this._onDefaultSessionChanged));
13bb5b
 
13bb5b
             this._greeter.connect('session-opened',
13bb5b
                                   Lang.bind(this, this._onSessionOpened));
13bb5b
             this._greeter.connect('timed-login-requested',
13bb5b
                                   Lang.bind(this, this._onTimedLoginRequested));
13bb5b
         }
13bb5b
 
13bb5b
         this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
13bb5b
 
13bb5b
         this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY,
13bb5b
                                Lang.bind(this, this._updateBanner));
13bb5b
         this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_TEXT_KEY,
13bb5b
                                Lang.bind(this, this._updateBanner));
13bb5b
         this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY,
13bb5b
                                Lang.bind(this, this._updateDisableUserList));
13bb5b
         this._settings.connect('changed::' + GdmUtil.LOGO_KEY,
13bb5b
                                Lang.bind(this, this._updateLogo));
13bb5b
 
13bb5b
         this._textureCache = St.TextureCache.get_default();
13bb5b
         this._textureCache.connect('texture-file-changed',
13bb5b
                                    Lang.bind(this, this._updateLogoTexture));
13bb5b
 
13bb5b
         this._userSelectionBox = new St.BoxLayout({ style_class: 'login-dialog-user-selection-box',
13bb5b
                                                     x_align: Clutter.ActorAlign.CENTER,
13bb5b
                                                     y_align: Clutter.ActorAlign.CENTER,
13bb5b
                                                     x_expand: true,
13bb5b
                                                     y_expand: true,
13bb5b
                                                     vertical: true,
13bb5b
                                                     visible: false });
13bb5b
+        this.actor.add_child(this._userSelectionBox);
13bb5b
+
13bb5b
+        this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
13bb5b
+                                           text: '' });
13bb5b
+        this._userSelectionBox.add(this._bannerLabel);
13bb5b
+        this._updateBanner();
13bb5b
+
13bb5b
         this._userList = new UserList();
13bb5b
         this._userSelectionBox.add(this._userList.actor,
13bb5b
                                    { expand: true,
13bb5b
                                      x_fill: true,
13bb5b
                                      y_fill: true });
13bb5b
 
13bb5b
         this._authPrompt = new AuthPrompt.AuthPrompt(gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_OR_LOG_IN);
13bb5b
         this._authPrompt.connect('prompted', Lang.bind(this, this._onPrompted));
13bb5b
         this._authPrompt.connect('reset', Lang.bind(this, this._onReset));
13bb5b
         this._authPrompt.hide();
13bb5b
-        this._authPrompt.actor.x_align = Clutter.ActorAlign.CENTER;
13bb5b
-        this._authPrompt.actor.y_align = Clutter.ActorAlign.CENTER;
13bb5b
-        this._authPrompt.actor.x_expand = false;
13bb5b
-        this._authPrompt.actor.y_expand = false;
13bb5b
-        table.pack(this._authPrompt.actor, 0, 0);
13bb5b
-        table.set_span(this._authPrompt.actor, 1, 3);
13bb5b
+        this.actor.add_child(this._authPrompt.actor);
13bb5b
 
13bb5b
         // translators: this message is shown below the user list on the
13bb5b
         // login screen. It can be activated to reveal an entry for
13bb5b
         // manually entering the username.
13bb5b
         let notListedLabel = new St.Label({ text: _("Not listed?"),
13bb5b
                                             style_class: 'login-dialog-not-listed-label' });
13bb5b
         this._notListedButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
13bb5b
                                                 button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
13bb5b
                                                 can_focus: true,
13bb5b
                                                 child: notListedLabel,
13bb5b
                                                 reactive: true,
13bb5b
                                                 x_align: St.Align.START,
13bb5b
                                                 x_fill: true });
13bb5b
 
13bb5b
         this._notListedButton.connect('clicked', Lang.bind(this, this._hideUserListAskForUsernameAndBeginVerification));
13bb5b
 
13bb5b
         this._notListedButton.hide();
13bb5b
 
13bb5b
         this._userSelectionBox.add(this._notListedButton,
13bb5b
                                    { expand: false,
13bb5b
                                      x_align: St.Align.START,
13bb5b
                                      x_fill: true });
13bb5b
 
13bb5b
         this._logoBin = new St.Widget({ style_class: 'login-dialog-logo-bin',
13bb5b
                                         x_align: Clutter.ActorAlign.CENTER,
13bb5b
                                         y_align: Clutter.ActorAlign.END,
13bb5b
                                         x_expand: true,
13bb5b
                                         y_expand: true });
13bb5b
-
13bb5b
-        table.pack(this._userSelectionBox, 0, 0);
13bb5b
-        table.set_span(this._userSelectionBox, 1, 3);
13bb5b
-
13bb5b
-        let outerBox = new St.BoxLayout({ x_align: Clutter.ActorAlign.CENTER,
13bb5b
-                                          y_align: Clutter.ActorAlign.CENTER,
13bb5b
-                                          vertical: true });
13bb5b
-        table.pack(outerBox, 0, 2);
13bb5b
-        table.set_span(outerBox, 1, 1);
13bb5b
-        this._bannerView = new St.ScrollView({ style_class: 'login-dialog-banner-view',
13bb5b
-                                               opacity: 0,
13bb5b
-                                               vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
13bb5b
-                                               hscrollbar_policy: Gtk.PolicyType.NEVER });
13bb5b
-        outerBox.add_actor(this._bannerView);
13bb5b
-
13bb5b
-        let innerBox = new St.BoxLayout({ vertical: true });
13bb5b
-
13bb5b
-        this._bannerView.add_actor(innerBox);
13bb5b
-        this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
13bb5b
-                                           text: '' });
13bb5b
-        this._bannerLabel.clutter_text.line_wrap = true;
13bb5b
-        this._bannerLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
13bb5b
-        innerBox.add_child(this._bannerLabel);
13bb5b
-        this._updateBanner();
13bb5b
-
13bb5b
-        table.pack(this._logoBin, 0, 2);
13bb5b
-        table.set_span(this._logoBin, 1, 1);
13bb5b
+        this.actor.add_child(this._logoBin);
13bb5b
         this._updateLogo();
13bb5b
 
13bb5b
-        // We have overlapping widgets to obtain the kind of centering we want.
13bb5b
-        // We need to make sure the widgets that take input are on top of the
13bb5b
-        // stack.
13bb5b
-        this.actor.set_child_above_sibling(this._userSelectionBox, null);
13bb5b
-        this.actor.set_child_above_sibling(this._authPrompt.actor, null);
13bb5b
+        if (!this._userManager.is_loaded)
13bb5b
+            this._userManagerLoadedId = this._userManager.connect('notify::is-loaded',
13bb5b
+                                                                  Lang.bind(this, function() {
13bb5b
+                                                                      if (this._userManager.is_loaded) {
13bb5b
+                                                                          this._loadUserList();
13bb5b
+                                                                          this._userManager.disconnect(this._userManagerLoadedId);
13bb5b
+                                                                          this._userManagerLoadedId = 0;
13bb5b
+                                                                      }
13bb5b
+                                                                  }));
13bb5b
+        else
13bb5b
+            this._loadUserList();
13bb5b
 
13bb5b
         this._userList.connect('activate',
13bb5b
                                Lang.bind(this, function(userList, item) {
13bb5b
                                    this._onUserListActivated(item);
13bb5b
                                }));
13bb5b
 
13bb5b
 
13bb5b
         this._sessionMenuButton = new SessionMenuButton();
13bb5b
         this._sessionMenuButton.connect('session-activated',
13bb5b
                                   Lang.bind(this, function(list, sessionId) {
13bb5b
                                                 this._greeter.call_select_session_sync (sessionId, null);
13bb5b
                                             }));
13bb5b
         this._sessionMenuButton.actor.opacity = 0;
13bb5b
         this._sessionMenuButton.actor.show();
13bb5b
         this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton.actor);
13bb5b
 
13bb5b
         this._disableUserList = undefined;
13bb5b
         this._userListLoaded = false;
13bb5b
 
13bb5b
         // If the user list is enabled, it should take key focus; make sure the
13bb5b
         // screen shield is initialized first to prevent it from stealing the
13bb5b
         // focus later
13bb5b
         Main.layoutManager.connect('startup-complete',
13bb5b
                                    Lang.bind(this, this._updateDisableUserList));
13bb5b
     },
13bb5b
 
13bb5b
     _ensureUserListLoaded: function() {
13bb5b
         if (!this._userManager.is_loaded)
13bb5b
             this._userManagerLoadedId = this._userManager.connect('notify::is-loaded',
13bb5b
                                                                   Lang.bind(this, function() {
13bb5b
@@ -568,101 +548,87 @@ const LoginDialog = new Lang.Class({
13bb5b
             if (this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
13bb5b
                 this._authPrompt.reset();
13bb5b
         }
13bb5b
     },
13bb5b
 
13bb5b
     _updateCancelButton: function() {
13bb5b
         let cancelVisible;
13bb5b
 
13bb5b
         // Hide the cancel button if the user list is disabled and we're asking for
13bb5b
         // a username
13bb5b
         if (this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING && this._disableUserList)
13bb5b
             cancelVisible = false;
13bb5b
         else
13bb5b
             cancelVisible = true;
13bb5b
 
13bb5b
         this._authPrompt.cancelButton.visible = cancelVisible;
13bb5b
     },
13bb5b
 
13bb5b
     _updateBanner: function() {
13bb5b
         let enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY);
13bb5b
         let text = this._settings.get_string(GdmUtil.BANNER_MESSAGE_TEXT_KEY);
13bb5b
 
13bb5b
         if (enabled && text) {
13bb5b
             this._bannerLabel.set_text(text);
13bb5b
             this._bannerLabel.show();
13bb5b
         } else {
13bb5b
             this._bannerLabel.hide();
13bb5b
         }
13bb5b
     },
13bb5b
 
13bb5b
-    _fadeInBannerView: function() {
13bb5b
-        Tweener.addTween(this._bannerView,
13bb5b
-                         { opacity: 255,
13bb5b
-                           time: _FADE_ANIMATION_TIME,
13bb5b
-                           transition: 'easeOutQuad' });
13bb5b
-    },
13bb5b
-
13bb5b
-    _hideBannerView: function() {
13bb5b
-        Tweener.removeTweens(this._bannerView);
13bb5b
-        this._bannerView.opacity = 0;
13bb5b
-    },
13bb5b
-
13bb5b
     _updateLogoTexture: function(cache, uri) {
13bb5b
         if (this._logoFileUri != uri)
13bb5b
             return;
13bb5b
 
13bb5b
         this._logoBin.destroy_all_children();
13bb5b
         if (this._logoFileUri)
13bb5b
             this._logoBin.add_child(this._textureCache.load_uri_async(this._logoFileUri,
13bb5b
                                                                       -1, _LOGO_ICON_HEIGHT));
13bb5b
     },
13bb5b
 
13bb5b
     _updateLogo: function() {
13bb5b
         let path = this._settings.get_string(GdmUtil.LOGO_KEY);
13bb5b
 
13bb5b
         this._logoFileUri = path ? Gio.file_new_for_path(path).get_uri() : null;
13bb5b
         this._updateLogoTexture(this._textureCache, this._logoFileUri);
13bb5b
     },
13bb5b
 
13bb5b
     _onPrompted: function() {
13bb5b
         this._sessionMenuButton.updateSensitivity(true);
13bb5b
-        this._fadeInBannerView();
13bb5b
 
13bb5b
         if (this._shouldShowSessionMenuButton())
13bb5b
             this._authPrompt.setActorInDefaultButtonWell(this._sessionMenuButton.actor);
13bb5b
         this._showPrompt();
13bb5b
     },
13bb5b
 
13bb5b
     _onReset: function(authPrompt, beginRequest) {
13bb5b
         this._sessionMenuButton.updateSensitivity(true);
13bb5b
-        this._hideBannerView();
13bb5b
 
13bb5b
         this._user = null;
13bb5b
 
13bb5b
         if (beginRequest == AuthPrompt.BeginRequestType.PROVIDE_USERNAME) {
13bb5b
             if (!this._disableUserList)
13bb5b
                 this._showUserList();
13bb5b
             else
13bb5b
                 this._hideUserListAskForUsernameAndBeginVerification();
13bb5b
         } else {
13bb5b
             this._hideUserListAndBeginVerification();
13bb5b
         }
13bb5b
     },
13bb5b
 
13bb5b
     _onDefaultSessionChanged: function(client, sessionId) {
13bb5b
         this._sessionMenuButton.setActiveSession(sessionId);
13bb5b
     },
13bb5b
 
13bb5b
     _shouldShowSessionMenuButton: function() {
13bb5b
         if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFYING &&
13bb5b
             this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFICATION_FAILED)
13bb5b
           return false;
13bb5b
 
13bb5b
         if (this._user && this._user.is_loaded && this._user.is_logged_in())
13bb5b
           return false;
13bb5b
 
13bb5b
         return true;
13bb5b
     },
13bb5b
 
13bb5b
     _showPrompt: function() {
13bb5b
         if (this._authPrompt.actor.visible)
13bb5b
-- 
13bb5b
2.1.0
13bb5b
13bb5b
13bb5b
From 4535550f8780b244f3e79a048c61eef3b2ed8cc8 Mon Sep 17 00:00:00 2001
13bb5b
From: Ray Strode <rstrode@redhat.com>
13bb5b
Date: Mon, 10 Nov 2014 14:36:07 -0500
13bb5b
Subject: [PATCH 3/5] loginDialog: allocate children manually
13bb5b
13bb5b
The login screen is pretty custom full screen container and the standard
13bb5b
layout managers aren't really a good fit for the kind of layout that's
13bb5b
happening. This will be even more problematic with upcoming changes
13bb5b
to login banners, so we need to switch techniques.
13bb5b
13bb5b
This commit moves login dialog over to using a custom allocate handler
13bb5b
that has specific domain knowledge of the parts of the login screen
13bb5b
and where they go.
13bb5b
---
13bb5b
 js/gdm/loginDialog.js | 94 ++++++++++++++++++++++++++++++++++++++++++++++-----
13bb5b
 1 file changed, 85 insertions(+), 9 deletions(-)
13bb5b
13bb5b
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
13bb5b
index f35921c..4835199 100644
13bb5b
--- a/js/gdm/loginDialog.js
13bb5b
+++ b/js/gdm/loginDialog.js
13bb5b
@@ -366,192 +366,268 @@ const SessionMenuButton = new Lang.Class({
13bb5b
         ids.sort();
13bb5b
 
13bb5b
         if (ids.length <= 1) {
13bb5b
             this._button.hide();
13bb5b
             return;
13bb5b
         }
13bb5b
 
13bb5b
         for (let i = 0; i < ids.length; i++) {
13bb5b
             let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]);
13bb5b
 
13bb5b
             let id = ids[i];
13bb5b
             let item = new PopupMenu.PopupMenuItem(sessionName);
13bb5b
             this._menu.addMenuItem(item);
13bb5b
             this._items[id] = item;
13bb5b
 
13bb5b
             if (!this._activeSessionId)
13bb5b
                 this.setActiveSession(id);
13bb5b
 
13bb5b
             item.connect('activate', Lang.bind(this, function() {
13bb5b
                 this.setActiveSession(id);
13bb5b
             }));
13bb5b
         }
13bb5b
     }
13bb5b
 });
13bb5b
 Signals.addSignalMethods(SessionMenuButton.prototype);
13bb5b
 
13bb5b
 const LoginDialog = new Lang.Class({
13bb5b
     Name: 'LoginDialog',
13bb5b
 
13bb5b
     _init: function(parentActor) {
13bb5b
-        this.actor = new St.Widget({ accessible_role: Atk.Role.WINDOW,
13bb5b
-                                     layout_manager: new Clutter.BinLayout(),
13bb5b
-                                     style_class: 'login-dialog',
13bb5b
-                                     visible: false });
13bb5b
+        this.actor = new Shell.GenericContainer({ style_class: 'login-dialog',
13bb5b
+                                                  visible: false });
13bb5b
+        this.actor.get_accessible().set_role(Atk.Role.WINDOW);
13bb5b
 
13bb5b
         this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true }));
13bb5b
+        this.actor.connect('allocate', Lang.bind(this, this._onAllocate));
13bb5b
         this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
13bb5b
         parentActor.add_child(this.actor);
13bb5b
 
13bb5b
         this._userManager = AccountsService.UserManager.get_default()
13bb5b
         let gdmClient = new Gdm.Client();
13bb5b
 
13bb5b
         if (GLib.getenv('GDM_GREETER_TEST') != '1') {
13bb5b
             this._greeter = gdmClient.get_greeter_sync(null);
13bb5b
 
13bb5b
             this._greeter.connect('default-session-name-changed',
13bb5b
                                   Lang.bind(this, this._onDefaultSessionChanged));
13bb5b
 
13bb5b
             this._greeter.connect('session-opened',
13bb5b
                                   Lang.bind(this, this._onSessionOpened));
13bb5b
             this._greeter.connect('timed-login-requested',
13bb5b
                                   Lang.bind(this, this._onTimedLoginRequested));
13bb5b
         }
13bb5b
 
13bb5b
         this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
13bb5b
 
13bb5b
         this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY,
13bb5b
                                Lang.bind(this, this._updateBanner));
13bb5b
         this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_TEXT_KEY,
13bb5b
                                Lang.bind(this, this._updateBanner));
13bb5b
         this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY,
13bb5b
                                Lang.bind(this, this._updateDisableUserList));
13bb5b
         this._settings.connect('changed::' + GdmUtil.LOGO_KEY,
13bb5b
                                Lang.bind(this, this._updateLogo));
13bb5b
 
13bb5b
         this._textureCache = St.TextureCache.get_default();
13bb5b
         this._textureCache.connect('texture-file-changed',
13bb5b
                                    Lang.bind(this, this._updateLogoTexture));
13bb5b
 
13bb5b
         this._userSelectionBox = new St.BoxLayout({ style_class: 'login-dialog-user-selection-box',
13bb5b
                                                     x_align: Clutter.ActorAlign.CENTER,
13bb5b
                                                     y_align: Clutter.ActorAlign.CENTER,
13bb5b
-                                                    x_expand: true,
13bb5b
-                                                    y_expand: true,
13bb5b
                                                     vertical: true,
13bb5b
                                                     visible: false });
13bb5b
         this.actor.add_child(this._userSelectionBox);
13bb5b
 
13bb5b
         this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
13bb5b
                                            text: '' });
13bb5b
         this._userSelectionBox.add(this._bannerLabel);
13bb5b
         this._updateBanner();
13bb5b
 
13bb5b
         this._userList = new UserList();
13bb5b
         this._userSelectionBox.add(this._userList.actor,
13bb5b
                                    { expand: true,
13bb5b
                                      x_fill: true,
13bb5b
                                      y_fill: true });
13bb5b
 
13bb5b
         this._authPrompt = new AuthPrompt.AuthPrompt(gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_OR_LOG_IN);
13bb5b
         this._authPrompt.connect('prompted', Lang.bind(this, this._onPrompted));
13bb5b
         this._authPrompt.connect('reset', Lang.bind(this, this._onReset));
13bb5b
         this._authPrompt.hide();
13bb5b
         this.actor.add_child(this._authPrompt.actor);
13bb5b
 
13bb5b
         // translators: this message is shown below the user list on the
13bb5b
         // login screen. It can be activated to reveal an entry for
13bb5b
         // manually entering the username.
13bb5b
         let notListedLabel = new St.Label({ text: _("Not listed?"),
13bb5b
                                             style_class: 'login-dialog-not-listed-label' });
13bb5b
         this._notListedButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
13bb5b
                                                 button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
13bb5b
                                                 can_focus: true,
13bb5b
                                                 child: notListedLabel,
13bb5b
                                                 reactive: true,
13bb5b
                                                 x_align: St.Align.START,
13bb5b
                                                 x_fill: true });
13bb5b
 
13bb5b
         this._notListedButton.connect('clicked', Lang.bind(this, this._hideUserListAskForUsernameAndBeginVerification));
13bb5b
 
13bb5b
         this._notListedButton.hide();
13bb5b
 
13bb5b
         this._userSelectionBox.add(this._notListedButton,
13bb5b
                                    { expand: false,
13bb5b
                                      x_align: St.Align.START,
13bb5b
                                      x_fill: true });
13bb5b
 
13bb5b
         this._logoBin = new St.Widget({ style_class: 'login-dialog-logo-bin',
13bb5b
                                         x_align: Clutter.ActorAlign.CENTER,
13bb5b
-                                        y_align: Clutter.ActorAlign.END,
13bb5b
-                                        x_expand: true,
13bb5b
-                                        y_expand: true });
13bb5b
+                                        y_align: Clutter.ActorAlign.END });
13bb5b
         this.actor.add_child(this._logoBin);
13bb5b
         this._updateLogo();
13bb5b
 
13bb5b
         if (!this._userManager.is_loaded)
13bb5b
             this._userManagerLoadedId = this._userManager.connect('notify::is-loaded',
13bb5b
                                                                   Lang.bind(this, function() {
13bb5b
                                                                       if (this._userManager.is_loaded) {
13bb5b
                                                                           this._loadUserList();
13bb5b
                                                                           this._userManager.disconnect(this._userManagerLoadedId);
13bb5b
                                                                           this._userManagerLoadedId = 0;
13bb5b
                                                                       }
13bb5b
                                                                   }));
13bb5b
         else
13bb5b
             this._loadUserList();
13bb5b
 
13bb5b
         this._userList.connect('activate',
13bb5b
                                Lang.bind(this, function(userList, item) {
13bb5b
                                    this._onUserListActivated(item);
13bb5b
                                }));
13bb5b
 
13bb5b
 
13bb5b
         this._sessionMenuButton = new SessionMenuButton();
13bb5b
         this._sessionMenuButton.connect('session-activated',
13bb5b
                                   Lang.bind(this, function(list, sessionId) {
13bb5b
                                                 this._greeter.call_select_session_sync (sessionId, null);
13bb5b
                                             }));
13bb5b
         this._sessionMenuButton.actor.opacity = 0;
13bb5b
         this._sessionMenuButton.actor.show();
13bb5b
         this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton.actor);
13bb5b
 
13bb5b
         this._disableUserList = undefined;
13bb5b
         this._userListLoaded = false;
13bb5b
 
13bb5b
         // If the user list is enabled, it should take key focus; make sure the
13bb5b
         // screen shield is initialized first to prevent it from stealing the
13bb5b
         // focus later
13bb5b
         Main.layoutManager.connect('startup-complete',
13bb5b
                                    Lang.bind(this, this._updateDisableUserList));
13bb5b
     },
13bb5b
 
13bb5b
+    _getLogoBinAllocation: function (dialogBox) {
13bb5b
+        let actorBox = new Clutter.ActorBox();
13bb5b
+
13bb5b
+        let [minWidth, minHeight, natWidth, natHeight] = this._logoBin.get_preferred_size();
13bb5b
+        let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
13bb5b
+
13bb5b
+        actorBox.x1 = centerX - natWidth / 2;
13bb5b
+        actorBox.y1 = dialogBox.y2 - natHeight;
13bb5b
+        actorBox.x2 = actorBox.x1 + natWidth;
13bb5b
+        actorBox.y2 = actorBox.y1 + natHeight;
13bb5b
+
13bb5b
+        return actorBox;
13bb5b
+    },
13bb5b
+
13bb5b
+    _getCenterActorAllocation: function (dialogBox, actor) {
13bb5b
+        let actorBox = new Clutter.ActorBox();
13bb5b
+
13bb5b
+        let [minWidth, minHeight, natWidth, natHeight] = actor.get_preferred_size();
13bb5b
+        let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
13bb5b
+        let centerY = dialogBox.y1 + (dialogBox.y2 - dialogBox.y1) / 2;
13bb5b
+
13bb5b
+        actorBox.x1 = centerX - natWidth / 2;
13bb5b
+        actorBox.y1 = centerY - natHeight / 2;
13bb5b
+        actorBox.x2 = actorBox.x1 + natWidth;
13bb5b
+        actorBox.y2 = actorBox.y1 + natHeight;
13bb5b
+
13bb5b
+        return actorBox;
13bb5b
+    },
13bb5b
+
13bb5b
+    _onAllocate: function (actor, dialogBox, flags) {
13bb5b
+        let dialogHeight = dialogBox.y2 - dialogBox.y1;
13bb5b
+
13bb5b
+        // First find out what space the children require
13bb5b
+        let authPromptAllocation = null;
13bb5b
+        if (this._authPrompt.actor.visible)
13bb5b
+            authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt.actor);
13bb5b
+
13bb5b
+        let userSelectionAllocation = null;
13bb5b
+        let userSelectionHeight = 0;
13bb5b
+        if (this._userSelectionBox.visible) {
13bb5b
+            userSelectionAllocation = this._getCenterActorAllocation(dialogBox, this._userSelectionBox);
13bb5b
+            userSelectionHeight = userSelectionAllocation.y2 - userSelectionAllocation.y1;
13bb5b
+        }
13bb5b
+
13bb5b
+        let logoAllocation = null;
13bb5b
+        let logoHeight = 0;
13bb5b
+        if (this._logoBin.visible) {
13bb5b
+            logoAllocation = this._getLogoBinAllocation(dialogBox);
13bb5b
+            logoHeight = logoAllocation.y2 - logoAllocation.y1;
13bb5b
+        }
13bb5b
+
13bb5b
+        // Then figure out what extra space we can hand out
13bb5b
+        let leftOverYSpace = dialogHeight - userSelectionHeight - logoHeight;
13bb5b
+        if (leftOverYSpace > 0) {
13bb5b
+            if (userSelectionAllocation) {
13bb5b
+                let topExpansion = leftOverYSpace / 2;
13bb5b
+
13bb5b
+                // Don't ever expand more than we have space for
13bb5b
+                if (userSelectionAllocation.y1 - topExpansion < 0)
13bb5b
+                    topExpansion = userSelectionAllocation.y1;
13bb5b
+
13bb5b
+                // Always expand the bottom the same as the top since it's centered
13bb5b
+                let bottomExpansion = topExpansion;
13bb5b
+
13bb5b
+                userSelectionAllocation.y1 -= topExpansion;
13bb5b
+                userSelectionAllocation.y2 += bottomExpansion;
13bb5b
+            }
13bb5b
+        }
13bb5b
+
13bb5b
+        // Finally hand out the allocations
13bb5b
+        if (authPromptAllocation)
13bb5b
+            this._authPrompt.actor.allocate(authPromptAllocation, flags);
13bb5b
+
13bb5b
+        if (userSelectionAllocation)
13bb5b
+            this._userSelectionBox.allocate(userSelectionAllocation, flags);
13bb5b
+
13bb5b
+        if (logoAllocation)
13bb5b
+            this._logoBin.allocate(logoAllocation, flags);
13bb5b
+    },
13bb5b
+
13bb5b
     _ensureUserListLoaded: function() {
13bb5b
         if (!this._userManager.is_loaded)
13bb5b
             this._userManagerLoadedId = this._userManager.connect('notify::is-loaded',
13bb5b
                                                                   Lang.bind(this, function() {
13bb5b
                                                                       if (this._userManager.is_loaded) {
13bb5b
                                                                           this._loadUserList();
13bb5b
                                                                           this._userManager.disconnect(this._userManagerLoadedId);
13bb5b
                                                                           this._userManagerLoadedId = 0;
13bb5b
                                                                       }
13bb5b
                                                                   }));
13bb5b
         else
13bb5b
             GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, this._loadUserList));
13bb5b
     },
13bb5b
 
13bb5b
     _updateDisableUserList: function() {
13bb5b
         let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY);
13bb5b
 
13bb5b
         if (disableUserList != this._disableUserList) {
13bb5b
             this._disableUserList = disableUserList;
13bb5b
 
13bb5b
             if (this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
13bb5b
                 this._authPrompt.reset();
13bb5b
         }
13bb5b
     },
13bb5b
 
13bb5b
     _updateCancelButton: function() {
13bb5b
         let cancelVisible;
13bb5b
 
13bb5b
         // Hide the cancel button if the user list is disabled and we're asking for
13bb5b
         // a username
13bb5b
-- 
13bb5b
2.1.0
13bb5b
13bb5b
13bb5b
From f3b8445905e1b34140b5e903a81a27650d68230b Mon Sep 17 00:00:00 2001
13bb5b
From: Ray Strode <rstrode@redhat.com>
13bb5b
Date: Tue, 11 Nov 2014 09:11:01 -0500
13bb5b
Subject: [PATCH 4/5] loginDialog: display banner message when
13bb5b
 disable-user-list=true
13bb5b
13bb5b
The login screen supports showing a banner message which admins
13bb5b
can use to mention login rules or disclaimers.
13bb5b
13bb5b
This message only shows up currently if the user list is enabled.
13bb5b
Most people who want to show a banner message also want to disable
13bb5b
the user list.
13bb5b
13bb5b
This commit moves the banner message to display when the user is
13bb5b
prompted for login credentials instead of when showing the user
13bb5b
list. It also adds a scrollbar if the message is too long.
13bb5b
---
13bb5b
 data/theme/gnome-shell.css |   8 ++--
13bb5b
 js/gdm/loginDialog.js      | 105 +++++++++++++++++++++++++++++++++++++++------
13bb5b
 2 files changed, 95 insertions(+), 18 deletions(-)
13bb5b
13bb5b
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
13bb5b
index aa82632..90eb64f 100644
13bb5b
--- a/data/theme/gnome-shell.css
13bb5b
+++ b/data/theme/gnome-shell.css
13bb5b
@@ -2187,67 +2187,67 @@ StScrollBar StButton#vhandle:active {
13bb5b
 .candidate-box:hover {
13bb5b
     border-radius: 4px;
13bb5b
     background-color: rgba(255,255,255,0.1);
13bb5b
 }
13bb5b
 .candidate-page-button-box {
13bb5b
     height: 2em;
13bb5b
     width: 80px;
13bb5b
 }
13bb5b
 
13bb5b
 .vertical .candidate-page-button-box {
13bb5b
     padding-top: 0.5em;
13bb5b
 }
13bb5b
 
13bb5b
 .horizontal .candidate-page-button-box {
13bb5b
     padding-left: 0.5em;
13bb5b
 }
13bb5b
 
13bb5b
 .candidate-page-button-previous {
13bb5b
     border-radius: 4px 0px 0px 4px;
13bb5b
 }
13bb5b
 
13bb5b
 .candidate-page-button-next {
13bb5b
     border-radius: 0px 4px 4px 0px;
13bb5b
 }
13bb5b
 
13bb5b
 .candidate-page-button-icon {
13bb5b
     icon-size: 1em;
13bb5b
 }
13bb5b
 
13bb5b
 /* Login Dialog */
13bb5b
+.login-dialog-banner-view {
13bb5b
+    padding-top: 24px;
13bb5b
+    max-width: 23em;
13bb5b
+}
13bb5b
 
13bb5b
 .login-dialog-banner {
13bb5b
-    font-size: 10pt;
13bb5b
-    font-weight: bold;
13bb5b
-    text-align: center;
13bb5b
     color: #666666;
13bb5b
-    padding-bottom: 1em;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog-title {
13bb5b
     font-size: 14pt;
13bb5b
     font-weight: bold;
13bb5b
     color: #666666;
13bb5b
     padding-bottom: 2em;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog {
13bb5b
     /* Reset border and background */
13bb5b
     border: none;
13bb5b
     background-color: transparent;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog-button-box {
13bb5b
     spacing: 5px;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog-user-list-view {
13bb5b
     -st-vfade-offset: 1em;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog-user-list {
13bb5b
     spacing: 12px;
13bb5b
     padding: .2em;
13bb5b
     width: 23em;
13bb5b
 }
13bb5b
 
13bb5b
 .login-dialog-user-list-item {
13bb5b
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
13bb5b
index 4835199..348798c 100644
13bb5b
--- a/js/gdm/loginDialog.js
13bb5b
+++ b/js/gdm/loginDialog.js
13bb5b
@@ -1,60 +1,61 @@
13bb5b
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
13bb5b
 /*
13bb5b
  * Copyright 2011 Red Hat, Inc
13bb5b
  *
13bb5b
  * This program is free software; you can redistribute it and/or modify
13bb5b
  * it under the terms of the GNU General Public License as published by
13bb5b
  * the Free Software Foundation; either version 2, or (at your option)
13bb5b
  * any later version.
13bb5b
  *
13bb5b
  * This program is distributed in the hope that it will be useful,
13bb5b
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13bb5b
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13bb5b
  * GNU General Public License for more details.
13bb5b
  *
13bb5b
  * You should have received a copy of the GNU General Public License
13bb5b
  * along with this program; if not, write to the Free Software
13bb5b
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
13bb5b
  * 02111-1307, USA.
13bb5b
  */
13bb5b
 
13bb5b
 const AccountsService = imports.gi.AccountsService;
13bb5b
 const Atk = imports.gi.Atk;
13bb5b
 const Clutter = imports.gi.Clutter;
13bb5b
 const Gdm = imports.gi.Gdm;
13bb5b
 const Gio = imports.gi.Gio;
13bb5b
 const GLib = imports.gi.GLib;
13bb5b
 const Gtk = imports.gi.Gtk;
13bb5b
 const Lang = imports.lang;
13bb5b
 const Mainloop = imports.mainloop;
13bb5b
 const Meta = imports.gi.Meta;
13bb5b
+const Pango = imports.gi.Pango;
13bb5b
 const Shell = imports.gi.Shell;
13bb5b
 const Signals = imports.signals;
13bb5b
 const St = imports.gi.St;
13bb5b
 
13bb5b
 const AuthPrompt = imports.gdm.authPrompt;
13bb5b
 const Batch = imports.gdm.batch;
13bb5b
 const BoxPointer = imports.ui.boxpointer;
13bb5b
 const CtrlAltTab = imports.ui.ctrlAltTab;
13bb5b
 const GdmUtil = imports.gdm.util;
13bb5b
 const Layout = imports.ui.layout;
13bb5b
 const Main = imports.ui.main;
13bb5b
 const PopupMenu = imports.ui.popupMenu;
13bb5b
 const Realmd = imports.gdm.realmd;
13bb5b
 const Tweener = imports.ui.tweener;
13bb5b
 const UserMenu = imports.ui.userMenu;
13bb5b
 const UserWidget = imports.ui.userWidget;
13bb5b
 
13bb5b
 const _FADE_ANIMATION_TIME = 0.25;
13bb5b
 const _SCROLL_ANIMATION_TIME = 0.5;
13bb5b
 const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
13bb5b
 const _LOGO_ICON_HEIGHT = 48;
13bb5b
 
13bb5b
 let _loginDialog = null;
13bb5b
 
13bb5b
 const UserListItem = new Lang.Class({
13bb5b
     Name: 'UserListItem',
13bb5b
 
13bb5b
     _init: function(user) {
13bb5b
         this.user = user;
13bb5b
         this._userChangedId = this.user.connect('changed',
13bb5b
@@ -412,272 +413,346 @@ const LoginDialog = new Lang.Class({
13bb5b
                                   Lang.bind(this, this._onDefaultSessionChanged));
13bb5b
 
13bb5b
             this._greeter.connect('session-opened',
13bb5b
                                   Lang.bind(this, this._onSessionOpened));
13bb5b
             this._greeter.connect('timed-login-requested',
13bb5b
                                   Lang.bind(this, this._onTimedLoginRequested));
13bb5b
         }
13bb5b
 
13bb5b
         this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
13bb5b
 
13bb5b
         this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY,
13bb5b
                                Lang.bind(this, this._updateBanner));
13bb5b
         this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_TEXT_KEY,
13bb5b
                                Lang.bind(this, this._updateBanner));
13bb5b
         this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY,
13bb5b
                                Lang.bind(this, this._updateDisableUserList));
13bb5b
         this._settings.connect('changed::' + GdmUtil.LOGO_KEY,
13bb5b
                                Lang.bind(this, this._updateLogo));
13bb5b
 
13bb5b
         this._textureCache = St.TextureCache.get_default();
13bb5b
         this._textureCache.connect('texture-file-changed',
13bb5b
                                    Lang.bind(this, this._updateLogoTexture));
13bb5b
 
13bb5b
         this._userSelectionBox = new St.BoxLayout({ style_class: 'login-dialog-user-selection-box',
13bb5b
                                                     x_align: Clutter.ActorAlign.CENTER,
13bb5b
                                                     y_align: Clutter.ActorAlign.CENTER,
13bb5b
                                                     vertical: true,
13bb5b
                                                     visible: false });
13bb5b
         this.actor.add_child(this._userSelectionBox);
13bb5b
 
13bb5b
-        this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
13bb5b
-                                           text: '' });
13bb5b
-        this._userSelectionBox.add(this._bannerLabel);
13bb5b
-        this._updateBanner();
13bb5b
-
13bb5b
         this._userList = new UserList();
13bb5b
         this._userSelectionBox.add(this._userList.actor,
13bb5b
                                    { expand: true,
13bb5b
                                      x_fill: true,
13bb5b
                                      y_fill: true });
13bb5b
 
13bb5b
         this._authPrompt = new AuthPrompt.AuthPrompt(gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_OR_LOG_IN);
13bb5b
         this._authPrompt.connect('prompted', Lang.bind(this, this._onPrompted));
13bb5b
         this._authPrompt.connect('reset', Lang.bind(this, this._onReset));
13bb5b
         this._authPrompt.hide();
13bb5b
         this.actor.add_child(this._authPrompt.actor);
13bb5b
 
13bb5b
         // translators: this message is shown below the user list on the
13bb5b
         // login screen. It can be activated to reveal an entry for
13bb5b
         // manually entering the username.
13bb5b
         let notListedLabel = new St.Label({ text: _("Not listed?"),
13bb5b
                                             style_class: 'login-dialog-not-listed-label' });
13bb5b
         this._notListedButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
13bb5b
                                                 button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
13bb5b
                                                 can_focus: true,
13bb5b
                                                 child: notListedLabel,
13bb5b
                                                 reactive: true,
13bb5b
                                                 x_align: St.Align.START,
13bb5b
                                                 x_fill: true });
13bb5b
 
13bb5b
         this._notListedButton.connect('clicked', Lang.bind(this, this._hideUserListAskForUsernameAndBeginVerification));
13bb5b
 
13bb5b
         this._notListedButton.hide();
13bb5b
 
13bb5b
         this._userSelectionBox.add(this._notListedButton,
13bb5b
                                    { expand: false,
13bb5b
                                      x_align: St.Align.START,
13bb5b
                                      x_fill: true });
13bb5b
 
13bb5b
+        this._bannerView = new St.ScrollView({ style_class: 'login-dialog-banner-view',
13bb5b
+                                               opacity: 0,
13bb5b
+                                               vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
13bb5b
+                                               hscrollbar_policy: Gtk.PolicyType.NEVER });
13bb5b
+        this.actor.add_child(this._bannerView);
13bb5b
+
13bb5b
+        let bannerBox = new St.BoxLayout({ vertical: true });
13bb5b
+
13bb5b
+        this._bannerView.add_actor(bannerBox);
13bb5b
+        this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
13bb5b
+                                           text: '' });
13bb5b
+        this._bannerLabel.clutter_text.line_wrap = true;
13bb5b
+        this._bannerLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
13bb5b
+        bannerBox.add_child(this._bannerLabel);
13bb5b
+        this._updateBanner();
13bb5b
+
13bb5b
         this._logoBin = new St.Widget({ style_class: 'login-dialog-logo-bin',
13bb5b
                                         x_align: Clutter.ActorAlign.CENTER,
13bb5b
                                         y_align: Clutter.ActorAlign.END });
13bb5b
         this.actor.add_child(this._logoBin);
13bb5b
         this._updateLogo();
13bb5b
 
13bb5b
         if (!this._userManager.is_loaded)
13bb5b
             this._userManagerLoadedId = this._userManager.connect('notify::is-loaded',
13bb5b
                                                                   Lang.bind(this, function() {
13bb5b
                                                                       if (this._userManager.is_loaded) {
13bb5b
                                                                           this._loadUserList();
13bb5b
                                                                           this._userManager.disconnect(this._userManagerLoadedId);
13bb5b
                                                                           this._userManagerLoadedId = 0;
13bb5b
                                                                       }
13bb5b
                                                                   }));
13bb5b
         else
13bb5b
             this._loadUserList();
13bb5b
 
13bb5b
         this._userList.connect('activate',
13bb5b
                                Lang.bind(this, function(userList, item) {
13bb5b
                                    this._onUserListActivated(item);
13bb5b
                                }));
13bb5b
 
13bb5b
 
13bb5b
         this._sessionMenuButton = new SessionMenuButton();
13bb5b
         this._sessionMenuButton.connect('session-activated',
13bb5b
                                   Lang.bind(this, function(list, sessionId) {
13bb5b
                                                 this._greeter.call_select_session_sync (sessionId, null);
13bb5b
                                             }));
13bb5b
         this._sessionMenuButton.actor.opacity = 0;
13bb5b
         this._sessionMenuButton.actor.show();
13bb5b
         this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton.actor);
13bb5b
 
13bb5b
         this._disableUserList = undefined;
13bb5b
         this._userListLoaded = false;
13bb5b
 
13bb5b
         // If the user list is enabled, it should take key focus; make sure the
13bb5b
         // screen shield is initialized first to prevent it from stealing the
13bb5b
         // focus later
13bb5b
         Main.layoutManager.connect('startup-complete',
13bb5b
                                    Lang.bind(this, this._updateDisableUserList));
13bb5b
     },
13bb5b
 
13bb5b
+    _getBannerAllocation: function (dialogBox) {
13bb5b
+        let actorBox = new Clutter.ActorBox();
13bb5b
+
13bb5b
+        let [minWidth, minHeight, natWidth, natHeight] = this._bannerView.get_preferred_size();
13bb5b
+        let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
13bb5b
+
13bb5b
+        actorBox.x1 = centerX - natWidth / 2;
13bb5b
+        actorBox.y1 = dialogBox.y1 + Main.layoutManager.panelBox.height;
13bb5b
+        actorBox.x2 = actorBox.x1 + natWidth;
13bb5b
+        actorBox.y2 = actorBox.y1 + natHeight;
13bb5b
+
13bb5b
+        return actorBox;
13bb5b
+    },
13bb5b
+
13bb5b
     _getLogoBinAllocation: function (dialogBox) {
13bb5b
         let actorBox = new Clutter.ActorBox();
13bb5b
 
13bb5b
         let [minWidth, minHeight, natWidth, natHeight] = this._logoBin.get_preferred_size();
13bb5b
         let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
13bb5b
 
13bb5b
         actorBox.x1 = centerX - natWidth / 2;
13bb5b
         actorBox.y1 = dialogBox.y2 - natHeight;
13bb5b
         actorBox.x2 = actorBox.x1 + natWidth;
13bb5b
         actorBox.y2 = actorBox.y1 + natHeight;
13bb5b
 
13bb5b
         return actorBox;
13bb5b
     },
13bb5b
 
13bb5b
     _getCenterActorAllocation: function (dialogBox, actor) {
13bb5b
         let actorBox = new Clutter.ActorBox();
13bb5b
 
13bb5b
         let [minWidth, minHeight, natWidth, natHeight] = actor.get_preferred_size();
13bb5b
         let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
13bb5b
         let centerY = dialogBox.y1 + (dialogBox.y2 - dialogBox.y1) / 2;
13bb5b
 
13bb5b
         actorBox.x1 = centerX - natWidth / 2;
13bb5b
         actorBox.y1 = centerY - natHeight / 2;
13bb5b
         actorBox.x2 = actorBox.x1 + natWidth;
13bb5b
         actorBox.y2 = actorBox.y1 + natHeight;
13bb5b
 
13bb5b
         return actorBox;
13bb5b
     },
13bb5b
 
13bb5b
     _onAllocate: function (actor, dialogBox, flags) {
13bb5b
         let dialogHeight = dialogBox.y2 - dialogBox.y1;
13bb5b
 
13bb5b
         // First find out what space the children require
13bb5b
+        let bannerAllocation = null;
13bb5b
+        let bannerHeight = 0;
13bb5b
+        let bannerWidth = 0;
13bb5b
+        if (this._bannerView.visible) {
13bb5b
+            bannerAllocation = this._getBannerAllocation(dialogBox, this._bannerView);
13bb5b
+            bannerHeight = bannerAllocation.y2 - bannerAllocation.y1;
13bb5b
+            bannerWidth = bannerAllocation.x2 - bannerAllocation.x1;
13bb5b
+        }
13bb5b
+
13bb5b
         let authPromptAllocation = null;
13bb5b
-        if (this._authPrompt.actor.visible)
13bb5b
+        let authPromptHeight = 0;
13bb5b
+        if (this._authPrompt.actor.visible) {
13bb5b
             authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt.actor);
13bb5b
+            authPromptHeight = authPromptAllocation.y2 - authPromptAllocation.y1;
13bb5b
+        }
13bb5b
 
13bb5b
         let userSelectionAllocation = null;
13bb5b
         let userSelectionHeight = 0;
13bb5b
         if (this._userSelectionBox.visible) {
13bb5b
             userSelectionAllocation = this._getCenterActorAllocation(dialogBox, this._userSelectionBox);
13bb5b
             userSelectionHeight = userSelectionAllocation.y2 - userSelectionAllocation.y1;
13bb5b
         }
13bb5b
 
13bb5b
         let logoAllocation = null;
13bb5b
         let logoHeight = 0;
13bb5b
         if (this._logoBin.visible) {
13bb5b
             logoAllocation = this._getLogoBinAllocation(dialogBox);
13bb5b
             logoHeight = logoAllocation.y2 - logoAllocation.y1;
13bb5b
         }
13bb5b
 
13bb5b
         // Then figure out what extra space we can hand out
13bb5b
-        let leftOverYSpace = dialogHeight - userSelectionHeight - logoHeight;
13bb5b
-        if (leftOverYSpace > 0) {
13bb5b
-            if (userSelectionAllocation) {
13bb5b
-                let topExpansion = leftOverYSpace / 2;
13bb5b
+        if (bannerAllocation) {
13bb5b
+            let leftOverYSpace = dialogHeight - bannerHeight - authPromptHeight - logoHeight;
13bb5b
+
13bb5b
+            if (leftOverYSpace > 0) {
13bb5b
+                 // First figure out how much left over space is up top
13bb5b
+                 let leftOverTopSpace = leftOverYSpace / 2;
13bb5b
 
13bb5b
-                // Don't ever expand more than we have space for
13bb5b
-                if (userSelectionAllocation.y1 - topExpansion < 0)
13bb5b
-                    topExpansion = userSelectionAllocation.y1;
13bb5b
+                 // Then, shift the banner into the middle of that extra space
13bb5b
+                 let yShift = leftOverTopSpace / 2;
13bb5b
+
13bb5b
+                 bannerAllocation.y1 += yShift;
13bb5b
+                 bannerAllocation.y2 += yShift;
13bb5b
+            } else {
13bb5b
+                 // recompute banner height to be constrained if there's no room for its
13bb5b
+                 // requested height
13bb5b
+
13bb5b
+                 // First figure out how much space there is without the banner
13bb5b
+                 leftOverYSpace += bannerHeight;
13bb5b
+
13bb5b
+                 // Then figure out how much of that space is up top
13bb5b
+                 let availableTopSpace = leftOverYSpace / 2;
13bb5b
+
13bb5b
+                 // Then give all of that space to the banner
13bb5b
+                 bannerAllocation.y2 = bannerAllocation.y1 + availableTopSpace;
13bb5b
+            }
13bb5b
+        } else if (userSelectionAllocation) {
13bb5b
+            // Grow the user list to fill the space
13bb5b
+            let leftOverYSpace = dialogHeight - userSelectionHeight - logoHeight;
13bb5b
 
13bb5b
-                // Always expand the bottom the same as the top since it's centered
13bb5b
+            if (leftOverYSpace > 0) {
13bb5b
+                let topExpansion = leftOverYSpace / 2;
13bb5b
                 let bottomExpansion = topExpansion;
13bb5b
 
13bb5b
                 userSelectionAllocation.y1 -= topExpansion;
13bb5b
                 userSelectionAllocation.y2 += bottomExpansion;
13bb5b
             }
13bb5b
         }
13bb5b
 
13bb5b
         // Finally hand out the allocations
13bb5b
+        if (bannerAllocation) {
13bb5b
+            this._bannerView.allocate(bannerAllocation, flags);
13bb5b
+        }
13bb5b
+
13bb5b
         if (authPromptAllocation)
13bb5b
             this._authPrompt.actor.allocate(authPromptAllocation, flags);
13bb5b
 
13bb5b
         if (userSelectionAllocation)
13bb5b
             this._userSelectionBox.allocate(userSelectionAllocation, flags);
13bb5b
 
13bb5b
         if (logoAllocation)
13bb5b
             this._logoBin.allocate(logoAllocation, flags);
13bb5b
     },
13bb5b
 
13bb5b
     _ensureUserListLoaded: function() {
13bb5b
         if (!this._userManager.is_loaded)
13bb5b
             this._userManagerLoadedId = this._userManager.connect('notify::is-loaded',
13bb5b
                                                                   Lang.bind(this, function() {
13bb5b
                                                                       if (this._userManager.is_loaded) {
13bb5b
                                                                           this._loadUserList();
13bb5b
                                                                           this._userManager.disconnect(this._userManagerLoadedId);
13bb5b
                                                                           this._userManagerLoadedId = 0;
13bb5b
                                                                       }
13bb5b
                                                                   }));
13bb5b
         else
13bb5b
             GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, this._loadUserList));
13bb5b
     },
13bb5b
 
13bb5b
     _updateDisableUserList: function() {
13bb5b
         let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY);
13bb5b
 
13bb5b
         if (disableUserList != this._disableUserList) {
13bb5b
             this._disableUserList = disableUserList;
13bb5b
 
13bb5b
             if (this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
13bb5b
                 this._authPrompt.reset();
13bb5b
         }
13bb5b
     },
13bb5b
 
13bb5b
     _updateCancelButton: function() {
13bb5b
         let cancelVisible;
13bb5b
 
13bb5b
         // Hide the cancel button if the user list is disabled and we're asking for
13bb5b
         // a username
13bb5b
         if (this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING && this._disableUserList)
13bb5b
             cancelVisible = false;
13bb5b
         else
13bb5b
             cancelVisible = true;
13bb5b
 
13bb5b
         this._authPrompt.cancelButton.visible = cancelVisible;
13bb5b
     },
13bb5b
 
13bb5b
     _updateBanner: function() {
13bb5b
         let enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY);
13bb5b
         let text = this._settings.get_string(GdmUtil.BANNER_MESSAGE_TEXT_KEY);
13bb5b
 
13bb5b
         if (enabled && text) {
13bb5b
             this._bannerLabel.set_text(text);
13bb5b
             this._bannerLabel.show();
13bb5b
         } else {
13bb5b
             this._bannerLabel.hide();
13bb5b
         }
13bb5b
     },
13bb5b
 
13bb5b
+    _fadeInBannerView: function() {
13bb5b
+        Tweener.addTween(this._bannerView,
13bb5b
+                         { opacity: 255,
13bb5b
+                           time: _FADE_ANIMATION_TIME,
13bb5b
+                           transition: 'easeOutQuad' });
13bb5b
+    },
13bb5b
+
13bb5b
+    _hideBannerView: function() {
13bb5b
+        Tweener.removeTweens(this._bannerView);
13bb5b
+        this._bannerView.opacity = 0;
13bb5b
+    },
13bb5b
+
13bb5b
     _updateLogoTexture: function(cache, uri) {
13bb5b
         if (this._logoFileUri != uri)
13bb5b
             return;
13bb5b
 
13bb5b
         this._logoBin.destroy_all_children();
13bb5b
         if (this._logoFileUri)
13bb5b
             this._logoBin.add_child(this._textureCache.load_uri_async(this._logoFileUri,
13bb5b
                                                                       -1, _LOGO_ICON_HEIGHT));
13bb5b
     },
13bb5b
 
13bb5b
     _updateLogo: function() {
13bb5b
         let path = this._settings.get_string(GdmUtil.LOGO_KEY);
13bb5b
 
13bb5b
         this._logoFileUri = path ? Gio.file_new_for_path(path).get_uri() : null;
13bb5b
         this._updateLogoTexture(this._textureCache, this._logoFileUri);
13bb5b
     },
13bb5b
 
13bb5b
     _onPrompted: function() {
13bb5b
         this._sessionMenuButton.updateSensitivity(true);
13bb5b
 
13bb5b
         if (this._shouldShowSessionMenuButton())
13bb5b
             this._authPrompt.setActorInDefaultButtonWell(this._sessionMenuButton.actor);
13bb5b
         this._showPrompt();
13bb5b
     },
13bb5b
 
13bb5b
     _onReset: function(authPrompt, beginRequest) {
13bb5b
         this._sessionMenuButton.updateSensitivity(true);
13bb5b
 
13bb5b
         this._user = null;
13bb5b
 
13bb5b
@@ -688,60 +763,61 @@ const LoginDialog = new Lang.Class({
13bb5b
                 this._hideUserListAskForUsernameAndBeginVerification();
13bb5b
         } else {
13bb5b
             this._hideUserListAndBeginVerification();
13bb5b
         }
13bb5b
     },
13bb5b
 
13bb5b
     _onDefaultSessionChanged: function(client, sessionId) {
13bb5b
         this._sessionMenuButton.setActiveSession(sessionId);
13bb5b
     },
13bb5b
 
13bb5b
     _shouldShowSessionMenuButton: function() {
13bb5b
         if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFYING &&
13bb5b
             this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFICATION_FAILED)
13bb5b
           return false;
13bb5b
 
13bb5b
         if (this._user && this._user.is_loaded && this._user.is_logged_in())
13bb5b
           return false;
13bb5b
 
13bb5b
         return true;
13bb5b
     },
13bb5b
 
13bb5b
     _showPrompt: function() {
13bb5b
         if (this._authPrompt.actor.visible)
13bb5b
             return;
13bb5b
         this._authPrompt.actor.opacity = 0;
13bb5b
         this._authPrompt.actor.show();
13bb5b
         Tweener.addTween(this._authPrompt.actor,
13bb5b
                          { opacity: 255,
13bb5b
                            time: _FADE_ANIMATION_TIME,
13bb5b
                            transition: 'easeOutQuad' });
13bb5b
+        this._fadeInBannerView();
13bb5b
     },
13bb5b
 
13bb5b
     _showRealmLoginHint: function(realmManager, hint) {
13bb5b
         if (!hint)
13bb5b
             return;
13bb5b
 
13bb5b
         hint = hint.replace(/%U/g, 'user');
13bb5b
         hint = hint.replace(/%D/g, 'DOMAIN');
13bb5b
         hint = hint.replace(/%[^UD]/g, '');
13bb5b
 
13bb5b
         // Translators: this message is shown below the username entry field
13bb5b
         // to clue the user in on how to login to the local network realm
13bb5b
         this._authPrompt.setMessage(_("(e.g., user or %s)").format(hint), GdmUtil.MessageType.HINT);
13bb5b
     },
13bb5b
 
13bb5b
     _askForUsernameAndBeginVerification: function() {
13bb5b
         this._authPrompt.setPasswordChar('');
13bb5b
         this._authPrompt.setQuestion(_("Username: "));
13bb5b
 
13bb5b
         let realmManager = new Realmd.Manager();
13bb5b
         let realmSignalId = realmManager.connect('login-format-changed',
13bb5b
                                                  Lang.bind(this, this._showRealmLoginHint));
13bb5b
         this._showRealmLoginHint(realmManager.loginFormat);
13bb5b
 
13bb5b
         let nextSignalId = this._authPrompt.connect('next',
13bb5b
                                                     Lang.bind(this, function() {
13bb5b
                                                         this._authPrompt.disconnect(nextSignalId);
13bb5b
                                                         this._authPrompt.updateSensitivity(false);
13bb5b
                                                         let answer = this._authPrompt.getAnswer();
13bb5b
                                                         this._user = this._userManager.get_user(answer);
13bb5b
@@ -909,60 +985,61 @@ const LoginDialog = new Lang.Class({
13bb5b
                                 }
13bb5b
 
13bb5b
                                 return false;
13bb5b
                              }));
13bb5b
     },
13bb5b
 
13bb5b
     _setUserListExpanded: function(expanded) {
13bb5b
         this._userList.updateStyle(expanded);
13bb5b
         this._userSelectionBox.visible = expanded;
13bb5b
     },
13bb5b
 
13bb5b
     _hideUserList: function() {
13bb5b
         this._setUserListExpanded(false);
13bb5b
         if (this._userSelectionBox.visible)
13bb5b
             GdmUtil.cloneAndFadeOutActor(this._userSelectionBox);
13bb5b
     },
13bb5b
 
13bb5b
     _hideUserListAskForUsernameAndBeginVerification: function() {
13bb5b
         this._hideUserList();
13bb5b
         this._askForUsernameAndBeginVerification();
13bb5b
     },
13bb5b
 
13bb5b
     _hideUserListAndBeginVerification: function() {
13bb5b
         this._hideUserList();
13bb5b
         this._authPrompt.begin();
13bb5b
     },
13bb5b
 
13bb5b
     _showUserList: function() {
13bb5b
         this._ensureUserListLoaded();
13bb5b
         this._authPrompt.hide();
13bb5b
+        this._hideBannerView();
13bb5b
         this._sessionMenuButton.close();
13bb5b
         this._setUserListExpanded(true);
13bb5b
         this._notListedButton.show();
13bb5b
         this._userList.actor.grab_key_focus();
13bb5b
     },
13bb5b
 
13bb5b
     _beginVerificationForItem: function(item) {
13bb5b
         this._authPrompt.setUser(item.user);
13bb5b
 
13bb5b
         let userName = item.user.get_user_name();
13bb5b
         let hold = new Batch.Hold();
13bb5b
 
13bb5b
         this._authPrompt.begin({ userName: userName,
13bb5b
                                  hold: hold });
13bb5b
         return hold;
13bb5b
     },
13bb5b
 
13bb5b
     _onUserListActivated: function(activatedItem) {
13bb5b
         let tasks = [function() {
13bb5b
                          return GdmUtil.cloneAndFadeOutActor(this._userSelectionBox);
13bb5b
                      },
13bb5b
                      function() {
13bb5b
                          this._setUserListExpanded(false);
13bb5b
                      }];
13bb5b
 
13bb5b
         this._user = activatedItem.user;
13bb5b
 
13bb5b
         this._updateCancelButton();
13bb5b
 
13bb5b
         let batch = new Batch.ConcurrentBatch(this, [new Batch.ConsecutiveBatch(this, tasks),
13bb5b
-- 
13bb5b
2.1.0
13bb5b
13bb5b
13bb5b
From 9bdce53329817e3453baa85cbc4d899511630154 Mon Sep 17 00:00:00 2001
13bb5b
From: Ray Strode <rstrode@redhat.com>
13bb5b
Date: Tue, 11 Nov 2014 09:11:01 -0500
13bb5b
Subject: [PATCH 5/5] loginDialog: use two column view if banner message long
13bb5b
13bb5b
Frequently banner messages are longer than can reasonable
13bb5b
fit in a one column view, which leads to a smooshed layout.
13bb5b
13bb5b
This commit changes the layout to a two column view, with the
13bb5b
banner on the left and the prompt on the right, if the banner
13bb5b
message is long enough that it can't fit well above the prompt.
13bb5b
If there isn't enough space for two columns then we keep the
13bb5b
one column layout but add scrollbars.
13bb5b
---
13bb5b
 js/gdm/loginDialog.js | 67 ++++++++++++++++++++++++++++++++++++++++++---------
13bb5b
 1 file changed, 55 insertions(+), 12 deletions(-)
13bb5b
13bb5b
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
13bb5b
index 348798c..9ee259f 100644
13bb5b
--- a/js/gdm/loginDialog.js
13bb5b
+++ b/js/gdm/loginDialog.js
13bb5b
@@ -550,118 +550,161 @@ const LoginDialog = new Lang.Class({
13bb5b
     _getLogoBinAllocation: function (dialogBox) {
13bb5b
         let actorBox = new Clutter.ActorBox();
13bb5b
 
13bb5b
         let [minWidth, minHeight, natWidth, natHeight] = this._logoBin.get_preferred_size();
13bb5b
         let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
13bb5b
 
13bb5b
         actorBox.x1 = centerX - natWidth / 2;
13bb5b
         actorBox.y1 = dialogBox.y2 - natHeight;
13bb5b
         actorBox.x2 = actorBox.x1 + natWidth;
13bb5b
         actorBox.y2 = actorBox.y1 + natHeight;
13bb5b
 
13bb5b
         return actorBox;
13bb5b
     },
13bb5b
 
13bb5b
     _getCenterActorAllocation: function (dialogBox, actor) {
13bb5b
         let actorBox = new Clutter.ActorBox();
13bb5b
 
13bb5b
         let [minWidth, minHeight, natWidth, natHeight] = actor.get_preferred_size();
13bb5b
         let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
13bb5b
         let centerY = dialogBox.y1 + (dialogBox.y2 - dialogBox.y1) / 2;
13bb5b
 
13bb5b
         actorBox.x1 = centerX - natWidth / 2;
13bb5b
         actorBox.y1 = centerY - natHeight / 2;
13bb5b
         actorBox.x2 = actorBox.x1 + natWidth;
13bb5b
         actorBox.y2 = actorBox.y1 + natHeight;
13bb5b
 
13bb5b
         return actorBox;
13bb5b
     },
13bb5b
 
13bb5b
     _onAllocate: function (actor, dialogBox, flags) {
13bb5b
+        let dialogWidth = dialogBox.x2 - dialogBox.x1;
13bb5b
         let dialogHeight = dialogBox.y2 - dialogBox.y1;
13bb5b
 
13bb5b
         // First find out what space the children require
13bb5b
         let bannerAllocation = null;
13bb5b
         let bannerHeight = 0;
13bb5b
         let bannerWidth = 0;
13bb5b
         if (this._bannerView.visible) {
13bb5b
             bannerAllocation = this._getBannerAllocation(dialogBox, this._bannerView);
13bb5b
             bannerHeight = bannerAllocation.y2 - bannerAllocation.y1;
13bb5b
             bannerWidth = bannerAllocation.x2 - bannerAllocation.x1;
13bb5b
         }
13bb5b
 
13bb5b
         let authPromptAllocation = null;
13bb5b
         let authPromptHeight = 0;
13bb5b
+        let authPromptWidth = 0;
13bb5b
         if (this._authPrompt.actor.visible) {
13bb5b
             authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt.actor);
13bb5b
             authPromptHeight = authPromptAllocation.y2 - authPromptAllocation.y1;
13bb5b
+            authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1;
13bb5b
         }
13bb5b
 
13bb5b
         let userSelectionAllocation = null;
13bb5b
         let userSelectionHeight = 0;
13bb5b
         if (this._userSelectionBox.visible) {
13bb5b
             userSelectionAllocation = this._getCenterActorAllocation(dialogBox, this._userSelectionBox);
13bb5b
             userSelectionHeight = userSelectionAllocation.y2 - userSelectionAllocation.y1;
13bb5b
         }
13bb5b
 
13bb5b
         let logoAllocation = null;
13bb5b
         let logoHeight = 0;
13bb5b
         if (this._logoBin.visible) {
13bb5b
             logoAllocation = this._getLogoBinAllocation(dialogBox);
13bb5b
             logoHeight = logoAllocation.y2 - logoAllocation.y1;
13bb5b
         }
13bb5b
 
13bb5b
-        // Then figure out what extra space we can hand out
13bb5b
+        // Then figure out if we're overly constrained and need to
13bb5b
+        // try a different layout, or if we have what extra space we
13bb5b
+        // can hand out
13bb5b
         if (bannerAllocation) {
13bb5b
             let leftOverYSpace = dialogHeight - bannerHeight - authPromptHeight - logoHeight;
13bb5b
 
13bb5b
             if (leftOverYSpace > 0) {
13bb5b
                  // First figure out how much left over space is up top
13bb5b
                  let leftOverTopSpace = leftOverYSpace / 2;
13bb5b
 
13bb5b
                  // Then, shift the banner into the middle of that extra space
13bb5b
                  let yShift = leftOverTopSpace / 2;
13bb5b
 
13bb5b
                  bannerAllocation.y1 += yShift;
13bb5b
                  bannerAllocation.y2 += yShift;
13bb5b
             } else {
13bb5b
-                 // recompute banner height to be constrained if there's no room for its
13bb5b
-                 // requested height
13bb5b
-
13bb5b
-                 // First figure out how much space there is without the banner
13bb5b
-                 leftOverYSpace += bannerHeight;
13bb5b
-
13bb5b
-                 // Then figure out how much of that space is up top
13bb5b
-                 let availableTopSpace = leftOverYSpace / 2;
13bb5b
-
13bb5b
-                 // Then give all of that space to the banner
13bb5b
-                 bannerAllocation.y2 = bannerAllocation.y1 + availableTopSpace;
13bb5b
+                 // Then figure out how much space there would be if we switched to a
13bb5b
+                 // wide layout with banner on one side and authprompt on the other.
13bb5b
+                 let leftOverXSpace = dialogWidth - authPromptWidth;
13bb5b
+
13bb5b
+                 // In a wide view, half of the available space goes to the banner,
13bb5b
+                 // and the other half goes to the margins.
13bb5b
+                 let wideBannerWidth = leftOverXSpace / 2;
13bb5b
+                 let wideSpacing  = leftOverXSpace - wideBannerWidth;
13bb5b
+
13bb5b
+                 // If we do go with a wide layout, we need there to be at least enough
13bb5b
+                 // space for the banner and the auth prompt to be the same width,
13bb5b
+                 // so it doesn't look unbalanced.
13bb5b
+                 if (authPromptWidth > 0 && wideBannerWidth > authPromptWidth) {
13bb5b
+                     let centerX = dialogBox.x1 + dialogWidth / 2;
13bb5b
+                     let centerY = dialogBox.y1 + dialogHeight / 2;
13bb5b
+
13bb5b
+                     // A small portion of the spacing goes down the center of the
13bb5b
+                     // screen to help delimit the two columns of the wide view
13bb5b
+                     let centerGap = wideSpacing / 8;
13bb5b
+
13bb5b
+                     // place the banner along the left edge of the center margin
13bb5b
+                     bannerAllocation.x2 = centerX - centerGap / 2;
13bb5b
+                     bannerAllocation.x1 = bannerAllocation.x2 - wideBannerWidth;
13bb5b
+
13bb5b
+                     // figure out how tall it would like to be and try to accomodate
13bb5b
+                     // but don't let it get too close to the logo
13bb5b
+                     let [wideMinHeight, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth);
13bb5b
+
13bb5b
+                     let maxWideHeight = dialogHeight - 3 * logoHeight;
13bb5b
+                     wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight);
13bb5b
+                     bannerAllocation.y1 = centerY - wideBannerHeight / 2;
13bb5b
+                     bannerAllocation.y2 = bannerAllocation.y1 + wideBannerHeight;
13bb5b
+
13bb5b
+                     // place the auth prompt along the right edge of the center margin
13bb5b
+                     authPromptAllocation.x1 = centerX + centerGap / 2;
13bb5b
+                     authPromptAllocation.x2 = authPromptAllocation.x1 + authPromptWidth;
13bb5b
+                 } else {
13bb5b
+                     // If we aren't going to do a wide view, then we need to limit
13bb5b
+                     // the height of the banner so it will present scrollbars
13bb5b
+
13bb5b
+                     // First figure out how much space there is without the banner
13bb5b
+                     leftOverYSpace += bannerHeight;
13bb5b
+
13bb5b
+                     // Then figure out how much of that space is up top
13bb5b
+                     let availableTopSpace = leftOverYSpace / 2;
13bb5b
+
13bb5b
+                     // Then give all of that space to the banner
13bb5b
+                     bannerAllocation.y2 = bannerAllocation.y1 + availableTopSpace;
13bb5b
+                 }
13bb5b
             }
13bb5b
         } else if (userSelectionAllocation) {
13bb5b
             // Grow the user list to fill the space
13bb5b
             let leftOverYSpace = dialogHeight - userSelectionHeight - logoHeight;
13bb5b
 
13bb5b
             if (leftOverYSpace > 0) {
13bb5b
                 let topExpansion = leftOverYSpace / 2;
13bb5b
                 let bottomExpansion = topExpansion;
13bb5b
 
13bb5b
                 userSelectionAllocation.y1 -= topExpansion;
13bb5b
                 userSelectionAllocation.y2 += bottomExpansion;
13bb5b
             }
13bb5b
         }
13bb5b
 
13bb5b
         // Finally hand out the allocations
13bb5b
         if (bannerAllocation) {
13bb5b
             this._bannerView.allocate(bannerAllocation, flags);
13bb5b
         }
13bb5b
 
13bb5b
         if (authPromptAllocation)
13bb5b
             this._authPrompt.actor.allocate(authPromptAllocation, flags);
13bb5b
 
13bb5b
         if (userSelectionAllocation)
13bb5b
             this._userSelectionBox.allocate(userSelectionAllocation, flags);
13bb5b
 
13bb5b
         if (logoAllocation)
13bb5b
             this._logoBin.allocate(logoAllocation, flags);
13bb5b
     },
13bb5b
 
13bb5b
     _ensureUserListLoaded: function() {
13bb5b
-- 
13bb5b
2.1.0
13bb5b