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