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: state: support pure virtual modifiers #450

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

whot
Copy link
Contributor

@whot whot commented Feb 14, 2024

Traditionally, virtual modifiers were merely name aliases for real modifiers, e.g. NumLock was usually mapped to Mod2 (see modifier_map statement). Virtual modifiers that were never mapped to a real one had no effect on the keymap state.

This patch introduces the concept of pure virtual modifiers, i.e. virtual modifiers that are not mapped now show up as if the were true modifiers.

Note that pure virtual modifiers cannot be used in an interpret action's AnyOf() and an interpret action for a pure virtual modifier must be AnyOfOrNone() to take effect:

virtual_modifiers APureMod,...;

interpret a+AnyOfOrNone(all) {
  virtualModifier= APureMod;
  action= SetMods(modifiers=APureMod);
};

The above adds a pure virtual modifier for keysym a.

Interestingly, this fixes one current issue with our tests: previously the de(neo) layout level5 didn't take effect correctly, with this patch in place it now behaves.


TODO:

  • Add tests for X11
  • Clarify the terminology
  • Update the doc (with examples)
  • Add changelog

This took forever to wrap my head around it almost feels too simple now... The one test case failure was in the de(neo) layout but after staring at this - it actually fixes that particular issue.

Related to #447

cc @wismill, @bluetech, @fooishbar

@wismill wismill added state Indicates a need for improvements or additions to the xkb_state API discussion: backward compatibility labels Feb 15, 2024
@whot
Copy link
Contributor Author

whot commented Feb 20, 2024

Referencing #36 here too since there's significant overlap.

@wismill wismill added this to the 1.8.0 milestone Mar 12, 2024
@fooishbar
Copy link
Member

Yeah, nice. I think this is definitely the right approach.

@wismill
Copy link
Member

wismill commented Jul 9, 2024

@whot I added some tests in whot#1.

@wismill
Copy link
Member

wismill commented Aug 30, 2024

Rebased and added first dedicated tests. Since this has the potential to breaks things, I would proceed with care. But honestly I feel it looks pretty solid for now. Maybe modify more tests much like keyseq where two rules files (usual vs “pure” virtual modifiers) are used alternatively on the same tests.

@wismill
Copy link
Member

wismill commented Sep 23, 2024

This will require #512 for a full implementation.

@bluetech
Copy link
Member

This patch introduces the concept of pure virtual modifiers, i.e. virtual modifiers that are not mapped now show up as if the were true modifiers.

@whot @wismill Can you remind me why not do this for all virtual modifiers (including non pure ones)?

@wismill
Copy link
Member

wismill commented Nov 20, 2024

@whot @wismill Can you remind me why not do this for all virtual modifiers (including non pure ones)?

@bluetech Compatibility: e.g. Alt is mapped to Mod1 by default and compositor/apps query the state using real modifiers[^1]. If we remove this link, then Alt cannot be queried anymore. It would when
#512 will be merged, but even then any program that did not migrate will still query with Mod1 and get wrong results. And we also need these mappings for libxkbcommon-x11.

So any usual modifier will have to keep its vmod/rmod mapping, probably forever. However, for unusual mods such as Hyper, Meta, LevelFive and ScrollLock, we will have the possibility to use them independently altogether instead of having them overlap.

@bluetech
Copy link
Member

Compatibility: e.g. Alt is mapped to Mod1 by default and compositor/apps query the state using real modifiers[^1]. If we remove this link, then Alt cannot be queried anymore. It would when
#512 will be merged, but even then any program that did not migrate will still query with Mod1 and get wrong results. And we also need these mappings for libxkbcommon-x11.

(Sorry again for possibly uninformed questions, I really did forget most of it...)

The Alt vmod sets Mod1 rmod. My question is not about removing this link, this should definitely stay for compatibility.

My question is, this patch only makes pure vmods show up in the effective mask, hence Alt (not a pure vmod) still won't show up in the effective mask. What's the reason for restricting this to pure vmods? Why not have Alt set both Mod1 and Alt in the effective mask?

@wismill
Copy link
Member

wismill commented Nov 20, 2024

My question is, this patch only makes pure vmods show up in the effective mask, hence Alt (not a pure vmod) still won't show up in the effective mask. What's the reason for restricting this to pure vmods? Why not have Alt set both Mod1 and Alt in the effective mask?

I guess the answer is normalization. It’s easier to work with the canonical representation, i.e. with only real modifiers, rather than a mix of both types. Or maybe I am just used to it. A good argument however is that this has always been so in both xkbcommon and X11. We could start to provide vmod in the effective mask, but we should not depend on it when updating the state in client: indeed, there is no clue of what version of xkbcommon the compositor is using, so if it is an older one then keyboard handling will be broken in the client.

By the way, we should revise the terminology. Or better expressed, let’s not introduce a new one with “pure”. I propose:

  • Real modifiers are modifiers that map to themselves: current real modifiers (aka legacy X11 real modifiers) and new pure virtual modifiers. Maybe call them respectively core/non-core real modifiers? Then drop the “pure virtual modifier” concept.
  • Virtual modifiers are modifiers defined as a combination of other modifiers: current virtual modifiers, as in X11. With perspective I would argue that “pure virtual” would be a much better description of those.

By this new terminology, the type of modifier may change depending on the keymap, except of course for the core real modifiers, which are predefined.

@whot
Copy link
Contributor Author

whot commented Nov 25, 2024

back from a few sick days, still a bit hazy in the brain...

the terminology is definitely a problem here and I'm not happy with it. real modifiers are actual modifiers that have effects on the keymap. virtual modifiers as we have them now are really just aliases - unless they alias a real modifier they do not exist in the keymap, regardless whether there are types for it, etc. It's a bit counterintuitive because I can set up key mappings to handle everything based on a virtual modifier but unless it's mapped to e.g. Mod3 nothing happens. and everything built in the last few decades relies on that.

"pure virtual modifiers" (using this so we know what I refer to) are somewhat a new concept that didn't exist before, I don't think we should use the same name as for real modifiers that existed before since the pure ones e.g. won't show up under x11.

If I had a time machine, I'd name the current virtual modifiers "modifier aliases" or something but then again, if I had a time machine I doubt I'd busy myself hacking on XKB related infrastructure :)

In the key maps the pure vmods will still show up as virtual_modifiers so IMO we really need a qualifier for virtual modifiers, pure was just the best/only one I came up with.

Also, core/non-core in X is core protocol/XKB extension so that term is mostly out, too much documentation out there that uses those terms.

Why not have Alt set both Mod1 and Alt in the effective mask?

I've paged most of this out too unfortunately but that also requires clients to keep track of an effective duplicate state in the modifier mask which seems unnecessary. Plus it was safer to just not touch anything the way it works right now :)

@wismill
Copy link
Member

wismill commented Nov 25, 2024

I would prefer to avoid “pure”, as it may imply that the rest is “impure”1.

I propose the following terminology:

  • Real modifier: core X11 modifier (unchanged).
  • Virtual modifier: Any modifier that is not a real modifier (unchanged).
  • Modifier alias: A virtual modifier that maps to another modifier. We ought to use it for virtual modifiers that map to multiple modifiers too.
  • Canonical modifier: A modifier that is used to encode/communicate the canonical keyboard state. Currently only the core X11 modifiers; with this MR also the “pure virtual modifiers”.
  • Virtual canonical modifier: A virtual modifier that is also a state modifier, i.e. that is not a modifier alias. Called “pure virtual modifier” in this MR.
  • Real canonical modifier: synonym of “real modifier”, used for highlighting difference with “virtual canonical modifier”.
EDIT: after a second thought “canonical modifier” in place of “state modifier” seems the right call after all.
  • State modifier: A modifier that is used to encode/communicate the canonical keyboard state. Currently only the real X11 modifiers; with this MR also the “pure virtual modifiers”.
  • Virtual state modifier: A virtual modifier that is also a state modifier, i.e. that is not a modifier alias. Called “pure virtual modifier” in this MR.
  • Real state modifier: synonym of “real modifier”.

I would avoid “canonical modifier”, or reserve it only as the single target of a modifier alias, e.g. Mod1 in Alt = Mod1, but not in WonderMod = Mod1 | Mod2.

Random thoughts that I discarded:

  • Post-X11: let’s not carry on with the X11 legacy burden.
  • Math terminology: auto/iso/identity/discreet… While Category Theory would provide a solid terminology, using these terms in our public doc will not help popularize XKB 😅

Footnotes

  1. I do use these terms in e.g. Functional Programming or Chemistry but there they have established meanings.

whot and others added 2 commits November 29, 2024 13:15
Traditionally, virtual modifiers were merely name aliases for real modifiers,
e.g. NumLock was usually mapped to Mod2 (see modifier_map statement). Virtual
modifiers that were never mapped to a real one had no effect on the keymap state.

This patch introduces the concept of pure virtual modifiers, i.e. virtual
modifiers that are not mapped now show up as if the were true modifiers.

Note that pure virtual modifiers cannot be used in an interpret action's AnyOf()
and an interpret action for a pure virtual modifier must be AnyOfOrNone() to
take effect:

    virtual_modifiers APureMod,...;

    interpret a+AnyOfOrNone(all) {
      virtualModifier= APureMod;
      action= SetMods(modifiers=APureMod);
    };

The above adds a pure virtual modifier for keysym `a`.

Interestingly, this fixes one current issue with our tests: previously the
de(neo) layout level5 didn't take effect correctly, with this patch in place it
now behaves.
@wismill wismill force-pushed the wip/pure-virtual-modifiers branch from 0c66d0a to 0421feb Compare November 29, 2024 12:40
@wismill
Copy link
Member

wismill commented Nov 29, 2024

Rebased + added tests. We still have to clarify the terminology.

@wismill
Copy link
Member

wismill commented Nov 29, 2024

By the way, I noted that xkb_state_update_mask accepts whatever modifier that is in the keymap but does not normalize them to real/pure vmods in the internal state; a call to xkb_state_serialize_mods may then produce a non-canonical serialization. Using xkb_state_update_mask with a vmod or its equivalent real mod mask may thus result in a different internal state and a different return value.

I would rather always normalize the internal state. Is there a use case for not doing so?

Anyway, the tests do check this.

@wismill wismill mentioned this pull request Nov 29, 2024
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion: backward compatibility state Indicates a need for improvements or additions to the xkb_state API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants