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