xref: /aoo41x/main/vcl/unx/headless/svpinst.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <sys/time.h>
31 #include <sys/poll.h>
32 
33 #include <sal/types.h>
34 
35 #include <vcl/apptypes.hxx>
36 
37 #include "svpinst.hxx"
38 #include "svpframe.hxx"
39 #include "svpdummies.hxx"
40 #include "svpvd.hxx"
41 #include "svpbmp.hxx"
42 
43 #include <salframe.hxx>
44 #include <svdata.hxx>
45 #include <saldatabasic.hxx>
46 
47 // plugin factory function
48 extern "C"
49 {
50     SAL_DLLPUBLIC_EXPORT SalInstance* create_SalInstance()
51     {
52         SvpSalInstance* pInstance = new SvpSalInstance();
53         SalData* pSalData = new SalData();
54         pSalData->m_pInstance = pInstance;
55         SetSalData( pSalData );
56         return pInstance;
57     }
58 }
59 
60 bool SvpSalInstance::isFrameAlive( const SalFrame* pFrame ) const
61 {
62     for( std::list< SalFrame* >::const_iterator it = m_aFrames.begin();
63          it != m_aFrames.end(); ++it )
64     {
65         if( *it == pFrame )
66         {
67             return true;
68         }
69     }
70     return false;
71 }
72 
73 SvpSalInstance* SvpSalInstance::s_pDefaultInstance = NULL;
74 
75 SvpSalInstance::SvpSalInstance()
76 {
77 	m_aTimeout.tv_sec 		= 0;
78 	m_aTimeout.tv_usec		= 0;
79 	m_nTimeoutMS 			= 0;
80 
81 	m_pTimeoutFDS[0] = m_pTimeoutFDS[1] = -1;
82 	if (pipe (m_pTimeoutFDS) != -1)
83 	{
84 		// initialize 'wakeup' pipe.
85 		int flags;
86 
87 		// set close-on-exec descriptor flag.
88 		if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFD)) != -1)
89 		{
90 			flags |= FD_CLOEXEC;
91 			fcntl (m_pTimeoutFDS[0], F_SETFD, flags);
92 		}
93 		if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFD)) != -1)
94 		{
95 			flags |= FD_CLOEXEC;
96 			fcntl (m_pTimeoutFDS[1], F_SETFD, flags);
97 		}
98 
99 		// set non-blocking I/O flag.
100 		if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFL)) != -1)
101 		{
102 			flags |= O_NONBLOCK;
103 			fcntl (m_pTimeoutFDS[0], F_SETFL, flags);
104 		}
105 		if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFL)) != -1)
106 		{
107 			flags |= O_NONBLOCK;
108 			fcntl (m_pTimeoutFDS[1], F_SETFL, flags);
109 		}
110 	}
111     m_aEventGuard = osl_createMutex();
112     if( s_pDefaultInstance == NULL )
113         s_pDefaultInstance = this;
114 }
115 
116 SvpSalInstance::~SvpSalInstance()
117 {
118     if( s_pDefaultInstance == this )
119         s_pDefaultInstance = NULL;
120 
121 	// close 'wakeup' pipe.
122 	close (m_pTimeoutFDS[0]);
123 	close (m_pTimeoutFDS[1]);
124     osl_destroyMutex( m_aEventGuard );
125 }
126 
127 void SvpSalInstance::PostEvent( const SalFrame* pFrame, void* pData, sal_uInt16 nEvent )
128 {
129     if( osl_acquireMutex( m_aEventGuard ) )
130     {
131         m_aUserEvents.push_back( SalUserEvent( pFrame, pData, nEvent ) );
132         osl_releaseMutex( m_aEventGuard );
133     }
134     Wakeup();
135 }
136 
137 void SvpSalInstance::CancelEvent( const SalFrame* pFrame, void* pData, sal_uInt16 nEvent )
138 {
139 	if( osl_acquireMutex( m_aEventGuard ) )
140     {
141         if( ! m_aUserEvents.empty() )
142         {
143             std::list< SalUserEvent >::iterator it = m_aUserEvents.begin();
144             do
145             {
146                 if( it->m_pFrame    == pFrame   &&
147                     it->m_pData     == pData    &&
148                     it->m_nEvent    == nEvent )
149                 {
150                     it = m_aUserEvents.erase( it );
151                 }
152                 else
153                     ++it;
154             } while( it != m_aUserEvents.end() );
155         }
156         osl_releaseMutex( m_aEventGuard );
157     }
158 }
159 
160 void SvpSalInstance::deregisterFrame( SalFrame* pFrame )
161 {
162     m_aFrames.remove( pFrame );
163 
164 	if( osl_acquireMutex( m_aEventGuard ) )
165     {
166         // cancel outstanding events for this frame
167         if( ! m_aUserEvents.empty() )
168         {
169             std::list< SalUserEvent >::iterator it = m_aUserEvents.begin();
170             do
171             {
172                 if( it->m_pFrame    == pFrame )
173                 {
174                     it = m_aUserEvents.erase( it );
175                 }
176                 else
177                     ++it;
178             } while( it != m_aUserEvents.end() );
179         }
180         osl_releaseMutex( m_aEventGuard );
181     }
182 }
183 
184 void SvpSalInstance::Wakeup()
185 {
186 	write (m_pTimeoutFDS[1], "", 1);
187 }
188 
189 
190 // -=-= timeval =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
191 inline int operator >= ( const timeval &t1, const timeval &t2 )
192 {
193 	if( t1.tv_sec == t2.tv_sec )
194 		return t1.tv_usec >= t2.tv_usec;
195 	return t1.tv_sec > t2.tv_sec;
196 }
197 inline timeval &operator += ( timeval &t1, sal_uLong t2 )
198 {
199 	t1.tv_sec  += t2 / 1000;
200 	t1.tv_usec += t2 ? (t2 % 1000) * 1000 : 500;
201 	if( t1.tv_usec > 1000000 )
202 	{
203 		t1.tv_sec++;
204 		t1.tv_usec -= 1000000;
205 	}
206 	return t1;
207 }
208 inline int operator > ( const timeval &t1, const timeval &t2 )
209 {
210 	if( t1.tv_sec == t2.tv_sec )
211 		return t1.tv_usec > t2.tv_usec;
212 	return t1.tv_sec > t2.tv_sec;
213 }
214 
215 bool SvpSalInstance::CheckTimeout( bool bExecuteTimers )
216 {
217     bool bRet = false;
218 	if( m_aTimeout.tv_sec ) // timer is started
219 	{
220 		timeval aTimeOfDay;
221 		gettimeofday( &aTimeOfDay, 0 );
222 		if( aTimeOfDay >= m_aTimeout )
223 		{
224             bRet = true;
225             if( bExecuteTimers )
226             {
227                 // timed out, update timeout
228                 m_aTimeout = aTimeOfDay;
229                 m_aTimeout += m_nTimeoutMS;
230                 // notify
231                 ImplSVData* pSVData = ImplGetSVData();
232                 if( pSVData->mpSalTimer )
233                     pSVData->mpSalTimer->CallCallback();
234             }
235 		}
236 	}
237     return bRet;
238 }
239 
240 SalFrame* SvpSalInstance::CreateChildFrame( SystemParentData* pParent, sal_uLong nStyle )
241 {
242     return new SvpSalFrame( this, NULL, nStyle, pParent );
243 }
244 
245 SalFrame* SvpSalInstance::CreateFrame( SalFrame* pParent, sal_uLong nStyle )
246 {
247     return new SvpSalFrame( this, pParent, nStyle );
248 }
249 
250 void SvpSalInstance::DestroyFrame( SalFrame* pFrame )
251 {
252     delete pFrame;
253 }
254 
255 SalObject* SvpSalInstance::CreateObject( SalFrame*, SystemWindowData*, sal_Bool )
256 {
257     return new SvpSalObject();
258 }
259 
260 void SvpSalInstance::DestroyObject( SalObject* pObject )
261 {
262     delete pObject;
263 }
264 
265 SalVirtualDevice* SvpSalInstance::CreateVirtualDevice( SalGraphics*,
266                                                        long nDX, long nDY,
267                                                        sal_uInt16 nBitCount, const SystemGraphicsData* )
268 {
269     SvpSalVirtualDevice* pNew = new SvpSalVirtualDevice( nBitCount );
270     pNew->SetSize( nDX, nDY );
271     return pNew;
272 }
273 
274 void SvpSalInstance::DestroyVirtualDevice( SalVirtualDevice* pDevice )
275 {
276     delete pDevice;
277 }
278 
279 SalTimer* SvpSalInstance::CreateSalTimer()
280 {
281     return new SvpSalTimer( this );
282 }
283 
284 SalI18NImeStatus* SvpSalInstance::CreateI18NImeStatus()
285 {
286     return new SvpImeStatus();
287 }
288 
289 SalSystem* SvpSalInstance::CreateSalSystem()
290 {
291     return new SvpSalSystem();
292 }
293 
294 SalBitmap* SvpSalInstance::CreateSalBitmap()
295 {
296     return new SvpSalBitmap();
297 }
298 
299 vos::IMutex* SvpSalInstance::GetYieldMutex()
300 {
301     return &m_aYieldMutex;
302 }
303 
304 sal_uLong SvpSalInstance::ReleaseYieldMutex()
305 {
306 	if ( m_aYieldMutex.GetThreadId() ==
307 		 vos::OThread::getCurrentIdentifier() )
308 	{
309 		sal_uLong nCount = m_aYieldMutex.GetAcquireCount();
310 		sal_uLong n = nCount;
311 		while ( n )
312 		{
313 			m_aYieldMutex.release();
314 			n--;
315 		}
316 
317 		return nCount;
318 	}
319 	else
320 		return 0;
321 }
322 
323 void SvpSalInstance::AcquireYieldMutex( sal_uLong nCount )
324 {
325 	while ( nCount )
326 	{
327 		m_aYieldMutex.acquire();
328 		nCount--;
329 	}
330 }
331 
332 bool SvpSalInstance::CheckYieldMutex()
333 {
334     bool bRet = true;
335 
336 	if ( m_aYieldMutex.GetThreadId() !=
337 		 vos::OThread::getCurrentIdentifier() )
338 	{
339 	    bRet = false;
340 	}
341 
342     return bRet;
343 }
344 
345 void SvpSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
346 {
347 	// first, check for already queued events.
348 
349     // release yield mutex
350     std::list< SalUserEvent > aEvents;
351     sal_uLong nAcquireCount = ReleaseYieldMutex();
352     if( osl_acquireMutex( m_aEventGuard ) )
353     {
354         if( ! m_aUserEvents.empty() )
355         {
356             if( bHandleAllCurrentEvents )
357             {
358                 aEvents = m_aUserEvents;
359                 m_aUserEvents.clear();
360             }
361             else
362             {
363                 aEvents.push_back( m_aUserEvents.front() );
364                 m_aUserEvents.pop_front();
365             }
366         }
367         osl_releaseMutex( m_aEventGuard );
368     }
369     // acquire yield mutex again
370     AcquireYieldMutex( nAcquireCount );
371 
372     bool bEvent = !aEvents.empty();
373     if( bEvent )
374     {
375         for( std::list<SalUserEvent>::const_iterator it = aEvents.begin(); it != aEvents.end(); ++it )
376         {
377             if ( isFrameAlive( it->m_pFrame ) )
378             {
379                 it->m_pFrame->CallCallback( it->m_nEvent, it->m_pData );
380                 if( it->m_nEvent == SALEVENT_RESIZE )
381                 {
382                     // this would be a good time to post a paint
383                     const SvpSalFrame* pSvpFrame = static_cast<const SvpSalFrame*>(it->m_pFrame);
384                     pSvpFrame->PostPaint();
385                 }
386             }
387         }
388     }
389 
390     bEvent = CheckTimeout() || bEvent;
391 
392 	if (bWait && ! bEvent )
393 	{
394         int nTimeoutMS = 0;
395 		if (m_aTimeout.tv_sec) // Timer is started.
396 		{
397             timeval Timeout;
398 			// determine remaining timeout.
399 			gettimeofday (&Timeout, 0);
400             nTimeoutMS = m_aTimeout.tv_sec*1000 + m_aTimeout.tv_usec/1000
401                          - Timeout.tv_sec*1000 - Timeout.tv_usec/1000;
402             if( nTimeoutMS < 0 )
403                 nTimeoutMS = 0;
404 		}
405         else
406             nTimeoutMS = -1; // wait until something happens
407 
408         // release yield mutex
409         nAcquireCount = ReleaseYieldMutex();
410         // poll
411         struct pollfd aPoll;
412         aPoll.fd = m_pTimeoutFDS[0];
413         aPoll.events = POLLIN;
414         aPoll.revents = 0;
415         poll( &aPoll, 1, nTimeoutMS );
416 
417         // acquire yield mutex again
418         AcquireYieldMutex( nAcquireCount );
419 
420         // clean up pipe
421         if( (aPoll.revents & POLLIN) != 0 )
422         {
423             int buffer;
424             while (read (m_pTimeoutFDS[0], &buffer, sizeof(buffer)) > 0)
425                 continue;
426         }
427 	}
428 }
429 
430 bool SvpSalInstance::AnyInput( sal_uInt16 nType )
431 {
432     if( (nType & INPUT_TIMER) != 0 )
433         return CheckTimeout( false );
434     return false;
435 }
436 
437 SalSession* SvpSalInstance::CreateSalSession()
438 {
439     return NULL;
440 }
441 
442 void* SvpSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes )
443 {
444 	rReturnedBytes  = 1;
445 	rReturnedType   = AsciiCString;
446 	return const_cast<char*>("");
447 }
448 
449 // -------------------------------------------------------------------------
450 //
451 // SalYieldMutex
452 //
453 // -------------------------------------------------------------------------
454 
455 SvpSalYieldMutex::SvpSalYieldMutex()
456 {
457 	mnCount 	= 0;
458 	mnThreadId	= 0;
459 }
460 
461 void SvpSalYieldMutex::acquire()
462 {
463 	OMutex::acquire();
464 	mnThreadId = vos::OThread::getCurrentIdentifier();
465 	mnCount++;
466 }
467 
468 void SvpSalYieldMutex::release()
469 {
470 	if ( mnThreadId == vos::OThread::getCurrentIdentifier() )
471 	{
472 		if ( mnCount == 1 )
473 			mnThreadId = 0;
474 		mnCount--;
475 	}
476 	OMutex::release();
477 }
478 
479 sal_Bool SvpSalYieldMutex::tryToAcquire()
480 {
481 	if ( OMutex::tryToAcquire() )
482 	{
483 		mnThreadId = vos::OThread::getCurrentIdentifier();
484 		mnCount++;
485 		return sal_True;
486 	}
487 	else
488 		return sal_False;
489 }
490 
491 // ---------------
492 // - SalTimer -
493 // ---------------
494 
495 void SvpSalInstance::StopTimer()
496 {
497 	m_aTimeout.tv_sec	= 0;
498 	m_aTimeout.tv_usec	= 0;
499 	m_nTimeoutMS		= 0;
500 }
501 
502 void SvpSalInstance::StartTimer( sal_uLong nMS )
503 {
504 	timeval Timeout (m_aTimeout); // previous timeout.
505 	gettimeofday (&m_aTimeout, 0);
506 
507 	m_nTimeoutMS  = nMS;
508 	m_aTimeout    += m_nTimeoutMS;
509 
510 	if ((Timeout > m_aTimeout) || (Timeout.tv_sec == 0))
511 	{
512 		// Wakeup from previous timeout (or stopped timer).
513 		Wakeup();
514 	}
515 }
516 
517 void SvpSalInstance::AddToRecentDocumentList(const rtl::OUString&, const rtl::OUString&)
518 {
519 }
520 
521 SvpSalTimer::~SvpSalTimer()
522 {
523 }
524 
525 void SvpSalTimer::Stop()
526 {
527 	m_pInstance->StopTimer();
528 }
529 
530 void SvpSalTimer::Start( sal_uLong nMS )
531 {
532 	m_pInstance->StartTimer( nMS );
533 }
534 
535