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
Родитель 5ef527b62e
Коммит e7f1a2326e
5 изменённых файлов: 82 добавлений и 29 удалений

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

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

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

@ -203,7 +203,11 @@ public:
mozilla::jni::MakeNativeMethod<GeckoView::Window::Open_t>( mozilla::jni::MakeNativeMethod<GeckoView::Window::Open_t>(
mozilla::jni::NativeStub<GeckoView::Window::Open_t, Impl> 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>)
}; };
}; };

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

@ -1113,6 +1113,17 @@ constexpr char GeckoView::Window::DisposeNative_t::signature[];
constexpr char GeckoView::Window::Open_t::name[]; constexpr char GeckoView::Window::Open_t::name[];
constexpr char GeckoView::Window::Open_t::signature[]; 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::name[];
constexpr char PrefsHelper::GetPrefsById_t::name[]; constexpr char PrefsHelper::GetPrefsById_t::name[];

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

@ -2995,6 +2995,39 @@ public:
mozilla::jni::ExceptionMode::ABORT; 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: public:
template<class Impl> class Natives; template<class Impl> class Natives;
}; };

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

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