Changeset 86436 in webkit


Ignore:
Timestamp:
May 13, 2011 9:00:35 AM (13 years ago)
Author:
Martin Robinson
Message:

2011-05-13 Martin Robinson <mrobinson@igalia.com>

Reviewed by Eric Seidel.

[GTK] Share the GTK+ key binding code between WebKit1 and WebKit2
https://bugs.webkit.org/show_bug.cgi?id=59765

Move the keybinding code form WebKit1/WebKit2 to this utility class. This code is
almost directly moved from the WebKit layer.

No new tests. This is covered by the editing tests.

  • GNUmakefile.list.am:
  • platform/gtk/KeyBindingTranslator.cpp: Added. (WebCore::backspaceCallback):Added. (WebCore::selectAllCallback):Added. (WebCore::cutClipboardCallback):Added. (WebCore::copyClipboardCallback):Added. (WebCore::pasteClipboardCallback):Added. (WebCore::toggleOverwriteCallback):Added. (WebCore::popupMenuCallback):Added. (WebCore::showHelpCallback):Added. (WebCore::deleteFromCursorCallback):Added. (WebCore::moveCursorCallback):Added. (WebCore::KeyBindingTranslator::KeyBindingTranslator):Added. (WebCore::KeyBindingTranslator::getEditorCommandsForKeyEvent):Added.
  • platform/gtk/KeyBindingTranslator.h: Added. (WebCore::KeyBindingTranslator::addPendingEditorCommand):Added.

2011-05-13 Martin Robinson <mrobinson@igalia.com>

Reviewed by Eric Seidel.

[GTK] Share the GTK+ key binding code between WebKit1 and WebKit2
https://bugs.webkit.org/show_bug.cgi?id=59765

Use the new KeyBindingTranslator class from WebCore/platform/gtk. With this utility
class we can now share the code with WebKit2.

  • WebCoreSupport/EditorClientGtk.cpp: (WebKit::EditorClient::executePendingEditorCommands): Updated to reflect the fact that the command vector now contains WTF::string. (WebKit::EditorClient::handleKeyboardEvent): Use the new helper utility class. (WebKit::EditorClient::EditorClient):
  • WebCoreSupport/EditorClientGtk.h: Remove unnecessary member. Add the utility class.

2011-05-13 Martin Robinson <mrobinson@igalia.com>

Reviewed by Eric Seidel.

[GTK] Share the GTK+ key binding code between WebKit1 and WebKit2
https://bugs.webkit.org/show_bug.cgi?id=59765

Use the new KeyBindingTranslator class from WebCore/platform/gtk. With this utility
class we can now share the code with WebKit2.

  • UIProcess/API/gtk/PageClientImpl.cpp: (WebKit::PageClientImpl::PageClientImpl): No longer need to initialize keybinding code. (WebKit::PageClientImpl::getEditorCommandsForKeyEvent): Use the new utility class.
  • UIProcess/API/gtk/PageClientImpl.h: Remove unnecessary members. Add utility class member.
Location:
trunk/Source
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r86433 r86436  
     12011-05-13  Martin Robinson  <mrobinson@igalia.com>
     2
     3        Reviewed by Eric Seidel.
     4
     5        [GTK] Share the GTK+ key binding code between WebKit1 and WebKit2
     6        https://bugs.webkit.org/show_bug.cgi?id=59765
     7
     8        Move the keybinding code form WebKit1/WebKit2 to this utility class. This code is
     9        almost directly moved from the WebKit layer.
     10
     11        No new tests. This is covered by the editing tests.
     12
     13        * GNUmakefile.list.am:
     14        * platform/gtk/KeyBindingTranslator.cpp: Added.
     15        (WebCore::backspaceCallback):Added.
     16        (WebCore::selectAllCallback):Added.
     17        (WebCore::cutClipboardCallback):Added.
     18        (WebCore::copyClipboardCallback):Added.
     19        (WebCore::pasteClipboardCallback):Added.
     20        (WebCore::toggleOverwriteCallback):Added.
     21        (WebCore::popupMenuCallback):Added.
     22        (WebCore::showHelpCallback):Added.
     23        (WebCore::deleteFromCursorCallback):Added.
     24        (WebCore::moveCursorCallback):Added.
     25        (WebCore::KeyBindingTranslator::KeyBindingTranslator):Added.
     26        (WebCore::KeyBindingTranslator::getEditorCommandsForKeyEvent):Added.
     27        * platform/gtk/KeyBindingTranslator.h: Added.
     28        (WebCore::KeyBindingTranslator::addPendingEditorCommand):Added.
     29
    1302011-05-01  Holger Hans Peter Freyther  <holger@moiji-mobile.com>
    231
  • trunk/Source/WebCore/GNUmakefile.list.am

    r86315 r86436  
    37513751        Source/WebCore/platform/gtk/GtkVersioning.c \
    37523752        Source/WebCore/platform/gtk/GtkVersioning.h \
     3753        Source/WebCore/platform/gtk/KeyBindingTranslator.cpp \
     3754        Source/WebCore/platform/gtk/KeyBindingTranslator.h \
    37533755        Source/WebCore/platform/gtk/KURLGtk.cpp \
    37543756        Source/WebCore/platform/gtk/LanguageGtk.cpp \
  • trunk/Source/WebKit/gtk/ChangeLog

    r86361 r86436  
     12011-05-13  Martin Robinson  <mrobinson@igalia.com>
     2
     3        Reviewed by Eric Seidel.
     4
     5        [GTK] Share the GTK+ key binding code between WebKit1 and WebKit2
     6        https://bugs.webkit.org/show_bug.cgi?id=59765
     7
     8        Use the new KeyBindingTranslator class from WebCore/platform/gtk. With this utility
     9        class we can now share the code with WebKit2.
     10
     11        * WebCoreSupport/EditorClientGtk.cpp:
     12        (WebKit::EditorClient::executePendingEditorCommands): Updated to reflect the fact that
     13        the command vector now contains WTF::string.
     14        (WebKit::EditorClient::handleKeyboardEvent): Use the new helper utility class.
     15        (WebKit::EditorClient::EditorClient):
     16        * WebCoreSupport/EditorClientGtk.h: Remove unnecessary member. Add the utility class.
     17
    1182011-05-12  Martin Robinson  <mrobinson@igalia.com>
    219
  • trunk/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp

    r85832 r86436  
    100100}
    101101
    102 static void backspaceCallback(GtkWidget* widget, EditorClient* client)
    103 {
    104     g_signal_stop_emission_by_name(widget, "backspace");
    105     client->addPendingEditorCommand("DeleteBackward");
    106 }
    107 
    108 static void selectAllCallback(GtkWidget* widget, gboolean select, EditorClient* client)
    109 {
    110     g_signal_stop_emission_by_name(widget, "select-all");
    111     client->addPendingEditorCommand(select ? "SelectAll" : "Unselect");
    112 }
    113 
    114 static void cutClipboardCallback(GtkWidget* widget, EditorClient* client)
    115 {
    116     g_signal_stop_emission_by_name(widget, "cut-clipboard");
    117     client->addPendingEditorCommand("Cut");
    118 }
    119 
    120 static void copyClipboardCallback(GtkWidget* widget, EditorClient* client)
    121 {
    122     g_signal_stop_emission_by_name(widget, "copy-clipboard");
    123     client->addPendingEditorCommand("Copy");
    124 }
    125 
    126 static void pasteClipboardCallback(GtkWidget* widget, EditorClient* client)
    127 {
    128     g_signal_stop_emission_by_name(widget, "paste-clipboard");
    129     client->addPendingEditorCommand("Paste");
    130 }
    131 
    132 static void toggleOverwriteCallback(GtkWidget* widget, EditorClient*)
    133 {
    134     // We don't support toggling the overwrite mode, but the default callback expects
    135     // the GtkTextView to have a layout, so we handle this signal just to stop it.
    136     g_signal_stop_emission_by_name(widget, "toggle-overwrite");
    137 }
    138 
    139 // GTK+ will still send these signals to the web view. So we can safely stop signal
    140 // emission without breaking accessibility.
    141 static void popupMenuCallback(GtkWidget* widget, EditorClient*)
    142 {
    143     g_signal_stop_emission_by_name(widget, "popup-menu");
    144 }
    145 
    146 static void showHelpCallback(GtkWidget* widget, EditorClient*)
    147 {
    148     g_signal_stop_emission_by_name(widget, "show-help");
    149 }
    150 
    151 static const char* const gtkDeleteCommands[][2] = {
    152     { "DeleteBackward",               "DeleteForward"                        }, // Characters
    153     { "DeleteWordBackward",           "DeleteWordForward"                    }, // Word ends
    154     { "DeleteWordBackward",           "DeleteWordForward"                    }, // Words
    155     { "DeleteToBeginningOfLine",      "DeleteToEndOfLine"                    }, // Lines
    156     { "DeleteToBeginningOfLine",      "DeleteToEndOfLine"                    }, // Line ends
    157     { "DeleteToBeginningOfParagraph", "DeleteToEndOfParagraph"               }, // Paragraph ends
    158     { "DeleteToBeginningOfParagraph", "DeleteToEndOfParagraph"               }, // Paragraphs
    159     { 0,                              0                                      } // Whitespace (M-\ in Emacs)
    160 };
    161 
    162 static void deleteFromCursorCallback(GtkWidget* widget, GtkDeleteType deleteType, gint count, EditorClient* client)
    163 {
    164     g_signal_stop_emission_by_name(widget, "delete-from-cursor");
    165     int direction = count > 0 ? 1 : 0;
    166 
    167     // Ensuring that deleteType <= G_N_ELEMENTS here results in a compiler warning
    168     // that the condition is always true.
    169 
    170     if (deleteType == GTK_DELETE_WORDS) {
    171         if (!direction) {
    172             client->addPendingEditorCommand("MoveWordForward");
    173             client->addPendingEditorCommand("MoveWordBackward");
    174         } else {
    175             client->addPendingEditorCommand("MoveWordBackward");
    176             client->addPendingEditorCommand("MoveWordForward");
    177         }
    178     } else if (deleteType == GTK_DELETE_DISPLAY_LINES) {
    179         if (!direction)
    180             client->addPendingEditorCommand("MoveToBeginningOfLine");
    181         else
    182             client->addPendingEditorCommand("MoveToEndOfLine");
    183     } else if (deleteType == GTK_DELETE_PARAGRAPHS) {
    184         if (!direction)
    185             client->addPendingEditorCommand("MoveToBeginningOfParagraph");
    186         else
    187             client->addPendingEditorCommand("MoveToEndOfParagraph");
    188     }
    189 
    190     const char* rawCommand = gtkDeleteCommands[deleteType][direction];
    191     if (!rawCommand)
    192       return;
    193 
    194     for (int i = 0; i < abs(count); i++)
    195         client->addPendingEditorCommand(rawCommand);
    196 }
    197 
    198 static const char* const gtkMoveCommands[][4] = {
    199     { "MoveBackward",                                   "MoveForward",
    200       "MoveBackwardAndModifySelection",                 "MoveForwardAndModifySelection"             }, // Forward/backward grapheme
    201     { "MoveLeft",                                       "MoveRight",
    202       "MoveBackwardAndModifySelection",                 "MoveForwardAndModifySelection"             }, // Left/right grapheme
    203     { "MoveWordBackward",                               "MoveWordForward",
    204       "MoveWordBackwardAndModifySelection",             "MoveWordForwardAndModifySelection"         }, // Forward/backward word
    205     { "MoveUp",                                         "MoveDown",
    206       "MoveUpAndModifySelection",                       "MoveDownAndModifySelection"                }, // Up/down line
    207     { "MoveToBeginningOfLine",                          "MoveToEndOfLine",
    208       "MoveToBeginningOfLineAndModifySelection",        "MoveToEndOfLineAndModifySelection"         }, // Up/down line ends
    209     { "MoveParagraphForward",                           "MoveParagraphBackward",
    210       "MoveParagraphForwardAndModifySelection",         "MoveParagraphBackwardAndModifySelection"   }, // Up/down paragraphs
    211     { "MoveToBeginningOfParagraph",                     "MoveToEndOfParagraph",
    212       "MoveToBeginningOfParagraphAndModifySelection",   "MoveToEndOfParagraphAndModifySelection"    }, // Up/down paragraph ends.
    213     { "MovePageUp",                                     "MovePageDown",
    214       "MovePageUpAndModifySelection",                   "MovePageDownAndModifySelection"            }, // Up/down page
    215     { "MoveToBeginningOfDocument",                      "MoveToEndOfDocument",
    216       "MoveToBeginningOfDocumentAndModifySelection",    "MoveToEndOfDocumentAndModifySelection"     }, // Begin/end of buffer
    217     { 0,                                                0,
    218       0,                                                0                                           } // Horizontal page movement
    219 };
    220 
    221 static void moveCursorCallback(GtkWidget* widget, GtkMovementStep step, gint count, gboolean extendSelection, EditorClient* client)
    222 {
    223     g_signal_stop_emission_by_name(widget, "move-cursor");
    224     int direction = count > 0 ? 1 : 0;
    225     if (extendSelection)
    226         direction += 2;
    227 
    228     if (static_cast<unsigned>(step) >= G_N_ELEMENTS(gtkMoveCommands))
    229         return;
    230 
    231     const char* rawCommand = gtkMoveCommands[step][direction];
    232     if (!rawCommand)
    233         return;
    234 
    235     for (int i = 0; i < abs(count); i++)
    236         client->addPendingEditorCommand(rawCommand);
    237 }
    238102
    239103void EditorClient::updatePendingComposition(const gchar* newComposition)
     
    587451}
    588452
    589 static const unsigned CtrlKey = 1 << 0;
    590 static const unsigned AltKey = 1 << 1;
    591 static const unsigned ShiftKey = 1 << 2;
    592 
    593 struct KeyDownEntry {
    594     unsigned virtualKey;
    595     unsigned modifiers;
    596     const char* name;
    597 };
    598 
    599 struct KeyPressEntry {
    600     unsigned charCode;
    601     unsigned modifiers;
    602     const char* name;
    603 };
    604 
    605 static const KeyDownEntry keyDownEntries[] = {
    606     { 'B',       CtrlKey,            "ToggleBold"                                  },
    607     { 'I',       CtrlKey,            "ToggleItalic"                                },
    608     { VK_ESCAPE, 0,                  "Cancel"                                      },
    609     { VK_OEM_PERIOD, CtrlKey,        "Cancel"                                      },
    610     { VK_TAB,    0,                  "InsertTab"                                   },
    611     { VK_TAB,    ShiftKey,           "InsertBacktab"                               },
    612     { VK_RETURN, 0,                  "InsertNewline"                               },
    613     { VK_RETURN, CtrlKey,            "InsertNewline"                               },
    614     { VK_RETURN, AltKey,             "InsertNewline"                               },
    615     { VK_RETURN, AltKey | ShiftKey,  "InsertNewline"                               },
    616 };
    617 
    618 static const KeyPressEntry keyPressEntries[] = {
    619     { '\t',   0,                  "InsertTab"                                   },
    620     { '\t',   ShiftKey,           "InsertBacktab"                               },
    621     { '\r',   0,                  "InsertNewline"                               },
    622     { '\r',   CtrlKey,            "InsertNewline"                               },
    623     { '\r',   AltKey,             "InsertNewline"                               },
    624     { '\r',   AltKey | ShiftKey,  "InsertNewline"                               },
    625 };
    626 
    627 void EditorClient::generateEditorCommands(const KeyboardEvent* event)
    628 {
    629     ASSERT(event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent);
    630 
    631     m_pendingEditorCommands.clear();
    632 
    633     // First try to interpret the command as a native GTK+ key binding.
    634 #ifdef GTK_API_VERSION_2
    635     gtk_bindings_activate_event(GTK_OBJECT(m_nativeWidget.get()), event->keyEvent()->gdkEventKey());
    636 #else
    637     gtk_bindings_activate_event(G_OBJECT(m_nativeWidget.get()), event->keyEvent()->gdkEventKey());
    638 #endif
    639     if (m_pendingEditorCommands.size() > 0)
    640         return;
    641 
    642     static HashMap<int, const char*> keyDownCommandsMap;
    643     static HashMap<int, const char*> keyPressCommandsMap;
    644 
    645     if (keyDownCommandsMap.isEmpty()) {
    646         for (unsigned i = 0; i < G_N_ELEMENTS(keyDownEntries); i++)
    647             keyDownCommandsMap.set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
    648 
    649         for (unsigned i = 0; i < G_N_ELEMENTS(keyPressEntries); i++)
    650             keyPressCommandsMap.set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name);
    651     }
    652 
    653     unsigned modifiers = 0;
    654     if (event->shiftKey())
    655         modifiers |= ShiftKey;
    656     if (event->altKey())
    657         modifiers |= AltKey;
    658     if (event->ctrlKey())
    659         modifiers |= CtrlKey;
    660 
    661     // For keypress events, we want charCode(), but keyCode() does that.
    662     int mapKey = modifiers << 16 | event->keyCode();
    663     if (!mapKey)
    664         return;
    665     HashMap<int, const char*>* commandMap = event->type() == eventNames().keydownEvent ?
    666         &keyDownCommandsMap : &keyPressCommandsMap;
    667     if (const char* commandString = commandMap->get(mapKey))
    668         m_pendingEditorCommands.append(commandString);
    669 }
    670 
    671453bool EditorClient::executePendingEditorCommands(Frame* frame, bool allowTextInsertion)
    672454{
    673455    Vector<Editor::Command> commands;
    674456    for (size_t i = 0; i < m_pendingEditorCommands.size(); i++) {
    675         const char* commandString = m_pendingEditorCommands.at(i);
    676         ASSERT(commandString);
    677         Editor::Command command = frame->editor()->command(commandString);
     457        Editor::Command command = frame->editor()->command(m_pendingEditorCommands.at(i).utf8().data());
    678458        if (command.isTextInsertion() && !allowTextInsertion)
    679459            return false;
     
    711491        return;
    712492
    713     generateEditorCommands(event);
     493    KeyBindingTranslator::EventType type = event->type() == eventNames().keydownEvent ?
     494        KeyBindingTranslator::KeyDown : KeyBindingTranslator::KeyPress;
     495    m_keyBindingTranslator.getEditorCommandsForKeyEvent(platformEvent->gdkEventKey(), type, m_pendingEditorCommands);
    714496    if (m_pendingEditorCommands.size() > 0) {
    715497
     
    845627    , m_preventNextCompositionCommit(false)
    846628    , m_treatContextCommitAsKeyEvent(false)
    847     , m_nativeWidget(gtk_text_view_new())
    848629{
    849630    WebKitWebViewPrivate* priv = m_webView->priv;
    850631    g_signal_connect(priv->imContext.get(), "commit", G_CALLBACK(imContextCommitted), this);
    851632    g_signal_connect(priv->imContext.get(), "preedit-changed", G_CALLBACK(imContextPreeditChanged), this);
    852 
    853     g_signal_connect(m_nativeWidget.get(), "backspace", G_CALLBACK(backspaceCallback), this);
    854     g_signal_connect(m_nativeWidget.get(), "cut-clipboard", G_CALLBACK(cutClipboardCallback), this);
    855     g_signal_connect(m_nativeWidget.get(), "copy-clipboard", G_CALLBACK(copyClipboardCallback), this);
    856     g_signal_connect(m_nativeWidget.get(), "paste-clipboard", G_CALLBACK(pasteClipboardCallback), this);
    857     g_signal_connect(m_nativeWidget.get(), "select-all", G_CALLBACK(selectAllCallback), this);
    858     g_signal_connect(m_nativeWidget.get(), "move-cursor", G_CALLBACK(moveCursorCallback), this);
    859     g_signal_connect(m_nativeWidget.get(), "delete-from-cursor", G_CALLBACK(deleteFromCursorCallback), this);
    860     g_signal_connect(m_nativeWidget.get(), "toggle-overwrite", G_CALLBACK(toggleOverwriteCallback), this);
    861     g_signal_connect(m_nativeWidget.get(), "popup-menu", G_CALLBACK(popupMenuCallback), this);
    862     g_signal_connect(m_nativeWidget.get(), "show-help", G_CALLBACK(showHelpCallback), this);
    863633}
    864634
  • trunk/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h

    r84574 r86436  
    3333
    3434#include "EditorClient.h"
     35#include "KeyBindingTranslator.h"
    3536#include "TextCheckerClient.h"
    36 
    3737#include <wtf/Deque.h>
    3838#include <wtf/Forward.h>
     
    147147        bool m_treatContextCommitAsKeyEvent;
    148148        GOwnPtr<gchar> m_pendingComposition;
    149         Vector<const char*> m_pendingEditorCommands;
    150         GRefPtr<GtkWidget> m_nativeWidget;
     149
     150        WebCore::KeyBindingTranslator m_keyBindingTranslator;
     151        Vector<WTF::String> m_pendingEditorCommands;
    151152    };
    152153}
  • trunk/Source/WebKit2/ChangeLog

    r86415 r86436  
     12011-05-13  Martin Robinson  <mrobinson@igalia.com>
     2
     3        Reviewed by Eric Seidel.
     4
     5        [GTK] Share the GTK+ key binding code between WebKit1 and WebKit2
     6        https://bugs.webkit.org/show_bug.cgi?id=59765
     7
     8        Use the new KeyBindingTranslator class from WebCore/platform/gtk. With this utility
     9        class we can now share the code with WebKit2.
     10
     11        * UIProcess/API/gtk/PageClientImpl.cpp:
     12        (WebKit::PageClientImpl::PageClientImpl): No longer need to initialize keybinding code.
     13        (WebKit::PageClientImpl::getEditorCommandsForKeyEvent): Use the new utility class.
     14        * UIProcess/API/gtk/PageClientImpl.h: Remove unnecessary members. Add utility class member.
     15
    1162011-05-12  Pratik Solanki  <psolanki@apple.com>
    217
  • trunk/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp

    r85987 r86436  
    4141#include <wtf/text/WTFString.h>
    4242
    43 typedef HashMap<int, const char*> IntConstCharHashMap;
    44 
    4543using namespace WebCore;
    4644
    4745namespace WebKit {
    48 
    49 static void backspaceCallback(GtkWidget* widget, PageClientImpl* client)
    50 {
    51     g_signal_stop_emission_by_name(widget, "backspace");
    52     client->addPendingEditorCommand("DeleteBackward");
    53 }
    54 
    55 static void selectAllCallback(GtkWidget* widget, gboolean select, PageClientImpl* client)
    56 {
    57     g_signal_stop_emission_by_name(widget, "select-all");
    58     client->addPendingEditorCommand(select ? "SelectAll" : "Unselect");
    59 }
    60 
    61 static void cutClipboardCallback(GtkWidget* widget, PageClientImpl* client)
    62 {
    63     g_signal_stop_emission_by_name(widget, "cut-clipboard");
    64     client->addPendingEditorCommand("Cut");
    65 }
    66 
    67 static void copyClipboardCallback(GtkWidget* widget, PageClientImpl* client)
    68 {
    69     g_signal_stop_emission_by_name(widget, "copy-clipboard");
    70     client->addPendingEditorCommand("Copy");
    71 }
    72 
    73 static void pasteClipboardCallback(GtkWidget* widget, PageClientImpl* client)
    74 {
    75     g_signal_stop_emission_by_name(widget, "paste-clipboard");
    76     client->addPendingEditorCommand("Paste");
    77 }
    78 
    79 static void toggleOverwriteCallback(GtkWidget* widget, EditorClient*)
    80 {
    81     // We don't support toggling the overwrite mode, but the default callback expects
    82     // the GtkTextView to have a layout, so we handle this signal just to stop it.
    83     g_signal_stop_emission_by_name(widget, "toggle-overwrite");
    84 }
    85 
    86 // GTK+ will still send these signals to the web view. So we can safely stop signal
    87 // emission without breaking accessibility.
    88 static void popupMenuCallback(GtkWidget* widget, EditorClient*)
    89 {
    90     g_signal_stop_emission_by_name(widget, "popup-menu");
    91 }
    92 
    93 static void showHelpCallback(GtkWidget* widget, EditorClient*)
    94 {
    95     g_signal_stop_emission_by_name(widget, "show-help");
    96 }
    97 
    98 static const char* const gtkDeleteCommands[][2] = {
    99     { "DeleteBackward",               "DeleteForward"                        }, // Characters
    100     { "DeleteWordBackward",           "DeleteWordForward"                    }, // Word ends
    101     { "DeleteWordBackward",           "DeleteWordForward"                    }, // Words
    102     { "DeleteToBeginningOfLine",      "DeleteToEndOfLine"                    }, // Lines
    103     { "DeleteToBeginningOfLine",      "DeleteToEndOfLine"                    }, // Line ends
    104     { "DeleteToBeginningOfParagraph", "DeleteToEndOfParagraph"               }, // Paragraph ends
    105     { "DeleteToBeginningOfParagraph", "DeleteToEndOfParagraph"               }, // Paragraphs
    106     { 0,                              0                                      } // Whitespace (M-\ in Emacs)
    107 };
    108 
    109 static void deleteFromCursorCallback(GtkWidget* widget, GtkDeleteType deleteType, gint count, PageClientImpl* client)
    110 {
    111     g_signal_stop_emission_by_name(widget, "delete-from-cursor");
    112     int direction = count > 0 ? 1 : 0;
    113 
    114     // Ensuring that deleteType <= G_N_ELEMENTS here results in a compiler warning
    115     // that the condition is always true.
    116 
    117     if (deleteType == GTK_DELETE_WORDS) {
    118         if (!direction) {
    119             client->addPendingEditorCommand("MoveWordForward");
    120             client->addPendingEditorCommand("MoveWordBackward");
    121         } else {
    122             client->addPendingEditorCommand("MoveWordBackward");
    123             client->addPendingEditorCommand("MoveWordForward");
    124         }
    125     } else if (deleteType == GTK_DELETE_DISPLAY_LINES) {
    126         if (!direction)
    127             client->addPendingEditorCommand("MoveToBeginningOfLine");
    128         else
    129             client->addPendingEditorCommand("MoveToEndOfLine");
    130     } else if (deleteType == GTK_DELETE_PARAGRAPHS) {
    131         if (!direction)
    132             client->addPendingEditorCommand("MoveToBeginningOfParagraph");
    133         else
    134             client->addPendingEditorCommand("MoveToEndOfParagraph");
    135     }
    136 
    137     const char* rawCommand = gtkDeleteCommands[deleteType][direction];
    138     if (!rawCommand)
    139       return;
    140 
    141     for (int i = 0; i < abs(count); i++)
    142         client->addPendingEditorCommand(rawCommand);
    143 }
    144 
    145 static const char* const gtkMoveCommands[][4] = {
    146     { "MoveBackward",                                   "MoveForward",
    147       "MoveBackwardAndModifySelection",                 "MoveForwardAndModifySelection"             }, // Forward/backward grapheme
    148     { "MoveLeft",                                       "MoveRight",
    149       "MoveBackwardAndModifySelection",                 "MoveForwardAndModifySelection"             }, // Left/right grapheme
    150     { "MoveWordBackward",                               "MoveWordForward",
    151       "MoveWordBackwardAndModifySelection",             "MoveWordForwardAndModifySelection"         }, // Forward/backward word
    152     { "MoveUp",                                         "MoveDown",
    153       "MoveUpAndModifySelection",                       "MoveDownAndModifySelection"                }, // Up/down line
    154     { "MoveToBeginningOfLine",                          "MoveToEndOfLine",
    155       "MoveToBeginningOfLineAndModifySelection",        "MoveToEndOfLineAndModifySelection"         }, // Up/down line ends
    156     { "MoveParagraphForward",                           "MoveParagraphBackward",
    157       "MoveParagraphForwardAndModifySelection",         "MoveParagraphBackwardAndModifySelection"   }, // Up/down paragraphs
    158     { "MoveToBeginningOfParagraph",                     "MoveToEndOfParagraph",
    159       "MoveToBeginningOfParagraphAndModifySelection",   "MoveToEndOfParagraphAndModifySelection"    }, // Up/down paragraph ends.
    160     { "MovePageUp",                                     "MovePageDown",
    161       "MovePageUpAndModifySelection",                   "MovePageDownAndModifySelection"            }, // Up/down page
    162     { "MoveToBeginningOfDocument",                      "MoveToEndOfDocument",
    163       "MoveToBeginningOfDocumentAndModifySelection",    "MoveToEndOfDocumentAndModifySelection"     }, // Begin/end of buffer
    164     { 0,                                                0,
    165       0,                                                0                                           } // Horizontal page movement
    166 };
    167 
    168 static void moveCursorCallback(GtkWidget* widget, GtkMovementStep step, gint count, gboolean extendSelection, PageClientImpl* client)
    169 {
    170     g_signal_stop_emission_by_name(widget, "move-cursor");
    171     int direction = count > 0 ? 1 : 0;
    172     if (extendSelection)
    173         direction += 2;
    174 
    175     if (static_cast<unsigned>(step) >= G_N_ELEMENTS(gtkMoveCommands))
    176         return;
    177 
    178     const char* rawCommand = gtkMoveCommands[step][direction];
    179     if (!rawCommand)
    180         return;
    181 
    182     for (int i = 0; i < abs(count); i++)
    183         client->addPendingEditorCommand(rawCommand);
    184 }
    185 
    186 static const unsigned CtrlKey = 1 << 0;
    187 static const unsigned AltKey = 1 << 1;
    188 static const unsigned ShiftKey = 1 << 2;
    189 
    190 struct KeyDownEntry {
    191     unsigned virtualKey;
    192     unsigned modifiers;
    193     const char* name;
    194 };
    195 
    196 struct KeyPressEntry {
    197     unsigned charCode;
    198     unsigned modifiers;
    199     const char* name;
    200 };
    201 
    202 static const KeyDownEntry keyDownEntries[] = {
    203     { 'B',       CtrlKey,            "ToggleBold"                                  },
    204     { 'I',       CtrlKey,            "ToggleItalic"                                },
    205     { VK_ESCAPE, 0,                  "Cancel"                                      },
    206     { VK_OEM_PERIOD, CtrlKey,        "Cancel"                                      },
    207     { VK_TAB,    0,                  "InsertTab"                                   },
    208     { VK_TAB,    ShiftKey,           "InsertBacktab"                               },
    209     { VK_RETURN, 0,                  "InsertNewline"                               },
    210     { VK_RETURN, CtrlKey,            "InsertNewline"                               },
    211     { VK_RETURN, AltKey,             "InsertNewline"                               },
    212     { VK_RETURN, AltKey | ShiftKey,  "InsertNewline"                               },
    213 };
    214 
    215 static const KeyPressEntry keyPressEntries[] = {
    216     { '\t',   0,                  "InsertTab"                                   },
    217     { '\t',   ShiftKey,           "InsertBacktab"                               },
    218     { '\r',   0,                  "InsertNewline"                               },
    219     { '\r',   CtrlKey,            "InsertNewline"                               },
    220     { '\r',   AltKey,             "InsertNewline"                               },
    221     { '\r',   AltKey | ShiftKey,  "InsertNewline"                               },
    222 };
    22346
    22447PageClientImpl::PageClientImpl(GtkWidget* viewWidget)
    22548    : m_viewWidget(viewWidget)
    226     , m_nativeWidget(gtk_text_view_new())
    227 {
    228     g_signal_connect(m_nativeWidget.get(), "backspace", G_CALLBACK(backspaceCallback), this);
    229     g_signal_connect(m_nativeWidget.get(), "cut-clipboard", G_CALLBACK(cutClipboardCallback), this);
    230     g_signal_connect(m_nativeWidget.get(), "copy-clipboard", G_CALLBACK(copyClipboardCallback), this);
    231     g_signal_connect(m_nativeWidget.get(), "paste-clipboard", G_CALLBACK(pasteClipboardCallback), this);
    232     g_signal_connect(m_nativeWidget.get(), "select-all", G_CALLBACK(selectAllCallback), this);
    233     g_signal_connect(m_nativeWidget.get(), "move-cursor", G_CALLBACK(moveCursorCallback), this);
    234     g_signal_connect(m_nativeWidget.get(), "delete-from-cursor", G_CALLBACK(deleteFromCursorCallback), this);
    235     g_signal_connect(m_nativeWidget.get(), "toggle-overwrite", G_CALLBACK(toggleOverwriteCallback), this);
    236     g_signal_connect(m_nativeWidget.get(), "popup-menu", G_CALLBACK(popupMenuCallback), this);
    237     g_signal_connect(m_nativeWidget.get(), "show-help", G_CALLBACK(showHelpCallback), this);
     49{
    23850}
    23951
     
    24456void PageClientImpl::getEditorCommandsForKeyEvent(const NativeWebKeyboardEvent& event, Vector<WTF::String>& commandList)
    24557{
    246     m_pendingEditorCommands.clear();
    247 
    248 #ifdef GTK_API_VERSION_2
    249     gtk_bindings_activate_event(GTK_OBJECT(m_nativeWidget.get()), const_cast<GdkEventKey*>(&event.nativeEvent()->key));
    250 #else
    251     gtk_bindings_activate_event(G_OBJECT(m_nativeWidget.get()), const_cast<GdkEventKey*>(&event.nativeEvent()->key));
    252 #endif
    253 
    254     if (m_pendingEditorCommands.isEmpty()) {
    255         commandList.append(m_pendingEditorCommands);
    256         return;
    257     }
    258 
    259     DEFINE_STATIC_LOCAL(IntConstCharHashMap, keyDownCommandsMap, ());
    260     DEFINE_STATIC_LOCAL(IntConstCharHashMap, keyPressCommandsMap, ());
    261 
    262     if (keyDownCommandsMap.isEmpty()) {
    263         for (unsigned i = 0; i < G_N_ELEMENTS(keyDownEntries); i++)
    264             keyDownCommandsMap.set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
    265 
    266         for (unsigned i = 0; i < G_N_ELEMENTS(keyPressEntries); i++)
    267             keyPressCommandsMap.set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name);
    268     }
    269 
    270     unsigned modifiers = 0;
    271     if (event.shiftKey())
    272         modifiers |= ShiftKey;
    273     if (event.altKey())
    274         modifiers |= AltKey;
    275     if (event.controlKey())
    276         modifiers |= CtrlKey;
    277 
    278     // For keypress events, we want charCode(), but keyCode() does that.
    279     int mapKey = modifiers << 16 | event.nativeVirtualKeyCode();
    280     if (mapKey) {
    281         HashMap<int, const char*>* commandMap = event.type() == WebEvent::KeyDown ?
    282             &keyDownCommandsMap : &keyPressCommandsMap;
    283         if (const char* commandString = commandMap->get(mapKey))
    284             m_pendingEditorCommands.append(commandString);
    285     }
    286 
    287     commandList.append(m_pendingEditorCommands);
     58    ASSERT(event.type == WebEvent::KeyDown || event.type == WebEvent.KeyPress);
     59    KeyBindingTranslator::EventType type = WebEvent::KeyDown ?
     60        KeyBindingTranslator::KeyDown : KeyBindingTranslator::KeyPress;
     61    m_keyBindingTranslator.getEditorCommandsForKeyEvent(const_cast<GdkEventKey*>(&event.nativeEvent()->key), type, commandList);
    28862}
    28963
  • trunk/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h

    r85931 r86436  
    2929#define PageClientImpl_h
    3030
     31#include "KeyBindingTranslator.h"
    3132#include "PageClient.h"
    3233#include "WebPageProxy.h"
     
    4748        return adoptPtr(new PageClientImpl(viewWidget));
    4849    }
    49 
    50     void addPendingEditorCommand(const char* command) { m_pendingEditorCommands.append(WTF::String(command)); }
    5150
    5251private:
     
    101100    // Members of PageClientImpl class
    102101    GtkWidget* m_viewWidget;
    103     Vector<WTF::String> m_pendingEditorCommands;
    104     GRefPtr<GtkWidget> m_nativeWidget;
     102    WebCore::KeyBindingTranslator m_keyBindingTranslator;
    105103};
    106104
Note: See TracChangeset for help on using the changeset viewer.