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