Home | History | Annotate | Download | only in win
      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