xref: /AOO42X/main/vcl/unx/generic/app/saldisp.cxx (revision ab96cd939cde1a19e747a32211616bb0c8a81d0b)
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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Null(const char * p)165 inline const char *Null( const char *p ) { return p ? p : ""; }
GetEnv(const char * p)166 inline const char *GetEnv( const char *p ) { return Null( getenv( p ) ); }
KeyStr(KeySym n)167 inline const char *KeyStr( KeySym n ) { return Null( XKeysymToString( n ) ); }
168 
GetAtomName(Display * d,Atom a)169 inline const char *GetAtomName( Display *d, Atom a )
170 { return Null( XGetAtomName( d, a ) ); }
171 
Hypothenuse(long w,long h)172 inline double Hypothenuse( long w, long h )
173 { return sqrt( (double)((w*w)+(h*h)) ); }
174 
ColorDiff(int r,int g,int b)175 inline int ColorDiff( int r, int g, int b )
176 { return (r*r)+(g*g)+(b*b); }
177 
ColorDiff(SalColor c1,int r,int g,int b)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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sal_Shift(Pixel nMask)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 
sal_significantBits(Pixel nMask)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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sal_GetVisualInfo(Display * pDisplay,XID nVID,XVisualInfo & rVI)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
sal_IsDisplayNumber(const char * pDisplayString)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
sal_EqualHosts(const OUString & Host1,const OUString & Host2)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
sal_IsLocalDisplay(Display * pDisplay)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 
IsLocal()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
sal_GetServerVendor(Display * p_display)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 
sal_IsTrustedSolaris(Display * p_display)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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
BestVisual(Display * pDisplay,int nScreen,XVisualInfo & rVI)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 
SalDisplay(Display * display)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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
~SalDisplay()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 
doDestruct()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 
DisplayHasEvent(int fd,SalX11Display * pDisplay)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 }
DisplayQueue(int fd,SalX11Display * pDisplay)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 }
DisplayYield(int fd,SalX11Display * pDisplay)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 
SalX11Display(Display * display)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 
~SalX11Display()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 
initScreen(int nScreen) const663 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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Init()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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Beep() const1018 void SalDisplay::Beep() const
1019 {
1020     XBell( pDisp_, 0 );
1021 }
1022 
1023 // Keyboard
1024 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
GetKeyNameFromKeySym(KeySym nKeySym) const1025 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 
sal_XModifier2Keysym(Display * pDisplay,XModifierKeymap * pXModMap,int n)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 
ModifierMapping()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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
GetKeyName(sal_uInt16 nKeyCode) const1093 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 
GetKeyCode(KeySym keysym,char * pcPrintable) const1276 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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
GetKeySym(XKeyEvent * pEvent,unsigned char * pPrintable,int * pLen,KeySym * pUnmodifiedKeySym,Status * pStatusReturn,XIC aInputContext) const1660 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 
GetPointer(int ePointerStyle)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_AUTOSCROLL_N:
2013             MAKE_CURSOR(asn_ );
2014             break;
2015         case POINTER_AUTOSCROLL_S:
2016             MAKE_CURSOR( ass_ );
2017             break;
2018         case POINTER_AUTOSCROLL_W:
2019             MAKE_CURSOR( asw_ );
2020             break;
2021         case POINTER_AUTOSCROLL_E:
2022             MAKE_CURSOR( ase_ );
2023             break;
2024         case POINTER_AUTOSCROLL_NW:
2025             MAKE_CURSOR( asnw_ );
2026             break;
2027         case POINTER_AUTOSCROLL_NE:
2028             MAKE_CURSOR( asne_ );
2029             break;
2030         case POINTER_AUTOSCROLL_SW:
2031             MAKE_CURSOR( assw_ );
2032             break;
2033         case POINTER_AUTOSCROLL_SE:
2034             MAKE_CURSOR( asse_ );
2035             break;
2036         case POINTER_AUTOSCROLL_NS:
2037             MAKE_CURSOR( asns_ );
2038             break;
2039         case POINTER_AUTOSCROLL_WE:
2040             MAKE_CURSOR( aswe_ );
2041             break;
2042         case POINTER_AUTOSCROLL_NSWE:
2043             MAKE_CURSOR( asnswe_ );
2044             break;
2045         case POINTER_AIRBRUSH:
2046             MAKE_CURSOR( airbrush_ );
2047             break;
2048         case POINTER_TEXT_VERTICAL:
2049             MAKE_CURSOR( vertcurs_ );
2050             break;
2051 
2052         // --> FME 2004-07-30 #i32329# Enhanced table selection
2053         case POINTER_TAB_SELECT_S:
2054             MAKE_CURSOR( tblsels_ );
2055             break;
2056         case POINTER_TAB_SELECT_E:
2057             MAKE_CURSOR( tblsele_ );
2058             break;
2059         case POINTER_TAB_SELECT_SE:
2060             MAKE_CURSOR( tblselse_ );
2061             break;
2062         case POINTER_TAB_SELECT_W:
2063             MAKE_CURSOR( tblselw_ );
2064             break;
2065         case POINTER_TAB_SELECT_SW:
2066             MAKE_CURSOR( tblselsw_ );
2067             break;
2068         // <--
2069 
2070         // --> FME 2004-08-16 #i20119# Paintbrush tool
2071         case POINTER_PAINTBRUSH :
2072             MAKE_CURSOR( paintbrush_ );
2073             break;
2074         // <--
2075 
2076         default:
2077             DBG_ERROR("pointer not implemented");
2078             aCur = XCreateFontCursor( pDisp_, XC_arrow );
2079             break;
2080     }
2081 
2082     if( None == aCur )
2083     {
2084         XColor      aBlack, aWhite, aDummy;
2085         Colormap    hColormap = GetColormap(m_nDefaultScreen).GetXColormap();
2086 
2087         XAllocNamedColor( pDisp_, hColormap, "black", &aBlack, &aDummy );
2088         XAllocNamedColor( pDisp_, hColormap, "white", &aWhite, &aDummy );
2089 
2090         aCur = XCreatePixmapCursor( pDisp_,
2091                                     aCursBitmap, aMaskBitmap,
2092                                     &aBlack, &aWhite,
2093                                     nXHot, nYHot );
2094 
2095         XFreePixmap( pDisp_, aCursBitmap );
2096         XFreePixmap( pDisp_, aMaskBitmap );
2097     }
2098 
2099     return aCur;
2100 }
2101 
CaptureMouse(SalFrame * pCapture)2102 int SalDisplay::CaptureMouse( SalFrame *pCapture )
2103 {
2104     if( !pCapture )
2105     {
2106         m_pCapture = NULL;
2107         XUngrabPointer( GetDisplay(), CurrentTime );
2108         XFlush( GetDisplay() );
2109         return 0;
2110     }
2111 
2112     m_pCapture = NULL;
2113 
2114     // FIXME: get rid of X11SalFrame
2115     const SystemEnvData* pEnvData = pCapture->GetSystemData();
2116     int ret = XGrabPointer( GetDisplay(),
2117                             (XLIB_Window)pEnvData->aWindow,
2118                             False,
2119                             PointerMotionMask| ButtonPressMask|ButtonReleaseMask,
2120                             GrabModeAsync,
2121                             GrabModeAsync,
2122                             None,
2123                             static_cast<X11SalFrame*>(pCapture)->GetCursor(),
2124                             CurrentTime );
2125 
2126     if( ret != GrabSuccess )
2127     {
2128         DBG_ASSERT( 1, "SalDisplay::CaptureMouse could not grab pointer\n");
2129         return -1;
2130     }
2131 
2132     m_pCapture = pCapture;
2133     return 1;
2134 }
2135 
2136 // Events
2137 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2138 
SendInternalEvent(SalFrame * pFrame,void * pData,sal_uInt16 nEvent)2139 void SalDisplay::SendInternalEvent( SalFrame* pFrame, void* pData, sal_uInt16 nEvent )
2140 {
2141     if( osl_acquireMutex( hEventGuard_ ) )
2142     {
2143         m_aUserEvents.push_back( SalUserEvent( pFrame, pData, nEvent ) );
2144 
2145         // Notify SalXLib::Yield() of a pending event.
2146         pXLib_->PostUserEvent();
2147 
2148         osl_releaseMutex( hEventGuard_ );
2149     }
2150     else {
2151         DBG_ASSERT( 1, "SalDisplay::SendInternalEvent !acquireMutex\n" );
2152     }
2153 }
2154 
CancelInternalEvent(SalFrame * pFrame,void * pData,sal_uInt16 nEvent)2155 void SalDisplay::CancelInternalEvent( SalFrame* pFrame, void* pData, sal_uInt16 nEvent )
2156 {
2157     if( osl_acquireMutex( hEventGuard_ ) )
2158     {
2159         if( ! m_aUserEvents.empty() )
2160         {
2161             std::list< SalUserEvent >::iterator it, next;
2162             next = m_aUserEvents.begin();
2163             do
2164             {
2165                 it = next++;
2166                 if( it->m_pFrame    == pFrame   &&
2167                     it->m_pData     == pData    &&
2168                     it->m_nEvent    == nEvent )
2169                 {
2170                     m_aUserEvents.erase( it );
2171                 }
2172             } while( next != m_aUserEvents.end() );
2173         }
2174 
2175         osl_releaseMutex( hEventGuard_ );
2176     }
2177     else {
2178         DBG_ASSERT( 1, "SalDisplay::CancelInternalEvent !acquireMutex\n" );
2179     }
2180 }
2181 
IsEvent()2182 sal_Bool SalX11Display::IsEvent()
2183 {
2184     sal_Bool bRet = sal_False;
2185 
2186     if( osl_acquireMutex( hEventGuard_ ) )
2187     {
2188         if( m_aUserEvents.begin() != m_aUserEvents.end() )
2189             bRet = sal_True;
2190         osl_releaseMutex( hEventGuard_ );
2191     }
2192 
2193     if( bRet || XEventsQueued( pDisp_, QueuedAlready ) )
2194         return sal_True;
2195 
2196     XFlush( pDisp_ );
2197     return sal_False;
2198 }
2199 
DispatchInternalEvent()2200 bool SalDisplay::DispatchInternalEvent()
2201 {
2202     SalFrame* pFrame = NULL;
2203     void* pData = NULL;
2204     sal_uInt16 nEvent = 0;
2205 
2206     if( osl_acquireMutex( hEventGuard_ ) )
2207     {
2208         if( m_aUserEvents.begin() != m_aUserEvents.end() )
2209         {
2210             pFrame  = m_aUserEvents.front().m_pFrame;
2211             pData   = m_aUserEvents.front().m_pData;
2212             nEvent  = m_aUserEvents.front().m_nEvent;
2213 
2214             m_aUserEvents.pop_front();
2215         }
2216         osl_releaseMutex( hEventGuard_ );
2217     }
2218     else {
2219         DBG_ASSERT( 1, "SalDisplay::Yield !acquireMutex\n" );
2220     }
2221 
2222     if( pFrame )
2223         pFrame->CallCallback( nEvent, pData );
2224 
2225     return pFrame != NULL;
2226 }
2227 
2228 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2229 
Yield()2230 void SalX11Display::Yield()
2231 {
2232     if( DispatchInternalEvent() )
2233         return;
2234 
2235     XEvent aEvent;
2236     DBG_ASSERT( static_cast<SalYieldMutex*>(GetSalData()->m_pInstance->GetYieldMutex())->GetThreadId() ==
2237                 vos::OThread::getCurrentIdentifier(),
2238                 "will crash soon since solar mutex not locked in SalDisplay::Yield" );
2239 
2240     XNextEvent( pDisp_, &aEvent );
2241 
2242     Dispatch( &aEvent );
2243 
2244 #ifdef DBG_UTIL
2245     if( pXLib_->HasXErrorOccured() )
2246     {
2247         XFlush( pDisp_ );
2248         PrintEvent( "SalDisplay::Yield (WasXError)", &aEvent );
2249     }
2250 #endif
2251     pXLib_->ResetXErrorOccured();
2252 }
2253 
Dispatch(XEvent * pEvent)2254 long SalX11Display::Dispatch( XEvent *pEvent )
2255 {
2256     if( pEvent->type == XLIB_KeyPress || pEvent->type == KeyRelease )
2257     {
2258         XLIB_Window aWindow = pEvent->xkey.window;
2259 
2260         std::list< SalFrame* >::const_iterator it;
2261         for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it )
2262         {
2263             const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it);
2264             if( pFrame->GetWindow() == aWindow || pFrame->GetShellWindow() == aWindow )
2265             {
2266                 aWindow = pFrame->GetWindow();
2267                 break;
2268             }
2269         }
2270         if( it != m_aFrames.end() )
2271         {
2272             if ( mpInputMethod->FilterEvent( pEvent , aWindow ) )
2273                 return 0;
2274         }
2275     }
2276     else
2277         if ( mpInputMethod->FilterEvent( pEvent, None ) )
2278             return 0;
2279 
2280     SalInstance* pInstance = GetSalData()->m_pInstance;
2281     pInstance->CallEventCallback( pEvent, sizeof( XEvent ) );
2282 
2283     switch( pEvent->type )
2284     {
2285         case MotionNotify:
2286             while( XCheckWindowEvent( pEvent->xany.display,
2287                                       pEvent->xany.window,
2288                                       ButtonMotionMask,
2289                                       pEvent ) )
2290                 ;
2291             m_nLastUserEventTime = pEvent->xmotion.time;
2292             break;
2293         case PropertyNotify:
2294             if( pEvent->xproperty.atom == getWMAdaptor()->getAtom( WMAdaptor::VCL_SYSTEM_SETTINGS ) )
2295             {
2296                 for( unsigned int i = 0; i < m_aScreens.size(); i++ )
2297                 {
2298                     if( pEvent->xproperty.window == m_aScreens[i].m_aRefWindow )
2299                     {
2300                         std::list< SalFrame* >::const_iterator it;
2301                         for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it )
2302                             (*it)->CallCallback( SALEVENT_SETTINGSCHANGED, NULL );
2303                         return 0;
2304                     }
2305                 }
2306             }
2307             break;
2308         case MappingNotify:
2309             if( MappingKeyboard == pEvent->xmapping.request ||
2310                 MappingModifier == pEvent->xmapping.request )
2311             {
2312                 XRefreshKeyboardMapping( &pEvent->xmapping );
2313                 if( MappingModifier == pEvent->xmapping.request )
2314                     ModifierMapping();
2315                 if( MappingKeyboard == pEvent->xmapping.request ) // refresh mapping
2316                     GetKeyboardName( sal_True );
2317             }
2318             break;
2319         case ButtonPress:
2320         case ButtonRelease:
2321             m_nLastUserEventTime = pEvent->xbutton.time;
2322             break;
2323         case XLIB_KeyPress:
2324         case KeyRelease:
2325             m_nLastUserEventTime = pEvent->xkey.time;
2326             break;
2327         default:
2328 
2329             if (   GetKbdExtension()->UseExtension()
2330                 && GetKbdExtension()->GetEventBase() == pEvent->type )
2331             {
2332                 GetKbdExtension()->Dispatch( pEvent );
2333                 return 1;
2334             }
2335             break;
2336     }
2337 
2338     std::list< SalFrame* >::iterator it;
2339     for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it )
2340     {
2341         X11SalFrame* pFrame = static_cast< X11SalFrame* >(*it);
2342         XLIB_Window aDispatchWindow = pEvent->xany.window;
2343         if( pFrame->GetWindow() == aDispatchWindow
2344             || pFrame->GetShellWindow() == aDispatchWindow
2345             || pFrame->GetForeignParent() == aDispatchWindow
2346             )
2347         {
2348             return pFrame->Dispatch( pEvent );
2349         }
2350         if( pEvent->type == ConfigureNotify && pEvent->xconfigure.window == pFrame->GetStackingWindow() )
2351         {
2352             return pFrame->Dispatch( pEvent );
2353         }
2354     }
2355 
2356     // dispatch to salobjects
2357     X11SalObject::Dispatch( pEvent );
2358 
2359     // is this perhaps a root window that changed size ?
2360     processRandREvent( pEvent );
2361 
2362     return 0;
2363 }
2364 
2365 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
PrintEvent(const ByteString & rComment,XEvent * pEvent) const2366 void SalDisplay::PrintEvent( const ByteString &rComment,
2367                                    XEvent       *pEvent ) const
2368 {
2369     if( pEvent->type <= MappingNotify )
2370     {
2371         fprintf( stderr, "[%s] %s s=%d w=%ld\n",
2372                  rComment.GetBuffer(),
2373                  EventNames[pEvent->type],
2374                  pEvent->xany.send_event,
2375                  pEvent->xany.window );
2376 
2377         switch( pEvent->type )
2378         {
2379             case XLIB_KeyPress:
2380             case KeyRelease:
2381                 fprintf( stderr, "\t\ts=%d c=%d\n",
2382                          pEvent->xkey.state,
2383                          pEvent->xkey.keycode );
2384                 break;
2385 
2386             case ButtonPress:
2387             case ButtonRelease:
2388                 fprintf( stderr, "\t\ts=%d b=%d x=%d y=%d rx=%d ry=%d\n",
2389                          pEvent->xbutton.state,
2390                          pEvent->xbutton.button,
2391                          pEvent->xbutton.x,
2392                          pEvent->xbutton.y,
2393                          pEvent->xbutton.x_root,
2394                          pEvent->xbutton.y_root );
2395                 break;
2396 
2397             case MotionNotify:
2398                 fprintf( stderr, "\t\ts=%d x=%d y=%d\n",
2399                          pEvent->xmotion.state,
2400                          pEvent->xmotion.x,
2401                          pEvent->xmotion.y );
2402                 break;
2403 
2404             case EnterNotify:
2405             case LeaveNotify:
2406                 fprintf( stderr, "\t\tm=%d f=%d x=%d y=%d\n",
2407                          pEvent->xcrossing.mode,
2408                          pEvent->xcrossing.focus,
2409                          pEvent->xcrossing.x,
2410                          pEvent->xcrossing.y );
2411                 break;
2412 
2413             case FocusIn:
2414             case FocusOut:
2415                 fprintf( stderr, "\t\tm=%d d=%d\n",
2416                          pEvent->xfocus.mode,
2417                          pEvent->xfocus.detail );
2418                 break;
2419 
2420             case Expose:
2421             case GraphicsExpose:
2422                 fprintf( stderr, "\t\tc=%d %d*%d %d+%d\n",
2423                          pEvent->xexpose.count,
2424                          pEvent->xexpose.width,
2425                          pEvent->xexpose.height,
2426                          pEvent->xexpose.x,
2427                          pEvent->xexpose.y );
2428                 break;
2429 
2430             case VisibilityNotify:
2431                 fprintf( stderr, "\t\ts=%d\n",
2432                          pEvent->xvisibility.state );
2433                 break;
2434 
2435             case CreateNotify:
2436             case DestroyNotify:
2437                 break;
2438 
2439             case MapNotify:
2440             case UnmapNotify:
2441                 break;
2442 
2443             case ReparentNotify:
2444                 fprintf( stderr, "\t\tp=%d x=%d y=%d\n",
2445                          sal::static_int_cast< int >(pEvent->xreparent.parent),
2446                          pEvent->xreparent.x,
2447                          pEvent->xreparent.y );
2448                 break;
2449 
2450             case ConfigureNotify:
2451                 fprintf( stderr, "\t\tb=%d %d*%d %d+%d\n",
2452                          pEvent->xconfigure.border_width,
2453                          pEvent->xconfigure.width,
2454                          pEvent->xconfigure.height,
2455                          pEvent->xconfigure.x,
2456                          pEvent->xconfigure.y );
2457                 break;
2458 
2459             case PropertyNotify:
2460                 fprintf( stderr, "\t\ta=%s (0x%X)\n",
2461                          GetAtomName( pDisp_, pEvent->xproperty.atom ),
2462                          sal::static_int_cast< unsigned int >(
2463                              pEvent->xproperty.atom) );
2464                 break;
2465 
2466             case ColormapNotify:
2467                 fprintf( stderr, "\t\tc=%ld n=%d s=%d\n",
2468                          pEvent->xcolormap.colormap,
2469                          pEvent->xcolormap.c_new,
2470                          pEvent->xcolormap.state );
2471                 break;
2472 
2473             case ClientMessage:
2474                 fprintf( stderr, "\t\ta=%s (0x%X) f=%i [0x%lX,0x%lX,0x%lX,0x%lX,0x%lX])\n",
2475                          GetAtomName( pDisp_, pEvent->xclient.message_type ),
2476                          sal::static_int_cast< unsigned int >(
2477                              pEvent->xclient.message_type),
2478                          pEvent->xclient.format,
2479                          pEvent->xclient.data.l[0],
2480                          pEvent->xclient.data.l[1],
2481                          pEvent->xclient.data.l[2],
2482                          pEvent->xclient.data.l[3],
2483                          pEvent->xclient.data.l[4] );
2484                 break;
2485 
2486             case MappingNotify:
2487                 fprintf( stderr, "\t\tr=%sd\n",
2488                          MappingModifier == pEvent->xmapping.request
2489                          ? "MappingModifier"
2490                          : MappingKeyboard == pEvent->xmapping.request
2491                            ? "MappingKeyboard"
2492                            : "MappingPointer" );
2493 
2494                 break;
2495         }
2496     }
2497     else
2498         fprintf( stderr, "[%s] %d s=%d w=%ld\n",
2499                  rComment.GetBuffer(),
2500                  pEvent->type,
2501                  pEvent->xany.send_event,
2502                  pEvent->xany.window );
2503 }
2504 
2505 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
PrintInfo() const2506 void SalDisplay::PrintInfo() const
2507 {
2508     if( IsDisplay() )
2509     {
2510         fprintf( stderr, "\n" );
2511         fprintf( stderr, "Environment\n" );
2512         fprintf( stderr, "\t$XENVIRONMENT     \t\"%s\"\n",
2513                  GetEnv( "XENVIRONMENT" ) );
2514         fprintf( stderr, "\t$DISPLAY          \t\"%s\"\n",
2515                  GetEnv( "DISPLAY" ) );
2516         fprintf( stderr, "\t$SAL_VISUAL       \t\"%s\"\n",
2517                  GetEnv( "SAL_VISUAL" ) );
2518         fprintf( stderr, "\t$SAL_FONTPATH     \t\"%s\"\n",
2519                  GetEnv( "SAL_FONTPATH" ) );
2520         fprintf( stderr, "\t$SAL_NOSEGV       \t\"%s\"\n",
2521                  GetEnv( "SAL_NOSEGV" ) );
2522         fprintf( stderr, "\t$SAL_IGNOREXERRORS\t\"%s\"\n",
2523                  GetEnv( "SAL_IGNOREXERRORS" ) );
2524         fprintf( stderr, "\t$SAL_PROPERTIES   \t\"%s\"\n",
2525                  GetEnv( "SAL_PROPERTIES" ) );
2526         fprintf( stderr, "\t$SAL_WM           \t\"%s\"\n",
2527                  GetEnv( "SAL_WM" ) );
2528         fprintf( stderr, "\t$SAL_SYNCHRONIZE  \t\"%s\"\n",
2529                  GetEnv( "SAL_SYNCHRONIZE" ) );
2530 
2531         char sHostname[ 120 ];
2532         gethostname (sHostname, 120 );
2533         fprintf( stderr, "Client\n" );
2534         fprintf( stderr, "\tHost              \t\"%s\"\n",
2535                  sHostname );
2536 
2537         fprintf( stderr, "Display\n" );
2538         fprintf( stderr, "\tHost              \t\"%s\"\n",
2539                  DisplayString(pDisp_) );
2540         fprintf( stderr, "\tVendor (Release)  \t\"%s (%d)\"\n",
2541                  ServerVendor(pDisp_), VendorRelease(pDisp_) );
2542         fprintf( stderr, "\tProtocol          \t%d.%d\n",
2543                  ProtocolVersion(pDisp_), ProtocolRevision(pDisp_) );
2544         fprintf( stderr, "\tScreen (count,def)\t%d (%d,%d)\n",
2545                  m_nDefaultScreen, ScreenCount(pDisp_), DefaultScreen(pDisp_) );
2546         fprintf( stderr, "\tshift ctrl alt    \t%s (0x%X) %s (0x%X) %s (0x%X)\n",
2547                  KeyStr( nShiftKeySym_ ), sal::static_int_cast< unsigned int >(nShiftKeySym_),
2548                  KeyStr( nCtrlKeySym_ ),  sal::static_int_cast< unsigned int >(nCtrlKeySym_),
2549                  KeyStr( nMod1KeySym_ ),  sal::static_int_cast< unsigned int >(nMod1KeySym_) );
2550         if( XExtendedMaxRequestSize(pDisp_) * 4 )
2551             fprintf( stderr, "\tXMaxRequestSize   \t%ld %ld [bytes]\n",
2552                      XMaxRequestSize(pDisp_) * 4, XExtendedMaxRequestSize(pDisp_) * 4 );
2553         if( GetProperties() != PROPERTY_DEFAULT )
2554             fprintf( stderr, "\tProperties        \t0x%lX\n", GetProperties() );
2555         if( eWindowManager_ != otherwm )
2556             fprintf( stderr, "\tWindowmanager     \t%d\n", eWindowManager_ );
2557         fprintf( stderr, "\tWMName            \t%s\n", rtl::OUStringToOString( getWMAdaptor()->getWindowManagerName(), osl_getThreadTextEncoding() ).getStr() );
2558     }
2559     fprintf( stderr, "Screen\n" );
2560     fprintf( stderr, "\tResolution/Size   \t%ld*%ld %ld*%ld %.1lf\"\n",
2561              aResolution_.A(), aResolution_.B(),
2562              m_aScreens[m_nDefaultScreen].m_aSize.Width(), m_aScreens[m_nDefaultScreen].m_aSize.Height(),
2563              Hypothenuse( DisplayWidthMM ( pDisp_, m_nDefaultScreen ),
2564                           DisplayHeightMM( pDisp_, m_nDefaultScreen ) ) / 25.4 );
2565     fprintf( stderr, "\tBlack&White       \t%lu %lu\n",
2566              GetColormap(m_nDefaultScreen).GetBlackPixel(), GetColormap(m_nDefaultScreen).GetWhitePixel() );
2567     fprintf( stderr, "\tRGB               \t0x%lx 0x%lx 0x%lx\n",
2568              GetVisual(m_nDefaultScreen).red_mask, GetVisual(m_nDefaultScreen).green_mask, GetVisual(m_nDefaultScreen).blue_mask );
2569     fprintf( stderr, "\tVisual            \t%d-bit %s ID=0x%x\n",
2570              GetVisual(m_nDefaultScreen).GetDepth(),
2571              VisualClassName[ GetVisual(m_nDefaultScreen).GetClass() ],
2572              sal::static_int_cast< unsigned int >(GetVisual(m_nDefaultScreen).GetVisualId()) );
2573 }
2574 
addXineramaScreenUnique(long i_nX,long i_nY,long i_nWidth,long i_nHeight)2575 int SalDisplay::addXineramaScreenUnique( long i_nX, long i_nY, long i_nWidth, long i_nHeight )
2576 {
2577     // see if any frame buffers are at the same coordinates
2578     // this can happen with weird configuration e.g. on
2579     // XFree86 and Clone displays
2580     const size_t nScreens = m_aXineramaScreens.size();
2581     for( size_t n = 0; n < nScreens; n++ )
2582     {
2583         if( m_aXineramaScreens[n].Left() == i_nX &&
2584             m_aXineramaScreens[n].Top() == i_nY )
2585         {
2586             if( m_aXineramaScreens[n].GetWidth() < i_nWidth ||
2587                 m_aXineramaScreens[n].GetHeight() < i_nHeight )
2588             {
2589                 m_aXineramaScreens[n].SetSize( Size( i_nWidth, i_nHeight ) );
2590             }
2591             return (int)n;
2592         }
2593     }
2594     m_aXineramaScreens.push_back( Rectangle( Point( i_nX, i_nY ), Size( i_nWidth, i_nHeight ) ) );
2595     return (int)m_aXineramaScreens.size()-1;
2596 }
2597 
InitXinerama()2598 void SalDisplay::InitXinerama()
2599 {
2600     if( m_aScreens.size() > 1 )
2601     {
2602         m_bXinerama = false;
2603         return; // multiple screens mean no xinerama
2604     }
2605 #ifdef USE_XINERAMA
2606 #if defined(USE_XINERAMA_XSUN)
2607     int nFramebuffers = 1;
2608     if( XineramaGetState( pDisp_, m_nDefaultScreen ) )
2609     {
2610         XRectangle pFramebuffers[MAXFRAMEBUFFERS];
2611         unsigned char hints[MAXFRAMEBUFFERS];
2612         int result = XineramaGetInfo( pDisp_,
2613                                       m_nDefaultScreen,
2614                                       pFramebuffers,
2615                                       hints,
2616                                       &nFramebuffers );
2617         if( result > 0 && nFramebuffers > 1 )
2618         {
2619             m_bXinerama = true;
2620             m_aXineramaScreens = std::vector<Rectangle>();
2621             for( int i = 0; i < nFramebuffers; i++ )
2622                 addXineramaScreenUnique( pFramebuffers[i].x,
2623                                          pFramebuffers[i].y,
2624                                          pFramebuffers[i].width,
2625                                          pFramebuffers[i].height );
2626         }
2627     }
2628 #elif defined(USE_XINERAMA_XORG)
2629 if( XineramaIsActive( pDisp_ ) )
2630 {
2631     int nFramebuffers = 1;
2632     XineramaScreenInfo* pScreens = XineramaQueryScreens( pDisp_, &nFramebuffers );
2633     if( pScreens )
2634     {
2635         if( nFramebuffers > 1 )
2636         {
2637             m_aXineramaScreens = std::vector<Rectangle>();
2638             for( int i = 0; i < nFramebuffers; i++ )
2639             {
2640                 addXineramaScreenUnique( pScreens[i].x_org,
2641                                          pScreens[i].y_org,
2642                                          pScreens[i].width,
2643                                          pScreens[i].height );
2644             }
2645             m_bXinerama = m_aXineramaScreens.size() > 1;
2646         }
2647         XFree( pScreens );
2648     }
2649 }
2650 #endif
2651 #if OSL_DEBUG_LEVEL > 1
2652     if( m_bXinerama )
2653     {
2654         for( std::vector< Rectangle >::const_iterator it = m_aXineramaScreens.begin(); it != m_aXineramaScreens.end(); ++it )
2655             fprintf( stderr, "Xinerama screen: %ldx%ld+%ld+%ld\n", it->GetWidth(), it->GetHeight(), it->Left(), it->Top() );
2656     }
2657 #endif
2658 #endif // USE_XINERAMA
2659 }
2660 
registerFrame(SalFrame * pFrame)2661 void SalDisplay::registerFrame( SalFrame* pFrame )
2662 {
2663     m_aFrames.push_front( pFrame );
2664 }
2665 
deregisterFrame(SalFrame * pFrame)2666 void SalDisplay::deregisterFrame( SalFrame* pFrame )
2667 {
2668     if( osl_acquireMutex( hEventGuard_ ) )
2669     {
2670         std::list< SalUserEvent >::iterator it = m_aUserEvents.begin();
2671         while ( it != m_aUserEvents.end() )
2672         {
2673             if( it->m_pFrame == pFrame )
2674                 it = m_aUserEvents.erase( it );
2675             else
2676                 ++it;
2677         }
2678         osl_releaseMutex( hEventGuard_ );
2679     }
2680     else {
2681         DBG_ERROR( "SalDisplay::deregisterFrame !acquireMutex\n" );
2682     }
2683 
2684     m_aFrames.remove( pFrame );
2685 }
2686 
2687 
2688 extern "C"
2689 {
timestamp_predicate(Display *,XEvent * i_pEvent,XPointer i_pArg)2690     static Bool timestamp_predicate( Display*, XEvent* i_pEvent, XPointer i_pArg )
2691     {
2692         SalDisplay* pSalDisplay = reinterpret_cast<SalDisplay*>(i_pArg);
2693         if( i_pEvent->type == PropertyNotify &&
2694             i_pEvent->xproperty.window == pSalDisplay->GetDrawable( pSalDisplay->GetDefaultScreenNumber() ) &&
2695             i_pEvent->xproperty.atom == pSalDisplay->getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT )
2696             )
2697         return True;
2698 
2699         return False;
2700     }
2701 }
2702 
GetLastUserEventTime(bool i_bAlwaysReget) const2703 XLIB_Time SalDisplay::GetLastUserEventTime( bool i_bAlwaysReget ) const
2704 {
2705     if( m_nLastUserEventTime == CurrentTime || i_bAlwaysReget )
2706     {
2707         // get current server time
2708         unsigned char c = 0;
2709         XEvent aEvent;
2710         Atom nAtom = getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT );
2711         XChangeProperty( GetDisplay(), GetDrawable( GetDefaultScreenNumber() ),
2712                          nAtom, nAtom, 8, PropModeReplace, &c, 1 );
2713         XFlush( GetDisplay() );
2714 
2715         if( ! XIfEventWithTimeout( &aEvent, (XPointer)this, timestamp_predicate ) )
2716         {
2717             // this should not happen at all; still sometimes it happens
2718             aEvent.xproperty.time = CurrentTime;
2719         }
2720 
2721         m_nLastUserEventTime = aEvent.xproperty.time;
2722     }
2723     return m_nLastUserEventTime;
2724 }
2725 
XIfEventWithTimeout(XEvent * o_pEvent,XPointer i_pPredicateData,X_if_predicate i_pPredicate,long i_nTimeout) const2726 bool SalDisplay::XIfEventWithTimeout( XEvent* o_pEvent, XPointer i_pPredicateData,
2727                                       X_if_predicate i_pPredicate, long i_nTimeout ) const
2728 {
2729     /* #i99360# ugly workaround an X11 library bug
2730        this replaces the following call:
2731        XIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData );
2732     */
2733     bool bRet = true;
2734 
2735     if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) )
2736     {
2737         // wait for some event to arrive
2738         struct pollfd aFD;
2739         aFD.fd = ConnectionNumber(GetDisplay());
2740         aFD.events = POLLIN;
2741         aFD.revents = 0;
2742         poll( &aFD, 1, i_nTimeout );
2743         if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) )
2744         {
2745             poll( &aFD, 1, i_nTimeout ); // try once more for a packet of events from the Xserver
2746             if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) )
2747             {
2748                 bRet = false;
2749             }
2750         }
2751     }
2752     return bRet;
2753 }
2754 
2755 // -=-= SalVisual -=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2756 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SalVisual()2757 SalVisual::SalVisual()
2758 {
2759     rtl_zeroMemory( this, sizeof( SalVisual ) );
2760 }
2761 
SalVisual(const XVisualInfo * pXVI)2762 SalVisual::SalVisual( const XVisualInfo* pXVI )
2763 {
2764     *(XVisualInfo*)this = *pXVI;
2765     if( GetClass() == TrueColor )
2766     {
2767         nRedShift_      = sal_Shift( red_mask );
2768         nGreenShift_    = sal_Shift( green_mask );
2769         nBlueShift_     = sal_Shift( blue_mask );
2770 
2771         nRedBits_       = sal_significantBits( red_mask );
2772         nGreenBits_     = sal_significantBits( green_mask );
2773         nBlueBits_      = sal_significantBits( blue_mask );
2774 
2775         if( GetDepth() == 24 )
2776             if( red_mask == 0xFF0000 )
2777                 if( green_mask == 0xFF00 )
2778                     if( blue_mask  == 0xFF )
2779                         eRGBMode_ = RGB;
2780                     else
2781                         eRGBMode_ = otherSalRGB;
2782                 else if( blue_mask  == 0xFF00 )
2783                     if( green_mask == 0xFF )
2784                         eRGBMode_ = RBG;
2785                     else
2786                         eRGBMode_ = otherSalRGB;
2787                 else
2788                     eRGBMode_ = otherSalRGB;
2789             else if( green_mask == 0xFF0000 )
2790                 if( red_mask == 0xFF00 )
2791                     if( blue_mask  == 0xFF )
2792                         eRGBMode_ = GRB;
2793                     else
2794                         eRGBMode_ = otherSalRGB;
2795                 else if( blue_mask == 0xFF00 )
2796                     if( red_mask  == 0xFF )
2797                         eRGBMode_ = GBR;
2798                     else
2799                         eRGBMode_ = otherSalRGB;
2800                 else
2801                     eRGBMode_ = otherSalRGB;
2802             else if( blue_mask == 0xFF0000 )
2803                 if( red_mask == 0xFF00 )
2804                     if( green_mask  == 0xFF )
2805                         eRGBMode_ = BRG;
2806                     else
2807                         eRGBMode_ = otherSalRGB;
2808                 else if( green_mask == 0xFF00 )
2809                     if( red_mask == 0xFF )
2810                         eRGBMode_ = BGR;
2811                     else
2812                         eRGBMode_ = otherSalRGB;
2813                 else
2814                     eRGBMode_ = otherSalRGB;
2815             else
2816                 eRGBMode_ = otherSalRGB;
2817         else
2818             eRGBMode_ = otherSalRGB;
2819     }
2820 }
2821 
2822 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
~SalVisual()2823 SalVisual::~SalVisual()
2824 {
2825     if( -1 == screen && VisualID(-1) == visualid ) delete visual;
2826 }
2827 
2828 // Konvertiert die Reihenfolge der Bytes eines Pixel in Bytes eines SalColors
2829 // fuer die 6 XXXA ist das nicht reversibel
2830 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2831 // SalColor is RGB (ABGR) a=0xFF000000, r=0xFF0000, g=0xFF00, b=0xFF
2832 
2833 #define SALCOLOR        RGB
2834 #define SALCOLORREVERSE BGR
2835 
Convert(int & n0,int & n1,int & n2,int & n3)2836 sal_Bool SalVisual::Convert( int &n0, int &n1, int &n2, int &n3 )
2837 {
2838     int n;
2839 
2840     switch( GetMode() )
2841     {
2842         case otherSalRGB:
2843             return sal_False;
2844         case SALCOLOR:
2845             break;
2846         case SALCOLORREVERSE:
2847         case RBG:
2848         case BRG:
2849         case GBR:
2850         case GRB:
2851             return Convert( n0, n1, n2 );
2852         case RGBA:
2853             n  = n0;
2854             n0 = n1;
2855             n1 = n2;
2856             n2 = n3;
2857             n3 = n;
2858             break;
2859         case BGRA:
2860         case RBGA:
2861         case BRGA:
2862         case GBRA:
2863         case GRBA:
2864         default:
2865             fprintf( stderr, "SalVisual::Convert %d\n", GetMode() );
2866             abort();
2867     }
2868     return sal_True;
2869 }
2870 
Convert(int & n0,int & n1,int & n2)2871 sal_Bool SalVisual::Convert( int &n0, int &n1, int &n2 )
2872 {
2873     int n;
2874 
2875     switch( GetMode() )
2876     {
2877         case otherSalRGB:
2878             return sal_False;
2879         case SALCOLOR:
2880             break;
2881         case RBG:
2882             n  = n0;
2883             n0 = n1;
2884             n1 = n;
2885             break;
2886         case GRB:
2887             n  = n1;
2888             n1 = n2;
2889             n2 = n;
2890             break;
2891         case SALCOLORREVERSE:
2892             n  = n0;
2893             n0 = n2;
2894             n2 = n;
2895             break;
2896         case BRG:
2897             n  = n0;
2898             n0 = n1;
2899             n1 = n2;
2900             n2 = n;
2901             break;
2902         case GBR:
2903             n  = n2;
2904             n2 = n1;
2905             n1 = n0;
2906             n0 = n;
2907             break;
2908         default:
2909             fprintf( stderr, "SalVisual::Convert %d\n", GetMode() );
2910             abort();
2911     }
2912     return sal_True;
2913 }
2914 
2915 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
GetTCColor(Pixel nPixel) const2916 SalColor SalVisual::GetTCColor( Pixel nPixel ) const
2917 {
2918     if( SALCOLOR == eRGBMode_ )
2919         return (SalColor)nPixel;
2920 
2921     if( SALCOLORREVERSE == eRGBMode_ )
2922         return MAKE_SALCOLOR( (nPixel & 0x0000FF),
2923                               (nPixel & 0x00FF00) >>  8,
2924                               (nPixel & 0xFF0000) >> 16);
2925 
2926     Pixel r = nPixel & red_mask;
2927     Pixel g = nPixel & green_mask;
2928     Pixel b = nPixel & blue_mask;
2929 
2930     if( otherSalRGB != eRGBMode_ ) // 8+8+8=24
2931         return MAKE_SALCOLOR( r >> nRedShift_,
2932                               g >> nGreenShift_,
2933                               b >> nBlueShift_ );
2934 
2935     if( nRedShift_ > 0 )   r >>= nRedShift_;   else r <<= -nRedShift_;
2936     if( nGreenShift_ > 0 ) g >>= nGreenShift_; else g <<= -nGreenShift_;
2937     if( nBlueShift_ > 0 )  b >>= nBlueShift_;  else b <<= -nBlueShift_;
2938 
2939     if( nRedBits_ != 8 )
2940         r |= (r & 0xff) >> (8-nRedBits_);
2941     if( nGreenBits_ != 8 )
2942         g |= (g & 0xff) >> (8-nGreenBits_);
2943     if( nBlueBits_ != 8 )
2944         b |= (b & 0xff) >> (8-nBlueBits_);
2945 
2946     return MAKE_SALCOLOR( r, g, b );
2947 }
2948 
GetTCPixel(SalColor nSalColor) const2949 Pixel SalVisual::GetTCPixel( SalColor nSalColor ) const
2950 {
2951     if( SALCOLOR == eRGBMode_ )
2952         return (Pixel)nSalColor;
2953 
2954     Pixel r = (Pixel)SALCOLOR_RED( nSalColor );
2955     Pixel g = (Pixel)SALCOLOR_GREEN( nSalColor );
2956     Pixel b = (Pixel)SALCOLOR_BLUE( nSalColor );
2957 
2958     if( SALCOLORREVERSE == eRGBMode_ )
2959         return (b << 16) | (g << 8) | (r);
2960 
2961     if( otherSalRGB != eRGBMode_ ) // 8+8+8=24
2962         return (r << nRedShift_) | (g << nGreenShift_) | (b << nBlueShift_);
2963 
2964     if( nRedShift_ > 0 )   r <<= nRedShift_;   else r >>= -nRedShift_;
2965     if( nGreenShift_ > 0 ) g <<= nGreenShift_; else g >>= -nGreenShift_;
2966     if( nBlueShift_ > 0 )  b <<= nBlueShift_;  else b >>= -nBlueShift_;
2967 
2968     return (r&red_mask) | (g&green_mask) | (b&blue_mask);
2969 }
2970 
2971 // -=-= SalColormap -=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2972 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SalColormap(const SalDisplay * pDisplay,Colormap hColormap,int nScreen)2973 SalColormap::SalColormap( const SalDisplay *pDisplay, Colormap hColormap, int nScreen )
2974     : m_pDisplay( pDisplay ),
2975       m_hColormap( hColormap ),
2976       m_nScreen( nScreen )
2977 {
2978     m_aVisual = m_pDisplay->GetVisual( m_nScreen );
2979 
2980     XColor aColor;
2981 
2982     GetXPixel( aColor, 0x00, 0x00, 0x00 );
2983     m_nBlackPixel = aColor.pixel;
2984 
2985     GetXPixel( aColor, 0xFF, 0xFF, 0xFF );
2986     m_nWhitePixel = aColor.pixel;
2987 
2988     m_nUsed = 1 << m_aVisual.GetDepth();
2989 
2990     if( m_aVisual.GetClass() == PseudoColor )
2991     {
2992         int r, g, b;
2993 
2994         // black, white, gray, ~gray = 4
2995         GetXPixels( aColor, 0xC0, 0xC0, 0xC0 );
2996 
2997         // light colors: 3 * 2 = 6
2998 //      GetXPixels( aColor, 0x00, 0x00, 0x00 );
2999         GetXPixels( aColor, 0x00, 0x00, 0xFF );
3000         GetXPixels( aColor, 0x00, 0xFF, 0x00 );
3001         GetXPixels( aColor, 0x00, 0xFF, 0xFF );
3002 //      GetXPixels( aColor, 0xFF, 0x00, 0x00 );
3003 //      GetXPixels( aColor, 0xFF, 0x00, 0xFF );
3004 //      GetXPixels( aColor, 0xFF, 0xFF, 0x00 );
3005 //      GetXPixels( aColor, 0xFF, 0xFF, 0xFF );
3006 
3007         // standard colors: 7 * 2 = 14
3008 //      GetXPixels( aColor, 0x00, 0x00, 0x00 );
3009         GetXPixels( aColor, 0x00, 0x00, 0x80 );
3010         GetXPixels( aColor, 0x00, 0x80, 0x00 );
3011         GetXPixels( aColor, 0x00, 0x80, 0x80 );
3012         GetXPixels( aColor, 0x80, 0x00, 0x00 );
3013         GetXPixels( aColor, 0x80, 0x00, 0x80 );
3014         GetXPixels( aColor, 0x80, 0x80, 0x00 );
3015         GetXPixels( aColor, 0x80, 0x80, 0x80 );
3016         GetXPixels( aColor, 0x00, 0xB8, 0xFF ); // Blau 7
3017 
3018         // cube: 6*6*6 - 8 = 208
3019         for( r = 0; r < 0x100; r += 0x33 ) // 0x33, 0x66, 0x99, 0xCC, 0xFF
3020             for( g = 0; g < 0x100; g += 0x33 )
3021                 for( b = 0; b < 0x100; b += 0x33 )
3022                     GetXPixels( aColor, r, g, b );
3023 
3024         // gray: 16 - 6 = 10
3025         for( g = 0x11; g < 0xFF; g += 0x11 )
3026             GetXPixels( aColor, g, g, g );
3027 
3028         // green: 16 - 6 = 10
3029         for( g = 0x11; g < 0xFF; g += 0x11 )
3030             GetXPixels( aColor, 0, g, 0 );
3031 
3032         // red: 16 - 6 = 10
3033         for( r = 0x11; r < 0xFF; r += 0x11 )
3034             GetXPixels( aColor, r, 0, 0 );
3035 
3036         // blue: 16 - 6 = 10
3037         for( b = 0x11; b < 0xFF; b += 0x11 )
3038             GetXPixels( aColor, 0, 0, b );
3039     }
3040 }
3041 
3042 // PseudoColor
SalColormap(const BitmapPalette & rPalette)3043 SalColormap::SalColormap( const BitmapPalette &rPalette )
3044     : m_pDisplay( GetX11SalData()->GetDisplay() ),
3045       m_hColormap( None ),
3046       m_nWhitePixel( SALCOLOR_NONE ),
3047       m_nBlackPixel( SALCOLOR_NONE ),
3048       m_nUsed( rPalette.GetEntryCount() ),
3049       m_nScreen( GetX11SalData()->GetDisplay()->GetDefaultScreenNumber() )
3050 {
3051     m_aPalette = std::vector<SalColor>(m_nUsed);
3052 
3053     for( unsigned int i = 0; i < m_nUsed; i++ )
3054     {
3055         const BitmapColor &rColor = rPalette[i];
3056         m_aPalette[i] = MAKE_SALCOLOR( rColor.GetRed(),
3057                                        rColor.GetGreen(),
3058                                        rColor.GetBlue() );
3059         if( (m_nBlackPixel == SALCOLOR_NONE) && (SALCOLOR_BLACK == m_aPalette[i]) )
3060             m_nBlackPixel = i;
3061         else if( (m_nWhitePixel == SALCOLOR_NONE) && (SALCOLOR_WHITE == m_aPalette[i]) )
3062             m_nWhitePixel = i;
3063     }
3064 }
3065 
3066 // MonoChrome
SalColormap()3067 SalColormap::SalColormap()
3068     : m_pDisplay( GetX11SalData()->GetDisplay() ),
3069       m_hColormap( None ),
3070       m_nWhitePixel( 1 ),
3071       m_nBlackPixel( 0 ),
3072       m_nUsed( 2 ),
3073       m_nScreen( 0 )
3074 {
3075     if( m_pDisplay )
3076         m_nScreen = m_pDisplay->GetDefaultScreenNumber();
3077     m_aPalette = std::vector<SalColor>(m_nUsed);
3078 
3079     m_aPalette[m_nBlackPixel] = SALCOLOR_BLACK;
3080     m_aPalette[m_nWhitePixel] = SALCOLOR_WHITE;
3081 }
3082 
3083 // TrueColor
SalColormap(sal_uInt16 nDepth)3084 SalColormap::SalColormap( sal_uInt16 nDepth )
3085     : m_pDisplay( GetX11SalData()->GetDisplay() ),
3086       m_hColormap( None ),
3087       m_nWhitePixel( (1 << nDepth) - 1 ),
3088       m_nBlackPixel( 0x00000000 ),
3089       m_nUsed( 1 << nDepth ),
3090       m_nScreen( GetX11SalData()->GetDisplay()->GetDefaultScreenNumber() )
3091 {
3092     const SalVisual *pVisual  = &m_pDisplay->GetVisual( m_nScreen );
3093 
3094     if( pVisual->GetClass() == TrueColor && pVisual->GetDepth() == nDepth )
3095         m_aVisual = *pVisual;
3096     else
3097     {
3098         XVisualInfo aVI;
3099 
3100         if( !XMatchVisualInfo( m_pDisplay->GetDisplay(),
3101                                m_pDisplay->GetDefaultScreenNumber(),
3102                                nDepth,
3103                                TrueColor,
3104                                &aVI ) )
3105         {
3106             aVI.visual          = new Visual();
3107             aVI.visualid        = (VisualID)0; // beware of temporary destructor below
3108             aVI.screen          = 0;
3109             aVI.depth           = nDepth;
3110             aVI.c_class         = TrueColor;
3111             if( 24 == nDepth ) // 888
3112             {
3113                 aVI.red_mask        = 0xFF0000;
3114                 aVI.green_mask      = 0x00FF00;
3115                 aVI.blue_mask       = 0x0000FF;
3116             }
3117             else if( 16 == nDepth ) // 565
3118             {
3119                 aVI.red_mask        = 0x00F800;
3120                 aVI.green_mask      = 0x0007E0;
3121                 aVI.blue_mask       = 0x00001F;
3122             }
3123             else if( 15 == nDepth ) // 555
3124             {
3125                 aVI.red_mask        = 0x007C00;
3126                 aVI.green_mask      = 0x0003E0;
3127                 aVI.blue_mask       = 0x00001F;
3128             }
3129             else if( 12 == nDepth ) // 444
3130             {
3131                 aVI.red_mask        = 0x000F00;
3132                 aVI.green_mask      = 0x0000F0;
3133                 aVI.blue_mask       = 0x00000F;
3134             }
3135             else if( 8 == nDepth ) // 332
3136             {
3137                 aVI.red_mask        = 0x0000E0;
3138                 aVI.green_mask      = 0x00001C;
3139                 aVI.blue_mask       = 0x000003;
3140             }
3141             else
3142             {
3143                 aVI.red_mask        = 0x000000;
3144                 aVI.green_mask      = 0x000000;
3145                 aVI.blue_mask       = 0x000000;
3146             }
3147             aVI.colormap_size   = 0;
3148             aVI.bits_per_rgb    = 8;
3149 
3150             aVI.visual->ext_data        = NULL;
3151             aVI.visual->visualid        = aVI.visualid;
3152             aVI.visual->c_class         = aVI.c_class;
3153             aVI.visual->red_mask        = aVI.red_mask;
3154             aVI.visual->green_mask      = aVI.green_mask;
3155             aVI.visual->blue_mask       = aVI.blue_mask;
3156             aVI.visual->bits_per_rgb    = aVI.bits_per_rgb;
3157             aVI.visual->map_entries     = aVI.colormap_size;
3158 
3159             m_aVisual = SalVisual( &aVI );
3160             // give ownership of constructed Visual() to m_aVisual
3161             // see SalVisual destructor
3162             m_aVisual.visualid        = (VisualID)-1;
3163             m_aVisual.screen          = -1;
3164         }
3165         else
3166             m_aVisual = SalVisual( &aVI );
3167     }
3168 }
3169 
~SalColormap()3170 SalColormap::~SalColormap()
3171 {
3172 #ifdef DBG_UTIL
3173     m_hColormap      = (Colormap)ILLEGAL_POINTER;
3174     m_pDisplay       = (SalDisplay*)ILLEGAL_POINTER;
3175 #endif
3176 }
3177 
3178 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SetPalette(const BitmapPalette & rPalette)3179 void SalColormap::SetPalette( const BitmapPalette &rPalette )
3180 {
3181     if( this != &GetX11SalData()->GetDisplay()->GetColormap(m_nScreen) )
3182     {
3183         m_nBlackPixel = SALCOLOR_NONE;
3184         m_nWhitePixel = SALCOLOR_NONE;
3185     }
3186 
3187     if( rPalette.GetEntryCount() > m_nUsed )
3188     {
3189         m_nBlackPixel = SALCOLOR_NONE;
3190         m_nWhitePixel = SALCOLOR_NONE;
3191         m_nUsed = rPalette.GetEntryCount();
3192         m_aPalette = std::vector<SalColor>(m_nUsed);
3193     }
3194 
3195     for( int i = 0; i < rPalette.GetEntryCount(); i++ )
3196     {
3197         const BitmapColor &rColor = rPalette[i];
3198         m_aPalette[i] = MAKE_SALCOLOR( rColor.GetRed(),
3199                                        rColor.GetGreen(),
3200                                        rColor.GetBlue() );
3201         if( (m_nBlackPixel == SALCOLOR_NONE) && (SALCOLOR_BLACK == m_aPalette[i]) )
3202             m_nBlackPixel = i;
3203         else if( (m_nWhitePixel == SALCOLOR_NONE) && (SALCOLOR_WHITE == m_aPalette[i]) )
3204             m_nWhitePixel = i;
3205     }
3206 }
3207 
GetPalette()3208 void SalColormap::GetPalette()
3209 {
3210     Pixel i;
3211     m_aPalette = std::vector<SalColor>(m_nUsed);
3212 
3213     XColor *aColor = new XColor[m_nUsed];
3214 
3215     for( i = 0; i < m_nUsed; i++ )
3216     {
3217         aColor[i].red = aColor[i].green = aColor[i].blue = 0;
3218         aColor[i].pixel = i;
3219     }
3220 
3221     XQueryColors( m_pDisplay->GetDisplay(), m_hColormap, aColor, m_nUsed );
3222 
3223     for( i = 0; i < m_nUsed; i++ )
3224     {
3225         m_aPalette[i] = MAKE_SALCOLOR( aColor[i].red   >> 8,
3226                                        aColor[i].green >> 8,
3227                                        aColor[i].blue  >> 8 );
3228     }
3229 
3230     delete [] aColor;
3231 }
3232 
3233 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sal_Lookup(const std::vector<SalColor> & rPalette,int r,int g,int b,Pixel nUsed)3234 static sal_uInt16 sal_Lookup( const std::vector<SalColor>& rPalette,
3235                                 int r, int g, int b,
3236                                 Pixel nUsed )
3237 {
3238     sal_uInt16 nPixel = 0;
3239     int    nBest  = ColorDiff( rPalette[0], r, g, b );
3240 
3241     for( sal_uInt16 i = 1; i < nUsed; i++ )
3242     {
3243         int n = ColorDiff( rPalette[i], r, g, b );
3244 
3245         if( n < nBest )
3246         {
3247             if( !n )
3248                 return i;
3249 
3250             nPixel = i;
3251             nBest  = n;
3252         }
3253     }
3254     return nPixel;
3255 }
3256 
GetLookupTable()3257 void SalColormap::GetLookupTable()
3258 {
3259     m_aLookupTable = std::vector<sal_uInt16>(16*16*16);
3260 
3261     int i = 0;
3262     for( int r = 0; r < 256; r += 17 )
3263         for( int g = 0; g < 256; g += 17 )
3264             for( int b = 0; b < 256; b += 17 )
3265                 m_aLookupTable[i++] = sal_Lookup( m_aPalette, r, g, b, m_nUsed );
3266 }
3267 
3268 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
GetColor(Pixel nPixel) const3269 SalColor SalColormap::GetColor( Pixel nPixel ) const
3270 {
3271     if( m_nBlackPixel == nPixel ) return SALCOLOR_BLACK;
3272     if( m_nWhitePixel == nPixel ) return SALCOLOR_WHITE;
3273 
3274     if( m_aVisual.GetVisual() )
3275     {
3276         if( m_aVisual.GetClass() == TrueColor )
3277             return m_aVisual.GetTCColor( nPixel );
3278 
3279         if( m_aPalette.empty()
3280             && m_hColormap
3281 #ifdef PSEUDOCOLOR12
3282             && m_aVisual.GetDepth() <= 12
3283 #else
3284             && m_aVisual.GetDepth() <= 8
3285 #endif
3286             && m_aVisual.GetClass() == PseudoColor )
3287             ((SalColormap*)this)->GetPalette();
3288     }
3289 
3290     if( !m_aPalette.empty() && nPixel < m_nUsed )
3291         return m_aPalette[nPixel];
3292 
3293     if( m_hColormap )
3294     {
3295         DBG_ASSERT( 1, "SalColormap::GetColor() !hColormap_\n" );
3296         return nPixel;
3297     }
3298 
3299     // DirectColor, StaticColor, StaticGray, GrayScale
3300     XColor aColor;
3301 
3302     aColor.pixel = nPixel;
3303 
3304     XQueryColor( m_pDisplay->GetDisplay(), m_hColormap, &aColor );
3305 
3306     return MAKE_SALCOLOR( aColor.red>>8, aColor.green>>8, aColor.blue>>8 );
3307 }
3308 
GetXPixel(XColor & rColor,int r,int g,int b) const3309 inline sal_Bool SalColormap::GetXPixel( XColor &rColor,
3310                                           int     r,
3311                                           int     g,
3312                                           int     b ) const
3313 {
3314     rColor.red      = r * 257;
3315     rColor.green    = g * 257;
3316     rColor.blue     = b * 257;
3317     return XAllocColor( GetXDisplay(), m_hColormap, &rColor );
3318 }
3319 
GetXPixels(XColor & rColor,int r,int g,int b) const3320 sal_Bool SalColormap::GetXPixels( XColor &rColor,
3321                                     int     r,
3322                                     int     g,
3323                                     int     b ) const
3324 {
3325     if( !GetXPixel( rColor, r, g, b ) )
3326         return sal_False;
3327     if( rColor.pixel & 1 )
3328         return sal_True;
3329     return GetXPixel( rColor, r^0xFF, g^0xFF, b^0xFF );
3330 }
3331 
GetPixel(SalColor nSalColor) const3332 Pixel SalColormap::GetPixel( SalColor nSalColor ) const
3333 {
3334     if( SALCOLOR_NONE == nSalColor )  return 0;
3335     if( SALCOLOR_BLACK == nSalColor ) return m_nBlackPixel;
3336     if( SALCOLOR_WHITE == nSalColor ) return m_nWhitePixel;
3337 
3338     if( m_aVisual.GetClass() == TrueColor )
3339         return m_aVisual.GetTCPixel( nSalColor );
3340 
3341     if( m_aLookupTable.empty() )
3342     {
3343         if( m_aPalette.empty()
3344             && m_hColormap
3345 #ifdef PSEUDOCOLOR12
3346             && m_aVisual.GetDepth() <= 12
3347 #else
3348             && m_aVisual.GetDepth() <= 8
3349 #endif
3350             && m_aVisual.GetClass() == PseudoColor ) // what else ???
3351             ((SalColormap*)this)->GetPalette();
3352 
3353         if( !m_aPalette.empty() )
3354             for( Pixel i = 0; i < m_nUsed; i++ )
3355                 if( m_aPalette[i] == nSalColor )
3356                     return i;
3357 
3358         if( m_hColormap )
3359         {
3360             // DirectColor, StaticColor, StaticGray, GrayScale (PseudoColor)
3361             XColor aColor;
3362 
3363             if( GetXPixel( aColor,
3364                            SALCOLOR_RED  ( nSalColor ),
3365                            SALCOLOR_GREEN( nSalColor ),
3366                            SALCOLOR_BLUE ( nSalColor ) ) )
3367             {
3368                 if( !m_aPalette.empty() && !m_aPalette[aColor.pixel] )
3369                 {
3370                     const_cast<SalColormap*>(this)->m_aPalette[aColor.pixel] = nSalColor;
3371 
3372                     if( !(aColor.pixel & 1) && !m_aPalette[aColor.pixel+1] )
3373                     {
3374                         XColor aInversColor;
3375 
3376                         SalColor nInversColor = nSalColor ^ 0xFFFFFF;
3377 
3378                         GetXPixel( aInversColor,
3379                                    SALCOLOR_RED  ( nInversColor ),
3380                                    SALCOLOR_GREEN( nInversColor ),
3381                                    SALCOLOR_BLUE ( nInversColor ) );
3382 
3383                         if( !m_aPalette[aInversColor.pixel] )
3384                             const_cast<SalColormap*>(this)->m_aPalette[aInversColor.pixel] = nInversColor;
3385 #ifdef DBG_UTIL
3386                         else
3387                             fprintf( stderr, "SalColormap::GetPixel() 0x%06lx=%lu 0x%06lx=%lu\n",
3388                                      static_cast< unsigned long >(nSalColor), aColor.pixel,
3389                                      static_cast< unsigned long >(nInversColor), aInversColor.pixel);
3390 #endif
3391                     }
3392                 }
3393 
3394                 return aColor.pixel;
3395             }
3396 
3397 #ifdef DBG_UTIL
3398             fprintf( stderr, "SalColormap::GetPixel() !XAllocColor %lx\n",
3399                      static_cast< unsigned long >(nSalColor) );
3400 #endif
3401         }
3402 
3403         if( m_aPalette.empty() )
3404         {
3405 #ifdef DBG_UTIL
3406             fprintf( stderr, "SalColormap::GetPixel() Palette empty %lx\n",
3407                      static_cast< unsigned long >(nSalColor));
3408 #endif
3409             return nSalColor;
3410         }
3411 
3412         ((SalColormap*)this)->GetLookupTable();
3413     }
3414 
3415     // Colormatching über Palette
3416     sal_uInt16 r = SALCOLOR_RED  ( nSalColor );
3417     sal_uInt16 g = SALCOLOR_GREEN( nSalColor );
3418     sal_uInt16 b = SALCOLOR_BLUE ( nSalColor );
3419     return m_aLookupTable[ (((r+8)/17) << 8)
3420                          + (((g+8)/17) << 4)
3421                          +  ((b+8)/17) ];
3422 }
3423 
3424 /* vim: set noet sw=4 ts=4: */
3425