diff --git a/docs/changelog.rst b/docs/changelog.rst index 0d6b31a97..3e677a3a2 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -12,6 +12,9 @@ Changelog - Fix triple-click to select line not working when the entire line is filled (:iss:`703`) +- When dragging to select with the mouse "grab" the mouse so that if it strays + into neighboring windows, the selection is still updated (:pull:`624`) + 0.11.2 [2018-07-01] ------------------------------ diff --git a/kitty/glfw.c b/kitty/glfw.c index f79b68b8a..d43e816d3 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -202,6 +202,7 @@ push_focus_history(OSWindow *w) { static void window_focus_callback(GLFWwindow *w, int focused) { + global_state.active_drag_in_window = 0; if (!set_callback_window(w)) return; global_state.callback_os_window->is_focused = focused ? true : false; if (focused) { diff --git a/kitty/mouse.c b/kitty/mouse.c index 8e59f4a9a..17da688e5 100644 --- a/kitty/mouse.c +++ b/kitty/mouse.c @@ -119,6 +119,8 @@ contains_mouse(Window *w, OSWindow *os_window) { return (w->visible && window_left(w, os_window) <= x && x <= window_right(w, os_window) && window_top(w, os_window) <= y && y <= window_bottom(w, os_window)); } +static bool clamp_to_window = false; + static inline bool cell_for_pos(Window *w, unsigned int *x, unsigned int *y, OSWindow *os_window) { WindowGeometry *g = &w->geometry; @@ -128,6 +130,10 @@ cell_for_pos(Window *w, unsigned int *x, unsigned int *y, OSWindow *os_window) { double mouse_x = global_state.callback_os_window->mouse_x; double mouse_y = global_state.callback_os_window->mouse_y; double left = window_left(w, os_window), top = window_top(w, os_window), right = window_right(w, os_window), bottom = window_bottom(w, os_window); + if (clamp_to_window) { + mouse_x = MIN(MAX(mouse_x, left), right); + mouse_y = MIN(MAX(mouse_y, top), bottom); + } if (mouse_x < left || mouse_y < top || mouse_x > right || mouse_y > bottom) return false; if (mouse_x >= g->right) qx = screen->columns - 1; else if (mouse_x >= g->left) qx = (unsigned int)((double)(mouse_x - g->left) / os_window->fonts_data->cell_width); @@ -147,10 +153,14 @@ update_drag(bool from_button, Window *w, bool is_release, int modifiers) { Screen *screen = w->render_data.screen; if (from_button) { if (is_release) { + global_state.active_drag_in_window = 0; if (screen->selection.in_progress) screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, true); } - else screen_start_selection(screen, w->mouse_cell_x, w->mouse_cell_y, modifiers == (int)OPT(rectangle_select_modifiers) || modifiers == ((int)OPT(rectangle_select_modifiers) | GLFW_MOD_SHIFT), EXTEND_CELL); + else { + global_state.active_drag_in_window = w->id; + screen_start_selection(screen, w->mouse_cell_x, w->mouse_cell_y, modifiers == (int)OPT(rectangle_select_modifiers) || modifiers == ((int)OPT(rectangle_select_modifiers) | GLFW_MOD_SHIFT), EXTEND_CELL); + } } else if (screen->selection.in_progress) { screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, false); } @@ -372,6 +382,16 @@ mouse_in_region(Region *r) { return true; } +static inline Window* +window_for_id(id_type window_id) { + Tab *t = global_state.callback_os_window->tabs + global_state.callback_os_window->active_tab; + for (unsigned int i = 0; i < t->num_windows; i++) { + Window *w = t->windows + i; + if (w->id == window_id) return w; + } + return NULL; +} + static inline Window* window_for_event(unsigned int *window_idx, bool *in_tab_bar) { Region central, tab_bar; @@ -405,7 +425,21 @@ mouse_event(int button, int modifiers) { MouseShape old_cursor = mouse_cursor_shape; bool in_tab_bar; unsigned int window_idx = 0; - Window *w = window_for_event(&window_idx, &in_tab_bar); + Window *w = NULL; + if (button == -1 && global_state.active_drag_in_window) { // drag move + w = window_for_id(global_state.active_drag_in_window); + if (w) { + for (int i = 0; i < GLFW_MOUSE_BUTTON_5; i++) { if (global_state.callback_os_window->mouse_button_pressed[i]) { button = i; break; } } + if (button == GLFW_MOUSE_BUTTON_LEFT) { + clamp_to_window = true; + handle_move_event(w, button, modifiers, window_idx); + clamp_to_window = false; + return; + } + } + + } + w = window_for_event(&window_idx, &in_tab_bar); if (in_tab_bar) { mouse_cursor_shape = HAND; handle_tab_bar_mouse(button, modifiers); diff --git a/kitty/state.h b/kitty/state.h index 811f06248..e962c0b26 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -141,6 +141,7 @@ typedef struct { bool in_sequence_mode; double font_sz_in_pts; struct { double x, y; } default_dpi; + id_type active_drag_in_window; } GlobalState; extern GlobalState global_state;