src/video/windows/SDL_windowsevents.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 27 Dec 2013 10:18:18 -0800
changeset 8084 96b1986b1e61
parent 8072 9d8865351afd
child 8093 b43765095a6f
permissions -rw-r--r--
Make sure our window has mouse focus before processing raw input events.
This happens rarely, but not reproducibly, where we get raw input events for the window even though it doesn't have focus.
slouken@1895
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6885
     3
  Copyright (C) 1997-2013 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
*/
slouken@6044
    21
#include "SDL_config.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@1895
    27
#include "SDL_syswm.h"
slouken@1895
    28
#include "SDL_vkeys.h"
slouken@1895
    29
#include "../../events/SDL_events_c.h"
slouken@4919
    30
#include "../../events/SDL_touch_c.h"
slouken@6938
    31
#include "../../events/scancodes_windows.h"
slouken@1895
    32
slouken@6523
    33
/* Dropfile support */
slouken@6523
    34
#include <shellapi.h>
slouken@6523
    35
jorgen@7276
    36
/* For GET_X_LPARAM, GET_Y_LPARAM. */
jorgen@7276
    37
#include <windowsx.h>
slouken@6523
    38
gabomdq@7678
    39
/* #define WMMSG_DEBUG */
slouken@1895
    40
#ifdef WMMSG_DEBUG
slouken@7191
    41
#include <stdio.h>
slouken@1895
    42
#include "wmmsg.h"
slouken@1895
    43
#endif
slouken@1895
    44
slouken@1895
    45
/* Masks for processing the windows KEYDOWN and KEYUP messages */
slouken@2317
    46
#define REPEATED_KEYMASK    (1<<30)
slouken@2317
    47
#define EXTENDED_KEYMASK    (1<<24)
slouken@1895
    48
bob@2324
    49
#define VK_ENTER    10          /* Keypad Enter ... no VKEY defined? */
slouken@6931
    50
#ifndef VK_OEM_NEC_EQUAL
slouken@7191
    51
#define VK_OEM_NEC_EQUAL 0x92
slouken@6931
    52
#endif
slouken@2313
    53
icculus@2127
    54
/* Make sure XBUTTON stuff is defined that isn't in older Platform SDKs... */
icculus@2127
    55
#ifndef WM_XBUTTONDOWN
icculus@2127
    56
#define WM_XBUTTONDOWN 0x020B
icculus@2127
    57
#endif
icculus@2127
    58
#ifndef WM_XBUTTONUP
icculus@2127
    59
#define WM_XBUTTONUP 0x020C
icculus@2127
    60
#endif
icculus@2127
    61
#ifndef GET_XBUTTON_WPARAM
icculus@2127
    62
#define GET_XBUTTON_WPARAM(w) (HIWORD(w))
icculus@2127
    63
#endif
bobbens@2733
    64
#ifndef WM_INPUT
bobbens@2733
    65
#define WM_INPUT 0x00ff
bobbens@2733
    66
#endif
slouken@4932
    67
#ifndef WM_TOUCH
slouken@4868
    68
#define WM_TOUCH 0x0240
slouken@4932
    69
#endif
slouken@7911
    70
#ifndef WM_MOUSEHWHEEL
slouken@7911
    71
#define WM_MOUSEHWHEEL 0x020E
slouken@7911
    72
#endif
slouken@4919
    73
slouken@7191
    74
static SDL_Scancode
slouken@6973
    75
WindowsScanCodeToSDLScanCode( LPARAM lParam, WPARAM wParam )
jorgen@6922
    76
{
slouken@7191
    77
    SDL_Scancode code;
slouken@7191
    78
    char bIsExtended;
slouken@7191
    79
    int nScanCode = ( lParam >> 16 ) & 0xFF;
jorgen@6922
    80
slouken@7191
    81
    /* 0x45 here to work around both pause and numlock sharing the same scancode, so use the VK key to tell them apart */
slouken@7191
    82
    if ( nScanCode == 0 || nScanCode == 0x45 )
slouken@7191
    83
    {
slouken@7191
    84
        switch( wParam )
slouken@7191
    85
        {
slouken@7191
    86
        case VK_CLEAR: return SDL_SCANCODE_CLEAR;
slouken@7191
    87
        case VK_MODECHANGE: return SDL_SCANCODE_MODE;
slouken@7191
    88
        case VK_SELECT: return SDL_SCANCODE_SELECT;
slouken@7191
    89
        case VK_EXECUTE: return SDL_SCANCODE_EXECUTE;
slouken@7191
    90
        case VK_HELP: return SDL_SCANCODE_HELP;
slouken@7191
    91
        case VK_PAUSE: return SDL_SCANCODE_PAUSE;
slouken@7191
    92
        case VK_NUMLOCK: return SDL_SCANCODE_NUMLOCKCLEAR;
jorgen@6922
    93
slouken@7191
    94
        case VK_F13: return SDL_SCANCODE_F13;
slouken@7191
    95
        case VK_F14: return SDL_SCANCODE_F14;
slouken@7191
    96
        case VK_F15: return SDL_SCANCODE_F15;
slouken@7191
    97
        case VK_F16: return SDL_SCANCODE_F16;
slouken@7191
    98
        case VK_F17: return SDL_SCANCODE_F17;
slouken@7191
    99
        case VK_F18: return SDL_SCANCODE_F18;
slouken@7191
   100
        case VK_F19: return SDL_SCANCODE_F19;
slouken@7191
   101
        case VK_F20: return SDL_SCANCODE_F20;
slouken@7191
   102
        case VK_F21: return SDL_SCANCODE_F21;
slouken@7191
   103
        case VK_F22: return SDL_SCANCODE_F22;
slouken@7191
   104
        case VK_F23: return SDL_SCANCODE_F23;
slouken@7191
   105
        case VK_F24: return SDL_SCANCODE_F24;
jorgen@6922
   106
slouken@7191
   107
        case VK_OEM_NEC_EQUAL: return SDL_SCANCODE_KP_EQUALS;
slouken@7191
   108
        case VK_BROWSER_BACK: return SDL_SCANCODE_AC_BACK;
slouken@7191
   109
        case VK_BROWSER_FORWARD: return SDL_SCANCODE_AC_FORWARD;
slouken@7191
   110
        case VK_BROWSER_REFRESH: return SDL_SCANCODE_AC_REFRESH;
slouken@7191
   111
        case VK_BROWSER_STOP: return SDL_SCANCODE_AC_STOP;
slouken@7191
   112
        case VK_BROWSER_SEARCH: return SDL_SCANCODE_AC_SEARCH;
slouken@7191
   113
        case VK_BROWSER_FAVORITES: return SDL_SCANCODE_AC_BOOKMARKS;
slouken@7191
   114
        case VK_BROWSER_HOME: return SDL_SCANCODE_AC_HOME;
slouken@7191
   115
        case VK_VOLUME_MUTE: return SDL_SCANCODE_AUDIOMUTE;
slouken@7191
   116
        case VK_VOLUME_DOWN: return SDL_SCANCODE_VOLUMEDOWN;
slouken@7191
   117
        case VK_VOLUME_UP: return SDL_SCANCODE_VOLUMEUP;
jorgen@6922
   118
slouken@7191
   119
        case VK_MEDIA_NEXT_TRACK: return SDL_SCANCODE_AUDIONEXT;
slouken@7191
   120
        case VK_MEDIA_PREV_TRACK: return SDL_SCANCODE_AUDIOPREV;
slouken@7191
   121
        case VK_MEDIA_STOP: return SDL_SCANCODE_AUDIOSTOP;
slouken@7191
   122
        case VK_MEDIA_PLAY_PAUSE: return SDL_SCANCODE_AUDIOPLAY;
slouken@7191
   123
        case VK_LAUNCH_MAIL: return SDL_SCANCODE_MAIL;
slouken@7191
   124
        case VK_LAUNCH_MEDIA_SELECT: return SDL_SCANCODE_MEDIASELECT;
jorgen@6922
   125
slouken@7191
   126
        case VK_OEM_102: return SDL_SCANCODE_NONUSBACKSLASH;
jorgen@6922
   127
slouken@7191
   128
        case VK_ATTN: return SDL_SCANCODE_SYSREQ;
slouken@7191
   129
        case VK_CRSEL: return SDL_SCANCODE_CRSEL;
slouken@7191
   130
        case VK_EXSEL: return SDL_SCANCODE_EXSEL;
slouken@7191
   131
        case VK_OEM_CLEAR: return SDL_SCANCODE_CLEAR;
jorgen@6922
   132
slouken@7191
   133
        case VK_LAUNCH_APP1: return SDL_SCANCODE_APP1;
slouken@7191
   134
        case VK_LAUNCH_APP2: return SDL_SCANCODE_APP2;
jorgen@6922
   135
slouken@7191
   136
        default: return SDL_SCANCODE_UNKNOWN;
slouken@7191
   137
        }
slouken@7191
   138
    }
jorgen@6922
   139
slouken@7191
   140
    if ( nScanCode > 127 )
slouken@7191
   141
        return SDL_SCANCODE_UNKNOWN;
slouken@7191
   142
slouken@7191
   143
    code = windows_scancode_table[nScanCode];
slouken@7191
   144
slouken@7191
   145
    bIsExtended = ( lParam & ( 1 << 24 ) ) != 0;
slouken@7191
   146
    if ( !bIsExtended )
slouken@7191
   147
    {
slouken@7191
   148
        switch ( code )
slouken@7191
   149
        {
slouken@7191
   150
        case SDL_SCANCODE_HOME:
slouken@7191
   151
            return SDL_SCANCODE_KP_7;
slouken@7191
   152
        case SDL_SCANCODE_UP:
slouken@7191
   153
            return SDL_SCANCODE_KP_8;
slouken@7191
   154
        case SDL_SCANCODE_PAGEUP:
slouken@7191
   155
            return SDL_SCANCODE_KP_9;
slouken@7191
   156
        case SDL_SCANCODE_LEFT:
slouken@7191
   157
            return SDL_SCANCODE_KP_4;
slouken@7191
   158
        case SDL_SCANCODE_RIGHT:
slouken@7191
   159
            return SDL_SCANCODE_KP_6;
slouken@7191
   160
        case SDL_SCANCODE_END:
slouken@7191
   161
            return SDL_SCANCODE_KP_1;
slouken@7191
   162
        case SDL_SCANCODE_DOWN:
slouken@7191
   163
            return SDL_SCANCODE_KP_2;
slouken@7191
   164
        case SDL_SCANCODE_PAGEDOWN:
slouken@7191
   165
            return SDL_SCANCODE_KP_3;
slouken@7191
   166
        case SDL_SCANCODE_INSERT:
slouken@7191
   167
            return SDL_SCANCODE_KP_0;
slouken@7191
   168
        case SDL_SCANCODE_DELETE:
slouken@7191
   169
            return SDL_SCANCODE_KP_PERIOD;
slouken@7191
   170
        case SDL_SCANCODE_PRINTSCREEN:
slouken@7191
   171
            return SDL_SCANCODE_KP_MULTIPLY;
slouken@7029
   172
        default:
slouken@7029
   173
            break;
slouken@7191
   174
        }
slouken@7191
   175
    }
slouken@7191
   176
    else
slouken@7191
   177
    {
slouken@7191
   178
        switch ( code )
slouken@7191
   179
        {
slouken@7191
   180
        case SDL_SCANCODE_RETURN:
slouken@7191
   181
            return SDL_SCANCODE_KP_ENTER;
slouken@7191
   182
        case SDL_SCANCODE_LALT:
slouken@7191
   183
            return SDL_SCANCODE_RALT;
slouken@7191
   184
        case SDL_SCANCODE_LCTRL:
slouken@7191
   185
            return SDL_SCANCODE_RCTRL;
slouken@7191
   186
        case SDL_SCANCODE_SLASH:
slouken@7191
   187
            return SDL_SCANCODE_KP_DIVIDE;
slouken@7191
   188
        case SDL_SCANCODE_CAPSLOCK:
slouken@7191
   189
            return SDL_SCANCODE_KP_PLUS;
slouken@7191
   190
        default:
slouken@7191
   191
            break;
slouken@7191
   192
        }
slouken@7191
   193
    }
jorgen@6922
   194
slouken@7191
   195
    return code;
jorgen@6922
   196
}
jorgen@6922
   197
jorgen@6922
   198
slouken@7191
   199
void
slouken@6943
   200
WIN_CheckWParamMouseButton( SDL_bool bwParamMousePressed, SDL_bool bSDLMousePressed, SDL_WindowData *data, Uint8 button )
slouken@6943
   201
{
slouken@7191
   202
    if ( bwParamMousePressed && !bSDLMousePressed )
slouken@7191
   203
    {
slouken@7191
   204
        SDL_SendMouseButton(data->window, 0, SDL_PRESSED, button);
slouken@7191
   205
    }
slouken@7191
   206
    else if ( !bwParamMousePressed && bSDLMousePressed )
slouken@7191
   207
    {
slouken@7191
   208
        SDL_SendMouseButton(data->window, 0, SDL_RELEASED, button);
slouken@7191
   209
    }
slouken@6943
   210
}
slouken@6943
   211
slouken@6943
   212
/*
slouken@6943
   213
* Some windows systems fail to send a WM_LBUTTONDOWN sometimes, but each mouse move contains the current button state also
slouken@6943
   214
*  so this funciton reconciles our view of the world with the current buttons reported by windows
slouken@6943
   215
*/
slouken@7191
   216
void
slouken@6943
   217
WIN_CheckWParamMouseButtons( WPARAM wParam, SDL_WindowData *data )
slouken@6943
   218
{
slouken@7191
   219
    if ( wParam != data->mouse_button_flags )
slouken@7191
   220
    {
slouken@7191
   221
        Uint32 mouseFlags = SDL_GetMouseState( NULL, NULL );
slouken@7191
   222
        WIN_CheckWParamMouseButton(  (wParam & MK_LBUTTON), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT );
slouken@7191
   223
        WIN_CheckWParamMouseButton(  (wParam & MK_MBUTTON), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE );
slouken@7191
   224
        WIN_CheckWParamMouseButton(  (wParam & MK_RBUTTON), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT );
slouken@7191
   225
        WIN_CheckWParamMouseButton(  (wParam & MK_XBUTTON1), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1 );
slouken@7191
   226
        WIN_CheckWParamMouseButton(  (wParam & MK_XBUTTON2), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2 );
slouken@7191
   227
        data->mouse_button_flags = wParam;
slouken@7191
   228
    }
slouken@6943
   229
}
slouken@6943
   230
slouken@6943
   231
slouken@7191
   232
void
slouken@6943
   233
WIN_CheckRawMouseButtons( ULONG rawButtons, SDL_WindowData *data )
slouken@6943
   234
{
slouken@7191
   235
    if ( rawButtons != data->mouse_button_flags )
slouken@7191
   236
    {
slouken@7191
   237
        Uint32 mouseFlags = SDL_GetMouseState( NULL, NULL );
slouken@7191
   238
        if ( (rawButtons & RI_MOUSE_BUTTON_1_DOWN) )
slouken@7191
   239
            WIN_CheckWParamMouseButton(  (rawButtons & RI_MOUSE_BUTTON_1_DOWN), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT );
slouken@7191
   240
        if ( (rawButtons & RI_MOUSE_BUTTON_1_UP) )
slouken@7191
   241
            WIN_CheckWParamMouseButton(  !(rawButtons & RI_MOUSE_BUTTON_1_UP), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT );
slouken@7191
   242
        if ( (rawButtons & RI_MOUSE_BUTTON_2_DOWN) )
slouken@7191
   243
            WIN_CheckWParamMouseButton(  (rawButtons & RI_MOUSE_BUTTON_2_DOWN), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT );
slouken@7191
   244
        if ( (rawButtons & RI_MOUSE_BUTTON_2_UP) )
slouken@7191
   245
            WIN_CheckWParamMouseButton(  !(rawButtons & RI_MOUSE_BUTTON_2_UP), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT );
slouken@7191
   246
        if ( (rawButtons & RI_MOUSE_BUTTON_3_DOWN) )
slouken@7191
   247
            WIN_CheckWParamMouseButton(  (rawButtons & RI_MOUSE_BUTTON_3_DOWN), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE );
slouken@7191
   248
        if ( (rawButtons & RI_MOUSE_BUTTON_3_UP) )
slouken@7191
   249
            WIN_CheckWParamMouseButton(  !(rawButtons & RI_MOUSE_BUTTON_3_UP), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE );
slouken@7191
   250
        if ( (rawButtons & RI_MOUSE_BUTTON_4_DOWN) )
slouken@7191
   251
            WIN_CheckWParamMouseButton(  (rawButtons & RI_MOUSE_BUTTON_4_DOWN), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1 );
slouken@7191
   252
        if ( (rawButtons & RI_MOUSE_BUTTON_4_UP) )
slouken@7191
   253
            WIN_CheckWParamMouseButton(  !(rawButtons & RI_MOUSE_BUTTON_4_UP), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1 );
slouken@7191
   254
        if ( (rawButtons & RI_MOUSE_BUTTON_5_DOWN) )
slouken@7191
   255
            WIN_CheckWParamMouseButton(  (rawButtons & RI_MOUSE_BUTTON_5_DOWN), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2 );
slouken@7191
   256
        if ( (rawButtons & RI_MOUSE_BUTTON_5_UP) )
slouken@7191
   257
            WIN_CheckWParamMouseButton(  !(rawButtons & RI_MOUSE_BUTTON_5_UP), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2 );
slouken@7191
   258
        data->mouse_button_flags = rawButtons;
slouken@7191
   259
    }
slouken@6943
   260
}
slouken@6943
   261
slouken@7647
   262
SDL_FORCE_INLINE BOOL
slouken@7645
   263
WIN_ConvertUTF32toUTF8(UINT32 codepoint, char * text)
slouken@7645
   264
{
slouken@7645
   265
    if (codepoint <= 0x7F) {
slouken@7645
   266
        text[0] = (char) codepoint;
slouken@7645
   267
        text[1] = '\0';
slouken@7645
   268
    } else if (codepoint <= 0x7FF) {
slouken@7645
   269
        text[0] = 0xC0 | (char) ((codepoint >> 6) & 0x1F);
slouken@7645
   270
        text[1] = 0x80 | (char) (codepoint & 0x3F);
slouken@7645
   271
        text[2] = '\0';
slouken@7645
   272
    } else if (codepoint <= 0xFFFF) {
slouken@7645
   273
        text[0] = 0xE0 | (char) ((codepoint >> 12) & 0x0F);
slouken@7645
   274
        text[1] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
slouken@7645
   275
        text[2] = 0x80 | (char) (codepoint & 0x3F);
slouken@7645
   276
        text[3] = '\0';
slouken@7645
   277
    } else if (codepoint <= 0x10FFFF) {
slouken@7645
   278
        text[0] = 0xF0 | (char) ((codepoint >> 18) & 0x0F);
slouken@7645
   279
        text[1] = 0x80 | (char) ((codepoint >> 12) & 0x3F);
slouken@7645
   280
        text[2] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
slouken@7645
   281
        text[3] = 0x80 | (char) (codepoint & 0x3F);
slouken@7645
   282
        text[4] = '\0';
slouken@7645
   283
    } else {
slouken@7645
   284
        return SDL_FALSE;
slouken@7645
   285
    }
slouken@7645
   286
    return SDL_TRUE;
slouken@7645
   287
}
slouken@7645
   288
slouken@1895
   289
LRESULT CALLBACK
slouken@1895
   290
WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
slouken@1895
   291
{
slouken@1895
   292
    SDL_WindowData *data;
slouken@3566
   293
    LRESULT returnCode = -1;
slouken@1895
   294
slouken@1951
   295
    /* Send a SDL_SYSWMEVENT if the application wants them */
slouken@4429
   296
    if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
slouken@1951
   297
        SDL_SysWMmsg wmmsg;
slouken@1951
   298
slouken@1951
   299
        SDL_VERSION(&wmmsg.version);
slouken@4900
   300
        wmmsg.subsystem = SDL_SYSWM_WINDOWS;
slouken@5056
   301
        wmmsg.msg.win.hwnd = hwnd;
slouken@5056
   302
        wmmsg.msg.win.msg = msg;
slouken@5056
   303
        wmmsg.msg.win.wParam = wParam;
slouken@5056
   304
        wmmsg.msg.win.lParam = lParam;
slouken@1951
   305
        SDL_SendSysWMEvent(&wmmsg);
slouken@1951
   306
    }
slouken@1951
   307
slouken@1895
   308
    /* Get the window data for the window */
slouken@1895
   309
    data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData"));
slouken@1895
   310
    if (!data) {
slouken@1895
   311
        return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
slouken@1895
   312
    }
jimtla@4650
   313
slouken@1895
   314
#ifdef WMMSG_DEBUG
slouken@7941
   315
    {
slouken@7941
   316
        char message[1024];
slouken@7941
   317
        if (msg > MAX_WMMSG) {
slouken@7941
   318
            SDL_snprintf(message, sizeof(message), "Received windows message: %p UNKNOWN (%d) -- 0x%X, 0x%X\n", hwnd, msg, wParam, lParam);
slouken@7941
   319
        } else {
slouken@7941
   320
            SDL_snprintf(message, sizeof(message), "Received windows message: %p %s -- 0x%X, 0x%X\n", hwnd, wmtab[msg], wParam, lParam);
slouken@7941
   321
        }
slouken@7941
   322
        OutputDebugStringA(message);
slouken@7941
   323
    }
slouken@7816
   324
#endif /* WMMSG_DEBUG */
slouken@2710
   325
dewyatt@4752
   326
    if (IME_HandleMessage(hwnd, msg, wParam, &lParam, data->videodata))
dewyatt@4752
   327
        return 0;
slouken@1895
   328
slouken@1895
   329
    switch (msg) {
slouken@1895
   330
slouken@1895
   331
    case WM_SHOWWINDOW:
slouken@1895
   332
        {
slouken@1895
   333
            if (wParam) {
slouken@3685
   334
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
slouken@1895
   335
            } else {
slouken@3685
   336
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
slouken@1895
   337
            }
slouken@1895
   338
        }
slouken@1895
   339
        break;
slouken@1895
   340
slouken@1895
   341
    case WM_ACTIVATE:
slouken@1895
   342
        {
slouken@1895
   343
            BOOL minimized;
slouken@1895
   344
slouken@1895
   345
            minimized = HIWORD(wParam);
slouken@1895
   346
            if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
slouken@7191
   347
                Uint32 mouseFlags;
slouken@7191
   348
                SHORT keyState;
slouken@6945
   349
slouken@3685
   350
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
slouken@4465
   351
                if (SDL_GetKeyboardFocus() != data->window) {
slouken@4465
   352
                    SDL_SetKeyboardFocus(data->window);
slouken@1895
   353
                }
slouken@7191
   354
                /* mouse buttons may have changed state here, we need
slouken@7191
   355
                to resync them, but we will get a WM_MOUSEMOVE right away which will fix
slouken@7191
   356
                things up if in non raw mode also
slouken@7191
   357
                */
slouken@7191
   358
                mouseFlags = SDL_GetMouseState( NULL, NULL );
slouken@6945
   359
slouken@7191
   360
                keyState = GetAsyncKeyState( VK_LBUTTON );
slouken@7191
   361
                WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT );
slouken@7191
   362
                keyState = GetAsyncKeyState( VK_RBUTTON );
slouken@7191
   363
                WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT );
slouken@7191
   364
                keyState = GetAsyncKeyState( VK_MBUTTON );
slouken@7191
   365
                WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE );
slouken@7191
   366
                keyState = GetAsyncKeyState( VK_XBUTTON1 );
slouken@7191
   367
                WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1 );
slouken@7191
   368
                keyState = GetAsyncKeyState( VK_XBUTTON2 );
slouken@7191
   369
                WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2 );
slouken@7191
   370
                data->mouse_button_flags = 0;
slouken@6350
   371
slouken@8036
   372
                WIN_UpdateClipCursor(data->window);
slouken@6350
   373
slouken@4504
   374
                /*
slouken@4504
   375
                 * FIXME: Update keyboard state
slouken@4504
   376
                 */
slouken@4504
   377
                WIN_CheckClipboardUpdate(data->videodata);
slouken@1895
   378
            } else {
slouken@4465
   379
                if (SDL_GetKeyboardFocus() == data->window) {
slouken@4465
   380
                    SDL_SetKeyboardFocus(NULL);
slouken@1895
   381
                }
slouken@8050
   382
slouken@8050
   383
                ClipCursor(NULL);
slouken@1895
   384
            }
slouken@1895
   385
        }
slouken@3566
   386
        returnCode = 0;
slouken@3566
   387
        break;
slouken@1895
   388
slouken@7191
   389
    case WM_MOUSEMOVE:
slouken@8071
   390
        {
slouken@8071
   391
            SDL_Mouse *mouse = SDL_GetMouse();
slouken@8071
   392
            if (!mouse->relative_mode || mouse->relative_mode_warp) {
slouken@8071
   393
                SDL_SendMouseMotion(data->window, 0, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
slouken@8071
   394
            }
slouken@8071
   395
        }
slouken@7191
   396
        /* don't break here, fall through to check the wParam like the button presses */
slouken@7191
   397
    case WM_LBUTTONUP:
slouken@7191
   398
    case WM_RBUTTONUP:
slouken@7191
   399
    case WM_MBUTTONUP:
slouken@7191
   400
    case WM_XBUTTONUP:
slouken@7191
   401
    case WM_LBUTTONDOWN:
slouken@7191
   402
    case WM_RBUTTONDOWN:
slouken@7191
   403
    case WM_MBUTTONDOWN:
slouken@7191
   404
    case WM_XBUTTONDOWN:
slouken@8071
   405
        {
slouken@8071
   406
            SDL_Mouse *mouse = SDL_GetMouse();
slouken@8071
   407
            if (!mouse->relative_mode || mouse->relative_mode_warp) {
slouken@8071
   408
                WIN_CheckWParamMouseButtons(wParam, data);
slouken@8071
   409
            }
slouken@8071
   410
        }
slouken@7191
   411
        break;
slouken@3139
   412
slouken@7191
   413
    case WM_INPUT:
slouken@8071
   414
        {
slouken@8071
   415
            SDL_Mouse *mouse = SDL_GetMouse();
slouken@8071
   416
            HRAWINPUT hRawInput = (HRAWINPUT)lParam;
slouken@8071
   417
            RAWINPUT inp;
slouken@8071
   418
            UINT size = sizeof(inp);
slouken@6782
   419
slouken@8084
   420
            if (!mouse->relative_mode || mouse->relative_mode_warp || mouse->focus != data->window) {
slouken@8071
   421
                break;
slouken@8071
   422
            }
slouken@6782
   423
slouken@8071
   424
            GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER));
slouken@6350
   425
slouken@8071
   426
            /* Mouse data */
slouken@8071
   427
            if (inp.header.dwType == RIM_TYPEMOUSE) {
slouken@8071
   428
                RAWMOUSE* mouse = &inp.data.mouse;
slouken@6350
   429
slouken@8071
   430
                if ((mouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) {
slouken@8071
   431
                    SDL_SendMouseMotion(data->window, 0, 1, (int)mouse->lLastX, (int)mouse->lLastY);
slouken@8071
   432
                } else {
slouken@8071
   433
                    /* synthesize relative moves from the abs position */
slouken@8071
   434
                    static SDL_Point initialMousePoint;
slouken@8071
   435
                    if (initialMousePoint.x == 0 && initialMousePoint.y == 0) {
slouken@8071
   436
                        initialMousePoint.x = mouse->lLastX;
slouken@8071
   437
                        initialMousePoint.y = mouse->lLastY;
slouken@8071
   438
                    }
slouken@8071
   439
slouken@8071
   440
                    SDL_SendMouseMotion(data->window, 0, 1, (int)(mouse->lLastX-initialMousePoint.x), (int)(mouse->lLastY-initialMousePoint.y) );
slouken@8071
   441
slouken@7191
   442
                    initialMousePoint.x = mouse->lLastX;
slouken@7191
   443
                    initialMousePoint.y = mouse->lLastY;
slouken@7191
   444
                }
slouken@8071
   445
                WIN_CheckRawMouseButtons( mouse->usButtonFlags, data );
slouken@7191
   446
            }
slouken@7191
   447
        }
slouken@7191
   448
        break;
slouken@6350
   449
slouken@5049
   450
    case WM_MOUSEWHEEL:
slouken@5049
   451
        {
slouken@7813
   452
            static short s_AccumulatedMotion;
slouken@5049
   453
slouken@7813
   454
            s_AccumulatedMotion += GET_WHEEL_DELTA_WPARAM(wParam);
slouken@7813
   455
            if (s_AccumulatedMotion > 0) {
slouken@7813
   456
                while (s_AccumulatedMotion >= WHEEL_DELTA) {
slouken@7813
   457
                    SDL_SendMouseWheel(data->window, 0, 0, 1);
slouken@7813
   458
                    s_AccumulatedMotion -= WHEEL_DELTA;
slouken@7813
   459
                }
slouken@7813
   460
            } else {
slouken@7813
   461
                while (s_AccumulatedMotion <= -WHEEL_DELTA) {
slouken@7813
   462
                    SDL_SendMouseWheel(data->window, 0, 0, -1);
slouken@7813
   463
                    s_AccumulatedMotion += WHEEL_DELTA;
slouken@7813
   464
                }
slouken@7813
   465
            }
slouken@5049
   466
        }
slouken@8071
   467
        break;
slouken@5049
   468
slouken@7911
   469
    case WM_MOUSEHWHEEL:
slouken@7911
   470
        {
slouken@7911
   471
            static short s_AccumulatedMotion;
slouken@7911
   472
slouken@7911
   473
            s_AccumulatedMotion += GET_WHEEL_DELTA_WPARAM(wParam);
slouken@7911
   474
            if (s_AccumulatedMotion > 0) {
slouken@7911
   475
                while (s_AccumulatedMotion >= WHEEL_DELTA) {
slouken@7912
   476
                    SDL_SendMouseWheel(data->window, 0, 1, 0);
slouken@7911
   477
                    s_AccumulatedMotion -= WHEEL_DELTA;
slouken@7911
   478
                }
slouken@7911
   479
            } else {
slouken@7911
   480
                while (s_AccumulatedMotion <= -WHEEL_DELTA) {
slouken@7912
   481
                    SDL_SendMouseWheel(data->window, 0, -1, 0);
slouken@7911
   482
                    s_AccumulatedMotion += WHEEL_DELTA;
slouken@7911
   483
                }
slouken@7911
   484
            }
slouken@7911
   485
        }
slouken@8071
   486
        break;
slouken@7911
   487
slouken@5086
   488
#ifdef WM_MOUSELEAVE
slouken@1895
   489
    case WM_MOUSELEAVE:
jorgen@7275
   490
        if (SDL_GetMouseFocus() == data->window && !SDL_GetMouse()->relative_mode) {
slouken@8035
   491
            if (!IsIconic(hwnd)) {
slouken@8035
   492
                POINT cursorPos;
slouken@8035
   493
                GetCursorPos(&cursorPos);
slouken@8035
   494
                ScreenToClient(hwnd, &cursorPos);
slouken@8035
   495
                SDL_SendMouseMotion(data->window, 0, 0, cursorPos.x, cursorPos.y);
slouken@8035
   496
            }
slouken@7191
   497
            SDL_SetMouseFocus(NULL);
slouken@1895
   498
        }
slouken@3566
   499
        returnCode = 0;
slouken@3566
   500
        break;
slouken@5086
   501
#endif /* WM_MOUSELEAVE */
slouken@1895
   502
slouken@7645
   503
    case WM_KEYDOWN:
slouken@7646
   504
    case WM_SYSKEYDOWN:
slouken@7645
   505
        {
slouken@7646
   506
            SDL_Scancode code = WindowsScanCodeToSDLScanCode( lParam, wParam );
slouken@7646
   507
            if ( code != SDL_SCANCODE_UNKNOWN ) {
slouken@7646
   508
                SDL_SendKeyboardKey(SDL_PRESSED, code );
slouken@7646
   509
            }
slouken@7646
   510
        }
slouken@7646
   511
        if (msg == WM_KEYDOWN) {
slouken@7645
   512
            BYTE keyboardState[256];
slouken@7645
   513
            char text[5];
slouken@7645
   514
            UINT32 utf32 = 0;
slouken@7645
   515
slouken@7645
   516
            GetKeyboardState(keyboardState);
slouken@7645
   517
            if (ToUnicode(wParam, (lParam >> 16) & 0xff, keyboardState, (LPWSTR)&utf32, 1, 0) > 0) {
slouken@8071
   518
                WORD repetition;
slouken@8071
   519
                for (repetition = lParam & 0xffff; repetition > 0; repetition--) {
slouken@7645
   520
                    WIN_ConvertUTF32toUTF8(utf32, text);
slouken@7645
   521
                    SDL_SendKeyboardText(text);
slouken@7645
   522
                }
slouken@7645
   523
            }
slouken@7645
   524
        }
slouken@3566
   525
        returnCode = 0;
slouken@3566
   526
        break;
slouken@1895
   527
slouken@1895
   528
    case WM_SYSKEYUP:
slouken@1895
   529
    case WM_KEYUP:
slouken@1895
   530
        {
slouken@6938
   531
            SDL_Scancode code = WindowsScanCodeToSDLScanCode( lParam, wParam );
gabomdq@7975
   532
            const Uint8 *keyboardState = SDL_GetKeyboardState(NULL);
gabomdq@7975
   533
gabomdq@7975
   534
            /* Detect relevant keyboard shortcuts */
gabomdq@7975
   535
            if (keyboardState[SDL_SCANCODE_LALT] == SDL_PRESSED || keyboardState[SDL_SCANCODE_RALT] == SDL_PRESSED ) {
gabomdq@7975
   536
	            /* ALT+F4: Close window */
gabomdq@7975
   537
	            if (code == SDL_SCANCODE_F4) {
gabomdq@7975
   538
		            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
gabomdq@7975
   539
	            }
gabomdq@7975
   540
            }
gabomdq@7975
   541
slouken@6938
   542
            if ( code != SDL_SCANCODE_UNKNOWN ) {
slouken@6938
   543
                if (code == SDL_SCANCODE_PRINTSCREEN &&
gabomdq@7975
   544
                    keyboardState[code] == SDL_RELEASED) {
slouken@6938
   545
                    SDL_SendKeyboardKey(SDL_PRESSED, code);
slouken@6938
   546
                }
slouken@6938
   547
                SDL_SendKeyboardKey(SDL_RELEASED, code);
slouken@2308
   548
            }
slouken@1895
   549
        }
slouken@3566
   550
        returnCode = 0;
slouken@3566
   551
        break;
slouken@1895
   552
slouken@7645
   553
    case WM_UNICHAR:
slouken@7645
   554
        {
slouken@7645
   555
            if (wParam == UNICODE_NOCHAR) {
slouken@7645
   556
                returnCode = 1;
slouken@7645
   557
                break;
slouken@7645
   558
            }
slouken@7645
   559
        }
gabomdq@7663
   560
        /* no break */
slouken@2309
   561
    case WM_CHAR:
slouken@2309
   562
        {
slouken@7645
   563
            char text[5];
slouken@2309
   564
slouken@7645
   565
            WIN_ConvertUTF32toUTF8(wParam, text);
slouken@4465
   566
            SDL_SendKeyboardText(text);
slouken@2309
   567
        }
slouken@3566
   568
        returnCode = 0;
slouken@3566
   569
        break;
slouken@2309
   570
slouken@5086
   571
#ifdef WM_INPUTLANGCHANGE
slouken@2311
   572
    case WM_INPUTLANGCHANGE:
slouken@2311
   573
        {
slouken@4465
   574
            WIN_UpdateKeymap();
slouken@2311
   575
        }
slouken@3566
   576
        returnCode = 1;
slouken@3566
   577
        break;
slouken@5086
   578
#endif /* WM_INPUTLANGCHANGE */
slouken@2311
   579
slouken@8036
   580
    case WM_ENTERSIZEMOVE:
slouken@8036
   581
    case WM_ENTERMENULOOP:
slouken@8036
   582
        {
slouken@8036
   583
            data->in_modal_loop = SDL_TRUE;
slouken@8036
   584
            WIN_UpdateClipCursor(data->window);
slouken@8036
   585
        }
slouken@8036
   586
        break;
slouken@8036
   587
slouken@8036
   588
    case WM_EXITSIZEMOVE:
slouken@8036
   589
    case WM_EXITMENULOOP:
slouken@8036
   590
        {
slouken@8036
   591
            data->in_modal_loop = SDL_FALSE;
slouken@8036
   592
            WIN_UpdateClipCursor(data->window);
slouken@8036
   593
        }
slouken@8036
   594
        break;
slouken@8036
   595
slouken@5086
   596
#ifdef WM_GETMINMAXINFO
slouken@1895
   597
    case WM_GETMINMAXINFO:
slouken@1895
   598
        {
slouken@1895
   599
            MINMAXINFO *info;
slouken@1895
   600
            RECT size;
slouken@1895
   601
            int x, y;
slouken@1895
   602
            int w, h;
stopiccot@6682
   603
            int min_w, min_h;
slouken@6788
   604
            int max_w, max_h;
slouken@1895
   605
            int style;
slouken@3168
   606
            BOOL menu;
slouken@7191
   607
            BOOL constrain_max_size;
slouken@1895
   608
stopiccot@6682
   609
            if (SDL_IsShapedWindow(data->window))
eligottlieb@4815
   610
                Win32_ResizeWindowShape(data->window);
slouken@1895
   611
slouken@7941
   612
            /* If this is an expected size change, allow it */
slouken@7941
   613
            if (data->expected_resize) {
slouken@7941
   614
                break;
slouken@7941
   615
            }
slouken@7941
   616
slouken@1895
   617
            /* Get the current position of our window */
slouken@1895
   618
            GetWindowRect(hwnd, &size);
slouken@1895
   619
            x = size.left;
slouken@1895
   620
            y = size.top;
slouken@1895
   621
slouken@1895
   622
            /* Calculate current size of our window */
slouken@3685
   623
            SDL_GetWindowSize(data->window, &w, &h);
stopiccot@6682
   624
            SDL_GetWindowMinimumSize(data->window, &min_w, &min_h);
slouken@6788
   625
            SDL_GetWindowMaximumSize(data->window, &max_w, &max_h);
stopiccot@6682
   626
slouken@7191
   627
            /* Store in min_w and min_h difference between current size and minimal
stopiccot@6682
   628
               size so we don't need to call AdjustWindowRectEx twice */
stopiccot@6682
   629
            min_w -= w;
stopiccot@6682
   630
            min_h -= h;
slouken@6837
   631
            if (max_w && max_h) {
slouken@6837
   632
                max_w -= w;
slouken@6837
   633
                max_h -= h;
slouken@6862
   634
                constrain_max_size = TRUE;
slouken@6862
   635
            } else {
slouken@6862
   636
                constrain_max_size = FALSE;
slouken@6837
   637
            }
stopiccot@6682
   638
slouken@1895
   639
            size.top = 0;
slouken@1895
   640
            size.left = 0;
slouken@1895
   641
            size.bottom = h;
slouken@1895
   642
            size.right = w;
slouken@1895
   643
slouken@3168
   644
            style = GetWindowLong(hwnd, GWL_STYLE);
slouken@1895
   645
            /* DJM - according to the docs for GetMenu(), the
slouken@1895
   646
               return value is undefined if hwnd is a child window.
slouken@1895
   647
               Aparently it's too difficult for MS to check
slouken@1895
   648
               inside their function, so I have to do it here.
slouken@1895
   649
             */
slouken@3168
   650
            menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
slouken@3168
   651
            AdjustWindowRectEx(&size, style, menu, 0);
slouken@1895
   652
            w = size.right - size.left;
slouken@1895
   653
            h = size.bottom - size.top;
slouken@1895
   654
slouken@1895
   655
            /* Fix our size to the current size */
slouken@1895
   656
            info = (MINMAXINFO *) lParam;
stopiccot@6682
   657
            if (SDL_GetWindowFlags(data->window) & SDL_WINDOW_RESIZABLE) {
stopiccot@6682
   658
                info->ptMinTrackSize.x = w + min_w;
stopiccot@6682
   659
                info->ptMinTrackSize.y = h + min_h;
slouken@6862
   660
                if (constrain_max_size) {
slouken@6862
   661
                    info->ptMaxTrackSize.x = w + max_w;
slouken@6862
   662
                    info->ptMaxTrackSize.y = h + max_h;
slouken@6862
   663
                }
stopiccot@6682
   664
            } else {
stopiccot@6682
   665
                info->ptMaxSize.x = w;
stopiccot@6682
   666
                info->ptMaxSize.y = h;
stopiccot@6682
   667
                info->ptMaxPosition.x = x;
stopiccot@6682
   668
                info->ptMaxPosition.y = y;
stopiccot@6682
   669
                info->ptMinTrackSize.x = w;
stopiccot@6682
   670
                info->ptMinTrackSize.y = h;
stopiccot@6682
   671
                info->ptMaxTrackSize.x = w;
stopiccot@6682
   672
                info->ptMaxTrackSize.y = h;
stopiccot@6682
   673
            }
slouken@1895
   674
        }
slouken@3566
   675
        returnCode = 0;
slouken@3566
   676
        break;
slouken@5086
   677
#endif /* WM_GETMINMAXINFO */
slouken@1895
   678
slouken@1895
   679
    case WM_WINDOWPOSCHANGED:
slouken@1895
   680
        {
slouken@1895
   681
            RECT rect;
slouken@1895
   682
            int x, y;
slouken@1895
   683
            int w, h;
slouken@1895
   684
slouken@8036
   685
            if (!GetClientRect(hwnd, &rect) || IsRectEmpty(&rect)) {
slouken@3256
   686
                break;
slouken@3256
   687
            }
slouken@1895
   688
            ClientToScreen(hwnd, (LPPOINT) & rect);
slouken@1895
   689
            ClientToScreen(hwnd, (LPPOINT) & rect + 1);
slouken@1895
   690
slouken@8036
   691
            WIN_UpdateClipCursor(data->window);
slouken@1895
   692
slouken@1895
   693
            x = rect.left;
slouken@1895
   694
            y = rect.top;
slouken@3685
   695
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, x, y);
slouken@1895
   696
slouken@1895
   697
            w = rect.right - rect.left;
slouken@1895
   698
            h = rect.bottom - rect.top;
slouken@3685
   699
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, w,
slouken@1895
   700
                                h);
slouken@1895
   701
        }
slouken@1895
   702
        break;
slouken@1895
   703
slouken@7941
   704
    case WM_SIZE:
slouken@7941
   705
        {
slouken@7941
   706
            switch (wParam)
slouken@7941
   707
            {
slouken@7941
   708
            case SIZE_MAXIMIZED:
slouken@7941
   709
                SDL_SendWindowEvent(data->window,
slouken@7941
   710
                    SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
slouken@7941
   711
                break;
slouken@7941
   712
            case SIZE_MINIMIZED:
slouken@7941
   713
                SDL_SendWindowEvent(data->window,
slouken@7941
   714
                    SDL_WINDOWEVENT_MINIMIZED, 0, 0);
slouken@7941
   715
                break;
slouken@7941
   716
            default:
slouken@7941
   717
                SDL_SendWindowEvent(data->window,
slouken@7941
   718
                    SDL_WINDOWEVENT_RESTORED, 0, 0);
slouken@7941
   719
                break;
slouken@7941
   720
            }
slouken@7941
   721
        }
slouken@7941
   722
        break;
slouken@7941
   723
slouken@1895
   724
    case WM_SETCURSOR:
slouken@1895
   725
        {
slouken@3076
   726
            Uint16 hittest;
slouken@1895
   727
slouken@3076
   728
            hittest = LOWORD(lParam);
slouken@3076
   729
            if (hittest == HTCLIENT) {
slouken@5421
   730
                SetCursor(SDL_cursor);
slouken@3566
   731
                returnCode = TRUE;
slouken@3076
   732
            }
slouken@1895
   733
        }
slouken@1895
   734
        break;
slouken@1895
   735
slouken@1895
   736
        /* We were occluded, refresh our display */
slouken@1895
   737
    case WM_PAINT:
slouken@1895
   738
        {
slouken@1895
   739
            RECT rect;
slouken@1895
   740
            if (GetUpdateRect(hwnd, &rect, FALSE)) {
slouken@7295
   741
                ValidateRect(hwnd, NULL);
slouken@3685
   742
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED,
slouken@1895
   743
                                    0, 0);
slouken@1895
   744
            }
slouken@1895
   745
        }
slouken@3566
   746
        returnCode = 0;
slouken@3566
   747
        break;
slouken@3095
   748
slouken@1895
   749
        /* We'll do our own drawing, prevent flicker */
slouken@1895
   750
    case WM_ERASEBKGND:
slouken@1895
   751
        {
slouken@1895
   752
        }
slouken@1895
   753
        return (1);
slouken@1895
   754
slouken@5086
   755
#if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
slouken@1895
   756
    case WM_SYSCOMMAND:
slouken@1895
   757
        {
slouken@1895
   758
            /* Don't start the screensaver or blank the monitor in fullscreen apps */
slouken@1895
   759
            if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
slouken@1895
   760
                (wParam & 0xFFF0) == SC_MONITORPOWER) {
slouken@3032
   761
                if (SDL_GetVideoDevice()->suspend_screensaver) {
slouken@1895
   762
                    return (0);
slouken@1895
   763
                }
slouken@1895
   764
            }
slouken@1895
   765
        }
slouken@1895
   766
        break;
slouken@5086
   767
#endif /* System has screensaver support */
slouken@1895
   768
slouken@1895
   769
    case WM_CLOSE:
slouken@1895
   770
        {
slouken@3685
   771
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
slouken@1895
   772
        }
slouken@3566
   773
        returnCode = 0;
slouken@3566
   774
        break;
slouken@4919
   775
slouken@7191
   776
    case WM_TOUCH:
slouken@7191
   777
        {
slouken@7191
   778
            UINT i, num_inputs = LOWORD(wParam);
slouken@7191
   779
            PTOUCHINPUT inputs = SDL_stack_alloc(TOUCHINPUT, num_inputs);
slouken@7191
   780
            if (data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs, sizeof(TOUCHINPUT))) {
slouken@7191
   781
                RECT rect;
slouken@7191
   782
                float x, y;
slouken@4919
   783
slouken@7191
   784
                if (!GetClientRect(hwnd, &rect) ||
slouken@7191
   785
                    (rect.right == rect.left && rect.bottom == rect.top)) {
philipp@7631
   786
                    if (inputs) {
philipp@7631
   787
                        SDL_stack_free(inputs);
philipp@7631
   788
                    }
slouken@7191
   789
                    break;
slouken@7191
   790
                }
slouken@7191
   791
                ClientToScreen(hwnd, (LPPOINT) & rect);
slouken@7191
   792
                ClientToScreen(hwnd, (LPPOINT) & rect + 1);
slouken@7191
   793
                rect.top *= 100;
slouken@7191
   794
                rect.left *= 100;
slouken@7191
   795
                rect.bottom *= 100;
slouken@7191
   796
                rect.right *= 100;
slouken@4932
   797
slouken@7191
   798
                for (i = 0; i < num_inputs; ++i) {
slouken@7191
   799
                    PTOUCHINPUT input = &inputs[i];
slouken@4919
   800
icculus@7543
   801
                    const SDL_TouchID touchId = (SDL_TouchID)((size_t)input->hSource);
slouken@7191
   802
                    if (!SDL_GetTouch(touchId)) {
slouken@7191
   803
                        if (SDL_AddTouch(touchId, "") < 0) {
slouken@7191
   804
                            continue;
slouken@7191
   805
                        }
slouken@7191
   806
                    }
slouken@4932
   807
slouken@7191
   808
                    /* Get the normalized coordinates for the window */
slouken@7191
   809
                    x = (float)(input->x - rect.left)/(rect.right - rect.left);
slouken@7191
   810
                    y = (float)(input->y - rect.top)/(rect.bottom - rect.top);
slouken@4932
   811
slouken@7191
   812
                    if (input->dwFlags & TOUCHEVENTF_DOWN) {
slouken@7191
   813
                        SDL_SendTouch(touchId, input->dwID, SDL_TRUE, x, y, 1.0f);
slouken@7191
   814
                    }
slouken@7191
   815
                    if (input->dwFlags & TOUCHEVENTF_MOVE) {
slouken@7191
   816
                        SDL_SendTouchMotion(touchId, input->dwID, x, y, 1.0f);
slouken@7191
   817
                    }
slouken@7191
   818
                    if (input->dwFlags & TOUCHEVENTF_UP) {
slouken@7191
   819
                        SDL_SendTouch(touchId, input->dwID, SDL_FALSE, x, y, 1.0f);
slouken@7191
   820
                    }
slouken@7191
   821
                }
slouken@7191
   822
            }
slouken@7191
   823
            SDL_stack_free(inputs);
slouken@4932
   824
slouken@7191
   825
            data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
slouken@7191
   826
            return 0;
slouken@7191
   827
        }
slouken@7191
   828
        break;
slouken@6523
   829
slouken@6523
   830
    case WM_DROPFILES:
slouken@6523
   831
        {
slouken@6523
   832
            UINT i;
slouken@6523
   833
            HDROP drop = (HDROP) wParam;
slouken@6523
   834
            UINT count = DragQueryFile(drop, 0xFFFFFFFF, NULL, 0);
slouken@6523
   835
            for (i = 0; i < count; ++i) {
slouken@6523
   836
                UINT size = DragQueryFile(drop, i, NULL, 0) + 1;
slouken@6523
   837
                LPTSTR buffer = SDL_stack_alloc(TCHAR, size);
slouken@6523
   838
                if (buffer) {
slouken@6523
   839
                    if (DragQueryFile(drop, i, buffer, size)) {
slouken@6523
   840
                        char *file = WIN_StringToUTF8(buffer);
slouken@6523
   841
                        SDL_SendDropFile(file);
slouken@6523
   842
                        SDL_free(file);
slouken@6523
   843
                    }
slouken@6523
   844
                    SDL_stack_free(buffer);
slouken@6523
   845
                }
slouken@6523
   846
            }
slouken@6523
   847
            DragFinish(drop);
slouken@6523
   848
            return 0;
slouken@6523
   849
        }
slouken@6523
   850
        break;
slouken@6523
   851
    }
slouken@3566
   852
slouken@3566
   853
    /* If there's a window proc, assume it's going to handle messages */
slouken@3566
   854
    if (data->wndproc) {
slouken@3566
   855
        return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam);
slouken@3566
   856
    } else if (returnCode >= 0) {
slouken@3566
   857
        return returnCode;
slouken@3566
   858
    } else {
slouken@3566
   859
        return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
slouken@3566
   860
    }
slouken@1895
   861
}
slouken@1895
   862
slouken@1895
   863
void
slouken@1895
   864
WIN_PumpEvents(_THIS)
slouken@1895
   865
{
icculus@7561
   866
    const Uint8 *keystate;
slouken@1895
   867
    MSG msg;
slouken@1895
   868
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
slouken@1895
   869
        DispatchMessage(&msg);
slouken@1895
   870
    }
icculus@7561
   871
icculus@7561
   872
    /* Windows loses a shift KEYUP event when you have both pressed at once and let go of one.
icculus@7561
   873
       You won't get a KEYUP until both are released, and that keyup will only be for the second
icculus@7561
   874
       key you released. Take heroic measures and check the keystate as of the last handled event,
icculus@7561
   875
       and if we think a key is pressed when Windows doesn't, unstick it in SDL's state. */
icculus@7561
   876
    keystate = SDL_GetKeyboardState(NULL);
icculus@7561
   877
    if ((keystate[SDL_SCANCODE_LSHIFT] == SDL_PRESSED) && !(GetKeyState(VK_LSHIFT) & 0x8000)) {
icculus@7561
   878
        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
icculus@7561
   879
    }
icculus@7561
   880
    if ((keystate[SDL_SCANCODE_RSHIFT] == SDL_PRESSED) && !(GetKeyState(VK_RSHIFT) & 0x8000)) {
icculus@7561
   881
        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RSHIFT);
icculus@7561
   882
    }
slouken@1895
   883
}
slouken@1895
   884
slouken@1895
   885
static int app_registered = 0;
slouken@1895
   886
LPTSTR SDL_Appname = NULL;
slouken@1895
   887
Uint32 SDL_Appstyle = 0;
slouken@1895
   888
HINSTANCE SDL_Instance = NULL;
slouken@1895
   889
slouken@1895
   890
/* Register the class for this application */
slouken@1895
   891
int
slouken@1895
   892
SDL_RegisterApp(char *name, Uint32 style, void *hInst)
slouken@1895
   893
{
slouken@1895
   894
    WNDCLASS class;
slouken@1895
   895
slouken@1895
   896
    /* Only do this once... */
slouken@1895
   897
    if (app_registered) {
slouken@1895
   898
        ++app_registered;
slouken@1895
   899
        return (0);
slouken@1895
   900
    }
slouken@1895
   901
    if (!name && !SDL_Appname) {
slouken@1895
   902
        name = "SDL_app";
slouken@5086
   903
#if defined(CS_BYTEALIGNCLIENT) || defined(CS_OWNDC)
slouken@1895
   904
        SDL_Appstyle = (CS_BYTEALIGNCLIENT | CS_OWNDC);
slouken@5086
   905
#endif
slouken@1895
   906
        SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
slouken@1895
   907
    }
slouken@1895
   908
slouken@1895
   909
    if (name) {
slouken@1895
   910
        SDL_Appname = WIN_UTF8ToString(name);
slouken@1895
   911
        SDL_Appstyle = style;
slouken@1895
   912
        SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
slouken@1895
   913
    }
slouken@1895
   914
slouken@1895
   915
    /* Register the application class */
slouken@1895
   916
    class.hCursor = NULL;
slouken@2710
   917
    class.hIcon =
slouken@2710
   918
        LoadImage(SDL_Instance, SDL_Appname, IMAGE_ICON, 0, 0,
slouken@2710
   919
                  LR_DEFAULTCOLOR);
slouken@1895
   920
    class.lpszMenuName = NULL;
slouken@1895
   921
    class.lpszClassName = SDL_Appname;
slouken@1895
   922
    class.hbrBackground = NULL;
slouken@1895
   923
    class.hInstance = SDL_Instance;
slouken@1895
   924
    class.style = SDL_Appstyle;
dewyatt@4733
   925
    class.lpfnWndProc = WIN_WindowProc;
slouken@1895
   926
    class.cbWndExtra = 0;
slouken@1895
   927
    class.cbClsExtra = 0;
slouken@1895
   928
    if (!RegisterClass(&class)) {
icculus@7037
   929
        return SDL_SetError("Couldn't register application class");
slouken@1895
   930
    }
slouken@1895
   931
slouken@1895
   932
    app_registered = 1;
icculus@7037
   933
    return 0;
slouken@1895
   934
}
slouken@1895
   935
slouken@1895
   936
/* Unregisters the windowclass registered in SDL_RegisterApp above. */
slouken@1895
   937
void
slouken@1895
   938
SDL_UnregisterApp()
slouken@1895
   939
{
slouken@1895
   940
    WNDCLASS class;
slouken@1895
   941
slouken@1895
   942
    /* SDL_RegisterApp might not have been called before */
slouken@1895
   943
    if (!app_registered) {
slouken@1895
   944
        return;
slouken@1895
   945
    }
slouken@1895
   946
    --app_registered;
slouken@1895
   947
    if (app_registered == 0) {
slouken@1895
   948
        /* Check for any registered window classes. */
slouken@1895
   949
        if (GetClassInfo(SDL_Instance, SDL_Appname, &class)) {
slouken@1895
   950
            UnregisterClass(SDL_Appname, SDL_Instance);
slouken@1895
   951
        }
slouken@1895
   952
        SDL_free(SDL_Appname);
slouken@1895
   953
        SDL_Appname = NULL;
slouken@1895
   954
    }
slouken@1895
   955
}
slouken@1895
   956
slouken@6044
   957
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
slouken@6044
   958
slouken@1895
   959
/* vi: set ts=4 sw=4 expandtab: */