diff options
author | twiz@chromium.org <twiz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-10 22:46:47 +0000 |
---|---|---|
committer | twiz@chromium.org <twiz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-10 22:46:47 +0000 |
commit | 2db27be7dbb16f02587b90f150a843d8ad234563 (patch) | |
tree | 9bfd5b6b2ff4637a69744ce35249361d1f3ea353 /chrome/browser/renderer_host | |
parent | e1ce144bd04336891bb12b967095e938ed5f1bbb (diff) | |
download | chromium_src-2db27be7dbb16f02587b90f150a843d8ad234563.zip chromium_src-2db27be7dbb16f02587b90f150a843d8ad234563.tar.gz chromium_src-2db27be7dbb16f02587b90f150a843d8ad234563.tar.bz2 |
CL implementing focus-dismissal of the chrome.experimental.popup set of extension APIs.
Specifically, these changes cause a displayed pop-up to be dismissed when the focus shifts away from both the pop-up view, and the extension-view that launched the pop-up.I had to do a lot of investigating and trial-and-error to converge to the solution present here. I was hoping to be able to piggy-back on the existing FocusManager's various listener routines, but because the pop-up is hosted in a BubbleWidget, which is a separate top-level window with its own focus manager, I could not rely on a given focus manager to take care of the focus change notifications. To get around the above issue, I added a new type of focus listener that can listen on native-window focus change events. I added invocations to this listener throughout the Widget classes in the system so that registered listeners will be notified on focus change.
I found some of the focus change events problematic, as the system will arbitrarily reassign the focus to the main browser window when shifting activation between chrome windows. (SeefocusManagerWin::ClearNativeFocus). To prevent this focus bounce from confusing focus listeners, I added a means to suppress notification of focus change during these operations.
I added GTK and Mac stubs for the new widget functions that will assert when called. GTK and Cocoa development is not my expertise, so I thought // TODO(port) would be wiser.I'm uncertain of the best means to unit-test these changes. Direction in this regard would be appreciated.
BUG=None
TEST=None
Review URL: http://codereview.chromium.org/552167
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38685 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/renderer_host')
8 files changed, 100 insertions, 1 deletions
diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h index f761053..e2f58d8 100644 --- a/chrome/browser/renderer_host/render_widget_host_view.h +++ b/chrome/browser/renderer_host/render_widget_host_view.h @@ -51,6 +51,11 @@ class RenderWidgetHostView { // going to be a regular RenderWidgetHost or a RenderViewHost (a subclass). static RenderWidgetHostView* CreateViewForWidget(RenderWidgetHost* widget); + // Retrieves the RenderWidgetHostView corresponding to the specified + // |native_view|, or NULL if there is no such instance. + static RenderWidgetHostView* GetRenderWidgetHostViewFromNativeView( + gfx::NativeView native_view); + // Perform all the initialization steps necessary for this object to represent // a popup (such as a <select> dropdown), then shows the popup at |pos|. virtual void InitAsPopup(RenderWidgetHostView* parent_host_view, @@ -204,6 +209,10 @@ class RenderWidgetHostView { } const SkBitmap& background() const { return background_; } + // Returns true if the native view, |native_view|, is contained within in the + // widget associated with this RenderWidgetHostView. + virtual bool ContainsNativeView(gfx::NativeView native_view) const = 0; + protected: // Interface class only, do not construct. RenderWidgetHostView() : activatable_(true) {} diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc index 66cbe52..dffb61f 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc @@ -43,6 +43,8 @@ static const int kMaxWindowHeight = 4000; // TODO(brettw) make this a command line option. static const bool kUseGPURendering = false; +static const char* kRenderWidgetHostViewKey = "__RENDER_WIDGET_HOST_VIEW__"; + using WebKit::WebInputEventFactory; // This class is a simple convenience wrapper for Gtk functions. It has only @@ -102,6 +104,9 @@ class RenderWidgetHostViewGtkWidget { g_signal_connect_after(widget, "scroll-event", G_CALLBACK(MouseScrollEvent), host_view); + g_object_set_data(G_OBJECT(widget), kRenderWidgetHostViewKey, + static_cast<RenderWidgetHostView*>(host_view)); + return widget; } @@ -744,6 +749,14 @@ void RenderWidgetHostViewGtk::DestroyPluginContainer( plugin_container_manager_.DestroyPluginContainer(id); } +bool RenderWidgetHostViewGtk::ContainsNativeView( + gfx::NativeView native_view) const { + // TODO(port) + NOTREACHED() << + "RenderWidgetHostViewGtk::ContainsNativeView not implemented."; + return false; +} + void RenderWidgetHostViewGtk::ForwardKeyboardEvent( const NativeWebKeyboardEvent& event) { if (!host_) @@ -755,3 +768,12 @@ void RenderWidgetHostViewGtk::ForwardKeyboardEvent( } host_->ForwardKeyboardEvent(event); } + +// static +RenderWidgetHostView* + RenderWidgetHostView::GetRenderWidgetHostViewFromNativeView( + gfx::NativeView widget) { + gpointer user_data = g_object_get_data(G_OBJECT(widget), + kRenderWidgetHostViewKey); + return reinterpret_cast<RenderWidgetHostView*>(user_data); +} diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.h b/chrome/browser/renderer_host/render_widget_host_view_gtk.h index f44a92b..fd2b579 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.h +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.h @@ -71,6 +71,7 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView { virtual void SetBackground(const SkBitmap& background); virtual void CreatePluginContainer(gfx::PluginWindowHandle id); virtual void DestroyPluginContainer(gfx::PluginWindowHandle id); + virtual bool ContainsNativeView(gfx::NativeView native_view) const; gfx::NativeView native_view() const { return view_.get(); } diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h index c707205..34903f0 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.h +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h @@ -115,6 +115,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { virtual void SetWindowVisibility(bool visible); virtual void WindowFrameChanged(); virtual void SetBackground(const SkBitmap& background); + virtual bool ContainsNativeView(gfx::NativeView native_view) const; // Methods associated with GPU plugin instances virtual gfx::PluginWindowHandle AllocateFakePluginWindowHandle(); diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm index 6e6df70..ac76e90 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm @@ -93,6 +93,16 @@ RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget( return new RenderWidgetHostViewMac(widget); } +// static +RenderWidgetHostView* RenderWidgetHostView:: + GetRenderWidgetHostViewFromNativeView(gfx::NativeView native_view) { + // TODO(port) + NOTREACHED() << + "RenderWidgetHostView::GetRenderWidgetHostViewFromNativeView not" + "implemented"; + return NULL; +} + /////////////////////////////////////////////////////////////////////////////// // RenderWidgetHostViewMac, public: @@ -645,6 +655,14 @@ void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) { render_widget_host_->routing_id(), background)); } +bool RenderWidgetHostViewMac::ContainsNativeView( + gfx::NativeView native_view) const { + // TODO(port) + NOTREACHED() << + "RenderWidgetHostViewMac::ContainsNativeView not implemented."; + return false; +} + // EditCommandMatcher --------------------------------------------------------- // This class is used to capture the shortcuts that a given key event maps to. diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc index 8bff4d2..3216c7c 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc @@ -35,6 +35,7 @@ #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" #include "third_party/WebKit/WebKit/chromium/public/win/WebInputEventFactory.h" #include "views/accessibility/view_accessibility.h" +#include "views/focus/focus_manager.h" #include "views/focus/focus_util_win.h" // Included for views::kReflectedMessage - TODO(beng): move this to win_util.h! #include "views/widget/widget_win.h" @@ -58,6 +59,8 @@ const int kTooltipMaxWidthPixels = 300; // Maximum number of characters we allow in a tooltip. const int kMaxTooltipLength = 1024; +const wchar_t* kRenderWidgetHostViewKey = L"__RENDER_WIDGET_HOST_VIEW__"; + // A callback function for EnumThreadWindows to enumerate and dismiss // any owned popop windows BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) { @@ -728,6 +731,23 @@ void RenderWidgetHostViewWin::SetBackground(const SkBitmap& background) { background)); } +bool RenderWidgetHostViewWin::ContainsNativeView( + gfx::NativeView native_view) const { + if (m_hWnd == native_view) + return true; + + // Traverse the set of parents of the given view to determine if native_view + // is a descendant of this window. + HWND parent_window = ::GetParent(native_view); + while (parent_window) { + if (parent_window == m_hWnd) + return true; + parent_window = ::GetParent(parent_window); + } + + return false; +} + /////////////////////////////////////////////////////////////////////////////// // RenderWidgetHostViewWin, private: @@ -740,7 +760,9 @@ LRESULT RenderWidgetHostViewWin::OnCreate(CREATESTRUCT* create_struct) { views::SetWindowSupportsRerouteMouseWheel(m_hWnd); // Save away our HWND in the parent window as a property so that the // accessibility code can find it. - SetProp(GetParent(), kViewsNativeHostPropForAccessibility, m_hWnd); + ::SetProp(GetParent(), kViewsNativeHostPropForAccessibility, m_hWnd); + ::SetProp(m_hWnd, kRenderWidgetHostViewKey, + static_cast<RenderWidgetHostView*>(this)); return 0; } @@ -771,6 +793,8 @@ void RenderWidgetHostViewWin::OnDestroy() { // sequence as part of the usual cleanup when the plugin instance goes away. EnumChildWindows(m_hWnd, DetachPluginWindowsCallback, NULL); + ::RemoveProp(m_hWnd, kRenderWidgetHostViewKey); + ResetTooltip(); TrackMouseLeave(false); } @@ -919,11 +943,17 @@ LRESULT RenderWidgetHostViewWin::OnSetCursor(HWND window, UINT hittest_code, } void RenderWidgetHostViewWin::OnSetFocus(HWND window) { + views::FocusManager::GetWidgetFocusManager()->OnWidgetFocusEvent(window, + m_hWnd); + if (render_widget_host_) render_widget_host_->GotFocus(); } void RenderWidgetHostViewWin::OnKillFocus(HWND window) { + views::FocusManager::GetWidgetFocusManager()->OnWidgetFocusEvent(m_hWnd, + window); + if (render_widget_host_) render_widget_host_->Blur(); } @@ -1516,3 +1546,16 @@ void RenderWidgetHostViewWin::ShutdownHost() { render_widget_host_->Shutdown(); // Do not touch any members at this point, |this| has been deleted. } + +// static +RenderWidgetHostView* + RenderWidgetHostView::GetRenderWidgetHostViewFromNativeView( + gfx::NativeView native_view) { + if (::IsWindow(native_view)) { + HANDLE raw_render_host_view = ::GetProp(native_view, + kRenderWidgetHostViewKey); + if (raw_render_host_view) + return reinterpret_cast<RenderWidgetHostView*>(raw_render_host_view); + } + return NULL; +} diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.h b/chrome/browser/renderer_host/render_widget_host_view_win.h index 5555495..64224fc 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.h +++ b/chrome/browser/renderer_host/render_widget_host_view_win.h @@ -137,6 +137,7 @@ class RenderWidgetHostViewWin virtual void SetTooltipText(const std::wstring& tooltip_text); virtual BackingStore* AllocBackingStore(const gfx::Size& size); virtual void SetBackground(const SkBitmap& background); + virtual bool ContainsNativeView(gfx::NativeView native_view) const; protected: // Windows Message Handlers diff --git a/chrome/browser/renderer_host/test/test_render_view_host.h b/chrome/browser/renderer_host/test/test_render_view_host.h index 0521de9..85e6eca 100644 --- a/chrome/browser/renderer_host/test/test_render_view_host.h +++ b/chrome/browser/renderer_host/test/test_render_view_host.h @@ -94,6 +94,10 @@ class TestRenderWidgetHostView : public RenderWidgetHostView { virtual void DestroyPluginContainer(gfx::PluginWindowHandle id) { } #endif + virtual bool ContainsNativeView(gfx::NativeView native_view) const { + return false; + } + bool is_showing() const { return is_showing_; } private: |