changeset 26520:278ae90567a7 stable

Don't use C++ callback to notify close request from Qt Figures (bug #54187) * Figure.h/cc (Figure::close_figure_callback): Remove callback. (Figure::eventNotifyBefore): Use gh_manager::post_callback rather than octave_link::post_event to notify that a figure should be closed. * graphics.in.h (graphics_event::create_mcode_event): New static function. * graphics.cc (mcode_event): New class to handle direct mcode evaluation. (gh_manager::do_post_callback): For "closerequestfcn" callback, create an mcode_event and use the "close" function to make the figure current before evaluating the actual closerequestfcn.
author Pantxo Diribarne <pantxo.diribarne@gmail.com>
date Fri, 11 Jan 2019 18:14:41 +0100
parents 9ed51ca68352
children 8b0c9dc0799a d6a4237a26b4
files libgui/graphics/Figure.cc libgui/graphics/Figure.h libinterp/corefcn/graphics.cc libinterp/corefcn/graphics.in.h
diffstat 4 files changed, 60 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/graphics/Figure.cc	Fri Jan 11 16:57:58 2019 +0100
+++ b/libgui/graphics/Figure.cc	Fri Jan 11 18:14:41 2019 +0100
@@ -650,15 +650,6 @@
                           prop == "position");
   }
 
-  void
-  Figure::close_figure_callback (void)
-  {
-    figure::properties& fp = properties<figure> ();
-    octave_value fnum = fp.get___myhandle__ ().as_octave_value ();
-
-    Ffeval (ovl ("close", fnum));
-  }
-
   bool
   Figure::eventNotifyBefore (QObject *obj, QEvent *xevent)
   {
@@ -697,7 +688,7 @@
               {
               case QEvent::Close:
                 xevent->ignore ();
-                octave_link::post_event (this, &Figure::close_figure_callback);
+                gh_manager::post_callback (m_handle, "closerequestfcn");
                 return true;
 
               default:
--- a/libgui/graphics/Figure.h	Fri Jan 11 16:57:58 2019 +0100
+++ b/libgui/graphics/Figure.h	Fri Jan 11 18:14:41 2019 +0100
@@ -108,8 +108,6 @@
     void updateFigureToolBarAndMenuBar (void);
     void set_geometry (QRect r);
 
-    void close_figure_callback (void);
-
     void enableMouseTracking (void);
 
   private slots:
--- a/libinterp/corefcn/graphics.cc	Fri Jan 11 16:57:58 2019 +0100
+++ b/libinterp/corefcn/graphics.cc	Fri Jan 11 18:14:41 2019 +0100
@@ -11358,6 +11358,38 @@
 };
 
 class
+mcode_event : public base_graphics_event
+{
+public:
+  mcode_event (const graphics_handle& h, const std::string& cmd,
+               int busyaction = base_graphics_event::QUEUE)
+    : base_graphics_event (busyaction), handle (h), mcode (cmd)
+  { }
+
+  void execute (void)
+  {
+    if (! mcode.empty ())
+      {
+        graphics_object go = gh_manager::get_object (handle);
+        if (go.valid_object ())
+          {
+            octave_value cb (mcode);
+            gh_manager::execute_callback (handle, cb);
+          }
+      }
+  }
+
+private:
+  mcode_event (void)
+    : base_graphics_event (), handle (), mcode ()
+  { }
+
+private:
+  graphics_handle handle;
+  std::string mcode;
+};
+
+class
 function_event : public base_graphics_event
 {
 public:
@@ -11481,6 +11513,14 @@
 }
 
 graphics_event
+graphics_event::create_mcode_event (const graphics_handle& h,
+                                    const std::string& cmd,
+                                    int busyaction)
+{
+  return graphics_event (new mcode_event (h, cmd, busyaction));
+}
+
+graphics_event
 graphics_event::create_function_event (graphics_event::event_fcn fcn,
                                        void *data)
 {
@@ -11562,7 +11602,6 @@
         }
 
       // Copy CB because "function_value" method is non-const.
-
       octave_value cb = cb_arg;
 
       if (cb.is_function () || cb.is_function_handle ())
@@ -11659,22 +11698,26 @@
       caseless_str cname (name);
       int busyaction = base_graphics_event::QUEUE;
 
-      if (cname.compare ("deletefcn")
-          || cname.compare ("createfcn")
-          || (go.isa ("figure")
-              && cname.compare ("closerequestfcn"))
-          || ((go.isa ("figure")
-               || go.isa ("uipanel")
+      if (cname == "deletefcn" || cname == "createfcn"
+          || cname == "closerequestfcn"
+          || ((go.isa ("figure") || go.isa ("uipanel")
                || go.isa ("uibuttongroup"))
-              && (cname.compare ("resizefcn")
-                  || cname.compare ("sizechangedfcn"))))
+              && (cname == "resizefcn" || cname == "sizechangedfcn")))
         busyaction = base_graphics_event::INTERRUPT;
       else if (go.get_properties ().get_busyaction () == "cancel")
         busyaction = base_graphics_event::CANCEL;
 
-
-      do_post_event (graphics_event::create_callback_event (h, name, data,
-                                                            busyaction));
+      // The "closerequestfcn" callback must be executed once the figure has
+      // been made current. Let "close" do the job.
+      if (cname == "closerequestfcn")
+        {
+          std::string cmd ("close (gcbf ());");
+          do_post_event (graphics_event::create_mcode_event (h, cmd,
+                                                             busyaction));
+        }
+      else
+        do_post_event (graphics_event::create_callback_event (h, name, data,
+                                                              busyaction));
     }
 }
 
--- a/libinterp/corefcn/graphics.in.h	Fri Jan 11 16:57:58 2019 +0100
+++ b/libinterp/corefcn/graphics.in.h	Fri Jan 11 18:14:41 2019 +0100
@@ -6161,6 +6161,10 @@
                          int busyaction = base_graphics_event::QUEUE);
 
   static graphics_event
+  create_mcode_event (const graphics_handle& h, const std::string& cmd,
+                      int busyaction);
+
+  static graphics_event
   create_function_event (event_fcn fcn, void *data = nullptr);
 
   static graphics_event