Bug 1530188 - Make nsChildView::GetEditorView() use eQueryContentState without flushing layout r=smaug

`nsChildView::GetEditorView()` is called by `TextInputHandlerBase::GetWindowLevel()`
which is called when Cocoa requests window level of focused widget.

It currently gets widget including focused element (e.g., it may be in a XUL
`<panel>`) with `eQueryTextContent` event.  However, it requires only the widget
(i.e., when a XUL `<panel>` has focused element, the widget for the panel).
Therefore, it does not require to flush the layout.

However, on macOS, `ContentEventHandler` always flushes layout even with
`eQueryContentState` which does not require any layout information.  Whether
it requires flushing layout or not is considered with
`WidgetQueryContentEvent::mNeedsToFlushLayout` but this is set to false only
when `IMEContentObserver` notifies widget (and IME) of focus set.  At this
time, only on macOS, IME caches the layout information, for example, the
character coordinates, but we don't have a way to update it.  This is the reason
why we always flush layout on macOS.

Unfortunately, when a menu popup frame is created, widget for the popup is
created synchronously.  Then, Cocoa retrieves window level of the widget including
focused element.  But this is unsafe to flush the layout.  So, we need to stop
flushing layout in this case.

Therefore, this patch moves the `#ifdef` from `TextEvents.h` to
`IMEContentObserver.cpp`, then, makes `nsChildView::GetEditorView()` use
`eQueryContentState` which is the simplest query content event, and finally,
sets `mNeedsToFlushLayout` to `false`.

Differential Revision: https://phabricator.services.mozilla.com/D25912

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Masayuki Nakano 2019-04-03 10:27:13 +00:00
Родитель d2005aabce
Коммит fefd623c98
4 изменённых файлов: 17 добавлений и 14 удалений

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

@ -70,7 +70,6 @@ skip-if = (verify && debug && (os == 'mac' || os == 'linux'))
[browser_library_left_pane_middleclick.js]
[browser_library_left_pane_select_hierarchy.js]
[browser_library_middleclick.js]
skip-if = (os == 'mac') # Re-enable once bug 1530188 has been fixed
[browser_library_new_bookmark.js]
[browser_library_open_leak.js]
[browser_library_openFlatContainer.js]

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

@ -1813,9 +1813,15 @@ void IMEContentObserver::IMENotificationSender::SendFocusSet() {
observer->mIMEHasFocus = true;
// Initialize selection cache with the first selection data.
#ifdef XP_MACOSX
// We need to flush layout only on macOS because character coordinates are
// cached by cocoa with this call, but we don't have a way to update them
// after that. Therefore, we need the latest layout information right now.
observer->UpdateSelectionCache(true);
#else
// We avoid flushing for focus in the general case.
observer->UpdateSelectionCache(false);
#endif // #ifdef XP_MACOSX #else
MOZ_LOG(sIMECOLog, LogLevel::Info,
("0x%p IMEContentObserver::IMENotificationSender::"
"SendFocusSet(), sending NOTIFY_IME_OF_FOCUS...",

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

@ -1001,13 +1001,7 @@ class WidgetQueryContentEvent : public WidgetGUIEvent {
Init(aOptions);
}
bool NeedsToFlushLayout() const {
#ifdef XP_MACOSX
return true;
#else
return mNeedsToFlushLayout;
#endif
}
bool NeedsToFlushLayout() const { return mNeedsToFlushLayout; }
void RequestFontRanges() {
NS_ASSERTION(mMessage == eQueryTextContent, "not querying text content");

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

@ -1687,12 +1687,16 @@ NSView<mozView>* nsChildView::GetEditorView() {
// We need to get editor's view. E.g., when the focus is in the bookmark
// dialog, the view is <panel> element of the dialog. At this time, the key
// events are processed the parent window's view that has native focus.
WidgetQueryContentEvent textContent(true, eQueryTextContent, this);
textContent.InitForQueryTextContent(0, 0);
DispatchWindowEvent(textContent);
if (textContent.mSucceeded && textContent.mReply.mFocusedWidget) {
WidgetQueryContentEvent queryContentState(true, eQueryContentState, this);
// This may be called during creating a menu popup frame due to creating
// widget synchronously and that causes Cocoa asking current window level.
// In this case, it's not safe to flush layout on the document and we don't
// need any layout information right now.
queryContentState.mNeedsToFlushLayout = false;
DispatchWindowEvent(queryContentState);
if (queryContentState.mSucceeded && queryContentState.mReply.mFocusedWidget) {
NSView<mozView>* view = static_cast<NSView<mozView>*>(
textContent.mReply.mFocusedWidget->GetNativeData(NS_NATIVE_WIDGET));
queryContentState.mReply.mFocusedWidget->GetNativeData(NS_NATIVE_WIDGET));
if (view) editorView = view;
}
return editorView;