diff options
author | msw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-02 19:51:38 +0000 |
---|---|---|
committer | msw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-02 19:51:38 +0000 |
commit | 70a1b5b157980ab6866c68edff388c62e4a4205a (patch) | |
tree | cc01eb004d2921228c455fc5059b47d427f16fa6 /ui/views | |
parent | 0b53e86bfa1de49c735e344a64a011cff1b4e1a6 (diff) | |
download | chromium_src-70a1b5b157980ab6866c68edff388c62e4a4205a.zip chromium_src-70a1b5b157980ab6866c68edff388c62e4a4205a.tar.gz chromium_src-70a1b5b157980ab6866c68edff388c62e4a4205a.tar.bz2 |
Support GTK key bindings in the Views Textfield.
Convert events to commands via TextEditKeyBindingsDelegateX11.
Translate the UI commands to corresponding IDS_* commands.
SkipDefaultKeyEventProcessing when a text command would run.
(ex/ CTRL+W deletes word backwards, instead of closing a tab)
Add IDS_MOVE_[DOWN|UP] with omnibox result up/down handling.
TODO: Consolidate ui::TextEditCommandX11 and IDS_* commands.
BUG=319437
TEST=Enable Emacs keybinging theme via gnome-tweak-tool; key bindings work as expected on Linux Aura omnibox, find bar, etc.
R=oshima@chromium.org
Review URL: https://codereview.chromium.org/213673009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@261169 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/views')
-rw-r--r-- | ui/views/controls/textfield/textfield.cc | 130 | ||||
-rw-r--r-- | ui/views/controls/textfield/textfield.h | 3 |
2 files changed, 129 insertions, 4 deletions
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc index 65554ac..ba72a31 100644 --- a/ui/views/controls/textfield/textfield.cc +++ b/ui/views/controls/textfield/textfield.cc @@ -40,6 +40,12 @@ #include "base/win/win_util.h" #endif +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) +#include "base/strings/utf_string_conversions.h" +#include "ui/events/x/text_edit_command_x11.h" +#include "ui/events/x/text_edit_key_bindings_delegate_x11.h" +#endif + namespace views { namespace { @@ -129,6 +135,92 @@ int GetCommandForKeyEvent(const ui::KeyEvent& event, bool has_selection) { return kNoCommand; } +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) +int GetViewsCommand(const ui::TextEditCommandX11& command, bool rtl) { + const bool select = command.extend_selection(); + switch (command.command_id()) { + case ui::TextEditCommandX11::COPY: + return IDS_APP_COPY; + case ui::TextEditCommandX11::CUT: + return IDS_APP_CUT; + case ui::TextEditCommandX11::DELETE_BACKWARD: + return IDS_DELETE_BACKWARD; + case ui::TextEditCommandX11::DELETE_FORWARD: + return IDS_DELETE_FORWARD; + case ui::TextEditCommandX11::DELETE_TO_BEGINING_OF_LINE: + case ui::TextEditCommandX11::DELETE_TO_BEGINING_OF_PARAGRAPH: + return IDS_DELETE_TO_BEGINNING_OF_LINE; + case ui::TextEditCommandX11::DELETE_TO_END_OF_LINE: + case ui::TextEditCommandX11::DELETE_TO_END_OF_PARAGRAPH: + return IDS_DELETE_TO_END_OF_LINE; + case ui::TextEditCommandX11::DELETE_WORD_BACKWARD: + return IDS_DELETE_WORD_BACKWARD; + case ui::TextEditCommandX11::DELETE_WORD_FORWARD: + return IDS_DELETE_WORD_FORWARD; + case ui::TextEditCommandX11::INSERT_TEXT: + return kNoCommand; + case ui::TextEditCommandX11::MOVE_BACKWARD: + if (rtl) + return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT; + return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT; + case ui::TextEditCommandX11::MOVE_DOWN: + return IDS_MOVE_DOWN; + case ui::TextEditCommandX11::MOVE_FORWARD: + if (rtl) + return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT; + return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT; + case ui::TextEditCommandX11::MOVE_LEFT: + return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT; + case ui::TextEditCommandX11::MOVE_PAGE_DOWN: + case ui::TextEditCommandX11::MOVE_PAGE_UP: + return kNoCommand; + case ui::TextEditCommandX11::MOVE_RIGHT: + return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT; + case ui::TextEditCommandX11::MOVE_TO_BEGINING_OF_DOCUMENT: + case ui::TextEditCommandX11::MOVE_TO_BEGINING_OF_LINE: + case ui::TextEditCommandX11::MOVE_TO_BEGINING_OF_PARAGRAPH: + return select ? IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION : + IDS_MOVE_TO_BEGINNING_OF_LINE; + case ui::TextEditCommandX11::MOVE_TO_END_OF_DOCUMENT: + case ui::TextEditCommandX11::MOVE_TO_END_OF_LINE: + case ui::TextEditCommandX11::MOVE_TO_END_OF_PARAGRAPH: + return select ? IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION : + IDS_MOVE_TO_END_OF_LINE; + case ui::TextEditCommandX11::MOVE_UP: + return IDS_MOVE_UP; + case ui::TextEditCommandX11::MOVE_WORD_BACKWARD: + if (rtl) { + return select ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION : + IDS_MOVE_WORD_RIGHT; + } + return select ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION : + IDS_MOVE_WORD_LEFT; + case ui::TextEditCommandX11::MOVE_WORD_FORWARD: + if (rtl) { + return select ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION : + IDS_MOVE_WORD_LEFT; + } + return select ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION : + IDS_MOVE_WORD_RIGHT; + case ui::TextEditCommandX11::MOVE_WORD_LEFT: + return select ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION : + IDS_MOVE_WORD_LEFT; + case ui::TextEditCommandX11::MOVE_WORD_RIGHT: + return select ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION : + IDS_MOVE_WORD_RIGHT; + case ui::TextEditCommandX11::PASTE: + return IDS_APP_PASTE; + case ui::TextEditCommandX11::SELECT_ALL: + return IDS_APP_SELECT_ALL; + case ui::TextEditCommandX11::SET_MARK: + case ui::TextEditCommandX11::UNSELECT: + case ui::TextEditCommandX11::INVALID_COMMAND: + return kNoCommand; + } + return kNoCommand; +} +#endif + } // namespace // static @@ -493,11 +585,30 @@ void Textfield::OnMouseReleased(const ui::MouseEvent& event) { } bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { - const bool handled = controller_ && controller_->HandleKeyEvent(this, event); + bool handled = controller_ && controller_->HandleKeyEvent(this, event); touch_selection_controller_.reset(); if (handled) return true; +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + ui::TextEditKeyBindingsDelegateX11* delegate = + ui::GetTextEditKeyBindingsDelegate(); + std::vector<ui::TextEditCommandX11> commands; + if (delegate) { + if (!delegate->MatchEvent(event, &commands)) + return false; + const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT; + for (size_t i = 0; i < commands.size(); ++i) { + int command = GetViewsCommand(commands[i], rtl); + if (IsCommandIdEnabled(command)) { + ExecuteCommand(command); + handled = true; + } + } + return handled; + } +#endif + const int command = GetCommandForKeyEvent(event, HasSelection()); if (IsCommandIdEnabled(command)) { ExecuteCommand(command); @@ -595,10 +706,23 @@ void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) { SelectAll(false); } -bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) { +bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) { +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + // Skip any accelerator handling that conflicts with custom keybindings. + ui::TextEditKeyBindingsDelegateX11* delegate = + ui::GetTextEditKeyBindingsDelegate(); + std::vector<ui::TextEditCommandX11> commands; + if (delegate && delegate->MatchEvent(event, &commands)) { + const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT; + for (size_t i = 0; i < commands.size(); ++i) + if (IsCommandIdEnabled(GetViewsCommand(commands[i], rtl))) + return true; + } +#endif + // Skip any accelerator handling of backspace; textfields handle this key. // Also skip processing Windows [Alt]+<num-pad digit> Unicode alt-codes. - return e.key_code() == ui::VKEY_BACK || e.IsUnicodeKeyCode(); + return event.key_code() == ui::VKEY_BACK || event.IsUnicodeKeyCode(); } bool Textfield::GetDropFormats( diff --git a/ui/views/controls/textfield/textfield.h b/ui/views/controls/textfield/textfield.h index 10e4894..2e02029 100644 --- a/ui/views/controls/textfield/textfield.h +++ b/ui/views/controls/textfield/textfield.h @@ -189,7 +189,8 @@ class VIEWS_EXPORT Textfield : public View, virtual ui::TextInputClient* GetTextInputClient() OVERRIDE; virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; virtual void AboutToRequestFocusFromTabTraversal(bool reverse) OVERRIDE; - virtual bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) OVERRIDE; + virtual bool SkipDefaultKeyEventProcessing( + const ui::KeyEvent& event) OVERRIDE; virtual bool GetDropFormats( int* formats, std::set<ui::OSExchangeData::CustomFormat>* custom_formats) OVERRIDE; |