From a4170d4b598eb6e97e3f921a7ee2d9ff1dd7c434 Mon Sep 17 00:00:00 2001 From: Petar Dobrev Date: Thu, 9 Apr 2026 10:27:01 +0300 Subject: [PATCH] Added macos_fullscreen_ignore_safe_area_insets option --- glfw/cocoa_window.m | 9 ++++++--- kitty/glfw.c | 2 ++ kitty/options/definition.py | 9 +++++++++ kitty/options/parse.py | 3 +++ kitty/options/to-c-generated.h | 15 +++++++++++++++ kitty/options/types.py | 2 ++ kitty/state.h | 2 +- 7 files changed, 38 insertions(+), 4 deletions(-) diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index baab680ca..20ac6f896 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -3419,6 +3419,7 @@ bool _glfwPlatformToggleFullscreen(_GLFWwindow* w, unsigned int flags) { NSWindow *window = w->ns.object; bool made_fullscreen = true; bool traditional = !(flags & 1); + bool ignore_safe_area_insets = flags & 2; NSWindowStyleMask sm = [window styleMask]; if (traditional) { if (@available(macOS 10.15.7, *)) { @@ -3438,12 +3439,14 @@ bool _glfwPlatformToggleFullscreen(_GLFWwindow* w, unsigned int flags) { [window setStyleMask: NSWindowStyleMaskBorderless]; [[NSApplication sharedApplication] setPresentationOptions: NSApplicationPresentationAutoHideMenuBar | NSApplicationPresentationAutoHideDock]; NSRect screenFrame = [window.screen frame]; - if (@available(macOS 12.0, *)) { - screenFrame.size.height -= window.screen.safeAreaInsets.top; + if (!ignore_safe_area_insets) { + if (@available(macOS 12.0, *)) { + screenFrame.size.height -= window.screen.safeAreaInsets.top; + } } [window setFrame:screenFrame display:YES]; w->ns.in_traditional_fullscreen = true; - _glfwUpdateNotchCover(w); + if (!ignore_safe_area_insets) _glfwUpdateNotchCover(w); } else { made_fullscreen = false; if (sm & NSWindowStyleMaskFullScreen) { diff --git a/kitty/glfw.c b/kitty/glfw.c index 0744615f6..8cc092c05 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -1502,6 +1502,8 @@ toggle_fullscreen_for_os_window(OSWindow *w) { if (!w->is_layer_shell) { #ifdef __APPLE__ if (!OPT(macos_traditional_fullscreen)) return do_toggle_fullscreen(w, 1, false); + unsigned int flags = OPT(macos_fullscreen_ignore_safe_area_insets) ? 2u : 0u; + return do_toggle_fullscreen(w, flags, true); #endif return do_toggle_fullscreen(w, 0, true); } diff --git a/kitty/options/definition.py b/kitty/options/definition.py index 1500c70c9..f3f6f15b2 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -2695,6 +2695,15 @@ pretty. ''' ) +opt('macos_fullscreen_ignore_safe_area_insets', 'no', + option_type='to_bool', ctype='bool', + long_text=''' +When using :opt:`macos_traditional_fullscreen`, ignore the safe area insets on +displays such as MacBook screens with a notch. This allows kitty to use the +full display frame instead of leaving space for the notch area. +''' + ) + opt('macos_show_window_title_in', 'all', choices=('all', 'menubar', 'none', 'window'), ctype='window_title_in', long_text=''' diff --git a/kitty/options/parse.py b/kitty/options/parse.py index f2e6c9024..d856fb549 100644 --- a/kitty/options/parse.py +++ b/kitty/options/parse.py @@ -1094,6 +1094,9 @@ class Parser: def macos_dock_badge_on_bell(self, val: str, ans: dict[str, typing.Any]) -> None: ans['macos_dock_badge_on_bell'] = to_bool(val) + def macos_fullscreen_ignore_safe_area_insets(self, val: str, ans: dict[str, typing.Any]) -> None: + ans['macos_fullscreen_ignore_safe_area_insets'] = to_bool(val) + def macos_hide_from_tasks(self, val: str, ans: dict[str, typing.Any]) -> None: ans['macos_hide_from_tasks'] = to_bool(val) diff --git a/kitty/options/to-c-generated.h b/kitty/options/to-c-generated.h index fdbe17478..1e915155f 100644 --- a/kitty/options/to-c-generated.h +++ b/kitty/options/to-c-generated.h @@ -1396,6 +1396,19 @@ convert_from_opts_macos_thicken_font(PyObject *py_opts, Options *opts) { Py_DECREF(ret); } +static void +convert_from_python_macos_fullscreen_ignore_safe_area_insets(PyObject *val, Options *opts) { + opts->macos_fullscreen_ignore_safe_area_insets = PyObject_IsTrue(val); +} + +static void +convert_from_opts_macos_fullscreen_ignore_safe_area_insets(PyObject *py_opts, Options *opts) { + PyObject *ret = PyObject_GetAttrString(py_opts, "macos_fullscreen_ignore_safe_area_insets"); + if (ret == NULL) return; + convert_from_python_macos_fullscreen_ignore_safe_area_insets(ret, opts); + Py_DECREF(ret); +} + static void convert_from_python_macos_traditional_fullscreen(PyObject *val, Options *opts) { opts->macos_traditional_fullscreen = PyObject_IsTrue(val); @@ -1671,6 +1684,8 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *opts) { if (PyErr_Occurred()) return false; convert_from_opts_macos_hide_from_tasks(py_opts, opts); if (PyErr_Occurred()) return false; + convert_from_opts_macos_fullscreen_ignore_safe_area_insets(py_opts, opts); + if (PyErr_Occurred()) return false; convert_from_opts_macos_quit_when_last_window_closed(py_opts, opts); if (PyErr_Occurred()) return false; convert_from_opts_macos_window_resizable(py_opts, opts); diff --git a/kitty/options/types.py b/kitty/options/types.py index 5faa60c2c..71547ed42 100644 --- a/kitty/options/types.py +++ b/kitty/options/types.py @@ -386,6 +386,7 @@ option_names = ( 'macos_colorspace', 'macos_custom_beam_cursor', 'macos_dock_badge_on_bell', + 'macos_fullscreen_ignore_safe_area_insets', 'macos_hide_from_tasks', 'macos_menubar_title_max_length', 'macos_option_as_alt', @@ -598,6 +599,7 @@ class Options: macos_colorspace: choices_for_macos_colorspace = 'srgb' macos_custom_beam_cursor: bool = False macos_dock_badge_on_bell: bool = True + macos_fullscreen_ignore_safe_area_insets: bool = False macos_hide_from_tasks: bool = False macos_menubar_title_max_length: int = 0 macos_option_as_alt: int = 0 diff --git a/kitty/state.h b/kitty/state.h index 8e737f1c4..e43d4a29e 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -76,7 +76,7 @@ typedef struct Options { monotonic_t repaint_delay, input_delay; bool focus_follows_mouse; unsigned int hide_window_decorations; - bool macos_hide_from_tasks, macos_quit_when_last_window_closed, macos_window_resizable, macos_traditional_fullscreen; + bool macos_hide_from_tasks, macos_quit_when_last_window_closed, macos_window_resizable, macos_traditional_fullscreen, macos_fullscreen_ignore_safe_area_insets; unsigned int macos_option_as_alt; float macos_thicken_font; WindowTitleIn macos_show_window_title_in;