src/video/windows/SDL_windowswindow.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 26 Aug 2018 10:34:23 -0700
changeset 12153 de4288fa5b0b
parent 12070 1d65571b57dd
child 12231 e653f009e6c0
child 12349 a67dedb293c8
permissions -rw-r--r--
Only reset the clip rect if it's currently the rect we previously clipped.
This prevents us from clearing the clip rect globally when another application has set it.

There's also an experimental change to regularly update the clip rect for a window defensively, in case someone else has reset it. It works well, but I don't know if it's cheap enough to call as frequently as it would be called now, and might have other undesirable side effects.

Also fixed whitespace and SDL coding style
slouken@1895
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@11811
     3
  Copyright (C) 1997-2018 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@11824
    54
/* For borderless Windows, still want the following flags:
slouken@11824
    55
   - WS_CAPTION: this seems to enable the Windows minimize animation
slouken@11824
    56
   - WS_SYSMENU: enables system context menu on task bar
slouken@11824
    57
   - WS_MINIMIZEBOX: window will respond to Windows minimize commands sent to all windows, such as windows key + m, shaking title bar, etc.
slouken@11824
    58
   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
slouken@11824
    59
 */
slouken@11528
    60
slouken@5305
    61
#define STYLE_BASIC         (WS_CLIPSIBLINGS | WS_CLIPCHILDREN)
slouken@5305
    62
#define STYLE_FULLSCREEN    (WS_POPUP)
slouken@11824
    63
#define STYLE_BORDERLESS    (WS_POPUP)
slouken@11824
    64
#define STYLE_BORDERLESS_WINDOWED (WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)
slouken@5305
    65
#define STYLE_NORMAL        (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)
slouken@5305
    66
#define STYLE_RESIZABLE     (WS_THICKFRAME | WS_MAXIMIZEBOX)
slouken@5305
    67
#define STYLE_MASK          (STYLE_FULLSCREEN | STYLE_BORDERLESS | STYLE_NORMAL | STYLE_RESIZABLE)
slouken@5305
    68
slouken@5305
    69
static DWORD
slouken@5305
    70
GetWindowStyle(SDL_Window * window)
slouken@5305
    71
{
slouken@5305
    72
    DWORD style = 0;
slouken@5305
    73
slouken@6078
    74
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@5305
    75
        style |= STYLE_FULLSCREEN;
slouken@6078
    76
    } else {
slouken@11460
    77
        if (window->flags & SDL_WINDOW_BORDERLESS) {
slouken@11824
    78
            /* SDL 2.1:
slouken@11824
    79
               This behavior more closely matches other platform where the window is borderless
slouken@11824
    80
               but still interacts with the window manager (e.g. task bar shows above it, it can
slouken@11824
    81
               be resized to fit within usable desktop area, etc.) so this should be the behavior
slouken@11824
    82
               for a future SDL release.
slouken@11824
    83
slouken@11824
    84
               If you want a borderless window the size of the desktop that looks like a fullscreen
slouken@11824
    85
               window, then you should use the SDL_WINDOW_FULLSCREEN_DESKTOP flag.
slouken@11824
    86
             */
slouken@11824
    87
            if (SDL_GetHintBoolean("SDL_BORDERLESS_WINDOWED_STYLE", SDL_FALSE)) {
slouken@11824
    88
                style |= STYLE_BORDERLESS_WINDOWED;
slouken@11824
    89
            } else {
slouken@11824
    90
                style |= STYLE_BORDERLESS;
slouken@11824
    91
            }
slouken@11460
    92
        } else {
slouken@11460
    93
            style |= STYLE_NORMAL;
slouken@11460
    94
        }
slouken@11460
    95
slouken@11460
    96
        /* You can have a borderless resizable window */
slouken@6078
    97
        if (window->flags & SDL_WINDOW_RESIZABLE) {
slouken@5305
    98
            style |= STYLE_RESIZABLE;
slouken@6078
    99
        }
slouken@12006
   100
slouken@12153
   101
        /* Need to set initialize minimize style, or when we call ShowWindow with WS_MINIMIZE it will activate a random window */
slouken@12153
   102
        if (window->flags & SDL_WINDOW_MINIMIZED) {
slouken@12153
   103
            style |= WS_MINIMIZE;
slouken@12153
   104
        }
slouken@6078
   105
    }
slouken@5305
   106
    return style;
slouken@5305
   107
}
slouken@5305
   108
slouken@7585
   109
static void
slouken@11481
   110
WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL menu, int *x, int *y, int *width, int *height, SDL_bool use_current)
slouken@11461
   111
{
slouken@11461
   112
    RECT rect;
slouken@11461
   113
slouken@11461
   114
    rect.left = 0;
slouken@11461
   115
    rect.top = 0;
slouken@11481
   116
    rect.right = (use_current ? window->w : window->windowed.w);
slouken@11481
   117
    rect.bottom = (use_current ? window->h : window->windowed.h);
slouken@11529
   118
slouken@11835
   119
    /* 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
slouken@11835
   120
       expanding the window client area to the previous window + chrome size, so shouldn't need to adjust the window size for the set styles.
slouken@11835
   121
     */
slouken@11540
   122
    if (!(window->flags & SDL_WINDOW_BORDERLESS))
slouken@11540
   123
        AdjustWindowRectEx(&rect, style, menu, 0);
slouken@11461
   124
slouken@11481
   125
    *x = (use_current ? window->x : window->windowed.x) + rect.left;
slouken@11481
   126
    *y = (use_current ? window->y : window->windowed.y) + rect.top;
slouken@11461
   127
    *width = (rect.right - rect.left);
slouken@11461
   128
    *height = (rect.bottom - rect.top);
slouken@11461
   129
}
slouken@11461
   130
slouken@11461
   131
static void
slouken@11481
   132
WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *height, SDL_bool use_current)
slouken@11461
   133
{
slouken@11461
   134
    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
slouken@11461
   135
    HWND hwnd = data->hwnd;
slouken@11461
   136
    DWORD style;
slouken@11461
   137
    BOOL menu;
slouken@11461
   138
slouken@11481
   139
    style = GetWindowLong(hwnd, GWL_STYLE);
slouken@11481
   140
    menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
slouken@11481
   141
    WIN_AdjustWindowRectWithStyle(window, style, menu, x, y, width, height, use_current);
slouken@11461
   142
}
slouken@11461
   143
slouken@11461
   144
static void
slouken@7585
   145
WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
slouken@7585
   146
{
slouken@7941
   147
    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
slouken@7941
   148
    HWND hwnd = data->hwnd;
slouken@7585
   149
    HWND top;
slouken@7585
   150
    int x, y;
slouken@7585
   151
    int w, h;
slouken@7585
   152
slouken@7585
   153
    /* Figure out what the window area will be */
slouken@11100
   154
    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))) {
slouken@7585
   155
        top = HWND_TOPMOST;
slouken@7585
   156
    } else {
slouken@7585
   157
        top = HWND_NOTOPMOST;
slouken@7585
   158
    }
slouken@11461
   159
slouken@11481
   160
    WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_TRUE);    
slouken@7585
   161
slouken@8817
   162
    data->expected_resize = SDL_TRUE;
slouken@9886
   163
    SetWindowPos(hwnd, top, x, y, w, h, flags);
slouken@8817
   164
    data->expected_resize = SDL_FALSE;
slouken@7585
   165
}
slouken@7585
   166
slouken@1895
   167
static int
slouken@11101
   168
SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool created)
slouken@1895
   169
{
slouken@1951
   170
    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
slouken@1895
   171
    SDL_WindowData *data;
slouken@1895
   172
slouken@1895
   173
    /* Allocate the window data */
slouken@7775
   174
    data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
slouken@1895
   175
    if (!data) {
icculus@7037
   176
        return SDL_OutOfMemory();
slouken@1895
   177
    }
slouken@3685
   178
    data->window = window;
slouken@1895
   179
    data->hwnd = hwnd;
slouken@11101
   180
    data->parent = parent;
slouken@1913
   181
    data->hdc = GetDC(hwnd);
slouken@10634
   182
    data->hinstance = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
slouken@1895
   183
    data->created = created;
slouken@6943
   184
    data->mouse_button_flags = 0;
slouken@1951
   185
    data->videodata = videodata;
slouken@9889
   186
    data->initializing = SDL_TRUE;
slouken@1895
   187
icculus@5980
   188
    window->driverdata = data;
icculus@5980
   189
slouken@1895
   190
    /* Associate the data with the window */
slouken@1895
   191
    if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
slouken@1913
   192
        ReleaseDC(hwnd, data->hdc);
slouken@1895
   193
        SDL_free(data);
icculus@7037
   194
        return WIN_SetError("SetProp() failed");
slouken@1895
   195
    }
slouken@1895
   196
slouken@1895
   197
    /* Set up the window proc function */
slouken@5086
   198
#ifdef GWLP_WNDPROC
slouken@1895
   199
    data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
dewyatt@4733
   200
    if (data->wndproc == WIN_WindowProc) {
slouken@3566
   201
        data->wndproc = NULL;
slouken@5086
   202
    } else {
dewyatt@4735
   203
        SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
dewyatt@4735
   204
    }
slouken@5086
   205
#else
slouken@5086
   206
    data->wndproc = (WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC);
slouken@5086
   207
    if (data->wndproc == WIN_WindowProc) {
slouken@5086
   208
        data->wndproc = NULL;
slouken@5086
   209
    } else {
slouken@5086
   210
        SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR) WIN_WindowProc);
slouken@5086
   211
    }
slouken@5086
   212
#endif
slouken@1895
   213
slouken@1895
   214
    /* Fill in the SDL window with the window data */
slouken@1895
   215
    {
slouken@7585
   216
        RECT rect;
slouken@7585
   217
        if (GetClientRect(hwnd, &rect)) {
slouken@7585
   218
            int w = rect.right;
slouken@7585
   219
            int h = rect.bottom;
slouken@11835
   220
            if ((window->windowed.w && window->windowed.w != w) || (window->windowed.h && window->windowed.h != h)) {
gabomdq@7663
   221
                /* We tried to create a window larger than the desktop and Windows didn't allow it.  Override! */
slouken@9886
   222
                int x, y;
slouken@9886
   223
                /* Figure out what the window area will be */
slouken@11835
   224
                WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_FALSE);
slouken@9886
   225
                SetWindowPos(hwnd, HWND_NOTOPMOST, x, y, w, h, SWP_NOCOPYBITS | SWP_NOZORDER | SWP_NOACTIVATE);
slouken@7585
   226
            } else {
slouken@7585
   227
                window->w = w;
slouken@7585
   228
                window->h = h;
slouken@7585
   229
            }
slouken@7585
   230
        }
slouken@7585
   231
    }
slouken@7585
   232
    {
slouken@1895
   233
        POINT point;
slouken@1895
   234
        point.x = 0;
slouken@1895
   235
        point.y = 0;
slouken@1895
   236
        if (ClientToScreen(hwnd, &point)) {
slouken@5246
   237
            window->x = point.x;
slouken@5246
   238
            window->y = point.y;
slouken@1895
   239
        }
slouken@1895
   240
    }
slouken@1895
   241
    {
slouken@1895
   242
        DWORD style = GetWindowLong(hwnd, GWL_STYLE);
slouken@1895
   243
        if (style & WS_VISIBLE) {
slouken@1895
   244
            window->flags |= SDL_WINDOW_SHOWN;
slouken@1895
   245
        } else {
slouken@1895
   246
            window->flags &= ~SDL_WINDOW_SHOWN;
slouken@1895
   247
        }
slouken@11528
   248
        if (style & WS_POPUP) {
slouken@11528
   249
            window->flags |= SDL_WINDOW_BORDERLESS;
slouken@11528
   250
        } else {
slouken@1895
   251
            window->flags &= ~SDL_WINDOW_BORDERLESS;
slouken@1895
   252
        }
slouken@1895
   253
        if (style & WS_THICKFRAME) {
slouken@1895
   254
            window->flags |= SDL_WINDOW_RESIZABLE;
slouken@1895
   255
        } else {
slouken@1895
   256
            window->flags &= ~SDL_WINDOW_RESIZABLE;
slouken@1895
   257
        }
slouken@5086
   258
#ifdef WS_MAXIMIZE
slouken@1895
   259
        if (style & WS_MAXIMIZE) {
slouken@1895
   260
            window->flags |= SDL_WINDOW_MAXIMIZED;
slouken@5086
   261
        } else
slouken@5086
   262
#endif
slouken@5086
   263
        {
slouken@1895
   264
            window->flags &= ~SDL_WINDOW_MAXIMIZED;
slouken@1895
   265
        }
slouken@5086
   266
#ifdef WS_MINIMIZE
slouken@1895
   267
        if (style & WS_MINIMIZE) {
slouken@1895
   268
            window->flags |= SDL_WINDOW_MINIMIZED;
slouken@5086
   269
        } else
slouken@5086
   270
#endif
slouken@5086
   271
        {
slouken@1895
   272
            window->flags &= ~SDL_WINDOW_MINIMIZED;
slouken@1895
   273
        }
slouken@1895
   274
    }
slouken@1895
   275
    if (GetFocus() == hwnd) {
slouken@1895
   276
        window->flags |= SDL_WINDOW_INPUT_FOCUS;
slouken@4465
   277
        SDL_SetKeyboardFocus(data->window);
slouken@1895
   278
slouken@1895
   279
        if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
slouken@1895
   280
            RECT rect;
slouken@1895
   281
            GetClientRect(hwnd, &rect);
slouken@1895
   282
            ClientToScreen(hwnd, (LPPOINT) & rect);
slouken@1895
   283
            ClientToScreen(hwnd, (LPPOINT) & rect + 1);
slouken@1895
   284
            ClipCursor(&rect);
slouken@1895
   285
        }
slouken@1895
   286
    }
slouken@1895
   287
slouken@6078
   288
    /* Enable multi-touch */
slouken@4948
   289
    if (videodata->RegisterTouchWindow) {
slouken@4948
   290
        videodata->RegisterTouchWindow(hwnd, (TWF_FINETOUCH|TWF_WANTPALM));
slouken@4948
   291
    }
slouken@4919
   292
slouken@9889
   293
    data->initializing = SDL_FALSE;
slouken@9888
   294
slouken@1895
   295
    /* All done! */
slouken@1895
   296
    return 0;
slouken@1895
   297
}
slouken@1895
   298
slouken@10806
   299
slouken@10806
   300
slouken@1895
   301
int
slouken@1895
   302
WIN_CreateWindow(_THIS, SDL_Window * window)
slouken@1895
   303
{
slouken@11100
   304
    HWND hwnd, parent = NULL;
slouken@5305
   305
    DWORD style = STYLE_BASIC;
slouken@1895
   306
    int x, y;
slouken@1895
   307
    int w, h;
slouken@7191
   308
slouken@11100
   309
    if (window->flags & SDL_WINDOW_SKIP_TASKBAR) {
slouken@11100
   310
        parent = CreateWindow(SDL_Appname, TEXT(""), STYLE_BASIC, 0, 0, 32, 32, NULL, NULL, SDL_Instance, NULL);
slouken@11100
   311
    }
slouken@11100
   312
slouken@5305
   313
    style |= GetWindowStyle(window);
slouken@1895
   314
slouken@1895
   315
    /* Figure out what the window area will be */
slouken@11835
   316
    WIN_AdjustWindowRectWithStyle(window, style, FALSE, &x, &y, &w, &h, SDL_FALSE);
slouken@1895
   317
slouken@1956
   318
    hwnd =
slouken@11100
   319
        CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, parent, NULL,
slouken@1956
   320
                     SDL_Instance, NULL);
slouken@1895
   321
    if (!hwnd) {
icculus@7037
   322
        return WIN_SetError("Couldn't create window");
slouken@1895
   323
    }
slouken@1895
   324
slouken@2710
   325
    WIN_PumpEvents(_this);
slouken@2710
   326
slouken@11101
   327
    if (SetupWindowData(_this, window, hwnd, parent, SDL_TRUE) < 0) {
slouken@1895
   328
        DestroyWindow(hwnd);
slouken@11101
   329
        if (parent) {
slouken@11101
   330
            DestroyWindow(parent);
slouken@11101
   331
        }
slouken@1895
   332
        return -1;
slouken@1895
   333
    }
gabomdq@8021
   334
slouken@11835
   335
    /* Inform Windows of the frame change so we can respond to WM_NCCALCSIZE */
slouken@11540
   336
    SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
slouken@11528
   337
slouken@12153
   338
    if (window->flags & SDL_WINDOW_MINIMIZED) {
slouken@12153
   339
        ShowWindow(hwnd, SW_SHOWMINNOACTIVE);
slouken@12153
   340
    }
slouken@12006
   341
slouken@10806
   342
    if (!(window->flags & SDL_WINDOW_OPENGL)) {
slouken@10806
   343
        return 0;
slouken@10806
   344
    }
slouken@10806
   345
slouken@10806
   346
    /* The rest of this macro mess is for OpenGL or OpenGL ES windows */
slouken@10806
   347
#if SDL_VIDEO_OPENGL_ES2
slouken@10806
   348
    if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES
gabomdq@8021
   349
#if SDL_VIDEO_OPENGL_WGL
slouken@10806
   350
        && (!_this->gl_data || WIN_GL_UseEGL(_this))
slouken@10806
   351
#endif /* SDL_VIDEO_OPENGL_WGL */
slouken@10806
   352
    ) {
slouken@10806
   353
#if SDL_VIDEO_OPENGL_EGL
gabomdq@8021
   354
        if (WIN_GLES_SetupWindow(_this, window) < 0) {
gabomdq@8021
   355
            WIN_DestroyWindow(_this, window);
gabomdq@8021
   356
            return -1;
gabomdq@8021
   357
        }
slouken@10806
   358
        return 0;
gabomdq@8021
   359
#else
slouken@10806
   360
        return SDL_SetError("Could not create GLES window surface (EGL support not configured)");
slouken@10806
   361
#endif /* SDL_VIDEO_OPENGL_EGL */ 
slouken@10806
   362
    }
gabomdq@8021
   363
#endif /* SDL_VIDEO_OPENGL_ES2 */
gabomdq@8021
   364
slouken@5088
   365
#if SDL_VIDEO_OPENGL_WGL
slouken@10806
   366
    if (WIN_GL_SetupWindow(_this, window) < 0) {
slouken@10806
   367
        WIN_DestroyWindow(_this, window);
slouken@10806
   368
        return -1;
slouken@1913
   369
    }
slouken@10806
   370
#else
slouken@10806
   371
    return SDL_SetError("Could not create GL window (WGL support not configured)");
slouken@1913
   372
#endif
gabomdq@8021
   373
slouken@1895
   374
    return 0;
slouken@1895
   375
}
slouken@1895
   376
slouken@1895
   377
int
slouken@1895
   378
WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
slouken@1895
   379
{
slouken@1895
   380
    HWND hwnd = (HWND) data;
slouken@1895
   381
    LPTSTR title;
slouken@1895
   382
    int titleLen;
slouken@1895
   383
slouken@1895
   384
    /* Query the title from the existing window */
slouken@1895
   385
    titleLen = GetWindowTextLength(hwnd);
slouken@1895
   386
    title = SDL_stack_alloc(TCHAR, titleLen + 1);
slouken@1895
   387
    if (title) {
slouken@1895
   388
        titleLen = GetWindowText(hwnd, title, titleLen);
slouken@1895
   389
    } else {
slouken@1895
   390
        titleLen = 0;
slouken@1895
   391
    }
slouken@1895
   392
    if (titleLen > 0) {
slouken@1895
   393
        window->title = WIN_StringToUTF8(title);
slouken@1895
   394
    }
slouken@1895
   395
    if (title) {
slouken@1895
   396
        SDL_stack_free(title);
slouken@1895
   397
    }
slouken@1895
   398
slouken@11102
   399
    if (SetupWindowData(_this, window, hwnd, GetParent(hwnd), SDL_FALSE) < 0) {
slouken@1895
   400
        return -1;
slouken@1895
   401
    }
slouken@8144
   402
slouken@8144
   403
#if SDL_VIDEO_OPENGL_WGL
slouken@8144
   404
    {
slouken@8144
   405
        const char *hint = SDL_GetHint(SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT);
slouken@8144
   406
        if (hint) {
philipp@8778
   407
            /* This hint is a pointer (in string form) of the address of
philipp@8778
   408
               the window to share a pixel format with
philipp@8778
   409
            */
slouken@8144
   410
            SDL_Window *otherWindow = NULL;
slouken@8144
   411
            SDL_sscanf(hint, "%p", (void**)&otherWindow);
slouken@8144
   412
philipp@8778
   413
            /* Do some error checking on the pointer */
slouken@12153
   414
            if (otherWindow != NULL && otherWindow->magic == &_this->window_magic) {
philipp@8778
   415
                /* If the otherWindow has SDL_WINDOW_OPENGL set, set it for the new window as well */
slouken@12153
   416
                if (otherWindow->flags & SDL_WINDOW_OPENGL) {
slouken@8144
   417
                    window->flags |= SDL_WINDOW_OPENGL;
slouken@12153
   418
                    if (!WIN_GL_SetPixelFormatFrom(_this, otherWindow, window)) {
slouken@8144
   419
                        return -1;
slouken@8144
   420
                    }
slouken@8144
   421
                }
slouken@8144
   422
            }
slouken@8144
   423
        }
slouken@8144
   424
    }
slouken@8144
   425
#endif
slouken@1895
   426
    return 0;
slouken@1895
   427
}
slouken@1895
   428
slouken@1895
   429
void
slouken@1895
   430
WIN_SetWindowTitle(_THIS, SDL_Window * window)
slouken@1895
   431
{
slouken@1895
   432
    HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
icculus@9474
   433
    LPTSTR title = WIN_UTF8ToString(window->title);
icculus@9474
   434
    SetWindowText(hwnd, title);
slouken@7719
   435
    SDL_free(title);
slouken@1895
   436
}
slouken@1895
   437
slouken@1895
   438
void
slouken@2970
   439
WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
slouken@2970
   440
{
slouken@2970
   441
    HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
slouken@2970
   442
    HICON hicon = NULL;
slouken@5418
   443
    BYTE *icon_bmp;
slouken@11825
   444
    int icon_len, mask_len, y;
slouken@5418
   445
    SDL_RWops *dst;
slouken@2970
   446
slouken@11825
   447
    /* Create temporary buffer for ICONIMAGE structure */
slouken@11825
   448
    mask_len = (icon->h * (icon->w + 7)/8);
slouken@11825
   449
    icon_len = 40 + icon->h * icon->w * sizeof(Uint32) + mask_len;
slouken@5418
   450
    icon_bmp = SDL_stack_alloc(BYTE, icon_len);
slouken@5418
   451
    dst = SDL_RWFromMem(icon_bmp, icon_len);
slouken@5418
   452
    if (!dst) {
slouken@5418
   453
        SDL_stack_free(icon_bmp);
slouken@5418
   454
        return;
slouken@5418
   455
    }
slouken@2970
   456
slouken@5418
   457
    /* Write the BITMAPINFO header */
slouken@5418
   458
    SDL_WriteLE32(dst, 40);
slouken@5418
   459
    SDL_WriteLE32(dst, icon->w);
slouken@5418
   460
    SDL_WriteLE32(dst, icon->h * 2);
slouken@5418
   461
    SDL_WriteLE16(dst, 1);
slouken@5418
   462
    SDL_WriteLE16(dst, 32);
slouken@5418
   463
    SDL_WriteLE32(dst, BI_RGB);
slouken@10816
   464
    SDL_WriteLE32(dst, icon->h * icon->w * sizeof(Uint32));
slouken@5418
   465
    SDL_WriteLE32(dst, 0);
slouken@5418
   466
    SDL_WriteLE32(dst, 0);
slouken@5418
   467
    SDL_WriteLE32(dst, 0);
slouken@5418
   468
    SDL_WriteLE32(dst, 0);
slouken@5418
   469
slouken@7523
   470
    /* Write the pixels upside down into the bitmap buffer */
slouken@7523
   471
    SDL_assert(icon->format->format == SDL_PIXELFORMAT_ARGB8888);
slouken@7527
   472
    y = icon->h;
slouken@7523
   473
    while (y--) {
slouken@7523
   474
        Uint8 *src = (Uint8 *) icon->pixels + y * icon->pitch;
slouken@10816
   475
        SDL_RWwrite(dst, src, icon->w * sizeof(Uint32), 1);
slouken@7523
   476
    }
slouken@2970
   477
slouken@11825
   478
    /* Write the mask */
slouken@11825
   479
    SDL_memset(icon_bmp + icon_len - mask_len, 0xFF, mask_len);
slouken@11825
   480
slouken@7523
   481
    hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
slouken@7523
   482
slouken@5418
   483
    SDL_RWclose(dst);
slouken@5418
   484
    SDL_stack_free(icon_bmp);
slouken@2970
   485
slouken@2971
   486
    /* Set the icon for the window */
slouken@2990
   487
    SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
slouken@2971
   488
slouken@2971
   489
    /* Set the icon in the task manager (should we do this?) */
slouken@2990
   490
    SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
slouken@2970
   491
}
slouken@2970
   492
icculus@6427
   493
void
icculus@6427
   494
WIN_SetWindowPosition(_THIS, SDL_Window * window)
icculus@6427
   495
{
slouken@6535
   496
    WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
slouken@1895
   497
}
slouken@1895
   498
slouken@1895
   499
void
slouken@1895
   500
WIN_SetWindowSize(_THIS, SDL_Window * window)
slouken@1895
   501
{
slouken@6535
   502
    WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOACTIVATE);
slouken@5246
   503
}
slouken@5178
   504
slouken@11815
   505
int
slouken@11815
   506
WIN_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right)
slouken@11815
   507
{
slouken@11815
   508
    HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
slouken@11815
   509
    RECT rcClient, rcWindow;
slouken@11815
   510
    POINT ptDiff;
slouken@11815
   511
slouken@11815
   512
    /* rcClient stores the size of the inner window, while rcWindow stores the outer size relative to the top-left
slouken@11815
   513
     * screen position; so the top/left values of rcClient are always {0,0} and bottom/right are {height,width} */
slouken@11815
   514
    GetClientRect(hwnd, &rcClient);
slouken@11815
   515
    GetWindowRect(hwnd, &rcWindow);
slouken@11815
   516
slouken@11815
   517
    /* convert the top/left values to make them relative to
slouken@11815
   518
     * the window; they will end up being slightly negative */
slouken@11815
   519
    ptDiff.y = rcWindow.top;
slouken@11815
   520
    ptDiff.x = rcWindow.left;
slouken@11815
   521
slouken@11815
   522
    ScreenToClient(hwnd, &ptDiff);
slouken@11815
   523
slouken@11815
   524
    rcWindow.top  = ptDiff.y;
slouken@11815
   525
    rcWindow.left = ptDiff.x;
slouken@11815
   526
slouken@11815
   527
    /* convert the bottom/right values to make them relative to the window,
slouken@11815
   528
     * these will be slightly bigger than the inner width/height */
slouken@11815
   529
    ptDiff.y = rcWindow.bottom;
slouken@11815
   530
    ptDiff.x = rcWindow.right;
slouken@11815
   531
slouken@11815
   532
    ScreenToClient(hwnd, &ptDiff);
slouken@11815
   533
slouken@11815
   534
    rcWindow.bottom = ptDiff.y;
slouken@11815
   535
    rcWindow.right  = ptDiff.x;
slouken@11815
   536
slouken@11815
   537
    /* Now that both the inner and outer rects use the same coordinate system we can substract them to get the border size.
slouken@11815
   538
     * Keep in mind that the top/left coordinates of rcWindow are negative because the border lies slightly before {0,0},
slouken@11815
   539
     * so switch them around because SDL2 wants them in positive. */
slouken@11815
   540
    *top    = rcClient.top    - rcWindow.top;
slouken@11815
   541
    *left   = rcClient.left   - rcWindow.left;
slouken@11815
   542
    *bottom = rcWindow.bottom - rcClient.bottom;
slouken@11815
   543
    *right  = rcWindow.right  - rcClient.right;
slouken@11815
   544
slouken@11815
   545
    return 0;
slouken@11815
   546
}
slouken@11815
   547
slouken@1895
   548
void
slouken@1895
   549
WIN_ShowWindow(_THIS, SDL_Window * window)
slouken@1895
   550
{
slouken@12153
   551
    DWORD style;
slouken@12153
   552
    HWND hwnd;
slouken@12153
   553
    int nCmdShow;
slouken@12153
   554
    
slouken@12153
   555
    hwnd = ((SDL_WindowData *)window->driverdata)->hwnd;
slouken@12153
   556
    nCmdShow = SW_SHOW;
slouken@12153
   557
    style = GetWindowLong(hwnd, GWL_EXSTYLE);
slouken@12153
   558
    if (style & WS_EX_NOACTIVATE) {
slouken@12153
   559
        nCmdShow = SW_SHOWNOACTIVATE;
slouken@12153
   560
    }
slouken@12153
   561
    ShowWindow(hwnd, nCmdShow);
slouken@1895
   562
}
slouken@1895
   563
slouken@1895
   564
void
slouken@1895
   565
WIN_HideWindow(_THIS, SDL_Window * window)
slouken@1895
   566
{
slouken@1895
   567
    HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
slouken@1895
   568
    ShowWindow(hwnd, SW_HIDE);
slouken@1895
   569
}
slouken@1895
   570
slouken@1895
   571
void
slouken@1895
   572
WIN_RaiseWindow(_THIS, SDL_Window * window)
slouken@1895
   573
{
slime73@10450
   574
    HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
slime73@10450
   575
    SetForegroundWindow(hwnd);
slouken@1895
   576
}
slouken@1895
   577
slouken@1895
   578
void
slouken@1895
   579
WIN_MaximizeWindow(_THIS, SDL_Window * window)
slouken@1895
   580
{
slouken@7941
   581
    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
slouken@7941
   582
    HWND hwnd = data->hwnd;
slouken@8817
   583
    data->expected_resize = SDL_TRUE;
slouken@1895
   584
    ShowWindow(hwnd, SW_MAXIMIZE);
slouken@8817
   585
    data->expected_resize = SDL_FALSE;
slouken@1895
   586
}
slouken@1895
   587
slouken@1895
   588
void
slouken@1895
   589
WIN_MinimizeWindow(_THIS, SDL_Window * window)
slouken@1895
   590
{
slouken@1895
   591
    HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
slouken@1895
   592
    ShowWindow(hwnd, SW_MINIMIZE);
slouken@1895
   593
}
slouken@1895
   594
slouken@1895
   595
void
icculus@6422
   596
WIN_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
icculus@6422
   597
{
slouken@8817
   598
    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
slouken@8817
   599
    HWND hwnd = data->hwnd;
slouken@11251
   600
    DWORD style;
icculus@6428
   601
slouken@11251
   602
    style = GetWindowLong(hwnd, GWL_STYLE);
slouken@11251
   603
    style &= ~STYLE_MASK;
slouken@11251
   604
    style |= GetWindowStyle(window);
icculus@6428
   605
slouken@8817
   606
    data->in_border_change = SDL_TRUE;
slouken@9886
   607
    SetWindowLong(hwnd, GWL_STYLE, style);
slouken@8817
   608
    WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE);
slouken@8817
   609
    data->in_border_change = SDL_FALSE;
icculus@6422
   610
}
icculus@6422
   611
icculus@6422
   612
void
icculus@10385
   613
WIN_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
icculus@10385
   614
{
icculus@10385
   615
    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
icculus@10385
   616
    HWND hwnd = data->hwnd;
slouken@11251
   617
    DWORD style;
icculus@10385
   618
slouken@11251
   619
    style = GetWindowLong(hwnd, GWL_STYLE);
slouken@11251
   620
    style &= ~STYLE_MASK;
slouken@11251
   621
    style |= GetWindowStyle(window);
icculus@10385
   622
icculus@10385
   623
    SetWindowLong(hwnd, GWL_STYLE, style);
icculus@10385
   624
}
icculus@10385
   625
icculus@10385
   626
void
slouken@1895
   627
WIN_RestoreWindow(_THIS, SDL_Window * window)
slouken@1895
   628
{
slouken@7941
   629
    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
slouken@7941
   630
    HWND hwnd = data->hwnd;
slouken@8817
   631
    data->expected_resize = SDL_TRUE;
slouken@1895
   632
    ShowWindow(hwnd, SW_RESTORE);
slouken@8817
   633
    data->expected_resize = SDL_FALSE;
slouken@1895
   634
}
slouken@1895
   635
slouken@1895
   636
void
slouken@5305
   637
WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
slouken@5305
   638
{
slouken@5305
   639
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@5305
   640
    HWND hwnd = data->hwnd;
slouken@5305
   641
    SDL_Rect bounds;
slouken@5305
   642
    DWORD style;
slouken@5305
   643
    HWND top;
slouken@5305
   644
    int x, y;
slouken@5305
   645
    int w, h;
slouken@5305
   646
jgranick@10978
   647
    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)) {
slouken@7191
   648
        top = HWND_TOPMOST;
slouken@7191
   649
    } else {
slouken@7191
   650
        top = HWND_NOTOPMOST;
slouken@7191
   651
    }
slouken@6782
   652
slouken@5305
   653
    style = GetWindowLong(hwnd, GWL_STYLE);
slouken@5305
   654
    style &= ~STYLE_MASK;
slouken@5305
   655
    style |= GetWindowStyle(window);
slouken@5305
   656
slouken@5305
   657
    WIN_GetDisplayBounds(_this, display, &bounds);
slouken@5305
   658
slouken@5305
   659
    if (fullscreen) {
slouken@5305
   660
        x = bounds.x;
slouken@5305
   661
        y = bounds.y;
slouken@5305
   662
        w = bounds.w;
slouken@5305
   663
        h = bounds.h;
dludwig@9990
   664
dludwig@9990
   665
        /* Unset the maximized flag.  This fixes
dludwig@9990
   666
           https://bugzilla.libsdl.org/show_bug.cgi?id=3215
dludwig@9990
   667
        */
dludwig@9990
   668
        if (style & WS_MAXIMIZE) {
dludwig@9990
   669
            data->windowed_mode_was_maximized = SDL_TRUE;
dludwig@9990
   670
            style &= ~WS_MAXIMIZE;
dludwig@9990
   671
        }
slouken@5305
   672
    } else {
slouken@11575
   673
        BOOL menu;
slouken@11575
   674
dludwig@9990
   675
        /* Restore window-maximization state, as applicable.
dludwig@9990
   676
           Special care is taken to *not* do this if and when we're
dludwig@9990
   677
           alt-tab'ing away (to some other window; as indicated by
dludwig@9990
   678
           in_window_deactivation), otherwise
dludwig@9990
   679
           https://bugzilla.libsdl.org/show_bug.cgi?id=3215 can reproduce!
dludwig@9990
   680
        */
dludwig@9990
   681
        if (data->windowed_mode_was_maximized && !data->in_window_deactivation) {
dludwig@9990
   682
            style |= WS_MAXIMIZE;
dludwig@9990
   683
            data->windowed_mode_was_maximized = SDL_FALSE;
dludwig@9990
   684
        }
slouken@11461
   685
slouken@11575
   686
        menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
slouken@11575
   687
        WIN_AdjustWindowRectWithStyle(window, style, menu, &x, &y, &w, &h, SDL_FALSE);
slouken@5305
   688
    }
slouken@5305
   689
    SetWindowLong(hwnd, GWL_STYLE, style);
slouken@8817
   690
    data->expected_resize = SDL_TRUE;
slouken@8205
   691
    SetWindowPos(hwnd, top, x, y, w, h, SWP_NOCOPYBITS | SWP_NOACTIVATE);
slouken@8817
   692
    data->expected_resize = SDL_FALSE;
slouken@5305
   693
}
slouken@5305
   694
slouken@5466
   695
int
slouken@5466
   696
WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
slouken@5466
   697
{
slouken@5466
   698
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5466
   699
    SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
slouken@5466
   700
    HDC hdc;
slouken@5466
   701
    BOOL succeeded = FALSE;
slouken@5466
   702
slouken@5466
   703
    hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
slouken@5466
   704
    if (hdc) {
slouken@5466
   705
        succeeded = SetDeviceGammaRamp(hdc, (LPVOID)ramp);
slouken@5466
   706
        if (!succeeded) {
slouken@5466
   707
            WIN_SetError("SetDeviceGammaRamp()");
slouken@5466
   708
        }
slouken@5466
   709
        DeleteDC(hdc);
slouken@5466
   710
    }
slouken@5466
   711
    return succeeded ? 0 : -1;
slouken@5466
   712
}
slouken@5466
   713
slouken@5466
   714
int
slouken@5466
   715
WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
slouken@5466
   716
{
slouken@5466
   717
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5466
   718
    SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
slouken@5466
   719
    HDC hdc;
slouken@5466
   720
    BOOL succeeded = FALSE;
slouken@5466
   721
slouken@5466
   722
    hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
slouken@5466
   723
    if (hdc) {
slouken@5466
   724
        succeeded = GetDeviceGammaRamp(hdc, (LPVOID)ramp);
slouken@5466
   725
        if (!succeeded) {
slouken@5466
   726
            WIN_SetError("GetDeviceGammaRamp()");
slouken@5466
   727
        }
slouken@5466
   728
        DeleteDC(hdc);
slouken@5466
   729
    }
slouken@5466
   730
    return succeeded ? 0 : -1;
slouken@5466
   731
}
slouken@5466
   732
slouken@5305
   733
void
slouken@6662
   734
WIN_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
slouken@1895
   735
{
slouken@8072
   736
    WIN_UpdateClipCursor(window);
slouken@6782
   737
slouken@7585
   738
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@7584
   739
        UINT flags = SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE;
slouken@6782
   740
slouken@7584
   741
        if (!(window->flags & SDL_WINDOW_SHOWN)) {
slouken@7584
   742
            flags |= SWP_NOACTIVATE;
slouken@7584
   743
        }
slouken@7585
   744
        WIN_SetWindowPositionInternal(_this, window, flags);
slouken@7191
   745
    }
slouken@1895
   746
}
slouken@1895
   747
slouken@1895
   748
void
slouken@1895
   749
WIN_DestroyWindow(_THIS, SDL_Window * window)
slouken@1895
   750
{
slouken@1895
   751
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1895
   752
slouken@1895
   753
    if (data) {
slouken@1913
   754
        ReleaseDC(data->hwnd, data->hdc);
slouken@9665
   755
        RemoveProp(data->hwnd, TEXT("SDL_WindowData"));
slouken@1895
   756
        if (data->created) {
slouken@1895
   757
            DestroyWindow(data->hwnd);
slouken@11101
   758
            if (data->parent) {
slouken@11101
   759
                DestroyWindow(data->parent);
slouken@11101
   760
            }
icculus@5580
   761
        } else {
icculus@5580
   762
            /* Restore any original event handler... */
icculus@5580
   763
            if (data->wndproc != NULL) {
icculus@5580
   764
#ifdef GWLP_WNDPROC
icculus@5581
   765
                SetWindowLongPtr(data->hwnd, GWLP_WNDPROC,
icculus@5581
   766
                                 (LONG_PTR) data->wndproc);
icculus@5580
   767
#else
icculus@5581
   768
                SetWindowLong(data->hwnd, GWL_WNDPROC,
icculus@5581
   769
                              (LONG_PTR) data->wndproc);
icculus@5580
   770
#endif
icculus@5580
   771
            }
slouken@1895
   772
        }
slouken@1895
   773
        SDL_free(data);
slouken@1895
   774
    }
slouken@8978
   775
    window->driverdata = NULL;
slouken@1895
   776
}
slouken@1895
   777
slouken@1895
   778
SDL_bool
slouken@1895
   779
WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
slouken@1895
   780
{
icculus@9422
   781
    const SDL_WindowData *data = (const SDL_WindowData *) window->driverdata;
slouken@1895
   782
    if (info->version.major <= SDL_MAJOR_VERSION) {
philipp@10631
   783
        int versionnum = SDL_VERSIONNUM(info->version.major, info->version.minor, info->version.patch);
philipp@10631
   784
slouken@4900
   785
        info->subsystem = SDL_SYSWM_WINDOWS;
icculus@9422
   786
        info->info.win.window = data->hwnd;
philipp@10631
   787
philipp@10631
   788
        if (versionnum >= SDL_VERSIONNUM(2, 0, 4)) {
philipp@10631
   789
            info->info.win.hdc = data->hdc;
philipp@10631
   790
        }
philipp@10631
   791
slouken@10634
   792
        if (versionnum >= SDL_VERSIONNUM(2, 0, 5)) {
slouken@10634
   793
            info->info.win.hinstance = data->hinstance;
slouken@10634
   794
        }
slouken@10634
   795
slouken@1895
   796
        return SDL_TRUE;
slouken@1895
   797
    } else {
philipp@10945
   798
        SDL_SetError("Application not compiled with SDL %d.%d",
slouken@1895
   799
                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
slouken@1895
   800
        return SDL_FALSE;
slouken@1895
   801
    }
slouken@1895
   802
}
slouken@1895
   803
slouken@2713
   804
slouken@2713
   805
/*
slouken@2713
   806
 * Creates a HelperWindow used for DirectInput events.
slouken@2713
   807
 */
slouken@2713
   808
int
slouken@2713
   809
SDL_HelperWindowCreate(void)
slouken@2713
   810
{
slouken@3097
   811
    HINSTANCE hInstance = GetModuleHandle(NULL);
slouken@3097
   812
    WNDCLASS wce;
slouken@2713
   813
bobbens@3045
   814
    /* Make sure window isn't created twice. */
bobbens@3045
   815
    if (SDL_HelperWindow != NULL) {
bobbens@3045
   816
        return 0;
bobbens@3045
   817
    }
bobbens@3045
   818
slouken@2713
   819
    /* Create the class. */
slouken@2714
   820
    SDL_zero(wce);
slouken@3097
   821
    wce.lpfnWndProc = DefWindowProc;
slouken@2713
   822
    wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
slouken@2713
   823
    wce.hInstance = hInstance;
slouken@2713
   824
slouken@2713
   825
    /* Register the class. */
slouken@3097
   826
    SDL_HelperWindowClass = RegisterClass(&wce);
slouken@8238
   827
    if (SDL_HelperWindowClass == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) {
icculus@7037
   828
        return WIN_SetError("Unable to create Helper Window Class");
slouken@2713
   829
    }
slouken@2713
   830
slouken@2713
   831
    /* Create the window. */
slouken@2714
   832
    SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
slouken@2714
   833
                                      SDL_HelperWindowName,
slouken@3168
   834
                                      WS_OVERLAPPED, CW_USEDEFAULT,
slouken@2714
   835
                                      CW_USEDEFAULT, CW_USEDEFAULT,
icculus@6430
   836
                                      CW_USEDEFAULT, HWND_MESSAGE, NULL,
slouken@2714
   837
                                      hInstance, NULL);
slouken@2713
   838
    if (SDL_HelperWindow == NULL) {
bobbens@3045
   839
        UnregisterClass(SDL_HelperWindowClassName, hInstance);
icculus@7037
   840
        return WIN_SetError("Unable to create Helper Window");
slouken@2713
   841
    }
slouken@2713
   842
slouken@2713
   843
    return 0;
slouken@2713
   844
}
slouken@2713
   845
slouken@2713
   846
slouken@2713
   847
/*
slouken@2713
   848
 * Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
slouken@2713
   849
 */
slouken@2713
   850
void
slouken@2713
   851
SDL_HelperWindowDestroy(void)
slouken@2713
   852
{
slouken@3097
   853
    HINSTANCE hInstance = GetModuleHandle(NULL);
bobbens@2863
   854
slouken@2713
   855
    /* Destroy the window. */
bobbens@2863
   856
    if (SDL_HelperWindow != NULL) {
bobbens@2863
   857
        if (DestroyWindow(SDL_HelperWindow) == 0) {
slouken@4500
   858
            WIN_SetError("Unable to destroy Helper Window");
slouken@2865
   859
            return;
bobbens@2863
   860
        }
slouken@2713
   861
        SDL_HelperWindow = NULL;
slouken@2713
   862
    }
slouken@2713
   863
slouken@2713
   864
    /* Unregister the class. */
bobbens@2863
   865
    if (SDL_HelperWindowClass != 0) {
bobbens@2863
   866
        if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
slouken@4500
   867
            WIN_SetError("Unable to destroy Helper Window Class");
slouken@2865
   868
            return;
bobbens@2863
   869
        }
slouken@2713
   870
        SDL_HelperWindowClass = 0;
slouken@2713
   871
    }
slouken@2713
   872
}
slouken@2713
   873
jorgen@7089
   874
void WIN_OnWindowEnter(_THIS, SDL_Window * window)
jorgen@7089
   875
{
jorgen@7089
   876
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
jorgen@7089
   877
jorgen@7089
   878
    if (!data || !data->hwnd) {
jorgen@7089
   879
        /* The window wasn't fully initialized */
jorgen@7089
   880
        return;
jorgen@7089
   881
    }
jorgen@7089
   882
jgranick@10978
   883
    if (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) {
jgranick@10978
   884
        WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
jgranick@10978
   885
    }
jorgen@7089
   886
jgranick@10978
   887
#ifdef WM_MOUSELEAVE
jgranick@10978
   888
    {
jgranick@10978
   889
        TRACKMOUSEEVENT trackMouseEvent;
jgranick@10978
   890
jgranick@10978
   891
        trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
jgranick@10978
   892
        trackMouseEvent.dwFlags = TME_LEAVE;
jgranick@10978
   893
        trackMouseEvent.hwndTrack = data->hwnd;
jgranick@10978
   894
jgranick@10978
   895
        TrackMouseEvent(&trackMouseEvent);
jgranick@10978
   896
    }
jorgen@7089
   897
#endif /* WM_MOUSELEAVE */
jorgen@7089
   898
}
jorgen@7089
   899
slouken@8072
   900
void
slouken@8072
   901
WIN_UpdateClipCursor(SDL_Window *window)
slouken@8072
   902
{
slouken@8072
   903
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@8072
   904
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@12153
   905
    RECT rect;
slouken@8072
   906
slouken@8916
   907
    if (data->focus_click_pending) {
slouken@8072
   908
        return;
slouken@8072
   909
    }
slouken@8072
   910
slouken@8072
   911
    if ((mouse->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
slouken@8072
   912
        (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
slouken@8072
   913
        if (mouse->relative_mode && !mouse->relative_mode_warp) {
slouken@8072
   914
            LONG cx, cy;
slouken@8072
   915
            GetWindowRect(data->hwnd, &rect);
slouken@8072
   916
slouken@8072
   917
            cx = (rect.left + rect.right) / 2;
slouken@8072
   918
            cy = (rect.top + rect.bottom) / 2;
slouken@8072
   919
slouken@8072
   920
            /* Make an absurdly small clip rect */
slouken@8072
   921
            rect.left = cx - 1;
slouken@8072
   922
            rect.right = cx + 1;
slouken@8072
   923
            rect.top = cy - 1;
slouken@8072
   924
            rect.bottom = cy + 1;
slouken@8072
   925
slouken@12153
   926
            if (ClipCursor(&rect)) {
slouken@12153
   927
                data->cursor_clipped_rect = rect;
slouken@12153
   928
            }
slouken@8072
   929
        } else {
slouken@8072
   930
            if (GetClientRect(data->hwnd, &rect) && !IsRectEmpty(&rect)) {
slouken@8072
   931
                ClientToScreen(data->hwnd, (LPPOINT) & rect);
slouken@8072
   932
                ClientToScreen(data->hwnd, (LPPOINT) & rect + 1);
slouken@12153
   933
                if (ClipCursor(&rect)) {
slouken@12153
   934
                    data->cursor_clipped_rect = rect;
slouken@12153
   935
                }
slouken@8072
   936
            }
slouken@8072
   937
        }
slouken@12153
   938
    } else if (GetClipCursor(&rect) && SDL_memcmp(&rect, &data->cursor_clipped_rect, sizeof(rect)) == 0) {
slouken@8072
   939
        ClipCursor(NULL);
slouken@12153
   940
        SDL_zero(data->cursor_clipped_rect);
slouken@8072
   941
    }
slouken@8072
   942
}
slouken@8072
   943
icculus@8938
   944
int
icculus@8938
   945
WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
icculus@8938
   946
{
icculus@8938
   947
    return 0;  /* just succeed, the real work is done elsewhere. */
icculus@8938
   948
}
icculus@8938
   949
icculus@10025
   950
int
icculus@10025
   951
WIN_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
icculus@10025
   952
{
icculus@10025
   953
    const SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
icculus@10025
   954
    const HWND hwnd = data->hwnd;
icculus@10025
   955
    const LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
icculus@10025
   956
icculus@10025
   957
    SDL_assert(style != 0);
icculus@10025
   958
icculus@10025
   959
    if (opacity == 1.0f) {
icculus@10025
   960
        /* want it fully opaque, just mark it unlayered if necessary. */
icculus@10025
   961
        if (style & WS_EX_LAYERED) {
icculus@10025
   962
            if (SetWindowLong(hwnd, GWL_EXSTYLE, style & ~WS_EX_LAYERED) == 0) {
icculus@10025
   963
                return WIN_SetError("SetWindowLong()");
icculus@10025
   964
            }
icculus@10025
   965
        }
icculus@10025
   966
    } else {
icculus@10025
   967
        const BYTE alpha = (BYTE) ((int) (opacity * 255.0f));
icculus@10025
   968
        /* want it transparent, mark it layered if necessary. */
icculus@10025
   969
        if ((style & WS_EX_LAYERED) == 0) {
icculus@10025
   970
            if (SetWindowLong(hwnd, GWL_EXSTYLE, style | WS_EX_LAYERED) == 0) {
icculus@10025
   971
                return WIN_SetError("SetWindowLong()");
icculus@10025
   972
            }
icculus@10025
   973
        }
icculus@10025
   974
icculus@10025
   975
        if (SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA) == 0) {
icculus@10025
   976
            return WIN_SetError("SetLayeredWindowAttributes()");
icculus@10025
   977
        }
icculus@10025
   978
    }
icculus@10025
   979
icculus@10025
   980
    return 0;
icculus@10025
   981
}
icculus@10025
   982
icculus@12070
   983
void
icculus@12070
   984
WIN_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept)
icculus@12070
   985
{
icculus@12070
   986
    const SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
icculus@12070
   987
    DragAcceptFiles(data->hwnd, accept ? TRUE : FALSE);
icculus@12070
   988
}
icculus@12070
   989
slouken@6044
   990
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
slouken@6044
   991
slouken@1895
   992
/* vi: set ts=4 sw=4 expandtab: */