blob: c1c724cd1db842944d6737ae577932a5f00bdffd [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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"
Ben Murdochca12bfa2013-07-23 11:17:05 +010019#include "base/message_loop/message_loop.h"
Torne (Richard Coles)5e3f23d2013-06-11 16:24:11 +010020#include "base/strings/string16.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000021#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.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010058class VIEWS_EXPORT HWNDMessageHandler :
59 public ui::WindowImpl,
60 public internal::InputMethodDelegate,
61 public base::MessageLoopForUI::Observer {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000062 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
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010078 void SetBounds(const gfx::Rect& bounds_in_pixels);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000079 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
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000128 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
Ben Murdocheb525c52013-07-10 11:40:50 +0100167 // Returns the auto-hide edges of the appbar. See Appbar::GetAutohideEdges()
168 // for details. If the edges change OnAppbarAutohideEdgesChanged() is called.
169 int GetAppbarAutohideEdges(HMONITOR monitor);
170
171 // Callback if the autohide edges have changed. See Appbar for details.
172 void OnAppbarAutohideEdgesChanged();
173
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000174 // Can be called after the delegate has had the opportunity to set focus and
175 // did not do so.
176 void SetInitialFocus();
177
178 // Called after the WM_ACTIVATE message has been processed by the default
179 // windows procedure.
180 void PostProcessActivateMessage(int activation_state);
181
182 // Enables disabled owner windows that may have been disabled due to this
183 // window's modality.
184 void RestoreEnabledIfNecessary();
185
186 // Executes the specified SC_command.
187 void ExecuteSystemMenuCommand(int command);
188
189 // Start tracking all mouse events so that this window gets sent mouse leave
190 // messages too.
191 void TrackMouseEvents(DWORD mouse_tracking_flags);
192
193 // Responds to the client area changing size, either at window creation time
194 // or subsequently.
195 void ClientAreaSizeChanged();
196
197 // Returns the insets of the client area relative to the non-client area of
198 // the window.
Ben Murdochbb1529c2013-08-08 10:24:53 +0100199 bool GetClientAreaInsets(gfx::Insets* insets) const;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000200
201 // Resets the window region for the current widget bounds if necessary.
202 // If |force| is true, the window region is reset to NULL even for native
203 // frame windows.
204 void ResetWindowRegion(bool force);
205
206 // Calls DefWindowProc, safely wrapping the call in a ScopedRedrawLock to
207 // prevent frame flicker. DefWindowProc handling can otherwise render the
208 // classic-look window title bar directly.
209 LRESULT DefWindowProcWithRedrawLock(UINT message,
210 WPARAM w_param,
211 LPARAM l_param);
212
213 // Notifies any owned windows that we're closing.
214 void NotifyOwnedWindowsParentClosing();
215
216 // Lock or unlock the window from being able to redraw itself in response to
217 // updates to its invalid region.
218 class ScopedRedrawLock;
219 void LockUpdates(bool force);
220 void UnlockUpdates(bool force);
221
222 // Stops ignoring SetWindowPos() requests (see below).
223 void StopIgnoringPosChanges() { ignore_window_pos_changes_ = false; }
224
225 // Synchronously paints the invalid contents of the Widget.
226 void RedrawInvalidRect();
227
228 // Synchronously updates the invalid contents of the Widget. Valid for
229 // layered windows only.
230 void RedrawLayeredWindowContents();
231
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000232 // Message Handlers ----------------------------------------------------------
233
234 BEGIN_MSG_MAP_EX(HWNDMessageHandler)
235 // Range handlers must go first!
236 MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange)
237 MESSAGE_RANGE_HANDLER_EX(WM_NCMOUSEMOVE, WM_NCXBUTTONDBLCLK, OnMouseRange)
238
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000239 // CustomFrameWindow hacks
240 MESSAGE_HANDLER_EX(WM_NCUAHDRAWCAPTION, OnNCUAHDrawCaption)
241 MESSAGE_HANDLER_EX(WM_NCUAHDRAWFRAME, OnNCUAHDrawFrame)
242
243 // Vista and newer
244 MESSAGE_HANDLER_EX(WM_DWMCOMPOSITIONCHANGED, OnDwmCompositionChanged)
245
246 // Non-atlcrack.h handlers
247 MESSAGE_HANDLER_EX(WM_GETOBJECT, OnGetObject)
248
249 // Mouse events.
250 MESSAGE_HANDLER_EX(WM_MOUSEACTIVATE, OnMouseActivate)
251 MESSAGE_HANDLER_EX(WM_MOUSELEAVE, OnMouseRange)
252 MESSAGE_HANDLER_EX(WM_NCMOUSELEAVE, OnMouseRange)
253 MESSAGE_HANDLER_EX(WM_SETCURSOR, OnSetCursor);
254
255 // Key events.
256 MESSAGE_HANDLER_EX(WM_KEYDOWN, OnKeyEvent)
257 MESSAGE_HANDLER_EX(WM_KEYUP, OnKeyEvent)
258 MESSAGE_HANDLER_EX(WM_SYSKEYDOWN, OnKeyEvent)
259 MESSAGE_HANDLER_EX(WM_SYSKEYUP, OnKeyEvent)
260
261 // IME Events.
262 MESSAGE_HANDLER_EX(WM_IME_SETCONTEXT, OnImeMessages)
263 MESSAGE_HANDLER_EX(WM_IME_STARTCOMPOSITION, OnImeMessages)
264 MESSAGE_HANDLER_EX(WM_IME_COMPOSITION, OnImeMessages)
265 MESSAGE_HANDLER_EX(WM_IME_ENDCOMPOSITION, OnImeMessages)
266 MESSAGE_HANDLER_EX(WM_IME_REQUEST, OnImeMessages)
Ben Murdocheb525c52013-07-10 11:40:50 +0100267 MESSAGE_HANDLER_EX(WM_IME_NOTIFY, OnImeMessages)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000268 MESSAGE_HANDLER_EX(WM_CHAR, OnImeMessages)
269 MESSAGE_HANDLER_EX(WM_SYSCHAR, OnImeMessages)
270 MESSAGE_HANDLER_EX(WM_DEADCHAR, OnImeMessages)
271 MESSAGE_HANDLER_EX(WM_SYSDEADCHAR, OnImeMessages)
272
273 // Touch Events.
274 MESSAGE_HANDLER_EX(WM_TOUCH, OnTouchEvent)
275
Ben Murdocheb525c52013-07-10 11:40:50 +0100276 // Uses the general handler macro since the specific handler macro
277 // MSG_WM_NCACTIVATE would convert WPARAM type to BOOL type. The high
278 // word of WPARAM could be set when the window is minimized or restored.
279 MESSAGE_HANDLER_EX(WM_NCACTIVATE, OnNCActivate)
280
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000281 // This list is in _ALPHABETICAL_ order! OR I WILL HURT YOU.
282 MSG_WM_ACTIVATEAPP(OnActivateApp)
283 MSG_WM_APPCOMMAND(OnAppCommand)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000284 MSG_WM_CANCELMODE(OnCancelMode)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000285 MSG_WM_CAPTURECHANGED(OnCaptureChanged)
286 MSG_WM_CLOSE(OnClose)
287 MSG_WM_COMMAND(OnCommand)
288 MSG_WM_CREATE(OnCreate)
289 MSG_WM_DESTROY(OnDestroy)
290 MSG_WM_DISPLAYCHANGE(OnDisplayChange)
291 MSG_WM_ERASEBKGND(OnEraseBkgnd)
292 MSG_WM_ENTERSIZEMOVE(OnEnterSizeMove)
293 MSG_WM_EXITSIZEMOVE(OnExitSizeMove)
294 MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo)
295 MSG_WM_INITMENU(OnInitMenu)
296 MSG_WM_INPUTLANGCHANGE(OnInputLangChange)
297 MSG_WM_KILLFOCUS(OnKillFocus)
298 MSG_WM_MOVE(OnMove)
299 MSG_WM_MOVING(OnMoving)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000300 MSG_WM_NCCALCSIZE(OnNCCalcSize)
301 MSG_WM_NCHITTEST(OnNCHitTest)
302 MSG_WM_NCPAINT(OnNCPaint)
303 MSG_WM_NOTIFY(OnNotify)
304 MSG_WM_PAINT(OnPaint)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000305 MSG_WM_SETFOCUS(OnSetFocus)
306 MSG_WM_SETICON(OnSetIcon)
307 MSG_WM_SETTEXT(OnSetText)
308 MSG_WM_SETTINGCHANGE(OnSettingChange)
309 MSG_WM_SIZE(OnSize)
310 MSG_WM_SYSCOMMAND(OnSysCommand)
311 MSG_WM_THEMECHANGED(OnThemeChanged)
312 MSG_WM_WINDOWPOSCHANGING(OnWindowPosChanging)
313 MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged)
314 END_MSG_MAP()
315
316 // Message Handlers.
317 // This list is in _ALPHABETICAL_ order!
318 // TODO(beng): Once this object becomes the WindowImpl, these methods can
319 // be made private.
320 void OnActivateApp(BOOL active, DWORD thread_id);
321 // TODO(beng): return BOOL is temporary until this object becomes a
322 // WindowImpl.
323 BOOL OnAppCommand(HWND window, short command, WORD device, int keystate);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000324 void OnCancelMode();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000325 void OnCaptureChanged(HWND window);
326 void OnClose();
327 void OnCommand(UINT notification_code, int command, HWND window);
328 LRESULT OnCreate(CREATESTRUCT* create_struct);
329 void OnDestroy();
330 void OnDisplayChange(UINT bits_per_pixel, const CSize& screen_size);
331 LRESULT OnDwmCompositionChanged(UINT msg, WPARAM w_param, LPARAM l_param);
332 void OnEnterSizeMove();
333 LRESULT OnEraseBkgnd(HDC dc);
334 void OnExitSizeMove();
335 void OnGetMinMaxInfo(MINMAXINFO* minmax_info);
336 LRESULT OnGetObject(UINT message, WPARAM w_param, LPARAM l_param);
337 LRESULT OnImeMessages(UINT message, WPARAM w_param, LPARAM l_param);
338 void OnInitMenu(HMENU menu);
339 void OnInputLangChange(DWORD character_set, HKL input_language_id);
340 LRESULT OnKeyEvent(UINT message, WPARAM w_param, LPARAM l_param);
341 void OnKillFocus(HWND focused_window);
342 LRESULT OnMouseActivate(UINT message, WPARAM w_param, LPARAM l_param);
343 LRESULT OnMouseRange(UINT message, WPARAM w_param, LPARAM l_param);
344 void OnMove(const CPoint& point);
345 void OnMoving(UINT param, const RECT* new_bounds);
Ben Murdocheb525c52013-07-10 11:40:50 +0100346 LRESULT OnNCActivate(UINT message, WPARAM w_param, LPARAM l_param);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000347 LRESULT OnNCCalcSize(BOOL mode, LPARAM l_param);
348 LRESULT OnNCHitTest(const CPoint& point);
349 void OnNCPaint(HRGN rgn);
350 LRESULT OnNCUAHDrawCaption(UINT message, WPARAM w_param, LPARAM l_param);
351 LRESULT OnNCUAHDrawFrame(UINT message, WPARAM w_param, LPARAM l_param);
352 LRESULT OnNotify(int w_param, NMHDR* l_param);
353 void OnPaint(HDC dc);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000354 LRESULT OnReflectedMessage(UINT message, WPARAM w_param, LPARAM l_param);
355 LRESULT OnSetCursor(UINT message, WPARAM w_param, LPARAM l_param);
356 void OnSetFocus(HWND last_focused_window);
357 LRESULT OnSetIcon(UINT size_type, HICON new_icon);
358 LRESULT OnSetText(const wchar_t* text);
359 void OnSettingChange(UINT flags, const wchar_t* section);
360 void OnSize(UINT param, const CSize& size);
361 void OnSysCommand(UINT notification_code, const CPoint& point);
362 void OnThemeChanged();
363 LRESULT OnTouchEvent(UINT message, WPARAM w_param, LPARAM l_param);
364 void OnWindowPosChanging(WINDOWPOS* window_pos);
365 void OnWindowPosChanged(WINDOWPOS* window_pos);
366
367 HWNDMessageHandlerDelegate* delegate_;
368
369 scoped_ptr<FullscreenHandler> fullscreen_handler_;
370
371 base::WeakPtrFactory<HWNDMessageHandler> close_widget_factory_;
372
373 bool remove_standard_frame_;
374
375 bool use_system_default_icon_;
376
377 // Whether the focus should be restored next time we get enabled. Needed to
378 // restore focus correctly when Windows modal dialogs are displayed.
379 bool restore_focus_when_enabled_;
380
381 // Whether all ancestors have been enabled. This is only used if is_modal_ is
382 // true.
383 bool restored_enabled_;
384
385 // The last cursor that was active before the current one was selected. Saved
386 // so that we can restore it.
387 HCURSOR previous_cursor_;
388
389 // Event handling ------------------------------------------------------------
390
391 // The flags currently being used with TrackMouseEvent to track mouse
392 // messages. 0 if there is no active tracking. The value of this member is
393 // used when tracking is canceled.
394 DWORD active_mouse_tracking_flags_;
395
396 // Set to true when the user presses the right mouse button on the caption
397 // area. We need this so we can correctly show the context menu on mouse-up.
398 bool is_right_mouse_pressed_on_caption_;
399
400 // The set of touch devices currently down.
401 TouchIDs touch_ids_;
402
403 // ScopedRedrawLock ----------------------------------------------------------
404
405 // Represents the number of ScopedRedrawLocks active against this widget.
406 // If this is greater than zero, the widget should be locked against updates.
407 int lock_updates_count_;
408
409 // This flag can be initialized and checked after certain operations (such as
410 // DefWindowProc) to avoid stack-controlled functions (such as unlocking the
411 // Window with a ScopedRedrawLock) after destruction.
412 bool* destroyed_;
413
414 // Window resizing -----------------------------------------------------------
415
416 // When true, this flag makes us discard incoming SetWindowPos() requests that
417 // only change our position/size. (We still allow changes to Z-order,
418 // activation, etc.)
419 bool ignore_window_pos_changes_;
420
421 // The following factory is used to ignore SetWindowPos() calls for short time
422 // periods.
423 base::WeakPtrFactory<HWNDMessageHandler> ignore_pos_changes_factory_;
424
425 // The last-seen monitor containing us, and its rect and work area. These are
426 // used to catch updates to the rect and work area and react accordingly.
427 HMONITOR last_monitor_;
428 gfx::Rect last_monitor_rect_, last_work_area_;
429
430 // Layered windows -----------------------------------------------------------
431
432 // Should we keep an off-screen buffer? This is false by default, set to true
433 // when WS_EX_LAYERED is specified before the native window is created.
434 //
435 // NOTE: this is intended to be used with a layered window (a window with an
436 // extended window style of WS_EX_LAYERED). If you are using a layered window
437 // and NOT changing the layered alpha or anything else, then leave this value
438 // alone. OTOH if you are invoking SetLayeredWindowAttributes then you'll
439 // most likely want to set this to false, or after changing the alpha toggle
440 // the extended style bit to false than back to true. See MSDN for more
441 // details.
442 bool use_layered_buffer_;
443
444 // The default alpha to be applied to the layered window.
445 BYTE layered_alpha_;
446
447 // A canvas that contains the window contents in the case of a layered
448 // window.
449 scoped_ptr<gfx::Canvas> layered_window_contents_;
450
451 // We must track the invalid rect ourselves, for two reasons:
452 // For layered windows, Windows will not do this properly with
453 // InvalidateRect()/GetUpdateRect(). (In fact, it'll return misleading
454 // information from GetUpdateRect()).
455 // We also need to keep track of the invalid rectangle for the RootView should
456 // we need to paint the non-client area. The data supplied to WM_NCPAINT seems
457 // to be insufficient.
458 gfx::Rect invalid_rect_;
459
460 // A factory that allows us to schedule a redraw for layered windows.
461 base::WeakPtrFactory<HWNDMessageHandler> paint_layered_window_factory_;
462
463 // True if we are allowed to update the layered window from the DIB backing
464 // store if necessary.
465 bool can_update_layered_window_;
466
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000467 // True the first time nccalc is called on a sizable widget
468 bool is_first_nccalc_;
469
Ben Murdocheb525c52013-07-10 11:40:50 +0100470 // A factory used to lookup appbar autohide edges.
471 base::WeakPtrFactory<HWNDMessageHandler> autohide_factory_;
472
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000473 DISALLOW_COPY_AND_ASSIGN(HWNDMessageHandler);
474};
475
476} // namespace views
477
478#endif // UI_VIEWS_WIN_HWND_MESSAGE_HANDLER_H_