diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-04 21:04:39 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-04 21:04:39 +0000 |
commit | 5b54a5c0327ea3ac2c13cff37573ccd4e7f41e57 (patch) | |
tree | e6137bcd166e3a5b83dbdc4a997099597dd7d82f /views/widget/widget_win.cc | |
parent | 6775e40aeb887f15dc9182b250cdc4100aa79ce0 (diff) | |
download | chromium_src-5b54a5c0327ea3ac2c13cff37573ccd4e7f41e57.zip chromium_src-5b54a5c0327ea3ac2c13cff37573ccd4e7f41e57.tar.gz chromium_src-5b54a5c0327ea3ac2c13cff37573ccd4e7f41e57.tar.bz2 |
Two things:
- simplify root view sizing.
- move focus manager creation/management to Widget
BUG=72040
TEST=existing unittests
Review URL: http://codereview.chromium.org/6609026
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76963 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/widget/widget_win.cc')
-rw-r--r-- | views/widget/widget_win.cc | 210 |
1 files changed, 72 insertions, 138 deletions
diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc index e81d5c2..7944e58 100644 --- a/views/widget/widget_win.cc +++ b/views/widget/widget_win.cc @@ -30,6 +30,7 @@ #include "views/widget/aero_tooltip_manager.h" #include "views/widget/child_window_message_processor.h" #include "views/widget/drop_target_win.h" +#include "views/widget/native_widget_delegate.h" #include "views/widget/root_view.h" #include "views/widget/widget_delegate.h" #include "views/window/window_win.h" @@ -106,6 +107,14 @@ BOOL CALLBACK EnumerateChildWindowsForNativeWidgets(HWND hwnd, LPARAM l_param) { return TRUE; } +// Returns true if the WINDOWPOS data provided indicates the client area of +// the window may have changed size. This can be caused by the window being +// resized or its frame changing. +bool DidClientAreaSizeChange(const WINDOWPOS* window_pos) { + return !(window_pos->flags & SWP_NOSIZE) || + window_pos->flags & SWP_FRAMECHANGED; +} + // Links the HWND to its NativeWidget. const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__"; @@ -155,31 +164,6 @@ WidgetWin* WidgetWin::GetWidget(HWND hwnd) { } // static -WidgetWin* WidgetWin::GetRootWidget(HWND hwnd) { - // First, check if the top-level window is a Widget. - HWND root = ::GetAncestor(hwnd, GA_ROOT); - if (!root) - return NULL; - - WidgetWin* widget = WidgetWin::GetWidget(root); - if (widget) - return widget; - - // Second, try to locate the last Widget window in the parent hierarchy. - HWND parent_hwnd = hwnd; - WidgetWin* parent_widget; - do { - parent_widget = WidgetWin::GetWidget(parent_hwnd); - if (parent_widget) { - widget = parent_widget; - parent_hwnd = ::GetAncestor(parent_hwnd, GA_PARENT); - } - } while (parent_hwnd != NULL && parent_widget != NULL); - - return widget; -} - -// static bool WidgetWin::IsAeroGlassEnabled() { if (base::win::GetVersion() < base::win::VERSION_VISTA) return false; @@ -218,55 +202,9 @@ void WidgetWin::ClearAccessibilityViewEvent(View* view) { void WidgetWin::Init(gfx::NativeView parent, const gfx::Rect& bounds) { Widget::Init(parent, bounds); - // Force creation of the RootView; otherwise, we may get a WM_SIZE after the - // window is created and before the root view is set up. - GetRootView(); // Create the window. WindowImpl::Init(parent, bounds); - - // 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(SetWindowSupportsRerouteMouseWheel(hwnd())); - - drop_target_ = new DropTargetWin(GetRootView()); - - if ((window_style() & WS_CHILD) == 0 || - (!GetTopLevelNativeWidget(parent) && parent != GetDesktopWindow())) { - // Top-level widgets and child widgets who do not have a top-level widget - // ancestor get a FocusManager. Child widgets parented to the desktop do not - // get a FocusManager because parenting to the desktop is the technique used - // to intentionally exclude a widget from the FocusManager hierarchy. - focus_manager_.reset(new FocusManager(this)); - } - - // 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. - if (GetThemeProvider()->ShouldUseNativeFrame()) { - tooltip_manager_.reset(new AeroTooltipManager(this)); - } else { - tooltip_manager_.reset(new TooltipManagerWin(this)); - } - - // 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); } void WidgetWin::InitWithWidget(Widget* parent, const gfx::Rect& bounds) { @@ -350,10 +288,6 @@ void WidgetWin::SetAlwaysOnTop(bool on_top) { set_window_ex_style(window_ex_style() & ~WS_EX_TOPMOST); } -Widget* WidgetWin::GetRootWidget() const { - return GetRootWidget(hwnd()); -} - bool WidgetWin::IsVisible() const { return !!::IsWindowVisible(hwnd()); } @@ -386,36 +320,14 @@ const Window* WidgetWin::GetWindow() const { return GetWindowImpl(hwnd()); } -FocusManager* WidgetWin::GetFocusManager() { - if (focus_manager_.get()) - return focus_manager_.get(); - - NativeWidget* native_widget = GetTopLevelNativeWidget(hwnd()); - if (native_widget && native_widget != this) { - // WidgetWin subclasses may override GetFocusManager(), for example for - // dealing with cases where the widget has been un-parented. - return native_widget->GetWidget()->GetFocusManager(); - } - return NULL; -} - void WidgetWin::ViewHierarchyChanged(bool is_add, View* parent, View* child) { Widget::ViewHierarchyChanged(is_add, parent, child); if (drop_target_.get()) drop_target_->ResetTargetViewIfEquals(child); - if (!is_add) { + if (!is_add) ClearAccessibilityViewEvent(child); - - FocusManager* focus_manager = GetFocusManager(); - if (focus_manager) { - if (focus_manager->GetFocusedView() == child) - focus_manager->SetFocusedView(NULL); - focus_manager->ViewRemoved(parent, child); - } - ViewStorage::GetInstance()->ViewRemoved(parent, child); - } } //////////////////////////////////////////////////////////////////////////////// @@ -547,7 +459,7 @@ LRESULT WidgetWin::OnWndProc(UINT message, WPARAM w_param, LPARAM l_param) { PostProcessActivateMessage(this, LOWORD(w_param)); if (message == WM_ENABLE && restore_focus_when_enabled_) { restore_focus_when_enabled_ = false; - focus_manager_->RestoreFocusedView(); + GetFocusManager()->RestoreFocusedView(); } return result; } @@ -595,8 +507,47 @@ LRESULT WidgetWin::OnCreate(CREATESTRUCT* create_struct) { // Widget::GetWidgetFromNativeView expects the contents of this property // to be of type Widget, so the cast is necessary. SetNativeWindowProperty(kNativeWidgetKey, this); + use_layered_buffer_ = !!(window_ex_style() & WS_EX_LAYERED); - LayoutRootView(); + + // 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(SetWindowSupportsRerouteMouseWheel(hwnd())); + + drop_target_ = new DropTargetWin(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. + if (GetThemeProvider()->ShouldUseNativeFrame()) { + tooltip_manager_.reset(new AeroTooltipManager(this)); + } else { + tooltip_manager_.reset(new TooltipManagerWin(this)); + } + + // 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); + + // 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(); return 0; } @@ -709,9 +660,7 @@ LRESULT WidgetWin::OnKeyUp(UINT message, WPARAM w_param, LPARAM l_param) { } void WidgetWin::OnKillFocus(HWND focused_window) { - GetFocusManager()->GetWidgetFocusManager()->OnWidgetFocusEvent( - this->GetNativeView(), - focused_window); + delegate_->OnNativeBlur(focused_window); SetMsgHandled(FALSE); } @@ -920,9 +869,7 @@ LRESULT WidgetWin::OnReflectedMessage(UINT msg, } void WidgetWin::OnSetFocus(HWND focused_window) { - GetFocusManager()->GetWidgetFocusManager()->OnWidgetFocusEvent( - focused_window, - this->GetNativeView()); + delegate_->OnNativeFocus(focused_window); SetMsgHandled(FALSE); } @@ -943,7 +890,7 @@ void WidgetWin::OnSettingChange(UINT flags, const wchar_t* section) { } void WidgetWin::OnSize(UINT param, const CSize& size) { - LayoutRootView(); + SetMsgHandled(FALSE); } void WidgetWin::OnSysCommand(UINT notification_code, CPoint click) { @@ -963,6 +910,8 @@ void WidgetWin::OnWindowPosChanging(WINDOWPOS* window_pos) { } void WidgetWin::OnWindowPosChanged(WINDOWPOS* window_pos) { + if (DidClientAreaSizeChange(window_pos)) + ClientAreaSizeChanged(); SetMsgHandled(FALSE); } @@ -974,16 +923,6 @@ void WidgetWin::OnFinalMessage(HWND window) { //////////////////////////////////////////////////////////////////////////////// // WidgetWin, protected: -gfx::Size WidgetWin::GetRootViewSize() const { - CRect rect; - if (use_layered_buffer_) - GetWindowRect(&rect); - else - GetClientRect(&rect); - - return gfx::Size(rect.Width(), rect.Height()); -} - void WidgetWin::TrackMouseEvents(DWORD mouse_tracking_flags) { // Begin tracking mouse events for this HWND so that we get WM_MOUSELEAVE // when the user moves the mouse outside this HWND's bounds. @@ -1096,18 +1035,6 @@ void WidgetWin::ProcessMouseExited() { active_mouse_tracking_flags_ = 0; } -void WidgetWin::LayoutRootView() { - gfx::Size size(GetRootViewSize()); - - if (use_layered_buffer_) - SizeContents(size); - - // Resizing changes the size of the view hierarchy and thus forces a - // complete relayout. - GetRootView()->SetBounds(0, 0, size.width(), size.height()); - GetRootView()->SchedulePaint(); -} - void WidgetWin::OnScreenReaderDetected() { screen_reader_active_ = true; } @@ -1134,13 +1061,8 @@ Window* WidgetWin::GetWindowImpl(HWND hwnd) { return NULL; } -void WidgetWin::SizeContents(const gfx::Size& window_size) { - layered_window_contents_.reset(new gfx::CanvasSkia(window_size.width(), - window_size.height(), - false)); -} - RootView* WidgetWin::GetFocusedViewRootView() { + // TODO(beng): get rid of this FocusManager* focus_manager = GetFocusManager(); if (!focus_manager) { NOTREACHED(); @@ -1155,15 +1077,16 @@ RootView* WidgetWin::GetFocusedViewRootView() { // static void WidgetWin::PostProcessActivateMessage(WidgetWin* widget, int activation_state) { - if (!widget->focus_manager_.get()) { + if (!widget->delegate_->HasFocusManager()) { NOTREACHED(); return; } + FocusManager* focus_manager = widget->GetWidget()->GetFocusManager(); if (WA_INACTIVE == activation_state) { // We might get activated/inactivated without being enabled, so we need to // clear restore_focus_when_enabled_. widget->restore_focus_when_enabled_ = false; - widget->focus_manager_->StoreFocusedView(); + focus_manager->StoreFocusedView(); } else { // We must restore the focus after the message has been DefProc'ed as it // does set the focus to the last focused HWND. @@ -1178,7 +1101,7 @@ void WidgetWin::PostProcessActivateMessage(WidgetWin* widget, widget->restore_focus_when_enabled_ = true; return; } - widget->focus_manager_->RestoreFocusedView(); + focus_manager->RestoreFocusedView(); } } @@ -1230,6 +1153,17 @@ void WidgetWin::RedrawLayeredWindowContents() { layered_window_invalid_rect_.SetRect(0, 0, 0, 0); } +void WidgetWin::ClientAreaSizeChanged() { + RECT r; + GetClientRect(&r); + gfx::Size s(r.right - r.left, r.bottom - r.top); + delegate_->OnSizeChanged(s); + if (use_layered_buffer_) { + layered_window_contents_.reset( + new gfx::CanvasSkia(s.width(), s.height(), false)); + } +} + //////////////////////////////////////////////////////////////////////////////// // Widget, public: |