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