aboutsummaryrefslogtreecommitdiffstats
path: root/src/ginput
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2014-07-02 09:40:01 +1000
committerinmarket <andrewh@inmarket.com.au>2014-07-02 09:40:01 +1000
commit92d972cfd83b67961dc63d60c5317ec2651eb256 (patch)
treec52c0f2b46a02466cae70fa2c08d54d964129ef5 /src/ginput
parent1a2e98af967d4433e98c5fa388cb816b1af46e2d (diff)
downloaduGFX-92d972cfd83b67961dc63d60c5317ec2651eb256.tar.gz
uGFX-92d972cfd83b67961dc63d60c5317ec2651eb256.tar.bz2
uGFX-92d972cfd83b67961dc63d60c5317ec2651eb256.zip
First part new mouse infrastructure
Diffstat (limited to 'src/ginput')
-rw-r--r--src/ginput/driver_mouse.h193
-rw-r--r--src/ginput/mouse.c389
-rw-r--r--src/ginput/sys_options.h45
3 files changed, 297 insertions, 330 deletions
diff --git a/src/ginput/driver_mouse.h b/src/ginput/driver_mouse.h
index 21d87dac..c60b9a0e 100644
--- a/src/ginput/driver_mouse.h
+++ b/src/ginput/driver_mouse.h
@@ -19,67 +19,80 @@
#if GINPUT_NEED_MOUSE || defined(__DOXYGEN__)
-#include "ginput_lld_mouse_config.h"
-
-// 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
+typedef struct MouseReading {
+ coord_t x, y, z;
+ uint16_t buttons;
+ } MouseReading;
-// ms - Millisecs seperating a CLICK from a CXTCLICK
-#ifndef GINPUT_MOUSE_CLICK_TIME
- #define GINPUT_MOUSE_CLICK_TIME 700
+#if !GINPUT_TOUCH_NOCALIBRATE
+ typedef struct MouseCalibration {
+ float ax;
+ float bx;
+ float cx;
+ float ay;
+ float by;
+ float cy;
+ } MouseCalibration;
#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 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;
-typedef struct MouseReading_t {
- coord_t x, y, z;
- uint16_t buttons;
- } MouseReading;
+#include "ginput_lld_mouse_config.h"
/*===========================================================================*/
/* External declarations. */
@@ -88,70 +101,33 @@ typedef struct MouseReading_t {
#ifdef __cplusplus
extern "C" {
#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
*/
- void ginput_lld_mouse_init(void);
+ MouseInstance *ginputMouseGetNewMouseForDisplay(const MOUSEVMT *vmt, GDisplay *g);
/**
- * @brief Read the mouse/touch position.
- *
- * @param[in] pt A pointer to the structure to fill
- *
- * @note For drivers that don't support returning a position
- * 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.
+ * @brief Release a mouse
+ * @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.
+ * When the display has finished with the mouse it can release it.
*
* @notapi
*/
- void ginput_lld_mouse_get_reading(MouseReading *pt);
-
- #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
+ void ginputMouseGetNewMouseForDisplay(MouseIntance *pmouse);
/**
* @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 Particularly useful if GINPUT_MOUSE_POLL_PERIOD = TIME_INFINITE
*
* @notapi
*/
@@ -161,7 +137,6 @@ extern "C" {
* @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 Particularly useful if GINPUT_MOUSE_POLL_PERIOD = TIME_INFINITE
*
* @iclass
* @notapi
@@ -172,7 +147,7 @@ extern "C" {
}
#endif
-#endif /* GINPUT_NEED_MOUSE || GINPUT_NEED_TOUCH */
+#endif /* GINPUT_NEED_MOUSE */
#endif /* _LLD_GINPUT_MOUSE_H */
/** @} */
diff --git a/src/ginput/mouse.c b/src/ginput/mouse.c
index f7842e33..1f1a18fe 100644
--- a/src/ginput/mouse.c
+++ b/src/ginput/mouse.c
@@ -19,7 +19,7 @@
#include "src/ginput/driver_mouse.h"
-#if GINPUT_MOUSE_NEED_CALIBRATION
+#if !GINPUT_TOUCH_NOCALIBRATE
#if !defined(GFX_USE_GDISP) || !GFX_USE_GDISP
#error "GINPUT: GFX_USE_GDISP must be defined when mouse or touch calibration is required"
#endif
@@ -38,87 +38,12 @@
#define GINPUT_MOUSE_CALIBRATION_POINTS 4
#endif
- typedef struct Calibration_t {
- float ax;
- float bx;
- float cx;
- float ay;
- float by;
- float cy;
- } Calibration;
-#endif
-
-typedef struct MousePoint_t {
- coord_t x, y;
-} MousePoint;
+endif
static GTIMER_DECL(MouseTimer);
-static struct MouseConfig_t {
- MouseReading t;
- 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) {
+#if !GINPUT_TOUCH_NOCALIBRATE
+ static inline void _tsSetIdentity(MouseCalibration *c) {
c->ax = 1;
c->bx = 0;
c->cx = 0;
@@ -127,7 +52,7 @@ void _tsOrientClip(MouseReading *pt, GDisplay *g, bool_t doClip) {
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+2, pp->y, pp->x+15, pp->y, 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
-#if GINPUT_MOUSE_READ_CYCLES > 1
- static void get_raw_reading(MouseReading *pt) {
- int32_t x, y, z;
- unsigned i;
-
- x = y = z = 0;
- for(i = 0; i < GINPUT_MOUSE_READ_CYCLES; i++) {
- ginput_lld_mouse_get_reading(pt);
- x += pt->x;
- y += pt->y;
- z += pt->z;
+static void DoMouseReading(MouseInstance *pm) {
+ MouseReading r;
+
+ pm->vmt->get(pm, &r);
+
+ // If touch then calculate button 1 from z
+ if ((pm->vmt->flags & GMOUSE_VFLG_TOUCH)) {
+ if (pm->vmt->z_min <= pm->vmt->z_max) {
+ 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;
- /* Take the average of the readings */
- pt->x = x / GINPUT_MOUSE_READ_CYCLES;
- pt->y = y / GINPUT_MOUSE_READ_CYCLES;
- pt->z = z / GINPUT_MOUSE_READ_CYCLES;
+ // Should we start a transition test
+ } else if (((r.buttons ^ pm->r.buttons) & GINPUT_MOUSE_BTN_LEFT)) {
+ pm->flags |= GMOUSE_FLG_INDELTA;
+ return;
+ }
}
-#else
- #define get_raw_reading(pt) ginput_lld_mouse_get_reading(pt)
-#endif
-static void get_calibrated_reading(MouseReading *pt) {
- get_raw_reading(pt);
+ // 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;
- #if GINPUT_MOUSE_NEED_CALIBRATION
- _tsTransform(pt, &MouseConfig.caldata);
- #endif
+ } else {
+ coord_t w, h;
- _tsOrientClip(pt, MouseConfig.display, !(MouseConfig.flags & FLG_CAL_RAW));
-}
+ #if !GINPUT_TOUCH_NOCALIBRATE
+ // Do we need to calibrate the reading?
+ if ((pm->flags & GMOUSE_FLG_CALIBRATE))
+ _tsTransform(&r, &MouseConfig.caldata);
+ #endif
-static void MousePoll(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
- 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;
- }
+ // We now need display information
+ w = gdispGGetWidth(g);
+ h = gdispGGetHeight(g);
- // 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;
- }
+ #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
- // 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;
+ // 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;
+ }
}
- // 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;
+ {
+ 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;
+ }
+ }
+
+ // Check if the click has moved outside the click area and if so cancel the click
+ if (pj->click > 0 && (pm->flags & GMOUSE_FLG_CLICK_TIMER)) {
+ 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);
+ if (diff > (uint32_t)pj->click * (uint32_t)pj->click)
+ 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;
+ {
+ GSourceListener *psl;
+ GEventMouse *pe;
+ unsigned meta;
+ uint16_t upbtns, dnbtns;
+
+ // Calculate out new event meta value and handle CLICK and CXTCLICK
+ dnbtns = r.buttons & ~pm->r.buttons;
+ upbtns = ~r.buttons & pm->r.buttons;
+ meta = GMETA_NONE;
+
+ // 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;
+ }
}
- // 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;
+ // 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);
}
- pe->display = MouseConfig.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) {
+ (void) param;
+
+ DoMouseReading(stuff in here);
}
GSourceHandle ginputGetMouse(uint16_t instance) {
@@ -481,7 +471,8 @@ bool_t ginputGetMouseStatus(uint16_t instance, GEventMouse *pe) {
}
bool_t ginputCalibrateMouse(uint16_t instance) {
- #if !GINPUT_MOUSE_NEED_CALIBRATION
+ #if GINPUT_TOUCH_NOCALIBRATE
+
(void) instance;
return FALSE;
diff --git a/src/ginput/sys_options.h b/src/ginput/sys_options.h
index c606262b..7ccc7b78 100644
--- a/src/ginput/sys_options.h
+++ b/src/ginput/sys_options.h
@@ -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 If TRUE, add ginput_lld_mouse_board.h to your project directory and customise it.
- * @note Not all GINPUT mouse/touch low level drivers use board definition files.
+ * @note Touch device handling requires a lot of code. If your mouse doesn't require it
+ * this can be turned off to save a lot of space.
*/
- #ifndef GINPUT_MOUSE_USE_CUSTOM_BOARD
- #define GINPUT_MOUSE_USE_CUSTOM_BOARD FALSE
+ #ifndef GINPUT_TOUCH_NOTOUCH
+ #define GINPUT_TOUCH_NOTOUCH FALSE
#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 If TRUE, add ginput_lld_keyboard_board.h to your project directory and customise it.
- * @note Not all GINPUT keyboard low level drivers use board definition files.
+ * @note Calibration requires a lot of code. If your mouse doesn't require it
+ * this can be turned off to save a lot of space.
*/
- #ifndef GINPUT_KEYBOARD_USE_CUSTOM_BOARD
- #define GINPUT_KEYBOARD_USE_CUSTOM_BOARD FALSE
+ #ifndef GINPUT_TOUCH_NOCALIBRATE
+ #define GINPUT_TOUCH_NOCALIBRATE FALSE
#endif
/**
- * @brief Use a custom board definition for the toggle driver even if a board definition exists.
- * @details Defaults to FALSE
- * @details If TRUE, add ginput_lld_toggle_board.h to your project directory and customise it.
- * @note Not all GINPUT toggle low level drivers use board definition files.
+ * @brief Milliseconds between mouse polls.
+ * @details Defaults to 25 millseconds
+ * @note How often mice should be polled. More often leads to smoother mouse movement
+ * but increases CPU usage. If no mouse drivers need polling the poll is not
+ * started.
*/
- #ifndef GINPUT_TOGGLE_USE_CUSTOM_BOARD
- #define GINPUT_TOGGLE_USE_CUSTOM_BOARD FALSE
+ #ifndef GINPUT_MOUSE_POLL_PERIOD
+ #define GINPUT_MOUSE_POLL_PERIOD 25
#endif
+
/**
- * @brief Use a custom board definition for the dial driver even if a board definition exists.
- * @details Defaults to FALSE
- * @details If TRUE, add ginput_lld_dial_board.h to your project directory and customise it.
- * @note Not all GINPUT dial low level drivers use board definition files.
+ * @brief Milliseconds separating a CLICK from a CXTCLICK.
+ * @details Defaults to 700 millseconds
+ * @note How long it takes for a click to turn into a CXTCLICK on a touch device.
*/
- #ifndef GINPUT_DIAL_USE_CUSTOM_BOARD
- #define GINPUT_DIAL_USE_CUSTOM_BOARD FALSE
+ #ifndef GINPUT_TOUCH_CLICK_TIME
+ #define GINPUT_TOUCH_CLICK_TIME 700
#endif
/** @} */