- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / omnibox / omnibox_view_win.h
1 // Copyright (c) 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_VIEWS_OMNIBOX_OMNIBOX_VIEW_WIN_H_
6 #define CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_VIEW_WIN_H_
7
8 #include <atlbase.h>
9 #include <atlapp.h>
10 #include <atlcrack.h>
11 #include <atlctrls.h>
12 #include <atlmisc.h>
13 #include <tom.h>  // For ITextDocument, a COM interface to CRichEditCtrl.
14
15 #include "base/memory/scoped_ptr.h"
16 #include "base/win/scoped_comptr.h"
17 #include "chrome/browser/ui/omnibox/omnibox_view.h"
18 #include "chrome/browser/ui/toolbar/toolbar_model.h"
19 #include "chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h"
20 #include "ui/base/ime/win/tsf_event_router.h"
21 #include "ui/base/models/simple_menu_model.h"
22 #include "ui/base/win/extra_sdk_defines.h"
23 #include "ui/base/window_open_disposition.h"
24 #include "ui/gfx/font_list.h"
25
26 class LocationBarView;
27 class OmniboxPopupView;
28
29 namespace views {
30 class MenuRunner;
31 class NativeViewHost;
32 class View;
33 }
34
35 // Provides the implementation of an edit control with a drop-down
36 // autocomplete box. The box itself is implemented in autocomplete_popup.cc
37 // This file implements the edit box and management for the popup.
38 class OmniboxViewWin
39     : public CWindowImpl<OmniboxViewWin,
40                          CRichEditCtrl,
41                          CWinTraits<WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL |
42                                     ES_NOHIDESEL> >,
43       public CRichEditCommands<OmniboxViewWin>,
44       public ui::SimpleMenuModel::Delegate,
45       public ui::TSFEventRouterObserver,
46       public OmniboxView {
47  public:
48   struct State {
49     State(const CHARRANGE& selection,
50           const CHARRANGE& saved_selection_for_focus_change)
51         : selection(selection),
52           saved_selection_for_focus_change(saved_selection_for_focus_change) {
53     }
54
55     const CHARRANGE selection;
56     const CHARRANGE saved_selection_for_focus_change;
57   };
58
59   DECLARE_WND_SUPERCLASS(L"Chrome_OmniboxView", MSFTEDIT_CLASS);
60
61   OmniboxViewWin(OmniboxEditController* controller,
62                  LocationBarView* parent_view,
63                  CommandUpdater* command_updater,
64                  bool popup_window_mode,
65                  const gfx::FontList& font_list,
66                  int font_y_offset);
67   ~OmniboxViewWin();
68
69   // Gets the relative window for the specified native view.
70   static gfx::NativeView GetRelativeWindowForNativeView(
71       gfx::NativeView edit_native_view);
72
73   views::View* parent_view() const;
74
75   // OmniboxView:
76   virtual void SaveStateToTab(content::WebContents* tab) OVERRIDE;
77   virtual void OnTabChanged(const content::WebContents* web_contents) OVERRIDE;
78   virtual void Update() OVERRIDE;
79   virtual void OpenMatch(const AutocompleteMatch& match,
80                          WindowOpenDisposition disposition,
81                          const GURL& alternate_nav_url,
82                          size_t index) OVERRIDE;
83   virtual string16 GetText() const OVERRIDE;
84   virtual void SetUserText(const string16& text,
85                            const string16& display_text,
86                            bool update_popup) OVERRIDE;
87   virtual void SetWindowTextAndCaretPos(const string16& text,
88                                         size_t caret_pos,
89                                         bool update_popup,
90                                         bool notify_text_changed) OVERRIDE;
91   virtual void SetForcedQuery() OVERRIDE;
92   virtual bool IsSelectAll() const OVERRIDE;
93   virtual bool DeleteAtEndPressed() OVERRIDE;
94   virtual void GetSelectionBounds(string16::size_type* start,
95                                   string16::size_type* end) const OVERRIDE;
96   virtual void SelectAll(bool reversed) OVERRIDE;
97   virtual void RevertAll() OVERRIDE;
98   virtual void UpdatePopup() OVERRIDE;
99   virtual void SetFocus() OVERRIDE;
100   virtual void ApplyCaretVisibility() OVERRIDE;
101   virtual void OnTemporaryTextMaybeChanged(
102       const string16& display_text,
103       bool save_original_selection,
104       bool notify_text_changed) OVERRIDE;
105   virtual bool OnInlineAutocompleteTextMaybeChanged(
106       const string16& display_text, size_t user_text_length) OVERRIDE;
107   virtual void OnRevertTemporaryText() OVERRIDE;
108   virtual void OnBeforePossibleChange() OVERRIDE;
109   virtual bool OnAfterPossibleChange() OVERRIDE;
110   virtual gfx::NativeView GetNativeView() const OVERRIDE;
111   virtual gfx::NativeView GetRelativeWindowForPopup() const OVERRIDE;
112   virtual void SetGrayTextAutocompletion(const string16& suggestion) OVERRIDE;
113   virtual int TextWidth() const OVERRIDE;
114   virtual string16 GetGrayTextAutocompletion() const OVERRIDE;
115   virtual bool IsImeComposing() const OVERRIDE;
116   virtual int GetMaxEditWidth(int entry_width) const OVERRIDE;
117   virtual views::View* AddToView(views::View* parent) OVERRIDE;
118   virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE;
119
120   int GetPopupMaxYCoordinate();
121
122   void SetDropHighlightPosition(int position);
123   int drop_highlight_position() const { return drop_highlight_position_; }
124
125   // Returns true if a drag a drop session was initiated by this edit.
126   bool in_drag() const { return in_drag_; }
127
128   // Moves the selected text to the specified position.
129   void MoveSelectedText(int new_position);
130
131   // Inserts the text at the specified position.
132   void InsertText(int position, const string16& text);
133
134   void set_force_hidden(bool force_hidden) { force_hidden_ = force_hidden; }
135
136   // Called before an accelerator is processed to give us a chance to override
137   // it.
138   bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& event);
139
140   // Handler for external events passed in to us.  The View that owns us may
141   // send us events that we should treat as if they were events on us.
142   void HandleExternalMsg(UINT msg, UINT flags, const CPoint& screen_point);
143
144   // CWindowImpl
145   BEGIN_MSG_MAP(OmniboxViewWin)
146     MSG_WM_CHAR(OnChar)
147     MSG_WM_CONTEXTMENU(OnContextMenu)
148     MSG_WM_COPY(OnCopy)
149     MSG_WM_CREATE(OnCreate)
150     MSG_WM_CUT(OnCut)
151     MESSAGE_HANDLER_EX(WM_GETOBJECT, OnGetObject)
152     MESSAGE_HANDLER_EX(WM_IME_COMPOSITION, OnImeComposition)
153     MESSAGE_HANDLER_EX(WM_IME_ENDCOMPOSITION, OnImeEndComposition)
154     MESSAGE_HANDLER_EX(WM_IME_NOTIFY, OnImeNotify)
155     MESSAGE_HANDLER_EX(WM_TOUCH, OnTouchEvent)
156     MSG_WM_KEYDOWN(OnKeyDown)
157     MSG_WM_KEYUP(OnKeyUp)
158     MSG_WM_KILLFOCUS(OnKillFocus)
159     MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
160     MSG_WM_LBUTTONDOWN(OnLButtonDown)
161     MSG_WM_LBUTTONUP(OnLButtonUp)
162     MSG_WM_MBUTTONDBLCLK(OnMButtonDblClk)
163     MSG_WM_MBUTTONDOWN(OnMButtonDown)
164     MSG_WM_MBUTTONUP(OnMButtonUp)
165     MSG_WM_MOUSEACTIVATE(OnMouseActivate)
166     MSG_WM_MOUSEMOVE(OnMouseMove)
167     MSG_WM_MOUSEWHEEL(OnMouseWheel)
168     MSG_WM_PAINT(OnPaint)
169     MSG_WM_PASTE(OnPaste)
170     MSG_WM_RBUTTONDBLCLK(OnRButtonDblClk)
171     MSG_WM_RBUTTONDOWN(OnRButtonDown)
172     MSG_WM_RBUTTONUP(OnRButtonUp)
173     MSG_WM_SETFOCUS(OnSetFocus)
174     MSG_WM_SETTEXT(OnSetText)
175     MSG_WM_SYSCHAR(OnSysChar)  // WM_SYSxxx == WM_xxx with ALT down
176     MSG_WM_SYSKEYDOWN(OnKeyDown)
177     MSG_WM_SYSKEYUP(OnKeyUp)
178     MSG_WM_WINDOWPOSCHANGING(OnWindowPosChanging)
179     DEFAULT_REFLECTION_HANDLER()  // avoids black margin area
180   END_MSG_MAP()
181
182   // ui::SimpleMenuModel::Delegate
183   virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
184   virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
185   virtual bool GetAcceleratorForCommandId(
186       int command_id,
187       ui::Accelerator* accelerator) OVERRIDE;
188   virtual bool IsItemForCommandIdDynamic(int command_id) const OVERRIDE;
189   virtual string16 GetLabelForCommandId(int command_id) const OVERRIDE;
190   virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
191
192  private:
193   enum MouseButton {
194     kLeft  = 0,
195     kRight = 1,
196   };
197
198   // This object freezes repainting of the edit until the object is destroyed.
199   // Some methods of the CRichEditCtrl draw synchronously to the screen.  If we
200   // don't freeze, the user will see a rapid series of calls to these as
201   // flickers.
202   //
203   // Freezing the control while it is already frozen is permitted; the control
204   // will unfreeze once both freezes are released (the freezes stack).
205   class ScopedFreeze {
206    public:
207     ScopedFreeze(OmniboxViewWin* edit, ITextDocument* text_object_model);
208     ~ScopedFreeze();
209
210    private:
211     OmniboxViewWin* const edit_;
212     ITextDocument* const text_object_model_;
213
214     DISALLOW_COPY_AND_ASSIGN(ScopedFreeze);
215   };
216
217   class EditDropTarget;
218   friend class EditDropTarget;
219
220   // This object suspends placing any operations on the edit's undo stack until
221   // the object is destroyed.  If we don't do this, some of the operations we
222   // perform behind the user's back will be undoable by the user, which feels
223   // bizarre and confusing.
224   class ScopedSuspendUndo {
225    public:
226     explicit ScopedSuspendUndo(ITextDocument* text_object_model);
227     ~ScopedSuspendUndo();
228
229    private:
230     ITextDocument* const text_object_model_;
231
232     DISALLOW_COPY_AND_ASSIGN(ScopedSuspendUndo);
233   };
234
235   // Replacement word-breaking proc for the rich edit control.
236   static int CALLBACK WordBreakProc(LPTSTR edit_text,
237                                     int current_pos,
238                                     int length,
239                                     int action);
240
241   // Returns true if |edit_text| starting at |current_pos| is "://".
242   static bool SchemeEnd(LPTSTR edit_text, int current_pos, int length);
243
244   // Message handlers
245   void OnChar(TCHAR ch, UINT repeat_count, UINT flags);
246   void OnContextMenu(HWND window, const CPoint& point);
247   void OnCopy();
248   LRESULT OnCreate(const CREATESTRUCTW* create_struct);
249   void OnCut();
250   LRESULT OnGetObject(UINT message, WPARAM wparam, LPARAM lparam);
251   LRESULT OnImeComposition(UINT message, WPARAM wparam, LPARAM lparam);
252   LRESULT OnImeEndComposition(UINT message, WPARAM wparam, LPARAM lparam);
253   LRESULT OnImeNotify(UINT message, WPARAM wparam, LPARAM lparam);
254   LRESULT OnTouchEvent(UINT message, WPARAM wparam, LPARAM lparam);
255   void OnKeyDown(TCHAR key, UINT repeat_count, UINT flags);
256   void OnKeyUp(TCHAR key, UINT repeat_count, UINT flags);
257   void OnKillFocus(HWND focus_wnd);
258   void OnLButtonDblClk(UINT keys, const CPoint& point);
259   void OnLButtonDown(UINT keys, const CPoint& point);
260   void OnLButtonUp(UINT keys, const CPoint& point);
261   void OnMButtonDblClk(UINT keys, const CPoint& point);
262   void OnMButtonDown(UINT keys, const CPoint& point);
263   void OnMButtonUp(UINT keys, const CPoint& point);
264   LRESULT OnMouseActivate(HWND window, UINT hit_test, UINT mouse_message);
265   void OnMouseMove(UINT keys, const CPoint& point);
266   BOOL OnMouseWheel(UINT flags, short delta, CPoint point);
267   void OnPaint(HDC bogus_hdc);
268   void OnPaste();
269   void OnRButtonDblClk(UINT keys, const CPoint& point);
270   void OnRButtonDown(UINT keys, const CPoint& point);
271   void OnRButtonUp(UINT keys, const CPoint& point);
272   void OnSetFocus(HWND focus_wnd);
273   LRESULT OnSetText(const wchar_t* text);
274   void OnSysChar(TCHAR ch, UINT repeat_count, UINT flags);
275   void OnWindowPosChanging(WINDOWPOS* window_pos);
276
277   // Helper function for OnChar() and OnKeyDown() that handles keystrokes that
278   // could change the text in the edit.
279   void HandleKeystroke(UINT message, TCHAR key, UINT repeat_count, UINT flags);
280
281   // Helper functions for OnKeyDown() that handle accelerators applicable when
282   // we're not read-only and all the time, respectively.  These return true if
283   // they handled the key.
284   bool OnKeyDownOnlyWritable(TCHAR key, UINT repeat_count, UINT flags);
285   bool OnKeyDownAllModes(TCHAR key, UINT repeat_count, UINT flags);
286
287   // Like GetSel(), but returns a range where |cpMin| will be larger than
288   // |cpMax| if the cursor is at the start rather than the end of the selection
289   // (in other words, tracks selection direction as well as offsets).
290   // Note the non-Google-style "non-const-ref" argument, which matches GetSel().
291   void GetSelection(CHARRANGE& sel) const;
292
293   // Returns the currently selected text of the edit control.
294   string16 GetSelectedText() const;
295
296   // Like SetSel(), but respects the selection direction implied by |start| and
297   // |end|: if |end| < |start|, the effective cursor will be placed at the
298   // beginning of the selection.
299   void SetSelection(LONG start, LONG end);
300
301   // Like SetSelection(), but takes a CHARRANGE.
302   void SetSelectionRange(const CHARRANGE& sel) {
303     SetSelection(sel.cpMin, sel.cpMax);
304   }
305
306   // Places the caret at the given position.  This clears any selection.
307   void PlaceCaretAt(size_t pos);
308
309   // Returns true if |sel| represents a forward or backward selection of all the
310   // text.
311   bool IsSelectAllForRange(const CHARRANGE& sel) const;
312
313   // Given an X coordinate in client coordinates, returns that coordinate
314   // clipped to be within the horizontal bounds of the visible text.
315   //
316   // This is used in our mouse handlers to work around quirky behaviors of the
317   // underlying CRichEditCtrl like not supporting triple-click when the user
318   // doesn't click on the text itself.
319   //
320   // |is_triple_click| should be true iff this is the third click of a triple
321   // click.  Sadly, we need to clip slightly differently in this case.
322   LONG ClipXCoordToVisibleText(LONG x, bool is_triple_click) const;
323
324   virtual int GetOmniboxTextLength() const OVERRIDE;
325
326   // Parses the contents of the control for the scheme and the host name.
327   // Highlights the scheme in green or red depending on it security level.
328   // If a host name is found, it makes it visually stronger.
329   virtual void EmphasizeURLComponents() OVERRIDE;
330
331   // TSFEventRouter::Observer:
332   virtual void OnCandidateWindowCountChanged(size_t window_count) OVERRIDE;
333   virtual void OnTextUpdated(const gfx::Range& composition_range) OVERRIDE;
334
335   // Erases the portion of the selection in the font's y-adjustment area.  For
336   // some reason the edit draws the selection rect here even though it's not
337   // part of the font.
338   void EraseTopOfSelection(CDC* dc,
339                            const CRect& client_rect,
340                            const CRect& paint_clip_rect);
341
342   // Draws a slash across the scheme if desired.
343   void DrawSlashForInsecureScheme(HDC hdc,
344                                   const CRect& client_rect,
345                                   const CRect& paint_clip_rect);
346
347   // Renders the drop highlight.
348   void DrawDropHighlight(HDC hdc,
349                          const CRect& client_rect,
350                          const CRect& paint_clip_rect);
351
352   // Internally invoked whenever the text changes in some way.
353   void TextChanged() OVERRIDE;
354
355   // Getter for the text_object_model_.  Note that the pointer returned here is
356   // only valid as long as the AutocompleteEdit is still alive.  Also, if the
357   // underlying call fails, this may return NULL.
358   ITextDocument* GetTextObjectModel() const;
359
360   // Invoked during a mouse move. As necessary starts a drag and drop session.
361   void StartDragIfNecessary(const CPoint& point);
362
363   // Invoked during a mouse down. If the mouse location is over the selection
364   // this sets possible_drag_ to true to indicate a drag should start if the
365   // user moves the mouse far enough to start a drag.
366   void OnPossibleDrag(const CPoint& point);
367
368   // Redraws the necessary region for a drop highlight at the specified
369   // position. This does nothing if position is beyond the bounds of the
370   // text.
371   void RepaintDropHighlight(int position);
372
373   // Generates the context menu for the edit field.
374   void BuildContextMenu();
375
376   void SelectAllIfNecessary(MouseButton button, const CPoint& point);
377   void TrackMousePosition(MouseButton button, const CPoint& point);
378
379   // Returns the sum of the left and right margins.
380   int GetHorizontalMargin() const;
381
382   // Returns the width in pixels needed to display |text|.
383   int WidthNeededToDisplay(const string16& text) const;
384
385   // Real implementation of OnAfterPossibleChange() method.
386   // If |force_text_changed| is true, then the text_changed code will always be
387   // triggerred no matter if the text is actually changed or not.
388   bool OnAfterPossibleChangeInternal(bool force_text_changed);
389
390   // Common implementation for performing a drop on the edit view.
391   int OnPerformDropImpl(const ui::DropTargetEvent& event, bool in_drag);
392
393   // The handle to the RichEdit DLL.  In the rare case where the user's system
394   // is missing this DLL (due to some kind of system corruption), the similar
395   // OmniboxViewViews is used instead; see Textfield::IsViewsTextfieldEnabled().
396   static HMODULE loaded_library_module_;
397
398   scoped_ptr<OmniboxPopupView> popup_view_;
399
400   // The parent view for the edit, used to align the popup and for
401   // accessibility.
402   LocationBarView* location_bar_;
403
404   // When true, the location bar view is read only and also is has a slightly
405   // different presentation (font size / color). This is used for popups.
406   bool popup_window_mode_;
407
408   // True if we should prevent attempts to make the window visible when we
409   // handle WM_WINDOWPOSCHANGING.  While toggling fullscreen mode, the main
410   // window is hidden, and if the edit is shown it will draw over the main
411   // window when that window reappears.
412   bool force_hidden_;
413
414   // Non-null when the edit is gaining focus from a left click.  This is only
415   // needed between when WM_MOUSEACTIVATE and WM_LBUTTONDOWN get processed.  It
416   // serves two purposes: first, by communicating to OnLButtonDown() that we're
417   // gaining focus from a left click, it allows us to work even with the
418   // inconsistent order in which various Windows messages get sent (see comments
419   // in OnMouseActivate()).  Second, by holding the edit frozen, it ensures that
420   // when we process WM_SETFOCUS the edit won't first redraw itself with the
421   // caret at the beginning, and then have it blink to where the mouse cursor
422   // really is shortly afterward.
423   scoped_ptr<ScopedFreeze> gaining_focus_;
424
425   // When the user clicks to give us focus, we watch to see if they're clicking
426   // or dragging.  When they're clicking, we select nothing until mouseup, then
427   // select all the text in the edit.  During this process, tracking_click_[X]
428   // is true and click_point_[X] holds the original click location.
429   // At other times, tracking_click_[X] is false, and the contents of
430   // click_point_[X] should be ignored. The arrays hold the state for the
431   // left and right mouse buttons, and are indexed using the MouseButton enum.
432   bool tracking_click_[2];
433   CPoint click_point_[2];
434
435   // We need to know if the user triple-clicks, so track double click points
436   // and times so we can see if subsequent clicks are actually triple clicks.
437   bool tracking_double_click_;
438   CPoint double_click_point_;
439   DWORD double_click_time_;
440
441   // Used to discard unnecessary WM_MOUSEMOVE events after the first such
442   // unnecessary event.  See detailed comments in OnMouseMove().
443   bool can_discard_mousemove_;
444
445   // Used to prevent IME message handling in the midst of updating the edit
446   // text.  See comments where this is used.
447   bool ignore_ime_messages_;
448
449   // Variables for tracking state before and after a possible change.
450   string16 text_before_change_;
451   CHARRANGE sel_before_change_;
452
453   // Set at the same time the model's original_* members are set, and valid in
454   // the same cases.
455   CHARRANGE original_selection_;
456
457   // Holds the user's selection across focus changes.  cpMin holds -1 when
458   // there is no saved selection.
459   CHARRANGE saved_selection_for_focus_change_;
460
461   // Was the delete key pressed with an empty selection at the end of the edit?
462   bool delete_at_end_pressed_;
463
464   // The context menu for the edit.
465   scoped_ptr<ui::SimpleMenuModel> context_menu_contents_;
466   scoped_ptr<views::MenuRunner> context_menu_runner_;
467
468   // The font list to draw text in Omnibox.
469   gfx::FontList font_list_;
470
471   // Metrics about the font, which we keep so we don't need to recalculate them
472   // every time we paint.  |font_y_adjustment_| is the number of pixels we need
473   // to shift the font vertically in order to make its baseline be at our
474   // desired baseline in the edit.
475   int font_x_height_;
476   int font_y_adjustment_;
477
478   // If true, indicates the mouse is down and if the mouse is moved enough we
479   // should start a drag.
480   bool possible_drag_;
481
482   // If true, we're in a call to DoDragDrop.
483   bool in_drag_;
484
485   // If true indicates we've run a drag and drop session. This is used to
486   // avoid starting two drag and drop sessions if the drag is canceled while
487   // the mouse is still down.
488   bool initiated_drag_;
489
490   // Position of the drop highlight.  If this is -1, there is no drop highlight.
491   int drop_highlight_position_;
492
493   // True if the IME candidate window is open.  When this is true, we want to
494   // avoid showing the popup.
495   bool ime_candidate_window_open_;
496
497   // Security UI-related data.
498   COLORREF background_color_;
499   ToolbarModel::SecurityLevel security_level_;
500
501   // This interface is useful for accessing the CRichEditCtrl at a low level.
502   mutable ITextDocument* text_object_model_;
503
504   // This contains the scheme char start and stop indexes that should be
505   // stricken-out when displaying an insecure scheme.
506   url_parse::Component insecure_scheme_component_;
507
508   // Instance of accessibility information and handling.
509   mutable base::win::ScopedComPtr<IAccessible> autocomplete_accessibility_;
510
511   // The native view host.
512   views::NativeViewHost* native_view_host_;
513
514   // TSF related event router.
515   scoped_ptr<ui::TSFEventRouter> tsf_event_router_;
516
517   DISALLOW_COPY_AND_ASSIGN(OmniboxViewWin);
518 };
519
520 #endif  // CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_VIEW_WIN_H_