src/video/win32/SDL_win32events.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 06 Jul 2006 07:17:11 +0000
branchSDL-1.3
changeset 1724 6c63fc2bd986
parent 1722 5daa04d862f1
child 1727 90a3e0fccb88
permissions -rw-r--r--
Proof of concept done - Win32 GDI implementation mostly complete.
slouken@1712
     1
/*
slouken@1712
     2
    SDL - Simple DirectMedia Layer
slouken@1712
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@1712
     4
slouken@1712
     5
    This library is free software; you can redistribute it and/or
slouken@1712
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1712
     7
    License as published by the Free Software Foundation; either
slouken@1712
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@1712
     9
slouken@1712
    10
    This library is distributed in the hope that it will be useful,
slouken@1712
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1712
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1712
    13
    Lesser General Public License for more details.
slouken@1712
    14
slouken@1712
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1712
    16
    License along with this library; if not, write to the Free Software
slouken@1712
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@1712
    18
slouken@1712
    19
    Sam Lantinga
slouken@1712
    20
    slouken@libsdl.org
slouken@1712
    21
*/
slouken@1712
    22
#include "SDL_config.h"
slouken@1712
    23
slouken@1712
    24
#include "SDL_win32video.h"
slouken@1724
    25
#include "SDL_version.h"
slouken@1724
    26
#include "SDL_syswm.h"
slouken@1724
    27
#include "SDL_vkeys.h"
slouken@1722
    28
#include "../../events/SDL_events_c.h"
slouken@1712
    29
slouken@1724
    30
/*#define WMMSG_DEBUG*/
slouken@1724
    31
#ifdef WMMSG_DEBUG
slouken@1724
    32
#include "wmmsg.h"
slouken@1724
    33
#endif
slouken@1724
    34
slouken@1724
    35
/* Masks for processing the windows KEYDOWN and KEYUP messages */
slouken@1724
    36
#define REPEATED_KEYMASK	(1<<30)
slouken@1724
    37
#define EXTENDED_KEYMASK	(1<<24)
slouken@1724
    38
slouken@1724
    39
slouken@1724
    40
static SDLKey
slouken@1724
    41
TranslateKey(WPARAM vkey)
slouken@1724
    42
{
slouken@1724
    43
    SDLKey key;
slouken@1724
    44
slouken@1724
    45
    /* FIXME: Assign vkey directly to key if in ASCII range */
slouken@1724
    46
    switch (vkey) {
slouken@1724
    47
    case VK_BACK:
slouken@1724
    48
        key = SDLK_BACKSPACE;
slouken@1724
    49
        break;
slouken@1724
    50
    case VK_TAB:
slouken@1724
    51
        key = SDLK_TAB;
slouken@1724
    52
        break;
slouken@1724
    53
    case VK_CLEAR:
slouken@1724
    54
        key = SDLK_CLEAR;
slouken@1724
    55
        break;
slouken@1724
    56
    case VK_RETURN:
slouken@1724
    57
        key = SDLK_RETURN;
slouken@1724
    58
        break;
slouken@1724
    59
    case VK_PAUSE:
slouken@1724
    60
        key = SDLK_PAUSE;
slouken@1724
    61
        break;
slouken@1724
    62
    case VK_ESCAPE:
slouken@1724
    63
        key = SDLK_ESCAPE;
slouken@1724
    64
        break;
slouken@1724
    65
    case VK_SPACE:
slouken@1724
    66
        key = SDLK_SPACE;
slouken@1724
    67
        break;
slouken@1724
    68
    case VK_APOSTROPHE:
slouken@1724
    69
        key = SDLK_QUOTE;
slouken@1724
    70
        break;
slouken@1724
    71
    case VK_COMMA:
slouken@1724
    72
        key = SDLK_COMMA;
slouken@1724
    73
        break;
slouken@1724
    74
    case VK_MINUS:
slouken@1724
    75
        key = SDLK_MINUS;
slouken@1724
    76
        break;
slouken@1724
    77
    case VK_PERIOD:
slouken@1724
    78
        key = SDLK_PERIOD;
slouken@1724
    79
        break;
slouken@1724
    80
    case VK_SLASH:
slouken@1724
    81
        key = SDLK_SLASH;
slouken@1724
    82
        break;
slouken@1724
    83
    case VK_0:
slouken@1724
    84
        key = SDLK_0;
slouken@1724
    85
        break;
slouken@1724
    86
    case VK_1:
slouken@1724
    87
        key = SDLK_1;
slouken@1724
    88
        break;
slouken@1724
    89
    case VK_2:
slouken@1724
    90
        key = SDLK_2;
slouken@1724
    91
        break;
slouken@1724
    92
    case VK_3:
slouken@1724
    93
        key = SDLK_3;
slouken@1724
    94
        break;
slouken@1724
    95
    case VK_4:
slouken@1724
    96
        key = SDLK_4;
slouken@1724
    97
        break;
slouken@1724
    98
    case VK_5:
slouken@1724
    99
        key = SDLK_5;
slouken@1724
   100
        break;
slouken@1724
   101
    case VK_6:
slouken@1724
   102
        key = SDLK_6;
slouken@1724
   103
        break;
slouken@1724
   104
    case VK_7:
slouken@1724
   105
        key = SDLK_7;
slouken@1724
   106
        break;
slouken@1724
   107
    case VK_8:
slouken@1724
   108
        key = SDLK_8;
slouken@1724
   109
        break;
slouken@1724
   110
    case VK_9:
slouken@1724
   111
        key = SDLK_9;
slouken@1724
   112
        break;
slouken@1724
   113
    case VK_SEMICOLON:
slouken@1724
   114
        key = SDLK_SEMICOLON;
slouken@1724
   115
        break;
slouken@1724
   116
    case VK_EQUALS:
slouken@1724
   117
        key = SDLK_EQUALS;
slouken@1724
   118
        break;
slouken@1724
   119
    case VK_LBRACKET:
slouken@1724
   120
        key = SDLK_LEFTBRACKET;
slouken@1724
   121
        break;
slouken@1724
   122
    case VK_BACKSLASH:
slouken@1724
   123
        key = SDLK_BACKSLASH;
slouken@1724
   124
        break;
slouken@1724
   125
    case VK_OEM_102:
slouken@1724
   126
        key = SDLK_LESS;
slouken@1724
   127
        break;
slouken@1724
   128
    case VK_RBRACKET:
slouken@1724
   129
        key = SDLK_RIGHTBRACKET;
slouken@1724
   130
        break;
slouken@1724
   131
    case VK_GRAVE:
slouken@1724
   132
        key = SDLK_BACKQUOTE;
slouken@1724
   133
        break;
slouken@1724
   134
    case VK_BACKTICK:
slouken@1724
   135
        key = SDLK_BACKQUOTE;
slouken@1724
   136
        break;
slouken@1724
   137
    case VK_A:
slouken@1724
   138
        key = SDLK_a;
slouken@1724
   139
        break;
slouken@1724
   140
    case VK_B:
slouken@1724
   141
        key = SDLK_b;
slouken@1724
   142
        break;
slouken@1724
   143
    case VK_C:
slouken@1724
   144
        key = SDLK_c;
slouken@1724
   145
        break;
slouken@1724
   146
    case VK_D:
slouken@1724
   147
        key = SDLK_d;
slouken@1724
   148
        break;
slouken@1724
   149
    case VK_E:
slouken@1724
   150
        key = SDLK_e;
slouken@1724
   151
        break;
slouken@1724
   152
    case VK_F:
slouken@1724
   153
        key = SDLK_f;
slouken@1724
   154
        break;
slouken@1724
   155
    case VK_G:
slouken@1724
   156
        key = SDLK_g;
slouken@1724
   157
        break;
slouken@1724
   158
    case VK_H:
slouken@1724
   159
        key = SDLK_h;
slouken@1724
   160
        break;
slouken@1724
   161
    case VK_I:
slouken@1724
   162
        key = SDLK_i;
slouken@1724
   163
        break;
slouken@1724
   164
    case VK_J:
slouken@1724
   165
        key = SDLK_j;
slouken@1724
   166
        break;
slouken@1724
   167
    case VK_K:
slouken@1724
   168
        key = SDLK_k;
slouken@1724
   169
        break;
slouken@1724
   170
    case VK_L:
slouken@1724
   171
        key = SDLK_l;
slouken@1724
   172
        break;
slouken@1724
   173
    case VK_M:
slouken@1724
   174
        key = SDLK_m;
slouken@1724
   175
        break;
slouken@1724
   176
    case VK_N:
slouken@1724
   177
        key = SDLK_n;
slouken@1724
   178
        break;
slouken@1724
   179
    case VK_O:
slouken@1724
   180
        key = SDLK_o;
slouken@1724
   181
        break;
slouken@1724
   182
    case VK_P:
slouken@1724
   183
        key = SDLK_p;
slouken@1724
   184
        break;
slouken@1724
   185
    case VK_Q:
slouken@1724
   186
        key = SDLK_q;
slouken@1724
   187
        break;
slouken@1724
   188
    case VK_R:
slouken@1724
   189
        key = SDLK_r;
slouken@1724
   190
        break;
slouken@1724
   191
    case VK_S:
slouken@1724
   192
        key = SDLK_s;
slouken@1724
   193
        break;
slouken@1724
   194
    case VK_T:
slouken@1724
   195
        key = SDLK_t;
slouken@1724
   196
        break;
slouken@1724
   197
    case VK_U:
slouken@1724
   198
        key = SDLK_u;
slouken@1724
   199
        break;
slouken@1724
   200
    case VK_V:
slouken@1724
   201
        key = SDLK_v;
slouken@1724
   202
        break;
slouken@1724
   203
    case VK_W:
slouken@1724
   204
        key = SDLK_w;
slouken@1724
   205
        break;
slouken@1724
   206
    case VK_X:
slouken@1724
   207
        key = SDLK_x;
slouken@1724
   208
        break;
slouken@1724
   209
    case VK_Y:
slouken@1724
   210
        key = SDLK_y;
slouken@1724
   211
        break;
slouken@1724
   212
    case VK_Z:
slouken@1724
   213
        key = SDLK_z;
slouken@1724
   214
        break;
slouken@1724
   215
    case VK_DELETE:
slouken@1724
   216
        key = SDLK_DELETE;
slouken@1724
   217
        break;
slouken@1724
   218
    case VK_NUMPAD0:
slouken@1724
   219
        key = SDLK_KP0;
slouken@1724
   220
        break;
slouken@1724
   221
    case VK_NUMPAD1:
slouken@1724
   222
        key = SDLK_KP1;
slouken@1724
   223
        break;
slouken@1724
   224
    case VK_NUMPAD2:
slouken@1724
   225
        key = SDLK_KP2;
slouken@1724
   226
        break;
slouken@1724
   227
    case VK_NUMPAD3:
slouken@1724
   228
        key = SDLK_KP3;
slouken@1724
   229
        break;
slouken@1724
   230
    case VK_NUMPAD4:
slouken@1724
   231
        key = SDLK_KP4;
slouken@1724
   232
        break;
slouken@1724
   233
    case VK_NUMPAD5:
slouken@1724
   234
        key = SDLK_KP5;
slouken@1724
   235
        break;
slouken@1724
   236
    case VK_NUMPAD6:
slouken@1724
   237
        key = SDLK_KP6;
slouken@1724
   238
        break;
slouken@1724
   239
    case VK_NUMPAD7:
slouken@1724
   240
        key = SDLK_KP7;
slouken@1724
   241
        break;
slouken@1724
   242
    case VK_NUMPAD8:
slouken@1724
   243
        key = SDLK_KP8;
slouken@1724
   244
        break;
slouken@1724
   245
    case VK_NUMPAD9:
slouken@1724
   246
        key = SDLK_KP9;
slouken@1724
   247
        break;
slouken@1724
   248
    case VK_DECIMAL:
slouken@1724
   249
        key = SDLK_KP_PERIOD;
slouken@1724
   250
        break;
slouken@1724
   251
    case VK_DIVIDE:
slouken@1724
   252
        key = SDLK_KP_DIVIDE;
slouken@1724
   253
        break;
slouken@1724
   254
    case VK_MULTIPLY:
slouken@1724
   255
        key = SDLK_KP_MULTIPLY;
slouken@1724
   256
        break;
slouken@1724
   257
    case VK_SUBTRACT:
slouken@1724
   258
        key = SDLK_KP_MINUS;
slouken@1724
   259
        break;
slouken@1724
   260
    case VK_ADD:
slouken@1724
   261
        key = SDLK_KP_PLUS;
slouken@1724
   262
        break;
slouken@1724
   263
    case VK_UP:
slouken@1724
   264
        key = SDLK_UP;
slouken@1724
   265
        break;
slouken@1724
   266
    case VK_DOWN:
slouken@1724
   267
        key = SDLK_DOWN;
slouken@1724
   268
        break;
slouken@1724
   269
    case VK_RIGHT:
slouken@1724
   270
        key = SDLK_RIGHT;
slouken@1724
   271
        break;
slouken@1724
   272
    case VK_LEFT:
slouken@1724
   273
        key = SDLK_LEFT;
slouken@1724
   274
        break;
slouken@1724
   275
    case VK_INSERT:
slouken@1724
   276
        key = SDLK_INSERT;
slouken@1724
   277
        break;
slouken@1724
   278
    case VK_HOME:
slouken@1724
   279
        key = SDLK_HOME;
slouken@1724
   280
        break;
slouken@1724
   281
    case VK_END:
slouken@1724
   282
        key = SDLK_END;
slouken@1724
   283
        break;
slouken@1724
   284
    case VK_PRIOR:
slouken@1724
   285
        key = SDLK_PAGEUP;
slouken@1724
   286
        break;
slouken@1724
   287
    case VK_NEXT:
slouken@1724
   288
        key = SDLK_PAGEDOWN;
slouken@1724
   289
        break;
slouken@1724
   290
    case VK_F1:
slouken@1724
   291
        key = SDLK_F1;
slouken@1724
   292
        break;
slouken@1724
   293
    case VK_F2:
slouken@1724
   294
        key = SDLK_F2;
slouken@1724
   295
        break;
slouken@1724
   296
    case VK_F3:
slouken@1724
   297
        key = SDLK_F3;
slouken@1724
   298
        break;
slouken@1724
   299
    case VK_F4:
slouken@1724
   300
        key = SDLK_F4;
slouken@1724
   301
        break;
slouken@1724
   302
    case VK_F5:
slouken@1724
   303
        key = SDLK_F5;
slouken@1724
   304
        break;
slouken@1724
   305
    case VK_F6:
slouken@1724
   306
        key = SDLK_F6;
slouken@1724
   307
        break;
slouken@1724
   308
    case VK_F7:
slouken@1724
   309
        key = SDLK_F7;
slouken@1724
   310
        break;
slouken@1724
   311
    case VK_F8:
slouken@1724
   312
        key = SDLK_F8;
slouken@1724
   313
        break;
slouken@1724
   314
    case VK_F9:
slouken@1724
   315
        key = SDLK_F9;
slouken@1724
   316
        break;
slouken@1724
   317
    case VK_F10:
slouken@1724
   318
        key = SDLK_F10;
slouken@1724
   319
        break;
slouken@1724
   320
    case VK_F11:
slouken@1724
   321
        key = SDLK_F11;
slouken@1724
   322
        break;
slouken@1724
   323
    case VK_F12:
slouken@1724
   324
        key = SDLK_F12;
slouken@1724
   325
        break;
slouken@1724
   326
    case VK_F13:
slouken@1724
   327
        key = SDLK_F13;
slouken@1724
   328
        break;
slouken@1724
   329
    case VK_F14:
slouken@1724
   330
        key = SDLK_F14;
slouken@1724
   331
        break;
slouken@1724
   332
    case VK_F15:
slouken@1724
   333
        key = SDLK_F15;
slouken@1724
   334
        break;
slouken@1724
   335
    case VK_NUMLOCK:
slouken@1724
   336
        key = SDLK_NUMLOCK;
slouken@1724
   337
        break;
slouken@1724
   338
    case VK_CAPITAL:
slouken@1724
   339
        key = SDLK_CAPSLOCK;
slouken@1724
   340
        break;
slouken@1724
   341
    case VK_SCROLL:
slouken@1724
   342
        key = SDLK_SCROLLOCK;
slouken@1724
   343
        break;
slouken@1724
   344
    case VK_RSHIFT:
slouken@1724
   345
        key = SDLK_RSHIFT;
slouken@1724
   346
        break;
slouken@1724
   347
    case VK_LSHIFT:
slouken@1724
   348
        key = SDLK_LSHIFT;
slouken@1724
   349
        break;
slouken@1724
   350
    case VK_RCONTROL:
slouken@1724
   351
        key = SDLK_RCTRL;
slouken@1724
   352
        break;
slouken@1724
   353
    case VK_LCONTROL:
slouken@1724
   354
        key = SDLK_LCTRL;
slouken@1724
   355
        break;
slouken@1724
   356
    case VK_RMENU:
slouken@1724
   357
        key = SDLK_RALT;
slouken@1724
   358
        break;
slouken@1724
   359
    case VK_LMENU:
slouken@1724
   360
        key = SDLK_LALT;
slouken@1724
   361
        break;
slouken@1724
   362
    case VK_RWIN:
slouken@1724
   363
        key = SDLK_RSUPER;
slouken@1724
   364
        break;
slouken@1724
   365
    case VK_LWIN:
slouken@1724
   366
        key = SDLK_LSUPER;
slouken@1724
   367
        break;
slouken@1724
   368
    case VK_HELP:
slouken@1724
   369
        key = SDLK_HELP;
slouken@1724
   370
        break;
slouken@1724
   371
    case VK_PRINT:
slouken@1724
   372
        key = SDLK_PRINT;
slouken@1724
   373
        break;
slouken@1724
   374
    case VK_SNAPSHOT:
slouken@1724
   375
        key = SDLK_PRINT;
slouken@1724
   376
        break;
slouken@1724
   377
    case VK_CANCEL:
slouken@1724
   378
        key = SDLK_BREAK;
slouken@1724
   379
        break;
slouken@1724
   380
    case VK_APPS:
slouken@1724
   381
        key = SDLK_MENU;
slouken@1724
   382
        break;
slouken@1724
   383
    default:
slouken@1724
   384
        key = SDLK_UNKNOWN;
slouken@1724
   385
        break;
slouken@1724
   386
    }
slouken@1724
   387
    return key;
slouken@1724
   388
}
slouken@1718
   389
slouken@1719
   390
LRESULT CALLBACK
slouken@1719
   391
WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
slouken@1718
   392
{
slouken@1719
   393
    SDL_WindowData *data;
slouken@1719
   394
slouken@1719
   395
    /* Get the window data for the window */
slouken@1719
   396
    data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData"));
slouken@1719
   397
    if (!data) {
slouken@1719
   398
        return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
slouken@1719
   399
    }
slouken@1724
   400
#ifdef WMMSG_DEBUG
slouken@1724
   401
    fprintf(stderr, "Received windows message:  ");
slouken@1724
   402
    if (msg > MAX_WMMSG) {
slouken@1724
   403
        fprintf(stderr, "%d", msg);
slouken@1724
   404
    } else {
slouken@1724
   405
        fprintf(stderr, "%s", wmtab[msg]);
slouken@1724
   406
    }
slouken@1724
   407
    fprintf(stderr, " -- 0x%X, 0x%X\n", wParam, lParam);
slouken@1724
   408
#endif
slouken@1724
   409
slouken@1724
   410
    /* Send a SDL_SYSWMEVENT if the application wants them */
slouken@1724
   411
    if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) {
slouken@1724
   412
        SDL_SysWMmsg wmmsg;
slouken@1724
   413
slouken@1724
   414
        SDL_VERSION(&wmmsg.version);
slouken@1724
   415
        wmmsg.hwnd = hwnd;
slouken@1724
   416
        wmmsg.msg = msg;
slouken@1724
   417
        wmmsg.wParam = wParam;
slouken@1724
   418
        wmmsg.lParam = lParam;
slouken@1724
   419
        SDL_SendSysWMEvent(&wmmsg);
slouken@1724
   420
    }
slouken@1724
   421
slouken@1722
   422
    switch (msg) {
slouken@1719
   423
slouken@1722
   424
    case WM_ACTIVATE:
slouken@1722
   425
        {
slouken@1724
   426
            int index;
slouken@1724
   427
            SDL_Keyboard *keyboard;
slouken@1722
   428
            BOOL minimized;
slouken@1722
   429
slouken@1722
   430
            minimized = HIWORD(wParam);
slouken@1724
   431
            index = data->videodata->keyboard;
slouken@1724
   432
            keyboard = SDL_GetKeyboard(index);
slouken@1722
   433
            if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
slouken@1724
   434
                SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_SHOWN,
slouken@1724
   435
                                    0, 0);
slouken@1724
   436
                SDL_SendWindowEvent(data->windowID,
slouken@1724
   437
                                    SDL_WINDOWEVENT_RESTORED, 0, 0);
slouken@1722
   438
                if (IsZoomed(hwnd)) {
slouken@1724
   439
                    SDL_SendWindowEvent(data->windowID,
slouken@1724
   440
                                        SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
slouken@1722
   441
                }
slouken@1724
   442
                if (keyboard && keyboard->focus != data->windowID) {
slouken@1724
   443
                    SDL_SetKeyboardFocus(index, data->windowID);
slouken@1724
   444
                }
slouken@1722
   445
                /* FIXME: Restore mode state (mode, gamma, grab) */
slouken@1722
   446
                /* FIXME: Update keyboard state */
slouken@1722
   447
            } else {
slouken@1724
   448
                if (keyboard && keyboard->focus == data->windowID) {
slouken@1724
   449
                    SDL_SetKeyboardFocus(index, 0);
slouken@1724
   450
                }
slouken@1722
   451
                if (minimized) {
slouken@1724
   452
                    SDL_SendWindowEvent(data->windowID,
slouken@1724
   453
                                        SDL_WINDOWEVENT_MINIMIZED, 0, 0);
slouken@1722
   454
                }
slouken@1722
   455
                /* FIXME: Restore desktop state (mode, gamma, grab) */
slouken@1722
   456
            }
slouken@1722
   457
            return (0);
slouken@1722
   458
        }
slouken@1722
   459
        break;
slouken@1722
   460
slouken@1722
   461
    case WM_MOUSEMOVE:
slouken@1722
   462
        {
slouken@1722
   463
            int index;
slouken@1722
   464
            SDL_Mouse *mouse;
slouken@1724
   465
            int x, y;
slouken@1722
   466
slouken@1724
   467
            index = data->videodata->mouse;
slouken@1724
   468
            mouse = SDL_GetMouse(index);
slouken@1724
   469
slouken@1724
   470
            if (mouse->focus != data->windowID) {
slouken@1722
   471
                TRACKMOUSEEVENT tme;
slouken@1722
   472
slouken@1722
   473
                tme.cbSize = sizeof(tme);
slouken@1722
   474
                tme.dwFlags = TME_LEAVE;
slouken@1722
   475
                tme.hwndTrack = hwnd;
slouken@1722
   476
                TrackMouseEvent(&tme);
slouken@1722
   477
slouken@1724
   478
                SDL_SetMouseFocus(index, data->windowID);
slouken@1722
   479
            }
slouken@1722
   480
slouken@1724
   481
            /* mouse has moved within the window */
slouken@1724
   482
            x = LOWORD(lParam);
slouken@1724
   483
            y = HIWORD(lParam);
slouken@1724
   484
            if (mouse->relative_mode) {
slouken@1724
   485
                int w, h;
slouken@1724
   486
                POINT center;
slouken@1724
   487
                SDL_GetWindowSize(data->windowID, &w, &h);
slouken@1724
   488
                center.x = (w / 2);
slouken@1724
   489
                center.y = (h / 2);
slouken@1724
   490
                x -= center.x;
slouken@1724
   491
                y -= center.y;
slouken@1724
   492
                if (x || y) {
slouken@1724
   493
                    ClientToScreen(hwnd, &center);
slouken@1724
   494
                    SetCursorPos(center.x, center.y);
slouken@1724
   495
                    SDL_SendMouseMotion(index, 1, x, y);
slouken@1722
   496
                }
slouken@1724
   497
            } else {
slouken@1724
   498
                SDL_SendMouseMotion(index, 0, x, y);
slouken@1722
   499
            }
slouken@1722
   500
        }
slouken@1722
   501
        return (0);
slouken@1722
   502
slouken@1722
   503
    case WM_MOUSELEAVE:
slouken@1722
   504
        {
slouken@1724
   505
            int index;
slouken@1724
   506
            SDL_Mouse *mouse;
slouken@1724
   507
slouken@1724
   508
            index = data->videodata->mouse;
slouken@1724
   509
            mouse = SDL_GetMouse(index);
slouken@1724
   510
slouken@1724
   511
            if (mouse->focus == data->windowID) {
slouken@1724
   512
                SDL_SetMouseFocus(index, 0);
slouken@1724
   513
            }
slouken@1722
   514
        }
slouken@1722
   515
        return (0);
slouken@1722
   516
slouken@1722
   517
    case WM_LBUTTONDOWN:
slouken@1722
   518
    case WM_LBUTTONUP:
slouken@1722
   519
    case WM_MBUTTONDOWN:
slouken@1722
   520
    case WM_MBUTTONUP:
slouken@1722
   521
    case WM_RBUTTONDOWN:
slouken@1722
   522
    case WM_RBUTTONUP:
slouken@1722
   523
        {
slouken@1724
   524
            int index;
slouken@1724
   525
            SDL_Mouse *mouse;
slouken@1722
   526
            Uint8 button, state;
slouken@1722
   527
slouken@1722
   528
            /* DJM:
slouken@1722
   529
               We want the SDL window to take focus so that
slouken@1722
   530
               it acts like a normal windows "component"
slouken@1722
   531
               (e.g. gains keyboard focus on a mouse click).
slouken@1722
   532
             */
slouken@1724
   533
            SetFocus(hwnd);
slouken@1724
   534
slouken@1724
   535
            index = data->videodata->mouse;
slouken@1724
   536
            mouse = SDL_GetMouse(index);
slouken@1722
   537
slouken@1722
   538
            /* Figure out which button to use */
slouken@1722
   539
            switch (msg) {
slouken@1722
   540
            case WM_LBUTTONDOWN:
slouken@1722
   541
                button = SDL_BUTTON_LEFT;
slouken@1722
   542
                state = SDL_PRESSED;
slouken@1722
   543
                break;
slouken@1722
   544
            case WM_LBUTTONUP:
slouken@1722
   545
                button = SDL_BUTTON_LEFT;
slouken@1722
   546
                state = SDL_RELEASED;
slouken@1722
   547
                break;
slouken@1722
   548
            case WM_MBUTTONDOWN:
slouken@1722
   549
                button = SDL_BUTTON_MIDDLE;
slouken@1722
   550
                state = SDL_PRESSED;
slouken@1722
   551
                break;
slouken@1722
   552
            case WM_MBUTTONUP:
slouken@1722
   553
                button = SDL_BUTTON_MIDDLE;
slouken@1722
   554
                state = SDL_RELEASED;
slouken@1722
   555
                break;
slouken@1722
   556
            case WM_RBUTTONDOWN:
slouken@1722
   557
                button = SDL_BUTTON_RIGHT;
slouken@1722
   558
                state = SDL_PRESSED;
slouken@1722
   559
                break;
slouken@1722
   560
            case WM_RBUTTONUP:
slouken@1722
   561
                button = SDL_BUTTON_RIGHT;
slouken@1722
   562
                state = SDL_RELEASED;
slouken@1722
   563
                break;
slouken@1722
   564
            default:
slouken@1722
   565
                /* Eh? Unknown button? */
slouken@1722
   566
                return (0);
slouken@1722
   567
            }
slouken@1722
   568
            if (state == SDL_PRESSED) {
slouken@1722
   569
                /* Grab mouse so we get up events */
slouken@1724
   570
                if (++data->mouse_pressed > 0) {
slouken@1722
   571
                    SetCapture(hwnd);
slouken@1722
   572
                }
slouken@1722
   573
            } else {
slouken@1722
   574
                /* Release mouse after all up events */
slouken@1724
   575
                if (--data->mouse_pressed <= 0) {
slouken@1722
   576
                    ReleaseCapture();
slouken@1724
   577
                    data->mouse_pressed = 0;
slouken@1722
   578
                }
slouken@1722
   579
            }
slouken@1724
   580
slouken@1724
   581
            if (!mouse->relative_mode) {
slouken@1724
   582
                int x, y;
slouken@1724
   583
                x = LOWORD(lParam);
slouken@1724
   584
                y = HIWORD(lParam);
slouken@1724
   585
                SDL_SendMouseMotion(index, 0, x, y);
slouken@1724
   586
            }
slouken@1724
   587
            SDL_SendMouseButton(index, state, button);
slouken@1722
   588
        }
slouken@1722
   589
        return (0);
slouken@1722
   590
slouken@1724
   591
    case WM_MOUSEWHEEL:
slouken@1724
   592
        {
slouken@1724
   593
            int index;
slouken@1724
   594
            int motion = (short) HIWORD(wParam);
slouken@1722
   595
slouken@1724
   596
            index = data->videodata->mouse;
slouken@1724
   597
            SDL_SendMouseWheel(index, motion);
slouken@1722
   598
        }
slouken@1722
   599
        return (0);
slouken@1722
   600
slouken@1724
   601
    case WM_SYSKEYDOWN:
slouken@1724
   602
    case WM_KEYDOWN:
slouken@1724
   603
        {
slouken@1724
   604
            int index;
slouken@1724
   605
slouken@1724
   606
            /* Ignore repeated keys */
slouken@1724
   607
            if (lParam & REPEATED_KEYMASK) {
slouken@1724
   608
                return (0);
slouken@1724
   609
            }
slouken@1724
   610
slouken@1724
   611
            index = data->videodata->keyboard;
slouken@1724
   612
            switch (wParam) {
slouken@1724
   613
            case VK_CONTROL:
slouken@1724
   614
                if (lParam & EXTENDED_KEYMASK)
slouken@1724
   615
                    wParam = VK_RCONTROL;
slouken@1724
   616
                else
slouken@1724
   617
                    wParam = VK_LCONTROL;
slouken@1724
   618
                break;
slouken@1724
   619
            case VK_SHIFT:
slouken@1724
   620
                /* EXTENDED trick doesn't work here */
slouken@1724
   621
                {
slouken@1724
   622
                    Uint8 *state = SDL_GetKeyState(NULL);
slouken@1724
   623
                    if (state[SDLK_LSHIFT] == SDL_RELEASED
slouken@1724
   624
                        && (GetKeyState(VK_LSHIFT) & 0x8000)) {
slouken@1724
   625
                        wParam = VK_LSHIFT;
slouken@1724
   626
                    } else if (state[SDLK_RSHIFT] == SDL_RELEASED
slouken@1724
   627
                               && (GetKeyState(VK_RSHIFT) & 0x8000)) {
slouken@1724
   628
                        wParam = VK_RSHIFT;
slouken@1724
   629
                    } else {
slouken@1724
   630
                        /* Probably a key repeat */
slouken@1724
   631
                        return (0);
slouken@1724
   632
                    }
slouken@1724
   633
                }
slouken@1724
   634
                break;
slouken@1724
   635
            case VK_MENU:
slouken@1724
   636
                if (lParam & EXTENDED_KEYMASK)
slouken@1724
   637
                    wParam = VK_RMENU;
slouken@1724
   638
                else
slouken@1724
   639
                    wParam = VK_LMENU;
slouken@1724
   640
                break;
slouken@1724
   641
            }
slouken@1724
   642
            SDL_SendKeyboardKey(index, SDL_PRESSED, (Uint8) HIWORD(lParam),
slouken@1724
   643
                                TranslateKey(wParam));
slouken@1724
   644
        }
slouken@1724
   645
        return (0);
slouken@1724
   646
slouken@1724
   647
    case WM_SYSKEYUP:
slouken@1724
   648
    case WM_KEYUP:
slouken@1724
   649
        {
slouken@1724
   650
            int index;
slouken@1724
   651
slouken@1724
   652
            index = data->videodata->keyboard;
slouken@1724
   653
            switch (wParam) {
slouken@1724
   654
            case VK_CONTROL:
slouken@1724
   655
                if (lParam & EXTENDED_KEYMASK)
slouken@1724
   656
                    wParam = VK_RCONTROL;
slouken@1724
   657
                else
slouken@1724
   658
                    wParam = VK_LCONTROL;
slouken@1724
   659
                break;
slouken@1724
   660
            case VK_SHIFT:
slouken@1724
   661
                /* EXTENDED trick doesn't work here */
slouken@1724
   662
                {
slouken@1724
   663
                    Uint8 *state = SDL_GetKeyState(NULL);
slouken@1724
   664
                    if (state[SDLK_LSHIFT] == SDL_PRESSED
slouken@1724
   665
                        && !(GetKeyState(VK_LSHIFT) & 0x8000)) {
slouken@1724
   666
                        wParam = VK_LSHIFT;
slouken@1724
   667
                    } else if (state[SDLK_RSHIFT] == SDL_PRESSED
slouken@1724
   668
                               && !(GetKeyState(VK_RSHIFT) & 0x8000)) {
slouken@1724
   669
                        wParam = VK_RSHIFT;
slouken@1724
   670
                    } else {
slouken@1724
   671
                        /* Probably a key repeat */
slouken@1724
   672
                        return (0);
slouken@1724
   673
                    }
slouken@1724
   674
                }
slouken@1724
   675
                break;
slouken@1724
   676
            case VK_MENU:
slouken@1724
   677
                if (lParam & EXTENDED_KEYMASK)
slouken@1724
   678
                    wParam = VK_RMENU;
slouken@1724
   679
                else
slouken@1724
   680
                    wParam = VK_LMENU;
slouken@1724
   681
                break;
slouken@1724
   682
            }
slouken@1724
   683
            /* Windows only reports keyup for print screen */
slouken@1724
   684
            if (wParam == VK_SNAPSHOT
slouken@1724
   685
                && SDL_GetKeyState(NULL)[SDLK_PRINT] == SDL_RELEASED) {
slouken@1724
   686
                SDL_SendKeyboardKey(index, SDL_PRESSED,
slouken@1724
   687
                                    (Uint8) HIWORD(lParam),
slouken@1724
   688
                                    TranslateKey(wParam));
slouken@1724
   689
            }
slouken@1724
   690
            SDL_SendKeyboardKey(index, SDL_RELEASED, (Uint8) HIWORD(lParam),
slouken@1724
   691
                                TranslateKey(wParam));
slouken@1724
   692
        }
slouken@1724
   693
        return (0);
slouken@1724
   694
slouken@1722
   695
    case WM_GETMINMAXINFO:
slouken@1722
   696
        {
slouken@1722
   697
            MINMAXINFO *info;
slouken@1722
   698
            RECT size;
slouken@1722
   699
            int x, y;
slouken@1724
   700
            int w, h;
slouken@1722
   701
            int style;
slouken@1722
   702
slouken@1724
   703
            /* If we allow resizing, let the resize happen naturally */
slouken@1724
   704
            if (SDL_GetWindowFlags(data->windowID) & SDL_WINDOW_RESIZABLE) {
slouken@1722
   705
                return (0);
slouken@1722
   706
            }
slouken@1722
   707
slouken@1722
   708
            /* Get the current position of our window */
slouken@1724
   709
            GetWindowRect(hwnd, &size);
slouken@1722
   710
            x = size.left;
slouken@1722
   711
            y = size.top;
slouken@1722
   712
slouken@1724
   713
            /* Calculate current size of our window */
slouken@1724
   714
            SDL_GetWindowSize(data->windowID, &w, &h);
slouken@1722
   715
            size.top = 0;
slouken@1722
   716
            size.left = 0;
slouken@1724
   717
            size.bottom = h;
slouken@1724
   718
            size.right = w;
slouken@1722
   719
slouken@1722
   720
            /* DJM - according to the docs for GetMenu(), the
slouken@1722
   721
               return value is undefined if hwnd is a child window.
slouken@1722
   722
               Aparently it's too difficult for MS to check
slouken@1722
   723
               inside their function, so I have to do it here.
slouken@1722
   724
             */
slouken@1722
   725
            style = GetWindowLong(hwnd, GWL_STYLE);
slouken@1722
   726
            AdjustWindowRect(&size,
slouken@1722
   727
                             style,
slouken@1722
   728
                             style & WS_CHILDWINDOW ? FALSE : GetMenu(hwnd) !=
slouken@1722
   729
                             NULL);
slouken@1722
   730
slouken@1724
   731
            w = size.right - size.left;
slouken@1724
   732
            h = size.bottom - size.top;
slouken@1722
   733
slouken@1722
   734
            /* Fix our size to the current size */
slouken@1722
   735
            info = (MINMAXINFO *) lParam;
slouken@1724
   736
            info->ptMaxSize.x = w;
slouken@1724
   737
            info->ptMaxSize.y = h;
slouken@1722
   738
            info->ptMaxPosition.x = x;
slouken@1722
   739
            info->ptMaxPosition.y = y;
slouken@1724
   740
            info->ptMinTrackSize.x = w;
slouken@1724
   741
            info->ptMinTrackSize.y = h;
slouken@1724
   742
            info->ptMaxTrackSize.x = w;
slouken@1724
   743
            info->ptMaxTrackSize.y = h;
slouken@1722
   744
        }
slouken@1722
   745
        return (0);
slouken@1722
   746
slouken@1722
   747
    case WM_WINDOWPOSCHANGED:
slouken@1722
   748
        {
slouken@1724
   749
            RECT rect;
slouken@1724
   750
            int x, y;
slouken@1722
   751
            int w, h;
slouken@1722
   752
slouken@1724
   753
            GetClientRect(hwnd, &rect);
slouken@1724
   754
            ClientToScreen(hwnd, (LPPOINT) & rect);
slouken@1724
   755
            ClientToScreen(hwnd, (LPPOINT) & rect + 1);
slouken@1724
   756
slouken@1724
   757
            if (SDL_GetWindowFlags(data->windowID) & SDL_WINDOW_INPUT_GRABBED) {
slouken@1724
   758
                ClipCursor(&rect);
slouken@1722
   759
            }
slouken@1724
   760
slouken@1724
   761
            x = rect.left;
slouken@1724
   762
            y = rect.top;
slouken@1724
   763
            SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MOVED, x, y);
slouken@1724
   764
slouken@1724
   765
            w = rect.right - rect.left;
slouken@1724
   766
            h = rect.bottom - rect.top;
slouken@1724
   767
            SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESIZED, w,
slouken@1724
   768
                                h);
slouken@1722
   769
        }
slouken@1722
   770
        break;
slouken@1722
   771
slouken@1722
   772
    case WM_SETCURSOR:
slouken@1722
   773
        {
slouken@1724
   774
            /*
slouken@1724
   775
               Uint16 hittest;
slouken@1722
   776
slouken@1724
   777
               hittest = LOWORD(lParam);
slouken@1724
   778
               if (hittest == HTCLIENT) {
slouken@1724
   779
               SetCursor(SDL_hcursor);
slouken@1724
   780
               return (TRUE);
slouken@1724
   781
               }
slouken@1724
   782
             */
slouken@1722
   783
        }
slouken@1722
   784
        break;
slouken@1722
   785
slouken@1722
   786
        /* We are about to get palette focus! */
slouken@1722
   787
    case WM_QUERYNEWPALETTE:
slouken@1722
   788
        {
slouken@1724
   789
            /*
slouken@1724
   790
               WIN_RealizePalette(current_video);
slouken@1724
   791
               return (TRUE);
slouken@1724
   792
             */
slouken@1722
   793
        }
slouken@1722
   794
        break;
slouken@1722
   795
slouken@1722
   796
        /* Another application changed the palette */
slouken@1722
   797
    case WM_PALETTECHANGED:
slouken@1722
   798
        {
slouken@1724
   799
            /*
slouken@1724
   800
               WIN_PaletteChanged(current_video, (HWND) wParam);
slouken@1724
   801
             */
slouken@1722
   802
        }
slouken@1722
   803
        break;
slouken@1722
   804
slouken@1722
   805
        /* We were occluded, refresh our display */
slouken@1722
   806
    case WM_PAINT:
slouken@1722
   807
        {
slouken@1724
   808
            RECT rect;
slouken@1724
   809
            if (GetUpdateRect(hwnd, &rect, FALSE)) {
slouken@1724
   810
                ValidateRect(hwnd, &rect);
slouken@1724
   811
                SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_EXPOSED,
slouken@1724
   812
                                    0, 0);
slouken@1722
   813
            }
slouken@1722
   814
        }
slouken@1722
   815
        return (0);
slouken@1722
   816
slouken@1724
   817
    case WM_SYSCOMMAND:
slouken@1722
   818
        {
slouken@1724
   819
            /* Don't start the screensaver or blank the monitor in fullscreen apps */
slouken@1724
   820
            if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
slouken@1724
   821
                (wParam & 0xFFF0) == SC_MONITORPOWER) {
slouken@1724
   822
                if (SDL_GetWindowFlags(data->windowID) &
slouken@1724
   823
                    SDL_WINDOW_FULLSCREEN) {
slouken@1724
   824
                    return (0);
slouken@1724
   825
                }
slouken@1724
   826
            }
slouken@1722
   827
        }
slouken@1724
   828
        break;
slouken@1722
   829
slouken@1722
   830
    case WM_CLOSE:
slouken@1722
   831
        {
slouken@1724
   832
            SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_CLOSE, 0, 0);
slouken@1722
   833
        }
slouken@1722
   834
        return (0);
slouken@1722
   835
    }
slouken@1719
   836
    return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam);
slouken@1718
   837
}
slouken@1718
   838
slouken@1712
   839
void
slouken@1718
   840
WIN_PumpEvents(_THIS)
slouken@1712
   841
{
slouken@1718
   842
    MSG msg;
slouken@1718
   843
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
slouken@1718
   844
        TranslateMessage(&msg);
slouken@1718
   845
        DispatchMessage(&msg);
slouken@1718
   846
    }
slouken@1718
   847
}
slouken@1718
   848
slouken@1718
   849
static int app_registered = 0;
slouken@1718
   850
LPTSTR SDL_Appname = NULL;
slouken@1718
   851
Uint32 SDL_Appstyle = 0;
slouken@1718
   852
HINSTANCE SDL_Instance = NULL;
slouken@1718
   853
slouken@1718
   854
/* Register the class for this application */
slouken@1718
   855
int
slouken@1718
   856
SDL_RegisterApp(char *name, Uint32 style, void *hInst)
slouken@1718
   857
{
slouken@1718
   858
    WNDCLASS class;
slouken@1718
   859
slouken@1718
   860
    /* Only do this once... */
slouken@1718
   861
    if (app_registered) {
slouken@1718
   862
        ++app_registered;
slouken@1718
   863
        return (0);
slouken@1718
   864
    }
slouken@1718
   865
    if (!name && !SDL_Appname) {
slouken@1718
   866
        name = "SDL_app";
slouken@1718
   867
        SDL_Appstyle = (CS_BYTEALIGNCLIENT | CS_OWNDC);
slouken@1718
   868
        SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
slouken@1718
   869
    }
slouken@1718
   870
slouken@1718
   871
    if (name) {
slouken@1719
   872
        SDL_Appname = WIN_UTF8ToString(name);
slouken@1718
   873
        SDL_Appstyle = style;
slouken@1718
   874
        SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
slouken@1718
   875
    }
slouken@1718
   876
slouken@1718
   877
    /* Register the application class */
slouken@1718
   878
    class.hCursor = NULL;
slouken@1718
   879
    class.hIcon = LoadImage(SDL_Instance, SDL_Appname,
slouken@1718
   880
                            IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
slouken@1718
   881
    class.lpszMenuName = NULL;
slouken@1718
   882
    class.lpszClassName = SDL_Appname;
slouken@1718
   883
    class.hbrBackground = NULL;
slouken@1718
   884
    class.hInstance = SDL_Instance;
slouken@1718
   885
    class.style = SDL_Appstyle;
slouken@1719
   886
    class.lpfnWndProc = DefWindowProc;
slouken@1718
   887
    class.cbWndExtra = 0;
slouken@1718
   888
    class.cbClsExtra = 0;
slouken@1718
   889
    if (!RegisterClass(&class)) {
slouken@1718
   890
        SDL_SetError("Couldn't register application class");
slouken@1718
   891
        return (-1);
slouken@1718
   892
    }
slouken@1718
   893
slouken@1718
   894
    app_registered = 1;
slouken@1718
   895
    return (0);
slouken@1718
   896
}
slouken@1718
   897
slouken@1718
   898
/* Unregisters the windowclass registered in SDL_RegisterApp above. */
slouken@1718
   899
void
slouken@1718
   900
SDL_UnregisterApp()
slouken@1718
   901
{
slouken@1718
   902
    WNDCLASS class;
slouken@1718
   903
slouken@1718
   904
    /* SDL_RegisterApp might not have been called before */
slouken@1718
   905
    if (!app_registered) {
slouken@1718
   906
        return;
slouken@1718
   907
    }
slouken@1718
   908
    --app_registered;
slouken@1718
   909
    if (app_registered == 0) {
slouken@1718
   910
        /* Check for any registered window classes. */
slouken@1718
   911
        if (GetClassInfo(SDL_Instance, SDL_Appname, &class)) {
slouken@1718
   912
            UnregisterClass(SDL_Appname, SDL_Instance);
slouken@1718
   913
        }
slouken@1718
   914
        SDL_free(SDL_Appname);
slouken@1718
   915
        SDL_Appname = NULL;
slouken@1718
   916
    }
slouken@1712
   917
}
slouken@1712
   918
slouken@1719
   919
/* Sets an error message based on GetLastError() */
slouken@1719
   920
void
slouken@1719
   921
WIN_SetError(const char *prefix)
slouken@1719
   922
{
slouken@1719
   923
    TCHAR buffer[1024];
slouken@1719
   924
    char *message;
slouken@1719
   925
slouken@1719
   926
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
slouken@1719
   927
                  NULL,
slouken@1719
   928
                  GetLastError(), 0, buffer, SDL_arraysize(buffer), NULL);
slouken@1719
   929
slouken@1719
   930
    message = WIN_StringToUTF8(buffer);
slouken@1719
   931
    SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ":" : "", message);
slouken@1719
   932
    SDL_free(message);
slouken@1719
   933
}
slouken@1719
   934
slouken@1712
   935
/* vi: set ts=4 sw=4 expandtab: */