Bug 165089 - Ctrl+Right_Shift+Left on Rename refactoring dialog changes text direction
Summary: Ctrl+Right_Shift+Left on Rename refactoring dialog changes text direction
Status: NEW
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.2.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Steve Northover CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-11-18 20:30 EST by Willian Mitsuda CLA
Modified: 2019-09-06 15:31 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Willian Mitsuda CLA 2006-11-18 20:30:07 EST
Steps to reproduce:

- Invoke the Rename Refactoring (Alt+Shift+R) on a local variable or a type name.
- With the cursor on the "new name" text field, type Ctrl+Shift+Left Arrow (it has to be the right-side Ctrl and Shift keys, NOT the left ones).
- After that the text will be right aligned, and the text direction and navigation will be inverted, from right to left.
Comment 1 Willian Mitsuda CLA 2006-11-18 23:21:07 EST
It also happens on other JDT dialogs, like "Open Type" or "Extract Local Variable".
Comment 2 Markus Keller CLA 2006-11-19 12:44:55 EST
Wheew, scary Windows "feature"!

When you press Ctrl+Right_Shift, then Windows switches the input mode to "right to left". I can reproduce that in every text widget (ControlExample, but also in the address field of the Internet Explorer). To switch back to "left to right", you have to press Ctrl+Left_Shift.

On all the fields you mentioned, we install a KeyListener and use our custom (CamelCase-aware) word selection methods for Java names. We set KeyEvent#doit to false in this case.

Unfortunately, SWT does not seem to catch the subsequent keyUp event for Ctrl+Shift, leading to the behavior you observe.
Comment 3 Willian Mitsuda CLA 2006-11-19 13:28:57 EST
(In reply to comment #2)
> To switch back to "left to
> right", you have to press Ctrl+Left_Shift.
> 

Humm... good to see it has a workaround to this "feature", since actually cancel the operation when it happens.

Yes, it is scary because I have the habit to use Right_Ctrl+Right_Shift+Left keys to camel-case-select (it is practical because I can use only my right hand).

BTW, do you know if there is some place to disable this lovely "feature" on Windows?
Comment 4 Markus Keller CLA 2007-04-02 14:45:39 EDT
> BTW, do you know if there is some place to disable this lovely "feature" on
> Windows?
Control Panel > Regional and Language Options > Languages tab:
Disable the checkboxes in 'Supplemental language support' and restart Windows.
Comment 5 Steve Northover CLA 2007-04-02 20:34:26 EDT
Felipe, can you confirm that this is happening?
Comment 6 Felipe Heidrich CLA 2007-04-30 11:38:18 EDT
Steve, this is native windows behaviour.
The user can disable this option in the control-panel. Note, this option is off by default, the user only gets this feature when he enables support for right-to-left languages.

Consider closing this problem report as wontfix.
Comment 7 Markus Keller CLA 2007-04-30 12:05:34 EDT
Just to clarify: I don't think you should block Ctrl+Right_Shift from switching direction.

It's just problematic that setting event.doit=false for the keyDown event for Ctrl+Right_Shift+Arrow_Left still lets the keyUp event Ctrl+Right_Shift go out to Windows to execute its evil intentions.
Comment 8 Felipe Heidrich CLA 2007-04-30 12:25:47 EDT
I think the event you are stopping is mask=ctrl+shift and keycode=arrowleft.
You need to stop mask=ctrl and keycode=shift.

There is nothing to do with key up in my opnion.

Try this:
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
public class PR165089 {
public static void main(String[] args) {
	Display display = new Display();
	Shell shell = new Shell(display);
	Text text = new Text (shell, SWT.SINGLE);
	text.setBounds(10, 10, 100, 30);
	Listener listener = new Listener () {
		public void handleEvent (Event e) {
			if ((e.stateMask & SWT.CTRL) != 0) {
				if (e.keyCode == SWT.SHIFT) e.doit = false;
			}
		}
	};
	text.addListener (SWT.KeyDown, listener);
	shell.open();
	while (!shell.isDisposed()) {
		if (!display.readAndDispatch())
			display.sleep();
	}
	display.dispose();
}
}
Comment 9 Markus Keller CLA 2007-05-09 14:19:45 EDT
(In reply to comment #8)
That example just cancels all keystrokes starting with Ctrl+Shift, but it
a) does not solve the problem, and
b) is Windows-specific and should therefore not have to be in client code.

Here's a snippet that reproduces the original problem in pure SWT:

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class Bug165089 {
    public static void main(String[] args) {
        Display display= new Display();
        Shell shell= new Shell(display);

        final Text text= new Text(shell, SWT.SINGLE);
        text.setText("press ()Ctrl+A or ()Ctrl+Right_Shift+ArrowRight");
        text.setBounds(10, 10, 300, 20);
        
        final Text text2= new Text(shell, SWT.SINGLE);
        text2.setText("no listener");
        text2.setBounds(10, 50, 300, 20);

        Listener listener= new Listener() {
            public void handleEvent(Event e) {
                if (e.stateMask == SWT.CTRL && e.keyCode == 'a') {
                    e.doit= false;
                    text.setSelection(7);

                } else if (e.stateMask == (SWT.CTRL | SWT.SHIFT)
                        && e.keyCode == SWT.ARROW_RIGHT) {
                    e.doit= false;
                    text.setSelection(19);
                    
                } else if (e.stateMask == (SWT.CTRL | SWT.SHIFT)
                        && e.keyCode == SWT.ARROW_LEFT) {
                    text2.setText("Ctrl+Shift+ArrowLeft pressed @"
                            + System.currentTimeMillis());
                }
            }
        };
        text.addListener(SWT.KeyDown, listener);
        
        shell.setSize(400, 200);
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }
        display.dispose();
    }
}


If you press Ctrl+A, the caret is moved into the first ().

If you press Ctrl+Shift+Arrow_Right, the caret is moved into the second ()
=> Unexpected: If you used the right Shift key, the text direction is also changed.

If you press Ctrl+Shift+Arrow_Left, the OS default action is executed (selection extended to include the previous word) and a message is written to the second text field
=> Works as it should: No matter what Shift key you pressed, the text direction stays unchanged.

Client code should not have to care about Windows' special handling of Ctrl+Shift. After a key event with Ctrl+Shift+something has arrived, Windows' Ctrl+Shift handling should always be canceled, regardless of the Event#doit flag.

In our real code, the keybindings can even be changed by the user, and it would be wrong to add a hack on our side to prevent this bug.
Comment 10 Felipe Heidrich CLA 2007-05-09 14:37:50 EDT
This is not bug, the user has configured the OS to changed the direction of text widget when the ctrl+right_shift is pressed. SWT gets this feature for free for being native.

I don't think you should put any hack in your code, neither should us put one in SWT (this would very much upset the developers in Egypt and Israel).

IMO you should explaing to your client how to use Windows Control Panel to disable this feature or how to assign its shortcut to something else.
Comment 11 Steve Northover CLA 2007-05-09 14:47:05 EDT
Felipe, is this a WONTFIX for SWT?
Comment 12 Markus Keller CLA 2007-05-09 14:53:33 EDT
No, the problem is NOT that Ctrl+Shift changes the direction!

The problem is that the text direction changes if Ctrl+Shift+something is handled with "e.doit = false". In that scenario, the user did NOT press Ctrl+Shift, so he should NOT get a direction change.

Of course, nobody should ever block Ctrl+Shift. It should just not occur as a side effect.
Comment 13 Felipe Heidrich CLA 2007-05-09 15:05:12 EDT
Markus, I'm confused, you said:
"The problem is that the text direction changes if Ctrl+Shift+something is
handled with "e.doit = false". In that scenario, the user did NOT press
Ctrl+Shift, so he should NOT get a direction change."

Means that the user actions were:
press CTRL and hold
press SHIFT and hold (there, the direction changes here in this WM_KEYDOWN)
press "something" (at this point the direction changed already does not matter what we do to the event)

So, the user DID press CTRL+SHIFT in order to compose CTRL+SHIFT+something.

am I missing something obvious here ?
Comment 14 Markus Keller CLA 2007-05-09 15:19:34 EDT
We're getting to the point ;-)

> Means that the user actions were:
> press CTRL and hold
> press SHIFT and hold (there, the direction changes here in this WM_KEYDOWN)
No, please try it. You can press and hold CTRL+RIGHT_SHIFT and the direction does not change.

> press "something" (at this point the direction changed already does not matter
> what we do to the event)
"something" is e.g. ARROW_RIGHT => this will select the next word.

The key is that Windows only interprets CTRL+SHIFT as direction change if no key was pressed afterwards. As soon as any third key has been pressed, Windows never changes the direction.

My code says "e.doit = false", which tells SWT (and Windows) that I don't want the default behavior for that keystroke. Nevertheless, the third key really has been pressed, so the direction change should be canceled.
Comment 15 Felipe Heidrich CLA 2007-05-09 15:40:03 EDT
> The key is that Windows only interprets CTRL+SHIFT as direction change if no
> key was pressed afterwards. As soon as any third key has been pressed, Windows
> never changes the direction.

Correct. I get it now.

> My code says "e.doit = false", which tells SWT (and Windows) that I don't want
> the default behavior for that keystroke. Nevertheless, the third key really has
> been pressed, so the direction change should be canceled.

Well, at this point you have to agree with me that you are doing this to yourself.
You know windows has to process the third key so it doesn't change direction on you. But at the same time you want windows not to process the key.

As far as I know, we (SWT) can propagate the key to windows (call windowProc) or not (according to event.doit). I don't think we can fix this problem. Sorry.
Comment 16 Markus Keller CLA 2007-06-13 10:03:45 EDT
> As far as I know, we (SWT) can propagate the key to windows (call windowProc)
> or not (according to event.doit). I don't think we can fix this problem. Sorry.

Couldn't you send a no-op event to Windows in the case that e.stateMask is (SWT.CTRL | SWT.SHIFT) for KeyDown events)?

I tried adding this code:
                    Event post= new Event();
                    post.type= SWT.KeyDown;
                    post.keyCode= SWT.CR;
                    e.display.post(post);

... to the end of my KeyDown listener in the ...
                } else if (e.stateMask == (SWT.CTRL | SWT.SHIFT)
                        && e.keyCode == SWT.ARROW_RIGHT) {
                    e.doit= false;

... branch of the snippet from comment 9. This successfully blocked the switching to RTL (although I don't understand why the SWT.CR doesn't show up anywhere).
Comment 17 Steve Northover CLA 2007-06-13 10:08:26 EDT
Felipe, please give me a demo and make me understand why this is an SWT bug.
Comment 18 Markus Keller CLA 2007-06-13 10:37:37 EDT
> Felipe, please give me a demo and make me understand why this is an SWT bug.
I think it's a Windows bug, but SWT would be the best place for a workaround.
Comment 19 Eclipse Webmaster CLA 2019-09-06 15:31:56 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.