src/video/win32/SDL_win32events.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 23 Mar 2009 05:35:21 +0000
changeset 3097 0d12e8f1de3c
parent 3095 75483112b97f
child 3102 73fe1f73a56f
permissions -rw-r--r--
Date: Thu, 05 Feb 2009 18:07:35 +0100
From: Stefan Klug
Subject: [SDL] SDL 1.3 WinCE backend

as promised, I've started to work on the WinCE backend of SDL 1.3
I've modified the win32 video backend and the gdi renderer, to work
properly in WinCE.
The results till now are great, but there is still some work to do.

Attached are two patches with my changes.
I would be happy if someone could review and propably commit them.

The first one (configure.in.patch) should be straight forward without
any side effects.

The second one does the necessary changes to the win32 backend. I was
really unhappy to start slicing this shiny new backend with
#ifdef/#endif but I saw no other option.

The most problematic issues are:
- WinCe has no GetDIBits, so its practically impossible to fill a
BITMAPINFO with correct values. I therefore removed the bmi member from
the GDI_RenderData in SDL_gdirender.c to prevent usage of a not or not
properly initialized bmi.
- In SDL_win32window.c I exchanged some ASCII function by their general
counterparts, (In CE only the Unicode versions are available). I don't
know if this has a negative effect when running in win32


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