#!/usr/bin/env python
from kivy.logger import Logger
log = Logger.getChild("KiTT")
from Xlib import X, XK, protocol, display, Xcursorfont
from Xlib.ext import xtest
from Xlib.protocol import request
import os
disp = display.Display()
[docs]def grab_mouse():
log.debug("grab_mouse")
cursor_font = disp.open_font('cursor')
cursor = 0
mycursor = cursor_font.create_glyph_cursor(cursor_font, cursor, cursor+1, (0,0,0), (0xFFFF, 0xFFFF, 0xFFFF))
# grab_pointer(owner_events, event_mask, pointer_mode, keyboard_mode, confine_to, cursor, time)
disp.screen().root.grab_pointer(False, # owner_events
X.Button4MotionMask | X.Button5MotionMask, # event_mask
X.GrabModeAsync, # pointer_mode
X.GrabModeAsync, # keyboard_mode
0, # confine_to
mycursor, # cursor
X.CurrentTime) # time
disp.sync()
[docs]def ungrab_mouse():
log.debug("ungrab_mouse")
disp.ungrab_pointer(X.CurrentTime)
disp.sync()
[docs]def do_mouse_click(button, target=None):
"""
executes mouse button click
:param button: X.Button1, X.Button2 or X.Button3 depending on which button to be triggered
:param target: list containing name(s) of the target window
"""
log.debug("do_mouse_click")
root = disp.screen().root
pointer_info = request.QueryPointer(display = disp.display,
window = root)
root_xpos, root_ypos = (pointer_info._data['root_x'], pointer_info._data['root_y'])
targetwindow = disp.get_input_focus().focus
if isinstance(button, basestring):
if button is "Button1":
button = X.Button1
elif button is "Button2":
button = X.Button2
elif button is "Button3":
button = X.Button3
else:
return False
elif not button in (X.Button1, X.Button2, X.Button3):
return False
if targetwindow.get_wm_name() is None and targetwindow.get_wm_class() is None:
targetwindow = targetwindow.query_tree().parent
ret = targetwindow.translate_coords(root, root_xpos, root_ypos)
target_xpos = ret.x
target_ypos = ret.y
if target:
for target in target:
if target in targetwindow.get_wm_class():
break
else:
return False
myevent_press = protocol.event.ButtonPress(detail = button,
root=root,
root_x=root_xpos,
root_y=root_ypos,
window=targetwindow.id,
event_x=target_xpos,
event_y=target_ypos,
same_screen=1,
state=0,
time=X.CurrentTime,
child=0)
myevent_release = protocol.event.ButtonRelease(detail = button,
root=root,
root_x=root_xpos,
root_y=root_ypos,
window=targetwindow.id,
event_x=target_xpos,
event_y=target_ypos,
same_screen=1,
state=0,
time=X.CurrentTime,
child=0)
# use window instead of display (xobject/drawable.py:send_event)
disp.send_event(X.InputFocus,
myevent_press,
event_mask=0,
propagate=1)
# use window instead of display (xobject/drawable.py:send_event)
disp.send_event(X.InputFocus,
myevent_release,
event_mask=0,
propagate=1)
disp.sync()
return True
[docs]def do_key_press(keys, target=None):
"""
executes a keypress
:param keys: argument tuple containing one or several modifier keys, and the key to press
:param target: list containing name(s) of the target window
the key to pass as a parameter has to be taken from Xlib.XK library
"""
log.debug("do_key_press")
root = disp.screen().root
keys = map(lambda k: XK.string_to_keysym(k) if isinstance(k, basestring) else k,
keys)
for key in keys:
if not key in XK.__dict__.values():
return False
pointer_info = request.QueryPointer(display = disp.display,
window = root)
root_xpos, root_ypos = (pointer_info._data['root_x'], pointer_info._data['root_y'])
targetwindow = disp.get_input_focus().focus
if targetwindow.get_wm_name() is None and targetwindow.get_wm_class() is None:
targetwindow = targetwindow.query_tree().parent
ret = targetwindow.translate_coords(root, root_xpos, root_ypos)
target_xpos = ret.x
target_ypos = ret.y
if target and targetwindow.get_wm_class():
for t in target:
if t in targetwindow.get_wm_class():
break
else:
log.info("Window '%s' not found in target(s) %s" % (targetwindow.get_wm_class(), target))
return False
def send_key(display, window, keycodes):
'''Send a KeyPress and KeyRelease event'''
if not type(keycodes) in (tuple, list):
keycodes = (keycodes,)
# send with modifier
for keycode in keycodes:
xtest.fake_input(window,
X.KeyPress,
display.keysym_to_keycode(keycode))
for keycode in reversed(keycodes):
xtest.fake_input(window,
X.KeyRelease,
display.keysym_to_keycode(keycode))
display.sync()
send_key(disp, root, keys)
return True
[docs]def switch_workspace(direction):
"""
switches workspace
:param direction: +1 for next workspace, -1 for previous workspace.
"""
log.debug("switch_workspace")
screen = disp.screen()
root = screen.root
if isinstance(direction, basestring):
direction = int(direction)
def get_property(disp, name):
atom = disp.intern_atom(name)
return disp.screen().root.get_full_property(atom, 0)
def send_event(win, ctype, data, mask=None):
""" Send a ClientMessage event to the root """
data = (data+[0]*(5-len(data)))[:5]
ev = protocol.event.ClientMessage(window=win, client_type=ctype, data=(32,(data)))
if not mask:
mask = (X.SubstructureRedirectMask|X.SubstructureNotifyMask)
root.send_event(ev, event_mask=mask)
disp.sync()
cur_ws = get_property(disp, '_NET_CURRENT_DESKTOP').value[0]
nb_ws = get_property(disp, '_NET_NUMBER_OF_DESKTOPS').value[0]
# switch to previous desktop
if cur_ws + direction < 0:
cur_ws = nb_ws -1
elif cur_ws + direction >= nb_ws:
cur_ws = 0
else:
cur_ws = cur_ws + direction
send_event(root,
display.Display().intern_atom("_NET_CURRENT_DESKTOP"),
[cur_ws, X.CurrentTime])
return True
ACTIONS = dict(
workspace = switch_workspace,
keypress = do_key_press,
mouseclick = do_mouse_click
)
if __name__ == "__main__":
import time
print "grab_mouse_wheel"
grab_mouse_wheel()
time.sleep(1)
print "do_mouse_click"
do_mouse_click(X.Button3)
time.sleep(1)
print "do_key_press"
do_key_press((XK.XK_Alt_L, XK.XK_Tab))
time.sleep(1)
print "ungrab_mouse_wheel"
ungrab_mouse_wheel()
# time.sleep(1)
# print "switch_workspace"
# switch_workspace(+1)