Bug 36908 - [Workbench] Workbench Window becomes disabled
Summary: [Workbench] Workbench Window becomes disabled
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 2.1   Edit
Hardware: PC Windows XP
: P2 critical (vote)
Target Milestone: ---   Edit
Assignee: Nick Edgar CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-04-25 11:12 EDT by Randy Hudson CLA
Modified: 2003-06-20 13:50 EDT (History)
5 users (show)

See Also:


Attachments
2.1 configuration file (94.28 KB, text/plain)
2003-05-08 15:44 EDT, Randy Hudson CLA
no flags Details
Eric's config file (356.26 KB, text/plain)
2003-05-08 16:36 EDT, Eric Bordeau CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Randy Hudson CLA 2003-04-25 11:12:10 EDT
The workbench window's client area becomes completely disabled sometimes when I 
save a java file.  Everything from the toolbar (inclusively) down is disabled 
to mouse and keyboard.  Is there somewhere that setEnabled(false) is being 
called?

Only the menu can be used, and I am forced to close the window because there is 
no way to get it enabled again.  This happens to me more than once per day.  
For some users, they would be forced to exit Eclipse.
Comment 1 Debbie Wilson CLA 2003-04-25 12:02:36 EDT
I assume you're on 2.1.  Anything in the .log?
Comment 2 Randy Hudson CLA 2003-04-25 13:13:44 EDT
Yes, 2.1, nothing in the log.
Comment 3 Simon Arsenault CLA 2003-05-02 13:34:50 EDT
Is this with or without your patch to the workbench?
Comment 4 Eric Bordeau CLA 2003-05-03 21:35:34 EDT
I haven't installed Randy's patch and I get this problem.
Comment 5 Randy Hudson CLA 2003-05-04 23:53:24 EDT
Eric, have you had this happen on any window *other* than one displaying the 
Java Hierarchy perspective? It seems like for me it is always the hierarchy 
perspective.
Comment 6 Eric Bordeau CLA 2003-05-05 11:29:48 EDT
Randy -- I've only seen this on windows with the Java Hierarchy perspective (but
that's the only perspective I use other than one window with the Java
perspective which has never frozen on me).
Comment 7 Simon Arsenault CLA 2003-05-05 16:08:23 EDT
Moving to JDT for comments - is there perhaps a view or action within this Java 
Hierarchy perspective that could cause this problem?

Randy/Eric - have you found a series of steps to reproduce this problem?
Comment 8 Randy Hudson CLA 2003-05-05 16:15:39 EDT
The only thing that seems to do it for me is F11.  But, it is hard to pinpoint 
since I often go through an entire debug session before returning to that 
workbench window instance.  But, it could even be happening during the 
debugging (for example, does Stepping Over update the ruler in the other 
workbench window?)
Comment 9 Dirk Baeumer CLA 2003-05-06 03:36:12 EDT
The type Hierarchy perspective is not different from other Java perspectives. 
The views used in this perspective are also used in the Java and Java Browsing 
perspective. So I doubt that it is special for the type hierarchy perspective. 

First comment says, that is happens during save. As far as I know save reports 
progress via the progress monitor embedded into the workbench window. To do so 
it uses the window as a runnable context. To ensure that no other user action 
can be triggered the ApplicationWindow.run method disables the client area of 
the window. Save triggers a delta which might cause another operation to run. 
If this operation also uses the workbench window as a runnable context the 
workbench window ends up with a disabled client area, since the run method 
doesn't seem to handle reentrancy.

It is very likely that this scenario happens when having a type hierarchy open 
since the type hierarchy listens to deltas and updates the hierarchy when 
needed. To do so it used the workbench window as a runnable context.

Moving to Platform/UI for comments.
Comment 10 Debbie Wilson CLA 2003-05-07 16:10:02 EDT
Randy/Eric could you perhaps attach the Configuration Details (Help->About 
Eclipse Platform to Configuration Details) to this PR.  Perhaps, Eric, you 
could do this as you don't have Randy's patch installed.
Comment 11 Randy Hudson CLA 2003-05-08 15:44:03 EDT
Created attachment 4827 [details]
2.1 configuration file

I don't see how my patch would affect the configuration file. Here's mine just
for fun.
Comment 12 Randy Hudson CLA 2003-05-08 15:46:54 EDT
Eric and I both have a small utility installed called CheckStyle.  It is a 
builder and audits your source, generating markers for incorrect formatting and 
JavaDoc.

But, I know for sure I have seen this problem on a hierarchy perspective on one 
of my sandbox projects, which does not have the checkstyle nature enabled.
Comment 13 Eric Bordeau CLA 2003-05-08 16:36:55 EDT
Created attachment 4830 [details]
Eric's config file

I haven't added the checkstyle plugin since I upgraded to 2.1, but I do have
references to it in my config file.  I'm not sure how old my workspace is.  I
thought I started fresh with 2.1, but I guess I didn't.
Comment 14 Debbie Wilson CLA 2003-05-12 15:07:27 EDT
Dirk,

Can you give us a concrete example of when the type hierarchy would need to 
update and use the workbench window as a runnable context.

Comment 15 Dirk Baeumer CLA 2003-05-13 05:13:14 EDT
I wasn't able to produce this using the simple case: create type hierarchy on 
TestCase, changed super class of TestCase to Object, and pressed save. This 
both updates the hierarchy and triggers a build.

But I am still pretty convinced that the problem is that two nested operations 
are both using the workbench window as a runnable context. JDT/UI doesn't have 
any code that disables the client area of a window.

Comment 16 Randy Hudson CLA 2003-05-13 10:29:12 EDT
I think it also possible that an asyncExec is involved.  I frequently press 
Ctrl+S, and then F11 before the save is completed. Perhaps the Ctrl+F11/F11 
keystroke is put on the event queue before some kind of asynchronous updating 
of the hierarchy tree or the CUEditor.

As I mentioned before, this *only* seems to happen when I invoke a debug 
session.
Comment 17 Nick Edgar CLA 2003-05-13 14:05:11 EDT
The code that does the disabling in ApplicationWindow.run runs right away.  
Although there is a delay before the progress bar and cancel button are shown 
(to reduce flicker), all controls in the shell (including the menu bar) are 
disabled immediately (except for the cancel button).  So the F11 should not get 
through until after run() returns.  Disabling the menubar disables the 
accelerators.  Although we've had problems with this on other platforms, we're 
confident that it's working properly on Windows.

There is no asyncExec in the processing of Ctrl+S (see 
org.eclipse.ui.internal.SaveAction.run), so there's no chance for F11 to come 
in earlier.

Randy and Eric, I'd appreciate it if you could try to come up with a 
reproduceable case.
Comment 18 Eric Bordeau CLA 2003-05-13 14:15:25 EDT
The problem is it always seems to happen on a window other than the currently
active window (for me anyway).  So, by the time I bring the screwed up window to
the front, it might have been screwed up for a while and I can't really pin down
what it is I did to cause it.  Plus, this doesn't happen to me very often.  

I just started using a fresh, new workspace in case a corrupted workspace might
have been the problem (I really don't know... I just guessing).  I kept the old
workspace around, just in case.  Even with my old workspace, it didn't happen at
all last week.
Comment 19 Nick Edgar CLA 2003-05-15 16:47:28 EDT
It's possible that it could get confused if somehow two operations end up using 
the status line progress monitor at the same time (whether in the same window, 
or different windows).
For example:
operation A starts
operation B starts
operation A ends
operation B ends

Since ApplicationWindow.run() remembers the enabled state of all controls it 
disables (including other shells), B would see them as disabled and would 
restore them as disabled when it ends.

If getActiveWorkbenchWindow() is used, it's also possible that operations are 
targetting the wrong window, if the user has the opportunity to switch windows 
between the time that an action is invoked and the time it starts its operation.
Comment 20 Randy Hudson CLA 2003-05-15 23:37:36 EDT
Per your request, I did some coding today using hierarchy workbench windows. I 
was able to make it happen, but I still can't determine when or how. In 
general, I definitely use ALT+TAB a lot. Sorry, I'll keep trying.
Comment 21 Nick Edgar CLA 2003-05-16 11:37:53 EDT
Randy, would you be able to instrument ApplicationWindow.run so that it prints 
out to the console when it disables and re-enables the controls, and indicates 
which window it's in?  If we have overlapping operations, this will make it 
obvious.

Comment 22 Randy Hudson CLA 2003-05-29 16:58:37 EDT
OK, I've been running for a while with Shell enablement logging.  There are 
many times when ApplicationWindow.run() disables a shell that is already 
disabled.  It doesn't seem to cause the problem.  When the shell is renabled, 
it is restore to false enabledment first, and then restored to enabled.

So, you have:
disable shell, remember "true"
disable shell, remember "false"
restore enablement to "false"
restore enablement to "true"

This is as expected, right?  Or did you expect ABAB instead of ABBA?

I have encountered the problem recently with logging enabled. I am only logging 
when shell enablement changes.  I DID see a println() indicating that the 
disabled shell was enabled, yet its contents was still disabled.  This makes me 
think the problem is in the code that disables/reenables the contents composite 
instead of the shell.  Lines 460-461.  Yet, I have no trouble using the menu on 
the disabled window, which is reenabled in lines 462-463.  What does disabling 
the menubar really do? Does it just block accelerators, but you can still use 
the mouse?  I think I had to use the mouse to save the editor.

I'm re-hacking the run() method to log enablement changes on the contents area 
instead of the shell.
Comment 23 Nick Edgar CLA 2003-05-30 11:21:38 EDT
Disabling the menubar should disable both keyboard and mouse activation.

The fact that the disablement/enablement code is being reentered at all is 
strange, and I'd like to understand how this occurs.
But given that it does, ABBA is the less surprising behaviour.

You should also log the window in which this occurs, if you're not already.
If one operation runs another one, where both try to use the active window as 
their runnable context, then you could get a case where the state is not 
restored symmetrically. 

Actualy, I think this is the problem.  This is caused by the fact that isEnabled
() returns false if any parent controls are disabled.

Consider the following scenario, with two nested operations, op1 and op2, being 
run in two separate windows, A and B:

A.run(op1):
  - disable B's shell (remembers enabled=true)
  - disable A's contents (remembers enabled=true)
  - op1.run():
    - B.run(op2):
      - disable A's shell (remembers enabled=true since only the contents of A 
were disabled above)
      - disable B's contents (remembers enabled=false for these since shell for 
B is disabled, and isEnabled() returns false if parent is disabled)
    - op2.run()
    - restore enabled state for A's shell (enabled=true)
    - restore enabled state for B's contents (** enabled=false **)
  - op2 is done
  - restore enabled state for B's shell (enabled=true)
  - restore enabled state for A's contents (enabled=true)
  - op1 is done

At this point, B's contents remain disabled.

I verified that isEnabled() returns false if the parent control is disabled, 
using the following program. 

public class Test36908 {
	public static void main(String[] args) {
		Display display = new Display ();
		Shell shell = new Shell(display);
		Button button = new Button(shell, SWT.NONE);
		button.setText("Hi there");
		button.pack();
		shell.pack();
		shell.setEnabled(false);
		boolean buttonWasEnabled = button.isEnabled();
		System.out.println(buttonWasEnabled);
		button.setEnabled(false);
		// do some stuff
		button.setEnabled(buttonWasEnabled);
		shell.setEnabled(true);
		shell.open();
		while (!shell.isDisposed ()) {
			if (!display.readAndDispatch ()) display.sleep ();
		}
		display.dispose ();
	}
}

It prints out false, and the button comes up disabled.

Comment 24 Randy Hudson CLA 2003-05-30 15:03:03 EDT
HA HA ;-)! It's not just me then. I got burnt by the same stupid naming issue.  
For some reason, SWT doesn't use the same naming conventions as the rest of 
Java.  I'll try changing contents.isEnabled() to getEnabled().

setEnabled(true) - as expected
isEnabled() - **not** the inverse of setEnabled(), walks up the parent tree
getEnabled() - does what isEnabled() should do

Same for setVisible() and isVisible()/getVisible().

Maybe we should both go do a global search for isVisible() and isEnabled()!! 
When you're done, go yell at SN for me ;-)

Maybe isVisible() could be deprecated and renamed isShowing(), since it is 
really a derived property. similar for is enabled.
Comment 25 Nick Edgar CLA 2003-06-16 16:49:27 EDT
Changed to use getEnabled(), in build I20030616.
Filed bug 38982 for the error-prone API.

Did a search in UI for refs to isEnabled and isVisible.  Found only one other 
problem case in WizardDialog.saveEnableStateAndSet, which I've fixed up.
Comment 26 Randy Hudson CLA 2003-06-16 17:13:44 EDT
Is this a candidate for 2.1 maintenance stream? Maybe the problem isn't that 
bad since I can always exit Eclipse and restart with the menubar, but it sounds 
like a safe fix.
Comment 27 Nick Edgar CLA 2003-06-20 13:50:42 EDT
I wasn't planning on putting it into 2.1.1, since only a couple of people have 
encountered it, both of whom are usually on the latest builds, and we're in the 
process of wrapping up 2.1.1.