Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

win_wndproc.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 
00023 #include "../client/client.h"
00024 #include "win_local.h"
00025 
00026 WinVars_t   g_wv;
00027 
00028 #ifndef WM_MOUSEWHEEL
00029 #define WM_MOUSEWHEEL (WM_MOUSELAST+1)  // message that will be supported by the OS 
00030 #endif
00031 
00032 static UINT MSH_MOUSEWHEEL;
00033 
00034 // Console variables that we need to access from this module
00035 cvar_t      *vid_xpos;          // X coordinate of window position
00036 cvar_t      *vid_ypos;          // Y coordinate of window position
00037 cvar_t      *r_fullscreen;
00038 
00039 #define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) )
00040 
00041 LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
00042 
00043 static qboolean s_alttab_disabled;
00044 
00045 static void WIN_DisableAltTab( void )
00046 {
00047     if ( s_alttab_disabled )
00048         return;
00049 
00050     if ( !Q_stricmp( Cvar_VariableString( "arch" ), "winnt" ) )
00051     {
00052         RegisterHotKey( 0, 0, MOD_ALT, VK_TAB );
00053     }
00054     else
00055     {
00056         BOOL old;
00057 
00058         SystemParametersInfo( SPI_SCREENSAVERRUNNING, 1, &old, 0 );
00059     }
00060     s_alttab_disabled = qtrue;
00061 }
00062 
00063 static void WIN_EnableAltTab( void )
00064 {
00065     if ( s_alttab_disabled )
00066     {
00067         if ( !Q_stricmp( Cvar_VariableString( "arch" ), "winnt" ) )
00068         {
00069             UnregisterHotKey( 0, 0 );
00070         }
00071         else
00072         {
00073             BOOL old;
00074 
00075             SystemParametersInfo( SPI_SCREENSAVERRUNNING, 0, &old, 0 );
00076         }
00077 
00078         s_alttab_disabled = qfalse;
00079     }
00080 }
00081 
00082 /*
00083 ==================
00084 VID_AppActivate
00085 ==================
00086 */
00087 static void VID_AppActivate(BOOL fActive, BOOL minimize)
00088 {
00089     g_wv.isMinimized = minimize;
00090 
00091     Com_DPrintf("VID_AppActivate: %i\n", fActive );
00092 
00093     Key_ClearStates();  // FIXME!!!
00094 
00095     // we don't want to act like we're active if we're minimized
00096     if (fActive && !g_wv.isMinimized )
00097     {
00098         g_wv.activeApp = qtrue;
00099     }
00100     else
00101     {
00102         g_wv.activeApp = qfalse;
00103     }
00104 
00105     // minimize/restore mouse-capture on demand
00106     if (!g_wv.activeApp )
00107     {
00108         IN_Activate (qfalse);
00109     }
00110     else
00111     {
00112         IN_Activate (qtrue);
00113     }
00114 }
00115 
00116 //==========================================================================
00117 
00118 static byte s_scantokey[128] = 
00119                     { 
00120 //  0           1       2       3       4       5       6       7 
00121 //  8           9       A       B       C       D       E       F 
00122     0  ,    27,     '1',    '2',    '3',    '4',    '5',    '6', 
00123     '7',    '8',    '9',    '0',    '-',    '=',    K_BACKSPACE, 9, // 0 
00124     'q',    'w',    'e',    'r',    't',    'y',    'u',    'i', 
00125     'o',    'p',    '[',    ']',    13 ,    K_CTRL,'a',  's',      // 1 
00126     'd',    'f',    'g',    'h',    'j',    'k',    'l',    ';', 
00127     '\'' ,    '`',    K_SHIFT,'\\',  'z',    'x',    'c',    'v',      // 2 
00128     'b',    'n',    'm',    ',',    '.',    '/',    K_SHIFT,'*', 
00129     K_ALT,' ',   K_CAPSLOCK  ,    K_F1, K_F2, K_F3, K_F4, K_F5,   // 3 
00130     K_F6, K_F7, K_F8, K_F9, K_F10,  K_PAUSE,    0  , K_HOME, 
00131     K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5,K_RIGHTARROW, K_KP_PLUS,K_END, //4 
00132     K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0,             0,              K_F11, 
00133     K_F12,0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 5
00134     0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
00135     0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 6 
00136     0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
00137     0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0         // 7 
00138 }; 
00139 
00140 /*
00141 =======
00142 MapKey
00143 
00144 Map from windows to quake keynums
00145 =======
00146 */
00147 static int MapKey (int key)
00148 {
00149     int result;
00150     int modified;
00151     qboolean is_extended;
00152 
00153 //  Com_Printf( "0x%x\n", key);
00154 
00155     modified = ( key >> 16 ) & 255;
00156 
00157     if ( modified > 127 )
00158         return 0;
00159 
00160     if ( key & ( 1 << 24 ) )
00161     {
00162         is_extended = qtrue;
00163     }
00164     else
00165     {
00166         is_extended = qfalse;
00167     }
00168 
00169     result = s_scantokey[modified];
00170 
00171     if ( !is_extended )
00172     {
00173         switch ( result )
00174         {
00175         case K_HOME:
00176             return K_KP_HOME;
00177         case K_UPARROW:
00178             return K_KP_UPARROW;
00179         case K_PGUP:
00180             return K_KP_PGUP;
00181         case K_LEFTARROW:
00182             return K_KP_LEFTARROW;
00183         case K_RIGHTARROW:
00184             return K_KP_RIGHTARROW;
00185         case K_END:
00186             return K_KP_END;
00187         case K_DOWNARROW:
00188             return K_KP_DOWNARROW;
00189         case K_PGDN:
00190             return K_KP_PGDN;
00191         case K_INS:
00192             return K_KP_INS;
00193         case K_DEL:
00194             return K_KP_DEL;
00195         default:
00196             return result;
00197         }
00198     }
00199     else
00200     {
00201         switch ( result )
00202         {
00203         case K_PAUSE:
00204             return K_KP_NUMLOCK;
00205         case 0x0D:
00206             return K_KP_ENTER;
00207         case 0x2F:
00208             return K_KP_SLASH;
00209         case 0xAF:
00210             return K_KP_PLUS;
00211         }
00212         return result;
00213     }
00214 }
00215 
00216 
00217 /*
00218 ====================
00219 MainWndProc
00220 
00221 main window procedure
00222 ====================
00223 */
00224 extern cvar_t *in_mouse;
00225 extern cvar_t *in_logitechbug;
00226 LONG WINAPI MainWndProc (
00227     HWND    hWnd,
00228     UINT    uMsg,
00229     WPARAM  wParam,
00230     LPARAM  lParam)
00231 {
00232     static qboolean flip = qtrue;
00233     int zDelta, i;
00234 
00235     // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/mouseinput/aboutmouseinput.asp
00236     // Windows 95, Windows NT 3.51 - uses MSH_MOUSEWHEEL
00237     // only relevant for non-DI input
00238     //
00239     // NOTE: not sure how reliable this is anymore, might trigger double wheel events
00240     if (in_mouse->integer != 1)
00241     {
00242         if ( uMsg == MSH_MOUSEWHEEL )
00243         {
00244             if ( ( ( int ) wParam ) > 0 )
00245             {
00246                 Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, qtrue, 0, NULL );
00247                 Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, qfalse, 0, NULL );
00248             }
00249             else
00250             {
00251                 Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, qtrue, 0, NULL );
00252                 Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, qfalse, 0, NULL );
00253             }
00254             return DefWindowProc (hWnd, uMsg, wParam, lParam);
00255         }
00256     }
00257 
00258     switch (uMsg)
00259     {
00260     case WM_MOUSEWHEEL:
00261         // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/mouseinput/aboutmouseinput.asp
00262         // Windows 98/Me, Windows NT 4.0 and later - uses WM_MOUSEWHEEL
00263         // only relevant for non-DI input and when console is toggled in window mode
00264         //   if console is toggled in window mode (KEYCATCH_CONSOLE) then mouse is released and DI doesn't see any mouse wheel
00265         if (in_mouse->integer != 1 || (!r_fullscreen->integer && (cls.keyCatchers & KEYCATCH_CONSOLE)))
00266         {
00267             // 120 increments, might be 240 and multiples if wheel goes too fast
00268             // NOTE Logitech: logitech drivers are screwed and send the message twice?
00269             //   could add a cvar to interpret the message as successive press/release events
00270             zDelta = ( short ) HIWORD( wParam ) / 120;
00271             if ( zDelta > 0 )
00272             {
00273                 for(i=0; i<zDelta; i++)
00274                 {
00275                     if (!in_logitechbug->integer)
00276                     {
00277                         Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, qtrue, 0, NULL );
00278                         Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, qfalse, 0, NULL );
00279                     }
00280                     else
00281                     {
00282                         Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, flip, 0, NULL );
00283                         flip = !flip;
00284                     }
00285                 }
00286             }
00287             else
00288             {
00289                 for(i=0; i<-zDelta; i++)
00290                 {
00291                     if (!in_logitechbug->integer)
00292                     {
00293                         Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, qtrue, 0, NULL );
00294                         Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, qfalse, 0, NULL );
00295                     }
00296                     else
00297                     {
00298                         Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, flip, 0, NULL );
00299                         flip = !flip;
00300                     }
00301                 }
00302             }
00303             // when an application processes the WM_MOUSEWHEEL message, it must return zero
00304             return 0;
00305         }
00306         break;
00307 
00308     case WM_CREATE:
00309 
00310         g_wv.hWnd = hWnd;
00311 
00312         vid_xpos = Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE);
00313         vid_ypos = Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE);
00314         r_fullscreen = Cvar_Get ("r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH );
00315 
00316         MSH_MOUSEWHEEL = RegisterWindowMessage("MSWHEEL_ROLLMSG"); 
00317         if ( r_fullscreen->integer )
00318         {
00319             WIN_DisableAltTab();
00320         }
00321         else
00322         {
00323             WIN_EnableAltTab();
00324         }
00325 
00326         break;
00327 #if 0
00328     case WM_DISPLAYCHANGE:
00329         Com_DPrintf( "WM_DISPLAYCHANGE\n" );
00330         // we need to force a vid_restart if the user has changed
00331         // their desktop resolution while the game is running,
00332         // but don't do anything if the message is a result of
00333         // our own calling of ChangeDisplaySettings
00334         if ( com_insideVidInit ) {
00335             break;      // we did this on purpose
00336         }
00337         // something else forced a mode change, so restart all our gl stuff
00338         Cbuf_AddText( "vid_restart\n" );
00339         break;
00340 #endif
00341     case WM_DESTROY:
00342         // let sound and input know about this?
00343         g_wv.hWnd = NULL;
00344         if ( r_fullscreen->integer )
00345         {
00346             WIN_EnableAltTab();
00347         }
00348         break;
00349 
00350     case WM_CLOSE:
00351         Cbuf_ExecuteText( EXEC_APPEND, "quit" );
00352         break;
00353 
00354     case WM_ACTIVATE:
00355         {
00356             int fActive, fMinimized;
00357 
00358             fActive = LOWORD(wParam);
00359             fMinimized = (BOOL) HIWORD(wParam);
00360 
00361             VID_AppActivate( fActive != WA_INACTIVE, fMinimized);
00362             SNDDMA_Activate();
00363         }
00364         break;
00365 
00366     case WM_MOVE:
00367         {
00368             int     xPos, yPos;
00369             RECT r;
00370             int     style;
00371 
00372             if (!r_fullscreen->integer )
00373             {
00374                 xPos = (short) LOWORD(lParam);    // horizontal position 
00375                 yPos = (short) HIWORD(lParam);    // vertical position 
00376 
00377                 r.left   = 0;
00378                 r.top    = 0;
00379                 r.right  = 1;
00380                 r.bottom = 1;
00381 
00382                 style = GetWindowLong( hWnd, GWL_STYLE );
00383                 AdjustWindowRect( &r, style, FALSE );
00384 
00385                 Cvar_SetValue( "vid_xpos", xPos + r.left);
00386                 Cvar_SetValue( "vid_ypos", yPos + r.top);
00387                 vid_xpos->modified = qfalse;
00388                 vid_ypos->modified = qfalse;
00389                 if ( g_wv.activeApp )
00390                 {
00391                     IN_Activate (qtrue);
00392                 }
00393             }
00394         }
00395         break;
00396 
00397 // this is complicated because Win32 seems to pack multiple mouse events into
00398 // one update sometimes, so we always check all states and look for events
00399     case WM_LBUTTONDOWN:
00400     case WM_LBUTTONUP:
00401     case WM_RBUTTONDOWN:
00402     case WM_RBUTTONUP:
00403     case WM_MBUTTONDOWN:
00404     case WM_MBUTTONUP:
00405     case WM_MOUSEMOVE:
00406         {
00407             int temp;
00408 
00409             temp = 0;
00410 
00411             if (wParam & MK_LBUTTON)
00412                 temp |= 1;
00413 
00414             if (wParam & MK_RBUTTON)
00415                 temp |= 2;
00416 
00417             if (wParam & MK_MBUTTON)
00418                 temp |= 4;
00419 
00420             IN_MouseEvent (temp);
00421         }
00422         break;
00423 
00424     case WM_SYSCOMMAND:
00425         if ( wParam == SC_SCREENSAVE )
00426             return 0;
00427         break;
00428 
00429     case WM_SYSKEYDOWN:
00430         if ( wParam == 13 )
00431         {
00432             if ( r_fullscreen )
00433             {
00434                 Cvar_SetValue( "r_fullscreen", !r_fullscreen->integer );
00435                 Cbuf_AddText( "vid_restart\n" );
00436             }
00437             return 0;
00438         }
00439         // fall through
00440     case WM_KEYDOWN:
00441         Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, MapKey( lParam ), qtrue, 0, NULL );
00442         break;
00443 
00444     case WM_SYSKEYUP:
00445     case WM_KEYUP:
00446         Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, MapKey( lParam ), qfalse, 0, NULL );
00447         break;
00448 
00449     case WM_CHAR:
00450         Sys_QueEvent( g_wv.sysMsgTime, SE_CHAR, wParam, 0, 0, NULL );
00451         break;
00452    }
00453 
00454     return DefWindowProc( hWnd, uMsg, wParam, lParam );
00455 }
00456 

Generated on Thu Aug 25 12:38:07 2005 for Quake III Arena by  doxygen 1.3.9.1