Bug 519972 part.4 Move NSTextInput handler to nsCocoaIMEHandler (except insertText) r=smichaud

This commit is contained in:
Masayuki Nakano 2011-02-19 13:55:49 +09:00
parent 6e4e990426
commit 6f6a0d477b
3 changed files with 256 additions and 118 deletions

View File

@ -4891,48 +4891,15 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
- (NSInteger) conversationIdentifier
{
#if DEBUG_IME
NSLog(@"****in conversationIdentifier");
#endif
if (!mGeckoChild)
return (long)self;
nsQueryContentEvent textContent(PR_TRUE, NS_QUERY_TEXT_CONTENT, mGeckoChild);
textContent.InitForQueryTextContent(0, 0);
mGeckoChild->DispatchWindowEvent(textContent);
if (!textContent.mSucceeded)
return (long)self;
#if DEBUG_IME
NSLog(@" the ID = %ld", (long)textContent.mReply.mContentsRoot);
#endif
return (long)textContent.mReply.mContentsRoot;
NS_ENSURE_TRUE(mGeckoChild, reinterpret_cast<NSInteger>(self));
return mGeckoChild->TextInputHandler()->ConversationIdentifier();
}
- (NSAttributedString *) attributedSubstringFromRange:(NSRange)theRange
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
#if DEBUG_IME
NSLog(@"****in attributedSubstringFromRange");
NSLog(@" theRange = %d, %d", theRange.location, theRange.length);
#endif
if (!mGeckoChild || theRange.length == 0)
return nil;
nsAutoString str;
nsQueryContentEvent textContent(PR_TRUE, NS_QUERY_TEXT_CONTENT, mGeckoChild);
textContent.InitForQueryTextContent(theRange.location, theRange.length);
mGeckoChild->DispatchWindowEvent(textContent);
if (!textContent.mSucceeded || textContent.mReply.mString.IsEmpty())
return nil;
NSString* nsstr = ToNSString(textContent.mReply.mString);
NSAttributedString* result =
[[[NSAttributedString alloc] initWithString:nsstr
attributes:nil] autorelease];
return result;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
NS_ENSURE_TRUE(mGeckoChild, nil);
return mGeckoChild->TextInputHandler()->
GetAttributedSubstringFromRange(theRange);
}
- (NSRange) markedRange
@ -4949,103 +4916,31 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
#if DEBUG_IME
NSLog(@"****in selectedRange");
#endif
if (!mGeckoChild)
return NSMakeRange(NSNotFound, 0);
nsQueryContentEvent selection(PR_TRUE, NS_QUERY_SELECTED_TEXT, mGeckoChild);
mGeckoChild->DispatchWindowEvent(selection);
if (!selection.mSucceeded)
return NSMakeRange(NSNotFound, 0);
#if DEBUG_IME
NSLog(@" result of selectedRange = %d, %d",
selection.mReply.mOffset, selection.mReply.mString.Length());
#endif
return NSMakeRange(selection.mReply.mOffset,
selection.mReply.mString.Length());
NS_ENSURE_TRUE(mGeckoChild, NSMakeRange(NSNotFound, 0));
return mGeckoChild->TextInputHandler()->SelectedRange();
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakeRange(0, 0));
}
- (NSRect) firstRectForCharacterRange:(NSRange)theRange
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
#if DEBUG_IME
NSLog(@"****in firstRectForCharacterRange");
NSLog(@" theRange = %d, %d", theRange.location, theRange.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
// implementation is enough for IMEs.
NSRect rect;
if (!mGeckoChild || theRange.location == NSNotFound)
return rect;
nsIntRect r;
PRBool useCaretRect = theRange.length == 0;
if (!useCaretRect) {
nsQueryContentEvent charRect(PR_TRUE, NS_QUERY_TEXT_RECT, mGeckoChild);
charRect.InitForQueryTextRect(theRange.location, 1);
mGeckoChild->DispatchWindowEvent(charRect);
if (charRect.mSucceeded)
r = charRect.mReply.mRect;
else
useCaretRect = PR_TRUE;
}
if (useCaretRect) {
nsQueryContentEvent caretRect(PR_TRUE, NS_QUERY_CARET_RECT, mGeckoChild);
caretRect.InitForQueryCaretRect(theRange.location);
mGeckoChild->DispatchWindowEvent(caretRect);
if (!caretRect.mSucceeded)
return rect;
r = caretRect.mReply.mRect;
r.width = 0;
}
nsIWidget* rootWidget = mGeckoChild->GetTopLevelWidget();
NSWindow* rootWindow =
static_cast<NSWindow*>(rootWidget->GetNativeData(NS_NATIVE_WINDOW));
NSView* rootView =
static_cast<NSView*>(rootWidget->GetNativeData(NS_NATIVE_WIDGET));
if (!rootWindow || !rootView)
return rect;
GeckoRectToNSRect(r, rect);
rect = [rootView convertRect:rect toView:nil];
rect.origin = [rootWindow convertBaseToScreen:rect.origin];
#if DEBUG_IME
NSLog(@" result rect (x,y,w,h) = %f, %f, %f, %f",
rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
#endif
return rect;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakeRect(0.0, 0.0, 0.0, 0.0));
NS_ENSURE_TRUE(mGeckoChild, rect);
return mGeckoChild->TextInputHandler()->FirstRectForCharacterRange(theRange);
}
- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint
{
#if DEBUG_IME
NSLog(@"****in characterIndexForPoint");
#endif
// To implement this, we'd have to grovel in text frames looking at text offsets.
return 0;
NS_ENSURE_TRUE(mGeckoChild, 0);
return mGeckoChild->TextInputHandler()->CharacterIndexForPoint(thePoint);
}
- (NSArray*) validAttributesForMarkedText
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
#if DEBUG_IME
NSLog(@"****in validAttributesForMarkedText");
#endif
//return [NSArray arrayWithObjects:NSUnderlineStyleAttributeName, NSMarkedClauseSegmentAttributeName, NSTextInputReplacementRangeAttributeName, nil];
return [NSArray array]; // empty array; we don't support any attributes right now
NS_ENSURE_TRUE(mGeckoChild, [NSArray array]);
return mGeckoChild->TextInputHandler()->GetValidAttributesForMarkedText();
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}

View File

@ -271,6 +271,69 @@ public:
*/
void InsertTextAsCommittingComposition(NSAttributedString* aAttrString);
/**
* ConversationIdentifier() returns an ID for the current editor. The ID is
* guaranteed to be unique among currently existing editors. But it might be
* the same as the ID of an editor that has already been destroyed.
*
* @return An identifier of current focused editor.
*/
NSInteger ConversationIdentifier();
/**
* GetAttributedSubstringFromRange() returns an NSAttributedString instance
* which is allocated as autorelease for aRange.
*
* @param aRange The range of string which you want.
* @return The string in aRange. If the string is empty,
* this returns nil. If succeeded, this returns
* an instance which is allocated as autorelease.
* If this has some troubles, returns nil.
*/
NSAttributedString* GetAttributedSubstringFromRange(NSRange& aRange);
/**
* SelectedRange() returns current selected range.
*
* @return If an editor has focus, this returns selection
* range in the editor. Otherwise, this returns
* selection range in the focused document.
*/
NSRange SelectedRange();
/**
* FirstRectForCharacterRange() returns first *character* rect in the range.
* Cocoa needs the first line rect in the range, but we cannot compute it
* on current implementation.
*
* @param aRange A range of text to examine. Its position is
* an offset from the beginning of the focused
* editor or document.
* @return An NSRect containing the first character in
* aRange, in screen coordinates.
* If the length of aRange is 0, the width will
* be 0.
*/
NSRect FirstRectForCharacterRange(NSRange& aRange);
/**
* CharacterIndexForPoint() returns an offset of a character at aPoint.
* XXX This isn't implemented, always returns 0.
*
* @param The point in screen coordinates.
* @return The offset of the character at aPoint from
* the beginning of the focused editor or
* document.
*/
NSUInteger CharacterIndexForPoint(NSPoint& aPoint);
/**
* GetValidAttributesForMarkedText() returns attributes which we support.
*
* @return Always empty array for now.
*/
NSArray* GetValidAttributesForMarkedText();
PRBool HasMarkedText()
{
return (mMarkedRange.location != NSNotFound) && (mMarkedRange.length != 0);

View File

@ -53,6 +53,8 @@
//#define DEBUG_IME_HANDLER 1
//#define DEBUG_TEXT_INPUT_HANDLER 1
// TODO: static methods should be moved to nsCocoaUtils
static void
GetStringForNSString(const NSString *aSrc, nsAString& aDist)
{
@ -69,6 +71,21 @@ GetStringForNSString(const NSString *aSrc, nsAString& aDist)
NS_OBJC_END_TRY_ABORT_BLOCK;
}
static NSString* ToNSString(const nsAString& aString)
{
return [NSString stringWithCharacters:aString.BeginReading()
length:aString.Length()];
}
static inline void
GeckoRectToNSRect(const nsIntRect& inGeckoRect, NSRect& outCocoaRect)
{
outCocoaRect.origin.x = inGeckoRect.x;
outCocoaRect.origin.y = inGeckoRect.y;
outCocoaRect.size.width = inGeckoRect.width;
outCocoaRect.size.height = inGeckoRect.height;
}
#ifdef DEBUG_IME_HANDLER
static const char*
@ -1160,6 +1177,169 @@ nsCocoaIMEHandler::SetMarkedText(NSAttributedString* aAttrString,
NS_OBJC_END_TRY_ABORT_BLOCK;
}
NSInteger
nsCocoaIMEHandler::ConversationIdentifier()
{
// NOTE: The size of NSInteger is same as pointer size.
nsQueryContentEvent textContent(PR_TRUE, NS_QUERY_TEXT_CONTENT, mOwnerWidget);
textContent.InitForQueryTextContent(0, 0);
mOwnerWidget->DispatchWindowEvent(textContent);
if (!textContent.mSucceeded) {
return reinterpret_cast<NSInteger>(mView);
}
// XXX This might return same ID as a previously existing editor if the
// deleted editor was created at the same address. Is there a better way?
return reinterpret_cast<NSInteger>(textContent.mReply.mContentsRoot);
}
NSAttributedString*
nsCocoaIMEHandler::GetAttributedSubstringFromRange(NSRange& aRange)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
#if DEBUG_IME_HANDLER
NSLog(@"****in GetAttributedSubstringFromRange");
NSLog(@" aRange = %d, %d", aRange.location, aRange.length);
#endif
if (aRange.location == NSNotFound || aRange.length == 0) {
return nil;
}
nsAutoString str;
nsQueryContentEvent textContent(PR_TRUE, NS_QUERY_TEXT_CONTENT, mOwnerWidget);
textContent.InitForQueryTextContent(aRange.location, aRange.length);
mOwnerWidget->DispatchWindowEvent(textContent);
if (!textContent.mSucceeded || textContent.mReply.mString.IsEmpty()) {
return nil;
}
NSString* nsstr = ToNSString(textContent.mReply.mString);
NSAttributedString* result =
[[[NSAttributedString alloc] initWithString:nsstr
attributes:nil] autorelease];
return result;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
NSRange
nsCocoaIMEHandler::SelectedRange()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
#if DEBUG_IME_HANDLER
NSLog(@"****in SelectedRange");
#endif
nsQueryContentEvent selection(PR_TRUE, NS_QUERY_SELECTED_TEXT, mOwnerWidget);
mOwnerWidget->DispatchWindowEvent(selection);
if (!selection.mSucceeded) {
return NSMakeRange(NSNotFound, 0);
}
#if DEBUG_IME_HANDLER
NSLog(@" result of SelectedRange = %d, %d",
selection.mReply.mOffset, selection.mReply.mString.Length());
#endif
return NSMakeRange(selection.mReply.mOffset,
selection.mReply.mString.Length());
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakeRange(0, 0));
}
NSRect
nsCocoaIMEHandler::FirstRectForCharacterRange(NSRange& aRange)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
#if DEBUG_IME_HANDLER
NSLog(@"****in FirstRectForCharacterRange");
NSLog(@" aRange = %d, %d", aRange.location, aRange.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
// implementation is enough for IMEs.
NSRect rect;
if (aRange.location == NSNotFound) {
return rect;
}
nsIntRect r;
PRBool useCaretRect = (aRange.length == 0);
if (!useCaretRect) {
nsQueryContentEvent charRect(PR_TRUE, NS_QUERY_TEXT_RECT, mOwnerWidget);
charRect.InitForQueryTextRect(aRange.location, 1);
mOwnerWidget->DispatchWindowEvent(charRect);
if (charRect.mSucceeded) {
r = charRect.mReply.mRect;
} else {
useCaretRect = PR_TRUE;
}
}
if (useCaretRect) {
nsQueryContentEvent caretRect(PR_TRUE, NS_QUERY_CARET_RECT, mOwnerWidget);
caretRect.InitForQueryCaretRect(aRange.location);
mOwnerWidget->DispatchWindowEvent(caretRect);
if (!caretRect.mSucceeded) {
return rect;
}
r = caretRect.mReply.mRect;
r.width = 0;
}
nsIWidget* rootWidget = mOwnerWidget->GetTopLevelWidget();
NSWindow* rootWindow =
static_cast<NSWindow*>(rootWidget->GetNativeData(NS_NATIVE_WINDOW));
NSView* rootView =
static_cast<NSView*>(rootWidget->GetNativeData(NS_NATIVE_WIDGET));
if (!rootWindow || !rootView) {
return rect;
}
GeckoRectToNSRect(r, rect);
rect = [rootView convertRect:rect toView:nil];
rect.origin = [rootWindow convertBaseToScreen:rect.origin];
#if DEBUG_IME_HANDLER
NSLog(@" result rect (x,y,w,h) = %f, %f, %f, %f",
rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
#endif
return rect;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakeRect(0.0, 0.0, 0.0, 0.0));
}
NSUInteger
nsCocoaIMEHandler::CharacterIndexForPoint(NSPoint& aPoint)
{
#if DEBUG_IME
NSLog(@"****in CharacterIndexForPoint");
#endif
// To implement this, we'd have to grovel in text frames looking at text
// offsets.
return 0;
}
NSArray*
nsCocoaIMEHandler::GetValidAttributesForMarkedText()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
#if DEBUG_IME
NSLog(@"****in GetValidAttributesForMarkedText");
#endif
//return [NSArray arrayWithObjects:NSUnderlineStyleAttributeName,
// NSMarkedClauseSegmentAttributeName,
// NSTextInputReplacementRangeAttributeName,
// nil];
// empty array; we don't support any attributes right now
return [NSArray array];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
#pragma mark -