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