How to Capture Mouseevents and Keyevents Using Python in Background on Linux

How can I capture mouseevents and keyevents using python in background on linux

I guess, you might use python bindings for evdev: http://packages.python.org/evdev/index.html. In tutorial they give an example for keyboard, but it should be similar for mouse events:

>>> from evdev import InputDevice, categorize, ecodes
>>> from select import select
>>> dev = InputDevice('/dev/input/event1')

>>> print(dev)
device /dev/input/event1, name "Dell Dell USB Keyboard", phys "usb-0000:00:12.1-2/input0"

>>> while True:
... r,w,x = select([dev], [], [])
... for event in dev.read():
... if event.type == ecodes.EV_KEY:
... print(categorize(event))
... # hitting a and holding space
key event at 1337016188.396030, 30 (KEY_A), down
key event at 1337016188.492033, 30 (KEY_A), up
key event at 1337016189.772129, 57 (KEY_SPACE), down
key event at 1337016190.275396, 57 (KEY_SPACE), hold
key event at 1337016190.284160, 57 (KEY_SPACE), up

Simulating Key Press event using Python for Linux

If the "model" is running graphically (with the X window system), the already-suggested xsendkey is a possibility, or xsendkeycode. If it's running textually (in a terminal window), then pexpect.

Check if key is pressed using python (a daemon in the background)

This allows me to get the state of modifier keys on my *nix system.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""OSD Neo2
========
On screen display for learning the keyboard layout Neo2
Copyright (c) 2009 Martin Zuther (http://www.mzuther.de/)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Thank you for using free software!
"""
# Here follows a plea in German to keep the comments in English so
# that you may understand them, dear visitor ...
#
# Meine Kommentare in den Quellcodes sind absichtlich auf Englisch
# gehalten, damit Leute, die im Internet nach Lösungen suchen, den
# Code nachvollziehen können. Daher bitte ich darum, zusätzliche
# Kommentare ebenfalls auf Englisch zu schreiben. Vielen Dank!
import ctypes
import ctypes.util
import gettext
import os
import types
# initialise localisation settings
module_path = os.path.dirname(os.path.realpath(__file__))
gettext.bindtextdomain('OSDneo2', os.path.join(module_path, 'po/'))
gettext.textdomain('OSDneo2')
_ = gettext.lgettext
class SimpleXkbWrapper:
"""
Far from complete wrapper for the "X Keyboard Extension" (well, to
be honest, it just wraps what I need using Python's "ctypes"
library <g>).
"""
# set this to true to get lots of debugging information (and
# considerably slow things down)
DEBUG_XKB = False
# "C defines" from file /usr/include/X11/extensions/XKB.h (Ubuntu 9.04):
# $XFree86: xc/include/extensions/XKB.h,v 1.5tsi Exp $
#
# XkbUseCoreKbd is used to specify the core keyboard without having to
# look up its X input extension identifier.
XkbUseCoreKbd = 0x0100
# "C defines" from file /usr/include/X11/XKBlib.h (Ubuntu 9.04):
# $XFree86: xc/lib/X11/XKBlib.h,v 3.5 2003/04/17 02:06:31 dawes Exp $ #
#
# XkbOpenDisplay error codes
XkbOD_Success = 0
XkbOD_BadLibraryVersion = 1
XkbOD_ConnectionRefused = 2
XkbOD_NonXkbServer = 3
XkbOD_BadServerVersion = 4
# "C typedef" from file /usr/include/X11/extensions/XKBstr.h (Ubuntu 9.04):
# $Xorg: XKBstr.h,v 1.3 2000/08/18 04:05:45 coskrey Exp $
#
# Common data structures and access macros
#
# typedef struct _XkbStateRec {
# unsigned char group;
# unsigned char locked_group;
# unsigned short base_group;
# unsigned short latched_group;
# unsigned char mods;
# unsigned char base_mods;
# unsigned char latched_mods;
# unsigned char locked_mods;
# unsigned char compat_state;
# unsigned char grab_mods;
# unsigned char compat_grab_mods;
# unsigned char lookup_mods;
# unsigned char compat_lookup_mods;
# unsigned short ptr_buttons;
# } XkbStateRec,*XkbStatePtr;
class XkbStateRec(ctypes.Structure):
_fields_ = [
('group', ctypes.c_ubyte), \
('locked_group', ctypes.c_ubyte), \
('base_group', ctypes.c_ushort), \
('latched_group', ctypes.c_ushort), \
('mods', ctypes.c_ubyte), \
('base_mods', ctypes.c_ubyte), \
('latched_mods', ctypes.c_ubyte), \
('locked_mods', ctypes.c_ubyte), \
('compat_state', ctypes.c_ubyte), \
('grab_mods', ctypes.c_ubyte), \
('compat_grab_mods', ctypes.c_ubyte), \
('lookup_mods', ctypes.c_ubyte), \
('compat_lookup_mods', ctypes.c_ubyte), \
('ptr_buttons', ctypes.c_ushort) \
]
# "C defines" from file /usr/include/X11/X.h (Ubuntu 9.04):
# $XFree86: xc/include/X.h,v 1.6 2003/07/09 15:27:28 tsi Exp $
#
# Key masks. Used as modifiers to GrabButton and GrabKey, results of
# QueryPointer, state in various key-, mouse-, and button-related
# events.
ShiftMask = 1
LockMask = 2
ControlMask = 4
Mod1Mask = 8
Mod2Mask = 16
Mod3Mask = 32
Mod4Mask = 64
Mod5Mask = 128
def __init__(self):
# dynamically link to "X Keyboard Extension" library
library_xf86misc = ctypes.CDLL(ctypes.util.find_library('Xxf86misc'))
# print debugging information if requested
if self.DEBUG_XKB:
print
print ' %s' % library_xf86misc
# define "ctypes" prototype for the function
#
# Display *XkbOpenDisplay(display_name, event_rtrn, error_rtrn,
# major_in_out, minor_in_out, reason_rtrn)
#
# char * display_name;
# int * event_rtrn;
# int * error_rtrn;
# int * major_in_out;
# int * minor_in_out;
# int * reason_rtrn;
paramflags_xkbopendisplay = \
(1, 'display_name'), \
(2, 'event_rtrn'), \
(2, 'error_rtrn'), \
(3, 'major_in_out'), \
(3, 'minor_in_out'), \
(2, 'reason_rtrn')
prototype_xkbopendisplay = ctypes.CFUNCTYPE( \
ctypes.c_uint, \
ctypes.c_char_p, \
ctypes.POINTER(ctypes.c_int), \
ctypes.POINTER(ctypes.c_int), \
ctypes.POINTER(ctypes.c_int), \
ctypes.POINTER(ctypes.c_int), \
ctypes.POINTER(ctypes.c_int) \
)
# set-up function (low-level)
self.__XkbOpenDisplay__ = prototype_xkbopendisplay( \
('XkbOpenDisplay', library_xf86misc), \
paramflags_xkbopendisplay \
)
# define error handler
def errcheck_xkbopendisplay(result, func, args):
# print debugging information if requested
if self.DEBUG_XKB:
print
print ' [XkbOpenDisplay]'
print ' Display: %#010x' % result
print ' display_name: %s' % args[0].value
print ' event_rtrn: %d' % args[1].value
print ' error_rtrn: %d' % args[2].value
print ' major_in_out: %d' % args[3].value
print ' minor_in_out: %d' % args[4].value
print ' reason_rt: %d' % args[5].value
# function didn't return display handle, so let's see why
# not
if result == 0:
# values were taken from file /usr/include/X11/XKBlib.h (Ubuntu 9.04):
# $XFree86: xc/lib/X11/XKBlib.h,v 3.5 2003/04/17 02:06:31 dawes Exp $ #
error_id = args[5].value
if error_id == self.XkbOD_Success:
error_name = 'XkbOD_Success'
elif error_id == self.XkbOD_BadLibraryVersion:
error_name = 'XkbOD_BadLibraryVersion'
elif error_id == self.XkbOD_ConnectionRefused:
error_name = 'XkbOD_ConnectionRefused'
elif error_id == self.XkbOD_NonXkbServer:
error_name = 'XkbOD_NonXkbServer'
elif error_id == self.XkbOD_BadServerVersion:
error_name = 'XkbOD_BadServerVersion'
else:
error_name = _('undefined')
error_message = \
_('"XkbOpenDisplay" reported an error (%(error_name)s).') % \
{'error_name': error_name}
raise OSError(error_message)
# return display handle and all function arguments
return (ctypes.c_uint(result), args)
# connect error handler to function
self.__XkbOpenDisplay__.errcheck = errcheck_xkbopendisplay
# define "ctypes" prototype for the function
#
# Bool XkbGetState(display, device_spec, state_return)
#
# Display * display;
# unsigned int device_spec;
# XkbStatePtr state_return;
paramflags_xkbgetstate = \
(1, 'display'), \
(1, 'device_spec'), \
(3, 'state_return')
prototype_xkbgetstate = ctypes.CFUNCTYPE( \
ctypes.c_int, # Python 2.5 doesn't yet know c_bool \
ctypes.c_uint, \
ctypes.c_uint, \
ctypes.POINTER(self.XkbStateRec) \
)
# set-up function (low-level)
self.__XkbGetState__ = prototype_xkbgetstate( \
('XkbGetState', library_xf86misc), \
paramflags_xkbgetstate \
)
# define error handler
def errcheck_xkbgetstate(result, func, args):
# print debugging information if requested
if self.DEBUG_XKB:
print
print ' [XkbGetState]'
print ' Status: %s' % result
print ' display: %#010x' % args[0].value
print ' device_spec: %d\n' % args[1].value
print ' state_return.group: %d' % \
args[2].group
print ' state_return.locked_group: %d' % \
args[2].locked_group
print ' state_return.base_group: %d' % \
args[2].base_group
print ' state_return.latched_group: %d' % \
args[2].latched_group
print ' state_return.mods: %d' % \
args[2].mods
print ' state_return.base_mods: %d' % \
args[2].base_mods
print ' state_return.latched_mods: %d' % \
args[2].latched_mods
print ' state_return.locked_mods: %d' % \
args[2].locked_mods
print ' state_return.compat_state: %d' % \
args[2].compat_state
print ' state_return.grab_mods: %d' % \
args[2].grab_mods
print ' state_return.compat_grab_mods: %d' % \
args[2].compat_grab_mods
print ' state_return.lookup_mods: %d' % \
args[2].lookup_mods
print ' state_return.compat_lookup_mods: %d' % \
args[2].compat_lookup_mods
print ' state_return.ptr_buttons: %d\n' % \
args[2].ptr_buttons
print ' Mask mods base_mods latched_mods locked_mods compat_state'
print ' --------------------------------------------------------------------------'
print ' ShiftMask %-5s %-5s %-5s %-5s %-5s' % \
((args[2].mods & self.ShiftMask) != 0, \
(args[2].base_mods & self.ShiftMask) != 0, \
(args[2].latched_mods & self.ShiftMask) != 0, \
(args[2].locked_mods & self.ShiftMask) != 0, \
(args[2].compat_state & self.ShiftMask) != 0)
print ' LockMask %-5s %-5s %-5s %-5s %-5s' % \
((args[2].mods & self.LockMask) != 0, \
(args[2].base_mods & self.LockMask) != 0, \
(args[2].latched_mods & self.LockMask) != 0, \
(args[2].locked_mods & self.LockMask) != 0, \
(args[2].compat_state & self.LockMask) != 0)
print ' ControlMask %-5s %-5s %-5s %-5s %-5s' % \
((args[2].mods & self.ControlMask) != 0, \
(args[2].base_mods & self.ControlMask) != 0, \
(args[2].latched_mods & self.ControlMask) != 0, \
(args[2].locked_mods & self.ControlMask) != 0, \
(args[2].compat_state & self.ControlMask) != 0)
print ' Mod1Mask %-5s %-5s %-5s %-5s %-5s' % \
((args[2].mods & self.Mod1Mask) != 0, \
(args[2].base_mods & self.Mod1Mask) != 0, \
(args[2].latched_mods & self.Mod1Mask) != 0, \
(args[2].locked_mods & self.Mod1Mask) != 0, \
(args[2].compat_state & self.Mod1Mask) != 0)
print ' Mod2Mask %-5s %-5s %-5s %-5s %-5s' % \
((args[2].mods & self.Mod2Mask) != 0, \
(args[2].base_mods & self.Mod2Mask) != 0, \
(args[2].latched_mods & self.Mod2Mask) != 0, \
(args[2].locked_mods & self.Mod2Mask) != 0, \
(args[2].compat_state & self.Mod2Mask) != 0)
print ' Mod3Mask %-5s %-5s %-5s %-5s %-5s' % \
((args[2].mods & self.Mod3Mask) != 0, \
(args[2].base_mods & self.Mod3Mask) != 0, \
(args[2].latched_mods & self.Mod3Mask) != 0, \
(args[2].locked_mods & self.Mod3Mask) != 0, \
(args[2].compat_state & self.Mod3Mask) != 0)
print ' Mod4Mask %-5s %-5s %-5s %-5s %-5s' % \
((args[2].mods & self.Mod4Mask) != 0, \
(args[2].base_mods & self.Mod4Mask) != 0, \
(args[2].latched_mods & self.Mod4Mask) != 0, \
(args[2].locked_mods & self.Mod4Mask) != 0, \
(args[2].compat_state & self.Mod4Mask) != 0)
print ' Mod5Mask %-5s %-5s %-5s %-5s %-5s' % \
((args[2].mods & self.Mod5Mask) != 0, \
(args[2].base_mods & self.Mod5Mask) != 0, \
(args[2].latched_mods & self.Mod5Mask) != 0, \
(args[2].locked_mods & self.Mod5Mask) != 0, \
(args[2].compat_state & self.Mod5Mask) != 0)
# return function return value and all function arguments
return (result, args)
# connect error handler to function
self.__XkbGetState__.errcheck = errcheck_xkbgetstate
# define high-level version of "XkbOpenDisplay"
def XkbOpenDisplay(self, display_name, major_in_out, minor_in_out):
# if we don't do type checking, nobody ever will
assert (type(display_name) == types.NoneType) or \
(type(display_name) == types.StringType)
assert type(major_in_out) == types.IntType
assert type(minor_in_out) == types.IntType
# convert function arguments to "ctypes", ...
__display_name__ = ctypes.c_char_p(display_name)
__major_in_out__ = ctypes.c_int(major_in_out)
__minor_in_out__ = ctypes.c_int(minor_in_out)
# ... call low-level function ...
ret = self.__XkbOpenDisplay__(__display_name__, __major_in_out__, \
__minor_in_out__)
# ... and return converted return value and function arguments
return {'display_handle': ret[0].value, \
'server_major_version': ret[1][3].value, \
'server_minor_version': ret[1][4].value}
# define high-level version of "XkbGetState"
def XkbGetState(self, display_handle, device_spec):
# if we don't do type checking, nobody ever will
assert type(display_handle) == types.LongType
assert type(device_spec) == types.IntType
# convert function arguments to "ctypes", ...
__display_handle__ = ctypes.c_uint(display_handle)
__device_spec__ = ctypes.c_uint(device_spec)
__xkbstaterec__ = self.XkbStateRec()
# ... call low-level function ...
ret = self.__XkbGetState__(__display_handle__, __device_spec__, \
__xkbstaterec__)
# ... and return converted function argument
xkbstaterec = ret[1][2]
return xkbstaterec
# extract modifier status using bitmasks
def ExtractLocks(self, xkbstaterec):
return {'group': xkbstaterec.group, \
'shift': \
(xkbstaterec.base_mods & self.ShiftMask) != 0, \
'shift_lock': \
(xkbstaterec.locked_mods & self.ShiftMask) != 0, \
'lock': \
(xkbstaterec.base_mods & self.LockMask) != 0, \
'lock_lock': \
(xkbstaterec.locked_mods & self.LockMask) != 0, \
'control': \
(xkbstaterec.base_mods & self.ControlMask) != 0, \
'control_lock': \
(xkbstaterec.locked_mods & self.ControlMask) != 0, \
'mod1': \
(xkbstaterec.base_mods & self.Mod1Mask) != 0, \
'mod1_lock': \
(xkbstaterec.locked_mods & self.Mod1Mask) != 0, \
'mod2': \
(xkbstaterec.base_mods & self.Mod2Mask) != 0, \
'mod2_lock': \
(xkbstaterec.locked_mods & self.Mod2Mask) != 0, \
'mod3': \
(xkbstaterec.base_mods & self.Mod3Mask) != 0, \
'mod3_lock': \
(xkbstaterec.locked_mods & self.Mod3Mask) != 0, \
'mod4': \
(xkbstaterec.base_mods & self.Mod4Mask) != 0, \
'mod4_lock': \
(xkbstaterec.locked_mods & self.Mod4Mask) != 0, \
'mod5': \
(xkbstaterec.base_mods & self.Mod5Mask) != 0, \
'mod5_lock': \
(xkbstaterec.locked_mods & self.Mod5Mask) != 0}

To call state to a dictionary,from another file, just call from FILENAME import * and do the following:

# simple demonstration of this wrapper
xkb = SimpleXkbWrapper()
# initialise wrapper for the X Keyboard Extension (v1.0) and
# open connection to default X display
display_name = None
major_in_out = 1
minor_in_out = 0
try:
ret = xkb.XkbOpenDisplay(display_name, major_in_out, minor_in_out)
except OSError, error:
print
print ' Error: %s' % error
print
exit(1)
# ... get modifier state of core keyboard ...
display_handle = ret['display_handle']
device_spec = xkb.XkbUseCoreKbd
xkbstaterec = xkb.XkbGetState(display_handle, device_spec)
# ... and extract and the information we need
print xkb.ExtractLocks(xkbstaterec)

Cheers to the creator whose code can be found here, and to Jason Orendorffl for drawing my attention to it.

How can i capture a mouse clicks onto the main Window in a child class

There is terminology that the OP uses that is confusing, for example FooView is a child class of BaseView but that has nothing to do with Qt so it is irrelevant for this case so I will omit that class and show the example of how another class can obtain information about the click event of a widget.

The logic is to create a class that inherits from QObject and apply an event filter to the other widget, then override the eventFilter method where the events of the widget are obtained.

import sys
from PyQt5 import QtWidgets, QtGui, QtCore

class MouseObserver(QtCore.QObject):
def __init__(self, widget):
super(MouseObserver, self).__init__(widget)
self._widget = widget
self.widget.installEventFilter(self)

@property
def widget(self):
return self._widget

def eventFilter(self, obj, event):
if obj is self.widget:
if event.type() == QtCore.QEvent.MouseButtonPress:
print(event.pos(), QtGui.QCursor.pos())
elif event.type() == QtCore.QEvent.MouseButtonRelease:
print(event.pos(), QtGui.QCursor.pos())
return super(MouseObserver, self).eventFilter(obj, event)

class Example(QtWidgets.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()

def initUI(self):
self.observer = MouseObserver(self)

qbtn = QtWidgets.QPushButton("Quit", self)
qbtn.resize(qbtn.sizeHint())
qbtn.move(50, 50)

self.setGeometry(0, 0, 1024, 768)
self.setWindowTitle("Quit button")
self.setWindowFlags(self.windowFlags() | QtCore.Qt.FramelessWindowHint)
self.show()

def main():
app = QtWidgets.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

if __name__ == "__main__":
main()

wxPython, key events not showing up on MacOS and Linux

I just ran this on OSX 11.4. Works fine with mouse and key events. The imporant part on OSX (and I suspect Linux as it is more similar to OSX than Windows) is that the parent panel is getting the focus and the events. Also, StaticText can't get focus.

Here's the working code:

import wx

class Main(wx.Frame):

def __init__(self, parent):
wx.Frame.__init__(self, parent, style=wx.WANTS_CHARS|wx.DEFAULT_FRAME_STYLE)

panel = wx.Panel(self, wx.ID_ANY)
panel.Bind(wx.EVT_KEY_DOWN, self.on_mouse_key_event)
panel.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_key_event)

def on_mouse_key_event(self, event):
print(f'{event}')

# Run the program
if __name__ == '__main__':
app = wx.App()
main = Main(None)
main.Show()
app.MainLoop()

how to detect a key press when a mouse click happened in tkinter canvas

Instead of detecting whether the shift key is pressed or not, you can bind to the <Shift-Button-1> event so that the callback is only called if the user shift-clicks on the object.

Here is an example that will display the color of an item when you shift-click on it.

import tkinter as tk

def handle_click(event):
color = event.widget.itemcget("current", "fill")
label.configure(text=f"item color: {color}")

root = tk.Tk()

canvas = tk.Canvas(root, background="bisque")
label = tk.Label(root)

label.pack(side="bottom", fill="x")
canvas.pack(fill="both", expand=True)

canvas.create_rectangle(10, 10, 110, 110, fill="red", tags=("rectangle",))
canvas.create_rectangle(150, 10, 200, 110, fill="green", tags=("rectangle",))

canvas.tag_bind("rectangle", "<Shift-Button-1>", handle_click)

root.mainloop()

screenshot of window with red and green canvas items

If you want to handle multiple combinations of modifier keys (alt, shift, control, meta, etc) you can bind to <1> and examine the state attribute of the event object. However, there are platform dependencies that make that problematic. I personally find making individual bindings easier and more straight-forward.

For more on how to use the event.state attribute, see check if modifier key is pressed in tkinter



Related Topics



Leave a reply



Submit