xref: /trunk/main/vcl/unx/generic/app/salinst.cxx (revision c82f2877)
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