diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index b437e1e2991..4bf8530a682 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -1982,8 +1982,15 @@ nsEditor::QueryComposition(nsTextEventReply* aReply) // XXX_kin: END HACK! HACK! HACK! - result = caretP->GetCaretCoordinates(nsCaret::eIMECoordinates, selection, - &(aReply->mCursorPosition), &(aReply->mCursorIsCollapsed), nsnull); + nsIView *view = nsnull; + result = + caretP->GetCaretCoordinates(nsCaret::eIMECoordinates, + selection, + &(aReply->mCursorPosition), + &(aReply->mCursorIsCollapsed), + &view); + if (NS_SUCCEEDED(result) && view) + aReply->mReferenceWidget = view->GetWidget(); } } return result; diff --git a/editor/libeditor/text/nsPlaintextEditor.cpp b/editor/libeditor/text/nsPlaintextEditor.cpp index 62ca609a736..758cfdc20e5 100644 --- a/editor/libeditor/text/nsPlaintextEditor.cpp +++ b/editor/libeditor/text/nsPlaintextEditor.cpp @@ -1736,12 +1736,15 @@ nsPlaintextEditor::SetCompositionString(const nsAString& aCompositionString, nsI if (caretP) { + nsIView *view = nsnull; result = caretP->GetCaretCoordinates(nsCaret::eIMECoordinates, selection, &(aReply->mCursorPosition), &(aReply->mCursorIsCollapsed), - nsnull); + &view); NS_ASSERTION(NS_SUCCEEDED(result), "cannot get caret position"); + if (NS_SUCCEEDED(result) && view) + aReply->mReferenceWidget = view->GetWidget(); } return result; diff --git a/widget/public/nsGUIEvent.h b/widget/public/nsGUIEvent.h index 4373a378c34..52b38e03aa6 100644 --- a/widget/public/nsGUIEvent.h +++ b/widget/public/nsGUIEvent.h @@ -790,12 +790,13 @@ typedef nsTextRange* nsTextRangeArray; struct nsTextEventReply { nsTextEventReply() - : mCursorIsCollapsed(PR_FALSE) + : mCursorIsCollapsed(PR_FALSE), mReferenceWidget(nsnull) { } nsRect mCursorPosition; PRBool mCursorIsCollapsed; + nsIWidget* mReferenceWidget; }; typedef struct nsTextEventReply nsTextEventReply; diff --git a/widget/src/gtk2/nsWindow.cpp b/widget/src/gtk2/nsWindow.cpp index 4a24cbf0d12..bc40ee00590 100644 --- a/widget/src/gtk2/nsWindow.cpp +++ b/widget/src/gtk2/nsWindow.cpp @@ -5574,20 +5574,7 @@ nsWindow::IMEComposeStart(void) if (NS_UNLIKELY(mIsDestroyed)) return; - gint x1, y1, x2, y2; - GtkWidget *widget = - get_gtk_widget_for_gdk_window(this->mDrawingarea->inner_window); - - gdk_window_get_origin(widget->window, &x1, &y1); - gdk_window_get_origin(this->mDrawingarea->inner_window, &x2, &y2); - - GdkRectangle area; - area.x = compEvent.theReply.mCursorPosition.x + (x2 - x1); - area.y = compEvent.theReply.mCursorPosition.y + (y2 - y1); - area.width = 0; - area.height = compEvent.theReply.mCursorPosition.height; - - gtk_im_context_set_cursor_location(IMEGetContext(), &area); + IMESetCursorPosition(compEvent.theReply); } void @@ -5633,20 +5620,7 @@ nsWindow::IMEComposeText(const PRUnichar *aText, if (NS_UNLIKELY(mIsDestroyed)) return; - gint x1, y1, x2, y2; - GtkWidget *widget = - get_gtk_widget_for_gdk_window(this->mDrawingarea->inner_window); - - gdk_window_get_origin(widget->window, &x1, &y1); - gdk_window_get_origin(this->mDrawingarea->inner_window, &x2, &y2); - - GdkRectangle area; - area.x = textEvent.theReply.mCursorPosition.x + (x2 - x1); - area.y = textEvent.theReply.mCursorPosition.y + (y2 - y1); - area.width = 0; - area.height = textEvent.theReply.mCursorPosition.height; - - gtk_im_context_set_cursor_location(IMEGetContext(), &area); + IMESetCursorPosition(textEvent.theReply); } void @@ -5781,6 +5755,42 @@ nsWindow::IMEFilterEvent(GdkEventKey *aEvent) return retval; } +void +nsWindow::IMESetCursorPosition(const nsTextEventReply& aReply) +{ + nsIWidget *refWidget = aReply.mReferenceWidget; + if (!refWidget) { + NS_WARNING("mReferenceWidget is null"); + refWidget = this; + } + nsWindow* refWindow = static_cast(refWidget); + + nsWindow* ownerWindow = IM_get_owning_window(mDrawingarea); + if (!ownerWindow) { + NS_ERROR("there is no owner"); + return; + } + + // Get the position of the refWindow in screen. + gint refX, refY; + gdk_window_get_origin(refWindow->mDrawingarea->inner_window, + &refX, &refY); + + // Get the position of IM context owner window in screen. + gint ownerX, ownerY; + gdk_window_get_origin(ownerWindow->mDrawingarea->inner_window, + &ownerX, &ownerY); + + // Compute the caret position in the IM owner window. + GdkRectangle area; + area.x = aReply.mCursorPosition.x + refX - ownerX; + area.y = aReply.mCursorPosition.y + refY - ownerY; + area.width = 0; + area.height = aReply.mCursorPosition.height; + + gtk_im_context_set_cursor_location(IMEGetContext(), &area); +} + NS_IMETHODIMP nsWindow::ResetInputState() { diff --git a/widget/src/gtk2/nsWindow.h b/widget/src/gtk2/nsWindow.h index 660379af822..6db1d63ea7e 100644 --- a/widget/src/gtk2/nsWindow.h +++ b/widget/src/gtk2/nsWindow.h @@ -294,6 +294,7 @@ public: nsWindow* IMEComposingWindow(void); void IMECreateContext (void); PRBool IMEFilterEvent (GdkEventKey *aEvent); + void IMESetCursorPosition(const nsTextEventReply& aReply); /* * |mIMEData| has all IME data for the window and its children widgets.