@@ -317,7 +317,9 @@ xkb_filter_group_lock_func(struct xkb_state *state,
317
317
}
318
318
319
319
static bool
320
- xkb_action_breaks_latch (const union xkb_action * action )
320
+ xkb_action_breaks_latch (const union xkb_action * action ,
321
+ enum xkb_internal_action_flags flag ,
322
+ xkb_mod_mask_t mask )
321
323
{
322
324
switch (action -> type ) {
323
325
case ACTION_TYPE_NONE :
@@ -328,6 +330,9 @@ xkb_action_breaks_latch(const union xkb_action *action)
328
330
case ACTION_TYPE_SWITCH_VT :
329
331
case ACTION_TYPE_TERMINATE :
330
332
return true;
333
+ case ACTION_TYPE_INTERNAL :
334
+ return (action -> internal .flags & flag ) &&
335
+ ((action -> internal .clear_latched_mods & mask ) == mask );
331
336
default :
332
337
return false;
333
338
}
@@ -411,7 +416,8 @@ xkb_filter_group_latch_func(struct xkb_state *state,
411
416
*/
412
417
continue ;
413
418
}
414
- else if (xkb_action_breaks_latch (& (actions [k ]))) {
419
+ else if (xkb_action_breaks_latch (& (actions [k ]),
420
+ INTERNAL_BREAKS_GROUP_LATCH , 0 )) {
415
421
/* Breaks the latch */
416
422
state -> components .latched_group -= priv .group_delta ;
417
423
filter -> func = NULL ;
@@ -569,9 +575,11 @@ xkb_filter_mod_latch_func(struct xkb_state *state,
569
575
/* XXX beep beep! */
570
576
return XKB_FILTER_CONSUME ;
571
577
}
572
- else if (xkb_action_breaks_latch (& (actions [k ]))) {
578
+ else if (xkb_action_breaks_latch (& (actions [k ]),
579
+ INTERNAL_BREAKS_MOD_LATCH ,
580
+ filter -> action .mods .mods .mask )) {
573
581
/* XXX: This may be totally broken, we might need to break the
574
- * latch in the next run after this press? */
582
+ * latch in the next run after this press? */
575
583
state -> components .latched_mods &= ~filter -> action .mods .mods .mask ;
576
584
filter -> func = NULL ;
577
585
return XKB_FILTER_CONTINUE ;
@@ -920,6 +928,153 @@ xkb_state_update_key(struct xkb_state *state, xkb_keycode_t kc,
920
928
return get_state_component_changes (& prev_components , & state -> components );
921
929
}
922
930
931
+ /* We need fake keys for update_latch_modifiers and update_latch_group.
932
+ * These keys must have at least one level in order to break latches. We need 2
933
+ * keys with specific actions in order to update group/mod latches without
934
+ * affecting each other. */
935
+ static struct xkb_key_type_entry synthetic_key_level_entry = { 0 };
936
+ static struct xkb_key_type synthetic_key_type = {
937
+ .num_entries = 1 ,
938
+ .num_levels = 1 ,
939
+ .entries = & synthetic_key_level_entry
940
+ };
941
+ static struct xkb_level synthetic_key_level_break_group_latch = {
942
+ .num_syms = 1 ,
943
+ .s = { XKB_KEY_NoSymbol },
944
+ .a = { { .internal = {
945
+ .type = ACTION_TYPE_INTERNAL ,
946
+ .flags = INTERNAL_BREAKS_GROUP_LATCH
947
+ } } }
948
+ };
949
+ static struct xkb_group synthetic_key_group_break_group_latch = {
950
+ .type = & synthetic_key_type ,
951
+ .levels = & synthetic_key_level_break_group_latch
952
+ };
953
+ static const struct xkb_key synthetic_key_break_group_latch = {
954
+ .num_groups = 1 ,
955
+ .groups = & synthetic_key_group_break_group_latch
956
+ };
957
+ static const struct xkb_key synthetic_key = { 0 };
958
+
959
+ /* Transcription from xserver: XkbLatchModifiers */
960
+ static void
961
+ update_latch_modifiers (struct xkb_state * state ,
962
+ xkb_mod_mask_t mask , xkb_mod_mask_t latches )
963
+ {
964
+ /* Clear affected latched modifiers */
965
+ const xkb_mod_mask_t clear =
966
+ mod_mask_get_effective (state -> keymap , mask & ~latches );
967
+ state -> components .latched_mods &= ~clear ;
968
+
969
+ /* Clear any pending latch to locks using ad hoc action:
970
+ * only affect corresponding modifier latches and no group latch. */
971
+ struct xkb_level synthetic_key_level_break_mod_latch = {
972
+ .num_syms = 1 ,
973
+ .s = { XKB_KEY_NoSymbol },
974
+ .a = { { .internal = {
975
+ .type = ACTION_TYPE_INTERNAL ,
976
+ .flags = INTERNAL_BREAKS_MOD_LATCH ,
977
+ .clear_latched_mods = clear
978
+ } } }
979
+ };
980
+ struct xkb_group synthetic_key_group_break_mod_latch = {
981
+ .type = & synthetic_key_type ,
982
+ .levels = & synthetic_key_level_break_mod_latch
983
+ };
984
+ const struct xkb_key synthetic_key_break_mod_latch = {
985
+ .num_groups = 1 ,
986
+ .groups = & synthetic_key_group_break_mod_latch
987
+ };
988
+ xkb_filter_apply_all (state , & synthetic_key_break_mod_latch , XKB_KEY_DOWN );
989
+
990
+ /* Finally set the latched mods by simulate tapping a key with the
991
+ * corresponding action */
992
+ const struct xkb_key * key = & synthetic_key ;
993
+ const union xkb_action latch_mods = {
994
+ .mods = {
995
+ .type = ACTION_TYPE_MOD_LATCH ,
996
+ .mods = {
997
+ .mask = mod_mask_get_effective (state -> keymap , mask & latches )
998
+ },
999
+ .flags = 0 ,
1000
+ },
1001
+ };
1002
+ struct xkb_filter * filter = xkb_filter_new (state );
1003
+ filter -> key = key ;
1004
+ filter -> func = xkb_filter_mod_latch_func ;
1005
+ filter -> action = latch_mods ;
1006
+ xkb_filter_mod_latch_new (state , filter );
1007
+ /* We added the filter manually, so only fire “up” event */
1008
+ xkb_filter_mod_latch_func (state , filter , key , XKB_KEY_UP );
1009
+ }
1010
+
1011
+ /* Transcription from xserver: XkbLatchGroup */
1012
+ static void
1013
+ update_latch_group (struct xkb_state * state , int32_t group )
1014
+ {
1015
+ /* Clear any pending latch to locks. */
1016
+ xkb_filter_apply_all (state , & synthetic_key_break_group_latch , XKB_KEY_DOWN );
1017
+
1018
+ /* Simulate tapping a key with a group latch action, but in isolation: i.e.
1019
+ * without affecting the other filters. */
1020
+ const struct xkb_key * key = & synthetic_key ;
1021
+ const union xkb_action latch_group = {
1022
+ .group = {
1023
+ .type = ACTION_TYPE_GROUP_LATCH ,
1024
+ .flags = ACTION_ABSOLUTE_SWITCH ,
1025
+ .group = group ,
1026
+ },
1027
+ };
1028
+ struct xkb_filter * filter = xkb_filter_new (state );
1029
+ filter -> key = key ;
1030
+ filter -> func = xkb_filter_group_latch_func ;
1031
+ filter -> action = latch_group ;
1032
+ xkb_filter_group_latch_new (state , filter );
1033
+ /* We added the filter manually, so only fire “up” event */
1034
+ xkb_filter_group_latch_func (state , filter , key , XKB_KEY_UP );
1035
+ }
1036
+
1037
+ XKB_EXPORT enum xkb_state_component
1038
+ xkb_state_update_latched_locked (struct xkb_state * state ,
1039
+ xkb_mod_mask_t affect_latched_mods ,
1040
+ xkb_mod_mask_t latched_mods ,
1041
+ bool affect_latched_layout ,
1042
+ int32_t latched_layout ,
1043
+ xkb_mod_mask_t affect_locked_mods ,
1044
+ xkb_mod_mask_t locked_mods ,
1045
+ bool affect_locked_layout ,
1046
+ int32_t locked_layout )
1047
+ {
1048
+ const struct state_components prev_components = state -> components ;
1049
+ /* Only include modifiers which exist in the keymap. */
1050
+ const xkb_mod_mask_t mask =
1051
+ (xkb_mod_mask_t ) ((1ull << xkb_keymap_num_mods (state -> keymap )) - 1u );
1052
+
1053
+ /* Update locks */
1054
+ affect_locked_mods &= mask ;
1055
+ if (affect_locked_mods ) {
1056
+ state -> components .locked_mods &= ~affect_locked_mods ;
1057
+ state -> components .locked_mods |= locked_mods & affect_locked_mods ;
1058
+ state -> components .locked_mods =
1059
+ mod_mask_get_effective (state -> keymap , state -> components .locked_mods );
1060
+ }
1061
+ if (affect_locked_layout ) {
1062
+ state -> components .locked_group = locked_layout ;
1063
+ }
1064
+
1065
+ /* Update latches */
1066
+ affect_latched_mods &= mask ;
1067
+ if (affect_latched_mods ) {
1068
+ update_latch_modifiers (state , affect_latched_mods , latched_mods );
1069
+ }
1070
+ if (affect_latched_layout ) {
1071
+ update_latch_group (state , latched_layout );
1072
+ }
1073
+
1074
+ xkb_state_update_derived (state );
1075
+ return get_state_component_changes (& prev_components , & state -> components );
1076
+ }
1077
+
923
1078
/**
924
1079
* Updates the state from a set of explicit masks as gained from
925
1080
* xkb_state_serialize_mods and xkb_state_serialize_groups. As noted in the
@@ -953,7 +1108,7 @@ xkb_state_update_mask(struct xkb_state *state,
953
1108
*
954
1109
* It might seem more reasonable to do this only for components.mods
955
1110
* in xkb_state_update_derived(), rather than for each component
956
- * seperately . That would allow to distinguish between "really"
1111
+ * separately . That would allow to distinguish between "really"
957
1112
* depressed mods (would be in MODS_DEPRESSED) and indirectly
958
1113
* depressed to to a mapping (would only be in MODS_EFFECTIVE).
959
1114
* However, the traditional behavior of xkb_state_update_key() is that
0 commit comments