src/video/windows/SDL_windowsevents.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 30 Sep 2012 11:10:17 -0700
changeset 6523 62d0193a7a02
parent 6430 48d519500f7e
child 6682 a0cbe4e5a07a
permissions -rw-r--r--
Fixed bug 1593 - SDL_DROPFILE event doesn't work on Windows

Philipp Wiesemann 2012-09-30 05:56:09 PDT

I attached a patch which tries to implement the dropfile support for Microsoft
Windows. If applied SDL_DROPFILE events should be sent for single or multiple
files which are dropped on window.

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