From 051f8050e88072c2711f4f297abf4f7cd869129a Mon Sep 17 00:00:00 2001 From: Philipp Hahn Date: Mon, 17 Jun 2024 07:15:31 +0200 Subject: [PATCH] fix: mouseDrag diagonally move mouse diagonally instead of first going up/down and then left/right. Do not use `time.sleep()` with Twisted reactor as it will also pause all other event processing. Patch `vncev` to print all mouse events, including those where not button is pressed / released. Issue #287 --- CHANGELOG.rst | 1 + libvncserver.mk | 1 + tests/functional/test_send_events.py | 8 ++++++- vncdotool/client.py | 35 +++++++++------------------- 4 files changed, 20 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fd1f86d..d479fe1 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,7 @@ - Python 3.12 is supported (@phahn) - Improve documentation (@phahn) - Improve PEP-484 type hinting (@phahn) + - Fix mouse dragging (@phahn) 1.2.0 (2023-06-06) ---------------------- diff --git a/libvncserver.mk b/libvncserver.mk index 2bed94e..5abfaa5 100644 --- a/libvncserver.mk +++ b/libvncserver.mk @@ -35,6 +35,7 @@ $(BUILD_DIR)/$(LIBVNCSERVER_TGZ): $(LIBVNCSERVER_DIR): $(BUILD_DIR)/$(LIBVNCSERVER_TGZ) tar xfzv $< -C $(BUILD_DIR) + sed -e '/^\s*if(buttonMask)\s*{$/s/buttonMask/1/' -i "$(LIBVNCSERVER_DIR)/examples/vncev.c" $(LIBVNCSERVER_MAKEFILE): $(LIBVNCSERVER_MAKEFILE_SRCS) cd $(LIBVNCSERVER_DIR) && cmake . diff --git a/tests/functional/test_send_events.py b/tests/functional/test_send_events.py index 8de9ed7..b69cfd0 100644 --- a/tests/functional/test_send_events.py +++ b/tests/functional/test_send_events.py @@ -65,11 +65,17 @@ def test_type(self) -> None: self.assertDisconnect() def test_mouse_move(self) -> None: - # vncev only prints click events, but will include the position self.run_vncdo('move 10 20 click 1') self.assertMouse(10, 20, 0x1) self.assertDisconnect() + def test_mouse_drag(self) -> None: + self.run_vncdo('move 10 20 drag 30 30 click 1') + self.assertMouse(10, 20, 0x0) + self.assertMouse(20, 25, 0x0) + self.assertMouse(30, 30, 0x1) + self.assertDisconnect() + def test_mouse_click_button_two(self) -> None: self.run_vncdo('click 2') self.assertMouse(0, 0, 0x2) diff --git a/vncdotool/client.py b/vncdotool/client.py index f6cd88e..129cfbc 100644 --- a/vncdotool/client.py +++ b/vncdotool/client.py @@ -10,13 +10,12 @@ import logging import math import socket -import time from pathlib import Path from struct import pack -from typing import IO, Any, TypeVar, Union +from typing import IO, Any, Iterator, TypeVar, Union from twisted.internet import reactor -from twisted.internet.defer import Deferred +from twisted.internet.defer import Deferred, inlineCallbacks, returnValue from twisted.internet.endpoints import HostnameEndpoint, UNIXClientEndpoint from twisted.internet.interfaces import IConnector, ITCPTransport from twisted.python.failure import Failure @@ -346,32 +345,20 @@ def mouseMove(self: TClient, x: int, y: int) -> TClient: self.pointerEvent(x, y, self.buttons) return self - def mouseDrag(self: TClient, x: int, y: int, step: int = 1) -> TClient: + @inlineCallbacks + def mouseDrag(self: TClient, x: int, y: int, step: int = 1) -> Iterator[Deferred]: """Move the mouse point to position (x, y) in increments of step""" log.debug("mouseDrag %d,%d", x, y) - if x < self.x: - xsteps = range(self.x - step, x, -step) - else: - xsteps = range(self.x + step, x, step) - - if y < self.y: - ysteps = range(self.y - step, y, -step) - else: - ysteps = range(self.y + step, y, step) - - for ypos in ysteps: - self.mouseMove(self.x, ypos) - reactor.doPoll(timeout=5) - time.sleep(0.2) - - for xpos in xsteps: - self.mouseMove(xpos, self.y) - reactor.doPoll(timeout=5) - time.sleep(0.2) + ox, oy = self.x, self.y + dx, dy = x - ox, y - oy + dmax = max(abs(dx), abs(dy)) + for s in range(0, dmax, step): + self.mouseMove(ox + dx * s // dmax, oy + dy * s // dmax) + yield self.pause(0.2) self.mouseMove(x, y) - return self + returnValue(self) def setImageMode(self) -> None: """Check support for PixelFormats announced by server or select client supported alternative."""