Bug 492233 [IMM32] Reimplement IME mouse handling r=VYV03354+roc, sr=roc

This commit is contained in:
Masayuki Nakano 2009-05-15 09:46:24 +09:00
parent 5064fd3c08
commit 54e13d1b23
11 changed files with 277 additions and 147 deletions

View File

@ -58,6 +58,7 @@
#include "nsISelectionController.h"
#include "nsISelectionPrivate.h"
#include "nsContentUtils.h"
#include "nsLayoutUtils.h"
#include "nsISelection2.h"
#include "nsIMEStateManager.h"
@ -730,6 +731,46 @@ nsContentEventHandler::OnQuerySelectionAsTransferable(nsQueryContentEvent* aEven
return NS_OK;
}
nsresult
nsContentEventHandler::OnQueryCharacterAtPoint(nsQueryContentEvent* aEvent)
{
nsresult rv = Init(aEvent);
if (NS_FAILED(rv))
return rv;
nsIFrame* rootFrame = mPresShell->GetRootFrame();
nsPoint ptInRoot =
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, rootFrame);
nsIFrame* targetFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, ptInRoot);
if (!targetFrame || targetFrame->GetType() != nsGkAtoms::textFrame) {
// there is no character at the point.
aEvent->mReply.mOffset = nsQueryContentEvent::NOT_FOUND;
aEvent->mSucceeded = PR_TRUE;
return NS_OK;
}
nsPoint ptInTarget = ptInRoot - targetFrame->GetOffsetTo(rootFrame);
nsTextFrame* textframe = static_cast<nsTextFrame*>(targetFrame);
nsIFrame::ContentOffsets offsets =
textframe->GetCharacterOffsetAtFramePoint(ptInTarget);
NS_ENSURE_TRUE(offsets.content, NS_ERROR_FAILURE);
PRUint32 nativeOffset;
rv = GetFlatTextOffsetOfRange(mRootContent, offsets.content, offsets.offset,
&nativeOffset);
NS_ENSURE_SUCCESS(rv, rv);
nsQueryContentEvent textRect(PR_TRUE, NS_QUERY_TEXT_RECT, aEvent->widget);
textRect.InitForQueryTextRect(nativeOffset, 1);
rv = OnQueryTextRect(&textRect);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(textRect.mSucceeded, NS_ERROR_FAILURE);
// currently, we don't need to get the actual text.
aEvent->mReply.mOffset = nativeOffset;
aEvent->mReply.mRect = textRect.mReply.mRect;
aEvent->mSucceeded = PR_TRUE;
return NS_OK;
}
nsresult
nsContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
nsINode* aNode,

View File

@ -81,6 +81,8 @@ public:
nsresult OnQueryContentState(nsQueryContentEvent* aEvent);
// NS_QUERY_SELECTION_AS_TRANSFERABLE event handler
nsresult OnQuerySelectionAsTransferable(nsQueryContentEvent* aEvent);
// NS_QUERY_CHARACTER_AT_POINT event handler
nsresult OnQueryCharacterAtPoint(nsQueryContentEvent* aEvent);
// NS_SELECTION_* event
nsresult OnSelectionEvent(nsSelectionEvent* aEvent);

View File

@ -1758,6 +1758,12 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
handler.OnQuerySelectionAsTransferable(static_cast<nsQueryContentEvent*>(aEvent));
}
break;
case NS_QUERY_CHARACTER_AT_POINT:
{
nsContentEventHandler handler(mPresContext);
handler.OnQueryCharacterAtPoint(static_cast<nsQueryContentEvent*>(aEvent));
}
break;
case NS_SELECTION_SET:
{
nsContentEventHandler handler(mPresContext);

View File

@ -630,7 +630,8 @@ nsLayoutUtils::GetEventCoordinatesRelativeTo(const nsEvent* aEvent, nsIFrame* aF
if (!aEvent || (aEvent->eventStructType != NS_MOUSE_EVENT &&
aEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
aEvent->eventStructType != NS_DRAG_EVENT &&
aEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT))
aEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT &&
aEvent->eventStructType != NS_QUERY_CONTENT_EVENT))
return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
const nsGUIEvent* GUIEvent = static_cast<const nsGUIEvent*>(aEvent);

View File

@ -153,7 +153,8 @@ public:
#endif
virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint);
ContentOffsets GetCharacterOffsetAtFramePoint(const nsPoint &aPoint);
NS_IMETHOD SetSelected(nsPresContext* aPresContext,
nsIDOMRange *aRange,
PRBool aSelected,
@ -448,6 +449,9 @@ protected:
nsRect& aRect);
PRBool IsFloatingFirstLetterChild();
ContentOffsets GetCharacterOffsetAtFramePointInternal(const nsPoint &aPoint,
PRBool aForInsertionPoint);
};
#endif

View File

@ -4812,7 +4812,21 @@ CountCharsFit(gfxTextRun* aTextRun, PRUint32 aStart, PRUint32 aLength,
}
nsIFrame::ContentOffsets
nsTextFrame::CalcContentOffsetsFromFramePoint(nsPoint aPoint) {
nsTextFrame::CalcContentOffsetsFromFramePoint(nsPoint aPoint)
{
return GetCharacterOffsetAtFramePointInternal(aPoint, PR_TRUE);
}
nsIFrame::ContentOffsets
nsTextFrame::GetCharacterOffsetAtFramePoint(const nsPoint &aPoint)
{
return GetCharacterOffsetAtFramePointInternal(aPoint, PR_FALSE);
}
nsIFrame::ContentOffsets
nsTextFrame::GetCharacterOffsetAtFramePointInternal(const nsPoint &aPoint,
PRBool aForInsertionPoint)
{
ContentOffsets offsets;
gfxSkipCharsIterator iter = EnsureTextRun();
@ -4844,7 +4858,7 @@ nsTextFrame::CalcContentOffsetsFromFramePoint(nsPoint aPoint) {
mTextRun->GetAdvanceWidth(extraCluster.GetSkippedOffset(),
GetSkippedDistance(extraCluster, extraClusterLastChar) + 1,
&provider);
selectedOffset = width <= fitWidth + charWidth/2
selectedOffset = !aForInsertionPoint || width <= fitWidth + charWidth/2
? extraCluster.GetOriginalOffset()
: extraClusterLastChar.GetOriginalOffset() + 1;
} else {

View File

@ -362,12 +362,15 @@ class nsHashKey;
#define NS_QUERY_TEXT_RECT (NS_QUERY_CONTENT_EVENT_START + 4)
// Query for the bounding rect of the current focused frame. Result is relative
// to top level widget coordinates
#define NS_QUERY_EDITOR_RECT (NS_QUERY_CONTENT_EVENT_START + 5)
#define NS_QUERY_EDITOR_RECT (NS_QUERY_CONTENT_EVENT_START + 5)
// Query for the current state of the content. The particular members of
// mReply that are set for each query content event will be valid on success.
#define NS_QUERY_CONTENT_STATE (NS_QUERY_CONTENT_EVENT_START + 6)
#define NS_QUERY_CONTENT_STATE (NS_QUERY_CONTENT_EVENT_START + 6)
// Query for the selection in the form of a nsITransferable.
#define NS_QUERY_SELECTION_AS_TRANSFERABLE (NS_QUERY_CONTENT_EVENT_START + 7)
// Query for character at a point. This returns the character offset and its
// rect. The point is specified by nsEvent::refPoint.
#define NS_QUERY_CHARACTER_AT_POINT (NS_QUERY_CONTENT_EVENT_START + 8)
// Video events
#ifdef MOZ_MEDIA
@ -1124,6 +1127,10 @@ public:
// used by NS_QUERY_SELECTION_AS_TRANSFERABLE
nsCOMPtr<nsITransferable> mTransferable;
} mReply;
enum {
NOT_FOUND = PR_UINT32_MAX
};
};
class nsSelectionEvent : public nsGUIEvent
@ -1381,7 +1388,10 @@ enum nsDragDropEventStatus {
((evnt)->message == NS_QUERY_TEXT_CONTENT) || \
((evnt)->message == NS_QUERY_CARET_RECT) || \
((evnt)->message == NS_QUERY_TEXT_RECT) || \
((evnt)->message == NS_QUERY_EDITOR_RECT))
((evnt)->message == NS_QUERY_EDITOR_RECT) || \
((evnt)->message == NS_QUERY_CONTENT_STATE) || \
((evnt)->message == NS_QUERY_SELECTION_AS_TRANSFERABLE) || \
((evnt)->message == NS_QUERY_CHARACTER_AT_POINT))
#define NS_IS_SELECTION_EVENT(evnt) \
(((evnt)->message == NS_SELECTION_SET))

View File

@ -205,7 +205,7 @@ nsIMM32Handler::GetKeyboardCodePage()
#define NO_IME_CARET -1
nsIMM32Handler::nsIMM32Handler() :
mCursorPosition(NO_IME_CARET), mIsComposing(PR_FALSE),
mCursorPosition(NO_IME_CARET), mCompositionStart(0), mIsComposing(PR_FALSE),
mNativeCaretIsCreated(PR_FALSE)
{
PR_LOG(gIMM32Log, PR_LOG_ALWAYS, ("IMM32: nsIMM32Handler is created\n"));
@ -645,42 +645,29 @@ nsIMM32Handler::HandleStartComposition(nsWindow* aWindow,
NS_PRECONDITION(!aWindow->PluginHasFocus(),
"HandleStartComposition should not be called when a plug-in has focus");
nsQueryContentEvent selection(PR_TRUE, NS_QUERY_SELECTED_TEXT, aWindow);
aWindow->InitEvent(selection, &nsIntPoint(0, 0));
aWindow->DispatchWindowEvent(&selection);
if (!selection.mSucceeded) {
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
("IMM32: HandleStartComposition, FAILED (NS_QUERY_SELECTED_TEXT)\n"));
return;
}
mCompositionStart = selection.mReply.mOffset;
nsCompositionEvent event(PR_TRUE, NS_COMPOSITION_START, aWindow);
nsIntPoint point(0, 0);
aWindow->InitEvent(event, &point);
aWindow->DispatchWindowEvent(&event);
//
// Post process event
//
SetIMERelatedWindowsPos(aWindow, aIMEContext);
mIsComposing = PR_TRUE;
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
("IMM32: HandleStartComposition, START composition\n"));
if (event.theReply.mCursorPosition.width <= 0 &&
event.theReply.mCursorPosition.height <= 0) {
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
("IMM32: HandleStartComposition, mCursorPosition is empty\n"));
// for some reason we don't know yet, theReply may contain invalid result
// need more debugging in nsCaret to find out the reason
// the best we can do now is to ignore the invalid result
return;
}
nsIntRect cursorPosition;
ResolveIMECaretPos(event.theReply.mReferenceWidget,
event.theReply.mCursorPosition, aWindow, cursorPosition);
#ifdef ENABLE_IME_MOUSE_HANDLING
memset(mCompCharPos, -1, sizeof(RECT) * IME_MAX_CHAR_POS);
mCompCharPos[0].left = cursorPosition.x;
mCompCharPos[0].top = cursorPosition.y;
mCompCharPos[0].bottom = cursorPosition.YMost();
#endif // ENABLE_IME_MOUSE_HANDLING
("IMM32: HandleStartComposition, START composition, mCompositionStart=%ld\n",
mCompositionStart));
}
PRBool
@ -1126,45 +1113,7 @@ nsIMM32Handler::DispatchTextEvent(nsWindow* aWindow,
aWindow->DispatchWindowEvent(&event);
//
// Post process event
//
SetIMERelatedWindowsPos(aWindow, aIMEContext);
if (event.theReply.mCursorPosition.width <= 0 &&
event.theReply.mCursorPosition.height <= 0) {
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
("IMM32: DispatchTextEvent, mCursorPosition is empty\n"));
// for some reason we don't know yet, theReply may contain invalid result
// need more debugging in nsCaret to find out the reason
// the best we can do now is to ignore the invalid result
return;
}
nsIntRect cursorPosition;
ResolveIMECaretPos(event.theReply.mReferenceWidget,
event.theReply.mCursorPosition, aWindow, cursorPosition);
#ifdef ENABLE_IME_MOUSE_HANDLING
if (mCursorPosition <= 0 || mCursorPosition >= IME_MAX_CHAR_POS) {
return;
}
// Record previous composing char position
// The cursor is always on the right char before it, but not necessarily on
// the left of next char, as what happens in wrapping.
mCompCharPos[mCursorPosition-1].right = cursorPosition.x;
mCompCharPos[mCursorPosition-1].top = cursorPosition.y;
mCompCharPos[mCursorPosition-1].bottom = cursorPosition.YMost();
if (mCompCharPos[mCursorPosition-1].top != cursorPosition.y) {
// wrapping, invalidate left position
mCompCharPos[mCursorPosition-1].left = -1;
}
mCompCharPos[mCursorPosition].left = cursorPosition.x;
mCompCharPos[mCursorPosition].top = cursorPosition.y;
mCompCharPos[mCursorPosition].bottom = cursorPosition.YMost();
#endif // ENABLE_IME_MOUSE_HANDLING
}
void
@ -1475,10 +1424,6 @@ nsIMM32Handler::ResolveIMECaretPos(nsIWidget* aReferenceWidget,
#ifdef ENABLE_IME_MOUSE_HANDLING
#define PT_IN_RECT(pt, rc) \
((pt).x>(rc).left && (pt).x <(rc).right && \
(pt).y>(rc).top && (pt).y<(rc).bottom)
PRBool
nsIMM32Handler::OnMouseEvent(nsWindow* aWindow, LPARAM lParam, int aAction)
{
@ -1486,38 +1431,37 @@ nsIMM32Handler::OnMouseEvent(nsWindow* aWindow, LPARAM lParam, int aAction)
return PR_FALSE;
}
POINT ptPos;
ptPos.x = (short)LOWORD(lParam);
ptPos.y = (short)HIWORD(lParam);
if (!IMECompositionHitTest(ptPos)) {
nsIntPoint cursor(LOWORD(lParam), HIWORD(lParam));
nsQueryContentEvent charAtPt(PR_TRUE, NS_QUERY_CHARACTER_AT_POINT, aWindow);
aWindow->InitEvent(charAtPt, &cursor);
aWindow->DispatchWindowEvent(&charAtPt);
if (!charAtPt.mSucceeded ||
charAtPt.mReply.mOffset == nsQueryContentEvent::NOT_FOUND ||
charAtPt.mReply.mOffset < mCompositionStart ||
charAtPt.mReply.mOffset >
mCompositionStart + mCompositionString.Length()) {
return PR_FALSE;
}
int positioning = 0;
int offset = 0;
// calcurate positioning and offset
// char : JCH1|JCH2|JCH3
// offset: 0011 1122 2233
// positioning: 2301 2301 2301
nsIntRect cursorInTopLevel;
ResolveIMECaretPos(aWindow, nsIntRect(cursor, nsIntSize(0, 0)),
aWindow->GetTopLevelWindow(PR_FALSE), cursorInTopLevel);
PRInt32 cursorXInChar = cursorInTopLevel.x - charAtPt.mReply.mRect.x;
int positioning = cursorXInChar * 4 / charAtPt.mReply.mRect.width;
positioning = (positioning + 2) % 4;
// Note: hitText has been done, so no check of mCompCharPos
// and composing char maximum limit is necessary.
PRUint32 len = mCompositionString.Length();
PRUint32 i = 0;
for (i = 0; i < len; ++i) {
if (PT_IN_RECT(ptPos, mCompCharPos[i]))
break;
}
offset = i;
if (ptPos.x - mCompCharPos[i].left > mCompCharPos[i].right - ptPos.x) {
int offset = charAtPt.mReply.mOffset - mCompositionStart;
if (positioning < 2) {
offset++;
}
positioning = (ptPos.x - mCompCharPos[i].left) * 4 /
(mCompCharPos[i].right - mCompCharPos[i].left);
positioning = (positioning + 2) % 4;
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
("IMM32: OnMouseEvent, x,y=%ld,%ld, offset=%ld, positioning=%ld\n",
cursor.x, cursor.y, offset, positioning));
// send MS_MSIME_MOUSE message to default IME window.
HWND imeWnd = ::ImmGetDefaultIMEWnd(aWindow->GetWindowHandle());
@ -1527,45 +1471,4 @@ nsIMM32Handler::OnMouseEvent(nsWindow* aWindow, LPARAM lParam, int aAction)
(LPARAM) IMEContext.get()) == 1;
}
//The coordinate is relative to the upper-left corner of the client area.
PRBool
nsIMM32Handler::IMECompositionHitTest(const POINT& aPos)
{
// figure out how many char in composing string,
// but keep it below the limit we can handle
PRInt32 len = mCompositionString.Length();
if (len > IME_MAX_CHAR_POS)
len = IME_MAX_CHAR_POS;
PRInt32 i;
PRInt32 aveWidth = 0;
// found per char width
for (i = 0; i < len; i++) {
if (mCompCharPos[i].left >= 0 && mCompCharPos[i].right > 0) {
aveWidth = mCompCharPos[i].right - mCompCharPos[i].left;
break;
}
}
// validate each rect and test
for (i = 0; i < len; i++) {
if (mCompCharPos[i].left < 0) {
if (i != 0 && mCompCharPos[i-1].top == mCompCharPos[i].top)
mCompCharPos[i].left = mCompCharPos[i-1].right;
else
mCompCharPos[i].left = mCompCharPos[i].right - aveWidth;
}
if (mCompCharPos[i].right < 0)
mCompCharPos[i].right = mCompCharPos[i].left + aveWidth;
if (mCompCharPos[i].top < 0) {
mCompCharPos[i].top = mCompCharPos[i-1].top;
mCompCharPos[i].bottom = mCompCharPos[i-1].bottom;
}
if (PT_IN_RECT(aPos, mCompCharPos[i])) {
return PR_TRUE;
}
}
return PR_FALSE;
}
#endif // ENABLE_IME_MOUSE_HANDLING

View File

@ -208,6 +208,7 @@ protected:
nsTArray<PRUint8> mAttributeArray;
PRInt32 mCursorPosition;
PRUint32 mCompositionStart;
PRPackedBool mIsComposing;
PRPackedBool mNativeCaretIsCreated;
@ -221,15 +222,7 @@ protected:
#endif // #ifndef WINCE
#ifdef ENABLE_IME_MOUSE_HANDLING
#define IME_MAX_CHAR_POS 64
// For describing composing frame
// XXX mnakano - We should remove this, because its value may be wrong in
// some cases, and we should query it when it is needed.
RECT mCompCharPos[IME_MAX_CHAR_POS];
PRBool OnMouseEvent(nsWindow* aWindow, LPARAM lParam, int aAction);
PRBool IMECompositionHitTest(const POINT& aPos);
#endif // ENABLE_IME_MOUSE_HANDLING
};

View File

@ -169,7 +169,8 @@ private:
//-------------------------------------------------------------------------
//
// from http://msdn.microsoft.com/library/en-us/dnime/html/msime.asp
// from http://download.microsoft.com/download/6/0/9/60908e9e-d2c1-47db-98f6-216af76a235f/msime.h
// The document for this has been removed from MSDN...
//
//-------------------------------------------------------------------------

View File

@ -88,6 +88,7 @@ class nsAFlatCString;
#include "nsISelectionController.h"
#include "nsIViewManager.h"
#include "nsTArray.h"
#include "nsGUIEvent.h"
#ifndef MOZILLA_INTERNAL_API
#undef nsString_h___
@ -129,6 +130,7 @@ protected:
PRBool TestExtents(void);
PRBool TestComposition(void);
PRBool TestNotification(void);
PRBool TestContentEvents(void);
PRBool TestApp::TestSelectionInternal(char* aTestName,
LONG aStart,
@ -1642,6 +1644,10 @@ TestApp::OnStateChange(nsIWebProgress *aWebProgress,
NS_ASSERTION(aStateFlags & nsIWebProgressListener::STATE_IS_WINDOW &&
aStateFlags & nsIWebProgressListener::STATE_STOP, "wrong state");
if (NS_SUCCEEDED(Init())) {
printf("Testing content events...\n");
if (TestContentEvents())
passed("TestContentEvents");
if (RunTest(&TestApp::TestFocus, PR_FALSE))
passed("TestFocus");
@ -2704,6 +2710,155 @@ TestApp::TestNotification(void)
return PR_TRUE;
}
PRBool
TestApp::TestContentEvents(void)
{
mTestString = NS_LITERAL_STRING(
"This is a test of the\r\nContent Events");
// 0123456789012345678901 2 34567890123456
// 0 1 2 3
mTextArea->SetValue(mTestString);
mTextArea->Focus();
nsCOMPtr<nsIWidget> widget;
nsCOMPtr<nsIDocShell> docShell;
nsresult nsr = mWindow->GetDocShell(getter_AddRefs(docShell));
if (NS_SUCCEEDED(nsr) && docShell) {
nsCOMPtr<nsIPresShell> presShell;
nsr = docShell->GetPresShell(getter_AddRefs(presShell));
if (NS_SUCCEEDED(nsr) && presShell) {
nsCOMPtr<nsIViewManager> viewManager = presShell->GetViewManager();
if (viewManager) {
nsr = viewManager->GetWidget(getter_AddRefs(widget));
}
}
}
if (NS_FAILED(nsr) || !widget) {
fail("TestContentEvents: get nsIWidget");
return PR_FALSE;
}
nsCOMPtr<nsIWidget> topLevel = widget->GetTopLevelWidget(nsnull);
if (!topLevel) {
fail("TestContentEvents: get top level widget");
return PR_FALSE;
}
nsIntRect widgetRect, topLevelRect;
nsr = widget->GetScreenBounds(widgetRect);
if (NS_FAILED(nsr)) {
fail("TestContentEvents: get widget rect");
return PR_FALSE;
}
nsr = topLevel->GetScreenBounds(topLevelRect);
if (NS_FAILED(nsr)) {
fail("TestContentEvents: get top level widget rect");
return PR_FALSE;
}
nsIntPoint widgetOffset = widgetRect.TopLeft() - topLevelRect.TopLeft();
nsEventStatus eventStatus;
PRBool result = PR_TRUE;
const PRUint32 kNone = nsQueryContentEvent::NOT_FOUND;
PRUint32 testingOffset[] = { 0, 10, 20, 23, 36 };
PRUint32 leftSideOffset[] = { kNone, 9, 19, kNone, 35 };
PRUint32 rightSideOffset[] = { 1, 11, kNone, 24, kNone };
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(testingOffset); i++) {
nsQueryContentEvent textRect(PR_TRUE, NS_QUERY_TEXT_RECT, widget);
textRect.InitForQueryTextRect(testingOffset[i], 1);
nsr = widget->DispatchEvent(&textRect, eventStatus);
if (NS_FAILED(nsr) || !textRect.mSucceeded ||
textRect.mReply.mRect.IsEmpty()) {
fail("TestContentEvents: get text rect");
return PR_FALSE;
}
nsIntRect &charRect = textRect.mReply.mRect;
charRect.MoveBy(widgetOffset);
// Note that charRect might be inflated at rounding to pixels!
printf("TestContentEvents: testing... i=%lu, pt={ %ld, %ld }, size={ %ld, %ld }\n",
i, charRect.x, charRect.y, charRect.width, charRect.height);
nsQueryContentEvent charAtPt1(PR_TRUE, NS_QUERY_CHARACTER_AT_POINT, widget);
charAtPt1.refPoint.x = charRect.x + 1;
charAtPt1.refPoint.y = charRect.y + 1;
nsr = widget->DispatchEvent(&charAtPt1, eventStatus);
if (NS_FAILED(nsr) || !charAtPt1.mSucceeded) {
fail(" TestContentEvents: get char at point1");
return PR_FALSE;
}
printf(" NS_QUERY_CHARACTER_AT_POINT: pt={ %ld, %ld }, offset=%lu, rect={ %ld, %ld, %ld, %ld }\n",
charAtPt1.refPoint.x, charAtPt1.refPoint.y,
charAtPt1.mReply.mOffset, charAtPt1.mReply.mRect.x,
charAtPt1.mReply.mRect.y, charAtPt1.mReply.mRect.width,
charAtPt1.mReply.mRect.height);
if (charAtPt1.mReply.mOffset != testingOffset[i]) {
fail(" TestContentEvents: get char at point1 (wrong offset)");
result = PR_FALSE;
} else if (charAtPt1.mReply.mRect != textRect.mReply.mRect) {
fail(" TestContentEvents: get char at point1 (rect mismatch)");
result = PR_FALSE;
}
nsQueryContentEvent charAtPt2(PR_TRUE, NS_QUERY_CHARACTER_AT_POINT, widget);
charAtPt2.refPoint.x = charRect.XMost() - 2;
charAtPt2.refPoint.y = charRect.YMost() - 2;
nsr = widget->DispatchEvent(&charAtPt2, eventStatus);
if (NS_FAILED(nsr) || !charAtPt2.mSucceeded) {
fail(" TestContentEvents: get char at point2");
return PR_FALSE;
}
printf(" NS_QUERY_CHARACTER_AT_POINT: pt={ %ld, %ld }, offset=%lu, rect={ %ld, %ld, %ld, %ld }\n",
charAtPt2.refPoint.x, charAtPt2.refPoint.y,
charAtPt2.mReply.mOffset, charAtPt2.mReply.mRect.x,
charAtPt2.mReply.mRect.y, charAtPt2.mReply.mRect.width,
charAtPt2.mReply.mRect.height);
if (charAtPt2.mReply.mOffset != testingOffset[i]) {
fail(" TestContentEvents: get char at point2 (wrong offset)");
result = PR_FALSE;
} else if (charAtPt2.mReply.mRect != textRect.mReply.mRect) {
fail(" TestContentEvents: get char at point2 (rect mismatch)");
result = PR_FALSE;
}
nsQueryContentEvent charAtPt3(PR_TRUE, NS_QUERY_CHARACTER_AT_POINT, widget);
charAtPt3.refPoint.x = charRect.x - 2;
charAtPt3.refPoint.y = charRect.y + 1;
nsr = widget->DispatchEvent(&charAtPt3, eventStatus);
if (NS_FAILED(nsr) || !charAtPt3.mSucceeded) {
fail(" TestContentEvents: get char at point3");
return PR_FALSE;
}
printf(" NS_QUERY_CHARACTER_AT_POINT: pt={ %ld, %ld }, offset=%lu, rect={ %ld, %ld, %ld, %ld }\n",
charAtPt3.refPoint.x, charAtPt3.refPoint.y,
charAtPt3.mReply.mOffset, charAtPt3.mReply.mRect.x,
charAtPt3.mReply.mRect.y, charAtPt3.mReply.mRect.width,
charAtPt3.mReply.mRect.height);
if (charAtPt3.mReply.mOffset != leftSideOffset[i]) {
fail(" TestContentEvents: get left side char at point (wrong offset)");
result = PR_FALSE;
}
nsQueryContentEvent charAtPt4(PR_TRUE, NS_QUERY_CHARACTER_AT_POINT, widget);
charAtPt4.refPoint.x = charRect.XMost() + 1;
charAtPt4.refPoint.y = charRect.YMost() - 2;
nsr = widget->DispatchEvent(&charAtPt4, eventStatus);
if (NS_FAILED(nsr) || !charAtPt4.mSucceeded) {
fail(" TestContentEvents: get char at point4");
return PR_FALSE;
}
printf(" NS_QUERY_CHARACTER_AT_POINT: pt={ %ld, %ld }, offset=%lu, rect={ %ld, %ld, %ld, %ld }\n",
charAtPt4.refPoint.x, charAtPt4.refPoint.y,
charAtPt4.mReply.mOffset, charAtPt4.mReply.mRect.x,
charAtPt4.mReply.mRect.y, charAtPt4.mReply.mRect.width,
charAtPt4.mReply.mRect.height);
if (charAtPt4.mReply.mOffset != rightSideOffset[i]) {
fail(" TestContentEvents: get right side char at point4 (wrong offset)");
result = PR_FALSE;
}
}
return result;
}
nsresult
TestApp::GetSelCon(nsISelectionController** aSelCon)
{