Merge branch 'master' of git.ugfx.io:uGFX/uGFX

release/v2.9
Joel Bodenmann 2017-08-27 13:43:53 +02:00
commit 285c6528e6
10 changed files with 1322 additions and 107 deletions

View File

@ -26,7 +26,7 @@
ARCH =
SRCFLAGS = -ggdb -O0
CFLAGS = `sdl2-config --libs --cflags`
CFLAGS = $(sdl2-config --cflags)
CXXFLAGS =
ASFLAGS =
LDFLAGS =
@ -34,7 +34,7 @@ LDFLAGS =
SRC =
OBJS =
DEFS =
LIBS =
LIBS = $(sdl2-config --libs)
INCPATH =
LIBPATH =

View File

@ -44,6 +44,11 @@ FIX: Fixed to allow gwinSetText with static text on a TextEdit control
FIX: Fixed to ChibiOS realloc on a TextEdit control
FEATURE: Added support for CMSIS V2.0 operating systems (eg RTX5)
REMOVED: Removed long deprecated functions gfxSemCounter() and gfxSemCounterI()
FIX: gwinDetachToggle() is now a visible part of the API
CHANGE: Update OSX makefiles (allows for 64bit building)
FIX: Fixed resetting a timer on gwinImage objects when using animated GIFs
FEATURE: Added gwinTextEditSendKey() and gwinTextEditSendSpecialKey()
FEATURE: Implemented the JPG image decoder
*** Release 2.7 ***

File diff suppressed because it is too large Load Diff

View File

@ -471,7 +471,7 @@ void _gkeyboardInit(void) {
static const GKeyboardVMT * const dclist[] = {GINPUT_KEYBOARD_DRIVER_LIST};
for(i = 0; i < sizeof(dclist)/sizeof(dclist[0]); i++) {
if (!(dclist[i]->d.flags & GKEYBOARD_VFLG_DYNAMICONLY))
if (!(dclist[i]->d.flags & GKEYBOARD_VFLG_DYNAMICONLY))
gdriverRegister(&dclist[i]->d, 0);
}
}
@ -481,8 +481,8 @@ void _gkeyboardInit(void) {
{
extern const GKeyboardVMT const GKEYBOARDVMT_OnlyOne[1];
if (!(GKEYBOARDVMT_OnlyOne->d.flags & GKEYBOARD_VFLG_DYNAMICONLY))
gdriverRegister(&GKEYBOARDVMT_OnlyOne->d, 0);
if (!(GKEYBOARDVMT_OnlyOne->d.flags & GKEYBOARD_VFLG_DYNAMICONLY))
gdriverRegister(&GKEYBOARDVMT_OnlyOne->d, 0);
}
#endif
@ -493,43 +493,43 @@ void _gkeyboardDeinit(void) {
}
bool_t _gkeyboardInitDriver(GDriver *g, void *param, unsigned driverinstance, unsigned systeminstance) {
#define k ((GKeyboard *)g)
#define k ((GKeyboard *)g)
(void) param;
(void) systeminstance;
(void) systeminstance;
// The initial keyboard layout comes from the VMT
k->pLayout = gkvmt(k)->defLayout;
// Init the mouse
if (!gkvmt(k)->init((GKeyboard *)g, driverinstance))
return FALSE;
if (!gkvmt(k)->init((GKeyboard *)g, driverinstance))
return FALSE;
// Ensure the Poll timer is started
if (!gtimerIsActive(&KeyboardTimer))
gtimerStart(&KeyboardTimer, KeyboardPoll, 0, TRUE, GINPUT_KEYBOARD_POLL_PERIOD);
return TRUE;
return TRUE;
#undef k
#undef k
}
void _gkeyboardPostInitDriver(GDriver *g) {
#define k ((GKeyboard *)g)
#define k ((GKeyboard *)g)
// Run the init sequence from the layout microcode.
microengine(k, 0, FLAG_INIT);
#undef k
#undef k
}
void _gkeyboardDeInitDriver(GDriver *g) {
(void) g;
(void) g;
}
GSourceHandle ginputGetKeyboard(unsigned instance) {
if (instance == GKEYBOARD_ALL_INSTANCES)
return (GSourceHandle)&KeyboardTimer;
return (GSourceHandle)gdriverGetInstance(GDRIVER_TYPE_KEYBOARD, instance);
return (GSourceHandle)gdriverGetInstance(GDRIVER_TYPE_KEYBOARD, instance);
}
bool_t ginputGetKeyboardStatus(unsigned instance, GEventKeyboard *pe) {

View File

@ -141,10 +141,10 @@ bool_t gfxSemWaitI(gfxSem *psem)
{
#if (CH_KERNEL_MAJOR == 2) || (CH_KERNEL_MAJOR == 3)
if (psem->sem.s_cnt <= 0)
return GFalse;
return FALSE;
#elif (CH_KERNEL_MAJOR == 4)
if (psem->sem.cnt <= 0)
return GFalse;
return FALSE;
#endif
chSemFastWaitI(&psem->sem);
return TRUE;

View File

@ -19,6 +19,10 @@
#define gw ((GImageObject *)gh)
static void ImageDestroy(GWindowObject *gh) {
// Stop the timer
#if GWIN_NEED_IMAGE_ANIMATION
gtimerStop(&gw->timer);
#endif
if (gdispImageIsOpen(&gw->image))
gdispImageClose(&gw->image);
}
@ -129,7 +133,7 @@ GHandle gwinGImageCreate(GDisplay *g, GImageObject *gobj, GWindowInit *pInit) {
#if GWIN_NEED_IMAGE_ANIMATION
gtimerInit(&gobj->timer);
#endif
gwinSetVisible((GHandle)gobj, pInit->show);
return (GHandle)gobj;

View File

@ -26,54 +26,54 @@
#define gh2obj ((GTexteditObject *)gh)
#define gw2obj ((GTexteditObject *)gw)
static void TextEditRemoveChar(GWidgetObject* gw) {
static void TextEditRemoveChar(GHandle gh) {
char *p;
const char *q;
unsigned sz;
unsigned pos;
sz = strlen(gw->text);
pos = gw2obj->cursorPos;
q = gw->text+pos;
sz = strlen(gh2obj->w.text);
pos = gh2obj->cursorPos;
q = gh2obj->w.text+pos;
if (!(gw->g.flags & GWIN_FLG_ALLOCTXT)) {
if (!(gh->flags & GWIN_FLG_ALLOCTXT)) {
// Allocate and then copy
if (!(p = gfxAlloc(sz)))
return;
if (pos)
memcpy(p, gw->text, pos);
memcpy(p, gh2obj->w.text, pos);
memcpy(p+pos, q+1, sz-pos);
gw->g.flags |= GWIN_FLG_ALLOCTXT;
gh->flags |= GWIN_FLG_ALLOCTXT;
} else {
// Copy and then reallocate
memcpy((char *)q, q+1, sz-pos);
if (!(p = gfxRealloc((char *)gw->text, sz+1, sz))) // This should never fail as we are making it smaller
if (!(p = gfxRealloc((char *)gh2obj->w.text, sz+1, sz))) // This should never fail as we are making it smaller
return;
}
gw->text = p;
gh2obj->w.text = p;
}
static bool_t TextEditAddChars(GWidgetObject* gw, unsigned cnt) {
static bool_t TextEditAddChars(GHandle gh, unsigned cnt) {
char *p;
const char *q;
unsigned sz;
unsigned pos;
// Get the size of the text buffer
sz = strlen(gw->text)+1;
pos = gw2obj->cursorPos;
sz = strlen(gh2obj->w.text)+1;
pos = gh2obj->cursorPos;
if (!(gw->g.flags & GWIN_FLG_ALLOCTXT)) {
if (!(gh->flags & GWIN_FLG_ALLOCTXT)) {
if (!(p = gfxAlloc(sz+cnt)))
return FALSE;
memcpy(p, gw->text, pos);
memcpy(p+pos+cnt, gw->text+pos, sz-pos);
gw->g.flags |= GWIN_FLG_ALLOCTXT;
gw->text = p;
memcpy(p, gh2obj->w.text, pos);
memcpy(p+pos+cnt, gh2obj->w.text+pos, sz-pos);
gh->flags |= GWIN_FLG_ALLOCTXT;
gh2obj->w.text = p;
} else {
if (!(p = gfxRealloc((char *)gw->text, sz, sz+cnt)))
if (!(p = gfxRealloc((char *)gh2obj->w.text, sz, sz+cnt)))
return FALSE;
gw->text = p;
gh2obj->w.text = p;
q = p+pos;
p += sz;
while(--p >= q)
@ -117,76 +117,13 @@ static void TextEditMouseDown(GWidgetObject* gw, coord_t x, coord_t y) {
// Is it a special key?
if (pke->keystate & GKEYSTATE_SPECIAL) {
// Arrow keys to move the cursor
switch ((uint8_t)pke->c[0]) {
case GKEY_LEFT:
if (!gw2obj->cursorPos)
return;
gw2obj->cursorPos--;
break;
case GKEY_RIGHT:
if (!gw->text[gw2obj->cursorPos])
return;
gw2obj->cursorPos++;
break;
case GKEY_HOME:
if (!gw2obj->cursorPos)
return;
gw2obj->cursorPos = 0;
break;
case GKEY_END:
if (!gw->text[gw2obj->cursorPos])
return;
gw2obj->cursorPos = strlen(gw->text);
break;
default:
return;
}
gwinTextEditSendSpecialKey(&gw->g, (uint8_t)pke->c[0]);
return;
} else {
// Normal key press
switch((uint8_t)pke->c[0]) {
case GKEY_BACKSPACE:
// Backspace
if (!gw2obj->cursorPos)
return;
gw2obj->cursorPos--;
TextEditRemoveChar(gw);
break;
case GKEY_TAB:
case GKEY_LF:
case GKEY_CR:
// Move to the next field
_gwinMoveFocus();
return;
case GKEY_DEL:
// Delete
if (!gw->text[gw2obj->cursorPos])
return;
TextEditRemoveChar(gw);
break;
default:
// Ignore any other control characters
if ((uint8_t)pke->c[0] < GKEY_SPACE)
return;
// Keep the edit length to less than the maximum
if (gw2obj->maxSize && strlen(gw->text)+pke->bytecount > gw2obj->maxSize)
return;
// Make space
if (TextEditAddChars(gw, pke->bytecount)) {
// Insert the characters
memcpy((char *)gw->text+gw2obj->cursorPos, pke->c, pke->bytecount);
gw2obj->cursorPos += pke->bytecount;
}
break;
}
}
_gwinUpdate((GHandle)gw);
gwinTextEditSendKey(&gw->g, pke->c, pke->bytecount);
}
#endif
@ -246,6 +183,89 @@ GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* wt, GWidgetInit* pInit
return (GHandle)wt;
}
#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
void gwinTextEditSendSpecialKey(GHandle gh, uint8_t key) {
// Is it a valid handle?
if (gh->vmt != (gwinVMT*)&texteditVMT)
return;
// Arrow keys to move the cursor
switch (key) {
case GKEY_LEFT:
if (!gh2obj->cursorPos)
return;
gh2obj->cursorPos--;
break;
case GKEY_RIGHT:
if (!gh2obj->w.text[gh2obj->cursorPos])
return;
gh2obj->cursorPos++;
break;
case GKEY_HOME:
if (!gh2obj->cursorPos)
return;
gh2obj->cursorPos = 0;
break;
case GKEY_END:
if (!gh2obj->w.text[gh2obj->cursorPos])
return;
gh2obj->cursorPos = strlen(gh2obj->w.text);
break;
default:
return;
}
_gwinUpdate(gh);
}
void gwinTextEditSendKey(GHandle gh, char *key, unsigned len) {
// Is it a valid handle?
if (gh->vmt != (gwinVMT*)&texteditVMT || !key || !len)
return;
// Normal key press
switch((uint8_t)key[0]) {
case GKEY_BACKSPACE:
// Backspace
if (!gh2obj->cursorPos)
return;
gh2obj->cursorPos--;
TextEditRemoveChar(gh);
break;
case GKEY_TAB:
case GKEY_LF:
case GKEY_CR:
// Move to the next field
_gwinMoveFocus();
return;
case GKEY_DEL:
// Delete
if (!gh2obj->w.text[gh2obj->cursorPos])
return;
TextEditRemoveChar(gh);
break;
default:
// Ignore any other control characters
if ((uint8_t)key[0] < GKEY_SPACE)
return;
// Keep the edit length to less than the maximum
if (gh2obj->maxSize && strlen(gh2obj->w.text)+len > gh2obj->maxSize)
return;
// Make space
if (TextEditAddChars(gh, len)) {
// Insert the characters
memcpy((char *)gh2obj->w.text+gh2obj->cursorPos, key, len);
gh2obj->cursorPos += len;
}
break;
}
_gwinUpdate(gh);
}
#endif
void gwinTexteditDefaultDraw(GWidgetObject* gw, void* param)
{
const char* p;

View File

@ -63,6 +63,32 @@ extern "C" {
GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* wt, GWidgetInit* pInit, size_t maxSize);
#define gwinTexteditCreate(wt, pInit, maxSize) gwinGTexteditCreate(GDISP, wt, pInit, maxSize)
/**
* @brief Send a special key to the textedit such as GKEY_LEFT, GKEY_RIGHT, GKEY_HOME, GKEY_END
*
* @param[in] gh The window handle (must be a textedit window)
* @param[in] key The special key to send.
* @pre Requires GINPUT_NEED_KEYBOARD or GWIN_NEED_KEYBOARD to be on
* @api
*/
void gwinTextEditSendSpecialKey(GHandle gh, uint8_t key);
/**
* @brief Send a normal utf8 character to the textedit
*
* @param[in] gh The window handle (must be a textedit window)
* @param[in] pkey The pointer to the utf8 character to send.
* @param[in] len The length of the utf8 character in bytes.
* @note This must ONLY be called with a single utf8 character at a time. Don't attempt to
* send a string of characters in the one call.
* @note Characters are interpreted as if they came directly from a keyboard ie a backspace
* character will perform the backspace operation, a tab will send the focus to the next
* control etc.
* @pre Requires GINPUT_NEED_KEYBOARD or GWIN_NEED_KEYBOARD to be on
* @api
*/
void gwinTextEditSendKey(GHandle gh, char *pkey, unsigned len);
/**
* @defgroup Renderings_Textedit Renderings
*

View File

@ -356,6 +356,20 @@ bool_t gwinAttachListener(GListener *pl);
* @api
*/
bool_t gwinAttachToggle(GHandle gh, uint16_t role, uint16_t instance);
/**
* @brief Detach a toggle from a widget
* @return TRUE on success
*
* @param[in] gh The widget handle
* @param[in] role The function the toggle will perform for the widget
*
* @note See the documentation on the specific widget to see the possible
* values for the role parameter. If it is out of range, this function
* will return FALSE
*
* @api
*/
bool_t gwinDetachToggle(GHandle gh, uint16_t role);
#endif
#if (GFX_USE_GINPUT && GINPUT_NEED_DIAL) || defined(__DOXYGEN__)

View File

@ -9,10 +9,10 @@
# Requirements:
#
# OSX_SDK The location of the SDK eg. OSX_SDK = /Developer/SDKs/MacOSX10.7.sdk
# OSX_ARCH The architecture flags eg. OSX_ARCH = -mmacosx-version-min=10.3
# OSX_SDK The location of the SDK eg. OSX_SDK = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk
# OSX_ARCH The architecture flags eg. OSX_ARCH = -mmacosx-version-min=10.12
#
SRCFLAGS += -isysroot $(OSX_SDK) $(OSX_ARCH)
LDFLAGS += -pthread -Wl,-syslibroot,$(OSX_SDK) $(OSX_ARCH)
OPT_CPU = x86
OPT_CPU = x64