mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-08 21:25:32 +02:00
Make it easier to handle simple click events
This commit is contained in:
@@ -24,7 +24,7 @@ class Mouse(Handler):
|
||||
def finalize(self) -> None:
|
||||
self.cmd.set_cursor_visible(True)
|
||||
|
||||
def on_mouse(self, ev: MouseEvent) -> None:
|
||||
def on_mouse_event(self, ev: MouseEvent) -> None:
|
||||
self.current_mouse_event = ev
|
||||
self.draw_screen()
|
||||
|
||||
@@ -43,6 +43,10 @@ class Mouse(Handler):
|
||||
if ev.mods:
|
||||
self.print(f'Modifiers: {format_mods(ev.mods)}')
|
||||
|
||||
def on_interrupt(self) -> None:
|
||||
self.quit_loop(0)
|
||||
on_eot = on_interrupt
|
||||
|
||||
|
||||
def main(args: List[str]) -> None:
|
||||
loop = Loop()
|
||||
|
||||
@@ -3,16 +3,19 @@
|
||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
|
||||
from collections import deque
|
||||
from time import monotonic
|
||||
from types import TracebackType
|
||||
from typing import (
|
||||
TYPE_CHECKING, Any, Callable, ContextManager, Dict, Optional, Sequence,
|
||||
Type, Union, cast
|
||||
TYPE_CHECKING, Any, Callable, ContextManager, Deque, Dict, NamedTuple,
|
||||
Optional, Sequence, Type, Union, cast
|
||||
)
|
||||
|
||||
from kitty.types import DecoratedFunc, ParsedShortcut
|
||||
from kitty.typing import (
|
||||
AbstractEventLoop, BossType, Debug, ImageManagerType, KeyActionType,
|
||||
KeyEventType, LoopType, MouseEvent, ScreenSize, TermManagerType
|
||||
KeyEventType, LoopType, MouseButton, MouseEvent, ScreenSize,
|
||||
TermManagerType
|
||||
)
|
||||
|
||||
from .operations import MouseTracking, pending_update
|
||||
@@ -21,6 +24,20 @@ if TYPE_CHECKING:
|
||||
from kitty.file_transmission import FileTransmissionCommand
|
||||
|
||||
|
||||
class ButtonEvent(NamedTuple):
|
||||
mouse_event: MouseEvent
|
||||
timestamp: float
|
||||
|
||||
|
||||
def is_click(a: ButtonEvent, b: ButtonEvent) -> bool:
|
||||
from .loop import EventType
|
||||
if a.mouse_event.type is not EventType.PRESS or b.mouse_event.type is not EventType.RELEASE:
|
||||
return False
|
||||
x = a.mouse_event.cell_x - b.mouse_event.cell_x
|
||||
y = a.mouse_event.cell_y - b.mouse_event.cell_y
|
||||
return x*x + y*y <= 4
|
||||
|
||||
|
||||
class Handler:
|
||||
|
||||
image_manager_class: Optional[Type[ImageManagerType]] = None
|
||||
@@ -44,6 +61,7 @@ class Handler:
|
||||
self.debug = debug
|
||||
self.cmd = commander(self)
|
||||
self._image_manager = image_manager
|
||||
self._button_events: Dict[MouseButton, Deque[ButtonEvent]] = {}
|
||||
|
||||
@property
|
||||
def image_manager(self) -> ImageManagerType:
|
||||
@@ -106,7 +124,27 @@ class Handler:
|
||||
def on_key(self, key_event: KeyEventType) -> None:
|
||||
pass
|
||||
|
||||
def on_mouse(self, mouse_event: MouseEvent) -> None:
|
||||
def on_mouse_event(self, mouse_event: MouseEvent) -> None:
|
||||
from .loop import EventType
|
||||
if mouse_event.type is EventType.MOVE:
|
||||
self.on_mouse_move(mouse_event)
|
||||
elif mouse_event.type is EventType.PRESS:
|
||||
q = self._button_events.setdefault(mouse_event.buttons, deque())
|
||||
q.append(ButtonEvent(mouse_event, monotonic()))
|
||||
if len(q) > 5:
|
||||
q.popleft()
|
||||
elif mouse_event.type is EventType.RELEASE:
|
||||
q = self._button_events.setdefault(mouse_event.buttons, deque())
|
||||
q.append(ButtonEvent(mouse_event, monotonic()))
|
||||
if len(q) > 5:
|
||||
q.popleft()
|
||||
if len(q) > 1 and is_click(q[-2], q[-1]):
|
||||
self.on_click(mouse_event)
|
||||
|
||||
def on_mouse_move(self, mouse_event: MouseEvent) -> None:
|
||||
pass
|
||||
|
||||
def on_click(self, mouse_event: MouseEvent) -> None:
|
||||
pass
|
||||
|
||||
def on_interrupt(self) -> None:
|
||||
|
||||
@@ -109,7 +109,7 @@ class TermManager:
|
||||
|
||||
|
||||
class MouseButton(IntFlag):
|
||||
LEFT, MIDDLE, RIGHT, FOURTH, FIFTH = 1, 2, 4, 8, 16
|
||||
NONE, LEFT, MIDDLE, RIGHT, FOURTH, FIFTH = 0, 1, 2, 4, 8, 16
|
||||
|
||||
|
||||
bmap = {0: MouseButton.LEFT, 1: MouseButton.MIDDLE, 2: MouseButton.RIGHT}
|
||||
@@ -132,7 +132,7 @@ class MouseEvent(NamedTuple):
|
||||
pixel_x: int
|
||||
pixel_y: int
|
||||
type: EventType
|
||||
buttons: int
|
||||
buttons: MouseButton
|
||||
mods: int
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ def decode_sgr_mouse(text: str, screen_size: ScreenSize) -> MouseEvent:
|
||||
m, y_ = y_[-1], y_[:-1]
|
||||
cb, x, y = map(int, (cb_, x_, y_))
|
||||
typ = EventType.RELEASE if m == 'm' else (EventType.MOVE if cb & MOTION_INDICATOR else EventType.PRESS)
|
||||
buttons = 0
|
||||
buttons: MouseButton = MouseButton.NONE
|
||||
cb3 = cb & 3
|
||||
if cb3 != 3:
|
||||
if cb & EXTRA_BUTTON_INDICATOR:
|
||||
@@ -310,7 +310,7 @@ class Loop:
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
self.handler.on_mouse(ev)
|
||||
self.handler.on_mouse_event(ev)
|
||||
elif q in 'u~ABCDEHFPQRS':
|
||||
if csi == '200~':
|
||||
self.in_bracketed_paste = True
|
||||
|
||||
Reference in New Issue
Block a user