/************************************************************** * * 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 #include #include #include #include #include #include #include #include #if defined(SOLARIS) #include #include #endif #include #include #include "unx/x11_cursors/salcursors.h" #include "unx/x11_cursors/invert50.h" #ifdef SOLARIS #define XK_KOREAN #endif #include #include #ifdef USE_XINERAMA #ifdef USE_XINERAMA_XORG #include #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 #endif #else #error USE_XINERAMA but no xinerama version #endif #endif #include #include #include #include "unx/i18n_im.hxx" #include "unx/i18n_xkb.hxx" #include #include #include #include #include #include #include #include #ifndef _OSL_THREADMUTEX_H_ #include #endif #include #include #include #include #include #include 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 whether displaystring is in format N.M or N. or just N // with N and M being 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(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(m_aScreens.size()) ) nScreen = m_nDefaultScreen; ScreenData& rSD = const_cast(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(argv), 2 ); XSelectInput( pDisp_, rSD.m_aRefWindow, PropertyChangeMask ); // - - - - - - - - - - GCs - - - - - - - - - - - - - - - - - XGCValues values; values.graphics_exposures = False; values.fill_style = FillOpaqueStippled; values.background = (1<(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(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<= 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 usually SunXK_Stop, // but VCL doesn't have a key definition 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 already 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(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(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(); 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(); 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(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(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(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(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(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& 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(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(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(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) ]; }