Bug 1031362 Part1: Dispatching mouse events by handling pen generated WM_POINTER* messages. r=jimm,smaug
This commit is contained in:
@@ -3398,7 +3398,7 @@ nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen)
|
||||
sCurrentWindow->DispatchMouseEvent(eMouseEnterIntoWidget,
|
||||
sMouseExitwParam, pos, false,
|
||||
WidgetMouseEvent::eLeftButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@@ -4132,7 +4132,7 @@ bool
|
||||
nsWindow::DispatchMouseEvent(EventMessage aEventMessage, WPARAM wParam,
|
||||
LPARAM lParam, bool aIsContextMenuKey,
|
||||
int16_t aButton, uint16_t aInputSource,
|
||||
uint16_t aPointerId)
|
||||
WinPointerInfo* aPointerInfo)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
@@ -4169,6 +4169,9 @@ nsWindow::DispatchMouseEvent(EventMessage aEventMessage, WPARAM wParam,
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t pointerId = aPointerInfo ? aPointerInfo->pointerId :
|
||||
MOUSE_POINTERID();
|
||||
|
||||
// Since it is unclear whether a user will use the digitizer,
|
||||
// Postpone initialization until first PEN message will be found.
|
||||
if (nsIDOMMouseEvent::MOZ_SOURCE_PEN == aInputSource
|
||||
@@ -4177,7 +4180,7 @@ nsWindow::DispatchMouseEvent(EventMessage aEventMessage, WPARAM wParam,
|
||||
// Currently this scheme is used only when pointer events is enabled.
|
||||
&& gfxPrefs::PointerEventsEnabled()) {
|
||||
InkCollector::sInkCollector->SetTarget(mWnd);
|
||||
InkCollector::sInkCollector->SetPointerId(aPointerId);
|
||||
InkCollector::sInkCollector->SetPointerId(pointerId);
|
||||
}
|
||||
|
||||
switch (aEventMessage) {
|
||||
@@ -4214,10 +4217,18 @@ nsWindow::DispatchMouseEvent(EventMessage aEventMessage, WPARAM wParam,
|
||||
modifierKeyState.InitInputEvent(event);
|
||||
event.button = aButton;
|
||||
event.inputSource = aInputSource;
|
||||
event.pointerId = aPointerId;
|
||||
// If we get here the mouse events must be from non-touch sources, so
|
||||
// convert it to pointer events as well
|
||||
event.convertToPointer = true;
|
||||
if (aPointerInfo) {
|
||||
// Mouse events from Windows WM_POINTER*. Fill more information in
|
||||
// WidgetMouseEvent.
|
||||
event.AssignPointerHelperData(*aPointerInfo);
|
||||
event.pressure = aPointerInfo->mPressure;
|
||||
event.buttons = aPointerInfo->mButtons;
|
||||
} else {
|
||||
// If we get here the mouse events must be from non-touch sources, so
|
||||
// convert it to pointer events as well
|
||||
event.convertToPointer = true;
|
||||
event.pointerId = pointerId;
|
||||
}
|
||||
|
||||
bool insideMovementThreshold = (DeprecatedAbs(sLastMousePoint.x - eventPoint.x) < (short)::GetSystemMetrics(SM_CXDOUBLECLK)) &&
|
||||
(DeprecatedAbs(sLastMousePoint.y - eventPoint.y) < (short)::GetSystemMetrics(SM_CYDOUBLECLK));
|
||||
@@ -4366,7 +4377,7 @@ nsWindow::DispatchMouseEvent(EventMessage aEventMessage, WPARAM wParam,
|
||||
sCurrentWindow->DispatchMouseEvent(eMouseExitFromWidget,
|
||||
wParam, pos, false,
|
||||
WidgetMouseEvent::eLeftButton,
|
||||
aInputSource, aPointerId);
|
||||
aInputSource, aPointerInfo);
|
||||
}
|
||||
sCurrentWindow = this;
|
||||
if (!mInDtor) {
|
||||
@@ -4374,7 +4385,7 @@ nsWindow::DispatchMouseEvent(EventMessage aEventMessage, WPARAM wParam,
|
||||
sCurrentWindow->DispatchMouseEvent(eMouseEnterIntoWidget,
|
||||
wParam, pos, false,
|
||||
WidgetMouseEvent::eLeftButton,
|
||||
aInputSource, aPointerId);
|
||||
aInputSource, aPointerInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5285,7 +5296,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
|
||||
result = DispatchMouseEvent(eMouseMove, wParam, lParam,
|
||||
false, WidgetMouseEvent::eLeftButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
if (userMovedMouse) {
|
||||
DispatchPendingEvents();
|
||||
}
|
||||
@@ -5303,7 +5314,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
{
|
||||
result = DispatchMouseEvent(eMouseDown, wParam, lParam,
|
||||
false, WidgetMouseEvent::eLeftButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
}
|
||||
break;
|
||||
@@ -5312,7 +5323,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
{
|
||||
result = DispatchMouseEvent(eMouseUp, wParam, lParam,
|
||||
false, WidgetMouseEvent::eLeftButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
}
|
||||
break;
|
||||
@@ -5333,7 +5344,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
LPARAM pos = lParamToClient(::GetMessagePos());
|
||||
DispatchMouseEvent(eMouseExitFromWidget, mouseState, pos, false,
|
||||
WidgetMouseEvent::eLeftButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -5342,9 +5353,11 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
LPARAM pos = lParamToClient(::GetMessagePos());
|
||||
uint16_t pointerId = InkCollector::sInkCollector->GetPointerId();
|
||||
if (pointerId != 0) {
|
||||
WinPointerInfo pointerInfo;
|
||||
pointerInfo.pointerId = pointerId;
|
||||
DispatchMouseEvent(eMouseExitFromWidget, wParam, pos, false,
|
||||
WidgetMouseEvent::eLeftButton,
|
||||
nsIDOMMouseEvent::MOZ_SOURCE_PEN, pointerId);
|
||||
nsIDOMMouseEvent::MOZ_SOURCE_PEN, &pointerInfo);
|
||||
InkCollector::sInkCollector->ClearTarget();
|
||||
InkCollector::sInkCollector->ClearPointerId();
|
||||
}
|
||||
@@ -5380,7 +5393,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
contextMenukey ?
|
||||
WidgetMouseEvent::eLeftButton :
|
||||
WidgetMouseEvent::eRightButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
if (lParam != -1 && !result && mCustomNonClient &&
|
||||
mDraggableRegion.Contains(GET_X_LPARAM(pos), GET_Y_LPARAM(pos))) {
|
||||
// Blank area hit, throw up the system menu.
|
||||
@@ -5390,11 +5403,19 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_POINTERLEAVE:
|
||||
case WM_POINTERDOWN:
|
||||
case WM_POINTERUP:
|
||||
case WM_POINTERUPDATE:
|
||||
result = OnPointerEvents(msg, wParam, lParam);
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDBLCLK:
|
||||
result = DispatchMouseEvent(eMouseDoubleClick, wParam,
|
||||
lParam, false,
|
||||
WidgetMouseEvent::eLeftButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
@@ -5402,7 +5423,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
result = DispatchMouseEvent(eMouseDown, wParam,
|
||||
lParam, false,
|
||||
WidgetMouseEvent::eMiddleButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
@@ -5410,7 +5431,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
result = DispatchMouseEvent(eMouseUp, wParam,
|
||||
lParam, false,
|
||||
WidgetMouseEvent::eMiddleButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
@@ -5418,7 +5439,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
result = DispatchMouseEvent(eMouseDoubleClick, wParam,
|
||||
lParam, false,
|
||||
WidgetMouseEvent::eMiddleButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
@@ -5426,7 +5447,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
result = DispatchMouseEvent(eMouseDown, 0,
|
||||
lParamToClient(lParam), false,
|
||||
WidgetMouseEvent::eMiddleButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
@@ -5434,7 +5455,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
result = DispatchMouseEvent(eMouseUp, 0,
|
||||
lParamToClient(lParam), false,
|
||||
WidgetMouseEvent::eMiddleButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
@@ -5442,7 +5463,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
result = DispatchMouseEvent(eMouseDoubleClick, 0,
|
||||
lParamToClient(lParam), false,
|
||||
WidgetMouseEvent::eMiddleButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
@@ -5450,7 +5471,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
result = DispatchMouseEvent(eMouseDown, wParam,
|
||||
lParam, false,
|
||||
WidgetMouseEvent::eRightButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
@@ -5458,7 +5479,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
result = DispatchMouseEvent(eMouseUp, wParam,
|
||||
lParam, false,
|
||||
WidgetMouseEvent::eRightButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
@@ -5466,7 +5487,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
result = DispatchMouseEvent(eMouseDoubleClick, wParam,
|
||||
lParam, false,
|
||||
WidgetMouseEvent::eRightButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
@@ -5474,7 +5495,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
result = DispatchMouseEvent(eMouseDown, 0,
|
||||
lParamToClient(lParam), false,
|
||||
WidgetMouseEvent::eRightButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
@@ -5482,7 +5503,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
result = DispatchMouseEvent(eMouseUp, 0,
|
||||
lParamToClient(lParam), false,
|
||||
WidgetMouseEvent::eRightButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
@@ -5490,7 +5511,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
result = DispatchMouseEvent(eMouseDoubleClick, 0,
|
||||
lParamToClient(lParam), false,
|
||||
WidgetMouseEvent::eRightButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
@@ -5571,11 +5592,11 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
case WM_NCLBUTTONDBLCLK:
|
||||
DispatchMouseEvent(eMouseDoubleClick, 0, lParamToClient(lParam),
|
||||
false, WidgetMouseEvent::eLeftButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
result =
|
||||
DispatchMouseEvent(eMouseUp, 0, lParamToClient(lParam),
|
||||
false, WidgetMouseEvent::eLeftButton,
|
||||
MOUSE_INPUT_SOURCE(), MOUSE_POINTERID());
|
||||
MOUSE_INPUT_SOURCE());
|
||||
DispatchPendingEvents();
|
||||
break;
|
||||
|
||||
@@ -8023,6 +8044,107 @@ 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.
|
||||
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
|
||||
// sLastClickCount. To prevent that, we keep the last pen down position
|
||||
// and compare it with the subsequent WM_POINTERUPDATE. If the movement is
|
||||
// smaller than GetSystemMetrics(SM_CXDRAG), then we suppress firing
|
||||
// eMouseMove for WM_POINTERUPDATE.
|
||||
static POINT sLastPointerDownPoint = {0};
|
||||
|
||||
// We don't support chorded buttons for pen. Keep the button at
|
||||
// WM_POINTERDOWN.
|
||||
static WidgetMouseEvent::buttonType sLastPenDownButton =
|
||||
WidgetMouseEvent::eLeftButton;
|
||||
static bool sPointerDown = false;
|
||||
|
||||
EventMessage message;
|
||||
WidgetMouseEvent::buttonType button = WidgetMouseEvent::eLeftButton;
|
||||
switch (msg) {
|
||||
case WM_POINTERDOWN:
|
||||
{
|
||||
LayoutDeviceIntPoint eventPoint(GET_X_LPARAM(aLParam),
|
||||
GET_Y_LPARAM(aLParam));
|
||||
sLastPointerDownPoint.x = eventPoint.x;
|
||||
sLastPointerDownPoint.y = eventPoint.y;
|
||||
message = eMouseDown;
|
||||
button = IS_POINTER_SECONDBUTTON_WPARAM(aWParam) ?
|
||||
WidgetMouseEvent::eRightButton : WidgetMouseEvent::eLeftButton;
|
||||
sLastPenDownButton = button;
|
||||
sPointerDown = true;
|
||||
}
|
||||
break;
|
||||
case WM_POINTERUP:
|
||||
message = eMouseUp;
|
||||
MOZ_ASSERT(sPointerDown, "receive WM_POINTERUP w/o WM_POINTERDOWN");
|
||||
button = sPointerDown ? sLastPenDownButton : WidgetMouseEvent::eLeftButton;
|
||||
sPointerDown = false;
|
||||
break;
|
||||
case WM_POINTERUPDATE:
|
||||
message = eMouseMove;
|
||||
if (sPointerDown) {
|
||||
LayoutDeviceIntPoint eventPoint(GET_X_LPARAM(aLParam),
|
||||
GET_Y_LPARAM(aLParam));
|
||||
int32_t movementX = sLastPointerDownPoint.x > eventPoint.x ?
|
||||
sLastPointerDownPoint.x - eventPoint.x :
|
||||
eventPoint.x - sLastPointerDownPoint.x;
|
||||
int32_t movementY = sLastPointerDownPoint.y > eventPoint.y ?
|
||||
sLastPointerDownPoint.y - eventPoint.y :
|
||||
eventPoint.y - sLastPointerDownPoint.y;
|
||||
bool insideMovementThreshold =
|
||||
movementX < (int32_t)::GetSystemMetrics(SM_CXDRAG) &&
|
||||
movementY < (int32_t)::GetSystemMetrics(SM_CYDRAG);
|
||||
|
||||
if (insideMovementThreshold) {
|
||||
// Suppress firing eMouseMove for WM_POINTERUPDATE if the movement
|
||||
// from last WM_POINTERDOWN is smaller than SM_CXDRAG / SM_CYDRAG
|
||||
return false;
|
||||
}
|
||||
button = sLastPenDownButton;
|
||||
}
|
||||
break;
|
||||
case WM_POINTERLEAVE:
|
||||
message = eMouseExitFromWidget;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
uint32_t pointerId = mPointerEvents.GetPointerId(aWParam);
|
||||
POINTER_PEN_INFO penInfo;
|
||||
mPointerEvents.GetPointerPenInfo(pointerId, &penInfo);
|
||||
|
||||
// Windows defines the pen pressure is normalized to a range between 0 and
|
||||
// 1024. Convert it to float.
|
||||
float pressure = penInfo.pressure ? (float)penInfo.pressure / 1024 : 0;
|
||||
int16_t buttons =
|
||||
sPointerDown ? button == WidgetMouseEvent::eLeftButton ?
|
||||
WidgetMouseEvent::eLeftButtonFlag :
|
||||
WidgetMouseEvent::eRightButtonFlag :
|
||||
WidgetMouseEvent::eNoButtonFlag;
|
||||
WinPointerInfo pointerInfo(pointerId, penInfo.tiltX, penInfo.tiltY, pressure,
|
||||
buttons);
|
||||
|
||||
// The aLParam of WM_POINTER* is the screen location. Convert it to client
|
||||
// location
|
||||
LPARAM newLParam = lParamToClient(aLParam);
|
||||
DispatchMouseEvent(message, aWParam, newLParam, false, button,
|
||||
nsIDOMMouseEvent::MOZ_SOURCE_PEN, &pointerInfo);
|
||||
// Consume WM_POINTER* to stop Windows fires WM_*BUTTONDOWN / WM_*BUTTONUP
|
||||
// WM_MOUSEMOVE.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
**************************************************************
|
||||
**
|
||||
|
||||
Reference in New Issue
Block a user