[x11] Support the XScreenSaver extension

And use it in preference to the crusty old XSetScreenSaver API. This
should work on modern systems (though might need to support the dbus
method too, but that can wait).
This commit is contained in:
Bill Currie 2025-01-12 17:58:09 +09:00
parent e9eae1c75f
commit ccd42c5c21
7 changed files with 98 additions and 36 deletions

View file

@ -35,6 +35,27 @@ if test "x$HAVE_VIDMODE" != xno; then
fi
AC_SUBST(VIDMODE_LIBS)
dnl Check for XScreenSaver support
AC_ARG_ENABLE(xi2,
AS_HELP_STRING([--disable-xss], [do not use Xorg XScreenSaver extension]),
HAVE_XSS=$enable_xi2, HAVE_XSS=auto)
if test "x$HAVE_XSS" != xno; then
save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$X_CFLAGS $CPPFLAGS"
AC_CHECK_HEADER(X11/extensions/scrnsaver.h,
dnl Make sure the library works
[AC_CHECK_LIB(Xss, XScreenSaverQueryExtension,
AC_DEFINE(HAVE_XSS, 1, [Define if you have the Xorg XScreenSaver extension])
HAVE_XSS=yes
XSS_LIBS="-lXss",,
[$X_LIBS -lXext -lX11 $X_EXTRA_LIBS]
)],,
[#include <X11/Xlib.h>]
)
CPPFLAGS="$save_CPPFLAGS"
fi
AC_SUBST(XSS_LIBS)
dnl Check for XInput2 support
AC_ARG_ENABLE(xi2,
AS_HELP_STRING([--disable-xi2], [do not use Xorg XInput2 extension]),

View file

@ -64,6 +64,7 @@ extern bool x_have_focus;
bool X11_AddEvent (int event, void (*event_handler)(XEvent *));
bool X11_RemoveEvent (int event, void (*event_handler)(XEvent *));
bool X11_SetGamma (double);
void X11_SetScreenSaver (void);
void X11_CloseDisplay (void);
void X11_CreateNullCursor (void);
void X11_CreateWindow (int, int);
@ -74,6 +75,7 @@ void X11_OpenDisplay (void);
void X11_ProcessEvent (void);
void X11_ProcessEvents (void);
void X11_RestoreGamma (void);
void X11_RestoreScreenSaver (void);
void X11_RestoreVidMode (void);
void X11_SetCaption (const char *);
void X11_SetVidMode (int, int);

View file

@ -44,18 +44,13 @@
# include <unistd.h>
#endif
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <X11/extensions/XShm.h>
#ifdef HAVE_VIDMODE
# include <X11/extensions/xf86vmode.h>
#endif
#ifdef HAVE_XSS
# include <X11/extensions/scrnsaver.h>
#endif
#include "QF/cmd.h"
#include "QF/cvar.h"
@ -78,8 +73,9 @@ bool oktodraw = false;
int x_shmeventtype;
static int x_disp_ref_count = 0;
static bool x_have_xss = false;
Display *x_disp = NULL;
Display *x_disp = nullptr;
int x_screen;
int x_width;
int x_height;
@ -99,8 +95,8 @@ static XF86VidModeModeInfo **vidmodes;
static int nummodes;
static int original_mode = 0;
static vec3_t x_gamma = {-1, -1, -1};
static bool vidmode_avail = false;
#endif
static bool vidmode_avail = false;
static bool vidmode_active = false;
@ -205,7 +201,7 @@ X11_RemoveEvent (int event, void (*event_handler) (XEvent *))
if (event_handlers[event] != event_handler)
return false;
event_handlers[event] = NULL;
event_handlers[event] = nullptr;
return true;
}
@ -252,34 +248,72 @@ X11_ProcessEvents (void)
X11_ProcessEvent ();
}
#ifdef HAVE_VIDMODE
static void
void
X11_SetScreenSaver (void)
{
XGetScreenSaver (x_disp, &xss_timeout, &xss_interval, &xss_blanking,
&xss_exposures);
XSetScreenSaver (x_disp, 0, xss_interval, xss_blanking, xss_exposures);
if (x_have_xss) {
#ifdef HAVE_XSS
XScreenSaverSuspend (x_disp, true);
#endif
} else {
#ifdef HAVE_VIDMODE
XGetScreenSaver (x_disp, &xss_timeout, &xss_interval, &xss_blanking,
&xss_exposures);
XSetScreenSaver (x_disp, 0, xss_interval, xss_blanking, xss_exposures);
#endif
}
}
void
X11_RestoreScreenSaver (void)
{
if (x_have_xss) {
#ifdef HAVE_XSS
XScreenSaverSuspend (x_disp, false);
#endif
} else {
#ifdef HAVE_VIDMODE
XSetScreenSaver (x_disp, xss_timeout, xss_interval, xss_blanking,
xss_exposures);
#endif
}
}
static void
X11_RestoreScreenSaver (void)
X11_CheckScreenSaver (void)
{
XSetScreenSaver (x_disp, xss_timeout, xss_interval, xss_blanking,
xss_exposures);
}
#ifdef HAVE_XSS
int ev_base, err_base;
int maj_ver, min_ver;
if (!XScreenSaverQueryExtension (x_disp, &ev_base, &err_base)) {
Sys_MaskPrintf (SYS_vid, "XSS not supported\n");
return;
}
if (!XScreenSaverQueryVersion (x_disp, &maj_ver, &min_ver)) {
Sys_MaskPrintf (SYS_vid, "XScreenSaver version query failed\n");
return;
}
Sys_MaskPrintf (SYS_vid, "XSS supperted: version %d.%d (ev:%d, err:%d)\n",
maj_ver, min_ver, ev_base, err_base);
x_have_xss = true;
#else
Sys_MaskPrintf (SYS_vid, "X11: XScreenSaver support not compiled in\n");
#endif
}
void
X11_OpenDisplay (void)
{
qfZoneScoped (true);
if (!x_disp) {
x_disp = XOpenDisplay (NULL);
x_disp = XOpenDisplay (nullptr);
if (!x_disp) {
Sys_Error ("X11_OpenDisplay: Could not open display [%s]",
XDisplayName (NULL));
XDisplayName (nullptr));
}
X11_CheckScreenSaver ();
x_net_state = XInternAtom (x_disp, "_NET_WM_STATE", False);
x_net_fullscreen = XInternAtom (x_disp, "_NET_WM_STATE_FULLSCREEN",
False);
@ -304,6 +338,7 @@ X11_CloseDisplay (void)
X11_RestoreVidMode ();
X11_RestoreGamma ();
X11_RestoreScreenSaver ();
if (x_nullcursor != None) {
XFreeCursor (x_disp, x_nullcursor);
@ -363,11 +398,11 @@ X11_GetGamma (void)
(*temp)[2] = xgamma.blue;
return temp;
}
return NULL;
return nullptr;
}
}
vid_gamma_avail = false;
return NULL;
return nullptr;
}
#endif
@ -393,7 +428,7 @@ X11_SetVidMode (int width, int height)
static int initialized = 0;
if (!vidmode_avail)
vidmode_avail = VID_CheckVMode (x_disp, NULL, NULL);
vidmode_avail = VID_CheckVMode (x_disp, nullptr, nullptr);
if (!initialized && vidmode_avail) {
vec3_t *temp;
@ -461,7 +496,6 @@ X11_SetVidMode (int width, int height)
vidmodes[best_mode]);
}
vidmode_active = true;
X11_SetScreenSaver ();
} else {
Sys_Printf ("VID: Mode %dx%d can't go fullscreen.\n",
viddef.width, viddef.height);
@ -569,14 +603,13 @@ X11_CreateWindow (int width, int height)
void
X11_RestoreVidMode (void)
{
#ifdef HAVE_VIDMODE
if (vidmode_active) {
X11_RestoreScreenSaver ();
#ifdef HAVE_VIDMODE
//XF86VidModeSwitchToMode (x_disp, x_screen, vidmodes[original_mode]);
XFree (vidmodes);
vidmode_active = false;
}
#endif
}
}
void

View file

@ -1143,6 +1143,7 @@ event_focusout (XEvent *event)
CDAudio_Pause ();
}
X11_RestoreGamma ();
X11_RestoreScreenSaver ();
}
}
@ -1162,6 +1163,10 @@ event_focusin (XEvent *event)
#endif
}
VID_UpdateGamma ();
// The assumption is that kb+mouse will generate enough input it doesn't
// matter, and that if the game is in focus, then assume a controller
// (which does not generate X11 events) might be in use.
X11_SetScreenSaver ();
}
static void

View file

@ -93,8 +93,8 @@ nq_x11_libs= \
$(nq_client_LIBS)
nq_x11_SOURCES= nq/source/sys_unix.c $(tracy_src) $(tracyvk_src)
nq_x11_LDADD= $(nq_x11_libs) \
$(VIDMODE_LIBS) $(DGA_LIBS) ${XFIXES_LIBS} $(XI2_LIBS) $(X_LIBS) \
-lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(DL_LIBS)
$(VIDMODE_LIBS) $(DGA_LIBS) ${XFIXES_LIBS} $(XI2_LIBS) $(XSS_LIBS) \
$(X_LIBS) -lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(DL_LIBS)
nq_x11_LDFLAGS= $(common_ldflags)
nq_x11_DEPENDENCIES= $(nq_x11_libs)

View file

@ -118,9 +118,9 @@ qw_client_x11_libs= \
$(qw_client_LIBS)
qw_client_x11_SOURCES= qw/source/cl_sys_unix.c $(tracy_src) $(tracyvk_src)
qw_client_x11_LDADD= $(qw_client_x11_libs) \
$(VIDMODE_LIBS) $(DGA_LIBS) ${XFIXES_LIBS} $(XI2_LIBS) $(X_LIBS) \
-lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(LIBCURL_LIBS) \
$(DL_LIBS)
$(VIDMODE_LIBS) $(DGA_LIBS) ${XFIXES_LIBS} $(XI2_LIBS) $(XSS_LIBS) \
$(X_LIBS) -lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) \
$(LIBCURL_LIBS) $(DL_LIBS)
qw_client_x11_LDFLAGS= $(common_ldflags)
qw_client_x11_DEPENDENCIES= $(qw_client_x11_libs)

View file

@ -124,8 +124,9 @@ ruamoko_qwaq_qwaq_x11_SOURCES= \
ruamoko/qwaq/builtins/qwaq-graphics.c \
ruamoko/qwaq/builtins/graphics.c $(tracy_src) $(tracyvk_src)
ruamoko_qwaq_qwaq_x11_LDADD= $(qwaq_x11_libs) $(QWAQ_LIBS) \
$(VIDMODE_LIBS) $(DGA_LIBS) ${XFIXES_LIBS} $(XI2_LIBS) $(X_LIBS) \
-lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) $(PTHREAD_LDFLAGS) $(DL_LIBS)
$(VIDMODE_LIBS) $(DGA_LIBS) ${XFIXES_LIBS} $(XI2_LIBS) $(XSS_LIBS)\
$(X_LIBS) -lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) $(PTHREAD_LDFLAGS) \
$(DL_LIBS)
ruamoko_qwaq_qwaq_x11_LDFLAGS=
ruamoko_qwaq_qwaq_x11_DEPENDENCIES= $(qwaq_x11_libs) $(QWAQ_DEPS)