зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1345398 - Fire WidgetMouseEvent by handling pen generated mouse messages to get Windows native dnd supports. r=jimm
Due to Windows doesn't support dnd in the pen message handler, we can't handle and consume WM_POINTER* to fire WidgetMouseEvent. On the other hand, we can't get some pen related attributes from Windows mouse messages. This patch gets and caches the attributes by handling WM_POINTER* but not fire WidgetMouseEvent to support dnd and pen related attributes. When handling the subsequent Windows mouse messages, we use the cached attributes to fire WidgetMouseEvent. Considering we might need to use WM_POINTER* someday, use a preference to control the behavior. MozReview-Commit-ID: 5E60KO1zo0W
This commit is contained in:
Родитель
9672dfeb91
Коммит
c2ff93f196
|
@ -4913,6 +4913,12 @@ pref("dom.w3c_pointer_events.enabled", true);
|
|||
pref("dom.w3c_pointer_events.enabled", false);
|
||||
#endif
|
||||
|
||||
// Control firing WidgetMouseEvent by handling Windows pointer messages or mouse
|
||||
// messages.
|
||||
#if defined(XP_WIN)
|
||||
pref("dom.w3c_pointer_events.dispatch_by_pointer_messages", false);
|
||||
#endif
|
||||
|
||||
// W3C pointer events draft
|
||||
pref("dom.w3c_pointer_events.implicit_capture", false);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ WinPointerEvents::GetPointerTypePtr WinPointerEvents::getPointerType = nullptr;
|
|||
WinPointerEvents::GetPointerInfoPtr WinPointerEvents::getPointerInfo = nullptr;
|
||||
WinPointerEvents::GetPointerPenInfoPtr WinPointerEvents::getPointerPenInfo = nullptr;
|
||||
bool WinPointerEvents::sPointerEventEnabled = true;
|
||||
bool WinPointerEvents::sFirePointerEventsByWinPointerMessages = false;
|
||||
|
||||
WinPointerEvents::WinPointerEvents()
|
||||
{
|
||||
|
@ -29,6 +30,9 @@ WinPointerEvents::WinPointerEvents()
|
|||
if (!addedPointerEventEnabled) {
|
||||
Preferences::AddBoolVarCache(&sPointerEventEnabled,
|
||||
"dom.w3c_pointer_events.enabled", true);
|
||||
Preferences::AddBoolVarCache(
|
||||
&sFirePointerEventsByWinPointerMessages,
|
||||
"dom.w3c_pointer_events.dispatch_by_pointer_messages", false);
|
||||
addedPointerEventEnabled = true;
|
||||
}
|
||||
}
|
||||
|
@ -67,14 +71,17 @@ WinPointerEvents::InitLibrary()
|
|||
}
|
||||
|
||||
bool
|
||||
WinPointerEvents::ShouldFireCompatibilityMouseEventsForPen(WPARAM aWParam)
|
||||
WinPointerEvents::ShouldHandleWinPointerMessages(UINT aMsg, WPARAM aWParam)
|
||||
{
|
||||
MOZ_ASSERT(aMsg == WM_POINTERDOWN || aMsg == WM_POINTERUP ||
|
||||
aMsg == WM_POINTERUPDATE || aMsg == WM_POINTERLEAVE);
|
||||
if (!sLibraryHandle || !sPointerEventEnabled) {
|
||||
// Firing mouse events by handling Windows WM_POINTER* when preference is on
|
||||
// and the Windows platform supports PointerEvent related interfaces.
|
||||
return false;
|
||||
}
|
||||
|
||||
// We only handle WM_POINTER* when the input source is pen. This is because
|
||||
// we need some information (e.g. tiltX, tiltY) which can't be retrieved by
|
||||
// WM_*BUTTONDOWN.
|
||||
uint32_t pointerId = GetPointerId(aWParam);
|
||||
POINTER_INPUT_TYPE pointerType = PT_POINTER;
|
||||
if (!GetPointerType(pointerId, &pointerType)) {
|
||||
|
@ -94,6 +101,14 @@ WinPointerEvents::GetPointerType(uint32_t aPointerId,
|
|||
return getPointerType(aPointerId, aPointerType);
|
||||
}
|
||||
|
||||
POINTER_INPUT_TYPE
|
||||
WinPointerEvents::GetPointerType(uint32_t aPointerId)
|
||||
{
|
||||
POINTER_INPUT_TYPE pointerType = PT_POINTER;
|
||||
Unused << GetPointerType(aPointerId, &pointerType);
|
||||
return pointerType;
|
||||
}
|
||||
|
||||
bool
|
||||
WinPointerEvents::GetPointerInfo(uint32_t aPointerId,
|
||||
POINTER_INFO *aPointerInfo)
|
||||
|
@ -123,9 +138,83 @@ WinPointerEvents::ShouldEnableInkCollector()
|
|||
}
|
||||
|
||||
bool
|
||||
WinPointerEvents::ShouldRollupOnPointerEvent(WPARAM aWParam)
|
||||
WinPointerEvents::ShouldRollupOnPointerEvent(UINT aMsg, WPARAM aWParam)
|
||||
{
|
||||
MOZ_ASSERT(aMsg == WM_POINTERDOWN);
|
||||
// Only roll up popups when we handling WM_POINTER* to fire Gecko
|
||||
// WidgetMouseEvent and suppress Windows WM_*BUTTONDOWN.
|
||||
return ShouldFireCompatibilityMouseEventsForPen(aWParam);
|
||||
return ShouldHandleWinPointerMessages(aMsg, aWParam) &&
|
||||
ShouldFirePointerEventByWinPointerMessages();
|
||||
}
|
||||
|
||||
bool
|
||||
WinPointerEvents::ShouldFirePointerEventByWinPointerMessages()
|
||||
{
|
||||
MOZ_ASSERT(sLibraryHandle && sPointerEventEnabled);
|
||||
return sFirePointerEventsByWinPointerMessages;
|
||||
}
|
||||
|
||||
WinPointerInfo*
|
||||
WinPointerEvents::GetCachedPointerInfo(UINT aMsg, WPARAM aWParam)
|
||||
{
|
||||
if (!sLibraryHandle || !sPointerEventEnabled ||
|
||||
MOUSE_INPUT_SOURCE() != nsIDOMMouseEvent::MOZ_SOURCE_PEN ||
|
||||
ShouldFirePointerEventByWinPointerMessages()) {
|
||||
return nullptr;
|
||||
}
|
||||
switch (aMsg) {
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
return &mPenPointerDownInfo;
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_RBUTTONUP:
|
||||
return &mPenPointerDownInfo;
|
||||
case WM_MOUSEMOVE:
|
||||
return &mPenPointerUpdateInfo;
|
||||
default:
|
||||
MOZ_ASSERT(false);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
WinPointerEvents::ConvertAndCachePointerInfo(UINT aMsg, WPARAM aWParam)
|
||||
{
|
||||
MOZ_ASSERT(!sFirePointerEventsByWinPointerMessages);
|
||||
// Windows doesn't support chorded buttons for pen, so we can simply keep the
|
||||
// latest information from pen generated pointer messages and use them when
|
||||
// handling mouse messages. Used different pointer info for pointerdown,
|
||||
// pointerupdate, and pointerup because Windows doesn't always interleave
|
||||
// pointer messages and mouse messages.
|
||||
switch (aMsg) {
|
||||
case WM_POINTERDOWN:
|
||||
ConvertAndCachePointerInfo(aWParam, &mPenPointerDownInfo);
|
||||
break;
|
||||
case WM_POINTERUP:
|
||||
ConvertAndCachePointerInfo(aWParam, &mPenPointerUpInfo);
|
||||
break;
|
||||
case WM_POINTERUPDATE:
|
||||
ConvertAndCachePointerInfo(aWParam, &mPenPointerUpdateInfo);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WinPointerEvents::ConvertAndCachePointerInfo(WPARAM aWParam,
|
||||
WinPointerInfo* aInfo)
|
||||
{
|
||||
MOZ_ASSERT(!sFirePointerEventsByWinPointerMessages);
|
||||
aInfo->pointerId = GetPointerId(aWParam);
|
||||
MOZ_ASSERT(GetPointerType(aInfo->pointerId) == PT_PEN);
|
||||
POINTER_PEN_INFO penInfo;
|
||||
GetPointerPenInfo(aInfo->pointerId, &penInfo);
|
||||
aInfo->tiltX = penInfo.tiltX;
|
||||
aInfo->tiltY = penInfo.tiltY;
|
||||
// Windows defines the pen pressure is normalized to a range between 0 and
|
||||
// 1024. Convert it to float.
|
||||
aInfo->mPressure = penInfo.pressure ? (float)penInfo.pressure / 1024 : 0;
|
||||
}
|
||||
|
|
|
@ -104,6 +104,8 @@ class WinPointerInfo final : public mozilla::WidgetPointerHelper
|
|||
public:
|
||||
WinPointerInfo()
|
||||
: WidgetPointerHelper()
|
||||
, mPressure(0)
|
||||
, mButtons(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -125,17 +127,23 @@ public:
|
|||
explicit WinPointerEvents();
|
||||
|
||||
public:
|
||||
bool ShouldFireCompatibilityMouseEventsForPen(WPARAM aWParam);
|
||||
bool ShouldHandleWinPointerMessages(UINT aMsg, WPARAM aWParam);
|
||||
|
||||
uint32_t GetPointerId(WPARAM aWParam)
|
||||
{
|
||||
return GET_POINTERID_WPARAM(aWParam);
|
||||
}
|
||||
bool GetPointerType(uint32_t aPointerId, POINTER_INPUT_TYPE *aPointerType);
|
||||
POINTER_INPUT_TYPE GetPointerType(uint32_t aPointerId);
|
||||
bool GetPointerInfo(uint32_t aPointerId, POINTER_INFO *aPointerInfo);
|
||||
bool GetPointerPenInfo(uint32_t aPointerId, POINTER_PEN_INFO *aPenInfo);
|
||||
bool ShouldEnableInkCollector();
|
||||
bool ShouldRollupOnPointerEvent(WPARAM aWParam);
|
||||
bool ShouldRollupOnPointerEvent(UINT aMsg, WPARAM aWParam);
|
||||
bool ShouldFirePointerEventByWinPointerMessages();
|
||||
WinPointerInfo* GetCachedPointerInfo(UINT aMsg, WPARAM aWParam);
|
||||
void ConvertAndCachePointerInfo(UINT aMsg, WPARAM aWParam);
|
||||
void ConvertAndCachePointerInfo(WPARAM aWParam, WinPointerInfo* aInfo);
|
||||
|
||||
private:
|
||||
// Function prototypes
|
||||
typedef BOOL (WINAPI* GetPointerTypePtr)(uint32_t aPointerId,
|
||||
|
@ -150,10 +158,14 @@ private:
|
|||
static HMODULE sLibraryHandle;
|
||||
static const wchar_t kPointerLibraryName[];
|
||||
static bool sPointerEventEnabled;
|
||||
static bool WinPointerEvents::sFirePointerEventsByWinPointerMessages;
|
||||
// Static function pointers
|
||||
static GetPointerTypePtr getPointerType;
|
||||
static GetPointerInfoPtr getPointerInfo;
|
||||
static GetPointerPenInfoPtr getPointerPenInfo;
|
||||
WinPointerInfo mPenPointerDownInfo;
|
||||
WinPointerInfo mPenPointerUpInfo;
|
||||
WinPointerInfo mPenPointerUpdateInfo;
|
||||
};
|
||||
|
||||
#endif // #ifndef WinPointerEvents_h__
|
||||
|
|
|
@ -5439,7 +5439,8 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
|||
|
||||
result = DispatchMouseEvent(eMouseMove, wParam, lParam,
|
||||
false, WidgetMouseEvent::eLeftButton,
|
||||
MOUSE_INPUT_SOURCE());
|
||||
MOUSE_INPUT_SOURCE(),
|
||||
mPointerEvents.GetCachedPointerInfo(msg, wParam));
|
||||
if (userMovedMouse) {
|
||||
DispatchPendingEvents();
|
||||
}
|
||||
|
@ -5457,7 +5458,8 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
|||
{
|
||||
result = DispatchMouseEvent(eMouseDown, wParam, lParam,
|
||||
false, WidgetMouseEvent::eLeftButton,
|
||||
MOUSE_INPUT_SOURCE());
|
||||
MOUSE_INPUT_SOURCE(),
|
||||
mPointerEvents.GetCachedPointerInfo(msg, wParam));
|
||||
DispatchPendingEvents();
|
||||
}
|
||||
break;
|
||||
|
@ -5466,7 +5468,8 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
|||
{
|
||||
result = DispatchMouseEvent(eMouseUp, wParam, lParam,
|
||||
false, WidgetMouseEvent::eLeftButton,
|
||||
MOUSE_INPUT_SOURCE());
|
||||
MOUSE_INPUT_SOURCE(),
|
||||
mPointerEvents.GetCachedPointerInfo(msg, wParam));
|
||||
DispatchPendingEvents();
|
||||
}
|
||||
break;
|
||||
|
@ -5617,7 +5620,8 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
|||
result = DispatchMouseEvent(eMouseDown, wParam,
|
||||
lParam, false,
|
||||
WidgetMouseEvent::eRightButton,
|
||||
MOUSE_INPUT_SOURCE());
|
||||
MOUSE_INPUT_SOURCE(),
|
||||
mPointerEvents.GetCachedPointerInfo(msg, wParam));
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
|
@ -5625,7 +5629,8 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
|||
result = DispatchMouseEvent(eMouseUp, wParam,
|
||||
lParam, false,
|
||||
WidgetMouseEvent::eRightButton,
|
||||
MOUSE_INPUT_SOURCE());
|
||||
MOUSE_INPUT_SOURCE(),
|
||||
mPointerEvents.GetCachedPointerInfo(msg, wParam));
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
|
@ -7781,7 +7786,7 @@ nsWindow::DealWithPopups(HWND aWnd, UINT aMessage,
|
|||
case WM_POINTERDOWN:
|
||||
{
|
||||
WinPointerEvents pointerEvents;
|
||||
if (!pointerEvents.ShouldRollupOnPointerEvent(aWParam)) {
|
||||
if (!pointerEvents.ShouldRollupOnPointerEvent(nativeMessage, aWParam)) {
|
||||
return false;
|
||||
}
|
||||
if (!GetPopupsToRollup(rollupListener, &popupsToRollup)) {
|
||||
|
@ -8197,14 +8202,18 @@ nsWindow::OnWindowedPluginKeyEvent(const NativeEventData& aKeyEventData,
|
|||
|
||||
bool nsWindow::OnPointerEvents(UINT msg, WPARAM aWParam, LPARAM aLParam)
|
||||
{
|
||||
if (!mPointerEvents.ShouldFireCompatibilityMouseEventsForPen(aWParam)) {
|
||||
// We only handle WM_POINTER* when the input source is pen. This is because
|
||||
// we need some information (e.g. tiltX, tiltY) which can't be retrieved by
|
||||
// WM_*BUTTONDOWN. So we fire Gecko WidgetMouseEvent when handling
|
||||
// WM_POINTER* and consume WM_POINTER* to stop Windows fire WM_*BUTTONDOWN.
|
||||
if (!mPointerEvents.ShouldHandleWinPointerMessages(msg, aWParam)) {
|
||||
return false;
|
||||
}
|
||||
if (!mPointerEvents.ShouldFirePointerEventByWinPointerMessages()) {
|
||||
// We have to handle WM_POINTER* to fetch and cache pen related information
|
||||
// and fire WidgetMouseEvent with the cached information the WM_*BUTTONDOWN
|
||||
// handler. This is because Windows doesn't support ::DoDragDrop in the touch
|
||||
// or pen message handlers.
|
||||
mPointerEvents.ConvertAndCachePointerInfo(msg, aWParam);
|
||||
// Don't consume the Windows WM_POINTER* messages
|
||||
return false;
|
||||
}
|
||||
|
||||
// When dispatching mouse events with pen, there may be some
|
||||
// WM_POINTERUPDATE messages between WM_POINTERDOWN and WM_POINTERUP with
|
||||
// small movements. Those events will reset sLastMousePoint and reset
|
||||
|
|
Загрузка…
Ссылка в новой задаче