diff options
author | StapleButter <thetotalworm@gmail.com> | 2017-09-09 02:30:51 +0200 |
---|---|---|
committer | StapleButter <thetotalworm@gmail.com> | 2017-09-09 02:30:51 +0200 |
commit | 70e4841d311d68689724768157cc9cbfbde7a9fc (patch) | |
tree | ba9499f77d1258530a7e60aa6e1732c41d98161c /src/libui_sdl/libui/common | |
parent | 81747d6c34eb159481a6ca3f283d065fa3568617 (diff) |
another UI attempt, I guess.
sorry.
Diffstat (limited to 'src/libui_sdl/libui/common')
-rw-r--r-- | src/libui_sdl/libui/common/CMakeLists.txt | 16 | ||||
-rw-r--r-- | src/libui_sdl/libui/common/areaevents.c | 167 | ||||
-rw-r--r-- | src/libui_sdl/libui/common/control.c | 101 | ||||
-rw-r--r-- | src/libui_sdl/libui/common/controlsigs.h | 25 | ||||
-rw-r--r-- | src/libui_sdl/libui/common/debug.c | 21 | ||||
-rw-r--r-- | src/libui_sdl/libui/common/matrix.c | 50 | ||||
-rw-r--r-- | src/libui_sdl/libui/common/shouldquit.c | 22 | ||||
-rw-r--r-- | src/libui_sdl/libui/common/uipriv.h | 58 | ||||
-rw-r--r-- | src/libui_sdl/libui/common/userbugs.c | 8 |
9 files changed, 468 insertions, 0 deletions
diff --git a/src/libui_sdl/libui/common/CMakeLists.txt b/src/libui_sdl/libui/common/CMakeLists.txt new file mode 100644 index 0000000..91d7949 --- /dev/null +++ b/src/libui_sdl/libui/common/CMakeLists.txt @@ -0,0 +1,16 @@ +# 3 june 2016 + +list(APPEND _LIBUI_SOURCES + common/areaevents.c + common/control.c + common/debug.c + common/matrix.c + common/shouldquit.c + common/userbugs.c +) +set(_LIBUI_SOURCES ${_LIBUI_SOURCES} PARENT_SCOPE) + +list(APPEND _LIBUI_INCLUDEDIRS + common +) +set(_LIBUI_INCLUDEDIRS ${_LIBUI_INCLUDEDIRS} PARENT_SCOPE) diff --git a/src/libui_sdl/libui/common/areaevents.c b/src/libui_sdl/libui/common/areaevents.c new file mode 100644 index 0000000..cf3c288 --- /dev/null +++ b/src/libui_sdl/libui/common/areaevents.c @@ -0,0 +1,167 @@ +// 29 march 2014 +#include "../ui.h" +#include "uipriv.h" + +/* +Windows and GTK+ have a limit of 2 and 3 clicks, respectively, natively supported. Fortunately, we can simulate the double/triple-click behavior to build higher-order clicks. We can use the same algorithm Windows uses on both: + http://blogs.msdn.com/b/oldnewthing/archive/2004/10/18/243925.aspx +For GTK+, we pull the double-click time and double-click distance, which work the same as the equivalents on Windows (so the distance is in all directions), from the GtkSettings system. + +On GTK+ this will also allow us to discard the GDK_BUTTON_2PRESS and GDK_BUTTON_3PRESS events, so the button press stream will be just like on other platforms. + +Thanks to mclasen, garnacho_, halfline, and tristan in irc.gimp.net/#gtk+. +*/ + +// x, y, xdist, ydist, and c.rect must have the same units +// so must time, maxTime, and c.prevTime +int clickCounterClick(clickCounter *c, int button, int x, int y, uintptr_t time, uintptr_t maxTime, int32_t xdist, int32_t ydist) +{ + // different button than before? if so, don't count + if (button != c->curButton) + c->count = 0; + + // (x, y) in the allowed region for a double-click? if not, don't count + if (x < c->rectX0) + c->count = 0; + if (y < c->rectY0) + c->count = 0; + if (x >= c->rectX1) + c->count = 0; + if (y >= c->rectY1) + c->count = 0; + + // too slow? if so, don't count + // note the below expression; time > (c.prevTime + maxTime) can overflow! + if ((time - c->prevTime) > maxTime) // too slow; don't count + c->count = 0; + + c->count++; // if either of the above ifs happened, this will make the click count 1; otherwise it will make the click count 2, 3, 4, 5, ... + + // now we need to update the internal structures for the next test + c->curButton = button; + c->prevTime = time; + c->rectX0 = x - xdist; + c->rectY0 = y - ydist; + c->rectX1 = x + xdist; + c->rectY1 = y + ydist; + + return c->count; +} + +void clickCounterReset(clickCounter *c) +{ + c->curButton = 0; + c->rectX0 = 0; + c->rectY0 = 0; + c->rectX1 = 0; + c->rectY1 = 0; + c->prevTime = 0; + c->count = 0; +} + +/* +For position independence across international keyboard layouts, typewriter keys are read using scancodes (which are always set 1). +Windows provides the scancodes directly in the LPARAM. +GTK+ provides the scancodes directly from the underlying window system via GdkEventKey.hardware_keycode. +On X11, this is scancode + 8 (because X11 keyboard codes have a range of [8,255]). +Wayland is guaranteed to give the same result (thanks ebassi in irc.gimp.net/#gtk+). +On Linux, where evdev is used instead of polling scancodes directly from the keyboard, evdev's typewriter section key code constants are the same as scancodes anyway, so the rules above apply. +Typewriter section scancodes are the same across international keyboards with some exceptions that have been accounted for (see KeyEvent's documentation); see http://www.quadibloc.com/comp/scan.htm for details. +Non-typewriter keys can be handled safely using constants provided by the respective backend API. + +Because GTK+ keysyms may or may not obey Num Lock, we also handle the 0-9 and . keys on the numeric keypad with scancodes (they match too). +*/ + +// use uintptr_t to be safe; the size of the scancode/hardware key code field on each platform is different +static const struct { + uintptr_t scancode; + char equiv; +} scancodeKeys[] = { + { 0x02, '1' }, + { 0x03, '2' }, + { 0x04, '3' }, + { 0x05, '4' }, + { 0x06, '5' }, + { 0x07, '6' }, + { 0x08, '7' }, + { 0x09, '8' }, + { 0x0A, '9' }, + { 0x0B, '0' }, + { 0x0C, '-' }, + { 0x0D, '=' }, + { 0x0E, '\b' }, + { 0x0F, '\t' }, + { 0x10, 'q' }, + { 0x11, 'w' }, + { 0x12, 'e' }, + { 0x13, 'r' }, + { 0x14, 't' }, + { 0x15, 'y' }, + { 0x16, 'u' }, + { 0x17, 'i' }, + { 0x18, 'o' }, + { 0x19, 'p' }, + { 0x1A, '[' }, + { 0x1B, ']' }, + { 0x1C, '\n' }, + { 0x1E, 'a' }, + { 0x1F, 's' }, + { 0x20, 'd' }, + { 0x21, 'f' }, + { 0x22, 'g' }, + { 0x23, 'h' }, + { 0x24, 'j' }, + { 0x25, 'k' }, + { 0x26, 'l' }, + { 0x27, ';' }, + { 0x28, '\'' }, + { 0x29, '`' }, + { 0x2B, '\\' }, + { 0x2C, 'z' }, + { 0x2D, 'x' }, + { 0x2E, 'c' }, + { 0x2F, 'v' }, + { 0x30, 'b' }, + { 0x31, 'n' }, + { 0x32, 'm' }, + { 0x33, ',' }, + { 0x34, '.' }, + { 0x35, '/' }, + { 0x39, ' ' }, + { 0xFFFF, 0 }, +}; + +static const struct { + uintptr_t scancode; + uiExtKey equiv; +} scancodeExtKeys[] = { + { 0x47, uiExtKeyN7 }, + { 0x48, uiExtKeyN8 }, + { 0x49, uiExtKeyN9 }, + { 0x4B, uiExtKeyN4 }, + { 0x4C, uiExtKeyN5 }, + { 0x4D, uiExtKeyN6 }, + { 0x4F, uiExtKeyN1 }, + { 0x50, uiExtKeyN2 }, + { 0x51, uiExtKeyN3 }, + { 0x52, uiExtKeyN0 }, + { 0x53, uiExtKeyNDot }, + { 0xFFFF, 0 }, +}; + +int fromScancode(uintptr_t scancode, uiAreaKeyEvent *ke) +{ + int i; + + for (i = 0; scancodeKeys[i].scancode != 0xFFFF; i++) + if (scancodeKeys[i].scancode == scancode) { + ke->Key = scancodeKeys[i].equiv; + return 1; + } + for (i = 0; scancodeExtKeys[i].scancode != 0xFFFF; i++) + if (scancodeExtKeys[i].scancode == scancode) { + ke->ExtKey = scancodeExtKeys[i].equiv; + return 1; + } + return 0; +} diff --git a/src/libui_sdl/libui/common/control.c b/src/libui_sdl/libui/common/control.c new file mode 100644 index 0000000..2806646 --- /dev/null +++ b/src/libui_sdl/libui/common/control.c @@ -0,0 +1,101 @@ +// 26 may 2015 +#include "../ui.h" +#include "uipriv.h" + +void uiControlDestroy(uiControl *c) +{ + (*(c->Destroy))(c); +} + +uintptr_t uiControlHandle(uiControl *c) +{ + return (*(c->Handle))(c); +} + +uiControl *uiControlParent(uiControl *c) +{ + return (*(c->Parent))(c); +} + +void uiControlSetParent(uiControl *c, uiControl *parent) +{ + (*(c->SetParent))(c, parent); +} + +int uiControlToplevel(uiControl *c) +{ + return (*(c->Toplevel))(c); +} + +int uiControlVisible(uiControl *c) +{ + return (*(c->Visible))(c); +} + +void uiControlShow(uiControl *c) +{ + (*(c->Show))(c); +} + +void uiControlHide(uiControl *c) +{ + (*(c->Hide))(c); +} + +int uiControlEnabled(uiControl *c) +{ + return (*(c->Enabled))(c); +} + +void uiControlEnable(uiControl *c) +{ + (*(c->Enable))(c); +} + +void uiControlDisable(uiControl *c) +{ + (*(c->Disable))(c); +} + +#define uiControlSignature 0x7569436F + +uiControl *uiAllocControl(size_t size, uint32_t OSsig, uint32_t typesig, const char *typenamestr) +{ + uiControl *c; + + c = (uiControl *) uiAlloc(size, typenamestr); + c->Signature = uiControlSignature; + c->OSSignature = OSsig; + c->TypeSignature = typesig; + return c; +} + +void uiFreeControl(uiControl *c) +{ + if (uiControlParent(c) != NULL) + userbug("You cannot destroy a uiControl while it still has a parent. (control: %p)", c); + uiFree(c); +} + +void uiControlVerifySetParent(uiControl *c, uiControl *parent) +{ + uiControl *curParent; + + if (uiControlToplevel(c)) + userbug("You cannot give a toplevel uiControl a parent. (control: %p)", c); + curParent = uiControlParent(c); + if (parent != NULL && curParent != NULL) + userbug("You cannot give a uiControl a parent while it already has one. (control: %p; current parent: %p; new parent: %p)", c, curParent, parent); + if (parent == NULL && curParent == NULL) + implbug("attempt to double unparent uiControl %p", c); +} + +int uiControlEnabledToUser(uiControl *c) +{ + while (c != NULL) { + if (!uiControlEnabled(c)) + return 0; + c = uiControlParent(c); + } + return 1; +} diff --git a/src/libui_sdl/libui/common/controlsigs.h b/src/libui_sdl/libui/common/controlsigs.h new file mode 100644 index 0000000..1cbf18d --- /dev/null +++ b/src/libui_sdl/libui/common/controlsigs.h @@ -0,0 +1,25 @@ +// 24 april 2016 + +#define uiAreaSignature 0x41726561 +#define uiBoxSignature 0x426F784C +#define uiButtonSignature 0x42746F6E +#define uiCheckboxSignature 0x43686B62 +#define uiColorButtonSignature 0x436F6C42 +#define uiComboboxSignature 0x436F6D62 +#define uiDateTimePickerSignature 0x44545069 +#define uiEditableComboboxSignature 0x45644362 +#define uiEntrySignature 0x456E7472 +#define uiFontButtonSignature 0x466F6E42 +#define uiFormSignature 0x466F726D +#define uiGridSignature 0x47726964 +#define uiGroupSignature 0x47727062 +#define uiLabelSignature 0x4C61626C +#define uiMultilineEntrySignature 0x4D6C6E45 +#define uiProgressBarSignature 0x50426172 +#define uiRadioButtonsSignature 0x5264696F +#define uiSeparatorSignature 0x53657061 +#define uiSliderSignature 0x536C6964 +#define uiSpinboxSignature 0x5370696E +#define uiTabSignature 0x54616273 +#define uiTableSignature 0x5461626C +#define uiWindowSignature 0x57696E64 diff --git a/src/libui_sdl/libui/common/debug.c b/src/libui_sdl/libui/common/debug.c new file mode 100644 index 0000000..97280b4 --- /dev/null +++ b/src/libui_sdl/libui/common/debug.c @@ -0,0 +1,21 @@ +// 13 may 2016 +#include "../ui.h" +#include "uipriv.h" + +void _implbug(const char *file, const char *line, const char *func, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + realbug(file, line, func, "POSSIBLE IMPLEMENTATION BUG; CONTACT ANDLABS:\n", format, ap); + va_end(ap); +} + +void _userbug(const char *file, const char *line, const char *func, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + realbug(file, line, func, "You have a bug: ", format, ap); + va_end(ap); +} diff --git a/src/libui_sdl/libui/common/matrix.c b/src/libui_sdl/libui/common/matrix.c new file mode 100644 index 0000000..676885d --- /dev/null +++ b/src/libui_sdl/libui/common/matrix.c @@ -0,0 +1,50 @@ +// 11 october 2015 +#include <math.h> +#include "../ui.h" +#include "uipriv.h" + +void uiDrawMatrixSetIdentity(uiDrawMatrix *m) +{ + m->M11 = 1; + m->M12 = 0; + m->M21 = 0; + m->M22 = 1; + m->M31 = 0; + m->M32 = 0; +} + +// The rest of this file provides basic utilities in case the platform doesn't provide any of its own for these tasks. +// Keep these as minimal as possible. They should generally not call other fallbacks. + +// see https://msdn.microsoft.com/en-us/library/windows/desktop/ff684171%28v=vs.85%29.aspx#skew_transform +// TODO see if there's a way we can avoid the multiplication +void fallbackSkew(uiDrawMatrix *m, double x, double y, double xamount, double yamount) +{ + uiDrawMatrix n; + + uiDrawMatrixSetIdentity(&n); + // TODO explain this + n.M12 = tan(yamount); + n.M21 = tan(xamount); + n.M31 = -y * tan(xamount); + n.M32 = -x * tan(yamount); + uiDrawMatrixMultiply(m, &n); +} + +void scaleCenter(double xCenter, double yCenter, double *x, double *y) +{ + *x = xCenter - (*x * xCenter); + *y = yCenter - (*y * yCenter); +} + +// the basic algorithm is from cairo +// but it's the same algorithm as the transform point, just without M31 and M32 taken into account, so let's just do that instead +void fallbackTransformSize(uiDrawMatrix *m, double *x, double *y) +{ + uiDrawMatrix m2; + + m2 = *m; + m2.M31 = 0; + m2.M32 = 0; + uiDrawMatrixTransformPoint(&m2, x, y); +} diff --git a/src/libui_sdl/libui/common/shouldquit.c b/src/libui_sdl/libui/common/shouldquit.c new file mode 100644 index 0000000..4e7aa5c --- /dev/null +++ b/src/libui_sdl/libui/common/shouldquit.c @@ -0,0 +1,22 @@ +// 9 may 2015 +#include "../ui.h" +#include "uipriv.h" + +static int defaultOnShouldQuit(void *data) +{ + return 0; +} + +static int (*onShouldQuit)(void *) = defaultOnShouldQuit; +static void *onShouldQuitData; + +void uiOnShouldQuit(int (*f)(void *), void *data) +{ + onShouldQuit = f; + onShouldQuitData = data; +} + +int shouldQuit(void) +{ + return (*onShouldQuit)(onShouldQuitData); +} diff --git a/src/libui_sdl/libui/common/uipriv.h b/src/libui_sdl/libui/common/uipriv.h new file mode 100644 index 0000000..d6b54e8 --- /dev/null +++ b/src/libui_sdl/libui/common/uipriv.h @@ -0,0 +1,58 @@ +// 6 april 2015 +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdarg.h> +#include "controlsigs.h" + +extern uiInitOptions options; + +extern void *uiAlloc(size_t, const char *); +#define uiNew(T) ((T *) uiAlloc(sizeof (T), #T)) +extern void *uiRealloc(void *, size_t, const char *); +extern void uiFree(void *); + +// ugh, this was only introduced in MSVC 2015... +#ifdef _MSC_VER +#define __func__ __FUNCTION__ +#endif +extern void realbug(const char *file, const char *line, const char *func, const char *prefix, const char *format, va_list ap); +#define _ns2(s) #s +#define _ns(s) _ns2(s) +extern void _implbug(const char *file, const char *line, const char *func, const char *format, ...); +#define implbug(...) _implbug(__FILE__, _ns(__LINE__), __func__, __VA_ARGS__) +extern void _userbug(const char *file, const char *line, const char *func, const char *format, ...); +#define userbug(...) _userbug(__FILE__, _ns(__LINE__), __func__, __VA_ARGS__) + +// control.c +extern uiControl *newControl(size_t size, uint32_t OSsig, uint32_t typesig, const char *typenamestr); + +// shouldquit.c +extern int shouldQuit(void); + +// areaevents.c +typedef struct clickCounter clickCounter; +// you should call Reset() to zero-initialize a new instance +// it doesn't matter that all the non-count fields are zero: the first click will fail the curButton test straightaway, so it'll return 1 and set the rest of the structure accordingly +struct clickCounter { + int curButton; + int rectX0; + int rectY0; + int rectX1; + int rectY1; + uintptr_t prevTime; + int count; +}; +int clickCounterClick(clickCounter *c, int button, int x, int y, uintptr_t time, uintptr_t maxTime, int32_t xdist, int32_t ydist); +extern void clickCounterReset(clickCounter *); +extern int fromScancode(uintptr_t, uiAreaKeyEvent *); + +// matrix.c +extern void fallbackSkew(uiDrawMatrix *, double, double, double, double); +extern void scaleCenter(double, double, double *, double *); +extern void fallbackTransformSize(uiDrawMatrix *, double *, double *); + +#ifdef __cplusplus +} +#endif diff --git a/src/libui_sdl/libui/common/userbugs.c b/src/libui_sdl/libui/common/userbugs.c new file mode 100644 index 0000000..0a85874 --- /dev/null +++ b/src/libui_sdl/libui/common/userbugs.c @@ -0,0 +1,8 @@ +// 22 may 2016 +#include "../ui.h" +#include "uipriv.h" + +void uiUserBugCannotSetParentOnToplevel(const char *type) +{ + userbug("You cannot make a %s a child of another uiControl,", type); +} |