src/video/windows/SDL_windowswindow.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 28 May 2015 08:41:07 -0700
changeset 9664 42ab66d97cc1
parent 9619 b94b6d0bff0f
child 9665 8d24b4bfa3dd
permissions -rw-r--r--
Fixed bug 2860 - SetProp must be paired with RemoveProp especially for properties added to external windows

Coriiander

Upon creating a window, a window property is added to it through the Win32-function "SetProp". This is done in the SDL-function "SetupWindowData" in file "src\video\windows\SDL_windowswindow.c".

Whenever you call "SetProp" to add a property to a Win32-window, you should also call the Win32-function "RemoveProp" to remove it before destroying that Win32-window.

While you might think that it's ok and that Windows will clean up nicely itself, it is not ok. It is against all Win32-API guidelines and is mostlikely a leak. Especially on external windows (CreateWindowFrom) you want to have things done right, not messy and leaky, affecting some other module. Even if SDL gets shutdown entirely that external window will now forever still have the "SDL_WindowData" prop attached to it.
slouken@1895
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@9619
     3
  Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
slouken@1895
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@1895
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@1895
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@1895
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@1895
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_WINDOWS
slouken@6044
    24
slouken@7828
    25
#include "../../core/windows/SDL_windows.h"
slouken@7828
    26
slouken@7523
    27
#include "SDL_assert.h"
slouken@1895
    28
#include "../SDL_sysvideo.h"
slouken@2970
    29
#include "../SDL_pixels_c.h"
slouken@1895
    30
#include "../../events/SDL_keyboard_c.h"
slouken@8072
    31
#include "../../events/SDL_mouse_c.h"
slouken@1895
    32
slouken@5062
    33
#include "SDL_windowsvideo.h"
slouken@5062
    34
#include "SDL_windowswindow.h"
slouken@8144
    35
#include "SDL_hints.h"
slouken@1895
    36
slouken@6523
    37
/* Dropfile support */
slouken@6523
    38
#include <shellapi.h>
slouken@6523
    39
slouken@5062
    40
/* This is included after SDL_windowsvideo.h, which includes windows.h */
slouken@1895
    41
#include "SDL_syswm.h"
slouken@1895
    42
slouken@5086
    43
/* Windows CE compatibility */
slouken@5086
    44
#ifndef SWP_NOCOPYBITS
slouken@5086
    45
#define SWP_NOCOPYBITS 0
slouken@5086
    46
#endif
slouken@3168
    47
slouken@2713
    48
/* Fake window to help with DirectInput events. */
slouken@2713
    49
HWND SDL_HelperWindow = NULL;
slouken@2714
    50
static WCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher");
slouken@2714
    51
static WCHAR *SDL_HelperWindowName = TEXT("SDLHelperWindowInputMsgWindow");
slouken@2713
    52
static ATOM SDL_HelperWindowClass = 0;
slouken@2713
    53
slouken@5305
    54
#define STYLE_BASIC         (WS_CLIPSIBLINGS | WS_CLIPCHILDREN)
slouken@5305
    55
#define STYLE_FULLSCREEN    (WS_POPUP)
slouken@5305
    56
#define STYLE_BORDERLESS    (WS_POPUP)
slouken@5305
    57
#define STYLE_NORMAL        (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)
slouken@5305
    58
#define STYLE_RESIZABLE     (WS_THICKFRAME | WS_MAXIMIZEBOX)
slouken@5305
    59
#define STYLE_MASK          (STYLE_FULLSCREEN | STYLE_BORDERLESS | STYLE_NORMAL | STYLE_RESIZABLE)
slouken@5305
    60
slouken@5305
    61
static DWORD
slouken@5305
    62
GetWindowStyle(SDL_Window * window)
slouken@5305
    63
{
slouken@5305
    64
    DWORD style = 0;
slouken@5305
    65
slouken@6078
    66
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@5305
    67
        style |= STYLE_FULLSCREEN;
slouken@6078
    68
    } else {
slouken@6078
    69
        if (window->flags & SDL_WINDOW_BORDERLESS) {
slouken@5305
    70
            style |= STYLE_BORDERLESS;
slouken@6078
    71
        } else {
slouken@5305
    72
            style |= STYLE_NORMAL;
slouken@6078
    73
        }
slouken@6078
    74
        if (window->flags & SDL_WINDOW_RESIZABLE) {
slouken@5305
    75
            style |= STYLE_RESIZABLE;
slouken@6078
    76
        }
slouken@6078
    77
    }
slouken@5305
    78
    return style;
slouken@5305
    79
}
slouken@5305
    80
slouken@7585
    81
static void
slouken@7585
    82
WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
slouken@7585
    83
{
slouken@7941
    84
    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
slouken@7941
    85
    HWND hwnd = data->hwnd;
slouken@7585
    86
    RECT rect;
slouken@7585
    87
    DWORD style;
slouken@7585
    88
    HWND top;
slouken@7585
    89
    BOOL menu;
slouken@7585
    90
    int x, y;
slouken@7585
    91
    int w, h;
slouken@7585
    92
slouken@7585
    93
    /* Figure out what the window area will be */
slouken@7585
    94
    if (SDL_ShouldAllowTopmost() && (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) {
slouken@7585
    95
        top = HWND_TOPMOST;
slouken@7585
    96
    } else {
slouken@7585
    97
        top = HWND_NOTOPMOST;
slouken@7585
    98
    }
slouken@7585
    99
    style = GetWindowLong(hwnd, GWL_STYLE);
slouken@7585
   100
    rect.left = 0;
slouken@7585
   101
    rect.top = 0;
slouken@7585
   102
    rect.right = window->w;
slouken@7585
   103
    rect.bottom = window->h;
slouken@7585
   104
    menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
slouken@7585
   105
    AdjustWindowRectEx(&rect, style, menu, 0);
slouken@7585
   106
    w = (rect.right - rect.left);
slouken@7585
   107
    h = (rect.bottom - rect.top);
slouken@7585
   108
    x = window->x + rect.left;
slouken@7585
   109
    y = window->y + rect.top;
slouken@7585
   110
slouken@8817
   111
    data->expected_resize = SDL_TRUE;
slouken@8817
   112
    SetWindowPos( hwnd, top, x, y, w, h, flags );
slouken@8817
   113
    data->expected_resize = SDL_FALSE;
slouken@7585
   114
}
slouken@7585
   115
slouken@1895
   116
static int
slouken@1951
   117
SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created)
slouken@1895
   118
{
slouken@1951
   119
    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
slouken@1895
   120
    SDL_WindowData *data;
slouken@1895
   121
slouken@1895
   122
    /* Allocate the window data */
slouken@7775
   123
    data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
slouken@1895
   124
    if (!data) {
icculus@7037
   125
        return SDL_OutOfMemory();
slouken@1895
   126
    }
slouken@3685
   127
    data->window = window;
slouken@1895
   128
    data->hwnd = hwnd;
slouken@1913
   129
    data->hdc = GetDC(hwnd);
slouken@1895
   130
    data->created = created;
slouken@6943
   131
    data->mouse_button_flags = 0;
slouken@1951
   132
    data->videodata = videodata;
slouken@1895
   133
icculus@5980
   134
    window->driverdata = data;
icculus@5980
   135
slouken@1895
   136
    /* Associate the data with the window */
slouken@1895
   137
    if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
slouken@1913
   138
        ReleaseDC(hwnd, data->hdc);
slouken@1895
   139
        SDL_free(data);
icculus@7037
   140
        return WIN_SetError("SetProp() failed");
slouken@1895
   141
    }
slouken@1895
   142
slouken@1895
   143
    /* Set up the window proc function */
slouken@5086
   144
#ifdef GWLP_WNDPROC
slouken@1895
   145
    data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
dewyatt@4733
   146
    if (data->wndproc == WIN_WindowProc) {
slouken@3566
   147
        data->wndproc = NULL;
slouken@5086
   148
    } else {
dewyatt@4735
   149
        SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
dewyatt@4735
   150
    }
slouken@5086
   151
#else
slouken@5086
   152
    data->wndproc = (WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC);
slouken@5086
   153
    if (data->wndproc == WIN_WindowProc) {
slouken@5086
   154
        data->wndproc = NULL;
slouken@5086
   155
    } else {
slouken@5086
   156
        SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR) WIN_WindowProc);
slouken@5086
   157
    }
slouken@5086
   158
#endif
slouken@1895
   159
slouken@1895
   160
    /* Fill in the SDL window with the window data */
slouken@1895
   161
    {
slouken@7585
   162
        RECT rect;
slouken@7585
   163
        if (GetClientRect(hwnd, &rect)) {
slouken@7585
   164
            int w = rect.right;
slouken@7585
   165
            int h = rect.bottom;
slouken@7585
   166
            if ((window->w && window->w != w) || (window->h && window->h != h)) {
gabomdq@7663
   167
                /* We tried to create a window larger than the desktop and Windows didn't allow it.  Override! */
slouken@7585
   168
                WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOZORDER | SWP_NOACTIVATE);
slouken@7585
   169
            } else {
slouken@7585
   170
                window->w = w;
slouken@7585
   171
                window->h = h;
slouken@7585
   172
            }
slouken@7585
   173
        }
slouken@7585
   174
    }
slouken@7585
   175
    {
slouken@1895
   176
        POINT point;
slouken@1895
   177
        point.x = 0;
slouken@1895
   178
        point.y = 0;
slouken@1895
   179
        if (ClientToScreen(hwnd, &point)) {
slouken@5246
   180
            window->x = point.x;
slouken@5246
   181
            window->y = point.y;
slouken@1895
   182
        }
slouken@1895
   183
    }
slouken@1895
   184
    {
slouken@1895
   185
        DWORD style = GetWindowLong(hwnd, GWL_STYLE);
slouken@1895
   186
        if (style & WS_VISIBLE) {
slouken@1895
   187
            window->flags |= SDL_WINDOW_SHOWN;
slouken@1895
   188
        } else {
slouken@1895
   189
            window->flags &= ~SDL_WINDOW_SHOWN;
slouken@1895
   190
        }
slouken@1895
   191
        if (style & (WS_BORDER | WS_THICKFRAME)) {
slouken@1895
   192
            window->flags &= ~SDL_WINDOW_BORDERLESS;
slouken@1895
   193
        } else {
slouken@1895
   194
            window->flags |= SDL_WINDOW_BORDERLESS;
slouken@1895
   195
        }
slouken@1895
   196
        if (style & WS_THICKFRAME) {
slouken@1895
   197
            window->flags |= SDL_WINDOW_RESIZABLE;
slouken@1895
   198
        } else {
slouken@1895
   199
            window->flags &= ~SDL_WINDOW_RESIZABLE;
slouken@1895
   200
        }
slouken@5086
   201
#ifdef WS_MAXIMIZE
slouken@1895
   202
        if (style & WS_MAXIMIZE) {
slouken@1895
   203
            window->flags |= SDL_WINDOW_MAXIMIZED;
slouken@5086
   204
        } else
slouken@5086
   205
#endif
slouken@5086
   206
        {
slouken@1895
   207
            window->flags &= ~SDL_WINDOW_MAXIMIZED;
slouken@1895
   208
        }
slouken@5086
   209
#ifdef WS_MINIMIZE
slouken@1895
   210
        if (style & WS_MINIMIZE) {
slouken@1895
   211
            window->flags |= SDL_WINDOW_MINIMIZED;
slouken@5086
   212
        } else
slouken@5086
   213
#endif
slouken@5086
   214
        {
slouken@1895
   215
            window->flags &= ~SDL_WINDOW_MINIMIZED;
slouken@1895
   216
        }
slouken@1895
   217
    }
slouken@1895
   218
    if (GetFocus() == hwnd) {
slouken@1895
   219
        window->flags |= SDL_WINDOW_INPUT_FOCUS;
slouken@4465
   220
        SDL_SetKeyboardFocus(data->window);
slouken@1895
   221
slouken@1895
   222
        if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
slouken@1895
   223
            RECT rect;
slouken@1895
   224
            GetClientRect(hwnd, &rect);
slouken@1895
   225
            ClientToScreen(hwnd, (LPPOINT) & rect);
slouken@1895
   226
            ClientToScreen(hwnd, (LPPOINT) & rect + 1);
slouken@1895
   227
            ClipCursor(&rect);
slouken@1895
   228
        }
slouken@1895
   229
    }
slouken@1895
   230
slouken@6078
   231
    /* Enable multi-touch */
slouken@4948
   232
    if (videodata->RegisterTouchWindow) {
slouken@4948
   233
        videodata->RegisterTouchWindow(hwnd, (TWF_FINETOUCH|TWF_WANTPALM));
slouken@4948
   234
    }
slouken@4919
   235
slouken@6523
   236
    /* Enable dropping files */
slouken@6523
   237
    DragAcceptFiles(hwnd, TRUE);
slouken@6523
   238
slouken@1895
   239
    /* All done! */
slouken@1895
   240
    return 0;
slouken@1895
   241
}
slouken@1895
   242
slouken@1895
   243
int
slouken@1895
   244
WIN_CreateWindow(_THIS, SDL_Window * window)
slouken@1895
   245
{
slouken@1895
   246
    HWND hwnd;
slouken@1895
   247
    RECT rect;
slouken@5305
   248
    DWORD style = STYLE_BASIC;
slouken@1895
   249
    int x, y;
slouken@1895
   250
    int w, h;
slouken@7191
   251
slouken@5305
   252
    style |= GetWindowStyle(window);
slouken@1895
   253
slouken@1895
   254
    /* Figure out what the window area will be */
slouken@5382
   255
    rect.left = window->x;
slouken@5382
   256
    rect.top = window->y;
slouken@5382
   257
    rect.right = window->x + window->w;
slouken@5382
   258
    rect.bottom = window->y + window->h;
slouken@1895
   259
    AdjustWindowRectEx(&rect, style, FALSE, 0);
slouken@5382
   260
    x = rect.left;
slouken@5382
   261
    y = rect.top;
slouken@1895
   262
    w = (rect.right - rect.left);
slouken@1895
   263
    h = (rect.bottom - rect.top);
slouken@1895
   264
slouken@1956
   265
    hwnd =
slouken@1956
   266
        CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, NULL, NULL,
slouken@1956
   267
                     SDL_Instance, NULL);
slouken@1895
   268
    if (!hwnd) {
icculus@7037
   269
        return WIN_SetError("Couldn't create window");
slouken@1895
   270
    }
slouken@1895
   271
slouken@2710
   272
    WIN_PumpEvents(_this);
slouken@2710
   273
slouken@1951
   274
    if (SetupWindowData(_this, window, hwnd, SDL_TRUE) < 0) {
slouken@1895
   275
        DestroyWindow(hwnd);
slouken@1895
   276
        return -1;
slouken@1895
   277
    }
gabomdq@8021
   278
gabomdq@8021
   279
#if SDL_VIDEO_OPENGL_WGL
gabomdq@8021
   280
    /* We need to initialize the extensions before deciding how to create ES profiles */
gabomdq@8021
   281
    if (window->flags & SDL_WINDOW_OPENGL) {
gabomdq@8021
   282
        WIN_GL_InitExtensions(_this);
gabomdq@8021
   283
    }
gabomdq@8021
   284
#endif
gabomdq@8021
   285
gabomdq@8021
   286
#if SDL_VIDEO_OPENGL_ES2
gabomdq@8021
   287
    if ((window->flags & SDL_WINDOW_OPENGL) &&
gabomdq@8021
   288
        _this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES
gabomdq@8021
   289
#if SDL_VIDEO_OPENGL_WGL           
gabomdq@8021
   290
        && (!_this->gl_data || !_this->gl_data->HAS_WGL_EXT_create_context_es2_profile)
gabomdq@8021
   291
#endif  
gabomdq@8021
   292
        ) {
gabomdq@8021
   293
#if SDL_VIDEO_OPENGL_EGL  
gabomdq@8021
   294
        if (WIN_GLES_SetupWindow(_this, window) < 0) {
gabomdq@8021
   295
            WIN_DestroyWindow(_this, window);
gabomdq@8021
   296
            return -1;
gabomdq@8021
   297
        }
gabomdq@8021
   298
#else
gabomdq@8021
   299
        return SDL_SetError("Could not create GLES window surface (no EGL support available)");
gabomdq@8021
   300
#endif /* SDL_VIDEO_OPENGL_EGL */
gabomdq@8021
   301
    } else 
gabomdq@8021
   302
#endif /* SDL_VIDEO_OPENGL_ES2 */
gabomdq@8021
   303
slouken@5088
   304
#if SDL_VIDEO_OPENGL_WGL
slouken@1913
   305
    if (window->flags & SDL_WINDOW_OPENGL) {
slouken@1913
   306
        if (WIN_GL_SetupWindow(_this, window) < 0) {
slouken@1913
   307
            WIN_DestroyWindow(_this, window);
slouken@1913
   308
            return -1;
slouken@1913
   309
        }
slouken@1913
   310
    }
slouken@1913
   311
#endif
gabomdq@8021
   312
slouken@1895
   313
    return 0;
slouken@1895
   314
}
slouken@1895
   315
slouken@1895
   316
int
slouken@1895
   317
WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
slouken@1895
   318
{
slouken@1895
   319
    HWND hwnd = (HWND) data;
slouken@1895
   320
    LPTSTR title;
slouken@1895
   321
    int titleLen;
slouken@1895
   322
slouken@1895
   323
    /* Query the title from the existing window */
slouken@1895
   324
    titleLen = GetWindowTextLength(hwnd);
slouken@1895
   325
    title = SDL_stack_alloc(TCHAR, titleLen + 1);
slouken@1895
   326
    if (title) {
slouken@1895
   327
        titleLen = GetWindowText(hwnd, title, titleLen);
slouken@1895
   328
    } else {
slouken@1895
   329
        titleLen = 0;
slouken@1895
   330
    }
slouken@1895
   331
    if (titleLen > 0) {
slouken@1895
   332
        window->title = WIN_StringToUTF8(title);
slouken@1895
   333
    }
slouken@1895
   334
    if (title) {
slouken@1895
   335
        SDL_stack_free(title);
slouken@1895
   336
    }
slouken@1895
   337
slouken@1951
   338
    if (SetupWindowData(_this, window, hwnd, SDL_FALSE) < 0) {
slouken@1895
   339
        return -1;
slouken@1895
   340
    }
slouken@8144
   341
slouken@8144
   342
#if SDL_VIDEO_OPENGL_WGL
slouken@8144
   343
    {
slouken@8144
   344
        const char *hint = SDL_GetHint(SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT);
slouken@8144
   345
        if (hint) {
philipp@8778
   346
            /* This hint is a pointer (in string form) of the address of
philipp@8778
   347
               the window to share a pixel format with
philipp@8778
   348
            */
slouken@8144
   349
            SDL_Window *otherWindow = NULL;
slouken@8144
   350
            SDL_sscanf(hint, "%p", (void**)&otherWindow);
slouken@8144
   351
philipp@8778
   352
            /* Do some error checking on the pointer */
slouken@8144
   353
            if (otherWindow != NULL && otherWindow->magic == &_this->window_magic)
slouken@8144
   354
            {
philipp@8778
   355
                /* If the otherWindow has SDL_WINDOW_OPENGL set, set it for the new window as well */
slouken@8144
   356
                if (otherWindow->flags & SDL_WINDOW_OPENGL)
slouken@8144
   357
                {
slouken@8144
   358
                    window->flags |= SDL_WINDOW_OPENGL;
slouken@8144
   359
                    if(!WIN_GL_SetPixelFormatFrom(_this, otherWindow, window)) {
slouken@8144
   360
                        return -1;
slouken@8144
   361
                    }
slouken@8144
   362
                }
slouken@8144
   363
            }
slouken@8144
   364
        }
slouken@8144
   365
    }
slouken@8144
   366
#endif
slouken@1895
   367
    return 0;
slouken@1895
   368
}
slouken@1895
   369
slouken@1895
   370
void
slouken@1895
   371
WIN_SetWindowTitle(_THIS, SDL_Window * window)
slouken@1895
   372
{
slouken@1895
   373
    HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
icculus@9474
   374
    LPTSTR title = WIN_UTF8ToString(window->title);
icculus@9474
   375
    SetWindowText(hwnd, title);
slouken@7719
   376
    SDL_free(title);
slouken@1895
   377
}
slouken@1895
   378
slouken@1895
   379
void
slouken@2970
   380
WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
slouken@2970
   381
{
slouken@2970
   382
    HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
slouken@2970
   383
    HICON hicon = NULL;
slouken@5418
   384
    BYTE *icon_bmp;
slouken@7527
   385
    int icon_len, y;
slouken@5418
   386
    SDL_RWops *dst;
slouken@2970
   387
slouken@5418
   388
    /* Create temporary bitmap buffer */
slouken@5418
   389
    icon_len = 40 + icon->h * icon->w * 4;
slouken@5418
   390
    icon_bmp = SDL_stack_alloc(BYTE, icon_len);
slouken@5418
   391
    dst = SDL_RWFromMem(icon_bmp, icon_len);
slouken@5418
   392
    if (!dst) {
slouken@5418
   393
        SDL_stack_free(icon_bmp);
slouken@5418
   394
        return;
slouken@5418
   395
    }
slouken@2970
   396
slouken@5418
   397
    /* Write the BITMAPINFO header */
slouken@5418
   398
    SDL_WriteLE32(dst, 40);
slouken@5418
   399
    SDL_WriteLE32(dst, icon->w);
slouken@5418
   400
    SDL_WriteLE32(dst, icon->h * 2);
slouken@5418
   401
    SDL_WriteLE16(dst, 1);
slouken@5418
   402
    SDL_WriteLE16(dst, 32);
slouken@5418
   403
    SDL_WriteLE32(dst, BI_RGB);
slouken@5418
   404
    SDL_WriteLE32(dst, icon->h * icon->w * 4);
slouken@5418
   405
    SDL_WriteLE32(dst, 0);
slouken@5418
   406
    SDL_WriteLE32(dst, 0);
slouken@5418
   407
    SDL_WriteLE32(dst, 0);
slouken@5418
   408
    SDL_WriteLE32(dst, 0);
slouken@5418
   409
slouken@7523
   410
    /* Write the pixels upside down into the bitmap buffer */
slouken@7523
   411
    SDL_assert(icon->format->format == SDL_PIXELFORMAT_ARGB8888);
slouken@7527
   412
    y = icon->h;
slouken@7523
   413
    while (y--) {
slouken@7523
   414
        Uint8 *src = (Uint8 *) icon->pixels + y * icon->pitch;
slouken@7523
   415
        SDL_RWwrite(dst, src, icon->pitch, 1);
slouken@7523
   416
    }
slouken@2970
   417
slouken@7523
   418
    hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
slouken@7523
   419
slouken@5418
   420
    SDL_RWclose(dst);
slouken@5418
   421
    SDL_stack_free(icon_bmp);
slouken@2970
   422
slouken@2971
   423
    /* Set the icon for the window */
slouken@2990
   424
    SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
slouken@2971
   425
slouken@2971
   426
    /* Set the icon in the task manager (should we do this?) */
slouken@2990
   427
    SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
slouken@2970
   428
}
slouken@2970
   429
icculus@6427
   430
void
icculus@6427
   431
WIN_SetWindowPosition(_THIS, SDL_Window * window)
icculus@6427
   432
{
slouken@6535
   433
    WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
slouken@1895
   434
}
slouken@1895
   435
slouken@1895
   436
void
slouken@1895
   437
WIN_SetWindowSize(_THIS, SDL_Window * window)
slouken@1895
   438
{
slouken@6535
   439
    WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOACTIVATE);
slouken@5246
   440
}
slouken@5178
   441
slouken@1895
   442
void
slouken@1895
   443
WIN_ShowWindow(_THIS, SDL_Window * window)
slouken@1895
   444
{
slouken@1895
   445
    HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
slouken@1895
   446
    ShowWindow(hwnd, SW_SHOW);
slouken@1895
   447
}
slouken@1895
   448
slouken@1895
   449
void
slouken@1895
   450
WIN_HideWindow(_THIS, SDL_Window * window)
slouken@1895
   451
{
slouken@1895
   452
    HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
slouken@1895
   453
    ShowWindow(hwnd, SW_HIDE);
slouken@1895
   454
}
slouken@1895
   455
slouken@1895
   456
void
slouken@1895
   457
WIN_RaiseWindow(_THIS, SDL_Window * window)
slouken@1895
   458
{
slouken@7585
   459
    WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE);
slouken@1895
   460
}
slouken@1895
   461
slouken@1895
   462
void
slouken@1895
   463
WIN_MaximizeWindow(_THIS, SDL_Window * window)
slouken@1895
   464
{
slouken@7941
   465
    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
slouken@7941
   466
    HWND hwnd = data->hwnd;
slouken@8817
   467
    data->expected_resize = SDL_TRUE;
slouken@1895
   468
    ShowWindow(hwnd, SW_MAXIMIZE);
slouken@8817
   469
    data->expected_resize = SDL_FALSE;
slouken@1895
   470
}
slouken@1895
   471
slouken@1895
   472
void
slouken@1895
   473
WIN_MinimizeWindow(_THIS, SDL_Window * window)
slouken@1895
   474
{
slouken@1895
   475
    HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
slouken@1895
   476
    ShowWindow(hwnd, SW_MINIMIZE);
slouken@1895
   477
}
slouken@1895
   478
slouken@1895
   479
void
icculus@6422
   480
WIN_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
icculus@6422
   481
{
slouken@8817
   482
    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
slouken@8817
   483
    HWND hwnd = data->hwnd;
icculus@6428
   484
    DWORD style = GetWindowLong(hwnd, GWL_STYLE);
icculus@6428
   485
icculus@6428
   486
    if (bordered) {
icculus@6428
   487
        style &= ~STYLE_BORDERLESS;
icculus@6428
   488
        style |= STYLE_NORMAL;
icculus@6428
   489
    } else {
icculus@6428
   490
        style &= ~STYLE_NORMAL;
icculus@6428
   491
        style |= STYLE_BORDERLESS;
icculus@6428
   492
    }
icculus@6428
   493
slouken@8817
   494
    data->in_border_change = SDL_TRUE;
slouken@8817
   495
    SetWindowLong( hwnd, GWL_STYLE, style );
slouken@8817
   496
    WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE);
slouken@8817
   497
    data->in_border_change = SDL_FALSE;
icculus@6422
   498
}
icculus@6422
   499
icculus@6422
   500
void
slouken@1895
   501
WIN_RestoreWindow(_THIS, SDL_Window * window)
slouken@1895
   502
{
slouken@7941
   503
    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
slouken@7941
   504
    HWND hwnd = data->hwnd;
slouken@8817
   505
    data->expected_resize = SDL_TRUE;
slouken@1895
   506
    ShowWindow(hwnd, SW_RESTORE);
slouken@8817
   507
    data->expected_resize = SDL_FALSE;
slouken@1895
   508
}
slouken@1895
   509
slouken@1895
   510
void
slouken@5305
   511
WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
slouken@5305
   512
{
slouken@5305
   513
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@5305
   514
    HWND hwnd = data->hwnd;
slouken@5305
   515
    RECT rect;
slouken@5305
   516
    SDL_Rect bounds;
slouken@5305
   517
    DWORD style;
slouken@5305
   518
    HWND top;
slouken@5305
   519
    BOOL menu;
slouken@5305
   520
    int x, y;
slouken@5305
   521
    int w, h;
slouken@5305
   522
slouken@7585
   523
    if (SDL_ShouldAllowTopmost() && (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) {
slouken@7191
   524
        top = HWND_TOPMOST;
slouken@7191
   525
    } else {
slouken@7191
   526
        top = HWND_NOTOPMOST;
slouken@7191
   527
    }
slouken@6782
   528
slouken@5305
   529
    style = GetWindowLong(hwnd, GWL_STYLE);
slouken@5305
   530
    style &= ~STYLE_MASK;
slouken@5305
   531
    style |= GetWindowStyle(window);
slouken@5305
   532
slouken@5305
   533
    WIN_GetDisplayBounds(_this, display, &bounds);
slouken@5305
   534
slouken@5305
   535
    if (fullscreen) {
slouken@5305
   536
        x = bounds.x;
slouken@5305
   537
        y = bounds.y;
slouken@5305
   538
        w = bounds.w;
slouken@5305
   539
        h = bounds.h;
slouken@5305
   540
    } else {
slouken@5305
   541
        rect.left = 0;
slouken@5305
   542
        rect.top = 0;
slouken@5398
   543
        rect.right = window->windowed.w;
slouken@5398
   544
        rect.bottom = window->windowed.h;
slouken@5305
   545
        menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
slouken@5305
   546
        AdjustWindowRectEx(&rect, style, menu, 0);
slouken@5305
   547
        w = (rect.right - rect.left);
slouken@5305
   548
        h = (rect.bottom - rect.top);
slouken@5398
   549
        x = window->windowed.x + rect.left;
slouken@5398
   550
        y = window->windowed.y + rect.top;
slouken@5305
   551
    }
slouken@5305
   552
    SetWindowLong(hwnd, GWL_STYLE, style);
slouken@8817
   553
    data->expected_resize = SDL_TRUE;
slouken@8205
   554
    SetWindowPos(hwnd, top, x, y, w, h, SWP_NOCOPYBITS | SWP_NOACTIVATE);
slouken@8817
   555
    data->expected_resize = SDL_FALSE;
slouken@5305
   556
}
slouken@5305
   557
slouken@5466
   558
int
slouken@5466
   559
WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
slouken@5466
   560
{
slouken@5466
   561
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5466
   562
    SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
slouken@5466
   563
    HDC hdc;
slouken@5466
   564
    BOOL succeeded = FALSE;
slouken@5466
   565
slouken@5466
   566
    hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
slouken@5466
   567
    if (hdc) {
slouken@5466
   568
        succeeded = SetDeviceGammaRamp(hdc, (LPVOID)ramp);
slouken@5466
   569
        if (!succeeded) {
slouken@5466
   570
            WIN_SetError("SetDeviceGammaRamp()");
slouken@5466
   571
        }
slouken@5466
   572
        DeleteDC(hdc);
slouken@5466
   573
    }
slouken@5466
   574
    return succeeded ? 0 : -1;
slouken@5466
   575
}
slouken@5466
   576
slouken@5466
   577
int
slouken@5466
   578
WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
slouken@5466
   579
{
slouken@5466
   580
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5466
   581
    SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
slouken@5466
   582
    HDC hdc;
slouken@5466
   583
    BOOL succeeded = FALSE;
slouken@5466
   584
slouken@5466
   585
    hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
slouken@5466
   586
    if (hdc) {
slouken@5466
   587
        succeeded = GetDeviceGammaRamp(hdc, (LPVOID)ramp);
slouken@5466
   588
        if (!succeeded) {
slouken@5466
   589
            WIN_SetError("GetDeviceGammaRamp()");
slouken@5466
   590
        }
slouken@5466
   591
        DeleteDC(hdc);
slouken@5466
   592
    }
slouken@5466
   593
    return succeeded ? 0 : -1;
slouken@5466
   594
}
slouken@5466
   595
slouken@5305
   596
void
slouken@6662
   597
WIN_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
slouken@1895
   598
{
slouken@8072
   599
    WIN_UpdateClipCursor(window);
slouken@6782
   600
slouken@7585
   601
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@7584
   602
        UINT flags = SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE;
slouken@6782
   603
slouken@7584
   604
        if (!(window->flags & SDL_WINDOW_SHOWN)) {
slouken@7584
   605
            flags |= SWP_NOACTIVATE;
slouken@7584
   606
        }
slouken@7585
   607
        WIN_SetWindowPositionInternal(_this, window, flags);
slouken@7191
   608
    }
slouken@1895
   609
}
slouken@1895
   610
slouken@1895
   611
void
slouken@1895
   612
WIN_DestroyWindow(_THIS, SDL_Window * window)
slouken@1895
   613
{
slouken@1895
   614
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1895
   615
slouken@1895
   616
    if (data) {
slouken@1913
   617
        ReleaseDC(data->hwnd, data->hdc);
slouken@9664
   618
        ReleaseProp(data->hwnd, TEXT("SDL_WindowData"));
slouken@1895
   619
        if (data->created) {
slouken@1895
   620
            DestroyWindow(data->hwnd);
icculus@5580
   621
        } else {
icculus@5580
   622
            /* Restore any original event handler... */
icculus@5580
   623
            if (data->wndproc != NULL) {
icculus@5580
   624
#ifdef GWLP_WNDPROC
icculus@5581
   625
                SetWindowLongPtr(data->hwnd, GWLP_WNDPROC,
icculus@5581
   626
                                 (LONG_PTR) data->wndproc);
icculus@5580
   627
#else
icculus@5581
   628
                SetWindowLong(data->hwnd, GWL_WNDPROC,
icculus@5581
   629
                              (LONG_PTR) data->wndproc);
icculus@5580
   630
#endif
icculus@5580
   631
            }
slouken@1895
   632
        }
slouken@1895
   633
        SDL_free(data);
slouken@1895
   634
    }
slouken@8978
   635
    window->driverdata = NULL;
slouken@1895
   636
}
slouken@1895
   637
slouken@1895
   638
SDL_bool
slouken@1895
   639
WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
slouken@1895
   640
{
icculus@9422
   641
    const SDL_WindowData *data = (const SDL_WindowData *) window->driverdata;
slouken@1895
   642
    if (info->version.major <= SDL_MAJOR_VERSION) {
slouken@4900
   643
        info->subsystem = SDL_SYSWM_WINDOWS;
icculus@9422
   644
        info->info.win.window = data->hwnd;
icculus@9422
   645
        info->info.win.hdc = data->hdc;
slouken@1895
   646
        return SDL_TRUE;
slouken@1895
   647
    } else {
slouken@1895
   648
        SDL_SetError("Application not compiled with SDL %d.%d\n",
slouken@1895
   649
                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
slouken@1895
   650
        return SDL_FALSE;
slouken@1895
   651
    }
slouken@1895
   652
}
slouken@1895
   653
slouken@2713
   654
slouken@2713
   655
/*
slouken@2713
   656
 * Creates a HelperWindow used for DirectInput events.
slouken@2713
   657
 */
slouken@2713
   658
int
slouken@2713
   659
SDL_HelperWindowCreate(void)
slouken@2713
   660
{
slouken@3097
   661
    HINSTANCE hInstance = GetModuleHandle(NULL);
slouken@3097
   662
    WNDCLASS wce;
slouken@2713
   663
bobbens@3045
   664
    /* Make sure window isn't created twice. */
bobbens@3045
   665
    if (SDL_HelperWindow != NULL) {
bobbens@3045
   666
        return 0;
bobbens@3045
   667
    }
bobbens@3045
   668
slouken@2713
   669
    /* Create the class. */
slouken@2714
   670
    SDL_zero(wce);
slouken@3097
   671
    wce.lpfnWndProc = DefWindowProc;
slouken@2713
   672
    wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
slouken@2713
   673
    wce.hInstance = hInstance;
slouken@2713
   674
slouken@2713
   675
    /* Register the class. */
slouken@3097
   676
    SDL_HelperWindowClass = RegisterClass(&wce);
slouken@8238
   677
    if (SDL_HelperWindowClass == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) {
icculus@7037
   678
        return WIN_SetError("Unable to create Helper Window Class");
slouken@2713
   679
    }
slouken@2713
   680
slouken@2713
   681
    /* Create the window. */
slouken@2714
   682
    SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
slouken@2714
   683
                                      SDL_HelperWindowName,
slouken@3168
   684
                                      WS_OVERLAPPED, CW_USEDEFAULT,
slouken@2714
   685
                                      CW_USEDEFAULT, CW_USEDEFAULT,
icculus@6430
   686
                                      CW_USEDEFAULT, HWND_MESSAGE, NULL,
slouken@2714
   687
                                      hInstance, NULL);
slouken@2713
   688
    if (SDL_HelperWindow == NULL) {
bobbens@3045
   689
        UnregisterClass(SDL_HelperWindowClassName, hInstance);
icculus@7037
   690
        return WIN_SetError("Unable to create Helper Window");
slouken@2713
   691
    }
slouken@2713
   692
slouken@2713
   693
    return 0;
slouken@2713
   694
}
slouken@2713
   695
slouken@2713
   696
slouken@2713
   697
/*
slouken@2713
   698
 * Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
slouken@2713
   699
 */
slouken@2713
   700
void
slouken@2713
   701
SDL_HelperWindowDestroy(void)
slouken@2713
   702
{
slouken@3097
   703
    HINSTANCE hInstance = GetModuleHandle(NULL);
bobbens@2863
   704
slouken@2713
   705
    /* Destroy the window. */
bobbens@2863
   706
    if (SDL_HelperWindow != NULL) {
bobbens@2863
   707
        if (DestroyWindow(SDL_HelperWindow) == 0) {
slouken@4500
   708
            WIN_SetError("Unable to destroy Helper Window");
slouken@2865
   709
            return;
bobbens@2863
   710
        }
slouken@2713
   711
        SDL_HelperWindow = NULL;
slouken@2713
   712
    }
slouken@2713
   713
slouken@2713
   714
    /* Unregister the class. */
bobbens@2863
   715
    if (SDL_HelperWindowClass != 0) {
bobbens@2863
   716
        if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
slouken@4500
   717
            WIN_SetError("Unable to destroy Helper Window Class");
slouken@2865
   718
            return;
bobbens@2863
   719
        }
slouken@2713
   720
        SDL_HelperWindowClass = 0;
slouken@2713
   721
    }
slouken@2713
   722
}
slouken@2713
   723
jorgen@7089
   724
void WIN_OnWindowEnter(_THIS, SDL_Window * window)
jorgen@7089
   725
{
jorgen@7089
   726
#ifdef WM_MOUSELEAVE
jorgen@7089
   727
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
jorgen@7089
   728
    TRACKMOUSEEVENT trackMouseEvent;
jorgen@7089
   729
jorgen@7089
   730
    if (!data || !data->hwnd) {
jorgen@7089
   731
        /* The window wasn't fully initialized */
jorgen@7089
   732
        return;
jorgen@7089
   733
    }
jorgen@7089
   734
jorgen@7089
   735
    trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
jorgen@7089
   736
    trackMouseEvent.dwFlags = TME_LEAVE;
jorgen@7089
   737
    trackMouseEvent.hwndTrack = data->hwnd;
jorgen@7089
   738
jorgen@7089
   739
    TrackMouseEvent(&trackMouseEvent);
jorgen@7089
   740
#endif /* WM_MOUSELEAVE */
jorgen@7089
   741
}
jorgen@7089
   742
slouken@8072
   743
void
slouken@8072
   744
WIN_UpdateClipCursor(SDL_Window *window)
slouken@8072
   745
{
slouken@8072
   746
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@8072
   747
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@8072
   748
slouken@8916
   749
    if (data->focus_click_pending) {
slouken@8072
   750
        return;
slouken@8072
   751
    }
slouken@8072
   752
slouken@8072
   753
    if ((mouse->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
slouken@8072
   754
        (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
slouken@8072
   755
        if (mouse->relative_mode && !mouse->relative_mode_warp) {
slouken@8072
   756
            LONG cx, cy;
slouken@8072
   757
            RECT rect;
slouken@8072
   758
            GetWindowRect(data->hwnd, &rect);
slouken@8072
   759
slouken@8072
   760
            cx = (rect.left + rect.right) / 2;
slouken@8072
   761
            cy = (rect.top + rect.bottom) / 2;
slouken@8072
   762
slouken@8072
   763
            /* Make an absurdly small clip rect */
slouken@8072
   764
            rect.left = cx - 1;
slouken@8072
   765
            rect.right = cx + 1;
slouken@8072
   766
            rect.top = cy - 1;
slouken@8072
   767
            rect.bottom = cy + 1;
slouken@8072
   768
slouken@8072
   769
            ClipCursor(&rect);
slouken@8072
   770
        } else {
slouken@8072
   771
            RECT rect;
slouken@8072
   772
            if (GetClientRect(data->hwnd, &rect) && !IsRectEmpty(&rect)) {
slouken@8072
   773
                ClientToScreen(data->hwnd, (LPPOINT) & rect);
slouken@8072
   774
                ClientToScreen(data->hwnd, (LPPOINT) & rect + 1);
slouken@8072
   775
                ClipCursor(&rect);
slouken@8072
   776
            }
slouken@8072
   777
        }
slouken@8072
   778
    } else {
slouken@8072
   779
        ClipCursor(NULL);
slouken@8072
   780
    }
slouken@8072
   781
}
slouken@8072
   782
icculus@8938
   783
int
icculus@8938
   784
WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
icculus@8938
   785
{
icculus@8938
   786
    return 0;  /* just succeed, the real work is done elsewhere. */
icculus@8938
   787
}
icculus@8938
   788
slouken@6044
   789
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
slouken@6044
   790
slouken@1895
   791
/* vi: set ts=4 sw=4 expandtab: */