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 : #include "headless/svpbmp.hxx"
34 :
35 : #include <salframe.hxx>
36 : #include <svdata.hxx>
37 : #include <generic/gendata.hxx>
38 : #include <basebmp/scanlineformats.hxx>
39 : #include <vcl/solarmutex.hxx>
40 : // FIXME: remove when we re-work the svp mainloop
41 : #include <unx/salunxtime.h>
42 :
43 21293 : bool SvpSalInstance::isFrameAlive( const SalFrame* pFrame ) const
44 : {
45 84963 : for( std::list< SalFrame* >::const_iterator it = m_aFrames.begin();
46 56642 : it != m_aFrames.end(); ++it )
47 : {
48 28320 : if( *it == pFrame )
49 : {
50 21292 : return true;
51 : }
52 : }
53 1 : return false;
54 : }
55 :
56 : SvpSalInstance* SvpSalInstance::s_pDefaultInstance = NULL;
57 :
58 151 : SvpSalInstance::SvpSalInstance( SalYieldMutex *pMutex ) :
59 151 : SalGenericInstance( pMutex )
60 : {
61 151 : m_aTimeout.tv_sec = 0;
62 151 : m_aTimeout.tv_usec = 0;
63 151 : m_nTimeoutMS = 0;
64 :
65 151 : m_pTimeoutFDS[0] = m_pTimeoutFDS[1] = -1;
66 151 : if (pipe (m_pTimeoutFDS) != -1)
67 : {
68 : // initialize 'wakeup' pipe.
69 : int flags;
70 :
71 : // set close-on-exec descriptor flag.
72 151 : if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFD)) != -1)
73 : {
74 151 : flags |= FD_CLOEXEC;
75 151 : fcntl (m_pTimeoutFDS[0], F_SETFD, flags);
76 : }
77 151 : if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFD)) != -1)
78 : {
79 151 : flags |= FD_CLOEXEC;
80 151 : fcntl (m_pTimeoutFDS[1], F_SETFD, flags);
81 : }
82 :
83 : // set non-blocking I/O flag.
84 151 : if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFL)) != -1)
85 : {
86 151 : flags |= O_NONBLOCK;
87 151 : fcntl (m_pTimeoutFDS[0], F_SETFL, flags);
88 : }
89 151 : if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFL)) != -1)
90 : {
91 151 : flags |= O_NONBLOCK;
92 151 : fcntl (m_pTimeoutFDS[1], F_SETFL, flags);
93 : }
94 : }
95 151 : m_aEventGuard = osl_createMutex();
96 151 : if( s_pDefaultInstance == NULL )
97 151 : s_pDefaultInstance = this;
98 151 : }
99 :
100 282 : SvpSalInstance::~SvpSalInstance()
101 : {
102 94 : if( s_pDefaultInstance == this )
103 94 : s_pDefaultInstance = NULL;
104 :
105 : // close 'wakeup' pipe.
106 94 : close (m_pTimeoutFDS[0]);
107 94 : close (m_pTimeoutFDS[1]);
108 94 : osl_destroyMutex( m_aEventGuard );
109 188 : }
110 :
111 25365 : void SvpSalInstance::PostEvent( const SalFrame* pFrame, void* pData, sal_uInt16 nEvent )
112 : {
113 25365 : if( osl_acquireMutex( m_aEventGuard ) )
114 : {
115 25365 : m_aUserEvents.push_back( SalUserEvent( pFrame, pData, nEvent ) );
116 25365 : osl_releaseMutex( m_aEventGuard );
117 : }
118 25365 : Wakeup();
119 25365 : }
120 :
121 0 : bool SvpSalInstance::PostedEventsInQueue()
122 : {
123 0 : bool result = false;
124 0 : if( osl_acquireMutex( m_aEventGuard ) )
125 : {
126 0 : result = m_aUserEvents.size() > 0;
127 0 : osl_releaseMutex( m_aEventGuard );
128 : }
129 0 : return result;
130 : }
131 :
132 3449 : void SvpSalInstance::deregisterFrame( SalFrame* pFrame )
133 : {
134 3449 : m_aFrames.remove( pFrame );
135 :
136 3449 : if( osl_acquireMutex( m_aEventGuard ) )
137 : {
138 : // cancel outstanding events for this frame
139 3449 : if( ! m_aUserEvents.empty() )
140 : {
141 3247 : std::list< SalUserEvent >::iterator it = m_aUserEvents.begin();
142 93738 : do
143 : {
144 46869 : if( it->m_pFrame == pFrame )
145 : {
146 3311 : it = m_aUserEvents.erase( it );
147 : }
148 : else
149 43558 : ++it;
150 93738 : } while( it != m_aUserEvents.end() );
151 : }
152 3449 : osl_releaseMutex( m_aEventGuard );
153 : }
154 3449 : }
155 :
156 35368 : void SvpSalInstance::Wakeup()
157 : {
158 35368 : OSL_VERIFY(write (m_pTimeoutFDS[1], "", 1) == 1);
159 35368 : }
160 :
161 126866 : bool SvpSalInstance::CheckTimeout( bool bExecuteTimers )
162 : {
163 126866 : bool bRet = false;
164 126866 : if( m_aTimeout.tv_sec ) // timer is started
165 : {
166 : timeval aTimeOfDay;
167 126710 : gettimeofday( &aTimeOfDay, 0 );
168 126710 : if( aTimeOfDay >= m_aTimeout )
169 : {
170 17284 : bRet = true;
171 17284 : if( bExecuteTimers )
172 : {
173 : // timed out, update timeout
174 16965 : m_aTimeout = aTimeOfDay;
175 16965 : m_aTimeout += m_nTimeoutMS;
176 :
177 16965 : osl::Guard< comphelper::SolarMutex > aGuard( mpSalYieldMutex );
178 :
179 : // notify
180 16965 : ImplSVData* pSVData = ImplGetSVData();
181 16965 : if( pSVData->mpSalTimer )
182 16965 : pSVData->mpSalTimer->CallCallback();
183 : }
184 : }
185 : }
186 126866 : return bRet;
187 : }
188 :
189 0 : SalFrame* SvpSalInstance::CreateChildFrame( SystemParentData* pParent, sal_uLong nStyle )
190 : {
191 0 : return new SvpSalFrame( this, NULL, nStyle, false, SVP_DEFAULT_BITMAP_FORMAT, pParent );
192 : }
193 :
194 3505 : SalFrame* SvpSalInstance::CreateFrame( SalFrame* pParent, sal_uLong nStyle )
195 : {
196 3505 : return new SvpSalFrame( this, pParent, nStyle, false, SVP_DEFAULT_BITMAP_FORMAT );
197 : }
198 :
199 3449 : void SvpSalInstance::DestroyFrame( SalFrame* pFrame )
200 : {
201 3449 : delete pFrame;
202 3449 : }
203 :
204 0 : SalObject* SvpSalInstance::CreateObject( SalFrame*, SystemWindowData*, sal_Bool )
205 : {
206 0 : return new SvpSalObject();
207 : }
208 :
209 0 : void SvpSalInstance::DestroyObject( SalObject* pObject )
210 : {
211 0 : delete pObject;
212 0 : }
213 :
214 67109 : SalVirtualDevice* SvpSalInstance::CreateVirtualDevice( SalGraphics*,
215 : long nDX, long nDY,
216 : sal_uInt16 nBitCount, const SystemGraphicsData* )
217 : {
218 67109 : SvpSalVirtualDevice* pNew = new SvpSalVirtualDevice( nBitCount );
219 67109 : pNew->SetSize( nDX, nDY );
220 67109 : return pNew;
221 : }
222 :
223 67030 : void SvpSalInstance::DestroyVirtualDevice( SalVirtualDevice* pDevice )
224 : {
225 67030 : delete pDevice;
226 67030 : }
227 :
228 133 : SalTimer* SvpSalInstance::CreateSalTimer()
229 : {
230 133 : return new SvpSalTimer( this );
231 : }
232 :
233 133 : SalI18NImeStatus* SvpSalInstance::CreateI18NImeStatus()
234 : {
235 133 : return new SvpImeStatus();
236 : }
237 :
238 55 : SalSystem* SvpSalInstance::CreateSalSystem()
239 : {
240 55 : return new SvpSalSystem();
241 : }
242 :
243 314454 : SalBitmap* SvpSalInstance::CreateSalBitmap()
244 : {
245 314454 : return new SvpSalBitmap();
246 : }
247 :
248 125836 : void SvpSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
249 : {
250 : // first, check for already queued events.
251 :
252 : // release yield mutex
253 125836 : std::list< SalUserEvent > aEvents;
254 125836 : sal_uLong nAcquireCount = ReleaseYieldMutex();
255 125836 : if( osl_acquireMutex( m_aEventGuard ) )
256 : {
257 125836 : if( ! m_aUserEvents.empty() )
258 : {
259 15887 : if( bHandleAllCurrentEvents )
260 : {
261 1164 : aEvents = m_aUserEvents;
262 1164 : m_aUserEvents.clear();
263 : }
264 : else
265 : {
266 14723 : aEvents.push_back( m_aUserEvents.front() );
267 14723 : m_aUserEvents.pop_front();
268 : }
269 : }
270 125836 : osl_releaseMutex( m_aEventGuard );
271 : }
272 : // acquire yield mutex again
273 125836 : AcquireYieldMutex( nAcquireCount );
274 :
275 125836 : bool bEvent = !aEvents.empty();
276 125836 : if( bEvent )
277 : {
278 37180 : for( std::list<SalUserEvent>::const_iterator it = aEvents.begin(); it != aEvents.end(); ++it )
279 : {
280 21293 : if ( isFrameAlive( it->m_pFrame ) )
281 : {
282 21292 : it->m_pFrame->CallCallback( it->m_nEvent, it->m_pData );
283 21292 : if( it->m_nEvent == SALEVENT_RESIZE )
284 : {
285 : // this would be a good time to post a paint
286 1009 : const SvpSalFrame* pSvpFrame = static_cast<const SvpSalFrame*>(it->m_pFrame);
287 1009 : pSvpFrame->PostPaint(false);
288 : }
289 : }
290 : }
291 : }
292 :
293 125836 : bEvent = CheckTimeout() || bEvent;
294 :
295 125836 : if (bWait && ! bEvent )
296 : {
297 96212 : int nTimeoutMS = 0;
298 96212 : if (m_aTimeout.tv_sec) // Timer is started.
299 : {
300 : timeval Timeout;
301 : // determine remaining timeout.
302 96143 : gettimeofday (&Timeout, 0);
303 96143 : nTimeoutMS = m_aTimeout.tv_sec*1000 + m_aTimeout.tv_usec/1000
304 96143 : - Timeout.tv_sec*1000 - Timeout.tv_usec/1000;
305 96143 : if( nTimeoutMS < 0 )
306 24 : nTimeoutMS = 0;
307 : }
308 : else
309 69 : nTimeoutMS = -1; // wait until something happens
310 :
311 96212 : DoReleaseYield(nTimeoutMS);
312 125836 : }
313 125836 : }
314 :
315 96212 : void SvpSalInstance::DoReleaseYield( int nTimeoutMS )
316 : {
317 : // poll
318 : struct pollfd aPoll;
319 96212 : aPoll.fd = m_pTimeoutFDS[0];
320 96212 : aPoll.events = POLLIN;
321 96212 : aPoll.revents = 0;
322 :
323 : // release yield mutex
324 96212 : sal_uLong nAcquireCount = ReleaseYieldMutex();
325 :
326 96212 : poll( &aPoll, 1, nTimeoutMS );
327 :
328 : // acquire yield mutex again
329 96212 : AcquireYieldMutex( nAcquireCount );
330 :
331 : // clean up pipe
332 96212 : if( (aPoll.revents & POLLIN) != 0 )
333 : {
334 : int buffer;
335 31538 : while (read (m_pTimeoutFDS[0], &buffer, sizeof(buffer)) > 0)
336 12322 : continue;
337 : }
338 96212 : }
339 :
340 15989 : bool SvpSalInstance::AnyInput( sal_uInt16 nType )
341 : {
342 15989 : if( (nType & VCL_INPUT_TIMER) != 0 )
343 1030 : return CheckTimeout( false );
344 14959 : return false;
345 : }
346 :
347 0 : SalSession* SvpSalInstance::CreateSalSession()
348 : {
349 0 : return NULL;
350 : }
351 :
352 61 : void* SvpSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes )
353 : {
354 61 : rReturnedBytes = 1;
355 61 : rReturnedType = AsciiCString;
356 61 : return const_cast<char*>("");
357 : }
358 :
359 : // ---------------
360 : // - SalTimer -
361 : // ---------------
362 :
363 50 : void SvpSalInstance::StopTimer()
364 : {
365 50 : m_aTimeout.tv_sec = 0;
366 50 : m_aTimeout.tv_usec = 0;
367 50 : m_nTimeoutMS = 0;
368 50 : }
369 :
370 22876 : void SvpSalInstance::StartTimer( sal_uLong nMS )
371 : {
372 22876 : timeval aPrevTimeout (m_aTimeout);
373 22876 : gettimeofday (&m_aTimeout, 0);
374 :
375 22876 : m_nTimeoutMS = nMS;
376 22876 : m_aTimeout += m_nTimeoutMS;
377 :
378 22876 : if ((aPrevTimeout > m_aTimeout) || (aPrevTimeout.tv_sec == 0))
379 : {
380 : // Wakeup from previous timeout (or stopped timer).
381 10003 : Wakeup();
382 : }
383 22876 : }
384 :
385 1142 : void SvpSalInstance::AddToRecentDocumentList(const OUString&, const OUString&)
386 : {
387 1142 : }
388 :
389 188 : SvpSalTimer::~SvpSalTimer()
390 : {
391 188 : }
392 :
393 50 : void SvpSalTimer::Stop()
394 : {
395 50 : m_pInstance->StopTimer();
396 50 : }
397 :
398 22876 : void SvpSalTimer::Start( sal_uLong nMS )
399 : {
400 22876 : m_pInstance->StartTimer( nMS );
401 23329 : }
402 :
403 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|