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