Community
Participate
Working Groups
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.
I assume you're on 2.1. Anything in the .log?
Yes, 2.1, nothing in the log.
Is this with or without your patch to the workbench?
I haven't installed Randy's patch and I get this problem.
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.
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).
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?
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?)
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.