summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorstuartmorgan@chromium.org <stuartmorgan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-30 18:02:11 +0000
committerstuartmorgan@chromium.org <stuartmorgan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-30 18:02:11 +0000
commit6c9c89b561f7f4469d382dc89ec0aced264463af (patch)
treee9b5ae1119bd2698e66dd00258e307c87e811199 /webkit
parentcbde1b2150a384562d6f0e10defc5a31de644d6d (diff)
downloadchromium_src-6c9c89b561f7f4469d382dc89ec0aced264463af.zip
chromium_src-6c9c89b561f7f4469d382dc89ec0aced264463af.tar.gz
chromium_src-6c9c89b561f7f4469d382dc89ec0aced264463af.tar.bz2
Work around coordinate problems in page zoom for Mac plugins
This is a temporary fix until the underlying problem with coordinates in windowless plugins is fixed at the WebKit level, since it's a more serious problem on the Mac (due to all plugins being windowless). Using what we know about the plugin location on screen, we infer zoom levels from the coordinates and correct the coordinates (to within a pixel or two, which is the best we can do with the already-rounded values we are given). BUG=26466 TEST=Zoom a page with plugins on the Mac; mouse interaction should work correctly. Review URL: http://codereview.chromium.org/1594001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@43106 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/glue/plugins/plugin_web_event_converter_mac.h6
-rw-r--r--webkit/glue/plugins/plugin_web_event_converter_mac.mm28
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.h7
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl_mac.mm51
4 files changed, 88 insertions, 4 deletions
diff --git a/webkit/glue/plugins/plugin_web_event_converter_mac.h b/webkit/glue/plugins/plugin_web_event_converter_mac.h
index ec5b86f..02f113a 100644
--- a/webkit/glue/plugins/plugin_web_event_converter_mac.h
+++ b/webkit/glue/plugins/plugin_web_event_converter_mac.h
@@ -25,6 +25,12 @@ class PluginWebEventConverter {
// could not be converted.
virtual bool InitWithEvent(const WebKit::WebInputEvent& web_event);
+ // Sets a zoom level to apply to mouse coordinates. Must be called after
+ // InitWithEvent.
+ // TODO(stuartmorgan): Re-evaluate whether this is necessary when
+ // http://crbug.com/9996 is fixed.
+ virtual void SetZoomLevel(float zoom) = 0;
+
// Returns a pointer to a plugin event--suitable for passing to
// NPP_HandleEvent--corresponding to the the web event this converter was
// created with. The pointer is valid only as long as this object is.
diff --git a/webkit/glue/plugins/plugin_web_event_converter_mac.mm b/webkit/glue/plugins/plugin_web_event_converter_mac.mm
index 030ed06..d8b5c05 100644
--- a/webkit/glue/plugins/plugin_web_event_converter_mac.mm
+++ b/webkit/glue/plugins/plugin_web_event_converter_mac.mm
@@ -49,6 +49,8 @@ class CarbonPluginWebEventConverter : public PluginWebEventConverter {
virtual bool InitWithEvent(const WebInputEvent& web_event);
+ virtual void SetZoomLevel(float zooom);
+
virtual void* plugin_event() { return &carbon_event_; }
protected:
@@ -75,6 +77,12 @@ bool CarbonPluginWebEventConverter::InitWithEvent(
return PluginWebEventConverter::InitWithEvent(web_event);
}
+void CarbonPluginWebEventConverter::SetZoomLevel(float zoom) {
+ // Nothing to do here; because the event is built using the WebMouseEvent's
+ // global coordinates, and the dummy window is in the right place, zoom has
+ // no effect.
+}
+
bool CarbonPluginWebEventConverter::ConvertKeyboardEvent(
const WebKeyboardEvent& key_event) {
// TODO: Figure out how to handle Unicode input to plugins, if that's
@@ -177,6 +185,8 @@ public:
virtual bool InitWithEvent(const WebInputEvent& web_event);
+ virtual void SetZoomLevel(float zoom);
+
virtual void* plugin_event() { return &cocoa_event_; }
protected:
@@ -202,6 +212,24 @@ bool CocoaPluginWebEventConverter::InitWithEvent(
return PluginWebEventConverter::InitWithEvent(web_event);
}
+void CocoaPluginWebEventConverter::SetZoomLevel(float zoom) {
+ // Make sure we are dealing with a mouse event.
+ if (!(cocoa_event_.type != NPCocoaEventMouseDown ||
+ cocoa_event_.type != NPCocoaEventMouseUp ||
+ cocoa_event_.type != NPCocoaEventMouseMoved ||
+ cocoa_event_.type != NPCocoaEventMouseEntered ||
+ cocoa_event_.type != NPCocoaEventMouseExited ||
+ cocoa_event_.type != NPCocoaEventMouseDragged ||
+ cocoa_event_.type != NPCocoaEventScrollWheel)) {
+ NOTREACHED();
+ return;
+ }
+ cocoa_event_.data.mouse.pluginX =
+ round(cocoa_event_.data.mouse.pluginX * zoom);
+ cocoa_event_.data.mouse.pluginY =
+ round(cocoa_event_.data.mouse.pluginY * zoom);
+}
+
bool CocoaPluginWebEventConverter::ConvertKeyboardEvent(
const WebKeyboardEvent& key_event) {
cocoa_event_.data.key.keyCode = key_event.nativeKeyCode;
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h
index 2582d9b..a66f282 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.h
+++ b/webkit/glue/plugins/webplugin_delegate_impl.h
@@ -387,6 +387,13 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
// Updates everything that depends on the plugin's absolute screen location.
void PluginScreenLocationChanged();
+ // 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
+ // fixed we should have correct event coordinates (or an explicit
+ // notification of zoom level).
+ float ApparentEventZoomLevel(const WebKit::WebMouseEvent& event);
+
// Informs the browser about the updated accelerated drawing surface.
void UpdateAcceleratedSurface();
diff --git a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
index a99c39e..1d0b138 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
+++ b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
@@ -995,6 +995,37 @@ static bool EventIsRelatedToDrag(const WebInputEvent& event, int drag_buttons) {
return false;
}
+float WebPluginDelegateImpl::ApparentEventZoomLevel(
+ const WebMouseEvent& event) {
+ float real_window_x = event.globalX - content_area_origin_.x();
+ float real_window_y = event.globalY - content_area_origin_.y();
+ if ((real_window_x == 0 && real_window_y == 0) ||
+ (event.windowX == 0 && event.windowY == 0))
+ return 1.0;
+ // There are two ways the window coordinates could be mismatched:
+ // 1) The plugin is zoomed (the event coordinates are scaled for the zoom
+ // level, even though window_rect_ isn't: <http://crbug.com/9996>).
+ // 2) The tracking of where the window is has gotten out of sync with reality.
+ // To distinguish, see if a zoom would explain both the x and y offsets.
+ // If not, this isn't a zoom.
+
+ // Figure out the apparent zoom ratio using the larger value, since it's less
+ // affected by rounding error, then see if the other value is consistent.
+ float apparent_zoom = 1.0;
+ float discrepancy = 0.0;
+ if (event.windowY > event.windowX) {
+ apparent_zoom = real_window_y / event.windowY;
+ discrepancy = fabsf(event.windowX * apparent_zoom - real_window_x);
+ } else {
+ apparent_zoom = real_window_x / event.windowX;
+ discrepancy = fabsf(event.windowY * apparent_zoom - real_window_y);
+ }
+ if (discrepancy > 2.5)
+ return 1.0;
+
+ return apparent_zoom;
+}
+
bool WebPluginDelegateImpl::PlatformHandleInputEvent(
const WebInputEvent& event, WebCursorInfo* cursor_info) {
DCHECK(cursor_info != NULL);
@@ -1009,7 +1040,10 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent(
}
#endif
- if (WebInputEvent::isMouseEventType(event.type)) {
+ float zoom_level = 1.0;
+ const float kEpsilon = 0.001; // Smaller than an actual zoom would ever be.
+ if (WebInputEvent::isMouseEventType(event.type) ||
+ event.type == WebInputEvent::MouseWheel) {
// 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 =
@@ -1019,9 +1053,15 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent(
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_origin);
+ // If there's a mismatch, figure out if it's due to zooming, or a missed
+ // window/plugin move (see comment in ApparentEventZoomLevel).
+ zoom_level = ApparentEventZoomLevel(*mouse_event);
+ if (fabsf(zoom_level - 1.0) < kEpsilon) {
+ DLOG(WARNING) << "Stale plugin content area location: "
+ << content_area_origin_ << " instead of "
+ << content_origin;
+ SetContentAreaOrigin(content_origin);
+ }
}
current_windowless_cursor_.GetCursorInfo(cursor_info);
@@ -1085,6 +1125,9 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent(
if (!(event_converter.get() && event_converter->InitWithEvent(event)))
return false;
void* plugin_event = event_converter->plugin_event();
+
+ if (fabsf(zoom_level - 1.0) > kEpsilon)
+ event_converter->SetZoomLevel(zoom_level);
if (instance()->event_model() == NPEventModelCocoa) {
// We recieve events related to drags starting outside the plugin, but the