doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
win_wndproc.cpp
Go to the documentation of this file.
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
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
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:
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 ) {
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
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 );
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 }
static bool IsDown(int keyNum)
Definition: KeyInput.cpp:271
Definition: KeyInput.h:78
Definition: KeyInput.h:83
Definition: KeyInput.h:82
idCVarSystem * cvarSystem
Definition: CVarSystem.cpp:487
Definition: KeyInput.h:88
bool activeApp
Definition: win_local.h:104
CONST PIXELFORMATDESCRIPTOR UINT
Definition: win_qgl.cpp:47
Definition: KeyInput.h:86
Definition: KeyInput.h:74
static void ClearStates(void)
Definition: KeyInput.cpp:746
Definition: KeyInput.h:85
const int SCREEN_HEIGHT
Definition: RenderSystem.h:154
idRenderSystem * renderSystem
#define WINAPI
Definition: qgl.h:64
Definition: KeyInput.h:81
idCmdSystem * cmdSystem
Definition: CmdSystem.cpp:116
#define BOOL
Definition: mprintf.c:71
Definition: KeyInput.h:91
Boolean result
void WIN_Sizing(WORD side, RECT *rect)
Definition: win_wndproc.cpp:68
int Icmp(const char *text) const
Definition: Str.h:667
static idCVar win_ypos
Definition: win_local.h:145
virtual void Frame(void)=0
int sysMsgTime
Definition: win_local.h:115
bool cdsFullscreen
Definition: win_local.h:131
virtual void BufferCommandText(cmdExecution_t exec, const char *text)=0
Definition: KeyInput.h:90
Definition: KeyInput.h:80
Definition: KeyInput.h:73
virtual bool IsFullScreen(void) const =0
static idCVar win_xpos
Definition: win_local.h:144
virtual void SetPlayingSoundWorld()=0
idCommon * common
Definition: Common.cpp:206
#define NULL
Definition: Lib.h:88
virtual const char * GetCVarString(const char *name) const =0
static idCVar win_allowAltTab
Definition: win_local.h:141
void GLW_WM_CREATE(HWND hWnd)
Definition: win_glimp.cpp:354
void SetInteger(const int value)
Definition: CVarSystem.h:148
virtual void SetCVarBool(const char *name, const bool value, int flags=0)=0
int MapKey(int key)
void Sys_QueEvent(int time, sysEventType_t type, int value, int value2, int ptrLength, void *ptr)
Definition: win_main.cpp:731
Definition: KeyInput.h:84
GLenum GLsizei width
Definition: glext.h:2846
int modified
Definition: KeyInput.h:87
GLenum GLsizei GLsizei height
Definition: glext.h:2856
LONG WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
long LONG
GLdouble GLdouble GLdouble r
Definition: glext.h:2951
const int SCREEN_WIDTH
Definition: RenderSystem.h:153
bool GetBool(void) const
Definition: CVarSystem.h:142
glconfig_t glConfig
void ClearModified(void)
Definition: CVarSystem.h:139
Definition: KeyInput.h:70
unsigned char byte
Definition: Lib.h:75
static idCVar win_timerUpdate
Definition: win_local.h:149
const unsigned char * Sys_GetScanTable(void)
Definition: win_input.cpp:744
#define FALSE
Definition: mprintf.c:70
bool isInitialized
Definition: RenderSystem.h:98
idSession * session
Definition: Session.cpp:48
#define WINDOW_STYLE
Definition: win_local.h:61
Win32Vars_t win32
Definition: win_main.cpp:65
bool movingWindow
Definition: win_local.h:106
Definition: KeyInput.h:89
bool com_editorActive
Definition: Common.cpp:98
void Sys_GrabMouseCursor(bool)
Definition: dedicated.cpp:43