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 |
25 | namespace |
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 | // ======================================================================= |
57 | Xw_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 | // ======================================================================= |
177 | Xw_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 | // ======================================================================= |
233 | void 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 | // ======================================================================= |
245 | Window Xw_Window::XWindow() const |
7fd59977 |
246 | { |
ed97f43c |
247 | return myXWindow; |
7fd59977 |
248 | } |
249 | |
ed97f43c |
250 | // ======================================================================= |
251 | // function : IsMapped |
252 | // purpose : |
253 | // ======================================================================= |
254 | Standard_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 | // ======================================================================= |
276 | void 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 | // ======================================================================= |
291 | void 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 | // ======================================================================= |
305 | Aspect_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 | // ======================================================================= |
352 | Standard_Boolean Xw_Window::DoMapping() const |
353 | { |
354 | return Standard_True; // IsMapped() |
7fd59977 |
355 | } |
356 | |
ed97f43c |
357 | // ======================================================================= |
358 | // function : Ratio |
359 | // purpose : |
360 | // ======================================================================= |
361 | Quantity_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 | // ======================================================================= |
378 | void 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 | // ======================================================================= |
403 | void 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 |