Okay, _now_ SDL_WM_ToggleFullScreen() works on all platforms. :)
authorSam Lantinga <slouken@libsdl.org>
Wed, 16 Feb 2011 01:26:39 -0800
changeset 5308 50ceebd6e12f
parent 5307 89a8263374ac
child 5309 da080d3247c9
Okay, _now_ SDL_WM_ToggleFullScreen() works on all platforms. :)
src/SDL_compat.c
--- a/src/SDL_compat.c	Wed Feb 16 00:45:10 2011 -0800
+++ b/src/SDL_compat.c	Wed Feb 16 01:26:39 2011 -0800
@@ -834,6 +834,32 @@
 int
 SDL_WM_ToggleFullScreen(SDL_Surface * surface)
 {
+    int length;
+    void *pixels;
+    Uint8 *src, *dst;
+    int row;
+    int window_w;
+    int window_h;
+
+    if (!SDL_PublicSurface) {
+        SDL_SetError("SDL_SetVideoMode() hasn't been called");
+        return 0;
+    }
+
+    /* Copy the old bits out */
+    length = SDL_VideoSurface->w * SDL_VideoSurface->format->BytesPerPixel;
+    pixels = SDL_malloc(SDL_VideoSurface->h * length);
+    if (pixels) {
+        src = (Uint8*)SDL_VideoSurface->pixels;
+        dst = (Uint8*)pixels;
+        for (row = 0; row < SDL_VideoSurface->h; ++row) {
+            SDL_memcpy(dst, src, length);
+            src += SDL_VideoSurface->pitch;
+            dst += length;
+        }
+    }
+
+    /* Do the physical mode switch */
     if (SDL_GetWindowFlags(SDL_VideoWindow) & SDL_WINDOW_FULLSCREEN) {
         if (SDL_SetWindowFullscreen(SDL_VideoWindow, 0) < 0) {
             return 0;
@@ -845,6 +871,74 @@
         }
         SDL_PublicSurface->flags |= SDL_FULLSCREEN;
     }
+
+    /* Recreate the screen surface */
+    SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
+    if (!SDL_WindowSurface) {
+        /* We're totally hosed... */
+        return 0;
+    }
+
+    /* Center the public surface in the window surface */
+    SDL_GetWindowSize(SDL_VideoWindow, &window_w, &window_h);
+    SDL_VideoViewport.x = (window_w - SDL_VideoSurface->w)/2;
+    SDL_VideoViewport.y = (window_h - SDL_VideoSurface->h)/2;
+    SDL_VideoViewport.w = SDL_VideoSurface->w;
+    SDL_VideoViewport.h = SDL_VideoSurface->h;
+
+    /* Do some shuffling behind the application's back if format changes */
+    if (SDL_VideoSurface->format->format != SDL_WindowSurface->format->format) {
+        if (SDL_ShadowSurface) {
+            if (SDL_ShadowSurface->format->format == SDL_WindowSurface->format->format) {
+                /* Whee!  We don't need a shadow surface anymore! */
+                SDL_VideoSurface->flags &= ~SDL_DONTFREE;
+                SDL_FreeSurface(SDL_VideoSurface);
+                SDL_free(SDL_ShadowSurface->pixels);
+                SDL_ShadowSurface->flags |= SDL_PREALLOC;
+                SDL_VideoSurface = SDL_ShadowSurface;
+                SDL_ShadowSurface = NULL;
+            } else {
+                /* No problem, just change the video surface format */
+                SDL_FreeFormat(SDL_VideoSurface->format);
+                SDL_VideoSurface->format = SDL_WindowSurface->format;
+                SDL_VideoSurface->format->refcount++;
+                SDL_InvalidateMap(SDL_ShadowSurface->map);
+            }
+        } else {
+            /* We can make the video surface the shadow surface */
+            SDL_ShadowSurface = SDL_VideoSurface;
+
+            SDL_VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
+            SDL_VideoSurface->flags = SDL_ShadowSurface->flags;
+            SDL_FreeFormat(SDL_VideoSurface->format);
+            SDL_VideoSurface->format = SDL_WindowSurface->format;
+            SDL_VideoSurface->format->refcount++;
+            SDL_VideoSurface->w = SDL_ShadowSurface->w;
+            SDL_VideoSurface->h = SDL_ShadowSurface->h;
+        }
+    }
+
+    /* Update the video surface */
+    SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
+    SDL_VideoSurface->pixels = (void *)((Uint8 *)SDL_WindowSurface->pixels +
+        SDL_VideoViewport.y * SDL_VideoSurface->pitch +
+        SDL_VideoViewport.x  * SDL_VideoSurface->format->BytesPerPixel);
+    SDL_SetClipRect(SDL_VideoSurface, NULL);
+
+    /* Copy the old bits back */
+    if (pixels) {
+        src = (Uint8*)pixels;
+        dst = (Uint8*)SDL_VideoSurface->pixels;
+        for (row = 0; row < SDL_VideoSurface->h; ++row) {
+            SDL_memcpy(dst, src, length);
+            src += length;
+            dst += SDL_VideoSurface->pitch;
+        }
+        SDL_Flip(SDL_VideoSurface);
+        SDL_free(pixels);
+    }
+
+    /* We're done! */
     return 1;
 }