/* Kaleidoscope - Firmware for computer input devices * Copyright (C) 2013-2021 Keyboard.io, Inc. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 3. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include // for PROGMEM #include // for uint8_t, int8_t #include "kaleidoscope/KeyAddr.h" // for KeyAddr #include "kaleidoscope/KeyEvent.h" // for KeyEvent #include "kaleidoscope/device/device.h" // for Device #include "kaleidoscope/key_defs.h" // for Key #include "kaleidoscope/keymaps.h" // IWYU pragma: keep #include "kaleidoscope/macro_helpers.h" // for __NL__ #include "kaleidoscope_internal/device.h" // for device #include "kaleidoscope_internal/shortname.h" // for _INIT_HID_GETSH... #include "kaleidoscope_internal/sketch_exploration/sketch_exploration.h" // for _INIT_SKETCH_EX... // clang-format off #define START_KEYMAPS __NL__ \ constexpr Key keymaps_linear[][kaleidoscope_internal::device.matrix_rows * kaleidoscope_internal::device.matrix_columns] PROGMEM = { #define END_KEYMAPS __NL__ \ }; __NL__ \ uint8_t layer_count __NL__ \ = sizeof(keymaps_linear) / sizeof(*keymaps_linear); __NL__ \ __NL__ \ _INIT_SKETCH_EXPLORATION __NL__ \ _INIT_HID_GETSHORTNAME // Macro for defining the keymap. This should be used in the sketch // file (*.ino) to define the keymap[] array that holds the user's // layers. It also computes the number of layers in that keymap. #define KEYMAPS(layers...) __NL__ \ START_KEYMAPS __NL__ \ layers __NL__ \ END_KEYMAPS // clang-format on extern uint8_t layer_count; namespace kaleidoscope { class Layer_ { public: Layer_() {} void setup(); // There are two lookup functions here, for historical reasons. Previously, // Kaleidoscope would need to look up a value for each active keyswitch in // every cycle, and pass that value on to the "event" handlers. Most of these // lookups were for keys that were being held, not toggled on or off. Because // these lookups were so frequent, a cache was used to speed them up. // // We no longer need to look up these values every cycle for keys that are // held, because Kaleidoscope now only acts on key events that are actual // toggle-on or toggle-off events, so the speed of the lookups here is not so // critical. However, the old "live composite keymap" cache was also used by // some plugins (and certain parts of Kaleidoscope itself) to override values // in the keymap, and these plugins might use calls to `Layer.lookup()`, // expecting to get the override values. // // Therefore, the `lookup()` function below first checks the `live_keys` array // (the keyboard state array that has replaced the keymap cache). This should // allow old code to continue working, until all the associated code (mostly // the `onKeyswitchEvent()` handlers) is replaced, at which point we can // remove dependence on `live_keys` entirely from this class. // // The `Runtime.lookupKey()` function replaces this one, for plugins that // still want to do this same check. static Key lookupOnActiveLayer(KeyAddr key_addr) { uint8_t layer = active_layer_keymap_[key_addr.toInt()]; return (*getKey)(layer, key_addr); } static uint8_t lookupActiveLayer(KeyAddr key_addr) { return active_layer_keymap_[key_addr.toInt()]; } static void activate(uint8_t layer); static void deactivate(uint8_t layer); static void activateNext(); static void deactivateMostRecent(); static void move(uint8_t layer); static uint8_t mostRecent() { return active_layers_[active_layer_count_ - 1]; } static bool isActive(uint8_t layer); static void handleLayerKeyEvent(const KeyEvent &event); typedef Key (*GetKeyFunction)(uint8_t layer, KeyAddr key_addr); static GetKeyFunction getKey; static Key getKeyFromPROGMEM(uint8_t layer, KeyAddr key_addr); static void updateActiveLayers(void); private: using forEachHandler = void (*)(uint8_t index, uint8_t layer); public: static void forEachActiveLayer(forEachHandler h); private: static uint8_t active_layer_count_; static int8_t active_layers_[31]; static uint8_t active_layer_keymap_[kaleidoscope_internal::device.numKeys()]; }; } // namespace kaleidoscope extern kaleidoscope::Layer_ Layer;