Refactor layer shell size callback to support multiple backends

This commit is contained in:
Kovid Goyal 2025-04-23 06:53:22 +05:30
parent c9bf7e4236
commit ae01cf3c1c
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
5 changed files with 64 additions and 50 deletions

View file

@ -1927,6 +1927,7 @@ screen_for_window_center(_GLFWwindow *window) {
bool
_glfwPlatformSetLayerShellConfig(_GLFWwindow* window, const GLFWLayerShellConfig *value) {
#define config window->ns.layer_shell.config
window->resizable = false;
const bool is_transparent = ![window->ns.object isOpaque];
int background_blur = value->related.background_blur;
@ -1953,11 +1954,15 @@ _glfwPlatformSetLayerShellConfig(_GLFWwindow* window, const GLFWLayerShellConfig
[window->ns.object makeFirstResponder:window->ns.view];
uint32_t width = 0, height = 0;
NSScreen *screen = screen_for_window_center(window);
CGFloat monitor_width = NSWidth(screen.frame), monitor_height = NSHeight(screen.frame);
window->ns.layer_shell.config.size_callback((GLFWwindow*)window, &window->ns.layer_shell.config, (unsigned)monitor_width, (unsigned)monitor_height, &width, &height);
// CGFloat monitor_width = NSWidth(screen.frame), monitor_height = NSHeight(screen.frame);
unsigned cell_width, cell_height; double left_edge_spacing, top_edge_spacing, right_edge_spacing, bottom_edge_spacing;
float xscale = (float)config.expected.xscale, yscale = (float)config.expected.yscale;
_glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
config.size_callback((GLFWwindow*)window, xscale, yscale, &cell_width, &cell_height, &left_edge_spacing, &top_edge_spacing, &right_edge_spacing, &bottom_edge_spacing);
CGFloat x = NSMinX(screen.visibleFrame), y = NSMinY(screen.visibleFrame);
[window->ns.object setFrame:NSMakeRect(x, y, (CGFloat)width, (CGFloat)height) display:YES];
return true;
#undef config
}
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)

4
glfw/glfw3.h vendored
View file

@ -1319,8 +1319,8 @@ typedef struct GLFWLayerShellConfig {
unsigned requested_right_margin;
int requested_exclusive_zone;
unsigned override_exclusive_zone;
void (*size_callback)(GLFWwindow *window, const struct GLFWLayerShellConfig *config, unsigned monitor_width, unsigned monitor_height, uint32_t *width, uint32_t *height);
struct { double xdpi, ydpi, xscale, yscale; } expected;
void (*size_callback)(GLFWwindow *window, float xscale, float yscale, unsigned *cell_width, unsigned *cell_height, double *left_edge_spacing, double *top_edge_spacing, double *right_edge_spacing, double *bottom_edge_spacing);
struct { float xscale, yscale; } expected;
struct {
float background_opacity; int background_blur, color_space;
} related;

45
glfw/wl_window.c vendored
View file

@ -1035,6 +1035,48 @@ layer_set_properties(_GLFWwindow *window) {
#undef surface
}
static void
calculate_layer_size(_GLFWwindow *window, uint32_t *width, uint32_t *height) {
const GLFWLayerShellConfig *config = &window->wl.layer_shell.config;
GLFWvidmode m = {0};
if (window->wl.monitorsCount) _glfwPlatformGetVideoMode(window->wl.monitors[0], &m);
const int y_margin = config->requested_bottom_margin + config->requested_top_margin, x_margin = config->requested_left_margin + config->requested_right_margin;
const int monitor_width = MAX(0, m.width - x_margin), monitor_height = MAX(0, m.height - y_margin);
float xscale = (float)config->expected.xscale, yscale = (float)config->expected.yscale;
if (window->wl.window_fully_created) _glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
unsigned cell_width, cell_height; double left_edge_spacing, top_edge_spacing, right_edge_spacing, bottom_edge_spacing;
config->size_callback((GLFWwindow*)window, xscale, yscale, &cell_width, &cell_height, &left_edge_spacing, &top_edge_spacing, &right_edge_spacing, &bottom_edge_spacing);
double spacing_x = left_edge_spacing + right_edge_spacing;
double spacing_y = top_edge_spacing + bottom_edge_spacing;
if (config->type == GLFW_LAYER_SHELL_BACKGROUND) {
if (!*width) *width = monitor_width;
if (!*height) *height = monitor_height;
return;
}
debug("Calculating layer shell window size at scale: %f\n", xscale);
const unsigned xsz = config->x_size_in_pixels ? (unsigned)(config->x_size_in_pixels * xscale) : (cell_width * config->x_size_in_cells);
const unsigned ysz = config->y_size_in_pixels ? (unsigned)(config->y_size_in_pixels * yscale) : (cell_height * config->y_size_in_cells);
if (config->edge == GLFW_EDGE_LEFT || config->edge == GLFW_EDGE_RIGHT) {
if (!*height) *height = monitor_height;
double spacing = spacing_x;
spacing += xsz / xscale;
*width = (uint32_t)(1. + spacing);
} else if (config->edge == GLFW_EDGE_TOP || config->edge == GLFW_EDGE_BOTTOM) {
if (!*width) *width = monitor_width;
double spacing = spacing_y;
spacing += ysz / yscale;
*height = (uint32_t)(1. + spacing);
} else if (config->edge == GLFW_EDGE_CENTER) {
if (!*width) *width = monitor_width;
if (!*height) *height = monitor_height;
} else {
spacing_x += xsz / xscale;
spacing_y += ysz / yscale;
*width = (uint32_t)(1. + spacing_x);
*height = (uint32_t)(1. + spacing_y);
}
}
static void
layer_surface_handle_configure(void* data, struct zwlr_layer_surface_v1* surface, uint32_t serial, uint32_t width, uint32_t height) {
debug("Layer shell configure event: width: %u height: %u\n", width, height);
@ -1047,8 +1089,7 @@ layer_surface_handle_configure(void* data, struct zwlr_layer_surface_v1* surface
}
GLFWvidmode m = {0};
if (window->wl.monitorsCount) _glfwPlatformGetVideoMode(window->wl.monitors[0], &m);
window->wl.layer_shell.config.size_callback(
(GLFWwindow*)window, &window->wl.layer_shell.config, m.width, m.height, &width, &height);
calculate_layer_size(window, &width, &height);
zwlr_layer_surface_v1_ack_configure(surface, serial);
if ((int)width != window->wl.width || (int)height != window->wl.height) {
debug("Layer shell size changed to %ux%u in layer_surface_handle_configure\n", width, height);

4
kitty/glfw-wrapper.h generated
View file

@ -1057,8 +1057,8 @@ typedef struct GLFWLayerShellConfig {
unsigned requested_right_margin;
int requested_exclusive_zone;
unsigned override_exclusive_zone;
void (*size_callback)(GLFWwindow *window, const struct GLFWLayerShellConfig *config, unsigned monitor_width, unsigned monitor_height, uint32_t *width, uint32_t *height);
struct { double xdpi, ydpi, xscale, yscale; } expected;
void (*size_callback)(GLFWwindow *window, float xscale, float yscale, unsigned *cell_width, unsigned *cell_height, double *left_edge_spacing, double *top_edge_spacing, double *right_edge_spacing, double *bottom_edge_spacing);
struct { float xscale, yscale; } expected;
struct {
float background_opacity; int background_blur, color_space;
} related;

View file

@ -1125,49 +1125,17 @@ edge_spacing(GLFWEdge which) {
static void
calculate_layer_shell_window_size(
GLFWwindow *window, const GLFWLayerShellConfig *config, unsigned monitor_width, unsigned monitor_height, uint32_t *width, uint32_t *height) {
request_tick_callback();
if (config->type == GLFW_LAYER_SHELL_BACKGROUND) {
if (!*width) *width = monitor_width;
if (!*height) *height = monitor_height;
return;
}
float xscale = (float)config->expected.xscale, yscale = (float)config->expected.yscale;
double xdpi = config->expected.xdpi, ydpi = config->expected.ydpi;
if (global_state.is_apple || (global_state.is_wayland && glfwWaylandIsWindowFullyCreated(window))) {
glfwGetWindowContentScale(window, &xscale, &yscale);
dpi_from_scale(xscale, yscale, &xdpi, &ydpi);
}
GLFWwindow *window, float xscale, float yscale, unsigned *cell_width, unsigned *cell_height, double *left_edge_spacing, double *top_edge_spacing, double *right_edge_spacing, double *bottom_edge_spacing) {
OSWindow *os_window = os_window_for_glfw_window(window);
debug("Calculating layer shell window size at scale: %f\n", xscale);
double xdpi, ydpi;
dpi_from_scale(xscale, yscale, &xdpi, &ydpi);
FONTS_DATA_HANDLE fonts_data = load_fonts_data(os_window ? os_window->fonts_data->font_sz_in_pts : OPT(font_size), xdpi, ydpi);
const unsigned xsz = config->x_size_in_pixels ? (unsigned)(config->x_size_in_pixels * xscale) : (fonts_data->fcm.cell_width * config->x_size_in_cells);
const unsigned ysz = config->y_size_in_pixels ? (unsigned)(config->y_size_in_pixels * yscale) : (fonts_data->fcm.cell_height * config->y_size_in_cells);
if (config->edge == GLFW_EDGE_LEFT || config->edge == GLFW_EDGE_RIGHT) {
if (!*height) *height = monitor_height;
double spacing = edge_spacing(GLFW_EDGE_LEFT) + edge_spacing(GLFW_EDGE_RIGHT);
spacing *= xdpi / 72.;
spacing += xsz / xscale;
*width = (uint32_t)(1. + spacing);
} else if (config->edge == GLFW_EDGE_TOP || config->edge == GLFW_EDGE_BOTTOM) {
if (!*width) *width = monitor_width;
double spacing = edge_spacing(GLFW_EDGE_TOP) + edge_spacing(GLFW_EDGE_BOTTOM);
spacing *= ydpi / 72.;
spacing += ysz / yscale;
*height = (uint32_t)(1. + spacing);
} else if (config->edge == GLFW_EDGE_CENTER) {
if (!*width) *width = monitor_width;
if (!*height) *height = monitor_height;
} else {
double spacing_x = edge_spacing(GLFW_EDGE_LEFT) + edge_spacing(GLFW_EDGE_RIGHT);
spacing_x *= xdpi / 72.;
spacing_x += xsz / xscale;
double spacing_y = edge_spacing(GLFW_EDGE_TOP) + edge_spacing(GLFW_EDGE_BOTTOM);
spacing_y *= ydpi / 72.;
spacing_y += ysz / yscale;
*width = (uint32_t)(1. + spacing_x);
*height = (uint32_t)(1. + spacing_y);
}
*cell_width = fonts_data->fcm.cell_width; *cell_height = fonts_data->fcm.cell_height;
double x_factor = xdpi / 72., y_factor = ydpi / 72.;
*left_edge_spacing = edge_spacing(GLFW_EDGE_LEFT) * x_factor;
*top_edge_spacing = edge_spacing(GLFW_EDGE_TOP) * y_factor;
*right_edge_spacing = edge_spacing(GLFW_EDGE_RIGHT) * x_factor;
*bottom_edge_spacing = edge_spacing(GLFW_EDGE_BOTTOM) * y_factor;
}
static PyObject*
@ -1352,7 +1320,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
Py_CLEAR(ret);
if (lsc) {
if (!layer_shell_config_from_python(layer_shell_config, lsc)) return NULL;
lsc->expected.xdpi = xdpi; lsc->expected.ydpi = ydpi; lsc->expected.xscale = xscale; lsc->expected.yscale = yscale;
lsc->expected.xscale = xscale; lsc->expected.yscale = yscale;
}
GLFWwindow *glfw_window = glfwCreateWindow(width, height, title, NULL, temp_window ? temp_window : common_context, lsc);
if (temp_window) { glfwDestroyWindow(temp_window); temp_window = NULL; }