diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ee7b9a673..876edeb4b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.10.0] - Unreleased + +### Changed + +- `MouseScrollUp` and `MouseScrollDown` now inherit from `MouseEvent` and have attached modifier keys. https://github.com/Textualize/textual/pull/1458 + ## [0.9.1] - 2022-12-30 ### Added diff --git a/src/textual/_win_sleep.py b/src/textual/_win_sleep.py index 4d417a07e3..e90930afca 100644 --- a/src/textual/_win_sleep.py +++ b/src/textual/_win_sleep.py @@ -12,7 +12,6 @@ CREATE_WAITABLE_TIMER_HIGH_RESOLUTION = 0x00000002 - def sleep(sleep_for: float) -> None: """A replacement sleep for Windows. diff --git a/src/textual/_xterm_parser.py b/src/textual/_xterm_parser.py index 40af686a48..ab760e2427 100644 --- a/src/textual/_xterm_parser.py +++ b/src/textual/_xterm_parser.py @@ -54,36 +54,40 @@ def parse_mouse_code(self, code: str, sender: MessageTarget) -> events.Event | N if sgr_match: _buttons, _x, _y, state = sgr_match.groups() buttons = int(_buttons) - button = (buttons + 1) & 3 x = int(_x) - 1 y = int(_y) - 1 delta_x = x - self.last_x delta_y = y - self.last_y self.last_x = x self.last_y = y - event: events.Event + event_class: type[events.MouseEvent] + if buttons & 64: - event = ( - events.MouseScrollUp if button == 1 else events.MouseScrollDown - )(sender, x, y) - else: - event = ( - events.MouseMove - if buttons & 32 - else (events.MouseDown if state == "M" else events.MouseUp) - )( - sender, - x, - y, - delta_x, - delta_y, - button, - bool(buttons & 4), - bool(buttons & 8), - bool(buttons & 16), - screen_x=x, - screen_y=y, + event_class = ( + events.MouseScrollDown if buttons & 1 else events.MouseScrollUp ) + button = 0 + else: + if buttons & 32: + event_class = events.MouseMove + else: + event_class = events.MouseDown if state == "M" else events.MouseUp + + button = (buttons + 1) & 3 + + event = event_class( + sender, + x, + y, + delta_x, + delta_y, + button, + bool(buttons & 4), + bool(buttons & 8), + bool(buttons & 16), + screen_x=x, + screen_y=y, + ) return event return None diff --git a/src/textual/events.py b/src/textual/events.py index 1f509a0723..e99007e211 100644 --- a/src/textual/events.py +++ b/src/textual/events.py @@ -419,22 +419,14 @@ class MouseUp(MouseEvent, bubble=True, verbose=True): pass -class MouseScrollDown(InputEvent, bubble=True, verbose=True): - __slots__ = ["x", "y"] - - def __init__(self, sender: MessageTarget, x: int, y: int) -> None: - super().__init__(sender) - self.x = x - self.y = y - +@rich.repr.auto +class MouseScrollDown(MouseEvent, bubble=True): + pass -class MouseScrollUp(InputEvent, bubble=True, verbose=True): - __slots__ = ["x", "y"] - def __init__(self, sender: MessageTarget, x: int, y: int) -> None: - super().__init__(sender) - self.x = x - self.y = y +@rich.repr.auto +class MouseScrollUp(MouseEvent, bubble=True): + pass class Click(MouseEvent, bubble=True): diff --git a/tests/test_xterm_parser.py b/tests/test_xterm_parser.py index 6e352d87da..1b426267bb 100644 --- a/tests/test_xterm_parser.py +++ b/tests/test_xterm_parser.py @@ -236,14 +236,14 @@ def test_mouse_move(parser, sequence, shift, meta, button): @pytest.mark.parametrize( - "sequence", + "sequence, shift, meta", [ - "\x1b[<64;18;25M", - "\x1b[<68;18;25M", - "\x1b[<72;18;25M", + ("\x1b[<64;18;25M", False, False), + ("\x1b[<68;18;25M", True, False), + ("\x1b[<72;18;25M", False, True), ], ) -def test_mouse_scroll_up(parser, sequence): +def test_mouse_scroll_up(parser, sequence, shift, meta): """Scrolling the mouse with and without modifiers held down. We don't currently capture modifier keys in scroll events. """ @@ -256,17 +256,19 @@ def test_mouse_scroll_up(parser, sequence): assert isinstance(event, MouseScrollUp) assert event.x == 17 assert event.y == 24 + assert event.shift is shift + assert event.meta is meta @pytest.mark.parametrize( - "sequence", + "sequence, shift, meta", [ - "\x1b[<65;18;25M", - "\x1b[<69;18;25M", - "\x1b[<73;18;25M", + ("\x1b[<65;18;25M", False, False), + ("\x1b[<69;18;25M", True, False), + ("\x1b[<73;18;25M", False, True), ], ) -def test_mouse_scroll_down(parser, sequence): +def test_mouse_scroll_down(parser, sequence, shift, meta): events = list(parser.feed(sequence)) assert len(events) == 1 @@ -276,6 +278,8 @@ def test_mouse_scroll_down(parser, sequence): assert isinstance(event, MouseScrollDown) assert event.x == 17 assert event.y == 24 + assert event.shift is shift + assert event.meta is meta def test_mouse_event_detected_but_info_not_parsed(parser):