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
XErrorHdl(Display * pDisplay,XErrorEvent * pEvent)229 int X11SalData::XErrorHdl( Display *pDisplay, XErrorEvent *pEvent )
230 {
231 GetX11SalData()->XError( pDisplay, pEvent );
232 return 0;
233 }
234
XIOErrorHdl(Display *)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
X11SalData()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
~X11SalData()276 X11SalData::~X11SalData()
277 {
278 DeleteDisplay();
279 }
280
DeleteDisplay()281 void X11SalData::DeleteDisplay()
282 {
283 delete m_pSalDisplay;
284 m_pSalDisplay = NULL;
285 delete pXLib_;
286 pXLib_ = NULL;
287 }
288
Init()289 void X11SalData::Init()
290 {
291 pXLib_ = new SalXLib();
292 pXLib_->Init();
293 }
294
initNWF(void)295 void X11SalData::initNWF( void )
296 {
297 }
298
deInitNWF(void)299 void X11SalData::deInitNWF( void )
300 {
301 }
302
303 // -=-= SalXLib =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
304 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SalXLib()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
~SalXLib()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
PushXErrorLevel(bool bIgnore)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
PopXErrorLevel()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
Init()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" {
EmitFontpathWarning(void)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
PrintXError(Display * pDisplay,XErrorEvent * pEvent)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
XError(Display * pDisplay,XErrorEvent * pEvent)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 occurred 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 (determines pending events)
585 YieldFunc queued; // read and queue up events
586 YieldFunc handle; // handle pending events
587
HasPendingEventYieldEntry588 inline int HasPendingEvent() const { return pending( fd, data ); }
IsEventQueuedYieldEntry589 inline int IsEventQueued() const { return queued( fd, data ); }
HandleNextEventYieldEntry590 inline void HandleNextEvent() const { handle( fd, data ); }
591 };
592
593 #define MAX_NUM_DESCRIPTORS 128
594
595 static YieldEntry yieldTable[ MAX_NUM_DESCRIPTORS ];
596
Insert(int nFD,void * data,YieldFunc pending,YieldFunc queued,YieldFunc handle)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
Remove(int nFD)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
CheckTimeout(bool bExecuteTimers)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
Yield(bool bWait,bool bHandleAllCurrentEvents)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
Wakeup()784 void SalXLib::Wakeup()
785 {
786 write (m_pTimeoutFDS[1], "", 1);
787 }
788
PostUserEvent()789 void SalXLib::PostUserEvent()
790 {
791 Wakeup();
792 }
793
getFrameResName()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
getFrameClassName()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
getFrameResName(SalExtStyle nStyle)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