diff --git a/demos/modules/ginput_touch_driver_test/main.c b/demos/modules/ginput_touch_driver_test/main.c index d93978cf..dc8bb0f9 100644 --- a/demos/modules/ginput_touch_driver_test/main.c +++ b/demos/modules/ginput_touch_driver_test/main.c @@ -26,18 +26,22 @@ #include "gwin.h" static GConsoleObject gc; +static GButtonObject gNext; +static GButtonObject gPrev; static GListener gl; /*------------------------------------------------------------------------* * GINPUT Touch Driver Calibrator. * *------------------------------------------------------------------------*/ int main(void) { - GSourceHandle gs; + GSourceHandle gs, gsNext, gsPrev; + GEvent *pe; GEventMouse *pem; + GEventGWinButton *peb; coord_t swidth, sheight; - GHandle ghc; + GHandle ghc, ghNext, ghPrev; BaseSequentialStream *gp; - unsigned testnum; + GEventType deviceType; halInit(); // Initialise the Hardware chSysInit(); // Initialize the OS @@ -46,7 +50,7 @@ int main(void) { // Get the display dimensions swidth = gdispGetWidth(); sheight = gdispGetHeight(); - testnum = 0; + ghNext = ghPrev = 0; // Create our title gdispFillStringBox(0, 0, swidth, 20, "Touch Calibration", &fontUI2, Red, White, justifyCenter); @@ -65,52 +69,87 @@ int main(void) { * Test: Device Type */ +StepDeviceType: gwinClear(ghc); gwinSetColor(ghc, Yellow); - chprintf(gp, "\n%u. DEVICE TYPE\n\n", ++testnum); + chprintf(gp, "\n1. DEVICE TYPE\n\n"); pem = (GEventMouse *)&gl.event; ginputGetMouseStatus(0, pem); + deviceType = pem->type; gwinSetColor(ghc, White); chprintf(gp, "This is detected as a %s device\n\n", - pem->type == GEVENT_MOUSE ? "MOUSE" : (pem->type == GEVENT_TOUCH ? "TOUCH" : "UNKNOWN")); + deviceType == GEVENT_MOUSE ? "MOUSE" : (pem->type == GEVENT_TOUCH ? "TOUCH" : "UNKNOWN")); - chprintf(gp, "Press and release your finger (or mouse button) to move on to the next test.\n"); + if (ghNext) + chprintf(gp, "Press Next or Back to continue.\n"); + else if (deviceType == GEVENT_MOUSE) + chprintf(gp, "Click the mouse button to move on to the next test.\n"); + else + chprintf(gp, "Press and release your finger to move on to the next test.\n"); - do { - pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE); - if (pem->type != GEVENT_MOUSE && pem->type != GEVENT_TOUCH) // Safety Check - continue; - - } while (!(pem->meta & GMETA_MOUSE_UP)); + while(1) { + pe = geventEventWait(&gl, TIME_INFINITE); + if (pe->type == GEVENT_GWIN_BUTTON) { + peb = (GEventGWinButton *)pe; + if (peb->button == ghPrev) + goto StepClickJitter; + if (peb->button == ghNext) + break; + } + if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) { + pem = (GEventMouse *)pe; + if (!ghNext && (pem->meta & GMETA_MOUSE_UP)) + break; + } + } /* * Test: Mouse raw reading jitter */ +StepRawJitter: gwinClear(ghc); gwinSetColor(ghc, Yellow); - chprintf(gp, "\n%u. GINPUT_MOUSE_READ_CYCLES\n\n", ++testnum); + chprintf(gp, "\n2. GINPUT_MOUSE_READ_CYCLES\n\n"); gwinSetColor(ghc, White); - chprintf(gp, "Press on the surface (or press and hold the mouse button).\n\n"); + if (deviceType == GEVENT_MOUSE) + chprintf(gp, "Press and hold the mouse button.\n\n"); + else + chprintf(gp, "Press and hold on the surface.\n\n"); chprintf(gp, "Numbers will display in this window.\n" "Ensure that values don't jump around very much when your finger is stationary.\n\n" - "Increasing GINPUT_MOUSE_READ_CYCLES helps reduce jitter but increases CPU usage.\n\n" - "Releasing your finger (or mouse button) will move on to the next test.\n\n"); + "Increasing GINPUT_MOUSE_READ_CYCLES helps reduce jitter but increases CPU usage.\n\n"); + + if (ghNext) + chprintf(gp, "Press Next or Back to continue.\n"); + else if (deviceType == GEVENT_MOUSE) + chprintf(gp, "Release the mouse button to move on to the next test.\n"); + else + chprintf(gp, "Release your finger to move on to the next test.\n"); // For this test turn on ALL mouse movement events geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA|GLISTEN_MOUSENOFILTER); - do { - pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE); - if (pem->type != GEVENT_MOUSE && pem->type != GEVENT_TOUCH) // Safety Check - continue; - - if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT)) - chprintf(gp, "%u:%u\n", pem->x, pem->y); - } while (!(pem->meta & GMETA_MOUSE_UP)); + while(1) { + pe = geventEventWait(&gl, TIME_INFINITE); + if (pe->type == GEVENT_GWIN_BUTTON) { + peb = (GEventGWinButton *)pe; + if (peb->button == ghPrev) + goto StepDeviceType; + if (peb->button == ghNext) + break; + } + if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) { + pem = (GEventMouse *)pe; + if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT)) + chprintf(gp, "%u:%u\n", pem->x, pem->y); + if (!ghNext && (pem->meta & GMETA_MOUSE_UP)) + break; + } + } // Reset to just changed movements. geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA); @@ -119,60 +158,124 @@ int main(void) { * Test: Calibration */ +StepCalibrate: gwinClear(ghc); gwinSetColor(ghc, Yellow); - chprintf(gp, "\n%u. GINPUT_MOUSE_CALIBRATION_ERROR\n\n", ++testnum); + chprintf(gp, "\n3. GINPUT_MOUSE_CALIBRATION_ERROR\n\n"); gwinSetColor(ghc, Gray); chprintf(gp, "Ensure GINPUT_MOUSE_NEED_CALIBRATION = TRUE and GINPUT_MOUSE_CALIBRATION_ERROR is >= 0\n\n"); gwinSetColor(ghc, White); - chprintf(gp, "When you press and release the surface, calibration will start.\n"); chprintf(gp, "You will be presented with a number of points to touch.\nPress them in turn.\n\n" - "If the calibration repeatedly fails increase GINPUT_MOUSE_CALIBRATION_ERROR and try again.\n"); + "If the calibration repeatedly fails, increase GINPUT_MOUSE_CALIBRATION_ERROR and try again.\n\n"); - do { - pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE); - if (pem->type != GEVENT_MOUSE && pem->type != GEVENT_TOUCH) // Safety Check - continue; + if (ghNext) + chprintf(gp, "Press Next to start the calibration.\n"); + else if (deviceType == GEVENT_MOUSE) + chprintf(gp, "Click the mouse button to start the calibration.\n"); + else + chprintf(gp, "Press and release your finger to start the calibration.\n"); - } while (!(pem->meta & GMETA_MOUSE_UP)); + while(1) { + pe = geventEventWait(&gl, TIME_INFINITE); + if (pe->type == GEVENT_GWIN_BUTTON) { + peb = (GEventGWinButton *)pe; + if (peb->button == ghPrev) + goto StepRawJitter; + if (peb->button == ghNext) + break; + } + if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) { + pem = (GEventMouse *)pe; + if (!ghNext && (pem->meta & GMETA_MOUSE_UP)) + break; + } + } // Calibrate ginputCalibrateMouse(0); - // Calibration uses the whole screen - re-establish our title + /* From now on we can use Next and Previous Buttons */ + if (!ghNext) { + + ghNext = gwinCreateButton(&gNext, swidth-50, 0, 50, 20, &fontUI2, GBTN_NORMAL); + gwinSetButtonText(ghNext, "Next", FALSE); + gsNext = gwinGetButtonSource(ghNext); + geventAttachSource(&gl, gsNext, 0); + gwinAttachButtonMouseSource(ghNext, gs); + + ghPrev = gwinCreateButton(&gPrev, swidth-100, 0, 50, 20, &fontUI2, GBTN_NORMAL); + gwinSetButtonText(ghPrev, "Back", FALSE); + gsPrev = gwinGetButtonSource(ghPrev); + geventAttachSource(&gl, gsPrev, 0); + gwinAttachButtonMouseSource(ghPrev, gs); + +#if 0 + { + GSourceHandle gsButton1, gsButton2; + + // Attach a couple of hardware toggle buttons to our Next and Back buttons as well. + // We can always use the mouse to trigger the buttons if you don't want to use hardware toggles. + // This code depends on your hardware. Turn it on only if you have + // defined a board definition for your toggle driver. Then change + // the next two lines to be correct for your hardware. The values + // below are correct for the Win32 toggle driver. + gsButton1 = ginputGetToggle(GINPUT_TOGGLE_MOMENTARY1); + gsButton2 = ginputGetToggle(GINPUT_TOGGLE_MOMENTARY2); + gwinAttachButtonToggleSource(ghNext, gsButton2); + gwinAttachButtonToggleSource(ghPrev, gsButton1); + } +#endif + } + + // Calibration used the whole screen - re-establish our title gdispFillStringBox(0, 0, swidth, 20, "Touch Calibration", &fontUI2, Green, White, justifyCenter); + gwinButtonDraw(ghNext); + gwinButtonDraw(ghPrev); /* * Test: Mouse movement jitter */ +StepJitter: gwinClear(ghc); gwinSetColor(ghc, Yellow); - chprintf(gp, "\n%u. GINPUT_MOUSE_MOVE_JITTER\n\n", ++testnum); + chprintf(gp, "\n4. GINPUT_MOUSE_MOVE_JITTER\n\n"); gwinSetColor(ghc, White); - chprintf(gp, "Press firmly on the surface (or press and hold the mouse button) and move around as if to draw.\n\n"); + if (deviceType == GEVENT_MOUSE) + chprintf(gp, "Press and hold the mouse button and move around as if to draw.\n\n"); + else + chprintf(gp, "Press firmly on the surface and move around as if to draw.\n\n"); + chprintf(gp, "Dots will display in this window. Ensure that when you stop moving your finger that " "new dots stop displaying.\nNew dots should only display when your finger is moving.\n\n" - "Adjust GINPUT_MOUSE_MOVE_JITTER to the smallest value that this reliably works for.\n\n" - "Releasing your finger (or mouse button) will move on to the next test.\n\n"); + "Adjust GINPUT_MOUSE_MOVE_JITTER to the smallest value that this reliably works for.\n\n"); + chprintf(gp, "Press Next or Back to continue.\n\n"); - do { - pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE); - if (pem->type != GEVENT_MOUSE && pem->type != GEVENT_TOUCH) // Safety Check - continue; - - if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT)) - chprintf(gp, "."); - } while (!(pem->meta & GMETA_MOUSE_UP)); + while(1) { + pe = geventEventWait(&gl, TIME_INFINITE); + if (pe->type == GEVENT_GWIN_BUTTON) { + peb = (GEventGWinButton *)pe; + if (peb->button == ghPrev) + goto StepCalibrate; + if (peb->button == ghNext) + break; + } + if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) { + pem = (GEventMouse *)pe; + if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT)) + chprintf(gp, "."); + } + } /* * Test: Polling frequency */ +StepPolling: gwinClear(ghc); gwinSetColor(ghc, Yellow); - chprintf(gp, "\n%u. GINPUT_MOUSE_POLL_PERIOD\n\n", ++testnum); + chprintf(gp, "\n5. GINPUT_MOUSE_POLL_PERIOD\n\n"); gwinSetColor(ghc, White); chprintf(gp, "Press firmly on the surface (or press and hold the mouse button) and move around as if to draw.\n\n"); @@ -180,26 +283,33 @@ int main(void) { "Adjust GINPUT_MOUSE_POLL_PERIOD to the highest value that provides a line without " "gaps that are too big.\nDecreasing the value increases CPU usage.\n" "About 25 (millisecs) normally produces good results." - "This test can be ignored for interrupt driven drivers.\n\n" - "Releasing your finger (or mouse button) will move on to the next test.\n"); - - do { - pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE); - if (pem->type != GEVENT_MOUSE && pem->type != GEVENT_TOUCH) // Safety Check - continue; - - if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT)) - gdispDrawPixel(pem->x, pem->y, Green); - } while (!(pem->meta & GMETA_MOUSE_UP)); + "This test can be ignored for interrupt driven drivers.\n\n"); + chprintf(gp, "Press Next or Back to continue.\n\n"); + while(1) { + pe = geventEventWait(&gl, TIME_INFINITE); + if (pe->type == GEVENT_GWIN_BUTTON) { + peb = (GEventGWinButton *)pe; + if (peb->button == ghPrev) + goto StepJitter; + if (peb->button == ghNext) + break; + } + if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) { + pem = (GEventMouse *)pe; + if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT)) + gdispDrawPixel(pem->x, pem->y, Green); + } + } /* * Test: Click Jitter */ +StepClickJitter: gwinClear(ghc); gwinSetColor(ghc, Yellow); - chprintf(gp, "\n%u. GINPUT_MOUSE_MAX_CLICK_JITTER\n\n", ++testnum); + chprintf(gp, "\n6. GINPUT_MOUSE_MAX_CLICK_JITTER\n\n"); gwinSetColor(ghc, White); chprintf(gp, "Press and release the touch surface to \"click\".\nTry both short and long presses.\n"); @@ -209,21 +319,31 @@ int main(void) { "Adjust GINPUT_MOUSE_CLICK_JITTER to the smallest value that this reliably works for.\n" "Adjust GINPUT_MOUSE_CLICK_TIME to adjust distinguishing short vs long presses.\n" "TIME_INFINITE means there are no long presses (although a right mouse button will still work).\n\n" - "Note: moving your finger (mouse) during a click cancels it." - "This test does not end.\n\n"); + "Note: moving your finger (mouse) during a click cancels it.\n\n"); + chprintf(gp, "This is the last test but you can press Next or Back to continue.\n\n"); while(1) { - pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE); - if (pem->type != GEVENT_MOUSE && pem->type != GEVENT_TOUCH) // Safety Check - continue; - - if ((pem->meta & GMETA_MOUSE_CLICK)) { - gwinSetColor(ghc, Yellow); - chprintf(gp, "-"); + pe = geventEventWait(&gl, TIME_INFINITE); + if (pe->type == GEVENT_GWIN_BUTTON) { + peb = (GEventGWinButton *)pe; + if (peb->button == ghPrev) + goto StepPolling; + if (peb->button == ghNext) + break; } - if ((pem->meta & GMETA_MOUSE_CXTCLICK)) { - gwinSetColor(ghc, Red); - chprintf(gp, "x"); + if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) { + pem = (GEventMouse *)pe; + if ((pem->meta & GMETA_MOUSE_CLICK)) { + gwinSetColor(ghc, Yellow); + chprintf(gp, "-"); + } + if ((pem->meta & GMETA_MOUSE_CXTCLICK)) { + gwinSetColor(ghc, Red); + chprintf(gp, "x"); + } } } + + // Can't let this really exit + goto StepDeviceType; } diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c index 30cd3389..5a741038 100644 --- a/drivers/multiple/Win32/gdisp_lld.c +++ b/drivers/multiple/Win32/gdisp_lld.c @@ -32,12 +32,6 @@ #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ -/* Include mouse support code */ -#include "lld/ginput/mouse.h" - -/* Include the emulation code for things we don't support */ -#include "lld/gdisp/emulation.c" - #include #include #include @@ -45,11 +39,41 @@ #include #include +#ifndef GINPUT_NEED_TOGGLE + #define GINPUT_NEED_TOGGLE FALSE +#endif +#ifndef GINPUT_NEED_MOUSE + #define GINPUT_NEED_MOUSE FALSE +#endif + +#if GINPUT_NEED_TOGGLE + /* Include toggle support code */ + #include "lld/ginput/toggle.h" + + const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = { + {0, 0xFF, 0x00, PAL_MODE_INPUT}, + }; +#endif + +#if GINPUT_NEED_MOUSE + /* Include mouse support code */ + #include "ginput.h" + #include "lld/ginput/mouse.h" +#endif + +/* Include the emulation code for things we don't support */ +#include "lld/gdisp/emulation.c" + /*===========================================================================*/ /* Driver local routines . */ /*===========================================================================*/ #define WIN32_USE_MSG_REDRAW FALSE +#if GINPUT_NEED_TOGGLE + #define WIN32_BUTTON_AREA 16 +#else + #define WIN32_BUTTON_AREA 0 +#endif #define APP_NAME "GDISP" @@ -61,37 +85,104 @@ static HDC dcBuffer = NULL; static HBITMAP dcBitmap = NULL; static HBITMAP dcOldBitmap; static volatile bool_t isReady = FALSE; -static coord_t mousex, mousey; -static uint16_t mousebuttons; +static coord_t wWidth, wHeight; + +#if GINPUT_NEED_MOUSE + static coord_t mousex, mousey; + static uint16_t mousebuttons; +#endif +#if GINPUT_NEED_TOGGLE + static uint8_t toggles = 0; +#endif static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { - HDC dc; - PAINTSTRUCT ps; + HDC dc; + PAINTSTRUCT ps; + #if GINPUT_NEED_TOGGLE + HBRUSH hbrOn, hbrOff; + HPEN pen; + RECT rect; + HGDIOBJ old; + POINT p; + coord_t pos; + uint8_t bit; + #endif switch (Msg) { case WM_CREATE: break; -#if GINPUT_NEED_MOUSE case WM_LBUTTONDOWN: - mousebuttons = 0x0001; - goto mousemove; + #if GINPUT_NEED_MOUSE + if ((coord_t)HIWORD(lParam) < wHeight) { + mousebuttons |= GINPUT_MOUSE_BTN_LEFT; + goto mousemove; + } + #endif + #if GINPUT_NEED_TOGGLE + bit = 1 << ((coord_t)LOWORD(lParam)*8/wWidth); + toggles ^= bit; + rect.left = 0; + rect.right = wWidth; + rect.top = wHeight; + rect.bottom = wHeight + WIN32_BUTTON_AREA; + InvalidateRect(hWnd, &rect, FALSE); + UpdateWindow(hWnd); + #if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE + ginputToggleWakeup(); + #endif + #endif + break; case WM_LBUTTONUP: - mousebuttons &= ~0x0001; - goto mousemove; + #if GINPUT_NEED_TOGGLE + if ((toggles & 0xF0)) { + toggles &= 0x0F; + rect.left = 0; + rect.right = wWidth; + rect.top = wHeight; + rect.bottom = wHeight + WIN32_BUTTON_AREA; + InvalidateRect(hWnd, &rect, FALSE); + UpdateWindow(hWnd); + #if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE + ginputToggleWakeup(); + #endif + } + #endif + #if GINPUT_NEED_MOUSE + if ((coord_t)HIWORD(lParam) < wHeight) { + mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT; + goto mousemove; + } + #endif + break; +#if GINPUT_NEED_MOUSE case WM_MBUTTONDOWN: - mousebuttons = 0x0004; - goto mousemove; + if ((coord_t)HIWORD(lParam) < wHeight) { + mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE; + goto mousemove; + } + break; case WM_MBUTTONUP: - mousebuttons &= ~0x0004; - goto mousemove; + if ((coord_t)HIWORD(lParam) < wHeight) { + mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE; + goto mousemove; + } + break; case WM_RBUTTONDOWN: - mousebuttons = 0x0002; - goto mousemove; + if ((coord_t)HIWORD(lParam) < wHeight) { + mousebuttons |= GINPUT_MOUSE_BTN_RIGHT; + goto mousemove; + } + break; case WM_RBUTTONUP: - mousebuttons &= ~0x0002; - goto mousemove; + if ((coord_t)HIWORD(lParam) < wHeight) { + mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT; + goto mousemove; + } + break; case WM_MOUSEMOVE: + if ((coord_t)HIWORD(lParam) >= wHeight) + break; mousemove: mousex = (coord_t)LOWORD(lParam); mousey = (coord_t)HIWORD(lParam); @@ -114,8 +205,32 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) dc = BeginPaint(hWnd, &ps); BitBlt(dc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, - ps.rcPaint.bottom - ps.rcPaint.top, + (ps.rcPaint.bottom > wHeight ? wHeight : ps.rcPaint.bottom) - ps.rcPaint.top, dcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY); + #if GINPUT_NEED_TOGGLE + if (ps.rcPaint.bottom >= wHeight) { + pen = CreatePen(PS_SOLID, 1, COLOR2BGR(Black)); + hbrOn = CreateSolidBrush(COLOR2BGR(Blue)); + hbrOff = CreateSolidBrush(COLOR2BGR(Gray)); + old = SelectObject(dc, pen); + MoveToEx(dc, 0, wHeight, &p); + LineTo(dc, wWidth, wHeight); + for(pos = 0, bit=1; pos < wWidth; pos=rect.right, bit <<= 1) { + rect.left = pos; + rect.right = pos + wWidth/8; + rect.top = wHeight; + rect.bottom = wHeight + WIN32_BUTTON_AREA; + FillRect(dc, &rect, (toggles & bit) ? hbrOn : hbrOff); + if (pos > 0) { + MoveToEx(dc, rect.left, rect.top, &p); + LineTo(dc, rect.left, rect.bottom); + } + } + DeleteObject(hbrOn); + DeleteObject(hbrOff); + SelectObject(dc, old); + } + #endif EndPaint(hWnd, &ps); break; case WM_DESTROY: @@ -154,8 +269,8 @@ static DWORD WINAPI WindowThread(LPVOID lpParameter) { wc.lpszClassName = APP_NAME; RegisterClass(&wc); - rect.top = 0; rect.bottom = GDISP.Height; - rect.left = 0; rect.right = GDISP.Width; + rect.top = 0; rect.bottom = wHeight+WIN32_BUTTON_AREA; + rect.left = 0; rect.right = wWidth; AdjustWindowRect(&rect, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0); winRootWindow = CreateWindow(APP_NAME, "", WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0, 0, rect.right-rect.left, rect.bottom-rect.top, 0, 0, hInstance, NULL); @@ -163,11 +278,11 @@ static DWORD WINAPI WindowThread(LPVOID lpParameter) { GetClientRect(winRootWindow, &rect); - GDISP.Width = rect.right-rect.left; - GDISP.Height = rect.bottom - rect.top; + wWidth = rect.right-rect.left; + wHeight = rect.bottom - rect.top - WIN32_BUTTON_AREA; dc = GetDC(winRootWindow); - dcBitmap = CreateCompatibleBitmap(dc, GDISP.Width, GDISP.Height); + dcBitmap = CreateCompatibleBitmap(dc, wWidth, wHeight); dcBuffer = CreateCompatibleDC(dc); ReleaseDC(winRootWindow, dc); dcOldBitmap = SelectObject(dcBuffer, dcBitmap); @@ -205,12 +320,12 @@ bool_t GDISP_LLD(init)(void) { /* Set the window dimensions */ GetWindowRect(GetDesktopWindow(), &rect); - GDISP.Width = rect.right - rect.left; - GDISP.Height = rect.bottom - rect.top; - if (GDISP.Width > GDISP_SCREEN_WIDTH) - GDISP.Width = GDISP_SCREEN_WIDTH; - if (GDISP.Height > GDISP_SCREEN_HEIGHT) - GDISP.Height = GDISP_SCREEN_HEIGHT; + wWidth = rect.right - rect.left; + wHeight = rect.bottom - rect.top - WIN32_BUTTON_AREA; + if (wWidth > GDISP_SCREEN_WIDTH) + wWidth = GDISP_SCREEN_WIDTH; + if (wHeight > GDISP_SCREEN_HEIGHT) + wHeight = GDISP_SCREEN_HEIGHT; /* Initialise the window */ CreateThread(0, 0, WindowThread, 0, 0, 0); @@ -222,6 +337,8 @@ bool_t GDISP_LLD(init)(void) { GDISP.Powermode = powerOn; GDISP.Backlight = 100; GDISP.Contrast = 50; + GDISP.Width = wWidth; + GDISP.Height = wHeight; #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP GDISP.clipx0 = 0; GDISP.clipy0 = 0; @@ -841,33 +958,26 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * @notapi */ void GDISP_LLD(control)(unsigned what, void *value) { - RECT rect; - switch(what) { case GDISP_CONTROL_ORIENTATION: if (GDISP.Orientation == (gdisp_orientation_t)value) return; - GetClientRect(winRootWindow, &rect); switch((gdisp_orientation_t)value) { case GDISP_ROTATE_0: - /* Code here */ - GDISP.Width = rect.right-rect.left; - GDISP.Height = rect.bottom - rect.top; + GDISP.Width = wWidth; + GDISP.Height = wHeight; break; case GDISP_ROTATE_90: - /* Code here */ - GDISP.Height = rect.right-rect.left; - GDISP.Width = rect.bottom - rect.top; + GDISP.Height = wWidth; + GDISP.Width = wHeight; break; case GDISP_ROTATE_180: - /* Code here */ - GDISP.Width = rect.right-rect.left; - GDISP.Height = rect.bottom - rect.top; + GDISP.Width = wWidth; + GDISP.Height = wHeight; break; case GDISP_ROTATE_270: - /* Code here */ - GDISP.Height = rect.right-rect.left; - GDISP.Width = rect.bottom - rect.top; + GDISP.Height = wWidth; + GDISP.Width = wHeight; break; default: return; @@ -892,16 +1002,21 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { #if GINPUT_NEED_MOUSE -#include "lld/ginput/mouse.h" + void ginput_lld_mouse_init(void) {} -void ginput_lld_mouse_init(void) {} + void ginput_lld_mouse_get_reading(MouseReading *pt) { + pt->x = mousex; + pt->y = mousey > wHeight ? wHeight : mousey; + pt->z = (mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0; + pt->buttons = mousebuttons; + } -void ginput_lld_mouse_get_reading(MouseReading *pt) { - pt->x = mousex; - pt->y = mousey; - pt->z = (mousebuttons & 0x0001) ? 100 : 0; - pt->buttons = mousebuttons; // We auto-magicaly know that the mousebutton bits match the MouseReading bits. -} +#endif /* GINPUT_NEED_MOUSE */ + +#if GINPUT_NEED_TOGGLE + + void ginput_lld_toggle_init(const GToggleConfig *ptc) { (void) ptc; } + unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc) { (void) ptc; return toggles; } #endif /* GINPUT_NEED_MOUSE */ diff --git a/drivers/multiple/Win32/ginput_lld_toggle_config.h b/drivers/multiple/Win32/ginput_lld_toggle_config.h new file mode 100644 index 00000000..58e47260 --- /dev/null +++ b/drivers/multiple/Win32/ginput_lld_toggle_config.h @@ -0,0 +1,51 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file drivers/multiple/Win32/ginput_lld_toggle_config.h + * @brief GINPUT Toggle Driver configuration header. + * + * @addtogroup GINPUT_TOGGLE + * @{ + */ + +#ifndef _GINPUT_LLD_TOGGLE_CONFIG_H +#define _GINPUT_LLD_TOGGLE_CONFIG_H + +#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE + +#define GINPUT_TOGGLE_POLL_PERIOD TIME_INFINITE // We are interrupt driven (or polled - ether works here) +#define GINPUT_TOGGLE_NUM_PORTS 8 // The total number of toggle inputs +#define GINPUT_TOGGLE_CONFIG_ENTRIES 1 // The total number of GToggleConfig entries + +#define GINPUT_TOGGLE_SW1 0 // Switch 1 - Toggle +#define GINPUT_TOGGLE_SW2 1 // Switch 2 - Toggle +#define GINPUT_TOGGLE_SW3 2 // Switch 3 - Toggle +#define GINPUT_TOGGLE_SW4 3 // Switch 4 - Toggle + +#define GINPUT_TOGGLE_MOMENTARY1 4 // Switch 5 - Momentary +#define GINPUT_TOGGLE_MOMENTARY2 5 // Switch 6 - Momentary +#define GINPUT_TOGGLE_MOMENTARY3 6 // Switch 7 - Momentary +#define GINPUT_TOGGLE_MOMENTARY4 7 // Switch 8 - Momentary + +#endif /* GFX_USE_GDISP && GINPUT_NEED_TOGGLE */ + +#endif /* _GINPUT_LLD_TOGGLE_CONFIG_H */ +/** @} */ diff --git a/include/gwin/gwin_button.h b/include/gwin/gwin_button.h index 69a2474c..e95628e4 100644 --- a/include/gwin/gwin_button.h +++ b/include/gwin/gwin_button.h @@ -129,8 +129,15 @@ extern "C" { // Get the source handle so the application can listen for events #define gwinGetButtonSource(gh) ((GSourceHandle)(gh)) - // Attach a source to this button. Sources recognised: Mouse, Touch and Toggle - others are ignored (returns false). - bool_t gwinAttachButtonSource(GHandle gh, GSourceHandle gsh, GEventType type); + #if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE + // Attach a mouse source to this button. + bool_t gwinAttachButtonMouseSource(GHandle gh, GSourceHandle gsh); + #endif + + #if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE + // Attach a toggle source to this button. + bool_t gwinAttachButtonToggleSource(GHandle gh, GSourceHandle gsh); + #endif #ifdef __cplusplus } diff --git a/include/lld/ginput/mouse.h b/include/lld/ginput/mouse.h index 64c7c5ec..423a6c3e 100644 --- a/include/lld/ginput/mouse.h +++ b/include/lld/ginput/mouse.h @@ -65,7 +65,7 @@ // n - Millisecs between poll's #ifndef GINPUT_MOUSE_POLL_PERIOD - #define GINPUT_MOUSE_POLL_PERIOD 100 + #define GINPUT_MOUSE_POLL_PERIOD 25 #endif // n - Movement allowed without discarding the CLICK or CLICKCXT event (+/- pixels) diff --git a/include/lld/ginput/toggle.h b/include/lld/ginput/toggle.h index 826ace83..72b097f0 100644 --- a/include/lld/ginput/toggle.h +++ b/include/lld/ginput/toggle.h @@ -30,22 +30,28 @@ #ifndef GFX_USE_GINPUT #define GFX_USE_GINPUT FALSE #endif - -#if GFX_USE_GINPUT || defined(__DOXYGEN__) - -#if GINPUT_NEED_TOGGLE - // Describes how the toggle bits are obtained - typedef struct GToggleConfig_t { - void *id; - unsigned mask; - unsigned invert; - iomode_t mode; - } GToggleConfig; +#ifndef GINPUT_NEED_TOGGLE + #define GINPUT_NEED_TOGGLE FALSE #endif +#if (GFX_USE_GINPUT && GINPUT_NEED_TOGGLE) || defined(__DOXYGEN__) + +// Describes how the toggle bits are obtained +typedef struct GToggleConfig_t { + void *id; + unsigned mask; + unsigned invert; + iomode_t mode; +} GToggleConfig; + // This must be included after the above type definition #include "ginput.h" +// n - Millisecs between poll's +#ifndef GINPUT_TOGGLE_POLL_PERIOD + #define GINPUT_TOGGLE_POLL_PERIOD 200 +#endif + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ @@ -54,18 +60,26 @@ extern "C" { #endif -#if GINPUT_NEED_TOGGLE extern const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES]; void ginput_lld_toggle_init(const GToggleConfig *ptc); unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc); -#endif + + /* This routine is provided to low level drivers to wakeup a value read from a thread context. + * Particularly useful if GINPUT_TOGGLE_POLL_PERIOD = TIME_INFINITE + */ + void ginputToggleWakeup(void); + + /* This routine is provided to low level drivers to wakeup a value read from an ISR + * Particularly useful if GINPUT_TOGGLE_POLL_PERIOD = TIME_INFINITE + */ + void ginputToggleWakeupI(void); #ifdef __cplusplus } #endif -#endif /* GFX_USE_GINPUT */ +#endif /* GFX_USE_GINPUT && GINPUT_NEED_TOGGLE */ #endif /* _LLD_GINPUT_TOGGLE_H */ /** @} */ diff --git a/src/ginput/toggle.c b/src/ginput/toggle.c index a49ebfd3..890ac1dc 100644 --- a/src/ginput/toggle.c +++ b/src/ginput/toggle.c @@ -34,10 +34,6 @@ #include "lld/ginput/toggle.h" -#ifndef GINPUT_TOGGLE_POLL_PERIOD - #define GINPUT_TOGGLE_POLL_PERIOD 250 -#endif - #define GINPUT_TOGGLE_ISON 0x01 #define GINPUT_TOGGLE_INVERT 0x02 @@ -157,5 +153,15 @@ bool_t ginputGetToggleStatus(uint16_t instance, GEventToggle *ptoggle) { return TRUE; } +/* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */ +void ginputToggleWakeup(void) { + gtimerJab(&ToggleTimer); +} + +/* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */ +void ginputToggleWakeupI(void) { + gtimerJabI(&ToggleTimer); +} + #endif /* GINPUT_NEED_TOGGLE */ /** @} */ diff --git a/src/gwin/button.c b/src/gwin/button.c index fce82a20..4e1e45f5 100644 --- a/src/gwin/button.c +++ b/src/gwin/button.c @@ -297,34 +297,23 @@ void gwinButtonDraw(GHandle gh) { #undef gbw } -// Attach a source to this button. Sources recognised: Mouse, Touch and Toggle - others are ignored (returns false). -bool_t gwinAttachButtonSource(GHandle gh, GSourceHandle gsh, GEventType type) { - #define gbw ((GButtonObject *)gh) - unsigned flags; +#if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE + bool_t gwinAttachButtonMouseSource(GHandle gh, GSourceHandle gsh) { + if (gh->type != GW_BUTTON) + return FALSE; - switch (type) { - #if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE - case GEVENT_MOUSE: - flags = 0; - break; - #endif - #if defined(GINPUT_NEED_TOUCH) && GINPUT_NEED_TOUCH - case GEVENT_TOUCH: - flags = 0; - break; - #endif - #if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE - case GEVENT_TOGGLE: - flags = GLISTEN_TOGGLE_OFF|GLISTEN_TOGGLE_ON; - break; - #endif - default: - return FALSE; + return geventAttachSource(&((GButtonObject *)gh)->listener, gsh, GLISTEN_MOUSEMETA); } - return geventAttachSource(&gbw->listener, gsh, flags); +#endif - #undef gbw -} +#if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE + bool_t gwinAttachButtonToggleSource(GHandle gh, GSourceHandle gsh) { + if (gh->type != GW_BUTTON) + return FALSE; + + return geventAttachSource(&((GButtonObject *)gh)->listener, gsh, GLISTEN_TOGGLE_OFF|GLISTEN_TOGGLE_ON); + } +#endif #endif /* GFX_USE_GWIN && GWIN_NEED_BUTTON */ /** @} */