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

Bug 368767

Summary: Del accelerator wins over input field
Product: [Eclipse Project] Platform Reporter: Thomas Singer <eclipse>
Component: SWTAssignee: Platform-SWT-Inbox <platform-swt-inbox>
Status: RESOLVED WORKSFORME QA Contact:
Severity: major    
Priority: P3 CC: eclipse.felipe, ram
Version: 3.7.1   
Target Milestone: ---   
Hardware: All   
OS: All   
Whiteboard: stalebug

Description Thomas Singer CLA 2012-01-16 15:33:13 EST
Build Identifier: 

Please run this sample:

import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class DelKeyTest {

	public static void main(String[] args) {
		final Display display = new Display();

		final Shell shell = new Shell(display, SWT.SHELL_TRIM);
		final Menu menuBar = new Menu(shell, SWT.BAR);
		shell.setMenuBar(menuBar);
		final Menu fileMenu = new Menu(menuBar);
		final MenuItem fileMenuItem = new MenuItem(menuBar, SWT.CASCADE);
		fileMenuItem.setText("&File");
		fileMenuItem.setMenu(fileMenu);
		final MenuItem delItem = new MenuItem(fileMenu, SWT.PUSH);
		delItem.setText("Delete\tDel");
		delItem.setAccelerator(SWT.DEL);
		delItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				System.out.println("Menu item selected");
			}
		});

		shell.setLayout(new FillLayout());

		final Text textField = new Text(shell, SWT.SINGLE | SWT.BORDER);
		textField.setText("ab");
		textField.setSelection(1);

		new Button(shell, SWT.PUSH).setText("Here Del should invoke the menu item");

		shell.pack();
		shell.setMinimumSize(shell.getSize());
		shell.open();

		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}

		display.dispose();
	}
}

If you press the Del key to delete some text in the input field, the menu item's listener will be invoked. It looks like this can't be prevented/worked-around. Imagine a larger GUI where, e.g. tables and input fields are located in one frame. Del should work on the selected table row object, but pressing it in the input field triggers the wrong action.

If I recall correctly, in Swing the key event could first processed by the focused control. If it did not handle it, its parent was asked, then the parent's parent. If no parent could handle it, the accelerators were checked. IMHO, this would be the correct work-flow for SWT, too.

This is a quite serious problem for us, because we are porting a Swing application to SWT and now have to prevent the user to use certain common shortcuts as accelerators which worked fine in Swing.

Reproducible: Always
Comment 1 Thomas Singer CLA 2012-01-18 02:42:52 EST
Same applies to other keys like Enter or Space.
Comment 2 Thomas Singer CLA 2012-01-28 12:24:10 EST
Is there a work-around this serious problem?
Comment 3 Felipe Heidrich CLA 2012-01-30 11:21:16 EST
The toolkit is actually doing what it is suppose to do. Accelerators have higher priority than key bindings.

The only solution that comes to my mind is to report a bug against the component that is using SWT.DEL as an accelerator.
Comment 4 Thomas Singer CLA 2012-01-30 13:41:26 EST
Let's look at a common example - Thunderbird. You can press N to go to the next message, Del to delete a message or folder. But this does not prevent to type the N into a search input field or deleting characters using Del.
Comment 5 Thomas Singer CLA 2012-01-30 13:43:17 EST
(In reply to comment #3)
> The toolkit is actually doing what it is suppose to do. Accelerators have
> higher priority than key bindings.

What is a "toolkit"?

> The only solution that comes to my mind is to report a bug against the
> component that is using SWT.DEL as an accelerator.

Menu item or text field?
Comment 6 Felipe Heidrich CLA 2012-01-30 14:03:01 EST
(In reply to comment #5)
> (In reply to comment #3)
> > The toolkit is actually doing what it is suppose to do. Accelerators have
> > higher priority than key bindings.
> 
> What is a "toolkit"?

just a short for Standard Widget Toolkit (SWT). sorry.

> 
> > The only solution that comes to my mind is to report a bug against the
> > component that is using SWT.DEL as an accelerator.
> 
> Menu item or text field?

the menu item is bad.
Comment 7 Felipe Heidrich CLA 2012-01-30 14:09:40 EST
(In reply to comment #4)
> Let's look at a common example - Thunderbird. You can press N to go to the next
> message, Del to delete a message or folder. But this does not prevent to type
> the N into a search input field or deleting characters using Del.

that can be implemented in SWT too. Instead of using accelerators the application could use a key down filter in display to implement N and Del, except that it should let the control have the key when focusControl is the search input field.
Comment 8 CLA 2012-02-01 11:40:12 EST
For a workaround could you add a focus listener to fields?

        textField.addFocusListener(new FocusListener() {
            @Override
            public void focusLost(FocusEvent e) {
                delItem.setAccelerator(SWT.DEL);
            }
            
            @Override
            public void focusGained(FocusEvent e) {
                delItem.setAccelerator(0);
            }
        });
Comment 9 Thomas Singer CLA 2012-02-01 12:16:34 EST
That is not possible, because 1) the Del accelerator might be used by any menu item (they are freely configurable by the user) and 2) the text fields have no reference to the actions/menu items.
Comment 10 Thomas Singer CLA 2012-02-01 12:19:10 EST
Maybe the solution would be to implement own shell-based accelerator handling code (instead of setting the menu item's accelerator property). Any hints, complains or suggestions?
Comment 11 Felipe Heidrich CLA 2012-02-01 13:24:52 EST
(In reply to comment #10)
> Maybe the solution would be to implement own shell-based accelerator handling
> code (instead of setting the menu item's accelerator property). Any hints,
> complains or suggestions?

That is the strategy used by Eclipse.
Comment 12 Thomas Singer CLA 2012-02-01 14:09:09 EST
I've tried registering a KeyDown listener on the menu's parent shell (decorations), but it is not invoked. I'm not sure whether registering a display filtering listener would be the best (most performant) solution. Any hints?
Comment 13 Felipe Heidrich CLA 2012-02-01 15:27:56 EST
(In reply to comment #12)
> I've tried registering a KeyDown listener on the menu's parent shell
> (decorations), but it is not invoked. I'm not sure whether registering a
> display filtering listener would be the best (most performant) solution. Any
> hints?

Display.addFilter()
it is the only say it can work.
Comment 14 Thomas Singer CLA 2012-02-06 10:25:21 EST
(In reply to comment #13)
> Display.addFilter()
> it is the only way it can work.

How to implement? As I understand it, the filter is invoked before anything else can process it. But I need to process it *after* it might have been processed by the input field.
Comment 15 Thomas Singer CLA 2012-02-10 15:48:18 EST
> > > The only solution that comes to my mind is to report a bug against the
> > > component that is using SWT.DEL as an accelerator.
> > 
> > Menu item or text field?
> 
> the menu item is bad.

See bug 371288
Comment 16 Felipe Heidrich CLA 2012-02-13 10:34:24 EST
> How to implement? As I understand it, the filter is invoked before anything
> else can process it. But I need to process it *after* it might have been
> processed by the input field.

Check where the focus is, if the focus is in Text we don't do anything.
Comment 17 Thomas Singer CLA 2012-02-13 11:07:35 EST
> > > The only solution that comes to my mind is to report a bug against the
> > > component that is using SWT.DEL as an accelerator.
> > 
> > Menu item or text field?
> 
> the menu item is bad.

Very helpful suggestion, especially because you closed it as immediately as Wont-Fix.
Comment 18 Thomas Singer CLA 2012-02-13 11:57:02 EST
(In reply to comment #16)
> > How to implement? As I understand it, the filter is invoked before anything
> > else can process it. But I need to process it *after* it might have been
> > processed by the input field.
> 
> Check where the focus is, if the focus is in Text we don't do anything.

Just to continue thinking about it: I should add a KeyDown filter listener on the Display, right? And, if the control is a Text or StyledText control, I should check for the keyCode, whether it is equal to, e.g., SWT.DEL, right? If it is the case, I should set doIt to false and hence prevent ANY further processing, e.g. by explicit key listeners?
Comment 19 Felipe Heidrich CLA 2012-02-13 13:45:11 EST
(In reply to comment #18)

> Just to continue thinking about it: I should add a KeyDown filter listener on
> the Display, right? And, if the control is a Text or StyledText control, I
> should check for the keyCode, whether it is equal to, e.g., SWT.DEL, right? If
> it is the case, I should set doIt to false and hence prevent ANY further
> processing, e.g. by explicit key listeners?

Can you just add a listener to the control (likely a Table or Tree) that actually needs to handle the Del instead ?

Why do you need Delete to be an accelerator ?
Comment 20 Thomas Singer CLA 2012-02-13 14:21:38 EST
(In reply to comment #19)
> Can you just add a listener to the control (likely a Table or Tree) that
> actually needs to handle the Del instead ?
> 
> Why do you need Delete to be an accelerator ?

Please see comment #9.
Comment 21 Thomas Singer CLA 2012-02-13 14:25:36 EST
Adding a KeyDown filter listener to the Display allows to get notified *before* any key event is triggered. Is there also a way to add a similar listener, so I can find out whether the KeyDown event *has been processed*?
Comment 22 Felipe Heidrich CLA 2012-02-14 16:29:16 EST
(In reply to comment #21)
> Adding a KeyDown filter listener to the Display allows to get notified *before*
> any key event is triggered. Is there also a way to add a similar listener, so I
> can find out whether the KeyDown event *has been processed*?

key events are sent always before the control has a chance to handle it (so that the application can stop the default handler), this is true for Display filters as well as plain listeners. There is no "event-after" variation for this event.

In your case you do not want your delete listener to execute all the time, for example you don't want it to execute when the text control has the focus.
What are the cases where you want it to run ? Maybe when some table or tree has the focus, maybe a few other controls ? I would add a key listener just to the control where I want the delete listener to execute. I would not try to implement a global listener for the delete listener. Sorry, I don't think there is an generic solution for this problem. What I just wrote is the usual way developer solve this problem (Eclipse does that all over the place, try delete when the package explorer has the focus).

During the Display#filter you do not have a way to be called  after for key down event, during the key down event you do not know if the control will consume the key or not (it can't be decided).
Comment 23 Thomas Singer CLA 2012-02-17 05:55:04 EST
I don't think that scattering the listeners to the different controls and pass the configured accelerators to these listeners is the choice to go. With accelerators and menu items you have the code at one central point. What you are suggesting is very bad code style by adding listeners to every control of my window. I'm surprised that Eclipse uses such bad style.
Comment 24 Felipe Heidrich CLA 2012-02-17 15:21:05 EST
(In reply to comment #23)
> I'm surprised that Eclipse uses such bad style.

In the Eclipse case they needed a handler for the delete key in the package explorer view, so it makes perfect sense to add it to the control. IMO, trying to use del as an accelerator is wrong.
Comment 25 Thomas Singer CLA 2012-02-17 15:44:21 EST
(In reply to comment #24)
> IMO, trying to use del as an accelerator is wrong.

Could you please explain why?

BTW, in our application (SmartGit) the user is able to change the accelerators. And a lot tend to use the Del because it is the most natural choice for them.
Comment 26 Felipe Heidrich CLA 2012-02-21 10:42:03 EST
(In reply to comment #25)
> (In reply to comment #24)
> > IMO, trying to use del as an accelerator is wrong.
> 
> Could you please explain why?
> 

Accelerators should have a modifier mask (to avoid collisions).
Del collides with control key bindings.
Comment 27 Thomas Singer CLA 2012-02-21 14:40:05 EST
(In reply to comment #26)
> (In reply to comment #25)
> > (In reply to comment #24)
> > > IMO, trying to use del as an accelerator is wrong.
> > 
> > Could you please explain why?
> > 
> 
> Accelerators should have a modifier mask (to avoid collisions).
> Del collides with control key bindings.

Well, there are multiple solutions to this conflict. One you suggested (avoid conflicts). Another I'm requesting (and is built into Swing) - first let the control try to handle it, then delegate it up the hierarchy to the shell, then try accelerators.
Comment 28 Felipe Heidrich CLA 2012-02-21 15:53:17 EST
(In reply to comment #27)

> Well, there are multiple solutions to this conflict. One you suggested (avoid
> conflicts). Another I'm requesting (and is built into Swing) - first let the
> control try to handle it, then delegate it up the hierarchy to the shell, then
> try accelerators.

It was a design choice we made in SWT many years ago, we can't just change it now. sorry.
Comment 29 Thomas Singer CLA 2012-02-22 01:04:22 EST
(In reply to comment #28)
> (In reply to comment #27)
> 
> > Well, there are multiple solutions to this conflict. One you suggested (avoid
> > conflicts). Another I'm requesting (and is built into Swing) - first let the
> > control try to handle it, then delegate it up the hierarchy to the shell, then
> > try accelerators.
> 
> It was a design choice we made in SWT many years ago, we can't just change it
> now. sorry.

Maybe there is a possibility for you to make it more flexible so I can hook my own implementation into SWT?
Comment 30 Ram Rachum CLA 2012-03-05 05:17:40 EST
I am also affected by this issue.
Comment 31 Eclipse Genie CLA 2018-10-30 00:04:25 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.

--
The automated Eclipse Genie.
Comment 32 Thomas Singer CLA 2018-10-30 02:50:42 EDT
We are not using SWT's accelerators any more because of this bug and instead use an own implementation using a SWT.KeyDown display filter.
Comment 33 Lars Vogel CLA 2019-09-02 15:03:02 EDT
This bug was marked as stalebug a while ago. Marking as worksforme.

If this report is still relevant for the current release, please reopen and remove the stalebug whiteboard tag.
Comment 34 Lars Vogel CLA 2019-09-02 15:09:51 EDT
This bug has been marked as stalebug a while ago without any further interaction.

If this report is still relevant for the current release, please reopen and remove the stalebug whiteboard flag.