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