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 = ARCH =
SRCFLAGS = -ggdb -O0 SRCFLAGS = -ggdb -O0
CFLAGS = `sdl2-config --libs --cflags` CFLAGS = $(sdl2-config --cflags)
CXXFLAGS = CXXFLAGS =
ASFLAGS = ASFLAGS =
LDFLAGS = LDFLAGS =
@ -34,7 +34,7 @@ LDFLAGS =
SRC = SRC =
OBJS = OBJS =
DEFS = DEFS =
LIBS = LIBS = $(sdl2-config --libs)
INCPATH = INCPATH =
LIBPATH = 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 FIX: Fixed to ChibiOS realloc on a TextEdit control
FEATURE: Added support for CMSIS V2.0 operating systems (eg RTX5) FEATURE: Added support for CMSIS V2.0 operating systems (eg RTX5)
REMOVED: Removed long deprecated functions gfxSemCounter() and gfxSemCounterI() 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 *** *** 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}; static const GKeyboardVMT * const dclist[] = {GINPUT_KEYBOARD_DRIVER_LIST};
for(i = 0; i < sizeof(dclist)/sizeof(dclist[0]); i++) { 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); gdriverRegister(&dclist[i]->d, 0);
} }
} }
@ -481,8 +481,8 @@ void _gkeyboardInit(void) {
{ {
extern const GKeyboardVMT const GKEYBOARDVMT_OnlyOne[1]; extern const GKeyboardVMT const GKEYBOARDVMT_OnlyOne[1];
if (!(GKEYBOARDVMT_OnlyOne->d.flags & GKEYBOARD_VFLG_DYNAMICONLY)) if (!(GKEYBOARDVMT_OnlyOne->d.flags & GKEYBOARD_VFLG_DYNAMICONLY))
gdriverRegister(&GKEYBOARDVMT_OnlyOne->d, 0); gdriverRegister(&GKEYBOARDVMT_OnlyOne->d, 0);
} }
#endif #endif
@ -493,43 +493,43 @@ void _gkeyboardDeinit(void) {
} }
bool_t _gkeyboardInitDriver(GDriver *g, void *param, unsigned driverinstance, unsigned systeminstance) { bool_t _gkeyboardInitDriver(GDriver *g, void *param, unsigned driverinstance, unsigned systeminstance) {
#define k ((GKeyboard *)g) #define k ((GKeyboard *)g)
(void) param; (void) param;
(void) systeminstance; (void) systeminstance;
// The initial keyboard layout comes from the VMT // The initial keyboard layout comes from the VMT
k->pLayout = gkvmt(k)->defLayout; k->pLayout = gkvmt(k)->defLayout;
// Init the mouse // Init the mouse
if (!gkvmt(k)->init((GKeyboard *)g, driverinstance)) if (!gkvmt(k)->init((GKeyboard *)g, driverinstance))
return FALSE; return FALSE;
// Ensure the Poll timer is started // Ensure the Poll timer is started
if (!gtimerIsActive(&KeyboardTimer)) if (!gtimerIsActive(&KeyboardTimer))
gtimerStart(&KeyboardTimer, KeyboardPoll, 0, TRUE, GINPUT_KEYBOARD_POLL_PERIOD); gtimerStart(&KeyboardTimer, KeyboardPoll, 0, TRUE, GINPUT_KEYBOARD_POLL_PERIOD);
return TRUE; return TRUE;
#undef k #undef k
} }
void _gkeyboardPostInitDriver(GDriver *g) { void _gkeyboardPostInitDriver(GDriver *g) {
#define k ((GKeyboard *)g) #define k ((GKeyboard *)g)
// Run the init sequence from the layout microcode. // Run the init sequence from the layout microcode.
microengine(k, 0, FLAG_INIT); microengine(k, 0, FLAG_INIT);
#undef k #undef k
} }
void _gkeyboardDeInitDriver(GDriver *g) { void _gkeyboardDeInitDriver(GDriver *g) {
(void) g; (void) g;
} }
GSourceHandle ginputGetKeyboard(unsigned instance) { GSourceHandle ginputGetKeyboard(unsigned instance) {
if (instance == GKEYBOARD_ALL_INSTANCES) if (instance == GKEYBOARD_ALL_INSTANCES)
return (GSourceHandle)&KeyboardTimer; return (GSourceHandle)&KeyboardTimer;
return (GSourceHandle)gdriverGetInstance(GDRIVER_TYPE_KEYBOARD, instance); return (GSourceHandle)gdriverGetInstance(GDRIVER_TYPE_KEYBOARD, instance);
} }
bool_t ginputGetKeyboardStatus(unsigned instance, GEventKeyboard *pe) { 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 (CH_KERNEL_MAJOR == 2) || (CH_KERNEL_MAJOR == 3)
if (psem->sem.s_cnt <= 0) if (psem->sem.s_cnt <= 0)
return GFalse; return FALSE;
#elif (CH_KERNEL_MAJOR == 4) #elif (CH_KERNEL_MAJOR == 4)
if (psem->sem.cnt <= 0) if (psem->sem.cnt <= 0)
return GFalse; return FALSE;
#endif #endif
chSemFastWaitI(&psem->sem); chSemFastWaitI(&psem->sem);
return TRUE; return TRUE;

View File

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

View File

@ -26,54 +26,54 @@
#define gh2obj ((GTexteditObject *)gh) #define gh2obj ((GTexteditObject *)gh)
#define gw2obj ((GTexteditObject *)gw) #define gw2obj ((GTexteditObject *)gw)
static void TextEditRemoveChar(GWidgetObject* gw) { static void TextEditRemoveChar(GHandle gh) {
char *p; char *p;
const char *q; const char *q;
unsigned sz; unsigned sz;
unsigned pos; unsigned pos;
sz = strlen(gw->text); sz = strlen(gh2obj->w.text);
pos = gw2obj->cursorPos; pos = gh2obj->cursorPos;
q = gw->text+pos; q = gh2obj->w.text+pos;
if (!(gw->g.flags & GWIN_FLG_ALLOCTXT)) { if (!(gh->flags & GWIN_FLG_ALLOCTXT)) {
// Allocate and then copy // Allocate and then copy
if (!(p = gfxAlloc(sz))) if (!(p = gfxAlloc(sz)))
return; return;
if (pos) if (pos)
memcpy(p, gw->text, pos); memcpy(p, gh2obj->w.text, pos);
memcpy(p+pos, q+1, sz-pos); memcpy(p+pos, q+1, sz-pos);
gw->g.flags |= GWIN_FLG_ALLOCTXT; gh->flags |= GWIN_FLG_ALLOCTXT;
} else { } else {
// Copy and then reallocate // Copy and then reallocate
memcpy((char *)q, q+1, sz-pos); 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; 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; char *p;
const char *q; const char *q;
unsigned sz; unsigned sz;
unsigned pos; unsigned pos;
// Get the size of the text buffer // Get the size of the text buffer
sz = strlen(gw->text)+1; sz = strlen(gh2obj->w.text)+1;
pos = gw2obj->cursorPos; pos = gh2obj->cursorPos;
if (!(gw->g.flags & GWIN_FLG_ALLOCTXT)) { if (!(gh->flags & GWIN_FLG_ALLOCTXT)) {
if (!(p = gfxAlloc(sz+cnt))) if (!(p = gfxAlloc(sz+cnt)))
return FALSE; return FALSE;
memcpy(p, gw->text, pos); memcpy(p, gh2obj->w.text, pos);
memcpy(p+pos+cnt, gw->text+pos, sz-pos); memcpy(p+pos+cnt, gh2obj->w.text+pos, sz-pos);
gw->g.flags |= GWIN_FLG_ALLOCTXT; gh->flags |= GWIN_FLG_ALLOCTXT;
gw->text = p; gh2obj->w.text = p;
} else { } else {
if (!(p = gfxRealloc((char *)gw->text, sz, sz+cnt))) if (!(p = gfxRealloc((char *)gh2obj->w.text, sz, sz+cnt)))
return FALSE; return FALSE;
gw->text = p; gh2obj->w.text = p;
q = p+pos; q = p+pos;
p += sz; p += sz;
while(--p >= q) while(--p >= q)
@ -117,76 +117,13 @@ static void TextEditMouseDown(GWidgetObject* gw, coord_t x, coord_t y) {
// Is it a special key? // Is it a special key?
if (pke->keystate & GKEYSTATE_SPECIAL) { if (pke->keystate & GKEYSTATE_SPECIAL) {
// Arrow keys to move the cursor // Arrow keys to move the cursor
switch ((uint8_t)pke->c[0]) { gwinTextEditSendSpecialKey(&gw->g, (uint8_t)pke->c[0]);
case GKEY_LEFT: return;
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;
}
} 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 #endif
@ -246,6 +183,89 @@ GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* wt, GWidgetInit* pInit
return (GHandle)wt; 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) void gwinTexteditDefaultDraw(GWidgetObject* gw, void* param)
{ {
const char* p; const char* p;

View File

@ -63,6 +63,32 @@ extern "C" {
GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* wt, GWidgetInit* pInit, size_t maxSize); GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* wt, GWidgetInit* pInit, size_t maxSize);
#define gwinTexteditCreate(wt, pInit, maxSize) gwinGTexteditCreate(GDISP, wt, pInit, 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 * @defgroup Renderings_Textedit Renderings
* *

View File

@ -356,6 +356,20 @@ bool_t gwinAttachListener(GListener *pl);
* @api * @api
*/ */
bool_t gwinAttachToggle(GHandle gh, uint16_t role, uint16_t instance); 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 #endif
#if (GFX_USE_GINPUT && GINPUT_NEED_DIAL) || defined(__DOXYGEN__) #if (GFX_USE_GINPUT && GINPUT_NEED_DIAL) || defined(__DOXYGEN__)

View File

@ -9,10 +9,10 @@
# Requirements: # Requirements:
# #
# OSX_SDK The location of the SDK eg. OSX_SDK = /Developer/SDKs/MacOSX10.7.sdk # 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.3 # OSX_ARCH The architecture flags eg. OSX_ARCH = -mmacosx-version-min=10.12
# #
SRCFLAGS += -isysroot $(OSX_SDK) $(OSX_ARCH) SRCFLAGS += -isysroot $(OSX_SDK) $(OSX_ARCH)
LDFLAGS += -pthread -Wl,-syslibroot,$(OSX_SDK) $(OSX_ARCH) LDFLAGS += -pthread -Wl,-syslibroot,$(OSX_SDK) $(OSX_ARCH)
OPT_CPU = x86 OPT_CPU = x64