diff options
author | David Robillard <d@drobilla.net> | 2019-07-23 19:58:10 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2019-09-03 08:34:38 +0200 |
commit | e5481cb32b6e63881670c885fb659ef5e0b4a7bf (patch) | |
tree | 52d43d18f7ca049277e75973ef5fc0ef704c3ece | |
parent | 816607027012de0205e144f3edd3fdcfd43db563 (diff) |
Make pugl_test use a nested view and test focus and movement
-rw-r--r-- | test/pugl_cairo_test.c | 5 | ||||
-rw-r--r-- | test/pugl_test.c | 215 | ||||
-rw-r--r-- | test/test_utils.h | 91 |
3 files changed, 228 insertions, 83 deletions
diff --git a/test/pugl_cairo_test.c b/test/pugl_cairo_test.c index 20a96e7..f339abd 100644 --- a/test/pugl_cairo_test.c +++ b/test/pugl_cairo_test.c @@ -207,9 +207,8 @@ main(int argc, char** argv) world = puglNewWorld(); - const PuglRect frame = { 0, 0, 512, 512 }; - - PuglView* view = puglNewView(world); + PuglRect frame = { 0, 0, 512, 512 }; + PuglView* view = puglNewView(world); puglInitWindowClass(view, "PuglCairoTest"); puglSetFrame(view, frame); puglInitWindowMinSize(view, 256, 256); diff --git a/test/pugl_test.c b/test/pugl_test.c index ea849a6..65f764e 100644 --- a/test/pugl_test.c +++ b/test/pugl_test.c @@ -32,9 +32,13 @@ #include <stdio.h> #include <string.h> +static const int borderWidth = 64; + typedef struct { PuglWorld* world; + PuglView* parent; + PuglView* child; bool continuous; int quit; float xAngle; @@ -47,6 +51,19 @@ typedef struct bool mouseEntered; } PuglTestApp; +static PuglRect +getChildFrame(const PuglRect parentFrame) +{ + const PuglRect childFrame = { + borderWidth, + borderWidth, + parentFrame.width - 2 * borderWidth, + parentFrame.height - 2 * borderWidth + }; + + return childFrame; +} + static void onReshape(PuglView* view, int width, int height) { @@ -83,29 +100,144 @@ onDisplay(PuglView* view) glRotatef(app->xAngle, 0.0f, 1.0f, 0.0f); glRotatef(app->yAngle, 1.0f, 0.0f, 0.0f); - const float bg = app->mouseEntered ? 0.2f : 0.0f; + const float bg = app->mouseEntered ? 0.2f : 0.1f; glClearColor(bg, bg, bg, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, cubeVertices); - glColorPointer(3, GL_FLOAT, 0, cubeVertices); - glDrawArrays(GL_TRIANGLES, 0, 12 * 3); + if (puglHasFocus(app->child)) { + // Draw cube surfaces + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, cubeStripVertices); + glColorPointer(3, GL_FLOAT, 0, cubeStripVertices); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 14); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + glColor3f(0.0f, 0.0f, 0.0f); + } else { + glColor3f(1.0f, 1.0f, 1.0f); + } + // Draw cube wireframe + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, cubeFrontLineLoop); + glDrawArrays(GL_LINE_LOOP, 0, 4); + glVertexPointer(3, GL_FLOAT, 0, cubeBackLineLoop); + glDrawArrays(GL_LINE_LOOP, 0, 4); + glVertexPointer(3, GL_FLOAT, 0, cubeSideLines); + glDrawArrays(GL_LINES, 0, 8); glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); app->lastDrawTime = thisTime; ++app->framesDrawn; } static void +swapFocus(PuglTestApp* app) +{ + if (puglHasFocus(app->parent)) { + puglGrabFocus(app->child); + } else { + puglGrabFocus(app->parent); + } + + puglPostRedisplay(app->parent); + puglPostRedisplay(app->child); +} + +static void +onKeyPress(PuglView* view, const PuglEventKey* event) +{ + PuglTestApp* app = (PuglTestApp*)puglGetHandle(view); + PuglRect frame = puglGetFrame(view); + + if (event->key == '\t') { + swapFocus(app); + } else if (event->key == 'q' || event->key == PUGL_KEY_ESCAPE) { + app->quit = 1; + } else if (event->state & PUGL_MOD_SHIFT) { + if (event->key == PUGL_KEY_UP) { + frame.height += 10; + } else if (event->key == PUGL_KEY_DOWN) { + frame.height -= 10; + } else if (event->key == PUGL_KEY_LEFT) { + frame.width -= 10; + } else if (event->key == PUGL_KEY_RIGHT) { + frame.width += 10; + } else { + return; + } + puglSetFrame(view, frame); + } else { + if (event->key == PUGL_KEY_UP) { + frame.y -= 10; + } else if (event->key == PUGL_KEY_DOWN) { + frame.y += 10; + } else if (event->key == PUGL_KEY_LEFT) { + frame.x -= 10; + } else if (event->key == PUGL_KEY_RIGHT) { + frame.x += 10; + } else { + return; + } + puglSetFrame(view, frame); + } +} + +static void +onParentEvent(PuglView* view, const PuglEvent* event) +{ + PuglTestApp* app = (PuglTestApp*)puglGetHandle(view); + const PuglRect parentFrame = puglGetFrame(view); + + printEvent(event, "Parent: "); + + switch (event->type) { + case PUGL_CONFIGURE: + onReshape(view, + (int)event->configure.width, + (int)event->configure.height); + + puglSetFrame(app->child, getChildFrame(parentFrame)); + break; + case PUGL_EXPOSE: + if (puglHasFocus(app->parent)) { + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, cubeStripVertices); + glColorPointer(3, GL_FLOAT, 0, cubeStripVertices); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 14); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + } else { + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + break; + case PUGL_KEY_PRESS: + onKeyPress(view, &event->key); + break; + case PUGL_MOTION_NOTIFY: + break; + case PUGL_CLOSE: + app->quit = 1; + break; + default: + break; + } +} + +static void onEvent(PuglView* view, const PuglEvent* event) { PuglTestApp* app = (PuglTestApp*)puglGetHandle(view); - printEvent(event, "Event: "); + printEvent(event, "Child: "); switch (event->type) { case PUGL_CONFIGURE: @@ -118,9 +250,7 @@ onEvent(PuglView* view, const PuglEvent* event) app->quit = 1; break; case PUGL_KEY_PRESS: - if (event->key.key == 'q' || event->key.key == PUGL_KEY_ESCAPE) { - app->quit = 1; - } + onKeyPress(view, &event->key); break; case PUGL_MOTION_NOTIFY: app->xAngle = fmodf(app->xAngle - (float)(event->motion.x - app->lastMouseX), 360.0f); @@ -128,6 +258,7 @@ onEvent(PuglView* view, const PuglEvent* event) app->lastMouseX = event->motion.x; app->lastMouseY = event->motion.y; puglPostRedisplay(view); + puglPostRedisplay(app->parent); break; case PUGL_SCROLL: app->dist = fmaxf(10.0f, app->dist + (float)event->scroll.dy); @@ -179,32 +310,50 @@ main(int argc, char** argv) } } - app.world = puglNewWorld(); + app.world = puglNewWorld(); + app.parent = puglNewView(app.world); + app.child = puglNewView(app.world); - const PuglRect frame = { 0, 0, 512, 512 }; + const PuglRect parentFrame = { 0, 0, 512, 512 }; + puglInitWindowClass(app.parent, "PuglTest"); + puglSetFrame(app.parent, parentFrame); + puglInitWindowMinSize(app.parent, 256, 256); + puglInitWindowAspectRatio(app.parent, 1, 1, 16, 9); + puglInitBackend(app.parent, puglGlBackend()); - PuglView* view = puglNewView(app.world); - puglInitWindowClass(view, "PuglTest"); - puglSetFrame(view, frame); - puglInitWindowMinSize(view, 256, 256); - puglInitWindowAspectRatio(view, 1, 1, 16, 9); - puglInitBackend(view, puglGlBackend()); - - puglInitWindowHint(view, PUGL_RESIZABLE, resizable); - puglInitWindowHint(view, PUGL_SAMPLES, samples); - puglInitWindowHint(view, PUGL_DOUBLE_BUFFER, doubleBuffer); - - puglInitWindowHint(view, PUGL_IGNORE_KEY_REPEAT, ignoreKeyRepeat); - puglSetEventFunc(view, onEvent); - puglSetHandle(view, &app); + puglInitWindowHint(app.parent, PUGL_RESIZABLE, resizable); + puglInitWindowHint(app.parent, PUGL_SAMPLES, samples); + puglInitWindowHint(app.parent, PUGL_DOUBLE_BUFFER, doubleBuffer); + puglInitWindowHint(app.parent, PUGL_IGNORE_KEY_REPEAT, ignoreKeyRepeat); + puglSetHandle(app.parent, &app); + puglSetEventFunc(app.parent, onParentEvent); const uint8_t title[] = { 'P', 'u', 'g', 'l', ' ', 'P', 'r', 0xC3, 0xBC, 'f', 'u', 'n', 'g', 0 }; - if (puglCreateWindow(view, (const char*)title)) { + if (puglCreateWindow(app.parent, (const char*)title)) { + fprintf(stderr, "error: Failed to create parent window\n"); + return 1; + } + + puglInitWindowClass(app.child, "PuglTest"); + puglSetFrame(app.child, getChildFrame(parentFrame)); + puglInitWindowParent(app.child, puglGetNativeWindow(app.parent)); + + puglInitWindowHint(app.child, PUGL_SAMPLES, samples); + puglInitWindowHint(app.child, PUGL_DOUBLE_BUFFER, doubleBuffer); + puglInitBackend(app.child, puglGlBackend()); + puglInitWindowHint(app.child, PUGL_IGNORE_KEY_REPEAT, ignoreKeyRepeat); + puglSetHandle(app.child, &app); + puglSetEventFunc(app.child, onEvent); + + const int st = puglCreateWindow(app.child, NULL); + if (st) { + fprintf(stderr, "error: Failed to create child window (%d)\n", st); return 1; } - puglShowWindow(view); + puglShowWindow(app.parent); + puglShowWindow(app.child); PuglFpsPrinter fpsPrinter = { puglGetTime(app.world) }; bool requestedAttention = false; @@ -212,7 +361,8 @@ main(int argc, char** argv) const double thisTime = puglGetTime(app.world); if (app.continuous) { - puglPostRedisplay(view); + puglPostRedisplay(app.parent); + puglPostRedisplay(app.child); } else { puglPollEvents(app.world, -1); } @@ -220,7 +370,7 @@ main(int argc, char** argv) puglDispatchEvents(app.world); if (!requestedAttention && thisTime > 5.0) { - puglRequestAttention(view); + puglRequestAttention(app.parent); requestedAttention = true; } @@ -229,7 +379,8 @@ main(int argc, char** argv) } } - puglFreeView(view); + puglFreeView(app.child); + puglFreeView(app.parent); puglFreeWorld(app.world); return 0; diff --git a/test/test_utils.h b/test/test_utils.h index 12dbfaa..bf058ac 100644 --- a/test/test_utils.h +++ b/test/test_utils.h @@ -24,54 +24,49 @@ typedef struct { double lastReportTime; } PuglFpsPrinter; -static const float cubeVertices[] = { - -1.0f, -1.0f, -1.0f, - -1.0f, -1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, - - 1.0f, 1.0f, -1.0f, - -1.0f, -1.0f, -1.0f, - -1.0f, 1.0f, -1.0f, - - 1.0f, -1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, - - 1.0f, 1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, - -1.0f, -1.0f, -1.0f, - - -1.0f, -1.0f, -1.0f, - -1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, -1.0f, - - 1.0f, -1.0f, 1.0f, - -1.0f, -1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, - - -1.0f, 1.0f, 1.0f, - -1.0f, -1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, - - 1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, - 1.0f, 1.0f, -1.0f, - - 1.0f, -1.0f, -1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, - - 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, -1.0f, - -1.0f, 1.0f, -1.0f, - - 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, -1.0f, - -1.0f, 1.0f, 1.0f, - - 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f +static const float cubeStripVertices[] = { + -1.0f, 1.0f, 1.0f, // Front top left + 1.0f, 1.0f, 1.0f, // Front top right + -1.0f, -1.0f, 1.0f, // Front bottom left + 1.0f, -1.0f, 1.0f, // Front bottom right + 1.0f, -1.0f, -1.0f, // Back bottom right + 1.0f, 1.0f, 1.0f, // Front top right + 1.0f, 1.0f, -1.0f, // Back top right + -1.0f, 1.0f, 1.0f, // Front top left + -1.0f, 1.0f, -1.0f, // Back top left + -1.0f, -1.0f, 1.0f, // Front bottom left + -1.0f, -1.0f, -1.0f, // Back bottom left + 1.0f, -1.0f, -1.0f, // Back bottom right + -1.0f, 1.0f, -1.0f, // Back top left + 1.0f, 1.0f, -1.0f // Back top right +}; + +static const float cubeFrontLineLoop[] = { + -1.0f, 1.0f, 1.0f, // Front top left + 1.0f, 1.0f, 1.0f, // Front top right + 1.0f, -1.0f, 1.0f, // Front bottom right + -1.0f, -1.0f, 1.0f, // Front bottom left +}; + +static const float cubeBackLineLoop[] = { + -1.0f, 1.0f, -1.0f, // Back top left + 1.0f, 1.0f, -1.0f, // Back top right + 1.0f, -1.0f, -1.0f, // Back bottom right + -1.0f, -1.0f, -1.0f, // Back bottom left +}; + +static const float cubeSideLines[] = { + -1.0f, 1.0f, 1.0f, // Front top left + -1.0f, 1.0f, -1.0f, // Back top left + + -1.0f, -1.0f, 1.0f, // Front bottom left + -1.0f, -1.0f, -1.0f, // Back bottom left + + 1.0f, 1.0f, 1.0f, // Front top right + 1.0f, 1.0f, -1.0f, // Back top right + + 1.0f, -1.0f, 1.0f, // Front bottom right + 1.0f, -1.0f, -1.0f, // Back bottom right }; /** Calculate a projection matrix for a given perspective. */ |