00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://www.ogre3d.org/ 00006 00007 Copyright © 2000-2004 The OGRE Team 00008 Also see acknowledgements in Readme.html 00009 00010 This program is free software; you can redistribute it and/or modify it under 00011 the terms of the GNU Lesser General Public License as published by the Free Software 00012 Foundation; either version 2 of the License, or (at your option) any later 00013 version. 00014 00015 This program is distributed in the hope that it will be useful, but WITHOUT 00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License along with 00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to 00022 http://www.gnu.org/copyleft/lesser.txt. 00023 ----------------------------------------------------------------------------- 00024 */ 00025 00026 #include "OgreGLXInput.h" 00027 #include "OgreLogManager.h" 00028 #include "OgreMouseEvent.h" 00029 #include "OgreCursor.h" 00030 00031 #include "OgreGLXWindow.h" 00032 00033 #include <X11/Xlib.h> 00034 #include <X11/Xutil.h> 00035 #include <X11/keysym.h> 00036 #include <X11/extensions/xf86vmode.h> 00037 00038 namespace Ogre { 00039 00040 GLXInput::GLXInput() 00041 : InputReader(), 00042 mMouseSpeed(0.002f) { 00043 mEventQueue = 0; 00044 00045 _key_map.insert(InputKeyMap::value_type(XK_Escape,KC_ESCAPE)); 00046 _key_map.insert(InputKeyMap::value_type(XK_1, KC_1)); 00047 _key_map.insert(InputKeyMap::value_type(XK_2, KC_2)); 00048 _key_map.insert(InputKeyMap::value_type(XK_3, KC_3)); 00049 _key_map.insert(InputKeyMap::value_type(XK_4, KC_4)); 00050 _key_map.insert(InputKeyMap::value_type(XK_5, KC_5)); 00051 _key_map.insert(InputKeyMap::value_type(XK_6, KC_6)); 00052 _key_map.insert(InputKeyMap::value_type(XK_7, KC_7)); 00053 _key_map.insert(InputKeyMap::value_type(XK_8, KC_8)); 00054 _key_map.insert(InputKeyMap::value_type(XK_9, KC_9)); 00055 _key_map.insert(InputKeyMap::value_type(XK_0, KC_0)); 00056 _key_map.insert(InputKeyMap::value_type(XK_minus, KC_MINUS)); 00057 _key_map.insert(InputKeyMap::value_type(XK_equal, KC_EQUALS)); 00058 _key_map.insert(InputKeyMap::value_type(XK_BackSpace, KC_BACK)); 00059 _key_map.insert(InputKeyMap::value_type(XK_Tab, KC_TAB)); 00060 _key_map.insert(InputKeyMap::value_type(XK_q, KC_Q)); 00061 _key_map.insert(InputKeyMap::value_type(XK_w, KC_W)); 00062 _key_map.insert(InputKeyMap::value_type(XK_e, KC_E)); 00063 _key_map.insert(InputKeyMap::value_type(XK_r, KC_R)); 00064 _key_map.insert(InputKeyMap::value_type(XK_t, KC_T)); 00065 _key_map.insert(InputKeyMap::value_type(XK_y, KC_Y)); 00066 _key_map.insert(InputKeyMap::value_type(XK_u, KC_U)); 00067 _key_map.insert(InputKeyMap::value_type(XK_i, KC_I)); 00068 _key_map.insert(InputKeyMap::value_type(XK_o, KC_O)); 00069 _key_map.insert(InputKeyMap::value_type(XK_p, KC_P)); 00070 _key_map.insert(InputKeyMap::value_type(XK_Return, KC_RETURN)); 00071 _key_map.insert(InputKeyMap::value_type(XK_Control_L, KC_LCONTROL)); 00072 _key_map.insert(InputKeyMap::value_type(XK_a, KC_A)); 00073 _key_map.insert(InputKeyMap::value_type(XK_s, KC_S)); 00074 _key_map.insert(InputKeyMap::value_type(XK_d, KC_D)); 00075 _key_map.insert(InputKeyMap::value_type(XK_f, KC_F)); 00076 _key_map.insert(InputKeyMap::value_type(XK_g, KC_G)); 00077 _key_map.insert(InputKeyMap::value_type(XK_h, KC_H)); 00078 _key_map.insert(InputKeyMap::value_type(XK_j, KC_J)); 00079 _key_map.insert(InputKeyMap::value_type(XK_k, KC_K)); 00080 _key_map.insert(InputKeyMap::value_type(XK_l, KC_L)); 00081 _key_map.insert(InputKeyMap::value_type(XK_semicolon, KC_SEMICOLON)); 00082 _key_map.insert(InputKeyMap::value_type(XK_colon, KC_COLON)); 00083 _key_map.insert(InputKeyMap::value_type(XK_apostrophe, KC_APOSTROPHE)); 00084 _key_map.insert(InputKeyMap::value_type(XK_grave, KC_GRAVE)); 00085 _key_map.insert(InputKeyMap::value_type(XK_Shift_L, KC_LSHIFT)); 00086 _key_map.insert(InputKeyMap::value_type(XK_backslash, KC_BACKSLASH)); 00087 _key_map.insert(InputKeyMap::value_type(XK_z, KC_Z)); 00088 _key_map.insert(InputKeyMap::value_type(XK_x, KC_X)); 00089 _key_map.insert(InputKeyMap::value_type(XK_c, KC_C)); 00090 _key_map.insert(InputKeyMap::value_type(XK_v, KC_V)); 00091 _key_map.insert(InputKeyMap::value_type(XK_b, KC_B)); 00092 _key_map.insert(InputKeyMap::value_type(XK_n, KC_N)); 00093 _key_map.insert(InputKeyMap::value_type(XK_m, KC_M)); 00094 _key_map.insert(InputKeyMap::value_type(XK_comma, KC_COMMA)); 00095 _key_map.insert(InputKeyMap::value_type(XK_period, KC_PERIOD)); 00096 _key_map.insert(InputKeyMap::value_type(XK_Shift_R, KC_RSHIFT)); 00097 _key_map.insert(InputKeyMap::value_type(XK_KP_Multiply, KC_MULTIPLY)); 00098 _key_map.insert(InputKeyMap::value_type(XK_Alt_L, KC_LMENU)); // ? 00099 _key_map.insert(InputKeyMap::value_type(XK_space, KC_SPACE)); 00100 _key_map.insert(InputKeyMap::value_type(XK_Escape, KC_CAPITAL)); 00101 _key_map.insert(InputKeyMap::value_type(XK_F1, KC_F1)); 00102 _key_map.insert(InputKeyMap::value_type(XK_F2, KC_F2)); 00103 _key_map.insert(InputKeyMap::value_type(XK_F3, KC_F3)); 00104 _key_map.insert(InputKeyMap::value_type(XK_F4, KC_F4)); 00105 _key_map.insert(InputKeyMap::value_type(XK_F5, KC_F5)); 00106 _key_map.insert(InputKeyMap::value_type(XK_F6, KC_F6)); 00107 _key_map.insert(InputKeyMap::value_type(XK_F7, KC_F7)); 00108 _key_map.insert(InputKeyMap::value_type(XK_F8, KC_F8)); 00109 _key_map.insert(InputKeyMap::value_type(XK_F9, KC_F9)); 00110 _key_map.insert(InputKeyMap::value_type(XK_F10, KC_F10)); 00111 _key_map.insert(InputKeyMap::value_type(XK_Num_Lock, KC_NUMLOCK)); 00112 _key_map.insert(InputKeyMap::value_type(XK_Scroll_Lock, KC_SCROLL)); 00113 _key_map.insert(InputKeyMap::value_type(XK_KP_7, KC_NUMPAD7)); 00114 _key_map.insert(InputKeyMap::value_type(XK_KP_8, KC_NUMPAD8)); 00115 _key_map.insert(InputKeyMap::value_type(XK_KP_9, KC_NUMPAD9)); 00116 _key_map.insert(InputKeyMap::value_type(XK_KP_Subtract, KC_SUBTRACT)); 00117 _key_map.insert(InputKeyMap::value_type(XK_KP_4, KC_NUMPAD4)); 00118 _key_map.insert(InputKeyMap::value_type(XK_KP_5, KC_NUMPAD5)); 00119 _key_map.insert(InputKeyMap::value_type(XK_KP_6, KC_NUMPAD6)); 00120 _key_map.insert(InputKeyMap::value_type(XK_KP_Add, KC_ADD)); 00121 _key_map.insert(InputKeyMap::value_type(XK_KP_1, KC_NUMPAD1)); 00122 _key_map.insert(InputKeyMap::value_type(XK_KP_2, KC_NUMPAD2)); 00123 _key_map.insert(InputKeyMap::value_type(XK_KP_3, KC_NUMPAD3)); 00124 _key_map.insert(InputKeyMap::value_type(XK_KP_0, KC_NUMPAD0)); 00125 _key_map.insert(InputKeyMap::value_type(XK_KP_Decimal, KC_DECIMAL)); 00126 _key_map.insert(InputKeyMap::value_type(XK_F11, KC_F11)); 00127 _key_map.insert(InputKeyMap::value_type(XK_F12, KC_F12)); 00128 _key_map.insert(InputKeyMap::value_type(XK_F13, KC_F13)); 00129 _key_map.insert(InputKeyMap::value_type(XK_F14, KC_F14)); 00130 _key_map.insert(InputKeyMap::value_type(XK_F15, KC_F15)); 00131 _key_map.insert(InputKeyMap::value_type(XK_KP_Equal, KC_NUMPADEQUALS)); 00132 _key_map.insert(InputKeyMap::value_type(XK_KP_Divide, KC_DIVIDE)); 00133 _key_map.insert(InputKeyMap::value_type(XK_Sys_Req, KC_SYSRQ)); 00134 _key_map.insert(InputKeyMap::value_type(XK_Alt_R, KC_RMENU)); // ? 00135 _key_map.insert(InputKeyMap::value_type(XK_Home, KC_HOME)); 00136 _key_map.insert(InputKeyMap::value_type(XK_Up, KC_UP)); 00137 _key_map.insert(InputKeyMap::value_type(XK_Page_Up, KC_PGUP)); 00138 _key_map.insert(InputKeyMap::value_type(XK_Left, KC_LEFT)); 00139 _key_map.insert(InputKeyMap::value_type(XK_Right, KC_RIGHT)); 00140 _key_map.insert(InputKeyMap::value_type(XK_End, KC_END)); 00141 _key_map.insert(InputKeyMap::value_type(XK_Down, KC_DOWN)); 00142 _key_map.insert(InputKeyMap::value_type(XK_Page_Down, KC_PGDOWN)); 00143 _key_map.insert(InputKeyMap::value_type(XK_Insert, KC_INSERT)); 00144 _key_map.insert(InputKeyMap::value_type(XK_Delete, KC_DELETE)); 00145 _key_map.insert(InputKeyMap::value_type(XK_Super_L, KC_LWIN)); // ? 00146 _key_map.insert(InputKeyMap::value_type(XK_Super_R, KC_RWIN)); // ? 00147 } 00148 00149 GLXInput::~GLXInput() { 00150 GrabCursor(false); 00151 XFreeCursor(mDisplay, mHiddenCursor); 00152 } 00153 00154 void GLXInput::initialise(RenderWindow* pWindow, bool useKeyboard, bool useMouse, bool useGameController) { 00155 mRenderWindow = pWindow; 00156 captureMouse = useMouse; 00157 00158 // Extract Window and Display from pWindow in magic way 00159 // This also raises an exception if it is not an GLXRenderWindow 00160 pWindow->getCustomAttribute("GLXWINDOW", &mWindow); 00161 pWindow->getCustomAttribute("GLXDISPLAY", &mDisplay); 00162 00163 // Create hidden cursor 00164 // X offers no standard support for this so we need to create a blank pixmap. 00165 Pixmap blank_pixmap = XCreatePixmap(mDisplay, mWindow, 1, 1, 1); 00166 GC gc = XCreateGC(mDisplay, blank_pixmap, (unsigned long)0, (XGCValues*)0); 00167 XDrawPoint(mDisplay, blank_pixmap, gc, 0, 0); 00168 XFreeGC(mDisplay, gc); 00169 XColor color; 00170 color.flags = DoRed | DoGreen | DoBlue; 00171 color.red = color.blue = color.green = 0; 00172 mHiddenCursor = XCreatePixmapCursor(mDisplay, blank_pixmap, blank_pixmap, &color, &color, 0, 0); 00173 XFreePixmap(mDisplay, blank_pixmap); 00174 00175 // Mousey stuff 00176 warpMouse = false; 00177 GrabCursor(true); 00178 00179 // Get the center and put the mouse there 00180 unsigned int width, height, depth; 00181 int left, top; 00182 pWindow->getMetrics(width, height, depth, left, top); 00183 00184 mMouseState.Buttons = 0; 00185 mouseLastX = mMouseState.Xabs = width / 2; 00186 mouseLastY = mMouseState.Yabs = height / 2; 00187 mMouseState.Zabs = 0; 00188 mMouseState.Xrel = 0; 00189 mMouseState.Yrel = 0; 00190 mMouseState.Zrel = 0; 00191 } 00192 00193 void GLXInput::capture() { 00194 GLXWindow *w = static_cast<GLXWindow*>(mRenderWindow); 00195 KeySym key; 00196 KeyCode ogrekey; 00197 XEvent event; 00198 00199 mMouseState.Xrel = 0; 00200 mMouseState.Yrel = 0; 00201 mMouseState.Zrel = 0; 00202 00203 bool hasMouseMoved = false; 00204 00205 // Process X events until event pump exhausted 00206 while(XPending(mDisplay) > 0) { 00207 XNextEvent(mDisplay,&event); 00208 00209 // Give window a shot as processing the event 00210 // TODO: call for every window 00211 w->processEvent(event); 00212 00213 int button_mask = -1; 00214 int button_bits = 0; 00215 bool button_down = false; 00216 switch(event.type) { 00217 case KeyPress: 00218 // Ignore shift and capslock state 00219 event.xkey.state &= ~ShiftMask; 00220 event.xkey.state &= ~LockMask; 00221 00222 XLookupString(&event.xkey,NULL,0,&key,NULL); 00223 // Ctrl-Escape should free mouse ala Q**** 00224 if(event.xkey.state & ControlMask && key == XK_Escape) { 00225 GrabCursor(false); 00226 break; 00227 } 00228 ogrekey = _key_map[key]; // key 00229 00230 // Unbuffered input 00231 _key_pressed_set.insert(ogrekey); 00232 00233 // Buffered input 00234 if(mUseBufferedKeys) 00235 keyChanged(ogrekey, true); 00236 break; 00237 case KeyRelease: 00238 XLookupString(&event.xkey,NULL,0,&key,NULL); 00239 ogrekey = _key_map[key]; 00240 00241 // Unbuffered input 00242 _key_pressed_set.erase(ogrekey); 00243 00244 // Buffered input 00245 if(mUseBufferedKeys) 00246 keyChanged(ogrekey, false); 00247 break; 00248 case MotionNotify: 00249 mMouseState.Xabs = event.xmotion.x; 00250 mMouseState.Yabs = event.xmotion.y; 00251 hasMouseMoved = true; 00252 break; 00253 00254 case ButtonPress: 00255 button_down = true; 00256 case ButtonRelease: 00257 switch(event.xbutton.button) { 00258 case 1: // LEFT 00259 button_mask = InputEvent::BUTTON0_MASK; 00260 button_bits = 1; 00261 break; 00262 case 2: // MIDDLE 00263 button_mask = InputEvent::BUTTON1_MASK; 00264 button_bits = 2; 00265 break; 00266 case 3: // RIGHT 00267 button_mask = InputEvent::BUTTON2_MASK; 00268 button_bits = 4; 00269 break; 00270 case 4: // WHEEL UP 00271 mMouseState.Zrel += mWheelStep; 00272 break; 00273 case 5: // WHEEN DOWN 00274 mMouseState.Zrel -= mWheelStep; 00275 break; 00276 }; 00277 // Unbuffered mouse 00278 if(button_down) 00279 mMouseState.Buttons |= button_bits; 00280 else 00281 mMouseState.Buttons &= ~button_bits; 00282 00283 // Buffered mouse 00284 if(mUseBufferedMouse) 00285 triggerMouseButton(button_mask, button_down); 00286 00287 // Mouse re-grab 00288 if(captureMouse && !warpMouse && button_down && event.xbutton.button==1) { 00289 GrabCursor(true); 00290 } 00291 00292 break; 00293 } 00294 } 00295 #define MOUSE_FUDGE_FACTOR 8 /* Thanks to SDL for this idea */ 00296 00297 if(warpMouse) { 00298 // Calculate the relative motion from the last mouse position and the new one. 00299 mMouseState.Xrel = mMouseState.Xabs - mouseLastX; 00300 mMouseState.Yrel = mMouseState.Yabs - mouseLastY; 00301 mouseLastX = mMouseState.Xabs; 00302 mouseLastY = mMouseState.Yabs; 00303 00304 unsigned int width, height, depth; 00305 int left, top; 00306 w->getMetrics(width, height, depth, left, top); 00307 // If the mouse cursor has reached the border of the window 00308 // (it is closer than MOUSE_FUDGE_FACTOR), warp it back to 00309 // the middle. 00310 if( (mMouseState.Xabs < MOUSE_FUDGE_FACTOR) || 00311 (mMouseState.Xabs > (width-MOUSE_FUDGE_FACTOR)) || 00312 (mMouseState.Yabs < MOUSE_FUDGE_FACTOR) || 00313 (mMouseState.Yabs > (height-MOUSE_FUDGE_FACTOR)) ) { 00314 mouseLastX = mMouseState.Xabs = width / 2; 00315 mouseLastY = mMouseState.Yabs = height / 2; 00316 XWarpPointer(mDisplay, None, mWindow, 0, 0, 0, 0, 00317 mMouseState.Xabs, mMouseState.Yabs); 00318 } 00319 } 00320 if(hasMouseMoved && mUseBufferedMouse) { 00321 // Send mouse moved event to application and move cursor. 00322 mouseMoved(); 00323 mCursor->addToX(mMouseState.Xrel * mMouseSpeed); 00324 mCursor->addToY(mMouseState.Yrel * mMouseSpeed); 00325 } 00326 00327 } 00328 00329 bool GLXInput::isKeyDownImmediate(KeyCode kc) const { 00330 return _key_pressed_set.count(kc); 00331 } 00332 00333 long GLXInput::getMouseRelX() const { 00334 return mMouseState.Xrel; 00335 } 00336 00337 long GLXInput::getMouseRelY() const { 00338 return mMouseState.Yrel; 00339 } 00340 00341 long GLXInput::getMouseRelZ() const { 00342 return mMouseState.Zrel; 00343 } 00344 00345 long GLXInput::getMouseAbsX() const { 00346 return mMouseState.Xabs; 00347 } 00348 00349 long GLXInput::getMouseAbsY() const { 00350 return mMouseState.Yabs; 00351 } 00352 00353 long GLXInput::getMouseAbsZ() const { 00354 return mMouseState.Zabs; 00355 } 00356 00357 bool GLXInput::getMouseButton( uchar button ) const { 00358 return mMouseState.isButtonDown( button ); 00359 } 00360 00361 void GLXInput::getMouseState( MouseState& state ) const { 00362 memcpy( &state, &mMouseState, sizeof( MouseState ) ); 00363 } 00364 00365 void GLXInput::GrabCursor(bool grab) { 00366 if(!captureMouse) 00367 // Never do mouse capture 00368 return; 00369 // Get window metrics 00370 unsigned int width, height, depth; 00371 int left, top; 00372 mRenderWindow->getMetrics(width, height, depth, left, top); 00373 00374 warpMouse = grab; 00375 if(warpMouse) { 00376 // Hide mouse 00377 XDefineCursor(mDisplay, mWindow, mHiddenCursor); 00378 // Grab keyboard and mouse 00379 XGrabPointer(mDisplay,mWindow,True,0,GrabModeAsync,GrabModeAsync,mWindow,None,CurrentTime); 00380 XGrabKeyboard(mDisplay,mWindow,True,GrabModeAsync,GrabModeAsync,CurrentTime); 00381 // Mouse warpin' fun 00382 mouseLastX = mMouseState.Xabs = width / 2; 00383 mouseLastY = mMouseState.Yabs = height / 2; 00384 XWarpPointer(mDisplay, None, mWindow, 0, 0, 0, 0, 00385 mMouseState.Xabs, mMouseState.Yabs); 00386 } else { 00387 // Show mouse 00388 XUndefineCursor(mDisplay, mWindow); 00389 // Ungrab keyboard and mouse 00390 XUngrabPointer(mDisplay,CurrentTime); 00391 XUngrabKeyboard(mDisplay,CurrentTime); 00392 00393 } 00394 } 00395 00396 00397 }
Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:27 2004