LCOV - code coverage report
Current view: top level - vcl/unx/generic/app - sm.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 320 0.0 %
Date: 2012-08-25 Functions: 0 39 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

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

Generated by: LCOV version 1.10