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