~ubuntu-branches/ubuntu/trusty/openscenegraph/trusty

« back to all changes in this revision

Viewing changes to OpenSceneGraph/src/osgViewer/GraphicsWindowX11.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cyril Brulebois
  • Date: 2008-07-29 04:34:38 UTC
  • mfrom: (1.1.6 upstream) (2.1.3 lenny)
  • Revision ID: james.westby@ubuntu.com-20080729043438-no1h9h0dpsrlzp1y
* Non-maintainer upload.
* No longer try to detect (using /proc/cpuinfo when available) how many
  CPUs are available, fixing the FTBFS (due to -j0) on various platforms
  (Closes: #477353). The right way to do it is to support parallel=n in
  DEB_BUILD_OPTIONS (see Debian Policy §4.9.1), and adequate support has
  been implemented.
* Add patch to fix FTBFS due to the build system now refusing to handle
  whitespaces (Policy CMP0004 say the logs), thanks to Andreas Putzo who
  provided it (Closes: #482239):
   - debian/patches/fix-cmp0004-build-failure.dpatch
* Remove myself from Uploaders, as requested a while ago, done by Luk in
  his 2.2.0-2.1 NMU, which was never acknowledged.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
*/
13
13
 
14
14
/* Note, elements of GraphicsWindowX11 have used Prodcer/RenderSurface_X11.cpp as both
15
 
 * a guide to use of X11/GLX and copiying directly in the case of setBorder().
16
 
 * These elements are license under OSGPL as above, with Copyright (C) 2001-2004  Don Burns.
 
15
 * a guide to use of X11/GLX and copying directly in the case of setBorder().
 
16
 * These elements are licensed under OSGPL as above, with Copyright (C) 2001-2004  Don Burns.
17
17
 */
18
18
 
19
19
#include <osgViewer/api/X11/GraphicsWindowX11>
27
27
#include <X11/Xmd.h>
28
28
#include <X11/keysym.h>
29
29
#include <X11/cursorfont.h>
30
 
#include <X11/Intrinsic.h>
31
30
 
32
31
#include <X11/Xmd.h>        /* For CARD16 */
33
32
 
 
33
#ifdef OSGVIEWER_USE_XRANDR
 
34
#include <X11/extensions/Xrandr.h>
 
35
#endif
 
36
 
34
37
#include <unistd.h>
35
38
 
36
39
using namespace osgViewer;
102
105
            _keymap[XK_semicolon    ] = ';';
103
106
            _keymap[XK_apostrophe   ] = '\'';
104
107
            _keymap[XK_Return       ] = osgGA::GUIEventAdapter::KEY_Return;
105
 
            _keymap[XK_Shift_L      ] = osgGA::GUIEventAdapter::KEY_Shift_L;
106
108
            _keymap[XK_comma        ] = ',';
107
109
            _keymap[XK_period       ] = '.';
108
110
            _keymap[XK_slash        ] = '/';
 
111
            _keymap[XK_space        ] = ' ';
 
112
            _keymap[XK_Shift_L      ] = osgGA::GUIEventAdapter::KEY_Shift_L;
109
113
            _keymap[XK_Shift_R      ] = osgGA::GUIEventAdapter::KEY_Shift_R;
110
114
            _keymap[XK_Control_L    ] = osgGA::GUIEventAdapter::KEY_Control_L;
111
 
            _keymap[XK_Super_L      ] = osgGA::GUIEventAdapter::KEY_Super_L;
112
 
            _keymap[XK_space        ] = ' ';
 
115
            _keymap[XK_Control_R    ] = osgGA::GUIEventAdapter::KEY_Control_R;
 
116
            _keymap[XK_Meta_L       ] = osgGA::GUIEventAdapter::KEY_Meta_L;
 
117
            _keymap[XK_Meta_R       ] = osgGA::GUIEventAdapter::KEY_Meta_R;
113
118
            _keymap[XK_Alt_L        ] = osgGA::GUIEventAdapter::KEY_Alt_L;
114
119
            _keymap[XK_Alt_R        ] = osgGA::GUIEventAdapter::KEY_Alt_R;
 
120
            _keymap[XK_Super_L      ] = osgGA::GUIEventAdapter::KEY_Super_L;
115
121
            _keymap[XK_Super_R      ] = osgGA::GUIEventAdapter::KEY_Super_R;
 
122
            _keymap[XK_Hyper_L      ] = osgGA::GUIEventAdapter::KEY_Hyper_L;
 
123
            _keymap[XK_Hyper_R      ] = osgGA::GUIEventAdapter::KEY_Hyper_R;
116
124
            _keymap[XK_Menu         ] = osgGA::GUIEventAdapter::KEY_Menu;
117
 
            _keymap[XK_Control_R    ] = osgGA::GUIEventAdapter::KEY_Control_R;
118
125
            _keymap[XK_Print        ] = osgGA::GUIEventAdapter::KEY_Print;
119
126
            _keymap[XK_Scroll_Lock  ] = osgGA::GUIEventAdapter::KEY_Scroll_Lock;
120
127
            _keymap[XK_Pause        ] = osgGA::GUIEventAdapter::KEY_Pause;
170
177
    return s_x11KeyboardMap.remapKey(key);
171
178
}
172
179
 
 
180
// Functions to handle key maps of type char[32] as contained in
 
181
// an XKeymapEvent or returned by XQueryKeymap().
 
182
static inline bool keyMapGetKey(const char* map, unsigned int key)
 
183
{
 
184
    return (map[(key & 0xff) / 8] & (1 << (key & 7))) != 0;
 
185
}
 
186
 
 
187
static inline void keyMapSetKey(char* map, unsigned int key)
 
188
{
 
189
    map[(key & 0xff) / 8] |= (1 << (key & 7));
 
190
}
 
191
 
 
192
static inline void keyMapClearKey(char* map, unsigned int key)
 
193
{
 
194
    map[(key & 0xff) / 8] &= ~(1 << (key & 7));
 
195
}
 
196
 
173
197
GraphicsWindowX11::~GraphicsWindowX11()
174
198
{
175
199
    close(true);
267
291
#define MWM_FUNC_CLOSE        (1L<<5)
268
292
 
269
293
 
 
294
bool GraphicsWindowX11::checkAndSendEventFullScreenIfNeeded(Display* display, int x, int y, int width, int height, bool windowDecoration)
 
295
{
 
296
  osg::GraphicsContext::WindowingSystemInterface *wsi = osg::GraphicsContext::getWindowingSystemInterface();
 
297
  if (wsi == NULL) {
 
298
    osg::notify(osg::NOTICE) << "Error, no WindowSystemInterface available, cannot toggle window fullscreen." << std::endl;
 
299
    return false;
 
300
  }
 
301
 
 
302
  unsigned int    screenWidth;
 
303
  unsigned int    screenHeight;
 
304
 
 
305
  wsi->getScreenResolution(*_traits, screenWidth, screenHeight);
 
306
  bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight && !windowDecoration;
 
307
 
 
308
  Atom netWMStateAtom = XInternAtom(display, "_NET_WM_STATE", True);
 
309
  Atom netWMStateFullscreenAtom = XInternAtom(display,
 
310
                                              "_NET_WM_STATE_FULLSCREEN", True);
 
311
 
 
312
  if (netWMStateAtom != None && netWMStateFullscreenAtom != None) {
 
313
    XEvent xev;
 
314
    xev.xclient.type = ClientMessage;
 
315
    xev.xclient.serial = 0;
 
316
    xev.xclient.send_event = True;
 
317
    xev.xclient.window = _window;
 
318
    xev.xclient.message_type = netWMStateAtom;
 
319
    xev.xclient.format = 32;
 
320
    xev.xclient.data.l[0] = isFullScreen ? 1 : 0;
 
321
    xev.xclient.data.l[1] = netWMStateFullscreenAtom;
 
322
    xev.xclient.data.l[2] = 0;
 
323
 
 
324
    XSendEvent(display, RootWindow(display, DefaultScreen(display)),
 
325
               False,  SubstructureRedirectMask | SubstructureNotifyMask, &xev);
 
326
    return true;
 
327
  }
 
328
  return false;
 
329
}
 
330
 
270
331
bool GraphicsWindowX11::setWindowDecorationImplementation(bool flag)
271
332
{
272
333
    Display* display = getDisplayToUse();
273
 
    
 
334
 
 
335
    XMapWindow(display, _window );
 
336
 
 
337
    checkAndSendEventFullScreenIfNeeded(display, _traits->x, _traits->y, _traits->width, _traits->height, flag);
 
338
    struct
 
339
    {
 
340
        unsigned long flags;
 
341
        unsigned long functions;
 
342
        unsigned long decorations;
 
343
        long          inputMode;
 
344
        unsigned long status;
 
345
    } wmHints;
 
346
 
274
347
    Atom atom;
 
348
    bool result = false;
275
349
    if( (atom = XInternAtom( display, "_MOTIF_WM_HINTS", 0 )) != None )
276
350
    {
277
 
    
278
 
        struct
279
 
        {
280
 
            unsigned long flags;
281
 
            unsigned long functions;
282
 
            unsigned long decorations;
283
 
            long          inputMode;
284
 
            unsigned long status;
285
 
        } wmHints;
286
351
        
287
352
        wmHints.flags = 0;
288
353
        wmHints.functions = MWM_FUNC_ALL;
300
365
            wmHints.flags |= MWM_HINTS_FUNCTIONS;
301
366
            if (_traits.valid() && !_traits->supportsResize) wmHints.functions |= MWM_FUNC_RESIZE;
302
367
        }
303
 
 
304
 
        XMapWindow(display, _window );
305
368
        XChangeProperty( display, _window, atom, atom, 32, PropModeReplace, (unsigned char *)&wmHints,  5 );
306
 
 
307
 
        XFlush(display);
308
 
        XSync(display,0);
309
 
 
310
 
#if 0
311
 
        // now update the window dimensions to account for any size changes made by the window manager,
312
 
        XGetWindowAttributes( display, _window, &watt );
313
 
        _traits->width = watt.width;
314
 
        _traits->height = watt.height;
315
 
#endif
316
 
 
317
 
        // add usleep here to give window manager a chance to handle the request, if
318
 
        // we don't add this sleep then any X11 calls right afterwards can produce
319
 
        // X11 errors.
320
 
        usleep(100000);
321
 
        
322
 
        return true;
323
 
 
 
369
        result = true;
324
370
    }
325
371
    else
326
372
    {
327
373
        osg::notify(osg::NOTICE)<<"Error: GraphicsWindowX11::setBorder(" << flag << ") - couldn't change decorations." << std::endl;
328
 
        return false;
 
374
        result = false;
329
375
    }
330
376
 
331
 
    
 
377
    XFlush(display);
 
378
    XSync(display,0);
 
379
    // add usleep here to give window manager a chance to handle the request, if
 
380
    // we don't add this sleep then any X11 calls right afterwards can produce
 
381
    // X11 errors.
 
382
    usleep(100000);
 
383
    return result;
332
384
}
333
385
 
334
386
bool GraphicsWindowX11::setWindowRectangleImplementation(int x, int y, int width, int height)
342
394
    XFlush(display);
343
395
    XSync(display, 0);
344
396
 
 
397
    checkAndSendEventFullScreenIfNeeded(display, x, y, width, height, _traits->windowDecoration);
 
398
 
345
399
    // add usleep here to give window manager a chance to handle the request, if
346
400
    // we don't add this sleep then any X11 calls right afterwards can produce
347
401
    // X11 errors.
348
402
    usleep(100000);
 
403
 
349
404
    
350
405
    return true;
351
406
}
659
714
 
660
715
    XSelectInput( _eventDisplay, _window, ExposureMask | StructureNotifyMask | 
661
716
                                     KeyPressMask | KeyReleaseMask |
662
 
                                     PointerMotionMask  | ButtonPressMask | ButtonReleaseMask);
 
717
                                     PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
 
718
                                     KeymapStateMask | FocusChangeMask | EnterWindowMask );
663
719
 
664
720
    XFlush( _eventDisplay );
665
721
    XSync( _eventDisplay, 0 );
 
722
    rescanModifierMapping();
666
723
 
667
724
    return true;
668
725
}
828
885
            {
829
886
                if (static_cast<Atom>(ev.xclient.data.l[0]) == _deleteWindow)
830
887
                {
831
 
                    osg::notify(osg::INFO)<<"DeleteWindow event recieved"<<std::endl;
 
888
                    osg::notify(osg::INFO)<<"DeleteWindow event received"<<std::endl;
832
889
                    getEventQueue()->closeWindow();
833
890
                }
834
891
            }
866
923
        {
867
924
            case ClientMessage:
868
925
            {
869
 
                osg::notify(osg::NOTICE)<<"ClientMessage event recieved"<<std::endl;
 
926
                osg::notify(osg::NOTICE)<<"ClientMessage event received"<<std::endl;
870
927
                if (static_cast<Atom>(ev.xclient.data.l[0]) == _deleteWindow)
871
928
                {
872
 
                    osg::notify(osg::NOTICE)<<"DeleteWindow event recieved"<<std::endl;
 
929
                    osg::notify(osg::NOTICE)<<"DeleteWindow event received"<<std::endl;
873
930
                    // FIXME only do if _ownsWindow ?
874
931
                    destroyWindowRequested = true;
875
932
                    getEventQueue()->closeWindow(eventTime);
880
937
                break;
881
938
 
882
939
            case GravityNotify :
883
 
                osg::notify(osg::INFO)<<"GravityNotify event recieved"<<std::endl;
884
 
                break;
885
 
 
886
 
            case UnmapNotify :
887
 
                osg::notify(osg::INFO)<<"UnmapNotify event recieved"<<std::endl;
 
940
                osg::notify(osg::INFO)<<"GravityNotify event received"<<std::endl;
888
941
                break;
889
942
 
890
943
            case ReparentNotify:
891
 
                osg::notify(osg::INFO)<<"ReparentNotify event recieved"<<std::endl;
 
944
                osg::notify(osg::INFO)<<"ReparentNotify event received"<<std::endl;
892
945
                break;
893
946
 
894
947
            case DestroyNotify :
895
 
                osg::notify(osg::NOTICE)<<"DestroyNotify event recieved"<<std::endl;
 
948
                osg::notify(osg::NOTICE)<<"DestroyNotify event received"<<std::endl;
896
949
                _realized =  false;
897
950
                _valid = false;
898
951
                break;
938
991
                break;
939
992
            }
940
993
 
941
 
           case MotionNotify :
942
 
           {
 
994
            case FocusIn :
 
995
                osg::notify(osg::INFO)<<"FocusIn event received"<<std::endl;
 
996
                break;
 
997
 
 
998
            case UnmapNotify :
 
999
            case FocusOut :
 
1000
            {
 
1001
                osg::notify(osg::INFO)<<"FocusOut/UnmapNotify event received"<<std::endl;
 
1002
                if (ev.type == FocusOut && ev.xfocus.mode != NotifyNormal) break;
 
1003
 
 
1004
                char modMap[32];
 
1005
                getModifierMap(modMap);
 
1006
 
 
1007
                // release normal (non-modifier) keys
 
1008
                for (unsigned int key = 8; key < 256; key++)
 
1009
                {
 
1010
                    bool isModifier = keyMapGetKey(modMap, key);
 
1011
                    if (!isModifier) forceKey(key, eventTime, false);
 
1012
                }
 
1013
 
 
1014
                // release modifier keys
 
1015
                for (unsigned int key = 8; key < 256; key++)
 
1016
                {
 
1017
                    bool isModifier = keyMapGetKey(modMap, key);
 
1018
                    if (isModifier) forceKey(key, eventTime, false);
 
1019
                }
 
1020
                break;
 
1021
            }
 
1022
 
 
1023
            case EnterNotify :
 
1024
                osg::notify(osg::INFO)<<"EnterNotify event received"<<std::endl;
 
1025
                _modifierState = ev.xcrossing.state;
 
1026
                syncLocks();
 
1027
                break;
 
1028
 
 
1029
            case KeymapNotify :
 
1030
            {
 
1031
                osg::notify(osg::INFO)<<"KeymapNotify event received"<<std::endl;
 
1032
 
 
1033
                // KeymapNotify is guaranteed to directly follow either a FocusIn or
 
1034
                // an EnterNotify event. We are only interested in the FocusIn case.
 
1035
                if (_lastEventType != FocusIn) break;
 
1036
 
 
1037
                char modMap[32];
 
1038
                getModifierMap(modMap);
 
1039
                syncLocks();
 
1040
 
 
1041
                // release normal (non-modifier) keys
 
1042
                for (unsigned int key = 8; key < 256; key++)
 
1043
                {
 
1044
                    bool isModifier = keyMapGetKey(modMap, key);
 
1045
                    if (isModifier) continue;
 
1046
                    bool isPressed = keyMapGetKey(ev.xkeymap.key_vector, key);
 
1047
                    if (!isPressed) forceKey(key, eventTime, false);
 
1048
                }
 
1049
 
 
1050
                // press/release modifier keys
 
1051
                for (unsigned int key = 8; key < 256; key++)
 
1052
                {
 
1053
                    bool isModifier = keyMapGetKey(modMap, key);
 
1054
                    if (!isModifier) continue;
 
1055
                    bool isPressed = keyMapGetKey(ev.xkeymap.key_vector, key);
 
1056
                    forceKey(key, eventTime, isPressed);
 
1057
                }
 
1058
 
 
1059
                // press normal keys
 
1060
                for (unsigned int key = 8; key < 256; key++)
 
1061
                {
 
1062
                    bool isModifier = keyMapGetKey(modMap, key);
 
1063
                    if (isModifier) continue;
 
1064
                    bool isPressed = keyMapGetKey(ev.xkeymap.key_vector, key);
 
1065
                    if (isPressed) forceKey(key, eventTime, true);
 
1066
                }
 
1067
                break;
 
1068
            }
 
1069
 
 
1070
            case MappingNotify :
 
1071
                osg::notify(osg::INFO)<<"MappingNotify event received"<<std::endl;
 
1072
                if (ev.xmapping.request == MappingModifier) rescanModifierMapping();
 
1073
                break;
 
1074
 
 
1075
            case MotionNotify :
 
1076
            {
943
1077
                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
944
1078
                Time relativeTime = ev.xmotion.time - firstEventTime;
945
1079
                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
1053
1187
                Time relativeTime = ev.xmotion.time - firstEventTime;
1054
1188
                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
1055
1189
 
 
1190
                _modifierState = ev.xkey.state;
 
1191
                keyMapSetKey(_keyMap, ev.xkey.keycode);
1056
1192
                int keySymbol = 0;
1057
 
                unsigned int modifierMask = 0;
1058
 
                adaptKey(ev.xkey, keySymbol, modifierMask);
 
1193
                adaptKey(ev.xkey, keySymbol);
1059
1194
 
1060
 
                //getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
1061
1195
                getEventQueue()->keyPress(keySymbol, eventTime);
1062
1196
                break;
1063
1197
            }
1083
1217
                        break;
1084
1218
                    }
1085
1219
                }
1086
 
#endif                
 
1220
#endif
 
1221
                _modifierState = ev.xkey.state;
 
1222
                keyMapClearKey(_keyMap, ev.xkey.keycode);
1087
1223
                int keySymbol = 0;
1088
 
                unsigned int modifierMask = 0;
1089
 
                adaptKey(ev.xkey, keySymbol, modifierMask);
 
1224
                adaptKey(ev.xkey, keySymbol);
1090
1225
                
1091
 
                //getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
1092
1226
                getEventQueue()->keyRelease(keySymbol, eventTime);
1093
1227
                break;
1094
1228
            }
1095
1229
            
1096
1230
            default:
1097
 
                osg::notify(osg::NOTICE)<<"Other event"<<std::endl;
 
1231
                osg::notify(osg::NOTICE)<<"Other event "<<ev.type<<std::endl;
1098
1232
                break;
1099
1233
                
1100
1234
        }
 
1235
        _lastEventType = ev.type;
1101
1236
    }
1102
1237
 
1103
1238
    if (windowX != _traits->x || 
1159
1294
    }
1160
1295
}
1161
1296
 
1162
 
void GraphicsWindowX11::adaptKey(XKeyEvent& keyevent, int& keySymbol, unsigned int& modifierMask)
 
1297
void GraphicsWindowX11::adaptKey(XKeyEvent& keyevent, int& keySymbol)
1163
1298
{
1164
1299
    Display* display = _eventDisplay;
1165
1300
 
1166
 
    static XComposeStatus state;
1167
1301
    unsigned char keybuf[32];
1168
 
    XLookupString( &keyevent, (char *)keybuf, sizeof(keybuf), NULL, &state );
1169
 
 
1170
 
    modifierMask = 0;
1171
 
    if( keyevent.state & ShiftMask )
1172
 
    {
1173
 
        modifierMask |= osgGA::GUIEventAdapter::MODKEY_SHIFT;
1174
 
    }
1175
 
    if( keyevent.state & LockMask )
1176
 
    {
1177
 
        modifierMask |= osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
1178
 
    }
1179
 
    if( keyevent.state & ControlMask )
1180
 
    {
1181
 
        modifierMask |= osgGA::GUIEventAdapter::MODKEY_CTRL;
1182
 
    }
1183
 
    if( keyevent.state & Mod1Mask )
1184
 
    {
1185
 
        modifierMask |= osgGA::GUIEventAdapter::MODKEY_ALT;
1186
 
    }
1187
 
    if( keyevent.state & Mod2Mask )
1188
 
    {
1189
 
        modifierMask |= osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
1190
 
    }
1191
 
    if( keyevent.state & Mod4Mask )
1192
 
    {
1193
 
        modifierMask |= osgGA::GUIEventAdapter::MODKEY_META;
1194
 
    }
1195
 
 
1196
 
    keySymbol = keybuf[0];
1197
 
    
 
1302
    XLookupString( &keyevent, (char *)keybuf, sizeof(keybuf), NULL, NULL );
 
1303
 
1198
1304
    KeySym ks = XKeycodeToKeysym( display, keyevent.keycode, 0 );
1199
1305
    int remappedKey = remapX11Key(ks);
1200
1306
    if (remappedKey & 0xff00) 
1207
1313
        // normal ascii key
1208
1314
        keySymbol = keybuf[0];
1209
1315
    }
1210
 
    
1211
 
    
 
1316
}
 
1317
 
 
1318
// Function to inject artificial key presses/releases.
 
1319
void GraphicsWindowX11::forceKey(int key, double time, bool state)
 
1320
{
 
1321
    if (!(state ^ keyMapGetKey(_keyMap, key))) return; // already pressed/released
 
1322
 
 
1323
    XKeyEvent event;
 
1324
    event.serial = 0;
 
1325
    event.send_event = True;
 
1326
    event.display = _eventDisplay;
 
1327
    event.window = _window;
 
1328
    event.subwindow = 0;
 
1329
    event.time = 0;
 
1330
    event.x = 0;
 
1331
    event.y = 0;
 
1332
    event.x_root = 0;
 
1333
    event.y_root = 0;
 
1334
    event.state = getModifierMask() | (_modifierState & (LockMask | _numLockMask));
 
1335
    event.keycode = key;
 
1336
    event.same_screen = True;
 
1337
 
 
1338
    int keySymbol = 0;
 
1339
    if (state)
 
1340
    {
 
1341
        event.type = KeyPress;
 
1342
        adaptKey(event, keySymbol);
 
1343
        getEventQueue()->keyPress(keySymbol, time);
 
1344
        keyMapSetKey(_keyMap, key);
 
1345
    }
 
1346
    else
 
1347
    {
 
1348
        event.type = KeyRelease;
 
1349
        adaptKey(event, keySymbol);
 
1350
        getEventQueue()->keyRelease(keySymbol, time);
 
1351
        keyMapClearKey(_keyMap, key);
 
1352
    }
 
1353
}
 
1354
 
 
1355
void GraphicsWindowX11::syncLocks()
 
1356
{
 
1357
    unsigned int mask = getEventQueue()->getCurrentEventState()->getModKeyMask();
 
1358
 
 
1359
    if (_modifierState & LockMask)
 
1360
        mask |= osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
 
1361
    else
 
1362
        mask &= ~osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
 
1363
 
 
1364
    if (_modifierState & _numLockMask)
 
1365
        mask |= osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
 
1366
    else
 
1367
        mask &= ~osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
 
1368
 
 
1369
    getEventQueue()->getCurrentEventState()->setModKeyMask(mask);
 
1370
}
 
1371
 
 
1372
void GraphicsWindowX11::rescanModifierMapping()
 
1373
{
 
1374
    XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay);
 
1375
    KeyCode *m = mkm->modifiermap;
 
1376
    KeyCode numlock = XKeysymToKeycode(_eventDisplay, XK_Num_Lock);
 
1377
    _numLockMask = 0;
 
1378
    for (int i = 0; i < mkm->max_keypermod * 8; i++, m++)
 
1379
    {
 
1380
        if (*m == numlock)
 
1381
        {
 
1382
            _numLockMask = 1 << (i / mkm->max_keypermod);
 
1383
            break;
 
1384
        }
 
1385
    }
 
1386
}
 
1387
 
 
1388
// Returns char[32] keymap with bits for every modifier key set.
 
1389
void GraphicsWindowX11::getModifierMap(char* keymap) const
 
1390
{
 
1391
    memset(keymap, 0, 32);
 
1392
    XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay);
 
1393
    KeyCode *m = mkm->modifiermap;
 
1394
    for (int i = 0; i < mkm->max_keypermod * 8; i++, m++)
 
1395
    {
 
1396
        if (*m) keyMapSetKey(keymap, *m);
 
1397
    }
 
1398
}
 
1399
 
 
1400
int GraphicsWindowX11::getModifierMask() const
 
1401
{
 
1402
    int mask = 0;
 
1403
    XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay);
 
1404
    for (int i = 0; i < mkm->max_keypermod * 8; i++)
 
1405
    {
 
1406
        unsigned int key = mkm->modifiermap[i];
 
1407
        if (key && keyMapGetKey(_keyMap, key))
 
1408
        {
 
1409
            mask |= 1 << (i / mkm->max_keypermod);
 
1410
        }
 
1411
    }
 
1412
    return mask;
1212
1413
}
1213
1414
 
1214
1415
void GraphicsWindowX11::requestWarpPointer(float x,float y)
1230
1431
extern "C" 
1231
1432
{
1232
1433
 
 
1434
typedef int (*X11ErrorHandler)(Display*, XErrorEvent*);
 
1435
 
1233
1436
int X11ErrorHandling(Display* display, XErrorEvent* event)
1234
1437
{
1235
1438
    osg::notify(osg::NOTICE)<<"Got an X11ErrorHandling call display="<<display<<" event="<<event<<std::endl;
1263
1466
 
1264
1467
}
1265
1468
 
1266
 
struct X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface
 
1469
class X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface
1267
1470
{
1268
 
 
 
1471
#ifdef OSGVIEWER_USE_XRANDR
 
1472
    // TODO: Investigate whether or not Robert thinks we should store/restore the original
 
1473
    // resolution in the destructor; I'm not sure the other ones do this, and it may be the
 
1474
    // responsibility of the user.
 
1475
    bool _setScreen(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned height, double rate) {
 
1476
        Display* display = XOpenDisplay(si.displayName().c_str());
 
1477
        
 
1478
        if(display)
 
1479
        {
 
1480
            XRRScreenConfiguration* sc = XRRGetScreenInfo(display, RootWindow(display, si.screenNum));
 
1481
 
 
1482
            if(!sc)
 
1483
            {
 
1484
                osg::notify(osg::NOTICE) << "Unable to create XRRScreenConfiguration on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
 
1485
                return false;
 
1486
            }
 
1487
 
 
1488
            int      numScreens = 0;
 
1489
            int      numRates   = 0;
 
1490
            Rotation currentRot = 0;
 
1491
            bool     okay       = false;
 
1492
 
 
1493
            XRRConfigRotations(sc, &currentRot);
 
1494
            
 
1495
            // If the width or height are zero, use our defaults.
 
1496
            if(!width || !height)
 
1497
            {
 
1498
                getScreenResolution(si, width, height);
 
1499
            }
 
1500
 
 
1501
            // If this somehow fails, okay will still be false, no iteration will take place below,
 
1502
            // and the sc pointer will still be freed later on.
 
1503
            XRRScreenSize* ss = XRRConfigSizes(sc, &numScreens);
 
1504
 
 
1505
            for(int i = 0; i < numScreens; i++)
 
1506
            {
 
1507
                if(ss[i].width == static_cast<int>(width) && ss[i].height == static_cast<int>(height))
 
1508
                {
 
1509
                    short* rates     = XRRConfigRates(sc, i, &numRates);
 
1510
                    bool   rateFound = false;
 
1511
                    
 
1512
                    // Search for our rate in the list of acceptable rates given to us by Xrandr.
 
1513
                    // If it's not found, rateFound will still be false and the call will never
 
1514
                    // be made to XRRSetScreenConfigAndRate since the rate will be invalid.
 
1515
                    for(int r = 0; r < numRates; r++)
 
1516
                    {
 
1517
                        if(rates[r] == static_cast<short>(rate))
 
1518
                        {
 
1519
                            rateFound = true;
 
1520
                            break;
 
1521
                        }
 
1522
                    }
 
1523
 
 
1524
                    if(rate > 0.0f && !rateFound)
 
1525
                    {
 
1526
                        osg::notify(osg::NOTICE) << "Unable to find valid refresh rate " << rate << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
 
1527
                    }
 
1528
                    else if(XRRSetScreenConfigAndRate(display, sc, DefaultRootWindow(display), i, currentRot, static_cast<short>(rate), CurrentTime) != RRSetConfigSuccess)
 
1529
                    {
 
1530
                        osg::notify(osg::NOTICE) << "Unable to set resolution to " << width << "x" << height << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
 
1531
                    }
 
1532
                    else
 
1533
                    {
 
1534
                        okay = true;
 
1535
                        break;
 
1536
                    }
 
1537
                }
 
1538
            }
 
1539
    
 
1540
            XRRFreeScreenConfigInfo(sc);
 
1541
    
 
1542
            return okay;
 
1543
        }
 
1544
        else
 
1545
        {
 
1546
            osg::notify(osg::NOTICE) << "Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
 
1547
            return false;
 
1548
        }
 
1549
    }
 
1550
#endif
 
1551
 
 
1552
protected:
 
1553
    bool _errorHandlerSet;
 
1554
    
 
1555
 
 
1556
public:
1269
1557
    X11WindowingSystemInterface()
1270
1558
    {
1271
1559
        osg::notify(osg::INFO)<<"X11WindowingSystemInterface()"<<std::endl;
1272
 
    
1273
 
        XSetErrorHandler(X11ErrorHandling);
 
1560
 
 
1561
 
 
1562
        // Install an X11 error handler, if the application has not already done so.
 
1563
        
 
1564
        // Set default handler, and get pointer to current handler.
 
1565
        X11ErrorHandler currentHandler = XSetErrorHandler(NULL);
 
1566
        
 
1567
        // Set our handler, and get pointer to default handler.
 
1568
        X11ErrorHandler defHandler = XSetErrorHandler(X11ErrorHandling);
 
1569
 
 
1570
        if ( currentHandler == defHandler )
 
1571
        {
 
1572
            // No application error handler, use ours.
 
1573
            // osg::notify(osg::INFO)<<"Set osgViewer X11 error handler"<<std::endl;
 
1574
            _errorHandlerSet = 1;
 
1575
        }
 
1576
        else
 
1577
        {
 
1578
            // Application error handler exists, leave it set.
 
1579
            // osg::notify(osg::INFO)<<"Existing application X11 error handler set"<<std::endl;
 
1580
            _errorHandlerSet = 0;
 
1581
            XSetErrorHandler(currentHandler);
 
1582
        }
1274
1583
    
1275
1584
#if 0
1276
1585
        if (XInitThreads() == 0)
1294
1603
        }
1295
1604
 
1296
1605
        //osg::notify(osg::NOTICE)<<"~X11WindowingSystemInterface()"<<std::endl;
1297
 
        XSetErrorHandler(0);
 
1606
 
 
1607
        // Unset our X11 error handler, providing the application has not replaced it.
 
1608
 
 
1609
        if ( _errorHandlerSet )
 
1610
        {
 
1611
            X11ErrorHandler currentHandler = XSetErrorHandler(NULL);
 
1612
            if ( currentHandler == X11ErrorHandling )
 
1613
            {
 
1614
                // osg::notify(osg::INFO)<<"osgViewer X11 error handler removed"<<std::endl;
 
1615
            }
 
1616
            else
 
1617
            {
 
1618
                // Not our error handler, leave it set.
 
1619
                // osg::notify(osg::INFO)<<"Application X11 error handler left"<<std::endl;
 
1620
                XSetErrorHandler(currentHandler);
 
1621
            }
 
1622
        }
1298
1623
    }
1299
1624
 
1300
1625
    virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si) 
1331
1656
        }
1332
1657
    }
1333
1658
 
 
1659
    virtual bool setScreenResolution(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height)
 
1660
    {
 
1661
#ifdef OSGVIEWER_USE_XRANDR
 
1662
        return _setScreen(si, width, height, 0.0f);
 
1663
#else
 
1664
        osg::notify(osg::NOTICE) << "You must build osgViewer with Xrandr 1.2 or higher for setScreenResolution support!" << std::endl;
 
1665
        return false;
 
1666
#endif
 
1667
    }
 
1668
 
 
1669
    virtual bool setScreenRefreshRate(const osg::GraphicsContext::ScreenIdentifier& si, double rate)
 
1670
    {
 
1671
#ifdef OSGVIEWER_USE_XRANDR
 
1672
        return _setScreen(si, 0, 0, rate);
 
1673
#else
 
1674
        osg::notify(osg::NOTICE) << "You must build osgViewer with Xrandr 1.2 or higher for setScreenRefreshRate support!" << std::endl;
 
1675
        return false;
 
1676
#endif
 
1677
    }
 
1678
 
1334
1679
    virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits)
1335
1680
    {
1336
1681
        if (traits->pbuffer)