commit
b128ed6234
@ -0,0 +1,246 @@
|
||||
# Kaleidoscope-MouseKeys
|
||||
|
||||
Have you ever wanted to control the mouse cursor from the comfort of your
|
||||
keyboard? With this plugin, you can. While it may not replace the mouse in all
|
||||
situations, there are plenty of cases where one will not have to lift their
|
||||
hands off the keyboard just to nudge the mouse cursor away a little.
|
||||
|
||||
Of course, there are a lot more one can do with the plugin than to nudge the
|
||||
cursor! Mouse keys are provided for all four *and* diagonal movement; mouse
|
||||
buttons; and a unique warping mechanism too. And not only these: the speed of
|
||||
the cursor, the mouse wheel, and that of acceleration can all be configured to
|
||||
match one's desired behaviour.
|
||||
|
||||
## Using the plugin
|
||||
|
||||
To use the plugin, simply include the header in your Sketch, tell the firmware
|
||||
to use the `MouseKeys` object, and place mouse keys on your keymap. It is best
|
||||
illustrated with an example:
|
||||
|
||||
```c++
|
||||
#include <Kaleidoscope.h>
|
||||
#include <Kaleidoscope-MouseKeys.h>
|
||||
|
||||
// Somewhere in the keymap:
|
||||
Key_mouseUp, Key_mouseDn, Key_mouseL, Key_mouseR,
|
||||
Key_mouseBtnL, Key_mouseBtnR
|
||||
|
||||
KALEIDOSCOPE_INIT_PLUGINS(MouseKeys);
|
||||
|
||||
void setup() {
|
||||
Kaleidoscope.setup ();
|
||||
}
|
||||
```
|
||||
|
||||
## Keys provided by the plugin
|
||||
|
||||
The plugin provides a number of keys one can put on the keymap, that allow
|
||||
control of the mouse. They can be divided into a few groups:
|
||||
|
||||
### Cursor movement
|
||||
|
||||
The simplest set of keys are the mouse cursor movement keys. These move the
|
||||
cursor one direction or the other, with speed and acceleration factored in. When
|
||||
a mouse cursor movement key is held down, it will move `.speed` pixels each
|
||||
`.speedDelay` milliseconds without acceleration. But when `.accelSpeed` is
|
||||
non-zero (and it is not zero by default,
|
||||
see [below](#accelspeed-and-acceldelay)), the speed will increase by
|
||||
`.accelSpeed` every `.accelDelay` milliseconds. Thus, unless configured
|
||||
otherwise, holding a direction will move that way at increasing speed.
|
||||
|
||||
One can hold more than one key down at the same time, and the cursor will move
|
||||
towards a direction that is the combination of the keys held. For example,
|
||||
holding the "mouse up" and "mouse right" keys together will move the cursor
|
||||
diagonally up and right.
|
||||
|
||||
The cursor movement keys are as follows:
|
||||
|
||||
* `Key_mouseUp`, `Key_mouseDn`, `Key_mouseL`, `Key_mouseR`: Move the cursor up,
|
||||
down, left, or right, respectively.
|
||||
* `Key_mouseUpL`, `Key_mouseUpR`, `Key_mouseDnL`, `Key_mouseDnR`: Move the
|
||||
cursor up-left, up-right, down-left, down-right, respectively.
|
||||
|
||||
### Scroll wheel
|
||||
|
||||
Controlling the scroll wheel is similarly simple. It does not have acceleration,
|
||||
but one can control the speed with the `.wheelSpeed` and `.wheelDelay`
|
||||
properties (see below).
|
||||
|
||||
* `Key_mouseScrollUp`, `Key_mouseScrollDn`: Scroll the mouse wheel up or down,
|
||||
respectively.
|
||||
* `Key_mouseScrollL`, `Key_mouseScrollR`: Scroll the mouse wheel left or right,
|
||||
respectively.
|
||||
|
||||
### Buttons
|
||||
|
||||
Buttons are even simpler than movement: there is no movement speed, nor
|
||||
acceleration involved. One just presses them.
|
||||
|
||||
* `Key_mouseBtnL`, `Key_mouseBtnM`, `Key_mouseBtnR`, `Key_mouseBtnP`,
|
||||
`Key_mouseBtnN`: The left, middle, right, previous, and next mouse buttons,
|
||||
respectively.
|
||||
|
||||
## Warping
|
||||
|
||||
Warping is one of the most interesting features of the plugin, and is a feature
|
||||
unique to Kaleidoscope, as far as we can tell. The warping keys position the
|
||||
mouse cursor within a sector of the screen on first press, and any subsequent
|
||||
taps will warp within the previously selected sector. For example, pressing the
|
||||
north-west warp key twice will first jump to the middle of the north-west
|
||||
sector of your screen, then select the north-west sector of that, and jump to
|
||||
the middle of it.
|
||||
|
||||
To stop warping, use any other mouse key, or hit the "warp end" key.
|
||||
|
||||
### Warp grid size
|
||||
|
||||
The warp grid size determines how MouseKeys partitions the screen to select the
|
||||
next position to jump to when pressing a warp key. The plugin provides two grid
|
||||
sizes to choose from: a *2x2* grid that splits the screen into quadrants, and a
|
||||
*3x3* grid with nine cells similar to a navigation feature included with some
|
||||
speech recognition software. By default, the plugin splits the screen into the
|
||||
2x2 grid.
|
||||
|
||||
To change the warp grid size, call the plugin's `setWarpGridSize()` method:
|
||||
|
||||
```c++
|
||||
MouseKeys.setWarpGridSize(MOUSE_WARP_GRID_3X3);
|
||||
```
|
||||
|
||||
#### 2x2 grid
|
||||
|
||||
As described above, MouseKeys warps the pointer using a grid model that reflects
|
||||
locations on the screen. By default, the plugin uses a 2x2 grid. To understand
|
||||
how warping works, examine this diagram of a screen split into that 2x2 grid:
|
||||
|
||||
+-----------------------|-----------------------+
|
||||
| | | |
|
||||
| G | tab | |
|
||||
| | | |
|
||||
|-----------|-----------| tab |
|
||||
| | | |
|
||||
| B | esc | |
|
||||
| | | |
|
||||
+-----------------------|-----------------------+
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
| B | esc |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
+-----------------------|-----------------------+
|
||||
|
||||
Each quadrant is labed with a key that, when pressed, moves the mouse pointer
|
||||
to the center of that quadrant. With this layout, pressing <kbd>G</kbd> warps
|
||||
the pointer to the top-left quadant. Then, the plugin "zooms" into that sector
|
||||
with a smaller grid so that the next warp key pressed jumps the pointer more
|
||||
precisely within the sector. In this case, if we press <kbd>esc</kbd> next,
|
||||
the pointer warps to the bottom-right corner within that quadrant.
|
||||
|
||||
The warping keys for the 2x2 grid are the following:
|
||||
|
||||
* `Key_mouseWarpNW`, `Key_mouseWarpNE`, `Key_mouseWarpSW`, `Key_mouseWarpSE`:
|
||||
Warp towards the north-west, north-east, south-west, or south-east quadrants,
|
||||
respectively.
|
||||
* `Key_mouseWarpEnd`: End the warping sequence, resetting it to the default
|
||||
state. Using any of the warping keys after this will start from the whole
|
||||
screen again.
|
||||
|
||||
#### 3x3 grid
|
||||
|
||||
A 3x3 warp grid assigns a key to each of nine sectors of the screen. The next
|
||||
diagram shows a screen with a key label that warps to each sector. As we can
|
||||
see, pressing <kbd>W</kbd> warps the pointer into the top-left sector, and
|
||||
pressing <kbd>V</kbd> warps to the bottom-right corner within that sector:
|
||||
|
||||
+-----------------|-----------------|-----------------+
|
||||
| W | E | R | | |
|
||||
|-----|-----|-----| | |
|
||||
| S | D | F | E | R |
|
||||
|-----|-----|-----| | |
|
||||
| X | C | V | | |
|
||||
+-----------------|-----------------|-----------------+
|
||||
| | | |
|
||||
| | | |
|
||||
| S | D | F |
|
||||
| | | |
|
||||
| | | |
|
||||
+-----------------|-----------------|-----------------+
|
||||
| | | |
|
||||
| | | |
|
||||
| X | C | V |
|
||||
| | | |
|
||||
| | | |
|
||||
+-----------------|-----------------|-----------------+
|
||||
|
||||
To use a 3x3 warp grid, we may need to remap some keys. A suggested warp key
|
||||
mapping is shown below on the left side of a keyboard with a QWERTY layout:
|
||||
|
||||
W | E | R T A - End Warping (Key_mouseWarpEnd)
|
||||
---|---|--- W - Warp NW Sector (Key_mouseWarpNW)
|
||||
A S | D | F G E - Warp N Sector (Key_mouseWarpN)
|
||||
---|---|--- R - Warp NE Sector (Key_mouseWarpNE)
|
||||
X | C | V B S - Warp E Sector (Key_mouseWarpE)
|
||||
D - Warp/Zoom Center (Key_mouseWarpIn)
|
||||
F - Warp W Sector (Key_mouseWarpW)
|
||||
K - Warp SE Sector (Key_mouseWarpSE)
|
||||
C - Warp S Sector (Key_mouseWarpS)
|
||||
V - Warp SW Sector (Key_mouseWarpSW)
|
||||
T - Right Click (Key_mouseBtnR)
|
||||
G - Left Click (Key_mouseBtnL)
|
||||
B - Middle Click (Key_mouseBtnM)
|
||||
|
||||
This example layout replaces the default directional mouse keys and sets the
|
||||
warp keys in a comfortable position for a warp-only configuration. Of course,
|
||||
a Kaleidoscope user may retain the directional keys and map the warp keys
|
||||
elsewhere according to his or her liking.
|
||||
|
||||
A 3x3 warp grid layout contains all of the keys from the 2x2 grid layout with
|
||||
the following additions:
|
||||
|
||||
* `Key_mouseWarpN`, `Key_mouseWarpE`, `Key_mouseWarpS`, `Key_mouseWarpW`:
|
||||
Warp towards the north, east, south, and west sectors, respectively.
|
||||
* `Key_mouseWarpIn`: Warp to the center sector of the grid. The plugin will
|
||||
continue to "zoom" into center of the current cell with each consecutive
|
||||
press of this key.
|
||||
|
||||
## Plugin methods
|
||||
|
||||
The plugin provides a `MouseKeys` object, with the following methods and
|
||||
properties available:
|
||||
|
||||
### `.speed` and `.speedDelay`
|
||||
|
||||
> These two control the speed of the mouse cursor, when a movement key is held.
|
||||
> The former, `.speed`, controls the amount of pixels the cursor moves, when it
|
||||
> has to move, and defaults to 1. The latter, `.speedDelay` is the amount of
|
||||
> time - in milliseconds - to wait between two movements, and defaults to 0, no
|
||||
> delay.
|
||||
|
||||
### `.accelSpeed` and `.accelDelay`
|
||||
|
||||
> These two properties control the speed of acceleration. The former,
|
||||
> `.accelSpeed`, controls how much the speed shall be increased at each step,
|
||||
> while the second, `.accelDelay`, controls how often (in milliseconds)
|
||||
> acceleration should be applied.
|
||||
>
|
||||
> They default to 1 pixel and 50 milliseconds, respectively.
|
||||
|
||||
### `.wheelSpeed` and `.wheelDelay`
|
||||
|
||||
> The last two properties supported by the plugin control the mouse wheel
|
||||
> scrolling speed. The former, `.wheelSpeed`, controls the amount of ticks the
|
||||
> wheel shall scroll, and defaults to 1. The second, `.wheelDelay`, controls the
|
||||
> delay between two scroll events, and defaults to 50 milliseconds.
|
||||
|
||||
### `.setSpeedLimit`
|
||||
|
||||
> This method sets the maximum speed after which acceleration stops.
|
||||
> The default is 127, and the minimum value is 16 (things will not work
|
||||
> properly below 16).
|
||||
|
||||
### `.setWarpGridSize`
|
||||
|
||||
> This method changes the size of the grid used for [warping](#warping). The
|
||||
> following are valid sizes: `MOUSE_WARP_GRID_2X2`, `MOUSE_WARP_GRID_3X3`
|
@ -0,0 +1,19 @@
|
||||
/* Kaleidoscope-MouseKeys - Mouse 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/MouseKeys.h"
|
@ -0,0 +1,21 @@
|
||||
/* Kaleidoscope-MouseKeys - Mouse 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
|
||||
|
||||
#warning The "MouseWrapper.h" header is deprecated, the same functionality is included by default when using <Kaleidoscope-MouseKeys.h>. It can be safely removed.
|
||||
|
||||
#include "kaleidoscope/plugin/MouseKeys/MouseWrapper.h"
|
@ -0,0 +1,190 @@
|
||||
/* Kaleidoscope-MouseKeys - Mouse 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 <Arduino.h>
|
||||
|
||||
#include "Kaleidoscope.h"
|
||||
#include "Kaleidoscope-MouseKeys.h"
|
||||
|
||||
namespace kaleidoscope {
|
||||
namespace plugin {
|
||||
|
||||
uint8_t MouseKeys_::mouseMoveIntent;
|
||||
|
||||
uint8_t MouseKeys_::speed = 1;
|
||||
uint16_t MouseKeys_::speedDelay = 1;
|
||||
|
||||
uint8_t MouseKeys_::accelSpeed = 1;
|
||||
uint16_t MouseKeys_::accelDelay = 64;
|
||||
|
||||
uint8_t MouseKeys_::wheelSpeed = 1;
|
||||
uint16_t MouseKeys_::wheelDelay = 50;
|
||||
|
||||
uint32_t MouseKeys_::accelEndTime;
|
||||
uint32_t MouseKeys_::endTime;
|
||||
uint32_t MouseKeys_::wheelEndTime;
|
||||
|
||||
void MouseKeys_::setWarpGridSize(uint8_t grid_size) {
|
||||
MouseWrapper.warp_grid_size = grid_size;
|
||||
}
|
||||
|
||||
void MouseKeys_::setSpeedLimit(uint8_t speed_limit) {
|
||||
MouseWrapper.speedLimit = speed_limit;
|
||||
}
|
||||
|
||||
void MouseKeys_::scrollWheel(uint8_t keyCode) {
|
||||
if (millis() < wheelEndTime)
|
||||
return;
|
||||
|
||||
wheelEndTime = millis() + wheelDelay;
|
||||
|
||||
if (keyCode & KEY_MOUSE_UP)
|
||||
kaleidoscope::hid::moveMouse(0, 0, wheelSpeed);
|
||||
else if (keyCode & KEY_MOUSE_DOWN)
|
||||
kaleidoscope::hid::moveMouse(0, 0, -wheelSpeed);
|
||||
else if (keyCode & KEY_MOUSE_LEFT)
|
||||
kaleidoscope::hid::moveMouse(0, 0, 0, -wheelSpeed);
|
||||
else if (keyCode & KEY_MOUSE_RIGHT)
|
||||
kaleidoscope::hid::moveMouse(0, 0, 0, wheelSpeed);
|
||||
}
|
||||
|
||||
EventHandlerResult MouseKeys_::afterEachCycle() {
|
||||
kaleidoscope::hid::sendMouseReport();
|
||||
kaleidoscope::hid::releaseAllMouseButtons();
|
||||
mouseMoveIntent = 0;
|
||||
|
||||
return EventHandlerResult::OK;
|
||||
}
|
||||
|
||||
EventHandlerResult MouseKeys_::beforeReportingState() {
|
||||
if (mouseMoveIntent == 0) {
|
||||
MouseWrapper.accelStep = 0;
|
||||
endTime = 0;
|
||||
accelEndTime = 0;
|
||||
return EventHandlerResult::OK;
|
||||
}
|
||||
|
||||
if (millis() < endTime)
|
||||
return EventHandlerResult::OK;
|
||||
|
||||
endTime = millis() + speedDelay;
|
||||
|
||||
int8_t moveX = 0, moveY = 0;
|
||||
|
||||
if (millis() >= accelEndTime) {
|
||||
if (MouseWrapper.accelStep < 255 - accelSpeed) {
|
||||
MouseWrapper.accelStep += accelSpeed;
|
||||
}
|
||||
accelEndTime = millis() + accelDelay;
|
||||
}
|
||||
|
||||
if (mouseMoveIntent & KEY_MOUSE_UP)
|
||||
moveY = -speed;
|
||||
else if (mouseMoveIntent & KEY_MOUSE_DOWN)
|
||||
moveY = speed;
|
||||
|
||||
if (mouseMoveIntent & KEY_MOUSE_LEFT)
|
||||
moveX = -speed;
|
||||
else if (mouseMoveIntent & KEY_MOUSE_RIGHT)
|
||||
moveX = speed;
|
||||
|
||||
MouseWrapper.move(moveX, moveY);
|
||||
|
||||
return EventHandlerResult::OK;
|
||||
}
|
||||
|
||||
EventHandlerResult MouseKeys_::onKeyswitchEvent(Key &mappedKey, byte row, byte col, uint8_t keyState) {
|
||||
if (mappedKey.flags != (SYNTHETIC | IS_MOUSE_KEY))
|
||||
return EventHandlerResult::OK;
|
||||
|
||||
if (mappedKey.keyCode & KEY_MOUSE_BUTTON && !(mappedKey.keyCode & KEY_MOUSE_WARP)) {
|
||||
uint8_t button = mappedKey.keyCode & ~KEY_MOUSE_BUTTON;
|
||||
|
||||
if (keyIsPressed(keyState)) {
|
||||
// Reset warp state on initial mouse button key-down only so we can use
|
||||
// warp keys to drag-and-drop:
|
||||
if (keyToggledOn(keyState)) {
|
||||
MouseWrapper.reset_warping();
|
||||
}
|
||||
|
||||
MouseWrapper.pressButton(button);
|
||||
} else if (keyToggledOff(keyState)) {
|
||||
MouseWrapper.release_button(button);
|
||||
}
|
||||
} else if (!(mappedKey.keyCode & KEY_MOUSE_WARP)) {
|
||||
if (keyToggledOn(keyState)) {
|
||||
endTime = millis() + speedDelay;
|
||||
accelEndTime = millis() + accelDelay;
|
||||
wheelEndTime = 0;
|
||||
}
|
||||
if (keyIsPressed(keyState)) {
|
||||
if (mappedKey.keyCode & KEY_MOUSE_WHEEL) {
|
||||
scrollWheel(mappedKey.keyCode);
|
||||
} else {
|
||||
mouseMoveIntent |= mappedKey.keyCode;
|
||||
}
|
||||
} else if (keyToggledOff(keyState)) {
|
||||
/* If a mouse key toggles off, we want to explicitly stop moving (or
|
||||
* scrolling) in that direction. We want to do this to support use-cases
|
||||
* where we send multiple reports per cycle (such as macros), and can't
|
||||
* rely on the main loop clearing the report for us. We do not want to
|
||||
* clear the whole report either, because we want any other mouse keys
|
||||
* to still have their desired effect. Therefore, we selectively stop
|
||||
* movement or scrolling. */
|
||||
mouseMoveIntent &= ~mappedKey.keyCode;
|
||||
bool x = false, y = false, vWheel = false, hWheel = false;
|
||||
|
||||
if (mappedKey.keyCode & KEY_MOUSE_UP ||
|
||||
mappedKey.keyCode & KEY_MOUSE_DOWN) {
|
||||
if (mappedKey.keyCode & KEY_MOUSE_WHEEL) {
|
||||
vWheel = true;
|
||||
} else {
|
||||
y = true;
|
||||
}
|
||||
} else if (mappedKey.keyCode & KEY_MOUSE_LEFT ||
|
||||
mappedKey.keyCode & KEY_MOUSE_RIGHT) {
|
||||
if (mappedKey.keyCode & KEY_MOUSE_WHEEL) {
|
||||
hWheel = true;
|
||||
} else {
|
||||
x = true;
|
||||
}
|
||||
}
|
||||
|
||||
kaleidoscope::hid::stopMouse(x, y, vWheel, hWheel);
|
||||
}
|
||||
} else if (keyToggledOn(keyState)) {
|
||||
if (mappedKey.keyCode & KEY_MOUSE_WARP && mappedKey.flags & IS_MOUSE_KEY) {
|
||||
MouseWrapper.warp(((mappedKey.keyCode & KEY_MOUSE_WARP_END) ? WARP_END : 0x00) |
|
||||
((mappedKey.keyCode & KEY_MOUSE_UP) ? WARP_UP : 0x00) |
|
||||
((mappedKey.keyCode & KEY_MOUSE_DOWN) ? WARP_DOWN : 0x00) |
|
||||
((mappedKey.keyCode & KEY_MOUSE_LEFT) ? WARP_LEFT : 0x00) |
|
||||
((mappedKey.keyCode & KEY_MOUSE_RIGHT) ? WARP_RIGHT : 0x00));
|
||||
}
|
||||
}
|
||||
|
||||
return EventHandlerResult::EVENT_CONSUMED;
|
||||
}
|
||||
|
||||
EventHandlerResult MouseKeys_::onSetup(void) {
|
||||
MouseWrapper.begin();
|
||||
|
||||
return EventHandlerResult::OK;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
kaleidoscope::plugin::MouseKeys_ MouseKeys;
|
@ -0,0 +1,56 @@
|
||||
/* Kaleidoscope-MouseKeys - Mouse 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/MouseKeys/MouseKeyDefs.h"
|
||||
#include "kaleidoscope/plugin/MouseKeys/MouseWarpModes.h"
|
||||
#include "kaleidoscope/plugin/MouseKeys/MouseWrapper.h"
|
||||
|
||||
namespace kaleidoscope {
|
||||
namespace plugin {
|
||||
class MouseKeys_ : public kaleidoscope::Plugin {
|
||||
public:
|
||||
MouseKeys_(void) {}
|
||||
|
||||
static uint8_t speed;
|
||||
static uint16_t speedDelay;
|
||||
static uint8_t accelSpeed;
|
||||
static uint16_t accelDelay;
|
||||
static uint8_t wheelSpeed;
|
||||
static uint16_t wheelDelay;
|
||||
|
||||
static void setWarpGridSize(uint8_t grid_size);
|
||||
static void setSpeedLimit(uint8_t speed_limit);
|
||||
|
||||
EventHandlerResult onSetup();
|
||||
EventHandlerResult beforeReportingState();
|
||||
EventHandlerResult afterEachCycle();
|
||||
EventHandlerResult onKeyswitchEvent(Key &mappedKey, byte row, byte col, uint8_t keyState);
|
||||
|
||||
private:
|
||||
static uint8_t mouseMoveIntent;
|
||||
static uint32_t endTime;
|
||||
static uint32_t accelEndTime;
|
||||
static uint32_t wheelEndTime;
|
||||
|
||||
static void scrollWheel(uint8_t keyCode);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
extern kaleidoscope::plugin::MouseKeys_ MouseKeys;
|
@ -0,0 +1,67 @@
|
||||
/* Kaleidoscope-MouseKeys - Mouse 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_MOUSE_KEY B00010000
|
||||
|
||||
// Synthetic, not internal
|
||||
#define KEY_MOUSE_BTN_L MOUSE_LEFT // Synthetic key
|
||||
#define KEY_MOUSE_BTN_M MOUSE_MIDDLE // Synthetic key
|
||||
#define KEY_MOUSE_BTN_R MOUSE_RIGHT // Synthetic key
|
||||
#define KEY_MOUSE_BTN_P MOUSE_PREV
|
||||
#define KEY_MOUSE_BTN_N MOUSE_NEXT
|
||||
|
||||
#define KEY_MOUSE_UP B0000001
|
||||
#define KEY_MOUSE_DOWN B0000010
|
||||
#define KEY_MOUSE_LEFT B0000100
|
||||
#define KEY_MOUSE_RIGHT B0001000
|
||||
#define KEY_MOUSE_WHEEL B0010000
|
||||
#define KEY_MOUSE_WARP B0100000
|
||||
#define KEY_MOUSE_WARP_END B1000000
|
||||
// all buttons end warp. also, we're out of bits
|
||||
#define KEY_MOUSE_BUTTON B1000000
|
||||
|
||||
|
||||
#define Key_mouseWarpNW (Key) { KEY_MOUSE_WARP| KEY_MOUSE_UP | KEY_MOUSE_LEFT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseWarpN (Key) { KEY_MOUSE_WARP| KEY_MOUSE_UP, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseWarpNE (Key) { KEY_MOUSE_WARP| KEY_MOUSE_UP | KEY_MOUSE_RIGHT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseWarpW (Key) { KEY_MOUSE_WARP| KEY_MOUSE_LEFT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseWarpIn (Key) { KEY_MOUSE_WARP| KEY_MOUSE_UP | KEY_MOUSE_DOWN, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseWarpE (Key) { KEY_MOUSE_WARP| KEY_MOUSE_RIGHT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseWarpSW (Key) { KEY_MOUSE_WARP| KEY_MOUSE_DOWN | KEY_MOUSE_LEFT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseWarpS (Key) { KEY_MOUSE_WARP| KEY_MOUSE_DOWN, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseWarpSE (Key) { KEY_MOUSE_WARP| KEY_MOUSE_DOWN | KEY_MOUSE_RIGHT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseWarpEnd (Key) { KEY_MOUSE_WARP| KEY_MOUSE_WARP_END, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
|
||||
|
||||
#define Key_mouseUpL (Key) { KEY_MOUSE_UP | KEY_MOUSE_LEFT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseUp (Key) { KEY_MOUSE_UP, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseUpR (Key) { KEY_MOUSE_UP | KEY_MOUSE_RIGHT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseL (Key) { KEY_MOUSE_LEFT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseR (Key) { KEY_MOUSE_RIGHT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseDnL (Key) { KEY_MOUSE_DOWN | KEY_MOUSE_LEFT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseDn (Key) { KEY_MOUSE_DOWN, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseDnR (Key) { KEY_MOUSE_DOWN | KEY_MOUSE_RIGHT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseScrollUp (Key) { KEY_MOUSE_WHEEL | KEY_MOUSE_UP, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseScrollDn (Key) { KEY_MOUSE_WHEEL | KEY_MOUSE_DOWN, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseScrollL (Key) { KEY_MOUSE_WHEEL | KEY_MOUSE_LEFT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseScrollR (Key) { KEY_MOUSE_WHEEL | KEY_MOUSE_RIGHT, KEY_FLAGS|SYNTHETIC|IS_MOUSE_KEY }
|
||||
#define Key_mouseBtnL (Key) { KEY_MOUSE_BUTTON | KEY_MOUSE_BTN_L, KEY_FLAGS | SYNTHETIC | IS_MOUSE_KEY }
|
||||
#define Key_mouseBtnM (Key) { KEY_MOUSE_BUTTON | KEY_MOUSE_BTN_M, KEY_FLAGS | SYNTHETIC | IS_MOUSE_KEY }
|
||||
#define Key_mouseBtnR (Key) { KEY_MOUSE_BUTTON | KEY_MOUSE_BTN_R, KEY_FLAGS | SYNTHETIC | IS_MOUSE_KEY }
|
||||
#define Key_mouseBtnP (Key) { KEY_MOUSE_BUTTON | KEY_MOUSE_BTN_P, KEY_FLAGS | SYNTHETIC | IS_MOUSE_KEY }
|
||||
#define Key_mouseBtnN (Key) { KEY_MOUSE_BUTTON | KEY_MOUSE_BTN_N, KEY_FLAGS | SYNTHETIC | IS_MOUSE_KEY }
|
@ -0,0 +1,26 @@
|
||||
/* Kaleidoscope-MouseKeys - Mouse 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
|
||||
|
||||
// Warp modes determine how the plugin jumps the mouse pointer to a screen
|
||||
// location when pressing a warp key.
|
||||
|
||||
|
||||
// Grid Based - the constant represents the number of cells in a row or column:
|
||||
|
||||
#define MOUSE_WARP_GRID_2X2 2
|
||||
#define MOUSE_WARP_GRID_3X3 3
|
@ -0,0 +1,182 @@
|
||||
/* Kaleidoscope-MouseKeys - Mouse 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/>.
|
||||
*/
|
||||
|
||||
|
||||
// Mouse-related methods
|
||||
//
|
||||
//
|
||||
#include "kaleidoscope/plugin/MouseKeys/MouseWrapper.h"
|
||||
#include "kaleidoscope/hid.h"
|
||||
|
||||
namespace kaleidoscope {
|
||||
namespace plugin {
|
||||
|
||||
uint8_t MouseWrapper_::warp_grid_size = MOUSE_WARP_GRID_2X2;
|
||||
uint16_t MouseWrapper_::next_width;
|
||||
uint16_t MouseWrapper_::next_height;
|
||||
uint16_t MouseWrapper_::section_top;
|
||||
uint16_t MouseWrapper_::section_left;
|
||||
boolean MouseWrapper_::is_warping;
|
||||
|
||||
uint8_t MouseWrapper_::accelStep;
|
||||
uint8_t MouseWrapper_::speedLimit = 127;
|
||||
uint8_t MouseWrapper_::subpixelsPerPixel = 16;
|
||||
|
||||
MouseWrapper_::MouseWrapper_(void) {
|
||||
}
|
||||
|
||||
void MouseWrapper_::begin(void) {
|
||||
kaleidoscope::hid::initializeMouse();
|
||||
kaleidoscope::hid::initializeAbsoluteMouse();
|
||||
}
|
||||
|
||||
void MouseWrapper_::pressButton(uint8_t button) {
|
||||
kaleidoscope::hid::pressMouseButtons(button);
|
||||
}
|
||||
|
||||
void MouseWrapper_::release_button(uint8_t button) {
|
||||
kaleidoscope::hid::releaseMouseButtons(button);
|
||||
end_warping();
|
||||
}
|
||||
|
||||
void MouseWrapper_::warp_jump(uint16_t left, uint16_t top, uint16_t height, uint16_t width) {
|
||||
uint16_t x_center = left + width / 2;
|
||||
uint16_t y_center = top + height / 2;
|
||||
kaleidoscope::hid::moveAbsoluteMouseTo(x_center, y_center, 0);
|
||||
}
|
||||
|
||||
void MouseWrapper_::begin_warping() {
|
||||
section_left = WARP_ABS_LEFT;
|
||||
section_top = WARP_ABS_TOP;
|
||||
next_width = MAX_WARP_WIDTH;
|
||||
next_height = MAX_WARP_HEIGHT;
|
||||
is_warping = true;
|
||||
}
|
||||
|
||||
void MouseWrapper_::end_warping() {
|
||||
is_warping = false;
|
||||
}
|
||||
|
||||
void MouseWrapper_::reset_warping() {
|
||||
if (is_warping == true) {
|
||||
begin_warping();
|
||||
}
|
||||
}
|
||||
|
||||
void MouseWrapper_::warp(uint8_t warp_cmd) {
|
||||
if (is_warping == false) {
|
||||
begin_warping();
|
||||
}
|
||||
|
||||
if (warp_cmd & WARP_END) {
|
||||
end_warping();
|
||||
return;
|
||||
}
|
||||
|
||||
next_width /= warp_grid_size;
|
||||
next_height /= warp_grid_size;
|
||||
|
||||
// WARP_UP + WARP_DOWN means "zoom in" to center sector
|
||||
if (warp_cmd & WARP_UP && warp_cmd & WARP_DOWN) {
|
||||
section_left += next_width;
|
||||
section_top += next_height;
|
||||
|
||||
warp_jump(section_left, section_top, next_height, next_width);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (warp_cmd & WARP_DOWN) {
|
||||
section_top += next_height * (warp_grid_size - 1);
|
||||
} else if (!(warp_cmd & WARP_UP)) {
|
||||
section_top += next_height;
|
||||
}
|
||||
|
||||
if (warp_cmd & WARP_RIGHT) {
|
||||
section_left += next_width * (warp_grid_size - 1);
|
||||
} else if (!(warp_cmd & WARP_LEFT)) {
|
||||
section_left += next_width;
|
||||
}
|
||||
|
||||
warp_jump(section_left, section_top, next_height, next_width);
|
||||
}
|
||||
|
||||
// cubic wave function based on code from FastLED
|
||||
// produces a shape similar to a sine curve from 0 to 255
|
||||
// (slow growth at 0, fast growth in the middle, slow growth at 255)
|
||||
// http://www.wolframalpha.com/input/?i=((3((x)**2)%2F256)+-+((2((x)(x)(x%2F256))%2F256)))+%2B+1
|
||||
uint8_t MouseWrapper_::acceleration(uint8_t cycles) {
|
||||
uint16_t i = cycles;
|
||||
|
||||
uint16_t ii = (i * i) >> 8;
|
||||
uint16_t iii = (ii * i) >> 8;
|
||||
|
||||
i = ((3 * ii) - (2 * iii)) + 1;
|
||||
|
||||
// Just in case (may go up to 256 at peak)
|
||||
if (i > 255) i = 255;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// Get the diagonalized version of a value, i.e. value * sqrt(2) / 2. If the
|
||||
// value ends up being zero, return the original value instead.
|
||||
static int16_t diagonalize(int16_t value) {
|
||||
// 99 / 140 closely approximates sqrt(2) / 2. Since integer division
|
||||
// truncates towards zero we do not need to worry about truncation errors.
|
||||
int16_t diagonalValue = value * 99 / 140;
|
||||
return (diagonalValue == 0 ? value : diagonalValue);
|
||||
}
|
||||
|
||||
void MouseWrapper_::move(int8_t x, int8_t y) {
|
||||
int16_t moveX = 0;
|
||||
int16_t moveY = 0;
|
||||
static int8_t remainderX = 0;
|
||||
static int8_t remainderY = 0;
|
||||
int16_t effectiveSpeedLimit = speedLimit;
|
||||
|
||||
if (x != 0 && y != 0) {
|
||||
// For diagonal movements, we apply a diagonalized speed limit. The
|
||||
// effective speed limit is set based on whether we are moving diagonally.
|
||||
effectiveSpeedLimit = diagonalize(effectiveSpeedLimit);
|
||||
|
||||
x = diagonalize(x);
|
||||
y = diagonalize(y);
|
||||
}
|
||||
|
||||
if (x != 0) {
|
||||
moveX = remainderX + (x * acceleration(accelStep));
|
||||
if (moveX > effectiveSpeedLimit) moveX = effectiveSpeedLimit;
|
||||
else if (moveX < -effectiveSpeedLimit) moveX = -effectiveSpeedLimit;
|
||||
}
|
||||
|
||||
if (y != 0) {
|
||||
moveY = remainderY + (y * acceleration(accelStep));
|
||||
if (moveY > effectiveSpeedLimit) moveY = effectiveSpeedLimit;
|
||||
else if (moveY < -effectiveSpeedLimit) moveY = -effectiveSpeedLimit;
|
||||
}
|
||||
|
||||
end_warping();
|
||||
// move by whole pixels, not subpixels
|
||||
kaleidoscope::hid::moveMouse(moveX / subpixelsPerPixel, moveY / subpixelsPerPixel, 0);
|
||||
// save leftover subpixel movements for later
|
||||
remainderX = moveX - moveX / subpixelsPerPixel * subpixelsPerPixel;
|
||||
remainderY = moveY - moveY / subpixelsPerPixel * subpixelsPerPixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kaleidoscope::plugin::MouseWrapper_ MouseWrapper;
|
@ -0,0 +1,74 @@
|
||||
/* Kaleidoscope-MouseKeys - Mouse 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 "Arduino.h"
|
||||
#include "kaleidoscope/plugin/MouseKeys/MouseWarpModes.h"
|
||||
|
||||
// Warping commands
|
||||
|
||||
#define WARP_END 1
|
||||
#define WARP_UP 2
|
||||
#define WARP_DOWN 4
|
||||
#define WARP_LEFT 8
|
||||
#define WARP_RIGHT 16
|
||||
|
||||
// apparently, the mac discards 15% of the value space for mouse movement.
|
||||
// need to test this on other platforms
|
||||
|
||||
#define MAX_WARP_WIDTH 32767
|
||||
#define MAX_WARP_HEIGHT 32767
|
||||
|
||||
#define WARP_ABS_TOP 0
|
||||
#define WARP_ABS_LEFT 0
|
||||
|
||||
// Mouse acceleration
|
||||
|
||||
namespace kaleidoscope {
|
||||
namespace plugin {
|
||||
|
||||
class MouseWrapper_ {
|
||||
public:
|
||||
MouseWrapper_(void);
|
||||
|
||||
static void begin(void);
|
||||
static void move(int8_t x, int8_t y);
|
||||
static void warp(uint8_t warp_cmd);
|
||||
static void reset_warping();
|
||||
static void pressButton(uint8_t button);
|
||||
static void release_button(uint8_t button);
|
||||
static uint8_t accelStep;
|
||||
static uint8_t speedLimit;
|
||||
static uint8_t subpixelsPerPixel;
|
||||
static uint8_t warp_grid_size;
|
||||
|
||||
private:
|
||||
static uint16_t next_width;
|
||||
static uint16_t next_height;
|
||||
static uint16_t section_top;
|
||||
static uint16_t section_left;
|
||||
static boolean is_warping;
|
||||
|
||||
static uint8_t acceleration(uint8_t cycles);
|
||||
static void begin_warping();
|
||||
static void end_warping();
|
||||
static void warp_jump(uint16_t left, uint16_t top, uint16_t height, uint16_t width);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
extern kaleidoscope::plugin::MouseWrapper_ MouseWrapper;
|
Loading…
Reference in new issue