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