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