blob: 20616cd344bc3710b4d0fe60c50e261e2ce8c1ad [file] [log] [blame]
/*
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_sysvideo.h"
#include "../../events/SDL_keyboard_c.h"
#include "SDL_win32video.h"
/* This is included after SDL_win32video.h, which includes windows.h */
#include "SDL_syswm.h"
static int
SetupWindowData(SDL_Window * window, HWND hwnd, BOOL created)
{
SDL_WindowData *data;
/* Allocate the window data */
data = (SDL_WindowData *) SDL_malloc(sizeof(*data));
if (!data) {
SDL_OutOfMemory();
return -1;
}
data->windowID = window->id;
data->hwnd = hwnd;
data->created = created;
data->mouse_pressed = SDL_FALSE;
data->videodata = (SDL_VideoData *) SDL_GetVideoDevice()->driverdata;
/* Associate the data with the window */
if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
SDL_free(data);
WIN_SetError("SetProp() failed");
return -1;
}
/* Set up the window proc function */
data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
if (data->wndproc == NULL) {
data->wndproc = DefWindowProc;
} else {
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
}
/* Fill in the SDL window with the window data */
{
POINT point;
point.x = 0;
point.y = 0;
if (ClientToScreen(hwnd, &point)) {
window->x = point.x;
window->y = point.y;
}
}
{
RECT rect;
if (GetClientRect(hwnd, &rect)) {
window->w = rect.right;
window->h = rect.bottom;
}
}
{
DWORD style = GetWindowLong(hwnd, GWL_STYLE);
if (style & WS_VISIBLE) {
window->flags |= SDL_WINDOW_SHOWN;
} else {
window->flags &= ~SDL_WINDOW_SHOWN;
}
if (style & (WS_BORDER | WS_THICKFRAME)) {
window->flags &= ~SDL_WINDOW_BORDERLESS;
} else {
window->flags |= SDL_WINDOW_BORDERLESS;
}
if (style & WS_THICKFRAME) {
window->flags |= SDL_WINDOW_RESIZABLE;
} else {
window->flags &= ~SDL_WINDOW_RESIZABLE;
}
if (style & WS_MAXIMIZE) {
window->flags |= SDL_WINDOW_MAXIMIZED;
} else {
window->flags &= ~SDL_WINDOW_MAXIMIZED;
}
if (style & WS_MINIMIZE) {
window->flags |= SDL_WINDOW_MINIMIZED;
} else {
window->flags &= ~SDL_WINDOW_MINIMIZED;
}
}
if (GetFocus() == hwnd) {
int index = data->videodata->keyboard;
window->flags |= SDL_WINDOW_INPUT_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! */
window->driverdata = data;
return 0;
}
int
WIN_CreateWindow(_THIS, SDL_Window * window)
{
HWND hwnd;
LPTSTR title = NULL;
HWND top;
RECT rect;
DWORD style = 0;
int x, y;
int w, h;
if (window->title) {
title = WIN_UTF8ToString(window->title);
} else {
title = NULL;
}
if (window->flags & SDL_WINDOW_SHOWN) {
style |= WS_VISIBLE;
}
if ((window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS))) {
style |= WS_POPUP;
} else {
style |= (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
}
if (window->flags & SDL_WINDOW_RESIZABLE) {
style |= (WS_THICKFRAME | WS_MAXIMIZEBOX);
}
if (window->flags & SDL_WINDOW_MAXIMIZED) {
style |= WS_MAXIMIZE;
}
if (window->flags & SDL_WINDOW_MINIMIZED) {
style |= WS_MINIMIZE;
}
/* Figure out what the window area will be */
if (window->flags & SDL_WINDOW_FULLSCREEN) {
top = HWND_TOPMOST;
} else {
top = HWND_NOTOPMOST;
}
rect.left = 0;
rect.top = 0;
rect.right = window->w;
rect.bottom = window->h;
AdjustWindowRectEx(&rect, style, FALSE, 0);
w = (rect.right - rect.left);
h = (rect.bottom - rect.top);
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->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;
} else {
y = window->y + rect.top;
}
hwnd = CreateWindow(SDL_Appname,
title ? title : TEXT(""),
style, x, y, w, h, NULL, NULL, SDL_Instance, NULL);
WIN_PumpEvents(_this);
if (title) {
SDL_free(title);
}
if (!hwnd) {
WIN_SetError("Couldn't create window");
return -1;
}
if (SetupWindowData(window, hwnd, TRUE) < 0) {
DestroyWindow(hwnd);
return -1;
}
return 0;
}
int
WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
{
HWND hwnd = (HWND) data;
LPTSTR title;
int titleLen;
/* Query the title from the existing window */
titleLen = GetWindowTextLength(hwnd);
title = SDL_stack_alloc(TCHAR, titleLen + 1);
if (title) {
titleLen = GetWindowText(hwnd, title, titleLen);
} else {
titleLen = 0;
}
if (titleLen > 0) {
window->title = WIN_StringToUTF8(title);
}
if (title) {
SDL_stack_free(title);
}
if (SetupWindowData(window, hwnd, FALSE) < 0) {
return -1;
}
return 0;
}
void
WIN_SetWindowTitle(_THIS, SDL_Window * window)
{
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
LPTSTR title;
if (window->title) {
title = WIN_UTF8ToString(window->title);
} else {
title = NULL;
}
SetWindowText(hwnd, title ? title : TEXT(""));
if (title) {
SDL_free(title);
}
}
void
WIN_SetWindowPosition(_THIS, SDL_Window * window)
{
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
RECT rect;
DWORD style;
HWND top;
int x, y;
int w, h;
/* Figure out what the window area will be */
if (window->flags & SDL_WINDOW_FULLSCREEN) {
top = HWND_TOPMOST;
} else {
top = HWND_NOTOPMOST;
}
style = GetWindowLong(hwnd, GWL_STYLE);
rect.left = 0;
rect.top = 0;
rect.right = window->w;
rect.bottom = window->h;
AdjustWindowRectEx(&rect, style,
(style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) !=
NULL), 0);
w = (rect.right - rect.left);
h = (rect.bottom - rect.top);
if ((window->flags & SDL_WINDOW_FULLSCREEN) ||
window->x == SDL_WINDOWPOS_CENTERED) {
x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
window->x = x - rect.left;
} else {
x = window->x + rect.left;
}
if ((window->flags & SDL_WINDOW_FULLSCREEN) ||
window->y == SDL_WINDOWPOS_CENTERED) {
y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
window->y = y - rect.top;
} else {
y = window->y + rect.top;
}
SetWindowPos(hwnd, top, x, y, h, w, (SWP_NOCOPYBITS | SWP_NOSIZE));
}
void
WIN_SetWindowSize(_THIS, SDL_Window * window)
{
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
RECT rect;
DWORD style;
HWND top;
int w, h;
/* Figure out what the window area will be */
if (window->flags & SDL_WINDOW_FULLSCREEN) {
top = HWND_TOPMOST;
} else {
top = HWND_NOTOPMOST;
}
style = GetWindowLong(hwnd, GWL_STYLE);
rect.left = 0;
rect.top = 0;
rect.right = window->w;
rect.bottom = window->h;
AdjustWindowRectEx(&rect, style,
(style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) !=
NULL), 0);
w = (rect.right - rect.left);
h = (rect.bottom - rect.top);
SetWindowPos(hwnd, top, 0, 0, h, w, (SWP_NOCOPYBITS | SWP_NOMOVE));
}
void
WIN_ShowWindow(_THIS, SDL_Window * window)
{
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
ShowWindow(hwnd, SW_SHOW);
}
void
WIN_HideWindow(_THIS, SDL_Window * window)
{
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
ShowWindow(hwnd, SW_HIDE);
}
void
WIN_RaiseWindow(_THIS, SDL_Window * window)
{
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
HWND top;
if (window->flags & SDL_WINDOW_FULLSCREEN) {
top = HWND_TOPMOST;
} else {
top = HWND_NOTOPMOST;
}
SetWindowPos(hwnd, top, 0, 0, 0, 0, (SWP_NOMOVE | SWP_NOSIZE));
}
void
WIN_MaximizeWindow(_THIS, SDL_Window * window)
{
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
ShowWindow(hwnd, SW_MAXIMIZE);
}
void
WIN_MinimizeWindow(_THIS, SDL_Window * window)
{
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
ShowWindow(hwnd, SW_MINIMIZE);
}
void
WIN_RestoreWindow(_THIS, SDL_Window * window)
{
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
ShowWindow(hwnd, SW_RESTORE);
}
void
WIN_SetWindowGrab(_THIS, SDL_Window * window)
{
HWND hwnd = ((SDL_WindowData *) window->driverdata)->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 {
ClipCursor(NULL);
}
}
void
WIN_DestroyWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if (data) {
if (data->created) {
DestroyWindow(data->hwnd);
}
SDL_free(data);
}
}
SDL_bool
WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
{
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
if (info->version.major <= SDL_MAJOR_VERSION) {
info->window = hwnd;
/* FIXME! */
info->hglrc = NULL;
return SDL_TRUE;
} else {
SDL_SetError("Application not compiled with SDL %d.%d\n",
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
return SDL_FALSE;
}
}
/* vi: set ts=4 sw=4 expandtab: */