Skip to content

Commit

Permalink
X11: support _NET_WM_SYNC_REQUEST
Browse files Browse the repository at this point in the history
  • Loading branch information
numberZero authored and icculus committed Dec 4, 2024
1 parent d320d71 commit 123306b
Show file tree
Hide file tree
Showing 16 changed files with 286 additions and 4 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ set_option(SDL_RPATH "Use an rpath when linking SDL" ${SDL_RPATH_D
set_option(SDL_CLOCK_GETTIME "Use clock_gettime() instead of gettimeofday()" ${SDL_CLOCK_GETTIME_DEFAULT})
dep_option(SDL_X11 "Use X11 video driver" ${UNIX_SYS} "SDL_VIDEO" OFF)
dep_option(SDL_X11_SHARED "Dynamically load X11 support" ON "SDL_X11" OFF)
set(SDL_X11_OPTIONS Xcursor Xdbe XInput Xfixes Xrandr Xscrnsaver XShape)
set(SDL_X11_OPTIONS Xcursor Xdbe XInput Xfixes Xrandr Xscrnsaver XShape Xsync)
foreach(_SUB ${SDL_X11_OPTIONS})
string(TOUPPER "SDL_X11_${_SUB}" _OPT)
dep_option(${_OPT} "Enable ${_SUB} support" ON "SDL_X11" OFF)
Expand Down
6 changes: 6 additions & 0 deletions cmake/sdlchecks.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ macro(CheckX11)
find_file(HAVE_XRANDR_H NAMES "X11/extensions/Xrandr.h" HINTS "${X11_INCLUDEDIR}")
find_file(HAVE_XFIXES_H_ NAMES "X11/extensions/Xfixes.h" HINTS "${X11_INCLUDEDIR}")
find_file(HAVE_XRENDER_H NAMES "X11/extensions/Xrender.h" HINTS "${X11_INCLUDEDIR}")
find_file(HAVE_XSYNC_H NAMES "X11/extensions/sync.h" HINTS "${X11_INCLUDEDIR}")
find_file(HAVE_XSS_H NAMES "X11/extensions/scrnsaver.h" HINTS "${X11_INCLUDEDIR}")
find_file(HAVE_XSHAPE_H NAMES "X11/extensions/shape.h" HINTS "${X11_INCLUDEDIR}")
find_file(HAVE_XDBE_H NAMES "X11/extensions/Xdbe.h" HINTS "${X11_INCLUDEDIR}")
Expand Down Expand Up @@ -445,6 +446,11 @@ macro(CheckX11)
set(HAVE_X11_XFIXES TRUE)
endif()

if(SDL_X11_XSYNC AND HAVE_XSYNC_H AND XEXT_LIB)
set(SDL_VIDEO_DRIVER_X11_XSYNC 1)
set(HAVE_X11_XSYNC TRUE)
endif()

if(SDL_X11_XRANDR AND HAVE_XRANDR_H AND XRANDR_LIB)
if(HAVE_X11_SHARED)
set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "\"${XRANDR_LIB_SONAME}\"")
Expand Down
1 change: 1 addition & 0 deletions include/build_config/SDL_build_config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@
#cmakedefine SDL_VIDEO_DRIVER_X11_XRANDR @SDL_VIDEO_DRIVER_X11_XRANDR@
#cmakedefine SDL_VIDEO_DRIVER_X11_XSCRNSAVER @SDL_VIDEO_DRIVER_X11_XSCRNSAVER@
#cmakedefine SDL_VIDEO_DRIVER_X11_XSHAPE @SDL_VIDEO_DRIVER_X11_XSHAPE@
#cmakedefine SDL_VIDEO_DRIVER_X11_XSYNC @SDL_VIDEO_DRIVER_X11_XSYNC@
#cmakedefine SDL_VIDEO_DRIVER_QNX @SDL_VIDEO_DRIVER_QNX@

#cmakedefine SDL_VIDEO_RENDER_D3D @SDL_VIDEO_RENDER_D3D@
Expand Down
3 changes: 3 additions & 0 deletions src/video/x11/SDL_x11dyn.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
#ifdef SDL_VIDEO_DRIVER_X11_XFIXES
#include <X11/extensions/Xfixes.h>
#endif
#ifdef SDL_VIDEO_DRIVER_X11_XSYNC
#include <X11/extensions/sync.h>
#endif
#ifdef SDL_VIDEO_DRIVER_X11_XRANDR
#include <X11/extensions/Xrandr.h>
#endif
Expand Down
17 changes: 17 additions & 0 deletions src/video/x11/SDL_x11events.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "SDL_x11xfixes.h"
#include "SDL_x11settings.h"
#include "../SDL_clipboard_c.h"
#include "SDL_x11xsync.h"
#include "../../core/unix/SDL_poll.h"
#include "../../events/SDL_events_c.h"
#include "../../events/SDL_mouse_c.h"
Expand Down Expand Up @@ -1376,6 +1377,11 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
}
}
}

#ifdef SDL_VIDEO_DRIVER_X11_XSYNC
X11_HandleConfigure(data->window, &xevent->xconfigure);
#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */

if (xevent->xconfigure.width != data->last_xconfigure.width ||
xevent->xconfigure.height != data->last_xconfigure.height) {
if (!data->disable_size_position_events) {
Expand Down Expand Up @@ -1501,6 +1507,17 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
#endif
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_CLOSE_REQUESTED, 0, 0);
break;
} else if ((xevent->xclient.message_type == videodata->atoms.WM_PROTOCOLS) &&
(xevent->xclient.format == 32) &&
(xevent->xclient.data.l[0] == videodata->atoms._NET_WM_SYNC_REQUEST)) {

#ifdef DEBUG_XEVENTS
printf("window %p: _NET_WM_SYNC_REQUEST\n", data);
#endif
#ifdef SDL_VIDEO_DRIVER_X11_XSYNC
X11_HandleSyncRequest(data->window, &xevent->xclient);
#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */
break;
}
} break;

Expand Down
5 changes: 5 additions & 0 deletions src/video/x11/SDL_x11framebuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include "SDL_x11video.h"
#include "SDL_x11framebuffer.h"
#include "SDL_x11xsync.h"

#ifndef NO_SHARED_MEMORY

Expand Down Expand Up @@ -216,6 +217,10 @@ bool X11_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, con
}
}

#ifdef SDL_VIDEO_DRIVER_X11_XSYNC
X11_HandlePresent(data->window);
#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */

X11_XSync(display, False);

return true;
Expand Down
3 changes: 2 additions & 1 deletion src/video/x11/SDL_x11messagebox.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,10 +459,11 @@ static bool X11_MessageBoxCreateWindow(SDL_MessageBoxDataX11 *data)
(unsigned char *)&_NET_WM_WINDOW_TYPE_DIALOG, 1);

// Allow the window to be deleted by the window manager
data->wm_protocols = X11_XInternAtom(display, "WM_PROTOCOLS", False);
data->wm_delete_message = X11_XInternAtom(display, "WM_DELETE_WINDOW", False);
X11_XSetWMProtocols(display, data->window, &data->wm_delete_message, 1);

data->wm_protocols = X11_XInternAtom(display, "WM_PROTOCOLS", False);

if (windowdata) {
XWindowAttributes attrib;
Window dummy;
Expand Down
6 changes: 6 additions & 0 deletions src/video/x11/SDL_x11opengl.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#ifdef SDL_VIDEO_DRIVER_X11

#include "SDL_x11video.h"
#include "SDL_x11xsync.h"

// GLX implementation of SDL OpenGL support

Expand Down Expand Up @@ -1089,6 +1090,11 @@ bool X11_GL_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
Display *display = data->videodata->display;

_this->gl_data->glXSwapBuffers(display, data->xwindow);

#ifdef SDL_VIDEO_DRIVER_X11_XSYNC
X11_HandlePresent(data->window);
#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */

return true;
}

Expand Down
14 changes: 13 additions & 1 deletion src/video/x11/SDL_x11opengles.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "SDL_x11video.h"
#include "SDL_x11opengles.h"
#include "SDL_x11opengl.h"
#include "SDL_x11xsync.h"

// EGL implementation of SDL OpenGL support

Expand Down Expand Up @@ -134,7 +135,18 @@ SDL_EGLSurface X11_GLES_GetEGLSurface(SDL_VideoDevice *_this, SDL_Window *window
return data->egl_surface;
}

SDL_EGL_SwapWindow_impl(X11)
bool X11_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
const bool ret = SDL_EGL_SwapBuffers(_this, window->internal->egl_surface); \

#ifdef SDL_VIDEO_DRIVER_X11_XSYNC
X11_HandlePresent(window);
#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */

return ret;
}

SDL_EGL_MakeCurrent_impl(X11)

#endif // SDL_VIDEO_DRIVER_X11 && SDL_VIDEO_OPENGL_EGL

9 changes: 9 additions & 0 deletions src/video/x11/SDL_x11sym.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,15 @@ SDL_X11_SYM(Status, XFixesQueryVersion,(Display* a, int* b, int* c), (a,b,c), re
SDL_X11_SYM(Status, XFixesSelectSelectionInput, (Display* a, Window b, Atom c, unsigned long d), (a,b,c,d), return)
#endif

#ifdef SDL_VIDEO_DRIVER_X11_XSYNC
SDL_X11_MODULE(XSYNC)
SDL_X11_SYM(Status, XSyncQueryExtension, (Display* a, int* b, int* c), (a, b, c), return)
SDL_X11_SYM(Status, XSyncInitialize, (Display* a, int* b, int* c), (a, b, c), return)
SDL_X11_SYM(XSyncCounter, XSyncCreateCounter, (Display* a, XSyncValue b), (a, b), return)
SDL_X11_SYM(Status, XSyncDestroyCounter, (Display* a, XSyncCounter b), (a, b), return)
SDL_X11_SYM(Status, XSyncSetCounter, (Display* a, XSyncCounter b, XSyncValue c), (a, b, c), return)
#endif

#ifdef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
SDL_X11_SYM(Bool,XGetEventData,(Display* a,XGenericEventCookie* b),(a,b),return)
SDL_X11_SYM(void,XFreeEventData,(Display* a,XGenericEventCookie* b),(a,b),)
Expand Down
7 changes: 7 additions & 0 deletions src/video/x11/SDL_x11video.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "SDL_x11xinput2.h"
#include "SDL_x11messagebox.h"
#include "SDL_x11shape.h"
#include "SDL_x11xsync.h"

#ifdef SDL_VIDEO_OPENGL_EGL
#include "SDL_x11opengles.h"
Expand Down Expand Up @@ -377,6 +378,8 @@ static bool X11_VideoInit(SDL_VideoDevice *_this)
GET_ATOM(_NET_WM_ICON_NAME);
GET_ATOM(_NET_WM_ICON);
GET_ATOM(_NET_WM_PING);
GET_ATOM(_NET_WM_SYNC_REQUEST);
GET_ATOM(_NET_WM_SYNC_REQUEST_COUNTER);
GET_ATOM(_NET_WM_WINDOW_OPACITY);
GET_ATOM(_NET_WM_USER_TIME);
GET_ATOM(_NET_ACTIVE_WINDOW);
Expand Down Expand Up @@ -420,6 +423,10 @@ static bool X11_VideoInit(SDL_VideoDevice *_this)

X11_InitXsettings(_this);

#ifdef SDL_VIDEO_DRIVER_X11_XSYNC
X11_InitXsync(_this);
#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */

#ifndef X_HAVE_UTF8_STRING
#warning X server does not support UTF8_STRING, a feature introduced in 2000! This is likely to become a hard error in a future libSDL3.
#endif
Expand Down
2 changes: 2 additions & 0 deletions src/video/x11/SDL_x11video.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ struct SDL_VideoData
Atom _NET_WM_ICON_NAME;
Atom _NET_WM_ICON;
Atom _NET_WM_PING;
Atom _NET_WM_SYNC_REQUEST;
Atom _NET_WM_SYNC_REQUEST_COUNTER;
Atom _NET_WM_WINDOW_OPACITY;
Atom _NET_WM_USER_TIME;
Atom _NET_ACTIVE_WINDOW;
Expand Down
22 changes: 21 additions & 1 deletion src/video/x11/SDL_x11window.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#include "SDL_x11opengles.h"
#endif

#include "SDL_x11xsync.h"

#define _NET_WM_STATE_REMOVE 0l
#define _NET_WM_STATE_ADD 1l

Expand Down Expand Up @@ -509,6 +511,7 @@ bool X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properties
}

const bool force_override_redirect = SDL_GetHintBoolean(SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT, false);
const bool use_resize_sync = (window->flags & SDL_WINDOW_VULKAN); /* doesn't work well with Vulkan */
SDL_WindowData *windowdata;
Display *display = data->display;
int screen = displaydata->screen;
Expand Down Expand Up @@ -770,7 +773,7 @@ bool X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properties
}

{
Atom protocols[3];
Atom protocols[4];
int proto_count = 0;

protocols[proto_count++] = data->atoms.WM_DELETE_WINDOW; // Allow window to be deleted by the WM
Expand All @@ -781,6 +784,12 @@ bool X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properties
protocols[proto_count++] = data->atoms._NET_WM_PING; // Respond so WM knows we're alive
}

#ifdef SDL_VIDEO_DRIVER_X11_XSYNC
if (use_resize_sync) {
protocols[proto_count++] = data->atoms._NET_WM_SYNC_REQUEST; /* Respond after completing resize */
}
#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */

SDL_assert(proto_count <= sizeof(protocols) / sizeof(protocols[0]));

X11_XSetWMProtocols(display, w, protocols, proto_count);
Expand All @@ -801,6 +810,12 @@ bool X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properties
windowdata->fullscreen_borders_forced_on = !!(window->pending_flags & SDL_WINDOW_FULLSCREEN) &&
!!(window->flags & SDL_WINDOW_BORDERLESS);

#ifdef SDL_VIDEO_DRIVER_X11_XSYNC
if (use_resize_sync) {
X11_InitResizeSync(window);
}
#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */

#if defined(SDL_VIDEO_OPENGL_ES) || defined(SDL_VIDEO_OPENGL_ES2) || defined(SDL_VIDEO_OPENGL_EGL)
if ((window->flags & SDL_WINDOW_OPENGL) &&
((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) ||
Expand Down Expand Up @@ -1976,6 +1991,11 @@ void X11_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
X11_XDestroyIC(data->ic);
}
#endif

#ifdef SDL_VIDEO_DRIVER_X11_XSYNC
X11_TermResizeSync(window);
#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */

if (!(window->flags & SDL_WINDOW_EXTERNAL)) {
X11_XDestroyWindow(display, data->xwindow);
X11_XFlush(display);
Expand Down
6 changes: 6 additions & 0 deletions src/video/x11/SDL_x11window.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ struct SDL_WindowData
PointerBarrier barrier[4];
SDL_Rect barrier_rect;
#endif // SDL_VIDEO_DRIVER_X11_XFIXES
#ifdef SDL_VIDEO_DRIVER_X11_XSYNC
XSyncCounter resize_counter;
XSyncValue resize_id;
bool resize_in_progress;
#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */

SDL_Rect expected;
SDL_DisplayMode requested_fullscreen_mode;

Expand Down
Loading

0 comments on commit 123306b

Please sign in to comment.