Bug 1362

Summary: NewtCanvasSWT doesn't work with GTK 3
Product: [JogAmp] Jogl Reporter: Wade Walker <wwalker3>
Component: swtAssignee: Sven Gothel <sgothel>
Status: RESOLVED FIXED    
Severity: blocker CC: sgothel
Priority: P4    
Version: 2.4.0   
Hardware: All   
OS: linux   
Type: DEFECT SCM Refs:
4cc7d45ad7e7e35b73afe7ddeb9dcf06893e7cb9 b52335c4c550aa8a9fd0007563f89dd8a04dc81c 56a3ea2077483925cb7da7729fe3afa4da498929 2280e821ea5f8e02fb99cf3f12e10115d6d4f13a 58dd634261ebb815771dcd3d59dbf972f1c79106 a2f09981ee7d590204bf865314c2cdf802c4ed77 ca3bf988bfad6adac9ad9ac240f3c15b129ef85e 705c7f7b3fb36c1d654f5d9b9016859506d93764 35e3789ba401e94cb4778971470eb90d5c383f79
Workaround: ---

Description Wade Walker 2019-02-18 17:25:42 CET
More detail at http://forum.jogamp.org/NewtCanvasSWT-Linux-Exception-with-GTK-VERSION-td4039442i20.html#a4039550 and the posts preceding it.
Comment 1 Wade Walker 2019-03-29 01:37:51 CET
Confirmed that it fails with GTK 3.22.30 on Ubuntu 18.04. I have a JOGL build patch that uses a more recent version of SWT (which contains GTK 2.22.30) if we want to duplicate this error in our test flow.
Comment 2 Sven Gothel 2019-03-30 02:20:55 CET
(In reply to Wade Walker from comment #1)
> Confirmed that it fails with GTK 3.22.30 on Ubuntu 18.04. I have a JOGL
> build patch that uses a more recent version of SWT (which contains GTK
> 2.22.30) if we want to duplicate this error in our test flow.

Please. Do you like to take this task?
It is OK to update our SWT lib within JOGL of course.
I also like this to be done for version 2.4.0.
Comment 3 Sven Gothel 2019-03-30 02:23:18 CET
FWIW, Debian 9 has GTK 3.22.11 installed.

ii  libgtk-3-0:amd64                              3.22.11-1                                   amd64        GTK+ graphical user interface library
Comment 4 Wade Walker 2019-03-30 14:52:21 CET
Let me add more details. To get to the real error, first you have to patch SWTAccessor.java:

diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
index c79ed2f67..051798e9c 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
@@ -81,7 +81,9 @@ public class SWTAccessor {
     private static final String str_internal_new_GC = "internal_new_GC";
     private static final String str_internal_dispose_GC = "internal_dispose_GC";
 
-    private static final String str_OS_gtk_class = "org.eclipse.swt.internal.gtk.OS";
+    private static final String str_OS_gtk_class = "org.eclipse.swt.internal.gtk.OS";    // used by earlier versions of SWT
+    private static final String str_GTK_gtk_class = "org.eclipse.swt.internal.gtk.GTK";  // used by later versions of SWT
+    private static final String str_GDK_gtk_class = "org.eclipse.swt.internal.gtk.GDK";  // used by later versions of SWT
     public static final Class<?> OS_gtk_class;
     private static final String str_OS_gtk_version = "GTK_VERSION";
     public static final VersionNumber OS_gtk_version;
@@ -96,6 +98,7 @@ public class SWTAccessor {
     private static final Method OS_gdk_x11_drawable_get_xid;
     private static final Method OS_gdk_x11_window_get_xid;
     private static final Method OS_gdk_window_set_back_pixmap;
+    private static final Method OS_gdk_window_set_background_pattern;
 
     private static final String str_gtk_widget_realize = "gtk_widget_realize";
     private static final String str_gtk_widget_unrealize = "gtk_widget_unrealize";
@@ -107,9 +110,11 @@ public class SWTAccessor {
     private static final String str_gdk_x11_drawable_get_xid = "gdk_x11_drawable_get_xid";
     private static final String str_gdk_x11_window_get_xid = "gdk_x11_window_get_xid";
     private static final String str_gdk_window_set_back_pixmap = "gdk_window_set_back_pixmap";
+    private static final String str_gdk_window_set_background_pattern = "gdk_window_set_background_pattern";
 
     private static final VersionNumber GTK_VERSION_2_14_0 = new VersionNumber(2, 14, 0);
     private static final VersionNumber GTK_VERSION_2_24_0 = new VersionNumber(2, 24, 0);
+    private static final VersionNumber GTK_VERSION_2_90_0 = new VersionNumber(2, 90, 0);
     private static final VersionNumber GTK_VERSION_3_0_0  = new VersionNumber(3,  0, 0);
 
     private static VersionNumber GTK_VERSION(final int version) {
@@ -174,13 +179,23 @@ public class SWTAccessor {
 
         Class<?> c=null;
         VersionNumber _gtk_version = new VersionNumber(0, 0, 0);
-        Method m1=null, m2=null, m3=null, m4=null, m5=null, m6=null, m7=null, m8=null, m9=null, ma=null;
+        Method m1=null, m2=null, m3=null, m4=null, m5=null, m6=null, m7=null, m8=null, m9=null, ma=null, mb=null;
         final Class<?> handleType = swt_uses_long_handles  ? long.class : int.class ;
         if( isX11 ) {
             // mandatory
             try {
                 c = ReflectionUtil.getClass(str_OS_gtk_class, false, SWTAccessor.class.getClassLoader());
-                final Field field_OS_gtk_version = c.getField(str_OS_gtk_version);
+                Field field_OS_gtk_version;
+                Class<?> cGDK=c;  // used for newer versions of SWT that have a org.eclipse.swt.internal.gtk.GDK object
+                try {
+                    field_OS_gtk_version = c.getField(str_OS_gtk_version);
+                } catch (NoSuchFieldException ex) {
+                       // if the GTK_VERSION field didn't exist in org.eclipse.swt.internal.gtk.OS, then look for
+                       // it in org.eclipse.swt.internal.gtk.GTK, where it was moved in later versions of SWT
+                    c = ReflectionUtil.getClass(str_GTK_gtk_class, false, SWTAccessor.class.getClassLoader());
+                    field_OS_gtk_version = c.getField(str_OS_gtk_version);
+                    cGDK = ReflectionUtil.getClass(str_GDK_gtk_class, false, SWTAccessor.class.getClassLoader());
+                }
                 _gtk_version = GTK_VERSION(field_OS_gtk_version.getInt(null));
                 m1 = c.getDeclaredMethod(str_gtk_widget_realize, handleType);
                 if (_gtk_version.compareTo(GTK_VERSION_2_14_0) >= 0) {
@@ -189,17 +204,22 @@ public class SWTAccessor {
                     m3 = c.getDeclaredMethod(str_GTK_WIDGET_WINDOW, handleType);
                 }
                 if (_gtk_version.compareTo(GTK_VERSION_2_24_0) >= 0) {
-                    m6 = c.getDeclaredMethod(str_gdk_x11_display_get_xdisplay, handleType);
-                    m7 = c.getDeclaredMethod(str_gdk_window_get_display, handleType);
+                    m6 = cGDK.getDeclaredMethod(str_gdk_x11_display_get_xdisplay, handleType);
+                    m7 = cGDK.getDeclaredMethod(str_gdk_window_get_display, handleType);
                 } else {
                     m5 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xdisplay, handleType);
                 }
                 if (_gtk_version.compareTo(GTK_VERSION_3_0_0) >= 0) {
-                    m9 = c.getDeclaredMethod(str_gdk_x11_window_get_xid, handleType);
+                    m9 = cGDK.getDeclaredMethod(str_gdk_x11_window_get_xid, handleType);
                 } else {
                     m8 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xid, handleType);
                 }
-                ma = c.getDeclaredMethod(str_gdk_window_set_back_pixmap, handleType, handleType, boolean.class);
+                
+                if (_gtk_version.compareTo(GTK_VERSION_2_90_0) >= 0) {
+                    mb = cGDK.getDeclaredMethod(str_gdk_window_set_background_pattern, handleType, handleType);
+                } else {
+                    ma = c.getDeclaredMethod(str_gdk_window_set_back_pixmap, handleType, handleType, boolean.class);
+                }
             } catch (final Exception ex) { throw new NativeWindowException(ex); }
             // optional
             try {
@@ -218,6 +238,7 @@ public class SWTAccessor {
         OS_gdk_x11_drawable_get_xid = m8;
         OS_gdk_x11_window_get_xid = m9;
         OS_gdk_window_set_back_pixmap = ma;
+        OS_gdk_window_set_background_pattern = mb;
 
         isX11GTK = isX11 && null != OS_gtk_class;
 
@@ -237,6 +258,10 @@ public class SWTAccessor {
         ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg) });
     }
 
+    private static void callStaticMethodLL2V(final Method m, final long arg0, final long arg1) {
+        ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg0), getIntOrLong(arg1) });
+    }
+
     private static void callStaticMethodLLZ2V(final Method m, final long arg0, final long arg1, final boolean arg3) {
         ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg0), getIntOrLong(arg1), Boolean.valueOf(arg3) });
     }
@@ -309,7 +334,13 @@ public class SWTAccessor {
     }
 
     public static void gdk_window_set_back_pixmap(final long window, final long pixmap, final boolean parent_relative) {
-        callStaticMethodLLZ2V(OS_gdk_window_set_back_pixmap, window, pixmap, parent_relative);
+       if(OS_gdk_window_set_back_pixmap != null) {
+           callStaticMethodLLZ2V(OS_gdk_window_set_back_pixmap, window, pixmap, parent_relative);
+       }
+       // in recent GTK, can't set background to pixmap any more; this sets it relative to parent
+       else if(OS_gdk_window_set_background_pattern != null) {
+               callStaticMethodLL2V(OS_gdk_window_set_background_pattern, window, 0);
+       }
     }
 
     //
@@ -510,7 +541,7 @@ public class SWTAccessor {
     public static long createCompatibleX11ChildWindow(final AbstractGraphicsScreen screen, final Control swtControl, final int visualID, final int width, final int height) {
         final long handle = getHandle(swtControl);
         final long parentWindow = gdk_widget_get_window( handle );
-        gdk_window_set_back_pixmap (parentWindow, 0, false);
+        // gdk_window_set_back_pixmap(parentWindow, 0, false);
 
         final long x11ParentHandle = gdk_window_get_xwindow(parentWindow);
         final long x11WindowHandle = X11Lib.CreateWindow(x11ParentHandle, screen.getDevice().getHandle(), screen.getIndex(), visualID, width, height, true, true);
Comment 5 Wade Walker 2019-03-30 14:54:09 CET
To debug, I extended the timeouts on the TestNewtCanvasSWTGLn unit test, which allows duplicating this failure even when stepping through the test in the debugger. I put breakpoints on gdk_window_begin_draw_frame() and gdk_window_end_draw_frame() in the GDK library so I could check if any calls to these are unpaired. 

But they aren't! I see six properly paired calls to begin/end, then on the seventh begin, it throws the
(SWT:15054): Gdk-CRITICAL **: 07:54:54.539: The window 0x7f073d2ec640 already has a drawing context. You cannot call gdk_window_begin_draw_frame() without calling gdk_window_end_draw_frame() first.
 The error always happens after the same number of calls, and is perfectly reproducible. 

What's more, these calls to gdk_window_begin_draw_frame()/gdk_window_end_draw_frame() are always in a call stack of pure GTK/SWT code. There's no JOGL code at all being invoked during window event processing. JOGL calls Display.readAndDispatch() at the top level, but that's it. This makes me think the problem has to do with how the NewtCanvasSWT is set up in the first place, but that part of the JOGL code is pretty difficult to understand. 

So in short, I think there are two bugs here. Bug #1 was that SWTAccessor didn't work with newer versions of SWT, which is fixed by the patch I posted. But bug #2 is that JOGL's NewtCanvasSWT doesn't work with GTK 3.22.30 on Ubuntu 18.04 for reasons which are still unknown.
Comment 6 Wade Walker 2019-03-30 14:57:01 CET
So my question for @Sven here is, do you have any insights about other debugging strategies I could try? I've already tried everything I can think of, but as noted above our calls to the GTK functions already seem correctly paired, and the error doesn't happen inside JOGL code. I'm willing to investigate further, but I can't think of what to do next.
Comment 7 Wade Walker 2019-03-30 15:03:51 CET
To summarize the work so far: 

- When users try to use JOGL with GTK 3, they get an exception when JOGL tries to read GTK_VERSION from org.eclipse.swt.internal.gtk.OS (its location in GTK 2) 

- If you fix JOGL to read GTK_VERSION from its new location in org.eclipse.swt.internal.gtk.GTK (where it moved in GTK 3, see the patch I posted for SWTAccessor.java), then you get another problem: 

(SWT:14860): Gdk-CRITICAL **: 17:47:49.569: The window 0x7f71e51ac640 already has a drawing context. You cannot call gdk_window_begin_draw_frame() without calling gdk_window_end_draw_frame() first. 

(SWT:14860): Gdk-CRITICAL **: 17:47:49.569: gdk_drawing_context_get_cairo_context: assertion 'GDK_IS_DRAWING_CONTEXT (context)' failed 
org.eclipse.swt.SWTError: No more handles 

- The problem shows up in JOGL unit tests like com.jogamp.opengl.test.junit.jogl.swt.preAttach_NoAnimator() 

- The problem seems to be caused by a significant change to the way drawing works between GTK 2 and GTK 3. Somehow the NewtCanvasSWT is skipping a gdk_window_end_draw_frame() somewhere. But JOGL never directly calls gdk_window_begin_draw_frame(), gdk_window_end_draw_frame(), or gdk_drawing_context_get_cairo_context(), and it's never erroneously disposing a Cairo context, so I don't know how this could be happening. 

- The gdk_window_begin_draw_frame()/gdk_window_end_draw_frame() calls are always properly paired when you set breakpoints on them (which you can do once you extend the test timeouts for com.jogamp.opengl.test.junit.jogl.swt.preAttach_NoAnimator())
Comment 8 Sven Gothel 2019-03-30 19:28:42 CET
Thank you Wade for the detailed report.

So your first patch (I merge it then w/ you as author?)
fixes the minor data structure change to fetch the windowing handle I assume.

But the real issue is the lifecycle or 'identity' or semantics of the
GTK3 handles? Maybe.

I recently walked through NewtCanvasSWT and NewtCanvasAWT 
to produce the new NewtCanvasJFX. 
Their concept is quite trivial: Fetch the toolkit's window handle
and attach our NEWT window as a child to it.
While the concept is trivial, the lifecycle is not :)
And this might have changed somewhat.

(Note that until now I don't even know what the error is after you have
applied the patch - but I will looks at it later as well)

As a debug strategy I would:
- Check the fetched toolkit's window handle: validate that it is a proper X11 Window.
- If that handle is valid, it implies a visible SWT X11 window and we can use it.

Maybe our way how we derive the X11 window handle is no more valid,
as you can see in SWTAccessor we use some gdk->gtk->X11 or similar.
Comment 9 Sven Gothel 2019-03-30 19:35:12 CET
Thank you Wade and sorry for my maybe too quick replies,
in the middle of changing diapers ;-)

(In reply to Wade Walker from comment #7)
> (SWT:14860): Gdk-CRITICAL **: 17:47:49.569: The window 0x7f71e51ac640
> already has a drawing context. You cannot call gdk_window_begin_draw_frame()
> without calling gdk_window_end_draw_frame() first. 
> 
> (SWT:14860): Gdk-CRITICAL **: 17:47:49.569:
> gdk_drawing_context_get_cairo_context: assertion 'GDK_IS_DRAWING_CONTEXT
> (context)' failed 
> org.eclipse.swt.SWTError: No more handles 
> 
> - The problem shows up in JOGL unit tests like
> com.jogamp.opengl.test.junit.jogl.swt.preAttach_NoAnimator() 
> 
> - The problem seems to be caused by a significant change to the way drawing
> works between GTK 2 and GTK 3. Somehow the NewtCanvasSWT is skipping a
> gdk_window_end_draw_frame() somewhere. But JOGL never directly calls
> gdk_window_begin_draw_frame(), gdk_window_end_draw_frame(), or
> gdk_drawing_context_get_cairo_context(), and it's never erroneously
> disposing a Cairo context, so I don't know how this could be happening. 
> 
> - The gdk_window_begin_draw_frame()/gdk_window_end_draw_frame() calls are
> always properly paired when you set breakpoints on them (which you can do
> once you extend the test timeouts for
> com.jogamp.opengl.test.junit.jogl.swt.preAttach_NoAnimator())

We really have no biz with GDK's drawing cycles, as we just attach a NEWT child window to the SWT native parent.

Also know that X11 has the luxury of allowing native window parenting to happen from different threads/process (I love it), so we should be quite relaxed ..

I wonder whether our window parenting action itself is disturbing GDK hmm,
this low level GDK issue should not happen.
Comment 10 Wade Walker 2019-03-30 19:52:38 CET
I had a thought that perhaps the extra call to gdk_window_begin_draw_frame() is happening in native code, rather than being at the end of a call chain that starts in Java. That would explain the GTK error message we see, and would also explain why my Java breakpoint didn't get triggered on any extra gdk_window_begin_draw_frame() (since I was breakpointing the Java wrapper around the native function, not the native function itself).

The question would then be, what could we be doing that would cause a native gdk_window_begin_draw_frame() without a corresponding gdk_window_end_draw_frame()?
Comment 11 Sven Gothel 2019-04-03 17:24:08 CEST
Blocker because: "In 4.11 only GTK3 is supported. The dropped GTK2 support",
assuming Marcel (forum) meant the version of the SWT implementation of course.
Comment 12 Sven Gothel 2019-04-05 06:01:17 CEST
I work on this now.
Comment 13 Sven Gothel 2019-04-05 06:34:40 CEST
Marcel: "In 4.11 only GTK3 is supported. They dropped GTK2 support in 4.10, see:

https://www.eclipse.org/eclipse/news/4.10/platform.php#gtk2-removal

I still get the handle error when I start the RCP from within Eclipse. Exported as a RCP product  I do not get any handle errors."

So SWT 4.10 does not support GTK2 anymore.
Comment 14 Sven Gothel 2019-04-05 06:52:58 CEST
http://forum.jogamp.org/com-jogamp-opengl-swt-GLCanvas-does-not-work-with-Eclipse-4-8-under-Linux-td4039229.html

Original complaint: JOGL doesn't work w/ SWT 4.8.

JOGL uses SWT 4.3, so somewhere in between things has been broken
w/ GTK2 / GTK3 and SWT >= 4.10 supports GTK3 only.

What I do now is: 
- Add SWT 4.10 library to test
- See how to get the binding working for GTK3.

I may 'risk' skipping testing SWT [4.4 - 4.9].

What is missing with this bug report is surely a version test matrix,
but I think getting SWT 4.10 to work would be the next clean step?

Nonetheless I also start w/ applying your patch Wade.
Comment 15 Sven Gothel 2019-04-05 07:14:26 CEST
(In reply to Sven Gothel from comment #14)
> What I do now is: 
> - Add SWT 4.10 library to test
> - See how to get the binding working for GTK3.
> 
> I may 'risk' skipping testing SWT [4.4 - 4.9].
> 
> What is missing with this bug report is surely a version test matrix,
> but I think getting SWT 4.10 to work would be the next clean step?

SWT 4.11: https://download.eclipse.org/eclipse/downloads/drops4/R-4.11-201903070500/
Comment 16 Sven Gothel 2019-04-05 09:35:27 CEST
Debug flags
-Dnativewindow.debug.SWT -Dnativewindow.debug.X11Util -Dnewt.debug.Window

Test:
com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT

Some output ..

(SWT:21037): GLib-CRITICAL **: g_base64_encode_step: assertion 'in != NULL' failed
Def. Icon: data_size 1284 * elem_size 8 = data java.nio.DirectByteBuffer[pos=0 lim=10272 cap=10272]
Loop 1/1
X11Util.Display: openDisplay [reuse false] NamedX11Display[:0, 0x7f070ca59bd0, refCount 1, unCloseable false]. Open[reuseable 0, pending 1]. Thread main
XineramaIsEnabled Cache: Display :0 (0x7f070ca59bd0) -> true
X11Util.Display: Closed (real: true) NamedX11Display[:0, 0x7f070ca59bd0, refCount 0, unCloseable false]. Thread main
X11Util.Display: openDisplay [reuse false] NamedX11Display[:0, 0x7f067c000910, refCount 1, unCloseable false]. Open[reuseable 0, pending 1]. Thread main-SharedResourceRunner
requested: vsync 1, GLCaps[rgba 8/8/8/0, opaque, accum-rgba 0/0/0/0, dp/st/ms 16/0/0, dbl, mono  , hw, GLProfile[GL4/GL4.hw], on-scr[.]]
X11Util.Display: openDisplay [reuse false] NamedX11Display[:0, 0x7f070ca5d660, refCount 1, unCloseable false]. Open[reuseable 0, pending 2]. Thread main
X11Util.Display: Closed (real: true) NamedX11Display[:0, 0x7f070ca5d660, refCount 0, unCloseable false]. Thread main
Window.addWindow2List: GCed 0, size 1
NewtCanvasSWT.setNEWTChild.0: win nil -> 0x0
NewtCanvasSWT.Event.RESIZE, Event {type=11 NewtCanvasSWT {} time=0 data=null x=0 y=0 width=0 height=0 detail=0}
NewtCanvasSWT.updatePosSizeCheck: sizeChanged true, posChanged false, updatePos false, (main): newtChildReady false, 0/0 640x480 - surfaceHandle 0x0
NewtCanvasSWT.setBounds: 0/0 640x480
NewtCanvasSWT.Event.DISPOSE, Event {type=12 NewtCanvasSWT {} time=394144768 data=null x=0 y=0 width=0 height=0 detail=0}
NewtCanvasSWT.dispose.0: EDTUtil cur jogamp.newt.DefaultEDTUtil@5123a213,

++++

Notable: NewtCanvasSWT.Event.DISPOSE has been reached, before even starting
Subsequent attempt to build the NEWT child and attach it cannot complete

+++

Ideas?
Some GTK3 setup issue?

https://stackoverflow.com/questions/48467865/glib-critical-g-base64-encode-step-assertion-in-null-failed-problems-i

https://www.eclipse.org/swt/faq.php#gtkstartup

hmm
Comment 17 Sven Gothel 2019-04-09 12:17:30 CEST
commit 58dd634261ebb815771dcd3d59dbf972f1c79106:

Bug 1362: Add two self contained unit tests to validate SWT >= 4.10 + GTK3 issues
    
TestSWTAccessor01: Simply tests SWTAccessor's returned native window handle. Works on SWT + GTK2 and SWT + GTK3.
    
TestSWTAccessor02NewtGLWindow: Uses same returned native window handle and tests a GLWindow.reparentWindow(..) operation
all rolled out and implemented here ad-hock (comparable to NewtCanvasSWT).
This shall allow simplified debugging.
Testing:
- SWT + GTK2: Works
- SWT + GTK3: Bug reproduced
Comment 18 Sven Gothel 2019-04-09 12:58:32 CEST
commit a2f09981ee7d590204bf865314c2cdf802c4ed77:
TestSWTAccessor02NewtGLWindow demonstrates a fix by letting the Canvas PAINT!

This commit shows the very little change set required to allow working on SWT >= 4.10 + GTK3,
i.e. adding the PAINT listener to Canvas and letting it paint.

Almost too ridiculous? I stumbled over it by creating this test in the first place
when copying the 01 test -> 02 and adding the native parenting.

Possible explanation: The parent Canvas may need to paint once at least due to some 
lazy initialization within SWT or GTK3?! 

+++

Successfull triage, next step: Fine tuning (paint only once?) and 
adding to NewtCanvasSWT and our GLCanvas implementation.

Therefor, this might be a SWT issue and our patch a workaround.
Comment 19 Sven Gothel 2019-04-09 19:32:58 CEST
Bug 1362 fix or workaround: Seems GTK3 at least performs lazy initialization

Minimal action required: setBackground + fillRectangle of some space in canvas ONCE before reparenting!
See commit ca3bf988bfad6adac9ad9ac240f3c15b129ef85e
Comment 20 Sven Gothel 2019-04-09 21:47:46 CEST
Even better:

commit 705c7f7b3fb36c1d654f5d9b9016859506d93764

Bug 1362: Minimal action required: setBackground of the parent canvas before reparenting!
    
Bug 1362 fix or workaround: Seems SWT/GTK3 at least performs lazy initialization
Minimal action required: setBackground of the parent canvas before reparenting!
Comment 21 Sven Gothel 2019-04-09 21:50:30 CEST
commit 705c7f7b3fb36c1d654f5d9b9016859506d93764
actually adds code to NewtCanvasSWT and our SWT GLCanvas 
hence this bug is now fixed.

I currently refactor AWTRobotUtil -> TestUtil interface and 
additional GLTestUtil, NewtTestUtil. 

Required to properly add some lifecycle checks in the SWT unit tests.
After passing all these, I will close this blocker.
Comment 22 Sven Gothel 2019-04-09 23:43:56 CEST
It was quite an interesting experience indeed,
hence adding the path of finding the issue here.

As I debated w/ Wade in the bugzilla comments,
I advised testing the native window handle first.
So I did and it was good using a proper little SWT app.

So the next step was to 'find the difference', 
knowing that we didn't do anything w/ the parent's 
SWT GTK/GDK object but attach our NEWT child to it.

Hence I added the little whole parenting code in the copied 
test case 02. And it worked!

Now I created a third copy 03 (not checked in)
and removed the difference to the NewtCanvasSWT test case,
i.e. the proper SWT canvas rendering.
Voila, the bug got reproduced.

Hence the issue was something added in 01, 
the SWT canvas rendering. 
And finally it turned out to be just the background setting.

I only checked in 02 w/ the removed SWT rendering producing the bug
and then re-added the parts fixing the issue - as committed to show.
Comment 23 Sven Gothel 2019-04-10 00:36:59 CEST
commit 35e3789ba401e94cb4778971470eb90d5c383f79

Final general lifecycle fixes of unit tests
    
SWT unit tests must wait while issuing 'display.readAndDispatch()'
so essential event dispatching won't get blocked.
    
Previous AWTRobotUtil cleanup and these patches ensure proper lifecycle checks.
Comment 24 Wade Walker 2019-04-10 02:01:54 CEST
Great catch on this bug! It makes sense that if the native code initiates a WM_PAINT, but it's not handled, that might prevent the gdk_window_end_draw_frame() from being called in the parent :)
Comment 25 Sven Gothel 2019-04-10 03:07:39 CEST
(In reply to Wade Walker from comment #24)
> Great catch on this bug! It makes sense that if the native code initiates a
> WM_PAINT, but it's not handled, that might prevent the
> gdk_window_end_draw_frame() from being called in the parent :)

I get the joke ;-)
That would be to obvious .. and the issue is only being visible when
the child window issues the native paint for the GDK painting.

But know that the only thing needed to fix this is setting the 
background color. I went through many permutations here and only that fixed it.

So maybe our native window does propagate a native windowing action 
to the SWT GTK parent, triggering some action requiring some resources set.
SWT might not have prepared these resources due to 'no background' settings
and/or lazy initialization.
One may forward this bug report to the SWT/GTK team 
and maybe they can triage it there - should be fixed in their code IMHO.

For us - one blocking issue less :)