foxygit / doom Log in
commit dd4e95dc08087503e1467a3ba8c6d534f285d5dd
Author:     Simon Howard <fraggle@gmail.com>
AuthorDate: Tue Nov 14 20:09:26 2006 +0000
Commit:     Simon Howard <fraggle@gmail.com>
CommitDate: Tue Nov 14 20:09:26 2006 +0000

    Support running as a screensaver under X!

    Subversion-branch: /trunk/chocolate-doom
    Subversion-revision: 750
---
 src/Makefile.am                        |   5 +-
 src/chocolate-doom-screensaver.desktop |  12 ++++
 src/d_main.c                           |   6 +-
 src/doomstat.h                         |   1 +
 src/i_sound.c                          |   3 +-
 src/i_system.c                         |  10 ++-
 src/i_video.c                          | 122 ++++++++++++++++++++++++++++-----
 src/i_video.h                          |   2 +
 8 files changed, 140 insertions(+), 21 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 5d038675..bb44f207 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -138,7 +138,10 @@ endif

 chocolate_doom_LDADD = ../textscreen/libtextscreen.a @LDFLAGS@ @SDL_LIBS@ @SDLMIXER_LIBS@ @SDLNET_LIBS@

-EXTRA_DIST = convert-icon chocolate_doom_icon.c
+EXTRA_DIST =                               \
+        convert-icon                       \
+        chocolate_doom_icon.c              \
+        chocolate-doom-screensaver.desktop

 .rc.o:
 	$(WINDRES) $^ -o $@
diff --git a/src/chocolate-doom-screensaver.desktop b/src/chocolate-doom-screensaver.desktop
new file mode 100644
index 00000000..d90127a3
--- /dev/null
+++ b/src/chocolate-doom-screensaver.desktop
@@ -0,0 +1,12 @@
+
+[Desktop Entry]
+Encoding=UTF-8
+Name=Doom
+Comment=DOOM by Id Software.
+TryExec=chocolate-doom
+Exec=chocolate-doom
+StartupNotify=false
+Terminal=false
+Type=Application
+Categories=Screensaver
+
diff --git a/src/d_main.c b/src/d_main.c
index 707f8c99..9d3e0076 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -111,6 +111,10 @@ boolean         fastparm;	// checkparm of -fast
 boolean		singletics = false; // debug flag to cancel adaptiveness


+// If true, game is running as a screensaver
+
+boolean         screensaver_mode = false;
+

 //extern int soundVolume;
 //extern  int	sfxVolume;
@@ -1295,7 +1299,7 @@ void D_DoomMain (void)
     char            demolumpname[9];

     FindResponseFile ();
-
+
     // print banner

     PrintBanner(PACKAGE_STRING);
diff --git a/src/doomstat.h b/src/doomstat.h
index e49ee54f..4fc174cd 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -55,6 +55,7 @@ extern  boolean	fastparm;	// checkparm of -fast
 extern  boolean	devparm;	// DEBUG: launched with -devparm


+extern  boolean screensaver_mode;    // game running as a screensaver?

 // -----------------------------------------------------
 // Game Mode - identify IWAD as shareware, retail etc.
diff --git a/src/i_sound.c b/src/i_sound.c
index 5bc9d109..165be416 100644
--- a/src/i_sound.c
+++ b/src/i_sound.c
@@ -462,8 +462,9 @@ I_InitSound()

     // If music or sound is going to play, we need to at least
     // initialise SDL
+    // No sound in screensaver mode.

-    if (nomusicparm && nosfxparm)
+    if (screensaver_mode || (nomusicparm && nosfxparm))
         return;

     if (SDL_Init(SDL_INIT_AUDIO) < 0)
diff --git a/src/i_system.c b/src/i_system.c
index bf8daa3a..4f1bdac3 100644
--- a/src/i_system.c
+++ b/src/i_system.c
@@ -106,6 +106,7 @@ byte *I_ZoneBase (int *size)
 //
 void I_Init (void)
 {
+    I_CheckIsScreensaver();
     I_InitSound();
     I_InitMusic();
     I_InitTimer();
@@ -164,10 +165,15 @@ void I_Quit (void)
     G_CheckDemoStatus();
     I_ShutdownSound();
     I_ShutdownMusic();
-    M_SaveDefaults ();
+
+    if (!screensaver_mode)
+    {
+        M_SaveDefaults ();
+    }
+
     I_ShutdownGraphics();

-    if (show_endoom && !testcontrols)
+    if (show_endoom && !testcontrols && !screensaver_mode)
     {
         I_Endoom();
     }
diff --git a/src/i_video.c b/src/i_video.c
index 6604ca04..669e6eec 100644
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -132,6 +132,11 @@ int mouse_threshold = 10;

 static boolean MouseShouldBeGrabbed()
 {
+    // never grab the mouse when in screensaver mode
+
+    if (screensaver_mode)
+        return false;
+
     // if the window doesnt have focus, never grab it

     if (!window_focused)
@@ -382,6 +387,11 @@ void I_GetEvent(void)
             continue;
         }

+        if (screensaver_mode && sdlevent.type == SDL_QUIT)
+        {
+            I_Quit();
+        }
+
         // process event

         switch (sdlevent.type)
@@ -392,11 +402,13 @@ void I_GetEvent(void)
 		event.data2 = sdlevent.key.keysym.unicode;
                 D_PostEvent(&event);
                 break;
+
             case SDL_KEYUP:
                 event.type = ev_keyup;
                 event.data1 = TranslateKey(&sdlevent.key.keysym);
                 D_PostEvent(&event);
                 break;
+
                 /*
             case SDL_MOUSEMOTION:
                 event.type = ev_mouse;
@@ -406,6 +418,7 @@ void I_GetEvent(void)
                 D_PostEvent(&event);
                 break;
                 */
+
             case SDL_MOUSEBUTTONDOWN:
 		if (usemouse && !nomouse)
 		{
@@ -415,6 +428,7 @@ void I_GetEvent(void)
                     D_PostEvent(&event);
 		}
                 break;
+
             case SDL_MOUSEBUTTONUP:
 		if (usemouse && !nomouse)
 		{
@@ -424,15 +438,18 @@ void I_GetEvent(void)
                     D_PostEvent(&event);
 		}
                 break;
+
             case SDL_QUIT:
                 // bring up the "quit doom?" prompt
                 S_StartSound(NULL,sfx_swtchn);
                 M_QuitDOOM(0);
                 break;
+
             case SDL_ACTIVEEVENT:
                 // need to update our focus state
                 UpdateFocus();
                 break;
+
             default:
                 break;
         }
@@ -534,18 +551,10 @@ static void UpdateGrab(void)
 static void BlitArea(int x1, int y1, int x2, int y2)
 {
     int w = x2 - x1;
-    int y_offset;
+    int x_offset, y_offset;

-    // Y offset when running in letterbox mode
-
-    if (fullscreen == FULLSCREEN_LETTERBOX)
-    {
-        y_offset = (LETTERBOX_SCREENHEIGHT - SCREENHEIGHT) / 2;
-    }
-    else
-    {
-        y_offset = 0;
-    }
+    x_offset = ((screen->w / screenmultiply) - SCREENWIDTH) / 2;
+    y_offset = ((screen->h / screenmultiply) - SCREENHEIGHT) / 2;

     // Need to byte-copy from buffer into the screen buffer

@@ -559,7 +568,8 @@ static void BlitArea(int x1, int y1, int x2, int y2)
         {
             pitch = screen->pitch;
             bufp = screens[0] + y1 * SCREENWIDTH + x1;
-            screenp = (byte *) screen->pixels + (y1 + y_offset) * pitch + x1;
+            screenp = (byte *) screen->pixels + (y1 + y_offset) * pitch
+                                              + x1 + x_offset;

             for (y=y1; y<y2; ++y)
             {
@@ -586,7 +596,7 @@ static void BlitArea(int x1, int y1, int x2, int y2)
             bufp = screens[0] + y1 * SCREENWIDTH + x1;
             screenp = (byte *) screen->pixels
                     + (y1 + y_offset) * pitch
-                    + x1 * 2;
+                    + (x1 + x_offset) * 2;
             screenp2 = screenp + screen->pitch;

             for (y=y1; y<y2; ++y)
@@ -623,7 +633,7 @@ static void BlitArea(int x1, int y1, int x2, int y2)
             bufp = screens[0] + y1 * SCREENWIDTH + x1;
             screenp = (byte *) screen->pixels
                     + (y1 + y_offset) * pitch
-                    + x1 * 3;
+                    + (x1 + x_offset) * 3;
             screenp2 = screenp + screen->pitch;
             screenp3 = screenp2 + screen->pitch;

@@ -664,7 +674,7 @@ static void BlitArea(int x1, int y1, int x2, int y2)
             bufp = screens[0] + y1 * SCREENWIDTH + x1;
             screenp = (byte *) screen->pixels
                     + (y1 + y_offset) * pitch
-                    + x1 * 4;
+                    + (x1 + x_offset) * 4;
             screenp2 = screenp + screen->pitch;
             screenp3 = screenp2 + screen->pitch;
             screenp4 = screenp3 + screen->pitch;
@@ -1041,10 +1051,75 @@ static void AutoAdjustSettings(void)
     }
 }

+// Check if we have been invoked as a screensaver by xscreensaver.
+
+void I_CheckIsScreensaver(void)
+{
+    char *env;
+
+    env = SDL_getenv("XSCREENSAVER_WINDOW");
+
+    if (env != NULL)
+    {
+        screensaver_mode = true;
+    }
+}
+
+// In screensaver mode, pick a screenmultiply value that fits
+// inside the screen.  It is okay to do this because settings
+// are not saved in screensaver mode.
+
+static void FindScreensaverMultiply(void)
+{
+    int i;
+
+    for (i=1; i<=4; ++i)
+    {
+        if (SCREENWIDTH * i <= screen->w
+         && SCREENHEIGHT * i <= screen->h)
+        {
+            screenmultiply = i;
+        }
+    }
+}
+
+// Blank cursor so we don't see the mouse.  It is not okay to
+// do SDL_ShowCursor(0) because this will hide the mouse in
+// the configuration dialog.  Only show no mouse when over this
+// window.
+
+static void SetBlankCursor(void)
+{
+    Uint8 zero = zero;
+    SDL_Cursor *cursor;
+
+    cursor = SDL_CreateCursor(&zero, &zero, 1, 1, 0, 0);
+
+    SDL_SetCursor(cursor);
+}
+
 void I_InitGraphics(void)
 {
     SDL_Event dummy;
     int flags = 0;
+    char *env;
+
+    // Pass through the XSCREENSAVER_WINDOW environment variable to
+    // SDL_WINDOWID, to embed the SDL window into the Xscreensaver
+    // window.
+
+    env = SDL_getenv("XSCREENSAVER_WINDOW");
+
+    if (env != NULL)
+    {
+        char winenv[30];
+        int winid;
+
+        sscanf(env, "0x%x", &winid);
+        sprintf(winenv, "SDL_WINDOWID=%i", winid);
+
+        SDL_putenv(winenv);
+    }

 #ifdef _WIN32

@@ -1096,6 +1171,12 @@ void I_InitGraphics(void)
         flags |= SDL_FULLSCREEN;
     }

+    if (screensaver_mode)
+    {
+        windowwidth = 0;
+        windowheight = 0;
+    }
+
     screen = SDL_SetVideoMode(windowwidth, windowheight, 8, flags);

     if (screen == NULL)
@@ -1103,6 +1184,15 @@ void I_InitGraphics(void)
         I_Error("Error setting video mode: %s\n", SDL_GetError());
     }

+    // In screensaver mode, screenmultiply as large as possible
+    // and set a blank cursor.
+
+    if (screensaver_mode)
+    {
+        FindScreensaverMultiply();
+        SetBlankCursor();
+    }
+
     // Start with a clear black screen
     // (screen will be flipped after we set the palette)

@@ -1137,7 +1227,7 @@ void I_InitGraphics(void)
     // setting the screen mode, so that the game doesn't start immediately
     // with the player unable to see anything.

-    if (fullscreen)
+    if (fullscreen && !screensaver_mode)
     {
         SDL_Delay(startup_delay);
     }
diff --git a/src/i_video.h b/src/i_video.h
index 2df17962..e9904fd8 100644
--- a/src/i_video.h
+++ b/src/i_video.h
@@ -58,6 +58,8 @@ void I_EndRead (void);
 void I_SetWindowCaption(void);
 void I_SetWindowIcon(void);

+void I_CheckIsScreensaver(void);
+
 extern int autoadjust_video_settings;
 extern boolean screenvisible;
 extern int screenmultiply;