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:
VCLKDEApplication()66 VCLKDEApplication() : KApplication() {}
67
68 virtual void commitData(QSessionManager &sm);
69 };
70
commitData(QSessionManager &)71 void VCLKDEApplication::commitData(QSessionManager&)
72 {
73 }
74
75 /***************************************************************************
76 * class SalKDEDisplay *
77 ***************************************************************************/
78
SalKDEDisplay(Display * pDisp)79 SalKDEDisplay::SalKDEDisplay( Display* pDisp )
80 : SalX11Display( pDisp )
81 {
82 }
83
~SalKDEDisplay()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
~KDEXLib()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
Init()118 void KDEXLib::Init()
119 {
120 SalI18N_InputMethod* pInputMethod = new SalI18N_InputMethod;
121 pInputMethod->SetLocale();
122 XrmInitialize();
123
124 KAboutData *kAboutData = new KAboutData( "Apache OpenOffice",
125 I18N_NOOP( "Apache OpenOffice" ),
126 "3.4.0",
127 I18N_NOOP( "Apache OpenOffice with KDE Native Widget Support." ),
128 KAboutData::License_File,
129 "(c) 2003, 2004 Novell, Inc and Apache Software Foundation",
130 I18N_NOOP( "Apache OpenOffice is an office suite.\n" ),
131 "http://openoffice.apache.org/index.html",
132 "ooo-issues@incubator.apache.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
doStartup()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
~KDEData()214 KDEData::~KDEData()
215 {
216 }
217
Init()218 void KDEData::Init()
219 {
220 pXLib_ = new KDEXLib();
221 pXLib_->Init();
222 }
223
224 /**********************************************************************
225 * plugin entry point *
226 **********************************************************************/
227
228 extern "C" {
create_SalInstance(oslModule)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