diff options
author | Paweł Redman <pawel.redman@gmail.com> | 2017-03-22 17:56:34 +0100 |
---|---|---|
committer | Paweł Redman <pawel.redman@gmail.com> | 2017-03-22 17:56:34 +0100 |
commit | 6a777afc079c2a8d3af3ecd2145fe8dd50567a39 (patch) | |
tree | 520f4489cebf8564ef6cb27064ceea45cbc005b3 /src/win32/win_wndproc.c |
Diffstat (limited to 'src/win32/win_wndproc.c')
-rw-r--r-- | src/win32/win_wndproc.c | 457 |
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 ); +} + |