src/video/win32/SDL_win32events.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 15 Dec 2009 09:20:10 +0000
changeset 3566 07c8339c95c6
parent 3565 f43c8f688f77
child 3685 64ce267332c6
permissions -rw-r--r--
Fixed bug #905

Give the foreign window message proc more control over Windows events.

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