#include "TGLEventHandler.h"
#include "TGEventHandler.h"
#include "TGLViewer.h"
#include "TGLWidget.h"
#include "TGWindow.h"
#include "TPoint.h"
#include "TVirtualPad.h"
#include "TVirtualX.h"
#include "TGClient.h"
#include "TVirtualGL.h"
#include "TGLOverlay.h"
#include "TGLLogicalShape.h"
#include "TGLPhysicalShape.h"
#include "TContextMenu.h"
#include "TGToolTip.h"
#include "KeySymbols.h"
#include "TGLAnnotation.h"
#include "TEnv.h"
#include "TMath.h"
#include "RConfigure.h"
ClassImp(TGLEventHandler);
TGLEventHandler::TGLEventHandler(TGWindow *w, TObject *obj) :
TGEventHandler ("TGLEventHandler", w, obj),
fGLViewer ((TGLViewer *)obj),
fMouseTimer (0),
fLastPos (-1, -1),
fLastMouseOverPos (-1, -1),
fLastMouseOverShape (0),
fTooltip (0),
fActiveButtonID (0),
fLastEventState (0),
fIgnoreButtonUp (kFALSE),
fInPointerGrab (kFALSE),
fMouseTimerRunning (kFALSE),
fTooltipShown (kFALSE),
fArcBall (kFALSE),
fTooltipPixelTolerance (3),
fSecSelType(TGLViewer::kOnRequest),
fDoInternalSelection(kTRUE),
fViewerCentricControls(kFALSE)
{
fMouseTimer = new TTimer(this, 80);
fTooltip = new TGToolTip(0, 0, "", 650);
fTooltip->Hide();
fViewerCentricControls = gEnv->GetValue("OpenGL.EventHandler.ViewerCentricControls", 0) != 0;
fArrowKeyFactor = gEnv->GetValue("OpenGL.EventHandler.ArrowKeyFactor", 1.0);
fMouseDragFactor = gEnv->GetValue("OpenGL.EventHandler.MouseDragFactor", 1.0);
fMouseWheelFactor = gEnv->GetValue("OpenGL.EventHandler.MouseWheelFactor", 1.0);
}
TGLEventHandler::~TGLEventHandler()
{
delete fMouseTimer;
delete fTooltip;
}
void TGLEventHandler::GrabMouse()
{
if (!fInPointerGrab)
{
gVirtualX->GrabPointer(fGLViewer->GetGLWidget()->GetId(),
kButtonPressMask | kButtonReleaseMask | kPointerMotionMask,
kNone, kNone, kTRUE, kFALSE);
fInPointerGrab = kTRUE;
}
}
void TGLEventHandler::UnGrabMouse()
{
if (fInPointerGrab)
{
gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
fInPointerGrab = kFALSE;
}
}
void TGLEventHandler::SelectForClicked(Event_t *event)
{
fGLViewer->RequestSelect(fLastPos.fX, fLastPos.fY);
TGLLogicalShape *lshp = fGLViewer->fSelRec.GetLogShape();
TObject *obj = fGLViewer->fSelRec.GetObject();
if (lshp && (event->fState & kKeyMod1Mask || (fSecSelType == TGLViewer::kOnRequest && lshp->AlwaysSecondarySelect())))
{
fGLViewer->RequestSecondarySelect(fLastPos.fX, fLastPos.fY);
fGLViewer->fSecSelRec.SetMultiple(event->fState & kKeyControlMask);
lshp->ProcessSelection(*fGLViewer->fRnrCtx, fGLViewer->fSecSelRec);
switch (fGLViewer->fSecSelRec.GetSecSelResult())
{
case TGLSelectRecord::kEnteringSelection:
fGLViewer->Clicked(obj, event->fCode, event->fState);
break;
case TGLSelectRecord::kLeavingSelection:
fGLViewer->UnClicked(obj, event->fCode, event->fState);
break;
case TGLSelectRecord::kModifyingInternalSelection:
fGLViewer->ReClicked(obj, event->fCode, event->fState);
break;
default:
break;
}
}
else
{
fGLViewer->Clicked(obj);
fGLViewer->Clicked(obj, event->fCode, event->fState);
}
}
void TGLEventHandler::SelectForMouseOver()
{
fGLViewer->RequestSelect(fLastPos.fX, fLastPos.fY);
TGLPhysicalShape *pshp = fGLViewer->fSelRec.GetPhysShape();
TGLLogicalShape *lshp = fGLViewer->fSelRec.GetLogShape();
TObject *obj = fGLViewer->fSelRec.GetObject();
if (lshp && (fSecSelType == TGLViewer::kOnRequest && lshp->AlwaysSecondarySelect()))
{
fGLViewer->RequestSecondarySelect(fLastPos.fX, fLastPos.fY);
fGLViewer->fSecSelRec.SetMultiple(kFALSE);
fGLViewer->fSecSelRec.SetHighlight(kTRUE);
lshp->ProcessSelection(*fGLViewer->fRnrCtx, fGLViewer->fSecSelRec);
fGLViewer->fSecSelRec.SetHighlight(kFALSE);
switch (fGLViewer->fSecSelRec.GetSecSelResult())
{
case TGLSelectRecord::kEnteringSelection:
fGLViewer->MouseOver(obj, fLastEventState);
break;
case TGLSelectRecord::kModifyingInternalSelection:
fGLViewer->ReMouseOver(obj, fLastEventState);
break;
case TGLSelectRecord::kLeavingSelection:
fGLViewer->UnMouseOver(obj, fLastEventState);
break;
default:
break;
}
}
else if (fLastMouseOverShape != pshp)
{
fGLViewer->MouseOver(pshp);
fGLViewer->MouseOver(pshp, fLastEventState);
fGLViewer->MouseOver(obj, fLastEventState);
}
fLastMouseOverShape = pshp;
fLastMouseOverPos = fLastPos;
}
void TGLEventHandler::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
Event_t eventSt = { kOtherEvent, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
kFALSE, 0, 0, {0, 0, 0, 0, 0} };
eventSt.fX = px;
eventSt.fY = py;
eventSt.fState = 0;
eventSt.fXRoot = eventSt.fYRoot = 0;
if (event != kKeyPress) {
eventSt.fY -= Int_t((1 - gPad->GetHNDC() - gPad->GetYlowNDC()) * gPad->GetWh());
eventSt.fX -= Int_t(gPad->GetXlowNDC() * gPad->GetWw());
eventSt.fXRoot = eventSt.fX;
eventSt.fYRoot = eventSt.fY;
}
switch (event) {
case kMouseMotion:
eventSt.fCode = kMouseMotion;
eventSt.fType = kMotionNotify;
HandleMotion(&eventSt);
break;
case kButton1Down:
case kButton1Up:
{
eventSt.fCode = kButton1;
eventSt.fType = event == kButton1Down ? kButtonPress:kButtonRelease;
HandleButton(&eventSt);
}
break;
case kButton2Down:
case kButton2Up:
{
eventSt.fCode = kButton2;
eventSt.fType = event == kButton2Down ? kButtonPress:kButtonRelease;
HandleButton(&eventSt);
}
break;
case kButton3Down:
{
eventSt.fState = kKeyShiftMask;
eventSt.fCode = kButton1;
eventSt.fType = kButtonPress;
HandleButton(&eventSt);
}
break;
case kButton3Up:
{
eventSt.fCode = kButton3;
eventSt.fType = kButtonRelease;
HandleButton(&eventSt);
}
break;
case kButton1Double:
case kButton2Double:
case kButton3Double:
{
eventSt.fCode = kButton1Double ? kButton1 : kButton2Double ? kButton2 : kButton3;
eventSt.fType = kButtonDoubleClick;
HandleDoubleClick(&eventSt);
}
break;
case kButton1Motion:
case kButton2Motion:
case kButton3Motion:
{
eventSt.fCode = event == kButton1Motion ? kButton1 : event == kButton2Motion ? kButton2 : kButton3;
eventSt.fType = kMotionNotify;
HandleMotion(&eventSt);
}
break;
case kKeyPress:
{
eventSt.fType = kGKeyPress;
eventSt.fCode = py;
HandleKey(&eventSt);
}
break;
case 6:
if (fGLViewer->CurrentCamera().Zoom(+50, kFALSE, kFALSE)) {
if (fGLViewer->fGLDevice != -1) {
gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kTRUE);
gVirtualX->SetDrawMode(TVirtualX::kCopy);
}
fGLViewer->RequestDraw();
}
break;
case 5:
if (fGLViewer->CurrentCamera().Zoom(-50, kFALSE, kFALSE)) {
if (fGLViewer->fGLDevice != -1) {
gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kTRUE);
gVirtualX->SetDrawMode(TVirtualX::kCopy);
}
fGLViewer->RequestDraw();
}
break;
case 7:
eventSt.fState = kKeyShiftMask;
eventSt.fCode = kButton1;
eventSt.fType = kButtonPress;
HandleButton(&eventSt);
break;
default:
{
}
}
}
Bool_t TGLEventHandler::HandleEvent(Event_t *event)
{
if (event->fType == kFocusIn) {
if (fGLViewer->fDragAction != TGLViewer::kDragNone) {
Error("TGLEventHandler::HandleEvent", "active drag-action at focus-in.");
fGLViewer->fDragAction = TGLViewer::kDragNone;
}
StartMouseTimer();
}
if (event->fType == kFocusOut) {
if (fGLViewer->fDragAction != TGLViewer::kDragNone) {
Warning("TGLEventHandler::HandleEvent", "drag-action active at focus-out.");
fGLViewer->fDragAction = TGLViewer::kDragNone;
}
StopMouseTimer();
ClearMouseOver();
}
return kTRUE;
}
Bool_t TGLEventHandler::HandleFocusChange(Event_t *event)
{
fGLViewer->MouseIdle(0, 0, 0);
if (event->fType == kFocusIn) {
if (fGLViewer->fDragAction != TGLViewer::kDragNone) {
Error("TGLEventHandler::HandleFocusChange", "active drag-action at focus-in.");
fGLViewer->fDragAction = TGLViewer::kDragNone;
}
StartMouseTimer();
fGLViewer->Activated();
}
if (event->fType == kFocusOut) {
if (fGLViewer->fDragAction != TGLViewer::kDragNone) {
Warning("TGLEventHandler::HandleFocusChange", "drag-action active at focus-out.");
fGLViewer->fDragAction = TGLViewer::kDragNone;
}
StopMouseTimer();
ClearMouseOver();
}
return kTRUE;
}
Bool_t TGLEventHandler::HandleCrossing(Event_t *event)
{
if (event->fCode != 0) {
return kTRUE;
}
fGLViewer->MouseIdle(0, 0, 0);
if (event->fType == kEnterNotify) {
if (fGLViewer->fDragAction != TGLViewer::kDragNone) {
Error("TGLEventHandler::HandleCrossing", "active drag-action at enter-notify.");
fGLViewer->fDragAction = TGLViewer::kDragNone;
}
StartMouseTimer();
fGLViewer->Activated();
}
if (event->fType == kLeaveNotify) {
if (fGLViewer->fDragAction != TGLViewer::kDragNone) {
Warning("TGLEventHandler::HandleCrossing", "drag-action active at leave-notify.");
fGLViewer->fDragAction = TGLViewer::kDragNone;
}
StopMouseTimer();
ClearMouseOver();
}
return kTRUE;
}
Bool_t TGLEventHandler::HandleButton(Event_t * event)
{
if (fGLViewer->IsLocked()) {
if (gDebug>2) {
Info("TGLEventHandler::HandleButton", "ignored - viewer is %s",
fGLViewer->LockName(fGLViewer->CurrentLock()));
}
return kFALSE;
}
if (event->fCode > kButton3)
{
if (event->fType == kButtonRelease)
{
Bool_t redraw = kFALSE;
Int_t zoom = TMath::Nint(fMouseWheelFactor * ControlValue(50));
switch(event->fCode)
{
case kButton5:
redraw = fGLViewer->CurrentCamera().Zoom(zoom, kFALSE, kFALSE);
break;
case kButton4:
redraw = fGLViewer->CurrentCamera().Zoom(-zoom, kFALSE, kFALSE);
break;
case kButton6:
case kButton7:
break;
}
if (redraw)
fGLViewer->fRedrawTimer->RequestDraw(10, TGLRnrCtx::kLODMed);
}
return kTRUE;
}
if (fActiveButtonID && event->fCode != fActiveButtonID)
{
return kTRUE;
}
else
{
fActiveButtonID = event->fCode;
}
#if defined(R__HAS_COCOA)
if (event->fCode == kButton1 && event->fState & kKeyMod2Mask)
{
event->fCode = event->fState & kKeyMod1Mask ? kButton3 : kButton2;
}
#endif
if (event->fType == kButtonPress)
{
GrabMouse();
fGLViewer->MouseIdle(0, 0, 0);
fButtonPushPos.fX = event->fX;
fButtonPushPos.fY = event->fY;
if (fGLViewer->GetPushAction() != TGLViewer::kPushStd)
{
fGLViewer->RequestSelect(event->fX, event->fY);
if (fGLViewer->fSelRec.GetN() > 0)
{
TGLVector3 v(event->fX, event->fY, 0.5*fGLViewer->fSelRec.GetMinZ());
fGLViewer->CurrentCamera().WindowToViewport(v);
v = fGLViewer->CurrentCamera().ViewportToWorld(v);
if (fGLViewer->GetPushAction() == TGLViewer::kPushCamCenter)
{
fGLViewer->CurrentCamera().SetExternalCenter(kTRUE);
fGLViewer->CurrentCamera().SetCenterVec(v.X(), v.Y(), v.Z());
}
else
{
TGLSelectRecord& rec = fGLViewer->GetSelRec();
TObject* obj = rec.GetObject();
TGLRect& vp = fGLViewer->CurrentCamera().RefViewport();
Int_t x = event->fX, y = event->fY;
TGLUtil::PointToViewport(x, y);
new TGLAnnotation(fGLViewer, obj->GetTitle(),
x * 1.0f/vp.Width(),
1 - y * 1.0f/vp.Height(), v);
}
fGLViewer->RequestDraw();
}
return kTRUE;
}
Bool_t handled = kFALSE;
if (fGLViewer->fDragAction == TGLViewer::kDragNone && fGLViewer->fCurrentOvlElm)
{
Event_t e = *event;
TGLUtil::PointToViewport(e.fX, e.fY);
if (fGLViewer->fCurrentOvlElm->Handle(*fGLViewer->fRnrCtx, fGLViewer->fOvlSelRec, &e))
{
handled = kTRUE;
fGLViewer->fDragAction = TGLViewer::kDragOverlay;
fGLViewer->RequestDraw();
}
}
if ( ! handled)
{
switch (event->fCode)
{
case kButton1:
{
fGLViewer->fDragAction = TGLViewer::kDragCameraRotate;
if (fMouseTimer)
{
fMouseTimer->TurnOff();
fMouseTimer->Reset();
}
break;
}
case kButton2:
{
fGLViewer->fDragAction = TGLViewer::kDragCameraTruck;
break;
}
case kButton3:
{
fGLViewer->fDragAction = TGLViewer::kDragCameraDolly;
break;
}
}
}
}
else if (event->fType == kButtonRelease)
{
fActiveButtonID = 0;
if (fInPointerGrab)
{
UnGrabMouse();
}
else
{
Warning("TGLEventHandler::HandleButton", "Unexpected button-release.");
}
if (fIgnoreButtonUp)
{
fIgnoreButtonUp = kFALSE;
return kTRUE;
}
if (fGLViewer->GetPushAction() != TGLViewer::kPushStd)
{
fGLViewer->fPushAction = TGLViewer::kPushStd;
fGLViewer->RefreshPadEditor(fGLViewer);
return kTRUE;
}
else if (fGLViewer->fDragAction == TGLViewer::kDragOverlay && fGLViewer->fCurrentOvlElm)
{
Event_t e = *event;
TGLUtil::PointToViewport(e.fX, e.fY);
fGLViewer->fCurrentOvlElm->Handle(*fGLViewer->fRnrCtx, fGLViewer->fOvlSelRec, &e);
fGLViewer->OverlayDragFinished();
if (fGLViewer->RequestOverlaySelect(event->fX, event->fY))
fGLViewer->RequestDraw();
}
else if (fGLViewer->fDragAction >= TGLViewer::kDragCameraRotate &&
fGLViewer->fDragAction <= TGLViewer::kDragCameraDolly)
{
fGLViewer->RequestDraw(TGLRnrCtx::kLODHigh);
}
fGLViewer->fDragAction = TGLViewer::kDragNone;
if (fGLViewer->fGLDevice != -1)
{
gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kFALSE);
}
if (event->fX == fButtonPushPos.fX && event->fY == fButtonPushPos.fY)
{
if (event->fCode == kButton1)
{
if (event->fState & kKeyShiftMask && fDoInternalSelection)
{
if (fGLViewer->RequestSelect(event->fX, event->fY))
{
fGLViewer->ApplySelection();
}
}
else
{
SelectForClicked(event);
}
}
else if (event->fCode == kButton3)
{
Int_t x, y;
Window_t childdum;
gVirtualX->TranslateCoordinates(fGLViewer->fGLWidget->GetId(), gClient->GetDefaultRoot()->GetId(),
event->fX, event->fY, x, y, childdum);
fGLViewer->RequestSelect(event->fX, event->fY);
PopupContextMenu(fGLViewer->fSelRec.GetPhysShape(), event, x, y);
}
}
if (event->fCode == kButton1 && fMouseTimer)
{
fMouseTimer->TurnOn();
}
}
return kTRUE;
}
Bool_t TGLEventHandler::HandleDoubleClick(Event_t *event)
{
if (fGLViewer->IsLocked()) {
if (gDebug>3) {
Info("TGLEventHandler::HandleDoubleClick", "ignored - viewer is %s",
fGLViewer->LockName(fGLViewer->CurrentLock()));
}
return kFALSE;
}
if (event->fCode > 3)
return kTRUE;
if (fActiveButtonID)
return kTRUE;
fActiveButtonID = event->fCode;
GrabMouse();
fGLViewer->MouseIdle(0, 0, 0);
if (event->fCode == kButton1)
{
fGLViewer->DoubleClicked();
if (fGLViewer->GetSelected() == 0)
fGLViewer->SelectionChanged();
}
return kTRUE;
}
Bool_t TGLEventHandler::HandleConfigureNotify(Event_t *event)
{
if (fGLViewer->IsLocked())
{
if (gDebug > 0) {
Info("TGLEventHandler::HandleConfigureNotify", "ignored - viewer is %s",
fGLViewer->LockName(fGLViewer->CurrentLock()));
}
return kFALSE;
}
if (event)
{
Int_t x = event->fX, y = event->fY, w = event->fWidth, h = event->fHeight;
TGLUtil::PointToViewport(x, y, w, h);
fGLViewer->SetViewport(x, y, w, h);
fGLViewer->fRedrawTimer->RequestDraw(10, TGLRnrCtx::kLODMed);
}
return kTRUE;
}
Bool_t TGLEventHandler::HandleExpose(Event_t * event)
{
if (event->fCount != 0) return kTRUE;
if (fGLViewer->IsLocked()) {
if (gDebug > 0) {
Info("TGLViewer::HandleExpose", "ignored - viewer is %s",
fGLViewer->LockName(fGLViewer->CurrentLock()));
}
return kFALSE;
}
fGLViewer->fRedrawTimer->RequestDraw(20, TGLRnrCtx::kLODHigh);
return kTRUE;
}
Bool_t TGLEventHandler::HandleKey(Event_t *event)
{
if (event->fType == kKeyRelease)
return kTRUE;
if (fTooltipShown)
fTooltip->Hide();
fLastEventState = event->fState;
fGLViewer->MouseIdle(0, 0, 0);
if (fGLViewer->IsLocked()) {
if (gDebug>3) {
Info("TGLEventHandler::HandleKey", "ignored - viewer is %s",
fGLViewer->LockName(fGLViewer->CurrentLock()));
}
return kFALSE;
}
char tmp[10] = {0};
UInt_t keysym = 0;
if (fGLViewer->fGLDevice == -1)
gVirtualX->LookupString(event, tmp, sizeof(tmp), keysym);
else
keysym = event->fCode;
fGLViewer->fRnrCtx->SetEventKeySym(keysym);
Bool_t handled = kFALSE;
Bool_t redraw = kFALSE;
if (fGLViewer->fCurrentOvlElm)
{
Event_t e = *event;
TGLUtil::PointToViewport(e.fX, e.fY);
if (fGLViewer->fCurrentOvlElm->Handle(*fGLViewer->fRnrCtx, fGLViewer->fOvlSelRec, &e))
{
handled = kTRUE;
redraw = kTRUE;
}
}
if ( ! handled)
{
const Bool_t mod1 = event->fState & kKeyControlMask;
const Bool_t mod2 = event->fState & kKeyShiftMask;
const Int_t shift = TMath::Nint(fArrowKeyFactor * ControlValue(10));
switch (keysym)
{
case kKey_R:
case kKey_r:
fGLViewer->SetStyle(TGLRnrCtx::kFill);
redraw = kTRUE;
break;
case kKey_E:
case kKey_e:
fGLViewer->SwitchColorSet();
redraw = kTRUE;
break;
case kKey_W:
case kKey_w:
fGLViewer->SetStyle(TGLRnrCtx::kWireFrame);
redraw = kTRUE;
break;
case kKey_T:
case kKey_t:
fGLViewer->SetStyle(TGLRnrCtx::kOutline);
redraw = kTRUE;
break;
case kKey_F1:
fGLViewer->RequestSelect(fLastPos.fX, fLastPos.fY);
fGLViewer->MouseIdle(fGLViewer->fSelRec.GetPhysShape(), (UInt_t)fLastPos.fX, (UInt_t)fLastPos.fY);
break;
case kKey_A:
case kKey_a:
fArcBall = ! fArcBall;
break;
case kKey_Plus:
case kKey_J:
case kKey_j:
redraw = fGLViewer->CurrentCamera().Dolly(shift, mod1, mod2);
break;
case kKey_Minus:
case kKey_K:
case kKey_k:
redraw = fGLViewer->CurrentCamera().Dolly(-shift, mod1, mod2);
break;
case kKey_Up:
redraw = fGLViewer->CurrentCamera().Truck(0, shift, mod1, mod2);
break;
case kKey_Down:
redraw = fGLViewer->CurrentCamera().Truck(0, -shift, mod1, mod2);
break;
case kKey_Left:
redraw = fGLViewer->CurrentCamera().Truck(-shift, 0, mod1, mod2);
break;
case kKey_Right:
redraw = fGLViewer->CurrentCamera().Truck(shift, 0, mod1, mod2);
break;
case kKey_Home:
if (mod1) {
TGLCamera &cam = fGLViewer->CurrentCamera();
cam.SetExternalCenter(!cam.GetExternalCenter());
fGLViewer->RefreshPadEditor(fGLViewer);
} else {
fGLViewer->ResetCurrentCamera();
}
redraw = kTRUE;
break;
case kKey_d:
fGLViewer->fDebugMode = !fGLViewer->fDebugMode;
redraw = kTRUE;
Info("OpenGL viewer debug mode : ", fGLViewer->fDebugMode ? "ON" : "OFF");
break;
case kKey_D:
if (fGLViewer->fDebugMode) {
Info("OpenGL viewer FORCED rebuild", " ");
fGLViewer->UpdateScene();
}
default:;
}
}
if (redraw) {
if (fGLViewer->fGLDevice != -1)
gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kTRUE);
fGLViewer->RequestDraw();
}
return kTRUE;
}
Bool_t TGLEventHandler::HandleMotion(Event_t * event)
{
fGLViewer->MouseIdle(0, 0, 0);
if (fGLViewer->IsLocked()) {
if (gDebug>3) {
Info("TGLEventHandler::HandleMotion", "ignored - viewer is %s",
fGLViewer->LockName(fGLViewer->CurrentLock()));
}
return kFALSE;
}
Bool_t processed = kFALSE, changed = kFALSE;
Short_t lod = TGLRnrCtx::kLODMed;
Int_t xDelta = TMath::Nint(fMouseDragFactor * ControlValue(event->fX - fLastPos.fX));
Int_t yDelta = TMath::Nint(fMouseDragFactor * ControlValue(event->fY - fLastPos.fY));
Bool_t mod1 = event->fState & kKeyControlMask;
Bool_t mod2 = event->fState & kKeyShiftMask;
TGLUtil::PointToViewport(xDelta, yDelta);
if (fMouseTimerRunning) StopMouseTimer();
if (fTooltipShown &&
( TMath::Abs(event->fXRoot - fTooltipPos.fX) > fTooltipPixelTolerance ||
TMath::Abs(event->fYRoot - fTooltipPos.fY) > fTooltipPixelTolerance ))
{
RemoveTooltip();
}
if (fGLViewer->fDragAction == TGLViewer::kDragNone)
{
if (fGLViewer->fRedrawTimer->IsPending()) {
if (gDebug > 2)
Info("TGLEventHandler::HandleMotion", "Redraw pending, ignoring.");
return kTRUE;
}
changed = fGLViewer->RequestOverlaySelect(event->fX, event->fY);
if (fGLViewer->fCurrentOvlElm)
{
Event_t e = *event;
TGLUtil::PointToViewport(e.fX, e.fY);
processed = fGLViewer->fCurrentOvlElm->Handle(*fGLViewer->fRnrCtx, fGLViewer->fOvlSelRec, &e);
}
lod = TGLRnrCtx::kLODHigh;
if ( ! processed && ! fMouseTimerRunning)
StartMouseTimer();
}
else if (fGLViewer->fDragAction == TGLViewer::kDragCameraRotate)
{
processed = Rotate(xDelta, yDelta, mod1, mod2);
}
else if (fGLViewer->fDragAction == TGLViewer::kDragCameraTruck)
{
processed = fGLViewer->CurrentCamera().Truck(xDelta, -yDelta, mod1, mod2);
}
else if (fGLViewer->fDragAction == TGLViewer::kDragCameraDolly)
{
processed = fGLViewer->CurrentCamera().Dolly(yDelta - xDelta, mod1, mod2);
}
else if (fGLViewer->fDragAction == TGLViewer::kDragOverlay)
{
if (fGLViewer->fCurrentOvlElm) {
Event_t e = *event;
TGLUtil::PointToViewport(e.fX, e.fY);
processed = fGLViewer->fCurrentOvlElm->Handle(*fGLViewer->fRnrCtx, fGLViewer->fOvlSelRec, &e);
}
}
fLastPos.fX = event->fX;
fLastPos.fY = event->fY;
fLastGlobalPos.fX = event->fXRoot;
fLastGlobalPos.fY = event->fYRoot;
if (processed || changed) {
if (fGLViewer->fGLDevice != -1) {
gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kTRUE);
gVirtualX->SetDrawMode(TVirtualX::kCopy);
}
fGLViewer->RequestDraw(lod);
}
return processed;
}
Bool_t TGLEventHandler::Rotate(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
{
TGLCamera &cam = fGLViewer->CurrentCamera();
if (fArcBall) return cam.RotateArcBall(xDelta, -yDelta, mod1, mod2);
else return cam.Rotate (xDelta, -yDelta, mod1, mod2);
}
Bool_t TGLEventHandler::HandleTimer(TTimer *t)
{
if (t != fMouseTimer) return kFALSE;
fMouseTimerRunning = kFALSE;
if (fGLViewer->fRedrawTimer->IsPending()) {
if (gDebug > 2)
Info("TGLEventHandler::HandleTimer", "Redraw pending, ignoring.");
return kTRUE;
}
if (fGLViewer->fDragAction == TGLViewer::kDragNone)
{
if (fLastMouseOverPos != fLastPos)
{
SelectForMouseOver();
}
}
return kTRUE;
}
void TGLEventHandler::StartMouseTimer()
{
fMouseTimer->Start(-1, kTRUE);
fMouseTimerRunning = kTRUE;
}
void TGLEventHandler::StopMouseTimer()
{
fMouseTimerRunning = kFALSE;
fMouseTimer->Stop();
}
void TGLEventHandler::ClearMouseOver()
{
fLastMouseOverPos.fX = fLastMouseOverPos.fY = -1;
fLastMouseOverShape = 0;
fGLViewer->MouseOver(fLastMouseOverShape);
fGLViewer->MouseOver(fLastMouseOverShape, fLastEventState);
fGLViewer->MouseOver((TObject*)0, fLastEventState);
fGLViewer->ClearCurrentOvlElm();
}
void TGLEventHandler::Repaint()
{
if (fGLViewer->IsLocked()) {
if (gDebug > 0) {
Info("TGLViewer::HandleExpose", "ignored - viewer is %s",
fGLViewer->LockName(fGLViewer->CurrentLock()));
}
return;
}
fGLViewer->fRedrawTimer->RequestDraw(20, TGLRnrCtx::kLODHigh);
}
void TGLEventHandler::PopupContextMenu(TGLPhysicalShape* pshp, Event_t * ,
Int_t gx, Int_t gy)
{
if (!fGLViewer->fContextMenu)
{
fGLViewer->fContextMenu = new TContextMenu("glcm", "GL Viewer Context Menu");
}
if (pshp)
{
fActiveButtonID = 0;
UnGrabMouse();
pshp->InvokeContextMenu(*fGLViewer->fContextMenu, gx, gy);
}
}
void TGLEventHandler::TriggerTooltip(const char* text)
{
static UInt_t screenW = 0, screenH = 0;
fTooltipPos = fLastGlobalPos;
fTooltipShown = kTRUE;
fTooltip->SetText(text);
Int_t x = fTooltipPos.fX + 16, y = fTooltipPos.fY + 16;
if (screenW == 0 || screenH == 0) {
screenW = gClient->GetDisplayWidth();
screenH = gClient->GetDisplayHeight();
}
if (x + 5 + fTooltip->GetWidth() > screenW) {
x = screenW - fTooltip->GetWidth() - 5;
if (y + 5 + fTooltip->GetHeight() > screenH) {
y -= (25 + fTooltip->GetHeight());
}
}
if (y + 5 + fTooltip->GetHeight() > screenH) {
y = screenH - fTooltip->GetHeight() - 10;
}
fTooltip->SetPosition(x, y);
fTooltip->Reset();
}
void TGLEventHandler::RemoveTooltip()
{
fTooltip->Hide();
fTooltipShown = kFALSE;
}
void TGLEventHandler::SetMouseOverSelectDelay(Int_t ms)
{
fMouseTimer->SetTime(ms);
}
void TGLEventHandler::SetMouseOverTooltipDelay(Int_t ms)
{
fTooltip->SetDelay(ms);
}