Compare commits
	
		
			2 Commits
		
	
	
		
			benzea/sys
			...
			wip/rstrod
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 9f925cf78d | ||
|   | 1fcb59104d | 
							
								
								
									
										190
									
								
								js/gdm/authList.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								js/gdm/authList.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,190 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* | ||||
|  * Copyright 2017 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, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const GObject = imports.gi.GObject; | ||||
| const Gtk = imports.gi.Gtk; | ||||
| const Lang = imports.lang; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Signals = imports.signals; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const Tweener = imports.ui.tweener; | ||||
|  | ||||
| const _SCROLL_ANIMATION_TIME = 0.5; | ||||
|  | ||||
| const AuthListItem = new Lang.Class({ | ||||
|     Name: 'AuthListItem', | ||||
|  | ||||
|     _init: function(key, text) { | ||||
|         this.key = key; | ||||
|         let label = new St.Label({ style_class: 'auth-list-item-label', | ||||
|                                    y_align: Clutter.ActorAlign.CENTER }); | ||||
|         label.text = text; | ||||
|  | ||||
|         this.actor = new St.Button({ style_class: 'login-dialog-user-list-item', | ||||
|                                      button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, | ||||
|                                      can_focus: true, | ||||
|                                      child: label, | ||||
|                                      reactive: true, | ||||
|                                      x_align: St.Align.START, | ||||
|                                      x_fill: true }); | ||||
|  | ||||
|         this.actor.connect('key-focus-in', () => { | ||||
|             this._setSelected(true); | ||||
|         }); | ||||
|         this.actor.connect('key-focus-out', () => { | ||||
|             this._setSelected(false); | ||||
|         }); | ||||
|         this.actor.connect('notify::hover', () => { | ||||
|             this._setSelected(this.actor.hover); | ||||
|         }); | ||||
|  | ||||
|         this.actor.connect('clicked', Lang.bind(this, this._onClicked)); | ||||
|     }, | ||||
|  | ||||
|     _onClicked: function() { | ||||
|         this.emit('activate'); | ||||
|     }, | ||||
|  | ||||
|     _setSelected: function(selected) { | ||||
|         if (selected) { | ||||
|             this.actor.add_style_pseudo_class('selected'); | ||||
|             this.actor.grab_key_focus(); | ||||
|         } else { | ||||
|             this.actor.remove_style_pseudo_class('selected'); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(AuthListItem.prototype); | ||||
|  | ||||
| const AuthList = new Lang.Class({ | ||||
|     Name: 'AuthList', | ||||
|  | ||||
|     _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.key); | ||||
|     }, | ||||
|  | ||||
|     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); | ||||
|     }, | ||||
|  | ||||
|     getItem: function(key) { | ||||
|         let item = this._items[key]; | ||||
|  | ||||
|         if (!item) | ||||
|             return null; | ||||
|  | ||||
|         return item; | ||||
|     }, | ||||
|  | ||||
|     addItem: function(key, text) { | ||||
|         this.removeItem(key); | ||||
|  | ||||
|         let item = new AuthListItem(key, text); | ||||
|         this._box.add(item.actor, { x_fill: true }); | ||||
|  | ||||
|         this._items[key] = 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); | ||||
|     }, | ||||
|  | ||||
|     removeItem: function(key) { | ||||
|         let item = this._items[key]; | ||||
|  | ||||
|         if (!item) | ||||
|             return; | ||||
|  | ||||
|         item.actor.destroy(); | ||||
|         delete this._items[key]; | ||||
|     }, | ||||
|  | ||||
|     numItems: function() { | ||||
|         return Object.keys(this._items).length; | ||||
|     }, | ||||
|  | ||||
|     clear: function() { | ||||
|         this._box.destroy_all_children(); | ||||
|         this._items = {}; | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(AuthList.prototype); | ||||
| @@ -8,6 +8,7 @@ const Signals = imports.signals; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const Animation = imports.ui.animation; | ||||
| const AuthList = imports.gdm.authList; | ||||
| const Batch = imports.gdm.batch; | ||||
| const GdmUtil = imports.gdm.util; | ||||
| const Params = imports.misc.params; | ||||
| @@ -57,6 +58,7 @@ var AuthPrompt = new Lang.Class({ | ||||
|  | ||||
|         this._userVerifier.connect('ask-question', Lang.bind(this, this._onAskQuestion)); | ||||
|         this._userVerifier.connect('show-message', Lang.bind(this, this._onShowMessage)); | ||||
|         this._userVerifier.connect('show-choice-list', Lang.bind(this, this._onShowChoiceList)); | ||||
|         this._userVerifier.connect('verification-failed', Lang.bind(this, this._onVerificationFailed)); | ||||
|         this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete)); | ||||
|         this._userVerifier.connect('reset', Lang.bind(this, this._onReset)); | ||||
| @@ -117,6 +119,17 @@ var AuthPrompt = new Lang.Class({ | ||||
|         this._message.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; | ||||
|         this.actor.add(this._message, { x_fill: false, x_align: St.Align.START, y_align: St.Align.START }); | ||||
|  | ||||
|         this._authList = new AuthList.AuthList(); | ||||
|         this._authList.connect('activate', (list, key) => { | ||||
|             this._userVerifier.selectChoice(this._queryingService, key); | ||||
|         }); | ||||
|         this._authList.actor.hide(); | ||||
|         this.actor.add(this._authList.actor, | ||||
|                        { expand: true, | ||||
|                          x_fill: true, | ||||
|                          y_fill: false, | ||||
|                          x_align: St.Align.START }); | ||||
|  | ||||
|         this._buttonBox = new St.BoxLayout({ style_class: 'login-dialog-button-box', | ||||
|                                              vertical: false }); | ||||
|         this.actor.add(this._buttonBox, | ||||
| @@ -222,6 +235,21 @@ var AuthPrompt = new Lang.Class({ | ||||
|         this.emit('prompted'); | ||||
|     }, | ||||
|  | ||||
|     _onShowChoiceList: function(userVerifier, serviceName, choiceList) { | ||||
|         if (this._queryingService) | ||||
|             this.clear(); | ||||
|  | ||||
|         this._queryingService = serviceName; | ||||
|  | ||||
|         if (this._preemptiveAnswer) | ||||
|             this._preemptiveAnswer = null; | ||||
|  | ||||
|         this.nextButton.label = _("Next"); | ||||
|         this.setChoiceList(choiceList); | ||||
|         this.updateSensitivity(true); | ||||
|         this.emit('prompted'); | ||||
|     }, | ||||
|  | ||||
|     _onOVirtUserAuthenticated: function() { | ||||
|         if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED) | ||||
|             this.reset(); | ||||
| @@ -350,6 +378,8 @@ var AuthPrompt = new Lang.Class({ | ||||
|     clear: function() { | ||||
|         this._entry.text = ''; | ||||
|         this.stopSpinning(); | ||||
|         this._authList.clear(); | ||||
|         this._authList.actor.hide(); | ||||
|     }, | ||||
|  | ||||
|     setPasswordChar: function(passwordChar) { | ||||
| @@ -360,12 +390,25 @@ var AuthPrompt = new Lang.Class({ | ||||
|     setQuestion: function(question) { | ||||
|         this._label.set_text(question); | ||||
|  | ||||
|         this._authList.actor.hide(); | ||||
|         this._label.show(); | ||||
|         this._entry.show(); | ||||
|  | ||||
|         this._entry.grab_key_focus(); | ||||
|     }, | ||||
|  | ||||
|     setChoiceList: function(choiceList) { | ||||
|         this._label.hide(); | ||||
|         this._entry.hide(); | ||||
|  | ||||
|         this._authList.clear(); | ||||
|         for (let key in choiceList) { | ||||
|             let text = choiceList[key]; | ||||
|             this._authList.addItem(key, text); | ||||
|         } | ||||
|         this._authList.actor.show(); | ||||
|     }, | ||||
|  | ||||
|     getAnswer: function() { | ||||
|         let text; | ||||
|  | ||||
| @@ -416,7 +459,7 @@ var AuthPrompt = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     updateSensitivity: function(sensitive) { | ||||
|         this._updateNextButtonSensitivity(sensitive && (this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING)); | ||||
|         this._updateNextButtonSensitivity(sensitive && !this._authList.actor.visible && (this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING)); | ||||
|         this._entry.reactive = sensitive; | ||||
|         this._entry.clutter_text.editable = sensitive; | ||||
|     }, | ||||
|   | ||||
| @@ -418,6 +418,11 @@ var LoginDialog = new Lang.Class({ | ||||
|         this._userManager = AccountsService.UserManager.get_default() | ||||
|         this._gdmClient = new Gdm.Client(); | ||||
|  | ||||
|         try { | ||||
|             this._gdmClient.set_enabled_extensions([Gdm.UserVerifierChoiceList.interface_info().name]); | ||||
|         } catch(e) { | ||||
|         } | ||||
|  | ||||
|         this._settings = new Gio.Settings({ schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA }); | ||||
|  | ||||
|         this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY, | ||||
|   | ||||
| @@ -199,6 +199,8 @@ var ShellUserVerifier = new Lang.Class({ | ||||
|         if (this._userVerifier) { | ||||
|             this._userVerifier.run_dispose(); | ||||
|             this._userVerifier = null; | ||||
|             this._userVerifierChoiceList.run_dispose(); | ||||
|             this._userVerifierChoiceList = null; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -226,6 +228,10 @@ var ShellUserVerifier = new Lang.Class({ | ||||
|         this._oVirtCredentialsManager = null; | ||||
|     }, | ||||
|  | ||||
|     selectChoice: function(serviceName, key) { | ||||
|         this._userVerifierChoiceList.call_select_choice(serviceName, key, this._cancellable, null); | ||||
|     }, | ||||
|  | ||||
|     answerQuery: function(serviceName, answer) { | ||||
|         if (!this.hasPendingMessages) { | ||||
|             this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null); | ||||
| @@ -365,6 +371,8 @@ var ShellUserVerifier = new Lang.Class({ | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this._userVerifierChoiceList = client.get_user_verifier_choice_list(); | ||||
|  | ||||
|         this.reauthenticating = true; | ||||
|         this._connectSignals(); | ||||
|         this._beginVerification(); | ||||
| @@ -382,6 +390,8 @@ var ShellUserVerifier = new Lang.Class({ | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this._userVerifierChoiceList = client.get_user_verifier_choice_list(); | ||||
|  | ||||
|         this._connectSignals(); | ||||
|         this._beginVerification(); | ||||
|         this._hold.release(); | ||||
| @@ -395,6 +405,9 @@ var ShellUserVerifier = new Lang.Class({ | ||||
|         this._userVerifier.connect('conversation-stopped', Lang.bind(this, this._onConversationStopped)); | ||||
|         this._userVerifier.connect('reset', Lang.bind(this, this._onReset)); | ||||
|         this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete)); | ||||
|  | ||||
|         if (this._userVerifierChoiceList) | ||||
|             this._userVerifierChoiceList.connect('choice-query', Lang.bind(this, this._onChoiceListQuery)); | ||||
|     }, | ||||
|  | ||||
|     _getForegroundService: function() { | ||||
| @@ -464,6 +477,13 @@ var ShellUserVerifier = new Lang.Class({ | ||||
|             this._startService(FINGERPRINT_SERVICE_NAME); | ||||
|     }, | ||||
|  | ||||
|     _onChoiceListQuery: function(client, serviceName, list) { | ||||
|         if (!this.serviceIsForeground(serviceName)) | ||||
|             return; | ||||
|  | ||||
|         this.emit('show-choice-list', serviceName, list.deep_unpack()); | ||||
|     }, | ||||
|  | ||||
|     _onInfo: function(client, serviceName, info) { | ||||
|         if (this.serviceIsForeground(serviceName)) { | ||||
|             this._queueMessage(info, MessageType.INFO); | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <gresources> | ||||
|   <gresource prefix="/org/gnome/shell"> | ||||
|     <file>gdm/authList.js</file> | ||||
|     <file>gdm/authPrompt.js</file> | ||||
|     <file>gdm/batch.js</file> | ||||
|     <file>gdm/fingerprint.js</file> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user