diff --git a/src/gui/jtk/Jtk-X.cc b/src/gui/jtk/Jtk.cc similarity index 52% rename from src/gui/jtk/Jtk-X.cc rename to src/gui/jtk/Jtk.cc index dd9af0b..f150c72 100644 --- a/src/gui/jtk/Jtk-X.cc +++ b/src/gui/jtk/Jtk.cc @@ -1,18 +1,14 @@ +#include "Jtk.h" + #ifdef JTK_X -#include "Jtk.h" #include #include -static Display * g_display; -static XVisualInfo * g_vi; -static XSetWindowAttributes g_swa; -static GLXContext g_context; - -static Bool WaitForNotify(Display * display, XEvent * event, XPointer arg) -{ - return (event->type == MapNotify) && (event->xmap.window == (Window)arg); -} +Display * g_display; +XVisualInfo * g_vi; +XSetWindowAttributes g_swa; +GLXContext g_context; /** * Initialize the Jtk subsystem. @@ -60,33 +56,4 @@ bool Jtk_Init() return true; } -void * Jtk_CreateWindow() -{ - XEvent event; - Window window = XCreateWindow(g_display, - RootWindow(g_display, g_vi->screen), - 0, 0, 800, 800, 0, g_vi->depth, InputOutput, g_vi->visual, - CWBorderPixel | CWColormap | CWEventMask, &g_swa); - XMapWindow(g_display, window); - XIfEvent(g_display, &event, WaitForNotify, (XPointer)window); - if (glXMakeCurrent(g_display, window, g_context) == False) - { - fprintf(stderr, "glXMakeCurrent() failure\n"); - XDestroyWindow(g_display, window); - return nullptr; - } - - return (void *)window; -} - -void Jtk_SwapBuffers(void * window) -{ - glXSwapBuffers(g_display, (Window)window); -} - -void Jtk_CloseWindow(void * window) -{ - XDestroyWindow(g_display, (Window)window); -} - #endif diff --git a/src/gui/jtk/Jtk_event.cc b/src/gui/jtk/Jtk_event.cc index 281c042..e75ab79 100644 --- a/src/gui/jtk/Jtk_event.cc +++ b/src/gui/jtk/Jtk_event.cc @@ -1,5 +1,94 @@ #include "Jtk.h" +#ifdef JTK_X + +#include +#include +#include +#include +#include "Jtk_internal.h" + +/** Do not wait longer than 100ms */ +#define MAX_WAIT_TIME 100000u + +/** + * Process an X event. + * + * @param x_event + * Pointer to the X event. + * @param event + * Pointer to the Jtk event. + * + * @retval true + * The event should be passed to the user and event has been filled in. + * @retval false + * The event should not be passed to the user. + */ +static bool ProcessXEvent(XEvent * x_event, Jtk_Event * event) +{ + switch (x_event->type) + { + case KeyPress: + break; + + case KeyRelease: + break; + + case ButtonPress: + break; + + case ButtonRelease: + break; + + case Expose: + break; + + case MappingNotify: + XRefreshKeyboardMapping(&x_event->xmapping); + return false; + } + + return false; +} + void Jtk_WaitForEvent(Jtk_Event * event) { + for (;;) + { + /* First check if any timer has expired. */ + size_t timer_id = Jtk_GetExpiredTimer(); + if (timer_id != (size_t)-1) + { + event->type = JTK_EVENT_TIMER; + event->timer.timer_id = timer_id; + return; + } + + /* Next check for an X event. */ + if (XPending(g_display) > 0) + { + XEvent x_event; + XNextEvent(g_display, &x_event); + if (ProcessXEvent(&x_event, event)) + return; + } + + /* Finally, wait for something to happen. */ + uint64_t time_to_wait = Jtk_TimeToNextTimerExpiration(); + if (time_to_wait > MAX_WAIT_TIME) + { + time_to_wait = MAX_WAIT_TIME; + } + + int x_fd = ConnectionNumber(g_display); + fd_set fds; + FD_ZERO(&fds); + FD_SET(x_fd, &fds); + struct timeval tv; + tv.tv_sec = time_to_wait / 1000000u; + tv.tv_usec = time_to_wait % 1000000u; + select(x_fd + 1, &fds, nullptr, nullptr, &tv); + } } + +#endif diff --git a/src/gui/jtk/Jtk_event.h b/src/gui/jtk/Jtk_event.h index 3fbedd0..88da58b 100644 --- a/src/gui/jtk/Jtk_event.h +++ b/src/gui/jtk/Jtk_event.h @@ -5,11 +5,12 @@ #include #define JTK_EVENT_CLOSE_WINDOW 1u -#define JTK_EVENT_EXPOSE 2u +#define JTK_EVENT_WINDOW_EXPOSE 2u #define JTK_EVENT_KEY_PRESS 3u #define JTK_EVENT_KEY_RELEASE 4u #define JTK_EVENT_BUTTON_PRESS 5u #define JTK_EVENT_BUTTON_RELEASE 6u +#define JTK_EVENT_TIMER 7u typedef struct { diff --git a/src/gui/jtk/Jtk_internal.h b/src/gui/jtk/Jtk_internal.h new file mode 100644 index 0000000..5d5c518 --- /dev/null +++ b/src/gui/jtk/Jtk_internal.h @@ -0,0 +1,9 @@ +#ifndef JTK_INTERNAL_H +#define JTK_INTERNAL_H + +extern Display * g_display; +extern XVisualInfo * g_vi; +extern XSetWindowAttributes g_swa; +extern GLXContext g_context; + +#endif diff --git a/src/gui/jtk/Jtk_window.cc b/src/gui/jtk/Jtk_window.cc new file mode 100644 index 0000000..b6b3dda --- /dev/null +++ b/src/gui/jtk/Jtk_window.cc @@ -0,0 +1,44 @@ + +#include "Jtk.h" + +#ifdef JTK_X + +#include +#include "Jtk_internal.h" +#include + +static Bool WaitForNotify(Display * display, XEvent * event, XPointer arg) +{ + return (event->type == MapNotify) && (event->xmap.window == (Window)arg); +} + +void * Jtk_CreateWindow() +{ + XEvent event; + Window window = XCreateWindow(g_display, + RootWindow(g_display, g_vi->screen), + 0, 0, 800, 800, 0, g_vi->depth, InputOutput, g_vi->visual, + CWBorderPixel | CWColormap | CWEventMask, &g_swa); + XMapWindow(g_display, window); + XIfEvent(g_display, &event, WaitForNotify, (XPointer)window); + if (glXMakeCurrent(g_display, window, g_context) == False) + { + fprintf(stderr, "glXMakeCurrent() failure\n"); + XDestroyWindow(g_display, window); + return nullptr; + } + + return (void *)window; +} + +void Jtk_SwapBuffers(void * window) +{ + glXSwapBuffers(g_display, (Window)window); +} + +void Jtk_CloseWindow(void * window) +{ + XDestroyWindow(g_display, (Window)window); +} + +#endif