#include "SDL_internal.h"
#if defined(SDL_VIDEO_DRIVER_X11) && defined(SDL_VIDEO_DRIVER_X11_XSYNC)
#include "SDL_x11video.h"
#include "SDL_x11xsync.h"
static bool xsync_initialized = false;
static int query_xsync_version(Display *display, int major, int minor)
{
X11_XSyncInitialize(display, &major, &minor);
return (major * 1000) + minor;
}
static bool xsync_version_atleast(const int version, const int wantmajor, const int wantminor)
{
return version >= ((wantmajor * 1000) + wantminor);
}
void X11_InitXsync(SDL_VideoDevice *_this)
{
SDL_VideoData *data = _this->internal;
int version = 0;
int event, error;
int sync_opcode;
if (!SDL_X11_HAVE_XSYNC ||
!X11_XQueryExtension(data->display, "SYNC", &sync_opcode, &event, &error)) {
return;
}
version = query_xsync_version(data->display, 5, 0);
if (!xsync_version_atleast(version, 3, 0)) {
return;
}
xsync_initialized = true;
}
bool X11_XsyncIsInitialized(void)
{
return xsync_initialized;
}
bool X11_InitResizeSync(SDL_Window *window)
{
SDL_assert(window != NULL);
SDL_WindowData *data = window->internal;
Display *display = data->videodata->display;
Atom counter_prop = data->videodata->atoms._NET_WM_SYNC_REQUEST_COUNTER;
XSyncCounter counter;
CARD32 counter_id;
if (!X11_XsyncIsInitialized()){
return SDL_Unsupported();
}
counter = X11_XSyncCreateCounter(display, (XSyncValue){0, 0});
data->resize_counter = counter;
data->resize_id.lo = 0;
data->resize_id.hi = 0;
data->resize_in_progress = false;
if (counter == None){
return SDL_Unsupported();
}
counter_id = counter;
X11_XChangeProperty(display, data->xwindow, counter_prop, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *)&counter_id, 1);
return true;
}
void X11_TermResizeSync(SDL_Window *window)
{
SDL_WindowData *data = window->internal;
Display *display = data->videodata->display;
Atom counter_prop = data->videodata->atoms._NET_WM_SYNC_REQUEST_COUNTER;
XSyncCounter counter = data->resize_counter;
X11_XDeleteProperty(display, data->xwindow, counter_prop);
if (counter != None) {
X11_XSyncDestroyCounter(display, counter);
}
}
void X11_HandleSyncRequest(SDL_Window *window, XClientMessageEvent *event)
{
SDL_WindowData *data = window->internal;
data->resize_id.lo = event->data.l[2];
data->resize_id.hi = event->data.l[3];
data->resize_in_progress = false;
}
void X11_HandleConfigure(SDL_Window *window, XConfigureEvent *event)
{
SDL_WindowData *data = window->internal;
if (data->resize_id.lo || data->resize_id.hi) {
data->resize_in_progress = true;
}
}
void X11_HandlePresent(SDL_Window *window)
{
SDL_WindowData *data = window->internal;
Display *display = data->videodata->display;
XSyncCounter counter = data->resize_counter;
if ((counter == None) || (!data->resize_in_progress)) {
return;
}
X11_XSyncSetCounter(display, counter, data->resize_id);
data->resize_id.lo = 0;
data->resize_id.hi = 0;
data->resize_in_progress = false;
}
#endif