mirror of
https://github.com/gosticks/PaperWM.git
synced 2026-10-04 11:36:54 +00:00
navigator: Rewrite the keybind handler
Using a SwitcherPopup was just tiresome.
This commit is contained in:
+73
-44
@@ -30,35 +30,35 @@ var display = global.display;
|
||||
var scale = 0.9;
|
||||
var navigating = false;
|
||||
|
||||
var PreviewedWindowNavigator = utils.registerClass(
|
||||
class PreviewedWindowNavigator extends SwitcherPopup.SwitcherPopup {
|
||||
_init() {
|
||||
// Do the absolute minimal here, as `parent.show` is buggy and can
|
||||
// return early making cleanup hard. We do most initialization in
|
||||
// `_initialSelection` instead.
|
||||
/**
|
||||
Handle catching keyevents and dispatching actions
|
||||
|
||||
// HACK: workaround to enable moving from empty workspace. See check in
|
||||
// SwitcherPopup.show
|
||||
super._init([1]);
|
||||
if (!('actor' in this)) { // 3.30 compat
|
||||
this.actor = this;
|
||||
Adapted from SwitcherPopup
|
||||
*/
|
||||
var ActionDispatcher = class {
|
||||
constructor() {
|
||||
this.actor = new Clutter.Actor();
|
||||
Main.uiGroup.add_actor(this.actor);
|
||||
if (!Main.pushModal(this.actor)) {
|
||||
// Probably someone else has a pointer grab, try again with keyboard only
|
||||
if (!Main.pushModal(this.actor, {
|
||||
options: Meta.ModalOptions.POINTER_ALREADY_GRABBED
|
||||
})) throw new Error('Could not grap a modal');;
|
||||
}
|
||||
this._switcherList = new SwitcherPopup.SwitcherList();
|
||||
if (!('actor' in this._switcherList)) {
|
||||
this._switcherList.actor = this._switcherList;
|
||||
}
|
||||
debug('#preview', 'init', this._switcherList);
|
||||
|
||||
this.actor.connect('key-press-event', this._keyPressEvent.bind(this));
|
||||
this.actor.connect('key-release-event', this._keyReleaseEvent.bind(this));
|
||||
|
||||
}
|
||||
|
||||
_initialSelection(backward, actionName) {
|
||||
debug('#preview', '_initialSelection');
|
||||
show(backward, binding, mask) {
|
||||
this._modifierMask = SwitcherPopup.primaryModifier(mask);
|
||||
this.navigator = getNavigator();
|
||||
this._switcherList.actor.hide();
|
||||
let actionId = Keybindings.idOf(actionName);
|
||||
let actionId = Keybindings.idOf(binding);
|
||||
if(actionId === Meta.KeyBindingAction.NONE) {
|
||||
try {
|
||||
// Check for built-in actions
|
||||
actionId = Meta.prefs_get_keybinding_action(actionName);
|
||||
actionId = Meta.prefs_get_keybinding_action(binding);
|
||||
} catch(e) {
|
||||
debug("Couldn't resolve action name");
|
||||
return;
|
||||
@@ -68,6 +68,52 @@ class PreviewedWindowNavigator extends SwitcherPopup.SwitcherPopup {
|
||||
this._doAction(actionId);
|
||||
}
|
||||
|
||||
_keyPressEvent(actor, event) {
|
||||
let keysym = event.get_key_symbol();
|
||||
let action = global.display.get_keybinding_action(event.get_key_code(), event.get_state());
|
||||
|
||||
if (this._keyPressHandler(keysym, action) != Clutter.EVENT_PROPAGATE)
|
||||
return Clutter.EVENT_STOP;
|
||||
|
||||
// Popping the modal on keypress doesn't work properly, as the release
|
||||
// event will leak to the active window. To work around this we initate
|
||||
// visual destruction on key-press and signal to the release handler
|
||||
// that we should destroy the dispactcher too
|
||||
// https://github.com/paperwm/PaperWM/issues/70
|
||||
if (keysym == Clutter.Escape || keysym == Clutter.Tab) {
|
||||
this.navigator.destroy();
|
||||
this._destroy = true;
|
||||
}
|
||||
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
_keyReleaseEvent(actor, event) {
|
||||
let keysym = event.get_key_symbol();
|
||||
if (this._destroy) {
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
if (this._modifierMask) {
|
||||
let [x, y, mods] = global.get_pointer();
|
||||
let state = mods & this._modifierMask;
|
||||
|
||||
if (state == 0)
|
||||
this._finish(event.get_time());
|
||||
}
|
||||
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
|
||||
_keyPressHandler(keysym, action) {
|
||||
if (keysym !== Clutter.KEY_Escape && this._doAction(action)) {
|
||||
return Clutter.EVENT_STOP;
|
||||
} else {
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
}
|
||||
|
||||
_doAction(mutterActionId) {
|
||||
|
||||
let action = Keybindings.byId(mutterActionId);
|
||||
@@ -91,35 +137,18 @@ class PreviewedWindowNavigator extends SwitcherPopup.SwitcherPopup {
|
||||
return false;
|
||||
}
|
||||
|
||||
_keyPressHandler(keysym, action) {
|
||||
if (keysym !== Clutter.KEY_Escape && this._doAction(action)) {
|
||||
return Clutter.EVENT_STOP;
|
||||
} else {
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
}
|
||||
|
||||
_finish(timestamp) {
|
||||
debug('#preview', 'finish');
|
||||
this.navigator.accept();
|
||||
super._finish(timestamp);
|
||||
}
|
||||
|
||||
_itemEnteredHandler() {
|
||||
// The item-enter (mouse hover) event is triggered even after a item is
|
||||
// accepted. This can cause _select to run on the item below the pointer
|
||||
// ensuring the wrong window.
|
||||
if(!this.was_accepted) {
|
||||
super._itemEnteredHandler.apply(this, arguments);
|
||||
}
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.actor.hide(); // Prevents finalized crap
|
||||
super.destroy();
|
||||
this.navigator.destroy();
|
||||
Main.popModal(this.actor);
|
||||
this.actor.destroy();
|
||||
!this._destroy && this.navigator.destroy();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var navigator;
|
||||
var Navigator = class Navigator {
|
||||
@@ -258,6 +287,6 @@ function getNavigator() {
|
||||
}
|
||||
|
||||
function preview_navigate(meta_window, space, {display, screen, binding}) {
|
||||
let tabPopup = new PreviewedWindowNavigator();
|
||||
let tabPopup = new ActionDispatcher();
|
||||
tabPopup.show(binding.is_reversed(), binding.get_name(), binding.get_mask());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user