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);
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)
184
return (map[(key & 0xff) / 8] & (1 << (key & 7))) != 0;
187
static inline void keyMapSetKey(char* map, unsigned int key)
189
map[(key & 0xff) / 8] |= (1 << (key & 7));
192
static inline void keyMapClearKey(char* map, unsigned int key)
194
map[(key & 0xff) / 8] &= ~(1 << (key & 7));
173
197
GraphicsWindowX11::~GraphicsWindowX11()
267
291
#define MWM_FUNC_CLOSE (1L<<5)
294
bool GraphicsWindowX11::checkAndSendEventFullScreenIfNeeded(Display* display, int x, int y, int width, int height, bool windowDecoration)
296
osg::GraphicsContext::WindowingSystemInterface *wsi = osg::GraphicsContext::getWindowingSystemInterface();
298
osg::notify(osg::NOTICE) << "Error, no WindowSystemInterface available, cannot toggle window fullscreen." << std::endl;
302
unsigned int screenWidth;
303
unsigned int screenHeight;
305
wsi->getScreenResolution(*_traits, screenWidth, screenHeight);
306
bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight && !windowDecoration;
308
Atom netWMStateAtom = XInternAtom(display, "_NET_WM_STATE", True);
309
Atom netWMStateFullscreenAtom = XInternAtom(display,
310
"_NET_WM_STATE_FULLSCREEN", True);
312
if (netWMStateAtom != None && netWMStateFullscreenAtom != None) {
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;
324
XSendEvent(display, RootWindow(display, DefaultScreen(display)),
325
False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
270
331
bool GraphicsWindowX11::setWindowDecorationImplementation(bool flag)
272
333
Display* display = getDisplayToUse();
335
XMapWindow(display, _window );
337
checkAndSendEventFullScreenIfNeeded(display, _traits->x, _traits->y, _traits->width, _traits->height, flag);
341
unsigned long functions;
342
unsigned long decorations;
344
unsigned long status;
275
349
if( (atom = XInternAtom( display, "_MOTIF_WM_HINTS", 0 )) != None )
281
unsigned long functions;
282
unsigned long decorations;
284
unsigned long status;
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;
304
XMapWindow(display, _window );
305
368
XChangeProperty( display, _window, atom, atom, 32, PropModeReplace, (unsigned char *)&wmHints, 5 );
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;
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
327
373
osg::notify(osg::NOTICE)<<"Error: GraphicsWindowX11::setBorder(" << flag << ") - couldn't change decorations." << std::endl;
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
334
386
bool GraphicsWindowX11::setWindowRectangleImplementation(int x, int y, int width, int height)
995
osg::notify(osg::INFO)<<"FocusIn event received"<<std::endl;
1001
osg::notify(osg::INFO)<<"FocusOut/UnmapNotify event received"<<std::endl;
1002
if (ev.type == FocusOut && ev.xfocus.mode != NotifyNormal) break;
1005
getModifierMap(modMap);
1007
// release normal (non-modifier) keys
1008
for (unsigned int key = 8; key < 256; key++)
1010
bool isModifier = keyMapGetKey(modMap, key);
1011
if (!isModifier) forceKey(key, eventTime, false);
1014
// release modifier keys
1015
for (unsigned int key = 8; key < 256; key++)
1017
bool isModifier = keyMapGetKey(modMap, key);
1018
if (isModifier) forceKey(key, eventTime, false);
1024
osg::notify(osg::INFO)<<"EnterNotify event received"<<std::endl;
1025
_modifierState = ev.xcrossing.state;
1031
osg::notify(osg::INFO)<<"KeymapNotify event received"<<std::endl;
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;
1038
getModifierMap(modMap);
1041
// release normal (non-modifier) keys
1042
for (unsigned int key = 8; key < 256; key++)
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);
1050
// press/release modifier keys
1051
for (unsigned int key = 8; key < 256; key++)
1053
bool isModifier = keyMapGetKey(modMap, key);
1054
if (!isModifier) continue;
1055
bool isPressed = keyMapGetKey(ev.xkeymap.key_vector, key);
1056
forceKey(key, eventTime, isPressed);
1059
// press normal keys
1060
for (unsigned int key = 8; key < 256; key++)
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);
1070
case MappingNotify :
1071
osg::notify(osg::INFO)<<"MappingNotify event received"<<std::endl;
1072
if (ev.xmapping.request == MappingModifier) rescanModifierMapping();
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;
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);
1060
//getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
1061
1195
getEventQueue()->keyPress(keySymbol, eventTime);
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);
1091
//getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
1092
1226
getEventQueue()->keyRelease(keySymbol, eventTime);
1097
osg::notify(osg::NOTICE)<<"Other event"<<std::endl;
1231
osg::notify(osg::NOTICE)<<"Other event "<<ev.type<<std::endl;
1235
_lastEventType = ev.type;
1103
1238
if (windowX != _traits->x ||
1162
void GraphicsWindowX11::adaptKey(XKeyEvent& keyevent, int& keySymbol, unsigned int& modifierMask)
1297
void GraphicsWindowX11::adaptKey(XKeyEvent& keyevent, int& keySymbol)
1164
1299
Display* display = _eventDisplay;
1166
static XComposeStatus state;
1167
1301
unsigned char keybuf[32];
1168
XLookupString( &keyevent, (char *)keybuf, sizeof(keybuf), NULL, &state );
1171
if( keyevent.state & ShiftMask )
1173
modifierMask |= osgGA::GUIEventAdapter::MODKEY_SHIFT;
1175
if( keyevent.state & LockMask )
1177
modifierMask |= osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
1179
if( keyevent.state & ControlMask )
1181
modifierMask |= osgGA::GUIEventAdapter::MODKEY_CTRL;
1183
if( keyevent.state & Mod1Mask )
1185
modifierMask |= osgGA::GUIEventAdapter::MODKEY_ALT;
1187
if( keyevent.state & Mod2Mask )
1189
modifierMask |= osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
1191
if( keyevent.state & Mod4Mask )
1193
modifierMask |= osgGA::GUIEventAdapter::MODKEY_META;
1196
keySymbol = keybuf[0];
1302
XLookupString( &keyevent, (char *)keybuf, sizeof(keybuf), NULL, NULL );
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];
1318
// Function to inject artificial key presses/releases.
1319
void GraphicsWindowX11::forceKey(int key, double time, bool state)
1321
if (!(state ^ keyMapGetKey(_keyMap, key))) return; // already pressed/released
1325
event.send_event = True;
1326
event.display = _eventDisplay;
1327
event.window = _window;
1328
event.subwindow = 0;
1334
event.state = getModifierMask() | (_modifierState & (LockMask | _numLockMask));
1335
event.keycode = key;
1336
event.same_screen = True;
1341
event.type = KeyPress;
1342
adaptKey(event, keySymbol);
1343
getEventQueue()->keyPress(keySymbol, time);
1344
keyMapSetKey(_keyMap, key);
1348
event.type = KeyRelease;
1349
adaptKey(event, keySymbol);
1350
getEventQueue()->keyRelease(keySymbol, time);
1351
keyMapClearKey(_keyMap, key);
1355
void GraphicsWindowX11::syncLocks()
1357
unsigned int mask = getEventQueue()->getCurrentEventState()->getModKeyMask();
1359
if (_modifierState & LockMask)
1360
mask |= osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
1362
mask &= ~osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
1364
if (_modifierState & _numLockMask)
1365
mask |= osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
1367
mask &= ~osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
1369
getEventQueue()->getCurrentEventState()->setModKeyMask(mask);
1372
void GraphicsWindowX11::rescanModifierMapping()
1374
XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay);
1375
KeyCode *m = mkm->modifiermap;
1376
KeyCode numlock = XKeysymToKeycode(_eventDisplay, XK_Num_Lock);
1378
for (int i = 0; i < mkm->max_keypermod * 8; i++, m++)
1382
_numLockMask = 1 << (i / mkm->max_keypermod);
1388
// Returns char[32] keymap with bits for every modifier key set.
1389
void GraphicsWindowX11::getModifierMap(char* keymap) const
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++)
1396
if (*m) keyMapSetKey(keymap, *m);
1400
int GraphicsWindowX11::getModifierMask() const
1403
XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay);
1404
for (int i = 0; i < mkm->max_keypermod * 8; i++)
1406
unsigned int key = mkm->modifiermap[i];
1407
if (key && keyMapGetKey(_keyMap, key))
1409
mask |= 1 << (i / mkm->max_keypermod);
1214
1415
void GraphicsWindowX11::requestWarpPointer(float x,float y)
1266
struct X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface
1469
class X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface
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());
1480
XRRScreenConfiguration* sc = XRRGetScreenInfo(display, RootWindow(display, si.screenNum));
1484
osg::notify(osg::NOTICE) << "Unable to create XRRScreenConfiguration on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
1490
Rotation currentRot = 0;
1493
XRRConfigRotations(sc, ¤tRot);
1495
// If the width or height are zero, use our defaults.
1496
if(!width || !height)
1498
getScreenResolution(si, width, height);
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);
1505
for(int i = 0; i < numScreens; i++)
1507
if(ss[i].width == static_cast<int>(width) && ss[i].height == static_cast<int>(height))
1509
short* rates = XRRConfigRates(sc, i, &numRates);
1510
bool rateFound = false;
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++)
1517
if(rates[r] == static_cast<short>(rate))
1524
if(rate > 0.0f && !rateFound)
1526
osg::notify(osg::NOTICE) << "Unable to find valid refresh rate " << rate << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
1528
else if(XRRSetScreenConfigAndRate(display, sc, DefaultRootWindow(display), i, currentRot, static_cast<short>(rate), CurrentTime) != RRSetConfigSuccess)
1530
osg::notify(osg::NOTICE) << "Unable to set resolution to " << width << "x" << height << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
1540
XRRFreeScreenConfigInfo(sc);
1546
osg::notify(osg::NOTICE) << "Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
1553
bool _errorHandlerSet;
1269
1557
X11WindowingSystemInterface()
1271
1559
osg::notify(osg::INFO)<<"X11WindowingSystemInterface()"<<std::endl;
1273
XSetErrorHandler(X11ErrorHandling);
1562
// Install an X11 error handler, if the application has not already done so.
1564
// Set default handler, and get pointer to current handler.
1565
X11ErrorHandler currentHandler = XSetErrorHandler(NULL);
1567
// Set our handler, and get pointer to default handler.
1568
X11ErrorHandler defHandler = XSetErrorHandler(X11ErrorHandling);
1570
if ( currentHandler == defHandler )
1572
// No application error handler, use ours.
1573
// osg::notify(osg::INFO)<<"Set osgViewer X11 error handler"<<std::endl;
1574
_errorHandlerSet = 1;
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);
1276
1585
if (XInitThreads() == 0)
1296
1605
//osg::notify(osg::NOTICE)<<"~X11WindowingSystemInterface()"<<std::endl;
1297
XSetErrorHandler(0);
1607
// Unset our X11 error handler, providing the application has not replaced it.
1609
if ( _errorHandlerSet )
1611
X11ErrorHandler currentHandler = XSetErrorHandler(NULL);
1612
if ( currentHandler == X11ErrorHandling )
1614
// osg::notify(osg::INFO)<<"osgViewer X11 error handler removed"<<std::endl;
1618
// Not our error handler, leave it set.
1619
// osg::notify(osg::INFO)<<"Application X11 error handler left"<<std::endl;
1620
XSetErrorHandler(currentHandler);
1300
1625
virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si)
1659
virtual bool setScreenResolution(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height)
1661
#ifdef OSGVIEWER_USE_XRANDR
1662
return _setScreen(si, width, height, 0.0f);
1664
osg::notify(osg::NOTICE) << "You must build osgViewer with Xrandr 1.2 or higher for setScreenResolution support!" << std::endl;
1669
virtual bool setScreenRefreshRate(const osg::GraphicsContext::ScreenIdentifier& si, double rate)
1671
#ifdef OSGVIEWER_USE_XRANDR
1672
return _setScreen(si, 0, 0, rate);
1674
osg::notify(osg::NOTICE) << "You must build osgViewer with Xrandr 1.2 or higher for setScreenRefreshRate support!" << std::endl;
1334
1679
virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits)
1336
1681
if (traits->pbuffer)