@@ -132,104 +132,8 @@ def valid_transitions(self) -> Tuple["PenState", ...]:
132132
133133 return tuple ()
134134
135-
136- class Pen (object ):
137- def __init__ (self , x , y ):
138- self .x = x
139- self .y = y
140- self .tipswitch = False
141- self .tippressure = 15
142- self .azimuth = 0
143- self .inrange = False
144- self .width = 10
145- self .height = 10
146- self .barrelswitch = False
147- self .invert = False
148- self .eraser = False
149- self .x_tilt = 0
150- self .y_tilt = 0
151- self .twist = 0
152- self ._old_values = None
153- self .current_state = None
154-
155- def _restore (self ):
156- if self ._old_values is not None :
157- for i in [
158- "x" ,
159- "y" ,
160- "tippressure" ,
161- "azimuth" ,
162- "width" ,
163- "height" ,
164- "twist" ,
165- "x_tilt" ,
166- "y_tilt" ,
167- ]:
168- setattr (self , i , getattr (self ._old_values , i ))
169-
170- def move_to (self , state ):
171- # fill in the previous values
172- if self .current_state == PenState .PEN_IS_OUT_OF_RANGE :
173- self ._restore ()
174-
175- print (f"\n *** pen is moving to { state } ***" )
176-
177- if state == PenState .PEN_IS_OUT_OF_RANGE :
178- self ._old_values = copy .copy (self )
179- self .x = 0
180- self .y = 0
181- self .tipswitch = False
182- self .tippressure = 0
183- self .azimuth = 0
184- self .inrange = False
185- self .width = 0
186- self .height = 0
187- self .invert = False
188- self .eraser = False
189- self .x_tilt = 0
190- self .y_tilt = 0
191- self .twist = 0
192- elif state == PenState .PEN_IS_IN_RANGE :
193- self .tipswitch = False
194- self .inrange = True
195- self .invert = False
196- self .eraser = False
197- elif state == PenState .PEN_IS_IN_CONTACT :
198- self .tipswitch = True
199- self .inrange = True
200- self .invert = False
201- self .eraser = False
202- elif state == PenState .PEN_IS_IN_RANGE_WITH_ERASING_INTENT :
203- self .tipswitch = False
204- self .inrange = True
205- self .invert = True
206- self .eraser = False
207- elif state == PenState .PEN_IS_ERASING :
208- self .tipswitch = False
209- self .inrange = True
210- self .invert = True
211- self .eraser = True
212-
213- self .current_state = state
214-
215- def __assert_axis (self , evdev , axis , value ):
216- if (
217- axis == libevdev .EV_KEY .BTN_TOOL_RUBBER
218- and evdev .value [libevdev .EV_KEY .BTN_TOOL_RUBBER ] is None
219- ):
220- return
221-
222- assert (
223- evdev .value [axis ] == value
224- ), f"assert evdev.value[{ axis } ] ({ evdev .value [axis ]} ) != { value } "
225-
226- def assert_expected_input_events (self , evdev ):
227- assert evdev .value [libevdev .EV_ABS .ABS_X ] == self .x
228- assert evdev .value [libevdev .EV_ABS .ABS_Y ] == self .y
229- assert self .current_state == PenState .from_evdev (evdev )
230-
231135 @staticmethod
232- def legal_transitions () -> Dict [str , Tuple [PenState , ...]]:
136+ def legal_transitions () -> Dict [str , Tuple [" PenState" , ...]]:
233137 """This is the first half of the Windows Pen Implementation state machine:
234138 we don't have Invert nor Erase bits, so just move in/out-of-range or proximity.
235139 https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states
@@ -255,7 +159,7 @@ def legal_transitions() -> Dict[str, Tuple[PenState, ...]]:
255159 }
256160
257161 @staticmethod
258- def legal_transitions_with_invert () -> Dict [str , Tuple [PenState , ...]]:
162+ def legal_transitions_with_invert () -> Dict [str , Tuple [" PenState" , ...]]:
259163 """This is the second half of the Windows Pen Implementation state machine:
260164 we now have Invert and Erase bits, so move in/out or proximity with the intend
261165 to erase.
@@ -293,7 +197,7 @@ def legal_transitions_with_invert() -> Dict[str, Tuple[PenState, ...]]:
293197 }
294198
295199 @staticmethod
296- def tolerated_transitions () -> Dict [str , Tuple [PenState , ...]]:
200+ def tolerated_transitions () -> Dict [str , Tuple [" PenState" , ...]]:
297201 """This is not adhering to the Windows Pen Implementation state machine
298202 but we should expect the kernel to behave properly, mostly for historical
299203 reasons."""
@@ -306,7 +210,7 @@ def tolerated_transitions() -> Dict[str, Tuple[PenState, ...]]:
306210 }
307211
308212 @staticmethod
309- def tolerated_transitions_with_invert () -> Dict [str , Tuple [PenState , ...]]:
213+ def tolerated_transitions_with_invert () -> Dict [str , Tuple [" PenState" , ...]]:
310214 """This is the second half of the Windows Pen Implementation state machine:
311215 we now have Invert and Erase bits, so move in/out or proximity with the intend
312216 to erase.
@@ -321,7 +225,7 @@ def tolerated_transitions_with_invert() -> Dict[str, Tuple[PenState, ...]]:
321225 }
322226
323227 @staticmethod
324- def broken_transitions () -> Dict [str , Tuple [PenState , ...]]:
228+ def broken_transitions () -> Dict [str , Tuple [" PenState" , ...]]:
325229 """Those tests are definitely not part of the Windows specification.
326230 However, a half broken device might export those transitions.
327231 For example, a pen that has the eraser button might wobble between
@@ -359,6 +263,102 @@ def broken_transitions() -> Dict[str, Tuple[PenState, ...]]:
359263 }
360264
361265
266+ class Pen (object ):
267+ def __init__ (self , x , y ):
268+ self .x = x
269+ self .y = y
270+ self .tipswitch = False
271+ self .tippressure = 15
272+ self .azimuth = 0
273+ self .inrange = False
274+ self .width = 10
275+ self .height = 10
276+ self .barrelswitch = False
277+ self .invert = False
278+ self .eraser = False
279+ self .x_tilt = 0
280+ self .y_tilt = 0
281+ self .twist = 0
282+ self ._old_values = None
283+ self .current_state = None
284+
285+ def _restore (self ):
286+ if self ._old_values is not None :
287+ for i in [
288+ "x" ,
289+ "y" ,
290+ "tippressure" ,
291+ "azimuth" ,
292+ "width" ,
293+ "height" ,
294+ "twist" ,
295+ "x_tilt" ,
296+ "y_tilt" ,
297+ ]:
298+ setattr (self , i , getattr (self ._old_values , i ))
299+
300+ def move_to (self , state ):
301+ # fill in the previous values
302+ if self .current_state == PenState .PEN_IS_OUT_OF_RANGE :
303+ self ._restore ()
304+
305+ print (f"\n *** pen is moving to { state } ***" )
306+
307+ if state == PenState .PEN_IS_OUT_OF_RANGE :
308+ self ._old_values = copy .copy (self )
309+ self .x = 0
310+ self .y = 0
311+ self .tipswitch = False
312+ self .tippressure = 0
313+ self .azimuth = 0
314+ self .inrange = False
315+ self .width = 0
316+ self .height = 0
317+ self .invert = False
318+ self .eraser = False
319+ self .x_tilt = 0
320+ self .y_tilt = 0
321+ self .twist = 0
322+ elif state == PenState .PEN_IS_IN_RANGE :
323+ self .tipswitch = False
324+ self .inrange = True
325+ self .invert = False
326+ self .eraser = False
327+ elif state == PenState .PEN_IS_IN_CONTACT :
328+ self .tipswitch = True
329+ self .inrange = True
330+ self .invert = False
331+ self .eraser = False
332+ elif state == PenState .PEN_IS_IN_RANGE_WITH_ERASING_INTENT :
333+ self .tipswitch = False
334+ self .inrange = True
335+ self .invert = True
336+ self .eraser = False
337+ elif state == PenState .PEN_IS_ERASING :
338+ self .tipswitch = False
339+ self .inrange = True
340+ self .invert = True
341+ self .eraser = True
342+
343+ self .current_state = state
344+
345+ def __assert_axis (self , evdev , axis , value ):
346+ if (
347+ axis == libevdev .EV_KEY .BTN_TOOL_RUBBER
348+ and evdev .value [libevdev .EV_KEY .BTN_TOOL_RUBBER ] is None
349+ ):
350+ return
351+
352+ assert (
353+ evdev .value [axis ] == value
354+ ), f"assert evdev.value[{ axis } ] ({ evdev .value [axis ]} ) != { value } "
355+
356+ def assert_expected_input_events (self , evdev ):
357+ assert evdev .value [libevdev .EV_ABS .ABS_X ] == self .x
358+ assert evdev .value [libevdev .EV_ABS .ABS_Y ] == self .y
359+ assert self .current_state == PenState .from_evdev (evdev )
360+
361+
362362class PenDigitizer (base .UHIDTestDevice ):
363363 def __init__ (
364364 self ,
@@ -486,7 +486,7 @@ def _test_states(self, state_list, scribble):
486486 @pytest .mark .parametrize ("scribble" , [True , False ], ids = ["scribble" , "static" ])
487487 @pytest .mark .parametrize (
488488 "state_list" ,
489- [pytest .param (v , id = k ) for k , v in Pen .legal_transitions ().items ()],
489+ [pytest .param (v , id = k ) for k , v in PenState .legal_transitions ().items ()],
490490 )
491491 def test_valid_pen_states (self , state_list , scribble ):
492492 """This is the first half of the Windows Pen Implementation state machine:
@@ -498,7 +498,10 @@ def test_valid_pen_states(self, state_list, scribble):
498498 @pytest .mark .parametrize ("scribble" , [True , False ], ids = ["scribble" , "static" ])
499499 @pytest .mark .parametrize (
500500 "state_list" ,
501- [pytest .param (v , id = k ) for k , v in Pen .tolerated_transitions ().items ()],
501+ [
502+ pytest .param (v , id = k )
503+ for k , v in PenState .tolerated_transitions ().items ()
504+ ],
502505 )
503506 def test_tolerated_pen_states (self , state_list , scribble ):
504507 """This is not adhering to the Windows Pen Implementation state machine
@@ -515,7 +518,7 @@ def test_tolerated_pen_states(self, state_list, scribble):
515518 "state_list" ,
516519 [
517520 pytest .param (v , id = k )
518- for k , v in Pen .legal_transitions_with_invert ().items ()
521+ for k , v in PenState .legal_transitions_with_invert ().items ()
519522 ],
520523 )
521524 def test_valid_invert_pen_states (self , state_list , scribble ):
@@ -535,7 +538,7 @@ def test_valid_invert_pen_states(self, state_list, scribble):
535538 "state_list" ,
536539 [
537540 pytest .param (v , id = k )
538- for k , v in Pen .tolerated_transitions_with_invert ().items ()
541+ for k , v in PenState .tolerated_transitions_with_invert ().items ()
539542 ],
540543 )
541544 def test_tolerated_invert_pen_states (self , state_list , scribble ):
@@ -553,7 +556,7 @@ def test_tolerated_invert_pen_states(self, state_list, scribble):
553556 @pytest .mark .parametrize ("scribble" , [True , False ], ids = ["scribble" , "static" ])
554557 @pytest .mark .parametrize (
555558 "state_list" ,
556- [pytest .param (v , id = k ) for k , v in Pen .broken_transitions ().items ()],
559+ [pytest .param (v , id = k ) for k , v in PenState .broken_transitions ().items ()],
557560 )
558561 def test_tolerated_broken_pen_states (self , state_list , scribble ):
559562 """Those tests are definitely not part of the Windows specification.
0 commit comments