mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Support MouseScrollLeft and MouseScrollRight control sequences.
This commit is contained in:
@@ -100,9 +100,12 @@ class XTermParser(Parser[Message]):
|
|||||||
event_class: type[events.MouseEvent]
|
event_class: type[events.MouseEvent]
|
||||||
|
|
||||||
if buttons & 64:
|
if buttons & 64:
|
||||||
event_class = (
|
event_class = [
|
||||||
events.MouseScrollDown if buttons & 1 else events.MouseScrollUp
|
events.MouseScrollUp,
|
||||||
)
|
events.MouseScrollDown,
|
||||||
|
events.MouseScrollLeft,
|
||||||
|
events.MouseScrollRight,
|
||||||
|
][buttons & 3]
|
||||||
button = 0
|
button = 0
|
||||||
else:
|
else:
|
||||||
button = (buttons + 1) & 3
|
button = (buttons + 1) & 3
|
||||||
|
|||||||
@@ -606,6 +606,24 @@ class MouseScrollUp(MouseEvent, bubble=True, verbose=True):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@rich.repr.auto
|
||||||
|
class MouseScrollRight(MouseEvent, bubble=True, verbose=True):
|
||||||
|
"""Sent when the mouse wheel is scrolled *right*.
|
||||||
|
|
||||||
|
- [X] Bubbles
|
||||||
|
- [X] Verbose
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@rich.repr.auto
|
||||||
|
class MouseScrollLeft(MouseEvent, bubble=True, verbose=True):
|
||||||
|
"""Sent when the mouse wheel is scrolled *left*.
|
||||||
|
|
||||||
|
- [X] Bubbles
|
||||||
|
- [X] Verbose
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Click(MouseEvent, bubble=True):
|
class Click(MouseEvent, bubble=True):
|
||||||
"""Sent when a widget is clicked.
|
"""Sent when a widget is clicked.
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,12 @@ _JUSTIFY_MAP: dict[str, JustifyMethod] = {
|
|||||||
|
|
||||||
|
|
||||||
_MOUSE_EVENTS_DISALLOW_IF_DISABLED = (events.MouseEvent, events.Enter, events.Leave)
|
_MOUSE_EVENTS_DISALLOW_IF_DISABLED = (events.MouseEvent, events.Enter, events.Leave)
|
||||||
_MOUSE_EVENTS_ALLOW_IF_DISABLED = (events.MouseScrollDown, events.MouseScrollUp)
|
_MOUSE_EVENTS_ALLOW_IF_DISABLED = (
|
||||||
|
events.MouseScrollDown,
|
||||||
|
events.MouseScrollUp,
|
||||||
|
events.MouseScrollRight,
|
||||||
|
events.MouseScrollLeft,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@rich.repr.auto
|
@rich.repr.auto
|
||||||
@@ -4569,6 +4574,18 @@ class Widget(DOMNode):
|
|||||||
if self._scroll_up_for_pointer(animate=False):
|
if self._scroll_up_for_pointer(animate=False):
|
||||||
event.stop()
|
event.stop()
|
||||||
|
|
||||||
|
def _on_mouse_scroll_right(self, event: events.MouseScrollRight) -> None:
|
||||||
|
if self.allow_horizontal_scroll:
|
||||||
|
self.release_anchor()
|
||||||
|
if self._scroll_right_for_pointer(animate=False):
|
||||||
|
event.stop()
|
||||||
|
|
||||||
|
def _on_mouse_scroll_left(self, event: events.MouseScrollLeft) -> None:
|
||||||
|
if self.allow_horizontal_scroll:
|
||||||
|
self.release_anchor()
|
||||||
|
if self._scroll_left_for_pointer(animate=False):
|
||||||
|
event.stop()
|
||||||
|
|
||||||
def _on_scroll_to(self, message: ScrollTo) -> None:
|
def _on_scroll_to(self, message: ScrollTo) -> None:
|
||||||
if self._allow_scroll:
|
if self._allow_scroll:
|
||||||
self.release_anchor()
|
self.release_anchor()
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ from textual.events import (
|
|||||||
MouseDown,
|
MouseDown,
|
||||||
MouseMove,
|
MouseMove,
|
||||||
MouseScrollDown,
|
MouseScrollDown,
|
||||||
|
MouseScrollLeft,
|
||||||
|
MouseScrollRight,
|
||||||
MouseScrollUp,
|
MouseScrollUp,
|
||||||
MouseUp,
|
MouseUp,
|
||||||
Paste,
|
Paste,
|
||||||
@@ -283,6 +285,56 @@ def test_mouse_scroll_down(parser, sequence, shift, meta):
|
|||||||
assert event.meta is meta
|
assert event.meta is meta
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"sequence, shift, meta",
|
||||||
|
[
|
||||||
|
("\x1b[<66;18;25M", False, False),
|
||||||
|
("\x1b[<70;18;25M", True, False),
|
||||||
|
("\x1b[<74;18;25M", False, True),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_mouse_scroll_left(parser, sequence, shift, meta):
|
||||||
|
"""Scrolling the mouse with and without modifiers held down.
|
||||||
|
We don't currently capture modifier keys in scroll events.
|
||||||
|
"""
|
||||||
|
events = list(parser.feed(sequence))
|
||||||
|
|
||||||
|
assert len(events) == 1
|
||||||
|
|
||||||
|
event = events[0]
|
||||||
|
|
||||||
|
assert isinstance(event, MouseScrollLeft)
|
||||||
|
assert event.x == 17
|
||||||
|
assert event.y == 24
|
||||||
|
assert event.shift is shift
|
||||||
|
assert event.meta is meta
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"sequence, shift, meta",
|
||||||
|
[
|
||||||
|
("\x1b[<67;18;25M", False, False),
|
||||||
|
("\x1b[<71;18;25M", True, False),
|
||||||
|
("\x1b[<75;18;25M", False, True),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_mouse_scroll_right(parser, sequence, shift, meta):
|
||||||
|
"""Scrolling the mouse with and without modifiers held down.
|
||||||
|
We don't currently capture modifier keys in scroll events.
|
||||||
|
"""
|
||||||
|
events = list(parser.feed(sequence))
|
||||||
|
|
||||||
|
assert len(events) == 1
|
||||||
|
|
||||||
|
event = events[0]
|
||||||
|
|
||||||
|
assert isinstance(event, MouseScrollRight)
|
||||||
|
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):
|
def test_mouse_event_detected_but_info_not_parsed(parser):
|
||||||
# I don't know if this can actually happen in reality, but
|
# I don't know if this can actually happen in reality, but
|
||||||
# there's a branch in the code that allows for the possibility.
|
# there's a branch in the code that allows for the possibility.
|
||||||
|
|||||||
Reference in New Issue
Block a user