SDL tampers with display power settings on the sly

SDL tampers with the power management settings of my display on the sly.
After running an SDL program, the display never turns off. It should turn
off after a minute of inactivity. I have to go to
kcontrol->peripherals->display->powersave, change something, change it
back and press Apply. Then the power management is restored.

So I have to keep a kcontrol instance open all the time and do that
after running an SDL program. This is annoying, but it was much worse
before I knew
that it was SDL programs that caused it.

To reproduce:

  1. Wait a minute until the display turns off, to check that the power
    management is working properly.
  2. Build and run any SDL program, such as the attached testcase (gcc
    -Wall -Wextra -I/usr/include/SDL prov.c -lSDL -o prov&&./prov).
  3. Wait a minute to see that the power management has stopped working.
  4. Switch to kcontrol->peripherals->display->powersave, change some
    setting, change it back and press Apply.
  5. Wait a minute to see that the power management works again.

The power management stops working when the SDL program is started and
remains dysfunctional even after the SDL-program has been closed.

Some system information:

  • Dell INSPIRON | 8600 (laptop)
  • VGA compatible controller: ATI Technologies Inc RV350 [Mobility Radeon
    9600 M10]
  • Linux 2.6.23-gentoo-r8 Intel® Pentium® M processor 1.60GHz
  • [ebuild R ] x11-base/xorg-server-1.3.0.0-r5 USE="dri ipv6 nptl
    sdl xorg -3dfx -debug -dmx -kdrive -minimal -xprint"
    INPUT_DEVICES="keyboard mouse -acecad -aiptek -calcomp -citron
    -digitaledge -dmc -dynapro -elo2300 -elographics -evdev -fpit -hyperpen
    -jamstudio -joystick -magellan -microtouch -mutouch -palmax -penmount
    -spaceorb -summa -synaptics -tek4957 -ur98 -vmmouse -void -wacom"
    VIDEO_CARDS=“radeon -apm -ark -chips -cirrus -cyrix -dummy -epson -fbdev
    -fglrx -glint -i128 -i740 -i810 (-impact) -imstt -mach64 -mga -neomagic
    (-newport) -nsc -nv -nvidia -r128 -rendition -s3 -s3virge -savage
    -siliconmotion -sis -sisusb (-sunbw2) (-suncg14) (-suncg3) (-suncg6)
    (-sunffb) (-sunleo) (-suntcx) -tdfx -tga -trident -tseng -v4l -vesa -vga
    -via -vmware -voodoo” 0 kB
  • [ebuild R ] media-libs/libsdl-1.2.11-r2 USE=“X alsa arts dga
    directfb fbcon ggi opengl xinerama xv -aalib -custom-cflags -esd
    -libcaca -nas -noaudio -nojoystick -novideo -oss -svga” 0 kB
  • [ebuild R ] kde-base/kcontrol-3.5.8-r2 USE=“arts kdeenablefinal
    kdehiddenvisibility opengl xinerama -debug -ieee1394 -joystick
    -logitech-mouse” 0 kB
    -------------- next part --------------
    A non-text attachment was scrubbed…
    Name: prov.c
    Type: text/x-csrc
    Size: 646 bytes
    Desc: not available
    URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20080223/8b0a8e3b/attachment.c

SDL tampers with the power management settings of my display on the sly.
After running an SDL program, the display never turns off. It should turn
off after a minute of inactivity. I have to go to
kcontrol->peripherals->display->powersave, change something, change it
back and press Apply. Then the power management is restored.

Disabling the screensaver for X11 was introduced in SDL 1.2.10 and is
setup in the src/video/x11/SDL_x11video.c and
src/video/x11/SDL_x11events.c files. You can stop the disabling of
screensaver by setting the SDL_VIDEO_ALLOW_SCREENSAVER environment
variable added in SDL 1.2.12.

However the problem you are noticing I have observed too, the
screensaver was not being restored after exiting any SDL program.
The SDL code all looks fine so I’d wondered if it was the programs fault
not exiting cleanly.

So I have to keep a kcontrol instance open all the time and do that
after running an SDL program. This is annoying, but it was much worse
before I knew that it was SDL programs that caused it.

To reproduce:

  1. Wait a minute until the display turns off, to check that the power
    management is working properly.

You can use “xset q” to check the screensaver settings.

  1. Build and run any SDL program, such as the attached testcase (gcc
    -Wall -Wextra -I/usr/include/SDL prov.c -lSDL -o prov&&./prov).
  2. Wait a minute to see that the power management has stopped working.
  3. Switch to kcontrol->peripherals->display->powersave, change some
    setting, change it back and press Apply.
  4. Wait a minute to see that the power management works again.

The power management stops working when the SDL program is started and
remains dysfunctional even after the SDL-program has been closed.

Oddly it’s all working fine at the moment both for test program and real
programs. Will need to retest but I wonder if it was driver issue. I’ve
updated to the current xf86-video-ati Git today.On Sat, 2008-02-23 at 04:22 +0100, Erik wrote:


Alan.

“One must never be purposelessnessnesslessness.”
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20080224/ed90e4da/attachment.pgp

Alan Swanson skrev:

SDL tampers with the power management settings of my display on the sly.
After running an SDL program, the display never turns off. It should turn
off after a minute of inactivity. I have to go to
kcontrol->peripherals->display->powersave, change something, change it
back and press Apply. Then the power management is restored.

Disabling the screensaver for X11 was introduced in SDL 1.2.10 and is
setup in the src/video/x11/SDL_x11video.c and
src/video/x11/SDL_x11events.c files. You can stop the disabling of
screensaver by setting the SDL_VIDEO_ALLOW_SCREENSAVER environment
variable added in SDL 1.2.12.

That was certainly a very bad thing to do! If a user has configured a
screensaver, he wants his setting to be obeyed. That is definitely
nothing that some library should mess around with on the sly. It might
be acceptable for application to give the user an option to disable the
screensaver (movie player comes to mind). That is on the application
level, but doing it on the library level is just insane!

However the problem you are noticing I have observed too, the screensaver was not being restored after exiting any SDL program.

How is it supposed to work? I know that there are mechanisms for closing
files that programs have left open when they end and reclaiming memory
that programs have not deallocated before they end, but how is the
system supposed to restore display settings that a program has manipulated?> On Sat, 2008-02-23 at 04:22 +0100, Erik wrote:

SDL could fork a monitoring process early in SDL_Init, so it would watch for
the parent thread and restore any options on its sudden death etc.On Sunday 24 February 2008 23:26:10 Erik wrote:

but how is the
system supposed to restore display settings that a program has manipulated?


Sincerely,
Vladimir “Farcaller” Pouzanov Hack&Dev Team
PGP/GPG: 0x3A40FF29 http://hackndev.com
Fingerprint: FA36 877A 2DC3 B56F CAB5 7DB3 4C97 A596 3A40 FF29
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 481 bytes
Desc: This is a digitally signed message part.
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20080224/32d6e96b/attachment.pgp

Vladimir Pouzanov skrev:> On Sunday 24 February 2008 23:26:10 Erik wrote:

but how is the
system supposed to restore display settings that a program has manipulated?

SDL could fork a monitoring process early in SDL_Init, so it would watch for
the parent thread and restore any options on its sudden death etc.

What if the monitoring process is killed? No, it has to be handled on
the system level to be reliable. You say “could”, so that is not how it
is done now? What mechanism does it rely on now? None, it seems since it
is broken. But why bother at all? What other libraries mess around with
settings like this? Qt? GTK? No, they don’t. Then why does SDL for
$DEITYs sake?

Yes, you have a point. The only reason I have a screen saver anymore
is because after X minutes of me being absent I want no-one else to
use my session. Having this disabled is not desired. If a given
application wants to do this, either SDL could expose the
functionality (or an add-on library) or let the application find
another way (using platform specific methods or another library).On Sun, Feb 24, 2008 at 10:16 PM, Erik wrote:

What if the monitoring process is killed? No, it has to be handled on
the system level to be reliable. You say “could”, so that is not how it
is done now? What mechanism does it rely on now? None, it seems since it
is broken. But why bother at all? What other libraries mess around with
settings like this? Qt? GTK? No, they don’t. Then why does SDL for
$DEITYs sake?

SDL turns off screensaver by default because 99% of the applications
which use SDL are games or media players, and authors have often
requested this functionality.

In SDL 1.3 it will be an API function, but to preserve API compatibility
it’s controlled by an environment variable in SDL 1.2.

Still, it’s supposed to restore the settings when you call SDL_Quit().
Is that happening properly in your application? I haven’t heard any
other reports of this issue… ?

See ya,
-Sam Lantinga, Lead Software Engineer, Blizzard Entertainment

Sam Lantinga skrev:

SDL turns off screensaver by default because 99% of the applications
which use SDL are games or media players,
I get the point about media players, but games?!? Games are interactive
like most other programs. It is not like people start a game and then
just sit there watching it without doing anything at all for several
minutes. At least that is not how I have played games, and I have
played plenty of them.

and authors have often requested this functionality.

100% of users that have set up a screensaver want it to work. Although I
know that SDL targets developers and they decide whether SDL gets used
or not.

In SDL 1.3 it will be an API function, but to preserve API compatibility
it’s controlled by an environment variable in SDL 1.2.

Still, it’s supposed to restore the settings when you call SDL_Quit().

What about the case when an SDL program is running in a window? What
happens when the window loses focus? Even if an SDL program was supposed
to disable the screensaver, it should certainly not do that when
running in a window in the background (the user is working with another
program currently).

it’s supposed to restore the settings when you call SDL_Quit(). Is that happening properly in your application?
That is the wrong question. It should be “Does that happen properly in
every application in every codepath, even if an exception is thrown,
the process is killed or something similar?” And even if it would be
guaranteed to restore the setting at exit, it would still be broken
while the program is running (even in background).

And what about reentrance? What if program A is started, reads the
screensaver settings, disables it. Then program B starts, reads the
screensaver settings (which is to not have a screensaver). Then program
A terminates and restorest the screensaver setting. Then program B would
not have the screensaver disabled any more, as it was intended by SDL.
But when it terminates it will disable the screensaver again (because
that was the state when it started), and leave the system broken.

I noticed this comment in the code:
“Note that this doesn’t stop anything on Vista if the screensaver has a
password”

So it seems like some systems protect against this kind of tampering and
put security first. I just tried it on my system and found out that it
seems just as secure as Vista in this regard. It will lock the session
and ask for a password after the specified time, even with an SDL
program running.

Screensavers are important features that users enable for reasons, so a
library is not supposed to just turn it off at will, directly against
the user’s orders. Some of the reasons that people use screensavers are:

  • Lock the session when they have been away for a minute or so (this
    seems to work despite SDL, at least on my system and Vista).
  • Prevent people from looking what is on the screen (even if they are
    not doing anything).
  • Make the battery time longer. I really hate it when I have been away
    from the computer for a while and some SDL program running in the
    background has drained the battery so that the system has shut off, when
    it should have turned off the display so that almost no energy would
    have been used while I was away.
  • Save energy as such (without thinking about battery time).
  • Save display hardware.

I get the point about media players, but games?!? Games are interactive
like most other programs. It is not like people start a game and then
just sit there watching it without doing anything at all for several
minutes.
Gamepads.
Halo for Mac, for instance, doesn’t disable the screensaver. When my
sister is playing it with her gamepad, she has to move the computer’s
mouse every 10 minutes or the screensaver comes up mid-game.
Usually it happens in the middle of a firefight.
SDL captures the screen on the Mac, though, which automatically
disables the screensaver, so it’s not a problem for fullscreen SDL
apps…

That is the wrong question. It should be “Does that happen properly in
every application in every codepath, even if an exception is thrown,
the process is killed or something similar?” And even if it would be
guaranteed to restore the setting at exit, it would still be broken
while the program is running (even in background).
SIGKILL a fullscreen app that’s grabbed the mouse. Like the
screensaver, what results is not something SDL or any other client
code can fix. It’s a fundamental problem with X11.
If you really want to fix this problem on Linux, beg the Xorg
developers for some sort of “temporarily disable screensaver while
this client is running” command.
-:sigma.SBOn Mon, Feb 25, 2008 at 3:29 AM, Erik wrote:

Solra Bizna skrev:

I get the point about media players, but games?!? Games are interactive
like most other programs. It is not like people start a game and then
just sit there watching it without doing anything at all for several
minutes.

Gamepads.
Halo for Mac, for instance, doesn’t disable the screensaver. When my
sister is playing it with her gamepad, she has to move the computer’s
mouse every 10 minutes or the screensaver comes up mid-game.
Usually it happens in the middle of a firefight.

That is a bug in the input handling. The system seems to forget to reset
the screensaver countdown when an event comes from certain input
devices. It should of course be fixed by treating that input as any
other input that comes from keyboards and mice. Just disabling the
screensaver is an ugly hack to work around that bug and causes other bugs.

That is the wrong question. It should be “Does that happen properly in
every application in every codepath, even if an exception is thrown,
the process is killed or something similar?” And even if it would be
guaranteed to restore the setting at exit, it would still be broken
while the program is running (even in background).

SIGKILL a fullscreen app that’s grabbed the mouse. Like the
screensaver, what results is not something SDL or any other client
code can fix. It’s a fundamental problem with X11.
If you really want to fix this problem on Linux, beg the Xorg
developers for some sort of “temporarily disable screensaver while
this client is running” command.

Do you happen to know of any bug report? I can not be the first one to
run into this problem.> On Mon, Feb 25, 2008 at 3:29 AM, Erik <@Erik1> wrote:

Erik skrev:

Sam Lantinga skrev:

SDL turns off screensaver by default because 99% of the applications
which use SDL are games or media players,
I get the point about media players, but games?!?
That might be interpreted as if I think that the current SDL behaviour
is fine for all media players, but it is certainly not. The only kinds
of applications that the current SDL behaviour sort of works for is the
very simple kind of media players that just start, play a movie and then
terminate, called from the command line like this:
% mediaplayer filename

(How many % of SDL applications are like that?) For all other
applications, the current SDL behaviour breaks things. Suppose that
there is a media player that not always plays a movie. Maybe it shows
some file selection dialog when started without a filename on the
command line. It has no excuse to mess around with display settings
until a file has been selected and it actually starts playing something.
Likewise, if the movie stops playing, the screensaver should be enabled,
even if the application does not terminate.

Solra Bizna skrev:

SIGKILL a fullscreen app that’s grabbed the mouse. Like the
screensaver, what results is not something SDL or any other client
code can fix. It’s a fundamental problem with X11.
If you really want to fix this problem on Linux, beg the Xorg
developers for some sort of “temporarily disable screensaver while
this client is running” command.

Like I just wrote in another reply, that feature would be of very
limited usefulness (movie players who simply start, play and terminate).
We would have to stop and think a while about what we really want to
achieve here.

The situation is that a user has configured his system to turn off the
display after a certain time of inactivity. Since that is an order from
the user, we must respect that unless we have a good reason. That reason
is that we are updating the display with some content that the user may
want to see even though he has not interacted with the system for a
while. This is the case when a movie (animation) is played.

So the solution would be something like this: Each time the application
updates the display with a new animation frame, it marks that update
with a special flag, indicating that this is the kind of thing that the
user may be watching even though he has not interacted with the system
for a while. The X server then resets the screensaver countdown.

So the solution would be something like this: Each time the application
updates the display with a new animation frame, it marks that update
with a special flag, indicating that this is the kind of thing that the
user may be watching even though he has not interacted with the system
for a while. The X server then resets the screensaver countdown.

That’s a great idea. :slight_smile:
Is there a way to pretend to the X server that there has been user input?

The feature was added because there are two cases where X will trigger the
screen saver even though you’re still interacting with the application:

  1. Using non-keyboard/mouse input (e.g. gamepads)
  2. Using fullscreen input (DGA)
    In both of these cases the input is bypassing X11’s normal input path and
    the screensaver kicks on. This can be quite annoying in the middle of say
    Quake Wars. :slight_smile:

So clearly you’re annnoyed at the default behavior of SDL, and while I can
certainly see your point, there are lots of applications where that behavior
is desired. SDL 1.2 won’t be changed at this point because of the large
number of applications that assume the existing behavior. SDL 1.3 will
have an API function for you to query and control this behavior.

In your case, you can simply set the environment variable either globally
as a user, or in specific applications using putenv(), and it’ll solve
the problem for you.

I’ll add a FAQ entry for this:
http://www.libsdl.org/faq.php?action=listentries&category=9#90

As for the original bug report saying that SDL doesn’t restore the power
settings when it quits, did you find out why this is? That is definitely
a bug and should be investigated.

See ya!
-Sam Lantinga, Lead Software Engineer, Blizzard Entertainment

Sam Lantinga skrev:

So the solution would be something like this: Each time the application
updates the display with a new animation frame, it marks that update
with a special flag, indicating that this is the kind of thing that the
user may be watching even though he has not interacted with the system
for a while. The X server then resets the screensaver countdown.

That’s a great idea. :slight_smile:
Is there a way to pretend to the X server that there has been user input?

I could try to bring it up on some Xorg mailing list and see what they
say. But note that the X server has to know the difference between real
and fake input events. Both should reset the screensaver countdown. But
for security reasons, only real input events may reset the session
locking countdown.

The feature was added because there are two cases where X will trigger the
screen saver even though you’re still interacting with the application:

  1. Using non-keyboard/mouse input (e.g. gamepads)

While the X server is active, all input, including gamepads, must go
through the X server. Not only so that it can handle the screensaver
correctly, but also so that it can send the events to the correct (the
currently active) client.

  1. Using fullscreen input (DGA)
    In both of these cases the input is bypassing X11’s normal input path and
    the screensaver kicks on.
    When the X server is not handling the input it should obviously not
    handle the screesaver either, since that feature depends on the input
    handling. So it seems like the X server is trying to do something, that
    it can not possibly do right. Therefore it fails.

In your case, you can simply set the environment variable either globally
as a user, or in specific applications using putenv(), and it’ll solve
the problem for you.

I added SDL_VIDEO_ALLOW_SCREENSAVER=1 to ~/.bashrc and added the
following line to an application, before SDL_Init:

setenv(“SDL_VIDEO_ALLOW_SCREENSAVER”, “1”, 0);

(All non-joystick-games should do the same.) I also added aliases for all other SDL applications (alias appname=“SDL_VIDEO_ALLOW_SCREENSAVER=1 appname”). (If I had had any menu entries or panel buttons for SDL programs, I would have done that for them as well.)

El Tuesday 26 February 2008 14:25:09 Erik escribi?:

The feature was added because there are two cases where X will trigger
the screen saver even though you’re still interacting with the
application: 1. Using non-keyboard/mouse input (e.g. gamepads)
?

While the X server is active, all input, including gamepads, must go
through the X server.

That setup is very uncommon. While it is possible to configure a gamepad as a
X input device, the vast majority of the systems out there doesn’t do that
way. As a disadvantage, you would loss the device’s PnP capability, as
current X servers seem to only look for devices at startup. You would have to
restart X after plugging the pad for it to be recognized as a X input device.

The
feature
was
added
because
there
are
two
cases
where
X
will
trigger
the screen
saver
even
though you’re
still
interacting
with
the
application:
1.
Using
non-keyboard/mouse
input
(e.g.
gamepads)
2.
Using
fullscreen
input
(DGA)
In
both
of
these
cases
the
input
is
bypassing
X11’s
normal
input
path
and
the
screensaver
kicks
on.
This
can
be
quite
annoying
in
the
middle
of
say
Quake
Wars.
:slight_smile:

  1. Playing a lengthy FMV or cutscene, in which case the user doesn’t input
    anything, but still doesn’t want the screensaver turning on. (This has caused
    trouble for me on many applications, including several games, various media
    players, and watching YouTube videos in my browser.) Since this is a legitimate
    problem just as much as the other two, there needs to be some way to deal with
    it. Is there a way to register an app with the system, with a “screensaver will
    never activate while this app has focus” flag? That would seem to me to be the
    simplest solution, if it exists.

Sam Lantinga skrev:

SDL doesn’t restore the power settings when it quits, did you find out why this is?
No, but I found out that DPMSEnable gets called (added debug output
before and after). I also made sure that its argument is the same as in
the call to DPMSDisable (although I did not check the target of that
pointer). So it seems like DPMSEnable does not do what SDL expects it to
do on my system. Maybe a bug in my video driver?

I attach a patch for SDL-1.2.13 that makes the screensaver disabling
configurable.
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed…
Name: confopt-disable-screensaver.patch
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20080226/63eb4695/attachment.txt

Alberto Luaces skrev:

El Tuesday 26 February 2008 14:25:09 Erik escribi?:

The feature was added because there are two cases where X will trigger
the screen saver even though you’re still interacting with the
application: 1. Using non-keyboard/mouse input (e.g. gamepads)

While the X server is active, all input, including gamepads, must go
through the X server.

That setup is very uncommon. While it is possible to configure a gamepad as a
X input device, the vast majority of the systems out there doesn’t do that
way. As a disadvantage, you would loss the device’s PnP capability, as
current X servers seem to only look for devices at startup. You would have to
restart X after plugging the pad for it to be recognized as a X input device.

That is the same problem as with mice. It is usually solved by having a
device called /dev/input/mice, which always exists and receives the
events from all mice that are currently connected. It is not a perfect
solution but better than nothing. The gamepad issue could be solved in
the same way; make X use /dev/input/gamepads.

Sam Lantinga skrev:

Is there a way to pretend to the X server that there has been user input?

XTestFakeKeyEvent, XTestFakeButtonEvent, XTestFakeMotionEvent,
XTestFakeRelativeMotionEvent, XTestFakeDeviceKeyEvent,
XTestFakeDeviceButtonEvent, XTestFakeProximityEvent,
XTestFakeDeviceMotionEvent.

Sam Lantinga skrev:

So the solution would be something like this: Each time the application
updates the display with a new animation frame, it marks that update
with a special flag, indicating that this is the kind of thing that the
user may be watching even though he has not interacted with the system
for a while. The X server then resets the screensaver countdown.

That’s a great idea. :slight_smile:
Is there a way to pretend to the X server that there has been user input?

I just found out that mplayer discovered the correct way to handle this.
“Remove most of the messy screensaver code in favour of only
XResetScreenSaver”:
http://svn.mplayerhq.hu/mplayer?view=rev&revision=25637