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