bugGNU Octave - Bugs: bug #56110, Setting figure position is ignored...

 
 

bug #56110: Setting figure position is ignored when set before the figure is drawn

Submitter:  Lars Kindermann <larskindermann>
Submitted:  Tue 09 Apr 2019 01:18:06 PM UTC
   
 
Category:  Plotting with OpenGL Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Incorrect Result
Status:  Fixed Assigned to:  None
Originator Name:  Open/Closed:  * Closed
Release:  * dev Operating System:  * GNU/Linux
Fixed Release:  None Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Wed 13 Nov 2019 11:14:22 PM UTC, comment #21: 

Changing the status to "Ready for Test".

Could anyone else who was able to reproduce this on the dev branch please try again with a recent tip and see if the issue has been fixed for them as well?

Rik <rik5>
Group administrator
Wed 13 Nov 2019 10:57:45 PM UTC, comment #20: 

Just reporting hat the initial bug is fixed for me in the meantime. Probably by jwe's recent rewrite of graphics call logic.

Lars Kindermann <larskindermann>
Thu 03 Oct 2019 02:47:40 AM UTC, comment #19: 

I had the same problem with 4.4.1 on the same PC.

Wayne Stephenson <stepho>
Thu 03 Oct 2019 02:38:26 AM UTC, comment #18: 

I also get this problem with a simple install of 5.1.0 on Win7 and no tweaking of settings.

Sample code (all one line):

close all;figure;hold on;figure(gcf,"units","pixels","position",[10,100,1900,800]);plot( [1:10] );

This will display a large window 1900 pixels wide with the graph only in the top left portion (about the same size as before the resize).

If I type all the commands in one by one on separate lines then I get the desired wide window with a nice wide graph inside.

The same commands run from an m-file also show the problem, regardless of whether they are one line or separate lines.

Sometimes it works correctly for plots with many sample points and many lines (using hold on and many plot commands).

I suspect this is a timing issue.

Wayne Stephenson <stepho>
Sat 13 Apr 2019 10:04:04 PM UTC, comment #17: 

I think the system/window-manager dependant behavior may well be explained by a race condition: the creation of Figure objects is synchronous, but not its updates.

When the "position" is changed from the interpreter using "set", the Figure object changes geometry and posts back the actual size it managed to reach. Since that happens asynchronously in the GUI thread, the new graphics event may or may not have already been posted at the time "drawnow" is called from the interpreter thread. IOW sometimes "drawnow" will only find one event in the queue, the one posted during "figure" call, sometimes it will also  find the event posted after "set".


Pantxo Diribarne <pantxo>
Group Member
Fri 12 Apr 2019 03:57:21 PM UTC, comment #16: 

I agree that someone needs to test Pantxo's patch from comment #15.  Clearly something is different between our mental model of how the threads are interacting, and the actual behavior.

Rik <rik5>
Group administrator
Thu 11 Apr 2019 07:08:10 PM UTC, comment #15: 


>> Maybe the problem is more that figure() returns control to the interpreter too quickly (on some computers) while the GUI thread is still active preparing the figure.

This should not happen since we enforce synchronous execution using a Qt::BlockingQueuedConnection. For testing, the following diff (also attached as sync_test.diff) should always print: "step 1, 2, 3" after a figure is created


diff -r 34267e66915a libgui/graphics/Backend.cc
--- a/libgui/graphics/Backend.cc        Fri Nov 16 17:57:00 2018 +0100
+++ b/libgui/graphics/Backend.cc        Thu Apr 11 20:57:34 2019 +0200
@@ -111,8 +111,14 @@
         OCTAVE_PTR_TYPE tmp (reinterpret_cast<OCTAVE_INTPTR_TYPE> (proxy));
         gObj.get_properties ().set (toolkitObjectProperty (go), tmp);

+        if (go.isa ("figure"))
+          printf ("step 1, ");
+
         emit createObject (go.get_handle ().value ());

+        if (go.isa ("figure"))
+          printf ("3\n");
+
         return true;
       }

diff -r 34267e66915a libgui/graphics/Figure.cc
--- a/libgui/graphics/Figure.cc Fri Nov 16 17:57:00 2018 +0100
+++ b/libgui/graphics/Figure.cc Thu Apr 11 20:57:34 2019 +0200
@@ -149,6 +149,8 @@

     win->addReceiver (this);
     m_container->addReceiver (this);
+
+    printf ("2, ");
   }

   Figure::~Figure (void)



>> This would be consistent with the fact that pasting the code in to an Octave window works

No, I think that executing the code in the command window is equivalent to calling "gh_manager::process_events" after each line of code.

>> Could someone who can reproduce this try the following code which uses a pause() statement after figure creation to let the graphics system settle out.

Yes, this works since pause is equivalent to "gh_manager::process_events" and thus equivalent to the diff in comment #12

(file #46752)

Pantxo Diribarne <pantxo>
Group Member
Thu 11 Apr 2019 06:45:23 PM UTC, comment #14: 

Yes, tst_figpos2 fixes the problem shown with tst_figpos for me.

Mike Miller <mtmiller>
Group Member
Thu 11 Apr 2019 04:58:18 PM UTC, comment #13: 

I see what you're saying.  Annotated code


f1 = figure();
## When created in the GUI, there may be graphics events that are put in
## to the queue after creation by the GUI thread
pos1 = get(f1,"position")
pos1(1) = pos1(1) + 50;
pos1(2) = pos1(2) - 50;
pos1(3) = pos1(4) * 2
set(f1,"position",pos1) #before drawn
## get/set operations don't cause a queue flush
## So, "position" is now updated pos1, but drawnow is about to fire and
## run the queued event that returns position back to its starting value
drawnow
get(f1,"position")


Maybe the problem is more that figure() returns control to the interpreter too quickly (on some computers) while the GUI thread is still active preparing the figure.  In this scenario, the queued event would actually be flushed, but there simply hasn't been enough time for the GUI to grab a mutex, post the event, etc.  This would be consistent with the fact that pasting the code in to an Octave window works (because there are extra delays with parsing each command), but fails when the same code is in a script (parsed once, and then run as fast as possible).

Could someone who can reproduce this try the following code which uses a pause() statement after figure creation to let the graphics system settle out.


f1 = figure();
pause (0.1);
pos1 = get(f1,"position")
pos1(1) = pos1(1) + 50;
pos1(2) = pos1(2) - 50;
pos1(3) = pos1(4) * 2
set(f1,"position",pos1) #before drawn
drawnow
pos1_after = get(f1,"position")
if (! isequal (pos1, pos1_after))
  warning ("position1 after drawnow is different");
endif


The script is attached as tst_figpos2.m as well.


(file #46749)

Rik <rik5>
Group administrator
Thu 11 Apr 2019 08:50:22 AM UTC, comment #12: 

I am able to reproduce and the root cause is that the Qt Figure object (which lives in the GUI thread) uses the graphics event queue to communicate position changes to the interpreter thread. This means, after the figure is constructed, there is a new event in the queue that will tell the interpreter to fix the position to an eventually new value.

The following simple diff fixes the issue for me


diff -r ca0230d3efbf libgui/graphics/Backend.cc
--- a/libgui/graphics/Backend.cc        Mon Apr 08 09:22:39 2019 -0700
+++ b/libgui/graphics/Backend.cc        Thu Apr 11 10:42:30 2019 +0200
@@ -113,6 +113,10 @@

         emit createObject (go.get_handle ().value ());

+        // We need to process graphics events that have been pushed while
+        // initializing the GUI objects
+        gh_manager::process_events ();
+
         return true;
       }


What I don't understand is why this behavior is not deterministic. IOW I don't see how the graphics event can be executed before drawnow on some systems.

Pantxo Diribarne <pantxo>
Group Member
Tue 09 Apr 2019 11:17:49 PM UTC, comment #11: 

I tried gnome/xorg, gnome/wayland/ kde/xorg(?) -- no problem.
This is on Fedora 30, qt5.12.1

Dmitri.

Dmitri A. Sergatskov <dasergatskov>
Tue 09 Apr 2019 10:47:48 PM UTC, comment #10: 

Yuck.  This looks hard to debug.  Is there a way to separate whether Octave is calling Qt incorrectly versus whether there is something wrong within Qt?

I checked the positions of figure 1 and 2 after running tst_figpos and they are correctly the same as printing within the script.

I am not using Wayland.  Am using X.Org Xserver with nouveau driver.


Rik <rik5>
Group administrator
Tue 09 Apr 2019 09:41:40 PM UTC, comment #9: 

For my part, I can reproduce Lars' behavior with Octave 5.1 or with the default branch, using Qt 5.11 or 5.12, and running in GNOME 3.30 on Wayland, Qt is using XWayland.

If I force Qt to use Wayland with QT_QPA_PLATFORM=wayland-egl, then the position is reported the same before and after drawnow inside Rik's script, but the actual figure sizes are not correct after the script returns to the prompt.


>> tst_figpos
pos1 =

   300   200   560   420

pos1 =

   350   150   840   420

pos1_after =

   350   150   840   420

pos2 =

   300   200   560   420

pos2 =

   350   150   840   420

pos2_after =

   350   150   840   420

>> get (f1, "position")
ans =

   350   150   560   420

>> get (f2, "position")
ans =

   350   150   560   420


Mike Miller <mtmiller>
Group Member
Tue 09 Apr 2019 07:31:28 PM UTC, comment #8: 

I'm using Kubuntu 18.04 so KDE as the window manager and Qt-5.9.5 for the libraries.

Could be something that has been fixed since 4/2016 in Lars' case.

Rik <rik5>
Group administrator
Tue 09 Apr 2019 06:31:13 PM UTC, comment #7: 

I'm also using GNOME (version 3.30) with default window placement rules.

Mike Miller <mtmiller>
Group Member
Tue 09 Apr 2019 05:47:50 PM UTC, comment #6: 

I wonder if this is windows manager trying to do some kind of
"smart window placement"...
In any case I do not get this problem on Fedora 30 / gnome desktop.

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Tue 09 Apr 2019 05:11:56 PM UTC, comment #5: 

I get the same results as Lars.

Mike Miller <mtmiller>
Group Member
Tue 09 Apr 2019 04:40:59 PM UTC, comment #4: 

It only happens with "graphics_toolkit qt". fltk works fine, gnuplot has no warning but different windows, but I think that's expected. I'm building against Qt 5.5.1.

Lars Kindermann <larskindermann>
Tue 09 Apr 2019 04:24:28 PM UTC, comment #3: 

Running your script on my system (Xubuntu 16.04) both with "run-octave -f" and "run-octave -f --gui" still yields


>> tst_figpos

pos1 =

   300   200   560   420

pos1 =

   350   150   840   420

pos1_after =

   300   200   560   418

warning: position1 after drawnow is different
warning: called from
    tst_figpos at line 10 column 3
pos2 =

   300   200   560   420

pos2 =

   350   150   840   420

pos2_after =

   350   150   840   420

>>


Lars Kindermann <larskindermann>
Tue 09 Apr 2019 04:00:21 PM UTC, comment #2: 

Works for me.  I'm attaching your commands as a script for others to try.  I added a check that the positions are the same so that tester's don't have to manually scan the results.

I used


run-octave -f --gui


as well as


run-octave -f


to test GUI and CLI versions and both worked.


(file #46740)

Rik <rik5>
Group administrator
Tue 09 Apr 2019 02:20:19 PM UTC, comment #1: 

The code below works fine if you paste it into the command window, the problem appears only if run as a script.

Lars Kindermann <larskindermann>
Tue 09 Apr 2019 01:18:06 PM UTC, original submission:  

These two figures should have the same size and position, regardless when they are drawn:


f1 = figure();
pos1 = get(f1,"position")
pos1(1) = pos1(1) + 50;
pos1(2) = pos1(2) - 50;
pos1(3) = pos1(4) * 2
set(f1,"position",pos1) #before drawn
drawnow
get(f1,"position")

f2 = figure();
pos2 = get(f2,"position")
pos2(1) = pos2(1) + 50;
pos2(2) = pos2(2) - 50;
pos2(3) = pos2(4) * 2
drawnow
set(f2,"position",pos2) #after drawn
get(f2,"position")


but the position of the first figure is changed back by drawnow (and even not exactly to the initial settings):


pos1 = 300   200   560   420
pos1 = 350   150   840   420
ans  = 300   200   560   418

pos2 = 300   200   560   420
pos2 = 350   150   840   420
ans  = 350   150   840   420


As far as I remember, Matlab always behaves like the second example. Maybe somebody could check this...

Lars Kindermann <larskindermann>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #46752:  sync_test.diff added by pantxo (1KiB - text/x-patch)
file #46749:  tst_figpos2.m added by rik5 (294B - text/x-matlab)
file #46740:  tst_figpos.m added by rik5 (562B - text/x-matlab)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by stepho (Posted a comment)
  • -email is unavailable- added by pantxo (Posted a comment)
  • -email is unavailable- added by dasergatskov (Posted a comment)
  • -email is unavailable- added by rik5 (Updated the item)
  • -email is unavailable- added by larskindermann (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only group members can vote.

     

    Follow 9 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2019-12-01 rik5 StatusReady For Test Fixed
        Open/ClosedOpen Closed
    2019-11-13 rik5 StatusConfirmed Ready For Test
    2019-10-04 pantxo StatusWorks For Me Confirmed
    2019-04-11 pantxo Attached File- Added sync_test.diff, #46752
    2019-04-11 rik5 Attached File- Added tst_figpos2.m, #46749
    2019-04-09 mtmiller CategoryPlotting Plotting with OpenGL
    2019-04-09 rik5 Attached File- Added tst_figpos.m, #46740
        StatusNone Works For Me

    Back to the top

    Powered by Savane 3.13-3230.
    Corresponding source code