/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
if (pSVData->mpWinData->mpFirstFloat && !pSVData->mpWinData->mpCaptureWin
&& !pSVData->mpWinData->mpFirstFloat->ImplIsFloatPopupModeWindow(pChild))
{ /* * #93895# since floats are system windows, coordinates have * to be converted to float relative for the hittest
*/ bool bHitTestInsideRect = false;
FloatingWindow* pFloat = pSVData->mpWinData->mpFirstFloat->ImplFloatHitTest( pChild, rMousePos, bHitTestInsideRect ); if ( nSVEvent == NotifyEventType::MOUSEMOVE )
{ if ( bMouseLeave ) returntrue;
if (comphelper::LibreOfficeKit::isActive() && AllSettings::GetLayoutRTL()
&& xWindow->GetOutDev() && !xWindow->GetOutDev()->ImplIsAntiparallel())
{
xWindow->GetOutDev()->ReMirror(aMousePos);
nX = aMousePos.X();
nY = aMousePos.Y();
}
// we need a mousemove event, before we get a mousebuttondown or a // mousebuttonup event if ( (nSVEvent == NotifyEventType::MOUSEBUTTONDOWN) || (nSVEvent == NotifyEventType::MOUSEBUTTONUP) )
{ if ( (nSVEvent == NotifyEventType::MOUSEBUTTONUP) && aHelpData.mbExtHelpMode )
Help::EndExtHelp(); if ( aHelpData.mpHelpWin )
{ if( xWindow->ImplGetWindow() == aHelpData.mpHelpWin )
{
ImplDestroyHelpWindow( false ); returntrue; // xWindow is dead now - avoid crash!
} else
ImplDestroyHelpWindow( true );
}
// test this because mouse events are buffered in the remote version // and size may not be in sync if ( !pChild && !bMouseLeave ) returnfalse;
// execute a few tests and catch the message or implement the status if ( pChild )
{ if( pChild->GetOutDev()->ImplIsAntiparallel() )
{ // re-mirror frame pos at pChild const OutputDevice *pChildWinOutDev = pChild->GetOutDev();
pChildWinOutDev->ReMirror( aMousePos );
}
// no mouse messages to disabled windows // #106845# if the window was disabled during capturing we have to pass the mouse events to release capturing if (pSVData->mpWinData->mpCaptureWin.get() != pChild
&& (!pChild->IsEnabled() || !pChild->IsInputEnabled() || pChild->IsInModalMode()))
{
ImplHandleMouseFloatMode( pChild, aMousePos, nCode, nSVEvent, bMouseLeave ); if ( nSVEvent == NotifyEventType::MOUSEMOVE )
{
ImplHandleMouseHelpRequest( pChild, aMousePos ); if( pWinFrameData->mpMouseMoveWin.get() != pChild )
nMode |= MouseEventModifiers::ENTERWINDOW;
}
// Call the hook also, if Window is disabled
if ( nSVEvent == NotifyEventType::MOUSEBUTTONDOWN ) returntrue; else
{ // Set normal MousePointer for disabled windows if ( nSVEvent == NotifyEventType::MOUSEMOVE )
ImplSetMousePointer( pChild );
returnfalse;
}
}
// End ExtTextInput-Mode, if the user click in the same TopLevel Window if (pSVData->mpWinData->mpExtTextInputWin
&& ((nSVEvent == NotifyEventType::MOUSEBUTTONDOWN)
|| (nSVEvent == NotifyEventType::MOUSEBUTTONUP)))
pSVData->mpWinData->mpExtTextInputWin->EndExtTextInput();
}
// determine mouse event data if ( nSVEvent == NotifyEventType::MOUSEMOVE )
{ // check if MouseMove belongs to same window and if the // status did not change if ( pChild )
{
Point aChildMousePos = pChild->ScreenToOutputPixel( aMousePos ); if ( !bMouseLeave &&
(pChild == pWinFrameData->mpMouseMoveWin) &&
(aChildMousePos.X() == pWinFrameData->mnLastMouseWinX) &&
(aChildMousePos.Y() == pWinFrameData->mnLastMouseWinY) &&
(nOldCode == pWinFrameData->mnMouseCode) )
{ // set mouse pointer anew, as it could have changed // due to the mode switch
ImplSetMousePointer( pChild ); returnfalse;
}
// call Start-Drag handler if required // Warning: should be called before Move, as otherwise during // fast mouse movements the applications move to the selection state
vcl::Window* pMouseDownWin = pWinFrameData->mpMouseDownWin; if ( pMouseDownWin )
{ // check for matching StartDrag mode. We only compare // the status of the mouse buttons, such that e. g. Mod1 can // change immediately to the copy mode const MouseSettings& rMSettings = pMouseDownWin->GetSettings().GetMouseSettings(); if ( (nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) ==
(MouseSettings::GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) )
{ if ( !pMouseDownWin->ImplGetFrameData()->mbStartDragCalled )
{
tools::Long nDragW = rMSettings.GetStartDragWidth();
tools::Long nDragH = rMSettings.GetStartDragHeight(); //long nMouseX = nX; //long nMouseY = nY;
tools::Long nMouseX = aMousePos.X(); // #106074# use the possibly re-mirrored coordinates (RTL) ! nX,nY are unmodified !
tools::Long nMouseY = aMousePos.Y(); if ( (((nMouseX-nDragW) > pMouseDownWin->ImplGetFrameData()->mnFirstMouseX) ||
((nMouseX+nDragW) < pMouseDownWin->ImplGetFrameData()->mnFirstMouseX)) ||
(((nMouseY-nDragH) > pMouseDownWin->ImplGetFrameData()->mnFirstMouseY) ||
((nMouseY+nDragH) < pMouseDownWin->ImplGetFrameData()->mnFirstMouseY)) )
{
pMouseDownWin->ImplGetFrameData()->mbStartDragCalled = true;
// Check if drag source provides its own recognizer if( pMouseDownWin->ImplGetFrameData()->mbInternalDragGestureRecognizer )
{ // query DropTarget from child window
rtl::Reference< DNDListenerContainer > xDragGestureRecognizer(
pMouseDownWin->ImplGetWindowImpl()->mxDNDListenerContainer );
if( xDragGestureRecognizer.is() )
{ // retrieve mouse position relative to mouse down window
Point relLoc = pMouseDownWin->ScreenToOutputPixel( Point(
pMouseDownWin->ImplGetFrameData()->mnFirstMouseX,
pMouseDownWin->ImplGetFrameData()->mnFirstMouseY ) );
// create a UNO mouse event out of the available data
css::awt::MouseEvent aMouseEvent( static_cast < css::uno::XInterface * > ( nullptr ), #ifdef MACOSX
nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3), #else
nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2), #endif
nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE),
nMouseX,
nMouseY,
nClicks, false );
SolarMutexReleaser aReleaser;
// FIXME: where do I get Action from ?
css::uno::Reference< css::datatransfer::dnd::XDragSource > xDragSource = pMouseDownWin->GetDragSource();
// bring window into foreground on mouseclick if ( nSVEvent == NotifyEventType::MOUSEBUTTONDOWN )
{ if (!pSVData->mpWinData->mpFirstFloat
&& // totop for floating windows in popup would change the focus and would close them immediately
!(pChild->ImplGetFrameWindow()->GetStyle()
& WB_OWNERDRAWDECORATION)) // ownerdrawdecorated windows must never grab focus
pChild->ToTop(); if ( pChild->isDisposed() ) returntrue;
}
if ( ImplCallPreNotify( aNEvt ) || pChild->isDisposed() )
bRet = true; else
{
bRet = false; if ( nSVEvent == NotifyEventType::MOUSEMOVE )
{ if (pSVData->mpWinData->mpTrackWin)
{
TrackingEvent aTEvt( aMEvt );
pChild->Tracking( aTEvt ); if ( !pChild->isDisposed() )
{ // When ScrollRepeat, we restart the timer if (pSVData->mpWinData->mpTrackTimer
&& (pSVData->mpWinData->mnTrackFlags & StartTrackingFlags::ScrollRepeat))
pSVData->mpWinData->mpTrackTimer->Start();
}
bCallHelpRequest = false;
bRet = true;
} else
{ if( pChild->isDisposed() )
bCallHelpRequest = false; else
{ // if the MouseMove handler changes the help window's visibility // the HelpRequest handler should not be called anymore
vcl::Window* pOldHelpTextWin = ImplGetSVHelpData().mpHelpWin;
pChild->MouseMove( aMEvt ); if ( pOldHelpTextWin != ImplGetSVHelpData().mpHelpWin )
bCallHelpRequest = false;
}
}
} elseif ( nSVEvent == NotifyEventType::MOUSEBUTTONDOWN )
{ if ( pSVData->mpWinData->mpTrackWin )
bRet = true; else
{
pChild->ImplGetWindowImpl()->mbMouseButtonDown = false;
pChild->MouseButtonDown( aMEvt );
}
} else
{ if (pSVData->mpWinData->mpTrackWin)
{
pChild->EndTracking();
bRet = true;
} else
{
pChild->ImplGetWindowImpl()->mbMouseButtonUp = false;
pChild->MouseButtonUp( aMEvt );
}
}
assert(aNEvt.GetWindow() == pChild);
if (!pChild->isDisposed())
pChild->ImplNotifyKeyMouseCommandEventListeners( aNEvt );
}
if (pChild->isDisposed()) returntrue;
if ( nSVEvent == NotifyEventType::MOUSEMOVE )
pChild->ImplGetWindowImpl()->mpFrameData->mbInMouseMove = false;
// determine last input time
pSVData->maAppData.mnLastInputTime = tools::Time::GetSystemTicks();
// #127104# workaround for destroyed windows if( pWindow->ImplGetWindowImpl() == nullptr ) return nullptr;
// find window - is every time the window which has currently the // focus or the last time the focus.
// the first floating window always has the focus, try it, or any parent floating windows, first
vcl::Window* pChild = pSVData->mpWinData->mpFirstFloat; while (pChild)
{ if (pChild->ImplGetWindowImpl())
{ if (pChild->ImplGetWindowImpl()->mbFloatWin)
{ if (static_cast<FloatingWindow *>(pChild)->GrabsFocus()) break;
} elseif (pChild->ImplGetWindowImpl()->mbDockWin)
{
vcl::Window* pParent = pChild->GetWindow(GetWindowType::RealParent); if (pParent && pParent->ImplGetWindowImpl()->mbFloatWin && static_cast<FloatingWindow *>(pParent)->GrabsFocus()) break;
}
}
pChild = pChild->GetParent();
}
// no child - then no input if ( !pChild ) return nullptr;
// We call also KeyInput if we haven't the focus, because on Unix // system this is often the case when a Lookup Choice Window has // the focus - because this windows send the KeyInput directly to // the window without resetting the focus
// no keyinput to disabled windows if ( !pChild->IsEnabled() || !pChild->IsInputEnabled() || pChild->IsInModalMode() ) return nullptr;
// allow application key listeners to remove the key event // but make sure we're not forwarding external KeyEvents, (ie where bForward is false) // because those are coming back from the listener itself and MUST be processed if( bForward )
{
VclEventId nVCLEvent; switch( nSVEvent )
{ case NotifyEventType::KEYINPUT:
nVCLEvent = VclEventId::WindowKeyInput; break; case NotifyEventType::KEYUP:
nVCLEvent = VclEventId::WindowKeyUp; break; default:
nVCLEvent = VclEventId::NONE; break;
}
KeyEvent aKeyEvent(static_cast<sal_Unicode>(nCharCode), aKeyCode, nRepeat); if (nVCLEvent != VclEventId::NONE && Application::HandleKey(nVCLEvent, pWindow, &aKeyEvent)) returntrue;
}
// #i1820# use locale specific decimal separator if (nEvCode == KEY_DECIMAL)
{ // tdf#138932: don't modify the meaning of the key for password box bool bPass = false; if (auto pEdit = dynamic_cast<Edit*>(pChild.get()))
bPass = pEdit->IsPassword(); if (!bPass && Application::GetSettings().GetMiscSettings().GetEnableLocalizedDecimalSep())
{
OUString aSep(pWindow->GetSettings().GetLocaleDataWrapper().getNumDecimalSep());
nCharCode = static_cast<sal_uInt16>(aSep[0]);
}
}
// #105591# send keyinput to parent if we are a floating window and the key was not processed yet if( !bRet && pWindow->ImplGetWindowImpl() && pWindow->ImplGetWindowImpl()->mbFloatWin && pWindow->GetParent() && (pWindow->ImplGetWindowImpl()->mpFrame != pWindow->GetParent()->ImplGetWindowImpl()->mpFrame) )
{
pChild = pWindow->GetParent();
if (comphelper::LibreOfficeKit::isActive())
{
SAL_WARN("vcl", "Failed to get ext text input context"); break;
}
Application::Yield();
}
// If it is the first ExtTextInput call, we inform the information // and allocate the data, which we must store in this mode
ImplWinData* pWinData = pChild->ImplGetWinData(); if ( !pChild->ImplGetWindowImpl()->mbExtTextInput )
{
pChild->ImplGetWindowImpl()->mbExtTextInput = true;
pWinData->mpExtOldText = OUString();
pWinData->mpExtOldAttrAry.reset();
pSVData->mpWinData->mpExtTextInputWin = pChild;
ImplCallCommand( pChild, CommandEventId::StartExtTextInput );
}
// be aware of being recursively called in StartExtTextInput if ( !pChild->ImplGetWindowImpl()->mbExtTextInput ) returnfalse;
// Test for changes bool bOnlyCursor = false;
sal_Int32 nMinLen = std::min( pWinData->mpExtOldText->getLength(), rText.getLength() );
sal_Int32 nDeltaStart = 0; while ( nDeltaStart < nMinLen )
{ if ( (*pWinData->mpExtOldText)[nDeltaStart] != rText[nDeltaStart] ) break;
nDeltaStart++;
} if ( pWinData->mpExtOldAttrAry || pTextAttr )
{ if ( !pWinData->mpExtOldAttrAry || !pTextAttr )
nDeltaStart = 0; else
{
sal_Int32 i = 0; while ( i < nDeltaStart )
{ if ( pWinData->mpExtOldAttrAry[i] != pTextAttr[i] )
{
nDeltaStart = i; break;
}
i++;
}
}
} if ( (nDeltaStart >= nMinLen) &&
(pWinData->mpExtOldText->getLength() == rText.getLength()) )
bOnlyCursor = true;
// Call Event and store the information
CommandExtTextInputData aData( rText, pTextAttr,
nCursorPos, nCursorFlags,
bOnlyCursor );
*pWinData->mpExtOldText = rText;
pWinData->mpExtOldAttrAry.reset(); if ( pTextAttr )
{
pWinData->mpExtOldAttrAry.reset( new ExtTextInputAttr[rText.getLength()] );
memcpy( pWinData->mpExtOldAttrAry.get(), pTextAttr, rText.getLength()*sizeof( ExtTextInputAttr ) );
} return !ImplCallCommand( pChild, CommandEventId::ExtTextInput, &aData );
}
if ( !pChild )
pChild = ImplGetKeyInputWindow( pWindow ); else
{ // Test, if the Window is related to the frame if ( !pWindow->ImplIsWindowOrChild( pChild ) )
pChild = ImplGetKeyInputWindow( pWindow );
}
//If the last event at the same absolute screen position was handled by a //different window then reuse that window if the event occurs within 1/2 a //second, i.e. so scrolling down something like the calc sidebar that contains //widgets that respond to wheel events will continue to send the event to the //scrolling widget in favour of the widget that happens to end up under the //mouse. staticbool shouldReusePreviousMouseWindow(const SalWheelMouseEvent& rPrevEvt, const SalWheelMouseEvent& rEvt)
{ return (rEvt.mnX == rPrevEvt.mnX && rEvt.mnY == rPrevEvt.mnY && rEvt.mnTime-rPrevEvt.mnTime < 500/*ms*/);
}
namespace {
class HandleGestureEventBase
{ protected:
ImplSVData* m_pSVData;
VclPtr<vcl::Window> m_pWindow;
Point m_aMousePos;
while (acceptableWheelScrollTarget(pMouseWindow))
{ if (pMouseWindow->IsEnabled()) break; //try the parent if this one is disabled
pMouseWindow = pMouseWindow->GetParent();
}
bool HandleWheelEvent::HandleEvent(const SalWheelMouseEvent& rEvt)
{ if (!Setup()) returnfalse;
VclPtr<vcl::Window> xMouseWindow = FindTarget();
ImplSVData* pSVData = ImplGetSVData();
// avoid the problem that scrolling via wheel to this point brings a widget // under the mouse that also accepts wheel commands, so stick with the old // widget if the time gap is very small if (shouldReusePreviousMouseWindow(pSVData->mpWinData->maLastWheelEvent, rEvt) &&
acceptableWheelScrollTarget(pSVData->mpWinData->mpLastWheelWindow))
{
xMouseWindow = pSVData->mpWinData->mpLastWheelWindow;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.