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