summaryrefslogtreecommitdiffstats
path: root/tools/site_compare/drivers/win32/mouse.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/site_compare/drivers/win32/mouse.py')
-rw-r--r--tools/site_compare/drivers/win32/mouse.py243
1 files changed, 243 insertions, 0 deletions
diff --git a/tools/site_compare/drivers/win32/mouse.py b/tools/site_compare/drivers/win32/mouse.py
new file mode 100644
index 0000000..9475f2d
--- /dev/null
+++ b/tools/site_compare/drivers/win32/mouse.py
@@ -0,0 +1,243 @@
+#!/usr/bin/python2.4
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""SiteCompare module for simulating mouse input.
+
+This module contains functions that can be used to simulate a user
+navigating using a pointing device. This includes mouse movement,
+clicking with any button, and dragging.
+"""
+
+import time # for sleep
+
+import win32api # for mouse_event
+import win32con # Windows constants
+import win32gui # for window functions
+
+
+def ScreenToMouse(pt):
+ """Convert a value in screen coordinates to mouse coordinates.
+
+ Mouse coordinates are specified as a percentage of screen dimensions,
+ normalized to 16 bits. 0 represents the far left/top of the screen,
+ 65535 represents the far right/bottom. This function assumes that
+ the size of the screen is fixed at module load time and does not change
+
+ Args:
+ pt: the point of the coords to convert
+
+ Returns:
+ the converted point
+ """
+
+ # Initialize the screen dimensions on first execution. Note that this
+ # function assumes that the screen dimensions do not change during run.
+ if not ScreenToMouse._SCREEN_DIMENSIONS:
+ desktop = win32gui.GetClientRect(win32gui.GetDesktopWindow())
+ ScreenToMouse._SCREEN_DIMENSIONS = (desktop[2], desktop[3])
+
+ return ((65535 * pt[0]) / ScreenToMouse._SCREEN_DIMENSIONS[0],
+ (65535 * pt[1]) / ScreenToMouse._SCREEN_DIMENSIONS[1])
+
+ScreenToMouse._SCREEN_DIMENSIONS = None
+
+
+def PressButton(down, button='left'):
+ """Simulate a mouse button press or release at the current mouse location.
+
+ Args:
+ down: whether the button is pressed or released
+ button: which button is pressed
+
+ Returns:
+ None
+ """
+
+ # Put the mouse_event flags in a convenient dictionary by button
+ flags = {
+ 'left': (win32con.MOUSEEVENTF_LEFTUP, win32con.MOUSEEVENTF_LEFTDOWN),
+ 'middle': (win32con.MOUSEEVENTF_MIDDLEUP, win32con.MOUSEEVENTF_MIDDLEDOWN),
+ 'right': (win32con.MOUSEEVENTF_RIGHTUP, win32con.MOUSEEVENTF_RIGHTDOWN)
+ }
+
+ # hit the button
+ win32api.mouse_event(flags[button][down], 0, 0)
+
+
+def ClickButton(button='left', click_time=0):
+ """Press and release a mouse button at the current mouse location.
+
+ Args:
+ button: which button to click
+ click_time: duration between press and release
+
+ Returns:
+ None
+ """
+ PressButton(True, button)
+ time.sleep(click_time)
+ PressButton(False, button)
+
+
+def DoubleClickButton(button='left', click_time=0, time_between_clicks=0):
+ """Double-click a mouse button at the current mouse location.
+
+ Args:
+ button: which button to click
+ click_time: duration between press and release
+ time_between_clicks: time to pause between clicks
+
+ Returns:
+ None
+ """
+ ClickButton(button, click_time)
+ time.sleep(time_between_clicks)
+ ClickButton(button, click_time)
+
+
+def MoveToLocation(pos, duration=0, tick=0.01):
+ """Move the mouse cursor to a specified location, taking the specified time.
+
+ Args:
+ pos: position (in screen coordinates) to move to
+ duration: amount of time the move should take
+ tick: amount of time between successive moves of the mouse
+
+ Returns:
+ None
+ """
+ # calculate the number of moves to reach the destination
+ num_steps = (duration/tick)+1
+
+ # get the current and final mouse position in mouse coords
+ current_location = ScreenToMouse(win32gui.GetCursorPos())
+ end_location = ScreenToMouse(pos)
+
+ # Calculate the step size
+ step_size = ((end_location[0]-current_location[0])/num_steps,
+ (end_location[1]-current_location[1])/num_steps)
+ step = 0
+
+ while step < num_steps:
+ # Move the mouse one step
+ current_location = (current_location[0]+step_size[0],
+ current_location[1]+step_size[1])
+
+ # Coerce the coords to int to avoid a warning from pywin32
+ win32api.mouse_event(
+ win32con.MOUSEEVENTF_MOVE|win32con.MOUSEEVENTF_ABSOLUTE,
+ int(current_location[0]), int(current_location[1]))
+
+ step += 1
+ time.sleep(tick)
+
+
+def ClickAtLocation(pos, button='left', click_time=0):
+ """Simulate a mouse click in a particular location, in screen coordinates.
+
+ Args:
+ pos: position in screen coordinates (x,y)
+ button: which button to click
+ click_time: duration of the click
+
+ Returns:
+ None
+ """
+ MoveToLocation(pos)
+ ClickButton(button, click_time)
+
+
+def ClickInWindow(hwnd, offset=None, button='left', click_time=0):
+ """Simulate a user mouse click in the center of a window.
+
+ Args:
+ hwnd: handle of the window to click in
+ offset: where to click, defaults to dead center
+ button: which button to click
+ click_time: duration of the click
+
+ Returns:
+ Nothing
+ """
+
+ rect = win32gui.GetClientRect(hwnd)
+ if offset is None: offset = (rect[2]/2, rect[3]/2)
+
+ # get the screen coordinates of the window's center
+ pos = win32gui.ClientToScreen(hwnd, offset)
+
+ ClickAtLocation(pos, button, click_time)
+
+
+def DoubleClickInWindow(
+ hwnd, offset=None, button='left', click_time=0, time_between_clicks=0.1):
+ """Simulate a user mouse double click in the center of a window.
+
+ Args:
+ hwnd: handle of the window to click in
+ offset: where to click, defaults to dead center
+ button: which button to click
+ click_time: duration of the clicks
+ time_between_clicks: length of time to pause between clicks
+
+ Returns:
+ Nothing
+ """
+ ClickInWindow(hwnd, offset, button, click_time)
+ time.sleep(time_between_clicks)
+ ClickInWindow(hwnd, offset, button, click_time)
+
+if __name__ == "__main__":
+ # We're being invoked rather than imported. Let's do some tests
+
+ screen_size = win32gui.GetClientRect(win32gui.GetDesktopWindow())
+ screen_size = (screen_size[2], screen_size[3])
+
+ # move the mouse (instantly) to the upper right corner
+ MoveToLocation((screen_size[0], 0))
+
+ # move the mouse (over five seconds) to the lower left corner
+ MoveToLocation((0, screen_size[1]), 5)
+
+ # click the left mouse button. This will open up the Start menu
+ # if the taskbar is at the bottom
+
+ ClickButton()
+
+ # wait a bit, then click the right button to open the context menu
+ time.sleep(3)
+ ClickButton('right')
+
+ # move the mouse away and then click the left button to dismiss the
+ # context menu
+ MoveToLocation((screen_size[0]/2, screen_size[1]/2), 3)
+ MoveToLocation((0, 0), 3)
+ ClickButton()
+ \ No newline at end of file