src/video/windows/SDL_windowsevents.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 01 Oct 2016 13:14:51 -0700
changeset 10426 5c06c3aaca68
parent 10417 b307b3ebce7d
child 10427 29ea63235018
permissions -rw-r--r--
Fixed bug 3405 - Wrong default icon size on windows systems

Evgeny Vrublevsky

Original code in the video/windows/SDL_windowsevents.c registers obsolete WNDCLASS (not WNDCLASSEX). As the result only one icon size is used as the small and normal icons. Also original code doesn't specify required size of an icon. As the result when 256x256 icon is available, the program uses it as a default icon, and it looks ugly.

We have to use WNDCLASSEX and load icons with proper sizes which we can get using GetSystemMetrics.

Better idea. We could use the first icon from resources, like the Explorer does. Patch is included. It also correctly loads large and small icons, so it will look nice everywhere.
slouken@1895
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@9998
     3
  Copyright (C) 1997-2016 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@2710
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_WINDOWS
slouken@1895
    24
slouken@5062
    25
#include "SDL_windowsvideo.h"
slouken@5062
    26
#include "SDL_windowsshape.h"
slouken@9597
    27
#include "SDL_system.h"
slouken@1895
    28
#include "SDL_syswm.h"
slouken@8218
    29
#include "SDL_timer.h"
slouken@1895
    30
#include "SDL_vkeys.h"
slouken@1895
    31
#include "../../events/SDL_events_c.h"
slouken@4919
    32
#include "../../events/SDL_touch_c.h"
slouken@6938
    33
#include "../../events/scancodes_windows.h"
icculus@8942
    34
#include "SDL_assert.h"
andrewb@9829
    35
#include "SDL_hints.h"
slouken@1895
    36
slouken@6523
    37
/* Dropfile support */
slouken@6523
    38
#include <shellapi.h>
slouken@6523
    39
jorgen@7276
    40
/* For GET_X_LPARAM, GET_Y_LPARAM. */
jorgen@7276
    41
#include <windowsx.h>
slouken@6523
    42
gabomdq@7678
    43
/* #define WMMSG_DEBUG */
slouken@1895
    44
#ifdef WMMSG_DEBUG
slouken@7191
    45
#include <stdio.h>
slouken@1895
    46
#include "wmmsg.h"
slouken@1895
    47
#endif
slouken@1895
    48
dludwig@9668
    49
/* For processing mouse WM_*BUTTON* and WM_MOUSEMOVE message-data from GetMessageExtraInfo() */
dludwig@9668
    50
#define MOUSEEVENTF_FROMTOUCH 0xFF515700
dludwig@9668
    51
slouken@1895
    52
/* Masks for processing the windows KEYDOWN and KEYUP messages */
slouken@2317
    53
#define REPEATED_KEYMASK    (1<<30)
slouken@2317
    54
#define EXTENDED_KEYMASK    (1<<24)
slouken@1895
    55
bob@2324
    56
#define VK_ENTER    10          /* Keypad Enter ... no VKEY defined? */
slouken@6931
    57
#ifndef VK_OEM_NEC_EQUAL
slouken@7191
    58
#define VK_OEM_NEC_EQUAL 0x92
slouken@6931
    59
#endif
slouken@2313
    60
icculus@2127
    61
/* Make sure XBUTTON stuff is defined that isn't in older Platform SDKs... */
icculus@2127
    62
#ifndef WM_XBUTTONDOWN
icculus@2127
    63
#define WM_XBUTTONDOWN 0x020B
icculus@2127
    64
#endif
icculus@2127
    65
#ifndef WM_XBUTTONUP
icculus@2127
    66
#define WM_XBUTTONUP 0x020C
icculus@2127
    67
#endif
icculus@2127
    68
#ifndef GET_XBUTTON_WPARAM
icculus@2127
    69
#define GET_XBUTTON_WPARAM(w) (HIWORD(w))
icculus@2127
    70
#endif
bobbens@2733
    71
#ifndef WM_INPUT
bobbens@2733
    72
#define WM_INPUT 0x00ff
bobbens@2733
    73
#endif
slouken@4932
    74
#ifndef WM_TOUCH
slouken@4868
    75
#define WM_TOUCH 0x0240
slouken@4932
    76
#endif
slouken@7911
    77
#ifndef WM_MOUSEHWHEEL
slouken@7911
    78
#define WM_MOUSEHWHEEL 0x020E
slouken@7911
    79
#endif
slouken@8624
    80
#ifndef WM_UNICHAR
slouken@8624
    81
#define WM_UNICHAR 0x0109
slouken@8624
    82
#endif
slouken@4919
    83
slouken@7191
    84
static SDL_Scancode
slouken@8813
    85
WindowsScanCodeToSDLScanCode(LPARAM lParam, WPARAM wParam)
jorgen@6922
    86
{
slouken@7191
    87
    SDL_Scancode code;
slouken@7191
    88
    char bIsExtended;
slouken@8813
    89
    int nScanCode = (lParam >> 16) & 0xFF;
jorgen@6922
    90
slouken@7191
    91
    /* 0x45 here to work around both pause and numlock sharing the same scancode, so use the VK key to tell them apart */
slouken@8813
    92
    if (nScanCode == 0 || nScanCode == 0x45) {
slouken@8813
    93
        switch(wParam) {
slouken@7191
    94
        case VK_CLEAR: return SDL_SCANCODE_CLEAR;
slouken@7191
    95
        case VK_MODECHANGE: return SDL_SCANCODE_MODE;
slouken@7191
    96
        case VK_SELECT: return SDL_SCANCODE_SELECT;
slouken@7191
    97
        case VK_EXECUTE: return SDL_SCANCODE_EXECUTE;
slouken@7191
    98
        case VK_HELP: return SDL_SCANCODE_HELP;
slouken@7191
    99
        case VK_PAUSE: return SDL_SCANCODE_PAUSE;
slouken@7191
   100
        case VK_NUMLOCK: return SDL_SCANCODE_NUMLOCKCLEAR;
jorgen@6922
   101
slouken@7191
   102
        case VK_F13: return SDL_SCANCODE_F13;
slouken@7191
   103
        case VK_F14: return SDL_SCANCODE_F14;
slouken@7191
   104
        case VK_F15: return SDL_SCANCODE_F15;
slouken@7191
   105
        case VK_F16: return SDL_SCANCODE_F16;
slouken@7191
   106
        case VK_F17: return SDL_SCANCODE_F17;
slouken@7191
   107
        case VK_F18: return SDL_SCANCODE_F18;
slouken@7191
   108
        case VK_F19: return SDL_SCANCODE_F19;
slouken@7191
   109
        case VK_F20: return SDL_SCANCODE_F20;
slouken@7191
   110
        case VK_F21: return SDL_SCANCODE_F21;
slouken@7191
   111
        case VK_F22: return SDL_SCANCODE_F22;
slouken@7191
   112
        case VK_F23: return SDL_SCANCODE_F23;
slouken@7191
   113
        case VK_F24: return SDL_SCANCODE_F24;
jorgen@6922
   114
slouken@7191
   115
        case VK_OEM_NEC_EQUAL: return SDL_SCANCODE_KP_EQUALS;
slouken@7191
   116
        case VK_BROWSER_BACK: return SDL_SCANCODE_AC_BACK;
slouken@7191
   117
        case VK_BROWSER_FORWARD: return SDL_SCANCODE_AC_FORWARD;
slouken@7191
   118
        case VK_BROWSER_REFRESH: return SDL_SCANCODE_AC_REFRESH;
slouken@7191
   119
        case VK_BROWSER_STOP: return SDL_SCANCODE_AC_STOP;
slouken@7191
   120
        case VK_BROWSER_SEARCH: return SDL_SCANCODE_AC_SEARCH;
slouken@7191
   121
        case VK_BROWSER_FAVORITES: return SDL_SCANCODE_AC_BOOKMARKS;
slouken@7191
   122
        case VK_BROWSER_HOME: return SDL_SCANCODE_AC_HOME;
slouken@7191
   123
        case VK_VOLUME_MUTE: return SDL_SCANCODE_AUDIOMUTE;
slouken@7191
   124
        case VK_VOLUME_DOWN: return SDL_SCANCODE_VOLUMEDOWN;
slouken@7191
   125
        case VK_VOLUME_UP: return SDL_SCANCODE_VOLUMEUP;
jorgen@6922
   126
slouken@7191
   127
        case VK_MEDIA_NEXT_TRACK: return SDL_SCANCODE_AUDIONEXT;
slouken@7191
   128
        case VK_MEDIA_PREV_TRACK: return SDL_SCANCODE_AUDIOPREV;
slouken@7191
   129
        case VK_MEDIA_STOP: return SDL_SCANCODE_AUDIOSTOP;
slouken@7191
   130
        case VK_MEDIA_PLAY_PAUSE: return SDL_SCANCODE_AUDIOPLAY;
slouken@7191
   131
        case VK_LAUNCH_MAIL: return SDL_SCANCODE_MAIL;
slouken@7191
   132
        case VK_LAUNCH_MEDIA_SELECT: return SDL_SCANCODE_MEDIASELECT;
jorgen@6922
   133
slouken@7191
   134
        case VK_OEM_102: return SDL_SCANCODE_NONUSBACKSLASH;
jorgen@6922
   135
slouken@7191
   136
        case VK_ATTN: return SDL_SCANCODE_SYSREQ;
slouken@7191
   137
        case VK_CRSEL: return SDL_SCANCODE_CRSEL;
slouken@7191
   138
        case VK_EXSEL: return SDL_SCANCODE_EXSEL;
slouken@7191
   139
        case VK_OEM_CLEAR: return SDL_SCANCODE_CLEAR;
jorgen@6922
   140
slouken@7191
   141
        case VK_LAUNCH_APP1: return SDL_SCANCODE_APP1;
slouken@7191
   142
        case VK_LAUNCH_APP2: return SDL_SCANCODE_APP2;
jorgen@6922
   143
slouken@7191
   144
        default: return SDL_SCANCODE_UNKNOWN;
slouken@7191
   145
        }
slouken@7191
   146
    }
jorgen@6922
   147
slouken@8813
   148
    if (nScanCode > 127)
slouken@7191
   149
        return SDL_SCANCODE_UNKNOWN;
slouken@7191
   150
slouken@7191
   151
    code = windows_scancode_table[nScanCode];
slouken@7191
   152
slouken@8813
   153
    bIsExtended = (lParam & (1 << 24)) != 0;
slouken@8813
   154
    if (!bIsExtended) {
slouken@8813
   155
        switch (code) {
slouken@7191
   156
        case SDL_SCANCODE_HOME:
slouken@7191
   157
            return SDL_SCANCODE_KP_7;
slouken@7191
   158
        case SDL_SCANCODE_UP:
slouken@7191
   159
            return SDL_SCANCODE_KP_8;
slouken@7191
   160
        case SDL_SCANCODE_PAGEUP:
slouken@7191
   161
            return SDL_SCANCODE_KP_9;
slouken@7191
   162
        case SDL_SCANCODE_LEFT:
slouken@7191
   163
            return SDL_SCANCODE_KP_4;
slouken@7191
   164
        case SDL_SCANCODE_RIGHT:
slouken@7191
   165
            return SDL_SCANCODE_KP_6;
slouken@7191
   166
        case SDL_SCANCODE_END:
slouken@7191
   167
            return SDL_SCANCODE_KP_1;
slouken@7191
   168
        case SDL_SCANCODE_DOWN:
slouken@7191
   169
            return SDL_SCANCODE_KP_2;
slouken@7191
   170
        case SDL_SCANCODE_PAGEDOWN:
slouken@7191
   171
            return SDL_SCANCODE_KP_3;
slouken@7191
   172
        case SDL_SCANCODE_INSERT:
slouken@7191
   173
            return SDL_SCANCODE_KP_0;
slouken@7191
   174
        case SDL_SCANCODE_DELETE:
slouken@7191
   175
            return SDL_SCANCODE_KP_PERIOD;
slouken@7191
   176
        case SDL_SCANCODE_PRINTSCREEN:
slouken@7191
   177
            return SDL_SCANCODE_KP_MULTIPLY;
slouken@7029
   178
        default:
slouken@7029
   179
            break;
slouken@7191
   180
        }
slouken@8813
   181
    } else {
slouken@8813
   182
        switch (code) {
slouken@7191
   183
        case SDL_SCANCODE_RETURN:
slouken@7191
   184
            return SDL_SCANCODE_KP_ENTER;
slouken@7191
   185
        case SDL_SCANCODE_LALT:
slouken@7191
   186
            return SDL_SCANCODE_RALT;
slouken@7191
   187
        case SDL_SCANCODE_LCTRL:
slouken@7191
   188
            return SDL_SCANCODE_RCTRL;
slouken@7191
   189
        case SDL_SCANCODE_SLASH:
slouken@7191
   190
            return SDL_SCANCODE_KP_DIVIDE;
slouken@7191
   191
        case SDL_SCANCODE_CAPSLOCK:
slouken@7191
   192
            return SDL_SCANCODE_KP_PLUS;
slouken@7191
   193
        default:
slouken@7191
   194
            break;
slouken@7191
   195
        }
slouken@7191
   196
    }
jorgen@6922
   197
slouken@7191
   198
    return code;
jorgen@6922
   199
}
jorgen@6922
   200
slouken@10379
   201
static SDL_bool
slouken@10379
   202
WIN_ShouldIgnoreFocusClick()
slouken@10379
   203
{
icculus@10389
   204
    const char *hint = SDL_GetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH);
slouken@10379
   205
    return (!hint || (*hint == '0')) ? SDL_TRUE : SDL_FALSE;
slouken@10379
   206
}
jorgen@6922
   207
slouken@7191
   208
void
dludwig@9668
   209
WIN_CheckWParamMouseButton(SDL_bool bwParamMousePressed, SDL_bool bSDLMousePressed, SDL_WindowData *data, Uint8 button, SDL_MouseID mouseID)
slouken@6943
   210
{
slouken@10377
   211
    if (data->focus_click_pending & SDL_BUTTON(button)) {
slouken@10377
   212
        /* Ignore the button click for activation */
slouken@10377
   213
        if (!bwParamMousePressed) {
slouken@10377
   214
            data->focus_click_pending &= ~SDL_BUTTON(button);
slouken@10377
   215
            if (!data->focus_click_pending) {
slouken@10377
   216
                WIN_UpdateClipCursor(data->window);
slouken@10377
   217
            }
slouken@10377
   218
        }
slouken@10379
   219
        if (WIN_ShouldIgnoreFocusClick()) {
slouken@10379
   220
            return;
slouken@10379
   221
        }
slouken@8916
   222
    }
slouken@8916
   223
slouken@8813
   224
    if (bwParamMousePressed && !bSDLMousePressed) {
dludwig@9668
   225
        SDL_SendMouseButton(data->window, mouseID, SDL_PRESSED, button);
slouken@8813
   226
    } else if (!bwParamMousePressed && bSDLMousePressed) {
dludwig@9668
   227
        SDL_SendMouseButton(data->window, mouseID, SDL_RELEASED, button);
slouken@7191
   228
    }
slouken@6943
   229
}
slouken@6943
   230
slouken@6943
   231
/*
slouken@6943
   232
* Some windows systems fail to send a WM_LBUTTONDOWN sometimes, but each mouse move contains the current button state also
slouken@6943
   233
*  so this funciton reconciles our view of the world with the current buttons reported by windows
slouken@6943
   234
*/
slouken@7191
   235
void
dludwig@9668
   236
WIN_CheckWParamMouseButtons(WPARAM wParam, SDL_WindowData *data, SDL_MouseID mouseID)
slouken@6943
   237
{
slouken@8813
   238
    if (wParam != data->mouse_button_flags) {
slouken@8813
   239
        Uint32 mouseFlags = SDL_GetMouseState(NULL, NULL);
dludwig@9668
   240
        WIN_CheckWParamMouseButton((wParam & MK_LBUTTON), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, mouseID);
dludwig@9668
   241
        WIN_CheckWParamMouseButton((wParam & MK_MBUTTON), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, mouseID);
dludwig@9668
   242
        WIN_CheckWParamMouseButton((wParam & MK_RBUTTON), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, mouseID);
dludwig@9668
   243
        WIN_CheckWParamMouseButton((wParam & MK_XBUTTON1), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, mouseID);
dludwig@9668
   244
        WIN_CheckWParamMouseButton((wParam & MK_XBUTTON2), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, mouseID);
slouken@7191
   245
        data->mouse_button_flags = wParam;
slouken@7191
   246
    }
slouken@6943
   247
}
slouken@6943
   248
slouken@6943
   249
slouken@7191
   250
void
slouken@8813
   251
WIN_CheckRawMouseButtons(ULONG rawButtons, SDL_WindowData *data)
slouken@6943
   252
{
slouken@8813
   253
    if (rawButtons != data->mouse_button_flags) {
slouken@8813
   254
        Uint32 mouseFlags = SDL_GetMouseState(NULL, NULL);
slouken@8813
   255
        if ((rawButtons & RI_MOUSE_BUTTON_1_DOWN))
dludwig@9668
   256
            WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_1_DOWN), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, 0);
slouken@8813
   257
        if ((rawButtons & RI_MOUSE_BUTTON_1_UP))
dludwig@9668
   258
            WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_1_UP), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, 0);
slouken@8813
   259
        if ((rawButtons & RI_MOUSE_BUTTON_2_DOWN))
dludwig@9668
   260
            WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_2_DOWN), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, 0);
slouken@8813
   261
        if ((rawButtons & RI_MOUSE_BUTTON_2_UP))
dludwig@9668
   262
            WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_2_UP), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, 0);
slouken@8813
   263
        if ((rawButtons & RI_MOUSE_BUTTON_3_DOWN))
dludwig@9668
   264
            WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_3_DOWN), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, 0);
slouken@8813
   265
        if ((rawButtons & RI_MOUSE_BUTTON_3_UP))
dludwig@9668
   266
            WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_3_UP), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, 0);
slouken@8813
   267
        if ((rawButtons & RI_MOUSE_BUTTON_4_DOWN))
dludwig@9668
   268
            WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_4_DOWN), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, 0);
slouken@8813
   269
        if ((rawButtons & RI_MOUSE_BUTTON_4_UP))
dludwig@9668
   270
            WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_4_UP), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, 0);
slouken@8813
   271
        if ((rawButtons & RI_MOUSE_BUTTON_5_DOWN))
dludwig@9668
   272
            WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_5_DOWN), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, 0);
slouken@8813
   273
        if ((rawButtons & RI_MOUSE_BUTTON_5_UP))
dludwig@9668
   274
            WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_5_UP), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, 0);
slouken@7191
   275
        data->mouse_button_flags = rawButtons;
slouken@7191
   276
    }
slouken@6943
   277
}
slouken@6943
   278
slouken@8212
   279
void
slouken@8813
   280
WIN_CheckAsyncMouseRelease(SDL_WindowData *data)
slouken@8212
   281
{
slouken@8212
   282
    Uint32 mouseFlags;
slouken@8212
   283
    SHORT keyState;
slouken@8212
   284
slouken@8212
   285
    /* mouse buttons may have changed state here, we need to resync them,
slouken@8212
   286
       but we will get a WM_MOUSEMOVE right away which will fix things up if in non raw mode also
slouken@8212
   287
    */
slouken@8813
   288
    mouseFlags = SDL_GetMouseState(NULL, NULL);
slouken@8212
   289
slouken@8813
   290
    keyState = GetAsyncKeyState(VK_LBUTTON);
slouken@8796
   291
    if (!(keyState & 0x8000)) {
dludwig@9668
   292
        WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, 0);
slouken@8796
   293
    }
slouken@8796
   294
    keyState = GetAsyncKeyState(VK_RBUTTON);
slouken@8796
   295
    if (!(keyState & 0x8000)) {
dludwig@9668
   296
        WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, 0);
slouken@8796
   297
    }
slouken@8796
   298
    keyState = GetAsyncKeyState(VK_MBUTTON);
slouken@8796
   299
    if (!(keyState & 0x8000)) {
dludwig@9668
   300
        WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, 0);
slouken@8796
   301
    }
slouken@8796
   302
    keyState = GetAsyncKeyState(VK_XBUTTON1);
slouken@8796
   303
    if (!(keyState & 0x8000)) {
dludwig@9668
   304
        WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, 0);
slouken@8796
   305
    }
slouken@8796
   306
    keyState = GetAsyncKeyState(VK_XBUTTON2);
slouken@8796
   307
    if (!(keyState & 0x8000)) {
dludwig@9668
   308
        WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, 0);
slouken@8796
   309
    }
slouken@8212
   310
    data->mouse_button_flags = 0;
slouken@8212
   311
}
slouken@8212
   312
slouken@9781
   313
BOOL 
slouken@7645
   314
WIN_ConvertUTF32toUTF8(UINT32 codepoint, char * text)
slouken@7645
   315
{
slouken@7645
   316
    if (codepoint <= 0x7F) {
slouken@7645
   317
        text[0] = (char) codepoint;
slouken@7645
   318
        text[1] = '\0';
slouken@7645
   319
    } else if (codepoint <= 0x7FF) {
slouken@7645
   320
        text[0] = 0xC0 | (char) ((codepoint >> 6) & 0x1F);
slouken@7645
   321
        text[1] = 0x80 | (char) (codepoint & 0x3F);
slouken@7645
   322
        text[2] = '\0';
slouken@7645
   323
    } else if (codepoint <= 0xFFFF) {
slouken@7645
   324
        text[0] = 0xE0 | (char) ((codepoint >> 12) & 0x0F);
slouken@7645
   325
        text[1] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
slouken@7645
   326
        text[2] = 0x80 | (char) (codepoint & 0x3F);
slouken@7645
   327
        text[3] = '\0';
slouken@7645
   328
    } else if (codepoint <= 0x10FFFF) {
slouken@7645
   329
        text[0] = 0xF0 | (char) ((codepoint >> 18) & 0x0F);
slouken@7645
   330
        text[1] = 0x80 | (char) ((codepoint >> 12) & 0x3F);
slouken@7645
   331
        text[2] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
slouken@7645
   332
        text[3] = 0x80 | (char) (codepoint & 0x3F);
slouken@7645
   333
        text[4] = '\0';
slouken@7645
   334
    } else {
slouken@7645
   335
        return SDL_FALSE;
slouken@7645
   336
    }
slouken@7645
   337
    return SDL_TRUE;
slouken@7645
   338
}
slouken@7645
   339
andrewb@9829
   340
static SDL_bool
andrewb@9829
   341
ShouldGenerateWindowCloseOnAltF4(void)
andrewb@9829
   342
{
andrewb@9829
   343
    const char *hint;
andrewb@9829
   344
    
andrewb@9829
   345
    hint = SDL_GetHint(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4);
andrewb@9829
   346
    if (hint) {
andrewb@9829
   347
        if (*hint == '0') {
andrewb@9829
   348
            return SDL_TRUE;
andrewb@9829
   349
        } else {
andrewb@9829
   350
            return SDL_FALSE;
andrewb@9829
   351
        }
andrewb@9829
   352
    }
andrewb@9829
   353
    return SDL_TRUE;
andrewb@9829
   354
}
andrewb@9829
   355
slouken@1895
   356
LRESULT CALLBACK
slouken@1895
   357
WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
slouken@1895
   358
{
slouken@1895
   359
    SDL_WindowData *data;
slouken@3566
   360
    LRESULT returnCode = -1;
slouken@1895
   361
slouken@1951
   362
    /* Send a SDL_SYSWMEVENT if the application wants them */
slouken@4429
   363
    if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
slouken@1951
   364
        SDL_SysWMmsg wmmsg;
slouken@1951
   365
slouken@1951
   366
        SDL_VERSION(&wmmsg.version);
slouken@4900
   367
        wmmsg.subsystem = SDL_SYSWM_WINDOWS;
slouken@5056
   368
        wmmsg.msg.win.hwnd = hwnd;
slouken@5056
   369
        wmmsg.msg.win.msg = msg;
slouken@5056
   370
        wmmsg.msg.win.wParam = wParam;
slouken@5056
   371
        wmmsg.msg.win.lParam = lParam;
slouken@1951
   372
        SDL_SendSysWMEvent(&wmmsg);
slouken@1951
   373
    }
slouken@1951
   374
slouken@1895
   375
    /* Get the window data for the window */
slouken@1895
   376
    data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData"));
slouken@1895
   377
    if (!data) {
slouken@1895
   378
        return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
slouken@1895
   379
    }
jimtla@4650
   380
slouken@1895
   381
#ifdef WMMSG_DEBUG
slouken@7941
   382
    {
slouken@7941
   383
        char message[1024];
slouken@7941
   384
        if (msg > MAX_WMMSG) {
slouken@7941
   385
            SDL_snprintf(message, sizeof(message), "Received windows message: %p UNKNOWN (%d) -- 0x%X, 0x%X\n", hwnd, msg, wParam, lParam);
slouken@7941
   386
        } else {
slouken@7941
   387
            SDL_snprintf(message, sizeof(message), "Received windows message: %p %s -- 0x%X, 0x%X\n", hwnd, wmtab[msg], wParam, lParam);
slouken@7941
   388
        }
slouken@7941
   389
        OutputDebugStringA(message);
slouken@7941
   390
    }
slouken@7816
   391
#endif /* WMMSG_DEBUG */
slouken@2710
   392
dewyatt@4752
   393
    if (IME_HandleMessage(hwnd, msg, wParam, &lParam, data->videodata))
dewyatt@4752
   394
        return 0;
slouken@1895
   395
slouken@1895
   396
    switch (msg) {
slouken@1895
   397
slouken@1895
   398
    case WM_SHOWWINDOW:
slouken@1895
   399
        {
slouken@1895
   400
            if (wParam) {
slouken@3685
   401
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
slouken@1895
   402
            } else {
slouken@3685
   403
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
slouken@1895
   404
            }
slouken@1895
   405
        }
slouken@1895
   406
        break;
slouken@1895
   407
slouken@1895
   408
    case WM_ACTIVATE:
slouken@1895
   409
        {
slouken@8796
   410
            POINT cursorPos;
slouken@1895
   411
            BOOL minimized;
slouken@1895
   412
slouken@1895
   413
            minimized = HIWORD(wParam);
slouken@1895
   414
            if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
slouken@10377
   415
                if (GetAsyncKeyState(VK_LBUTTON)) {
slouken@10377
   416
                    data->focus_click_pending |= SDL_BUTTON_LMASK;
slouken@10377
   417
                }
slouken@10377
   418
                if (GetAsyncKeyState(VK_RBUTTON)) {
slouken@10377
   419
                    data->focus_click_pending |= SDL_BUTTON_RMASK;
slouken@10377
   420
                }
slouken@10377
   421
                if (GetAsyncKeyState(VK_MBUTTON)) {
slouken@10377
   422
                    data->focus_click_pending |= SDL_BUTTON_MMASK;
slouken@10377
   423
                }
slouken@10377
   424
                if (GetAsyncKeyState(VK_XBUTTON1)) {
slouken@10377
   425
                    data->focus_click_pending |= SDL_BUTTON_X1MASK;
slouken@10377
   426
                }
slouken@10377
   427
                if (GetAsyncKeyState(VK_XBUTTON2)) {
slouken@10377
   428
                    data->focus_click_pending |= SDL_BUTTON_X2MASK;
slouken@10377
   429
                }
slouken@10377
   430
                
slouken@3685
   431
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
slouken@4465
   432
                if (SDL_GetKeyboardFocus() != data->window) {
slouken@4465
   433
                    SDL_SetKeyboardFocus(data->window);
slouken@1895
   434
                }
slouken@8796
   435
                
slouken@8796
   436
                GetCursorPos(&cursorPos);
slouken@8796
   437
                ScreenToClient(hwnd, &cursorPos);
slouken@8796
   438
                SDL_SendMouseMotion(data->window, 0, 0, cursorPos.x, cursorPos.y);
slouken@8796
   439
                
slouken@8212
   440
                WIN_CheckAsyncMouseRelease(data);
slouken@6350
   441
slouken@4504
   442
                /*
slouken@4504
   443
                 * FIXME: Update keyboard state
slouken@4504
   444
                 */
slouken@4504
   445
                WIN_CheckClipboardUpdate(data->videodata);
icculus@9974
   446
icculus@9974
   447
                SDL_ToggleModState(KMOD_CAPS, (GetKeyState(VK_CAPITAL) & 0x0001) != 0);
icculus@9974
   448
                SDL_ToggleModState(KMOD_NUM, (GetKeyState(VK_NUMLOCK) & 0x0001) != 0);
slouken@1895
   449
            } else {
dludwig@9990
   450
                data->in_window_deactivation = SDL_TRUE;
dludwig@9990
   451
slouken@4465
   452
                if (SDL_GetKeyboardFocus() == data->window) {
slouken@4465
   453
                    SDL_SetKeyboardFocus(NULL);
slouken@10411
   454
                    WIN_ResetDeadKeys();
slouken@1895
   455
                }
slouken@8050
   456
slouken@8050
   457
                ClipCursor(NULL);
dludwig@9990
   458
dludwig@9990
   459
                data->in_window_deactivation = SDL_FALSE;
slouken@1895
   460
            }
slouken@1895
   461
        }
slouken@3566
   462
        returnCode = 0;
slouken@3566
   463
        break;
slouken@1895
   464
slouken@7191
   465
    case WM_MOUSEMOVE:
slouken@8071
   466
        {
slouken@8071
   467
            SDL_Mouse *mouse = SDL_GetMouse();
slouken@8071
   468
            if (!mouse->relative_mode || mouse->relative_mode_warp) {
dludwig@9668
   469
                SDL_MouseID mouseID = (((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) ? SDL_TOUCH_MOUSEID : 0);
dludwig@9668
   470
                SDL_SendMouseMotion(data->window, mouseID, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
slouken@8071
   471
            }
slouken@8071
   472
        }
slouken@7191
   473
        /* don't break here, fall through to check the wParam like the button presses */
slouken@7191
   474
    case WM_LBUTTONUP:
slouken@7191
   475
    case WM_RBUTTONUP:
slouken@7191
   476
    case WM_MBUTTONUP:
slouken@7191
   477
    case WM_XBUTTONUP:
slouken@7191
   478
    case WM_LBUTTONDOWN:
slouken@8713
   479
    case WM_LBUTTONDBLCLK:
slouken@7191
   480
    case WM_RBUTTONDOWN:
slouken@8713
   481
    case WM_RBUTTONDBLCLK:
slouken@7191
   482
    case WM_MBUTTONDOWN:
slouken@8713
   483
    case WM_MBUTTONDBLCLK:
slouken@7191
   484
    case WM_XBUTTONDOWN:
slouken@8713
   485
    case WM_XBUTTONDBLCLK:
slouken@8071
   486
        {
slouken@8071
   487
            SDL_Mouse *mouse = SDL_GetMouse();
slouken@8071
   488
            if (!mouse->relative_mode || mouse->relative_mode_warp) {
dludwig@9668
   489
                SDL_MouseID mouseID = (((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) ? SDL_TOUCH_MOUSEID : 0);
dludwig@9668
   490
                WIN_CheckWParamMouseButtons(wParam, data, mouseID);
slouken@8071
   491
            }
slouken@8071
   492
        }
slouken@7191
   493
        break;
slouken@3139
   494
slouken@7191
   495
    case WM_INPUT:
slouken@8071
   496
        {
slouken@8071
   497
            SDL_Mouse *mouse = SDL_GetMouse();
slouken@8071
   498
            HRAWINPUT hRawInput = (HRAWINPUT)lParam;
slouken@8071
   499
            RAWINPUT inp;
slouken@8071
   500
            UINT size = sizeof(inp);
icculus@8942
   501
            const SDL_bool isRelative = mouse->relative_mode || mouse->relative_mode_warp;
icculus@8942
   502
            const SDL_bool isCapture = ((data->window->flags & SDL_WINDOW_MOUSE_CAPTURE) != 0);
slouken@6782
   503
icculus@8942
   504
            if (!isRelative || mouse->focus != data->window) {
icculus@8942
   505
                if (!isCapture) {
icculus@8942
   506
                    break;
icculus@8942
   507
                }
slouken@8071
   508
            }
slouken@6782
   509
slouken@8071
   510
            GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER));
slouken@6350
   511
slouken@8071
   512
            /* Mouse data */
slouken@8071
   513
            if (inp.header.dwType == RIM_TYPEMOUSE) {
icculus@8942
   514
                if (isRelative) {
slouken@8976
   515
                    RAWMOUSE* rawmouse = &inp.data.mouse;
slouken@6350
   516
slouken@8976
   517
                    if ((rawmouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) {
slouken@8976
   518
                        SDL_SendMouseMotion(data->window, 0, 1, (int)rawmouse->lLastX, (int)rawmouse->lLastY);
icculus@8942
   519
                    } else {
icculus@8942
   520
                        /* synthesize relative moves from the abs position */
icculus@8942
   521
                        static SDL_Point initialMousePoint;
icculus@8942
   522
                        if (initialMousePoint.x == 0 && initialMousePoint.y == 0) {
slouken@8976
   523
                            initialMousePoint.x = rawmouse->lLastX;
slouken@8976
   524
                            initialMousePoint.y = rawmouse->lLastY;
icculus@8942
   525
                        }
icculus@8942
   526
slouken@8976
   527
                        SDL_SendMouseMotion(data->window, 0, 1, (int)(rawmouse->lLastX-initialMousePoint.x), (int)(rawmouse->lLastY-initialMousePoint.y) );
icculus@8942
   528
slouken@8976
   529
                        initialMousePoint.x = rawmouse->lLastX;
slouken@8976
   530
                        initialMousePoint.y = rawmouse->lLastY;
slouken@8071
   531
                    }
slouken@8976
   532
                    WIN_CheckRawMouseButtons(rawmouse->usButtonFlags, data);
icculus@8942
   533
                } else if (isCapture) {
icculus@8942
   534
                    /* we check for where Windows thinks the system cursor lives in this case, so we don't really lose mouse accel, etc. */
icculus@8942
   535
                    POINT pt;
icculus@8942
   536
                    GetCursorPos(&pt);
icculus@8942
   537
                    if (WindowFromPoint(pt) != hwnd) {  /* if in the window, WM_MOUSEMOVE, etc, will cover it. */
slouken@8976
   538
                        ScreenToClient(hwnd, &pt);
icculus@8942
   539
                        SDL_SendMouseMotion(data->window, 0, 0, (int) pt.x, (int) pt.y);
icculus@8949
   540
                        SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_LEFT);
icculus@8949
   541
                        SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_RIGHT);
icculus@8949
   542
                        SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_MBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_MIDDLE);
icculus@8949
   543
                        SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_XBUTTON1) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X1);
icculus@8949
   544
                        SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_XBUTTON2) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X2);
icculus@8942
   545
                    }
icculus@8942
   546
                } else {
icculus@8942
   547
                    SDL_assert(0 && "Shouldn't happen");
slouken@7191
   548
                }
slouken@7191
   549
            }
slouken@7191
   550
        }
slouken@7191
   551
        break;
slouken@6350
   552
slouken@5049
   553
    case WM_MOUSEWHEEL:
slouken@5049
   554
        {
slouken@7813
   555
            static short s_AccumulatedMotion;
slouken@5049
   556
slouken@7813
   557
            s_AccumulatedMotion += GET_WHEEL_DELTA_WPARAM(wParam);
slouken@7813
   558
            if (s_AccumulatedMotion > 0) {
slouken@7813
   559
                while (s_AccumulatedMotion >= WHEEL_DELTA) {
urkle@9257
   560
                    SDL_SendMouseWheel(data->window, 0, 0, 1, SDL_MOUSEWHEEL_NORMAL);
slouken@7813
   561
                    s_AccumulatedMotion -= WHEEL_DELTA;
slouken@7813
   562
                }
slouken@7813
   563
            } else {
slouken@7813
   564
                while (s_AccumulatedMotion <= -WHEEL_DELTA) {
urkle@9257
   565
                    SDL_SendMouseWheel(data->window, 0, 0, -1, SDL_MOUSEWHEEL_NORMAL);
slouken@7813
   566
                    s_AccumulatedMotion += WHEEL_DELTA;
slouken@7813
   567
                }
slouken@7813
   568
            }
slouken@5049
   569
        }
slouken@8071
   570
        break;
slouken@5049
   571
slouken@7911
   572
    case WM_MOUSEHWHEEL:
slouken@7911
   573
        {
slouken@7911
   574
            static short s_AccumulatedMotion;
slouken@7911
   575
slouken@7911
   576
            s_AccumulatedMotion += GET_WHEEL_DELTA_WPARAM(wParam);
slouken@7911
   577
            if (s_AccumulatedMotion > 0) {
slouken@7911
   578
                while (s_AccumulatedMotion >= WHEEL_DELTA) {
urkle@9257
   579
                    SDL_SendMouseWheel(data->window, 0, 1, 0, SDL_MOUSEWHEEL_NORMAL);
slouken@7911
   580
                    s_AccumulatedMotion -= WHEEL_DELTA;
slouken@7911
   581
                }
slouken@7911
   582
            } else {
slouken@7911
   583
                while (s_AccumulatedMotion <= -WHEEL_DELTA) {
urkle@9257
   584
                    SDL_SendMouseWheel(data->window, 0, -1, 0, SDL_MOUSEWHEEL_NORMAL);
slouken@7911
   585
                    s_AccumulatedMotion += WHEEL_DELTA;
slouken@7911
   586
                }
slouken@7911
   587
            }
slouken@7911
   588
        }
slouken@8071
   589
        break;
slouken@7911
   590
slouken@5086
   591
#ifdef WM_MOUSELEAVE
slouken@1895
   592
    case WM_MOUSELEAVE:
icculus@8942
   593
        if (SDL_GetMouseFocus() == data->window && !SDL_GetMouse()->relative_mode && !(data->window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
slouken@8035
   594
            if (!IsIconic(hwnd)) {
slouken@8035
   595
                POINT cursorPos;
slouken@8035
   596
                GetCursorPos(&cursorPos);
slouken@8035
   597
                ScreenToClient(hwnd, &cursorPos);
slouken@8035
   598
                SDL_SendMouseMotion(data->window, 0, 0, cursorPos.x, cursorPos.y);
slouken@8035
   599
            }
slouken@7191
   600
            SDL_SetMouseFocus(NULL);
slouken@1895
   601
        }
slouken@3566
   602
        returnCode = 0;
slouken@3566
   603
        break;
slouken@5086
   604
#endif /* WM_MOUSELEAVE */
slouken@1895
   605
slouken@7645
   606
    case WM_KEYDOWN:
slouken@7646
   607
    case WM_SYSKEYDOWN:
slouken@7645
   608
        {
slouken@8813
   609
            SDL_Scancode code = WindowsScanCodeToSDLScanCode(lParam, wParam);
icculus@9641
   610
            const Uint8 *keyboardState = SDL_GetKeyboardState(NULL);
icculus@9641
   611
icculus@9641
   612
            /* Detect relevant keyboard shortcuts */
icculus@9641
   613
            if (keyboardState[SDL_SCANCODE_LALT] == SDL_PRESSED || keyboardState[SDL_SCANCODE_RALT] == SDL_PRESSED) {
icculus@9641
   614
                /* ALT+F4: Close window */
andrewb@9829
   615
                if (code == SDL_SCANCODE_F4 && ShouldGenerateWindowCloseOnAltF4()) {
icculus@9641
   616
                    SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
icculus@9641
   617
                }
icculus@9641
   618
            }
icculus@9641
   619
slouken@8813
   620
            if (code != SDL_SCANCODE_UNKNOWN) {
slouken@8813
   621
                SDL_SendKeyboardKey(SDL_PRESSED, code);
slouken@7646
   622
            }
slouken@7646
   623
        }
slouken@9781
   624
 
slouken@3566
   625
        returnCode = 0;
slouken@3566
   626
        break;
slouken@1895
   627
slouken@1895
   628
    case WM_SYSKEYUP:
slouken@1895
   629
    case WM_KEYUP:
slouken@1895
   630
        {
slouken@8813
   631
            SDL_Scancode code = WindowsScanCodeToSDLScanCode(lParam, wParam);
gabomdq@7975
   632
            const Uint8 *keyboardState = SDL_GetKeyboardState(NULL);
gabomdq@7975
   633
slouken@8813
   634
            if (code != SDL_SCANCODE_UNKNOWN) {
slouken@6938
   635
                if (code == SDL_SCANCODE_PRINTSCREEN &&
gabomdq@7975
   636
                    keyboardState[code] == SDL_RELEASED) {
slouken@6938
   637
                    SDL_SendKeyboardKey(SDL_PRESSED, code);
slouken@6938
   638
                }
slouken@6938
   639
                SDL_SendKeyboardKey(SDL_RELEASED, code);
slouken@2308
   640
            }
slouken@1895
   641
        }
slouken@3566
   642
        returnCode = 0;
slouken@3566
   643
        break;
slouken@1895
   644
slouken@8143
   645
    case WM_UNICHAR:
slouken@9889
   646
        if ( wParam == UNICODE_NOCHAR ) {
slouken@9889
   647
            returnCode = 1;
slouken@9889
   648
            break;
slouken@9889
   649
        }
slouken@9889
   650
        /* otherwise fall through to below */
slouken@9889
   651
    case WM_CHAR:
slouken@9889
   652
        {
slouken@9889
   653
            char text[5];
slouken@9889
   654
            if ( WIN_ConvertUTF32toUTF8( (UINT32)wParam, text ) ) {
slouken@9889
   655
                SDL_SendKeyboardText( text );
slouken@9889
   656
            }
slouken@9889
   657
        }
slouken@9889
   658
        returnCode = 0;
slouken@8143
   659
        break;
slouken@8143
   660
slouken@5086
   661
#ifdef WM_INPUTLANGCHANGE
slouken@2311
   662
    case WM_INPUTLANGCHANGE:
slouken@2311
   663
        {
slouken@4465
   664
            WIN_UpdateKeymap();
slouken@9898
   665
            SDL_SendKeymapChangedEvent();
slouken@2311
   666
        }
slouken@3566
   667
        returnCode = 1;
slouken@3566
   668
        break;
slouken@5086
   669
#endif /* WM_INPUTLANGCHANGE */
slouken@2311
   670
slouken@8253
   671
    case WM_NCLBUTTONDOWN:
slouken@8253
   672
        {
slouken@8253
   673
            data->in_title_click = SDL_TRUE;
slouken@8253
   674
        }
slouken@8253
   675
        break;
slouken@8253
   676
slouken@8916
   677
    case WM_CAPTURECHANGED:
slouken@8253
   678
        {
slouken@8253
   679
            data->in_title_click = SDL_FALSE;
slouken@8253
   680
slouken@8916
   681
            /* The mouse may have been released during a modal loop */
slouken@8212
   682
            WIN_CheckAsyncMouseRelease(data);
slouken@8036
   683
        }
slouken@8036
   684
        break;
slouken@8036
   685
slouken@5086
   686
#ifdef WM_GETMINMAXINFO
slouken@1895
   687
    case WM_GETMINMAXINFO:
slouken@1895
   688
        {
slouken@1895
   689
            MINMAXINFO *info;
slouken@1895
   690
            RECT size;
slouken@1895
   691
            int x, y;
slouken@1895
   692
            int w, h;
stopiccot@6682
   693
            int min_w, min_h;
slouken@6788
   694
            int max_w, max_h;
slouken@1895
   695
            int style;
slouken@3168
   696
            BOOL menu;
slouken@7191
   697
            BOOL constrain_max_size;
slouken@1895
   698
stopiccot@6682
   699
            if (SDL_IsShapedWindow(data->window))
eligottlieb@4815
   700
                Win32_ResizeWindowShape(data->window);
slouken@1895
   701
slouken@7941
   702
            /* If this is an expected size change, allow it */
slouken@7941
   703
            if (data->expected_resize) {
slouken@7941
   704
                break;
slouken@7941
   705
            }
slouken@7941
   706
slouken@1895
   707
            /* Get the current position of our window */
slouken@1895
   708
            GetWindowRect(hwnd, &size);
slouken@1895
   709
            x = size.left;
slouken@1895
   710
            y = size.top;
slouken@1895
   711
slouken@1895
   712
            /* Calculate current size of our window */
slouken@3685
   713
            SDL_GetWindowSize(data->window, &w, &h);
stopiccot@6682
   714
            SDL_GetWindowMinimumSize(data->window, &min_w, &min_h);
slouken@6788
   715
            SDL_GetWindowMaximumSize(data->window, &max_w, &max_h);
stopiccot@6682
   716
slouken@7191
   717
            /* Store in min_w and min_h difference between current size and minimal
stopiccot@6682
   718
               size so we don't need to call AdjustWindowRectEx twice */
stopiccot@6682
   719
            min_w -= w;
stopiccot@6682
   720
            min_h -= h;
slouken@6837
   721
            if (max_w && max_h) {
slouken@6837
   722
                max_w -= w;
slouken@6837
   723
                max_h -= h;
slouken@6862
   724
                constrain_max_size = TRUE;
slouken@6862
   725
            } else {
slouken@6862
   726
                constrain_max_size = FALSE;
slouken@6837
   727
            }
stopiccot@6682
   728
slouken@1895
   729
            size.top = 0;
slouken@1895
   730
            size.left = 0;
slouken@1895
   731
            size.bottom = h;
slouken@1895
   732
            size.right = w;
slouken@1895
   733
slouken@3168
   734
            style = GetWindowLong(hwnd, GWL_STYLE);
slouken@1895
   735
            /* DJM - according to the docs for GetMenu(), the
slouken@1895
   736
               return value is undefined if hwnd is a child window.
slouken@8817
   737
               Apparently it's too difficult for MS to check
slouken@1895
   738
               inside their function, so I have to do it here.
slouken@1895
   739
             */
slouken@3168
   740
            menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
slouken@3168
   741
            AdjustWindowRectEx(&size, style, menu, 0);
slouken@1895
   742
            w = size.right - size.left;
slouken@1895
   743
            h = size.bottom - size.top;
slouken@1895
   744
slouken@1895
   745
            /* Fix our size to the current size */
slouken@1895
   746
            info = (MINMAXINFO *) lParam;
stopiccot@6682
   747
            if (SDL_GetWindowFlags(data->window) & SDL_WINDOW_RESIZABLE) {
stopiccot@6682
   748
                info->ptMinTrackSize.x = w + min_w;
stopiccot@6682
   749
                info->ptMinTrackSize.y = h + min_h;
slouken@6862
   750
                if (constrain_max_size) {
slouken@6862
   751
                    info->ptMaxTrackSize.x = w + max_w;
slouken@6862
   752
                    info->ptMaxTrackSize.y = h + max_h;
slouken@6862
   753
                }
stopiccot@6682
   754
            } else {
stopiccot@6682
   755
                info->ptMaxSize.x = w;
stopiccot@6682
   756
                info->ptMaxSize.y = h;
stopiccot@6682
   757
                info->ptMaxPosition.x = x;
stopiccot@6682
   758
                info->ptMaxPosition.y = y;
stopiccot@6682
   759
                info->ptMinTrackSize.x = w;
stopiccot@6682
   760
                info->ptMinTrackSize.y = h;
stopiccot@6682
   761
                info->ptMaxTrackSize.x = w;
stopiccot@6682
   762
                info->ptMaxTrackSize.y = h;
stopiccot@6682
   763
            }
slouken@1895
   764
        }
slouken@3566
   765
        returnCode = 0;
slouken@3566
   766
        break;
slouken@5086
   767
#endif /* WM_GETMINMAXINFO */
slouken@1895
   768
icculus@10387
   769
    case WM_WINDOWPOSCHANGING:
icculus@10387
   770
icculus@10387
   771
        if (data->expected_resize) {
icculus@10387
   772
            returnCode = 0;
icculus@10387
   773
        }
icculus@10387
   774
        break;
icculus@10387
   775
slouken@1895
   776
    case WM_WINDOWPOSCHANGED:
slouken@1895
   777
        {
slouken@1895
   778
            RECT rect;
slouken@1895
   779
            int x, y;
slouken@1895
   780
            int w, h;
slouken@8817
   781
            
slouken@9888
   782
            if (data->initializing || data->in_border_change) {
slouken@8817
   783
                break;
slouken@8817
   784
            }
slouken@1895
   785
slouken@8036
   786
            if (!GetClientRect(hwnd, &rect) || IsRectEmpty(&rect)) {
slouken@3256
   787
                break;
slouken@3256
   788
            }
slouken@1895
   789
            ClientToScreen(hwnd, (LPPOINT) & rect);
slouken@1895
   790
            ClientToScreen(hwnd, (LPPOINT) & rect + 1);
slouken@1895
   791
slouken@8036
   792
            WIN_UpdateClipCursor(data->window);
slouken@1895
   793
slouken@1895
   794
            x = rect.left;
slouken@1895
   795
            y = rect.top;
slouken@3685
   796
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, x, y);
slouken@1895
   797
slouken@1895
   798
            w = rect.right - rect.left;
slouken@1895
   799
            h = rect.bottom - rect.top;
slouken@3685
   800
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, w,
slouken@1895
   801
                                h);
flibitijibibo@10417
   802
flibitijibibo@10417
   803
            /* Forces a WM_PAINT event */
flibitijibibo@10417
   804
            InvalidateRect(hwnd, NULL, FALSE);
slouken@1895
   805
        }
slouken@1895
   806
        break;
slouken@1895
   807
slouken@7941
   808
    case WM_SIZE:
slouken@7941
   809
        {
slouken@8813
   810
            switch (wParam) {
slouken@7941
   811
            case SIZE_MAXIMIZED:
slouken@7941
   812
                SDL_SendWindowEvent(data->window,
slouken@7941
   813
                    SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
slouken@7941
   814
                break;
slouken@7941
   815
            case SIZE_MINIMIZED:
slouken@7941
   816
                SDL_SendWindowEvent(data->window,
slouken@7941
   817
                    SDL_WINDOWEVENT_MINIMIZED, 0, 0);
slouken@7941
   818
                break;
slouken@7941
   819
            default:
slouken@7941
   820
                SDL_SendWindowEvent(data->window,
slouken@7941
   821
                    SDL_WINDOWEVENT_RESTORED, 0, 0);
slouken@7941
   822
                break;
slouken@7941
   823
            }
slouken@7941
   824
        }
slouken@7941
   825
        break;
slouken@7941
   826
slouken@1895
   827
    case WM_SETCURSOR:
slouken@1895
   828
        {
slouken@3076
   829
            Uint16 hittest;
slouken@1895
   830
slouken@3076
   831
            hittest = LOWORD(lParam);
slouken@3076
   832
            if (hittest == HTCLIENT) {
slouken@5421
   833
                SetCursor(SDL_cursor);
slouken@3566
   834
                returnCode = TRUE;
slouken@8813
   835
            } else if (!g_WindowFrameUsableWhileCursorHidden && !SDL_cursor) {
slouken@8813
   836
                SetCursor(NULL);
slouken@8813
   837
                returnCode = TRUE;
slouken@3076
   838
            }
slouken@1895
   839
        }
slouken@1895
   840
        break;
slouken@1895
   841
slouken@1895
   842
        /* We were occluded, refresh our display */
slouken@1895
   843
    case WM_PAINT:
slouken@1895
   844
        {
slouken@1895
   845
            RECT rect;
slouken@1895
   846
            if (GetUpdateRect(hwnd, &rect, FALSE)) {
slouken@7295
   847
                ValidateRect(hwnd, NULL);
slouken@3685
   848
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED,
slouken@1895
   849
                                    0, 0);
slouken@1895
   850
            }
slouken@1895
   851
        }
slouken@3566
   852
        returnCode = 0;
slouken@3566
   853
        break;
slouken@3095
   854
slouken@1895
   855
        /* We'll do our own drawing, prevent flicker */
slouken@1895
   856
    case WM_ERASEBKGND:
slouken@1895
   857
        {
slouken@1895
   858
        }
slouken@1895
   859
        return (1);
slouken@1895
   860
slouken@1895
   861
    case WM_SYSCOMMAND:
slouken@1895
   862
        {
slouken@9889
   863
            if ((wParam & 0xFFF0) == SC_KEYMENU) {
slouken@9889
   864
                return (0);
slouken@9889
   865
            }
icculus@9624
   866
icculus@9624
   867
#if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
slouken@1895
   868
            /* Don't start the screensaver or blank the monitor in fullscreen apps */
slouken@1895
   869
            if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
slouken@1895
   870
                (wParam & 0xFFF0) == SC_MONITORPOWER) {
slouken@3032
   871
                if (SDL_GetVideoDevice()->suspend_screensaver) {
slouken@1895
   872
                    return (0);
slouken@1895
   873
                }
slouken@1895
   874
            }
icculus@9624
   875
#endif /* System has screensaver support */
slouken@1895
   876
        }
slouken@1895
   877
        break;
slouken@1895
   878
slouken@1895
   879
    case WM_CLOSE:
slouken@1895
   880
        {
slouken@3685
   881
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
slouken@1895
   882
        }
slouken@3566
   883
        returnCode = 0;
slouken@3566
   884
        break;
slouken@4919
   885
slouken@7191
   886
    case WM_TOUCH:
slouken@7191
   887
        {
slouken@7191
   888
            UINT i, num_inputs = LOWORD(wParam);
slouken@7191
   889
            PTOUCHINPUT inputs = SDL_stack_alloc(TOUCHINPUT, num_inputs);
slouken@7191
   890
            if (data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs, sizeof(TOUCHINPUT))) {
slouken@7191
   891
                RECT rect;
slouken@7191
   892
                float x, y;
slouken@4919
   893
slouken@7191
   894
                if (!GetClientRect(hwnd, &rect) ||
slouken@7191
   895
                    (rect.right == rect.left && rect.bottom == rect.top)) {
philipp@7631
   896
                    if (inputs) {
philipp@7631
   897
                        SDL_stack_free(inputs);
philipp@7631
   898
                    }
slouken@7191
   899
                    break;
slouken@7191
   900
                }
slouken@7191
   901
                ClientToScreen(hwnd, (LPPOINT) & rect);
slouken@7191
   902
                ClientToScreen(hwnd, (LPPOINT) & rect + 1);
slouken@7191
   903
                rect.top *= 100;
slouken@7191
   904
                rect.left *= 100;
slouken@7191
   905
                rect.bottom *= 100;
slouken@7191
   906
                rect.right *= 100;
slouken@4932
   907
slouken@7191
   908
                for (i = 0; i < num_inputs; ++i) {
slouken@7191
   909
                    PTOUCHINPUT input = &inputs[i];
slouken@4919
   910
icculus@7543
   911
                    const SDL_TouchID touchId = (SDL_TouchID)((size_t)input->hSource);
slouken@9679
   912
                    if (SDL_AddTouch(touchId, "") < 0) {
slouken@9679
   913
                        continue;
slouken@7191
   914
                    }
slouken@4932
   915
slouken@7191
   916
                    /* Get the normalized coordinates for the window */
slouken@7191
   917
                    x = (float)(input->x - rect.left)/(rect.right - rect.left);
slouken@7191
   918
                    y = (float)(input->y - rect.top)/(rect.bottom - rect.top);
slouken@4932
   919
slouken@7191
   920
                    if (input->dwFlags & TOUCHEVENTF_DOWN) {
slouken@7191
   921
                        SDL_SendTouch(touchId, input->dwID, SDL_TRUE, x, y, 1.0f);
slouken@7191
   922
                    }
slouken@7191
   923
                    if (input->dwFlags & TOUCHEVENTF_MOVE) {
slouken@7191
   924
                        SDL_SendTouchMotion(touchId, input->dwID, x, y, 1.0f);
slouken@7191
   925
                    }
slouken@7191
   926
                    if (input->dwFlags & TOUCHEVENTF_UP) {
slouken@7191
   927
                        SDL_SendTouch(touchId, input->dwID, SDL_FALSE, x, y, 1.0f);
slouken@7191
   928
                    }
slouken@7191
   929
                }
slouken@7191
   930
            }
slouken@7191
   931
            SDL_stack_free(inputs);
slouken@4932
   932
slouken@7191
   933
            data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
slouken@7191
   934
            return 0;
slouken@7191
   935
        }
slouken@7191
   936
        break;
slouken@6523
   937
slouken@6523
   938
    case WM_DROPFILES:
slouken@6523
   939
        {
slouken@6523
   940
            UINT i;
slouken@6523
   941
            HDROP drop = (HDROP) wParam;
slouken@6523
   942
            UINT count = DragQueryFile(drop, 0xFFFFFFFF, NULL, 0);
slouken@6523
   943
            for (i = 0; i < count; ++i) {
slouken@6523
   944
                UINT size = DragQueryFile(drop, i, NULL, 0) + 1;
slouken@6523
   945
                LPTSTR buffer = SDL_stack_alloc(TCHAR, size);
slouken@6523
   946
                if (buffer) {
slouken@6523
   947
                    if (DragQueryFile(drop, i, buffer, size)) {
slouken@6523
   948
                        char *file = WIN_StringToUTF8(buffer);
icculus@10022
   949
                        SDL_SendDropFile(data->window, file);
slouken@6523
   950
                        SDL_free(file);
slouken@6523
   951
                    }
slouken@6523
   952
                    SDL_stack_free(buffer);
slouken@6523
   953
                }
slouken@6523
   954
            }
icculus@10022
   955
            SDL_SendDropComplete(data->window);
slouken@6523
   956
            DragFinish(drop);
slouken@6523
   957
            return 0;
slouken@6523
   958
        }
slouken@6523
   959
        break;
icculus@8938
   960
icculus@8938
   961
    case WM_NCHITTEST:
icculus@8938
   962
        {
icculus@8938
   963
            SDL_Window *window = data->window;
icculus@8938
   964
            if (window->hit_test) {
icculus@8941
   965
                POINT winpoint = { (int) LOWORD(lParam), (int) HIWORD(lParam) };
slouken@8976
   966
                if (ScreenToClient(hwnd, &winpoint)) {
icculus@8941
   967
                    const SDL_Point point = { (int) winpoint.x, (int) winpoint.y };
icculus@8941
   968
                    const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
icculus@8948
   969
                    switch (rc) {
icculus@10028
   970
                        #define POST_HIT_TEST(ret) { SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0); return ret; }
icculus@10028
   971
                        case SDL_HITTEST_DRAGGABLE: POST_HIT_TEST(HTCAPTION);
icculus@10028
   972
                        case SDL_HITTEST_RESIZE_TOPLEFT: POST_HIT_TEST(HTTOPLEFT);
icculus@10028
   973
                        case SDL_HITTEST_RESIZE_TOP: POST_HIT_TEST(HTTOP);
icculus@10028
   974
                        case SDL_HITTEST_RESIZE_TOPRIGHT: POST_HIT_TEST(HTTOPRIGHT);
icculus@10028
   975
                        case SDL_HITTEST_RESIZE_RIGHT: POST_HIT_TEST(HTRIGHT);
icculus@10028
   976
                        case SDL_HITTEST_RESIZE_BOTTOMRIGHT: POST_HIT_TEST(HTBOTTOMRIGHT);
icculus@10028
   977
                        case SDL_HITTEST_RESIZE_BOTTOM: POST_HIT_TEST(HTBOTTOM);
icculus@10028
   978
                        case SDL_HITTEST_RESIZE_BOTTOMLEFT: POST_HIT_TEST(HTBOTTOMLEFT);
icculus@10028
   979
                        case SDL_HITTEST_RESIZE_LEFT: POST_HIT_TEST(HTLEFT);
icculus@10028
   980
                        #undef POST_HIT_TEST
slouken@8976
   981
                        case SDL_HITTEST_NORMAL: return HTCLIENT;
icculus@8941
   982
                    }
icculus@8938
   983
                }
icculus@8948
   984
                /* If we didn't return, this will call DefWindowProc below. */
icculus@8938
   985
            }
icculus@8938
   986
        }
icculus@8938
   987
        break;
icculus@8938
   988
slouken@6523
   989
    }
slouken@3566
   990
slouken@3566
   991
    /* If there's a window proc, assume it's going to handle messages */
slouken@3566
   992
    if (data->wndproc) {
slouken@3566
   993
        return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam);
slouken@3566
   994
    } else if (returnCode >= 0) {
slouken@3566
   995
        return returnCode;
slouken@3566
   996
    } else {
slouken@3566
   997
        return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
slouken@3566
   998
    }
slouken@1895
   999
}
slouken@1895
  1000
slouken@9597
  1001
/* A message hook called before TranslateMessage() */
slouken@9597
  1002
static SDL_WindowsMessageHook g_WindowsMessageHook = NULL;
slouken@9599
  1003
static void *g_WindowsMessageHookData = NULL;
slouken@9597
  1004
slouken@9599
  1005
void SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata)
slouken@9597
  1006
{
slouken@9597
  1007
    g_WindowsMessageHook = callback;
slouken@9599
  1008
    g_WindowsMessageHookData = userdata;
slouken@9597
  1009
}
slouken@9597
  1010
slouken@1895
  1011
void
slouken@1895
  1012
WIN_PumpEvents(_THIS)
slouken@1895
  1013
{
icculus@7561
  1014
    const Uint8 *keystate;
slouken@1895
  1015
    MSG msg;
slouken@8218
  1016
    DWORD start_ticks = GetTickCount();
slouken@8218
  1017
slouken@8814
  1018
    if (g_WindowsEnableMessageLoop) {
slouken@8814
  1019
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
slouken@9597
  1020
            if (g_WindowsMessageHook) {
slouken@9599
  1021
                g_WindowsMessageHook(g_WindowsMessageHookData, msg.hwnd, msg.message, msg.wParam, msg.lParam);
slouken@9597
  1022
            }
slouken@9597
  1023
slouken@8814
  1024
            /* Always translate the message in case it's a non-SDL window (e.g. with Qt integration) */
slouken@8814
  1025
            TranslateMessage(&msg);
slouken@8814
  1026
            DispatchMessage(&msg);
slouken@8218
  1027
slouken@8814
  1028
            /* Make sure we don't busy loop here forever if there are lots of events coming in */
slouken@8814
  1029
            if (SDL_TICKS_PASSED(msg.time, start_ticks)) {
slouken@8814
  1030
                break;
slouken@8814
  1031
            }
slouken@8218
  1032
        }
slouken@1895
  1033
    }
icculus@7561
  1034
icculus@7561
  1035
    /* Windows loses a shift KEYUP event when you have both pressed at once and let go of one.
icculus@7561
  1036
       You won't get a KEYUP until both are released, and that keyup will only be for the second
icculus@7561
  1037
       key you released. Take heroic measures and check the keystate as of the last handled event,
icculus@7561
  1038
       and if we think a key is pressed when Windows doesn't, unstick it in SDL's state. */
icculus@7561
  1039
    keystate = SDL_GetKeyboardState(NULL);
icculus@7561
  1040
    if ((keystate[SDL_SCANCODE_LSHIFT] == SDL_PRESSED) && !(GetKeyState(VK_LSHIFT) & 0x8000)) {
icculus@7561
  1041
        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
icculus@7561
  1042
    }
icculus@7561
  1043
    if ((keystate[SDL_SCANCODE_RSHIFT] == SDL_PRESSED) && !(GetKeyState(VK_RSHIFT) & 0x8000)) {
icculus@7561
  1044
        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RSHIFT);
icculus@7561
  1045
    }
slouken@1895
  1046
}
slouken@1895
  1047
slouken@1895
  1048
static int app_registered = 0;
slouken@1895
  1049
LPTSTR SDL_Appname = NULL;
slouken@1895
  1050
Uint32 SDL_Appstyle = 0;
slouken@1895
  1051
HINSTANCE SDL_Instance = NULL;
slouken@1895
  1052
slouken@1895
  1053
/* Register the class for this application */
slouken@1895
  1054
int
slouken@1895
  1055
SDL_RegisterApp(char *name, Uint32 style, void *hInst)
slouken@1895
  1056
{
slouken@10426
  1057
    WNDCLASSEX wcex;
slouken@10426
  1058
    TCHAR path[MAX_PATH];
slouken@1895
  1059
slouken@1895
  1060
    /* Only do this once... */
slouken@1895
  1061
    if (app_registered) {
slouken@1895
  1062
        ++app_registered;
slouken@1895
  1063
        return (0);
slouken@1895
  1064
    }
slouken@1895
  1065
    if (!name && !SDL_Appname) {
slouken@1895
  1066
        name = "SDL_app";
slouken@5086
  1067
#if defined(CS_BYTEALIGNCLIENT) || defined(CS_OWNDC)
slouken@1895
  1068
        SDL_Appstyle = (CS_BYTEALIGNCLIENT | CS_OWNDC);
slouken@5086
  1069
#endif
slouken@1895
  1070
        SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
slouken@1895
  1071
    }
slouken@1895
  1072
slouken@1895
  1073
    if (name) {
slouken@1895
  1074
        SDL_Appname = WIN_UTF8ToString(name);
slouken@1895
  1075
        SDL_Appstyle = style;
slouken@1895
  1076
        SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
slouken@1895
  1077
    }
slouken@1895
  1078
slouken@1895
  1079
    /* Register the application class */
slouken@10426
  1080
    wcex.cbSize         = sizeof(WNDCLASSEX);
slouken@10426
  1081
    wcex.hCursor        = NULL;
slouken@10426
  1082
    wcex.hIcon          = NULL;
slouken@10426
  1083
    wcex.hIconSm        = NULL;
slouken@10426
  1084
    wcex.lpszMenuName   = NULL;
slouken@10426
  1085
    wcex.lpszClassName  = SDL_Appname;
slouken@10426
  1086
    wcex.style          = SDL_Appstyle;
slouken@10426
  1087
    wcex.hbrBackground  = NULL;
slouken@10426
  1088
    wcex.lpfnWndProc    = WIN_WindowProc;
slouken@10426
  1089
    wcex.hInstance      = SDL_Instance;
slouken@10426
  1090
    wcex.cbClsExtra     = 0;
slouken@10426
  1091
    wcex.cbWndExtra     = 0;
slouken@10426
  1092
slouken@10426
  1093
    /* Use the first icon as a default icon, like in the Explorer */
slouken@10426
  1094
    GetModuleFileName(SDL_Instance, path, MAX_PATH);
slouken@10426
  1095
    ExtractIconEx(path, 0, &wcex.hIcon, &wcex.hIconSm, 1);
slouken@10426
  1096
slouken@10426
  1097
    if (!RegisterClassEx(&wcex)) {
icculus@7037
  1098
        return SDL_SetError("Couldn't register application class");
slouken@1895
  1099
    }
slouken@1895
  1100
slouken@1895
  1101
    app_registered = 1;
icculus@7037
  1102
    return 0;
slouken@1895
  1103
}
slouken@1895
  1104
slouken@1895
  1105
/* Unregisters the windowclass registered in SDL_RegisterApp above. */
slouken@1895
  1106
void
slouken@1895
  1107
SDL_UnregisterApp()
slouken@1895
  1108
{
slouken@10426
  1109
    WNDCLASSEX wcex;
slouken@1895
  1110
slouken@1895
  1111
    /* SDL_RegisterApp might not have been called before */
slouken@1895
  1112
    if (!app_registered) {
slouken@1895
  1113
        return;
slouken@1895
  1114
    }
slouken@1895
  1115
    --app_registered;
slouken@1895
  1116
    if (app_registered == 0) {
slouken@1895
  1117
        /* Check for any registered window classes. */
slouken@10426
  1118
        if (GetClassInfoEx(SDL_Instance, SDL_Appname, &wcex)) {
slouken@1895
  1119
            UnregisterClass(SDL_Appname, SDL_Instance);
slouken@10426
  1120
            if (wcex.hIcon) DestroyIcon(wcex.hIcon);
slouken@10426
  1121
            if (wcex.hIconSm) DestroyIcon(wcex.hIconSm);
slouken@1895
  1122
        }
slouken@1895
  1123
        SDL_free(SDL_Appname);
slouken@1895
  1124
        SDL_Appname = NULL;
slouken@1895
  1125
    }
slouken@1895
  1126
}
slouken@1895
  1127
slouken@6044
  1128
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
slouken@6044
  1129
slouken@1895
  1130
/* vi: set ts=4 sw=4 expandtab: */