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