Refactor mouse event region detection
This commit is contained in:
parent
50bc3f465e
commit
be83cf3a4a
3 changed files with 67 additions and 64 deletions
123
kitty/mouse.c
123
kitty/mouse.c
|
|
@ -915,23 +915,29 @@ num_visible_windows(Tab *t) {
|
|||
return ans;
|
||||
}
|
||||
|
||||
static Window*
|
||||
window_for_event(unsigned int *window_idx, bool *in_tab_bar, Edge *window_border) {
|
||||
typedef struct MouseRegion {
|
||||
unsigned window_idx;
|
||||
bool in_tab_bar;
|
||||
Edge window_border;
|
||||
Window *window;
|
||||
} MouseRegion;
|
||||
|
||||
static MouseRegion
|
||||
mouse_region(bool detect_borders) {
|
||||
MouseRegion ans = {0};
|
||||
Region central, tab_bar;
|
||||
os_window_regions(global_state.callback_os_window, ¢ral, &tab_bar);
|
||||
const bool in_central = mouse_in_region(¢ral);
|
||||
*in_tab_bar = false;
|
||||
const OSWindow* w = global_state.callback_os_window;
|
||||
os_window_regions(w, ¢ral, &tab_bar);
|
||||
const bool in_central = mouse_in_region(¢ral);
|
||||
if (!in_central) {
|
||||
if (
|
||||
(tab_bar.top < central.top && w->mouse_y < central.top) ||
|
||||
(tab_bar.bottom > central.bottom && w->mouse_y >= central.bottom)
|
||||
) *in_tab_bar = true;
|
||||
) ans.in_tab_bar = true;
|
||||
}
|
||||
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 && num_visible_windows(t) > 1) {
|
||||
*window_border = 0;
|
||||
if (detect_borders && num_visible_windows(t) > 1) {
|
||||
id_type window_id = 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))));
|
||||
|
|
@ -943,7 +949,7 @@ window_for_event(unsigned int *window_idx, bool *in_tab_bar, Edge *window_border
|
|||
if (!br->border_type) continue;
|
||||
Edge edges = 0;
|
||||
if (border_contains_mouse(br, 0, &edges)) {
|
||||
*window_border |= edges;
|
||||
ans.window_border |= edges;
|
||||
is_within_border_without_tolerance = true;
|
||||
if (edges & (LEFT_EDGE | RIGHT_EDGE)) { closest_vert_dist = -1; closest_vert = NULL; }
|
||||
else { closest_horiz_dist = -1; closest_horiz = NULL; }
|
||||
|
|
@ -960,26 +966,30 @@ window_for_event(unsigned int *window_idx, bool *in_tab_bar, Edge *window_border
|
|||
}
|
||||
}
|
||||
if (!is_within_border_without_tolerance) {
|
||||
if (closest_vert && border_contains_mouse(closest_vert, tolerance, window_border) && !window_id)
|
||||
if (closest_vert && border_contains_mouse(closest_vert, tolerance, &ans.window_border) && !window_id)
|
||||
window_id = closest_vert->border_type < 0 ? -closest_vert->border_type : closest_vert->border_type;
|
||||
if (closest_horiz && border_contains_mouse(closest_horiz, tolerance, window_border) && !window_id)
|
||||
if (closest_horiz && border_contains_mouse(closest_horiz, tolerance, &ans.window_border) && !window_id)
|
||||
window_id = closest_horiz->border_type < 0 ? -closest_horiz->border_type : closest_horiz->border_type;
|
||||
}
|
||||
if (*window_border) {
|
||||
if (!window_id) return NULL;
|
||||
for (unsigned int i = 0; i < t->num_windows; i++)
|
||||
if (t->windows[i].id == window_id) return t->windows + i;
|
||||
return NULL;
|
||||
if (ans.window_border) {
|
||||
if (window_id) {
|
||||
for (unsigned int i = 0; i < t->num_windows; i++)
|
||||
if (t->windows[i].id == window_id) {
|
||||
ans.window = t->windows + i;
|
||||
ans.window_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
}
|
||||
for (unsigned int i = 0; i < t->num_windows; i++) {
|
||||
if (contains_mouse(t->windows + i) && t->windows[i].render_data.screen) {
|
||||
*window_idx = i;
|
||||
return t->windows + i;
|
||||
ans.window_idx = i; ans.window = t->windows + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return ans;
|
||||
}
|
||||
|
||||
static Window*
|
||||
|
|
@ -1002,13 +1012,11 @@ closest_window_for_event(unsigned int *window_idx) {
|
|||
void
|
||||
focus_in_event(void) {
|
||||
// Ensure that no URL is highlighted and the mouse cursor is in default shape
|
||||
bool in_tab_bar;
|
||||
unsigned int window_idx = 0;
|
||||
mouse_cursor_shape = TEXT_POINTER;
|
||||
Window *w = window_for_event(&window_idx, &in_tab_bar, NULL);
|
||||
if (w && w->render_data.screen) {
|
||||
screen_mark_url(w->render_data.screen, 0, 0, 0, 0);
|
||||
set_mouse_cursor_for_screen(w->render_data.screen);
|
||||
MouseRegion r = mouse_region(false);
|
||||
if (r.window && r.window->render_data.screen) {
|
||||
screen_mark_url(r.window->render_data.screen, 0, 0, 0, 0);
|
||||
set_mouse_cursor_for_screen(r.window->render_data.screen);
|
||||
}
|
||||
set_mouse_cursor(mouse_cursor_shape);
|
||||
}
|
||||
|
|
@ -1016,17 +1024,15 @@ focus_in_event(void) {
|
|||
void
|
||||
update_mouse_pointer_shape(void) {
|
||||
mouse_cursor_shape = TEXT_POINTER;
|
||||
bool in_tab_bar;
|
||||
unsigned int window_idx = 0;
|
||||
Window *w = window_for_event(&window_idx, &in_tab_bar, NULL);
|
||||
if (in_tab_bar) {
|
||||
MouseRegion r = mouse_region(false);
|
||||
if (r.in_tab_bar) {
|
||||
mouse_cursor_shape = POINTER_POINTER;
|
||||
} else if (w) {
|
||||
if (handle_scrollbar_mouse(w, -1, MOVE, 0)) {
|
||||
} else if (r.window) {
|
||||
if (handle_scrollbar_mouse(r.window, -1, MOVE, 0)) {
|
||||
mouse_cursor_shape = scrollbar_drag_mouse_cursor;
|
||||
} else if (w->render_data.screen) {
|
||||
screen_mark_url(w->render_data.screen, 0, 0, 0, 0);
|
||||
set_mouse_cursor_for_screen(w->render_data.screen);
|
||||
} else if (r.window->render_data.screen) {
|
||||
screen_mark_url(r.window->render_data.screen, 0, 0, 0, 0);
|
||||
set_mouse_cursor_for_screen(r.window->render_data.screen);
|
||||
}
|
||||
}
|
||||
set_mouse_cursor(mouse_cursor_shape);
|
||||
|
|
@ -1055,10 +1061,10 @@ enter_event(int modifiers) {
|
|||
// If the mouse is grabbed send a move event to update the cursor position
|
||||
// since the last report.
|
||||
if (global_state.redirect_mouse_handling || global_state.active_drag_in_window || global_state.tracked_drag_in_window) return;
|
||||
unsigned window_idx; bool in_tab_bar;
|
||||
Window *w = window_for_event(&window_idx, &in_tab_bar, NULL);
|
||||
MouseRegion r = mouse_region(false);
|
||||
Window *w = r.window;
|
||||
set_currently_hovered_window(w ? w->id : 0, modifiers);
|
||||
if (!w || in_tab_bar) return;
|
||||
if (!w || r.in_tab_bar) return;
|
||||
|
||||
if (handle_scrollbar_mouse(w, -1, MOVE, modifiers)) return;
|
||||
|
||||
|
|
@ -1148,7 +1154,6 @@ border_name(int edges) {
|
|||
void
|
||||
mouse_event(const int button, int modifiers, int action) {
|
||||
MouseShape old_cursor = mouse_cursor_shape;
|
||||
bool in_tab_bar;
|
||||
unsigned int window_idx = 0;
|
||||
Window *w = NULL;
|
||||
|
||||
|
|
@ -1159,9 +1164,9 @@ mouse_event(const int button, int modifiers, int action) {
|
|||
else { debug("%s mouse_button: %d %s", action == GLFW_RELEASE ? "\x1b[32mRelease\x1b[m" : "\x1b[31mPress\x1b[m", button, format_mods(modifiers)); }
|
||||
}
|
||||
if (global_state.redirect_mouse_handling) {
|
||||
w = window_for_event(&window_idx, &in_tab_bar, NULL);
|
||||
MouseRegion r= mouse_region(false); w = r.window;
|
||||
call_boss(mouse_event, "OK iiii dd",
|
||||
(in_tab_bar ? Py_True : Py_False), (w ? w->id : 0),
|
||||
(r.in_tab_bar ? Py_True : Py_False), (w ? w->id : 0),
|
||||
action, modifiers, button, currently_pressed_button(),
|
||||
global_state.callback_os_window->mouse_x, global_state.callback_os_window->mouse_y
|
||||
);
|
||||
|
|
@ -1236,32 +1241,31 @@ mouse_event(const int button, int modifiers, int action) {
|
|||
}
|
||||
return;
|
||||
}
|
||||
Edge window_border = 0;
|
||||
w = window_for_event(&window_idx, &in_tab_bar, &window_border);
|
||||
MouseRegion r = mouse_region(true);
|
||||
set_currently_hovered_window(w ? w->id : 0, modifiers);
|
||||
|
||||
if (in_tab_bar || global_state.tab_being_dragged.id) {
|
||||
if (r.in_tab_bar || global_state.tab_being_dragged.id) {
|
||||
mouse_cursor_shape = POINTER_POINTER;
|
||||
handle_tab_bar_mouse(button, modifiers, action);
|
||||
debug("handled by tab bar\n");
|
||||
} else if (window_border) {
|
||||
debug("window border: %s window id: %llu\n", border_name(window_border), w ? w->id : 0);
|
||||
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 if (r.window_border) {
|
||||
debug("window border: %s window id: %llu\n", border_name(r.window_border), w ? w->id : 0);
|
||||
if (r.window_border & LEFT_EDGE) {
|
||||
if (r.window_border & TOP_EDGE) mouse_cursor_shape = NWSE_RESIZE_POINTER;
|
||||
else if (r.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 if (r.window_border & RIGHT_EDGE) {
|
||||
if (r.window_border & TOP_EDGE) mouse_cursor_shape = NESW_RESIZE_POINTER;
|
||||
else if (r.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;
|
||||
} else if (r.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", "iddKII", window_border,
|
||||
RAII_PyObject(retval, PyObject_CallMethod(
|
||||
global_state.boss, "drag_resize_start", "iddKII", r.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; }
|
||||
if (PyObject_IsTrue(r)) global_state.active_drag_resize = w->id;
|
||||
if (retval == NULL) { PyErr_Print(); return; }
|
||||
if (PyObject_IsTrue(retval)) global_state.active_drag_resize = w->id;
|
||||
}
|
||||
} else if (w) {
|
||||
debug("grabbed: %d\n", w->render_data.screen->modes.mouse_tracking_mode != 0);
|
||||
|
|
@ -1361,10 +1365,8 @@ pixel_scroll_enabled_for_screen(const Screen *screen) {
|
|||
void
|
||||
scroll_event(const GLFWScrollEvent *ev) {
|
||||
debug("\x1b[36mScroll\x1b[m %s x: %f y: %f momentum: %s modifiers: %s\n", scroll_offset_type(ev->offset_type), ev->x_offset, ev->y_offset, scroll_phase(ev->momentum_type), format_mods(ev->keyboard_modifiers));
|
||||
bool in_tab_bar;
|
||||
static id_type window_for_momentum_scroll = 0;
|
||||
static bool main_screen_for_momentum_scroll = false;
|
||||
unsigned int window_idx = 0;
|
||||
// allow scroll events even if window is not currently focused (in
|
||||
// which case on some platforms such as macOS the mouse location is zeroed so
|
||||
// window_for_event() does not work).
|
||||
|
|
@ -1375,8 +1377,9 @@ scroll_event(const GLFWScrollEvent *ev) {
|
|||
osw->mouse_x = mouse_x * osw->viewport_x_ratio;
|
||||
osw->mouse_y = mouse_y * osw->viewport_y_ratio;
|
||||
}
|
||||
Window *w = window_for_event(&window_idx, &in_tab_bar, NULL);
|
||||
if (!w && !in_tab_bar) {
|
||||
MouseRegion r = mouse_region(false);
|
||||
Window *w = r.window;
|
||||
if (!w && !r.in_tab_bar) {
|
||||
// fallback to last active window
|
||||
Tab *t = osw->tabs + osw->active_tab;
|
||||
if (t) w = t->windows + t->active_window;
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ GlobalState global_state = {{0}};
|
|||
}}
|
||||
|
||||
static double
|
||||
dpi_for_os_window(OSWindow *os_window) {
|
||||
dpi_for_os_window(const OSWindow *os_window) {
|
||||
double dpi = (os_window->fonts_data->logical_dpi_x + os_window->fonts_data->logical_dpi_y) / 2.;
|
||||
if (dpi == 0) dpi = (global_state.default_dpi.x + global_state.default_dpi.y) / 2.;
|
||||
return dpi;
|
||||
|
|
@ -84,7 +84,7 @@ dpi_for_os_window_id(id_type os_window_id) {
|
|||
}
|
||||
|
||||
static long
|
||||
pt_to_px_for_os_window(double pt, OSWindow *w) {
|
||||
pt_to_px_for_os_window(double pt, const OSWindow *w) {
|
||||
const double dpi = dpi_for_os_window(w);
|
||||
return ((long)round((pt * (dpi / 72.0))));
|
||||
}
|
||||
|
|
@ -638,7 +638,7 @@ pyset_borders_rects(PyObject *self UNUSED, PyObject *args) {
|
|||
|
||||
|
||||
void
|
||||
os_window_regions(OSWindow *os_window, Region *central, Region *tab_bar) {
|
||||
os_window_regions(const OSWindow *os_window, Region *central, Region *tab_bar) {
|
||||
if (!OPT(tab_bar_hidden) && os_window->num_tabs && !os_window->has_too_few_tabs) {
|
||||
long margin_outer = pt_to_px_for_os_window(OPT(tab_bar_margin_height.outer), os_window);
|
||||
long margin_inner = pt_to_px_for_os_window(OPT(tab_bar_margin_height.inner), os_window);
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ OSWindow* os_window_for_kitty_window(id_type);
|
|||
OSWindow* os_window_for_id(id_type);
|
||||
OSWindow* add_os_window(void);
|
||||
OSWindow* current_os_window(void);
|
||||
void os_window_regions(OSWindow*, Region *main, Region *tab_bar);
|
||||
void os_window_regions(const OSWindow*, Region *main, Region *tab_bar);
|
||||
bool drag_scroll(Window *, OSWindow*);
|
||||
void draw_borders(ssize_t vao_idx, unsigned int num_border_rects, BorderRect *rect_buf, bool rect_data_is_dirty, color_type, unsigned int, bool, OSWindow *w);
|
||||
ssize_t create_cell_vao(void);
|
||||
|
|
|
|||
Loading…
Reference in a new issue