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 /views/widget | |
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 'views/widget')
-rw-r--r-- | views/widget/widget.h | 4 | ||||
-rw-r--r-- | views/widget/widget_gtk.cc | 9 | ||||
-rw-r--r-- | views/widget/widget_gtk.h | 2 | ||||
-rw-r--r-- | views/widget/widget_win.cc | 33 | ||||
-rw-r--r-- | views/widget/widget_win.h | 3 |
5 files changed, 49 insertions, 2 deletions
diff --git a/views/widget/widget.h b/views/widget/widget.h index fa8111e..a3959b4 100644 --- a/views/widget/widget.h +++ b/views/widget/widget.h @@ -193,6 +193,10 @@ class Widget { // Forwarded from the RootView so that the widget can do any cleanup. virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child) = 0; + + // Returns true if the native view |native_view| is contained in the + // views::View hierarchy rooted at this widget. + virtual bool ContainsNativeView(gfx::NativeView native_view) = 0; }; } // namespace views diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc index 3f9b3c4..44bc82d 100644 --- a/views/widget/widget_gtk.cc +++ b/views/widget/widget_gtk.cc @@ -590,6 +590,12 @@ void WidgetGtk::ViewHierarchyChanged(bool is_add, View *parent, drop_target_->ResetTargetViewIfEquals(child); } +bool WidgetGtk::ContainsNativeView(gfx::NativeView native_view) { + // TODO(port) See implementation in WidgetWin::ContainsNativeView. + NOTREACHED() << "WidgetGtk::ContainsNativeView is not implemented."; + return false; +} + //////////////////////////////////////////////////////////////////////////////// // WidgetGtk, MessageLoopForUI::Observer implementation: @@ -1239,7 +1245,8 @@ void WidgetGtk::CreateGtkWidget(GtkWidget* parent, const gfx::Rect& bounds) { gtk_fixed_set_has_window(GTK_FIXED(window_contents_), true); gtk_container_add(GTK_CONTAINER(widget_), window_contents_); gtk_widget_show(window_contents_); - g_object_set_data(G_OBJECT(window_contents_), kWidgetKey, this); + g_object_set_data(G_OBJECT(window_contents_), kWidgetKey, + static_cast<Widget*>(this)); if (transparent_) ConfigureWidgetForTransparentBackground(); diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h index 9d73bf0..0c0096c 100644 --- a/views/widget/widget_gtk.h +++ b/views/widget/widget_gtk.h @@ -168,6 +168,8 @@ class WidgetGtk virtual FocusManager* GetFocusManager(); virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child); + virtual bool ContainsNativeView(gfx::NativeView native_view); + // Overridden from MessageLoopForUI::Observer: virtual void WillProcessEvent(GdkEvent* event); diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc index 6f75506..ea54036 100644 --- a/views/widget/widget_win.cc +++ b/views/widget/widget_win.cc @@ -383,6 +383,28 @@ void WidgetWin::ViewHierarchyChanged(bool is_add, View *parent, drop_target_->ResetTargetViewIfEquals(child); } + +bool WidgetWin::ContainsNativeView(gfx::NativeView native_view) { + if (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); + HWND previous_child = native_view; + while (parent_window && parent_window != previous_child) { + if (hwnd() == parent_window) + return true; + previous_child = parent_window; + parent_window = ::GetParent(parent_window); + } + + // A views::NativeViewHost may contain the given native view, without it being + // an ancestor of hwnd(), so traverse the views::View hierarchy looking for + // such views. + return GetRootView()->ContainsNativeView(native_view); +} + //////////////////////////////////////////////////////////////////////////////// // MessageLoop::Observer @@ -595,6 +617,13 @@ void WidgetWin::OnKeyUp(TCHAR c, UINT rep_cnt, UINT flags) { SetMsgHandled(root_view->ProcessKeyEvent(event)); } +void WidgetWin::OnKillFocus(HWND focused_window) { + GetFocusManager()->GetWidgetFocusManager()->OnWidgetFocusEvent( + this->GetNativeView(), + focused_window); + SetMsgHandled(FALSE); +} + // TODO(pkasting): ORing the pressed/released button into the flags is _wrong_. // It makes it impossible to tell which button was modified when multiple // buttons are/were held down. We need to instead put the modified button into @@ -800,6 +829,9 @@ LRESULT WidgetWin::OnReflectedMessage(UINT msg, } void WidgetWin::OnSetFocus(HWND focused_window) { + GetFocusManager()->GetWidgetFocusManager()->OnWidgetFocusEvent( + focused_window, + this->GetNativeView()); SetMsgHandled(FALSE); } @@ -1236,7 +1268,6 @@ void Widget::FindAllRootViews(HWND window, root_views->push_back(*it); } - //////////////////////////////////////////////////////////////////////////////// // Widget, public: diff --git a/views/widget/widget_win.h b/views/widget/widget_win.h index 28a3782..ed233d4 100644 --- a/views/widget/widget_win.h +++ b/views/widget/widget_win.h @@ -130,6 +130,7 @@ class WidgetWin : public app::WindowImpl, MSG_WM_INITMENUPOPUP(OnInitMenuPopup) MSG_WM_KEYDOWN(OnKeyDown) MSG_WM_KEYUP(OnKeyUp) + MSG_WM_KILLFOCUS(OnKillFocus) MSG_WM_SYSKEYDOWN(OnKeyDown) MSG_WM_SYSKEYUP(OnKeyUp) MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk) @@ -207,6 +208,7 @@ class WidgetWin : public app::WindowImpl, virtual FocusManager* GetFocusManager(); virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child); + virtual bool ContainsNativeView(gfx::NativeView native_view); // Overridden from MessageLoop::Observer: void WillProcessMessage(const MSG& msg); @@ -335,6 +337,7 @@ class WidgetWin : public app::WindowImpl, virtual void OnInitMenuPopup(HMENU menu, UINT position, BOOL is_system_menu); virtual void OnKeyDown(TCHAR c, UINT rep_cnt, UINT flags); virtual void OnKeyUp(TCHAR c, UINT rep_cnt, UINT flags); + virtual void OnKillFocus(HWND focused_window); virtual void OnLButtonDblClk(UINT flags, const CPoint& point); virtual void OnLButtonDown(UINT flags, const CPoint& point); virtual void OnLButtonUp(UINT flags, const CPoint& point); |