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 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_vcl.hxx" 30 31 #ifdef USE_XTOOLKIT 32 # define SAL_XT 33 #endif 34 35 // -=-= #includes =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 36 37 #include <unistd.h> 38 #include <fcntl.h> 39 40 #include <cstdio> 41 #include <cstring> 42 #include <cstdlib> 43 #include <stdio.h> // snprintf, seems not to be in namespace std on every platform 44 #include <limits.h> 45 #include <errno.h> 46 #include <pthread.h> 47 #include <sys/resource.h> 48 #ifdef SUN 49 #include <sys/systeminfo.h> 50 #endif 51 #ifdef AIX 52 #include <strings.h> 53 #endif 54 #ifdef FREEBSD 55 #include <sys/types.h> 56 #include <sys/time.h> 57 #include <unistd.h> 58 #endif 59 60 #include <vos/process.hxx> 61 #include <vos/mutex.hxx> 62 63 #include "unx/Xproto.h" 64 #include "unx/saldisp.hxx" 65 #include "unx/saldata.hxx" 66 #include "unx/salframe.h" 67 #include "unx/sm.hxx" 68 #include "unx/i18n_im.hxx" 69 #include "unx/i18n_xkb.hxx" 70 #include "salinst.hxx" 71 72 #include <osl/signal.h> 73 #include <osl/thread.h> 74 #include <osl/process.h> 75 #include <rtl/strbuf.hxx> 76 #include <rtl/bootstrap.hxx> 77 78 #include <tools/debug.hxx> 79 #include <vcl/svapp.hxx> 80 81 // -=-= <signal.h> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 82 #ifndef UNX 83 #ifndef SIGBUS 84 #define SIGBUS 10 85 #endif 86 #ifndef SIGSEGV 87 #define SIGSEGV 11 88 #endif 89 #ifndef SIGIOT 90 #define SIGIOT SIGABRT 91 #endif 92 #endif 93 94 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 95 static const struct timeval noyield__ = { 0, 0 }; 96 static const struct timeval yield__ = { 0, 10000 }; 97 98 static const char* XRequest[] = { 99 // see /usr/lib/X11/XErrorDB, /usr/openwin/lib/XErrorDB ... 100 NULL, 101 "X_CreateWindow", 102 "X_ChangeWindowAttributes", 103 "X_GetWindowAttributes", 104 "X_DestroyWindow", 105 "X_DestroySubwindows", 106 "X_ChangeSaveSet", 107 "X_ReparentWindow", 108 "X_MapWindow", 109 "X_MapSubwindows", 110 "X_UnmapWindow", 111 "X_UnmapSubwindows", 112 "X_ConfigureWindow", 113 "X_CirculateWindow", 114 "X_GetGeometry", 115 "X_QueryTree", 116 "X_InternAtom", 117 "X_GetAtomName", 118 "X_ChangeProperty", 119 "X_DeleteProperty", 120 "X_GetProperty", 121 "X_ListProperties", 122 "X_SetSelectionOwner", 123 "X_GetSelectionOwner", 124 "X_ConvertSelection", 125 "X_SendEvent", 126 "X_GrabPointer", 127 "X_UngrabPointer", 128 "X_GrabButton", 129 "X_UngrabButton", 130 "X_ChangeActivePointerGrab", 131 "X_GrabKeyboard", 132 "X_UngrabKeyboard", 133 "X_GrabKey", 134 "X_UngrabKey", 135 "X_AllowEvents", 136 "X_GrabServer", 137 "X_UngrabServer", 138 "X_QueryPointer", 139 "X_GetMotionEvents", 140 "X_TranslateCoords", 141 "X_WarpPointer", 142 "X_SetInputFocus", 143 "X_GetInputFocus", 144 "X_QueryKeymap", 145 "X_OpenFont", 146 "X_CloseFont", 147 "X_QueryFont", 148 "X_QueryTextExtents", 149 "X_ListFonts", 150 "X_ListFontsWithInfo", 151 "X_SetFontPath", 152 "X_GetFontPath", 153 "X_CreatePixmap", 154 "X_FreePixmap", 155 "X_CreateGC", 156 "X_ChangeGC", 157 "X_CopyGC", 158 "X_SetDashes", 159 "X_SetClipRectangles", 160 "X_FreeGC", 161 "X_ClearArea", 162 "X_CopyArea", 163 "X_CopyPlane", 164 "X_PolyPoint", 165 "X_PolyLine", 166 "X_PolySegment", 167 "X_PolyRectangle", 168 "X_PolyArc", 169 "X_FillPoly", 170 "X_PolyFillRectangle", 171 "X_PolyFillArc", 172 "X_PutImage", 173 "X_GetImage", 174 "X_PolyText8", 175 "X_PolyText16", 176 "X_ImageText8", 177 "X_ImageText16", 178 "X_CreateColormap", 179 "X_FreeColormap", 180 "X_CopyColormapAndFree", 181 "X_InstallColormap", 182 "X_UninstallColormap", 183 "X_ListInstalledColormaps", 184 "X_AllocColor", 185 "X_AllocNamedColor", 186 "X_AllocColorCells", 187 "X_AllocColorPlanes", 188 "X_FreeColors", 189 "X_StoreColors", 190 "X_StoreNamedColor", 191 "X_QueryColors", 192 "X_LookupColor", 193 "X_CreateCursor", 194 "X_CreateGlyphCursor", 195 "X_FreeCursor", 196 "X_RecolorCursor", 197 "X_QueryBestSize", 198 "X_QueryExtension", 199 "X_ListExtensions", 200 "X_ChangeKeyboardMapping", 201 "X_GetKeyboardMapping", 202 "X_ChangeKeyboardControl", 203 "X_GetKeyboardControl", 204 "X_Bell", 205 "X_ChangePointerControl", 206 "X_GetPointerControl", 207 "X_SetScreenSaver", 208 "X_GetScreenSaver", 209 "X_ChangeHosts", 210 "X_ListHosts", 211 "X_SetAccessControl", 212 "X_SetCloseDownMode", 213 "X_KillClient", 214 "X_RotateProperties", 215 "X_ForceScreenSaver", 216 "X_SetPointerMapping", 217 "X_GetPointerMapping", 218 "X_SetModifierMapping", 219 "X_GetModifierMapping", 220 NULL, 221 NULL, 222 NULL, 223 NULL, 224 NULL, 225 NULL, 226 NULL, 227 "X_NoOperation" 228 }; 229 230 // -=-= C statics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 231 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 232 233 int X11SalData::XErrorHdl( Display *pDisplay, XErrorEvent *pEvent ) 234 { 235 GetX11SalData()->XError( pDisplay, pEvent ); 236 return 0; 237 } 238 239 int X11SalData::XIOErrorHdl( Display * ) 240 { 241 /* #106197# hack: until a real shutdown procedure exists 242 * _exit ASAP 243 */ 244 if( ImplGetSVData()->maAppData.mbAppQuit ) 245 _exit(1); 246 247 // really bad hack 248 if( ! SessionManagerClient::checkDocumentsSaved() ) 249 /* oslSignalAction eToDo = */ osl_raiseSignal (OSL_SIGNAL_USER_X11SUBSYSTEMERROR, NULL); 250 251 std::fprintf( stderr, "X IO Error\n" ); 252 std::fflush( stdout ); 253 std::fflush( stderr ); 254 255 /* #106197# the same reasons to use _exit instead of exit in salmain 256 * do apply here. Since there is nothing to be done after an XIO 257 * error we have to _exit immediately. 258 */ 259 _exit(0); 260 return 0; 261 } 262 263 // -=-= SalData =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 264 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 265 #include <pthread.h> 266 267 X11SalData::X11SalData() 268 { 269 bNoExceptions_ = !!getenv( "SAL_NOSEGV" ); 270 271 pXLib_ = NULL; 272 m_pSalDisplay = NULL; 273 m_pInstance = NULL; 274 m_pPlugin = NULL; 275 276 hMainThread_ = pthread_self(); 277 osl_getLocalHostname( &maLocalHostName.pData ); 278 } 279 280 X11SalData::~X11SalData() 281 { 282 DeleteDisplay(); 283 } 284 285 void X11SalData::DeleteDisplay() 286 { 287 delete m_pSalDisplay; 288 m_pSalDisplay = NULL; 289 delete pXLib_; 290 pXLib_ = NULL; 291 } 292 293 void X11SalData::Init() 294 { 295 pXLib_ = new SalXLib(); 296 pXLib_->Init(); 297 } 298 299 void X11SalData::initNWF( void ) 300 { 301 } 302 303 void X11SalData::deInitNWF( void ) 304 { 305 } 306 307 // -=-= SalXLib =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 308 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 309 SalXLib::SalXLib() 310 { 311 m_aTimeout.tv_sec = 0; 312 m_aTimeout.tv_usec = 0; 313 m_nTimeoutMS = 0; 314 315 nFDs_ = 0; 316 FD_ZERO( &aReadFDS_ ); 317 FD_ZERO( &aExceptionFDS_ ); 318 319 m_pTimeoutFDS[0] = m_pTimeoutFDS[1] = -1; 320 if (pipe (m_pTimeoutFDS) != -1) 321 { 322 // initialize 'wakeup' pipe. 323 int flags; 324 325 // set close-on-exec descriptor flag. 326 if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFD)) != -1) 327 { 328 flags |= FD_CLOEXEC; 329 fcntl (m_pTimeoutFDS[0], F_SETFD, flags); 330 } 331 if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFD)) != -1) 332 { 333 flags |= FD_CLOEXEC; 334 fcntl (m_pTimeoutFDS[1], F_SETFD, flags); 335 } 336 337 // set non-blocking I/O flag. 338 if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFL)) != -1) 339 { 340 flags |= O_NONBLOCK; 341 fcntl (m_pTimeoutFDS[0], F_SETFL, flags); 342 } 343 if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFL)) != -1) 344 { 345 flags |= O_NONBLOCK; 346 fcntl (m_pTimeoutFDS[1], F_SETFL, flags); 347 } 348 349 // insert [0] into read descriptor set. 350 FD_SET( m_pTimeoutFDS[0], &aReadFDS_ ); 351 nFDs_ = m_pTimeoutFDS[0] + 1; 352 } 353 354 m_bHaveSystemChildFrames = false; 355 m_aOrigXIOErrorHandler = XSetIOErrorHandler ( (XIOErrorHandler)X11SalData::XIOErrorHdl ); 356 PushXErrorLevel( !!getenv( "SAL_IGNOREXERRORS" ) ); 357 } 358 359 SalXLib::~SalXLib() 360 { 361 // close 'wakeup' pipe. 362 close (m_pTimeoutFDS[0]); 363 close (m_pTimeoutFDS[1]); 364 365 PopXErrorLevel(); 366 XSetIOErrorHandler (m_aOrigXIOErrorHandler); 367 } 368 369 void SalXLib::PushXErrorLevel( bool bIgnore ) 370 { 371 m_aXErrorHandlerStack.push_back( XErrorStackEntry() ); 372 XErrorStackEntry& rEnt = m_aXErrorHandlerStack.back(); 373 rEnt.m_bWas = false; 374 rEnt.m_bIgnore = bIgnore; 375 rEnt.m_nLastErrorRequest = 0; 376 rEnt.m_aHandler = XSetErrorHandler( (XErrorHandler)X11SalData::XErrorHdl ); 377 } 378 379 void SalXLib::PopXErrorLevel() 380 { 381 if( m_aXErrorHandlerStack.size() ) 382 { 383 XSetErrorHandler( m_aXErrorHandlerStack.back().m_aHandler ); 384 m_aXErrorHandlerStack.pop_back(); 385 } 386 } 387 388 void SalXLib::Init() 389 { 390 SalI18N_InputMethod* pInputMethod = new SalI18N_InputMethod; 391 pInputMethod->SetLocale(); 392 XrmInitialize(); 393 394 /* 395 * open connection to X11 Display 396 * try in this order: 397 * o -display command line parameter, 398 * o $DISPLAY environment variable 399 * o default display 400 */ 401 402 Display *pDisp = NULL; 403 404 // is there a -display command line parameter? 405 vos::OExtCommandLine aCommandLine; 406 sal_uInt32 nParams = aCommandLine.getCommandArgCount(); 407 rtl::OUString aParam; 408 rtl::OString aDisplay; 409 for (sal_uInt16 i=0; i<nParams; i++) 410 { 411 aCommandLine.getCommandArg(i, aParam); 412 if (aParam.equalsAscii("-display")) 413 { 414 aCommandLine.getCommandArg(i+1, aParam); 415 aDisplay = rtl::OUStringToOString( 416 aParam, osl_getThreadTextEncoding()); 417 418 if ((pDisp = XOpenDisplay(aDisplay.getStr()))!=NULL) 419 { 420 /* 421 * if a -display switch was used, we need 422 * to set the environment accoringly since 423 * the clipboard build another connection 424 * to the xserver using $DISPLAY 425 */ 426 rtl::OUString envVar(RTL_CONSTASCII_USTRINGPARAM("DISPLAY")); 427 osl_setEnvironment(envVar.pData, aParam.pData); 428 } 429 break; 430 } 431 } 432 433 if (!pDisp && !aDisplay.getLength()) 434 { 435 // Open $DISPLAY or default... 436 char *pDisplay = getenv("DISPLAY"); 437 if (pDisplay != NULL) 438 aDisplay = rtl::OString(pDisplay); 439 pDisp = XOpenDisplay(pDisplay); 440 } 441 442 if ( !pDisp ) 443 { 444 rtl::OUString aProgramFileURL; 445 osl_getExecutableFile( &aProgramFileURL.pData ); 446 rtl::OUString aProgramSystemPath; 447 osl_getSystemPathFromFileURL (aProgramFileURL.pData, &aProgramSystemPath.pData); 448 rtl::OString aProgramName = rtl::OUStringToOString( 449 aProgramSystemPath, 450 osl_getThreadTextEncoding() ); 451 std::fprintf( stderr, "%s X11 error: Can't open display: %s\n", 452 aProgramName.getStr(), aDisplay.getStr()); 453 std::fprintf( stderr, " Set DISPLAY environment variable, use -display option\n"); 454 std::fprintf( stderr, " or check permissions of your X-Server\n"); 455 std::fprintf( stderr, " (See \"man X\" resp. \"man xhost\" for details)\n"); 456 std::fflush( stderr ); 457 exit(0); 458 } 459 460 SalDisplay *pSalDisplay = new SalX11Display( pDisp ); 461 462 pInputMethod->CreateMethod( pDisp ); 463 pInputMethod->AddConnectionWatch( pDisp, (void*)this ); 464 pSalDisplay->SetInputMethod( pInputMethod ); 465 466 PushXErrorLevel( true ); 467 SalI18N_KeyboardExtension *pKbdExtension = new SalI18N_KeyboardExtension( pDisp ); 468 XSync( pDisp, False ); 469 470 pKbdExtension->UseExtension( ! HasXErrorOccured() ); 471 PopXErrorLevel(); 472 473 pSalDisplay->SetKbdExtension( pKbdExtension ); 474 } 475 476 extern "C" { 477 void EmitFontpathWarning( void ) 478 { 479 static Bool bOnce = False; 480 if ( !bOnce ) 481 { 482 bOnce = True; 483 std::fprintf( stderr, "Please verify your fontpath settings\n" 484 "\t(See \"man xset\" for details" 485 " or ask your system administrator)\n" ); 486 } 487 } 488 489 } /* extern "C" */ 490 491 static void PrintXError( Display *pDisplay, XErrorEvent *pEvent ) 492 { 493 char msg[ 120 ] = ""; 494 #if ! ( defined LINUX && defined PPC ) 495 XGetErrorText( pDisplay, pEvent->error_code, msg, sizeof( msg ) ); 496 #endif 497 std::fprintf( stderr, "X-Error: %s\n", msg ); 498 if( pEvent->request_code < capacityof( XRequest ) ) 499 { 500 const char* pName = XRequest[pEvent->request_code]; 501 if( !pName ) 502 pName = "BadRequest?"; 503 std::fprintf( stderr, "\tMajor opcode: %d (%s)\n", pEvent->request_code, pName ); 504 } 505 else 506 { 507 std::fprintf( stderr, "\tMajor opcode: %d\n", pEvent->request_code ); 508 // TODO: also display extension name? 509 std::fprintf( stderr, "\tMinor opcode: %d\n", pEvent->minor_code ); 510 } 511 512 std::fprintf( stderr, "\tResource ID: 0x%lx\n", 513 pEvent->resourceid ); 514 std::fprintf( stderr, "\tSerial No: %ld (%ld)\n", 515 pEvent->serial, LastKnownRequestProcessed(pDisplay) ); 516 517 if( !getenv( "SAL_SYNCHRONIZE" ) ) 518 { 519 std::fprintf( stderr, "These errors are reported asynchronously,\n"); 520 std::fprintf( stderr, "set environment variable SAL_SYNCHRONIZE to 1 to help debugging\n"); 521 } 522 523 std::fflush( stdout ); 524 std::fflush( stderr ); 525 } 526 527 void SalXLib::XError( Display *pDisplay, XErrorEvent *pEvent ) 528 { 529 if( m_bHaveSystemChildFrames ) 530 return; 531 532 if( ! m_aXErrorHandlerStack.back().m_bIgnore ) 533 { 534 if ( (pEvent->error_code == BadAlloc) 535 && (pEvent->request_code == X_OpenFont) ) 536 { 537 static Bool bOnce = False; 538 if ( !bOnce ) 539 { 540 std::fprintf(stderr, "X-Error occured in a request for X_OpenFont\n"); 541 EmitFontpathWarning(); 542 543 bOnce = True ; 544 } 545 return; 546 } 547 /* ignore 548 * X_SetInputFocus: it's a hint only anyway 549 * X_GetProperty: this is part of the XGetWindowProperty call and will 550 * be handled by the return value of that function 551 */ 552 else if( pEvent->request_code == X_SetInputFocus || 553 pEvent->request_code == X_GetProperty 554 ) 555 return; 556 557 558 if( pDisplay != GetX11SalData()->GetDisplay()->GetDisplay() ) 559 return; 560 561 PrintXError( pDisplay, pEvent ); 562 563 oslSignalAction eToDo = osl_raiseSignal (OSL_SIGNAL_USER_X11SUBSYSTEMERROR, NULL); 564 switch (eToDo) 565 { 566 case osl_Signal_ActIgnore : 567 return; 568 case osl_Signal_ActAbortApp : 569 abort(); 570 case osl_Signal_ActKillApp : 571 exit(0); 572 case osl_Signal_ActCallNextHdl : 573 break; 574 default : 575 break; 576 } 577 578 } 579 580 m_aXErrorHandlerStack.back().m_bWas = true; 581 } 582 583 struct YieldEntry 584 { 585 YieldEntry* next; // pointer to next entry 586 int fd; // file descriptor for reading 587 void* data; // data for predicate and callback 588 YieldFunc pending; // predicate (determins pending events) 589 YieldFunc queued; // read and queue up events 590 YieldFunc handle; // handle pending events 591 592 inline int HasPendingEvent() const { return pending( fd, data ); } 593 inline int IsEventQueued() const { return queued( fd, data ); } 594 inline void HandleNextEvent() const { handle( fd, data ); } 595 }; 596 597 #define MAX_NUM_DESCRIPTORS 128 598 599 static YieldEntry yieldTable[ MAX_NUM_DESCRIPTORS ]; 600 601 void SalXLib::Insert( int nFD, void* data, 602 YieldFunc pending, 603 YieldFunc queued, 604 YieldFunc handle ) 605 { 606 DBG_ASSERT( nFD, "can not insert stdin descriptor" ); 607 DBG_ASSERT( !yieldTable[nFD].fd, "SalXLib::Insert fd twice" ); 608 609 yieldTable[nFD].fd = nFD; 610 yieldTable[nFD].data = data; 611 yieldTable[nFD].pending = pending; 612 yieldTable[nFD].queued = queued; 613 yieldTable[nFD].handle = handle; 614 615 FD_SET( nFD, &aReadFDS_ ); 616 FD_SET( nFD, &aExceptionFDS_ ); 617 618 if( nFD >= nFDs_ ) 619 nFDs_ = nFD + 1; 620 } 621 622 void SalXLib::Remove( int nFD ) 623 { 624 FD_CLR( nFD, &aReadFDS_ ); 625 FD_CLR( nFD, &aExceptionFDS_ ); 626 627 yieldTable[nFD].fd = 0; 628 629 if ( nFD == nFDs_ ) 630 { 631 for ( nFD = nFDs_ - 1; 632 nFD >= 0 && !yieldTable[nFD].fd; 633 nFD-- ) ; 634 635 nFDs_ = nFD + 1; 636 } 637 } 638 639 bool SalXLib::CheckTimeout( bool bExecuteTimers ) 640 { 641 bool bRet = false; 642 if( m_aTimeout.tv_sec ) // timer is started 643 { 644 timeval aTimeOfDay; 645 gettimeofday( &aTimeOfDay, 0 ); 646 if( aTimeOfDay >= m_aTimeout ) 647 { 648 bRet = true; 649 if( bExecuteTimers ) 650 { 651 // timed out, update timeout 652 m_aTimeout = aTimeOfDay; 653 /* 654 * #107827# autorestart immediately, will be stopped (or set 655 * to different value in notify hdl if necessary; 656 * CheckTimeout should return false while 657 * timers are being dispatched. 658 */ 659 m_aTimeout += m_nTimeoutMS; 660 // notify 661 GetX11SalData()->Timeout(); 662 } 663 } 664 } 665 return bRet; 666 } 667 668 void SalXLib::Yield( bool bWait, bool bHandleAllCurrentEvents ) 669 { 670 // check for timeouts here if you want to make screenshots 671 static char* p_prioritize_timer = getenv ("SAL_HIGHPRIORITY_REPAINT"); 672 if (p_prioritize_timer != NULL) 673 CheckTimeout(); 674 675 const int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1; 676 677 // first, check for already queued events. 678 for ( int nFD = 0; nFD < nFDs_; nFD++ ) 679 { 680 YieldEntry* pEntry = &(yieldTable[nFD]); 681 if ( pEntry->fd ) 682 { 683 DBG_ASSERT( nFD == pEntry->fd, "wrong fd in Yield()" ); 684 for( int i = 0; i < nMaxEvents && pEntry->HasPendingEvent(); i++ ) 685 { 686 pEntry->HandleNextEvent(); 687 if( ! bHandleAllCurrentEvents ) 688 return; 689 } 690 } 691 } 692 693 // next, select with or without timeout according to bWait. 694 int nFDs = nFDs_; 695 fd_set ReadFDS = aReadFDS_; 696 fd_set ExceptionFDS = aExceptionFDS_; 697 int nFound = 0; 698 699 timeval Timeout = noyield__; 700 timeval *pTimeout = &Timeout; 701 702 if (bWait) 703 { 704 pTimeout = 0; 705 if (m_aTimeout.tv_sec) // Timer is started. 706 { 707 // determine remaining timeout. 708 gettimeofday (&Timeout, 0); 709 Timeout = m_aTimeout - Timeout; 710 if (yield__ >= Timeout) 711 { 712 // guard against micro timeout. 713 Timeout = yield__; 714 } 715 pTimeout = &Timeout; 716 } 717 } 718 719 { 720 // release YieldMutex (and re-acquire at block end) 721 YieldMutexReleaser aReleaser; 722 nFound = select( nFDs, &ReadFDS, NULL, &ExceptionFDS, pTimeout ); 723 } 724 if( nFound < 0 ) // error 725 { 726 #ifdef DBG_UTIL 727 std::fprintf( stderr, "SalXLib::Yield e=%d f=%d\n", errno, nFound ); 728 #endif 729 if( EINTR == errno ) 730 { 731 errno = 0; 732 } 733 } 734 735 // usually handle timeouts here (as in 5.2) 736 if (p_prioritize_timer == NULL) 737 CheckTimeout(); 738 739 // handle wakeup events. 740 if ((nFound > 0) && (FD_ISSET(m_pTimeoutFDS[0], &ReadFDS))) 741 { 742 int buffer; 743 while (read (m_pTimeoutFDS[0], &buffer, sizeof(buffer)) > 0) 744 continue; 745 nFound -= 1; 746 } 747 748 // handle other events. 749 if( nFound > 0 ) 750 { 751 // now we are in the protected section ! 752 // recall select if we have acquired fd's, ready for reading, 753 754 struct timeval noTimeout = { 0, 0 }; 755 nFound = select( nFDs_, &ReadFDS, NULL, 756 &ExceptionFDS, &noTimeout ); 757 758 // someone-else has done the job for us 759 if (nFound == 0) 760 return; 761 762 for ( int nFD = 0; nFD < nFDs_; nFD++ ) 763 { 764 YieldEntry* pEntry = &(yieldTable[nFD]); 765 if ( pEntry->fd ) 766 { 767 if ( FD_ISSET( nFD, &ExceptionFDS ) ) { 768 #if OSL_DEBUG_LEVEL > 1 769 std::fprintf( stderr, "SalXLib::Yield exception\n" ); 770 #endif 771 nFound--; 772 } 773 if ( FD_ISSET( nFD, &ReadFDS ) ) 774 { 775 for( int i = 0; pEntry->IsEventQueued() && i < nMaxEvents; i++ ) 776 { 777 pEntry->HandleNextEvent(); 778 // if a recursive call has done the job 779 // so abort here 780 } 781 nFound--; 782 } 783 } 784 } 785 } 786 } 787 788 void SalXLib::Wakeup() 789 { 790 write (m_pTimeoutFDS[1], "", 1); 791 } 792 793 void SalXLib::PostUserEvent() 794 { 795 Wakeup(); 796 } 797 798 const char* X11SalData::getFrameResName() 799 { 800 /* according to ICCCM: 801 * first search command line for -name parameter 802 * then try RESOURCE_NAME environment variable 803 * then use argv[0] stripped by directories 804 */ 805 static rtl::OStringBuffer aResName; 806 if( !aResName.getLength() ) 807 { 808 int nArgs = osl_getCommandArgCount(); 809 for( int n = 0; n < nArgs-1; n++ ) 810 { 811 rtl::OUString aArg; 812 if( ! osl_getCommandArg( n, &aArg.pData ) && 813 aArg.equalsIgnoreAsciiCaseAscii( "-name" ) && 814 ! osl_getCommandArg( n+1, &aArg.pData ) ) 815 { 816 aResName.append( rtl::OUStringToOString( aArg, osl_getThreadTextEncoding() ) ); 817 break; 818 } 819 } 820 if( !aResName.getLength() ) 821 { 822 const char* pEnv = getenv( "RESOURCE_NAME" ); 823 if( pEnv && *pEnv ) 824 aResName.append( pEnv ); 825 } 826 if( !aResName.getLength() ) 827 aResName.append( "VCLSalFrame" ); 828 } 829 return aResName.getStr(); 830 } 831 832 const char* X11SalData::getFrameClassName() 833 { 834 static rtl::OStringBuffer aClassName; 835 if( !aClassName.getLength() ) 836 { 837 rtl::OUString aIni, aProduct; 838 rtl::Bootstrap::get( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BRAND_BASE_DIR" ) ), aIni ); 839 aIni += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/program/" SAL_CONFIGFILE( "bootstrap" ) ) ); 840 rtl::Bootstrap aBootstrap( aIni ); 841 aBootstrap.getFrom( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ProductKey" ) ), aProduct ); 842 843 if( aProduct.getLength() ) 844 aClassName.append( rtl::OUStringToOString( aProduct, osl_getThreadTextEncoding() ) ); 845 else 846 aClassName.append( "VCLSalFrame" ); 847 } 848 return aClassName.getStr(); 849 } 850 851 rtl::OString X11SalData::getFrameResName( SalExtStyle nStyle ) 852 { 853 rtl::OStringBuffer aBuf( 64 ); 854 aBuf.append( getFrameResName() ); 855 if( (nStyle & SAL_FRAME_EXT_STYLE_DOCUMENT) ) 856 aBuf.append( ".DocumentWindow" ); 857 858 return aBuf.makeStringAndClear(); 859 } 860