From e7293b1976b6243ab45cad4ca0033f258be10744 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 9 Jul 2006 18:09:16 +0000 Subject: [PATCH] The general code handles restoring video mode/gamma/etc. when the window loses focus. Support for changing fullscreen/windowed mode in progress. --- include/SDL_video.h | 4 +- src/SDL_compat.c | 15 +++- src/events/SDL_windowevents.c | 8 +- src/video/SDL_gamma.c | 8 +- src/video/SDL_sysvideo.h | 7 +- src/video/SDL_video.c | 130 +++++++++++++++++++++++------- src/video/win32/SDL_win32events.c | 17 +--- src/video/win32/SDL_win32window.c | 23 +++--- 8 files changed, 139 insertions(+), 73 deletions(-) diff --git a/include/SDL_video.h b/include/SDL_video.h index 2e7182c2b..116907a13 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -125,7 +125,7 @@ typedef enum SDL_WINDOW_MINIMIZED = 0x00000020, /**< minimized */ SDL_WINDOW_MAXIMIZED = 0x00000040, /**< maximized */ SDL_WINDOW_INPUT_GRABBED = 0x00000100, /**< window has grabbed input focus */ - SDL_WINDOW_KEYBOARD_FOCUS = 0x00000200, /**< window has keyboard focus */ + SDL_WINDOW_INPUT_FOCUS = 0x00000200, /**< window has input focus */ SDL_WINDOW_MOUSE_FOCUS = 0x00000400, /**< window has mouse focus */ } SDL_WindowFlags; @@ -734,7 +734,7 @@ extern DECLSPEC void SDLCALL SDL_HideWindow(SDL_WindowID windowID); /** * \fn void SDL_RaiseWindow(SDL_WindowID windowID) * - * \brief Raise the window so it's above other windows. + * \brief Raise the window above other windows and set the input focus. */ extern DECLSPEC void SDLCALL SDL_RaiseWindow(SDL_WindowID windowID); diff --git a/src/SDL_compat.c b/src/SDL_compat.c index 2811fd8fd..3a88534ef 100644 --- a/src/SDL_compat.c +++ b/src/SDL_compat.c @@ -699,7 +699,18 @@ SDL_WM_IconifyWindow(void) int SDL_WM_ToggleFullScreen(SDL_Surface * surface) { - return 0; + if (SDL_GetWindowFlags(SDL_VideoWindow) & SDL_WINDOW_FULLSCREEN) { + if (SDL_SetWindowFullscreen(SDL_VideoWindow, 0) < 0) { + return 0; + } + SDL_PublicSurface->flags &= ~SDL_FULLSCREEN; + } else { + if (SDL_SetWindowFullscreen(SDL_VideoWindow, 1) < 0) { + return 0; + } + SDL_PublicSurface->flags |= SDL_FULLSCREEN; + } + return 1; } SDL_GrabMode @@ -727,7 +738,7 @@ SDL_GetAppState(void) if ((flags & SDL_WINDOW_SHOWN) && !(flags & SDL_WINDOW_MINIMIZED)) { state |= SDL_APPACTIVE; } - if (flags & SDL_WINDOW_KEYBOARD_FOCUS) { + if (flags & SDL_WINDOW_INPUT_FOCUS) { state |= SDL_APPINPUTFOCUS; } if (flags & SDL_WINDOW_MOUSE_FOCUS) { diff --git a/src/events/SDL_windowevents.c b/src/events/SDL_windowevents.c index 7b0da9ee9..9f3eeac27 100644 --- a/src/events/SDL_windowevents.c +++ b/src/events/SDL_windowevents.c @@ -100,17 +100,17 @@ SDL_SendWindowEvent(SDL_WindowID windowID, Uint8 windowevent, int data1, window->flags &= ~SDL_WINDOW_MOUSE_FOCUS; break; case SDL_WINDOWEVENT_FOCUS_GAINED: - if (window->flags & SDL_WINDOW_KEYBOARD_FOCUS) { + if (window->flags & SDL_WINDOW_INPUT_FOCUS) { return 0; } - window->flags |= SDL_WINDOW_KEYBOARD_FOCUS; + window->flags |= SDL_WINDOW_INPUT_FOCUS; SDL_OnWindowFocusGained(window); break; case SDL_WINDOWEVENT_FOCUS_LOST: - if (!(window->flags & SDL_WINDOW_KEYBOARD_FOCUS)) { + if (!(window->flags & SDL_WINDOW_INPUT_FOCUS)) { return 0; } - window->flags &= ~SDL_WINDOW_KEYBOARD_FOCUS; + window->flags &= ~SDL_WINDOW_INPUT_FOCUS; SDL_OnWindowFocusLost(window); break; } diff --git a/src/video/SDL_gamma.c b/src/video/SDL_gamma.c index 283101347..cd1dd1bc2 100644 --- a/src/video/SDL_gamma.c +++ b/src/video/SDL_gamma.c @@ -152,8 +152,12 @@ SDL_SetGammaRamp(const Uint16 * red, const Uint16 * green, /* Try to set the gamma ramp in the driver */ succeeded = -1; if (_this && _this->SetDisplayGammaRamp) { - succeeded = - _this->SetDisplayGammaRamp(_this, SDL_CurrentDisplay.gamma); + if (SDL_GetFocusWindow()) { + succeeded = + _this->SetDisplayGammaRamp(_this, SDL_CurrentDisplay.gamma); + } else { + succeeded = 0; + } } else { SDL_SetError("Gamma ramp manipulation not supported"); } diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 1144f25ea..5a31d56ae 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -124,9 +124,9 @@ struct SDL_Window void *driverdata; }; #define FULLSCREEN_VISIBLE(W) \ - ((W->flags & SDL_WINDOW_FULLSCREEN) && \ - (W->flags & SDL_WINDOW_SHOWN) && \ - !(W->flags & SDL_WINDOW_MINIMIZED)) + (((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. @@ -425,6 +425,7 @@ 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); +extern SDL_WindowID SDL_GetFocusWindow(void); #endif /* _SDL_sysvideo_h */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 4302c9ff4..0ea0b3b39 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -712,6 +712,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED | SDL_WINDOW_INPUT_GRABBED); + SDL_VideoDisplay *display; SDL_Window window; int num_windows; SDL_Window *windows; @@ -724,14 +725,8 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) SDL_zero(window); window.id = _this->next_object_id++; window.title = title ? SDL_strdup(title) : NULL; - if (flags & SDL_WINDOW_FULLSCREEN) { - const SDL_DisplayMode *mode = &SDL_CurrentDisplay.current_mode; - window.x = (mode->w - w) / 2; - window.y = (mode->h - h) / 2; - } else { - window.x = x; - window.y = y; - } + window.x = x; + window.y = y; window.w = w; window.h = h; window.flags = (flags & allowed_flags); @@ -744,10 +739,10 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) return 0; } - num_windows = SDL_CurrentDisplay.num_windows; + display = &SDL_CurrentDisplay; + num_windows = display->num_windows; windows = - SDL_realloc(SDL_CurrentDisplay.windows, - (num_windows + 1) * sizeof(*windows)); + SDL_realloc(display->windows, (num_windows + 1) * sizeof(*windows)); if (!windows) { if (_this->DestroyWindow) { _this->DestroyWindow(_this, &window); @@ -758,8 +753,20 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) return 0; } windows[num_windows] = window; - SDL_CurrentDisplay.windows = windows; - SDL_CurrentDisplay.num_windows++; + display->windows = windows; + display->num_windows++; + + if (FULLSCREEN_VISIBLE(&window)) { + /* Hide any other fullscreen windows */ + int i; + for (i = 0; i < display->num_windows; ++i) { + SDL_Window *other = &display->windows[i]; + if (other->id != window.id && FULLSCREEN_VISIBLE(other)) { + SDL_MinimizeWindow(other->id); + } + } + SDL_SetDisplayMode(display->fullscreen_mode); + } return window.id; } @@ -767,6 +774,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) SDL_WindowID SDL_CreateWindowFrom(const void *data) { + SDL_VideoDisplay *display; SDL_Window window; int num_windows; SDL_Window *windows; @@ -785,10 +793,10 @@ SDL_CreateWindowFrom(const void *data) return 0; } - num_windows = SDL_CurrentDisplay.num_windows; + display = &SDL_CurrentDisplay; + num_windows = display->num_windows; windows = - SDL_realloc(SDL_CurrentDisplay.windows, - (num_windows + 1) * sizeof(*windows)); + SDL_realloc(display->windows, (num_windows + 1) * sizeof(*windows)); if (!windows) { if (_this->DestroyWindow) { _this->DestroyWindow(_this, &window); @@ -799,8 +807,8 @@ SDL_CreateWindowFrom(const void *data) return 0; } windows[num_windows] = window; - SDL_CurrentDisplay.windows = windows; - SDL_CurrentDisplay.num_windows++; + display->windows = windows; + display->num_windows++; return window.id; } @@ -1062,6 +1070,48 @@ SDL_RestoreWindow(SDL_WindowID windowID) } } +int +SDL_SetWindowFullscreen(SDL_WindowID windowID, int fullscreen) +{ + SDL_Window *window = SDL_GetWindowFromID(windowID); + + if (!window) { + return -1; + } + + if (fullscreen) { + fullscreen = SDL_WINDOW_FULLSCREEN; + } + if ((window->flags & SDL_WINDOW_FULLSCREEN) == fullscreen) { + return 0; + } + + if (fullscreen) { + window->flags |= SDL_WINDOW_FULLSCREEN; + + if (FULLSCREEN_VISIBLE(window)) { + SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); + + /* Hide any other fullscreen windows */ + int i; + for (i = 0; i < display->num_windows; ++i) { + SDL_Window *other = &display->windows[i]; + if (other->id != windowID && FULLSCREEN_VISIBLE(other)) { + SDL_MinimizeWindow(other->id); + } + } + + SDL_SetDisplayMode(display->fullscreen_mode); + } + } else { + window->flags &= ~SDL_WINDOW_FULLSCREEN; + + if (FULLSCREEN_VISIBLE(window)) { + SDL_SetDisplayMode(NULL); + } + } +} + void SDL_SetWindowGrab(SDL_WindowID windowID, int mode) { @@ -1077,7 +1127,7 @@ SDL_SetWindowGrab(SDL_WindowID windowID, int mode) window->flags &= ~SDL_WINDOW_INPUT_GRABBED; } - if (_this->SetWindowGrab) { + if ((window->flags & SDL_WINDOW_INPUT_FOCUS) && _this->SetWindowGrab) { _this->SetWindowGrab(_this, window); } } @@ -1115,6 +1165,9 @@ SDL_OnWindowFocusGained(SDL_Window * window) if (display->gamma && _this->SetDisplayGammaRamp) { _this->SetDisplayGammaRamp(_this, display->gamma); } + if ((window->flags & SDL_WINDOW_INPUT_GRABBED) && _this->SetWindowGrab) { + _this->SetWindowGrab(_this, window); + } } void @@ -1123,12 +1176,36 @@ SDL_OnWindowFocusLost(SDL_Window * window) SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); if (window->flags & SDL_WINDOW_FULLSCREEN) { - SDL_SetDisplayMode(NULL); SDL_MinimizeWindow(window->id); + SDL_SetDisplayMode(NULL); } if (display->gamma && _this->SetDisplayGammaRamp) { _this->SetDisplayGammaRamp(_this, display->saved_gamma); } + if ((window->flags & SDL_WINDOW_INPUT_GRABBED) && _this->SetWindowGrab) { + _this->SetWindowGrab(_this, window); + } +} + +SDL_WindowID +SDL_GetFocusWindow(void) +{ + SDL_VideoDisplay *display; + int i; + + if (!_this) { + return 0; + } + + display = &SDL_CurrentDisplay; + for (i = 0; i < display->num_windows; ++i) { + SDL_Window *window = &display->windows[i]; + + if (window->flags & SDL_WINDOW_INPUT_FOCUS) { + return window->id; + } + } + return 0; } void @@ -1140,6 +1217,9 @@ SDL_DestroyWindow(SDL_WindowID windowID) return; } + /* Restore video mode, etc. */ + SDL_SendWindowEvent(windowID, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0); + for (i = 0; i < _this->num_displays; ++i) { SDL_VideoDisplay *display = &_this->displays[i]; for (j = 0; j < display->num_windows; ++j) { @@ -1147,16 +1227,6 @@ 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); - } if (window->renderer) { SDL_DestroyRenderer(window->id); } diff --git a/src/video/win32/SDL_win32events.c b/src/video/win32/SDL_win32events.c index 91c55b6ee..c2ce5feca 100644 --- a/src/video/win32/SDL_win32events.c +++ b/src/video/win32/SDL_win32events.c @@ -453,26 +453,11 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) } if (keyboard && keyboard->focus != data->windowID) { SDL_SetKeyboardFocus(index, data->windowID); - - if (SDL_GetWindowFlags(data->windowID) & - SDL_WINDOW_INPUT_GRABBED) { - RECT rect; - - GetClientRect(hwnd, &rect); - ClientToScreen(hwnd, (LPPOINT) & rect); - ClientToScreen(hwnd, (LPPOINT) & rect + 1); - ClipCursor(&rect); - } } /* FIXME: Update keyboard state */ } else { if (keyboard && keyboard->focus == data->windowID) { SDL_SetKeyboardFocus(index, 0); - - if (SDL_GetWindowFlags(data->windowID) & - SDL_WINDOW_INPUT_GRABBED) { - ClipCursor(NULL); - } } if (minimized) { SDL_SendWindowEvent(data->windowID, @@ -782,7 +767,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) window_flags = SDL_GetWindowFlags(data->windowID); if ((window_flags & SDL_WINDOW_INPUT_GRABBED) && - (window_flags & SDL_WINDOW_KEYBOARD_FOCUS)) { + (window_flags & SDL_WINDOW_INPUT_FOCUS)) { ClipCursor(&rect); } diff --git a/src/video/win32/SDL_win32window.c b/src/video/win32/SDL_win32window.c index 0845c9705..20616cd34 100644 --- a/src/video/win32/SDL_win32window.c +++ b/src/video/win32/SDL_win32window.c @@ -109,7 +109,7 @@ SetupWindowData(SDL_Window * window, HWND hwnd, BOOL created) } if (GetFocus() == hwnd) { int index = data->videodata->keyboard; - window->flags |= SDL_WINDOW_KEYBOARD_FOCUS; + window->flags |= SDL_WINDOW_INPUT_FOCUS; SDL_SetKeyboardFocus(index, data->windowID); if (window->flags & SDL_WINDOW_INPUT_GRABBED) { @@ -390,20 +390,15 @@ WIN_SetWindowGrab(_THIS, SDL_Window * window) { HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; - if (window->flags & SDL_WINDOW_INPUT_GRABBED) { - if (window->flags & SDL_WINDOW_KEYBOARD_FOCUS) { - RECT rect; - GetClientRect(hwnd, &rect); - ClientToScreen(hwnd, (LPPOINT) & rect); - ClientToScreen(hwnd, (LPPOINT) & rect + 1); - ClipCursor(&rect); - } else { - SetFocus(hwnd); - } + if ((window->flags & SDL_WINDOW_INPUT_GRABBED) && + (window->flags & SDL_WINDOW_INPUT_FOCUS)) { + RECT rect; + GetClientRect(hwnd, &rect); + ClientToScreen(hwnd, (LPPOINT) & rect); + ClientToScreen(hwnd, (LPPOINT) & rect + 1); + ClipCursor(&rect); } else { - if (window->flags & SDL_WINDOW_KEYBOARD_FOCUS) { - ClipCursor(NULL); - } + ClipCursor(NULL); } }