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