From 6dcc09a96f21eb737145445cf835d782fdb7f777 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 11 May 2021 11:49:44 +0530 Subject: [PATCH] Port mouse selection tests to new framework --- kitty/glfw-wrapper.h | 26 ++++++++++++++------------ kitty/mouse.c | 27 ++++++++++++++++++++++++--- kitty_tests/__init__.py | 30 ++++++++++++++++++++++++------ kitty_tests/mouse.py | 10 +++++++--- 4 files changed, 69 insertions(+), 24 deletions(-) diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 5003dadf3..74a7a7fab 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -261,18 +261,20 @@ typedef enum { * * @ingroup input * @{ */ -#define GLFW_MOUSE_BUTTON_1 0 -#define GLFW_MOUSE_BUTTON_2 1 -#define GLFW_MOUSE_BUTTON_3 2 -#define GLFW_MOUSE_BUTTON_4 3 -#define GLFW_MOUSE_BUTTON_5 4 -#define GLFW_MOUSE_BUTTON_6 5 -#define GLFW_MOUSE_BUTTON_7 6 -#define GLFW_MOUSE_BUTTON_8 7 -#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8 -#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1 -#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2 -#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3 +typedef enum GLFWMouseButton { + GLFW_MOUSE_BUTTON_1 = 0, + GLFW_MOUSE_BUTTON_LEFT = 0, + GLFW_MOUSE_BUTTON_2 = 1, + GLFW_MOUSE_BUTTON_RIGHT = 1, + GLFW_MOUSE_BUTTON_3 = 2, + GLFW_MOUSE_BUTTON_MIDDLE = 2, + GLFW_MOUSE_BUTTON_4 = 3, + GLFW_MOUSE_BUTTON_5 = 4, + GLFW_MOUSE_BUTTON_6 = 5, + GLFW_MOUSE_BUTTON_7 = 6, + GLFW_MOUSE_BUTTON_8 = 7, + GLFW_MOUSE_BUTTON_LAST = 7 +} GLFWMouseButton; /*! @} */ /*! @defgroup joysticks Joysticks diff --git a/kitty/mouse.c b/kitty/mouse.c index 120761914..4072bddbc 100644 --- a/kitty/mouse.c +++ b/kitty/mouse.c @@ -461,7 +461,7 @@ HANDLER(handle_button_event) { static inline int currently_pressed_button(void) { - for (int i = 0; i <= GLFW_MOUSE_BUTTON_8; i++) { + for (int i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) { if (global_state.callback_os_window->mouse_button_pressed[i]) return i; } return -1; @@ -791,6 +791,17 @@ test_encode_mouse(PyObject *self UNUSED, PyObject *args) { return PyUnicode_FromStringAndSize(mouse_event_buf, sz); } +static PyObject* +mock_mouse_selection(PyObject *self UNUSED, PyObject *args) { + PyObject *capsule; + int button, code; + if (!PyArg_ParseTuple(args, "O!ii", &PyCapsule_Type, &capsule, &button, &code)) return NULL; + Window *w = PyCapsule_GetPointer(capsule, "Window"); + if (!w) return NULL; + mouse_selection(w, code, button); + Py_RETURN_NONE; +} + static PyObject* send_mock_mouse_event_to_window(PyObject *self UNUSED, PyObject *args) { PyObject *capsule; @@ -804,12 +815,21 @@ send_mock_mouse_event_to_window(PyObject *self UNUSED, PyObject *args) { w->mouse_pos.x = 10 * x; w->mouse_pos.y = 20 * y; w->mouse_pos.cell_x = x; w->mouse_pos.cell_y = y; w->mouse_pos.in_left_half_of_cell = in_left_half_of_cell; + static int last_button_pressed = GLFW_MOUSE_BUTTON_LEFT; if (button < 0) { if (button == -2) do_drag_scroll(w, true); else if (button == -3) do_drag_scroll(w, false); - else handle_mouse_movement_in_kitty(w, GLFW_MOUSE_BUTTON_LEFT, mouse_cell_changed); + else handle_mouse_movement_in_kitty(w, last_button_pressed, mouse_cell_changed); } else { - dispatch_mouse_event(w, button, is_release ? -1 : 1, modifiers, false); + if (global_state.active_drag_in_window && is_release && button == global_state.active_drag_button) { + end_drag(w); + } else { + dispatch_mouse_event(w, button, is_release ? -1 : 1, modifiers, false); + if (!is_release) { + last_button_pressed = button; + add_click(w, button, modifiers, 0); + } + } } Py_RETURN_NONE; } @@ -818,6 +838,7 @@ static PyMethodDef module_methods[] = { METHODB(send_mouse_event, METH_VARARGS), METHODB(test_encode_mouse, METH_VARARGS), METHODB(send_mock_mouse_event_to_window, METH_VARARGS), + METHODB(mock_mouse_selection, METH_VARARGS), {NULL, NULL, 0, NULL} /* Sentinel */ }; diff --git a/kitty_tests/__init__.py b/kitty_tests/__init__.py index f141b3940..18f8ae975 100644 --- a/kitty_tests/__init__.py +++ b/kitty_tests/__init__.py @@ -5,15 +5,20 @@ import os from unittest import TestCase -from kitty.config import Options, defaults, merge_configs -from kitty.fast_data_types import set_options -from kitty.fast_data_types import LineBuf, Cursor, Screen, HistoryBuf +from kitty.config import ( + Options, defaults, finalize_keys, finalize_mouse_mappings, merge_configs +) +from kitty.fast_data_types import ( + Cursor, HistoryBuf, LineBuf, Screen, set_options +) +from kitty.types import MouseEvent class Callbacks: - def __init__(self) -> None: + def __init__(self, opts) -> None: self.clear() + self.opts = opts def write(self, data) -> None: self.wtcbuf += data @@ -54,6 +59,16 @@ class Callbacks: def on_activity_since_last_focus(self) -> None: pass + def on_mouse_event(self, event): + ev = MouseEvent(**event) + action = self.opts.mousemap.get(ev) + if action is None: + return False + self.current_mouse_button = ev.button + getattr(self, action.func)(*action.args) + self.current_mouse_button = 0 + return True + def filled_line_buf(ynum=5, xnum=5, cursor=Cursor()): ans = LineBuf(ynum, xnum) @@ -92,11 +107,14 @@ class BaseTest(TestCase): if options: final_options.update(options) options = Options(merge_configs(defaults._asdict(), final_options)) + finalize_keys(options) + finalize_mouse_mappings(options) set_options(options) + return options def create_screen(self, cols=5, lines=5, scrollback=5, cell_width=10, cell_height=20, options=None): - self.set_options(options) - c = Callbacks() + opts = self.set_options(options) + c = Callbacks(opts) s = Screen(c, lines, cols, scrollback, cell_width, cell_height, 0, c) return s diff --git a/kitty_tests/mouse.py b/kitty_tests/mouse.py index dfa88a582..a21905344 100644 --- a/kitty_tests/mouse.py +++ b/kitty_tests/mouse.py @@ -6,7 +6,7 @@ from functools import partial from kitty.fast_data_types import ( GLFW_MOD_ALT, GLFW_MOD_CONTROL, GLFW_MOUSE_BUTTON_LEFT, - GLFW_MOUSE_BUTTON_RIGHT, create_mock_window, + GLFW_MOUSE_BUTTON_RIGHT, create_mock_window, mock_mouse_selection, send_mock_mouse_event_to_window ) @@ -40,6 +40,11 @@ class TestMouse(BaseTest): w = create_mock_window(s) ev = partial(send_mouse_event, w) + def mouse_selection(code: int) -> None: + mock_mouse_selection(w, s.callbacks.current_mouse_button, code) + + s.callbacks.mouse_selection = mouse_selection + def sel(): return ''.join(s.text_for_selection()) @@ -210,7 +215,6 @@ class TestMouse(BaseTest): self.ae(sel(), '1234') press(x=1, y=1, button=GLFW_MOUSE_BUTTON_RIGHT) self.ae(sel(), '123456') - move(x=2, y=1) - self.ae(sel(), '1234567') + move(x=2, y=1, q='1234567') release(x=3, y=1, button=GLFW_MOUSE_BUTTON_RIGHT) self.ae(sel(), '12345678')