source: OGRE/trunk/ogrenew/PlatformManagers/GLX/src/OgreGLXInput.cpp @ 657

Revision 657, 14.5 KB checked in by mattausch, 18 years ago (diff)

added ogre dependencies and patched ogre sources

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6 
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9 
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14 
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18 
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25
26#include "OgreGLXInput.h"
27#include "OgreLogManager.h"
28#include "OgreMouseEvent.h"
29#include "OgreCursor.h"
30
31#include "OgreGLXWindow.h"
32
33#include <X11/Xlib.h>
34#include <X11/Xutil.h>
35#include <X11/keysym.h>
36
37namespace Ogre {
38
39GLXInput::GLXInput()
40                : InputReader(),
41                mMouseSpeed(0.002f) {
42        mEventQueue = 0;
43
44        _key_map.insert(InputKeyMap::value_type(XK_Escape,KC_ESCAPE));
45        _key_map.insert(InputKeyMap::value_type(XK_1, KC_1));
46        _key_map.insert(InputKeyMap::value_type(XK_2, KC_2));
47        _key_map.insert(InputKeyMap::value_type(XK_3, KC_3));
48        _key_map.insert(InputKeyMap::value_type(XK_4, KC_4));
49        _key_map.insert(InputKeyMap::value_type(XK_5, KC_5));
50        _key_map.insert(InputKeyMap::value_type(XK_6, KC_6));
51        _key_map.insert(InputKeyMap::value_type(XK_7, KC_7));
52        _key_map.insert(InputKeyMap::value_type(XK_8, KC_8));
53        _key_map.insert(InputKeyMap::value_type(XK_9, KC_9));
54        _key_map.insert(InputKeyMap::value_type(XK_0, KC_0));
55        _key_map.insert(InputKeyMap::value_type(XK_minus, KC_MINUS));
56        _key_map.insert(InputKeyMap::value_type(XK_equal, KC_EQUALS));
57        _key_map.insert(InputKeyMap::value_type(XK_BackSpace, KC_BACK));
58        _key_map.insert(InputKeyMap::value_type(XK_Tab, KC_TAB));
59        _key_map.insert(InputKeyMap::value_type(XK_q, KC_Q));
60        _key_map.insert(InputKeyMap::value_type(XK_w, KC_W));
61        _key_map.insert(InputKeyMap::value_type(XK_e, KC_E));
62        _key_map.insert(InputKeyMap::value_type(XK_r, KC_R));
63        _key_map.insert(InputKeyMap::value_type(XK_t, KC_T));
64        _key_map.insert(InputKeyMap::value_type(XK_y, KC_Y));
65        _key_map.insert(InputKeyMap::value_type(XK_u, KC_U));
66        _key_map.insert(InputKeyMap::value_type(XK_i, KC_I));
67        _key_map.insert(InputKeyMap::value_type(XK_o, KC_O));
68        _key_map.insert(InputKeyMap::value_type(XK_p, KC_P));
69        _key_map.insert(InputKeyMap::value_type(XK_Return, KC_RETURN));
70        _key_map.insert(InputKeyMap::value_type(XK_Control_L, KC_LCONTROL));
71        _key_map.insert(InputKeyMap::value_type(XK_a, KC_A));
72        _key_map.insert(InputKeyMap::value_type(XK_s, KC_S));
73        _key_map.insert(InputKeyMap::value_type(XK_d, KC_D));
74        _key_map.insert(InputKeyMap::value_type(XK_f, KC_F));
75        _key_map.insert(InputKeyMap::value_type(XK_g, KC_G));
76        _key_map.insert(InputKeyMap::value_type(XK_h, KC_H));
77        _key_map.insert(InputKeyMap::value_type(XK_j, KC_J));
78        _key_map.insert(InputKeyMap::value_type(XK_k, KC_K));
79        _key_map.insert(InputKeyMap::value_type(XK_l, KC_L));
80        _key_map.insert(InputKeyMap::value_type(XK_semicolon, KC_SEMICOLON));
81        _key_map.insert(InputKeyMap::value_type(XK_colon, KC_COLON));
82        _key_map.insert(InputKeyMap::value_type(XK_apostrophe, KC_APOSTROPHE));
83        _key_map.insert(InputKeyMap::value_type(XK_grave, KC_GRAVE));
84        _key_map.insert(InputKeyMap::value_type(XK_Shift_L, KC_LSHIFT));
85        _key_map.insert(InputKeyMap::value_type(XK_backslash, KC_BACKSLASH));
86        _key_map.insert(InputKeyMap::value_type(XK_z, KC_Z));
87        _key_map.insert(InputKeyMap::value_type(XK_x, KC_X));
88        _key_map.insert(InputKeyMap::value_type(XK_c, KC_C));
89        _key_map.insert(InputKeyMap::value_type(XK_v, KC_V));
90        _key_map.insert(InputKeyMap::value_type(XK_b, KC_B));
91        _key_map.insert(InputKeyMap::value_type(XK_n, KC_N));
92        _key_map.insert(InputKeyMap::value_type(XK_m, KC_M));
93        _key_map.insert(InputKeyMap::value_type(XK_comma, KC_COMMA));
94        _key_map.insert(InputKeyMap::value_type(XK_period, KC_PERIOD));
95        _key_map.insert(InputKeyMap::value_type(XK_Shift_R, KC_RSHIFT));
96        _key_map.insert(InputKeyMap::value_type(XK_KP_Multiply, KC_MULTIPLY));
97        _key_map.insert(InputKeyMap::value_type(XK_Alt_L, KC_LMENU));  // ?
98        _key_map.insert(InputKeyMap::value_type(XK_space, KC_SPACE));
99        _key_map.insert(InputKeyMap::value_type(XK_Escape, KC_CAPITAL));
100        _key_map.insert(InputKeyMap::value_type(XK_F1, KC_F1));
101        _key_map.insert(InputKeyMap::value_type(XK_F2, KC_F2));
102        _key_map.insert(InputKeyMap::value_type(XK_F3, KC_F3));
103        _key_map.insert(InputKeyMap::value_type(XK_F4, KC_F4));
104        _key_map.insert(InputKeyMap::value_type(XK_F5, KC_F5));
105        _key_map.insert(InputKeyMap::value_type(XK_F6, KC_F6));
106        _key_map.insert(InputKeyMap::value_type(XK_F7, KC_F7));
107        _key_map.insert(InputKeyMap::value_type(XK_F8, KC_F8));
108        _key_map.insert(InputKeyMap::value_type(XK_F9, KC_F9));
109        _key_map.insert(InputKeyMap::value_type(XK_F10, KC_F10));
110        _key_map.insert(InputKeyMap::value_type(XK_Num_Lock, KC_NUMLOCK));
111        _key_map.insert(InputKeyMap::value_type(XK_Scroll_Lock, KC_SCROLL));
112        _key_map.insert(InputKeyMap::value_type(XK_KP_7, KC_NUMPAD7));
113        _key_map.insert(InputKeyMap::value_type(XK_KP_8, KC_NUMPAD8));
114        _key_map.insert(InputKeyMap::value_type(XK_KP_9, KC_NUMPAD9));
115        _key_map.insert(InputKeyMap::value_type(XK_KP_Subtract, KC_SUBTRACT));
116        _key_map.insert(InputKeyMap::value_type(XK_KP_4, KC_NUMPAD4));
117        _key_map.insert(InputKeyMap::value_type(XK_KP_5, KC_NUMPAD5));
118        _key_map.insert(InputKeyMap::value_type(XK_KP_6, KC_NUMPAD6));
119        _key_map.insert(InputKeyMap::value_type(XK_KP_Add, KC_ADD));
120        _key_map.insert(InputKeyMap::value_type(XK_KP_1, KC_NUMPAD1));
121        _key_map.insert(InputKeyMap::value_type(XK_KP_2, KC_NUMPAD2));
122        _key_map.insert(InputKeyMap::value_type(XK_KP_3, KC_NUMPAD3));
123        _key_map.insert(InputKeyMap::value_type(XK_KP_0, KC_NUMPAD0));
124        _key_map.insert(InputKeyMap::value_type(XK_KP_Decimal, KC_DECIMAL));
125        _key_map.insert(InputKeyMap::value_type(XK_F11, KC_F11));
126        _key_map.insert(InputKeyMap::value_type(XK_F12, KC_F12));
127        _key_map.insert(InputKeyMap::value_type(XK_F13, KC_F13));
128        _key_map.insert(InputKeyMap::value_type(XK_F14, KC_F14));
129        _key_map.insert(InputKeyMap::value_type(XK_F15, KC_F15));
130        _key_map.insert(InputKeyMap::value_type(XK_KP_Equal, KC_NUMPADEQUALS));
131        _key_map.insert(InputKeyMap::value_type(XK_KP_Divide, KC_DIVIDE));
132        _key_map.insert(InputKeyMap::value_type(XK_Print, KC_SYSRQ));
133        _key_map.insert(InputKeyMap::value_type(XK_Alt_R, KC_RMENU)); // ?
134        _key_map.insert(InputKeyMap::value_type(XK_Home, KC_HOME));
135        _key_map.insert(InputKeyMap::value_type(XK_Up, KC_UP));
136        _key_map.insert(InputKeyMap::value_type(XK_Page_Up, KC_PGUP));
137        _key_map.insert(InputKeyMap::value_type(XK_Left, KC_LEFT));
138        _key_map.insert(InputKeyMap::value_type(XK_Right, KC_RIGHT));
139        _key_map.insert(InputKeyMap::value_type(XK_End, KC_END));
140        _key_map.insert(InputKeyMap::value_type(XK_Down, KC_DOWN));
141        _key_map.insert(InputKeyMap::value_type(XK_Page_Down, KC_PGDOWN));
142        _key_map.insert(InputKeyMap::value_type(XK_Insert, KC_INSERT));
143        _key_map.insert(InputKeyMap::value_type(XK_Delete, KC_DELETE));
144        _key_map.insert(InputKeyMap::value_type(XK_Super_L, KC_LWIN)); // ?
145        _key_map.insert(InputKeyMap::value_type(XK_Super_R, KC_RWIN)); // ?
146}
147
148GLXInput::~GLXInput() {
149        GrabCursor(false);
150        XFreeCursor(mDisplay, mHiddenCursor);
151}
152
153void GLXInput::initialise(RenderWindow* pWindow, bool useKeyboard, bool useMouse, bool useGameController) {
154        mRenderWindow = pWindow;
155        captureMouse = useMouse;
156
157        // Extract Window and Display from pWindow in magic way
158        // This also raises an exception if it is not an GLXRenderWindow
159        pWindow->getCustomAttribute("GLXWINDOW", &mWindow);
160        pWindow->getCustomAttribute("GLXDISPLAY", &mDisplay);
161
162        // Create hidden cursor
163        // X offers no standard support for this so we need to create a blank pixmap.
164        Pixmap blank_pixmap = XCreatePixmap(mDisplay, mWindow, 1, 1, 1);
165        GC gc = XCreateGC(mDisplay, blank_pixmap, (unsigned long)0, (XGCValues*)0);
166        XDrawPoint(mDisplay, blank_pixmap, gc, 0, 0);
167        XFreeGC(mDisplay, gc);
168        XColor color;
169        color.flags = DoRed | DoGreen | DoBlue;
170        color.red = color.blue = color.green = 0;
171        mHiddenCursor = XCreatePixmapCursor(mDisplay, blank_pixmap, blank_pixmap, &color, &color, 0, 0);
172        XFreePixmap(mDisplay, blank_pixmap);
173
174        // Mousey stuff
175        warpMouse = false;
176        GrabCursor(true);
177
178        // Get the center and put the mouse there
179        unsigned int width, height, depth;
180        int left, top;
181        pWindow->getMetrics(width, height, depth, left, top);
182
183        mMouseState.Buttons = 0;
184        mouseLastX = mMouseState.Xabs = width / 2;
185        mouseLastY = mMouseState.Yabs = height / 2;
186        mMouseState.Zabs = 0;
187        mMouseState.Xrel = 0;
188        mMouseState.Yrel = 0;
189        mMouseState.Zrel = 0;
190}
191
192void GLXInput::capture() {
193        GLXWindow *w = static_cast<GLXWindow*>(mRenderWindow);
194        KeySym key;
195        KeyCode ogrekey;
196        XEvent event;
197
198        mMouseState.Xrel = 0;
199        mMouseState.Yrel = 0;
200        mMouseState.Zrel = 0;
201
202        bool hasMouseMoved = false;
203
204        // Process X events until event pump exhausted
205        while(XPending(mDisplay) > 0) {
206                XNextEvent(mDisplay,&event);
207
208                // Give window a shot as processing the event
209                // TODO: call for every window
210                w->processEvent(event);
211
212                int button_mask = -1;
213                int button_bits = 0;
214                bool button_down = false;
215                switch(event.type) {
216                case KeyPress:
217                        // Ignore shift and capslock state
218                        event.xkey.state &= ~ShiftMask;
219                        event.xkey.state &= ~LockMask;
220
221                        XLookupString(&event.xkey,NULL,0,&key,NULL);
222                        // Ctrl-Escape should free mouse ala Q****
223                        // Alt-TAB should free mouse ala SDL
224                        if((event.xkey.state & ControlMask && key == XK_Escape)
225                        ||(event.xkey.state & Mod1Mask && key == XK_Tab)) {
226                                GrabCursor(false);
227                                break;
228                        }
229                       
230                        ogrekey = _key_map[key]; // key
231
232                        // Unbuffered input
233                        _key_pressed_set.insert(ogrekey);
234
235                        // Buffered input
236                        if(mUseBufferedKeys)
237                                keyChanged(ogrekey, true);
238                        break;
239                case KeyRelease:
240                        XLookupString(&event.xkey,NULL,0,&key,NULL);
241                        ogrekey = _key_map[key];
242
243                        // Unbuffered input
244                        _key_pressed_set.erase(ogrekey);
245
246                        // Buffered input
247                        if(mUseBufferedKeys)
248                                keyChanged(ogrekey, false);
249                        break;
250                case MotionNotify:
251                        mMouseState.Xabs = event.xmotion.x;
252                        mMouseState.Yabs = event.xmotion.y;
253                        hasMouseMoved = true;
254                        break;
255
256                case ButtonPress:
257                        button_down = true;
258                case ButtonRelease:
259                        switch(event.xbutton.button) {
260                        case 1: // LEFT
261                                button_mask = InputEvent::BUTTON0_MASK;
262                                button_bits = 1;
263                                break;
264                        case 2: // MIDDLE
265                                button_mask = InputEvent::BUTTON1_MASK;
266                                button_bits = 2;
267                                break;
268                        case 3: // RIGHT
269                                button_mask = InputEvent::BUTTON2_MASK;
270                                button_bits = 4;
271                                break;
272                        case 4: // WHEEL UP
273                                mMouseState.Zrel += mWheelStep;
274                                break;
275                        case 5: // WHEEN DOWN
276                                mMouseState.Zrel -= mWheelStep;
277                                break;
278                        };
279                        // Unbuffered mouse
280                        if(button_down)
281                                mMouseState.Buttons |= button_bits;
282                        else
283                                mMouseState.Buttons &= ~button_bits;
284
285                        // Buffered mouse
286                        if(mUseBufferedMouse)
287                                triggerMouseButton(button_mask, button_down);
288
289                        // Mouse re-grab
290                        if(captureMouse && !warpMouse && button_down &&  event.xbutton.button==1) {
291                                GrabCursor(true);
292                        }
293
294                        break;
295                }
296        }
297#define MOUSE_FUDGE_FACTOR      8 /* Thanks to SDL for this idea */
298
299        if(warpMouse) {
300                // Calculate the relative motion from the last mouse position and the new one.
301                mMouseState.Xrel = mMouseState.Xabs - mouseLastX;
302                mMouseState.Yrel = mMouseState.Yabs - mouseLastY;
303                mouseLastX = mMouseState.Xabs;
304                mouseLastY = mMouseState.Yabs;
305
306                unsigned int width, height, depth;
307                int left, top;
308                w->getMetrics(width, height, depth, left, top);
309                // If the mouse cursor has reached the border of the window
310                // (it is closer than MOUSE_FUDGE_FACTOR), warp it back to
311                // the middle.
312                if(     (mMouseState.Xabs < MOUSE_FUDGE_FACTOR) ||
313                        (mMouseState.Xabs > (width-MOUSE_FUDGE_FACTOR)) ||
314                        (mMouseState.Yabs < MOUSE_FUDGE_FACTOR) ||
315                        (mMouseState.Yabs > (height-MOUSE_FUDGE_FACTOR)) ) {
316                        mouseLastX = mMouseState.Xabs = width / 2;
317                        mouseLastY = mMouseState.Yabs = height / 2;
318                        XWarpPointer(mDisplay, None, mWindow, 0, 0, 0, 0,
319                                        mMouseState.Xabs, mMouseState.Yabs);
320                }
321        }
322        if(hasMouseMoved && mUseBufferedMouse) {
323                // Send mouse moved event to application and move cursor.
324                mouseMoved();
325                mCursor->addToX(mMouseState.Xrel * mMouseSpeed);
326                mCursor->addToY(mMouseState.Yrel * mMouseSpeed);
327        }
328
329}
330
331bool GLXInput::isKeyDownImmediate(KeyCode kc) const {
332        return _key_pressed_set.count(kc);
333}
334
335long GLXInput::getMouseRelX() const {
336        return mMouseState.Xrel;
337}
338
339long GLXInput::getMouseRelY() const {
340        return mMouseState.Yrel;
341}
342
343long GLXInput::getMouseRelZ() const {
344        return mMouseState.Zrel;
345}
346
347long GLXInput::getMouseAbsX() const {
348        return mMouseState.Xabs;
349}
350
351long GLXInput::getMouseAbsY() const {
352        return mMouseState.Yabs;
353}
354
355long GLXInput::getMouseAbsZ() const {
356        return mMouseState.Zabs;
357}
358
359bool GLXInput::getMouseButton( uchar button ) const {
360        return mMouseState.isButtonDown( button );
361}
362
363void GLXInput::getMouseState( MouseState& state ) const {
364        memcpy( &state, &mMouseState, sizeof( MouseState ) );
365}
366
367void GLXInput::GrabCursor(bool grab) {
368        if(!captureMouse)
369                // Never do mouse capture
370                return;
371        // Get window metrics
372        unsigned int width, height, depth;
373        int left, top;
374        mRenderWindow->getMetrics(width, height, depth, left, top);
375
376        warpMouse = grab;
377        if(warpMouse) {
378                // Hide mouse
379                XDefineCursor(mDisplay, mWindow, mHiddenCursor);
380                // Grab keyboard and mouse
381                XGrabPointer(mDisplay,mWindow,True,0,GrabModeAsync,GrabModeAsync,mWindow,None,CurrentTime);
382                XGrabKeyboard(mDisplay,mWindow,True,GrabModeAsync,GrabModeAsync,CurrentTime);
383                // Mouse warpin' fun
384                mouseLastX = mMouseState.Xabs = width / 2;
385                mouseLastY = mMouseState.Yabs = height / 2;
386                XWarpPointer(mDisplay, None, mWindow, 0, 0, 0, 0,
387                                       mMouseState.Xabs, mMouseState.Yabs);
388        } else {
389                // Show mouse
390                XUndefineCursor(mDisplay, mWindow);
391                // Ungrab keyboard and mouse
392                XUngrabPointer(mDisplay,CurrentTime);
393                XUngrabKeyboard(mDisplay,CurrentTime);
394
395        }
396}
397
398
399}
Note: See TracBrowser for help on using the repository browser.