From a9ff673e0a00e0c7d6a16ac104e4c71125e6b835 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 17 Dec 2008 07:17:54 +0000 Subject: [PATCH] * Implemented X11 fullscreen input grab * Progress towards being able to toggle in and out of fullscreen mode --- src/events/SDL_windowevents.c | 6 ++++ src/video/SDL_video.c | 58 +++++++++++++++---------------- src/video/win32/SDL_win32window.c | 23 ++++++++---- src/video/x11/SDL_x11window.c | 45 ++++++++++++++++++++---- 4 files changed, 90 insertions(+), 42 deletions(-) diff --git a/src/events/SDL_windowevents.c b/src/events/SDL_windowevents.c index 37b19376a..e72d37963 100644 --- a/src/events/SDL_windowevents.c +++ b/src/events/SDL_windowevents.c @@ -58,6 +58,12 @@ SDL_SendWindowEvent(SDL_WindowID windowID, Uint8 windowevent, int data1, if (window->flags & SDL_WINDOW_FULLSCREEN) { return 0; } + if (data1 == SDL_WINDOWPOS_UNDEFINED) { + data1 = window->x; + } + if (data2 == SDL_WINDOWPOS_UNDEFINED) { + data2 = window->y; + } if (data1 == window->x && data2 == window->y) { return 0; } diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index cebf089e4..6c57daddf 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -123,8 +123,7 @@ static VideoBootStrap *bootstrap[] = { static SDL_VideoDevice *_this = NULL; /* Various local functions */ -int SDL_VideoInit(const char *driver_name, Uint32 flags); -void SDL_VideoQuit(void); +static void SDL_UpdateWindowGrab(SDL_Window *window); static int cmpmodes(const void *A, const void *B) @@ -635,8 +634,7 @@ SDL_SetDisplayMode(const SDL_DisplayMode * mode) for (i = 0; i < display->num_windows; ++i) { SDL_Window *window = &display->windows[i]; if (FULLSCREEN_VISIBLE(window)) { - SDL_SetWindowPosition(window->id, SDL_WINDOWPOS_CENTERED, - SDL_WINDOWPOS_CENTERED); + SDL_SetWindowPosition(window->id, window->x, window->y); } } @@ -752,7 +750,8 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) const Uint32 allowed_flags = (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | - SDL_WINDOW_RESIZABLE); + SDL_WINDOW_RESIZABLE | + SDL_WINDOW_INPUT_GRABBED); SDL_VideoDisplay *display; SDL_Window window; int num_windows; @@ -766,11 +765,6 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) SDL_SetError("No OpenGL support in video driver"); return 0; } - /* Fullscreen windows don't have any window decorations */ - if (flags & SDL_WINDOW_FULLSCREEN) { - flags |= SDL_WINDOW_BORDERLESS; - flags &= ~SDL_WINDOW_RESIZABLE; - } SDL_zero(window); window.id = _this->next_object_id++; window.x = x; @@ -809,9 +803,8 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) if (flags & SDL_WINDOW_SHOWN) { SDL_ShowWindow(window.id); } - if (flags & SDL_WINDOW_INPUT_GRABBED) { - SDL_SetWindowGrab(window.id, 1); - } + SDL_UpdateWindowGrab(&window); + return window.id; } @@ -889,9 +882,8 @@ SDL_RecreateWindow(SDL_Window * window, Uint32 flags) if (flags & SDL_WINDOW_SHOWN) { SDL_ShowWindow(window->id); } - if (flags & SDL_WINDOW_INPUT_GRABBED) { - SDL_SetWindowGrab(window->id, 1); - } + SDL_UpdateWindowGrab(window); + return 0; } @@ -1004,19 +996,16 @@ SDL_SetWindowPosition(SDL_WindowID windowID, int x, int y) if (!window) { return; } - if (x == SDL_WINDOWPOS_CENTERED) { - window->x = (display->current_mode.w - window->w) / 2; - } else if (x != SDL_WINDOWPOS_UNDEFINED) { + if (x != SDL_WINDOWPOS_UNDEFINED) { window->x = x; } - if (y == SDL_WINDOWPOS_CENTERED) { - window->y = (display->current_mode.h - window->h) / 2; - } else if (y != SDL_WINDOWPOS_UNDEFINED) { + if (y != SDL_WINDOWPOS_UNDEFINED) { window->y = y; } if (_this->SetWindowPosition) { _this->SetWindowPosition(_this, window); } + SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MOVED, x, y); } void @@ -1082,11 +1071,11 @@ SDL_ShowWindow(SDL_WindowID windowID) if (!window || (window->flags & SDL_WINDOW_SHOWN)) { return; } - SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_SHOWN, 0, 0); if (_this->ShowWindow) { _this->ShowWindow(_this, window); } + SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_SHOWN, 0, 0); } void @@ -1097,11 +1086,11 @@ SDL_HideWindow(SDL_WindowID windowID) if (!window || !(window->flags & SDL_WINDOW_SHOWN)) { return; } - SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_HIDDEN, 0, 0); if (_this->HideWindow) { _this->HideWindow(_this, window); } + SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_HIDDEN, 0, 0); } void @@ -1125,11 +1114,11 @@ SDL_MaximizeWindow(SDL_WindowID windowID) if (!window || (window->flags & SDL_WINDOW_MAXIMIZED)) { return; } - SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MAXIMIZED, 0, 0); if (_this->MaximizeWindow) { _this->MaximizeWindow(_this, window); } + SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MAXIMIZED, 0, 0); } void @@ -1140,11 +1129,11 @@ SDL_MinimizeWindow(SDL_WindowID windowID) if (!window || (window->flags & SDL_WINDOW_MINIMIZED)) { return; } - SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MINIMIZED, 0, 0); if (_this->MinimizeWindow) { _this->MinimizeWindow(_this, window); } + SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MINIMIZED, 0, 0); } void @@ -1156,11 +1145,11 @@ SDL_RestoreWindow(SDL_WindowID windowID) || (window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) { return; } - SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_RESTORED, 0, 0); if (_this->RestoreWindow) { _this->RestoreWindow(_this, window); } + SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_RESTORED, 0, 0); } int @@ -1217,7 +1206,12 @@ SDL_SetWindowGrab(SDL_WindowID windowID, int mode) } else { window->flags &= ~SDL_WINDOW_INPUT_GRABBED; } + SDL_UpdateWindowGrab(window); +} +static void +SDL_UpdateWindowGrab(SDL_Window *window) +{ if ((window->flags & SDL_WINDOW_INPUT_FOCUS) && _this->SetWindowGrab) { _this->SetWindowGrab(_this, window); } @@ -1237,11 +1231,17 @@ SDL_GetWindowGrab(SDL_WindowID windowID) void SDL_OnWindowShown(SDL_Window * window) { + if (window->flags & SDL_WINDOW_FULLSCREEN) { + SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0); + } } void SDL_OnWindowHidden(SDL_Window * window) { + if (window->flags & SDL_WINDOW_FULLSCREEN) { + SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0); + } } void @@ -1265,7 +1265,7 @@ SDL_OnWindowFocusGained(SDL_Window * window) if (display->gamma && _this->SetDisplayGammaRamp) { _this->SetDisplayGammaRamp(_this, display->gamma); } - if ((window->flags & SDL_WINDOW_INPUT_GRABBED) && _this->SetWindowGrab) { + if ((window->flags & (SDL_WINDOW_INPUT_GRABBED|SDL_WINDOW_FULLSCREEN)) && _this->SetWindowGrab) { _this->SetWindowGrab(_this, window); } } @@ -1282,7 +1282,7 @@ SDL_OnWindowFocusLost(SDL_Window * window) if (display->gamma && _this->SetDisplayGammaRamp) { _this->SetDisplayGammaRamp(_this, display->saved_gamma); } - if ((window->flags & SDL_WINDOW_INPUT_GRABBED) && _this->SetWindowGrab) { + if ((window->flags & (SDL_WINDOW_INPUT_GRABBED|SDL_WINDOW_FULLSCREEN)) && _this->SetWindowGrab) { _this->SetWindowGrab(_this, window); } } diff --git a/src/video/win32/SDL_win32window.c b/src/video/win32/SDL_win32window.c index 9813f53ed..aee25423a 100644 --- a/src/video/win32/SDL_win32window.c +++ b/src/video/win32/SDL_win32window.c @@ -159,12 +159,12 @@ WIN_CreateWindow(_THIS, SDL_Window * window) int x, y; int w, h; - if (window->flags & SDL_WINDOW_BORDERLESS) { + if (window->flags & (SDL_WINDOW_BORDERLESS|SDL_WINDOW_FULLSCREEN)) { style |= WS_POPUP; } else { style |= (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX); } - if (window->flags & SDL_WINDOW_RESIZABLE) { + if ((window->flags & SDL_WINDOW_RESIZABLE) && !(window->flags & SDL_WINDOW_FULLSCREEN)) { style |= (WS_THICKFRAME | WS_MAXIMIZEBOX); } @@ -182,14 +182,14 @@ WIN_CreateWindow(_THIS, SDL_Window * window) w = (rect.right - rect.left); h = (rect.bottom - rect.top); - if (window->x == SDL_WINDOWPOS_CENTERED) { + if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->x == SDL_WINDOWPOS_CENTERED) { x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2; } else if (window->x == SDL_WINDOWPOS_UNDEFINED) { x = CW_USEDEFAULT; } else { x = window->x + rect.left; } - if (window->y == SDL_WINDOWPOS_CENTERED) { + if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->y == SDL_WINDOWPOS_CENTERED) { y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2; } else if (window->y == SDL_WINDOWPOS_UNDEFINED) { y = CW_USEDEFAULT; @@ -331,8 +331,17 @@ WIN_SetWindowPosition(_THIS, SDL_Window * window) AdjustWindowRectEx(&rect, style, (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL), 0); - x = window->x + rect.left; - y = window->y + rect.top; + + if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->x == SDL_WINDOWPOS_CENTERED) { + x = (GetSystemMetrics(SM_CXSCREEN) - window->w) / 2; + } else { + x = window->x + rect.left; + } + if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->y == SDL_WINDOWPOS_CENTERED) { + y = (GetSystemMetrics(SM_CYSCREEN) - window->h) / 2; + } else { + y = window->y + rect.top; + } SetWindowPos(hwnd, top, x, y, 0, 0, (SWP_NOCOPYBITS | SWP_NOSIZE)); } @@ -425,7 +434,7 @@ 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_INPUT_GRABBED|SDL_WINDOW_FULLSCREEN)) && (window->flags & SDL_WINDOW_INPUT_FOCUS)) { RECT rect; GetClientRect(hwnd, &rect); diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index f78c8c549..9510f9829 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -287,7 +287,7 @@ X11_CreateWindow(_THIS, SDL_Window * window) visual, AllocNone); } - if (window->x == SDL_WINDOWPOS_CENTERED) { + if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->x == SDL_WINDOWPOS_CENTERED) { x = (DisplayWidth(data->display, displaydata->screen) - window->w) / 2; } else if (window->x == SDL_WINDOWPOS_UNDEFINED) { @@ -295,7 +295,7 @@ X11_CreateWindow(_THIS, SDL_Window * window) } else { x = window->x; } - if (window->y == SDL_WINDOWPOS_CENTERED) { + if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->y == SDL_WINDOWPOS_CENTERED) { y = (DisplayHeight(data->display, displaydata->screen) - window->h) / 2; } else if (window->y == SDL_WINDOWPOS_UNDEFINED) { @@ -321,7 +321,7 @@ X11_CreateWindow(_THIS, SDL_Window * window) sizehints = XAllocSizeHints(); if (sizehints) { - if (window->flags & SDL_WINDOW_RESIZABLE) { + if ((window->flags & SDL_WINDOW_RESIZABLE) && !(window->flags & SDL_WINDOW_FULLSCREEN)) { sizehints->min_width = 32; sizehints->min_height = 32; sizehints->max_height = 4096; @@ -342,7 +342,7 @@ X11_CreateWindow(_THIS, SDL_Window * window) XFree(sizehints); } - if (window->flags & SDL_WINDOW_BORDERLESS) { + if (window->flags & (SDL_WINDOW_BORDERLESS|SDL_WINDOW_FULLSCREEN)) { SDL_bool set; Atom WM_HINTS; @@ -601,8 +601,19 @@ X11_SetWindowPosition(_THIS, SDL_Window * window) SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->driverdata; Display *display = data->videodata->display; + int x, y; - XMoveWindow(display, data->window, window->x, window->y); + if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->x == SDL_WINDOWPOS_CENTERED) { + x = (DisplayWidth(display, displaydata->screen) - window->w) / 2; + } else { + x = window->x; + } + if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->y == SDL_WINDOWPOS_CENTERED) { + y = (DisplayHeight(display, displaydata->screen) - window->h) / 2; + } else { + y = window->y; + } + XMoveWindow(display, data->window, x, y); } void @@ -662,7 +673,29 @@ X11_RestoreWindow(_THIS, SDL_Window * window) void X11_SetWindowGrab(_THIS, SDL_Window * window) { - /* FIXME */ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + Display *display = data->videodata->display; + + if ((window->flags & (SDL_WINDOW_INPUT_GRABBED|SDL_WINDOW_FULLSCREEN)) && + (window->flags & SDL_WINDOW_INPUT_FOCUS)) { + /* Try to grab the mouse */ + for ( ; ; ) { + int result = XGrabPointer(display, data->window, True, 0, GrabModeAsync, GrabModeAsync, data->window, None, CurrentTime); + if ( result == GrabSuccess ) { + break; + } + SDL_Delay(100); + } + + /* Raise the window if we grab the mouse */ + XRaiseWindow(display, data->window); + + /* Now grab the keyboard */ + XGrabKeyboard(display, data->window, True, GrabModeAsync, GrabModeAsync, CurrentTime); + } else { + XUngrabPointer(display, CurrentTime); + XUngrabKeyboard(display, CurrentTime); + } } void