diff --git a/glfw/glfw.py b/glfw/glfw.py index 77fc977ea..96475ac9b 100755 --- a/glfw/glfw.py +++ b/glfw/glfw.py @@ -316,7 +316,6 @@ def generate_wrappers(glfw_header: str) -> None: void glfwWaylandRedrawCSDWindowTitle(GLFWwindow *handle) void glfwWaylandSetupLayerShellForNextWindow(GLFWLayerShellConfig c) pid_t glfwWaylandCompositorPID(void) - bool glfwWaylandWindowFullyCreated(GLFWwindow *handle) unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, \ const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *data) void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler) diff --git a/glfw/wl_platform.h b/glfw/wl_platform.h index 912c67b91..0c9c6075b 100644 --- a/glfw/wl_platform.h +++ b/glfw/wl_platform.h @@ -172,6 +172,7 @@ typedef struct _GLFWwindowWayland struct { bool surface_configured, fractional_scale_received, preferred_scale_received; } once; + struct wl_buffer *temp_buffer_used_during_window_creation; struct { GLFWLayerShellConfig config; struct zwlr_layer_surface_v1* zwlr_layer_surface_v1; diff --git a/glfw/wl_window.c b/glfw/wl_window.c index 8c90fc044..08b359eac 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -373,6 +373,10 @@ _glfwWaylandAfterBufferSwap(_GLFWwindow* window) { // this is not really needed, since I think eglSwapBuffers() calls wl_surface_commit() // but lets be safe. See https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/egl/drivers/dri2/platform_wayland.c#L1510 wl_surface_commit(window->wl.surface); + if (window->wl.temp_buffer_used_during_window_creation) { + wl_buffer_destroy(window->wl.temp_buffer_used_during_window_creation); + window->wl.temp_buffer_used_during_window_creation = NULL; + } } } @@ -748,6 +752,51 @@ apply_xdg_configure_changes(_GLFWwindow *window) { window->wl.pending_state = 0; } +static bool +attach_temp_buffer_during_window_creation(_GLFWwindow *window) { + int width, height; + _glfwPlatformGetFramebufferSize(window, &width, &height); + const size_t size = 4 * width * height; + int fd = createAnonymousFile(size); + if (fd < 0) { + _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: failed to create anonymouse file"); + return false; + } + struct wl_shm_pool *pool = wl_shm_create_pool(_glfw.wl.shm, fd, size); + if (!pool) { + close(fd); + _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: failed to create wl_shm_pool of size: %zu", size); + return false; + } + struct wl_buffer *buffer = wl_shm_pool_create_buffer(pool, 0, width, height, width * 4, WL_SHM_FORMAT_ARGB8888); + wl_shm_pool_destroy(pool); close(fd); + if (!buffer) { + _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: failed to create wl_buffer of size: %zu", size); + return false; + } + if (window->wl.temp_buffer_used_during_window_creation) wl_buffer_destroy(window->wl.temp_buffer_used_during_window_creation); + window->wl.temp_buffer_used_during_window_creation = buffer; + wl_surface_set_buffer_scale(window->wl.surface, window->wl.fractional_scale ? 1: _glfwWaylandIntegerWindowScale(window)); + wl_surface_attach(window->wl.surface, buffer, 0, 0); + if (window->wl.wp_viewport) wp_viewport_set_destination(window->wl.wp_viewport, window->wl.width, window->wl.height); + wl_surface_commit(window->wl.surface); + debug("Attached temp buffer during window creation of size: %dx%d\n", width, height); + return true; +} + +static void +loop_till_window_fully_created(_GLFWwindow *window) { + if (!window->wl.window_fully_created) { + monotonic_t start = monotonic(); + while (!window->wl.window_fully_created && monotonic() - start < ms_to_monotonic_t(300)) { + if (wl_display_roundtrip(_glfw.wl.display) == -1) { + window->wl.window_fully_created = true; + } + } + window->wl.window_fully_created = true; + } +} + static void xdgSurfaceHandleConfigure(void* data, struct xdg_surface* surface, uint32_t serial) { // The poorly documented pattern Wayland requires is: @@ -763,6 +812,9 @@ xdgSurfaceHandleConfigure(void* data, struct xdg_surface* surface, uint32_t seri xdg_surface_ack_configure(surface, serial); debug("XDG surface configure event received and acknowledged\n"); apply_xdg_configure_changes(window); + if (!window->wl.window_fully_created) { + if (!attach_temp_buffer_during_window_creation(window)) window->wl.window_fully_created = true; + } } static const struct xdg_surface_listener xdgSurfaceListener = { @@ -877,6 +929,9 @@ layer_surface_handle_configure(void* data, struct zwlr_layer_surface_v1* surface layer_set_properties(window); } commit_window_surface_if_safe(window); + if (!window->wl.window_fully_created) { + if (!attach_temp_buffer_during_window_creation(window)) window->wl.window_fully_created = true; + } } static void @@ -1200,7 +1255,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, window->wl.monitors = calloc(1, sizeof(_GLFWmonitor*)); window->wl.monitorsCount = 0; window->wl.monitorsSize = 1; - + if (window->wl.visible) loop_till_window_fully_created(window); return true; } @@ -1220,6 +1275,9 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) _glfw.wl.keyRepeatInfo.keyboardFocusId = 0; } + if (window->wl.temp_buffer_used_during_window_creation) + wl_buffer_destroy(window->wl.temp_buffer_used_during_window_creation); + if (window->wl.wp_fractional_scale_v1) wp_fractional_scale_v1_destroy(window->wl.wp_fractional_scale_v1); if (window->wl.wp_viewport) @@ -1422,10 +1480,10 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window) void _glfwPlatformShowWindow(_GLFWwindow* window) { - if (!window->wl.visible) - { + if (!window->wl.visible) { create_window_desktop_surface(window); window->wl.visible = true; + loop_till_window_fully_created(window); } } @@ -2585,8 +2643,3 @@ GLFWAPI void glfwWaylandSetupLayerShellForNextWindow(GLFWLayerShellConfig c) { if (layer_shell_config_for_next_window.output_name && !layer_shell_config_for_next_window.output_name[0]) layer_shell_config_for_next_window.output_name = NULL; if (layer_shell_config_for_next_window.output_name) layer_shell_config_for_next_window.output_name = strdup(layer_shell_config_for_next_window.output_name); } - -GLFWAPI bool glfwWaylandWindowFullyCreated(GLFWwindow *handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; - return window->wl.window_fully_created; -} diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index 7002e3218..5244772a4 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1574,5 +1574,4 @@ def replace_c0_codes_except_nl_space_tab(text: str) -> str:... def replace_c0_codes_except_nl_space_tab(text: Union[bytes, memoryview, bytearray]) -> bytes:... def terminfo_data() -> bytes:... def wayland_compositor_pid() -> int:... -def window_fully_created(kitty_window_id: int) -> bool: ... def monotonic() -> float: ... diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index 78158d775..ceb1855b5 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -485,9 +485,6 @@ load_glfw(const char* path) { *(void **) (&glfwWaylandCompositorPID_impl) = dlsym(handle, "glfwWaylandCompositorPID"); if (glfwWaylandCompositorPID_impl == NULL) dlerror(); // clear error indicator - *(void **) (&glfwWaylandWindowFullyCreated_impl) = dlsym(handle, "glfwWaylandWindowFullyCreated"); - if (glfwWaylandWindowFullyCreated_impl == NULL) dlerror(); // clear error indicator - *(void **) (&glfwDBusUserNotify_impl) = dlsym(handle, "glfwDBusUserNotify"); if (glfwDBusUserNotify_impl == NULL) dlerror(); // clear error indicator diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index fa58afca8..d5b8e7678 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -2316,10 +2316,6 @@ typedef pid_t (*glfwWaylandCompositorPID_func)(void); GFW_EXTERN glfwWaylandCompositorPID_func glfwWaylandCompositorPID_impl; #define glfwWaylandCompositorPID glfwWaylandCompositorPID_impl -typedef bool (*glfwWaylandWindowFullyCreated_func)(GLFWwindow*); -GFW_EXTERN glfwWaylandWindowFullyCreated_func glfwWaylandWindowFullyCreated_impl; -#define glfwWaylandWindowFullyCreated glfwWaylandWindowFullyCreated_impl - typedef unsigned long long (*glfwDBusUserNotify_func)(const char*, const char*, const char*, const char*, const char*, int32_t, GLFWDBusnotificationcreatedfun, void*); GFW_EXTERN glfwDBusUserNotify_func glfwDBusUserNotify_impl; #define glfwDBusUserNotify glfwDBusUserNotify_impl diff --git a/kitty/glfw.c b/kitty/glfw.c index 89467c86d..cab371a60 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -2210,16 +2210,6 @@ make_x11_window_a_dock_window(PyObject *self UNUSED, PyObject *args UNUSED) { Py_RETURN_NONE; } -static PyObject* -window_fully_created(PyObject *self UNUSED, PyObject *wid) { - // On Wayland a window does not receive its final size by the time glfwCreateWindow returns - if (!global_state.is_wayland) Py_RETURN_TRUE; - OSWindow *w = os_window_for_kitty_window(PyLong_AsUnsignedLongLong(wid)); - if (!w || !w->handle) Py_RETURN_FALSE; - if (glfwWaylandWindowFullyCreated(w->handle)) Py_RETURN_TRUE; - Py_RETURN_FALSE; -} - // Boilerplate {{{ static PyMethodDef module_methods[] = { @@ -2239,7 +2229,6 @@ static PyMethodDef module_methods[] = { METHODB(glfw_window_hint, METH_VARARGS), METHODB(x11_display, METH_NOARGS), METHODB(wayland_compositor_pid, METH_NOARGS), - METHODB(window_fully_created, METH_O), METHODB(get_click_interval, METH_NOARGS), METHODB(x11_window_id, METH_O), METHODB(make_x11_window_a_dock_window, METH_VARARGS), diff --git a/kitty/window.py b/kitty/window.py index 04e176241..601ccad96 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -86,7 +86,6 @@ update_window_title, update_window_visibility, wakeup_main_loop, - window_fully_created, ) from .keys import keyboard_mode_name, mod_mask from .notify import ( @@ -839,14 +838,14 @@ def set_geometry(self, new_geometry: WindowGeometry) -> None: boss = get_boss() boss.child_monitor.resize_pty(self.id, *current_pty_size) self.last_resized_at = monotonic() - if not self.child_is_launched and window_fully_created(self.id): + if not self.child_is_launched: self.child.mark_terminal_ready() self.child_is_launched = True update_ime_position = True if boss.args.debug_rendering: now = monotonic() - print(f'[{now:.3f}] Child launched {now - self.started_at:.2f} seconds after window creation', file=sys.stderr) - if boss.args.debug_rendering and self.child_is_launched: + print(f'[{now:.3f}] Child launched', file=sys.stderr) + elif boss.args.debug_rendering: print(f'[{monotonic():.3f}] SIGWINCH sent to child in window: {self.id} with size: {current_pty_size}', file=sys.stderr) self.last_reported_pty_size = current_pty_size else: