src/video/win32/SDL_win32events.c
author dewyatt
Tue, 08 Jun 2010 05:22:49 -0400
changeset 4733 983eb9d5ed31
parent 4429 faa9fc8e7f67
child 4746 0c39b36dd104
permissions -rw-r--r--
Change SDL to not use DefWindowProc as the window class' window procedure.
For some reason, having lpfnWndProc=DefWindowProc during window class registration causes IME input to not work in windows.
With this small change, IME input should now work in SDL windows but not in fullscreen mode.
slouken@1895
     1
/*
slouken@1895
     2
    SDL - Simple DirectMedia Layer
slouken@3697
     3
    Copyright (C) 1997-2010 Sam Lantinga
slouken@1895
     4
slouken@1895
     5
    This library is free software; you can redistribute it and/or
slouken@1895
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1895
     7
    License as published by the Free Software Foundation; either
slouken@1895
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@1895
     9
slouken@1895
    10
    This library is distributed in the hope that it will be useful,
slouken@1895
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1895
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1895
    13
    Lesser General Public License for more details.
slouken@1895
    14
slouken@1895
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1895
    16
    License along with this library; if not, write to the Free Software
slouken@1895
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@1895
    18
slouken@1895
    19
    Sam Lantinga
slouken@1895
    20
    slouken@libsdl.org
slouken@1895
    21
*/
slouken@2710
    22
slouken@2710
    23
#if (_WIN32_WINNT < 0x0501)
slouken@2710
    24
#undef _WIN32_WINNT
slouken@2710
    25
#define _WIN32_WINNT 0x0501
slouken@2710
    26
#endif
slouken@2710
    27
slouken@1895
    28
#include "SDL_config.h"
slouken@1895
    29
slouken@1895
    30
#include "SDL_win32video.h"
slouken@1895
    31
#include "SDL_syswm.h"
slouken@1895
    32
#include "SDL_vkeys.h"
slouken@1895
    33
#include "../../events/SDL_events_c.h"
slouken@1895
    34
slouken@1895
    35
/*#define WMMSG_DEBUG*/
slouken@1895
    36
#ifdef WMMSG_DEBUG
slouken@1913
    37
#include <stdio.h>
slouken@1895
    38
#include "wmmsg.h"
slouken@1895
    39
#endif
slouken@1895
    40
slouken@1895
    41
/* Masks for processing the windows KEYDOWN and KEYUP messages */
slouken@2317
    42
#define REPEATED_KEYMASK    (1<<30)
slouken@2317
    43
#define EXTENDED_KEYMASK    (1<<24)
slouken@1895
    44
bob@2324
    45
#define VK_ENTER    10          /* Keypad Enter ... no VKEY defined? */
slouken@2313
    46
icculus@2127
    47
/* Make sure XBUTTON stuff is defined that isn't in older Platform SDKs... */
icculus@2127
    48
#ifndef WM_XBUTTONDOWN
icculus@2127
    49
#define WM_XBUTTONDOWN 0x020B
icculus@2127
    50
#endif
icculus@2127
    51
#ifndef WM_XBUTTONUP
icculus@2127
    52
#define WM_XBUTTONUP 0x020C
icculus@2127
    53
#endif
icculus@2127
    54
#ifndef GET_XBUTTON_WPARAM
icculus@2127
    55
#define GET_XBUTTON_WPARAM(w) (HIWORD(w))
icculus@2127
    56
#endif
bobbens@2733
    57
#ifndef WM_INPUT
bobbens@2733
    58
#define WM_INPUT 0x00ff
bobbens@2733
    59
#endif
slouken@1895
    60
slouken@2710
    61
extern HCTX *g_hCtx;
slouken@2710
    62
extern HANDLE *mice;
slouken@2710
    63
extern int total_mice;
slouken@2710
    64
extern int tablet;
slouken@2710
    65
int pressure = 0;               /* the pressure reported by the tablet */
slouken@2710
    66
slouken@2310
    67
static WPARAM
slouken@2310
    68
RemapVKEY(WPARAM wParam, LPARAM lParam)
slouken@2310
    69
{
slouken@2317
    70
    int i;
bob@2324
    71
    BYTE scancode = (BYTE) ((lParam >> 16) & 0xFF);
slouken@2317
    72
slouken@2310
    73
    /* Windows remaps alphabetic keys based on current layout.
slouken@2310
    74
       We try to provide USB scancodes, so undo this mapping.
slouken@2310
    75
     */
slouken@2310
    76
    if (wParam >= 'A' && wParam <= 'Z') {
slouken@2311
    77
        if (scancode != alpha_scancodes[wParam - 'A']) {
slouken@2311
    78
            for (i = 0; i < SDL_arraysize(alpha_scancodes); ++i) {
slouken@2311
    79
                if (scancode == alpha_scancodes[i]) {
slouken@2310
    80
                    wParam = 'A' + i;
slouken@2310
    81
                    break;
slouken@2310
    82
                }
slouken@2310
    83
            }
slouken@2310
    84
        }
slouken@2310
    85
    }
slouken@2317
    86
slouken@3700
    87
    /* Keypad keys are a little trickier, we always scan for them.
slouken@3700
    88
       Keypad arrow keys have the same scancode as normal arrow keys,
slouken@3700
    89
       except they don't have the extended bit (0x1000000) set.
slouken@3700
    90
     */
slouken@3700
    91
    if (!(lParam & 0x1000000)) {
slouken@3700
    92
        for (i = 0; i < SDL_arraysize(keypad_scancodes); ++i) {
slouken@3700
    93
            if (scancode == keypad_scancodes[i]) {
slouken@3700
    94
                wParam = VK_NUMPAD0 + i;
slouken@3700
    95
                break;
slouken@3700
    96
            }
slouken@2317
    97
        }
slouken@2317
    98
    }
slouken@2317
    99
slouken@2310
   100
    return wParam;
slouken@2310
   101
}
slouken@2310
   102
slouken@1895
   103
LRESULT CALLBACK
slouken@1895
   104
WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
slouken@1895
   105
{
slouken@1895
   106
    SDL_WindowData *data;
slouken@2710
   107
    RAWINPUT *raw;
slouken@2710
   108
    PACKET packet;
slouken@3566
   109
    LRESULT returnCode = -1;
slouken@1895
   110
slouken@1951
   111
    /* Send a SDL_SYSWMEVENT if the application wants them */
slouken@4429
   112
    if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
slouken@1951
   113
        SDL_SysWMmsg wmmsg;
slouken@1951
   114
slouken@1951
   115
        SDL_VERSION(&wmmsg.version);
slouken@1951
   116
        wmmsg.hwnd = hwnd;
slouken@1951
   117
        wmmsg.msg = msg;
slouken@1951
   118
        wmmsg.wParam = wParam;
slouken@1951
   119
        wmmsg.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
    }
slouken@1895
   128
#ifdef WMMSG_DEBUG
slouken@1913
   129
    {
slouken@1913
   130
        FILE *log = fopen("wmmsg.txt", "a");
slouken@1913
   131
        fprintf(log, "Received windows message: %p ", hwnd);
slouken@1913
   132
        if (msg > MAX_WMMSG) {
slouken@1913
   133
            fprintf(log, "%d", msg);
slouken@1913
   134
        } else {
slouken@1913
   135
            fprintf(log, "%s", wmtab[msg]);
slouken@1913
   136
        }
slouken@1913
   137
        fprintf(log, " -- 0x%X, 0x%X\n", wParam, lParam);
slouken@1913
   138
        fclose(log);
slouken@1895
   139
    }
slouken@2710
   140
slouken@1895
   141
#endif
slouken@1895
   142
slouken@1895
   143
    switch (msg) {
slouken@1895
   144
slouken@2710
   145
    case WT_PACKET:
slouken@2710
   146
        {
slouken@2710
   147
            /* if we receive such data we need to update the pressure */
slouken@2726
   148
            SDL_VideoData *videodata = data->videodata;
slouken@2726
   149
            if (videodata->wintabDLL
slouken@3253
   150
                && videodata->WTPacket((HCTX) lParam, (UINT) wParam, &packet)) {
slouken@2710
   151
                SDL_ChangeEnd(tablet, (int) packet.pkCursor);
slouken@2710
   152
                pressure = (int) packet.pkNormalPressure;
slouken@2710
   153
            }
slouken@2710
   154
        }
slouken@2710
   155
        break;
slouken@2710
   156
slouken@2710
   157
    case WT_PROXIMITY:
slouken@2710
   158
        {
slouken@2710
   159
            /* checking where the proximity message showed up */
slouken@2710
   160
            int h_context = LOWORD(lParam);
slouken@2724
   161
            POINT point;
slouken@2710
   162
            GetCursorPos(&point);
slouken@2710
   163
            ScreenToClient(hwnd, &point);
slouken@2710
   164
slouken@2710
   165
            /* are we in proximity or out of proximity */
slouken@2710
   166
            if (h_context == 0) {
slouken@2724
   167
                SDL_SendProximity(tablet, point.x, point.y, SDL_PROXIMITYOUT);
slouken@2710
   168
            } else {
slouken@2724
   169
                SDL_SendProximity(tablet, point.x, point.y, SDL_PROXIMITYIN);
slouken@2710
   170
            }
slouken@2710
   171
        }
slouken@2710
   172
        break;
slouken@2710
   173
slouken@1895
   174
    case WM_SHOWWINDOW:
slouken@1895
   175
        {
slouken@1895
   176
            if (wParam) {
slouken@3685
   177
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
slouken@1895
   178
            } else {
slouken@3685
   179
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
slouken@1895
   180
            }
slouken@1895
   181
        }
slouken@1895
   182
        break;
slouken@1895
   183
slouken@1895
   184
    case WM_ACTIVATE:
slouken@1895
   185
        {
slouken@1895
   186
            int index;
slouken@1895
   187
            SDL_Keyboard *keyboard;
slouken@1895
   188
            BOOL minimized;
slouken@1895
   189
slouken@1895
   190
            minimized = HIWORD(wParam);
slouken@1895
   191
            index = data->videodata->keyboard;
slouken@1895
   192
            keyboard = SDL_GetKeyboard(index);
slouken@1895
   193
            if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
slouken@3685
   194
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
slouken@3685
   195
                SDL_SendWindowEvent(data->window,
slouken@1895
   196
                                    SDL_WINDOWEVENT_RESTORED, 0, 0);
slouken@3139
   197
#ifndef _WIN32_WCE              /* WinCE misses IsZoomed() */
slouken@1895
   198
                if (IsZoomed(hwnd)) {
slouken@3685
   199
                    SDL_SendWindowEvent(data->window,
slouken@1895
   200
                                        SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
slouken@1895
   201
                }
slouken@3139
   202
#endif
slouken@3685
   203
                if (keyboard && keyboard->focus != data->window) {
slouken@3685
   204
                    SDL_SetKeyboardFocus(index, data->window);
slouken@1895
   205
                }
slouken@1895
   206
                /* FIXME: Update keyboard state */
slouken@1895
   207
            } else {
slouken@3685
   208
                if (keyboard && keyboard->focus == data->window) {
slouken@1895
   209
                    SDL_SetKeyboardFocus(index, 0);
slouken@1895
   210
                }
slouken@1895
   211
                if (minimized) {
slouken@3685
   212
                    SDL_SendWindowEvent(data->window,
slouken@1895
   213
                                        SDL_WINDOWEVENT_MINIMIZED, 0, 0);
slouken@1895
   214
                }
slouken@1895
   215
            }
slouken@1895
   216
        }
slouken@3566
   217
        returnCode = 0;
slouken@3566
   218
        break;
slouken@1895
   219
slouken@3097
   220
/* WinCE has no RawInput, so we use the classic mouse events.
slouken@3097
   221
   In classic Win32 this is done by WM_INPUT
slouken@3097
   222
 */
slouken@3097
   223
#ifdef _WIN32_WCE
slouken@3097
   224
    case WM_MOUSEMOVE:
slouken@3139
   225
        SDL_SendMouseMotion(0, 0, LOWORD(lParam), HIWORD(lParam), 0);
slouken@3139
   226
        break;
slouken@3139
   227
slouken@3097
   228
    case WM_LBUTTONDOWN:
slouken@3139
   229
        SDL_SendMouseMotion(0, 0, LOWORD(lParam), HIWORD(lParam), 0);
slouken@3139
   230
        SDL_SendMouseButton(0, SDL_PRESSED, SDL_BUTTON_LEFT);
slouken@3139
   231
        break;
slouken@3139
   232
slouken@3097
   233
    case WM_LBUTTONUP:
slouken@3139
   234
        SDL_SendMouseMotion(0, 0, LOWORD(lParam), HIWORD(lParam), 0);
slouken@3139
   235
        SDL_SendMouseButton(0, SDL_RELEASED, SDL_BUTTON_LEFT);
slouken@3139
   236
        break;
slouken@3097
   237
#else /* _WIN32_WCE */
slouken@3097
   238
slouken@2710
   239
    case WM_INPUT:             /* mouse events */
slouken@1895
   240
        {
slouken@2710
   241
            LPBYTE lpb;
slouken@2710
   242
            const RAWINPUTHEADER *header;
slouken@3260
   243
            int index = -1;
slouken@2710
   244
            int i;
slouken@2710
   245
            int size = 0;
slouken@2710
   246
            const RAWMOUSE *raw_mouse = NULL;
slouken@2724
   247
            POINT point;
slouken@2710
   248
            USHORT flags;
slouken@2974
   249
            int w, h;
slouken@1895
   250
slouken@3097
   251
            /* we're collecting raw data to be able to identify the mouse (if there are several) */
slouken@2710
   252
            GetRawInputData((HRAWINPUT) lParam, RID_INPUT, NULL, &size,
slouken@2710
   253
                            sizeof(RAWINPUTHEADER));
slouken@2766
   254
            lpb = SDL_stack_alloc(BYTE, size);
slouken@2710
   255
            GetRawInputData((HRAWINPUT) lParam, RID_INPUT, lpb, &size,
slouken@2710
   256
                            sizeof(RAWINPUTHEADER));
slouken@2710
   257
            raw = (RAWINPUT *) lpb;
slouken@2710
   258
            header = &raw->header;
slouken@2710
   259
            flags = raw->data.mouse.usButtonFlags;
slouken@1895
   260
slouken@2710
   261
            /* we're checking which mouse generated the event */
slouken@2710
   262
            for (i = 0; i < total_mice; ++i) {
slouken@2710
   263
                if (mice[i] == header->hDevice) {
slouken@2710
   264
                    index = i;
slouken@2710
   265
                    break;
slouken@2710
   266
                }
slouken@2710
   267
            }
slouken@3260
   268
            if (index < 0) {
slouken@3260
   269
                /* New mouse?  Should we dynamically update mouse list? */
slouken@3566
   270
                returnCode = 0;
slouken@3566
   271
                break;
slouken@3260
   272
            }
slouken@3139
   273
slouken@2710
   274
            GetCursorPos(&point);
slouken@2974
   275
            ScreenToClient(hwnd, &point);
slouken@2974
   276
slouken@3685
   277
            SDL_GetWindowSize(data->window, &w, &h);
slouken@2974
   278
            if (point.x >= 0 && point.y >= 0 && point.x < w && point.y < h) {
slouken@3685
   279
                SDL_SetMouseFocus(index, data->window);
slouken@2974
   280
            } else {
slouken@2974
   281
                SDL_SetMouseFocus(index, 0);
slouken@2974
   282
                /* FIXME: Should we be doing anything else here? */
slouken@2974
   283
                break;
slouken@2974
   284
            }
slouken@1895
   285
slouken@2710
   286
            /* if the message was sent by a tablet we have to send also pressure */
slouken@2794
   287
            if (index == tablet) {
slouken@2724
   288
                SDL_SendMouseMotion(index, 0, point.x, point.y, pressure);
slouken@2710
   289
            } else {
slouken@2724
   290
                SDL_SendMouseMotion(index, 0, point.x, point.y, 0);
slouken@1895
   291
            }
slouken@2710
   292
            /* we're sending mouse buttons messages to check up if sth changed */
slouken@2766
   293
            if (flags & RI_MOUSE_LEFT_BUTTON_DOWN) {
slouken@2710
   294
                SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_LEFT);
slouken@2766
   295
            } else if (flags & RI_MOUSE_LEFT_BUTTON_UP) {
slouken@2710
   296
                SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_LEFT);
slouken@2710
   297
            }
slouken@2766
   298
            if (flags & RI_MOUSE_MIDDLE_BUTTON_DOWN) {
slouken@2710
   299
                SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_MIDDLE);
slouken@2766
   300
            } else if (flags & RI_MOUSE_MIDDLE_BUTTON_UP) {
slouken@2710
   301
                SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_MIDDLE);
slouken@2710
   302
            }
slouken@2766
   303
            if (flags & RI_MOUSE_RIGHT_BUTTON_DOWN) {
slouken@2710
   304
                SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_RIGHT);
slouken@2766
   305
            } else if (flags & RI_MOUSE_RIGHT_BUTTON_UP) {
slouken@2710
   306
                SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_RIGHT);
slouken@2710
   307
            }
slouken@2711
   308
            if (flags & RI_MOUSE_BUTTON_4_DOWN) {
slouken@2711
   309
                SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_X1);
slouken@2711
   310
            } else if (flags & RI_MOUSE_BUTTON_4_UP) {
slouken@2711
   311
                SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_X1);
slouken@2711
   312
            }
slouken@2711
   313
            if (flags & RI_MOUSE_BUTTON_5_DOWN) {
slouken@2711
   314
                SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_X2);
slouken@2711
   315
            } else if (flags & RI_MOUSE_BUTTON_5_UP) {
slouken@2711
   316
                SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_X2);
slouken@2711
   317
            }
slouken@2710
   318
            if (flags & RI_MOUSE_WHEEL) {
slouken@2975
   319
                SDL_SendMouseWheel(index, 0,
slouken@2990
   320
                                   (short) raw->data.mouse.usButtonData);
slouken@1895
   321
            }
slouken@2766
   322
            SDL_stack_free(lpb);
slouken@1895
   323
        }
slouken@3566
   324
        returnCode = 0;
slouken@3566
   325
        break;
slouken@3097
   326
#endif /* _WIN32_WCE */
slouken@3139
   327
slouken@1895
   328
    case WM_MOUSELEAVE:
slouken@1895
   329
        {
slouken@2974
   330
            int i;
slouken@1895
   331
slouken@2974
   332
            for (i = 0; i < SDL_GetNumMice(); ++i) {
slouken@2974
   333
                SDL_Mouse *mouse = SDL_GetMouse(i);
slouken@1895
   334
slouken@3685
   335
                if (mouse->focus == data->window) {
slouken@2974
   336
                    SDL_SetMouseFocus(i, 0);
slouken@2974
   337
                }
slouken@1895
   338
            }
slouken@1895
   339
        }
slouken@3566
   340
        returnCode = 0;
slouken@3566
   341
        break;
slouken@1895
   342
slouken@1895
   343
    case WM_SYSKEYDOWN:
slouken@1895
   344
    case WM_KEYDOWN:
slouken@1895
   345
        {
slouken@1895
   346
            int index;
slouken@1895
   347
slouken@1895
   348
            /* Ignore repeated keys */
slouken@1895
   349
            if (lParam & REPEATED_KEYMASK) {
slouken@3566
   350
                returnCode = 0;
slouken@3566
   351
                break;
slouken@1895
   352
            }
slouken@1895
   353
slouken@1895
   354
            index = data->videodata->keyboard;
slouken@2310
   355
            wParam = RemapVKEY(wParam, lParam);
slouken@1895
   356
            switch (wParam) {
slouken@1895
   357
            case VK_CONTROL:
slouken@1895
   358
                if (lParam & EXTENDED_KEYMASK)
slouken@1895
   359
                    wParam = VK_RCONTROL;
slouken@1895
   360
                else
slouken@1895
   361
                    wParam = VK_LCONTROL;
slouken@1895
   362
                break;
slouken@1895
   363
            case VK_SHIFT:
slouken@1895
   364
                /* EXTENDED trick doesn't work here */
slouken@1895
   365
                {
slouken@2308
   366
                    Uint8 *state = SDL_GetKeyboardState(NULL);
slouken@2308
   367
                    if (state[SDL_SCANCODE_LSHIFT] == SDL_RELEASED
slouken@1895
   368
                        && (GetKeyState(VK_LSHIFT) & 0x8000)) {
slouken@1895
   369
                        wParam = VK_LSHIFT;
slouken@2308
   370
                    } else if (state[SDL_SCANCODE_RSHIFT] == SDL_RELEASED
slouken@1895
   371
                               && (GetKeyState(VK_RSHIFT) & 0x8000)) {
slouken@1895
   372
                        wParam = VK_RSHIFT;
slouken@1895
   373
                    } else {
slouken@1895
   374
                        /* Probably a key repeat */
slouken@3566
   375
                        wParam = 256;
slouken@1895
   376
                    }
slouken@1895
   377
                }
slouken@1895
   378
                break;
slouken@1895
   379
            case VK_MENU:
slouken@1895
   380
                if (lParam & EXTENDED_KEYMASK)
slouken@1895
   381
                    wParam = VK_RMENU;
slouken@1895
   382
                else
slouken@1895
   383
                    wParam = VK_LMENU;
slouken@1895
   384
                break;
slouken@2313
   385
            case VK_RETURN:
slouken@2313
   386
                if (lParam & EXTENDED_KEYMASK)
slouken@2313
   387
                    wParam = VK_ENTER;
slouken@2313
   388
                break;
slouken@1895
   389
            }
slouken@2308
   390
            if (wParam < 256) {
slouken@2308
   391
                SDL_SendKeyboardKey(index, SDL_PRESSED,
slouken@2308
   392
                                    data->videodata->key_layout[wParam]);
slouken@2308
   393
            }
slouken@1895
   394
        }
slouken@3566
   395
        returnCode = 0;
slouken@3566
   396
        break;
slouken@1895
   397
slouken@1895
   398
    case WM_SYSKEYUP:
slouken@1895
   399
    case WM_KEYUP:
slouken@1895
   400
        {
slouken@1895
   401
            int index;
slouken@1895
   402
slouken@1895
   403
            index = data->videodata->keyboard;
slouken@2310
   404
            wParam = RemapVKEY(wParam, lParam);
slouken@1895
   405
            switch (wParam) {
slouken@1895
   406
            case VK_CONTROL:
slouken@1895
   407
                if (lParam & EXTENDED_KEYMASK)
slouken@1895
   408
                    wParam = VK_RCONTROL;
slouken@1895
   409
                else
slouken@1895
   410
                    wParam = VK_LCONTROL;
slouken@1895
   411
                break;
slouken@1895
   412
            case VK_SHIFT:
slouken@1895
   413
                /* EXTENDED trick doesn't work here */
slouken@1895
   414
                {
slouken@2308
   415
                    Uint8 *state = SDL_GetKeyboardState(NULL);
slouken@2308
   416
                    if (state[SDL_SCANCODE_LSHIFT] == SDL_PRESSED
slouken@1895
   417
                        && !(GetKeyState(VK_LSHIFT) & 0x8000)) {
slouken@1895
   418
                        wParam = VK_LSHIFT;
slouken@2308
   419
                    } else if (state[SDL_SCANCODE_RSHIFT] == SDL_PRESSED
slouken@1895
   420
                               && !(GetKeyState(VK_RSHIFT) & 0x8000)) {
slouken@1895
   421
                        wParam = VK_RSHIFT;
slouken@1895
   422
                    } else {
slouken@1895
   423
                        /* Probably a key repeat */
slouken@3566
   424
                        wParam = 256;
slouken@1895
   425
                    }
slouken@1895
   426
                }
slouken@1895
   427
                break;
slouken@1895
   428
            case VK_MENU:
slouken@1895
   429
                if (lParam & EXTENDED_KEYMASK)
slouken@1895
   430
                    wParam = VK_RMENU;
slouken@1895
   431
                else
slouken@1895
   432
                    wParam = VK_LMENU;
slouken@1895
   433
                break;
slouken@2313
   434
            case VK_RETURN:
slouken@2313
   435
                if (lParam & EXTENDED_KEYMASK)
slouken@2313
   436
                    wParam = VK_ENTER;
slouken@2313
   437
                break;
slouken@1895
   438
            }
slouken@2710
   439
slouken@1895
   440
            /* Windows only reports keyup for print screen */
slouken@1895
   441
            if (wParam == VK_SNAPSHOT
slouken@2308
   442
                && SDL_GetKeyboardState(NULL)[SDL_SCANCODE_PRINTSCREEN] ==
slouken@2308
   443
                SDL_RELEASED) {
slouken@1895
   444
                SDL_SendKeyboardKey(index, SDL_PRESSED,
slouken@2308
   445
                                    data->videodata->key_layout[wParam]);
slouken@1895
   446
            }
slouken@2308
   447
            if (wParam < 256) {
slouken@2308
   448
                SDL_SendKeyboardKey(index, SDL_RELEASED,
slouken@2308
   449
                                    data->videodata->key_layout[wParam]);
slouken@2308
   450
            }
slouken@1895
   451
        }
slouken@3566
   452
        returnCode = 0;
slouken@3566
   453
        break;
slouken@1895
   454
slouken@2309
   455
    case WM_CHAR:
slouken@2309
   456
        {
slouken@2309
   457
            char text[4];
slouken@2309
   458
slouken@2309
   459
            /* Convert to UTF-8 and send it on... */
slouken@2309
   460
            if (wParam <= 0x7F) {
slouken@2309
   461
                text[0] = (char) wParam;
slouken@2309
   462
                text[1] = '\0';
slouken@2309
   463
            } else if (wParam <= 0x7FF) {
slouken@2309
   464
                text[0] = 0xC0 | (char) ((wParam >> 6) & 0x1F);
slouken@2309
   465
                text[1] = 0x80 | (char) (wParam & 0x3F);
slouken@2309
   466
                text[2] = '\0';
slouken@2309
   467
            } else {
slouken@2309
   468
                text[0] = 0xE0 | (char) ((wParam >> 12) & 0x0F);
slouken@2309
   469
                text[1] = 0x80 | (char) ((wParam >> 6) & 0x3F);
slouken@2309
   470
                text[2] = 0x80 | (char) (wParam & 0x3F);
slouken@2309
   471
                text[3] = '\0';
slouken@2309
   472
            }
slouken@2309
   473
            SDL_SendKeyboardText(data->videodata->keyboard, text);
slouken@2309
   474
        }
slouken@3566
   475
        returnCode = 0;
slouken@3566
   476
        break;
slouken@2309
   477
slouken@2311
   478
    case WM_INPUTLANGCHANGE:
slouken@2311
   479
        {
slouken@2311
   480
            WIN_UpdateKeymap(data->videodata->keyboard);
slouken@2311
   481
        }
slouken@3566
   482
        returnCode = 1;
slouken@3566
   483
        break;
slouken@2311
   484
slouken@1895
   485
    case WM_GETMINMAXINFO:
slouken@1895
   486
        {
slouken@1895
   487
            MINMAXINFO *info;
slouken@1895
   488
            RECT size;
slouken@1895
   489
            int x, y;
slouken@1895
   490
            int w, h;
slouken@1895
   491
            int style;
slouken@3168
   492
            BOOL menu;
slouken@1895
   493
slouken@1895
   494
            /* If we allow resizing, let the resize happen naturally */
slouken@3685
   495
            if (SDL_GetWindowFlags(data->window) & SDL_WINDOW_RESIZABLE) {
slouken@3566
   496
                returnCode = 0;
slouken@3566
   497
                break;
slouken@1895
   498
            }
slouken@1895
   499
slouken@1895
   500
            /* Get the current position of our window */
slouken@1895
   501
            GetWindowRect(hwnd, &size);
slouken@1895
   502
            x = size.left;
slouken@1895
   503
            y = size.top;
slouken@1895
   504
slouken@1895
   505
            /* Calculate current size of our window */
slouken@3685
   506
            SDL_GetWindowSize(data->window, &w, &h);
slouken@1895
   507
            size.top = 0;
slouken@1895
   508
            size.left = 0;
slouken@1895
   509
            size.bottom = h;
slouken@1895
   510
            size.right = w;
slouken@1895
   511
slouken@3168
   512
slouken@3168
   513
            style = GetWindowLong(hwnd, GWL_STYLE);
slouken@3168
   514
#ifdef _WIN32_WCE
slouken@3168
   515
            menu = FALSE;
slouken@3168
   516
#else
slouken@1895
   517
            /* DJM - according to the docs for GetMenu(), the
slouken@1895
   518
               return value is undefined if hwnd is a child window.
slouken@1895
   519
               Aparently it's too difficult for MS to check
slouken@1895
   520
               inside their function, so I have to do it here.
slouken@1895
   521
             */
slouken@3168
   522
            menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
slouken@3168
   523
#endif
slouken@3168
   524
            AdjustWindowRectEx(&size, style, menu, 0);
slouken@1895
   525
            w = size.right - size.left;
slouken@1895
   526
            h = size.bottom - size.top;
slouken@1895
   527
slouken@1895
   528
            /* Fix our size to the current size */
slouken@1895
   529
            info = (MINMAXINFO *) lParam;
slouken@1895
   530
            info->ptMaxSize.x = w;
slouken@1895
   531
            info->ptMaxSize.y = h;
slouken@1895
   532
            info->ptMaxPosition.x = x;
slouken@1895
   533
            info->ptMaxPosition.y = y;
slouken@1895
   534
            info->ptMinTrackSize.x = w;
slouken@1895
   535
            info->ptMinTrackSize.y = h;
slouken@1895
   536
            info->ptMaxTrackSize.x = w;
slouken@1895
   537
            info->ptMaxTrackSize.y = h;
slouken@1895
   538
        }
slouken@3566
   539
        returnCode = 0;
slouken@3566
   540
        break;
slouken@1895
   541
slouken@1895
   542
    case WM_WINDOWPOSCHANGED:
slouken@1895
   543
        {
slouken@1895
   544
            RECT rect;
slouken@1895
   545
            int x, y;
slouken@1895
   546
            int w, h;
slouken@1895
   547
            Uint32 window_flags;
slouken@1895
   548
slouken@3256
   549
            if (!GetClientRect(hwnd, &rect) ||
slouken@3256
   550
                (rect.right == rect.left && rect.bottom == rect.top)) {
slouken@3256
   551
                break;
slouken@3256
   552
            }
slouken@1895
   553
            ClientToScreen(hwnd, (LPPOINT) & rect);
slouken@1895
   554
            ClientToScreen(hwnd, (LPPOINT) & rect + 1);
slouken@1895
   555
slouken@3685
   556
            window_flags = SDL_GetWindowFlags(data->window);
slouken@1895
   557
            if ((window_flags & SDL_WINDOW_INPUT_GRABBED) &&
slouken@1895
   558
                (window_flags & SDL_WINDOW_INPUT_FOCUS)) {
slouken@1895
   559
                ClipCursor(&rect);
slouken@1895
   560
            }
slouken@1895
   561
slouken@1895
   562
            x = rect.left;
slouken@1895
   563
            y = rect.top;
slouken@3685
   564
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, x, y);
slouken@1895
   565
slouken@1895
   566
            w = rect.right - rect.left;
slouken@1895
   567
            h = rect.bottom - rect.top;
slouken@3685
   568
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, w,
slouken@1895
   569
                                h);
slouken@1895
   570
        }
slouken@1895
   571
        break;
slouken@1895
   572
slouken@1895
   573
    case WM_SETCURSOR:
slouken@1895
   574
        {
slouken@3076
   575
            Uint16 hittest;
slouken@1895
   576
slouken@3076
   577
            hittest = LOWORD(lParam);
slouken@3076
   578
            if (hittest == HTCLIENT) {
slouken@3076
   579
                /* FIXME: Implement the cursor API */
slouken@3076
   580
                static HCURSOR cursor;
slouken@3076
   581
                if (!cursor) {
slouken@3076
   582
                    cursor = LoadCursor(NULL, IDC_ARROW);
slouken@3076
   583
                }
slouken@3076
   584
                SetCursor(cursor);
slouken@3566
   585
                returnCode = TRUE;
slouken@3076
   586
            }
slouken@1895
   587
        }
slouken@1895
   588
        break;
slouken@1895
   589
slouken@1895
   590
        /* We are about to get palette focus! */
slouken@1895
   591
    case WM_QUERYNEWPALETTE:
slouken@1895
   592
        {
slouken@1895
   593
            /*
slouken@3566
   594
                WIN_RealizePalette(current_video);
slouken@3566
   595
                returnCode = TRUE;
slouken@1895
   596
             */
slouken@1895
   597
        }
slouken@1895
   598
        break;
slouken@1895
   599
slouken@1895
   600
        /* Another application changed the palette */
slouken@1895
   601
    case WM_PALETTECHANGED:
slouken@1895
   602
        {
slouken@1895
   603
            /*
slouken@1895
   604
               WIN_PaletteChanged(current_video, (HWND) wParam);
slouken@1895
   605
             */
slouken@1895
   606
        }
slouken@1895
   607
        break;
slouken@1895
   608
slouken@1895
   609
        /* We were occluded, refresh our display */
slouken@1895
   610
    case WM_PAINT:
slouken@1895
   611
        {
slouken@1895
   612
            RECT rect;
slouken@1895
   613
            if (GetUpdateRect(hwnd, &rect, FALSE)) {
slouken@1895
   614
                ValidateRect(hwnd, &rect);
slouken@3685
   615
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED,
slouken@1895
   616
                                    0, 0);
slouken@1895
   617
            }
slouken@1895
   618
        }
slouken@3566
   619
        returnCode = 0;
slouken@3566
   620
        break;
slouken@3095
   621
slouken@1895
   622
        /* We'll do our own drawing, prevent flicker */
slouken@1895
   623
    case WM_ERASEBKGND:
slouken@1895
   624
        {
slouken@1895
   625
        }
slouken@1895
   626
        return (1);
slouken@1895
   627
slouken@1895
   628
    case WM_SYSCOMMAND:
slouken@1895
   629
        {
slouken@1895
   630
            /* Don't start the screensaver or blank the monitor in fullscreen apps */
slouken@1895
   631
            if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
slouken@1895
   632
                (wParam & 0xFFF0) == SC_MONITORPOWER) {
slouken@3032
   633
                if (SDL_GetVideoDevice()->suspend_screensaver) {
slouken@1895
   634
                    return (0);
slouken@1895
   635
                }
slouken@1895
   636
            }
slouken@1895
   637
        }
slouken@1895
   638
        break;
slouken@1895
   639
slouken@1895
   640
    case WM_CLOSE:
slouken@1895
   641
        {
slouken@3685
   642
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
slouken@1895
   643
        }
slouken@3566
   644
        returnCode = 0;
slouken@3566
   645
        break;
slouken@1895
   646
    }
slouken@3566
   647
slouken@3566
   648
    /* If there's a window proc, assume it's going to handle messages */
slouken@3566
   649
    if (data->wndproc) {
slouken@3566
   650
        return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam);
slouken@3566
   651
    } else if (returnCode >= 0) {
slouken@3566
   652
        return returnCode;
slouken@3566
   653
    } else {
slouken@3566
   654
        return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
slouken@3566
   655
    }
slouken@1895
   656
}
slouken@1895
   657
slouken@1895
   658
void
slouken@1895
   659
WIN_PumpEvents(_THIS)
slouken@1895
   660
{
slouken@1895
   661
    MSG msg;
slouken@1895
   662
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
slouken@1895
   663
        TranslateMessage(&msg);
slouken@1895
   664
        DispatchMessage(&msg);
slouken@1895
   665
    }
slouken@1895
   666
}
slouken@1895
   667
slouken@1895
   668
static int app_registered = 0;
slouken@1895
   669
LPTSTR SDL_Appname = NULL;
slouken@1895
   670
Uint32 SDL_Appstyle = 0;
slouken@1895
   671
HINSTANCE SDL_Instance = NULL;
slouken@1895
   672
slouken@1895
   673
/* Register the class for this application */
slouken@1895
   674
int
slouken@1895
   675
SDL_RegisterApp(char *name, Uint32 style, void *hInst)
slouken@1895
   676
{
slouken@1895
   677
    WNDCLASS class;
slouken@1895
   678
slouken@1895
   679
    /* Only do this once... */
slouken@1895
   680
    if (app_registered) {
slouken@1895
   681
        ++app_registered;
slouken@1895
   682
        return (0);
slouken@1895
   683
    }
slouken@1895
   684
    if (!name && !SDL_Appname) {
slouken@1895
   685
        name = "SDL_app";
slouken@1895
   686
        SDL_Appstyle = (CS_BYTEALIGNCLIENT | CS_OWNDC);
slouken@1895
   687
        SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
slouken@1895
   688
    }
slouken@1895
   689
slouken@1895
   690
    if (name) {
slouken@1895
   691
        SDL_Appname = WIN_UTF8ToString(name);
slouken@1895
   692
        SDL_Appstyle = style;
slouken@1895
   693
        SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
slouken@1895
   694
    }
slouken@1895
   695
slouken@1895
   696
    /* Register the application class */
slouken@1895
   697
    class.hCursor = NULL;
slouken@2710
   698
    class.hIcon =
slouken@2710
   699
        LoadImage(SDL_Instance, SDL_Appname, IMAGE_ICON, 0, 0,
slouken@2710
   700
                  LR_DEFAULTCOLOR);
slouken@1895
   701
    class.lpszMenuName = NULL;
slouken@1895
   702
    class.lpszClassName = SDL_Appname;
slouken@1895
   703
    class.hbrBackground = NULL;
slouken@1895
   704
    class.hInstance = SDL_Instance;
slouken@1895
   705
    class.style = SDL_Appstyle;
dewyatt@4733
   706
    class.lpfnWndProc = WIN_WindowProc;
slouken@1895
   707
    class.cbWndExtra = 0;
slouken@1895
   708
    class.cbClsExtra = 0;
slouken@1895
   709
    if (!RegisterClass(&class)) {
slouken@1895
   710
        SDL_SetError("Couldn't register application class");
slouken@1895
   711
        return (-1);
slouken@1895
   712
    }
slouken@1895
   713
slouken@1895
   714
    app_registered = 1;
slouken@1895
   715
    return (0);
slouken@1895
   716
}
slouken@1895
   717
slouken@1895
   718
/* Unregisters the windowclass registered in SDL_RegisterApp above. */
slouken@1895
   719
void
slouken@1895
   720
SDL_UnregisterApp()
slouken@1895
   721
{
slouken@1895
   722
    WNDCLASS class;
slouken@1895
   723
slouken@1895
   724
    /* SDL_RegisterApp might not have been called before */
slouken@1895
   725
    if (!app_registered) {
slouken@1895
   726
        return;
slouken@1895
   727
    }
slouken@1895
   728
    --app_registered;
slouken@1895
   729
    if (app_registered == 0) {
slouken@1895
   730
        /* Check for any registered window classes. */
slouken@1895
   731
        if (GetClassInfo(SDL_Instance, SDL_Appname, &class)) {
slouken@1895
   732
            UnregisterClass(SDL_Appname, SDL_Instance);
slouken@1895
   733
        }
slouken@1895
   734
        SDL_free(SDL_Appname);
slouken@1895
   735
        SDL_Appname = NULL;
slouken@1895
   736
    }
slouken@1895
   737
}
slouken@1895
   738
slouken@1895
   739
/* Sets an error message based on GetLastError() */
slouken@1895
   740
void
slouken@1895
   741
WIN_SetError(const char *prefix)
slouken@1895
   742
{
slouken@1895
   743
    TCHAR buffer[1024];
slouken@1895
   744
    char *message;
slouken@2710
   745
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
slouken@2710
   746
                  buffer, SDL_arraysize(buffer), NULL);
slouken@1895
   747
    message = WIN_StringToUTF8(buffer);
slouken@3565
   748
    SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ": " : "", message);
slouken@1895
   749
    SDL_free(message);
slouken@1895
   750
}
slouken@1895
   751
slouken@1895
   752
/* vi: set ts=4 sw=4 expandtab: */