# OS dependent keymap?

**URL:** <https://community.keyboard.io/t/os-dependent-keymap/712>\
**Category:** Programming\
**Created:** [November 7, 2017, 5:00am UTC](https://community.keyboard.io/t/os-dependent-keymap/712 "2017-11-07T05:00:43Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![kajsa.anderson](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/kajsa.anderson/32/346_2.png) [@kajsa.anderson](https://community.keyboard.io/u/kajsa.anderson)\
**Post date:** [November 7, 2017, 5:00am UTC](https://community.keyboard.io/t/os-dependent-keymap/712/1 "2017-11-07T05:00:43Z")

</div>

Is it possible for a key to send one keycode for Windows and another for Mac? Is the firmware able to be aware of which OS it’s connected to? I seem to recall some discussions around this, but that was very early on, before most of us started working with Kaleidoscope.

Alternately, can I program some key on a function layer to swap the mappings of two keys?

My use case is this - when I’m gaming on my Windows box at home, I want to swap Alt and GUI, but when I’m at work on a Mac, I want them in the default positions. Eventually, when I get my second board, this will be a non-issue.

---

<div class="post-metadata">

**Author:** ![algernon](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/algernon/32/4404_2.png) [@algernon](https://community.keyboard.io/u/algernon)\
**Post date:** [November 7, 2017, 7:14am UTC](https://community.keyboard.io/t/os-dependent-keymap/712/2 "2017-11-07T07:14:50Z")

</div>

> [@kajsa.anderson](#):
>
> Is it possible for a key to send one keycode for Windows and another for Mac? Is the firmware able to be aware of which OS it’s connected to? I seem to recall some discussions around this, but that was very early on, before most of us started working with Kaleidoscope.

There is the `HostOS` plugin that can try to guess the OS, but it’s just a guess, and may very well be wrong. We can’t ask the OS, and it doesn’t tell us either. The plugin worked well for me when trying on Linux and Windows, but I’ve heard it doesn’t detect MacOS properly. (It also doesn’t support any of the BSDs)

> [@kajsa.anderson](#):
>
> Alternately, can I program some key on a function layer to swap the mappings of two keys?

Yes! If you disable the guesser part of `HostOS`, the plugin can help here, and you can pair it with a few macros.

> [@kajsa.anderson](#):
>
> My use case is this - when I’m gaming on my Windows box at home, I want to swap Alt and GUI, but when I’m at work on a Mac, I want them in the default positions.

```c++
static void AltGUI(uint8_t macro_index, uint8_t key_state) {
  if (HostOS.os() == kaleidoscope::hostos::OSX) {
    if (macro_index == M_ALTGUI) {
      handleKeyswitchEvent(Key_LeftAlt, Macros.row, Macros.col,
                           key_state | INJECTED);
    } else if (macro_index == M_GUIALT) {
      handleKeyswitchEvent(Key_LeftGUI, Macros.row, Macros.col, 
                           key_state | INJECTED);
    }
  } else if (HostOS.os() == kaleidoscope::hostos::WINDOWS) {
    if (macro_index == M_ALTGUI) {
      handleKeyswitchEvent(Key_LeftGUI, Macros.row, Macros.col, 
                           key_state | INJECTED);
    } else if (macro_index == M_GUIALT) {
      handleKeyswitchEvent(Key_LeftAlt, Macros.row, Macros.col, 
                           key_state | INJECTED);
    }
  }
}

void osSwitch(uint8_t key_state) {
  if (!keyToggledOn(key_state))
    return;

  if (HostOS.os() == kaleidoscope::hostos::OSX) {
    HostOS.os(kaleidoscope::hostos::WINDOWS);
  } else {
    HostOS.os(kaleidoscope::hostos::OSX);
  }
}

```

Something along these lines.

---

<div class="post-metadata">

**Author:** ![algernon](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/algernon/32/4404_2.png) [@algernon](https://community.keyboard.io/u/algernon)\
**Post date:** [November 7, 2017, 7:19am UTC](https://community.keyboard.io/t/os-dependent-keymap/712/3 "2017-11-07T07:19:33Z")

</div>

In the long run, it would make sense to have a plugin do this for us, and allow one to just specify a map like:

```auto
static const Key osMap[][4] PROGMEM = {
  // key, Linux, OSX, Windows
  { Key_LeftAlt, Key_LeftAlt, Key_LeftGUI, Key_LeftAlt },
  { NULL, NULL, NULL }
}

```

And then the plugin would automatically replace any `Key_LeftAlts` with either a left alt or a left GUI, depending on the OS. Could perhaps make it simpler by dropping the first item, and requiring the user to set a base OS.

---

<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 7, 2017, 12:57pm UTC](https://community.keyboard.io/t/os-dependent-keymap/712/4 "2017-11-07T12:57:14Z")

</div>

The trouble with that approach is that it would only replace keycodes; it would not allow the user to redefine _keys_ based on the OS. I’d much rather have an array for each alternate OS based on row and column indexing such that I could redefine just one of multiple keys for `Key_LeftAlt` (for example), without globally affecting every `Key_LeftAlt` in every layer. Entries could be like this:

```
{OS_MAC, 2, 4, Key_LeftGui}
{OS_LINUX, 1, 3, Key_RightAlt}

```

…with the first element an enum for the OS (or have a separate array per OS for more efficient code), then row & column numbers for the keyswitch, then the value of the override keycode (or macro).

---

<div class="post-metadata">

**Author:** ![lasse](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/lasse/32/185_2.png) [@lasse](https://community.keyboard.io/u/lasse)\
**Post date:** [November 19, 2017, 11:44pm UTC](https://community.keyboard.io/t/os-dependent-keymap/712/5 "2017-11-19T23:44:10Z")

</div>

Would it be possible to have OS specific layers?

Then maybe the OS layers could be half-empty and just override the keys I want to change and the fall through to the default layer (fn / querty / numlock)?

Maybe have different enums for keymaps depending on the OS?

---

<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 20, 2017, 1:32am UTC](https://community.keyboard.io/t/os-dependent-keymap/712/6 "2017-11-20T01:32:26Z")

</div>

there are a lot of things we could do. What would be most helpful to me is for people to explain their specific use cases and pain points. Once we have a better handle on the problem we are trying to solve (as opposed to some cool technical solutions that may or may not solve various Users issues) will be in a much better place to figure out a design that’s going to work well for everybody.

---

<div class="post-metadata">

**Author:** ![buc](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/buc/32/523_2.png) [@buc](https://community.keyboard.io/u/buc)\
**Post date:** [November 21, 2017, 7:33pm UTC](https://community.keyboard.io/t/os-dependent-keymap/712/7 "2017-11-21T19:33:44Z")

</div>

There’s one thing that I would love a solution to, but I expect is unsolvable. It is by no means a problem unique to the Model 01.

I want a way to unify many keyboard shortcuts (particularly browser shortcuts) between my Macbook and my Windows box. Games often allow ways to remap controls, but browsers and other applications rarely do.

As a specific example: to refresh a page in Chrome on my Macbook the shortcut is cmd-R, while on my Windows box that same shortcut is F5 or ctrl-R. If I type cmd-R on Windows the OS brings up a dialog box that steals keyboard focus.

But then there’s the added difficulty that I use (g)vim on both systems, as well as ssh into various other system types, so I _need_ ctrl to always be ctrl.

So I suppose I’m looking at something where on Windows cmd acts like ctrl unless some other modifier (e.g. fn) is pressed. Then all I have to do is start using the “mac” shortcuts with my windows applications and something else entirely for the windows-specific shortcuts (such as cmd-shift-esc).

But that couldn’t be default because it would fail the POLA test for anyone who doesn’t split their time between Windows and macOS (and maybe even most of those).

---

<div class="post-metadata">

**Author:** ![kajsa.anderson](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/kajsa.anderson/32/346_2.png) [@kajsa.anderson](https://community.keyboard.io/u/kajsa.anderson)\
**Post date:** [November 21, 2017, 7:45pm UTC](https://community.keyboard.io/t/os-dependent-keymap/712/8 "2017-11-21T19:45:00Z")

</div>

> [@buc](#):
>
> I want a way to unify many keyboard shortcuts (particularly browser shortcuts) between my Macbook and my Windows box.

That’s pretty much exactly my use case, with IntelliJ IDEA thrown into the mix. My plan was to swap GUI & Alt; I have some shortcuts that use both, but many of the ones that only use one use cmd on mac and alt on windows.

---

<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 21, 2017, 8:17pm UTC](https://community.keyboard.io/t/os-dependent-keymap/712/9 "2017-11-21T20:17:37Z")

</div>

I’m planning to use a combination of macros and global OS setting to deal with this problem. There’s an example of how to do this in the [AppSwitcher](https://github.com/keyboardio/Kaleidoscope/tree/master/examples/AppSwitcher) example in Kaleidoscope.

---

<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 21, 2017, 8:19pm UTC](https://community.keyboard.io/t/os-dependent-keymap/712/10 "2017-11-21T20:19:49Z")

</div>

Note: that example isn’t fully-fleshed out; it only contains the code for macOS, but it’s fairly straightforward how to add another OS or two.

---

<div class="post-metadata">

**Author:** ![polsonst](https://avatars.discourse-cdn.com/v4/letter/p/a587f6/32.png) [@polsonst](https://community.keyboard.io/u/polsonst)\
**Post date:** [July 6, 2018, 6:00pm UTC](https://community.keyboard.io/t/os-dependent-keymap/712/11 "2018-07-06T18:00:48Z")

</div>

On my own Mac PCs the system interprets ctrl as cmd and vice versa; this is an option in system preferences. That works ok for me, but since I tell keyboardio what my hostos is anyway, I wonder if I can make keyboardio switch just the ctrl and cmd keys depending on the os. I can see how I might do this using alternative keymaps, but it would be bizarre to switch an entire keymap to just change three keys.

Can I define my own alias key codes and change the definitions of those key codes on the fly with a macro?

---

<div class="post-metadata">

**Author:** ![algernon](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/algernon/32/4404_2.png) [@algernon](https://community.keyboard.io/u/algernon)\
**Post date:** [July 6, 2018, 7:03pm UTC](https://community.keyboard.io/t/os-dependent-keymap/712/12 "2018-07-06T19:03:59Z")

</div>

> [@polsonst](#):
>
> I wonder if I can make keyboardio switch just the ctrl and cmd keys depending on the os.

> [@polsonst](#):
>
> Can I define my own alias key codes and change the definitions of those key codes on the fly with a macro?

It’s definitely doable! Something along these lines:

```c++
namespace kaleidoscope {
class MacOSControl : public kaleidoscope::Plugin {
public:
  MacOSControl () {}

  EventHandlerResult onKeyswitchEvent(Key &mappedKey, byte row, byte col, 
                                      uint8_t keyState) {
    if (::HostOS.os() != kaleidoscope::hostos::OSX)
      return EventHandlerResult::OK;

    switch (mappedKey.raw) {
    case Key_LeftControl.raw:
      mappedKey = Key_LeftGui;
      break;
    case Key_LeftGui.raw:
      mappedKey = Key_LeftControl;
      break;
    case Key_RightControl.raw:
      mappedKey = Key_RightGui;
      break;
    case Key_LeftGui.raw:
      mappedKey = Key_RightControl;
      break;
    }
    return EventHandlerResult::OK;
  }
};
}

kaleidoscope::MacOSControl MacOSControl;

KALEIDOSCOPE_INIT_PLUGINS(MacOSControl, ....);

```

Something along these lines. The idea is that we create a tiny plugin that watches which keys are pressed, and if `HostOS` is set to OSX, does the appropriate swapping, otherwise leaves them alone. So on your keymap, you’d use the non-OSX keys. It’s also possible to do it the other way around with little change.

Do note that I still have trouble following which key is what on OSX, so the above example may very well require some tuning.

The same thing could be accomplished with a macro too, I think, but this approach is lighter, and I think more reliable. If it works, that is. I haven’t tested it yet. O:)

---

<div class="post-metadata">

**Author:** ![polsonst](https://avatars.discourse-cdn.com/v4/letter/p/a587f6/32.png) [@polsonst](https://community.keyboard.io/u/polsonst)\
**Post date:** [July 6, 2018, 7:51pm UTC](https://community.keyboard.io/t/os-dependent-keymap/712/13 "2018-07-06T19:51:46Z")

</div>

I understand that, I think. I’m going to try it. Thanks!

---

<div class="post-metadata">

**Author:** ![nevd](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/nevd/32/1307_2.png) [@nevd](https://community.keyboard.io/u/nevd)\
**Post date:** [July 22, 2018, 7:54pm UTC](https://community.keyboard.io/t/os-dependent-keymap/712/14 "2018-07-22T19:54:36Z")

</div>

Looking to do something very similar for CMD/ALT for OSX/Windows.

When I tried the example code I get an error about being able to reference the .raw,

Do I need to #include something else to enable this functionality?

```auto
error: accessing 'kaleidoscope::Key::raw' member instead of initialized 'kaleidoscope::Key::<anonymous>' member in constant expression                                                                                                                            
  case Key_LeftControl.raw:

```

---

<div class="post-metadata">

**Author:** ![algernon](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/algernon/32/4404_2.png) [@algernon](https://community.keyboard.io/u/algernon)\
**Post date:** [July 23, 2018, 4:26am UTC](https://community.keyboard.io/t/os-dependent-keymap/712/15 "2018-07-23T04:26:08Z")

</div>

> [@nevd](#):
>
> ```plaintext
> error: accessing 'kaleidoscope::Key::raw' member instead of initialized 
> 'kaleidoscope::Key::' member in constant expression case 
> Key_LeftControl.raw:
> 
> ```

Oops. It seems we need to do something about `Key_*` so they work like this again. There’s an existing PR which I will need to revisit… until then, you can use `if/else` instead:

```c++
    if (mappedKey == Key_LeftControl)
        mappedKey = Key_LeftGui;
    else if (mappedKey == Key_LeftGui)
        mappedKey = Key_LeftControl;
    else if (mappedKey == Key_RightControl)
        mappedKey = Key_RightGui;
    else if (mappedKey == Key_LeftGui)
        mappedKey = Key_RightControl;

```

Replace the `switch` statement in the original with this, and that should work.

---

<div class="post-metadata">

**Author:** ![nevd](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/nevd/32/1307_2.png) [@nevd](https://community.keyboard.io/u/nevd)\
**Post date:** [July 23, 2018, 9:37pm UTC](https://community.keyboard.io/t/os-dependent-keymap/712/16 "2018-07-23T21:37:18Z")

</div>

Thanks again, I have got it building at least and I have adapted for my use case, I will apply it tomorrow when I am near my Ki/oM01 again!

---

<div class="post-metadata">

**Author:** ![nevd](https://yyz1.discourse-cdn.com/flex031/user_avatar/community.keyboard.io/nevd/32/1307_2.png) [@nevd](https://community.keyboard.io/u/nevd)\
**Post date:** [August 4, 2018, 5:45pm UTC](https://community.keyboard.io/t/os-dependent-keymap/712/17 "2018-08-04T17:45:39Z")

</div>

Edit: Given up attempting to use HostOS, using separate layers for different OS with a key to flip between them.

I am having some trouble with the basic logic of HostOS detection, I am able to effect the change I want but not automatically. My code fragment looks like this:

```auto
namespace kaleidoscope {
class GuiAlt : public kaleidoscope::Plugin {
public:
     GuiAlt () {}
     EventHandlerResult onKeyswitchEvent(Key &amp;mappedKey, byte row, byte 
col, uint8_t keyState) {
         if (HostOS.os() == kaleidoscope::hostos::OSX) {
             return EventHandlerResult::OK;
         }
         else {
             if (mappedKey == Key_LeftGui)
                 mappedKey = Key_LeftAlt;
             else if (mappedKey == Key_RightGui)
                 mappedKey = Key_RightAlt;
             else if (mappedKey == Key_LeftAlt)
                 mappedKey = Key_LeftGui;
             else if (mappedKey == Key_RightAlt)
                 mappedKey = Key_RightGui;
             return EventHandlerResult::OK;
         }
     }
};
}

```

I have tried it exactly as you posted and _many_ variations in between. The only way I can make it work is when I am at work I switch the == to a != and that does flip the behaviour. Not sure if there is something functionally wrong with the very basic if/else or I have not gotten hostos setup correctly.

This is what I have in my sketch to facilitate the use of HostOS:

```auto
#include "Kaleidoscope-HostOS.h"
#include "Kaleidoscope/HostOS-select.h"
#define KALEIDOSCOPE_HOSTOS_GUESSER 1

KALEIDOSCOPE_INIT_PLUGINS(
  BootGreetingEffect,
  LEDControl,
  LEDOff,
  HostOS,
  Sand,
  Macros,
  MouseKeys,
  HostPowerManagement,
  Qukeys,
  TapDance,
  OneShot,
  EscapeOneShot,
  ActiveModColorEffect,
  GuiAlt
);

```
