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 | |
7fd59977 |
18 | #include <Aspect_Convert.hxx> |
e8e157df |
19 | #include <Aspect_ScrollDelta.hxx> |
ed97f43c |
20 | #include <Aspect_WindowDefinitionError.hxx> |
e8e157df |
21 | #include <Aspect_WindowInputListener.hxx> |
1136702b |
22 | #include <Message.hxx> |
23 | #include <Message_Messenger.hxx> |
b69e576a |
24 | #include <Standard_NotImplemented.hxx> |
25 | |
26 | #if defined(HAVE_XLIB) |
27 | #include <X11/Xlib.h> |
28 | #include <X11/Xutil.h> |
29 | #include <X11/Xatom.h> |
30 | //#include <X11/XF86keysym.h> |
31 | #endif |
7fd59977 |
32 | |
b69e576a |
33 | #include <Aspect_DisplayConnection.hxx> |
49582f9d |
34 | |
1136702b |
35 | IMPLEMENT_STANDARD_RTTIEXT(Xw_Window, Aspect_Window) |
36 | |
ed97f43c |
37 | // ======================================================================= |
38 | // function : Xw_Window |
39 | // purpose : |
40 | // ======================================================================= |
41 | Xw_Window::Xw_Window (const Handle(Aspect_DisplayConnection)& theXDisplay, |
42 | const Standard_CString theTitle, |
43 | const Standard_Integer thePxLeft, |
44 | const Standard_Integer thePxTop, |
45 | const Standard_Integer thePxWidth, |
3ae8c60b |
46 | const Standard_Integer thePxHeight) |
ed97f43c |
47 | : Aspect_Window(), |
48 | myDisplay (theXDisplay), |
49 | myXWindow (0), |
3ae8c60b |
50 | myFBConfig (NULL), |
ed97f43c |
51 | myXLeft (thePxLeft), |
52 | myYTop (thePxTop), |
53 | myXRight (thePxLeft + thePxWidth), |
54 | myYBottom (thePxTop + thePxHeight), |
55 | myIsOwnWin (Standard_True) |
7fd59977 |
56 | { |
ed97f43c |
57 | if (thePxWidth <= 0 || thePxHeight <= 0) |
58 | { |
9775fa61 |
59 | throw Aspect_WindowDefinitionError("Xw_Window, Coordinate(s) out of range"); |
ed97f43c |
60 | } |
61 | else if (theXDisplay.IsNull()) |
62 | { |
9775fa61 |
63 | throw Aspect_WindowDefinitionError("Xw_Window, X Display connection is undefined"); |
ed97f43c |
64 | } |
7fd59977 |
65 | |
b69e576a |
66 | #if defined(HAVE_XLIB) |
3ae8c60b |
67 | myFBConfig = theXDisplay->GetDefaultFBConfig(); |
b69e576a |
68 | XVisualInfo* aVisInfo = theXDisplay->GetDefaultVisualInfoX(); |
3ae8c60b |
69 | |
ed97f43c |
70 | Display* aDisp = myDisplay->GetDisplay(); |
71 | int aScreen = DefaultScreen(aDisp); |
72 | Window aParent = RootWindow (aDisp, aScreen); |
9aceb23d |
73 | |
ed97f43c |
74 | unsigned long aMask = 0; |
75 | XSetWindowAttributes aWinAttr; |
b69e576a |
76 | memset (&aWinAttr, 0, sizeof(aWinAttr)); |
ed97f43c |
77 | aWinAttr.event_mask = ExposureMask | StructureNotifyMask; |
78 | aMask |= CWEventMask; |
1136702b |
79 | if (aVisInfo != NULL) |
80 | { |
81 | aWinAttr.colormap = XCreateColormap(aDisp, aParent, aVisInfo->visual, AllocNone); |
82 | } |
ed97f43c |
83 | aWinAttr.border_pixel = 0; |
84 | aWinAttr.override_redirect = False; |
85 | |
b69e576a |
86 | myXWindow = (Window )XCreateWindow (aDisp, aParent, |
ed97f43c |
87 | myXLeft, myYTop, thePxWidth, thePxHeight, |
1136702b |
88 | 0, aVisInfo != NULL ? aVisInfo->depth : CopyFromParent, |
ed97f43c |
89 | InputOutput, |
1136702b |
90 | aVisInfo != NULL ? aVisInfo->visual : CopyFromParent, |
ed97f43c |
91 | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &aWinAttr); |
ed97f43c |
92 | if (myXWindow == 0) |
93 | { |
9775fa61 |
94 | throw Aspect_WindowDefinitionError("Xw_Window, Unable to create window"); |
ed97f43c |
95 | } |
7fd59977 |
96 | |
ed97f43c |
97 | // if parent - desktop |
98 | XSizeHints aSizeHints; |
99 | aSizeHints.x = myXLeft; |
100 | aSizeHints.y = myYTop; |
101 | aSizeHints.flags = PPosition; |
102 | aSizeHints.width = thePxWidth; |
103 | aSizeHints.height = thePxHeight; |
104 | aSizeHints.flags |= PSize; |
b69e576a |
105 | XSetStandardProperties (aDisp, (Window )myXWindow, theTitle, theTitle, None, |
ed97f43c |
106 | NULL, 0, &aSizeHints); |
107 | |
108 | /*XTextProperty aTitleProperty; |
109 | aTitleProperty.encoding = None; |
110 | char* aTitle = (char* )theTitle; |
111 | Xutf8TextListToTextProperty(aDisp, &aTitle, 1, XUTF8StringStyle, &aTitleProperty); |
b69e576a |
112 | XSetWMName (aDisp, (Window )myXWindow, &aTitleProperty); |
113 | XSetWMProperties(aDisp, (Window )myXWindow, &aTitleProperty, &aTitleProperty, NULL, 0, NULL, NULL, NULL);*/ |
ed97f43c |
114 | |
115 | XFlush (aDisp); |
b69e576a |
116 | #else |
117 | (void )theTitle; |
118 | if (myXWindow == 0) |
119 | { |
120 | throw Aspect_WindowDefinitionError ("Xw_Window, Unable to create window - not implemented"); |
121 | } |
122 | #endif |
7fd59977 |
123 | } |
124 | |
ed97f43c |
125 | // ======================================================================= |
126 | // function : Xw_Window |
127 | // purpose : |
128 | // ======================================================================= |
129 | Xw_Window::Xw_Window (const Handle(Aspect_DisplayConnection)& theXDisplay, |
b69e576a |
130 | const Aspect_Drawable theXWin, |
b6bf4ec1 |
131 | const Aspect_FBConfig theFBConfig) |
dc3fe572 |
132 | : Aspect_Window(), |
ed97f43c |
133 | myDisplay (theXDisplay), |
134 | myXWindow (theXWin), |
b6bf4ec1 |
135 | myFBConfig (theFBConfig), |
ed97f43c |
136 | myXLeft (0), |
137 | myYTop (0), |
138 | myXRight (512), |
139 | myYBottom (512), |
140 | myIsOwnWin (Standard_False) |
7fd59977 |
141 | { |
ed97f43c |
142 | if (theXWin == 0) |
143 | { |
9775fa61 |
144 | throw Aspect_WindowDefinitionError("Xw_Window, given invalid X window"); |
ed97f43c |
145 | } |
146 | else if (theXDisplay.IsNull()) |
147 | { |
9775fa61 |
148 | throw Aspect_WindowDefinitionError("Xw_Window, X Display connection is undefined"); |
ed97f43c |
149 | } |
7fd59977 |
150 | |
b69e576a |
151 | #if defined(HAVE_XLIB) |
ed97f43c |
152 | Display* aDisp = myDisplay->GetDisplay(); |
153 | |
154 | XWindowAttributes aWinAttr; |
b69e576a |
155 | XGetWindowAttributes (aDisp, (Window )myXWindow, &aWinAttr); |
ed97f43c |
156 | XVisualInfo aVisInfoTmp; |
157 | aVisInfoTmp.visualid = aWinAttr.visual->visualid; |
1136702b |
158 | aVisInfoTmp.screen = DefaultScreen (aDisp); |
ed97f43c |
159 | int aNbItems = 0; |
1136702b |
160 | XVisualInfo* aVisInfo = XGetVisualInfo (aDisp, VisualIDMask | VisualScreenMask, &aVisInfoTmp, &aNbItems); |
ed97f43c |
161 | if (aVisInfo == NULL) |
162 | { |
9775fa61 |
163 | throw Aspect_WindowDefinitionError("Xw_Window, Visual is unavailable"); |
ed97f43c |
164 | } |
165 | XFree (aVisInfo); |
7fd59977 |
166 | |
ed97f43c |
167 | DoResize(); |
b69e576a |
168 | #else |
169 | //throw Standard_NotImplemented("Xw_Window, not implemented"); |
170 | #endif |
7fd59977 |
171 | } |
172 | |
ed97f43c |
173 | // ======================================================================= |
e6f550da |
174 | // function : ~Xw_Window |
ed97f43c |
175 | // purpose : |
176 | // ======================================================================= |
e6f550da |
177 | Xw_Window::~Xw_Window() |
7fd59977 |
178 | { |
ed97f43c |
179 | if (myIsOwnWin && myXWindow != 0 && !myDisplay.IsNull()) |
7fd59977 |
180 | { |
b69e576a |
181 | #if defined(HAVE_XLIB) |
182 | XDestroyWindow (myDisplay->GetDisplay(), (Window )myXWindow); |
183 | #endif |
7fd59977 |
184 | } |
7fd59977 |
185 | } |
186 | |
ed97f43c |
187 | // ======================================================================= |
188 | // function : IsMapped |
189 | // purpose : |
190 | // ======================================================================= |
191 | Standard_Boolean Xw_Window::IsMapped() const |
7fd59977 |
192 | { |
ed97f43c |
193 | if (myXWindow == 0) |
194 | { |
195 | return false; |
dc3fe572 |
196 | } |
ed97f43c |
197 | else if (IsVirtual()) |
198 | { |
199 | return Standard_True; |
7fd59977 |
200 | } |
dc3fe572 |
201 | |
b69e576a |
202 | #if defined(HAVE_XLIB) |
ed97f43c |
203 | XFlush (myDisplay->GetDisplay()); |
204 | XWindowAttributes aWinAttr; |
b69e576a |
205 | XGetWindowAttributes (myDisplay->GetDisplay(), (Window )myXWindow, &aWinAttr); |
ed97f43c |
206 | return aWinAttr.map_state == IsUnviewable |
207 | || aWinAttr.map_state == IsViewable; |
b69e576a |
208 | #else |
209 | return Standard_False; |
210 | #endif |
7fd59977 |
211 | } |
212 | |
ed97f43c |
213 | // ======================================================================= |
214 | // function : Map |
215 | // purpose : |
216 | // ======================================================================= |
217 | void Xw_Window::Map() const |
7fd59977 |
218 | { |
ed97f43c |
219 | if (IsVirtual() || myXWindow == 0) |
220 | { |
221 | return; |
7fd59977 |
222 | } |
223 | |
b69e576a |
224 | #if defined(HAVE_XLIB) |
225 | XMapWindow (myDisplay->GetDisplay(), (Window )myXWindow); |
ed97f43c |
226 | XFlush (myDisplay->GetDisplay()); |
b69e576a |
227 | #endif |
7fd59977 |
228 | } |
229 | |
ed97f43c |
230 | // ======================================================================= |
231 | // function : Unmap |
232 | // purpose : |
233 | // ======================================================================= |
234 | void Xw_Window::Unmap() const |
235 | { |
236 | if (IsVirtual() || myXWindow == 0) |
237 | { |
238 | return; |
7fd59977 |
239 | } |
7fd59977 |
240 | |
b69e576a |
241 | #if defined(HAVE_XLIB) |
242 | XIconifyWindow (myDisplay->GetDisplay(), (Window )myXWindow, DefaultScreen(myDisplay->GetDisplay())); |
243 | #endif |
7fd59977 |
244 | } |
245 | |
ed97f43c |
246 | // ======================================================================= |
247 | // function : DoResize |
248 | // purpose : |
249 | // ======================================================================= |
1a5007a9 |
250 | Aspect_TypeOfResize Xw_Window::DoResize() |
ed97f43c |
251 | { |
e89202ea |
252 | if (IsVirtual() || myXWindow == 0) |
ed97f43c |
253 | { |
254 | return Aspect_TOR_UNKNOWN; |
255 | } |
7fd59977 |
256 | |
b69e576a |
257 | #if defined(HAVE_XLIB) |
ed97f43c |
258 | XFlush (myDisplay->GetDisplay()); |
259 | XWindowAttributes aWinAttr; |
b69e576a |
260 | memset (&aWinAttr, 0, sizeof(aWinAttr)); |
261 | XGetWindowAttributes (myDisplay->GetDisplay(), (Window )myXWindow, &aWinAttr); |
ed97f43c |
262 | if (aWinAttr.map_state == IsUnmapped) |
263 | { |
264 | return Aspect_TOR_UNKNOWN; |
265 | } |
7fd59977 |
266 | |
ed97f43c |
267 | Standard_Integer aMask = 0; |
268 | Aspect_TypeOfResize aMode = Aspect_TOR_UNKNOWN; |
7fd59977 |
269 | |
ed97f43c |
270 | if (Abs (aWinAttr.x - myXLeft ) > 2) aMask |= 1; |
271 | if (Abs ((aWinAttr.x + aWinAttr.width) - myXRight ) > 2) aMask |= 2; |
272 | if (Abs (aWinAttr.y - myYTop ) > 2) aMask |= 4; |
273 | if (Abs ((aWinAttr.y + aWinAttr.height) - myYBottom) > 2) aMask |= 8; |
274 | switch (aMask) |
275 | { |
276 | case 0: aMode = Aspect_TOR_NO_BORDER; break; |
277 | case 1: aMode = Aspect_TOR_LEFT_BORDER; break; |
278 | case 2: aMode = Aspect_TOR_RIGHT_BORDER; break; |
279 | case 4: aMode = Aspect_TOR_TOP_BORDER; break; |
280 | case 5: aMode = Aspect_TOR_LEFT_AND_TOP_BORDER; break; |
281 | case 6: aMode = Aspect_TOR_TOP_AND_RIGHT_BORDER; break; |
282 | case 8: aMode = Aspect_TOR_BOTTOM_BORDER; break; |
283 | case 9: aMode = Aspect_TOR_BOTTOM_AND_LEFT_BORDER; break; |
284 | case 10: aMode = Aspect_TOR_RIGHT_AND_BOTTOM_BORDER; break; |
285 | default: break; |
286 | } |
7fd59977 |
287 | |
1a5007a9 |
288 | myXLeft = aWinAttr.x; |
289 | myXRight = aWinAttr.x + aWinAttr.width; |
290 | myYTop = aWinAttr.y; |
291 | myYBottom = aWinAttr.y + aWinAttr.height; |
ed97f43c |
292 | return aMode; |
b69e576a |
293 | #else |
294 | return Aspect_TOR_UNKNOWN; |
295 | #endif |
7fd59977 |
296 | } |
297 | |
ed97f43c |
298 | // ======================================================================= |
299 | // function : Ratio |
300 | // purpose : |
301 | // ======================================================================= |
ee2be2a8 |
302 | Standard_Real Xw_Window::Ratio() const |
ed97f43c |
303 | { |
e89202ea |
304 | if (IsVirtual() || myXWindow == 0) |
ed97f43c |
305 | { |
e89202ea |
306 | return Standard_Real(myXRight - myXLeft) / Standard_Real(myYBottom - myYTop); |
ed97f43c |
307 | } |
7fd59977 |
308 | |
b69e576a |
309 | #if defined(HAVE_XLIB) |
ed97f43c |
310 | XFlush (myDisplay->GetDisplay()); |
311 | XWindowAttributes aWinAttr; |
b69e576a |
312 | memset (&aWinAttr, 0, sizeof(aWinAttr)); |
313 | XGetWindowAttributes (myDisplay->GetDisplay(), (Window )myXWindow, &aWinAttr); |
ee2be2a8 |
314 | return Standard_Real(aWinAttr.width) / Standard_Real(aWinAttr.height); |
b69e576a |
315 | #else |
316 | return 1.0; |
317 | #endif |
7fd59977 |
318 | } |
319 | |
ed97f43c |
320 | // ======================================================================= |
321 | // function : Position |
322 | // purpose : |
323 | // ======================================================================= |
e89202ea |
324 | void Xw_Window::Position (Standard_Integer& theX1, Standard_Integer& theY1, |
325 | Standard_Integer& theX2, Standard_Integer& theY2) const |
ed97f43c |
326 | { |
e89202ea |
327 | if (IsVirtual() || myXWindow == 0) |
18d715bd |
328 | { |
e89202ea |
329 | theX1 = myXLeft; |
330 | theX2 = myXRight; |
331 | theY1 = myYTop; |
332 | theY2 = myYBottom; |
18d715bd |
333 | return; |
334 | } |
335 | |
b69e576a |
336 | #if defined(HAVE_XLIB) |
18d715bd |
337 | XFlush (myDisplay->GetDisplay()); |
338 | XWindowAttributes anAttributes; |
b69e576a |
339 | memset (&anAttributes, 0, sizeof(anAttributes)); |
340 | XGetWindowAttributes (myDisplay->GetDisplay(), (Window )myXWindow, &anAttributes); |
18d715bd |
341 | Window aChild; |
b69e576a |
342 | XTranslateCoordinates (myDisplay->GetDisplay(), anAttributes.root, (Window )myXWindow, |
18d715bd |
343 | 0, 0, &anAttributes.x, &anAttributes.y, &aChild); |
344 | |
e89202ea |
345 | theX1 = -anAttributes.x; |
346 | theX2 = theX1 + anAttributes.width; |
347 | theY1 = -anAttributes.y; |
348 | theY2 = theY1 + anAttributes.height; |
b69e576a |
349 | #endif |
7fd59977 |
350 | } |
351 | |
ed97f43c |
352 | // ======================================================================= |
353 | // function : Size |
354 | // purpose : |
355 | // ======================================================================= |
356 | void Xw_Window::Size (Standard_Integer& theWidth, |
357 | Standard_Integer& theHeight) const |
358 | { |
e89202ea |
359 | if (IsVirtual() || myXWindow == 0) |
ed97f43c |
360 | { |
e89202ea |
361 | theWidth = myXRight - myXLeft; |
362 | theHeight = myYBottom - myYTop; |
ed97f43c |
363 | return; |
364 | } |
7fd59977 |
365 | |
b69e576a |
366 | #if defined(HAVE_XLIB) |
ed97f43c |
367 | XFlush (myDisplay->GetDisplay()); |
368 | XWindowAttributes aWinAttr; |
b69e576a |
369 | memset (&aWinAttr, 0, sizeof(aWinAttr)); |
370 | XGetWindowAttributes (myDisplay->GetDisplay(), (Window )myXWindow, &aWinAttr); |
ed97f43c |
371 | theWidth = aWinAttr.width; |
372 | theHeight = aWinAttr.height; |
b69e576a |
373 | #endif |
7fd59977 |
374 | } |
375 | |
49582f9d |
376 | // ======================================================================= |
377 | // function : SetTitle |
378 | // purpose : |
379 | // ======================================================================= |
380 | void Xw_Window::SetTitle (const TCollection_AsciiString& theTitle) |
381 | { |
382 | if (myXWindow != 0) |
383 | { |
b69e576a |
384 | #if defined(HAVE_XLIB) |
385 | XStoreName (myDisplay->GetDisplay(), (Window )myXWindow, theTitle.ToCString()); |
386 | #else |
387 | (void )theTitle; |
388 | #endif |
49582f9d |
389 | } |
390 | } |
391 | |
8693dfd0 |
392 | // ======================================================================= |
393 | // function : InvalidateContent |
394 | // purpose : |
395 | // ======================================================================= |
396 | void Xw_Window::InvalidateContent (const Handle(Aspect_DisplayConnection)& theDisp) |
397 | { |
398 | if (myXWindow == 0) |
399 | { |
400 | return; |
401 | } |
402 | |
b69e576a |
403 | #if defined(HAVE_XLIB) |
8693dfd0 |
404 | const Handle(Aspect_DisplayConnection)& aDisp = !theDisp.IsNull() ? theDisp : myDisplay; |
405 | Display* aDispX = aDisp->GetDisplay(); |
406 | |
407 | XEvent anEvent; |
408 | memset (&anEvent, 0, sizeof(anEvent)); |
409 | anEvent.type = Expose; |
b69e576a |
410 | anEvent.xexpose.window = (Window )myXWindow; |
411 | XSendEvent (aDispX, (Window )myXWindow, False, ExposureMask, &anEvent); |
8693dfd0 |
412 | XFlush (aDispX); |
b69e576a |
413 | #else |
414 | (void )theDisp; |
415 | #endif |
8693dfd0 |
416 | } |
417 | |
49582f9d |
418 | // ======================================================================= |
419 | // function : VirtualKeyFromNative |
420 | // purpose : |
421 | // ======================================================================= |
422 | Aspect_VKey Xw_Window::VirtualKeyFromNative (unsigned long theKey) |
423 | { |
b69e576a |
424 | #if defined(HAVE_XLIB) |
49582f9d |
425 | if (theKey >= XK_0 |
426 | && theKey <= XK_9) |
427 | { |
428 | return Aspect_VKey(theKey - XK_0 + Aspect_VKey_0); |
429 | } |
430 | |
431 | if (theKey >= XK_A |
432 | && theKey <= XK_Z) |
433 | { |
434 | return Aspect_VKey(theKey - XK_A + Aspect_VKey_A); |
435 | } |
436 | |
437 | if (theKey >= XK_a |
438 | && theKey <= XK_z) |
439 | { |
440 | return Aspect_VKey(theKey - XK_a + Aspect_VKey_A); |
441 | } |
442 | |
443 | if (theKey >= XK_F1 |
444 | && theKey <= XK_F24) |
445 | { |
446 | if (theKey <= XK_F12) |
447 | { |
448 | return Aspect_VKey(theKey - XK_F1 + Aspect_VKey_F1); |
449 | } |
450 | return Aspect_VKey_UNKNOWN; |
451 | } |
452 | |
453 | switch (theKey) |
454 | { |
455 | case XK_space: |
456 | return Aspect_VKey_Space; |
457 | case XK_apostrophe: |
458 | return Aspect_VKey_Apostrophe; |
459 | case XK_comma: |
460 | return Aspect_VKey_Comma; |
461 | case XK_minus: |
462 | return Aspect_VKey_Minus; |
463 | case XK_period: |
464 | return Aspect_VKey_Period; |
465 | case XK_semicolon: |
466 | return Aspect_VKey_Semicolon; |
467 | case XK_equal: |
468 | return Aspect_VKey_Equal; |
469 | case XK_bracketleft: |
470 | return Aspect_VKey_BracketLeft; |
471 | case XK_backslash: |
472 | return Aspect_VKey_Backslash; |
473 | case XK_bracketright: |
474 | return Aspect_VKey_BracketRight; |
475 | case XK_BackSpace: |
476 | return Aspect_VKey_Backspace; |
477 | case XK_Tab: |
478 | return Aspect_VKey_Tab; |
479 | //case XK_Linefeed: |
480 | case XK_Return: |
481 | case XK_KP_Enter: |
482 | return Aspect_VKey_Enter; |
483 | //case XK_Pause: |
484 | // return Aspect_VKey_Pause; |
485 | case XK_Escape: |
486 | return Aspect_VKey_Escape; |
487 | case XK_Home: |
488 | return Aspect_VKey_Home; |
489 | case XK_Left: |
490 | return Aspect_VKey_Left; |
491 | case XK_Up: |
492 | return Aspect_VKey_Up; |
493 | case XK_Right: |
494 | return Aspect_VKey_Right; |
495 | case XK_Down: |
496 | return Aspect_VKey_Down; |
497 | case XK_Prior: |
498 | return Aspect_VKey_PageUp; |
499 | case XK_Next: |
500 | return Aspect_VKey_PageDown; |
501 | case XK_End: |
502 | return Aspect_VKey_End; |
503 | //case XK_Insert: |
504 | // return Aspect_VKey_Insert; |
505 | case XK_Menu: |
506 | return Aspect_VKey_Menu; |
507 | case XK_Num_Lock: |
508 | return Aspect_VKey_Numlock; |
509 | //case XK_KP_Delete: |
510 | // return Aspect_VKey_NumDelete; |
511 | case XK_KP_Multiply: |
512 | return Aspect_VKey_NumpadMultiply; |
513 | case XK_KP_Add: |
514 | return Aspect_VKey_NumpadAdd; |
515 | //case XK_KP_Separator: |
516 | // return Aspect_VKey_Separator; |
517 | case XK_KP_Subtract: |
518 | return Aspect_VKey_NumpadSubtract; |
519 | //case XK_KP_Decimal: |
520 | // return Aspect_VKey_Decimal; |
521 | case XK_KP_Divide: |
522 | return Aspect_VKey_NumpadDivide; |
523 | case XK_Shift_L: |
524 | case XK_Shift_R: |
525 | return Aspect_VKey_Shift; |
526 | case XK_Control_L: |
527 | case XK_Control_R: |
528 | return Aspect_VKey_Control; |
529 | //case XK_Caps_Lock: |
530 | // return Aspect_VKey_CapsLock; |
531 | case XK_Alt_L: |
532 | case XK_Alt_R: |
533 | return Aspect_VKey_Alt; |
534 | //case XK_Super_L: |
535 | //case XK_Super_R: |
536 | // return Aspect_VKey_Super; |
537 | case XK_Delete: |
538 | return Aspect_VKey_Delete; |
539 | |
540 | case 0x1008FF11: // XF86AudioLowerVolume |
541 | return Aspect_VKey_VolumeDown; |
542 | case 0x1008FF12: // XF86AudioMute |
543 | return Aspect_VKey_VolumeMute; |
544 | case 0x1008FF13: // XF86AudioRaiseVolume |
545 | return Aspect_VKey_VolumeUp; |
546 | |
547 | case 0x1008FF14: // XF86AudioPlay |
548 | return Aspect_VKey_MediaPlayPause; |
549 | case 0x1008FF15: // XF86AudioStop |
550 | return Aspect_VKey_MediaStop; |
551 | case 0x1008FF16: // XF86AudioPrev |
552 | return Aspect_VKey_MediaPreviousTrack; |
553 | case 0x1008FF17: // XF86AudioNext |
554 | return Aspect_VKey_MediaNextTrack; |
555 | |
556 | case 0x1008FF18: // XF86HomePage |
557 | return Aspect_VKey_BrowserHome; |
558 | case 0x1008FF26: // XF86Back |
559 | return Aspect_VKey_BrowserBack; |
560 | case 0x1008FF27: // XF86Forward |
561 | return Aspect_VKey_BrowserForward; |
562 | case 0x1008FF28: // XF86Stop |
563 | return Aspect_VKey_BrowserStop; |
564 | case 0x1008FF29: // XF86Refresh |
565 | return Aspect_VKey_BrowserRefresh; |
566 | } |
b69e576a |
567 | #else |
568 | (void )theKey; |
569 | #endif |
49582f9d |
570 | return Aspect_VKey_UNKNOWN; |
571 | } |
572 | |
e8e157df |
573 | // ======================================================================= |
574 | // function : ProcessMessage |
575 | // purpose : |
576 | // ======================================================================= |
577 | bool Xw_Window::ProcessMessage (Aspect_WindowInputListener& theListener, |
b69e576a |
578 | XEvent& |
579 | #if defined(HAVE_XLIB) // msvc before VS2015 had problems with (void )theMsg |
580 | theMsg |
581 | #endif |
582 | ) |
e8e157df |
583 | { |
b69e576a |
584 | #if defined(HAVE_XLIB) |
e8e157df |
585 | Display* aDisplay = myDisplay->GetDisplay(); |
586 | |
587 | // Handle event for the chosen display connection |
588 | switch (theMsg.type) |
589 | { |
590 | case ClientMessage: |
591 | { |
592 | if ((Atom)theMsg.xclient.data.l[0] == myDisplay->GetAtom (Aspect_XA_DELETE_WINDOW) |
b69e576a |
593 | && theMsg.xclient.window == (Window )myXWindow) |
e8e157df |
594 | { |
595 | theListener.ProcessClose(); |
596 | return true; |
597 | } |
598 | return false; |
599 | } |
600 | case FocusIn: |
601 | case FocusOut: |
602 | { |
b69e576a |
603 | if (theMsg.xfocus.window == (Window )myXWindow) |
e8e157df |
604 | { |
605 | theListener.ProcessFocus (theMsg.type == FocusIn); |
606 | } |
607 | return true; |
608 | } |
609 | case Expose: |
610 | { |
b69e576a |
611 | if (theMsg.xexpose.window == (Window )myXWindow) |
e8e157df |
612 | { |
613 | theListener.ProcessExpose(); |
614 | } |
615 | |
616 | // remove all the ExposureMask and process them at once |
617 | for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents) |
618 | { |
b69e576a |
619 | if (!XCheckWindowEvent (aDisplay, (Window )myXWindow, ExposureMask, &theMsg)) |
e8e157df |
620 | { |
621 | break; |
622 | } |
623 | } |
624 | |
625 | return true; |
626 | } |
627 | case ConfigureNotify: |
628 | { |
629 | // remove all the StructureNotifyMask and process them at once |
630 | for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents) |
631 | { |
b69e576a |
632 | if (!XCheckWindowEvent (aDisplay, (Window )myXWindow, StructureNotifyMask, &theMsg)) |
e8e157df |
633 | { |
634 | break; |
635 | } |
636 | } |
637 | |
b69e576a |
638 | if (theMsg.xconfigure.window == (Window )myXWindow) |
e8e157df |
639 | { |
640 | theListener.ProcessConfigure (true); |
641 | } |
642 | return true; |
643 | } |
644 | case KeyPress: |
645 | case KeyRelease: |
646 | { |
647 | XKeyEvent* aKeyEvent = (XKeyEvent* )&theMsg; |
648 | const KeySym aKeySym = XLookupKeysym (aKeyEvent, 0); |
649 | const Aspect_VKey aVKey = Xw_Window::VirtualKeyFromNative (aKeySym); |
650 | if (aVKey != Aspect_VKey_UNKNOWN) |
651 | { |
652 | const double aTimeStamp = theListener.EventTime(); |
653 | if (theMsg.type == KeyPress) |
654 | { |
655 | theListener.KeyDown (aVKey, aTimeStamp); |
656 | } |
657 | else |
658 | { |
659 | theListener.KeyUp (aVKey, aTimeStamp); |
660 | } |
661 | theListener.ProcessInput(); |
662 | } |
663 | return true; |
664 | } |
665 | case ButtonPress: |
666 | case ButtonRelease: |
667 | { |
668 | const Graphic3d_Vec2i aPos (theMsg.xbutton.x, theMsg.xbutton.y); |
669 | Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE; |
670 | Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE; |
671 | if (theMsg.xbutton.button == Button1) { aButton = Aspect_VKeyMouse_LeftButton; } |
672 | if (theMsg.xbutton.button == Button2) { aButton = Aspect_VKeyMouse_MiddleButton; } |
673 | if (theMsg.xbutton.button == Button3) { aButton = Aspect_VKeyMouse_RightButton; } |
674 | |
675 | if ((theMsg.xbutton.state & ControlMask) != 0) { aFlags |= Aspect_VKeyFlags_CTRL; } |
676 | if ((theMsg.xbutton.state & ShiftMask) != 0) { aFlags |= Aspect_VKeyFlags_SHIFT; } |
677 | if (theListener.Keys().IsKeyDown (Aspect_VKey_Alt)) |
678 | { |
679 | aFlags |= Aspect_VKeyFlags_ALT; |
680 | } |
681 | |
682 | if (theMsg.xbutton.button == Button4 |
683 | || theMsg.xbutton.button == Button5) |
684 | { |
685 | if (theMsg.type != ButtonPress) |
686 | { |
687 | return true; |
688 | } |
689 | |
690 | const double aDeltaF = (theMsg.xbutton.button == Button4 ? 1.0 : -1.0); |
691 | theListener.UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags)); |
692 | } |
693 | else if (theMsg.type == ButtonPress) |
694 | { |
695 | theListener.PressMouseButton (aPos, aButton, aFlags, false); |
696 | } |
697 | else |
698 | { |
699 | theListener.ReleaseMouseButton (aPos, aButton, aFlags, false); |
700 | } |
701 | theListener.ProcessInput(); |
702 | return true; |
703 | } |
704 | case MotionNotify: |
705 | { |
b69e576a |
706 | if (theMsg.xmotion.window != (Window )myXWindow) |
e8e157df |
707 | { |
708 | return false; |
709 | } |
710 | |
711 | // remove all the ButtonMotionMask and process them at once |
712 | for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents) |
713 | { |
b69e576a |
714 | if (!XCheckWindowEvent (aDisplay, (Window )myXWindow, ButtonMotionMask | PointerMotionMask, &theMsg)) |
e8e157df |
715 | { |
716 | break; |
717 | } |
718 | } |
719 | |
720 | Graphic3d_Vec2i aPos (theMsg.xmotion.x, theMsg.xmotion.y); |
721 | Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE; |
722 | Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE; |
723 | if ((theMsg.xmotion.state & Button1Mask) != 0) { aButtons |= Aspect_VKeyMouse_LeftButton; } |
724 | if ((theMsg.xmotion.state & Button2Mask) != 0) { aButtons |= Aspect_VKeyMouse_MiddleButton; } |
725 | if ((theMsg.xmotion.state & Button3Mask) != 0) { aButtons |= Aspect_VKeyMouse_RightButton; } |
726 | |
727 | if ((theMsg.xmotion.state & ControlMask) != 0) { aFlags |= Aspect_VKeyFlags_CTRL; } |
728 | if ((theMsg.xmotion.state & ShiftMask) != 0) { aFlags |= Aspect_VKeyFlags_SHIFT; } |
729 | if (theListener.Keys().IsKeyDown (Aspect_VKey_Alt)) |
730 | { |
731 | aFlags |= Aspect_VKeyFlags_ALT; |
732 | } |
733 | |
734 | theListener.UpdateMousePosition (aPos, aButtons, aFlags, false); |
735 | theListener.ProcessInput(); |
736 | return true; |
737 | } |
738 | } |
b69e576a |
739 | #else |
740 | (void )theListener; |
741 | #endif |
e8e157df |
742 | return false; |
743 | } |