Spaces:
Sleeping
Sleeping
File size: 4,243 Bytes
d7b3d84 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | """Mouse class for mouse operations."""
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from cdp_use.cdp.input.commands import DispatchMouseEventParameters, SynthesizeScrollGestureParameters
from cdp_use.cdp.input.types import MouseButton
from browser_use.browser.session import BrowserSession
class Mouse:
"""Mouse operations for a target."""
def __init__(self, browser_session: 'BrowserSession', session_id: str | None = None, target_id: str | None = None):
self._browser_session = browser_session
self._client = browser_session.cdp_client
self._session_id = session_id
self._target_id = target_id
async def click(self, x: int, y: int, button: 'MouseButton' = 'left', click_count: int = 1) -> None:
"""Click at the specified coordinates."""
# Mouse press
press_params: 'DispatchMouseEventParameters' = {
'type': 'mousePressed',
'x': x,
'y': y,
'button': button,
'clickCount': click_count,
}
await self._client.send.Input.dispatchMouseEvent(
press_params,
session_id=self._session_id,
)
# Mouse release
release_params: 'DispatchMouseEventParameters' = {
'type': 'mouseReleased',
'x': x,
'y': y,
'button': button,
'clickCount': click_count,
}
await self._client.send.Input.dispatchMouseEvent(
release_params,
session_id=self._session_id,
)
async def down(self, button: 'MouseButton' = 'left', click_count: int = 1) -> None:
"""Press mouse button down."""
params: 'DispatchMouseEventParameters' = {
'type': 'mousePressed',
'x': 0, # Will use last mouse position
'y': 0,
'button': button,
'clickCount': click_count,
}
await self._client.send.Input.dispatchMouseEvent(
params,
session_id=self._session_id,
)
async def up(self, button: 'MouseButton' = 'left', click_count: int = 1) -> None:
"""Release mouse button."""
params: 'DispatchMouseEventParameters' = {
'type': 'mouseReleased',
'x': 0, # Will use last mouse position
'y': 0,
'button': button,
'clickCount': click_count,
}
await self._client.send.Input.dispatchMouseEvent(
params,
session_id=self._session_id,
)
async def move(self, x: int, y: int, steps: int = 1) -> None:
"""Move mouse to the specified coordinates."""
# TODO: Implement smooth movement with multiple steps if needed
_ = steps # Acknowledge parameter for future use
params: 'DispatchMouseEventParameters' = {'type': 'mouseMoved', 'x': x, 'y': y}
await self._client.send.Input.dispatchMouseEvent(params, session_id=self._session_id)
async def scroll(self, x: int = 0, y: int = 0, delta_x: int | None = None, delta_y: int | None = None) -> None:
"""Scroll the page using robust CDP methods."""
if not self._session_id:
raise RuntimeError('Session ID is required for scroll operations')
# Method 1: Try mouse wheel event (most reliable)
try:
# Get viewport dimensions
layout_metrics = await self._client.send.Page.getLayoutMetrics(session_id=self._session_id)
viewport_width = layout_metrics['layoutViewport']['clientWidth']
viewport_height = layout_metrics['layoutViewport']['clientHeight']
# Use provided coordinates or center of viewport
scroll_x = x if x > 0 else viewport_width / 2
scroll_y = y if y > 0 else viewport_height / 2
# Calculate scroll deltas (positive = down/right)
scroll_delta_x = delta_x or 0
scroll_delta_y = delta_y or 0
# Dispatch mouse wheel event
await self._client.send.Input.dispatchMouseEvent(
params={
'type': 'mouseWheel',
'x': scroll_x,
'y': scroll_y,
'deltaX': scroll_delta_x,
'deltaY': scroll_delta_y,
},
session_id=self._session_id,
)
return
except Exception:
pass
# Method 2: Fallback to synthesizeScrollGesture
try:
params: 'SynthesizeScrollGestureParameters' = {'x': x, 'y': y, 'xDistance': delta_x or 0, 'yDistance': delta_y or 0}
await self._client.send.Input.synthesizeScrollGesture(
params,
session_id=self._session_id,
)
except Exception:
# Method 3: JavaScript fallback
scroll_js = f'window.scrollBy({delta_x or 0}, {delta_y or 0})'
await self._client.send.Runtime.evaluate(
params={'expression': scroll_js, 'returnByValue': True},
session_id=self._session_id,
)
|