blob: 746fcc31455eac4b26e4149cfb9995ad66a3514b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018 Red Hat and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.tests.gtk.snippets;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
public class Bug521506_FakeClick {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("Snippet"); //$NON-NLS-1$
shell.setLocation(100, 100);
shell.setLayout(new GridLayout());
Button button = new Button(shell, SWT.PUSH);
button.setText("Test Button"); //$NON-NLS-1$
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
System.err.println("TEST BUTTON CLICKED"); //$NON-NLS-1$
}
});
// create shell menu bar
final Menu menuBar = new Menu(shell, SWT.BAR);
MenuItem menuItem = new MenuItem(menuBar, SWT.CASCADE);
menuItem.setText("Menu"); //$NON-NLS-1$
final Menu menu = new Menu(shell, SWT.DROP_DOWN);
menuItem.setMenu(menu);
MenuItem clickItem = new MenuItem(menu, SWT.PUSH);
clickItem.setText("Item"); //$NON-NLS-1$
clickItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
System.err.println("ITEM CLICKED"); //$NON-NLS-1$
}
});
shell.setMenuBar(menuBar);
new Thread(() -> {
try {
Thread.sleep(1000);
// click on button
display.syncExec(() -> {
Rectangle bounds = button.getBounds();
final Event mouseMove = new Event();
mouseMove.type = SWT.MouseMove;
mouseMove.x = button.toDisplay(bounds.x + bounds.width / 2, 0).x;
mouseMove.y = button.toDisplay(0, bounds.y + bounds.height / 2).y;
display.post(mouseMove);
});
Thread.sleep(100);
display.syncExec(() -> {
final Event mouseDown = new Event();
mouseDown.type = SWT.MouseDown;
mouseDown.button = 1;
mouseDown.widget = button;
display.post(mouseDown);
});
Thread.sleep(10);
display.syncExec(() -> {
final Event mouseUp = new Event();
mouseUp.type = SWT.MouseUp;
mouseUp.button = 1;
mouseUp.widget = button;
display.post(mouseUp);
});
Thread.sleep(1000);
// open menu
display.syncExec(() -> {
Rectangle bounds = getBounds(menuItem);
final Event mouseMove = new Event();
mouseMove.type = SWT.MouseMove;
mouseMove.x = bounds.x + bounds.width / 2;
mouseMove.y = bounds.y + bounds.height / 2;
display.post(mouseMove);
});
Thread.sleep(100);
display.syncExec(() -> {
final Event mouseDown = new Event();
mouseDown.type = SWT.MouseDown;
mouseDown.button = 1;
mouseDown.widget = menuItem;
display.post(mouseDown);
});
Thread.sleep(10);
display.syncExec(() -> {
final Event mouseUp = new Event();
mouseUp.type = SWT.MouseUp;
mouseUp.button = 1;
mouseUp.widget = menuItem;
display.post(mouseUp);
});
Thread.sleep(100);
// click on item
display.syncExec(() -> {
Rectangle bounds = getBounds(clickItem);
final Event mouseMove = new Event();
mouseMove.type = SWT.MouseMove;
mouseMove.x = bounds.x + bounds.width / 2;
mouseMove.y = bounds.y + bounds.height / 2;
display.post(mouseMove);
});
Thread.sleep(200);
display.syncExec(() -> {
final Event mouseDown = new Event();
mouseDown.type = SWT.MouseDown;
mouseDown.button = 1;
mouseDown.widget = clickItem;
display.post(mouseDown);
});
Thread.sleep(10);
display.syncExec(() -> {
final Event mouseUp = new Event();
mouseUp.type = SWT.MouseUp;
mouseUp.button = 1;
mouseUp.widget = clickItem;
display.post(mouseUp);
});
Thread.sleep(1000);
// display.syncExec(() -> shell.dispose());
} catch (Throwable t) {
t.printStackTrace();
}
}).start();
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
final static Rectangle getBounds(final MenuItem menuItem) {
Rectangle itemRect = getBounds((Object) menuItem);
Rectangle menuRect = getBounds(menuItem.getParent());
if ((menuItem.getParent().getStyle() & SWT.RIGHT_TO_LEFT) != 0) {
itemRect.x = menuRect.x + menuRect.width - itemRect.width - itemRect.x;
} else {
itemRect.x += menuRect.x;
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=38436#c143
itemRect.y += menuRect.y;
return itemRect;
}
private final static Rectangle getBounds(final Object object) {
try {
return (Rectangle) invoke(object, "getBounds"); //$NON-NLS-1$
} catch (Throwable th) {
th.printStackTrace();
NoSuchMethodError error = new NoSuchMethodError(th.getMessage());
error.initCause(th);
throw error;
}
}
private final static Object invoke(final Object obj, final String methodName, final Object... args) throws SecurityException, NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
return invoke(obj.getClass(), methodName, true, obj, args);
}
private final static Object invoke(final Class<?> clazz, final String methodName, final boolean declaredMethod, final Object obj, final Object... args) throws SecurityException,
NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
Class<?>[] params = new Class[args.length];
for (int i = 0; i < args.length; i++) {
Class<?> argClazz = args[i].getClass();
try {
Field typeField = argClazz.getField("TYPE"); //$NON-NLS-1$
params[i] = (Class<?>) typeField.get(null);
} catch (NoSuchFieldException e) {
params[i] = argClazz;
}
}
return invoke(clazz, methodName, declaredMethod, obj, params, args);
}
private final static Object invoke(final Class<?> clazz, final String methodName, final boolean declaredMethod, final Object obj, final Class<?>[] params, final Object... args)
throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
Method method;
if (declaredMethod) {
method = clazz.getDeclaredMethod(methodName, params);
method.setAccessible(true);
} else {
method = clazz.getMethod(methodName, params);
}
return method.invoke(obj, args);
}
}