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

Custom Tapping Term per key #5009

Merged
merged 19 commits into from
Apr 5, 2019
Merged

Conversation

drashna
Copy link
Member

@drashna drashna commented Jan 30, 2019

Description

Allow a user customizable tapping term, that is configurable, per key. In theory.

However, it doesn't work correctly. The default value works, but I can't seem to get it to properly work using the keycode, but does work if you specify the Row and Column of the key.

This is not ideal, at all. But I'm not sure sure how to fix this issue. So, I'm opening the pull request to get some input on this, and see if somebody can help me get this working "properly".

This isn't originally my code, but is fredizzimo and @danielo515

Types of changes

  • Core
  • Bugfix
  • New Feature
  • Enhancement/Optimization
  • Keyboard (addition or update)
  • Keymap/Layout/Userspace (addition or update)
  • Documentation

Issues Fixed or Closed by this PR

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document. (https://docs.qmk.fm/#/contributing)
  • I have added tests to cover my changes.
  • I have tested the changes and verified that they work and don't break anything (as well as I can manage).

@fauxpark
Copy link
Member

fauxpark commented Jan 30, 2019

keyevent_t only provides row, column and timing information:

// tmk_core/common/keyboard.h
typedef struct {
    keypos_t key;
    bool     pressed;
    uint16_t time;
} keyevent_t;

I see someone else has gone down this path before, using keymap_key_to_keycode() to conjure up the keycode from the position:

https://github.com/qmk/qmk_firmware/blob/master/keyboards/ergodox_infinity/keymaps/gordon/keymap.c#L21

EDIT: Whoops, this is pretty much the same code from the linked issue...

@drashna
Copy link
Member Author

drashna commented Jan 30, 2019

keyevent_t only provides row, column and timing information:

In theory, that's all we need.

uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key)
{
// Read entire word (16bits)
return pgm_read_word(&keymaps[(layer)][(key.row)][(key.col)]);
}

In, fact, all we really need is the keypos_t structure. We could skip everything else.

But it doesn't seem to work properly.

@fauxpark
Copy link
Member

fauxpark commented Jan 30, 2019

This probably isn't related, but I noticed layer_switch_get_layer returns an int8_t instead of uint8_t:

int8_t layer_switch_get_layer(keypos_t key);

Presumably everywhere else is uint8_t, so I doubt this is the root cause.

@drashna
Copy link
Member Author

drashna commented Jan 30, 2019

Yeah, there are a number of cases where this is the case. But yeah, is shouldn't matter. Feel free to correct it though. :)

@fauxpark
Copy link
Member

fauxpark commented Jan 30, 2019

Hm. Another thought: should event->key not be event.key? Neither event nor key are declared as pointers, so (as far as I understand the arrow operator) it does not need to be dereferenced.

@drashna
Copy link
Member Author

drashna commented Jan 30, 2019

I've tried:

uint16_t get_tapping_term(keyevent_t event) {
  switch (keymap_key_to_keycode(layer_switch_get_layer(event.key), event.key)) {

and

uint16_t get_tapping_term(keyevent_t* event) {
  switch (keymap_key_to_keycode(layer_switch_get_layer(event->key), event->key)) {

And the correct versions of the define. Neither way works.

I know the code change itself works, since, if you change the default, it absolutely has an affect. But .... it's some issue with detecting the keycodes.

@fauxpark
Copy link
Member

process_tapping() seems to be able to grab it seemingly perfectly well:

if (WITHIN_TAPPING_TERM(event)) {
if (tapping_key.tap.count == 0) {
if (IS_TAPPING_KEY(event.key) && !event.pressed) {

I notice that IS_TAPPING_KEY(k) surrounds k with parentheses (I'm not well versed enough in C to understand the significance of this, if any):

#define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))

@drashna
Copy link
Member Author

drashna commented Jan 31, 2019

Tried that, doesn't make a difference. z

#define WITHIN_TAPPING_TERM(e)  (TIMER_DIFF_16(e.time, tapping_key.event.time) < get_tapping_term((e)))

@drashna
Copy link
Member Author

drashna commented Jan 31, 2019

Okay, I added some debugging to it, and it looks like the issue is that the column and row are not being outputted correctly.

  xprintf("get_tapping_term (main): ");
  xprintf("col: %i, row: %\n", event.key.col, event.key.row);

is outputting

    get_tapping_term (main) col: 255, row: 255
    get_tapping_term (main) col: 255, row: 255
    get_tapping_term (main) col: 255, row: 255

Which means that it's not getting a valid structure at the time that this is occurring. :(

@fauxpark
Copy link
Member

Is that xprintf truncated for brevity? Cause that does not look right...

@drashna
Copy link
Member Author

drashna commented Jan 31, 2019

It was bad editing :D

But yeah, looks like if I want to fix this, I'll have to convert WITHIN_TAPPING_TERM to an actual function. And hope that works.

@fauxpark
Copy link
Member

KEYEQ is also doing some funky parenthesis stuff:

#define KEYEQ(keya, keyb) ((keya).row == (keyb).row && (keya).col == (keyb).col)

Sorry I can't be of more help right now, I don't have a QMK board in front of me...

@drashna
Copy link
Member Author

drashna commented Jan 31, 2019

Even changing the funky parenthesis stuff didn't affect anything. Using a pointer or not didn't make a difference.

Basically, it's not passing on the information correctly, from what I can tell

@fauxpark
Copy link
Member

fauxpark commented Jan 31, 2019

What if you pass WITHIN_TAPPING_TERM event.key instead? As you said, that's all that's really needed here.

Actually nope, it requires event.time.

@drashna
Copy link
Member Author

drashna commented Jan 31, 2019

Got it! e is wrong. Need to pass tapping_key.event

@drashna
Copy link
Member Author

drashna commented Jan 31, 2019

@fauxpark I tested it, and then to confirm, I dug and dug.

The issue is that "e" is actually "TICK". Which is this:

#define TICK (keyevent_t){ \
.key = (keypos_t){ .row = 255, .col = 255 }, \
.pressed = false, \
.time = (timer_read() | 1) \
}

This is why I was seeing 255 for both the row and column, above.

Thank you for trying to help. At the very lest, it kept me digging into this, for a proper solution. And it was found, so yay!

@drashna
Copy link
Member Author

drashna commented Jan 31, 2019

Now, I have to figure out this:
https://github.com/qmk/qmk_firmware/blob/30bf35b57a0c829ca2385680d9530c829baac2c1/tmk_core/common/action_tapping.c#L108-L121

Specifically, I need to replace #if TAPPING_TERM >= 500 || defined PERMISSIVE_HOLD with something that checks get_tapping_term and see if that's higher than 500.

But I'm .... done for today. Tomorrow's drashna gets to worry about that

@fauxpark
Copy link
Member

Argh, I saw that and didn't even register it! 😆

Looks like the chain goes from all the way up in keyboard_task() -> action_exec() -> action_tapping_process() -> process_tapping(). I got confused by the second call to process_tapping() with all the buffer stuff.

@drashna
Copy link
Member Author

drashna commented Jan 31, 2019

LOL, yeah. But hey, i learned some more QMK, so it's all worth it!

@drashna
Copy link
Member Author

drashna commented Jan 31, 2019

I lied, tomorrow's drashna is off the hook.

Changed one of the functions to check if the tapping term is 500ms or greater (based on the keycode, not the define)

@drashna drashna changed the title [WIP] Custom Tapping Term per key Custom Tapping Term per key Jan 31, 2019
@drashna drashna requested a review from mechmerlin January 31, 2019 03:54
drashna and others added 7 commits March 22, 2019 19:54
Co-Authored-By: drashna <drashna@live.com>
Since we can't be sure that tapping term is actually 500
Clean up function so that users don't need to call the event function, and instead only check the keycode
@drashna drashna force-pushed the custom_tapping_term branch from f932771 to 45d6d25 Compare March 23, 2019 02:54
@ezuk
Copy link
Contributor

ezuk commented Apr 5, 2019

👍 from me on the docs!

@jackhumbert jackhumbert merged commit 5701b75 into qmk:master Apr 5, 2019
@jackhumbert
Copy link
Member

Thanks :)

@drashna drashna deleted the custom_tapping_term branch April 5, 2019 20:03
drashna added a commit to drashna/qmk_firmware that referenced this pull request Apr 9, 2019
* Add customizable tapping terms

* Add Documentation

* Fix function

* Fixes

* It's not a pointer

* Add debugging output

* Update documentation to be at least vaguely accurate

* Use `get_tapping_term(tapping_key.event)` instead

`e` doesn't include column and row information, properly. It registers as 255, regardless of the actual keypress.

However `tapping_key.event` actually gives the correct column and row information.  It appears be the correct structure to use. 

In fact, it looks like the issue is that `e` is actually the "TICK" structure, as defined in keyboard.h

* Use variable tapping term value rather than define

* Silly drashna - tapping_key.event, not event

* add get_event_keycode() function

* Fix typo

Co-Authored-By: drashna <drashna@live.com>

* Remove post_process_record_quantum since it's the wrong PR

* Update quantum/quantum.c

Co-Authored-By: drashna <drashna@live.com>

* Better handle ifdef statement for permissive hold

Since we can't be sure that tapping term is actually 500

* Update quantum.c comments based on feedback

* Clean up get_tapping_term function

Clean up function so that users don't need to call the event function, and instead only check the keycode

* Add ability to run functionality on and off

* Make ifdef's more compact
danielo515 pushed a commit to danielo515/qmk_firmware that referenced this pull request May 15, 2019
* Add customizable tapping terms

* Add Documentation

* Fix function

* Fixes

* It's not a pointer

* Add debugging output

* Update documentation to be at least vaguely accurate

* Use `get_tapping_term(tapping_key.event)` instead

`e` doesn't include column and row information, properly. It registers as 255, regardless of the actual keypress.

However `tapping_key.event` actually gives the correct column and row information.  It appears be the correct structure to use. 

In fact, it looks like the issue is that `e` is actually the "TICK" structure, as defined in keyboard.h

* Use variable tapping term value rather than define

* Silly drashna - tapping_key.event, not event

* add get_event_keycode() function

* Fix typo

Co-Authored-By: drashna <drashna@live.com>

* Remove post_process_record_quantum since it's the wrong PR

* Update quantum/quantum.c

Co-Authored-By: drashna <drashna@live.com>

* Better handle ifdef statement for permissive hold

Since we can't be sure that tapping term is actually 500

* Update quantum.c comments based on feedback

* Clean up get_tapping_term function

Clean up function so that users don't need to call the event function, and instead only check the keycode

* Add ability to run functionality on and off

* Make ifdef's more compact
shimesaba-type0 pushed a commit to shimesaba-type0/qmk_firmware that referenced this pull request Jun 22, 2019
* Add customizable tapping terms

* Add Documentation

* Fix function

* Fixes

* It's not a pointer

* Add debugging output

* Update documentation to be at least vaguely accurate

* Use `get_tapping_term(tapping_key.event)` instead

`e` doesn't include column and row information, properly. It registers as 255, regardless of the actual keypress.

However `tapping_key.event` actually gives the correct column and row information.  It appears be the correct structure to use. 

In fact, it looks like the issue is that `e` is actually the "TICK" structure, as defined in keyboard.h

* Use variable tapping term value rather than define

* Silly drashna - tapping_key.event, not event

* add get_event_keycode() function

* Fix typo

Co-Authored-By: drashna <drashna@live.com>

* Remove post_process_record_quantum since it's the wrong PR

* Update quantum/quantum.c

Co-Authored-By: drashna <drashna@live.com>

* Better handle ifdef statement for permissive hold

Since we can't be sure that tapping term is actually 500

* Update quantum.c comments based on feedback

* Clean up get_tapping_term function

Clean up function so that users don't need to call the event function, and instead only check the keycode

* Add ability to run functionality on and off

* Make ifdef's more compact
Timbus pushed a commit to Timbus/qmk_firmware that referenced this pull request Jun 23, 2019
* Add customizable tapping terms

* Add Documentation

* Fix function

* Fixes

* It's not a pointer

* Add debugging output

* Update documentation to be at least vaguely accurate

* Use `get_tapping_term(tapping_key.event)` instead

`e` doesn't include column and row information, properly. It registers as 255, regardless of the actual keypress.

However `tapping_key.event` actually gives the correct column and row information.  It appears be the correct structure to use. 

In fact, it looks like the issue is that `e` is actually the "TICK" structure, as defined in keyboard.h

* Use variable tapping term value rather than define

* Silly drashna - tapping_key.event, not event

* add get_event_keycode() function

* Fix typo

Co-Authored-By: drashna <drashna@live.com>

* Remove post_process_record_quantum since it's the wrong PR

* Update quantum/quantum.c

Co-Authored-By: drashna <drashna@live.com>

* Better handle ifdef statement for permissive hold

Since we can't be sure that tapping term is actually 500

* Update quantum.c comments based on feedback

* Clean up get_tapping_term function

Clean up function so that users don't need to call the event function, and instead only check the keycode

* Add ability to run functionality on and off

* Make ifdef's more compact
drashna added a commit that referenced this pull request Jan 10, 2020
ridingqwerty pushed a commit that referenced this pull request Jan 17, 2020
* Fix bug in PERMISSIVE_HOLD check

caused by #5009 (aka, me)

* Remove check for per key
drashna added a commit to zsa/qmk_firmware that referenced this pull request Feb 12, 2020
* Fix bug in PERMISSIVE_HOLD check

caused by qmk#5009 (aka, me)

* Remove check for per key
fdidron pushed a commit to zsa/qmk_firmware that referenced this pull request Feb 14, 2020
* Fix bug in PERMISSIVE_HOLD check

caused by qmk#5009 (aka, me)

* Remove check for per key
HokieGeek pushed a commit to HokieGeek/qmk_firmware that referenced this pull request Feb 21, 2020
* Fix bug in PERMISSIVE_HOLD check

caused by qmk#5009 (aka, me)

* Remove check for per key
fdidron pushed a commit to zsa/qmk_firmware that referenced this pull request Feb 26, 2020
* Fix bug in PERMISSIVE_HOLD check

caused by qmk#5009 (aka, me)

* Remove check for per key
kylekuj pushed a commit to kylekuj/qmk_firmware that referenced this pull request Apr 21, 2020
* Fix bug in PERMISSIVE_HOLD check

caused by qmk#5009 (aka, me)

* Remove check for per key
BorisTestov pushed a commit to BorisTestov/qmk_firmware that referenced this pull request May 23, 2024
* Fix bug in PERMISSIVE_HOLD check

caused by qmk#5009 (aka, me)

* Remove check for per key
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants