Bug 914331 - On pointer released make sure all gecko touch events are delivered to insure dom state via accessibility is up to date. r=tabraldes, bbondy

This commit is contained in:
Jim Mathies 2013-09-13 05:34:24 -05:00
parent a6f3797eb4
commit d9c3eb7320
4 changed files with 69 additions and 15 deletions

View File

@ -42,6 +42,8 @@ extern UINT sAppShellGeckoMsgId;
static ComPtr<ICoreWindowStatic> sCoreStatic;
static bool sIsDispatching = false;
static bool sWillEmptyThreadQueue = false;
static bool sEmptyingThreadQueue = false;
MetroAppShell::~MetroAppShell()
{
@ -214,6 +216,43 @@ MetroAppShell::Run(void)
return rv;
}
// Called in certain cases where we have async input events in the thread
// queue and need to make sure they get dispatched before the stack unwinds.
void // static
MetroAppShell::MarkEventQueueForPurge()
{
LogFunction();
sWillEmptyThreadQueue = true;
// If we're dispatching native events, wait until the dispatcher is
// off the stack.
if (sIsDispatching) {
return;
}
// Safe to process pending events now
DispatchAllGeckoEvents();
}
// static
void
MetroAppShell::DispatchAllGeckoEvents()
{
if (!sWillEmptyThreadQueue) {
return;
}
LogFunction();
NS_ASSERTION(NS_IsMainThread(), "DispatchAllXPCOMEvents should be called on the main thread");
sWillEmptyThreadQueue = false;
AutoRestore<bool> dispatching(sEmptyingThreadQueue);
sEmptyingThreadQueue = true;
nsIThread *thread = NS_GetCurrentThread();
NS_ProcessPendingEvents(thread, 0);
}
static void
ProcessNativeEvents(CoreProcessEventsOption eventOption)
{
@ -238,16 +277,35 @@ bool
MetroAppShell::ProcessOneNativeEventIfPresent()
{
if (sIsDispatching) {
NS_RUNTIMEABORT("Reentrant call into process events, this is not allowed in Winrt land. Goodbye!");
// Calling into ProcessNativeEvents is harmless, but won't actually process any
// native events. So we log here so we can spot this and get a handle on the
// corner cases where this can happen.
Log("WARNING: Reentrant call into process events detected, returning early.");
return false;
}
AutoRestore<bool> dispatching(sIsDispatching);
ProcessNativeEvents(CoreProcessEventsOption::CoreProcessEventsOption_ProcessOneIfPresent);
{
AutoRestore<bool> dispatching(sIsDispatching);
sIsDispatching = true;
ProcessNativeEvents(CoreProcessEventsOption::CoreProcessEventsOption_ProcessOneIfPresent);
}
DispatchAllGeckoEvents();
return !!HIWORD(::GetQueueStatus(MOZ_QS_ALLEVENT));
}
bool
MetroAppShell::ProcessNextNativeEvent(bool mayWait)
{
// NS_ProcessPendingEvents will process thread events *and* call
// nsBaseAppShell::OnProcessNextEvent to process native events. However
// we do not want native events getting dispatched while we are in
// DispatchAllGeckoEvents.
if (sEmptyingThreadQueue) {
return false;
}
if (ProcessOneNativeEventIfPresent()) {
return true;
}

View File

@ -27,12 +27,14 @@ public:
static LRESULT CALLBACK EventWindowProc(HWND, UINT, WPARAM, LPARAM);
static bool ProcessOneNativeEventIfPresent();
static void MarkEventQueueForPurge();
protected:
NS_IMETHOD Run();
virtual void ScheduleNativeEventCallback();
virtual bool ProcessNextNativeEvent(bool mayWait);
static void DispatchAllGeckoEvents();
virtual ~MetroAppShell();
HWND mEventWnd;

View File

@ -12,6 +12,7 @@
#include "nsIDOMSimpleGestureEvent.h" // Constants for gesture events
#include "InputData.h"
#include "UIABridgePrivate.h"
#include "MetroAppShell.h"
// System headers (alphabetical)
#include <windows.ui.core.h> // ABI::Window::UI::Core namespace
@ -635,6 +636,11 @@ MetroInput::OnPointerReleased(UI::Core::ICoreWindow* aSender,
mGestureRecognizer->ProcessUpEvent(currentPoint.Get());
}
// Make sure all gecko events are dispatched and the dom is up to date
// so that when ui automation comes in looking for focus info it gets
// the right information.
MetroAppShell::MarkEventQueueForPurge();
return S_OK;
}
@ -1091,17 +1097,6 @@ MetroInput::DeliverNextQueuedEventIgnoreStatus()
delete event;
}
nsEventStatus
MetroInput::DeliverNextQueuedEvent()
{
nsGUIEvent* event = static_cast<nsGUIEvent*>(mInputEventQueue.PopFront());
MOZ_ASSERT(event);
nsEventStatus status;
mWidget->DispatchEvent(event, status);
delete event;
return status;
}
void
MetroInput::DispatchAsyncTouchEventIgnoreStatus(nsTouchEvent* aEvent)
{

View File

@ -264,7 +264,6 @@ private:
// Async event callbacks
void DeliverNextQueuedEventIgnoreStatus();
nsEventStatus DeliverNextQueuedEvent();
nsEventStatus DeliverNextQueuedTouchEvent();
// Misc. specialty async callbacks