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