Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / omnibox / omnibox_view_gtk.h
1 // Copyright 2012 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_UI_GTK_OMNIBOX_OMNIBOX_VIEW_GTK_H_
6 #define CHROME_BROWSER_UI_GTK_OMNIBOX_OMNIBOX_VIEW_GTK_H_
7
8 #include <gtk/gtk.h>
9
10 #include <algorithm>
11 #include <string>
12
13 #include "base/basictypes.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/strings/string_util.h"
16 #include "chrome/browser/ui/omnibox/omnibox_view.h"
17 #include "chrome/browser/ui/toolbar/toolbar_model.h"
18 #include "content/public/browser/notification_observer.h"
19 #include "content/public/browser/notification_registrar.h"
20 #include "ui/base/gtk/gtk_signal.h"
21 #include "ui/base/gtk/gtk_signal_registrar.h"
22 #include "ui/base/gtk/owned_widget_gtk.h"
23 #include "ui/base/window_open_disposition.h"
24 #include "ui/gfx/rect.h"
25
26 class Browser;
27 class OmniboxPopupView;
28 class Profile;
29
30 namespace gfx {
31 class Font;
32 }
33
34 class GtkThemeService;
35
36 class OmniboxViewGtk : public OmniboxView,
37                        public content::NotificationObserver {
38  public:
39   // Modeled like the Windows CHARRANGE.  Represent a pair of cursor position
40   // offsets.  Since GtkTextIters are invalid after the buffer is changed, we
41   // work in character offsets (not bytes).
42   struct CharRange {
43     CharRange() : cp_min(0), cp_max(0) { }
44     CharRange(int n, int x) : cp_min(n), cp_max(x) { }
45
46     // Returns the start/end of the selection.
47     int selection_min() const { return std::min(cp_min, cp_max); }
48     int selection_max() const { return std::max(cp_min, cp_max); }
49
50     // Work in integers to match the gint GTK APIs.
51     int cp_min;  // For a selection: Represents the start.
52     int cp_max;  // For a selection: Represents the end (insert position).
53   };
54
55   // profile parameter is introduced for unittests which can not instantiate
56   // browser object and pass NULL to the browser parameter.
57   // In other use case, you should pass browser->profile() object as
58   // profile parameter.
59   OmniboxViewGtk(OmniboxEditController* controller,
60                  Browser* browser,
61                  Profile* profile,
62                  CommandUpdater* command_updater,
63                  bool popup_window_mode,
64                  GtkWidget* location_bar);
65   virtual ~OmniboxViewGtk();
66
67   // Initialize, create the underlying widgets, etc.
68   void Init();
69
70   // OmniboxView:
71   virtual void SaveStateToTab(content::WebContents* tab) OVERRIDE;
72   virtual void OnTabChanged(const content::WebContents* web_contents) OVERRIDE;
73   virtual void Update() OVERRIDE;
74   virtual base::string16 GetText() const OVERRIDE;
75   virtual void SetWindowTextAndCaretPos(const base::string16& text,
76                                         size_t caret_pos,
77                                         bool update_popup,
78                                         bool notify_text_changed) OVERRIDE;
79   virtual void SetForcedQuery() OVERRIDE;
80   virtual bool IsSelectAll() const OVERRIDE;
81   virtual bool DeleteAtEndPressed() OVERRIDE;
82   virtual void GetSelectionBounds(
83       base::string16::size_type* start,
84       base::string16::size_type* end) const OVERRIDE;
85   virtual void SelectAll(bool reversed) OVERRIDE;
86   virtual void UpdatePopup() OVERRIDE;
87   virtual void SetFocus() OVERRIDE;
88   virtual void ApplyCaretVisibility() OVERRIDE;
89   virtual void OnTemporaryTextMaybeChanged(
90       const base::string16& display_text,
91       bool save_original_selection,
92       bool notify_text_changed) OVERRIDE;
93   virtual bool OnInlineAutocompleteTextMaybeChanged(
94       const base::string16& display_text, size_t user_text_length) OVERRIDE;
95   virtual void OnInlineAutocompleteTextCleared() OVERRIDE;
96   virtual void OnRevertTemporaryText() OVERRIDE;
97   virtual void OnBeforePossibleChange() OVERRIDE;
98   virtual bool OnAfterPossibleChange() OVERRIDE;
99   virtual gfx::NativeView GetNativeView() const OVERRIDE;
100   virtual gfx::NativeView GetRelativeWindowForPopup() const OVERRIDE;
101   virtual void SetGrayTextAutocompletion(
102       const base::string16& suggestion) OVERRIDE;
103   virtual base::string16 GetGrayTextAutocompletion() const OVERRIDE;
104   virtual int GetTextWidth() const OVERRIDE;
105   virtual int GetWidth() const OVERRIDE;
106   virtual bool IsImeComposing() const OVERRIDE;
107
108   // Overridden from content::NotificationObserver:
109   virtual void Observe(int type,
110                        const content::NotificationSource& source,
111                        const content::NotificationDetails& details) OVERRIDE;
112
113   // Sets the colors of the gray text suggestion view according to the theme.
114   void UpdateGrayTextViewColors();
115
116   // Returns the text view gtk widget. May return NULL if the widget
117   // has already been destroyed.
118   GtkWidget* text_view() {
119     return text_view_;
120   }
121
122  private:
123   friend class OmniboxViewGtkTest;
124
125   CHROMEG_CALLBACK_0(OmniboxViewGtk, void, HandleBeginUserAction,
126                      GtkTextBuffer*);
127   CHROMEG_CALLBACK_0(OmniboxViewGtk, void, HandleEndUserAction, GtkTextBuffer*);
128   CHROMEG_CALLBACK_2(OmniboxViewGtk, void, HandleMarkSet, GtkTextBuffer*,
129                      GtkTextIter*, GtkTextMark*);
130   // As above, but called after the default handler.
131   CHROMEG_CALLBACK_2(OmniboxViewGtk, void, HandleMarkSetAfter, GtkTextBuffer*,
132                      GtkTextIter*, GtkTextMark*);
133   CHROMEG_CALLBACK_3(OmniboxViewGtk, void, HandleInsertText, GtkTextBuffer*,
134                      GtkTextIter*, const gchar*, gint);
135   CHROMEG_CALLBACK_0(OmniboxViewGtk, void, HandleKeymapDirectionChanged,
136                      GdkKeymap*);
137   CHROMEG_CALLBACK_2(OmniboxViewGtk, void, HandleDeleteRange, GtkTextBuffer*,
138                      GtkTextIter*, GtkTextIter*);
139   // Unlike above HandleMarkSet and HandleMarkSetAfter, this handler will always
140   // be connected to the signal.
141   CHROMEG_CALLBACK_2(OmniboxViewGtk, void, HandleMarkSetAlways, GtkTextBuffer*,
142                      GtkTextIter*, GtkTextMark*);
143
144   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, gboolean, HandleKeyPress, GdkEventKey*);
145   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, gboolean, HandleKeyRelease,
146                        GdkEventKey*);
147   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, gboolean, HandleViewButtonPress,
148                        GdkEventButton*);
149   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, gboolean, HandleViewButtonRelease,
150                        GdkEventButton*);
151   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, gboolean, HandleViewFocusIn,
152                        GdkEventFocus*);
153   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, gboolean, HandleViewFocusOut,
154                        GdkEventFocus*);
155   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, void, HandleViewMoveFocus,
156                        GtkDirectionType);
157   CHROMEGTK_CALLBACK_3(OmniboxViewGtk, void, HandleViewMoveCursor,
158                        GtkMovementStep, gint, gboolean);
159   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, void, HandleViewSizeRequest,
160                        GtkRequisition*);
161   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, void, HandlePopulatePopup, GtkMenu*);
162   CHROMEGTK_CALLBACK_0(OmniboxViewGtk, void, HandlePasteAndGo);
163   CHROMEGTK_CALLBACK_0(OmniboxViewGtk, void, HandleShowURL);
164   CHROMEGTK_CALLBACK_0(OmniboxViewGtk, void, HandleEditSearchEngines);
165   CHROMEGTK_CALLBACK_6(OmniboxViewGtk, void, HandleDragDataReceived,
166                        GdkDragContext*, gint, gint, GtkSelectionData*,
167                        guint, guint);
168   CHROMEGTK_CALLBACK_4(OmniboxViewGtk, void, HandleDragDataGet,
169                        GdkDragContext*, GtkSelectionData*, guint, guint);
170   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, void, HandleDragBegin,
171                        GdkDragContext*);
172   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, void, HandleDragEnd,
173                        GdkDragContext*);
174   CHROMEGTK_CALLBACK_0(OmniboxViewGtk, void, HandleBackSpace);
175   CHROMEGTK_CALLBACK_0(OmniboxViewGtk, void, HandleCopyClipboard);
176   CHROMEGTK_CALLBACK_0(OmniboxViewGtk, void, HandleCutClipboard);
177   CHROMEGTK_CALLBACK_0(OmniboxViewGtk, void, HandlePasteClipboard);
178   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, gboolean, HandleExposeEvent,
179                        GdkEventExpose*);
180   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, gboolean, HandleExposeEventAfter,
181                        GdkEventExpose*);
182   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, void, HandleWidgetDirectionChanged,
183                        GtkTextDirection);
184   CHROMEGTK_CALLBACK_2(OmniboxViewGtk, void, HandleDeleteFromCursor,
185                        GtkDeleteType, gint);
186   // We connect to this so we can determine our toplevel window, so we can
187   // listen to focus change events on it.
188   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, void, HandleHierarchyChanged,
189                        GtkWidget*);
190   CHROMEGTK_CALLBACK_1(OmniboxViewGtk, void, HandlePreEditChanged,
191                        const gchar*);
192   // Undo/redo operations won't trigger "begin-user-action" and
193   // "end-user-action" signals, so we need to hook into "undo" and "redo"
194   // signals and call OnBeforePossibleChange()/OnAfterPossibleChange() by
195   // ourselves.
196   CHROMEGTK_CALLBACK_0(OmniboxViewGtk, void, HandleUndoRedo);
197   CHROMEGTK_CALLBACK_0(OmniboxViewGtk, void, HandleUndoRedoAfter);
198
199   CHROMEG_CALLBACK_1(OmniboxViewGtk, void, HandleWindowSetFocus,
200                      GtkWindow*, GtkWidget*);
201
202   // Callback function called after context menu is closed.
203   CHROMEGTK_CALLBACK_0(OmniboxViewGtk, void, HandlePopupMenuDeactivate);
204
205   // Callback for the PRIMARY selection clipboard.
206   static void ClipboardGetSelectionThunk(GtkClipboard* clipboard,
207                                          GtkSelectionData* selection_data,
208                                          guint info,
209                                          gpointer object);
210   void ClipboardGetSelection(GtkClipboard* clipboard,
211                              GtkSelectionData* selection_data,
212                              guint info);
213
214   void HandleCopyOrCutClipboard(bool copy);
215
216   // OmniboxView overrides.
217   virtual int GetOmniboxTextLength() const OVERRIDE;
218   virtual void EmphasizeURLComponents() OVERRIDE;
219
220   // Common implementation for performing a drop on the edit view.
221   bool OnPerformDropImpl(const base::string16& text);
222
223   // Sets the colors and font of the text view according to the theme.
224   void OnBrowserThemeChanged();
225
226   // Returns the font used in |text_view_|.
227   gfx::Font GetFont();
228
229   // Take control of the PRIMARY selection clipboard with |text|. Use
230   // |text_buffer_| as the owner, so that this doesn't remove the selection on
231   // it. This makes use of the above callbacks.
232   void OwnPrimarySelection(const std::string& text);
233
234   // Gets the GTK_TEXT_WINDOW_WIDGET coordinates for |text_view_| that bound the
235   // given iters.
236   gfx::Rect WindowBoundsFromIters(GtkTextIter* iter1, GtkTextIter* iter2);
237
238   // Actual implementation of SelectAll(), but also provides control over
239   // whether the PRIMARY selection is set to the selected text (in SelectAll(),
240   // it isn't, but we want set the selection when the user clicks in the entry).
241   void SelectAllInternal(bool reversed, bool update_primary_selection);
242
243   // Get ready to update |text_buffer_|'s highlighting without making changes to
244   // the PRIMARY selection.  Removes the clipboard from |text_buffer_| and
245   // blocks the "mark-set" signal handler.
246   void StartUpdatingHighlightedText();
247
248   // Finish updating |text_buffer_|'s highlighting such that future changes will
249   // automatically update the PRIMARY selection.  Undoes
250   // StartUpdatingHighlightedText()'s changes.
251   void FinishUpdatingHighlightedText();
252
253   // Get the character indices of the current selection.  This honors
254   // direction, cp_max is the insertion point, and cp_min is the bound.
255   CharRange GetSelection() const;
256
257   // Translate from character positions to iterators for the current buffer.
258   void ItersFromCharRange(const CharRange& range,
259                           GtkTextIter* iter_min,
260                           GtkTextIter* iter_max);
261
262   // Returns true if the caret is at the end of the content.
263   bool IsCaretAtEnd() const;
264
265   // Save |selected_text| as the PRIMARY X selection. Unlike
266   // OwnPrimarySelection(), this won't set an owner or use callbacks.
267   void SavePrimarySelection(const std::string& selected_text);
268
269   // Update the field with |text| and set the selection.
270   void SetTextAndSelectedRange(const base::string16& text,
271                                const CharRange& range);
272
273   // Set the selection to |range|.
274   void SetSelectedRange(const CharRange& range);
275
276   // Adjust the text justification according to the text direction of the widget
277   // and |text_buffer_|'s content, to make sure the real text justification is
278   // always in sync with the UI language direction.
279   void AdjustTextJustification();
280
281   // Get the text direction of |text_buffer_|'s content, by searching the first
282   // character that has a strong direction.
283   PangoDirection GetContentDirection();
284
285   // Returns the selected text.
286   std::string GetSelectedText() const;
287
288   // If the selected text parses as a URL OwnPrimarySelection is invoked.
289   void UpdatePrimarySelectionIfValidURL();
290
291   // Retrieves the first and last iterators in the |text_buffer_|, but excludes
292   // the anchor holding the |gray_text_view_| widget.
293   void GetTextBufferBounds(GtkTextIter* start, GtkTextIter* end) const;
294
295   // Validates an iterator in the |text_buffer_|, to make sure it doesn't go
296   // beyond the anchor for holding the |gray_text_view_| widget.
297   void ValidateTextBufferIter(GtkTextIter* iter) const;
298
299   // Adjusts vertical alignment of the |gray_text_view_| in the |text_view_|, to
300   // make sure they have the same baseline.
301   void AdjustVerticalAlignmentOfGrayTextView();
302
303   // The Browser that contains this omnibox.
304   Browser* browser_;
305
306   // The widget we expose, used for vertically centering the real text edit,
307   // since the height will change based on the font / font size, etc.
308   ui::OwnedWidgetGtk alignment_;
309
310   // The actual text entry which will be owned by the alignment_.  The
311   // reference will be set to NULL upon destruction to tell if the gtk
312   // widget tree has been destroyed. This is because gtk destroies child
313   // widgets if the parent (alignemtn_)'s refcount does not go down to 0.
314   GtkWidget* text_view_;
315
316   GtkTextTagTable* tag_table_;
317   GtkTextBuffer* text_buffer_;
318   GtkTextTag* faded_text_tag_;
319   GtkTextTag* secure_scheme_tag_;
320   GtkTextTag* security_error_scheme_tag_;
321   GtkTextTag* normal_text_tag_;
322
323   // Objects for the gray suggestion text view.
324   GtkTextTag* gray_text_anchor_tag_;
325
326   // A widget for displaying gray autocompletion text. It'll be attached to a
327   // child anchor in the |text_buffer_| object.
328   GtkWidget* gray_text_view_;
329
330   // A mark to split the content and the gray text anchor. Wherever the end
331   // iterator of the text buffer is required, the iterator to this mark should
332   // be used.
333   GtkTextMark* gray_text_mark_;
334
335   scoped_ptr<OmniboxPopupView> popup_view_;
336
337   // When true, the location bar view is read only and also is has a slightly
338   // different presentation (smaller font size). This is used for popups.
339   bool popup_window_mode_;
340
341   ToolbarModel::SecurityLevel security_level_;
342
343   // Selection at the point where the user started using the
344   // arrows to move around in the popup.
345   CharRange saved_temporary_selection_;
346
347   // Tracking state before and after a possible change.
348   base::string16 text_before_change_;
349   CharRange sel_before_change_;
350
351   // The most-recently-selected text from the entry that was copied to the
352   // clipboard.  This is updated on-the-fly as the user selects text. This may
353   // differ from the actual selected text, such as when 'http://' is prefixed to
354   // the text.  It is used in cases where we need to make the PRIMARY selection
355   // persist even after the user has unhighlighted the text in the view
356   // (e.g. when they highlight some text and then click to unhighlight it, we
357   // pass this string to SavePrimarySelection()).
358   std::string selected_text_;
359
360   std::string dragged_text_;
361   // When we own the X clipboard, this is the text for it.
362   std::string primary_selection_text_;
363
364   // IDs of the signal handlers for "mark-set" on |text_buffer_|.
365   gulong mark_set_handler_id_;
366   gulong mark_set_handler_id2_;
367
368   // Is the first mouse button currently down?  When selection marks get moved,
369   // we use this to determine if the user was highlighting text with the mouse
370   // -- if so, we avoid selecting all the text on mouse-up.
371   bool button_1_pressed_;
372
373   // Supplies colors, et cetera.
374   GtkThemeService* theme_service_;
375
376   content::NotificationRegistrar registrar_;
377
378   // Indicates if Enter key was pressed.
379   //
380   // It's used in the key press handler to detect an Enter key press event
381   // during sync dispatch of "end-user-action" signal so that an unexpected
382   // change caused by the event can be ignored in OnAfterPossibleChange().
383   bool enter_was_pressed_;
384
385   // Indicates if Tab key was pressed.
386   //
387   // It's only used in the key press handler to detect a Tab key press event
388   // during sync dispatch of "move-focus" signal.
389   bool tab_was_pressed_;
390
391   // Indicates if Shift key was pressed.
392   // Used in conjunction with the Tab key to determine if either traversal
393   // needs to move up the results or if the keyword needs to be cleared.
394   bool shift_was_pressed_;
395
396   // Indicates that user requested to paste clipboard.
397   // The actual paste clipboard action might be performed later if the
398   // clipboard is not empty.
399   bool paste_clipboard_requested_;
400
401   // Text to "Paste and go"; set by HandlePopulatePopup() and consumed by
402   // HandlePasteAndGo().
403   base::string16 sanitized_text_for_paste_and_go_;
404
405   // Indicates if an Enter key press is inserted as text.
406   // It's used in the key press handler to determine if an Enter key event is
407   // handled by IME or not.
408   bool enter_was_inserted_;
409
410   // Indicates whether the IME changed the text.  It's possible for the IME to
411   // handle a key event but not change the text contents (e.g., when pressing
412   // shift+del with no selection).
413   bool text_changed_;
414
415   // Contains the character range that should have a strikethrough (used for
416   // insecure schemes). If the range is size one or less, no strikethrough
417   // is needed.
418   CharRange strikethrough_;
419
420   // Indicates if the selected text is suggested text or not. If the selection
421   // is not suggested text, that means the user manually made the selection.
422   bool selection_suggested_;
423
424   // Was delete pressed?
425   bool delete_was_pressed_;
426
427   // Was the delete key pressed with an empty selection at the end of the edit?
428   bool delete_at_end_pressed_;
429
430   // Indicates if we are handling a key press event.
431   bool handling_key_press_;
432
433   // Indicates if omnibox's content maybe changed by a key press event, so that
434   // we need to call OnAfterPossibleChange() after handling the event.
435   // This flag should be set for changes directly caused by a key press event,
436   // including changes to content text, selection range and pre-edit string.
437   // Changes caused by function calls like SetUserText() should not affect this
438   // flag.
439   bool content_maybe_changed_by_key_press_;
440
441   // Set this flag to call UpdatePopup() in lost focus and need to update.
442   // Because context menu might take the focus, before setting the flag, check
443   // the focus with model_->has_focus().
444   bool update_popup_without_focus_;
445
446   // On GTK 2.20+ |pre_edit_| and |pre_edit_size_before_change_| will be used.
447   const bool supports_pre_edit_;
448
449   // Stores the text being composed by the input method.
450   base::string16 pre_edit_;
451
452   // Tracking pre-edit state before and after a possible change. We don't need
453   // to track pre-edit_'s content, as it'll be treated as part of text content.
454   size_t pre_edit_size_before_change_;
455
456   // The view that is going to be focused next. Only valid while handling
457   // "focus-out" events.
458   GtkWidget* going_to_focus_;
459
460   ui::GtkSignalRegistrar signals_;
461
462   // The baseline shift to be made to center the text.  Positive values move
463   // the text upward.
464   double font_baseline_shift_;
465
466   DISALLOW_COPY_AND_ASSIGN(OmniboxViewGtk);
467 };
468
469 #endif  // CHROME_BROWSER_UI_GTK_OMNIBOX_OMNIBOX_VIEW_GTK_H_