mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-27 00:00:07 -06:00
another UI attempt, I guess.
sorry.
This commit is contained in:
16
src/libui_sdl/libui/common/CMakeLists.txt
Normal file
16
src/libui_sdl/libui/common/CMakeLists.txt
Normal file
@ -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)
|
167
src/libui_sdl/libui/common/areaevents.c
Normal file
167
src/libui_sdl/libui/common/areaevents.c
Normal file
@ -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;
|
||||
}
|
101
src/libui_sdl/libui/common/control.c
Normal file
101
src/libui_sdl/libui/common/control.c
Normal file
@ -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;
|
||||
}
|
25
src/libui_sdl/libui/common/controlsigs.h
Normal file
25
src/libui_sdl/libui/common/controlsigs.h
Normal file
@ -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
|
21
src/libui_sdl/libui/common/debug.c
Normal file
21
src/libui_sdl/libui/common/debug.c
Normal file
@ -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);
|
||||
}
|
50
src/libui_sdl/libui/common/matrix.c
Normal file
50
src/libui_sdl/libui/common/matrix.c
Normal file
@ -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);
|
||||
}
|
22
src/libui_sdl/libui/common/shouldquit.c
Normal file
22
src/libui_sdl/libui/common/shouldquit.c
Normal file
@ -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);
|
||||
}
|
58
src/libui_sdl/libui/common/uipriv.h
Normal file
58
src/libui_sdl/libui/common/uipriv.h
Normal file
@ -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
|
8
src/libui_sdl/libui/common/userbugs.c
Normal file
8
src/libui_sdl/libui/common/userbugs.c
Normal file
@ -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);
|
||||
}
|
Reference in New Issue
Block a user