Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(220)

Side by Side Diff: chrome/browser/renderer_host/gtk_key_bindings_handler.cc

Issue 165293: Supports Gtk keyboard themes.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 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 #include "chrome/browser/renderer_host/gtk_key_bindings_handler.h"
6
7 #include <gdk/gdkkeysyms.h>
8
9 #include <string>
10
11 #include "base/logging.h"
12 #include "base/string_util.h"
13 #include "chrome/common/native_web_keyboard_event.h"
14
15 GtkKeyBindingsHandler::GtkKeyBindingsHandler(GtkWidget* parent_widget)
16 : handler_(CreateNewHandler()),
17 edit_commands_(NULL),
18 enabled_(false) {
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);
24 }
25
26 GtkKeyBindingsHandler::~GtkKeyBindingsHandler() {
27 handler_.Destroy();
28 }
29
30 bool GtkKeyBindingsHandler::Match(const NativeWebKeyboardEvent& wke,
31 EditCommands* edit_commands) {
32 if (!enabled_ || wke.type == WebKit::WebInputEvent::Char ||
33 !wke.os_event || wke.os_event->keyval == GDK_VoidSymbol)
34 return false;
35
36 edit_commands_.clear();
37 // If this key event matches a predefined key binding, corresponding signal
38 // will be emitted.
39 gtk_bindings_activate_event(GTK_OBJECT(handler_.get()), wke.os_event);
40
41 bool matched = !edit_commands_.empty();
42 if (edit_commands)
43 edit_commands->swap(edit_commands_);
44 return matched;
45 }
46
47 GtkWidget* GtkKeyBindingsHandler::CreateNewHandler() {
48 Handler* handler =
49 static_cast<Handler*>(g_object_new(HandlerGetType(), NULL));
50
51 handler->owner = this;
52
53 // We don't need to show the |handler| object on screen, so set its size to
54 // zero.
55 gtk_widget_set_size_request(GTK_WIDGET(handler), 0, 0);
56
57 // Prevents it from handling any events by itself.
58 gtk_widget_set_sensitive(GTK_WIDGET(handler), FALSE);
59 gtk_widget_set_events(GTK_WIDGET(handler), 0);
60 GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(handler), GTK_CAN_FOCUS);
61
62 #if !GTK_CHECK_VERSION(2, 14, 0)
63 // "move-viewport", "select-all" and "toggle-cursor-visible" have no
64 // corresponding virtual methods. Prior to glib 2.18 (gtk 2.14), there is no
65 // way to override the default class handler of a signal. So we need hook
66 // these signal explicitly.
67 g_signal_connect(handler, "move-viewport", G_CALLBACK(MoveViewport), NULL);
68 g_signal_connect(handler, "select-all", G_CALLBACK(SelectAll), NULL);
69 g_signal_connect(handler, "toggle-cursor-visible",
70 G_CALLBACK(ToggleCursorVisible), NULL);
71 #endif
72 return GTK_WIDGET(handler);
73 }
74
75 void GtkKeyBindingsHandler::EditCommandMatched(
76 const std::string& name, const std::string& value) {
77 edit_commands_.push_back(EditCommand(name, value));
78 }
79
80 void GtkKeyBindingsHandler::HandlerInit(Handler *self) {
81 self->owner = NULL;
82 }
83
84 void GtkKeyBindingsHandler::HandlerClassInit(HandlerClass *klass) {
85 GtkTextViewClass* text_view_class = GTK_TEXT_VIEW_CLASS(klass);
86
87 // Overrides all virtual methods related to editor key bindings.
88 text_view_class->backspace = BackSpace;
89 text_view_class->copy_clipboard = CopyClipboard;
90 text_view_class->cut_clipboard = CutClipboard;
91 text_view_class->delete_from_cursor = DeleteFromCursor;
92 text_view_class->insert_at_cursor = InsertAtCursor;
93 text_view_class->move_cursor = MoveCursor;
94 text_view_class->paste_clipboard = PasteClipboard;
95 text_view_class->set_anchor = SetAnchor;
96 text_view_class->toggle_overwrite = ToggleOverwrite;
97
98 #if GTK_CHECK_VERSION(2, 14, 0)
99 // "move-viewport", "select-all" and "toggle-cursor-visible" have no
100 // corresponding virtual methods. Since glib 2.18 (gtk 2.14),
101 // g_signal_override_class_handler() is introduced to override a signal
102 // handler.
103 g_signal_override_class_handler("move-viewport",
104 G_TYPE_FROM_CLASS(klass),
105 G_CALLBACK(MoveViewport));
106
107 g_signal_override_class_handler("select-all",
108 G_TYPE_FROM_CLASS(klass),
109 G_CALLBACK(SelectAll));
110
111 g_signal_override_class_handler("toggle-cursor-visible",
112 G_TYPE_FROM_CLASS(klass),
113 G_CALLBACK(ToggleCursorVisible));
114 #endif
115 }
116
117 GType GtkKeyBindingsHandler::HandlerGetType() {
118 static volatile gsize type_id_volatile = 0;
119 if (g_once_init_enter(&type_id_volatile)) {
120 GType type_id = g_type_register_static_simple(
121 GTK_TYPE_TEXT_VIEW,
122 g_intern_static_string("GtkKeyBindingsHandler"),
123 sizeof(HandlerClass),
124 reinterpret_cast<GClassInitFunc>(HandlerClassInit),
125 sizeof(Handler),
126 reinterpret_cast<GInstanceInitFunc>(HandlerInit),
127 static_cast<GTypeFlags>(0));
128 g_once_init_leave(&type_id_volatile, type_id);
129 }
130 return type_id_volatile;
131 }
132
133 GtkKeyBindingsHandler* GtkKeyBindingsHandler::GetHandlerOwner(
134 GtkTextView* text_view) {
135 Handler* handler = G_TYPE_CHECK_INSTANCE_CAST(
136 text_view, HandlerGetType(), Handler);
137 DCHECK(handler);
138 return handler->owner;
139 }
140
141 void GtkKeyBindingsHandler::BackSpace(GtkTextView* text_view) {
142 GetHandlerOwner(text_view)->EditCommandMatched("DeleteBackward", "");
143 }
144
145 void GtkKeyBindingsHandler::CopyClipboard(GtkTextView* text_view) {
146 GetHandlerOwner(text_view)->EditCommandMatched("Copy", "");
147 }
148
149 void GtkKeyBindingsHandler::CutClipboard(GtkTextView* text_view) {
150 GetHandlerOwner(text_view)->EditCommandMatched("Cut", "");
151 }
152
153 void GtkKeyBindingsHandler::DeleteFromCursor(
154 GtkTextView* text_view, GtkDeleteType type, gint count) {
155 if (!count)
156 return;
157
158 const char *commands[3] = { NULL, NULL, NULL };
159 switch (type) {
160 case GTK_DELETE_CHARS:
161 commands[0] = (count > 0 ? "DeleteForward" : "DeleteBackward");
162 break;
163 case GTK_DELETE_WORD_ENDS:
164 commands[0] = (count > 0 ? "DeleteWordForward" : "DeleteWordBackward");
165 break;
166 case GTK_DELETE_WORDS:
167 if (count > 0) {
168 commands[0] = "MoveWordForward";
169 commands[1] = "DeleteWordBackward";
170 } else {
171 commands[0] = "MoveWordBackward";
172 commands[1] = "DeleteWordForward";
173 }
174 break;
175 case GTK_DELETE_DISPLAY_LINES:
176 commands[0] = "MoveToBeginningOfLine";
177 commands[1] = "DeleteToEndOfLine";
178 break;
179 case GTK_DELETE_DISPLAY_LINE_ENDS:
180 commands[0] = (count > 0 ? "DeleteToEndOfLine" :
181 "DeleteToBeginningOfLine");
182 break;
183 case GTK_DELETE_PARAGRAPH_ENDS:
184 commands[0] = (count > 0 ? "DeleteToEndOfParagraph" :
185 "DeleteToBeginningOfParagraph");
186 break;
187 case GTK_DELETE_PARAGRAPHS:
188 commands[0] = "MoveToBeginningOfParagraph";
189 commands[1] = "DeleteToEndOfParagraph";
190 break;
191 default:
192 // GTK_DELETE_WHITESPACE has no corresponding editor command.
193 return;
194 }
195
196 GtkKeyBindingsHandler* owner = GetHandlerOwner(text_view);
197 if (count < 0)
198 count = -count;
199 for (; count > 0; --count) {
200 for (const char* const* p = commands; *p; ++p)
201 owner->EditCommandMatched(*p, "");
202 }
203 }
204
205 void GtkKeyBindingsHandler::InsertAtCursor(GtkTextView* text_view,
206 const gchar* str) {
207 if (str && *str)
208 GetHandlerOwner(text_view)->EditCommandMatched("InsertText", str);
209 }
210
211 void GtkKeyBindingsHandler::MoveCursor(
212 GtkTextView* text_view, GtkMovementStep step, gint count,
213 gboolean extend_selection) {
214 if (!count)
215 return;
216
217 std::string command;
218 switch (step) {
219 case GTK_MOVEMENT_LOGICAL_POSITIONS:
220 command = (count > 0 ? "MoveForward" : "MoveBackward");
221 break;
222 case GTK_MOVEMENT_VISUAL_POSITIONS:
223 command = (count > 0 ? "MoveRight" : "MoveLeft");
224 break;
225 case GTK_MOVEMENT_WORDS:
226 command = (count > 0 ? "MoveWordForward" : "MoveWordBackward");
227 break;
228 case GTK_MOVEMENT_DISPLAY_LINES:
229 command = (count > 0 ? "MoveDown" : "MoveUp");
230 break;
231 case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
232 command = (count > 0 ? "MoveToEndOfLine" : "MoveToBeginningOfLine");
233 break;
234 case GTK_MOVEMENT_PARAGRAPH_ENDS:
235 command = (count > 0 ? "MoveToEndOfParagraph" :
236 "MoveToBeginningOfParagraph");
237 break;
238 case GTK_MOVEMENT_PAGES:
239 command = (count > 0 ? "MovePageDown" : "MovePageUp");
240 break;
241 case GTK_MOVEMENT_BUFFER_ENDS:
242 command = (count > 0 ? "MoveToEndOfDocument" :
243 "MoveToBeginningOfDocument");
244 break;
245 default:
246 // GTK_MOVEMENT_PARAGRAPHS and GTK_MOVEMENT_HORIZONTAL_PAGES have
247 // no corresponding editor commands.
248 return;
249 }
250
251 GtkKeyBindingsHandler* owner = GetHandlerOwner(text_view);
252 if (extend_selection)
253 command.append("AndModifySelection");
254 if (count < 0)
255 count = -count;
256 for (; count > 0; --count)
257 owner->EditCommandMatched(command, "");
258 }
259
260 void GtkKeyBindingsHandler::MoveViewport(
261 GtkTextView* text_view, GtkScrollStep step, gint count) {
262 // Not supported by webkit.
263 #if !GTK_CHECK_VERSION(2, 14, 0)
264 // Before gtk 2.14.0, there is no way to override a non-virtual default signal
265 // handler, so we need stop the signal emission explicitly to prevent the
266 // default handler from being executed.
267 g_signal_stop_emission_by_name(text_view, "move-viewport");
268 #endif
269 }
270
271 void GtkKeyBindingsHandler::PasteClipboard(GtkTextView* text_view) {
272 GetHandlerOwner(text_view)->EditCommandMatched("Paste", "");
273 }
274
275 void GtkKeyBindingsHandler::SelectAll(GtkTextView* text_view, gboolean select) {
276 if (select)
277 GetHandlerOwner(text_view)->EditCommandMatched("SelectAll", "");
278 else
279 GetHandlerOwner(text_view)->EditCommandMatched("Unselect", "");
280 #if !GTK_CHECK_VERSION(2, 14, 0)
281 // Before gtk 2.14.0, there is no way to override a non-virtual default signal
282 // handler, so we need stop the signal emission explicitly to prevent the
283 // default handler from being executed.
284 g_signal_stop_emission_by_name(text_view, "select-all");
285 #endif
286 }
287
288 void GtkKeyBindingsHandler::SetAnchor(GtkTextView* text_view) {
289 GetHandlerOwner(text_view)->EditCommandMatched("SetMark", "");
290 }
291
292 void GtkKeyBindingsHandler::ToggleCursorVisible(GtkTextView* text_view) {
293 // Not supported by webkit.
294 #if !GTK_CHECK_VERSION(2, 14, 0)
295 // Before gtk 2.14.0, there is no way to override a non-virtual default signal
296 // handler, so we need stop the signal emission explicitly to prevent the
297 // default handler from being executed.
298 g_signal_stop_emission_by_name(text_view, "toggle-cursor-visible");
299 #endif
300 }
301
302 void GtkKeyBindingsHandler::ToggleOverwrite(GtkTextView* text_view) {
303 // Not supported by webkit.
304 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698