summaryrefslogtreecommitdiff
path: root/src/win32/win_wndproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/win32/win_wndproc.c')
-rw-r--r--src/win32/win_wndproc.c457
1 files changed, 457 insertions, 0 deletions
diff --git a/src/win32/win_wndproc.c b/src/win32/win_wndproc.c
new file mode 100644
index 0000000..334d97a
--- /dev/null
+++ b/src/win32/win_wndproc.c
@@ -0,0 +1,457 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+Copyright (C) 2000-2006 Tim Angus
+
+This file is part of Tremulous.
+
+Tremulous 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.
+
+Tremulous 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 Tremulous; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+#include "../client/client.h"
+#include "win_local.h"
+
+WinVars_t g_wv;
+
+#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_xpos; // X coordinate of window position
+cvar_t *vid_ypos; // Y coordinate of window position
+cvar_t *r_fullscreen;
+
+#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;
+
+static void WIN_DisableAltTab( void )
+{
+ if ( s_alttab_disabled )
+ return;
+
+ if ( !Q_stricmp( Cvar_VariableString( "arch" ), "winnt" ) )
+ {
+ RegisterHotKey( 0, 0, MOD_ALT, VK_TAB );
+ }
+ else
+ {
+ BOOL old;
+
+ SystemParametersInfo( SPI_SETSCREENSAVERRUNNING, 1, &old, 0 );
+ }
+ s_alttab_disabled = qtrue;
+}
+
+static void WIN_EnableAltTab( void )
+{
+ if ( s_alttab_disabled )
+ {
+ if ( !Q_stricmp( Cvar_VariableString( "arch" ), "winnt" ) )
+ {
+ UnregisterHotKey( 0, 0 );
+ }
+ else
+ {
+ BOOL old;
+
+ SystemParametersInfo( SPI_SETSCREENSAVERRUNNING, 0, &old, 0 );
+ }
+
+ s_alttab_disabled = qfalse;
+ }
+}
+
+/*
+==================
+VID_AppActivate
+==================
+*/
+static void VID_AppActivate(BOOL fActive, BOOL minimize)
+{
+ g_wv.isMinimized = minimize;
+
+ Com_DPrintf("VID_AppActivate: %i\n", fActive );
+
+ Key_ClearStates(); // FIXME!!!
+
+ // we don't want to act like we're active if we're minimized
+ if (fActive && !g_wv.isMinimized )
+ {
+ g_wv.activeApp = qtrue;
+ }
+ else
+ {
+ g_wv.activeApp = qfalse;
+ }
+
+ // minimize/restore mouse-capture on demand
+ if (!g_wv.activeApp )
+ {
+ IN_Activate (qfalse);
+ }
+ else
+ {
+ IN_Activate (qtrue);
+ }
+}
+
+//==========================================================================
+
+static byte s_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,' ', K_CAPSLOCK , 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
+=======
+*/
+static int MapKey (int key)
+{
+ int result;
+ int modified;
+ qboolean is_extended;
+
+// Com_Printf( "0x%x\n", key);
+
+ modified = ( key >> 16 ) & 255;
+
+ if ( modified > 127 )
+ return 0;
+
+ if ( key & ( 1 << 24 ) )
+ {
+ is_extended = qtrue;
+ }
+ else
+ {
+ is_extended = qfalse;
+ }
+
+ result = s_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 K_PAUSE:
+ return K_KP_NUMLOCK;
+ case 0x0D:
+ return K_KP_ENTER;
+ case 0x2F:
+ return K_KP_SLASH;
+ case 0xAF:
+ return K_KP_PLUS;
+ }
+ return result;
+ }
+}
+
+
+/*
+====================
+MainWndProc
+
+main window procedure
+====================
+*/
+extern cvar_t *in_mouse;
+extern cvar_t *in_logitechbug;
+LONG WINAPI MainWndProc (
+ HWND hWnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ static qboolean flip = qtrue;
+ int zDelta, i;
+
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/mouseinput/aboutmouseinput.asp
+ // Windows 95, Windows NT 3.51 - uses MSH_MOUSEWHEEL
+ // only relevant for non-DI input
+ //
+ // NOTE: not sure how reliable this is anymore, might trigger double wheel events
+ if (in_mouse->integer != 1)
+ {
+ if ( uMsg == MSH_MOUSEWHEEL )
+ {
+ if ( ( ( int ) wParam ) > 0 )
+ {
+ Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, qtrue, 0, NULL );
+ Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, qfalse, 0, NULL );
+ }
+ else
+ {
+ Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, qtrue, 0, NULL );
+ Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, qfalse, 0, NULL );
+ }
+ return DefWindowProc (hWnd, uMsg, wParam, lParam);
+ }
+ }
+
+ switch (uMsg)
+ {
+ case WM_MOUSEWHEEL:
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/mouseinput/aboutmouseinput.asp
+ // Windows 98/Me, Windows NT 4.0 and later - uses WM_MOUSEWHEEL
+ // only relevant for non-DI input and when console is toggled in window mode
+ // if console is toggled in window mode (KEYCATCH_CONSOLE) then mouse is released and DI doesn't see any mouse wheel
+ if (in_mouse->integer != 1 || (!r_fullscreen->integer && (cls.keyCatchers & KEYCATCH_CONSOLE)))
+ {
+ // 120 increments, might be 240 and multiples if wheel goes too fast
+ // NOTE Logitech: logitech drivers are screwed and send the message twice?
+ // could add a cvar to interpret the message as successive press/release events
+ zDelta = ( short ) HIWORD( wParam ) / 120;
+ if ( zDelta > 0 )
+ {
+ for(i=0; i<zDelta; i++)
+ {
+ if (!in_logitechbug->integer)
+ {
+ Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, qtrue, 0, NULL );
+ Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, qfalse, 0, NULL );
+ }
+ else
+ {
+ Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, flip, 0, NULL );
+ flip = !flip;
+ }
+ }
+ }
+ else
+ {
+ for(i=0; i<-zDelta; i++)
+ {
+ if (!in_logitechbug->integer)
+ {
+ Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, qtrue, 0, NULL );
+ Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, qfalse, 0, NULL );
+ }
+ else
+ {
+ Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, flip, 0, NULL );
+ flip = !flip;
+ }
+ }
+ }
+ // when an application processes the WM_MOUSEWHEEL message, it must return zero
+ return 0;
+ }
+ break;
+
+ case WM_CREATE:
+
+ g_wv.hWnd = hWnd;
+
+ vid_xpos = Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE);
+ vid_ypos = Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE);
+ r_fullscreen = Cvar_Get ("r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH );
+
+ MSH_MOUSEWHEEL = RegisterWindowMessage("MSWHEEL_ROLLMSG");
+ if ( r_fullscreen->integer )
+ {
+ WIN_DisableAltTab();
+ }
+ else
+ {
+ WIN_EnableAltTab();
+ }
+
+ break;
+#if 0
+ case WM_DISPLAYCHANGE:
+ Com_DPrintf( "WM_DISPLAYCHANGE\n" );
+ // we need to force a vid_restart if the user has changed
+ // their desktop resolution while the game is running,
+ // but don't do anything if the message is a result of
+ // our own calling of ChangeDisplaySettings
+ if ( com_insideVidInit ) {
+ break; // we did this on purpose
+ }
+ // something else forced a mode change, so restart all our gl stuff
+ Cbuf_AddText( "vid_restart\n" );
+ break;
+#endif
+ case WM_DESTROY:
+ // let sound and input know about this?
+ g_wv.hWnd = NULL;
+ if ( r_fullscreen->integer )
+ {
+ WIN_EnableAltTab();
+ }
+ break;
+
+ case WM_CLOSE:
+ Cbuf_ExecuteText( EXEC_APPEND, "quit" );
+ break;
+
+ case WM_ACTIVATE:
+ {
+ int fActive, fMinimized;
+
+ fActive = LOWORD(wParam);
+ fMinimized = (BOOL) HIWORD(wParam);
+
+ VID_AppActivate( fActive != WA_INACTIVE, fMinimized);
+ SNDDMA_Activate();
+ }
+ break;
+
+ case WM_MOVE:
+ {
+ int xPos, yPos;
+ RECT r;
+ int style;
+
+ if (!r_fullscreen->integer )
+ {
+ 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 = qfalse;
+ vid_ypos->modified = qfalse;
+ if ( g_wv.activeApp )
+ {
+ IN_Activate (qtrue);
+ }
+ }
+ }
+ break;
+
+// 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;
+ break;
+
+ case WM_SYSKEYDOWN:
+ if ( wParam == 13 )
+ {
+ if ( r_fullscreen )
+ {
+ Cvar_SetValue( "r_fullscreen", !r_fullscreen->integer );
+ Cbuf_AddText( "vid_restart\n" );
+ }
+ return 0;
+ }
+ // fall through
+ case WM_KEYDOWN:
+ Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, MapKey( lParam ), qtrue, 0, NULL );
+ break;
+
+ case WM_SYSKEYUP:
+ case WM_KEYUP:
+ Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, MapKey( lParam ), qfalse, 0, NULL );
+ break;
+
+ case WM_CHAR:
+ Sys_QueEvent( g_wv.sysMsgTime, SE_CHAR, wParam, 0, 0, NULL );
+ break;
+ }
+
+ return DefWindowProc( hWnd, uMsg, wParam, lParam );
+}
+