0026823: Configuration - use EGL on another platform without GLX
[occt.git] / src / Xw / Xw_Window.cxx
CommitLineData
ed97f43c 1// Created on: 2013-04-06
2// Created by: Kirill Gavrilov
d5f74e42 3// Copyright (c) 2013-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 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
973c2be1 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.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
b311480e 15
ed97f43c 16#include <Xw_Window.hxx>
7fd59977 17
d8d01f6e 18#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__)
7fd59977 19
7fd59977 20#include <Aspect_Convert.hxx>
ed97f43c 21#include <Aspect_WindowDefinitionError.hxx>
7fd59977 22
ed97f43c 23#include <GL/glx.h>
7fd59977 24
ed97f43c 25namespace
26{
7fd59977 27
a6eb515f 28 //! Search for RGBA double-buffered visual with stencil buffer.
b6bf4ec1 29 static int TheDoubleBuffVisual[] =
ed97f43c 30 {
31 GLX_RGBA,
32 GLX_DEPTH_SIZE, 16,
a6eb515f 33 GLX_STENCIL_SIZE, 1,
ed97f43c 34 GLX_DOUBLEBUFFER,
35 None
36 };
37
b6bf4ec1 38 //! Search for RGBA double-buffered visual with stencil buffer.
39 static int TheDoubleBuffFBConfig[] =
40 {
41 GLX_X_RENDERABLE, True,
42 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
43 GLX_RENDER_TYPE, GLX_RGBA_BIT,
44 GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
45 GLX_DEPTH_SIZE, 16,
46 GLX_STENCIL_SIZE, 1,
47 GLX_DOUBLEBUFFER, True,
48 None
49 };
ed97f43c 50
b6bf4ec1 51}
ed97f43c 52
53// =======================================================================
54// function : Xw_Window
55// purpose :
56// =======================================================================
57Xw_Window::Xw_Window (const Handle(Aspect_DisplayConnection)& theXDisplay,
58 const Standard_CString theTitle,
59 const Standard_Integer thePxLeft,
60 const Standard_Integer thePxTop,
61 const Standard_Integer thePxWidth,
b6bf4ec1 62 const Standard_Integer thePxHeight,
63 const Aspect_FBConfig theFBConfig)
ed97f43c 64: Aspect_Window(),
65 myDisplay (theXDisplay),
66 myXWindow (0),
b6bf4ec1 67 myFBConfig (theFBConfig),
ed97f43c 68 myXLeft (thePxLeft),
69 myYTop (thePxTop),
70 myXRight (thePxLeft + thePxWidth),
71 myYBottom (thePxTop + thePxHeight),
72 myIsOwnWin (Standard_True)
7fd59977 73{
ed97f43c 74 int aDummy = 0;
75 if (thePxWidth <= 0 || thePxHeight <= 0)
76 {
77 Aspect_WindowDefinitionError::Raise ("Xw_Window, Coordinate(s) out of range");
78 }
79 else if (theXDisplay.IsNull())
80 {
81 Aspect_WindowDefinitionError::Raise ("Xw_Window, X Display connection is undefined");
82 return;
83 }
84 else if (!glXQueryExtension (myDisplay->GetDisplay(), &aDummy, &aDummy))
85 {
86 Aspect_WindowDefinitionError::Raise ("Xw_Window, GLX extension is unavailable");
87 return;
7fd59977 88 }
89
ed97f43c 90 Display* aDisp = myDisplay->GetDisplay();
91 int aScreen = DefaultScreen(aDisp);
92 Window aParent = RootWindow (aDisp, aScreen);
b6bf4ec1 93 XVisualInfo* aVisInfo = NULL;
7fd59977 94
b6bf4ec1 95 if (myFBConfig == NULL)
96 {
97 // FBConfigs were added in GLX version 1.3
98 int aGlxMajor = 0;
99 int aGlxMinor = 0;
100 const bool hasFBCfg = glXQueryVersion (aDisp, &aGlxMajor, &aGlxMinor)
101 && ((aGlxMajor == 1 && aGlxMinor >= 3) || (aGlxMajor > 1));
102 if (hasFBCfg)
103 {
104 int aFBCount = 0;
105 GLXFBConfig* aFBCfgList = NULL;
106 if (hasFBCfg)
107 {
108 aFBCfgList = glXChooseFBConfig (aDisp, aScreen, TheDoubleBuffFBConfig, &aFBCount);
109 }
110 if(aFBCfgList != NULL
111 && aFBCount >= 1)
112 {
113 myFBConfig = aFBCfgList[0];
114 aVisInfo = glXGetVisualFromFBConfig (aDisp, myFBConfig);
115 }
116 XFree (aFBCfgList);
117 }
118 }
119
120 if (aVisInfo == NULL)
121 {
122 aVisInfo = glXChooseVisual (aDisp, aScreen, TheDoubleBuffVisual);
123 }
ed97f43c 124 if (aVisInfo == NULL)
125 {
126 Aspect_WindowDefinitionError::Raise ("Xw_Window, couldn't find compatible Visual (RGBA, double-buffered)");
127 return;
128 }
7fd59977 129
ed97f43c 130 unsigned long aMask = 0;
131 XSetWindowAttributes aWinAttr;
132 memset(&aWinAttr, 0, sizeof(XSetWindowAttributes));
133 aWinAttr.event_mask = ExposureMask | StructureNotifyMask;
134 aMask |= CWEventMask;
135 aWinAttr.colormap = XCreateColormap(aDisp, aParent, aVisInfo->visual, AllocNone);
136 aWinAttr.border_pixel = 0;
137 aWinAttr.override_redirect = False;
138
139 myXWindow = XCreateWindow(aDisp, aParent,
140 myXLeft, myYTop, thePxWidth, thePxHeight,
141 0, aVisInfo->depth,
142 InputOutput,
143 aVisInfo->visual,
144 CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &aWinAttr);
145 XFree (aVisInfo); aVisInfo = NULL;
146 if (myXWindow == 0)
147 {
148 Aspect_WindowDefinitionError::Raise ("Xw_Window, Unable to create window");
149 return;
150 }
7fd59977 151
ed97f43c 152 // if parent - desktop
153 XSizeHints aSizeHints;
154 aSizeHints.x = myXLeft;
155 aSizeHints.y = myYTop;
156 aSizeHints.flags = PPosition;
157 aSizeHints.width = thePxWidth;
158 aSizeHints.height = thePxHeight;
159 aSizeHints.flags |= PSize;
160 XSetStandardProperties (aDisp, myXWindow, theTitle, theTitle, None,
161 NULL, 0, &aSizeHints);
162
163 /*XTextProperty aTitleProperty;
164 aTitleProperty.encoding = None;
165 char* aTitle = (char* )theTitle;
166 Xutf8TextListToTextProperty(aDisp, &aTitle, 1, XUTF8StringStyle, &aTitleProperty);
167 XSetWMName (aDisp, myXWindow, &aTitleProperty);
168 XSetWMProperties(aDisp, myXWindow, &aTitleProperty, &aTitleProperty, NULL, 0, NULL, NULL, NULL);*/
169
170 XFlush (aDisp);
7fd59977 171}
172
ed97f43c 173// =======================================================================
174// function : Xw_Window
175// purpose :
176// =======================================================================
177Xw_Window::Xw_Window (const Handle(Aspect_DisplayConnection)& theXDisplay,
b6bf4ec1 178 const Window theXWin,
179 const Aspect_FBConfig theFBConfig)
dc3fe572 180: Aspect_Window(),
ed97f43c 181 myDisplay (theXDisplay),
182 myXWindow (theXWin),
b6bf4ec1 183 myFBConfig (theFBConfig),
ed97f43c 184 myXLeft (0),
185 myYTop (0),
186 myXRight (512),
187 myYBottom (512),
188 myIsOwnWin (Standard_False)
7fd59977 189{
ed97f43c 190 int aDummy = 0;
191 if (theXWin == 0)
192 {
193 Aspect_WindowDefinitionError::Raise ("Xw_Window, given invalid X window");
194 return;
195 }
196 else if (theXDisplay.IsNull())
197 {
198 Aspect_WindowDefinitionError::Raise ("Xw_Window, X Display connection is undefined");
199 return;
200 }
201 else if (!glXQueryExtension (myDisplay->GetDisplay(), &aDummy, &aDummy))
202 {
203 myXWindow = 0;
204 Aspect_WindowDefinitionError::Raise ("Xw_Window, GLX extension is unavailable");
205 return;
206 }
7fd59977 207
ed97f43c 208 Display* aDisp = myDisplay->GetDisplay();
209
210 XWindowAttributes aWinAttr;
211 XGetWindowAttributes (aDisp, myXWindow, &aWinAttr);
212 const int aScreen = DefaultScreen (aDisp);
213 const long aVisInfoMask = VisualIDMask | VisualScreenMask;
214 XVisualInfo aVisInfoTmp;
215 aVisInfoTmp.visualid = aWinAttr.visual->visualid;
216 aVisInfoTmp.screen = aScreen;
217 int aNbItems = 0;
218 XVisualInfo* aVisInfo = XGetVisualInfo (aDisp, aVisInfoMask, &aVisInfoTmp, &aNbItems);
219 if (aVisInfo == NULL)
220 {
221 Aspect_WindowDefinitionError::Raise ("Xw_Window, Visual is unavailable");
222 return;
223 }
224 XFree (aVisInfo);
7fd59977 225
ed97f43c 226 DoResize();
7fd59977 227}
228
ed97f43c 229// =======================================================================
230// function : Destroy
231// purpose :
232// =======================================================================
233void Xw_Window::Destroy()
7fd59977 234{
ed97f43c 235 if (myIsOwnWin && myXWindow != 0 && !myDisplay.IsNull())
7fd59977 236 {
ed97f43c 237 XDestroyWindow (myDisplay->GetDisplay(), myXWindow);
7fd59977 238 }
7fd59977 239}
240
ed97f43c 241// =======================================================================
242// function : XWindow
243// purpose :
244// =======================================================================
245Window Xw_Window::XWindow() const
7fd59977 246{
ed97f43c 247 return myXWindow;
7fd59977 248}
249
ed97f43c 250// =======================================================================
251// function : IsMapped
252// purpose :
253// =======================================================================
254Standard_Boolean Xw_Window::IsMapped() const
7fd59977 255{
ed97f43c 256 if (myXWindow == 0)
257 {
258 return false;
dc3fe572 259 }
ed97f43c 260 else if (IsVirtual())
261 {
262 return Standard_True;
7fd59977 263 }
dc3fe572 264
ed97f43c 265 XFlush (myDisplay->GetDisplay());
266 XWindowAttributes aWinAttr;
267 XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
268 return aWinAttr.map_state == IsUnviewable
269 || aWinAttr.map_state == IsViewable;
7fd59977 270}
271
ed97f43c 272// =======================================================================
273// function : Map
274// purpose :
275// =======================================================================
276void Xw_Window::Map() const
7fd59977 277{
ed97f43c 278 if (IsVirtual() || myXWindow == 0)
279 {
280 return;
7fd59977 281 }
282
ed97f43c 283 XMapWindow (myDisplay->GetDisplay(), myXWindow);
284 XFlush (myDisplay->GetDisplay());
7fd59977 285}
286
ed97f43c 287// =======================================================================
288// function : Unmap
289// purpose :
290// =======================================================================
291void Xw_Window::Unmap() const
292{
293 if (IsVirtual() || myXWindow == 0)
294 {
295 return;
7fd59977 296 }
7fd59977 297
ed97f43c 298 XIconifyWindow (myDisplay->GetDisplay(), myXWindow, DefaultScreen(myDisplay->GetDisplay()));
7fd59977 299}
300
ed97f43c 301// =======================================================================
302// function : DoResize
303// purpose :
304// =======================================================================
305Aspect_TypeOfResize Xw_Window::DoResize() const
306{
307 if (myXWindow == 0)
308 {
309 return Aspect_TOR_UNKNOWN;
310 }
7fd59977 311
ed97f43c 312 XFlush (myDisplay->GetDisplay());
313 XWindowAttributes aWinAttr;
314 XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
315 if (aWinAttr.map_state == IsUnmapped)
316 {
317 return Aspect_TOR_UNKNOWN;
318 }
7fd59977 319
ed97f43c 320 Standard_Integer aMask = 0;
321 Aspect_TypeOfResize aMode = Aspect_TOR_UNKNOWN;
7fd59977 322
ed97f43c 323 if (Abs (aWinAttr.x - myXLeft ) > 2) aMask |= 1;
324 if (Abs ((aWinAttr.x + aWinAttr.width) - myXRight ) > 2) aMask |= 2;
325 if (Abs (aWinAttr.y - myYTop ) > 2) aMask |= 4;
326 if (Abs ((aWinAttr.y + aWinAttr.height) - myYBottom) > 2) aMask |= 8;
327 switch (aMask)
328 {
329 case 0: aMode = Aspect_TOR_NO_BORDER; break;
330 case 1: aMode = Aspect_TOR_LEFT_BORDER; break;
331 case 2: aMode = Aspect_TOR_RIGHT_BORDER; break;
332 case 4: aMode = Aspect_TOR_TOP_BORDER; break;
333 case 5: aMode = Aspect_TOR_LEFT_AND_TOP_BORDER; break;
334 case 6: aMode = Aspect_TOR_TOP_AND_RIGHT_BORDER; break;
335 case 8: aMode = Aspect_TOR_BOTTOM_BORDER; break;
336 case 9: aMode = Aspect_TOR_BOTTOM_AND_LEFT_BORDER; break;
337 case 10: aMode = Aspect_TOR_RIGHT_AND_BOTTOM_BORDER; break;
338 default: break;
339 }
7fd59977 340
ed97f43c 341 *((Standard_Integer* )&myXLeft ) = aWinAttr.x;
342 *((Standard_Integer* )&myXRight ) = aWinAttr.x + aWinAttr.width;
343 *((Standard_Integer* )&myYTop ) = aWinAttr.y;
344 *((Standard_Integer* )&myYBottom ) = aWinAttr.y + aWinAttr.height;
345 return aMode;
7fd59977 346}
7fd59977 347
ed97f43c 348// =======================================================================
349// function : DoMapping
350// purpose :
351// =======================================================================
352Standard_Boolean Xw_Window::DoMapping() const
353{
354 return Standard_True; // IsMapped()
7fd59977 355}
356
ed97f43c 357// =======================================================================
358// function : Ratio
359// purpose :
360// =======================================================================
361Quantity_Ratio Xw_Window::Ratio() const
362{
363 if (myXWindow == 0)
364 {
365 return 1.0;
366 }
7fd59977 367
ed97f43c 368 XFlush (myDisplay->GetDisplay());
369 XWindowAttributes aWinAttr;
370 XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
371 return Quantity_Ratio(aWinAttr.width) / Quantity_Ratio(aWinAttr.height);
7fd59977 372}
373
ed97f43c 374// =======================================================================
375// function : Position
376// purpose :
377// =======================================================================
378void Xw_Window::Position (Standard_Integer& X1, Standard_Integer& Y1,
379 Standard_Integer& X2, Standard_Integer& Y2) const
380{
18d715bd 381 if (myXWindow == 0)
382 {
383 return;
384 }
385
386 XFlush (myDisplay->GetDisplay());
387 XWindowAttributes anAttributes;
388 XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &anAttributes);
389 Window aChild;
390 XTranslateCoordinates (myDisplay->GetDisplay(), anAttributes.root, myXWindow,
391 0, 0, &anAttributes.x, &anAttributes.y, &aChild);
392
393 X1 = -anAttributes.x;
394 X2 = X1 + anAttributes.width;
395 Y1 = -anAttributes.y;
396 Y2 = Y1 + anAttributes.height;
7fd59977 397}
398
ed97f43c 399// =======================================================================
400// function : Size
401// purpose :
402// =======================================================================
403void Xw_Window::Size (Standard_Integer& theWidth,
404 Standard_Integer& theHeight) const
405{
406 if (myXWindow == 0)
407 {
408 return;
409 }
7fd59977 410
ed97f43c 411 XFlush (myDisplay->GetDisplay());
412 XWindowAttributes aWinAttr;
413 XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
414 theWidth = aWinAttr.width;
415 theHeight = aWinAttr.height;
7fd59977 416}
417
ed97f43c 418#endif // Win32 or Mac OS X