зеркало из https://github.com/mozilla/gecko-dev.git
Bug 519972 part.4 Move NSTextInput handler to nsCocoaIMEHandler (except insertText) r=smichaud
This commit is contained in:
Родитель
6e4e990426
Коммит
6f6a0d477b
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 -
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче