зеркало из https://github.com/mozilla/gecko-dev.git
Bug 519972 part.2 Move text event dispatcher to nsCocoaIMEHandler r=smichaud
This commit is contained in:
Родитель
e6d71c2141
Коммит
bc645b6f71
|
@ -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 -
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче