Bug 1229403 - Use existing states if possible when initializing GeckoView; r=snorp

This patch changes onAttachedToWindow in GeckoView, so that if we have
states that have been restored, we use those states for initialization
instead of creating new states (e.g. opening a new nsWindow). Because
the GLController instance is associated with the nsWindow instance, we
need to keep the GLController instance as part of our saved states. This
patch also adds a reattach method to GeckoView.Window, because
GeckoEditable needs to be notified when its target View changes.
This commit is contained in:
Jim Chen 2015-12-23 22:03:35 -05:00
parent 77def6fcae
commit c56eece49a
5 changed files with 82 additions and 29 deletions

View File

@ -121,10 +121,14 @@ public class GeckoView extends LayerView
@WrapForJNI
private static final class Window extends JNIObject {
/* package */ final GLController glController = new GLController();
static native void open(Window instance, GeckoView view, GLController glController,
int width, int height);
@Override protected native void disposeNative();
native void close();
native void reattach(GeckoView view);
}
// Object to hold onto our nsWindow connection when GeckoView gets destroyed.
@ -292,20 +296,28 @@ public class GeckoView extends LayerView
{
final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
// TODO: reuse GLController when restoring state.
final GLController glController = new GLController();
if (window == null) {
// Open a new nsWindow if we didn't have one from before.
window = new Window();
if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
Window.open(window, this, glController,
if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
Window.open(window, this, window.glController,
metrics.widthPixels, metrics.heightPixels);
} else {
GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY, Window.class,
"open", window, GeckoView.class, this, window.glController,
metrics.widthPixels, metrics.heightPixels);
}
} else {
GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY, Window.class,
"open", window, GeckoView.class, this, glController,
metrics.widthPixels, metrics.heightPixels);
if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
window.reattach(this);
} else {
GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
window, "reattach", GeckoView.class, this);
}
}
setGLController(glController);
setGLController(window.glController);
super.onAttachedToWindow();
}

View File

@ -203,7 +203,11 @@ public:
mozilla::jni::MakeNativeMethod<GeckoView::Window::Open_t>(
mozilla::jni::NativeStub<GeckoView::Window::Open_t, Impl>
::template Wrap<&Impl::Open>)
::template Wrap<&Impl::Open>),
mozilla::jni::MakeNativeMethod<GeckoView::Window::Reattach_t>(
mozilla::jni::NativeStub<GeckoView::Window::Reattach_t, Impl>
::template Wrap<&Impl::Reattach>)
};
};

View File

@ -1113,6 +1113,17 @@ constexpr char GeckoView::Window::DisposeNative_t::signature[];
constexpr char GeckoView::Window::Open_t::name[];
constexpr char GeckoView::Window::Open_t::signature[];
constexpr char GeckoView::Window::Reattach_t::name[];
constexpr char GeckoView::Window::Reattach_t::signature[];
constexpr char GeckoView::Window::GlController_t::name[];
constexpr char GeckoView::Window::GlController_t::signature[];
auto GeckoView::Window::GlController() const -> mozilla::jni::Object::LocalRef
{
return mozilla::jni::Field<GlController_t>::Get(this, nullptr);
}
constexpr char PrefsHelper::name[];
constexpr char PrefsHelper::GetPrefsById_t::name[];

View File

@ -2995,6 +2995,39 @@ public:
mozilla::jni::ExceptionMode::ABORT;
};
public:
struct Reattach_t {
typedef Window Owner;
typedef void ReturnType;
typedef void SetterType;
typedef mozilla::jni::Args<
GeckoView::Param> Args;
static constexpr char name[] = "reattach";
static constexpr char signature[] =
"(Lorg/mozilla/gecko/GeckoView;)V";
static const bool isStatic = false;
static const bool isMultithreaded = true;
static const mozilla::jni::ExceptionMode exceptionMode =
mozilla::jni::ExceptionMode::ABORT;
};
public:
struct GlController_t {
typedef Window Owner;
typedef mozilla::jni::Object::LocalRef ReturnType;
typedef mozilla::jni::Object::Param SetterType;
typedef mozilla::jni::Args<> Args;
static constexpr char name[] = "glController";
static constexpr char signature[] =
"Lorg/mozilla/gecko/gfx/GLController;";
static const bool isStatic = false;
static const bool isMultithreaded = true;
static const mozilla::jni::ExceptionMode exceptionMode =
mozilla::jni::ExceptionMode::ABORT;
};
auto GlController() const -> mozilla::jni::Object::LocalRef;
public:
template<class Impl> class Natives;
};

View File

@ -144,10 +144,8 @@ NS_IMPL_ISUPPORTS(ContentCreationNotifier,
// one.
static nsTArray<nsWindow*> gTopLevelWindows;
// FIXME: because we don't support separate nsWindow for each GeckoView
// yet, we have to attach a new GeckoView to an existing nsWindow if it
// exists. Eventually, an nsWindow will be opened/closed as each GeckoView
// is created/destroyed.
// FIXME: because we don't support multiple GeckoViews for every feature
// yet, we have to default to a particular GeckoView for certain calls.
static nsWindow* gGeckoViewWindow;
static bool sFailedToCreateGLContext = false;
@ -274,6 +272,9 @@ public:
// Close and destroy the nsWindow.
void Close();
// Reattach this nsWindow to a new GeckoView.
void Reattach(GeckoView::Param aView);
/**
* GeckoEditable methods
*/
@ -649,21 +650,6 @@ nsWindow::GeckoViewSupport::Open(const jni::ClassObject::LocalRef& aCls,
PROFILER_LABEL("nsWindow", "GeckoViewSupport::Open",
js::ProfileEntry::Category::OTHER);
if (gGeckoViewWindow) {
// Should have been created the first time.
MOZ_ASSERT(gGeckoViewWindow->mGeckoViewSupport);
gGeckoViewWindow->mGeckoViewSupport->Reattach(
GeckoView::Window::LocalRef(aCls.Env(), aWindow));
MOZ_ASSERT(gGeckoViewWindow->mGLControllerSupport);
gGeckoViewWindow->mGLControllerSupport->Reattach(GLController::LocalRef(
aCls.Env(), GLController::Ref::From(aGLController)));
// Associate our previous GeckoEditable with the new GeckoView.
gGeckoViewWindow->mGeckoViewSupport->mEditable->OnViewChange(aView);
return;
}
nsCOMPtr<nsIWindowWatcher> ww = do_GetService(NS_WINDOWWATCHER_CONTRACTID);
MOZ_ASSERT(ww);
@ -729,6 +715,13 @@ nsWindow::GeckoViewSupport::Close()
baseWindow->Destroy();
}
void
nsWindow::GeckoViewSupport::Reattach(GeckoView::Param aView)
{
// Associate our previous GeckoEditable with the new GeckoView.
mEditable->OnViewChange(aView);
}
void
nsWindow::InitNatives()
{