2013-02-18 20:55:30 +00:00
|
|
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
2019-12-13 08:06:14 +00:00
|
|
|
/* exported addContextMenu CapsLockWarning */
|
2013-02-18 20:55:30 +00:00
|
|
|
|
2019-12-13 08:06:14 +00:00
|
|
|
const { Clutter, GObject, Pango, Shell, St } = imports.gi;
|
2011-09-14 16:47:09 +00:00
|
|
|
|
2013-02-18 20:55:44 +00:00
|
|
|
const BoxPointer = imports.ui.boxpointer;
|
2011-09-14 16:47:09 +00:00
|
|
|
const Main = imports.ui.main;
|
|
|
|
const Params = imports.misc.params;
|
|
|
|
const PopupMenu = imports.ui.popupMenu;
|
|
|
|
|
2017-10-31 01:19:44 +00:00
|
|
|
var EntryMenu = class extends PopupMenu.PopupMenu {
|
|
|
|
constructor(entry) {
|
|
|
|
super(entry, 0, St.Side.TOP);
|
2011-09-14 16:47:09 +00:00
|
|
|
|
|
|
|
this._entry = entry;
|
|
|
|
this._clipboard = St.Clipboard.get_default();
|
|
|
|
|
|
|
|
// Populate menu
|
|
|
|
let item;
|
|
|
|
item = new PopupMenu.PopupMenuItem(_("Copy"));
|
2017-12-02 00:27:35 +00:00
|
|
|
item.connect('activate', this._onCopyActivated.bind(this));
|
2011-09-14 16:47:09 +00:00
|
|
|
this.addMenuItem(item);
|
|
|
|
this._copyItem = item;
|
|
|
|
|
|
|
|
item = new PopupMenu.PopupMenuItem(_("Paste"));
|
2017-12-02 00:27:35 +00:00
|
|
|
item.connect('activate', this._onPasteActivated.bind(this));
|
2011-09-14 16:47:09 +00:00
|
|
|
this.addMenuItem(item);
|
|
|
|
this._pasteItem = item;
|
|
|
|
|
2019-12-12 09:08:42 +00:00
|
|
|
if (entry instanceof St.PasswordEntry)
|
|
|
|
this._makePasswordItem();
|
2011-09-14 16:47:09 +00:00
|
|
|
|
|
|
|
Main.uiGroup.add_actor(this.actor);
|
|
|
|
this.actor.hide();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-09-14 16:47:09 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_makePasswordItem() {
|
2012-05-27 17:06:08 +00:00
|
|
|
let item = new PopupMenu.PopupMenuItem('');
|
2017-12-02 00:27:35 +00:00
|
|
|
item.connect('activate', this._onPasswordActivated.bind(this));
|
2012-05-27 17:06:08 +00:00
|
|
|
this.addMenuItem(item);
|
|
|
|
this._passwordItem = item;
|
2021-07-21 18:01:48 +00:00
|
|
|
|
|
|
|
this._entry.bind_property('show-peek-icon',
|
|
|
|
this._passwordItem, 'visible',
|
|
|
|
GObject.BindingFlags.SYNC_CREATE);
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2012-05-27 17:06:08 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
open(animate) {
|
2011-09-14 16:47:09 +00:00
|
|
|
this._updatePasteItem();
|
|
|
|
this._updateCopyItem();
|
|
|
|
if (this._passwordItem)
|
|
|
|
this._updatePasswordItem();
|
|
|
|
|
2017-10-31 01:19:44 +00:00
|
|
|
super.open(animate);
|
2013-02-18 21:06:53 +00:00
|
|
|
this._entry.add_style_pseudo_class('focus');
|
|
|
|
|
2018-11-27 12:58:25 +00:00
|
|
|
let direction = St.DirectionType.TAB_FORWARD;
|
2011-09-14 16:47:09 +00:00
|
|
|
if (!this.actor.navigate_focus(null, direction, false))
|
|
|
|
this.actor.grab_key_focus();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2012-09-06 19:35:54 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_updateCopyItem() {
|
2011-09-14 16:47:09 +00:00
|
|
|
let selection = this._entry.clutter_text.get_selection();
|
2013-03-04 15:22:16 +00:00
|
|
|
this._copyItem.setSensitive(!this._entry.clutter_text.password_char &&
|
|
|
|
selection && selection != '');
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-09-14 16:47:09 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_updatePasteItem() {
|
2017-10-31 00:38:18 +00:00
|
|
|
this._clipboard.get_text(St.ClipboardType.CLIPBOARD,
|
|
|
|
(clipboard, text) => {
|
2011-09-14 16:47:09 +00:00
|
|
|
this._pasteItem.setSensitive(text && text != '');
|
2017-10-31 00:38:18 +00:00
|
|
|
});
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-09-14 16:47:09 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_updatePasswordItem() {
|
2019-12-12 09:08:42 +00:00
|
|
|
if (!this._entry.password_visible)
|
2011-09-14 16:47:09 +00:00
|
|
|
this._passwordItem.label.set_text(_("Show Text"));
|
|
|
|
else
|
|
|
|
this._passwordItem.label.set_text(_("Hide Text"));
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-09-14 16:47:09 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onCopyActivated() {
|
2011-09-14 16:47:09 +00:00
|
|
|
let selection = this._entry.clutter_text.get_selection();
|
2011-11-09 16:19:47 +00:00
|
|
|
this._clipboard.set_text(St.ClipboardType.CLIPBOARD, selection);
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-09-14 16:47:09 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onPasteActivated() {
|
2017-10-31 00:38:18 +00:00
|
|
|
this._clipboard.get_text(St.ClipboardType.CLIPBOARD,
|
|
|
|
(clipboard, text) => {
|
2011-09-14 16:47:09 +00:00
|
|
|
if (!text)
|
|
|
|
return;
|
|
|
|
this._entry.clutter_text.delete_selection();
|
|
|
|
let pos = this._entry.clutter_text.get_cursor_position();
|
|
|
|
this._entry.clutter_text.insert_text(text, pos);
|
2017-10-31 00:38:18 +00:00
|
|
|
});
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2011-09-14 16:47:09 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onPasswordActivated() {
|
2019-12-12 09:08:42 +00:00
|
|
|
this._entry.password_visible = !this._entry.password_visible;
|
2011-09-14 16:47:09 +00:00
|
|
|
}
|
2017-10-31 01:19:44 +00:00
|
|
|
};
|
2011-09-14 16:47:09 +00:00
|
|
|
|
|
|
|
function _setMenuAlignment(entry, stageX) {
|
2019-02-01 13:41:55 +00:00
|
|
|
let [success, entryX] = entry.transform_stage_point(stageX, 0);
|
2011-09-14 16:47:09 +00:00
|
|
|
if (success)
|
2012-05-27 17:06:08 +00:00
|
|
|
entry.menu.setSourceAlignment(entryX / entry.width);
|
2019-01-29 01:18:52 +00:00
|
|
|
}
|
2011-09-14 16:47:09 +00:00
|
|
|
|
2012-09-06 19:14:32 +00:00
|
|
|
function _onButtonPressEvent(actor, event, entry) {
|
2012-05-27 17:06:08 +00:00
|
|
|
if (entry.menu.isOpen) {
|
2013-02-18 20:55:44 +00:00
|
|
|
entry.menu.close(BoxPointer.PopupAnimation.FULL);
|
2013-11-29 18:17:34 +00:00
|
|
|
return Clutter.EVENT_STOP;
|
2012-09-06 19:14:32 +00:00
|
|
|
} else if (event.get_button() == 3) {
|
2019-02-01 13:41:55 +00:00
|
|
|
let [stageX] = event.get_coords();
|
2011-09-14 16:47:09 +00:00
|
|
|
_setMenuAlignment(entry, stageX);
|
2013-02-18 20:55:44 +00:00
|
|
|
entry.menu.open(BoxPointer.PopupAnimation.FULL);
|
2013-11-29 18:17:34 +00:00
|
|
|
return Clutter.EVENT_STOP;
|
2011-09-14 16:47:09 +00:00
|
|
|
}
|
2013-11-29 18:17:34 +00:00
|
|
|
return Clutter.EVENT_PROPAGATE;
|
2019-01-29 01:18:52 +00:00
|
|
|
}
|
2011-09-14 16:47:09 +00:00
|
|
|
|
2012-09-06 19:14:32 +00:00
|
|
|
function _onPopup(actor, entry) {
|
2019-12-08 20:56:46 +00:00
|
|
|
let cursorPosition = entry.clutter_text.get_cursor_position();
|
|
|
|
let [success, textX, textY_, lineHeight_] = entry.clutter_text.position_to_coords(cursorPosition);
|
2011-09-14 16:47:09 +00:00
|
|
|
if (success)
|
2012-05-27 17:06:08 +00:00
|
|
|
entry.menu.setSourceAlignment(textX / entry.width);
|
2013-02-18 20:55:44 +00:00
|
|
|
entry.menu.open(BoxPointer.PopupAnimation.FULL);
|
2019-01-29 01:18:52 +00:00
|
|
|
}
|
2011-09-14 16:47:09 +00:00
|
|
|
|
|
|
|
function addContextMenu(entry, params) {
|
2012-05-27 17:06:08 +00:00
|
|
|
if (entry.menu)
|
2011-09-14 16:47:09 +00:00
|
|
|
return;
|
|
|
|
|
2019-12-16 18:41:49 +00:00
|
|
|
params = Params.parse(params, { actionMode: Shell.ActionMode.POPUP });
|
2013-05-10 01:35:05 +00:00
|
|
|
|
|
|
|
entry.menu = new EntryMenu(entry);
|
2019-04-09 23:23:59 +00:00
|
|
|
entry._menuManager = new PopupMenu.PopupMenuManager(entry,
|
2019-01-23 20:59:42 +00:00
|
|
|
{ actionMode: params.actionMode });
|
2012-05-27 17:06:08 +00:00
|
|
|
entry._menuManager.addMenu(entry.menu);
|
2011-09-14 16:47:09 +00:00
|
|
|
|
2012-09-06 19:14:32 +00:00
|
|
|
// Add an event handler to both the entry and its clutter_text; the former
|
2011-09-14 16:47:09 +00:00
|
|
|
// so padding is included in the clickable area, the latter because the
|
|
|
|
// event processing of ClutterText prevents event-bubbling.
|
2017-12-02 00:27:35 +00:00
|
|
|
entry.clutter_text.connect('button-press-event', (actor, event) => {
|
|
|
|
_onButtonPressEvent(actor, event, entry);
|
|
|
|
});
|
|
|
|
entry.connect('button-press-event', (actor, event) => {
|
|
|
|
_onButtonPressEvent(actor, event, entry);
|
|
|
|
});
|
2011-09-14 16:47:09 +00:00
|
|
|
|
2019-01-28 00:42:00 +00:00
|
|
|
entry.connect('popup-menu', actor => _onPopup(actor, entry));
|
2013-04-04 15:35:50 +00:00
|
|
|
|
2017-10-31 00:38:18 +00:00
|
|
|
entry.connect('destroy', () => {
|
2013-04-04 15:35:50 +00:00
|
|
|
entry.menu.destroy();
|
|
|
|
entry.menu = null;
|
|
|
|
entry._menuManager = null;
|
|
|
|
});
|
2011-09-14 16:47:09 +00:00
|
|
|
}
|
2019-12-13 08:06:14 +00:00
|
|
|
|
|
|
|
var CapsLockWarning = GObject.registerClass(
|
|
|
|
class CapsLockWarning extends St.Label {
|
|
|
|
_init(params) {
|
2020-01-23 22:26:45 +00:00
|
|
|
let defaultParams = { style_class: 'caps-lock-warning-label' };
|
2019-12-13 08:06:14 +00:00
|
|
|
super._init(Object.assign(defaultParams, params));
|
|
|
|
|
|
|
|
this.text = _('Caps lock is on.');
|
|
|
|
|
2020-01-23 21:36:09 +00:00
|
|
|
this.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
|
|
|
this.clutter_text.line_wrap = true;
|
|
|
|
|
2020-01-30 18:57:12 +00:00
|
|
|
let seat = Clutter.get_default_backend().get_default_seat();
|
|
|
|
this._keymap = seat.get_keymap();
|
2019-12-13 08:06:14 +00:00
|
|
|
|
|
|
|
this.connect('notify::mapped', () => {
|
|
|
|
if (this.is_mapped()) {
|
2021-08-15 22:36:59 +00:00
|
|
|
this._keymap.connectObject(
|
|
|
|
'state-changed', () => this._sync(true), this);
|
2019-12-13 08:06:14 +00:00
|
|
|
} else {
|
2021-08-15 22:36:59 +00:00
|
|
|
this._keymap.disconnectObject(this);
|
2019-12-13 08:06:14 +00:00
|
|
|
}
|
|
|
|
|
2020-01-23 21:36:09 +00:00
|
|
|
this._sync(false);
|
2019-12-13 08:06:14 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-01-23 21:36:09 +00:00
|
|
|
_sync(animate) {
|
2019-12-13 08:06:14 +00:00
|
|
|
let capsLockOn = this._keymap.get_caps_lock_state();
|
2020-01-23 21:36:09 +00:00
|
|
|
|
|
|
|
this.remove_all_transitions();
|
|
|
|
|
2020-02-21 18:38:53 +00:00
|
|
|
const { naturalHeightSet } = this;
|
2020-01-23 21:36:09 +00:00
|
|
|
this.natural_height_set = false;
|
|
|
|
let [, height] = this.get_preferred_height(-1);
|
2020-02-21 18:38:53 +00:00
|
|
|
this.natural_height_set = naturalHeightSet;
|
2020-01-23 21:36:09 +00:00
|
|
|
|
|
|
|
this.ease({
|
|
|
|
height: capsLockOn ? height : 0,
|
|
|
|
opacity: capsLockOn ? 255 : 0,
|
|
|
|
duration: animate ? 200 : 0,
|
|
|
|
onComplete: () => {
|
|
|
|
if (capsLockOn)
|
|
|
|
this.height = -1;
|
|
|
|
},
|
|
|
|
});
|
2019-12-13 08:06:14 +00:00
|
|
|
}
|
|
|
|
});
|