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