Bug 1176955 part.1 TextComposition should guarantee that WidgetSelectionEvent should be handled by same content as the target of composition events when there is a composition r=smaug

This commit is contained in:
Masayuki Nakano 2015-07-17 11:25:00 +09:00
Родитель 3b86e653ba
Коммит 6a5c380903
6 изменённых файлов: 100 добавлений и 13 удалений

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

@ -805,18 +805,8 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
}
break;
case NS_SELECTION_SET:
{
WidgetSelectionEvent* selectionEvent = aEvent->AsSelectionEvent();
if (IsTargetCrossProcess(selectionEvent)) {
// Will not be handled locally, remote the event
if (GetCrossProcessTarget()->SendSelectionEvent(*selectionEvent)) {
selectionEvent->mSucceeded = true;
}
break;
}
ContentEventHandler handler(mPresContext);
handler.OnSelectionEvent(selectionEvent);
}
IMEStateManager::HandleSelectionEvent(aPresContext, GetFocusedContent(),
aEvent->AsSelectionEvent());
break;
case NS_CONTENT_COMMAND_CUT:
case NS_CONTENT_COMMAND_COPY:

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

@ -149,6 +149,8 @@ GetEventMessageName(uint32_t aMessage)
return "NS_COMPOSITION_COMMIT_AS_IS";
case NS_COMPOSITION_COMMIT:
return "NS_COMPOSITION_COMMIT";
case NS_SELECTION_SET:
return "NS_SELECTION_SET";
default:
return "unacceptable event message";
}
@ -1205,6 +1207,56 @@ IMEStateManager::DispatchCompositionEvent(
}
}
// static
nsIContent*
IMEStateManager::GetRootContent(nsPresContext* aPresContext)
{
nsIDocument* doc = aPresContext->Document();
if (NS_WARN_IF(!doc)) {
return nullptr;
}
return doc->GetRootElement();
}
// static
void
IMEStateManager::HandleSelectionEvent(nsPresContext* aPresContext,
nsIContent* aEventTargetContent,
WidgetSelectionEvent* aSelectionEvent)
{
nsIContent* eventTargetContent =
aEventTargetContent ? aEventTargetContent :
GetRootContent(aPresContext);
nsRefPtr<TabParent> tabParent =
eventTargetContent ? TabParent::GetFrom(eventTargetContent) : nullptr;
MOZ_LOG(sISMLog, LogLevel::Info,
("ISM: IMEStateManager::HandleSelectionEvent(aPresContext=0x%p, "
"aEventTargetContent=0x%p, aSelectionEvent={ message=%s, "
"mFlags={ mIsTrusted=%s } }), tabParent=%p",
aPresContext, aEventTargetContent,
GetEventMessageName(aSelectionEvent->message),
GetBoolName(aSelectionEvent->mFlags.mIsTrusted),
tabParent.get()));
if (!aSelectionEvent->mFlags.mIsTrusted) {
return;
}
nsRefPtr<TextComposition> composition = sTextCompositions ?
sTextCompositions->GetCompositionFor(aSelectionEvent->widget) : nullptr;
if (composition) {
// When there is a composition, TextComposition should guarantee that the
// selection event will be handled in same target as composition events.
composition->HandleSelectionEvent(aSelectionEvent);
} else {
// When there is no composition, the selection event should be handled
// in the aPresContext or tabParent.
TextComposition::HandleSelectionEvent(aPresContext, tabParent,
aSelectionEvent);
}
}
// static
void
IMEStateManager::OnCompositionEventDiscarded(

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

@ -152,6 +152,15 @@ public:
EventDispatchingCallback* aCallBack,
bool aIsSynthesized = false);
/**
* All selection events must be handled via HandleSelectionEvent()
* because they must be handled by same target as composition events when
* there is a composition.
*/
static void HandleSelectionEvent(nsPresContext* aPresContext,
nsIContent* aEventTargetContent,
WidgetSelectionEvent* aSelectionEvent);
/**
* This is called when PresShell ignores a composition event due to not safe
* to dispatch events.
@ -212,6 +221,8 @@ protected:
static bool IsIMEObserverNeeded(const IMEState& aState);
static nsIContent* GetRootContent(nsPresContext* aPresContext);
static StaticRefPtr<nsIContent> sContent;
static nsPresContext* sPresContext;
static StaticRefPtr<nsIWidget> sFocusedIMEWidget;

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

@ -374,6 +374,24 @@ TextComposition::DispatchCompositionEvent(
NotityUpdateComposition(aCompositionEvent);
}
// static
void
TextComposition::HandleSelectionEvent(nsPresContext* aPresContext,
TabParent* aTabParent,
WidgetSelectionEvent* aSelectionEvent)
{
// If the content is a container of TabParent, composition should be in the
// remote process.
if (aTabParent) {
unused << aTabParent->SendSelectionEvent(*aSelectionEvent);
aSelectionEvent->mFlags.mPropagationStopped = true;
return;
}
ContentEventHandler handler(aPresContext);
handler.OnSelectionEvent(aSelectionEvent);
}
void
TextComposition::NotityUpdateComposition(
const WidgetCompositionEvent* aCompositionEvent)

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

@ -284,6 +284,18 @@ private:
EventDispatchingCallback* aCallBack,
bool aIsSynthesized);
/**
* HandleSelectionEvent() sends the selection event to ContentEventHandler
* or dispatches it to the focused child process.
*/
void HandleSelectionEvent(WidgetSelectionEvent* aSelectionEvent)
{
HandleSelectionEvent(mPresContext, mTabParent, aSelectionEvent);
}
static void HandleSelectionEvent(nsPresContext* aPresContext,
TabParent* aTabParent,
WidgetSelectionEvent* aSelectionEvent);
/**
* MaybeDispatchCompositionUpdate() may dispatch a compositionupdate event
* if aCompositionEvent changes composition string.

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

@ -2298,7 +2298,11 @@ TabParent::SendSelectionEvent(WidgetSelectionEvent& event)
return true;
}
mContentCache.OnSelectionEvent(event);
return PBrowserParent::SendSelectionEvent(event);
if (NS_WARN_IF(!PBrowserParent::SendSelectionEvent(event))) {
return false;
}
event.mSucceeded = true;
return true;
}
/*static*/ TabParent*