bool_t _gwinDrawStart(GHandle gh) { // This test should occur inside the lock. We do this // here as well as an early out (more efficient). if (!(gh->flags & GWIN_FLG_SYSVISIBLE)) return FALSE; // Obtain the drawing lock gfxSemWait(&gwinsem, TIME_INFINITE); // Re-test visibility as we may have waited a while if (!(gh->flags & GWIN_FLG_SYSVISIBLE)) { _gwinDrawEnd(gh); return FALSE; } // OK - we are ready to draw. #if GDISP_NEED_CLIP gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height); #endif return TRUE; }
static uint32_t CalibrateMouse(GMouse *m) { coord_t w, h; point cross[4]; // The locations of the test points on the display point points[4]; // The x, y readings obtained from the mouse for each test point uint32_t err; #if GDISP_NEED_TEXT font_t font1, font2; #endif #if GDISP_NEED_TEXT font1 = gdispOpenFont(CALIBRATION_FONT); if (!font1) font1 = gdispOpenFont("*"); font2 = gdispOpenFont(CALIBRATION_FONT2); if (!font2) font2 = gdispOpenFont("*"); #endif err = 0; w = gdispGGetWidth(m->display); h = gdispGGetHeight(m->display); #if GDISP_NEED_CLIP gdispGSetClip(m->display, 0, 0, w, h); #endif // Ensure we get minimaly processed readings for the calibration m->flags |= GMOUSE_FLG_IN_CAL; // Set up our calibration locations if ((gmvmt(m)->d.flags & GMOUSE_VFLG_CAL_EXTREMES)) { cross[0].x = 0; cross[0].y = 0; cross[1].x = w-1; cross[1].y = 0; cross[2].x = w-1; cross[2].y = h-1; cross[3].x = w/2; cross[3].y = h/2; } else { cross[0].x = w/4; cross[0].y = h/4; cross[1].x = w-w/4; cross[1].y = h/4; cross[2].x = w-w/4; cross[2].y = h-h/4; cross[3].x = w/2; cross[3].y = h/2; } // Set up the calibration display gdispGClear(m->display, Blue); #if GDISP_NEED_TEXT gdispGFillStringBox(m->display, 0, CALIBRATION_TITLE_Y, w, CALIBRATION_TITLE_HEIGHT, CALIBRATION_TITLE, font1, CALIBRATION_TITLE_COLOR, CALIBRATION_TITLE_BACKGROUND, justifyCenter); #endif // Calculate the calibration { unsigned i, maxpoints; maxpoints = (gmvmt(m)->d.flags & GMOUSE_VFLG_CAL_TEST) ? 4 : 3; // Loop through the calibration points for(i = 0; i < maxpoints; i++) { int32_t px, py; unsigned j; // Draw the current calibration point CalibrationCrossDraw(m, &cross[i]); // Get a valid "point pressed" average reading do { // Wait for the mouse to be pressed while(!(m->r.buttons & GINPUT_MOUSE_BTN_LEFT)) gfxSleepMilliseconds(CALIBRATION_POLL_PERIOD); // Sum samples taken every CALIBRATION_POLL_PERIOD milliseconds while the mouse is down px = py = j = 0; while((m->r.buttons & GINPUT_MOUSE_BTN_LEFT)) { // Limit sampling period to prevent overflow if (j < CALIBRATION_MAXPRESS_PERIOD/CALIBRATION_POLL_PERIOD) { px += m->r.x; py += m->r.y; j++; } gfxSleepMilliseconds(CALIBRATION_POLL_PERIOD); } // Ignore presses less than CALIBRATION_MAXPRESS_PERIOD milliseconds } while(j < CALIBRATION_MINPRESS_PERIOD/CALIBRATION_POLL_PERIOD); points[i].x = px / j; points[i].y = py / j; // Clear the current calibration point CalibrationCrossClear(m, &cross[i]); } } // Apply 3 point calibration algorithm CalibrationCalculate(m, cross, points); /* Verification of correctness of calibration (optional) : * See if the 4th point (Middle of the screen) coincides with the calibrated * result. If point is within +/- Squareroot(ERROR) pixel margin, then successful calibration * Else return the error. */ if ((gmvmt(m)->d.flags & GMOUSE_VFLG_CAL_TEST)) { const GMouseJitter *pj; // Are we in pen or finger mode pj = (m->flags & GMOUSE_FLG_FINGERMODE) ? &gmvmt(m)->finger_jitter : &gmvmt(m)->pen_jitter; // Transform the co-ordinates CalibrationTransform((GMouseReading *)&points[3], &m->caldata); // Do we need to rotate the reading to match the display #if GDISP_NEED_CONTROL 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 = points[3].x; points[3].x = w - 1 - points[3].y; points[3].y = t; break; case GDISP_ROTATE_180: points[3].x = w - 1 - points[3].x; points[3].y = h - 1 - points[3].y; break; case GDISP_ROTATE_270: t = points[3].y; points[3].y = h - 1 - points[3].x; points[3].x = t; break; default: break; } } #endif // Is this accurate enough? err = (points[3].x - cross[3].x) * (points[3].x - cross[3].x) + (points[3].y - cross[3].y) * (points[3].y - cross[3].y); if (err > (uint32_t)pj->calibrate * (uint32_t)pj->calibrate) { #if GDISP_NEED_TEXT // No - Display error and return gdispGFillStringBox(m->display, 0, CALIBRATION_ERROR_Y, w, CALIBRATION_ERROR_HEIGHT, CALIBRATION_ERROR_TEXT, font2, CALIBRATION_ERROR_COLOR, CALIBRATION_ERROR_BACKGROUND, justifyCenter); gfxSleepMilliseconds(CALIBRATION_ERROR_DELAY); #endif } else err = 0; } // We are done calibrating #if GDISP_NEED_TEXT gdispCloseFont(font1); gdispCloseFont(font2); #endif m->flags &= ~GMOUSE_FLG_IN_CAL; m->flags |= GMOUSE_FLG_CLIP; // Save the calibration data (if possible) if (!err) { m->flags |= GMOUSE_FLG_CALIBRATE; #if GINPUT_TOUCH_USER_CALIBRATION_SAVE SaveMouseCalibration(gdriverGetDriverInstanceNumber((GDriver *)m), &m->caldata, sizeof(GMouseCalibration)); #endif if (gmvmt(m)->calsave) gmvmt(m)->calsave(m, &m->caldata, sizeof(GMouseCalibration)); } // Force an initial reading m->r.buttons = 0; GetMouseReading(m); // Clear the screen using the GWIN default background color #if GFX_USE_GWIN gdispGClear(m->display, gwinGetDefaultBgColor()); #else gdispGClear(m->display, GDISP_STARTUP_COLOR); #endif return err; }
bool_t ginputCalibrateMouse(uint16_t instance) { #if !GINPUT_MOUSE_NEED_CALIBRATION (void) instance; return FALSE; #else const coord_t height = gdispGGetHeight(MouseConfig.display); const coord_t width = gdispGGetWidth(MouseConfig.display); #if GINPUT_MOUSE_CALIBRATE_EXTREMES const MousePoint cross[] = {{0, 0}, {(width - 1) , 0}, {(width - 1) , (height - 1)}, {(width / 2), (height / 2)}}; /* Check point */ #else const MousePoint cross[] = {{(width / 4), (height / 4)}, {(width - (width / 4)) , (height / 4)}, {(width - (width / 4)) , (height - (height / 4))}, {(width / 2), (height / 2)}}; /* Check point */ #endif MousePoint points[GINPUT_MOUSE_CALIBRATION_POINTS]; const MousePoint *pc; MousePoint *pt; int32_t px, py; unsigned i, j; font_t font1, font2; #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0 unsigned err; #endif if (instance || (MouseConfig.flags & FLG_IN_CAL)) return FALSE; font1 = gdispOpenFont(GINPUT_MOUSE_CALIBRATION_FONT); font2 = gdispOpenFont(GINPUT_MOUSE_CALIBRATION_FONT2); MouseConfig.flags |= FLG_IN_CAL; gtimerStop(&MouseTimer); MouseConfig.flags &= ~(FLG_CAL_OK|FLG_CAL_SAVED|FLG_CAL_RAW); #if GDISP_NEED_CLIP gdispGSetClip(MouseConfig.display, 0, 0, width, height); #endif #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0 while(1) { #endif gdispGClear(MouseConfig.display, Blue); 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); do { /* Wait for the mouse to be pressed */ while(get_raw_reading(&MouseConfig.t), !(MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT)) gfxSleepMilliseconds(20); /* Average all the samples while the mouse is down */ for(px = py = 0, j = 0; gfxSleepMilliseconds(20), /* Settling time between readings */ get_raw_reading(&MouseConfig.t), (MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT); j++) { px += MouseConfig.t.x; py += MouseConfig.t.y; } } while(!j); pt->x = px / j; pt->y = py / j; _tsClearCross(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); gfxSleepMilliseconds(5000); gdispGFillArea(MouseConfig.display, 0, 35, width, 40, Blue); } } /* Apply 3 point calibration algorithm */ _tsDo3PointCalibration(cross, points, MouseConfig.display, &MouseConfig.caldata); /* Verification of correctness of calibration (optional) : * See if the 4th point (Middle of the screen) coincides with the calibrated * result. If point is within +/- Squareroot(ERROR) pixel margin, then successful calibration * Else, start from the beginning. */ #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0 /* Transform the co-ordinates */ MouseConfig.t.x = points[3].x; MouseConfig.t.y = points[3].y; _tsTransform(&MouseConfig.t, &MouseConfig.caldata); _tsOrientClip(&MouseConfig.t, MouseConfig.display, FALSE); /* Calculate the delta */ err = (MouseConfig.t.x - cross[3].x) * (MouseConfig.t.x - cross[3].x) + (MouseConfig.t.y - cross[3].y) * (MouseConfig.t.y - cross[3].y); if (err <= GINPUT_MOUSE_MAX_CALIBRATION_ERROR * GINPUT_MOUSE_MAX_CALIBRATION_ERROR) break; gdispGFillStringBox(MouseConfig.display, 0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_ERROR_TEXT, font2, Red, Yellow, justifyCenter); gfxSleepMilliseconds(5000); } #endif // Restart everything gdispCloseFont(font1); gdispCloseFont(font2); MouseConfig.flags |= FLG_CAL_OK; MouseConfig.last_buttons = 0; get_calibrated_reading(&MouseConfig.t); 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)); MouseConfig.flags |= FLG_CAL_SAVED; } // Clear the screen using the GWIN default background color #if GFX_USE_GWIN gdispGClear(MouseConfig.display, gwinGetDefaultBgColor()); #else gdispGClear(MouseConfig.display, Black); #endif return TRUE; #endif }
static void getLock(GHandle gh) { gfxMutexEnter(&gmutex); gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height); }
void _gwinFlushRedraws(GRedrawMethod how) { GHandle gh; // Do we really need to do anything? if (!RedrawPending) return; // Obtain the drawing lock if (how == REDRAW_WAIT) gfxSemWait(&gwinsem, TIME_INFINITE); else if (how == REDRAW_NOWAIT && !gfxSemWait(&gwinsem, TIME_IMMEDIATE)) // Someone is drawing - They will do the redraw when they are finished return; // Do loss of visibility first while ((RedrawPending & DOREDRAW_INVISIBLES)) { RedrawPending &= ~DOREDRAW_INVISIBLES; // Catch new requests for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) { if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) != GWIN_FLG_NEEDREDRAW) continue; // Do the redraw #if GDISP_NEED_CLIP gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height); _GWINwm->vmt->Redraw(gh); gdispGUnsetClip(gh->display); #else _GWINwm->vmt->Redraw(gh); #endif // Postpone further redraws #if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP if (how == REDRAW_NOWAIT) { RedrawPending |= DOREDRAW_INVISIBLES; TriggerRedraw(); goto releaselock; } #endif } } // Do the visible windows next while ((RedrawPending & DOREDRAW_VISIBLES)) { RedrawPending &= ~DOREDRAW_VISIBLES; // Catch new requests for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) { if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) continue; // Do the redraw #if GDISP_NEED_CLIP gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height); _GWINwm->vmt->Redraw(gh); gdispGUnsetClip(gh->display); #else _GWINwm->vmt->Redraw(gh); #endif // Postpone further redraws (if there are any and the options are set right) #if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP if (how == REDRAW_NOWAIT) { while((gh = gwinGetNextWindow(gh))) { if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) { RedrawPending |= DOREDRAW_VISIBLES; TriggerRedraw(); break; } } goto releaselock; } #endif } } #if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP releaselock: #endif // Release the lock if (how == REDRAW_WAIT || how == REDRAW_NOWAIT) gfxSemSignal(&gwinsem); }
void gwinListDefaultDraw(GWidgetObject* gw, void* param) { const gfxQueueASyncItem* qi; int i; coord_t x, y, iheight, iwidth; color_t fill; const GColorSet * ps; #if GWIN_NEED_LIST_IMAGES coord_t sy; #endif #if GDISP_NEED_CONVEX_POLYGON static const point upArrow[] = { {0, LST_ARROW_SZ}, {LST_ARROW_SZ, LST_ARROW_SZ}, {LST_ARROW_SZ/2, 0} }; static const point downArrow[] = { {0, 0}, {LST_ARROW_SZ, 0}, {LST_ARROW_SZ/2, LST_ARROW_SZ} }; #endif (void)param; // is it a valid handle? if (gw->g.vmt != (gwinVMT *)&listVMT) return; // don't render if render has been disabled if (!(gw->g.flags & GLIST_FLG_ENABLERENDER)) return; ps = (gw->g.flags & GWIN_FLG_SYSENABLED) ? &gw->pstyle->enabled : &gw->pstyle->disabled; iheight = gdispGetFontMetric(gw->g.font, fontHeight) + LST_VERT_PAD; x = 1; // the scroll area if (gw->g.flags & GLIST_FLG_SCROLLSMOOTH) { iwidth = gw->g.width - 2 - 4; if (gw2obj->cnt > 0) { int max_scroll_value = gw2obj->cnt * iheight - gw->g.height-2; if (max_scroll_value > 0) { int bar_height = (gw->g.height-2) * (gw->g.height-2) / (gw2obj->cnt * iheight); gdispGFillArea(gw->g.display, gw->g.x + gw->g.width-4, gw->g.y + 1, 2, gw->g.height-1, gw->pstyle->background); gdispGFillArea(gw->g.display, gw->g.x + gw->g.width-4, gw->g.y + gw2obj->top * ((gw->g.height-2)-bar_height) / max_scroll_value, 2, bar_height, ps->edge); } } } else if ((gw2obj->cnt > (gw->g.height-2) / iheight) || (gw->g.flags & GLIST_FLG_SCROLLALWAYS)) { iwidth = gw->g.width - (LST_SCROLLWIDTH+3); gdispGFillArea(gw->g.display, gw->g.x+iwidth+2, gw->g.y+1, LST_SCROLLWIDTH, gw->g.height-2, gdispBlendColor(ps->fill, gw->pstyle->background, 128)); gdispGDrawLine(gw->g.display, gw->g.x+iwidth+1, gw->g.y+1, gw->g.x+iwidth+1, gw->g.y+gw->g.height-2, ps->edge); #if GDISP_NEED_CONVEX_POLYGON gdispGFillConvexPoly(gw->g.display, gw->g.x+iwidth+((LST_SCROLLWIDTH-LST_ARROW_SZ)/2+2), gw->g.y+(LST_ARROW_SZ/2+1), upArrow, 3, ps->fill); gdispGFillConvexPoly(gw->g.display, gw->g.x+iwidth+((LST_SCROLLWIDTH-LST_ARROW_SZ)/2+2), gw->g.y+gw->g.height-(LST_ARROW_SZ+LST_ARROW_SZ/2+1), downArrow, 3, ps->fill); #else #warning "GWIN: Lists display better when GDISP_NEED_CONVEX_POLYGON is turned on" gdispGFillArea(gw->g.display, gw->g.x+iwidth+((LST_SCROLLWIDTH-LST_ARROW_SZ)/2+2), gw->g.y+(LST_ARROW_SZ/2+1), LST_ARROW_SZ, LST_ARROW_SZ, ps->fill); gdispGFillArea(gw->g.display, gw->g.x+iwidth+((LST_SCROLLWIDTH-LST_ARROW_SZ)/2+2), gw->g.y+gw->g.height-(LST_ARROW_SZ+LST_ARROW_SZ/2+1), LST_ARROW_SZ, LST_ARROW_SZ, ps->fill); #endif } else iwidth = gw->g.width - 2; #if GWIN_NEED_LIST_IMAGES if ((gw->g.flags & GLIST_FLG_HASIMAGES)) { x += iheight; iwidth -= iheight; } #endif // Find the top item for (qi = gfxQueueASyncPeek(&gw2obj->list_head), i = iheight - 1; i < gw2obj->top && qi; qi = gfxQueueASyncNext(qi), i+=iheight); // the list frame gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, ps->edge); // Set the clipping region so we do not override the frame. #if GDISP_NEED_CLIP gdispGSetClip(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2); #endif // Draw until we run out of room or items for (y = 1-(gw2obj->top%iheight); y < gw->g.height-2 && qi; qi = gfxQueueASyncNext(qi), y += iheight) { fill = (qi2li->flags & GLIST_FLG_SELECTED) ? ps->fill : gw->pstyle->background; gdispGFillArea(gw->g.display, gw->g.x+1, gw->g.y+y, iwidth, iheight, fill); #if GWIN_NEED_LIST_IMAGES if ((gw->g.flags & GLIST_FLG_HASIMAGES)) { // Clear the image area if (qi2li->pimg && gdispImageIsOpen(qi2li->pimg)) { // Calculate which image sy = (qi2li->flags & GLIST_FLG_SELECTED) ? 0 : (iheight-LST_VERT_PAD); if (!(gw->g.flags & GWIN_FLG_SYSENABLED)) sy += 2*(iheight-LST_VERT_PAD); while (sy > qi2li->pimg->height) sy -= iheight-LST_VERT_PAD; // Draw the image gdispImageSetBgColor(qi2li->pimg, fill); gdispGImageDraw(gw->g.display, qi2li->pimg, gw->g.x+1, gw->g.y+y, iheight-LST_VERT_PAD, iheight-LST_VERT_PAD, 0, sy); } } #endif gdispGFillStringBox(gw->g.display, gw->g.x+x+LST_HORIZ_PAD, gw->g.y+y, iwidth-LST_HORIZ_PAD, iheight, qi2li->text, gw->g.font, ps->text, fill, justifyLeft); } // Fill any remaining item space if (y < gw->g.height-1) gdispGFillArea(gw->g.display, gw->g.x+1, gw->g.y+y, iwidth, gw->g.height-1-y, gw->pstyle->background); }