1/* 2Copyright (C) 1996-1997 Id Software, Inc. 3 4This program is free software; you can redistribute it and/or 5modify it under the terms of the GNU General Public License 6as published by the Free Software Foundation; either version 2 7of the License, or (at your option) any later version. 8 9This program is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13See the GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program; if not, write to the Free Software 17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19*/ 20// in_sun.c -- SUN/X mouse input handler 21 22#include <sys/time.h> 23#include <sys/types.h> 24#include <unistd.h> 25#include <signal.h> 26#include <stdlib.h> 27#include <stdio.h> 28#include <string.h> 29#include <sys/ipc.h> 30#include <sys/shm.h> 31#include <X11/Xlib.h> 32#include <X11/Xutil.h> 33#include <X11/Xatom.h> 34#include <X11/keysym.h> 35 36#include "quakedef.h" 37 38 39// 40// typedefs and defines 41// 42 43#define MOUSE_SCALE 4 44 45// 46// externs 47// 48 49extern Display *x_disp; 50extern int x_screen, x_screen_width, x_screen_height; 51extern int x_center_height, x_center_width; 52extern int x_std_event_mask; 53extern Window x_win, x_root_win; 54extern qboolean x_fullscreen; 55extern qboolean x_focus; 56extern int global_dx, global_dy; 57// 58// globals 59// 60 61cvar_t _windowed_mouse = {"_windowed_mouse","1", true}; 62int x_root, y_root; 63int x_root_old, y_root_old; 64// 65// locals 66// 67 68static int x_mouse_num, x_mouse_denom, x_mouse_thresh; 69 70 71static qboolean x_grabbed = false; 72 73// 74// IN_CenterMouse - center the mouse in the screen 75// 76 77void IN_CenterMouse( void ) 78{ 79 CheckMouseState(); 80 81 if (!x_grabbed) 82 return; 83 84 XSelectInput( x_disp, x_win, x_std_event_mask & ~PointerMotionMask ); 85 XWarpPointer( x_disp, None, x_root_win, 0, 0, 0, 0, x_center_width, 86 x_center_height ); 87 XSelectInput( x_disp, x_win, x_std_event_mask ); 88} 89 90// 91// Check to see if we have grabbed the mouse or not and deal with it 92// appropriately 93// 94static void CheckMouseState(void) 95{ 96 if (x_focus && _windowed_mouse.value && !x_grabbed) { 97 x_grabbed = true; 98 printf("fooling with mouse!\n"); 99 if (XGetPointerControl( x_disp, &x_mouse_num, &x_mouse_denom, &x_mouse_thresh )) 100 printf( "XGetPointerControl failed!\n" ); 101 //printf( "mouse %d/%d thresh %d\n", x_mouse_num, x_mouse_denom, x_mouse_thresh ); 102 103 // make input rawer 104 XAutoRepeatOff(x_disp); 105 XGrabKeyboard(x_disp, x_win, True, GrabModeAsync, GrabModeAsync, CurrentTime); 106 XGrabPointer(x_disp, x_win, True, 107 PointerMotionMask | ButtonPressMask | ButtonReleaseMask, 108 GrabModeAsync, GrabModeAsync, None, None, CurrentTime); 109 110// if (XChangePointerControl( x_disp, True, True, 1, MOUSE_SCALE, x_mouse_thresh )) 111// printf( "XChangePointerControl failed!\n" ); 112 113 IN_CenterMouse(); 114 115 // safe initial values 116 x_root = x_root_old = vid.width >> 1; 117 y_root = y_root_old = vid.height >> 1; 118 } else if (x_grabbed && (!_windowed_mouse.value || !x_focus)) { 119 printf("fooling with mouse!\n"); 120 x_grabbed = false; 121 // undo mouse warp 122 if (XChangePointerControl( x_disp, True, True, x_mouse_num, x_mouse_denom, x_mouse_thresh )) 123 printf( "XChangePointerControl failed!\n" ); 124 125 XUngrabPointer( x_disp, CurrentTime ); 126 XUngrabKeyboard( x_disp, CurrentTime ); 127 XAutoRepeatOn( x_disp ); 128 } 129} 130 131 132// 133// IN_Init - setup mouse input 134// 135 136void IN_Init (void) 137{ 138 if (!x_disp) Sys_Error( "X display not open!\n" ); 139 140 Cvar_RegisterVariable (&_windowed_mouse); 141 142 // we really really want to clean these up... 143 atexit( IN_Shutdown ); 144} 145 146// 147// IN_Shutdown - clean up mouse settings (must be done from signal handler too!) 148// 149 150void IN_Shutdown (void) 151{ 152 if (!x_disp) return; 153 154 // undo mouse warp 155 if (XChangePointerControl( x_disp, True, True, x_mouse_num, x_mouse_denom, x_mouse_thresh )) 156 printf( "XChangePointerControl failed!\n" ); 157 158 XUngrabPointer( x_disp, CurrentTime ); 159 XUngrabKeyboard( x_disp, CurrentTime ); 160 XAutoRepeatOn( x_disp ); 161} 162 163// 164// IN_Commands - process buttons 165// 166 167void IN_Commands (void) 168{ 169 // done in X event handler 170} 171 172// 173// IN_Move - process mouse moves 174// 175 176void 177IN_Move (usercmd_t *cmd) 178{ 179 static int last_dx, last_dy; 180 static long long last_movement; 181 long long now, gethrtime(); 182 183 int dx, dy; 184 185 CheckMouseState(); 186 187 188 if (!x_grabbed) 189 return; // no mouse movement 190 191 192 now = gethrtime(); 193 194 dx = global_dx; 195 global_dx = 0; 196 197 dy = global_dy; 198 global_dy = 0; 199 200// printf("GOT: dx %d dy %d\n", dx, dy); 201 202 dx *= sensitivity.value; 203 dy *= sensitivity.value; 204 205// 206// implement low pass filter to smooth motion a bit 207// 208 if (now - last_movement > 100000000) { 209 dx = .6 * dx; 210 dy = .6 * dy; 211 } 212 last_movement = now; 213 214 dx = .6 * dx + .4 * last_dx; 215 dy = .6 * dy + .4 * last_dy; 216 217 218 last_dx = dx; 219 last_dy = dy; 220 221 if (!dx && !dy) { 222 if (in_mlook.state & 1) 223 V_StopPitchDrift (); 224 return; 225 } 226 227 // add mouse X/Y movement to cmd 228 if ((in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1))) 229 cmd->sidemove += m_side.value * dx; 230 else 231 cl.viewangles[YAW] -= m_yaw.value * dx; 232 233 if (in_mlook.state & 1) 234 V_StopPitchDrift (); 235 236 if ((in_mlook.state & 1) && !(in_strafe.state & 1)) { 237 cl.viewangles[PITCH] += m_pitch.value * dy; 238 if (cl.viewangles[PITCH] > 80) cl.viewangles[PITCH] = 80; 239 if (cl.viewangles[PITCH] < -70) cl.viewangles[PITCH] = -70; 240 } 241 else { 242 if ((in_strafe.state & 1) && noclip_anglehack) cmd->upmove -= m_forward.value * dy; 243 else cmd->forwardmove -= m_forward.value * dy; 244 } 245} 246