1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef CHROME_BROWSER_UI_LIBGTK2UI_GTK2_KEY_BINDINGS_HANDLER_H_ 6#define CHROME_BROWSER_UI_LIBGTK2UI_GTK2_KEY_BINDINGS_HANDLER_H_ 7 8#include <gtk/gtk.h> 9 10#include <string> 11#include <vector> 12 13#include "base/event_types.h" 14#include "chrome/browser/ui/libgtk2ui/owned_widget_gtk2.h" 15#include "ui/events/linux/text_edit_command_auralinux.h" 16 17namespace content { 18struct NativeWebKeyboardEvent; 19} 20 21namespace ui { 22class Event; 23} 24 25namespace libgtk2ui { 26 27// This class is a convenience class for handling editor key bindings defined 28// in gtk keyboard theme. 29// In gtk, only GtkEntry and GtkTextView support customizing editor key bindings 30// through keyboard theme. And in gtk keyboard theme definition file, each key 31// binding must be bound to a specific class or object. So existing keyboard 32// themes only define editor key bindings exactly for GtkEntry and GtkTextView. 33// Then, the only way for us to intercept editor key bindings defined in 34// keyboard theme, is to create a GtkEntry or GtkTextView object and call 35// gtk_bindings_activate_event() against it for the key events. If a key event 36// matches a predefined key binding, corresponding signal will be emitted. 37// GtkTextView is used here because it supports more key bindings than GtkEntry, 38// but in order to minimize the side effect of using a GtkTextView object, a new 39// class derived from GtkTextView is used, which overrides all signals related 40// to key bindings, to make sure GtkTextView won't receive them. 41// 42// See third_party/WebKit/Source/WebCore/editing/EditorCommand.cpp for detailed 43// definition of webkit edit commands. 44// See webkit/glue/editor_client_impl.cc for key bindings predefined in our 45// webkit glue. 46class Gtk2KeyBindingsHandler { 47 public: 48 Gtk2KeyBindingsHandler(); 49 virtual ~Gtk2KeyBindingsHandler(); 50 51 // Matches a key event against predefined gtk key bindings, false will be 52 // returned if the key event doesn't correspond to a predefined key binding. 53 // Edit commands matched with |event| will be stored in |edit_commands|, if 54 // non-NULL. 55 bool MatchEvent(const ui::Event& event, 56 std::vector<ui::TextEditCommandAuraLinux>* commands); 57 58 private: 59 // Object structure of Handler class, which is derived from GtkTextView. 60 struct Handler { 61 GtkTextView parent_object; 62 Gtk2KeyBindingsHandler *owner; 63 }; 64 65 // Class structure of Handler class. 66 struct HandlerClass { 67 GtkTextViewClass parent_class; 68 }; 69 70 // Creates a new instance of Handler class. 71 GtkWidget* CreateNewHandler(); 72 73 // Adds an edit command to the key event. 74 void EditCommandMatched(ui::TextEditCommandAuraLinux::CommandId id, 75 const std::string& value, 76 bool extend_selection); 77 78 // Builds a fake GdkEventKey from an XEvent. 79 void BuildGdkEventKeyFromXEvent(const base::NativeEvent& xevent, 80 GdkEventKey* gdk_event); 81 82 // Initializes Handler structure. 83 static void HandlerInit(Handler *self); 84 85 // Initializes HandlerClass structure. 86 static void HandlerClassInit(HandlerClass *klass); 87 88 // Registeres Handler class to GObject type system and return its type id. 89 static GType HandlerGetType(); 90 91 // Gets the Gtk2KeyBindingsHandler object which owns the Handler object. 92 static Gtk2KeyBindingsHandler* GetHandlerOwner(GtkTextView* text_view); 93 94 // Handler of "backspace" signal. 95 static void BackSpace(GtkTextView* text_view); 96 97 // Handler of "copy-clipboard" signal. 98 static void CopyClipboard(GtkTextView* text_view); 99 100 // Handler of "cut-clipboard" signal. 101 static void CutClipboard(GtkTextView* text_view); 102 103 // Handler of "delete-from-cursor" signal. 104 static void DeleteFromCursor(GtkTextView* text_view, GtkDeleteType type, 105 gint count); 106 107 // Handler of "insert-at-cursor" signal. 108 static void InsertAtCursor(GtkTextView* text_view, const gchar* str); 109 110 // Handler of "move-cursor" signal. 111 static void MoveCursor(GtkTextView* text_view, GtkMovementStep step, 112 gint count, gboolean extend_selection); 113 114 // Handler of "move-viewport" signal. 115 static void MoveViewport(GtkTextView* text_view, GtkScrollStep step, 116 gint count); 117 118 // Handler of "paste-clipboard" signal. 119 static void PasteClipboard(GtkTextView* text_view); 120 121 // Handler of "select-all" signal. 122 static void SelectAll(GtkTextView* text_view, gboolean select); 123 124 // Handler of "set-anchor" signal. 125 static void SetAnchor(GtkTextView* text_view); 126 127 // Handler of "toggle-cursor-visible" signal. 128 static void ToggleCursorVisible(GtkTextView* text_view); 129 130 // Handler of "toggle-overwrite" signal. 131 static void ToggleOverwrite(GtkTextView* text_view); 132 133 // Handler of "show-help" signal. 134 static gboolean ShowHelp(GtkWidget* widget, GtkWidgetHelpType arg1); 135 136 // Handler of "move-focus" signal. 137 static void MoveFocus(GtkWidget* widget, GtkDirectionType arg1); 138 139 GtkWidget* fake_window_; 140 141 libgtk2ui::OwnedWidgetGtk handler_; 142 143 // Buffer to store the match results. 144 std::vector<ui::TextEditCommandAuraLinux> edit_commands_; 145 146 // Whether the current X server has the XKeyboard extension. 147 bool has_xkb_; 148}; 149 150} // namespace libgtk2ui 151 152#endif // CHROME_BROWSER_UI_LIBGTK2UI_GTK2_KEY_BINDINGS_HANDLER_H_ 153