mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-08-04 14:46:03 +00:00
Merge branch 'wayland-initial-window-size' of https://github.com/egnor/kitty
Some checks are pending
CI / Linux (python=3.14 cc=clang sanitize=1) (push) Waiting to run
CI / Linux (python=3.12 cc=gcc sanitize=0) (push) Waiting to run
CI / Linux (python=3.13 cc=gcc sanitize=1) (push) Waiting to run
CI / Linux package (push) Waiting to run
CI / Bundle test (macos-latest) (push) Waiting to run
CI / Bundle test (ubuntu-latest) (push) Waiting to run
CI / macOS Brew (push) Waiting to run
CI / Test ./dev.sh and benchmark (push) Waiting to run
CodeQL / CodeQL-Build (actions, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (c, macos-latest) (push) Waiting to run
CodeQL / CodeQL-Build (c, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (go, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (python, ubuntu-latest) (push) Waiting to run
Depscan / Scan dependencies for vulnerabilities (push) Waiting to run
Some checks are pending
CI / Linux (python=3.14 cc=clang sanitize=1) (push) Waiting to run
CI / Linux (python=3.12 cc=gcc sanitize=0) (push) Waiting to run
CI / Linux (python=3.13 cc=gcc sanitize=1) (push) Waiting to run
CI / Linux package (push) Waiting to run
CI / Bundle test (macos-latest) (push) Waiting to run
CI / Bundle test (ubuntu-latest) (push) Waiting to run
CI / macOS Brew (push) Waiting to run
CI / Test ./dev.sh and benchmark (push) Waiting to run
CodeQL / CodeQL-Build (actions, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (c, macos-latest) (push) Waiting to run
CodeQL / CodeQL-Build (c, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (go, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (python, ubuntu-latest) (push) Waiting to run
Depscan / Scan dependencies for vulnerabilities (push) Waiting to run
This commit is contained in:
commit
0e38ca2b86
6 changed files with 86 additions and 7 deletions
|
|
@ -318,6 +318,7 @@ def generate_wrappers(glfw_header: str) -> None:
|
|||
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)
|
||||
void glfwCocoaRegisterMIMETypes(GLFWwindow *window, const char **mimes, size_t count)
|
||||
void glfwCocoaSetWindowLevel(GLFWwindow *window, const char *level_spec)
|
||||
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)
|
||||
|
|
@ -326,6 +327,7 @@ def generate_wrappers(glfw_header: str) -> None:
|
|||
void glfwWaylandRunWithActivationToken(GLFWwindow *handle, GLFWactivationcallback cb, void *cb_data)
|
||||
bool glfwWaylandSetTitlebarColor(GLFWwindow *handle, uint32_t color, bool use_system_color)
|
||||
void glfwWaylandSetTitlebarHidden(GLFWwindow *handle, bool hidden)
|
||||
void glfwWaylandSetInitialWindowSizeCallback(GLFWwaylandinitialsizefun callback)
|
||||
void glfwWaylandRedrawCSDWindowTitle(GLFWwindow *handle)
|
||||
bool glfwWaylandIsWindowFullyCreated(GLFWwindow *handle)
|
||||
bool glfwWaylandBeep(GLFWwindow *handle)
|
||||
|
|
|
|||
1
glfw/glfw3.h
vendored
1
glfw/glfw3.h
vendored
|
|
@ -1933,6 +1933,7 @@ typedef void (* GLFWjoystickfun)(int,int);
|
|||
typedef void (* GLFWuserdatafun)(unsigned long long, void*);
|
||||
typedef void (* GLFWtickcallback)(void*);
|
||||
typedef void (* GLFWactivationcallback)(GLFWwindow *window, const char *token, void *data);
|
||||
typedef void (* GLFWwaylandinitialsizefun)(GLFWwindow *window, float xscale, float yscale, int *width, int *height);
|
||||
typedef bool (* GLFWdrawtextfun)(GLFWwindow *window, const char *text, uint32_t fg, uint32_t bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset, size_t right_margin, bool is_single_glyph);
|
||||
typedef char* (* GLFWcurrentselectionfun)(void);
|
||||
typedef bool (* GLFWhascurrentselectionfun)(void);
|
||||
|
|
|
|||
33
glfw/wl_window.c
vendored
33
glfw/wl_window.c
vendored
|
|
@ -440,8 +440,41 @@ clipboard_mime(void) {
|
|||
return buf;
|
||||
}
|
||||
|
||||
static GLFWwaylandinitialsizefun initial_window_size_callback = NULL;
|
||||
|
||||
GLFWAPI void
|
||||
glfwWaylandSetInitialWindowSizeCallback(GLFWwaylandinitialsizefun callback) {
|
||||
initial_window_size_callback = callback;
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_recompute_initial_window_size(_GLFWwindow *window) {
|
||||
// Before the initial window is mapped, the compositor tells us the real
|
||||
// (possibly fractional) scale. For sizes specified in cells this changes
|
||||
// the correct logical window size, because cell metrics are not a linear
|
||||
// function of scale (integer-pixel rounding). Ask the embedder to recompute
|
||||
// the logical size now, while the window is still unmapped, so it is mapped
|
||||
// at the right size and the compositor's authoritative configure agrees.
|
||||
if (window->wl.window_fully_created) return;
|
||||
if (!initial_window_size_callback) return;
|
||||
if (!window->wl.xdg.toplevel) return; // only ordinary toplevels have cell-based sizes
|
||||
if (window->wl.layer_shell.zwlr_layer_surface_v1) return; // layer-shell surfaces size themselves
|
||||
double scale = _glfwWaylandWindowScale(window);
|
||||
int w = window->wl.width, h = window->wl.height;
|
||||
initial_window_size_callback((GLFWwindow*)window, (float)scale, (float)scale, &w, &h);
|
||||
if (w > 0 && h > 0 && (w != window->wl.width || h != window->wl.height)) {
|
||||
debug("Recomputed initial size of window %llu for scale %.3f: %dx%d -> %dx%d\n",
|
||||
window->id, scale, window->wl.width, window->wl.height, w, h);
|
||||
window->wl.width = w; window->wl.height = h;
|
||||
window->wl.user_requested_content_size.width = w;
|
||||
window->wl.user_requested_content_size.height = h;
|
||||
update_regions(window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
apply_scale_changes(_GLFWwindow *window, bool resize_framebuffer, bool update_csd) {
|
||||
maybe_recompute_initial_window_size(window);
|
||||
double scale = _glfwWaylandWindowScale(window);
|
||||
if (resize_framebuffer) resizeFramebuffer(window);
|
||||
_glfwInputWindowContentScale(window, (float)scale, (float)scale);
|
||||
|
|
|
|||
9
kitty/glfw-wrapper.c
generated
9
kitty/glfw-wrapper.c
generated
|
|
@ -497,15 +497,15 @@ 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
|
||||
|
||||
*(void **) (&glfwCocoaRegisterMIMETypes_impl) = dlsym(handle, "glfwCocoaRegisterMIMETypes");
|
||||
if (glfwCocoaRegisterMIMETypes_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
*(void **) (&glfwCocoaSetWindowLevel_impl) = dlsym(handle, "glfwCocoaSetWindowLevel");
|
||||
if (glfwCocoaSetWindowLevel_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
*(void **) (&glfwGetPrimarySelectionString_impl) = dlsym(handle, "glfwGetPrimarySelectionString");
|
||||
if (glfwGetPrimarySelectionString_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
|
|
@ -530,6 +530,9 @@ load_glfw(const char* path) {
|
|||
*(void **) (&glfwWaylandSetTitlebarHidden_impl) = dlsym(handle, "glfwWaylandSetTitlebarHidden");
|
||||
if (glfwWaylandSetTitlebarHidden_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
*(void **) (&glfwWaylandSetInitialWindowSizeCallback_impl) = dlsym(handle, "glfwWaylandSetInitialWindowSizeCallback");
|
||||
if (glfwWaylandSetInitialWindowSizeCallback_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
*(void **) (&glfwWaylandRedrawCSDWindowTitle_impl) = dlsym(handle, "glfwWaylandRedrawCSDWindowTitle");
|
||||
if (glfwWaylandRedrawCSDWindowTitle_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
|
|
|
|||
13
kitty/glfw-wrapper.h
generated
13
kitty/glfw-wrapper.h
generated
|
|
@ -1661,6 +1661,7 @@ typedef void (* GLFWjoystickfun)(int,int);
|
|||
typedef void (* GLFWuserdatafun)(unsigned long long, void*);
|
||||
typedef void (* GLFWtickcallback)(void*);
|
||||
typedef void (* GLFWactivationcallback)(GLFWwindow *window, const char *token, void *data);
|
||||
typedef void (* GLFWwaylandinitialsizefun)(GLFWwindow *window, float xscale, float yscale, int *width, int *height);
|
||||
typedef bool (* GLFWdrawtextfun)(GLFWwindow *window, const char *text, uint32_t fg, uint32_t bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset, size_t right_margin, bool is_single_glyph);
|
||||
typedef char* (* GLFWcurrentselectionfun)(void);
|
||||
typedef bool (* GLFWhascurrentselectionfun)(void);
|
||||
|
|
@ -2479,10 +2480,6 @@ 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
|
||||
|
|
@ -2491,6 +2488,10 @@ typedef void (*glfwCocoaRegisterMIMETypes_func)(GLFWwindow*, const char**, size_
|
|||
GFW_EXTERN glfwCocoaRegisterMIMETypes_func glfwCocoaRegisterMIMETypes_impl;
|
||||
#define glfwCocoaRegisterMIMETypes glfwCocoaRegisterMIMETypes_impl
|
||||
|
||||
typedef void (*glfwCocoaSetWindowLevel_func)(GLFWwindow*, const char*);
|
||||
GFW_EXTERN glfwCocoaSetWindowLevel_func glfwCocoaSetWindowLevel_impl;
|
||||
#define glfwCocoaSetWindowLevel glfwCocoaSetWindowLevel_impl
|
||||
|
||||
typedef const char* (*glfwGetPrimarySelectionString_func)(GLFWwindow*);
|
||||
GFW_EXTERN glfwGetPrimarySelectionString_func glfwGetPrimarySelectionString_impl;
|
||||
#define glfwGetPrimarySelectionString glfwGetPrimarySelectionString_impl
|
||||
|
|
@ -2523,6 +2524,10 @@ typedef void (*glfwWaylandSetTitlebarHidden_func)(GLFWwindow*, bool);
|
|||
GFW_EXTERN glfwWaylandSetTitlebarHidden_func glfwWaylandSetTitlebarHidden_impl;
|
||||
#define glfwWaylandSetTitlebarHidden glfwWaylandSetTitlebarHidden_impl
|
||||
|
||||
typedef void (*glfwWaylandSetInitialWindowSizeCallback_func)(GLFWwaylandinitialsizefun);
|
||||
GFW_EXTERN glfwWaylandSetInitialWindowSizeCallback_func glfwWaylandSetInitialWindowSizeCallback_impl;
|
||||
#define glfwWaylandSetInitialWindowSizeCallback glfwWaylandSetInitialWindowSizeCallback_impl
|
||||
|
||||
typedef void (*glfwWaylandRedrawCSDWindowTitle_func)(GLFWwindow*);
|
||||
GFW_EXTERN glfwWaylandRedrawCSDWindowTitle_func glfwWaylandRedrawCSDWindowTitle_impl;
|
||||
#define glfwWaylandRedrawCSDWindowTitle glfwWaylandRedrawCSDWindowTitle_impl
|
||||
|
|
|
|||
35
kitty/glfw.c
35
kitty/glfw.c
|
|
@ -1705,6 +1705,32 @@ os_window_update_size_increments(OSWindow *window) {
|
|||
}
|
||||
|
||||
|
||||
// Borrowed reference to the get_window_size callable, valid only for the
|
||||
// duration of a create_os_window() call. Used by the Wayland initial-size hook
|
||||
// below, which fires synchronously from inside glfwCreateWindow().
|
||||
static PyObject *initial_window_size_py_callback = NULL;
|
||||
|
||||
static void
|
||||
wayland_initial_size_callback(GLFWwindow *window UNUSED, float xscale, float yscale, int *width, int *height) {
|
||||
// The compositor has told us the real scale before the window is mapped;
|
||||
// recompute the cell-based logical size for that scale so the window is
|
||||
// mapped at the correct size in the first place.
|
||||
if (!initial_window_size_py_callback) return;
|
||||
double xdpi, ydpi;
|
||||
dpi_from_scale(xscale, yscale, &xdpi, &ydpi);
|
||||
FONTS_DATA_HANDLE fonts_data = load_fonts_data(OPT(font_size), xdpi, ydpi);
|
||||
if (!fonts_data) return;
|
||||
PyObject *ret = PyObject_CallFunction(initial_window_size_py_callback, "IIddff",
|
||||
fonts_data->fcm.cell_width, fonts_data->fcm.cell_height,
|
||||
fonts_data->logical_dpi_x, fonts_data->logical_dpi_y, xscale, yscale);
|
||||
if (ret) {
|
||||
int w = PyLong_AsLong(PyTuple_GET_ITEM(ret, 0)), h = PyLong_AsLong(PyTuple_GET_ITEM(ret, 1));
|
||||
if (!PyErr_Occurred() && w > 0 && h > 0) { *width = w; *height = h; }
|
||||
else PyErr_Clear();
|
||||
Py_DECREF(ret);
|
||||
} else PyErr_Clear();
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
||||
int x = INT_MIN, y = INT_MIN, window_state = WINDOW_NORMAL, disallow_override_title = 0;
|
||||
|
|
@ -1822,7 +1848,16 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
|||
if (!layer_shell_config_from_python(layer_shell_config, lsc)) return NULL;
|
||||
lsc->expected.xscale = xscale; lsc->expected.yscale = yscale;
|
||||
}
|
||||
// On Wayland the true (fractional) scale is only known after the surface
|
||||
// exists. Register a hook so the window is mapped at the correct cell-based
|
||||
// size once the compositor reveals the scale, rather than being resized
|
||||
// afterwards (which loses to the compositor's authoritative configure).
|
||||
if (global_state.is_wayland && glfwWaylandSetInitialWindowSizeCallback) {
|
||||
glfwWaylandSetInitialWindowSizeCallback(wayland_initial_size_callback);
|
||||
initial_window_size_py_callback = get_window_size;
|
||||
}
|
||||
GLFWwindow *glfw_window = glfwCreateWindow(width, height, title, NULL, temp_window ? temp_window : common_context, lsc);
|
||||
initial_window_size_py_callback = NULL;
|
||||
if (temp_window) { glfwDestroyWindow(temp_window); temp_window = NULL; }
|
||||
if (glfw_window == NULL) glfw_failure;
|
||||
#undef glfw_failure
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue