Commit c0775dd4 authored by Sam Lantinga's avatar Sam Lantinga

* Implemented X11 fullscreen input grab

* Progress towards being able to toggle in and out of fullscreen mode

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%403337
parent 67426e7b
...@@ -58,6 +58,12 @@ SDL_SendWindowEvent(SDL_WindowID windowID, Uint8 windowevent, int data1, ...@@ -58,6 +58,12 @@ SDL_SendWindowEvent(SDL_WindowID windowID, Uint8 windowevent, int data1,
if (window->flags & SDL_WINDOW_FULLSCREEN) { if (window->flags & SDL_WINDOW_FULLSCREEN) {
return 0; 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) { if (data1 == window->x && data2 == window->y) {
return 0; return 0;
} }
......
...@@ -123,8 +123,7 @@ static VideoBootStrap *bootstrap[] = { ...@@ -123,8 +123,7 @@ static VideoBootStrap *bootstrap[] = {
static SDL_VideoDevice *_this = NULL; static SDL_VideoDevice *_this = NULL;
/* Various local functions */ /* Various local functions */
int SDL_VideoInit(const char *driver_name, Uint32 flags); static void SDL_UpdateWindowGrab(SDL_Window *window);
void SDL_VideoQuit(void);
static int static int
cmpmodes(const void *A, const void *B) cmpmodes(const void *A, const void *B)
...@@ -635,8 +634,7 @@ SDL_SetDisplayMode(const SDL_DisplayMode * mode) ...@@ -635,8 +634,7 @@ SDL_SetDisplayMode(const SDL_DisplayMode * mode)
for (i = 0; i < display->num_windows; ++i) { for (i = 0; i < display->num_windows; ++i) {
SDL_Window *window = &display->windows[i]; SDL_Window *window = &display->windows[i];
if (FULLSCREEN_VISIBLE(window)) { if (FULLSCREEN_VISIBLE(window)) {
SDL_SetWindowPosition(window->id, SDL_WINDOWPOS_CENTERED, SDL_SetWindowPosition(window->id, window->x, window->y);
SDL_WINDOWPOS_CENTERED);
} }
} }
...@@ -752,7 +750,8 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) ...@@ -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 | const Uint32 allowed_flags = (SDL_WINDOW_FULLSCREEN |
SDL_WINDOW_OPENGL | SDL_WINDOW_OPENGL |
SDL_WINDOW_BORDERLESS | SDL_WINDOW_BORDERLESS |
SDL_WINDOW_RESIZABLE); SDL_WINDOW_RESIZABLE |
SDL_WINDOW_INPUT_GRABBED);
SDL_VideoDisplay *display; SDL_VideoDisplay *display;
SDL_Window window; SDL_Window window;
int num_windows; int num_windows;
...@@ -766,11 +765,6 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) ...@@ -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"); SDL_SetError("No OpenGL support in video driver");
return 0; 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); SDL_zero(window);
window.id = _this->next_object_id++; window.id = _this->next_object_id++;
window.x = x; window.x = x;
...@@ -809,9 +803,8 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) ...@@ -809,9 +803,8 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
if (flags & SDL_WINDOW_SHOWN) { if (flags & SDL_WINDOW_SHOWN) {
SDL_ShowWindow(window.id); SDL_ShowWindow(window.id);
} }
if (flags & SDL_WINDOW_INPUT_GRABBED) { SDL_UpdateWindowGrab(&window);
SDL_SetWindowGrab(window.id, 1);
}
return window.id; return window.id;
} }
...@@ -889,9 +882,8 @@ SDL_RecreateWindow(SDL_Window * window, Uint32 flags) ...@@ -889,9 +882,8 @@ SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
if (flags & SDL_WINDOW_SHOWN) { if (flags & SDL_WINDOW_SHOWN) {
SDL_ShowWindow(window->id); SDL_ShowWindow(window->id);
} }
if (flags & SDL_WINDOW_INPUT_GRABBED) { SDL_UpdateWindowGrab(window);
SDL_SetWindowGrab(window->id, 1);
}
return 0; return 0;
} }
...@@ -1004,19 +996,16 @@ SDL_SetWindowPosition(SDL_WindowID windowID, int x, int y) ...@@ -1004,19 +996,16 @@ SDL_SetWindowPosition(SDL_WindowID windowID, int x, int y)
if (!window) { if (!window) {
return; return;
} }
if (x == SDL_WINDOWPOS_CENTERED) { if (x != SDL_WINDOWPOS_UNDEFINED) {
window->x = (display->current_mode.w - window->w) / 2;
} else if (x != SDL_WINDOWPOS_UNDEFINED) {
window->x = x; window->x = x;
} }
if (y == SDL_WINDOWPOS_CENTERED) { if (y != SDL_WINDOWPOS_UNDEFINED) {
window->y = (display->current_mode.h - window->h) / 2;
} else if (y != SDL_WINDOWPOS_UNDEFINED) {
window->y = y; window->y = y;
} }
if (_this->SetWindowPosition) { if (_this->SetWindowPosition) {
_this->SetWindowPosition(_this, window); _this->SetWindowPosition(_this, window);
} }
SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MOVED, x, y);
} }
void void
...@@ -1082,11 +1071,11 @@ SDL_ShowWindow(SDL_WindowID windowID) ...@@ -1082,11 +1071,11 @@ SDL_ShowWindow(SDL_WindowID windowID)
if (!window || (window->flags & SDL_WINDOW_SHOWN)) { if (!window || (window->flags & SDL_WINDOW_SHOWN)) {
return; return;
} }
SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_SHOWN, 0, 0);
if (_this->ShowWindow) { if (_this->ShowWindow) {
_this->ShowWindow(_this, window); _this->ShowWindow(_this, window);
} }
SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_SHOWN, 0, 0);
} }
void void
...@@ -1097,11 +1086,11 @@ SDL_HideWindow(SDL_WindowID windowID) ...@@ -1097,11 +1086,11 @@ SDL_HideWindow(SDL_WindowID windowID)
if (!window || !(window->flags & SDL_WINDOW_SHOWN)) { if (!window || !(window->flags & SDL_WINDOW_SHOWN)) {
return; return;
} }
SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_HIDDEN, 0, 0);
if (_this->HideWindow) { if (_this->HideWindow) {
_this->HideWindow(_this, window); _this->HideWindow(_this, window);
} }
SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_HIDDEN, 0, 0);
} }
void void
...@@ -1125,11 +1114,11 @@ SDL_MaximizeWindow(SDL_WindowID windowID) ...@@ -1125,11 +1114,11 @@ SDL_MaximizeWindow(SDL_WindowID windowID)
if (!window || (window->flags & SDL_WINDOW_MAXIMIZED)) { if (!window || (window->flags & SDL_WINDOW_MAXIMIZED)) {
return; return;
} }
SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
if (_this->MaximizeWindow) { if (_this->MaximizeWindow) {
_this->MaximizeWindow(_this, window); _this->MaximizeWindow(_this, window);
} }
SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
} }
void void
...@@ -1140,11 +1129,11 @@ SDL_MinimizeWindow(SDL_WindowID windowID) ...@@ -1140,11 +1129,11 @@ SDL_MinimizeWindow(SDL_WindowID windowID)
if (!window || (window->flags & SDL_WINDOW_MINIMIZED)) { if (!window || (window->flags & SDL_WINDOW_MINIMIZED)) {
return; return;
} }
SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
if (_this->MinimizeWindow) { if (_this->MinimizeWindow) {
_this->MinimizeWindow(_this, window); _this->MinimizeWindow(_this, window);
} }
SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
} }
void void
...@@ -1156,11 +1145,11 @@ SDL_RestoreWindow(SDL_WindowID windowID) ...@@ -1156,11 +1145,11 @@ SDL_RestoreWindow(SDL_WindowID windowID)
|| (window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) { || (window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) {
return; return;
} }
SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_RESTORED, 0, 0);
if (_this->RestoreWindow) { if (_this->RestoreWindow) {
_this->RestoreWindow(_this, window); _this->RestoreWindow(_this, window);
} }
SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_RESTORED, 0, 0);
} }
int int
...@@ -1217,7 +1206,12 @@ SDL_SetWindowGrab(SDL_WindowID windowID, int mode) ...@@ -1217,7 +1206,12 @@ SDL_SetWindowGrab(SDL_WindowID windowID, int mode)
} else { } else {
window->flags &= ~SDL_WINDOW_INPUT_GRABBED; 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) { if ((window->flags & SDL_WINDOW_INPUT_FOCUS) && _this->SetWindowGrab) {
_this->SetWindowGrab(_this, window); _this->SetWindowGrab(_this, window);
} }
...@@ -1237,11 +1231,17 @@ SDL_GetWindowGrab(SDL_WindowID windowID) ...@@ -1237,11 +1231,17 @@ SDL_GetWindowGrab(SDL_WindowID windowID)
void void
SDL_OnWindowShown(SDL_Window * window) SDL_OnWindowShown(SDL_Window * window)
{ {
if (window->flags & SDL_WINDOW_FULLSCREEN) {
SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
}
} }
void void
SDL_OnWindowHidden(SDL_Window * window) SDL_OnWindowHidden(SDL_Window * window)
{ {
if (window->flags & SDL_WINDOW_FULLSCREEN) {
SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
}
} }
void void
...@@ -1265,7 +1265,7 @@ SDL_OnWindowFocusGained(SDL_Window * window) ...@@ -1265,7 +1265,7 @@ SDL_OnWindowFocusGained(SDL_Window * window)
if (display->gamma && _this->SetDisplayGammaRamp) { if (display->gamma && _this->SetDisplayGammaRamp) {
_this->SetDisplayGammaRamp(_this, display->gamma); _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); _this->SetWindowGrab(_this, window);
} }
} }
...@@ -1282,7 +1282,7 @@ SDL_OnWindowFocusLost(SDL_Window * window) ...@@ -1282,7 +1282,7 @@ SDL_OnWindowFocusLost(SDL_Window * window)
if (display->gamma && _this->SetDisplayGammaRamp) { if (display->gamma && _this->SetDisplayGammaRamp) {
_this->SetDisplayGammaRamp(_this, display->saved_gamma); _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); _this->SetWindowGrab(_this, window);
} }
} }
......
...@@ -159,12 +159,12 @@ WIN_CreateWindow(_THIS, SDL_Window * window) ...@@ -159,12 +159,12 @@ WIN_CreateWindow(_THIS, SDL_Window * window)
int x, y; int x, y;
int w, h; int w, h;
if (window->flags & SDL_WINDOW_BORDERLESS) { if (window->flags & (SDL_WINDOW_BORDERLESS|SDL_WINDOW_FULLSCREEN)) {
style |= WS_POPUP; style |= WS_POPUP;
} else { } else {
style |= (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX); 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); style |= (WS_THICKFRAME | WS_MAXIMIZEBOX);
} }
...@@ -182,14 +182,14 @@ WIN_CreateWindow(_THIS, SDL_Window * window) ...@@ -182,14 +182,14 @@ WIN_CreateWindow(_THIS, SDL_Window * window)
w = (rect.right - rect.left); w = (rect.right - rect.left);
h = (rect.bottom - rect.top); 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; x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
} else if (window->x == SDL_WINDOWPOS_UNDEFINED) { } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
x = CW_USEDEFAULT; x = CW_USEDEFAULT;
} else { } else {
x = window->x + rect.left; 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; y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
} else if (window->y == SDL_WINDOWPOS_UNDEFINED) { } else if (window->y == SDL_WINDOWPOS_UNDEFINED) {
y = CW_USEDEFAULT; y = CW_USEDEFAULT;
...@@ -331,8 +331,17 @@ WIN_SetWindowPosition(_THIS, SDL_Window * window) ...@@ -331,8 +331,17 @@ WIN_SetWindowPosition(_THIS, SDL_Window * window)
AdjustWindowRectEx(&rect, style, AdjustWindowRectEx(&rect, style,
(style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) !=
NULL), 0); NULL), 0);
if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->x == SDL_WINDOWPOS_CENTERED) {
x = (GetSystemMetrics(SM_CXSCREEN) - window->w) / 2;
} else {
x = window->x + rect.left; 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; y = window->y + rect.top;
}
SetWindowPos(hwnd, top, x, y, 0, 0, (SWP_NOCOPYBITS | SWP_NOSIZE)); SetWindowPos(hwnd, top, x, y, 0, 0, (SWP_NOCOPYBITS | SWP_NOSIZE));
} }
...@@ -425,7 +434,7 @@ WIN_SetWindowGrab(_THIS, SDL_Window * window) ...@@ -425,7 +434,7 @@ WIN_SetWindowGrab(_THIS, SDL_Window * window)
{ {
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; 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)) { (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
RECT rect; RECT rect;
GetClientRect(hwnd, &rect); GetClientRect(hwnd, &rect);
......
...@@ -287,7 +287,7 @@ X11_CreateWindow(_THIS, SDL_Window * window) ...@@ -287,7 +287,7 @@ X11_CreateWindow(_THIS, SDL_Window * window)
visual, AllocNone); 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) - x = (DisplayWidth(data->display, displaydata->screen) -
window->w) / 2; window->w) / 2;
} else if (window->x == SDL_WINDOWPOS_UNDEFINED) { } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
...@@ -295,7 +295,7 @@ X11_CreateWindow(_THIS, SDL_Window * window) ...@@ -295,7 +295,7 @@ X11_CreateWindow(_THIS, SDL_Window * window)
} else { } else {
x = window->x; 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) - y = (DisplayHeight(data->display, displaydata->screen) -
window->h) / 2; window->h) / 2;
} else if (window->y == SDL_WINDOWPOS_UNDEFINED) { } else if (window->y == SDL_WINDOWPOS_UNDEFINED) {
...@@ -321,7 +321,7 @@ X11_CreateWindow(_THIS, SDL_Window * window) ...@@ -321,7 +321,7 @@ X11_CreateWindow(_THIS, SDL_Window * window)
sizehints = XAllocSizeHints(); sizehints = XAllocSizeHints();
if (sizehints) { 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_width = 32;
sizehints->min_height = 32; sizehints->min_height = 32;
sizehints->max_height = 4096; sizehints->max_height = 4096;
...@@ -342,7 +342,7 @@ X11_CreateWindow(_THIS, SDL_Window * window) ...@@ -342,7 +342,7 @@ X11_CreateWindow(_THIS, SDL_Window * window)
XFree(sizehints); XFree(sizehints);
} }
if (window->flags & SDL_WINDOW_BORDERLESS) { if (window->flags & (SDL_WINDOW_BORDERLESS|SDL_WINDOW_FULLSCREEN)) {
SDL_bool set; SDL_bool set;
Atom WM_HINTS; Atom WM_HINTS;
...@@ -601,8 +601,19 @@ X11_SetWindowPosition(_THIS, SDL_Window * window) ...@@ -601,8 +601,19 @@ X11_SetWindowPosition(_THIS, SDL_Window * window)
SDL_DisplayData *displaydata = SDL_DisplayData *displaydata =
(SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->driverdata; (SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->driverdata;
Display *display = data->videodata->display; 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 void
...@@ -662,7 +673,29 @@ X11_RestoreWindow(_THIS, SDL_Window * window) ...@@ -662,7 +673,29 @@ X11_RestoreWindow(_THIS, SDL_Window * window)
void void
X11_SetWindowGrab(_THIS, SDL_Window * window) 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 void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment