More precise error on resize panel attempt

This commit is contained in:
Kovid Goyal 2025-04-21 12:32:20 +05:30
parent 796ee602de
commit 64b5d2d187
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
11 changed files with 40 additions and 16 deletions

View file

@ -325,6 +325,7 @@ def generate_wrappers(glfw_header: str) -> None:
void glfwWaylandRedrawCSDWindowTitle(GLFWwindow *handle)
bool glfwWaylandIsWindowFullyCreated(GLFWwindow *handle)
bool glfwWaylandBeep(GLFWwindow *handle)
GLFWLayerShellConfig* glfwWaylandLayerShellConfig(GLFWwindow *handle)
void glfwWaylandSetupLayerShellForNextWindow(const GLFWLayerShellConfig *c)
pid_t glfwWaylandCompositorPID(void)
unsigned long long glfwDBusUserNotify(const GLFWDBUSNotificationData *n, GLFWDBusnotificationcreatedfun callback, void *data)

4
glfw/glfw3.h vendored
View file

@ -1311,8 +1311,8 @@ typedef struct GLFWLayerShellConfig {
GLFWEdge edge;
char output_name[64];
GLFWFocusPolicy focus_policy;
unsigned x_size_in_cells;
unsigned y_size_in_cells;
unsigned x_size_in_cells, x_size_in_pixels;
unsigned y_size_in_cells, y_size_in_pixels;
unsigned requested_top_margin;
unsigned requested_left_margin;
unsigned requested_bottom_margin;

4
glfw/wl_window.c vendored
View file

@ -2830,6 +2830,10 @@ GLFWAPI void glfwWaylandSetupLayerShellForNextWindow(const GLFWLayerShellConfig
layer_shell_config_for_next_window = *c;
}
GLFWAPI GLFWLayerShellConfig* glfwWaylandLayerShellConfig(GLFWwindow *handle) {
return &((_GLFWwindow*)handle)->wl.layer_shell.config;
}
GLFWAPI bool glfwWaylandIsWindowFullyCreated(GLFWwindow *handle) { return handle != NULL && ((_GLFWwindow*)handle)->wl.window_fully_created; }
void

View file

@ -147,6 +147,7 @@ from .window import CommandOutput, CwdRequest, Window
if TYPE_CHECKING:
from .fast_data_types import OSWindowSize
from .rc.base import ResponseType
# }}}
@ -1582,12 +1583,14 @@ class Boss:
return None
return tab.resize_window_by(window.id, increment, is_horizontal)
def resize_os_window(self, os_window_id: int, width: int, height: int, unit: str, incremental: bool = False) -> None:
def resize_os_window(self, os_window_id: int, width: int, height: int, unit: str, incremental: bool = False, metrics: 'None | OSWindowSize' = None) -> None:
if not incremental and (width < 0 or height < 0):
return
metrics = get_os_window_size(os_window_id)
metrics = get_os_window_size(os_window_id) if metrics is None else metrics
if metrics is None:
return
if metrics['is_layer_shell']:
raise TypeError(f'The OS Window {os_window_id} is a panel and cannot be resized')
has_window_scaling = is_macos or is_wayland()
w, h = get_new_os_window_size(metrics, width, height, unit, incremental, has_window_scaling)
set_os_window_size(os_window_id, w, h)

View file

@ -1545,6 +1545,7 @@ class OSWindowSize(TypedDict):
ydpi: float
cell_width: int
cell_height: int
is_layer_shell: bool
def mark_os_window_dirty(os_window_id: int) -> None:

3
kitty/glfw-wrapper.c generated
View file

@ -491,6 +491,9 @@ load_glfw(const char* path) {
*(void **) (&glfwWaylandBeep_impl) = dlsym(handle, "glfwWaylandBeep");
if (glfwWaylandBeep_impl == NULL) dlerror(); // clear error indicator
*(void **) (&glfwWaylandLayerShellConfig_impl) = dlsym(handle, "glfwWaylandLayerShellConfig");
if (glfwWaylandLayerShellConfig_impl == NULL) dlerror(); // clear error indicator
*(void **) (&glfwWaylandSetupLayerShellForNextWindow_impl) = dlsym(handle, "glfwWaylandSetupLayerShellForNextWindow");
if (glfwWaylandSetupLayerShellForNextWindow_impl == NULL) dlerror(); // clear error indicator

8
kitty/glfw-wrapper.h generated
View file

@ -1049,8 +1049,8 @@ typedef struct GLFWLayerShellConfig {
GLFWEdge edge;
char output_name[64];
GLFWFocusPolicy focus_policy;
unsigned x_size_in_cells;
unsigned y_size_in_cells;
unsigned x_size_in_cells, x_size_in_pixels;
unsigned y_size_in_cells, y_size_in_pixels;
unsigned requested_top_margin;
unsigned requested_left_margin;
unsigned requested_bottom_margin;
@ -2348,6 +2348,10 @@ typedef bool (*glfwWaylandBeep_func)(GLFWwindow*);
GFW_EXTERN glfwWaylandBeep_func glfwWaylandBeep_impl;
#define glfwWaylandBeep glfwWaylandBeep_impl
typedef GLFWLayerShellConfig* (*glfwWaylandLayerShellConfig_func)(GLFWwindow*);
GFW_EXTERN glfwWaylandLayerShellConfig_func glfwWaylandLayerShellConfig_impl;
#define glfwWaylandLayerShellConfig glfwWaylandLayerShellConfig_impl
typedef void (*glfwWaylandSetupLayerShellForNextWindow_func)(const GLFWLayerShellConfig*);
GFW_EXTERN glfwWaylandSetupLayerShellForNextWindow_func glfwWaylandSetupLayerShellForNextWindow_impl;
#define glfwWaylandSetupLayerShellForNextWindow glfwWaylandSetupLayerShellForNextWindow_impl

View file

@ -1141,17 +1141,19 @@ calculate_layer_shell_window_size(
OSWindow *os_window = os_window_for_glfw_window(window);
debug("Calculating layer shell window size at scale: %f\n", xscale);
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 ? config->x_size_in_pixels : (fonts_data->fcm.cell_width * config->x_size_in_cells);
const unsigned ysz = config->y_size_in_pixels ? config->y_size_in_pixels : (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 += (fonts_data->fcm.cell_width * config->x_size_in_cells) / xscale;
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 += (fonts_data->fcm.cell_height * config->y_size_in_cells) / yscale;
spacing += ysz / yscale;
*height = (uint32_t)(1. + spacing);
} else if (config->edge == GLFW_EDGE_CENTER) {
if (!*width) *width = monitor_width;
@ -1159,10 +1161,10 @@ calculate_layer_shell_window_size(
} else {
double spacing_x = edge_spacing(GLFW_EDGE_LEFT) + edge_spacing(GLFW_EDGE_RIGHT);
spacing_x *= xdpi / 72.;
spacing_x += (fonts_data->fcm.cell_width * config->x_size_in_cells) / xscale;
spacing_x += xsz / xscale;
double spacing_y = edge_spacing(GLFW_EDGE_TOP) + edge_spacing(GLFW_EDGE_BOTTOM);
spacing_y *= ydpi / 72.;
spacing_y += (fonts_data->fcm.cell_height * config->y_size_in_cells) / yscale;
spacing_y += ysz / yscale;
*width = (uint32_t)(1. + spacing_x);
*height = (uint32_t)(1. + spacing_y);
}
@ -1355,6 +1357,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
OSWindow *w = add_os_window();
w->handle = glfw_window;
w->disallow_title_changes = disallow_override_title;
w->is_layer_shell = is_layer_shell;
update_os_window_references();
if (!is_layer_shell) {
for (size_t i = 0; i < global_state.num_os_windows; i++) {

View file

@ -3,6 +3,8 @@
from typing import TYPE_CHECKING
from kitty.fast_data_types import get_os_window_size
from .base import (
MATCH_WINDOW_OPTION,
ArgsType,
@ -88,17 +90,19 @@ using this option means that you will not be notified of failures.
}
def response_from_kitty(self, boss: Boss, window: Window | None, payload_get: PayloadGetType) -> ResponseType:
from kitty.main import is_panel_kitten
if is_panel_kitten():
raise RemoteControlErrorWithoutTraceback('Resizing of panels created by the panel kitten is not supported')
windows = self.windows_for_match_payload(boss, window, payload_get)
if windows:
ac = payload_get('action')
for os_window_id in {w.os_window_id for w in windows if w}:
metrics = get_os_window_size(os_window_id)
if metrics is None:
raise RemoteControlErrorWithoutTraceback(f'The OS Window {os_window_id} does not exist')
if metrics['is_layer_shell']:
raise RemoteControlErrorWithoutTraceback(f'The OS Window {os_window_id} is a panel and cannot be resized')
if ac == 'resize':
boss.resize_os_window(
os_window_id, width=payload_get('width'), height=payload_get('height'),
unit=payload_get('unit'), incremental=payload_get('incremental')
unit=payload_get('unit'), incremental=payload_get('incremental'), metrics=metrics,
)
elif ac == 'toggle-fullscreen':
boss.toggle_fullscreen(os_window_id)

View file

@ -1123,10 +1123,10 @@ PYWRAP1(get_os_window_size) {
get_os_window_size(os_window, &width, &height, &fw, &fh);
get_os_window_content_scale(os_window, &xdpi, &ydpi, &xscale, &yscale);
unsigned int cell_width = os_window->fonts_data->fcm.cell_width, cell_height = os_window->fonts_data->fcm.cell_height;
return Py_BuildValue("{si si si si sf sf sd sd sI sI}",
return Py_BuildValue("{si si si si sf sf sd sd sI sI sO}",
"width", width, "height", height, "framebuffer_width", fw, "framebuffer_height", fh,
"xscale", xscale, "yscale", yscale, "xdpi", xdpi, "ydpi", ydpi,
"cell_width", cell_width, "cell_height", cell_height);
"cell_width", cell_width, "cell_height", cell_height, "is_layer_shell", os_window->is_layer_shell ? Py_True : Py_False);
END_WITH_OS_WINDOW
Py_RETURN_NONE;
}

View file

@ -312,6 +312,7 @@ typedef struct {
uint64_t render_calls;
id_type last_focused_counter;
CloseRequest close_request;
bool is_layer_shell;
} OSWindow;