diff --git a/glfw/glfw3.h b/glfw/glfw3.h index 660ceb3cf..312665645 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -1049,6 +1049,7 @@ typedef enum { #define GLFW_X11_INSTANCE_NAME 0x00024002 #define GLFW_WAYLAND_APP_ID 0x00025001 +#define GLFW_WAYLAND_BGCOLOR 0x00025002 /*! @} */ #define GLFW_NO_API 0 diff --git a/glfw/internal.h b/glfw/internal.h index 9465d6319..aeedcd108 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -322,6 +322,7 @@ struct _GLFWwndconfig } x11; struct { char appId[256]; + uint32_t bgcolor; } wl; }; diff --git a/glfw/window.c b/glfw/window.c index 23ea9cfa0..4c2314a24 100644 --- a/glfw/window.c +++ b/glfw/window.c @@ -468,8 +468,10 @@ GLFWAPI void glfwWindowHint(int hint, int value) case GLFW_REFRESH_RATE: _glfw.hints.refreshRate = value; return; + case GLFW_WAYLAND_BGCOLOR: + _glfw.hints.window.wl.bgcolor = value; + return; } - _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint); } diff --git a/glfw/wl_window.c b/glfw/wl_window.c index 481e01225..92b2bfd7d 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -760,17 +760,37 @@ attach_temp_buffer_during_window_creation(_GLFWwindow *window) { const size_t size = 4 * width * height; int fd = createAnonymousFile(size); if (fd < 0) { - _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: failed to create anonymouse file"); + _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: failed to create anonymous file"); + return false; + } + uint32_t *shm_data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + union { + struct { + uint8_t blue, green, red, alpha; + }; + uint32_t value; + } color; + color.value = _glfw.hints.window.wl.bgcolor; + int shm_format = WL_SHM_FORMAT_ARGB8888; + if (!window->wl.transparent) { color.alpha = 0xff; shm_format = WL_SHM_FORMAT_XRGB8888; } + else if (color.alpha == 0) color.value = 0; // fully transparent blends best with black and we can use memset + // convert to pre-multiplied alpha + float alpha = color.alpha / 255.f; color.red = (uint8_t)(alpha * color.red); color.green = (uint8_t)(alpha * color.green); color.blue = (uint8_t)(alpha * color.blue); + if (color.value) for (size_t i = 0; i < size/4; i++) shm_data[i] = color.value; + else memset(shm_data, 0, size); + if (!shm_data) { + close(fd); + _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: failed to mmap anonymouse file"); return false; } struct wl_shm_pool *pool = wl_shm_create_pool(_glfw.wl.shm, fd, size); if (!pool) { - close(fd); + close(fd); munmap(shm_data, size); _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); + struct wl_buffer *buffer = wl_shm_pool_create_buffer(pool, 0, width, height, width * 4, shm_format); + wl_shm_pool_destroy(pool); munmap(shm_data, size); close(fd); if (!buffer) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: failed to create wl_buffer of size: %zu", size); return false; diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index d5b8e7678..ad09a7e63 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -787,6 +787,7 @@ typedef enum { #define GLFW_X11_INSTANCE_NAME 0x00024002 #define GLFW_WAYLAND_APP_ID 0x00025001 +#define GLFW_WAYLAND_BGCOLOR 0x00025002 /*! @} */ #define GLFW_NO_API 0 diff --git a/kitty/glfw.c b/kitty/glfw.c index cab371a60..da6d1ae34 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -1173,6 +1173,9 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) { } bool want_semi_transparent = (1.0 - OPT(background_opacity) >= 0.01) || OPT(dynamic_background_opacity); glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, want_semi_transparent); + uint32_t bgcolor = OPT(background); + uint32_t bgalpha = (uint32_t)((MAX(0.f, MIN((OPT(background_opacity) * 255), 255.f)))); + glfwWindowHint(GLFW_WAYLAND_BGCOLOR, ((bgalpha & 0xff) << 24) | bgcolor); // We use a temp window to avoid the need to set the window size after // creation, which causes a resize event and all the associated processing. // The temp window is used to get the DPI.