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