1706f2543Smrg/* 2706f2543Smrg * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. 3706f2543Smrg * 4706f2543Smrg * All Rights Reserved. 5706f2543Smrg * 6706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining 7706f2543Smrg * a copy of this software and associated documentation files (the 8706f2543Smrg * "Software"), to deal in the Software without restriction, including 9706f2543Smrg * without limitation on the rights to use, copy, modify, merge, 10706f2543Smrg * publish, distribute, sublicense, and/or sell copies of the Software, 11706f2543Smrg * and to permit persons to whom the Software is furnished to do so, 12706f2543Smrg * subject to the following conditions: 13706f2543Smrg * 14706f2543Smrg * The above copyright notice and this permission notice (including the 15706f2543Smrg * next paragraph) shall be included in all copies or substantial 16706f2543Smrg * portions of the Software. 17706f2543Smrg * 18706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19706f2543Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20706f2543Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21706f2543Smrg * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS 22706f2543Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23706f2543Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24706f2543Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25706f2543Smrg * SOFTWARE. 26706f2543Smrg */ 27706f2543Smrg 28706f2543Smrg/* 29706f2543Smrg * Author: 30706f2543Smrg * Rickard E. (Rik) Faith <faith@redhat.com> 31706f2543Smrg * 32706f2543Smrg */ 33706f2543Smrg 34706f2543Smrg/** \file 35706f2543Smrg * Provides DPMS support and unifies all DPMS and other screen-saver 36706f2543Smrg * support in one file. If -dpms is given on the command line, or the 37706f2543Smrg * Xdmx server is not compiled with DPMS support, then the DPMS extension 38706f2543Smrg * does not work for clients, but DPMS on the backends is still disables 39706f2543Smrg * (and restored at Xdmx server shutdown time). 40706f2543Smrg */ 41706f2543Smrg 42706f2543Smrg#ifdef HAVE_DMX_CONFIG_H 43706f2543Smrg#include <dmx-config.h> 44706f2543Smrg#endif 45706f2543Smrg 46706f2543Smrg#include "dmx.h" 47706f2543Smrg#include "dmxdpms.h" 48706f2543Smrg#include "dmxlog.h" 49706f2543Smrg#include "dmxsync.h" 50706f2543Smrg#ifdef DPMSExtension 51706f2543Smrg#include "dpmsproc.h" 52706f2543Smrg#endif 53706f2543Smrg#include "windowstr.h" /* For screenIsSaved */ 54706f2543Smrg#include <X11/extensions/dpms.h> 55706f2543Smrg 56706f2543Smrgstatic unsigned long dpmsGeneration = 0; 57706f2543Smrgstatic Bool dpmsSupported = TRUE; 58706f2543Smrg 59706f2543Smrgstatic void _dmxDPMSInit(DMXScreenInfo *dmxScreen) 60706f2543Smrg{ 61706f2543Smrg int event_base, error_base; 62706f2543Smrg int major, minor; 63706f2543Smrg CARD16 level, standby, suspend, off; 64706f2543Smrg BOOL state; 65706f2543Smrg const char *monitor; 66706f2543Smrg 67706f2543Smrg if (dpmsGeneration != serverGeneration) { 68706f2543Smrg dpmsSupported = TRUE; /* On unless a backend doesn't support it */ 69706f2543Smrg dpmsGeneration = serverGeneration; 70706f2543Smrg } 71706f2543Smrg 72706f2543Smrg#ifdef DPMSExtension 73706f2543Smrg if (DPMSDisabledSwitch) dpmsSupported = FALSE; /* -dpms turns off */ 74706f2543Smrg#endif 75706f2543Smrg 76706f2543Smrg dmxScreen->dpmsCapable = 0; 77706f2543Smrg 78706f2543Smrg if (!dmxScreen->beDisplay) { 79706f2543Smrg dmxLogOutput(dmxScreen, 80706f2543Smrg "Cannot determine if DPMS supported (detached screen)\n"); 81706f2543Smrg dpmsSupported = FALSE; 82706f2543Smrg return; 83706f2543Smrg } 84706f2543Smrg 85706f2543Smrg if (!DPMSQueryExtension(dmxScreen->beDisplay, 86706f2543Smrg &event_base, &error_base)) { 87706f2543Smrg dmxLogOutput(dmxScreen, "DPMS not supported\n"); 88706f2543Smrg dpmsSupported = FALSE; 89706f2543Smrg return; 90706f2543Smrg } 91706f2543Smrg if (!DPMSGetVersion(dmxScreen->beDisplay, &major, &minor)) { 92706f2543Smrg dmxLogOutput(dmxScreen, "DPMS not supported\n"); 93706f2543Smrg dpmsSupported = FALSE; 94706f2543Smrg return; 95706f2543Smrg } 96706f2543Smrg if (!DPMSCapable(dmxScreen->beDisplay)) { 97706f2543Smrg dmxLogOutput(dmxScreen, "DPMS %d.%d (not DPMS capable)\n", 98706f2543Smrg major, minor); 99706f2543Smrg dpmsSupported = FALSE; 100706f2543Smrg return; 101706f2543Smrg } 102706f2543Smrg 103706f2543Smrg DPMSInfo(dmxScreen->beDisplay, &level, &state); 104706f2543Smrg DPMSGetTimeouts(dmxScreen->beDisplay, &standby, &suspend, &off); 105706f2543Smrg DPMSSetTimeouts(dmxScreen->beDisplay, 0, 0, 0); 106706f2543Smrg DPMSEnable(dmxScreen->beDisplay); 107706f2543Smrg DPMSForceLevel(dmxScreen->beDisplay, DPMSModeOn); 108706f2543Smrg dmxScreen->dpmsCapable = 1; 109706f2543Smrg dmxScreen->dpmsEnabled = !!state; 110706f2543Smrg dmxScreen->dpmsStandby = standby; 111706f2543Smrg dmxScreen->dpmsSuspend = suspend; 112706f2543Smrg dmxScreen->dpmsOff = off; 113706f2543Smrg 114706f2543Smrg switch (level) { 115706f2543Smrg case DPMSModeOn: monitor = "on"; break; 116706f2543Smrg case DPMSModeStandby: monitor = "standby"; break; 117706f2543Smrg case DPMSModeSuspend: monitor = "suspend"; break; 118706f2543Smrg case DPMSModeOff: monitor = "off"; break; 119706f2543Smrg default: monitor = "unknown"; break; 120706f2543Smrg } 121706f2543Smrg 122706f2543Smrg dmxLogOutput(dmxScreen, 123706f2543Smrg "DPMS %d.%d (%s, %s, %d %d %d)\n", 124706f2543Smrg major, minor, monitor, state ? "enabled" : "disabled", 125706f2543Smrg standby, suspend, off); 126706f2543Smrg} 127706f2543Smrg 128706f2543Smrg/** Initialize DPMS support. We save the current settings and turn off 129706f2543Smrg * DPMS. The settings are restored in #dmxDPMSTerm. */ 130706f2543Smrgvoid dmxDPMSInit(DMXScreenInfo *dmxScreen) 131706f2543Smrg{ 132706f2543Smrg int interval, preferBlanking, allowExposures; 133706f2543Smrg 134706f2543Smrg /* Turn off DPMS */ 135706f2543Smrg _dmxDPMSInit(dmxScreen); 136706f2543Smrg 137706f2543Smrg if (!dmxScreen->beDisplay) 138706f2543Smrg return; 139706f2543Smrg 140706f2543Smrg /* Turn off screen saver */ 141706f2543Smrg XGetScreenSaver(dmxScreen->beDisplay, &dmxScreen->savedTimeout, &interval, 142706f2543Smrg &preferBlanking, &allowExposures); 143706f2543Smrg XSetScreenSaver(dmxScreen->beDisplay, 0, interval, 144706f2543Smrg preferBlanking, allowExposures); 145706f2543Smrg XResetScreenSaver(dmxScreen->beDisplay); 146706f2543Smrg dmxSync(dmxScreen, FALSE); 147706f2543Smrg} 148706f2543Smrg 149706f2543Smrg/** Terminate DPMS support on \a dmxScreen. We restore the settings 150706f2543Smrg * saved in #dmxDPMSInit. */ 151706f2543Smrgvoid dmxDPMSTerm(DMXScreenInfo *dmxScreen) 152706f2543Smrg{ 153706f2543Smrg int timeout, interval, preferBlanking, allowExposures; 154706f2543Smrg 155706f2543Smrg if (!dmxScreen->beDisplay) 156706f2543Smrg return; 157706f2543Smrg 158706f2543Smrg XGetScreenSaver(dmxScreen->beDisplay, &timeout, &interval, 159706f2543Smrg &preferBlanking, &allowExposures); 160706f2543Smrg XSetScreenSaver(dmxScreen->beDisplay, dmxScreen->savedTimeout, interval, 161706f2543Smrg preferBlanking, allowExposures); 162706f2543Smrg if (dmxScreen->dpmsCapable) { 163706f2543Smrg /* Restore saved state */ 164706f2543Smrg DPMSForceLevel(dmxScreen->beDisplay, DPMSModeOn); 165706f2543Smrg DPMSSetTimeouts(dmxScreen->beDisplay, dmxScreen->dpmsStandby, 166706f2543Smrg dmxScreen->dpmsSuspend, dmxScreen->dpmsOff); 167706f2543Smrg if (dmxScreen->dpmsEnabled) DPMSEnable(dmxScreen->beDisplay); 168706f2543Smrg else DPMSDisable(dmxScreen->beDisplay); 169706f2543Smrg } 170706f2543Smrg dmxSync(dmxScreen, FALSE); 171706f2543Smrg} 172706f2543Smrg 173706f2543Smrg/** Called when activity is detected so that DPMS power-saving mode can 174706f2543Smrg * be deactivated. */ 175706f2543Smrgvoid dmxDPMSWakeup(void) 176706f2543Smrg{ 177706f2543Smrg if (screenIsSaved == SCREEN_SAVER_ON) 178706f2543Smrg dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); 179706f2543Smrg#ifdef DPMSExtension 180706f2543Smrg if (DPMSPowerLevel) DPMSSet(serverClient, 0); 181706f2543Smrg#endif 182706f2543Smrg} 183706f2543Smrg 184706f2543Smrg#ifdef DPMSExtension 185706f2543Smrg/** This is called on each server generation. It should determine if 186706f2543Smrg * DPMS is supported on all of the backends and, if so, return TRUE. */ 187706f2543SmrgBool DPMSSupported(void) 188706f2543Smrg{ 189706f2543Smrg return dpmsSupported; 190706f2543Smrg} 191706f2543Smrg 192706f2543Smrg/** This is used by clients (e.g., xset) to set the DPMS level. */ 193706f2543Smrgint DPMSSet(ClientPtr client, int level) 194706f2543Smrg{ 195706f2543Smrg int i; 196706f2543Smrg 197706f2543Smrg if (!dpmsSupported) return Success; 198706f2543Smrg 199706f2543Smrg if (level < 0) level = DPMSModeOn; 200706f2543Smrg if (level > 3) level = DPMSModeOff; 201706f2543Smrg 202706f2543Smrg DPMSPowerLevel = level; 203706f2543Smrg 204706f2543Smrg for (i = 0; i < dmxNumScreens; i++) { 205706f2543Smrg DMXScreenInfo *dmxScreen = &dmxScreens[i]; 206706f2543Smrg if (dmxScreen->beDisplay) { 207706f2543Smrg DPMSForceLevel(dmxScreen->beDisplay, level); 208706f2543Smrg dmxSync(dmxScreen, FALSE); 209706f2543Smrg } 210706f2543Smrg } 211706f2543Smrg return Success; 212706f2543Smrg} 213706f2543Smrg#endif 214