1a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
2a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
3a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   All rights reserved.
4a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
5a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatThis file is part of x11vnc.
6a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
7a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatx11vnc is free software; you can redistribute it and/or modify
8a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatit under the terms of the GNU General Public License as published by
9a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatthe Free Software Foundation; either version 2 of the License, or (at
10a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatyour option) any later version.
11a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
12a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatx11vnc is distributed in the hope that it will be useful,
13a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatbut WITHOUT ANY WARRANTY; without even the implied warranty of
14a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatGNU General Public License for more details.
16a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
17a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatYou should have received a copy of the GNU General Public License
18a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatalong with x11vnc; if not, write to the Free Software
19a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
20a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehator see <http://www.gnu.org/licenses/>.
21a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
22a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatIn addition, as a special exception, Karl J. Runge
23a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatgives permission to link the code of its release of x11vnc with the
24a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatOpenSSL project's "OpenSSL" library (or with modified versions of it
25a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatthat use the same license as the "OpenSSL" library), and distribute
26a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatthe linked executables.  You must obey the GNU General Public License
27a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatin all respects for all of the code used other than "OpenSSL".  If you
28a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatmodify this file, you may extend this exception to your version of the
29a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatfile, but you are not obligated to do so.  If you do not wish to do
30a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatso, delete this exception statement from your version.
31a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat*/
32a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
33a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* -- pm.c -- */
34a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include "x11vnc.h"
35a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include "cleanup.h"
36a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
37a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid check_pm(void);
38a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid set_dpms_mode(char *mode);
39a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void check_fbpm(void);
40a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void check_dpms(void);
41a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
42a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if LIBVNCSERVER_HAVE_FBPM
43a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <X11/Xmd.h>
44a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <X11/extensions/fbpm.h>
45a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
46a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
47a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if LIBVNCSERVER_HAVE_DPMS
48a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <X11/extensions/dpms.h>
49a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
50a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
51a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid check_pm(void) {
52a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	static int skip = -1;
53a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (skip < 0) {
54a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		skip = 0;
55a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (getenv("X11VNC_NO_CHECK_PM")) {
56a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			skip = 1;
57a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
58a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
59a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (skip) {
60a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return;
61a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
62a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	check_fbpm();
63a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	check_dpms();
64a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	/* someday dpms activities? */
65a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
66a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
67a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void check_fbpm(void) {
68a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	static int init_fbpm = 0;
69a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if LIBVNCSERVER_HAVE_FBPM
70a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	static int fbpm_capable = 0;
71a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	static time_t last_fbpm = 0;
72a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int db = 0;
73a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
74a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	CARD16 level;
75a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	BOOL enabled;
76a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
77a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	RAWFB_RET_VOID
78a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
79a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! init_fbpm) {
80a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (getenv("FBPM_DEBUG")) {
81a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			db = atoi(getenv("FBPM_DEBUG"));
82a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
83a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (FBPMCapable(dpy)) {
84a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			fbpm_capable = 1;
85a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbLog("X display is capable of FBPM.\n");
86a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if (watch_fbpm) {
87a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				rfbLog("Preventing low-power FBPM modes when"
88a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				    " clients are connected.\n");
89a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
90a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else {
91a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if (! raw_fb_str) {
92a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				rfbLog("X display is not capable of FBPM.\n");
93a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
94a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			fbpm_capable = 0;
95a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
96a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		init_fbpm = 1;
97a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
98a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
99a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! watch_fbpm) {
100a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return;
101a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
102a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! fbpm_capable) {
103a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return;
104a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
105a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! client_count) {
106a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return;
107a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
108a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (time(NULL) < last_fbpm + 5) {
109a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return;
110a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
111a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	last_fbpm = time(NULL);
112a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
113a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (FBPMInfo(dpy, &level, &enabled)) {
114a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (db) fprintf(stderr, "FBPMInfo level: %d enabled: %d\n", level, enabled);
115a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
116a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (enabled && level != FBPMModeOn) {
117a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			char *from = "unknown-fbpm-state";
118a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			XErrorHandler old_handler = XSetErrorHandler(trap_xerror);
119a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			trapped_xerror = 0;
120a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
121a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if (level == FBPMModeStandby) {
122a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				from = "FBPMModeStandby";
123a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			} else if (level == FBPMModeSuspend) {
124a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				from = "FBPMModeSuspend";
125a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			} else if (level == FBPMModeOff) {
126a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				from = "FBPMModeOff";
127a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
128a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
129a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbLog("switching FBPM state from %s to FBPMModeOn\n", from);
130a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
131a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			FBPMForceLevel(dpy, FBPMModeOn);
132a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
133a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			XSetErrorHandler(old_handler);
134a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			trapped_xerror = 0;
135a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
136a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	} else {
137a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (db) fprintf(stderr, "FBPMInfo failed.\n");
138a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
139a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
140a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	RAWFB_RET_VOID
141a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! init_fbpm) {
142a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (! raw_fb_str) {
143a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbLog("X FBPM extension not supported.\n");
144a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
145a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		init_fbpm = 1;
146a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
147a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
148a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
149a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
150a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid set_dpms_mode(char *mode) {
151a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if NO_X11
152a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return;
153a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
154a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	RAWFB_RET_VOID
155a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if LIBVNCSERVER_HAVE_DPMS
156a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (dpy && DPMSCapable(dpy)) {
157a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		CARD16 level;
158a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		CARD16 want;
159a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		BOOL enabled;
160a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (!strcmp(mode, "off")) {
161a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			want = DPMSModeOff;
162a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else if (!strcmp(mode, "on")) {
163a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			want = DPMSModeOn;
164a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else if (!strcmp(mode, "standby")) {
165a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			want = DPMSModeStandby;
166a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else if (!strcmp(mode, "suspend")) {
167a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			want = DPMSModeSuspend;
168a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else if (!strcmp(mode, "enable")) {
169a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			DPMSEnable(dpy);
170a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			return;
171a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else if (!strcmp(mode, "disable")) {
172a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			DPMSDisable(dpy);
173a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			return;
174a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else {
175a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			return;
176a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
177a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (DPMSInfo(dpy, &level, &enabled)) {
178a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			char *from = "unk";
179a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if (enabled && level != want) {
180a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				XErrorHandler old_handler = XSetErrorHandler(trap_xerror);
181a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				trapped_xerror = 0;
182a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
183a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				rfbLog("DPMSInfo level: %d enabled: %d\n", level, enabled);
184a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if (level == DPMSModeStandby) {
185a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					from = "DPMSModeStandby";
186a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				} else if (level == DPMSModeSuspend) {
187a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					from = "DPMSModeSuspend";
188a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				} else if (level == DPMSModeOff) {
189a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					from = "DPMSModeOff";
190a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				} else if (level == DPMSModeOn) {
191a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					from = "DPMSModeOn";
192a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
193a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
194a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				rfbLog("switching DPMS state from %s to %s\n", from, mode);
195a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
196a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				DPMSForceLevel(dpy, want);
197a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
198a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				XSetErrorHandler(old_handler);
199a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				trapped_xerror = 0;
200a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
201a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
202a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
203a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
204a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
205a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
206a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
207a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void check_dpms(void) {
208a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	static int init_dpms = 0;
209a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if LIBVNCSERVER_HAVE_DPMS
210a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	static int dpms_capable = 0;
211a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	static time_t last_dpms = 0;
212a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int db = 0;
213a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
214a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	CARD16 level;
215a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	BOOL enabled;
216a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
217a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	RAWFB_RET_VOID
218a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
219a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! init_dpms) {
220a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (getenv("DPMS_DEBUG")) {
221a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			db = atoi(getenv("DPMS_DEBUG"));
222a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
223a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (DPMSCapable(dpy)) {
224a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			dpms_capable = 1;
225a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbLog("X display is capable of DPMS.\n");
226a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if (watch_dpms) {
227a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				rfbLog("Preventing low-power DPMS modes when"
228a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				    " clients are connected.\n");
229a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
230a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else {
231a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if (! raw_fb_str) {
232a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				rfbLog("X display is not capable of DPMS.\n");
233a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
234a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			dpms_capable = 0;
235a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
236a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		init_dpms = 1;
237a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
238a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
239a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (force_dpms || (client_dpms && client_count)) {
240a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		static int last_enable = 0;
241a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (time(NULL) > last_enable) {
242a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			set_dpms_mode("enable");
243a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			last_enable = time(NULL);
244a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
245a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		set_dpms_mode("off");
246a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
247a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! watch_dpms) {
248a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return;
249a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
250a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! dpms_capable) {
251a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return;
252a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
253a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! client_count) {
254a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return;
255a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
256a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (time(NULL) < last_dpms + 5) {
257a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return;
258a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
259a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	last_dpms = time(NULL);
260a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
261a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (DPMSInfo(dpy, &level, &enabled)) {
262a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (db) fprintf(stderr, "DPMSInfo level: %d enabled: %d\n", level, enabled);
263a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
264a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (enabled && level != DPMSModeOn) {
265a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			char *from = "unknown-dpms-state";
266a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			XErrorHandler old_handler = XSetErrorHandler(trap_xerror);
267a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			trapped_xerror = 0;
268a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
269a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if (level == DPMSModeStandby) {
270a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				from = "DPMSModeStandby";
271a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			} else if (level == DPMSModeSuspend) {
272a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				from = "DPMSModeSuspend";
273a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			} else if (level == DPMSModeOff) {
274a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				from = "DPMSModeOff";
275a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
276a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
277a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbLog("switching DPMS state from %s to DPMSModeOn\n", from);
278a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
279a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			DPMSForceLevel(dpy, DPMSModeOn);
280a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
281a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			XSetErrorHandler(old_handler);
282a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			trapped_xerror = 0;
283a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
284a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	} else {
285a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (db) fprintf(stderr, "DPMSInfo failed.\n");
286a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
287a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
288a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	RAWFB_RET_VOID
289a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! init_dpms) {
290a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (! raw_fb_str) {
291a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbLog("X DPMS extension not supported.\n");
292a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
293a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		init_dpms = 1;
294a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
295a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
296a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
297a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
298