| Summary: | Del accelerator wins over input field | ||
|---|---|---|---|
| Product: | [Eclipse Project] Platform | Reporter: | Thomas Singer <eclipse> |
| Component: | SWT | Assignee: | 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 | ||
Same applies to other keys like Enter or Space. Is there a work-around this serious problem? 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. 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. (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? (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. (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. 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);
}
});
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. 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? (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. 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? (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. (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. > > > 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 > 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.
> > > 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.
(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? (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 ? (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. 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*? (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). 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. (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. (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. (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. (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. (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. (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? I am also affected by this issue. 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. 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. 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. 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. |
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