xref: /AOO41X/main/vcl/unx/headless/svpinst.cxx (revision 9f62ea84a806e17e6f2bbff75724a7257a0eb5d9)
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