Add GWIN virtual keyboard widget
parent
b04148ca2b
commit
1ce3f20fa4
|
@ -0,0 +1,3 @@
|
||||||
|
DEMODIR = $(GFXLIB)/demos/modules/gwin/keyboard
|
||||||
|
GFXINC += $(DEMODIR)
|
||||||
|
GFXSRC += $(DEMODIR)/main.c
|
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
* This file has a different license to the rest of the uGFX system.
|
||||||
|
* You can copy, modify and distribute this file as you see fit.
|
||||||
|
* You do not need to publish your source modifications to this file.
|
||||||
|
* The only thing you are not permitted to do is to relicense it
|
||||||
|
* under a different license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy this file into your project directory and rename it as gfxconf.h
|
||||||
|
* Edit your copy to turn on the uGFX features you want to use.
|
||||||
|
* The values below are the defaults. You should delete anything
|
||||||
|
* you are leaving as default.
|
||||||
|
*
|
||||||
|
* Please use spaces instead of tabs in this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GFXCONF_H
|
||||||
|
#define _GFXCONF_H
|
||||||
|
|
||||||
|
/* The operating system to use. One of these must be defined - preferably in your Makefile */
|
||||||
|
//#define GFX_USE_OS_CHIBIOS TRUE
|
||||||
|
//#define GFX_USE_OS_WIN32 TRUE
|
||||||
|
//#define GFX_USE_OS_LINUX TRUE
|
||||||
|
//#define GFX_USE_OS_OSX TRUE
|
||||||
|
|
||||||
|
#define GFX_USE_GDISP TRUE
|
||||||
|
|
||||||
|
#define GDISP_NEED_VALIDATION TRUE
|
||||||
|
#define GDISP_NEED_CLIP TRUE
|
||||||
|
//#define GDISP_NEED_SCROLL TRUE
|
||||||
|
#define GDISP_NEED_TEXT TRUE
|
||||||
|
#define GDISP_INCLUDE_FONT_UI2 TRUE
|
||||||
|
|
||||||
|
//#define GDISP_NEED_CONTROL TRUE
|
||||||
|
//#define GDISP_DEFAULT_ORIENTATION GDISP_ROTATE_LANDSCAPE
|
||||||
|
#define GDISP_NEED_MULTITHREAD TRUE
|
||||||
|
|
||||||
|
#define GFX_USE_GWIN TRUE
|
||||||
|
#define GWIN_NEED_WINDOWMANAGER TRUE
|
||||||
|
#define GWIN_NEED_CONSOLE TRUE
|
||||||
|
#define GWIN_NEED_WIDGET TRUE
|
||||||
|
#define GWIN_NEED_KEYBOARD TRUE
|
||||||
|
|
||||||
|
#define GFX_USE_GEVENT TRUE
|
||||||
|
#define GFX_USE_GTIMER TRUE
|
||||||
|
|
||||||
|
#define GFX_USE_GQUEUE TRUE
|
||||||
|
#define GQUEUE_NEED_ASYNC TRUE
|
||||||
|
|
||||||
|
#define GFX_USE_GINPUT TRUE
|
||||||
|
#define GINPUT_NEED_MOUSE TRUE
|
||||||
|
//#define GINPUT_NEED_KEYBOARD TRUE
|
||||||
|
|
||||||
|
#endif /* _GFXCONF_H */
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
|
||||||
|
* Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <organization> nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include "gfx.h"
|
||||||
|
|
||||||
|
/* The variables we need */
|
||||||
|
static font_t font;
|
||||||
|
static GListener gl;
|
||||||
|
static GHandle ghConsole;
|
||||||
|
static GHandle ghKeyboard;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the widgets.
|
||||||
|
*/
|
||||||
|
static void createWidgets(void) {
|
||||||
|
GWidgetInit wi;
|
||||||
|
|
||||||
|
gwinWidgetClearInit(&wi);
|
||||||
|
|
||||||
|
// Create the console - set colors before making it visible
|
||||||
|
wi.g.show = FALSE;
|
||||||
|
wi.g.x = 0; wi.g.y = 0;
|
||||||
|
wi.g.width = gdispGetWidth(); wi.g.height = gdispGetHeight()/2;
|
||||||
|
ghConsole = gwinConsoleCreate(0, &wi.g);
|
||||||
|
gwinSetColor(ghConsole, Black);
|
||||||
|
gwinSetBgColor(ghConsole, HTML2COLOR(0xF0F0F0));
|
||||||
|
gwinShow(ghConsole);
|
||||||
|
gwinClear(ghConsole);
|
||||||
|
|
||||||
|
// Create the keyboard
|
||||||
|
wi.g.show = TRUE;
|
||||||
|
wi.g.x = 0; wi.g.y = gdispGetHeight()/2;
|
||||||
|
wi.g.width = gdispGetWidth(); wi.g.height = gdispGetHeight()/2;
|
||||||
|
ghKeyboard = gwinKeyboardCreate(0, &wi);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
GEvent * pe;
|
||||||
|
GEventKeyboard * pk;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
// Initialize the display
|
||||||
|
gfxInit();
|
||||||
|
|
||||||
|
// Set the widget defaults
|
||||||
|
font = gdispOpenFont("*"); // Get the first defined font.
|
||||||
|
gwinSetDefaultFont(font);
|
||||||
|
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
|
||||||
|
gdispClear(White);
|
||||||
|
|
||||||
|
// Create the gwin windows/widgets
|
||||||
|
createWidgets();
|
||||||
|
|
||||||
|
// We want to listen for widget events
|
||||||
|
geventListenerInit(&gl);
|
||||||
|
gwinAttachListener(&gl);
|
||||||
|
|
||||||
|
// We also want to listen to keyboard events from the virtual keyboard
|
||||||
|
geventAttachSource(&gl, gwinKeyboardGetEventSource(ghKeyboard), GLISTEN_KEYTRANSITIONS|GLISTEN_KEYUP);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
// Get an Event
|
||||||
|
pe = geventEventWait(&gl, TIME_INFINITE);
|
||||||
|
|
||||||
|
switch(pe->type) {
|
||||||
|
case GEVENT_GWIN_KEYBOARD:
|
||||||
|
// This is a widget event generated on the standard gwin event source
|
||||||
|
gwinPrintf(ghConsole, "Keyboard visibility has changed\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GEVENT_KEYBOARD:
|
||||||
|
// This is a keyboard event from a keyboard source which must be separately listened to.
|
||||||
|
// It is not sent on the gwin event source even though in this case it was generated by a gwin widget.
|
||||||
|
pk = (GEventKeyboard *)pe;
|
||||||
|
|
||||||
|
gwinPrintf(ghConsole, "KEYSTATE: 0x%04X [ %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s]",
|
||||||
|
pk->keystate,
|
||||||
|
(!pk->keystate ? "NONE " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_KEYUP) ? "KEYUP " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_REPEAT) ? "REPEAT " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_SPECIAL) ? "SPECIAL " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_RAW) ? "RAW " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_SHIFT_L) ? "LSHIFT " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_SHIFT_R) ? "RSHIFT " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_CTRL_L) ? "LCTRL " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_CTRL_R) ? "RCTRL " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_ALT_L) ? "LALT " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_ALT_R) ? "RALT " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_FN) ? "FN " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_COMPOSE) ? "COMPOSE " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_WINKEY) ? "WINKEY " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_CAPSLOCK) ? "CAPSLOCK " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_NUMLOCK) ? "NUMLOCK " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_SCROLLLOCK) ? "SCROLLLOCK " : "")
|
||||||
|
);
|
||||||
|
if (pk->bytecount) {
|
||||||
|
gwinPrintf(ghConsole, " Keys:");
|
||||||
|
for (i = 0; i < pk->bytecount; i++)
|
||||||
|
gwinPrintf(ghConsole, " 0x%02X", (uint8_t)pk->c[i]);
|
||||||
|
gwinPrintf(ghConsole, " [");
|
||||||
|
for (i = 0; i < pk->bytecount; i++)
|
||||||
|
gwinPrintf(ghConsole, "%c", pk->c[i] >= ' ' && pk->c[i] <= '~' ? pk->c[i] : ' ');
|
||||||
|
gwinPrintf(ghConsole, "]");
|
||||||
|
}
|
||||||
|
gwinPrintf(ghConsole, "\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
gwinPrintf(ghConsole, "Unknown %d\n", pe->type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
This demo demonstrates the virtual keyboard.
|
|
@ -36,6 +36,7 @@ FEATURE: Added SSD1331 gdisp driver
|
||||||
FEATURE: Added arduino as a GOS supported operating system
|
FEATURE: Added arduino as a GOS supported operating system
|
||||||
FEATURE: Added additional pixel format's
|
FEATURE: Added additional pixel format's
|
||||||
FIX: Color components fixed for some strange compilers
|
FIX: Color components fixed for some strange compilers
|
||||||
|
FEATURE: Add GWIN virtual keyboard widget
|
||||||
|
|
||||||
*** Release 2.2 ***
|
*** Release 2.2 ***
|
||||||
FEATURE: Added nested containers demo
|
FEATURE: Added nested containers demo
|
||||||
|
|
|
@ -180,6 +180,9 @@
|
||||||
// #define GWIN_NEED_LIST_IMAGES FALSE
|
// #define GWIN_NEED_LIST_IMAGES FALSE
|
||||||
// #define GWIN_NEED_PROGRESSBAR FALSE
|
// #define GWIN_NEED_PROGRESSBAR FALSE
|
||||||
// #define GWIN_PROGRESSBAR_AUTO FALSE
|
// #define GWIN_PROGRESSBAR_AUTO FALSE
|
||||||
|
// #define GWIN_NEED_KEYBOARD FALSE
|
||||||
|
// #define GWIN_KEYBOARD_DEFAULT_LAYOUT VirtualKeyboard_English1
|
||||||
|
// #define GWIN_NEED_KEYBOARD_ENGLISH1 TRUE
|
||||||
// #define GWIN_FLAT_STYLING FALSE
|
// #define GWIN_FLAT_STYLING FALSE
|
||||||
// #define GWIN_WIDGET_TAGS FALSE
|
// #define GWIN_WIDGET_TAGS FALSE
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#ifndef _GINPUT_KEYBOARD_H
|
#ifndef _GINPUT_KEYBOARD_H
|
||||||
#define _GINPUT_KEYBOARD_H
|
#define _GINPUT_KEYBOARD_H
|
||||||
|
|
||||||
#if GINPUT_NEED_KEYBOARD || defined(__DOXYGEN__)
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD || defined(__DOXYGEN__)
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Type definitions */
|
/* Type definitions */
|
||||||
|
@ -164,6 +164,10 @@ typedef struct GEventKeyboard_t {
|
||||||
#define GLISTEN_KEYTRANSITIONS 0x0008 // Return transitions to the key state
|
#define GLISTEN_KEYTRANSITIONS 0x0008 // Return transitions to the key state
|
||||||
#define GLISTEN_KEYRAW 0x0010 // Return raw scan-codes. This turns off normal character processing.
|
#define GLISTEN_KEYRAW 0x0010 // Return raw scan-codes. This turns off normal character processing.
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if GINPUT_NEED_KEYBOARD || defined(__DOXYGEN__)
|
||||||
|
|
||||||
// All keyboards
|
// All keyboards
|
||||||
#define GKEYBOARD_ALL_INSTANCES ((unsigned)-1)
|
#define GKEYBOARD_ALL_INSTANCES ((unsigned)-1)
|
||||||
|
|
||||||
|
|
|
@ -15,5 +15,7 @@ GFXSRC += $(GFXLIB)/src/gwin/gwin.c \
|
||||||
$(GFXLIB)/src/gwin/gwin_frame.c \
|
$(GFXLIB)/src/gwin/gwin_frame.c \
|
||||||
$(GFXLIB)/src/gwin/gwin_tabset.c \
|
$(GFXLIB)/src/gwin/gwin_tabset.c \
|
||||||
$(GFXLIB)/src/gwin/gwin_gl3d.c \
|
$(GFXLIB)/src/gwin/gwin_gl3d.c \
|
||||||
|
$(GFXLIB)/src/gwin/gwin_keyboard.c \
|
||||||
|
$(GFXLIB)/src/gwin/gwin_keyboard_layout.c
|
||||||
|
|
||||||
GFXINC += $(GFXLIB)/3rdparty/tinygl-0.4-ugfx/include
|
GFXINC += $(GFXLIB)/3rdparty/tinygl-0.4-ugfx/include
|
||||||
|
|
|
@ -0,0 +1,471 @@
|
||||||
|
/*
|
||||||
|
* This file is subject to the terms of the GFX License. If a copy of
|
||||||
|
* the license was not distributed with this file, you can obtain one at:
|
||||||
|
*
|
||||||
|
* http://ugfx.org/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file src/gwin/gwin_keyboard.c
|
||||||
|
* @brief GWIN sub-system virtual keyboard code
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gfx.h"
|
||||||
|
|
||||||
|
#if GFX_USE_GWIN && GWIN_NEED_KEYBOARD
|
||||||
|
|
||||||
|
#include "gwin_class.h"
|
||||||
|
#include "gwin_keyboard_layout.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define GKEYBOARD_FLG_REVERTSET (GWIN_FIRST_CONTROL_FLAG<<0)
|
||||||
|
#define GKEYBOARD_FLG_QUICKUPDATE (GWIN_FIRST_CONTROL_FLAG<<1)
|
||||||
|
|
||||||
|
#define BAD_ROWCOL 255
|
||||||
|
|
||||||
|
typedef uint8_t utf8;
|
||||||
|
typedef uint16_t utf16;
|
||||||
|
typedef uint32_t utf32;
|
||||||
|
|
||||||
|
// A character code - note this is not UTF-32 but a representation of the UTF-8 code stream for a single character.
|
||||||
|
typedef uint32_t ucode;
|
||||||
|
|
||||||
|
// Get the length of a UTF-8 string
|
||||||
|
static int UTF8StrLen(const utf8 *s) {
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
if (s) {
|
||||||
|
while (*s) {
|
||||||
|
len++;
|
||||||
|
if (!(s[0] & 0x80))
|
||||||
|
s++;
|
||||||
|
else if ((s[0] & 0xE0) == 0xC0 && (s[1] & 0xC0) == 0x80)
|
||||||
|
s+=2;
|
||||||
|
else if ((s[0] & 0xF0) == 0xE0 && (s[1] & 0xC0) == 0x80 && (s[2] & 0xC0) == 0x80)
|
||||||
|
s+=3;
|
||||||
|
else if ((s[0] & 0xF8) == 0xF0 && (s[1] & 0xC0) == 0x80 && (s[2] & 0xC0) == 0x80 && (s[3] & 0xC0) == 0x80)
|
||||||
|
s+=4;
|
||||||
|
else
|
||||||
|
// Invalid UTF-8 sequence - assume a single byte
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the nth character of a UTF8 string
|
||||||
|
static ucode UTF8CharAt(const utf8 *s, int n) {
|
||||||
|
ucode u;
|
||||||
|
|
||||||
|
u = 0;
|
||||||
|
if (!s) return 0;
|
||||||
|
|
||||||
|
while(*s) {
|
||||||
|
if (!(s[0] & 0x80)) {
|
||||||
|
u = s[0];
|
||||||
|
s++;
|
||||||
|
} else if ((s[0] & 0xE0) == 0xC0 && (s[1] & 0xC0) == 0x80) {
|
||||||
|
u = s[1] | ((ucode)s[0] << 8);
|
||||||
|
s+=2;
|
||||||
|
} else if ((s[0] & 0xF0) == 0xE0 && (s[1] & 0xC0) == 0x80 && (s[2] & 0xC0) == 0x80) {
|
||||||
|
u = s[2] | ((ucode)s[1] << 8) | ((ucode)s[0] << 16);
|
||||||
|
s+=3;
|
||||||
|
} else if ((s[0] & 0xF8) == 0xF0 && (s[1] & 0xC0) == 0x80 && (s[2] & 0xC0) == 0x80 && (s[3] & 0xC0) == 0x80) {
|
||||||
|
u = s[3] | ((ucode)s[2] << 8) | ((ucode)s[1] << 16) | ((ucode)s[0] << 24);
|
||||||
|
s+=4;
|
||||||
|
} else {
|
||||||
|
// Invalid UTF-8 sequence - assume a single byte
|
||||||
|
u = s[0];
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
if (--n < 0)
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a ucode to a UTF8 string (with no NULL on the end). Returns the number of bytes.
|
||||||
|
static unsigned UCode2UTF8(utf8 *dst, ucode u) {
|
||||||
|
if (!(u & 0xFFFFFF00)) {
|
||||||
|
dst[0] = u;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!(u & 0xFFFF0000)) {
|
||||||
|
dst[0] = u >> 8;
|
||||||
|
dst[1] = u;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (!(u & 0xFF000000)) {
|
||||||
|
dst[0] = u >> 16;
|
||||||
|
dst[1] = u >> 8;
|
||||||
|
dst[2] = u;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
dst[0] = u >> 24;
|
||||||
|
dst[1] = u >> 16;
|
||||||
|
dst[2] = u >> 8;
|
||||||
|
dst[3] = u;
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int NumKeyRows(const char **keyset) {
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
while(*keyset++)
|
||||||
|
len++;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SendKeyboardEventToListener(GSourceListener *psl, GKeyboardObject *gk) {
|
||||||
|
GEventKeyboard *pe;
|
||||||
|
const GVSpecialKey *skey;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
// If there is no event buffer just mark a missed event
|
||||||
|
if (!(pe = (GEventKeyboard *)geventGetEventBuffer(psl))) {
|
||||||
|
// This listener is missing - save the meta events that have happened
|
||||||
|
psl->srcflags |= GKEYSTATE_MISSED_EVENT;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The virtual keyboard can't generate repeats
|
||||||
|
//if ((psl->listenflags & GLISTEN_KEYREPEATSOFF) && (k->keystate & GKEYSTATE_REPEAT))
|
||||||
|
// return;
|
||||||
|
|
||||||
|
// The virtual keyboard can't generate special keys
|
||||||
|
//if ((psl->listenflags & GLISTEN_KEYNOSPECIALS) && (k->keystate & GKEYSTATE_SPECIAL))
|
||||||
|
// return;
|
||||||
|
|
||||||
|
// The virtual keyboard treats a key release as a keydown
|
||||||
|
//if (!(psl->listenflags & GLISTEN_KEYUP) && (k->keystate & GKEYSTATE_KEYUP))
|
||||||
|
// k->cntc = 0;
|
||||||
|
|
||||||
|
// The virtual keyboard has no transitions
|
||||||
|
//if (!(psl->listenflags & GLISTEN_KEYTRANSITIONS) && !k->cntc)
|
||||||
|
// return;
|
||||||
|
|
||||||
|
pe->type = GEVENT_KEYBOARD;
|
||||||
|
if (gk->key < 0x20) {
|
||||||
|
skey = &gk->keytable->skeys[gk->key-1];
|
||||||
|
for(i=0; skey->sendkey[i]; i++)
|
||||||
|
pe->c[i] = skey->sendkey[i];
|
||||||
|
} else
|
||||||
|
i = UCode2UTF8((utf8 *)pe->c, gk->key);
|
||||||
|
pe->bytecount = i;
|
||||||
|
for(; i < 8; i++)
|
||||||
|
pe->c[i] = 0;
|
||||||
|
pe->keystate = psl->srcflags;
|
||||||
|
psl->srcflags = 0;
|
||||||
|
geventSendEvent(psl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SendKeyboardEvent(GKeyboardObject *gk) {
|
||||||
|
GSourceListener *psl;
|
||||||
|
|
||||||
|
// Send to the keyboard specific source listeners
|
||||||
|
psl = 0;
|
||||||
|
while ((psl = geventGetSourceListener((GSourceHandle)gk, psl)))
|
||||||
|
SendKeyboardEventToListener(psl, gk);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if GINPUT_NEED_MOUSE
|
||||||
|
// Find the key from the keyset and the x, y position
|
||||||
|
static void FindKey(GKeyboardObject *gk, coord_t x, coord_t y) {
|
||||||
|
const utf8 *krow;
|
||||||
|
fixed f;
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
if (x < 0 || y < 0 || x >= gk->w.g.width || y >= gk->w.g.height) {
|
||||||
|
gk->keyrow = gk->keycol = BAD_ROWCOL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the y parameters
|
||||||
|
f = FIXED(gk->w.g.height) / NumKeyRows(gk->keyset);
|
||||||
|
gk->keyrow = FIXED(y) / f;
|
||||||
|
gk->keyy = NONFIXED(f * gk->keyrow + FIXED0_5);
|
||||||
|
gk->keycy = NONFIXED(f * (gk->keyrow+1) + FIXED0_5) - gk->keyy;
|
||||||
|
|
||||||
|
// Get the current row
|
||||||
|
krow = (const utf8 *)gk->keyset[gk->keyrow];
|
||||||
|
|
||||||
|
// Get the x parameters
|
||||||
|
f = FIXED(gk->w.g.width) / UTF8StrLen(krow);
|
||||||
|
gk->keycol = FIXED(x) / f;
|
||||||
|
|
||||||
|
// Get the key
|
||||||
|
gk->key = UTF8CharAt(krow, gk->keycol);
|
||||||
|
|
||||||
|
// Amalgamate identical keys into one big key
|
||||||
|
idx = gk->keycol;
|
||||||
|
while(gk->keycol > 0 && UTF8CharAt(krow, gk->keycol-1) == gk->key)
|
||||||
|
gk->keycol--;
|
||||||
|
while(UTF8CharAt(krow, ++idx) == gk->key);
|
||||||
|
gk->keyx = NONFIXED(f * gk->keycol + FIXED0_5);
|
||||||
|
gk->keycx = NONFIXED(f * idx + FIXED0_5) - gk->keyx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A mouse up has occurred (it may or may not be over the button)
|
||||||
|
static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) {
|
||||||
|
#define gk ((GKeyboardObject *)gw)
|
||||||
|
|
||||||
|
FindKey(gk, x, y);
|
||||||
|
|
||||||
|
// Do we have a valid key?
|
||||||
|
if (gk->keyrow == BAD_ROWCOL) {
|
||||||
|
if (gk->lastkeyrow != BAD_ROWCOL) {
|
||||||
|
gw->g.flags |= GKEYBOARD_FLG_QUICKUPDATE;
|
||||||
|
_gwinUpdate((GHandle)gw);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are turning off the display of the key
|
||||||
|
gk->keyrow = gk->keycol = BAD_ROWCOL;
|
||||||
|
|
||||||
|
// Is this one of the special keys
|
||||||
|
if (gk->key < 0x20) {
|
||||||
|
// This is a special key
|
||||||
|
const GVSpecialKey *skey;
|
||||||
|
|
||||||
|
skey = &gk->keytable->skeys[gk->key - 1];
|
||||||
|
|
||||||
|
if ((skey->flags & GVKEY_SINGLESET)) {
|
||||||
|
// Single character switch to a new layout
|
||||||
|
gk->keyset = gk->keytable->ksets[skey->newset];
|
||||||
|
gk->w.g.flags &= ~(GKEYBOARD_FLG_QUICKUPDATE|GKEYBOARD_FLG_REVERTSET);
|
||||||
|
gk->w.g.flags |= GKEYBOARD_FLG_REVERTSET;
|
||||||
|
|
||||||
|
} else if ((skey->flags & GVKEY_LOCKSET)) {
|
||||||
|
// Locked switch to a new layout
|
||||||
|
gk->keyset = gk->keytable->ksets[skey->newset];
|
||||||
|
gk->w.g.flags &= ~(GKEYBOARD_FLG_QUICKUPDATE|GKEYBOARD_FLG_REVERTSET);
|
||||||
|
|
||||||
|
} else if ((gk->w.g.flags & GKEYBOARD_FLG_REVERTSET)) {
|
||||||
|
// Revert to default layout
|
||||||
|
gk->keyset = gk->keytable->ksets[0];
|
||||||
|
gk->w.g.flags &= ~(GKEYBOARD_FLG_QUICKUPDATE|GKEYBOARD_FLG_REVERTSET);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Just turning off a key
|
||||||
|
gw->g.flags |= GKEYBOARD_FLG_QUICKUPDATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the key if required
|
||||||
|
if (skey->sendkey && skey->sendkey[0])
|
||||||
|
SendKeyboardEvent(gk);
|
||||||
|
|
||||||
|
// Update the display
|
||||||
|
_gwinUpdate((GHandle)gw);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we need to revert to the standard layout?
|
||||||
|
if ((gk->w.g.flags & GKEYBOARD_FLG_REVERTSET)) {
|
||||||
|
gk->keyset = gk->keytable->ksets[0];
|
||||||
|
gk->w.g.flags &= ~(GKEYBOARD_FLG_QUICKUPDATE|GKEYBOARD_FLG_REVERTSET);
|
||||||
|
} else {
|
||||||
|
gw->g.flags |= GKEYBOARD_FLG_QUICKUPDATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the key
|
||||||
|
SendKeyboardEvent(gk);
|
||||||
|
|
||||||
|
// Update the display
|
||||||
|
_gwinUpdate((GHandle)gw);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A mouse move has occurred (it may or may not be over the button)
|
||||||
|
static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y) {
|
||||||
|
#define gk ((GKeyboardObject *)gw)
|
||||||
|
|
||||||
|
FindKey(gk, x, y);
|
||||||
|
|
||||||
|
if (gk->keyrow != gk->lastkeyrow || gk->keycol != gk->lastkeycol) {
|
||||||
|
gk->w.g.flags |= GKEYBOARD_FLG_QUICKUPDATE;
|
||||||
|
_gwinUpdate((GHandle)gw);
|
||||||
|
}
|
||||||
|
#undef gk
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern GVKeyTable GWIN_KEYBOARD_DEFAULT_LAYOUT;
|
||||||
|
void gwinKeyboardDraw_Normal(GWidgetObject *gw, void *param);
|
||||||
|
|
||||||
|
// The button VMT table
|
||||||
|
static const gwidgetVMT keyboardVMT = {
|
||||||
|
{
|
||||||
|
"VKeyboard", // The classname
|
||||||
|
sizeof(GKeyboardObject), // The object size
|
||||||
|
_gwidgetDestroy, // The destroy routine
|
||||||
|
_gwidgetRedraw, // The redraw routine
|
||||||
|
0, // The after-clear routine
|
||||||
|
},
|
||||||
|
gwinKeyboardDraw_Normal, // The default drawing routine
|
||||||
|
#if GINPUT_NEED_MOUSE
|
||||||
|
{
|
||||||
|
MouseMove, // Process mouse down events
|
||||||
|
MouseUp, // Process mouse up events
|
||||||
|
MouseMove, // Process mouse move events
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#if GINPUT_NEED_TOGGLE
|
||||||
|
{
|
||||||
|
0, // No toggle roles
|
||||||
|
0, // Assign Toggles
|
||||||
|
0, // Get Toggles
|
||||||
|
0, // Process toggle off events
|
||||||
|
0, // Process toggle on events
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#if GINPUT_NEED_DIAL
|
||||||
|
{
|
||||||
|
0, // No dial roles
|
||||||
|
0, // Assign Dials (NOT USED)
|
||||||
|
0, // Get Dials (NOT USED)
|
||||||
|
0, // Process dial move events (NOT USED)
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
GHandle gwinGKeyboardCreate(GDisplay *g, GKeyboardObject *gk, const GWidgetInit *pInit) {
|
||||||
|
if (!(gk = (GKeyboardObject *)_gwidgetCreate(g, &gk->w, pInit, &keyboardVMT)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
gk->keytable = &GWIN_KEYBOARD_DEFAULT_LAYOUT;
|
||||||
|
gk->keyset = gk->keytable->ksets[0];
|
||||||
|
gk->lastkeyrow = gk->lastkeycol = gk->keyrow = gk->keycol = BAD_ROWCOL;
|
||||||
|
gwinSetVisible((GHandle)gk, pInit->g.show);
|
||||||
|
return (GHandle)gk;
|
||||||
|
}
|
||||||
|
|
||||||
|
GSourceHandle gwinKeyboardGetEventSource(GHandle gh) {
|
||||||
|
if (gh->vmt != (gwinVMT *)&keyboardVMT)
|
||||||
|
return 0;
|
||||||
|
return (GSourceHandle)gh;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gwinKeyboardSetLayout(GHandle gh, struct GVKeyTable *layout) {
|
||||||
|
#define gk ((GKeyboardObject *)gh)
|
||||||
|
|
||||||
|
if (gh->vmt != (gwinVMT *)&keyboardVMT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!layout)
|
||||||
|
layout = &GWIN_KEYBOARD_DEFAULT_LAYOUT;
|
||||||
|
gk->keytable = layout;
|
||||||
|
gk->keyset = gk->keytable->ksets[0];
|
||||||
|
gk->lastkeyrow = gk->lastkeycol = gk->keyrow = gk->keycol = BAD_ROWCOL;
|
||||||
|
gk->w.g.flags &= ~(GKEYBOARD_FLG_QUICKUPDATE|GKEYBOARD_FLG_REVERTSET);
|
||||||
|
gwinRedraw(gh);
|
||||||
|
#undef gk
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------
|
||||||
|
* Custom Draw Routines
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
static const GColorSet *getDrawColors(GWidgetObject *gw) {
|
||||||
|
if (!(gw->g.flags & GWIN_FLG_SYSENABLED)) return &gw->pstyle->disabled;
|
||||||
|
if ((gw->g.flags & GBUTTON_FLG_PRESSED)) return &gw->pstyle->pressed;
|
||||||
|
return &gw->pstyle->enabled;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void gwinKeyboardDraw_Normal(GWidgetObject *gw, void *param) {
|
||||||
|
#define gk ((GKeyboardObject *)gw)
|
||||||
|
|
||||||
|
char cap[5];
|
||||||
|
const char *pcap;
|
||||||
|
const utf8 *krow;
|
||||||
|
coord_t x, y, cx, cy;
|
||||||
|
uint8_t rows, cols, row, col, kcols;
|
||||||
|
ucode key;
|
||||||
|
fixed fx, fy;
|
||||||
|
const GColorSet *pcol;
|
||||||
|
(void) param;
|
||||||
|
|
||||||
|
if (gw->g.vmt != (gwinVMT *)&keyboardVMT) return;
|
||||||
|
|
||||||
|
// Get the y parameters
|
||||||
|
rows = NumKeyRows(gk->keyset);
|
||||||
|
fy = FIXED(gk->w.g.height) / rows;
|
||||||
|
for(row = 0; row < rows; row++) {
|
||||||
|
y = NONFIXED(fy * row + FIXED0_5);
|
||||||
|
cy = NONFIXED(fy * (row+1) + FIXED0_5) - y;
|
||||||
|
|
||||||
|
// Get the current row
|
||||||
|
krow = (const utf8 *)gk->keyset[row];
|
||||||
|
|
||||||
|
// Get the x parameters
|
||||||
|
cols = UTF8StrLen(krow);
|
||||||
|
fx = FIXED(gk->w.g.width) / cols;
|
||||||
|
for(col = 0; col < cols; col=kcols) {
|
||||||
|
|
||||||
|
// Choose the color
|
||||||
|
if (!(gk->w.g.flags & GWIN_FLG_SYSENABLED))
|
||||||
|
pcol = &gk->w.pstyle->disabled;
|
||||||
|
else if (gk->keyrow == row && gk->keycol == col)
|
||||||
|
pcol = &gk->w.pstyle->pressed;
|
||||||
|
else
|
||||||
|
pcol = &gk->w.pstyle->enabled;
|
||||||
|
|
||||||
|
// Get the key
|
||||||
|
key = UTF8CharAt(krow, col);
|
||||||
|
|
||||||
|
// Amalgamate identical keys into one big key
|
||||||
|
kcols = col+1;
|
||||||
|
while(UTF8CharAt(krow, kcols) == key)
|
||||||
|
kcols++;
|
||||||
|
x = NONFIXED(fx * col + FIXED0_5);
|
||||||
|
cx = NONFIXED(fx * kcols + FIXED0_5) - x;
|
||||||
|
|
||||||
|
if (key < 0x20) {
|
||||||
|
pcap = gk->keytable->skeys[key-1].keycap;
|
||||||
|
} else {
|
||||||
|
cap[UCode2UTF8((utf8 *)cap, key)] = 0;
|
||||||
|
pcap = cap;
|
||||||
|
}
|
||||||
|
switch(*pcap) {
|
||||||
|
case '\001': // Shift (up arrow)
|
||||||
|
gdispGFillArea(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->fill);
|
||||||
|
gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2, gw->g.y+y+1, gw->g.x+x+1, gw->g.y+y+cy-1, pcol->text);
|
||||||
|
gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2, gw->g.y+y+1, gw->g.x+x+cx-1, gw->g.y+y+cy-1, pcol->text);
|
||||||
|
break;
|
||||||
|
case '\002': // Shift locked (up arrow - bold)
|
||||||
|
gdispGFillArea(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->fill);
|
||||||
|
gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2, gw->g.y+y, gw->g.x+x+1, gw->g.y+y+cy-1, pcol->text);
|
||||||
|
gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2, gw->g.y+y, gw->g.x+x+cx-1, gw->g.y+y+cy-1, pcol->text);
|
||||||
|
gdispGDrawBox(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->edge);
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
gdispGFillArea(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->fill);
|
||||||
|
gdispGDrawLine(gw->g.display, gw->g.x+x+1, gw->g.y+y+1, gw->g.x+x+cx-1, gw->g.y+y+cy/2, pcol->text);
|
||||||
|
gdispGDrawLine(gw->g.display, gw->g.x+x+1, gw->g.y+y+cy-1, gw->g.x+x+cx-1, gw->g.y+y+cy/2, pcol->text);
|
||||||
|
gdispGDrawLine(gw->g.display, gw->g.x+x+cx-1, gw->g.y+y+1, gw->g.x+x+cx-1, gw->g.y+y+cy-1, pcol->text);
|
||||||
|
break;
|
||||||
|
case '\b':
|
||||||
|
gdispGFillArea(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->fill);
|
||||||
|
gdispGDrawLine(gw->g.display, gw->g.x+x+1, gw->g.y+y+cy/2, gw->g.x+x+cx-1, gw->g.y+y+1, pcol->text);
|
||||||
|
gdispGDrawLine(gw->g.display, gw->g.x+x+1, gw->g.y+y+cy/2, gw->g.x+x+cx-1, gw->g.y+y+cy-1, pcol->text);
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
gdispGFillArea(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->fill);
|
||||||
|
gdispGDrawLine(gw->g.display, gw->g.x+x+1, gw->g.y+y+cy/2, gw->g.x+x+cx-1, gw->g.y+y+cy/2, pcol->text);
|
||||||
|
gdispGDrawLine(gw->g.display, gw->g.x+x+cx-1, gw->g.y+y+cy/2, gw->g.x+x+cx-1, gw->g.y+y+1, pcol->text);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gdispGFillStringBox(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcap, gw->g.font, pcol->text, pcol->fill, justifyCenter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef gk
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* GFX_USE_GWIN && GWIN_NEED_KEYBOARD */
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* This file is subject to the terms of the GFX License. If a copy of
|
||||||
|
* the license was not distributed with this file, you can obtain one at:
|
||||||
|
*
|
||||||
|
* http://ugfx.org/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file src/gwin/gwin_button.h
|
||||||
|
* @brief GWIN Graphic window subsystem header file.
|
||||||
|
*
|
||||||
|
* @defgroup Button Button
|
||||||
|
* @ingroup Widgets
|
||||||
|
*
|
||||||
|
* @details GWIN allows it to easily create buttons with different styles
|
||||||
|
* and check for different meta states such as: PRESSED, CLICKED,
|
||||||
|
* RELEASED etc.
|
||||||
|
*
|
||||||
|
* @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h
|
||||||
|
* @pre GWIN_NEED_BUTTON must be set to TRUE in your gfxconf.h
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GWIN_KEYBOARD_H
|
||||||
|
#define _GWIN_KEYBOARD_H
|
||||||
|
|
||||||
|
/* This file is included within "src/gwin/gwin_widget.h" */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The Event Type for a Button Event
|
||||||
|
*/
|
||||||
|
#define GEVENT_GWIN_KEYBOARD (GEVENT_GWIN_CTRL_FIRST+6)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A Keyboard Event
|
||||||
|
* @note There are currently no GEventGWinButton listening flags - use 0 as the flags to @p gwinAttachListener()
|
||||||
|
*/
|
||||||
|
typedef GEventGWin GEventGWinKeyboard;
|
||||||
|
|
||||||
|
struct keyinfo {
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The keyboard widget structure
|
||||||
|
* @note Do not use the members directly - treat it as a black-box.
|
||||||
|
*/
|
||||||
|
typedef struct GKeyboardObject {
|
||||||
|
GWidgetObject w;
|
||||||
|
const struct GVKeyTable *keytable;
|
||||||
|
const char **keyset;
|
||||||
|
coord_t keyx, keyy;
|
||||||
|
coord_t keycx, keycy;
|
||||||
|
uint8_t lastkeyrow, lastkeycol;
|
||||||
|
uint8_t keyrow, keycol;
|
||||||
|
uint32_t key;
|
||||||
|
} GKeyboardObject;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a keyboard widget.
|
||||||
|
* @return NULL if there is no resultant drawing area, otherwise a window handle.
|
||||||
|
*
|
||||||
|
* @param[in] g The GDisplay to display this window on
|
||||||
|
* @param[in] gb The GKeyboardObject structure to initialise. If this is NULL the structure is dynamically allocated.
|
||||||
|
* @param[in] pInit The initialisation parameters
|
||||||
|
*
|
||||||
|
* @note The drawing color and the background color get set to the current defaults. If you haven't called
|
||||||
|
* @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
|
||||||
|
* @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
|
||||||
|
* is no default font and text drawing operations will no nothing.
|
||||||
|
* @note A keyboard remembers its normal drawing state. If there is a window manager then it is automatically
|
||||||
|
* redrawn if the window is moved or its visibility state is changed.
|
||||||
|
* @note A keyboard supports mouse input.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
GHandle gwinGKeyboardCreate(GDisplay *g, GKeyboardObject *gb, const GWidgetInit *pInit);
|
||||||
|
#define gwinKeyboardCreate(gb, pInit) gwinGKeyboardCreate(GDISP, gb, pInit)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the keyboard event source for a GWIN virtual keyboard
|
||||||
|
* @return The event source handle or NULL if this is not a virtual keyboard
|
||||||
|
*
|
||||||
|
* @param[in] gh The GWIN virtual keyboard
|
||||||
|
*
|
||||||
|
* @note Normal GINPUT Keyboard events are returned by this event source.
|
||||||
|
*/
|
||||||
|
GSourceHandle gwinKeyboardGetEventSource(GHandle gh);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the layout for the virtual keyboard
|
||||||
|
*
|
||||||
|
* @param[in] gh The GWIN virtual keyboard
|
||||||
|
* @param[in] layout The keyboard layout to use (described by gwin_keyboard_layout.h)
|
||||||
|
*
|
||||||
|
* @note Changing the layout resets the keyboard to key set 0 of the keyboard and cancels any
|
||||||
|
* pending shifts.
|
||||||
|
*/
|
||||||
|
void gwinKeyboardSetLayout(GHandle gh, struct GVKeyTable *layout);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _GWIN_KEYBOARD_H */
|
||||||
|
/** @} */
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* This file is subject to the terms of the GFX License. If a copy of
|
||||||
|
* the license was not distributed with this file, you can obtain one at:
|
||||||
|
*
|
||||||
|
* http://ugfx.org/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gfx.h"
|
||||||
|
|
||||||
|
#if GFX_USE_GWIN && GWIN_NEED_KEYBOARD
|
||||||
|
|
||||||
|
#include "gwin_keyboard_layout.h"
|
||||||
|
|
||||||
|
#if GWIN_NEED_KEYBOARD_ENGLISH1
|
||||||
|
/* For this keyboard mapping we use:
|
||||||
|
* Set 0 = Lowercase letters
|
||||||
|
* Set 1 = Uppercase letters (transient)
|
||||||
|
* Set 2 = Uppercase letters (locked)
|
||||||
|
* Set 3 = Numbers
|
||||||
|
* Set 4 = Symbols
|
||||||
|
*/
|
||||||
|
static const GVSpecialKey Eng1SKeys[] = {
|
||||||
|
{ "\001", 0, GVKEY_SINGLESET, 1 }, // \001 (1) = Shift Lower to Upper
|
||||||
|
{ "\001", 0, GVKEY_INVERT|GVKEY_LOCKSET, 2 }, // \002 (2) = Shift Upper to Upper Lock
|
||||||
|
{ "\002", 0, GVKEY_INVERT|GVKEY_LOCKSET, 0 }, // \003 (3) = Shift Upper Lock to Lower
|
||||||
|
{ "123", 0, GVKEY_LOCKSET, 3 }, // \004 (4) = Change to Numbers
|
||||||
|
{ "\010", "\b", 0, 0 }, // \005 (5) = Backspace
|
||||||
|
{ "\015", "\r", 0, 0 }, // \006 (6) = Enter 1
|
||||||
|
{ "\015", "\r", 0, 0 }, // \007 (7) = Enter 2 (Short keycap)
|
||||||
|
{ "Sym", 0, GVKEY_LOCKSET, 4 }, // \010 (8) = Change to Symbols
|
||||||
|
{ "aA", 0, GVKEY_LOCKSET, 0 }, // \011 (9) = Change to Lower Alpha
|
||||||
|
};
|
||||||
|
static const char Eng1Set0Row3[] = "\004 .\006\006";
|
||||||
|
static const char Eng1Set1Row0[] = "QWERTYUIOP";
|
||||||
|
static const char Eng1Set1Row1[] = "ASDFGHJKL";
|
||||||
|
static const char *Eng1Set0[] = { "qwertyuiop", "asdfghjkl", "\001zxcvbnm\005", Eng1Set0Row3, 0 };
|
||||||
|
static const char *Eng1Set1[] = { Eng1Set1Row0, Eng1Set1Row1, "\002ZXCVBNM\005", Eng1Set0Row3, 0 };
|
||||||
|
static const char *Eng1Set2[] = { Eng1Set1Row0, Eng1Set1Row1, "\003ZXCVBNM\005", Eng1Set0Row3, 0 };
|
||||||
|
static const char *Eng1Set3[] = { "+-*/", "@789", "\007456", "\010123", "\01100.", 0 };
|
||||||
|
static const char *Eng1Set4[] = { "#$%^&*()", "~`:;\"'{}", "<>?/\\|[]", "\011\004,! .@", 0 };
|
||||||
|
static const GVKeySet Eng1Sets[] = { Eng1Set0, Eng1Set1, Eng1Set2, Eng1Set3, Eng1Set4, 0 };
|
||||||
|
const GVKeyTable VirtualKeyboard_English1 = { Eng1SKeys, Eng1Sets };
|
||||||
|
#endif // GWIN_NEED_KEYBOARD_ENGLISH1
|
||||||
|
|
||||||
|
#endif // GFX_USE_GWIN && GWIN_NEED_KEYBOARD
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* This file is subject to the terms of the GFX License. If a copy of
|
||||||
|
* the license was not distributed with this file, you can obtain one at:
|
||||||
|
*
|
||||||
|
* http://ugfx.org/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file src/gwin/gwin_keyboard_layout.h
|
||||||
|
* @brief GWIN Virtual Keyboard Layout structures.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GWIN_KEYBOARD_LAYOUT_H
|
||||||
|
#define _GWIN_KEYBOARD_LAYOUT_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A GVKeyTable is a set of definitions that define how the keyboard lays out
|
||||||
|
* its keys. A GVKeyTable consists of a number of GVKeySets and a special key table.
|
||||||
|
*
|
||||||
|
* A GVKeySet is a set of keys that make up the currently visible keyboard.
|
||||||
|
* Special keys in the GVKeySet can be used to switch between GVKeySets within
|
||||||
|
* the GVKeyTable. An example is a shift key which switches between the GVKeySet of
|
||||||
|
* lower case keys and the GVKeySet of upper case keys. GVKeySet number 0 is special
|
||||||
|
* in that it is the default GVKeySet when the keyboard is first displayed.
|
||||||
|
*
|
||||||
|
* A GVKeySet is made up of GVKeyRow's. Each GVKeyRow describes the keys on one row
|
||||||
|
* of the keyboard.
|
||||||
|
*
|
||||||
|
* Each GVKeyRow covers a number of key columns. Different rows can have different numbers of columns.
|
||||||
|
* eg. 'Q' -> 'P' has 10 keys while 'A' to 'L' has 9. Additionally each key can cover more than one
|
||||||
|
* column position eg a wide space bar.
|
||||||
|
*
|
||||||
|
* Each GVKeyRow is just a string. Each character is the caption for one key. Using the same
|
||||||
|
* character for two or more adjacent keys merges the keys into one big key covering multiple key columns.
|
||||||
|
* Characters \001 to \037 (1 to 31) are special keys. How to handle and draw those is described by the
|
||||||
|
* special key structure array. Special keys do things like changing keysets, returning characters less than 32,
|
||||||
|
* have multiple character keycaps.
|
||||||
|
*
|
||||||
|
* Note: keycaps from the special key table with a single character from 1 to 31 in them may invoke special drawn
|
||||||
|
* symbols eg. character 13 may cause a special symbol to be drawn for the enter key. Other than those characters
|
||||||
|
* which are drawn as symbols by the keyboard draw function, all other characters for keycaps are drawn using the
|
||||||
|
* current widget font.
|
||||||
|
*
|
||||||
|
* Special keycaps handled by the standard draw:
|
||||||
|
* \001 (1) - Shift (up arrow)
|
||||||
|
* \002 (2) - Shift locked (up arrow - bold)
|
||||||
|
* \010 (8) - Tab (right arrow)
|
||||||
|
* \011 (9) - BackSpace (left arrow)
|
||||||
|
* \015 (13) - Carriage Return (hooked left arrow)
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct GVSpecialKey {
|
||||||
|
const char const *keycap; // The caption on the key
|
||||||
|
const char const *sendkey; // The key to send (NULL means none)
|
||||||
|
uint8_t flags; // Flags
|
||||||
|
#define GVKEY_INVERT 0x01 // Invert the color
|
||||||
|
#define GVKEY_SINGLESET 0x02 // Change set when this key is pressed but only for a single keystroke
|
||||||
|
#define GVKEY_LOCKSET 0x04 // Change set when this key is pressed but stay there until the set is changed by the user
|
||||||
|
uint8_t newset; // The new set to change to
|
||||||
|
} GVSpecialKey;
|
||||||
|
|
||||||
|
typedef const char **GVKeySet; // Array of Rows - Null indicates the end
|
||||||
|
typedef struct GVKeyTable {
|
||||||
|
const GVSpecialKey *skeys; // Array of Special Key structures
|
||||||
|
const GVKeySet *ksets; // Array of KeySets - Null indicates the end
|
||||||
|
} GVKeyTable;
|
||||||
|
|
||||||
|
#endif /* _GWIN_KEYBOARD_LAYOUT_H */
|
||||||
|
/** @} */
|
|
@ -135,6 +135,13 @@
|
||||||
#ifndef GWIN_NEED_TABSET
|
#ifndef GWIN_NEED_TABSET
|
||||||
#define GWIN_NEED_TABSET FALSE
|
#define GWIN_NEED_TABSET FALSE
|
||||||
#endif
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief Should the virtual keyboard be included.
|
||||||
|
* @details Defaults to FALSE
|
||||||
|
*/
|
||||||
|
#ifndef GWIN_NEED_KEYBOARD
|
||||||
|
#define GWIN_NEED_KEYBOARD FALSE
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*
|
*
|
||||||
|
@ -343,6 +350,27 @@
|
||||||
#ifndef GWIN_FLASHING_PERIOD
|
#ifndef GWIN_FLASHING_PERIOD
|
||||||
#define GWIN_FLASHING_PERIOD 250
|
#define GWIN_FLASHING_PERIOD 250
|
||||||
#endif
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief The default keyboard layout for the virtual gwin keyboard
|
||||||
|
* @details Defaults to VirtualKeyboardLayout_English1
|
||||||
|
*/
|
||||||
|
#ifndef GWIN_KEYBOARD_DEFAULT_LAYOUT
|
||||||
|
#define GWIN_KEYBOARD_DEFAULT_LAYOUT VirtualKeyboard_English1
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*
|
||||||
|
* @name GWIN Virtual Keyboard Layouts
|
||||||
|
* @brief One or more of these may be defined. They will only be created if GWIN_NEED_KEYBOARD is TRUE.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief The default keyboard layout for the virtual gwin keyboard
|
||||||
|
* @details Defaults to VirtualKeyboardLayout_English1
|
||||||
|
*/
|
||||||
|
#ifndef GWIN_NEED_KEYBOARD_ENGLISH1
|
||||||
|
#define GWIN_NEED_KEYBOARD_ENGLISH1 TRUE
|
||||||
|
#endif
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
#endif /* _GWIN_OPTIONS_H */
|
#endif /* _GWIN_OPTIONS_H */
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if GWIN_NEED_BUTTON || GWIN_NEED_SLIDER || GWIN_NEED_CHECKBOX || GWIN_NEED_LABEL || GWIN_NEED_RADIO || GWIN_NEED_LIST || \
|
#if GWIN_NEED_BUTTON || GWIN_NEED_SLIDER || GWIN_NEED_CHECKBOX || GWIN_NEED_LABEL || GWIN_NEED_RADIO || GWIN_NEED_LIST || \
|
||||||
GWIN_NEED_IMAGE || GWIN_NEED_CHECKBOX || GWIN_NEED_PROGRESSBAR
|
GWIN_NEED_IMAGE || GWIN_NEED_CHECKBOX || GWIN_NEED_PROGRESSBAR || GWIN_NEED_KEYBOARD
|
||||||
#if !GWIN_NEED_WIDGET
|
#if !GWIN_NEED_WIDGET
|
||||||
#if GFX_DISPLAY_RULE_WARNINGS
|
#if GFX_DISPLAY_RULE_WARNINGS
|
||||||
#warning "GWIN: GWIN_NEED_WIDGET is required when a widget is used. It has been turned on for you."
|
#warning "GWIN: GWIN_NEED_WIDGET is required when a widget is used. It has been turned on for you."
|
||||||
|
|
|
@ -377,5 +377,9 @@ bool_t gwinAttachListener(GListener *pl);
|
||||||
#include "gwin_progressbar.h"
|
#include "gwin_progressbar.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if GWIN_NEED_KEYBOARD || defined(__DOXYGEN__)
|
||||||
|
#include "gwin_keyboard.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _GWIDGET_H */
|
#endif /* _GWIDGET_H */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
Loading…
Reference in New Issue