Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [albireo-dev] inhibitSizePropagationToAWT

> I have a patch that avoids this behaviour (1. call checkPopulated() earlier
> than we do now, 2. override SwingControl.getClientArea() to keep track of
> the returned rectangle, so that we can override its values before said
> invokeLater is executed).

The first part was actually not needed. This workaround fixes the problem
in my tests:
  Without patch, with JDK 1.6 on Windows, about 1 out of 2 or 3 runs fails.
  With this patch, 0 out of 10 runs failed.

I think this proves that the pinpointed code in SWT_AWT was the problem.
So I'm committing it (although it's admittedly ugly).

Bruno


Index: src/org/eclipse/albireo/core/SwingControl.java
===================================================================
RCS file: /cvsroot/technology/org.eclipse.albireo/org.eclipse.albireo.core/src/org/eclipse/albireo/core/SwingControl.java,v
retrieving revision 1.30
diff -c -3 -r1.30 SwingControl.java
*** src/org/eclipse/albireo/core/SwingControl.java	13 Feb 2008 19:35:42 -0000	1.30
--- src/org/eclipse/albireo/core/SwingControl.java	13 Feb 2008 19:56:44 -0000
***************
*** 363,368 ****
--- 363,411 ----
      // - 2 after these sizes have been taken into account by the SWT side.
      private int cachedSizesInitialized = 0;
  
+     // Work around against a bug observed with the RelayoutExampleView on
+     // Windows with JDK 1.6: The SWT_AWT.new_Frame method executes this code:
+     //     parent.getDisplay().asyncExec(new Runnable() {
+     //         public void run () {
+     //             if (parent.isDisposed()) return;
+     //             final Rectangle clientArea = parent.getClientArea();
+     //             EventQueue.invokeLater(new Runnable () {
+     //                 public void run () {
+     //                     frame.setSize (clientArea.width, clientArea.height);
+     //                     frame.validate ();
+     //                 }
+     //             });
+     //         }
+     //     });
+     // This code overwrites the size of the frame with a size that is not
+     // valid any more!
+     private Rectangle initialClientArea;
+     /**
+      * Overridden.
+      */
+     public Rectangle getClientArea() {
+         assert Display.getCurrent() != null;     // On SWT event thread
+         Rectangle rect = super.getClientArea();
+         if (initialClientArea == null) {
+             synchronized (this) {
+                 if (cachedSizesInitialized >= 1) {
+                     rect.width = cachedPrefSize.width;
+                     rect.height = cachedPrefSize.height;
+                 }
+             }
+             // We don't want to clobber arbitrary Rectangle objects, only the
+             // one use by the SWT_AWT inner class.
+             Exception e = new Exception();
+             e.fillInStackTrace();
+             StackTraceElement[] stack = e.getStackTrace();
+             if (stack.length >= 2
+                 && stack[1].getClassName().startsWith("org.eclipse.swt.awt.SWT_AWT$")) {
+                 initialClientArea = rect;
+             }
+         }
+         return rect;
+     }
+ 
      // We have bidirectional size propagation, from AWT to SWT, and from
      // SWT to AWT. To avoid endless recursion in weird cases (for example,
      // when the AWT component refuses to accept the size that the SWT
***************
*** 393,398 ****
--- 436,449 ----
              cachedMinSize = min;
              cachedPrefSize = pref;
              cachedMaxSize = max;
+ 
+             /**
+              * Part of a workaround, see {@link #getClientArea()}.
+              */
+             if (initialClientArea != null) {
+                 initialClientArea.width = cachedPrefSize.width;
+                 initialClientArea.height = cachedPrefSize.height;
+             }
          }
  
          if (mustNotify) {


Back to the top