1/* 2 Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com> 3 All rights reserved. 4 5This file is part of x11vnc. 6 7x11vnc is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 2 of the License, or (at 10your option) any later version. 11 12x11vnc is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with x11vnc; if not, write to the Free Software 19Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA 20or see <http://www.gnu.org/licenses/>. 21 22In addition, as a special exception, Karl J. Runge 23gives permission to link the code of its release of x11vnc with the 24OpenSSL project's "OpenSSL" library (or with modified versions of it 25that use the same license as the "OpenSSL" library), and distribute 26the linked executables. You must obey the GNU General Public License 27in all respects for all of the code used other than "OpenSSL". If you 28modify this file, you may extend this exception to your version of the 29file, but you are not obligated to do so. If you do not wish to do 30so, delete this exception statement from your version. 31*/ 32 33/* -- pm.c -- */ 34#include "x11vnc.h" 35#include "cleanup.h" 36 37void check_pm(void); 38void set_dpms_mode(char *mode); 39static void check_fbpm(void); 40static 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 51void 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 67static 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 150void 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 207static 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