Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 374320 - ContextMenuHandler should use new MenuDetect API so controls can position context menu
Summary: ContextMenuHandler should use new MenuDetect API so controls can position con...
Status: VERIFIED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.8   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: 3.8 M7   Edit
Assignee: Markus Keller CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-03-14 17:50 EDT by Carolyn MacLeod CLA
Modified: 2012-05-07 13:28 EDT (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Carolyn MacLeod CLA 2012-03-14 17:50:47 EDT
Bug 374147 added new MenuDetect API for 3.8/4.2 M6. This is the first step in fixing bug 110005. Please use this API in ContextMenuHandler on Mac - here's the code to use, below. I tested this on Mac using shift+F10, and on Windows by creating a key binding for Show Context Menu (although the code will likely never run on Windows or Linux because shift+F10 is already bound by the platform... but it does work if someone want to rebind).
---- 

package org.eclipse.ui.internal.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.handlers.HandlerUtil;

public class ContextMenuHandler extends AbstractHandler {
	public Object execute(ExecutionEvent exEvent) throws ExecutionException {
		Shell shell = HandlerUtil.getActiveShell(exEvent);
		Display display = shell == null ? Display.getCurrent() : shell.getDisplay();
		Control focusControl = display.getFocusControl();
		if (focusControl != null) {
			Point pt = display.getCursorLocation();
			Event event = new Event ();
			event.x = pt.x;
			event.y = pt.y;
			event.detail = SWT.MENU_KEYBOARD;
			focusControl.notifyListeners (SWT.MenuDetect, event);
			//widget could be disposed at this point
			if (focusControl.isDisposed ()) return null;
			if (!event.doit) return null;
			Menu menu = focusControl.getMenu ();
			if (menu != null && !menu.isDisposed ()) {
				if (event.x != pt.x || event.y != pt.y) {
					menu.setLocation (event.x, event.y);
				}
				menu.setVisible(true);
			}
		}
		return null;
	}
}
Comment 1 Carolyn MacLeod CLA 2012-03-14 18:04:05 EDT
It would be great if this new code could go in soon (right after M6 if
possible) so that I can use it when I am testing future changes to fix bug 110005.

Remy, this is the new API we discussed. I cc'd you because you asked to be notified when it was in.
Comment 2 Markus Keller CLA 2012-03-30 09:49:12 EDT
Paul are you looking into this, or shall I take the bug?

I just tried Car's patch, and it looks good for widgets that have a custom menu set. But we should keep the old 'else' branch so that also native menus are shown:

public Object execute(ExecutionEvent exEvent) throws ExecutionException {
	Shell shell = HandlerUtil.getActiveShell(exEvent);
	Display display = shell == null ? Display.getCurrent() : shell.getDisplay();
	Control focusControl = display.getFocusControl();
	if (focusControl != null) {
		Point pt = display.getCursorLocation();
		Event event = new Event();
		event.x = pt.x;
		event.y = pt.y;
		event.detail = SWT.MENU_KEYBOARD;
		focusControl.notifyListeners(SWT.MenuDetect, event);
		// widget could be disposed at this point
		if (focusControl.isDisposed())
			return null;
		if (!event.doit)
			return null;
		Menu menu = focusControl.getMenu();
		if (menu != null && !menu.isDisposed()) {
			if (event.x != pt.x || event.y != pt.y) {
				menu.setLocation(event.x, event.y);
			}
			menu.setVisible(true);
		} else {
			Point size = focusControl.getSize();
			Point center = focusControl.toDisplay(Geometry.divide(size, 2));

			Point location = focusControl.toDisplay(0, 0);

			Event mouseEvent = new Event();
			mouseEvent.widget = focusControl;

			if (event.x < location.x || location.x + size.x <= event.x || event.y < location.y
					|| location.y + size.y <= event.y) {
				mouseEvent.x = center.x;
				mouseEvent.y = center.y;
				mouseEvent.type = SWT.MouseMove;
				display.post(mouseEvent);
			} else {
				mouseEvent.x = event.x;
				mouseEvent.y = event.y;
			}

			mouseEvent.button = 3;
			mouseEvent.type = SWT.MouseDown;
			display.post(mouseEvent);

			mouseEvent.type = SWT.MouseUp;
			display.post(mouseEvent);
		}
	}
	return null;
}
Comment 3 Paul Webster CLA 2012-03-30 14:40:13 EDT
Hi Markus,

I wasn't looking at this specifically, please take it.

PW
Comment 5 Eric Moffatt CLA 2012-05-07 11:02:07 EDT
Verified (visually) in I20120503-1800

Markus, is there a 3.x version of this defect? If not could you please verify this on 3.x and update this defect ?
Comment 6 Markus Keller CLA 2012-05-07 13:28:31 EDT
Verified in I20120502-2000 (3.8 M7). I've released the fix into both branches without a separate bug.

See bug 110005 comment 22 for remaining issues in SWT.