Make it easier to handle simple click events
This commit is contained in:
parent
a402a3ad12
commit
44bcbc4823
@ -24,7 +24,7 @@ class Mouse(Handler):
|
|||||||
def finalize(self) -> None:
|
def finalize(self) -> None:
|
||||||
self.cmd.set_cursor_visible(True)
|
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.current_mouse_event = ev
|
||||||
self.draw_screen()
|
self.draw_screen()
|
||||||
|
|
||||||
@ -43,6 +43,10 @@ class Mouse(Handler):
|
|||||||
if ev.mods:
|
if ev.mods:
|
||||||
self.print(f'Modifiers: {format_mods(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:
|
def main(args: List[str]) -> None:
|
||||||
loop = Loop()
|
loop = Loop()
|
||||||
|
|||||||
@ -3,16 +3,19 @@
|
|||||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
|
||||||
|
from collections import deque
|
||||||
|
from time import monotonic
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import (
|
from typing import (
|
||||||
TYPE_CHECKING, Any, Callable, ContextManager, Dict, Optional, Sequence,
|
TYPE_CHECKING, Any, Callable, ContextManager, Deque, Dict, NamedTuple,
|
||||||
Type, Union, cast
|
Optional, Sequence, Type, Union, cast
|
||||||
)
|
)
|
||||||
|
|
||||||
from kitty.types import DecoratedFunc, ParsedShortcut
|
from kitty.types import DecoratedFunc, ParsedShortcut
|
||||||
from kitty.typing import (
|
from kitty.typing import (
|
||||||
AbstractEventLoop, BossType, Debug, ImageManagerType, KeyActionType,
|
AbstractEventLoop, BossType, Debug, ImageManagerType, KeyActionType,
|
||||||
KeyEventType, LoopType, MouseEvent, ScreenSize, TermManagerType
|
KeyEventType, LoopType, MouseButton, MouseEvent, ScreenSize,
|
||||||
|
TermManagerType
|
||||||
)
|
)
|
||||||
|
|
||||||
from .operations import MouseTracking, pending_update
|
from .operations import MouseTracking, pending_update
|
||||||
@ -21,6 +24,20 @@ if TYPE_CHECKING:
|
|||||||
from kitty.file_transmission import FileTransmissionCommand
|
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:
|
class Handler:
|
||||||
|
|
||||||
image_manager_class: Optional[Type[ImageManagerType]] = None
|
image_manager_class: Optional[Type[ImageManagerType]] = None
|
||||||
@ -44,6 +61,7 @@ class Handler:
|
|||||||
self.debug = debug
|
self.debug = debug
|
||||||
self.cmd = commander(self)
|
self.cmd = commander(self)
|
||||||
self._image_manager = image_manager
|
self._image_manager = image_manager
|
||||||
|
self._button_events: Dict[MouseButton, Deque[ButtonEvent]] = {}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def image_manager(self) -> ImageManagerType:
|
def image_manager(self) -> ImageManagerType:
|
||||||
@ -106,7 +124,27 @@ class Handler:
|
|||||||
def on_key(self, key_event: KeyEventType) -> None:
|
def on_key(self, key_event: KeyEventType) -> None:
|
||||||
pass
|
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
|
pass
|
||||||
|
|
||||||
def on_interrupt(self) -> None:
|
def on_interrupt(self) -> None:
|
||||||
|
|||||||
@ -109,7 +109,7 @@ class TermManager:
|
|||||||
|
|
||||||
|
|
||||||
class MouseButton(IntFlag):
|
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}
|
bmap = {0: MouseButton.LEFT, 1: MouseButton.MIDDLE, 2: MouseButton.RIGHT}
|
||||||
@ -132,7 +132,7 @@ class MouseEvent(NamedTuple):
|
|||||||
pixel_x: int
|
pixel_x: int
|
||||||
pixel_y: int
|
pixel_y: int
|
||||||
type: EventType
|
type: EventType
|
||||||
buttons: int
|
buttons: MouseButton
|
||||||
mods: int
|
mods: int
|
||||||
|
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ def decode_sgr_mouse(text: str, screen_size: ScreenSize) -> MouseEvent:
|
|||||||
m, y_ = y_[-1], y_[:-1]
|
m, y_ = y_[-1], y_[:-1]
|
||||||
cb, x, y = map(int, (cb_, x_, y_))
|
cb, x, y = map(int, (cb_, x_, y_))
|
||||||
typ = EventType.RELEASE if m == 'm' else (EventType.MOVE if cb & MOTION_INDICATOR else EventType.PRESS)
|
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
|
cb3 = cb & 3
|
||||||
if cb3 != 3:
|
if cb3 != 3:
|
||||||
if cb & EXTRA_BUTTON_INDICATOR:
|
if cb & EXTRA_BUTTON_INDICATOR:
|
||||||
@ -310,7 +310,7 @@ class Loop:
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
self.handler.on_mouse(ev)
|
self.handler.on_mouse_event(ev)
|
||||||
elif q in 'u~ABCDEHFPQRS':
|
elif q in 'u~ABCDEHFPQRS':
|
||||||
if csi == '200~':
|
if csi == '200~':
|
||||||
self.in_bracketed_paste = True
|
self.in_bracketed_paste = True
|
||||||
|
|||||||
@ -12,7 +12,7 @@ SessionTab = SessionType = LayoutType = SpecialWindowInstance = None
|
|||||||
MarkType = RemoteCommandType = CoreTextFont = FontConfigPattern = None
|
MarkType = RemoteCommandType = CoreTextFont = FontConfigPattern = None
|
||||||
KeyEventType = ImageManagerType = KittyCommonOpts = HandlerType = None
|
KeyEventType = ImageManagerType = KittyCommonOpts = HandlerType = None
|
||||||
GRT_t = GRT_a = GRT_d = GRT_f = GRT_m = GRT_o = GRT_C = None
|
GRT_t = GRT_a = GRT_d = GRT_f = GRT_m = GRT_o = GRT_C = None
|
||||||
ScreenSize = KittensKeyActionType = MouseEvent = AbstractEventLoop = None
|
ScreenSize = KittensKeyActionType = MouseEvent = MouseButton = AbstractEventLoop = None
|
||||||
TermManagerType = LoopType = Debug = GraphicsCommandType = None
|
TermManagerType = LoopType = Debug = GraphicsCommandType = None
|
||||||
|
|
||||||
CompletedProcess = Tuple
|
CompletedProcess = Tuple
|
||||||
@ -21,5 +21,4 @@ EdgeLiteral = str
|
|||||||
PowerlineStyle = str
|
PowerlineStyle = str
|
||||||
MatchType = str
|
MatchType = str
|
||||||
Protocol = object
|
Protocol = object
|
||||||
MouseEvent = dict
|
|
||||||
OptionsProtocol = object
|
OptionsProtocol = object
|
||||||
|
|||||||
@ -9,8 +9,8 @@ from kittens.tui.images import (
|
|||||||
GraphicsCommand as GraphicsCommandType, ImageManager as ImageManagerType
|
GraphicsCommand as GraphicsCommandType, ImageManager as ImageManagerType
|
||||||
)
|
)
|
||||||
from kittens.tui.loop import (
|
from kittens.tui.loop import (
|
||||||
Debug as Debug, Loop as LoopType, MouseEvent as MouseEvent,
|
Debug as Debug, Loop as LoopType, MouseButton as MouseButton,
|
||||||
TermManager as TermManagerType
|
MouseEvent as MouseEvent, TermManager as TermManagerType
|
||||||
)
|
)
|
||||||
|
|
||||||
from .boss import Boss as BossType
|
from .boss import Boss as BossType
|
||||||
@ -23,9 +23,7 @@ from .fast_data_types import (
|
|||||||
)
|
)
|
||||||
from .key_encoding import KeyEvent as KeyEventType
|
from .key_encoding import KeyEvent as KeyEventType
|
||||||
from .layout.base import Layout as LayoutType
|
from .layout.base import Layout as LayoutType
|
||||||
from .options.utils import (
|
from .options.utils import KeyMap as KeyMap, SequenceMap as SequenceMap
|
||||||
KeyMap as KeyMap, SequenceMap as SequenceMap
|
|
||||||
)
|
|
||||||
from .rc.base import RemoteCommand as RemoteCommandType
|
from .rc.base import RemoteCommand as RemoteCommandType
|
||||||
from .session import Session as SessionType, Tab as SessionTab
|
from .session import Session as SessionType, Tab as SessionTab
|
||||||
from .tabs import (
|
from .tabs import (
|
||||||
@ -56,7 +54,7 @@ __all__ = (
|
|||||||
'EdgeLiteral', 'MatchType', 'GRT_a', 'GRT_f', 'GRT_t', 'GRT_o', 'GRT_m', 'GRT_d',
|
'EdgeLiteral', 'MatchType', 'GRT_a', 'GRT_f', 'GRT_t', 'GRT_o', 'GRT_m', 'GRT_d',
|
||||||
'GraphicsCommandType', 'HandlerType', 'AbstractEventLoop', 'AddressFamily', 'Socket', 'CompletedProcess',
|
'GraphicsCommandType', 'HandlerType', 'AbstractEventLoop', 'AddressFamily', 'Socket', 'CompletedProcess',
|
||||||
'PopenType', 'Protocol', 'TypedDict', 'MarkType', 'ImageManagerType', 'Debug', 'LoopType', 'MouseEvent',
|
'PopenType', 'Protocol', 'TypedDict', 'MarkType', 'ImageManagerType', 'Debug', 'LoopType', 'MouseEvent',
|
||||||
'TermManagerType', 'BossType', 'ChildType', 'BadLineType',
|
'TermManagerType', 'BossType', 'ChildType', 'BadLineType', 'MouseButton',
|
||||||
'KeyActionType', 'KeyMap', 'KittyCommonOpts', 'SequenceMap', 'CoreTextFont', 'WindowSystemMouseEvent',
|
'KeyActionType', 'KeyMap', 'KittyCommonOpts', 'SequenceMap', 'CoreTextFont', 'WindowSystemMouseEvent',
|
||||||
'FontConfigPattern', 'ScreenType', 'StartupCtx', 'KeyEventType', 'LayoutType', 'PowerlineStyle',
|
'FontConfigPattern', 'ScreenType', 'StartupCtx', 'KeyEventType', 'LayoutType', 'PowerlineStyle',
|
||||||
'RemoteCommandType', 'SessionType', 'SessionTab', 'SpecialWindowInstance', 'TabType', 'ScreenSize', 'WindowType'
|
'RemoteCommandType', 'SessionType', 'SessionTab', 'SpecialWindowInstance', 'TabType', 'ScreenSize', 'WindowType'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user