0022590: Migration to FreeImage - revision of Xw and WNT packages
[occt.git] / src / Xw / Xw_Window.cxx
1 // Created on: 2013-04-06
2 // Created by: Kirill Gavrilov
3 // Copyright (c) 2013 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20 #include <Xw_Window.hxx>
21
22 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
23
24 #include <Aspect_Convert.hxx>
25 #include <Aspect_WindowDefinitionError.hxx>
26
27 #include <GL/glx.h>
28
29 namespace
30 {
31
32   //! Search for RGBA double-buffered visual
33   static int TheDoubleBuff[] =
34   {
35     GLX_RGBA,
36     GLX_DEPTH_SIZE, 16,
37     GLX_DOUBLEBUFFER,
38     None
39   };
40
41 };
42
43 IMPLEMENT_STANDARD_HANDLE (Xw_Window, Aspect_Window)
44 IMPLEMENT_STANDARD_RTTIEXT(Xw_Window, Aspect_Window)
45
46 // =======================================================================
47 // function : Xw_Window
48 // purpose  :
49 // =======================================================================
50 Xw_Window::Xw_Window (const Handle(Aspect_DisplayConnection)& theXDisplay,
51                       const Standard_CString theTitle,
52                       const Standard_Integer thePxLeft,
53                       const Standard_Integer thePxTop,
54                       const Standard_Integer thePxWidth,
55                       const Standard_Integer thePxHeight)
56 : Aspect_Window(),
57   myDisplay  (theXDisplay),
58   myXWindow  (0),
59   myXLeft    (thePxLeft),
60   myYTop     (thePxTop),
61   myXRight   (thePxLeft + thePxWidth),
62   myYBottom  (thePxTop + thePxHeight),
63   myIsOwnWin (Standard_True)
64 {
65   int aDummy = 0;
66   if (thePxWidth <= 0 || thePxHeight <= 0)
67   {
68     Aspect_WindowDefinitionError::Raise ("Xw_Window, Coordinate(s) out of range");
69   }
70   else if (theXDisplay.IsNull())
71   {
72     Aspect_WindowDefinitionError::Raise ("Xw_Window, X Display connection is undefined");
73     return;
74   }
75   else if (!glXQueryExtension (myDisplay->GetDisplay(), &aDummy, &aDummy))
76   {
77     Aspect_WindowDefinitionError::Raise ("Xw_Window, GLX extension is unavailable");
78     return;
79   }
80
81   Display* aDisp   = myDisplay->GetDisplay();
82   int      aScreen = DefaultScreen(aDisp);
83   Window   aParent = RootWindow   (aDisp, aScreen);
84
85   XVisualInfo* aVisInfo = glXChooseVisual (aDisp, aScreen, TheDoubleBuff);
86   if (aVisInfo == NULL)
87   {
88     Aspect_WindowDefinitionError::Raise ("Xw_Window, couldn't find compatible Visual (RGBA, double-buffered)");
89     return;
90   }
91
92   unsigned long aMask = 0;
93   XSetWindowAttributes aWinAttr;
94   memset(&aWinAttr, 0, sizeof(XSetWindowAttributes));
95   aWinAttr.event_mask = ExposureMask | StructureNotifyMask;
96   aMask |= CWEventMask;
97   aWinAttr.colormap = XCreateColormap(aDisp, aParent, aVisInfo->visual, AllocNone);
98   aWinAttr.border_pixel = 0;
99   aWinAttr.override_redirect = False;
100
101   myXWindow = XCreateWindow(aDisp, aParent,
102                             myXLeft, myYTop, thePxWidth, thePxHeight,
103                             0, aVisInfo->depth,
104                             InputOutput,
105                             aVisInfo->visual,
106                             CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &aWinAttr);
107   XFree (aVisInfo); aVisInfo = NULL;
108   if (myXWindow == 0)
109   {
110     Aspect_WindowDefinitionError::Raise ("Xw_Window, Unable to create window");
111     return;
112   }
113
114   // if parent - desktop
115   XSizeHints aSizeHints;
116   aSizeHints.x      = myXLeft;
117   aSizeHints.y      = myYTop;
118   aSizeHints.flags  = PPosition;
119   aSizeHints.width  = thePxWidth;
120   aSizeHints.height = thePxHeight;
121   aSizeHints.flags |= PSize;
122   XSetStandardProperties (aDisp, myXWindow, theTitle, theTitle, None,
123                           NULL, 0, &aSizeHints);
124
125   /*XTextProperty aTitleProperty;
126   aTitleProperty.encoding = None;
127   char* aTitle = (char* )theTitle;
128   Xutf8TextListToTextProperty(aDisp, &aTitle, 1, XUTF8StringStyle, &aTitleProperty);
129   XSetWMName      (aDisp, myXWindow, &aTitleProperty);
130   XSetWMProperties(aDisp, myXWindow, &aTitleProperty, &aTitleProperty, NULL, 0, NULL, NULL, NULL);*/
131
132   XFlush (aDisp);
133 }
134
135 // =======================================================================
136 // function : Xw_Window
137 // purpose  :
138 // =======================================================================
139 Xw_Window::Xw_Window (const Handle(Aspect_DisplayConnection)& theXDisplay,
140                       const Window theXWin)
141 : Aspect_Window(),
142   myDisplay  (theXDisplay),
143   myXWindow  (theXWin),
144   myXLeft    (0),
145   myYTop     (0),
146   myXRight   (512),
147   myYBottom  (512),
148   myIsOwnWin (Standard_False)
149 {
150   int aDummy = 0;
151   if (theXWin == 0)
152   {
153     Aspect_WindowDefinitionError::Raise ("Xw_Window, given invalid X window");
154     return;
155   }
156   else if (theXDisplay.IsNull())
157   {
158     Aspect_WindowDefinitionError::Raise ("Xw_Window, X Display connection is undefined");
159     return;
160   }
161   else if (!glXQueryExtension (myDisplay->GetDisplay(), &aDummy, &aDummy))
162   {
163     myXWindow = 0;
164     Aspect_WindowDefinitionError::Raise ("Xw_Window, GLX extension is unavailable");
165     return;
166   }
167
168   Display* aDisp = myDisplay->GetDisplay();
169
170   XWindowAttributes aWinAttr;
171   XGetWindowAttributes (aDisp, myXWindow, &aWinAttr);
172   const int  aScreen      = DefaultScreen (aDisp);
173   const long aVisInfoMask = VisualIDMask | VisualScreenMask;
174   XVisualInfo aVisInfoTmp;
175   aVisInfoTmp.visualid = aWinAttr.visual->visualid;
176   aVisInfoTmp.screen   = aScreen;
177   int aNbItems = 0;
178   XVisualInfo* aVisInfo = XGetVisualInfo (aDisp, aVisInfoMask, &aVisInfoTmp, &aNbItems);
179   if (aVisInfo == NULL)
180   {
181     Aspect_WindowDefinitionError::Raise ("Xw_Window, Visual is unavailable");
182     return;
183   }
184   XFree (aVisInfo);
185
186   DoResize();
187 }
188
189 // =======================================================================
190 // function : Destroy
191 // purpose  :
192 // =======================================================================
193 void Xw_Window::Destroy()
194 {
195   if (myIsOwnWin && myXWindow != 0 && !myDisplay.IsNull())
196   {
197     XDestroyWindow (myDisplay->GetDisplay(), myXWindow);
198   }
199 }
200
201 // =======================================================================
202 // function : XWindow
203 // purpose  :
204 // =======================================================================
205 Window Xw_Window::XWindow() const
206 {
207   return myXWindow;
208 }
209
210 // =======================================================================
211 // function : IsMapped
212 // purpose  :
213 // =======================================================================
214 Standard_Boolean Xw_Window::IsMapped() const
215 {
216   if (myXWindow == 0)
217   {
218     return false;
219   }
220   else if (IsVirtual())
221   {
222     return Standard_True;
223   }
224
225   XFlush (myDisplay->GetDisplay());
226   XWindowAttributes aWinAttr;
227   XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
228   return aWinAttr.map_state == IsUnviewable
229       || aWinAttr.map_state == IsViewable;
230 }
231
232 // =======================================================================
233 // function : Map
234 // purpose  :
235 // =======================================================================
236 void Xw_Window::Map() const
237 {
238   if (IsVirtual() || myXWindow == 0)
239   {
240     return;
241   }
242
243   XMapWindow (myDisplay->GetDisplay(), myXWindow);
244   XFlush (myDisplay->GetDisplay());
245 }
246
247 // =======================================================================
248 // function : Unmap
249 // purpose  :
250 // =======================================================================
251 void Xw_Window::Unmap() const
252 {
253   if (IsVirtual() || myXWindow == 0)
254   {
255     return;
256   }
257
258   XIconifyWindow (myDisplay->GetDisplay(), myXWindow, DefaultScreen(myDisplay->GetDisplay()));
259 }
260
261 // =======================================================================
262 // function : DoResize
263 // purpose  :
264 // =======================================================================
265 Aspect_TypeOfResize Xw_Window::DoResize() const
266 {
267   if (myXWindow == 0)
268   {
269     return Aspect_TOR_UNKNOWN;
270   }
271
272   XFlush (myDisplay->GetDisplay());
273   XWindowAttributes aWinAttr;
274   XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
275   if (aWinAttr.map_state == IsUnmapped)
276   {
277     return Aspect_TOR_UNKNOWN;
278   }
279
280   Standard_Integer aMask = 0;
281   Aspect_TypeOfResize aMode = Aspect_TOR_UNKNOWN;
282
283   if (Abs (aWinAttr.x                     - myXLeft  ) > 2) aMask |= 1;
284   if (Abs ((aWinAttr.x + aWinAttr.width)  - myXRight ) > 2) aMask |= 2;
285   if (Abs (aWinAttr.y                     - myYTop   ) > 2) aMask |= 4;
286   if (Abs ((aWinAttr.y + aWinAttr.height) - myYBottom) > 2) aMask |= 8;
287   switch (aMask)
288   {
289     case 0:  aMode = Aspect_TOR_NO_BORDER;               break;
290     case 1:  aMode = Aspect_TOR_LEFT_BORDER;             break;
291     case 2:  aMode = Aspect_TOR_RIGHT_BORDER;            break;
292     case 4:  aMode = Aspect_TOR_TOP_BORDER;              break;
293     case 5:  aMode = Aspect_TOR_LEFT_AND_TOP_BORDER;     break;
294     case 6:  aMode = Aspect_TOR_TOP_AND_RIGHT_BORDER;    break;
295     case 8:  aMode = Aspect_TOR_BOTTOM_BORDER;           break;
296     case 9:  aMode = Aspect_TOR_BOTTOM_AND_LEFT_BORDER;  break;
297     case 10: aMode = Aspect_TOR_RIGHT_AND_BOTTOM_BORDER; break;
298     default: break;
299   }
300
301   *((Standard_Integer* )&myXLeft   ) = aWinAttr.x;
302   *((Standard_Integer* )&myXRight  ) = aWinAttr.x + aWinAttr.width;
303   *((Standard_Integer* )&myYTop    ) = aWinAttr.y;
304   *((Standard_Integer* )&myYBottom ) = aWinAttr.y + aWinAttr.height;
305   return aMode;
306 }
307
308 // =======================================================================
309 // function : DoMapping
310 // purpose  :
311 // =======================================================================
312 Standard_Boolean Xw_Window::DoMapping() const
313 {
314   return Standard_True; // IsMapped()
315 }
316
317 // =======================================================================
318 // function : Ratio
319 // purpose  :
320 // =======================================================================
321 Quantity_Ratio Xw_Window::Ratio() const
322 {
323   if (myXWindow == 0)
324   {
325     return 1.0;
326   }
327
328   XFlush (myDisplay->GetDisplay());
329   XWindowAttributes aWinAttr;
330   XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
331   return Quantity_Ratio(aWinAttr.width) / Quantity_Ratio(aWinAttr.height);
332 }
333
334 // =======================================================================
335 // function : Position
336 // purpose  :
337 // =======================================================================
338 void Xw_Window::Position (Standard_Integer& X1, Standard_Integer& Y1,
339                           Standard_Integer& X2, Standard_Integer& Y2) const
340 {
341   //
342 }
343
344 // =======================================================================
345 // function : Size
346 // purpose  :
347 // =======================================================================
348 void Xw_Window::Size (Standard_Integer& theWidth,
349                       Standard_Integer& theHeight) const
350 {
351   if (myXWindow == 0)
352   {
353     return;
354   }
355
356   XFlush (myDisplay->GetDisplay());
357   XWindowAttributes aWinAttr;
358   XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
359   theWidth  = aWinAttr.width;
360   theHeight = aWinAttr.height;
361 }
362
363 #endif //  Win32 or Mac OS X