1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_vcl.hxx" 30 31 #define _SV_SALDATA_CXX 32 #include <shell/kde_headers.h> 33 34 #include <unistd.h> 35 #include <fcntl.h> 36 37 #include <stdio.h> 38 #include <string.h> 39 #include <stdlib.h> 40 #include <limits.h> 41 #include <errno.h> 42 #include <poll.h> 43 #ifdef FREEBSD 44 #include <sys/types.h> 45 #include <sys/time.h> 46 #include <unistd.h> 47 #endif 48 49 #include <osl/thread.h> 50 #include <osl/process.h> 51 #include <osl/module.h> 52 53 #include <tools/debug.hxx> 54 55 #include <vos/process.hxx> 56 #include <vos/mutex.hxx> 57 58 #include "unx/kde/kdedata.hxx" 59 #include "unx/i18n_im.hxx" 60 #include "unx/i18n_xkb.hxx" 61 62 #include "vclpluginapi.h" 63 64 /* #i59042# override KApplications method for session management 65 * since it will interfere badly with our own. 66 */ 67 class VCLKDEApplication : public KApplication 68 { 69 public: 70 VCLKDEApplication() : KApplication() {} 71 72 virtual void commitData(QSessionManager &sm); 73 }; 74 75 void VCLKDEApplication::commitData(QSessionManager&) 76 { 77 } 78 79 /*************************************************************************** 80 * class SalKDEDisplay * 81 ***************************************************************************/ 82 83 SalKDEDisplay::SalKDEDisplay( Display* pDisp ) 84 : SalX11Display( pDisp ) 85 { 86 } 87 88 SalKDEDisplay::~SalKDEDisplay() 89 { 90 // in case never a frame opened 91 static_cast<KDEXLib*>(GetXLib())->doStartup(); 92 // clean up own members 93 doDestruct(); 94 // prevent SalDisplay from closing KApplication's display 95 pDisp_ = NULL; 96 } 97 98 /*************************************************************************** 99 * class KDEXLib * 100 ***************************************************************************/ 101 102 KDEXLib::~KDEXLib() 103 { 104 // #158056# on 64 bit linux using libXRandr.so.2 will crash in 105 // XCloseDisplay when freeing extension data 106 // no known work around, therefor currently leak. Hopefully 107 // this does not make problems since we're shutting down anyway 108 // should we ever get a real kde plugin that uses the KDE event loop 109 // we should use kde's method to signal screen changes similar 110 // to the gtk plugin 111 #if ! defined USE_RANDR || ! (defined LINUX && defined X86_64) 112 // properly deinitialize KApplication 113 delete (VCLKDEApplication*)m_pApplication; 114 #endif 115 // free the faked cmdline arguments no longer needed by KApplication 116 for( int i = 0; i < m_nFakeCmdLineArgs; i++ ) 117 free( m_pFreeCmdLineArgs[i] ); 118 delete [] m_pFreeCmdLineArgs; 119 delete [] m_pAppCmdLineArgs; 120 } 121 122 void KDEXLib::Init() 123 { 124 SalI18N_InputMethod* pInputMethod = new SalI18N_InputMethod; 125 pInputMethod->SetLocale(); 126 XrmInitialize(); 127 128 KAboutData *kAboutData = new KAboutData( "OpenOffice.org", 129 I18N_NOOP( "OpenOffice.org" ), 130 "1.1.0", 131 I18N_NOOP( "OpenOffice.org with KDE Native Widget Support." ), 132 KAboutData::License_LGPL, 133 "(c) 2003, 2004 Novell, Inc", 134 I18N_NOOP( "OpenOffice.org is an office suite.\n" ), 135 "http://kde.openoffice.org/index.html", 136 "dev@kde.openoffice.org"); 137 kAboutData->addAuthor( "Jan Holesovsky", 138 I18N_NOOP( "Original author and maintainer of the KDE NWF." ), 139 "kendy@artax.karlin.mff.cuni.cz", 140 "http://artax.karlin.mff.cuni.cz/~kendy" ); 141 142 m_nFakeCmdLineArgs = 1; 143 sal_uInt16 nIdx; 144 vos::OExtCommandLine aCommandLine; 145 int nParams = aCommandLine.getCommandArgCount(); 146 rtl::OString aDisplay; 147 rtl::OUString aParam, aBin; 148 149 for ( nIdx = 0; nIdx < nParams; ++nIdx ) 150 { 151 aCommandLine.getCommandArg( nIdx, aParam ); 152 if ( !m_pFreeCmdLineArgs && aParam.equalsAscii( "-display" ) && nIdx + 1 < nParams ) 153 { 154 aCommandLine.getCommandArg( nIdx + 1, aParam ); 155 aDisplay = rtl::OUStringToOString( aParam, osl_getThreadTextEncoding() ); 156 157 m_nFakeCmdLineArgs = 3; 158 m_pFreeCmdLineArgs = new char*[ m_nFakeCmdLineArgs ]; 159 m_pFreeCmdLineArgs[ 1 ] = strdup( "-display" ); 160 m_pFreeCmdLineArgs[ 2 ] = strdup( aDisplay.getStr() ); 161 } 162 } 163 if ( !m_pFreeCmdLineArgs ) 164 m_pFreeCmdLineArgs = new char*[ m_nFakeCmdLineArgs ]; 165 166 osl_getExecutableFile( &aParam.pData ); 167 osl_getSystemPathFromFileURL( aParam.pData, &aBin.pData ); 168 rtl::OString aExec = rtl::OUStringToOString( aBin, osl_getThreadTextEncoding() ); 169 m_pFreeCmdLineArgs[0] = strdup( aExec.getStr() ); 170 171 // make a copy of the string list for freeing it since 172 // KApplication manipulates the pointers inside the argument vector 173 // note: KApplication bad ! 174 m_pAppCmdLineArgs = new char*[ m_nFakeCmdLineArgs ]; 175 for( int i = 0; i < m_nFakeCmdLineArgs; i++ ) 176 m_pAppCmdLineArgs[i] = m_pFreeCmdLineArgs[i]; 177 178 KCmdLineArgs::init( m_nFakeCmdLineArgs, m_pAppCmdLineArgs, kAboutData ); 179 180 KApplication::disableAutoDcopRegistration(); 181 m_pApplication = new VCLKDEApplication(); 182 kapp->disableSessionManagement(); 183 184 Display* pDisp = QPaintDevice::x11AppDisplay(); 185 186 SalDisplay *pSalDisplay = new SalKDEDisplay( pDisp ); 187 188 pInputMethod->CreateMethod( pDisp ); 189 pInputMethod->AddConnectionWatch( pDisp, (void*)this ); 190 pSalDisplay->SetInputMethod( pInputMethod ); 191 192 PushXErrorLevel( true ); 193 SalI18N_KeyboardExtension *pKbdExtension = new SalI18N_KeyboardExtension( pDisp ); 194 XSync( pDisp, False ); 195 196 pKbdExtension->UseExtension( ! HasXErrorOccured() ); 197 PopXErrorLevel(); 198 199 pSalDisplay->SetKbdExtension( pKbdExtension ); 200 } 201 202 void KDEXLib::doStartup() 203 { 204 if( ! m_bStartupDone ) 205 { 206 KStartupInfo::appStarted(); 207 m_bStartupDone = true; 208 #if OSL_DEBUG_LEVEL > 1 209 fprintf( stderr, "called KStartupInfo::appStarted()\n" ); 210 #endif 211 } 212 } 213 214 /********************************************************************** 215 * class KDEData * 216 **********************************************************************/ 217 218 KDEData::~KDEData() 219 { 220 } 221 222 void KDEData::Init() 223 { 224 pXLib_ = new KDEXLib(); 225 pXLib_->Init(); 226 } 227 228 /********************************************************************** 229 * plugin entry point * 230 **********************************************************************/ 231 232 extern "C" { 233 VCLPLUG_KDE_PUBLIC SalInstance* create_SalInstance( oslModule ) 234 { 235 /* #i92121# workaround deadlocks in the X11 implementation 236 */ 237 static const char* pNoXInitThreads = getenv( "SAL_NO_XINITTHREADS" ); 238 /* #i90094# 239 from now on we know that an X connection will be 240 established, so protect X against itself 241 */ 242 if( ! ( pNoXInitThreads && *pNoXInitThreads ) ) 243 XInitThreads(); 244 245 rtl::OString aVersion( qVersion() ); 246 #if OSL_DEBUG_LEVEL > 1 247 fprintf( stderr, "qt version string is \"%s\"\n", aVersion.getStr() ); 248 #endif 249 sal_Int32 nIndex = 0, nMajor = 0, nMinor = 0, nMicro = 0; 250 nMajor = aVersion.getToken( 0, '.', nIndex ).toInt32(); 251 if( nIndex > 0 ) 252 nMinor = aVersion.getToken( 0, '.', nIndex ).toInt32(); 253 if( nIndex > 0 ) 254 nMicro = aVersion.getToken( 0, '.', nIndex ).toInt32(); 255 if( nMajor != 3 || nMinor < 2 || (nMinor == 2 && nMicro < 2) ) 256 { 257 #if OSL_DEBUG_LEVEL > 1 258 fprintf( stderr, "unsuitable qt version %d.%d.%d\n", (int)nMajor, (int)nMinor, (int)nMicro ); 259 #endif 260 return NULL; 261 } 262 263 KDESalInstance* pInstance = new KDESalInstance( new SalYieldMutex() ); 264 #if OSL_DEBUG_LEVEL > 1 265 fprintf( stderr, "created KDESalInstance 0x%p\n", pInstance ); 266 #endif 267 268 // initialize SalData 269 KDEData *pSalData = new KDEData(); 270 SetSalData( pSalData ); 271 pSalData->m_pInstance = pInstance; 272 pSalData->Init(); 273 pSalData->initNWF(); 274 275 return pInstance; 276 } 277 } 278