Bug 1343613 - [2.3] Add GeckoView event queuing in EventDispatcher. r=jchen,snorp

This commit is contained in:
Eugen Sawin 2017-03-06 18:16:45 +01:00
Родитель 5db48b0409
Коммит 5728cb6576
5 изменённых файлов: 55 добавлений и 13 удалений

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

@ -9,6 +9,7 @@ import org.mozilla.gecko.annotation.RobocopTarget;
import org.mozilla.gecko.annotation.WrapForJNI;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.mozglue.JNIObject;
import org.mozilla.gecko.NativeQueue.StateHolder;
import org.mozilla.gecko.util.BundleEventListener;
import org.mozilla.gecko.util.EventCallback;
import org.mozilla.gecko.util.GeckoBundle;
@ -57,6 +58,7 @@ public final class EventDispatcher extends JNIObject {
new HashMap<String, List<BundleEventListener>>(DEFAULT_BACKGROUND_EVENTS_COUNT);
private boolean mAttachedToGecko;
private final StateHolder mStateHolder;
@ReflectionTarget
@WrapForJNI(calledFrom = "gecko")
@ -65,6 +67,15 @@ public final class EventDispatcher extends JNIObject {
}
/* package */ EventDispatcher() {
mStateHolder = GeckoThread.getStateHolder();
}
/* package */ EventDispatcher(final NativeQueue.StateHolder stateHolder) {
mStateHolder = stateHolder;
}
private boolean isReadyForDispatchingToGecko() {
return mStateHolder.isReady();
}
@WrapForJNI(dispatchTo = "gecko") @Override // JNIObject
@ -228,7 +239,7 @@ public final class EventDispatcher extends JNIObject {
public void dispatch(final String type, final GeckoBundle message,
final EventCallback callback) {
synchronized (this) {
if (mAttachedToGecko && hasGeckoListener(type)) {
if (isReadyForDispatchingToGecko() && hasGeckoListener(type)) {
dispatchToGecko(type, message, JavaCallbackDelegate.wrap(callback));
return;
}
@ -279,15 +290,18 @@ public final class EventDispatcher extends JNIObject {
return true;
}
if (!GeckoThread.isRunning()) {
// Usually, we discard an event if there is no listeners for it by the time of
// the dispatch. However, if Gecko is not ready and there is no listener for
// this event that's possibly headed to Gecko, we make a special exception to
// queue this event until Gecko is ready. This way, Gecko can first register
// its listeners, and accept the event when it is ready.
GeckoThread.queueNativeCall(this, "dispatchToGecko",
String.class, type, GeckoBundle.class, message,
EventCallback.class, JavaCallbackDelegate.wrap(callback));
if (!isReadyForDispatchingToGecko()) {
// Usually, we discard an event if there is no listeners for it by
// the time of the dispatch. However, if Gecko(View) is not ready and
// there is no listener for this event that's possibly headed to
// Gecko, we make a special exception to queue this event until
// Gecko(View) is ready. This way, Gecko can first register its
// listeners, and accept the event when it is ready.
NativeQueue.queueUntil(mStateHolder,
mStateHolder.getReadyState(), this, "dispatchToGecko",
String.class, type,
GeckoBundle.class, message,
EventCallback.class, JavaCallbackDelegate.wrap(callback));
return true;
}

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

@ -74,7 +74,8 @@ public class GeckoView extends LayerView
mStateHolder.setState(newState);
}
private final EventDispatcher mEventDispatcher = new EventDispatcher();
private final EventDispatcher mEventDispatcher =
new EventDispatcher(mStateHolder);
private ChromeDelegate mChromeDelegate;
/* package */ ContentListener mContentListener;

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

@ -573,8 +573,15 @@ nsAppShell::Observe(nsISupports* aSubject,
java::GeckoThread::State::PROFILE_READY(),
java::GeckoThread::State::RUNNING());
}
removeObserver = true;
// Enable the window event dispatcher for the given GeckoView.
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aSubject);
MOZ_ASSERT(doc);
nsCOMPtr<nsIWidget> widget =
WidgetUtils::DOMWindowToWidget(doc->GetWindow());
MOZ_ASSERT(widget);
const auto window = static_cast<nsWindow*>(widget.get());
window->EnableEventDispatcher();
} else if (!strcmp(aTopic, "quit-application-granted")) {
if (jni::IsAvailable()) {
java::GeckoThread::SetState(

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

@ -237,12 +237,12 @@ public:
Impl* operator->() const { return mImpl; }
};
class nsWindow::GeckoViewSupport final
: public GeckoView::Window::Natives<GeckoViewSupport>
, public SupportsWeakPtr<GeckoViewSupport>
{
nsWindow& window;
GeckoView::GlobalRef mView;
public:
typedef GeckoView::Window::Natives<GeckoViewSupport> Base;
@ -268,6 +268,7 @@ public:
const GeckoView::Window::LocalRef& aInstance,
GeckoView::Param aView)
: window(*aWindow)
, mView(aView)
{
Base::AttachNative(aInstance, static_cast<SupportsWeakPtr*>(this));
}
@ -301,6 +302,8 @@ public:
jni::Object::Param aDispatcher);
void LoadUri(jni::String::Param aUri, int32_t aFlags);
void EnableEventDispatcher();
};
/**
@ -1535,6 +1538,15 @@ nsWindow::GetRootLayerId() const
return mCompositorSession ? mCompositorSession->RootLayerTreeId() : 0;
}
void
nsWindow::EnableEventDispatcher()
{
if (!mGeckoViewSupport) {
return;
}
mGeckoViewSupport->EnableEventDispatcher();
}
void
nsWindow::SetParent(nsIWidget *aNewParent)
{
@ -2061,6 +2073,13 @@ nsWindow::GetEventTimeStamp(int64_t aEventTime)
return TimeStamp::FromSystemTime(tick);
}
void
nsWindow::GeckoViewSupport::EnableEventDispatcher()
{
MOZ_ASSERT(mView);
mView->SetState(GeckoView::State::READY());
}
void
nsWindow::UserActivity()
{

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

@ -50,6 +50,7 @@ public:
static void InitNatives();
void SetScreenId(uint32_t aScreenId) { mScreenId = aScreenId; }
void EnableEventDispatcher();
private:
uint32_t mScreenId;