Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 475683

Summary: Shells receive pack() calls when not wanted
Product: [RT] RAP Reporter: Matthias Boehm <Matthias.Boehm>
Component: RWTAssignee: Project Inbox <rap-inbox>
Status: RESOLVED FIXED QA Contact:
Severity: major    
Priority: P3 CC: ivan, Matthias.Boehm
Version: 2.3   
Target Milestone: 3.1 M3   
Hardware: All   
OS: All   
Whiteboard:
Attachments:
Description Flags
Eclipse project demonstrating the described bug none

Description Matthias Boehm CLA 2015-08-24 04:27:51 EDT
I have an open modal dialog. This sometimes receives pack() calls at a (seemingly) arbitrary time, so that then it resizes to its initial size. That is very annoying if the dialog has been resized before. 

For analysis, I have overwritten the pack() method of my dialog, so that it prints the stack trace. It is as follows:

com.heidelberg.servicetools.prinect.lis.console.app.controls.scout.ServiceScoutDialog.pack(ServiceScoutDialog.java:582)
  org.eclipse.rap.rwt.internal.textsize.TextSizeRecalculation.restoreShellSize(TextSizeRecalculation.java:81)
  org.eclipse.rap.rwt.internal.textsize.TextSizeRecalculation.forceShellRecalculations(TextSizeRecalculation.java:52)
  org.eclipse.rap.rwt.internal.textsize.TextSizeRecalculation.execute(TextSizeRecalculation.java:35)
  org.eclipse.rap.rwt.internal.textsize.MeasurementListener.handleMeasurementResults(MeasurementListener.java:63)
  org.eclipse.rap.rwt.internal.textsize.MeasurementListener.beforePhase(MeasurementListener.java:36)
  org.eclipse.rap.rwt.internal.lifecycle.PhaseListenerManager.notifyBeforePhase(PhaseListenerManager.java:63)
  org.eclipse.rap.rwt.internal.lifecycle.RWTLifeCycle.continueLifeCycle(RWTLifeCycle.java:141)
  org.eclipse.rap.rwt.internal.lifecycle.RWTLifeCycle.sleep(RWTLifeCycle.java:230)
  org.eclipse.swt.widgets.Display.sleep(Display.java:1253)
  org.eclipse.ui.application.WorkbenchAdvisor.eventLoopIdle(WorkbenchAdvisor.java:361)
  org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2734)
  org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2694)
  org.eclipse.ui.internal.Workbench.access$5(Workbench.java:2530)
  org.eclipse.ui.internal.Workbench$5.run(Workbench.java:701)
  org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
  org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:684)
  org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:157)
  com.heidelberg.servicetools.prinect.lis.console.app.EntryPointApp.createUI(EntryPointApp.java:27)
  org.eclipse.rap.rwt.internal.lifecycle.RWTLifeCycle.createUI(RWTLifeCycle.java:172)
  org.eclipse.rap.rwt.internal.lifecycle.RWTLifeCycle$UIThreadController.run(RWTLifeCycle.java:284)
  java.lang.Thread.run(Thread.java:745)
  org.eclipse.rap.rwt.internal.lifecycle.UIThread.run(UIThread.java:105)

where ServiceScoutDialog is the open dialog. 

I took a look at the methods in the stack trace and I think I found the reason for which the pack() method of the dialog is called unwantedly. The method restoreShellSize() in TextSizeRecalculation is as follows:


private void restoreShellSize( Shell shell, Rectangle bufferedBounds, boolean isPacked ) {
    if( isPacked ) {
      shell.pack();
    } else {
      setShellSize( shell, bufferedBounds );
    }
  }


If the shell is packed already, shell.pack() is called again! Shouldn't the condition in the if-clause be negated:

private void restoreShellSize( Shell shell, Rectangle bufferedBounds, boolean isPacked ) {
    if( !isPacked ) {
      shell.pack();
    } else {
      setShellSize( shell, bufferedBounds );
    }
  }
Comment 1 Ivan Furnadjiev CLA 2015-08-31 03:06:26 EDT
(In reply to comment #0)
> If the shell is packed already, shell.pack() is called again! Shouldn't the
> condition in the if-clause be negated:
> 
> private void restoreShellSize( Shell shell, Rectangle bufferedBounds, boolean
> isPacked ) {
> if( !isPacked ) {
> shell.pack();
> } else {
> setShellSize( shell, bufferedBounds );
> }
> }

No... During the text-size-determination resizing, the packed Shells are resized to +1000 and then packed again (only if Shell was packed before - ) in order to do the layouting again. For me it sounds like the internal Control flag "packed" is not reset after the Shell size is changed manually. Could you provide a simple snippet to reproduce the issue?
Comment 2 Ivan Furnadjiev CLA 2015-10-23 03:52:21 EDT
Any chance for a snippet to reproduce it?
Comment 3 Matthias Boehm CLA 2015-10-26 04:14:13 EDT
Created attachment 257499 [details]
Eclipse project demonstrating the described bug

The sample is a simple rap application. When clicking on the "World" button, a sample dialog opens. This contains a table with some (long) items. After 5 seconds, the (long) table items are replaced with short table items. After this happened, a pack() is sent to the dialog unwantedly, so that the dialog resizes. This is not what we expect; we expect that the dialog retains its initial size. 

Note that this described behavior occurs only after the first start of the application; when clicking again on the "World" button, the dialog is not resized any more after the table items have been updated! This is how we want it. 

I've overwritten the pack method, so that one can see when pack() is called; additionally, a stack trace is printed on the console each time pack() is called.
Comment 4 Matthias Boehm CLA 2015-10-26 04:18:49 EDT
NOTE: With "After this happened, a pack() is sent to the dialog unwantedly" I mean, that the dialog's method pack() is called unwantedly.
Comment 5 Ivan Furnadjiev CLA 2015-10-26 04:25:10 EDT
That's because of text-size-determination. If the Dialog was packed initially, all sequential changes in it's content, that lead to text size measurement will repack the Dialog. This is how text-size-determination works. As a workaround set the dialog size manually again after the Dialog is packed for the first time.
Comment 6 Ivan Furnadjiev CLA 2015-10-26 08:54:44 EDT
Calling pack() again in TextSizeRecalculation#restoreShellSize will set the internal Control "packed" flag back to true. I think the fix is to replace the pack() call like:
-----
private void restoreShellSize( Shell shell, Rectangle bufferedBounds, boolean isPacked ) {
  if( isPacked ) {
    shell.setSize( shell.computeSize( SWT.DEFAULT, SWT.DEFAULT, true ) ); // This is the Control#pack() implementation whithout changing the internal "packed" flag
  } else {
    setShellSize( shell, bufferedBounds );
  }
}
Comment 7 Ivan Furnadjiev CLA 2015-10-27 05:14:32 EDT
Pending change: https://git.eclipse.org/r/#/c/58974/
Comment 8 Ivan Furnadjiev CLA 2015-10-27 08:29:13 EDT
Fix with change https://git.eclipse.org/r/#/c/58974/