Update ASan/Android runtime and setup script to LLVM r200682.
[chromium-blink-merge.git] / content / browser / renderer_host / gtk_key_bindings_handler.cc
blob3830364a0e8ff1b979306e06f5f6341d0fb58396
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.
5 #include "content/browser/renderer_host/gtk_key_bindings_handler.h"
7 #include <gdk/gdkkeysyms.h>
9 #include <string>
11 #include "base/logging.h"
12 #include "base/strings/string_util.h"
13 #include "content/public/browser/native_web_keyboard_event.h"
15 namespace content {
17 GtkKeyBindingsHandler::GtkKeyBindingsHandler(GtkWidget* parent_widget)
18 : handler_(CreateNewHandler()) {
19 DCHECK(GTK_IS_FIXED(parent_widget));
20 // We need add the |handler_| object into gtk widget hierarchy, so that
21 // gtk_bindings_activate_event() can find correct display and keymaps from
22 // the |handler_| object.
23 gtk_fixed_put(GTK_FIXED(parent_widget), handler_.get(), -1, -1);
26 GtkKeyBindingsHandler::~GtkKeyBindingsHandler() {
27 handler_.Destroy();
30 bool GtkKeyBindingsHandler::Match(const NativeWebKeyboardEvent& wke,
31 EditCommands* edit_commands) {
32 if (wke.type == blink::WebInputEvent::Char || !wke.os_event)
33 return false;
35 edit_commands_.clear();
36 // If this key event matches a predefined key binding, corresponding signal
37 // will be emitted.
38 gtk_bindings_activate_event(GTK_OBJECT(handler_.get()), &wke.os_event->key);
40 bool matched = !edit_commands_.empty();
41 if (edit_commands)
42 edit_commands->swap(edit_commands_);
43 return matched;
46 GtkWidget* GtkKeyBindingsHandler::CreateNewHandler() {
47 Handler* handler =
48 static_cast<Handler*>(g_object_new(HandlerGetType(), NULL));
50 handler->owner = this;
52 // We don't need to show the |handler| object on screen, so set its size to
53 // zero.
54 gtk_widget_set_size_request(GTK_WIDGET(handler), 0, 0);
56 // Prevents it from handling any events by itself.
57 gtk_widget_set_sensitive(GTK_WIDGET(handler), FALSE);
58 gtk_widget_set_events(GTK_WIDGET(handler), 0);
59 gtk_widget_set_can_focus(GTK_WIDGET(handler), TRUE);
61 return GTK_WIDGET(handler);
64 void GtkKeyBindingsHandler::EditCommandMatched(
65 const std::string& name, const std::string& value) {
66 edit_commands_.push_back(EditCommand(name, value));
69 void GtkKeyBindingsHandler::HandlerInit(Handler *self) {
70 self->owner = NULL;
73 void GtkKeyBindingsHandler::HandlerClassInit(HandlerClass *klass) {
74 GtkTextViewClass* text_view_class = GTK_TEXT_VIEW_CLASS(klass);
75 GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
77 // Overrides all virtual methods related to editor key bindings.
78 text_view_class->backspace = BackSpace;
79 text_view_class->copy_clipboard = CopyClipboard;
80 text_view_class->cut_clipboard = CutClipboard;
81 text_view_class->delete_from_cursor = DeleteFromCursor;
82 text_view_class->insert_at_cursor = InsertAtCursor;
83 text_view_class->move_cursor = MoveCursor;
84 text_view_class->paste_clipboard = PasteClipboard;
85 text_view_class->set_anchor = SetAnchor;
86 text_view_class->toggle_overwrite = ToggleOverwrite;
87 widget_class->show_help = ShowHelp;
89 // "move-focus", "move-viewport", "select-all" and "toggle-cursor-visible"
90 // have no corresponding virtual methods. Since glib 2.18 (gtk 2.14),
91 // g_signal_override_class_handler() is introduced to override a signal
92 // handler.
93 g_signal_override_class_handler("move-focus",
94 G_TYPE_FROM_CLASS(klass),
95 G_CALLBACK(MoveFocus));
97 g_signal_override_class_handler("move-viewport",
98 G_TYPE_FROM_CLASS(klass),
99 G_CALLBACK(MoveViewport));
101 g_signal_override_class_handler("select-all",
102 G_TYPE_FROM_CLASS(klass),
103 G_CALLBACK(SelectAll));
105 g_signal_override_class_handler("toggle-cursor-visible",
106 G_TYPE_FROM_CLASS(klass),
107 G_CALLBACK(ToggleCursorVisible));
110 GType GtkKeyBindingsHandler::HandlerGetType() {
111 static volatile gsize type_id_volatile = 0;
112 if (g_once_init_enter(&type_id_volatile)) {
113 GType type_id = g_type_register_static_simple(
114 GTK_TYPE_TEXT_VIEW,
115 g_intern_static_string("GtkKeyBindingsHandler"),
116 sizeof(HandlerClass),
117 reinterpret_cast<GClassInitFunc>(HandlerClassInit),
118 sizeof(Handler),
119 reinterpret_cast<GInstanceInitFunc>(HandlerInit),
120 static_cast<GTypeFlags>(0));
121 g_once_init_leave(&type_id_volatile, type_id);
123 return type_id_volatile;
126 GtkKeyBindingsHandler* GtkKeyBindingsHandler::GetHandlerOwner(
127 GtkTextView* text_view) {
128 Handler* handler = G_TYPE_CHECK_INSTANCE_CAST(
129 text_view, HandlerGetType(), Handler);
130 DCHECK(handler);
131 return handler->owner;
134 void GtkKeyBindingsHandler::BackSpace(GtkTextView* text_view) {
135 GetHandlerOwner(text_view)
136 ->EditCommandMatched("DeleteBackward", std::string());
139 void GtkKeyBindingsHandler::CopyClipboard(GtkTextView* text_view) {
140 GetHandlerOwner(text_view)->EditCommandMatched("Copy", std::string());
143 void GtkKeyBindingsHandler::CutClipboard(GtkTextView* text_view) {
144 GetHandlerOwner(text_view)->EditCommandMatched("Cut", std::string());
147 void GtkKeyBindingsHandler::DeleteFromCursor(
148 GtkTextView* text_view, GtkDeleteType type, gint count) {
149 if (!count)
150 return;
152 const char *commands[3] = { NULL, NULL, NULL };
153 switch (type) {
154 case GTK_DELETE_CHARS:
155 commands[0] = (count > 0 ? "DeleteForward" : "DeleteBackward");
156 break;
157 case GTK_DELETE_WORD_ENDS:
158 commands[0] = (count > 0 ? "DeleteWordForward" : "DeleteWordBackward");
159 break;
160 case GTK_DELETE_WORDS:
161 if (count > 0) {
162 commands[0] = "MoveWordForward";
163 commands[1] = "DeleteWordBackward";
164 } else {
165 commands[0] = "MoveWordBackward";
166 commands[1] = "DeleteWordForward";
168 break;
169 case GTK_DELETE_DISPLAY_LINES:
170 commands[0] = "MoveToBeginningOfLine";
171 commands[1] = "DeleteToEndOfLine";
172 break;
173 case GTK_DELETE_DISPLAY_LINE_ENDS:
174 commands[0] = (count > 0 ? "DeleteToEndOfLine" :
175 "DeleteToBeginningOfLine");
176 break;
177 case GTK_DELETE_PARAGRAPH_ENDS:
178 commands[0] = (count > 0 ? "DeleteToEndOfParagraph" :
179 "DeleteToBeginningOfParagraph");
180 break;
181 case GTK_DELETE_PARAGRAPHS:
182 commands[0] = "MoveToBeginningOfParagraph";
183 commands[1] = "DeleteToEndOfParagraph";
184 break;
185 default:
186 // GTK_DELETE_WHITESPACE has no corresponding editor command.
187 return;
190 GtkKeyBindingsHandler* owner = GetHandlerOwner(text_view);
191 if (count < 0)
192 count = -count;
193 for (; count > 0; --count) {
194 for (const char* const* p = commands; *p; ++p)
195 owner->EditCommandMatched(*p, std::string());
199 void GtkKeyBindingsHandler::InsertAtCursor(GtkTextView* text_view,
200 const gchar* str) {
201 if (str && *str)
202 GetHandlerOwner(text_view)->EditCommandMatched("InsertText", str);
205 void GtkKeyBindingsHandler::MoveCursor(
206 GtkTextView* text_view, GtkMovementStep step, gint count,
207 gboolean extend_selection) {
208 if (!count)
209 return;
211 std::string command;
212 switch (step) {
213 case GTK_MOVEMENT_LOGICAL_POSITIONS:
214 command = (count > 0 ? "MoveForward" : "MoveBackward");
215 break;
216 case GTK_MOVEMENT_VISUAL_POSITIONS:
217 command = (count > 0 ? "MoveRight" : "MoveLeft");
218 break;
219 case GTK_MOVEMENT_WORDS:
220 command = (count > 0 ? "MoveWordRight" : "MoveWordLeft");
221 break;
222 case GTK_MOVEMENT_DISPLAY_LINES:
223 command = (count > 0 ? "MoveDown" : "MoveUp");
224 break;
225 case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
226 command = (count > 0 ? "MoveToEndOfLine" : "MoveToBeginningOfLine");
227 break;
228 case GTK_MOVEMENT_PARAGRAPH_ENDS:
229 command = (count > 0 ? "MoveToEndOfParagraph" :
230 "MoveToBeginningOfParagraph");
231 break;
232 case GTK_MOVEMENT_PAGES:
233 command = (count > 0 ? "MovePageDown" : "MovePageUp");
234 break;
235 case GTK_MOVEMENT_BUFFER_ENDS:
236 command = (count > 0 ? "MoveToEndOfDocument" :
237 "MoveToBeginningOfDocument");
238 break;
239 default:
240 // GTK_MOVEMENT_PARAGRAPHS and GTK_MOVEMENT_HORIZONTAL_PAGES have
241 // no corresponding editor commands.
242 return;
245 GtkKeyBindingsHandler* owner = GetHandlerOwner(text_view);
246 if (extend_selection)
247 command.append("AndModifySelection");
248 if (count < 0)
249 count = -count;
250 for (; count > 0; --count)
251 owner->EditCommandMatched(command, std::string());
254 void GtkKeyBindingsHandler::MoveViewport(
255 GtkTextView* text_view, GtkScrollStep step, gint count) {
256 // Not supported by webkit.
259 void GtkKeyBindingsHandler::PasteClipboard(GtkTextView* text_view) {
260 GetHandlerOwner(text_view)->EditCommandMatched("Paste", std::string());
263 void GtkKeyBindingsHandler::SelectAll(GtkTextView* text_view, gboolean select) {
264 if (select)
265 GetHandlerOwner(text_view)->EditCommandMatched("SelectAll", std::string());
266 else
267 GetHandlerOwner(text_view)->EditCommandMatched("Unselect", std::string());
270 void GtkKeyBindingsHandler::SetAnchor(GtkTextView* text_view) {
271 GetHandlerOwner(text_view)->EditCommandMatched("SetMark", std::string());
274 void GtkKeyBindingsHandler::ToggleCursorVisible(GtkTextView* text_view) {
275 // Not supported by webkit.
278 void GtkKeyBindingsHandler::ToggleOverwrite(GtkTextView* text_view) {
279 // Not supported by webkit.
282 gboolean GtkKeyBindingsHandler::ShowHelp(GtkWidget* widget,
283 GtkWidgetHelpType arg1) {
284 // Just for disabling the default handler.
285 return FALSE;
288 void GtkKeyBindingsHandler::MoveFocus(GtkWidget* widget,
289 GtkDirectionType arg1) {
290 // Just for disabling the default handler.
293 } // namespace content