Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mac OS cmd+esc / shift+cmd+esc shortcuts to switch window stopped working in 0.24.0 #4501

Closed
fgoepel opened this issue Jan 12, 2022 · 45 comments
Labels

Comments

@fgoepel
Copy link

fgoepel commented Jan 12, 2022

Describe the bug
In 0.23.1 and below pressing cmd+esc/shift+cmd+esc would cycle between windows, as it does in all other Mac OS applications. This does not work anymore in 0.24.0/0.24.1.

It looks like 2b9408c is the culprit.

Environment details
kitty 0.24.0 created by Kovid Goyal
Darwin imac 18.7.0 Darwin Kernel Version 18.7.0: Tue Jun 22 19:37:08 PDT 2021; root:xnu-4903.278.70~1/RELEASE_X86_64 x86_64
ProductName: Mac OS X ProductVersion: 10.14.6 BuildVersion: 18G9323

@fgoepel fgoepel added the bug label Jan 12, 2022
@page-down
Copy link
Contributor

Doesn't cmd+` switch windows in the same application under macOS?

@fgoepel
Copy link
Author

fgoepel commented Jan 12, 2022

It seems I customized that shortcut in the OS settings.

I've tried to see if I could change the kitty config to make this work e.g. like this:

map cmd+escape next_window
map shift+cmd+escape previous_window

But that doesn't seem to work.

@kovidgoyal
Copy link
Owner

works fine for me with:

  1. kitty -o 'map cmd+esc next_window'
  2. Press ctrl+shift+enter to create a new kitty window
  3. press cmd+esc switches to the first window

Note that in kitty there are kitty windows and OS windows. An OS window
can contian multiple kitty windows.

@kovidgoyal
Copy link
Owner

And just for completeness the change in behavior comes because cmd+esc is no longer passed to cocoa, in order to make it mappable inside kitty. These were IIRC changes by @page-down see is_modified_special_key()

@fgoepel
Copy link
Author

fgoepel commented Jan 12, 2022

I see. However, I want to switch between OS windows. How do I achieve this now?

@Luflosi
Copy link
Contributor

Luflosi commented Jan 12, 2022

Is it enough to unmap the keyboard shortcut in kitty by mapping it to no_op?

@fgoepel
Copy link
Author

fgoepel commented Jan 12, 2022

Would it be possible to add an option to disable the hijacking of these keys so that the OS level mappings can continue to work?

@page-down
Copy link
Contributor

According to your description, I configured the key to switch between windows of the same application in macOS as cmd+esc.

At this point, the OS window cannot be switched in kitty. Such potential concerns were anticipated at the time of the discussion.

Mentioned in the comments:

// really one should use [[NSUserDefaults standardUserDefaults] valueForDefaultsDomain:@"com.apple.symbolichotkeys" key:@"AppleSymbolicHotKeys"]
// to get the list of global shortcuts and pass through the important ones,

To solve it, we need to read all the keys that the user has configured globally in the system. Then leave those keys untouched.
This is indeed too much work.
I don't have a good idea yet.


I implemented nth_os_window in this version, and I was wondering if I needed to implement next_os_window, because there is this system feature, so I didn't do it.

@Luflosi
Copy link
Contributor

Luflosi commented Jan 12, 2022

Would it be possible to only hijack the keyboard shortcut if it is actually used in kitty?

@fgoepel
Copy link
Author

fgoepel commented Jan 12, 2022

To solve it, we need to read all the keys that the user has configured globally in the system. Then leave those keys untouched. This is indeed too much work. I don't have a good idea yet.

You could add a "macos_hijack_escape" option or something similar to control this maybe?

@kovidgoyal
Copy link
Owner

kovidgoyal commented Jan 12, 2022 via email

@page-down
Copy link
Contributor

@shado23
For now, you can use the kitten below, although it is a bit different from the system's functionality.

~/.config/kitty/next_os_window.py

from kitty.fast_data_types import current_os_window, focus_os_window

def main(args):
    pass

from kittens.tui.handler import result_handler
@result_handler(no_ui=True)
def handle_result(args, answer, target_window_id, boss):
    l = list(boss.os_window_map.keys())
    osw_id = current_os_window()
    if osw_id in l:
        i = l.index(osw_id) + 1
        if i >= len(l):
            i = 0
        focus_os_window(l[i], True)
map cmd+esc kitten next_os_window.py

@page-down
Copy link
Contributor

page-down commented Jan 13, 2022

I tried the new changes and found that the keys are not repeatable, for example holding Backspace does not continuously delete text.

Pressing ctrl+d sometimes results in d being entered. It seems to be the same problem.

EDIT: It seems to be my problem.
EDIT2: The problem does seem to exist.

@kovidgoyal
Copy link
Owner

I cannot replicate, can you provide more detail? I tried the steps:

  1. run kitty --debug-input
  2. hold down a key
  3. a bunch of aaaa are present at the prompt
  4. hold down delete key
  5. the letters from 3 are deleted

@page-down
Copy link
Contributor

kitty --config=NONE --debug-input cat

No input source (IME) activated.

NSEvent: type=KeyDown loc=(562,695.016) time=22221.3 flags=0x100 win=0x7f7b2a7e20e0 winNum=1602 ctxt=0x0 chars="a" unmodchars="a" repeat=0 keyCode=0
NSEvent: type=KeyDown loc=(562,695.016) time=22221.7 flags=0x100 win=0x7f7b2a7e20e0 winNum=1602 ctxt=0x0 chars="a" unmodchars="a" repeat=1 keyCode=0
NSEvent: type=KeyDown loc=(562,695.016) time=22221.7 flags=0x100 win=0x7f7b2a7e20e0 winNum=1602 ctxt=0x0 chars="a" unmodchars="a" repeat=1 keyCode=0
NSEvent: type=KeyDown loc=(562,695.016) time=22221.8 flags=0x100 win=0x7f7b2a7e20e0 winNum=1602 ctxt=0x0 chars="a" unmodchars="a" repeat=1 keyCode=0
NSEvent: type=KeyDown loc=(562,695.016) time=22221.8 flags=0x100 win=0x7f7b2a7e20e0 winNum=1602 ctxt=0x0 chars="a" unmodchars="a" repeat=1 keyCode=0
NSEvent: type=KeyDown loc=(562,695.016) time=22221.8 flags=0x100 win=0x7f7b2a7e20e0 winNum=1602 ctxt=0x0 chars="a" unmodchars="a" repeat=1 keyCode=0
NSEvent: type=KeyDown loc=(562,695.016) time=22221.9 flags=0x100 win=0x7f7b2a7e20e0 winNum=1602 ctxt=0x0 chars="a" unmodchars="a" repeat=1 keyCode=0
NSEvent: type=KeyDown loc=(562,695.016) time=22221.9 flags=0x100 win=0x7f7b2a7e20e0 winNum=1602 ctxt=0x0 chars="a" unmodchars="a" repeat=1 keyCode=0
NSEvent: type=KeyUp loc=(562,695.016) time=22221.9 flags=0x100 win=0x7f7b2a7e20e0 winNum=1602 ctxt=0x0 chars="a" unmodchars="a" repeat=0 keyCode=0
Press: native_key: 0x0 (a) glfw_key: 0x61 mods: none char_count: 1 deadKeyState: 0 repeat: 0 
	insertText: a replacementRange: (9223372036854775807, 0)
text: 0x61 glfw_key: a marked_text: ()
on_key_input: glfw key: 0x61 native_code: 0x0 action: PRESS mods: none text: 'a' state: 0 updateIMEPosition: left=2.000000, top=2.000000, width=7.000000, height=13.000000
sent key as text to child
on_key_input: glfw key: 0xe062 native_code: 0x3b action: PRESS mods: ctrl text: '' state: 0 updateIMEPosition: left=9.000000, top=2.000000, width=7.000000, height=13.000000

@kovidgoyal
Copy link
Owner

That log looks like there is no key window present, try generating it
again with my latest commit to confirm.

@page-down
Copy link
Contributor

---------------- key down -------------------
NSEvent: type=KeyDown loc=(1000,435.016) time=22776.1 flags=0x100 win=0x7f7bbf491e60 winNum=1659 ctxt=0x0 chars="a" unmodchars="a" repeat=0 keyCode=0
---------------- key down -------------------
NSEvent: type=KeyDown loc=(1000,435.016) time=22776.5 flags=0x100 win=0x7f7bbf491e60 winNum=1659 ctxt=0x0 chars="a" unmodchars="a" repeat=1 keyCode=0
---------------- key down -------------------
NSEvent: type=KeyDown loc=(1000,435.016) time=22776.6 flags=0x100 win=0x7f7bbf491e60 winNum=1659 ctxt=0x0 chars="a" unmodchars="a" repeat=1 keyCode=0
---------------- key down -------------------
NSEvent: type=KeyDown loc=(1000,435.016) time=22776.6 flags=0x100 win=0x7f7bbf491e60 winNum=1659 ctxt=0x0 chars="a" unmodchars="a" repeat=1 keyCode=0
---------------- key down -------------------
NSEvent: type=KeyDown loc=(1000,435.016) time=22776.6 flags=0x100 win=0x7f7bbf491e60 winNum=1659 ctxt=0x0 chars="a" unmodchars="a" repeat=1 keyCode=0
---------------- key down -------------------
NSEvent: type=KeyDown loc=(1000,435.016) time=22776.7 flags=0x100 win=0x7f7bbf491e60 winNum=1659 ctxt=0x0 chars="a" unmodchars="a" repeat=1 keyCode=0
----------------- key up --------------------
NSEvent: type=KeyUp loc=(1000,435.016) time=22776.7 flags=0x100 win=0x7f7bbf491e60 winNum=1659 ctxt=0x0 chars="a" unmodchars="a" repeat=0 keyCode=0
Release: native_key: 0x0 (a) glfw_key: 0x61 mods: none 
on_key_input: glfw key: 0x61 native_code: 0x0 action: RELEASE mods: none text: '' state: 0 updateIMEPosition: left=2.000000, top=2.000000, width=7.000000, height=13.000000
ignoring as keyboard mode does not support encoding this event
on_key_input: glfw key: 0xe062 native_code: 0x3b action: PRESS mods: ctrl text: '' state: 0 updateIMEPosition: left=2.000000, top=2.000000, width=7.000000, height=13.000000
ignoring as keyboard mode does not support encoding this event
---------------- key down -------------------
NSEvent: type=KeyDown loc=(1000,435.016) time=22779.8 flags=0x40101 win=0x7f7bbf491e60 winNum=1659 ctxt=0x0 chars="" unmodchars="c" repeat=0 keyCode=8
----------------- key up --------------------
NSEvent: type=KeyUp loc=(1000,435.016) time=22779.9 flags=0x40101 win=0x7f7bbf491e60 winNum=1659 ctxt=0x0 chars="" unmodchars="c" repeat=0 keyCode=8
Release: native_key: 0x8 (c) glfw_key: 0x63 mods: ctrl

Hmm... ctrl+c does not work now.

@kovidgoyal
Copy link
Owner

I dont see how that log is possible, do you have this commit: 682eb7d

@page-down
Copy link
Contributor

Yes. 682eb7d80249f43cf7981cf5a780c4bfd2f60308.

I don't think I have any other software that would affect this.

@kovidgoyal
Copy link
Owner

then modify the key_down block to print that it is indeed calling contentWindow keyDown and then add some prints in keyDown in cocoa_window.m to confirm that it is being called and where it is returning.

@page-down
Copy link
Contributor

NSEvent* (^keydown_block)(NSEvent*) = ^ NSEvent* (NSEvent* event) {
...
// now check if there is a useful apple shortcut
int global_shortcut = is_active_apple_global_shortcut(event);
// <--- Never reached here.
is_active_apple_global_shortcut(NSEvent *event) {
if (global_shortcuts == nil) build_global_shortcuts_lookup();
// <--- Never reached here.
build_global_shortcuts_lookup(void) {
...
// <--- Never reached here.
global_shortcuts = [[NSDictionary dictionaryWithDictionary:temp] retain];  

It looks like ended up inside here.
[symbolic_hotkeys enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop)

@kovidgoyal
Copy link
Owner

weird how is that even possible. Try an asan build is there some memmory corruption happeing?

@page-down
Copy link
Contributor

make asan

    debug_key("---> before global_shortcuts = ...\n");
    global_shortcuts = [[NSDictionary dictionaryWithDictionary:temp] retain];
    ...
    debug_key("---> end build_global_shortcuts_lookup\n");
static int
is_active_apple_global_shortcut(NSEvent *event) {
    if (global_shortcuts == nil) build_global_shortcuts_lookup();
    debug_key("---> after build_global_shortcuts_lookup\n");
        debug_key("-----> before is_active_apple_global_shortcut\n");
        // now check if there is a useful apple shortcut
        int global_shortcut = is_active_apple_global_shortcut(event);
        debug_key("-----> after is_active_apple_global_shortcut\n");
---------------- key down -------------------
NSEvent: type=KeyDown loc=(1318,189.016) time=25543.7 flags=0x100 win=0x61400003f240 winNum=2196 ctxt=0x0 chars="a" unmodchars="a" repeat=0 keyCode=0
-----> before is_active_apple_global_shortcut
----------------- key up --------------------
NSEvent: type=KeyUp loc=(1318,189.016) time=25543.7 flags=0x100 win=0x61400003f240 winNum=2196 ctxt=0x0 chars="a" unmodchars="a" repeat=0 keyCode=0
Release: native_key: 0x0 (a) glfw_key: 0x61 mods: none

@kovidgoyal
Copy link
Owner

I changed it to use a for loop instead fo block for enumeration, see if
that helps.

@page-down
Copy link
Contributor

It does not appear to be due to the "block" problem.

  • It seems that in my case exceptions are handled silently, perhaps a way to catch them in kitty is needed. NSSetUncaughtExceptionHandler?
  • I have an item here with key id 164. I don't know what it is.

After I caught the exception:

// key=164
-[__NSCFArray objectAtIndexedSubscript:]: index (2) beyond bounds (2)

	0   CoreFoundation                      0x00007ff806020f0b __exceptionPreprocess + 242
	1   libobjc.A.dylib                     0x00007ff805d81b9d objc_exception_throw + 48
	2   CoreFoundation                      0x00007ff8060dc434 _CFThrowFormattedException + 202
	3   CoreFoundation                      0x00007ff8060dd763 _NSArrayRaiseInsertNilException + 0
	4   CoreFoundation                      0x00007ff805fc76d1 -[__NSCFArray objectAtIndexedSubscript:] + 154
	5   glfw-cocoa.so                       0x000000010215c360 ___glfwPlatformInit_block_invoke + 1280

At this point I can run it.
I'll try some more key combinations and hope there are no more potential misses.

@kovidgoyal
Copy link
Owner

I have added code to validate the parameters array

@page-down
Copy link
Contributor

I think I can update these definitions when I have time, but there are two right now that maybe need more work.

Maybe we can also check the type, I see that all the types are standard except 164.

164 = {
    ...
        type = modifier;
<key>type</key>
<string>standard</string>

I tried the following steps and could not switch OS windows, is it normal on your system?

  • quit kitty
  • set cmd+esc to Move focus to next window in system preferences
  • kitty --config=NONE --debug-input
  • cmd+n
  • cmd+esc
---------------- key down -------------------
NSEvent: type=KeyDown loc=(963,695.016) time=33498.8 flags=0x100108 win=0x7f84ca148020 winNum=2805 ctxt=0x0 chars=" unmodchars=" repeat=0 keyCode=53
Press: native_key: 0x35 (<cc>) glfw_key: 0xe000 mods: super char_count: 1 deadKeyState: 0 repeat: 0
	doCommandBySelector: (noop:)
text: <none> glfw_key: ESCAPE marked_text: ()
on_key_input: glfw key: 0xe000 native_code: 0x35 action: PRESS mods: super text: '' state: 0 updateIMEPosition: left=282.000000, top=15.000000, width=7.000000, height=13.000000
sent encoded key to child
----------------- key up --------------------
NSEvent: type=KeyUp loc=(963,695.016) time=33498.9 flags=0x100108 win=0x7f84ca148020 winNum=2805 ctxt=0x0 chars=" unmodchars=" repeat=0 keyCode=53
Release: native_key: 0x35 (<cc>) glfw_key: 0xe000 mods: super
on_key_input: glfw key: 0xe000 native_code: 0x35 action: RELEASE mods: super text: '' state: 0 updateIMEPosition: left=282.000000, top=15.000000, width=7.000000, height=13.000000

@kovidgoyal
Copy link
Owner

kovidgoyal commented Jan 13, 2022 via email

@page-down
Copy link
Contributor

Thanks. Now it works fine.

I have a question about the response of a key combination.

  • shift+cmd+5 (Screenshot and recording options) (currently not in enum list)
  • esc to cancel
  • a key release event in show_key kitten

Is this a key release event normal?

on_key_input: glfw key: 0xe064 native_code: 0x37 action: PRESS mods: super text: '' state: 0 updateIMEPosition: left=2.000000, top=323.000000, width=8.000000, height=17.000000
sent encoded key to child
on_key_input: glfw key: 0xe061 native_code: 0x38 action: PRESS mods: shift+super text: '' state: 0 updateIMEPosition: left=2.000000, top=374.000000, width=8.000000, height=17.000000
sent encoded key to child
on_key_input: glfw key: 0x61 native_code: 0x0 action: RELEASE mods: none text: '' state: 0 updateIMEPosition: left=2.000000, top=425.000000, width=8.000000, height=17.000000
sent encoded key to child
----------------- key up --------------------
NSEvent: type=KeyUp loc=(488,444.016) time=41479.7 flags=0x100 win=0x7fdb6276a9e0 winNum=3405 ctxt=0x0 chars=" unmodchars=" repeat=0 keyCode=53
Release: native_key: 0x35 (<cc>) glfw_key: 0xe000 mods: none
Shift+LEFT_SHIFT PRESS 
CSI 57441 ; 2 u

Shift+Super+LEFT_SUPER PRESS 
CSI 57444 ; 10 u

a RELEASE 
CSI 97 ; 1 : 3 u

@kovidgoyal
Copy link
Owner

Check in flagsChanged in cocoa_window.m that function should possibly be changed to only send events if the key is one of the modifier keys.

@kovidgoyal
Copy link
Owner

See 5e5cd1a

@page-down
Copy link
Contributor

Is this a key release event normal?

Check in flagsChanged in cocoa_window.m
See 5e5cd1a

Tested the latest changes and this issue no longer occurs.

@page-down
Copy link
Contributor

I found that the following global functions need special treatment.

When there is no shift modifier key combination in global_shortcuts, a new shortcut with shift should be added at the same time.

Otherwise Shift+XXX (e.g. Shift+Cmd+`) does not work.

kSHKMoveFocusToActiveOrNextWindow
kSHKMoveFocusToNextWindow

@kovidgoyal
Copy link
Owner

kovidgoyal commented Jan 14, 2022 via email

@page-down
Copy link
Contributor

Yes, for example, Cmd+Esc is set in the system settings to switch to the next window.
Pressing Shift+Cmd+Esc at this point should switch to the previous window.

However, I can't switch windows even if I set Shift+Cmd+Backtick explicitly now. I need to check it again.

@kovidgoyal
Copy link
Owner

kovidgoyal commented Jan 14, 2022 via email

@page-down
Copy link
Contributor

why? on my macOS with default shortcuts pressing shift+cmd+` has no effect.

By default, if "Cmd+`" is set to switch windows, then when you press the shortcut it switches to the next window.

At this point "Shift+Cmd+`" works fine in other applications on my system (as always) and will cycle to the previous window in the reverse order.

@kovidgoyal
Copy link
Owner

ah ok, it didnt work for me because I was doing it over vnc. Should be
simple enough to implement in build_global_shortcut_lookup. If you see
the shortcut is movetonextwindow and doesnt have shift in its modifiers,
add shift to the mods and create an extra entry.

@page-down
Copy link
Contributor

I found the reason why the shortcut key with Shift does not work. When checking if it is a global shortcut, the shift key transformed character is used.

global_shortcuts: (Shift+Cmd+`)

"c:120000:96"

When the Shift modifier key shortcut is pressed, the following (Shift+Cmd+~) is checked. (Not found.)

"c:120000:126"

So even if I set it directly to "Shift+Cmd+`" it doesn't work. Is there an existing function to convert Shift modified characters?

@kovidgoyal
Copy link
Owner

the code uses charactersIgnoringModifiers for this reason, however, it
seems this function does not ignore shift. I dont know of any function
that does this out of the box. The closes is UCKeyTranslate() I believe,
see the various function in coca_window.m that call this function, one
of them might work.

@kovidgoyal
Copy link
Owner

I have committed a fix for dealing with the shifted versions of those two shortcuts.

@page-down
Copy link
Contributor

I have committed a fix for dealing with the shifted versions of those two shortcuts.

I confirmed that when "Cmd+`" is configured, using the shift modifier key works fine.

However, there are still problems with using shortcuts with the shift key that I mentioned earlier.

... I can't switch windows even if I set Shift+Cmd+Backtick explicitly ...

---------------- key down -------------------
NSEvent: type=KeyDown loc=(729,702.016) time=13597.9 flags=0x12010a win=0x7fec9a44d810 winNum=972 ctxt=0x0 chars="`" unmodchars="~" repeat=0 keyCode=50
Press: native_key: 0x32 (`) glfw_key: 0x60 mods: shift+super char_count: 1 deadKeyState: 0 repeat: 0 
	TextInputCtx: doCommandBySelector: (noop:)
text: <none> glfw_key: ` marked_text: ()
on_key_input: glfw key: 0x60 native_code: 0x32 action: PRESS mods: shift+super text: '' state: 0 updateIMEPosition: left=2.000000, top=663.000000, width=8.000000, height=17.000000
sent encoded key to child
----------------- key up --------------------
NSEvent: type=KeyUp loc=(729,702.016) time=13598.0 flags=0x12010a win=0x7fec9a44d810 winNum=972 ctxt=0x0 chars="`" unmodchars="~" repeat=0 keyCode=50
Release: native_key: 0x32 (`) glfw_key: 0x60 mods: shift+super 
on_key_input: glfw key: 0x60 native_code: 0x32 action: RELEASE mods: shift+super text: '' state: 0 updateIMEPosition: left=2.000000, top=663.000000, width=8.000000, height=17.000000
sent encoded key to child

Here is what I tested.

  • kSHKMoveFocusToActiveOrNextWindow
    • Using the default shortcut Ctrl+F4, does not work and key events are sent to child.
  • kSHKMoveFocusToNextWindow
    • Using the default shortcut "Cmd+`", everything works fine, including the shift modifier key.
    • Using the shortcut "Shift+Cmd+`", does not work.

@kovidgoyal
Copy link
Owner

kovidgoyal commented Jan 15, 2022 via email

@page-down
Copy link
Contributor

Thanks, I tested it and it works.

About the other issues, maybe I'll take a look later.
To be honest I don't really care either.
However there are still some keys that don't work, so maybe that can be dealt with.

@fgoepel
Copy link
Author

fgoepel commented Feb 17, 2022

Finally found some time to test a nightly build. I can confirm it works as desired now.
Thanks again for the quick fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants