src/video/win32/SDL_win32events.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 07 Jun 2009 02:44:46 +0000
changeset 3168 6338b7f2d024
parent 3139 7f684f249ec9
child 3253 5d7ef5970073
permissions -rw-r--r--
Hi,

I have prepared a set of patches to readd WindowsCE support to SDL 1.3.
I've created a new GAPI/Rawframebuffer and a DirectDraw renderer.
Both renderers are work in progress and there are several unimplemented
cases. (Notably
RenderLine/RenderPoint/RenderFill/QueryTexturePixels/UpdateTexture and
texture blending )
Nevertheless I am successfully using these renderers together with the
SDL software renderer. (On most devices the SDL software renderer will
be much faster as there are only badly optimized vendor drivers available)

I send these patches now in this unpolished state because there seems to
be some interest in win ce and someone has to start supporting SDL 1.3

Now on to the patches:
wince_events_window_fixes.patch
fixes some wince incompatibilities and adds fullscreen support via
SHFullScreen. NOTE: This patch shouldn't have any side effects on
Windows, but I have NOT tested it on Windows, so please double-check.
This patch doesn't dependent on the following ones.

wince_renderers_system.patch
This patch does all necessary modifications to the SDL system.
- it adds the renderers to the configure system
- it adds the renderers to win32video

SDL_ceddrawrender.c
SDL_ceddrawrender.h
SDL_gapirender_c.h
SDL_gapirender.c
SDL_gapirender.h
these files add the new render drivers and should be placed in
src/video/win32

Some notes to people who want to test this:
- I have only compiled sdl with ming32ce, so the VisualC files are not
up to date
- As mingw32ce has no ddraw.h this file must be taken from the MS SDK
and modified to work with gcc
- I had to modify line 2611 in configure.in to
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lcoredll -lcommctrl -lmmtimer
-Wl,--image-base -Wl,0x10000"
otherwise GetCPinfo wouldn't link. If someone knows whats causing this
I'd be happy to hear about it.

It would be great if these patches could make their way into SVN as this
would make collaboration much much easier.

I'm out of office for the next week and therefore will be unavailable
via email.

Regards
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@3139
   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@3139
   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@3139
   221
        SDL_SendMouseMotion(0, 0, LOWORD(lParam), HIWORD(lParam), 0);
slouken@3139
   222
        break;
slouken@3139
   223
slouken@3097
   224
    case WM_LBUTTONDOWN:
slouken@3139
   225
        SDL_SendMouseMotion(0, 0, LOWORD(lParam), HIWORD(lParam), 0);
slouken@3139
   226
        SDL_SendMouseButton(0, SDL_PRESSED, SDL_BUTTON_LEFT);
slouken@3139
   227
        break;
slouken@3139
   228
slouken@3097
   229
    case WM_LBUTTONUP:
slouken@3139
   230
        SDL_SendMouseMotion(0, 0, LOWORD(lParam), HIWORD(lParam), 0);
slouken@3139
   231
        SDL_SendMouseButton(0, SDL_RELEASED, SDL_BUTTON_LEFT);
slouken@3139
   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@3139
   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@3139
   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@3168
   476
            BOOL menu;
slouken@1895
   477
slouken@1895
   478
            /* If we allow resizing, let the resize happen naturally */
slouken@1895
   479
            if (SDL_GetWindowFlags(data->windowID) & SDL_WINDOW_RESIZABLE) {
slouken@1895
   480
                return (0);
slouken@1895
   481
            }
slouken@1895
   482
slouken@1895
   483
            /* Get the current position of our window */
slouken@1895
   484
            GetWindowRect(hwnd, &size);
slouken@1895
   485
            x = size.left;
slouken@1895
   486
            y = size.top;
slouken@1895
   487
slouken@1895
   488
            /* Calculate current size of our window */
slouken@1895
   489
            SDL_GetWindowSize(data->windowID, &w, &h);
slouken@1895
   490
            size.top = 0;
slouken@1895
   491
            size.left = 0;
slouken@1895
   492
            size.bottom = h;
slouken@1895
   493
            size.right = w;
slouken@1895
   494
slouken@3168
   495
slouken@3168
   496
            style = GetWindowLong(hwnd, GWL_STYLE);
slouken@3168
   497
#ifdef _WIN32_WCE
slouken@3168
   498
            menu = FALSE;
slouken@3168
   499
#else
slouken@1895
   500
            /* DJM - according to the docs for GetMenu(), the
slouken@1895
   501
               return value is undefined if hwnd is a child window.
slouken@1895
   502
               Aparently it's too difficult for MS to check
slouken@1895
   503
               inside their function, so I have to do it here.
slouken@1895
   504
             */
slouken@3168
   505
            menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
slouken@3168
   506
#endif
slouken@3168
   507
            AdjustWindowRectEx(&size, style, menu, 0);
slouken@1895
   508
            w = size.right - size.left;
slouken@1895
   509
            h = size.bottom - size.top;
slouken@1895
   510
slouken@1895
   511
            /* Fix our size to the current size */
slouken@1895
   512
            info = (MINMAXINFO *) lParam;
slouken@1895
   513
            info->ptMaxSize.x = w;
slouken@1895
   514
            info->ptMaxSize.y = h;
slouken@1895
   515
            info->ptMaxPosition.x = x;
slouken@1895
   516
            info->ptMaxPosition.y = y;
slouken@1895
   517
            info->ptMinTrackSize.x = w;
slouken@1895
   518
            info->ptMinTrackSize.y = h;
slouken@1895
   519
            info->ptMaxTrackSize.x = w;
slouken@1895
   520
            info->ptMaxTrackSize.y = h;
slouken@1895
   521
        }
slouken@1895
   522
        return (0);
slouken@1895
   523
slouken@1895
   524
    case WM_WINDOWPOSCHANGED:
slouken@1895
   525
        {
slouken@1895
   526
            RECT rect;
slouken@1895
   527
            int x, y;
slouken@1895
   528
            int w, h;
slouken@1895
   529
            Uint32 window_flags;
slouken@1895
   530
slouken@1895
   531
            GetClientRect(hwnd, &rect);
slouken@1895
   532
            ClientToScreen(hwnd, (LPPOINT) & rect);
slouken@1895
   533
            ClientToScreen(hwnd, (LPPOINT) & rect + 1);
slouken@1895
   534
slouken@1895
   535
            window_flags = SDL_GetWindowFlags(data->windowID);
slouken@1895
   536
            if ((window_flags & SDL_WINDOW_INPUT_GRABBED) &&
slouken@1895
   537
                (window_flags & SDL_WINDOW_INPUT_FOCUS)) {
slouken@1895
   538
                ClipCursor(&rect);
slouken@1895
   539
            }
slouken@1895
   540
slouken@1895
   541
            x = rect.left;
slouken@1895
   542
            y = rect.top;
slouken@1895
   543
            SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MOVED, x, y);
slouken@1895
   544
slouken@1895
   545
            w = rect.right - rect.left;
slouken@1895
   546
            h = rect.bottom - rect.top;
slouken@1895
   547
            SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESIZED, w,
slouken@1895
   548
                                h);
slouken@1895
   549
        }
slouken@1895
   550
        break;
slouken@1895
   551
slouken@1895
   552
    case WM_SETCURSOR:
slouken@1895
   553
        {
slouken@3076
   554
            Uint16 hittest;
slouken@1895
   555
slouken@3076
   556
            hittest = LOWORD(lParam);
slouken@3076
   557
            if (hittest == HTCLIENT) {
slouken@3076
   558
                /* FIXME: Implement the cursor API */
slouken@3076
   559
                static HCURSOR cursor;
slouken@3076
   560
                if (!cursor) {
slouken@3076
   561
                    cursor = LoadCursor(NULL, IDC_ARROW);
slouken@3076
   562
                }
slouken@3076
   563
                SetCursor(cursor);
slouken@3076
   564
                return (TRUE);
slouken@3076
   565
            }
slouken@1895
   566
        }
slouken@1895
   567
        break;
slouken@1895
   568
slouken@1895
   569
        /* We are about to get palette focus! */
slouken@1895
   570
    case WM_QUERYNEWPALETTE:
slouken@1895
   571
        {
slouken@1895
   572
            /*
slouken@1895
   573
               WIN_RealizePalette(current_video);
slouken@1895
   574
               return (TRUE);
slouken@1895
   575
             */
slouken@1895
   576
        }
slouken@1895
   577
        break;
slouken@1895
   578
slouken@1895
   579
        /* Another application changed the palette */
slouken@1895
   580
    case WM_PALETTECHANGED:
slouken@1895
   581
        {
slouken@1895
   582
            /*
slouken@1895
   583
               WIN_PaletteChanged(current_video, (HWND) wParam);
slouken@1895
   584
             */
slouken@1895
   585
        }
slouken@1895
   586
        break;
slouken@1895
   587
slouken@1895
   588
        /* We were occluded, refresh our display */
slouken@1895
   589
    case WM_PAINT:
slouken@1895
   590
        {
slouken@1895
   591
            RECT rect;
slouken@1895
   592
            if (GetUpdateRect(hwnd, &rect, FALSE)) {
slouken@1895
   593
                ValidateRect(hwnd, &rect);
slouken@1895
   594
                SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_EXPOSED,
slouken@1895
   595
                                    0, 0);
slouken@1895
   596
            }
slouken@1895
   597
        }
slouken@1895
   598
        return (0);
slouken@1895
   599
slouken@3095
   600
        /* If this isn't our window, we don't need to repaint the frame.
slouken@3095
   601
           This fixes a reentrancy issue that can cause stack overflows with foreign windows.
slouken@3095
   602
           3/21/09 Mason Wheeler */
slouken@3095
   603
    case WM_NCPAINT:
slouken@3095
   604
        {
slouken@3102
   605
            if (SDL_GetWindowFlags(data->windowID) & SDL_WINDOW_FOREIGN) {
slouken@3139
   606
                return (0);
slouken@3095
   607
            }
slouken@3095
   608
            break;
slouken@3095
   609
        }
slouken@3095
   610
slouken@1895
   611
        /* We'll do our own drawing, prevent flicker */
slouken@1895
   612
    case WM_ERASEBKGND:
slouken@1895
   613
        {
slouken@1895
   614
        }
slouken@1895
   615
        return (1);
slouken@1895
   616
slouken@1895
   617
    case WM_SYSCOMMAND:
slouken@1895
   618
        {
slouken@1895
   619
            /* Don't start the screensaver or blank the monitor in fullscreen apps */
slouken@1895
   620
            if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
slouken@1895
   621
                (wParam & 0xFFF0) == SC_MONITORPOWER) {
slouken@3032
   622
                if (SDL_GetVideoDevice()->suspend_screensaver) {
slouken@1895
   623
                    return (0);
slouken@1895
   624
                }
slouken@1895
   625
            }
slouken@1895
   626
        }
slouken@1895
   627
        break;
slouken@1895
   628
slouken@1895
   629
    case WM_CLOSE:
slouken@1895
   630
        {
slouken@1895
   631
            SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_CLOSE, 0, 0);
slouken@1895
   632
        }
slouken@1895
   633
        return (0);
slouken@1895
   634
    }
slouken@1895
   635
    return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam);
slouken@1895
   636
}
slouken@1895
   637
slouken@1895
   638
void
slouken@1895
   639
WIN_PumpEvents(_THIS)
slouken@1895
   640
{
slouken@1895
   641
    MSG msg;
slouken@1895
   642
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
slouken@1895
   643
        TranslateMessage(&msg);
slouken@1895
   644
        DispatchMessage(&msg);
slouken@1895
   645
    }
slouken@1895
   646
}
slouken@1895
   647
slouken@1895
   648
static int app_registered = 0;
slouken@1895
   649
LPTSTR SDL_Appname = NULL;
slouken@1895
   650
Uint32 SDL_Appstyle = 0;
slouken@1895
   651
HINSTANCE SDL_Instance = NULL;
slouken@1895
   652
slouken@1895
   653
/* Register the class for this application */
slouken@1895
   654
int
slouken@1895
   655
SDL_RegisterApp(char *name, Uint32 style, void *hInst)
slouken@1895
   656
{
slouken@1895
   657
    WNDCLASS class;
slouken@1895
   658
slouken@1895
   659
    /* Only do this once... */
slouken@1895
   660
    if (app_registered) {
slouken@1895
   661
        ++app_registered;
slouken@1895
   662
        return (0);
slouken@1895
   663
    }
slouken@1895
   664
    if (!name && !SDL_Appname) {
slouken@1895
   665
        name = "SDL_app";
slouken@1895
   666
        SDL_Appstyle = (CS_BYTEALIGNCLIENT | CS_OWNDC);
slouken@1895
   667
        SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
slouken@1895
   668
    }
slouken@1895
   669
slouken@1895
   670
    if (name) {
slouken@1895
   671
        SDL_Appname = WIN_UTF8ToString(name);
slouken@1895
   672
        SDL_Appstyle = style;
slouken@1895
   673
        SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
slouken@1895
   674
    }
slouken@1895
   675
slouken@1895
   676
    /* Register the application class */
slouken@1895
   677
    class.hCursor = NULL;
slouken@2710
   678
    class.hIcon =
slouken@2710
   679
        LoadImage(SDL_Instance, SDL_Appname, IMAGE_ICON, 0, 0,
slouken@2710
   680
                  LR_DEFAULTCOLOR);
slouken@1895
   681
    class.lpszMenuName = NULL;
slouken@1895
   682
    class.lpszClassName = SDL_Appname;
slouken@1895
   683
    class.hbrBackground = NULL;
slouken@1895
   684
    class.hInstance = SDL_Instance;
slouken@1895
   685
    class.style = SDL_Appstyle;
slouken@1895
   686
    class.lpfnWndProc = DefWindowProc;
slouken@1895
   687
    class.cbWndExtra = 0;
slouken@1895
   688
    class.cbClsExtra = 0;
slouken@1895
   689
    if (!RegisterClass(&class)) {
slouken@1895
   690
        SDL_SetError("Couldn't register application class");
slouken@1895
   691
        return (-1);
slouken@1895
   692
    }
slouken@1895
   693
slouken@1895
   694
    app_registered = 1;
slouken@1895
   695
    return (0);
slouken@1895
   696
}
slouken@1895
   697
slouken@1895
   698
/* Unregisters the windowclass registered in SDL_RegisterApp above. */
slouken@1895
   699
void
slouken@1895
   700
SDL_UnregisterApp()
slouken@1895
   701
{
slouken@1895
   702
    WNDCLASS class;
slouken@1895
   703
slouken@1895
   704
    /* SDL_RegisterApp might not have been called before */
slouken@1895
   705
    if (!app_registered) {
slouken@1895
   706
        return;
slouken@1895
   707
    }
slouken@1895
   708
    --app_registered;
slouken@1895
   709
    if (app_registered == 0) {
slouken@1895
   710
        /* Check for any registered window classes. */
slouken@1895
   711
        if (GetClassInfo(SDL_Instance, SDL_Appname, &class)) {
slouken@1895
   712
            UnregisterClass(SDL_Appname, SDL_Instance);
slouken@1895
   713
        }
slouken@1895
   714
        SDL_free(SDL_Appname);
slouken@1895
   715
        SDL_Appname = NULL;
slouken@1895
   716
    }
slouken@1895
   717
}
slouken@1895
   718
slouken@1895
   719
/* Sets an error message based on GetLastError() */
slouken@1895
   720
void
slouken@1895
   721
WIN_SetError(const char *prefix)
slouken@1895
   722
{
slouken@1895
   723
    TCHAR buffer[1024];
slouken@1895
   724
    char *message;
slouken@2710
   725
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
slouken@2710
   726
                  buffer, SDL_arraysize(buffer), NULL);
slouken@1895
   727
    message = WIN_StringToUTF8(buffer);
slouken@1895
   728
    SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ":" : "", message);
slouken@1895
   729
    SDL_free(message);
slouken@1895
   730
}
slouken@1895
   731
slouken@1895
   732
/* vi: set ts=4 sw=4 expandtab: */