xref: /aoo42x/main/vcl/unx/kde/kdedata.cxx (revision cdf0e10c)
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