Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" | 5 #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" |
| 6 | 6 |
| 7 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
| 8 #include <gdk/gdkkeysyms.h> | |
|
Evan Martin
2009/03/11 18:25:32
alphabetize?
| |
| 8 | 9 |
| 9 #include "base/logging.h" | 10 #include "base/logging.h" |
| 10 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 11 #include "chrome/browser/autocomplete/autocomplete_edit.h" | 12 #include "chrome/browser/autocomplete/autocomplete_edit.h" |
| 12 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" | 13 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" |
| 13 #include "chrome/browser/autocomplete/autocomplete_popup_view_gtk.h" | 14 #include "chrome/browser/autocomplete/autocomplete_popup_view_gtk.h" |
| 14 #include "chrome/browser/tab_contents/tab_contents.h" | 15 #include "chrome/browser/tab_contents/tab_contents.h" |
| 15 #include "chrome/browser/toolbar_model.h" | 16 #include "chrome/browser/toolbar_model.h" |
| 16 #include "chrome/common/notification_service.h" | 17 #include "chrome/common/notification_service.h" |
| 17 #include "googleurl/src/gurl.h" | 18 #include "googleurl/src/gurl.h" |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 NULL, "foreground", kInsecureSchemeColor, NULL); | 80 NULL, "foreground", kInsecureSchemeColor, NULL); |
| 80 | 81 |
| 81 // NOTE: This code used to connect to "changed", however this was fired too | 82 // NOTE: This code used to connect to "changed", however this was fired too |
| 82 // often and during bad times (our own buffer changes?). It works out much | 83 // often and during bad times (our own buffer changes?). It works out much |
| 83 // better to listen to end-user-action, which should be fired whenever the | 84 // better to listen to end-user-action, which should be fired whenever the |
| 84 // user makes some sort of change to the buffer. | 85 // user makes some sort of change to the buffer. |
| 85 g_signal_connect(text_buffer_, "begin-user-action", | 86 g_signal_connect(text_buffer_, "begin-user-action", |
| 86 G_CALLBACK(&HandleBeginUserActionThunk), this); | 87 G_CALLBACK(&HandleBeginUserActionThunk), this); |
| 87 g_signal_connect(text_buffer_, "end-user-action", | 88 g_signal_connect(text_buffer_, "end-user-action", |
| 88 G_CALLBACK(&HandleEndUserActionThunk), this); | 89 G_CALLBACK(&HandleEndUserActionThunk), this); |
| 90 // We connect to key press and release for special handling of the enter key. | |
| 91 g_signal_connect(text_view_, "key-press-event", | |
| 92 G_CALLBACK(&HandleKeyPressThunk), this); | |
| 93 g_signal_connect(text_view_, "key-release-event", | |
| 94 G_CALLBACK(&HandleKeyReleaseThunk), this); | |
| 89 g_signal_connect(text_view_, "size-request", | 95 g_signal_connect(text_view_, "size-request", |
| 90 G_CALLBACK(&HandleViewSizeRequest), this); | 96 G_CALLBACK(&HandleViewSizeRequest), this); |
| 91 g_signal_connect(text_view_, "button-press-event", | 97 g_signal_connect(text_view_, "button-press-event", |
| 92 G_CALLBACK(&HandleViewButtonPressThunk), this); | 98 G_CALLBACK(&HandleViewButtonPressThunk), this); |
| 93 g_signal_connect(text_view_, "focus-in-event", | 99 g_signal_connect(text_view_, "focus-in-event", |
| 94 G_CALLBACK(&HandleViewFocusInThunk), this); | 100 G_CALLBACK(&HandleViewFocusInThunk), this); |
| 95 g_signal_connect(text_view_, "focus-out-event", | 101 g_signal_connect(text_view_, "focus-out-event", |
| 96 G_CALLBACK(&HandleViewFocusOutThunk), this); | 102 G_CALLBACK(&HandleViewFocusOutThunk), this); |
| 97 // NOTE: The GtkTextView documentation asks you not to connect to this | 103 // NOTE: The GtkTextView documentation asks you not to connect to this |
| 98 // signal, but it is very convenient and clean for catching up/down. | 104 // signal, but it is very convenient and clean for catching up/down. |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 286 gdk_window_get_origin(text_view_->window, x, y); | 292 gdk_window_get_origin(text_view_->window, x, y); |
| 287 *y += text_view_->allocation.height; | 293 *y += text_view_->allocation.height; |
| 288 *width = text_view_->allocation.width; | 294 *width = text_view_->allocation.width; |
| 289 } | 295 } |
| 290 | 296 |
| 291 void AutocompleteEditViewGtk::HandleBeginUserAction() { | 297 void AutocompleteEditViewGtk::HandleBeginUserAction() { |
| 292 OnBeforePossibleChange(); | 298 OnBeforePossibleChange(); |
| 293 } | 299 } |
| 294 | 300 |
| 295 void AutocompleteEditViewGtk::HandleEndUserAction() { | 301 void AutocompleteEditViewGtk::HandleEndUserAction() { |
| 296 bool had_newline = false; | 302 // Eat any newline / paragraphs that might have come in, for example in a |
| 303 // copy and paste. We want to make sure our widget stays single line. | |
| 304 for (;;) { | |
| 305 GtkTextIter cur; | |
| 306 gtk_text_buffer_get_start_iter(text_buffer_, &cur); | |
| 297 | 307 |
| 298 // TODO(deanm): obviously super inefficient. | 308 // If there is a line ending, this should put is right before the newline |
|
Evan Martin
2009/03/11 18:25:32
typo: s/is/it/
| |
| 299 for(;;) { | 309 // or carriage return / newline (or Unicode) sequence. If not, we're done. |
| 300 GtkTextIter cur, end; | 310 if (gtk_text_iter_forward_to_line_end(&cur) == FALSE) |
| 301 gtk_text_buffer_get_bounds(text_buffer_, &cur, &end); | 311 break; |
| 302 | 312 |
| 303 while (!gtk_text_iter_equal(&cur, &end)) { | 313 // Stepping to the next cursor position should put us on the other side of |
| 304 if (gtk_text_iter_ends_line(&cur)) { | 314 // the newline / paragraph / etc sequence, and then delete this range. |
| 305 had_newline = true; | 315 GtkTextIter next_line = cur; |
| 306 GtkTextIter next = cur; | 316 gtk_text_iter_forward_cursor_position(&next_line); |
| 307 gtk_text_iter_forward_char(&next); | 317 gtk_text_buffer_delete(text_buffer_, &cur, &next_line); |
| 308 gtk_text_buffer_delete(text_buffer_, &cur, &next); | |
| 309 | 318 |
| 310 // We've invalidated our iterators, gotta start again. | 319 // We've invalidated our iterators, gotta start again. |
| 311 break; | |
| 312 } | |
| 313 | |
| 314 gtk_text_iter_forward_char(&cur); | |
| 315 } | |
| 316 | |
| 317 // We've exhausted the whole input and there is now only 1 line, good. | |
| 318 if (gtk_text_iter_equal(&cur, &end)) | |
| 319 break; | |
| 320 } | 320 } |
| 321 | 321 |
| 322 OnAfterPossibleChange(); | 322 OnAfterPossibleChange(); |
| 323 } | |
| 323 | 324 |
| 324 if (had_newline) | 325 gboolean AutocompleteEditViewGtk::HandleKeyPress(GtkWidget* widget, |
| 325 model_->AcceptInput(CURRENT_TAB, false); | 326 GdkEventKey* event) { |
| 327 // This is very similar to the special casing of the return key in the | |
| 328 // GtkTextView key_press default handler. TODO(deanm): We do however omit | |
| 329 // some IME related code, this might become a problem if an IME wants to | |
| 330 // handle enter. We can get at the im_context and do it ourselves if needed. | |
| 331 if (event->keyval == GDK_Return || | |
| 332 event->keyval == GDK_ISO_Enter || | |
| 333 event->keyval == GDK_KP_Enter) { | |
| 334 bool alt_held = (event->state & GDK_MOD1_MASK); | |
| 335 model_->AcceptInput(alt_held ? NEW_FOREGROUND_TAB : CURRENT_TAB, false); | |
| 336 return TRUE; // Don't propagate into GtkTextView. | |
| 337 } | |
| 338 return FALSE; // Propagate into GtkTextView. | |
| 339 } | |
| 340 | |
| 341 gboolean AutocompleteEditViewGtk::HandleKeyRelease(GtkWidget* widget, | |
| 342 GdkEventKey* event) { | |
| 343 // We ate the press, might as well eat the release. | |
| 344 if (event->keyval == GDK_Return || | |
|
Evan Stade
2009/03/11 20:56:29
perhaps factor this out into a helper function Gdk
| |
| 345 event->keyval == GDK_ISO_Enter || | |
| 346 event->keyval == GDK_KP_Enter) { | |
| 347 return TRUE; // Don't propagate into GtkTextView. | |
| 348 } | |
| 349 return FALSE; // Propagate into GtkTextView. | |
| 326 } | 350 } |
| 327 | 351 |
| 328 // static | 352 // static |
| 329 void AutocompleteEditViewGtk::HandleViewSizeRequest(GtkWidget* view, | 353 void AutocompleteEditViewGtk::HandleViewSizeRequest(GtkWidget* view, |
| 330 GtkRequisition* req, | 354 GtkRequisition* req, |
| 331 gpointer unused) { | 355 gpointer unused) { |
| 332 // Don't force a minimum size, allow our embedder to size us better. | 356 // Don't force a minimum size, allow our embedder to size us better. |
| 333 req->height = req->width = 1; | 357 req->height = req->width = 1; |
| 334 } | 358 } |
| 335 | 359 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 367 gboolean AutocompleteEditViewGtk::HandleViewFocusIn() { | 391 gboolean AutocompleteEditViewGtk::HandleViewFocusIn() { |
| 368 model_->OnSetFocus(false); | 392 model_->OnSetFocus(false); |
| 369 // TODO(deanm): Some keyword hit business, etc here. | 393 // TODO(deanm): Some keyword hit business, etc here. |
| 370 | 394 |
| 371 return FALSE; // Continue propagation. | 395 return FALSE; // Continue propagation. |
| 372 } | 396 } |
| 373 | 397 |
| 374 gboolean AutocompleteEditViewGtk::HandleViewFocusOut() { | 398 gboolean AutocompleteEditViewGtk::HandleViewFocusOut() { |
| 375 // Close the popup. | 399 // Close the popup. |
| 376 ClosePopup(); | 400 ClosePopup(); |
| 377 | |
| 378 // Tell the model to reset itself. | 401 // Tell the model to reset itself. |
| 379 model_->OnKillFocus(); | 402 model_->OnKillFocus(); |
| 380 | |
| 381 // TODO(deanm): This probably isn't right, and doesn't match Windows. We | |
| 382 // don't really want to match Windows though, because it probably feels | |
| 383 // wrong on Linux. Firefox doesn't have great behavior here also, imo. | |
| 384 // Deselect any selection and make sure the input is at the beginning. | |
| 385 GtkTextIter start, end; | |
| 386 gtk_text_buffer_get_bounds(text_buffer_, &start, &end); | |
| 387 gtk_text_buffer_place_cursor(text_buffer_, &start); | |
| 388 return FALSE; // Pass the event on to the GtkTextView. | 403 return FALSE; // Pass the event on to the GtkTextView. |
| 389 } | 404 } |
| 390 | 405 |
| 391 void AutocompleteEditViewGtk::HandleViewMoveCursor( | 406 void AutocompleteEditViewGtk::HandleViewMoveCursor( |
| 392 GtkMovementStep step, | 407 GtkMovementStep step, |
| 393 gint count, | 408 gint count, |
| 394 gboolean extendion_selection) { | 409 gboolean extendion_selection) { |
| 395 // Handle up / down cursor movement on our own. | 410 // Handle up / down cursor movement on our own. |
| 396 if (step == GTK_MOVEMENT_DISPLAY_LINES) { | 411 if (step == GTK_MOVEMENT_DISPLAY_LINES) { |
| 397 model_->OnUpOrDownKeyPressed(count); | 412 model_->OnUpOrDownKeyPressed(count); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 478 &start, &end); | 493 &start, &end); |
| 479 } | 494 } |
| 480 gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL, background); | 495 gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL, background); |
| 481 } | 496 } |
| 482 } | 497 } |
| 483 | 498 |
| 484 void AutocompleteEditViewGtk::TextChanged() { | 499 void AutocompleteEditViewGtk::TextChanged() { |
| 485 EmphasizeURLComponents(); | 500 EmphasizeURLComponents(); |
| 486 controller_->OnChanged(); | 501 controller_->OnChanged(); |
| 487 } | 502 } |
| OLD | NEW |