mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-06-27 19:31:46 +00:00
wip: MacOS-specific config settings
This commit is contained in:
parent
511cb7b0b9
commit
8c32f093bb
16 changed files with 171 additions and 37 deletions
|
|
@ -2577,6 +2577,71 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||
window->ns.object = nil;
|
||||
}
|
||||
|
||||
static bool
|
||||
ns_window_level_constant(const char *name, long *val) {
|
||||
#define C(x) if (strcmp(name, #x) == 0) { *val = (long)x; return true; }
|
||||
C(NSNormalWindowLevel); C(NSFloatingWindowLevel); C(NSSubmenuWindowLevel); C(NSTornOffMenuWindowLevel);
|
||||
C(NSMainMenuWindowLevel); C(NSStatusWindowLevel); C(NSModalPanelWindowLevel); C(NSPopUpMenuWindowLevel);
|
||||
C(NSScreenSaverWindowLevel);
|
||||
C(kCGBaseWindowLevel); C(kCGMinimumWindowLevel); C(kCGDesktopWindowLevel); C(kCGBackstopMenuLevel);
|
||||
C(kCGNormalWindowLevel); C(kCGFloatingWindowLevel); C(kCGTornOffMenuWindowLevel); C(kCGDockWindowLevel);
|
||||
C(kCGMainMenuWindowLevel); C(kCGStatusWindowLevel); C(kCGModalPanelWindowLevel); C(kCGPopUpMenuWindowLevel);
|
||||
C(kCGDraggingWindowLevel); C(kCGScreenSaverWindowLevel); C(kCGMaximumWindowLevel); C(kCGOverlayWindowLevel);
|
||||
C(kCGHelpWindowLevel); C(kCGUtilityWindowLevel); C(kCGDesktopIconWindowLevel); C(kCGAssistiveTechHighWindowLevel);
|
||||
C(kCGCursorWindowLevel); C(kCGNumberOfWindowLevelKeys);
|
||||
#undef C
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_ns_window_level_term(const char **spec, long *val) {
|
||||
const char *s = *spec;
|
||||
while (isspace(*s)) s++;
|
||||
if (!*s) return false;
|
||||
if (*s == '+' || *s == '-' || isdigit(*s)) {
|
||||
errno = 0;
|
||||
char *end = NULL;
|
||||
long v = strtol(s, &end, 0);
|
||||
if (end == s || errno) return false;
|
||||
*val = v; *spec = end;
|
||||
return true;
|
||||
}
|
||||
char name[96]; size_t i = 0;
|
||||
while ((isalnum(*s) || *s == '_') && i + 1 < sizeof(name)) name[i++] = *s++;
|
||||
name[i] = '\0';
|
||||
if (!i || !ns_window_level_constant(name, val)) return false;
|
||||
*spec = s;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_ns_window_level(const char *spec, NSWindowLevel *level) {
|
||||
const char *original = spec;
|
||||
if (!spec) return false;
|
||||
while (isspace(*spec)) spec++;
|
||||
if (!*spec || strcmp(spec, "unset") == 0) return false;
|
||||
long total = 0;
|
||||
if (!parse_ns_window_level_term(&spec, &total)) goto invalid;
|
||||
while (true) {
|
||||
while (isspace(*spec)) spec++;
|
||||
if (!*spec) { *level = (NSWindowLevel)total; return true; }
|
||||
char op = *spec++;
|
||||
if (op != '+' && op != '-') goto invalid;
|
||||
long term = 0;
|
||||
if (!parse_ns_window_level_term(&spec, &term)) goto invalid;
|
||||
total = op == '+' ? total + term : total - term;
|
||||
}
|
||||
invalid:
|
||||
_glfwInputError(GLFW_INVALID_VALUE, "Cocoa: Invalid macOS NSWindow layer expression: %s", original);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
apply_ns_window_layer(_GLFWwindow *window, const char *spec) {
|
||||
NSWindowLevel level = 0;
|
||||
if (parse_ns_window_level(spec, &level)) [window->ns.object setLevel:level];
|
||||
}
|
||||
|
||||
static NSScreen*
|
||||
screen_for_window_center(_GLFWwindow *window) {
|
||||
NSRect windowFrame = [window->ns.object frame];
|
||||
|
|
@ -2681,9 +2746,9 @@ _glfwPlatformSetLayerShellConfig(_GLFWwindow* window, const GLFWLayerShellConfig
|
|||
double spacing_y = top_edge_spacing + bottom_edge_spacing;
|
||||
const unsigned xsz = config.x_size_in_pixels ? (unsigned)(config.x_size_in_pixels * xscale) : (cell_width * config.x_size_in_cells);
|
||||
const unsigned ysz = config.y_size_in_pixels ? (unsigned)(config.y_size_in_pixels * yscale) : (cell_height * config.y_size_in_cells);
|
||||
NSRect placement_frame = config.use_physical_screen_frame ? screen.frame : screen.visibleFrame;
|
||||
NSRect placement_frame = config.related.use_physical_screen_frame ? screen.frame : screen.visibleFrame;
|
||||
CGFloat dock_height = NSMinY(screen.visibleFrame) - NSMinY(screen.frame);
|
||||
CGFloat menubar_height = config.use_physical_screen_frame ? 0 : NSHeight(screen.frame) - NSHeight(screen.visibleFrame) - dock_height;
|
||||
CGFloat menubar_height = config.related.use_physical_screen_frame ? 0 : NSHeight(screen.frame) - NSHeight(screen.visibleFrame) - dock_height;
|
||||
CGFloat x = NSMinX(placement_frame), y = NSMinY(placement_frame) - 1, width = NSWidth(placement_frame), height = NSHeight(placement_frame) + 2;
|
||||
if (config.type == GLFW_LAYER_SHELL_BACKGROUND || config.edge == GLFW_EDGE_CENTER) {
|
||||
x = NSMinX(screen.frame); height = NSHeight(screen.frame) - menubar_height + 1; y = NSMinY(screen.frame); width = NSWidth(screen.frame);
|
||||
|
|
@ -2698,7 +2763,6 @@ _glfwPlatformSetLayerShellConfig(_GLFWwindow* window, const GLFWLayerShellConfig
|
|||
// See: https://stackoverflow.com/questions/4982584/how-do-i-draw-the-desktop-on-mac-os-x/4982619#4982619
|
||||
level = kCGDesktopWindowLevel;
|
||||
break;
|
||||
case GLFW_LAYER_SHELL_DESKTOP_SHELL: level = kCGBackstopMenuLevel; break;
|
||||
case GLFW_LAYER_SHELL_OVERLAY: case GLFW_LAYER_SHELL_NONE: break;
|
||||
case GLFW_LAYER_SHELL_PANEL: level = NSNormalWindowLevel - 1; break;
|
||||
case GLFW_LAYER_SHELL_TOP: level--; break;
|
||||
|
|
@ -2737,6 +2801,7 @@ _glfwPlatformSetLayerShellConfig(_GLFWwindow* window, const GLFWLayerShellConfig
|
|||
|
||||
[nswindow setAnimationBehavior:animation_behavior];
|
||||
[nswindow setLevel:level];
|
||||
apply_ns_window_layer(window, config.related.ns_window_layer);
|
||||
[nswindow setCollectionBehavior: (NSWindowCollectionBehaviorCanJoinAllSpaces | NSWindowCollectionBehaviorStationary | NSWindowCollectionBehaviorIgnoresCycle)];
|
||||
[nswindow setFrame:NSMakeRect(x, y, width, height) display:YES];
|
||||
return true;
|
||||
|
|
@ -4036,6 +4101,12 @@ apply_window_corner_curve(_GLFWwindow *window) {
|
|||
|
||||
|
||||
|
||||
GLFWAPI void glfwCocoaSetWindowLevel(GLFWwindow *w, const char *level_spec) { @autoreleasepool {
|
||||
_GLFWwindow* window = (_GLFWwindow*)w;
|
||||
apply_ns_window_layer(window, level_spec);
|
||||
}}
|
||||
|
||||
|
||||
GLFWAPI void glfwCocoaSetWindowChrome(GLFWwindow *w, unsigned int color, bool use_system_color, unsigned int system_color, int background_blur, unsigned int hide_window_decorations, bool show_text_in_titlebar, int color_space, float background_opacity, bool resizable) { @autoreleasepool {
|
||||
_GLFWwindow* window = (_GLFWwindow*)w;
|
||||
if (window->ns.layer_shell.is_active) return;
|
||||
|
|
|
|||
7
glfw/glfw3.h
vendored
7
glfw/glfw3.h
vendored
|
|
@ -1349,7 +1349,7 @@ typedef struct GLFWkeyevent
|
|||
bool fake_event_on_focus_change;
|
||||
} GLFWkeyevent;
|
||||
|
||||
typedef enum { GLFW_LAYER_SHELL_NONE, GLFW_LAYER_SHELL_BACKGROUND, GLFW_LAYER_SHELL_PANEL, GLFW_LAYER_SHELL_TOP, GLFW_LAYER_SHELL_DESKTOP_SHELL, GLFW_LAYER_SHELL_OVERLAY } GLFWLayerShellType;
|
||||
typedef enum { GLFW_LAYER_SHELL_NONE, GLFW_LAYER_SHELL_BACKGROUND, GLFW_LAYER_SHELL_PANEL, GLFW_LAYER_SHELL_TOP, GLFW_LAYER_SHELL_OVERLAY } GLFWLayerShellType;
|
||||
|
||||
typedef enum { GLFW_EDGE_TOP, GLFW_EDGE_BOTTOM, GLFW_EDGE_LEFT, GLFW_EDGE_RIGHT, GLFW_EDGE_CENTER, GLFW_EDGE_NONE, GLFW_EDGE_CENTER_SIZED } GLFWEdge;
|
||||
|
||||
|
|
@ -1368,12 +1368,13 @@ typedef struct GLFWLayerShellConfig {
|
|||
unsigned x_size_in_cells, x_size_in_pixels;
|
||||
unsigned y_size_in_cells, y_size_in_pixels;
|
||||
int requested_top_margin, requested_left_margin, requested_bottom_margin, requested_right_margin;
|
||||
int requested_exclusive_zone, hide_on_focus_loss, use_physical_screen_frame;
|
||||
int requested_exclusive_zone, hide_on_focus_loss;
|
||||
unsigned override_exclusive_zone;
|
||||
void (*size_callback)(GLFWwindow *window, float xscale, float yscale, unsigned *cell_width, unsigned *cell_height, double *left_edge_spacing, double *top_edge_spacing, double *right_edge_spacing, double *bottom_edge_spacing);
|
||||
struct { float xscale, yscale; } expected;
|
||||
struct {
|
||||
float background_opacity; int background_blur, color_space;
|
||||
float background_opacity; int background_blur, color_space, use_physical_screen_frame;
|
||||
char ns_window_layer[128];
|
||||
} related;
|
||||
} GLFWLayerShellConfig;
|
||||
|
||||
|
|
|
|||
3
glfw/wl_window.c
vendored
3
glfw/wl_window.c
vendored
|
|
@ -1020,7 +1020,7 @@ get_layer_shell_layer(const _GLFWwindow *window) {
|
|||
case GLFW_LAYER_SHELL_BACKGROUND: case GLFW_LAYER_SHELL_NONE: break;
|
||||
case GLFW_LAYER_SHELL_PANEL: which_layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM; break;
|
||||
case GLFW_LAYER_SHELL_TOP: which_layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP; break;
|
||||
case GLFW_LAYER_SHELL_DESKTOP_SHELL: case GLFW_LAYER_SHELL_OVERLAY: which_layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY; break;
|
||||
case GLFW_LAYER_SHELL_OVERLAY: which_layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY; break;
|
||||
}
|
||||
return which_layer;
|
||||
}
|
||||
|
|
@ -1043,7 +1043,6 @@ layer_set_properties(const _GLFWwindow *window, bool during_creation, uint32_t w
|
|||
case GLFW_LAYER_SHELL_NONE: break;
|
||||
case GLFW_LAYER_SHELL_BACKGROUND: exclusive_zone = -1; break;
|
||||
case GLFW_LAYER_SHELL_TOP:
|
||||
case GLFW_LAYER_SHELL_DESKTOP_SHELL:
|
||||
case GLFW_LAYER_SHELL_OVERLAY:
|
||||
case GLFW_LAYER_SHELL_PANEL:
|
||||
switch (config.edge) {
|
||||
|
|
|
|||
4
glfw/x11_window.c
vendored
4
glfw/x11_window.c
vendored
|
|
@ -644,7 +644,7 @@ calculate_layer_geometry(_GLFWwindow *window) {
|
|||
double xsz = config.x_size_in_pixels ? (unsigned)(config.x_size_in_pixels * xscale) : (cell_width * config.x_size_in_cells);
|
||||
double ysz = config.y_size_in_pixels ? (unsigned)(config.y_size_in_pixels * yscale) : (cell_height * config.y_size_in_cells);
|
||||
ans.width = (int)(1. + spacing_x + xsz); ans.height = (int)(1. + spacing_y + ysz);
|
||||
GeometryRect m = config.type == GLFW_LAYER_SHELL_TOP || config.type == GLFW_LAYER_SHELL_DESKTOP_SHELL || config.type == GLFW_LAYER_SHELL_OVERLAY ? mg.workarea : mg.full;
|
||||
GeometryRect m = config.type == GLFW_LAYER_SHELL_TOP || config.type == GLFW_LAYER_SHELL_OVERLAY ? mg.workarea : mg.full;
|
||||
static const struct {
|
||||
unsigned left, right, top, bottom, left_start_y, left_end_y, right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x, bottom_end_x;
|
||||
} s = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
|
||||
|
|
@ -762,7 +762,7 @@ update_wm_hints(_GLFWwindow *window, const WindowGeometry *wg, const _GLFWwndcon
|
|||
// i3 does not support NET_WM_STATE_BELOW but panels work without it
|
||||
if (_glfw.x11.NET_WM_STATE_BELOW) { S(NET_WM_STATE_BELOW); }
|
||||
break;
|
||||
case GLFW_LAYER_SHELL_TOP: case GLFW_LAYER_SHELL_DESKTOP_SHELL: case GLFW_LAYER_SHELL_OVERLAY: S(NET_WM_STATE_ABOVE); break;
|
||||
case GLFW_LAYER_SHELL_TOP: case GLFW_LAYER_SHELL_OVERLAY: S(NET_WM_STATE_ABOVE); break;
|
||||
}
|
||||
#undef S
|
||||
} else if (wndconfig) {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ from kitty.fast_data_types import (
|
|||
GLFW_LAYER_SHELL_BACKGROUND,
|
||||
GLFW_LAYER_SHELL_OVERLAY,
|
||||
GLFW_LAYER_SHELL_PANEL,
|
||||
GLFW_LAYER_SHELL_DESKTOP_SHELL,
|
||||
GLFW_LAYER_SHELL_TOP,
|
||||
layer_shell_config_for_os_window,
|
||||
set_layer_shell_config,
|
||||
|
|
@ -70,7 +69,6 @@ def layer_shell_config(opts: PanelCLIOptions) -> LayerShellConfig:
|
|||
'background': GLFW_LAYER_SHELL_BACKGROUND,
|
||||
'bottom': GLFW_LAYER_SHELL_PANEL,
|
||||
'top': GLFW_LAYER_SHELL_TOP,
|
||||
'shell': GLFW_LAYER_SHELL_DESKTOP_SHELL,
|
||||
'overlay': GLFW_LAYER_SHELL_OVERLAY
|
||||
}.get(opts.layer, GLFW_LAYER_SHELL_PANEL)
|
||||
ltype = GLFW_LAYER_SHELL_BACKGROUND if opts.edge == 'background' else ltype
|
||||
|
|
@ -96,7 +94,6 @@ def layer_shell_config(opts: PanelCLIOptions) -> LayerShellConfig:
|
|||
requested_exclusive_zone=opts.exclusive_zone,
|
||||
override_exclusive_zone=opts.override_exclusive_zone,
|
||||
hide_on_focus_loss=opts.hide_on_focus_loss,
|
||||
use_physical_screen_frame=opts.use_physical_screen_frame,
|
||||
output_name=opts.output_name or '')
|
||||
|
||||
|
||||
|
|
@ -115,8 +112,7 @@ def cli_option_to_lsc_configs_map() -> MappingProxyType[str, tuple[str, ...]]:
|
|||
'focus_policy': ('focus_policy',),
|
||||
'exclusive_zone': ('requested_exclusive_zone',),
|
||||
'override_exclusive_zone': ('override_exclusive_zone',),
|
||||
'hide_on_focus_loss': ('hide_on_focus_loss',),
|
||||
'use_physical_screen_frame': ('use_physical_screen_frame',)
|
||||
'hide_on_focus_loss': ('hide_on_focus_loss',)
|
||||
})
|
||||
|
||||
|
||||
|
|
|
|||
3
kitty/glfw-wrapper.c
generated
3
kitty/glfw-wrapper.c
generated
|
|
@ -497,6 +497,9 @@ load_glfw(const char* path) {
|
|||
*(void **) (&glfwCocoaCycleThroughOSWindows_impl) = dlsym(handle, "glfwCocoaCycleThroughOSWindows");
|
||||
if (glfwCocoaCycleThroughOSWindows_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
*(void **) (&glfwCocoaSetWindowLevel_impl) = dlsym(handle, "glfwCocoaSetWindowLevel");
|
||||
if (glfwCocoaSetWindowLevel_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
*(void **) (&glfwCocoaSetWindowChrome_impl) = dlsym(handle, "glfwCocoaSetWindowChrome");
|
||||
if (glfwCocoaSetWindowChrome_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
|
|
|
|||
11
kitty/glfw-wrapper.h
generated
11
kitty/glfw-wrapper.h
generated
|
|
@ -1077,7 +1077,7 @@ typedef struct GLFWkeyevent
|
|||
bool fake_event_on_focus_change;
|
||||
} GLFWkeyevent;
|
||||
|
||||
typedef enum { GLFW_LAYER_SHELL_NONE, GLFW_LAYER_SHELL_BACKGROUND, GLFW_LAYER_SHELL_PANEL, GLFW_LAYER_SHELL_TOP, GLFW_LAYER_SHELL_DESKTOP_SHELL, GLFW_LAYER_SHELL_OVERLAY } GLFWLayerShellType;
|
||||
typedef enum { GLFW_LAYER_SHELL_NONE, GLFW_LAYER_SHELL_BACKGROUND, GLFW_LAYER_SHELL_PANEL, GLFW_LAYER_SHELL_TOP, GLFW_LAYER_SHELL_OVERLAY } GLFWLayerShellType;
|
||||
|
||||
typedef enum { GLFW_EDGE_TOP, GLFW_EDGE_BOTTOM, GLFW_EDGE_LEFT, GLFW_EDGE_RIGHT, GLFW_EDGE_CENTER, GLFW_EDGE_NONE, GLFW_EDGE_CENTER_SIZED } GLFWEdge;
|
||||
|
||||
|
|
@ -1096,12 +1096,13 @@ typedef struct GLFWLayerShellConfig {
|
|||
unsigned x_size_in_cells, x_size_in_pixels;
|
||||
unsigned y_size_in_cells, y_size_in_pixels;
|
||||
int requested_top_margin, requested_left_margin, requested_bottom_margin, requested_right_margin;
|
||||
int requested_exclusive_zone, hide_on_focus_loss, use_physical_screen_frame;
|
||||
int requested_exclusive_zone, hide_on_focus_loss;
|
||||
unsigned override_exclusive_zone;
|
||||
void (*size_callback)(GLFWwindow *window, float xscale, float yscale, unsigned *cell_width, unsigned *cell_height, double *left_edge_spacing, double *top_edge_spacing, double *right_edge_spacing, double *bottom_edge_spacing);
|
||||
struct { float xscale, yscale; } expected;
|
||||
struct {
|
||||
float background_opacity; int background_blur, color_space;
|
||||
float background_opacity; int background_blur, color_space, use_physical_screen_frame;
|
||||
char ns_window_layer[128];
|
||||
} related;
|
||||
} GLFWLayerShellConfig;
|
||||
|
||||
|
|
@ -2478,6 +2479,10 @@ typedef void (*glfwCocoaCycleThroughOSWindows_func)(bool);
|
|||
GFW_EXTERN glfwCocoaCycleThroughOSWindows_func glfwCocoaCycleThroughOSWindows_impl;
|
||||
#define glfwCocoaCycleThroughOSWindows glfwCocoaCycleThroughOSWindows_impl
|
||||
|
||||
typedef void (*glfwCocoaSetWindowLevel_func)(GLFWwindow*, const char*);
|
||||
GFW_EXTERN glfwCocoaSetWindowLevel_func glfwCocoaSetWindowLevel_impl;
|
||||
#define glfwCocoaSetWindowLevel glfwCocoaSetWindowLevel_impl
|
||||
|
||||
typedef void (*glfwCocoaSetWindowChrome_func)(GLFWwindow*, unsigned int, bool, unsigned int, int, unsigned int, bool, int, float, bool);
|
||||
GFW_EXTERN glfwCocoaSetWindowChrome_func glfwCocoaSetWindowChrome_impl;
|
||||
#define glfwCocoaSetWindowChrome glfwCocoaSetWindowChrome_impl
|
||||
|
|
|
|||
12
kitty/glfw.c
12
kitty/glfw.c
|
|
@ -182,6 +182,9 @@ set_layer_shell_config_for(OSWindow *w, GLFWLayerShellConfig *lsc) {
|
|||
lsc->related.background_opacity = effective_os_window_alpha(w);
|
||||
lsc->related.background_blur = OPT(background_blur);
|
||||
lsc->related.color_space = OPT(macos_colorspace);
|
||||
lsc->related.use_physical_screen_frame = OPT(macos_use_physical_screen_frame);
|
||||
if (OPT(macos_ns_window_layer)) snprintf(lsc->related.ns_window_layer, sizeof(lsc->related.ns_window_layer), "%s", OPT(macos_ns_window_layer));
|
||||
else lsc->related.ns_window_layer[0] = '\0';
|
||||
w->hide_on_focus_loss = lsc->hide_on_focus_loss;
|
||||
}
|
||||
return glfwSetLayerShellConfig(w->handle, lsc);
|
||||
|
|
@ -1372,7 +1375,7 @@ toggle_fullscreen_for_os_window(OSWindow *w) {
|
|||
if (!prev) return false;
|
||||
GLFWLayerShellConfig lsc;
|
||||
memcpy(&lsc, prev, sizeof(lsc));
|
||||
if (prev->type == GLFW_LAYER_SHELL_OVERLAY || prev->type == GLFW_LAYER_SHELL_DESKTOP_SHELL || prev->type == GLFW_LAYER_SHELL_TOP) {
|
||||
if (prev->type == GLFW_LAYER_SHELL_OVERLAY || prev->type == GLFW_LAYER_SHELL_TOP) {
|
||||
if (prev->was_toggled_to_fullscreen) {
|
||||
lsc.edge = prev->previous.edge;
|
||||
lsc.requested_bottom_margin = prev->previous.requested_bottom_margin;
|
||||
|
|
@ -1642,7 +1645,6 @@ layer_shell_config_to_python(const GLFWLayerShellConfig *c) {
|
|||
A(requested_right_margin, fl);
|
||||
A(requested_exclusive_zone, fl);
|
||||
A(hide_on_focus_loss, b)
|
||||
A(use_physical_screen_frame, b)
|
||||
A(override_exclusive_zone, b);
|
||||
#undef A
|
||||
#undef fl
|
||||
|
|
@ -1670,7 +1672,6 @@ layer_shell_config_from_python(PyObject *p, GLFWLayerShellConfig *ans) {
|
|||
A(requested_exclusive_zone, PyLong_Check, PyLong_AsLong);
|
||||
A(override_exclusive_zone, PyBool_Check, PyLong_AsLong);
|
||||
A(hide_on_focus_loss, PyBool_Check, PyLong_AsLong);
|
||||
A(use_physical_screen_frame, PyBool_Check, PyLong_AsLong);
|
||||
#undef A
|
||||
#define A(attr) { \
|
||||
RAII_PyObject(attr, PyObject_GetAttrString(p, #attr)); if (attr == NULL) return false; \
|
||||
|
|
@ -1924,6 +1925,9 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
|||
if (global_state.is_apple) set_layer_shell_config_for(w, lsc);
|
||||
} else apply_window_chrome_state(
|
||||
w->handle, w->last_window_chrome, width, height, global_state.is_apple ? OPT(hide_window_decorations) != 0 : false);
|
||||
#ifdef __APPLE__
|
||||
if (!w->is_layer_shell) glfwCocoaSetWindowLevel(w->handle, OPT(macos_ns_window_layer));
|
||||
#endif
|
||||
// Update window state
|
||||
// We do not call glfwWindowHint to set GLFW_MAXIMIZED before the window is created.
|
||||
// That would cause the window to be set to maximize immediately after creation and use the wrong initial size when restored.
|
||||
|
|
@ -3262,7 +3266,7 @@ init_glfw(PyObject *m) {
|
|||
ADDC(GLFW_REPEAT);
|
||||
ADDC(true); ADDC(false);
|
||||
ADDC(GLFW_PRIMARY_SELECTION); ADDC(GLFW_CLIPBOARD);
|
||||
ADDC(GLFW_LAYER_SHELL_NONE); ADDC(GLFW_LAYER_SHELL_PANEL); ADDC(GLFW_LAYER_SHELL_BACKGROUND); ADDC(GLFW_LAYER_SHELL_TOP); ADDC(GLFW_LAYER_SHELL_DESKTOP_SHELL); ADDC(GLFW_LAYER_SHELL_OVERLAY);
|
||||
ADDC(GLFW_LAYER_SHELL_NONE); ADDC(GLFW_LAYER_SHELL_PANEL); ADDC(GLFW_LAYER_SHELL_BACKGROUND); ADDC(GLFW_LAYER_SHELL_TOP); ADDC(GLFW_LAYER_SHELL_OVERLAY);
|
||||
ADDC(GLFW_FOCUS_NOT_ALLOWED); ADDC(GLFW_FOCUS_EXCLUSIVE); ADDC(GLFW_FOCUS_ON_DEMAND);
|
||||
ADDC(GLFW_EDGE_TOP); ADDC(GLFW_EDGE_BOTTOM); ADDC(GLFW_EDGE_LEFT); ADDC(GLFW_EDGE_RIGHT); ADDC(GLFW_EDGE_CENTER); ADDC(GLFW_EDGE_NONE);
|
||||
ADDC(GLFW_EDGE_CENTER_SIZED);
|
||||
|
|
|
|||
|
|
@ -2724,6 +2724,27 @@ full display frame instead of leaving space for the notch area.
|
|||
'''
|
||||
)
|
||||
|
||||
opt('macos_use_physical_screen_frame', 'no',
|
||||
option_type='to_bool', ctype='bool',
|
||||
long_text='''
|
||||
Use the physical screen frame instead of the visible frame when placing macOS
|
||||
desktop panels such as those created by :code:`kitty +kitten panel`. This allows
|
||||
panels to draw in areas normally reserved for the native menu bar or Dock.
|
||||
'''
|
||||
)
|
||||
|
||||
opt('macos_ns_window_layer', 'unset',
|
||||
option_type='str', ctype='!macos_ns_window_layer',
|
||||
long_text='''
|
||||
Set the macOS NSWindow level for newly created OS windows. The default value
|
||||
:code:`unset` leaves kitty's normal window-level handling unchanged. Values can
|
||||
be integer window levels, AppKit/CoreGraphics window-level constant names, or
|
||||
simple arithmetic expressions combining them with integers. For example:
|
||||
:code:`NSFloatingWindowLevel`, :code:`kCGBackstopMenuLevel`,
|
||||
:code:`NSPopUpMenuWindowLevel - 1`.
|
||||
'''
|
||||
)
|
||||
|
||||
opt('macos_show_window_title_in', 'all',
|
||||
choices=('all', 'menubar', 'none', 'window'), ctype='window_title_in',
|
||||
long_text='''
|
||||
|
|
|
|||
6
kitty/options/parse.py
generated
6
kitty/options/parse.py
generated
|
|
@ -1112,6 +1112,9 @@ class Parser:
|
|||
def macos_menubar_title_max_length(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['macos_menubar_title_max_length'] = positive_int(val)
|
||||
|
||||
def macos_ns_window_layer(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['macos_ns_window_layer'] = str(val)
|
||||
|
||||
def macos_option_as_alt(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['macos_option_as_alt'] = macos_option_as_alt(val)
|
||||
|
||||
|
|
@ -1135,6 +1138,9 @@ class Parser:
|
|||
def macos_traditional_fullscreen(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['macos_traditional_fullscreen'] = to_bool(val)
|
||||
|
||||
def macos_use_physical_screen_frame(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['macos_use_physical_screen_frame'] = to_bool(val)
|
||||
|
||||
def macos_window_resizable(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['macos_window_resizable'] = to_bool(val)
|
||||
|
||||
|
|
|
|||
30
kitty/options/to-c-generated.h
generated
30
kitty/options/to-c-generated.h
generated
|
|
@ -1435,6 +1435,32 @@ convert_from_opts_macos_fullscreen_ignore_safe_area_insets(PyObject *py_opts, Op
|
|||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_macos_use_physical_screen_frame(PyObject *val, Options *opts) {
|
||||
opts->macos_use_physical_screen_frame = PyObject_IsTrue(val);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_opts_macos_use_physical_screen_frame(PyObject *py_opts, Options *opts) {
|
||||
PyObject *ret = PyObject_GetAttrString(py_opts, "macos_use_physical_screen_frame");
|
||||
if (ret == NULL) return;
|
||||
convert_from_python_macos_use_physical_screen_frame(ret, opts);
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_macos_ns_window_layer(PyObject *val, Options *opts) {
|
||||
macos_ns_window_layer(val, opts);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_opts_macos_ns_window_layer(PyObject *py_opts, Options *opts) {
|
||||
PyObject *ret = PyObject_GetAttrString(py_opts, "macos_ns_window_layer");
|
||||
if (ret == NULL) return;
|
||||
convert_from_python_macos_ns_window_layer(ret, opts);
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_macos_show_window_title_in(PyObject *val, Options *opts) {
|
||||
opts->macos_show_window_title_in = window_title_in(val);
|
||||
|
|
@ -1709,6 +1735,10 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *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_use_physical_screen_frame(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_macos_ns_window_layer(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_macos_show_window_title_in(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_macos_menubar_title_max_length(py_opts, opts);
|
||||
|
|
|
|||
|
|
@ -206,6 +206,9 @@ bell_path(PyObject *src, Options *opts) { STR_SETTER(bell_path); }
|
|||
static inline void
|
||||
bell_theme(PyObject *src, Options *opts) { STR_SETTER(bell_theme); }
|
||||
|
||||
static inline void
|
||||
macos_ns_window_layer(PyObject *src, Options *opts) { STR_SETTER(macos_ns_window_layer); }
|
||||
|
||||
static inline void
|
||||
window_logo_path(PyObject *src, Options *opts) { STR_SETTER(default_window_logo); }
|
||||
|
||||
|
|
@ -604,6 +607,6 @@ free_allocs_in_options(Options *opts) {
|
|||
free_background_images(opts);
|
||||
#define F(x) free(opts->x); opts->x = NULL;
|
||||
F(select_by_word_characters); F(url_excluded_characters); F(select_by_word_characters_forward);
|
||||
F(bell_path); F(bell_theme); F(default_window_logo);
|
||||
F(bell_path); F(bell_theme); F(macos_ns_window_layer); F(default_window_logo);
|
||||
#undef F
|
||||
}
|
||||
|
|
|
|||
4
kitty/options/types.py
generated
4
kitty/options/types.py
generated
|
|
@ -391,12 +391,14 @@ option_names = (
|
|||
'macos_fullscreen_ignore_safe_area_insets',
|
||||
'macos_hide_from_tasks',
|
||||
'macos_menubar_title_max_length',
|
||||
'macos_ns_window_layer',
|
||||
'macos_option_as_alt',
|
||||
'macos_quit_when_last_window_closed',
|
||||
'macos_show_window_title_in',
|
||||
'macos_thicken_font',
|
||||
'macos_titlebar_color',
|
||||
'macos_traditional_fullscreen',
|
||||
'macos_use_physical_screen_frame',
|
||||
'macos_window_resizable',
|
||||
'map',
|
||||
'map_timeout',
|
||||
|
|
@ -605,12 +607,14 @@ class Options:
|
|||
macos_fullscreen_ignore_safe_area_insets: bool = False
|
||||
macos_hide_from_tasks: bool = False
|
||||
macos_menubar_title_max_length: int = 0
|
||||
macos_ns_window_layer: str = 'unset'
|
||||
macos_option_as_alt: int = 0
|
||||
macos_quit_when_last_window_closed: bool = False
|
||||
macos_show_window_title_in: choices_for_macos_show_window_title_in = 'all'
|
||||
macos_thicken_font: float = 0
|
||||
macos_titlebar_color: int = 0
|
||||
macos_traditional_fullscreen: bool = False
|
||||
macos_use_physical_screen_frame: bool = False
|
||||
macos_window_resizable: bool = True
|
||||
map_timeout: float = 0
|
||||
mark1_background: Color = Color(152, 211, 203)
|
||||
|
|
|
|||
|
|
@ -573,7 +573,7 @@ panel_defaults = {
|
|||
'edge': 'top', 'layer': 'bottom', 'override': '', 'cls': f'{appname}-panel',
|
||||
'focus_policy': 'not-allowed', 'exclusive_zone': '-1', 'override_exclusive_zone': 'no',
|
||||
'single_instance': 'no', 'instance_group': '', 'toggle_visibility': 'no',
|
||||
'start_as_hidden': 'no', 'detach': 'no', 'detached_log': '', 'use_physical_screen_frame': 'no',
|
||||
'start_as_hidden': 'no', 'detach': 'no', 'detached_log': '',
|
||||
}
|
||||
|
||||
def build_panel_cli_spec(defaults: dict[str, str]) -> str:
|
||||
|
|
@ -639,20 +639,12 @@ that the panel is centered instead of in the top left corner and the margins hav
|
|||
|
||||
|
||||
--layer
|
||||
choices=background,bottom,top,shell,overlay
|
||||
choices=background,bottom,top,overlay
|
||||
default={layer}
|
||||
On a Wayland compositor that supports the wlr layer shell protocol, specifies the layer
|
||||
on which the panel should be drawn. This parameter is ignored and set to
|
||||
:code:`background` if :option:`--edge` is set to :code:`background`. On macOS, maps
|
||||
these to appropriate NSWindow *levels*. On macOS, :code:`shell` places the panel
|
||||
above normal application windows but below native system UI such as the menu bar.
|
||||
|
||||
|
||||
--use-physical-screen-frame
|
||||
type=bool-set
|
||||
default={use_physical_screen_frame}
|
||||
On macOS, use the physical screen frame rather than the visible frame when placing the panel.
|
||||
This allows panels to draw in areas reserved for the native menu bar or dock. Ignored on other platforms.
|
||||
these to appropriate NSWindow *levels*.
|
||||
|
||||
|
||||
--config -c
|
||||
|
|
|
|||
|
|
@ -78,11 +78,11 @@ typedef struct Options {
|
|||
bool on_cross, on_drop;
|
||||
} 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, macos_fullscreen_ignore_safe_area_insets;
|
||||
bool macos_hide_from_tasks, macos_quit_when_last_window_closed, macos_window_resizable, macos_traditional_fullscreen, macos_fullscreen_ignore_safe_area_insets, macos_use_physical_screen_frame;
|
||||
unsigned int macos_option_as_alt;
|
||||
float macos_thicken_font;
|
||||
WindowTitleIn macos_show_window_title_in;
|
||||
char *bell_path, *bell_theme;
|
||||
char *bell_path, *bell_theme, *macos_ns_window_layer;
|
||||
float background_opacity, dim_opacity;
|
||||
|
||||
ScrollbarVisibilityPolicy scrollbar;
|
||||
|
|
|
|||
|
|
@ -85,7 +85,6 @@ class LayerShellConfig(NamedTuple):
|
|||
requested_exclusive_zone: int = -1
|
||||
override_exclusive_zone: bool = False
|
||||
hide_on_focus_loss: bool = False
|
||||
use_physical_screen_frame: bool = False
|
||||
|
||||
|
||||
def mod_to_names(mods: int, has_kitty_mod: bool = False, kitty_mod: int = 0) -> Iterator[str]:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue