hwnd_message_handler.h revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
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 UI_VIEWS_WIN_HWND_MESSAGE_HANDLER_H_
6#define UI_VIEWS_WIN_HWND_MESSAGE_HANDLER_H_
7
8#include <windows.h>
9#include <atlbase.h>
10#include <atlapp.h>
11#include <atlmisc.h>
12
13#include <set>
14#include <vector>
15
16#include "base/basictypes.h"
17#include "base/compiler_specific.h"
18#include "base/memory/scoped_ptr.h"
19#include "base/memory/weak_ptr.h"
20#include "base/message_loop/message_loop.h"
21#include "base/strings/string16.h"
22#include "base/win/win_util.h"
23#include "ui/base/accessibility/accessibility_types.h"
24#include "ui/base/ui_base_types.h"
25#include "ui/events/event.h"
26#include "ui/gfx/rect.h"
27#include "ui/gfx/sequential_id_generator.h"
28#include "ui/gfx/win/window_impl.h"
29#include "ui/views/ime/input_method_delegate.h"
30#include "ui/views/views_export.h"
31
32namespace gfx {
33class Canvas;
34class ImageSkia;
35class Insets;
36}
37
38namespace views {
39
40class FullscreenHandler;
41class HWNDMessageHandlerDelegate;
42class InputMethod;
43
44// These two messages aren't defined in winuser.h, but they are sent to windows
45// with captions. They appear to paint the window caption and frame.
46// Unfortunately if you override the standard non-client rendering as we do
47// with CustomFrameWindow, sometimes Windows (not deterministically
48// reproducibly but definitely frequently) will send these messages to the
49// window and paint the standard caption/title over the top of the custom one.
50// So we need to handle these messages in CustomFrameWindow to prevent this
51// from happening.
52const int WM_NCUAHDRAWCAPTION = 0xAE;
53const int WM_NCUAHDRAWFRAME = 0xAF;
54
55// An object that handles messages for a HWND that implements the views
56// "Custom Frame" look. The purpose of this class is to isolate the windows-
57// specific message handling from the code that wraps it. It is intended to be
58// used by both a views::NativeWidget and an aura::RootWindowHost
59// implementation.
60// TODO(beng): This object should eventually *become* the WindowImpl.
61class VIEWS_EXPORT HWNDMessageHandler :
62    public gfx::WindowImpl,
63    public internal::InputMethodDelegate,
64    public base::MessageLoopForUI::Observer {
65 public:
66  explicit HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate);
67  ~HWNDMessageHandler();
68
69  void Init(HWND parent, const gfx::Rect& bounds);
70  void InitModalType(ui::ModalType modal_type);
71
72  void Close();
73  void CloseNow();
74
75  gfx::Rect GetWindowBoundsInScreen() const;
76  gfx::Rect GetClientAreaBoundsInScreen() const;
77  gfx::Rect GetRestoredBounds() const;
78  void GetWindowPlacement(gfx::Rect* bounds,
79                          ui::WindowShowState* show_state) const;
80
81  void SetBounds(const gfx::Rect& bounds_in_pixels);
82  void SetSize(const gfx::Size& size);
83  void CenterWindow(const gfx::Size& size);
84
85  void SetRegion(HRGN rgn);
86
87  void StackAbove(HWND other_hwnd);
88  void StackAtTop();
89
90  void Show();
91  void ShowWindowWithState(ui::WindowShowState show_state);
92  // TODO(beng): distinguish from ShowWindowWithState().
93  void Show(int show_state);
94  void ShowMaximizedWithBounds(const gfx::Rect& bounds);
95  void Hide();
96
97  void Maximize();
98  void Minimize();
99  void Restore();
100
101  void Activate();
102  void Deactivate();
103
104  void SetAlwaysOnTop(bool on_top);
105
106  bool IsVisible() const;
107  bool IsActive() const;
108  bool IsMinimized() const;
109  bool IsMaximized() const;
110
111  bool RunMoveLoop(const gfx::Vector2d& drag_offset, bool hide_on_escape);
112  void EndMoveLoop();
113
114  // Tells the HWND its client area has changed.
115  void SendFrameChanged();
116
117  void FlashFrame(bool flash);
118
119  void ClearNativeFocus();
120
121  void SetCapture();
122  void ReleaseCapture();
123  bool HasCapture() const;
124
125  FullscreenHandler* fullscreen_handler() { return fullscreen_handler_.get(); }
126
127  void SetVisibilityChangedAnimationsEnabled(bool enabled);
128
129  void SetTitle(const string16& title);
130
131  void SetCursor(HCURSOR cursor);
132
133  void FrameTypeChanged();
134
135  // Disable Layered Window updates by setting to false.
136  void set_can_update_layered_window(bool can_update_layered_window) {
137    can_update_layered_window_ = can_update_layered_window;
138  }
139  void SchedulePaintInRect(const gfx::Rect& rect);
140  void SetOpacity(BYTE opacity);
141
142  void SetWindowIcons(const gfx::ImageSkia& window_icon,
143                      const gfx::ImageSkia& app_icon);
144
145  void set_remove_standard_frame(bool remove_standard_frame) {
146    remove_standard_frame_ = remove_standard_frame;
147  }
148
149  void set_use_system_default_icon(bool use_system_default_icon) {
150    use_system_default_icon_ = use_system_default_icon;
151  }
152
153 private:
154  typedef std::set<DWORD> TouchIDs;
155
156  // Overridden from internal::InputMethodDelegate:
157  virtual void DispatchKeyEventPostIME(const ui::KeyEvent& key) OVERRIDE;
158
159  // Overridden from WindowImpl:
160  virtual HICON GetDefaultWindowIcon() const OVERRIDE;
161  virtual LRESULT OnWndProc(UINT message,
162                            WPARAM w_param,
163                            LPARAM l_param) OVERRIDE;
164
165  // Overridden from MessageLoopForUI::Observer:
166  virtual base::EventStatus WillProcessEvent(
167      const base::NativeEvent& event) OVERRIDE;
168  virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE;
169
170  // Returns the auto-hide edges of the appbar. See Appbar::GetAutohideEdges()
171  // for details. If the edges change OnAppbarAutohideEdgesChanged() is called.
172  int GetAppbarAutohideEdges(HMONITOR monitor);
173
174  // Callback if the autohide edges have changed. See Appbar for details.
175  void OnAppbarAutohideEdgesChanged();
176
177  // Can be called after the delegate has had the opportunity to set focus and
178  // did not do so.
179  void SetInitialFocus();
180
181  // Called after the WM_ACTIVATE message has been processed by the default
182  // windows procedure.
183  void PostProcessActivateMessage(int activation_state, bool minimized);
184
185  // Enables disabled owner windows that may have been disabled due to this
186  // window's modality.
187  void RestoreEnabledIfNecessary();
188
189  // Executes the specified SC_command.
190  void ExecuteSystemMenuCommand(int command);
191
192  // Start tracking all mouse events so that this window gets sent mouse leave
193  // messages too.
194  void TrackMouseEvents(DWORD mouse_tracking_flags);
195
196  // Responds to the client area changing size, either at window creation time
197  // or subsequently.
198  void ClientAreaSizeChanged();
199
200  // Returns the insets of the client area relative to the non-client area of
201  // the window.
202  bool GetClientAreaInsets(gfx::Insets* insets) const;
203
204  // Resets the window region for the current widget bounds if necessary.
205  // If |force| is true, the window region is reset to NULL even for native
206  // frame windows.
207  void ResetWindowRegion(bool force);
208
209  // Calls DefWindowProc, safely wrapping the call in a ScopedRedrawLock to
210  // prevent frame flicker. DefWindowProc handling can otherwise render the
211  // classic-look window title bar directly.
212  LRESULT DefWindowProcWithRedrawLock(UINT message,
213                                      WPARAM w_param,
214                                      LPARAM l_param);
215
216  // Notifies any owned windows that we're closing.
217  void NotifyOwnedWindowsParentClosing();
218
219  // Lock or unlock the window from being able to redraw itself in response to
220  // updates to its invalid region.
221  class ScopedRedrawLock;
222  void LockUpdates(bool force);
223  void UnlockUpdates(bool force);
224
225  // Stops ignoring SetWindowPos() requests (see below).
226  void StopIgnoringPosChanges() { ignore_window_pos_changes_ = false; }
227
228  // Synchronously paints the invalid contents of the Widget.
229  void RedrawInvalidRect();
230
231  // Synchronously updates the invalid contents of the Widget. Valid for
232  // layered windows only.
233  void RedrawLayeredWindowContents();
234
235  // Message Handlers ----------------------------------------------------------
236
237  BEGIN_MSG_MAP_EX(HWNDMessageHandler)
238    // Range handlers must go first!
239    MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange)
240    MESSAGE_RANGE_HANDLER_EX(WM_NCMOUSEMOVE, WM_NCXBUTTONDBLCLK, OnMouseRange)
241
242    // CustomFrameWindow hacks
243    MESSAGE_HANDLER_EX(WM_NCUAHDRAWCAPTION, OnNCUAHDrawCaption)
244    MESSAGE_HANDLER_EX(WM_NCUAHDRAWFRAME, OnNCUAHDrawFrame)
245
246    // Vista and newer
247    MESSAGE_HANDLER_EX(WM_DWMCOMPOSITIONCHANGED, OnDwmCompositionChanged)
248
249    // Non-atlcrack.h handlers
250    MESSAGE_HANDLER_EX(WM_GETOBJECT, OnGetObject)
251
252    // Mouse events.
253    MESSAGE_HANDLER_EX(WM_MOUSEACTIVATE, OnMouseActivate)
254    MESSAGE_HANDLER_EX(WM_MOUSELEAVE, OnMouseRange)
255    MESSAGE_HANDLER_EX(WM_NCMOUSELEAVE, OnMouseRange)
256    MESSAGE_HANDLER_EX(WM_SETCURSOR, OnSetCursor);
257
258    // Key events.
259    MESSAGE_HANDLER_EX(WM_KEYDOWN, OnKeyEvent)
260    MESSAGE_HANDLER_EX(WM_KEYUP, OnKeyEvent)
261    MESSAGE_HANDLER_EX(WM_SYSKEYDOWN, OnKeyEvent)
262    MESSAGE_HANDLER_EX(WM_SYSKEYUP, OnKeyEvent)
263
264    // IME Events.
265    MESSAGE_HANDLER_EX(WM_IME_SETCONTEXT, OnImeMessages)
266    MESSAGE_HANDLER_EX(WM_IME_STARTCOMPOSITION, OnImeMessages)
267    MESSAGE_HANDLER_EX(WM_IME_COMPOSITION, OnImeMessages)
268    MESSAGE_HANDLER_EX(WM_IME_ENDCOMPOSITION, OnImeMessages)
269    MESSAGE_HANDLER_EX(WM_IME_REQUEST, OnImeMessages)
270    MESSAGE_HANDLER_EX(WM_IME_NOTIFY, OnImeMessages)
271    MESSAGE_HANDLER_EX(WM_CHAR, OnImeMessages)
272    MESSAGE_HANDLER_EX(WM_SYSCHAR, OnImeMessages)
273    MESSAGE_HANDLER_EX(WM_DEADCHAR, OnImeMessages)
274    MESSAGE_HANDLER_EX(WM_SYSDEADCHAR, OnImeMessages)
275
276    // Touch Events.
277    MESSAGE_HANDLER_EX(WM_TOUCH, OnTouchEvent)
278
279    // Uses the general handler macro since the specific handler macro
280    // MSG_WM_NCACTIVATE would convert WPARAM type to BOOL type. The high
281    // word of WPARAM could be set when the window is minimized or restored.
282    MESSAGE_HANDLER_EX(WM_NCACTIVATE, OnNCActivate)
283
284    // This list is in _ALPHABETICAL_ order! OR I WILL HURT YOU.
285    MSG_WM_ACTIVATEAPP(OnActivateApp)
286    MSG_WM_APPCOMMAND(OnAppCommand)
287    MSG_WM_CANCELMODE(OnCancelMode)
288    MSG_WM_CAPTURECHANGED(OnCaptureChanged)
289    MSG_WM_CLOSE(OnClose)
290    MSG_WM_COMMAND(OnCommand)
291    MSG_WM_CREATE(OnCreate)
292    MSG_WM_DESTROY(OnDestroy)
293    MSG_WM_DISPLAYCHANGE(OnDisplayChange)
294    MSG_WM_ENTERSIZEMOVE(OnEnterSizeMove)
295    MSG_WM_ERASEBKGND(OnEraseBkgnd)
296    MSG_WM_EXITSIZEMOVE(OnExitSizeMove)
297    MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo)
298    MSG_WM_INITMENU(OnInitMenu)
299    MSG_WM_INPUTLANGCHANGE(OnInputLangChange)
300    MSG_WM_KILLFOCUS(OnKillFocus)
301    MSG_WM_MOVE(OnMove)
302    MSG_WM_MOVING(OnMoving)
303    MSG_WM_NCCALCSIZE(OnNCCalcSize)
304    MSG_WM_NCHITTEST(OnNCHitTest)
305    MSG_WM_NCPAINT(OnNCPaint)
306    MSG_WM_NOTIFY(OnNotify)
307    MSG_WM_PAINT(OnPaint)
308    MSG_WM_SETFOCUS(OnSetFocus)
309    MSG_WM_SETICON(OnSetIcon)
310    MSG_WM_SETTEXT(OnSetText)
311    MSG_WM_SETTINGCHANGE(OnSettingChange)
312    MSG_WM_SIZE(OnSize)
313    MSG_WM_SYSCOMMAND(OnSysCommand)
314    MSG_WM_THEMECHANGED(OnThemeChanged)
315    MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged)
316    MSG_WM_WINDOWPOSCHANGING(OnWindowPosChanging)
317  END_MSG_MAP()
318
319  // Message Handlers.
320  // This list is in _ALPHABETICAL_ order!
321  // TODO(beng): Once this object becomes the WindowImpl, these methods can
322  //             be made private.
323  void OnActivateApp(BOOL active, DWORD thread_id);
324  // TODO(beng): return BOOL is temporary until this object becomes a
325  //             WindowImpl.
326  BOOL OnAppCommand(HWND window, short command, WORD device, int keystate);
327  void OnCancelMode();
328  void OnCaptureChanged(HWND window);
329  void OnClose();
330  void OnCommand(UINT notification_code, int command, HWND window);
331  LRESULT OnCreate(CREATESTRUCT* create_struct);
332  void OnDestroy();
333  void OnDisplayChange(UINT bits_per_pixel, const CSize& screen_size);
334  LRESULT OnDwmCompositionChanged(UINT msg, WPARAM w_param, LPARAM l_param);
335  void OnEnterSizeMove();
336  LRESULT OnEraseBkgnd(HDC dc);
337  void OnExitSizeMove();
338  void OnGetMinMaxInfo(MINMAXINFO* minmax_info);
339  LRESULT OnGetObject(UINT message, WPARAM w_param, LPARAM l_param);
340  LRESULT OnImeMessages(UINT message, WPARAM w_param, LPARAM l_param);
341  void OnInitMenu(HMENU menu);
342  void OnInputLangChange(DWORD character_set, HKL input_language_id);
343  LRESULT OnKeyEvent(UINT message, WPARAM w_param, LPARAM l_param);
344  void OnKillFocus(HWND focused_window);
345  LRESULT OnMouseActivate(UINT message, WPARAM w_param, LPARAM l_param);
346  LRESULT OnMouseRange(UINT message, WPARAM w_param, LPARAM l_param);
347  void OnMove(const CPoint& point);
348  void OnMoving(UINT param, const RECT* new_bounds);
349  LRESULT OnNCActivate(UINT message, WPARAM w_param, LPARAM l_param);
350  LRESULT OnNCCalcSize(BOOL mode, LPARAM l_param);
351  LRESULT OnNCHitTest(const CPoint& point);
352  void OnNCPaint(HRGN rgn);
353  LRESULT OnNCUAHDrawCaption(UINT message, WPARAM w_param, LPARAM l_param);
354  LRESULT OnNCUAHDrawFrame(UINT message, WPARAM w_param, LPARAM l_param);
355  LRESULT OnNotify(int w_param, NMHDR* l_param);
356  void OnPaint(HDC dc);
357  LRESULT OnReflectedMessage(UINT message, WPARAM w_param, LPARAM l_param);
358  LRESULT OnSetCursor(UINT message, WPARAM w_param, LPARAM l_param);
359  void OnSetFocus(HWND last_focused_window);
360  LRESULT OnSetIcon(UINT size_type, HICON new_icon);
361  LRESULT OnSetText(const wchar_t* text);
362  void OnSettingChange(UINT flags, const wchar_t* section);
363  void OnSize(UINT param, const CSize& size);
364  void OnSysCommand(UINT notification_code, const CPoint& point);
365  void OnThemeChanged();
366  LRESULT OnTouchEvent(UINT message, WPARAM w_param, LPARAM l_param);
367  void OnWindowPosChanging(WINDOWPOS* window_pos);
368  void OnWindowPosChanged(WINDOWPOS* window_pos);
369
370  typedef std::vector<ui::TouchEvent> TouchEvents;
371  // Helper to handle the list of touch events passed in. We need this because
372  // touch events on windows don't fire if we enter a modal loop in the context
373  // of a touch event.
374  void HandleTouchEvents(const TouchEvents& touch_events);
375
376  HWNDMessageHandlerDelegate* delegate_;
377
378  scoped_ptr<FullscreenHandler> fullscreen_handler_;
379
380  base::WeakPtrFactory<HWNDMessageHandler> weak_factory_;
381
382  // Set to true in Close() and false is CloseNow().
383  bool waiting_for_close_now_;
384
385  bool remove_standard_frame_;
386
387  bool use_system_default_icon_;
388
389  // Whether the focus should be restored next time we get enabled.  Needed to
390  // restore focus correctly when Windows modal dialogs are displayed.
391  bool restore_focus_when_enabled_;
392
393  // Whether all ancestors have been enabled. This is only used if is_modal_ is
394  // true.
395  bool restored_enabled_;
396
397  // The last cursor that was active before the current one was selected. Saved
398  // so that we can restore it.
399  HCURSOR previous_cursor_;
400
401  // Event handling ------------------------------------------------------------
402
403  // The flags currently being used with TrackMouseEvent to track mouse
404  // messages. 0 if there is no active tracking. The value of this member is
405  // used when tracking is canceled.
406  DWORD active_mouse_tracking_flags_;
407
408  // Set to true when the user presses the right mouse button on the caption
409  // area. We need this so we can correctly show the context menu on mouse-up.
410  bool is_right_mouse_pressed_on_caption_;
411
412  // The set of touch devices currently down.
413  TouchIDs touch_ids_;
414
415  // ScopedRedrawLock ----------------------------------------------------------
416
417  // Represents the number of ScopedRedrawLocks active against this widget.
418  // If this is greater than zero, the widget should be locked against updates.
419  int lock_updates_count_;
420
421  // Window resizing -----------------------------------------------------------
422
423  // When true, this flag makes us discard incoming SetWindowPos() requests that
424  // only change our position/size.  (We still allow changes to Z-order,
425  // activation, etc.)
426  bool ignore_window_pos_changes_;
427
428  // The last-seen monitor containing us, and its rect and work area.  These are
429  // used to catch updates to the rect and work area and react accordingly.
430  HMONITOR last_monitor_;
431  gfx::Rect last_monitor_rect_, last_work_area_;
432
433  // Layered windows -----------------------------------------------------------
434
435  // Should we keep an off-screen buffer? This is false by default, set to true
436  // when WS_EX_LAYERED is specified before the native window is created.
437  //
438  // NOTE: this is intended to be used with a layered window (a window with an
439  // extended window style of WS_EX_LAYERED). If you are using a layered window
440  // and NOT changing the layered alpha or anything else, then leave this value
441  // alone. OTOH if you are invoking SetLayeredWindowAttributes then you'll
442  // most likely want to set this to false, or after changing the alpha toggle
443  // the extended style bit to false than back to true. See MSDN for more
444  // details.
445  bool use_layered_buffer_;
446
447  // The default alpha to be applied to the layered window.
448  BYTE layered_alpha_;
449
450  // A canvas that contains the window contents in the case of a layered
451  // window.
452  scoped_ptr<gfx::Canvas> layered_window_contents_;
453
454  // We must track the invalid rect ourselves, for two reasons:
455  // For layered windows, Windows will not do this properly with
456  // InvalidateRect()/GetUpdateRect(). (In fact, it'll return misleading
457  // information from GetUpdateRect()).
458  // We also need to keep track of the invalid rectangle for the RootView should
459  // we need to paint the non-client area. The data supplied to WM_NCPAINT seems
460  // to be insufficient.
461  gfx::Rect invalid_rect_;
462
463  // Set to true when waiting for RedrawLayeredWindowContents().
464  bool waiting_for_redraw_layered_window_contents_;
465
466  // True if we are allowed to update the layered window from the DIB backing
467  // store if necessary.
468  bool can_update_layered_window_;
469
470  // True the first time nccalc is called on a sizable widget
471  bool is_first_nccalc_;
472
473  // A factory used to lookup appbar autohide edges.
474  base::WeakPtrFactory<HWNDMessageHandler> autohide_factory_;
475
476  // Generates touch-ids for touch-events.
477  ui::SequentialIDGenerator id_generator_;
478
479  DISALLOW_COPY_AND_ASSIGN(HWNDMessageHandler);
480};
481
482}  // namespace views
483
484#endif  // UI_VIEWS_WIN_HWND_MESSAGE_HANDLER_H_
485