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

Bug 364402

Summary: NPE in MinMaxAddon with non-visible editor area
Product: [Eclipse Project] Platform Reporter: Brian de Alwis <bsd>
Component: UIAssignee: Eric Moffatt <emoffatt>
Status: VERIFIED FIXED QA Contact: Eric Moffatt <emoffatt>
Severity: normal    
Priority: P3 CC: dean.t.roberts, remy.suen
Version: 4.2   
Target Milestone: 4.2 M4   
Hardware: PC   
OS: Mac OS X - Carbon (unsup.)   
Whiteboard:

Description Brian de Alwis CLA 2011-11-21 13:16:22 EST
BuildId: I20111028-1100

I'm fiddling with an app that uses the compatibility layer that defines a custom perspective where the editor area is set to be not visible.  When running with the org.eclipse.e4.ui.swt.addons bundle, I double-clicked on a view tab that ultimately triggered an NPE in MinMaxAddon#createTrim().

The problem arises as:

1. MinMaxAddon's CTFDblClickListener#mouseDoubleClickListener marks the tab control to be maximized, 
2. This causes the part stack to have a new MAXIMIZED tag item.
3. This triggers MinMaxAddon's #tagChangeListener's handleEvent to try to maximize the part stack
4. The end of MinMaxAddon#maximize() fetches the editor area placeholder and adds a MINIMIZED tag.
5. This then triggers the MinMaxAddon's #tagChangeListener's handleEvent on the editor area MPlaceholder
6. This handler calls MinMaxAddon#minimize() on the MPlaceholder, which attempts to create trim for the placeholder.
7. MinMaxAddOn#createTrim() fetches bounds of the element's widget, which does not exist as it's not rendered:

	private void createTrim(MUIElement element) {
		...
		Control stackCtrl = (Control) element.getWidget();
		Rectangle stackBounds = stackCtrl.getBounds();   // NPE

My guess is that MinMaxAddon#minimize() and maximize() should have is-rendered guards for the provided element?




Stack values at MinMaxAddon#createTrim():
-----------------------
this = MinMaxAddon

element = org.eclipse.e4.ui.model.application.ui.advanced.impl.PlaceholderImpl@486985a3 (elementId: org.eclipse.ui.editorss, tags: [MinimizedByZoom, Minimized], contributorURI: null) (widget: null, renderer: null, toBeRendered: false, onTop: false, visible: true, containerData: 6000, accessibilityPhrase: null) (closeable: false)

window = org.eclipse.e4.ui.model.application.ui.basic.impl.TrimmedWindowImpl@32e6e42e (elementId: IDEWindow, tags: [topLevel], contributorURI: platform:/plugin/org.eclipse.ui.workbench) (widget: Shell {Eclipse SDK 4.0}, renderer: org.eclipse.e4.ui.workbench.renderers.swt.WBWRenderer@157dd1d1, toBeRendered: true, onTop: false, visible: true, containerData: null, accessibilityPhrase: null) (label: Eclipse SDK 4.0, iconURI: null, tooltip: null, context: TrimmedWindowImpl (IDEWindow) Context, variables: [], x: 79, y: 32, width: 1024, height: 768)

winShell = a shell

trimId = org.eclipse.ui.editorss(app.perspective)

trimStack = org.eclipse.e4.ui.model.application.ui.menu.impl.ToolControlImpl@5382ab40 (elementId: org.eclipse.ui.editorss(px.perspective), tags: null, contributorURI: null) (widget: null, renderer: null, toBeRendered: true, onTop: false, visible: true, containerData: null, accessibilityPhrase: null) (contributionURI: platform:/plugin/org.eclipse.e4.ui.workbench.addons.swt/org.eclipse.e4.ui.workbench.addons.minmax.TrimStack, object: null)

winBounds = Rectangle {79, 32, 1024, 768}

winCenterX = 512

stackCtrl = null
-----------------------


Stack values at at MinMaxAddon#tagChangeListener's #handleEvent:
-----------------------
event = org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/application/ApplicationElement/tags/ADD]

changedObject = org.eclipse.e4.ui.model.application.ui.advanced.impl.PlaceholderImpl@486985a3 (elementId: org.eclipse.ui.editorss, tags: [MinimizedByZoom, Minimized], contributorURI: null) (widget: null, renderer: null, toBeRendered: false, onTop: false, visible: true, containerData: 6000, accessibilityPhrase: null) (closeable: false)

tag = Minimized

oldVal = null
-----------------------


Stack:
Daemon Thread [Thread-1] (Suspended (exception NullPointerException))	
	MinMaxAddon.createTrim(MUIElement) line: 592	
	MinMaxAddon.minimize(MUIElement) line: 451	
	MinMaxAddon$6.handleEvent(Event) line: 297	
	UIEventHandler$1.run() line: 41	
	UISynchronizer(Synchronizer).syncExec(Runnable) line: 180	
	UISynchronizer.syncExec(Runnable) line: 150	
	Display.syncExec(Runnable) line: 4614	
	E4Application$1.syncExec(Runnable) line: 185	
	UIEventHandler.handleEvent(Event) line: 38	
	EventHandlerWrapper.handleEvent(Event, Permission) line: 197	
	EventHandlerTracker.dispatchEvent(EventHandlerWrapper, Permission, int, Event) line: 197	
	EventHandlerTracker.dispatchEvent(Object, Object, int, Object) line: 1	
	EventManager.dispatchEvent(Set, EventDispatcher, int, Object) line: 230	
	ListenerQueue.dispatchEventSynchronous(int, Object) line: 148	
	EventAdminImpl.dispatchEvent(Event, boolean) line: 135	
	EventAdminImpl.sendEvent(Event) line: 78	
	EventComponent.sendEvent(Event) line: 39	
	EventBroker.send(String, Object) line: 81	
	UIEventPublisher.notifyChanged(Notification) line: 55	
	PlaceholderImpl(BasicNotifierImpl).eNotify(Notification) line: 380	
	EDataTypeUniqueEList<E>(EcoreEList<E>).dispatchNotification(Notification) line: 255	
	EDataTypeUniqueEList<E>(NotifyingListImpl<E>).addUnique(E) line: 310	
	EDataTypeUniqueEList<E>(AbstractEList<E>).add(E) line: 307	
	MinMaxAddon.maximize(MUIElement) line: 519	
	MinMaxAddon$6.handleEvent(Event) line: 299	
	UIEventHandler$1.run() line: 41	
	UISynchronizer(Synchronizer).syncExec(Runnable) line: 180	
	UISynchronizer.syncExec(Runnable) line: 150	
	Display.syncExec(Runnable) line: 4614	
	E4Application$1.syncExec(Runnable) line: 185	
	UIEventHandler.handleEvent(Event) line: 38	
	EventHandlerWrapper.handleEvent(Event, Permission) line: 197	
	EventHandlerTracker.dispatchEvent(EventHandlerWrapper, Permission, int, Event) line: 197	
	EventHandlerTracker.dispatchEvent(Object, Object, int, Object) line: 1	
	EventManager.dispatchEvent(Set, EventDispatcher, int, Object) line: 230	
	ListenerQueue.dispatchEventSynchronous(int, Object) line: 148	
	EventAdminImpl.dispatchEvent(Event, boolean) line: 135	
	EventAdminImpl.sendEvent(Event) line: 78	
	EventComponent.sendEvent(Event) line: 39	
	EventBroker.send(String, Object) line: 81	
	UIEventPublisher.notifyChanged(Notification) line: 55	
	PartStackImpl(BasicNotifierImpl).eNotify(Notification) line: 380	
	EDataTypeUniqueEList<E>(EcoreEList<E>).dispatchNotification(Notification) line: 255	
	EDataTypeUniqueEList<E>(NotifyingListImpl<E>).addUnique(E) line: 310	
	EDataTypeUniqueEList<E>(AbstractEList<E>).add(E) line: 307	
	MinMaxAddon.setState(MUIElement, String) line: 184	
	MinMaxAddon.access$1(MinMaxAddon, MUIElement, String) line: 177	
	MinMaxAddon$2.mouseDoubleClick(MouseEvent) line: 140	
	TypedListener.handleEvent(Event) line: 195	
	EventTable.sendEvent(Event) line: 84	
	Display.sendEvent(EventTable, Event) line: 4129	
	CTabFolder(Widget).sendEvent(Event) line: 1457	
	CTabFolder(Widget).sendEvent(int, Event, boolean) line: 1480	
	CTabFolder(Widget).sendEvent(int, Event) line: 1465	
	CTabFolder(Widget).notifyListeners(int, Event) line: 1270	
	Display.runDeferredEvents() line: 3975	
	Display.readAndDispatch() line: 3614	
	PartRenderingEngine$9.run() line: 976	
	Realm.runWithDefault(Realm, Runnable) line: 332	
	PartRenderingEngine.run(MApplicationElement, IEclipseContext) line: 892	
	E4Workbench.createAndRunUI(MApplicationElement) line: 90	
	Workbench$3.run() line: 565	
	Realm.runWithDefault(Realm, Runnable) line: 332	
	Workbench.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 520	
	PlatformUI.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 149	
	PowerExplorerApplication.start(IApplicationContext) line: 81	
	EclipseAppHandle.run(Object) line: 196	
	EclipseAppLauncher.runApplication(Object) line: 110	
	EclipseAppLauncher.start(Object) line: 79	
	EclipseStarter.run(Object) line: 352	
	EclipseStarter.run(String[], Runnable) line: 179	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25	
	Method.invoke(Object, Object...) line: 597	
	Main.invokeFramework(String[], URL[]) line: 624	
	Main.basicRun(String[]) line: 579	
	Main.run(String[]) line: 1431	
	Main.main(String[]) line: 1407
Comment 1 Eric Moffatt CLA 2011-11-28 13:57:20 EST
Pushed in >20111128.

commit fc52dabeb6a3cc1905876f8ed9571f5d8c025e9c

Safe'd up the code by preventing non-TBR elements from having the MINIMIZED tag set on it.
Comment 2 Eric Moffatt CLA 2011-12-08 15:03:47 EST
Verified in I20111205-2330.