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 |
25 | IMPLEMENT_STANDARD_RTTIEXT(Xw_Window,Aspect_Window) |
26 | |
ed97f43c |
27 | namespace |
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 | // ======================================================================= |
59 | Xw_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 | { |
79 | Aspect_WindowDefinitionError::Raise ("Xw_Window, Coordinate(s) out of range"); |
80 | } |
81 | else if (theXDisplay.IsNull()) |
82 | { |
83 | Aspect_WindowDefinitionError::Raise ("Xw_Window, X Display connection is undefined"); |
84 | return; |
85 | } |
86 | else if (!glXQueryExtension (myDisplay->GetDisplay(), &aDummy, &aDummy)) |
87 | { |
88 | Aspect_WindowDefinitionError::Raise ("Xw_Window, GLX extension is unavailable"); |
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 | { |
128 | Aspect_WindowDefinitionError::Raise ("Xw_Window, couldn't find compatible Visual (RGBA, double-buffered)"); |
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 | { |
150 | Aspect_WindowDefinitionError::Raise ("Xw_Window, Unable to create window"); |
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 | // ======================================================================= |
179 | Xw_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 | { |
195 | Aspect_WindowDefinitionError::Raise ("Xw_Window, given invalid X window"); |
196 | return; |
197 | } |
198 | else if (theXDisplay.IsNull()) |
199 | { |
200 | Aspect_WindowDefinitionError::Raise ("Xw_Window, X Display connection is undefined"); |
201 | return; |
202 | } |
203 | else if (!glXQueryExtension (myDisplay->GetDisplay(), &aDummy, &aDummy)) |
204 | { |
205 | myXWindow = 0; |
206 | Aspect_WindowDefinitionError::Raise ("Xw_Window, GLX extension is unavailable"); |
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 | { |
223 | Aspect_WindowDefinitionError::Raise ("Xw_Window, Visual is unavailable"); |
224 | return; |
225 | } |
226 | XFree (aVisInfo); |
7fd59977 |
227 | |
ed97f43c |
228 | DoResize(); |
7fd59977 |
229 | } |
230 | |
ed97f43c |
231 | // ======================================================================= |
232 | // function : Destroy |
233 | // purpose : |
234 | // ======================================================================= |
235 | void Xw_Window::Destroy() |
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 | // ======================================================================= |
247 | Window Xw_Window::XWindow() const |
7fd59977 |
248 | { |
ed97f43c |
249 | return myXWindow; |
7fd59977 |
250 | } |
251 | |
ed97f43c |
252 | // ======================================================================= |
253 | // function : IsMapped |
254 | // purpose : |
255 | // ======================================================================= |
256 | Standard_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 | // ======================================================================= |
278 | void 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 | // ======================================================================= |
293 | void 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 | // ======================================================================= |
307 | Aspect_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 | // ======================================================================= |
354 | Standard_Boolean Xw_Window::DoMapping() const |
355 | { |
356 | return Standard_True; // IsMapped() |
7fd59977 |
357 | } |
358 | |
ed97f43c |
359 | // ======================================================================= |
360 | // function : Ratio |
361 | // purpose : |
362 | // ======================================================================= |
363 | Quantity_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 | // ======================================================================= |
380 | void 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 | // ======================================================================= |
405 | void 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 |