First part new mouse infrastructure
This commit is contained in:
parent
1a2e98af96
commit
92d972cfd8
3 changed files with 305 additions and 338 deletions
src/ginput
|
@ -19,68 +19,81 @@
|
||||||
|
|
||||||
#if GINPUT_NEED_MOUSE || defined(__DOXYGEN__)
|
#if GINPUT_NEED_MOUSE || defined(__DOXYGEN__)
|
||||||
|
|
||||||
#include "ginput_lld_mouse_config.h"
|
typedef struct MouseReading {
|
||||||
|
|
||||||
// GEVENT_MOUSE or GEVENT_TOUCH - What type of device is this.
|
|
||||||
#ifndef GINPUT_MOUSE_EVENT_TYPE
|
|
||||||
#define GINPUT_MOUSE_EVENT_TYPE GEVENT_MOUSE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TRUE/FALSE - Does the mouse/touch driver require calibration?
|
|
||||||
#ifndef GINPUT_MOUSE_NEED_CALIBRATION
|
|
||||||
#define GINPUT_MOUSE_NEED_CALIBRATION FALSE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TRUE/FALSE - Should the calibration happen at the extremes of the panel?
|
|
||||||
#ifndef GINPUT_MOUSE_CALIBRATE_EXTREMES
|
|
||||||
#define GINPUT_MOUSE_CALIBRATE_EXTREMES FALSE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TRUE/FALSE - Can the mouse/touch driver itself save calibration data?
|
|
||||||
#ifndef GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
|
|
||||||
#define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE FALSE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// n or -1 - n means to test calibration result (+/- pixels), -1 means not to.
|
|
||||||
#ifndef GINPUT_MOUSE_MAX_CALIBRATION_ERROR
|
|
||||||
#define GINPUT_MOUSE_MAX_CALIBRATION_ERROR -1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// n - How many times to read (and average) per poll
|
|
||||||
#ifndef GINPUT_MOUSE_READ_CYCLES
|
|
||||||
#define GINPUT_MOUSE_READ_CYCLES 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// n - Millisecs between poll's
|
|
||||||
#ifndef GINPUT_MOUSE_POLL_PERIOD
|
|
||||||
#define GINPUT_MOUSE_POLL_PERIOD 25
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// n - Movement allowed without discarding the CLICK or CLICKCXT event (+/- pixels)
|
|
||||||
#ifndef GINPUT_MOUSE_MAX_CLICK_JITTER
|
|
||||||
#define GINPUT_MOUSE_MAX_CLICK_JITTER 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// n - Movement allowed without discarding the MOVE event (+/- pixels)
|
|
||||||
#ifndef GINPUT_MOUSE_MAX_MOVE_JITTER
|
|
||||||
#define GINPUT_MOUSE_MAX_MOVE_JITTER 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ms - Millisecs seperating a CLICK from a CXTCLICK
|
|
||||||
#ifndef GINPUT_MOUSE_CLICK_TIME
|
|
||||||
#define GINPUT_MOUSE_CLICK_TIME 700
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// true/false - Whether the mouse driver internally handles screen rotation
|
|
||||||
#ifndef GINPUT_MOUSE_NO_ROTATION
|
|
||||||
#define GINPUT_MOUSE_NO_ROTATION FALSE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct MouseReading_t {
|
|
||||||
coord_t x, y, z;
|
coord_t x, y, z;
|
||||||
uint16_t buttons;
|
uint16_t buttons;
|
||||||
} MouseReading;
|
} MouseReading;
|
||||||
|
|
||||||
|
#if !GINPUT_TOUCH_NOCALIBRATE
|
||||||
|
typedef struct MouseCalibration {
|
||||||
|
float ax;
|
||||||
|
float bx;
|
||||||
|
float cx;
|
||||||
|
float ay;
|
||||||
|
float by;
|
||||||
|
float cy;
|
||||||
|
} MouseCalibration;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct MouseInstance {
|
||||||
|
struct MouseInstance * next; // The next mouse instance
|
||||||
|
const struct MOUSEVMT * vmt; // The mouse VMT
|
||||||
|
MouseReading r; // The current position and state
|
||||||
|
uint16_t flags; // Flags
|
||||||
|
#define GMOUSE_FLG_ACTIVE 0x0001 // Mouse is currently active
|
||||||
|
#define GMOUSE_FLG_DYNAMIC 0x0002 // Mouse is dynamically allocated
|
||||||
|
#define GMOUSE_FLG_CLICK_TIMER 0x0004 // Currently timing a click event
|
||||||
|
#define GMOUSE_FLG_INDELTA 0x0008 // Currently in a up/down transition test
|
||||||
|
#define GMOUSE_FLG_CLIP 0x0010 // Clip reading to the display
|
||||||
|
#define GMOUSE_FLG_CALIBRATE 0x0020 // Calibrate readings
|
||||||
|
#define GMOUSE_FLG_CAL_INPROGRESS 0x0040 // Calibrate is currently in progress
|
||||||
|
#define GMOUSE_FLG_CAL_SAVED 0x0080 // Calibration has been saved
|
||||||
|
#define GMOUSE_FLG_FINGERMODE 0x0100 // Mouse is currently in finger mode
|
||||||
|
point clickpos; // The position of the last click event
|
||||||
|
systemticks_t clicktime; // The time of the last click event
|
||||||
|
GDisplay * display; // The display the mouse is associated with
|
||||||
|
void * param; // A variable for private driver use
|
||||||
|
#if !GINPUT_TOUCH_NOCALIBRATE
|
||||||
|
GMouseCalibrationSaveRoutine fnsavecal; // The calibration load routine
|
||||||
|
GMouseCalibrationLoadRoutine fnloadcal; // The calibration save routine
|
||||||
|
MouseCalibration caldata; // The calibration data
|
||||||
|
#endif
|
||||||
|
} MouseInstance;
|
||||||
|
|
||||||
|
typedef struct MouseJitter {
|
||||||
|
coord_t calibrate; // Maximum error for a calibration to succeed
|
||||||
|
coord_t click; // Movement allowed without discarding the CLICK or CLICKCXT event
|
||||||
|
coord_t move; // Movement allowed without discarding the MOVE event
|
||||||
|
} MouseJitter;
|
||||||
|
|
||||||
|
typedef struct MOUSEVMT {
|
||||||
|
uint16_t flags; // Device flags
|
||||||
|
#define GMOUSE_VFLG_TOUCH 0x0001 // This is a touch device (rather than a mouse). Button 1 is calculated from z value.
|
||||||
|
#define GMOUSE_VFLG_NOPOLL 0x0002 // Do not poll this device - it is purely interrupt driven
|
||||||
|
#define GMOUSE_VFLG_SELFROTATION 0x0004 // This device returns readings that are aligned with the display orientation
|
||||||
|
#define GMOUSE_VFLG_DEFAULTFINGER 0x0008 // Default to finger mode
|
||||||
|
#define GMOUSE_VFLG_CALIBRATE 0x0010 // This device requires calibration
|
||||||
|
#define GMOUSE_VFLG_CAL_EXTREMES 0x0020 // Use edge to edge calibration
|
||||||
|
#define GMOUSE_VFLG_CAL_TEST 0x0040 // Test the results of the calibration
|
||||||
|
#define GMOUSE_VFLG_ONLY_DOWN 0x0100 // This device returns a valid position only when the mouse is down
|
||||||
|
#define GMOUSE_VFLG_POORUPDOWN 0x0200 // Position readings during up/down are unreliable
|
||||||
|
coord_t z_max; // TOUCH: Maximum possible z value (fully touched)
|
||||||
|
coord_t z_min; // TOUCH: Minimum possible z value (touch off screen). Note may also be > z_max
|
||||||
|
coord_t z_touchon; // TOUCH: z values between z_max and this are a solid touch on
|
||||||
|
coord_t z_touchoff; // TOUCH: z values between z_min and this are a solid touch off
|
||||||
|
|
||||||
|
MouseJitter pen_jitter; // PEN MODE: Jitter settings
|
||||||
|
MouseJitter finger_jitter; // FINGER MODE: Jitter settings
|
||||||
|
|
||||||
|
void (*init)((MouseInstance *pmouse); // Required
|
||||||
|
void (*get)(MouseInstance *pmouse, MouseReading *prd); // Required
|
||||||
|
void (*cal_save)(MouseInstance *pmouse, void *buf, size_t sz); // Optional
|
||||||
|
const char *(*cal_load)(MouseInstance *pmouse); // Optional: Can return NULL if no data is saved.
|
||||||
|
// Buffer is gfxFree()'d afterwards.
|
||||||
|
} MOUSEVMT;
|
||||||
|
|
||||||
|
#include "ginput_lld_mouse_config.h"
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* External declarations. */
|
/* External declarations. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -88,70 +101,33 @@ typedef struct MouseReading_t {
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialise the mouse/touch.
|
* @brief Get a new empty mouse instance and assign it this VMT and display
|
||||||
|
* @note This routine is provided to low level drivers by the high level code.
|
||||||
|
* @note This routine is designed for displays that have their own dedicated mouse
|
||||||
|
* eg. Win32, X, uGFXnet.
|
||||||
|
* The display driver will during initialisation call this routine to associate
|
||||||
|
* itself with a mouse.
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
void ginput_lld_mouse_init(void);
|
MouseInstance *ginputMouseGetNewMouseForDisplay(const MOUSEVMT *vmt, GDisplay *g);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read the mouse/touch position.
|
* @brief Release a mouse
|
||||||
*
|
* @note This routine is provided to low level drivers by the high level code.
|
||||||
* @param[in] pt A pointer to the structure to fill
|
* @note This routine is designed for displays that have their own dedicated mouse
|
||||||
*
|
* eg. Win32, X, uGFXnet.
|
||||||
* @note For drivers that don't support returning a position
|
* When the display has finished with the mouse it can release it.
|
||||||
* when the touch is up (most touch devices), it should
|
|
||||||
* return the previous position with the new Z value.
|
|
||||||
* The z value is the pressure for those touch devices
|
|
||||||
* that support it (-100 to 100 where > 0 is touched)
|
|
||||||
* or, 0 or 100 for those drivers that don't.
|
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
void ginput_lld_mouse_get_reading(MouseReading *pt);
|
void ginputMouseGetNewMouseForDisplay(MouseIntance *pmouse);
|
||||||
|
|
||||||
#if GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
|
|
||||||
/**
|
|
||||||
* @brief Load calibration data from a storage area on the touch controller.
|
|
||||||
*
|
|
||||||
* @param[in] instance The mouse instance number
|
|
||||||
*
|
|
||||||
* @note The instance parameter is currently always 0 as we only support
|
|
||||||
* one mouse/touch device at a time.
|
|
||||||
* @note This routine should only be provided if the driver has its own
|
|
||||||
* storage area where calibration data can be stored. The drivers
|
|
||||||
* option.h file should define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE = TRUE
|
|
||||||
* if it supports this.
|
|
||||||
*
|
|
||||||
* @notapi
|
|
||||||
*/
|
|
||||||
const char *ginput_lld_mouse_calibration_load(uint16_t instance);
|
|
||||||
/**
|
|
||||||
* @brief Save calibration data to a storage area on the touch controller.
|
|
||||||
*
|
|
||||||
* @param[in] instance The mouse instance number
|
|
||||||
* @param[in] calbuf The calibration data to be saved
|
|
||||||
* @param[in] sz The size of the calibration data
|
|
||||||
*
|
|
||||||
* @note The instance parameter is currently always 0 as we only support
|
|
||||||
* one mouse/touch device at a time.
|
|
||||||
* @note This routine should only be provided if the driver has its own
|
|
||||||
* storage area where calibration data can be stored. The drivers
|
|
||||||
* option.h file should define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE = TRUE
|
|
||||||
* if it supports this.
|
|
||||||
*
|
|
||||||
* @notapi
|
|
||||||
*/
|
|
||||||
void ginput_lld_mouse_calibration_save(uint16_t instance, const uint8_t *calbuf, size_t sz);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Wakeup the high level code so that it attempts another read
|
* @brief Wakeup the high level code so that it attempts another read
|
||||||
*
|
*
|
||||||
* @note This routine is provided to low level drivers by the high level code
|
* @note This routine is provided to low level drivers by the high level code
|
||||||
* @note Particularly useful if GINPUT_MOUSE_POLL_PERIOD = TIME_INFINITE
|
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
|
@ -161,7 +137,6 @@ extern "C" {
|
||||||
* @brief Wakeup the high level code so that it attempts another read
|
* @brief Wakeup the high level code so that it attempts another read
|
||||||
*
|
*
|
||||||
* @note This routine is provided to low level drivers by the high level code
|
* @note This routine is provided to low level drivers by the high level code
|
||||||
* @note Particularly useful if GINPUT_MOUSE_POLL_PERIOD = TIME_INFINITE
|
|
||||||
*
|
*
|
||||||
* @iclass
|
* @iclass
|
||||||
* @notapi
|
* @notapi
|
||||||
|
@ -172,7 +147,7 @@ extern "C" {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* GINPUT_NEED_MOUSE || GINPUT_NEED_TOUCH */
|
#endif /* GINPUT_NEED_MOUSE */
|
||||||
|
|
||||||
#endif /* _LLD_GINPUT_MOUSE_H */
|
#endif /* _LLD_GINPUT_MOUSE_H */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include "src/ginput/driver_mouse.h"
|
#include "src/ginput/driver_mouse.h"
|
||||||
|
|
||||||
#if GINPUT_MOUSE_NEED_CALIBRATION
|
#if !GINPUT_TOUCH_NOCALIBRATE
|
||||||
#if !defined(GFX_USE_GDISP) || !GFX_USE_GDISP
|
#if !defined(GFX_USE_GDISP) || !GFX_USE_GDISP
|
||||||
#error "GINPUT: GFX_USE_GDISP must be defined when mouse or touch calibration is required"
|
#error "GINPUT: GFX_USE_GDISP must be defined when mouse or touch calibration is required"
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,87 +38,12 @@
|
||||||
#define GINPUT_MOUSE_CALIBRATION_POINTS 4
|
#define GINPUT_MOUSE_CALIBRATION_POINTS 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct Calibration_t {
|
endif
|
||||||
float ax;
|
|
||||||
float bx;
|
|
||||||
float cx;
|
|
||||||
float ay;
|
|
||||||
float by;
|
|
||||||
float cy;
|
|
||||||
} Calibration;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct MousePoint_t {
|
|
||||||
coord_t x, y;
|
|
||||||
} MousePoint;
|
|
||||||
|
|
||||||
static GTIMER_DECL(MouseTimer);
|
static GTIMER_DECL(MouseTimer);
|
||||||
|
|
||||||
static struct MouseConfig_t {
|
#if !GINPUT_TOUCH_NOCALIBRATE
|
||||||
MouseReading t;
|
static inline void _tsSetIdentity(MouseCalibration *c) {
|
||||||
MousePoint movepos;
|
|
||||||
MousePoint clickpos;
|
|
||||||
systemticks_t clicktime;
|
|
||||||
uint16_t last_buttons;
|
|
||||||
uint16_t flags;
|
|
||||||
#define FLG_INIT_DONE 0x8000
|
|
||||||
#define FLG_CLICK_TIMER 0x0001
|
|
||||||
#define FLG_IN_CAL 0x0010
|
|
||||||
#define FLG_CAL_OK 0x0020
|
|
||||||
#define FLG_CAL_SAVED 0x0040
|
|
||||||
#define FLG_CAL_FREE 0x0080
|
|
||||||
#define FLG_CAL_RAW 0x0100
|
|
||||||
#if GINPUT_MOUSE_NEED_CALIBRATION
|
|
||||||
GMouseCalibrationSaveRoutine fnsavecal;
|
|
||||||
GMouseCalibrationLoadRoutine fnloadcal;
|
|
||||||
Calibration caldata;
|
|
||||||
#endif
|
|
||||||
GDisplay * display;
|
|
||||||
} MouseConfig;
|
|
||||||
|
|
||||||
void _tsOrientClip(MouseReading *pt, GDisplay *g, bool_t doClip) {
|
|
||||||
coord_t w, h;
|
|
||||||
|
|
||||||
w = gdispGGetWidth(g);
|
|
||||||
h = gdispGGetHeight(g);
|
|
||||||
|
|
||||||
#if GDISP_NEED_CONTROL && !GINPUT_MOUSE_NO_ROTATION
|
|
||||||
switch(gdispGGetOrientation(g)) {
|
|
||||||
case GDISP_ROTATE_0:
|
|
||||||
break;
|
|
||||||
case GDISP_ROTATE_90:
|
|
||||||
{
|
|
||||||
coord_t t = pt->x;
|
|
||||||
pt->x = w - 1 - pt->y;
|
|
||||||
pt->y = t;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GDISP_ROTATE_180:
|
|
||||||
pt->x = w - 1 - pt->x;
|
|
||||||
pt->y = h - 1 - pt->y;
|
|
||||||
break;
|
|
||||||
case GDISP_ROTATE_270:
|
|
||||||
{
|
|
||||||
coord_t t = pt->y;
|
|
||||||
pt->y = h - 1 - pt->x;
|
|
||||||
pt->x = t;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (doClip) {
|
|
||||||
if (pt->x < 0) pt->x = 0;
|
|
||||||
else if (pt->x >= w) pt->x = w-1;
|
|
||||||
if (pt->y < 0) pt->y = 0;
|
|
||||||
else if (pt->y >= h) pt->y = h-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if GINPUT_MOUSE_NEED_CALIBRATION
|
|
||||||
static inline void _tsSetIdentity(Calibration *c) {
|
|
||||||
c->ax = 1;
|
c->ax = 1;
|
||||||
c->bx = 0;
|
c->bx = 0;
|
||||||
c->cx = 0;
|
c->cx = 0;
|
||||||
|
@ -127,7 +52,7 @@ void _tsOrientClip(MouseReading *pt, GDisplay *g, bool_t doClip) {
|
||||||
c->cy = 0;
|
c->cy = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void _tsDrawCross(const MousePoint *pp) {
|
static inline void _tsDrawCross(const point *pp) {
|
||||||
gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y, pp->x-2, pp->y, White);
|
gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y, pp->x-2, pp->y, White);
|
||||||
gdispGDrawLine(MouseConfig.display, pp->x+2, pp->y, pp->x+15, pp->y, White);
|
gdispGDrawLine(MouseConfig.display, pp->x+2, pp->y, pp->x+15, pp->y, White);
|
||||||
gdispGDrawLine(MouseConfig.display, pp->x, pp->y-15, pp->x, pp->y-2, White);
|
gdispGDrawLine(MouseConfig.display, pp->x, pp->y-15, pp->x, pp->y-2, White);
|
||||||
|
@ -250,143 +175,208 @@ void _tsOrientClip(MouseReading *pt, GDisplay *g, bool_t doClip) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if GINPUT_MOUSE_READ_CYCLES > 1
|
static void DoMouseReading(MouseInstance *pm) {
|
||||||
static void get_raw_reading(MouseReading *pt) {
|
MouseReading r;
|
||||||
int32_t x, y, z;
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
x = y = z = 0;
|
pm->vmt->get(pm, &r);
|
||||||
for(i = 0; i < GINPUT_MOUSE_READ_CYCLES; i++) {
|
|
||||||
ginput_lld_mouse_get_reading(pt);
|
// If touch then calculate button 1 from z
|
||||||
x += pt->x;
|
if ((pm->vmt->flags & GMOUSE_VFLG_TOUCH)) {
|
||||||
y += pt->y;
|
if (pm->vmt->z_min <= pm->vmt->z_max) {
|
||||||
z += pt->z;
|
if (r.z >= pm->vmt->z_touchon) r.buttons |= GINPUT_MOUSE_BTN_LEFT;
|
||||||
|
else if (r.z <= pm->vmt->z_touchoff) r.buttons &= ~GINPUT_MOUSE_BTN_LEFT;
|
||||||
|
else return; // bad reading
|
||||||
|
} else {
|
||||||
|
if (r.z <= pm->vmt->z_touchon) r.buttons |= GINPUT_MOUSE_BTN_LEFT;
|
||||||
|
else if (r.z >= pm->vmt->z_touchoff) r.buttons &= ~GINPUT_MOUSE_BTN_LEFT;
|
||||||
|
else return; // bad reading
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Double check up & down events if needed
|
||||||
|
if ((pm->vmt->flags & GMOUSE_VFLG_POORUPDOWN)) {
|
||||||
|
// Are we in a transition test
|
||||||
|
if ((pm->flags & GMOUSE_FLG_INDELTA)) {
|
||||||
|
if (!((r.buttons ^ pm->r.buttons) & GINPUT_MOUSE_BTN_LEFT)) {
|
||||||
|
// Transition failed
|
||||||
|
pm->flags &= ~GMOUSE_FLG_INDELTA;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Transition succeeded
|
||||||
|
pm->flags &= ~GMOUSE_FLG_INDELTA;
|
||||||
|
|
||||||
|
// Should we start a transition test
|
||||||
|
} else if (((r.buttons ^ pm->r.buttons) & GINPUT_MOUSE_BTN_LEFT)) {
|
||||||
|
pm->flags |= GMOUSE_FLG_INDELTA;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the mouse is up we may need to keep our previous position
|
||||||
|
if ((pm->vmt->flags & GMOUSE_VFLG_ONLY_DOWN) && !(r.buttons & GINPUT_MOUSE_BTN_LEFT)) {
|
||||||
|
r.x = pm->r.x;
|
||||||
|
r.y = pm->r.y;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
coord_t w, h;
|
||||||
|
|
||||||
|
#if !GINPUT_TOUCH_NOCALIBRATE
|
||||||
|
// Do we need to calibrate the reading?
|
||||||
|
if ((pm->flags & GMOUSE_FLG_CALIBRATE))
|
||||||
|
_tsTransform(&r, &MouseConfig.caldata);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// We now need display information
|
||||||
|
w = gdispGGetWidth(g);
|
||||||
|
h = gdispGGetHeight(g);
|
||||||
|
|
||||||
|
#if GDISP_NEED_CONTROL
|
||||||
|
// Do we need to rotate the reading to match the display
|
||||||
|
if (!(pm->vmt->flags & GMOUSE_VFLG_SELFROTATION)) {
|
||||||
|
coord_t t;
|
||||||
|
|
||||||
|
switch(gdispGGetOrientation(g)) {
|
||||||
|
case GDISP_ROTATE_0:
|
||||||
|
break;
|
||||||
|
case GDISP_ROTATE_90:
|
||||||
|
t = r.x;
|
||||||
|
r.x = w - 1 - r.y;
|
||||||
|
r.y = t;
|
||||||
|
break;
|
||||||
|
case GDISP_ROTATE_180:
|
||||||
|
r.x = w - 1 - r.x;
|
||||||
|
r.y = h - 1 - r.y;
|
||||||
|
break;
|
||||||
|
case GDISP_ROTATE_270:
|
||||||
|
t = r.y;
|
||||||
|
r.y = h - 1 - r.x;
|
||||||
|
r.x = t;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Do we need to clip the reading to the display
|
||||||
|
if ((pm->flags & GMOUSE_FLG_CLIP)) {
|
||||||
|
if (r.x < 0) r.x = 0;
|
||||||
|
else if (r.x >= w) r.x = w-1;
|
||||||
|
if (r.y < 0) r.y = 0;
|
||||||
|
else if (r.y >= h) r.y = h-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MouseJitter *pj;
|
||||||
|
uint32_t diff;
|
||||||
|
|
||||||
|
// Are we in pen or finger mode
|
||||||
|
pj = (pm->flags & GMOUSE_FLG_FINGERMODE) ? &pm->vmt->finger_jitter : &pm->vmt->pen_jitter;
|
||||||
|
|
||||||
|
// Is this just movement jitter
|
||||||
|
if (pj->move > 0) {
|
||||||
|
diff = (uint32_t)(r.x - pm->r.x) * (uint32_t)(r.x - pm->r.x) + (uint32_t)(r.y - pm->r.y) * (uint32_t)(r.y - pm->r.y);
|
||||||
|
if (diff > (uint32_t)pj->move * (uint32_t)pj->move) {
|
||||||
|
r.x = pm->r.x;
|
||||||
|
r.y = pm->r.y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Take the average of the readings */
|
// Check if the click has moved outside the click area and if so cancel the click
|
||||||
pt->x = x / GINPUT_MOUSE_READ_CYCLES;
|
if (pj->click > 0 && (pm->flags & GMOUSE_FLG_CLICK_TIMER)) {
|
||||||
pt->y = y / GINPUT_MOUSE_READ_CYCLES;
|
diff = (uint32_t)(r.x - pm->clickpos.x) * (uint32_t)(r.x - pm->clickpos.x) + (uint32_t)(r.y - pm->clickpos.y) * (uint32_t)(r.y - pm->clickpos.y);
|
||||||
pt->z = z / GINPUT_MOUSE_READ_CYCLES;
|
if (diff > (uint32_t)pj->click * (uint32_t)pj->click)
|
||||||
|
pm->flags &= ~GMOUSE_FLG_CLICK_TIMER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#define get_raw_reading(pt) ginput_lld_mouse_get_reading(pt)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void get_calibrated_reading(MouseReading *pt) {
|
{
|
||||||
get_raw_reading(pt);
|
GSourceListener *psl;
|
||||||
|
GEventMouse *pe;
|
||||||
|
unsigned meta;
|
||||||
|
uint16_t upbtns, dnbtns;
|
||||||
|
|
||||||
#if GINPUT_MOUSE_NEED_CALIBRATION
|
// Calculate out new event meta value and handle CLICK and CXTCLICK
|
||||||
_tsTransform(pt, &MouseConfig.caldata);
|
dnbtns = r.buttons & ~pm->r.buttons;
|
||||||
#endif
|
upbtns = ~r.buttons & pm->r.buttons;
|
||||||
|
meta = GMETA_NONE;
|
||||||
|
|
||||||
_tsOrientClip(pt, MouseConfig.display, !(MouseConfig.flags & FLG_CAL_RAW));
|
// Mouse down
|
||||||
|
if ((dnbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
|
||||||
|
pm->clickpos.x = r.x;
|
||||||
|
pm->clickpos.y = r.y;
|
||||||
|
pm->clicktime = gfxSystemTicks();
|
||||||
|
pm->flags |= GMOUSE_FLG_CLICK_TIMER;
|
||||||
|
if ((dnbtns & GINPUT_MOUSE_BTN_LEFT))
|
||||||
|
meta |= GMETA_MOUSE_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mouse up
|
||||||
|
if ((upbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
|
||||||
|
if ((upbtns & GINPUT_MOUSE_BTN_LEFT))
|
||||||
|
meta |= GMETA_MOUSE_UP;
|
||||||
|
if ((pm->flags & GMOUSE_FLG_CLICK_TIMER)) {
|
||||||
|
if ((upbtns & GINPUT_MOUSE_BTN_LEFT)
|
||||||
|
#if GINPUT_TOUCH_CLICK_TIME != TIME_INFINITE
|
||||||
|
&& gfxSystemTicks() - pm->clicktime < gfxMillisecondsToTicks(GINPUT_TOUCH_CLICK_TIME)
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
meta |= GMETA_MOUSE_CLICK;
|
||||||
|
else
|
||||||
|
meta |= GMETA_MOUSE_CXTCLICK;
|
||||||
|
pm->flags &= ~GMOUSE_FLG_CLICK_TIMER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the event to the listeners that are interested.
|
||||||
|
psl = 0;
|
||||||
|
while ((psl = geventGetSourceListener((GSourceHandle)(&MouseConfig), psl))) {
|
||||||
|
if (!(pe = (GEventMouse *)geventGetEventBuffer(psl))) {
|
||||||
|
// This listener is missing - save the meta events that have happened
|
||||||
|
psl->srcflags |= meta;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we haven't really moved (and there are no meta events) don't bother sending the event
|
||||||
|
if (!meta && !psl->srcflags && !(psl->listenflags & GLISTEN_MOUSENOFILTER)
|
||||||
|
&& r.x == pm->r.x && r.y == pm->r.y && r.buttons == pm->r.buttons)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Send the event if we are listening for it
|
||||||
|
if (((r.buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEDOWNMOVES))
|
||||||
|
|| (!(r.buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEUPMOVES))
|
||||||
|
|| (meta && (psl->listenflags & GLISTEN_MOUSEMETA))) {
|
||||||
|
pe->type = GINPUT_MOUSE_EVENT_TYPE;
|
||||||
|
pe->instance = 0;
|
||||||
|
pe->x = r.x;
|
||||||
|
pe->y = r.y;
|
||||||
|
pe->z = r.z;
|
||||||
|
pe->current_buttons = r.buttons;
|
||||||
|
pe->last_buttons = pm->r.buttons;
|
||||||
|
pe->meta = meta;
|
||||||
|
if (psl->srcflags) {
|
||||||
|
pe->current_buttons |= GINPUT_MISSED_MOUSE_EVENT;
|
||||||
|
pe->meta |= psl->srcflags;
|
||||||
|
psl->srcflags = 0;
|
||||||
|
}
|
||||||
|
pe->display = pm->display;
|
||||||
|
geventSendEvent(psl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally save the results
|
||||||
|
pm->r.x = r.x;
|
||||||
|
pm->r.y = r.y;
|
||||||
|
pm->r.z = r.z;
|
||||||
|
pm->r.buttons = r.buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MousePoll(void *param) {
|
static void MousePoll(void *param) {
|
||||||
(void) param;
|
(void) param;
|
||||||
GSourceListener *psl;
|
|
||||||
GEventMouse *pe;
|
|
||||||
unsigned meta;
|
|
||||||
uint16_t upbtns, dnbtns;
|
|
||||||
uint32_t cdiff;
|
|
||||||
uint32_t mdiff;
|
|
||||||
|
|
||||||
// Save the last mouse state
|
DoMouseReading(stuff in here);
|
||||||
MouseConfig.last_buttons = MouseConfig.t.buttons;
|
|
||||||
|
|
||||||
// Get the new mouse reading
|
|
||||||
get_calibrated_reading(&MouseConfig.t);
|
|
||||||
|
|
||||||
// Calculate out new event meta value and handle CLICK and CXTCLICK
|
|
||||||
dnbtns = MouseConfig.t.buttons & ~MouseConfig.last_buttons;
|
|
||||||
upbtns = ~MouseConfig.t.buttons & MouseConfig.last_buttons;
|
|
||||||
meta = GMETA_NONE;
|
|
||||||
|
|
||||||
// As the touch moves up we need to return a point at the old position because some
|
|
||||||
// controllers return garbage with the mouse up
|
|
||||||
if ((upbtns & GINPUT_MOUSE_BTN_LEFT)) {
|
|
||||||
MouseConfig.t.x = MouseConfig.movepos.x;
|
|
||||||
MouseConfig.t.y = MouseConfig.movepos.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the position difference from our movement reference (update the reference if out of range)
|
|
||||||
mdiff = (MouseConfig.t.x - MouseConfig.movepos.x) * (MouseConfig.t.x - MouseConfig.movepos.x) +
|
|
||||||
(MouseConfig.t.y - MouseConfig.movepos.y) * (MouseConfig.t.y - MouseConfig.movepos.y);
|
|
||||||
if (mdiff > GINPUT_MOUSE_MAX_MOVE_JITTER * GINPUT_MOUSE_MAX_MOVE_JITTER) {
|
|
||||||
MouseConfig.movepos.x = MouseConfig.t.x;
|
|
||||||
MouseConfig.movepos.y = MouseConfig.t.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the click has moved outside the click area and if so cancel the click
|
|
||||||
if ((MouseConfig.flags & FLG_CLICK_TIMER)) {
|
|
||||||
cdiff = (MouseConfig.t.x - MouseConfig.clickpos.x) * (MouseConfig.t.x - MouseConfig.clickpos.x) +
|
|
||||||
(MouseConfig.t.y - MouseConfig.clickpos.y) * (MouseConfig.t.y - MouseConfig.clickpos.y);
|
|
||||||
if (cdiff > GINPUT_MOUSE_MAX_CLICK_JITTER * GINPUT_MOUSE_MAX_CLICK_JITTER)
|
|
||||||
MouseConfig.flags &= ~FLG_CLICK_TIMER;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mouse down
|
|
||||||
if ((dnbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
|
|
||||||
MouseConfig.clickpos.x = MouseConfig.t.x;
|
|
||||||
MouseConfig.clickpos.y = MouseConfig.t.y;
|
|
||||||
MouseConfig.clicktime = gfxSystemTicks();
|
|
||||||
MouseConfig.flags |= FLG_CLICK_TIMER;
|
|
||||||
if ((dnbtns & GINPUT_MOUSE_BTN_LEFT))
|
|
||||||
meta |= GMETA_MOUSE_DOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mouse up
|
|
||||||
if ((upbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
|
|
||||||
if ((upbtns & GINPUT_MOUSE_BTN_LEFT))
|
|
||||||
meta |= GMETA_MOUSE_UP;
|
|
||||||
if ((MouseConfig.flags & FLG_CLICK_TIMER)) {
|
|
||||||
if ((upbtns & GINPUT_MOUSE_BTN_LEFT)
|
|
||||||
#if GINPUT_MOUSE_CLICK_TIME != TIME_INFINITE
|
|
||||||
&& gfxSystemTicks() - MouseConfig.clicktime < gfxMillisecondsToTicks(GINPUT_MOUSE_CLICK_TIME)
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
meta |= GMETA_MOUSE_CLICK;
|
|
||||||
else
|
|
||||||
meta |= GMETA_MOUSE_CXTCLICK;
|
|
||||||
MouseConfig.flags &= ~FLG_CLICK_TIMER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the event to the listeners that are interested.
|
|
||||||
psl = 0;
|
|
||||||
while ((psl = geventGetSourceListener((GSourceHandle)(&MouseConfig), psl))) {
|
|
||||||
if (!(pe = (GEventMouse *)geventGetEventBuffer(psl))) {
|
|
||||||
// This listener is missing - save the meta events that have happened
|
|
||||||
psl->srcflags |= meta;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we haven't really moved (and there are no meta events) don't bother sending the event
|
|
||||||
if (mdiff <= GINPUT_MOUSE_MAX_MOVE_JITTER * GINPUT_MOUSE_MAX_MOVE_JITTER && !psl->srcflags
|
|
||||||
&& !meta && MouseConfig.last_buttons == MouseConfig.t.buttons && !(psl->listenflags & GLISTEN_MOUSENOFILTER))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Send the event if we are listening for it
|
|
||||||
if (((MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEDOWNMOVES))
|
|
||||||
|| (!(MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEUPMOVES))
|
|
||||||
|| (meta && (psl->listenflags & GLISTEN_MOUSEMETA))) {
|
|
||||||
pe->type = GINPUT_MOUSE_EVENT_TYPE;
|
|
||||||
pe->instance = 0;
|
|
||||||
pe->x = MouseConfig.t.x;
|
|
||||||
pe->y = MouseConfig.t.y;
|
|
||||||
pe->z = MouseConfig.t.z;
|
|
||||||
pe->current_buttons = MouseConfig.t.buttons;
|
|
||||||
pe->last_buttons = MouseConfig.last_buttons;
|
|
||||||
pe->meta = meta;
|
|
||||||
if (psl->srcflags) {
|
|
||||||
pe->current_buttons |= GINPUT_MISSED_MOUSE_EVENT;
|
|
||||||
pe->meta |= psl->srcflags;
|
|
||||||
psl->srcflags = 0;
|
|
||||||
}
|
|
||||||
pe->display = MouseConfig.display;
|
|
||||||
geventSendEvent(psl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GSourceHandle ginputGetMouse(uint16_t instance) {
|
GSourceHandle ginputGetMouse(uint16_t instance) {
|
||||||
|
@ -481,7 +471,8 @@ bool_t ginputGetMouseStatus(uint16_t instance, GEventMouse *pe) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t ginputCalibrateMouse(uint16_t instance) {
|
bool_t ginputCalibrateMouse(uint16_t instance) {
|
||||||
#if !GINPUT_MOUSE_NEED_CALIBRATION
|
#if GINPUT_TOUCH_NOCALIBRATE
|
||||||
|
|
||||||
(void) instance;
|
(void) instance;
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
@ -73,40 +73,41 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* @brief Use a custom board definition for the mouse/touch driver even if a board definition exists.
|
* @brief Turn off touch mouse support.
|
||||||
* @details Defaults to FALSE
|
* @details Defaults to FALSE
|
||||||
* @details If TRUE, add ginput_lld_mouse_board.h to your project directory and customise it.
|
* @note Touch device handling requires a lot of code. If your mouse doesn't require it
|
||||||
* @note Not all GINPUT mouse/touch low level drivers use board definition files.
|
* this can be turned off to save a lot of space.
|
||||||
*/
|
*/
|
||||||
#ifndef GINPUT_MOUSE_USE_CUSTOM_BOARD
|
#ifndef GINPUT_TOUCH_NOTOUCH
|
||||||
#define GINPUT_MOUSE_USE_CUSTOM_BOARD FALSE
|
#define GINPUT_TOUCH_NOTOUCH FALSE
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* @brief Use a custom board definition for the keyboard driver even if a board definition exists.
|
* @brief Turn off calibration support.
|
||||||
* @details Defaults to FALSE
|
* @details Defaults to FALSE
|
||||||
* @details If TRUE, add ginput_lld_keyboard_board.h to your project directory and customise it.
|
* @note Calibration requires a lot of code. If your mouse doesn't require it
|
||||||
* @note Not all GINPUT keyboard low level drivers use board definition files.
|
* this can be turned off to save a lot of space.
|
||||||
*/
|
*/
|
||||||
#ifndef GINPUT_KEYBOARD_USE_CUSTOM_BOARD
|
#ifndef GINPUT_TOUCH_NOCALIBRATE
|
||||||
#define GINPUT_KEYBOARD_USE_CUSTOM_BOARD FALSE
|
#define GINPUT_TOUCH_NOCALIBRATE FALSE
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* @brief Use a custom board definition for the toggle driver even if a board definition exists.
|
* @brief Milliseconds between mouse polls.
|
||||||
* @details Defaults to FALSE
|
* @details Defaults to 25 millseconds
|
||||||
* @details If TRUE, add ginput_lld_toggle_board.h to your project directory and customise it.
|
* @note How often mice should be polled. More often leads to smoother mouse movement
|
||||||
* @note Not all GINPUT toggle low level drivers use board definition files.
|
* but increases CPU usage. If no mouse drivers need polling the poll is not
|
||||||
|
* started.
|
||||||
*/
|
*/
|
||||||
#ifndef GINPUT_TOGGLE_USE_CUSTOM_BOARD
|
#ifndef GINPUT_MOUSE_POLL_PERIOD
|
||||||
#define GINPUT_TOGGLE_USE_CUSTOM_BOARD FALSE
|
#define GINPUT_MOUSE_POLL_PERIOD 25
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Use a custom board definition for the dial driver even if a board definition exists.
|
* @brief Milliseconds separating a CLICK from a CXTCLICK.
|
||||||
* @details Defaults to FALSE
|
* @details Defaults to 700 millseconds
|
||||||
* @details If TRUE, add ginput_lld_dial_board.h to your project directory and customise it.
|
* @note How long it takes for a click to turn into a CXTCLICK on a touch device.
|
||||||
* @note Not all GINPUT dial low level drivers use board definition files.
|
|
||||||
*/
|
*/
|
||||||
#ifndef GINPUT_DIAL_USE_CUSTOM_BOARD
|
#ifndef GINPUT_TOUCH_CLICK_TIME
|
||||||
#define GINPUT_DIAL_USE_CUSTOM_BOARD FALSE
|
#define GINPUT_TOUCH_CLICK_TIME 700
|
||||||
#endif
|
#endif
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue