commit
3d20fa0aff
@ -0,0 +1,183 @@
|
|||||||
|
# Kaleidoscope-Macros
|
||||||
|
|
||||||
|
Macros are a standard feature on many keyboards and Kaleidoscope-powered ones
|
||||||
|
are no exceptions. Macros are a way to have a single key-press do a whole lot of
|
||||||
|
things under the hood: conventionally, macros play back a key sequence, but with
|
||||||
|
Kaleidoscope, there is much more we can do. Nevertheless, playing back a
|
||||||
|
sequence of events is still the primary use of macros.
|
||||||
|
|
||||||
|
Playing back a sequence means that when we press a macro key, we can have it
|
||||||
|
play pretty much any sequence. It can type some text for us, or invoke a
|
||||||
|
complicated shortcut - the possibilities are endless!
|
||||||
|
|
||||||
|
In Kaleidoscope, macros are implemented via this plugin. You can define upto 256 macros.
|
||||||
|
|
||||||
|
## Using the plugin
|
||||||
|
|
||||||
|
To use the plugin, we need to include the header, tell the firmware to `use` the
|
||||||
|
plugin, place macros on the keymap, and create a special handler function
|
||||||
|
(`macroAction`) that will tell the plugin what shall happen when macro keys are
|
||||||
|
pressed. It is best illustrated with an example:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
#include <Kaleidoscope.h>
|
||||||
|
#include <Kaleidoscope-Macros.h>
|
||||||
|
|
||||||
|
// Give a name to the macros!
|
||||||
|
enum {
|
||||||
|
MACRO_MODEL01,
|
||||||
|
MACRO_HELLO,
|
||||||
|
MACRO_SPECIAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Somewhere in the keymap:
|
||||||
|
M(MACRO_MODEL01), M(MACRO_HELLO), M(MACRO_SPECIAL)
|
||||||
|
|
||||||
|
// later in the Sketch:
|
||||||
|
const macro_t *macroAction(uint8_t macroIndex, uint8_t keyState) {
|
||||||
|
switch (macroIndex) {
|
||||||
|
case MACRO_MODEL01:
|
||||||
|
return MACRODOWN(I(25),
|
||||||
|
D(LeftShift), T(M), U(LeftShift), T(O), T(D), T(E), T(L),
|
||||||
|
T(Spacebar),
|
||||||
|
W(100),
|
||||||
|
T(0), T(1) );
|
||||||
|
case MACRO_HELLO:
|
||||||
|
if (keyToggledOn(keyState)) {
|
||||||
|
return Macros.type(PSTR("Hello "), PSTR("world!"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MACRO_SPECIAL:
|
||||||
|
if (keyToggledOn(keyState)) {
|
||||||
|
// Do something special
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return MACRO_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
KALEIDOSCOPE_INIT_PLUGINS(Macros);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Kaleidoscope.setup ();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Keymap markup
|
||||||
|
|
||||||
|
### `M(id)`
|
||||||
|
|
||||||
|
> Places a macro key on the keymap, with the `id` number (0 to 255) as identifier. Whenever this key
|
||||||
|
> has to be handled, the `macroAction` overrideable function will be called,
|
||||||
|
> with the identifier and key state as arguments.
|
||||||
|
>
|
||||||
|
> It is recommended to give a *name* to macro ids, by using an `enum`.
|
||||||
|
|
||||||
|
## Plugin methods
|
||||||
|
|
||||||
|
The plugin provides a `Macros` object, with the following methods and properties available:
|
||||||
|
|
||||||
|
### `.play(macro)`
|
||||||
|
|
||||||
|
> Plays back a macro, where a macro is a sequence created with the `MACRO()`
|
||||||
|
> helper discussed below. This method will be used by the plugin to play back
|
||||||
|
> the result of the `macroAction()` method, but is used rarely otherwise.
|
||||||
|
>
|
||||||
|
> The `macro` argument must be a sequence created with the `MACRO()` helper!
|
||||||
|
|
||||||
|
### `.type(strings...)`
|
||||||
|
|
||||||
|
> In cases where we only want to type some strings, it is far more convenient to
|
||||||
|
> use this method: we do not have to use the `MACRO()` helper, but just give
|
||||||
|
> this one a set of strings, and it will type them for us on the keyboard. We
|
||||||
|
> can use as many strings as we want, and all of them will be typed in order.
|
||||||
|
>
|
||||||
|
> Each string is limited to a sequence of printable ASCII characters. No
|
||||||
|
> international symbols, or unicode, or anything like it: just plain ASCII.
|
||||||
|
>
|
||||||
|
> Each of `strings` arguments must also reside in program memory, and the
|
||||||
|
> easiest way to do that is to wrap the string in a `PSTR()` helper. See the
|
||||||
|
> program code at the beginning of this documentation for an example!
|
||||||
|
|
||||||
|
### `.row`, `.col`
|
||||||
|
|
||||||
|
> The `row` and `col` properties describe the physical position a macro was
|
||||||
|
> triggered from if it was triggered by a key. The playback functions
|
||||||
|
> do not use these properties, but they are available, would one want to create
|
||||||
|
> a macro that needs to know which key triggered it.
|
||||||
|
>
|
||||||
|
> When the macro was not triggered by a key the value of these properties are
|
||||||
|
> unspecified.
|
||||||
|
|
||||||
|
## Macro helpers
|
||||||
|
|
||||||
|
Macros need to be able to simulate key down and key up events for any key - even
|
||||||
|
keys that may not be on the keymap otherwise. For this reason and others, we
|
||||||
|
need to define them in a special way, using the `MACRO` helper (or its
|
||||||
|
`MACRODOWN()` variant, see below):
|
||||||
|
|
||||||
|
### `MACRO(steps...)`
|
||||||
|
|
||||||
|
> Defines a macro, that is built up from `steps` (explained below). The plugin
|
||||||
|
> will iterate through the sequence, and re-play the steps in order.
|
||||||
|
>
|
||||||
|
> Note: In older versions of the Macros plugin, the sequence of steps had to end
|
||||||
|
> with a special step called END. This is no longer required. Existing macros
|
||||||
|
> that end with END will still work correctly, but new code should not use END;
|
||||||
|
> usage of END is deprecated.
|
||||||
|
|
||||||
|
### `MACRODOWN(steps...)`
|
||||||
|
|
||||||
|
> The same as the `MACRO()` helper above, but it will create a special sequence,
|
||||||
|
> where the steps are only played back when the triggering key was just pressed.
|
||||||
|
> That is, the macro will not be performed when the key is released, or held, or
|
||||||
|
> not pressed at all.
|
||||||
|
>
|
||||||
|
> Use this over `MACRO()` when you only want to perform an action when the key
|
||||||
|
> actuates, and no action should be taken when it is held, released, or when it
|
||||||
|
> is not pressed at all. For a lot of macros that emit a sequence without any
|
||||||
|
> other side effects, `MACRODOWN()` is usually the better choice.
|
||||||
|
>
|
||||||
|
> Can only be used from the `macroAction()` overrideable method.
|
||||||
|
|
||||||
|
## `MACRO` steps
|
||||||
|
|
||||||
|
Macro steps can be divided into two groups:
|
||||||
|
|
||||||
|
### Delays
|
||||||
|
|
||||||
|
* `I(millis)`: Sets the interval between steps to `millis`. By default, there is
|
||||||
|
no delay between steps, and they are played back as fast as possible. Useful
|
||||||
|
when we want to see the macro being typed, or need to slow it down, to allow
|
||||||
|
the host to process it.
|
||||||
|
* `W(millis)`: Waits for `millis` milliseconds. For dramatic effects.
|
||||||
|
|
||||||
|
### Key events
|
||||||
|
|
||||||
|
Key event steps have three variants: one that prefixes its argument with `Key_`,
|
||||||
|
one that does not, and a third that allows for a more compact - but also more
|
||||||
|
limited - representation. The first are the `D`, `U`, and `T` variants, the
|
||||||
|
second are `Dr`, `Ur`, and `Tr`, and the last variant are `Dc`, `Uc`, and `Tc`.
|
||||||
|
In most cases, one is likely use normal keys for the steps, so the `D`, `U`, and
|
||||||
|
`T` steps apply the `Key_` prefix. This allows us to write `MACRO(T(X))` instead
|
||||||
|
of `MACRO(Tr(Key_X))` - making the macro definition shorter, and more readable.
|
||||||
|
|
||||||
|
The compact variant (`Dc`, `Uc`, and `Tc`) prefix the argument with `Key_` too,
|
||||||
|
but unlike `D`, `U`, and `T`, they ignore the `flags` component of the key, and
|
||||||
|
as such, are limited to ordinary keys. Mouse keys, consumer- or system keys are
|
||||||
|
not supported by this compact representation.
|
||||||
|
|
||||||
|
* `D(key)`, `Dr(key)`, `Dc(key)`: Simulates a key being pressed (pushed down).
|
||||||
|
* `U(key)`, `Ur(key)`, `Uc(key)`: Simulates a key being released (going up).
|
||||||
|
* `T(key)`, `Tr(key)`, `Tc(key)`: Simulates a key being tapped (pressed first, then released).
|
||||||
|
|
||||||
|
## Overrideable methods
|
||||||
|
|
||||||
|
### `macroAction(macroIndex, keyState)`
|
||||||
|
|
||||||
|
> The `macroAction` method is the brain of the macro support in Kaleidoscope:
|
||||||
|
> this function tells the plugin what sequence to play when given a macro index
|
||||||
|
> and a key state.
|
||||||
|
>
|
||||||
|
> It should return a macro sequence, or `MACRO_NONE` if nothing is to be played
|
||||||
|
> back.
|
@ -0,0 +1,19 @@
|
|||||||
|
/* Kaleidoscope-Macros - Macro keys for Kaleidoscope.
|
||||||
|
* Copyright (C) 2017-2018 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "kaleidoscope/plugin/Macros.h"
|
@ -0,0 +1,244 @@
|
|||||||
|
/* Kaleidoscope-Macros - Macro keys for Kaleidoscope.
|
||||||
|
* Copyright (C) 2017-2018 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Kaleidoscope-Macros.h"
|
||||||
|
#include "kaleidoscope/hid.h"
|
||||||
|
|
||||||
|
__attribute__((weak))
|
||||||
|
const macro_t *macroAction(uint8_t macroIndex, uint8_t keyState) {
|
||||||
|
return MACRO_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace plugin {
|
||||||
|
|
||||||
|
MacroKeyEvent Macros_::active_macros[];
|
||||||
|
byte Macros_::active_macro_count;
|
||||||
|
byte Macros_::row, Macros_::col;
|
||||||
|
|
||||||
|
void playMacroKeyswitchEvent(Key key, uint8_t keyswitch_state) {
|
||||||
|
handleKeyswitchEvent(key, UNKNOWN_KEYSWITCH_LOCATION, keyswitch_state | INJECTED);
|
||||||
|
|
||||||
|
kaleidoscope::hid::sendKeyboardReport();
|
||||||
|
kaleidoscope::hid::sendMouseReport();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void readKeyCodeAndPlay(const macro_t *macro_p, uint8_t flags, uint8_t keyStates) {
|
||||||
|
Key key;
|
||||||
|
key.flags = flags;
|
||||||
|
key.keyCode = pgm_read_byte(macro_p++);
|
||||||
|
|
||||||
|
if (keyIsPressed(keyStates)) {
|
||||||
|
playMacroKeyswitchEvent(key, IS_PRESSED);
|
||||||
|
}
|
||||||
|
if (keyWasPressed(keyStates)) {
|
||||||
|
playMacroKeyswitchEvent(key, WAS_PRESSED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Macros_::play(const macro_t *macro_p) {
|
||||||
|
macro_t macro = MACRO_ACTION_END;
|
||||||
|
uint8_t interval = 0;
|
||||||
|
uint8_t flags;
|
||||||
|
|
||||||
|
if (!macro_p)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
switch (macro = pgm_read_byte(macro_p++)) {
|
||||||
|
case MACRO_ACTION_STEP_INTERVAL:
|
||||||
|
interval = pgm_read_byte(macro_p++);
|
||||||
|
break;
|
||||||
|
case MACRO_ACTION_STEP_WAIT: {
|
||||||
|
uint8_t wait = pgm_read_byte(macro_p++);
|
||||||
|
delay(wait);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MACRO_ACTION_STEP_KEYDOWN:
|
||||||
|
flags = pgm_read_byte(macro_p++);
|
||||||
|
readKeyCodeAndPlay(macro_p++, flags, IS_PRESSED);
|
||||||
|
break;
|
||||||
|
case MACRO_ACTION_STEP_KEYUP:
|
||||||
|
flags = pgm_read_byte(macro_p++);
|
||||||
|
readKeyCodeAndPlay(macro_p++, flags, WAS_PRESSED);
|
||||||
|
break;
|
||||||
|
case MACRO_ACTION_STEP_TAP:
|
||||||
|
flags = pgm_read_byte(macro_p++);
|
||||||
|
readKeyCodeAndPlay(macro_p++, flags, IS_PRESSED | WAS_PRESSED);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MACRO_ACTION_STEP_KEYCODEDOWN:
|
||||||
|
readKeyCodeAndPlay(macro_p++, 0, IS_PRESSED);
|
||||||
|
break;
|
||||||
|
case MACRO_ACTION_STEP_KEYCODEUP:
|
||||||
|
readKeyCodeAndPlay(macro_p++, 0, WAS_PRESSED);
|
||||||
|
break;
|
||||||
|
case MACRO_ACTION_STEP_TAPCODE:
|
||||||
|
readKeyCodeAndPlay(macro_p++, 0, IS_PRESSED | WAS_PRESSED);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MACRO_ACTION_END:
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Key ascii_to_key_map[] PROGMEM = {
|
||||||
|
// 0x21 - 0x30
|
||||||
|
LSHIFT(Key_1),
|
||||||
|
LSHIFT(Key_Quote),
|
||||||
|
LSHIFT(Key_3),
|
||||||
|
LSHIFT(Key_4),
|
||||||
|
LSHIFT(Key_5),
|
||||||
|
LSHIFT(Key_7),
|
||||||
|
Key_Quote,
|
||||||
|
LSHIFT(Key_9),
|
||||||
|
LSHIFT(Key_0),
|
||||||
|
LSHIFT(Key_8),
|
||||||
|
LSHIFT(Key_Equals),
|
||||||
|
Key_Comma,
|
||||||
|
Key_Minus,
|
||||||
|
Key_Period,
|
||||||
|
Key_Slash,
|
||||||
|
Key_0,
|
||||||
|
|
||||||
|
// 0x3a ... 0x40
|
||||||
|
LSHIFT(Key_Semicolon),
|
||||||
|
Key_Semicolon,
|
||||||
|
LSHIFT(Key_Comma),
|
||||||
|
Key_Equals,
|
||||||
|
LSHIFT(Key_Period),
|
||||||
|
LSHIFT(Key_Slash),
|
||||||
|
LSHIFT(Key_2),
|
||||||
|
|
||||||
|
// 0x5b ... 0x60
|
||||||
|
Key_LeftBracket,
|
||||||
|
Key_Backslash,
|
||||||
|
Key_RightBracket,
|
||||||
|
LSHIFT(Key_6),
|
||||||
|
LSHIFT(Key_Minus),
|
||||||
|
Key_Backtick,
|
||||||
|
|
||||||
|
// 0x7b ... 0x7e
|
||||||
|
LSHIFT(Key_LeftBracket),
|
||||||
|
LSHIFT(Key_Backslash),
|
||||||
|
LSHIFT(Key_RightBracket),
|
||||||
|
LSHIFT(Key_Backtick),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Key Macros_::lookupAsciiCode(uint8_t ascii_code) {
|
||||||
|
Key key = Key_NoKey;
|
||||||
|
|
||||||
|
switch (ascii_code) {
|
||||||
|
case 0x08 ... 0x09:
|
||||||
|
key.keyCode = Key_Backspace.keyCode + ascii_code - 0x08;
|
||||||
|
break;
|
||||||
|
case 0x0A:
|
||||||
|
key.keyCode = Key_Enter.keyCode;
|
||||||
|
break;
|
||||||
|
case 0x1B:
|
||||||
|
key.keyCode = Key_Escape.keyCode;
|
||||||
|
break;
|
||||||
|
case 0x20:
|
||||||
|
key.keyCode = Key_Spacebar.keyCode;
|
||||||
|
break;
|
||||||
|
case 0x21 ... 0x30:
|
||||||
|
key.raw = pgm_read_word(&ascii_to_key_map[ascii_code - 0x21]);
|
||||||
|
break;
|
||||||
|
case 0x31 ... 0x39:
|
||||||
|
key.keyCode = Key_1.keyCode + ascii_code - 0x31;
|
||||||
|
break;
|
||||||
|
case 0x3A ... 0x40:
|
||||||
|
key.raw = pgm_read_word(&ascii_to_key_map[ascii_code - 0x3A + 16]);
|
||||||
|
break;
|
||||||
|
case 0x41 ... 0x5A:
|
||||||
|
key.flags = SHIFT_HELD;
|
||||||
|
key.keyCode = Key_A.keyCode + ascii_code - 0x41;
|
||||||
|
break;
|
||||||
|
case 0x5B ... 0x60:
|
||||||
|
key.raw = pgm_read_word(&ascii_to_key_map[ascii_code - 0x5B + 23]);
|
||||||
|
break;
|
||||||
|
case 0x61 ... 0x7A:
|
||||||
|
key.keyCode = Key_A.keyCode + ascii_code - 0x61;
|
||||||
|
break;
|
||||||
|
case 0x7B ... 0x7E:
|
||||||
|
key.raw = pgm_read_word(&ascii_to_key_map[ascii_code - 0x7B + 29]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
const macro_t *Macros_::type(const char *string) {
|
||||||
|
while (true) {
|
||||||
|
uint8_t ascii_code = pgm_read_byte(string++);
|
||||||
|
if (!ascii_code)
|
||||||
|
break;
|
||||||
|
|
||||||
|
Key key = lookupAsciiCode(ascii_code);
|
||||||
|
|
||||||
|
|
||||||
|
if (key.raw == Key_NoKey.raw)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
playMacroKeyswitchEvent(key, IS_PRESSED);
|
||||||
|
playMacroKeyswitchEvent(key, WAS_PRESSED);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return MACRO_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventHandlerResult Macros_::onKeyswitchEvent(Key &mappedKey, byte row, byte col, uint8_t keyState) {
|
||||||
|
if (mappedKey.flags != (SYNTHETIC | IS_MACRO))
|
||||||
|
return EventHandlerResult::OK;
|
||||||
|
|
||||||
|
byte key_id = (row * COLS) + col;
|
||||||
|
addActiveMacroKey(mappedKey.keyCode, key_id, keyState);
|
||||||
|
|
||||||
|
return EventHandlerResult::EVENT_CONSUMED;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventHandlerResult Macros_::afterEachCycle() {
|
||||||
|
active_macro_count = 0;
|
||||||
|
|
||||||
|
return EventHandlerResult::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventHandlerResult Macros_::beforeReportingState() {
|
||||||
|
for (byte i = 0; i < active_macro_count; ++i) {
|
||||||
|
if (active_macros[i].key_id == 0xFF) {
|
||||||
|
// i.e. UNKNOWN_KEYSWITCH_LOCATION
|
||||||
|
row = 0xFF;
|
||||||
|
col = 0xFF;
|
||||||
|
} else {
|
||||||
|
row = active_macros[i].key_id / COLS;
|
||||||
|
col = active_macros[i].key_id % COLS;
|
||||||
|
}
|
||||||
|
const macro_t *m = macroAction(active_macros[i].key_code,
|
||||||
|
active_macros[i].key_state);
|
||||||
|
Macros.play(m);
|
||||||
|
}
|
||||||
|
return EventHandlerResult::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kaleidoscope::plugin::Macros_ Macros;
|
@ -0,0 +1,86 @@
|
|||||||
|
/* Kaleidoscope-Macros - Macro keys for Kaleidoscope.
|
||||||
|
* Copyright (C) 2017-2018 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Kaleidoscope.h>
|
||||||
|
|
||||||
|
#include "kaleidoscope/plugin/Macros/MacroKeyDefs.h"
|
||||||
|
#include "kaleidoscope/plugin/Macros/MacroSteps.h"
|
||||||
|
|
||||||
|
const macro_t *macroAction(uint8_t macroIndex, uint8_t keyState);
|
||||||
|
|
||||||
|
#if !defined(MAX_CONCURRENT_MACROS)
|
||||||
|
#define MAX_CONCURRENT_MACROS 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct MacroKeyEvent {
|
||||||
|
byte key_code;
|
||||||
|
byte key_id;
|
||||||
|
byte key_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace plugin {
|
||||||
|
|
||||||
|
class Macros_ : public kaleidoscope::Plugin {
|
||||||
|
public:
|
||||||
|
Macros_(void) {}
|
||||||
|
|
||||||
|
static MacroKeyEvent active_macros[MAX_CONCURRENT_MACROS];
|
||||||
|
static byte active_macro_count;
|
||||||
|
static void addActiveMacroKey(byte key_code, byte key_id, byte key_state) {
|
||||||
|
// If we've got too many active macros, give up:
|
||||||
|
if (active_macro_count >= MAX_CONCURRENT_MACROS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
active_macros[active_macro_count].key_code = key_code;
|
||||||
|
active_macros[active_macro_count].key_id = key_id;
|
||||||
|
active_macros[active_macro_count].key_state = key_state;
|
||||||
|
++active_macro_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventHandlerResult onKeyswitchEvent(Key &mappedKey, byte row, byte col, uint8_t keyState);
|
||||||
|
EventHandlerResult beforeReportingState();
|
||||||
|
EventHandlerResult afterEachCycle();
|
||||||
|
|
||||||
|
void play(const macro_t *macro_p);
|
||||||
|
|
||||||
|
/* What follows below, is a bit of template magic that allows us to use
|
||||||
|
Macros.type() with any number of arguments, without having to use a
|
||||||
|
sentinel. See the comments on Kaleidoscope.use() for more details - this is
|
||||||
|
the same trick.
|
||||||
|
*/
|
||||||
|
inline const macro_t *type() {
|
||||||
|
return MACRO_NONE;
|
||||||
|
}
|
||||||
|
const macro_t *type(const char *string);
|
||||||
|
template <typename... Strings>
|
||||||
|
const macro_t *type(const char *first, Strings&&... strings) {
|
||||||
|
type(first);
|
||||||
|
return type(strings...);
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte row, col;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Key lookupAsciiCode(uint8_t ascii_code);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern kaleidoscope::plugin::Macros_ Macros;
|
@ -0,0 +1,31 @@
|
|||||||
|
/* Kaleidoscope-Macros - Macro keys for Kaleidoscope.
|
||||||
|
* Copyright (C) 2017-2018 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define IS_MACRO B00100000
|
||||||
|
|
||||||
|
#define M(n) (Key){ n, KEY_FLAGS|SYNTHETIC|IS_MACRO }
|
||||||
|
#define Key_macroKey1 M(1)
|
||||||
|
#define Key_macroKey2 M(2)
|
||||||
|
#define Key_macroKey3 M(3)
|
||||||
|
#define Key_macroKey4 M(4)
|
||||||
|
#define Key_macroKey5 M(5)
|
||||||
|
#define Key_macroKey6 M(6)
|
||||||
|
#define Key_macroKey7 M(7)
|
||||||
|
#define Key_macroKey8 M(8)
|
||||||
|
#define Key_macroKey9 M(9)
|
||||||
|
#define Key_macroKey10 M(10)
|
@ -0,0 +1,54 @@
|
|||||||
|
/* Kaleidoscope-Macros - Macro keys for Kaleidoscope.
|
||||||
|
* Copyright (C) 2017-2018 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MACRO_ACTION_END,
|
||||||
|
|
||||||
|
MACRO_ACTION_STEP_INTERVAL,
|
||||||
|
MACRO_ACTION_STEP_WAIT,
|
||||||
|
|
||||||
|
MACRO_ACTION_STEP_KEYDOWN,
|
||||||
|
MACRO_ACTION_STEP_KEYUP,
|
||||||
|
MACRO_ACTION_STEP_TAP,
|
||||||
|
|
||||||
|
MACRO_ACTION_STEP_KEYCODEDOWN,
|
||||||
|
MACRO_ACTION_STEP_KEYCODEUP,
|
||||||
|
MACRO_ACTION_STEP_TAPCODE,
|
||||||
|
} MacroActionStepType;
|
||||||
|
|
||||||
|
typedef uint8_t macro_t;
|
||||||
|
|
||||||
|
#define MACRO_NONE 0
|
||||||
|
#define MACRO(...) ({static const macro_t __m[] PROGMEM = { __VA_ARGS__, MACRO_ACTION_END }; &__m[0]; })
|
||||||
|
#define MACRODOWN(...) (keyToggledOn(keyState) ? MACRO(__VA_ARGS__) : MACRO_NONE)
|
||||||
|
|
||||||
|
#define I(n) MACRO_ACTION_STEP_INTERVAL, n
|
||||||
|
#define W(n) MACRO_ACTION_STEP_WAIT, n
|
||||||
|
|
||||||
|
#define Dr(k) MACRO_ACTION_STEP_KEYDOWN, (k).flags, (k).keyCode
|
||||||
|
#define D(k) Dr(Key_ ## k)
|
||||||
|
#define Ur(k) MACRO_ACTION_STEP_KEYUP, (k).flags, (k).keyCode
|
||||||
|
#define U(k) Ur(Key_ ## k)
|
||||||
|
#define Tr(k) MACRO_ACTION_STEP_TAP, (k).flags, (k).keyCode
|
||||||
|
#define T(k) Tr(Key_ ## k)
|
||||||
|
|
||||||
|
#define Dc(k) MACRO_ACTION_STEP_KEYCODEDOWN, (Key_ ## k).keyCode
|
||||||
|
#define Uc(k) MACRO_ACTION_STEP_KEYCODEUP, (Key_ ## k).keyCode
|
||||||
|
#define Tc(k) MACRO_ACTION_STEP_TAPCODE, (Key_ ## k).keyCode
|
||||||
|
|
||||||
|
__attribute__((deprecated("END is no longer required to end macros"))) const MacroActionStepType END = MACRO_ACTION_END;
|
Loading…
Reference in new issue