]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/sys/win32/win_wndproc.cpp
hello world
[icculus/iodoom3.git] / neo / sys / win32 / win_wndproc.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31
32 #include "win_local.h"
33 #include "../../renderer/tr_local.h"
34
35 LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
36
37 static bool s_alttab_disabled;
38
39 static void WIN_DisableAltTab( void ) {
40         if ( s_alttab_disabled || win32.win_allowAltTab.GetBool() ) {
41                 return;
42         }
43         if ( !idStr::Icmp( cvarSystem->GetCVarString( "sys_arch" ), "winnt" ) ) {
44                 RegisterHotKey( 0, 0, MOD_ALT, VK_TAB );
45         } else {
46                 BOOL old;
47
48                 SystemParametersInfo( SPI_SCREENSAVERRUNNING, 1, &old, 0 );
49         }
50         s_alttab_disabled = true;
51 }
52
53 static void WIN_EnableAltTab( void ) {
54         if ( !s_alttab_disabled || win32.win_allowAltTab.GetBool() ) {
55                 return;
56         }
57         if ( !idStr::Icmp( cvarSystem->GetCVarString( "sys_arch" ), "winnt" ) ) {
58                 UnregisterHotKey( 0, 0 );
59         } else {
60                 BOOL old;
61
62                 SystemParametersInfo( SPI_SCREENSAVERRUNNING, 0, &old, 0 );
63         }
64
65         s_alttab_disabled = false;
66 }
67
68 void WIN_Sizing(WORD side, RECT *rect)
69 {
70         if ( !glConfig.isInitialized || glConfig.vidHeight <= 0 || glConfig.vidWidth <= 0 ) {
71                 return;
72         }
73
74         if ( idKeyInput::IsDown( K_CTRL ) ) {
75                 return;
76         }
77
78         int width = rect->right - rect->left;
79         int height = rect->bottom - rect->top;
80
81         // Adjust width/height for window decoration
82         RECT decoRect = { 0, 0, 0, 0 };
83         AdjustWindowRect( &decoRect, WINDOW_STYLE|WS_SYSMENU, FALSE );
84         int decoWidth = decoRect.right - decoRect.left;
85         int decoHeight = decoRect.bottom - decoRect.top;
86
87         width -= decoWidth;
88         height -= decoHeight;
89
90         // Clamp to a minimum size
91         int minWidth = 160;
92         int minHeight = minWidth * SCREEN_HEIGHT / SCREEN_WIDTH;
93
94         if ( width < minWidth ) {
95                 width = minWidth;
96         }
97         if ( height < minHeight ) {
98                 height = minHeight;
99         }
100
101         // Set the new size
102         switch ( side ) {
103         case WMSZ_LEFT:
104                 rect->left = rect->right - width - decoWidth;
105                 rect->bottom = rect->top + ( width * SCREEN_HEIGHT / SCREEN_WIDTH ) + decoHeight;
106                 break;
107         case WMSZ_RIGHT:
108                 rect->right = rect->left + width + decoWidth;
109                 rect->bottom = rect->top + ( width * SCREEN_HEIGHT / SCREEN_WIDTH ) + decoHeight;
110                 break;
111         case WMSZ_BOTTOM:
112         case WMSZ_BOTTOMRIGHT:
113                 rect->bottom = rect->top + height + decoHeight;
114                 rect->right = rect->left + ( height * SCREEN_WIDTH / SCREEN_HEIGHT ) + decoWidth;
115                 break;
116         case WMSZ_TOP:
117         case WMSZ_TOPRIGHT:
118                 rect->top = rect->bottom - height - decoHeight;
119                 rect->right = rect->left + ( height * SCREEN_WIDTH / SCREEN_HEIGHT ) + decoWidth;
120                 break;
121         case WMSZ_BOTTOMLEFT:
122                 rect->bottom = rect->top + height + decoHeight;
123                 rect->left = rect->right - ( height * SCREEN_WIDTH / SCREEN_HEIGHT ) - decoWidth;
124                 break;
125         case WMSZ_TOPLEFT:
126                 rect->top = rect->bottom - height - decoHeight;
127                 rect->left = rect->right - ( height * SCREEN_WIDTH / SCREEN_HEIGHT ) - decoWidth;
128                 break;
129         }
130 }
131
132 //==========================================================================
133
134 // Keep this in sync with the one in win_input.cpp
135 // This one is used in the menu, the other one is used in game
136
137 static byte s_scantokey[128] = 
138
139 //  0            1       2          3          4       5            6         7
140 //  8            9       A          B          C       D            E         F
141         0,          27,    '1',       '2',        '3',    '4',         '5',      '6', 
142         '7',        '8',    '9',       '0',        '-',    '=',          K_BACKSPACE, 9, // 0
143         'q',        'w',    'e',       'r',        't',    'y',         'u',      'i', 
144         'o',        'p',    '[',       ']',        K_ENTER,K_CTRL,      'a',      's',   // 1
145         'd',        'f',    'g',       'h',        'j',    'k',         'l',      ';', 
146         '\'',       '`',    K_SHIFT,   '\\',       'z',    'x',         'c',      'v',   // 2
147         'b',        'n',    'm',       ',',        '.',    '/',         K_SHIFT,  K_KP_STAR, 
148         K_ALT,      ' ',    K_CAPSLOCK,K_F1,       K_F2,   K_F3,        K_F4,     K_F5,  // 3
149         K_F6,       K_F7,   K_F8,      K_F9,       K_F10,  K_PAUSE,     K_SCROLL, K_HOME, 
150         K_UPARROW,  K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
151         K_DOWNARROW,K_PGDN, K_INS,     K_DEL,      0,      0,           0,        K_F11, 
152         K_F12,      0,      0,         K_LWIN,     K_RWIN, K_MENU,      0,        0,     // 5
153         0,          0,      0,         0,          0,      0,           0,        0, 
154         0,          0,      0,         0,          0,      0,           0,        0,     // 6
155         0,          0,      0,         0,          0,      0,           0,        0, 
156         0,          0,      0,         0,          0,      0,           0,        0      // 7
157 }; 
158
159 static byte s_scantoshift[128] = 
160
161 //  0            1       2          3          4       5            6         7
162 //  8            9       A          B          C       D            E         F
163         0,           27,    '!',       '@',        '#',    '$',         '%',      '^', 
164         '&',        '*',    '(',       ')',        '_',    '+',         K_BACKSPACE, 9,  // 0 
165         'Q',        'W',    'E',       'R',        'T',    'Y',         'U',      'I', 
166         'O',        'P',    '{',       '}',        K_ENTER,K_CTRL,      'A',      'S',   // 1 
167         'D',        'F',    'G',       'H',        'J',    'K',         'L',      ':', 
168         '|' ,       '~',    K_SHIFT,   '\\',       'Z',    'X',         'C',      'V',   // 2 
169         'B',        'N',    'M',       '<',        '>',    '?',         K_SHIFT,  K_KP_STAR, 
170         K_ALT,      ' ',    K_CAPSLOCK,K_F1,       K_F2,   K_F3,        K_F4,     K_F5,  // 3
171         K_F6,       K_F7,   K_F8,      K_F9,       K_F10,  K_PAUSE,     K_SCROLL, K_HOME, 
172         K_UPARROW,  K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
173         K_DOWNARROW,K_PGDN, K_INS,     K_DEL,      0,      0,           0,        K_F11, 
174         K_F12,      0,      0,         K_LWIN,     K_RWIN, K_MENU,      0,        0,     // 5
175         0,          0,      0,         0,          0,      0,           0,        0, 
176         0,          0,      0,         0,          0,      0,           0,        0,     // 6
177         0,          0,      0,         0,          0,      0,           0,        0, 
178         0,          0,      0,         0,          0,      0,           0,        0      // 7
179 }; 
180
181
182 /*
183 =======
184 MapKey
185
186 Map from windows to Doom keynums
187 =======
188 */
189 int MapKey (int key)
190 {
191         int result;
192         int modified;
193         bool is_extended;
194
195         modified = ( key >> 16 ) & 255;
196
197         if ( modified > 127 )
198                 return 0;
199
200         if ( key & ( 1 << 24 ) ) {
201                 is_extended = true;
202         }
203         else {
204                 is_extended = false;
205         }
206
207         //Check for certain extended character codes.
208         //The specific case we are testing is the numpad / is not being translated
209         //properly for localized builds.
210         if(is_extended) {
211                 switch(modified) {
212                         case 0x35: //Numpad /
213                                 return K_KP_SLASH;
214                 }
215         }
216
217         const unsigned char *scanToKey = Sys_GetScanTable();
218         result = scanToKey[modified];
219
220         // common->Printf( "Key: 0x%08x Modified: 0x%02x Extended: %s Result: 0x%02x\n", key, modified, (is_extended?"Y":"N"), result);
221
222         if ( is_extended ) {
223                 switch ( result )
224                 {
225                 case K_PAUSE:
226                         return K_KP_NUMLOCK;
227                 case 0x0D:
228                         return K_KP_ENTER;
229                 case 0x2F:
230                         return K_KP_SLASH;
231                 case 0xAF:
232                         return K_KP_PLUS;
233                 case K_KP_STAR:
234                         return K_PRINT_SCR;
235                 case K_ALT:
236                         return K_RIGHT_ALT;
237                 }
238         }
239         else {
240                 switch ( result )
241                 {
242                 case K_HOME:
243                         return K_KP_HOME;
244                 case K_UPARROW:
245                         return K_KP_UPARROW;
246                 case K_PGUP:
247                         return K_KP_PGUP;
248                 case K_LEFTARROW:
249                         return K_KP_LEFTARROW;
250                 case K_RIGHTARROW:
251                         return K_KP_RIGHTARROW;
252                 case K_END:
253                         return K_KP_END;
254                 case K_DOWNARROW:
255                         return K_KP_DOWNARROW;
256                 case K_PGDN:
257                         return K_KP_PGDN;
258                 case K_INS:
259                         return K_KP_INS;
260                 case K_DEL:
261                         return K_KP_DEL;
262                 }
263         }
264
265         return result;
266 }
267
268
269 /*
270 ====================
271 MainWndProc
272
273 main window procedure
274 ====================
275 */
276 LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
277         int key;
278         switch( uMsg ) {
279                 case WM_WINDOWPOSCHANGED:
280                         if (glConfig.isInitialized) {
281                                 RECT rect;
282                                 if (::GetClientRect(win32.hWnd, &rect)) {
283                                         glConfig.vidWidth = rect.right - rect.left;
284                                         glConfig.vidHeight = rect.bottom - rect.top;
285                                 }
286                         }
287                         break;
288
289                 case WM_CREATE:
290
291                         win32.hWnd = hWnd;
292
293                         if ( win32.cdsFullscreen ) {
294                                 WIN_DisableAltTab();
295                         } else {
296                                 WIN_EnableAltTab();
297                         }
298
299                         // do the OpenGL setup
300                         void GLW_WM_CREATE( HWND hWnd );
301                         GLW_WM_CREATE( hWnd );
302
303                         break;
304
305                 case WM_DESTROY:
306                         // let sound and input know about this?
307                         win32.hWnd = NULL;
308                         if ( win32.cdsFullscreen ) {
309                                 WIN_EnableAltTab();
310                         }
311                         break;
312
313                 case WM_CLOSE:
314                         cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "quit" );
315                         break;
316
317                 case WM_ACTIVATE:
318                         // if we got here because of an alt-tab or maximize,
319                         // we should activate immediately.  If we are here because
320                         // the mouse was clicked on a title bar or drag control,
321                         // don't activate until the mouse button is released
322                         {
323                                 int     fActive, fMinimized;
324
325                                 fActive = LOWORD(wParam);
326                                 fMinimized = (BOOL) HIWORD(wParam);
327
328                                 win32.activeApp = (fActive != WA_INACTIVE);
329                                 if ( win32.activeApp ) {
330                                         idKeyInput::ClearStates();
331                                         com_editorActive = false;
332                                         Sys_GrabMouseCursor( true );
333                                 }
334
335                                 if ( fActive == WA_INACTIVE ) {
336                                         win32.movingWindow = false;
337                                 }
338
339                                 // start playing the game sound world
340                                 session->SetPlayingSoundWorld();
341
342                                 // we do not actually grab or release the mouse here,
343                                 // that will be done next time through the main loop
344                         }
345                         break;
346
347                 case WM_MOVE: {
348                         int             xPos, yPos;
349                         RECT r;
350                         int             style;
351
352                         if (!win32.cdsFullscreen )
353                         {
354                                 xPos = (short) LOWORD(lParam);    // horizontal position 
355                                 yPos = (short) HIWORD(lParam);    // vertical position 
356
357                                 r.left   = 0;
358                                 r.top    = 0;
359                                 r.right  = 1;
360                                 r.bottom = 1;
361
362                                 style = GetWindowLong( hWnd, GWL_STYLE );
363                                 AdjustWindowRect( &r, style, FALSE );
364
365                                 win32.win_xpos.SetInteger( xPos + r.left );
366                                 win32.win_ypos.SetInteger( yPos + r.top );
367                                 win32.win_xpos.ClearModified();
368                                 win32.win_ypos.ClearModified();
369                         }
370                         break;
371                 }
372                 case WM_TIMER: {
373                         if ( win32.win_timerUpdate.GetBool() ) {
374                                 common->Frame();
375                         }
376                         break;
377                 }
378                 case WM_SYSCOMMAND:
379                         if ( wParam == SC_SCREENSAVE || wParam == SC_KEYMENU ) {
380                                 return 0;
381                         }
382                         break;
383
384                 case WM_SYSKEYDOWN:
385                         if ( wParam == 13 ) {   // alt-enter toggles full-screen
386                                 cvarSystem->SetCVarBool( "r_fullscreen", !renderSystem->IsFullScreen() );
387                                 cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "vid_restart\n" );
388                                 return 0;
389                         }
390                         // fall through for other keys
391                 case WM_KEYDOWN:
392                         key = MapKey( lParam );
393                         if ( key == K_CTRL || key == K_ALT || key == K_RIGHT_ALT ) {
394                                 // let direct-input handle this because windows sends Alt-Gr
395                                 // as two events (ctrl then alt)
396                                 break;
397                         }
398                         Sys_QueEvent( win32.sysMsgTime, SE_KEY, key, true, 0, NULL );
399                         break;
400
401                 case WM_SYSKEYUP:
402                 case WM_KEYUP:
403                         key = MapKey( lParam );
404                         if ( key == K_PRINT_SCR ) {
405                                 // don't queue printscreen keys.  Since windows doesn't send us key
406                                 // down events for this, we handle queueing them with DirectInput
407                                 break;
408                         } else if ( key == K_CTRL || key == K_ALT || key == K_RIGHT_ALT ) {
409                                 // let direct-input handle this because windows sends Alt-Gr
410                                 // as two events (ctrl then alt)
411                                 break;
412                         }
413                         Sys_QueEvent( win32.sysMsgTime, SE_KEY, key, false, 0, NULL );
414                         break;
415
416                 case WM_CHAR:
417                         Sys_QueEvent( win32.sysMsgTime, SE_CHAR, wParam, 0, 0, NULL );
418                         break;
419
420                 case WM_NCLBUTTONDOWN:
421 //                      win32.movingWindow = true;
422                         break;
423
424                 case WM_ENTERSIZEMOVE:
425                         win32.movingWindow = true;
426                         break;
427
428                 case WM_EXITSIZEMOVE:
429                         win32.movingWindow = false;
430                         break;
431
432                 case WM_SIZING:
433                         WIN_Sizing(wParam, (RECT *)lParam);
434                         break;
435
436                 case WM_RBUTTONDOWN:
437                 case WM_RBUTTONUP:
438                 case WM_MBUTTONDOWN:
439                 case WM_MBUTTONUP:
440                 case WM_MOUSEMOVE: {
441                         break;
442                 }
443                 case WM_MOUSEWHEEL: {
444                         int delta = GET_WHEEL_DELTA_WPARAM( wParam ) / WHEEL_DELTA;
445                         int key = delta < 0 ? K_MWHEELDOWN : K_MWHEELUP;
446                         delta = abs( delta );
447                         while( delta-- > 0 ) {
448                                 Sys_QueEvent( win32.sysMsgTime, SE_KEY, key, true, 0, NULL );
449                                 Sys_QueEvent( win32.sysMsgTime, SE_KEY, key, false, 0, NULL );
450                         }
451                         break;
452                 }
453         }
454
455     return DefWindowProc( hWnd, uMsg, wParam, lParam );
456 }