neXromancers / hacksaw

hacksaw (Select Operation)
Mozilla Public License 2.0
97 stars 7 forks source link

Add escape key to quit program, closes #5 #16

Closed JuanPotato closed 4 years ago

JuanPotato commented 5 years ago

Please test this, it should let everything else passthrough except for ESC. Also should be pretty easy to add another key to quit key if we want.

JuanPotato commented 5 years ago

I'll add magic number constants tomorrow

expectocode commented 5 years ago

Doesn't work on my machine. Let's discuss further

pickfire commented 4 years ago

Any news on this?

expectocode commented 4 years ago

Seems like the mask is the problem. It works for me on Fedora 31 if I change the mask to xcb::NONE

image

expectocode commented 4 years ago

It seems that the mask behaviour may be distro-specific - see https://stackoverflow.com/questions/35906243/no-error-on-xcb-grab-key-but-event-loop-not-catching-global-hotkey

Lonami commented 4 years ago

I can confirm it works on my Linux Mint with @expectocode's patch (pasted here as text to make it easier to git apply):

--- a/src/lib/mod.rs
+++ b/src/lib/mod.rs
@@ -136,7 +136,7 @@ pub fn grab_escape_key(conn: &xcb::Connection, root: u32) {
         &conn,
         true,
         root,
-        xcb::MOD_MASK_ANY as u16,
+        xcb::NONE as u16,
         9, // ESCAPE, would be nice if wasn't a magic number
         xcb::GRAB_MODE_ASYNC as u8,
         xcb::GRAB_MODE_ASYNC as u8,
expectocode commented 4 years ago

So the mask thing turned out to be pretty annoying - MOD_MASK_ANY really should have done it, but just doesn't do what it's supposed to. And using xcb::NONE only grabs ESC with no modifiers, which isn't a good experience since that would not pick up Caps Lock + ESC or Num Lock + ESC which people might have on. So I've emulated MOD_MASK_ANY by sending off 256 different grab key requests, so we get every single combination of modifiers. If this turns out to be too many requests, I guess we could drop down to only grabbing those which are reasonable for people to have on for a while (ie not Shift, Ctrl etc). But for consistency I'm happy with grabbing all modifiers, so I'm going to merge this now.

expectocode commented 4 years ago

Another option is to grab every modifier, but not every modifier combination. This would pick up Num Lock + ESC but not Num Lock + Shift + Esc, which could be acceptable. This is what I did in 59d4fa2 and I wouldn't mind going back to that later if the combinations turn out to be a problem.

expectocode commented 4 years ago

@pickfire thanks for poking us!

pickfire commented 4 years ago

@expectocode This grabs the wrong key on my laptop since I swapped my keys.

setxkbmap -layout 'us,us,us' -variant 'dvorak,dvp,' -option 'compose:ralt,ctrl:swapcaps,grp:rctrl_rshift_toggle,terminate:ctrl_alt_bksp'
expectocode commented 4 years ago

@pickfire what key does it grab? Could you run xev, press ESC, and paste the result? It should say keycode 9. I'm not familiar with all the options in your command there, I use setxkbmap us -variant dvp -option ctrl:swapcaps -option compose:ralt personally.

9ary commented 4 years ago

setxkbmap is broken, don't use it. You should be setting those options in /etc/Xorg.conf(.d), and for swapping keys, either create a custom xkb layout or remap your keyboard at the evdev level. Anything else will cause you grief.

pickfire commented 4 years ago

66

pickfire commented 4 years ago

That was the old one, the new one uses .Xmodmap which is supported by fcitx, the IME I used.

! swap caps lock with escape
clear Lock
keycode   9 = Caps_Lock
keycode  66 = Escape NoSymbol Escape

! swap control with alt
clear control
clear mod1
keycode  37 = Alt_L Meta_L Alt_L Meta_L Alt_L Meta_L Alt_L Meta_L
keycode 105 = Alt_R Meta_R Alt_R Meta_R Alt_R Meta_R Alt_R Meta_R
keycode  64 = Control_L NoSymbol Control_L NoSymbol Control_L Control_L
keycode 108 = Control_R NoSymbol Control_R NoSymbol Control_R Control_R
add control = Control_L Control_R
add mod1 = Alt_L Meta_L

! f1 f2 f3 f4 undo cut copy paste
!keycode  67 = Undo F1 F1 F1 F1 F1 XF86Switch_VT_1 F1 F1 XF86Switch_VT_1
!keycode  68 = XF86Cut F2 F2 F2 F2 F2 XF86Switch_VT_2 F2 F2 XF86Switch_VT_2
!keycode  69 = XF86Copy F3 F3 F3 F3 F3 XF86Switch_VT_3 F3 F3 XF86Switch_VT_3
!keycode  70 = XF86Paste F4 F4 F4 F4 F4 XF86Switch_VT_4 F4 F4 XF86Switch_VT_4
9ary commented 4 years ago

xmodmap is even worse.

pickfire commented 4 years ago

@9ary What if my system is not just used by me and I want to switch the layout back?

pickfire commented 4 years ago

What I tried is get all the keys and find the escape keycode by keysym.

let setup = conn.get_setup();

let cookie = xcb::get_keyboard_mapping(
    &conn,
    setup.min_keycode(),
    setup.max_keycode() - setup.min_keycode() + 1,
);
let reply = cookie.get_reply().expect("failed to get keyboard mapping");

let keysyms = reply.keysyms();
let nkeycodes = keysyms.len() as u8 / reply.keysyms_per_keycode();
for keycode_idx in 0..nkeycodes {
    print!("keycode {}", setup.min_keycode() + keycode_idx);
    for keysym_idx in 0..reply.keysyms_per_keycode() {
        let keysym = keysyms[(keysym_idx + keycode_idx * reply.keysyms_per_keycode()) as usize];
        print!(" {}", keysym);
        if keysym == 0xff1b { // escape key
            break
        }
    }
    println!();
}

But currently it breaks halfway:

keycode 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
keycode 9 65509 0 65509 0 65509 0 0 0 0 0 0 0 0 0 0
keycode 10 49 33 49 33 49 33 0 0 0 0 0 0 0 0 0
keycode 11 50 64 50 64 50 64 0 0 0 0 0 0 0 0 0
keycode 12 51 35 51 35 51 35 0 0 0 0 0 0 0 0 0
keycode 13 52 36 52 36 52 36 0 0 0 0 0 0 0 0 0
keycode 14 53 37 53 37 53 37 0 0 0 0 0 0 0 0 0
keycode 15 54 94 54 94 65106 65106 65106 65106 54 94 65106 65106 0 0 0
keycode 16 55 38 55 38 55 38 0 0 0 0 0 0 0 0 0

https://stackoverflow.com/questions/18689863/obtain-keyboard-layout-and-keysyms-with-xcb Xcb seemed hard to me in the beginning such that documentation is not complete and not many examples are available online.

pickfire commented 4 years ago

@9ary fcitx is here helping me, I can switch my keymap but not fully, most of the home devices are used by few people.

9ary commented 4 years ago

What if my system is not just used by me and I want to switch the layout back?

That's not a problem, you already have your system set up for multiple keymaps. Other users can easily switch keymaps as they want. You might even be able to configure this per user (with ~/.local), but I'm not sure about that one.

9ary commented 4 years ago

Take a look at this SO answer. I don't agree with his recommendation to "call 10 different binaries upon login", changing settings that way is broken. Changes will randomly revert themselves, many things don't or can't support these changes properly either, one example being your problem.

pickfire commented 4 years ago

@9ary Still I hoped it can be supported.

expectocode commented 4 years ago

(for future reference, see #17)