void TextComposition::NotityUpdateComposition(WidgetGUIEvent* aEvent) { nsEventStatus status; // When compositon start, notify the rect of first offset character. // When not compositon start, notify the rect of selected composition // string if text event. if (aEvent->message == NS_COMPOSITION_START) { nsCOMPtr<nsIWidget> widget = mPresContext->GetRootWidget(); // Update composition start offset WidgetQueryContentEvent selectedTextEvent(true, NS_QUERY_SELECTED_TEXT, widget); widget->DispatchEvent(&selectedTextEvent, status); if (selectedTextEvent.mSucceeded) { mCompositionStartOffset = selectedTextEvent.mReply.mOffset; } else { // Unknown offset NS_WARNING("Cannot get start offset of IME composition"); mCompositionStartOffset = 0; } mCompositionTargetOffset = mCompositionStartOffset; } else if (aEvent->mClass != eTextEventClass) { return; } else { mCompositionTargetOffset = mCompositionStartOffset + aEvent->AsTextEvent()->TargetClauseOffset(); } NotifyIME(NOTIFY_IME_OF_COMPOSITION_UPDATE); }
void TextComposition::MaybeNotifyIMEOfCompositionEventHandled( const WidgetCompositionEvent* aCompositionEvent) { if (aCompositionEvent->mMessage != eCompositionStart && !aCompositionEvent->CausesDOMTextEvent()) { return; } RefPtr<IMEContentObserver> contentObserver = IMEStateManager::GetActiveContentObserver(); // When IMEContentObserver is managing the editor which has this composition, // composition event handled notification should be sent after the observer // notifies all pending notifications. Therefore, we should use it. // XXX If IMEContentObserver suddenly loses focus after here and notifying // widget of pending notifications, we won't notify widget of composition // event handled. Although, this is a bug but it should be okay since // destroying IMEContentObserver notifies IME of blur. So, native IME // handler can treat it as this notification too. if (contentObserver && contentObserver->IsManaging(this)) { contentObserver->MaybeNotifyCompositionEventHandled(); return; } // Otherwise, e.g., this composition is in non-active window, we should // notify widget directly. NotifyIME(NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED); }
void TextComposition::NotityUpdateComposition( const WidgetCompositionEvent* aCompositionEvent) { MOZ_RELEASE_ASSERT(!mTabParent); nsEventStatus status; // When compositon start, notify the rect of first offset character. // When not compositon start, notify the rect of selected composition // string if compositionchange event. if (aCompositionEvent->mMessage == eCompositionStart) { nsCOMPtr<nsIWidget> widget = mPresContext->GetRootWidget(); // Update composition start offset WidgetQueryContentEvent selectedTextEvent(true, eQuerySelectedText, widget); widget->DispatchEvent(&selectedTextEvent, status); if (selectedTextEvent.mSucceeded) { mCompositionStartOffset = selectedTextEvent.mReply.mOffset; } else { // Unknown offset NS_WARNING("Cannot get start offset of IME composition"); mCompositionStartOffset = 0; } mCompositionTargetOffset = mCompositionStartOffset; } else if (aCompositionEvent->CausesDOMTextEvent()) { mCompositionTargetOffset = mCompositionStartOffset + aCompositionEvent->TargetClauseOffset(); } else { return; } NotifyIME(NOTIFY_IME_OF_COMPOSITION_UPDATE); }
// static void IMEHandler::SetInputContext(nsWindow* aWindow, InputContext& aInputContext, const InputContextAction& aAction) { // FYI: If there is no composition, this call will do nothing. NotifyIME(aWindow, REQUEST_TO_COMMIT_COMPOSITION); // Assume that SetInputContext() is called only when aWindow has focus. sPluginHasFocus = (aInputContext.mIMEState.mEnabled == IMEState::PLUGIN); bool enable = IsIMEEnabled(aInputContext); bool adjustOpenState = (enable && aInputContext.mIMEState.mOpen != IMEState::DONT_CHANGE_OPEN_STATE); bool open = (adjustOpenState && aInputContext.mIMEState.mOpen == IMEState::OPEN); aInputContext.mNativeIMEContext = nullptr; #ifdef NS_ENABLE_TSF // Note that even while a plugin has focus, we need to notify TSF of that. if (sIsInTSFMode) { nsTextStore::SetInputContext(aWindow, aInputContext, aAction); if (IsTSFAvailable()) { aInputContext.mNativeIMEContext = nsTextStore::GetTextStore(); if (adjustOpenState) { nsTextStore::SetIMEOpenState(open); } return; } } else { // Set at least InputScope even when TextStore is not available. SetInputScopeForIMM32(aWindow, aInputContext.mHTMLInputType); } #endif // #ifdef NS_ENABLE_TSF nsIMEContext IMEContext(aWindow->GetWindowHandle()); if (enable) { IMEContext.AssociateDefaultContext(); if (!aInputContext.mNativeIMEContext) { aInputContext.mNativeIMEContext = static_cast<void*>(IMEContext.get()); } } else if (!aWindow->Destroyed()) { // Don't disassociate the context after the window is destroyed. IMEContext.Disassociate(); if (!aInputContext.mNativeIMEContext) { // The old InputContext must store the default IMC. aInputContext.mNativeIMEContext = aWindow->GetInputContext().mNativeIMEContext; } } if (adjustOpenState) { IMEContext.SetOpenState(open); } }
// static void IMEHandler::SetInputContext(nsWindow* aWindow, InputContext& aInputContext) { // FYI: If there is no composition, this call will do nothing. NotifyIME(aWindow, REQUEST_TO_COMMIT_COMPOSITION); // Assume that SetInputContext() is called only when aWindow has focus. sPluginHasFocus = (aInputContext.mIMEState.mEnabled == IMEState::PLUGIN); bool enable = IsIMEEnabled(aInputContext); bool adjustOpenState = (enable && aInputContext.mIMEState.mOpen != IMEState::DONT_CHANGE_OPEN_STATE); bool open = (adjustOpenState && aInputContext.mIMEState.mOpen == IMEState::OPEN); aInputContext.mNativeIMEContext = nullptr; #ifdef NS_ENABLE_TSF // Note that even while a plugin has focus, we need to notify TSF of that. if (sIsInTSFMode) { nsTextStore::SetInputContext(aInputContext); if (IsTSFAvailable()) { aInputContext.mNativeIMEContext = nsTextStore::GetTextStore(); } // Currently, nsTextStore doesn't set focus to keyboard disabled document. // Therefore, we still need to perform the following legacy code. } #endif // #ifdef NS_ENABLE_TSF nsIMEContext IMEContext(aWindow->GetWindowHandle()); if (enable) { IMEContext.AssociateDefaultContext(); if (!aInputContext.mNativeIMEContext) { aInputContext.mNativeIMEContext = static_cast<void*>(IMEContext.get()); } } else if (!aWindow->Destroyed()) { // Don't disassociate the context after the window is destroyed. IMEContext.Disassociate(); if (!aInputContext.mNativeIMEContext) { // The old InputContext must store the default IMC. aInputContext.mNativeIMEContext = aWindow->GetInputContext().mNativeIMEContext; } } if (adjustOpenState) { #ifdef NS_ENABLE_TSF if (IsTSFAvailable()) { nsTextStore::SetIMEOpenState(open); return; } #endif // #ifdef NS_ENABLE_TSF IMEContext.SetOpenState(open); } }
void TextComposition::NotityUpdateComposition(WidgetGUIEvent* aEvent) { nsEventStatus status; // When compositon start, notify the rect of first offset character. // When not compositon start, notify the rect of selected composition // string if text event. if (aEvent->message == NS_COMPOSITION_START) { nsCOMPtr<nsIWidget> widget = mPresContext->GetRootWidget(); // Update composition start offset WidgetQueryContentEvent selectedTextEvent(true, NS_QUERY_SELECTED_TEXT, widget); widget->DispatchEvent(&selectedTextEvent, status); if (selectedTextEvent.mSucceeded) { mCompositionStartOffset = selectedTextEvent.mReply.mOffset; } else { // Unknown offset NS_WARNING("Cannot get start offset of IME composition"); mCompositionStartOffset = 0; } mCompositionTargetOffset = mCompositionStartOffset; } else if (aEvent->eventStructType != NS_TEXT_EVENT) { return; } else { WidgetTextEvent* textEvent = aEvent->AsTextEvent(); mCompositionTargetOffset = mCompositionStartOffset; for (uint32_t i = 0; i < textEvent->rangeCount; i++) { TextRange& range = textEvent->rangeArray[i]; if (range.mRangeType == NS_TEXTRANGE_SELECTEDRAWTEXT || range.mRangeType == NS_TEXTRANGE_SELECTEDCONVERTEDTEXT) { mCompositionTargetOffset += range.mStartOffset; break; } } } NotifyIME(widget::NotificationToIME::NOTIFY_IME_OF_COMPOSITION_UPDATE); }
// static void IMEHandler::SetInputContext(nsWindow* aWindow, InputContext& aInputContext, const InputContextAction& aAction) { // FYI: If there is no composition, this call will do nothing. NotifyIME(aWindow, IMENotification(REQUEST_TO_COMMIT_COMPOSITION)); const InputContext& oldInputContext = aWindow->GetInputContext(); // Assume that SetInputContext() is called only when aWindow has focus. sPluginHasFocus = (aInputContext.mIMEState.mEnabled == IMEState::PLUGIN); bool enable = WinUtils::IsIMEEnabled(aInputContext); bool adjustOpenState = (enable && aInputContext.mIMEState.mOpen != IMEState::DONT_CHANGE_OPEN_STATE); bool open = (adjustOpenState && aInputContext.mIMEState.mOpen == IMEState::OPEN); aInputContext.mNativeIMEContext = nullptr; #ifdef NS_ENABLE_TSF // Note that even while a plugin has focus, we need to notify TSF of that. if (sIsInTSFMode) { nsTextStore::SetInputContext(aWindow, aInputContext, aAction); if (IsTSFAvailable()) { aInputContext.mNativeIMEContext = nsTextStore::GetTextStore(); if (sIsIMMEnabled) { // Associate IME context for IMM-IMEs. AssociateIMEContext(aWindow, enable); } else if (oldInputContext.mIMEState.mEnabled == IMEState::PLUGIN) { // Disassociate the IME context from the window when plugin loses focus // in pure TSF mode. AssociateIMEContext(aWindow, false); } if (adjustOpenState) { nsTextStore::SetIMEOpenState(open); } return; } } else { // Set at least InputScope even when TextStore is not available. SetInputScopeForIMM32(aWindow, aInputContext.mHTMLInputType); } #endif // #ifdef NS_ENABLE_TSF AssociateIMEContext(aWindow, enable); nsIMEContext IMEContext(aWindow->GetWindowHandle()); if (adjustOpenState) { IMEContext.SetOpenState(open); } if (aInputContext.mNativeIMEContext) { return; } // The old InputContext must store the default IMC or old TextStore. // When IME context is disassociated from the window, use it. aInputContext.mNativeIMEContext = enable ? static_cast<void*>(IMEContext.get()) : oldInputContext.mNativeIMEContext; }