summaryrefslogtreecommitdiff
path: root/vcl/source
diff options
context:
space:
mode:
authorYohei Yukawa <yukawa@google.com>2013-05-06 14:20:11 +0900
committerTor Lillqvist <tml@iki.fi>2013-05-13 05:14:37 +0000
commit57b5ed51d46fd5673dfe35125ceffa71d39f133d (patch)
treec6dcc9991647a7869451a15ba436cb7443f1dc06 /vcl/source
parentc0417e82174297ace604c68fc577c831929f3573 (diff)
Support IMR_QUERYCHARPOSITION in Writer and Calc.
IMR_QUERYCHARPOSITION is one of optional but fundamental request message sent from IMEs to application. This message is used for retrieving the positional information for each character in a composition text especially when the composition text is drawn by the application. This information is critical for IMEs to align suggestion window with the composition text. Change-Id: I53a344a78688060004cc8bcbbf1127f22a468e20 Reviewed-on: https://gerrit.libreoffice.org/3849 Reviewed-by: Tor Lillqvist <tml@iki.fi> Tested-by: Tor Lillqvist <tml@iki.fi>
Diffstat (limited to 'vcl/source')
-rw-r--r--vcl/source/control/edit.cxx34
-rw-r--r--vcl/source/window/window.cxx24
-rw-r--r--vcl/source/window/winproc.cxx47
3 files changed, 104 insertions, 1 deletions
diff --git a/vcl/source/control/edit.cxx b/vcl/source/control/edit.cxx
index 41722998160a..10b25dc94c6c 100644
--- a/vcl/source/control/edit.cxx
+++ b/vcl/source/control/edit.cxx
@@ -2313,6 +2313,40 @@ void Edit::Command( const CommandEvent& rCEvt )
Selection aSelection( pData->GetStart(), pData->GetEnd() );
SetSelection(aSelection);
}
+ else if ( rCEvt.GetCommand() == COMMAND_QUERYCHARPOSITION )
+ {
+ if (mpIMEInfos && mpIMEInfos->nLen > 0)
+ {
+ OUString aText = ImplGetText();
+ sal_Int32 nDXBuffer[256];
+ sal_Int32* pDXBuffer = NULL;
+ sal_Int32* pDX = nDXBuffer;
+
+ if( !aText.isEmpty() )
+ {
+ if( (size_t) (2*aText.getLength()) > SAL_N_ELEMENTS(nDXBuffer) )
+ {
+ pDXBuffer = new sal_Int32[2*(aText.getLength()+1)];
+ pDX = pDXBuffer;
+ }
+
+ GetCaretPositions( aText, pDX, 0, aText.getLength() );
+ }
+ long nTH = GetTextHeight();
+ Point aPos( mnXOffset, ImplGetTextYPosition() );
+
+ Rectangle* aRects = new Rectangle[ mpIMEInfos->nLen ];
+ for ( int nIndex = 0; nIndex < mpIMEInfos->nLen; ++nIndex )
+ {
+ Rectangle aRect( aPos, Size( 10, nTH ) );
+ aRect.Left() = pDX[2*(nIndex+mpIMEInfos->nPos)] + mnXOffset + ImplGetExtraOffset();
+ aRects[ nIndex ] = aRect;
+ }
+ SetCompositionCharRect( aRects, mpIMEInfos->nLen );
+ delete[] aRects;
+ delete[] pDXBuffer;
+ }
+ }
else
Control::Command( rCEvt );
}
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index fc692d21405e..dfb22398ed4b 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -1372,8 +1372,10 @@ ImplWinData* Window::ImplGetWinData() const
((Window*)this)->mpWindowImpl->mpWinData = new ImplWinData;
mpWindowImpl->mpWinData->mpExtOldText = NULL;
mpWindowImpl->mpWinData->mpExtOldAttrAry = NULL;
- mpWindowImpl->mpWinData->mpCursorRect = 0;
+ mpWindowImpl->mpWinData->mpCursorRect = NULL;
mpWindowImpl->mpWinData->mnCursorExtWidth = 0;
+ mpWindowImpl->mpWinData->mpCompositionCharRects = NULL;
+ mpWindowImpl->mpWinData->mnCompositionCharRects = 0;
mpWindowImpl->mpWinData->mpFocusRect = NULL;
mpWindowImpl->mpWinData->mpTrackRect = NULL;
mpWindowImpl->mpWinData->mnTrackFlags = 0;
@@ -4644,6 +4646,8 @@ Window::~Window()
delete mpWindowImpl->mpWinData->mpExtOldAttrAry;
if ( mpWindowImpl->mpWinData->mpCursorRect )
delete mpWindowImpl->mpWinData->mpCursorRect;
+ if ( mpWindowImpl->mpWinData->mpCompositionCharRects)
+ delete[] mpWindowImpl->mpWinData->mpCompositionCharRects;
if ( mpWindowImpl->mpWinData->mpFocusRect )
delete mpWindowImpl->mpWinData->mpFocusRect;
if ( mpWindowImpl->mpWinData->mpTrackRect )
@@ -5658,6 +5662,24 @@ long Window::GetCursorExtTextInputWidth() const
}
// -----------------------------------------------------------------------
+
+void Window::SetCompositionCharRect( const Rectangle* pRect, long nCompositionLength, sal_Bool bVertical ) {
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplWinData* pWinData = ImplGetWinData();
+ delete[] pWinData->mpCompositionCharRects;
+ pWinData->mbVertical = bVertical;
+ pWinData->mpCompositionCharRects = NULL;
+ pWinData->mnCompositionCharRects = nCompositionLength;
+ if ( pRect && (nCompositionLength > 0) )
+ {
+ pWinData->mpCompositionCharRects = new Rectangle[nCompositionLength];
+ for (long i = 0; i < nCompositionLength; ++i)
+ pWinData->mpCompositionCharRects[i] = pRect[i];
+ }
+}
+
+// -----------------------------------------------------------------------
void Window::SetSettings( const AllSettings& rSettings )
{
SetSettings( rSettings, sal_False );
diff --git a/vcl/source/window/winproc.cxx b/vcl/source/window/winproc.cxx
index 2a296ca8309d..73e5a7a6e800 100644
--- a/vcl/source/window/winproc.cxx
+++ b/vcl/source/window/winproc.cxx
@@ -2348,6 +2348,50 @@ static void ImplHandleStartReconversion( Window *pWindow )
// -----------------------------------------------------------------------
+static void ImplHandleSalQueryCharPosition( Window *pWindow,
+ SalQueryCharPositionEvent *pEvt )
+{
+ pEvt->mbValid = false;
+ pEvt->mbVertical = false;
+ pEvt->mnCursorBoundX = 0;
+ pEvt->mnCursorBoundY = 0;
+ pEvt->mnCursorBoundWidth = 0;
+ pEvt->mnCursorBoundHeight = 0;
+
+ ImplSVData* pSVData = ImplGetSVData();
+ Window* pChild = pSVData->maWinData.mpExtTextInputWin;
+
+ if ( !pChild )
+ pChild = ImplGetKeyInputWindow( pWindow );
+ else
+ {
+ // Test, if the Window is related to the frame
+ if ( !pWindow->ImplIsWindowOrChild( pChild ) )
+ pChild = ImplGetKeyInputWindow( pWindow );
+ }
+
+ if( pChild )
+ {
+ ImplCallCommand( pChild, COMMAND_QUERYCHARPOSITION );
+
+ ImplWinData* pWinData = pChild->ImplGetWinData();
+ if ( pWinData->mpCompositionCharRects && pEvt->mnCharPos < static_cast<sal_uLong>( pWinData->mnCompositionCharRects ) )
+ {
+ const Rectangle& aRect = pWinData->mpCompositionCharRects[ pEvt->mnCharPos ];
+ Rectangle aDeviceRect = pChild->ImplLogicToDevicePixel( aRect );
+ Point aAbsScreenPos = pChild->OutputToAbsoluteScreenPixel( pChild->ScreenToOutputPixel(aDeviceRect.TopLeft()) );
+ pEvt->mnCursorBoundX = aAbsScreenPos.X();
+ pEvt->mnCursorBoundY = aAbsScreenPos.Y();
+ pEvt->mnCursorBoundWidth = aDeviceRect.GetWidth();
+ pEvt->mnCursorBoundHeight = aDeviceRect.GetHeight();
+ pEvt->mbVertical = (pWinData->mbVertical != sal_False);
+ pEvt->mbValid = true;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
long ImplWindowFrameProc( Window* pWindow, SalFrame* /*pFrame*/,
sal_uInt16 nEvent, const void* pEvent )
{
@@ -2659,6 +2703,9 @@ long ImplWindowFrameProc( Window* pWindow, SalFrame* /*pFrame*/,
}
}
break;
+ case SALEVENT_QUERYCHARPOSITION:
+ ImplHandleSalQueryCharPosition( pWindow, (SalQueryCharPositionEvent*)pEvent );
+ break;
#ifdef DBG_UTIL
default:
SAL_WARN( "vcl.layout", "ImplWindowFrameProc(): unknown event (" << nEvent << ")" );