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