150150DEVICE = rq .Card16
151151DEVICEUSE = rq .Card8
152152
153+ class FP1616 (rq .Int32 ):
154+
155+ def check_value (self , value ):
156+ return int (value * 65536.0 )
157+
158+ def parse_value (self , value , display ):
159+ return float (value ) / float (1 << 16 )
160+
161+ class FP3232 (rq .ValueField ):
162+ structcode = 'lL'
163+ structvalues = 2
164+
165+ def check_value (self , value ):
166+ return value
167+
168+ def parse_value (self , value , display ):
169+ integral , frac = value
170+ ret = float (integral )
171+ # optimised math.ldexp(float(frac), -32)
172+ ret += float (frac ) * (1.0 / (1 << 32 ))
173+ return ret
153174
154175class XIQueryVersion (rq .ReplyRequest ):
155176 _request = rq .Struct (
@@ -239,31 +260,57 @@ def select_events(self, event_masks):
239260 masks = masks ,
240261 )
241262
242- DeviceInfo = rq .Struct (
243- DEVICEID ('deviceid' ),
244- rq .Card16 ('use' ),
245- rq .Card16 ('attachment' ),
246- rq .Card16 ('num_classes' ),
247- rq .LengthOf ('name' , 2 ),
248- rq .Bool ('enabled' ),
249- rq .Pad (1 ),
250- rq .String8 ('name' , 4 ),
251- # <num_classes> classes follow.
252- )
253-
254263AnyInfo = rq .Struct (
255264 rq .Card16 ('type' ),
256265 rq .Card16 ('length' ),
257266 rq .Card16 ('sourceid' ),
258267 rq .Pad (2 ),
259268)
260269
270+ class Mask (object ):
271+
272+ def __init__ (self , value , length ):
273+ self ._value = value
274+ self ._length = length
275+
276+ def __len__ (self ):
277+ return self ._length
278+
279+ def __getitem__ (self , key ):
280+ return self ._value & (1 << key )
281+
282+ def __str__ (self ):
283+ return ('{0:0%ub}' % self ._length ).format (self ._value )
284+
285+ def __repr__ (self ):
286+ return '%#0*x' % ((self ._length + 3 ) / 8 , self ._value )
287+
288+ class ButtonState (rq .ValueField ):
289+
290+ structcode = None
291+
292+ def __init__ (self , name ):
293+ rq .ValueField .__init__ (self , name )
294+
295+ def parse_binary_value (self , data , display , length , format ):
296+ # Mask: bitfield of <length> button states.
297+ mask_len = 4 * ((((length + 7 ) >> 3 ) + 3 ) >> 2 )
298+ mask_data = data [:mask_len ]
299+ mask_value = 0
300+ for b in reversed (struct .unpack ('=%uB' % mask_len , mask_data )):
301+ mask_value <<= 8
302+ mask_value |= b
303+ data = buffer (data , mask_len )
304+ assert 0 == (mask_value & 1 )
305+ return Mask (mask_value >> 1 , length ), data
306+
261307ButtonInfo = rq .Struct (
262308 rq .Card16 ('type' ),
263309 rq .Card16 ('length' ),
264310 rq .Card16 ('sourceid' ),
265- rq .Card16 ('num_buttons' ),
266- # state mask and label atoms follow.
311+ rq .LengthOf (('state' , 'labels' ), 2 ),
312+ ButtonState ('state' ),
313+ rq .List ('labels' , rq .Card32 ),
267314)
268315
269316KeyInfo = rq .Struct (
@@ -274,20 +321,6 @@ def select_events(self, event_masks):
274321 rq .List ('keycodes' , rq .Card32 ),
275322)
276323
277- class FP3232 (rq .ValueField ):
278- structcode = 'lL'
279- structvalues = 2
280-
281- def check_value (self , value ):
282- return value
283-
284- def parse_value (self , value , display ):
285- integral , frac = value
286- ret = float (integral )
287- # optimised math.ldexp(float(frac), -32)
288- ret += float (frac ) * (1.0 / (1 << 32 ))
289- return ret
290-
291324ValuatorInfo = rq .Struct (
292325 rq .Card16 ('type' ),
293326 rq .Card16 ('length' ),
@@ -329,6 +362,31 @@ def parse_value(self, value, display):
329362 TouchClass : TouchInfo ,
330363}
331364
365+ class ClassInfoClass :
366+
367+ structcode = None
368+
369+ def parse_binary (self , data , display ):
370+ class_type , length = struct .unpack ('=HH' , data [:4 ])
371+ class_struct = INFO_CLASSES .get (class_type , AnyInfo )
372+ class_data , _ = class_struct .parse_binary (data , display )
373+ data = buffer (data , length * 4 )
374+ return class_data , data
375+
376+ ClassInfo = ClassInfoClass ()
377+
378+ DeviceInfo = rq .Struct (
379+ DEVICEID ('deviceid' ),
380+ rq .Card16 ('use' ),
381+ rq .Card16 ('attachment' ),
382+ rq .LengthOf ('classes' , 2 ),
383+ rq .LengthOf ('name' , 2 ),
384+ rq .Bool ('enabled' ),
385+ rq .Pad (1 ),
386+ rq .String8 ('name' , 4 ),
387+ rq .List ('classes' , ClassInfo ),
388+ )
389+
332390class XIQueryDevice (rq .ReplyRequest ):
333391 _request = rq .Struct (
334392 rq .Card8 ('opcode' ),
@@ -343,44 +401,11 @@ class XIQueryDevice(rq.ReplyRequest):
343401 rq .Pad (1 ),
344402 rq .Card16 ('sequence_number' ),
345403 rq .ReplyLength (),
346- rq .Card16 ( 'num_devices' ),
404+ rq .LengthOf ( 'devices' , 2 ),
347405 rq .Pad (22 ),
406+ rq .List ('devices' , DeviceInfo ),
348407 )
349408
350- def _parse_response (self , data ):
351- self ._response_lock .acquire ()
352- self ._data , d = self ._reply .parse_binary (data , self ._display )
353- self ._data .devices = devices = []
354- for _ in range (self ._data .num_devices ):
355- devinfo , d = DeviceInfo .parse_binary (d , self ._display )
356- devinfo .classes = classes = []
357- for _ in range (devinfo .num_classes ):
358- class_type , length = struct .unpack ('=HH' , d [:4 ])
359- class_struct = INFO_CLASSES .get (class_type , None )
360- if class_struct is not None :
361- class_data , _ = class_struct .parse_binary (d , self ._display )
362- classes .append (class_data )
363- # Parse ButtonInfo state mask and label atoms.
364- if ButtonClass == class_type :
365- # Mask: bitfield of size a multiple of 4.
366- mask_offset = ButtonInfo .static_size
367- mask_len = 4 * ((((class_data .num_buttons + 7 ) >> 3 ) + 3 ) >> 2 )
368- mask_data = d [mask_offset :mask_offset + mask_len ]
369- mask = 0
370- for b in reversed (struct .unpack ('=%uB' % mask_len , mask_data )):
371- mask <<= 8
372- mask |= b
373- class_data .state = mask
374- # Labels: a list of <num_buttons> atoms.
375- labels_offset = mask_offset + mask_len
376- labels_len = class_data .num_buttons * 4
377- labels_data = d [labels_offset :labels_offset + labels_len ]
378- labels = struct .unpack ('=%uL' % class_data .num_buttons , labels_data )
379- class_data .labels = labels
380- d = buffer (d , length * 4 )
381- devices .append (devinfo )
382- self ._response_lock .release ()
383-
384409def query_device (self , deviceid ):
385410 return XIQueryDevice (
386411 display = self .display ,
@@ -572,14 +597,6 @@ def ungrab_keycode(self, deviceid, keycode, modifiers):
572597 rq .Card8 ('effective_group' ),
573598)
574599
575- class FP1616 (rq .Int32 ):
576-
577- def check_value (self , value ):
578- return int (value * 65536.0 )
579-
580- def parse_value (self , value , display ):
581- return float (value ) / float (1 << 16 )
582-
583600DeviceEventData = rq .Struct (
584601 DEVICEID ('deviceid' ),
585602 rq .Card32 ('time' ),
0 commit comments