From d281979f46eedf4bbc0bf700f3cd68866acf14de Mon Sep 17 00:00:00 2001
From: Matevz Tadel <matevz.tadel@cern.ch>
Date: Wed, 18 Nov 2009 21:06:28 +0000
Subject: [PATCH] Several small cleanups and improvements.

TGLViewer and sub-classes:
- Improve help text for TGLViewer ("Help on GL viewer").
- Add support for menu-bar hiding in TGLSAViewer.
- Allow TGLEmbeddedViewer to be connected to a GED editor.
- Remove support for "camera home" on double click -- show GED editor
  of the viewer instead.

TGLEventHandler:
- Improve handling of mouse-button events:
  - Only allow single button activity at the same time.
  - Remove function-static variables.

TEveViewer:
- Enable by default menu-bar hiding for GL viewers.


git-svn-id: http://root.cern.ch/svn/root/trunk@31299 27541ba8-7e3a-0410-8455-c3a389f83636
---
 graf3d/eve/inc/TEveViewer.h            |   2 +-
 graf3d/eve/src/TEveViewer.cxx          |   7 +-
 graf3d/gl/inc/TGLEmbeddedViewer.h      |   3 +-
 graf3d/gl/inc/TGLEventHandler.h        |   1 +
 graf3d/gl/inc/TGLSAViewer.h            |  28 +--
 graf3d/gl/inc/TGLViewer.h              |  19 +-
 graf3d/gl/inc/TGLViewerEditor.h        |   2 -
 graf3d/gl/src/TGLEmbeddedViewer.cxx    |   5 +-
 graf3d/gl/src/TGLEventHandler.cxx      | 204 +++++++++--------
 graf3d/gl/src/TGLSAViewer.cxx          | 301 +++++++++++++++++--------
 graf3d/gl/src/TGLViewer.cxx            |  72 ++++--
 graf3d/gl/src/TGLViewerEditor.cxx      |  18 +-
 graf3d/gviz3d/src/TStructViewerGUI.cxx |   1 -
 tutorials/eve/calorimeters.C           |   8 +-
 tutorials/eve/window_manager.C         |   6 +-
 15 files changed, 416 insertions(+), 261 deletions(-)

diff --git a/graf3d/eve/inc/TEveViewer.h b/graf3d/eve/inc/TEveViewer.h
index 574e327d2e9..83592b9b874 100644
--- a/graf3d/eve/inc/TEveViewer.h
+++ b/graf3d/eve/inc/TEveViewer.h
@@ -53,7 +53,7 @@ public:
    void SetGLViewer(TGLViewer* viewer, TGFrame* frame);
 
    TGLSAViewer*       SpawnGLViewer(TGedEditor* ged);
-   TGLEmbeddedViewer* SpawnGLEmbeddedViewer(Int_t border=0);
+   TGLEmbeddedViewer* SpawnGLEmbeddedViewer(TGedEditor* ged, Int_t border=0);
 
    void Redraw(Bool_t resetCameras=kFALSE);
 
diff --git a/graf3d/eve/src/TEveViewer.cxx b/graf3d/eve/src/TEveViewer.cxx
index 98efc693721..f85f2aa5c82 100644
--- a/graf3d/eve/src/TEveViewer.cxx
+++ b/graf3d/eve/src/TEveViewer.cxx
@@ -152,7 +152,6 @@ void TEveViewer::SetGLViewer(TGLViewer* viewer, TGFrame* frame)
    fGLViewerFrame = frame;
 
    fGLViewer->SetSmartRefresh(kTRUE);
-   fGLViewer->SetResetCameraOnDoubleClick(kFALSE);
 }
 
 //______________________________________________________________________________
@@ -168,6 +167,8 @@ TGLSAViewer* TEveViewer::SpawnGLViewer(TGedEditor* ged)
    TGLSAViewer* v = new TGLSAViewer(cf, 0, ged);
    cf->SetEditable(kFALSE);
    v->ToggleEditObject();
+   v->DisableCloseMenuEntries();
+   v->EnableMenuBarHiding();
    SetGLViewer(v, v->GetFrame());
 
    if (fEveFrame == 0)
@@ -177,7 +178,7 @@ TGLSAViewer* TEveViewer::SpawnGLViewer(TGedEditor* ged)
 }
 
 //______________________________________________________________________________
-TGLEmbeddedViewer* TEveViewer::SpawnGLEmbeddedViewer(Int_t border)
+TGLEmbeddedViewer* TEveViewer::SpawnGLEmbeddedViewer(TGedEditor* ged, Int_t border)
 {
    // Spawn new GLViewer and adopt it.
 
@@ -185,7 +186,7 @@ TGLEmbeddedViewer* TEveViewer::SpawnGLEmbeddedViewer(Int_t border)
 
    TGCompositeFrame* cf = GetGUICompositeFrame();
 
-   TGLEmbeddedViewer* v = new TGLEmbeddedViewer(cf, 0, border);
+   TGLEmbeddedViewer* v = new TGLEmbeddedViewer(cf, 0, ged, border);
    SetGLViewer(v, v->GetFrame());
 
    cf->AddFrame(fGLViewerFrame, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
diff --git a/graf3d/gl/inc/TGLEmbeddedViewer.h b/graf3d/gl/inc/TGLEmbeddedViewer.h
index 12ee8ad9731..9a7c6b7bdfb 100644
--- a/graf3d/gl/inc/TGLEmbeddedViewer.h
+++ b/graf3d/gl/inc/TGLEmbeddedViewer.h
@@ -22,6 +22,7 @@
 
 class TGLRenderArea;
 class TGLEventHandler;
+class TGedEditor;
 
 class TGLEmbeddedViewer : public TGLViewer
 {
@@ -36,7 +37,7 @@ private:
    TGLEmbeddedViewer& operator=(const TGLEmbeddedViewer&); // Not implemented
 
 public:
-   TGLEmbeddedViewer(const TGWindow *parent, TVirtualPad *pad=0, Int_t border=2);
+   TGLEmbeddedViewer(const TGWindow *parent, TVirtualPad *pad=0, TGedEditor *ged=0, Int_t border=2);
    ~TGLEmbeddedViewer();
 
    virtual void CreateGLWidget();
diff --git a/graf3d/gl/inc/TGLEventHandler.h b/graf3d/gl/inc/TGLEventHandler.h
index 8281d7f21f8..f1f6d164f29 100644
--- a/graf3d/gl/inc/TGLEventHandler.h
+++ b/graf3d/gl/inc/TGLEventHandler.h
@@ -35,6 +35,7 @@ class TGLEventHandler : public TGEventHandler
 protected:
    TGLViewer        *fGLViewer;
    TTimer           *fMouseTimer;     // mouse delay timer
+   TPoint            fButtonPushPos;
    TPoint            fLastPos;
    TPoint            fLastMouseOverPos;
    TGLPhysicalShape *fLastMouseOverShape;
diff --git a/graf3d/gl/inc/TGLSAViewer.h b/graf3d/gl/inc/TGLSAViewer.h
index 52f851e3b1c..3942e13ad91 100644
--- a/graf3d/gl/inc/TGLSAViewer.h
+++ b/graf3d/gl/inc/TGLSAViewer.h
@@ -12,21 +12,17 @@
 #ifndef ROOT_TGLSAViewer
 #define ROOT_TGLSAViewer
 
-#ifndef ROOT_TGLViewer
 #include "TGLViewer.h"
-#endif
-
-#ifndef ROOT_TString
 #include "TString.h"
-#endif
 
+class TGLSAFrame;
 class TGWindow;
 class TGFrame;
 class TGCompositeFrame;
 class TGPopupMenu;
+class TGButton;
 
 class TGedEditor;
-class TGLPShapeObj;
 class TGLEventHandler;
 class TGMenuBar;
 
@@ -52,7 +48,7 @@ public:
 
 private:
    // GUI components
-   TGCompositeFrame  *fFrame;
+   TGLSAFrame        *fFrame;
    TGPopupMenu       *fFileMenu;
    TGPopupMenu       *fFileSaveMenu;
    TGPopupMenu       *fCameraMenu;
@@ -60,8 +56,6 @@ private:
 
    // Ged
    TGCompositeFrame  *fLeftVerticalFrame;
-   TGedEditor        *fGedEditor;
-   TGLPShapeObj      *fPShapeWrap;
 
    TGCompositeFrame  *fRightVerticalFrame;
 
@@ -69,6 +63,8 @@ private:
    Int_t              fTypeIdx;
    Bool_t             fOverwrite;
    TGMenuBar         *fMenuBar;
+   TGButton          *fMenuBut;
+   Bool_t             fHideMenuBar;
    Bool_t             fDeleteMenuBar;
 
    // Initial window positioning
@@ -89,7 +85,7 @@ private:
 
 public:
    TGLSAViewer(TVirtualPad *pad);
-   TGLSAViewer(const TGWindow *parent, TVirtualPad *pad, TGedEditor *ged = 0);
+   TGLSAViewer(const TGWindow *parent, TVirtualPad *pad, TGedEditor *ged=0);
    ~TGLSAViewer();
 
    virtual void CreateGLWidget();
@@ -97,21 +93,21 @@ public:
 
    virtual const char* GetName() const { return "GLViewer"; }
 
-   virtual void SelectionChanged();     // *SIGNAL*
-   virtual void OverlayDragFinished(); // *SIGNAL*
-
-   virtual void RefreshPadEditor(TObject* changed=0);
+   virtual void SelectionChanged();
 
    void   Show();
    void   Close();
    void   DeleteMenuBar();
+   void   DisableCloseMenuEntries();
+   void   EnableMenuBarHiding();
+
+   void   HandleMenuBarHiding(Event_t* ev);
 
    // GUI events - editors, frame etc
    Bool_t ProcessFrameMessage(Long_t msg, Long_t parm1, Long_t);
 
-   TGCompositeFrame* GetFrame() const { return fFrame; }
+   TGCompositeFrame* GetFrame() const;
    TGCompositeFrame* GetLeftVerticalFrame() const { return fLeftVerticalFrame; }
-   TGedEditor*       GetGedEditor() const { return fGedEditor; }
 
    void ToggleEditObject();
    void ToggleOrthoRotate();
diff --git a/graf3d/gl/inc/TGLViewer.h b/graf3d/gl/inc/TGLViewer.h
index 8545b771936..353c086d99c 100644
--- a/graf3d/gl/inc/TGLViewer.h
+++ b/graf3d/gl/inc/TGLViewer.h
@@ -44,7 +44,8 @@ class TGLContextIdentity;
 class TTimer;
 
 class TContextMenu;
-
+class TGedEditor;
+class TGLPShapeObj;
 
 class TGLViewer : public TVirtualViewer3D,
                   public TGLViewerBase,
@@ -102,6 +103,8 @@ protected:
    TGLOvlSelectRecord   fOvlSelRec;            //! select record from last overlay select
 
    TGEventHandler      *fEventHandler;         //! event handler
+   TGedEditor          *fGedEditor;            //! GED editor
+   TGLPShapeObj        *fPShapeWrap;
 
    // Mouse ineraction
 public:
@@ -171,7 +174,6 @@ protected:
    Bool_t           fIgnoreSizesOnUpdate;      // ignore sizes of bounding-boxes on update
    Bool_t           fResetCamerasOnUpdate;     // reposition camera on each update
    Bool_t           fResetCamerasOnNextUpdate; // reposition camera on next update
-   Bool_t           fResetCameraOnDoubleClick; // reposition camera on double-click
 
 public:
    TGLViewer(TVirtualPad* pad, Int_t x, Int_t y, Int_t width, Int_t height);
@@ -204,8 +206,6 @@ public:
    virtual void   ResetCameras()                { SetupCameras(kTRUE); }
    virtual void   ResetCamerasAfterNextUpdate() { fResetCamerasOnNextUpdate = kTRUE; }
 
-   virtual void   RefreshPadEditor(TObject* = 0) {}
-
    TGLWidget* GetGLWidget() { return fGLWidget; }
 
    virtual void  CreateGLWidget()  {}
@@ -317,13 +317,9 @@ public:
    void   ResetCurrentCamera();
    Bool_t GetResetCamerasOnUpdate() const       { return fResetCamerasOnUpdate; }
    void   SetResetCamerasOnUpdate(Bool_t v)     { fResetCamerasOnUpdate = v; }
-   Bool_t GetResetCameraOnDoubleClick() const   { return fResetCameraOnDoubleClick; }
-   void   SetResetCameraOnDoubleClick(Bool_t v) { fResetCameraOnDoubleClick = v; }
 
    virtual void PostSceneBuildSetup(Bool_t resetCameras);
 
-   virtual void SelectionChanged();    // *SIGNAL*
-   virtual void OverlayDragFinished(); // *SIGNAL*
    virtual void MouseIdle(TGLPhysicalShape*,UInt_t,UInt_t); // *SIGNAL*
    virtual void MouseOver(TGLPhysicalShape*); // *SIGNAL*
    virtual void MouseOver(TGLPhysicalShape*, UInt_t state); // *SIGNAL*
@@ -337,6 +333,13 @@ public:
    TGEventHandler *GetEventHandler() const { return fEventHandler; }
    virtual void    SetEventHandler(TGEventHandler *handler);
 
+   TGedEditor*  GetGedEditor() const { return fGedEditor; }
+   virtual void SetGedEditor(TGedEditor* ed) { fGedEditor = ed; }
+
+   virtual void SelectionChanged();
+   virtual void OverlayDragFinished();
+   virtual void RefreshPadEditor(TObject* obj=0);
+
    virtual void RemoveOverlayElement(TGLOverlayElement* el);
 
    TGLSelectRecord&    GetSelRec()    { return fSelRec; }
diff --git a/graf3d/gl/inc/TGLViewerEditor.h b/graf3d/gl/inc/TGLViewerEditor.h
index c409b78e9da..79b50d65d6d 100644
--- a/graf3d/gl/inc/TGLViewerEditor.h
+++ b/graf3d/gl/inc/TGLViewerEditor.h
@@ -37,7 +37,6 @@ private:
    TGColorSelect    *fClearColor;
    TGCheckButton    *fIgnoreSizesOnUpdate;
    TGCheckButton    *fResetCamerasOnUpdate;
-   TGCheckButton    *fResetCameraOnDoubleClick;
    TGTextButton     *fUpdateScene;
    TGTextButton     *fCameraHome;
 
@@ -108,7 +107,6 @@ public:
    void DoClearColor(Pixel_t color);
    void DoIgnoreSizesOnUpdate();
    void DoResetCamerasOnUpdate();
-   void DoResetCameraOnDoubleClick();
    void DoUpdateScene();
    void DoCameraHome();
    void UpdateMaxDrawTimes();
diff --git a/graf3d/gl/src/TGLEmbeddedViewer.cxx b/graf3d/gl/src/TGLEmbeddedViewer.cxx
index b89e8ebe28a..6de4ae70bbd 100644
--- a/graf3d/gl/src/TGLEmbeddedViewer.cxx
+++ b/graf3d/gl/src/TGLEmbeddedViewer.cxx
@@ -31,7 +31,8 @@
 ClassImp(TGLEmbeddedViewer);
 
 //______________________________________________________________________________
-TGLEmbeddedViewer::TGLEmbeddedViewer(const TGWindow *parent, TVirtualPad *pad, Int_t border) :
+TGLEmbeddedViewer::TGLEmbeddedViewer(const TGWindow *parent, TVirtualPad *pad,
+                                     TGedEditor *ged, Int_t border) :
    TGLViewer(pad, 0, 0, 400, 300),
    fFrame(0),
    fBorder(border)
@@ -40,6 +41,8 @@ TGLEmbeddedViewer::TGLEmbeddedViewer(const TGWindow *parent, TVirtualPad *pad, I
    // Argument 'border' specifies how many pixels to pad on each side of the
    // viewer. This area can be used for highlightning of the active viewer.
 
+   fGedEditor = ged;
+
    fFrame = new TGCompositeFrame(parent);
 
    CreateFrames();
diff --git a/graf3d/gl/src/TGLEventHandler.cxx b/graf3d/gl/src/TGLEventHandler.cxx
index 30bef28ede9..dbe683bb598 100644
--- a/graf3d/gl/src/TGLEventHandler.cxx
+++ b/graf3d/gl/src/TGLEventHandler.cxx
@@ -301,7 +301,6 @@ Bool_t TGLEventHandler::HandleCrossing(Event_t *event)
 Bool_t TGLEventHandler::HandleButton(Event_t * event)
 {
    // Handle mouse button 'event'.
-   static Event_t eventSt = {kOtherEvent, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, kFALSE, 0, 0, {0,0,0,0,0}};
 
    if (fGLViewer->IsLocked()) {
       if (gDebug>2) {
@@ -311,19 +310,64 @@ Bool_t TGLEventHandler::HandleButton(Event_t * event)
       return kFALSE;
    }
 
+   // Handle mouse-wheel events first.
+   if (event->fCode > kButton3)
+   {
+      // On Win32 only button release events come for mouse wheel.
+      // Note: Modifiers (ctrl/shift) disabled as fState doesn't seem to
+      // have correct modifier flags with mouse wheel under Windows.
+      // TODO: Put '50' into some static const.
+
+      if (event->fType == kButtonRelease)
+      {
+         Bool_t redraw = kFALSE;
+
+         switch(event->fCode)
+         {
+            case kButton5: // Zoom out (dolly or adjust camera FOV).
+               redraw = fGLViewer->CurrentCamera().Zoom(50, kFALSE, kFALSE);
+               break;
+
+            case kButton4: // Zoom in (dolly or adjust camera FOV).
+               redraw = fGLViewer->CurrentCamera().Zoom(-50, kFALSE, kFALSE);
+               break;
+
+            case kButton6:
+            case kButton7: // Ignore for now.
+               break;
+         }
+
+         if (redraw)
+            fGLViewer->fRedrawTimer->RequestDraw(10, TGLRnrCtx::kLODMed);
+      }
+      return kTRUE;
+   }
+
+   // Now we know we have Button 1 -> 3.
+   // Allow a single action/button down/up pairing - block others
+   if (fActiveButtonID && event->fCode != fActiveButtonID)
+   {
+      return kTRUE;
+   }
+   else
+   {
+      fActiveButtonID = event->fCode;
+   }
+
    // Button DOWN
-   if (event->fType == kButtonPress && event->fCode <= kButton3)
+   if (event->fType == kButtonPress)
    {
-      // Allow a single action/button down/up pairing - block others
+      gVirtualX->GrabPointer(fGLViewer->GetGLWidget()->GetId(),
+                             kButtonPressMask | kButtonReleaseMask | kPointerMotionMask,
+                             kNone, kNone, kTRUE, kFALSE);
+      fInPointerGrab = kTRUE;
+
       fGLViewer->MouseIdle(0, 0, 0);
-      fGLViewer->Activated();
-      if (fGLViewer->fDragAction != TGLViewer::kDragNone)
-         return kFALSE;
-      eventSt.fX = event->fX;
-      eventSt.fY = event->fY;
-      eventSt.fCode = event->fCode;
 
-      if ( fGLViewer->GetPushAction() != TGLViewer::kPushStd )
+      fButtonPushPos.fX = event->fX;
+      fButtonPushPos.fY = event->fY;
+
+      if (fGLViewer->GetPushAction() != TGLViewer::kPushStd)
       {
          fGLViewer->RequestSelect(event->fX, event->fY);
          if (fGLViewer->fSelRec.GetN() > 0)
@@ -341,7 +385,9 @@ Bool_t TGLEventHandler::HandleButton(Event_t * event)
                TGLSelectRecord& rec = fGLViewer->GetSelRec();
                TObject* obj = rec.GetObject();
                TGLRect& vp = fGLViewer->CurrentCamera().RefViewport();
-               new TGLAnnotation(fGLViewer, obj->GetTitle(),  eventSt.fX*1.f/vp.Width(),  1 - eventSt.fY*1.f/vp.Height(), v);
+               new TGLAnnotation(fGLViewer, obj->GetTitle(),
+                                 event->fX * 1.0f/vp.Width(),
+                                 1 - event->fY * 1.0f/vp.Height(), v);
             }
 
             fGLViewer->RequestDraw();
@@ -349,18 +395,13 @@ Bool_t TGLEventHandler::HandleButton(Event_t * event)
          return kTRUE;
       }
 
-      Bool_t grabPointer = kFALSE;
-      Bool_t handled     = kFALSE;
-
-      // Record active button for release
-      fActiveButtonID = event->fCode;
+      Bool_t handled = kFALSE;
 
       if (fGLViewer->fDragAction == TGLViewer::kDragNone && fGLViewer->fCurrentOvlElm)
       {
          if (fGLViewer->fCurrentOvlElm->Handle(*fGLViewer->fRnrCtx, fGLViewer->fOvlSelRec, event))
          {
             handled     = kTRUE;
-            grabPointer = kTRUE;
             fGLViewer->fDragAction = TGLViewer::kDragOverlay;
             fGLViewer->RequestDraw();
          }
@@ -372,31 +413,37 @@ Bool_t TGLEventHandler::HandleButton(Event_t * event)
             // LEFT mouse button
             case kButton1:
             {
-               if (event->fState & kKeyShiftMask) {
-                  if (fGLViewer->RequestSelect(event->fX, event->fY)) {
+               if (event->fState & kKeyShiftMask)
+               {
+                  if (fGLViewer->RequestSelect(event->fX, event->fY))
+                  {
                      fGLViewer->ApplySelection();
                      handled = kTRUE;
-                  } else {
-                     fGLViewer->SelectionChanged(); // Just notify clients.
+                     fIgnoreButtonUp = kTRUE;
                   }
-                  fIgnoreButtonUp = kTRUE;
-               } else if ((fSecSelType == TGLViewer::kOnRequest || fSecSelType == TGLViewer::kOnKeyMod1) && (event->fState & kKeyMod1Mask)) {
+               }
+               else if ((fSecSelType == TGLViewer::kOnRequest ||
+                         fSecSelType == TGLViewer::kOnKeyMod1) &&
+                        event->fState & kKeyMod1Mask)
+               {
                   fGLViewer->RequestSelect(event->fX, event->fY);
                   fGLViewer->RequestSecondarySelect(event->fX, event->fY);
+
                   if (fGLViewer->fSecSelRec.GetPhysShape() != 0)
                   {
                      TGLLogicalShape& lshape = const_cast<TGLLogicalShape&>
                         (*fGLViewer->fSecSelRec.GetPhysShape()->GetLogical());
                      lshape.ProcessSelection(*fGLViewer->fRnrCtx, fGLViewer->fSecSelRec);
-                     handled = kTRUE;
                   }
+                  handled = kTRUE;
                   fIgnoreButtonUp = kTRUE;
                }
+
                if ( ! handled)
                {
                   fGLViewer->fDragAction = TGLViewer::kDragCameraRotate;
-                  grabPointer = kTRUE;
-                  if (fMouseTimer) {
+                  if (fMouseTimer)
+                  {
                      fMouseTimer->TurnOff();
                      fMouseTimer->Reset();
                   }
@@ -407,7 +454,6 @@ Bool_t TGLEventHandler::HandleButton(Event_t * event)
             case kButton2:
             {
                fGLViewer->fDragAction = TGLViewer::kDragCameraTruck;
-               grabPointer = kTRUE;
                break;
             }
             // RIGHT mouse button
@@ -417,49 +463,51 @@ Bool_t TGLEventHandler::HandleButton(Event_t * event)
                if (event->fState & kKeyShiftMask)
                {
                   fGLViewer->RequestSelect(event->fX, event->fY);
+                  if (!fGLViewer->fContextMenu) {
+                     fGLViewer->fContextMenu = new TContextMenu("glcm", "GL Viewer Context Menu");
+                  }
+                  Int_t    x, y;
+                  Window_t childdum;
+                  gVirtualX->TranslateCoordinates(fGLViewer->fGLWidget->GetId(),
+                                                  gClient->GetDefaultRoot()->GetId(),
+                                                  event->fX, event->fY, x, y, childdum);
                   const TGLPhysicalShape * selected = fGLViewer->fSelRec.GetPhysShape();
                   if (selected) {
-                     if (!fGLViewer->fContextMenu) {
-                        fGLViewer->fContextMenu = new TContextMenu("glcm", "GL Viewer Context Menu");
-                     }
-                     Int_t    x, y;
-                     Window_t childdum;
-                     gVirtualX->TranslateCoordinates(fGLViewer->fGLWidget->GetId(),
-                                                     gClient->GetDefaultRoot()->GetId(),
-                                                     event->fX, event->fY, x, y, childdum);
                      selected->InvokeContextMenu(*fGLViewer->fContextMenu, x, y);
                   }
+                  // This is dangerous ... should have special menu.
+                  // else 
+                  // {
+                  //    fGLViewer->fContextMenu->Popup(x, y, fGLViewer);
+                  // }
                } else {
                   fGLViewer->fDragAction = TGLViewer::kDragCameraDolly;
-                  grabPointer = kTRUE;
                }
                break;
             }
          }
       }
-
-      if (grabPointer)
-      {
-         gVirtualX->GrabPointer(fGLViewer->GetGLWidget()->GetId(),
-                                kButtonPressMask | kButtonReleaseMask | kPointerMotionMask,
-                                kNone, kNone, kTRUE, kFALSE);
-         fInPointerGrab = kTRUE;
-      }
    }
    // Button UP
    else if (event->fType == kButtonRelease)
    {
-      if (fIgnoreButtonUp)
-      {
-         fIgnoreButtonUp = kFALSE;
-         return kTRUE;
-      }
+      fActiveButtonID = 0;
 
       if (fInPointerGrab)
       {
          gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
          fInPointerGrab = kFALSE;
       }
+      else
+      {
+         Warning("TGLEventHandler::HandleButton", "Unexpected button-release.");
+      }
+
+      if (fIgnoreButtonUp)
+      {
+         fIgnoreButtonUp = kFALSE;
+         return kTRUE;
+      }
 
       if (fGLViewer->GetPushAction() != TGLViewer::kPushStd)
       {
@@ -481,35 +529,14 @@ Bool_t TGLEventHandler::HandleButton(Event_t * event)
          fGLViewer->RequestDraw(TGLRnrCtx::kLODHigh);
       }
 
-      // TODO: Check on Linux - on Win32 only see button release events
-      // for mouse wheel
-      switch(event->fCode) {
-         // Buttons 4/5 are mouse wheel
-         // Note: Modifiers (ctrl/shift) disabled as fState doesn't seem to
-         // have correct modifier flags with mouse wheel under Windows.
-         case kButton5: {
-            // Zoom out (dolly or adjust camera FOV). TODO : val static const somewhere
-            if (fGLViewer->CurrentCamera().Zoom(50, kFALSE, kFALSE))
-               fGLViewer->fRedrawTimer->RequestDraw(10, TGLRnrCtx::kLODMed);
-            return kTRUE;
-            break;
-         }
-         case kButton4: {
-            // Zoom in - adjust camera FOV. TODO : val static const somewhere
-            if (fGLViewer->CurrentCamera().Zoom(-50, kFALSE, kFALSE))
-               fGLViewer->fRedrawTimer->RequestDraw(10, TGLRnrCtx::kLODMed);
-            return kTRUE;
-            break;
-         }
-      }
       fGLViewer->fDragAction = TGLViewer::kDragNone;
+
       if (fGLViewer->fGLDevice != -1)
       {
          gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kFALSE);
       }
-      if ((event->fX == eventSt.fX) &&
-          (event->fY == eventSt.fY) &&
-          (eventSt.fCode == event->fCode))
+
+      if (event->fX == fButtonPushPos.fX && event->fY == fButtonPushPos.fY)
       {
          TObject *obj = 0;
          fGLViewer->RequestSelect(fLastPos.fX, fLastPos.fY);
@@ -518,8 +545,8 @@ Bool_t TGLEventHandler::HandleButton(Event_t * event)
          if (phys_shape) obj = phys_shape->GetLogical()->GetExternal();
       
          // secondary selection
-         if (phys_shape && fSecSelType == TGLViewer::kOnRequest
-             && phys_shape->GetLogical()->AlwaysSecondarySelect())
+         if (phys_shape && fSecSelType == TGLViewer::kOnRequest &&
+             phys_shape->GetLogical()->AlwaysSecondarySelect())
          {
             fGLViewer->RequestSecondarySelect(fLastPos.fX, fLastPos.fY);
             fGLViewer->fSecSelRec.SetMultiple(event->fState & kKeyControlMask);
@@ -551,11 +578,6 @@ Bool_t TGLEventHandler::HandleButton(Event_t * event)
             fGLViewer->Clicked(obj);
             fGLViewer->Clicked(obj, event->fCode, event->fState);
          }
-
-         eventSt.fX = 0;
-         eventSt.fY = 0;
-         eventSt.fCode = 0;
-         eventSt.fState = 0;
       }
       if (event->fCode == kButton1 && fMouseTimer)
       {
@@ -579,15 +601,21 @@ Bool_t TGLEventHandler::HandleDoubleClick(Event_t *event)
       return kFALSE;
    }
 
+   if (fActiveButtonID)
+      return kTRUE;
+
+   fActiveButtonID = event->fCode;
+   gVirtualX->GrabPointer(fGLViewer->GetGLWidget()->GetId(),
+                          kButtonPressMask | kButtonReleaseMask | kPointerMotionMask,
+                          kNone, kNone, kTRUE, kFALSE);
+   fInPointerGrab = kTRUE;
+
    fGLViewer->MouseIdle(0, 0, 0);
-   // Reset interactive camera mode on button double
-   // click (unless mouse wheel)
-   if (event->fCode != kButton4 && event->fCode != kButton5) {
-      if (fGLViewer->fResetCameraOnDoubleClick) {
-         fGLViewer->ResetCurrentCamera();
-         fGLViewer->RequestDraw();
-      }
+   if (event->fCode == kButton1)
+   {
       fGLViewer->DoubleClicked();
+      if (fGLViewer->GetSelected() == 0)
+         fGLViewer->SelectionChanged();
    }
    return kTRUE;
 }
@@ -806,7 +834,7 @@ Bool_t TGLEventHandler::HandleMotion(Event_t * event)
    }
    else if (fGLViewer->fDragAction == TGLViewer::kDragCameraDolly)
    {
-      processed = fGLViewer->CurrentCamera().Dolly(xDelta, mod1, mod2);
+      processed = fGLViewer->CurrentCamera().Dolly(xDelta - yDelta, mod1, mod2);
    }
    else if (fGLViewer->fDragAction == TGLViewer::kDragOverlay)
    {
diff --git a/graf3d/gl/src/TGLSAViewer.cxx b/graf3d/gl/src/TGLSAViewer.cxx
index 2ddecd7db19..0ea89eff0bb 100644
--- a/graf3d/gl/src/TGLSAViewer.cxx
+++ b/graf3d/gl/src/TGLSAViewer.cxx
@@ -23,6 +23,7 @@
 #include "TGFrame.h"
 #include "TGLabel.h"
 #include "TGMenu.h"
+#include "TGButton.h"
 #include "TGSplitter.h"
 #include "TColor.h"
 
@@ -51,6 +52,7 @@
 #include "TGLOutput.h"
 #include "TGLEventHandler.h"
 
+
 const char * TGLSAViewer::fgHelpText1 = "\
 DIRECT SCENE INTERACTIONS\n\n\
    Press:\n\
@@ -61,65 +63,103 @@ DIRECT SCENE INTERACTIONS\n\n\
    \tj          --- ZOOM in\n\
    \tk          --- ZOOM out\n\
    \tArrow Keys --- PAN (TRUCK) across scene\n\
-   \tHome       --- reset current camera\n\n\
-   You can ROTATE (ORBIT) the scene by holding the left mouse button and moving\n\
-   the mouse (perspective camera, needs to be enabled for orthograpic camers).\n\
+   \tHome       --- reset current camera\n\
+\n\
+   LEFT mouse button -- ROTATE (ORBIT) the scene by holding the mouse button and moving\n\
+   the mouse (perspective camera, needs to be enabled in menu for orthograpic cameras).\n\
    By default, the scene will be rotated about its center. To select arbitrary center\n\
-   bring up the viewer-editor and use 'Camera center' controls in the 'Guides' tab.\n\n\
-   You can PAN (TRUCK) the camera using the middle mouse button or arrow keys.\n\n\
-   You can ZOOM the camera by dragging side to side holding the right\n\
-   mouse button (in perspective mode the camera is translated along viewing axis).\n\n\
-   Mouse wheel action depends on the camera type:\n\
+   bring up the viewer-editor (e.g., shift-click into empty background) and use\n\
+   'Camera center' controls in the 'Guides' tab.\n\
+\n\
+   MIDDLE mouse button or arrow keys --  PAN (TRUCK) the camera.\n\
+\n\
+   RIGHT mouse button action depends on camera type:\n\
+     orthographic -- zoom,\n\
+     perspective  -- move camera forwards / backwards\n\
+\n\
+   By pressing Ctrl and Shift keys the mouse precision can be changed:\n\
+     Shift      -- 10 times less precise\n\
+     Ctrl       -- 10 times more precise\n\
+     Ctrl Shift -- 100 times more precise\n\
+\n\
+   Mouse wheel action depends on camera type:\n\
      orthographic -- zoom,\n\
-     perspective  -- change field-of-view (focal length)\n\n\
-   RESET the camera via the button in viewer-editor or Home key.\n\n\
-   SELECT a shape with Shift+Left mouse button click.\n\n\
-   SELECT the viewer with Shift+Left mouse button click on a free space.\n\n\
-   MOVE a selected shape using Shift+Mid mouse drag.\n\n\
+     perspective  -- change field-of-view (focal length)\n\
+\n\
+   Double clik will show GUI editor of the viewer (if assigned).\n\
+\n\
+   RESET the camera via the button in viewer-editor or Home key.\n\
+\n\
+   SELECT a shape with Shift+Left mouse button click.\n\
+\n\
+   SELECT the viewer with Shift+Left mouse button click on a free space.\n\
+\n\
+   MOVE a selected shape using Shift+Mid mouse drag.\n\
+\n\
    Invoke the CONTEXT menu with Shift+Right mouse click.\n\n"
    "Secondary selection and direct render object interaction is initiated\n\
-   by Alt+Left mouse click (Mod1, actually). Only few classes support this option.\n\n\
-CAMERA\n\n\
+   by Alt+Left mouse click (Mod1, actually). Only few classes support this option.\n\
+   When 'Alt' is taken by window manager, try Alt-Ctrl-Left.\n\
+\n\
+CAMERA\n\
+\n\
    The \"Camera\" menu is used to select the different projections from \n\
-   the 3D world onto the 2D viewport. There are three perspective cameras:\n\n\
+   the 3D world onto the 2D viewport. There are three perspective cameras:\n\
+\n\
    \tPerspective (Floor XOZ)\n\
    \tPerspective (Floor YOZ)\n\
-   \tPerspective (Floor XOY)\n\n\
-   In each case the floor plane (defined by two axes) is kept level.\n\n\
-   There are also three orthographic cameras:\n\n\
+   \tPerspective (Floor XOY)\n\
+\n\
+   In each case the floor plane (defined by two axes) is kept level.\n\
+\n\
+   There are also three orthographic cameras:\n\
+\n\
    \tOrthographic (XOY)\n\
    \tOrthographic (XOZ)\n\
-   \tOrthographic (ZOY)\n\n\
+   \tOrthographic (ZOY)\n\
+\n\
    In each case the first axis is placed horizontal, the second vertical e.g.\n\
    XOY means X horizontal, Y vertical.\n\n";
 
 const char * TGLSAViewer::fgHelpText2 = "\
-SHAPES COLOR AND MATERIAL\n\n\
+SHAPES COLOR AND MATERIAL\n\
+\n\
    The selected shape's color can be modified in the Shapes-Color tabs.\n\
    Shape's color is specified by the percentage of red, green, blue light\n\
    it reflects. A surface can reflect DIFFUSE, AMBIENT and SPECULAR light.\n\
    A surface can also emit light. The EMISSIVE parameter allows to define it.\n\
-   The surface SHININESS can also be modified.\n\n\
-SHAPES GEOMETRY\n\n\
+   The surface SHININESS can also be modified.\n\
+\n\
+SHAPES GEOMETRY\n\
+\n\
    The selected shape's location and geometry can be modified in the Shapes-Geom\n\
-   tabs by entering desired values in respective number entry controls.\n\n\
-SCENE CLIPPING\n\n\
-   In the Scene-Clipping tabs select a 'Clip Type': None, Plane, Box\n\n\
-   For 'Plane' and 'Box' the lower pane shows the relevant parameters:\n\n\
+   tabs by entering desired values in respective number entry controls.\n\
+\n\
+SCENE CLIPPING\n\
+\n\
+   In the Scene-Clipping tabs select a 'Clip Type': None, Plane, Box\n\
+\n\
+   For 'Plane' and 'Box' the lower pane shows the relevant parameters:\n\
+\n\
 \tPlane: Equation coefficients of form aX + bY + cZ + d = 0\n\
 \tBox: Center X/Y/Z and Length X/Y/Z\n\n"
    "For Box checking the 'Show / Edit' checkbox shows the clip box (in light blue)\n\
    in viewer. It also attaches the current manipulator to the box - enabling\n\
-   direct editing in viewer.\n\n\
-MANIPULATORS\n\n\
+   direct editing in viewer.\n\
+\n\
+MANIPULATORS\n\
+\n\
    A widget attached to the selected object - allowing direct manipulation\n\
-   of the object with respect to its local axes.\n\n\
-   There are three modes, toggled with keys while manipulator is active:\n\
+   of the object with respect to its local axes.\n\
+\n\
+   There are three modes, toggled with keys while manipulator is active, that is,\n\
+   mouse pointer is above it (switches color to yellow):\n\
    \tMode\t\tWidget Component Style\t\tKey\n\
    \t----\t\t----------------------\t\t---\n\
    \tTranslation\tLocal axes with arrows\t\tv\n\
    \tScale\t\tLocal axes with boxes\t\tx\n\
-   \tRotate\t\tLocal axes rings\t\tc\n\n\
+   \tRotate\t\tLocal axes rings\t\tc\n\
+\n\
    Each widget has three axis components - red (X), green (Y) and blue (Z).\n\
    The component turns yellow, indicating an active state, when the mouse is moved\n\
    over it. Left click and drag on the active component to adjust the objects\n\
@@ -165,33 +205,31 @@ TGLSAViewer::TGLSAViewer(TVirtualPad *pad) :
    fCameraMenu(0),
    fHelpMenu(0),
    fLeftVerticalFrame(0),
-   fGedEditor(0),
-   fPShapeWrap(0),
    fRightVerticalFrame(0),
    fDirName("."),
    fTypeIdx(0),
    fOverwrite(kFALSE),
    fMenuBar(0),
+   fMenuBut(0),
+   fHideMenuBar(kFALSE),
    fDeleteMenuBar(kFALSE)
 {
    // Construct a standalone viewer, bound to supplied 'pad'.
 
-   TGLSAFrame* gl_frame = new TGLSAFrame(*this);
-   fFrame = gl_frame;
+   fFrame = new TGLSAFrame(*this);
 
    CreateMenus();
    CreateFrames();
 
-   gl_frame->SetWindowName("ROOT's GL viewer");
-   gl_frame->SetClassHints("GLViewer", "GLViewer");
-   gl_frame->SetMWMHints(kMWMDecorAll, kMWMFuncAll, kMWMInputModeless);
-   gl_frame->MapSubwindows();
-
-   gl_frame->Resize(fFrame->GetDefaultSize());
-   gl_frame->MoveResize(fgInitX, fgInitY, fgInitW, fgInitH);
-   gl_frame->SetWMPosition(fgInitX, fgInitY);
+   fFrame->SetWindowName("ROOT's GL viewer");
+   fFrame->SetClassHints("GLViewer", "GLViewer");
+   fFrame->SetMWMHints(kMWMDecorAll, kMWMFuncAll, kMWMInputModeless);
+   fFrame->MapSubwindows();
+   fFrame->HideFrame(fMenuBut);
 
-   fPShapeWrap = new TGLPShapeObj(0, this);
+   fFrame->Resize(fFrame->GetDefaultSize());
+   fFrame->MoveResize(fgInitX, fgInitY, fgInitW, fgInitH);
+   fFrame->SetWMPosition(fgInitX, fgInitY);
 
    // set recursive cleanup, but exclude fGedEditor
    // destructor of fGedEditor has own way of handling child nodes
@@ -211,11 +249,11 @@ TGLSAViewer::TGLSAViewer(const TGWindow *parent, TVirtualPad *pad, TGedEditor *g
    fCameraMenu(0),
    fHelpMenu(0),
    fLeftVerticalFrame(0),
-   fGedEditor(ged),
-   fPShapeWrap(0),
    fRightVerticalFrame(0),
    fTypeIdx(0),
    fMenuBar(0),
+   fMenuBut(0),
+   fHideMenuBar(kFALSE),
    fDeleteMenuBar(kFALSE)
 {
    // Construct an embedded standalone viewer, bound to supplied 'pad'.
@@ -223,17 +261,17 @@ TGLSAViewer::TGLSAViewer(const TGWindow *parent, TVirtualPad *pad, TGedEditor *g
    // Modified version of the previous constructor for embedding the
    // viewer into another frame (parent).
 
+   fGedEditor = ged;
    fFrame = new TGLSAFrame(parent, *this);
 
    CreateMenus();
    CreateFrames();
 
    fFrame->MapSubwindows();
+   fFrame->HideFrame(fMenuBut);
    fFrame->Resize(fFrame->GetDefaultSize());
    fFrame->Resize(fgInitW, fgInitH);
 
-   fPShapeWrap = new TGLPShapeObj(0, this);
-
    // set recursive cleanup, but exclude fGedEditor
    // destructor of fGedEditor has own way of handling child nodes
    if (fLeftVerticalFrame)
@@ -265,6 +303,14 @@ TGLSAViewer::~TGLSAViewer()
    fGLWidget = 0;
 }
 
+//______________________________________________________________________________
+TGCompositeFrame* TGLSAViewer::GetFrame() const
+{
+   // Return the main-frame.
+
+   return fFrame;
+}
+
 //______________________________________________________________________________
 void TGLSAViewer::CreateGLWidget()
 {
@@ -308,16 +354,6 @@ void TGLSAViewer::DestroyGLWidget()
    fGLWidget = 0;
 }
 
-//______________________________________________________________________________
-void TGLSAViewer::RefreshPadEditor(TObject* changed)
-{
-   // Refresh pad editor.
-
-   if (changed == 0 || fGedEditor->GetModel() == changed) {
-      fGedEditor->SetModel(fPad, fGedEditor->GetModel(), kButton1Down);
-   }
-}
-
 //______________________________________________________________________________
 void TGLSAViewer::CreateMenus()
 {
@@ -363,12 +399,21 @@ void TGLSAViewer::CreateMenus()
    fHelpMenu->Associate(fFrame);
 
    // Create menubar
-   fMenuBar = new TGMenuBar(fFrame, 1, 1, kHorizontalFrame);
+   fMenuBar = new TGMenuBar(fFrame);
    fMenuBar->AddPopup("&File", fFileMenu, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0));
    fMenuBar->AddPopup("&Camera", fCameraMenu, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0));
    fMenuBar->AddPopup("&Help",    fHelpMenu,    new TGLayoutHints(kLHintsTop | kLHintsRight));
    fFrame->AddFrame(fMenuBar, new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 0, 0, 1, 1));
-
+   gVirtualX->SelectInput(fMenuBar->GetId(),
+                          kKeyPressMask | kExposureMask | kPointerMotionMask
+                          | kStructureNotifyMask | kFocusChangeMask
+                          | kEnterWindowMask | kLeaveWindowMask);
+
+   fMenuBut = new TGButton(fFrame);
+   fMenuBut->ChangeOptions(kRaisedFrame | kFixedHeight);
+   fMenuBut->Resize(20, 4);
+   fMenuBut->SetBackgroundColor(0x80A0C0);
+   fFrame->AddFrame(fMenuBut, new TGLayoutHints(kLHintsNormal | kLHintsExpandX, 0, 0, 1, 1));
 }
 
 //______________________________________________________________________________
@@ -414,6 +459,25 @@ void TGLSAViewer::CreateFrames()
    fRightVerticalFrame->AddFrame(fGLWidget, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
 }
 
+//______________________________________________________________________________
+void TGLSAViewer::SelectionChanged()
+{
+   // Update GUI components for embedded viewer selection change.
+   // Override from TGLViewer.
+
+   TGLPhysicalShape *selected = const_cast<TGLPhysicalShape*>(GetSelected());
+
+   if (selected) {
+      fPShapeWrap->fPShape = selected;
+      if (fFileMenu->IsEntryChecked(kGLEditObject))
+         fGedEditor->SetModel(fPad, selected->GetLogical()->GetExternal(), kButton1Down);
+      else
+         fGedEditor->SetModel(fPad, fPShapeWrap, kButton1Down);
+   } else {
+      fPShapeWrap->fPShape = 0;
+      fGedEditor->SetModel(fPad, this, kButton1Down);
+   }
+}
 
 //______________________________________________________________________________
 void TGLSAViewer::Show()
@@ -440,6 +504,77 @@ void TGLSAViewer::DeleteMenuBar()
    fDeleteMenuBar=kTRUE;
 }
 
+//______________________________________________________________________________
+void TGLSAViewer::DisableCloseMenuEntries()
+{
+   // Deactivate menu entries for closing the GL window and exiting ROOT.
+
+   fFileMenu->DeleteEntry(kGLCloseViewer);
+   fFileMenu->DeleteEntry(kGLQuitROOT);
+}
+
+//______________________________________________________________________________
+void TGLSAViewer::EnableMenuBarHiding()
+{
+   // Enable hiding of menu bar.
+
+   if (fHideMenuBar)
+      return;
+
+   fHideMenuBar = kTRUE;
+
+   fMenuBar->Connect("ProcessedEvent(Event_t*)", "TGLSAViewer", this, "HandleMenuBarHiding(Event_t*)");
+   fMenuBut->Connect("ProcessedEvent(Event_t*)", "TGLSAViewer", this, "HandleMenuBarHiding(Event_t*)");
+
+   fFrame->HideFrame(fMenuBar);
+   fFrame->ShowFrame(fMenuBut);
+   fFrame->Layout();
+}
+
+//______________________________________________________________________________
+void TGLSAViewer::HandleMenuBarHiding(Event_t* ev)
+{
+   // Maybe switch menu-bar / menu-button.
+
+   TGFrame *f = (TGFrame*) gTQSender;
+
+   if (f == fMenuBut)
+   {
+      if (ev->fType == kEnterNotify)
+      {
+         fFrame->HideFrame(fMenuBut);
+         fFrame->ShowFrame(fMenuBar);
+         fFrame->Layout();
+      }
+   }
+   else if (f == fMenuBar)
+   {
+      if (ev->fType == kLeaveNotify &&
+          (ev->fX < 0 || ev->fX >= (Int_t) f->GetWidth() ||
+           ev->fY < 0 || ev->fY >= (Int_t) f->GetHeight()))
+      {
+         if (fMenuBar->GetCurrent() == 0)
+         {
+            fFrame->HideFrame(fMenuBar);
+            fFrame->ShowFrame(fMenuBut);
+            fFrame->Layout();
+         }
+         else
+         {
+            fMenuBar->GetCurrent()->Connect("ProcessedEvent(Event_t*)", "TGLSAViewer", this, "HandleMenuBarHiding(Event_t*)");
+         }
+      }
+   }
+   else
+   {
+      f->Disconnect("ProcessedEvent(Event_t*)", this);
+
+      fFrame->HideFrame(fMenuBar);
+      fFrame->ShowFrame(fMenuBut);
+      fFrame->Layout();
+   }
+}
+
 //______________________________________________________________________________
 Bool_t TGLSAViewer::ProcessFrameMessage(Long_t msg, Long_t parm1, Long_t)
 {
@@ -476,7 +611,7 @@ Bool_t TGLSAViewer::ProcessFrameMessage(Long_t msg, Long_t parm1, Long_t)
             break;
          }
          case kGLHelpViewer: {
-            TRootHelpDialog * hd = new TRootHelpDialog(fFrame, "Help on GL Viewer...", 600, 400);
+            TRootHelpDialog * hd = new TRootHelpDialog(fFrame, "Help on GL Viewer...", 660, 400);
             hd->AddText(fgHelpText1);
             hd->AddText(fgHelpText2);
             hd->Popup();
@@ -572,18 +707,18 @@ Bool_t TGLSAViewer::ProcessFrameMessage(Long_t msg, Long_t parm1, Long_t)
          case kGLCloseViewer:
             // Exit needs to be delayed to avoid bad drawable X ids - GUI
             // will all be changed in future anyway
-
             TTimer::SingleShot(50, "TGLSAFrame", fFrame, "SendCloseMessage()");
             break;
          case kGLQuitROOT:
             if (!gApplication->ReturnFromRun())
                delete this;
             gApplication->Terminate(0);
-            default:
             break;
-            }
-            default:
+         default:
             break;
+         }
+      default:
+         break;
       }
    default:
       break;
@@ -592,40 +727,6 @@ Bool_t TGLSAViewer::ProcessFrameMessage(Long_t msg, Long_t parm1, Long_t)
    return kTRUE;
 }
 
-//______________________________________________________________________________
-void TGLSAViewer::SelectionChanged()
-{
-   // Update GUI components for embedded viewer selection change.
-
-   // !!! MT this whole selection-signal-stuff is verrrry strange.
-   // At least, shouldn't we emit a signal here?
-   //
-   // I misuse this function after overlay-mouse-drag as well.
-   // Need something like refresh-viewer-gui which also does ged update.
-
-   TGLPhysicalShape *selected = const_cast<TGLPhysicalShape*>(GetSelected());
-
-   if (selected) {
-      fPShapeWrap->fPShape = selected;
-      if (fFileMenu->IsEntryChecked(kGLEditObject))
-         fGedEditor->SetModel(fPad, selected->GetLogical()->GetExternal(), kButton1Down);
-      else
-         fGedEditor->SetModel(fPad, fPShapeWrap, kButton1Down);
-   } else {
-      fPShapeWrap->fPShape = 0;
-      fGedEditor->SetModel(fPad, this, kButton1Down);
-   }
-}
-
-//______________________________________________________________________________
-void TGLSAViewer::OverlayDragFinished()
-{
-   // An overlay operation can result in change to an object.
-   // Refresh geditor.
-
-   fGedEditor->SetModel(fPad, fGedEditor->GetModel(), kButton1Down);
-}
-
 //______________________________________________________________________________
 void TGLSAViewer::ToggleEditObject()
 {
diff --git a/graf3d/gl/src/TGLViewer.cxx b/graf3d/gl/src/TGLViewer.cxx
index eaa61601338..9f318b8f05b 100644
--- a/graf3d/gl/src/TGLViewer.cxx
+++ b/graf3d/gl/src/TGLViewer.cxx
@@ -48,6 +48,8 @@
 #include "TGLWidget.h"
 #include "TGLFBO.h"
 #include "TGLViewerEditor.h"
+#include "TGedEditor.h"
+#include "TGLPShapeObj.h"
 
 #include "KeySymbols.h"
 #include "TContextMenu.h"
@@ -117,6 +119,8 @@ TGLViewer::TGLViewer(TVirtualPad * pad, Int_t x, Int_t y,
    fCurrentOvlElm     (0),
 
    fEventHandler(0),
+   fGedEditor(0),
+   fPShapeWrap(0),
    fPushAction(kPushStd), fDragAction(kDragNone),
    fRedrawTimer(0),
    fMaxSceneDrawTimeHQ(5000),
@@ -139,8 +143,7 @@ TGLViewer::TGLViewer(TVirtualPad * pad, Int_t x, Int_t y,
    fGLCtxId(0),
    fIgnoreSizesOnUpdate(kFALSE),
    fResetCamerasOnUpdate(kTRUE),
-   fResetCamerasOnNextUpdate(kFALSE),
-   fResetCameraOnDoubleClick(kTRUE)
+   fResetCamerasOnNextUpdate(kFALSE)
 {
    // Construct the viewer object, with following arguments:
    //    'pad' - external pad viewer is bound to
@@ -174,6 +177,8 @@ TGLViewer::TGLViewer(TVirtualPad * pad) :
    fCurrentOvlElm     (0),
 
    fEventHandler(0),
+   fGedEditor(0),
+   fPShapeWrap(0),
    fPushAction(kPushStd), fDragAction(kDragNone),
    fRedrawTimer(0),
    fMaxSceneDrawTimeHQ(5000),
@@ -196,8 +201,7 @@ TGLViewer::TGLViewer(TVirtualPad * pad) :
    fGLCtxId(0),
    fIgnoreSizesOnUpdate(kFALSE),
    fResetCamerasOnUpdate(kTRUE),
-   fResetCamerasOnNextUpdate(kFALSE),
-   fResetCameraOnDoubleClick(kTRUE)
+   fResetCamerasOnNextUpdate(kFALSE)
 {
    //gl-embedded viewer's ctor
    // Construct the viewer object, with following arguments:
@@ -230,6 +234,8 @@ void TGLViewer::InitSecondaryObjects()
    fSelectedPShapeRef->SetDrawBBox(kTRUE);
    AddOverlayElement(fSelectedPShapeRef);
 
+   fPShapeWrap = new TGLPShapeObj(0, this);
+
    fLightColorSet.StdLightBackground();
    if (fgUseDefaultColorSetForNewViewers) {
       fRnrCtx->ChangeBaseColorSet(&fgDefaultColorSet);
@@ -1643,22 +1649,6 @@ const TGLPhysicalShape * TGLViewer::GetSelected() const
 /**************************************************************************/
 /**************************************************************************/
 
-//______________________________________________________________________________
-void TGLViewer::SelectionChanged()
-{
-   // Emit signal indicating selection has changed.
-
-   Emit("SelectionChanged()");
-}
-
-//______________________________________________________________________________
-void TGLViewer::OverlayDragFinished()
-{
-   // Emit signal indicating that an overlay drag has finished.
-
-   Emit("OverlayDragFinished()");
-}
-
 //______________________________________________________________________________
 void TGLViewer::MouseOver(TGLPhysicalShape *shape)
 {
@@ -1775,6 +1765,48 @@ void TGLViewer::PrintObjects()
    TGLOutput::Capture(*this);
 }
 
+//______________________________________________________________________________
+void TGLViewer::SelectionChanged()
+{
+   // Update GUI components for embedded viewer selection change.
+
+   if (!fGedEditor)
+      return;
+
+   TGLPhysicalShape *selected = const_cast<TGLPhysicalShape*>(GetSelected());
+
+   if (selected) {
+      fPShapeWrap->fPShape = selected;
+      fGedEditor->SetModel(fPad, fPShapeWrap, kButton1Down);
+   } else {
+      fPShapeWrap->fPShape = 0;
+      fGedEditor->SetModel(fPad, this, kButton1Down);
+   }
+}
+
+//______________________________________________________________________________
+void TGLViewer::OverlayDragFinished()
+{
+   // An overlay operation can result in change to an object.
+   // Refresh geditor.
+
+   if (fGedEditor)
+   {
+      fGedEditor->SetModel(fPad, fGedEditor->GetModel(), kButton1Down);
+   }
+}
+
+//______________________________________________________________________________
+void TGLViewer::RefreshPadEditor(TObject* obj)
+{
+   // Update GED editor if it is set.
+
+   if (fGedEditor && (obj == 0 || fGedEditor->GetModel() == obj))
+   {
+      fGedEditor->SetModel(fPad, fGedEditor->GetModel(), kButton1Down);
+   }
+}
+
 //______________________________________________________________________________
 void TGLViewer::SetEventHandler(TGEventHandler *handler)
 {
diff --git a/graf3d/gl/src/TGLViewerEditor.cxx b/graf3d/gl/src/TGLViewerEditor.cxx
index fac0a64010a..fa8dcad4ec5 100644
--- a/graf3d/gl/src/TGLViewerEditor.cxx
+++ b/graf3d/gl/src/TGLViewerEditor.cxx
@@ -35,7 +35,6 @@ TGLViewerEditor::TGLViewerEditor(const TGWindow *p,  Int_t width, Int_t height,
    fClearColor(0),
    fIgnoreSizesOnUpdate(0),
    fResetCamerasOnUpdate(0),
-   fResetCameraOnDoubleClick(0),
    fUpdateScene(0),
    fCameraHome(0),
    fMaxSceneDrawTimeHQ(0),
@@ -90,7 +89,6 @@ void TGLViewerEditor::ConnectSignals2Slots()
    fClearColor->Connect("ColorSelected(Pixel_t)", "TGLViewerEditor", this, "DoClearColor(Pixel_t)");
    fIgnoreSizesOnUpdate->Connect("Toggled(Bool_t)", "TGLViewerEditor", this, "DoIgnoreSizesOnUpdate()");
    fResetCamerasOnUpdate->Connect("Toggled(Bool_t)", "TGLViewerEditor", this, "DoResetCamerasOnUpdate()");
-   fResetCameraOnDoubleClick->Connect("Toggled(Bool_t)", "TGLViewerEditor", this, "DoResetCameraOnDoubleClick()");
    fUpdateScene->Connect("Pressed()", "TGLViewerEditor", this, "DoUpdateScene()");
    fCameraHome->Connect("Pressed()", "TGLViewerEditor", this, "DoCameraHome()");
    fMaxSceneDrawTimeHQ->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateMaxDrawTimes()");
@@ -157,7 +155,6 @@ void TGLViewerEditor::SetModel(TObject* obj)
    fClearColor->Enable(!fViewer->IsUsingDefaultColorSet());
    fIgnoreSizesOnUpdate->SetState(fViewer->GetIgnoreSizesOnUpdate() ? kButtonDown : kButtonUp);
    fResetCamerasOnUpdate->SetState(fViewer->GetResetCamerasOnUpdate() ? kButtonDown : kButtonUp);
-   fResetCameraOnDoubleClick->SetState(fViewer->GetResetCameraOnDoubleClick() ? kButtonDown : kButtonUp);
    fMaxSceneDrawTimeHQ->SetNumber(fViewer->GetMaxSceneDrawTimeHQ());
    fMaxSceneDrawTimeLQ->SetNumber(fViewer->GetMaxSceneDrawTimeLQ());
    fPointSizeScale->SetNumber(fViewer->GetPointScale());
@@ -210,18 +207,10 @@ void TGLViewerEditor::DoResetCamerasOnUpdate()
    fViewer->SetResetCamerasOnUpdate(fResetCamerasOnUpdate->IsOn());
 }
 
-//______________________________________________________________________________
-void TGLViewerEditor::DoResetCameraOnDoubleClick()
-{
-   // ResetCameraOnDoubleClick was toggled.
-
-   fViewer->SetResetCameraOnDoubleClick(fResetCameraOnDoubleClick->IsOn());
-}
-
 //______________________________________________________________________________
 void TGLViewerEditor::DoUpdateScene()
 {
-   // ResetCameraOnDoubleClick was toggled.
+   // UpdateScene was clicked.
 
    fViewer->UpdateScene();
 }
@@ -229,7 +218,7 @@ void TGLViewerEditor::DoUpdateScene()
 //______________________________________________________________________________
 void TGLViewerEditor::DoCameraHome()
 {
-   // ResetCameraOnDoubleClick was toggled.
+   // CameraHome was clicked.
 
    fViewer->ResetCurrentCamera();
    ViewerRedraw();
@@ -392,9 +381,6 @@ void TGLViewerEditor::CreateStyleTab()
    fResetCamerasOnUpdate = new TGCheckButton(this, "Reset on update");
    fResetCamerasOnUpdate->SetToolTipText("Reset camera on scene update");
    AddFrame(fResetCamerasOnUpdate, new TGLayoutHints(kLHintsLeft, 4, 1, 1, 1));
-   fResetCameraOnDoubleClick = new TGCheckButton(this, "Reset on dbl-click");
-   fResetCameraOnDoubleClick->SetToolTipText("Reset cameras on double-click");
-   AddFrame(fResetCameraOnDoubleClick, new TGLayoutHints(kLHintsLeft, 4, 1, 1, 1));
 
    TGCompositeFrame* af = this;
    fUpdateScene = new TGTextButton(af, "Update Scene", 130);
diff --git a/graf3d/gviz3d/src/TStructViewerGUI.cxx b/graf3d/gviz3d/src/TStructViewerGUI.cxx
index 19497303bd2..c961308fc24 100644
--- a/graf3d/gviz3d/src/TStructViewerGUI.cxx
+++ b/graf3d/gviz3d/src/TStructViewerGUI.cxx
@@ -214,7 +214,6 @@ TStructViewerGUI::TStructViewerGUI(TStructViewer* parent, TStructNode* nodePtr,
    fGLViewer->PadPaint(fCanvas);
    fGLViewer->Connect("MouseOver(TGLPhysicalShape*)", "TStructViewerGUI", this, "MouseOverSlot(TGLPhysicalShape*)");
    fGLViewer->GetGLWidget()->Connect("ProcessedEvent(Event_t*)", "TStructViewerGUI", this, "GLWidgetProcessedEventSlot(Event_t*))");
-   fGLViewer->SetResetCameraOnDoubleClick(false);
    fGLViewer->Connect("DoubleClicked()", "TStructViewerGUI", this, "DoubleClickedSlot()");
    fGLViewer->SetCurrentCamera(TGLViewer::kCameraPerspXOY);
    Update();
diff --git a/tutorials/eve/calorimeters.C b/tutorials/eve/calorimeters.C
index e4c2d0ddadc..d955f886e17 100644
--- a/tutorials/eve/calorimeters.C
+++ b/tutorials/eve/calorimeters.C
@@ -82,6 +82,8 @@ TEveCaloLego* MakeCaloLego(TEveCaloData* data, TEveWindowSlot* slot)
       v = gEve->GetDefaultViewer();
       s = gEve->GetEventScene();
    }
+   v->SetElementName("Viewer - Lego");
+   s->SetElementName("Scene - Lego");
 
    gStyle->SetPalette(1, 0);
    TEveCaloLego* lego = new TEveCaloLego(data);
@@ -113,6 +115,8 @@ TEveCalo3D* MakeCalo3D(TEveCaloData* data, TEveWindowSlot* slot)
 
    TEveViewer* v; TEveScene* s;
    MakeViewerScene(slot, v, s);
+   v->SetElementName("Viewer - 3D");
+   s->SetElementName("Scene - 3D");
 
    TEveCalo3D* calo3d = new TEveCalo3D(data);
    calo3d->SetBarrelRadius(129);
@@ -129,6 +133,8 @@ TEveCalo2D* MakeCalo2D(TEveCalo3D* calo3d, TEveWindowSlot* slot, TEveProjection:
 
    TEveViewer* v; TEveScene* s;
    MakeViewerScene(slot, v, s);
+   v->SetElementName("Viewer - 2D");
+   s->SetElementName("Scene - 2D");
 
    TEveProjectionManager* mng = new TEveProjectionManager();
    mng->SetProjection(t);
@@ -152,7 +158,7 @@ void MakeViewerScene(TEveWindowSlot* slot, TEveViewer*& v, TEveScene*& s)
    // Create a scene and a viewer in the given slot.
 
    v = new TEveViewer("Viewer");
-   v->SpawnGLEmbeddedViewer();
+   v->SpawnGLViewer(gEve->GetEditor());
    slot->ReplaceWindow(v);
    gEve->GetViewers()->AddElement(v);
    s = gEve->SpawnNewScene("Scene");
diff --git a/tutorials/eve/window_manager.C b/tutorials/eve/window_manager.C
index 110294ecb46..196263f5d3f 100644
--- a/tutorials/eve/window_manager.C
+++ b/tutorials/eve/window_manager.C
@@ -40,7 +40,7 @@ void PackTest()
    // Embedded viewer.
    slot = pack1->NewSlot();
    v = new TEveViewer("BarViewer");
-   v->SpawnGLEmbeddedViewer();
+   v->SpawnGLEmbeddedViewer(gEve->GetEditor());
    slot->ReplaceWindow(v);
    v->SetElementName("Bar Embedded Viewer");
 
@@ -117,8 +117,8 @@ void DetailTest()
       latex->DrawLatex(x, y, "#color[5]{#Box} color");
    }
 
-   // viwer
-   TGLEmbeddedViewer* ev = new TGLEmbeddedViewer(hf, 0, 0);
+   // viewer
+   TGLEmbeddedViewer* ev = new TGLEmbeddedViewer(hf, 0, 0, 0);
    TEveViewer *v = new TEveViewer();
    v->SetGLViewer(ev,ev->GetFrame());
    gEve->GetViewers()->AddElement(v);
-- 
GitLab