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