bool ImplWindowFrameProc( vcl::Window* _pWindow, SalEvent nEvent, const void* pEvent )
{
DBG_TESTSOLARMUTEX();
// Ensure the window survives during this method.
VclPtr<vcl::Window> pWindow( _pWindow );
bool bRet = false;
// #119709# for some unknown reason it is possible to receive events (in this case key events)
// although the corresponding VCL window must have been destroyed already
// at least ImplGetWindowImpl() was NULL in these cases, so check this here
if( pWindow->ImplGetWindowImpl() == nullptr )
return false;
switch ( nEvent )
{
case SalEvent::MouseMove:
bRet = ImplHandleSalMouseMove( pWindow, static_cast<SalMouseEvent const *>(pEvent) );
break;
case SalEvent::ExternalMouseMove:
{
MouseEvent const * pMouseEvt = static_cast<MouseEvent const *>(pEvent);
SalMouseEvent aSalMouseEvent;
aSalMouseEvent.mnTime = tools::Time::GetSystemTicks();
aSalMouseEvent.mnX = pMouseEvt->GetPosPixel().X();
aSalMouseEvent.mnY = pMouseEvt->GetPosPixel().Y();
aSalMouseEvent.mnButton = 0;
aSalMouseEvent.mnCode = pMouseEvt->GetButtons() | pMouseEvt->GetModifier();
bRet = ImplHandleSalMouseMove( pWindow, &aSalMouseEvent );
}
break;
case SalEvent::MouseLeave:
bRet = ImplHandleSalMouseLeave( pWindow, static_cast<SalMouseEvent const *>(pEvent) );
break;
case SalEvent::MouseButtonDown:
bRet = ImplHandleSalMouseButtonDown( pWindow, static_cast<SalMouseEvent const *>(pEvent) );
break;
case SalEvent::ExternalMouseButtonDown:
{
MouseEvent const * pMouseEvt = static_cast<MouseEvent const *>(pEvent);
SalMouseEvent aSalMouseEvent;
aSalMouseEvent.mnTime = tools::Time::GetSystemTicks();
aSalMouseEvent.mnX = pMouseEvt->GetPosPixel().X();
aSalMouseEvent.mnY = pMouseEvt->GetPosPixel().Y();
aSalMouseEvent.mnButton = pMouseEvt->GetButtons();
aSalMouseEvent.mnCode = pMouseEvt->GetButtons() | pMouseEvt->GetModifier();
bRet = ImplHandleSalMouseButtonDown( pWindow, &aSalMouseEvent );
}
break;
case SalEvent::MouseButtonUp:
bRet = ImplHandleSalMouseButtonUp( pWindow, static_cast<SalMouseEvent const *>(pEvent) );
break;
case SalEvent::ExternalMouseButtonUp:
{
MouseEvent const * pMouseEvt = static_cast<MouseEvent const *>(pEvent);
SalMouseEvent aSalMouseEvent;
aSalMouseEvent.mnTime = tools::Time::GetSystemTicks();
aSalMouseEvent.mnX = pMouseEvt->GetPosPixel().X();
aSalMouseEvent.mnY = pMouseEvt->GetPosPixel().Y();
aSalMouseEvent.mnButton = pMouseEvt->GetButtons();
aSalMouseEvent.mnCode = pMouseEvt->GetButtons() | pMouseEvt->GetModifier();
bRet = ImplHandleSalMouseButtonUp( pWindow, &aSalMouseEvent );
}
break;
case SalEvent::MouseActivate:
bRet = false;
break;
case SalEvent::KeyInput:
{
SalKeyEvent const * pKeyEvt = static_cast<SalKeyEvent const *>(pEvent);
bRet = ImplHandleKey( pWindow, MouseNotifyEvent::KEYINPUT,
pKeyEvt->mnCode, pKeyEvt->mnCharCode, pKeyEvt->mnRepeat, true );
}
break;
case SalEvent::ExternalKeyInput:
{
KeyEvent const * pKeyEvt = static_cast<KeyEvent const *>(pEvent);
bRet = ImplHandleKey( pWindow, MouseNotifyEvent::KEYINPUT,
pKeyEvt->GetKeyCode().GetFullCode(), pKeyEvt->GetCharCode(), pKeyEvt->GetRepeat(), false );
}
break;
case SalEvent::KeyUp:
{
SalKeyEvent const * pKeyEvt = static_cast<SalKeyEvent const *>(pEvent);
bRet = ImplHandleKey( pWindow, MouseNotifyEvent::KEYUP,
pKeyEvt->mnCode, pKeyEvt->mnCharCode, pKeyEvt->mnRepeat, true );
}
break;
case SalEvent::ExternalKeyUp:
{
KeyEvent const * pKeyEvt = static_cast<KeyEvent const *>(pEvent);
bRet = ImplHandleKey( pWindow, MouseNotifyEvent::KEYUP,
pKeyEvt->GetKeyCode().GetFullCode(), pKeyEvt->GetCharCode(), pKeyEvt->GetRepeat(), false );
}
break;
case SalEvent::KeyModChange:
ImplHandleSalKeyMod( pWindow, static_cast<SalKeyModEvent const *>(pEvent) );
break;
case SalEvent::InputLanguageChange:
ImplHandleInputLanguageChange( pWindow );
break;
case SalEvent::MenuActivate:
case SalEvent::MenuDeactivate:
case SalEvent::MenuHighlight:
case SalEvent::MenuCommand:
case SalEvent::MenuButtonCommand:
bRet = ImplHandleMenuEvent( pWindow, const_cast<SalMenuEvent *>(static_cast<SalMenuEvent const *>(pEvent)), nEvent );
break;
case SalEvent::WheelMouse:
bRet = ImplHandleWheelEvent( pWindow, *static_cast<const SalWheelMouseEvent*>(pEvent));
break;
case SalEvent::Paint:
{
SalPaintEvent const * pPaintEvt = static_cast<SalPaintEvent const *>(pEvent);
if( AllSettings::GetLayoutRTL() )
{
SalFrame* pSalFrame = pWindow->ImplGetWindowImpl()->mpFrame;
const_cast<SalPaintEvent *>(pPaintEvt)->mnBoundX = pSalFrame->maGeometry.nWidth-pPaintEvt->mnBoundWidth-pPaintEvt->mnBoundX;
}
tools::Rectangle aBoundRect( Point( pPaintEvt->mnBoundX, pPaintEvt->mnBoundY ),
Size( pPaintEvt->mnBoundWidth, pPaintEvt->mnBoundHeight ) );
ImplHandlePaint( pWindow, aBoundRect, pPaintEvt->mbImmediateUpdate );
}
break;
case SalEvent::Move:
ImplHandleMove( pWindow );
break;
case SalEvent::Resize:
{
long nNewWidth;
long nNewHeight;
pWindow->ImplGetWindowImpl()->mpFrame->GetClientSize( nNewWidth, nNewHeight );
ImplHandleResize( pWindow, nNewWidth, nNewHeight );
}
break;
case SalEvent::MoveResize:
{
SalFrameGeometry g = pWindow->ImplGetWindowImpl()->mpFrame->GetGeometry();
ImplHandleMoveResize( pWindow, g.nWidth, g.nHeight );
}
break;
case SalEvent::ClosePopups:
{
KillOwnPopups( pWindow );
}
break;
case SalEvent::GetFocus:
ImplHandleGetFocus( pWindow );
break;
case SalEvent::LoseFocus:
ImplHandleLoseFocus( pWindow );
break;
case SalEvent::Close:
ImplHandleClose( pWindow );
break;
case SalEvent::Shutdown:
{
static bool bInQueryExit = false;
if( !bInQueryExit )
{
bInQueryExit = true;
if ( GetpApp()->QueryExit() )
{
// end the message loop
Application::Quit();
return false;
}
else
{
bInQueryExit = false;
return true;
}
}
return false;
}
case SalEvent::SettingsChanged:
case SalEvent::PrinterChanged:
case SalEvent::DisplayChanged:
case SalEvent::FontChanged:
ImplHandleSalSettings( nEvent );
break;
case SalEvent::UserEvent:
ImplHandleUserEvent( const_cast<ImplSVEvent *>(static_cast<ImplSVEvent const *>(pEvent)) );
break;
case SalEvent::ExtTextInput:
{
SalExtTextInputEvent const * pEvt = static_cast<SalExtTextInputEvent const *>(pEvent);
bRet = ImplHandleExtTextInput( pWindow,
pEvt->maText, pEvt->mpTextAttr,
pEvt->mnCursorPos, pEvt->mnCursorFlags );
}
break;
case SalEvent::EndExtTextInput:
bRet = ImplHandleEndExtTextInput();
break;
case SalEvent::ExtTextInputPos:
ImplHandleSalExtTextInputPos( pWindow, const_cast<SalExtTextInputPosEvent *>(static_cast<SalExtTextInputPosEvent const *>(pEvent)) );
break;
case SalEvent::InputContextChange:
bRet = ImplHandleInputContextChange( pWindow );
break;
case SalEvent::ShowDialog:
{
ShowDialogId nLOKWindowId = static_cast<ShowDialogId>(reinterpret_cast<sal_IntPtr>(pEvent));
bRet = ImplHandleShowDialog( pWindow, nLOKWindowId );
}
break;
case SalEvent::SurroundingTextRequest:
ImplHandleSalSurroundingTextRequest( pWindow, const_cast<SalSurroundingTextRequestEvent *>(static_cast<SalSurroundingTextRequestEvent const *>(pEvent)) );
break;
case SalEvent::SurroundingTextSelectionChange:
{
SalSurroundingTextSelectionChangeEvent const * pEvt
= static_cast<SalSurroundingTextSelectionChangeEvent const *>(pEvent);
ImplHandleSurroundingTextSelectionChange( pWindow,
pEvt->mnStart,
pEvt->mnEnd );
[[fallthrough]]; // TODO: Fallthrough really intended?
}
case SalEvent::StartReconversion:
ImplHandleStartReconversion( pWindow );
break;
case SalEvent::QueryCharPosition:
ImplHandleSalQueryCharPosition( pWindow, const_cast<SalQueryCharPositionEvent *>(static_cast<SalQueryCharPositionEvent const *>(pEvent)) );
break;
case SalEvent::Swipe:
bRet = ImplHandleSwipe(pWindow, *static_cast<const SalSwipeEvent*>(pEvent));
break;
case SalEvent::LongPress:
bRet = ImplHandleLongPress(pWindow, *static_cast<const SalLongPressEvent*>(pEvent));
break;
case SalEvent::ExternalGesture:
{
auto const * pGestureEvent = static_cast<GestureEvent const *>(pEvent);
SalGestureEvent aSalGestureEvent;
aSalGestureEvent.mfOffset = pGestureEvent->mnOffset;
aSalGestureEvent.mnX = pGestureEvent->mnX;
aSalGestureEvent.mnY = pGestureEvent->mnY;
aSalGestureEvent.meEventType = pGestureEvent->meEventType;
aSalGestureEvent.meOrientation = pGestureEvent->meOrientation;
bRet = ImplHandleGestureEvent(pWindow, aSalGestureEvent);
}
break;
case SalEvent::Gesture:
{
auto const * aSalGestureEvent = static_cast<SalGestureEvent const *>(pEvent);
bRet = ImplHandleGestureEvent(pWindow, *aSalGestureEvent);
}
break;
default:
SAL_WARN( "vcl.layout", "ImplWindowFrameProc(): unknown event (" << static_cast<int>(nEvent) << ")" );
break;
}
return bRet;
}
\vcl\source\window\winproc.cxx
static bool ImplHandleIMECompositionInput( WinSalFrame* pFrame,
HIMC hIMC, LPARAM lParam )
{
bool bDef = true;
// Init Event
SalExtTextInputEvent aEvt;
aEvt.mpTextAttr = nullptr;
aEvt.mnCursorPos = 0;
aEvt.mnCursorFlags = 0;
// If we get a result string, then we handle this input
if ( lParam & GCS_RESULTSTR )
{
bDef = false;
LONG nTextLen = ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, nullptr, 0 ) / sizeof( WCHAR );
if ( nTextLen >= 0 )
{
auto pTextBuf = std::make_unique<WCHAR[]>(nTextLen);
ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, pTextBuf.get(), nTextLen*sizeof( WCHAR ) );
aEvt.maText = OUString( o3tl::toU(pTextBuf.get()), static_cast<sal_Int32>(nTextLen) );
}
aEvt.mnCursorPos = aEvt.maText.getLength();
pFrame->CallCallback( SalEvent::ExtTextInput, &aEvt );
pFrame->CallCallback( SalEvent::EndExtTextInput, nullptr );
ImplUpdateIMECursorPos( pFrame, hIMC );
}
// If the IME doesn't support OnSpot input, then there is nothing to do
if ( !pFrame->mbAtCursorIME )
return !bDef;
// If we get new Composition data, then we handle this new input
if ( (lParam & (GCS_COMPSTR | GCS_COMPATTR)) ||
((lParam & GCS_CURSORPOS) && !(lParam & GCS_RESULTSTR)) )
{
bDef = false;
ExtTextInputAttr* pSalAttrAry = nullptr;
LONG nTextLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, nullptr, 0 ) / sizeof( WCHAR );
if ( nTextLen > 0 )
{
{
auto pTextBuf = std::make_unique<WCHAR[]>(nTextLen);
ImmGetCompositionStringW( hIMC, GCS_COMPSTR, pTextBuf.get(), nTextLen*sizeof( WCHAR ) );
aEvt.maText = OUString( o3tl::toU(pTextBuf.get()), static_cast<sal_Int32>(nTextLen) );
}
std::unique_ptr<BYTE[]> pAttrBuf;
LONG nAttrLen = ImmGetCompositionStringW( hIMC, GCS_COMPATTR, nullptr, 0 );
if ( nAttrLen > 0 )
{
pAttrBuf.reset(new BYTE[nAttrLen]);
ImmGetCompositionStringW( hIMC, GCS_COMPATTR, pAttrBuf.get(), nAttrLen );
}
if ( pAttrBuf )
{
sal_Int32 nTextLen2 = aEvt.maText.getLength();
pSalAttrAry = new ExtTextInputAttr[nTextLen2];
memset( pSalAttrAry, 0, nTextLen2*sizeof( sal_uInt16 ) );
for( sal_Int32 i = 0; (i < nTextLen2) && (i < nAttrLen); i++ )
{
BYTE nWinAttr = pAttrBuf.get()[i];
ExtTextInputAttr nSalAttr;
if ( nWinAttr == ATTR_TARGET_CONVERTED )
{
nSalAttr = ExtTextInputAttr::BoldUnderline;
aEvt.mnCursorFlags |= EXTTEXTINPUT_CURSOR_INVISIBLE;
}
else if ( nWinAttr == ATTR_CONVERTED )
nSalAttr = ExtTextInputAttr::DashDotUnderline;
else if ( nWinAttr == ATTR_TARGET_NOTCONVERTED )
nSalAttr = ExtTextInputAttr::Highlight;
else if ( nWinAttr == ATTR_INPUT_ERROR )
nSalAttr = ExtTextInputAttr::RedText | ExtTextInputAttr::DottedUnderline;
else /* ( nWinAttr == ATTR_INPUT ) */
nSalAttr = ExtTextInputAttr::DottedUnderline;
pSalAttrAry[i] = nSalAttr;
}
aEvt.mpTextAttr = pSalAttrAry;
}
}
// Only when we get new composition data, we must send this event
if ( (nTextLen > 0) || !(lParam & GCS_RESULTSTR) )
{
// End the mode, if the last character is deleted
if ( !nTextLen && !pFrame->mbCandidateMode )
{
pFrame->CallCallback( SalEvent::ExtTextInput, &aEvt );
pFrame->CallCallback( SalEvent::EndExtTextInput, nullptr );
}
else
{
// Because Cursor-Position and DeltaStart never updated
// from the korean input engine, we must handle this here
if ( lParam & CS_INSERTCHAR )
{
aEvt.mnCursorPos = nTextLen;
if ( aEvt.mnCursorPos && (lParam & CS_NOMOVECARET) )
aEvt.mnCursorPos--;
}
else
aEvt.mnCursorPos = LOWORD( ImmGetCompositionStringW( hIMC, GCS_CURSORPOS, nullptr, 0 ) );
if ( pFrame->mbCandidateMode )
aEvt.mnCursorFlags |= EXTTEXTINPUT_CURSOR_INVISIBLE;
if ( lParam & CS_NOMOVECARET )
aEvt.mnCursorFlags |= EXTTEXTINPUT_CURSOR_OVERWRITE;
pFrame->CallCallback( SalEvent::ExtTextInput, &aEvt );
}
ImplUpdateIMECursorPos( pFrame, hIMC );
}
if ( pSalAttrAry )
delete [] pSalAttrAry;
}
return !bDef;
}