mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-05-13 16:37:27 +00:00
macOS: Fix window shadows not being drawn for transparent windows
Re-organize the whole infrastructure for setting window chrome, doing it in a single function that has access to all settings. Fixes #2827 Fixes #6416
This commit is contained in:
parent
b9bb9248f0
commit
d3f14ffbf4
16 changed files with 249 additions and 183 deletions
|
|
@ -85,6 +85,8 @@ Detailed list of changes
|
|||
|
||||
- Fix a regression in 0.27.0 that broke setting of specific edge padding/margin via remote control (:iss:`6333`)
|
||||
|
||||
- macOS: Fix window shadows not being drawn for transparent windows (:iss:`2827`, :pull:`6416`)
|
||||
|
||||
0.28.1 [2023-04-21]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -26,8 +26,9 @@
|
|||
// It is fine to use C99 in this file because it will not be built with VS
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
#include "../kitty/monotonic.h"
|
||||
#include "glfw3.h"
|
||||
#include "internal.h"
|
||||
|
||||
#include <Availability.h>
|
||||
#import <CoreServices/CoreServices.h>
|
||||
|
|
@ -35,6 +36,7 @@
|
|||
#include <float.h>
|
||||
#include <string.h>
|
||||
|
||||
#define debug(...) if (_glfw.hints.init.debugRendering) fprintf(stderr, __VA_ARGS__);
|
||||
|
||||
GLFWAPI int glfwCocoaSetBackgroundBlur(GLFWwindow *w, int radius);
|
||||
|
||||
|
|
@ -293,6 +295,7 @@ vk_to_unicode_key_with_current_layout(uint16_t keycode)
|
|||
static NSUInteger getStyleMask(_GLFWwindow* window)
|
||||
{
|
||||
NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;
|
||||
if (window->ns.titlebar_hidden) styleMask |= NSWindowStyleMaskFullSizeContentView;
|
||||
|
||||
if (window->monitor || !window->decorated)
|
||||
styleMask |= NSWindowStyleMaskBorderless;
|
||||
|
|
@ -2922,29 +2925,6 @@ GLFWAPI id glfwGetCocoaWindow(GLFWwindow* handle)
|
|||
return window->ns.object;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwHideCocoaTitlebar(GLFWwindow* handle, bool yes) {
|
||||
@autoreleasepool {
|
||||
_GLFWwindow* w = (_GLFWwindow*) handle;
|
||||
NSWindow *window = w->ns.object;
|
||||
w->ns.titlebar_hidden = yes;
|
||||
NSButton *button;
|
||||
button = [window standardWindowButton: NSWindowCloseButton];
|
||||
if (button) button.hidden = yes;
|
||||
button = [window standardWindowButton: NSWindowMiniaturizeButton];
|
||||
if (button) button.hidden = yes;
|
||||
button = [window standardWindowButton: NSWindowZoomButton];
|
||||
[window setTitlebarAppearsTransparent:yes];
|
||||
if (button) button.hidden = yes;
|
||||
if (yes) {
|
||||
[window setTitleVisibility:NSWindowTitleHidden];
|
||||
[window setStyleMask: [window styleMask] | NSWindowStyleMaskFullSizeContentView];
|
||||
} else {
|
||||
[window setTitleVisibility:NSWindowTitleVisible];
|
||||
[window setStyleMask: [window styleMask] & ~NSWindowStyleMaskFullSizeContentView];
|
||||
}
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
GLFWAPI GLFWcocoatextinputfilterfun glfwSetCocoaTextInputFilter(GLFWwindow *handle, GLFWcocoatextinputfilterfun callback) {
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(nil);
|
||||
|
|
@ -2984,6 +2964,92 @@ GLFWAPI int glfwCocoaSetBackgroundBlur(GLFWwindow *w, int radius) {
|
|||
return orig;
|
||||
}
|
||||
|
||||
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;
|
||||
const bool is_transparent = ![window->ns.object isOpaque];
|
||||
if (!is_transparent) { background_opacity = 1.0; background_blur = 0; }
|
||||
NSColor *background = nil;
|
||||
NSAppearance *appearance = nil;
|
||||
bool titlebar_transparent = false;
|
||||
NSWindowStyleMask current_style_mask = [window->ns.object styleMask];
|
||||
bool in_fullscreen = ((current_style_mask & NSWindowStyleMaskFullScreen) != 0) || window->ns.in_traditional_fullscreen;
|
||||
if (use_system_color || background_opacity < 1.0) {
|
||||
if (is_transparent) {
|
||||
// prevent blurring of shadows at window corners with desktop background by setting a low alpha background
|
||||
background = background_blur > 0 ? [NSColor colorWithWhite: 0 alpha: 0.001f] : [NSColor clearColor];
|
||||
} else background = [NSColor clearColor];
|
||||
switch (system_color) {
|
||||
case 1:
|
||||
appearance = [NSAppearance appearanceNamed:NSAppearanceNameVibrantLight]; break;
|
||||
case 2:
|
||||
appearance = [NSAppearance appearanceNamed:NSAppearanceNameVibrantDark]; break;
|
||||
}
|
||||
} else {
|
||||
// set a background color and make the title bar transparent so the background color is visible
|
||||
double red = ((color >> 16) & 0xFF) / 255.0;
|
||||
double green = ((color >> 8) & 0xFF) / 255.0;
|
||||
double blue = (color & 0xFF) / 255.0;
|
||||
double luma = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
|
||||
background = [NSColor colorWithSRGBRed:red green:green blue:blue alpha:1.f];
|
||||
appearance = [NSAppearance appearanceNamed:(luma < 0.5 ? NSAppearanceNameVibrantDark : NSAppearanceNameVibrantLight)];
|
||||
titlebar_transparent = true;
|
||||
}
|
||||
[window->ns.object setBackgroundColor:background];
|
||||
[window->ns.object setAppearance:appearance];
|
||||
glfwCocoaSetBackgroundBlur(w, background_blur);
|
||||
bool has_shadow = false;
|
||||
const char *decorations_desc = "full";
|
||||
window->ns.titlebar_hidden = false;
|
||||
switch (hide_window_decorations) {
|
||||
case 1:
|
||||
decorations_desc = "none";
|
||||
window->decorated = false;
|
||||
break;
|
||||
case 2:
|
||||
decorations_desc = "no-titlebar";
|
||||
window->decorated = true;
|
||||
has_shadow = true;
|
||||
titlebar_transparent = true;
|
||||
window->ns.titlebar_hidden = true;
|
||||
show_text_in_titlebar = false;
|
||||
break;
|
||||
default:
|
||||
window->decorated = true;
|
||||
has_shadow = true;
|
||||
break;
|
||||
}
|
||||
bool hide_titlebar_buttons = !in_fullscreen && window->ns.titlebar_hidden;
|
||||
[window->ns.object setTitlebarAppearsTransparent:titlebar_transparent];
|
||||
[window->ns.object setHasShadow:has_shadow];
|
||||
[window->ns.object setTitleVisibility:(show_text_in_titlebar) ? NSWindowTitleVisible : NSWindowTitleHidden];
|
||||
NSColorSpace *cs = nil;
|
||||
switch (color_space) {
|
||||
case SRGB_COLORSPACE: cs = [NSColorSpace sRGBColorSpace]; break;
|
||||
case DISPLAY_P3_COLORSPACE: cs = [NSColorSpace displayP3ColorSpace]; break;
|
||||
case DEFAULT_COLORSPACE: cs = [NSColorSpace deviceRGBColorSpace]; break;
|
||||
}
|
||||
window->resizable = resizable;
|
||||
[window->ns.object setColorSpace:cs];
|
||||
[[window->ns.object standardWindowButton: NSWindowCloseButton] setHidden:hide_titlebar_buttons];
|
||||
[[window->ns.object standardWindowButton: NSWindowMiniaturizeButton] setHidden:hide_titlebar_buttons];
|
||||
[[window->ns.object standardWindowButton: NSWindowZoomButton] setHidden:hide_titlebar_buttons];
|
||||
debug(
|
||||
"Window Chrome state:\n\tbackground: %s\n\tappearance: %s color_space: %s\n\t"
|
||||
"blur: %d has_shadow: %d resizable: %d decorations: %s (%d)\n\t"
|
||||
"titlebar: transparent: %d title_visibility: %d hidden: %d buttons_hidden: %d"
|
||||
"\n",
|
||||
background ? [background.description UTF8String] : "<nil>",
|
||||
appearance ? [appearance.name UTF8String] : "<nil>",
|
||||
cs ? (cs.localizedName ? [cs.localizedName UTF8String] : [cs.description UTF8String]) : "<nil>",
|
||||
background_blur, has_shadow, resizable, decorations_desc, window->decorated, titlebar_transparent,
|
||||
show_text_in_titlebar, window->ns.titlebar_hidden, hide_titlebar_buttons
|
||||
);
|
||||
window->ns.pre_full_screen_style_mask = getStyleMask(window);
|
||||
[window->ns.object setStyleMask:window->ns.pre_full_screen_style_mask];
|
||||
// HACK: Changing the style mask can cause the first responder to be cleared
|
||||
[window->ns.object makeFirstResponder:window->ns.view];
|
||||
}}
|
||||
|
||||
GLFWAPI int glfwGetCurrentSystemColorTheme(void) {
|
||||
int theme_type = 0;
|
||||
NSAppearance *changedAppearance = NSApp.effectiveAppearance;
|
||||
|
|
|
|||
|
|
@ -239,7 +239,6 @@ def generate_wrappers(glfw_header: str) -> None:
|
|||
functions.append(Function(decl))
|
||||
for line in '''\
|
||||
void* glfwGetCocoaWindow(GLFWwindow* window)
|
||||
void glfwHideCocoaTitlebar(GLFWwindow* window, bool yes)
|
||||
void* glfwGetNSGLContext(GLFWwindow *window)
|
||||
uint32_t glfwGetCocoaMonitor(GLFWmonitor* monitor)
|
||||
GLFWcocoatextinputfilterfun glfwSetCocoaTextInputFilter(GLFWwindow* window, GLFWcocoatextinputfilterfun callback)
|
||||
|
|
@ -254,6 +253,8 @@ def generate_wrappers(glfw_header: str) -> None:
|
|||
void* glfwGetX11Display(void)
|
||||
int32_t glfwGetX11Window(GLFWwindow* window)
|
||||
void glfwSetPrimarySelectionString(GLFWwindow* window, const char* string)
|
||||
void glfwCocoaSetWindowChrome(GLFWwindow* window, 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)
|
||||
const char* glfwGetPrimarySelectionString(GLFWwindow* window, void)
|
||||
int glfwGetNativeKeyForName(const char* key_name, int case_sensitive)
|
||||
void glfwRequestWaylandFrameEvent(GLFWwindow *handle, unsigned long long id, GLFWwaylandframecallbackfunc callback)
|
||||
|
|
|
|||
4
glfw/internal.h
vendored
4
glfw/internal.h
vendored
|
|
@ -92,11 +92,11 @@ typedef int (* _GLFWextensionsupportedfun)(const char*);
|
|||
typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*);
|
||||
typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
|
||||
|
||||
#define GL_VERSION 0x1f02
|
||||
#define GL_VERSION 0x1F02
|
||||
#define GL_NONE 0
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_EXTENSIONS 0x1f03
|
||||
#define GL_EXTENSIONS 0x1F03
|
||||
#define GL_NUM_EXTENSIONS 0x821d
|
||||
#define GL_CONTEXT_FLAGS 0x821e
|
||||
#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ from .fast_data_types import (
|
|||
set_options,
|
||||
set_os_window_size,
|
||||
set_os_window_title,
|
||||
set_window_chrome,
|
||||
thread_write,
|
||||
toggle_fullscreen,
|
||||
toggle_maximized,
|
||||
|
|
@ -1473,6 +1474,7 @@ class Boss:
|
|||
t = tm.tab_for_id(w.tab_id)
|
||||
if t is not None:
|
||||
t.relayout_borders()
|
||||
set_window_chrome(w.os_window_id)
|
||||
|
||||
def dispatch_action(
|
||||
self,
|
||||
|
|
@ -2397,6 +2399,7 @@ class Boss:
|
|||
t = tm.active_tab
|
||||
if t is not None:
|
||||
t.relayout_borders()
|
||||
set_window_chrome(tm.os_window_id)
|
||||
patch_global_colors(spec, configured)
|
||||
|
||||
def apply_new_options(self, opts: Options) -> None:
|
||||
|
|
|
|||
|
|
@ -699,25 +699,6 @@ cocoa_update_menu_bar_title(PyObject *pytitle) {
|
|||
[m release];
|
||||
} // }}}
|
||||
|
||||
bool
|
||||
cocoa_make_window_resizable(void *w, bool resizable) {
|
||||
NSWindow *window = (NSWindow*)w;
|
||||
|
||||
@try {
|
||||
if (resizable) {
|
||||
[window setStyleMask:
|
||||
[window styleMask] | NSWindowStyleMaskResizable];
|
||||
} else {
|
||||
[window setStyleMask:
|
||||
[window styleMask] & ~NSWindowStyleMaskResizable];
|
||||
}
|
||||
} @catch (NSException *e) {
|
||||
log_error("Failed to set style mask: %s: %s", [[e name] UTF8String], [[e reason] UTF8String]);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define NSLeftAlternateKeyMask (0x000020 | NSEventModifierFlagOption)
|
||||
#define NSRightAlternateKeyMask (0x000040 | NSEventModifierFlagOption)
|
||||
|
||||
|
|
@ -813,46 +794,6 @@ cocoa_set_activation_policy(bool hide_from_tasks) {
|
|||
[NSApp setActivationPolicy:(hide_from_tasks ? NSApplicationActivationPolicyAccessory : NSApplicationActivationPolicyRegular)];
|
||||
}
|
||||
|
||||
void
|
||||
cocoa_set_titlebar_appearance(void *w, unsigned int theme)
|
||||
{
|
||||
if (!theme) return;
|
||||
@autoreleasepool {
|
||||
NSWindow *window = (NSWindow*)w;
|
||||
[window setAppearance:[NSAppearance appearanceNamed:((theme == 2) ? NSAppearanceNameVibrantDark : NSAppearanceNameVibrantLight)]];
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
void
|
||||
cocoa_set_titlebar_color(void *w, color_type titlebar_color)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
NSWindow *window = (NSWindow*)w;
|
||||
|
||||
double red = ((titlebar_color >> 16) & 0xFF) / 255.0;
|
||||
double green = ((titlebar_color >> 8) & 0xFF) / 255.0;
|
||||
double blue = (titlebar_color & 0xFF) / 255.0;
|
||||
|
||||
NSColor *background =
|
||||
[NSColor colorWithSRGBRed:red
|
||||
green:green
|
||||
blue:blue
|
||||
alpha:1.0];
|
||||
[window setTitlebarAppearsTransparent:YES];
|
||||
[window setBackgroundColor:background];
|
||||
|
||||
double luma = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
|
||||
|
||||
if (luma < 0.5) {
|
||||
[window setAppearance:[NSAppearance appearanceNamed:NSAppearanceNameVibrantDark]];
|
||||
} else {
|
||||
[window setAppearance:[NSAppearance appearanceNamed:NSAppearanceNameVibrantLight]];
|
||||
}
|
||||
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
cocoa_set_url_handler(PyObject UNUSED *self, PyObject *args) {
|
||||
@autoreleasepool {
|
||||
|
|
@ -969,17 +910,6 @@ cleanup(void) {
|
|||
} // autoreleasepool
|
||||
}
|
||||
|
||||
void
|
||||
cocoa_hide_window_title(void *w)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
NSWindow *window = (NSWindow*)w;
|
||||
[window setTitleVisibility:NSWindowTitleHidden];
|
||||
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
void
|
||||
cocoa_system_beep(const char *path) {
|
||||
if (!path) { NSBeep(); return; }
|
||||
|
|
|
|||
|
|
@ -466,7 +466,7 @@ def init_cell_program() -> None:
|
|||
pass
|
||||
|
||||
|
||||
def set_titlebar_color(os_window_id: int, color: int, use_system_color: bool = False, system_color: int = 0) -> bool:
|
||||
def set_window_chrome(os_window_id: int) -> bool:
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
|||
6
kitty/glfw-wrapper.c
generated
6
kitty/glfw-wrapper.c
generated
|
|
@ -413,9 +413,6 @@ load_glfw(const char* path) {
|
|||
*(void **) (&glfwGetCocoaWindow_impl) = dlsym(handle, "glfwGetCocoaWindow");
|
||||
if (glfwGetCocoaWindow_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
*(void **) (&glfwHideCocoaTitlebar_impl) = dlsym(handle, "glfwHideCocoaTitlebar");
|
||||
if (glfwHideCocoaTitlebar_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
*(void **) (&glfwGetNSGLContext_impl) = dlsym(handle, "glfwGetNSGLContext");
|
||||
if (glfwGetNSGLContext_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
|
|
@ -458,6 +455,9 @@ load_glfw(const char* path) {
|
|||
*(void **) (&glfwSetPrimarySelectionString_impl) = dlsym(handle, "glfwSetPrimarySelectionString");
|
||||
if (glfwSetPrimarySelectionString_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
*(void **) (&glfwCocoaSetWindowChrome_impl) = dlsym(handle, "glfwCocoaSetWindowChrome");
|
||||
if (glfwCocoaSetWindowChrome_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
*(void **) (&glfwGetPrimarySelectionString_impl) = dlsym(handle, "glfwGetPrimarySelectionString");
|
||||
if (glfwGetPrimarySelectionString_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
|
|
|
|||
8
kitty/glfw-wrapper.h
generated
8
kitty/glfw-wrapper.h
generated
|
|
@ -2181,10 +2181,6 @@ typedef void* (*glfwGetCocoaWindow_func)(GLFWwindow*);
|
|||
GFW_EXTERN glfwGetCocoaWindow_func glfwGetCocoaWindow_impl;
|
||||
#define glfwGetCocoaWindow glfwGetCocoaWindow_impl
|
||||
|
||||
typedef void (*glfwHideCocoaTitlebar_func)(GLFWwindow*, bool);
|
||||
GFW_EXTERN glfwHideCocoaTitlebar_func glfwHideCocoaTitlebar_impl;
|
||||
#define glfwHideCocoaTitlebar glfwHideCocoaTitlebar_impl
|
||||
|
||||
typedef void* (*glfwGetNSGLContext_func)(GLFWwindow*);
|
||||
GFW_EXTERN glfwGetNSGLContext_func glfwGetNSGLContext_impl;
|
||||
#define glfwGetNSGLContext glfwGetNSGLContext_impl
|
||||
|
|
@ -2241,6 +2237,10 @@ typedef void (*glfwSetPrimarySelectionString_func)(GLFWwindow*, const char*);
|
|||
GFW_EXTERN glfwSetPrimarySelectionString_func glfwSetPrimarySelectionString_impl;
|
||||
#define glfwSetPrimarySelectionString glfwSetPrimarySelectionString_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
|
||||
|
||||
typedef const char* (*glfwGetPrimarySelectionString_func)(GLFWwindow*);
|
||||
GFW_EXTERN glfwGetPrimarySelectionString_func glfwGetPrimarySelectionString_impl;
|
||||
#define glfwGetPrimarySelectionString glfwGetPrimarySelectionString_impl
|
||||
|
|
|
|||
120
kitty/glfw.c
120
kitty/glfw.c
|
|
@ -15,15 +15,11 @@
|
|||
#ifndef __APPLE__
|
||||
#include "freetype_render_ui_text.h"
|
||||
#endif
|
||||
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_system_beep(const char*);
|
||||
extern void cocoa_set_activation_policy(bool);
|
||||
extern void cocoa_set_titlebar_appearance(void *w, unsigned int theme);
|
||||
extern void cocoa_set_titlebar_color(void *w, color_type color);
|
||||
extern bool cocoa_alt_option_key_pressed(unsigned long);
|
||||
extern void cocoa_toggle_secure_keyboard_entry(void);
|
||||
extern void cocoa_hide(void);
|
||||
|
|
@ -844,16 +840,87 @@ intercept_cocoa_fullscreen(GLFWwindow *w) {
|
|||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
set_titlebar_color(OSWindow *w, color_type color, bool use_system_color, unsigned int system_color UNUSED) {
|
||||
if (w->handle && (!w->last_titlebar_color || (w->last_titlebar_color & 0xffffff) != (color & 0xffffff))) {
|
||||
w->last_titlebar_color = (1 << 24) | (color & 0xffffff);
|
||||
static void
|
||||
init_window_chrome_state(WindowChromeState *s, color_type active_window_bg, bool is_semi_transparent, float background_opacity) {
|
||||
zero_at_ptr(s);
|
||||
const bool should_blur = background_opacity < 1.f && OPT(background_blur) > 0 && is_semi_transparent;
|
||||
#define SET_TCOL(val) \
|
||||
s->use_system_color = false; \
|
||||
switch (val & 0xff) { \
|
||||
case 0: s->use_system_color = true; break; \
|
||||
case 1: s->color = active_window_bg; break; \
|
||||
default: s->color = val >> 8; break; \
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (!use_system_color) cocoa_set_titlebar_color(glfwGetCocoaWindow(w->handle), color);
|
||||
else cocoa_set_titlebar_appearance(glfwGetCocoaWindow(w->handle), system_color);
|
||||
if (OPT(macos_titlebar_color) < 0) {
|
||||
s->use_system_color = true;
|
||||
s->system_color = -OPT(macos_titlebar_color);
|
||||
} else {
|
||||
unsigned long val = OPT(macos_titlebar_color);
|
||||
SET_TCOL(val);
|
||||
}
|
||||
s->macos_colorspace = OPT(macos_colorspace);
|
||||
s->resizable = OPT(macos_window_resizable);
|
||||
#else
|
||||
if (global_state.is_wayland && glfwWaylandSetTitlebarColor) glfwWaylandSetTitlebarColor(w->handle, color, use_system_color);
|
||||
if (global_state.is_wayland) { SET_TCOL(OPT(wayland_titlebar_color)); }
|
||||
#endif
|
||||
s->background_blur = should_blur ? OPT(background_blur) : 0;
|
||||
s->hide_window_decorations = OPT(hide_window_decorations);
|
||||
s->show_title_in_titlebar = (OPT(macos_show_window_title_in) & WINDOW) != 0;
|
||||
s->background_opacity = background_opacity;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
static void
|
||||
apply_window_chrome_state(GLFWwindow *w, WindowChromeState new_state, int width, int height, bool window_decorations_changed) {
|
||||
glfwCocoaSetWindowChrome(w,
|
||||
new_state.color, new_state.use_system_color, new_state.system_color,
|
||||
new_state.background_blur, new_state.hide_window_decorations,
|
||||
new_state.show_title_in_titlebar, new_state.macos_colorspace,
|
||||
new_state.background_opacity, new_state.resizable
|
||||
);
|
||||
// Need to resize the window again after hiding decorations or title bar to take up screen space
|
||||
if (window_decorations_changed) glfwSetWindowSize(w, width, height);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
set_window_chrome(OSWindow *w) {
|
||||
if (!w->handle) return;
|
||||
color_type bg = OPT(background);
|
||||
if (w->num_tabs > w->active_tab) {
|
||||
Tab *tab = w->tabs + w->active_tab;
|
||||
if (tab->num_windows > tab->active_window) {
|
||||
Window *window = tab->windows + tab->active_window;
|
||||
ColorProfile *c;
|
||||
if (window->render_data.screen && (c=window->render_data.screen->color_profile)) {
|
||||
bg = colorprofile_to_color(c, c->overridden.default_bg, c->configured.default_bg).rgb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WindowChromeState new_state;
|
||||
init_window_chrome_state(&new_state, bg, w->is_semi_transparent, w->background_opacity);
|
||||
if (memcmp(&new_state, &w->last_window_chrome, sizeof(WindowChromeState)) != 0) {
|
||||
int width, height;
|
||||
glfwGetWindowSize(w->handle, &width, &height);
|
||||
bool window_decorations_changed = new_state.hide_window_decorations != w->last_window_chrome.hide_window_decorations;
|
||||
#ifdef __APPLE__
|
||||
apply_window_chrome_state(w->handle, new_state, width, height, window_decorations_changed);
|
||||
#else
|
||||
if (window_decorations_changed) {
|
||||
bool hide_window_decorations = new_state.hide_window_decorations & 1;
|
||||
glfwSetWindowAttrib(w->handle, GLFW_DECORATED, !hide_window_decorations);
|
||||
glfwSetWindowSize(w->handle, width, height);
|
||||
}
|
||||
if (global_state.is_wayland) {
|
||||
if (glfwWaylandSetTitlebarColor) glfwWaylandSetTitlebarColor(w->handle, new_state.color, new_state.use_system_color);
|
||||
} else {
|
||||
glfwSetX11WindowBlurred(w->handle, new_state.background_blur > 0);
|
||||
}
|
||||
#endif
|
||||
w->last_window_chrome = new_state;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -886,7 +953,6 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
|||
// We don't use depth and stencil buffers
|
||||
glfwWindowHint(GLFW_DEPTH_BITS, 0);
|
||||
glfwWindowHint(GLFW_STENCIL_BITS, 0);
|
||||
if (OPT(hide_window_decorations) & 1) glfwWindowHint(GLFW_DECORATED, false);
|
||||
glfwSetApplicationCloseCallback(application_close_requested_callback);
|
||||
glfwSetCurrentSelectionCallback(get_current_selection);
|
||||
glfwSetHasCurrentSelectionCallback(has_current_selection);
|
||||
|
|
@ -899,6 +965,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
|||
glfwSetApplicationWillFinishLaunching(cocoa_create_global_menu);
|
||||
#endif
|
||||
}
|
||||
if (OPT(hide_window_decorations) & 1) glfwWindowHint(GLFW_DECORATED, false);
|
||||
|
||||
const bool set_blur = OPT(background_blur) > 0 && OPT(background_opacity) < 1.f;
|
||||
#ifdef __APPLE__
|
||||
|
|
@ -1012,18 +1079,6 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
|||
w->fonts_data = fonts_data;
|
||||
w->shown_once = true;
|
||||
w->last_focused_counter = ++focus_counter;
|
||||
#ifdef __APPLE__
|
||||
if (OPT(hide_window_decorations) & 2) {
|
||||
glfwHideCocoaTitlebar(glfw_window, true);
|
||||
} else if (!(OPT(macos_show_window_title_in) & WINDOW)) {
|
||||
if (glfwGetCocoaWindow) cocoa_hide_window_title(glfwGetCocoaWindow(glfw_window));
|
||||
else log_error("Failed to load glfwGetCocoaWindow");
|
||||
}
|
||||
if (OPT(hide_window_decorations)) {
|
||||
// Need to resize the window again after hiding decorations or title bar to take up screen space
|
||||
glfwSetWindowSize(glfw_window, width, height);
|
||||
}
|
||||
#endif
|
||||
os_window_update_size_increments(w);
|
||||
#ifdef __APPLE__
|
||||
if (OPT(macos_option_as_alt)) glfwSetCocoaTextInputFilter(glfw_window, filter_option);
|
||||
|
|
@ -1033,9 +1088,6 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
|||
if (logo.pixels && logo.width && logo.height) glfwSetWindowIcon(glfw_window, 1, &logo);
|
||||
glfwSetCursor(glfw_window, standard_cursor);
|
||||
update_os_window_viewport(w, false);
|
||||
#ifdef __APPLE__
|
||||
if (glfwGetCocoaWindow) cocoa_make_window_resizable(glfwGetCocoaWindow(glfw_window), OPT(macos_window_resizable));
|
||||
#endif
|
||||
glfwSetWindowPosCallback(glfw_window, window_pos_callback);
|
||||
// missing size callback
|
||||
glfwSetWindowCloseCallback(glfw_window, window_close_callback);
|
||||
|
|
@ -1066,6 +1118,10 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
|||
warned = true;
|
||||
}
|
||||
}
|
||||
init_window_chrome_state(&w->last_window_chrome, OPT(background), w->is_semi_transparent, w->background_opacity);
|
||||
#ifdef __APPLE__
|
||||
apply_window_chrome_state(w->handle, w->last_window_chrome, width, height, OPT(hide_window_decorations) != 0);
|
||||
#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.
|
||||
|
|
@ -1088,16 +1144,6 @@ os_window_update_size_increments(OSWindow *window) {
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
update_background_blur(OSWindow *os_window) {
|
||||
const bool should_blur = os_window->background_opacity < 1.f && OPT(background_blur) > 0 && os_window->is_semi_transparent;
|
||||
#ifdef __APPLE__
|
||||
glfwCocoaSetBackgroundBlur(os_window->handle, should_blur ? OPT(background_blur) : 0);
|
||||
#else
|
||||
if (!global_state.is_wayland) glfwSetX11WindowBlurred(os_window->handle, should_blur);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
static bool
|
||||
window_in_same_cocoa_workspace(void *w, size_t *source_workspaces, size_t source_workspace_count) {
|
||||
|
|
|
|||
|
|
@ -3084,9 +3084,7 @@ egr() # }}}
|
|||
# os {{{
|
||||
agr('os', 'OS specific tweaks')
|
||||
|
||||
opt('wayland_titlebar_color', 'system',
|
||||
option_type='titlebar_color',
|
||||
long_text='''
|
||||
opt('wayland_titlebar_color', 'system', option_type='titlebar_color', ctype='uint', long_text='''
|
||||
The color of the kitty window's titlebar on Wayland systems with client
|
||||
side window decorations such as GNOME. A value of :code:`system` means to use
|
||||
the default system color, a value of :code:`background` means to use the
|
||||
|
|
@ -3095,9 +3093,7 @@ arbitrary color, such as :code:`#12af59` or :code:`red`.
|
|||
'''
|
||||
)
|
||||
|
||||
opt('macos_titlebar_color', 'system',
|
||||
option_type='macos_titlebar_color',
|
||||
long_text='''
|
||||
opt('macos_titlebar_color', 'system', option_type='macos_titlebar_color', ctype='int', long_text='''
|
||||
The color of the kitty window's titlebar on macOS. A value of
|
||||
:code:`system` means to use the default system color, :code:`light` or
|
||||
:code:`dark` can also be used to set it explicitly. A value of
|
||||
|
|
@ -3151,8 +3147,7 @@ opt('macos_window_resizable', 'yes',
|
|||
option_type='to_bool', ctype='bool',
|
||||
long_text='''
|
||||
Disable this if you want kitty top-level OS windows to not be resizable on
|
||||
macOS. Changing this option by reloading the config will only affect newly
|
||||
created OS windows.
|
||||
macOS.
|
||||
'''
|
||||
)
|
||||
|
||||
|
|
|
|||
30
kitty/options/to-c-generated.h
generated
30
kitty/options/to-c-generated.h
generated
|
|
@ -941,6 +941,32 @@ convert_from_opts_allow_hyperlinks(PyObject *py_opts, Options *opts) {
|
|||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_wayland_titlebar_color(PyObject *val, Options *opts) {
|
||||
opts->wayland_titlebar_color = PyLong_AsUnsignedLong(val);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_opts_wayland_titlebar_color(PyObject *py_opts, Options *opts) {
|
||||
PyObject *ret = PyObject_GetAttrString(py_opts, "wayland_titlebar_color");
|
||||
if (ret == NULL) return;
|
||||
convert_from_python_wayland_titlebar_color(ret, opts);
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_macos_titlebar_color(PyObject *val, Options *opts) {
|
||||
opts->macos_titlebar_color = PyLong_AsLong(val);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_opts_macos_titlebar_color(PyObject *py_opts, Options *opts) {
|
||||
PyObject *ret = PyObject_GetAttrString(py_opts, "macos_titlebar_color");
|
||||
if (ret == NULL) return;
|
||||
convert_from_python_macos_titlebar_color(ret, opts);
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_macos_option_as_alt(PyObject *val, Options *opts) {
|
||||
opts->macos_option_as_alt = PyLong_AsUnsignedLong(val);
|
||||
|
|
@ -1204,6 +1230,10 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *opts) {
|
|||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_allow_hyperlinks(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_wayland_titlebar_color(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_macos_titlebar_color(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_macos_option_as_alt(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_macos_hide_from_tasks(py_opts, opts);
|
||||
|
|
|
|||
|
|
@ -516,6 +516,7 @@ set_active_window(id_type os_window_id, id_type tab_id, id_type window_id) {
|
|||
(void)window;
|
||||
tab->active_window = w;
|
||||
osw->needs_render = true;
|
||||
set_window_chrome(osw);
|
||||
END_WITH_WINDOW;
|
||||
}
|
||||
|
||||
|
|
@ -877,14 +878,11 @@ PYWRAP1(run_with_activation_token) {
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PYWRAP1(set_titlebar_color) {
|
||||
PYWRAP1(set_window_chrome) {
|
||||
id_type os_window_id;
|
||||
unsigned int color;
|
||||
int use_system_color = 0;
|
||||
unsigned int system_color = 0;
|
||||
PA("KI|pI", &os_window_id, &color, &use_system_color, &system_color);
|
||||
PA("K", &os_window_id);
|
||||
WITH_OS_WINDOW(os_window_id)
|
||||
set_titlebar_color(os_window, color, use_system_color, system_color);
|
||||
set_window_chrome(os_window);
|
||||
Py_RETURN_TRUE;
|
||||
END_WITH_OS_WINDOW
|
||||
Py_RETURN_FALSE;
|
||||
|
|
@ -1093,7 +1091,6 @@ PYWRAP0(apply_options_update) {
|
|||
get_platform_dependent_config_values(os_window->handle);
|
||||
os_window->background_opacity = OPT(background_opacity);
|
||||
os_window->is_damaged = true;
|
||||
update_background_blur(os_window);
|
||||
for (size_t t = 0; t < os_window->num_tabs; t++) {
|
||||
Tab *tab = os_window->tabs + t;
|
||||
for (size_t w = 0; w < tab->num_windows; w++) {
|
||||
|
|
@ -1363,7 +1360,7 @@ static PyMethodDef module_methods[] = {
|
|||
MW(mark_os_window_for_close, METH_VARARGS),
|
||||
MW(set_application_quit_request, METH_VARARGS),
|
||||
MW(current_application_quit_request, METH_NOARGS),
|
||||
MW(set_titlebar_color, METH_VARARGS),
|
||||
MW(set_window_chrome, METH_VARARGS),
|
||||
MW(focus_os_window, METH_VARARGS),
|
||||
MW(mark_tab_bar_dirty, METH_O),
|
||||
MW(run_with_activation_token, METH_O),
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ typedef struct {
|
|||
} underline_position, underline_thickness, strikethrough_position, strikethrough_thickness, cell_width, cell_height, baseline;
|
||||
bool show_hyperlink_targets;
|
||||
int background_blur;
|
||||
long macos_titlebar_color;
|
||||
unsigned long wayland_titlebar_color;
|
||||
} Options;
|
||||
|
||||
typedef struct WindowLogoRenderData {
|
||||
|
|
@ -186,6 +188,17 @@ typedef struct {
|
|||
unsigned int width, height, num_of_resize_events;
|
||||
} LiveResizeInfo;
|
||||
|
||||
typedef struct WindowChromeState {
|
||||
color_type color;
|
||||
bool use_system_color;
|
||||
unsigned system_color;
|
||||
int background_blur;
|
||||
unsigned hide_window_decorations;
|
||||
bool show_title_in_titlebar;
|
||||
bool resizable;
|
||||
int macos_colorspace;
|
||||
float background_opacity;
|
||||
} WindowChromeState;
|
||||
|
||||
typedef struct {
|
||||
void *handle;
|
||||
|
|
@ -218,7 +231,7 @@ typedef struct {
|
|||
LiveResizeInfo live_resize;
|
||||
bool has_pending_resizes, is_semi_transparent, shown_once, is_damaged;
|
||||
unsigned int clear_count;
|
||||
color_type last_titlebar_color;
|
||||
WindowChromeState last_window_chrome;
|
||||
float background_opacity;
|
||||
FONTS_DATA_HANDLE fonts_data;
|
||||
id_type temp_font_group_id;
|
||||
|
|
@ -301,7 +314,7 @@ void send_image_to_gpu(uint32_t*, const void*, int32_t, int32_t, bool, bool, boo
|
|||
void send_sprite_to_gpu(FONTS_DATA_HANDLE fg, unsigned int, unsigned int, unsigned int, pixel*);
|
||||
void blank_canvas(float, color_type);
|
||||
void blank_os_window(OSWindow *);
|
||||
void set_titlebar_color(OSWindow *w, color_type color, bool use_system_color, unsigned int system_color);
|
||||
void set_window_chrome(OSWindow *w);
|
||||
FONTS_DATA_HANDLE load_fonts_data(double, double, double);
|
||||
void send_prerendered_sprites_for_window(OSWindow *w);
|
||||
#ifdef __APPLE__
|
||||
|
|
@ -366,4 +379,3 @@ void update_ime_position(Window* w, Screen *screen);
|
|||
bool update_ime_position_for_window(id_type window_id, bool force, int update_focus);
|
||||
void set_ignore_os_keyboard_processing(bool enabled);
|
||||
void update_menu_bar_title(PyObject *title UNUSED);
|
||||
void update_background_blur(OSWindow *);
|
||||
|
|
|
|||
|
|
@ -167,9 +167,10 @@ class Tab: # {{{
|
|||
self._set_current_layout(self.enabled_layouts[0])
|
||||
self.relayout()
|
||||
|
||||
def apply_options(self) -> None:
|
||||
def apply_options(self, is_active: bool) -> None:
|
||||
aw = self.active_window
|
||||
for window in self:
|
||||
window.apply_options()
|
||||
window.apply_options(is_active and aw is window)
|
||||
self.set_enabled_layouts(get_options().enabled_layouts)
|
||||
|
||||
def take_over_from(self, other_tab: 'Tab') -> None:
|
||||
|
|
@ -287,15 +288,12 @@ class Tab: # {{{
|
|||
def relayout_borders(self) -> None:
|
||||
tm = self.tab_manager_ref()
|
||||
if tm is not None:
|
||||
w = self.active_window
|
||||
ly = self.current_layout
|
||||
self.borders(
|
||||
all_windows=self.windows,
|
||||
current_layout=ly, tab_bar_rects=tm.tab_bar_rects,
|
||||
draw_window_borders=(ly.needs_window_borders and self.windows.num_visble_groups > 1) or ly.must_draw_borders
|
||||
)
|
||||
if w is not None:
|
||||
w.change_titlebar_color()
|
||||
|
||||
def create_layout_object(self, name: str) -> Layout:
|
||||
return create_layout_object_for(name, self.os_window_id, self.id)
|
||||
|
|
@ -1218,8 +1216,9 @@ class TabManager: # {{{
|
|||
del self.tabs
|
||||
|
||||
def apply_options(self) -> None:
|
||||
at = self.active_tab
|
||||
for tab in self:
|
||||
tab.apply_options()
|
||||
tab.apply_options(at is tab)
|
||||
self.tab_bar_hidden = get_options().tab_bar_style == 'hidden'
|
||||
self.tab_bar.apply_options()
|
||||
self.update_tab_bar_data()
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ from .constants import (
|
|||
appname,
|
||||
clear_handled_signals,
|
||||
config_dir,
|
||||
is_macos,
|
||||
wakeup_io_loop,
|
||||
)
|
||||
from .fast_data_types import (
|
||||
|
|
@ -70,7 +69,6 @@ from .fast_data_types import (
|
|||
mouse_selection,
|
||||
move_cursor_to_mouse_if_in_prompt,
|
||||
pt_to_px,
|
||||
set_titlebar_color,
|
||||
set_window_logo,
|
||||
set_window_padding,
|
||||
set_window_render_data,
|
||||
|
|
@ -619,10 +617,9 @@ class Window:
|
|||
val = round(val)
|
||||
return int(val)
|
||||
|
||||
def apply_options(self) -> None:
|
||||
def apply_options(self, is_active: bool) -> None:
|
||||
opts = get_options()
|
||||
self.update_effective_padding()
|
||||
self.change_titlebar_color()
|
||||
setup_colors(self.screen, opts)
|
||||
|
||||
@property
|
||||
|
|
@ -1018,18 +1015,6 @@ class Window:
|
|||
tab.relayout_borders()
|
||||
tab.on_bell(self)
|
||||
|
||||
def change_titlebar_color(self) -> None:
|
||||
opts = get_options()
|
||||
val = opts.macos_titlebar_color if is_macos else opts.wayland_titlebar_color
|
||||
if val > 0:
|
||||
if (val & 0xff) == 1:
|
||||
val = self.screen.color_profile.default_bg
|
||||
else:
|
||||
val = val >> 8
|
||||
set_titlebar_color(self.os_window_id, val)
|
||||
else:
|
||||
set_titlebar_color(self.os_window_id, 0, True, -val)
|
||||
|
||||
def change_colors(self, changes: Dict[DynamicColor, Optional[str]]) -> None:
|
||||
dirtied = default_bg_changed = False
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue