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