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