changeset 27335:50216d7a2f6b

eliminate static wrapper functions in gh_manager class This is a large but straightforward change to eliminate the remains of the singleton pattern that was used for the gh_manager class. All static functions in the gh_manager class that previously used the "instance" function to access the gh_manager object stored in the global interpreter object and then called the corresponding "do_" functions have been eliminated. The "do_" prefix has been removed from the normal member functions and all uses of the static functions (calls of the form gh_manager::X) have been replaced with a call to the member function. The gh_manager object is accessed through the interpreter object and there is a new __get_gh_manager__ convenience function defined in the intepreter-private.cc file. Additionally, instead of using the gh_manager::auto_lock class, we access the mutex variable associated with the gh_manager object and pass it to the octave::autolock constructor to manage scoped locks for the gh_manager class. The following interpreter functions are now "methods" and require the interpreter as the first argument: F__calc_dimensions__, F__fltk_check__, F__get__, F__get_frame__, F__go_axes__, F__go_delete__, F__go_execute_callback__, F__go_figure__, F__go_figure_handles__, F__go_handles__, F__go_hggroup__, F__go_image__, F__go_light__, F__go_line__, F__go_patch__, F__go_post_callback__, F__go_surface__, F__go_text__, F__go_uibuttongroup__, F__go_uicontextmenu__, F__go_uicontrol__, F__go_uimenu__, F__go_uipanel__, F__go_uipushtool__, F__go_uitable__, F__go_uitoggletool__, F__go_uitoolbar__, F__image_pixel_size__, F__show_figure__, F__shutdown_qt__, F__update_normals__, F__zoom__, Faddlistener, Faddproperty, Fdellistener, Fdrawnow, Fget, Fishghandle, Fkbhit, Fpause, Freset, Fset, and Fwaitfor. Files affected: BaseControl.cc, ButtonControl.cc, ButtonGroup.cc, Canvas.cc, Container.cc, ContextMenu.cc, Figure.cc, GLCanvas.cc, Object.cc, Panel.cc, QtHandlesUtils.h, SliderControl.cc, Table.cc, __init_qt__.cc, qt-graphics-toolkit.cc, main-window.cc, gl-render.cc, gl-render.h, gl2ps-print.cc, graphics-toolkit.cc, graphics.cc, graphics.in.h, input.cc, interpreter.cc, sysdep.cc, utils.cc, __init_fltk__.cc.
author John W. Eaton <jwe@octave.org>
date Fri, 09 Aug 2019 10:36:08 -0400
parents 2c4759c8239c
children 1fb234f01eea
files libgui/graphics/BaseControl.cc libgui/graphics/ButtonControl.cc libgui/graphics/ButtonGroup.cc libgui/graphics/Canvas.cc libgui/graphics/Container.cc libgui/graphics/ContextMenu.cc libgui/graphics/Figure.cc libgui/graphics/GLCanvas.cc libgui/graphics/Object.cc libgui/graphics/Panel.cc libgui/graphics/QtHandlesUtils.h libgui/graphics/SliderControl.cc libgui/graphics/Table.cc libgui/graphics/__init_qt__.cc libgui/graphics/qt-graphics-toolkit.cc libgui/src/main-window.cc libinterp/corefcn/gl-render.cc libinterp/corefcn/gl-render.h libinterp/corefcn/gl2ps-print.cc libinterp/corefcn/graphics-toolkit.cc libinterp/corefcn/graphics.cc libinterp/corefcn/graphics.in.h libinterp/corefcn/input.cc libinterp/corefcn/interpreter.cc libinterp/corefcn/sysdep.cc libinterp/corefcn/utils.cc libinterp/dldfcn/__init_fltk__.cc
diffstat 27 files changed, 1468 insertions(+), 904 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/graphics/BaseControl.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/graphics/BaseControl.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -33,6 +33,9 @@
 #include "ContextMenu.h"
 #include "QtHandlesUtils.h"
 
+#include "graphics.h"
+#include "interpreter-private.h"
+
 namespace QtHandles
 {
 
@@ -195,12 +198,14 @@
   bool
   BaseControl::eventFilter (QObject *watched, QEvent *xevent)
   {
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("BaseControl::eventFilter");
+
     switch (xevent->type ())
       {
       case QEvent::Resize:
         if (m_normalizedFont)
           {
-            gh_manager::auto_lock lock;
+            octave::autolock guard (gh_mgr.graphics_lock ());
 
             qWidget<QWidget> ()->setFont (Utils::computeFont<uicontrol>
                                           (properties<uicontrol> ()));
@@ -209,7 +214,7 @@
 
       case QEvent::MouseButtonPress:
         {
-          gh_manager::auto_lock lock;
+          octave::autolock guard (gh_mgr.graphics_lock ());
 
           QMouseEvent *m = dynamic_cast<QMouseEvent *> (xevent);
           graphics_object go = object ();
@@ -251,7 +256,7 @@
       case QEvent::MouseMove:
         if (qWidget<QWidget> ()->hasMouseTracking ())
           {
-            gh_manager::auto_lock lock;
+            octave::autolock guard (gh_mgr.graphics_lock ());
 
             QMouseEvent *m = dynamic_cast<QMouseEvent *> (xevent);
             graphics_object go = object ();
@@ -270,7 +275,7 @@
       case QEvent::KeyPress:
         if (m_keyPressHandlerDefined)
           {
-            gh_manager::auto_lock lock;
+            octave::autolock guard (gh_mgr.graphics_lock ());
 
             octave_scalar_map keyData =
               Utils::makeKeyEventStruct (dynamic_cast<QKeyEvent *> (xevent));
--- a/libgui/graphics/ButtonControl.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/graphics/ButtonControl.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -31,6 +31,9 @@
 #include "Container.h"
 #include "QtHandlesUtils.h"
 
+#include "graphics.h"
+#include "interpreter-private.h"
+
 namespace QtHandles
 {
 
@@ -92,7 +95,9 @@
                     btn->setChecked (false);
                     if (up.style_is ("radiobutton") || up.style_is ("togglebutton"))
                       {
-                        Object *parent = Object::parentObject (gh_manager::get_object (up.get___myhandle__ ()));
+                        gh_manager& gh_mgr = octave::__get_gh_manager__ ("ButtonControl::update");
+
+                        Object *parent = Object::parentObject (gh_mgr.get_object (up.get___myhandle__ ()));
                         ButtonGroup *btnGroup = dynamic_cast<ButtonGroup *>(parent);
                         if (btnGroup)
                           btnGroup->selectNothing ();
@@ -118,7 +123,9 @@
 
     if (! m_blockCallback && btn->isCheckable ())
       {
-        gh_manager::auto_lock lock;
+        gh_manager& gh_mgr = octave::__get_gh_manager__ ("ButtonControl::toggled");
+
+        octave::autolock guard (gh_mgr.graphics_lock ());
 
         uicontrol::properties& up = properties<uicontrol> ();
 
--- a/libgui/graphics/ButtonGroup.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/graphics/ButtonGroup.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -42,6 +42,7 @@
 #include "QtHandlesUtils.h"
 #include "qt-graphics-toolkit.h"
 
+#include "interpreter-private.h"
 #include "ov-struct.h"
 
 namespace QtHandles
@@ -183,13 +184,16 @@
   {
     if (! m_blockUpdates)
       {
+        gh_manager& gh_mgr = octave::__get_gh_manager__ ("ButtonGroup::eventFilter");
+
         if (watched == qObject ())
           {
             switch (xevent->type ())
               {
               case QEvent::Resize:
                 {
-                  gh_manager::auto_lock lock;
+                  octave::autolock guard (gh_mgr.graphics_lock ());
+
                   graphics_object go = object ();
 
                   if (go.valid_object ())
@@ -219,7 +223,7 @@
 
                   if (m->button () == Qt::RightButton)
                     {
-                      gh_manager::auto_lock lock;
+                      octave::autolock guard (gh_mgr.graphics_lock ());
 
                       ContextMenu::executeAt (properties (), m->globalPos ());
                     }
@@ -237,7 +241,7 @@
               case QEvent::Resize:
                 if (qWidget<QWidget> ()->isVisible ())
                   {
-                    gh_manager::auto_lock lock;
+                    octave::autolock guard (gh_mgr.graphics_lock ());
 
                     properties ().update_boundingbox ();
                   }
@@ -353,8 +357,13 @@
       case uibuttongroup::properties::ID_SELECTEDOBJECT:
         {
           graphics_handle h = pp.get_selectedobject ();
-          gh_manager::auto_lock lock;
-          graphics_object go = gh_manager::get_object (h);
+
+          gh_manager& gh_mgr = octave::__get_gh_manager__ ("ButtonGroup::update");
+
+          octave::autolock guard (gh_mgr.graphics_lock ());
+
+          graphics_object go = gh_mgr.get_object (h);
+
           Object *selectedObject = qt_graphics_toolkit::toolkitObject (go);
           ToggleButtonControl *toggle = static_cast<ToggleButtonControl *>
                                         (selectedObject);
@@ -454,7 +463,10 @@
     Q_UNUSED (toggled);
     if (! m_blockUpdates)
       {
-        gh_manager::auto_lock lock;
+        gh_manager& gh_mgr = octave::__get_gh_manager__ ("ButtonGroup::buttonToggled");
+
+        octave::autolock guard (gh_mgr.graphics_lock ());
+
         uibuttongroup::properties& bp = properties<uibuttongroup> ();
 
         graphics_handle oldValue = bp.get_selectedobject ();
@@ -479,7 +491,10 @@
   {
     Q_UNUSED (btn);
 
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("ButtonGroup::buttonClicked");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
+
     uibuttongroup::properties& bp = properties<uibuttongroup> ();
 
     graphics_handle oldValue = bp.get_selectedobject ();
--- a/libgui/graphics/Canvas.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/graphics/Canvas.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -41,6 +41,7 @@
 
 #include "annotation-dialog.h"
 
+#include "graphics.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
 #include "oct-opengl.h"
@@ -192,7 +193,9 @@
   Canvas::updateCurrentPoint (const graphics_object& fig,
                               const graphics_object& obj, QMouseEvent *event)
   {
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Canvas::updateCurrentPoint");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     emit gh_set_event (fig.get_handle (), "currentpoint",
                        Utils::figureCurrentPoint (fig, event), false);
@@ -202,7 +205,7 @@
 
     for (int i = 0; i < num_children; i++)
       {
-        graphics_object childObj (gh_manager::get_object (children(i)));
+        graphics_object childObj (gh_mgr.get_object (children(i)));
 
         if (childObj.isa ("axes"))
           {
@@ -230,7 +233,9 @@
   Canvas::updateCurrentPoint (const graphics_object& fig,
                               const graphics_object& obj)
   {
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Canvas::updateCurrentPoint");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     emit gh_set_event (fig.get_handle (), "currentpoint",
                        Utils::figureCurrentPoint (fig), false);
@@ -240,7 +245,7 @@
 
     for (int i = 0; i < num_children; i++)
       {
-        graphics_object childObj (gh_manager::get_object (children(i)));
+        graphics_object childObj (gh_mgr.get_object (children(i)));
 
         if (childObj.isa ("axes"))
           {
@@ -269,7 +274,9 @@
   static void
   autoscale_axes (axes::properties& ap)
   {
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("autoscale_axes");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     // Reset zoom stack
     ap.clear_zoom_stack (false);
@@ -284,7 +291,9 @@
   {
     if (! m_redrawBlocked)
       {
-        gh_manager::auto_lock lock;
+        gh_manager& gh_mgr = octave::__get_gh_manager__ ("Canvas::canvasPaintEvent");
+
+        octave::autolock guard (gh_mgr.graphics_lock ());
 
         draw (m_handle);
 
@@ -350,9 +359,11 @@
     Matrix children = obj.get_properties ().get_all_children ();
     octave_idx_type num_children = children.numel ();
 
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Canvas::select_object");
+
     for (int i = 0; i < num_children; i++)
       {
-        graphics_object childObj (gh_manager::get_object (children(i)));
+        graphics_object childObj (gh_mgr.get_object (children(i)));
 
         if (childObj.isa ("axes"))
           {
@@ -446,8 +457,11 @@
   void
   Canvas::canvasMouseMoveEvent (QMouseEvent *event)
   {
-    gh_manager::auto_lock lock;
-    graphics_object ax = gh_manager::get_object (m_mouseAxes);
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Canvas::canvasMouseMoveEvent");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
+
+    graphics_object ax = gh_mgr.get_object (m_mouseAxes);
 
     if (m_mouseMode != NoMode && (ax.valid_object () || m_mouseMode == TextMode))
       {
@@ -502,7 +516,7 @@
       }
     else if (m_mouseMode == NoMode)
       {
-        graphics_object obj = gh_manager::get_object (m_handle);
+        graphics_object obj = gh_mgr.get_object (m_handle);
 
         if (obj.valid_object ())
           {
@@ -519,7 +533,7 @@
       }
 
     // Update mouse coordinates in the figure window status bar
-    graphics_object obj = gh_manager::get_object (m_handle);
+    graphics_object obj = gh_mgr.get_object (m_handle);
     graphics_object figObj = obj.get_ancestor ("figure");
 
     if (figObj.valid_object () && obj.valid_object ())
@@ -578,8 +592,11 @@
   void
   Canvas::canvasMousePressEvent (QMouseEvent *event)
   {
-    gh_manager::auto_lock lock;
-    graphics_object obj = gh_manager::get_object (m_handle);
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Canvas::canvasMousePressEvent");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
+
+    graphics_object obj = gh_mgr.get_object (m_handle);
 
     bool isdblclick = (event->type () == QEvent::MouseButtonDblClick);
 
@@ -590,7 +607,7 @@
         // Any click in a figure canvas makes it current
         if (figObj)
           {
-            graphics_object root = gh_manager::get_object (0);
+            graphics_object root = gh_mgr.get_object (0);
             Utils::properties<root_figure> (root)
               .set_currentfigure (figObj.get_handle ().as_octave_value ());
           }
@@ -611,9 +628,9 @@
             // Objects with "hittest"->"off" pass the mouse event to their
             // parent and so on.
             graphics_object tmpgo;
-            tmpgo = gh_manager::get_object (currentObj.get_parent ());
+            tmpgo = gh_mgr.get_object (currentObj.get_parent ());
             while (tmpgo && ! tmpgo.get_properties ().is_hittest ())
-              tmpgo = gh_manager::get_object (tmpgo.get_parent ());
+              tmpgo = gh_mgr.get_object (tmpgo.get_parent ());
 
             if (tmpgo && tmpgo.get_handle () != 0.0)
               currentObj = tmpgo;
@@ -787,17 +804,20 @@
   void
   Canvas::canvasMouseReleaseEvent (QMouseEvent *event)
   {
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Canvas::canvasMouseReleaseEvent");
+
     if ((m_mouseMode == ZoomInMode || m_mouseMode == ZoomOutMode)
         && m_mouseAxes.ok ())
       {
-        gh_manager::auto_lock lock;
-        graphics_object ax = gh_manager::get_object (m_mouseAxes);
+        octave::autolock guard (gh_mgr.graphics_lock ());
+
+        graphics_object ax = gh_mgr.get_object (m_mouseAxes);
 
         if (ax.valid_object ())
           {
             axes::properties& ap = Utils::properties<axes> (ax);
 
-            graphics_object obj = gh_manager::get_object (m_handle);
+            graphics_object obj = gh_mgr.get_object (m_handle);
 
             graphics_object figObj (obj.get_ancestor ("figure"));
 
@@ -834,8 +854,9 @@
       }
     else if (m_mouseMode == NoMode)
       {
-        gh_manager::auto_lock lock;
-        graphics_object obj = gh_manager::get_object (m_handle);
+        octave::autolock guard (gh_mgr.graphics_lock ());
+
+        graphics_object obj = gh_mgr.get_object (m_handle);
 
         if (obj.valid_object ())
           {
@@ -847,10 +868,11 @@
       }
     else if (m_mouseMode == TextMode)
       {
-        gh_manager::auto_lock lock;
+        octave::autolock guard (gh_mgr.graphics_lock ());
 
-        graphics_object figObj =
-          gh_manager::get_object (m_handle).get_ancestor ("figure");
+        graphics_object figObj
+          = gh_mgr.get_object (m_handle).get_ancestor ("figure");
+
         if (figObj.valid_object ())
           {
             QWidget *w = qWidget ();
@@ -890,8 +912,11 @@
   void
   Canvas::canvasWheelEvent (QWheelEvent *event)
   {
-    gh_manager::auto_lock lock;
-    graphics_object obj = gh_manager::get_object (m_handle);
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Canvas::canvasWheelEvent");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
+
+    graphics_object obj = gh_mgr.get_object (m_handle);
 
     if (obj.valid_object ())
       {
@@ -906,7 +931,7 @@
 
         for (int i = 0; i < num_children; i++)
           {
-            graphics_object childObj (gh_manager::get_object (children(i)));
+            graphics_object childObj (gh_mgr.get_object (children(i)));
 
             if (childObj.isa ("axes"))
               {
@@ -1012,8 +1037,11 @@
   {
     if (m_eventMask & KeyPress)
       {
-        gh_manager::auto_lock lock;
-        graphics_object obj = gh_manager::get_object (m_handle);
+        gh_manager& gh_mgr = octave::__get_gh_manager__ ("Canvas::canvasKeyPressEvent");
+
+        octave::autolock guard (gh_mgr.graphics_lock ());
+
+        graphics_object obj = gh_mgr.get_object (m_handle);
 
         if (obj.valid_object ())
           {
@@ -1040,8 +1068,11 @@
   {
     if (! event->isAutoRepeat () && (m_eventMask & KeyRelease))
       {
-        gh_manager::auto_lock lock;
-        graphics_object obj = gh_manager::get_object (m_handle);
+        gh_manager& gh_mgr = octave::__get_gh_manager__ ("Canvas::canvasKeyReleaseEvent");
+
+        octave::autolock guard (gh_mgr.graphics_lock ());
+
+        graphics_object obj = gh_mgr.get_object (m_handle);
 
         if (obj.valid_object ())
           {
--- a/libgui/graphics/Container.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/graphics/Container.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -27,13 +27,14 @@
 #include <QChildEvent>
 #include <QVBoxLayout>
 
-#include "graphics.h"
-
 #include "Canvas.h"
 #include "Container.h"
 #include "Object.h"
 #include "QtHandlesUtils.h"
 
+#include "graphics.h"
+#include "interpreter-private.h"
+
 namespace QtHandles
 {
 
@@ -51,8 +52,11 @@
   {
     if (! m_canvas && xcreate)
       {
-        gh_manager::auto_lock lock;
-        graphics_object go = gh_manager::get_object (gh);
+        gh_manager& gh_mgr = octave::__get_gh_manager__ ("Container::canvas");
+
+        octave::autolock guard (gh_mgr.graphics_lock ());
+
+        graphics_object go = gh_mgr.get_object (gh);
 
         if (go)
           {
@@ -127,7 +131,9 @@
     if (m_canvas)
       m_canvas->qWidget ()->setGeometry (0, 0, width (), height ());
 
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Container::resizeEvent");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     foreach (QObject *qObj, children ())
       {
--- a/libgui/graphics/ContextMenu.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/graphics/ContextMenu.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -30,6 +30,8 @@
 #include "QtHandlesUtils.h"
 #include "qt-graphics-toolkit.h"
 
+#include "interpreter-private.h"
+
 namespace QtHandles
 {
 
@@ -116,8 +118,10 @@
 
     if (h.ok ())
       {
-        gh_manager::auto_lock lock;
-        graphics_object go = gh_manager::get_object (h);
+        gh_manager& gh_mgr = octave::__get_gh_manager__ ("ContextMenu::executeAt");
+        octave::autolock guard (gh_mgr.graphics_lock ());
+
+        graphics_object go = gh_mgr.get_object (h);
 
         if (go.valid_object ())
           {
--- a/libgui/graphics/Figure.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/graphics/Figure.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -56,6 +56,8 @@
 #include "utils.h"
 #include "version.h"
 
+#include "interpreter-private.h"
+
 #include "qt-interpreter-events.h"
 
 #include "builtin-defun-decls.h"
@@ -189,7 +191,9 @@
   QString
   Figure::fileName (void)
   {
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Figure::fileName");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     const figure::properties& fp = properties<figure> ();
 
@@ -201,7 +205,9 @@
   void
   Figure::setFileName (const QString& name)
   {
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Figure::setFileName");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     figure::properties& fp = properties<figure> ();
 
@@ -211,7 +217,9 @@
   MouseMode
   Figure::mouseMode (void)
   {
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Figure::mouseMode");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     const figure::properties& fp = properties<figure> ();
 
@@ -321,8 +329,10 @@
 
     if (canvas)
       {
-        gh_manager::process_events ();
-        gh_manager::auto_lock lock;
+        gh_manager& gh_mgr = octave::__get_gh_manager__ ("Figure::slotGetPixels");
+
+        gh_mgr.process_events ();
+        octave::autolock guard (gh_mgr.graphics_lock ());
         retval = canvas->getPixels ();
       }
 
@@ -393,7 +403,9 @@
             QTimer::singleShot (0, win, SLOT (show ()));
             if (! fp.is___gl_window__ ())
               {
-                gh_manager::auto_lock lock;
+                gh_manager& gh_mgr = octave::__get_gh_manager__ ("Figure::update");
+
+                octave::autolock guard (gh_mgr.graphics_lock ());
                 fp.set ("__gl_window__", "on");
               }
           }
@@ -548,7 +560,9 @@
   void
   Figure::updateFigureHeight (int dh)
   {
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Figure::updateFigureHeight");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
     graphics_object go = object ();
 
     if (go.valid_object () && dh != 0)
@@ -647,7 +661,11 @@
         if (xevent->type () == QEvent::MouseButtonPress)
           {
             figure::properties& fp = properties<figure> ();
-            graphics_object root = gh_manager::get_object (0);
+
+            gh_manager& gh_mgr = octave::__get_gh_manager__ ("Figure::eventNotifyBefore");
+
+            graphics_object root = gh_mgr.get_object (0);
+
             if (fp.get_handlevisibility () == "on")
               root.set ("currentfigure",
                         fp.get___myhandle__ ().as_octave_value ());
@@ -695,6 +713,8 @@
       {
         if (watched == m_container)
           {
+            gh_manager& gh_mgr = octave::__get_gh_manager__ ("Figure::eventNotifyAfter");
+
             switch (xevent->type ())
               {
               case QEvent::Resize:
@@ -705,7 +725,7 @@
                 if (dynamic_cast<QChildEvent *> (xevent)->child
                     ()->isWidgetType())
                   {
-                    gh_manager::auto_lock lock;
+                    octave::autolock guard (gh_mgr.graphics_lock ());
                     update (figure::properties::ID_TOOLBAR);
 
                     enableMouseTracking ();
@@ -716,7 +736,7 @@
                 if (dynamic_cast<QChildEvent *> (xevent)->child
                     ()->isWidgetType())
                   {
-                    gh_manager::auto_lock lock;
+                    octave::autolock guard (gh_mgr.graphics_lock ());
                     update (figure::properties::ID_TOOLBAR);
                   }
                 break;
@@ -830,7 +850,9 @@
     QWindow* window = qWidget<QMainWindow> ()->windowHandle ();
     QScreen* screen = window->screen ();
 
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Figure::figureWindowShown");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     figure::properties& fp = properties<figure> ();
     fp.set___device_pixel_ratio__ (screen->devicePixelRatio ());
@@ -844,7 +866,9 @@
   Figure::screenChanged (QScreen* screen)
   {
 #if defined (HAVE_QSCREEN_DEVICEPIXELRATIO)
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Figure::screenChanged");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     figure::properties& fp = properties<figure> ();
     double old_dpr = fp.get___device_pixel_ratio__ ();
--- a/libgui/graphics/GLCanvas.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/graphics/GLCanvas.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -68,8 +68,11 @@
   void
   GLCanvas::draw (const graphics_handle& gh)
   {
-    gh_manager::auto_lock lock;
-    graphics_object go = gh_manager::get_object (gh);
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("GLCanvas::draw");
+
+    octave::autolock guard  (gh_mgr.graphics_lock ());
+
+    graphics_object go = gh_mgr.get_object (gh);
 
     if (go)
       {
@@ -85,7 +88,10 @@
   GLCanvas::do_getPixels (const graphics_handle& gh)
   {
     uint8NDArray retval;
-    graphics_object go = gh_manager::get_object (gh);
+
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("GLCanvas::do_getPixels");
+
+    graphics_object go = gh_mgr.get_object (gh);
 
     if (go && go.isa ("figure"))
       {
@@ -135,8 +141,11 @@
   GLCanvas::do_print (const QString& file_cmd, const QString& term,
                       const graphics_handle& handle)
   {
-    gh_manager::auto_lock lock;
-    graphics_object go = gh_manager::get_object (handle);
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("GLCanvas::do_print");
+
+    octave::autolock guard  (gh_mgr.graphics_lock ());
+
+    graphics_object go = gh_mgr.get_object (handle);
 
     if (go.valid_object ())
       {
--- a/libgui/graphics/Object.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/graphics/Object.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -31,15 +31,20 @@
 #include "QtHandlesUtils.h"
 #include "qt-graphics-toolkit.h"
 
+#include "graphics.h"
+#include "interpreter-private.h"
+
 namespace QtHandles
 {
 
   Object::Object (const graphics_object& go, QObject *obj)
     : QObject (), m_go (go), m_handle (go.get_handle ()), m_qobject (nullptr)
   {
-    gh_manager::auto_lock lock (false);
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Object::Object");
 
-    if (! lock)
+    octave::autolock guard (gh_mgr.graphics_lock ());
+
+    if (! guard)
       qCritical ("QtHandles::Object::Object: "
                  "creating Object (h=%g) without a valid lock!!!",
                  m_handle.value ());
@@ -71,9 +76,11 @@
   graphics_object
   Object::object (void) const
   {
-    gh_manager::auto_lock lock (false);
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Object::object");
 
-    if (! lock)
+    octave::autolock guard (gh_mgr.graphics_lock (), false);
+
+    if (! guard)
       qCritical ("QtHandles::Object::object: "
                  "accessing graphics object (h=%g) without a valid lock!!!",
                  m_handle.value ());
@@ -84,7 +91,9 @@
   void
   Object::slotUpdate (int pId)
   {
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Object::slotUpdate");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     switch (pId)
       {
@@ -105,7 +114,9 @@
   void
   Object::slotFinalize (void)
   {
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Object::slotFinalize");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     finalize ();
   }
@@ -113,7 +124,9 @@
   void
   Object::slotRedraw (void)
   {
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Object::slotRedraw");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     if (object ().valid_object ())
       redraw ();
@@ -122,7 +135,9 @@
   void
   Object::slotShow (void)
   {
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Object::slotShow");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     if (object ().valid_object ())
       show ();
@@ -131,7 +146,9 @@
   void
   Object::slotPrint (const QString& file_cmd, const QString& term)
   {
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Object::slotPrint");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     if (object ().valid_object ())
       print (file_cmd, term);
@@ -177,10 +194,12 @@
   Object*
   Object::parentObject (const graphics_object& go)
   {
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Object::parentObject");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     Object *parent = qt_graphics_toolkit::toolkitObject
-                     (gh_manager::get_object (go.get_parent ()));
+                     (gh_mgr.get_object (go.get_parent ()));
 
     return parent;
   }
--- a/libgui/graphics/Panel.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/graphics/Panel.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -36,6 +36,9 @@
 #include "Panel.h"
 #include "QtHandlesUtils.h"
 
+#include "graphics.h"
+#include "interpreter-private.h"
+
 namespace QtHandles
 {
 
@@ -166,13 +169,16 @@
   {
     if (! m_blockUpdates)
       {
+        gh_manager& gh_mgr = octave::__get_gh_manager__ ("Panel::eventFilter");
+
         if (watched == qObject ())
           {
             switch (xevent->type ())
               {
               case QEvent::Resize:
                 {
-                  gh_manager::auto_lock lock;
+                  octave::autolock guard (gh_mgr.graphics_lock ());
+
                   graphics_object go = object ();
 
                   if (go.valid_object ())
@@ -202,7 +208,7 @@
 
                   if (m->button () == Qt::RightButton)
                     {
-                      gh_manager::auto_lock lock;
+                      octave::autolock guard (gh_mgr.graphics_lock ());
 
                       graphics_object go = object ();
 
@@ -224,7 +230,7 @@
               case QEvent::Resize:
                 if (qWidget<QWidget> ()->isVisible ())
                   {
-                    gh_manager::auto_lock lock;
+                    octave::autolock guard (gh_mgr.graphics_lock ());
 
                     graphics_object go = object ();
 
--- a/libgui/graphics/QtHandlesUtils.h	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/graphics/QtHandlesUtils.h	Fri Aug 09 10:36:08 2019 -0400
@@ -32,6 +32,7 @@
 #include <string>
 
 #include "graphics.h"
+#include "interpreter-private.h"
 
 class QKeyEvent;
 class QMouseEvent;
@@ -73,7 +74,11 @@
     template <typename T>
     inline typename T::properties&
     properties (const graphics_handle& h)
-    { return Utils::properties<T> (gh_manager::get_object (h)); }
+    {
+      gh_manager& gh_mgr = octave::__get_gh_manager__ ("Utils::properties");
+
+      return Utils::properties<T> (gh_mgr.get_object (h));
+    }
 
     QImage makeImageFromCData (const octave_value& v, int width = -1,
                                int height = -1);
--- a/libgui/graphics/SliderControl.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/graphics/SliderControl.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -30,6 +30,9 @@
 #include "SliderControl.h"
 #include "QtHandlesUtils.h"
 
+#include "graphics.h"
+#include "interpreter-private.h"
+
 #define RANGE_INT_MAX 1000000
 
 namespace QtHandles
@@ -128,7 +131,10 @@
   {
     if (! m_blockUpdates)
       {
-        gh_manager::auto_lock lock;
+        gh_manager& gh_mgr = octave::__get_gh_manager__ ("SliderControl::valueChanged");
+
+        octave::autolock guard (gh_mgr.graphics_lock ());
+
         graphics_object go = object ();
 
         if (go.valid_object ())
--- a/libgui/graphics/Table.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/graphics/Table.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -46,6 +46,8 @@
 #include "Table.h"
 #include "QtHandlesUtils.h"
 
+#include "graphics.h"
+#include "interpreter-private.h"
 #include "oct-stream.h"
 #include "oct-string.h"
 #include "oct-strstrm.h"
@@ -560,7 +562,11 @@
       return;
 
     m_blockUpdates = true;
-    gh_manager::auto_lock lock;
+
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Table::comboBoxCurrentIndexChanged");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
+
     octave_value data = octave_value (m_curData);
     bool ok = false;
 
@@ -676,7 +682,10 @@
     if (m_blockUpdates)
       return;
     m_blockUpdates = true;
-    gh_manager::auto_lock lock;
+
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Table::checkBoxClicked");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
 
     bool new_value = ! checkBox->isChecked ();
 
@@ -789,7 +798,11 @@
     if (m_blockUpdates)
       return;
     m_blockUpdates = true;
-    gh_manager::auto_lock lock;
+
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Table::itemChanged");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
+
     octave_value data = octave_value (m_curData);
 
     int row = item->row ();
@@ -1497,6 +1510,8 @@
   bool
   Table::eventFilter (QObject *watched, QEvent *xevent)
   {
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("Table::eventFilter");
+
     //uitable::properties& tp = properties<uitable> ();
     if (qobject_cast<QTableWidget *> (watched))
       {
@@ -1504,7 +1519,8 @@
           {
           case QEvent::Resize:
             {
-              gh_manager::auto_lock lock;
+              octave::autolock guard (gh_mgr.graphics_lock ());
+
               graphics_object go = object ();
               if (go.valid_object ())
                 {
@@ -1518,7 +1534,8 @@
 
           case QEvent::MouseButtonPress:
             {
-              gh_manager::auto_lock lock;
+              octave::autolock guard (gh_mgr.graphics_lock ());
+
               QMouseEvent *m = dynamic_cast<QMouseEvent *> (xevent);
               graphics_object go = object ();
               const uitable::properties& tp =
@@ -1552,7 +1569,7 @@
               QKeyEvent *k = dynamic_cast<QKeyEvent *> (xevent);
               if (m_keyPressHandlerDefined)
                 {
-                  gh_manager::auto_lock lock;
+                  octave::autolock guard (gh_mgr.graphics_lock ());
 
                   octave_scalar_map keyData = Utils::makeKeyEventStruct (k);
                   graphics_object fig = object ().get_ancestor ("figure");
@@ -1636,7 +1653,8 @@
             {
               if (m_keyReleaseHandlerDefined)
                 {
-                  gh_manager::auto_lock lock;
+                  octave::autolock guard (gh_mgr.graphics_lock ());
+
                   QKeyEvent *k = dynamic_cast<QKeyEvent *> (xevent);
 
                   octave_scalar_map keyData = Utils::makeKeyEventStruct (k);
@@ -1659,7 +1677,8 @@
           {
           case QEvent::MouseButtonPress:
             {
-              gh_manager::auto_lock lock;
+              octave::autolock guard (gh_mgr.graphics_lock ());
+
               QMouseEvent *m = dynamic_cast<QMouseEvent *> (xevent);
               graphics_object go = object ();
               const uitable::properties& tp = Utils::properties<uitable> (go);
--- a/libgui/graphics/__init_qt__.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/graphics/__init_qt__.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -56,13 +56,15 @@
       {
         if (qApp)
           {
-            gh_manager::auto_lock lock;
+            gh_manager& gh_mgr = interp.get_gh_manager ();
+
+            octave::autolock guard (gh_mgr.graphics_lock ());
 
             interp.mlock ();
 
             qRegisterMetaType<graphics_object> ("graphics_object");
 
-            gh_manager::enable_event_processing (true);
+            gh_mgr.enable_event_processing (true);
 
             octave::gtk_manager& gtk_mgr = interp.get_gtk_manager ();
 
@@ -90,13 +92,15 @@
   }
 
   bool
-  __shutdown__ (void)
+  __shutdown__ (octave::interpreter& interp)
   {
     if (qtHandlesInitialized)
       {
-        gh_manager::auto_lock lock;
+        gh_manager& gh_mgr = interp.get_gh_manager ();
 
-        gh_manager::enable_event_processing (false);
+        octave::autolock guard (gh_mgr.graphics_lock ());
+
+        gh_mgr.enable_event_processing (false);
 
         qtHandlesInitialized = false;
 
@@ -114,9 +118,9 @@
   return octave_value ();
 }
 
-DEFUN_DLD (__shutdown_qt__, , , "")
+DEFMETHOD_DLD (__shutdown_qt__, interp, , , "")
 {
-  QtHandles::__shutdown__ ();
+  QtHandles::__shutdown__ (interp);
 
   return octave_value ();
 }
--- a/libgui/graphics/qt-graphics-toolkit.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/graphics/qt-graphics-toolkit.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -122,7 +122,10 @@
         // FIXME: We need to unlock the mutex here but we have no way to know if
         // if it was previously locked by this thread, and thus if we should
         // re-lock it.
-        gh_manager::unlock ();
+
+        gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
+
+        gh_mgr.unlock ();
 
         Logger::debug ("qt_graphics_toolkit::initialize %s from thread %08x",
                        go.type ().c_str (), QThread::currentThreadId ());
@@ -185,7 +188,10 @@
     // FIXME: We need to unlock the mutex here but we have no way to know if
     // if it was previously locked by this thread, and thus if we should
     // re-lock it.
-    gh_manager::unlock ();
+
+    gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
+
+    gh_mgr.unlock ();
 
     Logger::debug ("qt_graphics_toolkit::finalize %s from thread %08x",
                    go.type ().c_str (), QThread::currentThreadId ());
@@ -354,9 +360,11 @@
   void
   qt_graphics_toolkit::create_object (double handle)
   {
-    gh_manager::auto_lock lock;
+    gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
 
-    graphics_object go (gh_manager::get_object (graphics_handle (handle)));
+    octave::autolock guard (gh_mgr.graphics_lock ());
+
+    graphics_object go (gh_mgr.get_object (graphics_handle (handle)));
 
     if (go.valid_object ())
       {
@@ -498,21 +506,27 @@
   void qt_graphics_toolkit::gh_callback_event (const graphics_handle& h,
                                                const std::string& nm)
   {
-    gh_manager::post_callback (h, nm);
+    gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
+
+    gh_mgr.post_callback (h, nm);
   }
 
   void qt_graphics_toolkit::gh_callback_event (const graphics_handle& h,
                                                const std::string& nm,
                                                const octave_value& data)
   {
-    gh_manager::post_callback (h, nm, data);
+    gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
+
+    gh_mgr.post_callback (h, nm, data);
   }
 
   void qt_graphics_toolkit::gh_set_event (const graphics_handle& h,
                                           const std::string& nm,
                                           const octave_value& value)
   {
-    gh_manager::post_set (h, nm, value);
+    gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
+
+    gh_mgr.post_set (h, nm, value);
   }
 
   void qt_graphics_toolkit::gh_set_event (const graphics_handle& h,
@@ -520,7 +534,9 @@
                                           const octave_value& value,
                                           bool notify_toolkit)
   {
-    gh_manager::post_set (h, nm, value, notify_toolkit);
+    gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
+
+    gh_mgr.post_set (h, nm, value, notify_toolkit);
   }
 
   void qt_graphics_toolkit::gh_set_event (const graphics_handle& h,
@@ -529,6 +545,8 @@
                                           bool notify_toolkit,
                                           bool redraw_figure)
   {
-    gh_manager::post_set (h, nm, value, notify_toolkit, redraw_figure);
+    gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
+
+    gh_mgr.post_set (h, nm, value, notify_toolkit, redraw_figure);
   }
 };
--- a/libgui/src/main-window.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libgui/src/main-window.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -1090,7 +1090,7 @@
          // INTERPRETER THREAD
 
          Fbuiltin (interp, ovl ("figure"));
-         Fdrawnow ();
+         Fdrawnow (interp);
        });
   }
 
--- a/libinterp/corefcn/gl-render.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libinterp/corefcn/gl-render.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -37,6 +37,7 @@
 
 #include "errwarn.h"
 #include "gl-render.h"
+#include "interpreter-private.h"
 #include "oct-opengl.h"
 #include "text-renderer.h"
 
@@ -1529,6 +1530,9 @@
   {
 #if defined (HAVE_OPENGL)
 
+    gh_manager& gh_mgr
+      = __get_gh_manager__ ("opengl_renderer::draw_axes_x_grid");
+
     int xstate = props.get_xstate ();
 
     if (xstate != AXE_DEPTH_DIR
@@ -1701,10 +1705,10 @@
                                 zpTick, 0, halign, valign, wmax, hmax);
           }
 
-        gh_manager::get_object (props.get_xlabel ()).set ("visible", "on");
+        gh_mgr.get_object (props.get_xlabel ()).set ("visible", "on");
       }
     else
-      gh_manager::get_object (props.get_xlabel ()).set ("visible", "off");
+      gh_mgr.get_object (props.get_xlabel ()).set ("visible", "off");
 
 #else
 
@@ -1723,6 +1727,9 @@
   {
 #if defined (HAVE_OPENGL)
 
+    gh_manager& gh_mgr
+      = __get_gh_manager__ ("opengl_renderer::draw_axes_y_grid");
+
     int ystate = props.get_ystate ();
 
     if (ystate != AXE_DEPTH_DIR && props.is_visible ()
@@ -1896,10 +1903,10 @@
                                 zpTick, 1, halign, valign, wmax, hmax);
           }
 
-        gh_manager::get_object (props.get_ylabel ()).set ("visible", "on");
+        gh_mgr.get_object (props.get_ylabel ()).set ("visible", "on");
       }
     else
-      gh_manager::get_object (props.get_ylabel ()).set ("visible", "off");
+      gh_mgr.get_object (props.get_ylabel ()).set ("visible", "off");
 
 #else
 
@@ -1916,6 +1923,9 @@
   void
   opengl_renderer::draw_axes_z_grid (const axes::properties& props)
   {
+    gh_manager& gh_mgr
+      = __get_gh_manager__ ("opengl_renderer::draw_axes_z_grid");
+
     int zstate = props.get_zstate ();
 
     if (zstate != AXE_DEPTH_DIR && props.is_visible ()
@@ -2090,10 +2100,10 @@
               }
           }
 
-        gh_manager::get_object (props.get_zlabel ()).set ("visible", "on");
+        gh_mgr.get_object (props.get_zlabel ()).set ("visible", "on");
       }
     else
-      gh_manager::get_object (props.get_zlabel ()).set ("visible", "off");
+      gh_mgr.get_object (props.get_zlabel ()).set ("visible", "off");
   }
 
   void
@@ -2136,11 +2146,14 @@
                                     std::list<graphics_object>& obj_list)
   {
 #if defined (HAVE_OPENGL)
+    gh_manager& gh_mgr
+      = __get_gh_manager__ ("opengl_renderer::draw_axes_all_lights");
+
     Matrix children = props.get_all_children ();
 
     for (octave_idx_type i = children.numel () - 1; i >= 0; i--)
       {
-        graphics_object go = gh_manager::get_object (children(i));
+        graphics_object go = gh_mgr.get_object (children(i));
 
         base_properties p = go.get_properties ();
 
@@ -3950,6 +3963,21 @@
 #endif
   }
 
+  void opengl_renderer::draw (const Matrix& hlist, bool toplevel)
+  {
+    int len = hlist.numel ();
+
+    gh_manager& gh_mgr = __get_gh_manager__ ("opengl_renderer::draw");
+
+    for (int i = len-1; i >= 0; i--)
+      {
+        graphics_object obj = gh_mgr.get_object (hlist(i));
+
+        if (obj)
+          draw (obj, toplevel);
+      }
+  }
+
   void
   opengl_renderer::set_viewport (int w, int h)
   {
@@ -4067,12 +4095,14 @@
   opengl_renderer::set_linewidth (float w)
   {
 #if defined (HAVE_OPENGL)
+    gh_manager& gh_mgr = __get_gh_manager__ ("opengl_renderer::set_linewidth");
+
     // FIXME: See bug #53056 (measure LineWidth in points).
     //        pts2pix and m_devpixratio should eventually be combined in to a
     //        a single conversion factor so that only one multiplication per
     //        function call is required.
     const static double pts2pix
-      = (gh_manager::get_object (0).get ("screenpixelsperinch").double_value ()
+      = (gh_mgr.get_object (0).get ("screenpixelsperinch").double_value ()
          / 72.0);
 
     m_glfcns.glLineWidth (w * pts2pix * m_devpixratio);
@@ -4094,10 +4124,11 @@
                                   double linewidth)
   {
 #if defined (HAVE_OPENGL)
+    gh_manager& gh_mgr = __get_gh_manager__ ("opengl_renderer::set_linestyle");
 
     // FIXME: See bug #53056 (measure LineWidth in points).
     const static double pts2pix
-      = (gh_manager::get_object (0).get ("screenpixelsperinch").double_value ()
+      = (gh_mgr.get_object (0).get ("screenpixelsperinch").double_value ()
          / 72.0);
     int factor = math::round (linewidth * pts2pix * m_devpixratio);
     if (factor < 1)
@@ -4437,11 +4468,14 @@
     if (filled && (c == '+' || c == 'x' || c == '*' || c == '.'))
       return 0;
 
+    gh_manager& gh_mgr
+      = __get_gh_manager__ ("opengl_renderer::make_marker_list");
+
     unsigned int ID = m_glfcns.glGenLists (1);
 
     // FIXME: See bug #53056 (measure LineWidth in points).
     const static double pts2pix
-      = (gh_manager::get_object (0).get ("screenpixelsperinch").double_value ()
+      = (gh_mgr.get_object (0).get ("screenpixelsperinch").double_value ()
          / 72.0);
 
     double sz = size * pts2pix;
--- a/libinterp/corefcn/gl-render.h	Wed Aug 07 12:57:25 2019 -0700
+++ b/libinterp/corefcn/gl-render.h	Fri Aug 09 10:36:08 2019 -0400
@@ -55,18 +55,7 @@
     // The following version of the draw method is not declared virtual
     // because no derived class overrides it.
 
-    void draw (const Matrix& hlist, bool toplevel = false)
-    {
-      int len = hlist.numel ();
-
-      for (int i = len-1; i >= 0; i--)
-        {
-          graphics_object obj = gh_manager::get_object (hlist(i));
-
-          if (obj)
-            draw (obj, toplevel);
-        }
-    }
+    void draw (const Matrix& hlist, bool toplevel = false);
 
     virtual void set_viewport (int w, int h);
     virtual void set_device_pixel_ratio (double dpr) { m_devpixratio = dpr; }
--- a/libinterp/corefcn/gl2ps-print.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libinterp/corefcn/gl2ps-print.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -44,6 +44,7 @@
 #include "unwind-prot.h"
 
 #include "gl-render.h"
+#include "interpreter-private.h"
 #include "oct-opengl.h"
 #include "sighandlers.h"
 #include "sysdep.h"
@@ -99,7 +100,10 @@
     static bool has_alpha (const graphics_handle& h)
     {
       bool retval = false;
-      graphics_object go = gh_manager::get_object (h);
+
+      gh_manager& gh_mgr = __get_gh_manager__ ("gl2ps_renderer::has_alpha");
+
+      graphics_object go = gh_mgr.get_object (h);
 
       if (! go.valid_object ())
         return retval;
@@ -288,7 +292,10 @@
   has_2D_axes (const graphics_handle& h)
   {
     bool retval = true;
-    graphics_object go = gh_manager::get_object (h);
+
+    gh_manager& gh_mgr = __get_gh_manager__ ("gl2ps_renderer::has_2D_axes");
+
+    graphics_object go = gh_mgr.get_object (h);
 
     if (! go.valid_object ())
       return retval;
--- a/libinterp/corefcn/graphics-toolkit.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libinterp/corefcn/graphics-toolkit.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -26,11 +26,15 @@
 
 #include "graphics.h"
 #include "gtk-manager.h"
+#include "interpreter-private.h"
 
 void
 base_graphics_toolkit::update (const graphics_handle& h, int id)
 {
-  graphics_object go = gh_manager::get_object (h);
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_graphics_toolkit::update");
+
+  graphics_object go = gh_mgr.get_object (h);
 
   update (go, id);
 }
@@ -38,7 +42,10 @@
 bool
 base_graphics_toolkit::initialize (const graphics_handle& h)
 {
-  graphics_object go = gh_manager::get_object (h);
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_graphics_toolkit::initialize");
+
+  graphics_object go = gh_mgr.get_object (h);
 
   return initialize (go);
 }
--- a/libinterp/corefcn/graphics.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libinterp/corefcn/graphics.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -613,6 +613,19 @@
   return retval;
 }
 
+static graphics_handle
+make_graphics_handle (const std::string& go_name,
+                      const graphics_handle& parent,
+                      bool integer_figure_handle = false,
+                      bool call_createfcn = true,
+                      bool notify_toolkit = true)
+{
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("make_graphics_handle");
+
+  return gh_mgr.make_graphics_handle (go_name, parent, integer_figure_handle,
+                                      call_createfcn, notify_toolkit);
+}
+
 static double
 convert_font_size (double font_size, const caseless_str& from_units,
                    const caseless_str& to_units, double parent_height = 0)
@@ -821,7 +834,10 @@
                        const caseless_str& from_units,
                        const caseless_str& to_units)
 {
-  graphics_object go = gh_manager::get_object (props.get___myhandle__ ());
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("convert_text_position");
+
+  graphics_object go = gh_mgr.get_object (props.get___myhandle__ ());
+
   graphics_object ax = go.get_ancestor ("axes");
 
   Matrix retval;
@@ -908,8 +924,12 @@
 static Matrix
 screen_size_pixels (void)
 {
-  graphics_object obj = gh_manager::get_object (0);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("scren_size_pixels");
+
+  graphics_object obj = gh_mgr.get_object (0);
+
   Matrix sz = obj.get ("screensize").matrix_value ();
+
   return convert_position (sz, obj.get ("units").string_value (), "pixels",
                            sz.extract_n (0, 2, 1, 2)).extract_n (0, 2, 1, 2);
 }
@@ -919,7 +939,9 @@
 {
   double retval = 1.0;
 
-  graphics_object fig = gh_manager::get_object (h).get_ancestor ("figure");
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("device_pixel_ratio");
+
+  graphics_object fig = gh_mgr.get_object (h).get_ancestor ("figure");
 
   if (fig.valid_object ())
     retval = fig.get ("__device_pixel_ratio__").double_value ();
@@ -982,7 +1004,9 @@
   Matrix cmap (1, 3, 0.0);
   Matrix clim (1, 2, 0.0);
 
-  graphics_object go = gh_manager::get_object (props.get___myhandle__ ());
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("convert_cdata");
+
+  graphics_object go = gh_mgr.get_object (props.get___myhandle__ ());
   graphics_object ax = go.get_ancestor ("axes");
 
   if (ax.valid_object ())
@@ -1233,7 +1257,10 @@
       // Notify graphics toolkit.
       if (id >= 0 && do_notify_toolkit)
         {
-          graphics_object go = gh_manager::get_object (parent);
+          gh_manager& gh_mgr
+            = octave::__get_gh_manager__ ("base_property::set");
+
+          graphics_object go = gh_mgr.get_object (parent);
           if (go)
             go.update (id);
         }
@@ -1253,8 +1280,11 @@
 {
   const octave_value_list& l = listeners[mode];
 
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_property::run_listeners");
+
   for (int i = 0; i < l.length (); i++)
-    gh_manager::execute_listener (parent, l(i));
+    gh_mgr.execute_listener (parent, l(i));
 }
 
 radio_values::radio_values (const std::string& opt_string)
@@ -1711,14 +1741,16 @@
   double dv = v.xdouble_value (R"(set: invalid graphics handle for property "%s")",
                                get_name ().c_str ());
 
-  graphics_handle gh = gh_manager::lookup (dv);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("handle_property::do_set");
+
+  graphics_handle gh = gh_mgr.lookup (dv);
 
   // Check the object type if necessary
   bool type_ok = true;
   if (gh.ok () && ! type_constraints.empty ())
     {
       type_ok = false;
-      graphics_object obj = gh_manager::get_object (gh);
+      graphics_object obj = gh_mgr.get_object (gh);
 
       for (const auto& type : type_constraints)
         if (obj.isa (type))
@@ -1771,7 +1803,10 @@
   Matrix retval (children_list.size (), 1);
   octave_idx_type k = 0;
 
-  graphics_object go = gh_manager::get_object (0);
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("children_property::do_get_children");
+
+  graphics_object go = gh_mgr.get_object (0);
 
   root_figure::properties& props
     = dynamic_cast<root_figure::properties&> (go.get_properties ());
@@ -1782,7 +1817,7 @@
         {
           graphics_handle kid = hchild;
 
-          if (gh_manager::is_handle_visible (kid))
+          if (gh_mgr.is_handle_visible (kid))
             {
               if (! return_hidden)
                 retval(k++) = hchild;
@@ -1805,26 +1840,29 @@
 void
 children_property::do_delete_children (bool clear, bool from_root)
 {
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("children_property::do_delete_children");
+
   if (from_root)
     {
       for (graphics_handle hchild : children_list)
         {
-          graphics_object go = gh_manager::get_object (hchild);
+          graphics_object go = gh_mgr.get_object (hchild);
           if (go.valid_object ()
               && ! go.get_properties ().is_beingdeleted ())
-            gh_manager::free (hchild, from_root);
+            gh_mgr.free (hchild, from_root);
         }
       children_list.clear ();
     }
   else
     while (! children_list.empty ())
       {
-        // gh_manager::free removes hchild from children_list
+        // gh_mgr.free removes hchild from children_list
         graphics_handle hchild = children_list.front ();
-        graphics_object go = gh_manager::get_object (hchild);
+        graphics_object go = gh_mgr.get_object (hchild);
         if (go.valid_object ()
             && ! go.get_properties ().is_beingdeleted ())
-          gh_manager::free (hchild, from_root);
+          gh_mgr.free (hchild, from_root);
       }
 
   // FIXME: children_list should be clear anyway at this point.
@@ -1910,7 +1948,12 @@
       executing_callbacks.insert (this);
 
       if (callback.is_defined () && ! callback.isempty ())
-        gh_manager::execute_callback (get_parent (), callback, data);
+        {
+          gh_manager& gh_mgr
+            = octave::__get_gh_manager__ ("callback_property::execute");
+
+          gh_mgr.execute_callback (get_parent (), callback, data);
+        }
     }
 }
 
@@ -2045,7 +2088,9 @@
 static void
 finalize_r (const graphics_handle& h)
 {
-  graphics_object go = gh_manager::get_object (h);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("finalize_r");
+
+  graphics_object go = gh_mgr.get_object (h);
 
   if (go)
     {
@@ -2061,7 +2106,9 @@
 static void
 initialize_r (const graphics_handle& h)
 {
-  graphics_object go = gh_manager::get_object (h);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("initialize_r");
+
+  graphics_object go = gh_mgr.get_object (h);
 
   if (go)
     {
@@ -2153,17 +2200,23 @@
 {
   if (! is_handle_visible ())
     {
-      octave_value cf = gh_manager::get_object (0).get ("currentfigure");
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("figure::properties::update_handlevisibility");
+
+      octave_value cf = gh_mgr.get_object (0).get ("currentfigure");
+
       if (! cf.isempty () && cf.double_value () == __myhandle__)
         {
-          gh_manager::auto_lock guard;
-          octave_value kids =  gh_manager::get_object (0).get ("children");
+          octave::autolock guard (gh_mgr.graphics_lock ());
+
+          octave_value kids =  gh_mgr.get_object (0).get ("children");
+
           if (kids.isempty ())
-            gh_manager::get_object (0).set ("currentfigure", Matrix ());
+            gh_mgr.get_object (0).set ("currentfigure", Matrix ());
           else
             {
               NDArray kidsarray = kids.array_value ();
-              gh_manager::get_object (0).set ("currentfigure", kidsarray(0));
+              gh_mgr.get_object (0).set ("currentfigure", kidsarray(0));
             }
         }
     }
@@ -2174,7 +2227,10 @@
 static void
 update_text_pos (graphics_handle h)
 {
-  graphics_object go = gh_manager::get_object (h);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("update_text_pos");
+
+  graphics_object go = gh_mgr.get_object (h);
+
   if (go.isa ("text"))
     {
       text::properties& tp
@@ -2729,7 +2785,7 @@
 }
 
 graphics_handle
-gh_manager::do_get_handle (bool integer_figure_handle)
+gh_manager::get_handle (bool integer_figure_handle)
 {
   graphics_handle retval;
 
@@ -2772,13 +2828,15 @@
 static bool
 isfigure (double val)
 {
-  graphics_object go = gh_manager::get_object (val);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("isfigure");
+
+  graphics_object go = gh_mgr.get_object (val);
 
   return go && go.isa ("figure");
 }
 
 void
-gh_manager::do_free (const graphics_handle& h, bool from_root)
+gh_manager::free (const graphics_handle& h, bool from_root)
 {
   if (h.ok ())
     {
@@ -2798,7 +2856,7 @@
       graphics_handle parent_h = p->second.get_parent ();
       graphics_object parent_go = nullptr;
       if (! from_root || isfigure (h.value ()))
-        parent_go = gh_manager::get_object (parent_h);
+        parent_go = get_object (parent_h);
 
       bp.set_beingdeleted (true);
 
@@ -2841,8 +2899,8 @@
 }
 
 void
-gh_manager::do_renumber_figure (const graphics_handle& old_gh,
-                                const graphics_handle& new_gh)
+gh_manager::renumber_figure (const graphics_handle& old_gh,
+                             const graphics_handle& new_gh)
 {
   auto p = m_handle_map.find (old_gh);
 
@@ -2873,7 +2931,10 @@
 xset (const graphics_handle& h, const caseless_str& pname,
       const octave_value& val)
 {
-  graphics_object go = gh_manager::get_object (h);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("xset");
+
+  graphics_object go = gh_mgr.get_object (h);
+
   go.set (pname, val);
 }
 
@@ -2882,7 +2943,10 @@
 {
   if (args.length () > 0)
     {
-      graphics_object go = gh_manager::get_object (h);
+      gh_manager& gh_mgr = octave::__get_gh_manager__ ("xset");
+
+      graphics_object go = gh_mgr.get_object (h);
+
       go.set (args);
     }
 }
@@ -2890,7 +2954,10 @@
 static octave_value
 xget (const graphics_handle& h, const caseless_str& pname)
 {
-  graphics_object go = gh_manager::get_object (h);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("xget");
+
+  graphics_object go = gh_mgr.get_object (h);
+
   return go.get (pname);
 }
 
@@ -2902,17 +2969,19 @@
   double hv = ov.xdouble_value ("%s: %s must be a graphics handle",
                                 who.c_str (), pname.c_str ());
 
-  graphics_handle h = gh_manager::lookup (hv);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("reparent");
+
+  graphics_handle h = gh_mgr.lookup (hv);
 
   if (! h.ok ())
     error ("%s: invalid graphics handle (= %g) for %s",
            who.c_str (), hv, pname.c_str ());
 
-  graphics_object go = gh_manager::get_object (h);
+  graphics_object go = gh_mgr.get_object (h);
 
   graphics_handle parent_h = go.get_parent ();
 
-  graphics_object parent_go = gh_manager::get_object (parent_h);
+  graphics_object parent_go = gh_mgr.get_object (parent_h);
 
   parent_go.remove_child (h);
 
@@ -2949,7 +3018,10 @@
 {
   if (h.ok ())
     {
-      graphics_object go = gh_manager::get_object (h);
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("delete_graphics_object");
+
+      graphics_object go = gh_mgr.get_object (h);
 
       // Don't do recursive deleting, due to callbacks
       if (! go.get_properties ().is_beingdeleted ())
@@ -2957,7 +3029,7 @@
           // NOTE: Freeing the handle also calls any deletefcn.  It also calls
           //       the parent's delete_child function.
 
-          gh_manager::free (h, from_root || go.isa ("figure"));
+          gh_mgr.free (h, from_root || go.isa ("figure"));
 
           Vdrawnow_requested = true;
         }
@@ -2967,7 +3039,9 @@
 static void
 delete_graphics_object (double val, bool from_root = false)
 {
-  delete_graphics_object (gh_manager::lookup (val), from_root || isfigure (val));
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("delete_graphics_object");
+
+  delete_graphics_object (gh_mgr.lookup (val), from_root || isfigure (val));
 }
 
 // Flag to stop redraws due to callbacks while deletion is in progress.
@@ -2990,7 +3064,9 @@
 {
   octave_value closerequestfcn = xget (h, "closerequestfcn");
 
-  gh_manager::execute_callback (h, closerequestfcn);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("close_figure");
+
+  gh_mgr.execute_callback (h, closerequestfcn);
 }
 
 static void
@@ -3006,7 +3082,7 @@
 }
 
 void
-gh_manager::do_close_all_figures (void)
+gh_manager::close_all_figures (void)
 {
   // FIXME: should we process or discard pending events?
 
@@ -3015,11 +3091,11 @@
   // Don't use m_figure_list_iterator because we'll be removing elements
   // from the list elsewhere.
 
-  Matrix hlist = do_figure_handle_list (true);
+  Matrix hlist = figure_handle_list (true);
 
   for (octave_idx_type i = 0; i < hlist.numel (); i++)
     {
-      graphics_handle h = gh_manager::lookup (hlist(i));
+      graphics_handle h = lookup (hlist(i));
 
       if (h.ok ())
         close_figure (h);
@@ -3027,11 +3103,11 @@
 
   // They should all be closed now.  If not, force them to close.
 
-  hlist = do_figure_handle_list (true);
+  hlist = figure_handle_list (true);
 
   for (octave_idx_type i = 0; i < hlist.numel (); i++)
     {
-      graphics_handle h = gh_manager::lookup (hlist(i));
+      graphics_handle h = lookup (hlist(i));
 
       if (h.ok ())
         force_close_figure (h);
@@ -3039,10 +3115,10 @@
 
   // None left now, right?
 
-  hlist = do_figure_handle_list (true);
+  hlist = figure_handle_list (true);
 
   if (hlist.numel () != 0)
-    warning ("gh_manager::do_close_all_figures: some graphics elements failed to close.");
+    warning ("gh_manager::close_all_figures: some graphics elements failed to close.");
 
   // Clear all callback objects from our list.
 
@@ -3052,7 +3128,10 @@
 static void
 adopt (const graphics_handle& parent_h, const graphics_handle& h)
 {
-  graphics_object parent_go = gh_manager::get_object (parent_h);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("adopt");
+
+  graphics_object parent_go = gh_mgr.get_object (parent_h);
+
   parent_go.adopt (h);
 }
 
@@ -3065,7 +3144,9 @@
 static bool
 ishghandle (double val)
 {
-  graphics_handle h = gh_manager::lookup (val);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("ishghandle");
+
+  graphics_handle h = gh_mgr.lookup (val);
 
   return h.ok ();
 }
@@ -3095,14 +3176,19 @@
 static void
 xcreatefcn (const graphics_handle& h)
 {
-  graphics_object go = gh_manager::get_object (h);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("xcreatefcn");
+
+  graphics_object go = gh_mgr.get_object (h);
+
   go.get_properties ().execute_createfcn  ();
 }
 
 static void
 xinitialize (const graphics_handle& h)
 {
-  graphics_object go = gh_manager::get_object (h);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("xinitialize");
+
+  graphics_object go = gh_mgr.get_object (h);
 
   if (go)
     go.initialize ();
@@ -3113,7 +3199,10 @@
 void
 base_graphics_toolkit::finalize (const graphics_handle& h)
 {
-  graphics_object go = gh_manager::get_object (h);
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_graphics_toolkit::finalize");
+
+  graphics_object go = gh_mgr.get_object (h);
 
   finalize (go);
 }
@@ -3140,7 +3229,10 @@
 xreset_default_properties (graphics_handle h,
                            property_list::pval_map_type factory_pval)
 {
-  graphics_object go = gh_manager::get_object (h);
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("xreset_default_properties");
+
+  graphics_object go = gh_mgr.get_object (h);
 
   // Replace factory defaults by user defined ones
   std::string go_name = go.get_properties ().graphics_object_name ();
@@ -3301,13 +3393,16 @@
   if (hp == __myhandle__)
     error ("set: can not set object parent to be object itself");
 
-  graphics_handle new_parent = gh_manager::lookup (hp);
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_properties::set_parent");
+
+  graphics_handle new_parent = gh_mgr.lookup (hp);
   if (! new_parent.ok ())
     error ("set: invalid graphics handle (= %g) for parent", hp);
 
   // Remove child from current parent
   graphics_object old_parent_go;
-  old_parent_go = gh_manager::get_object (get_parent ());
+  old_parent_go = gh_mgr.get_object (get_parent ());
 
   if (old_parent_go.get_handle () != hp)
     old_parent_go.remove_child (__myhandle__);
@@ -3316,7 +3411,7 @@
 
   // Check new parent's parent is not this child to avoid recursion
   graphics_object new_parent_go;
-  new_parent_go = gh_manager::get_object (new_parent);
+  new_parent_go = gh_mgr.get_object (new_parent);
   if (new_parent_go.get_parent () == __myhandle__)
     {
       // new parent's parent gets child's original parent
@@ -3345,8 +3440,14 @@
 {
   // Mark existing object as modified
   __modified__ = "on";
+
   // Attempt to mark parent object as modified if it exists
-  graphics_object parent_go = gh_manager::get_object (get_parent ());
+
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_properties::mark_modified");
+
+  graphics_object parent_go = gh_mgr.get_object (get_parent ());
+
   if (parent_go)
     parent_go.mark_modified ();
 }
@@ -3354,7 +3455,10 @@
 void
 base_properties::override_defaults (base_graphics_object& obj)
 {
-  graphics_object parent_go = gh_manager::get_object (get_parent ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_properties::override_defaults");
+
+  graphics_object parent_go = gh_mgr.get_object (get_parent ());
 
   if (parent_go)
     parent_go.override_defaults (obj);
@@ -3363,7 +3467,10 @@
 void
 base_properties::update_axis_limits (const std::string& axis_type) const
 {
-  graphics_object go = gh_manager::get_object (__myhandle__);
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_properties::update_axis_limits");
+
+  graphics_object go = gh_mgr.get_object (__myhandle__);
 
   if (go)
     go.update_axis_limits (axis_type);
@@ -3373,7 +3480,10 @@
 base_properties::update_axis_limits (const std::string& axis_type,
                                      const graphics_handle& h) const
 {
-  graphics_object go = gh_manager::get_object (__myhandle__);
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_properties::update_axis_limits");
+
+  graphics_object go = gh_mgr.get_object (__myhandle__);
 
   if (go)
     go.update_axis_limits (axis_type, h);
@@ -3385,7 +3495,11 @@
   if (uicontextmenu.get ().isempty ())
     return;
 
-  graphics_object go = gh_manager::get_object (uicontextmenu.get ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_properties::update_uicontextmenu");
+
+  graphics_object go = gh_mgr.get_object (uicontextmenu.get ());
+
   if (go && go.isa ("uicontextmenu"))
     {
       uicontextmenu::properties& props
@@ -3404,7 +3518,10 @@
 graphics_toolkit
 base_properties::get_toolkit (void) const
 {
-  graphics_object go = gh_manager::get_object (get_parent ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_properties::get_toolkit");
+
+  graphics_object go = gh_mgr.get_object (get_parent ());
 
   if (go)
     return go.get_toolkit ();
@@ -3417,9 +3534,12 @@
 {
   Matrix kids = get_children ();
 
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_properties::update_boundingbox");
+
   for (int i = 0; i < kids.numel (); i++)
     {
-      graphics_object go = gh_manager::get_object (kids(i));
+      graphics_object go = gh_mgr.get_object (kids(i));
 
       if (go.valid_object ())
         go.get_properties ().update_boundingbox ();
@@ -3429,7 +3549,10 @@
 void
 base_properties::update_autopos (const std::string& elem_type)
 {
-  graphics_object parent_go = gh_manager::get_object (get_parent ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_properties::update_autopos");
+
+  graphics_object parent_go = gh_mgr.get_object (get_parent ());
 
   if (parent_go.valid_object ())
     parent_go.get_properties ().update_autopos (elem_type);
@@ -3442,14 +3565,21 @@
     return;
 
   // This object should not be the figure "currentobject"
-  graphics_object go (gh_manager::get_object (get___myhandle__ ()));
+
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_properties::update_handlevisibility");
+
+  graphics_object go (gh_mgr.get_object (get___myhandle__ ()));
+
   graphics_object fig (go.get_ancestor ("figure"));
+
   if (fig.valid_object ())
     {
       octave_value co = fig.get ("currentobject");
       if (! co.isempty () && co.double_value () == __myhandle__)
         {
-          gh_manager::auto_lock guard;
+          octave::autolock guard (gh_mgr.graphics_lock ());
+
           auto& fig_props = dynamic_cast<figure::properties&> (fig.get_properties ());
           fig_props.set_currentobject (Matrix ());
         }
@@ -3522,14 +3652,18 @@
                                        bool traverse,
                                        std::list<graphics_object> &children_list) const
 {
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_properties::get_children_of_type");
+
   Matrix ch = get_children ();
+
   for (octave_idx_type i = 0; i < ch.numel (); i++)
     {
-      graphics_handle hkid = gh_manager::lookup (ch(i));
+      graphics_handle hkid = gh_mgr.lookup (ch(i));
 
       if (hkid.ok ())
         {
-          graphics_object go = gh_manager::get_object (hkid);
+          graphics_object go = gh_mgr.get_object (hkid);
           if ( get_invisible || go.get_properties ().is_visible () )
             {
               if (go.isa (chtype))
@@ -3552,7 +3686,10 @@
   if (! valid_object ())
     error ("base_graphics_object::update_axis_limits: invalid graphics object");
 
-  graphics_object parent_go = gh_manager::get_object (get_parent ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_graphics_object::update_axis_limits");
+
+  graphics_object parent_go = gh_mgr.get_object (get_parent ());
 
   if (parent_go)
     parent_go.update_axis_limits (axis_type);
@@ -3565,7 +3702,10 @@
   if (! valid_object ())
     error ("base_graphics_object::update_axis_limits: invalid graphics object");
 
-  graphics_object parent_go = gh_manager::get_object (get_parent ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_graphics_object::update_axis_limits");
+
+  graphics_object parent_go = gh_mgr.get_object (get_parent ());
 
   if (parent_go)
     parent_go.update_axis_limits (axis_type, h);
@@ -3619,7 +3759,10 @@
         }
     }
 
-  graphics_object parent_go = gh_manager::get_object (get_parent ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_graphics_object::build_user_defaults_map");
+
+  graphics_object parent_go = gh_mgr.get_object (get_parent ());
 
   if (parent_go)
     parent_go.build_user_defaults_map (def, go_name);
@@ -3630,8 +3773,11 @@
 {
   if (valid_object ())
     {
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("base_graphics_object::reset_default_properties");
+
       property_list::pval_map_type factory_pval
-        = gh_manager::get_object (0).get_factory_defaults_list ().find (type ())->second;
+        = gh_mgr.get_object (0).get_factory_defaults_list ().find (type ())->second;
 
       remove_all_listeners ();
       xreset_default_properties (get_handle (), factory_pval);
@@ -3646,7 +3792,11 @@
 
   std::string retval;
   octave_map m = get ().map_value ();
-  graphics_object go = gh_manager::get_object (get_handle ());
+
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_graphics_object::values_as_string");
+
+  graphics_object go = gh_mgr.get_object (get_handle ());
 
   for (const auto& pm : m)
     {
@@ -3678,7 +3828,10 @@
   if (! valid_object ())
     error ("base_graphics_object::value_as_string: invalid graphics object");
 
-  graphics_object go = gh_manager::get_object (get_handle ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_graphics_object::value_as_string");
+
+  graphics_object go = gh_mgr.get_object (get_handle ());
 
   if (prop != "children" && ! go.has_readonly_property (prop))
     {
@@ -3706,7 +3859,11 @@
     error ("base_graphics_object::values_as_struct: invalid graphics object");
 
   octave_scalar_map m = get ().scalar_map_value ();
-  graphics_object go = gh_manager::get_object (get_handle ());
+
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_graphics_object::values_as_struct");
+
+  graphics_object go = gh_mgr.get_object (get_handle ());
 
   for (const auto& pm : m)
     {
@@ -3756,7 +3913,12 @@
       if (isa (obj_type))
         return *this;
       else
-        return gh_manager::get_object (get_parent ()).get_ancestor (obj_type);
+        {
+          gh_manager& gh_mgr
+            = octave::__get_gh_manager__ ("graphics_object::get_ancestor");
+
+          return gh_mgr.get_object (get_parent ()).get_ancestor (obj_type);
+        }
     }
   else
     return graphics_object ();
@@ -3791,7 +3953,12 @@
       currentfigure = val;
 
       if (val.ok ())
-        gh_manager::push_figure (val);
+        {
+          gh_manager& gh_mgr
+            = octave::__get_gh_manager__ ("root_figure::properties::set_currentfigure");
+
+          gh_mgr.push_figure (val);
+        }
     }
   else
     err_set_invalid ("currentfigure");
@@ -3804,15 +3971,18 @@
     {
       bool int_fig_handle = integerhandle.is_on ();
 
-      graphics_object this_go = gh_manager::get_object (__myhandle__);
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("figure::properties::set_integerhandle");
+
+      graphics_object this_go = gh_mgr.get_object (__myhandle__);
 
       graphics_handle old_myhandle = __myhandle__;
 
-      __myhandle__ = gh_manager::get_handle (int_fig_handle);
-
-      gh_manager::renumber_figure (old_myhandle, __myhandle__);
-
-      graphics_object parent_go = gh_manager::get_object (get_parent ());
+      __myhandle__ = gh_mgr.get_handle (int_fig_handle);
+
+      gh_mgr.renumber_figure (old_myhandle, __myhandle__);
+
+      graphics_object parent_go = gh_mgr.get_object (get_parent ());
 
       base_properties& props = parent_go.get_properties ();
 
@@ -3822,12 +3992,12 @@
 
       for (octave_idx_type i = 0; i < kids.numel (); i++)
         {
-          graphics_object kid = gh_manager::get_object (kids(i));
+          graphics_object kid = gh_mgr.get_object (kids(i));
 
           kid.get_properties ().renumber_parent (__myhandle__);
         }
 
-      graphics_handle cf = gh_manager::current_figure ();
+      graphics_handle cf = gh_mgr.current_figure ();
 
       if (__myhandle__ == cf)
         xset (0, "currentfigure", __myhandle__.value ());
@@ -3933,9 +4103,12 @@
 void
 root_figure::properties::remove_child (const graphics_handle& h, bool)
 {
-  gh_manager::pop_figure (h);
-
-  graphics_handle cf = gh_manager::current_figure ();
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("root_figure::properties::remove_child");
+
+  gh_mgr.pop_figure (h);
+
+  graphics_handle cf = gh_mgr.current_figure ();
 
   xset (0, "currentfigure", cf.value ());
 
@@ -3977,11 +4150,14 @@
 
       Matrix kids = get_children ();
 
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("root_figure::properties::remove_child");
+
       for (octave_idx_type i = 0; i < kids.numel (); i++)
         {
           graphics_handle kid = kids(i);
 
-          graphics_object go = gh_manager::get_object (kid);
+          graphics_object go = gh_mgr.get_object (kid);
 
           if (go.isa ("axes"))
             {
@@ -4047,7 +4223,10 @@
 
   if (! get_currentaxes ().ok ())
     {
-      graphics_object go = gh_manager::get_object (h);
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("figure::properties::adopt");
+
+      graphics_object go = gh_mgr.get_object (h);
 
       if (go.type () == "axes")
         set_currentaxes (h.as_octave_value ());
@@ -4175,11 +4354,14 @@
     {
       if (old_bb(2) != new_bb(2) || old_bb(3) != new_bb(3))
         {
+          gh_manager& gh_mgr
+            = octave::__get_gh_manager__ ("figure::properties::set_position");
+
           if (! get_resizefcn ().isempty ())
-            gh_manager::post_callback (__myhandle__, "resizefcn");
+            gh_mgr.post_callback (__myhandle__, "resizefcn");
 
           if (! get_sizechangedfcn ().isempty ())
-            gh_manager::post_callback (__myhandle__, "sizechangedfcn");
+            gh_mgr.post_callback (__myhandle__, "sizechangedfcn");
 
           update_boundingbox ();
         }
@@ -4864,7 +5046,10 @@
   if (retval.is_undefined ())
     {
       graphics_handle parent_h = get_parent ();
-      graphics_object parent_go = gh_manager::get_object (parent_h);
+
+      gh_manager& gh_mgr = octave::__get_gh_manager__ ("figure::get_default");
+
+      graphics_object parent_go = gh_mgr.get_object (parent_h);
 
       retval = parent_go.get_default (name);
     }
@@ -5053,7 +5238,12 @@
 axes::properties::calc_tightbox (const Matrix& init_pos)
 {
   Matrix pos = init_pos;
-  graphics_object go = gh_manager::get_object (get_parent ());
+
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("axes::properties::calc_tightbox");
+
+  graphics_object go = gh_mgr.get_object (get_parent ());
+
   Matrix parent_bb = go.get_properties ().get_boundingbox (true);
 
   // FIXME: The layout should be clean at this stage and we should not have to
@@ -5187,7 +5377,11 @@
     }
 
   graphics_handle val;
-  graphics_object go = gh_manager::get_object (gh_manager::lookup (v));
+
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("axes::properties::set_text_child");
+
+  graphics_object go = gh_mgr.get_object (gh_mgr.lookup (v));
 
   if (go.isa ("text"))
     val = ::reparent (v, "set", who, __myhandle__, false);
@@ -5201,7 +5395,7 @@
 
   xset (val, "handlevisibility", "off");
 
-  gh_manager::free (hp.handle_value ());
+  gh_mgr.free (hp.handle_value ());
 
   hp = val;
 
@@ -5413,13 +5607,16 @@
 
   visible = "on";
 
-  graphics_object go = gh_manager::get_object (xlabel.handle_value ());
-  go.reset_default_properties ();
-  go = gh_manager::get_object (ylabel.handle_value ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("axes::properties::set_defaults");
+
+  graphics_object go = gh_mgr.get_object (xlabel.handle_value ());
   go.reset_default_properties ();
-  go = gh_manager::get_object (zlabel.handle_value ());
+  go = gh_mgr.get_object (ylabel.handle_value ());
   go.reset_default_properties ();
-  go = gh_manager::get_object (title.handle_value ());
+  go = gh_mgr.get_object (zlabel.handle_value ());
+  go.reset_default_properties ();
+  go = gh_mgr.get_object (title.handle_value ());
   go.reset_default_properties ();
 
   xset (xlabel.handle_value (), "handlevisibility", "off");
@@ -5477,7 +5674,10 @@
 {
   if (__colormap__.get ().isempty ())
     {
-      graphics_object go (gh_manager::get_object (get___myhandle__ ()));
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("axes::properties::get_colormap");
+
+      graphics_object go (gh_mgr.get_object (get___myhandle__ ()));
       graphics_object go_f (go.get_ancestor ("figure"));
       figure::properties& figure_props
         = reinterpret_cast<figure::properties&> (go_f.get_properties ());
@@ -5492,12 +5692,15 @@
 {
   graphics_handle h = hp.handle_value ();
 
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("axes::properties::delete_text_child");
+
   if (h.ok ())
     {
-      graphics_object go = gh_manager::get_object (h);
+      graphics_object go = gh_mgr.get_object (h);
 
       if (go.valid_object ())
-        gh_manager::free (h, from_root);
+        gh_mgr.free (h, from_root);
     }
 
   // FIXME: is it necessary to check whether the axes object is
@@ -5507,7 +5710,7 @@
 
   if (! is_beingdeleted ())
     {
-      hp = gh_manager::make_graphics_handle ("text", __myhandle__,
+      hp = gh_mgr.make_graphics_handle ("text", __myhandle__,
                                              false, false);
 
       xset (hp.handle_value (), "handlevisibility", "off");
@@ -5519,7 +5722,10 @@
 void
 axes::properties::remove_child (const graphics_handle& h, bool from_root)
 {
-  graphics_object go = gh_manager::get_object (h);
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("axes::properties::remove_child");
+
+  graphics_object go = gh_mgr.get_object (h);
 
   if (xlabel.handle_value ().ok () && h == xlabel.handle_value ())
     {
@@ -5553,7 +5759,9 @@
 void
 axes::properties::adopt (const graphics_handle& h)
 {
-  graphics_object go (gh_manager::get_object (h));
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("axes::properties::adopt");
+
+  graphics_object go (gh_mgr.get_object (h));
 
   if (go.isa ("light") && go.get_properties ().is_visible ())
     increase_num_lights ();
@@ -6223,7 +6431,10 @@
   if (updating_xlabel_position)
     return;
 
-  graphics_object go = gh_manager::get_object (get_xlabel ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("axes::properties::update_xlabel_position");
+
+  graphics_object go = gh_mgr.get_object (get_xlabel ());
 
   if (! go.valid_object ())
     return;
@@ -6325,7 +6536,10 @@
   if (updating_ylabel_position)
     return;
 
-  graphics_object go = gh_manager::get_object (get_ylabel ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("axes::properties::update_ylabel_position");
+
+  graphics_object go = gh_mgr.get_object (get_ylabel ());
 
   if (! go.valid_object ())
     return;
@@ -6427,7 +6641,10 @@
   if (updating_zlabel_position)
     return;
 
-  graphics_object go = gh_manager::get_object (get_zlabel ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("axes::properties::update_zlabel_position");
+
+  graphics_object go = gh_mgr.get_object (get_zlabel ());
 
   if (! go.valid_object ())
     return;
@@ -6552,7 +6769,10 @@
   if (updating_title_position)
     return;
 
-  graphics_object go = gh_manager::get_object (get_title ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("axes::properties::update_title_position");
+
+  graphics_object go = gh_mgr.get_object (get_title ());
 
   if (! go.valid_object ())
     return;
@@ -6763,12 +6983,18 @@
 axes::properties::update_label_color (handle_property label,
                                       color_property col)
 {
-  gh_manager::get_object (label.handle_value ()).set ("color", col.get ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("axes::properties::update_label_color");
+
+  gh_mgr.get_object (label.handle_value ()).set ("color", col.get ());
 }
 
 void
 axes::properties::update_font (std::string prop)
 {
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("axes::properties::update_font");
+
   if (! prop.empty ())
     {
       octave_value val = get (prop);
@@ -6783,15 +7009,16 @@
       else if (prop == "fontweight")
         tval = get ("titlefontweight");
 
-      gh_manager::get_object (get_xlabel ()).set (prop, val);
-      gh_manager::get_object (get_ylabel ()).set (prop, val);
-      gh_manager::get_object (get_zlabel ()).set (prop, val);
-      gh_manager::get_object (get_title ()).set (prop, tval);
+      gh_mgr.get_object (get_xlabel ()).set (prop, val);
+      gh_mgr.get_object (get_ylabel ()).set (prop, val);
+      gh_mgr.get_object (get_zlabel ()).set (prop, val);
+      gh_mgr.get_object (get_title ()).set (prop, tval);
     }
 
   double dpr = device_pixel_ratio (get___myhandle__ ());
 
-  gh_manager::auto_lock guard;
+  octave::autolock guard (gh_mgr.graphics_lock ());
+
   txt_renderer.set_font (get ("fontname").string_value (),
                          get ("fontweight").string_value (),
                          get ("fontangle").string_value (),
@@ -6810,7 +7037,10 @@
 
   if (parent_size.isempty ())
     {
-      graphics_object go = gh_manager::get_object (get_parent ());
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("axes::properties::get_boundingbox");
+
+      graphics_object go = gh_mgr.get_object (get_parent ());
 
       if (go.valid_object ())
         parent_size
@@ -6863,9 +7093,12 @@
           else if (i == 3)
             htext = get_zlabel ();
 
+          gh_manager& gh_mgr
+            = octave::__get_gh_manager__ ("axes::properties::get_extent");
+
           text::properties& text_props
             = reinterpret_cast<text::properties&>
-                (gh_manager::get_object (htext).get_properties ());
+                (gh_mgr.get_object (htext).get_properties ());
 
           Matrix text_pos = text_props.get_data_position ();
           text_pos = xform.transform (text_pos(0), text_pos(1), text_pos(2));
@@ -7079,9 +7312,14 @@
 void
 axes::properties::update_units (const caseless_str& old_units)
 {
-  graphics_object parent_go = gh_manager::get_object (get_parent ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("axes::properties::update_units");
+
+  graphics_object parent_go = gh_mgr.get_object (get_parent ());
+
   Matrix parent_bb
     = parent_go.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);
+
   caseless_str new_units = get_units ();
   position.set (octave_value (convert_position (get_position ().matrix_value (),
                                                 old_units, new_units,
@@ -7186,7 +7424,11 @@
   if (retval.is_undefined ())
     {
       graphics_handle parent_h = get_parent ();
-      graphics_object parent_go = gh_manager::get_object (parent_h);
+
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("axes::properties::get_default");
+
+      graphics_object parent_go = gh_mgr.get_object (parent_h);
 
       retval = parent_go.get_default (pname);
     }
@@ -8091,7 +8333,11 @@
 
           if (txt_renderer.ok ())
             {
-              gh_manager::auto_lock guard;
+              gh_manager& gh_mgr
+                = octave::__get_gh_manager__ ("axes::properties::get_ticklabel_extents");
+
+              octave::autolock guard (gh_mgr.graphics_lock ());
+
               ext = txt_renderer.get_extent (label, 0.0,
                                              get_ticklabelinterpreter ());
 
@@ -8122,12 +8368,14 @@
 {
   octave_idx_type n = kids.numel ();
 
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("get_children_limits");
+
   switch (limit_type)
     {
     case 'x':
       for (octave_idx_type i = 0; i < n; i++)
         {
-          graphics_object go = gh_manager::get_object (kids(i));
+          graphics_object go = gh_mgr.get_object (kids(i));
 
           if (go.is_xliminclude ())
             {
@@ -8141,7 +8389,7 @@
     case 'y':
       for (octave_idx_type i = 0; i < n; i++)
         {
-          graphics_object go = gh_manager::get_object (kids(i));
+          graphics_object go = gh_mgr.get_object (kids(i));
 
           if (go.is_yliminclude ())
             {
@@ -8155,7 +8403,7 @@
     case 'z':
       for (octave_idx_type i = 0; i < n; i++)
         {
-          graphics_object go = gh_manager::get_object (kids(i));
+          graphics_object go = gh_mgr.get_object (kids(i));
 
           if (go.is_zliminclude ())
             {
@@ -8169,7 +8417,7 @@
     case 'c':
       for (octave_idx_type i = 0; i < n; i++)
         {
-          graphics_object go = gh_manager::get_object (kids(i));
+          graphics_object go = gh_mgr.get_object (kids(i));
 
           if (go.is_climinclude ())
             {
@@ -8183,7 +8431,7 @@
     case 'a':
       for (octave_idx_type i = 0; i < n; i++)
         {
-          graphics_object go = gh_manager::get_object (kids(i));
+          graphics_object go = gh_mgr.get_object (kids(i));
 
           if (go.is_aliminclude ())
             {
@@ -8982,12 +9230,17 @@
 {
   if (! is_handle_visible ())
     {
-      graphics_object go (gh_manager::get_object (get___myhandle__ ()));
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("axes::properties::update_handlevisibility");
+
+      graphics_object go (gh_mgr.get_object (get___myhandle__ ()));
+
       graphics_object fig (go.get_ancestor ("figure"));
       octave_value ca = fig.get ("currentaxes");
       if (! ca.isempty () && ca.double_value () == __myhandle__)
         {
-          gh_manager::auto_lock guard;
+          octave::autolock guard (gh_mgr.graphics_lock ());
+
           octave_value kids =  fig.get ("children");
           if (kids.isempty ())
             fig.set ("currentaxes", Matrix ());
@@ -9163,7 +9416,11 @@
 
   if (new_units == "normalized" || old_units == "normalized")
     {
-      graphics_object go (gh_manager::get_object (get___myhandle__ ()));
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("text::properties::update_fontunits");
+
+      graphics_object go (gh_mgr.get_object (get___myhandle__ ()));
+
       graphics_object ax (go.get_ancestor ("axes"));
 
       parent_height = ax.get_properties ().get_boundingbox (true).elem (3);
@@ -9179,7 +9436,11 @@
 {
   double dpr = device_pixel_ratio (get___myhandle__ ());
 
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("text::properties::update_font");
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
+
   txt_renderer.set_font (get ("fontname").string_value (),
                          get ("fontweight").string_value (),
                          get ("fontangle").string_value (),
@@ -9221,7 +9482,11 @@
 
   string_vector sv = string_prop.string_vector_value ();
 
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("text::properties::update_text_extent");
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
+
   txt_renderer.text_to_pixels (sv.join ("\n"), pixels, bbox,
                                halign, valign, get_rotation (),
                                get_interpreter ());
@@ -9285,7 +9550,11 @@
   double fontsz = get_fontsize ();
   double parent_height = box_pix_height;
 
-  graphics_object go (gh_manager::get_object (get___myhandle__ ()));
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("text::properties::get___fontsize_points__");
+
+  graphics_object go (gh_mgr.get_object (get___myhandle__ ()));
+
   if (fontunits_is ("normalized") && parent_height <= 0)
     {
       graphics_object ax (go.get_ancestor ("axes"));
@@ -9320,7 +9589,11 @@
 void
 light::properties::update_visible (void)
 {
-  graphics_object go = gh_manager::get_object (get___myhandle__ ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("light::properties::update_visible");
+
+  graphics_object go = gh_mgr.get_object (get___myhandle__ ());
+
   axes::properties& ax_props = dynamic_cast<axes::properties&>
     (go.get_ancestor ("axes").get_properties ());
   if (is_visible ())
@@ -9334,7 +9607,11 @@
 bool
 patch::properties::get_do_lighting (void) const
 {
-  graphics_object go = gh_manager::get_object (get___myhandle__ ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("patch::properties::get_do_lighting");
+
+  graphics_object go = gh_mgr.get_object (get___myhandle__ ());
+
   axes::properties& ax_props = dynamic_cast<axes::properties&>
     (go.get_ancestor ("axes").get_properties ());
 
@@ -9938,7 +10215,11 @@
 bool
 surface::properties::get_do_lighting (void) const
 {
-  graphics_object go = gh_manager::get_object (get___myhandle__ ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("surface::properties::get_do_lighting");
+
+  graphics_object go = gh_mgr.get_object (get___myhandle__ ());
+
   axes::properties& ax_prop = dynamic_cast<axes::properties&>
     (go.get_ancestor ("axes").get_properties ());
 
@@ -10155,22 +10436,24 @@
     vertexnormals = Matrix ();
 }
 
-DEFUN (__update_normals__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__update_normals__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __update_normals__ (@var{h})
 Update FaceNormals and VertexNormals of the patch or surface referred to by
 @var{h}.
 
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   if (args.length () != 1)
     print_usage ();
 
   octave_value val = args(0);
 
-  graphics_object go = gh_manager::get_object (val);
+  graphics_object go = gh_mgr.get_object (val);
 
   if (go.isa ("surface"))
     {
@@ -10225,7 +10508,11 @@
 void
 hggroup::properties::remove_child (const graphics_handle& h, bool from_root)
 {
-  graphics_object go = gh_manager::get_object (h);
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("hggroup::properties::remove_child");
+
+  graphics_object go = gh_mgr.get_object (h);
+
   if (! from_root && go.isa ("light") && go.get_properties ().is_visible ())
     {
       axes::properties& ax_props
@@ -10239,7 +10526,11 @@
 void
 hggroup::properties::adopt (const graphics_handle& h)
 {
-  graphics_object go = gh_manager::get_object (h);
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("hggroup::properties::adopt");
+
+  graphics_object go = gh_mgr.get_object (h);
+
   if (go.isa ("light") && go.get_properties ().is_visible ())
     {
       axes::properties& ax_props
@@ -10253,7 +10544,10 @@
 void
 hggroup::properties::update_limits (void) const
 {
-  graphics_object go = gh_manager::get_object (__myhandle__);
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("hggroup::properties::update_limits");
+
+  graphics_object go = gh_mgr.get_object (__myhandle__);
 
   if (go)
     {
@@ -10268,7 +10562,10 @@
 void
 hggroup::properties::update_limits (const graphics_handle& h) const
 {
-  graphics_object go = gh_manager::get_object (__myhandle__);
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("hggroup::properties::update_limits");
+
+  graphics_object go = gh_mgr.get_object (__myhandle__);
 
   if (go)
     {
@@ -10491,9 +10788,12 @@
   std::list<graphics_handle> lst = xproperties.get_dependent_obj_list ();
   std::list<graphics_handle>::const_iterator it;
 
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("uicontextmenu::~uicontextmenu");
+
   for (it = lst.begin (); it != lst.end (); it++)
     {
-      graphics_object go = gh_manager::get_object (*it);
+      graphics_object go = gh_mgr.get_object (*it);
 
       if (go.valid_object ()
           && go.get ("uicontextmenu") == xproperties.get___myhandle__ ())
@@ -10535,7 +10835,11 @@
 {
   Matrix m = extent.get ().matrix_value ();
 
-  graphics_object parent_go = gh_manager::get_object (get_parent ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("uicontrol::properties::get_extent");
+
+  graphics_object parent_go = gh_mgr.get_object (get_parent ());
+
   Matrix parent_bbox = parent_go.get_properties ().get_boundingbox (true);
   Matrix parent_size = parent_bbox.extract_n (0, 2, 1, 2);
 
@@ -10546,7 +10850,11 @@
 uicontrol::properties::update_text_extent (void)
 {
   // FIXME: support multiline text
-  graphics_object go = gh_manager::get_object (get___myhandle__ ());
+
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("uicontrol::properties::update_text_extent");
+
+  graphics_object go = gh_mgr.get_object (get___myhandle__ ());
 
   set_extent (go.get_toolkit ().get_text_extent (go));
 }
@@ -10556,7 +10864,11 @@
 {
   Matrix pos = get_position ().matrix_value ();
 
-  graphics_object parent_go = gh_manager::get_object (get_parent ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("uicontrol::properties::update_units");
+
+  graphics_object parent_go = gh_mgr.get_object (get_parent ());
+
   Matrix parent_bbox = parent_go.get_properties ().get_boundingbox (true);
   Matrix parent_size = parent_bbox.extract_n (0, 2, 1, 2);
 
@@ -10583,7 +10895,12 @@
         }
 
       // Notify toolkit
-      graphics_object go = gh_manager::get_object (get___myhandle__ ());
+
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("uicontrol::properties::set_style");
+
+      graphics_object go = gh_mgr.get_object (get___myhandle__ ());
+
       if (go)
         go.update (style.get_id ());
     }
@@ -10598,7 +10915,10 @@
 
   if (parent_size.isempty ())
     {
-      graphics_object go = gh_manager::get_object (get_parent ());
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("uicontrol::properties::get_boundingbox");
+
+      graphics_object go = gh_mgr.get_object (get_parent ());
 
       if (go.valid_object ())
         parent_size = go.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);
@@ -10662,7 +10982,10 @@
 
   if (parent_size.isempty ())
     {
-      graphics_object go = gh_manager::get_object (get_parent ());
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("uibuttongroup::properties::get_boundingbox");
+
+      graphics_object go = gh_mgr.get_object (get_parent ());
 
       parent_size = go.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);
     }
@@ -10735,11 +11058,14 @@
     {
       if (old_bb(2) != new_bb(2) || old_bb(3) != new_bb(3))
         {
+          gh_manager& gh_mgr
+            = octave::__get_gh_manager__ ("uibuttongroup::properties::set_position");
+
           if (! get_resizefcn ().isempty ())
-            gh_manager::post_callback (__myhandle__, "resizefcn");
+            gh_mgr.post_callback (__myhandle__, "resizefcn");
 
           if (! get_sizechangedfcn ().isempty ())
-            gh_manager::post_callback (__myhandle__, "sizechangedfcn");
+            gh_mgr.post_callback (__myhandle__, "sizechangedfcn");
 
           update_boundingbox ();
         }
@@ -10769,7 +11095,11 @@
 {
   Matrix pos = get_position ().matrix_value ();
 
-  graphics_object parent_go = gh_manager::get_object (get_parent ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("uibuttongroup::properties::update_units");
+
+  graphics_object parent_go = gh_mgr.get_object (get_parent ());
+
   Matrix parent_bbox = parent_go.get_properties ().get_boundingbox (true);
   Matrix parent_size = parent_bbox.extract_n (0, 2, 1, 2);
 
@@ -10831,7 +11161,11 @@
   graphics_handle val (v);
   if (val.ok ())
     {
-      graphics_object go (gh_manager::get_object (val));
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("uibuttongroup::properties::set_selectedobject");
+
+      graphics_object go (gh_mgr.get_object (val));
+
       base_properties& gop = go.get_properties ();
 
       if (go.valid_object ()
@@ -10863,7 +11197,10 @@
 
   if (parent_size.isempty ())
     {
-      graphics_object go = gh_manager::get_object (get_parent ());
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("uipanel::properties::get_boundingbox");
+
+      graphics_object go = gh_mgr.get_object (get_parent ());
 
       parent_size = go.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);
     }
@@ -10936,11 +11273,14 @@
     {
       if (old_bb(2) != new_bb(2) || old_bb(3) != new_bb(3))
         {
+          gh_manager& gh_mgr
+            = octave::__get_gh_manager__ ("uipanel::properties::set_position");
+
           if (! get_resizefcn ().isempty ())
-            gh_manager::post_callback (__myhandle__, "resizefcn");
+            gh_mgr.post_callback (__myhandle__, "resizefcn");
 
           if (! get_sizechangedfcn ().isempty ())
-            gh_manager::post_callback (__myhandle__, "sizechangedfcn");
+            gh_mgr.post_callback (__myhandle__, "sizechangedfcn");
 
           update_boundingbox ();
         }
@@ -10971,7 +11311,11 @@
 {
   Matrix pos = get_position ().matrix_value ();
 
-  graphics_object parent_go = gh_manager::get_object (get_parent ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("uipanel::properties::update_units");
+
+  graphics_object parent_go = gh_mgr.get_object (get_parent ());
+
   Matrix parent_bbox = parent_go.get_properties ().get_boundingbox (true);
   Matrix parent_size = parent_bbox.extract_n (0, 2, 1, 2);
 
@@ -11026,7 +11370,10 @@
 
   if (parent_size.isempty ())
     {
-      graphics_object go = gh_manager::get_object (get_parent ());
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("uitable::properties::get_boundingbox");
+
+      graphics_object go = gh_mgr.get_object (get_parent ());
 
       parent_size = go.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);
     }
@@ -11150,7 +11497,11 @@
 {
   Matrix pos = get_position ().matrix_value ();
 
-  graphics_object parent_go = gh_manager::get_object (get_parent ());
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("uitable::properties::update_units");
+
+  graphics_object parent_go = gh_mgr.get_object (get_parent ());
+
   Matrix parent_bbox = parent_go.get_properties ().get_boundingbox (true);
   Matrix parent_size = parent_bbox.extract_n (0, 2, 1, 2);
 
@@ -11235,7 +11586,12 @@
 {
   // FIXME: Is it really acceptable to just let the toolkit update the extent?
   Matrix m = extent.get ().matrix_value ();
-  graphics_object parent_go = gh_manager::get_object (get_parent ());
+
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("uitable::properties::get_extent");
+
+  graphics_object parent_go = gh_mgr.get_object (get_parent ());
+
   if (parent_go)
     {
       Matrix parent_bbox = parent_go.get_properties ().get_boundingbox (true);
@@ -11257,7 +11613,11 @@
   if (retval.is_undefined ())
     {
       graphics_handle parent_h = get_parent ();
-      graphics_object parent_go = gh_manager::get_object (parent_h);
+
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("uitoolbar::get_default");
+
+      graphics_object parent_go = gh_mgr.get_object (parent_h);
 
       retval = parent_go.get_default (pname);
     }
@@ -11281,7 +11641,11 @@
 base_graphics_object::get_default (const caseless_str& pname) const
 {
   graphics_handle parent_h = get_parent ();
-  graphics_object parent_go = gh_manager::get_object (parent_h);
+
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_graphics_object::get_default");
+
+  graphics_object parent_go = gh_mgr.get_object (parent_h);
 
   return parent_go.get_default (type () + pname);
 }
@@ -11289,7 +11653,10 @@
 octave_value
 base_graphics_object::get_factory_default (const caseless_str& name) const
 {
-  graphics_object parent_go = gh_manager::get_object (0);
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("base_graphics_object::get_factory_default");
+
+  graphics_object parent_go = gh_mgr.get_object (0);
 
   return parent_go.get_factory_default (type () + name);
 }
@@ -11310,24 +11677,18 @@
   gtk_mgr.default_toolkit ();
 }
 
-gh_manager& gh_manager::instance (void)
-{
-  return octave::__get_gh_manager__ ("gh_manager::instance");
-}
-
 graphics_handle
-gh_manager::do_make_graphics_handle (const std::string& go_name,
-                                     const graphics_handle& p,
-                                     bool integer_figure_handle,
-                                     bool do_createfcn,
-                                     bool do_notify_toolkit)
+gh_manager::make_graphics_handle (const std::string& go_name,
+                                  const graphics_handle& p,
+                                  bool integer_figure_handle,
+                                  bool call_createfcn, bool notify_toolkit)
 {
   graphics_handle h = get_handle (integer_figure_handle);
 
   base_graphics_object *bgo = make_graphics_object_from_type (go_name, h, p);
 
   if (! bgo)
-    error ("gh_manager::do_make_graphics_handle: invalid object type '%s'",
+    error ("gh_manager::make_graphics_handle: invalid object type '%s'",
            go_name.c_str ());
 
   graphics_object go (bgo);
@@ -11349,31 +11710,31 @@
 
       graphics_object tgo;
 
-      tgo = gh_manager::get_object (props.get_xlabel ());
+      tgo = get_object (props.get_xlabel ());
       tgo.override_defaults ();
 
-      tgo = gh_manager::get_object (props.get_ylabel ());
+      tgo = get_object (props.get_ylabel ());
       tgo.override_defaults ();
 
-      tgo = gh_manager::get_object (props.get_zlabel ());
+      tgo = get_object (props.get_zlabel ());
       tgo.override_defaults ();
 
-      tgo = gh_manager::get_object (props.get_title ());
+      tgo = get_object (props.get_title ());
       tgo.override_defaults ();
     }
 
-  if (do_createfcn)
+  if (call_createfcn)
     bgo->get_properties ().execute_createfcn ();
 
   // Notify graphics toolkit.
-  if (do_notify_toolkit)
+  if (notify_toolkit)
     go.initialize ();
 
   return h;
 }
 
 graphics_handle
-gh_manager::do_make_figure_handle (double val, bool do_notify_toolkit)
+gh_manager::make_figure_handle (double val, bool notify_toolkit)
 {
   graphics_handle h = val;
 
@@ -11383,7 +11744,7 @@
   m_handle_map[h] = go;
 
   // Notify graphics toolkit.
-  if (do_notify_toolkit)
+  if (notify_toolkit)
     go.initialize ();
 
   go.override_defaults ();
@@ -11392,15 +11753,15 @@
 }
 
 void
-gh_manager::do_push_figure (const graphics_handle& h)
-{
-  do_pop_figure (h);
+gh_manager::push_figure (const graphics_handle& h)
+{
+  pop_figure (h);
 
   m_figure_list.push_front (h);
 }
 
 void
-gh_manager::do_pop_figure (const graphics_handle& h)
+gh_manager::pop_figure (const graphics_handle& h)
 {
   for (auto it = m_figure_list.begin (); it != m_figure_list.end (); it++)
     {
@@ -11430,10 +11791,13 @@
 
   void execute (void)
   {
+    gh_manager& gh_mgr
+      = octave::__get_gh_manager__ ("callback_event::execute");
+
     if (callback.is_defined ())
-      gh_manager::execute_callback (handle, callback, callback_data);
+      gh_mgr.execute_callback (handle, callback, callback_data);
     else
-      gh_manager::execute_callback (handle, callback_name, callback_data);
+      gh_mgr.execute_callback (handle, callback_name, callback_data);
   }
 
 private:
@@ -11461,11 +11825,15 @@
   {
     if (! mcode.empty ())
       {
-        graphics_object go = gh_manager::get_object (handle);
+        gh_manager& gh_mgr
+          = octave::__get_gh_manager__ ("mcode_event::execute");
+
+        graphics_object go = gh_mgr.get_object (handle);
+
         if (go.valid_object ())
           {
             octave_value cb (mcode);
-            gh_manager::execute_callback (handle, cb);
+            gh_mgr.execute_callback (handle, cb);
           }
       }
   }
@@ -11525,9 +11893,11 @@
 
   void execute (void)
   {
-    gh_manager::auto_lock guard;
-
-    graphics_object go = gh_manager::get_object (handle);
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("set_event::execute");
+
+    octave::autolock guard (gh_mgr.graphics_lock ());
+
+    graphics_object go = gh_mgr.get_object (handle);
 
     if (go)
       {
@@ -11631,7 +12001,10 @@
 static void
 xset_gcbo (const graphics_handle& h)
 {
-  graphics_object go = gh_manager::get_object (0);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("xset_gcbo");
+
+  graphics_object go = gh_mgr.get_object (0);
+
   root_figure::properties& props
     = dynamic_cast<root_figure::properties&> (go.get_properties ());
 
@@ -11639,9 +12012,9 @@
 }
 
 void
-gh_manager::do_restore_gcbo (void)
-{
-  gh_manager::auto_lock guard;
+gh_manager::restore_gcbo (void)
+{
+  octave::autolock guard (m_graphics_lock);
 
   m_callback_objects.pop_front ();
 
@@ -11650,23 +12023,22 @@
 }
 
 void
-gh_manager::do_execute_listener (const graphics_handle& h,
-                                 const octave_value& l)
+gh_manager::execute_listener (const graphics_handle& h, const octave_value& l)
 {
   if (octave::thread::is_thread ())
-    gh_manager::execute_callback (h, l, octave_value ());
-  else
-    {
-      gh_manager::auto_lock guard;
-
-      do_post_event (graphics_event::create_callback_event (h, l));
-    }
-}
-
-void
-gh_manager::do_execute_callback (const graphics_handle& h,
-                                 const octave_value& cb_arg,
-                                 const octave_value& data)
+    execute_callback (h, l, octave_value ());
+  else
+    {
+      octave::autolock guard (m_graphics_lock);
+
+      post_event (graphics_event::create_callback_event (h, l));
+    }
+}
+
+void
+gh_manager::execute_callback (const graphics_handle& h,
+                              const octave_value& cb_arg,
+                              const octave_value& data)
 {
   if (cb_arg.is_defined () && ! cb_arg.isempty ())
     {
@@ -11681,14 +12053,15 @@
         args(1) = Matrix ();
 
       octave::unwind_protect_safe frame;
-      frame.add_fcn (gh_manager::restore_gcbo);
+
+      frame.add_method (this, &gh_manager::restore_gcbo);
 
       graphics_object go (get_object (h));
       if (go)
         {
           // FIXME: Is the lock necessary when we're only calling a
           //        const "get" method?
-          gh_manager::auto_lock guard;
+          octave::autolock guard (m_graphics_lock);
           m_callback_objects.push_front (go);
           xset_gcbo (h);
         }
@@ -11696,10 +12069,7 @@
       // Copy CB because "function_value" method is non-const.
       octave_value cb = cb_arg;
 
-      octave::interpreter& interp
-        = octave::__get_interpreter__ ("gh_manager::do_execute_callback");
-
-      octave::error_system& es = interp.get_error_system ();
+      octave::error_system& es = m_interpreter.get_error_system ();
 
       if (cb.is_function ())
         fcn = cb.function_value ();
@@ -11712,7 +12082,7 @@
 
           try
             {
-              interp.eval_string (s, false, status, 0);
+              m_interpreter.eval_string (s, false, status, 0);
             }
           catch (octave::execution_exception&)
             {
@@ -11774,7 +12144,7 @@
               if (go_name.length () > 1
                   && go_name[0] == 'u' && go_name[1] == 'i')
                 {
-                  Fdrawnow ();
+                  Fdrawnow (m_interpreter);
                   Vdrawnow_requested = false;
                 }
             }
@@ -11782,19 +12152,27 @@
     }
 }
 
-void
-gh_manager::do_post_event (const graphics_event& e)
+static int
+process_graphics_events (void)
+{
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("process_graphics_events");
+
+  return gh_mgr.process_events ();
+}
+
+void
+gh_manager::post_event (const graphics_event& e)
 {
   m_event_queue.push_back (e);
 
-  octave::command_editor::add_event_hook (gh_manager::process_events);
-}
-
-void
-gh_manager::do_post_callback (const graphics_handle& h, const std::string& name,
-                              const octave_value& data)
-{
-  gh_manager::auto_lock guard;
+  octave::command_editor::add_event_hook (process_graphics_events);
+}
+
+void
+gh_manager::post_callback (const graphics_handle& h, const std::string& name,
+                           const octave_value& data)
+{
+  octave::autolock guard (m_graphics_lock);
 
   graphics_object go = get_object (h);
 
@@ -11817,37 +12195,35 @@
       if (cname == "closerequestfcn")
         {
           std::string cmd ("close (gcbf ());");
-          do_post_event (graphics_event::create_mcode_event (h, cmd,
-                                                             busyaction));
+          post_event (graphics_event::create_mcode_event (h, cmd, busyaction));
         }
       else
-        do_post_event (graphics_event::create_callback_event (h, name, data,
-                                                              busyaction));
-    }
-}
-
-void
-gh_manager::do_post_function (graphics_event::event_fcn fcn, void *fcn_data)
-{
-  gh_manager::auto_lock guard;
-
-  do_post_event (graphics_event::create_function_event (fcn, fcn_data));
-}
-
-void
-gh_manager::do_post_set (const graphics_handle& h, const std::string& name,
-                         const octave_value& value, bool notify_toolkit,
-                         bool redraw_figure)
-{
-  gh_manager::auto_lock guard;
-
-  do_post_event (graphics_event::create_set_event (h, name, value,
-                                                   notify_toolkit,
-                                                   redraw_figure));
+        post_event (graphics_event::create_callback_event (h, name, data,
+                                                           busyaction));
+    }
+}
+
+void
+gh_manager::post_function (graphics_event::event_fcn fcn, void *fcn_data)
+{
+  octave::autolock guard (m_graphics_lock);
+
+  post_event (graphics_event::create_function_event (fcn, fcn_data));
+}
+
+void
+gh_manager::post_set (const graphics_handle& h, const std::string& name,
+                      const octave_value& value, bool notify_toolkit,
+                      bool redraw_figure)
+{
+  octave::autolock guard (m_graphics_lock);
+
+  post_event (graphics_event::create_set_event (h, name, value, notify_toolkit,
+                                                redraw_figure));
 }
 
 int
-gh_manager::do_process_events (bool force)
+gh_manager::process_events (bool force)
 {
   graphics_event e;
   bool old_Vdrawnow_requested = Vdrawnow_requested;
@@ -11858,7 +12234,7 @@
       e = graphics_event ();
 
       {
-        gh_manager::auto_lock guard;
+        octave::autolock guard (m_graphics_lock);
 
         if (! m_event_queue.empty ())
           {
@@ -11910,10 +12286,10 @@
   while (e.ok ());
 
   {
-    gh_manager::auto_lock guard;
+    octave::autolock guard (m_graphics_lock);
 
     if (m_event_queue.empty () && m_event_processing == 0)
-      octave::command_editor::remove_event_hook (gh_manager::process_events);
+      octave::command_editor::remove_event_hook (process_graphics_events);
   }
 
   if (events_executed)
@@ -11921,7 +12297,7 @@
 
   if (Vdrawnow_requested && ! old_Vdrawnow_requested)
     {
-      Fdrawnow ();
+      Fdrawnow (m_interpreter);
 
       Vdrawnow_requested = false;
     }
@@ -11985,22 +12361,22 @@
 */
 
 void
-gh_manager::do_enable_event_processing (bool enable)
-{
-  gh_manager::auto_lock guard;
+gh_manager::enable_event_processing (bool enable)
+{
+  octave::autolock guard (m_graphics_lock);
 
   if (enable)
     {
       m_event_processing++;
 
-      octave::command_editor::add_event_hook (gh_manager::process_events);
+      octave::command_editor::add_event_hook (process_graphics_events);
     }
   else
     {
       m_event_processing--;
 
       if (m_event_queue.empty () && m_event_processing == 0)
-        octave::command_editor::remove_event_hook (gh_manager::process_events);
+        octave::command_editor::remove_event_hook (process_graphics_events);
     }
 }
 
@@ -12032,8 +12408,8 @@
 
 // ---------------------------------------------------------------------
 
-DEFUN (ishghandle, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (ishghandle, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} ishghandle (@var{h})
 Return true if @var{h} is a graphics handle and false otherwise.
 
@@ -12043,7 +12419,9 @@
 @seealso{isgraphics, isaxes, isfigure, ishandle}
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   if (args.length () != 1)
     print_usage ();
@@ -12073,13 +12451,17 @@
 static bool
 is_handle_visible (const graphics_handle& h)
 {
-  return h.ok () && gh_manager::is_handle_visible (h);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("is_handle_visible");
+
+  return h.ok () && gh_mgr.is_handle_visible (h);
 }
 
 static bool
 is_handle_visible (double val)
 {
-  return is_handle_visible (gh_manager::lookup (val));
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("is_handle_visible");
+
+  return is_handle_visible (gh_mgr.lookup (val));
 }
 
 static octave_value
@@ -12116,8 +12498,8 @@
   return ovl (is_handle_visible (args(0)));
 }
 
-DEFUN (reset, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (reset, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} reset (@var{h})
 Reset the properties of the graphic object @var{h} to their default values.
 
@@ -12137,9 +12519,11 @@
   // get vector of graphics handles
   ColumnVector hcv = args(0).xvector_value ("reset: H must be a graphics handle");
 
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
   // loop over graphics objects
   for (octave_idx_type n = 0; n < hcv.numel (); n++)
-    gh_manager::get_object (hcv(n)).reset_default_properties ();
+    gh_mgr.get_object (hcv(n)).reset_default_properties ();
 
   Vdrawnow_requested = true;
 
@@ -12267,8 +12651,8 @@
 
 */
 
-DEFUN (set, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (set, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} set (@var{h}, @var{property}, @var{value}, @dots{})
 @deftypefnx {} {} set (@var{h}, @var{properties}, @var{values})
 @deftypefnx {} {} set (@var{h}, @var{pv})
@@ -12332,7 +12716,9 @@
 @seealso{get}
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   int nargin = args.length ();
 
@@ -12349,7 +12735,7 @@
   // loop over graphics objects
   for (octave_idx_type n = 0; n < hcv.numel (); n++)
     {
-      graphics_object go = gh_manager::get_object (hcv(n));
+      graphics_object go = gh_mgr.get_object (hcv(n));
 
       if (! go)
         error ("set: invalid handle (= %g)", hcv(n));
@@ -12426,7 +12812,9 @@
 {
   std::string retval;
 
-  graphics_object go = gh_manager::get_object (val);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("get_graphics_object_type");
+
+  graphics_object go = gh_mgr.get_object (val);
 
   if (! go)
     error ("get: invalid handle (= %g)", val);
@@ -12434,8 +12822,8 @@
   return go.type ();
 }
 
-DEFUN (get, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (get, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} get (@var{h})
 @deftypefnx {} {@var{val} =} get (@var{h}, @var{p})
 Return the value of the named property @var{p} from the graphics handle
@@ -12448,7 +12836,9 @@
 @seealso{set}
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   int nargin = args.length ();
 
@@ -12491,7 +12881,7 @@
 
       for (octave_idx_type n = 0; n < hcv_len; n++)
         {
-          graphics_object go = gh_manager::get_object (hcv(n));
+          graphics_object go = gh_mgr.get_object (hcv(n));
 
           if (! go)
             error ("get: invalid handle (= %g)", hcv(n));
@@ -12515,7 +12905,7 @@
 
       for (octave_idx_type n = 0; n < hcv_len; n++)
         {
-          graphics_object go = gh_manager::get_object (hcv(n));
+          graphics_object go = gh_mgr.get_object (hcv(n));
 
           if (! go)
             error ("get: invalid handle (= %g)", hcv(n));
@@ -12561,13 +12951,15 @@
 // If @var{h} is a vector, return a cell array including the
 // property values or lists respectively.
 
-DEFUN (__get__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__get__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __get__ (@var{h})
 Undocumented internal function.
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   if (args.length () != 1)
     print_usage ();
@@ -12582,7 +12974,7 @@
 
   for (octave_idx_type n = 0; n < hcv_len; n++)
     {
-      graphics_object go = gh_manager::get_object (hcv(n));
+      graphics_object go = gh_mgr.get_object (hcv(n));
 
       if (! go)
         error ("get: invalid handle (= %g)", hcv(n));
@@ -12638,7 +13030,9 @@
   if (octave::math::isnan (val))
     val = args(0).xdouble_value ("__go_%s__: invalid parent", go_name.c_str ());
 
-  graphics_handle parent = gh_manager::lookup (val);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("make_graphics_object");
+
+  graphics_handle parent = gh_mgr.lookup (val);
 
   if (! parent.ok ())
     error ("__go_%s__: invalid parent", go_name.c_str ());
@@ -12647,9 +13041,8 @@
 
   try
     {
-      h = gh_manager::make_graphics_handle (go_name, parent,
-                                            integer_figure_handle,
-                                            false, false);
+      h = gh_mgr.make_graphics_handle (go_name, parent,
+                                          integer_figure_handle, false, false);
     }
   catch (octave::execution_exception& e)
     {
@@ -12680,13 +13073,15 @@
   return retval;
 }
 
-DEFUN (__go_figure__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_figure__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_figure__ (@var{fignum})
 Undocumented internal function.
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   if (args.length () == 0)
     print_usage ();
@@ -12697,7 +13092,7 @@
 
   if (isfigure (val))
     {
-      graphics_handle h = gh_manager::lookup (val);
+      graphics_handle h = gh_mgr.lookup (val);
 
       xset (h, args.splice (0, 1));
 
@@ -12733,28 +13128,27 @@
                 }
             }
 
-          h = gh_manager::make_graphics_handle ("figure", 0,
-                                                int_fig_handle,
-                                                false, false);
+          h = gh_mgr.make_graphics_handle ("figure", 0, int_fig_handle,
+                                              false, false);
 
           if (! int_fig_handle)
             {
               // We need to initialize the integerhandle property
               // without calling the set_integerhandle method,
               // because doing that will generate a new handle value...
-              graphics_object go = gh_manager::get_object (h);
+              graphics_object go = gh_mgr.get_object (h);
               go.get_properties ().init_integerhandle ("off");
             }
         }
       else if (val > 0 && octave::math::x_nint (val) == val)
-        h = gh_manager::make_figure_handle (val, false);
+        h = gh_mgr.make_figure_handle (val, false);
 
       if (! h.ok ())
         error ("__go_figure__: failed to create figure handle");
 
       adopt (0, h);
 
-      gh_manager::push_figure (h);
+      gh_mgr.push_figure (h);
 
       xset (h, xargs);
       xcreatefcn (h);
@@ -12767,7 +13161,9 @@
 }
 
 #define GO_BODY(TYPE)                                                   \
-  gh_manager::auto_lock guard;                                          \
+  gh_manager& gh_mgr = interp.get_gh_manager ();                        \
+                                                                        \
+  octave::autolock guard (gh_mgr.graphics_lock ());                     \
                                                                         \
   if (args.length () == 0)                                              \
     print_usage ();                                                     \
@@ -12788,13 +13184,15 @@
     {
       Matrix kids = go.get_properties ().get_children ();
 
+      gh_manager& gh_mgr = octave::__get_gh_manager__ ("calc_dimensions");
+
       for (octave_idx_type i = 0; i < kids.numel (); i++)
         {
-          graphics_handle hkid = gh_manager::lookup (kids(i));
+          graphics_handle hkid = gh_mgr.lookup (kids(i));
 
           if (hkid.ok ())
             {
-              const graphics_object& kid = gh_manager::get_object (hkid);
+              const graphics_object& kid = gh_mgr.get_object (hkid);
 
               if (kid.valid_object ())
                 nd = calc_dimensions (kid);
@@ -12808,26 +13206,28 @@
   return nd;
 }
 
-DEFUN (__calc_dimensions__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__calc_dimensions__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __calc_dimensions__ (@var{axes})
 Internal function.
 
 Determine the number of dimensions in a graphics object, either 2 or 3.
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   if (args.length () != 1)
     print_usage ();
 
   double h = args(0).xdouble_value ("__calc_dimensions__: first argument must be a graphics handle");
 
-  return ovl (calc_dimensions (gh_manager::get_object (h)));
-}
-
-DEFUN (__go_axes__, args, ,
-       doc: /* -*- texinfo -*-
+  return ovl (calc_dimensions (gh_mgr.get_object (h)));
+}
+
+DEFMETHOD (__go_axes__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_axes__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12835,8 +13235,8 @@
   GO_BODY (axes);
 }
 
-DEFUN (__go_line__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_line__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_line__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12844,8 +13244,8 @@
   GO_BODY (line);
 }
 
-DEFUN (__go_text__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_text__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_text__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12853,8 +13253,8 @@
   GO_BODY (text);
 }
 
-DEFUN (__go_image__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_image__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_image__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12862,8 +13262,8 @@
   GO_BODY (image);
 }
 
-DEFUN (__go_surface__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_surface__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_surface__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12871,8 +13271,8 @@
   GO_BODY (surface);
 }
 
-DEFUN (__go_patch__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_patch__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_patch__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12880,8 +13280,8 @@
   GO_BODY (patch);
 }
 
-DEFUN (__go_light__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_light__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_light__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12889,8 +13289,8 @@
   GO_BODY (light);
 }
 
-DEFUN (__go_hggroup__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_hggroup__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_hggroup__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12898,8 +13298,8 @@
   GO_BODY (hggroup);
 }
 
-DEFUN (__go_uimenu__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_uimenu__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_uimenu__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12907,8 +13307,8 @@
   GO_BODY (uimenu);
 }
 
-DEFUN (__go_uicontrol__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_uicontrol__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_uicontrol__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12916,8 +13316,8 @@
   GO_BODY (uicontrol);
 }
 
-DEFUN (__go_uibuttongroup__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_uibuttongroup__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_uibuttongroup__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12925,8 +13325,8 @@
   GO_BODY (uibuttongroup);
 }
 
-DEFUN (__go_uipanel__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_uipanel__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_uipanel__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12934,8 +13334,8 @@
   GO_BODY (uipanel);
 }
 
-DEFUN (__go_uicontextmenu__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_uicontextmenu__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_uicontextmenu__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12943,8 +13343,8 @@
   GO_BODY (uicontextmenu);
 }
 
-DEFUN (__go_uitable__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_uitable__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_uitable__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12952,8 +13352,8 @@
   GO_BODY (uitable);
 }
 
-DEFUN (__go_uitoolbar__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_uitoolbar__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_uitoolbar__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12961,8 +13361,8 @@
   GO_BODY (uitoolbar);
 }
 
-DEFUN (__go_uipushtool__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_uipushtool__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_uipushtool__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12970,8 +13370,8 @@
   GO_BODY (uipushtool);
 }
 
-DEFUN (__go_uitoggletool__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_uitoggletool__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_uitoggletool__ (@var{parent})
 Undocumented internal function.
 @end deftypefn */)
@@ -12979,13 +13379,15 @@
   GO_BODY (uitoggletool);
 }
 
-DEFUN (__go_delete__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_delete__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_delete__ (@var{h})
 Undocumented internal function.
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   if (args.length () != 1)
     print_usage ();
@@ -12998,7 +13400,7 @@
   // as callbacks might delete one of the handles we later want to delete.
   for (octave_idx_type i = 0; i < vals.numel (); i++)
     {
-      h = gh_manager::lookup (vals(i));
+      h = gh_mgr.lookup (vals(i));
 
       if (! h.ok ())
         error ("delete: invalid graphics object (= %g)", vals(i));
@@ -13009,40 +13411,44 @@
   return ovl ();
 }
 
-DEFUN (__go_handles__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_handles__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_handles__ (@var{show_hidden})
 Undocumented internal function.
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   bool show_hidden = false;
 
   if (args.length () > 0)
     show_hidden = args(0).bool_value ();
 
-  return ovl (gh_manager::handle_list (show_hidden));
-}
-
-DEFUN (__go_figure_handles__, args, ,
-       doc: /* -*- texinfo -*-
+  return ovl (gh_mgr.handle_list (show_hidden));
+}
+
+DEFMETHOD (__go_figure_handles__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_figure_handles__ (@var{show_hidden})
 Undocumented internal function.
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   bool show_hidden = false;
 
   if (args.length () > 0)
     show_hidden = args(0).bool_value ();
 
-  return ovl (gh_manager::figure_handle_list (show_hidden));
-}
-
-DEFUN (__go_execute_callback__, args, ,
-       doc: /* -*- texinfo -*-
+  return ovl (gh_mgr.figure_handle_list (show_hidden));
+}
+
+DEFMETHOD (__go_execute_callback__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} __go_execute_callback__ (@var{h}, @var{name})
 @deftypefnx {} {} __go_execute_callback__ (@var{h}, @var{name}, @var{param})
 Undocumented internal function.
@@ -13057,26 +13463,28 @@
 
   std::string name = args(1).xstring_value ("__go_execute_callback__: invalid callback name");
 
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
   for (octave_idx_type i = 0; i < vals.numel (); i++)
     {
       double val = vals(i);
 
-      graphics_handle h = gh_manager::lookup (val);
+      graphics_handle h = gh_mgr.lookup (val);
 
       if (! h.ok ())
         error ("__go_execute_callback__: invalid graphics object (= %g)", val);
 
       if (nargin == 2)
-        gh_manager::execute_callback (h, name);
+        gh_mgr.execute_callback (h, name);
       else
-        gh_manager::execute_callback (h, name, args(2));
+        gh_mgr.execute_callback (h, name, args(2));
     }
 
   return ovl ();
 }
 
-DEFUN (__go_post_callback__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__go_post_callback__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} __go_post_callback__ (@var{h}, @var{name})
 @deftypefnx {} {} __go_post_callback__ (@var{h}, @var{name}, @var{param})
 Undocumented internal function.
@@ -13091,26 +13499,28 @@
 
   std::string name = args(1).xstring_value ("__go_post_callback__: invalid callback name");
 
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
   for (octave_idx_type i = 0; i < vals.numel (); i++)
     {
       double val = vals(i);
 
-      graphics_handle h = gh_manager::lookup (val);
+      graphics_handle h = gh_mgr.lookup (val);
 
       if (! h.ok ())
         error ("__go_execute_callback__: invalid graphics object (= %g)", val);
 
       if (nargin == 2)
-        gh_manager::post_callback (h, name);
+        gh_mgr.post_callback (h, name);
       else
-        gh_manager::post_callback (h, name, args(2));
+        gh_mgr.post_callback (h, name, args(2));
     }
 
   return ovl ();
 }
 
-DEFUN (__image_pixel_size__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__image_pixel_size__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {@var{sz} =} __image_pixel_size__ (@var{h})
 Internal function: returns the pixel size of the image in normalized units.
 @end deftypefn */)
@@ -13118,9 +13528,12 @@
   if (args.length () != 1)
     print_usage ();
 
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
   double h = args(0).xdouble_value ("__image_pixel_size__: argument is not a handle");
 
-  graphics_object go = gh_manager::get_object (h);
+  graphics_object go = gh_mgr.get_object (h);
+
   if (! go || ! go.isa ("image"))
     error ("__image_pixel_size__: object is not an image");
 
@@ -13140,7 +13553,9 @@
 @seealso{graphics_toolkit, register_graphics_toolkit}
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   octave::gtk_manager& gtk_mgr = interp.get_gtk_manager ();
 
@@ -13154,7 +13569,9 @@
 @seealso{available_graphics_toolkits}
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   if (args.length () != 1)
     print_usage ();
@@ -13175,15 +13592,17 @@
 @seealso{available_graphics_toolkits}
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   octave::gtk_manager& gtk_mgr = interp.get_gtk_manager ();
 
   return ovl (gtk_mgr.loaded_toolkits_list ());
 }
 
-DEFUN (__show_figure__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__show_figure__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __show_figure__ (@var{n})
 Undocumented internal function.
 @end deftypefn */)
@@ -13191,14 +13610,16 @@
   if (args.length () != 1)
     print_usage ();
 
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
   double h = args(0).xdouble_value ("__show_figure__: invalid handle H");
 
-  graphics_handle gh = gh_manager::lookup (h);
+  graphics_handle gh = gh_mgr.lookup (h);
 
   if (! gh.ok ())
     error ("__show_figure__: invalid graphics object (= %g)", h);
 
-  graphics_object go = gh_manager::get_object (gh);
+  graphics_object go = gh_mgr.get_object (gh);
 
   figure::properties& fprops
     = dynamic_cast<figure::properties&> (go.get_properties ());
@@ -13208,8 +13629,8 @@
   return ovl ();
 }
 
-DEFUN (drawnow, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (drawnow, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} drawnow ()
 @deftypefnx {} {} drawnow ("expose")
 @deftypefnx {} {} drawnow (@var{term}, @var{file}, @var{debug_file})
@@ -13236,7 +13657,9 @@
 
   if (! delete_executing)
     {
-      gh_manager::auto_lock guard;
+      gh_manager& gh_mgr = interp.get_gh_manager ();
+
+      octave::autolock guard (gh_mgr.graphics_lock ());
 
       if (args.length () <= 1)
         {
@@ -13256,23 +13679,23 @@
 
           if (do_events)
             {
-              gh_manager::unlock ();
-
-              gh_manager::process_events ();
-
-              gh_manager::lock ();
-            }
-
-          Matrix hlist = gh_manager::figure_handle_list (true);
+              gh_mgr.unlock ();
+
+              gh_mgr.process_events ();
+
+              gh_mgr.lock ();
+            }
+
+          Matrix hlist = gh_mgr.figure_handle_list (true);
 
           // Redraw modified figures
           for (int i = 0; i < hlist.numel (); i++)
             {
-              graphics_handle h = gh_manager::lookup (hlist(i));
+              graphics_handle h = gh_mgr.lookup (hlist(i));
 
               if (h.ok () && h != 0)
                 {
-                  graphics_object go = gh_manager::get_object (h);
+                  graphics_object go = gh_mgr.get_object (h);
                   figure::properties& fprops
                     = dynamic_cast<figure::properties&> (go.get_properties ());
 
@@ -13280,11 +13703,11 @@
                     {
                       if (fprops.is_visible ())
                         {
-                          gh_manager::unlock ();
+                          gh_mgr.unlock ();
 
                           fprops.get_toolkit ().redraw_figure (go);
 
-                          gh_manager::lock ();
+                          gh_mgr.lock ();
                         }
 
                       fprops.set_modified (false);
@@ -13329,21 +13752,21 @@
           if (! h.ok ())
             error ("drawnow: nothing to draw");
 
-          graphics_object go = gh_manager::get_object (h);
-
-          gh_manager::unlock ();
+          graphics_object go = gh_mgr.get_object (h);
+
+          gh_mgr.unlock ();
 
           go.get_toolkit ().print_figure (go, term, file, debug_file);
 
-          gh_manager::lock ();
+          gh_mgr.lock ();
         }
     }
 
   return ovl ();
 }
 
-DEFUN (addlistener, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (addlistener, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} addlistener (@var{h}, @var{prop}, @var{fcn})
 Register @var{fcn} as listener for the property @var{prop} of the graphics
 object @var{h}.
@@ -13377,7 +13800,9 @@
 @seealso{dellistener, addproperty, hggroup}
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   int nargin = args.length ();
 
@@ -13388,12 +13813,12 @@
 
   std::string pname = args(1).xstring_value ("addlistener: PROP must be a string");
 
-  graphics_handle gh = gh_manager::lookup (h);
+  graphics_handle gh = gh_mgr.lookup (h);
 
   if (! gh.ok ())
     error ("addlistener: invalid graphics object (= %g)", h);
 
-  graphics_object go = gh_manager::get_object (gh);
+  graphics_object go = gh_mgr.get_object (gh);
 
   go.add_property_listener (pname, args(2), GCB_POSTSET);
 
@@ -13407,8 +13832,8 @@
   return ovl ();
 }
 
-DEFUN (dellistener, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (dellistener, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} dellistener (@var{h}, @var{prop}, @var{fcn})
 Remove the registration of @var{fcn} as a listener for the property
 @var{prop} of the graphics object @var{h}.
@@ -13436,7 +13861,9 @@
 @seealso{addlistener}
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   if (args.length () < 2 || args.length () > 3)
     print_usage ();
@@ -13445,12 +13872,12 @@
 
   std::string pname = args(1).xstring_value ("dellistener: PROP must be a string");
 
-  graphics_handle gh = gh_manager::lookup (h);
+  graphics_handle gh = gh_mgr.lookup (h);
 
   if (! gh.ok ())
     error ("dellistener: invalid graphics object (= %g)", h);
 
-  graphics_object go = gh_manager::get_object (gh);
+  graphics_object go = gh_mgr.get_object (gh);
 
   if (args.length () == 2)
     go.delete_property_listener (pname, octave_value (), GCB_POSTSET);
@@ -13471,8 +13898,8 @@
   return ovl ();
 }
 
-DEFUN (addproperty, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (addproperty, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} addproperty (@var{name}, @var{h}, @var{type})
 @deftypefnx {} {} addproperty (@var{name}, @var{h}, @var{type}, @var{arg}, @dots{})
 Create a new property named @var{name} in graphics object @var{h}.
@@ -13543,7 +13970,9 @@
 @seealso{addlistener, hggroup}
 @end deftypefn */)
 {
-  gh_manager::auto_lock guard;
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
 
   if (args.length () < 3)
     print_usage ();
@@ -13552,12 +13981,12 @@
 
   double h = args(1).xdouble_value ("addproperty: invalid handle H");
 
-  graphics_handle gh = gh_manager::lookup (h);
+  graphics_handle gh = gh_mgr.lookup (h);
 
   if (! gh.ok ())
     error ("addproperty: invalid graphics object (= %g)", h);
 
-  graphics_object go = gh_manager::get_object (gh);
+  graphics_object go = gh_mgr.get_object (gh);
 
   std::string type = args(2).xstring_value ("addproperty: TYPE must be a string");
 
@@ -13576,9 +14005,11 @@
 get_property_from_handle (double handle, const std::string& property,
                           const std::string& func)
 {
-  gh_manager::auto_lock guard;
-
-  graphics_object go = gh_manager::get_object (handle);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("get_property_from_handle");
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
+
+  graphics_object go = gh_mgr.get_object (handle);
 
   if (! go)
     error ("%s: invalid handle (= %g)", func.c_str (), handle);
@@ -13590,9 +14021,11 @@
 set_property_in_handle (double handle, const std::string& property,
                         const octave_value& arg, const std::string& func)
 {
-  gh_manager::auto_lock guard;
-
-  graphics_object go = gh_manager::get_object (handle);
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ("set_property_in_handle");
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
+
+  graphics_object go = gh_mgr.get_object (handle);
 
   if (! go)
     error ("%s: invalid handle (= %g)", func.c_str (), handle);
@@ -13638,13 +14071,16 @@
 
       caseless_str pname = c(3).string_value ();
 
-      gh_manager::auto_lock guard;
-
-      graphics_handle gh = gh_manager::lookup (h);
+      gh_manager& gh_mgr
+        = octave::__get_gh_manager__ ("do_cleanup_waitfor_listener");
+
+      octave::autolock guard (gh_mgr.graphics_lock ());
+
+      graphics_handle gh = gh_mgr.lookup (h);
 
       if (gh.ok ())
         {
-          graphics_object go = gh_manager::get_object (gh);
+          graphics_object go = gh_mgr.get_object (gh);
 
           if (go.get_properties ().has_property (pname))
             {
@@ -13678,13 +14114,15 @@
 
           caseless_str pname = args(4).string_value ();
 
-          gh_manager::auto_lock guard;
-
-          graphics_handle gh = gh_manager::lookup (h);
+          gh_manager& gh_mgr = octave::__get_gh_manager__ ("waitfor_listener");
+
+          octave::autolock guard (gh_mgr.graphics_lock ());
+
+          graphics_handle gh = gh_mgr.lookup (h);
 
           if (gh.ok ())
             {
-              graphics_object go = gh_manager::get_object (gh);
+              graphics_object go = gh_mgr.get_object (gh);
               octave_value pvalue = go.get (pname);
 
               if (compare_property_values (pvalue, args(5)))
@@ -13710,8 +14148,8 @@
   return ovl ();
 }
 
-DEFUN (waitfor, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (waitfor, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} waitfor (@var{h})
 @deftypefnx {} {} waitfor (@var{h}, @var{prop})
 @deftypefnx {} {} waitfor (@var{h}, @var{prop}, @var{value})
@@ -13777,6 +14215,8 @@
 
   double timeout = 0;
 
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
   if (args.length () > 1)
     {
       pname = args(1).xstring_value ("waitfor: PROP must be a string");
@@ -13828,13 +14268,13 @@
 
           octave_value ov_listener (listener);
 
-          gh_manager::auto_lock guard;
-
-          graphics_handle gh = gh_manager::lookup (h);
+          octave::autolock guard (gh_mgr.graphics_lock ());
+
+          graphics_handle gh = gh_mgr.lookup (h);
 
           if (gh.ok ())
             {
-              graphics_object go = gh_manager::get_object (gh);
+              graphics_object go = gh_mgr.get_object (gh);
 
               if (max_arg_index >= 2
                   && compare_property_values (go.get (pname), args(2)))
@@ -13923,9 +14363,9 @@
     {
       if (true)
         {
-          gh_manager::auto_lock guard;
-
-          graphics_handle gh = gh_manager::lookup (h);
+          octave::autolock guard (gh_mgr.graphics_lock ());
+
+          graphics_handle gh = gh_mgr.lookup (h);
 
           if (gh.ok ())
             {
@@ -13954,8 +14394,8 @@
   return ovl ();
 }
 
-DEFUN (__zoom__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__zoom__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} __zoom__ (@var{axes}, @var{mode}, @var{factor})
 @deftypefnx {} {} __zoom__ (@var{axes}, "out")
 @deftypefnx {} {} __zoom__ (@var{axes}, "reset")
@@ -13969,14 +14409,16 @@
 
   double h = args(0).double_value ();
 
-  gh_manager::auto_lock guard;
-
-  graphics_handle handle = gh_manager::lookup (h);
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
+
+  graphics_handle handle = gh_mgr.lookup (h);
 
   if (! handle.ok ())
     error ("__zoom__: invalid handle");
 
-  graphics_object ax = gh_manager::get_object (handle);
+  graphics_object ax = gh_mgr.get_object (handle);
 
   axes::properties& ax_props
     = dynamic_cast<axes::properties&> (ax.get_properties ());
@@ -14008,8 +14450,8 @@
   return ovl ();
 }
 
-DEFUN (__get_frame__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__get_frame__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {@var{cdata} =} __get_frame__ (@var{hfig})
 Internal function.
 
@@ -14022,12 +14464,15 @@
 
   double h = args(0).xdouble_value ("__get_frame__: HFIG is not a handle");
 
-  graphics_object go = gh_manager::get_object (h);
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  graphics_object go = gh_mgr.get_object (h);
+
   if (! go || ! go.isa ("figure"))
     error ("__get_frame__: HFIG is not a figure");
 
   // For Matlab compatibility, getframe must flush the event queue.
-  gh_manager::process_events ();
+  gh_mgr.process_events ();
 
   return ovl (go.get_toolkit ().get_pixels (go));
 }
--- a/libinterp/corefcn/graphics.in.h	Wed Aug 07 12:57:25 2019 -0700
+++ b/libinterp/corefcn/graphics.in.h	Fri Aug 09 10:36:08 2019 -0400
@@ -3667,7 +3667,7 @@
       radio_property ticklabelinterpreter u , "{tex}|latex|none"
       array_property ticklength u , default_axes_ticklength ()
       array_property tightinset r , Matrix (1, 4, 0.0)
-      handle_property title SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false, false)
+      handle_property title SOf , make_graphics_handle ("text", __myhandle__, false, false, false)
       double_property titlefontsizemultiplier u , 1.1
       radio_property titlefontweight u , "{bold}|normal"
       // FIXME: uicontextmenu should be moved here.
@@ -3678,7 +3678,7 @@
       radio_property xcolormode , "{auto}|manual"
       radio_property xdir u , "{normal}|reverse"
       bool_property xgrid , "off"
-      handle_property xlabel SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false, false)
+      handle_property xlabel SOf , make_graphics_handle ("text", __myhandle__, false, false, false)
       row_vector_property xlim mu , default_lim ()
       radio_property xlimmode al , "{auto}|manual"
       bool_property xminorgrid , "off"
@@ -3695,7 +3695,7 @@
       radio_property ycolormode , "{auto}|manual"
       radio_property ydir u , "{normal}|reverse"
       bool_property ygrid , "off"
-      handle_property ylabel SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false, false)
+      handle_property ylabel SOf , make_graphics_handle ("text", __myhandle__, false, false, false)
       row_vector_property ylim mu , default_lim ()
       radio_property ylimmode al , "{auto}|manual"
       bool_property yminorgrid , "off"
@@ -3710,7 +3710,7 @@
       radio_property zcolormode , "{auto}|manual"
       radio_property zdir u , "{normal}|reverse"
       bool_property zgrid , "off"
-      handle_property zlabel SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false, false)
+      handle_property zlabel SOf , make_graphics_handle ("text", __myhandle__, false, false, false)
       row_vector_property zlim mu , default_lim ()
       radio_property zlimmode al , "{auto}|manual"
       bool_property zminorgrid , "off"
@@ -6203,119 +6203,116 @@
   // FIXME: eventually eliminate these static functions and access
   // gh_manager object through the interpreter.
 
-  static gh_manager& instance (void);
-
-  static graphics_handle get_handle (bool integer_figure_handle)
-  {
-    return instance().do_get_handle (integer_figure_handle);
-  }
-
-  static void free (const graphics_handle& h, bool from_root = false)
-  {
-    instance().do_free (h, from_root);
-  }
-
-  static void renumber_figure (const graphics_handle& old_gh,
-                               const graphics_handle& new_gh)
-  {
-    instance().do_renumber_figure (old_gh, new_gh);
-  }
-
-  static graphics_handle lookup (double val)
-  {
-    return instance().do_lookup (val);
-  }
-
-  static graphics_handle lookup (const octave_value& val)
+  graphics_handle get_handle (bool integer_figure_handle);
+
+  void free (const graphics_handle& h, bool from_root = false);
+
+  void renumber_figure (const graphics_handle& old_gh,
+                           const graphics_handle& new_gh);
+
+  graphics_handle lookup (double val) const
+  {
+    const_iterator p = (octave::math::isnan (val)
+                        ? m_handle_map.end () : m_handle_map.find (val));
+
+    return (p != m_handle_map.end ()) ? p->first : graphics_handle ();
+  }
+
+  graphics_handle lookup (const octave_value& val) const
   {
     return (val.is_real_scalar ()
             ? lookup (val.double_value ()) : graphics_handle ());
   }
 
-  static graphics_object get_object (double val)
+  graphics_object get_object (double val) const
   {
     return get_object (lookup (val));
   }
 
-  static graphics_object get_object (const graphics_handle& h)
-  {
-    return instance().do_get_object (h);
-  }
-
-  static graphics_handle
-  make_graphics_handle (const std::string& go_name,
-                        const graphics_handle& parent,
-                        bool integer_figure_handle = false,
-                        bool do_createfcn = true,
-                        bool do_notify_toolkit = true)
-  {
-    return instance().do_make_graphics_handle (go_name, parent,
-                                               integer_figure_handle,
-                                               do_createfcn,
-                                               do_notify_toolkit);
-  }
-
-  static graphics_handle make_figure_handle (double val,
-                                             bool do_notify_toolkit = true)
-  {
-    return instance().do_make_figure_handle (val, do_notify_toolkit);
-  }
-
-  static void push_figure (const graphics_handle& h)
-  {
-    instance().do_push_figure (h);
-  }
-
-  static void pop_figure (const graphics_handle& h)
-  {
-    instance().do_pop_figure (h);
-  }
-
-  static graphics_handle current_figure (void)
-  {
-    return instance().do_current_figure ();
-  }
-
-  static Matrix handle_list (bool show_hidden = false)
-  {
-    return instance().do_handle_list (show_hidden);
-  }
-
-  static void lock (void)
-  {
-    instance().do_lock ();
-  }
-
-  static bool try_lock (void)
-  {
-    return instance().do_try_lock ();
-  }
-
-  static void unlock (void)
-  {
-    instance().do_unlock ();
-  }
-
-  static Matrix figure_handle_list (bool show_hidden = false)
-  {
-    return instance().do_figure_handle_list (show_hidden);
-  }
-
-  static void execute_listener (const graphics_handle& h,
-                                const octave_value& l)
-  {
-    instance().do_execute_listener (h, l);
-  }
-
-  static void execute_callback (const graphics_handle& h,
-                                const std::string& name,
-                                const octave_value& data = Matrix ())
+  graphics_object get_object (const graphics_handle& h) const
+  {
+    const_iterator p = (h.ok () ? m_handle_map.find (h) : m_handle_map.end ());
+
+    return (p != m_handle_map.end ()) ? p->second : graphics_object ();
+  }
+
+graphics_handle make_graphics_handle (const std::string& go_name,
+                                      const graphics_handle& p,
+                                      bool integer_figure_handle = false,
+                                      bool call_createfcn = true,
+                                      bool notify_toolkit = true);
+
+  graphics_handle make_figure_handle (double val,
+                                      bool notify_toolkit = true);
+
+  void push_figure (const graphics_handle& h);
+
+  void pop_figure (const graphics_handle& h);
+
+  graphics_handle current_figure (void) const
+  {
+    graphics_handle retval;
+
+    for (const auto& hfig : m_figure_list)
+      {
+        if (is_handle_visible (hfig))
+          retval = hfig;
+      }
+
+    return retval;
+  }
+
+  Matrix handle_list (bool show_hidden = false)
+  {
+    Matrix retval (1, m_handle_map.size ());
+
+    octave_idx_type i = 0;
+    for (const auto& h_iter : m_handle_map)
+      {
+        graphics_handle h = h_iter.first;
+
+        if (show_hidden || is_handle_visible (h))
+          retval(i++) = h.value ();
+      }
+
+    retval.resize (1, i);
+
+    return retval;
+  }
+
+  void lock (void) { m_graphics_lock.lock (); }
+
+  bool try_lock (void) { return m_graphics_lock.try_lock (); }
+
+  void unlock (void) { m_graphics_lock.unlock (); }
+
+  Matrix figure_handle_list (bool show_hidden = false)
+  {
+    Matrix retval (1, m_figure_list.size ());
+
+    octave_idx_type i = 0;
+    for (const auto& hfig : m_figure_list)
+      {
+        if (show_hidden || is_handle_visible (hfig))
+          retval(i++) = hfig.value ();
+      }
+
+    retval.resize (1, i);
+
+    return retval;
+  }
+
+  void execute_listener (const graphics_handle& h, const octave_value& l);
+
+  void execute_callback (const graphics_handle& h,
+                         const std::string& name,
+                         const octave_value& data = Matrix ())
   {
     octave_value cb;
 
     if (true)
       {
-        gh_manager::auto_lock lock;
+        octave::autolock guard (graphics_lock ());
 
         graphics_object go = get_object (h);
 
@@ -6326,48 +6323,23 @@
     execute_callback (h, cb, data);
   }
 
-  static void execute_callback (const graphics_handle& h,
-                                const octave_value& cb,
-                                const octave_value& data = Matrix ())
-  {
-    instance().do_execute_callback (h, cb, data);
-  }
-
-  static void post_callback (const graphics_handle& h,
-                             const std::string& name,
-                             const octave_value& data = Matrix ())
-  {
-    instance().do_post_callback (h, name, data);
-  }
-
-  static void post_function (graphics_event::event_fcn fcn, void *data = nullptr)
-  {
-    instance().do_post_function (fcn, data);
-  }
-
-  static void post_set (const graphics_handle& h, const std::string& name,
-                        const octave_value& value, bool notify_toolkit = true,
-                        bool redraw_figure = false)
-  {
-    instance().do_post_set (h, name, value, notify_toolkit, redraw_figure);
-  }
-
-  static int process_events (void)
-  {
-    return instance().do_process_events ();
-  }
-
-  static int flush_events (void)
-  {
-    return instance().do_process_events (true);
-  }
-
-  static void enable_event_processing (bool enable = true)
-  {
-    instance().do_enable_event_processing (enable);
-  }
-
-  static bool is_handle_visible (const graphics_handle& h)
+  void execute_callback (const graphics_handle& h, const octave_value& cb,
+                         const octave_value& data = Matrix ());
+
+  void post_callback (const graphics_handle& h, const std::string& name,
+                      const octave_value& data = Matrix ());
+
+  void post_function (graphics_event::event_fcn fcn, void *fcn_data = nullptr);
+
+  void post_set (const graphics_handle& h, const std::string& name,
+                 const octave_value& value, bool notify_toolkit = true,
+                 bool redraw_figure = false);
+
+  int process_events (bool force = false);
+
+  void enable_event_processing (bool enable = true);
+
+  bool is_handle_visible (const graphics_handle& h) const
   {
     bool retval = false;
 
@@ -6379,25 +6351,16 @@
     return retval;
   }
 
-  static void close_all_figures (void)
-  {
-    instance().do_close_all_figures ();
-  }
-
-public:
-  class auto_lock : public octave::autolock
-  {
-  public:
-    auto_lock (bool wait = true)
-      : octave::autolock (instance().m_graphics_lock, wait)
-    { }
-
-    // No copying!
-
-    auto_lock (const auto_lock&) = delete;
-
-    auto_lock& operator = (const auto_lock&) = delete;
-  };
+  void close_all_figures (void);
+
+  void restore_gcbo (void);
+
+  void post_event (const graphics_event& e);
+
+  octave::mutex graphics_lock (void)
+  {
+    return m_graphics_lock;
+  }
 
 private:
 
@@ -6437,122 +6400,6 @@
 
   // A flag telling whether event processing must be constantly on.
   int m_event_processing;
-
-  graphics_handle do_get_handle (bool integer_figure_handle);
-
-  void do_free (const graphics_handle& h, bool from_root);
-
-  void do_renumber_figure (const graphics_handle& old_gh,
-                           const graphics_handle& new_gh);
-
-  graphics_handle do_lookup (double val)
-  {
-    iterator p = (octave::math::isnan (val)
-                  ? m_handle_map.end () : m_handle_map.find (val));
-
-    return (p != m_handle_map.end ()) ? p->first : graphics_handle ();
-  }
-
-  graphics_object do_get_object (const graphics_handle& h)
-  {
-    iterator p = (h.ok () ? m_handle_map.find (h) : m_handle_map.end ());
-
-    return (p != m_handle_map.end ()) ? p->second : graphics_object ();
-  }
-
-  graphics_handle do_make_graphics_handle (const std::string& go_name,
-                                           const graphics_handle& p,
-                                           bool integer_figure_handle,
-                                           bool do_createfcn,
-                                           bool do_notify_toolkit);
-
-  graphics_handle do_make_figure_handle (double val, bool do_notify_toolkit);
-
-  Matrix do_handle_list (bool show_hidden)
-  {
-    Matrix retval (1, m_handle_map.size ());
-
-    octave_idx_type i = 0;
-    for (const auto& h_iter : m_handle_map)
-      {
-        graphics_handle h = h_iter.first;
-
-        if (show_hidden || is_handle_visible (h))
-          retval(i++) = h.value ();
-      }
-
-    retval.resize (1, i);
-
-    return retval;
-  }
-
-  Matrix do_figure_handle_list (bool show_hidden)
-  {
-    Matrix retval (1, m_figure_list.size ());
-
-    octave_idx_type i = 0;
-    for (const auto& hfig : m_figure_list)
-      {
-        if (show_hidden || is_handle_visible (hfig))
-          retval(i++) = hfig.value ();
-      }
-
-    retval.resize (1, i);
-
-    return retval;
-  }
-
-  void do_push_figure (const graphics_handle& h);
-
-  void do_pop_figure (const graphics_handle& h);
-
-  graphics_handle do_current_figure (void) const
-  {
-    graphics_handle retval;
-
-    for (const auto& hfig : m_figure_list)
-      {
-        if (is_handle_visible (hfig))
-          retval = hfig;
-      }
-
-    return retval;
-  }
-
-  void do_lock (void) { m_graphics_lock.lock (); }
-
-  bool do_try_lock (void) { return m_graphics_lock.try_lock (); }
-
-  void do_unlock (void) { m_graphics_lock.unlock (); }
-
-  void do_execute_listener (const graphics_handle& h, const octave_value& l);
-
-  void do_execute_callback (const graphics_handle& h, const octave_value& cb,
-                            const octave_value& data);
-
-  void do_post_callback (const graphics_handle& h, const std::string& name,
-                         const octave_value& data);
-
-  void do_post_function (graphics_event::event_fcn fcn, void *fcn_data);
-
-  void do_post_set (const graphics_handle& h, const std::string& name,
-                    const octave_value& value, bool notify_toolkit = true,
-                    bool redraw_figure = false);
-
-  int do_process_events (bool force = false);
-
-  void do_close_all_figures (void);
-
-  static void restore_gcbo (void)
-  {
-    instance().do_restore_gcbo ();
-  }
-
-  void do_restore_gcbo (void);
-
-  void do_post_event (const graphics_event& e);
-
-  void do_enable_event_processing (bool enable = true);
 };
 
 void get_children_limits (double& min_val, double& max_val,
--- a/libinterp/corefcn/input.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libinterp/corefcn/input.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -550,7 +550,7 @@
 
         try
           {
-            Fdrawnow ();
+            Fdrawnow (m_interpreter);
           }
         catch (const execution_exception& e)
           {
--- a/libinterp/corefcn/interpreter.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libinterp/corefcn/interpreter.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -556,6 +556,8 @@
   interpreter::~interpreter (void)
   {
     cleanup ();
+
+    delete m_gh_manager;
   }
 
   void interpreter::intern_nargin (octave_idx_type nargs)
@@ -1070,7 +1072,7 @@
     if (! command_history::ignoring_entries ())
       OCTAVE_SAFE_CALL (command_history::clean_up_and_save, ());
 
-    OCTAVE_SAFE_CALL (gh_manager::close_all_figures, ());
+    OCTAVE_SAFE_CALL (m_gh_manager->close_all_figures, ());
 
     m_gtk_manager.unload_all_toolkits ();
 
--- a/libinterp/corefcn/sysdep.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libinterp/corefcn/sysdep.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -1084,8 +1084,8 @@
 
 // FIXME: perhaps kbhit should also be able to print a prompt?
 
-DEFUN (kbhit, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (kbhit, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} kbhit ()
 @deftypefnx {} {} kbhit (1)
 Read a single keystroke from the keyboard.
@@ -1114,7 +1114,7 @@
 {
   // FIXME: add timeout and default value args?
 
-  Fdrawnow ();
+  Fdrawnow (interp);
 
   int c = octave::kbhit (args.length () == 0);
 
@@ -1129,8 +1129,8 @@
 // State of the pause system
 static bool Vpause_enabled = true;
 
-DEFUN (pause, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (pause, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} pause ()
 @deftypefnx {} {} pause (@var{n})
 @deftypefnx {} {@var{old_state} =} pause ("on")
@@ -1218,7 +1218,7 @@
         warning ("pause: NaN is an invalid delay");
       else
         {
-          Fdrawnow ();
+          Fdrawnow (interp);
 
           octave::sleep (dval, true);
         }
--- a/libinterp/corefcn/utils.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libinterp/corefcn/utils.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -1307,8 +1307,11 @@
 
     // Allow free access to graphics resources while the interpreter thread
     // is asleep
+
+    gh_manager& gh_mgr = __get_gh_manager__ ("sleep");
+
     if (do_graphics_events)
-      gh_manager::unlock ();
+      gh_mgr.unlock ();
 
     if (math::isinf (seconds))
       {
@@ -1325,7 +1328,7 @@
             octave_quit ();
 
             if (do_graphics_events)
-              gh_manager::process_events ();
+              gh_mgr.process_events ();
 
             c = kbhit (false);
           }
@@ -1346,7 +1349,7 @@
 
             if (do_graphics_events)
               {
-                gh_manager::process_events ();
+                gh_mgr.process_events ();
 
                 now.stamp ();
                 remaining_time = end_time - now.double_value ();
--- a/libinterp/dldfcn/__init_fltk__.cc	Wed Aug 07 12:57:25 2019 -0700
+++ b/libinterp/dldfcn/__init_fltk__.cc	Fri Aug 09 10:36:08 2019 -0400
@@ -93,6 +93,7 @@
 #include "gl2ps-print.h"
 #include "graphics.h"
 #include "gtk-manager.h"
+#include "interpreter-private.h"
 #include "interpreter.h"
 #include "oct-map.h"
 #include "oct-opengl.h"
@@ -152,13 +153,17 @@
 
   void print (const std::string& cmd, const std::string& term)
   {
-    octave::gl2ps_print (m_glfcns, gh_manager::get_object (m_number),
-                         cmd, term);
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("OpenGL_fltk::print");
+
+    octave::gl2ps_print (m_glfcns, gh_mgr.get_object (m_number), cmd, term);
   }
 
   uint8NDArray get_pixels (void)
   {
-    m_renderer.draw (gh_manager::get_object (m_number));
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("OpenGL_fltk::get_pixels");
+
+    m_renderer.draw (gh_mgr.get_object (m_number));
+
     return m_renderer.get_pixels (w (), h ());
   }
 
@@ -219,7 +224,9 @@
         m_glfcns.glViewport (0, 0, w (), h ());
       }
 
-    m_renderer.draw (gh_manager::get_object (m_number));
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("OpenGL_fltk::draw");
+
+    m_renderer.draw (gh_mgr.get_object (m_number));
 
     if (zoom ())
       overlay ();
@@ -398,7 +405,10 @@
 
     for (octave_idx_type ii = 0; ii < uimenu_childs.numel (); ii++)
       {
-        graphics_object kidgo = gh_manager::get_object (uimenu_childs (ii));
+        gh_manager& gh_mgr
+          = octave::__get_gh_manager__ ("fltk_uimenu::do_find_uimenu_children");
+
+        graphics_object kidgo = gh_mgr.get_object (uimenu_childs (ii));
 
         if (kidgo.valid_object () && kidgo.isa ("uimenu"))
           {
@@ -625,9 +635,12 @@
     update_visible (uimenup);
     update_seperator (uimenup);
 
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("fltk_uimenu::add_to_menu");
+
     for (octave_idx_type ii = 0; ii < len; ii++)
       {
-        graphics_object kgo = gh_manager::get_object (kids (len - (ii + 1)));
+        graphics_object kgo = gh_mgr.get_object (kids (len - (ii + 1)));
+
         if (kgo.valid_object ())
           {
             uimenu::properties& kprop = dynamic_cast<uimenu::properties&>
@@ -647,7 +660,7 @@
     // create any delayed menus
     for (size_t ii = 0; ii < delayed_menus.size (); ii++)
       {
-        graphics_object kgo = gh_manager::get_object (kids (delayed_menus[ii]));
+        graphics_object kgo = gh_mgr.get_object (kids (delayed_menus[ii]));
 
         if (kgo.valid_object ())
           {
@@ -665,10 +678,14 @@
     Matrix kids = find_uimenu_children (figp);
     int len = kids.numel ();
     int count = 0;
+
     m_menubar->clear ();
+
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("fltk_uimenu::add_to_menu");
+
     for (octave_idx_type ii = 0; ii < len; ii++)
       {
-        graphics_object kgo = gh_manager::get_object (kids (len - (ii + 1)));
+        graphics_object kgo = gh_mgr.get_object (kids (len - (ii + 1)));
 
         if (kgo.valid_object ())
           {
@@ -690,7 +707,7 @@
     // create any delayed menus
     for (size_t ii = 0; ii < delayed_menus.size (); ii++)
       {
-        graphics_object kgo = gh_manager::get_object (kids (delayed_menus[ii]));
+        graphics_object kgo = gh_mgr.get_object (kids (delayed_menus[ii]));
 
         if (kgo.valid_object ())
           {
@@ -710,9 +727,11 @@
     kids = find_uimenu_children (prop);
     int len = kids.numel ();
 
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("fltk_uimenu::remove_from_menu");
+
     for (octave_idx_type ii = 0; ii < len; ii++)
       {
-        graphics_object kgo = gh_manager::get_object (kids (len - (ii + 1)));
+        graphics_object kgo = gh_mgr.get_object (kids (len - (ii + 1)));
 
         if (kgo.valid_object ())
           {
@@ -910,7 +929,9 @@
 
   void uimenu_update (const graphics_handle& gh, int id)
   {
-    graphics_object uimenu_obj = gh_manager::get_object (gh);
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("plot_window::uimenu_update");
+
+    graphics_object uimenu_obj = gh_mgr.get_object (gh);
 
     if (uimenu_obj.valid_object () && uimenu_obj.isa ("uimenu"))
       {
@@ -1128,9 +1149,14 @@
         graphics_handle gh = m_fp.get_currentaxes ();
         if (gh.ok ())
           {
-            graphics_object go = gh_manager::get_object (gh);
+            gh_manager& gh_mgr
+              = octave::__get_gh_manager__ ("plot_window::set_on_ax_obj");
+
+            graphics_object go = gh_mgr.get_object (gh);
+
             axes::properties& ap
               = dynamic_cast<axes::properties&>(go.get_properties ());
+
             ap.set (name, value);
           }
       }
@@ -1161,7 +1187,9 @@
   void pixel2pos (const graphics_handle& ax, int px, int py, double& xx,
                   double& yy) const
   {
-    pixel2pos (gh_manager::get_object (ax), px, py, xx, yy);
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("plot_window::pixel2pos");
+
+    pixel2pos (gh_mgr.get_object (ax), px, py, xx, yy);
   }
 
   void pixel2pos (graphics_object ax, int px, int py, double& xx,
@@ -1182,13 +1210,15 @@
     Matrix kids = m_fp.get_children ();
     int len = kids.numel ();
 
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("plot_window::pixel2axes_or_ca");
+
     for (int k = 0; k < len; k++)
       {
-        graphics_handle hnd = gh_manager::lookup (kids(k));
+        graphics_handle hnd = gh_mgr.lookup (kids(k));
 
         if (hnd.ok ())
           {
-            graphics_object kid = gh_manager::get_object (hnd);
+            graphics_object kid = gh_mgr.get_object (hnd);
 
             if (kid.valid_object () && kid.isa ("axes"))
               {
@@ -1208,7 +1238,9 @@
   void pixel2status (const graphics_handle& ax, int px0, int py0,
                      int px1 = -1, int py1 = -1)
   {
-    pixel2status (gh_manager::get_object (ax), px0, py0, px1, py1);
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("plot_window::pixel2status");
+
+    pixel2status (gh_mgr.get_object (ax), px0, py0, px1, py1);
   }
 
   void pixel2status (graphics_object ax, int px0, int py0,
@@ -1253,8 +1285,14 @@
       {
         Matrix pos = m_fp.map_from_boundingbox (px, py);
         m_fp.set_currentpoint (pos);
-        graphics_object robj = gh_manager::get_object (m_fp.get_parent ());
+
+        gh_manager& gh_mgr
+          = octave::__get_gh_manager__ ("plot_window::set_currentpoint");
+
+        graphics_object robj = gh_mgr.get_object (m_fp.get_parent ());
+
         root_figure::properties& rp
+
           = dynamic_cast<root_figure::properties&> (robj.get_properties ());
         rp.set_currentfigure (m_fp.get___myhandle__ ().value ());
       }
@@ -1468,6 +1506,8 @@
         // See Event Propagation http://www.fltk.org/doc-1.3/events.html
         static bool key_resent_detected = false;
 
+        gh_manager& gh_mgr = octave::__get_gh_manager__ ("plot_window::handle");
+
         switch (event)
           {
           case FL_SHORTCUT:
@@ -1512,7 +1552,7 @@
 
                       if (gh.ok ())
                         {
-                          m_ax_obj = gh_manager::get_object (gh);
+                          m_ax_obj = gh_mgr.get_object (gh);
                           set_axes_currentpoint (m_ax_obj, m_pos_x, m_pos_y);
                         }
                     }
@@ -1612,7 +1652,7 @@
 
               if (gh.ok ())
                 {
-                  m_ax_obj = gh_manager::get_object (gh);
+                  m_ax_obj = gh_mgr.get_object (gh);
                   set_axes_currentpoint (m_ax_obj, m_pos_x, m_pos_y);
                 }
 
@@ -1718,9 +1758,9 @@
             case FL_MOUSEWHEEL:
               {
                 graphics_object ax
-                  = gh_manager::get_object (pixel2axes_or_ca (Fl::event_x (),
-                                                              Fl::event_y ()
-                                                              - menu_dy ()));
+                  = gh_mgr.get_object (pixel2axes_or_ca (Fl::event_x (),
+                                                            Fl::event_y ()
+                                                            - menu_dy ()));
                 if (ax && ax.isa ("axes"))
                   {
                     axes::properties& ap
@@ -2188,7 +2228,10 @@
 
   static int hnd2idx (double h)
   {
-    graphics_object fobj = gh_manager::get_object (h);
+    gh_manager& gh_mgr = octave::__get_gh_manager__ ("figure_manager::hnd2idx");
+
+    graphics_object fobj = gh_mgr.get_object (h);
+
     if (fobj &&  fobj.isa ("figure"))
       {
         figure::properties& fp
@@ -2259,7 +2302,11 @@
         uimenu::properties& uimenup
           = dynamic_cast<uimenu::properties&> (uimenu_obj.get_properties ());
         std::string fltk_label = uimenup.get_label ();
-        graphics_object go = gh_manager::get_object (uimenu_obj.get_parent ());
+
+        gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
+
+        graphics_object go = gh_mgr.get_object (uimenu_obj.get_parent ());
+
         if (go.isa ("uimenu"))
           fltk_label = dynamic_cast<const uimenu::properties&>
                        (go.get_properties ()).get___fltk_label__ ()
@@ -2339,7 +2386,11 @@
   void redraw_figure (const graphics_object& go) const
   {
     // We scan all figures and add those which use FLTK.
-    graphics_object obj = gh_manager::get_object (0);
+
+    gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
+
+    graphics_object obj = gh_mgr.get_object (0);
+
     if (obj && obj.isa ("root"))
       {
         base_properties& props = obj.get_properties ();
@@ -2347,7 +2398,8 @@
 
         for (octave_idx_type n = 0; n < children.numel (); n++)
           {
-            graphics_object fobj = gh_manager::get_object (children (n));
+            graphics_object fobj = gh_mgr.get_object (children (n));
+
             if (fobj && fobj.isa ("figure"))
               {
                 figure::properties& fp
@@ -2430,8 +2482,8 @@
 
 #endif
 
-DEFUN_DLD (__fltk_check__, , ,
-           doc: /* -*- texinfo -*-
+DEFMETHOD_DLD (__fltk_check__, interp, , ,
+               doc: /* -*- texinfo -*-
 @deftypefn {} {} __fltk_check__ ()
 Undocumented internal function.  Calls Fl::check ()
 @end deftypefn */)
@@ -2440,7 +2492,7 @@
   Fl::check ();
 
   if (Vdrawnow_requested)
-    Fdrawnow ();
+    Fdrawnow (interp);
 
   return octave_value_list ();
 #else