summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-14 21:42:06 +0000
committergrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-14 21:42:06 +0000
commitcdcf18b0b4a7218e6053e3636b5038c679767528 (patch)
treed965289475e0bba117442b1b71a3a2273c6ee553
parente5f7c33fd248ce3443645b9a2f7a25624ad75188 (diff)
downloadchromium_src-cdcf18b0b4a7218e6053e3636b5038c679767528.zip
chromium_src-cdcf18b0b4a7218e6053e3636b5038c679767528.tar.gz
chromium_src-cdcf18b0b4a7218e6053e3636b5038c679767528.tar.bz2
Add an intermediate window between GCF's host window and the RHW.
Previously, GCF+Aura parented the ChromeFrameAutomationClient window directly to the DesktopRootWindowHostWin window. This caused some focus warping (and possibly other) issues when SetParent was called again. BUG=235411 Review URL: https://chromiumcodereview.appspot.com/14927013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@200080 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/ui/views/external_tab_container_win.cc95
-rw-r--r--chrome/browser/ui/views/external_tab_container_win.h8
-rw-r--r--chrome_frame/test/ui_test.cc5
3 files changed, 100 insertions, 8 deletions
diff --git a/chrome/browser/ui/views/external_tab_container_win.cc b/chrome/browser/ui/views/external_tab_container_win.cc
index b9ec6a74..2ec5555 100644
--- a/chrome/browser/ui/views/external_tab_container_win.cc
+++ b/chrome/browser/ui/views/external_tab_container_win.cc
@@ -7,6 +7,7 @@
#include <atlbase.h>
#include <atlapp.h>
#include <atlconv.h>
+#include <atlcrack.h>
#include <atlmisc.h>
#include <string>
@@ -157,6 +158,80 @@ ContextMenuModel* ConvertMenuModel(const ui::MenuModel* ui_model) {
} // namespace
+#if defined(USE_AURA)
+typedef ATL::CWinTraits<WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+ WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW>
+ ContainerWindowHWNDTraits;
+
+// A window placed in the parent/child hierarchy between the host (e.g., a
+// ChromeFrameAutomationClient window) and the Aura DesktopRootWindowHostWin.
+// This non-activatable window is necessary to prevent focus from warping from
+// the DRWHW up to the CFAC window during reparenting. This is not needed in the
+// non-Aura case because the ExternalTabContainer's primary widget takes this
+// role (the RenderWidgetHostViewWin's HWND is a grandchild of it).
+class ContainerWindow : public ATL::CWindowImpl<ContainerWindow,
+ ATL::CWindow,
+ ContainerWindowHWNDTraits>,
+ public base::SupportsWeakPtr<ContainerWindow> {
+ public:
+ DECLARE_WND_CLASS_EX(NULL, CS_DBLCLKS, 0);
+
+ BEGIN_MSG_MAP_EX(ContainerWindow)
+ MSG_WM_MOVE(OnMove)
+ MSG_WM_SHOWWINDOW(OnShowWindow)
+ MSG_WM_SIZE(OnSize)
+ END_MSG_MAP()
+
+ ContainerWindow(HWND parent, const gfx::Rect& bounds) : child_(NULL) {
+ RECT rect = bounds.ToRECT();
+ Create(parent, rect);
+ }
+
+ HWND hwnd() {
+ DCHECK(::IsWindow(m_hWnd));
+ return m_hWnd;
+ }
+
+ // Sets the child window (the DRWHW). The child is made activateable as part
+ // of the operation.
+ void SetChild(HWND window) {
+ child_ = window;
+
+ ::SetWindowLong(
+ window, GWL_STYLE,
+ (::GetWindowLong(window, GWL_STYLE) & ~WS_POPUP) | WS_CHILD);
+ ::SetWindowLong(window, GWL_EXSTYLE,
+ (::GetWindowLong(window, GWL_EXSTYLE) & ~WS_EX_NOACTIVATE));
+
+ ::SetParent(window, hwnd());
+ }
+
+ protected:
+ virtual void OnFinalMessage(HWND hwnd) OVERRIDE {
+ delete this;
+ }
+
+ private:
+ void OnMove(const CPoint& position) {
+ ::SetWindowPos(child_, NULL, position.x, position.y, 0, 0,
+ SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
+ }
+
+ void OnShowWindow(BOOL show, UINT status) {
+ ::ShowWindow(child_, SW_SHOWNA);
+ }
+
+ void OnSize(UINT type, const CSize& size) {
+ ::SetWindowPos(child_, NULL, 0, 0, size.cx, size.cy,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
+ }
+
+ HWND child_;
+
+ DISALLOW_COPY_AND_ASSIGN(ContainerWindow);
+};
+#endif
+
base::LazyInstance<ExternalTabContainerWin::PendingTabs>
ExternalTabContainerWin::pending_tabs_ = LAZY_INSTANCE_INITIALIZER;
@@ -224,15 +299,24 @@ bool ExternalTabContainerWin::Init(Profile* profile,
views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
params.bounds = bounds;
#if defined(USE_AURA)
+ // Create the window that sits between the parent (most likely a
+ // ChromeFrameAutomationClient) and the DesktopRootWindowHostWin.
+ tab_container_window_ =
+ (new ContainerWindow(HWND_DESKTOP, params.bounds))->AsWeakPtr();
+
params.native_widget = new views::DesktopNativeWidgetAura(widget_);
params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
#endif
widget_->Init(params);
- HWND window = views::HWNDForWidget(widget_);
+
+#if defined(USE_AURA)
+ tab_container_window_->SetChild(views::HWNDForWidget(widget_));
+#endif
// TODO(jcampan): limit focus traversal to contents.
- prop_.reset(new ui::ViewProp(window, kWindowObjectKey, this));
+ prop_.reset(new ui::ViewProp(views::HWNDForWidget(widget_), kWindowObjectKey,
+ this));
if (existing_contents) {
existing_contents->GetController().SetBrowserContext(profile);
@@ -284,6 +368,7 @@ bool ExternalTabContainerWin::Init(Profile* profile,
// Note that it's important to do this before we call SetParent since
// during the SetParent call we will otherwise get a WA_ACTIVATE call
// that causes us to steal the current focus.
+ HWND window = GetExternalTabHWND();
SetWindowLong(window, GWL_STYLE,
(GetWindowLong(window, GWL_STYLE) & ~WS_POPUP) | style);
@@ -367,7 +452,7 @@ bool ExternalTabContainerWin::Reinitialize(
weak_factory_.GetWeakPtr()));
if (parent_window)
- SetParent(views::HWNDForWidget(widget_), parent_window);
+ SetParent(GetExternalTabHWND(), parent_window);
return true;
}
@@ -376,7 +461,11 @@ WebContents* ExternalTabContainerWin::GetWebContents() const {
}
HWND ExternalTabContainerWin::GetExternalTabHWND() const {
+#if defined(USE_AURA)
+ return tab_container_window_.get() ? tab_container_window_->hwnd() : NULL;
+#else
return views::HWNDForWidget(widget_);
+#endif
}
HWND ExternalTabContainerWin::GetContentHWND() const {
diff --git a/chrome/browser/ui/views/external_tab_container_win.h b/chrome/browser/ui/views/external_tab_container_win.h
index 79a28652..324a0f3 100644
--- a/chrome/browser/ui/views/external_tab_container_win.h
+++ b/chrome/browser/ui/views/external_tab_container_win.h
@@ -45,6 +45,10 @@ class WebView;
class Widget;
}
+#if defined(USE_AURA)
+class ContainerWindow;
+#endif
+
// This class serves as the container window for an external tab.
// An external tab is a Chrome tab that is meant to displayed in an
// external process. This class provides the FocusManger needed by the
@@ -328,6 +332,10 @@ class ExternalTabContainerWin : public ExternalTabContainer,
// if this tab is a popup
bool is_popup_window_;
+#if defined(USE_AURA)
+ base::WeakPtr<ContainerWindow> tab_container_window_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(ExternalTabContainerWin);
};
diff --git a/chrome_frame/test/ui_test.cc b/chrome_frame/test/ui_test.cc
index 2342ca3..66a6fcf 100644
--- a/chrome_frame/test/ui_test.cc
+++ b/chrome_frame/test/ui_test.cc
@@ -360,12 +360,7 @@ void NavigateToCurrentUrl(MockIEEventSink* mock) {
// Tests that Chrome gets re-instantiated after crash if we reload via
// the address bar or via a new navigation.
-#if defined(USE_AURA)
-// Renderer doesn't have focus; see http://crbug.com/235411.
-TEST_P(FullTabUITest, DISABLED_TabCrashReload) {
-#else
TEST_P(FullTabUITest, TabCrashReload) {
-#endif
using testing::DoAll;
if (!GetParam().invokes_cf()) {