Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experiment: Add new real modifiers #447

Closed

Conversation

wismill
Copy link
Member

@wismill wismill commented Feb 11, 2024

In X11 we are limited to 8 real modifiers and it seems just fine in general. But they are some use cases where it would be useful to have some more:

  • Have true separate Meta and Hyper modifiers;
  • Have an Fn layer;
  • Possibly an accessibility modifier;
  • Use latch modifiers rather than dead keys, because then the layout is completely defined in XKB;
  • Differentiate right/left modifiers.

It is already possible to do this, but at the cost of other modifiers.

This PR adds 5 new modifiers (Mod6..Mod10) for a total of 13 (count subject to change). Why not add more? Good question! We encode the mask on 32 bits, but real and virtual modifiers share the same mask. So we cannot have 32 real modifiers because we need to keep some bits (at least 16) to encode the virtual modifiers as well.

This PR is a PoC to open the discussion.

Warning: The current implementation provides no backward-compatibility (X11, older xkbcommon).

@whot @bluetech

@wismill wismill added enhancement Indicates new feature requests compile-keymap Indicates a need for improvements or additions to keymap compilation labels Feb 11, 2024
@wismill wismill mentioned this pull request Feb 11, 2024
1 task
Copy link
Contributor

@whot whot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice, thanks! I stared at this over the weekend too and came up with the same approach (except naming them HMod1... as suggested).

I think we can add 8 modifiers immediately, XKB only allows for 16 virtual modifiers so we do have 8 bits available. But only adding 5 is the better approach, it kicks the can down the road for a bit and leaves us 3 bits for some potential emergency hack.

test/data/keymaps/real-modifiers.xkb Outdated Show resolved Hide resolved
test/data/keymaps/real-modifiers.xkb Outdated Show resolved Hide resolved
test/modifiers.c Outdated Show resolved Hide resolved
test/modifiers.c Outdated Show resolved Hide resolved
src/keymap-priv.c Show resolved Hide resolved
test/data/keymaps/real-modifiers.xkb Outdated Show resolved Hide resolved
test/modifiers.c Outdated Show resolved Hide resolved
@whot
Copy link
Contributor

whot commented Feb 12, 2024

So in terms of backwards-incompatibility:

  • dumping the keymap will include the new modifiers
  • the keys' modmap states will include bitmasks earlier clients don't know about?

Both of these could be handled via xkb context creation flags, I think. Anything else?

Also cc @fooishbar in case he remembers anything that would prevent this approach.

@wismill
Copy link
Member Author

wismill commented Feb 12, 2024

The MR was indeed under-documented. I improved it with new comments and some changes for the keysyms. Hopefully it makes it clearer.

Both of these could be handled via xkb context creation flags, I think. Anything else?

@whot maybe a new keymap format for xkb_keymap_get_as_string is enough? E.g. XKB_KEYMAP_FORMAT_TEXT_V1_X11 or XKB_KEYMAP_FORMAT_TEXT_V1_COMPAT?

@whot
Copy link
Contributor

whot commented Feb 12, 2024

Random-ish comment because right now this is a thought bubble because I haven't really wrapped my head around this: is it possible to make virtual modifiers actual virtual modifiers (as opposed to just name aliases for real modifiers?). They're not visible in the API at the moment but the information itself seems to be largely there?

e.g. remove the line modifier_map Mod2 { <NMLK> }; from your keymap and then run:

$ sudo ./build/interactive-evdev --keymap $keymapfile --print-modmaps
...
keycode [ NMLK ] modmap [         ] vmodmap [ NumLock  ] keysyms [ Num_Lock                    ] unicode [   ] layout [ English (US) (0) ] level [ 0 ] mods [ ] leds [ ]

The public api (mods [ ]) doesn't know about it but the internal API knows there is a virtual modifier even though it's not bound to anything. If we can add that modifier in the public API we may be able to get away with all this without backwards incompatible keymaps.

The API/behaviour may be backwards incompatible but I'm not sure that matters too much.

@whot
Copy link
Contributor

whot commented Feb 12, 2024

maybe a new keymap format for xkb_keymap_get_as_string is enough? E.g. XKB_KEYMAP_FORMAT_TEXT_V1_X11 or XKB_KEYMAP_FORMAT_TEXT_V1_COMPAT?

So this will be for the exchange format1 in Wayland which would be the next step. But right now Wayland has no way of announcing which format the client supports (and even with that added we'll have clients supporting the v1 format only). So we'll still need some way to tell libxkbcommon to export v1 format (i.e. without the incompatible new Mod6), and a newer libxkbcommon to behave like the old libxkbcommon (i.e. it can parse but never set the bits for Mod6 as seen by the public API). Not sure how much the latter is required, it feels like a bug if an application is confused by that.

Footnotes

  1. and IMO wee should just go with _V2 and document the permitted differences instead of trying to add semantic names. It's hard to run out of numbers after all and names will make it more confusing.

test/data/keymaps/real-modifiers.xkb Outdated Show resolved Hide resolved
src/keymap-priv.c Show resolved Hide resolved
test/data/keymaps/real-modifiers.xkb Outdated Show resolved Hide resolved
test/modifiers.c Outdated Show resolved Hide resolved
Copy link
Contributor

@whot whot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is a lot easier to understand now with the comments.

@fooishbar
Copy link
Member

Yeah, we thought a lot about it at the time and decided not to. The main reason was that it was far too early to break compatibility with X11. If this were to be done, you would either have to make the new modifiers purely virtual, or if they were real modifiers, to just no-op anything where a real modifier was active or set to be invoked for X11.

I don't think it's feasible to split real modifiers, e.g. turn the single Meta modifier (implying at least one of LAlt/RAlt virtual modifiers) into two separate modifiers. That would play havoc with all the existing keymaps, and also very likely clients who depend on, e.g. Meta active with A pressed to be interpreted as Alt+A, since they would instead see A pressed with some weird new left-alt modifier active. Similarly adding new real modifiers won't work; A pressed with Meta+LAlt real modifiers would be seen as different by clients to Meta+A when processing actions.

Adding new virtual modifiers is a great idea though. We did explicitly make room in the API for doing this, and it would be great to have. The API is probably incomplete and could use some description (implying more changes in keymap files), but the idea is sound.

So this will be for the exchange format1 in Wayland which would be the next step. But right now Wayland has no way of announcing which format the client supports (and even with that added we'll have clients supporting the v1 format only).

... yeah, you've picked this problem out. I got this badly wrong in the original wl_keyboard design. It paints clients into the same corner as X11. We'd need to fix that, and I'll gladly help with review etc.

@wismill
Copy link
Member Author

wismill commented Feb 12, 2024

@fooishbar IIRC the modifier mechanics, the mapping of virtual modifiers to real modifiers is quite essential. In this case, having virtual modifiers without such mapping will not work at all without a serious change in the modifier handling.

I don't think it's feasible to split real modifiers, e.g. turn the single Meta modifier (implying at least one of LAlt/RAlt virtual modifiers) into two separate modifiers. That would play havoc with all the existing keymaps, and also very likely clients who depend on, e.g. Meta active with A pressed to be interpreted as Alt+A, since they would instead see A pressed with some weird new left-alt modifier active. Similarly adding new real modifiers won't work; A pressed with Meta+LAlt real modifiers would be seen as different by clients to Meta+A when processing actions.

I am not sure I follow you. I remember having played with separate Alt/Meta and Super/Hyper without issue, but unfortunately I do not find the file. Also I would like to clarify that I do not propose to do that by default nor do I even propose to add it the option to xkeyboard-config. Anyway these are only some examples of use cases. There is another use case that I just added: some people prefer to use latch modifiers rather than dead keys, because then the layout is completely defined in XKB. If real modifiers mapping is required, then one can lack modifiers quickly!


I am all in favor to allow virtual modifiers to work without the need for a mapping to real modifiers. In this case, as you wrote, we do not even need any new real modifiers. If we go that route:

  • We should maybe change the vocabulary we use: real/virtual modifiers is a confusing terminology. Real modifier would be mere compatibility modifiers – aka X11 core modifiers – but I do not have a better name for the virtual modifiers.
  • We should add new warnings in order to forbid missing real modifiers mappings in xkeyboard-config.
  • Ensure we have enough tests of the current API.

@wismill
Copy link
Member Author

wismill commented Feb 12, 2024

For reference, what I understood from the modifiers machinery is in the section “Define and use a modifier” of the doc.

@whot
Copy link
Contributor

whot commented Feb 13, 2024

IIRC the modifier mechanics, the mapping of virtual modifiers to real modifiers is quite essential. In this case, having virtual modifiers without such mapping will not work at all without a serious change in the modifier handling.

Yes, the mapping of modifiers is essential atm. It's a bit confusing because virtual modifiers are really just name aliases, they're not actually modifiers (in the spec, anyway).

If we were to add true virtual modifiers the main breakage we would get is from keymaps that define interpret actions but rely on the virtual modifier being mapped or not to trigger those actions. There are only a handful of virtual modifiers currently that aren't in the default modifier_map statements:

  • OLPC's Square,Cross,Triangle,Circle, there is no section that uses those, so I'm not sure how those would ever be mapped (with our existing keymaps). I think we can ignore those
  • Kana_Lock used in symbols/sun_vendor/jp where it's mapped to Mod3. Only exposed via option japan:kana_lock.
  • Compose in compat/ledcompose where it's used for an indicator, exposed via option mod_led:compose
  • ScrollLock in compat/misc which is dragged into the default keymaps so we all have it but no-one has it by default. There's no option for it, only br(abnt2) maps it but that's a bug (xkeyboard-config!662).

So the immediate fallout of implementing purely virtual modifiers will likely be seen in the Scroll_Lock modifier which everyone has and will suddenly show up as modifier. At least that provides a somewhat widespread test bed for what will blow up :)

We should add new warnings in order to forbid missing real modifiers mappings in xkeyboard-config.

I'm not sure I understand this point, can you expand on it?

@wismill
Copy link
Member Author

wismill commented Feb 13, 2024

We should add new warnings in order to forbid missing real modifiers mappings in xkeyboard-config.

I'm not sure I understand this point, can you expand on it?

I mean that we should ensure that we do not rely on the new behavior in files used by XOrg, i.e. remove or forget real modifiers mappings that will remain mandatory for X11 systems.

@wismill
Copy link
Member Author

wismill commented Feb 15, 2024

Closing in favor of #450. This is a much simpler approach that require no syntax change, although the discussion here about backward compatibility will be very useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compile-keymap Indicates a need for improvements or additions to keymap compilation discussion: backward compatibility enhancement Indicates new feature requests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants