diff --git a/kitty/cocoa_window.m b/kitty/cocoa_window.m index fe7e9640f..fa404b87a 100644 --- a/kitty/cocoa_window.m +++ b/kitty/cocoa_window.m @@ -390,6 +390,12 @@ cocoa_focus_window(void *w) { [window makeKeyWindow]; } +long +cocoa_window_number(void *w) { + NSWindow *window = (NSWindow*)w; + return [window windowNumber]; +} + size_t cocoa_get_workspace_ids(void *w, size_t *workspace_ids, size_t array_sz) { NSWindow *window = (NSWindow*)w; diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index f34310379..e69d7fa8a 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -781,6 +781,10 @@ def x11_window_id(os_window_id: int) -> int: pass +def cocoa_window_id(os_window_id: int) -> int: + pass + + def swap_tabs(os_window_id: int, a: int, b: int) -> None: pass diff --git a/kitty/glfw.c b/kitty/glfw.c index 9587bdcb9..0fd2a20ce 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -11,6 +11,7 @@ #include "glfw-wrapper.h" extern bool cocoa_make_window_resizable(void *w, bool); extern void cocoa_focus_window(void *w); +extern long cocoa_window_number(void *w); extern void cocoa_create_global_menu(void); extern void cocoa_hide_window_title(void *w); extern void cocoa_hide_titlebar(void *w); @@ -1023,18 +1024,35 @@ x11_display(PYNOARG) { Py_RETURN_NONE; } +static OSWindow* +find_os_window(PyObject *os_wid) { + id_type os_window_id = PyLong_AsUnsignedLongLong(os_wid); + for (size_t i = 0; i < global_state.num_os_windows; i++) { + OSWindow *w = global_state.os_windows + i; + if (w->id == os_window_id) return w; + } + return NULL; +} + static PyObject* x11_window_id(PyObject UNUSED *self, PyObject *os_wid) { - if (glfwGetX11Window) { - id_type os_window_id = PyLong_AsUnsignedLongLong(os_wid); - for (size_t i = 0; i < global_state.num_os_windows; i++) { - OSWindow *w = global_state.os_windows + i; - if (w->id == os_window_id) return Py_BuildValue("l", (long)glfwGetX11Window(w->handle)); - } - } - else { PyErr_SetString(PyExc_RuntimeError, "Failed to load glfwGetX11Window"); return NULL; } - PyErr_SetString(PyExc_ValueError, "No OSWindow with the specified id found"); + OSWindow *w = find_os_window(os_wid); + if (!w) { PyErr_SetString(PyExc_ValueError, "No OSWindow with the specified id found"); return NULL; } + if (!glfwGetX11Window) { PyErr_SetString(PyExc_RuntimeError, "Failed to load glfwGetX11Window"); return NULL; } + return Py_BuildValue("l", (long)glfwGetX11Window(w->handle)); +} + +static PyObject* +cocoa_window_id(PyObject UNUSED *self, PyObject *os_wid) { + OSWindow *w = find_os_window(os_wid); + if (!w) { PyErr_SetString(PyExc_ValueError, "No OSWindow with the specified id found"); return NULL; } + if (!glfwGetCocoaWindow) { PyErr_SetString(PyExc_RuntimeError, "Failed to load glfwGetCocoaWindow"); return NULL; } +#ifdef __APPLE__ + return Py_BuildValue("l", (long)cocoa_window_number(glfwGetCocoaWindow(w->handle))); +#else + PyErr_SetString(PyExc_RuntimeError, "cocoa_window_id() is only supported on Mac"); return NULL; +#endif } static PyObject* @@ -1218,6 +1236,7 @@ static PyMethodDef module_methods[] = { #ifndef __APPLE__ METHODB(dbus_send_notification, METH_VARARGS), #endif + METHODB(cocoa_window_id, METH_O), {"glfw_init", (PyCFunction)glfw_init, METH_VARARGS, ""}, {"glfw_terminate", (PyCFunction)glfw_terminate, METH_NOARGS, ""}, {"glfw_get_physical_dpi", (PyCFunction)glfw_get_physical_dpi, METH_NOARGS, ""}, diff --git a/kitty/tabs.py b/kitty/tabs.py index 452adfbab..adb1b5b96 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -17,7 +17,7 @@ from .child import Child from .cli_stub import CLIOptions from .constants import appname, is_macos, is_wayland from .fast_data_types import ( - add_tab, attach_window, detach_window, get_boss, mark_tab_bar_dirty, + add_tab, attach_window, cocoa_window_id, detach_window, get_boss, mark_tab_bar_dirty, next_window_id, remove_tab, remove_window, ring_bell, set_active_tab, set_active_window, swap_tabs, sync_os_window_title, x11_window_id ) @@ -283,7 +283,13 @@ class Tab: # {{{ if env: fenv.update(env) fenv['KITTY_WINDOW_ID'] = str(next_window_id()) - if not is_macos and not is_wayland(): + if is_macos: + try: + fenv['WINDOWID'] = str(cocoa_window_id(self.os_window_id)) + except Exception: + import traceback + traceback.print_exc() + elif not is_wayland(): try: fenv['WINDOWID'] = str(x11_window_id(self.os_window_id)) except Exception: