Only use window occlusion on platforms where it is supported

This commit is contained in:
Kovid Goyal 2025-02-12 12:02:46 +05:30
parent 2cf83070a0
commit 50f64d5981
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
14 changed files with 42 additions and 22 deletions

View file

@ -107,8 +107,8 @@ Detailed list of changes
many cells to render a piece of text in (:iss:`8226`)
- **Behavior change**: The :opt:`notify_on_cmd_finish` option now uses OS
Window visibility instead of focus state when set to ``invisible``
(:iss:`8320`)
Window visibility instead of focus state when set to ``invisible`` on
platforms that support querying OS window visibility (:iss:`8320`)
- launch: Add options :option:`launch --source-window` and :option:`launch --next-to` to allow
specifying which window is used as the data source and destination location independently of the

View file

@ -791,10 +791,11 @@ GLFWAPI GLFWapplicationwillfinishlaunchingfun glfwSetApplicationWillFinishLaunch
return previous;
}
int _glfwPlatformInit(void)
int _glfwPlatformInit(bool *supports_window_occlusion)
{
@autoreleasepool {
*supports_window_occlusion = true;
_glfw.ns.helper = [[GLFWHelper alloc] init];
[NSThread detachNewThreadSelector:@selector(doNothing:)

2
glfw/glfw3.h vendored
View file

@ -1964,7 +1964,7 @@ typedef struct GLFWgamepadstate
*
* @ingroup init
*/
GLFWAPI int glfwInit(monotonic_t start_time);
GLFWAPI int glfwInit(monotonic_t start_time, bool *supports_window_occlusion);
GLFWAPI void glfwRunMainLoop(GLFWtickcallback callback, void *callback_data);
GLFWAPI void glfwStopMainLoop(void);
GLFWAPI unsigned long long glfwAddTimer(monotonic_t interval, bool repeats, GLFWuserdatafun callback, void * callback_data, GLFWuserdatafun free_callback);

5
glfw/init.c vendored
View file

@ -223,8 +223,9 @@ _glfwDebug(const char *format, ...) {
////// GLFW public API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI int glfwInit(monotonic_t start_time)
GLFWAPI int glfwInit(monotonic_t start_time, bool *supports_window_occlusion)
{
*supports_window_occlusion = false;
if (_glfw.initialized)
return true;
monotonic_start_time = start_time;
@ -233,7 +234,7 @@ GLFWAPI int glfwInit(monotonic_t start_time)
_glfw.hints.init = _glfwInitHints;
_glfw.ignoreOSKeyboardProcessing = false;
if (!_glfwPlatformInit())
if (!_glfwPlatformInit(supports_window_occlusion))
{
terminate();
return false;

2
glfw/internal.h vendored
View file

@ -672,7 +672,7 @@ extern _GLFWlibrary _glfw;
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformInit(void);
int _glfwPlatformInit(bool*);
void _glfwPlatformTerminate(void);
const char* _glfwPlatformGetVersionString(void);

3
glfw/wl_init.c vendored
View file

@ -721,7 +721,7 @@ get_compositor_missing_capabilities(void) {
GLFWAPI const char* glfwWaylandMissingCapabilities(void) { return get_compositor_missing_capabilities(); }
int _glfwPlatformInit(void)
int _glfwPlatformInit(bool *supports_window_occlusion)
{
int i;
_GLFWmonitor* monitor;
@ -812,6 +812,7 @@ int _glfwPlatformInit(void)
const char *mc = get_compositor_missing_capabilities();
if (mc && mc[0]) debug("Compositor missing capabilities: %s\n", mc);
}
*supports_window_occlusion = _glfw.wl.xdg_wm_base_version > 5;
return true;
}

3
glfw/x11_init.c vendored
View file

@ -621,8 +621,9 @@ GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(bool query_if_unintialize
void _glfwPlatformInputColorScheme(GLFWColorScheme appearance UNUSED) { }
int _glfwPlatformInit(void)
int _glfwPlatformInit(bool *supports_window_occlusion)
{
*supports_window_occlusion = false;
XInitThreads();
XrmInitialize();

View file

@ -330,3 +330,13 @@ def local_docs() -> str:
def wrapped_kitten_names() -> frozenset[str]:
import kitty.fast_data_types as f
return frozenset(f.wrapped_kitten_names())
_supports_window_occlusion = False
def supports_window_occlusion(set: bool | None = None) -> bool:
global _supports_window_occlusion
if set is not None:
_supports_window_occlusion = set
return _supports_window_occlusion

View file

@ -677,7 +677,7 @@ def glfw_terminate() -> None:
def glfw_init(
path: str, edge_spacing_func: Callable[[EdgeLiteral], float], debug_keyboard: bool = False, debug_rendering: bool = False,
wayland_enable_ime: bool = True
) -> bool:
) -> tuple[bool, bool]:
pass

2
kitty/glfw-wrapper.h generated
View file

@ -1713,7 +1713,7 @@ typedef void (* GLFWcocoarenderframefun)(GLFWwindow*);
typedef void (*GLFWwaylandframecallbackfunc)(unsigned long long id);
typedef void (*GLFWDBusnotificationcreatedfun)(unsigned long long, uint32_t, void*);
typedef void (*GLFWDBusnotificationactivatedfun)(uint32_t, int, const char*);
typedef int (*glfwInit_func)(monotonic_t);
typedef int (*glfwInit_func)(monotonic_t, bool*);
GFW_EXTERN glfwInit_func glfwInit_impl;
#define glfwInit glfwInit_impl

View file

@ -1503,8 +1503,9 @@ glfw_init(PyObject UNUSED *self, PyObject *args) {
glfwDBusSetUserNotificationHandler(dbus_user_notification_activated);
}
#endif
PyObject *ans = glfwInit(monotonic_start_time) ? Py_True: Py_False;
if (ans == Py_True) {
bool supports_window_occlusion = false;
bool ok = glfwInit(monotonic_start_time, &supports_window_occlusion);
if (ok) {
#ifdef __APPLE__
glfwSetCocoaURLOpenCallback(apple_url_open_callback);
#else
@ -1513,8 +1514,7 @@ glfw_init(PyObject UNUSED *self, PyObject *args) {
get_window_dpi(NULL, &global_state.default_dpi.x, &global_state.default_dpi.y);
edge_spacing_func = edge_sf; Py_INCREF(edge_spacing_func);
}
Py_INCREF(ans);
return ans;
return Py_BuildValue("OO", ok ? Py_True : Py_False, supports_window_occlusion ? Py_True : Py_False);
}
static PyObject*

View file

@ -28,6 +28,7 @@ from .constants import (
kitty_exe,
logo_png_file,
running_in_kitty,
supports_window_occlusion,
website_url,
)
from .fast_data_types import (
@ -89,8 +90,10 @@ def load_all_shaders(semi_transparent: bool = False) -> None:
def init_glfw_module(glfw_module: str, debug_keyboard: bool = False, debug_rendering: bool = False, wayland_enable_ime: bool = True) -> None:
if not glfw_init(glfw_path(glfw_module), edge_spacing, debug_keyboard, debug_rendering, wayland_enable_ime):
ok, swo = glfw_init(glfw_path(glfw_module), edge_spacing, debug_keyboard, debug_rendering, wayland_enable_ime)
if not ok:
raise SystemExit('GLFW initialization failed')
supports_window_occlusion(swo)
def init_glfw(opts: Options, debug_keyboard: bool = False, debug_rendering: bool = False) -> str:

View file

@ -12,7 +12,7 @@ from itertools import count
from typing import Any, NamedTuple, Set
from weakref import ReferenceType, ref
from .constants import cache_dir, config_dir, is_macos, logo_png_file, standard_icon_names, standard_sound_names
from .constants import cache_dir, config_dir, is_macos, logo_png_file, standard_icon_names, standard_sound_names, supports_window_occlusion
from .fast_data_types import (
ESC_OSC,
StreamingBase64Decoder,
@ -801,9 +801,12 @@ class Channel:
has_focus = is_visible = False
boss = get_boss()
if w := self.window_for_id(channel_id):
has_focus = w.is_active and w.os_window_id == current_focused_os_window_id()
# window is in the active OS window and the active tab and is visible in the tab layout
is_visible = not os_window_is_invisible(w.os_window_id) and w.tabref() is boss.active_tab and w.is_visible_in_layout
os_window_active = w.os_window_id == current_focused_os_window_id()
has_focus = w.is_active and os_window_active
is_visible = os_window_active
if supports_window_occlusion():
is_visible = not os_window_is_invisible(w.os_window_id)
is_visible = is_visible and w.tabref() is boss.active_tab and w.is_visible_in_layout
return UIState(has_focus, is_visible)
def send(self, channel_id: int, osc_escape_code: str) -> bool:

View file

@ -3306,8 +3306,8 @@ The possible values are:
:code:`invisible`
Only send a notification when the window both is unfocused and not visible
to the user, for example, because it is in an inactive tab or its OS window
is not currently visible (note that OS Window visibility is not implemented
by some Wayland compositors such as sway and also not implemented in X11).
is not currently visible (on platforms that support OS window visibility querying
this considers an OS Window visible iff it is active).
:code:`always`
Always send a notification, regardless of window state.