.gitlab
.gitlab-ci
.settings
data
docs
js
dbusServices
extensionPrefs
gdm
misc
perf
portalHelper
ui
components
__init__.js
automountManager.js
autorunManager.js
keyring.js
networkAgent.js
polkitAgent.js
telepathyClient.js
status
accessDialog.js
altTab.js
animation.js
appDisplay.js
appFavorites.js
audioDeviceSelection.js
background.js
backgroundMenu.js
barLevel.js
boxpointer.js
calendar.js
checkBox.js
closeDialog.js
ctrlAltTab.js
dash.js
dateMenu.js
dialog.js
dnd.js
edgeDragAction.js
endSessionDialog.js
environment.js
extensionDownloader.js
extensionSystem.js
focusCaretTracker.js
grabHelper.js
ibusCandidatePopup.js
iconGrid.js
inhibitShortcutsDialog.js
kbdA11yDialog.js
keyboard.js
layout.js
lightbox.js
locatePointer.js
lookingGlass.js
magnifier.js
magnifierDBus.js
main.js
messageList.js
messageTray.js
modalDialog.js
mpris.js
notificationDaemon.js
osdMonitorLabeler.js
osdWindow.js
overview.js
overviewControls.js
padOsd.js
pageIndicators.js
panel.js
panelMenu.js
pointerA11yTimeout.js
pointerWatcher.js
popupMenu.js
remoteSearch.js
ripples.js
runDialog.js
screenShield.js
screencast.js
screenshot.js
scripting.js
search.js
sessionMode.js
shellDBus.js
shellEntry.js
shellMountOperation.js
slider.js
swipeTracker.js
switchMonitor.js
switcherPopup.js
tweener.js
unlockDialog.js
userWidget.js
viewSelector.js
windowAttentionHandler.js
windowManager.js
windowMenu.js
workspace.js
workspaceSwitcherPopup.js
workspaceThumbnail.js
workspacesView.js
xdndHandler.js
js-resources.gresource.xml
meson.build
portal-resources.gresource.xml
prefs-resources.gresource.xml
lint
man
meson
po
src
subprojects
test
tests
tools
.eslintrc.yml
.gitignore
.gitlab-ci.yml
.gitmodules
COPYING
HACKING.md
NEWS
README.md
README.mdwn
cldr2json.py
config.h.meson
gnome-shell.doap
meson.build
meson_options.txt

If all password entries in dialogs are hidden, there is either an entry that has visible characters or no entry at all. That means we don't have to show the caps lock warning at all, so hide it. https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/942
234 lines
8.0 KiB
JavaScript
234 lines
8.0 KiB
JavaScript
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
/* exported Component */
|
|
|
|
const { Clutter, Gcr, Gio, GObject, Pango, Shell, St } = imports.gi;
|
|
|
|
const Dialog = imports.ui.dialog;
|
|
const ModalDialog = imports.ui.modalDialog;
|
|
const ShellEntry = imports.ui.shellEntry;
|
|
const CheckBox = imports.ui.checkBox;
|
|
const Util = imports.misc.util;
|
|
|
|
var KeyringDialog = GObject.registerClass(
|
|
class KeyringDialog extends ModalDialog.ModalDialog {
|
|
_init() {
|
|
super._init({ styleClass: 'prompt-dialog' });
|
|
|
|
this.prompt = new Shell.KeyringPrompt();
|
|
this.prompt.connect('show-password', this._onShowPassword.bind(this));
|
|
this.prompt.connect('show-confirm', this._onShowConfirm.bind(this));
|
|
this.prompt.connect('prompt-close', this._onHidePrompt.bind(this));
|
|
|
|
let content = new Dialog.MessageDialogContent();
|
|
|
|
this.prompt.bind_property('message',
|
|
content, 'title', GObject.BindingFlags.SYNC_CREATE);
|
|
this.prompt.bind_property('description',
|
|
content, 'description', GObject.BindingFlags.SYNC_CREATE);
|
|
|
|
let passwordBox = new St.BoxLayout({
|
|
style_class: 'prompt-dialog-password-layout',
|
|
vertical: true,
|
|
});
|
|
|
|
this._passwordEntry = new St.PasswordEntry({
|
|
style_class: 'prompt-dialog-password-entry',
|
|
can_focus: true,
|
|
x_align: Clutter.ActorAlign.CENTER,
|
|
});
|
|
ShellEntry.addContextMenu(this._passwordEntry);
|
|
this._passwordEntry.clutter_text.connect('activate', this._onPasswordActivate.bind(this));
|
|
this.prompt.bind_property('password-visible',
|
|
this._passwordEntry, 'visible', GObject.BindingFlags.SYNC_CREATE);
|
|
passwordBox.add_child(this._passwordEntry);
|
|
|
|
this._confirmEntry = new St.PasswordEntry({
|
|
style_class: 'prompt-dialog-password-entry',
|
|
can_focus: true,
|
|
x_align: Clutter.ActorAlign.CENTER,
|
|
});
|
|
ShellEntry.addContextMenu(this._confirmEntry);
|
|
this._confirmEntry.clutter_text.connect('activate', this._onConfirmActivate.bind(this));
|
|
this.prompt.bind_property('confirm-visible',
|
|
this._confirmEntry, 'visible', GObject.BindingFlags.SYNC_CREATE);
|
|
passwordBox.add_child(this._confirmEntry);
|
|
|
|
this.prompt.set_password_actor(this._passwordEntry.clutter_text);
|
|
this.prompt.set_confirm_actor(this._confirmEntry.clutter_text);
|
|
|
|
let warningBox = new St.BoxLayout({ vertical: true });
|
|
|
|
let capsLockWarning = new ShellEntry.CapsLockWarning();
|
|
let syncCapsLockWarningVisibility = () => {
|
|
capsLockWarning.visible =
|
|
this.prompt.password_visible || this.prompt.confirm_visible;
|
|
};
|
|
this.prompt.connect('notify::password-visible', syncCapsLockWarningVisibility);
|
|
this.prompt.connect('notify::confirm-visible', syncCapsLockWarningVisibility);
|
|
warningBox.add_child(capsLockWarning);
|
|
|
|
let warning = new St.Label({ style_class: 'prompt-dialog-error-label' });
|
|
warning.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
|
warning.clutter_text.line_wrap = true;
|
|
this.prompt.bind_property('warning',
|
|
warning, 'text', GObject.BindingFlags.SYNC_CREATE);
|
|
this.prompt.connect('notify::warning-visible', () => {
|
|
warning.opacity = this.prompt.warning_visible ? 255 : 0;
|
|
});
|
|
this.prompt.connect('notify::warning', () => {
|
|
if (this._passwordEntry && warning !== '')
|
|
Util.wiggle(this._passwordEntry);
|
|
});
|
|
warningBox.add_child(warning);
|
|
|
|
passwordBox.add_child(warningBox);
|
|
content.add_child(passwordBox);
|
|
|
|
this._choice = new CheckBox.CheckBox();
|
|
this.prompt.bind_property('choice-label', this._choice.getLabelActor(),
|
|
'text', GObject.BindingFlags.SYNC_CREATE);
|
|
this.prompt.bind_property('choice-chosen', this._choice,
|
|
'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL);
|
|
this.prompt.bind_property('choice-visible', this._choice,
|
|
'visible', GObject.BindingFlags.SYNC_CREATE);
|
|
content.add_child(this._choice);
|
|
|
|
this.contentLayout.add_child(content);
|
|
|
|
this._cancelButton = this.addButton({
|
|
label: '',
|
|
action: this._onCancelButton.bind(this),
|
|
key: Clutter.KEY_Escape,
|
|
});
|
|
this._continueButton = this.addButton({
|
|
label: '',
|
|
action: this._onContinueButton.bind(this),
|
|
default: true,
|
|
});
|
|
|
|
this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE);
|
|
this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE);
|
|
}
|
|
|
|
_updateSensitivity(sensitive) {
|
|
if (this._passwordEntry) {
|
|
this._passwordEntry.reactive = sensitive;
|
|
this._passwordEntry.clutter_text.editable = sensitive;
|
|
}
|
|
|
|
if (this._confirmEntry) {
|
|
this._confirmEntry.reactive = sensitive;
|
|
this._confirmEntry.clutter_text.editable = sensitive;
|
|
}
|
|
|
|
this._continueButton.can_focus = sensitive;
|
|
this._continueButton.reactive = sensitive;
|
|
}
|
|
|
|
_ensureOpen() {
|
|
// NOTE: ModalDialog.open() is safe to call if the dialog is
|
|
// already open - it just returns true without side-effects
|
|
if (this.open())
|
|
return true;
|
|
|
|
// The above fail if e.g. unable to get input grab
|
|
//
|
|
// In an ideal world this wouldn't happen (because the
|
|
// Shell is in complete control of the session) but that's
|
|
// just not how things work right now.
|
|
|
|
log('keyringPrompt: Failed to show modal dialog.' +
|
|
' Dismissing prompt request');
|
|
this.prompt.cancel();
|
|
return false;
|
|
}
|
|
|
|
_onShowPassword() {
|
|
this._ensureOpen();
|
|
this._updateSensitivity(true);
|
|
this._passwordEntry.text = '';
|
|
this._passwordEntry.grab_key_focus();
|
|
}
|
|
|
|
_onShowConfirm() {
|
|
this._ensureOpen();
|
|
this._updateSensitivity(true);
|
|
this._confirmEntry.text = '';
|
|
this._continueButton.grab_key_focus();
|
|
}
|
|
|
|
_onHidePrompt() {
|
|
this.close();
|
|
}
|
|
|
|
_onPasswordActivate() {
|
|
if (this.prompt.confirm_visible)
|
|
this._confirmEntry.grab_key_focus();
|
|
else
|
|
this._onContinueButton();
|
|
}
|
|
|
|
_onConfirmActivate() {
|
|
this._onContinueButton();
|
|
}
|
|
|
|
_onContinueButton() {
|
|
this._updateSensitivity(false);
|
|
this.prompt.complete();
|
|
}
|
|
|
|
_onCancelButton() {
|
|
this.prompt.cancel();
|
|
}
|
|
});
|
|
|
|
var KeyringDummyDialog = class {
|
|
constructor() {
|
|
this.prompt = new Shell.KeyringPrompt();
|
|
this.prompt.connect('show-password', this._cancelPrompt.bind(this));
|
|
this.prompt.connect('show-confirm', this._cancelPrompt.bind(this));
|
|
}
|
|
|
|
_cancelPrompt() {
|
|
this.prompt.cancel();
|
|
}
|
|
};
|
|
|
|
var KeyringPrompter = GObject.registerClass(
|
|
class KeyringPrompter extends Gcr.SystemPrompter {
|
|
_init() {
|
|
super._init();
|
|
this.connect('new-prompt', () => {
|
|
let dialog = this._enabled
|
|
? new KeyringDialog()
|
|
: new KeyringDummyDialog();
|
|
this._currentPrompt = dialog.prompt;
|
|
return this._currentPrompt;
|
|
});
|
|
this._dbusId = null;
|
|
this._registered = false;
|
|
this._enabled = false;
|
|
this._currentPrompt = null;
|
|
}
|
|
|
|
enable() {
|
|
if (!this._registered) {
|
|
this.register(Gio.DBus.session);
|
|
this._dbusId = Gio.DBus.session.own_name('org.gnome.keyring.SystemPrompter',
|
|
Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT, null, null);
|
|
this._registered = true;
|
|
}
|
|
this._enabled = true;
|
|
}
|
|
|
|
disable() {
|
|
this._enabled = false;
|
|
|
|
if (this.prompting)
|
|
this._currentPrompt.cancel();
|
|
this._currentPrompt = null;
|
|
}
|
|
});
|
|
|
|
var Component = KeyringPrompter;
|