Bug 519972 part.3 Move marked text handler to nsCocoaIMEHandler r=smichaud

This commit is contained in:
Masayuki Nakano 2011-02-19 13:55:34 +09:00
Родитель bc645b6f71
Коммит 6e4e990426
4 изменённых файлов: 209 добавлений и 154 удалений

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

@ -151,9 +151,6 @@ extern "C" long TSMProcessRawKeyEvent(EventRef carbonEvent);
// Valid when mKeyPressSent is true.
PRBool mKeyPressHandled;
// needed for NSTextInput implementation
NSRange mMarkedRange;
// when mouseDown: is called, we store its event here (strong)
NSEvent* mLastMouseDownEvent;

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

@ -155,9 +155,6 @@ PRUint32 nsChildView::sLastInputEventCount = 0;
- (id)initWithFrame:(NSRect)inFrame geckoChild:(nsChildView*)inChild;
- (void)forceRefreshOpenGL;
// sends gecko an ime composition event
- (void) sendCompositionEvent:(PRInt32)aEventType;
// do generic gecko event setup with a generic cocoa event. accepts nil inEvent.
- (void) convertGenericCocoaEvent:(NSEvent*)inEvent toGeckoEvent:(nsInputEvent*)outGeckoEvent;
@ -2200,10 +2197,6 @@ NSEvent* gLastDragMouseDownEvent = nil;
mPendingDisplay = NO;
mBlockedLastMouseDown = NO;
// initialization for NSTextInput
mMarkedRange.location = NSNotFound;
mMarkedRange.length = 0;
mLastMouseDownEvent = nil;
mClickThroughMouseDownEvent = nil;
mDragService = nsnull;
@ -4742,21 +4735,6 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
mPluginComplexTextInputRequested = YES;
}
- (void)sendCompositionEvent:(PRInt32) aEventType
{
#ifdef DEBUG_IME
NSLog(@"****in sendCompositionEvent; type = %d", aEventType);
#endif
if (!mGeckoChild)
return;
// static void init_composition_event( *aEvent, int aType)
nsCompositionEvent event(PR_TRUE, aEventType, mGeckoChild);
event.time = PR_IntervalNow();
mGeckoChild->DispatchWindowEvent(event);
}
#pragma mark -
// NSTextInput implementation
@ -4769,7 +4747,6 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
#if DEBUG_IME
NSLog(@"****in insertText: '%@'", insertString);
NSLog(@" markRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
#endif
if (!mGeckoChild)
return;
@ -4850,37 +4827,9 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
}
}
else {
if (!mGeckoChild->TextInputHandler()->IsIMEComposing()) {
[self sendCompositionEvent:NS_COMPOSITION_START];
// Note: mGeckoChild might have become null here. Don't count on it from here on.
if (mGeckoChild) {
mGeckoChild->TextInputHandler()->OnStartIMEComposition(self);
// Note: mGeckoChild might have become null here. Don't count on it from here on.
}
}
if (mGeckoChild && mGeckoChild->TextInputHandler()->IgnoreIMECommit()) {
tmpStr = [tmpStr init];
len = 0;
bufPtr[0] = PRUnichar('\0');
insertString =
[[[NSAttributedString alloc] initWithString:tmpStr] autorelease];
}
if (mGeckoChild) {
NSRange range = NSMakeRange(0, len);
mGeckoChild->TextInputHandler()->
DispatchTextEvent(nsDependentString(bufPtr), insertString,
range, PR_TRUE);
}
// Note: mGeckoChild might have become null here. Don't count on it from here on.
[self sendCompositionEvent:NS_COMPOSITION_END];
// Note: mGeckoChild might have become null here. Don't count on it from here on.
if (mGeckoChild) {
mGeckoChild->TextInputHandler()->OnEndIMEComposition();
// Note: mGeckoChild might have become null here. Don't count on it from here on.
}
mMarkedRange = NSMakeRange(NSNotFound, 0);
NSAttributedString* attrStr =
static_cast<NSAttributedString*>(insertString);
mGeckoChild->TextInputHandler()->InsertTextAsCommittingComposition(attrStr);
}
if (bufPtr != buffer)
@ -4912,95 +4861,32 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
#if DEBUG_IME
NSLog(@"****in setMarkedText location: %d, length: %d", selRange.location, selRange.length);
NSLog(@" markRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
NSLog(@" aString = '%@'", aString);
#endif
if (!mGeckoChild)
return;
if (mGeckoChild->TextInputHandler()->IgnoreIMEComposition())
return;
NS_ENSURE_TRUE(mGeckoChild, );
nsAutoRetainCocoaObject kungFuDeathGrip(self);
if (![aString isKindOfClass:[NSAttributedString class]])
aString = [[[NSAttributedString alloc] initWithString:aString] autorelease];
NSMutableAttributedString *mutableAttribStr = aString;
NSString *tmpStr = [mutableAttribStr string];
unsigned int len = [tmpStr length];
PRUnichar buffer[MAX_BUFFER_SIZE];
PRUnichar *bufPtr = (len >= MAX_BUFFER_SIZE) ? new PRUnichar[len + 1] : buffer;
[tmpStr getCharacters:bufPtr];
bufPtr[len] = PRUnichar('\0');
#if DEBUG_IME
printf("****in setMarkedText, len = %d, text = ", len);
PRUint32 n = 0;
PRUint32 maxlen = len > 12 ? 12 : len;
for (PRUnichar *a = bufPtr; (*a != PRUnichar('\0')) && n<maxlen; a++, n++)
printf((*a&0xff80) ? "\\u%4X" : "%c", *a);
printf("\n");
#endif
mMarkedRange.length = len;
if (!mGeckoChild->TextInputHandler()->IsIMEComposing() && len > 0) {
nsQueryContentEvent selection(PR_TRUE, NS_QUERY_SELECTED_TEXT, mGeckoChild);
mGeckoChild->DispatchWindowEvent(selection);
mMarkedRange.location = selection.mSucceeded ? selection.mReply.mOffset : 0;
[self sendCompositionEvent:NS_COMPOSITION_START];
// Note: mGeckoChild might have become null here. Don't count on it from here on.
if (mGeckoChild) {
mGeckoChild->TextInputHandler()->OnStartIMEComposition(self);
// Note: mGeckoChild might have become null here. Don't count on it from here on.
}
NSAttributedString* attrStr;
if ([aString isKindOfClass:[NSAttributedString class]]) {
attrStr = static_cast<NSAttributedString*>(aString);
} else {
attrStr = [[[NSAttributedString alloc] initWithString:aString] autorelease];
}
if (mGeckoChild->TextInputHandler()->IsIMEComposing()) {
mGeckoChild->TextInputHandler()->OnUpdateIMEComposition(tmpStr);
PRBool doCommit = (len == 0);
mGeckoChild->TextInputHandler()->
DispatchTextEvent(nsDependentString(bufPtr), aString, selRange, doCommit);
// Note: mGeckoChild might have become null here. Don't count on it from here on.
if (doCommit) {
[self sendCompositionEvent:NS_COMPOSITION_END];
// Note: mGeckoChild might have become null here. Don't count on it from here on.
if (mGeckoChild) {
mGeckoChild->TextInputHandler()->OnEndIMEComposition();
// Note: mGeckoChild might have become null here. Don't count on it from here on.
}
}
}
if (bufPtr != buffer)
delete[] bufPtr;
mGeckoChild->TextInputHandler()->SetMarkedText(attrStr, selRange);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (void) unmarkText
{
#if DEBUG_IME
NSLog(@"****in unmarkText");
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
#endif
if (mGeckoChild)
mGeckoChild->TextInputHandler()->CommitIMEComposition();
NS_ENSURE_TRUE(mGeckoChild, );
mGeckoChild->TextInputHandler()->CommitIMEComposition();
}
- (BOOL) hasMarkedText
{
#if DEBUG_IME
NSLog(@"****in hasMarkText");
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
#endif
return (mMarkedRange.location != NSNotFound) && (mMarkedRange.length != 0);
NS_ENSURE_TRUE(mGeckoChild, NO);
return mGeckoChild->TextInputHandler()->HasMarkedText();
}
- (NSInteger) conversationIdentifier
@ -5028,7 +4914,6 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
#if DEBUG_IME
NSLog(@"****in attributedSubstringFromRange");
NSLog(@" theRange = %d, %d", theRange.location, theRange.length);
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
#endif
if (!mGeckoChild || theRange.length == 0)
return nil;
@ -5054,16 +4939,8 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
#if DEBUG_IME
NSLog(@"****in markedRange");
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
#endif
if (![self hasMarkedText]) {
return NSMakeRange(NSNotFound, 0);
}
return mMarkedRange;
NS_ENSURE_TRUE(mGeckoChild, NSMakeRange(NSNotFound, 0));
return mGeckoChild->TextInputHandler()->MarkedRange();
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakeRange(0, 0));
}
@ -5074,7 +4951,6 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
#if DEBUG_IME
NSLog(@"****in selectedRange");
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
#endif
if (!mGeckoChild)
return NSMakeRange(NSNotFound, 0);
@ -5100,7 +4976,6 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
#if DEBUG_IME
NSLog(@"****in firstRectForCharacterRange");
NSLog(@" theRange = %d, %d", theRange.location, theRange.length);
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
#endif
// XXX this returns first character rect or caret rect, it is limitation of
// now. We need more work for returns first line rect. But current
@ -5155,7 +5030,6 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
{
#if DEBUG_IME
NSLog(@"****in characterIndexForPoint");
NSLog(@" markRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
#endif
// To implement this, we'd have to grovel in text frames looking at text offsets.
@ -5168,7 +5042,6 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
#if DEBUG_IME
NSLog(@"****in validAttributesForMarkedText");
NSLog(@" markRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
#endif
//return [NSArray arrayWithObjects:NSUnderlineStyleAttributeName, NSMarkedClauseSegmentAttributeName, NSTextInputReplacementRangeAttributeName, nil];

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

@ -50,6 +50,7 @@
#include "nsITimer.h"
#include "npapi.h"
#include "nsTArray.h"
#include "nsEvent.h"
struct PRLogModuleInfo;
class nsChildView;
@ -233,10 +234,6 @@ public:
virtual void OnFocusChangeInGecko(PRBool aFocus);
virtual void OnDestroyView(NSView<mozView> *aDestroyingView);
void OnStartIMEComposition(NSView<mozView> *aView);
void OnUpdateIMEComposition(NSString* aIMECompositionString);
void OnEndIMEComposition();
/**
* DispatchTextEvent() dispatches a text event on mOwnerWidget.
*
@ -252,6 +249,41 @@ public:
NSRange& aSelectedRange,
PRBool aDoCommit);
/**
* SetMarkedText() is a handler of setMarkedText of NSTextInput.
*
* @param aAttrString This mut be an instance of NSAttributedString.
* If the aString parameter to
* [ChildView setMarkedText:setSelectedRange:]
* isn't an instance of NSAttributedString,
* create an NSAttributedString from it and pass
* that instead.
* @param aSelectedRange Current selected range (or caret position).
*/
void SetMarkedText(NSAttributedString* aAttrString,
NSRange& aSelectedRange);
/**
* InsertTextAsCommittingComposition() commits current composition. If there
* is no composition, this starts a composition and commits it immediately.
*
* @param aAttrString A string which is committed.
*/
void InsertTextAsCommittingComposition(NSAttributedString* aAttrString);
PRBool HasMarkedText()
{
return (mMarkedRange.location != NSNotFound) && (mMarkedRange.length != 0);
}
NSRange MarkedRange()
{
if (!HasMarkedText()) {
return NSMakeRange(NSNotFound, 0);
}
return mMarkedRange;
}
PRBool IsIMEComposing() { return mIsIMEComposing; }
PRBool IsIMEOpened();
PRBool IsIMEEnabled() { return mIsIMEEnabled; }
@ -309,6 +341,8 @@ private:
// If mIsIMEComposing is true, the composition string is stored here.
NSString* mIMECompositionString;
NSRange mMarkedRange;
PRPackedBool mIsIMEComposing;
PRPackedBool mIsIMEEnabled;
PRPackedBool mIsASCIICapableOnly;
@ -379,6 +413,29 @@ private:
NSAttributedString *aAttrString,
NSRange& aSelectedRange);
/**
* InitCompositionEvent() initializes aCompositionEvent.
*
* @param aCompositionEvent A composition event which you want to
* initialize.
*/
void InitCompositionEvent(nsCompositionEvent& aCompositionEvent);
/**
* When a composition starts, OnStartIMEComposition() is called.
*/
void OnStartIMEComposition();
/**
* When a composition is updated, OnUpdateIMEComposition() is called.
*/
void OnUpdateIMEComposition(NSString* aIMECompositionString);
/**
* When a composition is finished, OnEndIMEComposition() is called.
*/
void OnEndIMEComposition();
// The focused IME handler. Please note that the handler might lost the
// actual focus by deactivating the application. If we are active, this
// must have the actual focused handle.

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

@ -1034,6 +1034,132 @@ nsCocoaIMEHandler::DispatchTextEvent(const nsString& aText,
return mOwnerWidget->DispatchWindowEvent(textEvent);
}
void
nsCocoaIMEHandler::InitCompositionEvent(nsCompositionEvent& aCompositionEvent)
{
aCompositionEvent.time = PR_IntervalNow();
}
void
nsCocoaIMEHandler::InsertTextAsCommittingComposition(
NSAttributedString* aAttrString)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
#if DEBUG_IME
NSLog(@"****in InsertTextAsCommittingComposition: '%@'", aAttrString);
NSLog(@" mMarkedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
#endif
nsRefPtr<nsChildView> kungFuDeathGrip(mOwnerWidget);
nsString str;
GetStringForNSString([aAttrString string], str);
if (!IsIMEComposing()) {
// XXXmnakano Probably, we shouldn't emulate composition in this case.
// I think that we should just fire DOM3 textInput event if we implement it.
nsCompositionEvent compStart(PR_TRUE, NS_COMPOSITION_START, mOwnerWidget);
InitCompositionEvent(compStart);
mOwnerWidget->DispatchWindowEvent(compStart);
if (!mView) {
return; // we're destroyed
}
OnStartIMEComposition();
}
if (IgnoreIMECommit()) {
str.Truncate();
}
NSRange range = NSMakeRange(0, str.Length());
DispatchTextEvent(str, aAttrString, range, PR_TRUE);
if (!mView) {
return; // we're destroyed
}
OnUpdateIMEComposition([aAttrString string]);
nsCompositionEvent compEnd(PR_TRUE, NS_COMPOSITION_END, mOwnerWidget);
InitCompositionEvent(compEnd);
mOwnerWidget->DispatchWindowEvent(compEnd);
if (!mView) {
return; // we're destroyed
}
OnEndIMEComposition();
mMarkedRange = NSMakeRange(NSNotFound, 0);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
void
nsCocoaIMEHandler::SetMarkedText(NSAttributedString* aAttrString,
NSRange& aSelectedRange)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
#if DEBUG_IME_HANDLER
NSLog(@"****in SetMarkedText location: %d, length: %d",
aSelectedRange.location, aSelectedRange.length);
NSLog(@" mMarkedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
NSLog(@" aAttrString = '%@'", aAttrString);
#endif
if (IgnoreIMEComposition()) {
return;
}
nsRefPtr<nsChildView> kungFuDeathGrip(mOwnerWidget);
nsString str;
GetStringForNSString([aAttrString string], str);
mMarkedRange.length = str.Length();
if (!IsIMEComposing() && !str.IsEmpty()) {
nsQueryContentEvent selection(PR_TRUE, NS_QUERY_SELECTED_TEXT,
mOwnerWidget);
mOwnerWidget->DispatchWindowEvent(selection);
mMarkedRange.location = selection.mSucceeded ? selection.mReply.mOffset : 0;
nsCompositionEvent compStart(PR_TRUE, NS_COMPOSITION_START, mOwnerWidget);
InitCompositionEvent(compStart);
mOwnerWidget->DispatchWindowEvent(compStart);
if (!mView) {
return; // we're destroyed
}
OnStartIMEComposition();
}
if (IsIMEComposing()) {
OnUpdateIMEComposition([aAttrString string]);
PRBool doCommit = str.IsEmpty();
DispatchTextEvent(str, aAttrString, aSelectedRange, doCommit);
if (!mView) {
return; // we're destroyed
}
if (doCommit) {
nsCompositionEvent compEnd(PR_TRUE, NS_COMPOSITION_END, mOwnerWidget);
InitCompositionEvent(compEnd);
mOwnerWidget->DispatchWindowEvent(compEnd);
if (!mView) {
return; // we're destroyed
}
OnEndIMEComposition();
}
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
#pragma mark -
@ -1053,6 +1179,9 @@ nsCocoaIMEHandler::nsCocoaIMEHandler() :
{
gHandlerInstanceCount++;
InitStaticMembers();
mMarkedRange.location = NSNotFound;
mMarkedRange.length = 0;
}
nsCocoaIMEHandler::~nsCocoaIMEHandler()
@ -1131,19 +1260,18 @@ nsCocoaIMEHandler::OnDestroyView(NSView<mozView> *aDestroyingView)
}
void
nsCocoaIMEHandler::OnStartIMEComposition(NSView<mozView> *aView)
nsCocoaIMEHandler::OnStartIMEComposition()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
#ifdef DEBUG_IME_HANDLER
DebugPrintPointer(this);
NSLog(@"nsCocoaIMEHandler::OnStartIMEComposition");
NSLog(@" aView:%p mView:%p currentInputManager:%p",
aView, mView, [NSInputManager currentInputManager]);
NSLog(@" mView=%p, currentInputManager:%p",
mView, [NSInputManager currentInputManager]);
#endif // DEBUG_IME_HANDLER
NS_ASSERTION(!mIsIMEComposing, "There is a composition already");
NS_ASSERTION(aView == mView, "The composition is started on another view");
mIsIMEComposing = PR_TRUE;
NS_OBJC_END_TRY_ABORT_BLOCK;