Update ooo320-m1
[ooovba.git] / vcl / unx / source / app / saldisp.cxx
blob9d278d433f794f3d9db2d1b8f4f874c0b4ad21ea
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: saldisp.cxx,v $
10 * $Revision: 1.101.30.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #define SAL_XT
36 // -=-= #includes =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
37 #include <string.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <math.h>
41 #if defined(IRIX)
42 #include <ctime>
43 #endif
44 #include <sys/time.h>
45 #include <pthread.h>
46 #include <unistd.h>
47 #include <ctype.h>
48 #include <string.h>
50 #if defined(SOLARIS) || defined(IRIX)
51 #include <sal/alloca.h>
52 #include <osl/module.h>
53 #endif
55 #include <tools/prex.h>
56 #include <X11/cursorfont.h>
57 #include "salcursors.h"
58 #include "invert50.h"
59 #ifdef SOLARIS
60 #define XK_KOREAN
61 #endif
62 #include <X11/keysym.h>
64 #include <X11/Xatom.h>
66 #ifdef USE_XINERAMA
67 #ifdef USE_XINERAMA_XORG
68 #if defined(X86) || defined(X86_64)
69 #include <X11/extensions/Xinerama.h>
70 #endif
71 #elif defined USE_XINERAMA_XSUN
72 #if defined(SOLARIS) && defined(INTEL) // missing extension header in standard installation
73 #define MAXFRAMEBUFFERS 16
74 Bool XineramaGetState(Display*, int);
75 Status XineramaGetInfo(Display*, int, XRectangle*, unsigned char*, int*);
76 #else
77 #include <X11/extensions/xinerama.h>
78 #endif
79 #else
80 #error USE_XINERAMA but no xinerama version
81 #endif
82 #endif
84 #if __XTestExtension__
85 #include <X11/extensions/XTest.h>
86 #include <X11/extensions/XKB.h>
87 #include <X11/XKBlib.h>
88 #endif
90 #include <tools/postx.h>
92 #include <salunx.h>
93 #include <sal/types.h>
94 #include "i18n_im.hxx"
95 #include "i18n_xkb.hxx"
96 #include <saldisp.hxx>
97 #include <saldata.hxx>
98 #include <vcl/salinst.hxx>
99 #include <salgdi.h>
100 #include <salframe.h>
101 #include <vcl/keycodes.hxx>
102 #include <vcl/salbtype.hxx>
103 #include <salbmp.h>
104 #ifndef _OSL_THREADMUTEX_H_
105 #include <osl/mutex.h>
106 #endif
107 #include <salobj.h>
108 #include <sm.hxx>
109 #include <wmadaptor.hxx>
110 #include <dtint.hxx>
112 #include <osl/socket.h>
113 #include <poll.h>
115 using namespace rtl;
116 using namespace vcl_sal;
118 // -=-= #defines -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
119 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
120 #define PSEUDOCOLOR12
121 #define PSEUDOCOLOR8
122 #define TRUECOLOR24
123 #define TRUECOLOR16
124 #define TRUECOLOR15
125 #define TRUECOLOR12
126 #define TRUECOLOR8
128 #define SALCOLOR_WHITE MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF )
129 #define SALCOLOR_BLACK MAKE_SALCOLOR( 0x00, 0x00, 0x00 )
131 // -=-= Prototyps =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
132 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
133 // -=-= static variables -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
134 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
135 static const char* const VisualClassName[] = {
136 "StaticGray",
137 "GrayScale",
138 "StaticColor",
139 "PseudoColor",
140 "TrueColor",
141 "DirectColor"
144 static const char* const EventNames[] =
146 NULL,
147 NULL,
148 "KeyPress",
149 "KeyRelease",
150 "ButtonPress",
151 "ButtonRelease",
152 "MotionNotify",
153 "EnterNotify",
154 "LeaveNotify",
155 "FocusIn",
156 "FocusOut",
157 "KeymapNotify",
158 "Expose",
159 "GraphicsExpose",
160 "NoExpose",
161 "VisibilityNotify",
162 "CreateNotify",
163 "DestroyNotify",
164 "UnmapNotify",
165 "MapNotify",
166 "MapRequest",
167 "ReparentNotify",
168 "ConfigureNotify",
169 "ConfigureRequest",
170 "GravityNotify",
171 "ResizeRequest",
172 "CirculateNotify",
173 "CirculateRequest",
174 "PropertyNotify",
175 "SelectionClear",
176 "SelectionRequest",
177 "SelectionNotify",
178 "ColormapNotify",
179 "ClientMessage",
180 "MappingNotify"
183 // -=-= global inline =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
184 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
185 inline const char *Null( const char *p ) { return p ? p : ""; }
186 inline const char *GetEnv( const char *p ) { return Null( getenv( p ) ); }
187 inline const char *KeyStr( KeySym n ) { return Null( XKeysymToString( n ) ); }
189 inline const char *GetAtomName( Display *d, Atom a )
190 { return Null( XGetAtomName( d, a ) ); }
192 inline double Hypothenuse( long w, long h )
193 { return sqrt( (double)((w*w)+(h*h)) ); }
195 inline int ColorDiff( int r, int g, int b )
196 { return (r*r)+(g*g)+(b*b); }
198 inline int ColorDiff( SalColor c1, int r, int g, int b )
199 { return ColorDiff( (int)SALCOLOR_RED (c1)-r,
200 (int)SALCOLOR_GREEN(c1)-g,
201 (int)SALCOLOR_BLUE (c1)-b ); }
203 // -=-= global functions -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
204 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
205 static int sal_Shift( Pixel nMask )
207 int i = 24;
208 if( nMask < 0x00010000 ) { nMask <<= 16; i -= 16; }
209 if( nMask < 0x01000000 ) { nMask <<= 8; i -= 8; }
210 if( nMask < 0x10000000 ) { nMask <<= 4; i -= 4; }
211 if( nMask < 0x40000000 ) { nMask <<= 2; i -= 2; }
212 if( nMask < 0x80000000 ) { nMask <<= 1; i -= 1; }
213 return i;
216 static int sal_significantBits( Pixel nMask )
218 int nRotate = sizeof(Pixel)*4;
219 int nBits = 0;
220 while( nRotate-- )
222 if( nMask & 1 )
223 nBits++;
224 nMask >>= 1;
226 return nBits;
229 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
230 static BOOL sal_GetVisualInfo( Display *pDisplay, XID nVID, XVisualInfo &rVI )
232 int nInfos;
233 XVisualInfo aTemplate;
234 XVisualInfo*pInfos;
236 aTemplate.visualid = nVID;
238 pInfos = XGetVisualInfo( pDisplay, VisualIDMask, &aTemplate, &nInfos );
239 if( !pInfos )
240 return FALSE;
242 rVI = *pInfos;
243 XFree( pInfos );
245 DBG_ASSERT( rVI.visualid == nVID,
246 "sal_GetVisualInfo: could not get correct visual by visualId" );
247 return TRUE;
250 // ---------------------------------------------------------------------------
252 // check wether displaystring is in format N.M or N. or just N
253 // with N and M beeing natural numbers
254 static BOOL
255 sal_IsDisplayNumber( const char *pDisplayString )
257 if ( ! isdigit(*pDisplayString) )
258 return FALSE;
259 while ( isdigit(*(++pDisplayString)) )
260 ; /* do nothing */
262 if ( *pDisplayString == '.' )
264 while ( isdigit(*(++pDisplayString)) )
265 ; /* do nothing */
268 return (*pDisplayString == '\0');
271 // check whether host1 and host2 point to the same ip address
272 static BOOL
273 sal_EqualHosts( const OUString& Host1, const OUString& Host2)
275 oslSocketAddr pHostAddr1;
276 oslSocketAddr pHostAddr2;
277 BOOL bEqualAddress = FALSE;
279 if ( Host1.toChar() >= '0' && Host1.toChar() <= '9' )
280 pHostAddr1 = osl_createInetSocketAddr( Host1.pData, 0 );
281 else
282 pHostAddr1 = osl_resolveHostname( Host1.pData );
284 if ( Host2.toChar() >= '0' && Host2.toChar() <= '9' )
285 pHostAddr2 = osl_createInetSocketAddr( Host2.pData, 0 );
286 else
287 pHostAddr2 = osl_resolveHostname( Host2.pData );
289 if( pHostAddr1 && pHostAddr2 )
290 bEqualAddress = osl_isEqualSocketAddr( pHostAddr1, pHostAddr2 ) ? TRUE : FALSE;
292 if( pHostAddr1 )
293 osl_destroySocketAddr( pHostAddr1 );
294 if( pHostAddr2 )
295 osl_destroySocketAddr( pHostAddr2 );
297 return bEqualAddress;
300 static BOOL
301 sal_IsLocalDisplay( Display *pDisplay )
303 const char *pDisplayString = DisplayString( pDisplay );
305 // no string, no idea
306 if ( pDisplayString == NULL || pDisplayString[ 0 ] == '\0')
307 return FALSE;
309 // check for ":x.y"
310 if ( pDisplayString[ 0 ] == ':' )
311 return sal_IsDisplayNumber( pDisplayString + 1 );
313 // check for fixed token which all mean localhost:x.y
314 const char pLocal[] = "localhost:";
315 const int nLocalLen = sizeof(pLocal) - 1;
316 if ( strncmp(pDisplayString, pLocal, nLocalLen) == 0 )
317 return sal_IsDisplayNumber( pDisplayString + nLocalLen );
319 const char pUnix[] = "unix:";
320 const int nUnixLen = sizeof(pUnix) - 1;
321 if ( strncmp(pDisplayString, pUnix, nUnixLen) == 0 )
322 return sal_IsDisplayNumber( pDisplayString + nUnixLen );
324 const char pLoopback[] = "127.0.0.1:";
325 const int nLoopbackLen= sizeof(pLoopback) - 1;
326 if ( strncmp(pDisplayString, pLoopback, nLoopbackLen) == 0 )
327 return sal_IsDisplayNumber( pDisplayString + nLoopbackLen );
329 // compare local hostname to displaystring, both may be ip address or
330 // hostname
331 BOOL bEqual = FALSE;
332 char *pDisplayHost = strdup( pDisplayString );
333 char *pPtr = strrchr( pDisplayHost, ':' );
335 if( pPtr != NULL )
337 OUString aLocalHostname;
338 if( osl_getLocalHostname( &aLocalHostname.pData ) == osl_Socket_Ok)
340 *pPtr = '\0';
341 OUString aDisplayHostname( pDisplayHost, strlen( pDisplayHost ), osl_getThreadTextEncoding() );
342 bEqual = sal_EqualHosts( aLocalHostname, aDisplayHostname );
343 bEqual = bEqual && sal_IsDisplayNumber( pPtr + 1 );
346 free( pDisplayHost );
348 return bEqual;
351 // ---------------------------------------------------------------------------
352 // IsLocal means soffice is running on the same host as the xserver
353 // since it is not called very often and sal_IsLocalDisplay() is relative
354 // expensive bLocal_ is initialized on first call
356 BOOL SalDisplay::IsLocal()
358 if ( ! mbLocalIsValid )
360 bLocal_ = sal_IsLocalDisplay( pDisp_ );
361 mbLocalIsValid = TRUE;
363 return (BOOL)bLocal_;
366 // ---------------------------------------------------------------------------
367 extern "C" srv_vendor_t
368 sal_GetServerVendor( Display *p_display )
370 typedef struct {
371 srv_vendor_t e_vendor; // vendor as enum
372 const char *p_name; // vendor name as returned by VendorString()
373 unsigned int n_len; // number of chars to compare
374 } vendor_t;
376 const vendor_t p_vendorlist[] = {
377 { vendor_xfree, "The XFree86 Project, Inc", 13 },
378 { vendor_sun, "Sun Microsystems, Inc.", 10 },
379 { vendor_attachmate, "Attachmate Corporation", 10 },
380 { vendor_excursion,
381 "DECWINDOWS DigitalEquipmentCorporation, eXcursion", 42 },
382 { vendor_hp, "Hewlett-Packard Company", 17 },
383 { vendor_hummingbird, "Hummingbird Communications Ltd.", 11 },
384 { vendor_ibm, "International Business Machines", 24 },
385 { vendor_sgi, "Silicon Graphics", 9 },
386 { vendor_sco, "The Santa Cruz Operation", 16 },
387 { vendor_xinside, "X Inside Inc.", 10 },
388 // allways the last entry: vendor_none to indicate eol
389 { vendor_none, NULL, 0 },
392 #ifdef _USE_PRINT_EXTENSION_
393 if ( ! XSalIsDisplay( p_display ) )
394 return vendor_xprinter;
395 #endif
397 // handle regular server vendors
398 char *p_name = ServerVendor( p_display );
399 vendor_t *p_vendor;
400 for (p_vendor = const_cast<vendor_t*>(p_vendorlist); p_vendor->e_vendor != vendor_none; p_vendor++)
402 if ( strncmp (p_name, p_vendor->p_name, p_vendor->n_len) == 0 )
403 return p_vendor->e_vendor;
406 // vendor not found in list
407 return vendor_unknown;
410 static sal_Bool sal_IsTrustedSolaris (Display *p_display)
412 int n_numextensions = 0;
413 char **p_extensions = XListExtensions (p_display, &n_numextensions);
414 sal_Bool b_is = sal_False;
416 if (p_extensions != NULL)
418 for (int i = 0; !b_is && i < n_numextensions; i++)
419 b_is = (strcmp (p_extensions[i], "SUN_TSOL") == 0);
420 XFreeExtensionList (p_extensions);
423 return b_is;
426 // -=-= SalDisplay -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
427 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
428 BOOL SalDisplay::BestVisual( Display *pDisplay,
429 int nScreen,
430 XVisualInfo &rVI )
432 VisualID nDefVID = XVisualIDFromVisual( DefaultVisual( pDisplay, nScreen ) );
433 VisualID nVID = 0;
434 char *pVID = getenv( "SAL_VISUAL" );
435 if( pVID )
436 sscanf( pVID, "%li", &nVID );
438 if( nVID && sal_GetVisualInfo( pDisplay, nVID, rVI ) )
439 return rVI.visualid == nDefVID;
441 XVisualInfo aVI;
442 aVI.screen = nScreen;
443 // get all visuals
444 int nVisuals;
445 XVisualInfo* pVInfos = XGetVisualInfo( pDisplay, VisualScreenMask,
446 &aVI, &nVisuals );
447 // pVInfos should contain at least one visual, otherwise
448 // we're in trouble
449 int* pWeight = (int*)alloca( sizeof(int)*nVisuals );
450 int i;
451 for( i = 0; i < nVisuals; i++ )
453 BOOL bUsable = FALSE;
454 int nTrueColor = 1;
456 if ( pVInfos[i].screen != nScreen )
458 bUsable = FALSE;
460 else
461 if( pVInfos[i].c_class == TrueColor )
463 nTrueColor = 2048;
464 if( pVInfos[i].depth == 24 )
465 bUsable = TRUE;
466 #ifdef TRUECOLOR8
467 else if( pVInfos[i].depth == 8 )
469 nTrueColor = -1; // strongly discourage 8 bit true color
470 bUsable = TRUE;
472 #endif
473 #ifdef TRUECOLOR15
474 else if( pVInfos[i].depth == 15 )
475 bUsable = TRUE;
476 #endif
477 #ifdef TRUECOLOR16
478 else if( pVInfos[i].depth == 16 )
479 bUsable = TRUE;
480 #endif
481 #ifdef TRUECOLOR32
482 else if( pVInfos[i].depth == 32 )
484 nTrueColor = 256;
485 // we do not have use for an alpha channel
486 // better use a 24 or 16 bit truecolor visual if possible
487 bUsable = TRUE;
489 #endif
491 else if( pVInfos[i].c_class == PseudoColor )
493 if( pVInfos[i].depth <= 8 )
494 bUsable = TRUE;
495 #ifdef PSEUDOCOLOR12
496 else if( pVInfos[i].depth == 12 )
497 bUsable = TRUE;
498 #endif
500 pWeight[ i ] = bUsable ? nTrueColor*pVInfos[i].depth : -1024;
501 pWeight[ i ] -= pVInfos[ i ].visualid;
504 int nBestVisual = 0;
505 int nBestWeight = -1024;
506 for( i = 0; i < nVisuals; i++ )
508 if( pWeight[ i ] > nBestWeight )
510 nBestWeight = pWeight[ i ];
511 nBestVisual = i;
515 rVI = pVInfos[ nBestVisual ];
517 XFree( pVInfos );
518 return rVI.visualid == nDefVID;
521 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
523 SalDisplay::SalDisplay( Display *display ) :
524 mpInputMethod( NULL ),
525 mpFallbackFactory ( NULL ),
526 pDisp_( display ),
527 m_pWMAdaptor( NULL ),
528 m_pDtIntegrator( NULL ),
529 m_bUseRandRWrapper( true ),
530 m_nLastUserEventTime( CurrentTime )
532 #if OSL_DEBUG_LEVEL > 1
533 fprintf( stderr, "SalDisplay::SalDisplay()\n" );
534 #endif
535 X11SalData *pSalData = GetX11SalData();
537 DBG_ASSERT( ! pSalData->GetDisplay(), "Second SalDisplay created !!!\n" );
538 pSalData->SetSalDisplay( this );
540 pXLib_ = pSalData->GetLib();
541 m_nDefaultScreen = DefaultScreen( pDisp_ );
545 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
546 SalDisplay::~SalDisplay( )
548 #if OSL_DEBUG_LEVEL > 1
549 fprintf( stderr, "SalDisplay::~SalDisplay()\n" );
550 #endif
551 if( pDisp_ )
553 doDestruct();
554 #if OSL_DEBUG_LEVEL > 1
555 fprintf( stderr, "display %p closed\n", pDisp_ );
556 #endif
557 pDisp_ = NULL;
559 // don't do this in doDestruct since RandR extension adds hooks into Display
560 // that is XCloseDisplay still needs the RandR library if it was used
561 DeInitRandR();
564 void SalDisplay::doDestruct()
566 X11SalData *pSalData = GetX11SalData();
568 delete m_pWMAdaptor;
569 m_pWMAdaptor = NULL;
570 delete m_pDtIntegrator;
571 m_pDtIntegrator = NULL;
572 X11SalBitmap::ImplDestroyCache();
573 X11SalGraphics::releaseGlyphPeer();
574 DestroyFontCache();
576 if( IsDisplay() )
578 delete mpInputMethod, mpInputMethod = (SalI18N_InputMethod*)ILLEGAL_POINTER;
579 delete mpKbdExtension, mpKbdExtension = (SalI18N_KeyboardExtension*)ILLEGAL_POINTER;
581 // do not call anything that could implicitly call back into
582 // this object after this point
583 osl_destroyMutex( hEventGuard_ );
585 for( unsigned int i = 0; i < m_aScreens.size(); i++ )
587 ScreenData& rData = m_aScreens[i];
588 if( rData.m_bInit )
590 if( rData.m_aMonoGC != rData.m_aCopyGC )
591 XFreeGC( pDisp_, rData.m_aMonoGC );
592 XFreeGC( pDisp_, rData.m_aCopyGC );
593 XFreeGC( pDisp_, rData.m_aAndInvertedGC );
594 XFreeGC( pDisp_, rData.m_aAndGC );
595 XFreeGC( pDisp_, rData.m_aOrGC );
596 XFreeGC( pDisp_, rData.m_aStippleGC );
597 XFreePixmap( pDisp_, rData.m_hInvert50 );
598 XDestroyWindow( pDisp_, rData.m_aRefWindow );
599 Colormap aColMap = rData.m_aColormap.GetXColormap();
600 if( aColMap != None && aColMap != DefaultColormap( pDisp_, i ) )
601 XFreeColormap( pDisp_, aColMap );
605 hEventGuard_ = (oslMutex)ILLEGAL_POINTER;
607 for( size_t i = 0; i < POINTER_COUNT; i++ )
609 if( aPointerCache_[i] )
610 XFreeCursor( pDisp_, aPointerCache_[i] );
613 pXLib_->Remove( ConnectionNumber( pDisp_ ) );
616 if( pSalData->GetDisplay() == this )
617 pSalData->SetSalDisplay( NULL );
620 static int DisplayHasEvent( int
621 #ifdef DBG_UTIL
623 #endif
624 , SalX11Display *pDisplay )
626 DBG_ASSERT( ConnectionNumber( pDisplay->GetDisplay() ) == fd,
627 "wrong fd in DisplayHasEvent" );
628 if( ! pDisplay->IsDisplay() )
629 return 0;
631 vos::IMutex* pSalInstYieldMutex =
632 GetSalData()->m_pInstance->GetYieldMutex();
633 ::vos::OGuard aGuard( *pSalInstYieldMutex );
634 return pDisplay->IsEvent();
636 static int DisplayQueue( int
637 #ifdef DBG_UTIL
639 #endif
640 , SalX11Display *pDisplay )
642 DBG_ASSERT( ConnectionNumber( pDisplay->GetDisplay() ) == fd,
643 "wrong fd in DisplayHasEvent" );
644 vos::IMutex* pSalInstYieldMutex =
645 GetSalData()->m_pInstance->GetYieldMutex();
646 ::vos::OGuard aGuard( *pSalInstYieldMutex );
647 return XEventsQueued( pDisplay->GetDisplay(),
648 QueuedAfterReading );
650 static int DisplayYield( int
651 #ifdef DBG_UTIL
653 #endif
654 , SalX11Display *pDisplay )
656 DBG_ASSERT( ConnectionNumber( pDisplay->GetDisplay() ) == fd,
657 "wrong fd in DisplayHasEvent" );
658 vos::IMutex* pSalInstYieldMutex =
659 GetSalData()->m_pInstance->GetYieldMutex();
660 ::vos::OGuard aGuard( *pSalInstYieldMutex );
661 pDisplay->Yield();
662 return TRUE;
665 SalX11Display::SalX11Display( Display *display )
666 : SalDisplay( display )
668 Init();
670 pXLib_->Insert( ConnectionNumber( pDisp_ ),
671 this,
672 (YieldFunc) DisplayHasEvent,
673 (YieldFunc) DisplayQueue,
674 (YieldFunc) DisplayYield );
677 SalX11Display::~SalX11Display()
679 #if OSL_DEBUG_LEVEL > 1
680 fprintf( stderr, "SalX11Display::~SalX11Display()\n" );
681 #endif
682 if( pDisp_ )
684 doDestruct();
685 XCloseDisplay( pDisp_ );
686 pDisp_ = NULL;
690 void SalDisplay::initScreen( int nScreen ) const
692 if( nScreen < 0 || nScreen >= static_cast<int>(m_aScreens.size()) )
693 nScreen = m_nDefaultScreen;
694 ScreenData& rSD = const_cast<ScreenData&>(m_aScreens[nScreen]);
695 if( rSD.m_bInit )
696 return;
697 rSD.m_bInit = true;
699 XVisualInfo aVI;
700 Colormap aColMap;
702 if( SalDisplay::BestVisual( pDisp_, nScreen, aVI ) ) // DefaultVisual
703 aColMap = DefaultColormap( pDisp_, nScreen );
704 else
705 aColMap = XCreateColormap( pDisp_,
706 RootWindow( pDisp_, nScreen ),
707 aVI.visual,
708 AllocNone );
710 Screen* pScreen = ScreenOfDisplay( pDisp_, nScreen );
712 rSD.m_aSize = Size( WidthOfScreen( pScreen ), HeightOfScreen( pScreen ) );
713 rSD.m_aRoot = RootWindow( pDisp_, nScreen );
714 rSD.m_aVisual = SalVisual( &aVI );
715 rSD.m_aColormap = SalColormap( this, aColMap, nScreen );
717 // we're interested in configure notification of root windows
718 InitRandR( rSD.m_aRoot );
720 // - - - - - - - - - - Reference Window/Default Drawable - -
721 XSetWindowAttributes aXWAttributes;
722 aXWAttributes.border_pixel = 0;
723 aXWAttributes.background_pixel = 0;
724 aXWAttributes.colormap = aColMap;
725 rSD.m_aRefWindow = XCreateWindow( pDisp_,
726 rSD.m_aRoot,
727 0,0, 16,16, 0,
728 rSD.m_aVisual.GetDepth(),
729 InputOutput,
730 rSD.m_aVisual.GetVisual(),
731 CWBorderPixel|CWBackPixel|CWColormap,
732 &aXWAttributes );
734 // set client leader (session id gets set when session is started)
735 if( rSD.m_aRefWindow )
737 // client leader must have WM_CLIENT_LEADER pointing to itself
738 XChangeProperty( pDisp_,
739 rSD.m_aRefWindow,
740 XInternAtom( pDisp_, "WM_CLIENT_LEADER", False ),
741 XA_WINDOW,
743 PropModeReplace,
744 (unsigned char*)&rSD.m_aRefWindow,
748 ByteString aExec( SessionManagerClient::getExecName(), osl_getThreadTextEncoding() );
749 const char* argv[2];
750 argv[0] = "/bin/sh";
751 argv[1] = aExec.GetBuffer();
752 XSetCommand( pDisp_, rSD.m_aRefWindow, const_cast<char**>(argv), 2 );
753 XSelectInput( pDisp_, rSD.m_aRefWindow, PropertyChangeMask );
755 // - - - - - - - - - - GCs - - - - - - - - - - - - - - - - -
756 XGCValues values;
757 values.graphics_exposures = False;
758 values.fill_style = FillOpaqueStippled;
759 values.background = (1<<rSD.m_aVisual.GetDepth())-1;
760 values.foreground = 0;
762 rSD.m_aCopyGC = XCreateGC( pDisp_,
763 rSD.m_aRefWindow,
764 GCGraphicsExposures
765 | GCForeground
766 | GCBackground,
767 &values );
768 rSD.m_aAndInvertedGC= XCreateGC( pDisp_,
769 rSD.m_aRefWindow,
770 GCGraphicsExposures
771 | GCForeground
772 | GCBackground,
773 &values );
774 rSD.m_aAndGC = XCreateGC( pDisp_,
775 rSD.m_aRefWindow,
776 GCGraphicsExposures
777 | GCForeground
778 | GCBackground,
779 &values );
780 rSD.m_aOrGC = XCreateGC( pDisp_,
781 rSD.m_aRefWindow,
782 GCGraphicsExposures
783 | GCForeground
784 | GCBackground,
785 &values );
786 rSD.m_aStippleGC = XCreateGC( pDisp_,
787 rSD.m_aRefWindow,
788 GCGraphicsExposures
789 | GCFillStyle
790 | GCForeground
791 | GCBackground,
792 &values );
794 XSetFunction( pDisp_, rSD.m_aAndInvertedGC, GXandInverted );
795 XSetFunction( pDisp_, rSD.m_aAndGC, GXand );
796 // #44556# PowerPC Solaris 2.5 (XSun 3500) Bug: GXor = GXnop
797 //XSetFunction( pDisp_, pOrGC_, GXor );
798 XSetFunction( pDisp_, rSD.m_aOrGC, GXxor );
800 if( 1 == rSD.m_aVisual.GetDepth() )
802 XSetFunction( pDisp_, rSD.m_aCopyGC, GXcopyInverted );
803 rSD.m_aMonoGC = rSD.m_aCopyGC;
805 else
807 Pixmap hPixmap = XCreatePixmap( pDisp_, rSD.m_aRefWindow, 1, 1, 1 );
808 rSD.m_aMonoGC = XCreateGC( pDisp_,
809 hPixmap,
810 GCGraphicsExposures,
811 &values );
812 XFreePixmap( pDisp_, hPixmap );
814 rSD.m_hInvert50 = XCreateBitmapFromData( pDisp_,
815 rSD.m_aRefWindow,
816 invert50_bits,
817 invert50_width,
818 invert50_height );
822 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
823 void SalDisplay::Init()
825 for( size_t i = 0; i < POINTER_COUNT; i++ )
826 aPointerCache_[i] = None;
828 eWindowManager_ = otherwm;
829 nProperties_ = PROPERTY_DEFAULT;
830 hEventGuard_ = NULL;
831 m_pFontCache = NULL;
832 mpFontList = (XlfdStorage*)NULL;
833 mpFactory = (AttributeProvider*)NULL;
834 m_pCapture = NULL;
835 m_bXinerama = false;
837 int nDisplayScreens = ScreenCount( pDisp_ );
838 m_aScreens = std::vector<ScreenData>(nDisplayScreens);
840 mbExactResolution = false;
841 /* #i15507#
842 * Xft resolution should take precedence since
843 * it is what modern desktops use.
845 const char* pValStr = XGetDefault( pDisp_, "Xft", "dpi" );
846 if( pValStr != NULL )
848 const rtl::OString aValStr( pValStr );
849 const long nDPI = (long) aValStr.toDouble();
850 // guard against insane resolution
851 if( (nDPI >= 50) && (nDPI <= 500) )
853 aResolution_ = Pair( nDPI, nDPI );
854 mbExactResolution = true;
857 if( mbExactResolution == false )
859 aResolution_ =
860 Pair( DPI( WidthOfScreen( DefaultScreenOfDisplay( pDisp_ ) ), DisplayWidthMM ( pDisp_, m_nDefaultScreen ) ),
861 DPI( HeightOfScreen( DefaultScreenOfDisplay( pDisp_ ) ), DisplayHeightMM( pDisp_, m_nDefaultScreen ) ) );
864 nMaxRequestSize_ = XExtendedMaxRequestSize( pDisp_ ) * 4;
865 if( !nMaxRequestSize_ )
866 nMaxRequestSize_ = XMaxRequestSize( pDisp_ ) * 4;
868 SetServerVendor();
869 X11SalBitmap::ImplCreateCache();
871 hEventGuard_ = osl_createMutex();
872 bLocal_ = FALSE; /* dont care, initialize later by
873 calling SalDisplay::IsLocal() */
874 mbLocalIsValid = FALSE; /* bLocal_ is not yet initialized */
876 // - - - - - - - - - - Synchronize - - - - - - - - - - - - -
877 if( getenv( "SAL_SYNCHRONIZE" ) )
878 XSynchronize( pDisp_, True );
880 // - - - - - - - - - - Keyboardmapping - - - - - - - - - - -
881 ModifierMapping();
883 // - - - - - - - - - - Window Manager - - - - - - - - - - -
884 m_pWMAdaptor = ::vcl_sal::WMAdaptor::createWMAdaptor( this );
885 const char *pWM = getenv( "SAL_WM" );
886 if( pWM )
888 long int nWM = 0;
889 sscanf( pWM, "%li", &nWM );
890 eWindowManager_ = SalWM(nWM);
892 else if( XInternAtom( pDisp_, "_SGI_TELL_WM", True ) )
893 eWindowManager_ = FourDwm;
894 else if( XInternAtom( pDisp_, "KWM_RUNNING", True ) )
895 eWindowManager_ = mwm; // naja, eigentlich kwm ...
896 else if( XInternAtom( pDisp_, "_OL_WIN_ATTR", True ) )
897 eWindowManager_ = olwm;
898 else if( m_pWMAdaptor->getWindowManagerName().EqualsAscii( "Dtwm" ) )
899 eWindowManager_ = dtwm;
901 // - - - - - - - - - - Properties - - - - - - - - - - - - -
902 const char *pProperties = getenv( "SAL_PROPERTIES" );
903 if( pProperties )
904 sscanf( pProperties, "%li", &nProperties_ );
905 else
907 #if defined DBG_UTIL || defined SUN || defined LINUX || defined FREEBSD || defined IRIX
908 nProperties_ |= PROPERTY_FEATURE_Maximize;
909 #endif
910 // Server Bugs & Properties
911 if( GetServerVendor() == vendor_excursion )
913 nProperties_ |= PROPERTY_BUG_Stipple;
914 nProperties_ |= PROPERTY_BUG_DrawLine;
915 nProperties_ &= ~PROPERTY_SUPPORT_XSetClipMask;
917 else
918 if( GetServerVendor() == vendor_attachmate )
920 nProperties_ |= PROPERTY_BUG_CopyPlane_RevertBWPixel;
922 else
923 if( GetServerVendor() == vendor_ibm )
925 nProperties_ |= PROPERTY_BUG_XA_FAMILY_NAME_nil;
927 if( otherwm == eWindowManager_ ) eWindowManager_ = mwm;
929 else
930 if( GetServerVendor() == vendor_xfree )
932 nProperties_ |= PROPERTY_BUG_XCopyArea_GXxor;
933 #if defined LINUX || defined FREEBSD
934 // otherwm and olwm are a kind of default, which are not detected
935 // carefully. if we are running linux (i.e. not netbsd) on an xfree
936 // display, fvwm is most probable the wm to choose, confusing with mwm
937 // doesn't harm. #57791# start maximized if possible
938 if( (otherwm == eWindowManager_)
939 || (olwm == eWindowManager_ ))
941 eWindowManager_ = fvwm; // ???
942 nProperties_ |= PROPERTY_FEATURE_Maximize;
944 #else
945 if( otherwm == eWindowManager_ ) eWindowManager_ = winmgr;
946 #endif
947 #if defined SOLARIS && defined SPARC
948 nProperties_ |= PROPERTY_BUG_Bitmap_Bit_Order;
949 // solaris xlib seems to have problems with putting images
950 // in correct bit order to xfree 8 bit displays
951 #endif
953 else
954 if( GetServerVendor() == vendor_sun )
956 // nicht alle! (bekannt: nur Sparc II CG3, CG6?)
957 nProperties_ &= ~PROPERTY_SUPPORT_XSetClipMask;
959 // trusted solaris doesn't allow to change properties on the
960 // wm decoration window
961 if (sal_IsTrustedSolaris (pDisp_))
962 nProperties_ |= PROPERTY_FEATURE_TrustedSolaris;
964 // Fehler im Sun-Solaris X86 Server !
965 if (ImageByteOrder(GetDisplay()) == LSBFirst)
967 nProperties_ |= PROPERTY_BUG_Tile;
968 nProperties_ |= PROPERTY_SUPPORT_3ButtonMouse;
970 else // MSBFirst Sun-Solaris Sparc Server
972 // XCopyPlane reverts black and white for 1bit bitmaps
973 // only sun, only 8bit pseudocolor target
974 if ( (GetVisual(m_nDefaultScreen).GetDepth() == 8)
975 && (GetVisual(m_nDefaultScreen).GetClass() == PseudoColor))
976 nProperties_ |= PROPERTY_BUG_CopyPlane_RevertBWPixel;
977 // Fehler in Solaris 2.5.1
978 if (VendorRelease ( GetDisplay() ) < 3600)
979 nProperties_ |= PROPERTY_BUG_FillPolygon_Tile;
982 if( otherwm == eWindowManager_ )
983 eWindowManager_ = olwm;
985 else
986 if( GetServerVendor() == vendor_sco )
988 if( otherwm == eWindowManager_ ) eWindowManager_ = pmwm;
990 else
991 if( GetServerVendor() == vendor_sgi )
993 if( GetVisual( m_nDefaultScreen ).GetDepth() > 8 && GetVisual( m_nDefaultScreen ).GetDepth() <= 16 )
994 nProperties_ |= PROPERTY_BUG_XCopyArea_GXxor;
995 nProperties_ |= PROPERTY_SUPPORT_XSetClipMask;
997 if( otherwm == eWindowManager_ )
998 eWindowManager_ = FourDwm;
1000 else
1001 if( GetServerVendor() == vendor_hp )
1003 if( otherwm == eWindowManager_ ) eWindowManager_ = dtwm;
1005 else
1006 if( GetServerVendor() == vendor_hummingbird )
1008 if (GetVisual(m_nDefaultScreen).GetDepth() == 24)
1009 nProperties_ |= PROPERTY_BUG_CopyArea_OnlySmallSlices;
1012 if( otherwm == eWindowManager_ )
1014 if( !XInternAtom( pDisp_, "_MOTIF_WM_INFO", True ) )
1015 eWindowManager_ = olwm;
1016 // ???
1019 if( winmgr == eWindowManager_ )
1021 nProperties_ &= ~PROPERTY_SUPPORT_WM_SetPos;
1022 nProperties_ &= ~PROPERTY_SUPPORT_WM_Screen;
1023 nProperties_ |= PROPERTY_FEATURE_Maximize;
1025 else if( dtwm == eWindowManager_ )
1027 nProperties_ &= ~PROPERTY_SUPPORT_WM_ClientPos;
1029 else if( pmwm == eWindowManager_ )
1031 nProperties_ &= ~PROPERTY_SUPPORT_WM_ClientPos;
1035 InitXinerama();
1037 // initialize system settings update
1038 m_pDtIntegrator = DtIntegrator::CreateDtIntegrator();
1040 #ifdef DBG_UTIL
1041 PrintInfo();
1042 #endif
1045 // Sound
1046 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1047 void SalDisplay::Beep() const
1049 XBell( pDisp_, 0 );
1052 // Keyboard
1053 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1055 void SalDisplay::SimulateKeyPress( USHORT nKeyCode )
1057 #if __XTestExtension__
1058 if (nKeyCode == KEY_CAPSLOCK)
1060 XLIB_KeyCode keyCaps = XKeysymToKeycode(GetDisplay(), XK_Caps_Lock);
1061 if (XTestFakeKeyEvent(GetDisplay(), keyCaps, true, CurrentTime))
1062 XTestFakeKeyEvent(GetDisplay(), keyCaps, false, CurrentTime);
1064 #endif
1067 USHORT SalDisplay::GetIndicatorState() const
1069 unsigned int _state = 0;
1070 USHORT nState = 0;
1071 XkbGetIndicatorState(pDisp_, XkbUseCoreKbd, &_state);
1073 if ((_state & 0x00000001))
1074 nState |= INDICATOR_CAPSLOCK;
1075 if ((_state & 0x00000002))
1076 nState |= INDICATOR_NUMLOCK;
1077 if ((_state & 0x00000004))
1078 nState |= INDICATOR_SCROLLLOCK;
1080 return nState;
1083 String SalDisplay::GetKeyNameFromKeySym( KeySym nKeySym ) const
1085 String aRet;
1087 // return an empty string for keysyms that are not bound to
1088 // any key code
1089 XLIB_KeyCode aKeyCode = XKeysymToKeycode( GetDisplay(), nKeySym );
1090 if( aKeyCode != 0 && aKeyCode != NoSymbol )
1092 if( !nKeySym )
1093 aRet = String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "???" ) );
1094 else
1096 aRet = ::vcl_sal::getKeysymReplacementName( const_cast<SalDisplay*>(this)->GetKeyboardName(), nKeySym );
1097 if( ! aRet.Len() )
1099 const char *pString = XKeysymToString( nKeySym );
1100 int n = strlen( pString );
1101 if( n > 2 && pString[n-2] == '_' )
1102 aRet = String( pString, n-2, RTL_TEXTENCODING_ISO_8859_1 );
1103 else
1104 aRet = String( pString, n, RTL_TEXTENCODING_ISO_8859_1 );
1108 return aRet;
1111 inline KeySym sal_XModifier2Keysym( Display *pDisplay,
1112 XModifierKeymap *pXModMap,
1113 int n )
1115 return XKeycodeToKeysym( pDisplay,
1116 pXModMap->modifiermap[n*pXModMap->max_keypermod],
1117 0 );
1120 void SalDisplay::ModifierMapping()
1122 XModifierKeymap *pXModMap = XGetModifierMapping( pDisp_ );
1124 bNumLockFromXS_ = True;
1125 nShiftKeySym_ = sal_XModifier2Keysym( pDisp_, pXModMap, ShiftMapIndex );
1126 nCtrlKeySym_ = sal_XModifier2Keysym( pDisp_, pXModMap, ControlMapIndex );
1127 nMod1KeySym_ = sal_XModifier2Keysym( pDisp_, pXModMap, Mod1MapIndex );
1128 // Auf Sun-Servern und SCO-Severn beruecksichtigt XLookupString
1129 // nicht den NumLock Modifier.
1130 if( (GetServerVendor() == vendor_sun)
1131 || (GetServerVendor() == vendor_sco) )
1133 XLIB_KeyCode aNumLock = XKeysymToKeycode( pDisp_, XK_Num_Lock );
1135 if( aNumLock ) for( int i = ShiftMapIndex; i <= Mod5MapIndex; i++ )
1137 if( pXModMap->modifiermap[i*pXModMap->max_keypermod] == aNumLock )
1139 bNumLockFromXS_ = False;
1140 nNumLockIndex_ = i;
1141 nNumLockMask_ = 1<<i;
1142 break;
1147 XFreeModifiermap( pXModMap );
1150 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1151 XubString SalDisplay::GetKeyName( USHORT nKeyCode ) const
1153 String aStrMap;
1155 if( nKeyCode & KEY_MOD1 )
1156 aStrMap += GetKeyNameFromKeySym( nCtrlKeySym_ );
1158 if( nKeyCode & KEY_MOD2 )
1160 if( aStrMap.Len() )
1161 aStrMap += '+';
1162 aStrMap += GetKeyNameFromKeySym( nMod1KeySym_ );
1165 if( nKeyCode & KEY_SHIFT )
1167 if( aStrMap.Len() )
1168 aStrMap += '+';
1169 aStrMap += GetKeyNameFromKeySym( nShiftKeySym_ );
1171 nKeyCode &= 0x0FFF;
1173 KeySym nKeySym = 0;
1175 if( KEY_0 <= nKeyCode && nKeyCode <= KEY_9 )
1176 nKeySym = XK_0 + (nKeyCode - KEY_0);
1177 else if( KEY_A <= nKeyCode && nKeyCode <= KEY_Z )
1178 nKeySym = XK_A + (nKeyCode - KEY_A);
1179 else if( KEY_F1 <= nKeyCode && nKeyCode <= KEY_F26 ) // Existiert die Taste
1180 nKeySym = XK_F1 + (nKeyCode - KEY_F1);
1181 else switch( nKeyCode )
1183 case KEY_DOWN:
1184 nKeySym = XK_Down;
1185 break;
1186 case KEY_UP:
1187 nKeySym = XK_Up;
1188 break;
1189 case KEY_LEFT:
1190 nKeySym = XK_Left;
1191 break;
1192 case KEY_RIGHT:
1193 nKeySym = XK_Right;
1194 break;
1195 case KEY_HOME:
1196 nKeySym = XK_Home;
1197 break;
1198 case KEY_END:
1199 nKeySym = XK_End;
1200 break;
1201 case KEY_PAGEUP:
1202 nKeySym = XK_Prior;
1203 break;
1204 case KEY_PAGEDOWN:
1205 nKeySym = XK_Next;
1206 break;
1207 case KEY_RETURN:
1208 nKeySym = XK_Return;
1209 break;
1210 case KEY_ESCAPE:
1211 nKeySym = XK_Escape;
1212 break;
1213 case KEY_TAB:
1214 nKeySym = XK_Tab;
1215 break;
1216 case KEY_BACKSPACE:
1217 nKeySym = XK_BackSpace;
1218 break;
1219 case KEY_SPACE:
1220 nKeySym = XK_space;
1221 break;
1222 case KEY_INSERT:
1223 nKeySym = XK_Insert;
1224 break;
1225 case KEY_DELETE:
1226 nKeySym = XK_Delete;
1227 break;
1229 #if !defined (SunXK_Undo)
1230 #define SunXK_Stop 0x0000FF69 // XK_Cancel
1231 #define SunXK_Props 0x1005FF70
1232 #define SunXK_Front 0x1005FF71
1233 #define SunXK_Copy 0x1005FF72
1234 #define SunXK_Open 0x1005FF73
1235 #define SunXK_Paste 0x1005FF74
1236 #define SunXK_Cut 0x1005FF75
1237 #endif
1239 case KEY_REPEAT:
1240 nKeySym = XK_Redo;
1241 break;
1242 case KEY_PROPERTIES:
1243 nKeySym = SunXK_Props;
1244 break;
1245 case KEY_UNDO:
1246 nKeySym = XK_Undo;
1247 break;
1248 case KEY_FRONT:
1249 nKeySym = SunXK_Front;
1250 break;
1251 case KEY_COPY:
1252 nKeySym = SunXK_Copy;
1253 break;
1254 case KEY_OPEN:
1255 nKeySym = SunXK_Open;
1256 break;
1257 case KEY_PASTE:
1258 nKeySym = SunXK_Paste;
1259 break;
1260 case KEY_FIND:
1261 nKeySym = XK_Find;
1262 break;
1263 case KEY_CUT:
1264 nKeySym = GetServerVendor() == vendor_sun ? SunXK_Cut : XK_L10;
1265 break;
1266 case KEY_ADD:
1267 nKeySym = XK_plus;
1268 break;
1269 case KEY_SUBTRACT:
1270 nKeySym = XK_minus;
1271 break;
1272 case KEY_MULTIPLY:
1273 nKeySym = XK_asterisk;
1274 break;
1275 case KEY_DIVIDE:
1276 nKeySym = XK_slash;
1277 break;
1278 case KEY_POINT:
1279 nKeySym = XK_period;
1280 break;
1281 case KEY_COMMA:
1282 nKeySym = XK_comma;
1283 break;
1284 case KEY_LESS:
1285 nKeySym = XK_less;
1286 break;
1287 case KEY_GREATER:
1288 nKeySym = XK_greater;
1289 break;
1290 case KEY_EQUAL:
1291 nKeySym = XK_equal;
1292 break;
1293 case KEY_HELP:
1294 nKeySym = XK_Help;
1295 break;
1296 case KEY_HANGUL_HANJA:
1297 nKeySym = XK_Hangul_Hanja;
1298 break;
1299 case KEY_TILDE:
1300 nKeySym = XK_asciitilde;
1301 break;
1302 case KEY_QUOTELEFT:
1303 nKeySym = XK_grave;
1304 break;
1305 case KEY_BRACKETLEFT:
1306 nKeySym = XK_bracketleft;
1307 break;
1308 case KEY_BRACKETRIGHT:
1309 nKeySym = XK_bracketright;
1310 break;
1312 default:
1313 nKeySym = 0;
1314 break;
1317 if( nKeySym )
1319 String aKeyName = GetKeyNameFromKeySym( nKeySym );
1320 if( aKeyName.Len() )
1322 if( aStrMap.Len() )
1323 aStrMap += '+';
1324 aStrMap += aKeyName;
1326 else
1327 aStrMap.Erase();
1329 else
1330 aStrMap.Erase();
1332 return aStrMap;
1335 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1336 #ifndef IsISOKey
1337 #define IsISOKey( n ) (0x0000FE00==((n)&0xFFFFFF00))
1338 #endif
1340 USHORT SalDisplay::GetKeyCode( KeySym keysym, char*pcPrintable ) const
1342 USHORT nKey = 0;
1344 if( XK_a <= keysym && XK_z >= keysym )
1345 nKey = (USHORT)(KEY_A + (keysym - XK_a));
1346 else if( XK_A <= keysym && XK_Z >= keysym )
1347 nKey = (USHORT)(KEY_A + (keysym - XK_A));
1348 else if( XK_0 <= keysym && XK_9 >= keysym )
1349 nKey = (USHORT)(KEY_0 + (keysym - XK_0));
1350 else if( IsModifierKey( keysym ) )
1352 else if( IsKeypadKey( keysym ) )
1354 if( (keysym >= XK_KP_0) && (keysym <= XK_KP_9) )
1356 nKey = (USHORT)(KEY_0 + (keysym - XK_KP_0));
1357 *pcPrintable = '0' + nKey - KEY_0;
1359 else if( IsPFKey( keysym ) )
1360 nKey = (USHORT)(KEY_F1 + (keysym - XK_KP_F1));
1361 else switch( keysym )
1363 case XK_KP_Space:
1364 nKey = KEY_SPACE;
1365 *pcPrintable = ' ';
1366 break;
1367 case XK_KP_Tab:
1368 nKey = KEY_TAB;
1369 break;
1370 case XK_KP_Enter:
1371 nKey = KEY_RETURN;
1372 break;
1373 case XK_KP_Begin:
1374 case XK_KP_Home:
1375 nKey = KEY_HOME;
1376 break;
1377 case XK_KP_Left:
1378 nKey = KEY_LEFT;
1379 break;
1380 case XK_KP_Up:
1381 nKey = KEY_UP;
1382 break;
1383 case XK_KP_Right:
1384 nKey = KEY_RIGHT;
1385 break;
1386 case XK_KP_Down:
1387 nKey = KEY_DOWN;
1388 break;
1389 case XK_KP_Prior: // XK_KP_Page_Up
1390 nKey = KEY_PAGEUP;
1391 break;
1392 case XK_KP_Next: // XK_KP_Page_Down
1393 nKey = KEY_PAGEDOWN;
1394 break;
1395 case XK_KP_End:
1396 nKey = KEY_END;
1397 break;
1398 case XK_KP_Insert:
1399 nKey = KEY_INSERT;
1400 break;
1401 case XK_KP_Delete:
1402 nKey = KEY_DELETE;
1403 break;
1404 case XK_KP_Equal:
1405 nKey = KEY_EQUAL;
1406 *pcPrintable = '=';
1407 break;
1408 case XK_KP_Multiply:
1409 nKey = KEY_MULTIPLY;
1410 *pcPrintable = '*';
1411 break;
1412 case XK_KP_Add:
1413 nKey = KEY_ADD;
1414 *pcPrintable = '+';
1415 break;
1416 case XK_KP_Separator:
1417 nKey = KEY_DECIMAL;
1418 *pcPrintable = ',';
1419 break;
1420 case XK_KP_Subtract:
1421 nKey = KEY_SUBTRACT;
1422 *pcPrintable = '-';
1423 break;
1424 case XK_KP_Decimal:
1425 nKey = KEY_DECIMAL;
1426 *pcPrintable = '.';
1427 break;
1428 case XK_KP_Divide:
1429 nKey = KEY_DIVIDE;
1430 *pcPrintable = '/';
1431 break;
1434 else if( IsFunctionKey( keysym ) )
1436 if( bNumLockFromXS_ )
1438 if( keysym >= XK_F1 && keysym <= XK_F26 )
1439 nKey = (USHORT)(KEY_F1 + keysym - XK_F1);
1441 else switch( keysym )
1443 // - - - - - Sun X-Server Tastatur ohne Cursorblock ??? - - -
1444 case XK_R7: // XK_F27:
1445 nKey = KEY_HOME;
1446 break;
1447 case XK_R8: // XK_F28:
1448 nKey = KEY_UP;
1449 break;
1450 case XK_R9: // XK_F29:
1451 nKey = KEY_PAGEUP;
1452 break;
1453 case XK_R10: // XK_F30:
1454 nKey = KEY_LEFT;
1455 break;
1456 case XK_R11: // XK_F31:
1457 nKey = 0; // KEY_F31
1458 break;
1459 case XK_R12: // XK_F32:
1460 nKey = KEY_RIGHT;
1461 break;
1462 case XK_R13: // XK_F33:
1463 nKey = KEY_END;
1464 break;
1465 case XK_R14: // XK_F34:
1466 nKey = KEY_DOWN;
1467 break;
1468 case XK_R15: // XK_F35:
1469 nKey = KEY_PAGEDOWN;
1470 break;
1471 // - - - - - Sun X-Server Tastatur ??? - - - - - - - - - - - -
1472 case XK_L1: // XK_F11:
1473 nKey = KEY_F11; // on a sun keyboard this actually is usally SunXK_Stop,
1474 // but VCL doesn't have a key defintion for that
1475 break;
1476 case XK_L2: // XK_F12:
1477 if ( GetServerVendor() == vendor_sun )
1478 nKey = KEY_REPEAT;
1479 else
1480 nKey = KEY_F12;
1481 break;
1482 case XK_L3: // XK_F13:
1483 nKey = KEY_PROPERTIES; // KEY_F13
1484 break;
1485 case XK_L4: // XK_F14:
1486 nKey = KEY_UNDO; // KEY_F14
1487 break;
1488 case XK_L5: // XK_F15:
1489 nKey = KEY_F15; // KEY_FRONT
1490 break;
1491 case XK_L6: // XK_F16:
1492 nKey = KEY_COPY; // KEY_F16
1493 break;
1494 case XK_L7: // XK_F17:
1495 nKey = KEY_F17; // KEY_OPEN
1496 break;
1497 case XK_L8: // XK_F18:
1498 nKey = KEY_PASTE; // KEY_F18
1499 break;
1500 case XK_L9: // XK_F19:
1501 nKey = KEY_F19; // KEY_FIND
1502 break;
1503 case XK_L10: // XK_F20:
1504 nKey = KEY_CUT; // KEY_F20
1505 break;
1506 default:
1507 if( keysym >= XK_F1 && keysym <= XK_F26 )
1508 nKey = (USHORT)(KEY_F1 + keysym - XK_F1);
1509 break;
1512 else if( IsCursorKey( keysym ) )
1514 switch( keysym )
1516 case XK_Begin:
1517 case XK_Home:
1518 nKey = KEY_HOME;
1519 break;
1520 case XK_Left:
1521 nKey = KEY_LEFT;
1522 break;
1523 case XK_Up:
1524 nKey = KEY_UP;
1525 break;
1526 case XK_Right:
1527 nKey = KEY_RIGHT;
1528 break;
1529 case XK_Down:
1530 nKey = KEY_DOWN;
1531 break;
1532 case XK_Prior: // XK_Page_Up
1533 nKey = KEY_PAGEUP;
1534 break;
1535 case XK_Next: // XK_Page_Down
1536 nKey = KEY_PAGEDOWN;
1537 break;
1538 case XK_End:
1539 nKey = KEY_END;
1540 break;
1543 else if( IsMiscFunctionKey( keysym ) )
1545 switch( keysym )
1547 case XK_Insert:
1548 nKey = KEY_INSERT;
1549 break;
1550 case XK_Redo:
1551 nKey = KEY_REPEAT;
1552 break;
1553 case XK_Undo:
1554 nKey = KEY_UNDO;
1555 break;
1556 case XK_Find:
1557 nKey = KEY_FIND;
1558 break;
1559 case XK_Help:
1560 nKey = KEY_HELP;
1561 break;
1562 case XK_Menu:
1563 nKey = KEY_CONTEXTMENU;
1564 break;
1566 case XK_Break:
1567 case XK_Select:
1568 case XK_Execute:
1569 case XK_Print:
1570 case XK_Cancel:
1574 else if( IsISOKey( keysym ) ) // XK_ISO_
1576 switch( keysym )
1578 case 0xFE20: // XK_ISO_Left_Tab:
1579 nKey = KEY_TAB;
1580 break;
1583 else switch( keysym )
1585 case XK_Return:
1586 nKey = KEY_RETURN;
1587 break;
1588 case XK_BackSpace:
1589 nKey = KEY_BACKSPACE;
1590 break;
1591 case XK_Delete:
1592 nKey = KEY_DELETE;
1593 break;
1594 case XK_space:
1595 nKey = KEY_SPACE;
1596 break;
1597 case XK_Tab:
1598 nKey = KEY_TAB;
1599 break;
1600 case XK_Escape:
1601 nKey = KEY_ESCAPE;
1602 break;
1603 case XK_plus:
1604 nKey = KEY_ADD;
1605 break;
1606 case XK_minus:
1607 nKey = KEY_SUBTRACT;
1608 break;
1609 case XK_asterisk:
1610 nKey = KEY_MULTIPLY;
1611 break;
1612 case XK_slash:
1613 nKey = KEY_DIVIDE;
1614 break;
1615 case XK_period:
1616 nKey = KEY_POINT;
1617 break;
1618 case XK_comma:
1619 nKey = KEY_COMMA;
1620 break;
1621 case XK_less:
1622 nKey = KEY_LESS;
1623 break;
1624 case XK_greater:
1625 nKey = KEY_GREATER;
1626 break;
1627 case XK_equal:
1628 nKey = KEY_EQUAL;
1629 break;
1630 case XK_Hangul_Hanja:
1631 nKey = KEY_HANGUL_HANJA;
1632 break;
1633 case XK_asciitilde:
1634 nKey = KEY_TILDE;
1635 *pcPrintable = '~';
1636 break;
1637 case XK_grave:
1638 nKey = KEY_QUOTELEFT;
1639 *pcPrintable = '`';
1640 break;
1641 case XK_bracketleft:
1642 nKey = KEY_BRACKETLEFT;
1643 *pcPrintable = '[';
1644 break;
1645 case XK_bracketright:
1646 nKey = KEY_BRACKETRIGHT;
1647 *pcPrintable = ']';
1648 break;
1649 // case XK_Linefeed:
1650 // *pcPrintable = '\n';
1651 // break;
1652 // - - - - - - - - - - - - - Apollo - - - - - - - - - - - - - 0x1000
1653 case 0x1000FF02: // apXK_Copy
1654 nKey = KEY_COPY;
1655 break;
1656 case 0x1000FF03: // apXK_Cut
1657 nKey = KEY_CUT;
1658 break;
1659 case 0x1000FF04: // apXK_Paste
1660 nKey = KEY_PASTE;
1661 break;
1662 case 0x1000FF14: // apXK_Repeat
1663 nKey = KEY_REPEAT;
1664 break;
1665 // Exit, Save
1666 // - - - - - - - - - - - - - - D E C - - - - - - - - - - - - - 0x1000
1667 case 0x1000FF00:
1668 nKey = KEY_DELETE;
1669 break;
1670 // - - - - - - - - - - - - - - H P - - - - - - - - - - - - - 0x1000
1671 case 0x1000FF73: // hpXK_DeleteChar
1672 nKey = KEY_DELETE;
1673 break;
1674 case 0x1000FF74: // hpXK_BackTab
1675 case 0x1000FF75: // hpXK_KP_BackTab
1676 nKey = KEY_TAB;
1677 break;
1678 // - - - - - - - - - - - - - - I B M - - - - - - - - - - - - -
1679 // - - - - - - - - - - - - - - O S F - - - - - - - - - - - - - 0x1004
1680 case 0x1004FF02: // osfXK_Copy
1681 nKey = KEY_COPY;
1682 break;
1683 case 0x1004FF03: // osfXK_Cut
1684 nKey = KEY_CUT;
1685 break;
1686 case 0x1004FF04: // osfXK_Paste
1687 nKey = KEY_PASTE;
1688 break;
1689 case 0x1004FF07: // osfXK_BackTab
1690 nKey = KEY_TAB;
1691 break;
1692 case 0x1004FF08: // osfXK_BackSpace
1693 nKey = KEY_BACKSPACE;
1694 break;
1695 case 0x1004FF1B: // osfXK_Escape
1696 nKey = KEY_ESCAPE;
1697 break;
1698 // Up, Down, Left, Right, PageUp, PageDown
1699 // - - - - - - - - - - - - - - S C O - - - - - - - - - - - - -
1700 // - - - - - - - - - - - - - - S G I - - - - - - - - - - - - - 0x1007
1701 // - - - - - - - - - - - - - - S N I - - - - - - - - - - - - -
1702 // - - - - - - - - - - - - - - S U N - - - - - - - - - - - - - 0x1005
1703 case 0x1005FF10: // SunXK_F36
1704 nKey = KEY_F11;
1705 break;
1706 case 0x1005FF11: // SunXK_F37
1707 nKey = KEY_F12;
1708 break;
1709 case 0x1005FF70: // SunXK_Props
1710 nKey = KEY_PROPERTIES;
1711 break;
1712 case 0x1005FF71: // SunXK_Front
1713 nKey = KEY_FRONT;
1714 break;
1715 case 0x1005FF72: // SunXK_Copy
1716 nKey = KEY_COPY;
1717 break;
1718 case 0x1005FF73: // SunXK_Open
1719 nKey = KEY_OPEN;
1720 break;
1721 case 0x1005FF74: // SunXK_Paste
1722 nKey = KEY_PASTE;
1723 break;
1724 case 0x1005FF75: // SunXK_Cut
1725 nKey = KEY_CUT;
1726 break;
1728 return nKey;
1731 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1732 KeySym SalDisplay::GetKeySym( XKeyEvent *pEvent,
1733 unsigned char *pPrintable,
1734 int *pLen,
1735 KeySym *pUnmodifiedKeySym,
1736 Status *pStatusReturn,
1737 XIC aInputContext ) const
1739 KeySym nKeySym = 0;
1740 memset( pPrintable, 0, *pLen );
1741 *pStatusReturn = 0;
1743 // first get the printable of the possibly modified KeySym
1744 if ( (aInputContext == 0)
1745 || (pEvent->type == KeyRelease)
1746 || (mpInputMethod != NULL && mpInputMethod->PosixLocale()) )
1748 // XmbLookupString must not be called for KeyRelease events
1749 // Cannot enter space in c locale problem #89616# #88978# btraq #4478197
1750 *pLen = XLookupString( pEvent, (char*)pPrintable, 1, &nKeySym, NULL );
1752 else
1754 *pLen = XmbLookupString( aInputContext,
1755 pEvent, (char*)pPrintable, *pLen - 1, &nKeySym, pStatusReturn );
1757 // Lookup the string again, now with appropriate size
1758 if ( *pStatusReturn == XBufferOverflow )
1760 pPrintable[ 0 ] = (char)0;
1761 return 0;
1764 switch ( *pStatusReturn )
1766 case XBufferOverflow:
1767 /* unhandled error */
1768 break;
1769 case XLookupNone:
1770 /* unhandled error */
1771 break;
1772 case XLookupKeySym:
1773 /* #72223# this is a strange one: on exceed sometimes
1774 * no printable is returned for the first char entered,
1775 * just to retry lookup solves the problem. The problem
1776 * is not yet fully understood, so restrict 2nd lookup
1777 * to 7bit ascii chars */
1778 if ( (XK_space <= nKeySym) && (XK_asciitilde >= nKeySym) )
1780 *pLen = 1;
1781 pPrintable[ 0 ] = (char)nKeySym;
1783 break;
1784 case XLookupBoth:
1785 case XLookupChars:
1787 /* nothing to, char allready in pPrintable */
1788 break;
1792 if( !bNumLockFromXS_
1793 && (IsCursorKey(nKeySym)
1794 || IsFunctionKey(nKeySym)
1795 || IsKeypadKey(nKeySym)
1796 || XK_Delete == nKeySym ) )
1798 // Bei einigen X-Servern muss man bei den Keypadtasten
1799 // schon sehr genau hinschauen. ZB. Solaris XServer:
1800 // 2, 4, 6, 8 werden als Cursorkeys klassifiziert (Up, Down, Left, Right
1801 // 1, 3, 5, 9 werden als Functionkeys klassifiziert (F27,F29,F33,F35)
1802 // 0 als Keypadkey und der Dezimalpunkt gar nicht (KP_Insert)
1803 KeySym nNewKeySym = XLookupKeysym( pEvent, nNumLockIndex_ );
1804 if( nNewKeySym != NoSymbol )
1805 nKeySym = nNewKeySym;
1808 // Now get the unmodified KeySym for KeyCode retrieval
1809 // try to strip off modifiers, e.g. Ctrl-$ becomes Ctrl-Shift-4
1810 *pUnmodifiedKeySym = XKeycodeToKeysym( GetDisplay(), pEvent->keycode, 0);
1812 return nKeySym;
1815 // Pointer
1816 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1817 #define MAKE_BITMAP( name ) \
1818 XCreateBitmapFromData( pDisp_, \
1819 DefaultRootWindow( pDisp_ ), \
1820 name##_bits, \
1821 name##_width, \
1822 name##_height )
1824 #define MAKE_CURSOR( name ) \
1825 aCursBitmap = MAKE_BITMAP( name##curs ); \
1826 aMaskBitmap = MAKE_BITMAP( name##mask ); \
1827 nXHot = name##curs_x_hot; \
1828 nYHot = name##curs_y_hot
1830 XLIB_Cursor SalDisplay::GetPointer( int ePointerStyle )
1832 if( ePointerStyle >= POINTER_COUNT )
1833 return 0;
1835 XLIB_Cursor &aCur = aPointerCache_[ePointerStyle];
1837 if( aCur != None )
1838 return aCur;
1840 Pixmap aCursBitmap = None, aMaskBitmap = None;
1841 unsigned int nXHot = 0, nYHot = 0;
1843 switch( ePointerStyle )
1845 case POINTER_NULL:
1846 MAKE_CURSOR( null );
1847 break;
1848 case POINTER_ARROW:
1849 aCur = XCreateFontCursor( pDisp_, XC_left_ptr );
1850 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1851 break;
1852 case POINTER_WAIT:
1853 aCur = XCreateFontCursor( pDisp_, XC_watch );
1854 break;
1855 case POINTER_TEXT: // Mouse Pointer ist ein "I" Beam
1856 aCur = XCreateFontCursor( pDisp_, XC_xterm );
1857 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1858 break;
1859 case POINTER_HELP:
1860 aCur = XCreateFontCursor( pDisp_, XC_question_arrow );
1861 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1862 break;
1863 case POINTER_CROSS: // Mouse Pointer ist ein Kreuz
1864 aCur = XCreateFontCursor( pDisp_, XC_crosshair );
1865 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1866 break;
1867 case POINTER_NSIZE:
1868 aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow );
1869 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1870 break;
1871 case POINTER_SSIZE:
1872 aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow );
1873 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1874 break;
1875 case POINTER_WSIZE:
1876 aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow );
1877 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1878 break;
1879 case POINTER_ESIZE:
1880 aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow );
1881 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1882 break;
1883 case POINTER_WINDOW_NSIZE:
1884 aCur = XCreateFontCursor( pDisp_, XC_top_side );
1885 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1886 break;
1887 case POINTER_WINDOW_SSIZE:
1888 aCur = XCreateFontCursor( pDisp_, XC_bottom_side );
1889 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1890 break;
1891 case POINTER_WINDOW_WSIZE:
1892 aCur = XCreateFontCursor( pDisp_, XC_left_side );
1893 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1894 break;
1895 case POINTER_WINDOW_ESIZE:
1896 aCur = XCreateFontCursor( pDisp_, XC_right_side );
1897 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1898 break;
1899 case POINTER_NWSIZE:
1900 aCur = XCreateFontCursor( pDisp_, XC_top_left_corner );
1901 break;
1902 case POINTER_NESIZE:
1903 aCur = XCreateFontCursor( pDisp_, XC_top_right_corner );
1904 break;
1905 case POINTER_SWSIZE:
1906 aCur = XCreateFontCursor( pDisp_, XC_bottom_left_corner );
1907 break;
1908 case POINTER_SESIZE:
1909 aCur = XCreateFontCursor( pDisp_, XC_bottom_right_corner );
1910 break;
1911 case POINTER_WINDOW_NWSIZE:
1912 aCur = XCreateFontCursor( pDisp_, XC_top_left_corner );
1913 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1914 break;
1915 case POINTER_WINDOW_NESIZE:
1916 aCur = XCreateFontCursor( pDisp_, XC_top_right_corner );
1917 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1918 break;
1919 case POINTER_WINDOW_SWSIZE:
1920 aCur = XCreateFontCursor( pDisp_, XC_bottom_left_corner );
1921 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1922 break;
1923 case POINTER_WINDOW_SESIZE:
1924 aCur = XCreateFontCursor( pDisp_, XC_bottom_right_corner );
1925 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1926 break;
1927 case POINTER_HSPLIT:
1928 aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow );
1929 break;
1930 case POINTER_VSPLIT:
1931 aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow );
1932 break;
1933 case POINTER_HSIZEBAR:
1934 aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow ); // ???
1935 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1936 break;
1937 case POINTER_VSIZEBAR:
1938 aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow ); // ???
1939 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1940 break;
1941 case POINTER_REFHAND:
1942 aCur = XCreateFontCursor( pDisp_, XC_hand1 );
1943 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1944 break;
1945 case POINTER_HAND:
1946 aCur = XCreateFontCursor( pDisp_, XC_hand2 );
1947 break;
1948 case POINTER_MAGNIFY:
1949 MAKE_CURSOR( magnify_ );
1950 break;
1951 case POINTER_FILL:
1952 MAKE_CURSOR( fill_ );
1953 break;
1954 case POINTER_MOVE:
1955 aCur = XCreateFontCursor( pDisp_, XC_fleur );
1956 break;
1957 case POINTER_MOVEDATA:
1958 MAKE_CURSOR( movedata_ );
1959 break;
1960 case POINTER_COPYDATA:
1961 MAKE_CURSOR( copydata_ );
1962 break;
1963 case POINTER_MOVEFILE:
1964 MAKE_CURSOR( movefile_ );
1965 break;
1966 case POINTER_COPYFILE:
1967 MAKE_CURSOR( copyfile_ );
1968 break;
1969 case POINTER_MOVEFILES:
1970 MAKE_CURSOR( movefiles_ );
1971 break;
1972 case POINTER_COPYFILES:
1973 MAKE_CURSOR( copyfiles_ );
1974 break;
1975 case POINTER_NOTALLOWED:
1976 MAKE_CURSOR( nodrop_ );
1977 break;
1978 case POINTER_ROTATE:
1979 MAKE_CURSOR( rotate_ );
1980 break;
1981 case POINTER_HSHEAR:
1982 MAKE_CURSOR( hshear_ );
1983 break;
1984 case POINTER_VSHEAR:
1985 MAKE_CURSOR( vshear_ );
1986 break;
1987 case POINTER_DRAW_LINE:
1988 MAKE_CURSOR( drawline_ );
1989 break;
1990 case POINTER_DRAW_RECT:
1991 MAKE_CURSOR( drawrect_ );
1992 break;
1993 case POINTER_DRAW_POLYGON:
1994 MAKE_CURSOR( drawpolygon_ );
1995 break;
1996 case POINTER_DRAW_BEZIER:
1997 MAKE_CURSOR( drawbezier_ );
1998 break;
1999 case POINTER_DRAW_ARC:
2000 MAKE_CURSOR( drawarc_ );
2001 break;
2002 case POINTER_DRAW_PIE:
2003 MAKE_CURSOR( drawpie_ );
2004 break;
2005 case POINTER_DRAW_CIRCLECUT:
2006 MAKE_CURSOR( drawcirclecut_ );
2007 break;
2008 case POINTER_DRAW_ELLIPSE:
2009 MAKE_CURSOR( drawellipse_ );
2010 break;
2011 case POINTER_DRAW_CONNECT:
2012 MAKE_CURSOR( drawconnect_ );
2013 break;
2014 case POINTER_DRAW_TEXT:
2015 MAKE_CURSOR( drawtext_ );
2016 break;
2017 case POINTER_MIRROR:
2018 MAKE_CURSOR( mirror_ );
2019 break;
2020 case POINTER_CROOK:
2021 MAKE_CURSOR( crook_ );
2022 break;
2023 case POINTER_CROP:
2024 MAKE_CURSOR( crop_ );
2025 break;
2026 case POINTER_MOVEPOINT:
2027 MAKE_CURSOR( movepoint_ );
2028 break;
2029 case POINTER_MOVEBEZIERWEIGHT:
2030 MAKE_CURSOR( movebezierweight_ );
2031 break;
2032 case POINTER_DRAW_FREEHAND:
2033 MAKE_CURSOR( drawfreehand_ );
2034 break;
2035 case POINTER_DRAW_CAPTION:
2036 MAKE_CURSOR( drawcaption_ );
2037 break;
2038 case POINTER_PEN: // Mouse Pointer ist ein Stift
2039 aCur = XCreateFontCursor( pDisp_, XC_pencil );
2040 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
2041 break;
2042 case POINTER_LINKDATA:
2043 MAKE_CURSOR( linkdata_ );
2044 break;
2045 case POINTER_MOVEDATALINK:
2046 MAKE_CURSOR( movedlnk_ );
2047 break;
2048 case POINTER_COPYDATALINK:
2049 MAKE_CURSOR( copydlnk_ );
2050 break;
2051 case POINTER_LINKFILE:
2052 MAKE_CURSOR( linkfile_ );
2053 break;
2054 case POINTER_MOVEFILELINK:
2055 MAKE_CURSOR( moveflnk_ );
2056 break;
2057 case POINTER_COPYFILELINK:
2058 MAKE_CURSOR( copyflnk_ );
2059 break;
2060 case POINTER_CHART:
2061 MAKE_CURSOR( chart_ );
2062 break;
2063 case POINTER_DETECTIVE:
2064 MAKE_CURSOR( detective_ );
2065 break;
2066 case POINTER_PIVOT_COL:
2067 MAKE_CURSOR( pivotcol_ );
2068 break;
2069 case POINTER_PIVOT_ROW:
2070 MAKE_CURSOR( pivotrow_ );
2071 break;
2072 case POINTER_PIVOT_FIELD:
2073 MAKE_CURSOR( pivotfld_ );
2074 break;
2075 case POINTER_PIVOT_DELETE:
2076 MAKE_CURSOR( pivotdel_ );
2077 break;
2078 case POINTER_CHAIN:
2079 MAKE_CURSOR( chain_ );
2080 break;
2081 case POINTER_CHAIN_NOTALLOWED:
2082 MAKE_CURSOR( chainnot_ );
2083 break;
2084 case POINTER_TIMEEVENT_MOVE:
2085 MAKE_CURSOR( timemove_ );
2086 break;
2087 case POINTER_TIMEEVENT_SIZE:
2088 MAKE_CURSOR( timesize_ );
2089 break;
2090 case POINTER_AUTOSCROLL_N:
2091 MAKE_CURSOR(asn_ );
2092 break;
2093 case POINTER_AUTOSCROLL_S:
2094 MAKE_CURSOR( ass_ );
2095 break;
2096 case POINTER_AUTOSCROLL_W:
2097 MAKE_CURSOR( asw_ );
2098 break;
2099 case POINTER_AUTOSCROLL_E:
2100 MAKE_CURSOR( ase_ );
2101 break;
2102 case POINTER_AUTOSCROLL_NW:
2103 MAKE_CURSOR( asnw_ );
2104 break;
2105 case POINTER_AUTOSCROLL_NE:
2106 MAKE_CURSOR( asne_ );
2107 break;
2108 case POINTER_AUTOSCROLL_SW:
2109 MAKE_CURSOR( assw_ );
2110 break;
2111 case POINTER_AUTOSCROLL_SE:
2112 MAKE_CURSOR( asse_ );
2113 break;
2114 case POINTER_AUTOSCROLL_NS:
2115 MAKE_CURSOR( asns_ );
2116 break;
2117 case POINTER_AUTOSCROLL_WE:
2118 MAKE_CURSOR( aswe_ );
2119 break;
2120 case POINTER_AUTOSCROLL_NSWE:
2121 MAKE_CURSOR( asnswe_ );
2122 break;
2123 case POINTER_AIRBRUSH:
2124 MAKE_CURSOR( airbrush_ );
2125 break;
2126 case POINTER_TEXT_VERTICAL:
2127 MAKE_CURSOR( vertcurs_ );
2128 break;
2130 // --> FME 2004-07-30 #i32329# Enhanced table selection
2131 case POINTER_TAB_SELECT_S:
2132 MAKE_CURSOR( tblsels_ );
2133 break;
2134 case POINTER_TAB_SELECT_E:
2135 MAKE_CURSOR( tblsele_ );
2136 break;
2137 case POINTER_TAB_SELECT_SE:
2138 MAKE_CURSOR( tblselse_ );
2139 break;
2140 case POINTER_TAB_SELECT_W:
2141 MAKE_CURSOR( tblselw_ );
2142 break;
2143 case POINTER_TAB_SELECT_SW:
2144 MAKE_CURSOR( tblselsw_ );
2145 break;
2146 // <--
2148 // --> FME 2004-08-16 #i20119# Paintbrush tool
2149 case POINTER_PAINTBRUSH :
2150 MAKE_CURSOR( paintbrush_ );
2151 break;
2152 // <--
2154 default:
2155 DBG_ERROR("pointer not implemented");
2156 aCur = XCreateFontCursor( pDisp_, XC_arrow );
2157 break;
2160 if( None == aCur )
2162 XColor aBlack, aWhite, aDummy;
2163 Colormap hColormap = GetColormap(m_nDefaultScreen).GetXColormap();
2165 XAllocNamedColor( pDisp_, hColormap, "black", &aBlack, &aDummy );
2166 XAllocNamedColor( pDisp_, hColormap, "white", &aWhite, &aDummy );
2168 aCur = XCreatePixmapCursor( pDisp_,
2169 aCursBitmap, aMaskBitmap,
2170 &aBlack, &aWhite,
2171 nXHot, nYHot );
2173 XFreePixmap( pDisp_, aCursBitmap );
2174 XFreePixmap( pDisp_, aMaskBitmap );
2177 return aCur;
2180 int SalDisplay::CaptureMouse( SalFrame *pCapture )
2182 if( !pCapture )
2184 m_pCapture = NULL;
2185 XUngrabPointer( GetDisplay(), CurrentTime );
2186 XFlush( GetDisplay() );
2187 return 0;
2190 m_pCapture = NULL;
2192 // FIXME: get rid of X11SalFrame
2193 const SystemEnvData* pEnvData = pCapture->GetSystemData();
2194 int ret = XGrabPointer( GetDisplay(),
2195 (XLIB_Window)pEnvData->aWindow,
2196 False,
2197 PointerMotionMask| ButtonPressMask|ButtonReleaseMask,
2198 GrabModeAsync,
2199 GrabModeAsync,
2200 None,
2201 static_cast<X11SalFrame*>(pCapture)->GetCursor(),
2202 CurrentTime );
2204 if( ret != GrabSuccess )
2206 DBG_ASSERT( 1, "SalDisplay::CaptureMouse could not grab pointer\n");
2207 return -1;
2210 m_pCapture = pCapture;
2211 return 1;
2214 // Events
2215 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2217 void SalDisplay::SendInternalEvent( SalFrame* pFrame, void* pData, USHORT nEvent )
2219 if( osl_acquireMutex( hEventGuard_ ) )
2221 m_aUserEvents.push_back( SalUserEvent( pFrame, pData, nEvent ) );
2223 // Notify SalXLib::Yield() of a pending event.
2224 pXLib_->PostUserEvent();
2226 osl_releaseMutex( hEventGuard_ );
2228 else {
2229 DBG_ASSERT( 1, "SalDisplay::SendInternalEvent !acquireMutex\n" );
2233 void SalDisplay::CancelInternalEvent( SalFrame* pFrame, void* pData, USHORT nEvent )
2235 if( osl_acquireMutex( hEventGuard_ ) )
2237 if( ! m_aUserEvents.empty() )
2239 std::list< SalUserEvent >::iterator it, next;
2240 next = m_aUserEvents.begin();
2243 it = next++;
2244 if( it->m_pFrame == pFrame &&
2245 it->m_pData == pData &&
2246 it->m_nEvent == nEvent )
2248 m_aUserEvents.erase( it );
2250 } while( next != m_aUserEvents.end() );
2253 osl_releaseMutex( hEventGuard_ );
2255 else {
2256 DBG_ASSERT( 1, "SalDisplay::CancelInternalEvent !acquireMutex\n" );
2260 BOOL SalX11Display::IsEvent()
2262 BOOL bRet = FALSE;
2264 if( osl_acquireMutex( hEventGuard_ ) )
2266 if( m_aUserEvents.begin() != m_aUserEvents.end() )
2267 bRet = TRUE;
2268 osl_releaseMutex( hEventGuard_ );
2271 if( bRet || XEventsQueued( pDisp_, QueuedAlready ) )
2272 return TRUE;
2274 XFlush( pDisp_ );
2275 return FALSE;
2278 bool SalDisplay::DispatchInternalEvent()
2280 SalFrame* pFrame = NULL;
2281 void* pData = NULL;
2282 USHORT nEvent = 0;
2284 if( osl_acquireMutex( hEventGuard_ ) )
2286 if( m_aUserEvents.begin() != m_aUserEvents.end() )
2288 pFrame = m_aUserEvents.front().m_pFrame;
2289 pData = m_aUserEvents.front().m_pData;
2290 nEvent = m_aUserEvents.front().m_nEvent;
2292 m_aUserEvents.pop_front();
2294 osl_releaseMutex( hEventGuard_ );
2296 else {
2297 DBG_ASSERT( 1, "SalDisplay::Yield !acquireMutex\n" );
2300 if( pFrame )
2301 pFrame->CallCallback( nEvent, pData );
2303 return pFrame != NULL;
2306 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2308 void SalX11Display::Yield()
2310 if( DispatchInternalEvent() )
2311 return;
2313 XEvent aEvent;
2314 DBG_ASSERT( static_cast<SalYieldMutex*>(GetSalData()->m_pInstance->GetYieldMutex())->GetThreadId() ==
2315 NAMESPACE_VOS(OThread)::getCurrentIdentifier(),
2316 "will crash soon since solar mutex not locked in SalDisplay::Yield" );
2318 XNextEvent( pDisp_, &aEvent );
2320 Dispatch( &aEvent );
2322 #ifdef DBG_UTIL
2323 if( pXLib_->HasXErrorOccured() )
2325 XFlush( pDisp_ );
2326 PrintEvent( "SalDisplay::Yield (WasXError)", &aEvent );
2328 #endif
2329 pXLib_->ResetXErrorOccured();
2332 long SalX11Display::Dispatch( XEvent *pEvent )
2334 if( pEvent->type == XLIB_KeyPress || pEvent->type == KeyRelease )
2336 XLIB_Window aWindow = pEvent->xkey.window;
2338 std::list< SalFrame* >::const_iterator it;
2339 for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it )
2341 const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it);
2342 if( pFrame->GetWindow() == aWindow || pFrame->GetShellWindow() == aWindow )
2344 aWindow = pFrame->GetWindow();
2345 break;
2348 if( it != m_aFrames.end() )
2350 if ( mpInputMethod->FilterEvent( pEvent , aWindow ) )
2351 return 0;
2354 else
2355 if ( mpInputMethod->FilterEvent( pEvent, None ) )
2356 return 0;
2358 SalInstance* pInstance = GetSalData()->m_pInstance;
2359 if( pInstance->GetEventCallback() )
2361 YieldMutexReleaser aReleaser;
2362 pInstance->CallEventCallback( pEvent, sizeof( XEvent ) );
2365 switch( pEvent->type )
2367 case MotionNotify:
2368 while( XCheckWindowEvent( pEvent->xany.display,
2369 pEvent->xany.window,
2370 ButtonMotionMask,
2371 pEvent ) )
2373 m_nLastUserEventTime = pEvent->xmotion.time;
2374 break;
2375 case PropertyNotify:
2376 if( pEvent->xproperty.atom == getWMAdaptor()->getAtom( WMAdaptor::VCL_SYSTEM_SETTINGS ) )
2378 for( unsigned int i = 0; i < m_aScreens.size(); i++ )
2380 if( pEvent->xproperty.window == m_aScreens[i].m_aRefWindow )
2382 std::list< SalFrame* >::const_iterator it;
2383 for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it )
2384 (*it)->CallCallback( SALEVENT_SETTINGSCHANGED, NULL );
2385 return 0;
2389 break;
2390 case MappingNotify:
2391 if( MappingKeyboard == pEvent->xmapping.request ||
2392 MappingModifier == pEvent->xmapping.request )
2394 XRefreshKeyboardMapping( &pEvent->xmapping );
2395 if( MappingModifier == pEvent->xmapping.request )
2396 ModifierMapping();
2397 if( MappingKeyboard == pEvent->xmapping.request ) // refresh mapping
2398 GetKeyboardName( TRUE );
2400 break;
2401 case ButtonPress:
2402 case ButtonRelease:
2403 m_nLastUserEventTime = pEvent->xbutton.time;
2404 break;
2405 case XLIB_KeyPress:
2406 case KeyRelease:
2407 m_nLastUserEventTime = pEvent->xkey.time;
2408 break;
2409 default:
2411 if ( GetKbdExtension()->UseExtension()
2412 && GetKbdExtension()->GetEventBase() == pEvent->type )
2414 GetKbdExtension()->Dispatch( pEvent );
2415 return 1;
2417 break;
2420 std::list< SalFrame* >::iterator it;
2421 for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it )
2423 X11SalFrame* pFrame = static_cast< X11SalFrame* >(*it);
2424 XLIB_Window aDispatchWindow = pEvent->xany.window;
2425 if( pFrame->GetWindow() == aDispatchWindow
2426 || pFrame->GetShellWindow() == aDispatchWindow
2427 || pFrame->GetForeignParent() == aDispatchWindow
2430 return pFrame->Dispatch( pEvent );
2432 if( pEvent->type == ConfigureNotify && pEvent->xconfigure.window == pFrame->GetStackingWindow() )
2434 return pFrame->Dispatch( pEvent );
2438 // dispatch to salobjects
2439 X11SalObject::Dispatch( pEvent );
2441 // is this perhaps a root window that changed size ?
2442 processRandREvent( pEvent );
2444 return 0;
2447 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2448 void SalDisplay::PrintEvent( const ByteString &rComment,
2449 XEvent *pEvent ) const
2451 if( pEvent->type <= MappingNotify )
2453 fprintf( stderr, "[%s] %s s=%d w=%ld\n",
2454 rComment.GetBuffer(),
2455 EventNames[pEvent->type],
2456 pEvent->xany.send_event,
2457 pEvent->xany.window );
2459 switch( pEvent->type )
2461 case XLIB_KeyPress:
2462 case KeyRelease:
2463 fprintf( stderr, "\t\ts=%d c=%d\n",
2464 pEvent->xkey.state,
2465 pEvent->xkey.keycode );
2466 break;
2468 case ButtonPress:
2469 case ButtonRelease:
2470 fprintf( stderr, "\t\ts=%d b=%d x=%d y=%d rx=%d ry=%d\n",
2471 pEvent->xbutton.state,
2472 pEvent->xbutton.button,
2473 pEvent->xbutton.x,
2474 pEvent->xbutton.y,
2475 pEvent->xbutton.x_root,
2476 pEvent->xbutton.y_root );
2477 break;
2479 case MotionNotify:
2480 fprintf( stderr, "\t\ts=%d x=%d y=%d\n",
2481 pEvent->xmotion.state,
2482 pEvent->xmotion.x,
2483 pEvent->xmotion.y );
2484 break;
2486 case EnterNotify:
2487 case LeaveNotify:
2488 fprintf( stderr, "\t\tm=%d f=%d x=%d y=%d\n",
2489 pEvent->xcrossing.mode,
2490 pEvent->xcrossing.focus,
2491 pEvent->xcrossing.x,
2492 pEvent->xcrossing.y );
2493 break;
2495 case FocusIn:
2496 case FocusOut:
2497 fprintf( stderr, "\t\tm=%d d=%d\n",
2498 pEvent->xfocus.mode,
2499 pEvent->xfocus.detail );
2500 break;
2502 case Expose:
2503 case GraphicsExpose:
2504 fprintf( stderr, "\t\tc=%d %d*%d %d+%d\n",
2505 pEvent->xexpose.count,
2506 pEvent->xexpose.width,
2507 pEvent->xexpose.height,
2508 pEvent->xexpose.x,
2509 pEvent->xexpose.y );
2510 break;
2512 case VisibilityNotify:
2513 fprintf( stderr, "\t\ts=%d\n",
2514 pEvent->xvisibility.state );
2515 break;
2517 case CreateNotify:
2518 case DestroyNotify:
2519 break;
2521 case MapNotify:
2522 case UnmapNotify:
2523 break;
2525 case ReparentNotify:
2526 fprintf( stderr, "\t\tp=%d x=%d y=%d\n",
2527 sal::static_int_cast< int >(pEvent->xreparent.parent),
2528 pEvent->xreparent.x,
2529 pEvent->xreparent.y );
2530 break;
2532 case ConfigureNotify:
2533 fprintf( stderr, "\t\tb=%d %d*%d %d+%d\n",
2534 pEvent->xconfigure.border_width,
2535 pEvent->xconfigure.width,
2536 pEvent->xconfigure.height,
2537 pEvent->xconfigure.x,
2538 pEvent->xconfigure.y );
2539 break;
2541 case PropertyNotify:
2542 fprintf( stderr, "\t\ta=%s (0x%X)\n",
2543 GetAtomName( pDisp_, pEvent->xproperty.atom ),
2544 sal::static_int_cast< unsigned int >(
2545 pEvent->xproperty.atom) );
2546 break;
2548 case ColormapNotify:
2549 fprintf( stderr, "\t\tc=%ld n=%d s=%d\n",
2550 pEvent->xcolormap.colormap,
2551 pEvent->xcolormap.c_new,
2552 pEvent->xcolormap.state );
2553 break;
2555 case ClientMessage:
2556 fprintf( stderr, "\t\ta=%s (0x%X) f=%i [0x%lX,0x%lX,0x%lX,0x%lX,0x%lX])\n",
2557 GetAtomName( pDisp_, pEvent->xclient.message_type ),
2558 sal::static_int_cast< unsigned int >(
2559 pEvent->xclient.message_type),
2560 pEvent->xclient.format,
2561 pEvent->xclient.data.l[0],
2562 pEvent->xclient.data.l[1],
2563 pEvent->xclient.data.l[2],
2564 pEvent->xclient.data.l[3],
2565 pEvent->xclient.data.l[4] );
2566 break;
2568 case MappingNotify:
2569 fprintf( stderr, "\t\tr=%sd\n",
2570 MappingModifier == pEvent->xmapping.request
2571 ? "MappingModifier"
2572 : MappingKeyboard == pEvent->xmapping.request
2573 ? "MappingKeyboard"
2574 : "MappingPointer" );
2576 break;
2579 else
2580 fprintf( stderr, "[%s] %d s=%d w=%ld\n",
2581 rComment.GetBuffer(),
2582 pEvent->type,
2583 pEvent->xany.send_event,
2584 pEvent->xany.window );
2587 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2588 void SalDisplay::PrintInfo() const
2590 if( IsDisplay() )
2592 fprintf( stderr, "\n" );
2593 fprintf( stderr, "Environment\n" );
2594 fprintf( stderr, "\t$XENVIRONMENT \t\"%s\"\n",
2595 GetEnv( "XENVIRONMENT" ) );
2596 fprintf( stderr, "\t$DISPLAY \t\"%s\"\n",
2597 GetEnv( "DISPLAY" ) );
2598 fprintf( stderr, "\t$SAL_VISUAL \t\"%s\"\n",
2599 GetEnv( "SAL_VISUAL" ) );
2600 fprintf( stderr, "\t$SAL_FONTPATH \t\"%s\"\n",
2601 GetEnv( "SAL_FONTPATH" ) );
2602 fprintf( stderr, "\t$SAL_NOSEGV \t\"%s\"\n",
2603 GetEnv( "SAL_NOSEGV" ) );
2604 fprintf( stderr, "\t$SAL_IGNOREXERRORS\t\"%s\"\n",
2605 GetEnv( "SAL_IGNOREXERRORS" ) );
2606 fprintf( stderr, "\t$SAL_PROPERTIES \t\"%s\"\n",
2607 GetEnv( "SAL_PROPERTIES" ) );
2608 fprintf( stderr, "\t$SAL_WM \t\"%s\"\n",
2609 GetEnv( "SAL_WM" ) );
2610 fprintf( stderr, "\t$SAL_SYNCHRONIZE \t\"%s\"\n",
2611 GetEnv( "SAL_SYNCHRONIZE" ) );
2613 char sHostname[ 120 ];
2614 gethostname (sHostname, 120 );
2615 fprintf( stderr, "Client\n" );
2616 fprintf( stderr, "\tHost \t\"%s\"\n",
2617 sHostname );
2619 fprintf( stderr, "Display\n" );
2620 fprintf( stderr, "\tHost \t\"%s\"\n",
2621 DisplayString(pDisp_) );
2622 fprintf( stderr, "\tVendor (Release) \t\"%s (%d)\"\n",
2623 ServerVendor(pDisp_), VendorRelease(pDisp_) );
2624 fprintf( stderr, "\tProtocol \t%d.%d\n",
2625 ProtocolVersion(pDisp_), ProtocolRevision(pDisp_) );
2626 fprintf( stderr, "\tScreen (count,def)\t%d (%d,%d)\n",
2627 m_nDefaultScreen, ScreenCount(pDisp_), DefaultScreen(pDisp_) );
2628 fprintf( stderr, "\tshift ctrl alt \t%s (0x%X) %s (0x%X) %s (0x%X)\n",
2629 KeyStr( nShiftKeySym_ ), sal::static_int_cast< unsigned int >(nShiftKeySym_),
2630 KeyStr( nCtrlKeySym_ ), sal::static_int_cast< unsigned int >(nCtrlKeySym_),
2631 KeyStr( nMod1KeySym_ ), sal::static_int_cast< unsigned int >(nMod1KeySym_) );
2632 if( XExtendedMaxRequestSize(pDisp_) * 4 )
2633 fprintf( stderr, "\tXMaxRequestSize \t%ld %ld [bytes]\n",
2634 XMaxRequestSize(pDisp_) * 4, XExtendedMaxRequestSize(pDisp_) * 4 );
2635 if( GetProperties() != PROPERTY_DEFAULT )
2636 fprintf( stderr, "\tProperties \t0x%lX\n", GetProperties() );
2637 if( eWindowManager_ != otherwm )
2638 fprintf( stderr, "\tWindowmanager \t%d\n", eWindowManager_ );
2640 fprintf( stderr, "Screen\n" );
2641 fprintf( stderr, "\tResolution/Size \t%ld*%ld %ld*%ld %.1lf\"\n",
2642 aResolution_.A(), aResolution_.B(),
2643 m_aScreens[m_nDefaultScreen].m_aSize.Width(), m_aScreens[m_nDefaultScreen].m_aSize.Height(),
2644 Hypothenuse( DisplayWidthMM ( pDisp_, m_nDefaultScreen ),
2645 DisplayHeightMM( pDisp_, m_nDefaultScreen ) ) / 25.4 );
2646 fprintf( stderr, "\tBlack&White \t%lu %lu\n",
2647 GetColormap(m_nDefaultScreen).GetBlackPixel(), GetColormap(m_nDefaultScreen).GetWhitePixel() );
2648 fprintf( stderr, "\tRGB \t0x%lx 0x%lx 0x%lx\n",
2649 GetVisual(m_nDefaultScreen).red_mask, GetVisual(m_nDefaultScreen).green_mask, GetVisual(m_nDefaultScreen).blue_mask );
2650 fprintf( stderr, "\tVisual \t%d-bit %s ID=0x%x\n",
2651 GetVisual(m_nDefaultScreen).GetDepth(),
2652 VisualClassName[ GetVisual(m_nDefaultScreen).GetClass() ],
2653 sal::static_int_cast< unsigned int >(GetVisual(m_nDefaultScreen).GetVisualId()) );
2656 void SalDisplay::InitXinerama()
2658 if( m_aScreens.size() > 1 )
2660 m_bXinerama = false;
2661 return; // multiple screens mean no xinerama
2663 #ifdef USE_XINERAMA
2664 #if defined(USE_XINERAMA_XSUN)
2665 int nFramebuffers = 1;
2666 if( XineramaGetState( pDisp_, m_nDefaultScreen ) )
2668 XRectangle pFramebuffers[MAXFRAMEBUFFERS];
2669 unsigned char hints[MAXFRAMEBUFFERS];
2670 int result = XineramaGetInfo( pDisp_,
2671 m_nDefaultScreen,
2672 pFramebuffers,
2673 hints,
2674 &nFramebuffers );
2675 if( result > 0 && nFramebuffers > 1 )
2677 m_bXinerama = true;
2678 m_aXineramaScreens = std::vector<Rectangle>( nFramebuffers );
2679 for( int i = 0; i < nFramebuffers; i++ )
2680 m_aXineramaScreens[i] = Rectangle( Point( pFramebuffers[i].x,
2681 pFramebuffers[i].y ),
2682 Size( pFramebuffers[i].width,
2683 pFramebuffers[i].height ) );
2686 #elif defined(USE_XINERAMA_XORG)
2687 #if defined( X86 ) || defined( X86_64 )
2688 if( XineramaIsActive( pDisp_ ) )
2690 int nFramebuffers = 1;
2691 XineramaScreenInfo* pScreens = XineramaQueryScreens( pDisp_, &nFramebuffers );
2692 if( pScreens )
2694 if( nFramebuffers > 1 )
2696 m_aXineramaScreens = std::vector<Rectangle>();
2697 for( int i = 0; i < nFramebuffers; i++ )
2699 // see if any frame buffers are at the same coordinates
2700 // this can happen with weird configuration e.g. on
2701 // XFree86 and Clone displays
2702 bool bDuplicate = false;
2703 for( int n = 0; n < i; n++ )
2705 if( m_aXineramaScreens[n].Left() == pScreens[i].x_org &&
2706 m_aXineramaScreens[n].Top() == pScreens[i].y_org )
2708 bDuplicate = true;
2709 if( m_aXineramaScreens[n].GetWidth() < pScreens[i].width ||
2710 m_aXineramaScreens[n].GetHeight() < pScreens[i].height )
2712 m_aXineramaScreens[n].SetSize( Size( pScreens[i].width,
2713 pScreens[i].height ) );
2715 break;
2718 if( ! bDuplicate )
2719 m_aXineramaScreens.push_back( Rectangle( Point( pScreens[i].x_org,
2720 pScreens[i].y_org ),
2721 Size( pScreens[i].width,
2722 pScreens[i].height ) ) );
2724 m_bXinerama = m_aXineramaScreens.size() > 1;
2726 XFree( pScreens );
2729 #endif
2730 #endif
2731 #if OSL_DEBUG_LEVEL > 1
2732 if( m_bXinerama )
2734 for( std::vector< Rectangle >::const_iterator it = m_aXineramaScreens.begin(); it != m_aXineramaScreens.end(); ++it )
2735 fprintf( stderr, "Xinerama screen: %ldx%ld+%ld+%ld\n", it->GetWidth(), it->GetHeight(), it->Left(), it->Top() );
2737 #endif
2738 #endif // USE_XINERAMA
2741 void SalDisplay::registerFrame( SalFrame* pFrame )
2743 m_aFrames.push_front( pFrame );
2746 void SalDisplay::deregisterFrame( SalFrame* pFrame )
2748 if( osl_acquireMutex( hEventGuard_ ) )
2750 std::list< SalUserEvent >::iterator it = m_aUserEvents.begin();
2751 while ( it != m_aUserEvents.end() )
2753 if( it->m_pFrame == pFrame )
2754 it = m_aUserEvents.erase( it );
2755 else
2756 ++it;
2758 osl_releaseMutex( hEventGuard_ );
2760 else {
2761 DBG_ERROR( "SalDisplay::deregisterFrame !acquireMutex\n" );
2764 m_aFrames.remove( pFrame );
2768 extern "C"
2770 static Bool timestamp_predicate( Display*, XEvent* i_pEvent, XPointer i_pArg )
2772 SalDisplay* pSalDisplay = reinterpret_cast<SalDisplay*>(i_pArg);
2773 if( i_pEvent->type == PropertyNotify &&
2774 i_pEvent->xproperty.window == pSalDisplay->GetDrawable( pSalDisplay->GetDefaultScreenNumber() ) &&
2775 i_pEvent->xproperty.atom == pSalDisplay->getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT )
2777 return True;
2779 return False;
2783 XLIB_Time SalDisplay::GetLastUserEventTime( bool i_bAlwaysReget ) const
2785 if( m_nLastUserEventTime == CurrentTime || i_bAlwaysReget )
2787 // get current server time
2788 unsigned char c = 0;
2789 XEvent aEvent;
2790 Atom nAtom = getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT );
2791 XChangeProperty( GetDisplay(), GetDrawable( GetDefaultScreenNumber() ),
2792 nAtom, nAtom, 8, PropModeReplace, &c, 1 );
2793 XFlush( GetDisplay() );
2795 if( ! XIfEventWithTimeout( &aEvent, (XPointer)this, timestamp_predicate ) )
2797 // this should not happen at all; still sometimes it happens
2798 aEvent.xproperty.time = CurrentTime;
2801 m_nLastUserEventTime = aEvent.xproperty.time;
2803 return m_nLastUserEventTime;
2806 bool SalDisplay::XIfEventWithTimeout( XEvent* o_pEvent, XPointer i_pPredicateData,
2807 X_if_predicate i_pPredicate, long i_nTimeout ) const
2809 /* #i99360# ugly workaround an X11 library bug
2810 this replaces the following call:
2811 XIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData );
2813 bool bRet = true;
2815 if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) )
2817 // wait for some event to arrive
2818 struct pollfd aFD;
2819 aFD.fd = ConnectionNumber(GetDisplay());
2820 aFD.events = POLLIN;
2821 aFD.revents = 0;
2822 poll( &aFD, 1, i_nTimeout );
2823 if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) )
2825 poll( &aFD, 1, i_nTimeout ); // try once more for a packet of events from the Xserver
2826 if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) )
2828 bRet = false;
2832 return bRet;
2835 // -=-= SalVisual -=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2836 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2837 SalVisual::SalVisual()
2839 rtl_zeroMemory( this, sizeof( SalVisual ) );
2842 SalVisual::SalVisual( const XVisualInfo* pXVI )
2844 *(XVisualInfo*)this = *pXVI;
2845 if( GetClass() == TrueColor )
2847 nRedShift_ = sal_Shift( red_mask );
2848 nGreenShift_ = sal_Shift( green_mask );
2849 nBlueShift_ = sal_Shift( blue_mask );
2851 nRedBits_ = sal_significantBits( red_mask );
2852 nGreenBits_ = sal_significantBits( green_mask );
2853 nBlueBits_ = sal_significantBits( blue_mask );
2855 if( GetDepth() == 24 )
2856 if( red_mask == 0xFF0000 )
2857 if( green_mask == 0xFF00 )
2858 if( blue_mask == 0xFF )
2859 eRGBMode_ = RGB;
2860 else
2861 eRGBMode_ = other;
2862 else if( blue_mask == 0xFF00 )
2863 if( green_mask == 0xFF )
2864 eRGBMode_ = RBG;
2865 else
2866 eRGBMode_ = other;
2867 else
2868 eRGBMode_ = other;
2869 else if( green_mask == 0xFF0000 )
2870 if( red_mask == 0xFF00 )
2871 if( blue_mask == 0xFF )
2872 eRGBMode_ = GRB;
2873 else
2874 eRGBMode_ = other;
2875 else if( blue_mask == 0xFF00 )
2876 if( red_mask == 0xFF )
2877 eRGBMode_ = GBR;
2878 else
2879 eRGBMode_ = other;
2880 else
2881 eRGBMode_ = other;
2882 else if( blue_mask == 0xFF0000 )
2883 if( red_mask == 0xFF00 )
2884 if( green_mask == 0xFF )
2885 eRGBMode_ = BRG;
2886 else
2887 eRGBMode_ = other;
2888 else if( green_mask == 0xFF00 )
2889 if( red_mask == 0xFF )
2890 eRGBMode_ = BGR;
2891 else
2892 eRGBMode_ = other;
2893 else
2894 eRGBMode_ = other;
2895 else
2896 eRGBMode_ = other;
2897 else
2898 eRGBMode_ = other;
2902 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2903 SalVisual::~SalVisual()
2905 if( -1 == screen && VisualID(-1) == visualid ) delete visual;
2908 // Konvertiert die Reihenfolge der Bytes eines Pixel in Bytes eines SalColors
2909 // fuer die 6 XXXA ist das nicht reversibel
2910 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2911 // SalColor is RGB (ABGR) a=0xFF000000, r=0xFF0000, g=0xFF00, b=0xFF
2913 #define SALCOLOR RGB
2914 #define SALCOLORREVERSE BGR
2916 BOOL SalVisual::Convert( int &n0, int &n1, int &n2, int &n3 )
2918 int n;
2920 switch( GetMode() )
2922 case other:
2923 return FALSE;
2924 case SALCOLOR:
2925 break;
2926 case SALCOLORREVERSE:
2927 case RBG:
2928 case BRG:
2929 case GBR:
2930 case GRB:
2931 return Convert( n0, n1, n2 );
2932 case RGBA:
2933 n = n0;
2934 n0 = n1;
2935 n1 = n2;
2936 n2 = n3;
2937 n3 = n;
2938 break;
2939 case BGRA:
2940 case RBGA:
2941 case BRGA:
2942 case GBRA:
2943 case GRBA:
2944 default:
2945 fprintf( stderr, "SalVisual::Convert %d\n", GetMode() );
2946 abort();
2948 return TRUE;
2951 BOOL SalVisual::Convert( int &n0, int &n1, int &n2 )
2953 int n;
2955 switch( GetMode() )
2957 case other:
2958 return FALSE;
2959 case SALCOLOR:
2960 break;
2961 case RBG:
2962 n = n0;
2963 n0 = n1;
2964 n1 = n;
2965 break;
2966 case GRB:
2967 n = n1;
2968 n1 = n2;
2969 n2 = n;
2970 break;
2971 case SALCOLORREVERSE:
2972 n = n0;
2973 n0 = n2;
2974 n2 = n;
2975 break;
2976 case BRG:
2977 n = n0;
2978 n0 = n1;
2979 n1 = n2;
2980 n2 = n;
2981 break;
2982 case GBR:
2983 n = n2;
2984 n2 = n1;
2985 n1 = n0;
2986 n0 = n;
2987 break;
2988 default:
2989 fprintf( stderr, "SalVisual::Convert %d\n", GetMode() );
2990 abort();
2992 return TRUE;
2995 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2996 SalColor SalVisual::GetTCColor( Pixel nPixel ) const
2998 if( SALCOLOR == eRGBMode_ )
2999 return (SalColor)nPixel;
3001 if( SALCOLORREVERSE == eRGBMode_ )
3002 return MAKE_SALCOLOR( (nPixel & 0x0000FF),
3003 (nPixel & 0x00FF00) >> 8,
3004 (nPixel & 0xFF0000) >> 16);
3006 Pixel r = nPixel & red_mask;
3007 Pixel g = nPixel & green_mask;
3008 Pixel b = nPixel & blue_mask;
3010 if( other != eRGBMode_ ) // 8+8+8=24
3011 return MAKE_SALCOLOR( r >> nRedShift_,
3012 g >> nGreenShift_,
3013 b >> nBlueShift_ );
3015 if( nRedShift_ > 0 ) r >>= nRedShift_; else r <<= -nRedShift_;
3016 if( nGreenShift_ > 0 ) g >>= nGreenShift_; else g <<= -nGreenShift_;
3017 if( nBlueShift_ > 0 ) b >>= nBlueShift_; else b <<= -nBlueShift_;
3019 if( nRedBits_ != 8 )
3020 r |= (r & 0xff) >> (8-nRedBits_);
3021 if( nGreenBits_ != 8 )
3022 g |= (g & 0xff) >> (8-nGreenBits_);
3023 if( nBlueBits_ != 8 )
3024 b |= (b & 0xff) >> (8-nBlueBits_);
3026 return MAKE_SALCOLOR( r, g, b );
3029 Pixel SalVisual::GetTCPixel( SalColor nSalColor ) const
3031 if( SALCOLOR == eRGBMode_ )
3032 return (Pixel)nSalColor;
3034 Pixel r = (Pixel)SALCOLOR_RED( nSalColor );
3035 Pixel g = (Pixel)SALCOLOR_GREEN( nSalColor );
3036 Pixel b = (Pixel)SALCOLOR_BLUE( nSalColor );
3038 if( SALCOLORREVERSE == eRGBMode_ )
3039 return (b << 16) | (g << 8) | (r);
3041 if( other != eRGBMode_ ) // 8+8+8=24
3042 return (r << nRedShift_) | (g << nGreenShift_) | (b << nBlueShift_);
3044 if( nRedShift_ > 0 ) r <<= nRedShift_; else r >>= -nRedShift_;
3045 if( nGreenShift_ > 0 ) g <<= nGreenShift_; else g >>= -nGreenShift_;
3046 if( nBlueShift_ > 0 ) b <<= nBlueShift_; else b >>= -nBlueShift_;
3048 return (r&red_mask) | (g&green_mask) | (b&blue_mask);
3051 // -=-= SalColormap -=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
3052 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
3053 SalColormap::SalColormap( const SalDisplay *pDisplay, Colormap hColormap, int nScreen )
3054 : m_pDisplay( pDisplay ),
3055 m_hColormap( hColormap ),
3056 m_nScreen( nScreen )
3058 m_aVisual = m_pDisplay->GetVisual( m_nScreen );
3060 XColor aColor;
3062 GetXPixel( aColor, 0x00, 0x00, 0x00 );
3063 m_nBlackPixel = aColor.pixel;
3065 GetXPixel( aColor, 0xFF, 0xFF, 0xFF );
3066 m_nWhitePixel = aColor.pixel;
3068 m_nUsed = 1 << m_aVisual.GetDepth();
3070 if( m_aVisual.GetClass() == PseudoColor )
3072 int r, g, b;
3074 // black, white, gray, ~gray = 4
3075 GetXPixels( aColor, 0xC0, 0xC0, 0xC0 );
3077 // light colors: 3 * 2 = 6
3078 // GetXPixels( aColor, 0x00, 0x00, 0x00 );
3079 GetXPixels( aColor, 0x00, 0x00, 0xFF );
3080 GetXPixels( aColor, 0x00, 0xFF, 0x00 );
3081 GetXPixels( aColor, 0x00, 0xFF, 0xFF );
3082 // GetXPixels( aColor, 0xFF, 0x00, 0x00 );
3083 // GetXPixels( aColor, 0xFF, 0x00, 0xFF );
3084 // GetXPixels( aColor, 0xFF, 0xFF, 0x00 );
3085 // GetXPixels( aColor, 0xFF, 0xFF, 0xFF );
3087 // standard colors: 7 * 2 = 14
3088 // GetXPixels( aColor, 0x00, 0x00, 0x00 );
3089 GetXPixels( aColor, 0x00, 0x00, 0x80 );
3090 GetXPixels( aColor, 0x00, 0x80, 0x00 );
3091 GetXPixels( aColor, 0x00, 0x80, 0x80 );
3092 GetXPixels( aColor, 0x80, 0x00, 0x00 );
3093 GetXPixels( aColor, 0x80, 0x00, 0x80 );
3094 GetXPixels( aColor, 0x80, 0x80, 0x00 );
3095 GetXPixels( aColor, 0x80, 0x80, 0x80 );
3096 GetXPixels( aColor, 0x00, 0xB8, 0xFF ); // Blau 7
3098 // cube: 6*6*6 - 8 = 208
3099 for( r = 0; r < 0x100; r += 0x33 ) // 0x33, 0x66, 0x99, 0xCC, 0xFF
3100 for( g = 0; g < 0x100; g += 0x33 )
3101 for( b = 0; b < 0x100; b += 0x33 )
3102 GetXPixels( aColor, r, g, b );
3104 // gray: 16 - 6 = 10
3105 for( g = 0x11; g < 0xFF; g += 0x11 )
3106 GetXPixels( aColor, g, g, g );
3108 // green: 16 - 6 = 10
3109 for( g = 0x11; g < 0xFF; g += 0x11 )
3110 GetXPixels( aColor, 0, g, 0 );
3112 // red: 16 - 6 = 10
3113 for( r = 0x11; r < 0xFF; r += 0x11 )
3114 GetXPixels( aColor, r, 0, 0 );
3116 // blue: 16 - 6 = 10
3117 for( b = 0x11; b < 0xFF; b += 0x11 )
3118 GetXPixels( aColor, 0, 0, b );
3122 // PseudoColor
3123 SalColormap::SalColormap( const BitmapPalette &rPalette )
3124 : m_pDisplay( GetX11SalData()->GetDisplay() ),
3125 m_hColormap( None ),
3126 m_nWhitePixel( SALCOLOR_NONE ),
3127 m_nBlackPixel( SALCOLOR_NONE ),
3128 m_nUsed( rPalette.GetEntryCount() ),
3129 m_nScreen( GetX11SalData()->GetDisplay()->GetDefaultScreenNumber() )
3131 m_aPalette = std::vector<SalColor>(m_nUsed);
3133 for( unsigned int i = 0; i < m_nUsed; i++ )
3135 const BitmapColor &rColor = rPalette[i];
3136 m_aPalette[i] = MAKE_SALCOLOR( rColor.GetRed(),
3137 rColor.GetGreen(),
3138 rColor.GetBlue() );
3139 if( (m_nBlackPixel == SALCOLOR_NONE) && (SALCOLOR_BLACK == m_aPalette[i]) )
3140 m_nBlackPixel = i;
3141 else if( (m_nWhitePixel == SALCOLOR_NONE) && (SALCOLOR_WHITE == m_aPalette[i]) )
3142 m_nWhitePixel = i;
3146 // MonoChrome
3147 SalColormap::SalColormap()
3148 : m_pDisplay( GetX11SalData()->GetDisplay() ),
3149 m_hColormap( None ),
3150 m_nWhitePixel( 1 ),
3151 m_nBlackPixel( 0 ),
3152 m_nUsed( 2 ),
3153 m_nScreen( 0 )
3155 if( m_pDisplay )
3156 m_nScreen = m_pDisplay->GetDefaultScreenNumber();
3157 m_aPalette = std::vector<SalColor>(m_nUsed);
3159 m_aPalette[m_nBlackPixel] = SALCOLOR_BLACK;
3160 m_aPalette[m_nWhitePixel] = SALCOLOR_WHITE;
3163 // TrueColor
3164 SalColormap::SalColormap( USHORT nDepth )
3165 : m_pDisplay( GetX11SalData()->GetDisplay() ),
3166 m_hColormap( None ),
3167 m_nWhitePixel( (1 << nDepth) - 1 ),
3168 m_nBlackPixel( 0x00000000 ),
3169 m_nUsed( 1 << nDepth ),
3170 m_nScreen( GetX11SalData()->GetDisplay()->GetDefaultScreenNumber() )
3172 const SalVisual *pVisual = &m_pDisplay->GetVisual( m_nScreen );
3174 if( pVisual->GetClass() == TrueColor && pVisual->GetDepth() == nDepth )
3175 m_aVisual = *pVisual;
3176 else
3178 XVisualInfo aVI;
3180 if( !XMatchVisualInfo( m_pDisplay->GetDisplay(),
3181 m_pDisplay->GetDefaultScreenNumber(),
3182 nDepth,
3183 TrueColor,
3184 &aVI ) )
3186 aVI.visual = new Visual();
3187 aVI.visualid = (VisualID)0; // beware of temporary destructor below
3188 aVI.screen = 0;
3189 aVI.depth = nDepth;
3190 aVI.c_class = TrueColor;
3191 if( 24 == nDepth ) // 888
3193 aVI.red_mask = 0xFF0000;
3194 aVI.green_mask = 0x00FF00;
3195 aVI.blue_mask = 0x0000FF;
3197 else if( 16 == nDepth ) // 565
3199 aVI.red_mask = 0x00F800;
3200 aVI.green_mask = 0x0007E0;
3201 aVI.blue_mask = 0x00001F;
3203 else if( 15 == nDepth ) // 555
3205 aVI.red_mask = 0x007C00;
3206 aVI.green_mask = 0x0003E0;
3207 aVI.blue_mask = 0x00001F;
3209 else if( 12 == nDepth ) // 444
3211 aVI.red_mask = 0x000F00;
3212 aVI.green_mask = 0x0000F0;
3213 aVI.blue_mask = 0x00000F;
3215 else if( 8 == nDepth ) // 332
3217 aVI.red_mask = 0x0000E0;
3218 aVI.green_mask = 0x00001C;
3219 aVI.blue_mask = 0x000003;
3221 else
3223 aVI.red_mask = 0x000000;
3224 aVI.green_mask = 0x000000;
3225 aVI.blue_mask = 0x000000;
3227 aVI.colormap_size = 0;
3228 aVI.bits_per_rgb = 8;
3230 aVI.visual->ext_data = NULL;
3231 aVI.visual->visualid = aVI.visualid;
3232 aVI.visual->c_class = aVI.c_class;
3233 aVI.visual->red_mask = aVI.red_mask;
3234 aVI.visual->green_mask = aVI.green_mask;
3235 aVI.visual->blue_mask = aVI.blue_mask;
3236 aVI.visual->bits_per_rgb = aVI.bits_per_rgb;
3237 aVI.visual->map_entries = aVI.colormap_size;
3239 m_aVisual = SalVisual( &aVI );
3240 // give ownership of constructed Visual() to m_aVisual
3241 // see SalVisual destructor
3242 m_aVisual.visualid = (VisualID)-1;
3243 m_aVisual.screen = -1;
3245 else
3246 m_aVisual = SalVisual( &aVI );
3250 SalColormap::~SalColormap()
3252 #ifdef DBG_UTIL
3253 m_hColormap = (Colormap)ILLEGAL_POINTER;
3254 m_pDisplay = (SalDisplay*)ILLEGAL_POINTER;
3255 #endif
3258 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
3259 void SalColormap::SetPalette( const BitmapPalette &rPalette )
3261 if( this != &GetX11SalData()->GetDisplay()->GetColormap(m_nScreen) )
3263 m_nBlackPixel = SALCOLOR_NONE;
3264 m_nWhitePixel = SALCOLOR_NONE;
3267 if( rPalette.GetEntryCount() > m_nUsed )
3269 m_nBlackPixel = SALCOLOR_NONE;
3270 m_nWhitePixel = SALCOLOR_NONE;
3271 m_nUsed = rPalette.GetEntryCount();
3272 m_aPalette = std::vector<SalColor>(m_nUsed);
3275 for( int i = 0; i < rPalette.GetEntryCount(); i++ )
3277 const BitmapColor &rColor = rPalette[i];
3278 m_aPalette[i] = MAKE_SALCOLOR( rColor.GetRed(),
3279 rColor.GetGreen(),
3280 rColor.GetBlue() );
3281 if( (m_nBlackPixel == SALCOLOR_NONE) && (SALCOLOR_BLACK == m_aPalette[i]) )
3282 m_nBlackPixel = i;
3283 else if( (m_nWhitePixel == SALCOLOR_NONE) && (SALCOLOR_WHITE == m_aPalette[i]) )
3284 m_nWhitePixel = i;
3288 void SalColormap::GetPalette()
3290 Pixel i;
3291 m_aPalette = std::vector<SalColor>(m_nUsed);
3293 XColor *aColor = new XColor[m_nUsed];
3295 for( i = 0; i < m_nUsed; i++ )
3297 aColor[i].red = aColor[i].green = aColor[i].blue = 0;
3298 aColor[i].pixel = i;
3301 XQueryColors( m_pDisplay->GetDisplay(), m_hColormap, aColor, m_nUsed );
3303 for( i = 0; i < m_nUsed; i++ )
3305 m_aPalette[i] = MAKE_SALCOLOR( aColor[i].red >> 8,
3306 aColor[i].green >> 8,
3307 aColor[i].blue >> 8 );
3310 delete [] aColor;
3313 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
3314 static USHORT sal_Lookup( const std::vector<SalColor>& rPalette,
3315 int r, int g, int b,
3316 Pixel nUsed )
3318 USHORT nPixel = 0;
3319 int nBest = ColorDiff( rPalette[0], r, g, b );
3321 for( USHORT i = 1; i < nUsed; i++ )
3323 int n = ColorDiff( rPalette[i], r, g, b );
3325 if( n < nBest )
3327 if( !n )
3328 return i;
3330 nPixel = i;
3331 nBest = n;
3334 return nPixel;
3337 void SalColormap::GetLookupTable()
3339 m_aLookupTable = std::vector<USHORT>(16*16*16);
3341 int i = 0;
3342 for( int r = 0; r < 256; r += 17 )
3343 for( int g = 0; g < 256; g += 17 )
3344 for( int b = 0; b < 256; b += 17 )
3345 m_aLookupTable[i++] = sal_Lookup( m_aPalette, r, g, b, m_nUsed );
3348 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
3349 SalColor SalColormap::GetColor( Pixel nPixel ) const
3351 if( m_nBlackPixel == nPixel ) return SALCOLOR_BLACK;
3352 if( m_nWhitePixel == nPixel ) return SALCOLOR_WHITE;
3354 if( m_aVisual.GetVisual() )
3356 if( m_aVisual.GetClass() == TrueColor )
3357 return m_aVisual.GetTCColor( nPixel );
3359 if( m_aPalette.empty()
3360 && m_hColormap
3361 #ifdef PSEUDOCOLOR12
3362 && m_aVisual.GetDepth() <= 12
3363 #else
3364 && m_aVisual.GetDepth() <= 8
3365 #endif
3366 && m_aVisual.GetClass() == PseudoColor )
3367 ((SalColormap*)this)->GetPalette();
3370 if( !m_aPalette.empty() && nPixel < m_nUsed )
3371 return m_aPalette[nPixel];
3373 if( m_hColormap )
3375 DBG_ASSERT( 1, "SalColormap::GetColor() !hColormap_\n" );
3376 return nPixel;
3379 // DirectColor, StaticColor, StaticGray, GrayScale
3380 XColor aColor;
3382 aColor.pixel = nPixel;
3384 XQueryColor( m_pDisplay->GetDisplay(), m_hColormap, &aColor );
3386 return MAKE_SALCOLOR( aColor.red>>8, aColor.green>>8, aColor.blue>>8 );
3389 inline BOOL SalColormap::GetXPixel( XColor &rColor,
3390 int r,
3391 int g,
3392 int b ) const
3394 rColor.red = r * 257;
3395 rColor.green = g * 257;
3396 rColor.blue = b * 257;
3397 return XAllocColor( GetXDisplay(), m_hColormap, &rColor );
3400 BOOL SalColormap::GetXPixels( XColor &rColor,
3401 int r,
3402 int g,
3403 int b ) const
3405 if( !GetXPixel( rColor, r, g, b ) )
3406 return FALSE;
3407 if( rColor.pixel & 1 )
3408 return TRUE;
3409 return GetXPixel( rColor, r^0xFF, g^0xFF, b^0xFF );
3412 Pixel SalColormap::GetPixel( SalColor nSalColor ) const
3414 if( SALCOLOR_NONE == nSalColor ) return 0;
3415 if( SALCOLOR_BLACK == nSalColor ) return m_nBlackPixel;
3416 if( SALCOLOR_WHITE == nSalColor ) return m_nWhitePixel;
3418 if( m_aVisual.GetClass() == TrueColor )
3419 return m_aVisual.GetTCPixel( nSalColor );
3421 if( m_aLookupTable.empty() )
3423 if( m_aPalette.empty()
3424 && m_hColormap
3425 #ifdef PSEUDOCOLOR12
3426 && m_aVisual.GetDepth() <= 12
3427 #else
3428 && m_aVisual.GetDepth() <= 8
3429 #endif
3430 && m_aVisual.GetClass() == PseudoColor ) // what else ???
3431 ((SalColormap*)this)->GetPalette();
3433 if( !m_aPalette.empty() )
3434 for( Pixel i = 0; i < m_nUsed; i++ )
3435 if( m_aPalette[i] == nSalColor )
3436 return i;
3438 if( m_hColormap )
3440 // DirectColor, StaticColor, StaticGray, GrayScale (PseudoColor)
3441 XColor aColor;
3443 if( GetXPixel( aColor,
3444 SALCOLOR_RED ( nSalColor ),
3445 SALCOLOR_GREEN( nSalColor ),
3446 SALCOLOR_BLUE ( nSalColor ) ) )
3448 if( !m_aPalette.empty() && !m_aPalette[aColor.pixel] )
3450 const_cast<SalColormap*>(this)->m_aPalette[aColor.pixel] = nSalColor;
3452 if( !(aColor.pixel & 1) && !m_aPalette[aColor.pixel+1] )
3454 XColor aInversColor;
3456 SalColor nInversColor = nSalColor ^ 0xFFFFFF;
3458 GetXPixel( aInversColor,
3459 SALCOLOR_RED ( nInversColor ),
3460 SALCOLOR_GREEN( nInversColor ),
3461 SALCOLOR_BLUE ( nInversColor ) );
3463 if( !m_aPalette[aInversColor.pixel] )
3464 const_cast<SalColormap*>(this)->m_aPalette[aInversColor.pixel] = nInversColor;
3465 #ifdef DBG_UTIL
3466 else
3467 fprintf( stderr, "SalColormap::GetPixel() 0x%06lx=%lu 0x%06lx=%lu\n",
3468 static_cast< unsigned long >(nSalColor), aColor.pixel,
3469 static_cast< unsigned long >(nInversColor), aInversColor.pixel);
3470 #endif
3474 return aColor.pixel;
3477 #ifdef DBG_UTIL
3478 fprintf( stderr, "SalColormap::GetPixel() !XAllocColor %lx\n",
3479 static_cast< unsigned long >(nSalColor) );
3480 #endif
3483 if( m_aPalette.empty() )
3485 #ifdef DBG_UTIL
3486 fprintf( stderr, "SalColormap::GetPixel() Palette empty %lx\n",
3487 static_cast< unsigned long >(nSalColor));
3488 #endif
3489 return nSalColor;
3492 ((SalColormap*)this)->GetLookupTable();
3495 // Colormatching ueber Palette
3496 USHORT r = SALCOLOR_RED ( nSalColor );
3497 USHORT g = SALCOLOR_GREEN( nSalColor );
3498 USHORT b = SALCOLOR_BLUE ( nSalColor );
3499 return m_aLookupTable[ (((r+8)/17) << 8)
3500 + (((g+8)/17) << 4)
3501 + ((b+8)/17) ];