summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--tools/virtual.c113
2 files changed, 109 insertions, 6 deletions
diff --git a/configure.ac b/configure.ac
index 9aa7d977..c18ad96c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -291,7 +291,7 @@ if test "x$shm" != "xyes"; then
tools="no"
fi
if test "x$tools" != "xno"; then
- ivo_requires="xrandr xdamage xfixes xcursor xtst xrender xext x11 pixman-1"
+ ivo_requires="xrandr xdamage xfixes xcursor xtst xrender xscrnsaver xext x11 pixman-1"
extra_cflags=""
ignore="xinerama"
diff --git a/tools/virtual.c b/tools/virtual.c
index 7bf6ee8d..bcbcb425 100644
--- a/tools/virtual.c
+++ b/tools/virtual.c
@@ -31,6 +31,7 @@
#include <X11/Xlibint.h>
#include <X11/extensions/record.h>
+#include <X11/extensions/scrnsaver.h>
#include <X11/extensions/XShm.h>
#if HAVE_X11_EXTENSIONS_SHMPROTO_H
#include <X11/extensions/shmproto.h>
@@ -79,13 +80,15 @@ static int verbose;
#define DRAW 0x8
#define DAMAGE 0x10
#define CURSOR 0x20
-#define POLL 0x40
+#define SCREEN 0x40
+#define POLL 0x80
struct display {
Display *dpy;
struct clone *clone;
struct context *ctx;
+ int saver_event, saver_error, saver_active;
int damage_event, damage_error;
int xfixes_event, xfixes_error;
int rr_event, rr_error, rr_active;
@@ -98,6 +101,7 @@ struct display {
int width;
int height;
int depth;
+ int active;
XRenderPictFormat *root_format;
XRenderPictFormat *rgb16_format;
@@ -123,6 +127,13 @@ struct display {
int send;
int skip_clone;
int skip_frame;
+
+ struct {
+ int timeout;
+ int interval;
+ int prefer_blank;
+ int allow_exp;
+ } saver;
};
struct output {
@@ -1249,6 +1260,56 @@ static void clone_update(struct clone *clone)
clone->rr_update = 0;
}
+static void screensaver_save(struct display *display)
+{
+ display->saver_active =
+ XScreenSaverQueryExtension(display->dpy,
+ &display->saver_event,
+ &display->saver_error);
+ DBG(SCREEN,
+ ("%s screen saver active? %d [event=%d, error=%d]\n",
+ DisplayString(display->dpy),
+ display->saver_active,
+ display->saver_event,
+ display->saver_error));
+
+ XGetScreenSaver(display->dpy,
+ &display->saver.timeout,
+ &display->saver.interval,
+ &display->saver.prefer_blank,
+ &display->saver.allow_exp);
+
+ DBG(SCREEN,
+ ("%s saving screen saver defaults: timeout=%d interval=%d prefer_blank=%d allow_exp=%d\n",
+ DisplayString(display->dpy),
+ display->saver.timeout,
+ display->saver.interval,
+ display->saver.prefer_blank,
+ display->saver.allow_exp));
+}
+
+static void screensaver_disable(struct display *display)
+{
+ DBG(SCREEN,
+ ("%s disabling screen saver\n", DisplayString(display->dpy)));
+
+ XSetScreenSaver(display->dpy, 0, 0, DefaultBlanking, DefaultExposures);
+ display_mark_flush(display);
+}
+
+static void screensaver_restore(struct display *display)
+{
+ DBG(SCREEN,
+ ("%s restoring screen saver\n", DisplayString(display->dpy)));
+
+ XSetScreenSaver(display->dpy,
+ display->saver.timeout,
+ display->saver.interval,
+ display->saver.prefer_blank,
+ display->saver.allow_exp);
+ display_mark_flush(display);
+}
+
static int context_update(struct context *ctx)
{
Display *dpy = ctx->display->dpy;
@@ -1605,6 +1666,13 @@ ungrab:
XUngrabServer(display->dpy);
}
+ for (n = 1; n < ctx->ndisplay; n++) {
+ struct display *display = &ctx->display[n];
+
+ display->active = 0;
+ screensaver_restore(display);
+ }
+
ctx->active = NULL;
for (n = 0; n < ctx->nclone; n++) {
struct clone *clone = &ctx->clones[n];
@@ -1615,7 +1683,10 @@ ungrab:
continue;
DBG(XRR, ("%s-%s: added to active list\n",
- DisplayString(clone->dst.display->dpy), clone->dst.name));
+ DisplayString(clone->dst.display->dpy), clone->dst.name));
+
+ if (clone->dst.display->active++ == 0)
+ screensaver_disable(clone->dst.display);
clone->active = ctx->active;
ctx->active = clone;
@@ -2396,6 +2467,8 @@ static int add_display(struct context *ctx, Display *dpy)
display->shm_opcode,
display->has_shm_pixmap));
+ screensaver_save(display);
+
display->rr_active = XRRQueryExtension(dpy, &display->rr_event, &display->rr_error);
DBG(X11, ("%s: randr_active?=%d, event=%d, error=%d\n",
DisplayString(dpy),
@@ -3400,6 +3473,11 @@ int main(int argc, char **argv)
if (ret)
goto out;
+ if (ctx.display->saver_active)
+ XScreenSaverSelectInput(ctx.display->dpy,
+ ctx.display->root,
+ ScreenSaverNotifyMask);
+
if ((ctx.display->rr_event | ctx.display->rr_error) == 0) {
fprintf(stderr, "RandR extension not supported by %s\n", DisplayString(ctx.display->dpy));
ret = EINVAL;
@@ -3476,7 +3554,32 @@ int main(int argc, char **argv)
do {
XNextEvent(ctx.display->dpy, &e);
- if (e.type == ctx.display->damage_event + XDamageNotify ) {
+ DBG(POLL, ("%s received event %d\n", DisplayString(ctx.display[0].dpy), e.type));
+
+ if (e.type == ctx.display->saver_event + ScreenSaverNotify) {
+ const XScreenSaverNotifyEvent *se = (const XScreenSaverNotifyEvent *)&e;
+ DBG(SCREEN,
+ ("%s screen saver: state=%d, kind=%d, forced=%d\n",
+ DisplayString(ctx.display->dpy),
+ se->state, se->kind, se->forced));
+ for (i = 1; i < ctx.ndisplay; i++) {
+ struct display *display = &ctx.display[i];
+
+ if (!display->active)
+ continue;
+
+ DBG(SCREEN,
+ ("%s %s screen saver\n",
+ DisplayString(display->dpy),
+ se->state == ScreenSaverOn ? "activating" : "resetting\n"));
+
+ if (se->state == ScreenSaverOn)
+ XActivateScreenSaver(display->dpy);
+ else
+ XResetScreenSaver(display->dpy);
+ XFlush(display->dpy);
+ }
+ } else if (e.type == ctx.display->damage_event + XDamageNotify) {
const XDamageNotifyEvent *de = (const XDamageNotifyEvent *)&e;
struct clone *clone;
@@ -3530,7 +3633,7 @@ int main(int argc, char **argv)
DBG(POLL, ("%s received event %d\n", DisplayString(ctx.display[i].dpy), e.type));
if (e.type == Expose) {
- XExposeEvent *xe = (XExposeEvent *)&e;
+ const XExposeEvent *xe = (XExposeEvent *)&e;
struct clone *clone;
int damaged = 0;
@@ -3555,7 +3658,7 @@ int main(int argc, char **argv)
if (damaged)
context_enable_timer(&ctx);
} else if (ctx.display[i].rr_active && e.type == ctx.display[i].rr_event + RRNotify) {
- XRRNotifyEvent *re = (XRRNotifyEvent *)&e;
+ const XRRNotifyEvent *re = (XRRNotifyEvent *)&e;
DBG(XRR, ("%s received RRNotify, type %d\n", DisplayString(ctx.display[i].dpy), re->subtype));
if (re->subtype == RRNotify_OutputChange) {