INTEGRATION: CWS dba23 (1.49.28); FILE MERGED
2005/02/11 12:41:04 oj 1.49.28.4: RESYNC: (1.50-1.51); FILE MERGED 2005/01/26 11:29:41 fs 1.49.28.3: RESYNC: (1.49-1.50); FILE MERGED 2005/01/18 15:44:43 fs 1.49.28.2: #i40647# +mnDrawingOntoParent: prevent recursive calls to certain branches of ::draw 2005/01/13 14:53:50 fs 1.49.28.1: #i40583# notify all events to XMouseListeners asynchronously
This commit is contained in:
parent
7a2c344ab9
commit
44b0b7035b
1 changed files with 168 additions and 33 deletions
|
@ -2,9 +2,9 @@
|
|||
*
|
||||
* $RCSfile: vclxwindow.cxx,v $
|
||||
*
|
||||
* $Revision: 1.51 $
|
||||
* $Revision: 1.52 $
|
||||
*
|
||||
* last change: $Author: rt $ $Date: 2005-01-31 08:58:15 $
|
||||
* last change: $Author: vg $ $Date: 2005-02-17 10:21:18 $
|
||||
*
|
||||
* The Contents of this file are made available subject to the terms of
|
||||
* either of the following licenses
|
||||
|
@ -152,12 +152,127 @@
|
|||
#include <vcl/dockwin.hxx>
|
||||
#endif
|
||||
|
||||
#ifndef COMPHELPER_ASYNCNOTIFICATION_HXX
|
||||
#include <comphelper/asyncnotification.hxx>
|
||||
#endif
|
||||
|
||||
using ::com::sun::star::style::VerticalAlignment;
|
||||
using ::com::sun::star::style::VerticalAlignment_TOP;
|
||||
using ::com::sun::star::style::VerticalAlignment_MIDDLE;
|
||||
using ::com::sun::star::style::VerticalAlignment_BOTTOM;
|
||||
using ::com::sun::star::style::VerticalAlignment_MAKE_FIXED_SIZE;
|
||||
|
||||
//====================================================================
|
||||
//= VCLXWindowImpl
|
||||
//====================================================================
|
||||
#define EVENT_MOUSE_PRESSED 0
|
||||
#define EVENT_MOUSE_RELEASED 1
|
||||
#define EVENT_MOUSE_ENTERED 2
|
||||
#define EVENT_MOUSE_EXITED 3
|
||||
|
||||
class SAL_DLLPRIVATE VCLXWindowImpl : public ::comphelper::IEventProcessor
|
||||
{
|
||||
private:
|
||||
typedef ::comphelper::EventObjectHolder< ::com::sun::star::awt::MouseEvent >
|
||||
MouseEventType;
|
||||
typedef ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >
|
||||
ComponentReference;
|
||||
|
||||
private:
|
||||
VCLXWindow& mrAntiImpl;
|
||||
::vos::IMutex& mrMutex;
|
||||
::comphelper::AsyncEventNotifier* mpAsyncNotifier;
|
||||
|
||||
public:
|
||||
/** ctor
|
||||
@param _pAntiImpl
|
||||
the <type>VCLXWindow</type> instance which the object belongs to. Must
|
||||
live longer then the object just being constructed.
|
||||
*/
|
||||
VCLXWindowImpl( VCLXWindow& _rAntiImpl, ::vos::IMutex& _rMutex );
|
||||
|
||||
/** asynchronously notifies a mousePressed event to the VCLXWindow's XMouseListeners
|
||||
*/
|
||||
void notifyMouseEvent( const ::com::sun::star::awt::MouseEvent& _rMouseEvent, sal_uInt16 _nType );
|
||||
|
||||
/** notifies the object that its VCLXWindow is being disposed
|
||||
*/
|
||||
void disposing();
|
||||
|
||||
protected:
|
||||
// IEventProcessor
|
||||
virtual void processEvent( const ::comphelper::EventDescription& _rEvent );
|
||||
virtual ComponentReference getComponent();
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
VCLXWindowImpl::VCLXWindowImpl( VCLXWindow& _rAntiImpl, ::vos::IMutex& _rMutex )
|
||||
:mrAntiImpl( _rAntiImpl )
|
||||
,mrMutex( _rMutex )
|
||||
,mpAsyncNotifier( NULL )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void VCLXWindowImpl::disposing()
|
||||
{
|
||||
::vos::OGuard aGuard( mrMutex );
|
||||
if ( mpAsyncNotifier )
|
||||
{
|
||||
mpAsyncNotifier->release();
|
||||
mpAsyncNotifier = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void VCLXWindowImpl::notifyMouseEvent( const ::com::sun::star::awt::MouseEvent& _rMouseEvent, sal_uInt16 _nType )
|
||||
{
|
||||
::vos::OGuard aGuard( mrMutex );
|
||||
if ( mrAntiImpl.GetMouseListeners().getLength() )
|
||||
{
|
||||
if ( !mpAsyncNotifier )
|
||||
{
|
||||
mpAsyncNotifier = new ::comphelper::AsyncEventNotifier( this );
|
||||
mpAsyncNotifier->acquire();
|
||||
mpAsyncNotifier->create();
|
||||
}
|
||||
mpAsyncNotifier->addEvent( new MouseEventType( _rMouseEvent, _nType ) );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void VCLXWindowImpl::processEvent( const ::comphelper::EventDescription& _rEvent )
|
||||
{
|
||||
const MouseEventType aEventDescriptor( static_cast< const MouseEventType& >( _rEvent ) );
|
||||
const ::com::sun::star::awt::MouseEvent& rEvent( aEventDescriptor.getEventObject() );
|
||||
switch ( aEventDescriptor.getEventType() )
|
||||
{
|
||||
case EVENT_MOUSE_PRESSED:
|
||||
mrAntiImpl.GetMouseListeners().mousePressed( rEvent );
|
||||
break;
|
||||
case EVENT_MOUSE_RELEASED:
|
||||
mrAntiImpl.GetMouseListeners().mouseReleased( rEvent );
|
||||
break;
|
||||
case EVENT_MOUSE_ENTERED:
|
||||
mrAntiImpl.GetMouseListeners().mouseEntered( rEvent );
|
||||
break;
|
||||
case EVENT_MOUSE_EXITED:
|
||||
mrAntiImpl.GetMouseListeners().mouseExited( rEvent );
|
||||
break;
|
||||
default:
|
||||
DBG_ERROR( "VCLXWindowImpl::processEvent: what kind of event *is* this?" );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
VCLXWindowImpl::ComponentReference VCLXWindowImpl::getComponent()
|
||||
{
|
||||
return static_cast< ::com::sun::star::awt::XWindow* >( &mrAntiImpl );
|
||||
}
|
||||
|
||||
//====================================================================
|
||||
//====================================================================
|
||||
|
||||
// Mit Out-Parameter besser als Rueckgabewert, wegen Ref-Objekt...
|
||||
|
||||
void ImplInitWindowEvent( ::com::sun::star::awt::WindowEvent& rEvent, Window* pWindow )
|
||||
|
@ -229,10 +344,14 @@ VCLXWindow::VCLXWindow()
|
|||
maPaintListeners( *this ),
|
||||
maContainerListeners( *this ),
|
||||
maTopWindowListeners( *this ),
|
||||
mnListenerLockLevel( 0 )
|
||||
mnListenerLockLevel( 0 ),
|
||||
mpImpl( NULL ),
|
||||
mbDrawingOntoParent( false )
|
||||
{
|
||||
DBG_CTOR( VCLXWindow, 0 );
|
||||
|
||||
mpImpl = new VCLXWindowImpl( *this, GetMutex() );
|
||||
|
||||
mbDisposing = sal_False;
|
||||
mbDesignMode = sal_False;
|
||||
mbSynthesizingVCLEvent = sal_False;
|
||||
|
@ -248,6 +367,8 @@ VCLXWindow::~VCLXWindow()
|
|||
GetWindow()->SetWindowPeer( NULL, NULL );
|
||||
GetWindow()->SetAccessible( NULL );
|
||||
}
|
||||
|
||||
DELETEZ( mpImpl );
|
||||
}
|
||||
|
||||
void VCLXWindow::SetWindow( Window* pWindow )
|
||||
|
@ -524,7 +645,7 @@ void VCLXWindow::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
|
|||
aEvent.Source = (::cppu::OWeakObject*)this;
|
||||
ImplInitMouseEvent( aEvent, aMEvt );
|
||||
aEvent.PopupTrigger = sal_True;
|
||||
GetMouseListeners().mousePressed( aEvent );
|
||||
mpImpl->notifyMouseEvent( aEvent, EVENT_MOUSE_PRESSED );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -537,10 +658,10 @@ void VCLXWindow::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
|
|||
aEvent.Source = (::cppu::OWeakObject*)this;
|
||||
ImplInitMouseEvent( aEvent, *pMouseEvt );
|
||||
|
||||
if ( pMouseEvt->IsEnterWindow() )
|
||||
GetMouseListeners().mouseEntered( aEvent );
|
||||
else
|
||||
GetMouseListeners().mouseExited( aEvent );
|
||||
mpImpl->notifyMouseEvent(
|
||||
aEvent,
|
||||
pMouseEvt->IsEnterWindow() ? EVENT_MOUSE_ENTERED : EVENT_MOUSE_EXITED
|
||||
);
|
||||
}
|
||||
|
||||
if ( GetMouseMotionListeners().getLength() && !pMouseEvt->IsEnterWindow() && !pMouseEvt->IsLeaveWindow() )
|
||||
|
@ -564,7 +685,7 @@ void VCLXWindow::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
|
|||
::com::sun::star::awt::MouseEvent aEvent;
|
||||
aEvent.Source = (::cppu::OWeakObject*)this;
|
||||
ImplInitMouseEvent( aEvent, *(MouseEvent*)rVclWindowEvent.GetData() );
|
||||
GetMouseListeners().mousePressed( aEvent );
|
||||
mpImpl->notifyMouseEvent( aEvent, EVENT_MOUSE_PRESSED );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -575,7 +696,7 @@ void VCLXWindow::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
|
|||
::com::sun::star::awt::MouseEvent aEvent;
|
||||
aEvent.Source = (::cppu::OWeakObject*)this;
|
||||
ImplInitMouseEvent( aEvent, *(MouseEvent*)rVclWindowEvent.GetData() );
|
||||
GetMouseListeners().mouseReleased( aEvent );
|
||||
mpImpl->notifyMouseEvent( aEvent, EVENT_MOUSE_RELEASED );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -797,6 +918,8 @@ void VCLXWindow::dispose( ) throw(::com::sun::star::uno::RuntimeException)
|
|||
{
|
||||
mbDisposing = sal_True;
|
||||
|
||||
mpImpl->disposing();
|
||||
|
||||
::com::sun::star::lang::EventObject aObj;
|
||||
aObj.Source = static_cast< ::cppu::OWeakObject* >( this );
|
||||
|
||||
|
@ -1857,32 +1980,44 @@ void VCLXWindow::draw( sal_Int32 nX, sal_Int32 nY ) throw(::com::sun::star::uno:
|
|||
|
||||
if ( pWindow->GetParent() && !pWindow->IsSystemWindow() && ( pWindow->GetParent() == pDev ) )
|
||||
{
|
||||
BOOL bWasVisible = pWindow->IsVisible();
|
||||
Point aOldPos( pWindow->GetPosPixel() );
|
||||
|
||||
if ( bWasVisible && aOldPos == aPos )
|
||||
// #i40647# don't draw here if this is a recursive call
|
||||
// sometimes this is called recursively, because the Update call on the parent
|
||||
// (strangely) triggers another paint. Prevent a stack overflow here
|
||||
// Yes, this is only fixing symptoms for the moment ....
|
||||
// #i40647# / 2005-01-18 / frank.schoenheit@sun.com
|
||||
if ( !mbDrawingOntoParent )
|
||||
{
|
||||
mbDrawingOntoParent = true;
|
||||
|
||||
BOOL bWasVisible = pWindow->IsVisible();
|
||||
Point aOldPos( pWindow->GetPosPixel() );
|
||||
|
||||
if ( bWasVisible && aOldPos == aPos )
|
||||
{
|
||||
pWindow->Update();
|
||||
return;
|
||||
}
|
||||
|
||||
pWindow->SetPosPixel( aPos );
|
||||
|
||||
// Erstmal ein Update auf den Parent, damit nicht beim Update
|
||||
// auf dieses Fenster noch ein Paint vom Parent abgearbeitet wird,
|
||||
// wo dann ggf. dieses Fenster sofort wieder gehidet wird.
|
||||
if( pWindow->GetParent() )
|
||||
pWindow->GetParent()->Update();
|
||||
|
||||
pWindow->Show();
|
||||
pWindow->Update();
|
||||
return;
|
||||
pWindow->SetParentUpdateMode( sal_False );
|
||||
pWindow->Hide();
|
||||
pWindow->SetParentUpdateMode( sal_True );
|
||||
|
||||
pWindow->SetPosPixel( aOldPos );
|
||||
if ( bWasVisible )
|
||||
pWindow->Show( TRUE );
|
||||
|
||||
mbDrawingOntoParent = false;
|
||||
}
|
||||
|
||||
pWindow->SetPosPixel( aPos );
|
||||
|
||||
// Erstmal ein Update auf den Parent, damit nicht beim Update
|
||||
// auf dieses Fenster noch ein Paint vom Parent abgearbeitet wird,
|
||||
// wo dann ggf. dieses Fenster sofort wieder gehidet wird.
|
||||
if( pWindow->GetParent() )
|
||||
pWindow->GetParent()->Update();
|
||||
|
||||
pWindow->Show();
|
||||
pWindow->Update();
|
||||
pWindow->SetParentUpdateMode( sal_False );
|
||||
pWindow->Hide();
|
||||
pWindow->SetParentUpdateMode( sal_True );
|
||||
|
||||
pWindow->SetPosPixel( aOldPos );
|
||||
if ( bWasVisible )
|
||||
pWindow->Show( TRUE );
|
||||
}
|
||||
else if ( pDev )
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue