Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[albireo-dev] resize/relayout problem again

The return of the undead bug:

To reproduce:
- On Windows.
- Set the Parameters.borderFlag = SWT.BORDER.
- Run the application, open the "Relayout example view" and maximize it.
  Then close.
- Run the application again.

I got a screenshot like this; the background of the part that is covered by
the borderlessChild but not by the AWT Frame is not repainted.

This mostly fixes it. There is still a race condition in it (I got a wrong
display once in 40 times); I'll try to see if I can fix that.

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.75
diff -c -3 -r1.75 SwingControl.java
*** src/org/eclipse/albireo/core/SwingControl.java	29 Apr 2008 20:12:05 -0000	1.75
--- src/org/eclipse/albireo/core/SwingControl.java	30 Apr 2008 15:42:52 -0000
***************
*** 694,731 ****
          Platform.isGtk() || Platform.isCarbon();
  
      /**
       * Propagate the width and height from SWT to the AWT frame.
       * Only used if !AUTOMATIC_SET_AWT_SIZE.
       */
!     private void setAWTSize(final int width, final int height) {
          assert Display.getCurrent() != null;     // On SWT event thread
-         if (verboseSizeLayout)
-             System.err.println("SWT thread: Preparing to set size: " + width + " x " + height + " for " + swingComponent);
          // Get the AWT time of the notification that triggered this processing.
          final Integer onBehalfAWTTime = (Integer)onBehalfAWTTimes.get(Thread.currentThread());
!         // Shortcut to post a Runnable that has no effect.
!         // (lastValidatedAWTTime can only increase until the Runnable is
!         // actually run.)
!         if (onBehalfAWTTime == null
!             || lastValidatedAWTTime - onBehalfAWTTime.intValue() < 0) {
              // Switch to the AWT thread.
!             EventQueue.invokeLater(
!                 new Runnable() {
!                     public void run() {
!                         // Compare the AWT time of the notification with the
!                         // time at which the rootpane was last validated.
!                         if (onBehalfAWTTime == null
!                             || lastValidatedAWTTime - onBehalfAWTTime.intValue() < 0) {
!                             // Set the frame's (and thus also the rootpane's) size.
!                             if (verboseSizeLayout)
!                                 System.err.println("SWT->AWT thread: Setting size: " + width + " x " + height + " for " + swingComponent);
!                             if (frame != null) {
!                                 frame.setBounds(0, 0, Math.max(width, 0), Math.max(height, 0));
!                                 frame.validate();
!                             }
!                         }
!                     }
!                 });
          }
      }
  
--- 694,804 ----
          Platform.isGtk() || Platform.isCarbon();
  
      /**
+      * This class represents a queue of requests to set the AWT frame's size.
+      * Multiple requests are automatically merged, by using the last among
+      * the specified sizes, and the OR of the preconditions.
+      */
+     class SetAWTSizeQueue implements Runnable {
+         private boolean pending /* = false */;
+         // If pending:
+         // The AWT time of the notification that triggered this request
+         // (null means unknown, i.e. execute the request unconditionally).
+         private Integer onBehalfAWTTime;
+         // If pending:
+         // The size to which the frame shall be resized.
+         private int width;
+         private int height;
+         /**
+          * Creates an empty queue.
+          */
+         SetAWTSizeQueue() {
+             pending = false;
+         }
+         /**
+          * Enqueues a request to this queue.
+          * @param onBehalfAWTTime The AWT time of the notification that
+          *                        triggered this request, or null.
+          * @param width The size to which the frame shall be resized.
+          * @param height The size to which the frame shall be resized.
+          * @return true if this queue needs to be started as a Runnable
+          */
+         synchronized boolean enqueue(Integer onBehalfAWTTime, int width, int height) {
+             assert Display.getCurrent() != null;     // On SWT event thread
+             if (verboseSizeLayout)
+                 System.err.println("SWT thread: Preparing to set size: " + width + " x " + height + " for " + swingComponent);
+             boolean wasPending = this.pending;
+             // Shortcut to avoid posting a Runnable that has no effect.
+             // (lastValidatedAWTTime can only increase until the Runnable is
+             // actually run.)
+             boolean effective = (onBehalfAWTTime == null
+                                  || lastValidatedAWTTime - onBehalfAWTTime.intValue() < 0);
+             if (wasPending || effective) {
+                 // Use the last specified size.
+                 this.width = width;
+                 this.height = height;
+                 // Use the OR of the old onBehalfAWTTime and the new onBehalfAWTTime.
+                 if (wasPending) {
+                     this.onBehalfAWTTime =
+                         (this.onBehalfAWTTime == null || onBehalfAWTTime == null
+                          ? null
+                          : (this.onBehalfAWTTime.intValue() - onBehalfAWTTime.intValue() < 0
+                             ? onBehalfAWTTime
+                             : this.onBehalfAWTTime));
+                 } else {
+                     this.onBehalfAWTTime = onBehalfAWTTime;
+                 }
+                 this.pending = true;
+                 return !wasPending;
+             } else {
+                 // Avoid posting a Runnable that has no effect.
+                 return false;
+             }
+         }
+         /**
+          * Returns the enqueued request and removes it from the queue.
+          * @return The size to which the frame shall be resized, or null if
+          *         if does not need to be resized after all.
+          */
+         private synchronized Dimension dequeue() {
+             assert EventQueue.isDispatchThread();    // On AWT event thread
+             if (pending) {
+                 pending = false;
+                 // Compare the AWT time of the notification with the
+                 // time at which the rootpane was last validated.
+                 if (onBehalfAWTTime == null
+                     || lastValidatedAWTTime - onBehalfAWTTime.intValue() < 0) {
+                     return new Dimension(width, height);
+                 }
+             }
+             return null;
+         }
+         // Implementation of Runnable.
+         public void run() {
+             Dimension size = dequeue();
+             if (size != null) {
+                 // Set the frame's (and thus also the rootpane's) size.
+                 if (verboseSizeLayout)
+                     System.err.println("SWT->AWT thread: Setting size: " + size.width + " x " + size.height + " for " + swingComponent);
+                 if (frame != null) {
+                     frame.setBounds(0, 0, Math.max(size.width, 0), Math.max(size.height, 0));
+                     frame.validate();
+                 }
+             }
+         }
+     }
+     private SetAWTSizeQueue setAWTSizeQueue = new SetAWTSizeQueue();
+ 
+     /**
       * Propagate the width and height from SWT to the AWT frame.
       * Only used if !AUTOMATIC_SET_AWT_SIZE.
       */
!     private void setAWTSize(int width, int height) {
          assert Display.getCurrent() != null;     // On SWT event thread
          // Get the AWT time of the notification that triggered this processing.
          final Integer onBehalfAWTTime = (Integer)onBehalfAWTTimes.get(Thread.currentThread());
!         if (setAWTSizeQueue.enqueue(onBehalfAWTTime, width, height)) {
              // Switch to the AWT thread.
!             EventQueue.invokeLater(setAWTSizeQueue);
          }
      }
  

GIF image

GIF image


Back to the top