diff options
-rw-r--r-- | demos/modules/ginput_touch_driver_test/main.c | 262 | ||||
-rw-r--r-- | drivers/multiple/Win32/gdisp_lld.c | 231 | ||||
-rw-r--r-- | drivers/multiple/Win32/ginput_lld_toggle_config.h | 51 | ||||
-rw-r--r-- | include/gwin/gwin_button.h | 11 | ||||
-rw-r--r-- | include/lld/ginput/mouse.h | 2 | ||||
-rw-r--r-- | include/lld/ginput/toggle.h | 40 | ||||
-rw-r--r-- | src/ginput/toggle.c | 14 | ||||
-rw-r--r-- | src/gwin/button.c | 39 |
8 files changed, 476 insertions, 174 deletions
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 <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -45,11 +39,41 @@ #include <wingdi.h>
#include <assert.h>
+#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 <joel@unormal.org>
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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
+#ifndef GINPUT_NEED_TOGGLE
+ #define GINPUT_NEED_TOGGLE FALSE
+#endif
-#if GFX_USE_GINPUT || defined(__DOXYGEN__)
+#if (GFX_USE_GINPUT && GINPUT_NEED_TOGGLE) || 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;
-#endif
+// 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 */
/** @} */
|