summaryrefslogtreecommitdiff
path: root/quantum/pointing_device
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/pointing_device')
-rw-r--r--quantum/pointing_device/pointing_device.c28
-rw-r--r--quantum/pointing_device/pointing_device.h11
-rw-r--r--quantum/pointing_device/pointing_device_auto_mouse.c384
-rw-r--r--quantum/pointing_device/pointing_device_auto_mouse.h87
-rw-r--r--quantum/pointing_device/pointing_device_drivers.c38
5 files changed, 528 insertions, 20 deletions
diff --git a/quantum/pointing_device/pointing_device.c b/quantum/pointing_device/pointing_device.c
index 505a7a6ffd..75bb5f81fc 100644
--- a/quantum/pointing_device/pointing_device.c
+++ b/quantum/pointing_device/pointing_device.c
@@ -22,6 +22,7 @@
#ifdef MOUSEKEY_ENABLE
# include "mousekey.h"
#endif
+
#if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1
# error More than one rotation selected. This is not supported.
#endif
@@ -144,7 +145,11 @@ __attribute__((weak)) void pointing_device_init(void) {
{
pointing_device_driver.init();
#ifdef POINTING_DEVICE_MOTION_PIN
+# ifdef POINTING_DEVICE_MOTION_PIN_ACTIVE_LOW
setPinInputHigh(POINTING_DEVICE_MOTION_PIN);
+# else
+ setPinInput(POINTING_DEVICE_MOTION_PIN);
+# endif
#endif
}
@@ -166,11 +171,9 @@ __attribute__((weak)) void pointing_device_send(void) {
host_mouse_send(&local_mouse_report);
}
// send it and 0 it out except for buttons, so those stay until they are explicity over-ridden using update_pointing_device
- local_mouse_report.x = 0;
- local_mouse_report.y = 0;
- local_mouse_report.v = 0;
- local_mouse_report.h = 0;
-
+ uint8_t buttons = local_mouse_report.buttons;
+ memset(&local_mouse_report, 0, sizeof(local_mouse_report));
+ local_mouse_report.buttons = buttons;
memcpy(&old_report, &local_mouse_report, sizeof(local_mouse_report));
}
@@ -238,7 +241,11 @@ __attribute__((weak)) void pointing_device_task(void) {
# if defined(SPLIT_POINTING_ENABLE)
# error POINTING_DEVICE_MOTION_PIN not supported when sharing the pointing device report between sides.
# endif
+# ifdef POINTING_DEVICE_MOTION_PIN_ACTIVE_LOW
if (!readPin(POINTING_DEVICE_MOTION_PIN))
+# else
+ if (readPin(POINTING_DEVICE_MOTION_PIN))
+# endif
#endif
#if defined(SPLIT_POINTING_ENABLE)
@@ -270,6 +277,10 @@ __attribute__((weak)) void pointing_device_task(void) {
local_mouse_report = pointing_device_adjust_by_defines(local_mouse_report);
local_mouse_report = pointing_device_task_kb(local_mouse_report);
#endif
+ // automatic mouse layer function
+#ifdef POINTING_DEVICE_AUTO_MOUSE_ENABLE
+ pointing_device_task_auto_mouse(local_mouse_report);
+#endif
// combine with mouse report to ensure that the combined is sent correctly
#ifdef MOUSEKEY_ENABLE
report_mouse_t mousekey_report = mousekey_get_report();
@@ -469,3 +480,10 @@ __attribute__((weak)) report_mouse_t pointing_device_task_combined_user(report_m
return pointing_device_combine_reports(left_report, right_report);
}
#endif
+
+__attribute__((weak)) void pointing_device_keycode_handler(uint16_t keycode, bool pressed) {
+ if IS_MOUSEKEY_BUTTON (keycode) {
+ local_mouse_report.buttons = pointing_device_handle_buttons(local_mouse_report.buttons, pressed, keycode - KC_MS_BTN1);
+ pointing_device_send();
+ }
+}
diff --git a/quantum/pointing_device/pointing_device.h b/quantum/pointing_device/pointing_device.h
index 77db5471ea..d430e6cfa4 100644
--- a/quantum/pointing_device/pointing_device.h
+++ b/quantum/pointing_device/pointing_device.h
@@ -21,20 +21,28 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "host.h"
#include "report.h"
+#ifdef POINTING_DEVICE_AUTO_MOUSE_ENABLE
+# include "pointing_device_auto_mouse.h"
+#endif
+
#if defined(POINTING_DEVICE_DRIVER_adns5050)
# include "drivers/sensors/adns5050.h"
+# define POINTING_DEVICE_MOTION_PIN_ACTIVE_LOW
#elif defined(POINTING_DEVICE_DRIVER_adns9800)
# include "spi_master.h"
# include "drivers/sensors/adns9800.h"
+# define POINTING_DEVICE_MOTION_PIN_ACTIVE_LOW
#elif defined(POINTING_DEVICE_DRIVER_analog_joystick)
# include "analog.h"
# include "drivers/sensors/analog_joystick.h"
+# define POINTING_DEVICE_MOTION_PIN_ACTIVE_LOW
#elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) || defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
# include "drivers/sensors/cirque_pinnacle.h"
# include "drivers/sensors/cirque_pinnacle_gestures.h"
# include "pointing_device_gestures.h"
#elif defined(POINTING_DEVICE_DRIVER_paw3204)
# include "drivers/sensors/paw3204.h"
+# define POINTING_DEVICE_MOTION_PIN_ACTIVE_LOW
#elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball)
# include "i2c_master.h"
# include "drivers/sensors/pimoroni_trackball.h"
@@ -48,9 +56,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# ifdef PIMORONI_TRACKBALL_ROTATE
# define POINTING_DEVICE_ROTATION_90
# endif
+# define POINTING_DEVICE_MOTION_PIN_ACTIVE_LOW
#elif defined(POINTING_DEVICE_DRIVER_pmw3360) || defined(POINTING_DEVICE_DRIVER_pmw3389)
# include "spi_master.h"
# include "drivers/sensors/pmw33xx_common.h"
+# define POINTING_DEVICE_MOTION_PIN_ACTIVE_LOW
#else
void pointing_device_driver_init(void);
report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report);
@@ -100,6 +110,7 @@ report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report);
report_mouse_t pointing_device_task_user(report_mouse_t mouse_report);
uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button);
report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report);
+void pointing_device_keycode_handler(uint16_t keycode, bool pressed);
#if defined(SPLIT_POINTING_ENABLE)
void pointing_device_set_shared_report(report_mouse_t report);
diff --git a/quantum/pointing_device/pointing_device_auto_mouse.c b/quantum/pointing_device/pointing_device_auto_mouse.c
new file mode 100644
index 0000000000..edffd44787
--- /dev/null
+++ b/quantum/pointing_device/pointing_device_auto_mouse.c
@@ -0,0 +1,384 @@
+/* Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ * Copyright 2022 Alabastard
+ *
+ * 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, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/>.
+ */
+
+#ifdef POINTING_DEVICE_AUTO_MOUSE_ENABLE
+
+# include "pointing_device_auto_mouse.h"
+
+/* local data structure for tracking auto mouse */
+static auto_mouse_context_t auto_mouse_context = {.config.layer = (uint8_t)AUTO_MOUSE_DEFAULT_LAYER};
+
+/* local functions */
+static bool is_mouse_record(uint16_t keycode, keyrecord_t* record);
+static void auto_mouse_reset(void);
+
+/* check for target layer deactivation overrides */
+static inline bool layer_hold_check(void) {
+ return get_auto_mouse_toggle() ||
+# ifndef NO_ACTION_ONESHOT
+ get_oneshot_layer() == (AUTO_MOUSE_TARGET_LAYER) ||
+# endif
+ false;
+}
+
+/* check all layer activation criteria */
+static inline bool is_auto_mouse_active(void) {
+ return auto_mouse_context.status.is_activated || auto_mouse_context.status.mouse_key_tracker || layer_hold_check();
+}
+
+/**
+ * @brief Get auto mouse enable state
+ *
+ * Return is_enabled value
+ *
+ * @return bool true: auto mouse enabled false: auto mouse disabled
+ */
+bool get_auto_mouse_enable(void) {
+ return auto_mouse_context.config.is_enabled;
+}
+
+/**
+ * @brief get current target layer index
+ *
+ * NOTE: (AUTO_MOUSE_TARGET_LAYER) is an alias for this function
+ *
+ * @return uint8_t target layer index
+ */
+uint8_t get_auto_mouse_layer(void) {
+ return auto_mouse_context.config.layer;
+}
+
+/**
+ * @brief get layer_toggled value
+ *
+ * @return bool of current layer_toggled state
+ */
+bool get_auto_mouse_toggle(void) {
+ return auto_mouse_context.status.is_toggled;
+}
+
+/**
+ * @brief Reset auto mouse context
+ *
+ * Clear timers and status
+ *
+ * NOTE: this will set is_toggled to false so careful when using it
+ */
+static void auto_mouse_reset(void) {
+ memset(&auto_mouse_context.status, 0, sizeof(auto_mouse_context.status));
+ memset(&auto_mouse_context.timer, 0, sizeof(auto_mouse_context.timer));
+}
+
+/**
+ * @brief Set auto mouse enable state
+ *
+ * Set local auto mouse enabled state
+ *
+ * @param[in] state bool
+ */
+void set_auto_mouse_enable(bool enable) {
+ // skip if unchanged
+ if (auto_mouse_context.config.is_enabled == enable) return;
+ auto_mouse_context.config.is_enabled = enable;
+ auto_mouse_reset();
+}
+
+/**
+ * @brief Change target layer for auto mouse
+ *
+ * Sets input as the new target layer if different from current and resets auto mouse
+ *
+ * NOTE: remove_auto_mouse_layer(state, false) or auto_mouse_layer_off should be called
+ * before this function to avoid issues with layers getting stuck
+ *
+ * @param[in] layer uint8_t
+ */
+void set_auto_mouse_layer(uint8_t layer) {
+ // skip if unchanged
+ if (auto_mouse_context.config.layer == layer) return;
+ auto_mouse_context.config.layer = layer;
+ auto_mouse_reset();
+}
+
+/**
+ * @brief toggle mouse layer setting
+ *
+ * Change state of local layer_toggled bool meant to track when the mouse layer is toggled on by other means
+ *
+ * NOTE: While is_toggled is true it will prevent deactiving target layer (but not activation)
+ */
+void auto_mouse_toggle(void) {
+ auto_mouse_context.status.is_toggled ^= 1;
+ auto_mouse_context.timer.delay = 0;
+}
+
+/**
+ * @brief Remove current auto mouse target layer from layer state
+ *
+ * Will remove auto mouse target layer from given layer state if appropriate.
+ *
+ * NOTE: Removal can be forced, ignoring appropriate critera
+ *
+ * @params state[in] layer_state_t original layer state
+ * @params force[in] bool force removal
+ *
+ * @return layer_state_t modified layer state
+ */
+layer_state_t remove_auto_mouse_layer(layer_state_t state, bool force) {
+ if (force || ((AUTO_MOUSE_ENABLED) && !layer_hold_check())) {
+ state &= ~((layer_state_t)1 << (AUTO_MOUSE_TARGET_LAYER));
+ }
+ return state;
+}
+
+/**
+ * @brief Disable target layer
+ *
+ * Will disable target layer if appropriate.
+ * NOTE: NOT TO BE USED in layer_state_set stack!!!
+ */
+void auto_mouse_layer_off(void) {
+ if (layer_state_is((AUTO_MOUSE_TARGET_LAYER)) && (AUTO_MOUSE_ENABLED) && !layer_hold_check()) {
+ layer_off((AUTO_MOUSE_TARGET_LAYER));
+ }
+}
+
+/**
+ * @brief Weak function to handel testing if pointing_device is active
+ *
+ * Will trigger target layer activation(if delay timer has expired) and prevent deactivation when true.
+ * May be replaced by bool in report_mouse_t in future
+ *
+ * NOTE: defined weakly to allow for changing and adding conditions for specific hardware/customization
+ *
+ * @param[in] mouse_report report_mouse_t
+ * @return bool of pointing_device activation
+ */
+__attribute__((weak)) bool auto_mouse_activation(report_mouse_t mouse_report) {
+ return mouse_report.x != 0 || mouse_report.y != 0 || mouse_report.h != 0 || mouse_report.v != 0 || mouse_report.buttons;
+}
+
+/**
+ * @brief Update the auto mouse based on mouse_report
+ *
+ * Handel activation/deactivation of target layer based on auto_mouse_activation and state timers and local key/layer tracking data
+ *
+ * @param[in] mouse_report report_mouse_t
+ */
+void pointing_device_task_auto_mouse(report_mouse_t mouse_report) {
+ // skip if disabled, delay timer running, or debounce
+ if (!(AUTO_MOUSE_ENABLED) || timer_elapsed(auto_mouse_context.timer.active) <= AUTO_MOUSE_DEBOUNCE || timer_elapsed(auto_mouse_context.timer.delay) <= AUTO_MOUSE_DELAY) {
+ return;
+ }
+ // update activation and reset debounce
+ auto_mouse_context.status.is_activated = auto_mouse_activation(mouse_report);
+ if (is_auto_mouse_active()) {
+ auto_mouse_context.timer.active = timer_read();
+ auto_mouse_context.timer.delay = 0;
+ if (!layer_state_is((AUTO_MOUSE_TARGET_LAYER))) {
+ layer_on((AUTO_MOUSE_TARGET_LAYER));
+ }
+ } else if (layer_state_is((AUTO_MOUSE_TARGET_LAYER)) && timer_elapsed(auto_mouse_context.timer.active) > AUTO_MOUSE_TIME) {
+ layer_off((AUTO_MOUSE_TARGET_LAYER));
+ auto_mouse_context.timer.active = 0;
+ }
+}
+
+/**
+ * @brief Handle mouskey event
+ *
+ * Increments/decrements mouse_key_tracker and restart active timer
+ *
+ * @param[in] pressed bool
+ */
+void auto_mouse_keyevent(bool pressed) {
+ if (pressed) {
+ auto_mouse_context.status.mouse_key_tracker++;
+ } else {
+ auto_mouse_context.status.mouse_key_tracker--;
+ }
+ auto_mouse_context.timer.delay = 0;
+}
+
+/**
+ * @brief Handle auto mouse non mousekey reset
+ *
+ * Start/restart delay timer and reset auto mouse on keydown as well as turn the
+ * target layer off if on and reset toggle status
+ *
+ * NOTE: NOT TO BE USED in layer_state_set stack!!!
+ *
+ * @param[in] pressed bool
+ */
+void auto_mouse_reset_trigger(bool pressed) {
+ if (pressed) {
+ if (layer_state_is((AUTO_MOUSE_TARGET_LAYER))) {
+ layer_off((AUTO_MOUSE_TARGET_LAYER));
+ };
+ auto_mouse_reset();
+ }
+ auto_mouse_context.timer.delay = timer_read();
+}
+
+/**
+ * @brief handle key events processing for auto mouse
+ *
+ * Will process keys differently depending on if key is defined as mousekey or not.
+ * Some keys have built in behaviour(not overwritable):
+ * mouse buttons : auto_mouse_keyevent()
+ * non-mouse keys : auto_mouse_reset_trigger()
+ * mod keys : skip auto mouse key processing
+ * mod tap : skip on hold (mod keys)
+ * QK mods e.g. LCTL(kc): default to non-mouse key, add at kb/user level as needed
+ * non target layer keys: skip auto mouse key processing (same as mod keys)
+ * MO(target layer) : auto_mouse_keyevent()
+ * target layer toggles : auto_mouse_toggle() (on both key up and keydown)
+ * target layer tap : default processing on tap mouse key on hold
+ * all other keycodes : default to non-mouse key, add at kb/user level as needed
+ *
+ * Will deactivate target layer once a non mouse key is pressed if nothing is holding the layer active
+ * such as held mousekey, toggled current target layer, or auto_mouse_activation is true
+ *
+ * @params keycode[in] uint16_t
+ * @params record[in] keyrecord_t pointer
+ */
+bool process_auto_mouse(uint16_t keycode, keyrecord_t* record) {
+ // skip if not enabled or mouse_layer not set
+ if (!(AUTO_MOUSE_ENABLED)) return true;
+
+ switch (keycode) {
+ // Skip Mod keys to avoid layer reset
+ case KC_LEFT_CTRL ... KC_RIGHT_GUI:
+ case QK_MODS ... QK_MODS_MAX:
+ break;
+ // TO((AUTO_MOUSE_TARGET_LAYER))-------------------------------------------------------------------------------
+ case QK_TO ... QK_TO_MAX: // same proccessing as next
+ // TG((AUTO_MOUSE_TARGET_LAYER))-------------------------------------------------------------------------------
+ case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX:
+ if ((keycode & 0xff) == (AUTO_MOUSE_TARGET_LAYER)) {
+ if (!(record->event.pressed)) auto_mouse_toggle();
+ }
+ break;
+ // MO((AUTO_MOUSE_TARGET_LAYER))-------------------------------------------------------------------------------
+ case QK_MOMENTARY ... QK_MOMENTARY_MAX:
+ if ((keycode & 0xff) == (AUTO_MOUSE_TARGET_LAYER)) {
+ auto_mouse_keyevent(record->event.pressed);
+ }
+ // DF ---------------------------------------------------------------------------------------------------------
+ case QK_DEF_LAYER ... QK_DEF_LAYER_MAX:
+# ifndef NO_ACTION_ONESHOT
+ // OSL((AUTO_MOUSE_TARGET_LAYER))------------------------------------------------------------------------------
+ case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX:
+ case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
+# endif
+ break;
+ // LM((AUTO_MOUSE_TARGET_LAYER), mod)--------------------------------------------------------------------------
+ case QK_LAYER_MOD ... QK_LAYER_MOD_MAX:
+ if (((keycode >> 8) & 0x0f) == (AUTO_MOUSE_TARGET_LAYER)) {
+ auto_mouse_keyevent(record->event.pressed);
+ }
+ break;
+ // TT((AUTO_MOUSE_TARGET_LAYER))---------------------------------------------------------------------------
+# ifndef NO_ACTION_TAPPING
+ case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
+ if ((keycode & 0xff) == (AUTO_MOUSE_TARGET_LAYER)) {
+ auto_mouse_keyevent(record->event.pressed);
+# if TAPPING_TOGGLE != 0
+ if (record->tap.count == TAPPING_TOGGLE) {
+ if (record->event.pressed) {
+ auto_mouse_context.status.mouse_key_tracker--;
+ } else {
+ auto_mouse_toggle();
+ auto_mouse_context.status.mouse_key_tracker++;
+ }
+ }
+# endif
+ }
+ break;
+ // LT((AUTO_MOUSE_TARGET_LAYER), kc)---------------------------------------------------------------------------
+ case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
+ if (!record->tap.count) {
+ if (((keycode >> 8) & 0x0f) == (AUTO_MOUSE_TARGET_LAYER)) {
+ auto_mouse_keyevent(record->event.pressed);
+ }
+ break;
+ }
+ // MT(kc) only skip on hold
+ case QK_MOD_TAP ... QK_MOD_TAP_MAX:
+ if (!record->tap.count) break;
+# endif
+ // QK_MODS goes to default
+ default:
+ // skip on no event
+ if (IS_NOEVENT(record->event)) break;
+ // check if keyrecord is mousekey
+ if (is_mouse_record(keycode, record)) {
+ auto_mouse_keyevent(record->event.pressed);
+ } else if (!is_auto_mouse_active()) {
+ // all non-mousekey presses restart delay timer and reset status
+ auto_mouse_reset_trigger(record->event.pressed);
+ }
+ }
+ if (auto_mouse_context.status.mouse_key_tracker < 0) {
+ auto_mouse_context.status.mouse_key_tracker = 0;
+ dprintf("key tracker error (<0) \n");
+ }
+ return true;
+}
+
+/**
+ * @brief Local function to handle checking if a keycode is a mouse button
+ *
+ * Starts code stack for checking keyrecord if defined as mousekey
+ *
+ * @params keycode[in] uint16_t
+ * @params record[in] keyrecord_t pointer
+ * @return bool true: keyrecord is mousekey false: keyrecord is not mousekey
+ */
+static bool is_mouse_record(uint16_t keycode, keyrecord_t* record) {
+ // allow for keyboard to hook in and override if need be
+ if (is_mouse_record_kb(keycode, record) || IS_MOUSEKEY(keycode)) return true;
+ return false;
+}
+
+/**
+ * @brief Weakly defined keyboard level callback for adding keyrecords as mouse keys
+ *
+ * Meant for redefinition at keyboard level and should return is_mouse_record_user by default at end of function
+ *
+ * @params keycode[in] uint16_t
+ * @params record[in] keyrecord_t pointer
+ * @return bool true: keyrecord is defined as mouse key false: keyrecord is not defined as mouse key
+ */
+__attribute__((weak)) bool is_mouse_record_kb(uint16_t keycode, keyrecord_t* record) {
+ return is_mouse_record_user(keycode, record);
+}
+
+/**
+ * @brief Weakly defined keymap/user level callback for adding keyrecords as mouse keys
+ *
+ * Meant for redefinition at keymap/user level and should return false by default at end of function
+ *
+ * @params keycode[in] uint16_t
+ * @params record[in] keyrecord_t pointer
+ * @return bool true: keyrecord is defined as mouse key false: keyrecord is not defined as mouse key
+ */
+__attribute__((weak)) bool is_mouse_record_user(uint16_t keycode, keyrecord_t* record) {
+ return false;
+}
+
+#endif // POINTING_DEVICE_AUTO_MOUSE_ENABLE
diff --git a/quantum/pointing_device/pointing_device_auto_mouse.h b/quantum/pointing_device/pointing_device_auto_mouse.h
new file mode 100644
index 0000000000..0f26af79e6
--- /dev/null
+++ b/quantum/pointing_device/pointing_device_auto_mouse.h
@@ -0,0 +1,87 @@
+/* Copyright 2022 Alabastard
+ *
+ * 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, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 <string.h>
+
+#include "quantum.h"
+#include "pointing_device.h"
+#include "print.h"
+
+/* check settings and set defaults */
+#ifndef POINTING_DEVICE_AUTO_MOUSE_ENABLE
+# error "POINTING_DEVICE_AUTO_MOUSE_ENABLE not defined! check config settings"
+#endif
+
+#ifndef AUTO_MOUSE_DEFAULT_LAYER
+# define AUTO_MOUSE_DEFAULT_LAYER 1
+#endif
+#ifndef AUTO_MOUSE_TIME
+# define AUTO_MOUSE_TIME 650
+#endif
+#ifndef AUTO_MOUSE_DELAY
+# define AUTO_MOUSE_DELAY GET_TAPPING_TERM(KC_MS_BTN1, &(keyrecord_t){})
+#endif
+#ifndef AUTO_MOUSE_DEBOUNCE
+# define AUTO_MOUSE_DEBOUNCE 25
+#endif
+
+/* data structure */
+typedef struct {
+ struct {
+ bool is_enabled;
+ uint8_t layer;
+ } config;
+ struct {
+ uint16_t active;
+ uint16_t delay;
+ } timer;
+ struct {
+ bool is_activated;
+ bool is_toggled;
+ int8_t mouse_key_tracker;
+ } status;
+} auto_mouse_context_t;
+
+/* ----------Set up and control------------------------------------------------------------------------------ */
+void set_auto_mouse_enable(bool enable); // enable/disable auto mouse feature
+bool get_auto_mouse_enable(void); // get auto_mouse_enable
+void set_auto_mouse_layer(uint8_t layer); // set target layer by index
+uint8_t get_auto_mouse_layer(void); // get target layer index
+void auto_mouse_layer_off(void); // disable target layer if appropriate (DO NOT USE in layer_state_set stack!!)
+layer_state_t remove_auto_mouse_layer(layer_state_t state, bool force); // remove auto mouse target layer from state if appropriate (can be forced)
+
+/* ----------For custom pointing device activation----------------------------------------------------------- */
+bool auto_mouse_activation(report_mouse_t mouse_report); // handles pointing device trigger conditions for target layer activation (overwritable)
+
+/* ----------Handling keyevents------------------------------------------------------------------------------ */
+void auto_mouse_keyevent(bool pressed); // trigger auto mouse keyevent: mouse_keytracker increment/decrement on press/release
+void auto_mouse_reset_trigger(bool pressed); // trigger non mouse keyevent: reset and start delay timer (DO NOT USE in layer_state_set stack!!)
+void auto_mouse_toggle(void); // toggle mouse layer flag disables mouse layer deactivation while on (meant for tap toggle or toggle of target)
+bool get_auto_mouse_toggle(void); // get toggle mouse layer flag value
+
+/* ----------Callbacks for adding keycodes to mouse record checking------------------------------------------ */
+bool is_mouse_record_kb(uint16_t keycode, keyrecord_t* record);
+bool is_mouse_record_user(uint16_t keycode, keyrecord_t* record);
+
+/* ----------Core functions (only used in custom pointing devices or key processing)------------------------- */
+void pointing_device_task_auto_mouse(report_mouse_t mouse_report); // add to pointing_device_task_*
+bool process_auto_mouse(uint16_t keycode, keyrecord_t* record); // add to process_record_*
+
+/* ----------Macros/Aliases---------------------------------------------------------------------------------- */
+#define AUTO_MOUSE_TARGET_LAYER get_auto_mouse_layer()
+#define AUTO_MOUSE_ENABLED get_auto_mouse_enable()
diff --git a/quantum/pointing_device/pointing_device_drivers.c b/quantum/pointing_device/pointing_device_drivers.c
index b96f8ff4b3..172c9f36d7 100644
--- a/quantum/pointing_device/pointing_device_drivers.c
+++ b/quantum/pointing_device/pointing_device_drivers.c
@@ -17,6 +17,7 @@
*/
#include "pointing_device.h"
+#include "pointing_device_internal.h"
#include "debug.h"
#include "wait.h"
#include "timer.h"
@@ -32,10 +33,7 @@ report_mouse_t adns5050_get_report(report_mouse_t mouse_report) {
report_adns5050_t data = adns5050_read_burst();
if (data.dx != 0 || data.dy != 0) {
-# ifdef CONSOLE_ENABLE
- if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.dx, data.dy);
-# endif
-
+ pd_dprintf("Raw ] X: %d, Y: %d\n", data.dx, data.dy);
mouse_report.x = (mouse_xy_report_t)data.dx;
mouse_report.y = (mouse_xy_report_t)data.dy;
}
@@ -76,9 +74,7 @@ const pointing_device_driver_t pointing_device_driver = {
report_mouse_t analog_joystick_get_report(report_mouse_t mouse_report) {
report_analog_joystick_t data = analog_joystick_read();
-# ifdef CONSOLE_ENABLE
- if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.x, data.y);
-# endif
+ pd_dprintf("Raw ] X: %d, Y: %d\n", data.x, data.y);
mouse_report.x = data.x;
mouse_report.y = data.y;
@@ -117,12 +113,24 @@ void cirque_pinnacle_configure_cursor_glide(float trigger_px) {
# endif
# if CIRQUE_PINNACLE_POSITION_MODE
+
+# ifdef POINTING_DEVICE_AUTO_MOUSE_ENABLE
+static bool is_touch_down;
+
+bool auto_mouse_activation(report_mouse_t mouse_report) {
+ return is_touch_down || mouse_report.x != 0 || mouse_report.y != 0 || mouse_report.h != 0 || mouse_report.v != 0 || mouse_report.buttons;
+}
+# endif
+
report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) {
pinnacle_data_t touchData = cirque_pinnacle_read_data();
mouse_xy_report_t report_x = 0, report_y = 0;
static uint16_t x = 0, y = 0;
+# if defined(CIRQUE_PINNACLE_TAP_ENABLE)
+ mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, false, POINTING_DEVICE_BUTTON1);
+# endif
# ifdef POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE
- cursor_glide_t glide_report = {0};
+ cursor_glide_t glide_report = {0};
if (cursor_glide_enable) {
glide_report = cursor_glide_check(&glide);
@@ -140,10 +148,12 @@ report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) {
return mouse_report;
}
-# if CONSOLE_ENABLE
- if (debug_mouse && touchData.touchDown) {
- dprintf("cirque_pinnacle touchData x=%4d y=%4d z=%2d\n", touchData.xValue, touchData.yValue, touchData.zValue);
+ if (touchData.touchDown) {
+ pd_dprintf("cirque_pinnacle touchData x=%4d y=%4d z=%2d\n", touchData.xValue, touchData.yValue, touchData.zValue);
}
+
+# ifdef POINTING_DEVICE_AUTO_MOUSE_ENABLE
+ is_touch_down = touchData.touchDown;
# endif
// Scale coordinates to arbitrary X, Y resolution
@@ -227,9 +237,7 @@ const pointing_device_driver_t pointing_device_driver = {
report_mouse_t paw3204_get_report(report_mouse_t mouse_report) {
report_paw3204_t data = paw3204_read();
if (data.isMotion) {
-# ifdef CONSOLE_ENABLE
- dprintf("Raw ] X: %d, Y: %d\n", data.x, data.y);
-# endif
+ pd_dprintf("Raw ] X: %d, Y: %d\n", data.x, data.y);
mouse_report.x = data.x;
mouse_report.y = data.y;
@@ -329,7 +337,7 @@ report_mouse_t pmw33xx_get_report(report_mouse_t mouse_report) {
if (!in_motion) {
in_motion = true;
- dprintf("PWM3360 (0): starting motion\n");
+ pd_dprintf("PWM3360 (0): starting motion\n");
}
mouse_report.x = CONSTRAIN_HID_XY(report.delta_x);