From d8b35a131d9be2e1408dcd3daf91b69fbb287b91 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 9 Jul 2006 09:02:26 +0000 Subject: [PATCH] Implemented gamma correction on Windows. Added general code to restore the video mode and gamma when windows lose focus. --- include/SDL_video.h | 127 +++++++++++++++++++----------- src/SDL_compat.c | 17 +--- src/events/SDL_windowevents.c | 10 +++ src/video/SDL_gamma.c | 92 +++++++++------------- src/video/SDL_sysvideo.h | 52 ++++++------ src/video/SDL_video.c | 119 +++++++++++++++++++++++----- src/video/win32/SDL_win32events.c | 14 +++- src/video/win32/SDL_win32gamma.c | 63 +++++++++++++++ src/video/win32/SDL_win32gamma.h | 32 ++++++++ src/video/win32/SDL_win32modes.c | 47 +++++++---- src/video/win32/SDL_win32modes.h | 12 +++ src/video/win32/SDL_win32video.c | 9 ++- src/video/win32/SDL_win32video.h | 1 + src/video/win32/SDL_win32window.c | 9 +++ test/testsprite2.c | 9 +-- test/testwm2.c | 6 -- 16 files changed, 429 insertions(+), 190 deletions(-) create mode 100644 src/video/win32/SDL_win32gamma.c create mode 100644 src/video/win32/SDL_win32gamma.h diff --git a/include/SDL_video.h b/include/SDL_video.h index 6e258bcaf..2e7182c2b 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -98,6 +98,7 @@ typedef struct * \sa SDL_RaiseWindow() * \sa SDL_RestoreWindow() * \sa SDL_SetWindowData() + * \sa SDL_SetWindowFullscreen() * \sa SDL_SetWindowGrab() * \sa SDL_SetWindowIcon() * \sa SDL_SetWindowPosition() @@ -474,15 +475,28 @@ extern DECLSPEC SDL_DisplayMode *SDLCALL SDL_GetClosestDisplayMode(const * closest); /** - * \fn int SDL_SetDisplayMode(const SDL_DisplayMode *mode) + * \fn int SDL_SetFullscreenDisplayMode(const SDL_DisplayMode *mode) * - * \brief Set up the closest available mode on the current display. + * \brief Set the display mode used when a fullscreen window is visible + * on the currently selected display. * - * \param mode The desired display mode, or NULL to set the desktop mode. + * \param mode The mode to use, or NULL for the desktop mode. * * \return 0 on success, or -1 if setting the display mode failed. + * + * \sa SDL_SetWindowFullscreen() */ -extern DECLSPEC int SDLCALL SDL_SetDisplayMode(const SDL_DisplayMode * mode); +extern DECLSPEC int SDLCALL SDL_SetFullscreenDisplayMode(const SDL_DisplayMode + * mode); + +/** + * \fn const SDL_DisplayMode *SDL_GetFullscreenDisplayMode(void) + * + * \brief Query the display mode used when a fullscreen window is visible + * on the currently selected display. + */ +extern DECLSPEC const SDL_DisplayMode *SDLCALL +SDL_GetFullscreenDisplayMode(void); /** * \fn int SDL_SetDisplayPalette(const SDL_Color *colors, int firstcolor, int ncolors) @@ -506,6 +520,57 @@ extern DECLSPEC int SDLCALL SDL_GetDisplayPalette(SDL_Color * colors, int firstcolor, int ncolors); +/** + * \fn int SDL_SetGamma(float red, float green, float blue) + * + * \brief Set the gamma correction for each of the color channels on the currently selected display. + * + * \return 0 on success, or -1 if setting the gamma isn't supported. + * + * \sa SDL_SetGammaRamp() + */ +extern DECLSPEC int SDLCALL SDL_SetGamma(float red, float green, float blue); + +/** + * \fn int SDL_SetGammaRamp(const Uint16 * red, const Uint16 * green, const Uint16 * blue) + * + * \brief Set the gamma ramp for the currently selected display. + * + * \param red The translation table for the red channel, or NULL + * \param green The translation table for the green channel, or NULL + * \param blue The translation table for the blue channel, or NULL + * + * \return 0 on success, or -1 if gamma ramps are unsupported. + * + * Set the gamma translation table for the red, green, and blue channels + * of the video hardware. Each table is an array of 256 16-bit quantities, + * representing a mapping between the input and output for that channel. + * The input is the index into the array, and the output is the 16-bit + * gamma value at that index, scaled to the output color precision. + * + * \sa SDL_GetGammaRamp() + */ +extern DECLSPEC int SDLCALL SDL_SetGammaRamp(const Uint16 * red, + const Uint16 * green, + const Uint16 * blue); + +/** + * \fn int SDL_GetGammaRamp(Uint16 * red, Uint16 * green, Uint16 * blue) + * + * \brief Get the gamma ramp for the currently selected display. + * + * \param red A pointer to a 256 element array of 16-bit quantities to hold the translation table for the red channel, or NULL. + * \param green A pointer to a 256 element array of 16-bit quantities to hold the translation table for the green channel, or NULL. + * \param blue A pointer to a 256 element array of 16-bit quantities to hold the translation table for the blue channel, or NULL. + * + * \return 0 on success, or -1 if gamma ramps are unsupported. + * + * \sa SDL_SetGammaRamp() + */ +extern DECLSPEC int SDLCALL SDL_GetGammaRamp(Uint16 * red, Uint16 * green, + Uint16 * blue); + + /** * \fn SDL_WindowID SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) * @@ -516,7 +581,7 @@ extern DECLSPEC int SDLCALL SDL_GetDisplayPalette(SDL_Color * colors, * \param y The y position of the window * \param w The width of the window * \param h The height of the window - * \param flags The flags for the window + * \param flags The flags for the window, a mask of any of the following: SDL_WINDOW_FULLSCREEN, SDL_WINDOW_OPENGL, SDL_WINDOW_SHOWN, SDL_WINDOW_BORDERLESS, SDL_WINDOW_RESIZABLE, SDL_WINDOW_MAXIMIZED, SDL_WINDOW_MINIMIZED, SDL_WINDOW_INPUT_GRABBED * * \return The id of the window created, or zero if window creation failed. * @@ -701,6 +766,18 @@ extern DECLSPEC void SDLCALL SDL_MinimizeWindow(SDL_WindowID windowID); */ extern DECLSPEC void SDLCALL SDL_RestoreWindow(SDL_WindowID windowID); +/** + * \fn int SDL_SetWindowFullscreen(SDL_WindowID windowID, int fullscreen) + * + * \brief Set the window's fullscreen state. + * + * \return 0 on success, or -1 if setting the display mode failed. + * + * \sa SDL_SetFullscreenDisplayMode() + */ +extern DECLSPEC int SDLCALL SDL_SetWindowFullscreen(SDL_WindowID windowID, + int fullscreen); + /** * \fn void SDL_SetWindowGrab(SDL_WindowID windowID, int mode) * @@ -708,7 +785,6 @@ extern DECLSPEC void SDLCALL SDL_RestoreWindow(SDL_WindowID windowID); * * \param mode This is 1 to grab input, and 0 to release input. * - * \sa SDL_GrabMode * \sa SDL_GetWindowGrab() */ extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_WindowID windowID, @@ -721,7 +797,6 @@ extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_WindowID windowID, * * \return This returns 1 if input is grabbed, and 0 otherwise. * - * \sa SDL_GrabMode * \sa SDL_SetWindowGrab() */ extern DECLSPEC int SDLCALL SDL_GetWindowGrab(SDL_WindowID windowID); @@ -1069,44 +1144,6 @@ extern DECLSPEC void SDLCALL SDL_DestroyTexture(SDL_TextureID textureID); */ extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_WindowID windowID); -/* - * Set the gamma correction for each of the color channels. - * The gamma values range (approximately) between 0.1 and 10.0 - * - * If this function isn't supported directly by the hardware, it will - * be emulated using gamma ramps, if available. If successful, this - * function returns 0, otherwise it returns -1. - */ -extern DECLSPEC int SDLCALL SDL_SetGamma(float red, float green, float blue); - -/* - * Set the gamma translation table for the red, green, and blue channels - * of the video hardware. Each table is an array of 256 16-bit quantities, - * representing a mapping between the input and output for that channel. - * The input is the index into the array, and the output is the 16-bit - * gamma value at that index, scaled to the output color precision. - * - * You may pass NULL for any of the channels to leave it unchanged. - * If the call succeeds, it will return 0. If the display driver or - * hardware does not support gamma translation, or otherwise fails, - * this function will return -1. - */ -extern DECLSPEC int SDLCALL SDL_SetGammaRamp(const Uint16 * red, - const Uint16 * green, - const Uint16 * blue); - -/* - * Retrieve the current values of the gamma translation tables. - * - * You must pass in valid pointers to arrays of 256 16-bit quantities. - * Any of the pointers may be NULL to ignore that channel. - * If the call succeeds, it will return 0. If the display driver or - * hardware does not support gamma translation, or otherwise fails, - * this function will return -1. - */ -extern DECLSPEC int SDLCALL SDL_GetGammaRamp(Uint16 * red, Uint16 * green, - Uint16 * blue); - /* * Maps an RGB triple to an opaque pixel value for a given pixel format */ diff --git a/src/SDL_compat.c b/src/SDL_compat.c index b5d213a91..2811fd8fd 100644 --- a/src/SDL_compat.c +++ b/src/SDL_compat.c @@ -360,9 +360,8 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) if (flags & SDL_NOFRAME) { window_flags |= SDL_WINDOW_BORDERLESS; } - if (SDL_getenv("SDL_WINDOW_POS")) { - } GetEnvironmentWindowPosition(width, height, &window_x, &window_y); + SDL_SetFullscreenDisplayMode(NULL); SDL_VideoWindow = SDL_CreateWindow(wm_title, window_x, window_y, width, height, window_flags); @@ -427,21 +426,9 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) /* Set the desired display mode */ if (flags & SDL_FULLSCREEN) { - if (!SDL_GetClosestDisplayMode(&mode, &mode)) { + if (SDL_SetFullscreenDisplayMode(&mode) < 0) { return NULL; } - } else { - if (desktop_format) { - mode.format = desktop_format; - } - if (desktop_mode->w && desktop_mode->h) { - mode.w = desktop_mode->w; - mode.h = desktop_mode->h; - } - mode.refresh_rate = desktop_mode->refresh_rate; - } - if (SDL_SetDisplayMode(&mode) < 0) { - return NULL; } /* If we're in OpenGL mode, just create a stub surface and we're done! */ diff --git a/src/events/SDL_windowevents.c b/src/events/SDL_windowevents.c index 08fa3d4dc..7b0da9ee9 100644 --- a/src/events/SDL_windowevents.c +++ b/src/events/SDL_windowevents.c @@ -44,19 +44,27 @@ SDL_SendWindowEvent(SDL_WindowID windowID, Uint8 windowevent, int data1, return 0; } window->flags |= SDL_WINDOW_SHOWN; + SDL_OnWindowShown(window); break; case SDL_WINDOWEVENT_HIDDEN: if (!(window->flags & SDL_WINDOW_SHOWN)) { return 0; } window->flags &= ~SDL_WINDOW_SHOWN; + SDL_OnWindowHidden(window); break; case SDL_WINDOWEVENT_MOVED: + if (window->flags & SDL_WINDOW_FULLSCREEN) { + return 0; + } if (data1 == window->x && data2 == window->y) { return 0; } break; case SDL_WINDOWEVENT_RESIZED: + if (window->flags & SDL_WINDOW_FULLSCREEN) { + return 0; + } if (data1 == window->w && data2 == window->h) { return 0; } @@ -96,12 +104,14 @@ SDL_SendWindowEvent(SDL_WindowID windowID, Uint8 windowevent, int data1, return 0; } window->flags |= SDL_WINDOW_KEYBOARD_FOCUS; + SDL_OnWindowFocusGained(window); break; case SDL_WINDOWEVENT_FOCUS_LOST: if (!(window->flags & SDL_WINDOW_KEYBOARD_FOCUS)) { return 0; } window->flags &= ~SDL_WINDOW_KEYBOARD_FOCUS; + SDL_OnWindowFocusLost(window); break; } diff --git a/src/video/SDL_gamma.c b/src/video/SDL_gamma.c index 991ae98db..283101347 100644 --- a/src/video/SDL_gamma.c +++ b/src/video/SDL_gamma.c @@ -96,24 +96,13 @@ CalculateGammaFromRamp(float *gamma, Uint16 * ramp) int SDL_SetGamma(float red, float green, float blue) { - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - int succeeded; + Uint16 ramp[3][256]; - succeeded = -1; - /* Prefer using SetGammaRamp(), as it's more flexible */ - { - Uint16 ramp[3][256]; + CalculateGammaRamp(red, ramp[0]); + CalculateGammaRamp(green, ramp[1]); + CalculateGammaRamp(blue, ramp[2]); - CalculateGammaRamp(red, ramp[0]); - CalculateGammaRamp(green, ramp[1]); - CalculateGammaRamp(blue, ramp[2]); - succeeded = SDL_SetGammaRamp(ramp[0], ramp[1], ramp[2]); - } - if ((succeeded < 0) && _this && _this->SetGamma) { - SDL_ClearError(); - succeeded = _this->SetGamma(_this, red, green, blue); - } - return succeeded; + return SDL_SetGammaRamp(ramp[0], ramp[1], ramp[2]); } /* Calculating the gamma by integrating the gamma ramps isn't exact, @@ -122,24 +111,14 @@ SDL_SetGamma(float red, float green, float blue) int SDL_GetGamma(float *red, float *green, float *blue) { - SDL_VideoDevice *_this = SDL_GetVideoDevice(); int succeeded; + Uint16 ramp[3][256]; - succeeded = -1; - /* Prefer using GetGammaRamp(), as it's more flexible */ - { - Uint16 ramp[3][256]; - - succeeded = SDL_GetGammaRamp(ramp[0], ramp[1], ramp[2]); - if (succeeded >= 0) { - CalculateGammaFromRamp(red, ramp[0]); - CalculateGammaFromRamp(green, ramp[1]); - CalculateGammaFromRamp(blue, ramp[2]); - } - } - if ((succeeded < 0) && _this && _this->GetGamma) { - SDL_ClearError(); - succeeded = _this->GetGamma(_this, red, green, blue); + succeeded = SDL_GetGammaRamp(ramp[0], ramp[1], ramp[2]); + if (succeeded >= 0) { + CalculateGammaFromRamp(red, ramp[0]); + CalculateGammaFromRamp(green, ramp[1]); + CalculateGammaFromRamp(blue, ramp[2]); } return succeeded; } @@ -152,28 +131,29 @@ SDL_SetGammaRamp(const Uint16 * red, const Uint16 * green, int succeeded; /* Lazily allocate the gamma tables */ - if (!SDL_CurrentWindow.gamma) { - SDL_GetGammaRamp(0, 0, 0); + if (!SDL_CurrentDisplay.gamma) { + SDL_GetGammaRamp(NULL, NULL, NULL); } /* Fill the gamma table with the new values */ if (red) { - SDL_memcpy(&SDL_CurrentWindow.gamma[0 * 256], red, - 256 * sizeof(*SDL_CurrentWindow.gamma)); + SDL_memcpy(&SDL_CurrentDisplay.gamma[0 * 256], red, + 256 * sizeof(*SDL_CurrentDisplay.gamma)); } if (green) { - SDL_memcpy(&SDL_CurrentWindow.gamma[1 * 256], green, - 256 * sizeof(*SDL_CurrentWindow.gamma)); + SDL_memcpy(&SDL_CurrentDisplay.gamma[1 * 256], green, + 256 * sizeof(*SDL_CurrentDisplay.gamma)); } if (blue) { - SDL_memcpy(&SDL_CurrentWindow.gamma[2 * 256], blue, - 256 * sizeof(*SDL_CurrentWindow.gamma)); + SDL_memcpy(&SDL_CurrentDisplay.gamma[2 * 256], blue, + 256 * sizeof(*SDL_CurrentDisplay.gamma)); } /* Try to set the gamma ramp in the driver */ succeeded = -1; - if (_this && _this->SetGammaRamp) { - succeeded = _this->SetGammaRamp(_this, SDL_CurrentWindow.gamma); + if (_this && _this->SetDisplayGammaRamp) { + succeeded = + _this->SetDisplayGammaRamp(_this, SDL_CurrentDisplay.gamma); } else { SDL_SetError("Gamma ramp manipulation not supported"); } @@ -186,38 +166,42 @@ SDL_GetGammaRamp(Uint16 * red, Uint16 * green, Uint16 * blue) SDL_VideoDevice *_this = SDL_GetVideoDevice(); /* Lazily allocate the gamma table */ - if (!SDL_CurrentWindow.gamma) { - SDL_CurrentWindow.gamma = - SDL_malloc(3 * 256 * sizeof(*SDL_CurrentWindow.gamma)); - if (!SDL_CurrentWindow.gamma) { + if (!SDL_CurrentDisplay.gamma) { + size_t rampsize = (3 * 256 * sizeof(*SDL_CurrentDisplay.gamma)); + + SDL_CurrentDisplay.gamma = SDL_malloc(rampsize * 2); + if (!SDL_CurrentDisplay.gamma) { SDL_OutOfMemory(); return -1; } - if (_this && _this->GetGammaRamp) { + if (_this && _this->GetDisplayGammaRamp) { /* Get the real hardware gamma */ - _this->GetGammaRamp(_this, SDL_CurrentWindow.gamma); + _this->GetDisplayGammaRamp(_this, SDL_CurrentDisplay.gamma); } else { /* Assume an identity gamma */ int i; for (i = 0; i < 256; ++i) { - SDL_CurrentWindow.gamma[0 * 256 + i] = (i << 8) | i; - SDL_CurrentWindow.gamma[1 * 256 + i] = (i << 8) | i; - SDL_CurrentWindow.gamma[2 * 256 + i] = (i << 8) | i; + SDL_CurrentDisplay.gamma[0 * 256 + i] = (i << 8) | i; + SDL_CurrentDisplay.gamma[1 * 256 + i] = (i << 8) | i; + SDL_CurrentDisplay.gamma[2 * 256 + i] = (i << 8) | i; } } + SDL_CurrentDisplay.saved_gamma = SDL_CurrentDisplay.gamma + (3 * 256); + SDL_memcpy(SDL_CurrentDisplay.saved_gamma, SDL_CurrentDisplay.gamma, + rampsize); } /* Just copy from our internal table */ if (red) { - SDL_memcpy(red, &SDL_CurrentWindow.gamma[0 * 256], + SDL_memcpy(red, &SDL_CurrentDisplay.gamma[0 * 256], 256 * sizeof(*red)); } if (green) { - SDL_memcpy(green, &SDL_CurrentWindow.gamma[1 * 256], + SDL_memcpy(green, &SDL_CurrentDisplay.gamma[1 * 256], 256 * sizeof(*green)); } if (blue) { - SDL_memcpy(blue, &SDL_CurrentWindow.gamma[2 * 256], + SDL_memcpy(blue, &SDL_CurrentDisplay.gamma[2 * 256], 256 * sizeof(*blue)); } return 0; diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 30a116472..1144f25ea 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -117,14 +117,16 @@ struct SDL_Window int w, h; Uint32 flags; - Uint16 *gamma; - int display; SDL_Renderer *renderer; void *userdata; void *driverdata; }; +#define FULLSCREEN_VISIBLE(W) \ + ((W->flags & SDL_WINDOW_FULLSCREEN) && \ + (W->flags & SDL_WINDOW_SHOWN) && \ + !(W->flags & SDL_WINDOW_MINIMIZED)) /* Define the SDL display structure This corresponds to physical monitors attached to the system. @@ -136,8 +138,13 @@ struct SDL_VideoDisplay SDL_DisplayMode *display_modes; SDL_DisplayMode desktop_mode; SDL_DisplayMode current_mode; + SDL_DisplayMode desired_mode; + SDL_DisplayMode *fullscreen_mode; SDL_Palette *palette; + Uint16 *gamma; + Uint16 *saved_gamma; /* (just offset into gamma) */ + int num_render_drivers; SDL_RenderDriver *render_drivers; @@ -174,6 +181,12 @@ struct SDL_VideoDevice /* * * */ /* Display functions */ + + /* Get a list of the available display modes. + * e.g. SDL_AddDisplayMode(_this->current_display, mode) + */ + void (*GetDisplayModes) (_THIS); + /* Setting the display mode is independent of creating windows, * so when the display mode is changed, all existing windows * should have their data updated accordingly, including the @@ -181,12 +194,18 @@ struct SDL_VideoDevice */ int (*SetDisplayMode) (_THIS, SDL_DisplayMode * mode); - /* Sets the color entries of the display palette to those in 'colors'. - The return value is 0 if all entries could be set properly or -1 - otherwise. - */ + /* Set the color entries of the display palette */ int (*SetDisplayPalette) (_THIS, SDL_Palette * palette); + /* Get the color entries of the display palette */ + int (*GetDisplayPalette) (_THIS, SDL_Palette * palette); + + /* Set the gamma ramp */ + int (*SetDisplayGammaRamp) (_THIS, Uint16 * ramp); + + /* Get the gamma ramp */ + int (*GetDisplayGammaRamp) (_THIS, Uint16 * ramp); + /* * * */ /* Window functions */ @@ -213,21 +232,6 @@ struct SDL_VideoDevice */ void (*VideoQuit) (_THIS); - /* * * */ - /* Gamma support */ - - /* Set the gamma correction directly (emulated with gamma ramps) */ - int (*SetGamma) (_THIS, float red, float green, float blue); - - /* Get the gamma correction directly (emulated with gamma ramps) */ - int (*GetGamma) (_THIS, float *red, float *green, float *blue); - - /* Set the gamma ramp */ - int (*SetGammaRamp) (_THIS, Uint16 * ramp); - - /* Get the gamma ramp */ - int (*GetGammaRamp) (_THIS, Uint16 * ramp); - /* * * */ /* OpenGL support */ @@ -405,7 +409,6 @@ extern VideoBootStrap glSDL_bootstrap; #endif #define SDL_CurrentDisplay (_this->displays[_this->current_display]) -#define SDL_CurrentWindow (SDL_CurrentDisplay.windows[0]) extern SDL_VideoDevice *SDL_GetVideoDevice(); extern int SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode); @@ -418,6 +421,11 @@ extern void SDL_AddRenderDriver(int displayIndex, extern SDL_Window *SDL_GetWindowFromID(SDL_WindowID windowID); extern SDL_VideoDisplay *SDL_GetDisplayFromWindow(SDL_Window * window); +extern void SDL_OnWindowShown(SDL_Window * window); +extern void SDL_OnWindowHidden(SDL_Window * window); +extern void SDL_OnWindowFocusGained(SDL_Window * window); +extern void SDL_OnWindowFocusLost(SDL_Window * window); + #endif /* _SDL_sysvideo_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 120c68990..4302c9ff4 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -267,13 +267,6 @@ SDL_VideoInit(const char *driver_name, Uint32 flags) return (-1); } - /* Sort the video modes */ - for (i = 0; i < _this->num_displays; ++i) { - SDL_qsort(_this->displays[i].display_modes, - _this->displays[i].num_display_modes, - sizeof(SDL_DisplayMode), cmpmodes); - } - /* The software renderer is always available */ for (i = 0; i < _this->num_displays; ++i) { if (_this->displays[i].num_render_drivers > 0) { @@ -398,7 +391,13 @@ int SDL_GetNumDisplayModes() { if (_this) { - return SDL_CurrentDisplay.num_display_modes; + SDL_VideoDisplay *display = &SDL_CurrentDisplay; + if (!display->num_display_modes && _this->GetDisplayModes) { + _this->GetDisplayModes(_this); + SDL_qsort(display->display_modes, display->num_display_modes, + sizeof(SDL_DisplayMode), cmpmodes); + } + return display->num_display_modes; } return 0; } @@ -460,7 +459,7 @@ SDL_GetClosestDisplayMode(const SDL_DisplayMode * mode, } match = NULL; - for (i = 0; i < SDL_CurrentDisplay.num_display_modes; ++i) { + for (i = 0; i < SDL_GetNumDisplayModes(); ++i) { current = &SDL_CurrentDisplay.display_modes[i]; if ((current->w && current->h) && @@ -602,7 +601,7 @@ SDL_SetDisplayMode(const SDL_DisplayMode * mode) /* Move any fullscreen windows into position */ for (i = 0; i < display->num_windows; ++i) { SDL_Window *window = &display->windows[i]; - if (window->flags & SDL_WINDOW_FULLSCREEN) { + if (FULLSCREEN_VISIBLE(window)) { SDL_SetWindowPosition(window->id, ((display_mode.w - window->w) / 2), ((display_mode.h - window->h) / 2)); @@ -612,6 +611,44 @@ SDL_SetDisplayMode(const SDL_DisplayMode * mode) return 0; } +int +SDL_SetFullscreenDisplayMode(const SDL_DisplayMode * mode) +{ + SDL_VideoDisplay *display; + int i; + + if (!_this) { + SDL_SetError("Video subsystem has not been initialized"); + return -1; + } + + display = &SDL_CurrentDisplay; + if (mode) { + SDL_GetClosestDisplayMode(mode, &display->desired_mode); + display->fullscreen_mode = &display->desired_mode; + } else { + display->fullscreen_mode = NULL; + } + + /* Actually set the mode if we have a fullscreen window visible */ + for (i = 0; i < display->num_windows; ++i) { + SDL_Window *window = &display->windows[i]; + if (FULLSCREEN_VISIBLE(window)) { + return SDL_SetDisplayMode(display->fullscreen_mode); + } + } + return 0; +} + +const SDL_DisplayMode * +SDL_GetFullscreenDisplayMode(void) +{ + if (_this) { + return SDL_CurrentDisplay.fullscreen_mode; + } + return NULL; +} + int SDL_SetDisplayPalette(const SDL_Color * colors, int firstcolor, int ncolors) { @@ -939,7 +976,7 @@ SDL_ShowWindow(SDL_WindowID windowID) return; } - window->flags |= SDL_WINDOW_SHOWN; + SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_SHOWN, 0, 0); if (_this->ShowWindow) { _this->ShowWindow(_this, window); @@ -955,7 +992,7 @@ SDL_HideWindow(SDL_WindowID windowID) return; } - window->flags &= ~SDL_WINDOW_SHOWN; + SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_HIDDEN, 0, 0); if (_this->HideWindow) { _this->HideWindow(_this, window); @@ -985,7 +1022,7 @@ SDL_MaximizeWindow(SDL_WindowID windowID) return; } - window->flags |= SDL_WINDOW_MAXIMIZED; + SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MAXIMIZED, 0, 0); if (_this->MaximizeWindow) { _this->MaximizeWindow(_this, window); @@ -1001,7 +1038,7 @@ SDL_MinimizeWindow(SDL_WindowID windowID) return; } - window->flags |= SDL_WINDOW_MINIMIZED; + SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MINIMIZED, 0, 0); if (_this->MinimizeWindow) { _this->MinimizeWindow(_this, window); @@ -1018,7 +1055,7 @@ SDL_RestoreWindow(SDL_WindowID windowID) return; } - window->flags &= ~(SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED); + SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_RESTORED, 0, 0); if (_this->RestoreWindow) { _this->RestoreWindow(_this, window); @@ -1057,6 +1094,43 @@ SDL_GetWindowGrab(SDL_WindowID windowID) return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0); } +void +SDL_OnWindowShown(SDL_Window * window) +{ +} + +void +SDL_OnWindowHidden(SDL_Window * window) +{ +} + +void +SDL_OnWindowFocusGained(SDL_Window * window) +{ + SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); + + if (window->flags & SDL_WINDOW_FULLSCREEN) { + SDL_SetDisplayMode(display->fullscreen_mode); + } + if (display->gamma && _this->SetDisplayGammaRamp) { + _this->SetDisplayGammaRamp(_this, display->gamma); + } +} + +void +SDL_OnWindowFocusLost(SDL_Window * window) +{ + SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); + + if (window->flags & SDL_WINDOW_FULLSCREEN) { + SDL_SetDisplayMode(NULL); + SDL_MinimizeWindow(window->id); + } + if (display->gamma && _this->SetDisplayGammaRamp) { + _this->SetDisplayGammaRamp(_this, display->saved_gamma); + } +} + void SDL_DestroyWindow(SDL_WindowID windowID) { @@ -1073,6 +1147,12 @@ SDL_DestroyWindow(SDL_WindowID windowID) if (window->id != windowID) { continue; } + if (window->flags & SDL_WINDOW_FULLSCREEN) { + SDL_SetDisplayMode(NULL); + } + if (display->gamma && _this->SetDisplayGammaRamp) { + _this->SetDisplayGammaRamp(_this, display->saved_gamma); + } if (window->flags & SDL_WINDOW_INPUT_GRABBED) { window->flags &= ~SDL_WINDOW_INPUT_GRABBED; _this->SetWindowGrab(_this, window); @@ -1086,9 +1166,6 @@ SDL_DestroyWindow(SDL_WindowID windowID) if (window->title) { SDL_free(window->title); } - if (window->gamma) { - SDL_free(window->gamma); - } if (j != display->num_windows - 1) { SDL_memcpy(&display->windows[i], &display->windows[i + 1], @@ -1868,6 +1945,12 @@ SDL_VideoQuit(void) SDL_FreePalette(display->palette); display->palette = NULL; } + if (display->gamma) { + SDL_free(display->gamma); + } + if (display->driverdata) { + SDL_free(display->driverdata); + } } if (_this->displays) { SDL_free(_this->displays); diff --git a/src/video/win32/SDL_win32events.c b/src/video/win32/SDL_win32events.c index 63f9a1af9..91c55b6ee 100644 --- a/src/video/win32/SDL_win32events.c +++ b/src/video/win32/SDL_win32events.c @@ -421,6 +421,18 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) switch (msg) { + case WM_SHOWWINDOW: + { + if (wParam) { + SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_SHOWN, 0, + 0); + } else { + SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_HIDDEN, 0, + 0); + } + } + break; + case WM_ACTIVATE: { int index; @@ -452,7 +464,6 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) ClipCursor(&rect); } } - /* FIXME: Restore mode state (mode, gamma) */ /* FIXME: Update keyboard state */ } else { if (keyboard && keyboard->focus == data->windowID) { @@ -467,7 +478,6 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MINIMIZED, 0, 0); } - /* FIXME: Restore desktop state (mode, gamma) */ } return (0); } diff --git a/src/video/win32/SDL_win32gamma.c b/src/video/win32/SDL_win32gamma.c new file mode 100644 index 000000000..775ffc514 --- /dev/null +++ b/src/video/win32/SDL_win32gamma.c @@ -0,0 +1,63 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2006 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_win32video.h" + + +int +WIN_SetDisplayGammaRamp(_THIS, Uint16 * ramp) +{ + SDL_DisplayData *data = (SDL_DisplayData *) SDL_CurrentDisplay.driverdata; + HDC hdc; + BOOL succeeded = FALSE; + + hdc = CreateDC(data->DeviceName, NULL, NULL, NULL); + if (hdc) { + succeeded = SetDeviceGammaRamp(hdc, ramp); + if (!succeeded) { + WIN_SetError("SetDeviceGammaRamp()"); + } + DeleteDC(hdc); + } + return succeeded ? 0 : -1; +} + +int +WIN_GetDisplayGammaRamp(_THIS, Uint16 * ramp) +{ + SDL_DisplayData *data = (SDL_DisplayData *) SDL_CurrentDisplay.driverdata; + HDC hdc; + BOOL succeeded = FALSE; + + hdc = CreateDC(data->DeviceName, NULL, NULL, NULL); + if (hdc) { + succeeded = GetDeviceGammaRamp(hdc, ramp); + if (!succeeded) { + WIN_SetError("GetDeviceGammaRamp()"); + } + DeleteDC(hdc); + } + return succeeded ? 0 : -1; +} + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/win32/SDL_win32gamma.h b/src/video/win32/SDL_win32gamma.h new file mode 100644 index 000000000..560e35906 --- /dev/null +++ b/src/video/win32/SDL_win32gamma.h @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2006 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_win32gamma_h +#define _SDL_win32gamma_h + +extern int WIN_SetDisplayGammaRamp(_THIS, Uint16 * ramp); +extern int WIN_GetDisplayGammaRamp(_THIS, Uint16 * ramp); + +#endif /* _SDL_win32gamma_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/win32/SDL_win32modes.c b/src/video/win32/SDL_win32modes.c index f58ddedc4..8a3efb682 100644 --- a/src/video/win32/SDL_win32modes.c +++ b/src/video/win32/SDL_win32modes.c @@ -24,12 +24,6 @@ #include "SDL_win32video.h" -typedef struct -{ - TCHAR DeviceName[32]; - DEVMODE DeviceMode; -} SDL_DisplayModeData; - /* FIXME: Each call to EnumDisplaySettings() takes about 6 ms on my laptop. With 500 or so modes, this takes almost 3 seconds to run! */ @@ -123,7 +117,7 @@ void WIN_InitModes(_THIS) { SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; - DWORD i, j, k; + DWORD i, j; DISPLAY_DEVICE device; device.cb = sizeof(device); @@ -143,6 +137,7 @@ WIN_InitModes(_THIS) for (j = 0;; ++j) { int index; SDL_VideoDisplay display; + SDL_DisplayData *displaydata; SDL_DisplayMode mode; if (!EnumDisplayDevices(DeviceName, j, &device, 0)) { @@ -157,19 +152,37 @@ WIN_InitModes(_THIS) if (!WIN_GetDisplayMode(DeviceName, ENUM_CURRENT_SETTINGS, &mode)) { break; } + + displaydata = + (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata)); + if (!displaydata) { + continue; + } + SDL_memcpy(displaydata->DeviceName, DeviceName, + sizeof(DeviceName)); + SDL_zero(display); display.desktop_mode = mode; display.current_mode = mode; - index = SDL_AddVideoDisplay(&display); - - for (k = 0;; ++k) { - if (!WIN_GetDisplayMode(DeviceName, k, &mode)) { - break; - } - if (!SDL_AddDisplayMode(index, &mode)) { - SDL_free(mode.driverdata); - } - } + display.driverdata = displaydata; + SDL_AddVideoDisplay(&display); + } + } +} + +void +WIN_GetDisplayModes(_THIS) +{ + SDL_DisplayData *data = (SDL_DisplayData *) SDL_CurrentDisplay.driverdata; + DWORD i; + SDL_DisplayMode mode; + + for (i = 0;; ++i) { + if (!WIN_GetDisplayMode(data->DeviceName, i, &mode)) { + break; + } + if (!SDL_AddDisplayMode(_this->current_display, &mode)) { + SDL_free(mode.driverdata); } } } diff --git a/src/video/win32/SDL_win32modes.h b/src/video/win32/SDL_win32modes.h index f3b3f9384..f7ef430e9 100644 --- a/src/video/win32/SDL_win32modes.h +++ b/src/video/win32/SDL_win32modes.h @@ -24,7 +24,19 @@ #ifndef _SDL_win32modes_h #define _SDL_win32modes_h +typedef struct +{ + TCHAR DeviceName[32]; +} SDL_DisplayData; + +typedef struct +{ + TCHAR DeviceName[32]; + DEVMODE DeviceMode; +} SDL_DisplayModeData; + extern void WIN_InitModes(_THIS); +extern void WIN_GetDisplayModes(_THIS); extern int WIN_SetDisplayMode(_THIS, SDL_DisplayMode * mode); extern void WIN_QuitModes(_THIS); diff --git a/src/video/win32/SDL_win32video.c b/src/video/win32/SDL_win32video.c index 5b5ba1721..7f913d74d 100644 --- a/src/video/win32/SDL_win32video.c +++ b/src/video/win32/SDL_win32video.c @@ -84,11 +84,11 @@ WIN_CreateDevice(int devindex) #if SDL_VIDEO_RENDER_D3D data->d3dDLL = LoadLibrary(TEXT("D3D9.DLL")); if (data->d3dDLL) { - IDirect3D9 *WINAPI(*D3DCreate) (UINT SDKVersion); + IDirect3D9 *(WINAPI * D3DCreate) (UINT SDKVersion); D3DCreate = - (IDirect3D9 * WINAPI(*)(UINT)) GetProcAddress(data->d3dDLL, - "Direct3DCreate9"); + (IDirect3D9 * (WINAPI *) (UINT)) GetProcAddress(data->d3dDLL, + "Direct3DCreate9"); if (D3DCreate) { data->d3d = D3DCreate(D3D_SDK_VERSION); } @@ -101,7 +101,10 @@ WIN_CreateDevice(int devindex) /* Set the function pointers */ device->VideoInit = WIN_VideoInit; + device->GetDisplayModes = WIN_GetDisplayModes; device->SetDisplayMode = WIN_SetDisplayMode; + device->SetDisplayGammaRamp = WIN_SetDisplayGammaRamp; + device->GetDisplayGammaRamp = WIN_GetDisplayGammaRamp; device->VideoQuit = WIN_VideoQuit; device->PumpEvents = WIN_PumpEvents; diff --git a/src/video/win32/SDL_win32video.h b/src/video/win32/SDL_win32video.h index 0422eff1f..a1f5033ac 100644 --- a/src/video/win32/SDL_win32video.h +++ b/src/video/win32/SDL_win32video.h @@ -36,6 +36,7 @@ #endif #include "SDL_win32events.h" +#include "SDL_win32gamma.h" #include "SDL_win32keyboard.h" #include "SDL_win32modes.h" #include "SDL_win32mouse.h" diff --git a/src/video/win32/SDL_win32window.c b/src/video/win32/SDL_win32window.c index 7a68f7781..0845c9705 100644 --- a/src/video/win32/SDL_win32window.c +++ b/src/video/win32/SDL_win32window.c @@ -22,6 +22,7 @@ #include "SDL_config.h" #include "../SDL_sysvideo.h" +#include "../../events/SDL_keyboard_c.h" #include "SDL_win32video.h" @@ -110,6 +111,14 @@ SetupWindowData(SDL_Window * window, HWND hwnd, BOOL created) int index = data->videodata->keyboard; window->flags |= SDL_WINDOW_KEYBOARD_FOCUS; SDL_SetKeyboardFocus(index, data->windowID); + + if (window->flags & SDL_WINDOW_INPUT_GRABBED) { + RECT rect; + GetClientRect(hwnd, &rect); + ClientToScreen(hwnd, (LPPOINT) & rect); + ClientToScreen(hwnd, (LPPOINT) & rect + 1); + ClipCursor(&rect); + } } /* All done! */ diff --git a/test/testsprite2.c b/test/testsprite2.c index 308c2bead..916ff6050 100644 --- a/test/testsprite2.c +++ b/test/testsprite2.c @@ -162,14 +162,7 @@ main(int argc, char *argv[]) SDL_zero(fullscreen_mode); fullscreen_mode.w = window_w; fullscreen_mode.h = window_h; - mode = &fullscreen_mode; - } else { - /* Set the desktop mode, we don't care what it is */ - mode = NULL; - } - if (SDL_SetDisplayMode(mode) < 0) { - fprintf(stderr, "Couldn't set display mode: %s\n", SDL_GetError()); - quit(2); + SDL_SetFullscreenDisplayMode(&fullscreen_mode); } /* Create the windows, initialize the renderers, and load the textures */ diff --git a/test/testwm2.c b/test/testwm2.c index efa2288ff..a5fc8bfcb 100644 --- a/test/testwm2.c +++ b/test/testwm2.c @@ -49,12 +49,6 @@ main(int argc, char *argv[]) } } - /* Set the desktop mode, we don't care what it is */ - if (SDL_SetDisplayMode(NULL) < 0) { - fprintf(stderr, "Couldn't set display mode: %s\n", SDL_GetError()); - quit(2); - } - /* Create the windows */ windows = (SDL_WindowID *) SDL_malloc(num_windows * sizeof(*windows)); if (!windows) {