blob: b3f03c9721e4a0f16ba5934d8cae867bacc4da3c [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"
#define SAL_XT
// -=-= #includes =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>
#include <pthread.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#if defined(SOLARIS)
#include <sal/alloca.h>
#include <osl/module.h>
#endif
#include <tools/prex.h>
#include <X11/cursorfont.h>
#include "unx/x11_cursors/salcursors.h"
#include "unx/x11_cursors/invert50.h"
#ifdef SOLARIS
#define XK_KOREAN
#endif
#include <X11/keysym.h>
#include <X11/Xatom.h>
#ifdef USE_XINERAMA
#ifdef USE_XINERAMA_XORG
#include <X11/extensions/Xinerama.h>
#elif defined USE_XINERAMA_XSUN
#if defined(SOLARIS) && defined(INTEL) // missing extension header in standard installation
#define MAXFRAMEBUFFERS 16
Bool XineramaGetState(Display*, int);
Status XineramaGetInfo(Display*, int, XRectangle*, unsigned char*, int*);
#else
#include <X11/extensions/xinerama.h>
#endif
#else
#error USE_XINERAMA but no xinerama version
#endif
#endif
#include <tools/postx.h>
#include <unx/salunx.h>
#include <sal/types.h>
#include "unx/i18n_im.hxx"
#include "unx/i18n_xkb.hxx"
#include <unx/saldisp.hxx>
#include <unx/saldata.hxx>
#include <salinst.hxx>
#include <unx/salgdi.h>
#include <unx/salframe.h>
#include <vcl/keycodes.hxx>
#include <vcl/salbtype.hxx>
#include <unx/salbmp.h>
#ifndef _OSL_THREADMUTEX_H_
#include <osl/mutex.h>
#endif
#include <unx/salobj.h>
#include <unx/sm.hxx>
#include <unx/wmadaptor.hxx>
#include <unx/dtint.hxx>
#include <osl/socket.h>
#include <poll.h>
using namespace rtl;
using namespace vcl_sal;
// -=-= #defines -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#define PSEUDOCOLOR12
#define PSEUDOCOLOR8
#define TRUECOLOR24
#define TRUECOLOR16
#define TRUECOLOR15
#define TRUECOLOR12
#define TRUECOLOR8
#define SALCOLOR_WHITE MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF )
#define SALCOLOR_BLACK MAKE_SALCOLOR( 0x00, 0x00, 0x00 )
// -=-= Prototyps =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-= static variables -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
static const char* const VisualClassName[] = {
"StaticGray",
"GrayScale",
"StaticColor",
"PseudoColor",
"TrueColor",
"DirectColor"
};
static const char* const EventNames[] =
{
NULL,
NULL,
"KeyPress",
"KeyRelease",
"ButtonPress",
"ButtonRelease",
"MotionNotify",
"EnterNotify",
"LeaveNotify",
"FocusIn",
"FocusOut",
"KeymapNotify",
"Expose",
"GraphicsExpose",
"NoExpose",
"VisibilityNotify",
"CreateNotify",
"DestroyNotify",
"UnmapNotify",
"MapNotify",
"MapRequest",
"ReparentNotify",
"ConfigureNotify",
"ConfigureRequest",
"GravityNotify",
"ResizeRequest",
"CirculateNotify",
"CirculateRequest",
"PropertyNotify",
"SelectionClear",
"SelectionRequest",
"SelectionNotify",
"ColormapNotify",
"ClientMessage",
"MappingNotify"
};
// -=-= global inline =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
inline const char *Null( const char *p ) { return p ? p : ""; }
inline const char *GetEnv( const char *p ) { return Null( getenv( p ) ); }
inline const char *KeyStr( KeySym n ) { return Null( XKeysymToString( n ) ); }
inline const char *GetAtomName( Display *d, Atom a )
{ return Null( XGetAtomName( d, a ) ); }
inline double Hypothenuse( long w, long h )
{ return sqrt( (double)((w*w)+(h*h)) ); }
inline int ColorDiff( int r, int g, int b )
{ return (r*r)+(g*g)+(b*b); }
inline int ColorDiff( SalColor c1, int r, int g, int b )
{ return ColorDiff( (int)SALCOLOR_RED (c1)-r,
(int)SALCOLOR_GREEN(c1)-g,
(int)SALCOLOR_BLUE (c1)-b ); }
// -=-= global functions -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
static int sal_Shift( Pixel nMask )
{
int i = 24;
if( nMask < 0x00010000 ) { nMask <<= 16; i -= 16; }
if( nMask < 0x01000000 ) { nMask <<= 8; i -= 8; }
if( nMask < 0x10000000 ) { nMask <<= 4; i -= 4; }
if( nMask < 0x40000000 ) { nMask <<= 2; i -= 2; }
if( nMask < 0x80000000 ) { nMask <<= 1; i -= 1; }
return i;
}
static int sal_significantBits( Pixel nMask )
{
int nRotate = sizeof(Pixel)*4;
int nBits = 0;
while( nRotate-- )
{
if( nMask & 1 )
nBits++;
nMask >>= 1;
}
return nBits;
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
static sal_Bool sal_GetVisualInfo( Display *pDisplay, XID nVID, XVisualInfo &rVI )
{
int nInfos;
XVisualInfo aTemplate;
XVisualInfo*pInfos;
aTemplate.visualid = nVID;
pInfos = XGetVisualInfo( pDisplay, VisualIDMask, &aTemplate, &nInfos );
if( !pInfos )
return sal_False;
rVI = *pInfos;
XFree( pInfos );
DBG_ASSERT( rVI.visualid == nVID,
"sal_GetVisualInfo: could not get correct visual by visualId" );
return sal_True;
}
// ---------------------------------------------------------------------------
// check wether displaystring is in format N.M or N. or just N
// with N and M beeing natural numbers
static sal_Bool
sal_IsDisplayNumber( const char *pDisplayString )
{
if ( ! isdigit(*pDisplayString) )
return sal_False;
while ( isdigit(*(++pDisplayString)) )
; /* do nothing */
if ( *pDisplayString == '.' )
{
while ( isdigit(*(++pDisplayString)) )
; /* do nothing */
}
return (*pDisplayString == '\0');
}
// check whether host1 and host2 point to the same ip address
static sal_Bool
sal_EqualHosts( const OUString& Host1, const OUString& Host2)
{
oslSocketAddr pHostAddr1;
oslSocketAddr pHostAddr2;
sal_Bool bEqualAddress = sal_False;
if ( Host1.toChar() >= '0' && Host1.toChar() <= '9' )
pHostAddr1 = osl_createInetSocketAddr( Host1.pData, 0 );
else
pHostAddr1 = osl_resolveHostname( Host1.pData );
if ( Host2.toChar() >= '0' && Host2.toChar() <= '9' )
pHostAddr2 = osl_createInetSocketAddr( Host2.pData, 0 );
else
pHostAddr2 = osl_resolveHostname( Host2.pData );
if( pHostAddr1 && pHostAddr2 )
bEqualAddress = osl_isEqualSocketAddr( pHostAddr1, pHostAddr2 ) ? sal_True : sal_False;
if( pHostAddr1 )
osl_destroySocketAddr( pHostAddr1 );
if( pHostAddr2 )
osl_destroySocketAddr( pHostAddr2 );
return bEqualAddress;
}
static sal_Bool
sal_IsLocalDisplay( Display *pDisplay )
{
const char *pDisplayString = DisplayString( pDisplay );
// no string, no idea
if ( pDisplayString == NULL || pDisplayString[ 0 ] == '\0')
return sal_False;
// check for ":x.y"
if ( pDisplayString[ 0 ] == ':' )
return sal_IsDisplayNumber( pDisplayString + 1 );
// check for fixed token which all mean localhost:x.y
const char pLocal[] = "localhost:";
const int nLocalLen = sizeof(pLocal) - 1;
if ( strncmp(pDisplayString, pLocal, nLocalLen) == 0 )
return sal_IsDisplayNumber( pDisplayString + nLocalLen );
const char pUnix[] = "unix:";
const int nUnixLen = sizeof(pUnix) - 1;
if ( strncmp(pDisplayString, pUnix, nUnixLen) == 0 )
return sal_IsDisplayNumber( pDisplayString + nUnixLen );
const char pLoopback[] = "127.0.0.1:";
const int nLoopbackLen= sizeof(pLoopback) - 1;
if ( strncmp(pDisplayString, pLoopback, nLoopbackLen) == 0 )
return sal_IsDisplayNumber( pDisplayString + nLoopbackLen );
// compare local hostname to displaystring, both may be ip address or
// hostname
sal_Bool bEqual = sal_False;
char *pDisplayHost = strdup( pDisplayString );
char *pPtr = strrchr( pDisplayHost, ':' );
if( pPtr != NULL )
{
const OUString& rLocalHostname( GetX11SalData()->GetLocalHostName() );
if( rLocalHostname.getLength() )
{
*pPtr = '\0';
OUString aDisplayHostname( pDisplayHost, strlen( pDisplayHost ), osl_getThreadTextEncoding() );
bEqual = sal_EqualHosts( rLocalHostname, aDisplayHostname );
bEqual = bEqual && sal_IsDisplayNumber( pPtr + 1 );
}
}
free( pDisplayHost );
return bEqual;
}
// ---------------------------------------------------------------------------
// IsLocal means soffice is running on the same host as the xserver
// since it is not called very often and sal_IsLocalDisplay() is relative
// expensive bLocal_ is initialized on first call
sal_Bool SalDisplay::IsLocal()
{
if ( ! mbLocalIsValid )
{
bLocal_ = sal_IsLocalDisplay( pDisp_ );
mbLocalIsValid = sal_True;
}
return (sal_Bool)bLocal_;
}
// ---------------------------------------------------------------------------
extern "C" srv_vendor_t
sal_GetServerVendor( Display *p_display )
{
typedef struct {
srv_vendor_t e_vendor; // vendor as enum
const char *p_name; // vendor name as returned by VendorString()
unsigned int n_len; // number of chars to compare
} vendor_t;
const vendor_t p_vendorlist[] = {
{ vendor_xfree, "The XFree86 Project, Inc", 13 },
{ vendor_sun, "Sun Microsystems, Inc.", 10 },
{ vendor_attachmate, "Attachmate Corporation", 10 },
{ vendor_excursion,
"DECWINDOWS DigitalEquipmentCorporation, eXcursion", 42 },
{ vendor_hp, "Hewlett-Packard Company", 17 },
{ vendor_hummingbird, "Hummingbird Communications Ltd.", 11 },
{ vendor_ibm, "International Business Machines", 24 },
{ vendor_sgi, "Silicon Graphics", 9 },
{ vendor_sco, "The Santa Cruz Operation", 16 },
{ vendor_xinside, "X Inside Inc.", 10 },
// allways the last entry: vendor_none to indicate eol
{ vendor_none, NULL, 0 },
};
// handle regular server vendors
char *p_name = ServerVendor( p_display );
vendor_t *p_vendor;
for (p_vendor = const_cast<vendor_t*>(p_vendorlist); p_vendor->e_vendor != vendor_none; p_vendor++)
{
if ( strncmp (p_name, p_vendor->p_name, p_vendor->n_len) == 0 )
return p_vendor->e_vendor;
}
// vendor not found in list
return vendor_unknown;
}
static sal_Bool sal_IsTrustedSolaris (Display *p_display)
{
int n_numextensions = 0;
char **p_extensions = XListExtensions (p_display, &n_numextensions);
sal_Bool b_is = sal_False;
if (p_extensions != NULL)
{
for (int i = 0; !b_is && i < n_numextensions; i++)
b_is = (strcmp (p_extensions[i], "SUN_TSOL") == 0);
XFreeExtensionList (p_extensions);
}
return b_is;
}
// -=-= SalDisplay -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sal_Bool SalDisplay::BestVisual( Display *pDisplay,
int nScreen,
XVisualInfo &rVI )
{
VisualID nDefVID = XVisualIDFromVisual( DefaultVisual( pDisplay, nScreen ) );
VisualID nVID = 0;
char *pVID = getenv( "SAL_VISUAL" );
if( pVID )
sscanf( pVID, "%li", &nVID );
if( nVID && sal_GetVisualInfo( pDisplay, nVID, rVI ) )
return rVI.visualid == nDefVID;
XVisualInfo aVI;
aVI.screen = nScreen;
// get all visuals
int nVisuals;
XVisualInfo* pVInfos = XGetVisualInfo( pDisplay, VisualScreenMask,
&aVI, &nVisuals );
// pVInfos should contain at least one visual, otherwise
// we're in trouble
int* pWeight = (int*)alloca( sizeof(int)*nVisuals );
int i;
for( i = 0; i < nVisuals; i++ )
{
sal_Bool bUsable = sal_False;
int nTrueColor = 1;
if ( pVInfos[i].screen != nScreen )
{
bUsable = sal_False;
}
else
if( pVInfos[i].c_class == TrueColor )
{
nTrueColor = 2048;
if( pVInfos[i].depth == 24 )
bUsable = sal_True;
#ifdef sal_TrueCOLOR8
else if( pVInfos[i].depth == 8 )
{
nTrueColor = -1; // strongly discourage 8 bit true color
bUsable = sal_True;
}
#endif
#ifdef sal_TrueCOLOR15
else if( pVInfos[i].depth == 15 )
bUsable = sal_True;
#endif
#ifdef sal_TrueCOLOR16
else if( pVInfos[i].depth == 16 )
bUsable = sal_True;
#endif
#ifdef sal_TrueCOLOR32
else if( pVInfos[i].depth == 32 )
{
nTrueColor = 256;
// we do not have use for an alpha channel
// better use a 24 or 16 bit truecolor visual if possible
bUsable = sal_True;
}
#endif
}
else if( pVInfos[i].c_class == PseudoColor )
{
if( pVInfos[i].depth <= 8 )
bUsable = sal_True;
#ifdef PSEUDOCOLOR12
else if( pVInfos[i].depth == 12 )
bUsable = sal_True;
#endif
}
pWeight[ i ] = bUsable ? nTrueColor*pVInfos[i].depth : -1024;
pWeight[ i ] -= pVInfos[ i ].visualid;
}
int nBestVisual = 0;
int nBestWeight = -1024;
for( i = 0; i < nVisuals; i++ )
{
if( pWeight[ i ] > nBestWeight )
{
nBestWeight = pWeight[ i ];
nBestVisual = i;
}
}
rVI = pVInfos[ nBestVisual ];
XFree( pVInfos );
return rVI.visualid == nDefVID;
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SalDisplay::SalDisplay( Display *display ) :
mpInputMethod( NULL ),
pDisp_( display ),
m_pWMAdaptor( NULL ),
m_pDtIntegrator( NULL ),
m_bUseRandRWrapper( true ),
m_nLastUserEventTime( CurrentTime )
{
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr, "SalDisplay::SalDisplay()\n" );
#endif
X11SalData *pSalData = GetX11SalData();
DBG_ASSERT( ! pSalData->GetDisplay(), "Second SalDisplay created !!!\n" );
pSalData->SetSalDisplay( this );
pXLib_ = pSalData->GetLib();
m_nDefaultScreen = DefaultScreen( pDisp_ );
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SalDisplay::~SalDisplay( )
{
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr, "SalDisplay::~SalDisplay()\n" );
#endif
if( pDisp_ )
{
doDestruct();
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr, "display %p closed\n", pDisp_ );
#endif
pDisp_ = NULL;
}
// don't do this in doDestruct since RandR extension adds hooks into Display
// that is XCloseDisplay still needs the RandR library if it was used
DeInitRandR();
}
void SalDisplay::doDestruct()
{
X11SalData *pSalData = GetX11SalData();
delete m_pWMAdaptor;
m_pWMAdaptor = NULL;
delete m_pDtIntegrator;
m_pDtIntegrator = NULL;
X11SalBitmap::ImplDestroyCache();
X11SalGraphics::releaseGlyphPeer();
if( IsDisplay() )
{
delete mpInputMethod, mpInputMethod = (SalI18N_InputMethod*)ILLEGAL_POINTER;
delete mpKbdExtension, mpKbdExtension = (SalI18N_KeyboardExtension*)ILLEGAL_POINTER;
// do not call anything that could implicitly call back into
// this object after this point
osl_destroyMutex( hEventGuard_ );
for( unsigned int i = 0; i < m_aScreens.size(); i++ )
{
ScreenData& rData = m_aScreens[i];
if( rData.m_bInit )
{
if( rData.m_aMonoGC != rData.m_aCopyGC )
XFreeGC( pDisp_, rData.m_aMonoGC );
XFreeGC( pDisp_, rData.m_aCopyGC );
XFreeGC( pDisp_, rData.m_aAndInvertedGC );
XFreeGC( pDisp_, rData.m_aAndGC );
XFreeGC( pDisp_, rData.m_aOrGC );
XFreeGC( pDisp_, rData.m_aStippleGC );
XFreePixmap( pDisp_, rData.m_hInvert50 );
XDestroyWindow( pDisp_, rData.m_aRefWindow );
Colormap aColMap = rData.m_aColormap.GetXColormap();
if( aColMap != None && aColMap != DefaultColormap( pDisp_, i ) )
XFreeColormap( pDisp_, aColMap );
}
}
hEventGuard_ = (oslMutex)ILLEGAL_POINTER;
for( size_t i = 0; i < POINTER_COUNT; i++ )
{
if( aPointerCache_[i] )
XFreeCursor( pDisp_, aPointerCache_[i] );
}
pXLib_->Remove( ConnectionNumber( pDisp_ ) );
}
if( pSalData->GetDisplay() == this )
pSalData->SetSalDisplay( NULL );
}
static int DisplayHasEvent( int
#ifdef DBG_UTIL
fd
#endif
, SalX11Display *pDisplay )
{
DBG_ASSERT( ConnectionNumber( pDisplay->GetDisplay() ) == fd,
"wrong fd in DisplayHasEvent" );
if( ! pDisplay->IsDisplay() )
return 0;
vos::IMutex* pSalInstYieldMutex =
GetSalData()->m_pInstance->GetYieldMutex();
::vos::OGuard aGuard( *pSalInstYieldMutex );
return pDisplay->IsEvent();
}
static int DisplayQueue( int
#ifdef DBG_UTIL
fd
#endif
, SalX11Display *pDisplay )
{
DBG_ASSERT( ConnectionNumber( pDisplay->GetDisplay() ) == fd,
"wrong fd in DisplayHasEvent" );
vos::IMutex* pSalInstYieldMutex =
GetSalData()->m_pInstance->GetYieldMutex();
::vos::OGuard aGuard( *pSalInstYieldMutex );
return XEventsQueued( pDisplay->GetDisplay(),
QueuedAfterReading );
}
static int DisplayYield( int
#ifdef DBG_UTIL
fd
#endif
, SalX11Display *pDisplay )
{
DBG_ASSERT( ConnectionNumber( pDisplay->GetDisplay() ) == fd,
"wrong fd in DisplayHasEvent" );
vos::IMutex* pSalInstYieldMutex =
GetSalData()->m_pInstance->GetYieldMutex();
::vos::OGuard aGuard( *pSalInstYieldMutex );
pDisplay->Yield();
return sal_True;
}
SalX11Display::SalX11Display( Display *display )
: SalDisplay( display )
{
Init();
pXLib_->Insert( ConnectionNumber( pDisp_ ),
this,
(YieldFunc) DisplayHasEvent,
(YieldFunc) DisplayQueue,
(YieldFunc) DisplayYield );
}
SalX11Display::~SalX11Display()
{
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr, "SalX11Display::~SalX11Display()\n" );
#endif
if( pDisp_ )
{
doDestruct();
XCloseDisplay( pDisp_ );
pDisp_ = NULL;
}
}
void SalDisplay::initScreen( int nScreen ) const
{
if( nScreen < 0 || nScreen >= static_cast<int>(m_aScreens.size()) )
nScreen = m_nDefaultScreen;
ScreenData& rSD = const_cast<ScreenData&>(m_aScreens[nScreen]);
if( rSD.m_bInit )
return;
rSD.m_bInit = true;
XVisualInfo aVI;
Colormap aColMap;
if( SalDisplay::BestVisual( pDisp_, nScreen, aVI ) ) // DefaultVisual
aColMap = DefaultColormap( pDisp_, nScreen );
else
aColMap = XCreateColormap( pDisp_,
RootWindow( pDisp_, nScreen ),
aVI.visual,
AllocNone );
Screen* pScreen = ScreenOfDisplay( pDisp_, nScreen );
rSD.m_aSize = Size( WidthOfScreen( pScreen ), HeightOfScreen( pScreen ) );
rSD.m_aRoot = RootWindow( pDisp_, nScreen );
rSD.m_aVisual = SalVisual( &aVI );
rSD.m_aColormap = SalColormap( this, aColMap, nScreen );
// we're interested in configure notification of root windows
InitRandR( rSD.m_aRoot );
// - - - - - - - - - - Reference Window/Default Drawable - -
XSetWindowAttributes aXWAttributes;
aXWAttributes.border_pixel = 0;
aXWAttributes.background_pixel = 0;
aXWAttributes.colormap = aColMap;
rSD.m_aRefWindow = XCreateWindow( pDisp_,
rSD.m_aRoot,
0,0, 16,16, 0,
rSD.m_aVisual.GetDepth(),
InputOutput,
rSD.m_aVisual.GetVisual(),
CWBorderPixel|CWBackPixel|CWColormap,
&aXWAttributes );
// set client leader (session id gets set when session is started)
if( rSD.m_aRefWindow )
{
// client leader must have WM_CLIENT_LEADER pointing to itself
XChangeProperty( pDisp_,
rSD.m_aRefWindow,
XInternAtom( pDisp_, "WM_CLIENT_LEADER", False ),
XA_WINDOW,
32,
PropModeReplace,
(unsigned char*)&rSD.m_aRefWindow,
1
);
ByteString aExec( SessionManagerClient::getExecName(), osl_getThreadTextEncoding() );
const char* argv[2];
argv[0] = "/bin/sh";
argv[1] = aExec.GetBuffer();
XSetCommand( pDisp_, rSD.m_aRefWindow, const_cast<char**>(argv), 2 );
XSelectInput( pDisp_, rSD.m_aRefWindow, PropertyChangeMask );
// - - - - - - - - - - GCs - - - - - - - - - - - - - - - - -
XGCValues values;
values.graphics_exposures = False;
values.fill_style = FillOpaqueStippled;
values.background = (1<<rSD.m_aVisual.GetDepth())-1;
values.foreground = 0;
rSD.m_aCopyGC = XCreateGC( pDisp_,
rSD.m_aRefWindow,
GCGraphicsExposures
| GCForeground
| GCBackground,
&values );
rSD.m_aAndInvertedGC= XCreateGC( pDisp_,
rSD.m_aRefWindow,
GCGraphicsExposures
| GCForeground
| GCBackground,
&values );
rSD.m_aAndGC = XCreateGC( pDisp_,
rSD.m_aRefWindow,
GCGraphicsExposures
| GCForeground
| GCBackground,
&values );
rSD.m_aOrGC = XCreateGC( pDisp_,
rSD.m_aRefWindow,
GCGraphicsExposures
| GCForeground
| GCBackground,
&values );
rSD.m_aStippleGC = XCreateGC( pDisp_,
rSD.m_aRefWindow,
GCGraphicsExposures
| GCFillStyle
| GCForeground
| GCBackground,
&values );
XSetFunction( pDisp_, rSD.m_aAndInvertedGC, GXandInverted );
XSetFunction( pDisp_, rSD.m_aAndGC, GXand );
// #44556# PowerPC Solaris 2.5 (XSun 3500) Bug: GXor = GXnop
//XSetFunction( pDisp_, pOrGC_, GXor );
XSetFunction( pDisp_, rSD.m_aOrGC, GXxor );
if( 1 == rSD.m_aVisual.GetDepth() )
{
XSetFunction( pDisp_, rSD.m_aCopyGC, GXcopyInverted );
rSD.m_aMonoGC = rSD.m_aCopyGC;
}
else
{
Pixmap hPixmap = XCreatePixmap( pDisp_, rSD.m_aRefWindow, 1, 1, 1 );
rSD.m_aMonoGC = XCreateGC( pDisp_,
hPixmap,
GCGraphicsExposures,
&values );
XFreePixmap( pDisp_, hPixmap );
}
rSD.m_hInvert50 = XCreateBitmapFromData( pDisp_,
rSD.m_aRefWindow,
(const char*)invert50_bits,
invert50_width,
invert50_height );
}
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void SalDisplay::Init()
{
for( size_t i = 0; i < POINTER_COUNT; i++ )
aPointerCache_[i] = None;
eWindowManager_ = otherwm;
nProperties_ = PROPERTY_DEFAULT;
hEventGuard_ = NULL;
mpFactory = (AttributeProvider*)NULL;
m_pCapture = NULL;
m_bXinerama = false;
int nDisplayScreens = ScreenCount( pDisp_ );
m_aScreens = std::vector<ScreenData>(nDisplayScreens);
mbExactResolution = false;
/* #i15507#
* Xft resolution should take precedence since
* it is what modern desktops use.
*/
const char* pValStr = XGetDefault( pDisp_, "Xft", "dpi" );
if( pValStr != NULL )
{
const rtl::OString aValStr( pValStr );
const long nDPI = (long) aValStr.toDouble();
// guard against insane resolution
if( (nDPI >= 50) && (nDPI <= 500) )
{
aResolution_ = Pair( nDPI, nDPI );
mbExactResolution = true;
}
}
if( mbExactResolution == false )
{
aResolution_ =
Pair( DPI( WidthOfScreen( DefaultScreenOfDisplay( pDisp_ ) ), DisplayWidthMM ( pDisp_, m_nDefaultScreen ) ),
DPI( HeightOfScreen( DefaultScreenOfDisplay( pDisp_ ) ), DisplayHeightMM( pDisp_, m_nDefaultScreen ) ) );
}
nMaxRequestSize_ = XExtendedMaxRequestSize( pDisp_ ) * 4;
if( !nMaxRequestSize_ )
nMaxRequestSize_ = XMaxRequestSize( pDisp_ ) * 4;
SetServerVendor();
X11SalBitmap::ImplCreateCache();
hEventGuard_ = osl_createMutex();
bLocal_ = sal_False; /* dont care, initialize later by
calling SalDisplay::IsLocal() */
mbLocalIsValid = sal_False; /* bLocal_ is not yet initialized */
// - - - - - - - - - - Synchronize - - - - - - - - - - - - -
if( getenv( "SAL_SYNCHRONIZE" ) )
XSynchronize( pDisp_, True );
// - - - - - - - - - - Keyboardmapping - - - - - - - - - - -
ModifierMapping();
// - - - - - - - - - - Window Manager - - - - - - - - - - -
m_pWMAdaptor = ::vcl_sal::WMAdaptor::createWMAdaptor( this );
const char *pWM = getenv( "SAL_WM" );
if( pWM )
{
long int nWM = 0;
sscanf( pWM, "%li", &nWM );
eWindowManager_ = SalWM(nWM);
}
else if( XInternAtom( pDisp_, "_SGI_TELL_WM", True ) )
eWindowManager_ = FourDwm;
else if( XInternAtom( pDisp_, "KWM_RUNNING", True ) )
eWindowManager_ = mwm; // naja, eigentlich kwm ...
else if( XInternAtom( pDisp_, "_OL_WIN_ATTR", True ) )
eWindowManager_ = olwm;
else if( m_pWMAdaptor->getWindowManagerName().EqualsAscii( "Dtwm" ) )
eWindowManager_ = dtwm;
// - - - - - - - - - - Properties - - - - - - - - - - - - -
const char *pProperties = getenv( "SAL_PROPERTIES" );
if( pProperties )
sscanf( pProperties, "%li", &nProperties_ );
else
{
#if defined DBG_UTIL || defined SUN || defined LINUX || defined FREEBSD
nProperties_ |= PROPERTY_FEATURE_Maximize;
#endif
// Server Bugs & Properties
if( GetServerVendor() == vendor_excursion )
{
nProperties_ |= PROPERTY_BUG_Stipple;
nProperties_ |= PROPERTY_BUG_DrawLine;
nProperties_ &= ~PROPERTY_SUPPORT_XSetClipMask;
}
else
if( GetServerVendor() == vendor_attachmate )
{
nProperties_ |= PROPERTY_BUG_CopyPlane_RevertBWPixel;
}
else
if( GetServerVendor() == vendor_ibm )
{
nProperties_ |= PROPERTY_BUG_XA_FAMILY_NAME_nil;
if( otherwm == eWindowManager_ ) eWindowManager_ = mwm;
}
else
if( GetServerVendor() == vendor_xfree )
{
nProperties_ |= PROPERTY_BUG_XCopyArea_GXxor;
#if defined LINUX || defined FREEBSD
// otherwm and olwm are a kind of default, which are not detected
// carefully. if we are running linux (i.e. not netbsd) on an xfree
// display, fvwm is most probable the wm to choose, confusing with mwm
// doesn't harm. #57791# start maximized if possible
if( (otherwm == eWindowManager_)
|| (olwm == eWindowManager_ ))
{
eWindowManager_ = fvwm; // ???
nProperties_ |= PROPERTY_FEATURE_Maximize;
}
#else
if( otherwm == eWindowManager_ ) eWindowManager_ = winmgr;
#endif
#if defined SOLARIS && defined SPARC
nProperties_ |= PROPERTY_BUG_Bitmap_Bit_Order;
// solaris xlib seems to have problems with putting images
// in correct bit order to xfree 8 bit displays
#endif
}
else
if( GetServerVendor() == vendor_sun )
{
// nicht alle! (bekannt: nur Sparc II CG3, CG6?)
nProperties_ &= ~PROPERTY_SUPPORT_XSetClipMask;
// trusted solaris doesn't allow to change properties on the
// wm decoration window
if (sal_IsTrustedSolaris (pDisp_))
nProperties_ |= PROPERTY_FEATURE_TrustedSolaris;
// Fehler im Sun-Solaris X86 Server !
if (ImageByteOrder(GetDisplay()) == LSBFirst)
{
nProperties_ |= PROPERTY_BUG_Tile;
nProperties_ |= PROPERTY_SUPPORT_3ButtonMouse;
}
else // MSBFirst Sun-Solaris Sparc Server
{
// XCopyPlane reverts black and white for 1bit bitmaps
// only sun, only 8bit pseudocolor target
if ( (GetVisual(m_nDefaultScreen).GetDepth() == 8)
&& (GetVisual(m_nDefaultScreen).GetClass() == PseudoColor))
nProperties_ |= PROPERTY_BUG_CopyPlane_RevertBWPixel;
// Fehler in Solaris 2.5.1
if (VendorRelease ( GetDisplay() ) < 3600)
nProperties_ |= PROPERTY_BUG_FillPolygon_Tile;
}
if( otherwm == eWindowManager_ )
eWindowManager_ = olwm;
}
else
if( GetServerVendor() == vendor_sco )
{
if( otherwm == eWindowManager_ ) eWindowManager_ = pmwm;
}
else
if( GetServerVendor() == vendor_sgi )
{
if( GetVisual( m_nDefaultScreen ).GetDepth() > 8 && GetVisual( m_nDefaultScreen ).GetDepth() <= 16 )
nProperties_ |= PROPERTY_BUG_XCopyArea_GXxor;
nProperties_ |= PROPERTY_SUPPORT_XSetClipMask;
if( otherwm == eWindowManager_ )
eWindowManager_ = FourDwm;
}
else
if( GetServerVendor() == vendor_hp )
{
if( otherwm == eWindowManager_ ) eWindowManager_ = dtwm;
}
else
if( GetServerVendor() == vendor_hummingbird )
{
if (GetVisual(m_nDefaultScreen).GetDepth() == 24)
nProperties_ |= PROPERTY_BUG_CopyArea_OnlySmallSlices;
}
if( otherwm == eWindowManager_ )
{
if( !XInternAtom( pDisp_, "_MOTIF_WM_INFO", True ) )
eWindowManager_ = olwm;
// ???
}
if( winmgr == eWindowManager_ )
{
nProperties_ &= ~PROPERTY_SUPPORT_WM_SetPos;
nProperties_ &= ~PROPERTY_SUPPORT_WM_Screen;
nProperties_ |= PROPERTY_FEATURE_Maximize;
}
else if( dtwm == eWindowManager_ )
{
nProperties_ &= ~PROPERTY_SUPPORT_WM_ClientPos;
}
else if( pmwm == eWindowManager_ )
{
nProperties_ &= ~PROPERTY_SUPPORT_WM_ClientPos;
}
}
InitXinerama();
// initialize system settings update
m_pDtIntegrator = DtIntegrator::CreateDtIntegrator();
#ifdef DBG_UTIL
PrintInfo();
#endif
}
// Sound
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void SalDisplay::Beep() const
{
XBell( pDisp_, 0 );
}
// Keyboard
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
String SalDisplay::GetKeyNameFromKeySym( KeySym nKeySym ) const
{
String aRet;
// return an empty string for keysyms that are not bound to
// any key code
XLIB_KeyCode aKeyCode = XKeysymToKeycode( GetDisplay(), nKeySym );
if( aKeyCode != 0 && aKeyCode != NoSymbol )
{
if( !nKeySym )
aRet = String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "???" ) );
else
{
aRet = ::vcl_sal::getKeysymReplacementName( const_cast<SalDisplay*>(this)->GetKeyboardName(), nKeySym );
if( ! aRet.Len() )
{
const char *pString = XKeysymToString( nKeySym );
int n = strlen( pString );
if( n > 2 && pString[n-2] == '_' )
aRet = String( pString, n-2, RTL_TEXTENCODING_ISO_8859_1 );
else
aRet = String( pString, n, RTL_TEXTENCODING_ISO_8859_1 );
}
}
}
return aRet;
}
inline KeySym sal_XModifier2Keysym( Display *pDisplay,
XModifierKeymap *pXModMap,
int n )
{
return XkbKeycodeToKeysym( pDisplay,
pXModMap->modifiermap[n*pXModMap->max_keypermod],
0, 0 );
}
void SalDisplay::ModifierMapping()
{
XModifierKeymap *pXModMap = XGetModifierMapping( pDisp_ );
bNumLockFromXS_ = True;
nShiftKeySym_ = sal_XModifier2Keysym( pDisp_, pXModMap, ShiftMapIndex );
nCtrlKeySym_ = sal_XModifier2Keysym( pDisp_, pXModMap, ControlMapIndex );
nMod1KeySym_ = sal_XModifier2Keysym( pDisp_, pXModMap, Mod1MapIndex );
// Auf Sun-Servern und SCO-Severn beruecksichtigt XLookupString
// nicht den NumLock Modifier.
if( (GetServerVendor() == vendor_sun)
|| (GetServerVendor() == vendor_sco) )
{
XLIB_KeyCode aNumLock = XKeysymToKeycode( pDisp_, XK_Num_Lock );
if( aNumLock ) for( int i = ShiftMapIndex; i <= Mod5MapIndex; i++ )
{
if( pXModMap->modifiermap[i*pXModMap->max_keypermod] == aNumLock )
{
bNumLockFromXS_ = False;
nNumLockIndex_ = i;
nNumLockMask_ = 1<<i;
break;
}
}
}
XFreeModifiermap( pXModMap );
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
XubString SalDisplay::GetKeyName( sal_uInt16 nKeyCode ) const
{
String aStrMap;
if( nKeyCode & KEY_MOD1 )
aStrMap += GetKeyNameFromKeySym( nCtrlKeySym_ );
if( nKeyCode & KEY_MOD2 )
{
if( aStrMap.Len() )
aStrMap += '+';
aStrMap += GetKeyNameFromKeySym( nMod1KeySym_ );
}
if( nKeyCode & KEY_SHIFT )
{
if( aStrMap.Len() )
aStrMap += '+';
aStrMap += GetKeyNameFromKeySym( nShiftKeySym_ );
}
nKeyCode &= 0x0FFF;
KeySym nKeySym = 0;
if( KEY_0 <= nKeyCode && nKeyCode <= KEY_9 )
nKeySym = XK_0 + (nKeyCode - KEY_0);
else if( KEY_A <= nKeyCode && nKeyCode <= KEY_Z )
nKeySym = XK_A + (nKeyCode - KEY_A);
else if( KEY_F1 <= nKeyCode && nKeyCode <= KEY_F26 ) // Existiert die Taste
nKeySym = XK_F1 + (nKeyCode - KEY_F1);
else switch( nKeyCode )
{
case KEY_DOWN:
nKeySym = XK_Down;
break;
case KEY_UP:
nKeySym = XK_Up;
break;
case KEY_LEFT:
nKeySym = XK_Left;
break;
case KEY_RIGHT:
nKeySym = XK_Right;
break;
case KEY_HOME:
nKeySym = XK_Home;
break;
case KEY_END:
nKeySym = XK_End;
break;
case KEY_PAGEUP:
nKeySym = XK_Prior;
break;
case KEY_PAGEDOWN:
nKeySym = XK_Next;
break;
case KEY_RETURN:
nKeySym = XK_Return;
break;
case KEY_ESCAPE:
nKeySym = XK_Escape;
break;
case KEY_TAB:
nKeySym = XK_Tab;
break;
case KEY_BACKSPACE:
nKeySym = XK_BackSpace;
break;
case KEY_SPACE:
nKeySym = XK_space;
break;
case KEY_INSERT:
nKeySym = XK_Insert;
break;
case KEY_DELETE:
nKeySym = XK_Delete;
break;
#if !defined (SunXK_Undo)
#define SunXK_Stop 0x0000FF69 // XK_Cancel
#define SunXK_Props 0x1005FF70
#define SunXK_Front 0x1005FF71
#define SunXK_Copy 0x1005FF72
#define SunXK_Open 0x1005FF73
#define SunXK_Paste 0x1005FF74
#define SunXK_Cut 0x1005FF75
#endif
case KEY_REPEAT:
nKeySym = XK_Redo;
break;
case KEY_PROPERTIES:
nKeySym = SunXK_Props;
break;
case KEY_UNDO:
nKeySym = XK_Undo;
break;
case KEY_FRONT:
nKeySym = SunXK_Front;
break;
case KEY_COPY:
nKeySym = SunXK_Copy;
break;
case KEY_OPEN:
nKeySym = SunXK_Open;
break;
case KEY_PASTE:
nKeySym = SunXK_Paste;
break;
case KEY_FIND:
nKeySym = XK_Find;
break;
case KEY_CUT:
nKeySym = GetServerVendor() == vendor_sun ? SunXK_Cut : XK_L10;
break;
case KEY_ADD:
nKeySym = XK_plus;
break;
case KEY_SUBTRACT:
nKeySym = XK_minus;
break;
case KEY_MULTIPLY:
nKeySym = XK_asterisk;
break;
case KEY_DIVIDE:
nKeySym = XK_slash;
break;
case KEY_POINT:
nKeySym = XK_period;
break;
case KEY_COMMA:
nKeySym = XK_comma;
break;
case KEY_LESS:
nKeySym = XK_less;
break;
case KEY_GREATER:
nKeySym = XK_greater;
break;
case KEY_EQUAL:
nKeySym = XK_equal;
break;
case KEY_HELP:
nKeySym = XK_Help;
break;
case KEY_HANGUL_HANJA:
nKeySym = XK_Hangul_Hanja;
break;
case KEY_TILDE:
nKeySym = XK_asciitilde;
break;
case KEY_QUOTELEFT:
nKeySym = XK_grave;
break;
default:
nKeySym = 0;
break;
}
if( nKeySym )
{
String aKeyName = GetKeyNameFromKeySym( nKeySym );
if( aKeyName.Len() )
{
if( aStrMap.Len() )
aStrMap += '+';
aStrMap += aKeyName;
}
else
aStrMap.Erase();
}
else
aStrMap.Erase();
return aStrMap;
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#ifndef IsISOKey
#define IsISOKey( n ) (0x0000FE00==((n)&0xFFFFFF00))
#endif
sal_uInt16 SalDisplay::GetKeyCode( KeySym keysym, char*pcPrintable ) const
{
sal_uInt16 nKey = 0;
if( XK_a <= keysym && XK_z >= keysym )
nKey = (sal_uInt16)(KEY_A + (keysym - XK_a));
else if( XK_A <= keysym && XK_Z >= keysym )
nKey = (sal_uInt16)(KEY_A + (keysym - XK_A));
else if( XK_0 <= keysym && XK_9 >= keysym )
nKey = (sal_uInt16)(KEY_0 + (keysym - XK_0));
else if( IsModifierKey( keysym ) )
;
else if( IsKeypadKey( keysym ) )
{
if( (keysym >= XK_KP_0) && (keysym <= XK_KP_9) )
{
nKey = (sal_uInt16)(KEY_0 + (keysym - XK_KP_0));
*pcPrintable = '0' + nKey - KEY_0;
}
else if( IsPFKey( keysym ) )
nKey = (sal_uInt16)(KEY_F1 + (keysym - XK_KP_F1));
else switch( keysym )
{
case XK_KP_Space:
nKey = KEY_SPACE;
*pcPrintable = ' ';
break;
case XK_KP_Tab:
nKey = KEY_TAB;
break;
case XK_KP_Enter:
nKey = KEY_RETURN;
break;
case XK_KP_Begin:
case XK_KP_Home:
nKey = KEY_HOME;
break;
case XK_KP_Left:
nKey = KEY_LEFT;
break;
case XK_KP_Up:
nKey = KEY_UP;
break;
case XK_KP_Right:
nKey = KEY_RIGHT;
break;
case XK_KP_Down:
nKey = KEY_DOWN;
break;
case XK_KP_Prior: // XK_KP_Page_Up
nKey = KEY_PAGEUP;
break;
case XK_KP_Next: // XK_KP_Page_Down
nKey = KEY_PAGEDOWN;
break;
case XK_KP_End:
nKey = KEY_END;
break;
case XK_KP_Insert:
nKey = KEY_INSERT;
break;
case XK_KP_Delete:
nKey = KEY_DELETE;
break;
case XK_KP_Equal:
nKey = KEY_EQUAL;
*pcPrintable = '=';
break;
case XK_KP_Multiply:
nKey = KEY_MULTIPLY;
*pcPrintable = '*';
break;
case XK_KP_Add:
nKey = KEY_ADD;
*pcPrintable = '+';
break;
case XK_KP_Separator:
nKey = KEY_DECIMAL;
*pcPrintable = ',';
break;
case XK_KP_Subtract:
nKey = KEY_SUBTRACT;
*pcPrintable = '-';
break;
case XK_KP_Decimal:
nKey = KEY_DECIMAL;
*pcPrintable = '.';
break;
case XK_KP_Divide:
nKey = KEY_DIVIDE;
*pcPrintable = '/';
break;
}
}
else if( IsFunctionKey( keysym ) )
{
if( bNumLockFromXS_ )
{
if( keysym >= XK_F1 && keysym <= XK_F26 )
nKey = (sal_uInt16)(KEY_F1 + keysym - XK_F1);
}
else switch( keysym )
{
// - - - - - Sun X-Server Tastatur ohne Cursorblock ??? - - -
case XK_R7: // XK_F27:
nKey = KEY_HOME;
break;
case XK_R8: // XK_F28:
nKey = KEY_UP;
break;
case XK_R9: // XK_F29:
nKey = KEY_PAGEUP;
break;
case XK_R10: // XK_F30:
nKey = KEY_LEFT;
break;
case XK_R11: // XK_F31:
nKey = 0; // KEY_F31
break;
case XK_R12: // XK_F32:
nKey = KEY_RIGHT;
break;
case XK_R13: // XK_F33:
nKey = KEY_END;
break;
case XK_R14: // XK_F34:
nKey = KEY_DOWN;
break;
case XK_R15: // XK_F35:
nKey = KEY_PAGEDOWN;
break;
// - - - - - Sun X-Server Tastatur ??? - - - - - - - - - - - -
case XK_L1: // XK_F11:
nKey = KEY_F11; // on a sun keyboard this actually is usally SunXK_Stop,
// but VCL doesn't have a key defintion for that
break;
case XK_L2: // XK_F12:
if ( GetServerVendor() == vendor_sun )
nKey = KEY_REPEAT;
else
nKey = KEY_F12;
break;
case XK_L3: // XK_F13:
nKey = KEY_PROPERTIES; // KEY_F13
break;
case XK_L4: // XK_F14:
nKey = KEY_UNDO; // KEY_F14
break;
case XK_L5: // XK_F15:
nKey = KEY_F15; // KEY_FRONT
break;
case XK_L6: // XK_F16:
nKey = KEY_COPY; // KEY_F16
break;
case XK_L7: // XK_F17:
nKey = KEY_F17; // KEY_OPEN
break;
case XK_L8: // XK_F18:
nKey = KEY_PASTE; // KEY_F18
break;
case XK_L9: // XK_F19:
nKey = KEY_F19; // KEY_FIND
break;
case XK_L10: // XK_F20:
nKey = KEY_CUT; // KEY_F20
break;
default:
if( keysym >= XK_F1 && keysym <= XK_F26 )
nKey = (sal_uInt16)(KEY_F1 + keysym - XK_F1);
break;
}
}
else if( IsCursorKey( keysym ) )
{
switch( keysym )
{
case XK_Begin:
case XK_Home:
nKey = KEY_HOME;
break;
case XK_Left:
nKey = KEY_LEFT;
break;
case XK_Up:
nKey = KEY_UP;
break;
case XK_Right:
nKey = KEY_RIGHT;
break;
case XK_Down:
nKey = KEY_DOWN;
break;
case XK_Prior: // XK_Page_Up
nKey = KEY_PAGEUP;
break;
case XK_Next: // XK_Page_Down
nKey = KEY_PAGEDOWN;
break;
case XK_End:
nKey = KEY_END;
break;
}
}
else if( IsMiscFunctionKey( keysym ) )
{
switch( keysym )
{
case XK_Insert:
nKey = KEY_INSERT;
break;
case XK_Redo:
nKey = KEY_REPEAT;
break;
case XK_Undo:
nKey = KEY_UNDO;
break;
case XK_Find:
nKey = KEY_FIND;
break;
case XK_Help:
nKey = KEY_HELP;
break;
case XK_Menu:
nKey = KEY_CONTEXTMENU;
break;
/*
case XK_Break:
case XK_Select:
case XK_Execute:
case XK_Print:
case XK_Cancel:
*/
}
}
else if( IsISOKey( keysym ) ) // XK_ISO_
{
switch( keysym )
{
case 0xFE20: // XK_ISO_Left_Tab:
nKey = KEY_TAB;
break;
}
}
else switch( keysym )
{
case XK_Return:
nKey = KEY_RETURN;
break;
case XK_BackSpace:
nKey = KEY_BACKSPACE;
break;
case XK_Delete:
nKey = KEY_DELETE;
break;
case XK_space:
nKey = KEY_SPACE;
break;
case XK_Tab:
nKey = KEY_TAB;
break;
case XK_Escape:
nKey = KEY_ESCAPE;
break;
case XK_plus:
nKey = KEY_ADD;
break;
case XK_minus:
nKey = KEY_SUBTRACT;
break;
case XK_asterisk:
nKey = KEY_MULTIPLY;
break;
case XK_slash:
nKey = KEY_DIVIDE;
break;
case XK_period:
nKey = KEY_POINT;
break;
case XK_comma:
nKey = KEY_COMMA;
break;
case XK_less:
nKey = KEY_LESS;
break;
case XK_greater:
nKey = KEY_GREATER;
break;
case XK_equal:
nKey = KEY_EQUAL;
break;
case XK_Hangul_Hanja:
nKey = KEY_HANGUL_HANJA;
break;
case XK_asciitilde:
nKey = KEY_TILDE;
*pcPrintable = '~';
break;
case XK_grave:
nKey = KEY_QUOTELEFT;
*pcPrintable = '`';
break;
// case XK_Linefeed:
// *pcPrintable = '\n';
// break;
// - - - - - - - - - - - - - Apollo - - - - - - - - - - - - - 0x1000
case 0x1000FF02: // apXK_Copy
nKey = KEY_COPY;
break;
case 0x1000FF03: // apXK_Cut
nKey = KEY_CUT;
break;
case 0x1000FF04: // apXK_Paste
nKey = KEY_PASTE;
break;
case 0x1000FF14: // apXK_Repeat
nKey = KEY_REPEAT;
break;
// Exit, Save
// - - - - - - - - - - - - - - D E C - - - - - - - - - - - - - 0x1000
case 0x1000FF00:
nKey = KEY_DELETE;
break;
// - - - - - - - - - - - - - - H P - - - - - - - - - - - - - 0x1000
case 0x1000FF73: // hpXK_DeleteChar
nKey = KEY_DELETE;
break;
case 0x1000FF74: // hpXK_BackTab
case 0x1000FF75: // hpXK_KP_BackTab
nKey = KEY_TAB;
break;
// - - - - - - - - - - - - - - I B M - - - - - - - - - - - - -
// - - - - - - - - - - - - - - O S F - - - - - - - - - - - - - 0x1004
case 0x1004FF02: // osfXK_Copy
nKey = KEY_COPY;
break;
case 0x1004FF03: // osfXK_Cut
nKey = KEY_CUT;
break;
case 0x1004FF04: // osfXK_Paste
nKey = KEY_PASTE;
break;
case 0x1004FF07: // osfXK_BackTab
nKey = KEY_TAB;
break;
case 0x1004FF08: // osfXK_BackSpace
nKey = KEY_BACKSPACE;
break;
case 0x1004FF1B: // osfXK_Escape
nKey = KEY_ESCAPE;
break;
// Up, Down, Left, Right, PageUp, PageDown
// - - - - - - - - - - - - - - S C O - - - - - - - - - - - - -
// - - - - - - - - - - - - - - S G I - - - - - - - - - - - - - 0x1007
// - - - - - - - - - - - - - - S N I - - - - - - - - - - - - -
// - - - - - - - - - - - - - - S U N - - - - - - - - - - - - - 0x1005
case 0x1005FF10: // SunXK_F36
nKey = KEY_F11;
break;
case 0x1005FF11: // SunXK_F37
nKey = KEY_F12;
break;
case 0x1005FF70: // SunXK_Props
nKey = KEY_PROPERTIES;
break;
case 0x1005FF71: // SunXK_Front
nKey = KEY_FRONT;
break;
case 0x1005FF72: // SunXK_Copy
nKey = KEY_COPY;
break;
case 0x1005FF73: // SunXK_Open
nKey = KEY_OPEN;
break;
case 0x1005FF74: // SunXK_Paste
nKey = KEY_PASTE;
break;
case 0x1005FF75: // SunXK_Cut
nKey = KEY_CUT;
break;
}
return nKey;
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
KeySym SalDisplay::GetKeySym( XKeyEvent *pEvent,
unsigned char *pPrintable,
int *pLen,
KeySym *pUnmodifiedKeySym,
Status *pStatusReturn,
XIC aInputContext ) const
{
KeySym nKeySym = 0;
memset( pPrintable, 0, *pLen );
*pStatusReturn = 0;
// first get the printable of the possibly modified KeySym
if ( (aInputContext == 0)
|| (pEvent->type == KeyRelease)
|| (mpInputMethod != NULL && mpInputMethod->PosixLocale()) )
{
// XmbLookupString must not be called for KeyRelease events
// Cannot enter space in c locale problem #89616# #88978# btraq #4478197
*pLen = XLookupString( pEvent, (char*)pPrintable, 1, &nKeySym, NULL );
}
else
{
*pLen = XmbLookupString( aInputContext,
pEvent, (char*)pPrintable, *pLen - 1, &nKeySym, pStatusReturn );
// Lookup the string again, now with appropriate size
if ( *pStatusReturn == XBufferOverflow )
{
pPrintable[ 0 ] = (char)0;
return 0;
}
switch ( *pStatusReturn )
{
case XBufferOverflow:
/* unhandled error */
break;
case XLookupNone:
/* unhandled error */
break;
case XLookupKeySym:
/* #72223# this is a strange one: on exceed sometimes
* no printable is returned for the first char entered,
* just to retry lookup solves the problem. The problem
* is not yet fully understood, so restrict 2nd lookup
* to 7bit ascii chars */
if ( (XK_space <= nKeySym) && (XK_asciitilde >= nKeySym) )
{
*pLen = 1;
pPrintable[ 0 ] = (char)nKeySym;
}
break;
case XLookupBoth:
case XLookupChars:
/* nothing to, char allready in pPrintable */
break;
}
}
if( !bNumLockFromXS_
&& (IsCursorKey(nKeySym)
|| IsFunctionKey(nKeySym)
|| IsKeypadKey(nKeySym)
|| XK_Delete == nKeySym ) )
{
// Bei einigen X-Servern muss man bei den Keypadtasten
// schon sehr genau hinschauen. ZB. Solaris XServer:
// 2, 4, 6, 8 werden als Cursorkeys klassifiziert (Up, Down, Left, Right
// 1, 3, 5, 9 werden als Functionkeys klassifiziert (F27,F29,F33,F35)
// 0 als Keypadkey und der Dezimalpunkt gar nicht (KP_Insert)
KeySym nNewKeySym = XLookupKeysym( pEvent, nNumLockIndex_ );
if( nNewKeySym != NoSymbol )
nKeySym = nNewKeySym;
}
// Now get the unmodified KeySym for KeyCode retrieval
// try to strip off modifiers, e.g. Ctrl-$ becomes Ctrl-Shift-4
*pUnmodifiedKeySym = XkbKeycodeToKeysym( GetDisplay(), pEvent->keycode, 0, 0 );
return nKeySym;
}
// Pointer
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#define MAKE_BITMAP( name ) \
XCreateBitmapFromData( pDisp_, \
DefaultRootWindow( pDisp_ ), \
(const char*)name##_bits, \
name##_width, \
name##_height )
#define MAKE_CURSOR( name ) \
aCursBitmap = MAKE_BITMAP( name##curs ); \
aMaskBitmap = MAKE_BITMAP( name##mask ); \
nXHot = name##curs_x_hot; \
nYHot = name##curs_y_hot
XLIB_Cursor SalDisplay::GetPointer( int ePointerStyle )
{
if( ePointerStyle >= POINTER_COUNT )
return 0;
XLIB_Cursor &aCur = aPointerCache_[ePointerStyle];
if( aCur != None )
return aCur;
Pixmap aCursBitmap = None, aMaskBitmap = None;
unsigned int nXHot = 0, nYHot = 0;
switch( ePointerStyle )
{
case POINTER_NULL:
MAKE_CURSOR( null );
break;
case POINTER_ARROW:
aCur = XCreateFontCursor( pDisp_, XC_left_ptr );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_WAIT:
aCur = XCreateFontCursor( pDisp_, XC_watch );
break;
case POINTER_TEXT: // Mouse Pointer ist ein "I" Beam
aCur = XCreateFontCursor( pDisp_, XC_xterm );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_HELP:
aCur = XCreateFontCursor( pDisp_, XC_question_arrow );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_CROSS: // Mouse Pointer ist ein Kreuz
aCur = XCreateFontCursor( pDisp_, XC_crosshair );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_NSIZE:
aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_SSIZE:
aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_WSIZE:
aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_ESIZE:
aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_WINDOW_NSIZE:
aCur = XCreateFontCursor( pDisp_, XC_top_side );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_WINDOW_SSIZE:
aCur = XCreateFontCursor( pDisp_, XC_bottom_side );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_WINDOW_WSIZE:
aCur = XCreateFontCursor( pDisp_, XC_left_side );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_WINDOW_ESIZE:
aCur = XCreateFontCursor( pDisp_, XC_right_side );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_NWSIZE:
aCur = XCreateFontCursor( pDisp_, XC_top_left_corner );
break;
case POINTER_NESIZE:
aCur = XCreateFontCursor( pDisp_, XC_top_right_corner );
break;
case POINTER_SWSIZE:
aCur = XCreateFontCursor( pDisp_, XC_bottom_left_corner );
break;
case POINTER_SESIZE:
aCur = XCreateFontCursor( pDisp_, XC_bottom_right_corner );
break;
case POINTER_WINDOW_NWSIZE:
aCur = XCreateFontCursor( pDisp_, XC_top_left_corner );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_WINDOW_NESIZE:
aCur = XCreateFontCursor( pDisp_, XC_top_right_corner );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_WINDOW_SWSIZE:
aCur = XCreateFontCursor( pDisp_, XC_bottom_left_corner );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_WINDOW_SESIZE:
aCur = XCreateFontCursor( pDisp_, XC_bottom_right_corner );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_HSPLIT:
aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow );
break;
case POINTER_VSPLIT:
aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow );
break;
case POINTER_HSIZEBAR:
aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow ); // ???
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_VSIZEBAR:
aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow ); // ???
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_REFHAND:
aCur = XCreateFontCursor( pDisp_, XC_hand1 );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_HAND:
aCur = XCreateFontCursor( pDisp_, XC_hand2 );
break;
case POINTER_MAGNIFY:
MAKE_CURSOR( magnify_ );
break;
case POINTER_FILL:
MAKE_CURSOR( fill_ );
break;
case POINTER_MOVE:
aCur = XCreateFontCursor( pDisp_, XC_fleur );
break;
case POINTER_MOVEDATA:
MAKE_CURSOR( movedata_ );
break;
case POINTER_COPYDATA:
MAKE_CURSOR( copydata_ );
break;
case POINTER_MOVEFILE:
MAKE_CURSOR( movefile_ );
break;
case POINTER_COPYFILE:
MAKE_CURSOR( copyfile_ );
break;
case POINTER_MOVEFILES:
MAKE_CURSOR( movefiles_ );
break;
case POINTER_COPYFILES:
MAKE_CURSOR( copyfiles_ );
break;
case POINTER_NOTALLOWED:
MAKE_CURSOR( nodrop_ );
break;
case POINTER_ROTATE:
MAKE_CURSOR( rotate_ );
break;
case POINTER_HSHEAR:
MAKE_CURSOR( hshear_ );
break;
case POINTER_VSHEAR:
MAKE_CURSOR( vshear_ );
break;
case POINTER_DRAW_LINE:
MAKE_CURSOR( drawline_ );
break;
case POINTER_DRAW_RECT:
MAKE_CURSOR( drawrect_ );
break;
case POINTER_DRAW_POLYGON:
MAKE_CURSOR( drawpolygon_ );
break;
case POINTER_DRAW_BEZIER:
MAKE_CURSOR( drawbezier_ );
break;
case POINTER_DRAW_ARC:
MAKE_CURSOR( drawarc_ );
break;
case POINTER_DRAW_PIE:
MAKE_CURSOR( drawpie_ );
break;
case POINTER_DRAW_CIRCLECUT:
MAKE_CURSOR( drawcirclecut_ );
break;
case POINTER_DRAW_ELLIPSE:
MAKE_CURSOR( drawellipse_ );
break;
case POINTER_DRAW_CONNECT:
MAKE_CURSOR( drawconnect_ );
break;
case POINTER_DRAW_TEXT:
MAKE_CURSOR( drawtext_ );
break;
case POINTER_MIRROR:
MAKE_CURSOR( mirror_ );
break;
case POINTER_CROOK:
MAKE_CURSOR( crook_ );
break;
case POINTER_CROP:
MAKE_CURSOR( crop_ );
break;
case POINTER_MOVEPOINT:
MAKE_CURSOR( movepoint_ );
break;
case POINTER_MOVEBEZIERWEIGHT:
MAKE_CURSOR( movebezierweight_ );
break;
case POINTER_DRAW_FREEHAND:
MAKE_CURSOR( drawfreehand_ );
break;
case POINTER_DRAW_CAPTION:
MAKE_CURSOR( drawcaption_ );
break;
case POINTER_PEN: // Mouse Pointer ist ein Stift
aCur = XCreateFontCursor( pDisp_, XC_pencil );
DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
break;
case POINTER_LINKDATA:
MAKE_CURSOR( linkdata_ );
break;
case POINTER_MOVEDATALINK:
MAKE_CURSOR( movedlnk_ );
break;
case POINTER_COPYDATALINK:
MAKE_CURSOR( copydlnk_ );
break;
case POINTER_LINKFILE:
MAKE_CURSOR( linkfile_ );
break;
case POINTER_MOVEFILELINK:
MAKE_CURSOR( moveflnk_ );
break;
case POINTER_COPYFILELINK:
MAKE_CURSOR( copyflnk_ );
break;
case POINTER_CHART:
MAKE_CURSOR( chart_ );
break;
case POINTER_DETECTIVE:
MAKE_CURSOR( detective_ );
break;
case POINTER_PIVOT_COL:
MAKE_CURSOR( pivotcol_ );
break;
case POINTER_PIVOT_ROW:
MAKE_CURSOR( pivotrow_ );
break;
case POINTER_PIVOT_FIELD:
MAKE_CURSOR( pivotfld_ );
break;
case POINTER_PIVOT_DELETE:
MAKE_CURSOR( pivotdel_ );
break;
case POINTER_CHAIN:
MAKE_CURSOR( chain_ );
break;
case POINTER_CHAIN_NOTALLOWED:
MAKE_CURSOR( chainnot_ );
break;
case POINTER_TIMEEVENT_MOVE:
MAKE_CURSOR( timemove_ );
break;
case POINTER_TIMEEVENT_SIZE:
MAKE_CURSOR( timesize_ );
break;
case POINTER_AUTOSCROLL_N:
MAKE_CURSOR(asn_ );
break;
case POINTER_AUTOSCROLL_S:
MAKE_CURSOR( ass_ );
break;
case POINTER_AUTOSCROLL_W:
MAKE_CURSOR( asw_ );
break;
case POINTER_AUTOSCROLL_E:
MAKE_CURSOR( ase_ );
break;
case POINTER_AUTOSCROLL_NW:
MAKE_CURSOR( asnw_ );
break;
case POINTER_AUTOSCROLL_NE:
MAKE_CURSOR( asne_ );
break;
case POINTER_AUTOSCROLL_SW:
MAKE_CURSOR( assw_ );
break;
case POINTER_AUTOSCROLL_SE:
MAKE_CURSOR( asse_ );
break;
case POINTER_AUTOSCROLL_NS:
MAKE_CURSOR( asns_ );
break;
case POINTER_AUTOSCROLL_WE:
MAKE_CURSOR( aswe_ );
break;
case POINTER_AUTOSCROLL_NSWE:
MAKE_CURSOR( asnswe_ );
break;
case POINTER_AIRBRUSH:
MAKE_CURSOR( airbrush_ );
break;
case POINTER_TEXT_VERTICAL:
MAKE_CURSOR( vertcurs_ );
break;
// --> FME 2004-07-30 #i32329# Enhanced table selection
case POINTER_TAB_SELECT_S:
MAKE_CURSOR( tblsels_ );
break;
case POINTER_TAB_SELECT_E:
MAKE_CURSOR( tblsele_ );
break;
case POINTER_TAB_SELECT_SE:
MAKE_CURSOR( tblselse_ );
break;
case POINTER_TAB_SELECT_W:
MAKE_CURSOR( tblselw_ );
break;
case POINTER_TAB_SELECT_SW:
MAKE_CURSOR( tblselsw_ );
break;
// <--
// --> FME 2004-08-16 #i20119# Paintbrush tool
case POINTER_PAINTBRUSH :
MAKE_CURSOR( paintbrush_ );
break;
// <--
default:
DBG_ERROR("pointer not implemented");
aCur = XCreateFontCursor( pDisp_, XC_arrow );
break;
}
if( None == aCur )
{
XColor aBlack, aWhite, aDummy;
Colormap hColormap = GetColormap(m_nDefaultScreen).GetXColormap();
XAllocNamedColor( pDisp_, hColormap, "black", &aBlack, &aDummy );
XAllocNamedColor( pDisp_, hColormap, "white", &aWhite, &aDummy );
aCur = XCreatePixmapCursor( pDisp_,
aCursBitmap, aMaskBitmap,
&aBlack, &aWhite,
nXHot, nYHot );
XFreePixmap( pDisp_, aCursBitmap );
XFreePixmap( pDisp_, aMaskBitmap );
}
return aCur;
}
int SalDisplay::CaptureMouse( SalFrame *pCapture )
{
if( !pCapture )
{
m_pCapture = NULL;
XUngrabPointer( GetDisplay(), CurrentTime );
XFlush( GetDisplay() );
return 0;
}
m_pCapture = NULL;
// FIXME: get rid of X11SalFrame
const SystemEnvData* pEnvData = pCapture->GetSystemData();
int ret = XGrabPointer( GetDisplay(),
(XLIB_Window)pEnvData->aWindow,
False,
PointerMotionMask| ButtonPressMask|ButtonReleaseMask,
GrabModeAsync,
GrabModeAsync,
None,
static_cast<X11SalFrame*>(pCapture)->GetCursor(),
CurrentTime );
if( ret != GrabSuccess )
{
DBG_ASSERT( 1, "SalDisplay::CaptureMouse could not grab pointer\n");
return -1;
}
m_pCapture = pCapture;
return 1;
}
// Events
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void SalDisplay::SendInternalEvent( SalFrame* pFrame, void* pData, sal_uInt16 nEvent )
{
if( osl_acquireMutex( hEventGuard_ ) )
{
m_aUserEvents.push_back( SalUserEvent( pFrame, pData, nEvent ) );
// Notify SalXLib::Yield() of a pending event.
pXLib_->PostUserEvent();
osl_releaseMutex( hEventGuard_ );
}
else {
DBG_ASSERT( 1, "SalDisplay::SendInternalEvent !acquireMutex\n" );
}
}
void SalDisplay::CancelInternalEvent( SalFrame* pFrame, void* pData, sal_uInt16 nEvent )
{
if( osl_acquireMutex( hEventGuard_ ) )
{
if( ! m_aUserEvents.empty() )
{
std::list< SalUserEvent >::iterator it, next;
next = m_aUserEvents.begin();
do
{
it = next++;
if( it->m_pFrame == pFrame &&
it->m_pData == pData &&
it->m_nEvent == nEvent )
{
m_aUserEvents.erase( it );
}
} while( next != m_aUserEvents.end() );
}
osl_releaseMutex( hEventGuard_ );
}
else {
DBG_ASSERT( 1, "SalDisplay::CancelInternalEvent !acquireMutex\n" );
}
}
sal_Bool SalX11Display::IsEvent()
{
sal_Bool bRet = sal_False;
if( osl_acquireMutex( hEventGuard_ ) )
{
if( m_aUserEvents.begin() != m_aUserEvents.end() )
bRet = sal_True;
osl_releaseMutex( hEventGuard_ );
}
if( bRet || XEventsQueued( pDisp_, QueuedAlready ) )
return sal_True;
XFlush( pDisp_ );
return sal_False;
}
bool SalDisplay::DispatchInternalEvent()
{
SalFrame* pFrame = NULL;
void* pData = NULL;
sal_uInt16 nEvent = 0;
if( osl_acquireMutex( hEventGuard_ ) )
{
if( m_aUserEvents.begin() != m_aUserEvents.end() )
{
pFrame = m_aUserEvents.front().m_pFrame;
pData = m_aUserEvents.front().m_pData;
nEvent = m_aUserEvents.front().m_nEvent;
m_aUserEvents.pop_front();
}
osl_releaseMutex( hEventGuard_ );
}
else {
DBG_ASSERT( 1, "SalDisplay::Yield !acquireMutex\n" );
}
if( pFrame )
pFrame->CallCallback( nEvent, pData );
return pFrame != NULL;
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void SalX11Display::Yield()
{
if( DispatchInternalEvent() )
return;
XEvent aEvent;
DBG_ASSERT( static_cast<SalYieldMutex*>(GetSalData()->m_pInstance->GetYieldMutex())->GetThreadId() ==
vos::OThread::getCurrentIdentifier(),
"will crash soon since solar mutex not locked in SalDisplay::Yield" );
XNextEvent( pDisp_, &aEvent );
Dispatch( &aEvent );
#ifdef DBG_UTIL
if( pXLib_->HasXErrorOccured() )
{
XFlush( pDisp_ );
PrintEvent( "SalDisplay::Yield (WasXError)", &aEvent );
}
#endif
pXLib_->ResetXErrorOccured();
}
long SalX11Display::Dispatch( XEvent *pEvent )
{
if( pEvent->type == XLIB_KeyPress || pEvent->type == KeyRelease )
{
XLIB_Window aWindow = pEvent->xkey.window;
std::list< SalFrame* >::const_iterator it;
for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it )
{
const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it);
if( pFrame->GetWindow() == aWindow || pFrame->GetShellWindow() == aWindow )
{
aWindow = pFrame->GetWindow();
break;
}
}
if( it != m_aFrames.end() )
{
if ( mpInputMethod->FilterEvent( pEvent , aWindow ) )
return 0;
}
}
else
if ( mpInputMethod->FilterEvent( pEvent, None ) )
return 0;
SalInstance* pInstance = GetSalData()->m_pInstance;
pInstance->CallEventCallback( pEvent, sizeof( XEvent ) );
switch( pEvent->type )
{
case MotionNotify:
while( XCheckWindowEvent( pEvent->xany.display,
pEvent->xany.window,
ButtonMotionMask,
pEvent ) )
;
m_nLastUserEventTime = pEvent->xmotion.time;
break;
case PropertyNotify:
if( pEvent->xproperty.atom == getWMAdaptor()->getAtom( WMAdaptor::VCL_SYSTEM_SETTINGS ) )
{
for( unsigned int i = 0; i < m_aScreens.size(); i++ )
{
if( pEvent->xproperty.window == m_aScreens[i].m_aRefWindow )
{
std::list< SalFrame* >::const_iterator it;
for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it )
(*it)->CallCallback( SALEVENT_SETTINGSCHANGED, NULL );
return 0;
}
}
}
break;
case MappingNotify:
if( MappingKeyboard == pEvent->xmapping.request ||
MappingModifier == pEvent->xmapping.request )
{
XRefreshKeyboardMapping( &pEvent->xmapping );
if( MappingModifier == pEvent->xmapping.request )
ModifierMapping();
if( MappingKeyboard == pEvent->xmapping.request ) // refresh mapping
GetKeyboardName( sal_True );
}
break;
case ButtonPress:
case ButtonRelease:
m_nLastUserEventTime = pEvent->xbutton.time;
break;
case XLIB_KeyPress:
case KeyRelease:
m_nLastUserEventTime = pEvent->xkey.time;
break;
default:
if ( GetKbdExtension()->UseExtension()
&& GetKbdExtension()->GetEventBase() == pEvent->type )
{
GetKbdExtension()->Dispatch( pEvent );
return 1;
}
break;
}
std::list< SalFrame* >::iterator it;
for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it )
{
X11SalFrame* pFrame = static_cast< X11SalFrame* >(*it);
XLIB_Window aDispatchWindow = pEvent->xany.window;
if( pFrame->GetWindow() == aDispatchWindow
|| pFrame->GetShellWindow() == aDispatchWindow
|| pFrame->GetForeignParent() == aDispatchWindow
)
{
return pFrame->Dispatch( pEvent );
}
if( pEvent->type == ConfigureNotify && pEvent->xconfigure.window == pFrame->GetStackingWindow() )
{
return pFrame->Dispatch( pEvent );
}
}
// dispatch to salobjects
X11SalObject::Dispatch( pEvent );
// is this perhaps a root window that changed size ?
processRandREvent( pEvent );
return 0;
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void SalDisplay::PrintEvent( const ByteString &rComment,
XEvent *pEvent ) const
{
if( pEvent->type <= MappingNotify )
{
fprintf( stderr, "[%s] %s s=%d w=%ld\n",
rComment.GetBuffer(),
EventNames[pEvent->type],
pEvent->xany.send_event,
pEvent->xany.window );
switch( pEvent->type )
{
case XLIB_KeyPress:
case KeyRelease:
fprintf( stderr, "\t\ts=%d c=%d\n",
pEvent->xkey.state,
pEvent->xkey.keycode );
break;
case ButtonPress:
case ButtonRelease:
fprintf( stderr, "\t\ts=%d b=%d x=%d y=%d rx=%d ry=%d\n",
pEvent->xbutton.state,
pEvent->xbutton.button,
pEvent->xbutton.x,
pEvent->xbutton.y,
pEvent->xbutton.x_root,
pEvent->xbutton.y_root );
break;
case MotionNotify:
fprintf( stderr, "\t\ts=%d x=%d y=%d\n",
pEvent->xmotion.state,
pEvent->xmotion.x,
pEvent->xmotion.y );
break;
case EnterNotify:
case LeaveNotify:
fprintf( stderr, "\t\tm=%d f=%d x=%d y=%d\n",
pEvent->xcrossing.mode,
pEvent->xcrossing.focus,
pEvent->xcrossing.x,
pEvent->xcrossing.y );
break;
case FocusIn:
case FocusOut:
fprintf( stderr, "\t\tm=%d d=%d\n",
pEvent->xfocus.mode,
pEvent->xfocus.detail );
break;
case Expose:
case GraphicsExpose:
fprintf( stderr, "\t\tc=%d %d*%d %d+%d\n",
pEvent->xexpose.count,
pEvent->xexpose.width,
pEvent->xexpose.height,
pEvent->xexpose.x,
pEvent->xexpose.y );
break;
case VisibilityNotify:
fprintf( stderr, "\t\ts=%d\n",
pEvent->xvisibility.state );
break;
case CreateNotify:
case DestroyNotify:
break;
case MapNotify:
case UnmapNotify:
break;
case ReparentNotify:
fprintf( stderr, "\t\tp=%d x=%d y=%d\n",
sal::static_int_cast< int >(pEvent->xreparent.parent),
pEvent->xreparent.x,
pEvent->xreparent.y );
break;
case ConfigureNotify:
fprintf( stderr, "\t\tb=%d %d*%d %d+%d\n",
pEvent->xconfigure.border_width,
pEvent->xconfigure.width,
pEvent->xconfigure.height,
pEvent->xconfigure.x,
pEvent->xconfigure.y );
break;
case PropertyNotify:
fprintf( stderr, "\t\ta=%s (0x%X)\n",
GetAtomName( pDisp_, pEvent->xproperty.atom ),
sal::static_int_cast< unsigned int >(
pEvent->xproperty.atom) );
break;
case ColormapNotify:
fprintf( stderr, "\t\tc=%ld n=%d s=%d\n",
pEvent->xcolormap.colormap,
pEvent->xcolormap.c_new,
pEvent->xcolormap.state );
break;
case ClientMessage:
fprintf( stderr, "\t\ta=%s (0x%X) f=%i [0x%lX,0x%lX,0x%lX,0x%lX,0x%lX])\n",
GetAtomName( pDisp_, pEvent->xclient.message_type ),
sal::static_int_cast< unsigned int >(
pEvent->xclient.message_type),
pEvent->xclient.format,
pEvent->xclient.data.l[0],
pEvent->xclient.data.l[1],
pEvent->xclient.data.l[2],
pEvent->xclient.data.l[3],
pEvent->xclient.data.l[4] );
break;
case MappingNotify:
fprintf( stderr, "\t\tr=%sd\n",
MappingModifier == pEvent->xmapping.request
? "MappingModifier"
: MappingKeyboard == pEvent->xmapping.request
? "MappingKeyboard"
: "MappingPointer" );
break;
}
}
else
fprintf( stderr, "[%s] %d s=%d w=%ld\n",
rComment.GetBuffer(),
pEvent->type,
pEvent->xany.send_event,
pEvent->xany.window );
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void SalDisplay::PrintInfo() const
{
if( IsDisplay() )
{
fprintf( stderr, "\n" );
fprintf( stderr, "Environment\n" );
fprintf( stderr, "\t$XENVIRONMENT \t\"%s\"\n",
GetEnv( "XENVIRONMENT" ) );
fprintf( stderr, "\t$DISPLAY \t\"%s\"\n",
GetEnv( "DISPLAY" ) );
fprintf( stderr, "\t$SAL_VISUAL \t\"%s\"\n",
GetEnv( "SAL_VISUAL" ) );
fprintf( stderr, "\t$SAL_FONTPATH \t\"%s\"\n",
GetEnv( "SAL_FONTPATH" ) );
fprintf( stderr, "\t$SAL_NOSEGV \t\"%s\"\n",
GetEnv( "SAL_NOSEGV" ) );
fprintf( stderr, "\t$SAL_IGNOREXERRORS\t\"%s\"\n",
GetEnv( "SAL_IGNOREXERRORS" ) );
fprintf( stderr, "\t$SAL_PROPERTIES \t\"%s\"\n",
GetEnv( "SAL_PROPERTIES" ) );
fprintf( stderr, "\t$SAL_WM \t\"%s\"\n",
GetEnv( "SAL_WM" ) );
fprintf( stderr, "\t$SAL_SYNCHRONIZE \t\"%s\"\n",
GetEnv( "SAL_SYNCHRONIZE" ) );
char sHostname[ 120 ];
gethostname (sHostname, 120 );
fprintf( stderr, "Client\n" );
fprintf( stderr, "\tHost \t\"%s\"\n",
sHostname );
fprintf( stderr, "Display\n" );
fprintf( stderr, "\tHost \t\"%s\"\n",
DisplayString(pDisp_) );
fprintf( stderr, "\tVendor (Release) \t\"%s (%d)\"\n",
ServerVendor(pDisp_), VendorRelease(pDisp_) );
fprintf( stderr, "\tProtocol \t%d.%d\n",
ProtocolVersion(pDisp_), ProtocolRevision(pDisp_) );
fprintf( stderr, "\tScreen (count,def)\t%d (%d,%d)\n",
m_nDefaultScreen, ScreenCount(pDisp_), DefaultScreen(pDisp_) );
fprintf( stderr, "\tshift ctrl alt \t%s (0x%X) %s (0x%X) %s (0x%X)\n",
KeyStr( nShiftKeySym_ ), sal::static_int_cast< unsigned int >(nShiftKeySym_),
KeyStr( nCtrlKeySym_ ), sal::static_int_cast< unsigned int >(nCtrlKeySym_),
KeyStr( nMod1KeySym_ ), sal::static_int_cast< unsigned int >(nMod1KeySym_) );
if( XExtendedMaxRequestSize(pDisp_) * 4 )
fprintf( stderr, "\tXMaxRequestSize \t%ld %ld [bytes]\n",
XMaxRequestSize(pDisp_) * 4, XExtendedMaxRequestSize(pDisp_) * 4 );
if( GetProperties() != PROPERTY_DEFAULT )
fprintf( stderr, "\tProperties \t0x%lX\n", GetProperties() );
if( eWindowManager_ != otherwm )
fprintf( stderr, "\tWindowmanager \t%d\n", eWindowManager_ );
fprintf( stderr, "\tWMName \t%s\n", rtl::OUStringToOString( getWMAdaptor()->getWindowManagerName(), osl_getThreadTextEncoding() ).getStr() );
}
fprintf( stderr, "Screen\n" );
fprintf( stderr, "\tResolution/Size \t%ld*%ld %ld*%ld %.1lf\"\n",
aResolution_.A(), aResolution_.B(),
m_aScreens[m_nDefaultScreen].m_aSize.Width(), m_aScreens[m_nDefaultScreen].m_aSize.Height(),
Hypothenuse( DisplayWidthMM ( pDisp_, m_nDefaultScreen ),
DisplayHeightMM( pDisp_, m_nDefaultScreen ) ) / 25.4 );
fprintf( stderr, "\tBlack&White \t%lu %lu\n",
GetColormap(m_nDefaultScreen).GetBlackPixel(), GetColormap(m_nDefaultScreen).GetWhitePixel() );
fprintf( stderr, "\tRGB \t0x%lx 0x%lx 0x%lx\n",
GetVisual(m_nDefaultScreen).red_mask, GetVisual(m_nDefaultScreen).green_mask, GetVisual(m_nDefaultScreen).blue_mask );
fprintf( stderr, "\tVisual \t%d-bit %s ID=0x%x\n",
GetVisual(m_nDefaultScreen).GetDepth(),
VisualClassName[ GetVisual(m_nDefaultScreen).GetClass() ],
sal::static_int_cast< unsigned int >(GetVisual(m_nDefaultScreen).GetVisualId()) );
}
int SalDisplay::addXineramaScreenUnique( long i_nX, long i_nY, long i_nWidth, long i_nHeight )
{
// see if any frame buffers are at the same coordinates
// this can happen with weird configuration e.g. on
// XFree86 and Clone displays
const size_t nScreens = m_aXineramaScreens.size();
for( size_t n = 0; n < nScreens; n++ )
{
if( m_aXineramaScreens[n].Left() == i_nX &&
m_aXineramaScreens[n].Top() == i_nY )
{
if( m_aXineramaScreens[n].GetWidth() < i_nWidth ||
m_aXineramaScreens[n].GetHeight() < i_nHeight )
{
m_aXineramaScreens[n].SetSize( Size( i_nWidth, i_nHeight ) );
}
return (int)n;
}
}
m_aXineramaScreens.push_back( Rectangle( Point( i_nX, i_nY ), Size( i_nWidth, i_nHeight ) ) );
return (int)m_aXineramaScreens.size()-1;
}
void SalDisplay::InitXinerama()
{
if( m_aScreens.size() > 1 )
{
m_bXinerama = false;
return; // multiple screens mean no xinerama
}
#ifdef USE_XINERAMA
#if defined(USE_XINERAMA_XSUN)
int nFramebuffers = 1;
if( XineramaGetState( pDisp_, m_nDefaultScreen ) )
{
XRectangle pFramebuffers[MAXFRAMEBUFFERS];
unsigned char hints[MAXFRAMEBUFFERS];
int result = XineramaGetInfo( pDisp_,
m_nDefaultScreen,
pFramebuffers,
hints,
&nFramebuffers );
if( result > 0 && nFramebuffers > 1 )
{
m_bXinerama = true;
m_aXineramaScreens = std::vector<Rectangle>();
for( int i = 0; i < nFramebuffers; i++ )
addXineramaScreenUnique( pFramebuffers[i].x,
pFramebuffers[i].y,
pFramebuffers[i].width,
pFramebuffers[i].height );
}
}
#elif defined(USE_XINERAMA_XORG)
if( XineramaIsActive( pDisp_ ) )
{
int nFramebuffers = 1;
XineramaScreenInfo* pScreens = XineramaQueryScreens( pDisp_, &nFramebuffers );
if( pScreens )
{
if( nFramebuffers > 1 )
{
m_aXineramaScreens = std::vector<Rectangle>();
for( int i = 0; i < nFramebuffers; i++ )
{
addXineramaScreenUnique( pScreens[i].x_org,
pScreens[i].y_org,
pScreens[i].width,
pScreens[i].height );
}
m_bXinerama = m_aXineramaScreens.size() > 1;
}
XFree( pScreens );
}
}
#endif
#if OSL_DEBUG_LEVEL > 1
if( m_bXinerama )
{
for( std::vector< Rectangle >::const_iterator it = m_aXineramaScreens.begin(); it != m_aXineramaScreens.end(); ++it )
fprintf( stderr, "Xinerama screen: %ldx%ld+%ld+%ld\n", it->GetWidth(), it->GetHeight(), it->Left(), it->Top() );
}
#endif
#endif // USE_XINERAMA
}
void SalDisplay::registerFrame( SalFrame* pFrame )
{
m_aFrames.push_front( pFrame );
}
void SalDisplay::deregisterFrame( SalFrame* pFrame )
{
if( osl_acquireMutex( hEventGuard_ ) )
{
std::list< SalUserEvent >::iterator it = m_aUserEvents.begin();
while ( it != m_aUserEvents.end() )
{
if( it->m_pFrame == pFrame )
it = m_aUserEvents.erase( it );
else
++it;
}
osl_releaseMutex( hEventGuard_ );
}
else {
DBG_ERROR( "SalDisplay::deregisterFrame !acquireMutex\n" );
}
m_aFrames.remove( pFrame );
}
extern "C"
{
static Bool timestamp_predicate( Display*, XEvent* i_pEvent, XPointer i_pArg )
{
SalDisplay* pSalDisplay = reinterpret_cast<SalDisplay*>(i_pArg);
if( i_pEvent->type == PropertyNotify &&
i_pEvent->xproperty.window == pSalDisplay->GetDrawable( pSalDisplay->GetDefaultScreenNumber() ) &&
i_pEvent->xproperty.atom == pSalDisplay->getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT )
)
return True;
return False;
}
}
XLIB_Time SalDisplay::GetLastUserEventTime( bool i_bAlwaysReget ) const
{
if( m_nLastUserEventTime == CurrentTime || i_bAlwaysReget )
{
// get current server time
unsigned char c = 0;
XEvent aEvent;
Atom nAtom = getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT );
XChangeProperty( GetDisplay(), GetDrawable( GetDefaultScreenNumber() ),
nAtom, nAtom, 8, PropModeReplace, &c, 1 );
XFlush( GetDisplay() );
if( ! XIfEventWithTimeout( &aEvent, (XPointer)this, timestamp_predicate ) )
{
// this should not happen at all; still sometimes it happens
aEvent.xproperty.time = CurrentTime;
}
m_nLastUserEventTime = aEvent.xproperty.time;
}
return m_nLastUserEventTime;
}
bool SalDisplay::XIfEventWithTimeout( XEvent* o_pEvent, XPointer i_pPredicateData,
X_if_predicate i_pPredicate, long i_nTimeout ) const
{
/* #i99360# ugly workaround an X11 library bug
this replaces the following call:
XIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData );
*/
bool bRet = true;
if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) )
{
// wait for some event to arrive
struct pollfd aFD;
aFD.fd = ConnectionNumber(GetDisplay());
aFD.events = POLLIN;
aFD.revents = 0;
poll( &aFD, 1, i_nTimeout );
if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) )
{
poll( &aFD, 1, i_nTimeout ); // try once more for a packet of events from the Xserver
if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) )
{
bRet = false;
}
}
}
return bRet;
}
// -=-= SalVisual -=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SalVisual::SalVisual()
{
rtl_zeroMemory( this, sizeof( SalVisual ) );
}
SalVisual::SalVisual( const XVisualInfo* pXVI )
{
*(XVisualInfo*)this = *pXVI;
if( GetClass() == TrueColor )
{
nRedShift_ = sal_Shift( red_mask );
nGreenShift_ = sal_Shift( green_mask );
nBlueShift_ = sal_Shift( blue_mask );
nRedBits_ = sal_significantBits( red_mask );
nGreenBits_ = sal_significantBits( green_mask );
nBlueBits_ = sal_significantBits( blue_mask );
if( GetDepth() == 24 )
if( red_mask == 0xFF0000 )
if( green_mask == 0xFF00 )
if( blue_mask == 0xFF )
eRGBMode_ = RGB;
else
eRGBMode_ = otherSalRGB;
else if( blue_mask == 0xFF00 )
if( green_mask == 0xFF )
eRGBMode_ = RBG;
else
eRGBMode_ = otherSalRGB;
else
eRGBMode_ = otherSalRGB;
else if( green_mask == 0xFF0000 )
if( red_mask == 0xFF00 )
if( blue_mask == 0xFF )
eRGBMode_ = GRB;
else
eRGBMode_ = otherSalRGB;
else if( blue_mask == 0xFF00 )
if( red_mask == 0xFF )
eRGBMode_ = GBR;
else
eRGBMode_ = otherSalRGB;
else
eRGBMode_ = otherSalRGB;
else if( blue_mask == 0xFF0000 )
if( red_mask == 0xFF00 )
if( green_mask == 0xFF )
eRGBMode_ = BRG;
else
eRGBMode_ = otherSalRGB;
else if( green_mask == 0xFF00 )
if( red_mask == 0xFF )
eRGBMode_ = BGR;
else
eRGBMode_ = otherSalRGB;
else
eRGBMode_ = otherSalRGB;
else
eRGBMode_ = otherSalRGB;
else
eRGBMode_ = otherSalRGB;
}
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SalVisual::~SalVisual()
{
if( -1 == screen && VisualID(-1) == visualid ) delete visual;
}
// Konvertiert die Reihenfolge der Bytes eines Pixel in Bytes eines SalColors
// fuer die 6 XXXA ist das nicht reversibel
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// SalColor is RGB (ABGR) a=0xFF000000, r=0xFF0000, g=0xFF00, b=0xFF
#define SALCOLOR RGB
#define SALCOLORREVERSE BGR
sal_Bool SalVisual::Convert( int &n0, int &n1, int &n2, int &n3 )
{
int n;
switch( GetMode() )
{
case otherSalRGB:
return sal_False;
case SALCOLOR:
break;
case SALCOLORREVERSE:
case RBG:
case BRG:
case GBR:
case GRB:
return Convert( n0, n1, n2 );
case RGBA:
n = n0;
n0 = n1;
n1 = n2;
n2 = n3;
n3 = n;
break;
case BGRA:
case RBGA:
case BRGA:
case GBRA:
case GRBA:
default:
fprintf( stderr, "SalVisual::Convert %d\n", GetMode() );
abort();
}
return sal_True;
}
sal_Bool SalVisual::Convert( int &n0, int &n1, int &n2 )
{
int n;
switch( GetMode() )
{
case otherSalRGB:
return sal_False;
case SALCOLOR:
break;
case RBG:
n = n0;
n0 = n1;
n1 = n;
break;
case GRB:
n = n1;
n1 = n2;
n2 = n;
break;
case SALCOLORREVERSE:
n = n0;
n0 = n2;
n2 = n;
break;
case BRG:
n = n0;
n0 = n1;
n1 = n2;
n2 = n;
break;
case GBR:
n = n2;
n2 = n1;
n1 = n0;
n0 = n;
break;
default:
fprintf( stderr, "SalVisual::Convert %d\n", GetMode() );
abort();
}
return sal_True;
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SalColor SalVisual::GetTCColor( Pixel nPixel ) const
{
if( SALCOLOR == eRGBMode_ )
return (SalColor)nPixel;
if( SALCOLORREVERSE == eRGBMode_ )
return MAKE_SALCOLOR( (nPixel & 0x0000FF),
(nPixel & 0x00FF00) >> 8,
(nPixel & 0xFF0000) >> 16);
Pixel r = nPixel & red_mask;
Pixel g = nPixel & green_mask;
Pixel b = nPixel & blue_mask;
if( otherSalRGB != eRGBMode_ ) // 8+8+8=24
return MAKE_SALCOLOR( r >> nRedShift_,
g >> nGreenShift_,
b >> nBlueShift_ );
if( nRedShift_ > 0 ) r >>= nRedShift_; else r <<= -nRedShift_;
if( nGreenShift_ > 0 ) g >>= nGreenShift_; else g <<= -nGreenShift_;
if( nBlueShift_ > 0 ) b >>= nBlueShift_; else b <<= -nBlueShift_;
if( nRedBits_ != 8 )
r |= (r & 0xff) >> (8-nRedBits_);
if( nGreenBits_ != 8 )
g |= (g & 0xff) >> (8-nGreenBits_);
if( nBlueBits_ != 8 )
b |= (b & 0xff) >> (8-nBlueBits_);
return MAKE_SALCOLOR( r, g, b );
}
Pixel SalVisual::GetTCPixel( SalColor nSalColor ) const
{
if( SALCOLOR == eRGBMode_ )
return (Pixel)nSalColor;
Pixel r = (Pixel)SALCOLOR_RED( nSalColor );
Pixel g = (Pixel)SALCOLOR_GREEN( nSalColor );
Pixel b = (Pixel)SALCOLOR_BLUE( nSalColor );
if( SALCOLORREVERSE == eRGBMode_ )
return (b << 16) | (g << 8) | (r);
if( otherSalRGB != eRGBMode_ ) // 8+8+8=24
return (r << nRedShift_) | (g << nGreenShift_) | (b << nBlueShift_);
if( nRedShift_ > 0 ) r <<= nRedShift_; else r >>= -nRedShift_;
if( nGreenShift_ > 0 ) g <<= nGreenShift_; else g >>= -nGreenShift_;
if( nBlueShift_ > 0 ) b <<= nBlueShift_; else b >>= -nBlueShift_;
return (r&red_mask) | (g&green_mask) | (b&blue_mask);
}
// -=-= SalColormap -=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SalColormap::SalColormap( const SalDisplay *pDisplay, Colormap hColormap, int nScreen )
: m_pDisplay( pDisplay ),
m_hColormap( hColormap ),
m_nScreen( nScreen )
{
m_aVisual = m_pDisplay->GetVisual( m_nScreen );
XColor aColor;
GetXPixel( aColor, 0x00, 0x00, 0x00 );
m_nBlackPixel = aColor.pixel;
GetXPixel( aColor, 0xFF, 0xFF, 0xFF );
m_nWhitePixel = aColor.pixel;
m_nUsed = 1 << m_aVisual.GetDepth();
if( m_aVisual.GetClass() == PseudoColor )
{
int r, g, b;
// black, white, gray, ~gray = 4
GetXPixels( aColor, 0xC0, 0xC0, 0xC0 );
// light colors: 3 * 2 = 6
// GetXPixels( aColor, 0x00, 0x00, 0x00 );
GetXPixels( aColor, 0x00, 0x00, 0xFF );
GetXPixels( aColor, 0x00, 0xFF, 0x00 );
GetXPixels( aColor, 0x00, 0xFF, 0xFF );
// GetXPixels( aColor, 0xFF, 0x00, 0x00 );
// GetXPixels( aColor, 0xFF, 0x00, 0xFF );
// GetXPixels( aColor, 0xFF, 0xFF, 0x00 );
// GetXPixels( aColor, 0xFF, 0xFF, 0xFF );
// standard colors: 7 * 2 = 14
// GetXPixels( aColor, 0x00, 0x00, 0x00 );
GetXPixels( aColor, 0x00, 0x00, 0x80 );
GetXPixels( aColor, 0x00, 0x80, 0x00 );
GetXPixels( aColor, 0x00, 0x80, 0x80 );
GetXPixels( aColor, 0x80, 0x00, 0x00 );
GetXPixels( aColor, 0x80, 0x00, 0x80 );
GetXPixels( aColor, 0x80, 0x80, 0x00 );
GetXPixels( aColor, 0x80, 0x80, 0x80 );
GetXPixels( aColor, 0x00, 0xB8, 0xFF ); // Blau 7
// cube: 6*6*6 - 8 = 208
for( r = 0; r < 0x100; r += 0x33 ) // 0x33, 0x66, 0x99, 0xCC, 0xFF
for( g = 0; g < 0x100; g += 0x33 )
for( b = 0; b < 0x100; b += 0x33 )
GetXPixels( aColor, r, g, b );
// gray: 16 - 6 = 10
for( g = 0x11; g < 0xFF; g += 0x11 )
GetXPixels( aColor, g, g, g );
// green: 16 - 6 = 10
for( g = 0x11; g < 0xFF; g += 0x11 )
GetXPixels( aColor, 0, g, 0 );
// red: 16 - 6 = 10
for( r = 0x11; r < 0xFF; r += 0x11 )
GetXPixels( aColor, r, 0, 0 );
// blue: 16 - 6 = 10
for( b = 0x11; b < 0xFF; b += 0x11 )
GetXPixels( aColor, 0, 0, b );
}
}
// PseudoColor
SalColormap::SalColormap( const BitmapPalette &rPalette )
: m_pDisplay( GetX11SalData()->GetDisplay() ),
m_hColormap( None ),
m_nWhitePixel( SALCOLOR_NONE ),
m_nBlackPixel( SALCOLOR_NONE ),
m_nUsed( rPalette.GetEntryCount() ),
m_nScreen( GetX11SalData()->GetDisplay()->GetDefaultScreenNumber() )
{
m_aPalette = std::vector<SalColor>(m_nUsed);
for( unsigned int i = 0; i < m_nUsed; i++ )
{
const BitmapColor &rColor = rPalette[i];
m_aPalette[i] = MAKE_SALCOLOR( rColor.GetRed(),
rColor.GetGreen(),
rColor.GetBlue() );
if( (m_nBlackPixel == SALCOLOR_NONE) && (SALCOLOR_BLACK == m_aPalette[i]) )
m_nBlackPixel = i;
else if( (m_nWhitePixel == SALCOLOR_NONE) && (SALCOLOR_WHITE == m_aPalette[i]) )
m_nWhitePixel = i;
}
}
// MonoChrome
SalColormap::SalColormap()
: m_pDisplay( GetX11SalData()->GetDisplay() ),
m_hColormap( None ),
m_nWhitePixel( 1 ),
m_nBlackPixel( 0 ),
m_nUsed( 2 ),
m_nScreen( 0 )
{
if( m_pDisplay )
m_nScreen = m_pDisplay->GetDefaultScreenNumber();
m_aPalette = std::vector<SalColor>(m_nUsed);
m_aPalette[m_nBlackPixel] = SALCOLOR_BLACK;
m_aPalette[m_nWhitePixel] = SALCOLOR_WHITE;
}
// TrueColor
SalColormap::SalColormap( sal_uInt16 nDepth )
: m_pDisplay( GetX11SalData()->GetDisplay() ),
m_hColormap( None ),
m_nWhitePixel( (1 << nDepth) - 1 ),
m_nBlackPixel( 0x00000000 ),
m_nUsed( 1 << nDepth ),
m_nScreen( GetX11SalData()->GetDisplay()->GetDefaultScreenNumber() )
{
const SalVisual *pVisual = &m_pDisplay->GetVisual( m_nScreen );
if( pVisual->GetClass() == TrueColor && pVisual->GetDepth() == nDepth )
m_aVisual = *pVisual;
else
{
XVisualInfo aVI;
if( !XMatchVisualInfo( m_pDisplay->GetDisplay(),
m_pDisplay->GetDefaultScreenNumber(),
nDepth,
TrueColor,
&aVI ) )
{
aVI.visual = new Visual();
aVI.visualid = (VisualID)0; // beware of temporary destructor below
aVI.screen = 0;
aVI.depth = nDepth;
aVI.c_class = TrueColor;
if( 24 == nDepth ) // 888
{
aVI.red_mask = 0xFF0000;
aVI.green_mask = 0x00FF00;
aVI.blue_mask = 0x0000FF;
}
else if( 16 == nDepth ) // 565
{
aVI.red_mask = 0x00F800;
aVI.green_mask = 0x0007E0;
aVI.blue_mask = 0x00001F;
}
else if( 15 == nDepth ) // 555
{
aVI.red_mask = 0x007C00;
aVI.green_mask = 0x0003E0;
aVI.blue_mask = 0x00001F;
}
else if( 12 == nDepth ) // 444
{
aVI.red_mask = 0x000F00;
aVI.green_mask = 0x0000F0;
aVI.blue_mask = 0x00000F;
}
else if( 8 == nDepth ) // 332
{
aVI.red_mask = 0x0000E0;
aVI.green_mask = 0x00001C;
aVI.blue_mask = 0x000003;
}
else
{
aVI.red_mask = 0x000000;
aVI.green_mask = 0x000000;
aVI.blue_mask = 0x000000;
}
aVI.colormap_size = 0;
aVI.bits_per_rgb = 8;
aVI.visual->ext_data = NULL;
aVI.visual->visualid = aVI.visualid;
aVI.visual->c_class = aVI.c_class;
aVI.visual->red_mask = aVI.red_mask;
aVI.visual->green_mask = aVI.green_mask;
aVI.visual->blue_mask = aVI.blue_mask;
aVI.visual->bits_per_rgb = aVI.bits_per_rgb;
aVI.visual->map_entries = aVI.colormap_size;
m_aVisual = SalVisual( &aVI );
// give ownership of constructed Visual() to m_aVisual
// see SalVisual destructor
m_aVisual.visualid = (VisualID)-1;
m_aVisual.screen = -1;
}
else
m_aVisual = SalVisual( &aVI );
}
}
SalColormap::~SalColormap()
{
#ifdef DBG_UTIL
m_hColormap = (Colormap)ILLEGAL_POINTER;
m_pDisplay = (SalDisplay*)ILLEGAL_POINTER;
#endif
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void SalColormap::SetPalette( const BitmapPalette &rPalette )
{
if( this != &GetX11SalData()->GetDisplay()->GetColormap(m_nScreen) )
{
m_nBlackPixel = SALCOLOR_NONE;
m_nWhitePixel = SALCOLOR_NONE;
}
if( rPalette.GetEntryCount() > m_nUsed )
{
m_nBlackPixel = SALCOLOR_NONE;
m_nWhitePixel = SALCOLOR_NONE;
m_nUsed = rPalette.GetEntryCount();
m_aPalette = std::vector<SalColor>(m_nUsed);
}
for( int i = 0; i < rPalette.GetEntryCount(); i++ )
{
const BitmapColor &rColor = rPalette[i];
m_aPalette[i] = MAKE_SALCOLOR( rColor.GetRed(),
rColor.GetGreen(),
rColor.GetBlue() );
if( (m_nBlackPixel == SALCOLOR_NONE) && (SALCOLOR_BLACK == m_aPalette[i]) )
m_nBlackPixel = i;
else if( (m_nWhitePixel == SALCOLOR_NONE) && (SALCOLOR_WHITE == m_aPalette[i]) )
m_nWhitePixel = i;
}
}
void SalColormap::GetPalette()
{
Pixel i;
m_aPalette = std::vector<SalColor>(m_nUsed);
XColor *aColor = new XColor[m_nUsed];
for( i = 0; i < m_nUsed; i++ )
{
aColor[i].red = aColor[i].green = aColor[i].blue = 0;
aColor[i].pixel = i;
}
XQueryColors( m_pDisplay->GetDisplay(), m_hColormap, aColor, m_nUsed );
for( i = 0; i < m_nUsed; i++ )
{
m_aPalette[i] = MAKE_SALCOLOR( aColor[i].red >> 8,
aColor[i].green >> 8,
aColor[i].blue >> 8 );
}
delete [] aColor;
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
static sal_uInt16 sal_Lookup( const std::vector<SalColor>& rPalette,
int r, int g, int b,
Pixel nUsed )
{
sal_uInt16 nPixel = 0;
int nBest = ColorDiff( rPalette[0], r, g, b );
for( sal_uInt16 i = 1; i < nUsed; i++ )
{
int n = ColorDiff( rPalette[i], r, g, b );
if( n < nBest )
{
if( !n )
return i;
nPixel = i;
nBest = n;
}
}
return nPixel;
}
void SalColormap::GetLookupTable()
{
m_aLookupTable = std::vector<sal_uInt16>(16*16*16);
int i = 0;
for( int r = 0; r < 256; r += 17 )
for( int g = 0; g < 256; g += 17 )
for( int b = 0; b < 256; b += 17 )
m_aLookupTable[i++] = sal_Lookup( m_aPalette, r, g, b, m_nUsed );
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SalColor SalColormap::GetColor( Pixel nPixel ) const
{
if( m_nBlackPixel == nPixel ) return SALCOLOR_BLACK;
if( m_nWhitePixel == nPixel ) return SALCOLOR_WHITE;
if( m_aVisual.GetVisual() )
{
if( m_aVisual.GetClass() == TrueColor )
return m_aVisual.GetTCColor( nPixel );
if( m_aPalette.empty()
&& m_hColormap
#ifdef PSEUDOCOLOR12
&& m_aVisual.GetDepth() <= 12
#else
&& m_aVisual.GetDepth() <= 8
#endif
&& m_aVisual.GetClass() == PseudoColor )
((SalColormap*)this)->GetPalette();
}
if( !m_aPalette.empty() && nPixel < m_nUsed )
return m_aPalette[nPixel];
if( m_hColormap )
{
DBG_ASSERT( 1, "SalColormap::GetColor() !hColormap_\n" );
return nPixel;
}
// DirectColor, StaticColor, StaticGray, GrayScale
XColor aColor;
aColor.pixel = nPixel;
XQueryColor( m_pDisplay->GetDisplay(), m_hColormap, &aColor );
return MAKE_SALCOLOR( aColor.red>>8, aColor.green>>8, aColor.blue>>8 );
}
inline sal_Bool SalColormap::GetXPixel( XColor &rColor,
int r,
int g,
int b ) const
{
rColor.red = r * 257;
rColor.green = g * 257;
rColor.blue = b * 257;
return XAllocColor( GetXDisplay(), m_hColormap, &rColor );
}
sal_Bool SalColormap::GetXPixels( XColor &rColor,
int r,
int g,
int b ) const
{
if( !GetXPixel( rColor, r, g, b ) )
return sal_False;
if( rColor.pixel & 1 )
return sal_True;
return GetXPixel( rColor, r^0xFF, g^0xFF, b^0xFF );
}
Pixel SalColormap::GetPixel( SalColor nSalColor ) const
{
if( SALCOLOR_NONE == nSalColor ) return 0;
if( SALCOLOR_BLACK == nSalColor ) return m_nBlackPixel;
if( SALCOLOR_WHITE == nSalColor ) return m_nWhitePixel;
if( m_aVisual.GetClass() == TrueColor )
return m_aVisual.GetTCPixel( nSalColor );
if( m_aLookupTable.empty() )
{
if( m_aPalette.empty()
&& m_hColormap
#ifdef PSEUDOCOLOR12
&& m_aVisual.GetDepth() <= 12
#else
&& m_aVisual.GetDepth() <= 8
#endif
&& m_aVisual.GetClass() == PseudoColor ) // what else ???
((SalColormap*)this)->GetPalette();
if( !m_aPalette.empty() )
for( Pixel i = 0; i < m_nUsed; i++ )
if( m_aPalette[i] == nSalColor )
return i;
if( m_hColormap )
{
// DirectColor, StaticColor, StaticGray, GrayScale (PseudoColor)
XColor aColor;
if( GetXPixel( aColor,
SALCOLOR_RED ( nSalColor ),
SALCOLOR_GREEN( nSalColor ),
SALCOLOR_BLUE ( nSalColor ) ) )
{
if( !m_aPalette.empty() && !m_aPalette[aColor.pixel] )
{
const_cast<SalColormap*>(this)->m_aPalette[aColor.pixel] = nSalColor;
if( !(aColor.pixel & 1) && !m_aPalette[aColor.pixel+1] )
{
XColor aInversColor;
SalColor nInversColor = nSalColor ^ 0xFFFFFF;
GetXPixel( aInversColor,
SALCOLOR_RED ( nInversColor ),
SALCOLOR_GREEN( nInversColor ),
SALCOLOR_BLUE ( nInversColor ) );
if( !m_aPalette[aInversColor.pixel] )
const_cast<SalColormap*>(this)->m_aPalette[aInversColor.pixel] = nInversColor;
#ifdef DBG_UTIL
else
fprintf( stderr, "SalColormap::GetPixel() 0x%06lx=%lu 0x%06lx=%lu\n",
static_cast< unsigned long >(nSalColor), aColor.pixel,
static_cast< unsigned long >(nInversColor), aInversColor.pixel);
#endif
}
}
return aColor.pixel;
}
#ifdef DBG_UTIL
fprintf( stderr, "SalColormap::GetPixel() !XAllocColor %lx\n",
static_cast< unsigned long >(nSalColor) );
#endif
}
if( m_aPalette.empty() )
{
#ifdef DBG_UTIL
fprintf( stderr, "SalColormap::GetPixel() Palette empty %lx\n",
static_cast< unsigned long >(nSalColor));
#endif
return nSalColor;
}
((SalColormap*)this)->GetLookupTable();
}
// Colormatching ueber Palette
sal_uInt16 r = SALCOLOR_RED ( nSalColor );
sal_uInt16 g = SALCOLOR_GREEN( nSalColor );
sal_uInt16 b = SALCOLOR_BLUE ( nSalColor );
return m_aLookupTable[ (((r+8)/17) << 8)
+ (((g+8)/17) << 4)
+ ((b+8)/17) ];
}