From 6cf36a852f05371a7826764771c9bc6c0f79a1be Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Tue, 7 Jul 2020 16:25:12 -0400 Subject: [PATCH] jtk.c: support multiple threads --- src/jtk/jtk.c | 49 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/src/jtk/jtk.c b/src/jtk/jtk.c index 2cb6274..397371c 100644 --- a/src/jtk/jtk.c +++ b/src/jtk/jtk.c @@ -28,6 +28,12 @@ bool jtk_init() None, }; + if (XInitThreads() != 0) + { + fprintf(stderr, "XInitThreads() failure\n"); + return false; + } + g_display = XOpenDisplay(NULL); if (g_display == NULL) { @@ -35,6 +41,8 @@ bool jtk_init() return false; } + XLockDisplay(g_display); + g_vi = glXChooseVisual(g_display, DefaultScreen(g_display), glx_attribute_list); if (g_vi == NULL) @@ -58,6 +66,8 @@ bool jtk_init() KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask; + XUnlockDisplay(g_display); + return true; } @@ -89,44 +99,56 @@ static Bool wait_for_notify(Display * display, XEvent * event, XPointer arg) void * jtk_window_create() { XEvent event; + + XLockDisplay(g_display); Window window = XCreateWindow(g_display, RootWindow(g_display, g_vi->screen), 0, 0, 800u, 800u, 0u, g_vi->depth, InputOutput, g_vi->visual, CWBorderPixel | CWColormap | CWEventMask, &g_swa); XMapWindow(g_display, window); XIfEvent(g_display, &event, wait_for_notify, (XPointer)window); - if (glXMakeCurrent(g_display, window, g_context) == False) + if (glXMakeCurrent(g_display, window, g_context) != False) + { + /* Disable the window close button. */ + Atom wm_delete_window_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", False); + XSetWMProtocols(g_display, window, &wm_delete_window_atom, 1); + } + else { fprintf(stderr, "glXMakeCurrent() failure\n"); XDestroyWindow(g_display, window); - return NULL; + window = NULL; } - /* Disable the window close button. */ - Atom wm_delete_window_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", False); - XSetWMProtocols(g_display, window, &wm_delete_window_atom, 1); + XUnlockDisplay(g_display); return (void *)window; } void jtk_window_swap_buffers(void * window) { + XLockDisplay(g_display); glXSwapBuffers(g_display, (Window)window); + XUnlockDisplay(g_display); } void jtk_window_close(void * window) { + XLockDisplay(g_display); XDestroyWindow(g_display, (Window)window); + XUnlockDisplay(g_display); } void jtk_window_set_title(void * window, const char * title) { + XLockDisplay(g_display); XTextProperty title_property; if (XStringListToTextProperty((char **)&title, 1, &title_property) != 0) { XSetTextProperty(g_display, (Window)window, &title_property, XA_WM_NAME); XFree(title_property.value); } + XUnlockDisplay(g_display); } /** @@ -145,6 +167,7 @@ void jtk_window_set_title(void * window, const char * title) void jtk_window_set_icon(void * window, const uint8_t * data, size_t width, size_t height) { + XLockDisplay(g_display); Atom net_wm_icon_atom = XInternAtom(g_display, "_NET_WM_ICON", False); size_t property_size = (2u + width * height) * sizeof(long); unsigned long * property_data = (unsigned long *)malloc(property_size); @@ -163,6 +186,7 @@ void jtk_window_set_icon(void * window, const uint8_t * data, 32, PropModeReplace, (uint8_t *)property_data, property_size); XFlush(g_display); free(property_data); + XUnlockDisplay(g_display); } /************************************************************************** @@ -631,16 +655,25 @@ static bool process_x_event(XEvent * x_event, jtk_event_t * event) bool jtk_check_event(jtk_event_t * event) { + bool event_found = false; + + XLockDisplay(g_display); + /* First check for an X event. */ while (XPending(g_display) > 0) { XEvent x_event; XNextEvent(g_display, &x_event); if (process_x_event(&x_event, event)) - return true; + { + event_found = true; + break; + } } - return false; + XUnlockDisplay(g_display); + + return event_found; } void jtk_wait_event(jtk_event_t * event, uint64_t time_to_wait) @@ -656,7 +689,9 @@ void jtk_wait_event(jtk_event_t * event, uint64_t time_to_wait) time_to_wait = MAX_WAIT_TIME; } + XLockDisplay(g_display); int x_fd = ConnectionNumber(g_display); + XUnlockDisplay(g_display); fd_set fds; FD_ZERO(&fds); FD_SET(x_fd, &fds);