# Both palm keys together to trigger a separate layer?

**URL:** <https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669>\
**Category:** Help and Getting Started\
**Created:** [November 3, 2017, 3:20am UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669 "2017-11-03T03:20:57Z")\
**Posts on this page:** 15\
**Page:** 2

<div class="post-metadata">

**Author:** ![jesse](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/jesse/32/361_2.png) [@jesse](https://community.keyboard.io/u/jesse)\
**Post date:** [November 10, 2017, 9:40pm UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/21 "2017-11-10T21:40:06Z")

</div>

> [@merlin](#):
>
> That way Kemap\_MomentaryNext (and potentially other things) could include a check to make sure it doesn’t read past the end of the array.

Could someone open a ticket for this bug?

---

<div class="post-metadata">

**Author:** ![merlin](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/merlin/32/3416_2.png) [@merlin](https://community.keyboard.io/u/merlin)\
**Post date:** [November 10, 2017, 9:44pm UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/22 "2017-11-10T21:44:15Z")

</div>

There’s another thread where I suggested an idea that would make use of a [variable that records and makes the number of layers accessible](https://community.keyboard.io/t/how-to-get-the-number-of-defined-layers/647/6?u=merlin).

---

<div class="post-metadata">

**Author:** ![bjn](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/bjn/32/5337_2.png) [@bjn](https://community.keyboard.io/u/bjn)\
**Post date:** [November 10, 2017, 9:53pm UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/23 "2017-11-10T21:53:32Z")

</div>

I mapped the palm keys on my numpad layer (only) to `ShiftToLayer(FUNCTION)` and everything seems to be OK. Thanks!

---

<div class="post-metadata">

**Author:** ![merlin](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/merlin/32/3416_2.png) [@merlin](https://community.keyboard.io/u/merlin)\
**Post date:** [November 10, 2017, 10:03pm UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/24 "2017-11-10T22:03:17Z")

</div>

> [@jesse](#):
>
> Could someone open a ticket for this bug?

I’ll take responsibility for writing this up and submitting an issue for it, unless someone else gets to it before me (later tonight). It’s in layers.cpp: Layer.next()…

---

<div class="post-metadata">

**Author:** ![merlin](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/merlin/32/3416_2.png) [@merlin](https://community.keyboard.io/u/merlin)\
**Post date:** [November 12, 2017, 6:10pm UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/25 "2017-11-12T18:10:19Z")

</div>

So, I went ahead and opened a pull request (two, actually: both [Model01-Firmware #35](https://github.com/keyboardio/Model01-Firmware/pull/35) & [Kaleidoscope #244](https://github.com/keyboardio/Kaleidoscope/pull/244)), but the only way I can think of to fix this is to introduce a new constant that stores the number of layers defined in `keymaps[]` in the sketch file. Unfortunately, the compiler/linker has defeated my attempts to get Kaleidoscope to build. When I build it from Model01-Firmware, everything looks fine, but if I try to build Kaleidoscope independently, it quits with an “undefined reference” error. I’ve tried lots of variations, but nothing works. The real mystery to me is that [`keymaps[]`](https://github.com/gedankenexperimenter/Model01-Firmware/blob/aab179b1f6f88851ebae56f6f823a05982dedd94/Model01-Firmware.ino#L127), which is defined in the same place as the new variable [`LayerCount`](https://github.com/gedankenexperimenter/Model01-Firmware/blob/aab179b1f6f88851ebae56f6f823a05982dedd94/Model01-Firmware.ino#L182) in my PR doesn’t cause the same error. I’m totally baffled by the fact that one works, but the other causes an error.

I’m hoping that someone more familiar with the build system in particular, or the C++ compiler & linker in general can help me make sense of this.

---

<div class="post-metadata">

**Author:** ![merlin](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/merlin/32/3416_2.png) [@merlin](https://community.keyboard.io/u/merlin)\
**Post date:** [November 13, 2017, 2:22am UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/26 "2017-11-13T02:22:47Z")

</div>

After some trial and error, I figured out the build problem. I hadn’t updated the example sketches. So in order to make the change I’m proposing, all of the example sketches in every plugin would need to add that one line too…

---

<div class="post-metadata">

**Author:** ![merlin](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/merlin/32/3416_2.png) [@merlin](https://community.keyboard.io/u/merlin)\
**Post date:** [November 29, 2017, 6:40pm UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/27 "2017-11-29T18:40:02Z")

</div>

Update for everyone in this discussion:

There are a couple of changes that have recently been merged into the `master` branch of `Kaleidoscope` that address issues that were discussed here.

1. @algernon [mentioned](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/14) that it was necessary to have `Key_KeymapNext_Momentary` on both the layer that was being switched _from_ and the one above it in order to keep the upper layer from getting stuck on. This should no longer be the case, as of [Kaleidoscope #247](https://github.com/keyboardio/Kaleidoscope/pull/247).

2. @andrewg [pointed out](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/9) that use of `Key_KeymapNext_Momentary` could result in reading past the end of the `keymaps[]` array into uninitialized memory. There is now a fix for that, as well, in [#244](https://github.com/keyboardio/Kaleidoscope/pull/244), but it only works if the sketch file is updated to use the new `KEYMAPS()` macro to define the keymap, instead of initializing `keymaps[]` directly.

To use the new macro to define a keymap, all you need to do is replace this line in your sketch file:

```auto
const Key keymaps[][ROWS][COLS] PROGMEM = {

```

…with this:

```auto
KEYMAPS(

```

…and replace the closing brace line:

```auto
};

```

…with this:

```auto
)

```

That makes a variable storing the number of defined layers available to Kaleidoscope, so it can stop trying to read past the end of the array.

---

<div class="post-metadata">

**Author:** ![tchernomax](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/tchernomax/32/1008_2.png) [@tchernomax](https://community.keyboard.io/u/tchernomax)\
**Post date:** [March 24, 2018, 2:41pm UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/28 "2018-03-24T14:41:03Z")

</div>

I also wanted to implement that (separate layer for both palm key).  
I didn’t want to use the magiccombo plugin as the function are trigger only it the combo is the only thing that it’s pressed.  
For example, I want the “both palm key” layer to be triggered even if “a+left fn+right fn” is pressed.  
Also magiccombo are triggered by a loop.

My (simplified) layer stack is: NORMAL, LEFT\_FN, RIGHT\_FN, LEFT\_AND\_RIGHT\_FN

At first I was just using ShiftToLayer(LEFT\_FN) and ShiftToLayer(RIGHT\_FN) in the NORMAL layer. And ShiftToLayer(LEFT\_AND\_RIGHT\_FN) in the LEFT\_FN and RIGHT\_FN layers.

It works but have a huge drawback.  
When pressed **left** fn+right fn then release **left** fn the LEFT\_AND\_RIGHT\_FN layer stay active, instead of switching to the RIGHT\_FN as the right fn is still held.

What I do now: I use Key\_KeymapNext\_Momentary and Key\_KeymapNextNext\_Momentary (a dirty hack).  
The left fn is configure to increment the layer by one, the right fn increment the layer by two.

so:  
NORMAL+left fn → 0+1 → LEFT\_FN  
NORMAL+right fn → 0+2 → RIGHT\_FN  
NORMAL+left fn+right fn → 0+1+2 → LEFT\_AND\_RIGHT\_FN

Here is the Key\_KeymapNextNext\_Momentary **dirty** hack:

```auto
diff --git a/src/key_defs_keymaps.h b/src/key_defs_keymaps.h
index c0dda0f..87997dd 100644
--- a/src/key_defs_keymaps.h
+++ b/src/key_defs_keymaps.h
@@ -15,6 +15,7 @@ static const uint8_t LAYER_SHIFT_OFFSET = 42;

 #define KEYMAP_PREVIOUS 33
 #define KEYMAP_NEXT 34
+#define KEYMAP_NEXT_NEXT 35

 #define Key_Keymap0 (Key) { KEYMAP_0, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP }
@@ -31,9 +32,9 @@ static const uint8_t LAYER_SHIFT_OFFSET = 42;
 #define Key_Keymap5_Momentary (Key){ KEYMAP_5 + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP }

 #define Key_KeymapNext_Momentary (Key) { KEYMAP_NEXT + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP }
+#define Key_KeymapNextNext_Momentary (Key) { KEYMAP_NEXT_NEXT + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP }
 #define Key_KeymapPrevious_Momentary (Key) { KEYMAP_PREVIOUS + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP }

-
 /** Lock/Unlock layer `n`.
  *
  * When locking a layer, it will remain active until unlocked explicitly. `n`
diff --git a/src/layers.cpp b/src/layers.cpp
index 389d8e9..9b646bc 100644
--- a/src/layers.cpp
+++ b/src/layers.cpp
@@ -23,6 +23,16 @@ static void handleKeymapKeyswitchEvent(Key keymapEntry, uint8_t keyState) {
     uint8_t target = keymapEntry.keyCode - LAYER_SHIFT_OFFSET;

     switch (target) {
+ case KEYMAP_NEXT_NEXT:
+ if (keyToggledOn(keyState)) {
+ Layer.next();
+ Layer.next();
+ } else if (keyToggledOff(keyState)) {
+ Layer.previous();
+ Layer.previous();
+ }
+ break;
+
     case KEYMAP_NEXT:
       if (keyToggledOn(keyState))
         Layer.next();

```

(How to decrement the layer by two without calling Layer.previous() two times ?)

And now it works as expected.  
left fn+right fn **-** left fn → RIGHT\_FN

---

<div class="post-metadata">

**Author:** ![bjn](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/bjn/32/5337_2.png) [@bjn](https://community.keyboard.io/u/bjn)\
**Post date:** [March 6, 2023, 10:41pm UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/29 "2023-03-06T22:41:18Z")

</div>

I’m now trying to do the same thing on my Model 100, via firmware (I’m not using Chrysalis).

I have my main layer, then function, then doublefunction, then numpad, as before. On my main layer I have both function keys set to `Key_KeymapNext_Momentary`. On the other layers they’re set to transparent.

But whether I’m holding one or both function keys, I’m getting the function layer behaviour, not the doublefunction layer behaviour.

Any ideas as to what might be wrong? Does anyone else have this method working on Model 100?

---

<div class="post-metadata">

**Author:** ![tchernomax](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/tchernomax/32/1008_2.png) [@tchernomax](https://community.keyboard.io/u/tchernomax)\
**Post date:** [March 7, 2023, 7:34pm UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/30 "2023-03-07T19:34:21Z")

</div>

I am now using another approach ; I use macro.

basically:

```auto
enum {
	MACRO_KEY_LF,
	MACRO_KEY_RF,
};
 
const macro_t *macroAction(uint8_t macro_id, KeyEvent &event) {
	enum {
		LAYER_NORM,
		LAYER_LF,
		LAYER_RF,
		LAYER_LF_PLUS_RF,
	};

	switch (macro_id) {

		case MACRO_KEY_LF:
			if (keyToggledOn(event.state)) {
				if (Layer.isActive(LAYER_RF)) {
					Layer.deactivate(LAYER_RF);
					Layer.activate(LAYER_LF_PLUS_RF);
				} else {
					Layer.activate(LAYER_LF);
				}
			} else if (keyToggledOff(event.state)) {
				if (Layer.isActive(LAYER_LF_PLUS_RF)) {
					Layer.deactivate(LAYER_LF_PLUS_RF);
					Layer.activate(LAYER_RF);
				} else {
					Layer.deactivate(LAYER_LF);
				}
			}
			break;

		case MACRO_KEY_RF:
			if (keyToggledOn(event.state)) {
				if (Layer.isActive(LAYER_LF)) {
					Layer.deactivate(LAYER_LF);
					Layer.activate(LAYER_LF_PLUS_RF);
				} else {
					Layer.activate(LAYER_RF);
				}
			} else if (keyToggledOff(event.state)) {
				if (Layer.isActive(LAYER_LF_PLUS_RF)) {
					Layer.deactivate(LAYER_LF_PLUS_RF);
					Layer.activate(LAYER_LF);
				} else {
					Layer.deactivate(LAYER_RF);
				}
			}
			break;
	}

	return MACRO_NONE;
}

```

(this code need to be adapt to your ino file… but you get the idea).

---

<div class="post-metadata">

**Author:** ![bjn](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/bjn/32/5337_2.png) [@bjn](https://community.keyboard.io/u/bjn)\
**Post date:** [March 7, 2023, 8:00pm UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/31 "2023-03-07T20:00:16Z")

</div>

Ah so you have separate layers for leftfn and rightfn, and then separate again for both.

I imagine I could do something very similar to what you suggested with a shared function layer for just one palm key being held down. Thank you for sharing your code.

I think I’ll hold back on trying that just for now though, since `Key_KeymapNext_Momentary` seems like it _ought_ to work; it feels like a bug, whether in my code or in Kaleidoscope. Having said that, maybe I’ll ask on the Kaleidoscope tracker…

---

<div class="post-metadata">

**Author:** ![merlin](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/merlin/32/3416_2.png) [@merlin](https://community.keyboard.io/u/merlin)\
**Post date:** [March 8, 2023, 6:01am UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/32 "2023-03-08T06:01:00Z")

</div>

> [@bjn](#):
>
> I think I’ll hold back on trying that just for now though, since `Key_KeymapNext_Momentary` seems like it _ought_ to work; it feels like a bug, whether in my code or in Kaleidoscope.

Yes, looking at the code, this does appear to be a bug in the treatment of `Key_KeymapNext_Momentary`. Would you mind submitting a Kaleidoscope issue for this?

---

<div class="post-metadata">

**Author:** ![bjn](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/bjn/32/5337_2.png) [@bjn](https://community.keyboard.io/u/bjn)\
**Post date:** [March 13, 2023, 10:09pm UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/33 "2023-03-13T22:09:33Z")

</div>

It’s working again; thanks @merlin!

---

<div class="post-metadata">

**Author:** ![eirvandelden](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/eirvandelden/32/2680_2.png) [@eirvandelden](https://community.keyboard.io/u/eirvandelden)\
**Post date:** [January 10, 2025, 6:12pm UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/34 "2025-01-10T18:12:21Z")

</div>

So what is currently the advised way to get a separate layer for left palm, right palm and both palm keys?

If I understand correctly, only using Key\_KeymapNext\_Momentary would make pressing only left or right palm key move to the same layer, instead of its own layer correct?

Is it then safer/“better” to use the `Key_KeymapNextNext_Momentary` or the macro posted by tchernomax (and would that need the macros plugin)?

---

<div class="post-metadata">

**Author:** ![rumpel](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/rumpel/32/626_2.png) [@rumpel](https://community.keyboard.io/u/rumpel)\
**Post date:** [January 22, 2025, 7:41pm UTC](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669/35 "2025-01-22T19:41:24Z")

</div>

> [@eirvandelden](#):
>
> So what is currently the advised way to get a separate layer for left palm, right palm and both palm keys?

It’s actually quite simple to solve without using plugins. I have been using the following approach since 2017 and never had trouble.

It requires 4 layers at minimum, your base layer, the left FN layer (LFN), right FN layer (RFN), and another layer that gets activated when left FN and right FN are pressed (let’s call it layer LFNandRFN).

```auto
  [BASE] = KEYMAP_STACKED
  ( ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ ,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ ,
   ShiftToLayer(LFN), // shift to LFN, nothing special here

   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ ,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ ,
   ShiftToLayer(RFN)), // shift to RFN, nothing special here

  [LFN] = KEYMAP_STACKED
  ( ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ ,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ ,
   ___, // this key is pressed down right now, which is why we are in layer LFN

   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ ,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ ,
   ShiftToLayer(LFNandRFN)), // pressing the right FN key while we're in LFN will shift us to layer LFNandRFN

  [RFN] = KEYMAP_STACKED
  ( ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ ,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ ,
   ShiftToLayer(LFNandRFN), // pressing the left FN key while we're in RFN will shift us to layer LFN and RFN

   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ ,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ ,
   ___), // this key is perssed right now, which is why we are in layer RFN

  [LFNandRFN] = KEYMAP_STACKED
  ( ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ ,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ ,
   ___,

   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ , ___,___ ,
   ___,___ , ___,___ , ___,___ , ___,
   ___,___ , ___,___ ,
   ___),

```

So no matter in which order you press both FN keys, you’ll always end up in the LFNandRFN layer.

[Previous page](https://community.keyboard.io/t/both-palm-keys-together-to-trigger-a-separate-layer/669.md?page=1)
