No fallback when using multiple keysyms per level
In order to support multiple keysyms per level, one has to use e.g. xkb_state_key_get_syms and not xkb_state_key_get_one_sym. From the doc of xkb_state_key_get_one_sym:
This function is similar to xkb_state_key_get_syms(), but intended for users which cannot or do not want to handle the case where multiple keysyms are returned (in which case this function is preferred).
But there are cases when we would like xkb_state_key_get_one_sym to return a fallback keysym:
- The initial use case for multiple keysyms per level was to be able to type glyphs that requires multiple Unicode code points to be encoded. The issue is that such key:
- Provides no feedback to the user when an app uses only
xkb_state_key_get_one_sym: it simply does nothing at all. - Cannot be used in shortcuts, which usually require only one keysym.
- Provides no feedback to the user when an app uses only
key <LCTL> { [ { Control_L, ISO_Group_Shift } ] };: HereISO_Group_Shiftis a considered a side effect, but if multiple keysyms are not supported then we looseControl_Lcompletely. It would be very useful to be able to fallback to a single keysymControl_L, e.g. when loading the keymap intoXWayland. Else no interpretation is run on the key and it may affect virtual modifiers mappings to real modifiers.
Issue 1.1 can be solved using e.g. a Unicode keysym in Unicode PUA and a corresponding entry in a Compose file. However, there is no alternative for issues 1.2 ~~and 2.~~ EDIT: since #487 we can have actions with a different count than keysyms.
We cannot blindly fallback to the first keysym of a list, because it may not make sense. But what about proposing to specify the fallback explicitly? E.g. (note the |):
EDIT: the following examples make less sense now that we have #487. But a fallback is still useful for compatibility with e.g. X11.
// Fallback to simply `Control_L` when using `xkb_state_key_get_one_sym` or similar functions.
key <LCTL> { [ { Control_L, ISO_Group_Shift } | Control_L ] };
// Different order, same result.
// It depends if we read the previous as “graceful degradation” or the next as “progressive enhancement”.
key <LCTL> { [ Control_L | { Control_L, ISO_Group_Shift } ] };
// Invalid: must be a single keysym and a single list
key <LCTL> { [ { Control_L, x } | { Control_L, ISO_Group_Shift } ] };
// Invalid: must be a single keysym and a single list
key <LCTL> { [ a | b | c ] };
// Some other ideas
// Better grouping?
key <LCTL> { [ { Control_L, ISO_Group_Shift | Control_L } ] };
// Better to be explicit but verbose?
key <LCTL> { [ { Control_L, ISO_Group_Shift, fallback=Control_L } ] };
What about the actions? If we have a fallback for actions too, I think we should run the interpretations on all keysyms (normal+fallback), even if the resulting actions differ: we defer the decision whether it makes sense or no to the layout designer. Note that the action on the single keysym will be unused by the state; it would be used only in an hypothetical compatibility format for e.g. loading into X servers.
@mahkoh What do you think of this proposal? #487 makes the original example with Control_ + ISO_Group_Shift obsolete, but the situation is not solved for e.g. shortcuts.
I think you should deprecate xkb_state_key_get_one_sym and have clients handle multiple keysyms.
I think you should deprecate xkb_state_key_get_one_sym and have clients handle multiple keysyms.
I do not think this is realistic. Especially for XWayland and the shortcut use case: if handling of multiple keysyms is not always great just to translate to strings, imagine for the shortcuts!
Added to that, xkb_state_key_get_syms does not currently handle Caps keysym transformation (see #552), so they would not be equivalent. It’s not totally clear to me if this is just a limitation of our implementation or something else. I see no reason not to propose the caps-transform option.