Skip to content

Commit

Permalink
Bug 1651705: Part 5 - GeckoEditableSupport updates to support `Native…
Browse files Browse the repository at this point in the history
…WeakPtr`; r=m_kato,geckoview-reviewers

This patch is similar to part 4 but for `GeckoEditableSupport`.

Conversions over to `NativeWeakPtr` are pretty straight forward thanks to the
type system.  Basically we take a `NativeWeakPtr`, call `Access()` on it, and
if the accessor is truthy, then we call whatever methods we need to call.

Creation of new pointers is done using `NativeWeakPtrHolder::Attach()` and
detaching of strong references is done by `NativeWeakPtr::Detach()`.

Differential Revision: https://phabricator.services.mozilla.com/D87364
  • Loading branch information
dblohm7 committed Sep 21, 2020
1 parent e1d14ba commit 3e3929e
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 34 deletions.
57 changes: 39 additions & 18 deletions widget/android/GeckoEditableSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "mozilla/TextEvents.h"
#include "mozilla/ToString.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/widget/GeckoViewSupport.h"

#include <android/api-level.h>
#include <android/input.h>
Expand All @@ -36,10 +37,6 @@
} while (0)
#endif

template <>
const char nsWindow::NativePtr<mozilla::widget::GeckoEditableSupport>::sName[] =
"GeckoEditableSupport";

static uint32_t ConvertAndroidKeyCodeToDOMKeyCode(int32_t androidKeyCode) {
// Special-case alphanumeric keycodes because they are most common.
if (androidKeyCode >= AKEYCODE_A && androidKeyCode <= AKEYCODE_Z) {
Expand Down Expand Up @@ -465,8 +462,10 @@ void GeckoEditableSupport::OnKeyEvent(int32_t aAction, int32_t aKeyCode,
: widget ? widget->GetTextEventDispatcher() : nullptr;
NS_ENSURE_TRUE_VOID(dispatcher && widget);

if (!aIsSynthesizedImeKey && mWindow) {
mWindow->UserActivity();
if (!aIsSynthesizedImeKey) {
if (nsWindow* window = GetNsWindow()) {
window->UserActivity();
}
} else if (aIsSynthesizedImeKey && mIMEMaskEventsCount > 0) {
// Don't synthesize editor keys when not focused.
return;
Expand Down Expand Up @@ -859,8 +858,8 @@ bool GeckoEditableSupport::DoReplaceText(int32_t aStart, int32_t aEnd,
return false;
}

if (mWindow) {
mWindow->UserActivity();
if (nsWindow* window = GetNsWindow()) {
window->UserActivity();
}

/*
Expand Down Expand Up @@ -1264,7 +1263,8 @@ nsresult GeckoEditableSupport::NotifyIME(
if (mIsRemote) {
if (!mEditableAttached) {
// Re-attach on focus; see OnRemovedFrom().
AttachNative(mEditable, this);
jni::NativeWeakPtrHolder<GeckoEditableSupport>::AttachExisting(
mEditable, do_AddRef(this));
mEditableAttached = true;
}
// Because GeckoEditableSupport in content process doesn't
Expand Down Expand Up @@ -1378,7 +1378,7 @@ void GeckoEditableSupport::OnRemovedFrom(

if (mIsRemote && mEditable->HasEditableParent()) {
// When we're remote, detach every time.
OnDetach(NS_NewRunnableFunction(
OnWeakNonIntrusiveDetach(NS_NewRunnableFunction(
"GeckoEditableSupport::OnRemovedFrom",
[editable = java::GeckoEditableChild::GlobalRef(mEditable)] {
DisposeNative(editable);
Expand Down Expand Up @@ -1470,7 +1470,7 @@ void GeckoEditableSupport::TransferParent(jni::Object::Param aEditableParent) {
// only, so mInputContext may be still invalid since it is set after
// we have gotton focus.
RefPtr<GeckoEditableSupport> self(this);
nsAppShell::PostEvent([self] {
nsAppShell::PostEvent([self = std::move(self)] {
NS_WARNING_ASSERTION(
self->mDispatcher,
"Text dispatcher is still null. Why don't we get focus yet?");
Expand Down Expand Up @@ -1515,15 +1515,19 @@ void GeckoEditableSupport::SetOnBrowserChild(dom::BrowserChild* aBrowserChild) {
// We need to set a new listener.
const auto editableChild = java::GeckoEditableChild::New(
/* parent */ nullptr, /* default */ false);
RefPtr<widget::GeckoEditableSupport> editableSupport =
new widget::GeckoEditableSupport(editableChild);

// Temporarily attach so we can receive the initial editable parent.
auto editableSupport =
jni::NativeWeakPtrHolder<GeckoEditableSupport>::Attach(editableChild,
editableChild);
auto accEditableSupport(editableSupport.Access());
MOZ_RELEASE_ASSERT(accEditableSupport);

// Tell PuppetWidget to use our listener for IME operations.
widget->SetNativeTextEventDispatcherListener(editableSupport);
widget->SetNativeTextEventDispatcherListener(
accEditableSupport.AsRefPtr().get());

// Temporarily attach so we can receive the initial editable parent.
AttachNative(editableChild, editableSupport);
editableSupport->mEditableAttached = true;
accEditableSupport->mEditableAttached = true;

// Connect the new child to a parent that corresponds to the BrowserChild.
java::GeckoServiceChildProcess::GetEditableParent(editableChild, contentId,
Expand All @@ -1545,7 +1549,8 @@ void GeckoEditableSupport::SetOnBrowserChild(dom::BrowserChild* aBrowserChild) {
static_cast<widget::GeckoEditableSupport*>(listener.get());
if (!support->mEditableAttached) {
// Temporarily attach so we can receive the initial editable parent.
AttachNative(support->GetJavaEditable(), support);
jni::NativeWeakPtrHolder<GeckoEditableSupport>::AttachExisting(
support->GetJavaEditable(), do_AddRef(support));
support->mEditableAttached = true;
}

Expand All @@ -1554,5 +1559,21 @@ void GeckoEditableSupport::SetOnBrowserChild(dom::BrowserChild* aBrowserChild) {
contentId, tabId);
}

nsIWidget* GeckoEditableSupport::GetWidget() const {
MOZ_ASSERT(NS_IsMainThread());
return mDispatcher ? mDispatcher->GetWidget() : GetNsWindow();
}

nsWindow* GeckoEditableSupport::GetNsWindow() const {
MOZ_ASSERT(NS_IsMainThread());

auto acc(mWindow.Access());
if (!acc) {
return nullptr;
}

return acc->GetNsWindow();
}

} // namespace widget
} // namespace mozilla
30 changes: 14 additions & 16 deletions widget/android/GeckoEditableSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class GeckoEditableSupport final
enum RemoveCompositionFlag { CANCEL_IME_COMPOSITION, COMMIT_IME_COMPOSITION };

const bool mIsRemote;
nsWindow::WindowPtr<GeckoEditableSupport> mWindow; // Parent only
jni::NativeWeakPtr<GeckoViewSupport> mWindow; // Parent only
RefPtr<TextEventDispatcher> mDispatcher;
java::GeckoEditableChild::GlobalRef mEditable;
bool mEditableAttached;
Expand All @@ -95,9 +95,8 @@ class GeckoEditableSupport final
bool mIMETextChangedDuringFlush;
bool mIMEMonitorCursor;

nsIWidget* GetWidget() const {
return mDispatcher ? mDispatcher->GetWidget() : mWindow;
}
nsIWidget* GetWidget() const;
nsWindow* GetNsWindow() const;

nsresult BeginInputTransaction(TextEventDispatcher* aDispatcher) {
if (mIsRemote) {
Expand Down Expand Up @@ -156,16 +155,14 @@ class GeckoEditableSupport final
static void SetOnBrowserChild(dom::BrowserChild* aBrowserChild);

// Constructor for main process GeckoEditableChild.
GeckoEditableSupport(nsWindow::NativePtr<GeckoEditableSupport>* aPtr,
nsWindow* aWindow,
GeckoEditableSupport(jni::NativeWeakPtr<GeckoViewSupport> aWindow,
java::GeckoEditableChild::Param aEditableChild)
: mIsRemote(!aWindow),
mWindow(aPtr, aWindow),
: mIsRemote(!aWindow.IsAttached()),
mWindow(aWindow),
mEditable(aEditableChild),
mEditableAttached(!mIsRemote),
mIMERanges(new TextRangeArray()),
mIMEMaskEventsCount(1) // Mask IME events since there's no focus yet
,
mIMEMaskEventsCount(1), // Mask IME events since there's no focus yet
mIMEFocusCount(0),
mIMEDelaySynchronizeReply(false),
mIMEActiveSynchronizeCount(0),
Expand All @@ -175,7 +172,7 @@ class GeckoEditableSupport final

// Constructor for content process GeckoEditableChild.
explicit GeckoEditableSupport(java::GeckoEditableChild::Param aEditableChild)
: GeckoEditableSupport(nullptr, nullptr, aEditableChild) {}
: GeckoEditableSupport(nullptr, aEditableChild) {}

NS_DECL_ISUPPORTS

Expand Down Expand Up @@ -204,12 +201,13 @@ class GeckoEditableSupport final

const java::GeckoEditableChild::Ref& GetJavaEditable() { return mEditable; }

void OnDetach(already_AddRefed<Runnable> aDisposer) {
void OnWeakNonIntrusiveDetach(already_AddRefed<Runnable> aDisposer) {
RefPtr<GeckoEditableSupport> self(this);
nsAppShell::PostEvent([this, self, disposer = RefPtr<Runnable>(aDisposer)] {
mEditableAttached = false;
disposer->Run();
});
nsAppShell::PostEvent(
[self = std::move(self), disposer = RefPtr<Runnable>(aDisposer)] {
self->mEditableAttached = false;
disposer->Run();
});
}

// Transfer to a new parent.
Expand Down

0 comments on commit 3e3929e

Please sign in to comment.