Allow handlers to ask for mouse events

This commit is contained in:
Kovid Goyal 2021-09-28 09:32:53 +05:30
parent 276696414e
commit f3447d187d
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 26 additions and 7 deletions

View File

@ -15,7 +15,7 @@ from kitty.typing import (
KeyEventType, LoopType, MouseEvent, ScreenSize, TermManagerType KeyEventType, LoopType, MouseEvent, ScreenSize, TermManagerType
) )
from .operations import pending_update from .operations import MouseTracking, pending_update
if TYPE_CHECKING: if TYPE_CHECKING:
from kitty.file_transmission import FileTransmissionCommand from kitty.file_transmission import FileTransmissionCommand
@ -25,6 +25,7 @@ class Handler:
image_manager_class: Optional[Type[ImageManagerType]] = None image_manager_class: Optional[Type[ImageManagerType]] = None
use_alternate_screen = True use_alternate_screen = True
mouse_tracking = MouseTracking.none
def _initialize( def _initialize(
self, self,

View File

@ -28,7 +28,7 @@ from kitty.typing import ImageManagerType, KeyEventType, Protocol
from kitty.utils import ScreenSizeGetter, screen_size_function, write_all from kitty.utils import ScreenSizeGetter, screen_size_function, write_all
from .handler import Handler from .handler import Handler
from .operations import init_state, reset_state from .operations import init_state, reset_state, MouseTracking
class BinaryWrite(Protocol): class BinaryWrite(Protocol):
@ -69,7 +69,10 @@ ftc_code = str(FILE_TRANSFER_CODE)
class TermManager: class TermManager:
def __init__(self, optional_actions: int = termios.TCSANOW, use_alternate_screen: bool = True) -> None: def __init__(
self, optional_actions: int = termios.TCSANOW, use_alternate_screen: bool = True,
mouse_tracking: MouseTracking = MouseTracking.none
) -> None:
self.extra_finalize: Optional[str] = None self.extra_finalize: Optional[str] = None
self.optional_actions = optional_actions self.optional_actions = optional_actions
self.use_alternate_screen = use_alternate_screen self.use_alternate_screen = use_alternate_screen
@ -421,7 +424,7 @@ class Loop:
handler.on_resize(handler.screen_size) handler.on_resize(handler.screen_size)
signal_manager = SignalManager(self.asycio_loop, _on_sigwinch, handler.on_interrupt, handler.on_term) signal_manager = SignalManager(self.asycio_loop, _on_sigwinch, handler.on_interrupt, handler.on_term)
with TermManager(self.optional_actions, handler.use_alternate_screen) as term_manager, signal_manager: with TermManager(self.optional_actions, handler.use_alternate_screen, handler.mouse_tracking) as term_manager, signal_manager:
self._get_screen_size: ScreenSizeGetter = screen_size_function(term_manager.tty_fd) self._get_screen_size: ScreenSizeGetter = screen_size_function(term_manager.tty_fd)
image_manager = None image_manager = None
if handler.image_manager_class is not None: if handler.image_manager_class is not None:

View File

@ -4,8 +4,8 @@
import sys import sys
from contextlib import contextmanager from contextlib import contextmanager
from enum import Enum, auto
from functools import wraps from functools import wraps
from enum import Enum
from typing import ( from typing import (
IO, Any, Callable, Dict, Generator, Optional, Tuple, TypeVar, Union IO, Any, Callable, Dict, Generator, Optional, Tuple, TypeVar, Union
) )
@ -281,7 +281,14 @@ def clear_images_on_screen(delete_data: bool = False) -> str:
return gc.serialize().decode('ascii') return gc.serialize().decode('ascii')
def init_state(alternate_screen: bool = True) -> str: class MouseTracking(Enum):
none = auto()
buttons_only = auto()
buttons_and_drag = auto()
full = auto()
def init_state(alternate_screen: bool = True, mouse_tracking: MouseTracking = MouseTracking.none) -> str:
sc = SAVE_CURSOR if alternate_screen else '' sc = SAVE_CURSOR if alternate_screen else ''
ans = ( ans = (
S7C1T + sc + SAVE_PRIVATE_MODE_VALUES + reset_mode(Mode.LNM) + S7C1T + sc + SAVE_PRIVATE_MODE_VALUES + reset_mode(Mode.LNM) +
@ -296,6 +303,14 @@ def init_state(alternate_screen: bool = True) -> str:
if alternate_screen: if alternate_screen:
ans += set_mode(Mode.ALTERNATE_SCREEN) + reset_mode(Mode.DECOM) ans += set_mode(Mode.ALTERNATE_SCREEN) + reset_mode(Mode.DECOM)
ans += clear_screen() ans += clear_screen()
if mouse_tracking is not MouseTracking.none:
ans += set_mode(Mode.MOUSE_SGR_MODE)
if mouse_tracking is MouseTracking.buttons_only:
ans += set_mode(Mode.MOUSE_BUTTON_TRACKING)
elif mouse_tracking is MouseTracking.buttons_and_drag:
ans += set_mode(Mode.MOUSE_MOTION_TRACKING)
elif mouse_tracking is MouseTracking.full:
ans += set_mode(Mode.MOUSE_MOVE_TRACKING)
ans += '\033[>31u' # extended keyboard mode ans += '\033[>31u' # extended keyboard mode
return ans return ans
@ -342,8 +357,8 @@ def alternate_screen(f: Optional[IO[str]] = None) -> Generator[None, None, None]
@contextmanager @contextmanager
def raw_mode(fd: Optional[int] = None) -> Generator[None, None, None]: def raw_mode(fd: Optional[int] = None) -> Generator[None, None, None]:
import tty
import termios import termios
import tty
if fd is None: if fd is None:
fd = sys.stdin.fileno() fd = sys.stdin.fileno()
old = termios.tcgetattr(fd) old = termios.tcgetattr(fd)