xref: /aoo42x/main/vcl/unx/generic/app/sm.cxx (revision c82f2877)
1*c82f2877SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*c82f2877SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*c82f2877SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*c82f2877SAndrew Rist  * distributed with this work for additional information
6*c82f2877SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*c82f2877SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*c82f2877SAndrew Rist  * "License"); you may not use this file except in compliance
9*c82f2877SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*c82f2877SAndrew Rist  *
11*c82f2877SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*c82f2877SAndrew Rist  *
13*c82f2877SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*c82f2877SAndrew Rist  * software distributed under the License is distributed on an
15*c82f2877SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*c82f2877SAndrew Rist  * KIND, either express or implied.  See the License for the
17*c82f2877SAndrew Rist  * specific language governing permissions and limitations
18*c82f2877SAndrew Rist  * under the License.
19*c82f2877SAndrew Rist  *
20*c82f2877SAndrew Rist  *************************************************************/
21*c82f2877SAndrew Rist 
22*c82f2877SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir #include <string.h>
27cdf0e10cSrcweir #include <unistd.h>
28cdf0e10cSrcweir #include <sys/poll.h>
29cdf0e10cSrcweir #include <fcntl.h>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <stdio.h>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <osl/process.h>
34cdf0e10cSrcweir #include <osl/security.h>
35cdf0e10cSrcweir #include <osl/conditn.h>
36cdf0e10cSrcweir 
37cdf0e10cSrcweir #include <tools/prex.h>
38cdf0e10cSrcweir #include <X11/Xatom.h>
39cdf0e10cSrcweir #include <tools/postx.h>
40cdf0e10cSrcweir 
41cdf0e10cSrcweir #include <unx/sm.hxx>
42cdf0e10cSrcweir #include <unx/saldata.hxx>
43cdf0e10cSrcweir #include <unx/saldisp.hxx>
44cdf0e10cSrcweir #include <unx/salframe.h>
45cdf0e10cSrcweir #include <unx/salinst.h>
46cdf0e10cSrcweir 
47cdf0e10cSrcweir #include <vcl/svapp.hxx>
48cdf0e10cSrcweir #include <vcl/window.hxx>
49cdf0e10cSrcweir 
50cdf0e10cSrcweir #define USE_SM_EXTENSION
51cdf0e10cSrcweir 
52cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
53cdf0e10cSrcweir #include <cstdarg>
54cdf0e10cSrcweir static bool bFirstAssert = true;
55cdf0e10cSrcweir #endif
56cdf0e10cSrcweir 
57cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
SMprintf(const char * pFormat,...)58cdf0e10cSrcweir inline void SMprintf( const char* pFormat, ... )
59cdf0e10cSrcweir #else
60cdf0e10cSrcweir inline void SMprintf( const char*, ... )
61cdf0e10cSrcweir #endif
62cdf0e10cSrcweir {
63cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
64cdf0e10cSrcweir     FILE* fp = fopen( "/tmp/sessionlog.txt", bFirstAssert ? "w" : "a" );
65cdf0e10cSrcweir     if(!fp) return;
66cdf0e10cSrcweir     bFirstAssert = false;
67cdf0e10cSrcweir     std::va_list ap;
68cdf0e10cSrcweir     va_start( ap, pFormat );
69cdf0e10cSrcweir     vfprintf( fp, pFormat, ap );
70cdf0e10cSrcweir     fclose( fp );
71cdf0e10cSrcweir     va_end( ap );
72cdf0e10cSrcweir #endif
73cdf0e10cSrcweir };
74cdf0e10cSrcweir 
75cdf0e10cSrcweir static IceSalSession* pOneInstance = NULL;
76cdf0e10cSrcweir 
CreateSalSession()77cdf0e10cSrcweir SalSession* X11SalInstance::CreateSalSession()
78cdf0e10cSrcweir {
79cdf0e10cSrcweir     if( ! pOneInstance )
80cdf0e10cSrcweir         pOneInstance = new IceSalSession();
81cdf0e10cSrcweir     return pOneInstance;
82cdf0e10cSrcweir }
83cdf0e10cSrcweir 
84cdf0e10cSrcweir /*
85cdf0e10cSrcweir  *  class IceSalSession
86cdf0e10cSrcweir  */
87cdf0e10cSrcweir 
88cdf0e10cSrcweir static X11SalFrame* pOldStyleSaveFrame = NULL;
89cdf0e10cSrcweir 
IceSalSession()90cdf0e10cSrcweir IceSalSession::IceSalSession()
91cdf0e10cSrcweir {
92cdf0e10cSrcweir }
93cdf0e10cSrcweir 
~IceSalSession()94cdf0e10cSrcweir IceSalSession::~IceSalSession()
95cdf0e10cSrcweir {
96cdf0e10cSrcweir     if( pOneInstance == this )
97cdf0e10cSrcweir         pOneInstance = NULL;
98cdf0e10cSrcweir }
99cdf0e10cSrcweir 
queryInteraction()100cdf0e10cSrcweir void IceSalSession::queryInteraction()
101cdf0e10cSrcweir {
102cdf0e10cSrcweir     if( ! SessionManagerClient::queryInteraction() )
103cdf0e10cSrcweir     {
104cdf0e10cSrcweir         SalSessionInteractionEvent aEvent( false );
105cdf0e10cSrcweir         CallCallback( &aEvent );
106cdf0e10cSrcweir     }
107cdf0e10cSrcweir }
108cdf0e10cSrcweir 
interactionDone()109cdf0e10cSrcweir void IceSalSession::interactionDone()
110cdf0e10cSrcweir {
111cdf0e10cSrcweir     SessionManagerClient::interactionDone( false );
112cdf0e10cSrcweir }
113cdf0e10cSrcweir 
saveDone()114cdf0e10cSrcweir void IceSalSession::saveDone()
115cdf0e10cSrcweir {
116cdf0e10cSrcweir     SessionManagerClient::saveDone();
117cdf0e10cSrcweir     if( pOldStyleSaveFrame )
118cdf0e10cSrcweir     {
119cdf0e10cSrcweir         // note: does nothing if not running in generic plugin
120cdf0e10cSrcweir         X11SalFrame::SaveYourselfDone( pOldStyleSaveFrame );
121cdf0e10cSrcweir     }
122cdf0e10cSrcweir }
123cdf0e10cSrcweir 
cancelShutdown()124cdf0e10cSrcweir bool IceSalSession::cancelShutdown()
125cdf0e10cSrcweir {
126cdf0e10cSrcweir     SessionManagerClient::interactionDone( true );
127cdf0e10cSrcweir     return false;
128cdf0e10cSrcweir }
129cdf0e10cSrcweir 
handleOldX11SaveYourself(SalFrame * pFrame)130cdf0e10cSrcweir void IceSalSession::handleOldX11SaveYourself( SalFrame* pFrame )
131cdf0e10cSrcweir {
132cdf0e10cSrcweir     // do this only once
133cdf0e10cSrcweir     if( ! pOldStyleSaveFrame )
134cdf0e10cSrcweir     {
135cdf0e10cSrcweir         pOldStyleSaveFrame = static_cast<X11SalFrame*>(pFrame);
136cdf0e10cSrcweir         if( pOneInstance )
137cdf0e10cSrcweir         {
138cdf0e10cSrcweir             SalSessionSaveRequestEvent aEvent( true, false );
139cdf0e10cSrcweir             pOneInstance->CallCallback( &aEvent );
140cdf0e10cSrcweir         }
141cdf0e10cSrcweir     }
142cdf0e10cSrcweir }
143cdf0e10cSrcweir 
144cdf0e10cSrcweir extern "C" void SAL_CALL ICEConnectionWorker( void* );
145cdf0e10cSrcweir 
146cdf0e10cSrcweir class ICEConnectionObserver
147cdf0e10cSrcweir {
148cdf0e10cSrcweir     friend void SAL_CALL ICEConnectionWorker(void*);
149cdf0e10cSrcweir 	static sal_Bool bIsWatching;
150cdf0e10cSrcweir 	static void ICEWatchProc( IceConn connection, IcePointer client_data,
151cdf0e10cSrcweir 							  Bool opening, IcePointer* watch_data );
152cdf0e10cSrcweir 
153cdf0e10cSrcweir     static struct pollfd* pFilehandles;
154cdf0e10cSrcweir     static IceConn* pConnections;
155cdf0e10cSrcweir     static int nConnections;
156cdf0e10cSrcweir     static int nWakeupFiles[2];
157cdf0e10cSrcweir     static oslMutex ICEMutex;
158cdf0e10cSrcweir     static oslThread ICEThread;
159cdf0e10cSrcweir #ifdef USE_SM_EXTENSION
160cdf0e10cSrcweir     static IceIOErrorHandler origIOErrorHandler;
161cdf0e10cSrcweir     static IceErrorHandler origErrorHandler;
162cdf0e10cSrcweir #endif
163cdf0e10cSrcweir public:
164cdf0e10cSrcweir 
165cdf0e10cSrcweir 	static void activate();
166cdf0e10cSrcweir     static void deactivate();
167cdf0e10cSrcweir     static void lock();
168cdf0e10cSrcweir     static void unlock();
169cdf0e10cSrcweir     static void wakeup();
170cdf0e10cSrcweir };
171cdf0e10cSrcweir 
172cdf0e10cSrcweir 
173cdf0e10cSrcweir SmcConn				SessionManagerClient::aSmcConnection			= NULL;
174cdf0e10cSrcweir ByteString			SessionManagerClient::aClientID;
175cdf0e10cSrcweir sal_Bool				ICEConnectionObserver::bIsWatching				= sal_False;
176cdf0e10cSrcweir struct pollfd* 	ICEConnectionObserver::pFilehandles				= NULL;
177cdf0e10cSrcweir IceConn*			ICEConnectionObserver::pConnections				= NULL;
178cdf0e10cSrcweir int					ICEConnectionObserver::nConnections				= 0;
179cdf0e10cSrcweir oslMutex			ICEConnectionObserver::ICEMutex					= NULL;
180cdf0e10cSrcweir oslThread			ICEConnectionObserver::ICEThread				= NULL;
181cdf0e10cSrcweir int					ICEConnectionObserver::nWakeupFiles[2]			= { 0, 0 };
182cdf0e10cSrcweir 
183cdf0e10cSrcweir #ifdef USE_SM_EXTENSION
184cdf0e10cSrcweir IceIOErrorHandler ICEConnectionObserver::origIOErrorHandler = NULL;
185cdf0e10cSrcweir IceErrorHandler ICEConnectionObserver::origErrorHandler = NULL;
186cdf0e10cSrcweir 
IgnoreIceErrors(IceConn,Bool,int,unsigned long,int,int,IcePointer)187cdf0e10cSrcweir static void IgnoreIceErrors(IceConn, Bool, int, unsigned long, int, int, IcePointer)
188cdf0e10cSrcweir {
189cdf0e10cSrcweir }
190cdf0e10cSrcweir 
IgnoreIceIOErrors(IceConn)191cdf0e10cSrcweir static void IgnoreIceIOErrors(IceConn)
192cdf0e10cSrcweir {
193cdf0e10cSrcweir }
194cdf0e10cSrcweir #endif
195cdf0e10cSrcweir 
196cdf0e10cSrcweir // HACK
197cdf0e10cSrcweir bool SessionManagerClient::bDocSaveDone = false;
198cdf0e10cSrcweir 
199cdf0e10cSrcweir 
200cdf0e10cSrcweir static SmProp*	pSmProps = NULL;
201cdf0e10cSrcweir static SmProp**	ppSmProps = NULL;
202cdf0e10cSrcweir static int		nSmProps = 0;
203cdf0e10cSrcweir static unsigned char   *pSmRestartHint = NULL;
204cdf0e10cSrcweir 
205cdf0e10cSrcweir 
BuildSmPropertyList()206cdf0e10cSrcweir static void BuildSmPropertyList()
207cdf0e10cSrcweir {
208cdf0e10cSrcweir 	if( ! pSmProps )
209cdf0e10cSrcweir 	{
210cdf0e10cSrcweir 		ByteString aExec( SessionManagerClient::getExecName(), osl_getThreadTextEncoding() );
211cdf0e10cSrcweir 
212cdf0e10cSrcweir 		nSmProps = 5;
213cdf0e10cSrcweir 		pSmProps = new SmProp[ nSmProps ];
214cdf0e10cSrcweir 
215cdf0e10cSrcweir 		pSmProps[ 0 ].name		= const_cast<char*>(SmCloneCommand);
216cdf0e10cSrcweir 		pSmProps[ 0 ].type		= const_cast<char*>(SmLISTofARRAY8);
217cdf0e10cSrcweir 		pSmProps[ 0 ].num_vals	= 1;
218cdf0e10cSrcweir 		pSmProps[ 0 ].vals		= new SmPropValue;
219cdf0e10cSrcweir 		pSmProps[ 0 ].vals->length	= aExec.Len()+1;
220cdf0e10cSrcweir 		pSmProps[ 0 ].vals->value	= strdup( aExec.GetBuffer() );
221cdf0e10cSrcweir 
222cdf0e10cSrcweir 		pSmProps[ 1 ].name		= const_cast<char*>(SmProgram);
223cdf0e10cSrcweir 		pSmProps[ 1 ].type		= const_cast<char*>(SmARRAY8);
224cdf0e10cSrcweir 		pSmProps[ 1 ].num_vals	= 1;
225cdf0e10cSrcweir 		pSmProps[ 1 ].vals		= new SmPropValue;
226cdf0e10cSrcweir 		pSmProps[ 1 ].vals->length	= aExec.Len()+1;
227cdf0e10cSrcweir 		pSmProps[ 1 ].vals->value	= strdup( aExec.GetBuffer() );
228cdf0e10cSrcweir 
229cdf0e10cSrcweir 		pSmProps[ 2 ].name		= const_cast<char*>(SmRestartCommand);
230cdf0e10cSrcweir 		pSmProps[ 2 ].type		= const_cast<char*>(SmLISTofARRAY8);
231cdf0e10cSrcweir 		pSmProps[ 2 ].num_vals	= 3;
232cdf0e10cSrcweir 		pSmProps[ 2 ].vals		= new SmPropValue[3];
233cdf0e10cSrcweir 		pSmProps[ 2 ].vals[0].length	= aExec.Len()+1;
234cdf0e10cSrcweir 		pSmProps[ 2 ].vals[0].value	= strdup( aExec.GetBuffer() );
235cdf0e10cSrcweir         	ByteString aRestartOption( "-session=" );
236cdf0e10cSrcweir 		aRestartOption.Append( SessionManagerClient::getSessionID() );
237cdf0e10cSrcweir 		pSmProps[ 2 ].vals[1].length	= aRestartOption.Len()+1;
238cdf0e10cSrcweir 		pSmProps[ 2 ].vals[1].value	= strdup( aRestartOption.GetBuffer() );
239cdf0e10cSrcweir         	ByteString aRestartOptionNoLogo( "-nologo" );
240cdf0e10cSrcweir 		pSmProps[ 2 ].vals[2].length	= aRestartOptionNoLogo.Len()+1;
241cdf0e10cSrcweir 		pSmProps[ 2 ].vals[2].value	= strdup( aRestartOptionNoLogo.GetBuffer() );
242cdf0e10cSrcweir 
243cdf0e10cSrcweir 		rtl::OUString aUserName;
244cdf0e10cSrcweir         rtl::OString aUser;
245cdf0e10cSrcweir         oslSecurity aSec = osl_getCurrentSecurity();
246cdf0e10cSrcweir         if( aSec )
247cdf0e10cSrcweir         {
248cdf0e10cSrcweir             osl_getUserName( aSec, &aUserName.pData );
249cdf0e10cSrcweir             aUser = rtl::OUStringToOString( aUserName, osl_getThreadTextEncoding() );
250cdf0e10cSrcweir             osl_freeSecurityHandle( aSec );
251cdf0e10cSrcweir         }
252cdf0e10cSrcweir 
253cdf0e10cSrcweir 		pSmProps[ 3 ].name		= const_cast<char*>(SmUserID);
254cdf0e10cSrcweir 		pSmProps[ 3 ].type		= const_cast<char*>(SmARRAY8);
255cdf0e10cSrcweir 		pSmProps[ 3 ].num_vals	= 1;
256cdf0e10cSrcweir 		pSmProps[ 3 ].vals		= new SmPropValue;
257cdf0e10cSrcweir 		pSmProps[ 3 ].vals->value	= strdup( aUser.getStr() );
258cdf0e10cSrcweir 		pSmProps[ 3 ].vals->length	= strlen( (char *)pSmProps[ 3 ].vals->value )+1;
259cdf0e10cSrcweir 
260cdf0e10cSrcweir 		pSmProps[ 4 ].name		= const_cast<char*>(SmRestartStyleHint);
261cdf0e10cSrcweir 		pSmProps[ 4 ].type		= const_cast<char*>(SmCARD8);
262cdf0e10cSrcweir 		pSmProps[ 4 ].num_vals	= 1;
263cdf0e10cSrcweir 		pSmProps[ 4 ].vals		= new SmPropValue;
264cdf0e10cSrcweir 		pSmProps[ 4 ].vals->value	= malloc(1);
265cdf0e10cSrcweir 		pSmRestartHint = (unsigned char *)pSmProps[ 4 ].vals->value;
266cdf0e10cSrcweir 		*pSmRestartHint = SmRestartIfRunning;
267cdf0e10cSrcweir 		pSmProps[ 4 ].vals->length	= 1;
268cdf0e10cSrcweir 
269cdf0e10cSrcweir 		ppSmProps = new SmProp*[ nSmProps ];
270cdf0e10cSrcweir 		for( int i = 0; i < nSmProps; i++ )
271cdf0e10cSrcweir 			ppSmProps[ i ] = &pSmProps[i];
272cdf0e10cSrcweir 	}
273cdf0e10cSrcweir }
274cdf0e10cSrcweir 
checkDocumentsSaved()275cdf0e10cSrcweir bool SessionManagerClient::checkDocumentsSaved()
276cdf0e10cSrcweir {
277cdf0e10cSrcweir     return bDocSaveDone;
278cdf0e10cSrcweir }
279cdf0e10cSrcweir 
IMPL_STATIC_LINK(SessionManagerClient,SaveYourselfHdl,void *,EMPTYARG)280cdf0e10cSrcweir IMPL_STATIC_LINK( SessionManagerClient, SaveYourselfHdl, void*, EMPTYARG )
281cdf0e10cSrcweir {
282cdf0e10cSrcweir     SMprintf( "posting save documents event shutdown = %s\n", (pThis!=0) ? "true" : "false" );
283cdf0e10cSrcweir 
284cdf0e10cSrcweir     static bool bFirstShutdown=true;
285cdf0e10cSrcweir     if (pThis != 0 && bFirstShutdown) //first shutdown request
286cdf0e10cSrcweir     {
287cdf0e10cSrcweir         bFirstShutdown = false;
288cdf0e10cSrcweir         /*
289cdf0e10cSrcweir           If we have no actual frames open, e.g. we launched a quickstarter,
290cdf0e10cSrcweir           and then shutdown all our frames leaving just a quickstarter running,
291cdf0e10cSrcweir           then we don't want to launch an empty toplevel frame on the next
292cdf0e10cSrcweir           start. (The job of scheduling the restart of the quick-starter is a
293cdf0e10cSrcweir           task of the quick-starter)
294cdf0e10cSrcweir         */
295cdf0e10cSrcweir         *pSmRestartHint = SmRestartNever;
296cdf0e10cSrcweir         const std::list< SalFrame* >& rFrames = GetX11SalData()->GetDisplay()->getFrames();
297cdf0e10cSrcweir         for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
298cdf0e10cSrcweir         {
299cdf0e10cSrcweir             Window *pWindow = (*it)->GetWindow();
300cdf0e10cSrcweir             if (pWindow && pWindow->IsVisible())
301cdf0e10cSrcweir             {
302cdf0e10cSrcweir                 *pSmRestartHint = SmRestartIfRunning;
303cdf0e10cSrcweir                 break;
304cdf0e10cSrcweir             }
305cdf0e10cSrcweir         }
306cdf0e10cSrcweir     }
307cdf0e10cSrcweir 
308cdf0e10cSrcweir     if( pOneInstance )
309cdf0e10cSrcweir     {
310cdf0e10cSrcweir         SalSessionSaveRequestEvent aEvent( pThis != 0, false );
311cdf0e10cSrcweir         pOneInstance->CallCallback( &aEvent );
312cdf0e10cSrcweir     }
313cdf0e10cSrcweir     else
314cdf0e10cSrcweir         saveDone();
315cdf0e10cSrcweir 
316cdf0e10cSrcweir     return 0;
317cdf0e10cSrcweir }
318cdf0e10cSrcweir 
IMPL_STATIC_LINK_NOINSTANCE(SessionManagerClient,InteractionHdl,void *,EMPTYARG)319cdf0e10cSrcweir IMPL_STATIC_LINK_NOINSTANCE( SessionManagerClient, InteractionHdl, void*, EMPTYARG )
320cdf0e10cSrcweir {
321cdf0e10cSrcweir     SMprintf( "interaction link\n" );
322cdf0e10cSrcweir     if( pOneInstance )
323cdf0e10cSrcweir     {
324cdf0e10cSrcweir         SalSessionInteractionEvent aEvent( true );
325cdf0e10cSrcweir         pOneInstance->CallCallback( &aEvent );
326cdf0e10cSrcweir     }
327cdf0e10cSrcweir 
328cdf0e10cSrcweir     return 0;
329cdf0e10cSrcweir }
330cdf0e10cSrcweir 
IMPL_STATIC_LINK_NOINSTANCE(SessionManagerClient,ShutDownCancelHdl,void *,EMPTYARG)331cdf0e10cSrcweir IMPL_STATIC_LINK_NOINSTANCE( SessionManagerClient, ShutDownCancelHdl, void*, EMPTYARG )
332cdf0e10cSrcweir {
333cdf0e10cSrcweir     SMprintf( "shutdown cancel\n" );
334cdf0e10cSrcweir     if( pOneInstance )
335cdf0e10cSrcweir     {
336cdf0e10cSrcweir         SalSessionShutdownCancelEvent aEvent;
337cdf0e10cSrcweir         pOneInstance->CallCallback( &aEvent );
338cdf0e10cSrcweir     }
339cdf0e10cSrcweir 
340cdf0e10cSrcweir     return 0;
341cdf0e10cSrcweir }
342cdf0e10cSrcweir 
SaveYourselfProc(SmcConn,SmPointer,int save_type,Bool shutdown,int interact_style,Bool)343cdf0e10cSrcweir void SessionManagerClient::SaveYourselfProc(
344cdf0e10cSrcweir 	SmcConn,
345cdf0e10cSrcweir 	SmPointer,
346cdf0e10cSrcweir 	int save_type,
347cdf0e10cSrcweir 	Bool shutdown,
348cdf0e10cSrcweir 	int interact_style,
349cdf0e10cSrcweir 	Bool
350cdf0e10cSrcweir 	)
351cdf0e10cSrcweir {
352cdf0e10cSrcweir     SMprintf( "Session: save yourself, save_type = %s, shutdown = %s, interact_style = %s, fast = %s\n",
353cdf0e10cSrcweir               save_type == SmSaveLocal ? "SmcSaveLocal" :
354cdf0e10cSrcweir               ( save_type == SmSaveGlobal ? "SmcSaveGlobal" :
355cdf0e10cSrcweir                 ( save_type == SmSaveBoth ? "SmcSaveBoth" : "<unknown>" ) ),
356cdf0e10cSrcweir               shutdown ? "true" : "false",
357cdf0e10cSrcweir               interact_style == SmInteractStyleNone ? "SmInteractStyleNone" :
358cdf0e10cSrcweir               ( interact_style == SmInteractStyleErrors ? "SmInteractStyleErrors" :
359cdf0e10cSrcweir                 ( interact_style == SmInteractStyleAny ? "SmInteractStyleAny" : "<unknown>" ) ),
360cdf0e10cSrcweir               false ? "true" : "false"
361cdf0e10cSrcweir               );
362cdf0e10cSrcweir 	BuildSmPropertyList();
363cdf0e10cSrcweir #ifdef USE_SM_EXTENSION
364cdf0e10cSrcweir     bDocSaveDone = false;
365cdf0e10cSrcweir     /* #i49875# some session managers send a "die" message if the
366cdf0e10cSrcweir      * saveDone does not come early enough for their convenience
367cdf0e10cSrcweir      * this can occasionally happen on startup, especially the first
368cdf0e10cSrcweir      * startup. So shortcut the "not shutting down" case since the
369cdf0e10cSrcweir      * upper layers are currently not interested in that event anyway.
370cdf0e10cSrcweir      */
371cdf0e10cSrcweir     if( ! shutdown )
372cdf0e10cSrcweir     {
373cdf0e10cSrcweir         SessionManagerClient::saveDone();
374cdf0e10cSrcweir         return;
375cdf0e10cSrcweir     }
376cdf0e10cSrcweir     Application::PostUserEvent( STATIC_LINK( (void*)(shutdown ? 0xffffffff : 0x0), SessionManagerClient, SaveYourselfHdl ) );
377cdf0e10cSrcweir     SMprintf( "waiting for save yourself event to be processed\n" );
378cdf0e10cSrcweir #endif
379cdf0e10cSrcweir }
380cdf0e10cSrcweir 
IMPL_STATIC_LINK_NOINSTANCE(SessionManagerClient,ShutDownHdl,void *,EMPTYARG)381cdf0e10cSrcweir IMPL_STATIC_LINK_NOINSTANCE( SessionManagerClient, ShutDownHdl, void*, EMPTYARG )
382cdf0e10cSrcweir {
383cdf0e10cSrcweir     if( pOneInstance )
384cdf0e10cSrcweir     {
385cdf0e10cSrcweir         SalSessionQuitEvent aEvent;
386cdf0e10cSrcweir         pOneInstance->CallCallback( &aEvent );
387cdf0e10cSrcweir     }
388cdf0e10cSrcweir 
389cdf0e10cSrcweir     const std::list< SalFrame* >& rFrames = GetX11SalData()->GetDisplay()->getFrames();
390cdf0e10cSrcweir     SMprintf( rFrames.begin() != rFrames.end() ? "shutdown on first frame\n" : "shutdown event but no frame\n" );
391cdf0e10cSrcweir     if( rFrames.begin() != rFrames.end() )
392cdf0e10cSrcweir         rFrames.front()->CallCallback( SALEVENT_SHUTDOWN, 0 );
393cdf0e10cSrcweir     return 0;
394cdf0e10cSrcweir }
395cdf0e10cSrcweir 
DieProc(SmcConn connection,SmPointer)396cdf0e10cSrcweir void SessionManagerClient::DieProc(
397cdf0e10cSrcweir 	SmcConn connection,
398cdf0e10cSrcweir 	SmPointer
399cdf0e10cSrcweir 	)
400cdf0e10cSrcweir {
401cdf0e10cSrcweir     SMprintf( "Session: die\n" );
402cdf0e10cSrcweir 	if( connection == aSmcConnection )
403cdf0e10cSrcweir     {
404cdf0e10cSrcweir         Application::PostUserEvent( STATIC_LINK( NULL, SessionManagerClient, ShutDownHdl ) );
405cdf0e10cSrcweir         SMprintf( "waiting for shutdown event to be processed\n" );
406cdf0e10cSrcweir     }
407cdf0e10cSrcweir }
408cdf0e10cSrcweir 
SaveCompleteProc(SmcConn,SmPointer)409cdf0e10cSrcweir void SessionManagerClient::SaveCompleteProc(
410cdf0e10cSrcweir 	SmcConn,
411cdf0e10cSrcweir 	SmPointer
412cdf0e10cSrcweir 	)
413cdf0e10cSrcweir {
414cdf0e10cSrcweir     SMprintf( "Session: save complete\n" );
415cdf0e10cSrcweir }
416cdf0e10cSrcweir 
ShutdownCanceledProc(SmcConn connection,SmPointer)417cdf0e10cSrcweir void SessionManagerClient::ShutdownCanceledProc(
418cdf0e10cSrcweir 	SmcConn connection,
419cdf0e10cSrcweir 	SmPointer )
420cdf0e10cSrcweir {
421cdf0e10cSrcweir     SMprintf( "Session: shutdown canceled\n" );
422cdf0e10cSrcweir 	if( connection == aSmcConnection )
423cdf0e10cSrcweir         Application::PostUserEvent( STATIC_LINK( NULL, SessionManagerClient, ShutDownCancelHdl ) );
424cdf0e10cSrcweir }
425cdf0e10cSrcweir 
InteractProc(SmcConn connection,SmPointer)426cdf0e10cSrcweir void SessionManagerClient::InteractProc(
427cdf0e10cSrcweir                                         SmcConn connection,
428cdf0e10cSrcweir                                         SmPointer )
429cdf0e10cSrcweir {
430cdf0e10cSrcweir     SMprintf( "Session: interaction request completed\n" );
431cdf0e10cSrcweir 	if( connection == aSmcConnection )
432cdf0e10cSrcweir         Application::PostUserEvent( STATIC_LINK( NULL, SessionManagerClient, InteractionHdl ) );
433cdf0e10cSrcweir }
434cdf0e10cSrcweir 
saveDone()435cdf0e10cSrcweir void SessionManagerClient::saveDone()
436cdf0e10cSrcweir {
437cdf0e10cSrcweir     if( aSmcConnection )
438cdf0e10cSrcweir     {
439cdf0e10cSrcweir         ICEConnectionObserver::lock();
440cdf0e10cSrcweir         SmcSetProperties( aSmcConnection, nSmProps, ppSmProps );
441cdf0e10cSrcweir         SmcSaveYourselfDone( aSmcConnection, True );
442cdf0e10cSrcweir         SMprintf( "sent SaveYourselfDone SmRestartHint of %d\n", *pSmRestartHint );
443cdf0e10cSrcweir         bDocSaveDone = true;
444cdf0e10cSrcweir         ICEConnectionObserver::unlock();
445cdf0e10cSrcweir     }
446cdf0e10cSrcweir }
447cdf0e10cSrcweir 
448cdf0e10cSrcweir 
open()449cdf0e10cSrcweir void SessionManagerClient::open()
450cdf0e10cSrcweir {
451cdf0e10cSrcweir 	static SmcCallbacks aCallbacks;
452cdf0e10cSrcweir 
453cdf0e10cSrcweir #ifdef USE_SM_EXTENSION
454cdf0e10cSrcweir 	// this is the way Xt does it, so we can too
455cdf0e10cSrcweir 	if( ! aSmcConnection && getenv( "SESSION_MANAGER" ) )
456cdf0e10cSrcweir 	{
457cdf0e10cSrcweir 		char aErrBuf[1024];
458cdf0e10cSrcweir 		ICEConnectionObserver::activate();
459cdf0e10cSrcweir         ICEConnectionObserver::lock();
460cdf0e10cSrcweir 
461cdf0e10cSrcweir         char* pClientID = NULL;
462cdf0e10cSrcweir         const ByteString& rPrevId( getPreviousSessionID() );
463cdf0e10cSrcweir 
464cdf0e10cSrcweir 		aCallbacks.save_yourself.callback			= SaveYourselfProc;
465cdf0e10cSrcweir 		aCallbacks.save_yourself.client_data		= NULL;
466cdf0e10cSrcweir 		aCallbacks.die.callback						= DieProc;
467cdf0e10cSrcweir 		aCallbacks.die.client_data					= NULL;
468cdf0e10cSrcweir 		aCallbacks.save_complete.callback			= SaveCompleteProc;
469cdf0e10cSrcweir 		aCallbacks.save_complete.client_data		= NULL;
470cdf0e10cSrcweir 		aCallbacks.shutdown_cancelled.callback		= ShutdownCanceledProc;
471cdf0e10cSrcweir 		aCallbacks.shutdown_cancelled.client_data	= NULL;
472cdf0e10cSrcweir 		aSmcConnection = SmcOpenConnection( NULL,
473cdf0e10cSrcweir 											NULL,
474cdf0e10cSrcweir 											SmProtoMajor,
475cdf0e10cSrcweir 											SmProtoMinor,
476cdf0e10cSrcweir 											SmcSaveYourselfProcMask			|
477cdf0e10cSrcweir 											SmcDieProcMask					|
478cdf0e10cSrcweir 											SmcSaveCompleteProcMask			|
479cdf0e10cSrcweir 											SmcShutdownCancelledProcMask	,
480cdf0e10cSrcweir 											&aCallbacks,
481cdf0e10cSrcweir 											rPrevId.Len() ? const_cast<char*>(rPrevId.GetBuffer()) : NULL,
482cdf0e10cSrcweir 											&pClientID,
483cdf0e10cSrcweir 											sizeof( aErrBuf ),
484cdf0e10cSrcweir 											aErrBuf );
485cdf0e10cSrcweir 		if( ! aSmcConnection )
486cdf0e10cSrcweir 			SMprintf( "SmcOpenConnection failed: %s\n", aErrBuf );
487cdf0e10cSrcweir         else
488cdf0e10cSrcweir             SMprintf( "SmcOpenConnection succeeded, client ID is \"%s\"\n", pClientID );
489cdf0e10cSrcweir         aClientID = ByteString( pClientID );
490cdf0e10cSrcweir         free( pClientID );
491cdf0e10cSrcweir         pClientID = NULL;
492cdf0e10cSrcweir         ICEConnectionObserver::unlock();
493cdf0e10cSrcweir 
494cdf0e10cSrcweir         SalDisplay* pDisp = GetX11SalData()->GetDisplay();
495cdf0e10cSrcweir         if( pDisp->GetDrawable( pDisp->GetDefaultScreenNumber() ) && aClientID.Len() )
496cdf0e10cSrcweir         {
497cdf0e10cSrcweir             XChangeProperty( pDisp->GetDisplay(),
498cdf0e10cSrcweir                              pDisp->GetDrawable( pDisp->GetDefaultScreenNumber() ),
499cdf0e10cSrcweir                              XInternAtom( pDisp->GetDisplay(), "SM_CLIENT_ID", False ),
500cdf0e10cSrcweir                              XA_STRING,
501cdf0e10cSrcweir                              8,
502cdf0e10cSrcweir                              PropModeReplace,
503cdf0e10cSrcweir                              (unsigned char*)aClientID.GetBuffer(),
504cdf0e10cSrcweir                              aClientID.Len()
505cdf0e10cSrcweir                              );
506cdf0e10cSrcweir         }
507cdf0e10cSrcweir 	}
508cdf0e10cSrcweir     else if( ! aSmcConnection )
509cdf0e10cSrcweir         SMprintf( "no SESSION_MANAGER\n" );
510cdf0e10cSrcweir #endif
511cdf0e10cSrcweir }
512cdf0e10cSrcweir 
getSessionID()513cdf0e10cSrcweir const ByteString& SessionManagerClient::getSessionID()
514cdf0e10cSrcweir {
515cdf0e10cSrcweir     return aClientID;
516cdf0e10cSrcweir }
517cdf0e10cSrcweir 
close()518cdf0e10cSrcweir void SessionManagerClient::close()
519cdf0e10cSrcweir {
520cdf0e10cSrcweir 	if( aSmcConnection )
521cdf0e10cSrcweir 	{
522cdf0e10cSrcweir #ifdef USE_SM_EXTENSION
523cdf0e10cSrcweir         ICEConnectionObserver::lock();
524cdf0e10cSrcweir         SMprintf( "attempting SmcCloseConnection\n" );
525cdf0e10cSrcweir 		SmcCloseConnection( aSmcConnection, 0, NULL );
526cdf0e10cSrcweir         SMprintf( "SmcConnection closed\n" );
527cdf0e10cSrcweir         ICEConnectionObserver::unlock();
528cdf0e10cSrcweir         ICEConnectionObserver::deactivate();
529cdf0e10cSrcweir #endif
530cdf0e10cSrcweir 		aSmcConnection = NULL;
531cdf0e10cSrcweir 	}
532cdf0e10cSrcweir }
533cdf0e10cSrcweir 
queryInteraction()534cdf0e10cSrcweir bool SessionManagerClient::queryInteraction()
535cdf0e10cSrcweir {
536cdf0e10cSrcweir     bool bRet = false;
537cdf0e10cSrcweir     if( aSmcConnection )
538cdf0e10cSrcweir     {
539cdf0e10cSrcweir         ICEConnectionObserver::lock();
540cdf0e10cSrcweir         if( SmcInteractRequest( aSmcConnection, SmDialogNormal, InteractProc, NULL ) )
541cdf0e10cSrcweir             bRet = true;
542cdf0e10cSrcweir         ICEConnectionObserver::unlock();
543cdf0e10cSrcweir     }
544cdf0e10cSrcweir     return bRet;
545cdf0e10cSrcweir }
546cdf0e10cSrcweir 
interactionDone(bool bCancelShutdown)547cdf0e10cSrcweir void SessionManagerClient::interactionDone( bool bCancelShutdown )
548cdf0e10cSrcweir {
549cdf0e10cSrcweir     if( aSmcConnection )
550cdf0e10cSrcweir     {
551cdf0e10cSrcweir         ICEConnectionObserver::lock();
552cdf0e10cSrcweir         SmcInteractDone( aSmcConnection, bCancelShutdown ? True : False );
553cdf0e10cSrcweir         ICEConnectionObserver::unlock();
554cdf0e10cSrcweir     }
555cdf0e10cSrcweir }
556cdf0e10cSrcweir 
557cdf0e10cSrcweir 
getExecName()558cdf0e10cSrcweir String SessionManagerClient::getExecName()
559cdf0e10cSrcweir {
560cdf0e10cSrcweir 	rtl::OUString aExec, aSysExec;
561cdf0e10cSrcweir 	osl_getExecutableFile( &aExec.pData );
562cdf0e10cSrcweir     osl_getSystemPathFromFileURL( aExec.pData, &aSysExec.pData );
563cdf0e10cSrcweir 
564cdf0e10cSrcweir 	int nPos = aSysExec.indexOf( rtl::OUString::createFromAscii( ".bin" ) );
565cdf0e10cSrcweir 	if( nPos != -1 )
566cdf0e10cSrcweir 		aSysExec = aSysExec.copy( 0, nPos );
567cdf0e10cSrcweir 	return aSysExec;
568cdf0e10cSrcweir }
569cdf0e10cSrcweir 
570cdf0e10cSrcweir 
getPreviousSessionID()571cdf0e10cSrcweir const ByteString& SessionManagerClient::getPreviousSessionID()
572cdf0e10cSrcweir {
573cdf0e10cSrcweir 	static ByteString aPrevId;
574cdf0e10cSrcweir 
575cdf0e10cSrcweir     int nCommands = osl_getCommandArgCount();
576cdf0e10cSrcweir     for( int i = 0; i < nCommands; i++ )
577cdf0e10cSrcweir     {
578cdf0e10cSrcweir         ::rtl::OUString aArg;
579cdf0e10cSrcweir         osl_getCommandArg( i, &aArg.pData );
580cdf0e10cSrcweir         if( aArg.compareToAscii( "-session=", 9 ) == 0 )
581cdf0e10cSrcweir         {
582cdf0e10cSrcweir             aPrevId = ByteString( ::rtl::OUStringToOString( aArg.copy( 9 ), osl_getThreadTextEncoding() ) );
583cdf0e10cSrcweir             break;
584cdf0e10cSrcweir         }
585cdf0e10cSrcweir     }
586cdf0e10cSrcweir     SMprintf( "previous ID = \"%s\"\n", aPrevId.GetBuffer() );
587cdf0e10cSrcweir     return aPrevId;
588cdf0e10cSrcweir }
589cdf0e10cSrcweir 
lock()590cdf0e10cSrcweir void ICEConnectionObserver::lock()
591cdf0e10cSrcweir {
592cdf0e10cSrcweir     osl_acquireMutex( ICEMutex );
593cdf0e10cSrcweir }
594cdf0e10cSrcweir 
unlock()595cdf0e10cSrcweir void ICEConnectionObserver::unlock()
596cdf0e10cSrcweir {
597cdf0e10cSrcweir     osl_releaseMutex( ICEMutex );
598cdf0e10cSrcweir }
599cdf0e10cSrcweir 
activate()600cdf0e10cSrcweir void ICEConnectionObserver::activate()
601cdf0e10cSrcweir {
602cdf0e10cSrcweir     if( ! bIsWatching )
603cdf0e10cSrcweir     {
604cdf0e10cSrcweir         nWakeupFiles[0] = nWakeupFiles[1] = 0;
605cdf0e10cSrcweir         ICEMutex = osl_createMutex();
606cdf0e10cSrcweir         bIsWatching = sal_True;
607cdf0e10cSrcweir #ifdef USE_SM_EXTENSION
608cdf0e10cSrcweir         /*
609cdf0e10cSrcweir          * Default handlers call exit, we don't care that strongly if something
610cdf0e10cSrcweir          * happens to fail
611cdf0e10cSrcweir          */
612cdf0e10cSrcweir         origIOErrorHandler = IceSetIOErrorHandler( IgnoreIceIOErrors );
613cdf0e10cSrcweir         origErrorHandler = IceSetErrorHandler( IgnoreIceErrors );
614cdf0e10cSrcweir         IceAddConnectionWatch( ICEWatchProc, NULL );
615cdf0e10cSrcweir #endif
616cdf0e10cSrcweir     }
617cdf0e10cSrcweir }
618cdf0e10cSrcweir 
deactivate()619cdf0e10cSrcweir void ICEConnectionObserver::deactivate()
620cdf0e10cSrcweir {
621cdf0e10cSrcweir     if( bIsWatching )
622cdf0e10cSrcweir     {
623cdf0e10cSrcweir         lock();
624cdf0e10cSrcweir         bIsWatching = sal_False;
625cdf0e10cSrcweir #ifdef USE_SM_EXTENSION
626cdf0e10cSrcweir         IceRemoveConnectionWatch( ICEWatchProc, NULL );
627cdf0e10cSrcweir         IceSetErrorHandler( origErrorHandler );
628cdf0e10cSrcweir         IceSetIOErrorHandler( origIOErrorHandler );
629cdf0e10cSrcweir #endif
630cdf0e10cSrcweir         nConnections = 0;
631cdf0e10cSrcweir         if( ICEThread )
632cdf0e10cSrcweir         {
633cdf0e10cSrcweir             osl_terminateThread( ICEThread );
634cdf0e10cSrcweir             wakeup();
635cdf0e10cSrcweir         }
636cdf0e10cSrcweir         unlock();
637cdf0e10cSrcweir         if( ICEThread )
638cdf0e10cSrcweir         {
639cdf0e10cSrcweir             osl_joinWithThread( ICEThread );
640cdf0e10cSrcweir             osl_destroyThread( ICEThread );
641cdf0e10cSrcweir             close( nWakeupFiles[1] );
642cdf0e10cSrcweir             close( nWakeupFiles[0] );
643cdf0e10cSrcweir             ICEThread = NULL;
644cdf0e10cSrcweir         }
645cdf0e10cSrcweir         osl_destroyMutex( ICEMutex );
646cdf0e10cSrcweir         ICEMutex = NULL;
647cdf0e10cSrcweir     }
648cdf0e10cSrcweir }
649cdf0e10cSrcweir 
wakeup()650cdf0e10cSrcweir void ICEConnectionObserver::wakeup()
651cdf0e10cSrcweir {
652cdf0e10cSrcweir     char cChar = 'w';
653cdf0e10cSrcweir     write( nWakeupFiles[1], &cChar, 1 );
654cdf0e10cSrcweir }
655cdf0e10cSrcweir 
ICEConnectionWorker(void *)656cdf0e10cSrcweir void ICEConnectionWorker( void* )
657cdf0e10cSrcweir {
658cdf0e10cSrcweir #ifdef USE_SM_EXTENSION
659cdf0e10cSrcweir     while( osl_scheduleThread(ICEConnectionObserver::ICEThread) && ICEConnectionObserver::nConnections )
660cdf0e10cSrcweir     {
661cdf0e10cSrcweir         ICEConnectionObserver::lock();
662cdf0e10cSrcweir         int nConnectionsBefore = ICEConnectionObserver::nConnections;
663cdf0e10cSrcweir         int nBytes = sizeof( struct pollfd )*(nConnectionsBefore+1);
664cdf0e10cSrcweir         struct pollfd* pLocalFD = (struct pollfd*)rtl_allocateMemory( nBytes );
665cdf0e10cSrcweir         rtl_copyMemory( pLocalFD, ICEConnectionObserver::pFilehandles, nBytes );
666cdf0e10cSrcweir         ICEConnectionObserver::unlock();
667cdf0e10cSrcweir 
668cdf0e10cSrcweir         int nRet = poll( pLocalFD,nConnectionsBefore+1,-1 );
669cdf0e10cSrcweir         bool bWakeup = (pLocalFD[0].revents & POLLIN);
670cdf0e10cSrcweir         rtl_freeMemory( pLocalFD );
671cdf0e10cSrcweir 
672cdf0e10cSrcweir         if( nRet < 1 )
673cdf0e10cSrcweir             continue;
674cdf0e10cSrcweir 
675cdf0e10cSrcweir         // clear wakeup pipe
676cdf0e10cSrcweir         if( bWakeup )
677cdf0e10cSrcweir         {
678cdf0e10cSrcweir             char buf[4];
679cdf0e10cSrcweir             while( read( ICEConnectionObserver::nWakeupFiles[0], buf, sizeof( buf ) ) > 0 )
680cdf0e10cSrcweir                 ;
681cdf0e10cSrcweir             SMprintf( "file handles active in wakeup: %d\n", nRet );
682cdf0e10cSrcweir             if( nRet == 1 )
683cdf0e10cSrcweir                 continue;
684cdf0e10cSrcweir         }
685cdf0e10cSrcweir 
686cdf0e10cSrcweir         // check fd's after we obtained the lock
687cdf0e10cSrcweir         ICEConnectionObserver::lock();
688cdf0e10cSrcweir         if( ICEConnectionObserver::nConnections > 0 && ICEConnectionObserver::nConnections == nConnectionsBefore )
689cdf0e10cSrcweir         {
690cdf0e10cSrcweir             nRet = poll( ICEConnectionObserver::pFilehandles+1, ICEConnectionObserver::nConnections, 0 );
691cdf0e10cSrcweir             if( nRet > 0 )
692cdf0e10cSrcweir             {
693cdf0e10cSrcweir                 SMprintf( "IceProcessMessages\n" );
694cdf0e10cSrcweir                 Bool bReply;
695cdf0e10cSrcweir                 for( int i = 0; i < ICEConnectionObserver::nConnections; i++ )
696cdf0e10cSrcweir                     if( ICEConnectionObserver::pFilehandles[i+1].revents & POLLIN )
697cdf0e10cSrcweir                         IceProcessMessages( ICEConnectionObserver::pConnections[i], NULL, &bReply );
698cdf0e10cSrcweir             }
699cdf0e10cSrcweir         }
700cdf0e10cSrcweir         ICEConnectionObserver::unlock();
701cdf0e10cSrcweir     }
702cdf0e10cSrcweir #endif
703cdf0e10cSrcweir     SMprintf( "shutting donw ICE dispatch thread\n" );
704cdf0e10cSrcweir }
705cdf0e10cSrcweir 
ICEWatchProc(IceConn connection,IcePointer,Bool opening,IcePointer *)706cdf0e10cSrcweir void ICEConnectionObserver::ICEWatchProc(
707cdf0e10cSrcweir 	IceConn connection,
708cdf0e10cSrcweir 	IcePointer,
709cdf0e10cSrcweir 	Bool opening,
710cdf0e10cSrcweir 	IcePointer*
711cdf0e10cSrcweir 	)
712cdf0e10cSrcweir {
713cdf0e10cSrcweir     // note: this is a callback function for ICE
714cdf0e10cSrcweir     // this implicitly means that a call into ICE lib is calling this
715cdf0e10cSrcweir     // so the ICEMutex MUST already be locked by the caller
716cdf0e10cSrcweir 
717cdf0e10cSrcweir #ifdef USE_SM_EXTENSION
718cdf0e10cSrcweir     if( opening )
719cdf0e10cSrcweir     {
720cdf0e10cSrcweir         int fd = IceConnectionNumber( connection );
721cdf0e10cSrcweir         nConnections++;
722cdf0e10cSrcweir         pConnections = (IceConn*)rtl_reallocateMemory( pConnections, sizeof( IceConn )*nConnections );
723cdf0e10cSrcweir         pFilehandles = (struct pollfd*)rtl_reallocateMemory( pFilehandles, sizeof( struct pollfd )*(nConnections+1) );
724cdf0e10cSrcweir         pConnections[ nConnections-1 ]		= connection;
725cdf0e10cSrcweir         pFilehandles[ nConnections ].fd		= fd;
726cdf0e10cSrcweir         pFilehandles[ nConnections ].events	= POLLIN;
727cdf0e10cSrcweir         if( nConnections == 1 )
728cdf0e10cSrcweir         {
729cdf0e10cSrcweir             if( ! pipe( nWakeupFiles ) )
730cdf0e10cSrcweir             {
731cdf0e10cSrcweir                 int flags;
732cdf0e10cSrcweir                 pFilehandles[0].fd		= nWakeupFiles[0];
733cdf0e10cSrcweir                 pFilehandles[0].events	= POLLIN;
734cdf0e10cSrcweir                 // set close-on-exec and nonblock descriptor flag.
735cdf0e10cSrcweir                 if ((flags = fcntl (nWakeupFiles[0], F_GETFD)) != -1)
736cdf0e10cSrcweir                 {
737cdf0e10cSrcweir                     flags |= FD_CLOEXEC;
738cdf0e10cSrcweir                     fcntl (nWakeupFiles[0], F_SETFD, flags);
739cdf0e10cSrcweir                 }
740cdf0e10cSrcweir                 if ((flags = fcntl (nWakeupFiles[0], F_GETFL)) != -1)
741cdf0e10cSrcweir                 {
742cdf0e10cSrcweir                     flags |= O_NONBLOCK;
743cdf0e10cSrcweir                     fcntl (nWakeupFiles[0], F_SETFL, flags);
744cdf0e10cSrcweir                 }
745cdf0e10cSrcweir                 // set close-on-exec and nonblock descriptor flag.
746cdf0e10cSrcweir                 if ((flags = fcntl (nWakeupFiles[1], F_GETFD)) != -1)
747cdf0e10cSrcweir                 {
748cdf0e10cSrcweir                     flags |= FD_CLOEXEC;
749cdf0e10cSrcweir                     fcntl (nWakeupFiles[1], F_SETFD, flags);
750cdf0e10cSrcweir                 }
751cdf0e10cSrcweir                 if ((flags = fcntl (nWakeupFiles[1], F_GETFL)) != -1)
752cdf0e10cSrcweir                 {
753cdf0e10cSrcweir                     flags |= O_NONBLOCK;
754cdf0e10cSrcweir                     fcntl (nWakeupFiles[1], F_SETFL, flags);
755cdf0e10cSrcweir                 }
756cdf0e10cSrcweir                 ICEThread = osl_createSuspendedThread( ICEConnectionWorker, NULL );
757cdf0e10cSrcweir                 osl_resumeThread( ICEThread );
758cdf0e10cSrcweir             }
759cdf0e10cSrcweir         }
760cdf0e10cSrcweir     }
761cdf0e10cSrcweir     else
762cdf0e10cSrcweir     {
763cdf0e10cSrcweir         for( int i = 0; i < nConnections; i++ )
764cdf0e10cSrcweir         {
765cdf0e10cSrcweir             if( pConnections[i] == connection )
766cdf0e10cSrcweir             {
767cdf0e10cSrcweir                 if( i < nConnections-1 )
768cdf0e10cSrcweir                 {
769cdf0e10cSrcweir                     rtl_moveMemory( pConnections+i, pConnections+i+1, sizeof( IceConn )*(nConnections-i-1) );
770cdf0e10cSrcweir                     rtl_moveMemory( pFilehandles+i+1, pFilehandles+i+2, sizeof( struct pollfd )*(nConnections-i-1) );
771cdf0e10cSrcweir                 }
772cdf0e10cSrcweir                 nConnections--;
773cdf0e10cSrcweir                 pConnections = (IceConn*)rtl_reallocateMemory( pConnections, sizeof( IceConn )*nConnections );
774cdf0e10cSrcweir                 pFilehandles = (struct pollfd*)rtl_reallocateMemory( pFilehandles, sizeof( struct pollfd )*(nConnections+1) );
775cdf0e10cSrcweir                 break;
776cdf0e10cSrcweir             }
777cdf0e10cSrcweir         }
778cdf0e10cSrcweir         if( nConnections == 0 && ICEThread )
779cdf0e10cSrcweir         {
780cdf0e10cSrcweir             SMprintf( "terminating ICEThread\n" );
781cdf0e10cSrcweir             osl_terminateThread( ICEThread );
782cdf0e10cSrcweir             wakeup();
783cdf0e10cSrcweir             // must release the mutex here
784cdf0e10cSrcweir             osl_releaseMutex( ICEMutex );
785cdf0e10cSrcweir             osl_joinWithThread( ICEThread );
786cdf0e10cSrcweir             osl_destroyThread( ICEThread );
787cdf0e10cSrcweir             close( nWakeupFiles[1] );
788cdf0e10cSrcweir             close( nWakeupFiles[0] );
789cdf0e10cSrcweir             ICEThread = NULL;
790cdf0e10cSrcweir         }
791cdf0e10cSrcweir     }
792cdf0e10cSrcweir     SMprintf( "ICE connection on %d %s\n",
793cdf0e10cSrcweir               IceConnectionNumber( connection ),
794cdf0e10cSrcweir               opening ? "inserted" : "removed" );
795cdf0e10cSrcweir     SMprintf( "Display connection is %d\n", ConnectionNumber( GetX11SalData()->GetDisplay()->GetDisplay() ) );
796cdf0e10cSrcweir #endif
797cdf0e10cSrcweir }
798