| /************************************************************** |
| * |
| * 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) ]; |
| } |
| |