Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <string.h>
21 : #include <stdio.h>
22 : #include <stdlib.h>
23 : #include <math.h>
24 : #include <sys/time.h>
25 : #include <pthread.h>
26 : #include <unistd.h>
27 : #include <ctype.h>
28 :
29 : #if defined(SOLARIS) || defined(AIX)
30 : #include <sal/alloca.h>
31 : #include <osl/module.h>
32 : #endif
33 :
34 : #include <prex.h>
35 : #include <X11/cursorfont.h>
36 : #include "unx/x11_cursors/salcursors.h"
37 : #include "unx/x11_cursors/invert50.h"
38 : #ifdef SOLARIS
39 : #define XK_KOREAN
40 : #endif
41 : #include <X11/keysym.h>
42 : #include <X11/XKBlib.h>
43 : #include <X11/Xatom.h>
44 :
45 : #ifdef USE_XINERAMA_XORG
46 : #include <X11/extensions/Xinerama.h>
47 : #elif defined USE_XINERAMA_XSUN
48 : #if defined(SOLARIS) && defined(INTEL) // missing extension header in standard installation
49 : #define MAXFRAMEBUFFERS 16
50 : Bool XineramaGetState(Display*, int);
51 : Status XineramaGetInfo(Display*, int, XRectangle*, unsigned char*, int*);
52 : #else
53 : #include <X11/extensions/xinerama.h>
54 : #endif
55 : #endif
56 :
57 : #include <postx.h>
58 :
59 : #include <vcl/svapp.hxx>
60 : #include <unx/salunx.h>
61 : #include <sal/types.h>
62 : #include "unx/i18n_im.hxx"
63 : #include "unx/i18n_xkb.hxx"
64 : #include <unx/saldisp.hxx>
65 : #include <unx/saldata.hxx>
66 : #include <salinst.hxx>
67 : #include <unx/salgdi.h>
68 : #include <unx/salframe.h>
69 : #include <vcl/keycodes.hxx>
70 : #include <unx/salbmp.h>
71 : #include <osl/mutex.h>
72 : #include <unx/salobj.h>
73 : #include <unx/sm.hxx>
74 : #include <unx/wmadaptor.hxx>
75 :
76 : #include <osl/socket.h>
77 : #include <poll.h>
78 :
79 : using namespace vcl_sal;
80 :
81 :
82 : #define SALCOLOR_WHITE MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF )
83 : #define SALCOLOR_BLACK MAKE_SALCOLOR( 0x00, 0x00, 0x00 )
84 :
85 : static const char* const EventNames[] =
86 : {
87 : NULL,
88 : NULL,
89 : "KeyPress",
90 : "KeyRelease",
91 : "ButtonPress",
92 : "ButtonRelease",
93 : "MotionNotify",
94 : "EnterNotify",
95 : "LeaveNotify",
96 : "FocusIn",
97 : "FocusOut",
98 : "KeymapNotify",
99 : "Expose",
100 : "GraphicsExpose",
101 : "NoExpose",
102 : "VisibilityNotify",
103 : "CreateNotify",
104 : "DestroyNotify",
105 : "UnmapNotify",
106 : "MapNotify",
107 : "MapRequest",
108 : "ReparentNotify",
109 : "ConfigureNotify",
110 : "ConfigureRequest",
111 : "GravityNotify",
112 : "ResizeRequest",
113 : "CirculateNotify",
114 : "CirculateRequest",
115 : "PropertyNotify",
116 : "SelectionClear",
117 : "SelectionRequest",
118 : "SelectionNotify",
119 : "ColormapNotify",
120 : "ClientMessage",
121 : "MappingNotify"
122 : };
123 :
124 : inline const char *Null( const char *p ) { return p ? p : ""; }
125 : inline const char *GetEnv( const char *p ) { return Null( getenv( p ) ); }
126 : inline const char *KeyStr( KeySym n ) { return Null( XKeysymToString( n ) ); }
127 :
128 : inline const char *GetAtomName( Display *d, Atom a )
129 : { return Null( XGetAtomName( d, a ) ); }
130 :
131 : inline double Hypothenuse( long w, long h )
132 : { return sqrt( (double)((w*w)+(h*h)) ); }
133 :
134 0 : inline int ColorDiff( int r, int g, int b )
135 0 : { return (r*r)+(g*g)+(b*b); }
136 :
137 0 : inline int ColorDiff( SalColor c1, int r, int g, int b )
138 0 : { return ColorDiff( (int)SALCOLOR_RED (c1)-r,
139 0 : (int)SALCOLOR_GREEN(c1)-g,
140 0 : (int)SALCOLOR_BLUE (c1)-b ); }
141 :
142 0 : static int sal_Shift( Pixel nMask )
143 : {
144 0 : int i = 24;
145 0 : if( nMask < 0x00010000 ) { nMask <<= 16; i -= 16; }
146 0 : if( nMask < 0x01000000 ) { nMask <<= 8; i -= 8; }
147 0 : if( nMask < 0x10000000 ) { nMask <<= 4; i -= 4; }
148 0 : if( nMask < 0x40000000 ) { nMask <<= 2; i -= 2; }
149 0 : if( nMask < 0x80000000 ) { nMask <<= 1; i -= 1; }
150 0 : return i;
151 : }
152 :
153 0 : static int sal_significantBits( Pixel nMask )
154 : {
155 0 : int nRotate = sizeof(Pixel)*4;
156 0 : int nBits = 0;
157 0 : while( nRotate-- )
158 : {
159 0 : if( nMask & 1 )
160 0 : nBits++;
161 0 : nMask >>= 1;
162 : }
163 0 : return nBits;
164 : }
165 :
166 0 : static sal_Bool sal_GetVisualInfo( Display *pDisplay, XID nVID, XVisualInfo &rVI )
167 : {
168 : int nInfos;
169 : XVisualInfo aTemplate;
170 : XVisualInfo*pInfos;
171 :
172 0 : aTemplate.visualid = nVID;
173 :
174 0 : pInfos = XGetVisualInfo( pDisplay, VisualIDMask, &aTemplate, &nInfos );
175 0 : if( !pInfos )
176 0 : return sal_False;
177 :
178 0 : rVI = *pInfos;
179 0 : XFree( pInfos );
180 :
181 : DBG_ASSERT( rVI.visualid == nVID,
182 : "sal_GetVisualInfo: could not get correct visual by visualId" );
183 0 : return sal_True;
184 : }
185 :
186 : // ---------------------------------------------------------------------------
187 : extern "C" srv_vendor_t
188 0 : sal_GetServerVendor( Display *p_display )
189 : {
190 : typedef struct {
191 : srv_vendor_t e_vendor; // vendor as enum
192 : const char *p_name; // vendor name as returned by VendorString()
193 : unsigned int n_len; // number of chars to compare
194 : } vendor_t;
195 :
196 : const vendor_t p_vendorlist[] = {
197 : { vendor_sun, "Sun Microsystems, Inc.", 10 },
198 : // always the last entry: vendor_none to indicate eol
199 : { vendor_none, NULL, 0 },
200 0 : };
201 :
202 : // handle regular server vendors
203 0 : char *p_name = ServerVendor( p_display );
204 : vendor_t *p_vendor;
205 0 : for (p_vendor = const_cast<vendor_t*>(p_vendorlist); p_vendor->e_vendor != vendor_none; p_vendor++)
206 : {
207 0 : if ( strncmp (p_name, p_vendor->p_name, p_vendor->n_len) == 0 )
208 0 : return p_vendor->e_vendor;
209 : }
210 :
211 : // vendor not found in list
212 0 : return vendor_unknown;
213 : }
214 :
215 0 : sal_Bool SalDisplay::BestVisual( Display *pDisplay,
216 : int nScreen,
217 : XVisualInfo &rVI )
218 : {
219 0 : VisualID nDefVID = XVisualIDFromVisual( DefaultVisual( pDisplay, nScreen ) );
220 0 : VisualID nVID = 0;
221 0 : char *pVID = getenv( "SAL_VISUAL" );
222 0 : if( pVID )
223 0 : sscanf( pVID, "%li", &nVID );
224 :
225 0 : if( nVID && sal_GetVisualInfo( pDisplay, nVID, rVI ) )
226 0 : return rVI.visualid == nDefVID;
227 :
228 : XVisualInfo aVI;
229 0 : aVI.screen = nScreen;
230 : // get all visuals
231 : int nVisuals;
232 : XVisualInfo* pVInfos = XGetVisualInfo( pDisplay, VisualScreenMask,
233 0 : &aVI, &nVisuals );
234 : // pVInfos should contain at least one visual, otherwise
235 : // we're in trouble
236 0 : int* pWeight = (int*)alloca( sizeof(int)*nVisuals );
237 : int i;
238 0 : for( i = 0; i < nVisuals; i++ )
239 : {
240 0 : sal_Bool bUsable = sal_False;
241 0 : int nTrueColor = 1;
242 :
243 0 : if ( pVInfos[i].screen != nScreen )
244 : {
245 0 : bUsable = sal_False;
246 : }
247 0 : else if( pVInfos[i].c_class == TrueColor )
248 : {
249 0 : nTrueColor = 2048;
250 0 : if( pVInfos[i].depth == 24 )
251 0 : bUsable = sal_True;
252 : }
253 0 : else if( pVInfos[i].c_class == PseudoColor )
254 : {
255 0 : bUsable = sal_True;
256 : }
257 0 : pWeight[ i ] = bUsable ? nTrueColor*pVInfos[i].depth : -1024;
258 0 : pWeight[ i ] -= pVInfos[ i ].visualid;
259 : }
260 :
261 0 : int nBestVisual = 0;
262 0 : int nBestWeight = -1024;
263 0 : for( i = 0; i < nVisuals; i++ )
264 : {
265 0 : if( pWeight[ i ] > nBestWeight )
266 : {
267 0 : nBestWeight = pWeight[ i ];
268 0 : nBestVisual = i;
269 : }
270 : }
271 :
272 0 : rVI = pVInfos[ nBestVisual ];
273 :
274 0 : XFree( pVInfos );
275 0 : return rVI.visualid == nDefVID;
276 : }
277 :
278 0 : SalDisplay::SalDisplay( Display *display ) :
279 : mpInputMethod( NULL ),
280 : pDisp_( display ),
281 : m_nXDefaultScreen( 0 ),
282 : m_pWMAdaptor( NULL ),
283 : m_bUseRandRWrapper( true ),
284 0 : m_nLastUserEventTime( CurrentTime )
285 : {
286 : #if OSL_DEBUG_LEVEL > 1
287 : fprintf( stderr, "SalDisplay::SalDisplay()\n" );
288 : #endif
289 0 : SalGenericData *pData = GetGenericData();
290 :
291 0 : pXLib_ = NULL;
292 : DBG_ASSERT( ! pData->GetDisplay(), "Second SalDisplay created !!!\n" );
293 0 : pData->SetDisplay( this );
294 :
295 0 : m_nXDefaultScreen = SalX11Screen( DefaultScreen( pDisp_ ) );
296 0 : }
297 :
298 0 : SalDisplay::~SalDisplay()
299 : {
300 : #if OSL_DEBUG_LEVEL > 1
301 : fprintf( stderr, "SalDisplay::~SalDisplay()\n" );
302 : #endif
303 0 : if( pDisp_ )
304 : {
305 0 : doDestruct();
306 : #if OSL_DEBUG_LEVEL > 1
307 : fprintf( stderr, "display %p closed\n", pDisp_ );
308 : #endif
309 0 : pDisp_ = NULL;
310 : }
311 : // don't do this in doDestruct since RandR extension adds hooks into Display
312 : // that is XCloseDisplay still needs the RandR library if it was used
313 0 : DeInitRandR();
314 0 : }
315 :
316 0 : void SalDisplay::doDestruct()
317 : {
318 0 : SalGenericData *pData = GetGenericData();
319 :
320 0 : delete m_pWMAdaptor;
321 0 : m_pWMAdaptor = NULL;
322 0 : X11SalBitmap::ImplDestroyCache();
323 0 : X11SalGraphics::releaseGlyphPeer();
324 :
325 0 : if( IsDisplay() )
326 : {
327 0 : delete mpInputMethod, mpInputMethod = NULL;
328 0 : delete mpKbdExtension, mpKbdExtension = NULL;
329 :
330 0 : for( unsigned int i = 0; i < m_aScreens.size(); i++ )
331 : {
332 0 : ScreenData& rData = m_aScreens[i];
333 0 : if( rData.m_bInit )
334 : {
335 0 : if( rData.m_aMonoGC != rData.m_aCopyGC )
336 0 : XFreeGC( pDisp_, rData.m_aMonoGC );
337 0 : XFreeGC( pDisp_, rData.m_aCopyGC );
338 0 : XFreeGC( pDisp_, rData.m_aAndInvertedGC );
339 0 : XFreeGC( pDisp_, rData.m_aAndGC );
340 0 : XFreeGC( pDisp_, rData.m_aOrGC );
341 0 : XFreeGC( pDisp_, rData.m_aStippleGC );
342 0 : XFreePixmap( pDisp_, rData.m_hInvert50 );
343 0 : XDestroyWindow( pDisp_, rData.m_aRefWindow );
344 0 : Colormap aColMap = rData.m_aColormap.GetXColormap();
345 0 : if( aColMap != None && aColMap != DefaultColormap( pDisp_, i ) )
346 0 : XFreeColormap( pDisp_, aColMap );
347 : }
348 : }
349 :
350 0 : for( size_t i = 0; i < POINTER_COUNT; i++ )
351 : {
352 0 : if( aPointerCache_[i] )
353 0 : XFreeCursor( pDisp_, aPointerCache_[i] );
354 : }
355 :
356 0 : if( pXLib_ )
357 0 : pXLib_->Remove( ConnectionNumber( pDisp_ ) );
358 : }
359 :
360 0 : if( pData->GetDisplay() == static_cast<const SalGenericDisplay *>( this ) )
361 0 : pData->SetDisplay( NULL );
362 0 : }
363 :
364 0 : static int DisplayHasEvent( int fd, SalX11Display *pDisplay )
365 : {
366 : (void)fd;
367 : DBG_ASSERT( ConnectionNumber( pDisplay->GetDisplay() ) == fd,
368 : "wrong fd in DisplayHasEvent" );
369 0 : if( ! pDisplay->IsDisplay() )
370 0 : return 0;
371 :
372 : int result;
373 :
374 0 : GetSalData()->m_pInstance->GetYieldMutex()->acquire();
375 0 : result = pDisplay->IsEvent();
376 0 : GetSalData()->m_pInstance->GetYieldMutex()->release();
377 0 : return result;
378 : }
379 0 : static int DisplayQueue( int fd, SalX11Display *pDisplay )
380 : {
381 : (void)fd;
382 : DBG_ASSERT( ConnectionNumber( pDisplay->GetDisplay() ) == fd,
383 : "wrong fd in DisplayHasEvent" );
384 : int result;
385 :
386 0 : GetSalData()->m_pInstance->GetYieldMutex()->acquire();
387 : result = XEventsQueued( pDisplay->GetDisplay(),
388 0 : QueuedAfterReading );
389 0 : GetSalData()->m_pInstance->GetYieldMutex()->release();
390 :
391 0 : return result;
392 : }
393 0 : static int DisplayYield( int fd, SalX11Display *pDisplay )
394 : {
395 : (void)fd;
396 : DBG_ASSERT( ConnectionNumber( pDisplay->GetDisplay() ) == fd,
397 : "wrong fd in DisplayHasEvent" );
398 :
399 0 : GetSalData()->m_pInstance->GetYieldMutex()->acquire();
400 0 : pDisplay->Yield();
401 0 : GetSalData()->m_pInstance->GetYieldMutex()->release();
402 0 : return sal_True;
403 : }
404 :
405 0 : SalX11Display::SalX11Display( Display *display )
406 0 : : SalDisplay( display )
407 : {
408 0 : Init();
409 :
410 0 : pXLib_ = GetX11SalData()->GetLib();
411 : pXLib_->Insert( ConnectionNumber( pDisp_ ),
412 : this,
413 : (YieldFunc) DisplayHasEvent,
414 : (YieldFunc) DisplayQueue,
415 0 : (YieldFunc) DisplayYield );
416 0 : }
417 :
418 0 : SalX11Display::~SalX11Display()
419 : {
420 : #if OSL_DEBUG_LEVEL > 1
421 : fprintf( stderr, "SalX11Display::~SalX11Display()\n" );
422 : #endif
423 0 : if( pDisp_ )
424 : {
425 0 : doDestruct();
426 0 : XCloseDisplay( pDisp_ );
427 0 : pDisp_ = NULL;
428 : }
429 0 : }
430 :
431 0 : void SalX11Display::PostUserEvent()
432 : {
433 0 : if( pXLib_ )
434 0 : pXLib_->PostUserEvent();
435 0 : }
436 :
437 : SalDisplay::ScreenData *
438 0 : SalDisplay::initScreen( SalX11Screen nXScreen ) const
439 : {
440 0 : if( nXScreen.getXScreen() >= m_aScreens.size() )
441 0 : nXScreen = m_nXDefaultScreen;
442 0 : ScreenData* pSD = const_cast<ScreenData *>(&m_aScreens[nXScreen.getXScreen()]);
443 0 : if( pSD->m_bInit )
444 0 : return NULL;
445 0 : pSD->m_bInit = true;
446 :
447 : XVisualInfo aVI;
448 : Colormap aColMap;
449 :
450 0 : if( SalDisplay::BestVisual( pDisp_, nXScreen.getXScreen(), aVI ) ) // DefaultVisual
451 0 : aColMap = DefaultColormap( pDisp_, nXScreen.getXScreen() );
452 : else
453 : aColMap = XCreateColormap( pDisp_,
454 0 : RootWindow( pDisp_, nXScreen.getXScreen() ),
455 : aVI.visual,
456 0 : AllocNone );
457 :
458 0 : Screen* pScreen = ScreenOfDisplay( pDisp_, nXScreen.getXScreen() );
459 :
460 0 : pSD->m_aSize = Size( WidthOfScreen( pScreen ), HeightOfScreen( pScreen ) );
461 0 : pSD->m_aRoot = RootWindow( pDisp_, nXScreen.getXScreen() );
462 0 : pSD->m_aVisual = SalVisual( &aVI );
463 0 : pSD->m_aColormap = SalColormap( this, aColMap, nXScreen );
464 :
465 : // we're interested in configure notification of root windows
466 0 : InitRandR( pSD->m_aRoot );
467 :
468 : // - - - - - - - - - - Reference Window/Default Drawable - -
469 : XSetWindowAttributes aXWAttributes;
470 0 : aXWAttributes.border_pixel = 0;
471 0 : aXWAttributes.background_pixel = 0;
472 0 : aXWAttributes.colormap = aColMap;
473 : pSD->m_aRefWindow = XCreateWindow( pDisp_,
474 : pSD->m_aRoot,
475 : 0,0, 16,16, 0,
476 : pSD->m_aVisual.GetDepth(),
477 : InputOutput,
478 : pSD->m_aVisual.GetVisual(),
479 : CWBorderPixel|CWBackPixel|CWColormap,
480 0 : &aXWAttributes );
481 :
482 : // set client leader (session id gets set when session is started)
483 0 : if( pSD->m_aRefWindow )
484 : {
485 : // client leader must have WM_CLIENT_LEADER pointing to itself
486 : XChangeProperty( pDisp_,
487 : pSD->m_aRefWindow,
488 : XInternAtom( pDisp_, "WM_CLIENT_LEADER", False ),
489 : XA_WINDOW,
490 : 32,
491 : PropModeReplace,
492 : (unsigned char*)&pSD->m_aRefWindow,
493 : 1
494 0 : );
495 :
496 0 : OString aExec(OUStringToOString(SessionManagerClient::getExecName(), osl_getThreadTextEncoding()));
497 : const char* argv[1];
498 0 : argv[0] = aExec.getStr();
499 0 : XSetCommand( pDisp_, pSD->m_aRefWindow, const_cast<char**>(argv), 1 );
500 0 : XSelectInput( pDisp_, pSD->m_aRefWindow, PropertyChangeMask );
501 :
502 : // - - - - - - - - - - GCs - - - - - - - - - - - - - - - - -
503 : XGCValues values;
504 0 : values.graphics_exposures = False;
505 0 : values.fill_style = FillOpaqueStippled;
506 0 : values.background = (1<<pSD->m_aVisual.GetDepth())-1;
507 0 : values.foreground = 0;
508 :
509 : pSD->m_aCopyGC = XCreateGC( pDisp_,
510 : pSD->m_aRefWindow,
511 : GCGraphicsExposures
512 : | GCForeground
513 : | GCBackground,
514 0 : &values );
515 : pSD->m_aAndInvertedGC= XCreateGC( pDisp_,
516 : pSD->m_aRefWindow,
517 : GCGraphicsExposures
518 : | GCForeground
519 : | GCBackground,
520 0 : &values );
521 : pSD->m_aAndGC = XCreateGC( pDisp_,
522 : pSD->m_aRefWindow,
523 : GCGraphicsExposures
524 : | GCForeground
525 : | GCBackground,
526 0 : &values );
527 : pSD->m_aOrGC = XCreateGC( pDisp_,
528 : pSD->m_aRefWindow,
529 : GCGraphicsExposures
530 : | GCForeground
531 : | GCBackground,
532 0 : &values );
533 : pSD->m_aStippleGC = XCreateGC( pDisp_,
534 : pSD->m_aRefWindow,
535 : GCGraphicsExposures
536 : | GCFillStyle
537 : | GCForeground
538 : | GCBackground,
539 0 : &values );
540 :
541 0 : XSetFunction( pDisp_, pSD->m_aAndInvertedGC, GXandInverted );
542 0 : XSetFunction( pDisp_, pSD->m_aAndGC, GXand );
543 : // PowerPC Solaris 2.5 (XSun 3500) Bug: GXor = GXnop
544 0 : XSetFunction( pDisp_, pSD->m_aOrGC, GXxor );
545 :
546 0 : if( 1 == pSD->m_aVisual.GetDepth() )
547 : {
548 0 : XSetFunction( pDisp_, pSD->m_aCopyGC, GXcopyInverted );
549 0 : pSD->m_aMonoGC = pSD->m_aCopyGC;
550 : }
551 : else
552 : {
553 0 : Pixmap hPixmap = XCreatePixmap( pDisp_, pSD->m_aRefWindow, 1, 1, 1 );
554 : pSD->m_aMonoGC = XCreateGC( pDisp_,
555 : hPixmap,
556 : GCGraphicsExposures,
557 0 : &values );
558 0 : XFreePixmap( pDisp_, hPixmap );
559 : }
560 : pSD->m_hInvert50 = XCreateBitmapFromData( pDisp_,
561 : pSD->m_aRefWindow,
562 : reinterpret_cast<const char*>(invert50_bits),
563 : invert50_width,
564 0 : invert50_height );
565 : }
566 0 : return pSD;
567 : }
568 :
569 0 : void SalDisplay::Init()
570 : {
571 0 : for( size_t i = 0; i < POINTER_COUNT; i++ )
572 0 : aPointerCache_[i] = None;
573 :
574 0 : mpFactory = (AttributeProvider*)NULL;
575 0 : m_bXinerama = false;
576 :
577 0 : int nDisplayScreens = ScreenCount( pDisp_ );
578 0 : m_aScreens = std::vector<ScreenData>(nDisplayScreens);
579 :
580 0 : mbExactResolution = false;
581 : /* #i15507#
582 : * Xft resolution should take precedence since
583 : * it is what modern desktops use.
584 : */
585 0 : const char* pValStr = XGetDefault( pDisp_, "Xft", "dpi" );
586 0 : if( pValStr != NULL )
587 : {
588 0 : const OString aValStr( pValStr );
589 0 : const long nDPI = (long) aValStr.toDouble();
590 : // guard against insane resolution
591 0 : if( (nDPI >= 50) && (nDPI <= 500) )
592 : {
593 0 : aResolution_ = Pair( nDPI, nDPI );
594 0 : mbExactResolution = true;
595 0 : }
596 : }
597 0 : if( mbExactResolution == false )
598 : {
599 : aResolution_ =
600 0 : Pair( DPI( WidthOfScreen( DefaultScreenOfDisplay( pDisp_ ) ),
601 0 : DisplayWidthMM ( pDisp_, m_nXDefaultScreen.getXScreen() ) ),
602 0 : DPI( HeightOfScreen( DefaultScreenOfDisplay( pDisp_ ) ),
603 0 : DisplayHeightMM( pDisp_, m_nXDefaultScreen.getXScreen() ) ) );
604 : }
605 :
606 0 : nMaxRequestSize_ = XExtendedMaxRequestSize( pDisp_ ) * 4;
607 0 : if( !nMaxRequestSize_ )
608 0 : nMaxRequestSize_ = XMaxRequestSize( pDisp_ ) * 4;
609 :
610 0 : SetServerVendor();
611 0 : X11SalBitmap::ImplCreateCache();
612 :
613 : // - - - - - - - - - - Synchronize - - - - - - - - - - - - -
614 0 : if( getenv( "SAL_SYNCHRONIZE" ) )
615 0 : XSynchronize( pDisp_, True );
616 :
617 : // - - - - - - - - - - Keyboardmapping - - - - - - - - - - -
618 0 : ModifierMapping();
619 :
620 : // - - - - - - - - - - Window Manager - - - - - - - - - - -
621 0 : m_pWMAdaptor = ::vcl_sal::WMAdaptor::createWMAdaptor( this );
622 :
623 0 : InitXinerama();
624 :
625 : #ifdef DBG_UTIL
626 : PrintInfo();
627 : #endif
628 0 : }
629 :
630 0 : void SalX11Display::SetupInput( SalI18N_InputMethod *pInputMethod )
631 : {
632 0 : SetInputMethod( pInputMethod );
633 :
634 0 : GetGenericData()->ErrorTrapPush();
635 0 : SalI18N_KeyboardExtension *pKbdExtension = new SalI18N_KeyboardExtension( pDisp_ );
636 0 : XSync( pDisp_, False );
637 :
638 0 : bool bError = GetGenericData()->ErrorTrapPop( false );
639 0 : GetGenericData()->ErrorTrapPush();
640 0 : pKbdExtension->UseExtension( ! bError );
641 0 : GetGenericData()->ErrorTrapPop();
642 :
643 0 : SetKbdExtension( pKbdExtension );
644 0 : }
645 :
646 : // Sound
647 0 : void SalDisplay::Beep() const
648 : {
649 0 : XBell( pDisp_, 100 );
650 0 : }
651 :
652 : // Keyboard
653 :
654 : namespace {
655 :
656 0 : bool InitXkb(Display* dpy)
657 : {
658 : int nOpcode, nEvent, nError;
659 0 : int nXkbMajor = XkbMajorVersion;
660 0 : int nXkbMinor = XkbMinorVersion;
661 :
662 0 : if (!XkbLibraryVersion(&nXkbMajor, &nXkbMinor))
663 0 : return false;
664 :
665 : return XkbQueryExtension(
666 0 : dpy, &nOpcode, &nEvent, &nError, &nXkbMajor, &nXkbMinor);
667 : }
668 :
669 0 : unsigned int GetKeySymMask(Display* dpy, KeySym nKeySym)
670 : {
671 0 : int nMask = 0;
672 0 : XModifierKeymap* pXmkMap = XGetModifierMapping(dpy);
673 0 : KeyCode nKeyCode = XKeysymToKeycode(dpy, nKeySym);
674 0 : if (nKeyCode == NoSymbol)
675 0 : return 0;
676 :
677 0 : for (int i = 0; i < 8; ++i)
678 : {
679 0 : KeyCode nThisKeyCode = pXmkMap->modifiermap[pXmkMap->max_keypermod*i];
680 0 : if (nThisKeyCode == nKeyCode)
681 0 : nMask = 1 << i;
682 : }
683 0 : XFreeModifiermap(pXmkMap);
684 0 : return nMask;
685 : }
686 :
687 : }
688 :
689 0 : void SalDisplay::SimulateKeyPress( sal_uInt16 nKeyCode )
690 : {
691 0 : if (nKeyCode == KEY_CAPSLOCK)
692 : {
693 0 : Display* dpy = GetDisplay();
694 0 : if (!InitXkb(dpy))
695 0 : return;
696 :
697 0 : unsigned int nMask = GetKeySymMask(dpy, XK_Caps_Lock);
698 : XkbStateRec xkbState;
699 0 : XkbGetState(dpy, XkbUseCoreKbd, &xkbState);
700 0 : unsigned int nCapsLockState = xkbState.locked_mods & nMask;
701 0 : if (nCapsLockState)
702 0 : XkbLockModifiers (dpy, XkbUseCoreKbd, nMask, 0);
703 : else
704 0 : XkbLockModifiers (dpy, XkbUseCoreKbd, nMask, nMask);
705 : }
706 : }
707 :
708 0 : sal_uInt16 SalDisplay::GetIndicatorState() const
709 : {
710 0 : unsigned int _state = 0;
711 0 : sal_uInt16 nState = 0;
712 0 : XkbGetIndicatorState(pDisp_, XkbUseCoreKbd, &_state);
713 :
714 0 : if ((_state & 0x00000001))
715 0 : nState |= INDICATOR_CAPSLOCK;
716 0 : if ((_state & 0x00000002))
717 0 : nState |= INDICATOR_NUMLOCK;
718 0 : if ((_state & 0x00000004))
719 0 : nState |= INDICATOR_SCROLLLOCK;
720 :
721 0 : return nState;
722 : }
723 :
724 0 : OUString SalDisplay::GetKeyNameFromKeySym( KeySym nKeySym ) const
725 : {
726 0 : OUString aLang = Application::GetSettings().GetUILanguageTag().getLanguage();
727 0 : OUString aRet;
728 :
729 : // return an empty string for keysyms that are not bound to
730 : // any key code
731 0 : XLIB_KeyCode aKeyCode = XKeysymToKeycode( GetDisplay(), nKeySym );
732 0 : if( aKeyCode != 0 && aKeyCode != NoSymbol )
733 : {
734 0 : if( !nKeySym )
735 0 : aRet = OUString( "???" );
736 : else
737 : {
738 0 : aRet = ::vcl_sal::getKeysymReplacementName( aLang, nKeySym );
739 0 : if( aRet.isEmpty() )
740 : {
741 0 : const char *pString = XKeysymToString( nKeySym );
742 0 : int n = strlen( pString );
743 0 : if( n > 2 && pString[n-2] == '_' )
744 0 : aRet = OUString( pString, n-2, RTL_TEXTENCODING_ISO_8859_1 );
745 : else
746 0 : aRet = OUString( pString, n, RTL_TEXTENCODING_ISO_8859_1 );
747 : }
748 : }
749 : }
750 0 : return aRet;
751 : }
752 :
753 0 : inline KeySym sal_XModifier2Keysym( Display *pDisplay,
754 : XModifierKeymap *pXModMap,
755 : int n )
756 : {
757 : return XkbKeycodeToKeysym( pDisplay,
758 0 : pXModMap->modifiermap[n*pXModMap->max_keypermod],
759 0 : 0,0 );
760 : }
761 :
762 0 : void SalDisplay::ModifierMapping()
763 : {
764 0 : XModifierKeymap *pXModMap = XGetModifierMapping( pDisp_ );
765 :
766 0 : bNumLockFromXS_ = True;
767 0 : nShiftKeySym_ = sal_XModifier2Keysym( pDisp_, pXModMap, ShiftMapIndex );
768 0 : nCtrlKeySym_ = sal_XModifier2Keysym( pDisp_, pXModMap, ControlMapIndex );
769 0 : nMod1KeySym_ = sal_XModifier2Keysym( pDisp_, pXModMap, Mod1MapIndex );
770 : // on Sun and SCO servers XLookupString does not account for NumLock
771 0 : if( GetServerVendor() == vendor_sun )
772 : {
773 0 : XLIB_KeyCode aNumLock = XKeysymToKeycode( pDisp_, XK_Num_Lock );
774 :
775 0 : if( aNumLock ) for( int i = ShiftMapIndex; i <= Mod5MapIndex; i++ )
776 : {
777 0 : if( pXModMap->modifiermap[i*pXModMap->max_keypermod] == aNumLock )
778 : {
779 0 : bNumLockFromXS_ = False;
780 0 : nNumLockIndex_ = i;
781 0 : nNumLockMask_ = 1<<i;
782 0 : break;
783 : }
784 : }
785 : }
786 :
787 0 : XFreeModifiermap( pXModMap );
788 0 : }
789 :
790 0 : OUString SalDisplay::GetKeyName( sal_uInt16 nKeyCode ) const
791 : {
792 0 : String aStrMap;
793 0 : String aCustomKeyName;
794 :
795 0 : if( nKeyCode & KEY_MOD1 )
796 0 : aStrMap += GetKeyNameFromKeySym( nCtrlKeySym_ );
797 :
798 0 : if( nKeyCode & KEY_MOD2 )
799 : {
800 0 : if( aStrMap.Len() )
801 0 : aStrMap += '+';
802 0 : aStrMap += GetKeyNameFromKeySym( nMod1KeySym_ );
803 : }
804 :
805 0 : if( nKeyCode & KEY_SHIFT )
806 : {
807 0 : if( aStrMap.Len() )
808 0 : aStrMap += '+';
809 0 : aStrMap += GetKeyNameFromKeySym( nShiftKeySym_ );
810 : }
811 0 : nKeyCode &= 0x0FFF;
812 :
813 0 : KeySym nKeySym = 0;
814 :
815 0 : if( KEY_0 <= nKeyCode && nKeyCode <= KEY_9 )
816 0 : nKeySym = XK_0 + (nKeyCode - KEY_0);
817 0 : else if( KEY_A <= nKeyCode && nKeyCode <= KEY_Z )
818 0 : nKeySym = XK_A + (nKeyCode - KEY_A);
819 0 : else if( KEY_F1 <= nKeyCode && nKeyCode <= KEY_F26 ) // does this key exist?
820 0 : nKeySym = XK_F1 + (nKeyCode - KEY_F1);
821 0 : else switch( nKeyCode )
822 : {
823 : case KEY_DOWN:
824 0 : nKeySym = XK_Down;
825 0 : break;
826 : case KEY_UP:
827 0 : nKeySym = XK_Up;
828 0 : break;
829 : case KEY_LEFT:
830 0 : nKeySym = XK_Left;
831 0 : break;
832 : case KEY_RIGHT:
833 0 : nKeySym = XK_Right;
834 0 : break;
835 : case KEY_HOME:
836 0 : nKeySym = XK_Home;
837 0 : break;
838 : case KEY_END:
839 0 : nKeySym = XK_End;
840 0 : break;
841 : case KEY_PAGEUP:
842 0 : nKeySym = XK_Prior;
843 0 : break;
844 : case KEY_PAGEDOWN:
845 0 : nKeySym = XK_Next;
846 0 : break;
847 : case KEY_RETURN:
848 0 : nKeySym = XK_Return;
849 0 : break;
850 : case KEY_ESCAPE:
851 0 : nKeySym = XK_Escape;
852 0 : break;
853 : case KEY_TAB:
854 0 : nKeySym = XK_Tab;
855 0 : break;
856 : case KEY_BACKSPACE:
857 0 : nKeySym = XK_BackSpace;
858 0 : break;
859 : case KEY_SPACE:
860 0 : nKeySym = XK_space;
861 0 : break;
862 : case KEY_INSERT:
863 0 : nKeySym = XK_Insert;
864 0 : break;
865 : case KEY_DELETE:
866 0 : nKeySym = XK_Delete;
867 0 : break;
868 :
869 : #if !defined (SunXK_Undo)
870 : #define SunXK_Props 0x1005FF70
871 : #define SunXK_Front 0x1005FF71
872 : #define SunXK_Copy 0x1005FF72
873 : #define SunXK_Open 0x1005FF73
874 : #define SunXK_Paste 0x1005FF74
875 : #define SunXK_Cut 0x1005FF75
876 : #endif
877 :
878 : case KEY_REPEAT:
879 0 : nKeySym = XK_Redo;
880 0 : break;
881 : case KEY_PROPERTIES:
882 0 : nKeySym = SunXK_Props;
883 0 : break;
884 : case KEY_UNDO:
885 0 : nKeySym = XK_Undo;
886 0 : break;
887 : case KEY_FRONT:
888 0 : nKeySym = SunXK_Front;
889 0 : break;
890 : case KEY_COPY:
891 0 : nKeySym = SunXK_Copy;
892 0 : break;
893 : case KEY_OPEN:
894 0 : nKeySym = SunXK_Open;
895 0 : break;
896 : case KEY_PASTE:
897 0 : nKeySym = SunXK_Paste;
898 0 : break;
899 : case KEY_FIND:
900 0 : nKeySym = XK_Find;
901 0 : break;
902 : case KEY_CUT:
903 0 : nKeySym = GetServerVendor() == vendor_sun ? SunXK_Cut : XK_L10;
904 0 : break;
905 : case KEY_ADD:
906 0 : aCustomKeyName = '+';
907 0 : break;
908 : case KEY_SUBTRACT:
909 0 : aCustomKeyName = '-';
910 0 : break;
911 : case KEY_MULTIPLY:
912 0 : nKeySym = XK_asterisk;
913 0 : break;
914 : case KEY_DIVIDE:
915 0 : nKeySym = XK_slash;
916 0 : break;
917 : case KEY_POINT:
918 0 : aCustomKeyName = '.';
919 0 : break;
920 : case KEY_COMMA:
921 0 : nKeySym = XK_comma;
922 0 : break;
923 : case KEY_LESS:
924 0 : nKeySym = XK_less;
925 0 : break;
926 : case KEY_GREATER:
927 0 : nKeySym = XK_greater;
928 0 : break;
929 : case KEY_EQUAL:
930 0 : nKeySym = XK_equal;
931 0 : break;
932 : case KEY_HELP:
933 0 : nKeySym = XK_Help;
934 0 : break;
935 : case KEY_HANGUL_HANJA:
936 0 : nKeySym = XK_Hangul_Hanja;
937 0 : break;
938 : case KEY_TILDE:
939 0 : nKeySym = XK_asciitilde;
940 0 : break;
941 : case KEY_QUOTELEFT:
942 0 : nKeySym = XK_grave;
943 0 : break;
944 : case KEY_BRACKETLEFT:
945 0 : aCustomKeyName = '[';
946 0 : break;
947 : case KEY_BRACKETRIGHT:
948 0 : aCustomKeyName = ']';
949 0 : break;
950 : case KEY_SEMICOLON:
951 0 : aCustomKeyName = ';';
952 0 : break;
953 :
954 : default:
955 0 : nKeySym = 0;
956 0 : break;
957 : }
958 :
959 0 : if( nKeySym )
960 : {
961 0 : String aKeyName = GetKeyNameFromKeySym( nKeySym );
962 0 : if( aKeyName.Len() )
963 : {
964 0 : if( aStrMap.Len() )
965 0 : aStrMap += '+';
966 0 : aStrMap += aKeyName;
967 : }
968 : else
969 0 : aStrMap.Erase();
970 : }
971 0 : else if (aCustomKeyName.Len())
972 : {
973 : // For semicolumn, bracket left and bracket right, it's better to use
974 : // their keys than their names. (fdo#32891)
975 0 : if (aStrMap.Len())
976 0 : aStrMap += '+';
977 0 : aStrMap += aCustomKeyName;
978 : }
979 : else
980 0 : aStrMap.Erase();
981 :
982 0 : return aStrMap;
983 : }
984 :
985 : #ifndef IsISOKey
986 : #define IsISOKey( n ) (0x0000FE00==((n)&0xFFFFFF00))
987 : #endif
988 :
989 0 : sal_uInt16 SalDisplay::GetKeyCode( KeySym keysym, char*pcPrintable ) const
990 : {
991 0 : sal_uInt16 nKey = 0;
992 :
993 0 : if( XK_a <= keysym && XK_z >= keysym )
994 0 : nKey = (sal_uInt16)(KEY_A + (keysym - XK_a));
995 0 : else if( XK_A <= keysym && XK_Z >= keysym )
996 0 : nKey = (sal_uInt16)(KEY_A + (keysym - XK_A));
997 0 : else if( XK_0 <= keysym && XK_9 >= keysym )
998 0 : nKey = (sal_uInt16)(KEY_0 + (keysym - XK_0));
999 0 : else if( IsModifierKey( keysym ) )
1000 : ;
1001 0 : else if( IsKeypadKey( keysym ) )
1002 : {
1003 0 : if( (keysym >= XK_KP_0) && (keysym <= XK_KP_9) )
1004 : {
1005 0 : nKey = (sal_uInt16)(KEY_0 + (keysym - XK_KP_0));
1006 0 : *pcPrintable = '0' + nKey - KEY_0;
1007 : }
1008 0 : else if( IsPFKey( keysym ) )
1009 0 : nKey = (sal_uInt16)(KEY_F1 + (keysym - XK_KP_F1));
1010 0 : else switch( keysym )
1011 : {
1012 : case XK_KP_Space:
1013 0 : nKey = KEY_SPACE;
1014 0 : *pcPrintable = ' ';
1015 0 : break;
1016 : case XK_KP_Tab:
1017 0 : nKey = KEY_TAB;
1018 0 : break;
1019 : case XK_KP_Enter:
1020 0 : nKey = KEY_RETURN;
1021 0 : break;
1022 : case XK_KP_Begin:
1023 : case XK_KP_Home:
1024 0 : nKey = KEY_HOME;
1025 0 : break;
1026 : case XK_KP_Left:
1027 0 : nKey = KEY_LEFT;
1028 0 : break;
1029 : case XK_KP_Up:
1030 0 : nKey = KEY_UP;
1031 0 : break;
1032 : case XK_KP_Right:
1033 0 : nKey = KEY_RIGHT;
1034 0 : break;
1035 : case XK_KP_Down:
1036 0 : nKey = KEY_DOWN;
1037 0 : break;
1038 : case XK_KP_Prior: // XK_KP_Page_Up
1039 0 : nKey = KEY_PAGEUP;
1040 0 : break;
1041 : case XK_KP_Next: // XK_KP_Page_Down
1042 0 : nKey = KEY_PAGEDOWN;
1043 0 : break;
1044 : case XK_KP_End:
1045 0 : nKey = KEY_END;
1046 0 : break;
1047 : case XK_KP_Insert:
1048 0 : nKey = KEY_INSERT;
1049 0 : break;
1050 : case XK_KP_Delete:
1051 0 : nKey = KEY_DELETE;
1052 0 : break;
1053 : case XK_KP_Equal:
1054 0 : nKey = KEY_EQUAL;
1055 0 : *pcPrintable = '=';
1056 0 : break;
1057 : case XK_KP_Multiply:
1058 0 : nKey = KEY_MULTIPLY;
1059 0 : *pcPrintable = '*';
1060 0 : break;
1061 : case XK_KP_Add:
1062 0 : nKey = KEY_ADD;
1063 0 : *pcPrintable = '+';
1064 0 : break;
1065 : case XK_KP_Separator:
1066 0 : nKey = KEY_DECIMAL;
1067 0 : *pcPrintable = ',';
1068 0 : break;
1069 : case XK_KP_Subtract:
1070 0 : nKey = KEY_SUBTRACT;
1071 0 : *pcPrintable = '-';
1072 0 : break;
1073 : case XK_KP_Decimal:
1074 0 : nKey = KEY_DECIMAL;
1075 0 : *pcPrintable = '.';
1076 0 : break;
1077 : case XK_KP_Divide:
1078 0 : nKey = KEY_DIVIDE;
1079 0 : *pcPrintable = '/';
1080 0 : break;
1081 : }
1082 : }
1083 0 : else if( IsFunctionKey( keysym ) )
1084 : {
1085 0 : if( bNumLockFromXS_ )
1086 : {
1087 0 : if( keysym >= XK_F1 && keysym <= XK_F26 )
1088 0 : nKey = (sal_uInt16)(KEY_F1 + keysym - XK_F1);
1089 : }
1090 0 : else switch( keysym )
1091 : {
1092 : // - - - - - Sun X-Server keyboard without Cursorblock ??? - - -
1093 : case XK_R7: // XK_F27:
1094 0 : nKey = KEY_HOME;
1095 0 : break;
1096 : case XK_R8: // XK_F28:
1097 0 : nKey = KEY_UP;
1098 0 : break;
1099 : case XK_R9: // XK_F29:
1100 0 : nKey = KEY_PAGEUP;
1101 0 : break;
1102 : case XK_R10: // XK_F30:
1103 0 : nKey = KEY_LEFT;
1104 0 : break;
1105 : case XK_R11: // XK_F31:
1106 0 : nKey = 0; // KEY_F31
1107 0 : break;
1108 : case XK_R12: // XK_F32:
1109 0 : nKey = KEY_RIGHT;
1110 0 : break;
1111 : case XK_R13: // XK_F33:
1112 0 : nKey = KEY_END;
1113 0 : break;
1114 : case XK_R14: // XK_F34:
1115 0 : nKey = KEY_DOWN;
1116 0 : break;
1117 : case XK_R15: // XK_F35:
1118 0 : nKey = KEY_PAGEDOWN;
1119 0 : break;
1120 : // - - - - - Sun X-Server keyboard ??? - - - - - - - - - - - -
1121 : case XK_L1: // XK_F11:
1122 0 : nKey = KEY_F11; // on a sun keyboard this actually is usally SunXK_Stop = 0x0000FF69 (XK_Cancel),
1123 : // but VCL doesn't have a key defintion for that
1124 0 : break;
1125 : case XK_L2: // XK_F12:
1126 0 : if ( GetServerVendor() == vendor_sun )
1127 0 : nKey = KEY_REPEAT;
1128 : else
1129 0 : nKey = KEY_F12;
1130 0 : break;
1131 : case XK_L3: // XK_F13:
1132 0 : nKey = KEY_PROPERTIES; // KEY_F13
1133 0 : break;
1134 : case XK_L4: // XK_F14:
1135 0 : nKey = KEY_UNDO; // KEY_F14
1136 0 : break;
1137 : case XK_L5: // XK_F15:
1138 0 : nKey = KEY_F15; // KEY_FRONT
1139 0 : break;
1140 : case XK_L6: // XK_F16:
1141 0 : nKey = KEY_COPY; // KEY_F16
1142 0 : break;
1143 : case XK_L7: // XK_F17:
1144 0 : nKey = KEY_F17; // KEY_OPEN
1145 0 : break;
1146 : case XK_L8: // XK_F18:
1147 0 : nKey = KEY_PASTE; // KEY_F18
1148 0 : break;
1149 : case XK_L9: // XK_F19:
1150 0 : nKey = KEY_F19; // KEY_FIND
1151 0 : break;
1152 : case XK_L10: // XK_F20:
1153 0 : nKey = KEY_CUT; // KEY_F20
1154 0 : break;
1155 : default:
1156 0 : if( keysym >= XK_F1 && keysym <= XK_F26 )
1157 0 : nKey = (sal_uInt16)(KEY_F1 + keysym - XK_F1);
1158 0 : break;
1159 : }
1160 : }
1161 0 : else if( IsCursorKey( keysym ) )
1162 : {
1163 0 : switch( keysym )
1164 : {
1165 : case XK_Begin:
1166 : case XK_Home:
1167 0 : nKey = KEY_HOME;
1168 0 : break;
1169 : case XK_Left:
1170 0 : nKey = KEY_LEFT;
1171 0 : break;
1172 : case XK_Up:
1173 0 : nKey = KEY_UP;
1174 0 : break;
1175 : case XK_Right:
1176 0 : nKey = KEY_RIGHT;
1177 0 : break;
1178 : case XK_Down:
1179 0 : nKey = KEY_DOWN;
1180 0 : break;
1181 : case XK_Prior: // XK_Page_Up
1182 0 : nKey = KEY_PAGEUP;
1183 0 : break;
1184 : case XK_Next: // XK_Page_Down
1185 0 : nKey = KEY_PAGEDOWN;
1186 0 : break;
1187 : case XK_End:
1188 0 : nKey = KEY_END;
1189 0 : break;
1190 : }
1191 : }
1192 0 : else if( IsMiscFunctionKey( keysym ) )
1193 : {
1194 0 : switch( keysym )
1195 : {
1196 : case XK_Insert:
1197 0 : nKey = KEY_INSERT;
1198 0 : break;
1199 : case XK_Redo:
1200 0 : nKey = KEY_REPEAT;
1201 0 : break;
1202 : case XK_Undo:
1203 0 : nKey = KEY_UNDO;
1204 0 : break;
1205 : case XK_Find:
1206 0 : nKey = KEY_FIND;
1207 0 : break;
1208 : case XK_Help:
1209 0 : nKey = KEY_HELP;
1210 0 : break;
1211 : case XK_Menu:
1212 0 : nKey = KEY_CONTEXTMENU;
1213 0 : break;
1214 : }
1215 : }
1216 0 : else if( IsISOKey( keysym ) ) // XK_ISO_
1217 : {
1218 0 : switch( keysym )
1219 : {
1220 : case 0xFE20: // XK_ISO_Left_Tab:
1221 0 : nKey = KEY_TAB;
1222 0 : break;
1223 : }
1224 : }
1225 0 : else switch( keysym )
1226 : {
1227 : case XK_Return:
1228 0 : nKey = KEY_RETURN;
1229 0 : break;
1230 : case XK_BackSpace:
1231 0 : nKey = KEY_BACKSPACE;
1232 0 : break;
1233 : case XK_Delete:
1234 0 : nKey = KEY_DELETE;
1235 0 : break;
1236 : case XK_space:
1237 0 : nKey = KEY_SPACE;
1238 0 : break;
1239 : case XK_Tab:
1240 0 : nKey = KEY_TAB;
1241 0 : break;
1242 : case XK_Escape:
1243 0 : nKey = KEY_ESCAPE;
1244 0 : break;
1245 : case XK_plus:
1246 0 : nKey = KEY_ADD;
1247 0 : break;
1248 : case XK_minus:
1249 0 : nKey = KEY_SUBTRACT;
1250 0 : break;
1251 : case XK_asterisk:
1252 0 : nKey = KEY_MULTIPLY;
1253 0 : break;
1254 : case XK_slash:
1255 0 : nKey = KEY_DIVIDE;
1256 0 : break;
1257 : case XK_period:
1258 0 : nKey = KEY_POINT;
1259 0 : *pcPrintable = '.';
1260 0 : break;
1261 : case XK_comma:
1262 0 : nKey = KEY_COMMA;
1263 0 : break;
1264 : case XK_less:
1265 0 : nKey = KEY_LESS;
1266 0 : break;
1267 : case XK_greater:
1268 0 : nKey = KEY_GREATER;
1269 0 : break;
1270 : case XK_equal:
1271 0 : nKey = KEY_EQUAL;
1272 0 : break;
1273 : case XK_Hangul_Hanja:
1274 0 : nKey = KEY_HANGUL_HANJA;
1275 0 : break;
1276 : case XK_asciitilde:
1277 0 : nKey = KEY_TILDE;
1278 0 : *pcPrintable = '~';
1279 0 : break;
1280 : case XK_grave:
1281 0 : nKey = KEY_QUOTELEFT;
1282 0 : *pcPrintable = '`';
1283 0 : break;
1284 : case XK_bracketleft:
1285 0 : nKey = KEY_BRACKETLEFT;
1286 0 : *pcPrintable = '[';
1287 0 : break;
1288 : case XK_bracketright:
1289 0 : nKey = KEY_BRACKETRIGHT;
1290 0 : *pcPrintable = ']';
1291 0 : break;
1292 : case XK_semicolon:
1293 0 : nKey = KEY_SEMICOLON;
1294 0 : *pcPrintable = ';';
1295 0 : break;
1296 : // - - - - - - - - - - - - - Apollo - - - - - - - - - - - - - 0x1000
1297 : case 0x1000FF02: // apXK_Copy
1298 0 : nKey = KEY_COPY;
1299 0 : break;
1300 : case 0x1000FF03: // apXK_Cut
1301 0 : nKey = KEY_CUT;
1302 0 : break;
1303 : case 0x1000FF04: // apXK_Paste
1304 0 : nKey = KEY_PASTE;
1305 0 : break;
1306 : case 0x1000FF14: // apXK_Repeat
1307 0 : nKey = KEY_REPEAT;
1308 0 : break;
1309 : // Exit, Save
1310 : // - - - - - - - - - - - - - - D E C - - - - - - - - - - - - - 0x1000
1311 : case 0x1000FF00:
1312 0 : nKey = KEY_DELETE;
1313 0 : break;
1314 : // - - - - - - - - - - - - - - H P - - - - - - - - - - - - - 0x1000
1315 : case 0x1000FF73: // hpXK_DeleteChar
1316 0 : nKey = KEY_DELETE;
1317 0 : break;
1318 : case 0x1000FF74: // hpXK_BackTab
1319 : case 0x1000FF75: // hpXK_KP_BackTab
1320 0 : nKey = KEY_TAB;
1321 0 : break;
1322 : // - - - - - - - - - - - - - - I B M - - - - - - - - - - - - -
1323 : // - - - - - - - - - - - - - - O S F - - - - - - - - - - - - - 0x1004
1324 : case 0x1004FF02: // osfXK_Copy
1325 0 : nKey = KEY_COPY;
1326 0 : break;
1327 : case 0x1004FF03: // osfXK_Cut
1328 0 : nKey = KEY_CUT;
1329 0 : break;
1330 : case 0x1004FF04: // osfXK_Paste
1331 0 : nKey = KEY_PASTE;
1332 0 : break;
1333 : case 0x1004FF07: // osfXK_BackTab
1334 0 : nKey = KEY_TAB;
1335 0 : break;
1336 : case 0x1004FF08: // osfXK_BackSpace
1337 0 : nKey = KEY_BACKSPACE;
1338 0 : break;
1339 : case 0x1004FF1B: // osfXK_Escape
1340 0 : nKey = KEY_ESCAPE;
1341 0 : break;
1342 : // Up, Down, Left, Right, PageUp, PageDown
1343 : // - - - - - - - - - - - - - - S C O - - - - - - - - - - - - -
1344 : // - - - - - - - - - - - - - - S G I - - - - - - - - - - - - - 0x1007
1345 : // - - - - - - - - - - - - - - S N I - - - - - - - - - - - - -
1346 : // - - - - - - - - - - - - - - S U N - - - - - - - - - - - - - 0x1005
1347 : case 0x1005FF10: // SunXK_F36
1348 0 : nKey = KEY_F11;
1349 0 : break;
1350 : case 0x1005FF11: // SunXK_F37
1351 0 : nKey = KEY_F12;
1352 0 : break;
1353 : case 0x1005FF70: // SunXK_Props
1354 0 : nKey = KEY_PROPERTIES;
1355 0 : break;
1356 : case 0x1005FF71: // SunXK_Front
1357 0 : nKey = KEY_FRONT;
1358 0 : break;
1359 : case 0x1005FF72: // SunXK_Copy
1360 0 : nKey = KEY_COPY;
1361 0 : break;
1362 : case 0x1005FF73: // SunXK_Open
1363 0 : nKey = KEY_OPEN;
1364 0 : break;
1365 : case 0x1005FF74: // SunXK_Paste
1366 0 : nKey = KEY_PASTE;
1367 0 : break;
1368 : case 0x1005FF75: // SunXK_Cut
1369 0 : nKey = KEY_CUT;
1370 0 : break;
1371 : }
1372 0 : return nKey;
1373 : }
1374 :
1375 0 : KeySym SalDisplay::GetKeySym( XKeyEvent *pEvent,
1376 : unsigned char *pPrintable,
1377 : int *pLen,
1378 : KeySym *pUnmodifiedKeySym,
1379 : Status *pStatusReturn,
1380 : XIC aInputContext ) const
1381 : {
1382 0 : KeySym nKeySym = 0;
1383 0 : memset( pPrintable, 0, *pLen );
1384 0 : *pStatusReturn = 0;
1385 :
1386 : // first get the printable of the possibly modified KeySym
1387 0 : if ( (aInputContext == 0)
1388 0 : || (pEvent->type == KeyRelease)
1389 0 : || (mpInputMethod != NULL && mpInputMethod->PosixLocale()) )
1390 : {
1391 : // XmbLookupString must not be called for KeyRelease events
1392 : // Cannot enter space in c locale problem #89616# #88978# btraq #4478197
1393 0 : *pLen = XLookupString( pEvent, (char*)pPrintable, 1, &nKeySym, NULL );
1394 : }
1395 : else
1396 : {
1397 : *pLen = XmbLookupString( aInputContext,
1398 0 : pEvent, (char*)pPrintable, *pLen - 1, &nKeySym, pStatusReturn );
1399 :
1400 : // Lookup the string again, now with appropriate size
1401 0 : if ( *pStatusReturn == XBufferOverflow )
1402 : {
1403 0 : pPrintable[ 0 ] = (char)0;
1404 0 : return 0;
1405 : }
1406 :
1407 0 : switch ( *pStatusReturn )
1408 : {
1409 : case XBufferOverflow:
1410 : /* unhandled error */
1411 0 : break;
1412 : case XLookupNone:
1413 : /* unhandled error */
1414 0 : break;
1415 : case XLookupKeySym:
1416 : /* this is a strange one: on exceed sometimes
1417 : * no printable is returned for the first char entered,
1418 : * just to retry lookup solves the problem. The problem
1419 : * is not yet fully understood, so restrict 2nd lookup
1420 : * to 7bit ascii chars */
1421 0 : if ( (XK_space <= nKeySym) && (XK_asciitilde >= nKeySym) )
1422 : {
1423 0 : *pLen = 1;
1424 0 : pPrintable[ 0 ] = (char)nKeySym;
1425 : }
1426 0 : break;
1427 : case XLookupBoth:
1428 : case XLookupChars:
1429 :
1430 : /* nothing to, char already in pPrintable */
1431 0 : break;
1432 : }
1433 : }
1434 :
1435 0 : if( !bNumLockFromXS_
1436 0 : && (IsCursorKey(nKeySym)
1437 0 : || IsFunctionKey(nKeySym)
1438 0 : || IsKeypadKey(nKeySym)
1439 0 : || XK_Delete == nKeySym ) )
1440 : {
1441 : // For some X-servers special care is needed for Keypad keys.
1442 : // For example Solaris XServer:
1443 : // 2, 4, 6, 8 are classified as Cursorkeys (Up, Down, Left, Right)
1444 : // 1, 3, 5, 9 are classified as Funtionkeys (F27,F29,F33,F35)
1445 : // 0 as Keypadkey, and the decimal point key not at all (KP_Insert)
1446 0 : KeySym nNewKeySym = XLookupKeysym( pEvent, nNumLockIndex_ );
1447 0 : if( nNewKeySym != NoSymbol )
1448 0 : nKeySym = nNewKeySym;
1449 : }
1450 :
1451 : // Now get the unmodified KeySym for KeyCode retrieval
1452 : // try to strip off modifiers, e.g. Ctrl-$ becomes Ctrl-Shift-4
1453 0 : *pUnmodifiedKeySym = XkbKeycodeToKeysym( GetDisplay(), pEvent->keycode, 0, 0);
1454 :
1455 0 : return nKeySym;
1456 : }
1457 :
1458 : // Pointer
1459 : #define MAKE_BITMAP( name ) \
1460 : XCreateBitmapFromData( pDisp_, \
1461 : DefaultRootWindow( pDisp_ ), \
1462 : reinterpret_cast<const char*>(name##_bits), \
1463 : name##_width, \
1464 : name##_height )
1465 :
1466 : #define MAKE_CURSOR( name ) \
1467 : aCursBitmap = MAKE_BITMAP( name##curs ); \
1468 : aMaskBitmap = MAKE_BITMAP( name##mask ); \
1469 : nXHot = name##curs_x_hot; \
1470 : nYHot = name##curs_y_hot
1471 :
1472 0 : XLIB_Cursor SalDisplay::GetPointer( int ePointerStyle )
1473 : {
1474 0 : if( ePointerStyle >= POINTER_COUNT )
1475 0 : return 0;
1476 :
1477 0 : XLIB_Cursor &aCur = aPointerCache_[ePointerStyle];
1478 :
1479 0 : if( aCur != None )
1480 0 : return aCur;
1481 :
1482 0 : Pixmap aCursBitmap = None, aMaskBitmap = None;
1483 0 : unsigned int nXHot = 0, nYHot = 0;
1484 :
1485 0 : switch( ePointerStyle )
1486 : {
1487 : case POINTER_NULL:
1488 0 : MAKE_CURSOR( null );
1489 0 : break;
1490 : case POINTER_ARROW:
1491 0 : aCur = XCreateFontCursor( pDisp_, XC_left_ptr );
1492 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1493 0 : break;
1494 : case POINTER_WAIT:
1495 0 : aCur = XCreateFontCursor( pDisp_, XC_watch );
1496 0 : break;
1497 : case POINTER_TEXT: // Mouse Pointer is a "I" Beam
1498 0 : aCur = XCreateFontCursor( pDisp_, XC_xterm );
1499 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1500 0 : break;
1501 : case POINTER_HELP:
1502 0 : aCur = XCreateFontCursor( pDisp_, XC_question_arrow );
1503 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1504 0 : break;
1505 : case POINTER_CROSS: // Mouse Pointer is a cross
1506 0 : aCur = XCreateFontCursor( pDisp_, XC_crosshair );
1507 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1508 0 : break;
1509 : case POINTER_NSIZE:
1510 0 : aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow );
1511 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1512 0 : break;
1513 : case POINTER_SSIZE:
1514 0 : aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow );
1515 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1516 0 : break;
1517 : case POINTER_WSIZE:
1518 0 : aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow );
1519 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1520 0 : break;
1521 : case POINTER_ESIZE:
1522 0 : aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow );
1523 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1524 0 : break;
1525 : case POINTER_WINDOW_NSIZE:
1526 0 : aCur = XCreateFontCursor( pDisp_, XC_top_side );
1527 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1528 0 : break;
1529 : case POINTER_WINDOW_SSIZE:
1530 0 : aCur = XCreateFontCursor( pDisp_, XC_bottom_side );
1531 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1532 0 : break;
1533 : case POINTER_WINDOW_WSIZE:
1534 0 : aCur = XCreateFontCursor( pDisp_, XC_left_side );
1535 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1536 0 : break;
1537 : case POINTER_WINDOW_ESIZE:
1538 0 : aCur = XCreateFontCursor( pDisp_, XC_right_side );
1539 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1540 0 : break;
1541 : case POINTER_NWSIZE:
1542 0 : aCur = XCreateFontCursor( pDisp_, XC_top_left_corner );
1543 0 : break;
1544 : case POINTER_NESIZE:
1545 0 : aCur = XCreateFontCursor( pDisp_, XC_top_right_corner );
1546 0 : break;
1547 : case POINTER_SWSIZE:
1548 0 : aCur = XCreateFontCursor( pDisp_, XC_bottom_left_corner );
1549 0 : break;
1550 : case POINTER_SESIZE:
1551 0 : aCur = XCreateFontCursor( pDisp_, XC_bottom_right_corner );
1552 0 : break;
1553 : case POINTER_WINDOW_NWSIZE:
1554 0 : aCur = XCreateFontCursor( pDisp_, XC_top_left_corner );
1555 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1556 0 : break;
1557 : case POINTER_WINDOW_NESIZE:
1558 0 : aCur = XCreateFontCursor( pDisp_, XC_top_right_corner );
1559 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1560 0 : break;
1561 : case POINTER_WINDOW_SWSIZE:
1562 0 : aCur = XCreateFontCursor( pDisp_, XC_bottom_left_corner );
1563 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1564 0 : break;
1565 : case POINTER_WINDOW_SESIZE:
1566 0 : aCur = XCreateFontCursor( pDisp_, XC_bottom_right_corner );
1567 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1568 0 : break;
1569 : case POINTER_HSPLIT:
1570 0 : aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow );
1571 0 : break;
1572 : case POINTER_VSPLIT:
1573 0 : aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow );
1574 0 : break;
1575 : case POINTER_HSIZEBAR:
1576 0 : aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow ); // ???
1577 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1578 0 : break;
1579 : case POINTER_VSIZEBAR:
1580 0 : aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow ); // ???
1581 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1582 0 : break;
1583 : case POINTER_REFHAND:
1584 0 : aCur = XCreateFontCursor( pDisp_, XC_hand1 );
1585 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1586 0 : break;
1587 : case POINTER_HAND:
1588 0 : aCur = XCreateFontCursor( pDisp_, XC_hand2 );
1589 0 : break;
1590 : case POINTER_MAGNIFY:
1591 0 : MAKE_CURSOR( magnify_ );
1592 0 : break;
1593 : case POINTER_FILL:
1594 0 : MAKE_CURSOR( fill_ );
1595 0 : break;
1596 : case POINTER_MOVE:
1597 0 : aCur = XCreateFontCursor( pDisp_, XC_fleur );
1598 0 : break;
1599 : case POINTER_MOVEDATA:
1600 0 : MAKE_CURSOR( movedata_ );
1601 0 : break;
1602 : case POINTER_COPYDATA:
1603 0 : MAKE_CURSOR( copydata_ );
1604 0 : break;
1605 : case POINTER_MOVEFILE:
1606 0 : MAKE_CURSOR( movefile_ );
1607 0 : break;
1608 : case POINTER_COPYFILE:
1609 0 : MAKE_CURSOR( copyfile_ );
1610 0 : break;
1611 : case POINTER_MOVEFILES:
1612 0 : MAKE_CURSOR( movefiles_ );
1613 0 : break;
1614 : case POINTER_COPYFILES:
1615 0 : MAKE_CURSOR( copyfiles_ );
1616 0 : break;
1617 : case POINTER_NOTALLOWED:
1618 0 : MAKE_CURSOR( nodrop_ );
1619 0 : break;
1620 : case POINTER_ROTATE:
1621 0 : MAKE_CURSOR( rotate_ );
1622 0 : break;
1623 : case POINTER_HSHEAR:
1624 0 : MAKE_CURSOR( hshear_ );
1625 0 : break;
1626 : case POINTER_VSHEAR:
1627 0 : MAKE_CURSOR( vshear_ );
1628 0 : break;
1629 : case POINTER_DRAW_LINE:
1630 0 : MAKE_CURSOR( drawline_ );
1631 0 : break;
1632 : case POINTER_DRAW_RECT:
1633 0 : MAKE_CURSOR( drawrect_ );
1634 0 : break;
1635 : case POINTER_DRAW_POLYGON:
1636 0 : MAKE_CURSOR( drawpolygon_ );
1637 0 : break;
1638 : case POINTER_DRAW_BEZIER:
1639 0 : MAKE_CURSOR( drawbezier_ );
1640 0 : break;
1641 : case POINTER_DRAW_ARC:
1642 0 : MAKE_CURSOR( drawarc_ );
1643 0 : break;
1644 : case POINTER_DRAW_PIE:
1645 0 : MAKE_CURSOR( drawpie_ );
1646 0 : break;
1647 : case POINTER_DRAW_CIRCLECUT:
1648 0 : MAKE_CURSOR( drawcirclecut_ );
1649 0 : break;
1650 : case POINTER_DRAW_ELLIPSE:
1651 0 : MAKE_CURSOR( drawellipse_ );
1652 0 : break;
1653 : case POINTER_DRAW_CONNECT:
1654 0 : MAKE_CURSOR( drawconnect_ );
1655 0 : break;
1656 : case POINTER_DRAW_TEXT:
1657 0 : MAKE_CURSOR( drawtext_ );
1658 0 : break;
1659 : case POINTER_MIRROR:
1660 0 : MAKE_CURSOR( mirror_ );
1661 0 : break;
1662 : case POINTER_CROOK:
1663 0 : MAKE_CURSOR( crook_ );
1664 0 : break;
1665 : case POINTER_CROP:
1666 0 : MAKE_CURSOR( crop_ );
1667 0 : break;
1668 : case POINTER_MOVEPOINT:
1669 0 : MAKE_CURSOR( movepoint_ );
1670 0 : break;
1671 : case POINTER_MOVEBEZIERWEIGHT:
1672 0 : MAKE_CURSOR( movebezierweight_ );
1673 0 : break;
1674 : case POINTER_DRAW_FREEHAND:
1675 0 : MAKE_CURSOR( drawfreehand_ );
1676 0 : break;
1677 : case POINTER_DRAW_CAPTION:
1678 0 : MAKE_CURSOR( drawcaption_ );
1679 0 : break;
1680 : case POINTER_PEN: // Mouse Pointer is a pencil
1681 0 : aCur = XCreateFontCursor( pDisp_, XC_pencil );
1682 : DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" );
1683 0 : break;
1684 : case POINTER_LINKDATA:
1685 0 : MAKE_CURSOR( linkdata_ );
1686 0 : break;
1687 : case POINTER_MOVEDATALINK:
1688 0 : MAKE_CURSOR( movedlnk_ );
1689 0 : break;
1690 : case POINTER_COPYDATALINK:
1691 0 : MAKE_CURSOR( copydlnk_ );
1692 0 : break;
1693 : case POINTER_LINKFILE:
1694 0 : MAKE_CURSOR( linkfile_ );
1695 0 : break;
1696 : case POINTER_MOVEFILELINK:
1697 0 : MAKE_CURSOR( moveflnk_ );
1698 0 : break;
1699 : case POINTER_COPYFILELINK:
1700 0 : MAKE_CURSOR( copyflnk_ );
1701 0 : break;
1702 : case POINTER_CHART:
1703 0 : MAKE_CURSOR( chart_ );
1704 0 : break;
1705 : case POINTER_DETECTIVE:
1706 0 : MAKE_CURSOR( detective_ );
1707 0 : break;
1708 : case POINTER_PIVOT_COL:
1709 0 : MAKE_CURSOR( pivotcol_ );
1710 0 : break;
1711 : case POINTER_PIVOT_ROW:
1712 0 : MAKE_CURSOR( pivotrow_ );
1713 0 : break;
1714 : case POINTER_PIVOT_FIELD:
1715 0 : MAKE_CURSOR( pivotfld_ );
1716 0 : break;
1717 : case POINTER_PIVOT_DELETE:
1718 0 : MAKE_CURSOR( pivotdel_ );
1719 0 : break;
1720 : case POINTER_CHAIN:
1721 0 : MAKE_CURSOR( chain_ );
1722 0 : break;
1723 : case POINTER_CHAIN_NOTALLOWED:
1724 0 : MAKE_CURSOR( chainnot_ );
1725 0 : break;
1726 : case POINTER_TIMEEVENT_MOVE:
1727 0 : MAKE_CURSOR( timemove_ );
1728 0 : break;
1729 : case POINTER_TIMEEVENT_SIZE:
1730 0 : MAKE_CURSOR( timesize_ );
1731 0 : break;
1732 : case POINTER_AUTOSCROLL_N:
1733 0 : MAKE_CURSOR(asn_ );
1734 0 : break;
1735 : case POINTER_AUTOSCROLL_S:
1736 0 : MAKE_CURSOR( ass_ );
1737 0 : break;
1738 : case POINTER_AUTOSCROLL_W:
1739 0 : MAKE_CURSOR( asw_ );
1740 0 : break;
1741 : case POINTER_AUTOSCROLL_E:
1742 0 : MAKE_CURSOR( ase_ );
1743 0 : break;
1744 : case POINTER_AUTOSCROLL_NW:
1745 0 : MAKE_CURSOR( asnw_ );
1746 0 : break;
1747 : case POINTER_AUTOSCROLL_NE:
1748 0 : MAKE_CURSOR( asne_ );
1749 0 : break;
1750 : case POINTER_AUTOSCROLL_SW:
1751 0 : MAKE_CURSOR( assw_ );
1752 0 : break;
1753 : case POINTER_AUTOSCROLL_SE:
1754 0 : MAKE_CURSOR( asse_ );
1755 0 : break;
1756 : case POINTER_AUTOSCROLL_NS:
1757 0 : MAKE_CURSOR( asns_ );
1758 0 : break;
1759 : case POINTER_AUTOSCROLL_WE:
1760 0 : MAKE_CURSOR( aswe_ );
1761 0 : break;
1762 : case POINTER_AUTOSCROLL_NSWE:
1763 0 : MAKE_CURSOR( asnswe_ );
1764 0 : break;
1765 : case POINTER_AIRBRUSH:
1766 0 : MAKE_CURSOR( airbrush_ );
1767 0 : break;
1768 : case POINTER_TEXT_VERTICAL:
1769 0 : MAKE_CURSOR( vertcurs_ );
1770 0 : break;
1771 :
1772 : // #i32329# Enhanced table selection
1773 : case POINTER_TAB_SELECT_S:
1774 0 : MAKE_CURSOR( tblsels_ );
1775 0 : break;
1776 : case POINTER_TAB_SELECT_E:
1777 0 : MAKE_CURSOR( tblsele_ );
1778 0 : break;
1779 : case POINTER_TAB_SELECT_SE:
1780 0 : MAKE_CURSOR( tblselse_ );
1781 0 : break;
1782 : case POINTER_TAB_SELECT_W:
1783 0 : MAKE_CURSOR( tblselw_ );
1784 0 : break;
1785 : case POINTER_TAB_SELECT_SW:
1786 0 : MAKE_CURSOR( tblselsw_ );
1787 0 : break;
1788 :
1789 : // #i20119# Paintbrush tool
1790 : case POINTER_PAINTBRUSH :
1791 0 : MAKE_CURSOR( paintbrush_ );
1792 0 : break;
1793 :
1794 : default:
1795 : OSL_FAIL("pointer not implemented");
1796 0 : aCur = XCreateFontCursor( pDisp_, XC_arrow );
1797 0 : break;
1798 : }
1799 :
1800 0 : if( None == aCur )
1801 : {
1802 : XColor aBlack, aWhite, aDummy;
1803 0 : Colormap hColormap = GetColormap(m_nXDefaultScreen).GetXColormap();
1804 :
1805 0 : XAllocNamedColor( pDisp_, hColormap, "black", &aBlack, &aDummy );
1806 0 : XAllocNamedColor( pDisp_, hColormap, "white", &aWhite, &aDummy );
1807 :
1808 : aCur = XCreatePixmapCursor( pDisp_,
1809 : aCursBitmap, aMaskBitmap,
1810 : &aBlack, &aWhite,
1811 0 : nXHot, nYHot );
1812 :
1813 0 : XFreePixmap( pDisp_, aCursBitmap );
1814 0 : XFreePixmap( pDisp_, aMaskBitmap );
1815 : }
1816 :
1817 0 : return aCur;
1818 : }
1819 :
1820 0 : int SalDisplay::CaptureMouse( SalFrame *pCapture )
1821 : {
1822 0 : static const char* pEnv = getenv( "SAL_NO_MOUSEGRABS" );
1823 :
1824 0 : if( !pCapture )
1825 : {
1826 0 : m_pCapture = NULL;
1827 0 : if( !pEnv || !*pEnv )
1828 0 : XUngrabPointer( GetDisplay(), CurrentTime );
1829 0 : XFlush( GetDisplay() );
1830 0 : return 0;
1831 : }
1832 :
1833 0 : m_pCapture = NULL;
1834 :
1835 : // FIXME: get rid of X11SalFrame
1836 0 : const SystemEnvData* pEnvData = pCapture->GetSystemData();
1837 0 : if( !pEnv || !*pEnv )
1838 : {
1839 : int ret = XGrabPointer( GetDisplay(),
1840 : (XLIB_Window)pEnvData->aWindow,
1841 : False,
1842 : PointerMotionMask| ButtonPressMask|ButtonReleaseMask,
1843 : GrabModeAsync,
1844 : GrabModeAsync,
1845 : None,
1846 : static_cast<X11SalFrame*>(pCapture)->GetCursor(),
1847 0 : CurrentTime );
1848 :
1849 0 : if( ret != GrabSuccess )
1850 : {
1851 : DBG_ASSERT( 1, "SalDisplay::CaptureMouse could not grab pointer\n");
1852 0 : return -1;
1853 : }
1854 : }
1855 :
1856 0 : m_pCapture = pCapture;
1857 0 : return 1;
1858 : }
1859 :
1860 : // Events
1861 :
1862 0 : sal_Bool SalX11Display::IsEvent()
1863 : {
1864 0 : if( HasUserEvents() || XEventsQueued( pDisp_, QueuedAlready ) )
1865 0 : return sal_True;
1866 :
1867 0 : XFlush( pDisp_ );
1868 0 : return sal_False;
1869 : }
1870 :
1871 0 : void SalX11Display::Yield()
1872 : {
1873 0 : if( DispatchInternalEvent() )
1874 0 : return;
1875 :
1876 : XEvent aEvent;
1877 : DBG_ASSERT( static_cast<SalYieldMutex*>(GetSalData()->m_pInstance->GetYieldMutex())->GetThreadId() ==
1878 : osl::Thread::getCurrentIdentifier(),
1879 : "will crash soon since solar mutex not locked in SalDisplay::Yield" );
1880 :
1881 0 : XNextEvent( pDisp_, &aEvent );
1882 :
1883 0 : Dispatch( &aEvent );
1884 :
1885 : #ifdef DBG_UTIL
1886 : if( GetX11SalData()->HasXErrorOccurred() )
1887 : {
1888 : XFlush( pDisp_ );
1889 : DbgPrintDisplayEvent("SalDisplay::Yield (WasXError)", &aEvent);
1890 : }
1891 : #endif
1892 0 : GetX11SalData()->ResetXErrorOccurred();
1893 : }
1894 :
1895 0 : long SalX11Display::Dispatch( XEvent *pEvent )
1896 : {
1897 0 : if( pEvent->type == XLIB_KeyPress || pEvent->type == KeyRelease )
1898 : {
1899 0 : XLIB_Window aWindow = pEvent->xkey.window;
1900 :
1901 0 : std::list< SalFrame* >::const_iterator it;
1902 0 : for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it )
1903 : {
1904 0 : const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it);
1905 0 : if( pFrame->GetWindow() == aWindow || pFrame->GetShellWindow() == aWindow )
1906 : {
1907 0 : aWindow = pFrame->GetWindow();
1908 0 : break;
1909 : }
1910 : }
1911 0 : if( it != m_aFrames.end() )
1912 : {
1913 0 : if ( mpInputMethod->FilterEvent( pEvent , aWindow ) )
1914 0 : return 0;
1915 0 : }
1916 : }
1917 : else
1918 0 : if ( mpInputMethod->FilterEvent( pEvent, None ) )
1919 0 : return 0;
1920 :
1921 0 : SalInstance* pInstance = GetSalData()->m_pInstance;
1922 0 : pInstance->CallEventCallback( pEvent, sizeof( XEvent ) );
1923 :
1924 0 : switch( pEvent->type )
1925 : {
1926 : case MotionNotify:
1927 0 : while( XCheckWindowEvent( pEvent->xany.display,
1928 : pEvent->xany.window,
1929 : ButtonMotionMask,
1930 0 : pEvent ) )
1931 : ;
1932 0 : m_nLastUserEventTime = pEvent->xmotion.time;
1933 0 : break;
1934 : case PropertyNotify:
1935 0 : if( pEvent->xproperty.atom == getWMAdaptor()->getAtom( WMAdaptor::VCL_SYSTEM_SETTINGS ) )
1936 : {
1937 0 : for( unsigned int i = 0; i < m_aScreens.size(); i++ )
1938 : {
1939 0 : if( pEvent->xproperty.window == m_aScreens[i].m_aRefWindow )
1940 : {
1941 0 : std::list< SalFrame* >::const_iterator it;
1942 0 : for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it )
1943 0 : (*it)->CallCallback( SALEVENT_SETTINGSCHANGED, NULL );
1944 0 : return 0;
1945 : }
1946 : }
1947 : }
1948 0 : break;
1949 : case MappingNotify:
1950 0 : if( MappingModifier == pEvent->xmapping.request )
1951 : {
1952 0 : XRefreshKeyboardMapping( &pEvent->xmapping );
1953 0 : ModifierMapping();
1954 : }
1955 0 : break;
1956 : case ButtonPress:
1957 : case ButtonRelease:
1958 0 : m_nLastUserEventTime = pEvent->xbutton.time;
1959 0 : break;
1960 : case XLIB_KeyPress:
1961 : case KeyRelease:
1962 0 : m_nLastUserEventTime = pEvent->xkey.time;
1963 0 : break;
1964 : default:
1965 :
1966 0 : if ( GetKbdExtension()->UseExtension()
1967 0 : && GetKbdExtension()->GetEventBase() == pEvent->type )
1968 : {
1969 0 : GetKbdExtension()->Dispatch( pEvent );
1970 0 : return 1;
1971 : }
1972 0 : break;
1973 : }
1974 :
1975 0 : std::list< SalFrame* >::iterator it;
1976 0 : for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it )
1977 : {
1978 0 : X11SalFrame* pFrame = static_cast< X11SalFrame* >(*it);
1979 0 : XLIB_Window aDispatchWindow = pEvent->xany.window;
1980 0 : if( pFrame->GetWindow() == aDispatchWindow
1981 0 : || pFrame->GetShellWindow() == aDispatchWindow
1982 0 : || pFrame->GetForeignParent() == aDispatchWindow
1983 : )
1984 : {
1985 0 : return pFrame->Dispatch( pEvent );
1986 : }
1987 0 : if( pEvent->type == ConfigureNotify && pEvent->xconfigure.window == pFrame->GetStackingWindow() )
1988 : {
1989 0 : return pFrame->Dispatch( pEvent );
1990 : }
1991 : }
1992 :
1993 : // dispatch to salobjects
1994 0 : X11SalObject::Dispatch( pEvent );
1995 :
1996 : // is this perhaps a root window that changed size ?
1997 0 : processRandREvent( pEvent );
1998 :
1999 0 : return 0;
2000 : }
2001 :
2002 : #ifdef DBG_UTIL
2003 : void SalDisplay::DbgPrintDisplayEvent(const char *pComment, XEvent *pEvent) const
2004 : {
2005 : if( pEvent->type <= MappingNotify )
2006 : {
2007 : fprintf( stderr, "[%s] %s s=%d w=%ld\n",
2008 : pComment,
2009 : EventNames[pEvent->type],
2010 : pEvent->xany.send_event,
2011 : pEvent->xany.window );
2012 :
2013 : switch( pEvent->type )
2014 : {
2015 : case XLIB_KeyPress:
2016 : case KeyRelease:
2017 : fprintf( stderr, "\t\ts=%d c=%d\n",
2018 : pEvent->xkey.state,
2019 : pEvent->xkey.keycode );
2020 : break;
2021 :
2022 : case ButtonPress:
2023 : case ButtonRelease:
2024 : fprintf( stderr, "\t\ts=%d b=%d x=%d y=%d rx=%d ry=%d\n",
2025 : pEvent->xbutton.state,
2026 : pEvent->xbutton.button,
2027 : pEvent->xbutton.x,
2028 : pEvent->xbutton.y,
2029 : pEvent->xbutton.x_root,
2030 : pEvent->xbutton.y_root );
2031 : break;
2032 :
2033 : case MotionNotify:
2034 : fprintf( stderr, "\t\ts=%d x=%d y=%d\n",
2035 : pEvent->xmotion.state,
2036 : pEvent->xmotion.x,
2037 : pEvent->xmotion.y );
2038 : break;
2039 :
2040 : case EnterNotify:
2041 : case LeaveNotify:
2042 : fprintf( stderr, "\t\tm=%d f=%d x=%d y=%d\n",
2043 : pEvent->xcrossing.mode,
2044 : pEvent->xcrossing.focus,
2045 : pEvent->xcrossing.x,
2046 : pEvent->xcrossing.y );
2047 : break;
2048 :
2049 : case FocusIn:
2050 : case FocusOut:
2051 : fprintf( stderr, "\t\tm=%d d=%d\n",
2052 : pEvent->xfocus.mode,
2053 : pEvent->xfocus.detail );
2054 : break;
2055 :
2056 : case Expose:
2057 : case GraphicsExpose:
2058 : fprintf( stderr, "\t\tc=%d %d*%d %d+%d\n",
2059 : pEvent->xexpose.count,
2060 : pEvent->xexpose.width,
2061 : pEvent->xexpose.height,
2062 : pEvent->xexpose.x,
2063 : pEvent->xexpose.y );
2064 : break;
2065 :
2066 : case VisibilityNotify:
2067 : fprintf( stderr, "\t\ts=%d\n",
2068 : pEvent->xvisibility.state );
2069 : break;
2070 :
2071 : case CreateNotify:
2072 : case DestroyNotify:
2073 : break;
2074 :
2075 : case MapNotify:
2076 : case UnmapNotify:
2077 : break;
2078 :
2079 : case ReparentNotify:
2080 : fprintf( stderr, "\t\tp=%d x=%d y=%d\n",
2081 : sal::static_int_cast< int >(pEvent->xreparent.parent),
2082 : pEvent->xreparent.x,
2083 : pEvent->xreparent.y );
2084 : break;
2085 :
2086 : case ConfigureNotify:
2087 : fprintf( stderr, "\t\tb=%d %d*%d %d+%d\n",
2088 : pEvent->xconfigure.border_width,
2089 : pEvent->xconfigure.width,
2090 : pEvent->xconfigure.height,
2091 : pEvent->xconfigure.x,
2092 : pEvent->xconfigure.y );
2093 : break;
2094 :
2095 : case PropertyNotify:
2096 : fprintf( stderr, "\t\ta=%s (0x%X)\n",
2097 : GetAtomName( pDisp_, pEvent->xproperty.atom ),
2098 : sal::static_int_cast< unsigned int >(
2099 : pEvent->xproperty.atom) );
2100 : break;
2101 :
2102 : case ColormapNotify:
2103 : fprintf( stderr, "\t\tc=%ld n=%d s=%d\n",
2104 : pEvent->xcolormap.colormap,
2105 : pEvent->xcolormap.c_new,
2106 : pEvent->xcolormap.state );
2107 : break;
2108 :
2109 : case ClientMessage:
2110 : fprintf( stderr, "\t\ta=%s (0x%X) f=%i [0x%lX,0x%lX,0x%lX,0x%lX,0x%lX])\n",
2111 : GetAtomName( pDisp_, pEvent->xclient.message_type ),
2112 : sal::static_int_cast< unsigned int >(
2113 : pEvent->xclient.message_type),
2114 : pEvent->xclient.format,
2115 : pEvent->xclient.data.l[0],
2116 : pEvent->xclient.data.l[1],
2117 : pEvent->xclient.data.l[2],
2118 : pEvent->xclient.data.l[3],
2119 : pEvent->xclient.data.l[4] );
2120 : break;
2121 :
2122 : case MappingNotify:
2123 : fprintf( stderr, "\t\tr=%sd\n",
2124 : MappingModifier == pEvent->xmapping.request
2125 : ? "MappingModifier"
2126 : : MappingKeyboard == pEvent->xmapping.request
2127 : ? "MappingKeyboard"
2128 : : "MappingPointer" );
2129 :
2130 : break;
2131 : }
2132 : }
2133 : else
2134 : fprintf( stderr, "[%s] %d s=%d w=%ld\n",
2135 : pComment,
2136 : pEvent->type,
2137 : pEvent->xany.send_event,
2138 : pEvent->xany.window );
2139 : }
2140 : #endif
2141 :
2142 0 : void SalDisplay::PrintInfo() const
2143 : {
2144 0 : if( IsDisplay() )
2145 : {
2146 : SAL_INFO( "vcl", "Environment" );
2147 : SAL_INFO( "vcl", "\t$DISPLAY \t\"" << GetEnv( "DISPLAY" ) << "\"");
2148 : SAL_INFO( "vcl", "\t$SAL_VISUAL \t\"" << GetEnv( "SAL_VISUAL" ) << "\"");
2149 : SAL_INFO( "vcl", "\t$SAL_IGNOREXERRORS\t\"" << GetEnv( "SAL_IGNOREXERRORS" ) << "\"");
2150 : SAL_INFO( "vcl", "\t$SAL_PROPERTIES \t\"" << GetEnv( "SAL_PROPERTIES" ) << "\"");
2151 : SAL_INFO( "vcl", "\t$SAL_SYNCHRONIZE \t\"" << GetEnv( "SAL_SYNCHRONIZE" ) << "\"");
2152 :
2153 : char sHostname[ 120 ];
2154 0 : gethostname (sHostname, 120 );
2155 : SAL_INFO( "vcl", "Client\n" );
2156 : SAL_INFO( "vcl", "\tHost \t\"" << sHostname << "\"");
2157 :
2158 : SAL_INFO( "vcl", "Display" );
2159 : SAL_INFO( "vcl", "\tHost \t\"" << DisplayString(pDisp_) << "\"");
2160 : SAL_INFO( "vcl", "\tVendor (Release) \t\"" << ServerVendor(pDisp_) << " (" << VendorRelease(pDisp_) << ")\"");
2161 : SAL_INFO( "vcl", "\tProtocol \t" << ProtocolVersion(pDisp_) << "." << ProtocolRevision(pDisp_) );
2162 : SAL_INFO( "vcl", "\tScreen (count,def)\t" << m_nXDefaultScreen.getXScreen() << " (" << ScreenCount(pDisp_) << "," << DefaultScreen(pDisp_) << ")");
2163 : SAL_INFO( "vcl", "\tshift ctrl alt \t" << KeyStr( nShiftKeySym_ ) << " (0x" << std::hex << sal::static_int_cast< unsigned int >(nShiftKeySym_) << ") "
2164 : << KeyStr( nCtrlKeySym_ ) << " (0x" << sal::static_int_cast< unsigned int >(nCtrlKeySym_) << ") "
2165 : << KeyStr( nMod1KeySym_ ) << " (0x" << sal::static_int_cast< unsigned int >(nMod1KeySym_) << ")");
2166 0 : if( XExtendedMaxRequestSize(pDisp_) * 4 )
2167 : SAL_INFO( "vcl", "\tXMaxRequestSize \t" << XMaxRequestSize(pDisp_) * 4 << " " << XExtendedMaxRequestSize(pDisp_) * 4 << " [bytes]");
2168 0 : if( GetProperties() != PROPERTY_DEFAULT )
2169 : SAL_INFO( "vcl", "\tProperties \t0x" << std::hex << GetProperties() << "\n");
2170 : SAL_INFO( "vcl", "\tWMName \t" << getWMAdaptor()->getWindowManagerName() );
2171 : }
2172 : SAL_INFO( "vcl", "Screen" );
2173 : SAL_INFO( "vcl", "\tResolution/Size \t" << aResolution_.A() << "*" << aResolution_.B()
2174 : << " " << m_aScreens[m_nXDefaultScreen.getXScreen()].m_aSize.Width() << "*" << m_aScreens[m_nXDefaultScreen.getXScreen()].m_aSize.Height()
2175 : << " " << (Hypothenuse( DisplayWidthMM ( pDisp_, m_nXDefaultScreen.getXScreen() ),
2176 : DisplayHeightMM( pDisp_, m_nXDefaultScreen.getXScreen() ) ) / 25.4 ) << "\"" );
2177 : SAL_INFO( "vcl", "\tBlack&White \t" << GetColormap(m_nXDefaultScreen).GetBlackPixel() << " "
2178 : << GetColormap(m_nXDefaultScreen).GetWhitePixel() );
2179 : SAL_INFO( "vcl", "\tRGB \t0x" << std::hex << GetVisual(m_nXDefaultScreen).red_mask
2180 : << " 0x" << GetVisual(m_nXDefaultScreen).green_mask
2181 : << " 0x" << GetVisual(m_nXDefaultScreen).blue_mask);
2182 0 : }
2183 :
2184 0 : void SalDisplay::addXineramaScreenUnique( int i, long i_nX, long i_nY, long i_nWidth, long i_nHeight )
2185 : {
2186 : // see if any frame buffers are at the same coordinates
2187 : // this can happen with weird configuration e.g. on
2188 : // XFree86 and Clone displays
2189 0 : const size_t nScreens = m_aXineramaScreens.size();
2190 0 : for( size_t n = 0; n < nScreens; n++ )
2191 : {
2192 0 : if( m_aXineramaScreens[n].Left() == i_nX &&
2193 0 : m_aXineramaScreens[n].Top() == i_nY )
2194 : {
2195 0 : if( m_aXineramaScreens[n].GetWidth() < i_nWidth ||
2196 0 : m_aXineramaScreens[n].GetHeight() < i_nHeight )
2197 : {
2198 0 : m_aXineramaScreenIndexMap[i] = n;
2199 0 : m_aXineramaScreens[n].SetSize( Size( i_nWidth, i_nHeight ) );
2200 : }
2201 0 : return;
2202 : }
2203 : }
2204 0 : m_aXineramaScreenIndexMap[i] = m_aXineramaScreens.size();
2205 0 : m_aXineramaScreens.push_back( Rectangle( Point( i_nX, i_nY ), Size( i_nWidth, i_nHeight ) ) );
2206 : }
2207 :
2208 0 : void SalDisplay::InitXinerama()
2209 : {
2210 0 : if( m_aScreens.size() > 1 )
2211 : {
2212 0 : m_bXinerama = false;
2213 0 : return; // multiple screens mean no xinerama
2214 : }
2215 : #if defined(USE_XINERAMA_XSUN)
2216 : int nFramebuffers = 1;
2217 : if( XineramaGetState( pDisp_, m_nDefaultScreen ) )
2218 : {
2219 : XRectangle pFramebuffers[MAXFRAMEBUFFERS];
2220 : unsigned char hints[MAXFRAMEBUFFERS];
2221 : int result = XineramaGetInfo( pDisp_,
2222 : m_nDefaultScreen,
2223 : pFramebuffers,
2224 : hints,
2225 : &nFramebuffers );
2226 : if( result > 0 && nFramebuffers > 1 )
2227 : {
2228 : m_bXinerama = true;
2229 : m_aXineramaScreens = std::vector<Rectangle>();
2230 : m_aXineramaScreenIndexMap = std::vector<int>(nFramebuffers);
2231 : for( int i = 0; i < nFramebuffers; i++ )
2232 : addXineramaScreenUnique( i, pFramebuffers[i].x,
2233 : pFramebuffers[i].y,
2234 : pFramebuffers[i].width,
2235 : pFramebuffers[i].height );
2236 : }
2237 : }
2238 : #elif defined(USE_XINERAMA_XORG)
2239 0 : if( XineramaIsActive( pDisp_ ) )
2240 : {
2241 0 : int nFramebuffers = 1;
2242 0 : XineramaScreenInfo* pScreens = XineramaQueryScreens( pDisp_, &nFramebuffers );
2243 0 : if( pScreens )
2244 : {
2245 0 : if( nFramebuffers > 1 )
2246 : {
2247 0 : m_aXineramaScreens = std::vector<Rectangle>();
2248 0 : m_aXineramaScreenIndexMap = std::vector<int>(nFramebuffers);
2249 0 : for( int i = 0; i < nFramebuffers; i++ )
2250 : {
2251 0 : addXineramaScreenUnique( i, pScreens[i].x_org,
2252 0 : pScreens[i].y_org,
2253 0 : pScreens[i].width,
2254 0 : pScreens[i].height );
2255 : }
2256 0 : m_bXinerama = m_aXineramaScreens.size() > 1;
2257 : }
2258 0 : XFree( pScreens );
2259 : }
2260 : }
2261 : #endif
2262 : #if OSL_DEBUG_LEVEL > 1
2263 : if( m_bXinerama )
2264 : {
2265 : for( std::vector< Rectangle >::const_iterator it = m_aXineramaScreens.begin(); it != m_aXineramaScreens.end(); ++it )
2266 : fprintf( stderr, "Xinerama screen: %ldx%ld+%ld+%ld\n", it->GetWidth(), it->GetHeight(), it->Left(), it->Top() );
2267 : }
2268 : #endif
2269 : }
2270 :
2271 :
2272 : extern "C"
2273 : {
2274 0 : static Bool timestamp_predicate( Display*, XEvent* i_pEvent, XPointer i_pArg )
2275 : {
2276 0 : SalDisplay* pSalDisplay = reinterpret_cast<SalDisplay*>(i_pArg);
2277 0 : if( i_pEvent->type == PropertyNotify &&
2278 0 : i_pEvent->xproperty.window == pSalDisplay->GetDrawable( pSalDisplay->GetDefaultXScreen() ) &&
2279 0 : i_pEvent->xproperty.atom == pSalDisplay->getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT )
2280 : )
2281 0 : return True;
2282 :
2283 0 : return False;
2284 : }
2285 : }
2286 :
2287 0 : XLIB_Time SalDisplay::GetLastUserEventTime( bool i_bAlwaysReget ) const
2288 : {
2289 0 : if( m_nLastUserEventTime == CurrentTime || i_bAlwaysReget )
2290 : {
2291 : // get current server time
2292 0 : unsigned char c = 0;
2293 : XEvent aEvent;
2294 0 : Atom nAtom = getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT );
2295 : XChangeProperty( GetDisplay(), GetDrawable( GetDefaultXScreen() ),
2296 0 : nAtom, nAtom, 8, PropModeReplace, &c, 1 );
2297 0 : XFlush( GetDisplay() );
2298 :
2299 0 : if( ! XIfEventWithTimeout( &aEvent, (XPointer)this, timestamp_predicate ) )
2300 : {
2301 : // this should not happen at all; still sometimes it happens
2302 0 : aEvent.xproperty.time = CurrentTime;
2303 : }
2304 :
2305 0 : m_nLastUserEventTime = aEvent.xproperty.time;
2306 : }
2307 0 : return m_nLastUserEventTime;
2308 : }
2309 :
2310 0 : bool SalDisplay::XIfEventWithTimeout( XEvent* o_pEvent, XPointer i_pPredicateData,
2311 : X_if_predicate i_pPredicate, long i_nTimeout ) const
2312 : {
2313 : /* #i99360# ugly workaround an X11 library bug
2314 : this replaces the following call:
2315 : XIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData );
2316 : */
2317 0 : bool bRet = true;
2318 :
2319 0 : if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) )
2320 : {
2321 : // wait for some event to arrive
2322 : struct pollfd aFD;
2323 0 : aFD.fd = ConnectionNumber(GetDisplay());
2324 0 : aFD.events = POLLIN;
2325 0 : aFD.revents = 0;
2326 0 : poll( &aFD, 1, i_nTimeout );
2327 0 : if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) )
2328 : {
2329 0 : poll( &aFD, 1, i_nTimeout ); // try once more for a packet of events from the Xserver
2330 0 : if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) )
2331 : {
2332 0 : bRet = false;
2333 : }
2334 : }
2335 : }
2336 0 : return bRet;
2337 : }
2338 :
2339 0 : SalVisual::SalVisual()
2340 : {
2341 0 : memset( this, 0, sizeof( SalVisual ) );
2342 0 : }
2343 :
2344 0 : SalVisual::SalVisual( const XVisualInfo* pXVI )
2345 : {
2346 0 : *(XVisualInfo*)this = *pXVI;
2347 0 : if( GetClass() == TrueColor )
2348 : {
2349 0 : nRedShift_ = sal_Shift( red_mask );
2350 0 : nGreenShift_ = sal_Shift( green_mask );
2351 0 : nBlueShift_ = sal_Shift( blue_mask );
2352 :
2353 0 : nRedBits_ = sal_significantBits( red_mask );
2354 0 : nGreenBits_ = sal_significantBits( green_mask );
2355 0 : nBlueBits_ = sal_significantBits( blue_mask );
2356 :
2357 0 : if( GetDepth() == 24 )
2358 0 : if( red_mask == 0xFF0000 )
2359 0 : if( green_mask == 0xFF00 )
2360 0 : if( blue_mask == 0xFF )
2361 0 : eRGBMode_ = RGB;
2362 : else
2363 0 : eRGBMode_ = otherSalRGB;
2364 0 : else if( blue_mask == 0xFF00 )
2365 0 : if( green_mask == 0xFF )
2366 0 : eRGBMode_ = RBG;
2367 : else
2368 0 : eRGBMode_ = otherSalRGB;
2369 : else
2370 0 : eRGBMode_ = otherSalRGB;
2371 0 : else if( green_mask == 0xFF0000 )
2372 0 : if( red_mask == 0xFF00 )
2373 0 : if( blue_mask == 0xFF )
2374 0 : eRGBMode_ = GRB;
2375 : else
2376 0 : eRGBMode_ = otherSalRGB;
2377 0 : else if( blue_mask == 0xFF00 )
2378 0 : if( red_mask == 0xFF )
2379 0 : eRGBMode_ = GBR;
2380 : else
2381 0 : eRGBMode_ = otherSalRGB;
2382 : else
2383 0 : eRGBMode_ = otherSalRGB;
2384 0 : else if( blue_mask == 0xFF0000 )
2385 0 : if( red_mask == 0xFF00 )
2386 0 : if( green_mask == 0xFF )
2387 0 : eRGBMode_ = BRG;
2388 : else
2389 0 : eRGBMode_ = otherSalRGB;
2390 0 : else if( green_mask == 0xFF00 )
2391 0 : if( red_mask == 0xFF )
2392 0 : eRGBMode_ = BGR;
2393 : else
2394 0 : eRGBMode_ = otherSalRGB;
2395 : else
2396 0 : eRGBMode_ = otherSalRGB;
2397 : else
2398 0 : eRGBMode_ = otherSalRGB;
2399 : else
2400 0 : eRGBMode_ = otherSalRGB;
2401 : }
2402 0 : }
2403 :
2404 0 : SalVisual::~SalVisual()
2405 : {
2406 0 : if( -1 == screen && VisualID(-1) == visualid ) delete visual;
2407 0 : }
2408 :
2409 : // Converts the order of bytes of a Pixel into bytes of a SalColor
2410 : // This is not reversible for the 6 XXXA
2411 :
2412 : // SalColor is RGB (ABGR) a=0xFF000000, r=0xFF0000, g=0xFF00, b=0xFF
2413 :
2414 : #define SALCOLOR RGB
2415 : #define SALCOLORREVERSE BGR
2416 :
2417 0 : SalColor SalVisual::GetTCColor( Pixel nPixel ) const
2418 : {
2419 0 : if( SALCOLOR == eRGBMode_ )
2420 0 : return (SalColor)nPixel;
2421 :
2422 0 : if( SALCOLORREVERSE == eRGBMode_ )
2423 0 : return MAKE_SALCOLOR( (nPixel & 0x0000FF),
2424 : (nPixel & 0x00FF00) >> 8,
2425 : (nPixel & 0xFF0000) >> 16);
2426 :
2427 0 : Pixel r = nPixel & red_mask;
2428 0 : Pixel g = nPixel & green_mask;
2429 0 : Pixel b = nPixel & blue_mask;
2430 :
2431 0 : if( otherSalRGB != eRGBMode_ ) // 8+8+8=24
2432 0 : return MAKE_SALCOLOR( r >> nRedShift_,
2433 : g >> nGreenShift_,
2434 : b >> nBlueShift_ );
2435 :
2436 0 : if( nRedShift_ > 0 ) r >>= nRedShift_; else r <<= -nRedShift_;
2437 0 : if( nGreenShift_ > 0 ) g >>= nGreenShift_; else g <<= -nGreenShift_;
2438 0 : if( nBlueShift_ > 0 ) b >>= nBlueShift_; else b <<= -nBlueShift_;
2439 :
2440 0 : if( nRedBits_ != 8 )
2441 0 : r |= (r & 0xff) >> (8-nRedBits_);
2442 0 : if( nGreenBits_ != 8 )
2443 0 : g |= (g & 0xff) >> (8-nGreenBits_);
2444 0 : if( nBlueBits_ != 8 )
2445 0 : b |= (b & 0xff) >> (8-nBlueBits_);
2446 :
2447 0 : return MAKE_SALCOLOR( r, g, b );
2448 : }
2449 :
2450 0 : Pixel SalVisual::GetTCPixel( SalColor nSalColor ) const
2451 : {
2452 0 : if( SALCOLOR == eRGBMode_ )
2453 0 : return (Pixel)nSalColor;
2454 :
2455 0 : Pixel r = (Pixel)SALCOLOR_RED( nSalColor );
2456 0 : Pixel g = (Pixel)SALCOLOR_GREEN( nSalColor );
2457 0 : Pixel b = (Pixel)SALCOLOR_BLUE( nSalColor );
2458 :
2459 0 : if( SALCOLORREVERSE == eRGBMode_ )
2460 0 : return (b << 16) | (g << 8) | (r);
2461 :
2462 0 : if( otherSalRGB != eRGBMode_ ) // 8+8+8=24
2463 0 : return (r << nRedShift_) | (g << nGreenShift_) | (b << nBlueShift_);
2464 :
2465 0 : if( nRedShift_ > 0 ) r <<= nRedShift_; else r >>= -nRedShift_;
2466 0 : if( nGreenShift_ > 0 ) g <<= nGreenShift_; else g >>= -nGreenShift_;
2467 0 : if( nBlueShift_ > 0 ) b <<= nBlueShift_; else b >>= -nBlueShift_;
2468 :
2469 0 : return (r&red_mask) | (g&green_mask) | (b&blue_mask);
2470 : }
2471 :
2472 0 : SalColormap::SalColormap( const SalDisplay *pDisplay, Colormap hColormap,
2473 : SalX11Screen nXScreen )
2474 : : m_pDisplay( pDisplay ),
2475 : m_hColormap( hColormap ),
2476 0 : m_nXScreen( nXScreen )
2477 : {
2478 0 : m_aVisual = m_pDisplay->GetVisual( m_nXScreen );
2479 :
2480 : XColor aColor;
2481 :
2482 0 : GetXPixel( aColor, 0x00, 0x00, 0x00 );
2483 0 : m_nBlackPixel = aColor.pixel;
2484 :
2485 0 : GetXPixel( aColor, 0xFF, 0xFF, 0xFF );
2486 0 : m_nWhitePixel = aColor.pixel;
2487 :
2488 0 : m_nUsed = 1 << m_aVisual.GetDepth();
2489 :
2490 0 : if( m_aVisual.GetClass() == PseudoColor )
2491 : {
2492 : int r, g, b;
2493 :
2494 : // black, white, gray, ~gray = 4
2495 0 : GetXPixels( aColor, 0xC0, 0xC0, 0xC0 );
2496 :
2497 : // light colors: 3 * 2 = 6
2498 :
2499 0 : GetXPixels( aColor, 0x00, 0x00, 0xFF );
2500 0 : GetXPixels( aColor, 0x00, 0xFF, 0x00 );
2501 0 : GetXPixels( aColor, 0x00, 0xFF, 0xFF );
2502 :
2503 : // standard colors: 7 * 2 = 14
2504 0 : GetXPixels( aColor, 0x00, 0x00, 0x80 );
2505 0 : GetXPixels( aColor, 0x00, 0x80, 0x00 );
2506 0 : GetXPixels( aColor, 0x00, 0x80, 0x80 );
2507 0 : GetXPixels( aColor, 0x80, 0x00, 0x00 );
2508 0 : GetXPixels( aColor, 0x80, 0x00, 0x80 );
2509 0 : GetXPixels( aColor, 0x80, 0x80, 0x00 );
2510 0 : GetXPixels( aColor, 0x80, 0x80, 0x80 );
2511 0 : GetXPixels( aColor, 0x00, 0xB8, 0xFF ); // Blue 7
2512 :
2513 : // cube: 6*6*6 - 8 = 208
2514 0 : for( r = 0; r < 0x100; r += 0x33 ) // 0x33, 0x66, 0x99, 0xCC, 0xFF
2515 0 : for( g = 0; g < 0x100; g += 0x33 )
2516 0 : for( b = 0; b < 0x100; b += 0x33 )
2517 0 : GetXPixels( aColor, r, g, b );
2518 :
2519 : // gray: 16 - 6 = 10
2520 0 : for( g = 0x11; g < 0xFF; g += 0x11 )
2521 0 : GetXPixels( aColor, g, g, g );
2522 :
2523 : // green: 16 - 6 = 10
2524 0 : for( g = 0x11; g < 0xFF; g += 0x11 )
2525 0 : GetXPixels( aColor, 0, g, 0 );
2526 :
2527 : // red: 16 - 6 = 10
2528 0 : for( r = 0x11; r < 0xFF; r += 0x11 )
2529 0 : GetXPixels( aColor, r, 0, 0 );
2530 :
2531 : // blue: 16 - 6 = 10
2532 0 : for( b = 0x11; b < 0xFF; b += 0x11 )
2533 0 : GetXPixels( aColor, 0, 0, b );
2534 : }
2535 0 : }
2536 :
2537 : // MonoChrome
2538 0 : SalColormap::SalColormap()
2539 0 : : m_pDisplay( GetGenericData()->GetSalDisplay() ),
2540 : m_hColormap( None ),
2541 : m_nWhitePixel( 1 ),
2542 : m_nBlackPixel( 0 ),
2543 : m_nUsed( 2 ),
2544 0 : m_nXScreen( m_pDisplay != NULL ? m_pDisplay->GetDefaultXScreen() : SalX11Screen( 0 ) )
2545 : {
2546 0 : m_aPalette = std::vector<SalColor>(m_nUsed);
2547 :
2548 0 : m_aPalette[m_nBlackPixel] = SALCOLOR_BLACK;
2549 0 : m_aPalette[m_nWhitePixel] = SALCOLOR_WHITE;
2550 0 : }
2551 :
2552 : // TrueColor
2553 0 : SalColormap::SalColormap( sal_uInt16 nDepth )
2554 0 : : m_pDisplay( GetGenericData()->GetSalDisplay() ),
2555 : m_hColormap( None ),
2556 0 : m_nWhitePixel( (1 << nDepth) - 1 ),
2557 : m_nBlackPixel( 0x00000000 ),
2558 0 : m_nUsed( 1 << nDepth ),
2559 0 : m_nXScreen( GetGenericData()->GetSalDisplay()->GetDefaultXScreen() )
2560 : {
2561 0 : const SalVisual *pVisual = &m_pDisplay->GetVisual( m_nXScreen );
2562 :
2563 0 : if( pVisual->GetClass() == TrueColor && pVisual->GetDepth() == nDepth )
2564 0 : m_aVisual = *pVisual;
2565 : else
2566 : {
2567 : XVisualInfo aVI;
2568 :
2569 0 : if( !XMatchVisualInfo( m_pDisplay->GetDisplay(),
2570 0 : m_pDisplay->GetDefaultXScreen().getXScreen(),
2571 : nDepth,
2572 : TrueColor,
2573 0 : &aVI ) )
2574 : {
2575 0 : aVI.visual = new Visual();
2576 0 : aVI.visualid = (VisualID)0; // beware of temporary destructor below
2577 0 : aVI.screen = 0;
2578 0 : aVI.depth = nDepth;
2579 0 : aVI.c_class = TrueColor;
2580 0 : if( 24 == nDepth ) // 888
2581 : {
2582 0 : aVI.red_mask = 0xFF0000;
2583 0 : aVI.green_mask = 0x00FF00;
2584 0 : aVI.blue_mask = 0x0000FF;
2585 : }
2586 0 : else if( 16 == nDepth ) // 565
2587 : {
2588 0 : aVI.red_mask = 0x00F800;
2589 0 : aVI.green_mask = 0x0007E0;
2590 0 : aVI.blue_mask = 0x00001F;
2591 : }
2592 0 : else if( 15 == nDepth ) // 555
2593 : {
2594 0 : aVI.red_mask = 0x007C00;
2595 0 : aVI.green_mask = 0x0003E0;
2596 0 : aVI.blue_mask = 0x00001F;
2597 : }
2598 0 : else if( 12 == nDepth ) // 444
2599 : {
2600 0 : aVI.red_mask = 0x000F00;
2601 0 : aVI.green_mask = 0x0000F0;
2602 0 : aVI.blue_mask = 0x00000F;
2603 : }
2604 0 : else if( 8 == nDepth ) // 332
2605 : {
2606 0 : aVI.red_mask = 0x0000E0;
2607 0 : aVI.green_mask = 0x00001C;
2608 0 : aVI.blue_mask = 0x000003;
2609 : }
2610 : else
2611 : {
2612 0 : aVI.red_mask = 0x000000;
2613 0 : aVI.green_mask = 0x000000;
2614 0 : aVI.blue_mask = 0x000000;
2615 : }
2616 0 : aVI.colormap_size = 0;
2617 0 : aVI.bits_per_rgb = 8;
2618 :
2619 0 : aVI.visual->ext_data = NULL;
2620 0 : aVI.visual->visualid = aVI.visualid;
2621 0 : aVI.visual->c_class = aVI.c_class;
2622 0 : aVI.visual->red_mask = aVI.red_mask;
2623 0 : aVI.visual->green_mask = aVI.green_mask;
2624 0 : aVI.visual->blue_mask = aVI.blue_mask;
2625 0 : aVI.visual->bits_per_rgb = aVI.bits_per_rgb;
2626 0 : aVI.visual->map_entries = aVI.colormap_size;
2627 :
2628 0 : m_aVisual = SalVisual( &aVI );
2629 : // give ownership of constructed Visual() to m_aVisual
2630 : // see SalVisual destructor
2631 0 : m_aVisual.visualid = (VisualID)-1;
2632 0 : m_aVisual.screen = -1;
2633 : }
2634 : else
2635 0 : m_aVisual = SalVisual( &aVI );
2636 : }
2637 0 : }
2638 :
2639 0 : SalColormap::~SalColormap()
2640 : {
2641 : #ifdef DBG_UTIL
2642 : m_hColormap = None;
2643 : m_pDisplay = NULL;
2644 : #endif
2645 0 : }
2646 :
2647 0 : void SalColormap::GetPalette()
2648 : {
2649 : Pixel i;
2650 0 : m_aPalette = std::vector<SalColor>(m_nUsed);
2651 :
2652 0 : XColor *aColor = new XColor[m_nUsed];
2653 :
2654 0 : for( i = 0; i < m_nUsed; i++ )
2655 : {
2656 0 : aColor[i].red = aColor[i].green = aColor[i].blue = 0;
2657 0 : aColor[i].pixel = i;
2658 : }
2659 :
2660 0 : XQueryColors( m_pDisplay->GetDisplay(), m_hColormap, aColor, m_nUsed );
2661 :
2662 0 : for( i = 0; i < m_nUsed; i++ )
2663 : {
2664 0 : m_aPalette[i] = MAKE_SALCOLOR( aColor[i].red >> 8,
2665 : aColor[i].green >> 8,
2666 0 : aColor[i].blue >> 8 );
2667 : }
2668 :
2669 0 : delete [] aColor;
2670 0 : }
2671 :
2672 0 : static sal_uInt16 sal_Lookup( const std::vector<SalColor>& rPalette,
2673 : int r, int g, int b,
2674 : Pixel nUsed )
2675 : {
2676 0 : sal_uInt16 nPixel = 0;
2677 0 : int nBest = ColorDiff( rPalette[0], r, g, b );
2678 :
2679 0 : for( sal_uInt16 i = 1; i < nUsed; i++ )
2680 : {
2681 0 : int n = ColorDiff( rPalette[i], r, g, b );
2682 :
2683 0 : if( n < nBest )
2684 : {
2685 0 : if( !n )
2686 0 : return i;
2687 :
2688 0 : nPixel = i;
2689 0 : nBest = n;
2690 : }
2691 : }
2692 0 : return nPixel;
2693 : }
2694 :
2695 0 : void SalColormap::GetLookupTable()
2696 : {
2697 0 : m_aLookupTable = std::vector<sal_uInt16>(16*16*16);
2698 :
2699 0 : int i = 0;
2700 0 : for( int r = 0; r < 256; r += 17 )
2701 0 : for( int g = 0; g < 256; g += 17 )
2702 0 : for( int b = 0; b < 256; b += 17 )
2703 0 : m_aLookupTable[i++] = sal_Lookup( m_aPalette, r, g, b, m_nUsed );
2704 0 : }
2705 :
2706 0 : SalColor SalColormap::GetColor( Pixel nPixel ) const
2707 : {
2708 0 : if( m_nBlackPixel == nPixel ) return SALCOLOR_BLACK;
2709 0 : if( m_nWhitePixel == nPixel ) return SALCOLOR_WHITE;
2710 :
2711 0 : if( m_aVisual.GetVisual() )
2712 : {
2713 0 : if( m_aVisual.GetClass() == TrueColor )
2714 0 : return m_aVisual.GetTCColor( nPixel );
2715 :
2716 0 : if( m_aPalette.empty()
2717 0 : && m_hColormap
2718 0 : && m_aVisual.GetDepth() <= 12
2719 0 : && m_aVisual.GetClass() == PseudoColor )
2720 0 : ((SalColormap*)this)->GetPalette();
2721 : }
2722 :
2723 0 : if( !m_aPalette.empty() && nPixel < m_nUsed )
2724 0 : return m_aPalette[nPixel];
2725 :
2726 0 : if( m_hColormap )
2727 : {
2728 : DBG_ASSERT( 1, "SalColormap::GetColor() !hColormap_\n" );
2729 0 : return nPixel;
2730 : }
2731 :
2732 : // DirectColor, StaticColor, StaticGray, GrayScale
2733 : XColor aColor;
2734 :
2735 0 : aColor.pixel = nPixel;
2736 :
2737 0 : XQueryColor( m_pDisplay->GetDisplay(), m_hColormap, &aColor );
2738 :
2739 0 : return MAKE_SALCOLOR( aColor.red>>8, aColor.green>>8, aColor.blue>>8 );
2740 : }
2741 :
2742 0 : inline sal_Bool SalColormap::GetXPixel( XColor &rColor,
2743 : int r,
2744 : int g,
2745 : int b ) const
2746 : {
2747 0 : rColor.red = r * 257;
2748 0 : rColor.green = g * 257;
2749 0 : rColor.blue = b * 257;
2750 0 : return XAllocColor( GetXDisplay(), m_hColormap, &rColor );
2751 : }
2752 :
2753 0 : sal_Bool SalColormap::GetXPixels( XColor &rColor,
2754 : int r,
2755 : int g,
2756 : int b ) const
2757 : {
2758 0 : if( !GetXPixel( rColor, r, g, b ) )
2759 0 : return sal_False;
2760 0 : if( rColor.pixel & 1 )
2761 0 : return sal_True;
2762 0 : return GetXPixel( rColor, r^0xFF, g^0xFF, b^0xFF );
2763 : }
2764 :
2765 0 : Pixel SalColormap::GetPixel( SalColor nSalColor ) const
2766 : {
2767 0 : if( SALCOLOR_NONE == nSalColor ) return 0;
2768 0 : if( SALCOLOR_BLACK == nSalColor ) return m_nBlackPixel;
2769 0 : if( SALCOLOR_WHITE == nSalColor ) return m_nWhitePixel;
2770 :
2771 0 : if( m_aVisual.GetClass() == TrueColor )
2772 0 : return m_aVisual.GetTCPixel( nSalColor );
2773 :
2774 0 : if( m_aLookupTable.empty() )
2775 : {
2776 0 : if( m_aPalette.empty()
2777 0 : && m_hColormap
2778 0 : && m_aVisual.GetDepth() <= 12
2779 0 : && m_aVisual.GetClass() == PseudoColor ) // what else ???
2780 0 : ((SalColormap*)this)->GetPalette();
2781 :
2782 0 : if( !m_aPalette.empty() )
2783 0 : for( Pixel i = 0; i < m_nUsed; i++ )
2784 0 : if( m_aPalette[i] == nSalColor )
2785 0 : return i;
2786 :
2787 0 : if( m_hColormap )
2788 : {
2789 : // DirectColor, StaticColor, StaticGray, GrayScale (PseudoColor)
2790 : XColor aColor;
2791 :
2792 0 : if( GetXPixel( aColor,
2793 0 : SALCOLOR_RED ( nSalColor ),
2794 0 : SALCOLOR_GREEN( nSalColor ),
2795 0 : SALCOLOR_BLUE ( nSalColor ) ) )
2796 : {
2797 0 : if( !m_aPalette.empty() && !m_aPalette[aColor.pixel] )
2798 : {
2799 0 : const_cast<SalColormap*>(this)->m_aPalette[aColor.pixel] = nSalColor;
2800 :
2801 0 : if( !(aColor.pixel & 1) && !m_aPalette[aColor.pixel+1] )
2802 : {
2803 : XColor aInversColor;
2804 :
2805 0 : SalColor nInversColor = nSalColor ^ 0xFFFFFF;
2806 :
2807 : GetXPixel( aInversColor,
2808 0 : SALCOLOR_RED ( nInversColor ),
2809 0 : SALCOLOR_GREEN( nInversColor ),
2810 0 : SALCOLOR_BLUE ( nInversColor ) );
2811 :
2812 0 : if( !m_aPalette[aInversColor.pixel] )
2813 0 : const_cast<SalColormap*>(this)->m_aPalette[aInversColor.pixel] = nInversColor;
2814 : #ifdef DBG_UTIL
2815 : else
2816 : fprintf( stderr, "SalColormap::GetPixel() 0x%06lx=%lu 0x%06lx=%lu\n",
2817 : static_cast< unsigned long >(nSalColor), aColor.pixel,
2818 : static_cast< unsigned long >(nInversColor), aInversColor.pixel);
2819 : #endif
2820 : }
2821 : }
2822 :
2823 0 : return aColor.pixel;
2824 : }
2825 :
2826 : #ifdef DBG_UTIL
2827 : fprintf( stderr, "SalColormap::GetPixel() !XAllocColor %lx\n",
2828 : static_cast< unsigned long >(nSalColor) );
2829 : #endif
2830 : }
2831 :
2832 0 : if( m_aPalette.empty() )
2833 : {
2834 : #ifdef DBG_UTIL
2835 : fprintf( stderr, "SalColormap::GetPixel() Palette empty %lx\n",
2836 : static_cast< unsigned long >(nSalColor));
2837 : #endif
2838 0 : return nSalColor;
2839 : }
2840 :
2841 0 : ((SalColormap*)this)->GetLookupTable();
2842 : }
2843 :
2844 : // Colormatching ueber Palette
2845 0 : sal_uInt16 r = SALCOLOR_RED ( nSalColor );
2846 0 : sal_uInt16 g = SALCOLOR_GREEN( nSalColor );
2847 0 : sal_uInt16 b = SALCOLOR_BLUE ( nSalColor );
2848 0 : return m_aLookupTable[ (((r+8)/17) << 8)
2849 0 : + (((g+8)/17) << 4)
2850 0 : + ((b+8)/17) ];
2851 0 : }
2852 :
2853 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|