Bug 705057 part.3 XP level code shouldn't call nsIWidget::ResetInputState() and nsIWidget::CancelIMEComposition() directly r=smaug+ehsan

This commit is contained in:
Masayuki Nakano 2012-09-26 14:47:51 +09:00
parent 680159333c
commit d03c724521
7 changed files with 95 additions and 71 deletions

View File

@ -89,6 +89,13 @@ TextComposition::SynthesizeCommit(bool aDiscard)
composition.DispatchCompsotionEventRunnable(NS_COMPOSITION_END, data);
}
nsresult
TextComposition::NotifyIME(widget::NotificationToIME aNotification)
{
NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_AVAILABLE);
return nsIMEStateManager::NotifyIME(aNotification, mPresContext);
}
/******************************************************************************
* TextComposition::CompositionEventDispatcher
******************************************************************************/

View File

@ -61,6 +61,12 @@ public:
*/
void SynthesizeCommit(bool aDiscard);
/**
* Send a notification to IME. It depends on the IME or platform spec what
* will occur (or not occur).
*/
nsresult NotifyIME(widget::NotificationToIME aNotification);
private:
// This class holds nsPresContext weak. This instance shouldn't block
// destroying it. When the presContext is being destroyed, it's notified to

View File

@ -112,9 +112,10 @@ nsIMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
// to unsafe to run script (in PresShell::HandleEvent()).
nsCOMPtr<nsIWidget> widget = aPresContext->GetNearestWidget();
if (widget) {
nsresult rv = widget->CancelIMEComposition();
nsresult rv =
storedComposition.NotifyIME(REQUEST_TO_CANCEL_COMPOSITION);
if (NS_FAILED(rv)) {
widget->ResetInputState();
storedComposition.NotifyIME(REQUEST_TO_COMMIT_COMPOSITION);
}
// By calling the APIs, the composition may have been finished normally.
compositionInContent =
@ -220,8 +221,9 @@ nsIMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
oldWidget = widget;
else
oldWidget = GetWidget(sPresContext);
if (oldWidget)
oldWidget->ResetInputState();
if (oldWidget) {
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
}
}
// Update IME state for new focus widget
@ -307,7 +309,7 @@ nsIMEStateManager::UpdateIMEState(const IMEState &aNewIMEState,
}
// commit current composition
widget->ResetInputState();
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, widget);
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
InputContextAction::FOCUS_NOT_CHANGED);
@ -495,6 +497,44 @@ nsIMEStateManager::DispatchCompositionEvent(nsINode* aEventTargetNode,
}
}
// static
nsresult
nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
nsIWidget* aWidget)
{
NS_ENSURE_TRUE(aWidget, NS_ERROR_INVALID_ARG);
TextComposition* composition = nullptr;
if (sTextCompositions) {
composition = sTextCompositions->GetCompositionFor(aWidget);
}
switch (aNotification) {
case NOTIFY_IME_OF_CURSOR_POS_CHANGED:
return aWidget->ResetInputState();
case REQUEST_TO_COMMIT_COMPOSITION:
return composition ? aWidget->ResetInputState() : NS_OK;
case REQUEST_TO_CANCEL_COMPOSITION:
return composition ? aWidget->CancelIMEComposition() : NS_OK;
default:
MOZ_NOT_REACHED("Unsupported notification");
return NS_ERROR_INVALID_ARG;
}
}
// static
nsresult
nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
nsPresContext* aPresContext)
{
NS_ENSURE_TRUE(aPresContext, NS_ERROR_INVALID_ARG);
nsIWidget* widget = aPresContext->GetNearestWidget();
if (!widget) {
return NS_ERROR_NOT_AVAILABLE;
}
return NotifyIME(aNotification, widget);
}
// nsTextStateManager notifies widget of any text and selection changes
// in the currently focused editor

View File

@ -7,6 +7,7 @@
#define nsIMEStateManager_h__
#include "nscore.h"
#include "nsEvent.h"
#include "nsIWidget.h"
class nsDispatchingCallback;
@ -96,6 +97,15 @@ public:
nsEventStatus* aStatus,
nsDispatchingCallback* aCallBack);
/**
* Send a notification to IME. It depends on the IME or platform spec what
* will occur (or not occur).
*/
static nsresult NotifyIME(mozilla::widget::NotificationToIME aNotification,
nsIWidget* aWidget);
static nsresult NotifyIME(mozilla::widget::NotificationToIME aNotification,
nsPresContext* aPresContext);
protected:
static nsresult OnChangeFocusInternal(nsPresContext* aPresContext,
nsIContent* aContent,

View File

@ -2031,73 +2031,31 @@ nsEditor::GetPhonetic(nsAString& aPhonetic)
return NS_OK;
}
static nsresult
GetEditorContentWindow(dom::Element *aRoot, nsIWidget **aResult)
{
NS_ENSURE_TRUE(aRoot && aResult, NS_ERROR_NULL_POINTER);
*aResult = 0;
// Not ref counted
nsIFrame *frame = aRoot->GetPrimaryFrame();
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
*aResult = frame->GetNearestWidget();
NS_ENSURE_TRUE(*aResult, NS_ERROR_FAILURE);
NS_ADDREF(*aResult);
return NS_OK;
}
nsresult
nsEditor::GetWidget(nsIWidget **aWidget)
{
NS_ENSURE_TRUE(aWidget, NS_ERROR_NULL_POINTER);
*aWidget = nullptr;
nsCOMPtr<nsIWidget> widget;
nsresult res = GetEditorContentWindow(GetRoot(), getter_AddRefs(widget));
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_TRUE(widget, NS_ERROR_NOT_AVAILABLE);
NS_ADDREF(*aWidget = widget);
return NS_OK;
}
NS_IMETHODIMP
nsEditor::ForceCompositionEnd()
{
// We can test mInIMEMode and do some optimization for Mac and Window
// Howerver, since UNIX support over-the-spot, we cannot rely on that
// flag for Unix.
// We should use LookAndFeel to resolve this
#if defined(XP_MACOSX) || defined(XP_WIN) || defined(XP_OS2)
// XXXmnakano see bug 558976, ResetInputState() has two meaning which are
// "commit the composition" and "cursor is moved". This method name is
// "ForceCompositionEnd", so, ResetInputState() should be used only for the
// former here. However, ResetInputState() is also used for the latter here
// because even if we don't have composition, we call ResetInputState() on
// Linux. Currently, nsGtkIMModule can know the timing of the cursor move,
// so, the latter meaning should be gone and we should remove this #if.
if(! mInIMEMode)
return NS_OK;
#endif
nsCOMPtr<nsIWidget> widget;
nsresult res = GetWidget(getter_AddRefs(widget));
NS_ENSURE_SUCCESS(res, res);
if (widget) {
res = widget->ResetInputState();
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsIPresShell> ps = GetPresShell();
if (!ps) {
return NS_ERROR_NOT_AVAILABLE;
}
nsPresContext* pc = ps->GetPresContext();
if (!pc) {
return NS_ERROR_NOT_AVAILABLE;
}
return NS_OK;
if (!mInIMEMode) {
// XXXmnakano see bug 558976, ResetInputState() has two meaning which are
// "commit the composition" and "cursor is moved". This method name is
// "ForceCompositionEnd", so, ResetInputState() should be used only for the
// former here. However, ResetInputState() is also used for the latter here
// because even if we don't have composition, we call ResetInputState() on
// Linux. Currently, nsGtkIMModule can know the timing of the cursor move,
// so, the latter meaning should be gone.
// XXX This may commit a composition in another editor.
return nsIMEStateManager::NotifyIME(NOTIFY_IME_OF_CURSOR_POS_CHANGED, pc);
}
return nsIMEStateManager::NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, pc);
}
NS_IMETHODIMP

View File

@ -388,10 +388,6 @@ protected:
bool aGoForward,
bool bNoBlockCrossing);
// Get nsIWidget interface
nsresult GetWidget(nsIWidget **aWidget);
// install the event listeners for the editor
virtual nsresult InstallEventListeners();

View File

@ -98,6 +98,13 @@ enum Modifier {
typedef uint16_t Modifiers;
// NotificationToIME is shared by nsIMEStateManager and TextComposition.
enum NotificationToIME {
NOTIFY_IME_OF_CURSOR_POS_CHANGED,
REQUEST_TO_COMMIT_COMPOSITION,
REQUEST_TO_CANCEL_COMPOSITION
};
} // namespace widget
} // namespace mozilla