update dev300-m58
[ooovba.git] / vcl / unx / source / app / sm.cxx
blobb9ed5ed8e7f17c6bf4b48d54c0940c8a4a7afe32
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sm.cxx,v $
10 * $Revision: 1.33.90.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <string.h>
34 #include <unistd.h>
35 #include <sys/poll.h>
36 #include <fcntl.h>
38 #include <stdio.h>
40 #include <osl/process.h>
41 #include <osl/security.h>
43 #include <tools/prex.h>
44 #include <X11/Xatom.h>
45 #include <tools/postx.h>
46 #include <sm.hxx>
47 #include <saldata.hxx>
48 #include <saldisp.hxx>
49 #include <salframe.h>
50 #include <vcl/svapp.hxx>
51 #include <vcl/window.hxx>
52 #include <salinst.h>
54 #include <osl/conditn.h>
56 #define USE_SM_EXTENSION
58 #if OSL_DEBUG_LEVEL > 1
59 #include <cstdarg>
60 static bool bFirstAssert = true;
61 #endif
63 #if OSL_DEBUG_LEVEL > 1
64 inline void SMprintf( const char* pFormat, ... )
65 #else
66 inline void SMprintf( const char*, ... )
67 #endif
69 #if OSL_DEBUG_LEVEL > 1
70 FILE* fp = fopen( "/tmp/sessionlog.txt", bFirstAssert ? "w" : "a" );
71 if(!fp) return;
72 bFirstAssert = false;
73 std::va_list ap;
74 va_start( ap, pFormat );
75 vfprintf( fp, pFormat, ap );
76 fclose( fp );
77 va_end( ap );
78 #endif
81 static IceSalSession* pOneInstance = NULL;
83 SalSession* X11SalInstance::CreateSalSession()
85 if( ! pOneInstance )
86 pOneInstance = new IceSalSession();
87 return pOneInstance;
91 * class IceSalSession
94 static X11SalFrame* pOldStyleSaveFrame = NULL;
96 IceSalSession::IceSalSession()
100 IceSalSession::~IceSalSession()
102 if( pOneInstance == this )
103 pOneInstance = NULL;
106 void IceSalSession::queryInteraction()
108 if( ! SessionManagerClient::queryInteraction() )
110 SalSessionInteractionEvent aEvent( false );
111 CallCallback( &aEvent );
115 void IceSalSession::interactionDone( bool bCancelShutdown )
117 SessionManagerClient::interactionDone( bCancelShutdown );
120 void IceSalSession::saveDone()
122 SessionManagerClient::saveDone();
123 if( pOldStyleSaveFrame )
125 // note: does nothing if not running in generic plugin
126 X11SalFrame::SaveYourselfDone( pOldStyleSaveFrame );
130 void IceSalSession::handleOldX11SaveYourself( SalFrame* pFrame )
132 // do this only once
133 if( ! pOldStyleSaveFrame )
135 pOldStyleSaveFrame = static_cast<X11SalFrame*>(pFrame);
136 if( pOneInstance )
138 SalSessionSaveRequestEvent aEvent( true, false );
139 pOneInstance->CallCallback( &aEvent );
144 extern "C" void SAL_CALL ICEConnectionWorker( void* );
146 class ICEConnectionObserver
148 friend void SAL_CALL ICEConnectionWorker(void*);
149 static BOOL bIsWatching;
150 static void ICEWatchProc( IceConn connection, IcePointer client_data,
151 Bool opening, IcePointer* watch_data );
153 static struct pollfd* pFilehandles;
154 static IceConn* pConnections;
155 static int nConnections;
156 static int nWakeupFiles[2];
157 static oslMutex ICEMutex;
158 static oslThread ICEThread;
159 public:
161 static void activate();
162 static void deactivate();
163 static void lock();
164 static void unlock();
165 static void wakeup();
169 SmcConn SessionManagerClient::aSmcConnection = NULL;
170 ByteString SessionManagerClient::aClientID;
171 BOOL ICEConnectionObserver::bIsWatching = FALSE;
172 struct pollfd* ICEConnectionObserver::pFilehandles = NULL;
173 IceConn* ICEConnectionObserver::pConnections = NULL;
174 int ICEConnectionObserver::nConnections = 0;
175 oslMutex ICEConnectionObserver::ICEMutex = NULL;
176 oslThread ICEConnectionObserver::ICEThread = NULL;
177 int ICEConnectionObserver::nWakeupFiles[2] = { 0, 0 };
179 // HACK
180 bool SessionManagerClient::bDocSaveDone = false;
182 bool SessionManagerClient::bSaveDoneSent = false;
184 static SmProp* pSmProps = NULL;
185 static SmProp** ppSmProps = NULL;
186 static int nSmProps = 0;
187 static unsigned char *pSmRestartHint = NULL;
190 static void BuildSmPropertyList()
192 if( ! pSmProps )
194 ByteString aExec( SessionManagerClient::getExecName(), osl_getThreadTextEncoding() );
196 nSmProps = 5;
197 pSmProps = new SmProp[ nSmProps ];
199 pSmProps[ 0 ].name = const_cast<char*>(SmCloneCommand);
200 pSmProps[ 0 ].type = const_cast<char*>(SmLISTofARRAY8);
201 pSmProps[ 0 ].num_vals = 1;
202 pSmProps[ 0 ].vals = new SmPropValue;
203 pSmProps[ 0 ].vals->length = aExec.Len()+1;
204 pSmProps[ 0 ].vals->value = strdup( aExec.GetBuffer() );
206 pSmProps[ 1 ].name = const_cast<char*>(SmProgram);
207 pSmProps[ 1 ].type = const_cast<char*>(SmARRAY8);
208 pSmProps[ 1 ].num_vals = 1;
209 pSmProps[ 1 ].vals = new SmPropValue;
210 pSmProps[ 1 ].vals->length = aExec.Len()+1;
211 pSmProps[ 1 ].vals->value = strdup( aExec.GetBuffer() );
213 pSmProps[ 2 ].name = const_cast<char*>(SmRestartCommand);
214 pSmProps[ 2 ].type = const_cast<char*>(SmLISTofARRAY8);
215 pSmProps[ 2 ].num_vals = 3;
216 pSmProps[ 2 ].vals = new SmPropValue[3];
217 pSmProps[ 2 ].vals[0].length = aExec.Len()+1;
218 pSmProps[ 2 ].vals[0].value = strdup( aExec.GetBuffer() );
219 ByteString aRestartOption( "-session=" );
220 aRestartOption.Append( SessionManagerClient::getSessionID() );
221 pSmProps[ 2 ].vals[1].length = aRestartOption.Len()+1;
222 pSmProps[ 2 ].vals[1].value = strdup( aRestartOption.GetBuffer() );
223 ByteString aRestartOptionNoLogo( "-nologo" );
224 pSmProps[ 2 ].vals[2].length = aRestartOptionNoLogo.Len()+1;
225 pSmProps[ 2 ].vals[2].value = strdup( aRestartOptionNoLogo.GetBuffer() );
227 rtl::OUString aUserName;
228 rtl::OString aUser;
229 oslSecurity aSec = osl_getCurrentSecurity();
230 if( aSec )
232 osl_getUserName( aSec, &aUserName.pData );
233 aUser = rtl::OUStringToOString( aUserName, osl_getThreadTextEncoding() );
234 osl_freeSecurityHandle( aSec );
237 pSmProps[ 3 ].name = const_cast<char*>(SmUserID);
238 pSmProps[ 3 ].type = const_cast<char*>(SmARRAY8);
239 pSmProps[ 3 ].num_vals = 1;
240 pSmProps[ 3 ].vals = new SmPropValue;
241 pSmProps[ 3 ].vals->value = strdup( aUser.getStr() );
242 pSmProps[ 3 ].vals->length = strlen( (char *)pSmProps[ 3 ].vals->value )+1;
244 pSmProps[ 4 ].name = const_cast<char*>(SmRestartStyleHint);
245 pSmProps[ 4 ].type = const_cast<char*>(SmCARD8);
246 pSmProps[ 4 ].num_vals = 1;
247 pSmProps[ 4 ].vals = new SmPropValue;
248 pSmProps[ 4 ].vals->value = malloc(1);
249 pSmRestartHint = (unsigned char *)pSmProps[ 4 ].vals->value;
250 *pSmRestartHint = SmRestartIfRunning;
251 pSmProps[ 4 ].vals->length = 1;
253 ppSmProps = new SmProp*[ nSmProps ];
254 for( int i = 0; i < nSmProps; i++ )
255 ppSmProps[ i ] = &pSmProps[i];
259 bool SessionManagerClient::checkDocumentsSaved()
261 return bDocSaveDone;
264 struct SaveYourselfArgs {
265 bool bShutdown;
266 bool bFast;
267 int nInteractionStyle;
268 } aSaveYourselfArg;
270 IMPL_STATIC_LINK( SessionManagerClient, SaveYourselfHdl, void*, EMPTYARG )
272 SMprintf( "posting save documents event shutdown = %s\n", (pThis!=0) ? "true" : "false" );
274 static bool bFirstShutdown=true;
275 if (pThis != 0 && bFirstShutdown) //first shutdown request
277 bFirstShutdown = false;
279 If we have no actual frames open, e.g. we launched a quickstarter,
280 and then shutdown all our frames leaving just a quickstarter running,
281 then we don't want to launch an empty toplevel frame on the next
282 start. (The job of scheduling the restart of the quick-starter is a
283 task of the quick-starter)
285 *pSmRestartHint = SmRestartNever;
286 const std::list< SalFrame* >& rFrames = GetX11SalData()->GetDisplay()->getFrames();
287 for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
289 Window *pWindow = (*it)->GetWindow();
290 if (pWindow && pWindow->IsVisible())
292 *pSmRestartHint = SmRestartIfRunning;
293 break;
298 if( pOneInstance )
300 SalSessionSaveRequestEvent aEvent( aSaveYourselfArg.bShutdown, aSaveYourselfArg.nInteractionStyle == SmInteractStyleAny && !aSaveYourselfArg.bFast );
301 pOneInstance->CallCallback( &aEvent );
303 else
304 saveDone();
306 return 0;
309 IMPL_STATIC_LINK_NOINSTANCE( SessionManagerClient, InteractionHdl, void*, EMPTYARG )
311 SMprintf( "interaction link\n" );
313 if( pOneInstance )
315 SalSessionInteractionEvent aEvent( true );
316 pOneInstance->CallCallback( &aEvent );
319 return 0;
322 IMPL_STATIC_LINK_NOINSTANCE( SessionManagerClient, ShutDownCancelHdl, void*, EMPTYARG )
324 SMprintf( "shutdown cancel\n" );
325 if( pOneInstance )
327 SalSessionShutdownCancelEvent aEvent;
328 pOneInstance->CallCallback( &aEvent );
331 if( !bSaveDoneSent )
332 saveDone( false );
334 return 0;
337 void SessionManagerClient::SaveYourselfProc(
338 SmcConn,
339 SmPointer,
340 int save_type,
341 Bool shutdown,
342 int interact_style,
343 Bool fast
346 SMprintf( "Session: save yourself, save_type = %s, shutdown = %s, interact_style = %s, fast = %s\n",
347 save_type == SmSaveLocal ? "SmcSaveLocal" :
348 ( save_type == SmSaveGlobal ? "SmcSaveGlobal" :
349 ( save_type == SmSaveBoth ? "SmcSaveBoth" : "<unknown>" ) ),
350 shutdown ? "true" : "false",
351 interact_style == SmInteractStyleNone ? "SmInteractStyleNone" :
352 ( interact_style == SmInteractStyleErrors ? "SmInteractStyleErrors" :
353 ( interact_style == SmInteractStyleAny ? "SmInteractStyleAny" : "<unknown>" ) ),
354 fast ? "true" : "false"
356 bSaveDoneSent = false;
357 BuildSmPropertyList();
358 #ifdef USE_SM_EXTENSION
359 bDocSaveDone = false;
360 /* #i49875# some session managers send a "die" message if the
361 * saveDone does not come early enough for their convenience
362 * this can occasionally happen on startup, especially the first
363 * startup. So shortcut the "not shutting down" case since the
364 * upper layers are currently not interested in that event anyway.
366 if( ! shutdown )
368 SessionManagerClient::saveDone();
369 return;
372 aSaveYourselfArg.bShutdown = shutdown;
373 aSaveYourselfArg.nInteractionStyle = interact_style;
374 aSaveYourselfArg.bFast = fast;
375 Application::PostUserEvent( STATIC_LINK( NULL, SessionManagerClient, SaveYourselfHdl ) );
377 SMprintf( "waiting for save yourself event to be processed\n" );
378 #endif
381 IMPL_STATIC_LINK_NOINSTANCE( SessionManagerClient, ShutDownHdl, void*, EMPTYARG )
383 const std::list< SalFrame* >& rFrames = GetX11SalData()->GetDisplay()->getFrames();
384 SMprintf( rFrames.begin() != rFrames.end() ? "shutdown on first frame\n" : "shutdown event but no frame\n" );
385 if( rFrames.begin() != rFrames.end() )
386 rFrames.front()->CallCallback( SALEVENT_SHUTDOWN, 0 );
387 return 0;
390 void SessionManagerClient::DieProc(
391 SmcConn connection,
392 SmPointer
395 SMprintf( "Session: die\n" );
396 if( connection == aSmcConnection )
398 Application::PostUserEvent( STATIC_LINK( NULL, SessionManagerClient, ShutDownHdl ) );
399 SMprintf( "waiting for shutdown event to be processed\n" );
403 void SessionManagerClient::SaveCompleteProc(
404 SmcConn,
405 SmPointer
408 SMprintf( "Session: save complete\n" );
411 void SessionManagerClient::ShutdownCanceledProc(
412 SmcConn connection,
413 SmPointer )
415 SMprintf( "Session: shutdown canceled\n" );
416 if( connection == aSmcConnection )
417 Application::PostUserEvent( STATIC_LINK( NULL, SessionManagerClient, ShutDownCancelHdl ) );
420 void SessionManagerClient::InteractProc(
421 SmcConn connection,
422 SmPointer )
424 SMprintf( "Session: interaction request completed\n" );
425 if( connection == aSmcConnection )
426 Application::PostUserEvent( STATIC_LINK( NULL, SessionManagerClient, InteractionHdl ) );
429 void SessionManagerClient::saveDone( bool bSuccess )
431 if( aSmcConnection )
433 ICEConnectionObserver::lock();
434 if( bSuccess )
435 SmcSetProperties( aSmcConnection, nSmProps, ppSmProps );
436 SmcSaveYourselfDone( aSmcConnection, bSuccess );
437 SMprintf( "sent SaveYourselfDone SmRestartHint of %d\n", *pSmRestartHint );
438 bDocSaveDone = bSuccess;
439 bSaveDoneSent = true;
440 ICEConnectionObserver::unlock();
445 void SessionManagerClient::open()
447 static SmcCallbacks aCallbacks;
449 #ifdef USE_SM_EXTENSION
450 // this is the way Xt does it, so we can too
451 if( ! aSmcConnection && getenv( "SESSION_MANAGER" ) )
453 char aErrBuf[1024];
454 ICEConnectionObserver::activate();
455 ICEConnectionObserver::lock();
457 char* pClientID = NULL;
458 const ByteString& rPrevId( getPreviousSessionID() );
460 aCallbacks.save_yourself.callback = SaveYourselfProc;
461 aCallbacks.save_yourself.client_data = NULL;
462 aCallbacks.die.callback = DieProc;
463 aCallbacks.die.client_data = NULL;
464 aCallbacks.save_complete.callback = SaveCompleteProc;
465 aCallbacks.save_complete.client_data = NULL;
466 aCallbacks.shutdown_cancelled.callback = ShutdownCanceledProc;
467 aCallbacks.shutdown_cancelled.client_data = NULL;
468 aSmcConnection = SmcOpenConnection( NULL,
469 NULL,
470 SmProtoMajor,
471 SmProtoMinor,
472 SmcSaveYourselfProcMask |
473 SmcDieProcMask |
474 SmcSaveCompleteProcMask |
475 SmcShutdownCancelledProcMask ,
476 &aCallbacks,
477 rPrevId.Len() ? const_cast<char*>(rPrevId.GetBuffer()) : NULL,
478 &pClientID,
479 sizeof( aErrBuf ),
480 aErrBuf );
481 if( ! aSmcConnection )
482 SMprintf( "SmcOpenConnection failed: %s\n", aErrBuf );
483 else
484 SMprintf( "SmcOpenConnection succeeded, client ID is \"%s\"\n", pClientID );
485 aClientID = ByteString( pClientID );
486 free( pClientID );
487 pClientID = NULL;
488 ICEConnectionObserver::unlock();
490 SalDisplay* pDisp = GetX11SalData()->GetDisplay();
491 if( pDisp->GetDrawable( pDisp->GetDefaultScreenNumber() ) && aClientID.Len() )
493 XChangeProperty( pDisp->GetDisplay(),
494 pDisp->GetDrawable( pDisp->GetDefaultScreenNumber() ),
495 XInternAtom( pDisp->GetDisplay(), "SM_CLIENT_ID", False ),
496 XA_STRING,
498 PropModeReplace,
499 (unsigned char*)aClientID.GetBuffer(),
500 aClientID.Len()
504 else if( ! aSmcConnection )
505 SMprintf( "no SESSION_MANAGER\n" );
506 #endif
509 const ByteString& SessionManagerClient::getSessionID()
511 return aClientID;
514 void SessionManagerClient::close()
516 if( aSmcConnection )
518 #ifdef USE_SM_EXTENSION
519 ICEConnectionObserver::lock();
520 SMprintf( "attempting SmcCloseConnection\n" );
521 SmcCloseConnection( aSmcConnection, 0, NULL );
522 SMprintf( "SmcConnection closed\n" );
523 ICEConnectionObserver::unlock();
524 ICEConnectionObserver::deactivate();
525 #endif
526 aSmcConnection = NULL;
530 bool SessionManagerClient::queryInteraction()
532 bool bRet = false;
533 if( aSmcConnection )
535 ICEConnectionObserver::lock();
536 if( SmcInteractRequest( aSmcConnection, SmDialogNormal, InteractProc, NULL ) )
537 bRet = true;
538 ICEConnectionObserver::unlock();
540 return bRet;
543 void SessionManagerClient::interactionDone( bool bCancelShutdown )
545 if( aSmcConnection )
547 ICEConnectionObserver::lock();
548 SmcInteractDone( aSmcConnection, bCancelShutdown );
549 ICEConnectionObserver::unlock();
554 String SessionManagerClient::getExecName()
556 rtl::OUString aExec, aSysExec;
557 osl_getExecutableFile( &aExec.pData );
558 osl_getSystemPathFromFileURL( aExec.pData, &aSysExec.pData );
560 int nPos = aSysExec.indexOf( rtl::OUString::createFromAscii( ".bin" ) );
561 if( nPos != -1 )
562 aSysExec = aSysExec.copy( 0, nPos );
563 return aSysExec;
567 const ByteString& SessionManagerClient::getPreviousSessionID()
569 static ByteString aPrevId;
571 int nCommands = osl_getCommandArgCount();
572 for( int i = 0; i < nCommands; i++ )
574 ::rtl::OUString aArg;
575 osl_getCommandArg( i, &aArg.pData );
576 if( aArg.compareToAscii( "-session=", 9 ) == 0 )
578 aPrevId = ByteString( ::rtl::OUStringToOString( aArg.copy( 9 ), osl_getThreadTextEncoding() ) );
579 break;
582 SMprintf( "previous ID = \"%s\"\n", aPrevId.GetBuffer() );
583 return aPrevId;
586 void ICEConnectionObserver::lock()
588 osl_acquireMutex( ICEMutex );
591 void ICEConnectionObserver::unlock()
593 osl_releaseMutex( ICEMutex );
596 void ICEConnectionObserver::activate()
598 if( ! bIsWatching )
600 nWakeupFiles[0] = nWakeupFiles[1] = 0;
601 ICEMutex = osl_createMutex();
602 bIsWatching = TRUE;
603 #ifdef USE_SM_EXTENSION
604 IceAddConnectionWatch( ICEWatchProc, NULL );
605 #endif
609 void ICEConnectionObserver::deactivate()
611 if( bIsWatching )
613 lock();
614 bIsWatching = FALSE;
615 #ifdef USE_SM_EXTENSION
616 IceRemoveConnectionWatch( ICEWatchProc, NULL );
617 #endif
618 nConnections = 0;
619 if( ICEThread )
621 osl_terminateThread( ICEThread );
622 wakeup();
624 unlock();
625 if( ICEThread )
627 osl_joinWithThread( ICEThread );
628 osl_destroyThread( ICEThread );
629 close( nWakeupFiles[1] );
630 close( nWakeupFiles[0] );
631 ICEThread = NULL;
633 osl_destroyMutex( ICEMutex );
634 ICEMutex = NULL;
638 void ICEConnectionObserver::wakeup()
640 char cChar = 'w';
641 write( nWakeupFiles[1], &cChar, 1 );
644 void ICEConnectionWorker( void* )
646 #ifdef USE_SM_EXTENSION
647 while( osl_scheduleThread(ICEConnectionObserver::ICEThread) && ICEConnectionObserver::nConnections )
649 ICEConnectionObserver::lock();
650 int nConnectionsBefore = ICEConnectionObserver::nConnections;
651 int nBytes = sizeof( struct pollfd )*(nConnectionsBefore+1);
652 struct pollfd* pLocalFD = (struct pollfd*)rtl_allocateMemory( nBytes );
653 rtl_copyMemory( pLocalFD, ICEConnectionObserver::pFilehandles, nBytes );
654 ICEConnectionObserver::unlock();
656 int nRet = poll( pLocalFD,nConnectionsBefore+1,-1 );
657 bool bWakeup = (pLocalFD[0].revents & POLLIN);
658 rtl_freeMemory( pLocalFD );
660 if( nRet < 1 )
661 continue;
663 // clear wakeup pipe
664 if( bWakeup )
666 char buf[4];
667 while( read( ICEConnectionObserver::nWakeupFiles[0], buf, sizeof( buf ) ) > 0 )
669 SMprintf( "file handles active in wakeup: %d\n", nRet );
670 if( nRet == 1 )
671 continue;
674 // check fd's after we obtained the lock
675 ICEConnectionObserver::lock();
676 if( ICEConnectionObserver::nConnections > 0 && ICEConnectionObserver::nConnections == nConnectionsBefore )
678 nRet = poll( ICEConnectionObserver::pFilehandles+1, ICEConnectionObserver::nConnections, 0 );
679 if( nRet > 0 )
681 SMprintf( "IceProcessMessages\n" );
682 Bool bReply;
683 for( int i = 0; i < ICEConnectionObserver::nConnections; i++ )
684 if( ICEConnectionObserver::pFilehandles[i+1].revents & POLLIN )
685 IceProcessMessages( ICEConnectionObserver::pConnections[i], NULL, &bReply );
688 ICEConnectionObserver::unlock();
690 #endif
691 SMprintf( "shutting donw ICE dispatch thread\n" );
694 void ICEConnectionObserver::ICEWatchProc(
695 IceConn connection,
696 IcePointer,
697 Bool opening,
698 IcePointer*
701 // note: this is a callback function for ICE
702 // this implicitly means that a call into ICE lib is calling this
703 // so the ICEMutex MUST already be locked by the caller
705 #ifdef USE_SM_EXTENSION
706 if( opening )
708 int fd = IceConnectionNumber( connection );
709 nConnections++;
710 pConnections = (IceConn*)rtl_reallocateMemory( pConnections, sizeof( IceConn )*nConnections );
711 pFilehandles = (struct pollfd*)rtl_reallocateMemory( pFilehandles, sizeof( struct pollfd )*(nConnections+1) );
712 pConnections[ nConnections-1 ] = connection;
713 pFilehandles[ nConnections ].fd = fd;
714 pFilehandles[ nConnections ].events = POLLIN;
715 if( nConnections == 1 )
717 if( ! pipe( nWakeupFiles ) )
719 int flags;
720 pFilehandles[0].fd = nWakeupFiles[0];
721 pFilehandles[0].events = POLLIN;
722 // set close-on-exec and nonblock descriptor flag.
723 if ((flags = fcntl (nWakeupFiles[0], F_GETFD)) != -1)
725 flags |= FD_CLOEXEC;
726 fcntl (nWakeupFiles[0], F_SETFD, flags);
728 if ((flags = fcntl (nWakeupFiles[0], F_GETFL)) != -1)
730 flags |= O_NONBLOCK;
731 fcntl (nWakeupFiles[0], F_SETFL, flags);
733 // set close-on-exec and nonblock descriptor flag.
734 if ((flags = fcntl (nWakeupFiles[1], F_GETFD)) != -1)
736 flags |= FD_CLOEXEC;
737 fcntl (nWakeupFiles[1], F_SETFD, flags);
739 if ((flags = fcntl (nWakeupFiles[1], F_GETFL)) != -1)
741 flags |= O_NONBLOCK;
742 fcntl (nWakeupFiles[1], F_SETFL, flags);
744 ICEThread = osl_createSuspendedThread( ICEConnectionWorker, NULL );
745 osl_resumeThread( ICEThread );
749 else
751 for( int i = 0; i < nConnections; i++ )
753 if( pConnections[i] == connection )
755 if( i < nConnections-1 )
757 rtl_moveMemory( pConnections+i, pConnections+i+1, sizeof( IceConn )*(nConnections-i-1) );
758 rtl_moveMemory( pFilehandles+i+1, pFilehandles+i+2, sizeof( struct pollfd )*(nConnections-i-1) );
760 nConnections--;
761 pConnections = (IceConn*)rtl_reallocateMemory( pConnections, sizeof( IceConn )*nConnections );
762 pFilehandles = (struct pollfd*)rtl_reallocateMemory( pFilehandles, sizeof( struct pollfd )*(nConnections+1) );
763 break;
766 if( nConnections == 0 && ICEThread )
768 SMprintf( "terminating ICEThread\n" );
769 osl_terminateThread( ICEThread );
770 wakeup();
771 // must release the mutex here
772 osl_releaseMutex( ICEMutex );
773 osl_joinWithThread( ICEThread );
774 osl_destroyThread( ICEThread );
775 close( nWakeupFiles[1] );
776 close( nWakeupFiles[0] );
777 ICEThread = NULL;
780 SMprintf( "ICE connection on %d %s\n",
781 IceConnectionNumber( connection ),
782 opening ? "inserted" : "removed" );
783 SMprintf( "Display connection is %d\n", ConnectionNumber( GetX11SalData()->GetDisplay()->GetDisplay() ) );
784 #endif