Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <unistd.h>
21 : #include <fcntl.h>
22 : #include <sys/time.h>
23 : #include <sys/poll.h>
24 :
25 : #include <sal/types.h>
26 :
27 : #include <vcl/apptypes.hxx>
28 :
29 : #include "headless/svpinst.hxx"
30 : #include "headless/svpframe.hxx"
31 : #include "headless/svpdummies.hxx"
32 : #include "headless/svpvd.hxx"
33 : #ifdef IOS
34 : #include "headless/svpgdi.hxx"
35 : #include "quartz/salbmp.h"
36 : #include "quartz/salgdi.h"
37 : #include "quartz/salvd.h"
38 : #endif
39 : #include "headless/svpbmp.hxx"
40 :
41 : #include <salframe.hxx>
42 : #include <svdata.hxx>
43 : #include <generic/gendata.hxx>
44 : #include <basebmp/scanlineformats.hxx>
45 : // FIXME: remove when we re-work the svp mainloop
46 : #include <unx/salunxtime.h>
47 :
48 31583 : bool SvpSalInstance::isFrameAlive( const SalFrame* pFrame ) const
49 : {
50 109317 : for( std::list< SalFrame* >::const_iterator it = m_aFrames.begin();
51 72878 : it != m_aFrames.end(); ++it )
52 : {
53 36437 : if( *it == pFrame )
54 : {
55 31581 : return true;
56 : }
57 : }
58 2 : return false;
59 : }
60 :
61 : SvpSalInstance* SvpSalInstance::s_pDefaultInstance = NULL;
62 :
63 165 : SvpSalInstance::SvpSalInstance( SalYieldMutex *pMutex ) :
64 165 : SalGenericInstance( pMutex )
65 : {
66 165 : m_aTimeout.tv_sec = 0;
67 165 : m_aTimeout.tv_usec = 0;
68 165 : m_nTimeoutMS = 0;
69 :
70 165 : m_pTimeoutFDS[0] = m_pTimeoutFDS[1] = -1;
71 165 : if (pipe (m_pTimeoutFDS) != -1)
72 : {
73 : // initialize 'wakeup' pipe.
74 : int flags;
75 :
76 : // set close-on-exec descriptor flag.
77 165 : if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFD)) != -1)
78 : {
79 165 : flags |= FD_CLOEXEC;
80 165 : fcntl (m_pTimeoutFDS[0], F_SETFD, flags);
81 : }
82 165 : if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFD)) != -1)
83 : {
84 165 : flags |= FD_CLOEXEC;
85 165 : fcntl (m_pTimeoutFDS[1], F_SETFD, flags);
86 : }
87 :
88 : // set non-blocking I/O flag.
89 165 : if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFL)) != -1)
90 : {
91 165 : flags |= O_NONBLOCK;
92 165 : fcntl (m_pTimeoutFDS[0], F_SETFL, flags);
93 : }
94 165 : if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFL)) != -1)
95 : {
96 165 : flags |= O_NONBLOCK;
97 165 : fcntl (m_pTimeoutFDS[1], F_SETFL, flags);
98 : }
99 : }
100 165 : m_aEventGuard = osl_createMutex();
101 165 : if( s_pDefaultInstance == NULL )
102 165 : s_pDefaultInstance = this;
103 165 : }
104 :
105 273 : SvpSalInstance::~SvpSalInstance()
106 : {
107 91 : if( s_pDefaultInstance == this )
108 91 : s_pDefaultInstance = NULL;
109 :
110 : // close 'wakeup' pipe.
111 91 : close (m_pTimeoutFDS[0]);
112 91 : close (m_pTimeoutFDS[1]);
113 91 : osl_destroyMutex( m_aEventGuard );
114 182 : }
115 :
116 36919 : void SvpSalInstance::PostEvent( const SalFrame* pFrame, void* pData, sal_uInt16 nEvent )
117 : {
118 36919 : if( osl_acquireMutex( m_aEventGuard ) )
119 : {
120 36919 : m_aUserEvents.push_back( SalUserEvent( pFrame, pData, nEvent ) );
121 36919 : osl_releaseMutex( m_aEventGuard );
122 : }
123 36919 : Wakeup();
124 36919 : }
125 :
126 0 : bool SvpSalInstance::PostedEventsInQueue()
127 : {
128 0 : bool result = false;
129 0 : if( osl_acquireMutex( m_aEventGuard ) )
130 : {
131 0 : result = m_aUserEvents.size() > 0;
132 0 : osl_releaseMutex( m_aEventGuard );
133 : }
134 0 : return result;
135 : }
136 :
137 4524 : void SvpSalInstance::deregisterFrame( SalFrame* pFrame )
138 : {
139 4524 : m_aFrames.remove( pFrame );
140 :
141 4524 : if( osl_acquireMutex( m_aEventGuard ) )
142 : {
143 : // cancel outstanding events for this frame
144 4524 : if( ! m_aUserEvents.empty() )
145 : {
146 4343 : std::list< SalUserEvent >::iterator it = m_aUserEvents.begin();
147 135256 : do
148 : {
149 67628 : if( it->m_pFrame == pFrame )
150 : {
151 4452 : it = m_aUserEvents.erase( it );
152 : }
153 : else
154 63176 : ++it;
155 135256 : } while( it != m_aUserEvents.end() );
156 : }
157 4524 : osl_releaseMutex( m_aEventGuard );
158 : }
159 4524 : }
160 :
161 49544 : void SvpSalInstance::Wakeup()
162 : {
163 49544 : OSL_VERIFY(write (m_pTimeoutFDS[1], "", 1) == 1);
164 49544 : }
165 :
166 145321 : bool SvpSalInstance::CheckTimeout( bool bExecuteTimers )
167 : {
168 145321 : bool bRet = false;
169 145321 : if( m_aTimeout.tv_sec ) // timer is started
170 : {
171 : timeval aTimeOfDay;
172 145152 : gettimeofday( &aTimeOfDay, 0 );
173 145152 : if( aTimeOfDay >= m_aTimeout )
174 : {
175 22273 : bRet = true;
176 22273 : if( bExecuteTimers )
177 : {
178 : // timed out, update timeout
179 21960 : m_aTimeout = aTimeOfDay;
180 21960 : m_aTimeout += m_nTimeoutMS;
181 :
182 21960 : osl::Guard< comphelper::SolarMutex > aGuard( mpSalYieldMutex );
183 :
184 : // notify
185 21960 : ImplSVData* pSVData = ImplGetSVData();
186 21960 : if( pSVData->mpSalTimer )
187 21960 : pSVData->mpSalTimer->CallCallback();
188 : }
189 : }
190 : }
191 145321 : return bRet;
192 : }
193 :
194 0 : SalFrame* SvpSalInstance::CreateChildFrame( SystemParentData* pParent, sal_uLong nStyle )
195 : {
196 0 : return new SvpSalFrame( this, NULL, nStyle, false, SVP_DEFAULT_BITMAP_FORMAT, pParent );
197 : }
198 :
199 4601 : SalFrame* SvpSalInstance::CreateFrame( SalFrame* pParent, sal_uLong nStyle )
200 : {
201 4601 : return new SvpSalFrame( this, pParent, nStyle, false, SVP_DEFAULT_BITMAP_FORMAT );
202 : }
203 :
204 4524 : void SvpSalInstance::DestroyFrame( SalFrame* pFrame )
205 : {
206 4524 : delete pFrame;
207 4524 : }
208 :
209 0 : SalObject* SvpSalInstance::CreateObject( SalFrame*, SystemWindowData*, bool )
210 : {
211 0 : return new SvpSalObject();
212 : }
213 :
214 0 : void SvpSalInstance::DestroyObject( SalObject* pObject )
215 : {
216 0 : delete pObject;
217 0 : }
218 :
219 : #ifndef IOS
220 :
221 112272 : SalVirtualDevice* SvpSalInstance::CreateVirtualDevice( SalGraphics* /* pGraphics */,
222 : long nDX, long nDY,
223 : sal_uInt16 nBitCount,
224 : const SystemGraphicsData* /* pData */ )
225 : {
226 112272 : SvpSalVirtualDevice* pNew = new SvpSalVirtualDevice( nBitCount );
227 112272 : pNew->SetSize( nDX, nDY );
228 112272 : return pNew;
229 : }
230 :
231 : #endif
232 :
233 211 : SalTimer* SvpSalInstance::CreateSalTimer()
234 : {
235 211 : return new SvpSalTimer( this );
236 : }
237 :
238 143 : SalI18NImeStatus* SvpSalInstance::CreateI18NImeStatus()
239 : {
240 143 : return new SvpImeStatus();
241 : }
242 :
243 60 : SalSystem* SvpSalInstance::CreateSalSystem()
244 : {
245 60 : return new SvpSalSystem();
246 : }
247 :
248 301556 : SalBitmap* SvpSalInstance::CreateSalBitmap()
249 : {
250 : #ifdef IOS
251 : return new QuartzSalBitmap();
252 : #else
253 301556 : return new SvpSalBitmap();
254 : #endif
255 : }
256 :
257 144317 : void SvpSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
258 : {
259 : // first, check for already queued events.
260 :
261 : // release yield mutex
262 144317 : std::list< SalUserEvent > aEvents;
263 144317 : sal_uLong nAcquireCount = ReleaseYieldMutex();
264 144317 : if( osl_acquireMutex( m_aEventGuard ) )
265 : {
266 144317 : if( ! m_aUserEvents.empty() )
267 : {
268 15316 : if( bHandleAllCurrentEvents )
269 : {
270 3525 : aEvents = m_aUserEvents;
271 3525 : m_aUserEvents.clear();
272 : }
273 : else
274 : {
275 11791 : aEvents.push_back( m_aUserEvents.front() );
276 11791 : m_aUserEvents.pop_front();
277 : }
278 : }
279 144317 : osl_releaseMutex( m_aEventGuard );
280 : }
281 : // acquire yield mutex again
282 144317 : AcquireYieldMutex( nAcquireCount );
283 :
284 144317 : bool bEvent = !aEvents.empty();
285 144317 : if( bEvent )
286 : {
287 46899 : for( std::list<SalUserEvent>::const_iterator it = aEvents.begin(); it != aEvents.end(); ++it )
288 : {
289 31583 : if ( isFrameAlive( it->m_pFrame ) )
290 : {
291 31581 : it->m_pFrame->CallCallback( it->m_nEvent, it->m_pData );
292 31581 : if( it->m_nEvent == SALEVENT_RESIZE )
293 : {
294 : // this would be a good time to post a paint
295 1982 : const SvpSalFrame* pSvpFrame = static_cast<const SvpSalFrame*>(it->m_pFrame);
296 1982 : pSvpFrame->PostPaint(false);
297 : }
298 : }
299 : }
300 : }
301 :
302 144317 : bEvent = CheckTimeout() || bEvent;
303 :
304 144317 : if (bWait && ! bEvent )
305 : {
306 111866 : int nTimeoutMS = 0;
307 111866 : if (m_aTimeout.tv_sec) // Timer is started.
308 : {
309 : timeval Timeout;
310 : // determine remaining timeout.
311 111797 : gettimeofday (&Timeout, 0);
312 111797 : nTimeoutMS = m_aTimeout.tv_sec*1000 + m_aTimeout.tv_usec/1000
313 111797 : - Timeout.tv_sec*1000 - Timeout.tv_usec/1000;
314 111797 : if( nTimeoutMS < 0 )
315 57 : nTimeoutMS = 0;
316 : }
317 : else
318 69 : nTimeoutMS = -1; // wait until something happens
319 :
320 111866 : DoReleaseYield(nTimeoutMS);
321 144317 : }
322 144317 : }
323 :
324 111866 : void SvpSalInstance::DoReleaseYield( int nTimeoutMS )
325 : {
326 : // poll
327 : struct pollfd aPoll;
328 111866 : aPoll.fd = m_pTimeoutFDS[0];
329 111866 : aPoll.events = POLLIN;
330 111866 : aPoll.revents = 0;
331 :
332 : // release yield mutex
333 111866 : sal_uLong nAcquireCount = ReleaseYieldMutex();
334 :
335 111866 : poll( &aPoll, 1, nTimeoutMS );
336 :
337 : // acquire yield mutex again
338 111866 : AcquireYieldMutex( nAcquireCount );
339 :
340 : // clean up pipe
341 111866 : if( (aPoll.revents & POLLIN) != 0 )
342 : {
343 : int buffer;
344 34439 : while (read (m_pTimeoutFDS[0], &buffer, sizeof(buffer)) > 0)
345 12743 : continue;
346 : }
347 111866 : }
348 :
349 35612 : bool SvpSalInstance::AnyInput( sal_uInt16 nType )
350 : {
351 35612 : if( (nType & VCL_INPUT_TIMER) != 0 )
352 1004 : return CheckTimeout( false );
353 34608 : return false;
354 : }
355 :
356 0 : SalSession* SvpSalInstance::CreateSalSession()
357 : {
358 0 : return NULL;
359 : }
360 :
361 70 : void* SvpSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes )
362 : {
363 70 : rReturnedBytes = 1;
364 70 : rReturnedType = AsciiCString;
365 70 : return const_cast<char*>("");
366 : }
367 :
368 61 : void SvpSalInstance::StopTimer()
369 : {
370 61 : m_aTimeout.tv_sec = 0;
371 61 : m_aTimeout.tv_usec = 0;
372 61 : m_nTimeoutMS = 0;
373 61 : }
374 :
375 30755 : void SvpSalInstance::StartTimer( sal_uLong nMS )
376 : {
377 30755 : timeval aPrevTimeout (m_aTimeout);
378 30755 : gettimeofday (&m_aTimeout, 0);
379 :
380 30755 : m_nTimeoutMS = nMS;
381 30755 : m_aTimeout += m_nTimeoutMS;
382 :
383 30755 : if ((aPrevTimeout > m_aTimeout) || (aPrevTimeout.tv_sec == 0))
384 : {
385 : // Wakeup from previous timeout (or stopped timer).
386 12625 : Wakeup();
387 : }
388 30755 : }
389 :
390 3520 : void SvpSalInstance::AddToRecentDocumentList(const OUString&, const OUString&, const OUString&)
391 : {
392 3520 : }
393 :
394 318 : SvpSalTimer::~SvpSalTimer()
395 : {
396 318 : }
397 :
398 61 : void SvpSalTimer::Stop()
399 : {
400 61 : m_pInstance->StopTimer();
401 61 : }
402 :
403 30755 : void SvpSalTimer::Start( sal_uLong nMS )
404 : {
405 30755 : m_pInstance->StartTimer( nMS );
406 31250 : }
407 :
408 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|