jtk.c: support multiple threads

This commit is contained in:
Josh Holtrop 2020-07-07 16:25:12 -04:00
parent d3d6fd0fbf
commit 6cf36a852f

View File

@ -28,6 +28,12 @@ bool jtk_init()
None, None,
}; };
if (XInitThreads() != 0)
{
fprintf(stderr, "XInitThreads() failure\n");
return false;
}
g_display = XOpenDisplay(NULL); g_display = XOpenDisplay(NULL);
if (g_display == NULL) if (g_display == NULL)
{ {
@ -35,6 +41,8 @@ bool jtk_init()
return false; return false;
} }
XLockDisplay(g_display);
g_vi = glXChooseVisual(g_display, DefaultScreen(g_display), g_vi = glXChooseVisual(g_display, DefaultScreen(g_display),
glx_attribute_list); glx_attribute_list);
if (g_vi == NULL) if (g_vi == NULL)
@ -58,6 +66,8 @@ bool jtk_init()
KeyPressMask | KeyReleaseMask | KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask; ButtonPressMask | ButtonReleaseMask;
XUnlockDisplay(g_display);
return true; return true;
} }
@ -89,44 +99,56 @@ static Bool wait_for_notify(Display * display, XEvent * event, XPointer arg)
void * jtk_window_create() void * jtk_window_create()
{ {
XEvent event; XEvent event;
XLockDisplay(g_display);
Window window = XCreateWindow(g_display, Window window = XCreateWindow(g_display,
RootWindow(g_display, g_vi->screen), RootWindow(g_display, g_vi->screen),
0, 0, 800u, 800u, 0u, g_vi->depth, InputOutput, g_vi->visual, 0, 0, 800u, 800u, 0u, g_vi->depth, InputOutput, g_vi->visual,
CWBorderPixel | CWColormap | CWEventMask, &g_swa); CWBorderPixel | CWColormap | CWEventMask, &g_swa);
XMapWindow(g_display, window); XMapWindow(g_display, window);
XIfEvent(g_display, &event, wait_for_notify, (XPointer)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"); fprintf(stderr, "glXMakeCurrent() failure\n");
XDestroyWindow(g_display, window); XDestroyWindow(g_display, window);
return NULL; window = NULL;
} }
/* Disable the window close button. */ XUnlockDisplay(g_display);
Atom wm_delete_window_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(g_display, window, &wm_delete_window_atom, 1);
return (void *)window; return (void *)window;
} }
void jtk_window_swap_buffers(void * window) void jtk_window_swap_buffers(void * window)
{ {
XLockDisplay(g_display);
glXSwapBuffers(g_display, (Window)window); glXSwapBuffers(g_display, (Window)window);
XUnlockDisplay(g_display);
} }
void jtk_window_close(void * window) void jtk_window_close(void * window)
{ {
XLockDisplay(g_display);
XDestroyWindow(g_display, (Window)window); XDestroyWindow(g_display, (Window)window);
XUnlockDisplay(g_display);
} }
void jtk_window_set_title(void * window, const char * title) void jtk_window_set_title(void * window, const char * title)
{ {
XLockDisplay(g_display);
XTextProperty title_property; XTextProperty title_property;
if (XStringListToTextProperty((char **)&title, 1, &title_property) != 0) if (XStringListToTextProperty((char **)&title, 1, &title_property) != 0)
{ {
XSetTextProperty(g_display, (Window)window, &title_property, XA_WM_NAME); XSetTextProperty(g_display, (Window)window, &title_property, XA_WM_NAME);
XFree(title_property.value); 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, void jtk_window_set_icon(void * window, const uint8_t * data,
size_t width, size_t height) size_t width, size_t height)
{ {
XLockDisplay(g_display);
Atom net_wm_icon_atom = XInternAtom(g_display, "_NET_WM_ICON", False); Atom net_wm_icon_atom = XInternAtom(g_display, "_NET_WM_ICON", False);
size_t property_size = (2u + width * height) * sizeof(long); size_t property_size = (2u + width * height) * sizeof(long);
unsigned long * property_data = (unsigned long *)malloc(property_size); 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); 32, PropModeReplace, (uint8_t *)property_data, property_size);
XFlush(g_display); XFlush(g_display);
free(property_data); 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 jtk_check_event(jtk_event_t * event)
{ {
bool event_found = false;
XLockDisplay(g_display);
/* First check for an X event. */ /* First check for an X event. */
while (XPending(g_display) > 0) while (XPending(g_display) > 0)
{ {
XEvent x_event; XEvent x_event;
XNextEvent(g_display, &x_event); XNextEvent(g_display, &x_event);
if (process_x_event(&x_event, 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) 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; time_to_wait = MAX_WAIT_TIME;
} }
XLockDisplay(g_display);
int x_fd = ConnectionNumber(g_display); int x_fd = ConnectionNumber(g_display);
XUnlockDisplay(g_display);
fd_set fds; fd_set fds;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(x_fd, &fds); FD_SET(x_fd, &fds);