mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-09 15:08:13 +02:00
Start work on intercepting mouse events
This commit is contained in:
@@ -736,27 +736,34 @@ class Boss:
|
||||
if t is not None:
|
||||
t.relayout_borders()
|
||||
|
||||
def dispatch_action(self, key_action: KeyAction) -> bool:
|
||||
def dispatch_action(
|
||||
self,
|
||||
key_action: KeyAction,
|
||||
window_for_dispatch: Optional[Window] = None,
|
||||
dispatch_type: str = 'KeyPress'
|
||||
) -> bool:
|
||||
if key_action is not None:
|
||||
f = getattr(self, key_action.func, None)
|
||||
if f is not None:
|
||||
if self.args.debug_keyboard:
|
||||
print('Keypress matched action:', func_name(f))
|
||||
print(f'{dispatch_type} matched action:', func_name(f))
|
||||
passthrough = f(*key_action.args)
|
||||
if passthrough is not True:
|
||||
return True
|
||||
tab = self.active_tab
|
||||
if tab is None:
|
||||
return False
|
||||
window = self.active_window
|
||||
if window is None:
|
||||
if window_for_dispatch is None:
|
||||
tab = self.active_tab
|
||||
window = self.active_window
|
||||
else:
|
||||
window = window_for_dispatch
|
||||
tab = window.tabref()
|
||||
if tab is None or window is None:
|
||||
return False
|
||||
if key_action is not None:
|
||||
f = getattr(tab, key_action.func, getattr(window, key_action.func, None))
|
||||
if f is not None:
|
||||
passthrough = f(*key_action.args)
|
||||
if self.args.debug_keyboard:
|
||||
print('Keypress matched action:', func_name(f))
|
||||
print(f'{dispatch_type} matched action:', func_name(f))
|
||||
if passthrough is not True:
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -122,14 +122,19 @@ encode_mouse_scroll(Window *w, bool upwards, int mods) {
|
||||
|
||||
// }}}
|
||||
|
||||
static inline void
|
||||
static bool
|
||||
dispatch_mouse_event(Window *w, int button, int count, int modifiers, bool grabbed) {
|
||||
if (w->render_data.screen && PyCallable_Check(w->render_data.screen->callbacks)) {
|
||||
bool handled = false;
|
||||
if (w->render_data.screen && w->render_data.screen->callbacks != Py_None) {
|
||||
PyObject *callback_ret = PyObject_CallMethod(w->render_data.screen->callbacks, "on_mouse_event", "{si si si sO}",
|
||||
"button", button, "repeat_count", count, "mods", modifiers, "grabbed", grabbed ? Py_True : Py_False);
|
||||
if (callback_ret == NULL) PyErr_Print();
|
||||
else Py_DECREF(callback_ret);
|
||||
else {
|
||||
handled = callback_ret == Py_True;
|
||||
Py_DECREF(callback_ret);
|
||||
}
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
@@ -443,6 +448,7 @@ HANDLER(add_click) {
|
||||
N(0).at = now; N(0).button = button; N(0).modifiers = modifiers; N(0).x = w->mouse_pos.x; N(0).y = w->mouse_pos.y;
|
||||
q->length++;
|
||||
double multi_click_allowed_radius = 1.2 * (global_state.callback_os_window ? global_state.callback_os_window->fonts_data->cell_height : 20);
|
||||
Screen *screen = w->render_data.screen;
|
||||
// Now dispatch the multi-click if any
|
||||
if (q->length > 2) {
|
||||
// possible triple-click
|
||||
@@ -450,7 +456,7 @@ HANDLER(add_click) {
|
||||
N(1).at - N(3).at <= 2 * OPT(click_interval) &&
|
||||
distance(N(1).x, N(1).y, N(3).x, N(3).y) <= multi_click_allowed_radius
|
||||
) {
|
||||
multi_click(w, 3);
|
||||
if (screen) dispatch_mouse_event(w, button, 3, modifiers, screen->modes.mouse_tracking_mode != 0);
|
||||
q->length = 0;
|
||||
}
|
||||
}
|
||||
@@ -460,7 +466,7 @@ HANDLER(add_click) {
|
||||
N(1).at - N(2).at <= OPT(click_interval) &&
|
||||
distance(N(1).x, N(1).y, N(2).x, N(2).y) <= multi_click_allowed_radius
|
||||
) {
|
||||
multi_click(w, 2);
|
||||
if (screen) dispatch_mouse_event(w, button, 2, modifiers, screen->modes.mouse_tracking_mode != 0);
|
||||
}
|
||||
}
|
||||
#undef N
|
||||
@@ -473,7 +479,7 @@ open_url(Window *w) {
|
||||
screen_open_url(screen);
|
||||
}
|
||||
|
||||
static inline void
|
||||
static void
|
||||
handle_button_event_in_kitty(Window *w, int button, int modifiers, bool is_release) {
|
||||
switch(button) {
|
||||
case GLFW_MOUSE_BUTTON_LEFT:
|
||||
@@ -500,17 +506,11 @@ HANDLER(handle_button_event) {
|
||||
}
|
||||
Screen *screen = w->render_data.screen;
|
||||
if (!screen) return;
|
||||
const int ts1 = OPT(terminal_select_modifiers), ts2 = OPT(terminal_select_modifiers) | OPT(rectangle_select_modifiers);
|
||||
bool handle_in_kitty = (
|
||||
modifiers == ts1 || modifiers == ts2 ||
|
||||
screen->modes.mouse_tracking_mode == 0 ||
|
||||
(modifiers == (int)OPT(open_url_modifiers) && button == GLFW_MOUSE_BUTTON_LEFT)
|
||||
);
|
||||
if (handle_in_kitty) handle_button_event_in_kitty(w, button, modifiers, is_release);
|
||||
else {
|
||||
if (!dispatch_mouse_event(w, button, is_release ? -1 : 1, modifiers, screen->modes.mouse_tracking_mode != 0)) {
|
||||
int sz = encode_mouse_button(w, button, is_release ? RELEASE : PRESS, modifiers);
|
||||
if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, CSI, mouse_event_buf); }
|
||||
}
|
||||
add_click(w, button, modifiers, 0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
||||
@@ -19,7 +19,7 @@ from typing import (
|
||||
from .child import ProcessDesc
|
||||
from .cli_stub import CLIOptions
|
||||
from .config import build_ansi_color_table
|
||||
from .constants import appname, wakeup, is_macos
|
||||
from .constants import appname, is_macos, wakeup
|
||||
from .fast_data_types import (
|
||||
BGIMAGE_PROGRAM, BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_FG_PROGRAM,
|
||||
CELL_PROGRAM, CELL_SPECIAL_PROGRAM, DCS, DECORATION, DIM, GLFW_MOD_CONTROL,
|
||||
@@ -36,7 +36,7 @@ from .notify import NotificationCommand, handle_notification_cmd
|
||||
from .options_stub import Options
|
||||
from .rgb import to_color
|
||||
from .terminfo import get_capabilities
|
||||
from .types import ScreenGeometry, WindowGeometry
|
||||
from .types import MouseEvent, ScreenGeometry, WindowGeometry
|
||||
from .typing import BossType, ChildType, EdgeLiteral, TabType, TypedDict
|
||||
from .utils import (
|
||||
color_as_int, get_primary_selection, load_shaders, log_error, open_cmd,
|
||||
@@ -530,6 +530,13 @@ class Window:
|
||||
def use_utf8(self, on: bool) -> None:
|
||||
get_boss().child_monitor.set_iutf8_winid(self.id, on)
|
||||
|
||||
def on_mouse_event(self, event: Dict[str, Any]) -> bool:
|
||||
ev = MouseEvent(**event)
|
||||
action = self.opts.mousemap.get(ev)
|
||||
if action is None:
|
||||
return False
|
||||
return get_boss().dispatch_action(action, window_for_dispatch=self, dispatch_type='MouseEvent')
|
||||
|
||||
def open_url(self, url: str, hyperlink_id: int, cwd: Optional[str] = None) -> None:
|
||||
if hyperlink_id:
|
||||
if not self.opts.allow_hyperlinks:
|
||||
|
||||
Reference in New Issue
Block a user