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