cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_windowswindow.c (22802B)


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