Coder Social home page Coder Social logo

Ctrl+w functionality about kitty HOT 13 CLOSED

kovidgoyal avatar kovidgoyal commented on May 14, 2024
Ctrl+w functionality

from kitty.

Comments (13)

kovidgoyal avatar kovidgoyal commented on May 14, 2024

I cannot reproduce this, with the following vimrc

nnoremap <C-w> dw

Then pressing Ctrl-W in normal mode in vim deletes the word under the cursor for me.

And, in command mode, pressing Ctrl-V then Ctrl-W yields ^W which indicates that kitty is correctly sending ^W to vim.

from kitty.

sebosp avatar sebosp commented on May 14, 2024

tl;dr "Key events relate to actual physical keyboard keys, whereas character events relate to the Unicode code points generated by pressing some of them."

Thank you for checking and the fast response. This turned out to be a bit more complex and my setup is in part culprit. I use dvorak keyboard layout and this would also affect AZERTY layouts and other non-qwerty keyboards may be affected in different ways too.
I found out by mistake that if I hit "Ctrl+," I could get the "delete-word" to work. The "," is the layout-translated character on top of the "W" physical key.

After checking the (glfw documentation)[http://www.glfw.org/docs/latest/input_guide.html#input_char] started trying to understand what needed to be checked. I failed a bit and then came to see that the input worked correctly on https://github.com/glfw/glfw/blob/master/tests/events.c (short ref f29c9630) the translated/real key is named "name" on this events.c (line 368 key_callback function).

So I changed a couple of files to get this working:

17:33 seb@amon:[/data/git/kitty] (master *$%=)$ git diff kitty/glfw.c
diff --git a/kitty/glfw.c b/kitty/glfw.c
index d77d1c4..4b1bfea 100644
--- a/kitty/glfw.c
+++ b/kitty/glfw.c
@@ -59,7 +59,7 @@ char_mods_callback(GLFWwindow *w, unsigned int codepoint, int mods) {
 
 static void 
 key_callback(GLFWwindow *w, int key, int scancode, int action, int mods) {
-    WINDOW_CALLBACK(key_callback, "iiii", key, scancode, action, mods);
+    WINDOW_CALLBACK(key_callback, "iiiis", key, scancode, action, mods, glfwGetKeyName(key, scancode));
 }

17:34 seb@amon:[/data/git/kitty] (master *$%=)$ git diff kitty/keys.py 
diff --git a/kitty/keys.py b/kitty/keys.py
index b8cef95..46e505b 100644
--- a/kitty/keys.py
+++ b/kitty/keys.py
@@ -48,29 +48,42 @@ control_codes[defines.GLFW_KEY_DELETE] = bytearray(key_as_bytes('kdch1').replace
 alt_codes = {k: (0x1b, k) for i, k in enumerate(range(defines.GLFW_KEY_SPACE, defines.GLFW_KEY_RIGHT_BRACKET + 1))}
 
 
-def interpret_key_event(key, scancode, mods):
+def interpret_key_event(key, scancode, mods,name):

17:36 seb@amon:[/data/git/kitty] (master *$%=)$ git diff kitty/boss.py 
diff --git a/kitty/boss.py b/kitty/boss.py
index 1450daa..c7d3405 100644
--- a/kitty/boss.py
+++ b/kitty/boss.py
@@ -254,7 +254,7 @@ class Boss(Thread):
                 w.write_to_child(data)
 
     @callback
-    def on_key(self, window, key, scancode, action, mods):
+    def on_key(self, window, key, scancode, action, mods, name):
         is_key_pressed[key] = action == GLFW_PRESS
         self.start_cursor_blink()
         self.cursor_blink_zero_time = monotonic()
@@ -281,7 +281,9 @@ class Boss(Thread):
                 if window.screen.auto_repeat_enabled or action == GLFW_PRESS:
                     if window.char_grid.scrolled_by and key not in MODIFIER_KEYS:
                         window.scroll_end()
-                    data = interpret_key_event(key, scancode, mods)
+                    # name variable comes with effective casing but the control codes
+                    # are set towards strictly upppercase letters, so we uppercase them:
+                    data = interpret_key_event(ord(name.upper()), scancode, mods, name)
                     if data:
                         window.write_to_child(data)

This gets Ctrl + D, Ctrl + W, Ctrl + C working, but, backspace is broken now, I will try to fix that soon and send a PR or something.

Thanks,
Seb.

from kitty.

kovidgoyal avatar kovidgoyal commented on May 14, 2024

I'm somewhat confused, if the problem is that the key code is incorrect, why should it only affect the Ctrl+key? Does just pressing W give a W or does it give something else? Also I dont think we can use glfwGetKeyName() according to the glfw docs that returns localized key names and is meant only for display key names to users, so I doubt there is a robust way to map those back to ascii keys.

from kitty.

kovidgoyal avatar kovidgoyal commented on May 14, 2024

To answer the first part of my question -- it does not affect plain w because that is handled by interpret_text_event not interpret_key_event

But the problem remains that glfwGetKeyName does not seem very robust. Instead we need to do whatever glfw does to map keycodes to text events. I dont know if there is an API to do that.

from kitty.

kovidgoyal avatar kovidgoyal commented on May 14, 2024

Maybe use interpret_text_event() instead of interpret_key_event() for all key handling?

from kitty.

kovidgoyal avatar kovidgoyal commented on May 14, 2024

Unfortunately, despite what the docs say, the glfw char mods callback is not called if any non-shift modifier keys are pressed, so it cannot be used. Probably this bug needs to be fixed in glfw

from kitty.

sebosp avatar sebosp commented on May 14, 2024

Perhaps this is easier to see if we run the test units from glfw and I simply press "Ctrl+w" with dvorak layout active, this is the output:

00000003 to 1 at 0.876: Key 0x0155 Scancode 0x0025 (LEFT CONTROL) (with no mods) was pressed
00000004 to 1 at 0.956: Key 0x002c Scancode 0x003b (COMMA) (w) (with control) was pressed
00000005 to 1 at 1.025: Key 0x002c Scancode 0x003b (COMMA) (w) (with control) was released
00000006 to 1 at 1.100: Key 0x0155 Scancode 0x0025 (LEFT CONTROL) (with control) was released

The code for the above print, I tried to add a bit of comments

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    const char* name = glfwGetKeyName(key, scancode); // This translates to the layout effective final key
   if (name)
    {   
        printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (%s) (with%s) was %s\n",
               counter++, slot->number, glfwGetTime(), key, scancode,
               get_key_name(key), // Key continues to be the hardware key ","
               name, // This is what we want to support multiple or non-standard layouts
               get_mods_name(mods),
               get_action_name(action));
    }   
}

You can see it has "COMMA" and "w", COMMA being the hardware key pressed, and "w" being the actual key after the layout translation has been performed.
Sorry I understand this is tricky, in my window manager I setup the keyboard layout to dvorak programmer, or I could try with azerty and it would break if I don't use the "name" as in the test unit does.
From some discussions on glfw repo the reason they may provide both is to consider game scenarios, where the "AWSD" keys act physically like arrow keys and so the position of the hardware keyboards is kept in memory, it may be why they advise against "Key" for user-input that should be handled by "Char" input... But then again their test is using Key :P

from kitty.

sebosp avatar sebosp commented on May 14, 2024

I placed a fix on sebosp@802333c if you want to test, it works for me on dvorak and qwerty, but there seems to be a bug and when you switch keyboard it doesn't switch the "name" properly, I may be missing a flag or an invalidation somewhere.

from kitty.

kovidgoyal avatar kovidgoyal commented on May 14, 2024

The problem I have with that patch is that there is no guarantee that glfwGetKeyName() will return actual ascii key names. Since it is supposed to return localised key names, they could be pretty much anything. So using that patch might actually break keyboard input on some systems where it is currently working.

from kitty.

sebosp avatar sebosp commented on May 14, 2024

Thank you, it works!

from kitty.

wis avatar wis commented on May 14, 2024

I don't want to open a new issue, but I am also having an issue with control+shift key combinations/shortcuts, I have this key mapping in my .vimrc

vnoremap <C-N> <gv
vnoremap <C-E> xp`[V`]
vnoremap <C-I> xkP`[V`]
vnoremap <C-O> >gv

which indent/undent, move the line down/up. my colemak layout's neio = your qwerty's hjkl

I just tested it and it works as it used to, in the suckless terminal, my previous beloved terminal ...that doesn't support Emoji (became a huge deal breaker 😄), because of it's limited by it's not nearly as developed as cairo+pango drawing library.
I also liked that it resized faster than kitty and alacritty with my i3wm tiling window manager, how is CPU rendering faster with resizing?

from kitty.

kovidgoyal avatar kovidgoyal commented on May 14, 2024

kitty's primary goal is reducing CPU usage, not speed. It deliberately debounces resize events, to avoid unneccessary computation while a resize is in progress.

As for your issues, I cannot reproduce them. Use the --debug-keyboard option to see what key events are being sent.

from kitty.

wis avatar wis commented on May 14, 2024

before remaping kitty_mod or unmaping default shortcuts I got this error message:
this error message
now here's my config file:

font_size 12.5
cursor_blink_interval 0.3
font_family firacode
clear_all_shortcuts yes
kitty_mod ctrl+alt
rectangle_select_modifiers ctrl+shift+alt

and here's the output of kitty --debug-keyboard

// opening vim
// move cursor down 4 lines
Press scancode: 0x2e clean_sym: e composed_sym: e text: e mods: none glfw_key: 69 (E) xkb_key: 101 (e)
on_key_input: glfw key: 69 native_code: 0x65 action: PRESS mods: 0x0 text: 'e' state: 0 sent text to child
Release scancode: 0x2e clean_sym: e mods: none glfw_key: 69 (E) xkb_key: 101 (e)
on_key_input: glfw key: 69 native_code: 0x65 action: RELEASE mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow release events
Press scancode: 0x2e clean_sym: e composed_sym: e text: e mods: none glfw_key: 69 (E) xkb_key: 101 (e)
on_key_input: glfw key: 69 native_code: 0x65 action: PRESS mods: 0x0 text: 'e' state: 0 sent text to child
Release scancode: 0x2e clean_sym: e mods: none glfw_key: 69 (E) xkb_key: 101 (e)
on_key_input: glfw key: 69 native_code: 0x65 action: RELEASE mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow release events
Press scancode: 0x2e clean_sym: e composed_sym: e text: e mods: none glfw_key: 69 (E) xkb_key: 101 (e)
on_key_input: glfw key: 69 native_code: 0x65 action: PRESS mods: 0x0 text: 'e' state: 0 sent text to child
Release scancode: 0x2e clean_sym: e mods: none glfw_key: 69 (E) xkb_key: 101 (e)
on_key_input: glfw key: 69 native_code: 0x65 action: RELEASE mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow release events
// enter visual line mode
Press scancode: 0x6c clean_sym: Shift_L composed_sym: Shift_L mods: none glfw_key: 340 (LEFT SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 340 native_code: 0xffe1 action: PRESS mods: 0x0 text: '' state: 0 sent key to child
Press scancode: 0x38 clean_sym: v composed_sym: V text: V mods: shift+numlock glfw_key: 86 (V) xkb_key: 118 (v)
on_key_input: glfw key: 86 native_code: 0x76 action: PRESS mods: 0x1 text: 'V' state: 0 sent text to child
Release scancode: 0x38 clean_sym: v mods: shift+numlock glfw_key: 86 (V) xkb_key: 118 (v)
on_key_input: glfw key: 86 native_code: 0x76 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
// press ctrl+shift+o to indent forward
Press scancode: 0x41 clean_sym: Hyper_L composed_sym: Hyper_L mods: shift+numlock glfw_fallback_key: 32 (SPACE) xkb_key: 32 (space)
on_key_input: glfw key: 32 native_code: 0x20 action: PRESS mods: 0x1 text: '' state: 0 sent key to child
Press scancode: 0x30 clean_sym: o composed_sym: O mods: ctrl+shift+numlock glfw_key: 79 (O) xkb_key: 111 (o)
on_key_input: glfw key: 79 native_code: 0x6f action: PRESS mods: 0x3 text: '' state: 0 sent key to child
Release scancode: 0x30 clean_sym: o mods: ctrl+shift+numlock glfw_key: 79 (O) xkb_key: 111 (o)
// press ctrl+shift+n to indent backward
on_key_input: glfw key: 79 native_code: 0x6f action: RELEASE mods: 0x3 text: '' state: 0 ignoring as keyboard mode does not allow release events
Press scancode: 0x2d clean_sym: n composed_sym: N mods: ctrl+shift+numlock glfw_key: 78 (N) xkb_key: 110 (n)
on_key_input: glfw key: 78 native_code: 0x6e action: PRESS mods: 0x3 text: '' state: 0 sent key to child
Release scancode: 0x2d clean_sym: n mods: ctrl+shift+numlock glfw_key: 78 (N) xkb_key: 110 (n)
on_key_input: glfw key: 78 native_code: 0x6e action: RELEASE mods: 0x3 text: '' state: 0 ignoring as keyboard mode does not allow release events
// press ctrl+shift+e to move selected line/s down
Press scancode: 0x2e clean_sym: e composed_sym: E mods: ctrl+shift+numlock glfw_key: 69 (E) xkb_key: 101 (e)
on_key_input: glfw key: 69 native_code: 0x65 action: PRESS mods: 0x3 text: '' state: 0 sent key to child
Release scancode: 0x2e clean_sym: e mods: ctrl+shift+numlock glfw_key: 69 (E) xkb_key: 101 (e)
on_key_input: glfw key: 69 native_code: 0x65 action: RELEASE mods: 0x3 text: '' state: 0 ignoring as keyboard mode does not allow release events
// press ctrl+shift+e to move selected line/s up
Press scancode: 0x2f clean_sym: i composed_sym: I mods: ctrl+shift+numlock glfw_key: 73 (I) xkb_key: 105 (i)
on_key_input: glfw key: 73 native_code: 0x69 action: PRESS mods: 0x3 text: '' state: 0 sent key to child
Release scancode: 0x2f clean_sym: i mods: ctrl+shift+numlock glfw_key: 73 (I) xkb_key: 105 (i)
on_key_input: glfw key: 73 native_code: 0x69 action: RELEASE mods: 0x3 text: '' state: 0 ignoring as keyboard mode does not allow release events
Release scancode: 0x41 clean_sym: Hyper_L mods: ctrl+shift+numlock glfw_fallback_key: 32 (SPACE) xkb_key: 32 (space)
// where are the space and the numlock coming from? I didn't press them,
// but I have space mapped to ctrl with https://github.com/r0adrunner/Space2Ctrl
// and right alt mapped to shift, both always under my thumbs
on_key_input: glfw key: 32 native_code: 0x20 action: RELEASE mods: 0x3 text: '' state: 0 ignoring as keyboard mode does not allow release events
Release scancode: 0x6c clean_sym: Shift_L mods: shift+numlock glfw_key: 340 (LEFT SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 340 native_code: 0xffe1 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Press scancode: 0x86 clean_sym: Super_R composed_sym: Super_R mods: numlock glfw_key: 347 (RIGHT SUPER) xkb_key: 65516 (Super_R)
on_key_input: glfw key: 347 native_code: 0xffec action: PRESS mods: 0x0 text: '' state: 0 sent key to child
on_key_input: glfw key: 347 native_code: 0xffec action: RELEASE mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow release events
// closing vim and exiting shell to close kitty

output of kitty --version: kitty 0.13.3 created by Kovid Goyal

from kitty.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.