office-gobmx/vcl/headless/svpinst.cxx

398 lines
10 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/poll.h>
#include <sal/types.h>
#include <vcl/apptypes.hxx>
#include "headless/svpinst.hxx"
#include "headless/svpframe.hxx"
#include "headless/svpdummies.hxx"
#include "headless/svpvd.hxx"
#include "headless/svpbmp.hxx"
#include <salframe.hxx>
#include <svdata.hxx>
#include <generic/gendata.hxx>
#include <basebmp/scanlineformats.hxx>
#include <vcl/solarmutex.hxx>
// FIXME: remove when we re-work the svp mainloop
#include <unx/salunxtime.h>
bool SvpSalInstance::isFrameAlive( const SalFrame* pFrame ) const
{
for( std::list< SalFrame* >::const_iterator it = m_aFrames.begin();
it != m_aFrames.end(); ++it )
{
if( *it == pFrame )
{
return true;
}
}
return false;
}
SvpSalInstance* SvpSalInstance::s_pDefaultInstance = NULL;
SvpSalInstance::SvpSalInstance( SalYieldMutex *pMutex ) :
SalGenericInstance( pMutex )
{
m_aTimeout.tv_sec = 0;
m_aTimeout.tv_usec = 0;
m_nTimeoutMS = 0;
m_pTimeoutFDS[0] = m_pTimeoutFDS[1] = -1;
if (pipe (m_pTimeoutFDS) != -1)
{
// initialize 'wakeup' pipe.
int flags;
// set close-on-exec descriptor flag.
if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFD)) != -1)
{
flags |= FD_CLOEXEC;
fcntl (m_pTimeoutFDS[0], F_SETFD, flags);
}
if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFD)) != -1)
{
flags |= FD_CLOEXEC;
fcntl (m_pTimeoutFDS[1], F_SETFD, flags);
}
// set non-blocking I/O flag.
if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFL)) != -1)
{
flags |= O_NONBLOCK;
fcntl (m_pTimeoutFDS[0], F_SETFL, flags);
}
if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFL)) != -1)
{
flags |= O_NONBLOCK;
fcntl (m_pTimeoutFDS[1], F_SETFL, flags);
}
}
m_aEventGuard = osl_createMutex();
if( s_pDefaultInstance == NULL )
s_pDefaultInstance = this;
}
SvpSalInstance::~SvpSalInstance()
{
if( s_pDefaultInstance == this )
s_pDefaultInstance = NULL;
// close 'wakeup' pipe.
close (m_pTimeoutFDS[0]);
close (m_pTimeoutFDS[1]);
osl_destroyMutex( m_aEventGuard );
}
void SvpSalInstance::PostEvent( const SalFrame* pFrame, void* pData, sal_uInt16 nEvent )
{
if( osl_acquireMutex( m_aEventGuard ) )
{
m_aUserEvents.push_back( SalUserEvent( pFrame, pData, nEvent ) );
osl_releaseMutex( m_aEventGuard );
}
Wakeup();
}
void SvpSalInstance::deregisterFrame( SalFrame* pFrame )
{
m_aFrames.remove( pFrame );
if( osl_acquireMutex( m_aEventGuard ) )
{
// cancel outstanding events for this frame
if( ! m_aUserEvents.empty() )
{
std::list< SalUserEvent >::iterator it = m_aUserEvents.begin();
do
{
if( it->m_pFrame == pFrame )
{
it = m_aUserEvents.erase( it );
}
else
++it;
} while( it != m_aUserEvents.end() );
}
osl_releaseMutex( m_aEventGuard );
}
}
void SvpSalInstance::Wakeup()
{
OSL_VERIFY(write (m_pTimeoutFDS[1], "", 1) == 1);
}
bool SvpSalInstance::CheckTimeout( bool bExecuteTimers )
{
bool bRet = false;
if( m_aTimeout.tv_sec ) // timer is started
{
timeval aTimeOfDay;
gettimeofday( &aTimeOfDay, 0 );
if( aTimeOfDay >= m_aTimeout )
{
bRet = true;
if( bExecuteTimers )
{
// timed out, update timeout
m_aTimeout = aTimeOfDay;
m_aTimeout += m_nTimeoutMS;
// notify
ImplSVData* pSVData = ImplGetSVData();
if( pSVData->mpSalTimer )
pSVData->mpSalTimer->CallCallback();
}
}
}
return bRet;
}
SalFrame* SvpSalInstance::CreateChildFrame( SystemParentData* pParent, sal_uLong nStyle )
{
return new SvpSalFrame( this, NULL, nStyle, false, SVP_DEFAULT_BITMAP_FORMAT, pParent );
}
SalFrame* SvpSalInstance::CreateFrame( SalFrame* pParent, sal_uLong nStyle )
{
return new SvpSalFrame( this, pParent, nStyle, false, SVP_DEFAULT_BITMAP_FORMAT );
}
void SvpSalInstance::DestroyFrame( SalFrame* pFrame )
{
delete pFrame;
}
SalObject* SvpSalInstance::CreateObject( SalFrame*, SystemWindowData*, sal_Bool )
{
return new SvpSalObject();
}
void SvpSalInstance::DestroyObject( SalObject* pObject )
{
delete pObject;
}
SalVirtualDevice* SvpSalInstance::CreateVirtualDevice( SalGraphics*,
long nDX, long nDY,
sal_uInt16 nBitCount, const SystemGraphicsData* )
{
SvpSalVirtualDevice* pNew = new SvpSalVirtualDevice( nBitCount );
pNew->SetSize( nDX, nDY );
return pNew;
}
void SvpSalInstance::DestroyVirtualDevice( SalVirtualDevice* pDevice )
{
delete pDevice;
}
SalTimer* SvpSalInstance::CreateSalTimer()
{
return new SvpSalTimer( this );
}
SalI18NImeStatus* SvpSalInstance::CreateI18NImeStatus()
{
return new SvpImeStatus();
}
SalSystem* SvpSalInstance::CreateSalSystem()
{
return new SvpSalSystem();
}
SalBitmap* SvpSalInstance::CreateSalBitmap()
{
return new SvpSalBitmap();
}
void SvpSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
{
// first, check for already queued events.
// release yield mutex
std::list< SalUserEvent > aEvents;
sal_uLong nAcquireCount = ReleaseYieldMutex();
if( osl_acquireMutex( m_aEventGuard ) )
{
if( ! m_aUserEvents.empty() )
{
if( bHandleAllCurrentEvents )
{
aEvents = m_aUserEvents;
m_aUserEvents.clear();
}
else
{
aEvents.push_back( m_aUserEvents.front() );
m_aUserEvents.pop_front();
}
}
osl_releaseMutex( m_aEventGuard );
}
// acquire yield mutex again
AcquireYieldMutex( nAcquireCount );
bool bEvent = !aEvents.empty();
if( bEvent )
{
for( std::list<SalUserEvent>::const_iterator it = aEvents.begin(); it != aEvents.end(); ++it )
{
if ( isFrameAlive( it->m_pFrame ) )
{
it->m_pFrame->CallCallback( it->m_nEvent, it->m_pData );
if( it->m_nEvent == SALEVENT_RESIZE )
{
// this would be a good time to post a paint
const SvpSalFrame* pSvpFrame = static_cast<const SvpSalFrame*>(it->m_pFrame);
pSvpFrame->PostPaint(false);
}
}
}
}
bEvent = CheckTimeout() || bEvent;
if (bWait && ! bEvent )
{
int nTimeoutMS = 0;
if (m_aTimeout.tv_sec) // Timer is started.
{
timeval Timeout;
// determine remaining timeout.
gettimeofday (&Timeout, 0);
nTimeoutMS = m_aTimeout.tv_sec*1000 + m_aTimeout.tv_usec/1000
- Timeout.tv_sec*1000 - Timeout.tv_usec/1000;
if( nTimeoutMS < 0 )
nTimeoutMS = 0;
}
else
nTimeoutMS = -1; // wait until something happens
DoReleaseYield(nTimeoutMS);
}
}
void SvpSalInstance::DoReleaseYield( int nTimeoutMS )
{
// poll
struct pollfd aPoll;
aPoll.fd = m_pTimeoutFDS[0];
aPoll.events = POLLIN;
aPoll.revents = 0;
// release yield mutex
sal_uLong nAcquireCount = ReleaseYieldMutex();
poll( &aPoll, 1, nTimeoutMS );
// acquire yield mutex again
AcquireYieldMutex( nAcquireCount );
// clean up pipe
if( (aPoll.revents & POLLIN) != 0 )
{
int buffer;
while (read (m_pTimeoutFDS[0], &buffer, sizeof(buffer)) > 0)
continue;
}
}
bool SvpSalInstance::AnyInput( sal_uInt16 nType )
{
if( (nType & VCL_INPUT_TIMER) != 0 )
return CheckTimeout( false );
return false;
}
SalSession* SvpSalInstance::CreateSalSession()
{
return NULL;
}
void* SvpSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes )
{
rReturnedBytes = 1;
rReturnedType = AsciiCString;
return const_cast<char*>("");
}
// ---------------
// - SalTimer -
// ---------------
void SvpSalInstance::StopTimer()
{
m_aTimeout.tv_sec = 0;
m_aTimeout.tv_usec = 0;
m_nTimeoutMS = 0;
}
void SvpSalInstance::StartTimer( sal_uLong nMS )
{
timeval Timeout (m_aTimeout); // previous timeout.
gettimeofday (&m_aTimeout, 0);
m_nTimeoutMS = nMS;
m_aTimeout += m_nTimeoutMS;
if ((Timeout > m_aTimeout) || (Timeout.tv_sec == 0))
{
// Wakeup from previous timeout (or stopped timer).
Wakeup();
}
}
void SvpSalInstance::AddToRecentDocumentList(const rtl::OUString&, const rtl::OUString&)
{
}
SvpSalTimer::~SvpSalTimer()
{
}
void SvpSalTimer::Stop()
{
m_pInstance->StopTimer();
}
void SvpSalTimer::Start( sal_uLong nMS )
{
m_pInstance->StartTimer( nMS );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */