c3d9de7016df30e78b521007f6a072ca4e120a1f
[occt.git] / src / Xw / Xw_Window.cxx
1 // Created on: 2013-04-06
2 // Created by: Kirill Gavrilov
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <Xw_Window.hxx>
17
18 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
19
20 #include <Aspect_Convert.hxx>
21 #include <Aspect_WindowDefinitionError.hxx>
22 #include <Message.hxx>
23 #include <Message_Messenger.hxx>
24
25 //#include <X11/XF86keysym.h>
26
27 IMPLEMENT_STANDARD_RTTIEXT(Xw_Window, Aspect_Window)
28
29 // =======================================================================
30 // function : Xw_Window
31 // purpose  :
32 // =======================================================================
33 Xw_Window::Xw_Window (const Handle(Aspect_DisplayConnection)& theXDisplay,
34                       const Standard_CString theTitle,
35                       const Standard_Integer thePxLeft,
36                       const Standard_Integer thePxTop,
37                       const Standard_Integer thePxWidth,
38                       const Standard_Integer thePxHeight)
39 : Aspect_Window(),
40   myDisplay  (theXDisplay),
41   myXWindow  (0),
42   myFBConfig (NULL),
43   myXLeft    (thePxLeft),
44   myYTop     (thePxTop),
45   myXRight   (thePxLeft + thePxWidth),
46   myYBottom  (thePxTop + thePxHeight),
47   myIsOwnWin (Standard_True)
48 {
49   if (thePxWidth <= 0 || thePxHeight <= 0)
50   {
51     throw Aspect_WindowDefinitionError("Xw_Window, Coordinate(s) out of range");
52   }
53   else if (theXDisplay.IsNull())
54   {
55     throw Aspect_WindowDefinitionError("Xw_Window, X Display connection is undefined");
56   }
57
58   myFBConfig = theXDisplay->GetDefaultFBConfig();
59   XVisualInfo* aVisInfo = theXDisplay->GetDefaultVisualInfo();
60
61   Display* aDisp   = myDisplay->GetDisplay();
62   int      aScreen = DefaultScreen(aDisp);
63   Window   aParent = RootWindow   (aDisp, aScreen);
64
65
66   unsigned long aMask = 0;
67   XSetWindowAttributes aWinAttr;
68   memset(&aWinAttr, 0, sizeof(XSetWindowAttributes));
69   aWinAttr.event_mask = ExposureMask | StructureNotifyMask;
70   aMask |= CWEventMask;
71   if (aVisInfo != NULL)
72   {
73     aWinAttr.colormap = XCreateColormap(aDisp, aParent, aVisInfo->visual, AllocNone);
74   }
75   aWinAttr.border_pixel = 0;
76   aWinAttr.override_redirect = False;
77
78   myXWindow = XCreateWindow(aDisp, aParent,
79                             myXLeft, myYTop, thePxWidth, thePxHeight,
80                             0, aVisInfo != NULL ? aVisInfo->depth : CopyFromParent,
81                             InputOutput,
82                             aVisInfo != NULL ? aVisInfo->visual : CopyFromParent,
83                             CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &aWinAttr);
84   if (myXWindow == 0)
85   {
86     throw Aspect_WindowDefinitionError("Xw_Window, Unable to create window");
87   }
88
89   // if parent - desktop
90   XSizeHints aSizeHints;
91   aSizeHints.x      = myXLeft;
92   aSizeHints.y      = myYTop;
93   aSizeHints.flags  = PPosition;
94   aSizeHints.width  = thePxWidth;
95   aSizeHints.height = thePxHeight;
96   aSizeHints.flags |= PSize;
97   XSetStandardProperties (aDisp, myXWindow, theTitle, theTitle, None,
98                           NULL, 0, &aSizeHints);
99
100   /*XTextProperty aTitleProperty;
101   aTitleProperty.encoding = None;
102   char* aTitle = (char* )theTitle;
103   Xutf8TextListToTextProperty(aDisp, &aTitle, 1, XUTF8StringStyle, &aTitleProperty);
104   XSetWMName      (aDisp, myXWindow, &aTitleProperty);
105   XSetWMProperties(aDisp, myXWindow, &aTitleProperty, &aTitleProperty, NULL, 0, NULL, NULL, NULL);*/
106
107   XFlush (aDisp);
108 }
109
110 // =======================================================================
111 // function : Xw_Window
112 // purpose  :
113 // =======================================================================
114 Xw_Window::Xw_Window (const Handle(Aspect_DisplayConnection)& theXDisplay,
115                       const Window theXWin,
116                       const Aspect_FBConfig theFBConfig)
117 : Aspect_Window(),
118   myDisplay  (theXDisplay),
119   myXWindow  (theXWin),
120   myFBConfig (theFBConfig),
121   myXLeft    (0),
122   myYTop     (0),
123   myXRight   (512),
124   myYBottom  (512),
125   myIsOwnWin (Standard_False)
126 {
127   if (theXWin == 0)
128   {
129     throw Aspect_WindowDefinitionError("Xw_Window, given invalid X window");
130   }
131   else if (theXDisplay.IsNull())
132   {
133     throw Aspect_WindowDefinitionError("Xw_Window, X Display connection is undefined");
134   }
135
136   Display* aDisp = myDisplay->GetDisplay();
137
138   XWindowAttributes aWinAttr;
139   XGetWindowAttributes (aDisp, myXWindow, &aWinAttr);
140   XVisualInfo aVisInfoTmp;
141   aVisInfoTmp.visualid = aWinAttr.visual->visualid;
142   aVisInfoTmp.screen   = DefaultScreen (aDisp);
143   int aNbItems = 0;
144   XVisualInfo* aVisInfo = XGetVisualInfo (aDisp, VisualIDMask | VisualScreenMask, &aVisInfoTmp, &aNbItems);
145   if (aVisInfo == NULL)
146   {
147     throw Aspect_WindowDefinitionError("Xw_Window, Visual is unavailable");
148   }
149   XFree (aVisInfo);
150
151   DoResize();
152 }
153
154 // =======================================================================
155 // function : ~Xw_Window
156 // purpose  :
157 // =======================================================================
158 Xw_Window::~Xw_Window()
159 {
160   if (myIsOwnWin && myXWindow != 0 && !myDisplay.IsNull())
161   {
162     XDestroyWindow (myDisplay->GetDisplay(), myXWindow);
163   }
164 }
165
166 // =======================================================================
167 // function : XWindow
168 // purpose  :
169 // =======================================================================
170 Window Xw_Window::XWindow() const
171 {
172   return myXWindow;
173 }
174
175 // =======================================================================
176 // function : IsMapped
177 // purpose  :
178 // =======================================================================
179 Standard_Boolean Xw_Window::IsMapped() const
180 {
181   if (myXWindow == 0)
182   {
183     return false;
184   }
185   else if (IsVirtual())
186   {
187     return Standard_True;
188   }
189
190   XFlush (myDisplay->GetDisplay());
191   XWindowAttributes aWinAttr;
192   XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
193   return aWinAttr.map_state == IsUnviewable
194       || aWinAttr.map_state == IsViewable;
195 }
196
197 // =======================================================================
198 // function : Map
199 // purpose  :
200 // =======================================================================
201 void Xw_Window::Map() const
202 {
203   if (IsVirtual() || myXWindow == 0)
204   {
205     return;
206   }
207
208   XMapWindow (myDisplay->GetDisplay(), myXWindow);
209   XFlush (myDisplay->GetDisplay());
210 }
211
212 // =======================================================================
213 // function : Unmap
214 // purpose  :
215 // =======================================================================
216 void Xw_Window::Unmap() const
217 {
218   if (IsVirtual() || myXWindow == 0)
219   {
220     return;
221   }
222
223   XIconifyWindow (myDisplay->GetDisplay(), myXWindow, DefaultScreen(myDisplay->GetDisplay()));
224 }
225
226 // =======================================================================
227 // function : DoResize
228 // purpose  :
229 // =======================================================================
230 Aspect_TypeOfResize Xw_Window::DoResize()
231 {
232   if (IsVirtual() || myXWindow == 0)
233   {
234     return Aspect_TOR_UNKNOWN;
235   }
236
237   XFlush (myDisplay->GetDisplay());
238   XWindowAttributes aWinAttr;
239   XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
240   if (aWinAttr.map_state == IsUnmapped)
241   {
242     return Aspect_TOR_UNKNOWN;
243   }
244
245   Standard_Integer aMask = 0;
246   Aspect_TypeOfResize aMode = Aspect_TOR_UNKNOWN;
247
248   if (Abs (aWinAttr.x                     - myXLeft  ) > 2) aMask |= 1;
249   if (Abs ((aWinAttr.x + aWinAttr.width)  - myXRight ) > 2) aMask |= 2;
250   if (Abs (aWinAttr.y                     - myYTop   ) > 2) aMask |= 4;
251   if (Abs ((aWinAttr.y + aWinAttr.height) - myYBottom) > 2) aMask |= 8;
252   switch (aMask)
253   {
254     case 0:  aMode = Aspect_TOR_NO_BORDER;               break;
255     case 1:  aMode = Aspect_TOR_LEFT_BORDER;             break;
256     case 2:  aMode = Aspect_TOR_RIGHT_BORDER;            break;
257     case 4:  aMode = Aspect_TOR_TOP_BORDER;              break;
258     case 5:  aMode = Aspect_TOR_LEFT_AND_TOP_BORDER;     break;
259     case 6:  aMode = Aspect_TOR_TOP_AND_RIGHT_BORDER;    break;
260     case 8:  aMode = Aspect_TOR_BOTTOM_BORDER;           break;
261     case 9:  aMode = Aspect_TOR_BOTTOM_AND_LEFT_BORDER;  break;
262     case 10: aMode = Aspect_TOR_RIGHT_AND_BOTTOM_BORDER; break;
263     default: break;
264   }
265
266   myXLeft   = aWinAttr.x;
267   myXRight  = aWinAttr.x + aWinAttr.width;
268   myYTop    = aWinAttr.y;
269   myYBottom = aWinAttr.y + aWinAttr.height;
270   return aMode;
271 }
272
273 // =======================================================================
274 // function : DoMapping
275 // purpose  :
276 // =======================================================================
277 Standard_Boolean Xw_Window::DoMapping() const
278 {
279   return Standard_True; // IsMapped()
280 }
281
282 // =======================================================================
283 // function : Ratio
284 // purpose  :
285 // =======================================================================
286 Standard_Real Xw_Window::Ratio() const
287 {
288   if (IsVirtual() || myXWindow == 0)
289   {
290     return Standard_Real(myXRight - myXLeft) / Standard_Real(myYBottom - myYTop);
291   }
292
293   XFlush (myDisplay->GetDisplay());
294   XWindowAttributes aWinAttr;
295   XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
296   return Standard_Real(aWinAttr.width) / Standard_Real(aWinAttr.height);
297 }
298
299 // =======================================================================
300 // function : Position
301 // purpose  :
302 // =======================================================================
303 void Xw_Window::Position (Standard_Integer& theX1, Standard_Integer& theY1,
304                           Standard_Integer& theX2, Standard_Integer& theY2) const
305 {
306   if (IsVirtual() || myXWindow == 0)
307   {
308     theX1  = myXLeft;
309     theX2  = myXRight;
310     theY1  = myYTop;
311     theY2  = myYBottom;
312     return;
313   }
314
315   XFlush (myDisplay->GetDisplay());
316   XWindowAttributes anAttributes;
317   XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &anAttributes);
318   Window aChild;
319   XTranslateCoordinates (myDisplay->GetDisplay(), anAttributes.root, myXWindow,
320                          0, 0, &anAttributes.x, &anAttributes.y, &aChild);
321
322   theX1 = -anAttributes.x;
323   theX2 = theX1 + anAttributes.width;
324   theY1 = -anAttributes.y;
325   theY2 = theY1 + anAttributes.height;
326 }
327
328 // =======================================================================
329 // function : Size
330 // purpose  :
331 // =======================================================================
332 void Xw_Window::Size (Standard_Integer& theWidth,
333                       Standard_Integer& theHeight) const
334 {
335   if (IsVirtual() || myXWindow == 0)
336   {
337     theWidth  = myXRight - myXLeft;
338     theHeight = myYBottom - myYTop;
339     return;
340   }
341
342   XFlush (myDisplay->GetDisplay());
343   XWindowAttributes aWinAttr;
344   XGetWindowAttributes (myDisplay->GetDisplay(), myXWindow, &aWinAttr);
345   theWidth  = aWinAttr.width;
346   theHeight = aWinAttr.height;
347 }
348
349 // =======================================================================
350 // function : SetTitle
351 // purpose  :
352 // =======================================================================
353 void Xw_Window::SetTitle (const TCollection_AsciiString& theTitle)
354 {
355   if (myXWindow != 0)
356   {
357     XStoreName (myDisplay->GetDisplay(), myXWindow, theTitle.ToCString());
358   }
359 }
360
361 // =======================================================================
362 // function : InvalidateContent
363 // purpose  :
364 // =======================================================================
365 void Xw_Window::InvalidateContent (const Handle(Aspect_DisplayConnection)& theDisp)
366 {
367   if (myXWindow == 0)
368   {
369     return;
370   }
371
372   const Handle(Aspect_DisplayConnection)& aDisp = !theDisp.IsNull() ? theDisp : myDisplay;
373   Display* aDispX = aDisp->GetDisplay();
374
375   XEvent anEvent;
376   memset (&anEvent, 0, sizeof(anEvent));
377   anEvent.type = Expose;
378   anEvent.xexpose.window = myXWindow;
379   XSendEvent (aDispX, myXWindow, False, ExposureMask, &anEvent);
380   XFlush (aDispX);
381 }
382
383 // =======================================================================
384 // function : VirtualKeyFromNative
385 // purpose  :
386 // =======================================================================
387 Aspect_VKey Xw_Window::VirtualKeyFromNative (unsigned long theKey)
388 {
389   if (theKey >= XK_0
390    && theKey <= XK_9)
391   {
392     return Aspect_VKey(theKey - XK_0 + Aspect_VKey_0);
393   }
394
395   if (theKey >= XK_A
396    && theKey <= XK_Z)
397   {
398     return Aspect_VKey(theKey - XK_A + Aspect_VKey_A);
399   }
400
401   if (theKey >= XK_a
402    && theKey <= XK_z)
403   {
404     return Aspect_VKey(theKey - XK_a + Aspect_VKey_A);
405   }
406
407   if (theKey >= XK_F1
408    && theKey <= XK_F24)
409   {
410     if (theKey <= XK_F12)
411     {
412       return Aspect_VKey(theKey - XK_F1 + Aspect_VKey_F1);
413     }
414     return Aspect_VKey_UNKNOWN;
415   }
416
417   switch (theKey)
418   {
419     case XK_space:
420       return Aspect_VKey_Space;
421     case XK_apostrophe:
422       return Aspect_VKey_Apostrophe;
423     case XK_comma:
424       return Aspect_VKey_Comma;
425     case XK_minus:
426       return Aspect_VKey_Minus;
427     case XK_period:
428       return Aspect_VKey_Period;
429     case XK_semicolon:
430       return Aspect_VKey_Semicolon;
431     case XK_equal:
432       return Aspect_VKey_Equal;
433     case XK_bracketleft:
434       return Aspect_VKey_BracketLeft;
435     case XK_backslash:
436       return Aspect_VKey_Backslash;
437     case XK_bracketright:
438       return Aspect_VKey_BracketRight;
439     case XK_BackSpace:
440       return Aspect_VKey_Backspace;
441     case XK_Tab:
442       return Aspect_VKey_Tab;
443     //case XK_Linefeed:
444     case XK_Return:
445     case XK_KP_Enter:
446       return Aspect_VKey_Enter;
447     //case XK_Pause:
448     //  return Aspect_VKey_Pause;
449     case XK_Escape:
450       return Aspect_VKey_Escape;
451     case XK_Home:
452       return Aspect_VKey_Home;
453     case XK_Left:
454       return Aspect_VKey_Left;
455     case XK_Up:
456       return Aspect_VKey_Up;
457     case XK_Right:
458       return Aspect_VKey_Right;
459     case XK_Down:
460       return Aspect_VKey_Down;
461     case XK_Prior:
462       return Aspect_VKey_PageUp;
463     case XK_Next:
464       return Aspect_VKey_PageDown;
465     case XK_End:
466       return Aspect_VKey_End;
467     //case XK_Insert:
468     //  return Aspect_VKey_Insert;
469     case XK_Menu:
470       return Aspect_VKey_Menu;
471     case XK_Num_Lock:
472       return Aspect_VKey_Numlock;
473     //case XK_KP_Delete:
474     //  return Aspect_VKey_NumDelete;
475     case XK_KP_Multiply:
476       return Aspect_VKey_NumpadMultiply;
477     case XK_KP_Add:
478       return Aspect_VKey_NumpadAdd;
479     //case XK_KP_Separator:
480     //  return Aspect_VKey_Separator;
481     case XK_KP_Subtract:
482       return Aspect_VKey_NumpadSubtract;
483     //case XK_KP_Decimal:
484     //  return Aspect_VKey_Decimal;
485     case XK_KP_Divide:
486       return Aspect_VKey_NumpadDivide;
487     case XK_Shift_L:
488     case XK_Shift_R:
489       return Aspect_VKey_Shift;
490     case XK_Control_L:
491     case XK_Control_R:
492       return Aspect_VKey_Control;
493     //case XK_Caps_Lock:
494     //  return Aspect_VKey_CapsLock;
495     case XK_Alt_L:
496     case XK_Alt_R:
497       return Aspect_VKey_Alt;
498     //case XK_Super_L:
499     //case XK_Super_R:
500     //  return Aspect_VKey_Super;
501     case XK_Delete:
502       return Aspect_VKey_Delete;
503
504     case 0x1008FF11: // XF86AudioLowerVolume
505       return Aspect_VKey_VolumeDown;
506     case 0x1008FF12: // XF86AudioMute
507       return Aspect_VKey_VolumeMute;
508     case 0x1008FF13: // XF86AudioRaiseVolume
509       return Aspect_VKey_VolumeUp;
510
511     case 0x1008FF14: // XF86AudioPlay
512       return Aspect_VKey_MediaPlayPause;
513     case 0x1008FF15: // XF86AudioStop
514       return Aspect_VKey_MediaStop;
515     case 0x1008FF16: // XF86AudioPrev
516       return Aspect_VKey_MediaPreviousTrack;
517     case 0x1008FF17: // XF86AudioNext
518       return Aspect_VKey_MediaNextTrack;
519
520     case 0x1008FF18: // XF86HomePage
521       return Aspect_VKey_BrowserHome;
522     case 0x1008FF26: // XF86Back
523       return Aspect_VKey_BrowserBack;
524     case 0x1008FF27: // XF86Forward
525       return Aspect_VKey_BrowserForward;
526     case 0x1008FF28: // XF86Stop
527       return Aspect_VKey_BrowserStop;
528     case 0x1008FF29: // XF86Refresh
529       return Aspect_VKey_BrowserRefresh;
530   }
531   return Aspect_VKey_UNKNOWN;
532 }
533
534 #endif //  Win32 or Mac OS X