aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-04-30 06:10:29 +0000
committerDavid Robillard <d@drobilla.net>2012-04-30 06:10:29 +0000
commitfb2ec4fd62e8218ac485c4ad1992c7e01951159d (patch)
tree7b4d9ebc8a7306dfd7b780b0a60131e4c5effa5b
parentc0059bd2d7673a155efca5cb86e92b8106f12ac5 (diff)
Implement special keys and keyboard modifiers on X11.
-rw-r--r--pugl/pugl.h46
-rw-r--r--pugl/pugl_internal.h16
-rw-r--r--pugl/pugl_win.cpp4
-rw-r--r--pugl/pugl_x11.c58
-rw-r--r--pugl_test.c32
5 files changed, 146 insertions, 10 deletions
diff --git a/pugl/pugl.h b/pugl/pugl.h
index 8bc3f72..a77a831 100644
--- a/pugl/pugl.h
+++ b/pugl/pugl.h
@@ -77,6 +77,37 @@ typedef enum {
PUGL_SUCCESS = 0
} PuglStatus;
+typedef enum {
+ PUGL_KEY_F1 = 1,
+ PUGL_KEY_F2,
+ PUGL_KEY_F3,
+ PUGL_KEY_F4,
+ PUGL_KEY_F5,
+ PUGL_KEY_F6,
+ PUGL_KEY_F7,
+ PUGL_KEY_F8,
+ PUGL_KEY_F9,
+ PUGL_KEY_F10,
+ PUGL_KEY_F11,
+ PUGL_KEY_F12,
+ PUGL_KEY_LEFT,
+ PUGL_KEY_UP,
+ PUGL_KEY_RIGHT,
+ PUGL_KEY_DOWN,
+ PUGL_KEY_PAGE_UP,
+ PUGL_KEY_PAGE_DOWN,
+ PUGL_KEY_HOME,
+ PUGL_KEY_END,
+ PUGL_KEY_INSERT
+} PuglKey;
+
+typedef enum {
+ PUGL_MOD_SHIFT = 1, /**< Shift key */
+ PUGL_MOD_CTRL = 1 << 1, /**< Control key */
+ PUGL_MOD_ALT = 1 << 2, /**< Alt/Option key */
+ PUGL_MOD_SUPER = 1 << 3, /**< Mod4/Command/Windows key */
+} PuglModifier;
+
/**
Handle for opaque user data.
*/
@@ -90,6 +121,7 @@ typedef void (*PuglMouseFunc)(PuglView* view, int button, bool down,
int x, int y);
typedef void (*PuglReshapeFunc)(PuglView* view, int width, int height);
typedef void (*PuglScrollFunc)(PuglView* view, float dx, float dy);
+typedef void (*PuglSpecialFunc)(PuglView* view, bool press, PuglKey key);
/**
Create a new GL window.
@@ -125,6 +157,14 @@ PUGL_API PuglHandle
puglGetHandle(PuglView* view);
/**
+ Get the currently active modifiers (PuglModifier flags).
+
+ This should only be called from an event handler.
+*/
+int
+puglGetModifiers(PuglView* view);
+
+/**
Set the function to call when the window is closed.
*/
PUGL_API void
@@ -161,6 +201,12 @@ PUGL_API void
puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc);
/**
+ Set the function to call on special events.
+*/
+PUGL_API void
+puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc);
+
+/**
Set the function to call when the window size changes.
*/
PUGL_API void
diff --git a/pugl/pugl_internal.h b/pugl/pugl_internal.h
index 0b04e5d..21e9eb4 100644
--- a/pugl/pugl_internal.h
+++ b/pugl/pugl_internal.h
@@ -36,11 +36,13 @@ struct PuglViewImpl {
PuglMouseFunc mouseFunc;
PuglReshapeFunc reshapeFunc;
PuglScrollFunc scrollFunc;
+ PuglSpecialFunc specialFunc;
PuglPlatformData* impl;
int width;
int height;
+ int mods;
bool redisplay;
};
@@ -56,6 +58,12 @@ puglGetHandle(PuglView* view)
return view->handle;
}
+int
+puglGetModifiers(PuglView* view)
+{
+ return view->mods;
+}
+
void
puglSetCloseFunc(PuglView* view, PuglCloseFunc closeFunc)
{
@@ -85,7 +93,7 @@ puglSetMouseFunc(PuglView* view, PuglMouseFunc mouseFunc)
{
view->mouseFunc = mouseFunc;
}
-
+
void
puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc)
{
@@ -97,3 +105,9 @@ puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc)
{
view->scrollFunc = scrollFunc;
}
+
+void
+puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc)
+{
+ view->specialFunc = specialFunc;
+}
diff --git a/pugl/pugl_win.cpp b/pugl/pugl_win.cpp
index f487352..a5c9dde 100644
--- a/pugl/pugl_win.cpp
+++ b/pugl/pugl_win.cpp
@@ -157,8 +157,8 @@ processMouseEvent(PuglView* view, int button, bool press, LPARAM lParam)
{
if (view->mouseFunc) {
view->mouseFunc(view, button, press,
- GET_X_LPARAM(lParam),
- GET_Y_LPARAM(lParam));
+ GET_X_LPARAM(lParam),
+ GET_Y_LPARAM(lParam));
}
}
diff --git a/pugl/pugl_x11.c b/pugl/pugl_x11.c
index 606f348..f7d6e32 100644
--- a/pugl/pugl_x11.c
+++ b/pugl/pugl_x11.c
@@ -207,6 +207,45 @@ puglDisplay(PuglView* view)
view->redisplay = false;
}
+static PuglKey
+keySymToSpecial(KeySym sym)
+{
+ switch (sym) {
+ case XK_F1: return PUGL_KEY_F1;
+ case XK_F2: return PUGL_KEY_F2;
+ case XK_F3: return PUGL_KEY_F3;
+ case XK_F4: return PUGL_KEY_F4;
+ case XK_F5: return PUGL_KEY_F5;
+ case XK_F6: return PUGL_KEY_F6;
+ case XK_F7: return PUGL_KEY_F7;
+ case XK_F8: return PUGL_KEY_F8;
+ case XK_F9: return PUGL_KEY_F9;
+ case XK_F10: return PUGL_KEY_F10;
+ case XK_F11: return PUGL_KEY_F11;
+ case XK_F12: return PUGL_KEY_F12;
+ case XK_Left: return PUGL_KEY_LEFT;
+ case XK_Up: return PUGL_KEY_UP;
+ case XK_Right: return PUGL_KEY_RIGHT;
+ case XK_Down: return PUGL_KEY_DOWN;
+ case XK_Page_Up: return PUGL_KEY_PAGE_UP;
+ case XK_Page_Down: return PUGL_KEY_PAGE_DOWN;
+ case XK_Home: return PUGL_KEY_HOME;
+ case XK_End: return PUGL_KEY_END;
+ case XK_Insert: return PUGL_KEY_INSERT;
+ }
+ return (PuglKey)0;
+}
+
+static void
+setModifiers(PuglView* view, int xstate)
+{
+ view->mods = 0;
+ view->mods |= (xstate & ShiftMask) ? PUGL_MOD_SHIFT : 0;
+ view->mods |= (xstate & ControlMask) ? PUGL_MOD_CTRL : 0;
+ view->mods |= (xstate & Mod1Mask) ? PUGL_MOD_ALT : 0;
+ view->mods |= (xstate & Mod4Mask) ? PUGL_MOD_SUPER : 0;
+}
+
PuglStatus
puglProcessEvents(PuglView* view)
{
@@ -235,11 +274,13 @@ puglProcessEvents(PuglView* view)
view->redisplay = false;
break;
case MotionNotify:
+ setModifiers(view, event.xmotion.state);
if (view->motionFunc) {
view->motionFunc(view, event.xmotion.x, event.xmotion.y);
}
break;
case ButtonPress:
+ setModifiers(view, event.xbutton.state);
if (event.xbutton.button >= 4 && event.xbutton.button <= 7) {
if (view->scrollFunc) {
float dx = 0, dy = 0;
@@ -255,6 +296,7 @@ puglProcessEvents(PuglView* view)
}
// nobreak
case ButtonRelease:
+ setModifiers(view, event.xbutton.state);
if (view->mouseFunc &&
(event.xbutton.button < 4 || event.xbutton.button > 7)) {
view->mouseFunc(view,
@@ -263,13 +305,20 @@ puglProcessEvents(PuglView* view)
}
break;
case KeyPress:
+ setModifiers(view, event.xkey.state);
if (view->keyboardFunc) {
KeySym sym = XKeycodeToKeysym(
view->impl->display, event.xkey.keycode, 0);
- view->keyboardFunc(view, event.type == KeyPress, sym);
+ PuglKey special = keySymToSpecial(sym);
+ if (!special) {
+ view->keyboardFunc(view, true, sym);
+ } else if (view->specialFunc) {
+ view->specialFunc(view, true, special);
+ }
}
break;
case KeyRelease: {
+ setModifiers(view, event.xkey.state);
bool retriggered = false;
if (XEventsQueued(view->impl->display, QueuedAfterReading)) {
XEvent next;
@@ -286,7 +335,12 @@ puglProcessEvents(PuglView* view)
if (!retriggered && view->keyboardFunc) {
KeySym sym = XKeycodeToKeysym(
view->impl->display, event.xkey.keycode, 0);
- view->keyboardFunc(view, false, sym);
+ PuglKey special = keySymToSpecial(sym);
+ if (!special) {
+ view->keyboardFunc(view, false, sym);
+ } else if (view->specialFunc) {
+ view->specialFunc(view, false, special);
+ }
}
}
case ClientMessage:
diff --git a/pugl_test.c b/pugl_test.c
index 4abbcda..cf8da2e 100644
--- a/pugl_test.c
+++ b/pugl_test.c
@@ -75,15 +75,34 @@ onDisplay(PuglView* view)
}
static void
+printModifiers(PuglView* view)
+{
+ int mods = puglGetModifiers(view);
+ fprintf(stderr, "Modifiers:%s%s%s%s\n",
+ (mods & PUGL_MOD_SHIFT) ? " Shift" : "",
+ (mods & PUGL_MOD_CTRL) ? " Ctrl" : "",
+ (mods & PUGL_MOD_ALT) ? " Alt" : "",
+ (mods & PUGL_MOD_SUPER) ? " Super" : "");
+}
+
+static void
onKeyboard(PuglView* view, bool press, uint32_t key)
{
- fprintf(stderr, "Key %c %s\n", (char)key, press ? "down" : "up");
+ fprintf(stderr, "Key %c %s ", (char)key, press ? "down" : "up");
+ printModifiers(view);
if (key == 'q' || key == 'Q' || key == KEY_ESCAPE) {
quit = 1;
}
}
static void
+onSpecial(PuglView* view, bool press, PuglKey key)
+{
+ fprintf(stderr, "Special key %d %s ", key, press ? "down" : "up");
+ printModifiers(view);
+}
+
+static void
onMotion(PuglView* view, int x, int y)
{
xAngle = x % 360;
@@ -94,14 +113,16 @@ onMotion(PuglView* view, int x, int y)
static void
onMouse(PuglView* view, int button, bool press, int x, int y)
{
- fprintf(stderr, "Mouse %d %s at %d,%d\n",
+ fprintf(stderr, "Mouse %d %s at %d,%d ",
button, press ? "down" : "up", x, y);
+ printModifiers(view);
}
static void
onScroll(PuglView* view, float dx, float dy)
{
- fprintf(stderr, "Scroll %f %f\n", dx, dy);
+ fprintf(stderr, "Scroll %f %f ", dx, dy);
+ printModifiers(view);
dist += dy / 4.0f;
puglPostRedisplay(view);
}
@@ -115,12 +136,13 @@ onClose(PuglView* view)
int
main(int argc, char** argv)
{
- bool resizable = argc > 1;
- PuglView* view = puglCreate(0, "Pugl Test", 512, 512, resizable);
+ bool resizable = argc > 1;
+ PuglView* view = puglCreate(0, "Pugl Test", 512, 512, resizable);
puglSetKeyboardFunc(view, onKeyboard);
puglSetMotionFunc(view, onMotion);
puglSetMouseFunc(view, onMouse);
puglSetScrollFunc(view, onScroll);
+ puglSetSpecialFunc(view, onSpecial);
puglSetDisplayFunc(view, onDisplay);
puglSetCloseFunc(view, onClose);