Opened 10 years ago

Last modified 6 years ago

#11320 confirmed defect

Accelerators take precedence over wxTextCtrl shortcuts

Reported by: obfuscated Owned by:
Priority: normal Milestone:
Component: GUI-all Version: stable-latest
Keywords: copy/paste/del wxTextCtrl wxFrame Cc: Carsten
Blocked By: Blocking:
Patch: no

Description

  1. I've created a simple wx application on linux (using the wx project template in codeblocks)
  2. In the frame I've added a wxBoxSizer, then in the sizer two wxTextCtrls
  3. I've added Edit->Copy and Edit->Paste menu items, their ids are wxID_COPY and wxID_PASTE
  4. I build and run the app
  5. I type and select some text in one of the wxTextCtrls
  6. Hit ctrl+c
  7. Focus the other text control
  8. Hit ctrl+v and nothing happens.

If I remove the menu items the shortcuts work.
I've done the same test on windows (xp sp3 + wx2.8.10) and there it works.

Attachments (1)

wxframe_textctrl.zip download (4.9 KB) - added by obfuscated 10 years ago.
sample project to reproduce the bug

Download all attachments as: .zip

Change History (16)

Changed 10 years ago by obfuscated

sample project to reproduce the bug

comment:1 Changed 10 years ago by vadz

  • Summary changed from copy and paste doesn't work in wxTextCtrl placed in wxFrame to Accelerators take precedence over wxTextCtrl shortcuts

I'm not sure if this is a bug, aren't accelerators supposed to take precedence? I.e. Ctrl-V now invokes your wxID_PASTE item, isn't this what you wanted?

P.S. Please read HowToSubmitPatches, in particular notice an explicit plea to not submit ZIP files with entire projects.

comment:2 Changed 10 years ago by Carsten

Just for info, I too have been surprised by this behavior in the past:
Whenever you use (menu) accelerator keys like , Ctrl+X, Shift+X, Del, etc., none of these is available in a wxTextCtrl child. That is, you actually cannot use the Del key any more if you have a Del accelerator and cannot enter capital letters if you use Shift+... accelerators a lot.

This in turn means that one must be careful to only employ accelerator keys that have no printable character equivalents (like the capital letters) and no other use in wxTextCtrl (like Ctrl+C|V|X and Del).

If we wanted make such "problematic" accelerators also work with wxTextCtrl (in user code), the related event handler had to determine if the currently active window (the one with the input focus) is a wxTextCtrl, and if so, reroute the event to it (and otherwise run the usual / default code for this event). Note that this means that possible *many* event handlers must carry this special-case event interception code.

If instead it was the other way round (that would be my personal preference), wxWidgets would do the interception work; that is, when processing an accelerator key, determine if an active wxTextCtrl should receive it or if normal processing should proceed.

The only drawback that I can see with this strategy is possible confusion of the app user when he is editing in a wxTextCtrl, then uses the mouse to choose e.g. the menu entry with the Ctrl+X accelerator, and the Cut operation in the wxTextCtrl does *not* happen (in contrast to pressing Ctrl+X key!), but instead the action defined by the menu event handler happens. (Or maybe he is not confused, depending on the label next to the acceleration key.)
This is still a better user experience though than the "Is my keyboard broken?" confusion that arises from (apparently) missing capital letters, Del key, etc.

Hope this makes sense. ;-)

comment:3 Changed 10 years ago by obfuscated

vadz: sorry, for the attachment I've read the guide but I've missed the part about attaching files.
If you can't reproduce the problem, I can try to make a patch from some of the samples.

I'm not sure if this is a bug, aren't accelerators supposed to take precedence?

I.e. Ctrl-V now invokes your wxID_PASTE item, isn't this what you wanted?

The exact problem is in the Codeblocks IDE, the menu items are added for the source editor window (wxScintilla base), so you can copy and paste some code using the menu and because every editor has them (and possibly redefine the keys).
But when you have focused another control (entry to send commands to the debugger or entry in the script console) you can't copy and paste with the keyboard.
Wouldn't it be better to allow the code below to work:

// this handler is called first, then the default handlers in the controls
void MyKeyHandler(event) 
{
    if(my_window is focused)
    {
         my_window->HandleKeyCommand();
         event.Skip(); // skip the default handlers
    }
}

And as I've mentioned the accelerators work on windows. If the wxGTK have the correct behaviour, the wxMSW one should be corrected (maybe).

Best regards,
Teodor Petrov

comment:4 Changed 10 years ago by vadz

  • Component changed from wxGTK to GUI-all
  • Priority changed from normal to low
  • Status changed from new to confirmed

I think current behaviour is consistent among all platforms. So changing it won't be easy as it would need to be done for all platforms at once too because having different behaviour in different ports would certainly be worse than what we have now.

Also, personally I'm absolutely not motivated by fixing this, IMO it's much easier and less confusing for the user to just avoid using keys which may do something in standard controls as accelerators.

comment:5 Changed 10 years ago by obfuscated

So you say that the wxMSW has a wrong behavior, because there it works (I can copy/paste in the text ctrls)? (Have you done tests to verify that it is broken in wxMSW, hence the "changed from wxGTK to GUI-all"?)

I have no Mac, so I can't test there :( .

Also what do you suggest to do when I need to/must have edit->copy/paste menu items?

comment:6 Changed 10 years ago by vadz

I think that accelerators take precedence currently on all platforms but I'm not sure.

My suggestion is:

  1. Don't do this.
  2. If you absolutely have to, find the currently focused control and call the appropriate operation if it's a wxTextCtrl from your menu handler.

comment:7 follow-up: Changed 10 years ago by obfuscated

  1. I don't like it :) it is counter intuitive
  2. Can you provide an example/pseudo code, because I don't know how to implement the things you're talking about

What is the reason about this behaviour:

  1. It is impossible to implement on some platforms
  2. No one needed it
  3. No one bothered to implement it the "right way"

?

Would you accept a patch for this? And if you would what platforms need to be covered by it?

comment:8 in reply to: ↑ 7 ; follow-up: Changed 10 years ago by vadz

Replying to obfuscated:

  1. Can you provide an example/pseudo code, because I don't know how to implement the things you're talking about

Use wxWindow::FindFocus() to find the focused control and dynamic_cast<wxTextEntryBase *> to check if it's a text control.

What is the reason about this behaviour:

  1. It is impossible to implement on some platforms
  2. No one needed it
  3. No one bothered to implement it the "right way"

?

Would you accept a patch for this? And if you would what platforms need to be covered by it?

This would depend on what exactly "this" is. It's still not really clear to me what's the desired behaviour is. I'd like to encourage you to post to wx-dev as it would be more convenient to discuss it there rather than in Trac interface.

Thanks!

comment:9 in reply to: ↑ 8 Changed 8 years ago by Carsten

  • Cc Carsten added
  • Keywords copy/paste/del added; copy/paste removed
  • Priority changed from low to normal
  • Version changed from 2.8.10 to 2.9-svn

Replying to vadz:

It's still not really clear to me what's the desired behaviour is.

Please consider Windows Explorer:

  • When you click a file, then press "Del", the file is deleted (you're asked first if you're sure etc.)
  • When you click a file, then press "F2" for rename, and press "Del" while editing the file name, not the file is deleted, but the character to the right of the text cursor. Similarly, if you enter text into the address or search bar, "Del" deletes characters, not the selected files.

Most applications work exactly like Windows Explorer:
The "Del" key deletes the selected objects, but if a text control is active, it takes precedence.

More generally, when a text control has focus, it processes key events first. Unprocessed key events (e.g. because the text control has or focus or interest) are processed as accelerators. This way, you can even have accelerators like "Shift+A" without conflicts.

As the problem described in this ticket bites me over and over again, and as current wxWidget behaviour seems contrary to 99% of all native applications, please allow me to raise priority back to "normal".

comment:10 Changed 8 years ago by vadz

I disagree with Explorer example because Del in it is not an accelerator at all, it's simply handled by the focused control in the usual way. But
I agree that in theory it can be a problem if you really need to have Del as an accelerator. I still don't know how to actually fix it it even just in wxMSW though.

One easy solution would be to add more keys to the list of exceptions in wxTextCtrl::MSWShouldPreProcessMessage(), e.g. also return false from it for VK_DELETE. This should make your example work. BTW, the original example works under wxMSW because Ctrl+C and Ctrl+V are already handled there.

The trouble is that it looks like there could be more exceptions like this so I wonder if we shouldn't revert the logic and return false by default only making the exceptions for the keys that the text control definitely does not need, e.g. VK_Fn, VK_TAB (unless using wxTE_PROCESS_TAB), VK_ENTER (unless IsMultiLine() || HasStyle(wxTE_PROCESS_ENTER)) and so on (although I can't really see many other exceptions in fact). Does anybody see a problem with it?

The second solution is more dangerous as it might break something but looks better in he long term. If anybody could test it and let me know about any problems found (or their absence), it would be great. Of course, any patches are welcome as usual. An automatic test using wxUIActionSimulator would be great to have too.

But if don't do this, at least adding VK_DELETE to the list of exceptions shouldn't break anything and can be done easily.

Finally, I have no idea what goes under wxGTK. I'd need to read its code and/or debug it to learn what logic does it use. If anybody knows it already, please let me know.

comment:12 Changed 8 years ago by rk

r69739 seems to implement Vadim's last suggestion to add VK_DELETE as an exception. Could this change be extended to also include Shift+Home and Shift+End, because these are also needed for the control.

BTW, the same change should also be done in wxComboBox::MSWShouldPreProcessMessage() in order to be consistent.

comment:13 Changed 6 years ago by eco

I know this is old but the current way is both unintuitive (I've been getting complaints from my OS X end users) and inconsistent among platforms.

On wxMSW you can copy and paste in a text control or, if a text control isn't selected, copy and paste at a higher level through the accelerator (in my cases it's objects drawn on the screen that can be selected, copied, and pasted). On wxOSX the event hits the higher level first which prevents users from copying and pasting within a text control.

As it is now, you can't copy and paste within text controls on wxOSX if you have a copy and paste accelerator (I've tried using if(FindFocus()->IsKindOf(wxCLASSINFO(wxTextCtrl))) { event.Skip(); return; } in the accelerator handler but that doesn't fix the problem.

Is there a workaround for this that doesn't require patching wxWidgets?

comment:14 Changed 6 years ago by vadz

I don't know how to fix this for wxOSX but it should be possible to do in the same way wxMSW does it, i.e. adding a virtual method that can be overridden by the control to indicate whether it wants to handle this key even if it's used as an accelerator and calling it before the accelerator processing takes place. Of course, the trouble is that I have no idea where does accelerator handling actually happen in wxOSX...

And if we have this in both wxMSW and wxOSX, we should really try to implement this in wxGTK as well where I think (now, after having spent some time with its keyboard handling code) it should be possible too. And then make this virtual method public to allow user-defined controls to override it. Perhaps this could even replace the ugly wxWANTS_CHARS.

But the first thing to do would be to check if it's possible to do what we want in wxOSX.

comment:15 Changed 6 years ago by jeffhostetler

I think the OSX issue in the last 2 comments is
discussed in #14954.

Note: See TracTickets for help on using tickets.