Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreGLXInput.cpp

Go to the documentation of this file.
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