Skip to content

Commit

Permalink
Implementation of WM_*BUTTONDBLCLK
Browse files Browse the repository at this point in the history
  • Loading branch information
Vinyzu committed Aug 17, 2024
1 parent 1e736b5 commit 63e8a9b
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 20 deletions.
29 changes: 23 additions & 6 deletions cdp_patches/input/async_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,18 @@ async def _sleep_timeout(self, timeout: Optional[float] = None) -> None:
await asyncio.sleep(timeout)

async def click(
self, button: Literal["left", "right", "middle"], x: Union[int, float], y: Union[int, float], pressed: str = "", emulate_behaviour: Optional[bool] = True, timeout: Optional[float] = None
self,
button: Literal["left", "right", "middle"],
x: Union[int, float],
y: Union[int, float],
pressed: str = "",
emulate_behaviour: Optional[bool] = True,
timeout: Optional[float] = None,
double_down: Optional[bool] = False,
) -> None:
x, y = int(x), int(y)

await self.down(button=button, x=x, y=y, emulate_behaviour=emulate_behaviour, timeout=timeout, pressed=pressed)
await self.down(button=button, x=x, y=y, emulate_behaviour=emulate_behaviour, timeout=timeout, pressed=pressed, double_down=double_down)
if self.emulate_behaviour and emulate_behaviour:
await self._sleep_timeout(timeout=timeout)
await self.up(button=button, x=x, y=y, pressed=pressed)
Expand All @@ -130,24 +137,34 @@ async def double_click(
) -> None:
x, y = int(x), int(y)

await self.click(button=button, x=x, y=y, timeout=timeout, emulate_behaviour=emulate_behaviour, pressed="__double_click__")
await self.click(button=button, x=x, y=y, timeout=timeout, emulate_behaviour=emulate_behaviour, pressed=pressed)
if self.emulate_behaviour and emulate_behaviour:
# await self._sleep_timeout(random.uniform(0.14, 0.21))
# await self._sleep_timeout(timeout=timeout)
pass
await self.click(button=button, x=x, y=y, emulate_behaviour=False, timeout=timeout, pressed="__double_click__")
await self.click(button=button, x=x, y=y, emulate_behaviour=False, timeout=timeout, pressed=pressed, double_down=True)

self.last_x, self.last_y = x, y

async def down(
self, button: Literal["left", "right", "middle"], x: Union[int, float], y: Union[int, float], pressed: str = "", emulate_behaviour: Optional[bool] = True, timeout: Optional[float] = None
self,
button: Literal["left", "right", "middle"],
x: Union[int, float],
y: Union[int, float],
pressed: str = "",
emulate_behaviour: Optional[bool] = True,
timeout: Optional[float] = None,
double_down: Optional[bool] = False,
) -> None:
x, y = int(x), int(y)

if self.emulate_behaviour and emulate_behaviour:
await self.move(x=x, y=y, timeout=timeout, emulate_behaviour=emulate_behaviour, pressed=pressed)
kwargs = _mk_kwargs(pressed)
self._base.down(button=button, x=x, y=y, **kwargs)
if double_down:
self._base.double_down(button=button, x=x, y=y, **kwargs)
else:
self._base.down(button=button, x=x, y=y, **kwargs)
self.last_x, self.last_y = x, y

async def up(self, button: Literal["left", "right", "middle"], x: Union[int, float], y: Union[int, float], pressed: str = "") -> None:
Expand Down
2 changes: 2 additions & 0 deletions cdp_patches/input/os_base/linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ def down(self, button: Literal["left", "right", "middle"], x: int, y: int) -> No
fake_input(self.display, X.ButtonPress, self._translate_button(button))
self.display.sync()

double_down = down

def up(self, button: Literal["left", "right", "middle"], x: int, y: int) -> None:
self.ensure_window()
self.move(x=x, y=y)
Expand Down
24 changes: 17 additions & 7 deletions cdp_patches/input/os_base/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
from pywinauto import application, timings
from pywinauto.application import WindowSpecification
from pywinauto.base_wrapper import ElementNotVisible
from pywinauto.controls.hwndwrapper import HwndWrapper, InvalidWindowHandle
from pywinauto.controls.hwndwrapper import HwndWrapper, InvalidWindowHandle, _calc_flags_and_coords
from pywinauto.windows import win32defines, win32functions, win32structures

from cdp_patches.input.exceptions import WindowClosedException

Expand Down Expand Up @@ -130,20 +131,29 @@ async def async_get_window(self, timeout: float = 1) -> WindowSpecification:
def down(self, button: Literal["left", "right", "middle"], x: int, y: int, pressed: str = "") -> None:
if not pressed:
pressed = button
if pressed == "__double_click__":
pressed = ""
self.ensure_window()
self.browser_window.press_mouse(button=button, pressed=pressed, coords=(int(x * self.scale_factor), int(y * self.scale_factor)))

def double_down(self, button: Literal["left", "right", "middle"], x: int, y: int, pressed: str = ""):
if not pressed:
pressed = button
self.ensure_window()

if button == "left":
msg = win32defines.WM_LBUTTONDBLCLK
elif button == "right":
msg = win32defines.WM_RBUTTONDBLCLK
else:
msg = win32defines.WM_MBUTTONDBLCLK

flags, click_point = _calc_flags_and_coords(pressed, [x, y])
win32functions.PostMessage(self.browser_window, msg, win32structures.WPARAM(flags), win32structures.LPARAM(click_point))

def up(self, button: Literal["left", "right", "middle"], x: int, y: int, pressed: str = "") -> None:
if pressed == "__double_click__":
pressed = ""
self.ensure_window()
self.browser_window.release_mouse(button=button, pressed=pressed, coords=(int(x * self.scale_factor), int(y * self.scale_factor)))

def move(self, x: int, y: int, pressed: str = "") -> None:
if pressed == "__double_click__":
pressed = ""
self.ensure_window()
self.browser_window.move_mouse(coords=(int(x * self.scale_factor), int(y * self.scale_factor)), pressed=pressed)

Expand Down
29 changes: 23 additions & 6 deletions cdp_patches/input/sync_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,18 @@ def _sleep_timeout(self, timeout: Optional[float] = None) -> None:
# pass

def click(
self, button: Literal["left", "right", "middle"], x: Union[int, float], y: Union[int, float], pressed: str = "", emulate_behaviour: Optional[bool] = True, timeout: Optional[float] = 0.07
self,
button: Literal["left", "right", "middle"],
x: Union[int, float],
y: Union[int, float],
pressed: str = "",
emulate_behaviour: Optional[bool] = True,
timeout: Optional[float] = 0.07,
double_down: Optional[bool] = False,
) -> None:
x, y = int(x), int(y)

self.down(button=button, x=x, y=y, emulate_behaviour=emulate_behaviour, timeout=timeout, pressed=pressed)
self.down(button=button, x=x, y=y, emulate_behaviour=emulate_behaviour, timeout=timeout, pressed=pressed, double_down=double_down)
if self.emulate_behaviour and emulate_behaviour:
self._sleep_timeout(timeout=timeout)
self.up(button=button, x=x, y=y, pressed=pressed)
Expand All @@ -128,23 +135,33 @@ def double_click(
) -> None:
x, y = int(x), int(y)

self.click(button=button, x=x, y=y, timeout=timeout, emulate_behaviour=emulate_behaviour, pressed="__double_click__")
self.click(button=button, x=x, y=y, timeout=timeout, emulate_behaviour=emulate_behaviour, pressed=pressed)
if emulate_behaviour and self.emulate_behaviour:
# self._sleep_timeout(random.uniform(0.14, 0.21))
# self._sleep_timeout(timeout=timeout)
pass
self.click(button=button, x=x, y=y, emulate_behaviour=False, timeout=timeout, pressed="__double_click__")
self.click(button=button, x=x, y=y, emulate_behaviour=False, timeout=timeout, pressed=pressed, double_down=True)

self.last_x, self.last_y = x, y

def down(
self, button: Literal["left", "right", "middle"], x: Union[int, float], y: Union[int, float], pressed: str = "", emulate_behaviour: Optional[bool] = True, timeout: Optional[float] = None
self,
button: Literal["left", "right", "middle"],
x: Union[int, float],
y: Union[int, float],
pressed: str = "",
emulate_behaviour: Optional[bool] = True,
timeout: Optional[float] = None,
double_down: Optional[bool] = False,
) -> None:
x, y = int(x), int(y)

if self.emulate_behaviour and emulate_behaviour:
self.move(x=x, y=y, emulate_behaviour=emulate_behaviour, timeout=timeout, pressed=pressed)
self._base.down(button=button, x=x, y=y, **_mk_kwargs(pressed))
if double_down:
self._base.double_down(button=button, x=x, y=y, **_mk_kwargs(pressed))
else:
self._base.down(button=button, x=x, y=y, **_mk_kwargs(pressed))
self.last_x, self.last_y = x, y

def up(self, button: Literal["left", "right", "middle"], x: Union[int, float], y: Union[int, float], pressed: str = "") -> None:
Expand Down
8 changes: 7 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import signal
import subprocess
import sys
import tempfile
from typing import AsyncGenerator, Generator, List

Expand Down Expand Up @@ -167,7 +168,12 @@ async def async_driver() -> AsyncGenerator[async_webdriver.Chrome, None]:

@pytest.fixture
def chrome_proc() -> Generator[subprocess.Popen[bytes], None, None]:
with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as tempdir:
if sys.version_info.minor >= 10:
options = {"ignore_cleanup_errors": True}
else:
options = {}

with tempfile.TemporaryDirectory(**options) as tempdir: # type: ignore[call-overload]
path = find_chrome_executable()
proc = subprocess.Popen([path, f"--remote-debugging-port={random_port()}", f"--user-data-dir={tempdir}", "--no-first-run"])
try:
Expand Down

0 comments on commit 63e8a9b

Please sign in to comment.