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