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

Feature: Virtual keys #340

Closed
steamraven opened this issue Mar 25, 2021 · 3 comments
Closed

Feature: Virtual keys #340

steamraven opened this issue Mar 25, 2021 · 3 comments

Comments

@steamraven
Copy link
Contributor

steamraven commented Mar 25, 2021

So right now, we some really cool mouse modules, but no way to configure them. Even if we did make them accessible from the agent, the code setup is pretty clunky. A solution may be Virtual Keys.

The idea is to make use of some of the keyIds in the keymap for each module that are not being used by a physical key. For example KeyId 6 in the left keycluster module, and 3 in each of the right modules.

Then we assign to this special keyid, a special new KeyAction: MouseMove. This KeyAction has a NavigationMode parameter : Cursor, Scroll, Caret

Then for each keymap, each layer, and each module, you can assign a navigation mode to the mouse functionality just by changing the KeyAction of the required KeyID

For example, we can emulate the current configuration by assigning

  • Base Layer:
    • Left Keycluster: KeyID 6 = MouseMove(Scroll)
    • Right trackball: KeyID 3 = MouseMove(Cursor)
  • Mod Layer:
    • Left Keycluster: KeyID 6 = MouseMove(Cursor)
    • Right trackball: KeyID 3 = MouseMove(Scroll)

Of course, you can change this however you want. Each layer or keymap a different mode.

We can go farther, we can assign some Virtual Keys to gestures on the Touchpad. It currently can currently do:

  • Tap and Hold
  • Scroll
  • Zoom
  • Swipe up/Down/Left/Right

We can give each of these a new virtual key (in its own module keymap, so it doesn't interfere) and assign scancodes, mosue actions, Mouse navigation, etc to each one. All Layer and keymap variable!

Technical details (see code at the bottom):

  • A keyID must be assigned per module for each special function
  • A new KeyAction (mouseMove=36) with the following data:
    • uint8_t naviagationMode =
      • Cursor = 1,
      • Scroll = 2,
      • Caret = 3 (Not Implemented)
      • Media = 4 (Not implemented),
      • Zoom = 5 (Not implemented)
    • uint16_t Multiplier (not used, set to zero)
  • When a module is activated, it should set its hardwareSwitchState to 1, and clear when disconnected.

This will also require some Agent changes and a new UI for specifying these virtual keys. Changing the Agent configuration to handle the new KeyAction should be trivial and allow configuration through JSON. Adding the UI will be quite a bit more work.

KeyIds:

  • Left Key cluster Module:
    • MouseMove = 6
  • Right Trackpad
  • Right Trackpoint
    • MouseMove = 3
  • Right Touchpad
    • MouseMove = 3
    • TapAndHold = 4
    • SwipeUp = 5
    • SwipeDown = 6
    • SwipeLeft = 7
    • SwipeRight = 8
    • MoveScroll = 9
    • MoveZoom = 10

Here is a link to some code. I tried to break it into small commits. I haven't tested it, but it does compile.

https://github.com/steamraven/firmware/tree/keymap_mouse_move

@kareltucek
Copy link
Collaborator

kareltucek commented Apr 6, 2021

I've been thinking about a similar approach some time ago, although in less sophisticated terms.

Some notes to this sketchup (note that I by no means represent UHK team in this (and no other) matter, and my own opinions are usually rather contrary to Laci's):

  • I like it, except I think that you do not want a special new action. On the contrary, I think that the mouse mode should be implemented on level of regular mouse state, and should be assignable even within regular mappings. This would alleviate dependence on layer/keymap.

  • I like the concept of a "layer coactivation action", if I understand it correctly. I.e., as a general action slot which is made always active. (Also could be directly used, e.g., for making some layer always activate some modifier (e.g., shift) when it is active.)

  • in its own module keymap, so it doesn't interfere

    This is going to take quite a bit of memory, which is becoming a scarce resource, especially with the promise of 12 layer support. But generally I like it.

  • check out the proposed caret config format in https://github.com/UltimateHackingKeyboard/firmware/pull/344/files I think it resonates with some of your ideas. Atm., there's no config serialization background, but it could be easily fed from your virtual keys.

@steamraven
Copy link
Contributor Author

  • I think that you do not want a special new action. On the contrary, I think that the mouse mode should be implemented on level of regular mouse state, and should be assignable even within regular mappings

I could implement this as a a new MouseAction, but either way, there is going to be special code in the UI and the firmware. This action is a MouseMove, it does not fit nicely into any of the current MouseActions.

In addition, it does more than just MouseAction. This is about taking mouse input from a module and "doing something" with it. That "something" could be:

  • moving a mouse (multiple mouseMove_up, left, etc) .
  • scrolling the mouse (no keyActions for this)
  • It could be moving the caret. (uparrow, leftarrow, etc)

Technically, this moves all the "module mouse input", out of MouseController_ProcessMouseActions, and adds it as a special keyaction to be called during the applyKeyAction loop.

When "mouse input" is detected in a module, it looks up the appropriate virtual key, then sets its hardwardSwitchState.

When the applyKeyAction loop comes to this keyid, it sees the hardwareSwitchState, and looks up the appropriate keyAction for the active layer. This keyAction says what to do with the input, then calls into the MouseController to update x,y values or scroll values

  • This is going to take quite a bit of memory, which is becoming a scarce resource, especially with the promise of 12 layer support. But generally I like it.

So the basic idea is to move all the mouse configuration into unused keys in the keymap. Since the keymap is statically allocated, this is actually saving space. This is moving the navigationModes from the modules structure into keyactions within the keymap.

Each keyaction in the keymap has 5 bytes to use, and this is already allocated in the keymap.

Another benefit of moving into the keymap, is it allows the user to change configuration by changing keymap. This is much easier cycling between configs then opening up the agent and fiddling with the (yet unimplemted) navigation settings.

  • This would alleviate dependence on layer/keymap.
    I want dependence on layer/keymap. I want my "mouse input" to do different things based on which module it is, which layer is active, which keymap is active. This way I can change it on the fly.
  • check out the proposed caret
    This was specifically designed to eventually call into the caret code when implemented. This allows different layers or keymaps to define how "mouse input" will get translated. Don't have to go through moduleConfig
  • I like the concept of a "layer coactivation action"

I'm not sure where you are getting this. This entirely relies on the current layer selection code.

@mondalaci
Copy link
Member

@steamraven Thank you very much for coming up with such a detailed solution!

I've been thinking about how to introduce additional configuration options, such as module-related options, in the simplest and most general way possible and without affecting Agent, and I'm heavily leaning towards smart macros.

I'm closing this issue, but feel free to follow up regardless.

ert78gb pushed a commit that referenced this issue Dec 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants