Use the correct resize pointer shape on corners

This commit is contained in:
Kovid Goyal
2026-02-26 19:43:24 +05:30
parent 1a185e7027
commit 131a6ba8c6
6 changed files with 43 additions and 30 deletions

View File

@@ -24,17 +24,17 @@ class Border(NamedTuple):
right: int
bottom: int
color: BorderColor
is_actual_border: bool = False
border_type: int = 0
def vertical_edge(rects: list[Border], color: BorderColor, width: int, top: int, bottom: int, left: int) -> None:
def vertical_edge(rects: list[Border], color: BorderColor, width: int, top: int, bottom: int, left: int, is_left: bool) -> None:
if width > 0:
rects.append(Border(left, top, left + width, bottom, color, True))
rects.append(Border(left, top, left + width, bottom, color, -1 if is_left else 1))
def horizontal_edge(rects: list[Border], color: BorderColor, height: int, left: int, right: int, top: int) -> None:
def horizontal_edge(rects: list[Border], color: BorderColor, height: int, left: int, right: int, top: int, is_top: bool) -> None:
if height > 0:
rects.append(Border(left, top, right, top + height, color, True))
rects.append(Border(left, top, right, top + height, color, -1 if is_top else 1))
def add_borders(rects: list[Border], color: BorderColor, wg: WindowGroup) -> None:
@@ -59,10 +59,10 @@ def add_borders(rects: list[Border], color: BorderColor, wg: WindowGroup) -> Non
right += width
bottom += width
pl = pr = pb = pt = width
h(pt, left, right, top)
h(pb, left, right, bt)
v(pl, top, bottom, left)
v(pr, top, bottom, lr)
h(pt, left, right, top, True)
h(pb, left, right, bt, False)
v(pl, top, bottom, left, True)
v(pr, top, bottom, lr, False)
def load_borders_program() -> None:
@@ -125,5 +125,5 @@ class Borders:
if draw_minimal_borders:
for border_line in current_layout.get_minimal_borders(all_windows):
rects.append(Border(*border_line.edges, border_line.color, is_actual_border=True))
rects.append(Border(*border_line.edges, border_line.color, True))
set_borders_rects(self.os_window_id, self.tab_id, rects)

View File

@@ -57,6 +57,7 @@ from .constants import (
website_url,
)
from .fast_data_types import (
BOTTOM_EDGE,
CLOSE_BEING_CONFIRMED,
GLFW_FKEY_ESCAPE,
GLFW_MOD_ALT,
@@ -66,7 +67,10 @@ from .fast_data_types import (
GLFW_MOUSE_BUTTON_LEFT,
GLFW_PRESS,
IMPERATIVE_CLOSE_REQUESTED,
LEFT_EDGE,
NO_CLOSE_REQUESTED,
RIGHT_EDGE,
TOP_EDGE,
ChildMonitor,
Color,
EllipticCurveKey,
@@ -2420,11 +2424,12 @@ class Boss:
tab.set_active_window(window_id)
def drag_resize_start(
self, horizontal_allowed: bool, vertical_allowed: float, x: float, y: float,
window_id: int, cell_width: int, cell_height: int,
self, edges: int, x: float, y: float, window_id: int, cell_width: int, cell_height: int,
) -> bool:
if (w := self.window_id_map.get(window_id)) and (tab := w.tabref()):
horizontal, vertical = tab.current_layout.drag_resize_target_windows(w, x, y, tab.windows)
horizontal_allowed = bool(edges & (LEFT_EDGE | RIGHT_EDGE))
vertical_allowed = bool(edges & (TOP_EDGE | BOTTOM_EDGE))
self.drag_resize_of_window = WindowResizeDrag(
is_active=True, horizontal_target_window_id=horizontal.id if horizontal_allowed else 0,
vertical_target_window_id=vertical.id if vertical_allowed else 0,

View File

@@ -328,6 +328,8 @@ WINDOW_HIDDEN: int
TEXT_SIZE_CODE: int
TOP_EDGE: int
BOTTOM_EDGE: int
LEFT_EDGE: int
RIGHT_EDGE: int
# }}}

View File

@@ -254,10 +254,10 @@ contains_mouse(Window *w) {
}
static void
border_contains_mouse(BorderRect *br, double tolerance, bool *horizontal, bool *vertical) {
border_contains_mouse(BorderRect *br, double tolerance, Edge *edges) {
double x = global_state.callback_os_window->mouse_x, y = global_state.callback_os_window->mouse_y;
if ((int)br->px.left - tolerance <= x && x < (int)br->px.right + tolerance && (int)br->px.top - tolerance <= y && y < (int)br->px.bottom + tolerance) {
if (br->px.right - br->px.left > br->px.bottom - br->px.top) *horizontal = true; else *vertical = true;
if (br->px.right - br->px.left > br->px.bottom - br->px.top) *edges |= br->border_type < 1 ? LEFT_EDGE : RIGHT_EDGE; else *edges |= br->border_type < 1 ? TOP_EDGE : BOTTOM_EDGE;
}
}
@@ -894,7 +894,7 @@ mouse_in_region(Region *r) {
}
static Window*
window_for_event(unsigned int *window_idx, bool *in_tab_bar, int *window_border) {
window_for_event(unsigned int *window_idx, bool *in_tab_bar, Edge *window_border) {
Region central, tab_bar;
os_window_regions(global_state.callback_os_window, &central, &tab_bar);
const bool in_central = mouse_in_region(&central);
@@ -909,16 +909,14 @@ window_for_event(unsigned int *window_idx, bool *in_tab_bar, int *window_border)
if (in_central && w->num_tabs > 0) {
Tab *t = global_state.callback_os_window->tabs + global_state.callback_os_window->active_tab;
if (window_border) {
bool horizontal = false, vertical = false;
Edge edges = 0;
double dpi = (w->fonts_data->logical_dpi_x + w->fonts_data->logical_dpi_y) / 2.;
double tolerance = ((long)round((OPT(window_drag_tolerance) * (dpi / 72.0))));
for (unsigned i = 0; i < t->border_rects.num_border_rects && !(horizontal && vertical); i++) {
for (unsigned i = 0; i < t->border_rects.num_border_rects; i++) {
BorderRect *br = t->border_rects.rect_buf + i;
if (br->is_actual_border) border_contains_mouse(br, tolerance, &horizontal, &vertical);
if (br->border_type) border_contains_mouse(br, tolerance, &edges);
}
*window_border = 0;
if (horizontal) *window_border |= 1;
if (vertical) *window_border |= 2;
*window_border = edges;
}
for (unsigned int i = 0; i < t->num_windows; i++) {
if (contains_mouse(t->windows + i) && t->windows[i].render_data.screen) {
@@ -1167,7 +1165,7 @@ mouse_event(const int button, int modifiers, int action) {
}
return;
}
int window_border;
Edge window_border;
w = window_for_event(&window_idx, &in_tab_bar, &window_border);
set_currently_hovered_window(w ? w->id : 0, modifiers);
@@ -1179,12 +1177,18 @@ mouse_event(const int button, int modifiers, int action) {
debug("window border: %d\n", window_border);
w = window_for_event(&window_idx, &in_tab_bar, NULL);
if (!w) w = closest_window_for_event(&window_idx);
if (window_border & 1) mouse_cursor_shape = window_border & 2 ? NESW_RESIZE_POINTER : NS_RESIZE_POINTER;
else if (window_border & 2) mouse_cursor_shape = EW_RESIZE_POINTER;
if (window_border & LEFT_EDGE) {
if (window_border & TOP_EDGE) mouse_cursor_shape = NWSE_RESIZE_POINTER;
else if (window_border & BOTTOM_EDGE) mouse_cursor_shape = NESW_RESIZE_POINTER;
else mouse_cursor_shape = EW_RESIZE_POINTER;
} else if (window_border & RIGHT_EDGE) {
if (window_border & TOP_EDGE) mouse_cursor_shape = NESW_RESIZE_POINTER;
else if (window_border & BOTTOM_EDGE) mouse_cursor_shape = NWSE_RESIZE_POINTER;
else mouse_cursor_shape = EW_RESIZE_POINTER;
} else if (window_border & (TOP_EDGE | BOTTOM_EDGE)) mouse_cursor_shape = NS_RESIZE_POINTER;
if (w && button == GLFW_MOUSE_BUTTON_LEFT && w->render_data.screen) {
RAII_PyObject(r, PyObject_CallMethod(
global_state.boss, "drag_resize_start", "OOddKII",
window_border & 2 ? Py_True : Py_False, window_border & 1 ? Py_True : Py_False,
global_state.boss, "drag_resize_start", "iddKII", window_border,
osw->mouse_x, osw->mouse_y, w->id,
w->render_data.screen->cell_size.width, w->render_data.screen->cell_size.height));
if (r == NULL) { PyErr_Print(); return; }

View File

@@ -612,16 +612,16 @@ pyset_borders_rects(PyObject *self UNUSED, PyObject *args) {
ensure_space_for(br, rect_buf, BorderRect, br->num_border_rects + 1, capacity, 32, false);
for (unsigned i = 0; i < br->num_border_rects; i++) {
PyObject *pr = PyList_GET_ITEM(rects, i);
unsigned long color; int is_actual_border;
unsigned long color; int border_type;
BorderRect *r = br->rect_buf + i;
if (!PyArg_ParseTuple(
pr, "IIIIkp", &r->px.left, &r->px.top, &r->px.right, &r->px.bottom, &color, &is_actual_border
pr, "IIIIki", &r->px.left, &r->px.top, &r->px.right, &r->px.bottom, &color, &border_type
)) return NULL;
r->left = gl_pos_x(r->px.left, osw->viewport_width);
r->top = gl_pos_y(r->px.top, osw->viewport_height);
r->right = r->left + gl_size(r->px.right - r->px.left, osw->viewport_width);
r->bottom = r->top - gl_size(r->px.bottom - r->px.top, osw->viewport_height);
r->color = color; r->is_actual_border = is_actual_border;
r->color = color; r->border_type = border_type;
}
END_WITH_TAB
Py_RETURN_NONE;
@@ -1681,6 +1681,8 @@ init_state(PyObject *module) {
PyModule_AddIntMacro(module, WINDOW_MAXIMIZED);
PyModule_AddIntMacro(module, WINDOW_HIDDEN);
PyModule_AddIntMacro(module, WINDOW_MINIMIZED);
PyModule_AddIntMacro(module, LEFT_EDGE);
PyModule_AddIntMacro(module, RIGHT_EDGE);
PyModule_AddIntMacro(module, TOP_EDGE);
PyModule_AddIntMacro(module, BOTTOM_EDGE);
register_at_exit_cleanup_func(STATE_CLEANUP_FUNC, finalize);

View File

@@ -240,7 +240,7 @@ typedef struct BorderRect {
float left, top, right, bottom;
struct { unsigned left, top, right, bottom; } px;
uint32_t color;
bool is_actual_border;
int border_type;
} BorderRect;
typedef struct BorderRects {