778 lines
21 KiB
Python
778 lines
21 KiB
Python
# Xlib.ext.xinput -- XInput extension module
|
|
#
|
|
# Copyright (C) 2012 Outpost Embedded, LLC
|
|
# Forest Bond <forest.bond@rapidrollout.com>
|
|
#
|
|
# This library is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU Lesser General Public License
|
|
# as published by the Free Software Foundation; either version 2.1
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# This library 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 Lesser General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
# License along with this library; if not, write to the
|
|
# Free Software Foundation, Inc.,
|
|
# 59 Temple Place,
|
|
# Suite 330,
|
|
# Boston, MA 02111-1307 USA
|
|
|
|
'''
|
|
A very incomplete implementation of the XInput extension.
|
|
'''
|
|
|
|
import sys
|
|
import array
|
|
import struct
|
|
|
|
# Python 2/3 compatibility.
|
|
from six import integer_types
|
|
|
|
from Xlib.protocol import rq
|
|
from Xlib import X
|
|
|
|
|
|
extname = 'XInputExtension'
|
|
|
|
PropertyDeleted = 0
|
|
PropertyCreated = 1
|
|
PropertyModified = 2
|
|
|
|
NotifyNormal = 0
|
|
NotifyGrab = 1
|
|
NotifyUngrab = 2
|
|
NotifyWhileGrabbed = 3
|
|
NotifyPassiveGrab = 4
|
|
NotifyPassiveUngrab = 5
|
|
|
|
NotifyAncestor = 0
|
|
NotifyVirtual = 1
|
|
NotifyInferior = 2
|
|
NotifyNonlinear = 3
|
|
NotifyNonlinearVirtual = 4
|
|
NotifyPointer = 5
|
|
NotifyPointerRoot = 6
|
|
NotifyDetailNone = 7
|
|
|
|
GrabtypeButton = 0
|
|
GrabtypeKeycode = 1
|
|
GrabtypeEnter = 2
|
|
GrabtypeFocusIn = 3
|
|
GrabtypeTouchBegin = 4
|
|
|
|
AnyModifier = (1 << 31)
|
|
AnyButton = 0
|
|
AnyKeycode = 0
|
|
|
|
AsyncDevice = 0
|
|
SyncDevice = 1
|
|
ReplayDevice = 2
|
|
AsyncPairedDevice = 3
|
|
AsyncPair = 4
|
|
SyncPair = 5
|
|
|
|
SlaveSwitch = 1
|
|
DeviceChange = 2
|
|
|
|
MasterAdded = (1 << 0)
|
|
MasterRemoved = (1 << 1)
|
|
SlaveAdded = (1 << 2)
|
|
SlaveRemoved = (1 << 3)
|
|
SlaveAttached = (1 << 4)
|
|
SlaveDetached = (1 << 5)
|
|
DeviceEnabled = (1 << 6)
|
|
DeviceDisabled = (1 << 7)
|
|
|
|
AddMaster = 1
|
|
RemoveMaster = 2
|
|
AttachSlave = 3
|
|
DetachSlave = 4
|
|
|
|
AttachToMaster = 1
|
|
Floating = 2
|
|
|
|
ModeRelative = 0
|
|
ModeAbsolute = 1
|
|
|
|
MasterPointer = 1
|
|
MasterKeyboard = 2
|
|
SlavePointer = 3
|
|
SlaveKeyboard = 4
|
|
FloatingSlave = 5
|
|
|
|
KeyClass = 0
|
|
ButtonClass = 1
|
|
ValuatorClass = 2
|
|
ScrollClass = 3
|
|
TouchClass = 8
|
|
|
|
KeyRepeat = (1 << 16)
|
|
|
|
AllDevices = 0
|
|
AllMasterDevices = 1
|
|
|
|
DeviceChanged = 1
|
|
KeyPress = 2
|
|
KeyRelease = 3
|
|
ButtonPress = 4
|
|
ButtonRelease = 5
|
|
Motion = 6
|
|
Enter = 7
|
|
Leave = 8
|
|
FocusIn = 9
|
|
FocusOut = 10
|
|
HierarchyChanged = 11
|
|
PropertyEvent = 12
|
|
RawKeyPress = 13
|
|
RawKeyRelease = 14
|
|
RawButtonPress = 15
|
|
RawButtonRelease = 16
|
|
RawMotion = 17
|
|
|
|
DeviceChangedMask = (1 << DeviceChanged)
|
|
KeyPressMask = (1 << KeyPress)
|
|
KeyReleaseMask = (1 << KeyRelease)
|
|
ButtonPressMask = (1 << ButtonPress)
|
|
ButtonReleaseMask = (1 << ButtonRelease)
|
|
MotionMask = (1 << Motion)
|
|
EnterMask = (1 << Enter)
|
|
LeaveMask = (1 << Leave)
|
|
FocusInMask = (1 << FocusIn)
|
|
FocusOutMask = (1 << FocusOut)
|
|
HierarchyChangedMask = (1 << HierarchyChanged)
|
|
PropertyEventMask = (1 << PropertyEvent)
|
|
RawKeyPressMask = (1 << RawKeyPress)
|
|
RawKeyReleaseMask = (1 << RawKeyRelease)
|
|
RawButtonPressMask = (1 << RawButtonPress)
|
|
RawButtonReleaseMask = (1 << RawButtonRelease)
|
|
RawMotionMask = (1 << RawMotion)
|
|
|
|
GrabModeSync = 0
|
|
GrabModeAsync = 1
|
|
GrabModeTouch = 2
|
|
|
|
DEVICEID = rq.Card16
|
|
DEVICE = rq.Card16
|
|
DEVICEUSE = rq.Card8
|
|
|
|
PROPERTY_TYPE_FLOAT = 'FLOAT'
|
|
|
|
class FP1616(rq.Int32):
|
|
|
|
def check_value(self, value):
|
|
return int(value * 65536.0)
|
|
|
|
def parse_value(self, value, display):
|
|
return float(value) / float(1 << 16)
|
|
|
|
class FP3232(rq.ValueField):
|
|
structcode = 'lL'
|
|
structvalues = 2
|
|
|
|
def check_value(self, value):
|
|
return value
|
|
|
|
def parse_value(self, value, display):
|
|
integral, frac = value
|
|
ret = float(integral)
|
|
# optimised math.ldexp(float(frac), -32)
|
|
ret += float(frac) * (1.0 / (1 << 32))
|
|
return ret
|
|
|
|
class XIQueryVersion(rq.ReplyRequest):
|
|
_request = rq.Struct(
|
|
rq.Card8('opcode'),
|
|
rq.Opcode(47),
|
|
rq.RequestLength(),
|
|
rq.Card16('major_version'),
|
|
rq.Card16('minor_version'),
|
|
)
|
|
_reply = rq.Struct(
|
|
rq.ReplyCode(),
|
|
rq.Pad(1),
|
|
rq.Card16('sequence_number'),
|
|
rq.ReplyLength(),
|
|
rq.Card16('major_version'),
|
|
rq.Card16('minor_version'),
|
|
rq.Pad(20),
|
|
)
|
|
|
|
|
|
def query_version(self):
|
|
return XIQueryVersion(
|
|
display=self.display,
|
|
opcode=self.display.get_extension_major(extname),
|
|
major_version=2,
|
|
minor_version=0,
|
|
)
|
|
|
|
class Mask(rq.List):
|
|
|
|
def __init__(self, name):
|
|
rq.List.__init__(self, name, rq.Card32, pad=0)
|
|
|
|
def pack_value(self, val):
|
|
|
|
mask_seq = array.array(rq.struct_to_array_codes['L'])
|
|
|
|
if isinstance(val, integer_types):
|
|
# We need to build a "binary mask" that (as far as I can tell) is
|
|
# encoded in native byte order from end to end. The simple case is
|
|
# with a single unsigned 32-bit value, for which we construct an
|
|
# array with just one item. For values too big to fit inside 4
|
|
# bytes we build a longer array, being careful to maintain native
|
|
# byte order across the entire set of values.
|
|
if sys.byteorder == 'little':
|
|
def fun(val):
|
|
mask_seq.insert(0, val)
|
|
elif sys.byteorder == 'big':
|
|
fun = mask_seq.append
|
|
else:
|
|
raise AssertionError(sys.byteorder)
|
|
while val:
|
|
fun(val & 0xFFFFFFFF)
|
|
val = val >> 32
|
|
else:
|
|
mask_seq.extend(val)
|
|
|
|
return rq.encode_array(mask_seq), len(mask_seq), None
|
|
|
|
EventMask = rq.Struct(
|
|
DEVICE('deviceid'),
|
|
rq.LengthOf('mask', 2),
|
|
Mask('mask'),
|
|
)
|
|
|
|
|
|
class XISelectEvents(rq.Request):
|
|
_request = rq.Struct(
|
|
rq.Card8('opcode'),
|
|
rq.Opcode(46),
|
|
rq.RequestLength(),
|
|
rq.Window('window'),
|
|
rq.LengthOf('masks', 2),
|
|
rq.Pad(2),
|
|
rq.List('masks', EventMask),
|
|
)
|
|
|
|
def select_events(self, event_masks):
|
|
'''
|
|
select_events(event_masks)
|
|
|
|
event_masks:
|
|
Sequence of (deviceid, mask) pairs, where deviceid is a numerical device
|
|
ID, or AllDevices or AllMasterDevices, and mask is either an unsigned
|
|
integer or sequence of 32 bits unsigned values
|
|
'''
|
|
return XISelectEvents(
|
|
display=self.display,
|
|
opcode=self.display.get_extension_major(extname),
|
|
window=self,
|
|
masks=event_masks,
|
|
)
|
|
|
|
AnyInfo = rq.Struct(
|
|
rq.Card16('type'),
|
|
rq.Card16('length'),
|
|
rq.Card16('sourceid'),
|
|
rq.Pad(2),
|
|
)
|
|
|
|
class ButtonMask(object):
|
|
|
|
def __init__(self, value, length):
|
|
self._value = value
|
|
self._length = length
|
|
|
|
def __len__(self):
|
|
return self._length
|
|
|
|
def __getitem__(self, key):
|
|
return self._value & (1 << key)
|
|
|
|
def __str__(self):
|
|
return repr(self)
|
|
|
|
def __repr__(self):
|
|
return '0b{value:0{width}b}'.format(value=self._value,
|
|
width=self._length)
|
|
|
|
class ButtonState(rq.ValueField):
|
|
|
|
structcode = None
|
|
|
|
def __init__(self, name):
|
|
rq.ValueField.__init__(self, name)
|
|
|
|
def parse_binary_value(self, data, display, length, fmt):
|
|
# Mask: bitfield of <length> button states.
|
|
mask_len = 4 * ((((length + 7) >> 3) + 3) >> 2)
|
|
mask_data = data[:mask_len]
|
|
mask_value = 0
|
|
for byte in reversed(struct.unpack('={0:d}B'.format(mask_len), mask_data)):
|
|
mask_value <<= 8
|
|
mask_value |= byte
|
|
data = data[mask_len:]
|
|
assert (mask_value & 1) == 0
|
|
return ButtonMask(mask_value >> 1, length), data
|
|
|
|
ButtonInfo = rq.Struct(
|
|
rq.Card16('type'),
|
|
rq.Card16('length'),
|
|
rq.Card16('sourceid'),
|
|
rq.LengthOf(('state', 'labels'), 2),
|
|
ButtonState('state'),
|
|
rq.List('labels', rq.Card32),
|
|
)
|
|
|
|
KeyInfo = rq.Struct(
|
|
rq.Card16('type'),
|
|
rq.Card16('length'),
|
|
rq.Card16('sourceid'),
|
|
rq.LengthOf('keycodes', 2),
|
|
rq.List('keycodes', rq.Card32),
|
|
)
|
|
|
|
ValuatorInfo = rq.Struct(
|
|
rq.Card16('type'),
|
|
rq.Card16('length'),
|
|
rq.Card16('sourceid'),
|
|
rq.Card16('number'),
|
|
rq.Card32('label'),
|
|
FP3232('min'),
|
|
FP3232('max'),
|
|
FP3232('value'),
|
|
rq.Card32('resolution'),
|
|
rq.Card8('mode'),
|
|
rq.Pad(3),
|
|
)
|
|
|
|
ScrollInfo = rq.Struct(
|
|
rq.Card16('type'),
|
|
rq.Card16('length'),
|
|
rq.Card16('sourceid'),
|
|
rq.Card16('number'),
|
|
rq.Card16('scroll_type'),
|
|
rq.Pad(2),
|
|
rq.Card32('flags'),
|
|
FP3232('increment'),
|
|
)
|
|
|
|
TouchInfo = rq.Struct(
|
|
rq.Card16('type'),
|
|
rq.Card16('length'),
|
|
rq.Card16('sourceid'),
|
|
rq.Card8('mode'),
|
|
rq.Card8('num_touches'),
|
|
)
|
|
|
|
INFO_CLASSES = {
|
|
KeyClass: KeyInfo,
|
|
ButtonClass: ButtonInfo,
|
|
ValuatorClass: ValuatorInfo,
|
|
ScrollClass: ScrollInfo,
|
|
TouchClass: TouchInfo,
|
|
}
|
|
|
|
class ClassInfoClass(object):
|
|
|
|
structcode = None
|
|
|
|
def parse_binary(self, data, display):
|
|
class_type, length = struct.unpack('=HH', data[:4])
|
|
class_struct = INFO_CLASSES.get(class_type, AnyInfo)
|
|
class_data, _ = class_struct.parse_binary(data, display)
|
|
data = data[length * 4:]
|
|
return class_data, data
|
|
|
|
ClassInfo = ClassInfoClass()
|
|
|
|
DeviceInfo = rq.Struct(
|
|
DEVICEID('deviceid'),
|
|
rq.Card16('use'),
|
|
rq.Card16('attachment'),
|
|
rq.LengthOf('classes', 2),
|
|
rq.LengthOf('name', 2),
|
|
rq.Bool('enabled'),
|
|
rq.Pad(1),
|
|
rq.String8('name', 4),
|
|
rq.List('classes', ClassInfo),
|
|
)
|
|
|
|
class XIQueryDevice(rq.ReplyRequest):
|
|
_request = rq.Struct(
|
|
rq.Card8('opcode'),
|
|
rq.Opcode(48),
|
|
rq.RequestLength(),
|
|
DEVICEID('deviceid'),
|
|
rq.Pad(2),
|
|
)
|
|
|
|
_reply = rq.Struct(
|
|
rq.ReplyCode(),
|
|
rq.Pad(1),
|
|
rq.Card16('sequence_number'),
|
|
rq.ReplyLength(),
|
|
rq.LengthOf('devices', 2),
|
|
rq.Pad(22),
|
|
rq.List('devices', DeviceInfo),
|
|
)
|
|
|
|
def query_device(self, deviceid):
|
|
return XIQueryDevice(
|
|
display=self.display,
|
|
opcode=self.display.get_extension_major(extname),
|
|
deviceid=deviceid,
|
|
)
|
|
|
|
class XIListProperties(rq.ReplyRequest):
|
|
_request = rq.Struct(
|
|
rq.Card8('opcode'),
|
|
rq.Opcode(56),
|
|
rq.RequestLength(),
|
|
DEVICEID('deviceid'),
|
|
rq.Pad(2),
|
|
)
|
|
|
|
_reply = rq.Struct(
|
|
rq.ReplyCode(),
|
|
rq.Pad(1),
|
|
rq.Card16('sequence_number'),
|
|
rq.ReplyLength(),
|
|
rq.LengthOf('atoms', 2),
|
|
rq.Pad(22),
|
|
rq.List('atoms', rq.Card32Obj),
|
|
)
|
|
|
|
def list_device_properties(self, deviceid):
|
|
return XIListProperties(
|
|
display=self.display,
|
|
opcode=self.display.get_extension_major(extname),
|
|
deviceid=deviceid,
|
|
)
|
|
|
|
class XIGetProperty(rq.ReplyRequest):
|
|
_request = rq.Struct(
|
|
rq.Card8('opcode'),
|
|
rq.Opcode(59),
|
|
rq.RequestLength(),
|
|
DEVICEID('deviceid'),
|
|
rq.Card8('delete'),
|
|
rq.Pad(1),
|
|
rq.Card32('property'),
|
|
rq.Card32('type'),
|
|
rq.Card32('offset'),
|
|
rq.Card32('length'),
|
|
)
|
|
|
|
_reply = rq.Struct(
|
|
rq.ReplyCode(),
|
|
rq.Pad(1),
|
|
rq.Card16('sequence_number'),
|
|
rq.ReplyLength(),
|
|
rq.Card32('type'),
|
|
rq.Card32('bytes_after'),
|
|
rq.LengthOf('value', 4),
|
|
rq.Format('value', 1),
|
|
rq.Pad(11),
|
|
rq.PropertyData('value')
|
|
)
|
|
|
|
def get_device_property(self, deviceid, property, type, offset, length, delete=False):
|
|
return XIGetProperty(
|
|
display=self.display,
|
|
opcode=self.display.get_extension_major(extname),
|
|
deviceid=deviceid,
|
|
property=property,
|
|
type=type,
|
|
offset=offset,
|
|
length=length,
|
|
delete=delete,
|
|
)
|
|
|
|
class XIChangeProperty(rq.Request):
|
|
_request = rq.Struct(
|
|
rq.Card8('opcode'),
|
|
rq.Opcode(57),
|
|
rq.RequestLength(),
|
|
DEVICEID('deviceid'),
|
|
rq.Card8('mode'),
|
|
rq.Format('value', 1),
|
|
rq.Card32('property'),
|
|
rq.Card32('type'),
|
|
rq.LengthOf('value', 4),
|
|
rq.PropertyData('value'),
|
|
)
|
|
|
|
def change_device_property(self, deviceid, property, type, mode, value):
|
|
return XIChangeProperty(
|
|
display=self.display,
|
|
opcode=self.display.get_extension_major(extname),
|
|
deviceid=deviceid,
|
|
property=property,
|
|
type=type,
|
|
mode=mode,
|
|
value=value,
|
|
)
|
|
|
|
class XIDeleteProperty(rq.Request):
|
|
_request = rq.Struct(
|
|
rq.Card8('opcode'),
|
|
rq.Opcode(58),
|
|
rq.RequestLength(),
|
|
DEVICEID('deviceid'),
|
|
rq.Pad(2),
|
|
rq.Card32('property'),
|
|
)
|
|
|
|
def delete_device_property(self, deviceid, property):
|
|
return XIDeleteProperty(
|
|
display=self.display,
|
|
opcode=self.display.get_extension_major(extname),
|
|
deviceid=deviceid,
|
|
property=property,
|
|
)
|
|
|
|
class XIGrabDevice(rq.ReplyRequest):
|
|
_request = rq.Struct(
|
|
rq.Card8('opcode'),
|
|
rq.Opcode(51),
|
|
rq.RequestLength(),
|
|
rq.Window('grab_window'),
|
|
rq.Card32('time'),
|
|
rq.Cursor('cursor', (X.NONE, )),
|
|
DEVICEID('deviceid'),
|
|
rq.Set('grab_mode', 1, (GrabModeSync, GrabModeAsync)),
|
|
rq.Set('paired_device_mode', 1, (GrabModeSync, GrabModeAsync)),
|
|
rq.Bool('owner_events'),
|
|
rq.Pad(1),
|
|
rq.LengthOf('mask', 2),
|
|
Mask('mask'),
|
|
)
|
|
|
|
_reply = rq.Struct(
|
|
rq.ReplyCode(),
|
|
rq.Pad(1),
|
|
rq.Card16('sequence_number'),
|
|
rq.ReplyLength(),
|
|
rq.Card8('status'),
|
|
rq.Pad(23),
|
|
)
|
|
|
|
def grab_device(self, deviceid, time, grab_mode, paired_device_mode, owner_events, event_mask):
|
|
return XIGrabDevice(
|
|
display=self.display,
|
|
opcode=self.display.get_extension_major(extname),
|
|
deviceid=deviceid,
|
|
grab_window=self,
|
|
time=time,
|
|
cursor=X.NONE,
|
|
grab_mode=grab_mode,
|
|
paired_device_mode=paired_device_mode,
|
|
owner_events=owner_events,
|
|
mask=event_mask,
|
|
)
|
|
|
|
class XIUngrabDevice(rq.Request):
|
|
_request = rq.Struct(
|
|
rq.Card8('opcode'),
|
|
rq.Opcode(52),
|
|
rq.RequestLength(),
|
|
rq.Card32('time'),
|
|
DEVICEID('deviceid'),
|
|
rq.Pad(2),
|
|
)
|
|
|
|
def ungrab_device(self, deviceid, time):
|
|
return XIUngrabDevice(
|
|
display=self.display,
|
|
opcode=self.display.get_extension_major(extname),
|
|
time=time,
|
|
deviceid=deviceid,
|
|
)
|
|
|
|
class XIPassiveGrabDevice(rq.ReplyRequest):
|
|
_request = rq.Struct(
|
|
rq.Card8('opcode'),
|
|
rq.Opcode(54),
|
|
rq.RequestLength(),
|
|
rq.Card32('time'),
|
|
rq.Window('grab_window'),
|
|
rq.Cursor('cursor', (X.NONE, )),
|
|
rq.Card32('detail'),
|
|
DEVICEID('deviceid'),
|
|
rq.LengthOf('modifiers', 2),
|
|
rq.LengthOf('mask', 2),
|
|
rq.Set('grab_type', 1, (GrabtypeButton, GrabtypeKeycode, GrabtypeEnter,
|
|
GrabtypeFocusIn, GrabtypeTouchBegin)),
|
|
rq.Set('grab_mode', 1, (GrabModeSync, GrabModeAsync)),
|
|
rq.Set('paired_device_mode', 1, (GrabModeSync, GrabModeAsync)),
|
|
rq.Bool('owner_events'),
|
|
rq.Pad(2),
|
|
Mask('mask'),
|
|
rq.List('modifiers', rq.Card32),
|
|
)
|
|
|
|
_reply = rq.Struct(
|
|
rq.ReplyCode(),
|
|
rq.Pad(1),
|
|
rq.Card16('sequence_number'),
|
|
rq.ReplyLength(),
|
|
rq.LengthOf('modifiers', 2),
|
|
rq.Pad(22),
|
|
rq.List('modifiers', rq.Card32),
|
|
)
|
|
|
|
def passive_grab_device(self, deviceid, time, detail,
|
|
grab_type, grab_mode, paired_device_mode,
|
|
owner_events, event_mask, modifiers):
|
|
return XIPassiveGrabDevice(
|
|
display=self.display,
|
|
opcode=self.display.get_extension_major(extname),
|
|
deviceid=deviceid,
|
|
grab_window=self,
|
|
time=time,
|
|
cursor=X.NONE,
|
|
detail=detail,
|
|
grab_type=grab_type,
|
|
grab_mode=grab_mode,
|
|
paired_device_mode=paired_device_mode,
|
|
owner_events=owner_events,
|
|
mask=event_mask,
|
|
modifiers=modifiers,
|
|
)
|
|
|
|
def grab_keycode(self, deviceid, time, keycode,
|
|
grab_mode, paired_device_mode,
|
|
owner_events, event_mask, modifiers):
|
|
return passive_grab_device(self, deviceid, time, keycode,
|
|
GrabtypeKeycode,
|
|
grab_mode, paired_device_mode,
|
|
owner_events, event_mask, modifiers)
|
|
|
|
class XIPassiveUngrabDevice(rq.Request):
|
|
|
|
_request = rq.Struct(
|
|
rq.Card8('opcode'),
|
|
rq.Opcode(55),
|
|
rq.RequestLength(),
|
|
rq.Window('grab_window'),
|
|
rq.Card32('detail'),
|
|
DEVICEID('deviceid'),
|
|
rq.LengthOf('modifiers', 2),
|
|
rq.Set('grab_type', 1, (GrabtypeButton, GrabtypeKeycode,
|
|
GrabtypeEnter, GrabtypeFocusIn,
|
|
GrabtypeTouchBegin)),
|
|
rq.Pad(3),
|
|
rq.List('modifiers', rq.Card32),
|
|
)
|
|
|
|
def passive_ungrab_device(self, deviceid, detail, grab_type, modifiers):
|
|
return XIPassiveUngrabDevice(
|
|
display=self.display,
|
|
opcode=self.display.get_extension_major(extname),
|
|
deviceid=deviceid,
|
|
grab_window=self,
|
|
detail=detail,
|
|
grab_type=grab_type,
|
|
modifiers=modifiers,
|
|
)
|
|
|
|
def ungrab_keycode(self, deviceid, keycode, modifiers):
|
|
return passive_ungrab_device(self, deviceid, keycode,
|
|
GrabtypeKeycode, modifiers)
|
|
|
|
HierarchyInfo = rq.Struct(
|
|
DEVICEID('deviceid'),
|
|
DEVICEID('attachment'),
|
|
DEVICEUSE('type'),
|
|
rq.Bool('enabled'),
|
|
rq.Pad(2),
|
|
rq.Card32('flags'),
|
|
)
|
|
|
|
|
|
HierarchyEventData = rq.Struct(
|
|
DEVICEID('deviceid'),
|
|
rq.Card32('time'),
|
|
rq.Card32('flags'),
|
|
rq.LengthOf('info', 2),
|
|
rq.Pad(10),
|
|
rq.List('info', HierarchyInfo),
|
|
)
|
|
|
|
ModifierInfo = rq.Struct(
|
|
rq.Card32('base_mods'),
|
|
rq.Card32('latched_mods'),
|
|
rq.Card32('locked_mods'),
|
|
rq.Card32('effective_mods'),
|
|
)
|
|
|
|
GroupInfo = rq.Struct(
|
|
rq.Card8('base_group'),
|
|
rq.Card8('latched_group'),
|
|
rq.Card8('locked_group'),
|
|
rq.Card8('effective_group'),
|
|
)
|
|
|
|
DeviceEventData = rq.Struct(
|
|
DEVICEID('deviceid'),
|
|
rq.Card32('time'),
|
|
rq.Card32('detail'),
|
|
rq.Window('root'),
|
|
rq.Window('event'),
|
|
rq.Window('child'),
|
|
FP1616('root_x'),
|
|
FP1616('root_y'),
|
|
FP1616('event_x'),
|
|
FP1616('event_y'),
|
|
rq.LengthOf('buttons', 2),
|
|
rq.Card16('valulators_len'),
|
|
DEVICEID('sourceid'),
|
|
rq.Pad(2),
|
|
rq.Card32('flags'),
|
|
rq.Object('mods', ModifierInfo),
|
|
rq.Object('groups', GroupInfo),
|
|
ButtonState('buttons'),
|
|
)
|
|
|
|
DeviceChangedEventData = rq.Struct(
|
|
DEVICEID('deviceid'),
|
|
rq.Card32('time'),
|
|
rq.LengthOf('classes', 2),
|
|
DEVICEID('sourceid'),
|
|
rq.Card8('reason'),
|
|
rq.Pad(11),
|
|
rq.List('classes', ClassInfo),
|
|
)
|
|
|
|
PropertyEventData = rq.Struct(
|
|
DEVICEID('deviceid'),
|
|
rq.Card32('time'),
|
|
rq.Card32('property'),
|
|
rq.Card8('what'),
|
|
rq.Pad(11),
|
|
)
|
|
|
|
def init(disp, info):
|
|
disp.extension_add_method('display', 'xinput_query_version', query_version)
|
|
disp.extension_add_method('window', 'xinput_select_events', select_events)
|
|
disp.extension_add_method('display', 'xinput_query_device', query_device)
|
|
disp.extension_add_method('window', 'xinput_grab_device', grab_device)
|
|
disp.extension_add_method('display', 'xinput_ungrab_device', ungrab_device)
|
|
disp.extension_add_method('window', 'xinput_grab_keycode', grab_keycode)
|
|
disp.extension_add_method('window', 'xinput_ungrab_keycode', ungrab_keycode)
|
|
disp.extension_add_method('display', 'xinput_get_device_property', get_device_property)
|
|
disp.extension_add_method('display', 'xinput_list_device_properties', list_device_properties)
|
|
disp.extension_add_method('display', 'xinput_change_device_property', change_device_property)
|
|
disp.extension_add_method('display', 'xinput_delete_device_property', delete_device_property)
|
|
if hasattr(disp,"ge_add_event_data"):
|
|
for device_event in (ButtonPress, ButtonRelease, KeyPress, KeyRelease, Motion):
|
|
disp.ge_add_event_data(info.major_opcode, device_event, DeviceEventData)
|
|
disp.ge_add_event_data(info.major_opcode, DeviceChanged, DeviceEventData)
|
|
disp.ge_add_event_data(info.major_opcode, HierarchyChanged, HierarchyEventData)
|
|
disp.ge_add_event_data(info.major_opcode, PropertyEvent, PropertyEventData)
|