mirror of
https://github.com/kovidgoyal/kitty.git
synced 2024-11-13 12:09:35 +03:00
macOS: Fix the new OS window keyboard shortcut not working if no kitty window currently has focus.
Fixes #524
This commit is contained in:
parent
f259c23695
commit
2e8d19601b
@ -44,6 +44,9 @@ Changelog
|
||||
|
||||
- Wayland: Fix mouse wheel/touchpad scrolling in opposite direction to other apps (:iss:`594`)
|
||||
|
||||
- macOS: Fix the new OS window keyboard shortcut (:sc:`new_os_window`) not
|
||||
working if no kitty window currently has focus. (:iss:`524`)
|
||||
|
||||
- Add a config option to set the EDITOR kitty uses (:iss:`580`)
|
||||
|
||||
- Add an option to @set-window-title to make the title change non-permanent
|
||||
|
@ -2088,3 +2088,96 @@ GLFWAPI GLFWcocoatextinputfilterfun glfwSetCocoaTextInputFilter(GLFWwindow *hand
|
||||
window->ns.textInputFilterCallback = callback;
|
||||
return previous;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, unsigned short *cocoa_key, int *cocoa_mods) {
|
||||
*cocoa_key = 0;
|
||||
*cocoa_mods = 0;
|
||||
|
||||
if (glfw_mods & GLFW_MOD_SHIFT)
|
||||
*cocoa_mods |= NSEventModifierFlagShift;
|
||||
if (glfw_mods & GLFW_MOD_CONTROL)
|
||||
*cocoa_mods |= NSEventModifierFlagControl;
|
||||
if (glfw_mods & GLFW_MOD_ALT)
|
||||
*cocoa_mods |= NSEventModifierFlagOption;
|
||||
if (glfw_mods & GLFW_MOD_SUPER)
|
||||
*cocoa_mods |= NSEventModifierFlagCommand;
|
||||
if (glfw_mods & GLFW_MOD_CAPS_LOCK)
|
||||
*cocoa_mods |= NSEventModifierFlagCapsLock;
|
||||
|
||||
switch(glfw_key) {
|
||||
#define K(ch, name) case GLFW_KEY_##name: *cocoa_key = ch; break;
|
||||
K('a', A);
|
||||
K('b', B);
|
||||
K('c', C);
|
||||
K('d', D);
|
||||
K('e', E);
|
||||
K('f', F);
|
||||
K('g', G);
|
||||
K('h', H);
|
||||
K('i', I);
|
||||
K('j', J);
|
||||
K('k', K);
|
||||
K('l', L);
|
||||
K('m', M);
|
||||
K('n', N);
|
||||
K('o', O);
|
||||
K('p', P);
|
||||
K('q', Q);
|
||||
K('r', R);
|
||||
K('s', S);
|
||||
K('t', T);
|
||||
K('u', U);
|
||||
K('v', V);
|
||||
K('w', W);
|
||||
K('x', X);
|
||||
K('y', Y);
|
||||
K('z', Z);
|
||||
K('0', 0);
|
||||
K('1', 1);
|
||||
K('2', 2);
|
||||
K('3', 3);
|
||||
K('5', 5);
|
||||
K('6', 6);
|
||||
K('7', 7);
|
||||
K('8', 8);
|
||||
K('9', 9);
|
||||
K('\'', APOSTROPHE);
|
||||
K(',', COMMA);
|
||||
K('.', PERIOD);
|
||||
K('/', SLASH);
|
||||
K('-', MINUS);
|
||||
K('=', EQUAL);
|
||||
K(';', SEMICOLON);
|
||||
K('[', LEFT_BRACKET);
|
||||
K(']', RIGHT_BRACKET);
|
||||
K('`', GRAVE_ACCENT);
|
||||
K('\\', BACKSLASH);
|
||||
|
||||
K(0x35, ESCAPE);
|
||||
K('\r', ENTER);
|
||||
K('\t', TAB);
|
||||
K(NSBackspaceCharacter, BACKSPACE);
|
||||
K(NSInsertFunctionKey, INSERT);
|
||||
K(NSDeleteCharacter, DELETE);
|
||||
K(NSLeftArrowFunctionKey, LEFT);
|
||||
K(NSRightArrowFunctionKey, RIGHT);
|
||||
K(NSUpArrowFunctionKey, UP);
|
||||
K(NSDownArrowFunctionKey, DOWN);
|
||||
K(NSPageUpFunctionKey, PAGE_UP);
|
||||
K(NSPageDownFunctionKey, PAGE_DOWN);
|
||||
K(NSHomeFunctionKey, HOME);
|
||||
K(NSEndFunctionKey, END);
|
||||
K(NSPrintFunctionKey, PRINT_SCREEN);
|
||||
case GLFW_KEY_F1 ... GLFW_KEY_F24:
|
||||
*cocoa_key = NSF1FunctionKey + (glfw_key - GLFW_KEY_F1); break;
|
||||
case GLFW_KEY_KP_0 ... GLFW_KEY_KP_9:
|
||||
*cocoa_key = NSEventModifierFlagNumericPad | (0x52 + (glfw_key - GLFW_KEY_KP_0)); break;
|
||||
K((unichar)(0x41|NSEventModifierFlagNumericPad), KP_DECIMAL);
|
||||
K((unichar)(0x43|NSEventModifierFlagNumericPad), KP_MULTIPLY);
|
||||
K((unichar)(0x45|NSEventModifierFlagNumericPad), KP_ADD);
|
||||
K((unichar)(0x4B|NSEventModifierFlagNumericPad), KP_DIVIDE);
|
||||
K((unichar)(0x4E|NSEventModifierFlagNumericPad), KP_SUBTRACT);
|
||||
K((unichar)(0x51|NSEventModifierFlagNumericPad), KP_EQUAL);
|
||||
#undef K
|
||||
}
|
||||
}
|
||||
|
@ -202,6 +202,7 @@ def generate_wrappers(glfw_header, glfw_native_header):
|
||||
void* glfwGetCocoaWindow(GLFWwindow* window)
|
||||
uint32_t glfwGetCocoaMonitor(GLFWmonitor* monitor)
|
||||
GLFWcocoatextinputfilterfun glfwSetCocoaTextInputFilter(GLFWwindow* window, GLFWcocoatextinputfilterfun callback)
|
||||
void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, void* cocoa_key, void* cocoa_mods)
|
||||
void* glfwGetX11Display(void)
|
||||
int32_t glfwGetX11Window(GLFWwindow* window)
|
||||
void glfwSetX11SelectionString(const char* string)
|
||||
|
@ -75,7 +75,7 @@ class DumpCommands: # {{{
|
||||
|
||||
class Boss:
|
||||
|
||||
def __init__(self, os_window_id, opts, args, cached_values):
|
||||
def __init__(self, os_window_id, opts, args, cached_values, new_os_window_trigger):
|
||||
self.window_id_map = WeakValueDictionary()
|
||||
self.startup_colors = {k: opts[k] for k in opts if isinstance(opts[k], Color)}
|
||||
self.pending_sequences = None
|
||||
@ -96,6 +96,9 @@ class Boss:
|
||||
set_boss(self)
|
||||
self.opts, self.args = opts, args
|
||||
startup_session = create_session(opts, args)
|
||||
self.keymap = self.opts.keymap.copy()
|
||||
if new_os_window_trigger is not None:
|
||||
self.keymap.pop(new_os_window_trigger, None)
|
||||
self.add_os_window(startup_session, os_window_id=os_window_id)
|
||||
|
||||
def add_os_window(self, startup_session, os_window_id=None, wclass=None, wname=None, opts_for_size=None, startup_id=None):
|
||||
@ -411,7 +414,7 @@ class Boss:
|
||||
|
||||
def dispatch_special_key(self, key, scancode, action, mods):
|
||||
# Handles shortcuts, return True if the key was consumed
|
||||
key_action = get_shortcut(self.opts.keymap, mods, key, scancode)
|
||||
key_action = get_shortcut(self.keymap, mods, key, scancode)
|
||||
if key_action is None:
|
||||
sequences = get_shortcut(self.opts.sequence_map, mods, key, scancode)
|
||||
if sequences:
|
||||
|
@ -68,6 +68,12 @@ find_app_name(void) {
|
||||
call_boss(edit_config_file, NULL);
|
||||
}
|
||||
|
||||
- (void) new_os_window : (id)sender {
|
||||
(void)sender;
|
||||
call_boss(new_os_window, NULL);
|
||||
}
|
||||
|
||||
|
||||
+ (GlobalMenuTarget *) shared_instance
|
||||
{
|
||||
static GlobalMenuTarget *sharedGlobalMenuTarget = nil;
|
||||
@ -81,6 +87,20 @@ find_app_name(void) {
|
||||
|
||||
@end
|
||||
|
||||
static unichar new_window_key = 0;
|
||||
static NSEventModifierFlags new_window_mods = 0;
|
||||
|
||||
static PyObject*
|
||||
cocoa_set_new_window_trigger(PyObject *self UNUSED, PyObject *args) {
|
||||
int mods, key;
|
||||
if (!PyArg_ParseTuple(args, "ii", &mods, &key)) return NULL;
|
||||
int nwm;
|
||||
get_cocoa_key_equivalent(key, mods, &new_window_key, &nwm);
|
||||
new_window_mods = nwm;
|
||||
if (new_window_key) Py_RETURN_TRUE;
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
cocoa_create_global_menu(void) {
|
||||
NSString* app_name = find_app_name();
|
||||
@ -97,9 +117,19 @@ cocoa_create_global_menu(void) {
|
||||
action:@selector(orderFrontStandardAboutPanel:)
|
||||
keyEquivalent:@""];
|
||||
[appMenu addItem:[NSMenuItem separatorItem]];
|
||||
NSMenuItem* preferences_menu_item = [[NSMenuItem alloc] initWithTitle:@"Preferences..." action:@selector(show_preferences:) keyEquivalent:@","];
|
||||
NSMenuItem* preferences_menu_item = [[NSMenuItem alloc] initWithTitle:@"Preferences..." action:@selector(show_preferences:) keyEquivalent:@","], *new_os_window_menu_item = NULL;
|
||||
[preferences_menu_item setTarget:global_menu_target];
|
||||
[appMenu addItem:preferences_menu_item];
|
||||
if (new_window_key) {
|
||||
NSString *s = [NSString stringWithCharacters:&new_window_key length:1];
|
||||
new_os_window_menu_item = [[NSMenuItem alloc] initWithTitle:@"New OS window" action:@selector(new_os_window:) keyEquivalent:s];
|
||||
[new_os_window_menu_item setKeyEquivalentModifierMask:new_window_mods];
|
||||
[new_os_window_menu_item setTarget:global_menu_target];
|
||||
[appMenu addItem:new_os_window_menu_item];
|
||||
[s release];
|
||||
}
|
||||
|
||||
|
||||
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", app_name]
|
||||
action:@selector(hide:)
|
||||
keyEquivalent:@"h"];
|
||||
@ -150,6 +180,9 @@ cocoa_create_global_menu(void) {
|
||||
[NSApp setWindowsMenu:windowMenu];
|
||||
[windowMenu release];
|
||||
[preferences_menu_item release];
|
||||
if (new_os_window_menu_item) {
|
||||
[new_os_window_menu_item release];
|
||||
}
|
||||
|
||||
[bar release];
|
||||
}
|
||||
@ -239,6 +272,7 @@ cocoa_set_titlebar_color(void *w, color_type titlebar_color)
|
||||
static PyMethodDef module_methods[] = {
|
||||
{"cocoa_get_lang", (PyCFunction)cocoa_get_lang, METH_NOARGS, ""},
|
||||
{"cwd_of_process", (PyCFunction)cwd_of_process, METH_O, ""},
|
||||
{"cocoa_set_new_window_trigger", (PyCFunction)cocoa_set_new_window_trigger, METH_VARARGS, ""},
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
2
kitty/glfw-wrapper.c
generated
2
kitty/glfw-wrapper.c
generated
@ -359,6 +359,8 @@ load_glfw(const char* path) {
|
||||
|
||||
*(void **) (&glfwSetCocoaTextInputFilter_impl) = dlsym(handle, "glfwSetCocoaTextInputFilter");
|
||||
|
||||
*(void **) (&glfwGetCocoaKeyEquivalent_impl) = dlsym(handle, "glfwGetCocoaKeyEquivalent");
|
||||
|
||||
*(void **) (&glfwGetX11Display_impl) = dlsym(handle, "glfwGetX11Display");
|
||||
|
||||
*(void **) (&glfwGetX11Window_impl) = dlsym(handle, "glfwGetX11Window");
|
||||
|
4
kitty/glfw-wrapper.h
generated
4
kitty/glfw-wrapper.h
generated
@ -1836,6 +1836,10 @@ typedef GLFWcocoatextinputfilterfun (*glfwSetCocoaTextInputFilter_func)(GLFWwind
|
||||
glfwSetCocoaTextInputFilter_func glfwSetCocoaTextInputFilter_impl;
|
||||
#define glfwSetCocoaTextInputFilter glfwSetCocoaTextInputFilter_impl
|
||||
|
||||
typedef void (*glfwGetCocoaKeyEquivalent_func)(int, int, void*, void*);
|
||||
glfwGetCocoaKeyEquivalent_func glfwGetCocoaKeyEquivalent_impl;
|
||||
#define glfwGetCocoaKeyEquivalent glfwGetCocoaKeyEquivalent_impl
|
||||
|
||||
typedef void* (*glfwGetX11Display_func)();
|
||||
glfwGetX11Display_func glfwGetX11Display_impl;
|
||||
#define glfwGetX11Display glfwGetX11Display_impl
|
||||
|
@ -799,6 +799,12 @@ set_smallest_allowed_resize(PyObject *self UNUSED, PyObject *args) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
void
|
||||
get_cocoa_key_equivalent(int key, int mods, unsigned short *cocoa_key, int *cocoa_mods) {
|
||||
glfwGetCocoaKeyEquivalent(key, mods, cocoa_key, cocoa_mods);
|
||||
}
|
||||
#endif
|
||||
// Boilerplate {{{
|
||||
|
||||
static PyMethodDef module_methods[] = {
|
||||
|
@ -43,6 +43,15 @@ def init_graphics(debug_keyboard=False):
|
||||
|
||||
|
||||
def _run_app(opts, args):
|
||||
new_os_window_trigger = None
|
||||
if is_macos:
|
||||
for k, v in opts.keymap.items():
|
||||
if v.func == 'new_os_window':
|
||||
new_os_window_trigger = k
|
||||
from .fast_data_types import cocoa_set_new_window_trigger
|
||||
if not cocoa_set_new_window_trigger(*new_os_window_trigger):
|
||||
new_os_window_trigger = None
|
||||
|
||||
with cached_values_for(run_app.cached_values_name) as cached_values:
|
||||
with startup_notification_handler(extra_callback=run_app.first_window_callback) as pre_show_callback:
|
||||
window_id = create_os_window(
|
||||
@ -53,7 +62,7 @@ def _run_app(opts, args):
|
||||
if not is_wayland and not is_macos: # no window icons on wayland
|
||||
with open(logo_data_file, 'rb') as f:
|
||||
set_default_window_icon(f.read(), 256, 256)
|
||||
boss = Boss(window_id, opts, args, cached_values)
|
||||
boss = Boss(window_id, opts, args, cached_values, new_os_window_trigger)
|
||||
boss.start()
|
||||
try:
|
||||
boss.child_monitor.main_loop()
|
||||
|
@ -188,3 +188,6 @@ void send_sprite_to_gpu(FONTS_DATA_HANDLE fg, unsigned int, unsigned int, unsign
|
||||
void set_titlebar_color(OSWindow *w, color_type color);
|
||||
FONTS_DATA_HANDLE load_fonts_data(double, double, double);
|
||||
void send_prerendered_sprites_for_window(OSWindow *w);
|
||||
#ifdef __APPLE__
|
||||
void get_cocoa_key_equivalent(int, int, unsigned short*, int*);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user