aboutsummaryrefslogtreecommitdiffstats
path: root/build/lib/dogtail/rawinput.py
diff options
context:
space:
mode:
Diffstat (limited to 'build/lib/dogtail/rawinput.py')
-rw-r--r--build/lib/dogtail/rawinput.py252
1 files changed, 252 insertions, 0 deletions
diff --git a/build/lib/dogtail/rawinput.py b/build/lib/dogtail/rawinput.py
new file mode 100644
index 00000000000..7100b29bfae
--- /dev/null
+++ b/build/lib/dogtail/rawinput.py
@@ -0,0 +1,252 @@
+# -*- coding: utf-8 -*-
+"""
+Handles raw input using AT-SPI event generation.
+
+Note: Think of keyvals as keysyms, and keynames as keystrings.
+
+Authors: David Malcolm <dmalcolm@redhat.com>, Zack Cerza <zcerza@redhat.com>
+"""
+
+__author__ = """
+David Malcolm <dmalcolm@redhat.com>,
+Zack Cerza <zcerza@redhat.com>
+"""
+import gi
+
+gi.require_version('Gtk', '3.0')
+gi.require_version('Gdk', '3.0')
+
+from gi.repository import Gdk
+from config import config
+from utils import doDelay
+from logging import debugLogger as logger
+from pyatspi import Registry as registry
+from pyatspi import (KEY_SYM, KEY_PRESS, KEY_PRESSRELEASE, KEY_RELEASE)
+from exceptions import ValueError
+from __builtin__ import unicode, unichr
+
+
+def doTypingDelay():
+ doDelay(config.typingDelay)
+
+
+def checkCoordinates(x, y):
+ if x < 0 or y < 0:
+ raise ValueError(
+ "Attempting to generate a mouse event at negative coordinates: (%s,%s)" % (x, y))
+
+
+def click(x, y, button=1, check=True):
+ """
+ Synthesize a mouse button click at (x,y)
+ """
+ if check:
+ checkCoordinates(x, y)
+ logger.log("Mouse button %s click at (%s,%s)" % (button, x, y))
+ registry.generateMouseEvent(x, y, 'b%sc' % button)
+ doDelay(config.actionDelay)
+
+
+def doubleClick(x, y, button=1, check=True):
+ """
+ Synthesize a mouse button double-click at (x,y)
+ """
+ if check:
+ checkCoordinates(x, y)
+ logger.log("Mouse button %s doubleclick at (%s,%s)" % (button, x, y))
+ registry.generateMouseEvent(x, y, 'b%sd' % button)
+ doDelay()
+
+
+def press(x, y, button=1, check=True):
+ """
+ Synthesize a mouse button press at (x,y)
+ """
+ if check:
+ checkCoordinates(x, y)
+ logger.log("Mouse button %s press at (%s,%s)" % (button, x, y))
+ registry.generateMouseEvent(x, y, 'b%sp' % button)
+ doDelay()
+
+
+def release(x, y, button=1, check=True):
+ """
+ Synthesize a mouse button release at (x,y)
+ """
+ if check:
+ checkCoordinates(x, y)
+ logger.log("Mouse button %s release at (%s,%s)" % (button, x, y))
+ registry.generateMouseEvent(x, y, 'b%sr' % button)
+ doDelay()
+
+
+def absoluteMotion(x, y, mouseDelay=None, check=True):
+ """
+ Synthesize mouse absolute motion to (x,y)
+ """
+ if check:
+ checkCoordinates(x, y)
+ logger.log("Mouse absolute motion to (%s,%s)" % (x, y))
+ registry.generateMouseEvent(x, y, 'abs')
+ if mouseDelay:
+ doDelay(mouseDelay)
+ else:
+ doDelay()
+
+
+def relativeMotion(x, y, mouseDelay=None):
+ logger.log("Mouse relative motion of (%s,%s)" % (x, y))
+ registry.generateMouseEvent(x, y, 'rel')
+ if mouseDelay:
+ doDelay(mouseDelay)
+ else:
+ doDelay()
+
+
+def drag(fromXY, toXY, button=1, check=True):
+ """
+ Synthesize a mouse press, drag, and release on the screen.
+ """
+ logger.log("Mouse button %s drag from %s to %s" % (button, fromXY, toXY))
+
+ (x, y) = fromXY
+ press(x, y, button, check)
+ # doDelay()
+
+ (x, y) = toXY
+ absoluteMotion(x, y, check=check)
+ doDelay()
+
+ release(x, y, button, check)
+ doDelay()
+
+
+def typeText(string):
+ """
+ Types the specified string, one character at a time.
+ Please note, you may have to set a higher typing delay,
+ if your machine misses/switches the characters typed.
+ Needed sometimes on slow setups/VMs typing non-ASCII utf8 chars.
+ """
+ if not isinstance(string, unicode):
+ string = string.decode('utf-8')
+ for char in string:
+ pressKey(char)
+
+keyNameAliases = {
+ 'enter': 'Return',
+ 'esc': 'Escape',
+ 'alt': 'Alt_L',
+ 'control': 'Control_L',
+ 'ctrl': 'Control_L',
+ 'shift': 'Shift_L',
+ 'del': 'Delete',
+ 'ins': 'Insert',
+ 'pageup': 'Page_Up',
+ 'pagedown': 'Page_Down',
+ ' ': 'space',
+ '\t': 'Tab',
+ '\n': 'Return'
+}
+
+
+# TODO: Dead code
+def keySymToUniChar(keySym): # pragma: no cover
+ i = Gdk.keyval_to_unicode(keySym)
+ if i:
+ UniChar = unichr(i)
+ else:
+ UniChar = ''
+ return UniChar
+
+
+def uniCharToKeySym(uniChar):
+ # OK, if it's not actually unicode we can fix that, right?
+ if not isinstance(uniChar, unicode):
+ uniChar = unicode(uniChar, 'utf-8')
+ i = ord(uniChar)
+ keySym = Gdk.unicode_to_keyval(i)
+ return keySym
+
+
+# dead code
+def keySymToKeyName(keySym): # pragma: no cover
+ return Gdk.keyval_name(keySym)
+
+
+def keyNameToKeySym(keyName):
+ keyName = keyNameAliases.get(keyName.lower(), keyName)
+ keySym = Gdk.keyval_from_name(keyName)
+ # various error 'codes' returned for non-recognized chars in versions of GTK3.X
+ if keySym == 0xffffff or keySym == 0x0 or keySym is None:
+ try:
+ keySym = uniCharToKeySym(keyName)
+ except: # not even valid utf-8 char
+ try: # Last attempt run at a keyName ('Meta_L', 'Dash' ...)
+ keySym = getattr(Gdk, 'KEY_' + keyName)
+ except AttributeError:
+ raise KeyError(keyName)
+ return keySym
+
+
+def keyNameToKeyCode(keyName):
+ """
+ Use GDK to get the keycode for a given keystring.
+
+ Note that the keycode returned by this function is often incorrect when
+ the requested keystring is obtained by holding down the Shift key.
+
+ Generally you should use uniCharToKeySym() and should only need this
+ function for nonprintable keys anyway.
+ """
+ keymap = Gdk.Keymap.get_for_display(Gdk.Display.get_default())
+ entries = keymap.get_entries_for_keyval(
+ Gdk.keyval_from_name(keyName))
+ try:
+ return entries[1][0].keycode
+ except TypeError:
+ pass
+
+
+def pressKey(keyName):
+ """
+ Presses (and releases) the key specified by keyName.
+ keyName is the English name of the key as seen on the keyboard. Ex: 'enter'
+ Names are looked up in Gdk.KEY_ If they are not found there, they are
+ looked up by uniCharToKeySym().
+ """
+ keySym = keyNameToKeySym(keyName)
+ registry.generateKeyboardEvent(keySym, None, KEY_SYM)
+ doTypingDelay()
+
+
+def keyCombo(comboString):
+ """
+ Generates the appropriate keyboard events to simulate a user pressing the
+ specified key combination.
+
+ comboString is the representation of the key combo to be generated.
+ e.g. '<Control><Alt>p' or '<Control><Shift>PageUp' or '<Control>q'
+ """
+ strings = []
+ for s in comboString.split('<'):
+ if s:
+ for S in s.split('>'):
+ if S:
+ S = keyNameAliases.get(S.lower(), S)
+ strings.append(S)
+ for s in strings:
+ if not hasattr(Gdk, s):
+ if not hasattr(Gdk, 'KEY_' + s):
+ raise ValueError("Cannot find key %s" % s)
+ modifiers = strings[:-1]
+ finalKey = strings[-1]
+ for modifier in modifiers:
+ code = keyNameToKeyCode(modifier)
+ registry.generateKeyboardEvent(code, None, KEY_PRESS)
+ code = keyNameToKeyCode(finalKey)
+ registry.generateKeyboardEvent(code, None, KEY_PRESSRELEASE)
+ for modifier in modifiers:
+ code = keyNameToKeyCode(modifier)
+ registry.generateKeyboardEvent(code, None, KEY_RELEASE)
+ doDelay()