1 // Created on: 2013-04-06
2 // Created by: Kirill Gavrilov
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <Xw_Window.hxx>
18 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
20 #include <Aspect_Convert.hxx>
21 #include <Aspect_WindowDefinitionError.hxx>
22 #include <Message.hxx>
23 #include <Message_Messenger.hxx>
25 //#include <X11/XF86keysym.h>
27 #if defined(HAVE_EGL) || defined(HAVE_GLES2)
29 #ifndef EGL_OPENGL_ES3_BIT
30 #define EGL_OPENGL_ES3_BIT 0x00000040
38 //! Search for RGBA double-buffered visual with stencil buffer.
39 static int TheDoubleBuffVisual[] =
48 //! Search for RGBA double-buffered visual with stencil buffer.
49 static int TheDoubleBuffFBConfig[] =
51 GLX_X_RENDERABLE, True,
52 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
53 GLX_RENDER_TYPE, GLX_RGBA_BIT,
54 GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
57 GLX_DOUBLEBUFFER, True,
65 IMPLEMENT_STANDARD_RTTIEXT(Xw_Window, Aspect_Window)
67 // =======================================================================
68 // function : Xw_Window
70 // =======================================================================
71 Xw_Window::Xw_Window (const Handle(Aspect_DisplayConnection)& theXDisplay,
72 const Standard_CString theTitle,
73 const Standard_Integer thePxLeft,
74 const Standard_Integer thePxTop,
75 const Standard_Integer thePxWidth,
76 const Standard_Integer thePxHeight,
77 const Aspect_FBConfig theFBConfig)
79 myDisplay (theXDisplay),
81 myFBConfig (theFBConfig),
84 myXRight (thePxLeft + thePxWidth),
85 myYBottom (thePxTop + thePxHeight),
86 myIsOwnWin (Standard_True)
88 if (thePxWidth <= 0 || thePxHeight <= 0)
90 throw Aspect_WindowDefinitionError("Xw_Window, Coordinate(s) out of range");
92 else if (theXDisplay.IsNull())
94 throw Aspect_WindowDefinitionError("Xw_Window, X Display connection is undefined");
98 Display* aDisp = myDisplay->GetDisplay();
99 int aScreen = DefaultScreen(aDisp);
100 Window aParent = RootWindow (aDisp, aScreen);
101 XVisualInfo* aVisInfo = NULL;
103 #if defined(HAVE_EGL) || defined(HAVE_GLES2)
104 EGLDisplay anEglDisplay = eglGetDisplay (aDisp);
105 EGLint aVerMajor = 0; EGLint aVerMinor = 0;
106 XVisualInfo aVisInfoTmp; memset (&aVisInfoTmp, 0, sizeof(aVisInfoTmp));
107 if (anEglDisplay != EGL_NO_DISPLAY
108 && eglInitialize (anEglDisplay, &aVerMajor, &aVerMinor) == EGL_TRUE)
110 EGLint aConfigAttribs[] =
118 #if defined(HAVE_GLES2)
119 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
121 EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
126 EGLint aNbConfigs = 0;
127 void* anEglConfig = NULL;
128 for (Standard_Integer aGlesVer = 3; aGlesVer >= 2; --aGlesVer)
130 #if defined(GL_ES_VERSION_2_0)
131 aConfigAttribs[6 * 2 + 1] = aGlesVer == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
139 if (eglChooseConfig (anEglDisplay, aConfigAttribs, &anEglConfig, 1, &aNbConfigs) == EGL_TRUE
140 && anEglConfig != NULL)
146 aConfigAttribs[4 * 2 + 1] = 16; // try config with smaller depth buffer
147 if (eglChooseConfig (anEglDisplay, aConfigAttribs, &anEglConfig, 1, &aNbConfigs) == EGL_TRUE
148 && anEglConfig != NULL)
155 if (anEglConfig != NULL
156 && eglGetConfigAttrib (anEglDisplay, anEglConfig, EGL_NATIVE_VISUAL_ID, (EGLint* )&aVisInfoTmp.visualid) == EGL_TRUE)
159 aVisInfoTmp.screen = DefaultScreen (aDisp);
160 aVisInfo = XGetVisualInfo (aDisp, VisualIDMask | VisualScreenMask, &aVisInfoTmp, &aNbVisuals);
163 if (aVisInfo == NULL)
165 Message::SendWarning ("Warning: cannot choose Visual using EGL while creating Xw_Window");
169 if (!glXQueryExtension (myDisplay->GetDisplay(), &aDummy, &aDummy))
171 throw Aspect_WindowDefinitionError("Xw_Window, GLX extension is unavailable");
174 if (myFBConfig == NULL)
176 // FBConfigs were added in GLX version 1.3
179 const bool hasFBCfg = glXQueryVersion (aDisp, &aGlxMajor, &aGlxMinor)
180 && ((aGlxMajor == 1 && aGlxMinor >= 3) || (aGlxMajor > 1));
184 GLXFBConfig* aFBCfgList = NULL;
187 aFBCfgList = glXChooseFBConfig (aDisp, aScreen, TheDoubleBuffFBConfig, &aFBCount);
189 if(aFBCfgList != NULL
192 myFBConfig = aFBCfgList[0];
193 aVisInfo = glXGetVisualFromFBConfig (aDisp, myFBConfig);
199 if (aVisInfo == NULL)
201 aVisInfo = glXChooseVisual (aDisp, aScreen, TheDoubleBuffVisual);
203 if (aVisInfo == NULL)
205 throw Aspect_WindowDefinitionError("Xw_Window, couldn't find compatible Visual (RGBA, double-buffered)");
210 unsigned long aMask = 0;
211 XSetWindowAttributes aWinAttr;
212 memset(&aWinAttr, 0, sizeof(XSetWindowAttributes));
213 aWinAttr.event_mask = ExposureMask | StructureNotifyMask;
214 aMask |= CWEventMask;
215 if (aVisInfo != NULL)
217 aWinAttr.colormap = XCreateColormap(aDisp, aParent, aVisInfo->visual, AllocNone);
219 aWinAttr.border_pixel = 0;
220 aWinAttr.override_redirect = False;
222 myXWindow = XCreateWindow(aDisp, aParent,
223 myXLeft, myYTop, thePxWidth, thePxHeight,
224 0, aVisInfo != NULL ? aVisInfo->depth : CopyFromParent,
226 aVisInfo != NULL ? aVisInfo->visual : CopyFromParent,
227 CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &aWinAttr);
228 if (aVisInfo != NULL)
235 throw Aspect_WindowDefinitionError("Xw_Window, Unable to create window");
239 // if parent - desktop
240 XSizeHints aSizeHints;
241 aSizeHints.x = myXLeft;
242 aSizeHints.y = myYTop;
243 aSizeHints.flags = PPosition;
244 aSizeHints.width = thePxWidth;
245 aSizeHints.height = thePxHeight;
246 aSizeHints.flags |= PSize;
247 XSetStandardProperties (aDisp, myXWindow, theTitle, theTitle, None,
248 NULL, 0, &aSizeHints);
250 /*XTextProperty aTitleProperty;
251 aTitleProperty.encoding = None;
252 char* aTitle = (char* )theTitle;
253 Xutf8TextListToTextProperty(aDisp, &aTitle, 1, XUTF8StringStyle, &aTitleProperty);
254 XSetWMName (aDisp, myXWindow, &aTitleProperty);
255 XSetWMProperties(aDisp, myXWindow, &aTitleProperty, &aTitleProperty, NULL, 0, NULL, NULL, NULL);*/
260 // =======================================================================
261 // function : Xw_Window
263 // =======================================================================
264 Xw_Window::Xw_Window (const Handle(Aspect_DisplayConnection)& theXDisplay,
265 const Window theXWin,
266 const Aspect_FBConfig theFBConfig)
268 myDisplay (theXDisplay),
270 myFBConfig (theFBConfig),
275 myIsOwnWin (Standard_False)
279 throw Aspect_WindowDefinitionError("Xw_Window, given invalid X window");
282 else if (theXDisplay.IsNull())
284 throw Aspect_WindowDefinitionError("Xw_Window, X Display connection is undefined");
287 #if !defined(HAVE_EGL) && !defined(HAVE_GLES2)
289 if (!glXQueryExtension (myDisplay->GetDisplay(), &aDummy, &aDummy))
292 throw Aspect_WindowDefinitionError("Xw_Window, GLX extension is unavailable");
297 Display* aDisp = myDisplay->GetDisplay();
299 XWindowAttributes aWinAttr;
300 XGetWindowAttributes (aDisp, myXWindow, &aWinAttr);
301 XVisualInfo aVisInfoTmp;
302 aVisInfoTmp.visualid = aWinAttr.visual->visualid;
303 aVisInfoTmp.screen = DefaultScreen (aDisp);
305 XVisualInfo* aVisInfo = XGetVisualInfo (aDisp, VisualIDMask | VisualScreenMask, &aVisInfoTmp, &aNbItems);
306 if (aVisInfo == NULL)
308 throw Aspect_WindowDefinitionError("Xw_Window, Visual is unavailable");
316 // =======================================================================
317 // function : ~Xw_Window
319 // =======================================================================
320 Xw_Window::~Xw_Window()
322 if (myIsOwnWin && myXWindow != 0 && !myDisplay.IsNull())
324 XDestroyWindow (myDisplay->GetDisplay(), myXWindow);
328 // =======================================================================
329 // function : XWindow
331 // =======================================================================
332 Window Xw_Window::XWindow() const
337 // =======================================================================
338 // function : IsMapped
340 // =======================================================================
341 Standard_Boolean Xw_Window::IsMapped() const
347 else if (IsVirtual())
349 return Standard_True;
352 XFlush (myDisplay->GetDisplay());
353 XWindowAttributes aWinAttr;
354 XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
355 return aWinAttr.map_state == IsUnviewable
356 || aWinAttr.map_state == IsViewable;
359 // =======================================================================
362 // =======================================================================
363 void Xw_Window::Map() const
365 if (IsVirtual() || myXWindow == 0)
370 XMapWindow (myDisplay->GetDisplay(), myXWindow);
371 XFlush (myDisplay->GetDisplay());
374 // =======================================================================
377 // =======================================================================
378 void Xw_Window::Unmap() const
380 if (IsVirtual() || myXWindow == 0)
385 XIconifyWindow (myDisplay->GetDisplay(), myXWindow, DefaultScreen(myDisplay->GetDisplay()));
388 // =======================================================================
389 // function : DoResize
391 // =======================================================================
392 Aspect_TypeOfResize Xw_Window::DoResize()
396 return Aspect_TOR_UNKNOWN;
399 XFlush (myDisplay->GetDisplay());
400 XWindowAttributes aWinAttr;
401 XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
402 if (aWinAttr.map_state == IsUnmapped)
404 return Aspect_TOR_UNKNOWN;
407 Standard_Integer aMask = 0;
408 Aspect_TypeOfResize aMode = Aspect_TOR_UNKNOWN;
410 if (Abs (aWinAttr.x - myXLeft ) > 2) aMask |= 1;
411 if (Abs ((aWinAttr.x + aWinAttr.width) - myXRight ) > 2) aMask |= 2;
412 if (Abs (aWinAttr.y - myYTop ) > 2) aMask |= 4;
413 if (Abs ((aWinAttr.y + aWinAttr.height) - myYBottom) > 2) aMask |= 8;
416 case 0: aMode = Aspect_TOR_NO_BORDER; break;
417 case 1: aMode = Aspect_TOR_LEFT_BORDER; break;
418 case 2: aMode = Aspect_TOR_RIGHT_BORDER; break;
419 case 4: aMode = Aspect_TOR_TOP_BORDER; break;
420 case 5: aMode = Aspect_TOR_LEFT_AND_TOP_BORDER; break;
421 case 6: aMode = Aspect_TOR_TOP_AND_RIGHT_BORDER; break;
422 case 8: aMode = Aspect_TOR_BOTTOM_BORDER; break;
423 case 9: aMode = Aspect_TOR_BOTTOM_AND_LEFT_BORDER; break;
424 case 10: aMode = Aspect_TOR_RIGHT_AND_BOTTOM_BORDER; break;
428 myXLeft = aWinAttr.x;
429 myXRight = aWinAttr.x + aWinAttr.width;
431 myYBottom = aWinAttr.y + aWinAttr.height;
435 // =======================================================================
436 // function : DoMapping
438 // =======================================================================
439 Standard_Boolean Xw_Window::DoMapping() const
441 return Standard_True; // IsMapped()
444 // =======================================================================
447 // =======================================================================
448 Standard_Real Xw_Window::Ratio() const
455 XFlush (myDisplay->GetDisplay());
456 XWindowAttributes aWinAttr;
457 XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
458 return Standard_Real(aWinAttr.width) / Standard_Real(aWinAttr.height);
461 // =======================================================================
462 // function : Position
464 // =======================================================================
465 void Xw_Window::Position (Standard_Integer& X1, Standard_Integer& Y1,
466 Standard_Integer& X2, Standard_Integer& Y2) const
473 XFlush (myDisplay->GetDisplay());
474 XWindowAttributes anAttributes;
475 XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &anAttributes);
477 XTranslateCoordinates (myDisplay->GetDisplay(), anAttributes.root, myXWindow,
478 0, 0, &anAttributes.x, &anAttributes.y, &aChild);
480 X1 = -anAttributes.x;
481 X2 = X1 + anAttributes.width;
482 Y1 = -anAttributes.y;
483 Y2 = Y1 + anAttributes.height;
486 // =======================================================================
489 // =======================================================================
490 void Xw_Window::Size (Standard_Integer& theWidth,
491 Standard_Integer& theHeight) const
498 XFlush (myDisplay->GetDisplay());
499 XWindowAttributes aWinAttr;
500 XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
501 theWidth = aWinAttr.width;
502 theHeight = aWinAttr.height;
505 // =======================================================================
506 // function : SetTitle
508 // =======================================================================
509 void Xw_Window::SetTitle (const TCollection_AsciiString& theTitle)
513 XStoreName (myDisplay->GetDisplay(), myXWindow, theTitle.ToCString());
517 // =======================================================================
518 // function : InvalidateContent
520 // =======================================================================
521 void Xw_Window::InvalidateContent (const Handle(Aspect_DisplayConnection)& theDisp)
528 const Handle(Aspect_DisplayConnection)& aDisp = !theDisp.IsNull() ? theDisp : myDisplay;
529 Display* aDispX = aDisp->GetDisplay();
532 memset (&anEvent, 0, sizeof(anEvent));
533 anEvent.type = Expose;
534 anEvent.xexpose.window = myXWindow;
535 XSendEvent (aDispX, myXWindow, False, ExposureMask, &anEvent);
539 // =======================================================================
540 // function : VirtualKeyFromNative
542 // =======================================================================
543 Aspect_VKey Xw_Window::VirtualKeyFromNative (unsigned long theKey)
548 return Aspect_VKey(theKey - XK_0 + Aspect_VKey_0);
554 return Aspect_VKey(theKey - XK_A + Aspect_VKey_A);
560 return Aspect_VKey(theKey - XK_a + Aspect_VKey_A);
566 if (theKey <= XK_F12)
568 return Aspect_VKey(theKey - XK_F1 + Aspect_VKey_F1);
570 return Aspect_VKey_UNKNOWN;
576 return Aspect_VKey_Space;
578 return Aspect_VKey_Apostrophe;
580 return Aspect_VKey_Comma;
582 return Aspect_VKey_Minus;
584 return Aspect_VKey_Period;
586 return Aspect_VKey_Semicolon;
588 return Aspect_VKey_Equal;
590 return Aspect_VKey_BracketLeft;
592 return Aspect_VKey_Backslash;
593 case XK_bracketright:
594 return Aspect_VKey_BracketRight;
596 return Aspect_VKey_Backspace;
598 return Aspect_VKey_Tab;
602 return Aspect_VKey_Enter;
604 // return Aspect_VKey_Pause;
606 return Aspect_VKey_Escape;
608 return Aspect_VKey_Home;
610 return Aspect_VKey_Left;
612 return Aspect_VKey_Up;
614 return Aspect_VKey_Right;
616 return Aspect_VKey_Down;
618 return Aspect_VKey_PageUp;
620 return Aspect_VKey_PageDown;
622 return Aspect_VKey_End;
624 // return Aspect_VKey_Insert;
626 return Aspect_VKey_Menu;
628 return Aspect_VKey_Numlock;
630 // return Aspect_VKey_NumDelete;
632 return Aspect_VKey_NumpadMultiply;
634 return Aspect_VKey_NumpadAdd;
635 //case XK_KP_Separator:
636 // return Aspect_VKey_Separator;
638 return Aspect_VKey_NumpadSubtract;
639 //case XK_KP_Decimal:
640 // return Aspect_VKey_Decimal;
642 return Aspect_VKey_NumpadDivide;
645 return Aspect_VKey_Shift;
648 return Aspect_VKey_Control;
650 // return Aspect_VKey_CapsLock;
653 return Aspect_VKey_Alt;
656 // return Aspect_VKey_Super;
658 return Aspect_VKey_Delete;
660 case 0x1008FF11: // XF86AudioLowerVolume
661 return Aspect_VKey_VolumeDown;
662 case 0x1008FF12: // XF86AudioMute
663 return Aspect_VKey_VolumeMute;
664 case 0x1008FF13: // XF86AudioRaiseVolume
665 return Aspect_VKey_VolumeUp;
667 case 0x1008FF14: // XF86AudioPlay
668 return Aspect_VKey_MediaPlayPause;
669 case 0x1008FF15: // XF86AudioStop
670 return Aspect_VKey_MediaStop;
671 case 0x1008FF16: // XF86AudioPrev
672 return Aspect_VKey_MediaPreviousTrack;
673 case 0x1008FF17: // XF86AudioNext
674 return Aspect_VKey_MediaNextTrack;
676 case 0x1008FF18: // XF86HomePage
677 return Aspect_VKey_BrowserHome;
678 case 0x1008FF26: // XF86Back
679 return Aspect_VKey_BrowserBack;
680 case 0x1008FF27: // XF86Forward
681 return Aspect_VKey_BrowserForward;
682 case 0x1008FF28: // XF86Stop
683 return Aspect_VKey_BrowserStop;
684 case 0x1008FF29: // XF86Refresh
685 return Aspect_VKey_BrowserRefresh;
687 return Aspect_VKey_UNKNOWN;
690 #endif // Win32 or Mac OS X