Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 184974 - Windows eats button selection event during shell deactivate
Summary: Windows eats button selection event during shell deactivate
Status: CLOSED WONTFIX
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.2.2   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Steve Northover CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
Depends on:
Blocks:
 
Reported: 2007-05-01 16:27 EDT by Mei Thom CLA
Modified: 2022-01-11 16:47 EST (History)
6 users (show)

See Also:


Attachments
Sinppet to demo the dropdown shell re-opened on the second click on the button on Linux (3.15 KB, text/plain)
2007-05-01 16:34 EDT, Mei Thom CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Mei Thom CLA 2007-05-01 16:27:46 EDT
Build ID: M20070212-1330

Steps To Reproduce:
1. Open an Eclipse application which has a Button object.
2. Left mouse click on the button to display a dropdown shell under the button.
3. Left mouse click on the button one more time to try to close the dropdown shell.

Result: On Linux platform (RHEL4 and SLED10), the dropdown shell closes and re-opens right away. On Windows, the dropdown shell closes.

Expected result: as on Windows, user would expect the second click on the button to close the dropdown shell.

More information:
1. This problem happens on linux platform. In my testing, I see it on RHEL4 and SLED10.

2. The dropdown shell has SWT.Deactivate event handler to close the shell. Usually when user clicks on anywhere outside the dropdown shell, the handler will be called to close the dropdown shell. So naturally user would expect the second click on the button will close the dropdown shell too.

3. I found that on Linux, on the second click on the button, not only the dropdown shell's SWT.Deactivate event handler is called, the button's mouseDown event handler is called too. But on Windows, only the dropdown shell's SWT.Deactivate event handler is called. Button does not catch any mouse event.

4. In SWT Button, only when the mouseUp event handler sees that there is a mouseDown event before it, then it will call listener's SWT.Selection event handler. Therefore, on Linux, on the second click on the button, since mouseDown event happens, mouseUp event will call the listener's selection handler which will open the dropdown shell again. But on Windows, on the second click on the button, there is not a mouseDown event before the mouseUp event, so the selection listener is not called to open the dropdown shell.

I will attach a snippet to show the event fired on the console.
Comment 1 Mei Thom CLA 2007-05-01 16:34:45 EDT
Created attachment 65531 [details]
Sinppet to demo the dropdown shell re-opened on the second click on the button on Linux

Here are the println statements on the event fired on two clicks on the button:

On Windows:
First mouse down on the Open button:
Open button entering mouseDown event handler

First mouse up on the Open button to display the dropdown shell:
Open button entering mouseUp event handler
Open button entering widgetSelected event handler and will show the dropdown shell

Then second mouse down on the Open button:
dropDownShell entering Deactivate event handler and will hide the dropdown shell
dropDownShell entering Deactivate event handler and will hide the dropdown shell

Second mouse up the Open button
Open button entering mouseUp event handler

As a result, the dropdown shell is closed.


==============================================================================

On Linux:

First mouse down on the Open button:
Open button entering mouseDown event handler

First mouse up on the Open button to display the dropdown shell:
Open button entering mouseUp event handler
Open button entering widgetSelected event handler and will show the dropdown shell
(Up till here, both Windows and Linux are the same behavior)

Second mouse down on the Open button:
dropDownShell entering Deactivate event handler and will hide the dropdown shell
Open button entering mouseDown event handler

Second mouse up the Open button:
Open button entering mouseUp event handler
Open button entering widgetSelected event handler and will show the dropdown shell

As a result, the dropdown shell is still opened.
Comment 2 Steve Northover CLA 2007-05-14 18:38:48 EDT
Bogdan, can you conifrm this bug?
Comment 3 Bogdan Gheorghe CLA 2007-05-17 09:23:47 EDT
3.3M7

It turns out that there is a bug here but the bug is actually on Windows - Linux is actually doing the right thing here. Running your snippet on Windows, clicking on the Open button when the on_top shell is visible causes the on_top shell to close but something eats the mouse down event. So the 'extra' mouseDown event you initially reported as seeing on Linux is actually correct and you should be getting one on Windows as well.

Also, a few notes about your snippet:


1) You can work around this bug by running the hide code in an asyncExec

2) DROP_DOWN is not a valid style hint for a shell - it has no effect on it

3) You should not use Device.DEBUG=true in your snippets (or code) as it forces the X server to run synchronously 

We're currently trying to find out what's happened to the mouseDown event on Windows.
Comment 4 Mei Thom CLA 2007-05-17 09:54:17 EDT
Thanks for all this information!

We think that the problem is on Linux because we want the behavior on Windows, which means clicking on the button when the dropdown window is visible should close the dropdown window. 
1. We can try the asyncExec.
2. We use the DROP_DOWN style bit to get a shadow around the dropdown shell.
3. I got the suggestion in another bugzilla report to use Device.DEBUG=true in order to get more debug info. And I don't see the difference between using it and not using it. Thanks for telling me the difference.
Comment 5 Mike Wilson CLA 2008-03-27 14:57:42 EDT
Mei Thom, have you found a path through this that works for you?

Comment 6 Raji Akella CLA 2008-03-27 15:40:27 EDT
Chih-Hung, can you take a look at this and provide a response?

Comment 7 Raji Akella CLA 2008-04-07 15:27:37 EDT
To clarify.. we are happy with the way it works on Windows. We want Linux to behave the same way as Windows. Are you saying that is not the right approach and Linux is working as expected? 

Comment 8 Chih-Hung Chiang CLA 2008-04-07 15:47:55 EDT
We solve this issue by changing our design. The SWT.Deactivate event will not hide the Shell if it is caused by that Button and the SWT.Selection event will hide/show the Shell depend on the state. 
Comment 9 Bogdan Gheorghe CLA 2008-04-09 12:49:29 EDT
Glad to hear you have a workaround. I understand that this is a consistency problem between platforms. The real solution here is to find out why Win32 is eating the SelectionEvent on the second mouse down. 

Moving over to Steve.
Comment 10 Steve Northover CLA 2008-04-09 15:52:22 EDT
This code works around the problem (the behavior is the same on Windows and Linux):

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

public class PR_184974 {
	static Display display = null;
	static Shell shell = null;
	static Button button = null;
	static Shell dropDownShell = null;

	public static void main(String[] args) {
		Device.DEBUG = true;
		display = new Display();
		shell = new Shell(display);
		shell.setLayout(new RowLayout());

		// create the drop down shell
		dropDownShell = new Shell(shell, SWT.ON_TOP | SWT.DROP_DOWN);
		dropDownShell.setLayout(new RowLayout());
		dropDownShell.setVisible(false);
		dropDownShell.addListener(SWT.Deactivate, new Listener() {
			public void handleEvent(Event event) {
				System.out.println("dropDownShell entering Deactivate event handler and will hide the dropdown shell");
				display.asyncExec(new Runnable () {
					public void run () {
						hideDropDown();
					}
				});
			}
		});

		dropDownShell.addListener(SWT.Close, new Listener() {
			public void handleEvent(Event event) {
				hideDropDown();
			}
		});

		// create the button
		button = new Button(shell, SWT.PUSH);
		button.setText("Open");
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				if (!dropDownShell.isVisible()) {
					System.out.println("Open button entering widgetSelected event handler and will show the dropdown shell");
					if (dropDownShell != null && !dropDownShell.isDisposed()) {
						showDropDown();
					}
				}
			}
		});

		button.addMouseListener(new MouseAdapter() {
			public void mouseDown(MouseEvent e) {
				System.out.println("Open button entering mouseDown event handler");
				super.mouseDown(e);
			}
			public void mouseUp(MouseEvent e) {
				System.out .println("Open button entering mouseUp event handler");
				super.mouseUp(e);
			}
		});

		shell.setSize(300, 300);
		shell.addDisposeListener(new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				if (dropDownShell != null && !dropDownShell.isDisposed()) {
					dropDownShell.dispose();
					dropDownShell = null;
				}
			}
		});
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}

	private static void showDropDown() {
		if (dropDownShell != null && !dropDownShell.isDisposed()) {
			dropDownShell.setText("This is a drop down shell");
			dropDownShell.setSize(100, 200);
			Rectangle buttonRect = button.getBounds();
			Point p = button.getParent().toDisplay(new Point(buttonRect.x, buttonRect.y + buttonRect.height));
			dropDownShell.setLocation(p.x, p.y);
			dropDownShell.setVisible(true);
			dropDownShell.setFocus();
		}
	}

	private static void hideDropDown() {
		dropDownShell.setVisible(false);
	}

}
Comment 11 Steve Northover CLA 2008-04-09 15:55:57 EDT
To be clear, the selection event is delivered and the shell pops back up (which is unwanted behavior for the code snippet, but correct).
Comment 12 Eclipse Webmaster CLA 2019-09-06 16:04:02 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.
Comment 13 Eclipse Genie CLA 2022-01-11 16:47:45 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug.

If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.