diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-21 19:24:44 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-21 19:24:44 +0000 |
commit | 4f2c7acdd25fb0eb251c0309921b77feb90998f6 (patch) | |
tree | aa8c0b86d142b17a96637b03340b61a737ce73a9 /ui | |
parent | 819c94b891cf5ca5250cd89c7870dc15eaa36d2f (diff) | |
download | chromium_src-4f2c7acdd25fb0eb251c0309921b77feb90998f6.zip chromium_src-4f2c7acdd25fb0eb251c0309921b77feb90998f6.tar.gz chromium_src-4f2c7acdd25fb0eb251c0309921b77feb90998f6.tar.bz2 |
Move more message handlers from NWW to HWNDMessageHandler.
http://crbug.com/142962
TBR=sky@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10832419
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@152607 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/views/widget/native_widget_win.cc | 328 | ||||
-rw-r--r-- | ui/views/widget/native_widget_win.h | 14 | ||||
-rw-r--r-- | ui/views/win/hwnd_message_handler.cc | 239 | ||||
-rw-r--r-- | ui/views/win/hwnd_message_handler.h | 17 | ||||
-rw-r--r-- | ui/views/win/hwnd_message_handler_delegate.h | 31 |
5 files changed, 400 insertions, 229 deletions
diff --git a/ui/views/widget/native_widget_win.cc b/ui/views/widget/native_widget_win.cc index 15e8d2c..be19bd1 100644 --- a/ui/views/widget/native_widget_win.cc +++ b/ui/views/widget/native_widget_win.cc @@ -238,30 +238,12 @@ BOOL CALLBACK SendDwmCompositionChanged(HWND window, LPARAM param) { return TRUE; } -// Tells the window its frame (non-client area) has changed. -void SendFrameChanged(HWND window) { - SetWindowPos(window, NULL, 0, 0, 0, 0, - SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOCOPYBITS | - SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREPOSITION | - SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER); -} - // Enables or disables the menu item for the specified command and menu. void EnableMenuItem(HMENU menu, UINT command, bool enabled) { UINT flags = MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_DISABLED | MF_GRAYED); EnableMenuItem(menu, command, flags); } -BOOL CALLBACK EnumChildWindowsForRedraw(HWND hwnd, LPARAM lparam) { - DWORD process_id; - GetWindowThreadProcessId(hwnd, &process_id); - int flags = RDW_INVALIDATE | RDW_NOCHILDREN | RDW_FRAME; - if (process_id == GetCurrentProcessId()) - flags |= RDW_UPDATENOW; - RedrawWindow(hwnd, NULL, NULL, flags); - return TRUE; -} - // See comments in OnNCPaint() for details of this struct. struct ClipState { // The window being painted. @@ -314,10 +296,6 @@ bool GetMonitorAndRects(const RECT& rect, // Links the HWND to its NativeWidget. const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__"; -// A custom MSAA object id used to determine if a screen reader is actively -// listening for MSAA events. -const int kCustomObjectID = 1; - const int kDragFrameWindowAlpha = 200; struct FindOwnedWindowsData { @@ -568,7 +546,7 @@ void NativeWidgetWin::FrameTypeChanged() { // Send a frame change notification, since the non-client metrics have // changed. - SendFrameChanged(GetNativeView()); + message_handler_->SendFrameChanged(); // Update the non-client view with the correct frame view for the active frame // type. @@ -940,7 +918,7 @@ void NativeWidgetWin::ShowWithWindowState(ui::WindowShowState show_state) { } bool NativeWidgetWin::IsVisible() const { - return !!::IsWindowVisible(hwnd()); + return message_handler_->IsVisible(); } void NativeWidgetWin::Activate() { @@ -958,7 +936,7 @@ void NativeWidgetWin::Deactivate() { } bool NativeWidgetWin::IsActive() const { - return GetActiveWindow() == hwnd(); + return message_handler_->IsActive(); } void NativeWidgetWin::SetAlwaysOnTop(bool on_top) { @@ -1292,70 +1270,7 @@ void NativeWidgetWin::OnCommand(UINT notification_code, } LRESULT NativeWidgetWin::OnCreate(CREATESTRUCT* create_struct) { - SetNativeWindowProperty(kNativeWidgetKey, this); - CHECK_EQ(this, GetNativeWidgetForNativeView(hwnd())); - - use_layered_buffer_ = !!(window_ex_style() & WS_EX_LAYERED); - - // Attempt to detect screen readers by sending an event with our custom id. - if (!IsAccessibleWidget()) - NotifyWinEvent(EVENT_SYSTEM_ALERT, hwnd(), kCustomObjectID, CHILDID_SELF); - - props_.push_back(ui::SetWindowSupportsRerouteMouseWheel(hwnd())); - - drop_target_ = new DropTargetWin( - static_cast<internal::RootView*>(GetWidget()->GetRootView())); - - // We need to add ourselves as a message loop observer so that we can repaint - // aggressively if the contents of our window become invalid. Unfortunately - // WM_PAINT messages are starved and we get flickery redrawing when resizing - // if we do not do this. - MessageLoopForUI::current()->AddObserver(this); - - // Windows special DWM window frame requires a special tooltip manager so - // that window controls in Chrome windows don't flicker when you move your - // mouse over them. See comment in aero_tooltip_manager.h. - Widget* widget = GetWidget()->GetTopLevelWidget(); - if (widget && widget->ShouldUseNativeFrame()) { - tooltip_manager_.reset(new AeroTooltipManager(GetWidget())); - } else { - tooltip_manager_.reset(new TooltipManagerWin(GetWidget())); - } - if (!tooltip_manager_->Init()) { - // There was a problem creating the TooltipManager. Common error is 127. - // See 82193 for details. - LOG_GETLASTERROR(WARNING) << "tooltip creation failed, disabling tooltips"; - tooltip_manager_.reset(); - } - - // This message initializes the window so that focus border are shown for - // windows. - SendMessage( - hwnd(), WM_CHANGEUISTATE, MAKELPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0); - - // Bug 964884: detach the IME attached to this window. - // We should attach IMEs only when we need to input CJK strings. - ImmAssociateContextEx(hwnd(), NULL, 0); - - if (message_handler_->remove_standard_frame()) { - SetWindowLong(GWL_STYLE, GetWindowLong(GWL_STYLE) & ~WS_CAPTION); - SendFrameChanged(GetNativeView()); - } - - // We need to allow the delegate to size its contents since the window may not - // receive a size notification when its initial bounds are specified at window - // creation time. - ClientAreaSizeChanged(); - - delegate_->OnNativeWidgetCreated(); - - // Get access to a modifiable copy of the system menu. - GetSystemMenu(hwnd(), false); - - if (base::win::GetVersion() >= base::win::VERSION_WIN7) - RegisterTouchWindow(hwnd(), 0); - - return 0; + return message_handler_->OnCreate(create_struct); } void NativeWidgetWin::OnDestroy() { @@ -1369,8 +1284,7 @@ void NativeWidgetWin::OnDisplayChange(UINT bits_per_pixel, CSize screen_size) { LRESULT NativeWidgetWin::OnDwmCompositionChanged(UINT msg, WPARAM w_param, LPARAM l_param) { - message_handler_->OnDwmCompositionChanged(msg, w_param, l_param); - return 0; + return message_handler_->OnDwmCompositionChanged(msg, w_param, l_param); } void NativeWidgetWin::OnEndSession(BOOL ending, UINT logoff) { @@ -1393,65 +1307,20 @@ void NativeWidgetWin::OnExitSizeMove() { message_handler_->OnExitSizeMove(); } -LRESULT NativeWidgetWin::OnGetObject(UINT uMsg, +LRESULT NativeWidgetWin::OnGetObject(UINT message, WPARAM w_param, LPARAM l_param) { - LRESULT reference_result = static_cast<LRESULT>(0L); - - // Accessibility readers will send an OBJID_CLIENT message - if (OBJID_CLIENT == l_param) { - // Retrieve MSAA dispatch object for the root view. - base::win::ScopedComPtr<IAccessible> root( - GetWidget()->GetRootView()->GetNativeViewAccessible()); - - // Create a reference that MSAA will marshall to the client. - reference_result = LresultFromObject(IID_IAccessible, w_param, - static_cast<IAccessible*>(root.Detach())); - } - - if (kCustomObjectID == l_param) { - // An MSAA client requestes our custom id. Assume that we have detected an - // active windows screen reader. - OnScreenReaderDetected(); - - // Return with failure. - return static_cast<LRESULT>(0L); - } - - return reference_result; + return message_handler_->OnGetObject(message, w_param, l_param); } void NativeWidgetWin::OnGetMinMaxInfo(MINMAXINFO* minmax_info) { - gfx::Size min_window_size(delegate_->GetMinimumSize()); - gfx::Size max_window_size(delegate_->GetMaximumSize()); - // Add the native frame border size to the minimum and maximum size if the - // view reports its size as the client size. - if (WidgetSizeIsClientSize()) { - CRect client_rect, window_rect; - GetClientRect(&client_rect); - GetWindowRect(&window_rect); - window_rect -= client_rect; - min_window_size.Enlarge(window_rect.Width(), window_rect.Height()); - if (!max_window_size.IsEmpty()) - max_window_size.Enlarge(window_rect.Width(), window_rect.Height()); - } - minmax_info->ptMinTrackSize.x = min_window_size.width(); - minmax_info->ptMinTrackSize.y = min_window_size.height(); - if (max_window_size.width() || max_window_size.height()) { - if (!max_window_size.width()) - max_window_size.set_width(GetSystemMetrics(SM_CXMAXTRACK)); - if (!max_window_size.height()) - max_window_size.set_height(GetSystemMetrics(SM_CYMAXTRACK)); - minmax_info->ptMaxTrackSize.x = max_window_size.width(); - minmax_info->ptMaxTrackSize.y = max_window_size.height(); - } - SetMsgHandled(FALSE); + message_handler_->OnGetMinMaxInfo(minmax_info); } void NativeWidgetWin::OnHScroll(int scroll_type, short position, HWND scrollbar) { - SetMsgHandled(FALSE); + message_handler_->OnHScroll(scroll_type, position, scrollbar); } LRESULT NativeWidgetWin::OnImeMessages(UINT message, @@ -1488,14 +1357,7 @@ void NativeWidgetWin::OnKillFocus(HWND focused_window) { LRESULT NativeWidgetWin::OnMouseActivate(UINT message, WPARAM w_param, LPARAM l_param) { - // TODO(beng): resolve this with the GetWindowLong() check on the subsequent - // line. - if (GetWidget()->non_client_view()) - return delegate_->CanActivate() ? MA_ACTIVATE : MA_NOACTIVATEANDEAT; - if (GetWindowLong(GWL_EXSTYLE) & WS_EX_NOACTIVATE) - return MA_NOACTIVATE; - SetMsgHandled(FALSE); - return MA_ACTIVATE; + return message_handler_->OnMouseActivate(message, w_param, l_param); } LRESULT NativeWidgetWin::OnMouseRange(UINT message, @@ -1598,50 +1460,7 @@ void NativeWidgetWin::OnMoving(UINT param, const LPRECT new_bounds) { } LRESULT NativeWidgetWin::OnNCActivate(BOOL active) { - if (delegate_->CanActivate()) - delegate_->OnNativeWidgetActivationChanged(!!active); - - if (!GetWidget()->non_client_view()) { - SetMsgHandled(FALSE); - return 0; - } - - if (!delegate_->CanActivate()) - return TRUE; - - // The frame may need to redraw as a result of the activation change. - // We can get WM_NCACTIVATE before we're actually visible. If we're not - // visible, no need to paint. - if (IsVisible()) - GetWidget()->non_client_view()->SchedulePaint(); - - if (!GetWidget()->ShouldUseNativeFrame()) { - // TODO(beng, et al): Hack to redraw this window and child windows - // synchronously upon activation. Not all child windows are redrawing - // themselves leading to issues like http://crbug.com/74604 - // We redraw out-of-process HWNDs asynchronously to avoid hanging the - // whole app if a child HWND belonging to a hung plugin is encountered. - RedrawWindow(GetNativeView(), NULL, NULL, - RDW_NOCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW); - EnumChildWindows(GetNativeView(), EnumChildWindowsForRedraw, NULL); - } - - // If we're active again, we should be allowed to render as inactive, so - // tell the non-client view. - bool inactive_rendering_disabled = delegate_->IsInactiveRenderingDisabled(); - if (IsActive()) - delegate_->EnableInactiveRendering(); - - // Avoid DefWindowProc non-client rendering over our custom frame on newer - // Windows versions only (breaks taskbar activation indication on XP/Vista). - if (!GetWidget()->ShouldUseNativeFrame() && - base::win::GetVersion() > base::win::VERSION_VISTA) { - SetMsgHandled(TRUE); - return TRUE; - } - - return DefWindowProcWithRedrawLock( - WM_NCACTIVATE, inactive_rendering_disabled || active, 0); + return message_handler_->OnNCActivate(active); } LRESULT NativeWidgetWin::OnNCCalcSize(BOOL mode, LPARAM l_param) { @@ -1827,17 +1646,7 @@ LRESULT NativeWidgetWin::OnNCUAHDrawFrame(UINT msg, } LRESULT NativeWidgetWin::OnNotify(int w_param, NMHDR* l_param) { - // We can be sent this message before the tooltip manager is created, if a - // subclass overrides OnCreate and creates some kind of Windows control there - // that sends WM_NOTIFY messages. - if (tooltip_manager_.get()) { - bool handled; - LRESULT result = tooltip_manager_->OnNotify(w_param, l_param, &handled); - SetMsgHandled(handled); - return result; - } - SetMsgHandled(FALSE); - return 0; + return message_handler_->OnNotify(w_param, l_param); } void NativeWidgetWin::OnPaint(HDC dc) { @@ -1867,8 +1676,7 @@ LRESULT NativeWidgetWin::OnPowerBroadcast(DWORD power_event, DWORD data) { LRESULT NativeWidgetWin::OnReflectedMessage(UINT msg, WPARAM w_param, LPARAM l_param) { - SetMsgHandled(FALSE); - return 0; + return message_handler_->OnReflectedMessage(msg, w_param, l_param); } LRESULT NativeWidgetWin::OnSetCursor(UINT message, @@ -1890,19 +1698,7 @@ LRESULT NativeWidgetWin::OnSetText(const wchar_t* text) { } void NativeWidgetWin::OnSettingChange(UINT flags, const wchar_t* section) { - if (!GetParent() && (flags == SPI_SETWORKAREA) && - !GetWidget()->widget_delegate()->WillProcessWorkAreaChange()) { - // Fire a dummy SetWindowPos() call, so we'll trip the code in - // OnWindowPosChanging() below that notices work area changes. - ::SetWindowPos(GetNativeView(), 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | - SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOOWNERZORDER); - SetMsgHandled(TRUE); - } else { - // TODO(beng): move to Widget. - if (flags == SPI_SETWORKAREA) - GetWidget()->widget_delegate()->OnWorkAreaChanged(); - SetMsgHandled(FALSE); - } + message_handler_->OnSettingChange(flags, section); } void NativeWidgetWin::OnSize(UINT param, const CSize& size) { @@ -2192,6 +1988,18 @@ bool NativeWidgetWin::IsUsingCustomFrame() const { return !GetWidget()->ShouldUseNativeFrame(); } +void NativeWidgetWin::SchedulePaint() { + GetWidget()->GetRootView()->SchedulePaint(); +} + +void NativeWidgetWin::EnableInactiveRendering() { + delegate_->EnableInactiveRendering(); +} + +bool NativeWidgetWin::IsInactiveRenderingDisabled() { + return delegate_->IsInactiveRenderingDisabled(); +} + bool NativeWidgetWin::CanResize() const { return GetWidget()->widget_delegate()->CanResize(); } @@ -2204,6 +2012,10 @@ bool NativeWidgetWin::CanActivate() const { return delegate_->CanActivate(); } +bool NativeWidgetWin::WillProcessWorkAreaChange() const { + return GetWidget()->widget_delegate()->WillProcessWorkAreaChange(); +} + int NativeWidgetWin::GetNonClientComponent(const gfx::Point& point) const { return delegate_->GetNonClientComponent(point); } @@ -2212,16 +2024,30 @@ void NativeWidgetWin::GetWindowMask(const gfx::Size& size, gfx::Path* path) { GetWidget()->non_client_view()->GetWindowMask(size, path); } +void NativeWidgetWin::GetMinMaxSize(gfx::Size* min_size, + gfx::Size* max_size) const { + *min_size = delegate_->GetMinimumSize(); + *max_size = delegate_->GetMaximumSize(); +} + InputMethod* NativeWidgetWin::GetInputMethod() { return GetWidget()->GetInputMethodDirect(); } +gfx::NativeViewAccessible NativeWidgetWin::GetNativeViewAccessible() { + return GetWidget()->GetRootView()->GetNativeViewAccessible(); +} + void NativeWidgetWin::HandleAppDeactivated() { // Another application was activated, we should reset any state that // disables inactive rendering now. delegate_->EnableInactiveRendering(); } +void NativeWidgetWin::HandleActivationChanged(bool active) { + delegate_->OnNativeWidgetActivationChanged(active); +} + bool NativeWidgetWin::HandleAppCommand(short command) { // We treat APPCOMMAND ids as an extension of our command namespace, and just // let the delegate figure out what to do... @@ -2241,6 +2067,49 @@ bool NativeWidgetWin::HandleCommand(int command) { return GetWidget()->widget_delegate()->ExecuteWindowsCommand(command); } +void NativeWidgetWin::HandleCreate() { + // TODO(beng): much of this could/should maybe move to HWNDMessageHandler. + + SetNativeWindowProperty(kNativeWidgetKey, this); + CHECK_EQ(this, GetNativeWidgetForNativeView(hwnd())); + + use_layered_buffer_ = !!(window_ex_style() & WS_EX_LAYERED); + + props_.push_back(ui::SetWindowSupportsRerouteMouseWheel(hwnd())); + + drop_target_ = new DropTargetWin( + static_cast<internal::RootView*>(GetWidget()->GetRootView())); + + // We need to add ourselves as a message loop observer so that we can repaint + // aggressively if the contents of our window become invalid. Unfortunately + // WM_PAINT messages are starved and we get flickery redrawing when resizing + // if we do not do this. + MessageLoopForUI::current()->AddObserver(this); + + // Windows special DWM window frame requires a special tooltip manager so + // that window controls in Chrome windows don't flicker when you move your + // mouse over them. See comment in aero_tooltip_manager.h. + Widget* widget = GetWidget()->GetTopLevelWidget(); + if (widget && widget->ShouldUseNativeFrame()) { + tooltip_manager_.reset(new AeroTooltipManager(GetWidget())); + } else { + tooltip_manager_.reset(new TooltipManagerWin(GetWidget())); + } + if (!tooltip_manager_->Init()) { + // There was a problem creating the TooltipManager. Common error is 127. + // See 82193 for details. + LOG_GETLASTERROR(WARNING) << "tooltip creation failed, disabling tooltips"; + tooltip_manager_.reset(); + } + + // We need to allow the delegate to size its contents since the window may not + // receive a size notification when its initial bounds are specified at window + // creation time. + ClientAreaSizeChanged(); + + delegate_->OnNativeWidgetCreated(); +} + void NativeWidgetWin::HandleDestroy() { delegate_->OnNativeWidgetDestroying(); if (drop_target_.get()) { @@ -2275,6 +2144,10 @@ void NativeWidgetWin::HandleMove() { delegate_->OnNativeWidgetMove(); } +void NativeWidgetWin::HandleWorkAreaChanged() { + GetWidget()->widget_delegate()->OnWorkAreaChanged(); +} + void NativeWidgetWin::HandleNativeFocus(HWND last_focused_window) { delegate_->OnNativeFocus(last_focused_window); } @@ -2283,6 +2156,25 @@ void NativeWidgetWin::HandleNativeBlur(HWND focused_window) { delegate_->OnNativeBlur(focused_window); } +void NativeWidgetWin::HandleScreenReaderDetected() { + // TODO(beng): just consolidate this with OnScreenReaderDetected. + OnScreenReaderDetected(); +} + +bool NativeWidgetWin::HandleTooltipNotify(int w_param, + NMHDR* l_param, + LRESULT* l_result) { + // We can be sent this message before the tooltip manager is created, if a + // subclass overrides OnCreate and creates some kind of Windows control there + // that sends WM_NOTIFY messages. + if (tooltip_manager_.get()) { + bool handled; + *l_result = tooltip_manager_->OnNotify(w_param, l_param, &handled); + return handled; + } + return false; +} + NativeWidgetWin* NativeWidgetWin::AsNativeWidgetWin() { return this; } diff --git a/ui/views/widget/native_widget_win.h b/ui/views/widget/native_widget_win.h index 7106448..26c8fbe 100644 --- a/ui/views/widget/native_widget_win.h +++ b/ui/views/widget/native_widget_win.h @@ -494,25 +494,39 @@ class VIEWS_EXPORT NativeWidgetWin : public ui::WindowImpl, // Overridden from HWNDMessageHandlerDelegate: virtual bool IsWidgetWindow() const OVERRIDE; virtual bool IsUsingCustomFrame() const OVERRIDE; + virtual void SchedulePaint() OVERRIDE; + virtual void EnableInactiveRendering() OVERRIDE; + virtual bool IsInactiveRenderingDisabled() OVERRIDE; virtual bool CanResize() const OVERRIDE; virtual bool CanMaximize() const OVERRIDE; virtual bool CanActivate() const OVERRIDE; + virtual bool WillProcessWorkAreaChange() const OVERRIDE; virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE; virtual void GetWindowMask(const gfx::Size& size, gfx::Path* path) OVERRIDE; + virtual void GetMinMaxSize(gfx::Size* min_size, + gfx::Size* max_size) const OVERRIDE; + virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE; virtual InputMethod* GetInputMethod() OVERRIDE; virtual void HandleAppDeactivated() OVERRIDE; + virtual void HandleActivationChanged(bool active) OVERRIDE; virtual bool HandleAppCommand(short command) OVERRIDE; virtual void HandleCaptureLost() OVERRIDE; virtual void HandleClose() OVERRIDE; virtual bool HandleCommand(int command) OVERRIDE; + virtual void HandleCreate() OVERRIDE; virtual void HandleDestroy() OVERRIDE; virtual void HandleDisplayChange() OVERRIDE; virtual void HandleGlassModeChange() OVERRIDE; virtual void HandleBeginWMSizeMove() OVERRIDE; virtual void HandleEndWMSizeMove() OVERRIDE; virtual void HandleMove() OVERRIDE; + virtual void HandleWorkAreaChanged() OVERRIDE; virtual void HandleNativeFocus(HWND last_focused_window) OVERRIDE; virtual void HandleNativeBlur(HWND focused_window) OVERRIDE; + virtual void HandleScreenReaderDetected() OVERRIDE; + virtual bool HandleTooltipNotify(int w_param, + NMHDR* l_param, + LRESULT* l_result) OVERRIDE; virtual NativeWidgetWin* AsNativeWidgetWin() OVERRIDE; // Called after the WM_ACTIVATE message has been processed by the default diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc index 780025c..ea54edc 100644 --- a/ui/views/win/hwnd_message_handler.cc +++ b/ui/views/win/hwnd_message_handler.cc @@ -7,6 +7,7 @@ #include <dwmapi.h> #include "base/system_monitor/system_monitor.h" +#include "base/win/windows_version.h" #include "ui/gfx/path.h" #include "ui/base/native_theme/native_theme_win.h" #include "ui/views/ime/input_method_win.h" @@ -14,6 +15,24 @@ #include "ui/views/win/hwnd_message_handler_delegate.h" namespace views { +namespace { + +// Called from OnNCActivate. +BOOL CALLBACK EnumChildWindowsForRedraw(HWND hwnd, LPARAM lparam) { + DWORD process_id; + GetWindowThreadProcessId(hwnd, &process_id); + int flags = RDW_INVALIDATE | RDW_NOCHILDREN | RDW_FRAME; + if (process_id == GetCurrentProcessId()) + flags |= RDW_UPDATENOW; + RedrawWindow(hwnd, NULL, NULL, flags); + return TRUE; +} + +// A custom MSAA object id used to determine if a screen reader is actively +// listening for MSAA events. +const int kCustomObjectID = 1; + +} // namespace //////////////////////////////////////////////////////////////////////////////// // HWNDMessageHandler, public: @@ -26,6 +45,21 @@ HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate) HWNDMessageHandler::~HWNDMessageHandler() { } +bool HWNDMessageHandler::IsActive() const { + return GetActiveWindow() == hwnd(); +} + +bool HWNDMessageHandler::IsVisible() const { + return !!::IsWindowVisible(hwnd()); +} + +void HWNDMessageHandler::SendFrameChanged() { + SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, + SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOCOPYBITS | + SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREPOSITION | + SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER); +} + void HWNDMessageHandler::OnActivate(UINT action, BOOL minimized, HWND window) { SetMsgHandled(FALSE); } @@ -35,12 +69,8 @@ void HWNDMessageHandler::OnActivateApp(BOOL active, DWORD thread_id) { thread_id != GetCurrentThreadId()) { delegate_->HandleAppDeactivated(); // Also update the native frame if it is rendering the non-client area. - if (!remove_standard_frame_ && - !delegate_->IsUsingCustomFrame() && - delegate_->AsNativeWidgetWin()) { - delegate_->AsNativeWidgetWin()->DefWindowProcWithRedrawLock( - WM_NCACTIVATE, FALSE, 0); - } + if (!remove_standard_frame_ && !delegate_->IsUsingCustomFrame()) + DefWindowProcWithRedrawLock(WM_NCACTIVATE, FALSE, 0); } } @@ -77,6 +107,39 @@ void HWNDMessageHandler::OnCommand(UINT notification_code, SetMsgHandled(FALSE); } +LRESULT HWNDMessageHandler::OnCreate(CREATESTRUCT* create_struct) { + // Attempt to detect screen readers by sending an event with our custom id. + NotifyWinEvent(EVENT_SYSTEM_ALERT, hwnd(), kCustomObjectID, CHILDID_SELF); + + // This message initializes the window so that focus border are shown for + // windows. + SendMessage(hwnd(), + WM_CHANGEUISTATE, + MAKELPARAM(UIS_CLEAR, UISF_HIDEFOCUS), + 0); + + // Bug 964884: detach the IME attached to this window. + // We should attach IMEs only when we need to input CJK strings. + ImmAssociateContextEx(hwnd(), NULL, 0); + + if (remove_standard_frame_) { + SetWindowLong(hwnd(), GWL_STYLE, + GetWindowLong(hwnd(), GWL_STYLE) & ~WS_CAPTION); + SendFrameChanged(); + } + + // Get access to a modifiable copy of the system menu. + GetSystemMenu(hwnd(), false); + + if (base::win::GetVersion() >= base::win::VERSION_WIN7) + RegisterTouchWindow(hwnd(), 0); + + delegate_->HandleCreate(); + + // TODO(beng): move more of NWW::OnCreate here. + return 0; +} + void HWNDMessageHandler::OnDestroy() { delegate_->HandleDestroy(); } @@ -86,14 +149,15 @@ void HWNDMessageHandler::OnDisplayChange(UINT bits_per_pixel, delegate_->HandleDisplayChange(); } -void HWNDMessageHandler::OnDwmCompositionChanged(UINT msg, - WPARAM w_param, - LPARAM l_param) { +LRESULT HWNDMessageHandler::OnDwmCompositionChanged(UINT msg, + WPARAM w_param, + LPARAM l_param) { if (!delegate_->IsWidgetWindow()) { SetMsgHandled(FALSE); - return; + return 0; } delegate_->HandleGlassModeChange(); + return 0; } void HWNDMessageHandler::OnEndSession(BOOL ending, UINT logoff) { @@ -119,6 +183,69 @@ void HWNDMessageHandler::OnExitSizeMove() { SetMsgHandled(FALSE); } +void HWNDMessageHandler::OnGetMinMaxInfo(MINMAXINFO* minmax_info) { + gfx::Size min_window_size; + gfx::Size max_window_size; + delegate_->GetMinMaxSize(&min_window_size, &max_window_size); + + // Add the native frame border size to the minimum and maximum size if the + // view reports its size as the client size. + if (delegate_->AsNativeWidgetWin()->WidgetSizeIsClientSize()) { + CRect client_rect, window_rect; + GetClientRect(hwnd(), &client_rect); + GetWindowRect(hwnd(), &window_rect); + window_rect -= client_rect; + min_window_size.Enlarge(window_rect.Width(), window_rect.Height()); + if (!max_window_size.IsEmpty()) + max_window_size.Enlarge(window_rect.Width(), window_rect.Height()); + } + minmax_info->ptMinTrackSize.x = min_window_size.width(); + minmax_info->ptMinTrackSize.y = min_window_size.height(); + if (max_window_size.width() || max_window_size.height()) { + if (!max_window_size.width()) + max_window_size.set_width(GetSystemMetrics(SM_CXMAXTRACK)); + if (!max_window_size.height()) + max_window_size.set_height(GetSystemMetrics(SM_CYMAXTRACK)); + minmax_info->ptMaxTrackSize.x = max_window_size.width(); + minmax_info->ptMaxTrackSize.y = max_window_size.height(); + } + SetMsgHandled(FALSE); +} + +LRESULT HWNDMessageHandler::OnGetObject(UINT message, + WPARAM w_param, + LPARAM l_param) { + LRESULT reference_result = static_cast<LRESULT>(0L); + + // Accessibility readers will send an OBJID_CLIENT message + if (OBJID_CLIENT == l_param) { + // Retrieve MSAA dispatch object for the root view. + base::win::ScopedComPtr<IAccessible> root( + delegate_->GetNativeViewAccessible()); + + // Create a reference that MSAA will marshall to the client. + reference_result = LresultFromObject(IID_IAccessible, w_param, + static_cast<IAccessible*>(root.Detach())); + } + + if (kCustomObjectID == l_param) { + // An MSAA client requested our custom id. Assume that we have detected an + // active windows screen reader. + delegate_->HandleScreenReaderDetected(); + + // Return with failure. + return static_cast<LRESULT>(0L); + } + + return reference_result; +} + +void HWNDMessageHandler::OnHScroll(int scroll_type, + short position, + HWND scrollbar) { + SetMsgHandled(FALSE); +} + LRESULT HWNDMessageHandler::OnImeMessages(UINT message, WPARAM w_param, LPARAM l_param) { @@ -184,6 +311,19 @@ void HWNDMessageHandler::OnKillFocus(HWND focused_window) { SetMsgHandled(FALSE); } +LRESULT HWNDMessageHandler::OnMouseActivate(UINT message, + WPARAM w_param, + LPARAM l_param) { + // TODO(beng): resolve this with the GetWindowLong() check on the subsequent + // line. + if (delegate_->IsWidgetWindow()) + return delegate_->CanActivate() ? MA_ACTIVATE : MA_NOACTIVATEANDEAT; + if (GetWindowLong(hwnd(), GWL_EXSTYLE) & WS_EX_NOACTIVATE) + return MA_NOACTIVATE; + SetMsgHandled(FALSE); + return MA_ACTIVATE; +} + void HWNDMessageHandler::OnMove(const CPoint& point) { delegate_->HandleMove(); SetMsgHandled(FALSE); @@ -193,6 +333,53 @@ void HWNDMessageHandler::OnMoving(UINT param, const RECT* new_bounds) { delegate_->HandleMove(); } +LRESULT HWNDMessageHandler::OnNCActivate(BOOL active) { + if (delegate_->CanActivate()) + delegate_->HandleActivationChanged(!!active); + + if (!delegate_->IsWidgetWindow()) { + SetMsgHandled(FALSE); + return 0; + } + + if (!delegate_->CanActivate()) + return TRUE; + + // The frame may need to redraw as a result of the activation change. + // We can get WM_NCACTIVATE before we're actually visible. If we're not + // visible, no need to paint. + if (IsVisible()) + delegate_->SchedulePaint(); + + if (delegate_->IsUsingCustomFrame()) { + // TODO(beng, et al): Hack to redraw this window and child windows + // synchronously upon activation. Not all child windows are redrawing + // themselves leading to issues like http://crbug.com/74604 + // We redraw out-of-process HWNDs asynchronously to avoid hanging the + // whole app if a child HWND belonging to a hung plugin is encountered. + RedrawWindow(hwnd(), NULL, NULL, + RDW_NOCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW); + EnumChildWindows(hwnd(), EnumChildWindowsForRedraw, NULL); + } + + // If we're active again, we should be allowed to render as inactive, so + // tell the non-client view. + bool inactive_rendering_disabled = delegate_->IsInactiveRenderingDisabled(); + if (IsActive()) + delegate_->EnableInactiveRendering(); + + // Avoid DefWindowProc non-client rendering over our custom frame on newer + // Windows versions only (breaks taskbar activation indication on XP/Vista). + if (delegate_->IsUsingCustomFrame() && + base::win::GetVersion() > base::win::VERSION_VISTA) { + SetMsgHandled(TRUE); + return TRUE; + } + + return DefWindowProcWithRedrawLock( + WM_NCACTIVATE, inactive_rendering_disabled || active, 0); +} + LRESULT HWNDMessageHandler::OnNCHitTest(const CPoint& point) { if (!delegate_->IsWidgetWindow()) { SetMsgHandled(FALSE); @@ -241,6 +428,12 @@ LRESULT HWNDMessageHandler::OnNCUAHDrawFrame(UINT message, return 0; } +LRESULT HWNDMessageHandler::OnNotify(int w_param, NMHDR* l_param) { + LRESULT l_result = 0; + SetMsgHandled(delegate_->HandleTooltipNotify(w_param, l_param, &l_result)); + return l_result; +} + LRESULT HWNDMessageHandler::OnPowerBroadcast(DWORD power_event, DWORD data) { base::SystemMonitor* monitor = base::SystemMonitor::Get(); if (monitor) @@ -249,6 +442,13 @@ LRESULT HWNDMessageHandler::OnPowerBroadcast(DWORD power_event, DWORD data) { return 0; } +LRESULT HWNDMessageHandler::OnReflectedMessage(UINT message, + WPARAM w_param, + LPARAM l_param) { + SetMsgHandled(FALSE); + return 0; +} + LRESULT HWNDMessageHandler::OnSetCursor(UINT message, WPARAM w_param, LPARAM l_param) { @@ -280,6 +480,21 @@ LRESULT HWNDMessageHandler::OnSetText(const wchar_t* text) { reinterpret_cast<LPARAM>(text)); } +void HWNDMessageHandler::OnSettingChange(UINT flags, const wchar_t* section) { + if (!GetParent(hwnd()) && (flags == SPI_SETWORKAREA) && + !delegate_->WillProcessWorkAreaChange()) { + // Fire a dummy SetWindowPos() call, so we'll trip the code in + // OnWindowPosChanging() below that notices work area changes. + ::SetWindowPos(hwnd(), 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | + SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOOWNERZORDER); + SetMsgHandled(TRUE); + } else { + if (flags == SPI_SETWORKAREA) + delegate_->HandleWorkAreaChanged(); + SetMsgHandled(FALSE); + } +} + void HWNDMessageHandler::OnSize(UINT param, const CSize& size) { RedrawWindow(hwnd(), NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); // ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've @@ -346,6 +561,10 @@ HWND HWNDMessageHandler::hwnd() { return delegate_->AsNativeWidgetWin()->hwnd(); } +HWND HWNDMessageHandler::hwnd() const { + return delegate_->AsNativeWidgetWin()->hwnd(); +} + LRESULT HWNDMessageHandler::DefWindowProcWithRedrawLock(UINT message, WPARAM w_param, LPARAM l_param) { diff --git a/ui/views/win/hwnd_message_handler.h b/ui/views/win/hwnd_message_handler.h index cd1a7a7..d24195a 100644 --- a/ui/views/win/hwnd_message_handler.h +++ b/ui/views/win/hwnd_message_handler.h @@ -28,6 +28,12 @@ class VIEWS_EXPORT HWNDMessageHandler { explicit HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate); ~HWNDMessageHandler(); + bool IsActive() const; + bool IsVisible() const; + + // Tells the HWND its client area has changed. + void SendFrameChanged(); + // Message Handlers. void OnActivate(UINT action, BOOL minimized, HWND window); // TODO(beng): Once this object becomes the WindowImpl, these methods can @@ -40,31 +46,39 @@ class VIEWS_EXPORT HWNDMessageHandler { void OnCaptureChanged(HWND window); void OnClose(); void OnCommand(UINT notification_code, int command, HWND window); + LRESULT OnCreate(CREATESTRUCT* create_struct); void OnDestroy(); void OnDisplayChange(UINT bits_per_pixel, const CSize& screen_size); - void OnDwmCompositionChanged(UINT msg, WPARAM w_param, LPARAM l_param); + LRESULT OnDwmCompositionChanged(UINT msg, WPARAM w_param, LPARAM l_param); void OnEndSession(BOOL ending, UINT logoff); void OnEnterSizeMove(); LRESULT OnEraseBkgnd(HDC dc); void OnExitMenuLoop(BOOL is_track_popup_menu); void OnExitSizeMove(); + void OnHScroll(int scroll_type, short position, HWND scrollbar); + void OnGetMinMaxInfo(MINMAXINFO* minmax_info); + LRESULT OnGetObject(UINT message, WPARAM w_param, LPARAM l_param); LRESULT OnImeMessages(UINT message, WPARAM w_param, LPARAM l_param); void OnInitMenu(HMENU menu); void OnInitMenuPopup(); void OnInputLangChange(DWORD character_set, HKL input_language_id); LRESULT OnKeyEvent(UINT message, WPARAM w_param, LPARAM l_param); void OnKillFocus(HWND focused_window); + LRESULT OnMouseActivate(UINT message, WPARAM w_param, LPARAM l_param); void OnMove(const CPoint& point); void OnMoving(UINT param, const RECT* new_bounds); + LRESULT OnNCActivate(BOOL active); LRESULT OnNCHitTest(const CPoint& point); LRESULT OnNCUAHDrawCaption(UINT message, WPARAM w_param, LPARAM l_param); LRESULT OnNCUAHDrawFrame(UINT message, WPARAM w_param, LPARAM l_param); + LRESULT OnNotify(int w_param, NMHDR* l_param); LRESULT OnPowerBroadcast(DWORD power_event, DWORD data); LRESULT OnReflectedMessage(UINT message, WPARAM w_param, LPARAM l_param); LRESULT OnSetCursor(UINT message, WPARAM w_param, LPARAM l_param); void OnSetFocus(HWND last_focused_window); LRESULT OnSetIcon(UINT size_type, HICON new_icon); LRESULT OnSetText(const wchar_t* text); + void OnSettingChange(UINT flags, const wchar_t* section); void OnSize(UINT param, const CSize& size); void OnThemeChanged(); void OnVScroll(int scroll_type, short position, HWND scrollbar); @@ -84,6 +98,7 @@ class VIEWS_EXPORT HWNDMessageHandler { // TODO(beng): This won't be a style violation once this object becomes the // WindowImpl. HWND hwnd(); + HWND hwnd() const; // TODO(beng): Remove once this class becomes the WindowImpl. LRESULT DefWindowProcWithRedrawLock(UINT message, diff --git a/ui/views/win/hwnd_message_handler_delegate.h b/ui/views/win/hwnd_message_handler_delegate.h index 61fb894..944d2ab 100644 --- a/ui/views/win/hwnd_message_handler_delegate.h +++ b/ui/views/win/hwnd_message_handler_delegate.h @@ -28,21 +28,38 @@ class VIEWS_EXPORT HWNDMessageHandlerDelegate { // to avoid confusion. virtual bool IsUsingCustomFrame() const = 0; + virtual void SchedulePaint() = 0; + virtual void EnableInactiveRendering() = 0; + virtual bool IsInactiveRenderingDisabled() = 0; + virtual bool CanResize() const = 0; virtual bool CanMaximize() const = 0; virtual bool CanActivate() const = 0; + virtual bool WillProcessWorkAreaChange() const = 0; + virtual int GetNonClientComponent(const gfx::Point& point) const = 0; virtual void GetWindowMask(const gfx::Size& size, gfx::Path* mask) = 0; + // Returns the minimum and maximum size the window can be resized to by the + // user. + virtual void GetMinMaxSize(gfx::Size* min_size, + gfx::Size* max_size) const = 0; + virtual InputMethod* GetInputMethod() = 0; + virtual gfx::NativeViewAccessible GetNativeViewAccessible() = 0; + // TODO(beng): Investigate migrating these methods to On* prefixes once // HWNDMessageHandler is the WindowImpl. // Called when another app was activated. virtual void HandleAppDeactivated() = 0; + // Called when the window was activated or deactivated. |active| reflects the + // new state. + virtual void HandleActivationChanged(bool active) = 0; + // Called when a well known "app command" from the system was performed. // Returns true if the command was handled. virtual bool HandleAppCommand(short command) = 0; @@ -57,6 +74,9 @@ class VIEWS_EXPORT HWNDMessageHandlerDelegate { // true if the command was handled. virtual bool HandleCommand(int command) = 0; + // Called when the HWND is created. + virtual void HandleCreate() = 0; + // Called when the HWND is destroyed. virtual void HandleDestroy() = 0; @@ -74,12 +94,23 @@ class VIEWS_EXPORT HWNDMessageHandlerDelegate { // Called when the window's position changed. virtual void HandleMove() = 0; + // Called when the system's work area has changed. + virtual void HandleWorkAreaChanged() = 0; + // Called when focus shifted to this HWND from |last_focused_window|. virtual void HandleNativeFocus(HWND last_focused_window) = 0; // Called when focus shifted from the HWND to a different window. virtual void HandleNativeBlur(HWND focused_window) = 0; + // Called when we have detected a screen reader. + virtual void HandleScreenReaderDetected() = 0; + + // Called to forward a WM_NOTIFY message to the tooltip manager. + virtual bool HandleTooltipNotify(int w_param, + NMHDR* l_param, + LRESULT* l_result) = 0; + // This is provided for methods that need to call private methods on NWW. // TODO(beng): should be removed once HWNDMessageHandler is the WindowImpl. virtual NativeWidgetWin* AsNativeWidgetWin() = 0; |