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

Revision 692, 14.8 KB checked in by mattausch, 19 years ago (diff)

adding ogre 1.2 and dependencies

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