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

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

Issue 172041: Implements unimplemented methods of AutocompleteEditViewGtk.... (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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 popup_positioner)), 93 popup_positioner)),
94 controller_(controller), 94 controller_(controller),
95 toolbar_model_(toolbar_model), 95 toolbar_model_(toolbar_model),
96 command_updater_(command_updater), 96 command_updater_(command_updater),
97 popup_window_mode_(popup_window_mode), 97 popup_window_mode_(popup_window_mode),
98 scheme_security_level_(ToolbarModel::NORMAL), 98 scheme_security_level_(ToolbarModel::NORMAL),
99 selection_saved_(false), 99 selection_saved_(false),
100 mark_set_handler_id_(0), 100 mark_set_handler_id_(0),
101 button_1_pressed_(false), 101 button_1_pressed_(false),
102 text_selected_during_click_(false), 102 text_selected_during_click_(false),
103 text_view_focused_before_button_press_(false) 103 text_view_focused_before_button_press_(false),
104 #if !defined(TOOLKIT_VIEWS) 104 #if !defined(TOOLKIT_VIEWS)
105 , 105 theme_provider_(GtkThemeProvider::GetFrom(profile)),
106 theme_provider_(GtkThemeProvider::GetFrom(profile))
107 #endif 106 #endif
108 { 107 tab_was_pressed_(false) {
109 model_->set_popup_model(popup_view_->GetModel()); 108 model_->set_popup_model(popup_view_->GetModel());
110 } 109 }
111 110
112 AutocompleteEditViewGtk::~AutocompleteEditViewGtk() { 111 AutocompleteEditViewGtk::~AutocompleteEditViewGtk() {
113 NotificationService::current()->Notify( 112 NotificationService::current()->Notify(
114 NotificationType::AUTOCOMPLETE_EDIT_DESTROYED, 113 NotificationType::AUTOCOMPLETE_EDIT_DESTROYED,
115 Source<AutocompleteEditViewGtk>(this), 114 Source<AutocompleteEditViewGtk>(this),
116 NotificationService::NoDetails()); 115 NotificationService::NoDetails());
117 116
118 // Explicitly teardown members which have a reference to us. Just to be safe 117 // Explicitly teardown members which have a reference to us. Just to be safe
(...skipping 27 matching lines...) Expand all
146 145
147 // Until we switch to vector graphics, force the font size. 146 // Until we switch to vector graphics, force the font size.
148 gtk_util::ForceFontSizePixels(text_view_, 147 gtk_util::ForceFontSizePixels(text_view_,
149 popup_window_mode_ ? 148 popup_window_mode_ ?
150 browser_defaults::kAutocompleteEditFontPixelSizeInPopup : 149 browser_defaults::kAutocompleteEditFontPixelSizeInPopup :
151 browser_defaults::kAutocompleteEditFontPixelSize); 150 browser_defaults::kAutocompleteEditFontPixelSize);
152 151
153 // The text view was floating. It will now be owned by the alignment. 152 // The text view was floating. It will now be owned by the alignment.
154 gtk_container_add(GTK_CONTAINER(alignment_.get()), text_view_); 153 gtk_container_add(GTK_CONTAINER(alignment_.get()), text_view_);
155 154
156 // Allows inserting tab characters when pressing tab key, to prevent 155 // Do not allow inserting tab characters when pressing Tab key, so that when
157 // |text_view_| from moving focus. 156 // Tab key is pressed, |text_view_| will emit "move-focus" signal, which will
158 // Tab characters will be filtered out by our "insert-text" signal handler 157 // be intercepted by our own handler to trigger Tab to search feature when
159 // attached to |text_buffer_| object. 158 // necessary.
160 // Tab key events will be handled by our "key-press-event" signal handler for 159 gtk_text_view_set_accepts_tab(GTK_TEXT_VIEW(text_view_), FALSE);
161 // tab to search feature.
162 gtk_text_view_set_accepts_tab(GTK_TEXT_VIEW(text_view_), TRUE);
163 160
164 faded_text_tag_ = gtk_text_buffer_create_tag(text_buffer_, 161 faded_text_tag_ = gtk_text_buffer_create_tag(text_buffer_,
165 NULL, "foreground", kTextBaseColor, NULL); 162 NULL, "foreground", kTextBaseColor, NULL);
166 secure_scheme_tag_ = gtk_text_buffer_create_tag(text_buffer_, 163 secure_scheme_tag_ = gtk_text_buffer_create_tag(text_buffer_,
167 NULL, "foreground", kSecureSchemeColor, NULL); 164 NULL, "foreground", kSecureSchemeColor, NULL);
168 insecure_scheme_tag_ = gtk_text_buffer_create_tag(text_buffer_, 165 insecure_scheme_tag_ = gtk_text_buffer_create_tag(text_buffer_,
169 NULL, "foreground", kInsecureSchemeColor, NULL); 166 NULL, "foreground", kInsecureSchemeColor, NULL);
170 normal_text_tag_ = gtk_text_buffer_create_tag(text_buffer_, 167 normal_text_tag_ = gtk_text_buffer_create_tag(text_buffer_,
171 NULL, "foreground", "#000000", NULL); 168 NULL, "foreground", "#000000", NULL);
172 169
(...skipping 17 matching lines...) Expand all
190 g_signal_connect(text_view_, "button-release-event", 187 g_signal_connect(text_view_, "button-release-event",
191 G_CALLBACK(&HandleViewButtonReleaseThunk), this); 188 G_CALLBACK(&HandleViewButtonReleaseThunk), this);
192 g_signal_connect(text_view_, "focus-in-event", 189 g_signal_connect(text_view_, "focus-in-event",
193 G_CALLBACK(&HandleViewFocusInThunk), this); 190 G_CALLBACK(&HandleViewFocusInThunk), this);
194 g_signal_connect(text_view_, "focus-out-event", 191 g_signal_connect(text_view_, "focus-out-event",
195 G_CALLBACK(&HandleViewFocusOutThunk), this); 192 G_CALLBACK(&HandleViewFocusOutThunk), this);
196 // NOTE: The GtkTextView documentation asks you not to connect to this 193 // NOTE: The GtkTextView documentation asks you not to connect to this
197 // signal, but it is very convenient and clean for catching up/down. 194 // signal, but it is very convenient and clean for catching up/down.
198 g_signal_connect(text_view_, "move-cursor", 195 g_signal_connect(text_view_, "move-cursor",
199 G_CALLBACK(&HandleViewMoveCursorThunk), this); 196 G_CALLBACK(&HandleViewMoveCursorThunk), this);
197 g_signal_connect(text_view_, "move-focus",
198 G_CALLBACK(&HandleViewMoveFocusThunk), this);
200 // Override the size request. We want to keep the original height request 199 // Override the size request. We want to keep the original height request
201 // from the widget, since that's font dependent. We want to ignore the width 200 // from the widget, since that's font dependent. We want to ignore the width
202 // so we don't force a minimum width based on the text length. 201 // so we don't force a minimum width based on the text length.
203 g_signal_connect(text_view_, "size-request", 202 g_signal_connect(text_view_, "size-request",
204 G_CALLBACK(&HandleViewSizeRequestThunk), this); 203 G_CALLBACK(&HandleViewSizeRequestThunk), this);
205 g_signal_connect(text_view_, "populate-popup", 204 g_signal_connect(text_view_, "populate-popup",
206 G_CALLBACK(&HandlePopulatePopupThunk), this); 205 G_CALLBACK(&HandlePopulatePopupThunk), this);
207 mark_set_handler_id_ = g_signal_connect( 206 mark_set_handler_id_ = g_signal_connect(
208 text_buffer_, "mark-set", G_CALLBACK(&HandleMarkSetThunk), this); 207 text_buffer_, "mark-set", G_CALLBACK(&HandleMarkSetThunk), this);
209 g_signal_connect(text_view_, "drag-data-received", 208 g_signal_connect(text_view_, "drag-data-received",
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 model_->SetUserText(text); 323 model_->SetUserText(text);
325 // TODO(deanm): something about selection / focus change here. 324 // TODO(deanm): something about selection / focus change here.
326 SetWindowTextAndCaretPos(display_text, display_text.length()); 325 SetWindowTextAndCaretPos(display_text, display_text.length());
327 if (update_popup) 326 if (update_popup)
328 UpdatePopup(); 327 UpdatePopup();
329 TextChanged(); 328 TextChanged();
330 } 329 }
331 330
332 void AutocompleteEditViewGtk::SetWindowTextAndCaretPos(const std::wstring& text, 331 void AutocompleteEditViewGtk::SetWindowTextAndCaretPos(const std::wstring& text,
333 size_t caret_pos) { 332 size_t caret_pos) {
333 CharRange range(static_cast<int>(caret_pos), static_cast<int>(caret_pos));
334 SetTextAndSelectedRange(text, range);
335 }
336
337 void AutocompleteEditViewGtk::SetTextAndSelectedRange(const std::wstring& text,
338 const CharRange& range) {
334 std::string utf8 = WideToUTF8(text); 339 std::string utf8 = WideToUTF8(text);
335 gtk_text_buffer_set_text(text_buffer_, utf8.data(), utf8.length()); 340 gtk_text_buffer_set_text(text_buffer_, utf8.data(), utf8.length());
336 EmphasizeURLComponents();
337 341
338 GtkTextIter cur_pos; 342 GtkTextIter insert, bound;
339 gtk_text_buffer_get_iter_at_offset(text_buffer_, &cur_pos, caret_pos); 343 ItersFromCharRange(range, &insert, &bound);
340 gtk_text_buffer_place_cursor(text_buffer_, &cur_pos); 344 gtk_text_buffer_select_range(text_buffer_, &insert, &bound);
341 } 345 }
342 346
343 void AutocompleteEditViewGtk::SetForcedQuery() { 347 void AutocompleteEditViewGtk::SetForcedQuery() {
344 const std::wstring current_text(GetText()); 348 const std::wstring current_text(GetText());
345 if (current_text.empty() || (current_text[0] != '?')) { 349 if (current_text.empty() || (current_text[0] != '?')) {
346 SetUserText(L"?"); 350 SetUserText(L"?");
347 } else { 351 } else {
348 GtkTextIter start, end; 352 GtkTextIter start, end;
349 gtk_text_buffer_get_bounds(text_buffer_, &start, &end); 353 gtk_text_buffer_get_bounds(text_buffer_, &start, &end);
350 gtk_text_buffer_get_iter_at_offset(text_buffer_, &start, 1); 354 gtk_text_buffer_get_iter_at_offset(text_buffer_, &start, 1);
351 StartUpdatingHighlightedText(); 355 StartUpdatingHighlightedText();
352 gtk_text_buffer_select_range(text_buffer_, &start, &end); 356 gtk_text_buffer_select_range(text_buffer_, &start, &end);
353 FinishUpdatingHighlightedText(); 357 FinishUpdatingHighlightedText();
354 } 358 }
355 } 359 }
356 360
357 bool AutocompleteEditViewGtk::IsSelectAll() { 361 bool AutocompleteEditViewGtk::IsSelectAll() {
358 NOTIMPLEMENTED(); 362 GtkTextIter sel_start, sel_end;
359 return false; 363 if (!gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end))
364 return false;
365
366 GtkTextIter start, end;
367 gtk_text_buffer_get_bounds(text_buffer_, &start, &end);
368
369 return gtk_text_iter_equal(&start, &sel_start) &&
370 gtk_text_iter_equal(&end, &sel_end);
360 } 371 }
361 372
362 void AutocompleteEditViewGtk::SelectAll(bool reversed) { 373 void AutocompleteEditViewGtk::SelectAll(bool reversed) {
363 // SelectAll() is invoked as a side effect of other actions (e.g. switching 374 // SelectAll() is invoked as a side effect of other actions (e.g. switching
364 // tabs or hitting Escape) in autocomplete_edit.cc, so we don't update the 375 // tabs or hitting Escape) in autocomplete_edit.cc, so we don't update the
365 // PRIMARY selection here. 376 // PRIMARY selection here.
366 // TODO(derat): But this is also called by LocationBarView::FocusLocation() -- 377 // TODO(derat): But this is also called by LocationBarView::FocusLocation() --
367 // should the X selection be updated when the user hits Ctrl-L? 378 // should the X selection be updated when the user hits Ctrl-L?
368 SelectAllInternal(reversed, false); 379 SelectAllInternal(reversed, false);
369 } 380 }
(...skipping 15 matching lines...) Expand all
385 model_->StartAutocomplete(sel.cp_max < GetTextLength()); 396 model_->StartAutocomplete(sel.cp_max < GetTextLength());
386 } 397 }
387 398
388 void AutocompleteEditViewGtk::ClosePopup() { 399 void AutocompleteEditViewGtk::ClosePopup() {
389 popup_view_->GetModel()->StopAutocomplete(); 400 popup_view_->GetModel()->StopAutocomplete();
390 } 401 }
391 402
392 void AutocompleteEditViewGtk::OnTemporaryTextMaybeChanged( 403 void AutocompleteEditViewGtk::OnTemporaryTextMaybeChanged(
393 const std::wstring& display_text, 404 const std::wstring& display_text,
394 bool save_original_selection) { 405 bool save_original_selection) {
395 // TODO(deanm): Ignoring save_original_selection here, etc. 406 if (save_original_selection) {
407 saved_temporary_selection_ = GetSelection();
408 saved_temporary_text_ = GetText();
409 }
410
411 StartUpdatingHighlightedText();
396 SetWindowTextAndCaretPos(display_text, display_text.length()); 412 SetWindowTextAndCaretPos(display_text, display_text.length());
413 FinishUpdatingHighlightedText();
397 TextChanged(); 414 TextChanged();
398 } 415 }
399 416
400 bool AutocompleteEditViewGtk::OnInlineAutocompleteTextMaybeChanged( 417 bool AutocompleteEditViewGtk::OnInlineAutocompleteTextMaybeChanged(
401 const std::wstring& display_text, 418 const std::wstring& display_text,
402 size_t user_text_length) { 419 size_t user_text_length) {
403 if (display_text == GetText()) 420 if (display_text == GetText())
404 return false; 421 return false;
405 422
406 StartUpdatingHighlightedText(); 423 StartUpdatingHighlightedText();
407 SetWindowTextAndCaretPos(display_text, 0); 424 SetWindowTextAndCaretPos(display_text, 0);
408 425
409 // Select the part of the text that was inline autocompleted. 426 // Select the part of the text that was inline autocompleted.
410 GtkTextIter bound, insert; 427 GtkTextIter bound, insert;
411 gtk_text_buffer_get_bounds(text_buffer_, &insert, &bound); 428 gtk_text_buffer_get_bounds(text_buffer_, &insert, &bound);
412 gtk_text_buffer_get_iter_at_offset(text_buffer_, &insert, user_text_length); 429 gtk_text_buffer_get_iter_at_offset(text_buffer_, &insert, user_text_length);
413 gtk_text_buffer_select_range(text_buffer_, &insert, &bound); 430 gtk_text_buffer_select_range(text_buffer_, &insert, &bound);
414 431
415 FinishUpdatingHighlightedText(); 432 FinishUpdatingHighlightedText();
416 TextChanged(); 433 TextChanged();
417 return true; 434 return true;
418 } 435 }
419 436
420 void AutocompleteEditViewGtk::OnRevertTemporaryText() { 437 void AutocompleteEditViewGtk::OnRevertTemporaryText() {
421 NOTIMPLEMENTED(); 438 StartUpdatingHighlightedText();
439 SetTextAndSelectedRange(saved_temporary_text_, saved_temporary_selection_);
440 FinishUpdatingHighlightedText();
441 saved_temporary_text_.clear();
442 TextChanged();
422 } 443 }
423 444
424 void AutocompleteEditViewGtk::OnBeforePossibleChange() { 445 void AutocompleteEditViewGtk::OnBeforePossibleChange() {
425 // Record our state. 446 // Record our state.
426 text_before_change_ = GetText(); 447 text_before_change_ = GetText();
427 sel_before_change_ = GetSelection(); 448 sel_before_change_ = GetSelection();
428 } 449 }
429 450
430 // TODO(deanm): This is mostly stolen from Windows, and will need some work. 451 // TODO(deanm): This is mostly stolen from Windows, and will need some work.
431 bool AutocompleteEditViewGtk::OnAfterPossibleChange() { 452 bool AutocompleteEditViewGtk::OnAfterPossibleChange() {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 OnBeforePossibleChange(); 534 OnBeforePossibleChange();
514 } 535 }
515 536
516 void AutocompleteEditViewGtk::HandleEndUserAction() { 537 void AutocompleteEditViewGtk::HandleEndUserAction() {
517 OnAfterPossibleChange(); 538 OnAfterPossibleChange();
518 } 539 }
519 540
520 gboolean AutocompleteEditViewGtk::HandleKeyPress(GtkWidget* widget, 541 gboolean AutocompleteEditViewGtk::HandleKeyPress(GtkWidget* widget,
521 GdkEventKey* event) { 542 GdkEventKey* event) {
522 // Background of this piece of complicated code: 543 // Background of this piece of complicated code:
523 // The omnibox supports several special behavior which may be triggered by 544 // The omnibox supports several special behaviors which may be triggered by
524 // certain key events: 545 // certain key events:
525 // Tab to search - triggered by Tab key 546 // Tab to search - triggered by Tab key
526 // Accept input - triggered by Enter key 547 // Accept input - triggered by Enter key
527 // Revert input - triggered by Escape key 548 // Revert input - triggered by Escape key
528 // 549 //
529 // Because we use a GtkTextView object |text_view_| for text input, we need 550 // Because we use a GtkTextView object |text_view_| for text input, we need
530 // send all key events to |text_view_| before handling them, to make sure 551 // send all key events to |text_view_| before handling them, to make sure
531 // IME works without any problem. So here, we intercept "key-press-event" 552 // IME works without any problem. So here, we intercept "key-press-event"
532 // signal of |text_view_| object and call its default handler to handle the 553 // signal of |text_view_| object and call its default handler to handle the
533 // key event first. 554 // key event first.
534 // 555 //
535 // Then if the key event is one of Tab, Enter and Escape, we need trigger 556 // Then if the key event is one of Tab, Enter and Escape, we need to trigger
536 // corresponding special behavior if IME did not handle it. 557 // the corresponding special behavior if IME did not handle it.
537 // For Escape key if the default signal handler returns FALSE, then we know 558 // For Escape key, if the default signal handler returns FALSE, then we know
538 // it's not handled by IME. 559 // it's not handled by IME.
539 // 560 //
540 // But for Tab and Enter key, the default signal handler always returns TRUE, 561 // For Tab key, as "accepts-tab" property of |text_view_| is set to FALSE,
541 // and following operation will be performed by GtkTextView if IME did not 562 // if IME did not handle it then "move-focus" signal will be emitted by the
542 // handle it: 563 // default signal handler of |text_view_|. So we can intercept "move-focus"
543 // Tab key - delete current selection range and insert '\t' 564 // signal of |text_view_| to know if a Tab key press event was handled by IME,
544 // Enter key - delete current selection range and insert '\n' 565 // and trigger Tab to search behavior when necessary in the signal handler.
545 // 566 //
546 // We need dinstinguish if IME handled the key event or not, and avoid above 567 // But for Enter key, if IME did not handle the key event, the default signal
547 // built-in operation if IME did not handle the key event. Because we don't 568 // handler will delete current selection range and insert '\n' and always
548 // want the content of omnibox to be changed before triggering our special 569 // return TRUE. We need to prevent |text_view_| from performing this default
549 // behavior. Otherwise our special behavior would not be performed correctly. 570 // action if IME did not handle the key event, because we don't want the
571 // content of omnibox to be changed before triggering our special behavior.
572 // Otherwise our special behavior would not be performed correctly.
550 // 573 //
551 // But there is no way for us to prevent GtkTextView from handling the key 574 // But there is no way for us to prevent GtkTextView from handling the key
552 // event and performing above built-in operation. So in order to achieve our 575 // event and performing built-in operation. So in order to achieve our goal,
553 // goal, "insert-text" signal of |text_buffer_| object is intercepted, and 576 // "insert-text" signal of |text_buffer_| object is intercepted, and
554 // following actions are done in the signal handler: 577 // following actions are done in the signal handler:
555 // - If there is only one character in inserted text, save it in 578 // - If there is only one character in inserted text, save it in
556 // char_inserted_. 579 // char_inserted_.
557 // - Filter out all new line and tab characters. 580 // - Filter out all new line and tab characters.
558 // 581 //
559 // So if char_inserted_ equals to '\t' after calling |text_view_|'s 582 // So if |char_inserted_| equals '\n' after calling |text_view_|'s
560 // default signal handler against a Tab key press event, then we can sure this 583 // default signal handler against an Enter key press event, then we know that
561 // Tab key press event is handled by GtkTextView instead of IME. Then we can 584 // the Enter key press event was handled by GtkTextView rather than IME, and
562 // perform the special behavior of Tab key safely. 585 // can perform the special behavior for Enter key safely.
563 //
564 // Enter key press event can be treated in the same way.
565 // 586 //
566 // Now the last thing is to prevent the content of omnibox from being changed 587 // Now the last thing is to prevent the content of omnibox from being changed
567 // by GtkTextView when Tab or Enter key is pressed. Because we can't prevent 588 // by GtkTextView when Tab or Enter key is pressed. Because we can't prevent
568 // it, we use backup and restore trick: If Tab or Enter is pressed, backup the 589 // it, we use a backup and restore trick: If Enter is pressed, backup the
569 // content of omnibox before sending the key event to |text_view_|, and then 590 // content of omnibox before sending the key event to |text_view_|, and
570 // restore it afterwards if IME did not handle the event. 591 // then restore it afterwards if IME did not handle the event.
571 592
572 GtkWidgetClass* klass = GTK_WIDGET_GET_CLASS(widget); 593 GtkWidgetClass* klass = GTK_WIDGET_GET_CLASS(widget);
573 bool tab_pressed = ((event->keyval == GDK_Tab ||
574 event->keyval == GDK_ISO_Left_Tab ||
575 event->keyval == GDK_KP_Tab) &&
576 !(event->state & GDK_CONTROL_MASK));
577 594
578 bool enter_pressed = (event->keyval == GDK_Return || 595 bool enter_pressed = (event->keyval == GDK_Return ||
579 event->keyval == GDK_ISO_Enter || 596 event->keyval == GDK_ISO_Enter ||
580 event->keyval == GDK_KP_Enter); 597 event->keyval == GDK_KP_Enter);
581 598
582 gchar* original_text = NULL; 599 std::wstring original_text;
583 600
584 // Tab and Enter key will have special behavior if it's not handled by IME. 601 // Enter key will have special behavior if it's not handled by IME.
585 // We need save the original content of |text_buffer_| and restore it when 602 // We need save the original content of |text_buffer_| and restore it when
586 // necessary, because GtkTextView might alter the content. 603 // necessary, because GtkTextView might alter the content.
587 if (tab_pressed || enter_pressed) { 604 if (enter_pressed) {
588 GtkTextIter start, end; 605 original_text = GetText();
589 gtk_text_buffer_get_bounds(text_buffer_, &start, &end); 606 // Reset |char_inserted_|, which may be set in the "insert-text" signal
590 original_text = gtk_text_buffer_get_text(text_buffer_, &start, &end, FALSE); 607 // handler, so that we'll know if an Enter key event was handled by IME.
591
592 // Reset these variable, which may be set in "insert-text" signal handler.
593 // So that we can know if Tab or Enter key event is handled by IME or not.
594 char_inserted_ = 0; 608 char_inserted_ = 0;
595 } 609 }
596 610
611 // Set |tab_was_pressed_| to true if it's a Tab key press event, so that our
612 // handler of "move-focus" signal can trigger Tab to search behavior when
613 // necessary.
614 tab_was_pressed_ = ((event->keyval == GDK_Tab ||
615 event->keyval == GDK_ISO_Left_Tab ||
616 event->keyval == GDK_KP_Tab) &&
617 !(event->state & GDK_CONTROL_MASK));
618
597 // Call the default handler, so that IME can work as normal. 619 // Call the default handler, so that IME can work as normal.
598 // New line and tab characters will be filtered out by our "insert-text" 620 // New line characters will be filtered out by our "insert-text"
599 // signal handler attached to |text_buffer_| object. 621 // signal handler attached to |text_buffer_| object.
600 gboolean result = klass->key_press_event(widget, event); 622 gboolean result = klass->key_press_event(widget, event);
601 623
602 bool tab_inserted = (char_inserted_ == '\t'); 624 // Set |tab_was_pressed_| to false, to make sure Tab to search behavior can
603 bool new_line_inserted = (char_inserted_ == '\n' || char_inserted_ == '\r'); 625 // only be triggered by pressing Tab key.
604 if ((tab_pressed && tab_inserted) || (enter_pressed && new_line_inserted)) { 626 tab_was_pressed_ = false;
605 // Tab or Enter key is handled by GtkTextView, so we are sure that it is not
606 // handled by IME.
607 // Revert the original content in case it has been altered.
608 // Call gtk_text_buffer_{begin|end}_user_action() to make sure |model_| will
609 // be updated correctly.
610 gtk_text_buffer_begin_user_action(text_buffer_);
611 gtk_text_buffer_set_text(text_buffer_, original_text, -1);
612 gtk_text_buffer_end_user_action(text_buffer_);
613 }
614 627
615 if (original_text) 628 if (enter_pressed && (char_inserted_ == '\n' || char_inserted_ == '\r')) {
616 g_free(original_text);
617
618 if (tab_pressed && tab_inserted) {
619 if (model_->is_keyword_hint() && !model_->keyword().empty()) {
620 model_->AcceptKeyword();
621 } else {
622 // Handle move focus by ourselves.
623 static guint signal_id = g_signal_lookup("move-focus", GTK_TYPE_WIDGET);
624 g_signal_emit(widget, signal_id, 0, (event->state & GDK_SHIFT_MASK) ?
625 GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD);
626 }
627 result = TRUE;
628 } else if (enter_pressed && new_line_inserted) {
629 bool alt_held = (event->state & GDK_MOD1_MASK); 629 bool alt_held = (event->state & GDK_MOD1_MASK);
630 // Revert the original text in case the text has been changed.
631 SetUserText(original_text);
630 model_->AcceptInput(alt_held ? NEW_FOREGROUND_TAB : CURRENT_TAB, false); 632 model_->AcceptInput(alt_held ? NEW_FOREGROUND_TAB : CURRENT_TAB, false);
631 result = TRUE; 633 result = TRUE;
632 } else if (!result && event->keyval == GDK_Escape && 634 } else if (!result && event->keyval == GDK_Escape &&
633 (event->state & gtk_accelerator_get_default_mod_mask()) == 0) { 635 (event->state & gtk_accelerator_get_default_mod_mask()) == 0) {
634 // We can handle Escape key if |text_view_| did not handle it. 636 // We can handle the Escape key if |text_view_| did not handle it.
635 // If it's not handled by us, then we need propagate it upto parent 637 // If it's not handled by us, then we need to propagate it up to the parent
636 // widgets, so that Escape accelerator can still work. 638 // widgets, so that Escape accelerator can still work.
637 result = model_->OnEscapeKeyPressed(); 639 result = model_->OnEscapeKeyPressed();
640 } else if (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R) {
641 // Omnibox2 can switch its contents while pressing a control key. To switch
642 // the contents of omnibox2, we notify the AutocompleteEditModel class when
643 // the control-key state is changed.
644 model_->OnControlKeyChanged(true);
638 } 645 }
639 646
640 // If the key event is not handled by |text_view_| and us, then we need 647 // If the key event is not handled by |text_view_| or us, then we need to
641 // propagate the key event up to parent widgets by returning FALSE. 648 // propagate the key event up to parent widgets by returning FALSE.
642 // In this case we need stop the signal emission explicitly to prevent the 649 // In this case we need to stop the signal emission explicitly to prevent the
643 // default "key-press-event" handler of |text_view_| from being called again. 650 // default "key-press-event" handler of |text_view_| from being called again.
644 if (!result) { 651 if (!result) {
645 static guint signal_id = 652 static guint signal_id =
646 g_signal_lookup("key-press-event", GTK_TYPE_WIDGET); 653 g_signal_lookup("key-press-event", GTK_TYPE_WIDGET);
647 g_signal_stop_emission(widget, signal_id, 0); 654 g_signal_stop_emission(widget, signal_id, 0);
648 } 655 }
649 656
650 return result; 657 return result;
651 } 658 }
652 659
653 gboolean AutocompleteEditViewGtk::HandleKeyRelease(GtkWidget* widget, 660 gboolean AutocompleteEditViewGtk::HandleKeyRelease(GtkWidget* widget,
654 GdkEventKey* event) { 661 GdkEventKey* event) {
662 if (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R) {
663 // Omnibox2 can switch its contents while pressing a control key. To switch
664 // the contents of omnibox2, we notify the AutocompleteEditModel class when
665 // the control-key state is changed.
666 model_->OnControlKeyChanged(false);
Dean McNamee 2009/08/21 18:21:35 I am still not happy with this code, but I will le
667 }
668
655 // Even though we handled the press ourselves, let GtkTextView handle the 669 // Even though we handled the press ourselves, let GtkTextView handle the
656 // release. It shouldn't do anything particularly interesting, but it will 670 // release. It shouldn't do anything particularly interesting, but it will
657 // handle the IME work for us. 671 // handle the IME work for us.
658 return FALSE; // Propagate into GtkTextView. 672 return FALSE; // Propagate into GtkTextView.
659 } 673 }
660 674
661 gboolean AutocompleteEditViewGtk::HandleViewButtonPress(GdkEventButton* event) { 675 gboolean AutocompleteEditViewGtk::HandleViewButtonPress(GdkEventButton* event) {
662 if (event->button == 1) { 676 if (event->button == 1) {
663 // When the first button is pressed, track some stuff that will help us 677 // When the first button is pressed, track some stuff that will help us
664 // determine whether we should select all of the text when the button is 678 // determine whether we should select all of the text when the button is
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
865 GtkTextBuffer* buffer, GtkTextIter* location, const gchar* text, gint len) { 879 GtkTextBuffer* buffer, GtkTextIter* location, const gchar* text, gint len) {
866 std::string filtered_text; 880 std::string filtered_text;
867 filtered_text.reserve(len); 881 filtered_text.reserve(len);
868 882
869 // Filter out new line and tab characters. 883 // Filter out new line and tab characters.
870 // |text| is guaranteed to be a valid UTF-8 string, so it's safe here to 884 // |text| is guaranteed to be a valid UTF-8 string, so it's safe here to
871 // filter byte by byte. 885 // filter byte by byte.
872 // 886 //
873 // If there was only a single character, then it might be generated by a key 887 // If there was only a single character, then it might be generated by a key
874 // event. In this case, we save the single character to help our 888 // event. In this case, we save the single character to help our
875 // "key-press-event" signal handler distinguish if a Tab or Enter key event 889 // "key-press-event" signal handler distinguish if an Enter key event is
876 // is handled by IME or not. 890 // handled by IME or not.
877 if (len == 1) 891 if (len == 1)
878 char_inserted_ = text[0]; 892 char_inserted_ = text[0];
879 893
880 for (gint i = 0; i < len; ++i) { 894 for (gint i = 0; i < len; ++i) {
881 gchar c = text[i]; 895 gchar c = text[i];
882 if (c == '\n' || c == '\r' || c == '\t') 896 if (c == '\n' || c == '\r' || c == '\t')
883 continue; 897 continue;
884 898
885 filtered_text.push_back(c); 899 filtered_text.push_back(c);
886 } 900 }
(...skipping 29 matching lines...) Expand all
916 930
917 // We're showing a keyword and the user pressed backspace at the beginning 931 // We're showing a keyword and the user pressed backspace at the beginning
918 // of the text. Delete the selected keyword. 932 // of the text. Delete the selected keyword.
919 model_->ClearKeyword(GetText()); 933 model_->ClearKeyword(GetText());
920 934
921 // Stop propagating the signal emission into GtkTextView. 935 // Stop propagating the signal emission into GtkTextView.
922 static guint signal_id = g_signal_lookup("backspace", GTK_TYPE_TEXT_VIEW); 936 static guint signal_id = g_signal_lookup("backspace", GTK_TYPE_TEXT_VIEW);
923 g_signal_stop_emission(text_view_, signal_id, 0); 937 g_signal_stop_emission(text_view_, signal_id, 0);
924 } 938 }
925 939
940 void AutocompleteEditViewGtk::HandleViewMoveFocus(GtkWidget* widget) {
941 // Trigger Tab to search behavior only when Tab key is pressed.
942 if (tab_was_pressed_ && model_->is_keyword_hint() &&
943 !model_->keyword().empty()) {
944 model_->AcceptKeyword();
945
946 // If Tab to search behavior is triggered, then stop the signal emission to
947 // prevent the focus from being moved.
948 static guint signal_id = g_signal_lookup("move-focus", GTK_TYPE_WIDGET);
949 g_signal_stop_emission(widget, signal_id, 0);
950 }
951
952 // Propagate the signal so that focus can be moved as normal.
953 }
954
926 void AutocompleteEditViewGtk::HandleCopyClipboard() { 955 void AutocompleteEditViewGtk::HandleCopyClipboard() {
927 // On copy, we manually update the PRIMARY selection to contain the 956 // On copy, we manually update the PRIMARY selection to contain the
928 // highlighted text. This matches Firefox -- we highlight the URL but don't 957 // highlighted text. This matches Firefox -- we highlight the URL but don't
929 // update PRIMARY on Ctrl-L, so Ctrl-L, Ctrl-C and then middle-click is a 958 // update PRIMARY on Ctrl-L, so Ctrl-L, Ctrl-C and then middle-click is a
930 // convenient way to paste the current URL somewhere. 959 // convenient way to paste the current URL somewhere.
931 if (!gtk_text_buffer_get_has_selection(text_buffer_)) 960 if (!gtk_text_buffer_get_has_selection(text_buffer_))
932 return; 961 return;
933 962
934 GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); 963 GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
935 DCHECK(clipboard); 964 DCHECK(clipboard);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1076 const std::string& selected_text) { 1105 const std::string& selected_text) {
1077 GtkClipboard* clipboard = 1106 GtkClipboard* clipboard =
1078 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY); 1107 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY);
1079 DCHECK(clipboard); 1108 DCHECK(clipboard);
1080 if (!clipboard) 1109 if (!clipboard)
1081 return; 1110 return;
1082 1111
1083 gtk_clipboard_set_text( 1112 gtk_clipboard_set_text(
1084 clipboard, selected_text.data(), selected_text.size()); 1113 clipboard, selected_text.data(), selected_text.size());
1085 } 1114 }
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