# HG changeset patch
# User Pantxo Diribarne <pantxo.diribarne@gmail.com>
# Date 1540218846 -7200
#      Mon Oct 22 16:34:06 2018 +0200
# Node ID 1f4119cc38599e75025e9bccff7844496db65531
# Parent  91711db98d8aee8055de296b90a2193dfb6bdae8
Allow graphics events to be processed while pause is active (bug #53729)

* util.h/cc (octave::sleep): Add second argument "do_graphics_events" that
  defaults to false. Depending on do_graphics_events, unlock the graphics mutex
  and call gh_manager::process_events after each time laps. When the requested
  time is infinite, call octave::kbhit after each time laps and interrupt if
  a character was typed.

* sysdep.cc (Fpause): Without argument, set time value to inf. Call
  octave::sleep with the second argument true. Document that graphics events
  are handled even though the program is paused.

diff -r 91711db98d8a -r 1f4119cc3859 libinterp/corefcn/sysdep.cc
--- a/libinterp/corefcn/sysdep.cc	Wed Oct 17 21:53:23 2018 +0200
+++ b/libinterp/corefcn/sysdep.cc	Mon Oct 22 16:34:06 2018 +0200
@@ -1084,6 +1084,9 @@
 @end group
 @end example
 
+While the program is supended, Octave still handles figures painting and 
+graphics callbacks execution.
+
 @seealso{kbhit}
 @end deftypefn */)
 {
@@ -1092,32 +1095,22 @@
   if (nargin > 1)
     print_usage ();
 
-  if (nargin == 1)
-    {
-      double dval = args(0).double_value ();
+  double dval;
+  
+  if (nargin == 0)
+    dval = octave_Inf;
+  else
+    dval = args(0).xdouble_value ("pause: N must be a scalar double value");
 
-      if (octave::math::isnan (dval))
-        warning ("pause: NaN is an invalid delay");
-      else
-        {
-          Fdrawnow ();
-
-          if (octave::math::isinf (dval))
-            {
-              octave::flush_stdout ();
-              octave::kbhit ();
-            }
-          else
-            octave::sleep (dval);
-        }
-    }
+  if (octave::math::isnan (dval))
+    warning ("pause: NaN is an invalid delay");
   else
     {
       Fdrawnow ();
-      octave::flush_stdout ();
-      octave::kbhit ();
+      
+      octave::sleep (dval, true);
     }
-
+      
   return ovl ();
 }
 
diff -r 91711db98d8a -r 1f4119cc3859 libinterp/corefcn/utils.cc
--- a/libinterp/corefcn/utils.cc	Wed Oct 17 21:53:23 2018 +0200
+++ b/libinterp/corefcn/utils.cc	Mon Oct 22 16:34:06 2018 +0200
@@ -52,6 +52,7 @@
 #include "dirfns.h"
 #include "error.h"
 #include "errwarn.h"
+#include "graphics.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
 #include "lex.h"
@@ -1270,55 +1271,89 @@
   // won't respond to SIGINT.  Maybe there is a better way than
   // breaking this up into multiple shorter intervals?
 
-  void sleep (double seconds)
+  void sleep (double seconds, bool do_graphics_events)
   {
     if (seconds <= 0)
       return;
 
-    // Split delay into whole seconds and the remainder as a decimal
-    // fraction.
-
-    double fraction = std::modf (seconds, &seconds);
-
-    // Further split the fractional seconds into whole tenths and the
-    // nearest number of nanoseconds remaining.
-
-    double tenths = 0;
-    fraction = std::modf (fraction * 10, &tenths) / 10;
-    fraction = std::round (fraction * 1000000000);
-
-    // Sleep for the hundredths portion.
-
-    struct timespec hundredths_delay = { 0, static_cast<long> (fraction) };
-
-    octave_nanosleep_wrapper (&hundredths_delay, nullptr);
-
-    // Sleep for the whole tenths portion, allowing interrupts every
-    // tenth.
-
-    struct timespec one_tenth = { 0, 100000000 };
-
-    for (int i = 0; i < static_cast<int> (tenths); i++)
+    // Allow free access to graphics resources while the interpreter thread
+    // is asleep
+    if (do_graphics_events)
+      gh_manager::unlock ();
+    
+    if (octave::math::isinf (seconds))
       {
-        octave_nanosleep_wrapper (&one_tenth, nullptr);
-
-        octave_quit ();
-      }
-
-    // Sleep for the whole seconds portion, allowing interrupts every
-    // tenth.
-
-    time_t sec = ((seconds > std::numeric_limits<time_t>::max ())
-                  ? std::numeric_limits<time_t>::max ()
-                  : static_cast<time_t> (seconds));
-
-    for (time_t s = 0; s < sec; s++)
-      {
-        for (int i = 0; i < 10; i++)
+        // Wait for kbhit
+        int c = -1;
+        octave::flush_stdout ();
+        
+        struct timespec one_tenth = { 0, 100000000 };
+        
+        while (c < 0)
           {
             octave_nanosleep_wrapper (&one_tenth, nullptr);
 
             octave_quit ();
+
+            if (do_graphics_events)
+              gh_manager::process_events ();
+
+            c = octave::kbhit (false);
+          }
+      }
+    else
+      {
+        // Split delay into whole seconds and the remainder as a decimal
+        // fraction.
+
+        double fraction = std::modf (seconds, &seconds);
+
+        // Further split the fractional seconds into whole tenths and the
+        // nearest number of nanoseconds remaining.
+
+        double tenths = 0;
+        fraction = std::modf (fraction * 10, &tenths) / 10;
+        fraction = std::round (fraction * 1000000000);
+
+        // Sleep for the hundredths portion.
+
+        struct timespec hundredths_delay = { 0, static_cast<long> (fraction) };
+
+        octave_nanosleep_wrapper (&hundredths_delay, nullptr);
+
+        // Sleep for the whole tenths portion, allowing interrupts every
+        // tenth.
+
+        struct timespec one_tenth = { 0, 100000000 };
+
+        for (int i = 0; i < static_cast<int> (tenths); i++)
+          {
+            octave_nanosleep_wrapper (&one_tenth, nullptr);
+
+            octave_quit ();
+
+            if (do_graphics_events)
+              gh_manager::process_events ();
+          }
+
+        // Sleep for the whole seconds portion, allowing interrupts every
+        // tenth.
+
+        time_t sec = ((seconds > std::numeric_limits<time_t>::max ())
+                      ? std::numeric_limits<time_t>::max ()
+                      : static_cast<time_t> (seconds));
+
+        for (time_t s = 0; s < sec; s++)
+          {
+            for (int i = 0; i < 10; i++)
+              {
+                octave_nanosleep_wrapper (&one_tenth, nullptr);
+
+                octave_quit ();
+
+                if (do_graphics_events)
+                  gh_manager::process_events ();
+              }
           }
       }
   }
diff -r 91711db98d8a -r 1f4119cc3859 libinterp/corefcn/utils.h
--- a/libinterp/corefcn/utils.h	Wed Oct 17 21:53:23 2018 +0200
+++ b/libinterp/corefcn/utils.h	Mon Oct 22 16:34:06 2018 +0200
@@ -116,7 +116,8 @@
 
   extern OCTINTERP_API std::string asprintf (const char *fmt, ...);
 
-  extern OCTINTERP_API void sleep (double seconds);
+  extern OCTINTERP_API void sleep (double seconds,
+                                   bool do_graphics_events = false);
 
   extern OCTINTERP_API
   octave_value_list
