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__)
20 #include <Aspect_Convert.hxx>
21 #include <Aspect_WindowDefinitionError.hxx>
22 #include <Message.hxx>
23 #include <Message_Messenger.hxx>
25 #if defined(HAVE_EGL) || defined(HAVE_GLES2)
27 #ifndef EGL_OPENGL_ES3_BIT
28 #define EGL_OPENGL_ES3_BIT 0x00000040
36 //! Search for RGBA double-buffered visual with stencil buffer.
37 static int TheDoubleBuffVisual[] =
46 //! Search for RGBA double-buffered visual with stencil buffer.
47 static int TheDoubleBuffFBConfig[] =
49 GLX_X_RENDERABLE, True,
50 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
51 GLX_RENDER_TYPE, GLX_RGBA_BIT,
52 GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
55 GLX_DOUBLEBUFFER, True,
63 IMPLEMENT_STANDARD_RTTIEXT(Xw_Window, Aspect_Window)
65 // =======================================================================
66 // function : Xw_Window
68 // =======================================================================
69 Xw_Window::Xw_Window (const Handle(Aspect_DisplayConnection)& theXDisplay,
70 const Standard_CString theTitle,
71 const Standard_Integer thePxLeft,
72 const Standard_Integer thePxTop,
73 const Standard_Integer thePxWidth,
74 const Standard_Integer thePxHeight,
75 const Aspect_FBConfig theFBConfig)
77 myDisplay (theXDisplay),
79 myFBConfig (theFBConfig),
82 myXRight (thePxLeft + thePxWidth),
83 myYBottom (thePxTop + thePxHeight),
84 myIsOwnWin (Standard_True)
86 if (thePxWidth <= 0 || thePxHeight <= 0)
88 throw Aspect_WindowDefinitionError("Xw_Window, Coordinate(s) out of range");
90 else if (theXDisplay.IsNull())
92 throw Aspect_WindowDefinitionError("Xw_Window, X Display connection is undefined");
96 Display* aDisp = myDisplay->GetDisplay();
97 int aScreen = DefaultScreen(aDisp);
98 Window aParent = RootWindow (aDisp, aScreen);
99 XVisualInfo* aVisInfo = NULL;
101 #if defined(HAVE_EGL) || defined(HAVE_GLES2)
102 EGLDisplay anEglDisplay = eglGetDisplay (aDisp);
103 EGLint aVerMajor = 0; EGLint aVerMinor = 0;
104 XVisualInfo aVisInfoTmp; memset (&aVisInfoTmp, 0, sizeof(aVisInfoTmp));
105 if (anEglDisplay != EGL_NO_DISPLAY
106 && eglInitialize (anEglDisplay, &aVerMajor, &aVerMinor) == EGL_TRUE)
108 EGLint aConfigAttribs[] =
116 #if defined(HAVE_GLES2)
117 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
119 EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
124 EGLint aNbConfigs = 0;
125 void* anEglConfig = NULL;
126 for (Standard_Integer aGlesVer = 3; aGlesVer >= 2; --aGlesVer)
128 #if defined(GL_ES_VERSION_2_0)
129 aConfigAttribs[6 * 2 + 1] = aGlesVer == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
137 if (eglChooseConfig (anEglDisplay, aConfigAttribs, &anEglConfig, 1, &aNbConfigs) == EGL_TRUE
138 && anEglConfig != NULL)
144 aConfigAttribs[4 * 2 + 1] = 16; // try config with smaller depth buffer
145 if (eglChooseConfig (anEglDisplay, aConfigAttribs, &anEglConfig, 1, &aNbConfigs) == EGL_TRUE
146 && anEglConfig != NULL)
153 if (anEglConfig != NULL
154 && eglGetConfigAttrib (anEglDisplay, anEglConfig, EGL_NATIVE_VISUAL_ID, (EGLint* )&aVisInfoTmp.visualid) == EGL_TRUE)
157 aVisInfoTmp.screen = DefaultScreen (aDisp);
158 aVisInfo = XGetVisualInfo (aDisp, VisualIDMask | VisualScreenMask, &aVisInfoTmp, &aNbVisuals);
161 if (aVisInfo == NULL)
163 Message::DefaultMessenger()->Send ("Warning: cannot choose Visual using EGL while creating Xw_Window", Message_Warning);
167 if (!glXQueryExtension (myDisplay->GetDisplay(), &aDummy, &aDummy))
169 throw Aspect_WindowDefinitionError("Xw_Window, GLX extension is unavailable");
172 if (myFBConfig == NULL)
174 // FBConfigs were added in GLX version 1.3
177 const bool hasFBCfg = glXQueryVersion (aDisp, &aGlxMajor, &aGlxMinor)
178 && ((aGlxMajor == 1 && aGlxMinor >= 3) || (aGlxMajor > 1));
182 GLXFBConfig* aFBCfgList = NULL;
185 aFBCfgList = glXChooseFBConfig (aDisp, aScreen, TheDoubleBuffFBConfig, &aFBCount);
187 if(aFBCfgList != NULL
190 myFBConfig = aFBCfgList[0];
191 aVisInfo = glXGetVisualFromFBConfig (aDisp, myFBConfig);
197 if (aVisInfo == NULL)
199 aVisInfo = glXChooseVisual (aDisp, aScreen, TheDoubleBuffVisual);
201 if (aVisInfo == NULL)
203 throw Aspect_WindowDefinitionError("Xw_Window, couldn't find compatible Visual (RGBA, double-buffered)");
208 unsigned long aMask = 0;
209 XSetWindowAttributes aWinAttr;
210 memset(&aWinAttr, 0, sizeof(XSetWindowAttributes));
211 aWinAttr.event_mask = ExposureMask | StructureNotifyMask;
212 aMask |= CWEventMask;
213 if (aVisInfo != NULL)
215 aWinAttr.colormap = XCreateColormap(aDisp, aParent, aVisInfo->visual, AllocNone);
217 aWinAttr.border_pixel = 0;
218 aWinAttr.override_redirect = False;
220 myXWindow = XCreateWindow(aDisp, aParent,
221 myXLeft, myYTop, thePxWidth, thePxHeight,
222 0, aVisInfo != NULL ? aVisInfo->depth : CopyFromParent,
224 aVisInfo != NULL ? aVisInfo->visual : CopyFromParent,
225 CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &aWinAttr);
226 if (aVisInfo != NULL)
233 throw Aspect_WindowDefinitionError("Xw_Window, Unable to create window");
237 // if parent - desktop
238 XSizeHints aSizeHints;
239 aSizeHints.x = myXLeft;
240 aSizeHints.y = myYTop;
241 aSizeHints.flags = PPosition;
242 aSizeHints.width = thePxWidth;
243 aSizeHints.height = thePxHeight;
244 aSizeHints.flags |= PSize;
245 XSetStandardProperties (aDisp, myXWindow, theTitle, theTitle, None,
246 NULL, 0, &aSizeHints);
248 /*XTextProperty aTitleProperty;
249 aTitleProperty.encoding = None;
250 char* aTitle = (char* )theTitle;
251 Xutf8TextListToTextProperty(aDisp, &aTitle, 1, XUTF8StringStyle, &aTitleProperty);
252 XSetWMName (aDisp, myXWindow, &aTitleProperty);
253 XSetWMProperties(aDisp, myXWindow, &aTitleProperty, &aTitleProperty, NULL, 0, NULL, NULL, NULL);*/
258 // =======================================================================
259 // function : Xw_Window
261 // =======================================================================
262 Xw_Window::Xw_Window (const Handle(Aspect_DisplayConnection)& theXDisplay,
263 const Window theXWin,
264 const Aspect_FBConfig theFBConfig)
266 myDisplay (theXDisplay),
268 myFBConfig (theFBConfig),
273 myIsOwnWin (Standard_False)
277 throw Aspect_WindowDefinitionError("Xw_Window, given invalid X window");
280 else if (theXDisplay.IsNull())
282 throw Aspect_WindowDefinitionError("Xw_Window, X Display connection is undefined");
285 #if !defined(HAVE_EGL) && !defined(HAVE_GLES2)
287 if (!glXQueryExtension (myDisplay->GetDisplay(), &aDummy, &aDummy))
290 throw Aspect_WindowDefinitionError("Xw_Window, GLX extension is unavailable");
295 Display* aDisp = myDisplay->GetDisplay();
297 XWindowAttributes aWinAttr;
298 XGetWindowAttributes (aDisp, myXWindow, &aWinAttr);
299 XVisualInfo aVisInfoTmp;
300 aVisInfoTmp.visualid = aWinAttr.visual->visualid;
301 aVisInfoTmp.screen = DefaultScreen (aDisp);
303 XVisualInfo* aVisInfo = XGetVisualInfo (aDisp, VisualIDMask | VisualScreenMask, &aVisInfoTmp, &aNbItems);
304 if (aVisInfo == NULL)
306 throw Aspect_WindowDefinitionError("Xw_Window, Visual is unavailable");
314 // =======================================================================
315 // function : ~Xw_Window
317 // =======================================================================
318 Xw_Window::~Xw_Window()
320 if (myIsOwnWin && myXWindow != 0 && !myDisplay.IsNull())
322 XDestroyWindow (myDisplay->GetDisplay(), myXWindow);
326 // =======================================================================
327 // function : XWindow
329 // =======================================================================
330 Window Xw_Window::XWindow() const
335 // =======================================================================
336 // function : IsMapped
338 // =======================================================================
339 Standard_Boolean Xw_Window::IsMapped() const
345 else if (IsVirtual())
347 return Standard_True;
350 XFlush (myDisplay->GetDisplay());
351 XWindowAttributes aWinAttr;
352 XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
353 return aWinAttr.map_state == IsUnviewable
354 || aWinAttr.map_state == IsViewable;
357 // =======================================================================
360 // =======================================================================
361 void Xw_Window::Map() const
363 if (IsVirtual() || myXWindow == 0)
368 XMapWindow (myDisplay->GetDisplay(), myXWindow);
369 XFlush (myDisplay->GetDisplay());
372 // =======================================================================
375 // =======================================================================
376 void Xw_Window::Unmap() const
378 if (IsVirtual() || myXWindow == 0)
383 XIconifyWindow (myDisplay->GetDisplay(), myXWindow, DefaultScreen(myDisplay->GetDisplay()));
386 // =======================================================================
387 // function : DoResize
389 // =======================================================================
390 Aspect_TypeOfResize Xw_Window::DoResize() const
394 return Aspect_TOR_UNKNOWN;
397 XFlush (myDisplay->GetDisplay());
398 XWindowAttributes aWinAttr;
399 XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
400 if (aWinAttr.map_state == IsUnmapped)
402 return Aspect_TOR_UNKNOWN;
405 Standard_Integer aMask = 0;
406 Aspect_TypeOfResize aMode = Aspect_TOR_UNKNOWN;
408 if (Abs (aWinAttr.x - myXLeft ) > 2) aMask |= 1;
409 if (Abs ((aWinAttr.x + aWinAttr.width) - myXRight ) > 2) aMask |= 2;
410 if (Abs (aWinAttr.y - myYTop ) > 2) aMask |= 4;
411 if (Abs ((aWinAttr.y + aWinAttr.height) - myYBottom) > 2) aMask |= 8;
414 case 0: aMode = Aspect_TOR_NO_BORDER; break;
415 case 1: aMode = Aspect_TOR_LEFT_BORDER; break;
416 case 2: aMode = Aspect_TOR_RIGHT_BORDER; break;
417 case 4: aMode = Aspect_TOR_TOP_BORDER; break;
418 case 5: aMode = Aspect_TOR_LEFT_AND_TOP_BORDER; break;
419 case 6: aMode = Aspect_TOR_TOP_AND_RIGHT_BORDER; break;
420 case 8: aMode = Aspect_TOR_BOTTOM_BORDER; break;
421 case 9: aMode = Aspect_TOR_BOTTOM_AND_LEFT_BORDER; break;
422 case 10: aMode = Aspect_TOR_RIGHT_AND_BOTTOM_BORDER; break;
426 *((Standard_Integer* )&myXLeft ) = aWinAttr.x;
427 *((Standard_Integer* )&myXRight ) = aWinAttr.x + aWinAttr.width;
428 *((Standard_Integer* )&myYTop ) = aWinAttr.y;
429 *((Standard_Integer* )&myYBottom ) = aWinAttr.y + aWinAttr.height;
433 // =======================================================================
434 // function : DoMapping
436 // =======================================================================
437 Standard_Boolean Xw_Window::DoMapping() const
439 return Standard_True; // IsMapped()
442 // =======================================================================
445 // =======================================================================
446 Standard_Real Xw_Window::Ratio() const
453 XFlush (myDisplay->GetDisplay());
454 XWindowAttributes aWinAttr;
455 XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
456 return Standard_Real(aWinAttr.width) / Standard_Real(aWinAttr.height);
459 // =======================================================================
460 // function : Position
462 // =======================================================================
463 void Xw_Window::Position (Standard_Integer& X1, Standard_Integer& Y1,
464 Standard_Integer& X2, Standard_Integer& Y2) const
471 XFlush (myDisplay->GetDisplay());
472 XWindowAttributes anAttributes;
473 XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &anAttributes);
475 XTranslateCoordinates (myDisplay->GetDisplay(), anAttributes.root, myXWindow,
476 0, 0, &anAttributes.x, &anAttributes.y, &aChild);
478 X1 = -anAttributes.x;
479 X2 = X1 + anAttributes.width;
480 Y1 = -anAttributes.y;
481 Y2 = Y1 + anAttributes.height;
484 // =======================================================================
487 // =======================================================================
488 void Xw_Window::Size (Standard_Integer& theWidth,
489 Standard_Integer& theHeight) const
496 XFlush (myDisplay->GetDisplay());
497 XWindowAttributes aWinAttr;
498 XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
499 theWidth = aWinAttr.width;
500 theHeight = aWinAttr.height;
503 // =======================================================================
504 // function : InvalidateContent
506 // =======================================================================
507 void Xw_Window::InvalidateContent (const Handle(Aspect_DisplayConnection)& theDisp)
514 const Handle(Aspect_DisplayConnection)& aDisp = !theDisp.IsNull() ? theDisp : myDisplay;
515 Display* aDispX = aDisp->GetDisplay();
518 memset (&anEvent, 0, sizeof(anEvent));
519 anEvent.type = Expose;
520 anEvent.xexpose.window = myXWindow;
521 XSendEvent (aDispX, myXWindow, False, ExposureMask, &anEvent);
525 #endif // Win32 or Mac OS X