diff options
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller.mm | 23 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view.h | 3 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_mac.h | 2 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_mac.mm | 44 | ||||
-rw-r--r-- | chrome/browser/renderer_host/test/test_render_view_host.h | 1 | ||||
-rw-r--r-- | chrome/common/plugin_messages.h | 27 | ||||
-rw-r--r-- | chrome/common/plugin_messages_internal.h | 12 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 5 | ||||
-rw-r--r-- | chrome/plugin/webplugin_delegate_stub.cc | 25 | ||||
-rw-r--r-- | chrome/plugin/webplugin_delegate_stub.h | 5 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 25 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 5 | ||||
-rw-r--r-- | chrome/renderer/render_widget.h | 2 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_proxy.cc | 38 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_proxy.h | 2 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.h | 40 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl_mac.mm | 122 |
17 files changed, 288 insertions, 93 deletions
diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm index ae59e2f..d7058e9 100644 --- a/chrome/browser/cocoa/browser_window_controller.mm +++ b/chrome/browser/cocoa/browser_window_controller.mm @@ -1701,6 +1701,12 @@ willPositionSheet:(NSWindow*)sheet if (statusBubble_) { statusBubble_->UpdateSizeAndPosition(); } + + // Let the selected RenderWidgetHostView know, so that it can tell plugins. + if (TabContents* contents = browser_->GetSelectedTabContents()) { + if (RenderWidgetHostView* rwhv = contents->render_widget_host_view()) + rwhv->WindowFrameChanged(); + } } // Handle the openLearnMoreAboutCrashLink: action from SadTabController when @@ -1738,6 +1744,12 @@ willPositionSheet:(NSWindow*)sheet (windowTopGrowth_ > 0 && NSMinY(windowFrame) != NSMinY(workarea)) || (windowBottomGrowth_ > 0 && NSMaxY(windowFrame) != NSMaxY(workarea))) [self resetWindowGrowthState]; + + // Let the selected RenderWidgetHostView know, so that it can tell plugins. + if (TabContents* contents = browser_->GetSelectedTabContents()) { + if (RenderWidgetHostView* rwhv = contents->render_widget_host_view()) + rwhv->WindowFrameChanged(); + } } // Delegate method called when window will be resized; not called for @@ -2114,10 +2126,21 @@ willPositionSheet:(NSWindow*)sheet width:(CGFloat)width { NSView* tabContentView = [self tabContentArea]; NSRect tabContentFrame = [tabContentView frame]; + + bool contentShifted = NSMaxY(tabContentFrame) != maxY; + tabContentFrame.origin.y = minY; tabContentFrame.size.height = maxY - minY; tabContentFrame.size.width = width; [tabContentView setFrame:tabContentFrame]; + + // If the relayout shifts the content area up or down, let the renderer know. + if (contentShifted) { + if (TabContents* contents = browser_->GetSelectedTabContents()) { + if (RenderWidgetHostView* rwhv = contents->render_widget_host_view()) + rwhv->WindowFrameChanged(); + } + } } - (BOOL)shouldShowBookmarkBar { diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h index ccb1b31..f761053 100644 --- a/chrome/browser/renderer_host/render_widget_host_view.h +++ b/chrome/browser/renderer_host/render_widget_host_view.h @@ -171,6 +171,9 @@ class RenderWidgetHostView { // WasHidden/DidBecomeSelected. virtual void SetWindowVisibility(bool visible) = 0; + // Informs the view that its containing window's frame changed. + virtual void WindowFrameChanged() = 0; + // Methods associated with GPU plugin instances virtual gfx::PluginWindowHandle AllocateFakePluginWindowHandle() = 0; virtual void DestroyFakePluginWindowHandle( 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 c9834bf..c707205 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.h +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h @@ -46,6 +46,7 @@ class RWHVMEditCommandHelper; scoped_nsobject<NSString> toolTip_; scoped_nsobject<NSEvent> lastKeyPressedEvent_; + NSWindow* lastWindow_; // weak } - (void)setCanBeKeyView:(BOOL)can; @@ -112,6 +113,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { virtual gfx::Rect GetRootWindowRect(); virtual void SetActive(bool active); virtual void SetWindowVisibility(bool visible); + virtual void WindowFrameChanged(); virtual void SetBackground(const SkBitmap& background); // Methods associated with GPU plugin instances 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 db78a46..c804892 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm @@ -582,13 +582,20 @@ gfx::Rect RenderWidgetHostViewMac::GetWindowRect() { // TODO(shess): In case of !window, the view has been removed from // the view hierarchy because the tab isn't main. Could retrieve // the information from the main tab for our window. - if (!cocoa_view_ || ![cocoa_view_ window]) { + NSWindow* enclosing_window = [cocoa_view_ window]; + if (!cocoa_view_ || !enclosing_window) { return gfx::Rect(); } + // During dragging of a torn-off tab, [cocoa_view_ window] is a floating panel + // attached to the actual browser window that the tab is visually part of; we + // want the bounds of the browser window rather than the panel. + if ([enclosing_window parentWindow]) + enclosing_window = [enclosing_window parentWindow]; + NSRect bounds = [cocoa_view_ bounds]; bounds = [cocoa_view_ convertRect:bounds toView:nil]; - bounds.origin = [[cocoa_view_ window] convertBaseToScreen:bounds.origin]; + bounds.origin = [enclosing_window convertBaseToScreen:bounds.origin]; return NSRectToRect(bounds, [[cocoa_view_ window] screen]); } @@ -596,12 +603,19 @@ gfx::Rect RenderWidgetHostViewMac::GetRootWindowRect() { // TODO(shess): In case of !window, the view has been removed from // the view hierarchy because the tab isn't main. Could retrieve // the information from the main tab for our window. - if (!cocoa_view_ || ![cocoa_view_ window]) { + NSWindow* enclosing_window = [cocoa_view_ window]; + if (!enclosing_window) { return gfx::Rect(); } - NSRect bounds = [[cocoa_view_ window] frame]; - return NSRectToRect(bounds, [[cocoa_view_ window] screen]); + // During dragging of a torn-off tab, [cocoa_view_ window] is a floating panel + // attached to the actual browser window that the tab is visually part of; we + // want the bounds of the browser window rather than the panel. + if ([enclosing_window parentWindow]) + enclosing_window = [enclosing_window parentWindow]; + + NSRect bounds = [enclosing_window frame]; + return NSRectToRect(bounds, [enclosing_window screen]); } void RenderWidgetHostViewMac::SetActive(bool active) { @@ -616,6 +630,14 @@ void RenderWidgetHostViewMac::SetWindowVisibility(bool visible) { } } +void RenderWidgetHostViewMac::WindowFrameChanged() { + if (render_widget_host_) { + render_widget_host_->Send(new ViewMsg_WindowFrameChanged( + render_widget_host_->routing_id(), GetRootWindowRect(), + GetWindowRect())); + } +} + void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) { RenderWidgetHostView::SetBackground(background); if (render_widget_host_) @@ -1518,4 +1540,16 @@ extern NSString *NSTextInputReplacementRangeAttributeName; renderWidgetHostView_->im_composing_ = false; } +- (void)viewDidMoveToWindow { + // If we move into a new window, refresh the frame information. We don't need + // to do it if it was the same window as it used to be in, since that case + // is covered by DidBecomeSelected. + NSWindow* newWindow = [self window]; + // Pointer comparison only, since we don't know if lastWindow_ is still valid. + if (newWindow && (newWindow != lastWindow_)) { + lastWindow_ = newWindow; + renderWidgetHostView_->WindowFrameChanged(); + } +} + @end 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 fde21b5..0521de9 100644 --- a/chrome/browser/renderer_host/test/test_render_view_host.h +++ b/chrome/browser/renderer_host/test/test_render_view_host.h @@ -78,6 +78,7 @@ class TestRenderWidgetHostView : public RenderWidgetHostView { virtual gfx::Rect GetRootWindowRect(); virtual void SetActive(bool active); virtual void SetWindowVisibility(bool visible) {} + virtual void WindowFrameChanged() {} virtual gfx::PluginWindowHandle AllocateFakePluginWindowHandle(); virtual void DestroyFakePluginWindowHandle(gfx::PluginWindowHandle window); virtual void GPUPluginSetIOSurface(gfx::PluginWindowHandle window, diff --git a/chrome/common/plugin_messages.h b/chrome/common/plugin_messages.h index 74de33f..b195f5c 100644 --- a/chrome/common/plugin_messages.h +++ b/chrome/common/plugin_messages.h @@ -39,6 +39,11 @@ struct PluginMsg_Init_Params { std::vector<std::string> arg_values; bool load_manually; int host_render_view_routing_id; +#if defined(OS_MACOSX) + gfx::Rect containing_window_frame; + gfx::Rect containing_content_frame; + bool containing_window_has_focus; +#endif }; struct PluginHostMsg_URLRequest_Params { @@ -119,6 +124,11 @@ struct ParamTraits<PluginMsg_Init_Params> { WriteParam(m, p.arg_values); WriteParam(m, p.load_manually); WriteParam(m, p.host_render_view_routing_id); +#if defined(OS_MACOSX) + WriteParam(m, p.containing_window_frame); + WriteParam(m, p.containing_content_frame); + WriteParam(m, p.containing_window_has_focus); +#endif } static bool Read(const Message* m, void** iter, param_type* p) { return ReadParam(m, iter, &p->containing_window) && @@ -127,7 +137,14 @@ struct ParamTraits<PluginMsg_Init_Params> { ReadParam(m, iter, &p->arg_names) && ReadParam(m, iter, &p->arg_values) && ReadParam(m, iter, &p->load_manually) && - ReadParam(m, iter, &p->host_render_view_routing_id); + ReadParam(m, iter, &p->host_render_view_routing_id) +#if defined(OS_MACOSX) + && + ReadParam(m, iter, &p->containing_window_frame) && + ReadParam(m, iter, &p->containing_content_frame) && + ReadParam(m, iter, &p->containing_window_has_focus) +#endif + ; } static void Log(const param_type& p, std::wstring* l) { l->append(L"("); @@ -144,6 +161,14 @@ struct ParamTraits<PluginMsg_Init_Params> { LogParam(p.load_manually, l); l->append(L", "); LogParam(p.host_render_view_routing_id, l); +#if defined(OS_MACOSX) + l->append(L", "); + LogParam(p.containing_window_frame, l); + l->append(L", "); + LogParam(p.containing_content_frame, l); + l->append(L", "); + LogParam(p.containing_window_has_focus, l); +#endif l->append(L")"); } }; diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h index 05e532b..b5908a8 100644 --- a/chrome/common/plugin_messages_internal.h +++ b/chrome/common/plugin_messages_internal.h @@ -233,8 +233,16 @@ IPC_BEGIN_MESSAGES(Plugin) IPC_MESSAGE_ROUTED1(PluginMsg_SetWindowFocus, bool /* has_focus */) - IPC_MESSAGE_ROUTED1(PluginMsg_SetContainerVisibility, - bool /* is_visible */) + IPC_MESSAGE_ROUTED0(PluginMsg_ContainerHidden) + + IPC_MESSAGE_ROUTED3(PluginMsg_ContainerShown, + gfx::Rect /* window_frame */, + gfx::Rect /* view_frame */, + bool /* has_focus */) + + IPC_MESSAGE_ROUTED2(PluginMsg_WindowFrameChanged, + gfx::Rect /* window_frame */, + gfx::Rect /* view_frame */) #endif IPC_SYNC_MESSAGE_ROUTED2_0(PluginMsg_WillSendRequest, diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index bd23f31..69d7bb2 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -745,6 +745,11 @@ IPC_BEGIN_MESSAGES(View) // Let the RenderView know its window has changed visibility. IPC_MESSAGE_ROUTED1(ViewMsg_SetWindowVisibility, bool /* visibile */) + + // Let the RenderView know its window's frame has changed. + IPC_MESSAGE_ROUTED2(ViewMsg_WindowFrameChanged, + gfx::Rect /* window frame */, + gfx::Rect /* content view frame */) #endif // Response message to ViewHostMsg_CreateShared/DedicatedWorker. diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc index 80d6e62..a24f7fa 100644 --- a/chrome/plugin/webplugin_delegate_stub.cc +++ b/chrome/plugin/webplugin_delegate_stub.cc @@ -123,8 +123,9 @@ void WebPluginDelegateStub::OnMessageReceived(const IPC::Message& msg) { OnSendJavaScriptStream) #if defined(OS_MACOSX) IPC_MESSAGE_HANDLER(PluginMsg_SetWindowFocus, OnSetWindowFocus) - IPC_MESSAGE_HANDLER(PluginMsg_SetContainerVisibility, - OnSetContainerVisibility) + IPC_MESSAGE_HANDLER(PluginMsg_ContainerHidden, OnContainerHidden) + IPC_MESSAGE_HANDLER(PluginMsg_ContainerShown, OnContainerShown) + IPC_MESSAGE_HANDLER(PluginMsg_WindowFrameChanged, OnWindowFrameChanged) #endif IPC_MESSAGE_HANDLER(PluginMsg_DidReceiveManualResponse, OnDidReceiveManualResponse) @@ -195,6 +196,9 @@ void WebPluginDelegateStub::OnInit(const PluginMsg_Init_Params& params, params.load_manually); #if defined(OS_MACOSX) delegate_->SetFocusNotifier(FocusNotifier); + delegate_->WindowFrameChanged(params.containing_window_frame, + params.containing_content_frame); + delegate_->SetWindowHasFocus(params.containing_window_has_focus); #endif } } @@ -345,8 +349,21 @@ void WebPluginDelegateStub::OnSetWindowFocus(bool has_focus) { delegate_->SetWindowHasFocus(has_focus); } -void WebPluginDelegateStub::OnSetContainerVisibility(bool is_visible) { - delegate_->SetContainerVisibility(is_visible); +void WebPluginDelegateStub::OnContainerHidden() { + delegate_->SetContainerVisibility(false); +} + +void WebPluginDelegateStub::OnContainerShown(gfx::Rect window_frame, + gfx::Rect view_frame, + bool has_focus) { + delegate_->WindowFrameChanged(window_frame, view_frame); + delegate_->SetContainerVisibility(true); + delegate_->SetWindowHasFocus(has_focus); +} + +void WebPluginDelegateStub::OnWindowFrameChanged(gfx::Rect window_frame, + gfx::Rect view_frame) { + delegate_->WindowFrameChanged(window_frame, view_frame); } #endif // OS_MACOSX diff --git a/chrome/plugin/webplugin_delegate_stub.h b/chrome/plugin/webplugin_delegate_stub.h index 5a04758..efe93c10 100644 --- a/chrome/plugin/webplugin_delegate_stub.h +++ b/chrome/plugin/webplugin_delegate_stub.h @@ -80,7 +80,10 @@ class WebPluginDelegateStub : public IPC::Channel::Listener, #if defined(OS_MACOSX) void OnSetWindowFocus(bool has_focus); - void OnSetContainerVisibility(bool is_visible); + void OnContainerHidden(); + void OnContainerShown(gfx::Rect window_frame, gfx::Rect view_frame, + bool has_focus); + void OnWindowFrameChanged(gfx::Rect window_frame, gfx::Rect view_frame); #endif void OnDidReceiveManualResponse( diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index aa433bd..08cb4e0 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -579,6 +579,7 @@ void RenderView::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewMsg_SetActive, OnSetActive) #if defined(OS_MACOSX) IPC_MESSAGE_HANDLER(ViewMsg_SetWindowVisibility, OnSetWindowVisibility) + IPC_MESSAGE_HANDLER(ViewMsg_WindowFrameChanged, OnWindowFrameChanged) #endif IPC_MESSAGE_HANDLER(ViewMsg_SetEditCommandsForNextKeyEvent, OnSetEditCommandsForNextKeyEvent) @@ -3812,6 +3813,16 @@ void RenderView::OnSetWindowVisibility(bool visible) { (*plugin_it)->SetContainerVisibility(visible); } } + +void RenderView::OnWindowFrameChanged(gfx::Rect window_frame, + gfx::Rect view_frame) { + // Inform plugins that their window's frame has changed. + std::set<WebPluginDelegateProxy*>::iterator plugin_it; + for (plugin_it = plugin_delegates_.begin(); + plugin_it != plugin_delegates_.end(); ++plugin_it) { + (*plugin_it)->WindowFrameChanged(window_frame, view_frame); + } +} #endif // OS_MACOSX void RenderView::SendExtensionRequest(const std::string& name, @@ -4335,6 +4346,20 @@ void RenderView::OnWasRestored(bool needs_repainting) { (*plugin_it)->SetContainerVisibility(true); } } + +void RenderView::OnSetFocus(bool enable) { + RenderWidget::OnSetFocus(enable); + + // RenderWidget's call to setFocus can cause the underlying webview's + // activation state to change just like a call to setIsActive. + if (enable && webview() && webview()->isActive()) { + std::set<WebPluginDelegateProxy*>::iterator plugin_it; + for (plugin_it = plugin_delegates_.begin(); + plugin_it != plugin_delegates_.end(); ++plugin_it) { + (*plugin_it)->SetWindowFocus(true); + } + } +} #endif // OS_MACOSX void RenderView::EnsureDocumentTag() { diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 7245df1..0066bf3 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -484,6 +484,7 @@ class RenderView : public RenderWidget, virtual void DidPaint(); virtual void DidHandleKeyEvent(); #if OS_MACOSX + virtual void OnSetFocus(bool enable); virtual void OnWasHidden(); virtual void OnWasRestored(bool needs_repainting); #endif @@ -725,6 +726,10 @@ class RenderView : public RenderWidget, #if defined(OS_MACOSX) void OnSetWindowVisibility(bool visible); + + // Notifies the view that window frame has been updated. window_frame and + // view_frame are in screen coordinates. + void OnWindowFrameChanged(gfx::Rect window_frame, gfx::Rect view_frame); #endif // Execute custom context menu action. diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h index 86f2a17..27086a4 100644 --- a/chrome/renderer/render_widget.h +++ b/chrome/renderer/render_widget.h @@ -146,7 +146,7 @@ class RenderWidget : public IPC::Channel::Listener, void OnRequestMoveAck(); void OnHandleInputEvent(const IPC::Message& message); void OnMouseCaptureLost(); - void OnSetFocus(bool enable); + virtual void OnSetFocus(bool enable); void OnImeSetInputMode(bool is_active); void OnImeSetComposition(WebKit::WebCompositionCommand command, int cursor_position, diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc index 2c87077..f4063e4 100644 --- a/chrome/renderer/webplugin_delegate_proxy.cc +++ b/chrome/renderer/webplugin_delegate_proxy.cc @@ -283,6 +283,18 @@ bool WebPluginDelegateProxy::Initialize(const GURL& url, params.arg_names.push_back("wmode"); params.arg_values.push_back("opaque"); } + + params.containing_window_frame = render_view_->rootWindowRect(); + // If the renderer isn't currently visible, don't bother asking for anything + // else; the plugin will get real data when its renderer becomes visible. + if (params.containing_window_frame.IsEmpty()) { + params.containing_content_frame = gfx::Rect(); + params.containing_window_has_focus = false; + } else { + params.containing_content_frame = render_view_->windowRect(); + WebKit::WebView* webview = render_view_->webview(); + params.containing_window_has_focus = webview && webview->isActive(); + } #endif params.load_manually = load_manually; @@ -874,16 +886,32 @@ void WebPluginDelegateProxy::SetWindowFocus(bool window_has_focus) { } void WebPluginDelegateProxy::SetContainerVisibility(bool is_visible) { - // TODO(stuartmorgan): Split this into two messages, and send location and - // focus information with the "became visible" version since the plugins in a - // hidden tab will not have been getting live updates. - IPC::Message* msg = new PluginMsg_SetContainerVisibility(instance_id_, - is_visible); + IPC::Message* msg; + if (is_visible) { + gfx::Rect window_frame = render_view_->rootWindowRect(); + gfx::Rect view_frame = render_view_->windowRect(); + WebKit::WebView* webview = render_view_->webview(); + msg = new PluginMsg_ContainerShown(instance_id_, window_frame, view_frame, + webview && webview->isActive()); + } else { + msg = new PluginMsg_ContainerHidden(instance_id_); + } // Make sure visibility events are delivered in the right order relative to // sync messages they might interact with (Paint, HandleEvent, etc.). msg->set_unblock(true); Send(msg); } + +void WebPluginDelegateProxy::WindowFrameChanged(gfx::Rect window_frame, + gfx::Rect view_frame) { + IPC::Message* msg = new PluginMsg_WindowFrameChanged(instance_id_, + window_frame, + view_frame); + // Make sure frame events are delivered in the right order relative to + // sync messages they might interact with (e.g., HandleEvent). + msg->set_unblock(true); + Send(msg); +} #endif // OS_MACOSX void WebPluginDelegateProxy::OnSetWindow(gfx::PluginWindowHandle window) { diff --git a/chrome/renderer/webplugin_delegate_proxy.h b/chrome/renderer/webplugin_delegate_proxy.h index 1afbacd9..98eb1ee 100644 --- a/chrome/renderer/webplugin_delegate_proxy.h +++ b/chrome/renderer/webplugin_delegate_proxy.h @@ -75,6 +75,8 @@ class WebPluginDelegateProxy virtual void SetWindowFocus(bool window_has_focus); // Inform the plugin that its container (window/tab) has changed visibility. virtual void SetContainerVisibility(bool is_visible); + // Inform the plugin that its enclosing window's frame has changed. + virtual void WindowFrameChanged(gfx::Rect window_frame, gfx::Rect view_frame); #endif // IPC::Channel::Listener implementation: diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h index 32dca05..7978964 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.h +++ b/webkit/glue/plugins/webplugin_delegate_impl.h @@ -134,6 +134,9 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { bool GetWindowHasFocus() const { return containing_window_has_focus_; } // Informs the plugin that its tab or window has been hidden or shown. void SetContainerVisibility(bool is_visible); + // Informs the plugin that its containing window's frame has changed. + // Frames are in screen coordinates. + void WindowFrameChanged(gfx::Rect window_frame, gfx::Rect view_frame); // Informs the delegate that the plugin set a Carbon ThemeCursor. void SetThemeCursor(ThemeCursor cursor); // Informs the delegate that the plugin set a Carbon Cursor. @@ -336,45 +339,40 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { LPWSTR class_name, LPDWORD class_size, PFILETIME last_write_time); #elif defined(OS_MACOSX) - - // Updates the internal information about where the plugin is located on - // the screen. - void UpdatePluginLocation(const WebKit::WebMouseEvent& event); + // Sets window_rect_ to |rect| + void SetPluginRect(const gfx::Rect& rect); + // Sets content_area_origin to |origin| + void SetContentAreaOrigin(const gfx::Point& origin); + // Updates everything that depends on the plugin's absolute screen location. + void PluginScreenLocationChanged(); #ifndef NP_NO_CARBON - // Moves our dummy window to the given offset relative to the last known - // location of the real renderer window's content view. - // If new_width or new_height is non-zero, the window size (content region) - // will be updated accordingly; if they are zero, the existing size will be - // preserved. - void UpdateDummyWindowBoundsWithOffset(int x_offset, int y_offset, - int new_width, int new_height); + // Moves our dummy window to match the current screen location of the plugin. + void UpdateDummyWindowBounds(const gfx::Point& plugin_origin); // Adjusts the idle event rate for a Carbon plugin based on its current // visibility. void UpdateIdleEventRate(); #endif // !NP_NO_CARBON - // The most recently seen offset between global and browser-window-local - // coordinates. We use this to keep the placeholder Carbon WindowRef's origin - // in sync with the actual browser window, without having to pass that - // geometry over IPC. - int last_window_x_offset_; - int last_window_y_offset_; + // Note: the following coordinates are all in screen coordinates, relative an + // upper-left (0,0). + // The frame of the window containing this plugin. + gfx::Rect containing_window_frame_; + // The upper-left corner of the web content area. + gfx::Point content_area_origin_; - // Last mouse position within the plugin's rect (used for null events). - int last_mouse_x_; - int last_mouse_y_; // 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 containing_window_has_focus_; + bool initial_window_focus_; bool container_is_visible_; bool have_called_set_window_; gfx::Rect cached_clip_rect_; -#endif +#endif // OS_MACOSX // Called by the message filter hook when the plugin enters a modal loop. void OnModalLoopEntered(); diff --git a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm index a7d93f9..2955ec5 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm +++ b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm @@ -176,13 +176,10 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( instance_(instance), parent_(containing_view), quirks_(0), - last_window_x_offset_(0), - last_window_y_offset_(0), - last_mouse_x_(0), - last_mouse_y_(0), have_focus_(false), focus_notifier_(NULL), containing_window_has_focus_(false), + initial_window_focus_(false), container_is_visible_(false), have_called_set_window_(false), handle_event_depth_(0), @@ -354,7 +351,7 @@ void WebPluginDelegateImpl::WindowlessUpdateGeometry( bool new_clip_is_empty = clip_rect_.IsEmpty(); // Only resend to the instance if the geometry has changed (see note in - // WindowlesSetWindow for why we only care about the clip rect switching + // WindowlessSetWindow for why we only care about the clip rect switching // empty state). if (window_rect == window_rect_ && old_clip_was_empty == new_clip_is_empty) return; @@ -367,7 +364,7 @@ void WebPluginDelegateImpl::WindowlessUpdateGeometry( } #endif - window_rect_ = window_rect; + SetPluginRect(window_rect); WindowlessSetWindow(true); } @@ -459,19 +456,12 @@ void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) { window_.clipRect.bottom += window_.height; } - UpdateDummyWindowBoundsWithOffset(window_rect_.x(), window_rect_.y(), - window_rect_.width(), - window_rect_.height()); - NPError err = instance()->NPP_SetWindow(&window_); - // Plugins expect to get an initial window focus call if they are in an active - // window when they get their first SetWindow call. + // Send an appropriate window focus event after the first SetWindow. if (!have_called_set_window_) { - // TODO(stuartmorgan): We need real window information about the initial - // window state; for now, assume window focus. - SetWindowHasFocus(true); have_called_set_window_ = true; + SetWindowHasFocus(initial_window_focus_); } DCHECK(err == NPERR_NO_ERROR); @@ -525,6 +515,13 @@ void WebPluginDelegateImpl::SetFocus() { } 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 == containing_window_has_focus_) return; containing_window_has_focus_ = has_focus; @@ -587,6 +584,12 @@ void WebPluginDelegateImpl::SetContainerVisibility(bool is_visible) { } } +void WebPluginDelegateImpl::WindowFrameChanged(gfx::Rect window_frame, + gfx::Rect view_frame) { + containing_window_frame_ = window_frame; + SetContentAreaOrigin(gfx::Point(view_frame.x(), view_frame.y())); +} + void WebPluginDelegateImpl::SetThemeCursor(ThemeCursor cursor) { current_windowless_cursor_.InitFromThemeCursor(cursor); } @@ -599,48 +602,52 @@ void WebPluginDelegateImpl::SetNSCursor(NSCursor* cursor) { current_windowless_cursor_.InitFromNSCursor(cursor); } -void WebPluginDelegateImpl::UpdatePluginLocation(const WebMouseEvent& event) { - instance()->set_plugin_origin(gfx::Point(event.globalX - event.x, - event.globalY - event.y)); +void WebPluginDelegateImpl::SetPluginRect(const gfx::Rect& rect) { + window_rect_ = rect; + PluginScreenLocationChanged(); +} - if (instance()->event_model() == NPEventModelCarbon) { - last_window_x_offset_ = event.globalX - event.windowX; - last_window_y_offset_ = event.globalY - event.windowY; - last_mouse_x_ = event.globalX; - last_mouse_y_ = event.globalY; +void WebPluginDelegateImpl::SetContentAreaOrigin(const gfx::Point& origin) { + content_area_origin_ = origin; + PluginScreenLocationChanged(); +} + +void WebPluginDelegateImpl::PluginScreenLocationChanged() { + gfx::Point plugin_origin(content_area_origin_.x() + window_rect_.x(), + content_area_origin_.y() + window_rect_.y()); + instance()->set_plugin_origin(plugin_origin); #ifndef NP_NO_CARBON - UpdateDummyWindowBoundsWithOffset(event.windowX - event.x, - event.windowY - event.y, 0, 0); + if (instance()->event_model() == NPEventModelCarbon) { + UpdateDummyWindowBounds(plugin_origin); } #endif } #ifndef NP_NO_CARBON -void WebPluginDelegateImpl::UpdateDummyWindowBoundsWithOffset( - int x_offset, int y_offset, int new_width, int new_height) { - if (instance()->event_model() == NPEventModelCocoa) - return; - - int target_x = last_window_x_offset_ + x_offset; - int target_y = last_window_y_offset_ + y_offset; +void WebPluginDelegateImpl::UpdateDummyWindowBounds( + const gfx::Point& plugin_origin) { WindowRef window = reinterpret_cast<WindowRef>(cg_context_.window); - Rect window_bounds; - GetWindowBounds(window, kWindowContentRgn, &window_bounds); - int old_width = window_bounds.right - window_bounds.left; - int old_height = window_bounds.bottom - window_bounds.top; - if (window_bounds.left != target_x || - window_bounds.top != target_y || - (new_width && new_width != old_width) || - (new_height && new_height != old_height)) { - int height = new_height ? new_height : old_height; - int width = new_width ? new_width : old_width; - window_bounds.left = target_x; - window_bounds.top = target_y; - window_bounds.right = window_bounds.left + width; - window_bounds.bottom = window_bounds.top + height; - SetWindowBounds(window, kWindowContentRgn, &window_bounds); + Rect current_bounds; + GetWindowBounds(window, kWindowContentRgn, ¤t_bounds); + + Rect new_bounds; + // We never want to resize the window to 0x0, so if the plugin is 0x0 just + // move the window without resizing it. + if (window_rect_.width() > 0 && window_rect_.height() > 0) { + SetRect(&new_bounds, 0, 0, window_rect_.width(), window_rect_.height()); + OffsetRect(&new_bounds, plugin_origin.x(), plugin_origin.y()); + } else { + new_bounds = current_bounds; + OffsetRect(&new_bounds, plugin_origin.x() - current_bounds.left, + plugin_origin.y() - current_bounds.top); } + + if (new_bounds.left != current_bounds.left || + new_bounds.top != current_bounds.top || + new_bounds.right != current_bounds.right || + new_bounds.bottom != current_bounds.bottom) + SetWindowBounds(window, kWindowContentRgn, &new_bounds); } void WebPluginDelegateImpl::UpdateIdleEventRate() { @@ -932,12 +939,19 @@ bool WebPluginDelegateImpl::HandleInputEvent(const WebInputEvent& event, #endif if (WebInputEventIsWebMouseEvent(event)) { - // Make sure we update our plugin location tracking before we send the - // event to the plugin, so that any coordinate conversion the plugin does - // will work out. + // Check our plugin location before we send the event to the plugin, just + // in case we somehow missed a plugin frame change. const WebMouseEvent* mouse_event = static_cast<const WebMouseEvent*>(&event); - UpdatePluginLocation(*mouse_event); + gfx::Point content_origin( + mouse_event->globalX - mouse_event->x - window_rect_.x(), + mouse_event->globalY - mouse_event->y - window_rect_.y()); + if (content_origin.x() != content_area_origin_.x() || + content_origin.y() != content_area_origin_.y()) { + DLOG(WARNING) << "Stale plugin location: " << content_area_origin_ + << " instead of " << content_origin; + SetContentAreaOrigin(content_area_origin_); + } current_windowless_cursor_.GetCursorInfo(cursor); } @@ -1057,8 +1071,10 @@ void WebPluginDelegateImpl::FireIdleEvent() { np_event.modifiers = GetCurrentKeyModifiers(); if (!Button()) np_event.modifiers |= btnState; - np_event.where.h = last_mouse_x_; - np_event.where.v = last_mouse_y_; + HIPoint mouse_location; + HIGetMousePosition(kHICoordSpaceScreenPixel, NULL, &mouse_location); + np_event.where.h = mouse_location.x; + np_event.where.v = mouse_location.y; instance()->NPP_HandleEvent(&np_event); } |