1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include <unistd.h> 29 #include <fcntl.h> 30 #include <sys/time.h> 31 #include <sys/poll.h> 32 33 #include <sal/types.h> 34 35 #include <vcl/apptypes.hxx> 36 37 #include "svpinst.hxx" 38 #include "svpframe.hxx" 39 #include "svpdummies.hxx" 40 #include "svpvd.hxx" 41 #include "svpbmp.hxx" 42 43 #include <salframe.hxx> 44 #include <svdata.hxx> 45 #include <saldatabasic.hxx> 46 47 // plugin factory function 48 extern "C" 49 { 50 SAL_DLLPUBLIC_EXPORT SalInstance* create_SalInstance() 51 { 52 SvpSalInstance* pInstance = new SvpSalInstance(); 53 SalData* pSalData = new SalData(); 54 pSalData->m_pInstance = pInstance; 55 SetSalData( pSalData ); 56 return pInstance; 57 } 58 } 59 60 bool SvpSalInstance::isFrameAlive( const SalFrame* pFrame ) const 61 { 62 for( std::list< SalFrame* >::const_iterator it = m_aFrames.begin(); 63 it != m_aFrames.end(); ++it ) 64 { 65 if( *it == pFrame ) 66 { 67 return true; 68 } 69 } 70 return false; 71 } 72 73 SvpSalInstance* SvpSalInstance::s_pDefaultInstance = NULL; 74 75 SvpSalInstance::SvpSalInstance() 76 { 77 m_aTimeout.tv_sec = 0; 78 m_aTimeout.tv_usec = 0; 79 m_nTimeoutMS = 0; 80 81 m_pTimeoutFDS[0] = m_pTimeoutFDS[1] = -1; 82 if (pipe (m_pTimeoutFDS) != -1) 83 { 84 // initialize 'wakeup' pipe. 85 int flags; 86 87 // set close-on-exec descriptor flag. 88 if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFD)) != -1) 89 { 90 flags |= FD_CLOEXEC; 91 fcntl (m_pTimeoutFDS[0], F_SETFD, flags); 92 } 93 if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFD)) != -1) 94 { 95 flags |= FD_CLOEXEC; 96 fcntl (m_pTimeoutFDS[1], F_SETFD, flags); 97 } 98 99 // set non-blocking I/O flag. 100 if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFL)) != -1) 101 { 102 flags |= O_NONBLOCK; 103 fcntl (m_pTimeoutFDS[0], F_SETFL, flags); 104 } 105 if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFL)) != -1) 106 { 107 flags |= O_NONBLOCK; 108 fcntl (m_pTimeoutFDS[1], F_SETFL, flags); 109 } 110 } 111 m_aEventGuard = osl_createMutex(); 112 if( s_pDefaultInstance == NULL ) 113 s_pDefaultInstance = this; 114 } 115 116 SvpSalInstance::~SvpSalInstance() 117 { 118 if( s_pDefaultInstance == this ) 119 s_pDefaultInstance = NULL; 120 121 // close 'wakeup' pipe. 122 close (m_pTimeoutFDS[0]); 123 close (m_pTimeoutFDS[1]); 124 osl_destroyMutex( m_aEventGuard ); 125 } 126 127 void SvpSalInstance::PostEvent( const SalFrame* pFrame, void* pData, sal_uInt16 nEvent ) 128 { 129 if( osl_acquireMutex( m_aEventGuard ) ) 130 { 131 m_aUserEvents.push_back( SalUserEvent( pFrame, pData, nEvent ) ); 132 osl_releaseMutex( m_aEventGuard ); 133 } 134 Wakeup(); 135 } 136 137 void SvpSalInstance::CancelEvent( const SalFrame* pFrame, void* pData, sal_uInt16 nEvent ) 138 { 139 if( osl_acquireMutex( m_aEventGuard ) ) 140 { 141 if( ! m_aUserEvents.empty() ) 142 { 143 std::list< SalUserEvent >::iterator it = m_aUserEvents.begin(); 144 do 145 { 146 if( it->m_pFrame == pFrame && 147 it->m_pData == pData && 148 it->m_nEvent == nEvent ) 149 { 150 it = m_aUserEvents.erase( it ); 151 } 152 else 153 ++it; 154 } while( it != m_aUserEvents.end() ); 155 } 156 osl_releaseMutex( m_aEventGuard ); 157 } 158 } 159 160 void SvpSalInstance::deregisterFrame( SalFrame* pFrame ) 161 { 162 m_aFrames.remove( pFrame ); 163 164 if( osl_acquireMutex( m_aEventGuard ) ) 165 { 166 // cancel outstanding events for this frame 167 if( ! m_aUserEvents.empty() ) 168 { 169 std::list< SalUserEvent >::iterator it = m_aUserEvents.begin(); 170 do 171 { 172 if( it->m_pFrame == pFrame ) 173 { 174 it = m_aUserEvents.erase( it ); 175 } 176 else 177 ++it; 178 } while( it != m_aUserEvents.end() ); 179 } 180 osl_releaseMutex( m_aEventGuard ); 181 } 182 } 183 184 void SvpSalInstance::Wakeup() 185 { 186 write (m_pTimeoutFDS[1], "", 1); 187 } 188 189 190 // -=-= timeval =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 191 inline int operator >= ( const timeval &t1, const timeval &t2 ) 192 { 193 if( t1.tv_sec == t2.tv_sec ) 194 return t1.tv_usec >= t2.tv_usec; 195 return t1.tv_sec > t2.tv_sec; 196 } 197 inline timeval &operator += ( timeval &t1, sal_uLong t2 ) 198 { 199 t1.tv_sec += t2 / 1000; 200 t1.tv_usec += t2 ? (t2 % 1000) * 1000 : 500; 201 if( t1.tv_usec > 1000000 ) 202 { 203 t1.tv_sec++; 204 t1.tv_usec -= 1000000; 205 } 206 return t1; 207 } 208 inline int operator > ( const timeval &t1, const timeval &t2 ) 209 { 210 if( t1.tv_sec == t2.tv_sec ) 211 return t1.tv_usec > t2.tv_usec; 212 return t1.tv_sec > t2.tv_sec; 213 } 214 215 bool SvpSalInstance::CheckTimeout( bool bExecuteTimers ) 216 { 217 bool bRet = false; 218 if( m_aTimeout.tv_sec ) // timer is started 219 { 220 timeval aTimeOfDay; 221 gettimeofday( &aTimeOfDay, 0 ); 222 if( aTimeOfDay >= m_aTimeout ) 223 { 224 bRet = true; 225 if( bExecuteTimers ) 226 { 227 // timed out, update timeout 228 m_aTimeout = aTimeOfDay; 229 m_aTimeout += m_nTimeoutMS; 230 // notify 231 ImplSVData* pSVData = ImplGetSVData(); 232 if( pSVData->mpSalTimer ) 233 pSVData->mpSalTimer->CallCallback(); 234 } 235 } 236 } 237 return bRet; 238 } 239 240 SalFrame* SvpSalInstance::CreateChildFrame( SystemParentData* pParent, sal_uLong nStyle ) 241 { 242 return new SvpSalFrame( this, NULL, nStyle, pParent ); 243 } 244 245 SalFrame* SvpSalInstance::CreateFrame( SalFrame* pParent, sal_uLong nStyle ) 246 { 247 return new SvpSalFrame( this, pParent, nStyle ); 248 } 249 250 void SvpSalInstance::DestroyFrame( SalFrame* pFrame ) 251 { 252 delete pFrame; 253 } 254 255 SalObject* SvpSalInstance::CreateObject( SalFrame*, SystemWindowData*, sal_Bool ) 256 { 257 return new SvpSalObject(); 258 } 259 260 void SvpSalInstance::DestroyObject( SalObject* pObject ) 261 { 262 delete pObject; 263 } 264 265 SalVirtualDevice* SvpSalInstance::CreateVirtualDevice( SalGraphics*, 266 long nDX, long nDY, 267 sal_uInt16 nBitCount, const SystemGraphicsData* ) 268 { 269 SvpSalVirtualDevice* pNew = new SvpSalVirtualDevice( nBitCount ); 270 pNew->SetSize( nDX, nDY ); 271 return pNew; 272 } 273 274 void SvpSalInstance::DestroyVirtualDevice( SalVirtualDevice* pDevice ) 275 { 276 delete pDevice; 277 } 278 279 SalTimer* SvpSalInstance::CreateSalTimer() 280 { 281 return new SvpSalTimer( this ); 282 } 283 284 SalI18NImeStatus* SvpSalInstance::CreateI18NImeStatus() 285 { 286 return new SvpImeStatus(); 287 } 288 289 SalSystem* SvpSalInstance::CreateSalSystem() 290 { 291 return new SvpSalSystem(); 292 } 293 294 SalBitmap* SvpSalInstance::CreateSalBitmap() 295 { 296 return new SvpSalBitmap(); 297 } 298 299 vos::IMutex* SvpSalInstance::GetYieldMutex() 300 { 301 return &m_aYieldMutex; 302 } 303 304 sal_uLong SvpSalInstance::ReleaseYieldMutex() 305 { 306 if ( m_aYieldMutex.GetThreadId() == 307 vos::OThread::getCurrentIdentifier() ) 308 { 309 sal_uLong nCount = m_aYieldMutex.GetAcquireCount(); 310 sal_uLong n = nCount; 311 while ( n ) 312 { 313 m_aYieldMutex.release(); 314 n--; 315 } 316 317 return nCount; 318 } 319 else 320 return 0; 321 } 322 323 void SvpSalInstance::AcquireYieldMutex( sal_uLong nCount ) 324 { 325 while ( nCount ) 326 { 327 m_aYieldMutex.acquire(); 328 nCount--; 329 } 330 } 331 332 bool SvpSalInstance::CheckYieldMutex() 333 { 334 bool bRet = true; 335 336 if ( m_aYieldMutex.GetThreadId() != 337 vos::OThread::getCurrentIdentifier() ) 338 { 339 bRet = false; 340 } 341 342 return bRet; 343 } 344 345 void SvpSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents ) 346 { 347 // first, check for already queued events. 348 349 // release yield mutex 350 std::list< SalUserEvent > aEvents; 351 sal_uLong nAcquireCount = ReleaseYieldMutex(); 352 if( osl_acquireMutex( m_aEventGuard ) ) 353 { 354 if( ! m_aUserEvents.empty() ) 355 { 356 if( bHandleAllCurrentEvents ) 357 { 358 aEvents = m_aUserEvents; 359 m_aUserEvents.clear(); 360 } 361 else 362 { 363 aEvents.push_back( m_aUserEvents.front() ); 364 m_aUserEvents.pop_front(); 365 } 366 } 367 osl_releaseMutex( m_aEventGuard ); 368 } 369 // acquire yield mutex again 370 AcquireYieldMutex( nAcquireCount ); 371 372 bool bEvent = !aEvents.empty(); 373 if( bEvent ) 374 { 375 for( std::list<SalUserEvent>::const_iterator it = aEvents.begin(); it != aEvents.end(); ++it ) 376 { 377 if ( isFrameAlive( it->m_pFrame ) ) 378 { 379 it->m_pFrame->CallCallback( it->m_nEvent, it->m_pData ); 380 if( it->m_nEvent == SALEVENT_RESIZE ) 381 { 382 // this would be a good time to post a paint 383 const SvpSalFrame* pSvpFrame = static_cast<const SvpSalFrame*>(it->m_pFrame); 384 pSvpFrame->PostPaint(); 385 } 386 } 387 } 388 } 389 390 bEvent = CheckTimeout() || bEvent; 391 392 if (bWait && ! bEvent ) 393 { 394 int nTimeoutMS = 0; 395 if (m_aTimeout.tv_sec) // Timer is started. 396 { 397 timeval Timeout; 398 // determine remaining timeout. 399 gettimeofday (&Timeout, 0); 400 nTimeoutMS = m_aTimeout.tv_sec*1000 + m_aTimeout.tv_usec/1000 401 - Timeout.tv_sec*1000 - Timeout.tv_usec/1000; 402 if( nTimeoutMS < 0 ) 403 nTimeoutMS = 0; 404 } 405 else 406 nTimeoutMS = -1; // wait until something happens 407 408 // release yield mutex 409 nAcquireCount = ReleaseYieldMutex(); 410 // poll 411 struct pollfd aPoll; 412 aPoll.fd = m_pTimeoutFDS[0]; 413 aPoll.events = POLLIN; 414 aPoll.revents = 0; 415 poll( &aPoll, 1, nTimeoutMS ); 416 417 // acquire yield mutex again 418 AcquireYieldMutex( nAcquireCount ); 419 420 // clean up pipe 421 if( (aPoll.revents & POLLIN) != 0 ) 422 { 423 int buffer; 424 while (read (m_pTimeoutFDS[0], &buffer, sizeof(buffer)) > 0) 425 continue; 426 } 427 } 428 } 429 430 bool SvpSalInstance::AnyInput( sal_uInt16 nType ) 431 { 432 if( (nType & INPUT_TIMER) != 0 ) 433 return CheckTimeout( false ); 434 return false; 435 } 436 437 SalSession* SvpSalInstance::CreateSalSession() 438 { 439 return NULL; 440 } 441 442 void* SvpSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ) 443 { 444 rReturnedBytes = 1; 445 rReturnedType = AsciiCString; 446 return const_cast<char*>(""); 447 } 448 449 // ------------------------------------------------------------------------- 450 // 451 // SalYieldMutex 452 // 453 // ------------------------------------------------------------------------- 454 455 SvpSalYieldMutex::SvpSalYieldMutex() 456 { 457 mnCount = 0; 458 mnThreadId = 0; 459 } 460 461 void SvpSalYieldMutex::acquire() 462 { 463 OMutex::acquire(); 464 mnThreadId = vos::OThread::getCurrentIdentifier(); 465 mnCount++; 466 } 467 468 void SvpSalYieldMutex::release() 469 { 470 if ( mnThreadId == vos::OThread::getCurrentIdentifier() ) 471 { 472 if ( mnCount == 1 ) 473 mnThreadId = 0; 474 mnCount--; 475 } 476 OMutex::release(); 477 } 478 479 sal_Bool SvpSalYieldMutex::tryToAcquire() 480 { 481 if ( OMutex::tryToAcquire() ) 482 { 483 mnThreadId = vos::OThread::getCurrentIdentifier(); 484 mnCount++; 485 return sal_True; 486 } 487 else 488 return sal_False; 489 } 490 491 // --------------- 492 // - SalTimer - 493 // --------------- 494 495 void SvpSalInstance::StopTimer() 496 { 497 m_aTimeout.tv_sec = 0; 498 m_aTimeout.tv_usec = 0; 499 m_nTimeoutMS = 0; 500 } 501 502 void SvpSalInstance::StartTimer( sal_uLong nMS ) 503 { 504 timeval Timeout (m_aTimeout); // previous timeout. 505 gettimeofday (&m_aTimeout, 0); 506 507 m_nTimeoutMS = nMS; 508 m_aTimeout += m_nTimeoutMS; 509 510 if ((Timeout > m_aTimeout) || (Timeout.tv_sec == 0)) 511 { 512 // Wakeup from previous timeout (or stopped timer). 513 Wakeup(); 514 } 515 } 516 517 void SvpSalInstance::AddToRecentDocumentList(const rtl::OUString&, const rtl::OUString&) 518 { 519 } 520 521 SvpSalTimer::~SvpSalTimer() 522 { 523 } 524 525 void SvpSalTimer::Stop() 526 { 527 m_pInstance->StopTimer(); 528 } 529 530 void SvpSalTimer::Start( sal_uLong nMS ) 531 { 532 m_pInstance->StartTimer( nMS ); 533 } 534 535