| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | |
|---|
| 20 | |
|---|
| 21 | |
|---|
| 22 | #include <osgViewer/api/X11/GraphicsWindowX11> |
|---|
| 23 | #include <osgViewer/api/X11/PixelBufferX11> |
|---|
| 24 | |
|---|
| 25 | #include <osg/DeleteHandler> |
|---|
| 26 | |
|---|
| 27 | #include <X11/Xlib.h> |
|---|
| 28 | #include <X11/Xutil.h> |
|---|
| 29 | |
|---|
| 30 | #include <X11/Xmd.h> |
|---|
| 31 | #include <X11/keysym.h> |
|---|
| 32 | #include <X11/cursorfont.h> |
|---|
| 33 | |
|---|
| 34 | #include <X11/Xmd.h> |
|---|
| 35 | |
|---|
| 36 | #ifdef OSGVIEWER_USE_XRANDR |
|---|
| 37 | #include <X11/extensions/Xrandr.h> |
|---|
| 38 | #endif |
|---|
| 39 | |
|---|
| 40 | #include <unistd.h> |
|---|
| 41 | |
|---|
| 42 | using namespace osgViewer; |
|---|
| 43 | |
|---|
| 44 | #ifdef OSG_USE_EGL |
|---|
| 45 | bool checkEGLError(const char* str) |
|---|
| 46 | { |
|---|
| 47 | EGLint err = eglGetError(); |
|---|
| 48 | if (err != EGL_SUCCESS) |
|---|
| 49 | { |
|---|
| 50 | OSG_WARN<<"Warning: "<<str<<" EGL error "<<std::hex<<err<<std::dec<<std::endl; |
|---|
| 51 | return true; |
|---|
| 52 | } |
|---|
| 53 | else |
|---|
| 54 | { |
|---|
| 55 | |
|---|
| 56 | return false; |
|---|
| 57 | } |
|---|
| 58 | } |
|---|
| 59 | #endif |
|---|
| 60 | |
|---|
| 61 | class X11KeyboardMap |
|---|
| 62 | { |
|---|
| 63 | public: |
|---|
| 64 | |
|---|
| 65 | X11KeyboardMap() |
|---|
| 66 | { |
|---|
| 67 | #if 0 |
|---|
| 68 | _extendKeymap[8 ] = osgGA::GUIEventAdapter::KEY_BackSpace; |
|---|
| 69 | _extendKeymap[127 ] = osgGA::GUIEventAdapter::KEY_Delete; |
|---|
| 70 | _extendKeymap[27 ] = osgGA::GUIEventAdapter::KEY_Escape; |
|---|
| 71 | |
|---|
| 72 | #endif |
|---|
| 73 | _extendedKeymap[XK_Escape ] = osgGA::GUIEventAdapter::KEY_Escape; |
|---|
| 74 | _extendedKeymap[XK_F1 ] = osgGA::GUIEventAdapter::KEY_F1; |
|---|
| 75 | _extendedKeymap[XK_F2 ] = osgGA::GUIEventAdapter::KEY_F2; |
|---|
| 76 | _extendedKeymap[XK_F3 ] = osgGA::GUIEventAdapter::KEY_F3; |
|---|
| 77 | _extendedKeymap[XK_F4 ] = osgGA::GUIEventAdapter::KEY_F4; |
|---|
| 78 | _extendedKeymap[XK_F5 ] = osgGA::GUIEventAdapter::KEY_F5; |
|---|
| 79 | _extendedKeymap[XK_F6 ] = osgGA::GUIEventAdapter::KEY_F6; |
|---|
| 80 | _extendedKeymap[XK_F7 ] = osgGA::GUIEventAdapter::KEY_F7; |
|---|
| 81 | _extendedKeymap[XK_F8 ] = osgGA::GUIEventAdapter::KEY_F8; |
|---|
| 82 | _extendedKeymap[XK_F9 ] = osgGA::GUIEventAdapter::KEY_F9; |
|---|
| 83 | _extendedKeymap[XK_F10 ] = osgGA::GUIEventAdapter::KEY_F10; |
|---|
| 84 | _extendedKeymap[XK_F11 ] = osgGA::GUIEventAdapter::KEY_F11; |
|---|
| 85 | _extendedKeymap[XK_F12 ] = osgGA::GUIEventAdapter::KEY_F12; |
|---|
| 86 | _extendedKeymap[XK_quoteleft ] = '`'; |
|---|
| 87 | _extendedKeymap[XK_minus ] = '-'; |
|---|
| 88 | _extendedKeymap[XK_equal ] = '='; |
|---|
| 89 | _extendedKeymap[XK_BackSpace ] = osgGA::GUIEventAdapter::KEY_BackSpace; |
|---|
| 90 | _extendedKeymap[XK_Tab ] = osgGA::GUIEventAdapter::KEY_Tab; |
|---|
| 91 | _extendedKeymap[XK_bracketleft ] = '['; |
|---|
| 92 | _extendedKeymap[XK_bracketright ] = ']'; |
|---|
| 93 | _extendedKeymap[XK_backslash ] = '\\'; |
|---|
| 94 | _extendedKeymap[XK_Caps_Lock ] = osgGA::GUIEventAdapter::KEY_Caps_Lock; |
|---|
| 95 | _extendedKeymap[XK_semicolon ] = ';'; |
|---|
| 96 | _extendedKeymap[XK_apostrophe ] = '\''; |
|---|
| 97 | _extendedKeymap[XK_Return ] = osgGA::GUIEventAdapter::KEY_Return; |
|---|
| 98 | _extendedKeymap[XK_comma ] = ','; |
|---|
| 99 | _extendedKeymap[XK_period ] = '.'; |
|---|
| 100 | _extendedKeymap[XK_slash ] = '/'; |
|---|
| 101 | _extendedKeymap[XK_space ] = ' '; |
|---|
| 102 | _extendedKeymap[XK_Shift_L ] = osgGA::GUIEventAdapter::KEY_Shift_L; |
|---|
| 103 | _extendedKeymap[XK_Shift_R ] = osgGA::GUIEventAdapter::KEY_Shift_R; |
|---|
| 104 | _extendedKeymap[XK_Control_L ] = osgGA::GUIEventAdapter::KEY_Control_L; |
|---|
| 105 | _extendedKeymap[XK_Control_R ] = osgGA::GUIEventAdapter::KEY_Control_R; |
|---|
| 106 | _extendedKeymap[XK_Meta_L ] = osgGA::GUIEventAdapter::KEY_Meta_L; |
|---|
| 107 | _extendedKeymap[XK_Meta_R ] = osgGA::GUIEventAdapter::KEY_Meta_R; |
|---|
| 108 | _extendedKeymap[XK_Alt_L ] = osgGA::GUIEventAdapter::KEY_Alt_L; |
|---|
| 109 | _extendedKeymap[XK_Alt_R ] = osgGA::GUIEventAdapter::KEY_Alt_R; |
|---|
| 110 | _extendedKeymap[XK_Super_L ] = osgGA::GUIEventAdapter::KEY_Super_L; |
|---|
| 111 | _extendedKeymap[XK_Super_R ] = osgGA::GUIEventAdapter::KEY_Super_R; |
|---|
| 112 | _extendedKeymap[XK_Hyper_L ] = osgGA::GUIEventAdapter::KEY_Hyper_L; |
|---|
| 113 | _extendedKeymap[XK_Hyper_R ] = osgGA::GUIEventAdapter::KEY_Hyper_R; |
|---|
| 114 | _extendedKeymap[XK_Menu ] = osgGA::GUIEventAdapter::KEY_Menu; |
|---|
| 115 | _extendedKeymap[XK_Print ] = osgGA::GUIEventAdapter::KEY_Print; |
|---|
| 116 | _extendedKeymap[XK_Scroll_Lock ] = osgGA::GUIEventAdapter::KEY_Scroll_Lock; |
|---|
| 117 | _extendedKeymap[XK_Pause ] = osgGA::GUIEventAdapter::KEY_Pause; |
|---|
| 118 | _extendedKeymap[XK_Home ] = osgGA::GUIEventAdapter::KEY_Home; |
|---|
| 119 | _extendedKeymap[XK_Page_Up ] = osgGA::GUIEventAdapter::KEY_Page_Up; |
|---|
| 120 | _extendedKeymap[XK_End ] = osgGA::GUIEventAdapter::KEY_End; |
|---|
| 121 | _extendedKeymap[XK_Page_Down ] = osgGA::GUIEventAdapter::KEY_Page_Down; |
|---|
| 122 | _extendedKeymap[XK_Delete ] = osgGA::GUIEventAdapter::KEY_Delete; |
|---|
| 123 | _extendedKeymap[XK_Insert ] = osgGA::GUIEventAdapter::KEY_Insert; |
|---|
| 124 | _extendedKeymap[XK_Left ] = osgGA::GUIEventAdapter::KEY_Left; |
|---|
| 125 | _extendedKeymap[XK_Up ] = osgGA::GUIEventAdapter::KEY_Up; |
|---|
| 126 | _extendedKeymap[XK_Right ] = osgGA::GUIEventAdapter::KEY_Right; |
|---|
| 127 | _extendedKeymap[XK_Down ] = osgGA::GUIEventAdapter::KEY_Down; |
|---|
| 128 | _extendedKeymap[XK_Num_Lock ] = osgGA::GUIEventAdapter::KEY_Num_Lock; |
|---|
| 129 | _extendedKeymap[XK_KP_Divide ] = osgGA::GUIEventAdapter::KEY_KP_Divide; |
|---|
| 130 | _extendedKeymap[XK_KP_Multiply ] = osgGA::GUIEventAdapter::KEY_KP_Multiply; |
|---|
| 131 | _extendedKeymap[XK_KP_Subtract ] = osgGA::GUIEventAdapter::KEY_KP_Subtract; |
|---|
| 132 | _extendedKeymap[XK_KP_Add ] = osgGA::GUIEventAdapter::KEY_KP_Add; |
|---|
| 133 | _extendedKeymap[XK_KP_Home ] = osgGA::GUIEventAdapter::KEY_KP_Home; |
|---|
| 134 | _extendedKeymap[XK_KP_Up ] = osgGA::GUIEventAdapter::KEY_KP_Up; |
|---|
| 135 | _extendedKeymap[XK_KP_Page_Up ] = osgGA::GUIEventAdapter::KEY_KP_Page_Up; |
|---|
| 136 | _extendedKeymap[XK_KP_Left ] = osgGA::GUIEventAdapter::KEY_KP_Left; |
|---|
| 137 | _extendedKeymap[XK_KP_Begin ] = osgGA::GUIEventAdapter::KEY_KP_Begin; |
|---|
| 138 | _extendedKeymap[XK_KP_Right ] = osgGA::GUIEventAdapter::KEY_KP_Right; |
|---|
| 139 | _extendedKeymap[XK_KP_End ] = osgGA::GUIEventAdapter::KEY_KP_End; |
|---|
| 140 | _extendedKeymap[XK_KP_Down ] = osgGA::GUIEventAdapter::KEY_KP_Down; |
|---|
| 141 | _extendedKeymap[XK_KP_Page_Down ] = osgGA::GUIEventAdapter::KEY_KP_Page_Down; |
|---|
| 142 | _extendedKeymap[XK_KP_Insert ] = osgGA::GUIEventAdapter::KEY_KP_Insert; |
|---|
| 143 | _extendedKeymap[XK_KP_Delete ] = osgGA::GUIEventAdapter::KEY_KP_Delete; |
|---|
| 144 | _extendedKeymap[XK_KP_Enter ] = osgGA::GUIEventAdapter::KEY_KP_Enter; |
|---|
| 145 | |
|---|
| 146 | _standardKeymap[XK_1 ] = '1'; |
|---|
| 147 | _standardKeymap[XK_2 ] = '2'; |
|---|
| 148 | _standardKeymap[XK_3 ] = '3'; |
|---|
| 149 | _standardKeymap[XK_4 ] = '4'; |
|---|
| 150 | _standardKeymap[XK_5 ] = '5'; |
|---|
| 151 | _standardKeymap[XK_6 ] = '6'; |
|---|
| 152 | _standardKeymap[XK_7 ] = '7'; |
|---|
| 153 | _standardKeymap[XK_8 ] = '8'; |
|---|
| 154 | _standardKeymap[XK_9 ] = '9'; |
|---|
| 155 | _standardKeymap[XK_0 ] = '0'; |
|---|
| 156 | _standardKeymap[XK_A ] = 'A'; |
|---|
| 157 | _standardKeymap[XK_B ] = 'B'; |
|---|
| 158 | _standardKeymap[XK_C ] = 'C'; |
|---|
| 159 | _standardKeymap[XK_D ] = 'D'; |
|---|
| 160 | _standardKeymap[XK_E ] = 'E'; |
|---|
| 161 | _standardKeymap[XK_F ] = 'F'; |
|---|
| 162 | _standardKeymap[XK_G ] = 'G'; |
|---|
| 163 | _standardKeymap[XK_H ] = 'H'; |
|---|
| 164 | _standardKeymap[XK_I ] = 'I'; |
|---|
| 165 | _standardKeymap[XK_J ] = 'J'; |
|---|
| 166 | _standardKeymap[XK_K ] = 'K'; |
|---|
| 167 | _standardKeymap[XK_L ] = 'L'; |
|---|
| 168 | _standardKeymap[XK_M ] = 'M'; |
|---|
| 169 | _standardKeymap[XK_N ] = 'N'; |
|---|
| 170 | _standardKeymap[XK_O ] = 'O'; |
|---|
| 171 | _standardKeymap[XK_P ] = 'P'; |
|---|
| 172 | _standardKeymap[XK_Q ] = 'Q'; |
|---|
| 173 | _standardKeymap[XK_R ] = 'R'; |
|---|
| 174 | _standardKeymap[XK_S ] = 'S'; |
|---|
| 175 | _standardKeymap[XK_T ] = 'T'; |
|---|
| 176 | _standardKeymap[XK_U ] = 'U'; |
|---|
| 177 | _standardKeymap[XK_V ] = 'V'; |
|---|
| 178 | _standardKeymap[XK_W ] = 'W'; |
|---|
| 179 | _standardKeymap[XK_X ] = 'X'; |
|---|
| 180 | _standardKeymap[XK_Y ] = 'Y'; |
|---|
| 181 | _standardKeymap[XK_Z ] = 'Z'; |
|---|
| 182 | _standardKeymap[XK_a ] = 'a'; |
|---|
| 183 | _standardKeymap[XK_b ] = 'b'; |
|---|
| 184 | _standardKeymap[XK_c ] = 'c'; |
|---|
| 185 | _standardKeymap[XK_d ] = 'd'; |
|---|
| 186 | _standardKeymap[XK_e ] = 'e'; |
|---|
| 187 | _standardKeymap[XK_f ] = 'f'; |
|---|
| 188 | _standardKeymap[XK_g ] = 'g'; |
|---|
| 189 | _standardKeymap[XK_h ] = 'h'; |
|---|
| 190 | _standardKeymap[XK_i ] = 'i'; |
|---|
| 191 | _standardKeymap[XK_j ] = 'j'; |
|---|
| 192 | _standardKeymap[XK_k ] = 'k'; |
|---|
| 193 | _standardKeymap[XK_l ] = 'l'; |
|---|
| 194 | _standardKeymap[XK_m ] = 'm'; |
|---|
| 195 | _standardKeymap[XK_n ] = 'n'; |
|---|
| 196 | _standardKeymap[XK_o ] = 'o'; |
|---|
| 197 | _standardKeymap[XK_p ] = 'p'; |
|---|
| 198 | _standardKeymap[XK_q ] = 'q'; |
|---|
| 199 | _standardKeymap[XK_r ] = 'r'; |
|---|
| 200 | _standardKeymap[XK_s ] = 's'; |
|---|
| 201 | _standardKeymap[XK_t ] = 't'; |
|---|
| 202 | _standardKeymap[XK_u ] = 'u'; |
|---|
| 203 | _standardKeymap[XK_v ] = 'v'; |
|---|
| 204 | _standardKeymap[XK_w ] = 'w'; |
|---|
| 205 | _standardKeymap[XK_x ] = 'x'; |
|---|
| 206 | _standardKeymap[XK_y ] = 'y'; |
|---|
| 207 | _standardKeymap[XK_z ] = 'z'; |
|---|
| 208 | } |
|---|
| 209 | |
|---|
| 210 | ~X11KeyboardMap() {} |
|---|
| 211 | |
|---|
| 212 | int remapKey(int key) |
|---|
| 213 | { |
|---|
| 214 | KeyMap::iterator itr = _extendedKeymap.find(key); |
|---|
| 215 | if (itr != _extendedKeymap.end()) return itr->second; |
|---|
| 216 | |
|---|
| 217 | itr = _standardKeymap.find(key); |
|---|
| 218 | if (itr != _standardKeymap.end()) return itr->second; |
|---|
| 219 | |
|---|
| 220 | return key; |
|---|
| 221 | } |
|---|
| 222 | |
|---|
| 223 | bool remapExtendedKey(int& key) |
|---|
| 224 | { |
|---|
| 225 | KeyMap::iterator itr = _extendedKeymap.find(key); |
|---|
| 226 | if (itr != _extendedKeymap.end()) |
|---|
| 227 | { |
|---|
| 228 | key = itr->second; |
|---|
| 229 | return true; |
|---|
| 230 | } |
|---|
| 231 | else return false; |
|---|
| 232 | } |
|---|
| 233 | |
|---|
| 234 | protected: |
|---|
| 235 | |
|---|
| 236 | typedef std::map<int, int> KeyMap; |
|---|
| 237 | KeyMap _extendedKeymap; |
|---|
| 238 | KeyMap _standardKeymap; |
|---|
| 239 | }; |
|---|
| 240 | |
|---|
| 241 | static bool remapExtendedX11Key(int& key) |
|---|
| 242 | { |
|---|
| 243 | static X11KeyboardMap s_x11KeyboardMap; |
|---|
| 244 | return s_x11KeyboardMap.remapExtendedKey(key); |
|---|
| 245 | } |
|---|
| 246 | |
|---|
| 247 | |
|---|
| 248 | |
|---|
| 249 | static inline bool keyMapGetKey(const char* map, unsigned int key) |
|---|
| 250 | { |
|---|
| 251 | return (map[(key & 0xff) / 8] & (1 << (key & 7))) != 0; |
|---|
| 252 | } |
|---|
| 253 | |
|---|
| 254 | static inline void keyMapSetKey(char* map, unsigned int key) |
|---|
| 255 | { |
|---|
| 256 | map[(key & 0xff) / 8] |= (1 << (key & 7)); |
|---|
| 257 | } |
|---|
| 258 | |
|---|
| 259 | static inline void keyMapClearKey(char* map, unsigned int key) |
|---|
| 260 | { |
|---|
| 261 | map[(key & 0xff) / 8] &= ~(1 << (key & 7)); |
|---|
| 262 | } |
|---|
| 263 | |
|---|
| 264 | GraphicsWindowX11::~GraphicsWindowX11() |
|---|
| 265 | { |
|---|
| 266 | close(true); |
|---|
| 267 | } |
|---|
| 268 | |
|---|
| 269 | Display* GraphicsWindowX11::getDisplayToUse() const |
|---|
| 270 | { |
|---|
| 271 | if (_threadOfLastMakeCurrent==0) |
|---|
| 272 | { |
|---|
| 273 | return _display; |
|---|
| 274 | } |
|---|
| 275 | |
|---|
| 276 | if (OpenThreads::Thread::CurrentThread()==_threadOfLastMakeCurrent) |
|---|
| 277 | { |
|---|
| 278 | return _display; |
|---|
| 279 | } |
|---|
| 280 | else |
|---|
| 281 | { |
|---|
| 282 | return _eventDisplay; |
|---|
| 283 | } |
|---|
| 284 | } |
|---|
| 285 | |
|---|
| 286 | bool GraphicsWindowX11::createVisualInfo() |
|---|
| 287 | { |
|---|
| 288 | if (_visualInfo) |
|---|
| 289 | { |
|---|
| 290 | #ifdef OSG_USE_EGL |
|---|
| 291 | delete _visualInfo; |
|---|
| 292 | #else |
|---|
| 293 | XFree(_visualInfo); |
|---|
| 294 | #endif |
|---|
| 295 | _visualInfo = 0; |
|---|
| 296 | } |
|---|
| 297 | |
|---|
| 298 | if( _window != 0 ) |
|---|
| 299 | { |
|---|
| 300 | XWindowAttributes watt; |
|---|
| 301 | XGetWindowAttributes( _display, _window, &watt ); |
|---|
| 302 | XVisualInfo temp; |
|---|
| 303 | temp.visualid = XVisualIDFromVisual(watt.visual); |
|---|
| 304 | int n; |
|---|
| 305 | _visualInfo = XGetVisualInfo( _display, VisualIDMask, &temp, &n ); |
|---|
| 306 | } |
|---|
| 307 | else |
|---|
| 308 | { |
|---|
| 309 | #ifdef OSG_USE_EGL |
|---|
| 310 | |
|---|
| 311 | _visualInfo = new XVisualInfo; |
|---|
| 312 | int depth = DefaultDepth( _display, _traits->screenNum ); |
|---|
| 313 | if (XMatchVisualInfo( _display, _traits->screenNum, depth, TrueColor, _visualInfo )==0) |
|---|
| 314 | { |
|---|
| 315 | OSG_NOTICE<<"GraphicsWindowX11::createVisualInfo() failed."<<std::endl; |
|---|
| 316 | return false; |
|---|
| 317 | } |
|---|
| 318 | |
|---|
| 319 | #else |
|---|
| 320 | |
|---|
| 321 | typedef std::vector<int> Attributes; |
|---|
| 322 | Attributes attributes; |
|---|
| 323 | |
|---|
| 324 | attributes.push_back(GLX_USE_GL); |
|---|
| 325 | |
|---|
| 326 | attributes.push_back(GLX_RGBA); |
|---|
| 327 | |
|---|
| 328 | if (_traits->doubleBuffer) attributes.push_back(GLX_DOUBLEBUFFER); |
|---|
| 329 | |
|---|
| 330 | if (_traits->quadBufferStereo) attributes.push_back(GLX_STEREO); |
|---|
| 331 | |
|---|
| 332 | attributes.push_back(GLX_RED_SIZE); attributes.push_back(_traits->red); |
|---|
| 333 | attributes.push_back(GLX_GREEN_SIZE); attributes.push_back(_traits->green); |
|---|
| 334 | attributes.push_back(GLX_BLUE_SIZE); attributes.push_back(_traits->blue); |
|---|
| 335 | attributes.push_back(GLX_DEPTH_SIZE); attributes.push_back(_traits->depth); |
|---|
| 336 | |
|---|
| 337 | if (_traits->alpha) { attributes.push_back(GLX_ALPHA_SIZE); attributes.push_back(_traits->alpha); } |
|---|
| 338 | |
|---|
| 339 | if (_traits->stencil) { attributes.push_back(GLX_STENCIL_SIZE); attributes.push_back(_traits->stencil); } |
|---|
| 340 | |
|---|
| 341 | #if defined(GLX_SAMPLE_BUFFERS) && defined (GLX_SAMPLES) |
|---|
| 342 | |
|---|
| 343 | if (_traits->sampleBuffers) { attributes.push_back(GLX_SAMPLE_BUFFERS); attributes.push_back(_traits->sampleBuffers); } |
|---|
| 344 | if (_traits->samples) { attributes.push_back(GLX_SAMPLES); attributes.push_back(_traits->samples); } |
|---|
| 345 | |
|---|
| 346 | #endif |
|---|
| 347 | |
|---|
| 348 | |
|---|
| 349 | |
|---|
| 350 | |
|---|
| 351 | |
|---|
| 352 | attributes.push_back(None); |
|---|
| 353 | |
|---|
| 354 | _visualInfo = glXChooseVisual( _display, _traits->screenNum, &(attributes.front()) ); |
|---|
| 355 | #endif |
|---|
| 356 | } |
|---|
| 357 | |
|---|
| 358 | return _visualInfo != 0; |
|---|
| 359 | } |
|---|
| 360 | |
|---|
| 361 | bool GraphicsWindowX11::checkAndSendEventFullScreenIfNeeded(Display* display, int x, int y, int width, int height, bool windowDecoration) |
|---|
| 362 | { |
|---|
| 363 | osg::GraphicsContext::WindowingSystemInterface *wsi = osg::GraphicsContext::getWindowingSystemInterface(); |
|---|
| 364 | if (wsi == NULL) |
|---|
| 365 | { |
|---|
| 366 | OSG_NOTICE << "Error, no WindowSystemInterface available, cannot toggle window fullscreen." << std::endl; |
|---|
| 367 | return false; |
|---|
| 368 | } |
|---|
| 369 | |
|---|
| 370 | unsigned int screenWidth; |
|---|
| 371 | unsigned int screenHeight; |
|---|
| 372 | |
|---|
| 373 | wsi->getScreenResolution(*_traits, screenWidth, screenHeight); |
|---|
| 374 | bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight && !windowDecoration; |
|---|
| 375 | |
|---|
| 376 | if (isFullScreen) { |
|---|
| 377 | resized(x, y, width, height); |
|---|
| 378 | getEventQueue()->windowResize(x, y, width, height, getEventQueue()->getTime()); |
|---|
| 379 | } |
|---|
| 380 | |
|---|
| 381 | Atom netWMStateAtom = XInternAtom(display, "_NET_WM_STATE", True); |
|---|
| 382 | Atom netWMStateFullscreenAtom = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", True); |
|---|
| 383 | |
|---|
| 384 | if (netWMStateAtom != None && netWMStateFullscreenAtom != None) |
|---|
| 385 | { |
|---|
| 386 | XEvent xev; |
|---|
| 387 | xev.xclient.type = ClientMessage; |
|---|
| 388 | xev.xclient.serial = 0; |
|---|
| 389 | xev.xclient.send_event = True; |
|---|
| 390 | xev.xclient.window = _window; |
|---|
| 391 | xev.xclient.message_type = netWMStateAtom; |
|---|
| 392 | xev.xclient.format = 32; |
|---|
| 393 | xev.xclient.data.l[0] = isFullScreen ? 1 : 0; |
|---|
| 394 | xev.xclient.data.l[1] = netWMStateFullscreenAtom; |
|---|
| 395 | xev.xclient.data.l[2] = 0; |
|---|
| 396 | |
|---|
| 397 | XSendEvent(display, RootWindow(display, DefaultScreen(display)), |
|---|
| 398 | False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); |
|---|
| 399 | return true; |
|---|
| 400 | } |
|---|
| 401 | return false; |
|---|
| 402 | } |
|---|
| 403 | |
|---|
| 404 | #define MWM_HINTS_FUNCTIONS (1L << 0) |
|---|
| 405 | #define MWM_HINTS_DECORATIONS (1L << 1) |
|---|
| 406 | #define MWM_HINTS_INPUT_MODE (1L << 2) |
|---|
| 407 | #define MWM_HINTS_STATUS (1L << 3) |
|---|
| 408 | |
|---|
| 409 | #define MWM_DECOR_ALL (1L<<0) |
|---|
| 410 | #define MWM_DECOR_BORDER (1L<<1) |
|---|
| 411 | #define MWM_DECOR_RESIZEH (1L<<2) |
|---|
| 412 | #define MWM_DECOR_TITLE (1L<<3) |
|---|
| 413 | #define MWM_DECOR_MENU (1L<<4) |
|---|
| 414 | #define MWM_DECOR_MINIMIZE (1L<<5) |
|---|
| 415 | #define MWM_DECOR_MAXIMIZE (1L<<6) |
|---|
| 416 | |
|---|
| 417 | #define MWM_FUNC_ALL (1L<<0) |
|---|
| 418 | #define MWM_FUNC_RESIZE (1L<<1) |
|---|
| 419 | #define MWM_FUNC_MOVE (1L<<2) |
|---|
| 420 | #define MWM_FUNC_MINIMIZE (1L<<3) |
|---|
| 421 | #define MWM_FUNC_MAXIMIZE (1L<<4) |
|---|
| 422 | #define MWM_FUNC_CLOSE (1L<<5) |
|---|
| 423 | |
|---|
| 424 | bool GraphicsWindowX11::setWindowDecorationImplementation(bool flag) |
|---|
| 425 | { |
|---|
| 426 | Display* display = getDisplayToUse(); |
|---|
| 427 | |
|---|
| 428 | XMapWindow(display, _window ); |
|---|
| 429 | |
|---|
| 430 | checkAndSendEventFullScreenIfNeeded(display, _traits->x, _traits->y, _traits->width, _traits->height, flag); |
|---|
| 431 | struct |
|---|
| 432 | { |
|---|
| 433 | unsigned long flags; |
|---|
| 434 | unsigned long functions; |
|---|
| 435 | unsigned long decorations; |
|---|
| 436 | long inputMode; |
|---|
| 437 | unsigned long status; |
|---|
| 438 | } wmHints; |
|---|
| 439 | |
|---|
| 440 | Atom atom; |
|---|
| 441 | bool result = false; |
|---|
| 442 | if( (atom = XInternAtom( display, "_MOTIF_WM_HINTS", 0 )) != None ) |
|---|
| 443 | { |
|---|
| 444 | |
|---|
| 445 | if (flag) |
|---|
| 446 | { |
|---|
| 447 | wmHints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS; |
|---|
| 448 | wmHints.functions = MWM_FUNC_ALL; |
|---|
| 449 | wmHints.decorations = MWM_DECOR_ALL; |
|---|
| 450 | wmHints.inputMode = 0; |
|---|
| 451 | wmHints.status = 0; |
|---|
| 452 | |
|---|
| 453 | |
|---|
| 454 | |
|---|
| 455 | if (_traits.valid() && !_traits->supportsResize) wmHints.functions = wmHints.functions | MWM_FUNC_RESIZE; |
|---|
| 456 | |
|---|
| 457 | } |
|---|
| 458 | else |
|---|
| 459 | { |
|---|
| 460 | wmHints.flags = MWM_HINTS_DECORATIONS; |
|---|
| 461 | wmHints.functions = 0; |
|---|
| 462 | wmHints.decorations = 0; |
|---|
| 463 | wmHints.inputMode = 0; |
|---|
| 464 | wmHints.status = 0; |
|---|
| 465 | } |
|---|
| 466 | |
|---|
| 467 | XChangeProperty( display, _window, atom, atom, 32, PropModeReplace, (unsigned char *)&wmHints, 5 ); |
|---|
| 468 | result = true; |
|---|
| 469 | } |
|---|
| 470 | else |
|---|
| 471 | { |
|---|
| 472 | OSG_NOTICE<<"Error: GraphicsWindowX11::setWindowDecorationImplementation(" << flag << ") - couldn't change decorations." << std::endl; |
|---|
| 473 | result = false; |
|---|
| 474 | } |
|---|
| 475 | |
|---|
| 476 | XFlush(display); |
|---|
| 477 | XSync(display,0); |
|---|
| 478 | |
|---|
| 479 | |
|---|
| 480 | |
|---|
| 481 | usleep(100000); |
|---|
| 482 | return result; |
|---|
| 483 | } |
|---|
| 484 | |
|---|
| 485 | bool GraphicsWindowX11::setWindowRectangleImplementation(int x, int y, int width, int height) |
|---|
| 486 | { |
|---|
| 487 | if (!_initialized) return false; |
|---|
| 488 | |
|---|
| 489 | Display* display = getDisplayToUse(); |
|---|
| 490 | |
|---|
| 491 | checkAndSendEventFullScreenIfNeeded(display, x, y, width, height, _traits->windowDecoration); |
|---|
| 492 | |
|---|
| 493 | XMoveResizeWindow(display, _window, x, y, width, height); |
|---|
| 494 | |
|---|
| 495 | XFlush(display); |
|---|
| 496 | XSync(display, 0); |
|---|
| 497 | |
|---|
| 498 | |
|---|
| 499 | |
|---|
| 500 | |
|---|
| 501 | usleep(100000); |
|---|
| 502 | |
|---|
| 503 | |
|---|
| 504 | return true; |
|---|
| 505 | } |
|---|
| 506 | |
|---|
| 507 | void GraphicsWindowX11::setWindowName(const std::string& name) |
|---|
| 508 | { |
|---|
| 509 | if( _window == 0) return; |
|---|
| 510 | |
|---|
| 511 | |
|---|
| 512 | |
|---|
| 513 | |
|---|
| 514 | |
|---|
| 515 | |
|---|
| 516 | Display* display = getDisplayToUse(); |
|---|
| 517 | if( !display ) return; |
|---|
| 518 | |
|---|
| 519 | |
|---|
| 520 | XStoreName( display, _window, name.c_str() ); |
|---|
| 521 | XSetIconName( display, _window, name.c_str() ); |
|---|
| 522 | |
|---|
| 523 | XFlush(display); |
|---|
| 524 | XSync(display,0); |
|---|
| 525 | |
|---|
| 526 | _traits->windowName = name; |
|---|
| 527 | } |
|---|
| 528 | |
|---|
| 529 | void GraphicsWindowX11::setCursor(MouseCursor mouseCursor) |
|---|
| 530 | { |
|---|
| 531 | Cursor newCursor = getOrCreateCursor(mouseCursor); |
|---|
| 532 | if (newCursor == _currentCursor) return; |
|---|
| 533 | |
|---|
| 534 | _currentCursor = newCursor; |
|---|
| 535 | if (!_window) return; |
|---|
| 536 | Display* display = getDisplayToUse(); |
|---|
| 537 | if (!display) return; |
|---|
| 538 | XDefineCursor( display, _window, _currentCursor ); |
|---|
| 539 | XFlush(display); |
|---|
| 540 | XSync(display, 0); |
|---|
| 541 | |
|---|
| 542 | _traits->useCursor = (_currentCursor != getOrCreateCursor(NoCursor)); |
|---|
| 543 | } |
|---|
| 544 | |
|---|
| 545 | Cursor GraphicsWindowX11::getOrCreateCursor(MouseCursor mouseCursor) |
|---|
| 546 | { |
|---|
| 547 | std::map<MouseCursor,Cursor>::iterator i = _mouseCursorMap.find(mouseCursor); |
|---|
| 548 | if (i != _mouseCursorMap.end()) return i->second; |
|---|
| 549 | |
|---|
| 550 | Display* display = getDisplayToUse(); |
|---|
| 551 | if (!display) return None; |
|---|
| 552 | |
|---|
| 553 | switch (mouseCursor) { |
|---|
| 554 | case NoCursor: |
|---|
| 555 | { |
|---|
| 556 | |
|---|
| 557 | |
|---|
| 558 | char buff[2] = {0,0}; |
|---|
| 559 | XColor ncol = {0,0,0,0,DoRed|DoGreen|DoBlue,0}; |
|---|
| 560 | Pixmap pixmap = XCreateBitmapFromData( display, _parent, buff, 1, 1); |
|---|
| 561 | _mouseCursorMap[mouseCursor] = XCreatePixmapCursor( display, pixmap, pixmap, &ncol, &ncol, 0, 0 ); |
|---|
| 562 | XFreePixmap(display, pixmap); |
|---|
| 563 | |
|---|
| 564 | XFlush(display); |
|---|
| 565 | XSync(display, 0); |
|---|
| 566 | break; |
|---|
| 567 | } |
|---|
| 568 | case RightArrowCursor: |
|---|
| 569 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_ptr ); |
|---|
| 570 | break; |
|---|
| 571 | case LeftArrowCursor: |
|---|
| 572 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_arrow ); |
|---|
| 573 | break; |
|---|
| 574 | case InfoCursor: |
|---|
| 575 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_hand1 ); |
|---|
| 576 | break; |
|---|
| 577 | case DestroyCursor: |
|---|
| 578 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_pirate ); |
|---|
| 579 | break; |
|---|
| 580 | case HelpCursor: |
|---|
| 581 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_question_arrow ); |
|---|
| 582 | break; |
|---|
| 583 | case CycleCursor: |
|---|
| 584 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_exchange ); |
|---|
| 585 | break; |
|---|
| 586 | case SprayCursor: |
|---|
| 587 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_spraycan ); |
|---|
| 588 | break; |
|---|
| 589 | case WaitCursor: |
|---|
| 590 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_watch ); |
|---|
| 591 | break; |
|---|
| 592 | case TextCursor: |
|---|
| 593 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_xterm ); |
|---|
| 594 | break; |
|---|
| 595 | case CrosshairCursor: |
|---|
| 596 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_crosshair ); |
|---|
| 597 | break; |
|---|
| 598 | case UpDownCursor: |
|---|
| 599 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_v_double_arrow ); |
|---|
| 600 | break; |
|---|
| 601 | case LeftRightCursor: |
|---|
| 602 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_h_double_arrow ); |
|---|
| 603 | break; |
|---|
| 604 | case TopSideCursor: |
|---|
| 605 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_side ); |
|---|
| 606 | break; |
|---|
| 607 | case BottomSideCursor: |
|---|
| 608 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_side ); |
|---|
| 609 | break; |
|---|
| 610 | case LeftSideCursor: |
|---|
| 611 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_side ); |
|---|
| 612 | break; |
|---|
| 613 | case RightSideCursor: |
|---|
| 614 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_right_side ); |
|---|
| 615 | break; |
|---|
| 616 | case TopLeftCorner: |
|---|
| 617 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_corner ); |
|---|
| 618 | break; |
|---|
| 619 | case TopRightCorner: |
|---|
| 620 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_right_corner ); |
|---|
| 621 | break; |
|---|
| 622 | case BottomRightCorner: |
|---|
| 623 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_right_corner ); |
|---|
| 624 | break; |
|---|
| 625 | case BottomLeftCorner: |
|---|
| 626 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_left_corner ); |
|---|
| 627 | break; |
|---|
| 628 | case HandCursor: |
|---|
| 629 | _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_hand1 ); |
|---|
| 630 | break; |
|---|
| 631 | |
|---|
| 632 | case InheritCursor: |
|---|
| 633 | default: |
|---|
| 634 | _mouseCursorMap[mouseCursor] = None; |
|---|
| 635 | break; |
|---|
| 636 | }; |
|---|
| 637 | return _mouseCursorMap[mouseCursor]; |
|---|
| 638 | } |
|---|
| 639 | |
|---|
| 640 | void GraphicsWindowX11::init() |
|---|
| 641 | { |
|---|
| 642 | if (_initialized) return; |
|---|
| 643 | |
|---|
| 644 | if (!_traits) |
|---|
| 645 | { |
|---|
| 646 | _valid = false; |
|---|
| 647 | return; |
|---|
| 648 | } |
|---|
| 649 | |
|---|
| 650 | |
|---|
| 651 | |
|---|
| 652 | WindowData* inheritedWindowData = dynamic_cast<WindowData*>(_traits->inheritedWindowData.get()); |
|---|
| 653 | Window windowHandle = inheritedWindowData ? inheritedWindowData->_window : 0; |
|---|
| 654 | |
|---|
| 655 | _ownsWindow = windowHandle == 0; |
|---|
| 656 | |
|---|
| 657 | _display = XOpenDisplay(_traits->displayName().c_str()); |
|---|
| 658 | |
|---|
| 659 | if (!_display) |
|---|
| 660 | { |
|---|
| 661 | OSG_NOTICE<<"Error: Unable to open display \"" << XDisplayName(_traits->displayName().c_str()) << "\"."<<std::endl; |
|---|
| 662 | _valid = false; |
|---|
| 663 | return; |
|---|
| 664 | } |
|---|
| 665 | |
|---|
| 666 | #ifdef OSG_USE_EGL |
|---|
| 667 | |
|---|
| 668 | _eglDisplay = eglGetDisplay((EGLNativeDisplayType)_display); |
|---|
| 669 | |
|---|
| 670 | EGLint eglMajorVersion, eglMinorVersion; |
|---|
| 671 | if (!eglInitialize(_eglDisplay, &eglMajorVersion, &eglMinorVersion)) |
|---|
| 672 | { |
|---|
| 673 | OSG_NOTICE<<"GraphicsWindowX11::init() - eglInitialize() failed."<<std::endl; |
|---|
| 674 | |
|---|
| 675 | XCloseDisplay( _display ); |
|---|
| 676 | _display = 0; |
|---|
| 677 | _valid = false; |
|---|
| 678 | return; |
|---|
| 679 | } |
|---|
| 680 | |
|---|
| 681 | OSG_NOTICE<<"GraphicsWindowX11::init() - eglInitialize() succeded eglMajorVersion="<<eglMajorVersion<<" iMinorVersion="<<eglMinorVersion<<std::endl; |
|---|
| 682 | |
|---|
| 683 | #else |
|---|
| 684 | |
|---|
| 685 | int errorBase, eventBase; |
|---|
| 686 | if( glXQueryExtension( _display, &errorBase, &eventBase) == False ) |
|---|
| 687 | { |
|---|
| 688 | OSG_NOTICE<<"Error: " << XDisplayName(_traits->displayName().c_str()) <<" has no GLX extension." << std::endl; |
|---|
| 689 | |
|---|
| 690 | XCloseDisplay( _display ); |
|---|
| 691 | _display = 0; |
|---|
| 692 | _valid = false; |
|---|
| 693 | return; |
|---|
| 694 | } |
|---|
| 695 | #endif |
|---|
| 696 | |
|---|
| 697 | |
|---|
| 698 | |
|---|
| 699 | if (!createVisualInfo()) |
|---|
| 700 | { |
|---|
| 701 | _traits->red /= 2; |
|---|
| 702 | _traits->green /= 2; |
|---|
| 703 | _traits->blue /= 2; |
|---|
| 704 | _traits->alpha /= 2; |
|---|
| 705 | _traits->depth /= 2; |
|---|
| 706 | |
|---|
| 707 | OSG_INFO<<"Relaxing traits"<<std::endl; |
|---|
| 708 | |
|---|
| 709 | if (!createVisualInfo()) |
|---|
| 710 | { |
|---|
| 711 | OSG_NOTICE<<"Error: Not able to create requested visual." << std::endl; |
|---|
| 712 | XCloseDisplay( _display ); |
|---|
| 713 | _display = 0; |
|---|
| 714 | _valid = false; |
|---|
| 715 | return; |
|---|
| 716 | } |
|---|
| 717 | } |
|---|
| 718 | |
|---|
| 719 | |
|---|
| 720 | GraphicsHandleX11* graphicsHandleX11 = dynamic_cast<GraphicsHandleX11*>(_traits->sharedContext); |
|---|
| 721 | Context sharedContext = graphicsHandleX11 ? graphicsHandleX11->getContext() : 0; |
|---|
| 722 | |
|---|
| 723 | #ifdef OSG_USE_EGL |
|---|
| 724 | |
|---|
| 725 | _valid = _ownsWindow ? createWindow() : setWindow(windowHandle); |
|---|
| 726 | |
|---|
| 727 | if (!_valid) |
|---|
| 728 | { |
|---|
| 729 | XCloseDisplay( _display ); |
|---|
| 730 | _display = 0; |
|---|
| 731 | return; |
|---|
| 732 | } |
|---|
| 733 | |
|---|
| 734 | OSG_NOTICE<<"GraphicsWindowX11::init() - window created ="<<_valid<<std::endl; |
|---|
| 735 | |
|---|
| 736 | eglBindAPI(EGL_OPENGL_ES_API); |
|---|
| 737 | |
|---|
| 738 | EGLConfig eglConfig = 0; |
|---|
| 739 | |
|---|
| 740 | #if defined(OSG_GLES2_AVAILABLE) |
|---|
| 741 | #define OSG_EGL_OPENGL_TARGET_BIT EGL_OPENGL_ES2_BIT |
|---|
| 742 | #else |
|---|
| 743 | #define OSG_EGL_OPENGL_TARGET_BIT EGL_OPENGL_ES_BIT |
|---|
| 744 | #endif |
|---|
| 745 | |
|---|
| 746 | typedef std::vector<EGLint> Attributes; |
|---|
| 747 | Attributes attributes; |
|---|
| 748 | |
|---|
| 749 | attributes.push_back(EGL_RED_SIZE); attributes.push_back(_traits->red); |
|---|
| 750 | attributes.push_back(EGL_GREEN_SIZE); attributes.push_back(_traits->green); |
|---|
| 751 | attributes.push_back(EGL_BLUE_SIZE); attributes.push_back(_traits->blue); |
|---|
| 752 | attributes.push_back(EGL_DEPTH_SIZE); attributes.push_back(_traits->depth); |
|---|
| 753 | |
|---|
| 754 | if (_traits->alpha) { attributes.push_back(EGL_ALPHA_SIZE); attributes.push_back(_traits->alpha); } |
|---|
| 755 | if (_traits->stencil) { attributes.push_back(EGL_STENCIL_SIZE); attributes.push_back(_traits->stencil); } |
|---|
| 756 | |
|---|
| 757 | if (_traits->sampleBuffers) { attributes.push_back(EGL_SAMPLE_BUFFERS); attributes.push_back(_traits->sampleBuffers); } |
|---|
| 758 | if (_traits->samples) { attributes.push_back(EGL_SAMPLES); attributes.push_back(_traits->samples); } |
|---|
| 759 | |
|---|
| 760 | attributes.push_back(EGL_RENDERABLE_TYPE); attributes.push_back(OSG_EGL_OPENGL_TARGET_BIT); |
|---|
| 761 | |
|---|
| 762 | attributes.push_back(EGL_NONE); |
|---|
| 763 | attributes.push_back(EGL_NONE); |
|---|
| 764 | |
|---|
| 765 | int numConfigs; |
|---|
| 766 | if (!eglChooseConfig(_eglDisplay, &(attributes.front()), &eglConfig, 1, &numConfigs) || (numConfigs != 1)) |
|---|
| 767 | { |
|---|
| 768 | OSG_NOTICE<<"GraphicsWindowX11::init() - eglChooseConfig() failed."<<std::endl; |
|---|
| 769 | XCloseDisplay( _display ); |
|---|
| 770 | _valid = false; |
|---|
| 771 | _display = 0; |
|---|
| 772 | return; |
|---|
| 773 | } |
|---|
| 774 | |
|---|
| 775 | |
|---|
| 776 | _eglSurface = eglCreateWindowSurface(_eglDisplay, eglConfig, (EGLNativeWindowType)_window, NULL); |
|---|
| 777 | if (_eglSurface == EGL_NO_SURFACE) |
|---|
| 778 | { |
|---|
| 779 | OSG_NOTICE<<"GraphicsWindowX11::init() - eglCreateWindowSurface(..) failed."<<std::endl; |
|---|
| 780 | XCloseDisplay( _display ); |
|---|
| 781 | _valid = false; |
|---|
| 782 | _display = 0; |
|---|
| 783 | return; |
|---|
| 784 | } |
|---|
| 785 | |
|---|
| 786 | #if defined(OSG_GLES1_AVAILABLE) |
|---|
| 787 | EGLint* contextAttribs = 0; |
|---|
| 788 | #else |
|---|
| 789 | EGLint contextAttribs[] = { |
|---|
| 790 | EGL_CONTEXT_CLIENT_VERSION, |
|---|
| 791 | 2, |
|---|
| 792 | EGL_NONE |
|---|
| 793 | }; |
|---|
| 794 | #endif |
|---|
| 795 | |
|---|
| 796 | _context = eglCreateContext(_eglDisplay, eglConfig, sharedContext, contextAttribs); |
|---|
| 797 | if (_context == EGL_NO_CONTEXT) |
|---|
| 798 | { |
|---|
| 799 | OSG_NOTICE<<"GraphicsWindowX11::init() - eglCreateContext(..) failed."<<std::endl; |
|---|
| 800 | XCloseDisplay( _display ); |
|---|
| 801 | _valid = false; |
|---|
| 802 | _display = 0; |
|---|
| 803 | return; |
|---|
| 804 | } |
|---|
| 805 | |
|---|
| 806 | _initialized = true; |
|---|
| 807 | |
|---|
| 808 | checkEGLError("after eglCreateContext()"); |
|---|
| 809 | |
|---|
| 810 | #else |
|---|
| 811 | |
|---|
| 812 | _context = glXCreateContext( _display, _visualInfo, sharedContext, True ); |
|---|
| 813 | |
|---|
| 814 | if (!_context) |
|---|
| 815 | { |
|---|
| 816 | OSG_NOTICE<<"Error: Unable to create OpenGL graphics context."<<std::endl; |
|---|
| 817 | XCloseDisplay( _display ); |
|---|
| 818 | _display = 0; |
|---|
| 819 | _valid = false; |
|---|
| 820 | return; |
|---|
| 821 | } |
|---|
| 822 | |
|---|
| 823 | _initialized = _ownsWindow ? createWindow() : setWindow(windowHandle); |
|---|
| 824 | _valid = _initialized; |
|---|
| 825 | |
|---|
| 826 | #endif |
|---|
| 827 | |
|---|
| 828 | if (_valid == false) |
|---|
| 829 | { |
|---|
| 830 | if (_display) |
|---|
| 831 | { |
|---|
| 832 | XCloseDisplay( _display ); |
|---|
| 833 | _display = 0; |
|---|
| 834 | } |
|---|
| 835 | |
|---|
| 836 | if (_eventDisplay) |
|---|
| 837 | { |
|---|
| 838 | XCloseDisplay( _eventDisplay ); |
|---|
| 839 | _eventDisplay = 0; |
|---|
| 840 | } |
|---|
| 841 | } |
|---|
| 842 | |
|---|
| 843 | |
|---|
| 844 | |
|---|
| 845 | } |
|---|
| 846 | |
|---|
| 847 | bool GraphicsWindowX11::createWindow() |
|---|
| 848 | { |
|---|
| 849 | unsigned int screen = _traits->screenNum; |
|---|
| 850 | |
|---|
| 851 | _eventDisplay = XOpenDisplay(_traits->displayName().c_str()); |
|---|
| 852 | |
|---|
| 853 | _parent = RootWindow( _display, screen ); |
|---|
| 854 | |
|---|
| 855 | XWindowAttributes watt; |
|---|
| 856 | XGetWindowAttributes( _display, _parent, &watt ); |
|---|
| 857 | |
|---|
| 858 | |
|---|
| 859 | XSetWindowAttributes swatt; |
|---|
| 860 | swatt.colormap = XCreateColormap( _display, _parent, _visualInfo->visual, AllocNone); |
|---|
| 861 | |
|---|
| 862 | swatt.background_pixel = 0; |
|---|
| 863 | swatt.border_pixel = 0; |
|---|
| 864 | swatt.event_mask = 0; |
|---|
| 865 | unsigned long mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap; |
|---|
| 866 | |
|---|
| 867 | if (_traits->overrideRedirect) |
|---|
| 868 | { |
|---|
| 869 | swatt.override_redirect = true; |
|---|
| 870 | mask |= CWOverrideRedirect; |
|---|
| 871 | |
|---|
| 872 | OSG_INFO<<"Setting override redirect"<<std::endl; |
|---|
| 873 | } |
|---|
| 874 | |
|---|
| 875 | |
|---|
| 876 | osg::GraphicsContext::WindowingSystemInterface *wsi = osg::GraphicsContext::getWindowingSystemInterface(); |
|---|
| 877 | if (wsi == NULL) { |
|---|
| 878 | OSG_NOTICE << "Error, no WindowSystemInterface available, cannot toggle window fullscreen." << std::endl; |
|---|
| 879 | return false; |
|---|
| 880 | } |
|---|
| 881 | |
|---|
| 882 | int x = _traits->x; |
|---|
| 883 | int y = _traits->y; |
|---|
| 884 | int width = _traits->width; |
|---|
| 885 | int height = _traits->height; |
|---|
| 886 | |
|---|
| 887 | |
|---|
| 888 | unsigned int screenWidth; |
|---|
| 889 | unsigned int screenHeight; |
|---|
| 890 | wsi->getScreenResolution(*_traits, screenWidth, screenHeight); |
|---|
| 891 | |
|---|
| 892 | bool doFullSceenWorkAround = false; |
|---|
| 893 | bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight && !_traits->windowDecoration; |
|---|
| 894 | if (isFullScreen && !_traits->overrideRedirect) |
|---|
| 895 | { |
|---|
| 896 | |
|---|
| 897 | |
|---|
| 898 | |
|---|
| 899 | |
|---|
| 900 | Atom netWMStateAtom = XInternAtom(_display, "_NET_WM_STATE", True); |
|---|
| 901 | Atom netWMStateFullscreenAtom = XInternAtom(_display, "_NET_WM_STATE_FULLSCREEN", True); |
|---|
| 902 | |
|---|
| 903 | |
|---|
| 904 | if (netWMStateAtom != None && netWMStateFullscreenAtom != None) |
|---|
| 905 | { |
|---|
| 906 | |
|---|
| 907 | |
|---|
| 908 | |
|---|
| 909 | |
|---|
| 910 | x = width/4; |
|---|
| 911 | y = height/4; |
|---|
| 912 | width /= 2; |
|---|
| 913 | height /= 2; |
|---|
| 914 | |
|---|
| 915 | doFullSceenWorkAround = true; |
|---|
| 916 | } |
|---|
| 917 | } |
|---|
| 918 | |
|---|
| 919 | _window = XCreateWindow( _display, _parent, |
|---|
| 920 | x, |
|---|
| 921 | y, |
|---|
| 922 | width, height, 0, |
|---|
| 923 | _visualInfo->depth, InputOutput, |
|---|
| 924 | _visualInfo->visual, mask, &swatt ); |
|---|
| 925 | |
|---|
| 926 | if (!_window) |
|---|
| 927 | { |
|---|
| 928 | OSG_NOTICE<<"Error: Unable to create Window."<<std::endl; |
|---|
| 929 | _context = 0; |
|---|
| 930 | return false; |
|---|
| 931 | } |
|---|
| 932 | |
|---|
| 933 | |
|---|
| 934 | |
|---|
| 935 | XClassHint clH; |
|---|
| 936 | clH.res_name = (char *)"OSG"; |
|---|
| 937 | clH.res_class = (char *)"osgViewer"; |
|---|
| 938 | XSetClassHint( _display, _window, &clH); |
|---|
| 939 | |
|---|
| 940 | |
|---|
| 941 | XSizeHints sh; |
|---|
| 942 | sh.flags = 0; |
|---|
| 943 | sh.flags |= USSize; |
|---|
| 944 | sh.flags &= 0x7; |
|---|
| 945 | sh.flags |= USPosition; |
|---|
| 946 | sh.flags &= 0xB; |
|---|
| 947 | sh.x = _traits->x; |
|---|
| 948 | sh.y = _traits->y; |
|---|
| 949 | sh.width = _traits->width; |
|---|
| 950 | sh.height = _traits->height; |
|---|
| 951 | XSetStandardProperties( _display, _window, _traits->windowName.c_str(), _traits->windowName.c_str(), None, 0, 0, &sh); |
|---|
| 952 | |
|---|
| 953 | setWindowDecoration(_traits->windowDecoration); |
|---|
| 954 | |
|---|
| 955 | |
|---|
| 956 | useCursor(_traits->useCursor); |
|---|
| 957 | |
|---|
| 958 | _deleteWindow = XInternAtom (_display, "WM_DELETE_WINDOW", False); |
|---|
| 959 | XSetWMProtocols(_display, _window, &_deleteWindow, 1); |
|---|
| 960 | |
|---|
| 961 | |
|---|
| 962 | XFlush( _display ); |
|---|
| 963 | XSync( _display, 0 ); |
|---|
| 964 | |
|---|
| 965 | |
|---|
| 966 | XGetWindowAttributes( _display, _window, &watt ); |
|---|
| 967 | |
|---|
| 968 | if (_traits->x != watt.x || _traits->y != watt.y |
|---|
| 969 | ||_traits->width != watt.width || _traits->height != watt.height) |
|---|
| 970 | { |
|---|
| 971 | |
|---|
| 972 | if (doFullSceenWorkAround) |
|---|
| 973 | { |
|---|
| 974 | OSG_INFO<<"Full Screen failed, resizing manually"<<std::endl; |
|---|
| 975 | XMoveResizeWindow(_display, _window, _traits->x, _traits->y, _traits->width, _traits->height); |
|---|
| 976 | |
|---|
| 977 | XFlush(_display); |
|---|
| 978 | XSync(_display, 0); |
|---|
| 979 | |
|---|
| 980 | XGetWindowAttributes( _display, _window, &watt ); |
|---|
| 981 | } |
|---|
| 982 | |
|---|
| 983 | resized( watt.x, watt.y, watt.width, watt.height ); |
|---|
| 984 | } |
|---|
| 985 | |
|---|
| 986 | |
|---|
| 987 | |
|---|
| 988 | |
|---|
| 989 | XSelectInput( _eventDisplay, _window, ExposureMask | StructureNotifyMask | |
|---|
| 990 | KeyPressMask | KeyReleaseMask | |
|---|
| 991 | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | |
|---|
| 992 | KeymapStateMask | FocusChangeMask | EnterWindowMask ); |
|---|
| 993 | |
|---|
| 994 | XFlush( _eventDisplay ); |
|---|
| 995 | XSync( _eventDisplay, 0 ); |
|---|
| 996 | rescanModifierMapping(); |
|---|
| 997 | |
|---|
| 998 | return true; |
|---|
| 999 | } |
|---|
| 1000 | |
|---|
| 1001 | bool GraphicsWindowX11::setWindow(Window window) |
|---|
| 1002 | { |
|---|
| 1003 | if (_initialized) |
|---|
| 1004 | { |
|---|
| 1005 | OSG_NOTICE << "GraphicsWindowX11::setWindow() - Window already created; it cannot be changed"; |
|---|
| 1006 | return false; |
|---|
| 1007 | } |
|---|
| 1008 | |
|---|
| 1009 | if (window==0) |
|---|
| 1010 | { |
|---|
| 1011 | OSG_NOTICE << "GraphicsWindowX11::setWindow() - Invalid window handle passed "; |
|---|
| 1012 | return false; |
|---|
| 1013 | } |
|---|
| 1014 | |
|---|
| 1015 | _window = window; |
|---|
| 1016 | if (_window==0) |
|---|
| 1017 | { |
|---|
| 1018 | OSG_NOTICE << "GraphicsWindowX11::setWindow() - Unable to retrieve native window handle"; |
|---|
| 1019 | return false; |
|---|
| 1020 | } |
|---|
| 1021 | |
|---|
| 1022 | XWindowAttributes watt; |
|---|
| 1023 | XGetWindowAttributes( _display, _window, &watt ); |
|---|
| 1024 | _traits->x = watt.x; |
|---|
| 1025 | _traits->y = watt.y; |
|---|
| 1026 | _traits->width = watt.width; |
|---|
| 1027 | _traits->height = watt.height; |
|---|
| 1028 | |
|---|
| 1029 | _parent = DefaultRootWindow( _display ); |
|---|
| 1030 | |
|---|
| 1031 | |
|---|
| 1032 | _traits->windowDecoration = false; |
|---|
| 1033 | |
|---|
| 1034 | if (_traits->windowName.size()) setWindowName(_traits->windowName); |
|---|
| 1035 | |
|---|
| 1036 | _eventDisplay = XOpenDisplay(_traits->displayName().c_str()); |
|---|
| 1037 | |
|---|
| 1038 | XFlush( _eventDisplay ); |
|---|
| 1039 | XSync( _eventDisplay, 0 ); |
|---|
| 1040 | |
|---|
| 1041 | return true; |
|---|
| 1042 | } |
|---|
| 1043 | |
|---|
| 1044 | bool GraphicsWindowX11::realizeImplementation() |
|---|
| 1045 | { |
|---|
| 1046 | if (_realized) |
|---|
| 1047 | { |
|---|
| 1048 | OSG_NOTICE<<"GraphicsWindowX11::realizeImplementation() Already realized"<<std::endl; |
|---|
| 1049 | return true; |
|---|
| 1050 | } |
|---|
| 1051 | |
|---|
| 1052 | if (!_initialized) init(); |
|---|
| 1053 | |
|---|
| 1054 | if (!_initialized) return false; |
|---|
| 1055 | |
|---|
| 1056 | XMapWindow( _display, _window ); |
|---|
| 1057 | |
|---|
| 1058 | |
|---|
| 1059 | |
|---|
| 1060 | |
|---|
| 1061 | _realized = true; |
|---|
| 1062 | |
|---|
| 1063 | return true; |
|---|
| 1064 | } |
|---|
| 1065 | |
|---|
| 1066 | bool GraphicsWindowX11::makeCurrentImplementation() |
|---|
| 1067 | { |
|---|
| 1068 | if (!_realized) |
|---|
| 1069 | { |
|---|
| 1070 | OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<<std::endl; |
|---|
| 1071 | return false; |
|---|
| 1072 | } |
|---|
| 1073 | |
|---|
| 1074 | #ifdef OSG_USE_EGL |
|---|
| 1075 | bool result = eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _context)==EGL_TRUE; |
|---|
| 1076 | checkEGLError("after eglMakeCurrent()"); |
|---|
| 1077 | return result; |
|---|
| 1078 | #else |
|---|
| 1079 | return glXMakeCurrent( _display, _window, _context )==True; |
|---|
| 1080 | #endif |
|---|
| 1081 | } |
|---|
| 1082 | |
|---|
| 1083 | bool GraphicsWindowX11::releaseContextImplementation() |
|---|
| 1084 | { |
|---|
| 1085 | if (!_realized) |
|---|
| 1086 | { |
|---|
| 1087 | OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do release context."<<std::endl; |
|---|
| 1088 | return false; |
|---|
| 1089 | } |
|---|
| 1090 | |
|---|
| 1091 | #ifdef OSG_USE_EGL |
|---|
| 1092 | bool result = eglMakeCurrent( _eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT )==EGL_TRUE; |
|---|
| 1093 | checkEGLError("after eglMakeCurrent() release"); |
|---|
| 1094 | return result; |
|---|
| 1095 | #else |
|---|
| 1096 | return glXMakeCurrent( _display, None, NULL )==True; |
|---|
| 1097 | #endif |
|---|
| 1098 | } |
|---|
| 1099 | |
|---|
| 1100 | |
|---|
| 1101 | void GraphicsWindowX11::closeImplementation() |
|---|
| 1102 | { |
|---|
| 1103 | |
|---|
| 1104 | |
|---|
| 1105 | if (_eventDisplay) |
|---|
| 1106 | { |
|---|
| 1107 | XCloseDisplay( _eventDisplay ); |
|---|
| 1108 | _eventDisplay = 0; |
|---|
| 1109 | } |
|---|
| 1110 | |
|---|
| 1111 | if (_display) |
|---|
| 1112 | { |
|---|
| 1113 | if (_context) |
|---|
| 1114 | { |
|---|
| 1115 | #ifdef OSG_USE_EGL |
|---|
| 1116 | eglDestroyContext( _eglDisplay, _context ); |
|---|
| 1117 | #else |
|---|
| 1118 | glXDestroyContext( _display, _context ); |
|---|
| 1119 | #endif |
|---|
| 1120 | } |
|---|
| 1121 | |
|---|
| 1122 | if (_window && _ownsWindow) |
|---|
| 1123 | { |
|---|
| 1124 | XDestroyWindow(_display, _window); |
|---|
| 1125 | } |
|---|
| 1126 | |
|---|
| 1127 | XFlush( _display ); |
|---|
| 1128 | XSync( _display,0 ); |
|---|
| 1129 | } |
|---|
| 1130 | |
|---|
| 1131 | _window = 0; |
|---|
| 1132 | _parent = 0; |
|---|
| 1133 | _context = 0; |
|---|
| 1134 | |
|---|
| 1135 | if (_visualInfo) |
|---|
| 1136 | { |
|---|
| 1137 | #ifdef OSG_USE_EGL |
|---|
| 1138 | delete _visualInfo; |
|---|
| 1139 | #else |
|---|
| 1140 | XFree(_visualInfo); |
|---|
| 1141 | #endif |
|---|
| 1142 | _visualInfo = 0; |
|---|
| 1143 | } |
|---|
| 1144 | |
|---|
| 1145 | |
|---|
| 1146 | if (_display) |
|---|
| 1147 | { |
|---|
| 1148 | XCloseDisplay( _display ); |
|---|
| 1149 | _display = 0; |
|---|
| 1150 | } |
|---|
| 1151 | |
|---|
| 1152 | _initialized = false; |
|---|
| 1153 | _realized = false; |
|---|
| 1154 | _valid = false; |
|---|
| 1155 | } |
|---|
| 1156 | |
|---|
| 1157 | void GraphicsWindowX11::swapBuffersImplementation() |
|---|
| 1158 | { |
|---|
| 1159 | if (!_realized) return; |
|---|
| 1160 | |
|---|
| 1161 | |
|---|
| 1162 | |
|---|
| 1163 | #ifdef OSG_USE_EGL |
|---|
| 1164 | eglSwapBuffers( _eglDisplay, _eglSurface ); |
|---|
| 1165 | checkEGLError("after eglSwapBuffers()"); |
|---|
| 1166 | #else |
|---|
| 1167 | #if 0 |
|---|
| 1168 | if (_traits.valid() && _traits->vsync) { |
|---|
| 1169 | |
|---|
| 1170 | unsigned int counter; |
|---|
| 1171 | glXGetVideoSyncSGI(&counter); |
|---|
| 1172 | glXWaitVideoSyncSGI(1, 0, &counter); |
|---|
| 1173 | } |
|---|
| 1174 | #endif |
|---|
| 1175 | glXSwapBuffers( _display, _window ); |
|---|
| 1176 | #endif |
|---|
| 1177 | |
|---|
| 1178 | |
|---|
| 1179 | while( XPending(_display) ) |
|---|
| 1180 | { |
|---|
| 1181 | XEvent ev; |
|---|
| 1182 | XNextEvent( _display, &ev ); |
|---|
| 1183 | |
|---|
| 1184 | switch( ev.type ) |
|---|
| 1185 | { |
|---|
| 1186 | case ClientMessage: |
|---|
| 1187 | { |
|---|
| 1188 | if (static_cast<Atom>(ev.xclient.data.l[0]) == _deleteWindow) |
|---|
| 1189 | { |
|---|
| 1190 | OSG_INFO<<"DeleteWindow event received"<<std::endl; |
|---|
| 1191 | getEventQueue()->closeWindow(); |
|---|
| 1192 | } |
|---|
| 1193 | } |
|---|
| 1194 | } |
|---|
| 1195 | } |
|---|
| 1196 | } |
|---|
| 1197 | |
|---|
| 1198 | void GraphicsWindowX11::checkEvents() |
|---|
| 1199 | { |
|---|
| 1200 | if (!_realized) return; |
|---|
| 1201 | |
|---|
| 1202 | Display* display = _eventDisplay; |
|---|
| 1203 | |
|---|
| 1204 | double baseTime = _timeOfLastCheckEvents; |
|---|
| 1205 | double eventTime = baseTime; |
|---|
| 1206 | double resizeTime = eventTime; |
|---|
| 1207 | _timeOfLastCheckEvents = getEventQueue()->getTime(); |
|---|
| 1208 | if (baseTime>_timeOfLastCheckEvents) baseTime = _timeOfLastCheckEvents; |
|---|
| 1209 | |
|---|
| 1210 | |
|---|
| 1211 | |
|---|
| 1212 | |
|---|
| 1213 | int windowX = _traits->x; |
|---|
| 1214 | int windowY = _traits->y; |
|---|
| 1215 | int windowWidth = _traits->width; |
|---|
| 1216 | int windowHeight = _traits->height; |
|---|
| 1217 | |
|---|
| 1218 | Time firstEventTime = 0; |
|---|
| 1219 | |
|---|
| 1220 | |
|---|
| 1221 | while( XPending(display) ) |
|---|
| 1222 | { |
|---|
| 1223 | XEvent ev; |
|---|
| 1224 | XNextEvent( display, &ev ); |
|---|
| 1225 | |
|---|
| 1226 | switch( ev.type ) |
|---|
| 1227 | { |
|---|
| 1228 | case ClientMessage: |
|---|
| 1229 | { |
|---|
| 1230 | OSG_NOTICE<<"ClientMessage event received"<<std::endl; |
|---|
| 1231 | if (static_cast<Atom>(ev.xclient.data.l[0]) == _deleteWindow) |
|---|
| 1232 | { |
|---|
| 1233 | OSG_NOTICE<<"DeleteWindow event received"<<std::endl; |
|---|
| 1234 | |
|---|
| 1235 | getEventQueue()->closeWindow(eventTime); |
|---|
| 1236 | } |
|---|
| 1237 | break; |
|---|
| 1238 | } |
|---|
| 1239 | case Expose : |
|---|
| 1240 | OSG_INFO<<"Expose x="<<ev.xexpose.x<<" y="<<ev.xexpose.y<<" width="<<ev.xexpose.width<<", height="<<ev.xexpose.height<<std::endl; |
|---|
| 1241 | requestRedraw(); |
|---|
| 1242 | break; |
|---|
| 1243 | |
|---|
| 1244 | case GravityNotify : |
|---|
| 1245 | OSG_INFO<<"GravityNotify event received"<<std::endl; |
|---|
| 1246 | break; |
|---|
| 1247 | |
|---|
| 1248 | case ReparentNotify: |
|---|
| 1249 | OSG_INFO<<"ReparentNotify event received"<<std::endl; |
|---|
| 1250 | break; |
|---|
| 1251 | |
|---|
| 1252 | case DestroyNotify : |
|---|
| 1253 | OSG_NOTICE<<"DestroyNotify event received"<<std::endl; |
|---|
| 1254 | _realized = false; |
|---|
| 1255 | _valid = false; |
|---|
| 1256 | break; |
|---|
| 1257 | |
|---|
| 1258 | case ConfigureNotify : |
|---|
| 1259 | { |
|---|
| 1260 | OSG_INFO<<"ConfigureNotify x="<<ev.xconfigure.x<<" y="<<ev.xconfigure.y<<" width="<<ev.xconfigure.width<<", height="<<ev.xconfigure.height<<std::endl; |
|---|
| 1261 | |
|---|
| 1262 | if (windowX != ev.xconfigure.x || |
|---|
| 1263 | windowY != ev.xconfigure.y || |
|---|
| 1264 | windowWidth != ev.xconfigure.width || |
|---|
| 1265 | windowHeight != ev.xconfigure.height) |
|---|
| 1266 | { |
|---|
| 1267 | resizeTime = eventTime; |
|---|
| 1268 | |
|---|
| 1269 | windowX = ev.xconfigure.x; |
|---|
| 1270 | windowY = ev.xconfigure.y; |
|---|
| 1271 | windowWidth = ev.xconfigure.width; |
|---|
| 1272 | windowHeight = ev.xconfigure.height; |
|---|
| 1273 | } |
|---|
| 1274 | |
|---|
| 1275 | break; |
|---|
| 1276 | } |
|---|
| 1277 | |
|---|
| 1278 | case MapNotify : |
|---|
| 1279 | { |
|---|
| 1280 | OSG_INFO<<"MapNotify"<<std::endl; |
|---|
| 1281 | XWindowAttributes watt; |
|---|
| 1282 | do |
|---|
| 1283 | XGetWindowAttributes(display, _window, &watt ); |
|---|
| 1284 | while( watt.map_state != IsViewable ); |
|---|
| 1285 | |
|---|
| 1286 | OSG_INFO<<"MapNotify x="<<watt.x<<" y="<<watt.y<<" width="<<watt.width<<", height="<<watt.height<<std::endl; |
|---|
| 1287 | |
|---|
| 1288 | if (windowWidth != watt.width || windowHeight != watt.height) |
|---|
| 1289 | { |
|---|
| 1290 | resizeTime = eventTime; |
|---|
| 1291 | |
|---|
| 1292 | windowWidth = watt.width; |
|---|
| 1293 | windowHeight = watt.height; |
|---|
| 1294 | } |
|---|
| 1295 | |
|---|
| 1296 | break; |
|---|
| 1297 | } |
|---|
| 1298 | |
|---|
| 1299 | case FocusIn : |
|---|
| 1300 | OSG_INFO<<"FocusIn event received"<<std::endl; |
|---|
| 1301 | flushKeyEvents(); |
|---|
| 1302 | break; |
|---|
| 1303 | |
|---|
| 1304 | case UnmapNotify : |
|---|
| 1305 | case FocusOut : |
|---|
| 1306 | { |
|---|
| 1307 | OSG_INFO<<"FocusOut/UnmapNotify event received"<<std::endl; |
|---|
| 1308 | if (ev.type == FocusOut && ev.xfocus.mode != NotifyNormal) break; |
|---|
| 1309 | |
|---|
| 1310 | char modMap[32]; |
|---|
| 1311 | getModifierMap(modMap); |
|---|
| 1312 | |
|---|
| 1313 | |
|---|
| 1314 | for (unsigned int key = 8; key < 256; key++) |
|---|
| 1315 | { |
|---|
| 1316 | bool isModifier = keyMapGetKey(modMap, key); |
|---|
| 1317 | if (!isModifier) forceKey(key, eventTime, false); |
|---|
| 1318 | } |
|---|
| 1319 | |
|---|
| 1320 | |
|---|
| 1321 | for (unsigned int key = 8; key < 256; key++) |
|---|
| 1322 | { |
|---|
| 1323 | bool isModifier = keyMapGetKey(modMap, key); |
|---|
| 1324 | if (isModifier) forceKey(key, eventTime, false); |
|---|
| 1325 | } |
|---|
| 1326 | break; |
|---|
| 1327 | } |
|---|
| 1328 | |
|---|
| 1329 | case EnterNotify : |
|---|
| 1330 | OSG_INFO<<"EnterNotify event received"<<std::endl; |
|---|
| 1331 | _modifierState = ev.xcrossing.state; |
|---|
| 1332 | syncLocks(); |
|---|
| 1333 | break; |
|---|
| 1334 | |
|---|
| 1335 | case KeymapNotify : |
|---|
| 1336 | { |
|---|
| 1337 | OSG_INFO<<"KeymapNotify event received"<<std::endl; |
|---|
| 1338 | |
|---|
| 1339 | |
|---|
| 1340 | |
|---|
| 1341 | if (_lastEventType != FocusIn) break; |
|---|
| 1342 | |
|---|
| 1343 | char modMap[32]; |
|---|
| 1344 | getModifierMap(modMap); |
|---|
| 1345 | syncLocks(); |
|---|
| 1346 | |
|---|
| 1347 | char keyMap[32]; |
|---|
| 1348 | XQueryKeymap(_eventDisplay, keyMap); |
|---|
| 1349 | |
|---|
| 1350 | |
|---|
| 1351 | for (unsigned int key = 8; key < 256; key++) |
|---|
| 1352 | { |
|---|
| 1353 | bool isModifier = keyMapGetKey(modMap, key); |
|---|
| 1354 | if (isModifier) continue; |
|---|
| 1355 | bool isPressed = keyMapGetKey(keyMap, key); |
|---|
| 1356 | if (!isPressed) forceKey(key, eventTime, false); |
|---|
| 1357 | } |
|---|
| 1358 | |
|---|
| 1359 | |
|---|
| 1360 | for (unsigned int key = 8; key < 256; key++) |
|---|
| 1361 | { |
|---|
| 1362 | bool isModifier = keyMapGetKey(modMap, key); |
|---|
| 1363 | if (!isModifier) continue; |
|---|
| 1364 | bool isPressed = keyMapGetKey(keyMap, key); |
|---|
| 1365 | forceKey(key, eventTime, isPressed); |
|---|
| 1366 | } |
|---|
| 1367 | |
|---|
| 1368 | |
|---|
| 1369 | for (unsigned int key = 8; key < 256; key++) |
|---|
| 1370 | { |
|---|
| 1371 | bool isModifier = keyMapGetKey(modMap, key); |
|---|
| 1372 | if (isModifier) continue; |
|---|
| 1373 | bool isPressed = keyMapGetKey(keyMap, key); |
|---|
| 1374 | if (isPressed) forceKey(key, eventTime, true); |
|---|
| 1375 | } |
|---|
| 1376 | break; |
|---|
| 1377 | } |
|---|
| 1378 | |
|---|
| 1379 | case MappingNotify : |
|---|
| 1380 | OSG_INFO<<"MappingNotify event received"<<std::endl; |
|---|
| 1381 | if (ev.xmapping.request == MappingModifier) rescanModifierMapping(); |
|---|
| 1382 | break; |
|---|
| 1383 | |
|---|
| 1384 | case MotionNotify : |
|---|
| 1385 | { |
|---|
| 1386 | if (firstEventTime==0) firstEventTime = ev.xmotion.time; |
|---|
| 1387 | Time relativeTime = ev.xmotion.time - firstEventTime; |
|---|
| 1388 | eventTime = baseTime + static_cast<double>(relativeTime)*0.001; |
|---|
| 1389 | |
|---|
| 1390 | int wx, wy; |
|---|
| 1391 | Window win = 0L; |
|---|
| 1392 | if( ev.xmotion.same_screen ) |
|---|
| 1393 | { |
|---|
| 1394 | wx = ev.xmotion.x; |
|---|
| 1395 | wy = ev.xmotion.y; |
|---|
| 1396 | } |
|---|
| 1397 | else |
|---|
| 1398 | { |
|---|
| 1399 | |
|---|
| 1400 | |
|---|
| 1401 | |
|---|
| 1402 | |
|---|
| 1403 | Window root; |
|---|
| 1404 | int rx, ry; |
|---|
| 1405 | unsigned int buttons; |
|---|
| 1406 | |
|---|
| 1407 | int screenOrigin_x = 0; |
|---|
| 1408 | int screenOrigin_y = 0; |
|---|
| 1409 | int i; |
|---|
| 1410 | for(i= 0; i < ScreenCount(display); i++ ) |
|---|
| 1411 | { |
|---|
| 1412 | if( XQueryPointer( display, RootWindow(display, i), |
|---|
| 1413 | &root, &win, &rx, &ry, &wx, &wy, &buttons) ) |
|---|
| 1414 | { |
|---|
| 1415 | break; |
|---|
| 1416 | } |
|---|
| 1417 | |
|---|
| 1418 | screenOrigin_x += DisplayWidth(display, i); |
|---|
| 1419 | } |
|---|
| 1420 | |
|---|
| 1421 | for(i= 0; i < static_cast<int>(_traits->screenNum); i++ ) |
|---|
| 1422 | { |
|---|
| 1423 | screenOrigin_x -= DisplayWidth(display, i); |
|---|
| 1424 | } |
|---|
| 1425 | |
|---|
| 1426 | int dest_x_return, dest_y_return; |
|---|
| 1427 | Window child_return; |
|---|
| 1428 | XTranslateCoordinates(display, _window, _parent, 0, 0, &dest_x_return, &dest_y_return, &child_return); |
|---|
| 1429 | |
|---|
| 1430 | wx += (screenOrigin_x - dest_x_return); |
|---|
| 1431 | wy += (screenOrigin_y - dest_y_return); |
|---|
| 1432 | } |
|---|
| 1433 | |
|---|
| 1434 | |
|---|
| 1435 | float mx = wx; |
|---|
| 1436 | float my = wy; |
|---|
| 1437 | transformMouseXY(mx, my); |
|---|
| 1438 | getEventQueue()->mouseMotion(mx, my, eventTime); |
|---|
| 1439 | |
|---|
| 1440 | |
|---|
| 1441 | |
|---|
| 1442 | break; |
|---|
| 1443 | } |
|---|
| 1444 | |
|---|
| 1445 | case ButtonPress : |
|---|
| 1446 | { |
|---|
| 1447 | if (firstEventTime==0) firstEventTime = ev.xmotion.time; |
|---|
| 1448 | Time relativeTime = ev.xmotion.time - firstEventTime; |
|---|
| 1449 | eventTime = baseTime + static_cast<double>(relativeTime)*0.001; |
|---|
| 1450 | |
|---|
| 1451 | if( ev.xbutton.button == Button4 ) |
|---|
| 1452 | { |
|---|
| 1453 | getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_UP, eventTime); |
|---|
| 1454 | } |
|---|
| 1455 | else if( ev.xbutton.button == Button5) |
|---|
| 1456 | { |
|---|
| 1457 | getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_DOWN, eventTime); |
|---|
| 1458 | } |
|---|
| 1459 | else |
|---|
| 1460 | { |
|---|
| 1461 | float mx = ev.xbutton.x; |
|---|
| 1462 | float my = ev.xmotion.y; |
|---|
| 1463 | transformMouseXY(mx, my); |
|---|
| 1464 | getEventQueue()->mouseButtonPress(mx, my, ev.xbutton.button, eventTime); |
|---|
| 1465 | } |
|---|
| 1466 | break; |
|---|
| 1467 | } |
|---|
| 1468 | |
|---|
| 1469 | case ButtonRelease : |
|---|
| 1470 | { |
|---|
| 1471 | if (firstEventTime==0) firstEventTime = ev.xmotion.time; |
|---|
| 1472 | Time relativeTime = ev.xmotion.time - firstEventTime; |
|---|
| 1473 | eventTime = baseTime + static_cast<double>(relativeTime)*0.001; |
|---|
| 1474 | |
|---|
| 1475 | if( ev.xbutton.button == Button4 ) |
|---|
| 1476 | { |
|---|
| 1477 | getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_UP, eventTime); |
|---|
| 1478 | } |
|---|
| 1479 | else if( ev.xbutton.button == Button5) |
|---|
| 1480 | { |
|---|
| 1481 | getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_DOWN, eventTime); |
|---|
| 1482 | } |
|---|
| 1483 | else |
|---|
| 1484 | { |
|---|
| 1485 | float mx = ev.xbutton.x; |
|---|
| 1486 | float my = ev.xmotion.y; |
|---|
| 1487 | transformMouseXY(mx, my); |
|---|
| 1488 | getEventQueue()->mouseButtonRelease(mx, my, ev.xbutton.button, eventTime); |
|---|
| 1489 | } |
|---|
| 1490 | break; |
|---|
| 1491 | } |
|---|
| 1492 | |
|---|
| 1493 | case KeyPress: |
|---|
| 1494 | { |
|---|
| 1495 | if (firstEventTime==0) firstEventTime = ev.xmotion.time; |
|---|
| 1496 | Time relativeTime = ev.xmotion.time - firstEventTime; |
|---|
| 1497 | eventTime = baseTime + static_cast<double>(relativeTime)*0.001; |
|---|
| 1498 | |
|---|
| 1499 | _modifierState = ev.xkey.state; |
|---|
| 1500 | keyMapSetKey(_keyMap, ev.xkey.keycode); |
|---|
| 1501 | int keySymbol = 0; |
|---|
| 1502 | int unmodifiedKeySymbol = 0; |
|---|
| 1503 | adaptKey(ev.xkey, keySymbol, unmodifiedKeySymbol); |
|---|
| 1504 | |
|---|
| 1505 | getEventQueue()->keyPress(keySymbol, eventTime, unmodifiedKeySymbol); |
|---|
| 1506 | break; |
|---|
| 1507 | } |
|---|
| 1508 | |
|---|
| 1509 | case KeyRelease: |
|---|
| 1510 | { |
|---|
| 1511 | if (firstEventTime==0) firstEventTime = ev.xmotion.time; |
|---|
| 1512 | Time relativeTime = ev.xmotion.time - firstEventTime; |
|---|
| 1513 | eventTime = baseTime + static_cast<double>(relativeTime)*0.001; |
|---|
| 1514 | #if 1 |
|---|
| 1515 | |
|---|
| 1516 | |
|---|
| 1517 | |
|---|
| 1518 | |
|---|
| 1519 | XEvent nextev; |
|---|
| 1520 | if (XPending(display)) |
|---|
| 1521 | { |
|---|
| 1522 | XPeekEvent(display, &nextev); |
|---|
| 1523 | if ((nextev.type == KeyPress) |
|---|
| 1524 | && (nextev.xkey.keycode == ev.xkey.keycode) |
|---|
| 1525 | && (nextev.xmotion.time - ev.xmotion.time < 2)) |
|---|
| 1526 | { |
|---|
| 1527 | break; |
|---|
| 1528 | } |
|---|
| 1529 | } |
|---|
| 1530 | #endif |
|---|
| 1531 | _modifierState = ev.xkey.state; |
|---|
| 1532 | keyMapClearKey(_keyMap, ev.xkey.keycode); |
|---|
| 1533 | int keySymbol = 0; |
|---|
| 1534 | int unmodifiedKeySymbol = 0; |
|---|
| 1535 | adaptKey(ev.xkey, keySymbol, unmodifiedKeySymbol); |
|---|
| 1536 | |
|---|
| 1537 | getEventQueue()->keyRelease(keySymbol, eventTime, unmodifiedKeySymbol); |
|---|
| 1538 | break; |
|---|
| 1539 | } |
|---|
| 1540 | |
|---|
| 1541 | default: |
|---|
| 1542 | OSG_NOTICE<<"Other event "<<ev.type<<std::endl; |
|---|
| 1543 | break; |
|---|
| 1544 | |
|---|
| 1545 | } |
|---|
| 1546 | _lastEventType = ev.type; |
|---|
| 1547 | } |
|---|
| 1548 | |
|---|
| 1549 | |
|---|
| 1550 | if (windowX != _traits->x || |
|---|
| 1551 | windowY != _traits->y || |
|---|
| 1552 | windowWidth != _traits->width || |
|---|
| 1553 | windowHeight != _traits->height) |
|---|
| 1554 | { |
|---|
| 1555 | resized(windowX, windowY, windowWidth, windowHeight); |
|---|
| 1556 | getEventQueue()->windowResize(windowX, windowY, windowWidth, windowHeight, resizeTime); |
|---|
| 1557 | |
|---|
| 1558 | |
|---|
| 1559 | if (windowWidth != _traits->width || |
|---|
| 1560 | windowHeight != _traits->height) |
|---|
| 1561 | { |
|---|
| 1562 | requestRedraw(); |
|---|
| 1563 | } |
|---|
| 1564 | } |
|---|
| 1565 | } |
|---|
| 1566 | |
|---|
| 1567 | void GraphicsWindowX11::grabFocus() |
|---|
| 1568 | { |
|---|
| 1569 | Display* display = getDisplayToUse(); |
|---|
| 1570 | |
|---|
| 1571 | XSetInputFocus( display, _window, RevertToNone, CurrentTime ); |
|---|
| 1572 | XFlush(display); |
|---|
| 1573 | XSync(display,0); |
|---|
| 1574 | } |
|---|
| 1575 | |
|---|
| 1576 | void GraphicsWindowX11::grabFocusIfPointerInWindow() |
|---|
| 1577 | { |
|---|
| 1578 | Window win, root; |
|---|
| 1579 | int wx, wy, rx, ry; |
|---|
| 1580 | unsigned int buttons; |
|---|
| 1581 | |
|---|
| 1582 | Display* display = getDisplayToUse(); |
|---|
| 1583 | |
|---|
| 1584 | if( XQueryPointer( display, _window, |
|---|
| 1585 | &root, &win, &rx, &ry, &wx, &wy, &buttons)) |
|---|
| 1586 | { |
|---|
| 1587 | #if 0 |
|---|
| 1588 | if (wx>=0 && wx<_traits->width && |
|---|
| 1589 | wy>=0 && wy<_traits->height) |
|---|
| 1590 | { |
|---|
| 1591 | grabFocus(); |
|---|
| 1592 | } |
|---|
| 1593 | #else |
|---|
| 1594 | grabFocus(); |
|---|
| 1595 | #endif |
|---|
| 1596 | } |
|---|
| 1597 | } |
|---|
| 1598 | |
|---|
| 1599 | void GraphicsWindowX11::transformMouseXY(float& x, float& y) |
|---|
| 1600 | { |
|---|
| 1601 | if (getEventQueue()->getUseFixedMouseInputRange()) |
|---|
| 1602 | { |
|---|
| 1603 | osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState(); |
|---|
| 1604 | x = eventState->getXmin() + (eventState->getXmax()-eventState->getXmin())*x/float(_traits->width); |
|---|
| 1605 | y = eventState->getYmin() + (eventState->getYmax()-eventState->getYmin())*y/float(_traits->height); |
|---|
| 1606 | } |
|---|
| 1607 | } |
|---|
| 1608 | |
|---|
| 1609 | void GraphicsWindowX11::adaptKey(XKeyEvent& keyevent, int& keySymbol, int& unmodifiedKeySymbol) |
|---|
| 1610 | { |
|---|
| 1611 | unsigned char buffer_return[32]; |
|---|
| 1612 | int bytes_buffer = 32; |
|---|
| 1613 | KeySym keysym_return; |
|---|
| 1614 | |
|---|
| 1615 | int numChars = XLookupString(&keyevent, reinterpret_cast<char*>(buffer_return), bytes_buffer, &keysym_return, NULL); |
|---|
| 1616 | keySymbol = keysym_return; |
|---|
| 1617 | if (!remapExtendedX11Key(keySymbol) && (numChars==1)) |
|---|
| 1618 | { |
|---|
| 1619 | keySymbol = buffer_return[0]; |
|---|
| 1620 | } |
|---|
| 1621 | |
|---|
| 1622 | unmodifiedKeySymbol = XKeycodeToKeysym(keyevent.display, keyevent.keycode, 0); |
|---|
| 1623 | } |
|---|
| 1624 | |
|---|
| 1625 | |
|---|
| 1626 | void GraphicsWindowX11::forceKey(int key, double time, bool state) |
|---|
| 1627 | { |
|---|
| 1628 | if (!(state ^ keyMapGetKey(_keyMap, key))) return; |
|---|
| 1629 | |
|---|
| 1630 | XKeyEvent event; |
|---|
| 1631 | event.serial = 0; |
|---|
| 1632 | event.send_event = True; |
|---|
| 1633 | event.display = _eventDisplay; |
|---|
| 1634 | event.window = _window; |
|---|
| 1635 | event.subwindow = 0; |
|---|
| 1636 | event.time = 0; |
|---|
| 1637 | event.x = 0; |
|---|
| 1638 | event.y = 0; |
|---|
| 1639 | event.x_root = 0; |
|---|
| 1640 | event.y_root = 0; |
|---|
| 1641 | event.state = getModifierMask() | (_modifierState & (LockMask | _numLockMask)); |
|---|
| 1642 | event.keycode = key; |
|---|
| 1643 | event.same_screen = True; |
|---|
| 1644 | |
|---|
| 1645 | int keySymbol = 0; |
|---|
| 1646 | int unmodifiedKeySymbol = 0; |
|---|
| 1647 | if (state) |
|---|
| 1648 | { |
|---|
| 1649 | event.type = KeyPress; |
|---|
| 1650 | adaptKey(event, keySymbol, unmodifiedKeySymbol); |
|---|
| 1651 | getEventQueue()->keyPress(keySymbol, time, unmodifiedKeySymbol); |
|---|
| 1652 | keyMapSetKey(_keyMap, key); |
|---|
| 1653 | } |
|---|
| 1654 | else |
|---|
| 1655 | { |
|---|
| 1656 | event.type = KeyRelease; |
|---|
| 1657 | adaptKey(event, keySymbol, unmodifiedKeySymbol); |
|---|
| 1658 | getEventQueue()->keyRelease(keySymbol, time, unmodifiedKeySymbol); |
|---|
| 1659 | keyMapClearKey(_keyMap, key); |
|---|
| 1660 | } |
|---|
| 1661 | } |
|---|
| 1662 | |
|---|
| 1663 | void GraphicsWindowX11::syncLocks() |
|---|
| 1664 | { |
|---|
| 1665 | unsigned int mask = getEventQueue()->getCurrentEventState()->getModKeyMask(); |
|---|
| 1666 | |
|---|
| 1667 | if (_modifierState & LockMask) |
|---|
| 1668 | mask |= osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK; |
|---|
| 1669 | else |
|---|
| 1670 | mask &= ~osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK; |
|---|
| 1671 | |
|---|
| 1672 | if (_modifierState & _numLockMask) |
|---|
| 1673 | mask |= osgGA::GUIEventAdapter::MODKEY_NUM_LOCK; |
|---|
| 1674 | else |
|---|
| 1675 | mask &= ~osgGA::GUIEventAdapter::MODKEY_NUM_LOCK; |
|---|
| 1676 | |
|---|
| 1677 | getEventQueue()->getCurrentEventState()->setModKeyMask(mask); |
|---|
| 1678 | } |
|---|
| 1679 | |
|---|
| 1680 | void GraphicsWindowX11::rescanModifierMapping() |
|---|
| 1681 | { |
|---|
| 1682 | XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay); |
|---|
| 1683 | KeyCode *m = mkm->modifiermap; |
|---|
| 1684 | KeyCode numlock = XKeysymToKeycode(_eventDisplay, XK_Num_Lock); |
|---|
| 1685 | _numLockMask = 0; |
|---|
| 1686 | for (int i = 0; i < mkm->max_keypermod * 8; i++, m++) |
|---|
| 1687 | { |
|---|
| 1688 | if (*m == numlock) |
|---|
| 1689 | { |
|---|
| 1690 | _numLockMask = 1 << (i / mkm->max_keypermod); |
|---|
| 1691 | break; |
|---|
| 1692 | } |
|---|
| 1693 | } |
|---|
| 1694 | XFree(mkm->modifiermap); |
|---|
| 1695 | XFree(mkm); |
|---|
| 1696 | } |
|---|
| 1697 | |
|---|
| 1698 | void GraphicsWindowX11::flushKeyEvents() |
|---|
| 1699 | { |
|---|
| 1700 | XEvent e; |
|---|
| 1701 | while (XCheckMaskEvent(_eventDisplay, KeyPressMask|KeyReleaseMask, &e)) |
|---|
| 1702 | continue; |
|---|
| 1703 | } |
|---|
| 1704 | |
|---|
| 1705 | |
|---|
| 1706 | void GraphicsWindowX11::getModifierMap(char* keymap) const |
|---|
| 1707 | { |
|---|
| 1708 | memset(keymap, 0, 32); |
|---|
| 1709 | XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay); |
|---|
| 1710 | KeyCode *m = mkm->modifiermap; |
|---|
| 1711 | for (int i = 0; i < mkm->max_keypermod * 8; i++, m++) |
|---|
| 1712 | { |
|---|
| 1713 | if (*m) keyMapSetKey(keymap, *m); |
|---|
| 1714 | } |
|---|
| 1715 | XFree(mkm->modifiermap); |
|---|
| 1716 | XFree(mkm); |
|---|
| 1717 | } |
|---|
| 1718 | |
|---|
| 1719 | int GraphicsWindowX11::getModifierMask() const |
|---|
| 1720 | { |
|---|
| 1721 | int mask = 0; |
|---|
| 1722 | XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay); |
|---|
| 1723 | for (int i = 0; i < mkm->max_keypermod * 8; i++) |
|---|
| 1724 | { |
|---|
| 1725 | unsigned int key = mkm->modifiermap[i]; |
|---|
| 1726 | if (key && keyMapGetKey(_keyMap, key)) |
|---|
| 1727 | { |
|---|
| 1728 | mask |= 1 << (i / mkm->max_keypermod); |
|---|
| 1729 | } |
|---|
| 1730 | } |
|---|
| 1731 | XFree(mkm->modifiermap); |
|---|
| 1732 | XFree(mkm); |
|---|
| 1733 | return mask; |
|---|
| 1734 | } |
|---|
| 1735 | |
|---|
| 1736 | void GraphicsWindowX11::requestWarpPointer(float x,float y) |
|---|
| 1737 | { |
|---|
| 1738 | if (!_realized) |
|---|
| 1739 | { |
|---|
| 1740 | OSG_INFO<<"GraphicsWindowX11::requestWarpPointer() - Window not realized; cannot warp pointer, screenNum="<< _traits->screenNum<<std::endl; |
|---|
| 1741 | return; |
|---|
| 1742 | } |
|---|
| 1743 | |
|---|
| 1744 | Display* display = _eventDisplay; |
|---|
| 1745 | |
|---|
| 1746 | XWarpPointer( display, |
|---|
| 1747 | None, |
|---|
| 1748 | _window, |
|---|
| 1749 | 0, 0, 0, 0, |
|---|
| 1750 | static_cast<int>(x), static_cast<int>(y) ); |
|---|
| 1751 | |
|---|
| 1752 | XFlush(display); |
|---|
| 1753 | XSync(display, 0); |
|---|
| 1754 | |
|---|
| 1755 | getEventQueue()->mouseWarped(x,y); |
|---|
| 1756 | } |
|---|
| 1757 | |
|---|
| 1758 | extern "C" |
|---|
| 1759 | { |
|---|
| 1760 | |
|---|
| 1761 | typedef int (*X11ErrorHandler)(Display*, XErrorEvent*); |
|---|
| 1762 | |
|---|
| 1763 | int X11ErrorHandling(Display* display, XErrorEvent* event) |
|---|
| 1764 | { |
|---|
| 1765 | OSG_NOTICE<<"Got an X11ErrorHandling call display="<<display<<" event="<<event<<std::endl; |
|---|
| 1766 | |
|---|
| 1767 | char buffer[256]; |
|---|
| 1768 | XGetErrorText( display, event->error_code, buffer, 256); |
|---|
| 1769 | |
|---|
| 1770 | OSG_NOTICE << buffer << std::endl; |
|---|
| 1771 | OSG_NOTICE << "Major opcode: " << (int)event->request_code << std::endl; |
|---|
| 1772 | OSG_NOTICE << "Minor opcode: " << (int)event->minor_code << std::endl; |
|---|
| 1773 | OSG_NOTICE << "Error code: " << (int)event->error_code << std::endl; |
|---|
| 1774 | OSG_NOTICE << "Request serial: " << event->serial << std::endl; |
|---|
| 1775 | OSG_NOTICE << "Current serial: " << NextRequest( display ) - 1 << std::endl; |
|---|
| 1776 | |
|---|
| 1777 | switch( event->error_code ) |
|---|
| 1778 | { |
|---|
| 1779 | case BadValue: |
|---|
| 1780 | OSG_NOTICE << " Value: " << event->resourceid << std::endl; |
|---|
| 1781 | break; |
|---|
| 1782 | |
|---|
| 1783 | case BadAtom: |
|---|
| 1784 | OSG_NOTICE << " AtomID: " << event->resourceid << std::endl; |
|---|
| 1785 | break; |
|---|
| 1786 | |
|---|
| 1787 | default: |
|---|
| 1788 | OSG_NOTICE << " ResourceID: " << event->resourceid << std::endl; |
|---|
| 1789 | break; |
|---|
| 1790 | } |
|---|
| 1791 | return 0; |
|---|
| 1792 | } |
|---|
| 1793 | |
|---|
| 1794 | } |
|---|
| 1795 | |
|---|
| 1796 | class X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface |
|---|
| 1797 | { |
|---|
| 1798 | #ifdef OSGVIEWER_USE_XRANDR |
|---|
| 1799 | |
|---|
| 1800 | |
|---|
| 1801 | |
|---|
| 1802 | bool _setScreen(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height, unsigned int colorDepth, double rate) { |
|---|
| 1803 | if (colorDepth>0) |
|---|
| 1804 | OSG_NOTICE << "X11WindowingSystemInterface::_setScreen() is not fully implemented (missing depth)."<<std::endl; |
|---|
| 1805 | |
|---|
| 1806 | Display* display = XOpenDisplay(si.displayName().c_str()); |
|---|
| 1807 | |
|---|
| 1808 | if(display) |
|---|
| 1809 | { |
|---|
| 1810 | XRRScreenConfiguration* sc = XRRGetScreenInfo(display, RootWindow(display, si.screenNum)); |
|---|
| 1811 | |
|---|
| 1812 | if(!sc) |
|---|
| 1813 | { |
|---|
| 1814 | OSG_NOTICE << "Unable to create XRRScreenConfiguration on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl; |
|---|
| 1815 | return false; |
|---|
| 1816 | } |
|---|
| 1817 | |
|---|
| 1818 | int numScreens = 0; |
|---|
| 1819 | int numRates = 0; |
|---|
| 1820 | Rotation currentRot = 0; |
|---|
| 1821 | bool okay = false; |
|---|
| 1822 | |
|---|
| 1823 | XRRConfigRotations(sc, ¤tRot); |
|---|
| 1824 | |
|---|
| 1825 | |
|---|
| 1826 | if(!width || !height) |
|---|
| 1827 | { |
|---|
| 1828 | getScreenResolution(si, width, height); |
|---|
| 1829 | } |
|---|
| 1830 | |
|---|
| 1831 | |
|---|
| 1832 | |
|---|
| 1833 | XRRScreenSize* ss = XRRConfigSizes(sc, &numScreens); |
|---|
| 1834 | |
|---|
| 1835 | for(int i = 0; i < numScreens; i++) |
|---|
| 1836 | { |
|---|
| 1837 | if(ss[i].width == static_cast<int>(width) && ss[i].height == static_cast<int>(height)) |
|---|
| 1838 | { |
|---|
| 1839 | short* rates = XRRConfigRates(sc, i, &numRates); |
|---|
| 1840 | bool rateFound = false; |
|---|
| 1841 | |
|---|
| 1842 | |
|---|
| 1843 | |
|---|
| 1844 | |
|---|
| 1845 | for(int r = 0; r < numRates; r++) |
|---|
| 1846 | { |
|---|
| 1847 | if(rates[r] == static_cast<short>(rate)) |
|---|
| 1848 | { |
|---|
| 1849 | rateFound = true; |
|---|
| 1850 | break; |
|---|
| 1851 | } |
|---|
| 1852 | } |
|---|
| 1853 | |
|---|
| 1854 | if(rate > 0.0f && !rateFound) |
|---|
| 1855 | { |
|---|
| 1856 | OSG_NOTICE << "Unable to find valid refresh rate " << rate << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl; |
|---|
| 1857 | } |
|---|
| 1858 | else if(XRRSetScreenConfigAndRate(display, sc, DefaultRootWindow(display), i, currentRot, static_cast<short>(rate), CurrentTime) != RRSetConfigSuccess) |
|---|
| 1859 | { |
|---|
| 1860 | OSG_NOTICE << "Unable to set resolution to " << width << "x" << height << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl; |
|---|
| 1861 | } |
|---|
| 1862 | else |
|---|
| 1863 | { |
|---|
| 1864 | okay = true; |
|---|
| 1865 | break; |
|---|
| 1866 | } |
|---|
| 1867 | } |
|---|
| 1868 | } |
|---|
| 1869 | |
|---|
| 1870 | XRRFreeScreenConfigInfo(sc); |
|---|
| 1871 | |
|---|
| 1872 | return okay; |
|---|
| 1873 | } |
|---|
| 1874 | else |
|---|
| 1875 | { |
|---|
| 1876 | OSG_NOTICE << "Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl; |
|---|
| 1877 | return false; |
|---|
| 1878 | } |
|---|
| 1879 | } |
|---|
| 1880 | #endif |
|---|
| 1881 | |
|---|
| 1882 | protected: |
|---|
| 1883 | bool _errorHandlerSet; |
|---|
| 1884 | |
|---|
| 1885 | |
|---|
| 1886 | public: |
|---|
| 1887 | X11WindowingSystemInterface() |
|---|
| 1888 | { |
|---|
| 1889 | OSG_INFO<<"X11WindowingSystemInterface()"<<std::endl; |
|---|
| 1890 | |
|---|
| 1891 | |
|---|
| 1892 | |
|---|
| 1893 | |
|---|
| 1894 | |
|---|
| 1895 | X11ErrorHandler currentHandler = XSetErrorHandler(NULL); |
|---|
| 1896 | |
|---|
| 1897 | |
|---|
| 1898 | X11ErrorHandler defHandler = XSetErrorHandler(X11ErrorHandling); |
|---|
| 1899 | |
|---|
| 1900 | if ( currentHandler == defHandler ) |
|---|
| 1901 | { |
|---|
| 1902 | |
|---|
| 1903 | |
|---|
| 1904 | _errorHandlerSet = 1; |
|---|
| 1905 | } |
|---|
| 1906 | else |
|---|
| 1907 | { |
|---|
| 1908 | |
|---|
| 1909 | |
|---|
| 1910 | _errorHandlerSet = 0; |
|---|
| 1911 | XSetErrorHandler(currentHandler); |
|---|
| 1912 | } |
|---|
| 1913 | |
|---|
| 1914 | #if 0 |
|---|
| 1915 | if (XInitThreads() == 0) |
|---|
| 1916 | { |
|---|
| 1917 | OSG_NOTICE << "Error: XInitThreads() failed. Aborting." << std::endl; |
|---|
| 1918 | exit(1); |
|---|
| 1919 | } |
|---|
| 1920 | else |
|---|
| 1921 | { |
|---|
| 1922 | OSG_INFO << "X11WindowingSystemInterface, xInitThreads() multi-threaded X support initialized.\n"; |
|---|
| 1923 | } |
|---|
| 1924 | #endif |
|---|
| 1925 | |
|---|
| 1926 | } |
|---|
| 1927 | |
|---|
| 1928 | |
|---|
| 1929 | |
|---|
| 1930 | ~X11WindowingSystemInterface() |
|---|
| 1931 | { |
|---|
| 1932 | if (osg::Referenced::getDeleteHandler()) |
|---|
| 1933 | { |
|---|
| 1934 | osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); |
|---|
| 1935 | osg::Referenced::getDeleteHandler()->flushAll(); |
|---|
| 1936 | } |
|---|
| 1937 | |
|---|
| 1938 | |
|---|
| 1939 | |
|---|
| 1940 | |
|---|
| 1941 | |
|---|
| 1942 | if ( _errorHandlerSet ) |
|---|
| 1943 | { |
|---|
| 1944 | X11ErrorHandler currentHandler = XSetErrorHandler(NULL); |
|---|
| 1945 | if ( currentHandler == X11ErrorHandling ) |
|---|
| 1946 | { |
|---|
| 1947 | |
|---|
| 1948 | } |
|---|
| 1949 | else |
|---|
| 1950 | { |
|---|
| 1951 | |
|---|
| 1952 | |
|---|
| 1953 | XSetErrorHandler(currentHandler); |
|---|
| 1954 | } |
|---|
| 1955 | } |
|---|
| 1956 | } |
|---|
| 1957 | |
|---|
| 1958 | virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si) |
|---|
| 1959 | { |
|---|
| 1960 | Display* display = XOpenDisplay(si.displayName().c_str()); |
|---|
| 1961 | if(display) |
|---|
| 1962 | { |
|---|
| 1963 | unsigned int numScreens = ScreenCount(display); |
|---|
| 1964 | XCloseDisplay(display); |
|---|
| 1965 | |
|---|
| 1966 | return numScreens; |
|---|
| 1967 | } |
|---|
| 1968 | else |
|---|
| 1969 | { |
|---|
| 1970 | OSG_NOTICE << "A Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\""<<std::endl; |
|---|
| 1971 | return 0; |
|---|
| 1972 | } |
|---|
| 1973 | } |
|---|
| 1974 | |
|---|
| 1975 | bool supportsRandr(Display* display) const |
|---|
| 1976 | { |
|---|
| 1977 | #ifdef OSGVIEWER_USE_XRANDR |
|---|
| 1978 | int event_basep; |
|---|
| 1979 | int error_basep; |
|---|
| 1980 | bool supports_randr = XRRQueryExtension( display, &event_basep, &error_basep ); |
|---|
| 1981 | if( supports_randr ) |
|---|
| 1982 | { |
|---|
| 1983 | int major, minor; |
|---|
| 1984 | XRRQueryVersion( display, &major, &minor ); |
|---|
| 1985 | return ( major > 1 || ( major == 1 && minor >= 2 ) ); |
|---|
| 1986 | } |
|---|
| 1987 | #endif |
|---|
| 1988 | return false; |
|---|
| 1989 | } |
|---|
| 1990 | |
|---|
| 1991 | virtual void getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution ) |
|---|
| 1992 | { |
|---|
| 1993 | Display* display = XOpenDisplay(si.displayName().c_str()); |
|---|
| 1994 | if(display) |
|---|
| 1995 | { |
|---|
| 1996 | resolution.width = DisplayWidth(display, si.screenNum); |
|---|
| 1997 | resolution.height = DisplayHeight(display, si.screenNum); |
|---|
| 1998 | resolution.colorDepth = DefaultDepth(display, si.screenNum); |
|---|
| 1999 | |
|---|
| 2000 | resolution.refreshRate = 0; |
|---|
| 2001 | |
|---|
| 2002 | |
|---|
| 2003 | #ifdef OSGVIEWER_USE_XRANDR |
|---|
| 2004 | if (supportsRandr(display)) |
|---|
| 2005 | { |
|---|
| 2006 | |
|---|
| 2007 | XRRScreenConfiguration* screenConfig = XRRGetScreenInfo ( display, RootWindow(display, si.screenNum) ); |
|---|
| 2008 | |
|---|
| 2009 | resolution.refreshRate = XRRConfigCurrentRate ( screenConfig ); |
|---|
| 2010 | |
|---|
| 2011 | XRRFreeScreenConfigInfo( screenConfig ); |
|---|
| 2012 | } |
|---|
| 2013 | #endif |
|---|
| 2014 | |
|---|
| 2015 | |
|---|
| 2016 | XCloseDisplay(display); |
|---|
| 2017 | } |
|---|
| 2018 | else |
|---|
| 2019 | { |
|---|
| 2020 | OSG_NOTICE << "Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl; |
|---|
| 2021 | resolution.width = 0; |
|---|
| 2022 | resolution.height = 0; |
|---|
| 2023 | resolution.colorDepth = 0; |
|---|
| 2024 | resolution.refreshRate = 0; |
|---|
| 2025 | } |
|---|
| 2026 | } |
|---|
| 2027 | |
|---|
| 2028 | virtual bool setScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, const osg::GraphicsContext::ScreenSettings & resolution ) |
|---|
| 2029 | { |
|---|
| 2030 | #ifdef OSGVIEWER_USE_XRANDR |
|---|
| 2031 | _setScreen(si, resolution.width, resolution.height, resolution.colorDepth, resolution.refreshRate); |
|---|
| 2032 | #else |
|---|
| 2033 | OSG_NOTICE << "You must build osgViewer with Xrandr 1.2 or higher for setScreenSettings support!" << std::endl; |
|---|
| 2034 | #endif |
|---|
| 2035 | return false; |
|---|
| 2036 | } |
|---|
| 2037 | |
|---|
| 2038 | virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettingsList & resolutionList) |
|---|
| 2039 | { |
|---|
| 2040 | resolutionList.clear(); |
|---|
| 2041 | |
|---|
| 2042 | Display* display = XOpenDisplay(si.displayName().c_str()); |
|---|
| 2043 | if(display) |
|---|
| 2044 | { |
|---|
| 2045 | #ifdef OSGVIEWER_USE_XRANDR |
|---|
| 2046 | int defaultDepth = DefaultDepth(display, si.screenNum); |
|---|
| 2047 | |
|---|
| 2048 | if (supportsRandr(display)) |
|---|
| 2049 | { |
|---|
| 2050 | int nsizes = 0; |
|---|
| 2051 | XRRScreenSize * screenSizes = XRRSizes(display, si.screenNum, &nsizes); |
|---|
| 2052 | if (screenSizes && nsizes>0) |
|---|
| 2053 | { |
|---|
| 2054 | for(int i=0; i<nsizes; ++i) |
|---|
| 2055 | { |
|---|
| 2056 | OSG_INFO<<"Screen size "<<screenSizes[i].width<<" "<<screenSizes[i].height<<" "<<screenSizes[i].mwidth<<" "<<screenSizes[i].mheight<<std::endl; |
|---|
| 2057 | |
|---|
| 2058 | int nrates; |
|---|
| 2059 | short * rates = XRRRates (display, si.screenNum, i, &nrates); |
|---|
| 2060 | if (rates && nrates>0) |
|---|
| 2061 | { |
|---|
| 2062 | for(int j=0; j<nrates; ++j) |
|---|
| 2063 | { |
|---|
| 2064 | OSG_INFO<<" rates "<<rates[j]<<std::endl; |
|---|
| 2065 | |
|---|
| 2066 | resolutionList.push_back(osg::GraphicsContext::ScreenSettings( |
|---|
| 2067 | screenSizes[i].width, |
|---|
| 2068 | screenSizes[i].height, |
|---|
| 2069 | double(rates[j]), |
|---|
| 2070 | defaultDepth)); |
|---|
| 2071 | } |
|---|
| 2072 | } |
|---|
| 2073 | else |
|---|
| 2074 | { |
|---|
| 2075 | resolutionList.push_back(osg::GraphicsContext::ScreenSettings( |
|---|
| 2076 | screenSizes[i].width, |
|---|
| 2077 | screenSizes[i].height, |
|---|
| 2078 | 0.0, |
|---|
| 2079 | defaultDepth)); |
|---|
| 2080 | } |
|---|
| 2081 | |
|---|
| 2082 | } |
|---|
| 2083 | } |
|---|
| 2084 | } |
|---|
| 2085 | #endif |
|---|
| 2086 | XCloseDisplay(display); |
|---|
| 2087 | } |
|---|
| 2088 | |
|---|
| 2089 | if (resolutionList.empty()) |
|---|
| 2090 | { |
|---|
| 2091 | OSG_NOTICE << "X11WindowingSystemInterface::enumerateScreenSettings() not supported." << std::endl; |
|---|
| 2092 | } |
|---|
| 2093 | } |
|---|
| 2094 | |
|---|
| 2095 | virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits) |
|---|
| 2096 | { |
|---|
| 2097 | if (traits->pbuffer) |
|---|
| 2098 | { |
|---|
| 2099 | #if 1 |
|---|
| 2100 | osg::ref_ptr<osgViewer::PixelBufferX11> pbuffer = new PixelBufferX11(traits); |
|---|
| 2101 | if (pbuffer->valid()) return pbuffer.release(); |
|---|
| 2102 | else return 0; |
|---|
| 2103 | #else |
|---|
| 2104 | osg::ref_ptr<osgViewer::GraphicsWindowX11> window = new GraphicsWindowX11(traits); |
|---|
| 2105 | if (window->valid()) return window.release(); |
|---|
| 2106 | else return 0; |
|---|
| 2107 | #endif |
|---|
| 2108 | } |
|---|
| 2109 | else |
|---|
| 2110 | { |
|---|
| 2111 | osg::ref_ptr<osgViewer::GraphicsWindowX11> window = new GraphicsWindowX11(traits); |
|---|
| 2112 | if (window->valid()) return window.release(); |
|---|
| 2113 | else return 0; |
|---|
| 2114 | } |
|---|
| 2115 | } |
|---|
| 2116 | |
|---|
| 2117 | }; |
|---|
| 2118 | |
|---|
| 2119 | struct RegisterWindowingSystemInterfaceProxy |
|---|
| 2120 | { |
|---|
| 2121 | RegisterWindowingSystemInterfaceProxy() |
|---|
| 2122 | { |
|---|
| 2123 | OSG_INFO<<"RegisterWindowingSystemInterfaceProxy()"<<std::endl; |
|---|
| 2124 | osg::GraphicsContext::setWindowingSystemInterface(new X11WindowingSystemInterface); |
|---|
| 2125 | } |
|---|
| 2126 | |
|---|
| 2127 | ~RegisterWindowingSystemInterfaceProxy() |
|---|
| 2128 | { |
|---|
| 2129 | OSG_INFO<<"~RegisterWindowingSystemInterfaceProxy()"<<std::endl; |
|---|
| 2130 | |
|---|
| 2131 | if (osg::Referenced::getDeleteHandler()) |
|---|
| 2132 | { |
|---|
| 2133 | osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); |
|---|
| 2134 | osg::Referenced::getDeleteHandler()->flushAll(); |
|---|
| 2135 | } |
|---|
| 2136 | |
|---|
| 2137 | osg::GraphicsContext::setWindowingSystemInterface(0); |
|---|
| 2138 | |
|---|
| 2139 | } |
|---|
| 2140 | }; |
|---|
| 2141 | |
|---|
| 2142 | RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy; |
|---|
| 2143 | |
|---|
| 2144 | |
|---|
| 2145 | extern "C" void graphicswindow_X11(void) |
|---|
| 2146 | { |
|---|
| 2147 | osg::GraphicsContext::setWindowingSystemInterface(new X11WindowingSystemInterface); |
|---|
| 2148 | } |
|---|
| 2149 | |
|---|
| 2150 | |
|---|
| 2151 | void GraphicsWindowX11::raiseWindow() |
|---|
| 2152 | { |
|---|
| 2153 | Display* display = getDisplayToUse(); |
|---|
| 2154 | XWindowAttributes winAttrib; |
|---|
| 2155 | |
|---|
| 2156 | Window root_return, parent_return, *children; |
|---|
| 2157 | unsigned int nchildren, i=0; |
|---|
| 2158 | XTextProperty windowName; |
|---|
| 2159 | bool xraise = false; |
|---|
| 2160 | |
|---|
| 2161 | |
|---|
| 2162 | XQueryTree(display, _parent, &root_return, &parent_return, &children, &nchildren); |
|---|
| 2163 | while (!xraise && i<nchildren) |
|---|
| 2164 | { |
|---|
| 2165 | XGetWMName(display,children[i++],&windowName); |
|---|
| 2166 | if ((windowName.nitems != 0) && (strcmp(_traits->windowName.c_str(),(const char *)windowName.value) == 0)) xraise = true; |
|---|
| 2167 | } |
|---|
| 2168 | if (xraise) XRaiseWindow(display,_window); |
|---|
| 2169 | else |
|---|
| 2170 | { |
|---|
| 2171 | XGetWindowAttributes(display, _window, &winAttrib); |
|---|
| 2172 | XReparentWindow(display, _window, _parent, winAttrib.x, winAttrib.y); |
|---|
| 2173 | } |
|---|
| 2174 | XFree(children); |
|---|
| 2175 | |
|---|
| 2176 | XFlush(display); |
|---|
| 2177 | XSync(display,0); |
|---|
| 2178 | } |
|---|