Bug 519972 part.2 Move text event dispatcher to nsCocoaIMEHandler r=smichaud

This commit is contained in:
Masayuki Nakano 2011-02-17 16:41:36 +09:00
Родитель e6d71c2141
Коммит bc645b6f71
3 изменённых файлов: 202 добавлений и 156 удалений

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

@ -158,13 +158,6 @@ PRUint32 nsChildView::sLastInputEventCount = 0;
// sends gecko an ime composition event
- (void) sendCompositionEvent:(PRInt32)aEventType;
// sends gecko an ime text event
- (void) sendTextEvent:(PRUnichar*) aBuffer
attributedString:(NSAttributedString*) aString
selectedRange:(NSRange)selRange
markedRange:(NSRange)markRange
doCommit:(BOOL)doCommit;
// do generic gecko event setup with a generic cocoa event. accepts nil inEvent.
- (void) convertGenericCocoaEvent:(NSEvent*)inEvent toGeckoEvent:(nsInputEvent*)outGeckoEvent;
@ -346,121 +339,6 @@ InitNPCocoaEvent(NPCocoaEvent* event)
memset(event, 0, sizeof(NPCocoaEvent));
}
static PRUint32
UnderlineAttributeToTextRangeType(PRUint32 aUnderlineStyle, NSRange selRange)
{
#ifdef DEBUG_IME
NSLog(@"****in underlineAttributeToTextRangeType = %d", aUnderlineStyle);
#endif
// For more info on the underline attribute, please see:
// http://developer.apple.com/techpubs/macosx/Cocoa/TasksAndConcepts/ProgrammingTopics/AttributedStrings/Tasks/AccessingAttrs.html
// We are not clear where the define for value 2 is right now.
// To see this value in japanese ime, type 'aaaaaaaaa' and hit space to make the
// ime send you some part of text in 1 (NSSingleUnderlineStyle) and some part in 2.
// ftang will ask apple for more details
//
// It probably means show 1-pixel thickness underline vs 2-pixel thickness.
PRUint32 attr;
if (selRange.length == 0) {
switch (aUnderlineStyle) {
case 1:
attr = NS_TEXTRANGE_RAWINPUT;
break;
case 2:
default:
attr = NS_TEXTRANGE_SELECTEDRAWTEXT;
break;
}
}
else {
switch (aUnderlineStyle) {
case 1:
attr = NS_TEXTRANGE_CONVERTEDTEXT;
break;
case 2:
default:
attr = NS_TEXTRANGE_SELECTEDCONVERTEDTEXT;
break;
}
}
return attr;
}
static PRUint32
CountRanges(NSAttributedString *aString)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
// Iterate through aString for the NSUnderlineStyleAttributeName and count the
// different segments adjusting limitRange as we go.
PRUint32 count = 0;
NSRange effectiveRange;
NSRange limitRange = NSMakeRange(0, [aString length]);
while (limitRange.length > 0) {
[aString attribute:NSUnderlineStyleAttributeName
atIndex:limitRange.location
longestEffectiveRange:&effectiveRange
inRange:limitRange];
limitRange = NSMakeRange(NSMaxRange(effectiveRange),
NSMaxRange(limitRange) - NSMaxRange(effectiveRange));
count++;
}
return count;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
}
static void
ConvertAttributeToGeckoRange(NSAttributedString *aString, NSRange markRange, NSRange selRange, PRUint32 inCount, nsTextRange* aRanges)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
// Convert the Cocoa range into the nsTextRange Array used in Gecko.
// Iterate through the attributed string and map the underline attribute to Gecko IME textrange attributes.
// We may need to change the code here if we change the implementation of validAttributesForMarkedText.
PRUint32 i = 0;
NSRange effectiveRange;
NSRange limitRange = NSMakeRange(0, [aString length]);
while ((limitRange.length > 0) && (i < inCount)) {
id attributeValue = [aString attribute:NSUnderlineStyleAttributeName
atIndex:limitRange.location
longestEffectiveRange:&effectiveRange
inRange:limitRange];
aRanges[i].mStartOffset = effectiveRange.location;
aRanges[i].mEndOffset = NSMaxRange(effectiveRange);
aRanges[i].mRangeType = UnderlineAttributeToTextRangeType([attributeValue intValue], selRange);
limitRange = NSMakeRange(NSMaxRange(effectiveRange),
NSMaxRange(limitRange) - NSMaxRange(effectiveRange));
i++;
}
// Get current caret position.
aRanges[i].mStartOffset = selRange.location + selRange.length;
aRanges[i].mEndOffset = aRanges[i].mStartOffset;
aRanges[i].mRangeType = NS_TEXTRANGE_CARETPOSITION;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
static void
FillTextRangeInTextEvent(nsTextEvent *aTextEvent, NSAttributedString* aString, NSRange markRange, NSRange selRange)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
// Count the number of segments in the attributed string and add one more count for sending current caret position to Gecko.
// Allocate the right size of nsTextRange and draw caret at right position.
// Convert the attributed string into an array of nsTextRange and get current caret position by calling above functions.
PRUint32 count = CountRanges(aString) + 1;
aTextEvent->rangeArray = new nsTextRange[count];
if (aTextEvent->rangeArray) {
aTextEvent->rangeCount = count;
ConvertAttributeToGeckoRange(aString, markRange, selRange, aTextEvent->rangeCount, aTextEvent->rangeArray);
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
#if defined(DEBUG) && defined(PR_LOGGING)
static void DebugPrintAllKeyboardLayouts()
@ -4879,30 +4757,6 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
mGeckoChild->DispatchWindowEvent(event);
}
- (void)sendTextEvent:(PRUnichar*) aBuffer
attributedString:(NSAttributedString*) aString
selectedRange:(NSRange) selRange
markedRange:(NSRange) markRange
doCommit:(BOOL) doCommit
{
#ifdef DEBUG_IME
NSLog(@"****in sendTextEvent; string = '%@'", aString);
NSLog(@" markRange = %d, %d; selRange = %d, %d", markRange.location, markRange.length, selRange.location, selRange.length);
#endif
if (!mGeckoChild)
return;
nsTextEvent textEvent(PR_TRUE, NS_TEXT_TEXT, mGeckoChild);
textEvent.time = PR_IntervalNow();
textEvent.theText = aBuffer;
if (!doCommit)
FillTextRangeInTextEvent(&textEvent, aString, markRange, selRange);
mGeckoChild->DispatchWindowEvent(textEvent);
if (textEvent.rangeArray)
delete [] textEvent.rangeArray;
}
#pragma mark -
// NSTextInput implementation
@ -5012,10 +4866,12 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
insertString =
[[[NSAttributedString alloc] initWithString:tmpStr] autorelease];
}
[self sendTextEvent:bufPtr attributedString:insertString
selectedRange:NSMakeRange(0, len)
markedRange:mMarkedRange
doCommit:YES];
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];
@ -5107,14 +4963,12 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
if (mGeckoChild->TextInputHandler()->IsIMEComposing()) {
mGeckoChild->TextInputHandler()->OnUpdateIMEComposition(tmpStr);
BOOL commit = len == 0;
[self sendTextEvent:bufPtr attributedString:aString
selectedRange:selRange
markedRange:mMarkedRange
doCommit:commit];
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 (commit) {
if (doCommit) {
[self sendCompositionEvent:NS_COMPOSITION_END];
// Note: mGeckoChild might have become null here. Don't count on it from here on.
if (mGeckoChild) {

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

@ -49,9 +49,11 @@
#include "nsCOMPtr.h"
#include "nsITimer.h"
#include "npapi.h"
#include "nsTArray.h"
struct PRLogModuleInfo;
class nsChildView;
struct nsTextRange;
/**
* nsTISInputSource is a wrapper for the TISInputSourceRef. If we get the
@ -235,6 +237,21 @@ public:
void OnUpdateIMEComposition(NSString* aIMECompositionString);
void OnEndIMEComposition();
/**
* DispatchTextEvent() dispatches a text event on mOwnerWidget.
*
* @param aText User text input.
* @param aAttrString An NSAttributedString instance which indicates
* current composition string.
* @param aSelectedRange Current selected range (or caret position).
* @param aDoCommit TRUE if the composition string should be
* committed. Otherwise, FALSE.
*/
PRBool DispatchTextEvent(const nsString& aText,
NSAttributedString* aAttrString,
NSRange& aSelectedRange,
PRBool aDoCommit);
PRBool IsIMEComposing() { return mIsIMEComposing; }
PRBool IsIMEOpened();
PRBool IsIMEEnabled() { return mIsIMEEnabled; }
@ -322,6 +339,46 @@ private:
static void FlushPendingMethods(nsITimer* aTimer, void* aClosure);
/**
* ConvertToTextRangeStyle converts the given native underline style to
* our defined text range type.
*
* @param aUnderlineStyle NSUnderlineStyleSingle or
* NSUnderlineStyleThick.
* @param aSelectedRange Current selected range (or caret position).
* @return NS_TEXTRANGE_*.
*/
PRUint32 ConvertToTextRangeType(PRUint32 aUnderlineStyle,
NSRange& aSelectedRange);
/**
* GetRangeCount() computes the range count of aAttrString.
*
* @param aAttrString An NSAttributedString instance whose number of
* NSUnderlineStyleAttributeName ranges you with
* to know.
* @return The count of NSUnderlineStyleAttributeName
* ranges in aAttrString.
*/
PRUint32 GetRangeCount(NSAttributedString *aString);
/**
* SetTextRangeList() appends text ranges to aTextRangeList.
*
* @param aTextRangeList When SetTextRangeList() returns, this will
* be set to the NSUnderlineStyleAttributeName
* ranges in aAttrString. Note that if you pass
* in a large enough auto-range instance for most
* cases (e.g., nsAutoTArray<nsTextRange, 4>),
* it prevents memory fragmentation.
* @param aAttrString An NSAttributedString instance which indicates
* current composition string.
* @param aSelectedRange Current selected range (or caret position).
*/
void SetTextRangeList(nsTArray<nsTextRange>& aTextRangeList,
NSAttributedString *aAttrString,
NSRange& aSelectedRange);
// 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.

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

@ -899,6 +899,141 @@ nsCocoaIMEHandler::ExecutePendingMethods()
NS_OBJC_END_TRY_ABORT_BLOCK;
}
#pragma mark -
/******************************************************************************
*
* nsCocoaIMEHandler implementation (native event handlers)
*
******************************************************************************/
PRUint32
nsCocoaIMEHandler::ConvertToTextRangeType(PRUint32 aUnderlineStyle,
NSRange& aSelectedRange)
{
#ifdef DEBUG_IME_HANDLER
NSLog(@"****in ConvertToTextRangeType = %d", aUnderlineStyle);
#endif
// We assume that aUnderlineStyle is NSUnderlineStyleSingle or
// NSUnderlineStyleThick. NSUnderlineStyleThick should indicate a selected
// clause. Otherwise, should indicate non-selected clause.
if (aSelectedRange.length == 0) {
switch (aUnderlineStyle) {
case NSUnderlineStyleSingle:
return NS_TEXTRANGE_RAWINPUT;
case NSUnderlineStyleThick:
return NS_TEXTRANGE_SELECTEDRAWTEXT;
default:
NS_WARNING("Unexpected line style");
return NS_TEXTRANGE_SELECTEDRAWTEXT;
}
}
switch (aUnderlineStyle) {
case NSUnderlineStyleSingle:
return NS_TEXTRANGE_CONVERTEDTEXT;
case NSUnderlineStyleThick:
return NS_TEXTRANGE_SELECTEDCONVERTEDTEXT;
default:
NS_WARNING("Unexpected line style");
return NS_TEXTRANGE_SELECTEDCONVERTEDTEXT;
}
}
PRUint32
nsCocoaIMEHandler::GetRangeCount(NSAttributedString *aAttrString)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
// Iterate through aAttrString for the NSUnderlineStyleAttributeName and
// count the different segments adjusting limitRange as we go.
PRUint32 count = 0;
NSRange effectiveRange;
NSRange limitRange = NSMakeRange(0, [aAttrString length]);
while (limitRange.length > 0) {
[aAttrString attribute:NSUnderlineStyleAttributeName
atIndex:limitRange.location
longestEffectiveRange:&effectiveRange
inRange:limitRange];
limitRange =
NSMakeRange(NSMaxRange(effectiveRange),
NSMaxRange(limitRange) - NSMaxRange(effectiveRange));
count++;
}
return count;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
}
void
nsCocoaIMEHandler::SetTextRangeList(nsTArray<nsTextRange>& aTextRangeList,
NSAttributedString *aAttrString,
NSRange& aSelectedRange)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
// Convert the Cocoa range into the nsTextRange Array used in Gecko.
// Iterate through the attributed string and map the underline attribute to
// Gecko IME textrange attributes. We may need to change the code here if
// we change the implementation of validAttributesForMarkedText.
NSRange limitRange = NSMakeRange(0, [aAttrString length]);
PRUint32 rangeCount = GetRangeCount(aAttrString);
for (PRUint32 i = 0; i < rangeCount && limitRange.length > 0; i++) {
NSRange effectiveRange;
id attributeValue = [aAttrString attribute:NSUnderlineStyleAttributeName
atIndex:limitRange.location
longestEffectiveRange:&effectiveRange
inRange:limitRange];
nsTextRange range;
range.mStartOffset = effectiveRange.location;
range.mEndOffset = NSMaxRange(effectiveRange);
range.mRangeType =
ConvertToTextRangeType([attributeValue intValue], aSelectedRange);
aTextRangeList.AppendElement(range);
limitRange =
NSMakeRange(NSMaxRange(effectiveRange),
NSMaxRange(limitRange) - NSMaxRange(effectiveRange));
}
// Get current caret position.
nsTextRange range;
range.mStartOffset = aSelectedRange.location + aSelectedRange.length;
range.mEndOffset = range.mStartOffset;
range.mRangeType = NS_TEXTRANGE_CARETPOSITION;
aTextRangeList.AppendElement(range);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
PRBool
nsCocoaIMEHandler::DispatchTextEvent(const nsString& aText,
NSAttributedString* aAttrString,
NSRange& aSelectedRange,
PRBool aDoCommit)
{
#ifdef DEBUG_IME_HANDLER
NSLog(@"****in DispatchTextEvent; string = '%@'", aAttrString);
NSLog(@" aSelectedRange = %d, %d",
aSelectedRange.location, aSelectedRange.length);
#endif
nsTextEvent textEvent(PR_TRUE, NS_TEXT_TEXT, mOwnerWidget);
textEvent.time = PR_IntervalNow();
textEvent.theText = aText;
nsAutoTArray<nsTextRange, 4> textRanges;
if (!aDoCommit) {
SetTextRangeList(textRanges, aAttrString, aSelectedRange);
}
textEvent.rangeArray = textRanges.Elements();
textEvent.rangeCount = textRanges.Length();
return mOwnerWidget->DispatchWindowEvent(textEvent);
}
#pragma mark -