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