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