autocomplete_edit_view_gtk.h revision 513209b27ff55e2841eac0e4120199c23acce758
1// Copyright (c) 2010 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#ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_EDIT_VIEW_GTK_H_ 6#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_EDIT_VIEW_GTK_H_ 7#pragma once 8 9#include <gtk/gtk.h> 10 11#include <algorithm> 12#include <string> 13 14#include "app/gtk_signal.h" 15#include "app/gtk_signal_registrar.h" 16#include "base/basictypes.h" 17#include "base/scoped_ptr.h" 18#include "base/string_util.h" 19#include "chrome/browser/autocomplete/autocomplete_edit_view.h" 20#include "chrome/browser/gtk/owned_widget_gtk.h" 21#include "chrome/browser/toolbar_model.h" 22#include "chrome/common/notification_observer.h" 23#include "chrome/common/notification_registrar.h" 24#include "chrome/common/page_transition_types.h" 25#include "gfx/rect.h" 26#include "webkit/glue/window_open_disposition.h" 27 28class AutocompleteEditController; 29class AutocompleteEditModel; 30class AutocompletePopupView; 31class Profile; 32class TabContents; 33 34namespace gfx{ 35class Font; 36} 37 38namespace views { 39class View; 40} 41 42#if !defined(TOOLKIT_VIEWS) 43class GtkThemeProvider; 44#endif 45 46class AutocompleteEditViewGtk : public AutocompleteEditView, 47 public NotificationObserver { 48 public: 49 // Modeled like the Windows CHARRANGE. Represent a pair of cursor position 50 // offsets. Since GtkTextIters are invalid after the buffer is changed, we 51 // work in character offsets (not bytes). 52 struct CharRange { 53 CharRange() : cp_min(0), cp_max(0) { } 54 CharRange(int n, int x) : cp_min(n), cp_max(x) { } 55 56 // Returns the start of the selection. 57 int selection_min() const { return std::min(cp_min, cp_max); } 58 59 // Work in integers to match the gint GTK APIs. 60 int cp_min; // For a selection: Represents the start. 61 int cp_max; // For a selection: Represents the end (insert position). 62 }; 63 64 AutocompleteEditViewGtk(AutocompleteEditController* controller, 65 ToolbarModel* toolbar_model, 66 Profile* profile, 67 CommandUpdater* command_updater, 68 bool popup_window_mode, 69#if defined(TOOLKIT_VIEWS) 70 const views::View* location_bar); 71#else 72 GtkWidget* location_bar); 73#endif 74 ~AutocompleteEditViewGtk(); 75 76 // Initialize, create the underlying widgets, etc. 77 void Init(); 78 79 // Returns the width in pixels needed to display the current text. The 80 // returned value includes margins. 81 int TextWidth(); 82 83 // Returns the width in pixels needed to display the text from one character 84 // before the caret to the end of the string. See comments in 85 // LocationBarView::Layout as to why this uses -1. 86 int WidthOfTextAfterCursor(); 87 88 // Returns the font. 89 gfx::Font GetFont(); 90 91 // Implement the AutocompleteEditView interface. 92 virtual AutocompleteEditModel* model() { return model_.get(); } 93 virtual const AutocompleteEditModel* model() const { return model_.get(); } 94 95 virtual void SaveStateToTab(TabContents* tab); 96 97 virtual void Update(const TabContents* tab_for_state_restoring); 98 99 virtual void OpenURL(const GURL& url, 100 WindowOpenDisposition disposition, 101 PageTransition::Type transition, 102 const GURL& alternate_nav_url, 103 size_t selected_line, 104 const std::wstring& keyword); 105 106 virtual std::wstring GetText() const; 107 108 virtual bool IsEditingOrEmpty() const; 109 virtual int GetIcon() const; 110 111 virtual void SetUserText(const std::wstring& text); 112 virtual void SetUserText(const std::wstring& text, 113 const std::wstring& display_text, 114 bool update_popup); 115 116 virtual void SetWindowTextAndCaretPos(const std::wstring& text, 117 size_t caret_pos); 118 119 virtual void SetForcedQuery(); 120 121 virtual bool IsSelectAll(); 122 virtual void GetSelectionBounds(std::wstring::size_type* start, 123 std::wstring::size_type* end); 124 virtual void SelectAll(bool reversed); 125 virtual void RevertAll(); 126 127 virtual void UpdatePopup(); 128 virtual void ClosePopup(); 129 130 virtual void SetFocus(); 131 132 virtual void OnTemporaryTextMaybeChanged(const std::wstring& display_text, 133 bool save_original_selection); 134 virtual bool OnInlineAutocompleteTextMaybeChanged( 135 const std::wstring& display_text, size_t user_text_length); 136 virtual void OnRevertTemporaryText(); 137 virtual void OnBeforePossibleChange(); 138 virtual bool OnAfterPossibleChange(); 139 virtual gfx::NativeView GetNativeView() const; 140 virtual CommandUpdater* GetCommandUpdater(); 141 142 // Overridden from NotificationObserver: 143 virtual void Observe(NotificationType type, 144 const NotificationSource& source, 145 const NotificationDetails& details); 146 147 void SetBaseColor(); 148 149 void SetInstantSuggestion(const std::string& suggestion); 150 bool CommitInstantSuggestion(); 151 152 // Used by LocationBarViewGtk to inform AutocompleteEditViewGtk if the tab to 153 // search should be enabled or not. See the comment of |enable_tab_to_search_| 154 // for details. 155 void set_enable_tab_to_search(bool enable) { 156 enable_tab_to_search_ = enable; 157 } 158 159 GtkWidget* text_view() { 160 return text_view_; 161 } 162 163 private: 164 CHROMEG_CALLBACK_0(AutocompleteEditViewGtk, void, HandleBeginUserAction, 165 GtkTextBuffer*); 166 CHROMEG_CALLBACK_0(AutocompleteEditViewGtk, void, HandleEndUserAction, 167 GtkTextBuffer*); 168 CHROMEG_CALLBACK_2(AutocompleteEditViewGtk, void, HandleMarkSet, 169 GtkTextBuffer*, GtkTextIter*, GtkTextMark*); 170 // As above, but called after the default handler. 171 CHROMEG_CALLBACK_2(AutocompleteEditViewGtk, void, HandleMarkSetAfter, 172 GtkTextBuffer*, GtkTextIter*, GtkTextMark*); 173 CHROMEG_CALLBACK_3(AutocompleteEditViewGtk, void, HandleInsertText, 174 GtkTextBuffer*, GtkTextIter*, const gchar*, gint); 175 CHROMEG_CALLBACK_0(AutocompleteEditViewGtk, void, 176 HandleKeymapDirectionChanged, GdkKeymap*); 177 CHROMEG_CALLBACK_2(AutocompleteEditViewGtk, void, HandleDeleteRange, 178 GtkTextBuffer*, GtkTextIter*, GtkTextIter*); 179 // Unlike above HandleMarkSet and HandleMarkSetAfter, this handler will always 180 // be connected to the signal. 181 CHROMEG_CALLBACK_2(AutocompleteEditViewGtk, void, HandleMarkSetAlways, 182 GtkTextBuffer*, GtkTextIter*, GtkTextMark*); 183 184 CHROMEGTK_CALLBACK_1(AutocompleteEditViewGtk, gboolean, HandleKeyPress, 185 GdkEventKey*); 186 CHROMEGTK_CALLBACK_1(AutocompleteEditViewGtk, gboolean, HandleKeyRelease, 187 GdkEventKey*); 188 CHROMEGTK_CALLBACK_1(AutocompleteEditViewGtk, gboolean, HandleViewButtonPress, 189 GdkEventButton*); 190 CHROMEGTK_CALLBACK_1(AutocompleteEditViewGtk, gboolean, 191 HandleViewButtonRelease, GdkEventButton*); 192 CHROMEGTK_CALLBACK_1(AutocompleteEditViewGtk, gboolean, HandleViewFocusIn, 193 GdkEventFocus*); 194 CHROMEGTK_CALLBACK_1(AutocompleteEditViewGtk, gboolean, HandleViewFocusOut, 195 GdkEventFocus*); 196 CHROMEGTK_CALLBACK_1(AutocompleteEditViewGtk, void, HandleViewMoveFocus, 197 GtkDirectionType); 198 CHROMEGTK_CALLBACK_3(AutocompleteEditViewGtk, void, HandleViewMoveCursor, 199 GtkMovementStep, gint, gboolean); 200 CHROMEGTK_CALLBACK_1(AutocompleteEditViewGtk, void, HandleViewSizeRequest, 201 GtkRequisition*); 202 CHROMEGTK_CALLBACK_1(AutocompleteEditViewGtk, void, HandlePopulatePopup, 203 GtkMenu*); 204 CHROMEGTK_CALLBACK_0(AutocompleteEditViewGtk, void, HandleEditSearchEngines); 205 CHROMEGTK_CALLBACK_0(AutocompleteEditViewGtk, void, HandlePasteAndGo); 206 CHROMEGTK_CALLBACK_6(AutocompleteEditViewGtk, void, HandleDragDataReceived, 207 GdkDragContext*, gint, gint, GtkSelectionData*, 208 guint, guint); 209 CHROMEGTK_CALLBACK_4(AutocompleteEditViewGtk, void, HandleDragDataGet, 210 GdkDragContext*, GtkSelectionData*, guint, guint); 211 CHROMEGTK_CALLBACK_0(AutocompleteEditViewGtk, void, HandleBackSpace); 212 CHROMEGTK_CALLBACK_0(AutocompleteEditViewGtk, void, HandleCopyClipboard); 213 CHROMEGTK_CALLBACK_0(AutocompleteEditViewGtk, void, HandleCutClipboard); 214 CHROMEGTK_CALLBACK_0(AutocompleteEditViewGtk, void, HandlePasteClipboard); 215 CHROMEGTK_CALLBACK_1(AutocompleteEditViewGtk, gboolean, HandleExposeEvent, 216 GdkEventExpose*); 217 CHROMEGTK_CALLBACK_1(AutocompleteEditViewGtk, void, 218 HandleWidgetDirectionChanged, GtkTextDirection); 219 CHROMEGTK_CALLBACK_2(AutocompleteEditViewGtk, void, 220 HandleDeleteFromCursor, GtkDeleteType, gint); 221 // We connect to this so we can determine our toplevel window, so we can 222 // listen to focus change events on it. 223 CHROMEGTK_CALLBACK_1(AutocompleteEditViewGtk, void, HandleHierarchyChanged, 224 GtkWidget*); 225#if GTK_CHECK_VERSION(2, 20, 0) 226 CHROMEGTK_CALLBACK_1(AutocompleteEditViewGtk, void, HandlePreeditChanged, 227 const gchar*); 228#endif 229 // Undo/redo operations won't trigger "begin-user-action" and 230 // "end-user-action" signals, so we need to hook into "undo" and "redo" 231 // signals and call OnBeforePossibleChange()/OnAfterPossibleChange() by 232 // ourselves. 233 CHROMEGTK_CALLBACK_0(AutocompleteEditViewGtk, void, HandleUndoRedo); 234 CHROMEGTK_CALLBACK_0(AutocompleteEditViewGtk, void, HandleUndoRedoAfter); 235 236 CHROMEG_CALLBACK_1(AutocompleteEditViewGtk, void, HandleWindowSetFocus, 237 GtkWindow*, GtkWidget*); 238 239 // Callback for the PRIMARY selection clipboard. 240 static void ClipboardGetSelectionThunk(GtkClipboard* clipboard, 241 GtkSelectionData* selection_data, 242 guint info, 243 gpointer object); 244 void ClipboardGetSelection(GtkClipboard* clipboard, 245 GtkSelectionData* selection_data, 246 guint info); 247 248 void HandleCopyOrCutClipboard(bool copy); 249 250 // Take control of the PRIMARY selection clipboard with |text|. Use 251 // |text_buffer_| as the owner, so that this doesn't remove the selection on 252 // it. This makes use of the above callbacks. 253 void OwnPrimarySelection(const std::string& text); 254 255 // Gets the GTK_TEXT_WINDOW_WIDGET coordinates for |text_view_| that bound the 256 // given iters. 257 gfx::Rect WindowBoundsFromIters(GtkTextIter* iter1, GtkTextIter* iter2); 258 259 // Actual implementation of SelectAll(), but also provides control over 260 // whether the PRIMARY selection is set to the selected text (in SelectAll(), 261 // it isn't, but we want set the selection when the user clicks in the entry). 262 void SelectAllInternal(bool reversed, bool update_primary_selection); 263 264 // Get ready to update |text_buffer_|'s highlighting without making changes to 265 // the PRIMARY selection. Removes the clipboard from |text_buffer_| and 266 // blocks the "mark-set" signal handler. 267 void StartUpdatingHighlightedText(); 268 269 // Finish updating |text_buffer_|'s highlighting such that future changes will 270 // automatically update the PRIMARY selection. Undoes 271 // StartUpdatingHighlightedText()'s changes. 272 void FinishUpdatingHighlightedText(); 273 274 // Get the character indices of the current selection. This honors 275 // direction, cp_max is the insertion point, and cp_min is the bound. 276 CharRange GetSelection(); 277 278 // Translate from character positions to iterators for the current buffer. 279 void ItersFromCharRange(const CharRange& range, 280 GtkTextIter* iter_min, 281 GtkTextIter* iter_max); 282 283 // Return the number of characers in the current buffer. 284 int GetTextLength() const; 285 286 // Try to parse the current text as a URL and colorize the components. 287 void EmphasizeURLComponents(); 288 289 // Internally invoked whenever the text changes in some way. 290 void TextChanged(); 291 292 // Save |selected_text| as the PRIMARY X selection. Unlike 293 // OwnPrimarySelection(), this won't set an owner or use callbacks. 294 void SavePrimarySelection(const std::string& selected_text); 295 296 // Update the field with |text| and set the selection. 297 void SetTextAndSelectedRange(const std::wstring& text, 298 const CharRange& range); 299 300 // Set the selection to |range|. 301 void SetSelectedRange(const CharRange& range); 302 303 // Adjust the text justification according to the text direction of the widget 304 // and |text_buffer_|'s content, to make sure the real text justification is 305 // always in sync with the UI language direction. 306 void AdjustTextJustification(); 307 308 // Get the text direction of |text_buffer_|'s content, by searching the first 309 // character that has a strong direction. 310 PangoDirection GetContentDirection(); 311 312 // Returns the selected text. 313 std::string GetSelectedText() const; 314 315 // If the selected text parses as a URL OwnPrimarySelection is invoked. 316 void UpdatePrimarySelectionIfValidURL(); 317 318 // Retrieves the first and last iterators in the |text_buffer_|, but excludes 319 // the anchor holding the |instant_view_| widget. 320 void GetTextBufferBounds(GtkTextIter* start, GtkTextIter* end) const; 321 322 // Validates an iterator in the |text_buffer_|, to make sure it doesn't go 323 // beyond the anchor for holding the |instant_view_| widget. 324 void ValidateTextBufferIter(GtkTextIter* iter) const; 325 326 // Adjusts vertical alignment of the |instant_view_| in the |text_view_|, to 327 // make sure they have the same baseline. 328 void AdjustVerticalAlignmentOfInstantView(); 329 330 // The widget we expose, used for vertically centering the real text edit, 331 // since the height will change based on the font / font size, etc. 332 OwnedWidgetGtk alignment_; 333 334 // The actual text entry which will be owned by the alignment_. 335 GtkWidget* text_view_; 336 337 GtkTextTagTable* tag_table_; 338 GtkTextBuffer* text_buffer_; 339 GtkTextTag* faded_text_tag_; 340 GtkTextTag* secure_scheme_tag_; 341 GtkTextTag* security_error_scheme_tag_; 342 GtkTextTag* normal_text_tag_; 343 344 // Objects for the instant suggestion text view. 345 GtkTextTag* instant_anchor_tag_; 346 347 // A widget for displaying instant suggestion text. It'll be attached to a 348 // child anchor in the |text_buffer_| object. 349 GtkWidget* instant_view_; 350 351 // A mark to split the content and the instant anchor. Wherever the end 352 // iterator of the text buffer is required, the iterator to this mark should 353 // be used. 354 GtkTextMark* instant_mark_; 355 356 scoped_ptr<AutocompleteEditModel> model_; 357 scoped_ptr<AutocompletePopupView> popup_view_; 358 AutocompleteEditController* controller_; 359 ToolbarModel* toolbar_model_; 360 361 // The object that handles additional command functionality exposed on the 362 // edit, such as invoking the keyword editor. 363 CommandUpdater* command_updater_; 364 365 // When true, the location bar view is read only and also is has a slightly 366 // different presentation (smaller font size). This is used for popups. 367 bool popup_window_mode_; 368 369 ToolbarModel::SecurityLevel security_level_; 370 371 // Selection at the point where the user started using the 372 // arrows to move around in the popup. 373 CharRange saved_temporary_selection_; 374 375 // Tracking state before and after a possible change. 376 std::wstring text_before_change_; 377 CharRange sel_before_change_; 378 379 // The most-recently-selected text from the entry that was copied to the 380 // clipboard. This is updated on-the-fly as the user selects text. This may 381 // differ from the actual selected text, such as when 'http://' is prefixed to 382 // the text. It is used in cases where we need to make the PRIMARY selection 383 // persist even after the user has unhighlighted the text in the view 384 // (e.g. when they highlight some text and then click to unhighlight it, we 385 // pass this string to SavePrimarySelection()). 386 std::string selected_text_; 387 388 // When we own the X clipboard, this is the text for it. 389 std::string primary_selection_text_; 390 391 // IDs of the signal handlers for "mark-set" on |text_buffer_|. 392 gulong mark_set_handler_id_; 393 gulong mark_set_handler_id2_; 394 395#if defined(OS_CHROMEOS) 396 // The following variables are used to implement select-all-on-mouse-up, which 397 // is disabled in the standard Linux build due to poor interaction with the 398 // PRIMARY X selection. 399 400 // Is the first mouse button currently down? When selection marks get moved, 401 // we use this to determine if the user was highlighting text with the mouse 402 // -- if so, we avoid selecting all the text on mouse-up. 403 bool button_1_pressed_; 404 405 // Did the user change the selected text in the middle of the current click? 406 // If so, we don't select all of the text when the button is released -- we 407 // don't want to blow away their selection. 408 bool text_selected_during_click_; 409 410 // Was the text view already focused before the user clicked in it? We use 411 // this to figure out whether we should select all of the text when the button 412 // is released (we only do so if the view was initially unfocused). 413 bool text_view_focused_before_button_press_; 414#endif 415 416#if !defined(TOOLKIT_VIEWS) 417 // Supplies colors, et cetera. 418 GtkThemeProvider* theme_provider_; 419 420 NotificationRegistrar registrar_; 421#endif 422 423 // Indicates if Enter key was pressed. 424 // 425 // It's used in the key press handler to detect an Enter key press event 426 // during sync dispatch of "end-user-action" signal so that an unexpected 427 // change caused by the event can be ignored in OnAfterPossibleChange(). 428 bool enter_was_pressed_; 429 430 // Indicates if Tab key was pressed. 431 // 432 // It's only used in the key press handler to detect a Tab key press event 433 // during sync dispatch of "move-focus" signal. 434 bool tab_was_pressed_; 435 436 // Indicates that user requested to paste clipboard. 437 // The actual paste clipboard action might be performed later if the 438 // clipboard is not empty. 439 bool paste_clipboard_requested_; 440 441 // Indicates if an Enter key press is inserted as text. 442 // It's used in the key press handler to determine if an Enter key event is 443 // handled by IME or not. 444 bool enter_was_inserted_; 445 446 // Indicates whether the IME changed the text. It's possible for the IME to 447 // handle a key event but not change the text contents (e.g., when pressing 448 // shift+del with no selection). 449 bool text_changed_; 450 451 // Contains the character range that should have a strikethrough (used for 452 // insecure schemes). If the range is size one or less, no strikethrough 453 // is needed. 454 CharRange strikethrough_; 455 456 // Indicate if the tab to search should be enabled or not. It's true by 457 // default and will only be set to false if the location bar view is not able 458 // to show the tab to search hint. 459 bool enable_tab_to_search_; 460 461 // Indicates if the selected text is suggested text or not. If the selection 462 // is not suggested text, that means the user manually made the selection. 463 bool selection_suggested_; 464 465#if GTK_CHECK_VERSION(2, 20, 0) 466 // Stores the text being composed by the input method. 467 std::wstring preedit_; 468#endif 469 470 // The view that is going to be focused next. Only valid while handling 471 // "focus-out" events. 472 GtkWidget* going_to_focus_; 473 474 GtkSignalRegistrar signals_; 475 476 DISALLOW_COPY_AND_ASSIGN(AutocompleteEditViewGtk); 477}; 478 479#endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_EDIT_VIEW_GTK_H_ 480