SDL_windowswindow.c
Go to the documentation of this file.
/*
Simple DirectMedia Layer
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_WINDOWS
#include "../../core/windows/SDL_windows.h"
#include "SDL_assert.h"
#include "../SDL_sysvideo.h"
#include "../SDL_pixels_c.h"
#include "../../events/SDL_keyboard_c.h"
#include "../../events/SDL_mouse_c.h"
#include "SDL_windowsvideo.h"
#include "SDL_windowswindow.h"
#include "SDL_hints.h"
/* Dropfile support */
#include <shellapi.h>
/* This is included after SDL_windowsvideo.h, which includes windows.h */
#include "SDL_syswm.h"
/* Windows CE compatibility */
#ifndef SWP_NOCOPYBITS
#define SWP_NOCOPYBITS 0
#endif
/* Fake window to help with DirectInput events. */
HWND SDL_HelperWindow = NULL;
static WCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher");
static WCHAR *SDL_HelperWindowName = TEXT("SDLHelperWindowInputMsgWindow");
static ATOM SDL_HelperWindowClass = 0;
/* For borderless Windows, still want the following flags:
- WS_CAPTION: this seems to enable the Windows minimize animation
- WS_SYSMENU: enables system context menu on task bar
- WS_MINIMIZEBOX: window will respond to Windows minimize commands sent to all windows, such as windows key + m, shaking title bar, etc.
This will also cause the task bar to overlap the window and other windowed behaviors, so only use this for windows that shouldn't appear to be fullscreen
*/
#define STYLE_BASIC (WS_CLIPSIBLINGS | WS_CLIPCHILDREN)
#define STYLE_FULLSCREEN (WS_POPUP)
#define STYLE_BORDERLESS (WS_POPUP)
#define STYLE_BORDERLESS_WINDOWED (WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)
#define STYLE_NORMAL (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)
#define STYLE_RESIZABLE (WS_THICKFRAME | WS_MAXIMIZEBOX)
#define STYLE_MASK (STYLE_FULLSCREEN | STYLE_BORDERLESS | STYLE_NORMAL | STYLE_RESIZABLE)
static DWORD
GetWindowStyle(SDL_Window * window)
{
DWORD style = 0;
if (window->flags & SDL_WINDOW_FULLSCREEN) {
style |= STYLE_FULLSCREEN;
} else {
if (window->flags & SDL_WINDOW_BORDERLESS) {
/* SDL 2.1:
This behavior more closely matches other platform where the window is borderless
but still interacts with the window manager (e.g. task bar shows above it, it can
be resized to fit within usable desktop area, etc.) so this should be the behavior
for a future SDL release.
If you want a borderless window the size of the desktop that looks like a fullscreen
window, then you should use the SDL_WINDOW_FULLSCREEN_DESKTOP flag.
*/
if (SDL_GetHintBoolean("SDL_BORDERLESS_WINDOWED_STYLE", SDL_FALSE)) {
style |= STYLE_BORDERLESS_WINDOWED;
} else {
style |= STYLE_BORDERLESS;
}
} else {
style |= STYLE_NORMAL;
}
/* You can have a borderless resizable window */
if (window->flags & SDL_WINDOW_RESIZABLE) {
style |= STYLE_RESIZABLE;
}
}
return style;
}
static void
WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL menu, int *x, int *y, int *width, int *height, SDL_bool use_current)
{
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = (use_current ? window->w : window->windowed.w);
rect.bottom = (use_current ? window->h : window->windowed.h);
/* borderless windows will have WM_NCCALCSIZE return 0 for the non-client area. When this happens, it looks like windows will send a resize message
expanding the window client area to the previous window + chrome size, so shouldn't need to adjust the window size for the set styles.
*/
if (!(window->flags & SDL_WINDOW_BORDERLESS))
AdjustWindowRectEx(&rect, style, menu, 0);
*x = (use_current ? window->x : window->windowed.x) + rect.left;
*y = (use_current ? window->y : window->windowed.y) + rect.top;
*width = (rect.right - rect.left);
*height = (rect.bottom - rect.top);
}
static void
WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *height, SDL_bool use_current)
{
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
HWND hwnd = data->hwnd;
DWORD style;
BOOL menu;
style = GetWindowLong(hwnd, GWL_STYLE);
menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
WIN_AdjustWindowRectWithStyle(window, style, menu, x, y, width, height, use_current);
}
static void
WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
{
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
HWND hwnd = data->hwnd;
HWND top;
int x, y;
int w, h;
/* Figure out what the window area will be */
if (SDL_ShouldAllowTopmost() && ((window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS) || (window->flags & SDL_WINDOW_ALWAYS_ON_TOP))) {
top = HWND_TOPMOST;
} else {
top = HWND_NOTOPMOST;
}
WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_TRUE);
data->expected_resize = SDL_TRUE;
SetWindowPos(hwnd, top, x, y, w, h, flags);
data->expected_resize = SDL_FALSE;
}
static int
SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool created)
{
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
SDL_WindowData *data;
/* Allocate the window data */
data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
if (!data) {
return SDL_OutOfMemory();
}
data->window = window;
data->hwnd = hwnd;
data->parent = parent;
data->hdc = GetDC(hwnd);
data->hinstance = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
data->created = created;
data->mouse_button_flags = 0;
data->videodata = videodata;
data->initializing = SDL_TRUE;
window->driverdata = data;
/* Associate the data with the window */
if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
ReleaseDC(hwnd, data->hdc);
SDL_free(data);
return WIN_SetError("SetProp() failed");
}
/* Set up the window proc function */
#ifdef GWLP_WNDPROC
data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
if (data->wndproc == WIN_WindowProc) {
data->wndproc = NULL;
} else {
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
}
#else
data->wndproc = (WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC);
if (data->wndproc == WIN_WindowProc) {
data->wndproc = NULL;
} else {
SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR) WIN_WindowProc);
}
#endif
/* Fill in the SDL window with the window data */
{
RECT rect;
if (GetClientRect(hwnd, &rect)) {
int w = rect.right;
int h = rect.bottom;
if ((window->windowed.w && window->windowed.w != w) || (window->windowed.h && window->windowed.h != h)) {
/* We tried to create a window larger than the desktop and Windows didn't allow it. Override! */
int x, y;
int w, h;
/* Figure out what the window area will be */
WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_FALSE);
SetWindowPos(hwnd, HWND_NOTOPMOST, x, y, w, h, SWP_NOCOPYBITS | SWP_NOZORDER | SWP_NOACTIVATE);
} else {
window->w = w;
window->h = h;
}
}
}
{
POINT point;
point.x = 0;
point.y = 0;
if (ClientToScreen(hwnd, &point)) {
window->x = point.x;
window->y = point.y;
}
}
{
DWORD style = GetWindowLong(hwnd, GWL_STYLE);
if (style & WS_VISIBLE) {
window->flags |= SDL_WINDOW_SHOWN;
} else {
window->flags &= ~SDL_WINDOW_SHOWN;
}
if (style & WS_POPUP) {
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;
}
#ifdef WS_MAXIMIZE
if (style & WS_MAXIMIZE) {
window->flags |= SDL_WINDOW_MAXIMIZED;
} else
#endif
{
window->flags &= ~SDL_WINDOW_MAXIMIZED;
}
#ifdef WS_MINIMIZE
if (style & WS_MINIMIZE) {
window->flags |= SDL_WINDOW_MINIMIZED;
} else
#endif
{
window->flags &= ~SDL_WINDOW_MINIMIZED;
}
}
if (GetFocus() == hwnd) {
window->flags |= SDL_WINDOW_INPUT_FOCUS;
SDL_SetKeyboardFocus(data->window);
if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
RECT rect;
GetClientRect(hwnd, &rect);
ClientToScreen(hwnd, (LPPOINT) & rect);
ClientToScreen(hwnd, (LPPOINT) & rect + 1);
ClipCursor(&rect);
}
}
/* Enable multi-touch */
if (videodata->RegisterTouchWindow) {
videodata->RegisterTouchWindow(hwnd, (TWF_FINETOUCH|TWF_WANTPALM));
}
/* Enable dropping files */
DragAcceptFiles(hwnd, TRUE);
data->initializing = SDL_FALSE;
/* All done! */
return 0;
}
int
WIN_CreateWindow(_THIS, SDL_Window * window)
{
HWND hwnd, parent = NULL;
DWORD style = STYLE_BASIC;
int x, y;
int w, h;
if (window->flags & SDL_WINDOW_SKIP_TASKBAR) {
parent = CreateWindow(SDL_Appname, TEXT(""), STYLE_BASIC, 0, 0, 32, 32, NULL, NULL, SDL_Instance, NULL);
}
style |= GetWindowStyle(window);
/* Figure out what the window area will be */
WIN_AdjustWindowRectWithStyle(window, style, FALSE, &x, &y, &w, &h, SDL_FALSE);
hwnd =
CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, parent, NULL,
SDL_Instance, NULL);
if (!hwnd) {
return WIN_SetError("Couldn't create window");
}
WIN_PumpEvents(_this);
if (SetupWindowData(_this, window, hwnd, parent, SDL_TRUE) < 0) {
DestroyWindow(hwnd);
if (parent) {
DestroyWindow(parent);
}
return -1;
}
/* Inform Windows of the frame change so we can respond to WM_NCCALCSIZE */
SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
if (!(window->flags & SDL_WINDOW_OPENGL)) {
return 0;
}
/* The rest of this macro mess is for OpenGL or OpenGL ES windows */
#if SDL_VIDEO_OPENGL_ES2
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES
#if SDL_VIDEO_OPENGL_WGL
&& (!_this->gl_data || WIN_GL_UseEGL(_this))
#endif /* SDL_VIDEO_OPENGL_WGL */
) {
#if SDL_VIDEO_OPENGL_EGL
if (WIN_GLES_SetupWindow(_this, window) < 0) {
WIN_DestroyWindow(_this, window);
return -1;
}
return 0;
#else
return SDL_SetError("Could not create GLES window surface (EGL support not configured)");
#endif /* SDL_VIDEO_OPENGL_EGL */
}
#endif /* SDL_VIDEO_OPENGL_ES2 */
#if SDL_VIDEO_OPENGL_WGL
if (WIN_GL_SetupWindow(_this, window) < 0) {
WIN_DestroyWindow(_this, window);
return -1;
}
#else
return SDL_SetError("Could not create GL window (WGL support not configured)");
#endif
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(_this, window, hwnd, GetParent(hwnd), SDL_FALSE) < 0) {
return -1;
}
#if SDL_VIDEO_OPENGL_WGL
{
const char *hint = SDL_GetHint(SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT);
if (hint) {
/* This hint is a pointer (in string form) of the address of
the window to share a pixel format with
*/
SDL_Window *otherWindow = NULL;
SDL_sscanf(hint, "%p", (void**)&otherWindow);
/* Do some error checking on the pointer */
if (otherWindow != NULL && otherWindow->magic == &_this->window_magic)
{
/* If the otherWindow has SDL_WINDOW_OPENGL set, set it for the new window as well */
if (otherWindow->flags & SDL_WINDOW_OPENGL)
{
window->flags |= SDL_WINDOW_OPENGL;
if(!WIN_GL_SetPixelFormatFrom(_this, otherWindow, window)) {
return -1;
}
}
}
}
}
#endif
return 0;
}
void
WIN_SetWindowTitle(_THIS, SDL_Window * window)
{
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
LPTSTR title = WIN_UTF8ToString(window->title);
SetWindowText(hwnd, title);
SDL_free(title);
}
void
WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
{
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
HICON hicon = NULL;
BYTE *icon_bmp;
int icon_len, mask_len, y;
SDL_RWops *dst;
/* Create temporary buffer for ICONIMAGE structure */
mask_len = (icon->h * (icon->w + 7)/8);
icon_len = 40 + icon->h * icon->w * sizeof(Uint32) + mask_len;
icon_bmp = SDL_stack_alloc(BYTE, icon_len);
dst = SDL_RWFromMem(icon_bmp, icon_len);
if (!dst) {
SDL_stack_free(icon_bmp);
return;
}
/* Write the BITMAPINFO header */
SDL_WriteLE32(dst, 40);
SDL_WriteLE32(dst, icon->w);
SDL_WriteLE32(dst, icon->h * 2);
SDL_WriteLE16(dst, 1);
SDL_WriteLE16(dst, 32);
SDL_WriteLE32(dst, BI_RGB);
SDL_WriteLE32(dst, icon->h * icon->w * sizeof(Uint32));
SDL_WriteLE32(dst, 0);
SDL_WriteLE32(dst, 0);
SDL_WriteLE32(dst, 0);
SDL_WriteLE32(dst, 0);
/* Write the pixels upside down into the bitmap buffer */
SDL_assert(icon->format->format == SDL_PIXELFORMAT_ARGB8888);
y = icon->h;
while (y--) {
Uint8 *src = (Uint8 *) icon->pixels + y * icon->pitch;
SDL_RWwrite(dst, src, icon->w * sizeof(Uint32), 1);
}
/* Write the mask */
SDL_memset(icon_bmp + icon_len - mask_len, 0xFF, mask_len);
hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
SDL_RWclose(dst);
SDL_stack_free(icon_bmp);
/* Set the icon for the window */
SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
/* Set the icon in the task manager (should we do this?) */
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
}
void
WIN_SetWindowPosition(_THIS, SDL_Window * window)
{
WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
}
void
WIN_SetWindowSize(_THIS, SDL_Window * window)
{
WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOACTIVATE);
}
int
WIN_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right)
{
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
RECT rcClient, rcWindow;
POINT ptDiff;
/* rcClient stores the size of the inner window, while rcWindow stores the outer size relative to the top-left
* screen position; so the top/left values of rcClient are always {0,0} and bottom/right are {height,width} */
GetClientRect(hwnd, &rcClient);
GetWindowRect(hwnd, &rcWindow);
/* convert the top/left values to make them relative to
* the window; they will end up being slightly negative */
ptDiff.y = rcWindow.top;
ptDiff.x = rcWindow.left;
ScreenToClient(hwnd, &ptDiff);
rcWindow.top = ptDiff.y;
rcWindow.left = ptDiff.x;
/* convert the bottom/right values to make them relative to the window,
* these will be slightly bigger than the inner width/height */
ptDiff.y = rcWindow.bottom;
ptDiff.x = rcWindow.right;
ScreenToClient(hwnd, &ptDiff);
rcWindow.bottom = ptDiff.y;
rcWindow.right = ptDiff.x;
/* Now that both the inner and outer rects use the same coordinate system we can substract them to get the border size.
* Keep in mind that the top/left coordinates of rcWindow are negative because the border lies slightly before {0,0},
* so switch them around because SDL2 wants them in positive. */
*top = rcClient.top - rcWindow.top;
*left = rcClient.left - rcWindow.left;
*bottom = rcWindow.bottom - rcClient.bottom;
*right = rcWindow.right - rcClient.right;
return 0;
}
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;
SetForegroundWindow(hwnd);
}
void
WIN_MaximizeWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
HWND hwnd = data->hwnd;
data->expected_resize = SDL_TRUE;
ShowWindow(hwnd, SW_MAXIMIZE);
data->expected_resize = SDL_FALSE;
}
void
WIN_MinimizeWindow(_THIS, SDL_Window * window)
{
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
ShowWindow(hwnd, SW_MINIMIZE);
}
void
WIN_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
{
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
HWND hwnd = data->hwnd;
DWORD style;
style = GetWindowLong(hwnd, GWL_STYLE);
style &= ~STYLE_MASK;
style |= GetWindowStyle(window);
data->in_border_change = SDL_TRUE;
SetWindowLong(hwnd, GWL_STYLE, style);
WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE);
data->in_border_change = SDL_FALSE;
}
void
WIN_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
{
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
HWND hwnd = data->hwnd;
DWORD style;
style = GetWindowLong(hwnd, GWL_STYLE);
style &= ~STYLE_MASK;
style |= GetWindowStyle(window);
SetWindowLong(hwnd, GWL_STYLE, style);
}
void
WIN_RestoreWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
HWND hwnd = data->hwnd;
data->expected_resize = SDL_TRUE;
ShowWindow(hwnd, SW_RESTORE);
data->expected_resize = SDL_FALSE;
}
void
WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
HWND hwnd = data->hwnd;
SDL_Rect bounds;
DWORD style;
HWND top;
int x, y;
int w, h;
if (SDL_ShouldAllowTopmost() && ((window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS) || window->flags & SDL_WINDOW_ALWAYS_ON_TOP)) {
top = HWND_TOPMOST;
} else {
top = HWND_NOTOPMOST;
}
style = GetWindowLong(hwnd, GWL_STYLE);
style &= ~STYLE_MASK;
style |= GetWindowStyle(window);
WIN_GetDisplayBounds(_this, display, &bounds);
if (fullscreen) {
x = bounds.x;
y = bounds.y;
w = bounds.w;
h = bounds.h;
/* Unset the maximized flag. This fixes
https://bugzilla.libsdl.org/show_bug.cgi?id=3215
*/
if (style & WS_MAXIMIZE) {
data->windowed_mode_was_maximized = SDL_TRUE;
style &= ~WS_MAXIMIZE;
}
} else {
BOOL menu;
/* Restore window-maximization state, as applicable.
Special care is taken to *not* do this if and when we're
alt-tab'ing away (to some other window; as indicated by
in_window_deactivation), otherwise
https://bugzilla.libsdl.org/show_bug.cgi?id=3215 can reproduce!
*/
if (data->windowed_mode_was_maximized && !data->in_window_deactivation) {
style |= WS_MAXIMIZE;
data->windowed_mode_was_maximized = SDL_FALSE;
}
menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
WIN_AdjustWindowRectWithStyle(window, style, menu, &x, &y, &w, &h, SDL_FALSE);
}
SetWindowLong(hwnd, GWL_STYLE, style);
data->expected_resize = SDL_TRUE;
SetWindowPos(hwnd, top, x, y, w, h, SWP_NOCOPYBITS | SWP_NOACTIVATE);
data->expected_resize = SDL_FALSE;
}
int
WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
{
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
HDC hdc;
BOOL succeeded = FALSE;
hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
if (hdc) {
succeeded = SetDeviceGammaRamp(hdc, (LPVOID)ramp);
if (!succeeded) {
WIN_SetError("SetDeviceGammaRamp()");
}
DeleteDC(hdc);
}
return succeeded ? 0 : -1;
}
int
WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
{
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
HDC hdc;
BOOL succeeded = FALSE;
hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
if (hdc) {
succeeded = GetDeviceGammaRamp(hdc, (LPVOID)ramp);
if (!succeeded) {
WIN_SetError("GetDeviceGammaRamp()");
}
DeleteDC(hdc);
}
return succeeded ? 0 : -1;
}
void
WIN_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
{
WIN_UpdateClipCursor(window);
if (window->flags & SDL_WINDOW_FULLSCREEN) {
UINT flags = SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE;
if (!(window->flags & SDL_WINDOW_SHOWN)) {
flags |= SWP_NOACTIVATE;
}
WIN_SetWindowPositionInternal(_this, window, flags);
}
}
void
WIN_DestroyWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if (data) {
ReleaseDC(data->hwnd, data->hdc);
RemoveProp(data->hwnd, TEXT("SDL_WindowData"));
if (data->created) {
DestroyWindow(data->hwnd);
if (data->parent) {
DestroyWindow(data->parent);
}
} else {
/* Restore any original event handler... */
if (data->wndproc != NULL) {
#ifdef GWLP_WNDPROC
SetWindowLongPtr(data->hwnd, GWLP_WNDPROC,
(LONG_PTR) data->wndproc);
#else
SetWindowLong(data->hwnd, GWL_WNDPROC,
(LONG_PTR) data->wndproc);
#endif
}
}
SDL_free(data);
}
window->driverdata = NULL;
}
SDL_bool
WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
{
const SDL_WindowData *data = (const SDL_WindowData *) window->driverdata;
if (info->version.major <= SDL_MAJOR_VERSION) {
int versionnum = SDL_VERSIONNUM(info->version.major, info->version.minor, info->version.patch);
info->subsystem = SDL_SYSWM_WINDOWS;
info->info.win.window = data->hwnd;
if (versionnum >= SDL_VERSIONNUM(2, 0, 4)) {
info->info.win.hdc = data->hdc;
}
if (versionnum >= SDL_VERSIONNUM(2, 0, 5)) {
info->info.win.hinstance = data->hinstance;
}
return SDL_TRUE;
} else {
SDL_SetError("Application not compiled with SDL %d.%d",
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
return SDL_FALSE;
}
}
/*
* Creates a HelperWindow used for DirectInput events.
*/
int
SDL_HelperWindowCreate(void)
{
HINSTANCE hInstance = GetModuleHandle(NULL);
WNDCLASS wce;
/* Make sure window isn't created twice. */
if (SDL_HelperWindow != NULL) {
return 0;
}
/* Create the class. */
SDL_zero(wce);
wce.lpfnWndProc = DefWindowProc;
wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
wce.hInstance = hInstance;
/* Register the class. */
SDL_HelperWindowClass = RegisterClass(&wce);
if (SDL_HelperWindowClass == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) {
return WIN_SetError("Unable to create Helper Window Class");
}
/* Create the window. */
SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
SDL_HelperWindowName,
WS_OVERLAPPED, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, HWND_MESSAGE, NULL,
hInstance, NULL);
if (SDL_HelperWindow == NULL) {
UnregisterClass(SDL_HelperWindowClassName, hInstance);
return WIN_SetError("Unable to create Helper Window");
}
return 0;
}
/*
* Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
*/
void
SDL_HelperWindowDestroy(void)
{
HINSTANCE hInstance = GetModuleHandle(NULL);
/* Destroy the window. */
if (SDL_HelperWindow != NULL) {
if (DestroyWindow(SDL_HelperWindow) == 0) {
WIN_SetError("Unable to destroy Helper Window");
return;
}
SDL_HelperWindow = NULL;
}
/* Unregister the class. */
if (SDL_HelperWindowClass != 0) {
if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
WIN_SetError("Unable to destroy Helper Window Class");
return;
}
SDL_HelperWindowClass = 0;
}
}
void WIN_OnWindowEnter(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if (!data || !data->hwnd) {
/* The window wasn't fully initialized */
return;
}
if (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) {
WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
}
#ifdef WM_MOUSELEAVE
{
TRACKMOUSEEVENT trackMouseEvent;
trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
trackMouseEvent.dwFlags = TME_LEAVE;
trackMouseEvent.hwndTrack = data->hwnd;
TrackMouseEvent(&trackMouseEvent);
}
#endif /* WM_MOUSELEAVE */
}
void
WIN_UpdateClipCursor(SDL_Window *window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
SDL_Mouse *mouse = SDL_GetMouse();
if (data->focus_click_pending) {
return;
}
if ((mouse->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
if (mouse->relative_mode && !mouse->relative_mode_warp) {
LONG cx, cy;
RECT rect;
GetWindowRect(data->hwnd, &rect);
cx = (rect.left + rect.right) / 2;
cy = (rect.top + rect.bottom) / 2;
/* Make an absurdly small clip rect */
rect.left = cx - 1;
rect.right = cx + 1;
rect.top = cy - 1;
rect.bottom = cy + 1;
ClipCursor(&rect);
} else {
RECT rect;
if (GetClientRect(data->hwnd, &rect) && !IsRectEmpty(&rect)) {
ClientToScreen(data->hwnd, (LPPOINT) & rect);
ClientToScreen(data->hwnd, (LPPOINT) & rect + 1);
ClipCursor(&rect);
}
}
} else {
ClipCursor(NULL);
}
}
int
WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
{
return 0; /* just succeed, the real work is done elsewhere. */
}
int
WIN_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
{
const SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
const HWND hwnd = data->hwnd;
const LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
SDL_assert(style != 0);
if (opacity == 1.0f) {
/* want it fully opaque, just mark it unlayered if necessary. */
if (style & WS_EX_LAYERED) {
if (SetWindowLong(hwnd, GWL_EXSTYLE, style & ~WS_EX_LAYERED) == 0) {
return WIN_SetError("SetWindowLong()");
}
}
} else {
const BYTE alpha = (BYTE) ((int) (opacity * 255.0f));
/* want it transparent, mark it layered if necessary. */
if ((style & WS_EX_LAYERED) == 0) {
if (SetWindowLong(hwnd, GWL_EXSTYLE, style | WS_EX_LAYERED) == 0) {
return WIN_SetError("SetWindowLong()");
}
}
if (SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA) == 0) {
return WIN_SetError("SetLayeredWindowAttributes()");
}
}
return 0;
}
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
/* vi: set ts=4 sw=4 expandtab: */
BI_RGB
#define BI_RGB
Definition: SDL_bmp.c:45
SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:248
SDL_MINOR_VERSION
#define SDL_MINOR_VERSION
Definition: SDL_version.h:61
SDL_Instance
HINSTANCE SDL_Instance
SDL_WindowData::hwnd
HWND hwnd
Definition: SDL_windowswindow.h:33
WIN_UTF8ToString
#define WIN_UTF8ToString(S)
Definition: SDL_windows.h:47
SDL_GetMouse
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:112
SDL_WindowData::parent
HWND parent
Definition: SDL_windowswindow.h:34
WIN_SetWindowSize
void WIN_SetWindowSize(_THIS, SDL_Window *window)
SDL_TRUE
Definition: SDL_stdinc.h:142
SDL_SetKeyboardFocus
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:630
right
GLdouble GLdouble right
Definition: SDL_opengl_glext.h:6103
dst
GLenum GLenum dst
Definition: SDL_opengl_glext.h:1737
SDL_Window::w
int w
Definition: SDL_sysvideo.h:80
SDL_Surface::h
int h
Definition: SDL_surface.h:73
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
SDL_RWwrite
#define SDL_RWwrite(ctx, ptr, size, n)
Definition: SDL_rwops.h:188
SDL_MAJOR_VERSION
#define SDL_MAJOR_VERSION
Definition: SDL_version.h:60
SDL_RWops
Definition: SDL_rwops.h:52
SDL_Window::x
int x
Definition: SDL_sysvideo.h:79
WIN_RaiseWindow
void WIN_RaiseWindow(_THIS, SDL_Window *window)
SDL_Window::magic
const void * magic
Definition: SDL_sysvideo.h:75
rect
SDL_Rect rect
Definition: testrelative.c:27
WIN_GetWindowGammaRamp
int WIN_GetWindowGammaRamp(_THIS, SDL_Window *window, Uint16 *ramp)
WIN_WindowProc
LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
SDL_FALSE
Definition: SDL_stdinc.h:141
WIN_DestroyWindow
void WIN_DestroyWindow(_THIS, SDL_Window *window)
h
GLfloat GLfloat GLfloat GLfloat h
Definition: SDL_opengl_glext.h:1946
WIN_GetWindowWMInfo
SDL_bool WIN_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
SDL_Surface
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
SDL_VideoDevice::driverdata
void * driverdata
Definition: SDL_sysvideo.h:377
WIN_MaximizeWindow
void WIN_MaximizeWindow(_THIS, SDL_Window *window)
SDL_GetHint
#define SDL_GetHint
Definition: SDL_dynapi_overrides.h:191
SDL_SysWMinfo::version
SDL_version version
Definition: SDL_syswm.h:196
SDL_WindowData::expected_resize
SDL_bool expected_resize
Definition: SDL_windowswindow.h:43
SDL_version::major
Uint8 major
Definition: SDL_version.h:53
SDL_WriteLE16
#define SDL_WriteLE16
Definition: SDL_dynapi_overrides.h:364
SDL_Appname
LPTSTR SDL_Appname
SDL_VideoDevice::profile_mask
int profile_mask
Definition: SDL_sysvideo.h:342
bottom
GLint GLint bottom
Definition: SDL_opengl_glext.h:1949
f
GLfloat f
Definition: SDL_opengl_glext.h:1870
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
SDL_SysWMinfo::subsystem
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:197
SDL_WindowData::window
SDL_Window * window
Definition: SDL_cocoawindow.h:114
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:181
SDL_WindowData::hdc
HDC hdc
Definition: SDL_windowswindow.h:35
SDL_Surface::w
int w
Definition: SDL_surface.h:73
src
GLenum src
Definition: SDL_opengl_glext.h:1737
top
GLdouble GLdouble GLdouble GLdouble top
Definition: SDL_opengl_glext.h:6103
SDL_Window::windowed
SDL_Rect windowed
Definition: SDL_sysvideo.h:87
WIN_OnWindowEnter
void WIN_OnWindowEnter(_THIS, SDL_Window *window)
SDL_DisplayData
Definition: SDL_cocoamodes.h:26
alpha
GLfloat GLfloat GLfloat alpha
Definition: SDL_opengl_glext.h:412
SDL_WINDOW_SHOWN
Definition: SDL_video.h:102
width
GLint GLint GLsizei width
Definition: SDL_opengl.h:1572
SDL_WindowData::initializing
SDL_bool initializing
Definition: SDL_windowswindow.h:42
SDL_VideoDevice::gl_data
struct SDL_GLDriverData * gl_data
Definition: SDL_sysvideo.h:378
WIN_SetWindowPosition
void WIN_SetWindowPosition(_THIS, SDL_Window *window)
SDL_WindowData
Definition: SDL_androidwindow.h:35
WIN_SetWindowHitTest
int WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
SDL_GetHintBoolean
#define SDL_GetHintBoolean
Definition: SDL_dynapi_overrides.h:608
WIN_CreateWindow
int WIN_CreateWindow(_THIS, SDL_Window *window)
_this
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
SDL_SYSWM_WINDOWS
Definition: SDL_syswm.h:119
SDL_WindowData::windowed_mode_was_maximized
SDL_bool windowed_mode_was_maximized
Definition: SDL_windowswindow.h:47
SDL_DisplayData::DeviceName
TCHAR DeviceName[32]
Definition: SDL_windowsmodes.h:28
SDL_WindowData::in_border_change
SDL_bool in_border_change
Definition: SDL_windowswindow.h:44
WIN_GetDisplayBounds
int WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect)
SDL_SysWMinfo
Definition: SDL_syswm.h:194
WIN_SetWindowResizable
void WIN_SetWindowResizable(_THIS, SDL_Window *window, SDL_bool resizable)
SDL_WindowData::wndproc
WNDPROC wndproc
Definition: SDL_windowswindow.h:39
SDL_Surface::pixels
void * pixels
Definition: SDL_surface.h:75
WIN_MinimizeWindow
void WIN_MinimizeWindow(_THIS, SDL_Window *window)
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
SDL_WindowData::videodata
struct SDL_VideoData * videodata
Definition: SDL_cocoawindow.h:120
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:157
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
SDL_stack_alloc
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:354
SDL_VERSIONNUM
#define SDL_VERSIONNUM(X, Y, Z)
Definition: SDL_version.h:94
WIN_SetWindowOpacity
int WIN_SetWindowOpacity(_THIS, SDL_Window *window, float opacity)
TRUE
#define TRUE
Definition: edid-parse.c:33
SDL_WINDOW_SKIP_TASKBAR
Definition: SDL_video.h:118
WIN_SetWindowIcon
void WIN_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon)
WIN_ShowWindow
void WIN_ShowWindow(_THIS, SDL_Window *window)
SDL_hints.h
w
GLubyte GLubyte GLubyte GLubyte w
Definition: SDL_opengl_glext.h:731
SDL_RWFromMem
#define SDL_RWFromMem
Definition: SDL_dynapi_overrides.h:352
WIN_UpdateClipCursor
void WIN_UpdateClipCursor(SDL_Window *window)
SDL_version::minor
Uint8 minor
Definition: SDL_version.h:54
WIN_StringToUTF8
#define WIN_StringToUTF8(S)
Definition: SDL_windows.h:46
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT
#define SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT
A variable that is the address of another SDL_Window* (as a hex string formatted with "%p")...
Definition: SDL_hints.h:579
SDL_WINDOW_MINIMIZED
Definition: SDL_video.h:106
SDL_sscanf
#define SDL_sscanf
Definition: SDL_dynapi_overrides.h:39
SDL_Window::title
char * title
Definition: SDL_sysvideo.h:77
y
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
SDL_Window::y
int y
Definition: SDL_sysvideo.h:79
SDL_Rect::x
int x
Definition: SDL_rect.h:66
SDL_VIDEO_OPENGL_WGL
#define SDL_VIDEO_OPENGL_WGL
Definition: SDL_config_windows.h:219
TWF_FINETOUCH
#define TWF_FINETOUCH
Definition: SDL_windowsvideo.h:55
TWF_WANTPALM
#define TWF_WANTPALM
Definition: SDL_windowsvideo.h:56
SDL_Rect::w
int w
Definition: SDL_rect.h:67
WIN_RestoreWindow
void WIN_RestoreWindow(_THIS, SDL_Window *window)
SDL_VideoDevice::window_magic
Uint8 window_magic
Definition: SDL_sysvideo.h:315
enabled
GLenum GLenum GLsizei const GLuint GLboolean enabled
Definition: SDL_opengl_glext.h:2479
SDL_VideoDisplay
Definition: SDL_sysvideo.h:125
SDL_Window::h
int h
Definition: SDL_sysvideo.h:80
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
WIN_SetWindowGammaRamp
int WIN_SetWindowGammaRamp(_THIS, SDL_Window *window, const Uint16 *ramp)
SDL_SysWMinfo::window
Window window
Definition: SDL_syswm.h:218
SDL_ShouldAllowTopmost
SDL_bool SDL_ShouldAllowTopmost(void)
Definition: SDL_video.c:3888
NULL
#define NULL
Definition: begin_code.h:164
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:139
SDL_WINDOW_INPUT_FOCUS
Definition: SDL_video.h:109
SDL_WINDOW_RESIZABLE
Definition: SDL_video.h:105
SDL_Surface::format
SDL_PixelFormat * format
Definition: SDL_surface.h:72
SDL_RWclose
#define SDL_RWclose(ctx)
Definition: SDL_rwops.h:189
WIN_SetError
int WIN_SetError(const char *prefix)
SDL_WINDOW_BORDERLESS
Definition: SDL_video.h:104
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
WIN_SetWindowTitle
void WIN_SetWindowTitle(_THIS, SDL_Window *window)
SDL_WINDOW_ALWAYS_ON_TOP
Definition: SDL_video.h:117
flags
GLbitfield flags
Definition: SDL_opengl_glext.h:1480
height
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1572
WIN_PumpEvents
void WIN_PumpEvents(_THIS)
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
SDL_GetDisplayForWindow
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1073
window
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
WIN_SetWindowGrab
void WIN_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
SDL_Rect::h
int h
Definition: SDL_rect.h:67
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:73
SDL_WINDOW_MAXIMIZED
Definition: SDL_video.h:107
SDL_WINDOW_FULLSCREEN
Definition: SDL_video.h:100
SDL_Surface::pitch
int pitch
Definition: SDL_surface.h:74
WIN_SetWindowFullscreen
void WIN_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
SDL_WriteLE32
#define SDL_WriteLE32
Definition: SDL_dynapi_overrides.h:366
SDL_WindowData::hinstance
HINSTANCE hinstance
Definition: SDL_windowswindow.h:37
SDL_VideoData
Definition: SDL_androidvideo.h:35
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:169
SDL_WindowData::in_window_deactivation
SDL_bool in_window_deactivation
Definition: SDL_windowswindow.h:48
SDL_SysWMinfo::info
union SDL_SysWMinfo::@18 info
SDL_WindowData::created
SDL_bool created
Definition: SDL_cocoawindow.h:117
SDL_WINDOW_OPENGL
Definition: SDL_video.h:101
WIN_SetWindowBordered
void WIN_SetWindowBordered(_THIS, SDL_Window *window, SDL_bool bordered)
SDL_Mouse
Definition: SDL_mouse_c.h:43
SDL_VideoDevice::gl_config
struct SDL_VideoDevice::@34 gl_config
SDL_Window::driverdata
void * driverdata
Definition: SDL_sysvideo.h:111
WIN_GetWindowBordersSize
int WIN_GetWindowBordersSize(_THIS, SDL_Window *window, int *top, int *left, int *bottom, int *right)
WIN_CreateWindowFrom
int WIN_CreateWindowFrom(_THIS, SDL_Window *window, const void *data)
SDL_PixelFormat::format
Uint32 format
Definition: SDL_pixels.h:317
SDL_stack_free
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:355
WIN_HideWindow
void WIN_HideWindow(_THIS, SDL_Window *window)
FALSE
#define FALSE
Definition: edid-parse.c:34
SDL_windowswindow.h
SDL_WindowData::mouse_button_flags
WPARAM mouse_button_flags
Definition: SDL_windowswindow.h:41
SDL_Window::flags
Uint32 flags
Definition: SDL_sysvideo.h:83
SDL_GL_CONTEXT_PROFILE_ES
Definition: SDL_video.h:215
SDL_windowsvideo.h
SDL_syswm.h
SDL_Rect::y
int y
Definition: SDL_rect.h:66
SDL_WINDOW_INPUT_GRABBED
Definition: SDL_video.h:108
SDL_memset
#define SDL_memset
Definition: SDL_dynapi_overrides.h:386
SDL_Rect
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
SDL_WindowData::focus_click_pending
Uint8 focus_click_pending
Definition: SDL_windowswindow.h:46
SDL_VideoDisplay::driverdata
void * driverdata
Definition: SDL_sysvideo.h:138
SDL_assert.h
left
GLint left
Definition: SDL_opengl_glext.h:1949
SDL_version::patch
Uint8 patch
Definition: SDL_version.h:55