Compare commits
	
		
			15 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | d985477a9d | ||
|   | b188d57609 | ||
|   | 412af26e4e | ||
|   | 7b440f3864 | ||
|   | 2d98903c90 | ||
|   | 9a0d0d2fd3 | ||
|   | 9451c04a09 | ||
|   | ca9099997c | ||
|   | 4de18f2d4b | ||
|   | 73d8f6c993 | ||
|   | 2141138a6f | ||
|   | 4f135be89a | ||
|   | 026ec2d4c2 | ||
|   | a82fae3a2f | ||
|   | 892d224cd7 | 
| @@ -381,6 +381,7 @@ StScrollBar StButton#vhandle:active { | ||||
| /* Entries */ | ||||
|  | ||||
| #searchEntry, | ||||
| .login-dialog StEntry, | ||||
| .notification StEntry, | ||||
| .modal-dialog StEntry { | ||||
|     color: rgb(64, 64, 64); | ||||
| @@ -392,6 +393,7 @@ StScrollBar StButton#vhandle:active { | ||||
| } | ||||
|  | ||||
| #searchEntry, | ||||
| .login-dialog StEntry, | ||||
| .run-dialog-entry, | ||||
| .notification StEntry { | ||||
|     border: 2px solid rgba(245,245,245,0.2); | ||||
| @@ -404,6 +406,7 @@ StScrollBar StButton#vhandle:active { | ||||
|  | ||||
| #searchEntry:focus, | ||||
| #searchEntry:hover, | ||||
| .login-dialog StEntry:focus, | ||||
| .notification StEntry:focus, | ||||
| .modal-dialog StEntry { | ||||
|     border: 2px solid rgb(136,138,133); | ||||
| @@ -413,6 +416,7 @@ StScrollBar StButton#vhandle:active { | ||||
|     box-shadow: inset 0px 2px 4px rgba(0,0,0,0.6); | ||||
| } | ||||
|  | ||||
| .login-dialog StEntry:focus, | ||||
| .notification StEntry:focus, | ||||
| .modal-dialog StEntry:focus { | ||||
|     border: 2px solid #3465a4; | ||||
| @@ -436,6 +440,7 @@ StScrollBar StButton#vhandle:active { | ||||
|     transition-duration: 0ms; | ||||
| } | ||||
|  | ||||
| .login-dialog StEntry, | ||||
| .notification StEntry, | ||||
| .modal-dialog StEntry { | ||||
|     border-radius: 5px; | ||||
| @@ -449,6 +454,7 @@ StScrollBar StButton#vhandle:active { | ||||
|     padding: 0 4px; | ||||
| } | ||||
|  | ||||
| .login-dialog StEntry:insensitive, | ||||
| .modal-dialog StEntry:insensitive { | ||||
|     border-color: #666666; | ||||
|     color: #9f9f9f; | ||||
| @@ -2234,8 +2240,13 @@ StScrollBar StButton#vhandle:active { | ||||
|     min-width: 350px; | ||||
| } | ||||
|  | ||||
| .login-dialog-button-box { | ||||
|     spacing: 21px; | ||||
| } | ||||
|  | ||||
| .login-dialog-prompt-login-hint-message { | ||||
|     font-size: 10.5pt; | ||||
|     min-width: 480px; | ||||
| } | ||||
|  | ||||
| .login-dialog-user-list-view { | ||||
| @@ -2342,7 +2353,7 @@ StScrollBar StButton#vhandle:active { | ||||
| } | ||||
|  | ||||
| .login-dialog-prompt-entry { | ||||
|     width: 15em; | ||||
|     width: 480px; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list, | ||||
|   | ||||
| @@ -17,13 +17,8 @@ misc/config.js: misc/config.js.in Makefile | ||||
| jsdir = $(pkgdatadir)/js | ||||
|  | ||||
| nobase_dist_js_DATA = 	\ | ||||
| 	gdm/batch.js		\ | ||||
| 	gdm/fingerprint.js	\ | ||||
| 	gdm/loginDialog.js	\ | ||||
| 	gdm/powerMenu.js	\ | ||||
| 	gdm/realmd.js		\ | ||||
| 	gdm/util.js		\ | ||||
| 	extensionPrefs/main.js	\ | ||||
| 	misc/batch.js		\ | ||||
| 	misc/config.js		\ | ||||
| 	misc/extensionUtils.js	\ | ||||
| 	misc/fileUtils.js	\ | ||||
| @@ -37,6 +32,7 @@ nobase_dist_js_DATA = 	\ | ||||
| 	misc/util.js		\ | ||||
| 	perf/core.js		\ | ||||
| 	ui/altTab.js		\ | ||||
| 	ui/animation.js		\ | ||||
| 	ui/appDisplay.js	\ | ||||
| 	ui/appFavorites.js	\ | ||||
| 	ui/backgroundMenu.js	\ | ||||
| @@ -95,7 +91,7 @@ nobase_dist_js_DATA = 	\ | ||||
| 	ui/status/bluetooth.js	\ | ||||
| 	ui/switcherPopup.js	\ | ||||
| 	ui/tweener.js		\ | ||||
| 	ui/unlockDialog.js	\ | ||||
| 	ui/userAvatar.js	\ | ||||
| 	ui/userMenu.js		\ | ||||
| 	ui/userWidget.js	\ | ||||
| 	ui/viewSelector.js	\ | ||||
| @@ -107,6 +103,14 @@ nobase_dist_js_DATA = 	\ | ||||
| 	ui/workspacesView.js	\ | ||||
| 	ui/workspaceSwitcherPopup.js    \ | ||||
| 	ui/xdndHandler.js	\ | ||||
| 	ui/auth/fingerprint.js	\ | ||||
| 	ui/auth/loginDialog.js	\ | ||||
| 	ui/auth/powerMenu.js	\ | ||||
| 	ui/auth/realmd.js	\ | ||||
| 	ui/auth/sessionList.js	\ | ||||
| 	ui/auth/unlockDialog.js	\ | ||||
| 	ui/auth/userList.js	\ | ||||
| 	ui/auth/util.js		\ | ||||
| 	ui/components/__init__.js		\ | ||||
| 	ui/components/autorunManager.js		\ | ||||
| 	ui/components/automountManager.js	\ | ||||
|   | ||||
							
								
								
									
										84
									
								
								js/ui/animation.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								js/ui/animation.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const Lang = imports.lang; | ||||
| const Mainloop = imports.mainloop; | ||||
| const St = imports.gi.St; | ||||
| const Signals = imports.signals; | ||||
| const Atk = imports.gi.Atk; | ||||
|  | ||||
| const ANIMATED_ICON_UPDATE_TIMEOUT = 100; | ||||
|  | ||||
| const Animation = new Lang.Class({ | ||||
|     Name: 'Animation', | ||||
|  | ||||
|     _init: function(filename, width, height, speed) { | ||||
|         this.actor = new St.Bin(); | ||||
|         this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | ||||
|         this._speed = speed; | ||||
|  | ||||
|         this._isLoaded = false; | ||||
|         this._isPlaying = false; | ||||
|         this._timeoutId = 0; | ||||
|         this._frame = 0; | ||||
|         this._animations = St.TextureCache.get_default().load_sliced_image (filename, width, height, | ||||
|                                                                             Lang.bind(this, this._animationsLoaded)); | ||||
|         this.actor.set_child(this._animations); | ||||
|     }, | ||||
|  | ||||
|     play: function() { | ||||
|         if (this._isLoaded && this._timeoutId == 0) { | ||||
|             if (this._frame == 0) | ||||
|                 this._showFrame(0); | ||||
|  | ||||
|             this._timeoutId = Mainloop.timeout_add(this._speed, Lang.bind(this, this._update)); | ||||
|         } | ||||
|  | ||||
|         this._isPlaying = true; | ||||
|     }, | ||||
|  | ||||
|     stop: function() { | ||||
|         if (this._timeoutId > 0) { | ||||
|             Mainloop.source_remove(this._timeoutId); | ||||
|             this._timeoutId = 0; | ||||
|         } | ||||
|  | ||||
|         this._isPlaying = false; | ||||
|     }, | ||||
|  | ||||
|     _showFrame: function(frame) { | ||||
|         let oldFrameActor = this._animations.get_child_at_index(this._frame); | ||||
|         if (oldFrameActor) | ||||
|             oldFrameActor.hide(); | ||||
|  | ||||
|         this._frame = (frame % this._animations.get_n_children()); | ||||
|  | ||||
|         let newFrameActor = this._animations.get_child_at_index(this._frame); | ||||
|         if (newFrameActor) | ||||
|             newFrameActor.show(); | ||||
|     }, | ||||
|  | ||||
|     _update: function() { | ||||
|         this._showFrame(this._frame + 1); | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     _animationsLoaded: function() { | ||||
|         this._isLoaded = true; | ||||
|  | ||||
|         if (this._isPlaying) | ||||
|             this.play(); | ||||
|     }, | ||||
|  | ||||
|     _onDestroy: function() { | ||||
|         this.stop(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const AnimatedIcon = new Lang.Class({ | ||||
|     Name: 'AnimatedIcon', | ||||
|     Extends: Animation, | ||||
|  | ||||
|     _init: function(filename, size) { | ||||
|         this.parent(filename, size, size, ANIMATED_ICON_UPDATE_TIMEOUT); | ||||
|     } | ||||
| }); | ||||
| @@ -19,6 +19,7 @@ | ||||
|  */ | ||||
| 
 | ||||
| const AccountsService = imports.gi.AccountsService; | ||||
| const Atk = imports.gi.Atk; | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const CtrlAltTab = imports.ui.ctrlAltTab; | ||||
| const Gio = imports.gi.Gio; | ||||
| @@ -28,464 +29,50 @@ const Mainloop = imports.mainloop; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Lang = imports.lang; | ||||
| const Pango = imports.gi.Pango; | ||||
| const Realmd = imports.gdm.realmd; | ||||
| const Realmd = imports.ui.auth.realmd; | ||||
| const Signals = imports.signals; | ||||
| const Shell = imports.gi.Shell; | ||||
| const St = imports.gi.St; | ||||
| const Gdm = imports.gi.Gdm; | ||||
| 
 | ||||
| const Batch = imports.gdm.batch; | ||||
| const Fprint = imports.gdm.fingerprint; | ||||
| const GdmUtil = imports.gdm.util; | ||||
| const Lightbox = imports.ui.lightbox; | ||||
| const Animation = imports.ui.animation; | ||||
| const AuthUtil = imports.ui.auth.util; | ||||
| const Batch = imports.misc.batch; | ||||
| const Fprint = imports.ui.auth.fingerprint; | ||||
| const Layout = imports.ui.layout; | ||||
| const Main = imports.ui.main; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
| const PanelMenu = imports.ui.panelMenu; | ||||
| const SessionList = imports.ui.auth.sessionList; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const UserMenu = imports.ui.userMenu; | ||||
| const UserAvatar = imports.ui.userAvatar; | ||||
| const UserList = imports.ui.auth.userList; | ||||
| const UserWidget = imports.ui.userWidget; | ||||
| 
 | ||||
| const _FADE_ANIMATION_TIME = 0.25; | ||||
| const _SCROLL_ANIMATION_TIME = 0.5; | ||||
| const _WORK_SPINNER_ICON_SIZE = 24; | ||||
| const _WORK_SPINNER_ANIMATION_DELAY = 1.0; | ||||
| const _WORK_SPINNER_ANIMATION_TIME = 0.3; | ||||
| const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0; | ||||
| const _LOGO_ICON_HEIGHT = 48; | ||||
| 
 | ||||
| let _loginDialog = null; | ||||
| 
 | ||||
| const UserListItem = new Lang.Class({ | ||||
|     Name: 'UserListItem', | ||||
| 
 | ||||
|     _init: function(user) { | ||||
|         this.user = user; | ||||
|         this._userChangedId = this.user.connect('changed', | ||||
|                                                  Lang.bind(this, this._onUserChanged)); | ||||
| 
 | ||||
|         let layout = new St.BoxLayout({ vertical: false }); | ||||
|         this.actor = new St.Button({ style_class: 'login-dialog-user-list-item', | ||||
|                                      button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, | ||||
|                                      can_focus: true, | ||||
|                                      child: layout, | ||||
|                                      reactive: true, | ||||
|                                      x_align: St.Align.START, | ||||
|                                      x_fill: true }); | ||||
| 
 | ||||
|         this._userAvatar = new UserMenu.UserAvatarWidget(this.user, | ||||
|                                                          { styleClass: 'login-dialog-user-list-item-icon' }); | ||||
|         layout.add(this._userAvatar.actor); | ||||
|         let textLayout = new St.BoxLayout({ style_class: 'login-dialog-user-list-item-text-box', | ||||
|                                             vertical:    true }); | ||||
|         layout.add(textLayout, { expand: true }); | ||||
| 
 | ||||
|         this._nameLabel = new St.Label({ style_class: 'login-dialog-user-list-item-name' }); | ||||
|         this.actor.label_actor = this._nameLabel; | ||||
|         textLayout.add(this._nameLabel, | ||||
|                        { y_fill: false, | ||||
|                          y_align: St.Align.MIDDLE, | ||||
|                          expand: true }); | ||||
| 
 | ||||
|         this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator', | ||||
|                                                  scale_x: 0 }); | ||||
|         textLayout.add(this._timedLoginIndicator, | ||||
|                        { x_fill: true, | ||||
|                          x_align: St.Align.MIDDLE, | ||||
|                          y_fill: false, | ||||
|                          y_align: St.Align.END }); | ||||
| 
 | ||||
|         this.actor.connect('clicked', Lang.bind(this, this._onClicked)); | ||||
|         this._onUserChanged(); | ||||
|     }, | ||||
| 
 | ||||
|     _onUserChanged: function() { | ||||
|         this._nameLabel.set_text(this.user.get_real_name()); | ||||
|         this._userAvatar.update(); | ||||
|         this._updateLoggedIn(); | ||||
|     }, | ||||
| 
 | ||||
|     syncStyleClasses: function() { | ||||
|         this._updateLoggedIn(); | ||||
| 
 | ||||
|         if (global.stage.get_key_focus() == this.actor) | ||||
|             this.actor.add_style_pseudo_class('focus'); | ||||
|         else | ||||
|             this.actor.remove_style_pseudo_class('focus'); | ||||
|     }, | ||||
| 
 | ||||
|     _updateLoggedIn: function() { | ||||
|         if (this.user.is_logged_in()) | ||||
|             this.actor.add_style_pseudo_class('logged-in'); | ||||
|         else | ||||
|             this.actor.remove_style_pseudo_class('logged-in'); | ||||
|     }, | ||||
| 
 | ||||
|     _onClicked: function() { | ||||
|         this.emit('activate'); | ||||
|     }, | ||||
| 
 | ||||
|     showTimedLoginIndicator: function(time) { | ||||
|         let hold = new Batch.Hold(); | ||||
| 
 | ||||
|         this.hideTimedLoginIndicator(); | ||||
|         Tweener.addTween(this._timedLoginIndicator, | ||||
|                          { scale_x: 1., | ||||
|                            time: time, | ||||
|                            transition: 'linear', | ||||
|                            onComplete: function() { | ||||
|                                hold.release(); | ||||
|                            }, | ||||
|                            onCompleteScope: this | ||||
|                          }); | ||||
|         return hold; | ||||
|     }, | ||||
| 
 | ||||
|     hideTimedLoginIndicator: function() { | ||||
|         Tweener.removeTweens(this._timedLoginIndicator); | ||||
|         this._timedLoginIndicator.scale_x = 0.; | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(UserListItem.prototype); | ||||
| 
 | ||||
| const UserList = new Lang.Class({ | ||||
|     Name: 'UserList', | ||||
| 
 | ||||
|     _init: function() { | ||||
|         this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'}); | ||||
|         this.actor.set_policy(Gtk.PolicyType.NEVER, | ||||
|                               Gtk.PolicyType.AUTOMATIC); | ||||
| 
 | ||||
|         this._box = new St.BoxLayout({ vertical: true, | ||||
|                                        style_class: 'login-dialog-user-list', | ||||
|                                        pseudo_class: 'expanded' }); | ||||
| 
 | ||||
|         this.actor.add_actor(this._box); | ||||
|         this._items = {}; | ||||
| 
 | ||||
|         this.actor.connect('key-focus-in', Lang.bind(this, this._moveFocusToItems)); | ||||
|     }, | ||||
| 
 | ||||
|     _moveFocusToItems: function() { | ||||
|         let hasItems = Object.keys(this._items).length > 0; | ||||
| 
 | ||||
|         if (!hasItems) | ||||
|             return; | ||||
| 
 | ||||
|         if (global.stage.get_key_focus() != this.actor) | ||||
|             return; | ||||
| 
 | ||||
|         let focusSet = this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); | ||||
|         if (!focusSet) { | ||||
|             Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { | ||||
|                 this._moveFocusToItems(); | ||||
|                 return false; | ||||
|             })); | ||||
|         } | ||||
|     }, | ||||
| 
 | ||||
|     _onItemActivated: function(activatedItem) { | ||||
|         this.emit('activate', activatedItem); | ||||
|     }, | ||||
| 
 | ||||
|     updateStyle: function(isExpanded) { | ||||
|         let tasks = []; | ||||
| 
 | ||||
|         if (isExpanded) | ||||
|             this._box.add_style_pseudo_class('expanded'); | ||||
|         else | ||||
|             this._box.remove_style_pseudo_class('expanded'); | ||||
| 
 | ||||
|         for (let userName in this._items) { | ||||
|             let item = this._items[userName]; | ||||
|             item.actor.sync_hover(); | ||||
|             item.syncStyleClasses(); | ||||
|         } | ||||
|     }, | ||||
| 
 | ||||
|     scrollToItem: function(item) { | ||||
|         let box = item.actor.get_allocation_box(); | ||||
| 
 | ||||
|         let adjustment = this.actor.get_vscroll_bar().get_adjustment(); | ||||
| 
 | ||||
|         let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0); | ||||
|         Tweener.removeTweens(adjustment); | ||||
|         Tweener.addTween (adjustment, | ||||
|                           { value: value, | ||||
|                             time: _SCROLL_ANIMATION_TIME, | ||||
|                             transition: 'easeOutQuad' }); | ||||
|     }, | ||||
| 
 | ||||
|     jumpToItem: function(item) { | ||||
|         let box = item.actor.get_allocation_box(); | ||||
| 
 | ||||
|         let adjustment = this.actor.get_vscroll_bar().get_adjustment(); | ||||
| 
 | ||||
|         let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0); | ||||
| 
 | ||||
|         adjustment.set_value(value); | ||||
|     }, | ||||
| 
 | ||||
|     getItemFromUserName: function(userName) { | ||||
|         let item = this._items[userName]; | ||||
| 
 | ||||
|         if (!item) | ||||
|             return null; | ||||
| 
 | ||||
|         return item; | ||||
|     }, | ||||
| 
 | ||||
|     addUser: function(user) { | ||||
|         if (!user.is_loaded) | ||||
|             return; | ||||
| 
 | ||||
|         if (user.is_system_account()) | ||||
|             return; | ||||
| 
 | ||||
|         if (user.locked) | ||||
|            return; | ||||
| 
 | ||||
|         let userName = user.get_user_name(); | ||||
| 
 | ||||
|         if (!userName) | ||||
|             return; | ||||
| 
 | ||||
|         this.removeUser(user); | ||||
| 
 | ||||
|         let item = new UserListItem(user); | ||||
|         this._box.add(item.actor, { x_fill: true }); | ||||
| 
 | ||||
|         this._items[userName] = item; | ||||
| 
 | ||||
|         item.connect('activate', | ||||
|                      Lang.bind(this, this._onItemActivated)); | ||||
| 
 | ||||
|         // Try to keep the focused item front-and-center
 | ||||
|         item.actor.connect('key-focus-in', | ||||
|                            Lang.bind(this, | ||||
|                                      function() { | ||||
|                                          this.scrollToItem(item); | ||||
|                                      })); | ||||
| 
 | ||||
|         this._moveFocusToItems(); | ||||
| 
 | ||||
|         this.emit('item-added', item); | ||||
|     }, | ||||
| 
 | ||||
|     removeUser: function(user) { | ||||
|         if (!user.is_loaded) | ||||
|             return; | ||||
| 
 | ||||
|         let userName = user.get_user_name(); | ||||
| 
 | ||||
|         if (!userName) | ||||
|             return; | ||||
| 
 | ||||
|         let item = this._items[userName]; | ||||
| 
 | ||||
|         if (!item) | ||||
|             return; | ||||
| 
 | ||||
|         item.actor.destroy(); | ||||
|         delete this._items[userName]; | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(UserList.prototype); | ||||
| 
 | ||||
| const SessionListItem = new Lang.Class({ | ||||
|     Name: 'SessionListItem', | ||||
| 
 | ||||
|     _init: function(id, name) { | ||||
|         this.id = id; | ||||
| 
 | ||||
|         this.actor = new St.Button({ style_class: 'login-dialog-session-list-item', | ||||
|                                      button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, | ||||
|                                      can_focus: true, | ||||
|                                      reactive: true, | ||||
|                                      x_fill: true, | ||||
|                                      x_align: St.Align.START }); | ||||
| 
 | ||||
|         this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list-item-box' }); | ||||
| 
 | ||||
|         this.actor.add_actor(this._box); | ||||
|         this.actor.connect('clicked', Lang.bind(this, this._onClicked)); | ||||
| 
 | ||||
|         this._dot = new St.DrawingArea({ style_class: 'login-dialog-session-list-item-dot' }); | ||||
|         this._dot.connect('repaint', Lang.bind(this, this._onRepaintDot)); | ||||
|         this._box.add_actor(this._dot); | ||||
|         this.setShowDot(false); | ||||
| 
 | ||||
|         let label = new St.Label({ style_class: 'login-dialog-session-list-item-label', | ||||
|                                    text: name }); | ||||
|         this.actor.label_actor = label; | ||||
| 
 | ||||
|         this._box.add_actor(label); | ||||
|     }, | ||||
| 
 | ||||
|     setShowDot: function(show) { | ||||
|         if (show) | ||||
|             this._dot.opacity = 255; | ||||
|         else | ||||
|             this._dot.opacity = 0; | ||||
|     }, | ||||
| 
 | ||||
|     _onRepaintDot: function(area) { | ||||
|         let cr = area.get_context(); | ||||
|         let [width, height] = area.get_surface_size(); | ||||
|         let color = area.get_theme_node().get_foreground_color(); | ||||
| 
 | ||||
|         cr.setSourceRGBA (color.red / 255, | ||||
|                           color.green / 255, | ||||
|                           color.blue / 255, | ||||
|                           color.alpha / 255); | ||||
|         cr.arc(width / 2, height / 2, width / 3, 0, 2 * Math.PI); | ||||
|         cr.fill(); | ||||
|         cr.$dispose(); | ||||
|     }, | ||||
| 
 | ||||
|     _onClicked: function() { | ||||
|         this.emit('activate'); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(SessionListItem.prototype); | ||||
| 
 | ||||
| const SessionList = new Lang.Class({ | ||||
|     Name: 'SessionList', | ||||
| 
 | ||||
|     _init: function() { | ||||
|         this.actor = new St.Bin(); | ||||
| 
 | ||||
|         this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list', | ||||
|                                        vertical: true}); | ||||
|         this.actor.child = this._box; | ||||
| 
 | ||||
|         this._button = new St.Button({ style_class: 'login-dialog-session-list-button', | ||||
|                                        button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, | ||||
|                                        can_focus: true, | ||||
|                                        x_fill: true, | ||||
|                                        y_fill: true }); | ||||
|         let box = new St.BoxLayout(); | ||||
|         this._button.add_actor(box); | ||||
| 
 | ||||
|         this._triangle = new St.Label({ style_class: 'login-dialog-session-list-triangle', | ||||
|                                         text: '\u25B8' }); | ||||
|         box.add_actor(this._triangle); | ||||
| 
 | ||||
|         let label = new St.Label({ style_class: 'login-dialog-session-list-label', | ||||
|                                    text: _("Session…") }); | ||||
|         box.add_actor(label); | ||||
| 
 | ||||
|         this._button.connect('clicked', | ||||
|                              Lang.bind(this, this._onClicked)); | ||||
|         this._box.add_actor(this._button); | ||||
|         this._scrollView = new St.ScrollView({ style_class: 'login-dialog-session-list-scroll-view'}); | ||||
|         this._scrollView.set_policy(Gtk.PolicyType.NEVER, | ||||
|                                     Gtk.PolicyType.AUTOMATIC); | ||||
|         this._box.add_actor(this._scrollView); | ||||
|         this._itemList = new St.BoxLayout({ style_class: 'login-dialog-session-item-list', | ||||
|                                             vertical: true }); | ||||
|         this._scrollView.add_actor(this._itemList); | ||||
|         this._scrollView.hide(); | ||||
|         this.isOpen = false; | ||||
|         this._populate(); | ||||
|     }, | ||||
| 
 | ||||
|     open: function() { | ||||
|         if (this.isOpen) | ||||
|             return; | ||||
| 
 | ||||
|         this._button.add_style_pseudo_class('open'); | ||||
|         this._scrollView.show(); | ||||
|         this._triangle.set_text('\u25BE'); | ||||
| 
 | ||||
|         this.isOpen = true; | ||||
|     }, | ||||
| 
 | ||||
|     close: function() { | ||||
|         if (!this.isOpen) | ||||
|             return; | ||||
| 
 | ||||
|         this._button.remove_style_pseudo_class('open'); | ||||
|         this._scrollView.hide(); | ||||
|         this._triangle.set_text('\u25B8'); | ||||
| 
 | ||||
|         this.isOpen = false; | ||||
|     }, | ||||
| 
 | ||||
|     _onClicked: function() { | ||||
|         if (!this.isOpen) | ||||
|             this.open(); | ||||
|         else | ||||
|             this.close(); | ||||
|     }, | ||||
| 
 | ||||
|     updateSensitivity: function(sensitive) { | ||||
|         this._button.reactive = sensitive; | ||||
|         this._button.can_focus = sensitive; | ||||
| 
 | ||||
|         for (let id in this._items) | ||||
|             this._items[id].actor.reactive = sensitive; | ||||
|     }, | ||||
| 
 | ||||
|     setActiveSession: function(sessionId) { | ||||
|          if (sessionId == this._activeSessionId) | ||||
|              return; | ||||
| 
 | ||||
|          if (this._activeSessionId) | ||||
|              this._items[this._activeSessionId].setShowDot(false); | ||||
| 
 | ||||
|          this._items[sessionId].setShowDot(true); | ||||
|          this._activeSessionId = sessionId; | ||||
| 
 | ||||
|          this.emit('session-activated', this._activeSessionId); | ||||
|     }, | ||||
| 
 | ||||
|     _populate: function() { | ||||
|         this._itemList.destroy_all_children(); | ||||
|         this._activeSessionId = null; | ||||
|         this._items = {}; | ||||
| 
 | ||||
|         let ids = Gdm.get_session_ids(); | ||||
|         ids.sort(); | ||||
| 
 | ||||
|         if (ids.length <= 1) { | ||||
|             this._box.hide(); | ||||
|             this._button.hide(); | ||||
|         } else { | ||||
|             this._button.show(); | ||||
|             this._box.show(); | ||||
|         } | ||||
| 
 | ||||
|         for (let i = 0; i < ids.length; i++) { | ||||
|             let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]); | ||||
| 
 | ||||
|             let item = new SessionListItem(ids[i], sessionName); | ||||
|             this._itemList.add_actor(item.actor); | ||||
|             this._items[ids[i]] = item; | ||||
| 
 | ||||
|             if (!this._activeSessionId) | ||||
|                 this.setActiveSession(ids[i]); | ||||
| 
 | ||||
|             item.connect('activate', | ||||
|                          Lang.bind(this, function() { | ||||
|                              this.setActiveSession(item.id); | ||||
|                          })); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(SessionList.prototype); | ||||
| 
 | ||||
| const LoginDialog = new Lang.Class({ | ||||
|     Name: 'LoginDialog', | ||||
|     Extends: ModalDialog.ModalDialog, | ||||
| 
 | ||||
|     _init: function(parentActor) { | ||||
|         this.parent({ shellReactive: true, | ||||
|                       styleClass: 'login-dialog', | ||||
|                       parentActor: parentActor, | ||||
|                       keybindingMode: Shell.KeyBindingMode.LOGIN_SCREEN, | ||||
|                       shouldFadeIn: false }); | ||||
|         this.connect('destroy', | ||||
|                      Lang.bind(this, this._onDestroy)); | ||||
|         this.connect('opened', | ||||
|                      Lang.bind(this, this._onOpened)); | ||||
|         this.actor = new St.Widget({ accessible_role: Atk.Role.WINDOW, | ||||
|                                      style_class: 'login-dialog' }); | ||||
| 
 | ||||
|         this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true })); | ||||
|         this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | ||||
|         parentActor.add_child(this.actor); | ||||
| 
 | ||||
|         Main.ctrlAltTabManager.addGroup(this.actor, | ||||
|                                         _("Login Window"), | ||||
|                                         'dialog-password-symbolic', | ||||
|                                         { sortGroup: CtrlAltTab.SortGroup.MIDDLE }); | ||||
|         this._userManager = AccountsService.UserManager.get_default() | ||||
|         this._greeterClient = new Gdm.Client(); | ||||
| 
 | ||||
| @@ -501,24 +88,24 @@ const LoginDialog = new Lang.Class({ | ||||
|                                   Lang.bind(this, this._onTimedLoginRequested)); | ||||
|         } | ||||
| 
 | ||||
|         this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient); | ||||
|         this._userVerifier = new AuthUtil.ShellUserVerifier(this._greeterClient); | ||||
|         this._userVerifier.connect('ask-question', Lang.bind(this, this._askQuestion)); | ||||
|         this._userVerifier.connect('show-message', Lang.bind(this, this._showMessage)); | ||||
|         this._userVerifier.connect('show-message', Lang.bind(this, this._onShowMessage)); | ||||
|         this._userVerifier.connect('verification-failed', Lang.bind(this, this._verificationFailed)); | ||||
|         this._userVerifier.connect('reset', Lang.bind(this, this._reset)); | ||||
|         this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint)); | ||||
|         this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint)); | ||||
|         this._verifyingUser = false; | ||||
| 
 | ||||
|         this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA }); | ||||
|         this._settings = new Gio.Settings({ schema: AuthUtil.LOGIN_SCREEN_SCHEMA }); | ||||
| 
 | ||||
|         this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY, | ||||
|         this._settings.connect('changed::' + AuthUtil.BANNER_MESSAGE_KEY, | ||||
|                                Lang.bind(this, this._updateBanner)); | ||||
|         this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_TEXT_KEY, | ||||
|         this._settings.connect('changed::' + AuthUtil.BANNER_MESSAGE_TEXT_KEY, | ||||
|                                Lang.bind(this, this._updateBanner)); | ||||
|         this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY, | ||||
|         this._settings.connect('changed::' + AuthUtil.DISABLE_USER_LIST_KEY, | ||||
|                                Lang.bind(this, this._updateDisableUserList)); | ||||
|         this._settings.connect('changed::' + GdmUtil.LOGO_KEY, | ||||
|         this._settings.connect('changed::' + AuthUtil.LOGO_KEY, | ||||
|                                Lang.bind(this, this._updateLogo)); | ||||
| 
 | ||||
|         this._textureCache = St.TextureCache.get_default(); | ||||
| @@ -527,28 +114,31 @@ const LoginDialog = new Lang.Class({ | ||||
| 
 | ||||
|         this._userSelectionBox = new St.BoxLayout({ style_class: 'login-dialog-user-selection-box', | ||||
|                                                     vertical: true }); | ||||
|         this.contentLayout.add(this._userSelectionBox); | ||||
| 
 | ||||
|         this._userSelectionBox.add_constraint(new Clutter.AlignConstraint({ source: this.actor, | ||||
|                                                                             align_axis: Clutter.AlignAxis.BOTH, | ||||
|                                                                             factor: 0.5 })); | ||||
|         this.actor.add_child(this._userSelectionBox); | ||||
| 
 | ||||
|         this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner', | ||||
|                                            text: '' }); | ||||
|         this._userSelectionBox.add(this._bannerLabel); | ||||
|         this._updateBanner(); | ||||
| 
 | ||||
|         this._userList = new UserList(); | ||||
|         this._userList = new UserList.UserList(); | ||||
|         this._userSelectionBox.add(this._userList.actor, | ||||
|                                    { expand: true, | ||||
|                                      x_fill: true, | ||||
|                                      y_fill: true }); | ||||
| 
 | ||||
|         this.setInitialKeyFocus(this._userList.actor); | ||||
|         this._userList.actor.grab_key_focus(); | ||||
| 
 | ||||
|         this._promptBox = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout', | ||||
|                                              vertical: true }); | ||||
|         this.contentLayout.add(this._promptBox, | ||||
|                                { expand: true, | ||||
|                                  x_fill: true, | ||||
|                                  y_fill: true, | ||||
|                                  x_align: St.Align.START }); | ||||
|         this._promptBox.add_constraint(new Clutter.AlignConstraint({ source: this.actor, | ||||
|                                                                      align_axis: Clutter.AlignAxis.BOTH, | ||||
|                                                                      factor: 0.5 })); | ||||
|         this.actor.add_child(this._promptBox); | ||||
|         this._promptUser = new St.Bin({ x_fill: true, | ||||
|                                         x_align: St.Align.START }); | ||||
|         this._promptBox.add(this._promptUser, | ||||
| @@ -568,21 +158,29 @@ const LoginDialog = new Lang.Class({ | ||||
|         this._promptEntryTextChangedId = 0; | ||||
|         this._promptEntryActivateId = 0; | ||||
|         this._promptBox.add(this._promptEntry, | ||||
|                             { expand: true, | ||||
|                               x_fill: true, | ||||
|                               y_fill: false, | ||||
|                               x_align: St.Align.START }); | ||||
|                             { expand: false, | ||||
|                               x_fill: false }); | ||||
| 
 | ||||
|         this._promptMessage = new St.Label({ visible: false }); | ||||
|         this._promptBox.add(this._promptMessage, { x_fill: true }); | ||||
|         this._promptMessage = new St.Label({ opacity: 0 }); | ||||
|         this.actor.add_child(this._promptMessage); | ||||
| 
 | ||||
|         this._promptLoginHint = new St.Label({ style_class: 'login-dialog-prompt-login-hint-message' }); | ||||
|         this._promptLoginHint.hide(); | ||||
|         this._promptBox.add(this._promptLoginHint); | ||||
|         this._promptMessagePlaceholder = new Clutter.Actor({ width: 1, height: 1 }); | ||||
|         this._promptBox.add_child(this._promptMessagePlaceholder); | ||||
| 
 | ||||
|         this._signInButton = null; | ||||
|         this._promptMessagePlaceholder.add_constraint(new Clutter.BindConstraint({ source: this._promptMessage, | ||||
|                                                                                    coordinate: Clutter.BindCoordinate.HEIGHT })); | ||||
| 
 | ||||
|         this._sessionList = new SessionList(); | ||||
|         this._promptMessage.add_constraint(new Clutter.AlignConstraint({ source: this.actor, | ||||
|                                                                          align_axis: Clutter.AlignAxis.X_AXIS, | ||||
|                                                                          factor: 0.5 })); | ||||
| 
 | ||||
|         this._promptMessagePlaceholder.connect("notify::y", Lang.bind(this, function() { | ||||
|                                                    let [placeholderX , placeholderY] = this._promptMessagePlaceholder.get_transformed_position(); | ||||
|                                                    let [actorX, actorY] = this.actor.get_transformed_position(); | ||||
|                                                    this._promptMessage.y = placeholderY - actorY; | ||||
|                                                })); | ||||
| 
 | ||||
|         this._sessionList = new SessionList.SessionList(); | ||||
|         this._sessionList.connect('session-activated', | ||||
|                                   Lang.bind(this, function(list, sessionId) { | ||||
|                                                 this._greeter.call_select_session_sync (sessionId, null); | ||||
| @@ -593,6 +191,16 @@ const LoginDialog = new Lang.Class({ | ||||
|                               x_fill: false, | ||||
|                               y_fill: true, | ||||
|                               x_align: St.Align.START }); | ||||
| 
 | ||||
|         this._buttonBox = new St.BoxLayout({ style_class: 'login-dialog-button-box', | ||||
|                                              vertical: false }); | ||||
|         this._promptBox.add(this._buttonBox, | ||||
|                             { expand:  true, | ||||
|                               x_align: St.Align.MIDDLE, | ||||
|                               y_align: St.Align.END }); | ||||
|         this._cancelButton = null; | ||||
|         this._signInButton = null; | ||||
| 
 | ||||
|         this._promptBox.hide(); | ||||
| 
 | ||||
|         // translators: this message is shown below the user list on the
 | ||||
| @@ -617,7 +225,13 @@ const LoginDialog = new Lang.Class({ | ||||
| 
 | ||||
|         this._logoBin = new St.Bin({ style_class: 'login-dialog-logo-bin', y_expand: true }); | ||||
|         this._logoBin.set_y_align(Clutter.ActorAlign.END); | ||||
|         this.backgroundStack.add_actor(this._logoBin); | ||||
|         this._logoBin.add_constraint(new Clutter.AlignConstraint({ source: this.actor, | ||||
|                                                                    align_axis: Clutter.AlignAxis.X_AXIS, | ||||
|                                                                    factor: 0.5 })); | ||||
|         this._logoBin.add_constraint(new Clutter.AlignConstraint({ source: this.actor, | ||||
|                                                                    align_axis: Clutter.AlignAxis.Y_AXIS, | ||||
|                                                                    factor: 1.0 })); | ||||
|         this.actor.add_actor(this._logoBin); | ||||
|         this._updateLogo(); | ||||
| 
 | ||||
|         if (!this._userManager.is_loaded) | ||||
| @@ -640,7 +254,7 @@ const LoginDialog = new Lang.Class({ | ||||
|    }, | ||||
| 
 | ||||
|     _updateDisableUserList: function() { | ||||
|         let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY); | ||||
|         let disableUserList = this._settings.get_boolean(AuthUtil.DISABLE_USER_LIST_KEY); | ||||
| 
 | ||||
|         // If this is the first time around, set initial focus
 | ||||
|         if (this._disableUserList == undefined && disableUserList) | ||||
| @@ -655,8 +269,8 @@ const LoginDialog = new Lang.Class({ | ||||
|     }, | ||||
| 
 | ||||
|     _updateBanner: function() { | ||||
|         let enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY); | ||||
|         let text = this._settings.get_string(GdmUtil.BANNER_MESSAGE_TEXT_KEY); | ||||
|         let enabled = this._settings.get_boolean(AuthUtil.BANNER_MESSAGE_KEY); | ||||
|         let text = this._settings.get_string(AuthUtil.BANNER_MESSAGE_TEXT_KEY); | ||||
| 
 | ||||
|         if (enabled && text) { | ||||
|             this._bannerLabel.set_text(text); | ||||
| @@ -678,7 +292,7 @@ const LoginDialog = new Lang.Class({ | ||||
|     }, | ||||
| 
 | ||||
|     _updateLogo: function() { | ||||
|         let path = this._settings.get_string(GdmUtil.LOGO_KEY); | ||||
|         let path = this._settings.get_string(AuthUtil.LOGO_KEY); | ||||
| 
 | ||||
|         this._logoFileUri = path ? Gio.file_new_for_path(path).get_uri() : null; | ||||
|         this._updateLogoTexture(this._textureCache, this._logoFileUri); | ||||
| @@ -688,7 +302,7 @@ const LoginDialog = new Lang.Class({ | ||||
|         this._userVerifier.clear(); | ||||
| 
 | ||||
|         this._updateSensitivity(true); | ||||
|         this._promptMessage.hide(); | ||||
|         this._promptMessage.opacity = 0; | ||||
|         this._user = null; | ||||
|         this._verifyingUser = false; | ||||
| 
 | ||||
| @@ -698,36 +312,69 @@ const LoginDialog = new Lang.Class({ | ||||
|             this._showUserList(); | ||||
|     }, | ||||
| 
 | ||||
|     _setWorking: function(working) { | ||||
|         if (!this._workSpinner) | ||||
|             return; | ||||
| 
 | ||||
|         Tweener.removeTweens(this._workSpinner.actor); | ||||
|         if (working) { | ||||
|             this._workSpinner.play(); | ||||
|             Tweener.addTween(this._workSpinner.actor, | ||||
|                              { opacity: 255, | ||||
|                                delay: _WORK_SPINNER_ANIMATION_DELAY, | ||||
|                                time: _WORK_SPINNER_ANIMATION_TIME, | ||||
|                                transition: 'linear' | ||||
|                              }); | ||||
|         } else { | ||||
|             Tweener.addTween(this._workSpinner.actor, | ||||
|                              { opacity: 0, | ||||
|                                time: _WORK_SPINNER_ANIMATION_TIME, | ||||
|                                transition: 'linear', | ||||
|                                onCompleteScope: this, | ||||
|                                onComplete: function() { | ||||
|                                    if (this._workSpinner) | ||||
|                                        this._workSpinner.stop(); | ||||
|                                } | ||||
|                              }); | ||||
|         } | ||||
|     }, | ||||
| 
 | ||||
|     _verificationFailed: function() { | ||||
|         this._promptEntry.text = ''; | ||||
| 
 | ||||
|         this._updateSensitivity(true); | ||||
|         this.setWorking(false); | ||||
|         this._setWorking(false); | ||||
|     }, | ||||
| 
 | ||||
|     _onDefaultSessionChanged: function(client, sessionId) { | ||||
|         this._sessionList.setActiveSession(sessionId); | ||||
|     }, | ||||
| 
 | ||||
|     _showMessage: function(userVerifier, message, styleClass) { | ||||
|     _showMessage: function(message, styleClass) { | ||||
|         if (message) { | ||||
|             this._promptMessage.text = message; | ||||
|             this._promptMessage.styleClass = styleClass; | ||||
|             this._promptMessage.show(); | ||||
|             this._promptMessage.opacity = 255; | ||||
|         } else { | ||||
|             this._promptMessage.hide(); | ||||
|             this._promptMessage.opacity = 0; | ||||
|         } | ||||
|     }, | ||||
| 
 | ||||
|     _onShowMessage: function(userVerifier, message, styleClass) { | ||||
|         this._showMessage(message, styleClass); | ||||
|         this._loginHintShown = false; | ||||
|     }, | ||||
| 
 | ||||
|     _showLoginHint: function(verifier, message) { | ||||
|         this._promptLoginHint.set_text(message) | ||||
|         this._promptLoginHint.show(); | ||||
|         this._promptLoginHint.opacity = 255; | ||||
|         this._showMessage(message, 'login-dialog-prompt-login-hint-message'); | ||||
|         this._loginHintShown = true; | ||||
|     }, | ||||
| 
 | ||||
|     _hideLoginHint: function() { | ||||
|         this._promptLoginHint.hide(); | ||||
|         this._promptLoginHint.set_text(''); | ||||
|         if (!this._loginHintShown) | ||||
|             return; | ||||
|         this._showMessage('', 'login-dialog-prompt-login-hint-message'); | ||||
|         this._loginHintShown = false; | ||||
|     }, | ||||
| 
 | ||||
|     cancel: function() { | ||||
| @@ -741,8 +388,6 @@ const LoginDialog = new Lang.Class({ | ||||
|         this._sessionList.actor.hide(); | ||||
|         this._promptLabel.show(); | ||||
|         this._promptEntry.show(); | ||||
|         this._promptLoginHint.opacity = 0; | ||||
|         this._promptLoginHint.show(); | ||||
|         this._promptBox.opacity = 0; | ||||
|         this._promptBox.show(); | ||||
|         Tweener.addTween(this._promptBox, | ||||
| @@ -768,33 +413,62 @@ const LoginDialog = new Lang.Class({ | ||||
|     }, | ||||
| 
 | ||||
|     _prepareDialog: function(forSecret, hold) { | ||||
|         this.buttonLayout.visible = true; | ||||
|         this.clearButtons(); | ||||
|         this._buttonBox.visible = true; | ||||
|         this._buttonBox.destroy_all_children(); | ||||
| 
 | ||||
|         if (!this._disableUserList || this._verifyingUser) | ||||
|             this.addButton({ action: Lang.bind(this, this.cancel), | ||||
|                              label: _("Cancel"), | ||||
|                              key: Clutter.Escape }, | ||||
|                            { expand: true, | ||||
|                              x_fill: false, | ||||
|                              y_fill: false, | ||||
|                              x_align: St.Align.START, | ||||
|                              y_align: St.Align.MIDDLE }); | ||||
|         this.placeSpinner({ expand: false, | ||||
|                             x_fill: false, | ||||
|                             y_fill: false, | ||||
|                             x_align: St.Align.END, | ||||
|                             y_align: St.Align.MIDDLE }); | ||||
|         this._signInButton = this.addButton({ action: Lang.bind(this, function() { | ||||
|                                                           hold.release(); | ||||
|                                                       }), | ||||
|                                               label: forSecret ? C_("button", "Sign In") : _("Next"), | ||||
|                                               default: true }, | ||||
|                                             { expand: false, | ||||
|                                               x_fill: false, | ||||
|                                               y_fill: false, | ||||
|                                               x_align: St.Align.END, | ||||
|                                               y_align: St.Align.MIDDLE }); | ||||
|         if (!this._disableUserList || this._verifyingUser) { | ||||
|             this._cancelButton = new St.Button({ style_class: 'modal-dialog-button', | ||||
|                                                  button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, | ||||
|                                                  reactive: true, | ||||
|                                                  can_focus: true, | ||||
|                                                  label: _("Cancel") }); | ||||
|             this._cancelButton.connect('clicked', | ||||
|                                        Lang.bind(this, function() { | ||||
|                                            this.cancel(); | ||||
|                                        })); | ||||
|             global.stage.connect('captured-event', | ||||
|                                  Lang.bind(this, function(actor, event) { | ||||
|                                     if (event.type() == Clutter.EventType.KEY_PRESS && | ||||
|                                         event.get_key_symbol() == Clutter.KEY_Escape) { | ||||
|                                         this.cancel(); | ||||
|                                     } | ||||
|                                  })); | ||||
|             this._buttonBox.add(this._cancelButton, | ||||
|                                 { expand: true, | ||||
|                                   x_fill: false, | ||||
|                                   y_fill: false, | ||||
|                                   x_align: St.Align.START, | ||||
|                                   y_align: St.Align.END }); | ||||
|         } | ||||
| 
 | ||||
|         let spinnerIcon = global.datadir + '/theme/process-working.svg'; | ||||
|         this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, _WORK_SPINNER_ICON_SIZE); | ||||
|         this._workSpinner.actor.opacity = 0; | ||||
|         this._workSpinner.actor.show(); | ||||
| 
 | ||||
|         this._buttonBox.add(this._workSpinner.actor, | ||||
|                             { expand: false, | ||||
|                               x_fill: false, | ||||
|                               y_fill: false, | ||||
|                               x_align: St.Align.END, | ||||
|                               y_align: St.Align.MIDDLE }); | ||||
| 
 | ||||
|         this._signInButton = new St.Button({ style_class: 'modal-dialog-button', | ||||
|                                              button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, | ||||
|                                              reactive: true, | ||||
|                                              can_focus: true, | ||||
|                                              label: forSecret ? C_("button", "Sign In") : _("Next") }); | ||||
|         this._signInButton.connect('clicked', | ||||
|                                    Lang.bind(this, function() { | ||||
|                                        hold.release(); | ||||
|                                    })); | ||||
|         this._signInButton.add_style_pseudo_class('default'); | ||||
|         this._buttonBox.add(this._signInButton, | ||||
|                             { expand: true, | ||||
|                               x_fill: false, | ||||
|                               y_fill: false, | ||||
|                               x_align: St.Align.END, | ||||
|                               y_align: St.Align.END }); | ||||
| 
 | ||||
|         this._updateSignInButtonSensitivity(this._promptEntry.text.length > 0); | ||||
| 
 | ||||
| @@ -804,10 +478,10 @@ const LoginDialog = new Lang.Class({ | ||||
|                                                         this._updateSignInButtonSensitivity(this._promptEntry.text.length > 0); | ||||
|                                                     })); | ||||
| 
 | ||||
|         this._promptEntryActivateId = | ||||
|             this._promptEntry.clutter_text.connect('activate', function() { | ||||
|                 hold.release(); | ||||
|             }); | ||||
|          this._promptEntryActivateId = | ||||
|              this._promptEntry.clutter_text.connect('activate', function() { | ||||
|                  hold.release(); | ||||
|              }); | ||||
|     }, | ||||
| 
 | ||||
|     _updateSensitivity: function(sensitive) { | ||||
| @@ -825,7 +499,7 @@ const LoginDialog = new Lang.Class({ | ||||
|     }, | ||||
| 
 | ||||
|     _hidePrompt: function() { | ||||
|         this.setButtons([]); | ||||
|         this._buttonBox.destroy_all_children(); | ||||
| 
 | ||||
|         if (this._promptEntryTextChangedId > 0) { | ||||
|             this._promptEntry.clutter_text.disconnect(this._promptEntryTextChangedId); | ||||
| @@ -837,9 +511,8 @@ const LoginDialog = new Lang.Class({ | ||||
|             this._promptEntryActivateId = 0; | ||||
|         } | ||||
| 
 | ||||
|         this.setWorking(false); | ||||
|         this._setWorking(false); | ||||
|         this._promptBox.hide(); | ||||
|         this._promptLoginHint.hide(); | ||||
| 
 | ||||
|         this._promptUser.set_child(null); | ||||
| 
 | ||||
| @@ -847,10 +520,10 @@ const LoginDialog = new Lang.Class({ | ||||
|         this._promptEntry.set_text(''); | ||||
| 
 | ||||
|         this._sessionList.close(); | ||||
|         this._promptLoginHint.hide(); | ||||
| 
 | ||||
|         this.clearButtons(); | ||||
|         this._buttonBox.destroy_all_children(); | ||||
|         this._signInButton = null; | ||||
|         this._cancelButton = null; | ||||
|     }, | ||||
| 
 | ||||
|     _askQuestion: function(verifier, serviceName, question, passwordChar) { | ||||
| @@ -867,7 +540,7 @@ const LoginDialog = new Lang.Class({ | ||||
|                      function() { | ||||
|                          let text = this._promptEntry.get_text(); | ||||
|                          this._updateSensitivity(false); | ||||
|                          this.setWorking(true); | ||||
|                          this._setWorking(true); | ||||
|                          this._userVerifier.answerQuery(serviceName, text); | ||||
|                      }]; | ||||
| 
 | ||||
| @@ -916,7 +589,7 @@ const LoginDialog = new Lang.Class({ | ||||
|     }, | ||||
| 
 | ||||
|     _startSession: function(serviceName) { | ||||
|         Tweener.addTween(this.dialogLayout, | ||||
|         Tweener.addTween(this.actor, | ||||
|                          { opacity: 0, | ||||
|                            time: _FADE_ANIMATION_TIME, | ||||
|                            transition: 'easeOutQuad', | ||||
| @@ -925,7 +598,7 @@ const LoginDialog = new Lang.Class({ | ||||
| 
 | ||||
|                                for (let i = 0; i < children.length; i++) { | ||||
|                                    if (children[i] != Main.layoutManager.screenShieldGroup) | ||||
|                                        children[i].opacity = this.dialogLayout.opacity; | ||||
|                                        children[i].opacity = this.actor.opacity; | ||||
|                                } | ||||
|                            }, | ||||
|                            onUpdateScope: this, | ||||
| @@ -1081,7 +754,7 @@ const LoginDialog = new Lang.Class({ | ||||
| 
 | ||||
|     _hideUserListAndLogIn: function() { | ||||
|         this._setUserListExpanded(false); | ||||
|         GdmUtil.cloneAndFadeOutActor(this._userSelectionBox); | ||||
|         AuthUtil.cloneAndFadeOutActor(this._userSelectionBox); | ||||
|         this._askForUsernameAndLogIn(); | ||||
|     }, | ||||
| 
 | ||||
| @@ -1113,7 +786,7 @@ const LoginDialog = new Lang.Class({ | ||||
| 
 | ||||
|     _onUserListActivated: function(activatedItem) { | ||||
|         let tasks = [function() { | ||||
|                          return GdmUtil.cloneAndFadeOutActor(this._userSelectionBox); | ||||
|                          return AuthUtil.cloneAndFadeOutActor(this._userSelectionBox); | ||||
|                      }, | ||||
|                      function() { | ||||
|                          this._setUserListExpanded(false); | ||||
| @@ -1131,6 +804,8 @@ const LoginDialog = new Lang.Class({ | ||||
|             this._userManager.disconnect(this._userManagerLoadedId); | ||||
|             this._userManagerLoadedId = 0; | ||||
|         } | ||||
| 
 | ||||
|         Main.ctrlAltTabManager.removeGroup(this.actor); | ||||
|     }, | ||||
| 
 | ||||
|     _loadUserList: function() { | ||||
| @@ -1153,20 +828,6 @@ const LoginDialog = new Lang.Class({ | ||||
|                                   })); | ||||
|     }, | ||||
| 
 | ||||
|     _onOpened: function() { | ||||
|         Main.ctrlAltTabManager.addGroup(this.dialogLayout, | ||||
|                                         _("Login Window"), | ||||
|                                         'dialog-password-symbolic', | ||||
|                                         { sortGroup: CtrlAltTab.SortGroup.MIDDLE }); | ||||
| 
 | ||||
|     }, | ||||
| 
 | ||||
|     close: function() { | ||||
|         this.parent(); | ||||
| 
 | ||||
|         Main.ctrlAltTabManager.removeGroup(this.dialogLayout); | ||||
|     }, | ||||
| 
 | ||||
|     addCharacter: function(unichar) { | ||||
|         this._promptEntry.clutter_text.insert_unichar(unichar); | ||||
|     }, | ||||
| @@ -23,7 +23,7 @@ const Lang = imports.lang; | ||||
| 
 | ||||
| const LoginManager = imports.misc.loginManager; | ||||
| 
 | ||||
| const GdmUtil = imports.gdm.util; | ||||
| const AuthUtil = imports.ui.auth.util; | ||||
| const PanelMenu = imports.ui.panelMenu; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
| 
 | ||||
| @@ -37,7 +37,7 @@ const PowerMenuButton = new Lang.Class({ | ||||
| 
 | ||||
|         this._loginManager = LoginManager.getLoginManager(); | ||||
| 
 | ||||
|         this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA }); | ||||
|         this._settings = new Gio.Settings({ schema: AuthUtil.LOGIN_SCREEN_SCHEMA }); | ||||
|         this._settings.connect('changed::disable-restart-buttons', | ||||
|                                Lang.bind(this, this._updateVisibility)); | ||||
| 
 | ||||
							
								
								
									
										230
									
								
								js/ui/auth/sessionList.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								js/ui/auth/sessionList.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,230 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* | ||||
|  * Copyright 2011 Red Hat, Inc | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2, or (at your option) | ||||
|  * any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  */ | ||||
|  | ||||
| const Gtk = imports.gi.Gtk; | ||||
| const Lang = imports.lang; | ||||
| const Signals = imports.signals; | ||||
| const St = imports.gi.St; | ||||
| const Gdm = imports.gi.Gdm; | ||||
|  | ||||
| const SessionListItem = new Lang.Class({ | ||||
|     Name: 'SessionListItem', | ||||
|  | ||||
|     _init: function(id, name) { | ||||
|         this.id = id; | ||||
|  | ||||
|         this.actor = new St.Button({ style_class: 'login-dialog-session-list-item', | ||||
|                                      button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, | ||||
|                                      can_focus: true, | ||||
|                                      reactive: true, | ||||
|                                      x_fill: true, | ||||
|                                      x_align: St.Align.START }); | ||||
|  | ||||
|         this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list-item-box' }); | ||||
|  | ||||
|         this.actor.add_actor(this._box); | ||||
|         this.actor.connect('clicked', Lang.bind(this, this._onClicked)); | ||||
|  | ||||
|         this._dot = new St.DrawingArea({ style_class: 'login-dialog-session-list-item-dot' }); | ||||
|         this._dot.connect('repaint', Lang.bind(this, this._onRepaintDot)); | ||||
|         this._box.add_actor(this._dot); | ||||
|         this.setShowDot(false); | ||||
|  | ||||
|         let label = new St.Label({ style_class: 'login-dialog-session-list-item-label', | ||||
|                                    text: name }); | ||||
|         this.actor.label_actor = label; | ||||
|  | ||||
|         this._box.add_actor(label); | ||||
|     }, | ||||
|  | ||||
|     setShowDot: function(show) { | ||||
|         if (show) | ||||
|             this._dot.opacity = 255; | ||||
|         else | ||||
|             this._dot.opacity = 0; | ||||
|     }, | ||||
|  | ||||
|     _onRepaintDot: function(area) { | ||||
|         let cr = area.get_context(); | ||||
|         let [width, height] = area.get_surface_size(); | ||||
|         let color = area.get_theme_node().get_foreground_color(); | ||||
|  | ||||
|         cr.setSourceRGBA (color.red / 255, | ||||
|                           color.green / 255, | ||||
|                           color.blue / 255, | ||||
|                           color.alpha / 255); | ||||
|         cr.arc(width / 2, height / 2, width / 3, 0, 2 * Math.PI); | ||||
|         cr.fill(); | ||||
|         cr.$dispose(); | ||||
|     }, | ||||
|  | ||||
|     _onClicked: function() { | ||||
|         this.emit('activate'); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(SessionListItem.prototype); | ||||
|  | ||||
| const SessionList = new Lang.Class({ | ||||
|     Name: 'SessionList', | ||||
|  | ||||
|     _init: function() { | ||||
|         this.actor = new St.Bin(); | ||||
|  | ||||
|         this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list', | ||||
|                                        vertical: true}); | ||||
|         this.actor.child = this._box; | ||||
|  | ||||
|         this._button = new St.Button({ style_class: 'login-dialog-session-list-button', | ||||
|                                        button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, | ||||
|                                        can_focus: true, | ||||
|                                        x_fill: true, | ||||
|                                        y_fill: true }); | ||||
|         let box = new St.BoxLayout(); | ||||
|         this._button.add_actor(box); | ||||
|  | ||||
|         this._triangle = new St.Label({ style_class: 'login-dialog-session-list-triangle', | ||||
|                                         text: '\u25B8' }); | ||||
|         box.add_actor(this._triangle); | ||||
|  | ||||
|         let label = new St.Label({ style_class: 'login-dialog-session-list-label', | ||||
|                                    text: _("Session…") }); | ||||
|         box.add_actor(label); | ||||
|  | ||||
|         this._button.connect('clicked', | ||||
|                              Lang.bind(this, this._onClicked)); | ||||
|         this._box.add_actor(this._button); | ||||
|         this._scrollView = new St.ScrollView({ style_class: 'login-dialog-session-list-scroll-view'}); | ||||
|         this._scrollView.set_policy(Gtk.PolicyType.NEVER, | ||||
|                                     Gtk.PolicyType.AUTOMATIC); | ||||
|         this._box.add_actor(this._scrollView); | ||||
|         this._itemList = new St.BoxLayout({ style_class: 'login-dialog-session-item-list', | ||||
|                                             vertical: true }); | ||||
|         this._scrollView.add_actor(this._itemList); | ||||
|         this._hideSessions(); | ||||
|         this.isOpen = false; | ||||
|         this._populate(); | ||||
|     }, | ||||
|  | ||||
|     _hideSessions: function() { | ||||
|         this._itemList.can_focus = false; | ||||
|         this._itemList.reactive = false; | ||||
|         this._scrollView.opacity = 0; | ||||
|     }, | ||||
|  | ||||
|     _showSessions: function() { | ||||
|         this._scrollView.opacity = 255; | ||||
|         this._itemList.reactive = true; | ||||
|         this._itemList.can_focus = true; | ||||
|     }, | ||||
|  | ||||
|     open: function() { | ||||
|         if (this.isOpen) | ||||
|             return; | ||||
|  | ||||
|         this._button.add_style_pseudo_class('open'); | ||||
|         this._showSessions(); | ||||
|         this._triangle.set_text('\u25BE'); | ||||
|  | ||||
|         this.isOpen = true; | ||||
|     }, | ||||
|  | ||||
|     close: function() { | ||||
|         if (!this.isOpen) | ||||
|             return; | ||||
|  | ||||
|         this._button.remove_style_pseudo_class('open'); | ||||
|         this._hideSessions(); | ||||
|         this._triangle.set_text('\u25B8'); | ||||
|  | ||||
|         this.isOpen = false; | ||||
|     }, | ||||
|  | ||||
|     _onClicked: function() { | ||||
|         if (!this.isOpen) | ||||
|             this.open(); | ||||
|         else | ||||
|             this.close(); | ||||
|     }, | ||||
|  | ||||
|     updateSensitivity: function(sensitive) { | ||||
|         this._button.reactive = sensitive; | ||||
|         this._button.can_focus = sensitive; | ||||
|  | ||||
|         for (let id in this._items) | ||||
|             this._items[id].actor.reactive = sensitive; | ||||
|     }, | ||||
|  | ||||
|     setActiveSession: function(sessionId) { | ||||
|          if (sessionId == this._activeSessionId) | ||||
|              return; | ||||
|  | ||||
|          if (this._activeSessionId) | ||||
|              this._items[this._activeSessionId].setShowDot(false); | ||||
|  | ||||
|          this._items[sessionId].setShowDot(true); | ||||
|          this._activeSessionId = sessionId; | ||||
|  | ||||
|          this.emit('session-activated', this._activeSessionId); | ||||
|     }, | ||||
|  | ||||
|     _populate: function() { | ||||
|         this._itemList.destroy_all_children(); | ||||
|         this._activeSessionId = null; | ||||
|         this._items = {}; | ||||
|  | ||||
|         let ids = Gdm.get_session_ids(); | ||||
|         ids.sort(); | ||||
|  | ||||
|         if (ids.length <= 1) { | ||||
|             this._box.hide(); | ||||
|             this._button.hide(); | ||||
|         } else { | ||||
|             this._button.show(); | ||||
|             this._box.show(); | ||||
|         } | ||||
|  | ||||
|         for (let i = 0; i < ids.length; i++) { | ||||
|             let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]); | ||||
|  | ||||
|             let item = new SessionListItem(ids[i], sessionName); | ||||
|             this._itemList.add_actor(item.actor); | ||||
|             this._items[ids[i]] = item; | ||||
|  | ||||
|             if (!this._activeSessionId) | ||||
|                 this.setActiveSession(ids[i]); | ||||
|  | ||||
|             item.connect('activate', | ||||
|                          Lang.bind(this, function() { | ||||
|                              this.setActiveSession(item.id); | ||||
|                          })); | ||||
|  | ||||
|             item.actor.can_focus = this._itemList.can_focus; | ||||
|             let signalId = this._itemList.connect('notify::can-focus', | ||||
|                                                   Lang.bind(this, function() { | ||||
|                                                       item.actor.can_focus = this._itemList.can_focus; | ||||
|                                                   })); | ||||
|             item.actor.connect('destroy', | ||||
|                                Lang.bind(this, function() { | ||||
|                                    this._itemList.disconnect(signalId); | ||||
|                                })); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(SessionList.prototype); | ||||
| @@ -6,23 +6,17 @@ const Gdm  = imports.gi.Gdm; | ||||
| const Gio = imports.gi.Gio; | ||||
| const GLib = imports.gi.GLib; | ||||
| const GnomeDesktop = imports.gi.GnomeDesktop; | ||||
| const Gtk = imports.gi.Gtk; | ||||
| const Lang = imports.lang; | ||||
| const Signals = imports.signals; | ||||
| const Shell = imports.gi.Shell; | ||||
| const St = imports.gi.St; | ||||
| 
 | ||||
| const Main = imports.ui.main; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
| const Panel = imports.ui.panel; | ||||
| const ShellEntry = imports.ui.shellEntry; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const UserMenu = imports.ui.userMenu; | ||||
| const UserWidget = imports.ui.userWidget; | ||||
| 
 | ||||
| const Batch = imports.gdm.batch; | ||||
| const GdmUtil = imports.gdm.util; | ||||
| const LoginDialog = imports.gdm.loginDialog; | ||||
| const AuthUtil = imports.ui.auth.util; | ||||
| const Batch = imports.misc.batch; | ||||
| 
 | ||||
| // The timeout before going back automatically to the lock screen (in seconds)
 | ||||
| const IDLE_TIMEOUT = 2 * 60; | ||||
| @@ -46,7 +40,7 @@ const UnlockDialog = new Lang.Class({ | ||||
|         this._firstQuestion = true; | ||||
| 
 | ||||
|         this._greeterClient = new Gdm.Client(); | ||||
|         this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient, { reauthenticationOnly: true }); | ||||
|         this._userVerifier = new AuthUtil.ShellUserVerifier(this._greeterClient, { reauthenticationOnly: true }); | ||||
|         this._userVerified = false; | ||||
| 
 | ||||
|         this._userVerifier.connect('ask-question', Lang.bind(this, this._onAskQuestion)); | ||||
| @@ -163,9 +157,9 @@ const UnlockDialog = new Lang.Class({ | ||||
|         if (message) { | ||||
|             this._promptMessage.text = message; | ||||
|             this._promptMessage.styleClass = styleClass; | ||||
|             GdmUtil.fadeInActor(this._promptMessage); | ||||
|             AuthUtil.fadeInActor(this._promptMessage); | ||||
|         } else { | ||||
|             GdmUtil.fadeOutActor(this._promptMessage); | ||||
|             AuthUtil.fadeOutActor(this._promptMessage); | ||||
|         } | ||||
|     }, | ||||
| 
 | ||||
| @@ -194,11 +188,11 @@ const UnlockDialog = new Lang.Class({ | ||||
| 
 | ||||
|     _showLoginHint: function(verifier, message) { | ||||
|         this._promptLoginHint.set_text(message) | ||||
|         GdmUtil.fadeInActor(this._promptLoginHint); | ||||
|         AuthUtil.fadeInActor(this._promptLoginHint); | ||||
|     }, | ||||
| 
 | ||||
|     _hideLoginHint: function() { | ||||
|         GdmUtil.fadeOutActor(this._promptLoginHint); | ||||
|         AuthUtil.fadeOutActor(this._promptLoginHint); | ||||
|     }, | ||||
| 
 | ||||
|     _doUnlock: function() { | ||||
							
								
								
									
										251
									
								
								js/ui/auth/userList.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										251
									
								
								js/ui/auth/userList.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,251 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const AccountsService = imports.gi.AccountsService; | ||||
| const Gtk = imports.gi.Gtk; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Lang = imports.lang; | ||||
| const Signals = imports.signals; | ||||
| const St = imports.gi.St; | ||||
| const Gdm = imports.gi.Gdm; | ||||
|  | ||||
| const Batch = imports.misc.batch; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const UserAvatar = imports.ui.userAvatar; | ||||
|  | ||||
| const _SCROLL_ANIMATION_TIME = 0.5; | ||||
|  | ||||
| const UserListItem = new Lang.Class({ | ||||
|     Name: 'UserListItem', | ||||
|  | ||||
|     _init: function(user) { | ||||
|         this.user = user; | ||||
|         this._userChangedId = this.user.connect('changed', | ||||
|                                                  Lang.bind(this, this._onUserChanged)); | ||||
|  | ||||
|         let layout = new St.BoxLayout({ vertical: false }); | ||||
|         this.actor = new St.Button({ style_class: 'login-dialog-user-list-item', | ||||
|                                      button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, | ||||
|                                      can_focus: true, | ||||
|                                      child: layout, | ||||
|                                      reactive: true, | ||||
|                                      x_align: St.Align.START, | ||||
|                                      x_fill: true }); | ||||
|  | ||||
|         this._userAvatar = new UserAvatar.UserAvatar(this.user, | ||||
|                                                      { styleClass: 'login-dialog-user-list-item-icon' }); | ||||
|         layout.add(this._userAvatar.actor); | ||||
|         let textLayout = new St.BoxLayout({ style_class: 'login-dialog-user-list-item-text-box', | ||||
|                                             vertical:    true }); | ||||
|         layout.add(textLayout, { expand: true }); | ||||
|  | ||||
|         this._nameLabel = new St.Label({ style_class: 'login-dialog-user-list-item-name' }); | ||||
|         this.actor.label_actor = this._nameLabel; | ||||
|         textLayout.add(this._nameLabel, | ||||
|                        { y_fill: false, | ||||
|                          y_align: St.Align.MIDDLE, | ||||
|                          expand: true }); | ||||
|  | ||||
|         this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator', | ||||
|                                                  scale_x: 0 }); | ||||
|         textLayout.add(this._timedLoginIndicator, | ||||
|                        { x_fill: true, | ||||
|                          x_align: St.Align.MIDDLE, | ||||
|                          y_fill: false, | ||||
|                          y_align: St.Align.END }); | ||||
|  | ||||
|         this.actor.connect('clicked', Lang.bind(this, this._onClicked)); | ||||
|         this._onUserChanged(); | ||||
|     }, | ||||
|  | ||||
|     _onUserChanged: function() { | ||||
|         this._nameLabel.set_text(this.user.get_real_name()); | ||||
|         this._userAvatar.update(); | ||||
|         this._updateLoggedIn(); | ||||
|     }, | ||||
|  | ||||
|     syncStyleClasses: function() { | ||||
|         this._updateLoggedIn(); | ||||
|  | ||||
|         if (global.stage.get_key_focus() == this.actor) | ||||
|             this.actor.add_style_pseudo_class('focus'); | ||||
|         else | ||||
|             this.actor.remove_style_pseudo_class('focus'); | ||||
|     }, | ||||
|  | ||||
|     _updateLoggedIn: function() { | ||||
|         if (this.user.is_logged_in()) | ||||
|             this.actor.add_style_pseudo_class('logged-in'); | ||||
|         else | ||||
|             this.actor.remove_style_pseudo_class('logged-in'); | ||||
|     }, | ||||
|  | ||||
|     _onClicked: function() { | ||||
|         this.emit('activate'); | ||||
|     }, | ||||
|  | ||||
|     showTimedLoginIndicator: function(time) { | ||||
|         let hold = new Batch.Hold(); | ||||
|  | ||||
|         this.hideTimedLoginIndicator(); | ||||
|         Tweener.addTween(this._timedLoginIndicator, | ||||
|                          { scale_x: 1., | ||||
|                            time: time, | ||||
|                            transition: 'linear', | ||||
|                            onComplete: function() { | ||||
|                                hold.release(); | ||||
|                            }, | ||||
|                            onCompleteScope: this | ||||
|                          }); | ||||
|         return hold; | ||||
|     }, | ||||
|  | ||||
|     hideTimedLoginIndicator: function() { | ||||
|         Tweener.removeTweens(this._timedLoginIndicator); | ||||
|         this._timedLoginIndicator.scale_x = 0.; | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(UserListItem.prototype); | ||||
|  | ||||
| const UserList = new Lang.Class({ | ||||
|     Name: 'UserList', | ||||
|  | ||||
|     _init: function() { | ||||
|         this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'}); | ||||
|         this.actor.set_policy(Gtk.PolicyType.NEVER, | ||||
|                               Gtk.PolicyType.AUTOMATIC); | ||||
|  | ||||
|         this._box = new St.BoxLayout({ vertical: true, | ||||
|                                        style_class: 'login-dialog-user-list', | ||||
|                                        pseudo_class: 'expanded' }); | ||||
|  | ||||
|         this.actor.add_actor(this._box); | ||||
|         this._items = {}; | ||||
|  | ||||
|         this.actor.connect('key-focus-in', Lang.bind(this, this._moveFocusToItems)); | ||||
|     }, | ||||
|  | ||||
|     _moveFocusToItems: function() { | ||||
|         let hasItems = Object.keys(this._items).length > 0; | ||||
|  | ||||
|         if (!hasItems) | ||||
|             return; | ||||
|  | ||||
|         if (global.stage.get_key_focus() != this.actor) | ||||
|             return; | ||||
|  | ||||
|         let focusSet = this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); | ||||
|         if (!focusSet) { | ||||
|             Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { | ||||
|                 this._moveFocusToItems(); | ||||
|                 return false; | ||||
|             })); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _onItemActivated: function(activatedItem) { | ||||
|         this.emit('activate', activatedItem); | ||||
|     }, | ||||
|  | ||||
|     updateStyle: function(isExpanded) { | ||||
|         let tasks = []; | ||||
|  | ||||
|         if (isExpanded) | ||||
|             this._box.add_style_pseudo_class('expanded'); | ||||
|         else | ||||
|             this._box.remove_style_pseudo_class('expanded'); | ||||
|  | ||||
|         for (let userName in this._items) { | ||||
|             let item = this._items[userName]; | ||||
|             item.actor.sync_hover(); | ||||
|             item.syncStyleClasses(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     scrollToItem: function(item) { | ||||
|         let box = item.actor.get_allocation_box(); | ||||
|  | ||||
|         let adjustment = this.actor.get_vscroll_bar().get_adjustment(); | ||||
|  | ||||
|         let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0); | ||||
|         Tweener.removeTweens(adjustment); | ||||
|         Tweener.addTween (adjustment, | ||||
|                           { value: value, | ||||
|                             time: _SCROLL_ANIMATION_TIME, | ||||
|                             transition: 'easeOutQuad' }); | ||||
|     }, | ||||
|  | ||||
|     jumpToItem: function(item) { | ||||
|         let box = item.actor.get_allocation_box(); | ||||
|  | ||||
|         let adjustment = this.actor.get_vscroll_bar().get_adjustment(); | ||||
|  | ||||
|         let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0); | ||||
|  | ||||
|         adjustment.set_value(value); | ||||
|     }, | ||||
|  | ||||
|     getItemFromUserName: function(userName) { | ||||
|         let item = this._items[userName]; | ||||
|  | ||||
|         if (!item) | ||||
|             return null; | ||||
|  | ||||
|         return item; | ||||
|     }, | ||||
|  | ||||
|     addUser: function(user) { | ||||
|         if (!user.is_loaded) | ||||
|             return; | ||||
|  | ||||
|         if (user.is_system_account()) | ||||
|             return; | ||||
|  | ||||
|         if (user.locked) | ||||
|            return; | ||||
|  | ||||
|         let userName = user.get_user_name(); | ||||
|  | ||||
|         if (!userName) | ||||
|             return; | ||||
|  | ||||
|         this.removeUser(user); | ||||
|  | ||||
|         let item = new UserListItem(user); | ||||
|         this._box.add(item.actor, { x_fill: true }); | ||||
|  | ||||
|         this._items[userName] = item; | ||||
|  | ||||
|         item.connect('activate', | ||||
|                      Lang.bind(this, this._onItemActivated)); | ||||
|  | ||||
|         // Try to keep the focused item front-and-center | ||||
|         item.actor.connect('key-focus-in', | ||||
|                            Lang.bind(this, | ||||
|                                      function() { | ||||
|                                          this.scrollToItem(item); | ||||
|                                      })); | ||||
|  | ||||
|         this._moveFocusToItems(); | ||||
|  | ||||
|         this.emit('item-added', item); | ||||
|     }, | ||||
|  | ||||
|     removeUser: function(user) { | ||||
|         if (!user.is_loaded) | ||||
|             return; | ||||
|  | ||||
|         let userName = user.get_user_name(); | ||||
|  | ||||
|         if (!userName) | ||||
|             return; | ||||
|  | ||||
|         let item = this._items[userName]; | ||||
|  | ||||
|         if (!item) | ||||
|             return; | ||||
|  | ||||
|         item.actor.destroy(); | ||||
|         delete this._items[userName]; | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(UserList.prototype); | ||||
| @@ -7,8 +7,8 @@ const Lang = imports.lang; | ||||
| const Mainloop = imports.mainloop; | ||||
| const Signals = imports.signals; | ||||
| 
 | ||||
| const Batch = imports.gdm.batch; | ||||
| const Fprint = imports.gdm.fingerprint; | ||||
| const Batch = imports.misc.batch; | ||||
| const Fprint = imports.ui.auth.fingerprint; | ||||
| const Main = imports.ui.main; | ||||
| const Params = imports.misc.params; | ||||
| const Tweener = imports.ui.tweener; | ||||
| @@ -16,7 +16,7 @@ const PolkitAgent = imports.gi.PolkitAgent; | ||||
| const Components = imports.ui.components; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
| const ShellEntry = imports.ui.shellEntry; | ||||
| const UserMenu = imports.ui.userMenu; | ||||
| const UserAvatar = imports.ui.userAvatar; | ||||
|  | ||||
| const DIALOG_ICON_SIZE = 48; | ||||
|  | ||||
| @@ -100,9 +100,9 @@ const AuthenticationDialog = new Lang.Class({ | ||||
|             let userBox = new St.BoxLayout({ style_class: 'polkit-dialog-user-layout', | ||||
|                                              vertical: false }); | ||||
|             messageBox.add(userBox); | ||||
|             this._userAvatar = new UserMenu.UserAvatarWidget(this._user, | ||||
|                                                              { iconSize: DIALOG_ICON_SIZE, | ||||
|                                                                styleClass: 'polkit-dialog-user-icon' }); | ||||
|             this._userAvatar = new UserAvatar.UserAvatar(this._user, | ||||
|                                                          { iconSize: DIALOG_ICON_SIZE, | ||||
|                                                            styleClass: 'polkit-dialog-user-icon' }); | ||||
|             this._userAvatar.actor.hide(); | ||||
|             userBox.add(this._userAvatar.actor, | ||||
|                         { x_fill:  true, | ||||
|   | ||||
| @@ -35,7 +35,7 @@ const GnomeSession = imports.misc.gnomeSession; | ||||
| const Main = imports.ui.main; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const UserMenu = imports.ui.userMenu; | ||||
| const UserAvatar = imports.ui.userAvatar; | ||||
|  | ||||
| let _endSessionDialog = null; | ||||
|  | ||||
| @@ -360,9 +360,9 @@ const EndSessionDialog = new Lang.Class({ | ||||
|                                                 icon_size: _DIALOG_ICON_SIZE, | ||||
|                                                 style_class: dialogContent.iconStyleClass }); | ||||
|         } else { | ||||
|             let avatarWidget = new UserMenu.UserAvatarWidget(this._user, | ||||
|                                                              { iconSize: _DIALOG_ICON_SIZE, | ||||
|                                                                styleClass: dialogContent.iconStyleClass }); | ||||
|             let avatarWidget = new UserAvatar.UserAvatar(this._user, | ||||
|                                                          { iconSize: _DIALOG_ICON_SIZE, | ||||
|                                                            styleClass: dialogContent.iconStyleClass }); | ||||
|             this._iconBin.child = avatarWidget.actor; | ||||
|             avatarWidget.update(); | ||||
|         } | ||||
|   | ||||
| @@ -14,6 +14,7 @@ const Atk = imports.gi.Atk; | ||||
|  | ||||
| const Params = imports.misc.params; | ||||
|  | ||||
| const Animation = imports.ui.animation; | ||||
| const Layout = imports.ui.layout; | ||||
| const Lightbox = imports.ui.lightbox; | ||||
| const Main = imports.ui.main; | ||||
| @@ -187,10 +188,8 @@ const ModalDialog = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     placeSpinner: function(layoutInfo) { | ||||
|         /* This is here because of recursive imports */ | ||||
|         const Panel = imports.ui.panel; | ||||
|         let spinnerIcon = global.datadir + '/theme/process-working.svg'; | ||||
|         this._workSpinner = new Panel.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE); | ||||
|         this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE); | ||||
|         this._workSpinner.actor.opacity = 0; | ||||
|         this._workSpinner.actor.show(); | ||||
|  | ||||
|   | ||||
| @@ -15,6 +15,7 @@ const Signals = imports.signals; | ||||
| const Atk = imports.gi.Atk; | ||||
|  | ||||
|  | ||||
| const Animation = imports.ui.animation; | ||||
| const Config = imports.misc.config; | ||||
| const CtrlAltTab = imports.ui.ctrlAltTab; | ||||
| const DND = imports.ui.dnd; | ||||
| @@ -29,7 +30,6 @@ const PANEL_ICON_SIZE = 24; | ||||
|  | ||||
| const BUTTON_DND_ACTIVATION_TIMEOUT = 250; | ||||
|  | ||||
| const ANIMATED_ICON_UPDATE_TIMEOUT = 100; | ||||
| const SPINNER_ANIMATION_TIME = 0.2; | ||||
|  | ||||
| // To make sure the panel corners blend nicely with the panel, | ||||
| @@ -75,81 +75,6 @@ function _unpremultiply(color) { | ||||
|                                blue: blue, alpha: color.alpha }); | ||||
| }; | ||||
|  | ||||
| const Animation = new Lang.Class({ | ||||
|     Name: 'Animation', | ||||
|  | ||||
|     _init: function(filename, width, height, speed) { | ||||
|         this.actor = new St.Bin(); | ||||
|         this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | ||||
|         this._speed = speed; | ||||
|  | ||||
|         this._isLoaded = false; | ||||
|         this._isPlaying = false; | ||||
|         this._timeoutId = 0; | ||||
|         this._frame = 0; | ||||
|         this._animations = St.TextureCache.get_default().load_sliced_image (filename, width, height, | ||||
|                                                                             Lang.bind(this, this._animationsLoaded)); | ||||
|         this.actor.set_child(this._animations); | ||||
|     }, | ||||
|  | ||||
|     play: function() { | ||||
|         if (this._isLoaded && this._timeoutId == 0) { | ||||
|             if (this._frame == 0) | ||||
|                 this._showFrame(0); | ||||
|  | ||||
|             this._timeoutId = Mainloop.timeout_add(this._speed, Lang.bind(this, this._update)); | ||||
|         } | ||||
|  | ||||
|         this._isPlaying = true; | ||||
|     }, | ||||
|  | ||||
|     stop: function() { | ||||
|         if (this._timeoutId > 0) { | ||||
|             Mainloop.source_remove(this._timeoutId); | ||||
|             this._timeoutId = 0; | ||||
|         } | ||||
|  | ||||
|         this._isPlaying = false; | ||||
|     }, | ||||
|  | ||||
|     _showFrame: function(frame) { | ||||
|         let oldFrameActor = this._animations.get_child_at_index(this._frame); | ||||
|         if (oldFrameActor) | ||||
|             oldFrameActor.hide(); | ||||
|  | ||||
|         this._frame = (frame % this._animations.get_n_children()); | ||||
|  | ||||
|         let newFrameActor = this._animations.get_child_at_index(this._frame); | ||||
|         if (newFrameActor) | ||||
|             newFrameActor.show(); | ||||
|     }, | ||||
|  | ||||
|     _update: function() { | ||||
|         this._showFrame(this._frame + 1); | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     _animationsLoaded: function() { | ||||
|         this._isLoaded = true; | ||||
|  | ||||
|         if (this._isPlaying) | ||||
|             this.play(); | ||||
|     }, | ||||
|  | ||||
|     _onDestroy: function() { | ||||
|         this.stop(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const AnimatedIcon = new Lang.Class({ | ||||
|     Name: 'AnimatedIcon', | ||||
|     Extends: Animation, | ||||
|  | ||||
|     _init: function(filename, size) { | ||||
|         this.parent(filename, size, size, ANIMATED_ICON_UPDATE_TIMEOUT); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const TextShadower = new Lang.Class({ | ||||
|     Name: 'TextShadower', | ||||
|  | ||||
| @@ -360,7 +285,7 @@ const AppMenuButton = new Lang.Class({ | ||||
|         if (!success || this._spinnerIcon == icon) | ||||
|             return; | ||||
|         this._spinnerIcon = icon; | ||||
|         this._spinner = new AnimatedIcon(this._spinnerIcon, PANEL_ICON_SIZE); | ||||
|         this._spinner = new Animation.AnimatedIcon(this._spinnerIcon, PANEL_ICON_SIZE); | ||||
|         this._container.add_actor(this._spinner.actor); | ||||
|         this._spinner.actor.hide(); | ||||
|         this._spinner.actor.lower_bottom(); | ||||
| @@ -931,7 +856,7 @@ const PANEL_ITEM_IMPLEMENTATIONS = { | ||||
|     'battery': imports.ui.status.power.Indicator, | ||||
|     'lockScreen': imports.ui.status.lockScreenMenu.Indicator, | ||||
|     'keyboard': imports.ui.status.keyboard.InputSourceIndicator, | ||||
|     'powerMenu': imports.gdm.powerMenu.PowerMenuButton, | ||||
|     'powerMenu': imports.ui.auth.powerMenu.PowerMenuButton, | ||||
|     'userMenu': imports.ui.userMenu.UserMenuButton | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -42,7 +42,7 @@ const _modes = { | ||||
|         hasNotifications: true, | ||||
|         isGreeter: true, | ||||
|         isPrimary: true, | ||||
|         unlockDialog: imports.gdm.loginDialog.LoginDialog, | ||||
|         unlockDialog: imports.ui.auth.loginDialog.LoginDialog, | ||||
|         components: ['polkitAgent'], | ||||
|         panel: { | ||||
|             left: [], | ||||
| @@ -89,7 +89,7 @@ const _modes = { | ||||
|         hasNotifications: true, | ||||
|         isLocked: false, | ||||
|         isPrimary: true, | ||||
|         unlockDialog: imports.ui.unlockDialog.UnlockDialog, | ||||
|         unlockDialog: imports.ui.auth.unlockDialog.UnlockDialog, | ||||
|         components: ['networkAgent', 'polkitAgent', 'telepathyClient', | ||||
|                      'keyring', 'recorder', 'autorunManager', 'automountManager'], | ||||
|         panel: { | ||||
|   | ||||
							
								
								
									
										52
									
								
								js/ui/userAvatar.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								js/ui/userAvatar.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const Gio = imports.gi.Gio; | ||||
| const GLib = imports.gi.GLib; | ||||
| const Lang = imports.lang; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const Params = imports.misc.params; | ||||
|  | ||||
| const DIALOG_ICON_SIZE = 64; | ||||
|  | ||||
| // Adapted from gdm/gui/user-switch-applet/applet.c | ||||
| // | ||||
| // Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>. | ||||
| // Copyright (C) 2008,2009 Red Hat, Inc. | ||||
|  | ||||
| const UserAvatar = new Lang.Class({ | ||||
|     Name: 'UserAvatar', | ||||
|  | ||||
|     _init: function(user, params) { | ||||
|         this._user = user; | ||||
|         params = Params.parse(params, { reactive: false, | ||||
|                                         iconSize: DIALOG_ICON_SIZE, | ||||
|                                         styleClass: 'status-chooser-user-icon' }); | ||||
|         this._iconSize = params.iconSize; | ||||
|  | ||||
|         this.actor = new St.Bin({ style_class: params.styleClass, | ||||
|                                   track_hover: params.reactive, | ||||
|                                   reactive: params.reactive }); | ||||
|     }, | ||||
|  | ||||
|     setSensitive: function(sensitive) { | ||||
|         this.actor.can_focus = sensitive; | ||||
|         this.actor.reactive = sensitive; | ||||
|     }, | ||||
|  | ||||
|     update: function() { | ||||
|         let iconFile = this._user.get_icon_file(); | ||||
|         if (iconFile && !GLib.file_test(iconFile, GLib.FileTest.EXISTS)) | ||||
|             iconFile = null; | ||||
|  | ||||
|         if (iconFile) { | ||||
|             let file = Gio.File.new_for_path(iconFile); | ||||
|             this.actor.child = null; | ||||
|             this.actor.style = 'background-image: url("%s");'.format(iconFile); | ||||
|         } else { | ||||
|             this.actor.style = null; | ||||
|             this.actor.child = new St.Icon({ icon_name: 'avatar-default-symbolic', | ||||
|                                              icon_size: this._iconSize }); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
| @@ -21,6 +21,7 @@ const ModalDialog = imports.ui.modalDialog; | ||||
| const PanelMenu = imports.ui.panelMenu; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
| const Params = imports.misc.params; | ||||
| const UserAvatar = imports.ui.userAvatar; | ||||
| const Util = imports.misc.util; | ||||
|  | ||||
| const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown'; | ||||
| @@ -57,48 +58,6 @@ const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session | ||||
|  | ||||
| const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface); | ||||
|  | ||||
| // Adapted from gdm/gui/user-switch-applet/applet.c | ||||
| // | ||||
| // Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>. | ||||
| // Copyright (C) 2008,2009 Red Hat, Inc. | ||||
|  | ||||
| const UserAvatarWidget = new Lang.Class({ | ||||
|     Name: 'UserAvatarWidget', | ||||
|  | ||||
|     _init: function(user, params) { | ||||
|         this._user = user; | ||||
|         params = Params.parse(params, { reactive: false, | ||||
|                                         iconSize: DIALOG_ICON_SIZE, | ||||
|                                         styleClass: 'status-chooser-user-icon' }); | ||||
|         this._iconSize = params.iconSize; | ||||
|  | ||||
|         this.actor = new St.Bin({ style_class: params.styleClass, | ||||
|                                   track_hover: params.reactive, | ||||
|                                   reactive: params.reactive }); | ||||
|     }, | ||||
|  | ||||
|     setSensitive: function(sensitive) { | ||||
|         this.actor.can_focus = sensitive; | ||||
|         this.actor.reactive = sensitive; | ||||
|     }, | ||||
|  | ||||
|     update: function() { | ||||
|         let iconFile = this._user.get_icon_file(); | ||||
|         if (iconFile && !GLib.file_test(iconFile, GLib.FileTest.EXISTS)) | ||||
|             iconFile = null; | ||||
|  | ||||
|         if (iconFile) { | ||||
|             let file = Gio.File.new_for_path(iconFile); | ||||
|             this.actor.child = null; | ||||
|             this.actor.style = 'background-image: url("%s");'.format(iconFile); | ||||
|         } else { | ||||
|             this.actor.style = null; | ||||
|             this.actor.child = new St.Icon({ icon_name: 'avatar-default-symbolic', | ||||
|                                              icon_size: this._iconSize }); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const IMStatusItem = new Lang.Class({ | ||||
|     Name: 'IMStatusItem', | ||||
|     Extends: PopupMenu.PopupBaseMenuItem, | ||||
| @@ -170,7 +129,7 @@ const IMStatusChooserItem = new Lang.Class({ | ||||
|         this._userManager = AccountsService.UserManager.get_default(); | ||||
|         this._user = this._userManager.get_user(GLib.get_user_name()); | ||||
|  | ||||
|         this._avatar = new UserAvatarWidget(this._user, { reactive: true }); | ||||
|         this._avatar = new UserAvatar.UserAvatar(this._user, { reactive: true }); | ||||
|         this._iconBin = new St.Button({ child: this._avatar.actor }); | ||||
|         this.addActor(this._iconBin); | ||||
|  | ||||
| @@ -908,7 +867,7 @@ const UserMenuButton = new Lang.Class({ | ||||
|             let session = sessions[i]; | ||||
|             let userEntry = new St.BoxLayout({ style_class: 'login-dialog-user-list-item', | ||||
|                                                vertical: false }); | ||||
|             let avatar = new UserAvatarWidget(session.user); | ||||
|             let avatar = new UserAvatar.UserAvatar(session.user); | ||||
|             avatar.update(); | ||||
|             userEntry.add(avatar.actor); | ||||
|  | ||||
|   | ||||
| @@ -6,7 +6,7 @@ const AccountsService = imports.gi.AccountsService; | ||||
| const Lang = imports.lang; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const UserMenu = imports.ui.userMenu; | ||||
| const UserAvatar = imports.ui.userAvatar; | ||||
|  | ||||
| const UserWidget = new Lang.Class({ | ||||
|     Name: 'UserWidget', | ||||
| @@ -18,7 +18,7 @@ const UserWidget = new Lang.Class({ | ||||
|                                         vertical: false }); | ||||
|         this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | ||||
|  | ||||
|         this._avatar = new UserMenu.UserAvatarWidget(user); | ||||
|         this._avatar = new UserAvatar.UserAvatar(user); | ||||
|         this.actor.add(this._avatar.actor, | ||||
|                        { x_fill: true, y_fill: true }); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user