1 /* 2 Copyright (C) 1996-1997 Id Software, Inc. 3 4 This program is free software; you can redistribute it and/or 5 modify it under the terms of the GNU General Public License 6 as published by the Free Software Foundation; either version 2 7 of the License, or (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 See the GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, 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 49 extern Display *x_disp; 50 extern int x_screen, x_screen_width, x_screen_height; 51 extern int x_center_height, x_center_width; 52 extern int x_std_event_mask; 53 extern Window x_win, x_root_win; 54 extern qboolean x_fullscreen; 55 extern qboolean x_focus; 56 extern int global_dx, global_dy; 57 // 58 // globals 59 // 60 61 cvar_t _windowed_mouse = {"_windowed_mouse","1", true}; 62 int x_root, y_root; 63 int x_root_old, y_root_old; 64 // 65 // locals 66 // 67 68 static int x_mouse_num, x_mouse_denom, x_mouse_thresh; 69 70 71 static qboolean x_grabbed = false; 72 73 // 74 // IN_CenterMouse - center the mouse in the screen 75 // 76 77 void 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 // 94 static 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 136 void 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 150 void 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 167 void IN_Commands (void) 168 { 169 // done in X event handler 170 } 171 172 // 173 // IN_Move - process mouse moves 174 // 175 176 void 177 IN_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