diff options
author | stuartmorgan@chromium.org <stuartmorgan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-05 23:10:31 +0000 |
---|---|---|
committer | stuartmorgan@chromium.org <stuartmorgan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-05 23:10:31 +0000 |
commit | 7d3c02c0eaf7d4cf7becfe869c6b4030ded6293a (patch) | |
tree | 83cb9e4813a07021c771e625d036a5d0a9188dfe /webkit | |
parent | f3692bc59a04276845ae33f0d2e98f4738b38525 (diff) | |
download | chromium_src-7d3c02c0eaf7d4cf7becfe869c6b4030ded6293a.zip chromium_src-7d3c02c0eaf7d4cf7becfe869c6b4030ded6293a.tar.gz chromium_src-7d3c02c0eaf7d4cf7becfe869c6b4030ded6293a.tar.bz2 |
Update Mac plugins for SetFocus changes, and remove old workaround messages
Now that WebKit is sending unfocus events, rework Mac plugins to correctly track plugin focus as a function of WebKit element focus and window-level view focus. Remove message plumbing for the old workarounds that were used to partially simulate focus switching for Mac plugins.
Windows and Linux will currently ignore the new focus loss notifications so their behavior is unchanged.
BUG=32721
TEST=Mac plugins should stop reacting to keyboard events once another control on the page, or the omnibox, is focused. They should also regain keyboard focus when switching back to their tab if they had it when the tab was hidden.
Review URL: http://codereview.chromium.org/1736007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46516 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate.h | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.h | 29 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl_gtk.cc | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl_mac.mm | 118 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl_win.cc | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_impl.cc | 4 |
6 files changed, 71 insertions, 92 deletions
diff --git a/webkit/glue/plugins/webplugin_delegate.h b/webkit/glue/plugins/webplugin_delegate.h index 0b08c9e..6b15839 100644 --- a/webkit/glue/plugins/webplugin_delegate.h +++ b/webkit/glue/plugins/webplugin_delegate.h @@ -83,9 +83,9 @@ class WebPluginDelegate : public WebPlugin2DDeviceDelegate, // Tells the plugin to print itself. virtual void Print(gfx::NativeDrawingContext hdc) = 0; - // Informs the plugin that it now has focus. This is only called in + // Informs the plugin that it has gained or lost focus. This is only called in // windowless mode. - virtual void SetFocus() = 0; + virtual void SetFocus(bool focused) = 0; // For windowless plugins, gives them a user event like mouse/keyboard. // Returns whether the event was handled. This is only called in windowsless diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h index 2fef88b..0d113ca 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.h +++ b/webkit/glue/plugins/webplugin_delegate_impl.h @@ -97,7 +97,7 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { const gfx::Rect& clip_rect); virtual void Paint(WebKit::WebCanvas* canvas, const gfx::Rect& rect); virtual void Print(gfx::NativeDrawingContext context); - virtual void SetFocus(); + virtual void SetFocus(bool focused); virtual bool HandleInputEvent(const WebKit::WebInputEvent& event, WebKit::WebCursorInfo* cursor_info); virtual NPObject* GetPluginScriptableObject(); @@ -141,19 +141,11 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { gfx::NativeDrawingContext context); // Returns the delegate currently processing events. static WebPluginDelegateImpl* GetActiveDelegate(); - // Returns a vector of currently active delegates in this process. - static std::set<WebPluginDelegateImpl*> GetActiveDelegates(); - // Informs the delegate that it has gained or lost focus. - void FocusChanged(bool has_focus); - // Set a notifier function that gets called when the delegate is accepting - // the focus. If no notifier function has been set, the delegate will just - // call FocusChanged(true). This is used in a multiprocess environment to - // propagate focus notifications to all running plugin processes. - void SetFocusNotifier(void (*notifier)(WebPluginDelegateImpl*)) { - focus_notifier_ = notifier; - } // Informs the plugin that the window it is in has gained or lost focus. void SetWindowHasFocus(bool has_focus); + // Informs the plugin that the view it is in has gained or lost first + // responder status. + void SetContentAreaHasFocus(bool has_focus); // Returns whether or not the window the plugin is in has focus. bool GetWindowHasFocus() const { return containing_window_has_focus_; } // Informs the plugin that its tab or window has been hidden or shown. @@ -369,6 +361,10 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { // Updates everything that depends on the plugin's absolute screen location. void PluginScreenLocationChanged(); + // Informs the plugin that it has gained or lost keyboard focus (i.e., window + // first responder status). + void SetPluginHasFocus(bool has_focus); + // Returns the apparent zoom ratio for the given event, as inferred from our // current knowledge about about where on screen the plugin is. // This is a temporary workaround for <http://crbug.com/9996>; once that is @@ -424,9 +420,12 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { gfx::Point content_area_origin_; // True if the plugin thinks it has keyboard focus - bool have_focus_; - // A function to call when we want to accept keyboard focus - void (*focus_notifier_)(WebPluginDelegateImpl* notifier); + bool plugin_has_focus_; + // True if the plugin element has focus within the page, regardless of whether + // its containing view is currently the first responder for the window. + bool has_webkit_focus_; + // True if the containing view is the window's first responder. + bool containing_view_has_focus_; bool containing_window_has_focus_; bool initial_window_focus_; diff --git a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc index bf8b141..e9830b4 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc @@ -480,8 +480,10 @@ void WebPluginDelegateImpl::WindowlessSetWindow() { } } -void WebPluginDelegateImpl::SetFocus() { +void WebPluginDelegateImpl::SetFocus(bool focused) { DCHECK(instance()->windowless()); + if (!focused) + return; NPEvent np_event = {0}; XFocusChangeEvent &event = np_event.xfocus; diff --git a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm index 3d5f71a..ee40ceb 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm +++ b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm @@ -53,9 +53,6 @@ const int kCoreAnimationRedrawPeriodMs = 20; // 50fps namespace { -base::LazyInstance<std::set<WebPluginDelegateImpl*> > g_active_delegates( - base::LINKER_INITIALIZED); - WebPluginDelegateImpl* g_active_delegate; // Helper to simplify correct usage of g_active_delegate. Instantiating will @@ -262,8 +259,9 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( layer_(nil), surface_(NULL), renderer_(nil), - have_focus_(false), - focus_notifier_(NULL), + plugin_has_focus_(false), + has_webkit_focus_(false), + containing_view_has_focus_(false), containing_window_has_focus_(false), initial_window_focus_(false), container_is_visible_(false), @@ -278,15 +276,9 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( memset(&qd_port_, 0, sizeof(qd_port_)); #endif instance->set_windowless(true); - - std::set<WebPluginDelegateImpl*>* delegates = g_active_delegates.Pointer(); - delegates->insert(this); } WebPluginDelegateImpl::~WebPluginDelegateImpl() { - std::set<WebPluginDelegateImpl*>* delegates = g_active_delegates.Pointer(); - delegates->erase(this); - DestroyInstance(); #ifndef NP_NO_CARBON @@ -476,11 +468,13 @@ void WebPluginDelegateImpl::Print(CGContextRef context) { NOTIMPLEMENTED(); } -void WebPluginDelegateImpl::SetFocus() { - if (focus_notifier_) - focus_notifier_(this); - else - FocusChanged(true); +void WebPluginDelegateImpl::SetFocus(bool focused) { + // This is called when internal WebKit focus (the focused element on the page) + // changes, but plugins need to know about actual first responder status, so + // we have an extra layer of focus tracking. + has_webkit_focus_ = focused; + if (containing_view_has_focus_) + SetPluginHasFocus(focused); } bool WebPluginDelegateImpl::PlatformHandleInputEvent( @@ -559,17 +553,6 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent( } #endif - // if we do not currently have focus and this is a mouseDown, trigger a - // notification that we are taking the keyboard focus. We can't just key - // off of incoming calls to SetFocus, since WebKit may already think we - // have it if we were the most recently focused element on our parent tab. - if (event.type == WebInputEvent::MouseDown && !have_focus_) { - SetFocus(); - // Make sure that the plugin is still there after handling the focus event. - if (!instance()) - return false; - } - ScopedActiveDelegate active_delegate(this); // Create the plugin event structure. @@ -812,29 +795,34 @@ WebPluginDelegateImpl* WebPluginDelegateImpl::GetActiveDelegate() { return g_active_delegate; } -std::set<WebPluginDelegateImpl*> WebPluginDelegateImpl::GetActiveDelegates() { - std::set<WebPluginDelegateImpl*>* delegates = g_active_delegates.Pointer(); - return *delegates; -} - -void WebPluginDelegateImpl::FocusChanged(bool has_focus) { - if (!have_called_set_window_) +void WebPluginDelegateImpl::SetWindowHasFocus(bool has_focus) { + // If we get a window focus event before calling SetWindow, just remember the + // states (WindowlessSetWindow will then send it on the first call). + if (!have_called_set_window_) { + initial_window_focus_ = has_focus; return; + } - if (has_focus == have_focus_) + if (has_focus == containing_window_has_focus_) return; - have_focus_ = has_focus; + containing_window_has_focus_ = has_focus; - ScopedActiveDelegate active_delegate(this); +#ifndef NP_NO_QUICKDRAW + // Make sure controls repaint with the correct look. + if (quirks_ & PLUGIN_QUIRK_ALLOW_FASTER_QUICKDRAW_PATH) + SetQuickDrawFastPathEnabled(false); +#endif + ScopedActiveDelegate active_delegate(this); switch (instance()->event_model()) { #ifndef NP_NO_CARBON case NPEventModelCarbon: { NPEvent focus_event = { 0 }; - if (have_focus_) - focus_event.what = NPEventType_GetFocusEvent; - else - focus_event.what = NPEventType_LoseFocusEvent; + focus_event.what = activateEvt; + if (has_focus) + focus_event.modifiers |= activeFlag; + focus_event.message = + reinterpret_cast<unsigned long>(np_cg_context_.window); focus_event.when = TickCount(); instance()->NPP_HandleEvent(&focus_event); break; @@ -843,42 +831,32 @@ void WebPluginDelegateImpl::FocusChanged(bool has_focus) { case NPEventModelCocoa: { NPCocoaEvent focus_event; memset(&focus_event, 0, sizeof(focus_event)); - focus_event.type = NPCocoaEventFocusChanged; - focus_event.data.focus.hasFocus = have_focus_; + focus_event.type = NPCocoaEventWindowFocusChanged; + focus_event.data.focus.hasFocus = has_focus; instance()->NPP_HandleEvent(&focus_event); break; } } } -void WebPluginDelegateImpl::SetWindowHasFocus(bool has_focus) { - // If we get a window focus event before calling SetWindow, just remember the - // states (WindowlessSetWindow will then send it on the first call). - if (!have_called_set_window_) { - initial_window_focus_ = has_focus; +void WebPluginDelegateImpl::SetPluginHasFocus(bool has_focus) { + if (!have_called_set_window_) return; - } - if (has_focus == containing_window_has_focus_) + if (has_focus == plugin_has_focus_) return; - containing_window_has_focus_ = has_focus; - -#ifndef NP_NO_QUICKDRAW - // Make sure controls repaint with the correct look. - if (quirks_ & PLUGIN_QUIRK_ALLOW_FASTER_QUICKDRAW_PATH) - SetQuickDrawFastPathEnabled(false); -#endif + plugin_has_focus_ = has_focus; ScopedActiveDelegate active_delegate(this); + switch (instance()->event_model()) { #ifndef NP_NO_CARBON case NPEventModelCarbon: { NPEvent focus_event = { 0 }; - focus_event.what = activateEvt; - if (has_focus) - focus_event.modifiers |= activeFlag; - focus_event.message = - reinterpret_cast<unsigned long>(np_cg_context_.window); + if (plugin_has_focus_) + focus_event.what = NPEventType_GetFocusEvent; + else + focus_event.what = NPEventType_LoseFocusEvent; focus_event.when = TickCount(); instance()->NPP_HandleEvent(&focus_event); break; @@ -887,14 +865,19 @@ void WebPluginDelegateImpl::SetWindowHasFocus(bool has_focus) { case NPEventModelCocoa: { NPCocoaEvent focus_event; memset(&focus_event, 0, sizeof(focus_event)); - focus_event.type = NPCocoaEventWindowFocusChanged; - focus_event.data.focus.hasFocus = has_focus; + focus_event.type = NPCocoaEventFocusChanged; + focus_event.data.focus.hasFocus = plugin_has_focus_; instance()->NPP_HandleEvent(&focus_event); break; } } } +void WebPluginDelegateImpl::SetContentAreaHasFocus(bool has_focus) { + containing_view_has_focus_ = has_focus; + SetPluginHasFocus(containing_view_has_focus_ && has_webkit_focus_); +} + void WebPluginDelegateImpl::SetContainerVisibility(bool is_visible) { if (is_visible == container_is_visible_) return; @@ -910,13 +893,6 @@ void WebPluginDelegateImpl::SetContainerVisibility(bool is_visible) { clip_rect_.set_height(0); } - // TODO(stuartmorgan): We may need to remember whether we had focus, and - // restore it ourselves when we become visible again. Revisit once SetFocus - // is actually being called in all the cases it should be, at which point - // we'll know whether or not that's handled for us by WebKit. - if (!is_visible) - FocusChanged(false); - // If the plugin is changing visibility, let the plugin know. If it's scrolled // off screen (i.e., cached_clip_rect_ is empty), then container visibility // doesn't change anything. diff --git a/webkit/glue/plugins/webplugin_delegate_impl_win.cc b/webkit/glue/plugins/webplugin_delegate_impl_win.cc index ed8203a..b8af405 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_win.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl_win.cc @@ -1031,8 +1031,10 @@ void WebPluginDelegateImpl::WindowlessSetWindow() { DCHECK(err == NPERR_NO_ERROR); } -void WebPluginDelegateImpl::SetFocus() { +void WebPluginDelegateImpl::SetFocus(bool focused) { DCHECK(instance()->windowless()); + if (!focused) + return; NPEvent focus_event; focus_event.event = WM_SETFOCUS; diff --git a/webkit/glue/plugins/webplugin_impl.cc b/webkit/glue/plugins/webplugin_impl.cc index 30c2fa3..9ee98ed 100644 --- a/webkit/glue/plugins/webplugin_impl.cc +++ b/webkit/glue/plugins/webplugin_impl.cc @@ -298,8 +298,8 @@ void WebPluginImpl::updateGeometry( } void WebPluginImpl::updateFocus(bool focused) { - if (focused && accepts_input_events_) - delegate_->SetFocus(); + if (accepts_input_events_) + delegate_->SetFocus(focused); } void WebPluginImpl::updateVisibility(bool visible) { |