diff options
Diffstat (limited to 'src/ginput/ginput_mouse.c')
-rw-r--r-- | src/ginput/ginput_mouse.c | 714 |
1 files changed, 366 insertions, 348 deletions
diff --git a/src/ginput/ginput_mouse.c b/src/ginput/ginput_mouse.c index a0daba98..ee6f51b6 100644 --- a/src/ginput/ginput_mouse.c +++ b/src/ginput/ginput_mouse.c @@ -19,106 +19,29 @@ #include "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 #include <string.h> // Required for memcpy - #define GINPUT_MOUSE_CALIBRATION_FONT "* Double" - #define GINPUT_MOUSE_CALIBRATION_FONT2 "* Narrow" - #define GINPUT_MOUSE_CALIBRATION_TEXT "Calibration" - #define GINPUT_MOUSE_CALIBRATION_ERROR_TEXT "Failed - Please try again!" - #define GINPUT_MOUSE_CALIBRATION_SAME_TEXT "Error: Same Reading - Check Driver!" + #define CALIBRATION_FONT "* Double" + #define CALIBRATION_FONT2 "* Narrow" + #define CALIBRATION_TEXT "Calibration" + #define CALIBRATION_ERROR_TEXT "Failed - Please try again!" + #define CALIBRATION_SAME_TEXT "Error: Same Reading - Check Driver!" + #define CALIBRATION_BACKGROUND Blue + #define CALIBRATION_COLOR1 White + #define CALIBRATION_COLOR2 RGB2COLOR(184,158,131) - #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR < 0 - #define GINPUT_MOUSE_CALIBRATION_POINTS 3 - #else - #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; - 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 CalibrationSetIdentity(MouseCalibration *c) { c->ax = 1; c->bx = 0; c->cx = 0; @@ -126,334 +49,427 @@ void _tsOrientClip(MouseReading *pt, GDisplay *g, bool_t doClip) { c->by = 1; c->cy = 0; } - - static inline void _tsDrawCross(const MousePoint *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); - gdispGDrawLine(MouseConfig.display, pp->x, pp->y+2, pp->x, pp->y+15, White); - - gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y+15, pp->x-7, pp->y+15, RGB2COLOR(184,158,131)); - gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y+7, pp->x-15, pp->y+15, RGB2COLOR(184,158,131)); - - gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y-15, pp->x-7, pp->y-15, RGB2COLOR(184,158,131)); - gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y-7, pp->x-15, pp->y-15, RGB2COLOR(184,158,131)); - - gdispGDrawLine(MouseConfig.display, pp->x+7, pp->y+15, pp->x+15, pp->y+15, RGB2COLOR(184,158,131)); - gdispGDrawLine(MouseConfig.display, pp->x+15, pp->y+7, pp->x+15, pp->y+15, RGB2COLOR(184,158,131)); - - gdispGDrawLine(MouseConfig.display, pp->x+7, pp->y-15, pp->x+15, pp->y-15, RGB2COLOR(184,158,131)); - gdispGDrawLine(MouseConfig.display, pp->x+15, pp->y-15, pp->x+15, pp->y-7, RGB2COLOR(184,158,131)); + */ + + static inline void CalibrationCrossDraw(GMouse *m, const point *pp) { + gdispGDrawLine(m->display, pp->x-15, pp->y, pp->x-2, pp->y, CALIBRATION_COLOR1); + gdispGDrawLine(m->display, pp->x+2, pp->y, pp->x+15, pp->y, CALIBRATION_COLOR1); + gdispGDrawLine(m->display, pp->x, pp->y-15, pp->x, pp->y-2, CALIBRATION_COLOR1); + gdispGDrawLine(m->display, pp->x, pp->y+2, pp->x, pp->y+15, CALIBRATION_COLOR1); + gdispGDrawLine(m->display, pp->x-15, pp->y+15, pp->x-7, pp->y+15, CALIBRATION_COLOR2); + gdispGDrawLine(m->display, pp->x-15, pp->y+7, pp->x-15, pp->y+15, CALIBRATION_COLOR2); + gdispGDrawLine(m->display, pp->x-15, pp->y-15, pp->x-7, pp->y-15, CALIBRATION_COLOR2); + gdispGDrawLine(m->display, pp->x-15, pp->y-7, pp->x-15, pp->y-15, CALIBRATION_COLOR2); + gdispGDrawLine(m->display, pp->x+7, pp->y+15, pp->x+15, pp->y+15, CALIBRATION_COLOR2); + gdispGDrawLine(m->display, pp->x+15, pp->y+7, pp->x+15, pp->y+15, CALIBRATION_COLOR2); + gdispGDrawLine(m->display, pp->x+7, pp->y-15, pp->x+15, pp->y-15, CALIBRATION_COLOR2); + gdispGDrawLine(m->display, pp->x+15, pp->y-15, pp->x+15, pp->y-7, CALIBRATION_COLOR2); } - static inline void _tsClearCross(const MousePoint *pp) { - gdispGFillArea(MouseConfig.display, pp->x - 15, pp->y - 15, 42, 42, Blue); + static inline void CalibrationCrossClear(GMouse *m, const point *pp) { + gdispGFillArea(m->display, pp->x - 15, pp->y - 15, 32, 32, CALIBRATION_BACKGROUND); } - static inline void _tsTransform(MouseReading *pt, const Calibration *c) { + static inline void CalibrationTransform(GMouseReading *pt, const GMouseCalibration *c) { pt->x = (coord_t) (c->ax * pt->x + c->bx * pt->y + c->cx); pt->y = (coord_t) (c->ay * pt->x + c->by * pt->y + c->cy); } - static inline void _tsDo3PointCalibration(const MousePoint *cross, const MousePoint *points, GDisplay *g, Calibration *c) { + static inline void CalibrationCalculate(GMouse *m, const point *cross, const point *points) { float dx; coord_t c0, c1, c2; + (void) m; + + // Work on x values + c0 = cross[0].x; + c1 = cross[1].x; + c2 = cross[2].x; #if GDISP_NEED_CONTROL - /* Convert all cross points back to GDISP_ROTATE_0 convention - * before calculating the calibration matrix. - */ - switch(gdispGGetOrientation(g)) { - case GDISP_ROTATE_90: - c0 = cross[0].y; - c1 = cross[1].y; - c2 = cross[2].y; - break; - case GDISP_ROTATE_180: - c0 = c1 = c2 = gdispGGetWidth(g) - 1; - c0 -= cross[0].x; - c1 -= cross[1].x; - c2 -= cross[2].x; - break; - case GDISP_ROTATE_270: - c0 = c1 = c2 = gdispGGetHeight(g) - 1; - c0 -= cross[0].y; - c1 -= cross[1].y; - c2 -= cross[2].y; - break; - case GDISP_ROTATE_0: - default: - c0 = cross[0].x; - c1 = cross[1].x; - c2 = cross[2].x; - break; + if (!(gmvmt(m)->d.flags & GMOUSE_VFLG_SELFROTATION)) { + /* Convert all cross points back to GDISP_ROTATE_0 convention + * before calculating the calibration matrix. + */ + switch(gdispGGetOrientation(m->display)) { + case GDISP_ROTATE_90: + c0 = cross[0].y; + c1 = cross[1].y; + c2 = cross[2].y; + break; + case GDISP_ROTATE_180: + c0 = c1 = c2 = gdispGGetWidth(m->display) - 1; + c0 -= cross[0].x; + c1 -= cross[1].x; + c2 -= cross[2].x; + break; + case GDISP_ROTATE_270: + c0 = c1 = c2 = gdispGGetHeight(m->display) - 1; + c0 -= cross[0].y; + c1 -= cross[1].y; + c2 -= cross[2].y; + break; + default: + break; + } } - #else - (void) g; - - c0 = cross[0].x; - c1 = cross[1].x; - c2 = cross[2].x; #endif /* Compute all the required determinants */ dx = (float)(points[0].x - points[2].x) * (float)(points[1].y - points[2].y) - (float)(points[1].x - points[2].x) * (float)(points[0].y - points[2].y); - c->ax = ((float)(c0 - c2) * (float)(points[1].y - points[2].y) - - (float)(c1 - c2) * (float)(points[0].y - points[2].y)) / dx; - c->bx = ((float)(c1 - c2) * (float)(points[0].x - points[2].x) - - (float)(c0 - c2) * (float)(points[1].x - points[2].x)) / dx; - c->cx = (c0 * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y) - - c1 * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y) - + c2 * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y)) / dx; + m->caldata.ax = ((float)(c0 - c2) * (float)(points[1].y - points[2].y) + - (float)(c1 - c2) * (float)(points[0].y - points[2].y)) / dx; + m->caldata.bx = ((float)(c1 - c2) * (float)(points[0].x - points[2].x) + - (float)(c0 - c2) * (float)(points[1].x - points[2].x)) / dx; + m->caldata.cx = (c0 * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y) + - c1 * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y) + + c2 * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y)) / dx; + + // Work on y values + c0 = cross[0].y; + c1 = cross[1].y; + c2 = cross[2].y; #if GDISP_NEED_CONTROL - switch(gdispGGetOrientation(g)) { - case GDISP_ROTATE_90: - c0 = c1 = c2 = gdispGGetWidth(g) - 1; - c0 -= cross[0].x; - c1 -= cross[1].x; - c2 -= cross[2].x; - break; - case GDISP_ROTATE_180: - c0 = c1 = c2 = gdispGGetHeight(g) - 1; - c0 -= cross[0].y; - c1 -= cross[1].y; - c2 -= cross[2].y; - break; - case GDISP_ROTATE_270: - c0 = cross[0].x; - c1 = cross[1].x; - c2 = cross[2].x; - break; - case GDISP_ROTATE_0: - default: - c0 = cross[0].y; - c1 = cross[1].y; - c2 = cross[2].y; - break; + if (!(gmvmt(m)->d.flags & GMOUSE_VFLG_SELFROTATION)) { + switch(gdispGGetOrientation(m->display)) { + case GDISP_ROTATE_90: + c0 = c1 = c2 = gdispGGetWidth(m->display) - 1; + c0 -= cross[0].x; + c1 -= cross[1].x; + c2 -= cross[2].x; + break; + case GDISP_ROTATE_180: + c0 = c1 = c2 = gdispGGetHeight(m->display) - 1; + c0 -= cross[0].y; + c1 -= cross[1].y; + c2 -= cross[2].y; + break; + case GDISP_ROTATE_270: + c0 = cross[0].x; + c1 = cross[1].x; + c2 = cross[2].x; + break; + default: + break; + } } - #else - c0 = cross[0].y; - c1 = cross[1].y; - c2 = cross[2].y; #endif - c->ay = ((float)(c0 - c2) * (float)(points[1].y - points[2].y) - - (float)(c1 - c2) * (float)(points[0].y - points[2].y)) / dx; - c->by = ((float)(c1 - c2) * (float)(points[0].x - points[2].x) - - (float)(c0 - c2) * (float)(points[1].x - points[2].x)) / dx; - c->cy = (c0 * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y) - - c1 * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y) - + c2 * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y)) / dx; + m->caldata.ay = ((float)(c0 - c2) * (float)(points[1].y - points[2].y) + - (float)(c1 - c2) * (float)(points[0].y - points[2].y)) / dx; + m->caldata.by = ((float)(c1 - c2) * (float)(points[0].x - points[2].x) + - (float)(c0 - c2) * (float)(points[1].x - points[2].x)) / dx; + m->caldata.cy = (c0 * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y) + - c1 * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y) + + c2 * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y)) / dx; } #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 GetMouseReading(GMouse *m) { + GMouseReading r; + + // Get the raw reading. + gmvmt(m)->get(m, &r); + m->flags &= ~GMOUSE_FLG_NEEDREAD; + + // If touch then calculate button 0 from z + if ((gmvmt(m)->d.flags & GMOUSE_VFLG_TOUCH)) { + if (gmvmt(m)->z_min <= gmvmt(m)->z_max) { + if (r.z >= gmvmt(m)->z_touchon) r.buttons |= GINPUT_MOUSE_BTN_LEFT; + else if (r.z <= gmvmt(m)->z_touchoff) r.buttons &= ~GINPUT_MOUSE_BTN_LEFT; + else return; // bad transitional reading + } else { + if (r.z <= gmvmt(m)->z_touchon) r.buttons |= GINPUT_MOUSE_BTN_LEFT; + else if (r.z >= gmvmt(m)->z_touchoff) r.buttons &= ~GINPUT_MOUSE_BTN_LEFT; + else return; // bad transitional reading } + } + + // Double check up & down events if needed + if ((gmvmt(m)->d.flags & GMOUSE_VFLG_POORUPDOWN)) { + // Are we in a transition test + if ((m->flags & GMOUSE_FLG_INDELTA)) { + if (!((r.buttons ^ m->r.buttons) & GINPUT_MOUSE_BTN_LEFT)) { + // Transition failed + m->flags &= ~GMOUSE_FLG_INDELTA; + return; + } + // Transition succeeded + m->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 ^ m->r.buttons) & GINPUT_MOUSE_BTN_LEFT)) { + m->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 ((gmvmt(m)->d.flags & GMOUSE_VFLG_ONLY_DOWN) && !(r.buttons & GINPUT_MOUSE_BTN_LEFT)) { + r.x = m->r.x; + r.y = m->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 ((m->flags & GMOUSE_FLG_CALIBRATE)) + CalibrationTransform(&r, &m->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 can't clip or rotate if we don't have a display + if (m->display) { + + // We now need display information + w = gdispGGetWidth(m->display); + h = gdispGGetHeight(m->display); + + #if GDISP_NEED_CONTROL + // Do we need to rotate the reading to match the display + if (!(gmvmt(m)->d.flags & GMOUSE_VFLG_SELFROTATION)) { + coord_t t; + + switch(gdispGGetOrientation(m->display)) { + 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 - // 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; + // Do we need to clip the reading to the display + if ((m->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 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; - } + { + const GMouseJitter *pj; + uint32_t diff; + + // Are we in pen or finger mode + pj = (m->flags & GMOUSE_FLG_FINGERMODE) ? &gmvmt(m)->finger_jitter : &gmvmt(m)->pen_jitter; + + // Is this just movement jitter + if (pj->move > 0) { + diff = (uint32_t)(r.x - m->r.x) * (uint32_t)(r.x - m->r.x) + (uint32_t)(r.y - m->r.y) * (uint32_t)(r.y - m->r.y); + if (diff > (uint32_t)pj->move * (uint32_t)pj->move) { + r.x = m->r.x; + r.y = m->r.y; + } + } - // 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; + // Check if the click has moved outside the click area and if so cancel the click + if (pj->click > 0 && (m->flags & GMOUSE_FLG_CLICK_TIMER)) { + diff = (uint32_t)(r.x - m->clickpos.x) * (uint32_t)(r.x - m->clickpos.x) + (uint32_t)(r.y - m->clickpos.y) * (uint32_t)(r.y - m->clickpos.y); + if (diff > (uint32_t)pj->click * (uint32_t)pj->click) + m->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 & ~m->r.buttons; + upbtns = ~r.buttons & m->r.buttons; + meta = GMETA_NONE; + + // Mouse down + if ((dnbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) { + m->clickpos.x = r.x; + m->clickpos.y = r.y; + m->clicktime = gfxSystemTicks(); + m->flags |= GMOUSE_FLG_CLICK_TIMER; + if ((dnbtns & GINPUT_MOUSE_BTN_LEFT)) + meta |= GMETA_MOUSE_DOWN; } - // 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; + // Mouse up + if ((upbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) { + if ((upbtns & GINPUT_MOUSE_BTN_LEFT)) + meta |= GMETA_MOUSE_UP; + if ((m->flags & GMOUSE_FLG_CLICK_TIMER)) { + if ((upbtns & GINPUT_MOUSE_BTN_LEFT) + #if GINPUT_TOUCH_CLICK_TIME != TIME_INFINITE + && gfxSystemTicks() - m->clicktime < gfxMillisecondsToTicks(GINPUT_TOUCH_CLICK_TIME) + #endif + ) + meta |= GMETA_MOUSE_CLICK; + else + meta |= GMETA_MOUSE_CXTCLICK; + m->flags &= ~GMOUSE_FLG_CLICK_TIMER; + } + } + + // Send the event to the listeners that are interested. + psl = 0; + while ((psl = geventGetSourceListener((GSourceHandle)m, 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 == m->r.x && r.y == m->r.y && r.buttons == m->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 = (gmvmt(m)->d.flags & GMOUSE_VFLG_TOUCH) ? GEVENT_TOUCH : GEVENT_MOUSE; + pe->x = r.x; + pe->y = r.y; + pe->z = r.z; + pe->current_buttons = r.buttons; + pe->last_buttons = m->r.buttons; + pe->meta = meta; + if (psl->srcflags) { + pe->current_buttons |= GINPUT_MISSED_MOUSE_EVENT; + pe->meta |= psl->srcflags; + psl->srcflags = 0; + } + pe->display = m->display; + geventSendEvent(psl); } - pe->display = MouseConfig.display; - geventSendEvent(psl); } } + + // Finally save the results + m->r.x = r.x; + m->r.y = r.y; + m->r.z = r.z; + m->r.buttons = r.buttons; +} + +static void MousePoll(void *param) { + GMouse * m; + (void) param; + + for(m = (GMouse *)gdriverGetNext(GDRIVER_TYPE_MOUSE, 0); m; m = (GMouse *)gdriverGetNext(GDRIVER_TYPE_MOUSE, (GDriver *)m)) { + if (!(gmvmt(m)->d.flags & GMOUSE_VFLG_NOPOLL) || (m->flags & GMOUSE_FLG_NEEDREAD)) + GetMouseReading(m); + } +} + +void _gmouseInit(void) { + // GINPUT_MOUSE_DRIVER_LIST is defined - create each driver instance + #if defined(GINPUT_MOUSE_DRIVER_LIST) + { + int i; + + extern GDriverVMTList GINPUT_MOUSE_DRIVER_LIST; + static const struct GDriverVMT const * dclist[] = {GINPUT_MOUSE_DRIVER_LIST}; + static const unsigned dnlist[] = {GDISP_CONTROLLER_DISPLAYS}; + + for(i = 0; i < sizeof(dclist)/sizeof(dclist[0]); i++) + gdriverRegister(dclist[i]); + } + + // One and only one display + #else + { + extern GDriverVMTList GINPUTMOUSEVMT_OnlyOne; + + gdriverRegister(GINPUTMOUSEVMT_OnlyOne); + } + #endif +} + +void _gmouseDeinit(void) { } GSourceHandle ginputGetMouse(uint16_t instance) { + GMouse *m; #if GINPUT_MOUSE_NEED_CALIBRATION - Calibration *pc; + GCalibration *pc; #endif - // We only support a single mouse instance currently - // Instance 9999 is the same as instance 0 except that it installs - // a special "raw" calibration if there isn't one we can load. - if (instance && instance != 9999) - return 0; + if (!(m = (GMouse *)gdriverGetInstance(GDRIVER_TYPE_MOUSE, instance))) + return 0; // Make sure we have a valid mouse display - if (!MouseConfig.display) - MouseConfig.display = GDISP; + if (!m->display) + m->display = GDISP; // Do we need to initialise the mouse subsystem? - if (!(MouseConfig.flags & FLG_INIT_DONE)) { + if (!(m->flags & FLG_INIT_DONE)) { ginput_lld_mouse_init(); #if GINPUT_MOUSE_NEED_CALIBRATION #if GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE - if (!MouseConfig.fnloadcal) { - MouseConfig.fnloadcal = ginput_lld_mouse_calibration_load; - MouseConfig.flags &= ~FLG_CAL_FREE; + if (!m->fnloadcal) { + m->fnloadcal = ginput_lld_mouse_calibration_load; + m->flags &= ~FLG_CAL_FREE; } - if (!MouseConfig.fnsavecal) - MouseConfig.fnsavecal = ginput_lld_mouse_calibration_save; + if (!m->fnsavecal) + m->fnsavecal = ginput_lld_mouse_calibration_save; #endif - if (MouseConfig.fnloadcal && (pc = (Calibration *)MouseConfig.fnloadcal(instance))) { - memcpy(&MouseConfig.caldata, pc, sizeof(MouseConfig.caldata)); - MouseConfig.flags |= (FLG_CAL_OK|FLG_CAL_SAVED); - if ((MouseConfig.flags & FLG_CAL_FREE)) + if (m->fnloadcal && (pc = (Calibration *)m->fnloadcal(instance))) { + memcpy(&m->caldata, pc, sizeof(m->caldata)); + m->flags |= (FLG_CAL_OK|FLG_CAL_SAVED); + if ((m->flags & FLG_CAL_FREE)) gfxFree((void *)pc); } else if (instance == 9999) { - _tsSetIdentity(&MouseConfig.caldata); - MouseConfig.flags |= (FLG_CAL_OK|FLG_CAL_SAVED|FLG_CAL_RAW); + CalibrationSetIdentity(&m->caldata); + m->flags |= (FLG_CAL_OK|FLG_CAL_SAVED|FLG_CAL_RAW); } else ginputCalibrateMouse(instance); #endif // Get the first reading - MouseConfig.last_buttons = 0; - get_calibrated_reading(&MouseConfig.t); + m->last_buttons = 0; + get_calibrated_reading(&m->t); // Mark init as done and start the Poll timer - MouseConfig.flags |= FLG_INIT_DONE; + m->flags |= FLG_INIT_DONE; gtimerStart(&MouseTimer, MousePoll, 0, TRUE, GINPUT_MOUSE_POLL_PERIOD); } // Return our structure as the handle - return (GSourceHandle)&MouseConfig; + return (GSourceHandle)m; } void ginputSetMouseDisplay(uint16_t instance, GDisplay *g) { if (instance) return; - MouseConfig.display = g ? g : GDISP; + m->display = g ? g : GDISP; } GDisplay *ginputGetMouseDisplay(uint16_t instance) { if (instance) return 0; - return MouseConfig.display; + return m->display; } bool_t ginputGetMouseStatus(uint16_t instance, GEventMouse *pe) { @@ -461,16 +477,15 @@ bool_t ginputGetMouseStatus(uint16_t instance, GEventMouse *pe) { // so we add a sleep here to prevent 100% polled applications from locking up. gfxSleepMilliseconds(1); - if (instance || (MouseConfig.flags & (FLG_INIT_DONE|FLG_IN_CAL)) != FLG_INIT_DONE) + if (instance || (m->flags & (FLG_INIT_DONE|FLG_IN_CAL)) != FLG_INIT_DONE) return FALSE; pe->type = GINPUT_MOUSE_EVENT_TYPE; - pe->instance = instance; - 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->x = m->t.x; + pe->y = m->t.y; + pe->z = m->t.z; + pe->current_buttons = m->t.buttons; + pe->last_buttons = m->last_buttons; if (pe->current_buttons & ~pe->last_buttons & GINPUT_MOUSE_BTN_LEFT) pe->meta = GMETA_MOUSE_DOWN; else if (~pe->current_buttons & pe->last_buttons & GINPUT_MOUSE_BTN_LEFT) @@ -481,9 +496,10 @@ 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; #else @@ -500,7 +516,7 @@ bool_t ginputCalibrateMouse(uint16_t instance) { {(width - (width / 4)) , (height - (height / 4))}, {(width / 2), (height / 2)}}; /* Check point */ #endif - MousePoint points[GINPUT_MOUSE_CALIBRATION_POINTS]; + MousePoint points[4]; const MousePoint *pc; MousePoint *pt; int32_t px, py; @@ -532,7 +548,7 @@ bool_t ginputCalibrateMouse(uint16_t instance) { gdispGFillStringBox(MouseConfig.display, 0, 5, width, 30, GINPUT_MOUSE_CALIBRATION_TEXT, font1, White, Blue, justifyCenter); for(i = 0, pt = points, pc = cross; i < GINPUT_MOUSE_CALIBRATION_POINTS; i++, pt++, pc++) { - _tsDrawCross(pc); + CalibrationCrossDraw(pc); do { @@ -555,7 +571,7 @@ bool_t ginputCalibrateMouse(uint16_t instance) { pt->x = px / j; pt->y = py / j; - _tsClearCross(pc); + CalibrationCrossClear(pc); if (i >= 1 && pt->x == (pt-1)->x && pt->y == (pt-1)->y) { gdispGFillStringBox(MouseConfig.display, 0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_SAME_TEXT, font2, Red, Yellow, justifyCenter); @@ -566,7 +582,7 @@ bool_t ginputCalibrateMouse(uint16_t instance) { } /* Apply 3 point calibration algorithm */ - _tsDo3PointCalibration(cross, points, MouseConfig.display, &MouseConfig.caldata); + CalibrationCalculate(&MouseConfig, cross, points); /* Verification of correctness of calibration (optional) : * See if the 4th point (Middle of the screen) coincides with the calibrated @@ -577,7 +593,7 @@ bool_t ginputCalibrateMouse(uint16_t instance) { /* Transform the co-ordinates */ MouseConfig.t.x = points[3].x; MouseConfig.t.y = points[3].y; - _tsTransform(&MouseConfig.t, &MouseConfig.caldata); + CalibrationTransform(&MouseConfig.t, &MouseConfig.caldata); _tsOrientClip(&MouseConfig.t, MouseConfig.display, FALSE); /* Calculate the delta */ @@ -601,7 +617,7 @@ bool_t ginputCalibrateMouse(uint16_t instance) { MouseConfig.flags &= ~FLG_IN_CAL; if ((MouseConfig.flags & FLG_INIT_DONE)) gtimerStart(&MouseTimer, MousePoll, 0, TRUE, GINPUT_MOUSE_POLL_PERIOD); - + // Save the calibration data (if possible) if (MouseConfig.fnsavecal) { MouseConfig.fnsavecal(instance, (const uint8_t *)&MouseConfig.caldata, sizeof(MouseConfig.caldata)); @@ -614,7 +630,7 @@ bool_t ginputCalibrateMouse(uint16_t instance) { #else gdispGClear(MouseConfig.display, Black); #endif - + return TRUE; #endif } @@ -666,12 +682,14 @@ bool_t ginputRequireMouseCalibrationStorage(uint16_t instance) { } /* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */ -void ginputMouseWakeup(void) { +void ginputMouseWakeup(GMouse *m) { + m->flags |= GMOUSE_FLG_NEEDREAD; gtimerJab(&MouseTimer); } /* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */ -void ginputMouseWakeupI(void) { +void ginputMouseWakeupI(GMouse *m) { + m->flags |= GMOUSE_FLG_NEEDREAD; gtimerJabI(&MouseTimer); } |