Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/vcl/source/window/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 12 kB image not shown  

Quelle  dndeventdispatcher.cxx   Sprache: C

 
/* -*- 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 .
 */


#include <dndeventdispatcher.hxx>
#include <dndlistenercontainer.hxx>
#include <sal/log.hxx>

#include <osl/mutex.hxx>
#include <vcl/svapp.hxx>
#include <vcl/settings.hxx>

using namespace ::cppu;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::datatransfer;
using namespace ::com::sun::star::datatransfer::dnd;

DNDEventDispatcher::DNDEventDispatcher( vcl::Window * pTopWindow ):
    m_pTopWindow( pTopWindow ),
    m_pCurrentWindow( nullptr )
{
}

DNDEventDispatcher::~DNDEventDispatcher()
{
    designate_currentwindow(nullptr);
}

vcl::Window* DNDEventDispatcher::findTopLevelWindow(Point& location)
{
    SolarMutexGuard aSolarGuard;

    // find the window that is toplevel for this coordinates
    // because those coordinates come from outside, they must be mirrored if RTL layout is active
    if( AllSettings::GetLayoutRTL() )
        m_pTopWindow->ImplMirrorFramePos( location );
    vcl::Window * pChildWindow = m_pTopWindow->ImplFindWindow( location );

    if( nullptr == pChildWindow )
        pChildWindow = m_pTopWindow;

    while( pChildWindow->ImplGetClientWindow() )
        pChildWindow = pChildWindow->ImplGetClientWindow();

    if( pChildWindow->GetOutDev()->ImplIsAntiparallel() )
    {
        const OutputDevice *pChildWinOutDev = pChildWindow->GetOutDev();
        pChildWinOutDev->ReMirror( location );
    }

    return pChildWindow;
}

IMPL_LINK(DNDEventDispatcher, WindowEventListener, VclWindowEvent&, rEvent, void)
{
    if (rEvent.GetId() == VclEventId::ObjectDying)
    {
        designate_currentwindow(nullptr);
    }
}

void DNDEventDispatcher::designate_currentwindow(vcl::Window *pWindow)
{
    if (m_pCurrentWindow)
        m_pCurrentWindow->RemoveEventListener(LINK(this, DNDEventDispatcher, WindowEventListener));
    m_pCurrentWindow = pWindow;
    if (m_pCurrentWindow)
        m_pCurrentWindow->AddEventListener(LINK(this, DNDEventDispatcher, WindowEventListener));
}

void SAL_CALL DNDEventDispatcher::drop( const DropTargetDropEvent& dtde )
{
    std::scoped_lock aImplGuard( m_aMutex );

    Point location( dtde.LocationX, dtde.LocationY );

    vcl::Window* pChildWindow = findTopLevelWindow(location);

    // handle the case that drop is in another vcl window than the last dragOver
    if( pChildWindow != m_pCurrentWindow.get() )
    {
        // fire dragExit on listeners of previous window
        fireDragExitEvent( m_pCurrentWindow );

        fireDragEnterEvent( pChildWindow, static_cast < XDropTargetDragContext * > (this),
            dtde.DropAction, location, dtde.SourceActions, m_aDataFlavorList );
    }

    // send drop event to the child window
    sal_Int32 nListeners = fireDropEvent( pChildWindow, dtde.Context, dtde.DropAction,
        location, dtde.SourceActions, dtde.Transferable );

    // reject drop if no listeners found
    if( nListeners == 0 ) {
        SAL_WARN( "vcl""rejecting drop due to missing listeners." );
        dtde.Context->rejectDrop();
    }

    // this is a drop -> no further drag overs
    designate_currentwindow(nullptr);
    m_aDataFlavorList.realloc( 0 );
}

void SAL_CALL DNDEventDispatcher::dragEnter( const DropTargetDragEnterEvent& dtdee )
{
    std::scoped_lock aImplGuard( m_aMutex );
    Point location( dtdee.LocationX, dtdee.LocationY );

    vcl::Window * pChildWindow = findTopLevelWindow(location);

    // assume pointer write operation to be atomic
    designate_currentwindow(pChildWindow);
    m_aDataFlavorList = dtdee.SupportedDataFlavors;

    // fire dragEnter on listeners of current window
    sal_Int32 nListeners = fireDragEnterEvent( pChildWindow, dtdee.Context, dtdee.DropAction, location,
        dtdee.SourceActions, dtdee.SupportedDataFlavors );

    // reject drag if no listener found
    if( nListeners == 0 ) {
        SAL_WARN( "vcl""rejecting drag enter due to missing listeners." );
        dtdee.Context->rejectDrag();
    }

}

void SAL_CALL DNDEventDispatcher::dragExit( const DropTargetEvent& /*dte*/ )
{
    std::scoped_lock aImplGuard( m_aMutex );

    fireDragExitEvent( m_pCurrentWindow );

    // reset member values
    designate_currentwindow(nullptr);
    m_aDataFlavorList.realloc( 0 );
}

void SAL_CALL DNDEventDispatcher::dragOver( const DropTargetDragEvent& dtde )
{
    std::scoped_lock aImplGuard( m_aMutex );

    Point location( dtde.LocationX, dtde.LocationY );
    sal_Int32 nListeners;

    vcl::Window * pChildWindow = findTopLevelWindow(location);

    if( pChildWindow != m_pCurrentWindow.get() )
    {
        // fire dragExit on listeners of previous window
        fireDragExitEvent( m_pCurrentWindow );

        // remember new window
        designate_currentwindow(pChildWindow);

        // fire dragEnter on listeners of current window
        nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
            dtde.SourceActions, m_aDataFlavorList );
    }
    else
    {
        // fire dragOver on listeners of current window
        nListeners = fireDragOverEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
            dtde.SourceActions );
    }

    // reject drag if no listener found
    if( nListeners == 0 )
    {
        SAL_WARN( "vcl""rejecting drag over due to missing listeners." );
        dtde.Context->rejectDrag();
    }
}

void SAL_CALL DNDEventDispatcher::dropActionChanged( const DropTargetDragEvent& dtde )
{
    std::scoped_lock aImplGuard( m_aMutex );

    Point location( dtde.LocationX, dtde.LocationY );
    sal_Int32 nListeners;

    vcl::Window* pChildWindow = findTopLevelWindow(location);

    if( pChildWindow != m_pCurrentWindow.get() )
    {
        // fire dragExit on listeners of previous window
        fireDragExitEvent( m_pCurrentWindow );

        // remember new window
        designate_currentwindow(pChildWindow);

        // fire dragEnter on listeners of current window
        nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
            dtde.SourceActions, m_aDataFlavorList );
    }
    else
    {
        // fire dropActionChanged on listeners of current window
        nListeners = fireDropActionChangedEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
            dtde.SourceActions );
    }

    // reject drag if no listener found
    if( nListeners == 0 )
    {
        SAL_WARN( "vcl""rejecting dropActionChanged due to missing listeners." );
        dtde.Context->rejectDrag();
    }
}

void SAL_CALL DNDEventDispatcher::dragGestureRecognized( const DragGestureEvent& dge )
{
    std::scoped_lock aImplGuard( m_aMutex );

    Point origin( dge.DragOriginX, dge.DragOriginY );

    vcl::Window* pChildWindow = findTopLevelWindow(origin);

    fireDragGestureEvent( pChildWindow, dge.DragSource, dge.Event, origin, dge.DragAction );
}

void SAL_CALL DNDEventDispatcher::disposing( const EventObject& )
{
}

void SAL_CALL DNDEventDispatcher::acceptDrag( sal_Int8 /*dropAction*/ )
{
}

void SAL_CALL DNDEventDispatcher::rejectDrag()
{
}

sal_Int32 DNDEventDispatcher::fireDragEnterEvent( vcl::Window *pWindow,
    const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
    const Point& rLocation, const sal_Int8 nSourceActions, const Sequence< DataFlavor >& ;aFlavorList
)
{
    sal_Int32 n = 0;

    if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
    {
        SolarMutexClearableGuard aSolarGuard;

        // query DropTarget from window
        Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();

        if( xDropTarget.is() )
        {
            // retrieve relative mouse position
            Point relLoc = pWindow->ScreenToOutputPixel( rLocation );
            aSolarGuard.clear();

            n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragEnterEvent(
                xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, aFlavorList );
        }
    }

    return n;
}

sal_Int32 DNDEventDispatcher::fireDragOverEvent( vcl::Window *pWindow,
    const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
    const Point& rLocation, const sal_Int8 nSourceActions
)
{
    sal_Int32 n = 0;

    if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
    {
        SolarMutexClearableGuard aSolarGuard;

        // query DropTarget from window
        Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();

        if( xDropTarget.is() )
        {
            // retrieve relative mouse position
            Point relLoc = pWindow->ScreenToOutputPixel( rLocation );
            aSolarGuard.clear();

            n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragOverEvent(
                xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
        }
    }

    return n;
}

sal_Int32 DNDEventDispatcher::fireDragExitEvent( vcl::Window *pWindow )
{
    sal_Int32 n = 0;

    if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
    {
        SolarMutexClearableGuard aGuard;

        // query DropTarget from window
        Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();

        aGuard.clear();

        if( xDropTarget.is() )
            n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragExitEvent();
    }

    return n;
}

sal_Int32 DNDEventDispatcher::fireDropActionChangedEvent( vcl::Window *pWindow,
    const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
    const Point& rLocation, const sal_Int8 nSourceActions
)
{
    sal_Int32 n = 0;

    if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
    {
        SolarMutexClearableGuard aGuard;

        // query DropTarget from window
        Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();

        if( xDropTarget.is() )
        {
            // retrieve relative mouse position
            Point relLoc = pWindow->ScreenToOutputPixel( rLocation );
            aGuard.clear();

            n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropActionChangedEvent(
                xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
        }
    }

    return n;
}

sal_Int32 DNDEventDispatcher::fireDropEvent( vcl::Window *pWindow,
    const Reference< XDropTargetDropContext >& xContext, const sal_Int8 nDropAction, const Point& rLocation,
    const sal_Int8 nSourceActions, const Reference< XTransferable >& xTransferable
)
{
    sal_Int32 n = 0;

    if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
    {
        SolarMutexClearableGuard aGuard;

        // query DropTarget from window
        Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();

        // window may be destroyed in drop event handler
        VclPtr<vcl::Window> xPreventDelete = pWindow;

        if( xDropTarget.is() )
        {
            // retrieve relative mouse position
            Point relLoc = pWindow->ScreenToOutputPixel( rLocation );
            aGuard.clear();

            n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropEvent(
                xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, xTransferable );
        }
    }

    return n;
}

sal_Int32 DNDEventDispatcher::fireDragGestureEvent( vcl::Window *pWindow,
    const Reference< XDragSource >& xSource, const Any& event,
    const Point& rOrigin, const sal_Int8 nDragAction
)
{
    sal_Int32 n = 0;

    if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
    {
        SolarMutexClearableGuard aGuard;

        // query DropTarget from window
        Reference< XDragGestureRecognizer > xDragGestureRecognizer = pWindow->GetDragGestureRecognizer();

        if( xDragGestureRecognizer.is() )
        {
            // retrieve relative mouse position
            Point relLoc = pWindow->ScreenToOutputPixel( rOrigin );
            aGuard.clear();

            n = static_cast < DNDListenerContainer * > ( xDragGestureRecognizer.get() )->fireDragGestureEvent(
                nDragAction, relLoc.X(), relLoc.Y(), xSource, event );
        }
    }

    return n;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=91 H=98 G=94

¤ Dauer der Verarbeitung: 0.0 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.