Bug 894485 - Have touch events precede mouse events to simulate touch devices. r=surkov

This commit is contained in:
Eitan Isaacson 2013-07-25 08:59:08 -07:00
Родитель dc0fcce6eb
Коммит cf1e33d72d
3 изменённых файлов: 60 добавлений и 45 удалений

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

@ -32,6 +32,7 @@
#include "nsView.h"
#include "nsLayoutUtils.h"
#include "nsGkAtoms.h"
#include "nsDOMTouchEvent.h"
#include "nsComponentManagerUtils.h"
#include "nsIInterfaceRequestorUtils.h"
@ -113,6 +114,7 @@ nsCoreUtils::DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj,
int32_t cnvdY = presContext->CSSPixelsToDevPixels(tcY + y + 1) +
presContext->AppUnitsToDevPixels(offset.y);
// XUL is just desktop, so there is no real reason for senfing touch events.
DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, cnvdX, cnvdY,
tcContent, tcFrame, presShell, rootWidget);
@ -120,33 +122,6 @@ nsCoreUtils::DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj,
tcContent, tcFrame, presShell, rootWidget);
}
bool
nsCoreUtils::DispatchMouseEvent(uint32_t aEventType,
nsIPresShell *aPresShell,
nsIContent *aContent)
{
nsIFrame *frame = aContent->GetPrimaryFrame();
if (!frame)
return false;
// Compute x and y coordinates.
nsPoint point;
nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget(point);
if (!widget)
return false;
nsSize size = frame->GetSize();
nsPresContext* presContext = aPresShell->GetPresContext();
int32_t x = presContext->AppUnitsToDevPixels(point.x + size.width / 2);
int32_t y = presContext->AppUnitsToDevPixels(point.y + size.height / 2);
// Fire mouse event.
DispatchMouseEvent(aEventType, x, y, aContent, frame, aPresShell, widget);
return true;
}
void
nsCoreUtils::DispatchMouseEvent(uint32_t aEventType, int32_t aX, int32_t aY,
nsIContent *aContent, nsIFrame *aFrame,
@ -166,6 +141,28 @@ nsCoreUtils::DispatchMouseEvent(uint32_t aEventType, int32_t aX, int32_t aY,
aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status);
}
void
nsCoreUtils::DispatchTouchEvent(uint32_t aEventType, int32_t aX, int32_t aY,
nsIContent* aContent, nsIFrame* aFrame,
nsIPresShell* aPresShell, nsIWidget* aRootWidget)
{
if (!nsDOMTouchEvent::PrefEnabled())
return;
nsTouchEvent event(true, aEventType, aRootWidget);
event.time = PR_IntervalNow();
// XXX: Touch has an identifier of -1 to hint that it is synthesized.
nsRefPtr<mozilla::dom::Touch> t =
new mozilla::dom::Touch(-1, nsIntPoint(aX, aY),
nsIntPoint(1, 1), 0.0f, 1.0f);
t->SetTarget(aContent);
event.touches.AppendElement(t);
nsEventStatus status = nsEventStatus_eIgnore;
aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status);
}
uint32_t
nsCoreUtils::GetAccessKeyFor(nsIContent* aContent)
{

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

@ -46,17 +46,6 @@ public:
int32_t aRowIndex, nsITreeColumn *aColumn,
const nsCString& aPseudoElt = EmptyCString());
/**
* Send mouse event to the given element.
*
* @param aEventType [in] an event type (see nsGUIEvent.h for constants)
* @param aPresShell [in] the presshell for the given element
* @param aContent [in] the element
*/
static bool DispatchMouseEvent(uint32_t aEventType,
nsIPresShell *aPresShell,
nsIContent *aContent);
/**
* Send mouse event to the given element.
*
@ -70,8 +59,22 @@ public:
*/
static void DispatchMouseEvent(uint32_t aEventType, int32_t aX, int32_t aY,
nsIContent *aContent, nsIFrame *aFrame,
nsIPresShell *aPresShell,
nsIWidget *aRootWidget);
nsIPresShell *aPresShell, nsIWidget *aRootWidget);
/**
* Send a touch event with a single touch point to the given element.
*
* @param aEventType [in] an event type (see nsGUIEvent.h for constants)
* @param aX [in] x coordinate in dev pixels
* @param aY [in] y coordinate in dev pixels
* @param aContent [in] the element
* @param aFrame [in] frame of the element
* @param aPresShell [in] the presshell for the element
* @param aRootWidget [in] the root widget of the element
*/
static void DispatchTouchEvent(uint32_t aEventType, int32_t aX, int32_t aY,
nsIContent* aContent, nsIFrame* aFrame,
nsIPresShell* aPresShell, nsIWidget* aRootWidget);
/**
* Return an accesskey registered on the given element by

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

@ -2293,13 +2293,28 @@ Accessible::DispatchClickEvent(nsIContent *aContent, uint32_t aActionIndex)
nsIPresShell::ScrollAxis(),
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
// Fire mouse down and mouse up events.
bool res = nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, presShell,
aContent);
if (!res)
nsIFrame* frame = aContent->GetPrimaryFrame();
if (!frame)
return;
nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_UP, presShell, aContent);
// Compute x and y coordinates.
nsPoint point;
nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget(point);
if (!widget)
return;
nsSize size = frame->GetSize();
nsPresContext* presContext = presShell->GetPresContext();
int32_t x = presContext->AppUnitsToDevPixels(point.x + size.width / 2);
int32_t y = presContext->AppUnitsToDevPixels(point.y + size.height / 2);
// Simulate a touch interaction by dispatching touch events with mouse events.
nsCoreUtils::DispatchTouchEvent(NS_TOUCH_START, x, y, aContent, frame, presShell, widget);
nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, x, y, aContent, frame, presShell, widget);
nsCoreUtils::DispatchTouchEvent(NS_TOUCH_END, x, y, aContent, frame, presShell, widget);
nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_UP, x, y, aContent, frame, presShell, widget);
}
NS_IMETHODIMP