2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
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.
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.
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/>.
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.
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.
26 ===========================================================================
29 #include "../../idlib/precompiled.h"
32 #include "win_local.h"
33 #include "../../renderer/tr_local.h"
35 LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
37 static bool s_alttab_disabled;
39 static void WIN_DisableAltTab( void ) {
40 if ( s_alttab_disabled || win32.win_allowAltTab.GetBool() ) {
43 if ( !idStr::Icmp( cvarSystem->GetCVarString( "sys_arch" ), "winnt" ) ) {
44 RegisterHotKey( 0, 0, MOD_ALT, VK_TAB );
48 SystemParametersInfo( SPI_SCREENSAVERRUNNING, 1, &old, 0 );
50 s_alttab_disabled = true;
53 static void WIN_EnableAltTab( void ) {
54 if ( !s_alttab_disabled || win32.win_allowAltTab.GetBool() ) {
57 if ( !idStr::Icmp( cvarSystem->GetCVarString( "sys_arch" ), "winnt" ) ) {
58 UnregisterHotKey( 0, 0 );
62 SystemParametersInfo( SPI_SCREENSAVERRUNNING, 0, &old, 0 );
65 s_alttab_disabled = false;
68 void WIN_Sizing(WORD side, RECT *rect)
70 if ( !glConfig.isInitialized || glConfig.vidHeight <= 0 || glConfig.vidWidth <= 0 ) {
74 if ( idKeyInput::IsDown( K_CTRL ) ) {
78 int width = rect->right - rect->left;
79 int height = rect->bottom - rect->top;
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;
90 // Clamp to a minimum size
92 int minHeight = minWidth * SCREEN_HEIGHT / SCREEN_WIDTH;
94 if ( width < minWidth ) {
97 if ( height < minHeight ) {
104 rect->left = rect->right - width - decoWidth;
105 rect->bottom = rect->top + ( width * SCREEN_HEIGHT / SCREEN_WIDTH ) + decoHeight;
108 rect->right = rect->left + width + decoWidth;
109 rect->bottom = rect->top + ( width * SCREEN_HEIGHT / SCREEN_WIDTH ) + decoHeight;
112 case WMSZ_BOTTOMRIGHT:
113 rect->bottom = rect->top + height + decoHeight;
114 rect->right = rect->left + ( height * SCREEN_WIDTH / SCREEN_HEIGHT ) + decoWidth;
118 rect->top = rect->bottom - height - decoHeight;
119 rect->right = rect->left + ( height * SCREEN_WIDTH / SCREEN_HEIGHT ) + decoWidth;
121 case WMSZ_BOTTOMLEFT:
122 rect->bottom = rect->top + height + decoHeight;
123 rect->left = rect->right - ( height * SCREEN_WIDTH / SCREEN_HEIGHT ) - decoWidth;
126 rect->top = rect->bottom - height - decoHeight;
127 rect->left = rect->right - ( height * SCREEN_WIDTH / SCREEN_HEIGHT ) - decoWidth;
132 //==========================================================================
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
137 static byte s_scantokey[128] =
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
159 static byte s_scantoshift[128] =
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
186 Map from windows to Doom keynums
195 modified = ( key >> 16 ) & 255;
197 if ( modified > 127 )
200 if ( key & ( 1 << 24 ) ) {
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.
212 case 0x35: //Numpad /
217 const unsigned char *scanToKey = Sys_GetScanTable();
218 result = scanToKey[modified];
220 // common->Printf( "Key: 0x%08x Modified: 0x%02x Extended: %s Result: 0x%02x\n", key, modified, (is_extended?"Y":"N"), result);
249 return K_KP_LEFTARROW;
251 return K_KP_RIGHTARROW;
255 return K_KP_DOWNARROW;
273 main window procedure
276 LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
279 case WM_WINDOWPOSCHANGED:
280 if (glConfig.isInitialized) {
282 if (::GetClientRect(win32.hWnd, &rect)) {
283 glConfig.vidWidth = rect.right - rect.left;
284 glConfig.vidHeight = rect.bottom - rect.top;
293 if ( win32.cdsFullscreen ) {
299 // do the OpenGL setup
300 void GLW_WM_CREATE( HWND hWnd );
301 GLW_WM_CREATE( hWnd );
306 // let sound and input know about this?
308 if ( win32.cdsFullscreen ) {
314 cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "quit" );
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
323 int fActive, fMinimized;
325 fActive = LOWORD(wParam);
326 fMinimized = (BOOL) HIWORD(wParam);
328 win32.activeApp = (fActive != WA_INACTIVE);
329 if ( win32.activeApp ) {
330 idKeyInput::ClearStates();
331 com_editorActive = false;
332 Sys_GrabMouseCursor( true );
335 if ( fActive == WA_INACTIVE ) {
336 win32.movingWindow = false;
339 // start playing the game sound world
340 session->SetPlayingSoundWorld();
342 // we do not actually grab or release the mouse here,
343 // that will be done next time through the main loop
352 if (!win32.cdsFullscreen )
354 xPos = (short) LOWORD(lParam); // horizontal position
355 yPos = (short) HIWORD(lParam); // vertical position
362 style = GetWindowLong( hWnd, GWL_STYLE );
363 AdjustWindowRect( &r, style, FALSE );
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();
373 if ( win32.win_timerUpdate.GetBool() ) {
379 if ( wParam == SC_SCREENSAVE || wParam == SC_KEYMENU ) {
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" );
390 // fall through for other keys
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)
398 Sys_QueEvent( win32.sysMsgTime, SE_KEY, key, true, 0, NULL );
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
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)
413 Sys_QueEvent( win32.sysMsgTime, SE_KEY, key, false, 0, NULL );
417 Sys_QueEvent( win32.sysMsgTime, SE_CHAR, wParam, 0, 0, NULL );
420 case WM_NCLBUTTONDOWN:
421 // win32.movingWindow = true;
424 case WM_ENTERSIZEMOVE:
425 win32.movingWindow = true;
428 case WM_EXITSIZEMOVE:
429 win32.movingWindow = false;
433 WIN_Sizing(wParam, (RECT *)lParam);
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 );
455 return DefWindowProc( hWnd, uMsg, wParam, lParam );