MouseScrollUp/MouseScrollDown => plain MousEvent's

... which means they get passesd x, y, etc. In particular,
they are passed the keyboard modifiers. This allows widgets
to use e.g. ctrl-wheel to scroll right/left.
This commit is contained in:
Nitzan Shaked
2022-12-30 18:44:09 +02:00
parent a33d87d3d4
commit e13ea5e0bd
3 changed files with 43 additions and 48 deletions

View File

@@ -54,36 +54,35 @@ class XTermParser(Parser[events.Event]):
if sgr_match: if sgr_match:
_buttons, _x, _y, state = sgr_match.groups() _buttons, _x, _y, state = sgr_match.groups()
buttons = int(_buttons) buttons = int(_buttons)
button = (buttons + 1) & 3
x = int(_x) - 1 x = int(_x) - 1
y = int(_y) - 1 y = int(_y) - 1
delta_x = x - self.last_x delta_x = x - self.last_x
delta_y = y - self.last_y delta_y = y - self.last_y
self.last_x = x self.last_x = x
self.last_y = y self.last_y = y
event: events.Event event_cls = (
if buttons & 64: (events.MouseScrollDown if buttons & 1 else events.MouseScrollUp)
event = ( if buttons & 64
events.MouseScrollUp if button == 1 else events.MouseScrollDown else events.MouseMove
)(sender, x, y) if buttons & 32
else: else (events.MouseDown if state == "M" else events.MouseUp)
event = ( )
events.MouseMove if event_cls in (events.MouseScrollUp, events.MouseScrollDown):
if buttons & 32 buttons &= ~(64 | 3)
else (events.MouseDown if state == "M" else events.MouseUp) button = (buttons + 1) & 3
)( event = event_cls(
sender, sender,
x, x,
y, y,
delta_x, delta_x,
delta_y, delta_y,
button, button,
bool(buttons & 4), bool(buttons & 4),
bool(buttons & 8), bool(buttons & 8),
bool(buttons & 16), bool(buttons & 16),
screen_x=x, screen_x=x,
screen_y=y, screen_y=y,
) )
return event return event
return None return None

View File

@@ -419,22 +419,14 @@ class MouseUp(MouseEvent, bubble=True, verbose=True):
pass pass
class MouseScrollDown(InputEvent, bubble=True, verbose=True): @rich.repr.auto
__slots__ = ["x", "y"] class MouseScrollDown(MouseEvent, bubble=True):
pass
def __init__(self, sender: MessageTarget, x: int, y: int) -> None:
super().__init__(sender)
self.x = x
self.y = y
class MouseScrollUp(InputEvent, bubble=True, verbose=True): @rich.repr.auto
__slots__ = ["x", "y"] class MouseScrollUp(MouseEvent, bubble=True):
pass
def __init__(self, sender: MessageTarget, x: int, y: int) -> None:
super().__init__(sender)
self.x = x
self.y = y
class Click(MouseEvent, bubble=True): class Click(MouseEvent, bubble=True):

View File

@@ -236,14 +236,14 @@ def test_mouse_move(parser, sequence, shift, meta, button):
@pytest.mark.parametrize( @pytest.mark.parametrize(
"sequence", "sequence, shift, meta",
[ [
"\x1b[<64;18;25M", ("\x1b[<64;18;25M", False, False),
"\x1b[<68;18;25M", ("\x1b[<68;18;25M", True, False),
"\x1b[<72;18;25M", ("\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. """Scrolling the mouse with and without modifiers held down.
We don't currently capture modifier keys in scroll events. 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 isinstance(event, MouseScrollUp)
assert event.x == 17 assert event.x == 17
assert event.y == 24 assert event.y == 24
assert event.shift is shift
assert event.meta is meta
@pytest.mark.parametrize( @pytest.mark.parametrize(
"sequence", "sequence, shift, meta",
[ [
"\x1b[<65;18;25M", ("\x1b[<65;18;25M", False, False),
"\x1b[<69;18;25M", ("\x1b[<69;18;25M", True, False),
"\x1b[<73;18;25M", ("\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)) events = list(parser.feed(sequence))
assert len(events) == 1 assert len(events) == 1
@@ -276,6 +278,8 @@ def test_mouse_scroll_down(parser, sequence):
assert isinstance(event, MouseScrollDown) assert isinstance(event, MouseScrollDown)
assert event.x == 17 assert event.x == 17
assert event.y == 24 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):