Merge remote-tracking branch 'plugin/MouseKeys/f/monorepo' into f/monorepo

pull/365/head
Gergely Nagy 6 years ago
commit b128ed6234
No known key found for this signature in database
GPG Key ID: AC1E90BAC433F68F

@ -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…
Cancel
Save