src/video/windows/SDL_windowsevents.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 23 Dec 2013 17:37:22 -0800
changeset 8071 1ac2db4abe11
parent 8050 be19dbc5ff4e
child 8072 9d8865351afd
permissions -rw-r--r--
Added a relative mouse mode that uses mouse warping instead of raw input.
To enable this, set the environment variable SDL_MOUSE_RELATIVE_MODE_WARP to "1"

When mouse relative mode is disabled, put the cursor back where the application expects it to be, instead of where it was when relative mode was enabled.
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@8036
   289
static void
slouken@8036
   290
WIN_UpdateClipCursor(SDL_Window *window)
slouken@8036
   291
{
slouken@8036
   292
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@8071
   293
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@8036
   294
slouken@8036
   295
    /* Don't clip the cursor while we're in the modal resize or move loop */
slouken@8036
   296
    if (data->in_modal_loop) {
slouken@8036
   297
        ClipCursor(NULL);
slouken@8036
   298
        return;
slouken@8036
   299
    }
slouken@8036
   300
        
slouken@8071
   301
    if (mouse->relative_mode && !mouse->relative_mode_warp) {
slouken@8036
   302
        LONG cx, cy;
slouken@8036
   303
        RECT rect;
slouken@8036
   304
        GetWindowRect(data->hwnd, &rect);
slouken@8036
   305
slouken@8036
   306
        cx = (rect.left + rect.right) / 2;
slouken@8036
   307
        cy = (rect.top + rect.bottom) / 2;
slouken@8036
   308
slouken@8036
   309
        /* Make an absurdly small clip rect */
slouken@8036
   310
        rect.left = cx-1;
slouken@8036
   311
        rect.right = cx+1;
slouken@8036
   312
        rect.top = cy-1;
slouken@8036
   313
        rect.bottom = cy+1;
slouken@8036
   314
slouken@8036
   315
        ClipCursor(&rect);
slouken@8071
   316
    } else if (mouse->relative_mode_warp ||
slouken@8071
   317
               ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
slouken@8071
   318
                (window->flags & SDL_WINDOW_INPUT_FOCUS))) {
slouken@8036
   319
        RECT rect;
slouken@8036
   320
        if (GetClientRect(data->hwnd, &rect) && !IsRectEmpty(&rect)) {
slouken@8036
   321
            ClientToScreen(data->hwnd, (LPPOINT) & rect);
slouken@8036
   322
            ClientToScreen(data->hwnd, (LPPOINT) & rect + 1);
slouken@8036
   323
            ClipCursor(&rect);
slouken@8036
   324
        }
slouken@8036
   325
    } else {
slouken@8036
   326
        ClipCursor(NULL);
slouken@8036
   327
    }
slouken@8036
   328
}
slouken@8036
   329
slouken@1895
   330
LRESULT CALLBACK
slouken@1895
   331
WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
slouken@1895
   332
{
slouken@1895
   333
    SDL_WindowData *data;
slouken@3566
   334
    LRESULT returnCode = -1;
slouken@1895
   335
slouken@1951
   336
    /* Send a SDL_SYSWMEVENT if the application wants them */
slouken@4429
   337
    if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
slouken@1951
   338
        SDL_SysWMmsg wmmsg;
slouken@1951
   339
slouken@1951
   340
        SDL_VERSION(&wmmsg.version);
slouken@4900
   341
        wmmsg.subsystem = SDL_SYSWM_WINDOWS;
slouken@5056
   342
        wmmsg.msg.win.hwnd = hwnd;
slouken@5056
   343
        wmmsg.msg.win.msg = msg;
slouken@5056
   344
        wmmsg.msg.win.wParam = wParam;
slouken@5056
   345
        wmmsg.msg.win.lParam = lParam;
slouken@1951
   346
        SDL_SendSysWMEvent(&wmmsg);
slouken@1951
   347
    }
slouken@1951
   348
slouken@1895
   349
    /* Get the window data for the window */
slouken@1895
   350
    data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData"));
slouken@1895
   351
    if (!data) {
slouken@1895
   352
        return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
slouken@1895
   353
    }
jimtla@4650
   354
slouken@1895
   355
#ifdef WMMSG_DEBUG
slouken@7941
   356
    {
slouken@7941
   357
        char message[1024];
slouken@7941
   358
        if (msg > MAX_WMMSG) {
slouken@7941
   359
            SDL_snprintf(message, sizeof(message), "Received windows message: %p UNKNOWN (%d) -- 0x%X, 0x%X\n", hwnd, msg, wParam, lParam);
slouken@7941
   360
        } else {
slouken@7941
   361
            SDL_snprintf(message, sizeof(message), "Received windows message: %p %s -- 0x%X, 0x%X\n", hwnd, wmtab[msg], wParam, lParam);
slouken@7941
   362
        }
slouken@7941
   363
        OutputDebugStringA(message);
slouken@7941
   364
    }
slouken@7816
   365
#endif /* WMMSG_DEBUG */
slouken@2710
   366
dewyatt@4752
   367
    if (IME_HandleMessage(hwnd, msg, wParam, &lParam, data->videodata))
dewyatt@4752
   368
        return 0;
slouken@1895
   369
slouken@1895
   370
    switch (msg) {
slouken@1895
   371
slouken@1895
   372
    case WM_SHOWWINDOW:
slouken@1895
   373
        {
slouken@1895
   374
            if (wParam) {
slouken@3685
   375
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
slouken@1895
   376
            } else {
slouken@3685
   377
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
slouken@1895
   378
            }
slouken@1895
   379
        }
slouken@1895
   380
        break;
slouken@1895
   381
slouken@1895
   382
    case WM_ACTIVATE:
slouken@1895
   383
        {
slouken@1895
   384
            BOOL minimized;
slouken@1895
   385
slouken@1895
   386
            minimized = HIWORD(wParam);
slouken@1895
   387
            if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
slouken@7191
   388
                Uint32 mouseFlags;
slouken@7191
   389
                SHORT keyState;
slouken@6945
   390
slouken@3685
   391
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
slouken@4465
   392
                if (SDL_GetKeyboardFocus() != data->window) {
slouken@4465
   393
                    SDL_SetKeyboardFocus(data->window);
slouken@1895
   394
                }
slouken@7191
   395
                /* mouse buttons may have changed state here, we need
slouken@7191
   396
                to resync them, but we will get a WM_MOUSEMOVE right away which will fix
slouken@7191
   397
                things up if in non raw mode also
slouken@7191
   398
                */
slouken@7191
   399
                mouseFlags = SDL_GetMouseState( NULL, NULL );
slouken@6945
   400
slouken@7191
   401
                keyState = GetAsyncKeyState( VK_LBUTTON );
slouken@7191
   402
                WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT );
slouken@7191
   403
                keyState = GetAsyncKeyState( VK_RBUTTON );
slouken@7191
   404
                WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT );
slouken@7191
   405
                keyState = GetAsyncKeyState( VK_MBUTTON );
slouken@7191
   406
                WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE );
slouken@7191
   407
                keyState = GetAsyncKeyState( VK_XBUTTON1 );
slouken@7191
   408
                WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1 );
slouken@7191
   409
                keyState = GetAsyncKeyState( VK_XBUTTON2 );
slouken@7191
   410
                WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2 );
slouken@7191
   411
                data->mouse_button_flags = 0;
slouken@6350
   412
slouken@8036
   413
                WIN_UpdateClipCursor(data->window);
slouken@6350
   414
slouken@4504
   415
                /*
slouken@4504
   416
                 * FIXME: Update keyboard state
slouken@4504
   417
                 */
slouken@4504
   418
                WIN_CheckClipboardUpdate(data->videodata);
slouken@1895
   419
            } else {
slouken@4465
   420
                if (SDL_GetKeyboardFocus() == data->window) {
slouken@4465
   421
                    SDL_SetKeyboardFocus(NULL);
slouken@1895
   422
                }
slouken@8050
   423
slouken@8050
   424
                ClipCursor(NULL);
slouken@1895
   425
            }
slouken@1895
   426
        }
slouken@3566
   427
        returnCode = 0;
slouken@3566
   428
        break;
slouken@1895
   429
slouken@7191
   430
    case WM_MOUSEMOVE:
slouken@8071
   431
        {
slouken@8071
   432
            SDL_Mouse *mouse = SDL_GetMouse();
slouken@8071
   433
            if (!mouse->relative_mode || mouse->relative_mode_warp) {
slouken@8071
   434
                SDL_SendMouseMotion(data->window, 0, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
slouken@8071
   435
            }
slouken@8071
   436
        }
slouken@7191
   437
        /* don't break here, fall through to check the wParam like the button presses */
slouken@7191
   438
    case WM_LBUTTONUP:
slouken@7191
   439
    case WM_RBUTTONUP:
slouken@7191
   440
    case WM_MBUTTONUP:
slouken@7191
   441
    case WM_XBUTTONUP:
slouken@7191
   442
    case WM_LBUTTONDOWN:
slouken@7191
   443
    case WM_RBUTTONDOWN:
slouken@7191
   444
    case WM_MBUTTONDOWN:
slouken@7191
   445
    case WM_XBUTTONDOWN:
slouken@8071
   446
        {
slouken@8071
   447
            SDL_Mouse *mouse = SDL_GetMouse();
slouken@8071
   448
            if (!mouse->relative_mode || mouse->relative_mode_warp) {
slouken@8071
   449
                WIN_CheckWParamMouseButtons(wParam, data);
slouken@8071
   450
            }
slouken@8071
   451
        }
slouken@7191
   452
        break;
slouken@3139
   453
slouken@7191
   454
    case WM_INPUT:
slouken@8071
   455
        {
slouken@8071
   456
            SDL_Mouse *mouse = SDL_GetMouse();
slouken@8071
   457
            HRAWINPUT hRawInput = (HRAWINPUT)lParam;
slouken@8071
   458
            RAWINPUT inp;
slouken@8071
   459
            UINT size = sizeof(inp);
slouken@6782
   460
slouken@8071
   461
            if (!mouse->relative_mode || mouse->relative_mode_warp) {
slouken@8071
   462
                break;
slouken@8071
   463
            }
slouken@6782
   464
slouken@8071
   465
            GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER));
slouken@6350
   466
slouken@8071
   467
            /* Mouse data */
slouken@8071
   468
            if (inp.header.dwType == RIM_TYPEMOUSE) {
slouken@8071
   469
                RAWMOUSE* mouse = &inp.data.mouse;
slouken@6350
   470
slouken@8071
   471
                if ((mouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) {
slouken@8071
   472
                    SDL_SendMouseMotion(data->window, 0, 1, (int)mouse->lLastX, (int)mouse->lLastY);
slouken@8071
   473
                } else {
slouken@8071
   474
                    /* synthesize relative moves from the abs position */
slouken@8071
   475
                    static SDL_Point initialMousePoint;
slouken@8071
   476
                    if (initialMousePoint.x == 0 && initialMousePoint.y == 0) {
slouken@8071
   477
                        initialMousePoint.x = mouse->lLastX;
slouken@8071
   478
                        initialMousePoint.y = mouse->lLastY;
slouken@8071
   479
                    }
slouken@8071
   480
slouken@8071
   481
                    SDL_SendMouseMotion(data->window, 0, 1, (int)(mouse->lLastX-initialMousePoint.x), (int)(mouse->lLastY-initialMousePoint.y) );
slouken@8071
   482
slouken@7191
   483
                    initialMousePoint.x = mouse->lLastX;
slouken@7191
   484
                    initialMousePoint.y = mouse->lLastY;
slouken@7191
   485
                }
slouken@8071
   486
                WIN_CheckRawMouseButtons( mouse->usButtonFlags, data );
slouken@7191
   487
            }
slouken@7191
   488
        }
slouken@7191
   489
        break;
slouken@6350
   490
slouken@5049
   491
    case WM_MOUSEWHEEL:
slouken@5049
   492
        {
slouken@7813
   493
            static short s_AccumulatedMotion;
slouken@5049
   494
slouken@7813
   495
            s_AccumulatedMotion += GET_WHEEL_DELTA_WPARAM(wParam);
slouken@7813
   496
            if (s_AccumulatedMotion > 0) {
slouken@7813
   497
                while (s_AccumulatedMotion >= WHEEL_DELTA) {
slouken@7813
   498
                    SDL_SendMouseWheel(data->window, 0, 0, 1);
slouken@7813
   499
                    s_AccumulatedMotion -= WHEEL_DELTA;
slouken@7813
   500
                }
slouken@7813
   501
            } else {
slouken@7813
   502
                while (s_AccumulatedMotion <= -WHEEL_DELTA) {
slouken@7813
   503
                    SDL_SendMouseWheel(data->window, 0, 0, -1);
slouken@7813
   504
                    s_AccumulatedMotion += WHEEL_DELTA;
slouken@7813
   505
                }
slouken@7813
   506
            }
slouken@5049
   507
        }
slouken@8071
   508
        break;
slouken@5049
   509
slouken@7911
   510
    case WM_MOUSEHWHEEL:
slouken@7911
   511
        {
slouken@7911
   512
            static short s_AccumulatedMotion;
slouken@7911
   513
slouken@7911
   514
            s_AccumulatedMotion += GET_WHEEL_DELTA_WPARAM(wParam);
slouken@7911
   515
            if (s_AccumulatedMotion > 0) {
slouken@7911
   516
                while (s_AccumulatedMotion >= WHEEL_DELTA) {
slouken@7912
   517
                    SDL_SendMouseWheel(data->window, 0, 1, 0);
slouken@7911
   518
                    s_AccumulatedMotion -= WHEEL_DELTA;
slouken@7911
   519
                }
slouken@7911
   520
            } else {
slouken@7911
   521
                while (s_AccumulatedMotion <= -WHEEL_DELTA) {
slouken@7912
   522
                    SDL_SendMouseWheel(data->window, 0, -1, 0);
slouken@7911
   523
                    s_AccumulatedMotion += WHEEL_DELTA;
slouken@7911
   524
                }
slouken@7911
   525
            }
slouken@7911
   526
        }
slouken@8071
   527
        break;
slouken@7911
   528
slouken@5086
   529
#ifdef WM_MOUSELEAVE
slouken@1895
   530
    case WM_MOUSELEAVE:
jorgen@7275
   531
        if (SDL_GetMouseFocus() == data->window && !SDL_GetMouse()->relative_mode) {
slouken@8035
   532
            if (!IsIconic(hwnd)) {
slouken@8035
   533
                POINT cursorPos;
slouken@8035
   534
                GetCursorPos(&cursorPos);
slouken@8035
   535
                ScreenToClient(hwnd, &cursorPos);
slouken@8035
   536
                SDL_SendMouseMotion(data->window, 0, 0, cursorPos.x, cursorPos.y);
slouken@8035
   537
            }
slouken@7191
   538
            SDL_SetMouseFocus(NULL);
slouken@1895
   539
        }
slouken@3566
   540
        returnCode = 0;
slouken@3566
   541
        break;
slouken@5086
   542
#endif /* WM_MOUSELEAVE */
slouken@1895
   543
slouken@7645
   544
    case WM_KEYDOWN:
slouken@7646
   545
    case WM_SYSKEYDOWN:
slouken@7645
   546
        {
slouken@7646
   547
            SDL_Scancode code = WindowsScanCodeToSDLScanCode( lParam, wParam );
slouken@7646
   548
            if ( code != SDL_SCANCODE_UNKNOWN ) {
slouken@7646
   549
                SDL_SendKeyboardKey(SDL_PRESSED, code );
slouken@7646
   550
            }
slouken@7646
   551
        }
slouken@7646
   552
        if (msg == WM_KEYDOWN) {
slouken@7645
   553
            BYTE keyboardState[256];
slouken@7645
   554
            char text[5];
slouken@7645
   555
            UINT32 utf32 = 0;
slouken@7645
   556
slouken@7645
   557
            GetKeyboardState(keyboardState);
slouken@7645
   558
            if (ToUnicode(wParam, (lParam >> 16) & 0xff, keyboardState, (LPWSTR)&utf32, 1, 0) > 0) {
slouken@8071
   559
                WORD repetition;
slouken@8071
   560
                for (repetition = lParam & 0xffff; repetition > 0; repetition--) {
slouken@7645
   561
                    WIN_ConvertUTF32toUTF8(utf32, text);
slouken@7645
   562
                    SDL_SendKeyboardText(text);
slouken@7645
   563
                }
slouken@7645
   564
            }
slouken@7645
   565
        }
slouken@3566
   566
        returnCode = 0;
slouken@3566
   567
        break;
slouken@1895
   568
slouken@1895
   569
    case WM_SYSKEYUP:
slouken@1895
   570
    case WM_KEYUP:
slouken@1895
   571
        {
slouken@6938
   572
            SDL_Scancode code = WindowsScanCodeToSDLScanCode( lParam, wParam );
gabomdq@7975
   573
            const Uint8 *keyboardState = SDL_GetKeyboardState(NULL);
gabomdq@7975
   574
gabomdq@7975
   575
            /* Detect relevant keyboard shortcuts */
gabomdq@7975
   576
            if (keyboardState[SDL_SCANCODE_LALT] == SDL_PRESSED || keyboardState[SDL_SCANCODE_RALT] == SDL_PRESSED ) {
gabomdq@7975
   577
	            /* ALT+F4: Close window */
gabomdq@7975
   578
	            if (code == SDL_SCANCODE_F4) {
gabomdq@7975
   579
		            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
gabomdq@7975
   580
	            }
gabomdq@7975
   581
            }
gabomdq@7975
   582
slouken@6938
   583
            if ( code != SDL_SCANCODE_UNKNOWN ) {
slouken@6938
   584
                if (code == SDL_SCANCODE_PRINTSCREEN &&
gabomdq@7975
   585
                    keyboardState[code] == SDL_RELEASED) {
slouken@6938
   586
                    SDL_SendKeyboardKey(SDL_PRESSED, code);
slouken@6938
   587
                }
slouken@6938
   588
                SDL_SendKeyboardKey(SDL_RELEASED, code);
slouken@2308
   589
            }
slouken@1895
   590
        }
slouken@3566
   591
        returnCode = 0;
slouken@3566
   592
        break;
slouken@1895
   593
slouken@7645
   594
    case WM_UNICHAR:
slouken@7645
   595
        {
slouken@7645
   596
            if (wParam == UNICODE_NOCHAR) {
slouken@7645
   597
                returnCode = 1;
slouken@7645
   598
                break;
slouken@7645
   599
            }
slouken@7645
   600
        }
gabomdq@7663
   601
        /* no break */
slouken@2309
   602
    case WM_CHAR:
slouken@2309
   603
        {
slouken@7645
   604
            char text[5];
slouken@2309
   605
slouken@7645
   606
            WIN_ConvertUTF32toUTF8(wParam, text);
slouken@4465
   607
            SDL_SendKeyboardText(text);
slouken@2309
   608
        }
slouken@3566
   609
        returnCode = 0;
slouken@3566
   610
        break;
slouken@2309
   611
slouken@5086
   612
#ifdef WM_INPUTLANGCHANGE
slouken@2311
   613
    case WM_INPUTLANGCHANGE:
slouken@2311
   614
        {
slouken@4465
   615
            WIN_UpdateKeymap();
slouken@2311
   616
        }
slouken@3566
   617
        returnCode = 1;
slouken@3566
   618
        break;
slouken@5086
   619
#endif /* WM_INPUTLANGCHANGE */
slouken@2311
   620
slouken@8036
   621
    case WM_ENTERSIZEMOVE:
slouken@8036
   622
    case WM_ENTERMENULOOP:
slouken@8036
   623
        {
slouken@8036
   624
            data->in_modal_loop = SDL_TRUE;
slouken@8036
   625
            WIN_UpdateClipCursor(data->window);
slouken@8036
   626
        }
slouken@8036
   627
        break;
slouken@8036
   628
slouken@8036
   629
    case WM_EXITSIZEMOVE:
slouken@8036
   630
    case WM_EXITMENULOOP:
slouken@8036
   631
        {
slouken@8036
   632
            data->in_modal_loop = SDL_FALSE;
slouken@8036
   633
            WIN_UpdateClipCursor(data->window);
slouken@8036
   634
        }
slouken@8036
   635
        break;
slouken@8036
   636
slouken@5086
   637
#ifdef WM_GETMINMAXINFO
slouken@1895
   638
    case WM_GETMINMAXINFO:
slouken@1895
   639
        {
slouken@1895
   640
            MINMAXINFO *info;
slouken@1895
   641
            RECT size;
slouken@1895
   642
            int x, y;
slouken@1895
   643
            int w, h;
stopiccot@6682
   644
            int min_w, min_h;
slouken@6788
   645
            int max_w, max_h;
slouken@1895
   646
            int style;
slouken@3168
   647
            BOOL menu;
slouken@7191
   648
            BOOL constrain_max_size;
slouken@1895
   649
stopiccot@6682
   650
            if (SDL_IsShapedWindow(data->window))
eligottlieb@4815
   651
                Win32_ResizeWindowShape(data->window);
slouken@1895
   652
slouken@7941
   653
            /* If this is an expected size change, allow it */
slouken@7941
   654
            if (data->expected_resize) {
slouken@7941
   655
                break;
slouken@7941
   656
            }
slouken@7941
   657
slouken@1895
   658
            /* Get the current position of our window */
slouken@1895
   659
            GetWindowRect(hwnd, &size);
slouken@1895
   660
            x = size.left;
slouken@1895
   661
            y = size.top;
slouken@1895
   662
slouken@1895
   663
            /* Calculate current size of our window */
slouken@3685
   664
            SDL_GetWindowSize(data->window, &w, &h);
stopiccot@6682
   665
            SDL_GetWindowMinimumSize(data->window, &min_w, &min_h);
slouken@6788
   666
            SDL_GetWindowMaximumSize(data->window, &max_w, &max_h);
stopiccot@6682
   667
slouken@7191
   668
            /* Store in min_w and min_h difference between current size and minimal
stopiccot@6682
   669
               size so we don't need to call AdjustWindowRectEx twice */
stopiccot@6682
   670
            min_w -= w;
stopiccot@6682
   671
            min_h -= h;
slouken@6837
   672
            if (max_w && max_h) {
slouken@6837
   673
                max_w -= w;
slouken@6837
   674
                max_h -= h;
slouken@6862
   675
                constrain_max_size = TRUE;
slouken@6862
   676
            } else {
slouken@6862
   677
                constrain_max_size = FALSE;
slouken@6837
   678
            }
stopiccot@6682
   679
slouken@1895
   680
            size.top = 0;
slouken@1895
   681
            size.left = 0;
slouken@1895
   682
            size.bottom = h;
slouken@1895
   683
            size.right = w;
slouken@1895
   684
slouken@3168
   685
            style = GetWindowLong(hwnd, GWL_STYLE);
slouken@1895
   686
            /* DJM - according to the docs for GetMenu(), the
slouken@1895
   687
               return value is undefined if hwnd is a child window.
slouken@1895
   688
               Aparently it's too difficult for MS to check
slouken@1895
   689
               inside their function, so I have to do it here.
slouken@1895
   690
             */
slouken@3168
   691
            menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
slouken@3168
   692
            AdjustWindowRectEx(&size, style, menu, 0);
slouken@1895
   693
            w = size.right - size.left;
slouken@1895
   694
            h = size.bottom - size.top;
slouken@1895
   695
slouken@1895
   696
            /* Fix our size to the current size */
slouken@1895
   697
            info = (MINMAXINFO *) lParam;
stopiccot@6682
   698
            if (SDL_GetWindowFlags(data->window) & SDL_WINDOW_RESIZABLE) {
stopiccot@6682
   699
                info->ptMinTrackSize.x = w + min_w;
stopiccot@6682
   700
                info->ptMinTrackSize.y = h + min_h;
slouken@6862
   701
                if (constrain_max_size) {
slouken@6862
   702
                    info->ptMaxTrackSize.x = w + max_w;
slouken@6862
   703
                    info->ptMaxTrackSize.y = h + max_h;
slouken@6862
   704
                }
stopiccot@6682
   705
            } else {
stopiccot@6682
   706
                info->ptMaxSize.x = w;
stopiccot@6682
   707
                info->ptMaxSize.y = h;
stopiccot@6682
   708
                info->ptMaxPosition.x = x;
stopiccot@6682
   709
                info->ptMaxPosition.y = y;
stopiccot@6682
   710
                info->ptMinTrackSize.x = w;
stopiccot@6682
   711
                info->ptMinTrackSize.y = h;
stopiccot@6682
   712
                info->ptMaxTrackSize.x = w;
stopiccot@6682
   713
                info->ptMaxTrackSize.y = h;
stopiccot@6682
   714
            }
slouken@1895
   715
        }
slouken@3566
   716
        returnCode = 0;
slouken@3566
   717
        break;
slouken@5086
   718
#endif /* WM_GETMINMAXINFO */
slouken@1895
   719
slouken@1895
   720
    case WM_WINDOWPOSCHANGED:
slouken@1895
   721
        {
slouken@1895
   722
            RECT rect;
slouken@1895
   723
            int x, y;
slouken@1895
   724
            int w, h;
slouken@1895
   725
slouken@8036
   726
            if (!GetClientRect(hwnd, &rect) || IsRectEmpty(&rect)) {
slouken@3256
   727
                break;
slouken@3256
   728
            }
slouken@1895
   729
            ClientToScreen(hwnd, (LPPOINT) & rect);
slouken@1895
   730
            ClientToScreen(hwnd, (LPPOINT) & rect + 1);
slouken@1895
   731
slouken@8036
   732
            WIN_UpdateClipCursor(data->window);
slouken@1895
   733
slouken@1895
   734
            x = rect.left;
slouken@1895
   735
            y = rect.top;
slouken@3685
   736
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, x, y);
slouken@1895
   737
slouken@1895
   738
            w = rect.right - rect.left;
slouken@1895
   739
            h = rect.bottom - rect.top;
slouken@3685
   740
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, w,
slouken@1895
   741
                                h);
slouken@1895
   742
        }
slouken@1895
   743
        break;
slouken@1895
   744
slouken@7941
   745
    case WM_SIZE:
slouken@7941
   746
        {
slouken@7941
   747
            switch (wParam)
slouken@7941
   748
            {
slouken@7941
   749
            case SIZE_MAXIMIZED:
slouken@7941
   750
                SDL_SendWindowEvent(data->window,
slouken@7941
   751
                    SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
slouken@7941
   752
                break;
slouken@7941
   753
            case SIZE_MINIMIZED:
slouken@7941
   754
                SDL_SendWindowEvent(data->window,
slouken@7941
   755
                    SDL_WINDOWEVENT_MINIMIZED, 0, 0);
slouken@7941
   756
                break;
slouken@7941
   757
            default:
slouken@7941
   758
                SDL_SendWindowEvent(data->window,
slouken@7941
   759
                    SDL_WINDOWEVENT_RESTORED, 0, 0);
slouken@7941
   760
                break;
slouken@7941
   761
            }
slouken@7941
   762
        }
slouken@7941
   763
        break;
slouken@7941
   764
slouken@1895
   765
    case WM_SETCURSOR:
slouken@1895
   766
        {
slouken@3076
   767
            Uint16 hittest;
slouken@1895
   768
slouken@3076
   769
            hittest = LOWORD(lParam);
slouken@3076
   770
            if (hittest == HTCLIENT) {
slouken@5421
   771
                SetCursor(SDL_cursor);
slouken@3566
   772
                returnCode = TRUE;
slouken@3076
   773
            }
slouken@1895
   774
        }
slouken@1895
   775
        break;
slouken@1895
   776
slouken@1895
   777
        /* We were occluded, refresh our display */
slouken@1895
   778
    case WM_PAINT:
slouken@1895
   779
        {
slouken@1895
   780
            RECT rect;
slouken@1895
   781
            if (GetUpdateRect(hwnd, &rect, FALSE)) {
slouken@7295
   782
                ValidateRect(hwnd, NULL);
slouken@3685
   783
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED,
slouken@1895
   784
                                    0, 0);
slouken@1895
   785
            }
slouken@1895
   786
        }
slouken@3566
   787
        returnCode = 0;
slouken@3566
   788
        break;
slouken@3095
   789
slouken@1895
   790
        /* We'll do our own drawing, prevent flicker */
slouken@1895
   791
    case WM_ERASEBKGND:
slouken@1895
   792
        {
slouken@1895
   793
        }
slouken@1895
   794
        return (1);
slouken@1895
   795
slouken@5086
   796
#if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
slouken@1895
   797
    case WM_SYSCOMMAND:
slouken@1895
   798
        {
slouken@1895
   799
            /* Don't start the screensaver or blank the monitor in fullscreen apps */
slouken@1895
   800
            if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
slouken@1895
   801
                (wParam & 0xFFF0) == SC_MONITORPOWER) {
slouken@3032
   802
                if (SDL_GetVideoDevice()->suspend_screensaver) {
slouken@1895
   803
                    return (0);
slouken@1895
   804
                }
slouken@1895
   805
            }
slouken@1895
   806
        }
slouken@1895
   807
        break;
slouken@5086
   808
#endif /* System has screensaver support */
slouken@1895
   809
slouken@1895
   810
    case WM_CLOSE:
slouken@1895
   811
        {
slouken@3685
   812
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
slouken@1895
   813
        }
slouken@3566
   814
        returnCode = 0;
slouken@3566
   815
        break;
slouken@4919
   816
slouken@7191
   817
    case WM_TOUCH:
slouken@7191
   818
        {
slouken@7191
   819
            UINT i, num_inputs = LOWORD(wParam);
slouken@7191
   820
            PTOUCHINPUT inputs = SDL_stack_alloc(TOUCHINPUT, num_inputs);
slouken@7191
   821
            if (data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs, sizeof(TOUCHINPUT))) {
slouken@7191
   822
                RECT rect;
slouken@7191
   823
                float x, y;
slouken@4919
   824
slouken@7191
   825
                if (!GetClientRect(hwnd, &rect) ||
slouken@7191
   826
                    (rect.right == rect.left && rect.bottom == rect.top)) {
philipp@7631
   827
                    if (inputs) {
philipp@7631
   828
                        SDL_stack_free(inputs);
philipp@7631
   829
                    }
slouken@7191
   830
                    break;
slouken@7191
   831
                }
slouken@7191
   832
                ClientToScreen(hwnd, (LPPOINT) & rect);
slouken@7191
   833
                ClientToScreen(hwnd, (LPPOINT) & rect + 1);
slouken@7191
   834
                rect.top *= 100;
slouken@7191
   835
                rect.left *= 100;
slouken@7191
   836
                rect.bottom *= 100;
slouken@7191
   837
                rect.right *= 100;
slouken@4932
   838
slouken@7191
   839
                for (i = 0; i < num_inputs; ++i) {
slouken@7191
   840
                    PTOUCHINPUT input = &inputs[i];
slouken@4919
   841
icculus@7543
   842
                    const SDL_TouchID touchId = (SDL_TouchID)((size_t)input->hSource);
slouken@7191
   843
                    if (!SDL_GetTouch(touchId)) {
slouken@7191
   844
                        if (SDL_AddTouch(touchId, "") < 0) {
slouken@7191
   845
                            continue;
slouken@7191
   846
                        }
slouken@7191
   847
                    }
slouken@4932
   848
slouken@7191
   849
                    /* Get the normalized coordinates for the window */
slouken@7191
   850
                    x = (float)(input->x - rect.left)/(rect.right - rect.left);
slouken@7191
   851
                    y = (float)(input->y - rect.top)/(rect.bottom - rect.top);
slouken@4932
   852
slouken@7191
   853
                    if (input->dwFlags & TOUCHEVENTF_DOWN) {
slouken@7191
   854
                        SDL_SendTouch(touchId, input->dwID, SDL_TRUE, x, y, 1.0f);
slouken@7191
   855
                    }
slouken@7191
   856
                    if (input->dwFlags & TOUCHEVENTF_MOVE) {
slouken@7191
   857
                        SDL_SendTouchMotion(touchId, input->dwID, x, y, 1.0f);
slouken@7191
   858
                    }
slouken@7191
   859
                    if (input->dwFlags & TOUCHEVENTF_UP) {
slouken@7191
   860
                        SDL_SendTouch(touchId, input->dwID, SDL_FALSE, x, y, 1.0f);
slouken@7191
   861
                    }
slouken@7191
   862
                }
slouken@7191
   863
            }
slouken@7191
   864
            SDL_stack_free(inputs);
slouken@4932
   865
slouken@7191
   866
            data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
slouken@7191
   867
            return 0;
slouken@7191
   868
        }
slouken@7191
   869
        break;
slouken@6523
   870
slouken@6523
   871
    case WM_DROPFILES:
slouken@6523
   872
        {
slouken@6523
   873
            UINT i;
slouken@6523
   874
            HDROP drop = (HDROP) wParam;
slouken@6523
   875
            UINT count = DragQueryFile(drop, 0xFFFFFFFF, NULL, 0);
slouken@6523
   876
            for (i = 0; i < count; ++i) {
slouken@6523
   877
                UINT size = DragQueryFile(drop, i, NULL, 0) + 1;
slouken@6523
   878
                LPTSTR buffer = SDL_stack_alloc(TCHAR, size);
slouken@6523
   879
                if (buffer) {
slouken@6523
   880
                    if (DragQueryFile(drop, i, buffer, size)) {
slouken@6523
   881
                        char *file = WIN_StringToUTF8(buffer);
slouken@6523
   882
                        SDL_SendDropFile(file);
slouken@6523
   883
                        SDL_free(file);
slouken@6523
   884
                    }
slouken@6523
   885
                    SDL_stack_free(buffer);
slouken@6523
   886
                }
slouken@6523
   887
            }
slouken@6523
   888
            DragFinish(drop);
slouken@6523
   889
            return 0;
slouken@6523
   890
        }
slouken@6523
   891
        break;
slouken@6523
   892
    }
slouken@3566
   893
slouken@3566
   894
    /* If there's a window proc, assume it's going to handle messages */
slouken@3566
   895
    if (data->wndproc) {
slouken@3566
   896
        return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam);
slouken@3566
   897
    } else if (returnCode >= 0) {
slouken@3566
   898
        return returnCode;
slouken@3566
   899
    } else {
slouken@3566
   900
        return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
slouken@3566
   901
    }
slouken@1895
   902
}
slouken@1895
   903
slouken@1895
   904
void
slouken@1895
   905
WIN_PumpEvents(_THIS)
slouken@1895
   906
{
icculus@7561
   907
    const Uint8 *keystate;
slouken@1895
   908
    MSG msg;
slouken@1895
   909
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
slouken@1895
   910
        DispatchMessage(&msg);
slouken@1895
   911
    }
icculus@7561
   912
icculus@7561
   913
    /* Windows loses a shift KEYUP event when you have both pressed at once and let go of one.
icculus@7561
   914
       You won't get a KEYUP until both are released, and that keyup will only be for the second
icculus@7561
   915
       key you released. Take heroic measures and check the keystate as of the last handled event,
icculus@7561
   916
       and if we think a key is pressed when Windows doesn't, unstick it in SDL's state. */
icculus@7561
   917
    keystate = SDL_GetKeyboardState(NULL);
icculus@7561
   918
    if ((keystate[SDL_SCANCODE_LSHIFT] == SDL_PRESSED) && !(GetKeyState(VK_LSHIFT) & 0x8000)) {
icculus@7561
   919
        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
icculus@7561
   920
    }
icculus@7561
   921
    if ((keystate[SDL_SCANCODE_RSHIFT] == SDL_PRESSED) && !(GetKeyState(VK_RSHIFT) & 0x8000)) {
icculus@7561
   922
        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RSHIFT);
icculus@7561
   923
    }
slouken@1895
   924
}
slouken@1895
   925
slouken@1895
   926
static int app_registered = 0;
slouken@1895
   927
LPTSTR SDL_Appname = NULL;
slouken@1895
   928
Uint32 SDL_Appstyle = 0;
slouken@1895
   929
HINSTANCE SDL_Instance = NULL;
slouken@1895
   930
slouken@1895
   931
/* Register the class for this application */
slouken@1895
   932
int
slouken@1895
   933
SDL_RegisterApp(char *name, Uint32 style, void *hInst)
slouken@1895
   934
{
slouken@1895
   935
    WNDCLASS class;
slouken@1895
   936
slouken@1895
   937
    /* Only do this once... */
slouken@1895
   938
    if (app_registered) {
slouken@1895
   939
        ++app_registered;
slouken@1895
   940
        return (0);
slouken@1895
   941
    }
slouken@1895
   942
    if (!name && !SDL_Appname) {
slouken@1895
   943
        name = "SDL_app";
slouken@5086
   944
#if defined(CS_BYTEALIGNCLIENT) || defined(CS_OWNDC)
slouken@1895
   945
        SDL_Appstyle = (CS_BYTEALIGNCLIENT | CS_OWNDC);
slouken@5086
   946
#endif
slouken@1895
   947
        SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
slouken@1895
   948
    }
slouken@1895
   949
slouken@1895
   950
    if (name) {
slouken@1895
   951
        SDL_Appname = WIN_UTF8ToString(name);
slouken@1895
   952
        SDL_Appstyle = style;
slouken@1895
   953
        SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
slouken@1895
   954
    }
slouken@1895
   955
slouken@1895
   956
    /* Register the application class */
slouken@1895
   957
    class.hCursor = NULL;
slouken@2710
   958
    class.hIcon =
slouken@2710
   959
        LoadImage(SDL_Instance, SDL_Appname, IMAGE_ICON, 0, 0,
slouken@2710
   960
                  LR_DEFAULTCOLOR);
slouken@1895
   961
    class.lpszMenuName = NULL;
slouken@1895
   962
    class.lpszClassName = SDL_Appname;
slouken@1895
   963
    class.hbrBackground = NULL;
slouken@1895
   964
    class.hInstance = SDL_Instance;
slouken@1895
   965
    class.style = SDL_Appstyle;
dewyatt@4733
   966
    class.lpfnWndProc = WIN_WindowProc;
slouken@1895
   967
    class.cbWndExtra = 0;
slouken@1895
   968
    class.cbClsExtra = 0;
slouken@1895
   969
    if (!RegisterClass(&class)) {
icculus@7037
   970
        return SDL_SetError("Couldn't register application class");
slouken@1895
   971
    }
slouken@1895
   972
slouken@1895
   973
    app_registered = 1;
icculus@7037
   974
    return 0;
slouken@1895
   975
}
slouken@1895
   976
slouken@1895
   977
/* Unregisters the windowclass registered in SDL_RegisterApp above. */
slouken@1895
   978
void
slouken@1895
   979
SDL_UnregisterApp()
slouken@1895
   980
{
slouken@1895
   981
    WNDCLASS class;
slouken@1895
   982
slouken@1895
   983
    /* SDL_RegisterApp might not have been called before */
slouken@1895
   984
    if (!app_registered) {
slouken@1895
   985
        return;
slouken@1895
   986
    }
slouken@1895
   987
    --app_registered;
slouken@1895
   988
    if (app_registered == 0) {
slouken@1895
   989
        /* Check for any registered window classes. */
slouken@1895
   990
        if (GetClassInfo(SDL_Instance, SDL_Appname, &class)) {
slouken@1895
   991
            UnregisterClass(SDL_Appname, SDL_Instance);
slouken@1895
   992
        }
slouken@1895
   993
        SDL_free(SDL_Appname);
slouken@1895
   994
        SDL_Appname = NULL;
slouken@1895
   995
    }
slouken@1895
   996
}
slouken@1895
   997
slouken@6044
   998
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
slouken@6044
   999
slouken@1895
  1000
/* vi: set ts=4 sw=4 expandtab: */