123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761 |
- /*
- Copyright (C) 1997-2001 Id Software, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- // Main windowed and fullscreen graphics interface module. This module
- // is used for both the software and OpenGL rendering versions of the
- // Quake refresh engine.
- #include <assert.h>
- #include <float.h>
- #include "..\client\client.h"
- #include "winquake.h"
- //#include "zmouse.h"
- // Structure containing functions exported from refresh DLL
- refexport_t re;
- cvar_t *win_noalttab;
- #ifndef WM_MOUSEWHEEL
- #define WM_MOUSEWHEEL (WM_MOUSELAST+1) // message that will be supported by the OS
- #endif
- static UINT MSH_MOUSEWHEEL;
- // Console variables that we need to access from this module
- cvar_t *vid_gamma;
- cvar_t *vid_ref; // Name of Refresh DLL loaded
- cvar_t *vid_xpos; // X coordinate of window position
- cvar_t *vid_ypos; // Y coordinate of window position
- cvar_t *vid_fullscreen;
- // Global variables used internally by this module
- viddef_t viddef; // global video state; used by other modules
- HINSTANCE reflib_library; // Handle to refresh DLL
- qboolean reflib_active = 0;
- HWND cl_hwnd; // Main window handle for life of program
- #define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) )
- LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
- static qboolean s_alttab_disabled;
- extern unsigned sys_msg_time;
- /*
- ** WIN32 helper functions
- */
- extern qboolean s_win95;
- static void WIN_DisableAltTab( void )
- {
- if ( s_alttab_disabled )
- return;
- if ( s_win95 )
- {
- BOOL old;
- SystemParametersInfo( SPI_SCREENSAVERRUNNING, 1, &old, 0 );
- }
- else
- {
- RegisterHotKey( 0, 0, MOD_ALT, VK_TAB );
- RegisterHotKey( 0, 1, MOD_ALT, VK_RETURN );
- }
- s_alttab_disabled = true;
- }
- static void WIN_EnableAltTab( void )
- {
- if ( s_alttab_disabled )
- {
- if ( s_win95 )
- {
- BOOL old;
- SystemParametersInfo( SPI_SCREENSAVERRUNNING, 0, &old, 0 );
- }
- else
- {
- UnregisterHotKey( 0, 0 );
- UnregisterHotKey( 0, 1 );
- }
- s_alttab_disabled = false;
- }
- }
- /*
- ==========================================================================
- DLL GLUE
- ==========================================================================
- */
- #define MAXPRINTMSG 4096
- void VID_Printf (int print_level, char *fmt, ...)
- {
- va_list argptr;
- char msg[MAXPRINTMSG];
- static qboolean inupdate;
-
- va_start (argptr,fmt);
- vsprintf (msg,fmt,argptr);
- va_end (argptr);
- if (print_level == PRINT_ALL)
- {
- Com_Printf ("%s", msg);
- }
- else if ( print_level == PRINT_DEVELOPER )
- {
- Com_DPrintf ("%s", msg);
- }
- else if ( print_level == PRINT_ALERT )
- {
- MessageBox( 0, msg, "PRINT_ALERT", MB_ICONWARNING );
- OutputDebugString( msg );
- }
- }
- void VID_Error (int err_level, char *fmt, ...)
- {
- va_list argptr;
- char msg[MAXPRINTMSG];
- static qboolean inupdate;
-
- va_start (argptr,fmt);
- vsprintf (msg,fmt,argptr);
- va_end (argptr);
- Com_Error (err_level,"%s", msg);
- }
- //==========================================================================
- byte scantokey[128] =
- {
- // 0 1 2 3 4 5 6 7
- // 8 9 A B C D E F
- 0 , 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0
- 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
- 'o', 'p', '[', ']', 13 , K_CTRL,'a', 's', // 1
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
- '\'' , '`', K_SHIFT,'\\', 'z', 'x', 'c', 'v', // 2
- 'b', 'n', 'm', ',', '.', '/', K_SHIFT,'*',
- K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3
- K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, 0 , K_HOME,
- K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5,K_RIGHTARROW, K_KP_PLUS,K_END, //4
- K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11,
- K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
- };
- /*
- =======
- MapKey
- Map from windows to quake keynums
- =======
- */
- int MapKey (int key)
- {
- int result;
- int modified = ( key >> 16 ) & 255;
- qboolean is_extended = false;
- if ( modified > 127)
- return 0;
- if ( key & ( 1 << 24 ) )
- is_extended = true;
- result = scantokey[modified];
- if ( !is_extended )
- {
- switch ( result )
- {
- case K_HOME:
- return K_KP_HOME;
- case K_UPARROW:
- return K_KP_UPARROW;
- case K_PGUP:
- return K_KP_PGUP;
- case K_LEFTARROW:
- return K_KP_LEFTARROW;
- case K_RIGHTARROW:
- return K_KP_RIGHTARROW;
- case K_END:
- return K_KP_END;
- case K_DOWNARROW:
- return K_KP_DOWNARROW;
- case K_PGDN:
- return K_KP_PGDN;
- case K_INS:
- return K_KP_INS;
- case K_DEL:
- return K_KP_DEL;
- default:
- return result;
- }
- }
- else
- {
- switch ( result )
- {
- case 0x0D:
- return K_KP_ENTER;
- case 0x2F:
- return K_KP_SLASH;
- case 0xAF:
- return K_KP_PLUS;
- }
- return result;
- }
- }
- void AppActivate(BOOL fActive, BOOL minimize)
- {
- Minimized = minimize;
- Key_ClearStates();
- // we don't want to act like we're active if we're minimized
- if (fActive && !Minimized)
- ActiveApp = true;
- else
- ActiveApp = false;
- // minimize/restore mouse-capture on demand
- if (!ActiveApp)
- {
- IN_Activate (false);
- CDAudio_Activate (false);
- S_Activate (false);
- if ( win_noalttab->value )
- {
- WIN_EnableAltTab();
- }
- }
- else
- {
- IN_Activate (true);
- CDAudio_Activate (true);
- S_Activate (true);
- if ( win_noalttab->value )
- {
- WIN_DisableAltTab();
- }
- }
- }
- /*
- ====================
- MainWndProc
- main window procedure
- ====================
- */
- LONG WINAPI MainWndProc (
- HWND hWnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
- {
- LONG lRet = 0;
- if ( uMsg == MSH_MOUSEWHEEL )
- {
- if ( ( ( int ) wParam ) > 0 )
- {
- Key_Event( K_MWHEELUP, true, sys_msg_time );
- Key_Event( K_MWHEELUP, false, sys_msg_time );
- }
- else
- {
- Key_Event( K_MWHEELDOWN, true, sys_msg_time );
- Key_Event( K_MWHEELDOWN, false, sys_msg_time );
- }
- return DefWindowProc (hWnd, uMsg, wParam, lParam);
- }
- switch (uMsg)
- {
- case WM_MOUSEWHEEL:
- /*
- ** this chunk of code theoretically only works under NT4 and Win98
- ** since this message doesn't exist under Win95
- */
- if ( ( short ) HIWORD( wParam ) > 0 )
- {
- Key_Event( K_MWHEELUP, true, sys_msg_time );
- Key_Event( K_MWHEELUP, false, sys_msg_time );
- }
- else
- {
- Key_Event( K_MWHEELDOWN, true, sys_msg_time );
- Key_Event( K_MWHEELDOWN, false, sys_msg_time );
- }
- break;
- case WM_HOTKEY:
- return 0;
- case WM_CREATE:
- cl_hwnd = hWnd;
- MSH_MOUSEWHEEL = RegisterWindowMessage("MSWHEEL_ROLLMSG");
- return DefWindowProc (hWnd, uMsg, wParam, lParam);
- case WM_PAINT:
- SCR_DirtyScreen (); // force entire screen to update next frame
- return DefWindowProc (hWnd, uMsg, wParam, lParam);
- case WM_DESTROY:
- // let sound and input know about this?
- cl_hwnd = NULL;
- return DefWindowProc (hWnd, uMsg, wParam, lParam);
- case WM_ACTIVATE:
- {
- int fActive, fMinimized;
- // KJB: Watch this for problems in fullscreen modes with Alt-tabbing.
- fActive = LOWORD(wParam);
- fMinimized = (BOOL) HIWORD(wParam);
- AppActivate( fActive != WA_INACTIVE, fMinimized);
- if ( reflib_active )
- re.AppActivate( !( fActive == WA_INACTIVE ) );
- }
- return DefWindowProc (hWnd, uMsg, wParam, lParam);
- case WM_MOVE:
- {
- int xPos, yPos;
- RECT r;
- int style;
- if (!vid_fullscreen->value)
- {
- xPos = (short) LOWORD(lParam); // horizontal position
- yPos = (short) HIWORD(lParam); // vertical position
- r.left = 0;
- r.top = 0;
- r.right = 1;
- r.bottom = 1;
- style = GetWindowLong( hWnd, GWL_STYLE );
- AdjustWindowRect( &r, style, FALSE );
- Cvar_SetValue( "vid_xpos", xPos + r.left);
- Cvar_SetValue( "vid_ypos", yPos + r.top);
- vid_xpos->modified = false;
- vid_ypos->modified = false;
- if (ActiveApp)
- IN_Activate (true);
- }
- }
- return DefWindowProc (hWnd, uMsg, wParam, lParam);
- // this is complicated because Win32 seems to pack multiple mouse events into
- // one update sometimes, so we always check all states and look for events
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_RBUTTONDOWN:
- case WM_RBUTTONUP:
- case WM_MBUTTONDOWN:
- case WM_MBUTTONUP:
- case WM_MOUSEMOVE:
- {
- int temp;
- temp = 0;
- if (wParam & MK_LBUTTON)
- temp |= 1;
- if (wParam & MK_RBUTTON)
- temp |= 2;
- if (wParam & MK_MBUTTON)
- temp |= 4;
- IN_MouseEvent (temp);
- }
- break;
- case WM_SYSCOMMAND:
- if ( wParam == SC_SCREENSAVE )
- return 0;
- return DefWindowProc (hWnd, uMsg, wParam, lParam);
- case WM_SYSKEYDOWN:
- if ( wParam == 13 )
- {
- if ( vid_fullscreen )
- {
- Cvar_SetValue( "vid_fullscreen", !vid_fullscreen->value );
- }
- return 0;
- }
- // fall through
- case WM_KEYDOWN:
- Key_Event( MapKey( lParam ), true, sys_msg_time);
- break;
- case WM_SYSKEYUP:
- case WM_KEYUP:
- Key_Event( MapKey( lParam ), false, sys_msg_time);
- break;
- case MM_MCINOTIFY:
- {
- LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
- lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
- }
- break;
- default: // pass all unhandled messages to DefWindowProc
- return DefWindowProc (hWnd, uMsg, wParam, lParam);
- }
- /* return 0 if handled message, 1 if not */
- return DefWindowProc( hWnd, uMsg, wParam, lParam );
- }
- /*
- ============
- VID_Restart_f
- Console command to re-start the video mode and refresh DLL. We do this
- simply by setting the modified flag for the vid_ref variable, which will
- cause the entire video mode and refresh DLL to be reset on the next frame.
- ============
- */
- void VID_Restart_f (void)
- {
- vid_ref->modified = true;
- }
- void VID_Front_f( void )
- {
- SetWindowLong( cl_hwnd, GWL_EXSTYLE, WS_EX_TOPMOST );
- SetForegroundWindow( cl_hwnd );
- }
- /*
- ** VID_GetModeInfo
- */
- typedef struct vidmode_s
- {
- const char *description;
- int width, height;
- int mode;
- } vidmode_t;
- vidmode_t vid_modes[] =
- {
- { "Mode 0: 320x240", 320, 240, 0 },
- { "Mode 1: 400x300", 400, 300, 1 },
- { "Mode 2: 512x384", 512, 384, 2 },
- { "Mode 3: 640x480", 640, 480, 3 },
- { "Mode 4: 800x600", 800, 600, 4 },
- { "Mode 5: 960x720", 960, 720, 5 },
- { "Mode 6: 1024x768", 1024, 768, 6 },
- { "Mode 7: 1152x864", 1152, 864, 7 },
- { "Mode 8: 1280x960", 1280, 960, 8 },
- { "Mode 9: 1600x1200", 1600, 1200, 9 }
- };
- qboolean VID_GetModeInfo( int *width, int *height, int mode )
- {
- if ( mode < 0 || mode >= VID_NUM_MODES )
- return false;
- *width = vid_modes[mode].width;
- *height = vid_modes[mode].height;
- return true;
- }
- /*
- ** VID_UpdateWindowPosAndSize
- */
- void VID_UpdateWindowPosAndSize( int x, int y )
- {
- RECT r;
- int style;
- int w, h;
- r.left = 0;
- r.top = 0;
- r.right = viddef.width;
- r.bottom = viddef.height;
- style = GetWindowLong( cl_hwnd, GWL_STYLE );
- AdjustWindowRect( &r, style, FALSE );
- w = r.right - r.left;
- h = r.bottom - r.top;
- MoveWindow( cl_hwnd, vid_xpos->value, vid_ypos->value, w, h, TRUE );
- }
- /*
- ** VID_NewWindow
- */
- void VID_NewWindow ( int width, int height)
- {
- viddef.width = width;
- viddef.height = height;
- cl.force_refdef = true; // can't use a paused refdef
- }
- void VID_FreeReflib (void)
- {
- if ( !FreeLibrary( reflib_library ) )
- Com_Error( ERR_FATAL, "Reflib FreeLibrary failed" );
- memset (&re, 0, sizeof(re));
- reflib_library = NULL;
- reflib_active = false;
- }
- /*
- ==============
- VID_LoadRefresh
- ==============
- */
- qboolean VID_LoadRefresh( char *name )
- {
- refimport_t ri;
- GetRefAPI_t GetRefAPI;
-
- if ( reflib_active )
- {
- re.Shutdown();
- VID_FreeReflib ();
- }
- Com_Printf( "------- Loading %s -------\n", name );
- if ( ( reflib_library = LoadLibrary( name ) ) == 0 )
- {
- Com_Printf( "LoadLibrary(\"%s\") failed\n", name );
- return false;
- }
- ri.Cmd_AddCommand = Cmd_AddCommand;
- ri.Cmd_RemoveCommand = Cmd_RemoveCommand;
- ri.Cmd_Argc = Cmd_Argc;
- ri.Cmd_Argv = Cmd_Argv;
- ri.Cmd_ExecuteText = Cbuf_ExecuteText;
- ri.Con_Printf = VID_Printf;
- ri.Sys_Error = VID_Error;
- ri.FS_LoadFile = FS_LoadFile;
- ri.FS_FreeFile = FS_FreeFile;
- ri.FS_Gamedir = FS_Gamedir;
- ri.Cvar_Get = Cvar_Get;
- ri.Cvar_Set = Cvar_Set;
- ri.Cvar_SetValue = Cvar_SetValue;
- ri.Vid_GetModeInfo = VID_GetModeInfo;
- ri.Vid_MenuInit = VID_MenuInit;
- ri.Vid_NewWindow = VID_NewWindow;
- if ( ( GetRefAPI = (void *) GetProcAddress( reflib_library, "GetRefAPI" ) ) == 0 )
- Com_Error( ERR_FATAL, "GetProcAddress failed on %s", name );
- re = GetRefAPI( ri );
- if (re.api_version != API_VERSION)
- {
- VID_FreeReflib ();
- Com_Error (ERR_FATAL, "%s has incompatible api_version", name);
- }
- if ( re.Init( global_hInstance, MainWndProc ) == -1 )
- {
- re.Shutdown();
- VID_FreeReflib ();
- return false;
- }
- Com_Printf( "------------------------------------\n");
- reflib_active = true;
- //======
- //PGM
- vidref_val = VIDREF_OTHER;
- if(vid_ref)
- {
- if(!strcmp (vid_ref->string, "gl"))
- vidref_val = VIDREF_GL;
- else if(!strcmp(vid_ref->string, "soft"))
- vidref_val = VIDREF_SOFT;
- }
- //PGM
- //======
- return true;
- }
- /*
- ============
- VID_CheckChanges
- This function gets called once just before drawing each frame, and it's sole purpose in life
- is to check to see if any of the video mode parameters have changed, and if they have to
- update the rendering DLL and/or video mode to match.
- ============
- */
- void VID_CheckChanges (void)
- {
- char name[100];
- if ( win_noalttab->modified )
- {
- if ( win_noalttab->value )
- {
- WIN_DisableAltTab();
- }
- else
- {
- WIN_EnableAltTab();
- }
- win_noalttab->modified = false;
- }
- if ( vid_ref->modified )
- {
- cl.force_refdef = true; // can't use a paused refdef
- S_StopAllSounds();
- }
- while (vid_ref->modified)
- {
- /*
- ** refresh has changed
- */
- vid_ref->modified = false;
- vid_fullscreen->modified = true;
- cl.refresh_prepped = false;
- cls.disable_screen = true;
- Com_sprintf( name, sizeof(name), "ref_%s.dll", vid_ref->string );
- if ( !VID_LoadRefresh( name ) )
- {
- if ( strcmp (vid_ref->string, "soft") == 0 )
- Com_Error (ERR_FATAL, "Couldn't fall back to software refresh!");
- Cvar_Set( "vid_ref", "soft" );
- /*
- ** drop the console if we fail to load a refresh
- */
- if ( cls.key_dest != key_console )
- {
- Con_ToggleConsole_f();
- }
- }
- cls.disable_screen = false;
- }
- /*
- ** update our window position
- */
- if ( vid_xpos->modified || vid_ypos->modified )
- {
- if (!vid_fullscreen->value)
- VID_UpdateWindowPosAndSize( vid_xpos->value, vid_ypos->value );
- vid_xpos->modified = false;
- vid_ypos->modified = false;
- }
- }
- /*
- ============
- VID_Init
- ============
- */
- void VID_Init (void)
- {
- /* Create the video variables so we know how to start the graphics drivers */
- vid_ref = Cvar_Get ("vid_ref", "soft", CVAR_ARCHIVE);
- vid_xpos = Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE);
- vid_ypos = Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE);
- vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE);
- vid_gamma = Cvar_Get( "vid_gamma", "1", CVAR_ARCHIVE );
- win_noalttab = Cvar_Get( "win_noalttab", "0", CVAR_ARCHIVE );
- /* Add some console commands that we want to handle */
- Cmd_AddCommand ("vid_restart", VID_Restart_f);
- Cmd_AddCommand ("vid_front", VID_Front_f);
- /*
- ** this is a gross hack but necessary to clamp the mode for 3Dfx
- */
- #if 0
- {
- cvar_t *gl_driver = Cvar_Get( "gl_driver", "opengl32", 0 );
- cvar_t *gl_mode = Cvar_Get( "gl_mode", "3", 0 );
- if ( stricmp( gl_driver->string, "3dfxgl" ) == 0 )
- {
- Cvar_SetValue( "gl_mode", 3 );
- viddef.width = 640;
- viddef.height = 480;
- }
- }
- #endif
- /* Disable the 3Dfx splash screen */
- putenv("FX_GLIDE_NO_SPLASH=0");
-
- /* Start the graphics mode and load refresh DLL */
- VID_CheckChanges();
- }
- /*
- ============
- VID_Shutdown
- ============
- */
- void VID_Shutdown (void)
- {
- if ( reflib_active )
- {
- re.Shutdown ();
- VID_FreeReflib ();
- }
- }
|