Logo ROOT   6.21/01
Reference Guide
TGLEventHandler.cxx
Go to the documentation of this file.
1 // @(#)root/gl:$Id$
2 // Author: Bertrand Bellenot 29/01/2008
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TGLEventHandler.h"
13 #include "TGEventHandler.h"
14 #include "TGLViewer.h"
15 #include "TGLWidget.h"
16 #include "TGWindow.h"
17 #include "TPoint.h"
18 #include "TVirtualPad.h" // Remove when pad removed - use signal
19 #include "TVirtualX.h"
20 #include "TGClient.h"
21 #include "TVirtualGL.h"
22 #include "TGLOverlay.h"
23 #include "TGLLogicalShape.h"
24 #include "TGLPhysicalShape.h"
25 #include "TContextMenu.h"
26 #include "TGToolTip.h"
27 #include "KeySymbols.h"
28 #include "TGLAnnotation.h"
29 #include "TEnv.h"
30 #include "TMath.h"
31 #include "RConfigure.h"
32 
33 /** \class TGLEventHandler
34 \ingroup opengl
35 Base-class and default implementation of event-handler for TGLViewer.
36 
37 This allows for complete disentanglement of GL-viewer from GUI
38 event handling. Further, alternative event-handlers can easily be
39 designed and set at run-time.
40 
41 The signals about object being selected or hovered above are
42 emitted via the TGLViewer itself.
43 
44 The following rootrc settings influence the behaviour:
45 ~~~ {.cpp}
46 OpenGL.EventHandler.ViewerCentricControls: 1
47 OpenGL.EventHandler.ArrowKeyFactor: -1.0
48 OpenGL.EventHandler.MouseDragFactor: -1.0
49 OpenGL.EventHandler.MouseWheelFactor: -1.0
50 ~~~
51 */
52 
54 
55 ////////////////////////////////////////////////////////////////////////////////
56 /// Constructor.
57 
59  TGEventHandler ("TGLEventHandler", w, obj),
60  fGLViewer ((TGLViewer *)obj),
61  fMouseTimer (0),
62  fLastPos (-1, -1),
63  fLastMouseOverPos (-1, -1),
64  fLastMouseOverShape (0),
65  fTooltip (0),
66  fActiveButtonID (0),
67  fLastEventState (0),
68  fIgnoreButtonUp (kFALSE),
69  fInPointerGrab (kFALSE),
70  fMouseTimerRunning (kFALSE),
71  fTooltipShown (kFALSE),
72  fArcBall (kFALSE),
73  fTooltipPixelTolerance (3),
74  fSecSelType(TGLViewer::kOnRequest),
75  fDoInternalSelection(kTRUE),
76  fViewerCentricControls(kFALSE)
77 {
78  fMouseTimer = new TTimer(this, 80);
79  fTooltip = new TGToolTip(0, 0, "", 650);
80  fTooltip->Hide();
81  fViewerCentricControls = gEnv->GetValue("OpenGL.EventHandler.ViewerCentricControls", 0) != 0;
82  fArrowKeyFactor = gEnv->GetValue("OpenGL.EventHandler.ArrowKeyFactor", 1.0);
83  fMouseDragFactor = gEnv->GetValue("OpenGL.EventHandler.MouseDragFactor", 1.0);
84  fMouseWheelFactor = gEnv->GetValue("OpenGL.EventHandler.MouseWheelFactor", 1.0);
85 }
86 
87 ////////////////////////////////////////////////////////////////////////////////
88 /// Destructor.
89 
91 {
92  delete fMouseTimer;
93  delete fTooltip;
94 }
95 
96 ////////////////////////////////////////////////////////////////////////////////
97 /// Acquire mouse grab.
98 
100 {
101  if (!fInPointerGrab)
102  {
103  gVirtualX->GrabPointer(fGLViewer->GetGLWidget()->GetId(),
105  kNone, kNone, kTRUE, kFALSE);
107  }
108 }
109 
110 ////////////////////////////////////////////////////////////////////////////////
111 /// Release mouse grab.
112 
114 {
115  if (fInPointerGrab)
116  {
117  gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
119  }
120 }
121 
122 ////////////////////////////////////////////////////////////////////////////////
123 /// Run selection (optionally with on secondary selection) and emit
124 /// corresponding Clicked() signals.
125 /// Protected method.
126 
128 {
130 
133 
134  // secondary selection
135  if (lshp && (event->fState & kKeyMod1Mask || (fSecSelType == TGLViewer::kOnRequest && lshp->AlwaysSecondarySelect())))
136  {
139 
141 
143  {
145  fGLViewer->Clicked(obj, event->fCode, event->fState);
146  break;
148  fGLViewer->UnClicked(obj, event->fCode, event->fState);
149  break;
151  fGLViewer->ReClicked(obj, event->fCode, event->fState);
152  break;
153  default:
154  break;
155  }
156  }
157  else
158  {
159  fGLViewer->Clicked(obj);
160  fGLViewer->Clicked(obj, event->fCode, event->fState);
161  }
162 }
163 
164 ////////////////////////////////////////////////////////////////////////////////
165 /// Run selection (optionally with on secondary selection) and emit
166 /// corresponding MouseOver() signals.
167 /// Protected method.
168 
170 {
172 
176 
177  if (lshp && (fSecSelType == TGLViewer::kOnRequest && lshp->AlwaysSecondarySelect()))
178  {
182 
184 
186 
188  {
191  break;
194  break;
197  break;
198  default:
199  break;
200  }
201  }
202  else if (fLastMouseOverShape != pshp)
203  {
204  fGLViewer->MouseOver(pshp);
207  }
208  fLastMouseOverShape = pshp;
210 }
211 
212 //==============================================================================
213 
214 ////////////////////////////////////////////////////////////////////////////////
215 /// Process event of type 'event' - one of EEventType types,
216 /// occurring at window location px, py
217 /// This is provided for use when embedding GL viewer into pad
218 
220 {
221  /*enum EEventType {
222  kNoEvent = 0,
223  kButton1Down = 1, kButton2Down = 2, kButton3Down = 3, kKeyDown = 4,
224  kButton1Up = 11, kButton2Up = 12, kButton3Up = 13, kKeyUp = 14,
225  kButton1Motion = 21, kButton2Motion = 22, kButton3Motion = 23, kKeyPress = 24,
226  kButton1Locate = 41, kButton2Locate = 42, kButton3Locate = 43,
227  kMouseMotion = 51, kMouseEnter = 52, kMouseLeave = 53,
228  kButton1Double = 61, kButton2Double = 62, kButton3Double = 63
229 
230  enum EGEventType {
231  kGKeyPress, kKeyRelease, kButtonPress, kButtonRelease,
232  kMotionNotify, kEnterNotify, kLeaveNotify, kFocusIn, kFocusOut,
233  kExpose, kConfigureNotify, kMapNotify, kUnmapNotify, kDestroyNotify,
234  kClientMessage, kSelectionClear, kSelectionRequest, kSelectionNotify,
235  kColormapNotify, kButtonDoubleClick, kOtherEvent*/
236 
237  // Map our event EEventType (base/inc/Buttons.h) back to Event_t (base/inc/GuiTypes.h)
238  // structure, and call appropriate HandleXyzz() function
239  Event_t eventSt = { kOtherEvent, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
240  kFALSE, 0, 0, {0, 0, 0, 0, 0} };
241  eventSt.fX = px;
242  eventSt.fY = py;
243  eventSt.fState = 0;
244  eventSt.fXRoot = eventSt.fYRoot = 0;
245 
246  if (event != kKeyPress) {
247  eventSt.fY -= Int_t((1 - gPad->GetHNDC() - gPad->GetYlowNDC()) * gPad->GetWh());
248  eventSt.fX -= Int_t(gPad->GetXlowNDC() * gPad->GetWw());
249  eventSt.fXRoot = eventSt.fX;
250  eventSt.fYRoot = eventSt.fY;
251  }
252 
253  switch (event) {
254  case kMouseMotion:
255  eventSt.fCode = kMouseMotion;
256  eventSt.fType = kMotionNotify;
257  HandleMotion(&eventSt);
258  break;
259  case kButton1Down:
260  case kButton1Up:
261  {
262  eventSt.fCode = kButton1;
263  eventSt.fType = event == kButton1Down ? kButtonPress:kButtonRelease;
264  HandleButton(&eventSt);
265  }
266  break;
267  case kButton2Down:
268  case kButton2Up:
269  {
270  eventSt.fCode = kButton2;
271  eventSt.fType = event == kButton2Down ? kButtonPress:kButtonRelease;
272  HandleButton(&eventSt);
273  }
274  break;
275  case kButton3Down:
276  {
277  eventSt.fState = kKeyShiftMask;
278  eventSt.fCode = kButton1;
279  eventSt.fType = kButtonPress;
280  HandleButton(&eventSt);
281  }
282  break;
283  case kButton3Up:
284  {
285  eventSt.fCode = kButton3;
286  eventSt.fType = kButtonRelease;//event == kButton3Down ? kButtonPress:kButtonRelease;
287  HandleButton(&eventSt);
288  }
289  break;
290  case kButton1Double:
291  case kButton2Double:
292  case kButton3Double:
293  {
294  eventSt.fCode = event == kButton1Double ? kButton1 : event == kButton2Double ? kButton2 : kButton3;
295  eventSt.fType = kButtonDoubleClick;
296  HandleDoubleClick(&eventSt);
297  }
298  break;
299  case kButton1Motion:
300  case kButton2Motion:
301  case kButton3Motion:
302  {
303 
304  eventSt.fCode = event == kButton1Motion ? kButton1 : event == kButton2Motion ? kButton2 : kButton3;
305  eventSt.fType = kMotionNotify;
306  HandleMotion(&eventSt);
307  }
308  break;
309  case kKeyPress: // We only care about full key 'presses' not individual down/up
310  {
311  eventSt.fType = kGKeyPress;
312  eventSt.fCode = py; // px contains key code - need modifiers from somewhere
313  HandleKey(&eventSt);
314  }
315  break;
316  case 6://trick :)
317  if (fGLViewer->CurrentCamera().Zoom(+50, kFALSE, kFALSE)) { //TODO : val static const somewhere
318  if (fGLViewer->fGLDevice != -1) {
319  gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kTRUE);
320  gVirtualX->SetDrawMode(TVirtualX::kCopy);
321  }
323  }
324  break;
325  case 5://trick :)
326  if (fGLViewer->CurrentCamera().Zoom(-50, kFALSE, kFALSE)) { //TODO : val static const somewhere
327  if (fGLViewer->fGLDevice != -1) {
328  gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kTRUE);
329  gVirtualX->SetDrawMode(TVirtualX::kCopy);
330  }
332  }
333  break;
334  case 7://trick :)
335  eventSt.fState = kKeyShiftMask;
336  eventSt.fCode = kButton1;
337  eventSt.fType = kButtonPress;
338  HandleButton(&eventSt);
339  break;
340  default:
341  {
342  // Error("TGLEventHandler::ExecuteEvent", "invalid event type");
343  }
344  }
345 }
346 
347 ////////////////////////////////////////////////////////////////////////////////
348 /// Handle generic Event_t type 'event' - provided to catch focus changes
349 /// and terminate any interaction in viewer.
350 
352 {
353  if (event->fType == kFocusIn) {
355  Error("TGLEventHandler::HandleEvent", "active drag-action at focus-in.");
357  }
358  StartMouseTimer();
359  }
360  if (event->fType == kFocusOut) {
362  Warning("TGLEventHandler::HandleEvent", "drag-action active at focus-out.");
364  }
365  StopMouseTimer();
366  ClearMouseOver();
367  }
368 
369  return kTRUE;
370 }
371 
372 ////////////////////////////////////////////////////////////////////////////////
373 /// Handle generic Event_t type 'event' - provided to catch focus changes
374 /// and terminate any interaction in viewer.
375 
377 {
378  fGLViewer->MouseIdle(0, 0, 0);
379  if (event->fType == kFocusIn) {
381  Error("TGLEventHandler::HandleFocusChange", "active drag-action at focus-in.");
383  }
384  StartMouseTimer();
385  fGLViewer->Activated();
386  }
387  if (event->fType == kFocusOut) {
389  Warning("TGLEventHandler::HandleFocusChange", "drag-action active at focus-out.");
391  }
392  StopMouseTimer();
393  ClearMouseOver();
394  }
395 
396  return kTRUE;
397 }
398 
399 ////////////////////////////////////////////////////////////////////////////////
400 /// Handle generic Event_t type 'event' - provided to catch focus changes
401 /// and terminate any interaction in viewer.
402 
404 {
405  // Ignore grab and ungrab events.
406  if (event->fCode != 0) {
407  return kTRUE;
408  }
409 
410  fGLViewer->MouseIdle(0, 0, 0);
411  if (event->fType == kEnterNotify) {
413  Error("TGLEventHandler::HandleCrossing", "active drag-action at enter-notify.");
415  }
416  StartMouseTimer();
417  // Maybe, maybe not...
418  fGLViewer->Activated();
419  }
420  if (event->fType == kLeaveNotify) {
422  Warning("TGLEventHandler::HandleCrossing", "drag-action active at leave-notify.");
424  }
425  StopMouseTimer();
426  ClearMouseOver();
427  }
428 
429  return kTRUE;
430 }
431 
432 ////////////////////////////////////////////////////////////////////////////////
433 /// Handle mouse button 'event'.
434 
436 {
437  if (fGLViewer->IsLocked()) {
438  if (gDebug>2) {
439  Info("TGLEventHandler::HandleButton", "ignored - viewer is %s",
441  }
442  return kFALSE;
443  }
444 
445  // Handle mouse-wheel events first.
446  if (event->fCode > kButton3)
447  {
448  // On Win32 only button release events come for mouse wheel.
449  // Note: Modifiers (ctrl/shift) disabled as fState doesn't seem to
450  // have correct modifier flags with mouse wheel under Windows.
451 
452  if (event->fType == kButtonRelease)
453  {
454  Bool_t redraw = kFALSE;
455 
457  switch(event->fCode)
458  {
459  case kButton5: // Zoom out (dolly or adjust camera FOV).
460  redraw = fGLViewer->CurrentCamera().Zoom(zoom, kFALSE, kFALSE);
461  break;
462 
463  case kButton4: // Zoom in (dolly or adjust camera FOV).
464  redraw = fGLViewer->CurrentCamera().Zoom(-zoom, kFALSE, kFALSE);
465  break;
466 
467  case kButton6:
468  case kButton7: // Ignore for now.
469  break;
470  }
471 
472  if (redraw)
474  }
475  return kTRUE;
476  }
477 
478  // Now we know we have Button 1 -> 3.
479  // Allow a single action/button down/up pairing - block others
480  if (fActiveButtonID && event->fCode != fActiveButtonID)
481  {
482  return kTRUE;
483  }
484  else
485  {
486  fActiveButtonID = event->fCode;
487  }
488 
489 #if defined(R__HAS_COCOA)
490  // On osx/cocoa use cmd modifier for mouse-2 and cmd-alt for mouse-3.
491  if (event->fCode == kButton1 && event->fState & kKeyMod2Mask)
492  {
493  event->fCode = event->fState & kKeyMod1Mask ? kButton3 : kButton2;
494  }
495 #endif
496 
497  // Button DOWN
498  if (event->fType == kButtonPress)
499  {
500  GrabMouse();
501 
502  fGLViewer->MouseIdle(0, 0, 0);
503 
504  fButtonPushPos.fX = event->fX;
505  fButtonPushPos.fY = event->fY;
506 
508  {
509  fGLViewer->RequestSelect(event->fX, event->fY);
510  if (fGLViewer->fSelRec.GetN() > 0)
511  {
512  TGLVector3 v(event->fX, event->fY, 0.5*fGLViewer->fSelRec.GetMinZ());
516  {
518  fGLViewer->CurrentCamera().SetCenterVec(v.X(), v.Y(), v.Z());
519  }
520  else
521  {
523  TObject* obj = rec.GetObject();
525  Int_t x = event->fX, y = event->fY;
527  new TGLAnnotation(fGLViewer, obj->GetTitle(),
528  x * 1.0f/vp.Width(),
529  1 - y * 1.0f/vp.Height(), v);
530  }
531 
533  }
534  return kTRUE;
535  }
536 
537  Bool_t handled = kFALSE;
538 
540  {
541  Event_t e = *event;
542  TGLUtil::PointToViewport(e.fX, e.fY);
544  {
545  handled = kTRUE;
548  }
549  }
550 
551  if ( ! handled)
552  {
553  switch (event->fCode)
554  {
555  // LEFT mouse button
556  case kButton1:
557  {
559  if (fMouseTimer)
560  {
561  fMouseTimer->TurnOff();
562  fMouseTimer->Reset();
563  }
564  break;
565  }
566  // MIDDLE mouse button
567  case kButton2:
568  {
570  break;
571  }
572  // RIGHT mouse button
573  case kButton3:
574  {
576  break;
577  }
578  }
579  }
580  }
581  // Button UP
582  else if (event->fType == kButtonRelease)
583  {
584  fActiveButtonID = 0;
585 
586  if (fInPointerGrab)
587  {
588  UnGrabMouse();
589  }
590  else
591  {
592  Warning("TGLEventHandler::HandleButton", "Unexpected button-release.");
593  }
594 
595  if (fIgnoreButtonUp)
596  {
598  return kTRUE;
599  }
600 
602  {
603  // This should be 'tool' dependant.
606  return kTRUE;
607  }
609  {
610  Event_t e = *event;
611  TGLUtil::PointToViewport(e.fX, e.fY);
614  if (fGLViewer->RequestOverlaySelect(event->fX, event->fY))
616  }
619  {
621  }
622 
624 
625  if (fGLViewer->fGLDevice != -1)
626  {
627  gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kFALSE);
628  }
629 
630  if (event->fX == fButtonPushPos.fX && event->fY == fButtonPushPos.fY)
631  {
632  if (event->fCode == kButton1)
633  {
634  if (event->fState & kKeyShiftMask && fDoInternalSelection)
635  {
636  if (fGLViewer->RequestSelect(event->fX, event->fY))
637  {
639  }
640  }
641  else
642  {
643  SelectForClicked(event);
644  }
645  }
646  else if (event->fCode == kButton3)
647  {
648  Int_t x, y;
649  Window_t childdum;
650  gVirtualX->TranslateCoordinates(fGLViewer->fGLWidget->GetId(), gClient->GetDefaultRoot()->GetId(),
651  event->fX, event->fY, x, y, childdum);
652 
653  fGLViewer->RequestSelect(event->fX, event->fY);
654 
656  }
657  }
658 
659  if (event->fCode == kButton1 && fMouseTimer)
660  {
661  fMouseTimer->TurnOn();
662  }
663  }
664 
665  return kTRUE;
666 }
667 
668 ////////////////////////////////////////////////////////////////////////////////
669 /// Handle mouse double click 'event'.
670 
672 {
673  if (fGLViewer->IsLocked()) {
674  if (gDebug>3) {
675  Info("TGLEventHandler::HandleDoubleClick", "ignored - viewer is %s",
677  }
678  return kFALSE;
679  }
680 
681  if (event->fCode > 3)
682  return kTRUE;
683 
684  if (fActiveButtonID)
685  return kTRUE;
686 
687  fActiveButtonID = event->fCode;
688  GrabMouse();
689 
690  fGLViewer->MouseIdle(0, 0, 0);
691  if (event->fCode == kButton1)
692  {
694  if (fGLViewer->GetSelected() == 0)
696  }
697  return kTRUE;
698 }
699 
700 ////////////////////////////////////////////////////////////////////////////////
701 /// Handle configure notify 'event' - a window resize/movement.
702 
704 {
705  if (fGLViewer->IsLocked())
706  {
707  if (gDebug > 0) {
708  Info("TGLEventHandler::HandleConfigureNotify", "ignored - viewer is %s",
710  }
711  return kFALSE;
712  }
713  if (event)
714  {
715  Int_t x = event->fX, y = event->fY, w = event->fWidth, h = event->fHeight;
717  fGLViewer->SetViewport(x, y, w, h);
719  }
720  return kTRUE;
721 }
722 
723 ////////////////////////////////////////////////////////////////////////////////
724 /// Handle window expose 'event' - show.
725 
727 {
728  if (event->fCount != 0) return kTRUE;
729 
730  if (fGLViewer->IsLocked()) {
731  if (gDebug > 0) {
732  Info("TGLViewer::HandleExpose", "ignored - viewer is %s",
734  }
735  return kFALSE;
736  }
737 
739  return kTRUE;
740 }
741 
742 ////////////////////////////////////////////////////////////////////////////////
743 /// Handle keyboard 'event'.
744 
746 {
747  // We only handle key-press events.
748  if (event->fType == kKeyRelease)
749  return kTRUE;
750 
751  if (fTooltipShown)
752  fTooltip->Hide();
753 
754  fLastEventState = event->fState;
755 
756  fGLViewer->MouseIdle(0, 0, 0);
757  if (fGLViewer->IsLocked()) {
758  if (gDebug>3) {
759  Info("TGLEventHandler::HandleKey", "ignored - viewer is %s",
761  }
762  return kFALSE;
763  }
764 
765  char tmp[10] = {0};
766  UInt_t keysym = 0;
767 
768  if (fGLViewer->fGLDevice == -1)
769  gVirtualX->LookupString(event, tmp, sizeof(tmp), keysym);
770  else
771  keysym = event->fCode;
772  fGLViewer->fRnrCtx->SetEventKeySym(keysym);
773 
774  Bool_t handled = kFALSE;
775  Bool_t redraw = kFALSE;
776 
778  {
779  Event_t e = *event;
780  TGLUtil::PointToViewport(e.fX, e.fY);
782  {
783  handled = kTRUE;
784  redraw = kTRUE;
785  }
786  }
787 
788  if ( ! handled)
789  {
790  const Bool_t mod1 = event->fState & kKeyControlMask;
791  const Bool_t mod2 = event->fState & kKeyShiftMask;
792 
793  const Int_t shift = TMath::Nint(fArrowKeyFactor * ControlValue(10));
794 
795  switch (keysym)
796  {
797  case kKey_R:
798  case kKey_r:
800  redraw = kTRUE;
801  break;
802  case kKey_E:
803  case kKey_e:
805  redraw = kTRUE;
806  break;
807  case kKey_W:
808  case kKey_w:
810  redraw = kTRUE;
811  break;
812  case kKey_T:
813  case kKey_t:
815  redraw = kTRUE;
816  break;
817 
818  case kKey_F1:
821  break;
822 
823  // Camera
824  case kKey_A:
825  case kKey_a:
826  fArcBall = ! fArcBall;
827  break;
828  case kKey_Plus:
829  case kKey_J:
830  case kKey_j:
831  redraw = fGLViewer->CurrentCamera().Dolly(shift, mod1, mod2);
832  break;
833  case kKey_Minus:
834  case kKey_K:
835  case kKey_k:
836  redraw = fGLViewer->CurrentCamera().Dolly(-shift, mod1, mod2);
837  break;
838  case kKey_Up:
839  redraw = fGLViewer->CurrentCamera().Truck(0, shift, mod1, mod2);
840  break;
841  case kKey_Down:
842  redraw = fGLViewer->CurrentCamera().Truck(0, -shift, mod1, mod2);
843  break;
844  case kKey_Left:
845  redraw = fGLViewer->CurrentCamera().Truck(-shift, 0, mod1, mod2);
846  break;
847  case kKey_Right:
848  redraw = fGLViewer->CurrentCamera().Truck(shift, 0, mod1, mod2);
849  break;
850  case kKey_Home:
851  if (mod1) {
855  } else {
857  }
858  redraw = kTRUE;
859  break;
860 
861  // Toggle debugging mode
862  case kKey_d:
864  redraw = kTRUE;
865  Info("OpenGL viewer debug mode : ", fGLViewer->fDebugMode ? "ON" : "OFF");
866  break;
867  // Forced rebuild for debugging mode
868  case kKey_D:
869  if (fGLViewer->fDebugMode) {
870  Info("OpenGL viewer FORCED rebuild", " ");
872  }
873  default:;
874  } // switch
875  }
876 
877  if (redraw) {
878  if (fGLViewer->fGLDevice != -1)
879  gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kTRUE);
881  }
882 
883  return kTRUE;
884 }
885 
886 ////////////////////////////////////////////////////////////////////////////////
887 /// Handle mouse motion 'event'.
888 
890 {
891  fGLViewer->MouseIdle(0, 0, 0);
892  if (fGLViewer->IsLocked()) {
893  if (gDebug>3) {
894  Info("TGLEventHandler::HandleMotion", "ignored - viewer is %s",
896  }
897  return kFALSE;
898  }
899 
900  Bool_t processed = kFALSE, changed = kFALSE;
902 
903  // Camera interface requires GL coords - Y inverted
906  Bool_t mod1 = event->fState & kKeyControlMask;
907  Bool_t mod2 = event->fState & kKeyShiftMask;
908  TGLUtil::PointToViewport(xDelta, yDelta);
909 
911 
912  if (fTooltipShown &&
915  {
916  RemoveTooltip();
917  }
918 
920  {
921  if (fGLViewer->fRedrawTimer->IsPending()) {
922  if (gDebug > 2)
923  Info("TGLEventHandler::HandleMotion", "Redraw pending, ignoring.");
924  return kTRUE;
925  }
926  changed = fGLViewer->RequestOverlaySelect(event->fX, event->fY);
928  {
929  Event_t e = *event;
930  TGLUtil::PointToViewport(e.fX, e.fY);
932  }
933  lod = TGLRnrCtx::kLODHigh;
934  if ( ! processed && ! fMouseTimerRunning)
935  StartMouseTimer();
936  }
938  {
939  processed = Rotate(xDelta, yDelta, mod1, mod2);
940  }
942  {
943  processed = fGLViewer->CurrentCamera().Truck(xDelta, -yDelta, mod1, mod2);
944  }
946  {
947  processed = fGLViewer->CurrentCamera().Dolly(yDelta - xDelta, mod1, mod2);
948  }
950  {
951  if (fGLViewer->fCurrentOvlElm) {
952  Event_t e = *event;
953  TGLUtil::PointToViewport(e.fX, e.fY);
955  }
956  }
957 
958  fLastPos.fX = event->fX;
959  fLastPos.fY = event->fY;
960 
961  fLastGlobalPos.fX = event->fXRoot;
962  fLastGlobalPos.fY = event->fYRoot;
963 
964  if (processed || changed) {
965  if (fGLViewer->fGLDevice != -1) {
966  gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kTRUE);
967  gVirtualX->SetDrawMode(TVirtualX::kCopy);
968  }
969 
970  fGLViewer->RequestDraw(lod);
971  }
972 
973  return processed;
974 }
975 
976 ////////////////////////////////////////////////////////////////////////////////
977 /// Method to handle action TGLViewer::kDragCameraRotate.
978 
980 {
982  if (fArcBall) return cam.RotateArcBall(xDelta, -yDelta, mod1, mod2);
983  else return cam.Rotate (xDelta, -yDelta, mod1, mod2);
984 }
985 
986 ////////////////////////////////////////////////////////////////////////////////
987 /// If mouse delay timer times out emit signal.
988 
990 {
991  if (t != fMouseTimer) return kFALSE;
992 
994 
995  if (fGLViewer->fRedrawTimer->IsPending()) {
996  if (gDebug > 2)
997  Info("TGLEventHandler::HandleTimer", "Redraw pending, ignoring.");
998  return kTRUE;
999  }
1000 
1002  {
1003  if (fLastMouseOverPos != fLastPos)
1004  {
1006  }
1007  }
1008  return kTRUE;
1009 }
1010 
1011 ////////////////////////////////////////////////////////////////////////////////
1012 /// Start mouse timer in single-shot mode.
1013 
1015 {
1016  fMouseTimer->Start(-1, kTRUE);
1018 }
1019 
1020 ////////////////////////////////////////////////////////////////////////////////
1021 /// Make sure mouse timers are not running.
1022 
1024 {
1026  fMouseTimer->Stop();
1027 }
1028 
1029 ////////////////////////////////////////////////////////////////////////////////
1030 /// Clear mouse-over state and emit mouse-over signals.
1031 /// Current overlay element is also told the mouse has left.
1032 
1034 {
1036  fLastMouseOverShape = 0;
1040 
1042 }
1043 
1044 ////////////////////////////////////////////////////////////////////////////////
1045 /// Handle window expose 'event' - show.
1046 
1048 {
1049  if (fGLViewer->IsLocked()) {
1050  if (gDebug > 0) {
1051  Info("TGLViewer::HandleExpose", "ignored - viewer is %s",
1053  }
1054  return;
1055  }
1057 }
1058 
1059 ////////////////////////////////////////////////////////////////////////////////
1060 /// Popup context menu.
1061 
1063  Int_t gx, Int_t gy)
1064 {
1065  if (!fGLViewer->fContextMenu)
1066  {
1067  fGLViewer->fContextMenu = new TContextMenu("glcm", "GL Viewer Context Menu");
1068  }
1069 
1070  if (pshp)
1071  {
1072  fActiveButtonID = 0;
1073  UnGrabMouse();
1074 
1075  pshp->InvokeContextMenu(*fGLViewer->fContextMenu, gx, gy);
1076  }
1077 
1078  // This is dangerous ... should have special menu, probably even
1079  // tool / context specific.
1080  // else
1081  // {
1082  // fGLViewer->fContextMenu->Popup(x, y, fGLViewer);
1083  // }
1084 }
1085 
1086 ////////////////////////////////////////////////////////////////////////////////
1087 /// Trigger display of tooltip.
1088 
1090 {
1091  static UInt_t screenW = 0, screenH = 0;
1093  fTooltipShown = kTRUE;
1094  fTooltip->SetText(text);
1095  Int_t x = fTooltipPos.fX + 16, y = fTooltipPos.fY + 16;
1096  if (screenW == 0 || screenH == 0) {
1097  screenW = gClient->GetDisplayWidth();
1098  screenH = gClient->GetDisplayHeight();
1099  }
1100  if (x + 5 + fTooltip->GetWidth() > screenW) {
1101  x = screenW - fTooltip->GetWidth() - 5;
1102  if (y + 5 + fTooltip->GetHeight() > screenH) {
1103  y -= (25 + fTooltip->GetHeight());
1104  }
1105  }
1106  if (y + 5 + fTooltip->GetHeight() > screenH) {
1107  y = screenH - fTooltip->GetHeight() - 10;
1108  }
1109  fTooltip->SetPosition(x, y);
1110  fTooltip->Reset();
1111 }
1112 
1113 ////////////////////////////////////////////////////////////////////////////////
1114 /// Hide the tooltip.
1115 
1117 {
1118  fTooltip->Hide();
1120 }
1121 
1122 ////////////////////////////////////////////////////////////////////////////////
1123 /// Set delay of mouse-over probe (highlight).
1124 
1126 {
1128 }
1129 
1130 ////////////////////////////////////////////////////////////////////////////////
1131 /// Set delay of tooltip timer.
1132 
1134 {
1135  fTooltip->SetDelay(ms);
1136 }
virtual void ReMouseOver(TObject *obj, UInt_t state)
Emit MouseOver signal.
Definition: TGLViewer.cxx:2127
TGLSelectRecord fSelRec
select record in use as selected
Definition: TGLViewer.h:114
virtual void ProcessSelection(TGLRnrCtx &rnrCtx, TGLSelectRecord &rec)
Virtual method called-back after a secondary selection hit is recorded (see TGLViewer::HandleButton()...
void InvokeContextMenu(TContextMenu &menu, UInt_t x, UInt_t y) const
Request creation of context menu on shape, attached to 'menu' at screen position 'x' 'y'...
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
Abstract base camera class - concrete classes for orthographic and perspective cameras derive from it...
Definition: TGLCamera.h:43
const Mask_t kKeyMod2Mask
Definition: GuiTypes.h:198
void Reset()
Reset the timer.
Definition: TTimer.cxx:157
virtual void MouseOver(TGLPhysicalShape *)
Emit MouseOver signal.
Definition: TGLViewer.cxx:2097
void SwitchColorSet()
Switch between dark and light colorsets.
Definition: TGLViewer.cxx:1635
const Mask_t kKeyShiftMask
Definition: GuiTypes.h:194
const Mask_t kKeyMod1Mask
Definition: GuiTypes.h:197
TGLEventHandler(TGWindow *w, TObject *obj)
Constructor.
void Reset()
Reset tool tip popup delay timer.
Definition: TGToolTip.cxx:259
Int_t fCount
Definition: GuiTypes.h:182
void SetText(const char *new_text)
Set new tool tip text.
Definition: TGToolTip.cxx:386
GL-overlay annotation.
Definition: TGLAnnotation.h:25
UInt_t GetHeight() const
Definition: TGFrame.h:272
TGLLogicalShape * GetLogShape() const
void ResetCurrentCamera()
Resets position/rotation of current camera to default values.
Definition: TGLViewer.cxx:360
Bool_t RequestOverlaySelect(Int_t x, Int_t y)
Post request for secondary selection rendering of selected object around the window point (x...
Definition: TGLViewer.cxx:1491
Float_t fMouseWheelFactor
SCoord_t fX
Definition: TPoint.h:35
Int_t fY
Definition: GuiTypes.h:177
SCoord_t fY
Definition: TPoint.h:36
#define gClient
Definition: TGClient.h:166
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
virtual void SelectForMouseOver()
Run selection (optionally with on secondary selection) and emit corresponding MouseOver() signals...
const TGLPhysicalShape * GetSelected() const
Return selected physical shape.
Definition: TGLViewer.cxx:2086
static void PointToViewport(Int_t &x, Int_t &y)
Convert from point/screen coordinates to GL viewport coordinates.
Definition: TGLUtil.cxx:1818
virtual void UnGrabMouse()
Release mouse grab.
void Hide()
Hide tool tip window.
Definition: TGToolTip.cxx:246
virtual Bool_t RotateArcBall(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
Rotate the camera round view volume center established in Setup().
Definition: TGLCamera.cxx:990
TGLRect & RefViewport()
Definition: TGLCamera.h:128
virtual void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Process event of type 'event' - one of EEventType types, occurring at window location px...
Bool_t RequestSecondarySelect(Int_t x, Int_t y)
Request secondary select.
Definition: TGLViewer.cxx:1384
virtual void UnMouseOver(TObject *obj, UInt_t state)
Emit UnMouseOver signal.
Definition: TGLViewer.cxx:2139
UInt_t GetWidth() const
Definition: TGFrame.h:271
TGLVertex3 ViewportToWorld(const TGLVertex3 &viewportVertex, TGLMatrix *modviewMat=0) const
Convert a '3D' viewport vertex to 3D world one.
Definition: TGLCamera.cxx:442
Short_t Abs(Short_t d)
Definition: TMathBase.h:120
Handle_t GetId() const
Definition: TGObject.h:47
TTimer * fMouseTimer
Concrete physical shape - a GL drawable.
Int_t ControlValue(Int_t v)
TGLCamera & CurrentCamera() const
Definition: TGLViewer.h:269
Bool_t fMouseTimerRunning
virtual ~TGLEventHandler()
Destructor.
const Mask_t kPointerMotionMask
Definition: GuiTypes.h:162
Bool_t fDoInternalSelection
TGLPhysicalShape * GetPhysShape() const
Double_t x[n]
Definition: legend1.C:17
virtual void OverlayDragFinished()
An overlay operation can result in change to an object.
Definition: TGLViewer.cxx:2267
Bool_t fDebugMode
cache logicals during scene rebuilds
Definition: TGLViewer.h:158
TGLRedrawTimer * fRedrawTimer
Definition: TGLViewer.h:137
TGLRnrCtx * fRnrCtx
Definition: TGLViewerBase.h:62
virtual void Start(Long_t milliSec=-1, Bool_t singleShot=kFALSE)
Starts the timer with a milliSec timeout.
Definition: TTimer.cxx:211
Int_t fXRoot
Definition: GuiTypes.h:178
virtual Bool_t HandleEvent(Event_t *event)
Handle generic Event_t type 'event' - provided to catch focus changes and terminate any interaction i...
Viewport (pixel base) 2D rectangle class.
Definition: TGLUtil.h:420
virtual Bool_t Rotate(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
Rotate the camera round view volume center established in Setup().
Definition: TGLCamera.cxx:916
3 component (x/y/z) vector class.
Definition: TGLUtil.h:246
void SetMouseOverTooltipDelay(Int_t ms)
Set delay of tooltip timer.
void SetDelay(Long_t delayms)
Set delay in milliseconds.
Definition: TGToolTip.cxx:395
void SetPosition(Int_t x, Int_t y)
Set popup position within specified frame (as specified in the ctor).
Definition: TGToolTip.cxx:405
virtual Bool_t HandleMotion(Event_t *event)
Handle mouse motion 'event'.
void ApplySelection()
Process result from last selection (in fSelRec) and extract a new current selection from it...
Definition: TGLViewer.cxx:1474
TGLWidget * fGLWidget
Definition: TGLViewer.h:187
void SetMultiple(Bool_t multi)
virtual void GrabMouse()
Acquire mouse grab.
void UpdateScene(Bool_t redraw=kTRUE)
Force update of pad-scenes.
Definition: TGLViewer.cxx:338
virtual void StopMouseTimer()
Make sure mouse timers are not running.
TGLSelectRecord & GetSelRec()
Definition: TGLViewer.h:391
void SetEventKeySym(UInt_t k)
Definition: TGLRnrCtx.h:248
virtual void PopupContextMenu(TGLPhysicalShape *pshp, Event_t *event, Int_t gx, Int_t gy)
Popup context menu.
const Mask_t kButtonPressMask
Definition: GuiTypes.h:160
void RequestDraw(Short_t LOD=TGLRnrCtx::kLODMed)
Post request for redraw of viewer at level of detail 'LOD' Request is directed via cross thread gVirt...
Definition: TGLViewer.cxx:440
void SetMouseOverSelectDelay(Int_t ms)
Set delay of mouse-over probe (highlight).
TGLViewer * fGLViewer
void WindowToViewport(Int_t &, Int_t &y) const
Definition: TGLCamera.h:198
virtual Bool_t HandleTimer(TTimer *t)
If mouse delay timer times out emit signal.
Bool_t RequestSelect(Int_t x, Int_t y)
Post request for selection render pass viewer, picking objects around the window point (x...
Definition: TGLViewer.cxx:1308
Float_t fArrowKeyFactor
EGEventType fType
Definition: GuiTypes.h:174
void RequestDraw(Int_t milliSec, Short_t redrawLOD)
Definition: TGLViewer.h:412
Standard selection record including information about containing scene and details ob out selected ob...
static constexpr double ms
Int_t fGLDevice
Definition: TGLViewer.h:188
This class provides an interface to context sensitive popup menus.
Definition: TContextMenu.h:40
virtual Bool_t HandleFocusChange(Event_t *event)
Handle generic Event_t type 'event' - provided to catch focus changes and terminate any interaction i...
virtual Bool_t Zoom(Int_t delta, Bool_t mod1, Bool_t mod2)=0
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual void Clicked(TObject *obj)
Emit Clicked signal.
Definition: TGLViewer.cxx:2150
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
const Handle_t kNone
Definition: GuiTypes.h:87
void SetExternalCenter(Bool_t x)
Set camera center diffrent than scene center, if enable is kTRUE.
Definition: TGLCamera.cxx:825
TGToolTip * fTooltip
EDragAction fDragAction
Definition: TGLViewer.h:134
virtual void TurnOff()
Remove timer from system timer list.
Definition: TTimer.cxx:229
ELock CurrentLock() const
Definition: TGLLockable.h:61
virtual Bool_t Truck(Double_t xDelta, Double_t yDelta)
Truck the camera - 'move camera parallel to film plane'.
Definition: TGLCamera.cxx:894
short Short_t
Definition: RtypesCore.h:35
virtual void DoubleClicked()
Definition: TGLViewer.h:377
Int_t fYRoot
Definition: GuiTypes.h:178
TGLOvlSelectRecord fOvlSelRec
current overlay element
Definition: TGLViewer.h:119
Handles synchronous and a-synchronous timer events.
Definition: TTimer.h:51
virtual Bool_t Handle(TGLRnrCtx &rnrCtx, TGLOvlSelectRecord &selRec, Event_t *event)
Handle overlay event.
Definition: TGLOverlay.cxx:46
Base GL viewer object - used by both standalone and embedded (in pad) GL.
Definition: TGLViewer.h:53
#define gVirtualX
Definition: TVirtualX.h:345
Int_t fTooltipPixelTolerance
#define h(i)
Definition: RSha256.hxx:106
virtual Bool_t HandleDoubleClick(Event_t *event)
Handle mouse double click 'event'.
ESecSelResult GetSecSelResult() const
Abstract logical shape - a GL 'drawable' - base for all shapes - faceset sphere etc.
Int_t Width() const
Definition: TGLUtil.h:449
const Bool_t kFALSE
Definition: RtypesCore.h:88
void SetCenterVec(Double_t x, Double_t y, Double_t z)
Set camera center vector.
Definition: TGLCamera.cxx:847
TGLPhysicalShape * fLastMouseOverShape
virtual void TriggerTooltip(const char *text)
Trigger display of tooltip.
virtual void ClearMouseOver()
Clear mouse-over state and emit mouse-over signals.
static const char * LockName(ELock lock)
Return name-string for given lock-type.
Definition: TGLLockable.cxx:69
#define ClassImp(name)
Definition: Rtypes.h:365
TObject * GetObject() const
TText * text
void SetViewport(Int_t x, Int_t y, Int_t width, Int_t height)
Set viewer viewport (window area) with bottom/left at (x,y), with dimensions 'width'/'height'.
Definition: TGLViewer.cxx:1724
const Mask_t kButtonReleaseMask
Definition: GuiTypes.h:161
EPushAction fPushAction
Definition: TGLViewer.h:133
UInt_t fCode
Definition: GuiTypes.h:179
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
Base-class and default implementation of event-handler for TGLViewer.
Double_t y[n]
Definition: legend1.C:17
virtual void SelectionChanged()
Update GUI components for embedded viewer selection change.
Definition: TGLViewer.cxx:2247
virtual void ReClicked(TObject *obj, UInt_t button, UInt_t state)
Emit ReClicked signal with button id and modifier state.
Definition: TGLViewer.cxx:2171
#define gGLManager
Definition: TVirtualGL.h:162
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
virtual Bool_t Dolly(Int_t delta, Bool_t mod1, Bool_t mod2)
Dolly the camera - 'move camera along eye line, retaining lens focal length'.
Definition: TGLCamera.cxx:1046
TContextMenu * fContextMenu
external pad - remove replace with signal
Definition: TGLViewer.h:83
Bool_t IsLocked() const
Definition: TGLLockable.h:60
TGLOverlayElement * fCurrentOvlElm
Definition: TGLViewer.h:118
void SetHighlight(Bool_t hlt)
Mother of all ROOT objects.
Definition: TObject.h:37
Bool_t IsPending() const
Definition: TGLViewer.h:418
virtual void RefreshPadEditor(TObject *obj=0)
Update GED editor if it is set.
Definition: TGLViewer.cxx:2278
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:401
virtual Bool_t HandleCrossing(Event_t *event)
Handle generic Event_t type 'event' - provided to catch focus changes and terminate any interaction i...
Handle_t Window_t
Definition: GuiTypes.h:28
void ClearCurrentOvlElm()
Reset current overlay-element to zero, eventually notifying the old one that the mouse has left...
Definition: TGLViewer.cxx:2320
virtual void SelectForClicked(Event_t *event)
Run selection (optionally with on secondary selection) and emit corresponding Clicked() signals...
virtual Bool_t HandleExpose(Event_t *event)
Handle window expose 'event' - show.
virtual void MouseIdle(TGLPhysicalShape *, UInt_t, UInt_t)
Emit MouseIdle signal.
Definition: TGLViewer.cxx:2195
EPushAction GetPushAction() const
Definition: TGLViewer.h:300
TPoint fLastMouseOverPos
Float_t GetMinZ() const
Int_t GetN() const
virtual Bool_t Rotate(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
Method to handle action TGLViewer::kDragCameraRotate.
Bool_t GetExternalCenter()
Definition: TGLCamera.h:153
#define gPad
Definition: TVirtualPad.h:286
UInt_t fState
Definition: GuiTypes.h:180
R__EXTERN Int_t gDebug
Definition: Rtypes.h:91
virtual void Activated()
Definition: TGLViewer.h:364
virtual Bool_t HandleConfigureNotify(Event_t *event)
Handle configure notify 'event' - a window resize/movement.
virtual void Stop()
Definition: TTimer.h:93
virtual void UnClicked(TObject *obj, UInt_t button, UInt_t state)
Emit UnClicked signal with button id and modifier state.
Definition: TGLViewer.cxx:2183
const Mask_t kKeyControlMask
Definition: GuiTypes.h:196
virtual void StartMouseTimer()
Start mouse timer in single-shot mode.
Int_t Height() const
Definition: TGLUtil.h:451
virtual Bool_t AlwaysSecondarySelect() const
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
virtual void TurnOn()
Add the timer to the system timer list.
Definition: TTimer.cxx:241
const Bool_t kTRUE
Definition: RtypesCore.h:87
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition: TMath.h:703
Bool_t fViewerCentricControls
Float_t fMouseDragFactor
Int_t fX
Definition: GuiTypes.h:177
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
void SetStyle(Short_t st)
virtual Bool_t HandleButton(Event_t *event)
Handle mouse button 'event'.
virtual void RemoveTooltip()
Hide the tooltip.
virtual Bool_t HandleKey(Event_t *event)
Handle keyboard 'event'.
TGLSelectRecord fSecSelRec
select record from last select (should go to context)
Definition: TGLViewer.h:115
void SetTime(Long_t milliSec)
Definition: TTimer.h:90
virtual void Repaint()
Handle window expose 'event' - show.
TGLWidget * GetGLWidget()
Definition: TGLViewer.h:225