blob: 5d9a69d288cbd2b1c964885bd83a2b9634294cc6 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"
#ifdef USE_XTOOLKIT
# define SAL_XT
#endif
// -=-= #includes =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#include <unistd.h>
#include <fcntl.h>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <stdio.h> // snprintf, seems not to be in namespace std on every platform
#include <limits.h>
#include <errno.h>
#include <pthread.h>
#include <sys/resource.h>
#ifdef SUN
#include <sys/systeminfo.h>
#endif
#ifdef AIX
#include <strings.h>
#endif
#ifdef FREEBSD
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#endif
#include <vos/process.hxx>
#include <vos/mutex.hxx>
#include "unx/Xproto.h"
#include "unx/saldisp.hxx"
#include "unx/saldata.hxx"
#include "unx/salframe.h"
#include "unx/sm.hxx"
#include "unx/i18n_im.hxx"
#include "unx/i18n_xkb.hxx"
#include "salinst.hxx"
#include <osl/signal.h>
#include <osl/thread.h>
#include <osl/process.h>
#include <rtl/strbuf.hxx>
#include <rtl/bootstrap.hxx>
#include <tools/debug.hxx>
#include <vcl/svapp.hxx>
// -=-= <signal.h> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#ifndef UNX
#ifndef SIGBUS
#define SIGBUS 10
#endif
#ifndef SIGSEGV
#define SIGSEGV 11
#endif
#ifndef SIGIOT
#define SIGIOT SIGABRT
#endif
#endif
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
static const struct timeval noyield__ = { 0, 0 };
static const struct timeval yield__ = { 0, 10000 };
static const char* XRequest[] = {
// see /usr/lib/X11/XErrorDB, /usr/openwin/lib/XErrorDB ...
NULL,
"X_CreateWindow",
"X_ChangeWindowAttributes",
"X_GetWindowAttributes",
"X_DestroyWindow",
"X_DestroySubwindows",
"X_ChangeSaveSet",
"X_ReparentWindow",
"X_MapWindow",
"X_MapSubwindows",
"X_UnmapWindow",
"X_UnmapSubwindows",
"X_ConfigureWindow",
"X_CirculateWindow",
"X_GetGeometry",
"X_QueryTree",
"X_InternAtom",
"X_GetAtomName",
"X_ChangeProperty",
"X_DeleteProperty",
"X_GetProperty",
"X_ListProperties",
"X_SetSelectionOwner",
"X_GetSelectionOwner",
"X_ConvertSelection",
"X_SendEvent",
"X_GrabPointer",
"X_UngrabPointer",
"X_GrabButton",
"X_UngrabButton",
"X_ChangeActivePointerGrab",
"X_GrabKeyboard",
"X_UngrabKeyboard",
"X_GrabKey",
"X_UngrabKey",
"X_AllowEvents",
"X_GrabServer",
"X_UngrabServer",
"X_QueryPointer",
"X_GetMotionEvents",
"X_TranslateCoords",
"X_WarpPointer",
"X_SetInputFocus",
"X_GetInputFocus",
"X_QueryKeymap",
"X_OpenFont",
"X_CloseFont",
"X_QueryFont",
"X_QueryTextExtents",
"X_ListFonts",
"X_ListFontsWithInfo",
"X_SetFontPath",
"X_GetFontPath",
"X_CreatePixmap",
"X_FreePixmap",
"X_CreateGC",
"X_ChangeGC",
"X_CopyGC",
"X_SetDashes",
"X_SetClipRectangles",
"X_FreeGC",
"X_ClearArea",
"X_CopyArea",
"X_CopyPlane",
"X_PolyPoint",
"X_PolyLine",
"X_PolySegment",
"X_PolyRectangle",
"X_PolyArc",
"X_FillPoly",
"X_PolyFillRectangle",
"X_PolyFillArc",
"X_PutImage",
"X_GetImage",
"X_PolyText8",
"X_PolyText16",
"X_ImageText8",
"X_ImageText16",
"X_CreateColormap",
"X_FreeColormap",
"X_CopyColormapAndFree",
"X_InstallColormap",
"X_UninstallColormap",
"X_ListInstalledColormaps",
"X_AllocColor",
"X_AllocNamedColor",
"X_AllocColorCells",
"X_AllocColorPlanes",
"X_FreeColors",
"X_StoreColors",
"X_StoreNamedColor",
"X_QueryColors",
"X_LookupColor",
"X_CreateCursor",
"X_CreateGlyphCursor",
"X_FreeCursor",
"X_RecolorCursor",
"X_QueryBestSize",
"X_QueryExtension",
"X_ListExtensions",
"X_ChangeKeyboardMapping",
"X_GetKeyboardMapping",
"X_ChangeKeyboardControl",
"X_GetKeyboardControl",
"X_Bell",
"X_ChangePointerControl",
"X_GetPointerControl",
"X_SetScreenSaver",
"X_GetScreenSaver",
"X_ChangeHosts",
"X_ListHosts",
"X_SetAccessControl",
"X_SetCloseDownMode",
"X_KillClient",
"X_RotateProperties",
"X_ForceScreenSaver",
"X_SetPointerMapping",
"X_GetPointerMapping",
"X_SetModifierMapping",
"X_GetModifierMapping",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
"X_NoOperation"
};
// -=-= C statics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
int X11SalData::XErrorHdl( Display *pDisplay, XErrorEvent *pEvent )
{
GetX11SalData()->XError( pDisplay, pEvent );
return 0;
}
int X11SalData::XIOErrorHdl( Display * )
{
/* #106197# hack: until a real shutdown procedure exists
* _exit ASAP
*/
if( ImplGetSVData()->maAppData.mbAppQuit )
_exit(1);
// really bad hack
if( ! SessionManagerClient::checkDocumentsSaved() )
/* oslSignalAction eToDo = */ osl_raiseSignal (OSL_SIGNAL_USER_X11SUBSYSTEMERROR, NULL);
std::fprintf( stderr, "X IO Error\n" );
std::fflush( stdout );
std::fflush( stderr );
/* #106197# the same reasons to use _exit instead of exit in salmain
* do apply here. Since there is nothing to be done after an XIO
* error we have to _exit immediately.
*/
_exit(0);
return 0;
}
// -=-= SalData =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#include <pthread.h>
X11SalData::X11SalData()
{
bNoExceptions_ = !!getenv( "SAL_NOSEGV" );
pXLib_ = NULL;
m_pSalDisplay = NULL;
m_pInstance = NULL;
m_pPlugin = NULL;
hMainThread_ = pthread_self();
osl_getLocalHostname( &maLocalHostName.pData );
}
X11SalData::~X11SalData()
{
DeleteDisplay();
}
void X11SalData::DeleteDisplay()
{
delete m_pSalDisplay;
m_pSalDisplay = NULL;
delete pXLib_;
pXLib_ = NULL;
}
void X11SalData::Init()
{
pXLib_ = new SalXLib();
pXLib_->Init();
}
void X11SalData::initNWF( void )
{
}
void X11SalData::deInitNWF( void )
{
}
// -=-= SalXLib =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SalXLib::SalXLib()
{
m_aTimeout.tv_sec = 0;
m_aTimeout.tv_usec = 0;
m_nTimeoutMS = 0;
nFDs_ = 0;
FD_ZERO( &aReadFDS_ );
FD_ZERO( &aExceptionFDS_ );
m_pTimeoutFDS[0] = m_pTimeoutFDS[1] = -1;
if (pipe (m_pTimeoutFDS) != -1)
{
// initialize 'wakeup' pipe.
int flags;
// set close-on-exec descriptor flag.
if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFD)) != -1)
{
flags |= FD_CLOEXEC;
fcntl (m_pTimeoutFDS[0], F_SETFD, flags);
}
if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFD)) != -1)
{
flags |= FD_CLOEXEC;
fcntl (m_pTimeoutFDS[1], F_SETFD, flags);
}
// set non-blocking I/O flag.
if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFL)) != -1)
{
flags |= O_NONBLOCK;
fcntl (m_pTimeoutFDS[0], F_SETFL, flags);
}
if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFL)) != -1)
{
flags |= O_NONBLOCK;
fcntl (m_pTimeoutFDS[1], F_SETFL, flags);
}
// insert [0] into read descriptor set.
FD_SET( m_pTimeoutFDS[0], &aReadFDS_ );
nFDs_ = m_pTimeoutFDS[0] + 1;
}
m_bHaveSystemChildFrames = false;
m_aOrigXIOErrorHandler = XSetIOErrorHandler ( (XIOErrorHandler)X11SalData::XIOErrorHdl );
PushXErrorLevel( !!getenv( "SAL_IGNOREXERRORS" ) );
}
SalXLib::~SalXLib()
{
// close 'wakeup' pipe.
close (m_pTimeoutFDS[0]);
close (m_pTimeoutFDS[1]);
PopXErrorLevel();
XSetIOErrorHandler (m_aOrigXIOErrorHandler);
}
void SalXLib::PushXErrorLevel( bool bIgnore )
{
m_aXErrorHandlerStack.push_back( XErrorStackEntry() );
XErrorStackEntry& rEnt = m_aXErrorHandlerStack.back();
rEnt.m_bWas = false;
rEnt.m_bIgnore = bIgnore;
rEnt.m_nLastErrorRequest = 0;
rEnt.m_aHandler = XSetErrorHandler( (XErrorHandler)X11SalData::XErrorHdl );
}
void SalXLib::PopXErrorLevel()
{
if( m_aXErrorHandlerStack.size() )
{
XSetErrorHandler( m_aXErrorHandlerStack.back().m_aHandler );
m_aXErrorHandlerStack.pop_back();
}
}
void SalXLib::Init()
{
SalI18N_InputMethod* pInputMethod = new SalI18N_InputMethod;
pInputMethod->SetLocale();
XrmInitialize();
/*
* open connection to X11 Display
* try in this order:
* o -display command line parameter,
* o $DISPLAY environment variable
* o default display
*/
Display *pDisp = NULL;
// is there a -display command line parameter?
vos::OExtCommandLine aCommandLine;
sal_uInt32 nParams = aCommandLine.getCommandArgCount();
rtl::OUString aParam;
rtl::OString aDisplay;
for (sal_uInt16 i=0; i<nParams; i++)
{
aCommandLine.getCommandArg(i, aParam);
if (aParam.equalsAscii("-display"))
{
aCommandLine.getCommandArg(i+1, aParam);
aDisplay = rtl::OUStringToOString(
aParam, osl_getThreadTextEncoding());
if ((pDisp = XOpenDisplay(aDisplay.getStr()))!=NULL)
{
/*
* if a -display switch was used, we need
* to set the environment accoringly since
* the clipboard build another connection
* to the xserver using $DISPLAY
*/
rtl::OUString envVar(RTL_CONSTASCII_USTRINGPARAM("DISPLAY"));
osl_setEnvironment(envVar.pData, aParam.pData);
}
break;
}
}
if (!pDisp && !aDisplay.getLength())
{
// Open $DISPLAY or default...
char *pDisplay = getenv("DISPLAY");
if (pDisplay != NULL)
aDisplay = rtl::OString(pDisplay);
pDisp = XOpenDisplay(pDisplay);
}
if ( !pDisp )
{
rtl::OUString aProgramFileURL;
osl_getExecutableFile( &aProgramFileURL.pData );
rtl::OUString aProgramSystemPath;
osl_getSystemPathFromFileURL (aProgramFileURL.pData, &aProgramSystemPath.pData);
rtl::OString aProgramName = rtl::OUStringToOString(
aProgramSystemPath,
osl_getThreadTextEncoding() );
std::fprintf( stderr, "%s X11 error: Can't open display: %s\n",
aProgramName.getStr(), aDisplay.getStr());
std::fprintf( stderr, " Set DISPLAY environment variable, use -display option\n");
std::fprintf( stderr, " or check permissions of your X-Server\n");
std::fprintf( stderr, " (See \"man X\" resp. \"man xhost\" for details)\n");
std::fflush( stderr );
exit(0);
}
SalDisplay *pSalDisplay = new SalX11Display( pDisp );
pInputMethod->CreateMethod( pDisp );
pInputMethod->AddConnectionWatch( pDisp, (void*)this );
pSalDisplay->SetInputMethod( pInputMethod );
PushXErrorLevel( true );
SalI18N_KeyboardExtension *pKbdExtension = new SalI18N_KeyboardExtension( pDisp );
XSync( pDisp, False );
pKbdExtension->UseExtension( ! HasXErrorOccured() );
PopXErrorLevel();
pSalDisplay->SetKbdExtension( pKbdExtension );
}
extern "C" {
void EmitFontpathWarning( void )
{
static Bool bOnce = False;
if ( !bOnce )
{
bOnce = True;
std::fprintf( stderr, "Please verify your fontpath settings\n"
"\t(See \"man xset\" for details"
" or ask your system administrator)\n" );
}
}
} /* extern "C" */
static void PrintXError( Display *pDisplay, XErrorEvent *pEvent )
{
char msg[ 120 ] = "";
#if ! ( defined LINUX && defined PPC )
XGetErrorText( pDisplay, pEvent->error_code, msg, sizeof( msg ) );
#endif
std::fprintf( stderr, "X-Error: %s\n", msg );
if( pEvent->request_code < capacityof( XRequest ) )
{
const char* pName = XRequest[pEvent->request_code];
if( !pName )
pName = "BadRequest?";
std::fprintf( stderr, "\tMajor opcode: %d (%s)\n", pEvent->request_code, pName );
}
else
{
std::fprintf( stderr, "\tMajor opcode: %d\n", pEvent->request_code );
// TODO: also display extension name?
std::fprintf( stderr, "\tMinor opcode: %d\n", pEvent->minor_code );
}
std::fprintf( stderr, "\tResource ID: 0x%lx\n",
pEvent->resourceid );
std::fprintf( stderr, "\tSerial No: %ld (%ld)\n",
pEvent->serial, LastKnownRequestProcessed(pDisplay) );
if( !getenv( "SAL_SYNCHRONIZE" ) )
{
std::fprintf( stderr, "These errors are reported asynchronously,\n");
std::fprintf( stderr, "set environment variable SAL_SYNCHRONIZE to 1 to help debugging\n");
}
std::fflush( stdout );
std::fflush( stderr );
}
void SalXLib::XError( Display *pDisplay, XErrorEvent *pEvent )
{
if( m_bHaveSystemChildFrames )
return;
if( ! m_aXErrorHandlerStack.back().m_bIgnore )
{
if ( (pEvent->error_code == BadAlloc)
&& (pEvent->request_code == X_OpenFont) )
{
static Bool bOnce = False;
if ( !bOnce )
{
std::fprintf(stderr, "X-Error occured in a request for X_OpenFont\n");
EmitFontpathWarning();
bOnce = True ;
}
return;
}
/* ignore
* X_SetInputFocus: it's a hint only anyway
* X_GetProperty: this is part of the XGetWindowProperty call and will
* be handled by the return value of that function
*/
else if( pEvent->request_code == X_SetInputFocus ||
pEvent->request_code == X_GetProperty
)
return;
if( pDisplay != GetX11SalData()->GetDisplay()->GetDisplay() )
return;
PrintXError( pDisplay, pEvent );
oslSignalAction eToDo = osl_raiseSignal (OSL_SIGNAL_USER_X11SUBSYSTEMERROR, NULL);
switch (eToDo)
{
case osl_Signal_ActIgnore :
return;
case osl_Signal_ActAbortApp :
abort();
case osl_Signal_ActKillApp :
exit(0);
case osl_Signal_ActCallNextHdl :
break;
default :
break;
}
}
m_aXErrorHandlerStack.back().m_bWas = true;
}
struct YieldEntry
{
YieldEntry* next; // pointer to next entry
int fd; // file descriptor for reading
void* data; // data for predicate and callback
YieldFunc pending; // predicate (determins pending events)
YieldFunc queued; // read and queue up events
YieldFunc handle; // handle pending events
inline int HasPendingEvent() const { return pending( fd, data ); }
inline int IsEventQueued() const { return queued( fd, data ); }
inline void HandleNextEvent() const { handle( fd, data ); }
};
#define MAX_NUM_DESCRIPTORS 128
static YieldEntry yieldTable[ MAX_NUM_DESCRIPTORS ];
void SalXLib::Insert( int nFD, void* data,
YieldFunc pending,
YieldFunc queued,
YieldFunc handle )
{
DBG_ASSERT( nFD, "can not insert stdin descriptor" );
DBG_ASSERT( !yieldTable[nFD].fd, "SalXLib::Insert fd twice" );
yieldTable[nFD].fd = nFD;
yieldTable[nFD].data = data;
yieldTable[nFD].pending = pending;
yieldTable[nFD].queued = queued;
yieldTable[nFD].handle = handle;
FD_SET( nFD, &aReadFDS_ );
FD_SET( nFD, &aExceptionFDS_ );
if( nFD >= nFDs_ )
nFDs_ = nFD + 1;
}
void SalXLib::Remove( int nFD )
{
FD_CLR( nFD, &aReadFDS_ );
FD_CLR( nFD, &aExceptionFDS_ );
yieldTable[nFD].fd = 0;
if ( nFD == nFDs_ )
{
for ( nFD = nFDs_ - 1;
nFD >= 0 && !yieldTable[nFD].fd;
nFD-- ) ;
nFDs_ = nFD + 1;
}
}
bool SalXLib::CheckTimeout( bool bExecuteTimers )
{
bool bRet = false;
if( m_aTimeout.tv_sec ) // timer is started
{
timeval aTimeOfDay;
gettimeofday( &aTimeOfDay, 0 );
if( aTimeOfDay >= m_aTimeout )
{
bRet = true;
if( bExecuteTimers )
{
// timed out, update timeout
m_aTimeout = aTimeOfDay;
/*
* #107827# autorestart immediately, will be stopped (or set
* to different value in notify hdl if necessary;
* CheckTimeout should return false while
* timers are being dispatched.
*/
m_aTimeout += m_nTimeoutMS;
// notify
GetX11SalData()->Timeout();
}
}
}
return bRet;
}
void SalXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
{
// check for timeouts here if you want to make screenshots
static char* p_prioritize_timer = getenv ("SAL_HIGHPRIORITY_REPAINT");
if (p_prioritize_timer != NULL)
CheckTimeout();
const int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
// first, check for already queued events.
for ( int nFD = 0; nFD < nFDs_; nFD++ )
{
YieldEntry* pEntry = &(yieldTable[nFD]);
if ( pEntry->fd )
{
DBG_ASSERT( nFD == pEntry->fd, "wrong fd in Yield()" );
for( int i = 0; i < nMaxEvents && pEntry->HasPendingEvent(); i++ )
{
pEntry->HandleNextEvent();
if( ! bHandleAllCurrentEvents )
return;
}
}
}
// next, select with or without timeout according to bWait.
int nFDs = nFDs_;
fd_set ReadFDS = aReadFDS_;
fd_set ExceptionFDS = aExceptionFDS_;
int nFound = 0;
timeval Timeout = noyield__;
timeval *pTimeout = &Timeout;
if (bWait)
{
pTimeout = 0;
if (m_aTimeout.tv_sec) // Timer is started.
{
// determine remaining timeout.
gettimeofday (&Timeout, 0);
Timeout = m_aTimeout - Timeout;
if (yield__ >= Timeout)
{
// guard against micro timeout.
Timeout = yield__;
}
pTimeout = &Timeout;
}
}
{
// release YieldMutex (and re-acquire at block end)
YieldMutexReleaser aReleaser;
nFound = select( nFDs, &ReadFDS, NULL, &ExceptionFDS, pTimeout );
}
if( nFound < 0 ) // error
{
#ifdef DBG_UTIL
std::fprintf( stderr, "SalXLib::Yield e=%d f=%d\n", errno, nFound );
#endif
if( EINTR == errno )
{
errno = 0;
}
}
// usually handle timeouts here (as in 5.2)
if (p_prioritize_timer == NULL)
CheckTimeout();
// handle wakeup events.
if ((nFound > 0) && (FD_ISSET(m_pTimeoutFDS[0], &ReadFDS)))
{
int buffer;
while (read (m_pTimeoutFDS[0], &buffer, sizeof(buffer)) > 0)
continue;
nFound -= 1;
}
// handle other events.
if( nFound > 0 )
{
// now we are in the protected section !
// recall select if we have acquired fd's, ready for reading,
struct timeval noTimeout = { 0, 0 };
nFound = select( nFDs_, &ReadFDS, NULL,
&ExceptionFDS, &noTimeout );
// someone-else has done the job for us
if (nFound == 0)
return;
for ( int nFD = 0; nFD < nFDs_; nFD++ )
{
YieldEntry* pEntry = &(yieldTable[nFD]);
if ( pEntry->fd )
{
if ( FD_ISSET( nFD, &ExceptionFDS ) ) {
#if OSL_DEBUG_LEVEL > 1
std::fprintf( stderr, "SalXLib::Yield exception\n" );
#endif
nFound--;
}
if ( FD_ISSET( nFD, &ReadFDS ) )
{
for( int i = 0; pEntry->IsEventQueued() && i < nMaxEvents; i++ )
{
pEntry->HandleNextEvent();
// if a recursive call has done the job
// so abort here
}
nFound--;
}
}
}
}
}
void SalXLib::Wakeup()
{
write (m_pTimeoutFDS[1], "", 1);
}
void SalXLib::PostUserEvent()
{
Wakeup();
}
const char* X11SalData::getFrameResName()
{
/* according to ICCCM:
* first search command line for -name parameter
* then try RESOURCE_NAME environment variable
* then use argv[0] stripped by directories
*/
static rtl::OStringBuffer aResName;
if( !aResName.getLength() )
{
int nArgs = osl_getCommandArgCount();
for( int n = 0; n < nArgs-1; n++ )
{
rtl::OUString aArg;
if( ! osl_getCommandArg( n, &aArg.pData ) &&
aArg.equalsIgnoreAsciiCaseAscii( "-name" ) &&
! osl_getCommandArg( n+1, &aArg.pData ) )
{
aResName.append( rtl::OUStringToOString( aArg, osl_getThreadTextEncoding() ) );
break;
}
}
if( !aResName.getLength() )
{
const char* pEnv = getenv( "RESOURCE_NAME" );
if( pEnv && *pEnv )
aResName.append( pEnv );
}
if( !aResName.getLength() )
aResName.append( "VCLSalFrame" );
}
return aResName.getStr();
}
const char* X11SalData::getFrameClassName()
{
static rtl::OStringBuffer aClassName;
if( !aClassName.getLength() )
{
rtl::OUString aIni, aProduct;
rtl::Bootstrap::get( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OOO_BASE_DIR" ) ), aIni );
aIni += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/program/" SAL_CONFIGFILE( "bootstrap" ) ) );
rtl::Bootstrap aBootstrap( aIni );
aBootstrap.getFrom( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ProductKey" ) ), aProduct );
if( aProduct.getLength() )
aClassName.append( rtl::OUStringToOString( aProduct, osl_getThreadTextEncoding() ) );
else
aClassName.append( "VCLSalFrame" );
}
return aClassName.getStr();
}
rtl::OString X11SalData::getFrameResName( SalExtStyle nStyle )
{
rtl::OStringBuffer aBuf( 64 );
aBuf.append( getFrameResName() );
if( (nStyle & SAL_FRAME_EXT_STYLE_DOCUMENT) )
aBuf.append( ".DocumentWindow" );
return aBuf.makeStringAndClear();
}