diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-27 20:35:03 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-27 20:35:03 +0000 |
commit | 252f86be785920b4ed67f0e194e5833ad0c88142 (patch) | |
tree | 59d8a230f04ddac29ba2a1668abbac90cf75c325 | |
parent | 9c276ac152a6ea8753ae7427ba3955afeb845d82 (diff) | |
download | chromium_src-252f86be785920b4ed67f0e194e5833ad0c88142.zip chromium_src-252f86be785920b4ed67f0e194e5833ad0c88142.tar.gz chromium_src-252f86be785920b4ed67f0e194e5833ad0c88142.tar.bz2 |
Allow the BrowserFrame to customize the RootWindowHost implementation.
This is achieved by subclassing DesktopRootWindowHost, similar to how we subclass NativeWidgetWin etc. The subclass is forwarded through to the DesktopNativeWidgetAura via Widget::InitParams.
There's probably a cleaner way to do this but given that this code is currently already subclassing this seems no worse.
http://crbug.com/146077
R=jam@chromium.org
Review URL: https://codereview.chromium.org/10959003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@159104 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/ui/views/frame/browser_desktop_root_window_host_win.cc | 177 | ||||
-rw-r--r-- | chrome/browser/ui/views/frame/browser_desktop_root_window_host_win.h | 45 | ||||
-rw-r--r-- | chrome/browser/ui/views/frame/desktop_browser_frame_aura.cc | 18 | ||||
-rw-r--r-- | chrome/browser/ui/views/frame/desktop_browser_frame_aura.h | 3 | ||||
-rw-r--r-- | chrome/chrome_browser_ui.gypi | 2 | ||||
-rw-r--r-- | ui/aura/root_window_host.h | 3 | ||||
-rw-r--r-- | ui/views/widget/desktop_native_widget_aura.cc | 3 | ||||
-rw-r--r-- | ui/views/widget/desktop_root_window_host.h | 3 | ||||
-rw-r--r-- | ui/views/widget/desktop_root_window_host_win.cc | 6 | ||||
-rw-r--r-- | ui/views/widget/desktop_root_window_host_win.h | 12 | ||||
-rw-r--r-- | ui/views/widget/widget.cc | 2 | ||||
-rw-r--r-- | ui/views/widget/widget.h | 6 |
12 files changed, 273 insertions, 7 deletions
diff --git a/chrome/browser/ui/views/frame/browser_desktop_root_window_host_win.cc b/chrome/browser/ui/views/frame/browser_desktop_root_window_host_win.cc new file mode 100644 index 0000000..404ccf0 --- /dev/null +++ b/chrome/browser/ui/views/frame/browser_desktop_root_window_host_win.cc @@ -0,0 +1,177 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/frame/browser_desktop_root_window_host_win.h" + +#include <dwmapi.h> + +#include "chrome/browser/ui/views/frame/browser_frame.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/tabs/tab_strip.h" +#include "ui/base/theme_provider.h" + +#pragma comment(lib, "dwmapi.lib") + +namespace { + +const int kClientEdgeThickness = 3; +// We need to offset the DWMFrame into the toolbar so that the blackness +// doesn't show up on our rounded corners. +const int kDWMFrameTopOffset = 3; + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// BrowserDesktopRootWindowHostWin, public: + +BrowserDesktopRootWindowHostWin::BrowserDesktopRootWindowHostWin( + views::internal::NativeWidgetDelegate* native_widget_delegate, + const gfx::Rect& initial_bounds, + BrowserView* browser_view, + BrowserFrame* browser_frame) + : DesktopRootWindowHostWin(native_widget_delegate, initial_bounds), + browser_view_(browser_view), + browser_frame_(browser_frame) { +} + +BrowserDesktopRootWindowHostWin::~BrowserDesktopRootWindowHostWin() { +} + +//////////////////////////////////////////////////////////////////////////////// +// BrowserDesktopRootWindowHostWin, views::DesktopRootWindowHostWin overrides: + +int BrowserDesktopRootWindowHostWin::GetInitialShowState() const { + STARTUPINFO si = {0}; + si.cb = sizeof(si); + si.dwFlags = STARTF_USESHOWWINDOW; + GetStartupInfo(&si); + return si.wShowWindow; +} + +bool BrowserDesktopRootWindowHostWin::GetClientAreaInsets( + gfx::Insets* insets) const { + // Use the default client insets for an opaque frame or a glass popup/app + // frame. + if (!GetWidget()->ShouldUseNativeFrame() || + !browser_view_->IsBrowserTypeNormal()) { + return false; + } + + int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME); + // In fullscreen mode, we have no frame. In restored mode, we draw our own + // client edge over part of the default frame. + if (GetWidget()->IsFullscreen()) + border_thickness = 0; + else if (!IsMaximized()) + border_thickness -= kClientEdgeThickness; + insets->Set(0, border_thickness, border_thickness, border_thickness); + return true; +} + +void BrowserDesktopRootWindowHostWin::HandleFrameChanged() { + // We need to update the glass region on or off before the base class adjusts + // the window region. + UpdateDWMFrame(); + DesktopRootWindowHostWin::HandleFrameChanged(); +} + +bool BrowserDesktopRootWindowHostWin::PreHandleMSG(UINT message, + WPARAM w_param, + LPARAM l_param, + LRESULT* result) { + switch (message) { + case WM_ENDSESSION: + browser::SessionEnding(); + return true; + } + return false; +} + +void BrowserDesktopRootWindowHostWin::PostHandleMSG(UINT message, + WPARAM w_param, + LPARAM l_param) { + switch (message) { + case WM_WINDOWPOSCHANGED: + UpdateDWMFrame(); + + // Windows lies to us about the position of the minimize button before a + // window is visible. We use this position to place the OTR avatar in RTL + // mode, so when the window is shown, we need to re-layout and schedule a + // paint for the non-client frame view so that the icon top has the correct + // position when the window becomes visible. This fixes bugs where the icon + // appears to overlay the minimize button. + // Note that we will call Layout every time SetWindowPos is called with + // SWP_SHOWWINDOW, however callers typically are careful about not + // specifying this flag unless necessary to avoid flicker. + // This may be invoked during creation on XP and before the non_client_view + // has been created. + WINDOWPOS* window_pos = reinterpret_cast<WINDOWPOS*>(l_param); + if (window_pos->flags & SWP_SHOWWINDOW && GetWidget()->non_client_view()) { + GetWidget()->non_client_view()->Layout(); + GetWidget()->non_client_view()->SchedulePaint(); + } + break; + } +} + +bool BrowserDesktopRootWindowHostWin::IsUsingCustomFrame() const { + // App panel windows draw their own frame. + if (browser_view_->IsPanel()) + return true; + + // We don't theme popup or app windows, so regardless of whether or not a + // theme is active for normal browser windows, we don't want to use the custom + // frame for popups/apps. + if (!browser_view_->IsBrowserTypeNormal() && + !DesktopRootWindowHostWin::IsUsingCustomFrame()) { + return false; + } + + // Otherwise, we use the native frame when we're told we should by the theme + // provider (e.g. no custom theme is active). + return !GetWidget()->GetThemeProvider()->ShouldUseNativeFrame(); +} + +//////////////////////////////////////////////////////////////////////////////// +// BrowserDesktopRootWindowHostWin, private: + +void BrowserDesktopRootWindowHostWin::UpdateDWMFrame() { + // For "normal" windows on Aero, we always need to reset the glass area + // correctly, even if we're not currently showing the native frame (e.g. + // because a theme is showing), so we explicitly check for that case rather + // than checking browser_frame_->ShouldUseNativeFrame() here. Using that here + // would mean we wouldn't reset the glass area to zero when moving from the + // native frame to an opaque frame, leading to graphical glitches behind the + // opaque frame. Instead, we use that function below to tell us whether the + // frame is currently native or opaque. + if (!GetWidget()->client_view() || !browser_view_->IsBrowserTypeNormal() || + !DesktopRootWindowHostWin::ShouldUseNativeFrame()) + return; + + MARGINS margins = { 0 }; + + // If the opaque frame is visible, we use the default (zero) margins. + // Otherwise, we need to figure out how to extend the glass in. + if (GetWidget()->ShouldUseNativeFrame()) { + // In fullscreen mode, we don't extend glass into the client area at all, + // because the GDI-drawn text in the web content composited over it will + // become semi-transparent over any glass area. + if (!IsMaximized() && !GetWidget()->IsFullscreen()) { + margins.cxLeftWidth = kClientEdgeThickness + 1; + margins.cxRightWidth = kClientEdgeThickness + 1; + margins.cyBottomHeight = kClientEdgeThickness + 1; + margins.cyTopHeight = kClientEdgeThickness + 1; + } + // In maximized mode, we only have a titlebar strip of glass, no side/bottom + // borders. + if (!browser_view_->IsFullscreen()) { + gfx::Rect tabstrip_bounds( + browser_frame_->GetBoundsForTabStrip(browser_view_->tabstrip())); + margins.cyTopHeight = tabstrip_bounds.bottom() + kDWMFrameTopOffset; + } + } + + DwmExtendFrameIntoClientArea(GetHWND(), &margins); +} + diff --git a/chrome/browser/ui/views/frame/browser_desktop_root_window_host_win.h b/chrome/browser/ui/views/frame/browser_desktop_root_window_host_win.h new file mode 100644 index 0000000..911066c --- /dev/null +++ b/chrome/browser/ui/views/frame/browser_desktop_root_window_host_win.h @@ -0,0 +1,45 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_DESKTOP_ROOT_WINDOW_HOST_WIN_H_ +#define CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_DESKTOP_ROOT_WINDOW_HOST_WIN_H_ + +#include "ui/views/widget/desktop_root_window_host_win.h" + +class BrowserFrame; +class BrowserView; + +class BrowserDesktopRootWindowHostWin : public views::DesktopRootWindowHostWin { + public: + BrowserDesktopRootWindowHostWin( + views::internal::NativeWidgetDelegate* native_widget_delegate, + const gfx::Rect& initial_bounds, + BrowserView* browser_view, + BrowserFrame* browser_frame); + virtual ~BrowserDesktopRootWindowHostWin(); + + private: + // Overridden from DesktopRootWindowHostWin: + virtual int GetInitialShowState() const OVERRIDE; + virtual bool GetClientAreaInsets(gfx::Insets* insets) const OVERRIDE; + virtual void HandleFrameChanged() OVERRIDE; + virtual bool PreHandleMSG(UINT message, + WPARAM w_param, + LPARAM l_param, + LRESULT* result) OVERRIDE; + virtual void PostHandleMSG(UINT message, + WPARAM w_param, + LPARAM l_param) OVERRIDE; + virtual bool IsUsingCustomFrame() const OVERRIDE; + + void UpdateDWMFrame(); + + BrowserView* browser_view_; + BrowserFrame* browser_frame_; + + DISALLOW_COPY_AND_ASSIGN(BrowserDesktopRootWindowHostWin); +}; + + +#endif // CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_DESKTOP_ROOT_WINDOW_HOST_WIN_H_ diff --git a/chrome/browser/ui/views/frame/desktop_browser_frame_aura.cc b/chrome/browser/ui/views/frame/desktop_browser_frame_aura.cc index 7cb0308..2d97c98 100644 --- a/chrome/browser/ui/views/frame/desktop_browser_frame_aura.cc +++ b/chrome/browser/ui/views/frame/desktop_browser_frame_aura.cc @@ -24,6 +24,10 @@ #include "ash/wm/property_util.h" #endif +#if defined(OS_WIN) +#include "chrome/browser/ui/views/frame/browser_desktop_root_window_host_win.h" +#endif + using aura::Window; //////////////////////////////////////////////////////////////////////////////// @@ -78,6 +82,7 @@ DesktopBrowserFrameAura::DesktopBrowserFrameAura( BrowserView* browser_view) : views::DesktopNativeWidgetAura(browser_frame), browser_view_(browser_view), + browser_frame_(browser_frame), window_property_watcher_(new WindowPropertyWatcher(this, browser_frame)) { GetNativeWindow()->SetName("BrowserFrameAura"); GetNativeWindow()->AddObserver(window_property_watcher_.get()); @@ -133,6 +138,19 @@ void DesktopBrowserFrameAura::ShowContextMenuForView(views::View* source, /////////////////////////////////////////////////////////////////////////////// // DesktopBrowserFrameAura, views::DestkopNativeWidgetAura overrides: +void DesktopBrowserFrameAura::InitNativeWidget( + const views::Widget::InitParams& params) { + views::Widget::InitParams modified_params = params; +#if defined(OS_WIN) + modified_params.desktop_root_window_host = + new BrowserDesktopRootWindowHostWin(browser_frame_, + params.bounds, + browser_view_, + browser_frame_); +#endif + DesktopNativeWidgetAura::InitNativeWidget(modified_params); +} + void DesktopBrowserFrameAura::OnWindowDestroying() { // Window is destroyed before our destructor is called, so clean up our // observer here. diff --git a/chrome/browser/ui/views/frame/desktop_browser_frame_aura.h b/chrome/browser/ui/views/frame/desktop_browser_frame_aura.h index 55fb751..59a6c36 100644 --- a/chrome/browser/ui/views/frame/desktop_browser_frame_aura.h +++ b/chrome/browser/ui/views/frame/desktop_browser_frame_aura.h @@ -39,6 +39,8 @@ class DesktopBrowserFrameAura : public views::ContextMenuController, const gfx::Point& p) OVERRIDE; // Overridden from views::NativeWidgetAura: + virtual void InitNativeWidget( + const views::Widget::InitParams& params) OVERRIDE; virtual void OnWindowDestroying() OVERRIDE; virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE; @@ -56,6 +58,7 @@ class DesktopBrowserFrameAura : public views::ContextMenuController, // The BrowserView is our ClientView. This is a pointer to it. BrowserView* browser_view_; + BrowserFrame* browser_frame_; scoped_ptr<WindowPropertyWatcher> window_property_watcher_; diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index 69ed9db..7319fb5 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -1419,6 +1419,8 @@ 'browser/ui/views/frame/contents_container.h', 'browser/ui/views/frame/desktop_browser_frame_aura.cc', 'browser/ui/views/frame/desktop_browser_frame_aura.h', + 'browser/ui/views/frame/browser_desktop_root_window_host_win.cc', + 'browser/ui/views/frame/browser_desktop_root_window_host_win.h', 'browser/ui/views/frame/glass_browser_frame_view.cc', 'browser/ui/views/frame/glass_browser_frame_view.h', 'browser/ui/views/frame/native_browser_frame.h', diff --git a/ui/aura/root_window_host.h b/ui/aura/root_window_host.h index ee5eb20..5105fa9 100644 --- a/ui/aura/root_window_host.h +++ b/ui/aura/root_window_host.h @@ -8,6 +8,7 @@ #include <vector> #include "base/message_loop.h" +#include "ui/aura/aura_export.h" #include "ui/base/cursor/cursor.h" #include "ui/gfx/native_widget_types.h" @@ -25,7 +26,7 @@ class RootWindowHostDelegate; // RootWindowHost bridges between a native window and the embedded RootWindow. // It provides the accelerated widget and maps events from the native os to // aura. -class RootWindowHost { +class AURA_EXPORT RootWindowHost { public: virtual ~RootWindowHost() {} diff --git a/ui/views/widget/desktop_native_widget_aura.cc b/ui/views/widget/desktop_native_widget_aura.cc index 159265a..601d745 100644 --- a/ui/views/widget/desktop_native_widget_aura.cc +++ b/ui/views/widget/desktop_native_widget_aura.cc @@ -34,7 +34,8 @@ void DesktopNativeWidgetAura::InitNativeWidget( window_->Init(params.layer_type); window_->Show(); - desktop_root_window_host_ = + desktop_root_window_host_ = params.desktop_root_window_host ? + params.desktop_root_window_host : DesktopRootWindowHost::Create(native_widget_delegate_, params.bounds); desktop_root_window_host_->Init(window_, params); } diff --git a/ui/views/widget/desktop_root_window_host.h b/ui/views/widget/desktop_root_window_host.h index 3a518db..8071bba 100644 --- a/ui/views/widget/desktop_root_window_host.h +++ b/ui/views/widget/desktop_root_window_host.h @@ -6,6 +6,7 @@ #define UI_VIEWS_WIDGET_DESKTOP_ROOT_WINDOW_HOST_H_ #include "ui/base/ui_base_types.h" +#include "ui/views/views_export.h" #include "ui/views/widget/widget.h" namespace aura { @@ -24,7 +25,7 @@ class InputMethodDelegate; class NativeWidgetDelegate; } -class DesktopRootWindowHost { +class VIEWS_EXPORT DesktopRootWindowHost { public: virtual ~DesktopRootWindowHost() {} diff --git a/ui/views/widget/desktop_root_window_host_win.cc b/ui/views/widget/desktop_root_window_host_win.cc index 781bac1..753ea8f 100644 --- a/ui/views/widget/desktop_root_window_host_win.cc +++ b/ui/views/widget/desktop_root_window_host_win.cc @@ -520,6 +520,8 @@ void DesktopRootWindowHostWin::HandleCreate() { // TODO(beng): moar NOTIMPLEMENTED(); + native_widget_delegate_->OnNativeWidgetCreated(); + // 1. Window property association // 2. MouseWheel. // 3. Drop target. @@ -680,6 +682,10 @@ const Widget* DesktopRootWindowHostWin::GetWidget() const { return native_widget_delegate_->AsWidget(); } +HWND DesktopRootWindowHostWin::GetHWND() { + return message_handler_->hwnd(); +} + //////////////////////////////////////////////////////////////////////////////// // DesktopRootWindowHost, public: diff --git a/ui/views/widget/desktop_root_window_host_win.h b/ui/views/widget/desktop_root_window_host_win.h index 0e68f52..9b4d41a 100644 --- a/ui/views/widget/desktop_root_window_host_win.h +++ b/ui/views/widget/desktop_root_window_host_win.h @@ -6,6 +6,7 @@ #define UI_VIEWS_WIDGET_DESKTOP_ROOT_WINDOW_HOST_WIN_H_ #include "ui/aura/root_window_host.h" +#include "ui/views/views_export.h" #include "ui/views/widget/desktop_root_window_host.h" #include "ui/views/win/hwnd_message_handler_delegate.h" @@ -23,16 +24,17 @@ namespace views { class DesktopCaptureClient; class HWNDMessageHandler; -class DesktopRootWindowHostWin : public DesktopRootWindowHost, - public aura::RootWindowHost, - public HWNDMessageHandlerDelegate { +class VIEWS_EXPORT DesktopRootWindowHostWin + : public DesktopRootWindowHost, + public aura::RootWindowHost, + public HWNDMessageHandlerDelegate { public: DesktopRootWindowHostWin( internal::NativeWidgetDelegate* native_widget_delegate, const gfx::Rect& initial_bounds); virtual ~DesktopRootWindowHostWin(); - private: + protected: // Overridden from DesktopRootWindowHost: virtual void Init(aura::Window* content_window, const Widget::InitParams& params) OVERRIDE; @@ -186,7 +188,9 @@ class DesktopRootWindowHostWin : public DesktopRootWindowHost, Widget* GetWidget(); const Widget* GetWidget() const; + HWND GetHWND(); + private: scoped_ptr<aura::RootWindow> root_window_; scoped_ptr<HWNDMessageHandler> message_handler_; scoped_ptr<DesktopCaptureClient> capture_client_; diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc index 51c4fe0b..1677c82 100644 --- a/ui/views/widget/widget.cc +++ b/ui/views/widget/widget.cc @@ -156,6 +156,7 @@ Widget::InitParams::InitParams() parent(NULL), parent_widget(NULL), native_widget(NULL), + desktop_root_window_host(NULL), top_level(false), layer_type(ui::LAYER_TEXTURED) { } @@ -180,6 +181,7 @@ Widget::InitParams::InitParams(Type type) parent(NULL), parent_widget(NULL), native_widget(NULL), + desktop_root_window_host(NULL), top_level(false), layer_type(ui::LAYER_TEXTURED) { } diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h index 0379cf5..48f1295 100644 --- a/ui/views/widget/widget.h +++ b/ui/views/widget/widget.h @@ -53,6 +53,7 @@ enum TouchStatus; namespace views { class DefaultThemeProvider; +class DesktopRootWindowHost; class InputMethod; class NativeWidget; class NonClientFrameView; @@ -181,6 +182,11 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // When set, this value is used as the Widget's NativeWidget implementation. // The Widget will not construct a default one. Default is NULL. NativeWidget* native_widget; + // Aura-only. Provides a DesktopRootWindowHost implementation to use instead + // of the default one. + // TODO(beng): Figure out if there's a better way to expose this, e.g. get + // rid of NW subclasses and do this all via message handling. + DesktopRootWindowHost* desktop_root_window_host; bool top_level; // Only used by NativeWidgetAura. Specifies the type of layer for the // aura::Window. Default is LAYER_TEXTURED. |