Support hide_window_decorations titlebar-only on Wayland
Hide the CSD titlebar subsurface while keeping shadow borders for resizing. On SSD compositors (GNOME), forces CSD mode to draw kitty's own shadows without a titlebar. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
parent
abb1141826
commit
ef4574ae97
9 changed files with 82 additions and 20 deletions
|
|
@ -214,6 +214,11 @@ Detailed list of changes
|
||||||
|
|
||||||
- edit-in-kitty: Handle connection drop more gracefully (:pull:`9480`)
|
- edit-in-kitty: Handle connection drop more gracefully (:pull:`9480`)
|
||||||
|
|
||||||
|
- Wayland: Add support for :code:`titlebar-only` in
|
||||||
|
:opt:`hide_window_decorations` to hide the titlebar while keeping shadow
|
||||||
|
borders for resizing. On compositors that use server-side decorations (such as
|
||||||
|
GNOME), this forces client-side decoration mode (:pull:`9486`)
|
||||||
|
|
||||||
|
|
||||||
0.45.0 [2025-12-24]
|
0.45.0 [2025-12-24]
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
||||||
|
|
@ -323,6 +323,7 @@ def generate_wrappers(glfw_header: str) -> None:
|
||||||
const char* glfwWaylandMissingCapabilities(void)
|
const char* glfwWaylandMissingCapabilities(void)
|
||||||
void glfwWaylandRunWithActivationToken(GLFWwindow *handle, GLFWactivationcallback cb, void *cb_data)
|
void glfwWaylandRunWithActivationToken(GLFWwindow *handle, GLFWactivationcallback cb, void *cb_data)
|
||||||
bool glfwWaylandSetTitlebarColor(GLFWwindow *handle, uint32_t color, bool use_system_color)
|
bool glfwWaylandSetTitlebarColor(GLFWwindow *handle, uint32_t color, bool use_system_color)
|
||||||
|
void glfwWaylandSetTitlebarHidden(GLFWwindow *handle, bool hidden)
|
||||||
void glfwWaylandRedrawCSDWindowTitle(GLFWwindow *handle)
|
void glfwWaylandRedrawCSDWindowTitle(GLFWwindow *handle)
|
||||||
bool glfwWaylandIsWindowFullyCreated(GLFWwindow *handle)
|
bool glfwWaylandIsWindowFullyCreated(GLFWwindow *handle)
|
||||||
bool glfwWaylandBeep(GLFWwindow *handle)
|
bool glfwWaylandBeep(GLFWwindow *handle)
|
||||||
|
|
|
||||||
48
glfw/wl_client_side_decorations.c
vendored
48
glfw/wl_client_side_decorations.c
vendored
|
|
@ -469,12 +469,14 @@ render_shadows(_GLFWwindow *window) {
|
||||||
static bool
|
static bool
|
||||||
create_shm_buffers(_GLFWwindow* window) {
|
create_shm_buffers(_GLFWwindow* window) {
|
||||||
decs.mapping.size = 0;
|
decs.mapping.size = 0;
|
||||||
|
const bool has_titlebar = !decs.titlebar_hidden;
|
||||||
|
const int side_height = window->wl.height + (has_titlebar ? decs.metrics.visible_titlebar_height : 0);
|
||||||
#define bp(which, width, height) decs.mapping.size += init_buffer_pair(&decs.which.buffer, width, height, decs.for_window_state.fscale);
|
#define bp(which, width, height) decs.mapping.size += init_buffer_pair(&decs.which.buffer, width, height, decs.for_window_state.fscale);
|
||||||
bp(titlebar, window->wl.width, decs.metrics.visible_titlebar_height);
|
if (has_titlebar) bp(titlebar, window->wl.width, decs.metrics.visible_titlebar_height);
|
||||||
bp(shadow_top, window->wl.width, decs.metrics.width);
|
bp(shadow_top, window->wl.width, decs.metrics.width);
|
||||||
bp(shadow_bottom, window->wl.width, decs.metrics.width);
|
bp(shadow_bottom, window->wl.width, decs.metrics.width);
|
||||||
bp(shadow_left, decs.metrics.width, window->wl.height + decs.metrics.visible_titlebar_height);
|
bp(shadow_left, decs.metrics.width, side_height);
|
||||||
bp(shadow_right, decs.metrics.width, window->wl.height + decs.metrics.visible_titlebar_height);
|
bp(shadow_right, decs.metrics.width, side_height);
|
||||||
bp(shadow_upper_left, decs.metrics.width, decs.metrics.width);
|
bp(shadow_upper_left, decs.metrics.width, decs.metrics.width);
|
||||||
bp(shadow_upper_right, decs.metrics.width, decs.metrics.width);
|
bp(shadow_upper_right, decs.metrics.width, decs.metrics.width);
|
||||||
bp(shadow_lower_left, decs.metrics.width, decs.metrics.width);
|
bp(shadow_lower_left, decs.metrics.width, decs.metrics.width);
|
||||||
|
|
@ -497,10 +499,11 @@ create_shm_buffers(_GLFWwindow* window) {
|
||||||
close(fd);
|
close(fd);
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
#define Q(which) alloc_buffer_pair(window->id, &decs.which.buffer, pool, decs.mapping.data, &offset)
|
#define Q(which) alloc_buffer_pair(window->id, &decs.which.buffer, pool, decs.mapping.data, &offset)
|
||||||
all_surfaces(Q);
|
if (has_titlebar) Q(titlebar);
|
||||||
|
all_shadow_surfaces(Q);
|
||||||
#undef Q
|
#undef Q
|
||||||
wl_shm_pool_destroy(pool);
|
wl_shm_pool_destroy(pool);
|
||||||
render_title_bar(window, true);
|
if (has_titlebar) render_title_bar(window, true);
|
||||||
render_shadows(window);
|
render_shadows(window);
|
||||||
debug("Created decoration buffers at scale: %f\n", decs.for_window_state.fscale);
|
debug("Created decoration buffers at scale: %f\n", decs.for_window_state.fscale);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -578,6 +581,7 @@ csd_should_window_be_decorated(_GLFWwindow *window) {
|
||||||
static bool
|
static bool
|
||||||
ensure_csd_resources(_GLFWwindow *window) {
|
ensure_csd_resources(_GLFWwindow *window) {
|
||||||
if (!window_is_csd_capable(window)) return false;
|
if (!window_is_csd_capable(window)) return false;
|
||||||
|
const bool has_titlebar = !decs.titlebar_hidden;
|
||||||
const bool is_focused = window->id == _glfw.focusedWindowId;
|
const bool is_focused = window->id == _glfw.focusedWindowId;
|
||||||
const bool focus_changed = is_focused != decs.for_window_state.focused;
|
const bool focus_changed = is_focused != decs.for_window_state.focused;
|
||||||
const double current_scale = _glfwWaylandWindowScale(window);
|
const double current_scale = _glfwWaylandWindowScale(window);
|
||||||
|
|
@ -588,34 +592,47 @@ ensure_csd_resources(_GLFWwindow *window) {
|
||||||
!decs.mapping.data
|
!decs.mapping.data
|
||||||
);
|
);
|
||||||
const bool state_changed = decs.for_window_state.toplevel_states != window->wl.current.toplevel_states;
|
const bool state_changed = decs.for_window_state.toplevel_states != window->wl.current.toplevel_states;
|
||||||
const bool needs_update = focus_changed || size_changed || !decs.titlebar.surface || decs.buffer_destroyed || state_changed;
|
const bool titlebar_state_changed = (has_titlebar && !decs.titlebar.surface) || (!has_titlebar && decs.titlebar.surface);
|
||||||
|
const bool needs_update = focus_changed || size_changed || titlebar_state_changed || decs.buffer_destroyed || state_changed;
|
||||||
debug("CSD: old.size: %dx%d new.size: %dx%d needs_update: %d size_changed: %d state_changed: %d buffer_destroyed: %d\n",
|
debug("CSD: old.size: %dx%d new.size: %dx%d needs_update: %d size_changed: %d state_changed: %d buffer_destroyed: %d\n",
|
||||||
decs.for_window_state.width, decs.for_window_state.height, window->wl.width, window->wl.height, needs_update,
|
decs.for_window_state.width, decs.for_window_state.height, window->wl.width, window->wl.height, needs_update,
|
||||||
size_changed, state_changed, decs.buffer_destroyed);
|
size_changed, state_changed, decs.buffer_destroyed);
|
||||||
if (!needs_update) return false;
|
if (!needs_update) return false;
|
||||||
decs.for_window_state.fscale = current_scale; // used in create_shm_buffers
|
decs.for_window_state.fscale = current_scale; // used in create_shm_buffers
|
||||||
if (size_changed || decs.buffer_destroyed) {
|
if (size_changed || decs.buffer_destroyed || titlebar_state_changed) {
|
||||||
free_csd_buffers(window);
|
free_csd_buffers(window);
|
||||||
if (!create_shm_buffers(window)) return false;
|
if (!create_shm_buffers(window)) return false;
|
||||||
decs.buffer_destroyed = false;
|
decs.buffer_destroyed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int top_y = has_titlebar ? -(int)decs.metrics.visible_titlebar_height : 0;
|
||||||
|
|
||||||
#define setup_surface(which, x, y) \
|
#define setup_surface(which, x, y) \
|
||||||
if (!decs.which.surface) create_csd_surfaces(window, &decs.which); \
|
if (!decs.which.surface) create_csd_surfaces(window, &decs.which); \
|
||||||
position_csd_surface(&decs.which, x, y);
|
position_csd_surface(&decs.which, x, y);
|
||||||
|
|
||||||
setup_surface(titlebar, 0, -decs.metrics.visible_titlebar_height);
|
if (has_titlebar) {
|
||||||
setup_surface(shadow_top, decs.titlebar.x, decs.titlebar.y - decs.metrics.width);
|
setup_surface(titlebar, 0, -decs.metrics.visible_titlebar_height);
|
||||||
setup_surface(shadow_bottom, decs.titlebar.x, window->wl.height);
|
} else {
|
||||||
setup_surface(shadow_left, -decs.metrics.width, decs.titlebar.y);
|
free_csd_surface(&decs.titlebar);
|
||||||
|
if (decs.focus == CSD_titlebar) {
|
||||||
|
decs.focus = CENTRAL_WINDOW;
|
||||||
|
decs.dragging = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setup_surface(shadow_top, 0, top_y - decs.metrics.width);
|
||||||
|
setup_surface(shadow_bottom, 0, window->wl.height);
|
||||||
|
setup_surface(shadow_left, -decs.metrics.width, top_y);
|
||||||
setup_surface(shadow_right, window->wl.width, decs.shadow_left.y);
|
setup_surface(shadow_right, window->wl.width, decs.shadow_left.y);
|
||||||
setup_surface(shadow_upper_left, decs.shadow_left.x, decs.shadow_top.y);
|
setup_surface(shadow_upper_left, decs.shadow_left.x, decs.shadow_top.y);
|
||||||
setup_surface(shadow_upper_right, decs.shadow_right.x, decs.shadow_top.y);
|
setup_surface(shadow_upper_right, decs.shadow_right.x, decs.shadow_top.y);
|
||||||
setup_surface(shadow_lower_left, decs.shadow_left.x, decs.shadow_bottom.y);
|
setup_surface(shadow_lower_left, decs.shadow_left.x, decs.shadow_bottom.y);
|
||||||
setup_surface(shadow_lower_right, decs.shadow_right.x, decs.shadow_bottom.y);
|
setup_surface(shadow_lower_right, decs.shadow_right.x, decs.shadow_bottom.y);
|
||||||
|
|
||||||
if (focus_changed || state_changed) update_title_bar(window);
|
if (has_titlebar) {
|
||||||
damage_csd(titlebar, decs.titlebar.buffer.front);
|
if (focus_changed || state_changed) update_title_bar(window);
|
||||||
|
damage_csd(titlebar, decs.titlebar.buffer.front);
|
||||||
|
}
|
||||||
#define d(which) damage_csd(which, is_focused ? decs.which.buffer.front : decs.which.buffer.back);
|
#define d(which) damage_csd(which, is_focused ? decs.which.buffer.front : decs.which.buffer.back);
|
||||||
d(shadow_left); d(shadow_right); d(shadow_top); d(shadow_bottom);
|
d(shadow_left); d(shadow_right); d(shadow_top); d(shadow_bottom);
|
||||||
d(shadow_upper_left); d(shadow_upper_right); d(shadow_lower_left); d(shadow_lower_right);
|
d(shadow_upper_left); d(shadow_upper_right); d(shadow_lower_left); d(shadow_lower_right);
|
||||||
|
|
@ -659,17 +676,18 @@ csd_change_title(_GLFWwindow *window) {
|
||||||
void
|
void
|
||||||
csd_set_window_geometry(_GLFWwindow *window, int32_t *width, int32_t *height) {
|
csd_set_window_geometry(_GLFWwindow *window, int32_t *width, int32_t *height) {
|
||||||
const bool include_space_for_csd = csd_should_window_be_decorated(window);
|
const bool include_space_for_csd = csd_should_window_be_decorated(window);
|
||||||
|
const bool has_titlebar = include_space_for_csd && !decs.titlebar_hidden;
|
||||||
bool size_specified_by_compositor = *width > 0 && *height > 0;
|
bool size_specified_by_compositor = *width > 0 && *height > 0;
|
||||||
if (!size_specified_by_compositor) {
|
if (!size_specified_by_compositor) {
|
||||||
*width = window->wl.user_requested_content_size.width;
|
*width = window->wl.user_requested_content_size.width;
|
||||||
*height = window->wl.user_requested_content_size.height;
|
*height = window->wl.user_requested_content_size.height;
|
||||||
if (window->wl.xdg.top_level_bounds.width > 0) *width = MIN(*width, window->wl.xdg.top_level_bounds.width);
|
if (window->wl.xdg.top_level_bounds.width > 0) *width = MIN(*width, window->wl.xdg.top_level_bounds.width);
|
||||||
if (window->wl.xdg.top_level_bounds.height > 0) *height = MIN(*height, window->wl.xdg.top_level_bounds.height);
|
if (window->wl.xdg.top_level_bounds.height > 0) *height = MIN(*height, window->wl.xdg.top_level_bounds.height);
|
||||||
if (include_space_for_csd) *height += decs.metrics.visible_titlebar_height;
|
if (has_titlebar) *height += decs.metrics.visible_titlebar_height;
|
||||||
}
|
}
|
||||||
decs.geometry.x = 0; decs.geometry.y = 0;
|
decs.geometry.x = 0; decs.geometry.y = 0;
|
||||||
decs.geometry.width = *width; decs.geometry.height = *height;
|
decs.geometry.width = *width; decs.geometry.height = *height;
|
||||||
if (include_space_for_csd) {
|
if (has_titlebar) {
|
||||||
decs.geometry.y = -decs.metrics.visible_titlebar_height;
|
decs.geometry.y = -decs.metrics.visible_titlebar_height;
|
||||||
*height -= decs.metrics.visible_titlebar_height;
|
*height -= decs.metrics.visible_titlebar_height;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
glfw/wl_platform.h
vendored
2
glfw/wl_platform.h
vendored
|
|
@ -231,7 +231,7 @@ typedef struct _GLFWwindowWayland
|
||||||
} pointerLock;
|
} pointerLock;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool serverSide, buffer_destroyed, titlebar_needs_update, dragging;
|
bool serverSide, buffer_destroyed, titlebar_needs_update, dragging, titlebar_hidden;
|
||||||
_GLFWCSDSurface focus;
|
_GLFWCSDSurface focus;
|
||||||
|
|
||||||
_GLFWWaylandCSDSurface titlebar, shadow_left, shadow_right, shadow_top, shadow_bottom, shadow_upper_left, shadow_upper_right, shadow_lower_left, shadow_lower_right;
|
_GLFWWaylandCSDSurface titlebar, shadow_left, shadow_right, shadow_top, shadow_bottom, shadow_upper_left, shadow_upper_right, shadow_lower_left, shadow_lower_right;
|
||||||
|
|
|
||||||
25
glfw/wl_window.c
vendored
25
glfw/wl_window.c
vendored
|
|
@ -813,6 +813,8 @@ apply_xdg_configure_changes(_GLFWwindow *window) {
|
||||||
if (window->wl.pending_state & PENDING_STATE_DECORATION) {
|
if (window->wl.pending_state & PENDING_STATE_DECORATION) {
|
||||||
uint32_t mode = window->wl.pending.decoration_mode;
|
uint32_t mode = window->wl.pending.decoration_mode;
|
||||||
bool has_server_side_decorations = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
bool has_server_side_decorations = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||||
|
// Force CSD when decorations are hidden or titlebar is hidden
|
||||||
|
if (!window->decorated || window->wl.decorations.titlebar_hidden) has_server_side_decorations = false;
|
||||||
window->wl.decorations.serverSide = has_server_side_decorations;
|
window->wl.decorations.serverSide = has_server_side_decorations;
|
||||||
window->wl.current.decoration_mode = mode;
|
window->wl.current.decoration_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
@ -960,8 +962,14 @@ static void
|
||||||
setXdgDecorations(_GLFWwindow* window)
|
setXdgDecorations(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window->wl.xdg.decoration) {
|
if (window->wl.xdg.decoration) {
|
||||||
window->wl.decorations.serverSide = true;
|
if (window->wl.decorations.titlebar_hidden) {
|
||||||
zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, window->decorated ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE: ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE);
|
window->wl.decorations.serverSide = false;
|
||||||
|
zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE);
|
||||||
|
csd_set_visible(window, csd_should_window_be_decorated(window));
|
||||||
|
} else {
|
||||||
|
window->wl.decorations.serverSide = true;
|
||||||
|
zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, window->decorated ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE: ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
window->wl.decorations.serverSide = false;
|
window->wl.decorations.serverSide = false;
|
||||||
csd_set_visible(window, csd_should_window_be_decorated(window));
|
csd_set_visible(window, csd_should_window_be_decorated(window));
|
||||||
|
|
@ -1707,7 +1715,8 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||||
if (window->decorated && !window->monitor && !window->wl.decorations.serverSide)
|
if (window->decorated && !window->monitor && !window->wl.decorations.serverSide)
|
||||||
{
|
{
|
||||||
if (top)
|
if (top)
|
||||||
*top = window->wl.decorations.metrics.top - window->wl.decorations.metrics.visible_titlebar_height;
|
*top = window->wl.decorations.titlebar_hidden ? 0 :
|
||||||
|
window->wl.decorations.metrics.top - window->wl.decorations.metrics.visible_titlebar_height;
|
||||||
if (left)
|
if (left)
|
||||||
*left = window->wl.decorations.metrics.width;
|
*left = window->wl.decorations.metrics.width;
|
||||||
if (right)
|
if (right)
|
||||||
|
|
@ -3034,6 +3043,16 @@ GLFWAPI void glfwWaylandRedrawCSDWindowTitle(GLFWwindow *handle) {
|
||||||
if (csd_change_title(window)) commit_window_surface_if_safe(window);
|
if (csd_change_title(window)) commit_window_surface_if_safe(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwWaylandSetTitlebarHidden(GLFWwindow *handle, bool hidden) {
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
if (window->wl.decorations.titlebar_hidden != hidden) {
|
||||||
|
window->wl.decorations.titlebar_hidden = hidden;
|
||||||
|
setXdgDecorations(window);
|
||||||
|
inform_compositor_of_window_geometry(window, "SetTitlebarHidden");
|
||||||
|
commit_window_surface_if_safe(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const GLFWLayerShellConfig*
|
const GLFWLayerShellConfig*
|
||||||
_glfwPlatformGetLayerShellConfig(_GLFWwindow *window) {
|
_glfwPlatformGetLayerShellConfig(_GLFWwindow *window) {
|
||||||
return &window->wl.layer_shell.config;
|
return &window->wl.layer_shell.config;
|
||||||
|
|
|
||||||
3
kitty/glfw-wrapper.c
generated
3
kitty/glfw-wrapper.c
generated
|
|
@ -515,6 +515,9 @@ load_glfw(const char* path) {
|
||||||
*(void **) (&glfwWaylandSetTitlebarColor_impl) = dlsym(handle, "glfwWaylandSetTitlebarColor");
|
*(void **) (&glfwWaylandSetTitlebarColor_impl) = dlsym(handle, "glfwWaylandSetTitlebarColor");
|
||||||
if (glfwWaylandSetTitlebarColor_impl == NULL) dlerror(); // clear error indicator
|
if (glfwWaylandSetTitlebarColor_impl == NULL) dlerror(); // clear error indicator
|
||||||
|
|
||||||
|
*(void **) (&glfwWaylandSetTitlebarHidden_impl) = dlsym(handle, "glfwWaylandSetTitlebarHidden");
|
||||||
|
if (glfwWaylandSetTitlebarHidden_impl == NULL) dlerror(); // clear error indicator
|
||||||
|
|
||||||
*(void **) (&glfwWaylandRedrawCSDWindowTitle_impl) = dlsym(handle, "glfwWaylandRedrawCSDWindowTitle");
|
*(void **) (&glfwWaylandRedrawCSDWindowTitle_impl) = dlsym(handle, "glfwWaylandRedrawCSDWindowTitle");
|
||||||
if (glfwWaylandRedrawCSDWindowTitle_impl == NULL) dlerror(); // clear error indicator
|
if (glfwWaylandRedrawCSDWindowTitle_impl == NULL) dlerror(); // clear error indicator
|
||||||
|
|
||||||
|
|
|
||||||
4
kitty/glfw-wrapper.h
generated
4
kitty/glfw-wrapper.h
generated
|
|
@ -2516,6 +2516,10 @@ typedef bool (*glfwWaylandSetTitlebarColor_func)(GLFWwindow*, uint32_t, bool);
|
||||||
GFW_EXTERN glfwWaylandSetTitlebarColor_func glfwWaylandSetTitlebarColor_impl;
|
GFW_EXTERN glfwWaylandSetTitlebarColor_func glfwWaylandSetTitlebarColor_impl;
|
||||||
#define glfwWaylandSetTitlebarColor glfwWaylandSetTitlebarColor_impl
|
#define glfwWaylandSetTitlebarColor glfwWaylandSetTitlebarColor_impl
|
||||||
|
|
||||||
|
typedef void (*glfwWaylandSetTitlebarHidden_func)(GLFWwindow*, bool);
|
||||||
|
GFW_EXTERN glfwWaylandSetTitlebarHidden_func glfwWaylandSetTitlebarHidden_impl;
|
||||||
|
#define glfwWaylandSetTitlebarHidden glfwWaylandSetTitlebarHidden_impl
|
||||||
|
|
||||||
typedef void (*glfwWaylandRedrawCSDWindowTitle_func)(GLFWwindow*);
|
typedef void (*glfwWaylandRedrawCSDWindowTitle_func)(GLFWwindow*);
|
||||||
GFW_EXTERN glfwWaylandRedrawCSDWindowTitle_func glfwWaylandRedrawCSDWindowTitle_impl;
|
GFW_EXTERN glfwWaylandRedrawCSDWindowTitle_func glfwWaylandRedrawCSDWindowTitle_impl;
|
||||||
#define glfwWaylandRedrawCSDWindowTitle glfwWaylandRedrawCSDWindowTitle_impl
|
#define glfwWaylandRedrawCSDWindowTitle glfwWaylandRedrawCSDWindowTitle_impl
|
||||||
|
|
|
||||||
|
|
@ -1308,6 +1308,10 @@ apply_window_chrome_state(GLFWwindow *w, WindowChromeState new_state, int width,
|
||||||
// Need to resize the window again after hiding decorations or title bar to take up screen space
|
// 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);
|
if (window_decorations_changed) glfwSetWindowSize(w, width, height);
|
||||||
#else
|
#else
|
||||||
|
if (global_state.is_wayland && glfwWaylandSetTitlebarHidden) {
|
||||||
|
bool titlebar_only = (new_state.hide_window_decorations & 2) != 0;
|
||||||
|
glfwWaylandSetTitlebarHidden(w, titlebar_only);
|
||||||
|
}
|
||||||
if (window_decorations_changed) {
|
if (window_decorations_changed) {
|
||||||
bool hide_window_decorations = new_state.hide_window_decorations & 1;
|
bool hide_window_decorations = new_state.hide_window_decorations & 1;
|
||||||
glfwSetWindowAttrib(w, GLFW_DECORATED, !hide_window_decorations);
|
glfwSetWindowAttrib(w, GLFW_DECORATED, !hide_window_decorations);
|
||||||
|
|
@ -1587,6 +1591,10 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
||||||
if (temp_window) { glfwDestroyWindow(temp_window); temp_window = NULL; }
|
if (temp_window) { glfwDestroyWindow(temp_window); temp_window = NULL; }
|
||||||
if (glfw_window == NULL) glfw_failure;
|
if (glfw_window == NULL) glfw_failure;
|
||||||
#undef glfw_failure
|
#undef glfw_failure
|
||||||
|
// Set titlebar-only mode before the window becomes visible
|
||||||
|
if (global_state.is_wayland && (OPT(hide_window_decorations) & 2) && glfwWaylandSetTitlebarHidden) {
|
||||||
|
glfwWaylandSetTitlebarHidden(glfw_window, true);
|
||||||
|
}
|
||||||
glfwMakeContextCurrent(glfw_window);
|
glfwMakeContextCurrent(glfw_window);
|
||||||
if (is_first_window) gl_init();
|
if (is_first_window) gl_init();
|
||||||
bool is_semi_transparent = glfwGetWindowAttrib(glfw_window, GLFW_TRANSPARENT_FRAMEBUFFER);
|
bool is_semi_transparent = glfwGetWindowAttrib(glfw_window, GLFW_TRANSPARENT_FRAMEBUFFER);
|
||||||
|
|
|
||||||
|
|
@ -1341,9 +1341,13 @@
|
||||||
long_text='''
|
long_text='''
|
||||||
Hide the window decorations (title-bar and window borders) with :code:`yes`. On
|
Hide the window decorations (title-bar and window borders) with :code:`yes`. On
|
||||||
macOS, :code:`titlebar-only` and :code:`titlebar-and-corners` can be used to only hide the titlebar and the rounded corners.
|
macOS, :code:`titlebar-only` and :code:`titlebar-and-corners` can be used to only hide the titlebar and the rounded corners.
|
||||||
|
On Wayland, :code:`titlebar-only` can be used to hide the titlebar while keeping
|
||||||
|
the window shadow borders for resizing. On compositors that use server-side
|
||||||
|
decorations (such as GNOME), both :code:`yes` and :code:`titlebar-only` force
|
||||||
|
client-side decoration mode.
|
||||||
Whether this works and exactly what effect it has depends on the window manager/operating
|
Whether this works and exactly what effect it has depends on the window manager/operating
|
||||||
system. Note that the effects of changing this option when reloading config
|
system. Note that the effects of changing this option when reloading config
|
||||||
are undefined. When using :code:`titlebar-only`, it is useful to also set
|
are undefined. When using :code:`titlebar-only` on macOS, it is useful to also set
|
||||||
:opt:`window_margin_width` and :opt:`placement_strategy` to prevent the rounded
|
:opt:`window_margin_width` and :opt:`placement_strategy` to prevent the rounded
|
||||||
corners from clipping text. Or use :code:`titlebar-and-corners`.
|
corners from clipping text. Or use :code:`titlebar-and-corners`.
|
||||||
'''
|
'''
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue