Beispiel #1
0
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;
	}
Beispiel #3
0
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
}
Beispiel #4
0
		static void getLock(GHandle gh) {
			gfxMutexEnter(&gmutex);
			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
		}
Beispiel #5
0
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);
}