From 81f144df155f6079c2cfa4f80f4524d65863211d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 25 Feb 2021 11:54:53 +0530 Subject: [PATCH] macOS: Add entries to global menu bar for creating and changing tabs --- kitty/child-monitor.c | 3 ++ kitty/cocoa_window.m | 65 +++++++++++++++++++++++-------------------- kitty/config_data.py | 4 +-- kitty/main.py | 2 +- kitty/state.h | 5 +++- 5 files changed, 45 insertions(+), 34 deletions(-) diff --git a/kitty/child-monitor.c b/kitty/child-monitor.c index 4550040ea..a98b0827d 100644 --- a/kitty/child-monitor.c +++ b/kitty/child-monitor.c @@ -982,6 +982,9 @@ process_global_state(void *data) { if (cocoa_pending_actions & NEW_OS_WINDOW) { call_boss(new_os_window, NULL); } if (cocoa_pending_actions & CLOSE_OS_WINDOW) { call_boss(close_os_window, NULL); } if (cocoa_pending_actions & CLOSE_TAB) { call_boss(close_tab, NULL); } + if (cocoa_pending_actions & NEW_TAB) { call_boss(new_tab, NULL); } + if (cocoa_pending_actions & NEXT_TAB) { call_boss(next_tab, NULL); } + if (cocoa_pending_actions & PREVIOUS_TAB) { call_boss(previous_tab, NULL); } if (cocoa_pending_actions_wd) { if (cocoa_pending_actions & NEW_OS_WINDOW_WITH_WD) { call_boss(new_os_window_with_wd, "s", cocoa_pending_actions_wd); } if (cocoa_pending_actions & NEW_TAB_WITH_WD) { call_boss(new_tab_with_wd, "s", cocoa_pending_actions_wd); } diff --git a/kitty/cocoa_window.m b/kitty/cocoa_window.m index 1da0c5b54..f840d1678 100644 --- a/kitty/cocoa_window.m +++ b/kitty/cocoa_window.m @@ -77,7 +77,7 @@ find_app_name(void) { @implementation GlobalMenuTarget -- (void)show_preferences:(id)sender { +- (void)edit_config_file:(id)sender { (void)sender; set_cocoa_pending_action(PREFERENCES_WINDOW, NULL); } @@ -97,6 +97,21 @@ find_app_name(void) { set_cocoa_pending_action(CLOSE_TAB, NULL); } +- (void)new_tab:(id)sender { + (void)sender; + set_cocoa_pending_action(NEW_TAB, NULL); +} + +- (void)next_tab:(id)sender { + (void)sender; + set_cocoa_pending_action(NEXT_TAB, NULL); +} + +- (void)previous_tab:(id)sender { + (void)sender; + set_cocoa_pending_action(PREVIOUS_TAB, NULL); +} + - (void)open_kitty_website_url:(id)sender { (void)sender; [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://sw.kovidgoyal.net/kitty/"]]; @@ -122,6 +137,7 @@ typedef struct { } GlobalShortcut; typedef struct { GlobalShortcut new_os_window, close_os_window, close_tab, edit_config_file; + GlobalShortcut previous_tab, next_tab, new_tab; } GlobalShortcuts; static GlobalShortcuts global_shortcuts; @@ -132,10 +148,10 @@ cocoa_set_global_shortcut(PyObject *self UNUSED, PyObject *args) { const char *name; if (!PyArg_ParseTuple(args, "siI", &name, &mods, &key)) return NULL; GlobalShortcut *gs = NULL; - if (strcmp(name, "new_os_window") == 0) gs = &global_shortcuts.new_os_window; - else if (strcmp(name, "close_os_window") == 0) gs = &global_shortcuts.close_os_window; - else if (strcmp(name, "close_tab") == 0) gs = &global_shortcuts.close_tab; - else if (strcmp(name, "edit_config_file") == 0) gs = &global_shortcuts.edit_config_file; +#define Q(x) if (strcmp(name, #x) == 0) gs = &global_shortcuts.x + Q(new_os_window); else Q(close_os_window); else Q(close_tab); else Q(edit_config_file); + else Q(new_tab); else Q(next_tab); else Q(previous_tab); +#undef Q if (gs == NULL) { PyErr_SetString(PyExc_KeyError, "Unknown shortcut name"); return NULL; } int cocoa_mods; get_cocoa_key_equivalent(key, mods, gs->key, 32, &cocoa_mods); @@ -362,6 +378,12 @@ cocoa_create_global_menu(void) { GlobalMenuTarget *global_menu_target = [GlobalMenuTarget shared_instance]; [NSApp setMainMenu:bar]; +#define MENU_ITEM(menu, title, name) { \ + NSMenuItem *__mi = [menu addItemWithTitle:title action:@selector(name:) keyEquivalent:@(global_shortcuts.name.key)]; \ + [__mi setKeyEquivalentModifierMask:global_shortcuts.name.mods]; \ + [__mi setTarget:global_menu_target]; \ +} + NSMenuItem* appMenuItem = [bar addItemWithTitle:@"" action:NULL @@ -373,19 +395,8 @@ cocoa_create_global_menu(void) { action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; [appMenu addItem:[NSMenuItem separatorItem]]; - NSMenuItem *preferences_menu_item = [appMenu addItemWithTitle:@"Preferences..." - action:@selector(show_preferences:) - keyEquivalent:@(global_shortcuts.edit_config_file.key)]; - [preferences_menu_item setKeyEquivalentModifierMask:global_shortcuts.edit_config_file.mods]; - [preferences_menu_item setTarget:global_menu_target]; - - NSMenuItem* new_os_window_menu_item = - [appMenu addItemWithTitle:@"New OS window" - action:@selector(new_os_window:) - keyEquivalent:@(global_shortcuts.new_os_window.key)]; - [new_os_window_menu_item setKeyEquivalentModifierMask:global_shortcuts.new_os_window.mods]; - [new_os_window_menu_item setTarget:global_menu_target]; - + MENU_ITEM(appMenu, @"Preferences…", edit_config_file); + MENU_ITEM(appMenu, @"New OS window", new_os_window); [appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", app_name] action:@selector(hide:) @@ -432,18 +443,11 @@ cocoa_create_global_menu(void) { keyEquivalent:@""]; [windowMenu addItem:[NSMenuItem separatorItem]]; - NSMenuItem* close_tab_item = - [windowMenu addItemWithTitle:@"Close Tab" - action:@selector(close_tab:) - keyEquivalent:@(global_shortcuts.close_tab.key)]; - [close_tab_item setKeyEquivalentModifierMask:global_shortcuts.close_tab.mods]; - [close_tab_item setTarget:global_menu_target]; - NSMenuItem* close_os_window_menu_item = - [windowMenu addItemWithTitle:@"Close OS Window" - action:@selector(close_os_window:) - keyEquivalent:@(global_shortcuts.close_os_window.key)]; - [close_os_window_menu_item setKeyEquivalentModifierMask:global_shortcuts.close_os_window.mods]; - [close_os_window_menu_item setTarget:global_menu_target]; + MENU_ITEM(windowMenu, @"New Tab", new_tab); + MENU_ITEM(windowMenu, @"Show Previous Tab", previous_tab); + MENU_ITEM(windowMenu, @"Show Next Tab", next_tab); + MENU_ITEM(windowMenu, @"Close Tab", close_tab); + MENU_ITEM(windowMenu, @"Close OS Window", close_os_window); [windowMenu addItem:[NSMenuItem separatorItem]]; [[windowMenu addItemWithTitle:@"Enter Full Screen" @@ -475,6 +479,7 @@ cocoa_create_global_menu(void) { [NSApp setServicesProvider:[[[ServiceProvider alloc] init] autorelease]]; +#undef MENU_ITEM } void diff --git a/kitty/config_data.py b/kitty/config_data.py index 1a44b9b05..aec8636d2 100644 --- a/kitty/config_data.py +++ b/kitty/config_data.py @@ -1492,12 +1492,12 @@ if is_macos: g('shortcuts.tab') # {{{ k('next_tab', 'kitty_mod+right', 'next_tab', _('Next tab')) if is_macos: - k('next_tab', 'ctrl+tab', 'next_tab', _('Next tab'), add_to_docs=False) k('next_tab', 'shift+cmd+]', 'next_tab', _('Next tab'), add_to_docs=False) + k('next_tab', 'ctrl+tab', 'next_tab', _('Next tab'), add_to_docs=False) k('previous_tab', 'kitty_mod+left', 'previous_tab', _('Previous tab')) if is_macos: - k('previous_tab', 'shift+ctrl+tab', 'previous_tab', _('Previous tab'), add_to_docs=False) k('previous_tab', 'shift+cmd+[', 'previous_tab', _('Previous tab'), add_to_docs=False) + k('previous_tab', 'shift+ctrl+tab', 'previous_tab', _('Previous tab'), add_to_docs=False) k('new_tab', 'kitty_mod+t', 'new_tab', _('New tab')) if is_macos: k('new_tab', 'cmd+t', 'new_tab', _('New tab'), add_to_docs=False) diff --git a/kitty/main.py b/kitty/main.py index 1f27cf759..0846e7d27 100644 --- a/kitty/main.py +++ b/kitty/main.py @@ -130,7 +130,7 @@ def set_x11_window_icon() -> None: def _run_app(opts: OptionsStub, args: CLIOptions, bad_lines: Sequence[BadLine] = ()) -> None: global_shortcuts: Dict[str, SingleKey] = {} if is_macos: - for ac in ('new_os_window', 'close_os_window', 'close_tab', 'edit_config_file'): + for ac in ('new_os_window', 'close_os_window', 'close_tab', 'edit_config_file', 'previous_tab', 'next_tab', 'new_tab'): val = get_macos_shortcut_for(opts, ac) if val is not None: global_shortcuts[ac] = val diff --git a/kitty/state.h b/kitty/state.h index bd9011139..2421756e9 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -266,7 +266,10 @@ typedef enum { NEW_OS_WINDOW_WITH_WD = 4, NEW_TAB_WITH_WD = 8, CLOSE_OS_WINDOW = 16, - CLOSE_TAB = 32 + CLOSE_TAB = 32, + NEW_TAB = 64, + NEXT_TAB = 128, + PREVIOUS_TAB = 256 } CocoaPendingAction; void set_cocoa_pending_action(CocoaPendingAction action, const char*); #endif