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

Side by Side Diff: chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc

Issue 165457: Fix regression caused by CL 16142... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 4 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
« no previous file with comments | « chrome/browser/autocomplete/autocomplete_edit_view_gtk.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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> 8 #include <gdk/gdkkeysyms.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 void AutocompleteEditViewGtk::HandleBeginUserAction() { 507 void AutocompleteEditViewGtk::HandleBeginUserAction() {
508 OnBeforePossibleChange(); 508 OnBeforePossibleChange();
509 } 509 }
510 510
511 void AutocompleteEditViewGtk::HandleEndUserAction() { 511 void AutocompleteEditViewGtk::HandleEndUserAction() {
512 OnAfterPossibleChange(); 512 OnAfterPossibleChange();
513 } 513 }
514 514
515 gboolean AutocompleteEditViewGtk::HandleKeyPress(GtkWidget* widget, 515 gboolean AutocompleteEditViewGtk::HandleKeyPress(GtkWidget* widget,
516 GdkEventKey* event) { 516 GdkEventKey* event) {
517 // Background of this piece of complicated code:
518 // The omnibox supports several special behavior which may be triggered by
Daniel Erat 2009/08/13 23:36:38 s/behavior/behaviors/
519 // certain key events:
520 // Tab to search - triggered by Tab key
521 // Accept input - triggered by Enter key
522 // Revert input - triggered by Escape key
523 //
524 // Because we use a GtkTextView object |text_view_| for text input, we need
525 // send all key events to |text_view_| before handling them, to make sure
526 // IME works without any problem. So here, we intercept "key-press-event"
527 // signal of |text_view_| object and call its default handler to handle the
528 // key event first.
529 //
530 // Then if the key event is one of Tab, Enter and Escape, we need trigger
Daniel Erat 2009/08/13 23:36:38 s/need trigger/need to trigger the/
531 // corresponding special behavior if IME did not handle it.
532 // For Escape key if the default signal handler returns FALSE, then we know
533 // it's not handled by IME.
534 //
535 // But for Tab and Enter key, the default signal handler always returns TRUE,
536 // and following operation will be performed by GtkTextView if IME did not
537 // handle it:
538 // Tab key - delete current selection range and insert '\t'
539 // Enter key - delete current selection range and insert '\n'
540 //
541 // We need dinstinguish if IME handled the key event or not, and avoid above
542 // built-in operation if IME did not handle the key event. Because we don't
Daniel Erat 2009/08/13 23:36:38 change to "... and avoid the above built-in operat
543 // want the content of omnibox to be changed before triggering our special
544 // behavior. Otherwise our special behavior would not be performed correctly.
545 //
546 // But there is no way for us to prevent GtkTextView from handling the key
547 // event and performing above built-in operation. So in order to achieve our
548 // goal, "insert-text" signal of |text_buffer_| object is intercepted, and
549 // following actions are done in the signal handler:
550 // - If there is only one character in inserted text, save it in
551 // char_inserted_.
552 // - Filter out all new line and tab characters.
553 //
554 // So if char_inserted_ equals to '\t' after calling |text_view_|'s
Daniel Erat 2009/08/13 23:36:38 s/equals to '\t'/equals '\t'/
555 // default signal handler against a Tab key press event, then we can sure this
Daniel Erat 2009/08/13 23:36:38 switch to "then we know that the Tab key press eve
556 // Tab key press event is handled by GtkTextView instead of IME. Then we can
557 // perform the special behavior of Tab key safely.
558 //
559 // Enter key press event can be treated in the same way.
560 //
561 // Now the last thing is to prevent the content of omnibox from being changed
562 // by GtkTextView when Tab or Enter key is pressed. Because we can't prevent
563 // it, we use backup and restore trick: If Tab or Enter is pressed, backup the
Daniel Erat 2009/08/13 23:36:38 s/we use backup/we use a backup/
564 // content of omnibox before sending the key event to |text_view_|, and then
565 // restore it afterwards if IME did not handle the event.
566
517 GtkWidgetClass* klass = GTK_WIDGET_GET_CLASS(widget); 567 GtkWidgetClass* klass = GTK_WIDGET_GET_CLASS(widget);
568 bool tab_pressed = ((event->keyval == GDK_Tab ||
Daniel Erat 2009/08/13 23:36:38 insert a blank line before this line? it looks st
569 event->keyval == GDK_ISO_Left_Tab ||
570 event->keyval == GDK_KP_Tab) &&
571 !(event->state & GDK_CONTROL_MASK));
572
573 bool enter_pressed = (event->keyval == GDK_Return ||
574 event->keyval == GDK_ISO_Enter ||
575 event->keyval == GDK_KP_Enter);
576
577 gchar* original_text = NULL;
578
579 // Tab and Enter key will have special behavior if it's not handled by IME.
580 // We need save the original content of |text_buffer_| and restore it when
581 // necessary, because GtkTextView might alter the content.
582 if (tab_pressed || enter_pressed) {
583 GtkTextIter start, end;
584 gtk_text_buffer_get_bounds(text_buffer_, &start, &end);
585 original_text = gtk_text_buffer_get_text(text_buffer_, &start, &end, FALSE);
586
587 // Reset these variable, which may be set in "insert-text" signal handler.
Daniel Erat 2009/08/13 23:36:38 change to "Reset |char_inserted_|, which may be se
588 // So that we can know if Tab or Enter key event is handled by IME or not.
589 char_inserted_ = 0;
590 }
518 591
519 // Call the default handler, so that IME can work as normal. 592 // Call the default handler, so that IME can work as normal.
520 // New line and tab characters will be filtered out by our "insert-text" 593 // New line and tab characters will be filtered out by our "insert-text"
521 // signal handler attached to |text_buffer_| object. 594 // signal handler attached to |text_buffer_| object.
522 klass->key_press_event(widget, event); 595 gboolean result = klass->key_press_event(widget, event);
523 596
524 if ((event->keyval == GDK_Tab || event->keyval == GDK_ISO_Left_Tab || 597 bool tab_inserted = (char_inserted_ == '\t');
525 event->keyval == GDK_KP_Tab) && !(event->state & GDK_CONTROL_MASK)) { 598 bool new_line_inserted = (char_inserted_ == '\n' || char_inserted_ == '\r');
599 if ((tab_pressed && tab_inserted) || (enter_pressed && new_line_inserted)) {
600 // Tab or Enter key is handled by GtkTextView, so we are sure that it is not
601 // handled by IME.
602 // Revert the original content in case it has been altered.
603 // Call gtk_text_buffer_{begin|end}_user_action() to make sure |model_| will
604 // be updated correctly.
605 gtk_text_buffer_begin_user_action(text_buffer_);
606 gtk_text_buffer_set_text(text_buffer_, original_text, -1);
607 gtk_text_buffer_end_user_action(text_buffer_);
608 }
609
610 if (original_text)
611 g_free(original_text);
612
613 if (tab_pressed && tab_inserted) {
526 if (model_->is_keyword_hint() && !model_->keyword().empty()) { 614 if (model_->is_keyword_hint() && !model_->keyword().empty()) {
527 model_->AcceptKeyword(); 615 model_->AcceptKeyword();
528 } else { 616 } else {
529 // Handle move focus by ourselves. 617 // Handle move focus by ourselves.
530 static guint signal_id = g_signal_lookup("move-focus", GTK_TYPE_WIDGET); 618 static guint signal_id = g_signal_lookup("move-focus", GTK_TYPE_WIDGET);
531 g_signal_emit(widget, signal_id, 0, (event->state & GDK_SHIFT_MASK) ? 619 g_signal_emit(widget, signal_id, 0, (event->state & GDK_SHIFT_MASK) ?
532 GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD); 620 GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD);
533 } 621 }
534 } else if (event->keyval == GDK_Return || 622 result = TRUE;
535 event->keyval == GDK_ISO_Enter || 623 } else if (enter_pressed && new_line_inserted) {
536 event->keyval == GDK_KP_Enter) {
537 bool alt_held = (event->state & GDK_MOD1_MASK); 624 bool alt_held = (event->state & GDK_MOD1_MASK);
538 model_->AcceptInput(alt_held ? NEW_FOREGROUND_TAB : CURRENT_TAB, false); 625 model_->AcceptInput(alt_held ? NEW_FOREGROUND_TAB : CURRENT_TAB, false);
539 } else if (event->keyval == GDK_Escape && 626 result = TRUE;
627 } else if (!result && event->keyval == GDK_Escape &&
540 (event->state & gtk_accelerator_get_default_mod_mask()) == 0) { 628 (event->state & gtk_accelerator_get_default_mod_mask()) == 0) {
541 model_->OnEscapeKeyPressed(); 629 // We can handle Escape key if |text_view_| did not handle it.
Daniel Erat 2009/08/13 23:36:38 s/can handle Escape/can handle the Escape/
630 // If it's not handled by us, then we need propagate it upto parent
Daniel Erat 2009/08/13 23:36:38 change to "... then we need to propagate it up to
631 // widgets, so that Escape accelerator can still work.
632 result = model_->OnEscapeKeyPressed();
542 } 633 }
543 634
544 // Stop propagating the event to prevent the default handler from being 635 // If the key event is not handled by |text_view_| and us, then we need
Daniel Erat 2009/08/13 23:36:38 s/and us/or us/ s/need/need to/
545 // called again. 636 // propagate the key event up to parent widgets by returning FALSE.
546 return TRUE; 637 // In this case we need stop the signal emission explicitly to prevent the
Daniel Erat 2009/08/13 23:36:38 s/need stop/need to stop/
638 // default "key-press-event" handler of |text_view_| from being called again.
639 if (!result) {
640 static guint signal_id =
641 g_signal_lookup("key-press-event", GTK_TYPE_WIDGET);
642 g_signal_stop_emission(widget, signal_id, 0);
643 }
644
645 return result;
547 } 646 }
548 647
549 gboolean AutocompleteEditViewGtk::HandleKeyRelease(GtkWidget* widget, 648 gboolean AutocompleteEditViewGtk::HandleKeyRelease(GtkWidget* widget,
550 GdkEventKey* event) { 649 GdkEventKey* event) {
551 // Even though we handled the press ourselves, let GtkTextView handle the 650 // Even though we handled the press ourselves, let GtkTextView handle the
552 // release. It shouldn't do anything particularly interesting, but it will 651 // release. It shouldn't do anything particularly interesting, but it will
553 // handle the IME work for us. 652 // handle the IME work for us.
554 return FALSE; // Propagate into GtkTextView. 653 return FALSE; // Propagate into GtkTextView.
555 } 654 }
556 655
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 } 846 }
748 847
749 void AutocompleteEditViewGtk::HandleInsertText( 848 void AutocompleteEditViewGtk::HandleInsertText(
750 GtkTextBuffer* buffer, GtkTextIter* location, const gchar* text, gint len) { 849 GtkTextBuffer* buffer, GtkTextIter* location, const gchar* text, gint len) {
751 std::string filtered_text; 850 std::string filtered_text;
752 filtered_text.reserve(len); 851 filtered_text.reserve(len);
753 852
754 // Filter out new line and tab characters. 853 // Filter out new line and tab characters.
755 // |text| is guaranteed to be a valid UTF-8 string, so it's safe here to 854 // |text| is guaranteed to be a valid UTF-8 string, so it's safe here to
756 // filter byte by byte. 855 // filter byte by byte.
856 //
857 // If there was only a single character, then it might be generated by a key
858 // event. In this case, we save the single character to help our
859 // "key-press-event" signal handler distinguish if a Tab or Enter key event
860 // is handled by IME or not.
861 if (len == 1)
862 char_inserted_ = text[0];
863
757 for (gint i = 0; i < len; ++i) { 864 for (gint i = 0; i < len; ++i) {
758 gchar c = text[i]; 865 gchar c = text[i];
759 if (c == '\n' || c == '\r' || c == '\t') 866 if (c == '\n' || c == '\r' || c == '\t')
760 continue; 867 continue;
761 868
762 filtered_text.push_back(c); 869 filtered_text.push_back(c);
763 } 870 }
764 871
765 if (filtered_text.length()) { 872 if (filtered_text.length()) {
766 // Call the default handler to insert filtered text. 873 // Call the default handler to insert filtered text.
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
928 const std::string& selected_text) { 1035 const std::string& selected_text) {
929 GtkClipboard* clipboard = 1036 GtkClipboard* clipboard =
930 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY); 1037 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY);
931 DCHECK(clipboard); 1038 DCHECK(clipboard);
932 if (!clipboard) 1039 if (!clipboard)
933 return; 1040 return;
934 1041
935 gtk_clipboard_set_text( 1042 gtk_clipboard_set_text(
936 clipboard, selected_text.data(), selected_text.size()); 1043 clipboard, selected_text.data(), selected_text.size());
937 } 1044 }
OLDNEW
« no previous file with comments | « chrome/browser/autocomplete/autocomplete_edit_view_gtk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698