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