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