Bug 376679 part.2 EventStateManager should treat plugin frame as scrollable frame if the plugin wants to handle wheel events as default action r=smaug

This commit is contained in:
Masayuki Nakano 2015-10-16 13:19:27 +09:00
Родитель 1376b5162b
Коммит 5f2c3f035e
4 изменённых файлов: 102 добавлений и 8 удалений

Просмотреть файл

@ -50,6 +50,7 @@
#include "nsIContentViewer.h"
#include "nsFrameManager.h"
#include "nsITabChild.h"
#include "nsPluginFrame.h"
#include "nsIDOMXULElement.h"
#include "nsIDOMKeyEvent.h"
@ -2346,6 +2347,13 @@ EventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
// hasn't moved.
nsIFrame* lastScrollFrame = WheelTransaction::GetTargetFrame();
if (lastScrollFrame) {
if (aOptions & INCLUDE_PLUGIN_AS_TARGET) {
nsPluginFrame* pluginFrame = do_QueryFrame(lastScrollFrame);
if (pluginFrame &&
pluginFrame->WantsToHandleWheelEventAsDefaultAction()) {
return lastScrollFrame;
}
}
nsIScrollableFrame* scrollableFrame =
lastScrollFrame->GetScrollTargetFrame();
if (scrollableFrame) {
@ -2375,6 +2383,18 @@ EventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
// Check whether the frame wants to provide us with a scrollable view.
nsIScrollableFrame* scrollableFrame = scrollFrame->GetScrollTargetFrame();
if (!scrollableFrame) {
// If the frame is a plugin frame, then, the plugin content may handle
// wheel events. Only when the caller computes the scroll target for
// default action handling, we should assume the plugin frame as
// scrollable if the plugin wants to handle wheel events as default
// action.
if (aOptions & INCLUDE_PLUGIN_AS_TARGET) {
nsPluginFrame* pluginFrame = do_QueryFrame(scrollFrame);
if (pluginFrame &&
pluginFrame->WantsToHandleWheelEventAsDefaultAction()) {
return scrollFrame;
}
}
continue;
}
@ -3121,10 +3141,23 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
break;
}
nsIScrollableFrame* scrollTarget =
do_QueryFrame(ComputeScrollTarget(aTargetFrame, wheelEvent,
COMPUTE_DEFAULT_ACTION_TARGET));
nsIFrame* frameToScroll =
ComputeScrollTarget(aTargetFrame, wheelEvent,
COMPUTE_DEFAULT_ACTION_TARGET);
// XXX Temporarily, we should check if the target is a plugin frame
// here. In the following patch, this should be checked before
// checking wheel action since if the default action handler is
// a plugin, our pref shouldn't decide the default action.
nsPluginFrame* pluginFrame = do_QueryFrame(frameToScroll);
if (pluginFrame) {
// XXX Needs to work with WheelTransaction, will be fixed in
// the following patch.
pluginFrame->HandleWheelEventAsDefaultAction(wheelEvent);
break;
}
nsIScrollableFrame* scrollTarget = do_QueryFrame(frameToScroll);
ScrollbarsForWheel::SetActiveScrollTarget(scrollTarget);
nsIFrame* rootScrollFrame = !aTargetFrame ? nullptr :

Просмотреть файл

@ -617,10 +617,11 @@ protected:
// COMPUTE_*.
enum
{
PREFER_MOUSE_WHEEL_TRANSACTION = 1,
PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS = 2,
PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS = 4,
START_FROM_PARENT = 8
PREFER_MOUSE_WHEEL_TRANSACTION = 0x00000001,
PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS = 0x00000002,
PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS = 0x00000004,
START_FROM_PARENT = 0x00000008,
INCLUDE_PLUGIN_AS_TARGET = 0x00000010
};
enum ComputeScrollTargetOptions
{
@ -630,10 +631,13 @@ protected:
// Default action prefers the scrolled element immediately before if it's
// still under the mouse cursor. Otherwise, it prefers the nearest
// scrollable ancestor which will be scrolled actually.
// When this is specified, the result may be nsPluginFrame. In such case,
// the frame doesn't have nsIScrollableFrame interface.
COMPUTE_DEFAULT_ACTION_TARGET =
(PREFER_MOUSE_WHEEL_TRANSACTION |
PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS |
PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS),
PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS |
INCLUDE_PLUGIN_AS_TARGET),
// Look for the nearest scrollable ancestor which can be scrollable with
// aEvent.
COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS =

Просмотреть файл

@ -12,6 +12,7 @@
#include "gfxMatrix.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/BasicEvents.h"
#include "mozilla/MouseEvents.h"
#ifdef XP_WIN
// This is needed for DoublePassRenderingEvent.
#include "mozilla/plugins/PluginMessageUtils.h"
@ -1846,6 +1847,48 @@ nsPluginFrame::HandleEvent(nsPresContext* aPresContext,
return rv;
}
void
nsPluginFrame::HandleWheelEventAsDefaultAction(WidgetWheelEvent* aWheelEvent)
{
MOZ_ASSERT(WantsToHandleWheelEventAsDefaultAction());
MOZ_ASSERT(!aWheelEvent->mFlags.mDefaultPrevented);
if (NS_WARN_IF(!mInstanceOwner) ||
NS_WARN_IF(aWheelEvent->mMessage != eWheel)) {
return;
}
// If the wheel event has native message, it should may be handled by
// HandleEvent() in the future. In such case, we should do nothing here.
if (NS_WARN_IF(!!aWheelEvent->mPluginEvent)) {
return;
}
mInstanceOwner->ProcessEvent(*aWheelEvent);
// We need to assume that the event is always consumed/handled by the
// plugin. There is no way to know if it's actually consumed/handled.
aWheelEvent->mViewPortIsOverscrolled = false;
aWheelEvent->overflowDeltaX = 0;
aWheelEvent->overflowDeltaY = 0;
}
bool
nsPluginFrame::WantsToHandleWheelEventAsDefaultAction() const
{
#ifdef XP_WIN
if (!mInstanceOwner) {
return false;
}
NPWindow* window = nullptr;
mInstanceOwner->GetWindow(window);
// On Windows, only when the plugin is windowless, we need to send wheel
// events as default action.
return window->type == NPWindowTypeDrawable;
#else
return false;
#endif
}
nsresult
nsPluginFrame::GetPluginInstance(nsNPAPIPluginInstance** aPluginInstance)
{

Просмотреть файл

@ -9,6 +9,7 @@
#define nsPluginFrame_h___
#include "mozilla/Attributes.h"
#include "mozilla/EventForwards.h"
#include "nsIObjectFrame.h"
#include "nsFrame.h"
#include "nsRegion.h"
@ -205,6 +206,19 @@ public:
*/
void SetScrollVisibility(bool aState);
/**
* HandleWheelEventAsDefaultAction() handles eWheel event as default action.
* This should be called only when WantsToHandleWheelEventAsDefaultAction()
* returns true.
*/
void HandleWheelEventAsDefaultAction(mozilla::WidgetWheelEvent* aEvent);
/**
* WantsToHandleWheelEventAsDefaultAction() returns true if the plugin
* may want to handle wheel events as default action.
*/
bool WantsToHandleWheelEventAsDefaultAction() const;
protected:
explicit nsPluginFrame(nsStyleContext* aContext);
virtual ~nsPluginFrame();