src/video/windows/SDL_windowsevents.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 03 Jul 2012 23:52:02 -0400
changeset 6350 19545983ac76
parent 6138 4c64952a58fb
child 6430 48d519500f7e
permissions -rwxr-xr-x
Patrick Baggett implemented relative mouse mode on Win32

Here is my first rough attempt. "testrelative" feels right to me, but I'd like it someone else tested this, especially compared to Linux/OSX. The "Ctrl+r" to switch between relative and normal mouse movements seems to work flawlessly. With relative mouse movement, the only way to change focus is via keyboard. I'm not sure if that is the correct approach, but that would seem to be the most useful mode for games. Still, if my assumption is wrong, I can fix that no problem.
slouken@1895
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6138
     3
  Copyright (C) 1997-2012 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@1895
    31
jimtla@4650
    32
jimtla@4650
    33
slouken@4868
    34
/*#define WMMSG_DEBUG*/
slouken@1895
    35
#ifdef WMMSG_DEBUG
jimtla@4650
    36
#include <stdio.h>	
slouken@1895
    37
#include "wmmsg.h"
slouken@1895
    38
#endif
slouken@1895
    39
slouken@1895
    40
/* Masks for processing the windows KEYDOWN and KEYUP messages */
slouken@2317
    41
#define REPEATED_KEYMASK    (1<<30)
slouken@2317
    42
#define EXTENDED_KEYMASK    (1<<24)
slouken@1895
    43
bob@2324
    44
#define VK_ENTER    10          /* Keypad Enter ... no VKEY defined? */
slouken@2313
    45
icculus@2127
    46
/* Make sure XBUTTON stuff is defined that isn't in older Platform SDKs... */
icculus@2127
    47
#ifndef WM_XBUTTONDOWN
icculus@2127
    48
#define WM_XBUTTONDOWN 0x020B
icculus@2127
    49
#endif
icculus@2127
    50
#ifndef WM_XBUTTONUP
icculus@2127
    51
#define WM_XBUTTONUP 0x020C
icculus@2127
    52
#endif
icculus@2127
    53
#ifndef GET_XBUTTON_WPARAM
icculus@2127
    54
#define GET_XBUTTON_WPARAM(w) (HIWORD(w))
icculus@2127
    55
#endif
bobbens@2733
    56
#ifndef WM_INPUT
bobbens@2733
    57
#define WM_INPUT 0x00ff
bobbens@2733
    58
#endif
slouken@4932
    59
#ifndef WM_TOUCH
slouken@4868
    60
#define WM_TOUCH 0x0240
slouken@4932
    61
#endif
slouken@4919
    62
slouken@1895
    63
slouken@2310
    64
static WPARAM
slouken@2310
    65
RemapVKEY(WPARAM wParam, LPARAM lParam)
slouken@2310
    66
{
slouken@2317
    67
    int i;
bob@2324
    68
    BYTE scancode = (BYTE) ((lParam >> 16) & 0xFF);
slouken@2317
    69
slouken@2310
    70
    /* Windows remaps alphabetic keys based on current layout.
slouken@2310
    71
       We try to provide USB scancodes, so undo this mapping.
slouken@2310
    72
     */
slouken@2310
    73
    if (wParam >= 'A' && wParam <= 'Z') {
slouken@2311
    74
        if (scancode != alpha_scancodes[wParam - 'A']) {
slouken@2311
    75
            for (i = 0; i < SDL_arraysize(alpha_scancodes); ++i) {
slouken@2311
    76
                if (scancode == alpha_scancodes[i]) {
slouken@2310
    77
                    wParam = 'A' + i;
slouken@2310
    78
                    break;
slouken@2310
    79
                }
slouken@2310
    80
            }
slouken@2310
    81
        }
slouken@2310
    82
    }
slouken@2317
    83
slouken@3700
    84
    /* Keypad keys are a little trickier, we always scan for them.
slouken@3700
    85
       Keypad arrow keys have the same scancode as normal arrow keys,
slouken@3700
    86
       except they don't have the extended bit (0x1000000) set.
slouken@3700
    87
     */
slouken@3700
    88
    if (!(lParam & 0x1000000)) {
slouken@4561
    89
        if (wParam == VK_DELETE) {
slouken@4561
    90
            wParam = VK_DECIMAL;
slouken@4561
    91
        } else {
slouken@4561
    92
            for (i = 0; i < SDL_arraysize(keypad_scancodes); ++i) {
slouken@4561
    93
                if (scancode == keypad_scancodes[i]) {
slouken@4561
    94
                    wParam = VK_NUMPAD0 + i;
slouken@4561
    95
                    break;
slouken@4561
    96
                }
slouken@3700
    97
            }
slouken@2317
    98
        }
slouken@2317
    99
    }
slouken@2317
   100
slouken@2310
   101
    return wParam;
slouken@2310
   102
}
slouken@2310
   103
slouken@1895
   104
LRESULT CALLBACK
slouken@1895
   105
WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
slouken@1895
   106
{
slouken@1895
   107
    SDL_WindowData *data;
slouken@3566
   108
    LRESULT returnCode = -1;
slouken@1895
   109
slouken@1951
   110
    /* Send a SDL_SYSWMEVENT if the application wants them */
slouken@4429
   111
    if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
slouken@1951
   112
        SDL_SysWMmsg wmmsg;
slouken@1951
   113
slouken@1951
   114
        SDL_VERSION(&wmmsg.version);
slouken@4900
   115
        wmmsg.subsystem = SDL_SYSWM_WINDOWS;
slouken@5056
   116
        wmmsg.msg.win.hwnd = hwnd;
slouken@5056
   117
        wmmsg.msg.win.msg = msg;
slouken@5056
   118
        wmmsg.msg.win.wParam = wParam;
slouken@5056
   119
        wmmsg.msg.win.lParam = lParam;
slouken@1951
   120
        SDL_SendSysWMEvent(&wmmsg);
slouken@1951
   121
    }
slouken@1951
   122
slouken@1895
   123
    /* Get the window data for the window */
slouken@1895
   124
    data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData"));
slouken@1895
   125
    if (!data) {
slouken@1895
   126
        return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
slouken@1895
   127
    }
jimtla@4650
   128
slouken@1895
   129
#ifdef WMMSG_DEBUG
jimtla@4650
   130
    {		
jimtla@4650
   131
        FILE *log = fopen("wmmsg.txt", "a");		
slouken@1913
   132
        fprintf(log, "Received windows message: %p ", hwnd);
slouken@1913
   133
        if (msg > MAX_WMMSG) {
slouken@1913
   134
            fprintf(log, "%d", msg);
slouken@1913
   135
        } else {
slouken@1913
   136
            fprintf(log, "%s", wmtab[msg]);
slouken@1913
   137
        }
slouken@1913
   138
        fprintf(log, " -- 0x%X, 0x%X\n", wParam, lParam);
slouken@1913
   139
        fclose(log);
slouken@1895
   140
    }
slouken@4868
   141
#endif
slouken@2710
   142
dewyatt@4752
   143
    if (IME_HandleMessage(hwnd, msg, wParam, &lParam, data->videodata))
dewyatt@4752
   144
        return 0;
slouken@1895
   145
slouken@1895
   146
    switch (msg) {
slouken@1895
   147
slouken@1895
   148
    case WM_SHOWWINDOW:
slouken@1895
   149
        {
slouken@1895
   150
            if (wParam) {
slouken@3685
   151
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
slouken@1895
   152
            } else {
slouken@3685
   153
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
slouken@1895
   154
            }
slouken@1895
   155
        }
slouken@1895
   156
        break;
slouken@1895
   157
slouken@1895
   158
    case WM_ACTIVATE:
slouken@1895
   159
        {
slouken@1895
   160
            BOOL minimized;
slouken@1895
   161
slouken@1895
   162
            minimized = HIWORD(wParam);
slouken@1895
   163
            if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
slouken@3685
   164
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
slouken@3685
   165
                SDL_SendWindowEvent(data->window,
slouken@1895
   166
                                    SDL_WINDOWEVENT_RESTORED, 0, 0);
slouken@3139
   167
#ifndef _WIN32_WCE              /* WinCE misses IsZoomed() */
slouken@1895
   168
                if (IsZoomed(hwnd)) {
slouken@3685
   169
                    SDL_SendWindowEvent(data->window,
slouken@1895
   170
                                        SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
slouken@1895
   171
                }
slouken@3139
   172
#endif
slouken@4465
   173
                if (SDL_GetKeyboardFocus() != data->window) {
slouken@4465
   174
                    SDL_SetKeyboardFocus(data->window);
slouken@1895
   175
                }
slouken@6350
   176
slouken@6350
   177
				if(SDL_GetMouse()->relative_mode) {
slouken@6350
   178
					LONG cx, cy;
slouken@6350
   179
					RECT rect;
slouken@6350
   180
					GetWindowRect(hwnd, &rect);
slouken@6350
   181
slouken@6350
   182
					cx = (rect.left + rect.right) / 2;
slouken@6350
   183
					cy = (rect.top + rect.bottom) / 2;
slouken@6350
   184
slouken@6350
   185
					/* Make an absurdly small clip rect */
slouken@6350
   186
					rect.left = cx-1;
slouken@6350
   187
					rect.right = cx+1;
slouken@6350
   188
					rect.top = cy-1;
slouken@6350
   189
					rect.bottom = cy+1;
slouken@6350
   190
slouken@6350
   191
					ClipCursor(&rect);
slouken@6350
   192
				}
slouken@6350
   193
slouken@4504
   194
                /*
slouken@4504
   195
                 * FIXME: Update keyboard state
slouken@4504
   196
                 */
slouken@4504
   197
                WIN_CheckClipboardUpdate(data->videodata);
slouken@1895
   198
            } else {
slouken@4465
   199
                if (SDL_GetKeyboardFocus() == data->window) {
slouken@4465
   200
                    SDL_SetKeyboardFocus(NULL);
slouken@1895
   201
                }
slouken@1895
   202
                if (minimized) {
slouken@3685
   203
                    SDL_SendWindowEvent(data->window,
slouken@1895
   204
                                        SDL_WINDOWEVENT_MINIMIZED, 0, 0);
slouken@1895
   205
                }
slouken@1895
   206
            }
slouken@1895
   207
        }
slouken@3566
   208
        returnCode = 0;
slouken@3566
   209
        break;
slouken@1895
   210
slouken@4470
   211
	case WM_MOUSEMOVE:
slouken@6350
   212
		if(SDL_GetMouse()->relative_mode)
slouken@6350
   213
			break;
slouken@3097
   214
#ifdef _WIN32_WCE
slouken@5086
   215
        /* transform coords for VGA, WVGA... */
slouken@5086
   216
        {
slouken@5086
   217
            SDL_VideoData *videodata = data->videodata;
slouken@5139
   218
            if(videodata->CoordTransform) {
slouken@5086
   219
                POINT pt;
slouken@5086
   220
                pt.x = LOWORD(lParam);
slouken@5086
   221
                pt.y = HIWORD(lParam);
slouken@5086
   222
                videodata->CoordTransform(data->window, &pt);
slouken@5139
   223
                SDL_SendMouseMotion(data->window, 0, pt.x, pt.y);
slouken@5086
   224
                break;
slouken@5086
   225
            }
slouken@5086
   226
        }
slouken@4569
   227
#endif
slouken@4484
   228
        SDL_SendMouseMotion(data->window, 0, LOWORD(lParam), HIWORD(lParam));
slouken@3139
   229
        break;
slouken@3139
   230
slouken@6350
   231
	case WM_INPUT:
slouken@6350
   232
	{
slouken@6350
   233
		HRAWINPUT hRawInput = (HRAWINPUT)lParam;
slouken@6350
   234
		RAWINPUT inp;
slouken@6350
   235
		UINT size = sizeof(inp);
slouken@6350
   236
		GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER));
slouken@6350
   237
slouken@6350
   238
		/* Mouse data */
slouken@6350
   239
		if(inp.header.dwType == RIM_TYPEMOUSE)
slouken@6350
   240
		{
slouken@6350
   241
			RAWMOUSE* mouse = &inp.data.mouse;
slouken@6350
   242
slouken@6350
   243
			if((mouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE)
slouken@6350
   244
				SDL_SendMouseMotion(data->window, 1, (int)mouse->lLastX, (int)mouse->lLastY);
slouken@6350
   245
slouken@6350
   246
		}
slouken@6350
   247
		break;
slouken@6350
   248
	}
slouken@6350
   249
slouken@3097
   250
    case WM_LBUTTONDOWN:
slouken@4484
   251
        SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_LEFT);
slouken@3139
   252
        break;
slouken@3139
   253
slouken@3097
   254
    case WM_LBUTTONUP:
slouken@4484
   255
        SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_LEFT);
slouken@3139
   256
        break;
slouken@3139
   257
slouken@5049
   258
    case WM_RBUTTONDOWN:
slouken@5049
   259
        SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_RIGHT);
slouken@5049
   260
        break;
slouken@5049
   261
slouken@5049
   262
    case WM_RBUTTONUP:
slouken@5049
   263
        SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_RIGHT);
slouken@5049
   264
        break;
slouken@5049
   265
slouken@5049
   266
    case WM_MBUTTONDOWN:
slouken@5049
   267
        SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_MIDDLE);
slouken@5049
   268
        break;
slouken@5049
   269
slouken@5049
   270
    case WM_MBUTTONUP:
slouken@5049
   271
        SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_MIDDLE);
slouken@5049
   272
        break;
slouken@5049
   273
slouken@5049
   274
    case WM_XBUTTONDOWN:
slouken@5049
   275
        SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_X1 + GET_XBUTTON_WPARAM(wParam) - 1);
slouken@5049
   276
        returnCode = TRUE;
slouken@5049
   277
        break;
slouken@5049
   278
slouken@5049
   279
    case WM_XBUTTONUP:
slouken@5049
   280
        SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_X1 + GET_XBUTTON_WPARAM(wParam) - 1);
slouken@5049
   281
        returnCode = TRUE;
slouken@5049
   282
        break;
slouken@5049
   283
slouken@5049
   284
    case WM_MOUSEWHEEL:
slouken@5049
   285
        {
slouken@5049
   286
            int motion = (short) HIWORD(wParam);
slouken@5049
   287
slouken@5049
   288
            SDL_SendMouseWheel(data->window, 0, motion);
slouken@5049
   289
            break;
slouken@5049
   290
        }
slouken@5049
   291
slouken@5086
   292
#ifdef WM_MOUSELEAVE
slouken@5086
   293
    /* FIXME: Do we need the SDL 1.2 hack to generate WM_MOUSELEAVE now? */
slouken@1895
   294
    case WM_MOUSELEAVE:
slouken@4470
   295
        if (SDL_GetMouseFocus() == data->window) {
slouken@4470
   296
            SDL_SetMouseFocus(NULL);
slouken@1895
   297
        }
slouken@3566
   298
        returnCode = 0;
slouken@3566
   299
        break;
slouken@5086
   300
#endif /* WM_MOUSELEAVE */
slouken@1895
   301
slouken@1895
   302
    case WM_SYSKEYDOWN:
slouken@1895
   303
    case WM_KEYDOWN:
slouken@1895
   304
        {
slouken@2310
   305
            wParam = RemapVKEY(wParam, lParam);
slouken@1895
   306
            switch (wParam) {
slouken@1895
   307
            case VK_CONTROL:
slouken@1895
   308
                if (lParam & EXTENDED_KEYMASK)
slouken@1895
   309
                    wParam = VK_RCONTROL;
slouken@1895
   310
                else
slouken@1895
   311
                    wParam = VK_LCONTROL;
slouken@1895
   312
                break;
slouken@1895
   313
            case VK_SHIFT:
slouken@1895
   314
                /* EXTENDED trick doesn't work here */
slouken@1895
   315
                {
slouken@2308
   316
                    Uint8 *state = SDL_GetKeyboardState(NULL);
slouken@2308
   317
                    if (state[SDL_SCANCODE_LSHIFT] == SDL_RELEASED
slouken@1895
   318
                        && (GetKeyState(VK_LSHIFT) & 0x8000)) {
slouken@1895
   319
                        wParam = VK_LSHIFT;
slouken@2308
   320
                    } else if (state[SDL_SCANCODE_RSHIFT] == SDL_RELEASED
slouken@1895
   321
                               && (GetKeyState(VK_RSHIFT) & 0x8000)) {
slouken@1895
   322
                        wParam = VK_RSHIFT;
slouken@1895
   323
                    } else {
slouken@1895
   324
                        /* Probably a key repeat */
slouken@3566
   325
                        wParam = 256;
slouken@1895
   326
                    }
slouken@1895
   327
                }
slouken@1895
   328
                break;
slouken@1895
   329
            case VK_MENU:
slouken@1895
   330
                if (lParam & EXTENDED_KEYMASK)
slouken@1895
   331
                    wParam = VK_RMENU;
slouken@1895
   332
                else
slouken@1895
   333
                    wParam = VK_LMENU;
slouken@1895
   334
                break;
slouken@2313
   335
            case VK_RETURN:
slouken@2313
   336
                if (lParam & EXTENDED_KEYMASK)
slouken@2313
   337
                    wParam = VK_ENTER;
slouken@2313
   338
                break;
slouken@1895
   339
            }
slouken@2308
   340
            if (wParam < 256) {
slouken@4465
   341
                SDL_SendKeyboardKey(SDL_PRESSED,
slouken@2308
   342
                                    data->videodata->key_layout[wParam]);
slouken@2308
   343
            }
slouken@1895
   344
        }
slouken@3566
   345
        returnCode = 0;
slouken@3566
   346
        break;
slouken@1895
   347
slouken@1895
   348
    case WM_SYSKEYUP:
slouken@1895
   349
    case WM_KEYUP:
slouken@1895
   350
        {
slouken@2310
   351
            wParam = RemapVKEY(wParam, lParam);
slouken@1895
   352
            switch (wParam) {
slouken@1895
   353
            case VK_CONTROL:
slouken@1895
   354
                if (lParam & EXTENDED_KEYMASK)
slouken@1895
   355
                    wParam = VK_RCONTROL;
slouken@1895
   356
                else
slouken@1895
   357
                    wParam = VK_LCONTROL;
slouken@1895
   358
                break;
slouken@1895
   359
            case VK_SHIFT:
slouken@1895
   360
                /* EXTENDED trick doesn't work here */
slouken@1895
   361
                {
slouken@2308
   362
                    Uint8 *state = SDL_GetKeyboardState(NULL);
slouken@2308
   363
                    if (state[SDL_SCANCODE_LSHIFT] == SDL_PRESSED
slouken@1895
   364
                        && !(GetKeyState(VK_LSHIFT) & 0x8000)) {
slouken@1895
   365
                        wParam = VK_LSHIFT;
slouken@2308
   366
                    } else if (state[SDL_SCANCODE_RSHIFT] == SDL_PRESSED
slouken@1895
   367
                               && !(GetKeyState(VK_RSHIFT) & 0x8000)) {
slouken@1895
   368
                        wParam = VK_RSHIFT;
slouken@1895
   369
                    } else {
slouken@1895
   370
                        /* Probably a key repeat */
slouken@3566
   371
                        wParam = 256;
slouken@1895
   372
                    }
slouken@1895
   373
                }
slouken@1895
   374
                break;
slouken@1895
   375
            case VK_MENU:
slouken@1895
   376
                if (lParam & EXTENDED_KEYMASK)
slouken@1895
   377
                    wParam = VK_RMENU;
slouken@1895
   378
                else
slouken@1895
   379
                    wParam = VK_LMENU;
slouken@1895
   380
                break;
slouken@2313
   381
            case VK_RETURN:
slouken@2313
   382
                if (lParam & EXTENDED_KEYMASK)
slouken@2313
   383
                    wParam = VK_ENTER;
slouken@2313
   384
                break;
slouken@1895
   385
            }
slouken@2710
   386
slouken@1895
   387
            /* Windows only reports keyup for print screen */
slouken@1895
   388
            if (wParam == VK_SNAPSHOT
slouken@2308
   389
                && SDL_GetKeyboardState(NULL)[SDL_SCANCODE_PRINTSCREEN] ==
slouken@2308
   390
                SDL_RELEASED) {
slouken@4465
   391
                SDL_SendKeyboardKey(SDL_PRESSED,
slouken@2308
   392
                                    data->videodata->key_layout[wParam]);
slouken@1895
   393
            }
slouken@2308
   394
            if (wParam < 256) {
slouken@4465
   395
                SDL_SendKeyboardKey(SDL_RELEASED,
slouken@2308
   396
                                    data->videodata->key_layout[wParam]);
slouken@2308
   397
            }
slouken@1895
   398
        }
slouken@3566
   399
        returnCode = 0;
slouken@3566
   400
        break;
slouken@1895
   401
slouken@2309
   402
    case WM_CHAR:
slouken@2309
   403
        {
slouken@2309
   404
            char text[4];
slouken@2309
   405
slouken@2309
   406
            /* Convert to UTF-8 and send it on... */
slouken@2309
   407
            if (wParam <= 0x7F) {
slouken@2309
   408
                text[0] = (char) wParam;
slouken@2309
   409
                text[1] = '\0';
slouken@2309
   410
            } else if (wParam <= 0x7FF) {
slouken@2309
   411
                text[0] = 0xC0 | (char) ((wParam >> 6) & 0x1F);
slouken@2309
   412
                text[1] = 0x80 | (char) (wParam & 0x3F);
slouken@2309
   413
                text[2] = '\0';
slouken@2309
   414
            } else {
slouken@2309
   415
                text[0] = 0xE0 | (char) ((wParam >> 12) & 0x0F);
slouken@2309
   416
                text[1] = 0x80 | (char) ((wParam >> 6) & 0x3F);
slouken@2309
   417
                text[2] = 0x80 | (char) (wParam & 0x3F);
slouken@2309
   418
                text[3] = '\0';
slouken@2309
   419
            }
slouken@4465
   420
            SDL_SendKeyboardText(text);
slouken@2309
   421
        }
slouken@3566
   422
        returnCode = 0;
slouken@3566
   423
        break;
slouken@2309
   424
slouken@5086
   425
#ifdef WM_INPUTLANGCHANGE
slouken@2311
   426
    case WM_INPUTLANGCHANGE:
slouken@2311
   427
        {
slouken@4465
   428
            WIN_UpdateKeymap();
slouken@2311
   429
        }
slouken@3566
   430
        returnCode = 1;
slouken@3566
   431
        break;
slouken@5086
   432
#endif /* WM_INPUTLANGCHANGE */
slouken@2311
   433
slouken@5086
   434
#ifdef WM_GETMINMAXINFO
slouken@1895
   435
    case WM_GETMINMAXINFO:
slouken@1895
   436
        {
slouken@1895
   437
            MINMAXINFO *info;
slouken@1895
   438
            RECT size;
slouken@1895
   439
            int x, y;
slouken@1895
   440
            int w, h;
slouken@1895
   441
            int style;
slouken@3168
   442
            BOOL menu;
slouken@1895
   443
slouken@1895
   444
            /* If we allow resizing, let the resize happen naturally */
eligottlieb@4788
   445
            if(SDL_IsShapedWindow(data->window))
eligottlieb@4815
   446
                Win32_ResizeWindowShape(data->window);
slouken@3685
   447
            if (SDL_GetWindowFlags(data->window) & SDL_WINDOW_RESIZABLE) {
slouken@3566
   448
                returnCode = 0;
slouken@3566
   449
                break;
slouken@1895
   450
            }
slouken@1895
   451
slouken@1895
   452
            /* Get the current position of our window */
slouken@1895
   453
            GetWindowRect(hwnd, &size);
slouken@1895
   454
            x = size.left;
slouken@1895
   455
            y = size.top;
slouken@1895
   456
slouken@1895
   457
            /* Calculate current size of our window */
slouken@3685
   458
            SDL_GetWindowSize(data->window, &w, &h);
slouken@1895
   459
            size.top = 0;
slouken@1895
   460
            size.left = 0;
slouken@1895
   461
            size.bottom = h;
slouken@1895
   462
            size.right = w;
slouken@1895
   463
slouken@3168
   464
slouken@3168
   465
            style = GetWindowLong(hwnd, GWL_STYLE);
slouken@3168
   466
#ifdef _WIN32_WCE
slouken@3168
   467
            menu = FALSE;
slouken@3168
   468
#else
slouken@1895
   469
            /* DJM - according to the docs for GetMenu(), the
slouken@1895
   470
               return value is undefined if hwnd is a child window.
slouken@1895
   471
               Aparently it's too difficult for MS to check
slouken@1895
   472
               inside their function, so I have to do it here.
slouken@1895
   473
             */
slouken@3168
   474
            menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
slouken@3168
   475
#endif
slouken@3168
   476
            AdjustWindowRectEx(&size, style, menu, 0);
slouken@1895
   477
            w = size.right - size.left;
slouken@1895
   478
            h = size.bottom - size.top;
slouken@1895
   479
slouken@1895
   480
            /* Fix our size to the current size */
slouken@1895
   481
            info = (MINMAXINFO *) lParam;
slouken@1895
   482
            info->ptMaxSize.x = w;
slouken@1895
   483
            info->ptMaxSize.y = h;
slouken@1895
   484
            info->ptMaxPosition.x = x;
slouken@1895
   485
            info->ptMaxPosition.y = y;
slouken@1895
   486
            info->ptMinTrackSize.x = w;
slouken@1895
   487
            info->ptMinTrackSize.y = h;
slouken@1895
   488
            info->ptMaxTrackSize.x = w;
slouken@1895
   489
            info->ptMaxTrackSize.y = h;
slouken@1895
   490
        }
slouken@3566
   491
        returnCode = 0;
slouken@3566
   492
        break;
slouken@5086
   493
#endif /* WM_GETMINMAXINFO */
slouken@1895
   494
slouken@1895
   495
    case WM_WINDOWPOSCHANGED:
slouken@1895
   496
        {
slouken@1895
   497
            RECT rect;
slouken@1895
   498
            int x, y;
slouken@1895
   499
            int w, h;
slouken@1895
   500
            Uint32 window_flags;
slouken@1895
   501
slouken@3256
   502
            if (!GetClientRect(hwnd, &rect) ||
slouken@3256
   503
                (rect.right == rect.left && rect.bottom == rect.top)) {
slouken@3256
   504
                break;
slouken@3256
   505
            }
slouken@1895
   506
            ClientToScreen(hwnd, (LPPOINT) & rect);
slouken@1895
   507
            ClientToScreen(hwnd, (LPPOINT) & rect + 1);
slouken@1895
   508
slouken@3685
   509
            window_flags = SDL_GetWindowFlags(data->window);
slouken@1895
   510
            if ((window_flags & SDL_WINDOW_INPUT_GRABBED) &&
slouken@1895
   511
                (window_flags & SDL_WINDOW_INPUT_FOCUS)) {
slouken@1895
   512
                ClipCursor(&rect);
slouken@1895
   513
            }
slouken@1895
   514
slouken@1895
   515
            x = rect.left;
slouken@1895
   516
            y = rect.top;
slouken@3685
   517
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, x, y);
slouken@1895
   518
slouken@1895
   519
            w = rect.right - rect.left;
slouken@1895
   520
            h = rect.bottom - rect.top;
slouken@3685
   521
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, w,
slouken@1895
   522
                                h);
slouken@1895
   523
        }
slouken@1895
   524
        break;
slouken@1895
   525
slouken@1895
   526
    case WM_SETCURSOR:
slouken@1895
   527
        {
slouken@3076
   528
            Uint16 hittest;
slouken@1895
   529
slouken@3076
   530
            hittest = LOWORD(lParam);
slouken@3076
   531
            if (hittest == HTCLIENT) {
slouken@5421
   532
                SetCursor(SDL_cursor);
slouken@3566
   533
                returnCode = TRUE;
slouken@3076
   534
            }
slouken@1895
   535
        }
slouken@1895
   536
        break;
slouken@1895
   537
slouken@1895
   538
        /* We were occluded, refresh our display */
slouken@1895
   539
    case WM_PAINT:
slouken@1895
   540
        {
slouken@1895
   541
            RECT rect;
slouken@1895
   542
            if (GetUpdateRect(hwnd, &rect, FALSE)) {
slouken@1895
   543
                ValidateRect(hwnd, &rect);
slouken@3685
   544
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED,
slouken@1895
   545
                                    0, 0);
slouken@1895
   546
            }
slouken@1895
   547
        }
slouken@3566
   548
        returnCode = 0;
slouken@3566
   549
        break;
slouken@3095
   550
slouken@1895
   551
        /* We'll do our own drawing, prevent flicker */
slouken@1895
   552
    case WM_ERASEBKGND:
slouken@1895
   553
        {
slouken@1895
   554
        }
slouken@1895
   555
        return (1);
slouken@1895
   556
slouken@5086
   557
#if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
slouken@1895
   558
    case WM_SYSCOMMAND:
slouken@1895
   559
        {
slouken@1895
   560
            /* Don't start the screensaver or blank the monitor in fullscreen apps */
slouken@1895
   561
            if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
slouken@1895
   562
                (wParam & 0xFFF0) == SC_MONITORPOWER) {
slouken@3032
   563
                if (SDL_GetVideoDevice()->suspend_screensaver) {
slouken@1895
   564
                    return (0);
slouken@1895
   565
                }
slouken@1895
   566
            }
slouken@1895
   567
        }
slouken@1895
   568
        break;
slouken@5086
   569
#endif /* System has screensaver support */
slouken@1895
   570
slouken@1895
   571
    case WM_CLOSE:
slouken@1895
   572
        {
slouken@3685
   573
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
slouken@1895
   574
        }
slouken@3566
   575
        returnCode = 0;
slouken@3566
   576
        break;
slouken@4919
   577
jimtla@4650
   578
	case WM_TOUCH:
slouken@4932
   579
		{
slouken@4932
   580
			UINT i, num_inputs = LOWORD(wParam);
slouken@4932
   581
			PTOUCHINPUT inputs = SDL_stack_alloc(TOUCHINPUT, num_inputs);
slouken@4919
   582
			if (data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs, sizeof(TOUCHINPUT))) {
slouken@4932
   583
				RECT rect;
slouken@4919
   584
				float x, y;
slouken@4919
   585
slouken@4919
   586
				if (!GetClientRect(hwnd, &rect) ||
slouken@4919
   587
				    (rect.right == rect.left && rect.bottom == rect.top)) {
slouken@4919
   588
					break;
slouken@4919
   589
				}
slouken@4919
   590
				ClientToScreen(hwnd, (LPPOINT) & rect);
slouken@4932
   591
				ClientToScreen(hwnd, (LPPOINT) & rect + 1);
slouken@4932
   592
				rect.top *= 100;
slouken@4932
   593
				rect.left *= 100;
slouken@4932
   594
				rect.bottom *= 100;
slouken@4932
   595
				rect.right *= 100;
slouken@4932
   596
slouken@4932
   597
				for (i = 0; i < num_inputs; ++i) {
slouken@4932
   598
					PTOUCHINPUT input = &inputs[i];
slouken@4919
   599
icculus@5889
   600
					const SDL_TouchID touchId = (SDL_TouchID)
icculus@5889
   601
												((size_t)input->hSource);
slouken@4919
   602
					if (!SDL_GetTouch(touchId)) {
slouken@4919
   603
						SDL_Touch touch;
slouken@4919
   604
slouken@4919
   605
						touch.id = touchId;
slouken@4919
   606
						touch.x_min = 0;
slouken@4919
   607
						touch.x_max = 1;
slouken@4919
   608
						touch.native_xres = touch.x_max - touch.x_min;
slouken@4919
   609
						touch.y_min = 0;
slouken@4919
   610
						touch.y_max = 1;
slouken@4919
   611
						touch.native_yres = touch.y_max - touch.y_min;
slouken@4919
   612
						touch.pressure_min = 0;
slouken@4919
   613
						touch.pressure_max = 1;
slouken@4919
   614
						touch.native_pressureres = touch.pressure_max - touch.pressure_min;
slouken@4919
   615
slouken@4919
   616
						if (SDL_AddTouch(&touch, "") < 0) {
slouken@4919
   617
							continue;
slouken@4919
   618
						}
slouken@4932
   619
					}
slouken@4932
   620
slouken@4932
   621
					// Get the normalized coordinates for the window
slouken@4932
   622
					x = (float)(input->x - rect.left)/(rect.right - rect.left);
slouken@4932
   623
					y = (float)(input->y - rect.top)/(rect.bottom - rect.top);
slouken@4932
   624
slouken@4919
   625
					if (input->dwFlags & TOUCHEVENTF_DOWN) {
slouken@4932
   626
						SDL_SendFingerDown(touchId, input->dwID, SDL_TRUE, x, y, 1);
slouken@4932
   627
					}
slouken@4919
   628
					if (input->dwFlags & TOUCHEVENTF_MOVE) {
slouken@4932
   629
						SDL_SendTouchMotion(touchId, input->dwID, SDL_FALSE, x, y, 1);
slouken@4932
   630
					}
slouken@4919
   631
					if (input->dwFlags & TOUCHEVENTF_UP) {
slouken@4932
   632
						SDL_SendFingerDown(touchId, input->dwID, SDL_FALSE, x, y, 1);
slouken@4932
   633
					}
slouken@4932
   634
				}
slouken@4932
   635
			}
slouken@4932
   636
			SDL_stack_free(inputs);
slouken@4932
   637
slouken@4932
   638
			data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
slouken@4919
   639
			return 0;
jimtla@4650
   640
		}
jimtla@4650
   641
		break;
jimtla@4650
   642
	}
slouken@3566
   643
slouken@3566
   644
    /* If there's a window proc, assume it's going to handle messages */
slouken@3566
   645
    if (data->wndproc) {
slouken@3566
   646
        return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam);
slouken@3566
   647
    } else if (returnCode >= 0) {
slouken@3566
   648
        return returnCode;
slouken@3566
   649
    } else {
slouken@3566
   650
        return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
slouken@3566
   651
    }
slouken@1895
   652
}
slouken@1895
   653
slouken@1895
   654
void
slouken@1895
   655
WIN_PumpEvents(_THIS)
slouken@1895
   656
{
slouken@1895
   657
    MSG msg;
slouken@1895
   658
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
slouken@1895
   659
        TranslateMessage(&msg);
slouken@1895
   660
        DispatchMessage(&msg);
slouken@1895
   661
    }
slouken@1895
   662
}
slouken@1895
   663
slouken@1895
   664
static int app_registered = 0;
slouken@1895
   665
LPTSTR SDL_Appname = NULL;
slouken@1895
   666
Uint32 SDL_Appstyle = 0;
slouken@1895
   667
HINSTANCE SDL_Instance = NULL;
slouken@1895
   668
slouken@1895
   669
/* Register the class for this application */
slouken@1895
   670
int
slouken@1895
   671
SDL_RegisterApp(char *name, Uint32 style, void *hInst)
slouken@1895
   672
{
slouken@1895
   673
    WNDCLASS class;
slouken@1895
   674
slouken@1895
   675
    /* Only do this once... */
slouken@1895
   676
    if (app_registered) {
slouken@1895
   677
        ++app_registered;
slouken@1895
   678
        return (0);
slouken@1895
   679
    }
slouken@1895
   680
    if (!name && !SDL_Appname) {
slouken@1895
   681
        name = "SDL_app";
slouken@5086
   682
#if defined(CS_BYTEALIGNCLIENT) || defined(CS_OWNDC)
slouken@1895
   683
        SDL_Appstyle = (CS_BYTEALIGNCLIENT | CS_OWNDC);
slouken@5086
   684
#endif
slouken@1895
   685
        SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
slouken@1895
   686
    }
slouken@1895
   687
slouken@1895
   688
    if (name) {
slouken@1895
   689
        SDL_Appname = WIN_UTF8ToString(name);
slouken@1895
   690
        SDL_Appstyle = style;
slouken@1895
   691
        SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
slouken@1895
   692
    }
slouken@1895
   693
slouken@1895
   694
    /* Register the application class */
slouken@1895
   695
    class.hCursor = NULL;
slouken@2710
   696
    class.hIcon =
slouken@2710
   697
        LoadImage(SDL_Instance, SDL_Appname, IMAGE_ICON, 0, 0,
slouken@2710
   698
                  LR_DEFAULTCOLOR);
slouken@1895
   699
    class.lpszMenuName = NULL;
slouken@1895
   700
    class.lpszClassName = SDL_Appname;
slouken@1895
   701
    class.hbrBackground = NULL;
slouken@1895
   702
    class.hInstance = SDL_Instance;
slouken@1895
   703
    class.style = SDL_Appstyle;
dewyatt@4733
   704
    class.lpfnWndProc = WIN_WindowProc;
slouken@1895
   705
    class.cbWndExtra = 0;
slouken@1895
   706
    class.cbClsExtra = 0;
slouken@1895
   707
    if (!RegisterClass(&class)) {
slouken@1895
   708
        SDL_SetError("Couldn't register application class");
slouken@1895
   709
        return (-1);
slouken@1895
   710
    }
slouken@1895
   711
slouken@1895
   712
    app_registered = 1;
slouken@1895
   713
    return (0);
slouken@1895
   714
}
slouken@1895
   715
slouken@1895
   716
/* Unregisters the windowclass registered in SDL_RegisterApp above. */
slouken@1895
   717
void
slouken@1895
   718
SDL_UnregisterApp()
slouken@1895
   719
{
slouken@1895
   720
    WNDCLASS class;
slouken@1895
   721
slouken@1895
   722
    /* SDL_RegisterApp might not have been called before */
slouken@1895
   723
    if (!app_registered) {
slouken@1895
   724
        return;
slouken@1895
   725
    }
slouken@1895
   726
    --app_registered;
slouken@1895
   727
    if (app_registered == 0) {
slouken@1895
   728
        /* Check for any registered window classes. */
slouken@1895
   729
        if (GetClassInfo(SDL_Instance, SDL_Appname, &class)) {
slouken@1895
   730
            UnregisterClass(SDL_Appname, SDL_Instance);
slouken@1895
   731
        }
slouken@1895
   732
        SDL_free(SDL_Appname);
slouken@1895
   733
        SDL_Appname = NULL;
slouken@1895
   734
    }
slouken@1895
   735
}
slouken@1895
   736
slouken@6044
   737
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
slouken@6044
   738
slouken@1895
   739
/* vi: set ts=4 sw=4 expandtab: */