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/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 29 namespace gfx { 30 class Canvas; 31 class ImageSkia; 32 class Insets; 33 } 34 35 namespace views { 36 37 class FullscreenHandler; 38 class HWNDMessageHandlerDelegate; 39 class 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. 49 const int WM_NCUAHDRAWCAPTION = 0xAE; 50 const 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. 58 class 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_in_pixels); 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 // 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 174 // 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. 199 bool GetClientAreaInsets(gfx::Insets* insets) const; 200 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 232 // 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 239 // 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) 267 MESSAGE_HANDLER_EX(WM_IME_NOTIFY, OnImeMessages) 268 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 276 // 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 281 // This list is in _ALPHABETICAL_ order! OR I WILL HURT YOU. 282 MSG_WM_ACTIVATEAPP(OnActivateApp) 283 MSG_WM_APPCOMMAND(OnAppCommand) 284 MSG_WM_CANCELMODE(OnCancelMode) 285 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) 300 MSG_WM_NCCALCSIZE(OnNCCalcSize) 301 MSG_WM_NCHITTEST(OnNCHitTest) 302 MSG_WM_NCPAINT(OnNCPaint) 303 MSG_WM_NOTIFY(OnNotify) 304 MSG_WM_PAINT(OnPaint) 305 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); 324 void OnCancelMode(); 325 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); 346 LRESULT OnNCActivate(UINT message, WPARAM w_param, LPARAM l_param); 347 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); 354 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 467 // True the first time nccalc is called on a sizable widget 468 bool is_first_nccalc_; 469 470 // A factory used to lookup appbar autohide edges. 471 base::WeakPtrFactory<HWNDMessageHandler> autohide_factory_; 472 473 DISALLOW_COPY_AND_ASSIGN(HWNDMessageHandler); 474 }; 475 476 } // namespace views 477 478 #endif // UI_VIEWS_WIN_HWND_MESSAGE_HANDLER_H_ 479