@@ -317,6 +317,55 @@ def legal_transitions_with_invert() -> Dict[str, Tuple["PenState", ...]]:
317
317
),
318
318
}
319
319
320
+ @staticmethod
321
+ def legal_transitions_with_primary_button () -> Dict [str , Tuple ["PenState" , ...]]:
322
+ """We revisit the Windows Pen Implementation state machine:
323
+ we now have a primary button.
324
+ """
325
+ return {
326
+ "hover-button" : (PenState .PEN_IS_IN_RANGE_WITH_BUTTON ,),
327
+ "hover-button -> out-of-range" : (
328
+ PenState .PEN_IS_IN_RANGE_WITH_BUTTON ,
329
+ PenState .PEN_IS_OUT_OF_RANGE ,
330
+ ),
331
+ "in-range -> button-press" : (
332
+ PenState .PEN_IS_IN_RANGE ,
333
+ PenState .PEN_IS_IN_RANGE_WITH_BUTTON ,
334
+ ),
335
+ "in-range -> button-press -> button-release" : (
336
+ PenState .PEN_IS_IN_RANGE ,
337
+ PenState .PEN_IS_IN_RANGE_WITH_BUTTON ,
338
+ PenState .PEN_IS_IN_RANGE ,
339
+ ),
340
+ "in-range -> touch -> button-press -> button-release" : (
341
+ PenState .PEN_IS_IN_RANGE ,
342
+ PenState .PEN_IS_IN_CONTACT ,
343
+ PenState .PEN_IS_IN_CONTACT_WITH_BUTTON ,
344
+ PenState .PEN_IS_IN_CONTACT ,
345
+ ),
346
+ "in-range -> touch -> button-press -> release -> button-release" : (
347
+ PenState .PEN_IS_IN_RANGE ,
348
+ PenState .PEN_IS_IN_CONTACT ,
349
+ PenState .PEN_IS_IN_CONTACT_WITH_BUTTON ,
350
+ PenState .PEN_IS_IN_RANGE_WITH_BUTTON ,
351
+ PenState .PEN_IS_IN_RANGE ,
352
+ ),
353
+ "in-range -> button-press -> touch -> release -> button-release" : (
354
+ PenState .PEN_IS_IN_RANGE ,
355
+ PenState .PEN_IS_IN_RANGE_WITH_BUTTON ,
356
+ PenState .PEN_IS_IN_CONTACT_WITH_BUTTON ,
357
+ PenState .PEN_IS_IN_RANGE_WITH_BUTTON ,
358
+ PenState .PEN_IS_IN_RANGE ,
359
+ ),
360
+ "in-range -> button-press -> touch -> button-release -> release" : (
361
+ PenState .PEN_IS_IN_RANGE ,
362
+ PenState .PEN_IS_IN_RANGE_WITH_BUTTON ,
363
+ PenState .PEN_IS_IN_CONTACT_WITH_BUTTON ,
364
+ PenState .PEN_IS_IN_CONTACT ,
365
+ PenState .PEN_IS_IN_RANGE ,
366
+ ),
367
+ }
368
+
320
369
@staticmethod
321
370
def tolerated_transitions () -> Dict [str , Tuple ["PenState" , ...]]:
322
371
"""This is not adhering to the Windows Pen Implementation state machine
@@ -671,6 +720,22 @@ def test_tolerated_pen_states(self, state_list, scribble):
671
720
reasons."""
672
721
self ._test_states (state_list , scribble )
673
722
723
+ @pytest .mark .skip_if_uhdev (
724
+ lambda uhdev : "Barrel Switch" not in uhdev .fields ,
725
+ "Device not compatible, missing Barrel Switch usage" ,
726
+ )
727
+ @pytest .mark .parametrize ("scribble" , [True , False ], ids = ["scribble" , "static" ])
728
+ @pytest .mark .parametrize (
729
+ "state_list" ,
730
+ [
731
+ pytest .param (v , id = k )
732
+ for k , v in PenState .legal_transitions_with_primary_button ().items ()
733
+ ],
734
+ )
735
+ def test_valid_primary_button_pen_states (self , state_list , scribble ):
736
+ """Rework the transition state machine by adding the primary button."""
737
+ self ._test_states (state_list , scribble )
738
+
674
739
@pytest .mark .skip_if_uhdev (
675
740
lambda uhdev : "Invert" not in uhdev .fields ,
676
741
"Device not compatible, missing Invert usage" ,
@@ -728,101 +793,6 @@ def test_tolerated_broken_pen_states(self, state_list, scribble):
728
793
state machine."""
729
794
self ._test_states (state_list , scribble )
730
795
731
- @pytest .mark .skip_if_uhdev (
732
- lambda uhdev : "Barrel Switch" not in uhdev .fields ,
733
- "Device not compatible, missing Barrel Switch usage" ,
734
- )
735
- def test_primary_button (self ):
736
- """Primary button (stylus) pressed, reports as pressed even while hovering.
737
- Actual reporting from the device: hid=TIPSWITCH,BARRELSWITCH,INRANGE (code=TOUCH,STYLUS,PEN):
738
- { 0, 0, 1 } <- hover
739
- { 0, 1, 1 } <- primary button pressed
740
- { 0, 1, 1 } <- liftoff
741
- { 0, 0, 0 } <- leaves
742
- """
743
-
744
- uhdev = self .uhdev
745
- evdev = uhdev .get_evdev ()
746
-
747
- p = Pen (50 , 60 )
748
- p .inrange = True
749
- events = self .post (uhdev , p )
750
- assert libevdev .InputEvent (libevdev .EV_KEY .BTN_TOOL_PEN , 1 ) in events
751
- assert evdev .value [libevdev .EV_ABS .ABS_X ] == 50
752
- assert evdev .value [libevdev .EV_ABS .ABS_Y ] == 60
753
- assert not evdev .value [libevdev .EV_KEY .BTN_STYLUS ]
754
-
755
- p .barrelswitch = True
756
- events = self .post (uhdev , p )
757
- assert libevdev .InputEvent (libevdev .EV_KEY .BTN_STYLUS , 1 ) in events
758
-
759
- p .x += 1
760
- p .y -= 1
761
- events = self .post (uhdev , p )
762
- assert len (events ) == 3 # X, Y, SYN
763
- assert libevdev .InputEvent (libevdev .EV_ABS .ABS_X , 51 ) in events
764
- assert libevdev .InputEvent (libevdev .EV_ABS .ABS_Y , 59 ) in events
765
-
766
- p .barrelswitch = False
767
- events = self .post (uhdev , p )
768
- assert libevdev .InputEvent (libevdev .EV_KEY .BTN_STYLUS , 0 ) in events
769
-
770
- p .inrange = False
771
- events = self .post (uhdev , p )
772
- assert libevdev .InputEvent (libevdev .EV_KEY .BTN_TOOL_PEN , 0 ) in events
773
-
774
- @pytest .mark .skip_if_uhdev (
775
- lambda uhdev : "Barrel Switch" not in uhdev .fields ,
776
- "Device not compatible, missing Barrel Switch usage" ,
777
- )
778
- def test_contact_primary_button (self ):
779
- """Primary button (stylus) pressed, reports as pressed even while hovering.
780
- Actual reporting from the device: hid=TIPSWITCH,BARRELSWITCH,INRANGE (code=TOUCH,STYLUS,PEN):
781
- { 0, 0, 1 } <- hover
782
- { 0, 1, 1 } <- primary button pressed
783
- { 1, 1, 1 } <- touch-down
784
- { 1, 1, 1 } <- still touch, scribble on the screen
785
- { 0, 1, 1 } <- liftoff
786
- { 0, 0, 0 } <- leaves
787
- """
788
-
789
- uhdev = self .uhdev
790
- evdev = uhdev .get_evdev ()
791
-
792
- p = Pen (50 , 60 )
793
- p .inrange = True
794
- events = self .post (uhdev , p )
795
- assert libevdev .InputEvent (libevdev .EV_KEY .BTN_TOOL_PEN , 1 ) in events
796
- assert evdev .value [libevdev .EV_ABS .ABS_X ] == 50
797
- assert evdev .value [libevdev .EV_ABS .ABS_Y ] == 60
798
- assert not evdev .value [libevdev .EV_KEY .BTN_STYLUS ]
799
-
800
- p .barrelswitch = True
801
- events = self .post (uhdev , p )
802
- assert libevdev .InputEvent (libevdev .EV_KEY .BTN_STYLUS , 1 ) in events
803
-
804
- p .tipswitch = True
805
- events = self .post (uhdev , p )
806
- assert libevdev .InputEvent (libevdev .EV_KEY .BTN_TOUCH , 1 ) in events
807
- assert evdev .value [libevdev .EV_KEY .BTN_STYLUS ]
808
-
809
- p .x += 1
810
- p .y -= 1
811
- events = self .post (uhdev , p )
812
- assert len (events ) == 3 # X, Y, SYN
813
- assert libevdev .InputEvent (libevdev .EV_ABS .ABS_X , 51 ) in events
814
- assert libevdev .InputEvent (libevdev .EV_ABS .ABS_Y , 59 ) in events
815
-
816
- p .tipswitch = False
817
- events = self .post (uhdev , p )
818
- assert libevdev .InputEvent (libevdev .EV_KEY .BTN_TOUCH , 0 ) in events
819
-
820
- p .barrelswitch = False
821
- p .inrange = False
822
- events = self .post (uhdev , p )
823
- assert libevdev .InputEvent (libevdev .EV_KEY .BTN_TOOL_PEN , 0 ) in events
824
- assert libevdev .InputEvent (libevdev .EV_KEY .BTN_STYLUS , 0 ) in events
825
-
826
796
827
797
class GXTP_pen (PenDigitizer ):
828
798
def event (self , pen ):
0 commit comments