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 #include <string.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 #include "osl/module.hxx"
32 #include "tools/solarmutex.hxx"
33 #include "vos/mutex.hxx"
34
35
36 #include "unx/salunx.h"
37 #include "unx/saldata.hxx"
38 #include "unx/saldisp.hxx"
39 #include "unx/salinst.h"
40 #include "unx/salframe.h"
41 #include "unx/dtint.hxx"
42 #include "unx/salprn.h"
43 #include "unx/sm.hxx"
44
45 #include "vcl/apptypes.hxx"
46 #include "vcl/helper.hxx"
47
48 #include "salwtype.hxx"
49
50 // -------------------------------------------------------------------------
51 //
52 // SalYieldMutex
53 //
54 // -------------------------------------------------------------------------
55
SalYieldMutex()56 SalYieldMutex::SalYieldMutex()
57 {
58 mnCount = 0;
59 mnThreadId = 0;
60 ::tools::SolarMutex::SetSolarMutex( this );
61 }
62
acquire()63 void SalYieldMutex::acquire()
64 {
65 OMutex::acquire();
66 mnThreadId = vos::OThread::getCurrentIdentifier();
67 mnCount++;
68 }
69
release()70 void SalYieldMutex::release()
71 {
72 if ( mnThreadId == vos::OThread::getCurrentIdentifier() )
73 {
74 if ( mnCount == 1 )
75 mnThreadId = 0;
76 mnCount--;
77 }
78 OMutex::release();
79 }
80
tryToAcquire()81 sal_Bool SalYieldMutex::tryToAcquire()
82 {
83 if ( OMutex::tryToAcquire() )
84 {
85 mnThreadId = vos::OThread::getCurrentIdentifier();
86 mnCount++;
87 return True;
88 }
89 else
90 return False;
91 }
92
93 //----------------------------------------------------------------------------
94
95 // -=-= SalInstance =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
96 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
97
98 // plugin factory function
99 extern "C"
100 {
create_SalInstance()101 VCLPLUG_GEN_PUBLIC SalInstance* create_SalInstance()
102 {
103 /* #i92121# workaround deadlocks in the X11 implementation
104 */
105 static const char* pNoXInitThreads = getenv( "SAL_NO_XINITTHREADS" );
106 /* #i90094#
107 from now on we know that an X connection will be
108 established, so protect X against itself
109 */
110 if( ! ( pNoXInitThreads && *pNoXInitThreads ) )
111 XInitThreads();
112
113 X11SalInstance* pInstance = new X11SalInstance( new SalYieldMutex() );
114
115 // initialize SalData
116 X11SalData *pSalData = new X11SalData;
117 SetSalData( pSalData );
118 pSalData->m_pInstance = pInstance;
119 pSalData->Init();
120
121 return pInstance;
122 }
123 }
124
~X11SalInstance()125 X11SalInstance::~X11SalInstance()
126 {
127 // close session management
128 SessionManagerClient::close();
129
130 // dispose SalDisplay list from SalData
131 // would be done in a static destructor else which is
132 // a little late
133
134 X11SalData *pSalData = GetX11SalData();
135 pSalData->deInitNWF();
136 delete pSalData;
137 SetSalData( NULL );
138
139 ::tools::SolarMutex::SetSolarMutex( 0 );
140 delete mpSalYieldMutex;
141 }
142
143
144 // --------------------------------------------------------
145 // AnyInput from sv/mow/source/app/svapp.cxx
146
147 struct PredicateReturn
148 {
149 sal_uInt16 nType;
150 sal_Bool bRet;
151 };
152
153 extern "C" {
ImplPredicateEvent(Display *,XEvent * pEvent,char * pData)154 Bool ImplPredicateEvent( Display *, XEvent *pEvent, char *pData )
155 {
156 PredicateReturn *pPre = (PredicateReturn *)pData;
157
158 if ( pPre->bRet )
159 return False;
160
161 sal_uInt16 nType;
162
163 switch( pEvent->type )
164 {
165 case ButtonPress:
166 case ButtonRelease:
167 case MotionNotify:
168 case EnterNotify:
169 case LeaveNotify:
170 nType = INPUT_MOUSE;
171 break;
172
173 case XLIB_KeyPress:
174 //case KeyRelease:
175 nType = INPUT_KEYBOARD;
176 break;
177 case Expose:
178 case GraphicsExpose:
179 case NoExpose:
180 nType = INPUT_PAINT;
181 break;
182 default:
183 nType = 0;
184 }
185
186 if ( (nType & pPre->nType) || ( ! nType && (pPre->nType & INPUT_OTHER) ) )
187 pPre->bRet = sal_True;
188
189 return False;
190 }
191 }
192
AnyInput(sal_uInt16 nType)193 bool X11SalInstance::AnyInput(sal_uInt16 nType)
194 {
195 X11SalData *pSalData = GetX11SalData();
196 Display *pDisplay = pSalData->GetDisplay()->GetDisplay();
197 sal_Bool bRet = sal_False;
198
199 if( (nType & INPUT_TIMER) &&
200 pSalData->GetDisplay()->GetXLib()->CheckTimeout( false ) )
201 {
202 bRet = sal_True;
203 }
204 else if (XPending(pDisplay) )
205 {
206 PredicateReturn aInput;
207 XEvent aEvent;
208
209 aInput.bRet = sal_False;
210 aInput.nType = nType;
211
212 XCheckIfEvent(pDisplay, &aEvent, ImplPredicateEvent,
213 (char *)&aInput );
214
215 bRet = aInput.bRet;
216 }
217 return bRet;
218 }
219
GetYieldMutex()220 vos::IMutex* X11SalInstance::GetYieldMutex()
221 {
222 return mpSalYieldMutex;
223 }
224
225 // -----------------------------------------------------------------------
226
ReleaseYieldMutex()227 sal_uLong X11SalInstance::ReleaseYieldMutex()
228 {
229 SalYieldMutex* pYieldMutex = mpSalYieldMutex;
230 if ( pYieldMutex->GetThreadId() ==
231 vos::OThread::getCurrentIdentifier() )
232 {
233 sal_uLong nCount = pYieldMutex->GetAcquireCount();
234 sal_uLong n = nCount;
235 while ( n )
236 {
237 pYieldMutex->release();
238 n--;
239 }
240
241 return nCount;
242 }
243 else
244 return 0;
245 }
246
247 // -----------------------------------------------------------------------
248
AcquireYieldMutex(sal_uLong nCount)249 void X11SalInstance::AcquireYieldMutex( sal_uLong nCount )
250 {
251 SalYieldMutex* pYieldMutex = mpSalYieldMutex;
252 while ( nCount )
253 {
254 pYieldMutex->acquire();
255 nCount--;
256 }
257 }
258
259 // -----------------------------------------------------------------------
260
CheckYieldMutex()261 bool X11SalInstance::CheckYieldMutex()
262 {
263 bool bRet = true;
264
265 SalYieldMutex* pYieldMutex = mpSalYieldMutex;
266 if ( pYieldMutex->GetThreadId() !=
267 vos::OThread::getCurrentIdentifier() )
268 {
269 bRet = false;
270 }
271
272 return bRet;
273 }
274
275 // -----------------------------------------------------------------------
276
Yield(bool bWait,bool bHandleAllCurrentEvents)277 void X11SalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
278 { GetX11SalData()->GetLib()->Yield( bWait, bHandleAllCurrentEvents ); }
279
GetConnectionIdentifier(ConnectionIdentifierType & rReturnedType,int & rReturnedBytes)280 void* X11SalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes )
281 {
282 static const char* pDisplay = getenv( "DISPLAY" );
283 rReturnedType = AsciiCString;
284 rReturnedBytes = pDisplay ? strlen( pDisplay )+1 : 1;
285 return pDisplay ? (void*)pDisplay : (void*)"";
286 }
287
CreateFrame(SalFrame * pParent,sal_uLong nSalFrameStyle)288 SalFrame *X11SalInstance::CreateFrame( SalFrame *pParent, sal_uLong nSalFrameStyle )
289 {
290 SalFrame *pFrame = new X11SalFrame( pParent, nSalFrameStyle );
291
292 return pFrame;
293 }
294
CreateChildFrame(SystemParentData * pParentData,sal_uLong nStyle)295 SalFrame* X11SalInstance::CreateChildFrame( SystemParentData* pParentData, sal_uLong nStyle )
296 {
297 SalFrame* pFrame = new X11SalFrame( NULL, nStyle, pParentData );
298
299 return pFrame;
300 }
301
DestroyFrame(SalFrame * pFrame)302 void X11SalInstance::DestroyFrame( SalFrame* pFrame )
303 {
304 delete pFrame;
305 }
306
getServerDirectories(std::list<rtl::OString> & o_rFontPaths)307 static void getServerDirectories( std::list< rtl::OString >& o_rFontPaths )
308 {
309 #ifdef LINUX
310 /*
311 * chkfontpath exists on some (RH derived) Linux distributions
312 */
313 static const char* pCommands[] = {
314 "/usr/sbin/chkfontpath 2>/dev/null", "chkfontpath 2>/dev/null"
315 };
316 ::std::list< ByteString > aLines;
317
318 for( unsigned int i = 0; i < sizeof(pCommands)/sizeof(pCommands[0]); i++ )
319 {
320 FILE* pPipe = popen( pCommands[i], "r" );
321 aLines.clear();
322 if( pPipe )
323 {
324 char line[1024];
325 char* pSearch;
326 while( fgets( line, sizeof(line), pPipe ) )
327 {
328 int nLen = strlen( line );
329 if( line[nLen-1] == '\n' )
330 line[nLen-1] = 0;
331 pSearch = strstr( line, ": " );
332 if( pSearch )
333 aLines.push_back( pSearch+2 );
334 }
335 if( ! pclose( pPipe ) )
336 break;
337 }
338 }
339
340 for( ::std::list< ByteString >::iterator it = aLines.begin(); it != aLines.end(); ++it )
341 {
342 if( ! access( it->GetBuffer(), F_OK ) )
343 {
344 o_rFontPaths.push_back( *it );
345 #if OSL_DEBUG_LEVEL > 1
346 fprintf( stderr, "adding fs dir %s\n", it->GetBuffer() );
347 #endif
348 }
349 }
350 #else
351 (void)o_rFontPaths;
352 #endif
353 }
354
355
356
FillFontPathList(std::list<rtl::OString> & o_rFontPaths)357 void X11SalInstance::FillFontPathList( std::list< rtl::OString >& o_rFontPaths )
358 {
359 Display *pDisplay = GetX11SalData()->GetDisplay()->GetDisplay();
360
361 DBG_ASSERT( pDisplay, "No Display !" );
362 if( pDisplay )
363 {
364 // get font paths to look for fonts
365 int nPaths = 0, i;
366 char** pPaths = XGetFontPath( pDisplay, &nPaths );
367
368 bool bServerDirs = false;
369 for( i = 0; i < nPaths; i++ )
370 {
371 OString aPath( pPaths[i] );
372 sal_Int32 nPos = 0;
373 if( ! bServerDirs
374 && ( nPos = aPath.indexOf( ':' ) ) > 0
375 && ( !aPath.copy(nPos).equals( ":unscaled" ) ) )
376 {
377 bServerDirs = true;
378 getServerDirectories( o_rFontPaths );
379 }
380 else
381 {
382 psp::normPath( aPath );
383 o_rFontPaths.push_back( aPath );
384 }
385 }
386
387 if( nPaths )
388 XFreeFontPath( pPaths );
389 }
390
391 // insert some standard directories
392 o_rFontPaths.push_back( "/usr/openwin/lib/X11/fonts/TrueType" );
393 o_rFontPaths.push_back( "/usr/openwin/lib/X11/fonts/Type1" );
394 o_rFontPaths.push_back( "/usr/openwin/lib/X11/fonts/Type1/sun" );
395 o_rFontPaths.push_back( "/usr/X11R6/lib/X11/fonts/truetype" );
396 o_rFontPaths.push_back( "/usr/X11R6/lib/X11/fonts/Type1" );
397
398 #ifdef SOLARIS
399 /* cde specials, from /usr/dt/bin/Xsession: here are the good fonts,
400 the OWfontpath file may contain as well multiple lines as a comma
401 separated list of fonts in each line. to make it even more weird
402 environment variables are allowed as well */
403
404 const char* lang = getenv("LANG");
405 if ( lang != NULL )
406 {
407 String aOpenWinDir( String::CreateFromAscii( "/usr/openwin/lib/locale/" ) );
408 aOpenWinDir.AppendAscii( lang );
409 aOpenWinDir.AppendAscii( "/OWfontpath" );
410
411 SvFileStream aStream( aOpenWinDir, STREAM_READ );
412
413 // TODO: replace environment variables
414 while( aStream.IsOpen() && ! aStream.IsEof() )
415 {
416 ByteString aLine;
417 aStream.ReadLine( aLine );
418 // need an OString for normpath
419 OString aNLine( aLine );
420 psp::normPath( aNLine );
421 aLine = aNLine;
422 // try to avoid bad fonts in some cases
423 static bool bAvoid = (strncasecmp( lang, "ar", 2 ) == 0) || (strncasecmp( lang, "he", 2 ) == 0) || strncasecmp( lang, "iw", 2 ) == 0 || (strncasecmp( lang, "hi", 2 ) == 0);
424 if( bAvoid && aLine.Search( "iso_8859" ) != STRING_NOTFOUND )
425 continue;
426 o_rFontPaths.push_back( aLine );
427 }
428 }
429 #endif /* SOLARIS */
430 }
431
thisModule()432 extern "C" { static void SAL_CALL thisModule() {} }
433
AddToRecentDocumentList(const rtl::OUString & rFileUrl,const rtl::OUString & rMimeType)434 void X11SalInstance::AddToRecentDocumentList(const rtl::OUString& rFileUrl, const rtl::OUString& rMimeType)
435 {
436 const rtl::OUString SYM_ADD_TO_RECENTLY_USED_FILE_LIST(RTL_CONSTASCII_USTRINGPARAM("add_to_recently_used_file_list"));
437 const rtl::OUString LIB_RECENT_FILE(RTL_CONSTASCII_USTRINGPARAM("librecentfile.so"));
438 typedef void (*PFUNC_ADD_TO_RECENTLY_USED_LIST)(const rtl::OUString&, const rtl::OUString&);
439
440 PFUNC_ADD_TO_RECENTLY_USED_LIST add_to_recently_used_file_list = 0;
441
442 osl::Module module;
443 module.loadRelative( &thisModule, LIB_RECENT_FILE );
444 if (module.is())
445 add_to_recently_used_file_list = (PFUNC_ADD_TO_RECENTLY_USED_LIST)module.getFunctionSymbol(SYM_ADD_TO_RECENTLY_USED_FILE_LIST);
446 if (add_to_recently_used_file_list)
447 add_to_recently_used_file_list(rFileUrl, rMimeType);
448 }
449