1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
26 #if defined(__sun) || defined(AIX)
27 #include <osl/module.h>
31 #include <X11/Xutil.h>
32 #include <X11/XKBlib.h>
34 #include <X11/cursorfont.h>
35 #include <unx/x11_cursors/salcursors.h>
36 #include <unx/x11_cursors/invert50.h>
40 #include <X11/keysym.h>
41 #include <X11/Xatom.h>
43 #ifdef USE_XINERAMA_XORG
44 #include <X11/extensions/Xinerama.h>
47 #include <opengl/zone.hxx>
49 #include <i18nlangtag/languagetag.hxx>
50 #include <tools/debug.hxx>
51 #include <vcl/svapp.hxx>
52 #include <vcl/settings.hxx>
54 #include <sal/log.hxx>
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/salframe.h>
62 #include <vcl/keycodes.hxx>
63 #include <unx/salbmp.h>
64 #include <osl/diagnose.h>
65 #include <unx/salobj.h>
67 #include <unx/wmadaptor.hxx>
68 #include <unx/x11/xrender_peer.hxx>
69 #include <unx/glyphcache.hxx>
71 #include <vcl/opengl/OpenGLHelper.hxx>
77 /* From <X11/Intrinsic.h> */
78 typedef unsigned long Pixel
;
80 using namespace vcl_sal
;
83 static const char *Null( const char *p
) { return p
? p
: ""; }
84 static const char *GetEnv( const char *p
) { return Null( getenv( p
) ); }
85 static const char *KeyStr( KeySym n
) { return Null( XKeysymToString( n
) ); }
87 static const char *GetAtomName( Display
*d
, Atom a
)
88 { return Null( XGetAtomName( d
, a
) ); }
90 static double Hypothenuse( tools::Long w
, tools::Long h
)
91 { return sqrt( static_cast<double>((w
*w
)+(h
*h
)) ); }
94 static int ColorDiff( int r
, int g
, int b
)
95 { return (r
*r
)+(g
*g
)+(b
*b
); }
97 static int ColorDiff( Color c1
, int r
, int g
, int b
)
98 { return ColorDiff( static_cast<int>(c1
.GetRed())-r
,
99 static_cast<int>(c1
.GetGreen())-g
,
100 static_cast<int>(c1
.GetBlue())-b
); }
102 static int sal_Shift( Pixel nMask
)
105 if( nMask
< 0x00010000 ) { nMask
<<= 16; i
-= 16; }
106 if( nMask
< 0x01000000 ) { nMask
<<= 8; i
-= 8; }
107 if( nMask
< 0x10000000 ) { nMask
<<= 4; i
-= 4; }
108 if( nMask
< 0x40000000 ) { nMask
<<= 2; i
-= 2; }
109 if( nMask
< 0x80000000 ) { i
-= 1; }
113 static int sal_significantBits( Pixel nMask
)
115 int nRotate
= sizeof(Pixel
)*4;
126 // check if the resolution is sane
127 static bool sal_ValidDPI(tools::Long nDPI
)
129 return (nDPI
>= 50) && (nDPI
<= 500);
132 static bool sal_GetVisualInfo( Display
*pDisplay
, XID nVID
, XVisualInfo
&rVI
)
135 XVisualInfo aTemplate
;
138 aTemplate
.visualid
= nVID
;
140 pInfo
= XGetVisualInfo( pDisplay
, VisualIDMask
, &aTemplate
, &nInfos
);
147 SAL_WARN_IF( rVI
.visualid
!= nVID
, "vcl",
148 "sal_GetVisualInfo: could not get correct visual by visualId" );
152 extern "C" srv_vendor_t
153 sal_GetServerVendor( Display
*p_display
)
156 srv_vendor_t e_vendor
; // vendor as enum
157 const char* p_name
; // vendor name as returned by VendorString()
158 unsigned int n_len
; // number of chars to compare
161 static const vendor_t vendorlist
[] = {
162 { vendor_sun
, "Sun Microsystems, Inc.", 10 },
165 // handle regular server vendors
166 char *p_name
= ServerVendor( p_display
);
167 for (auto const & vendor
: vendorlist
)
169 if ( strncmp (p_name
, vendor
.p_name
, vendor
.n_len
) == 0 )
170 return vendor
.e_vendor
;
173 // vendor not found in list
174 return vendor_unknown
;
177 bool SalDisplay::BestOpenGLVisual(Display
* pDisplay
, int nScreen
, XVisualInfo
& rVI
)
182 int aAttrib
[] = { GLX_RGBA
,
190 pVI
= glXChooseVisual( pDisplay
, nScreen
, aAttrib
);
201 bool SalDisplay::BestVisual( Display
*pDisplay
,
205 VisualID nDefVID
= XVisualIDFromVisual( DefaultVisual( pDisplay
, nScreen
) );
207 char *pVID
= getenv( "SAL_VISUAL" );
209 sscanf( pVID
, "%li", &nVID
);
211 if( nVID
&& sal_GetVisualInfo( pDisplay
, nVID
, rVI
) )
212 return rVI
.visualid
== nDefVID
;
215 bool bUseOpenGL
= OpenGLHelper::isVCLOpenGLEnabled();
216 if (bUseOpenGL
&& BestOpenGLVisual(pDisplay
, nScreen
, rVI
))
217 return rVI
.visualid
== nDefVID
;
220 aVI
.screen
= nScreen
;
223 XVisualInfo
* pVInfos
= XGetVisualInfo( pDisplay
, VisualScreenMask
,
225 // pVInfos should contain at least one visual, otherwise
227 std::vector
<int> aWeights(nVisuals
);
229 for( i
= 0; i
< nVisuals
; i
++ )
231 bool bUsable
= false;
234 if ( pVInfos
[i
].screen
!= nScreen
)
238 else if( pVInfos
[i
].c_class
== TrueColor
)
241 if( pVInfos
[i
].depth
== 24 )
244 else if( pVInfos
[i
].c_class
== PseudoColor
)
248 aWeights
[i
] = bUsable
? nTrueColor
*pVInfos
[i
].depth
: -1024;
249 aWeights
[i
] -= pVInfos
[ i
].visualid
;
253 int nBestWeight
= -1024;
254 for( i
= 0; i
< nVisuals
; i
++ )
256 if (aWeights
[i
] > nBestWeight
)
258 nBestWeight
= aWeights
[i
];
263 rVI
= pVInfos
[ nBestVisual
];
266 return rVI
.visualid
== nDefVID
;
269 SalDisplay::SalDisplay( Display
*display
) :
271 mpKbdExtension( nullptr ),
273 m_nXDefaultScreen( 0 ),
274 nMaxRequestSize_( 0 ),
275 meServerVendor( vendor_unknown
),
276 bNumLockFromXS_( false ),
281 m_bXinerama( false ),
282 m_nLastUserEventTime( CurrentTime
)
284 #if OSL_DEBUG_LEVEL > 1
285 SAL_INFO("vcl.app", "SalDisplay::SalDisplay().");
287 GenericUnixSalData
*pData
= GetGenericUnixSalData();
289 SAL_WARN_IF( pData
->GetDisplay(), "vcl", "Second SalDisplay created !!!" );
290 pData
->SetDisplay( this );
292 m_nXDefaultScreen
= SalX11Screen( DefaultScreen( pDisp_
) );
295 SalDisplay::~SalDisplay()
297 #if OSL_DEBUG_LEVEL > 1
298 SAL_INFO("vcl.app", "SalDisplay::~SalDisplay().");
303 #if OSL_DEBUG_LEVEL > 1
304 SAL_INFO("vcl.app", "display " << pDisp_
<< " closed.");
308 // don't do this in doDestruct since RandR extension adds hooks into Display
309 // that is XCloseDisplay still needs the RandR library if it was used
313 void SalDisplay::doDestruct()
315 GenericUnixSalData
*pData
= GetGenericUnixSalData();
317 m_pWMAdaptor
.reset();
318 X11SalBitmap::ImplDestroyCache();
322 SalDisplay
* pSalDisp
= vcl_sal::getSalDisplay(pData
);
323 Display
* const pX11Disp
= pSalDisp
->GetDisplay();
324 int nMaxScreens
= pSalDisp
->GetXScreenCount();
325 XRenderPeer
& rRenderPeer
= XRenderPeer::GetInstance();
327 for (int i
= 0; i
< nMaxScreens
; i
++)
329 SalDisplay::RenderEntryMap
& rMap
= pSalDisp
->GetRenderEntries(SalX11Screen(i
));
330 for (auto const& elem
: rMap
)
332 if (elem
.second
.m_aPixmap
)
333 ::XFreePixmap(pX11Disp
, elem
.second
.m_aPixmap
);
334 if (elem
.second
.m_aPicture
)
335 rRenderPeer
.FreePicture(elem
.second
.m_aPicture
);
340 FreetypeManager::get().ClearFontCache();
344 delete mpKbdExtension
;
345 mpKbdExtension
= nullptr;
347 for( size_t i
= 0; i
< m_aScreens
.size(); i
++ )
349 ScreenData
& rData
= m_aScreens
[i
];
352 if( rData
.m_aMonoGC
!= rData
.m_aCopyGC
)
353 XFreeGC( pDisp_
, rData
.m_aMonoGC
);
354 XFreeGC( pDisp_
, rData
.m_aCopyGC
);
355 XFreeGC( pDisp_
, rData
.m_aAndInvertedGC
);
356 XFreeGC( pDisp_
, rData
.m_aAndGC
);
357 XFreeGC( pDisp_
, rData
.m_aOrGC
);
358 XFreeGC( pDisp_
, rData
.m_aStippleGC
);
359 XFreePixmap( pDisp_
, rData
.m_hInvert50
);
360 XDestroyWindow( pDisp_
, rData
.m_aRefWindow
);
361 Colormap aColMap
= rData
.m_aColormap
.GetXColormap();
362 if( aColMap
!= None
&& aColMap
!= DefaultColormap( pDisp_
, i
) )
363 XFreeColormap( pDisp_
, aColMap
);
367 for( const Cursor
& aCsr
: aPointerCache_
)
370 XFreeCursor( pDisp_
, aCsr
);
374 pXLib_
->Remove( ConnectionNumber( pDisp_
) );
377 if( pData
->GetDisplay() == static_cast<const SalGenericDisplay
*>( this ) )
378 pData
->SetDisplay( nullptr );
381 static int DisplayHasEvent( int fd
, void * data
)
383 auto pDisplay
= static_cast<SalX11Display
*>(data
);
384 SAL_WARN_IF( ConnectionNumber( pDisplay
->GetDisplay() ) != fd
, "vcl",
385 "wrong fd in DisplayHasEvent" );
386 if( ! pDisplay
->IsDisplay() )
391 SolarMutexGuard aGuard
;
392 result
= pDisplay
->IsEvent();
395 static int DisplayQueue( int fd
, void * data
)
397 auto pDisplay
= static_cast<SalX11Display
*>(data
);
398 SAL_WARN_IF( ConnectionNumber( pDisplay
->GetDisplay() ) != fd
, "vcl",
399 "wrong fd in DisplayHasEvent" );
402 SolarMutexGuard aGuard
;
403 result
= XEventsQueued( pDisplay
->GetDisplay(),
404 QueuedAfterReading
);
407 static int DisplayYield( int fd
, void * data
)
409 auto pDisplay
= static_cast<SalX11Display
*>(data
);
410 SAL_WARN_IF( ConnectionNumber( pDisplay
->GetDisplay() ) != fd
, "vcl",
411 "wrong fd in DisplayHasEvent" );
413 SolarMutexGuard aGuard
;
418 SalX11Display::SalX11Display( Display
*display
)
419 : SalDisplay( display
)
423 pXLib_
= GetX11SalData()->GetLib();
424 pXLib_
->Insert( ConnectionNumber( pDisp_
),
426 reinterpret_cast<YieldFunc
>(DisplayHasEvent
),
427 reinterpret_cast<YieldFunc
>(DisplayQueue
),
428 reinterpret_cast<YieldFunc
>(DisplayYield
) );
431 SalX11Display::~SalX11Display()
433 #if OSL_DEBUG_LEVEL > 1
434 SAL_INFO("vcl.app", "SalX11Display::~SalX11Display().");
439 XCloseDisplay( pDisp_
);
444 void SalX11Display::TriggerUserEventProcessing()
447 pXLib_
->TriggerUserEventProcessing();
450 SalDisplay::ScreenData
*
451 SalDisplay::initScreen( SalX11Screen nXScreen
) const
453 if( nXScreen
.getXScreen() >= m_aScreens
.size() )
454 nXScreen
= m_nXDefaultScreen
;
455 ScreenData
* pSD
= const_cast<ScreenData
*>(&m_aScreens
[nXScreen
.getXScreen()]);
463 if( SalDisplay::BestVisual( pDisp_
, nXScreen
.getXScreen(), aVI
) ) // DefaultVisual
464 aColMap
= DefaultColormap( pDisp_
, nXScreen
.getXScreen() );
466 aColMap
= XCreateColormap( pDisp_
,
467 RootWindow( pDisp_
, nXScreen
.getXScreen() ),
471 Screen
* pScreen
= ScreenOfDisplay( pDisp_
, nXScreen
.getXScreen() );
473 pSD
->m_aSize
= Size( WidthOfScreen( pScreen
), HeightOfScreen( pScreen
) );
474 pSD
->m_aRoot
= RootWindow( pDisp_
, nXScreen
.getXScreen() );
475 pSD
->m_aVisual
= SalVisual( &aVI
);
476 pSD
->m_aColormap
= SalColormap( this, aColMap
, nXScreen
);
478 // we're interested in configure notification of root windows
479 InitRandR( pSD
->m_aRoot
);
481 // - - - - - - - - - - Reference Window/Default Drawable - -
482 XSetWindowAttributes aXWAttributes
;
483 aXWAttributes
.border_pixel
= 0;
484 aXWAttributes
.background_pixel
= 0;
485 aXWAttributes
.colormap
= aColMap
;
486 pSD
->m_aRefWindow
= XCreateWindow( pDisp_
,
489 pSD
->m_aVisual
.GetDepth(),
491 pSD
->m_aVisual
.GetVisual(),
492 CWBorderPixel
|CWBackPixel
|CWColormap
,
495 // set client leader (session id gets set when session is started)
496 if( pSD
->m_aRefWindow
)
498 // client leader must have WM_CLIENT_LEADER pointing to itself
499 XChangeProperty( pDisp_
,
501 XInternAtom( pDisp_
, "WM_CLIENT_LEADER", False
),
505 reinterpret_cast<unsigned char*>(&pSD
->m_aRefWindow
),
509 OString
aExec(OUStringToOString(SessionManagerClient::getExecName(), osl_getThreadTextEncoding()));
511 argv
[0] = aExec
.getStr();
512 XSetCommand( pDisp_
, pSD
->m_aRefWindow
, const_cast<char**>(argv
), 1 );
513 XSelectInput( pDisp_
, pSD
->m_aRefWindow
, PropertyChangeMask
);
515 // - - - - - - - - - - GCs - - - - - - - - - - - - - - - - -
517 values
.graphics_exposures
= False
;
518 values
.fill_style
= FillOpaqueStippled
;
519 values
.background
= (1<<pSD
->m_aVisual
.GetDepth())-1;
520 values
.foreground
= 0;
522 pSD
->m_aCopyGC
= XCreateGC( pDisp_
,
528 pSD
->m_aAndInvertedGC
= XCreateGC( pDisp_
,
534 pSD
->m_aAndGC
= XCreateGC( pDisp_
,
540 pSD
->m_aOrGC
= XCreateGC( pDisp_
,
546 pSD
->m_aStippleGC
= XCreateGC( pDisp_
,
554 XSetFunction( pDisp_
, pSD
->m_aAndInvertedGC
, GXandInverted
);
555 XSetFunction( pDisp_
, pSD
->m_aAndGC
, GXand
);
556 // PowerPC Solaris 2.5 (XSun 3500) Bug: GXor = GXnop
557 XSetFunction( pDisp_
, pSD
->m_aOrGC
, GXxor
);
559 if( 1 == pSD
->m_aVisual
.GetDepth() )
561 XSetFunction( pDisp_
, pSD
->m_aCopyGC
, GXcopyInverted
);
562 pSD
->m_aMonoGC
= pSD
->m_aCopyGC
;
566 Pixmap hPixmap
= XCreatePixmap( pDisp_
, pSD
->m_aRefWindow
, 1, 1, 1 );
567 pSD
->m_aMonoGC
= XCreateGC( pDisp_
,
571 XFreePixmap( pDisp_
, hPixmap
);
573 pSD
->m_hInvert50
= XCreateBitmapFromData( pDisp_
,
575 reinterpret_cast<const char*>(invert50_bits
),
582 void SalDisplay::Init()
584 for( Cursor
& aCsr
: aPointerCache_
)
589 int nDisplayScreens
= ScreenCount( pDisp_
);
590 m_aScreens
= std::vector
<ScreenData
>(nDisplayScreens
);
592 bool bExactResolution
= false;
594 * Xft resolution should take precedence since
595 * it is what modern desktops use.
597 const char* pValStr
= XGetDefault( pDisp_
, "Xft", "dpi" );
598 if( pValStr
!= nullptr )
600 const OString
aValStr( pValStr
);
601 const tools::Long nDPI
= static_cast<tools::Long
>(aValStr
.toDouble());
602 // guard against insane resolution
603 if( sal_ValidDPI(nDPI
) )
605 aResolution_
= Pair( nDPI
, nDPI
);
606 bExactResolution
= true;
609 if( !bExactResolution
)
611 /* if Xft.dpi is not set, try and find the DPI from the
612 * reported screen sizes and resolution. If there are multiple
613 * screens, just fall back to the default 96x96
615 tools::Long xDPI
= 96;
616 tools::Long yDPI
= 96;
617 if (m_aScreens
.size() == 1) {
618 xDPI
= static_cast<tools::Long
>(round(DisplayWidth(pDisp_
, 0)*25.4/DisplayWidthMM(pDisp_
, 0)));
619 yDPI
= static_cast<tools::Long
>(round(DisplayHeight(pDisp_
, 0)*25.4/DisplayHeightMM(pDisp_
, 0)));
620 // if either is invalid set it equal to the other
621 if (!sal_ValidDPI(xDPI
) && sal_ValidDPI(yDPI
))
623 if (!sal_ValidDPI(yDPI
) && sal_ValidDPI(xDPI
))
625 // if both are invalid, reset them to the default
626 if (!sal_ValidDPI(xDPI
) && !sal_ValidDPI(yDPI
))
629 aResolution_
= Pair( xDPI
, yDPI
);
632 nMaxRequestSize_
= XExtendedMaxRequestSize( pDisp_
) * 4;
633 if( !nMaxRequestSize_
)
634 nMaxRequestSize_
= XMaxRequestSize( pDisp_
) * 4;
636 meServerVendor
= sal_GetServerVendor(pDisp_
);
637 X11SalBitmap::ImplCreateCache();
639 // - - - - - - - - - - Synchronize - - - - - - - - - - - - -
640 if( getenv( "SAL_SYNCHRONIZE" ) )
641 XSynchronize( pDisp_
, True
);
643 // - - - - - - - - - - Keyboardmapping - - - - - - - - - - -
646 // - - - - - - - - - - Window Manager - - - - - - - - - - -
647 m_pWMAdaptor
= ::vcl_sal::WMAdaptor::createWMAdaptor( this );
656 void SalX11Display::SetupInput()
658 GetGenericUnixSalData()->ErrorTrapPush();
659 SalI18N_KeyboardExtension
*pKbdExtension
= new SalI18N_KeyboardExtension( pDisp_
);
660 XSync( pDisp_
, False
);
662 bool bError
= GetGenericUnixSalData()->ErrorTrapPop( false );
663 GetGenericUnixSalData()->ErrorTrapPush();
664 pKbdExtension
->UseExtension( ! bError
);
665 GetGenericUnixSalData()->ErrorTrapPop();
667 SetKbdExtension( pKbdExtension
);
671 void SalDisplay::Beep() const
673 XBell( pDisp_
, 100 );
680 bool InitXkb(Display
* dpy
)
682 int nOpcode
, nEvent
, nError
;
683 int nXkbMajor
= XkbMajorVersion
;
684 int nXkbMinor
= XkbMinorVersion
;
686 if (!XkbLibraryVersion(&nXkbMajor
, &nXkbMinor
))
689 return XkbQueryExtension(
690 dpy
, &nOpcode
, &nEvent
, &nError
, &nXkbMajor
, &nXkbMinor
);
693 unsigned int GetKeySymMask(Display
* dpy
, KeySym nKeySym
)
696 XModifierKeymap
* pXmkMap
= XGetModifierMapping(dpy
);
697 KeyCode nKeyCode
= XKeysymToKeycode(dpy
, nKeySym
);
698 if (nKeyCode
== NoSymbol
)
701 for (int i
= 0; i
< 8; ++i
)
703 KeyCode nThisKeyCode
= pXmkMap
->modifiermap
[pXmkMap
->max_keypermod
*i
];
704 if (nThisKeyCode
== nKeyCode
)
707 XFreeModifiermap(pXmkMap
);
713 void SalDisplay::SimulateKeyPress( sal_uInt16 nKeyCode
)
715 if (nKeyCode
!= KEY_CAPSLOCK
)
718 Display
* dpy
= GetDisplay();
722 unsigned int nMask
= GetKeySymMask(dpy
, XK_Caps_Lock
);
723 XkbStateRec xkbState
;
724 XkbGetState(dpy
, XkbUseCoreKbd
, &xkbState
);
725 unsigned int nCapsLockState
= xkbState
.locked_mods
& nMask
;
727 XkbLockModifiers (dpy
, XkbUseCoreKbd
, nMask
, 0);
729 XkbLockModifiers (dpy
, XkbUseCoreKbd
, nMask
, nMask
);
732 KeyIndicatorState
SalDisplay::GetIndicatorState() const
734 unsigned int _state
= 0;
735 KeyIndicatorState nState
= KeyIndicatorState::NONE
;
736 XkbGetIndicatorState(pDisp_
, XkbUseCoreKbd
, &_state
);
738 if (_state
& 0x00000001)
739 nState
|= KeyIndicatorState::CAPSLOCK
;
740 if (_state
& 0x00000002)
741 nState
|= KeyIndicatorState::NUMLOCK
;
742 if (_state
& 0x00000004)
743 nState
|= KeyIndicatorState::SCROLLLOCK
;
748 OUString
SalDisplay::GetKeyNameFromKeySym( KeySym nKeySym
) const
750 OUString aLang
= Application::GetSettings().GetUILanguageTag().getLanguage();
753 // return an empty string for keysyms that are not bound to
755 KeyCode aKeyCode
= XKeysymToKeycode( GetDisplay(), nKeySym
);
756 static_assert(NoSymbol
== 0, "X11 inconsistency");
757 if( aKeyCode
!= NoSymbol
)
763 aRet
= ::vcl_sal::getKeysymReplacementName( aLang
, nKeySym
);
766 const char *pString
= XKeysymToString( nKeySym
);
769 int n
= strlen( pString
);
770 if( n
> 2 && pString
[n
-2] == '_' )
771 aRet
= OUString( pString
, n
-2, RTL_TEXTENCODING_ISO_8859_1
);
773 aRet
= OUString( pString
, n
, RTL_TEXTENCODING_ISO_8859_1
);
783 static KeySym
sal_XModifier2Keysym( Display
*pDisplay
,
784 XModifierKeymap
const *pXModMap
,
787 return XkbKeycodeToKeysym( pDisplay
,
788 pXModMap
->modifiermap
[n
*pXModMap
->max_keypermod
],
792 void SalDisplay::ModifierMapping()
794 XModifierKeymap
*pXModMap
= XGetModifierMapping( pDisp_
);
796 bNumLockFromXS_
= True
;
797 nShiftKeySym_
= sal_XModifier2Keysym( pDisp_
, pXModMap
, ShiftMapIndex
);
798 nCtrlKeySym_
= sal_XModifier2Keysym( pDisp_
, pXModMap
, ControlMapIndex
);
799 nMod1KeySym_
= sal_XModifier2Keysym( pDisp_
, pXModMap
, Mod1MapIndex
);
800 // on Sun and SCO servers XLookupString does not account for NumLock
801 if( GetServerVendor() == vendor_sun
)
803 KeyCode aNumLock
= XKeysymToKeycode( pDisp_
, XK_Num_Lock
);
805 if( aNumLock
) for( int i
= ShiftMapIndex
; i
<= Mod5MapIndex
; i
++ )
807 if( pXModMap
->modifiermap
[i
*pXModMap
->max_keypermod
] == aNumLock
)
809 bNumLockFromXS_
= False
;
816 XFreeModifiermap( pXModMap
);
819 OUString
SalDisplay::GetKeyName( sal_uInt16 nKeyCode
) const
822 OUString aCustomKeyName
;
824 if( nKeyCode
& KEY_MOD1
)
825 aStrMap
+= GetKeyNameFromKeySym( nCtrlKeySym_
);
827 if( nKeyCode
& KEY_MOD2
)
829 if( !aStrMap
.isEmpty() )
831 aStrMap
+= GetKeyNameFromKeySym( nMod1KeySym_
);
834 if( nKeyCode
& KEY_SHIFT
)
836 if( !aStrMap
.isEmpty() )
838 aStrMap
+= GetKeyNameFromKeySym( nShiftKeySym_
);
844 if( KEY_0
<= nKeyCode
&& nKeyCode
<= KEY_9
)
845 nKeySym
= XK_0
+ (nKeyCode
- KEY_0
);
846 else if( KEY_A
<= nKeyCode
&& nKeyCode
<= KEY_Z
)
847 nKeySym
= XK_A
+ (nKeyCode
- KEY_A
);
848 else if( KEY_F1
<= nKeyCode
&& nKeyCode
<= KEY_F26
) // does this key exist?
849 nKeySym
= XK_F1
+ (nKeyCode
- KEY_F1
);
850 else switch( nKeyCode
)
871 nKeySym
= XK_Page_Up
;
874 nKeySym
= XK_Page_Down
;
886 nKeySym
= XK_BackSpace
;
898 #if !defined (SunXK_Undo)
899 // we don't intend to use SunXK_Undo, but if it has not been
900 // defined already, then we _do_ need the following:
901 #define SunXK_Props 0x1005FF70
902 #define SunXK_Front 0x1005FF71
903 #define SunXK_Copy 0x1005FF72
904 #define SunXK_Open 0x1005FF73
905 #define SunXK_Paste 0x1005FF74
906 #define SunXK_Cut 0x1005FF75
908 // the following are for XF86 systems
909 #define XF86XK_Copy 0x1008FF57
910 #define XF86XK_Cut 0x1008FF58
911 #define XF86XK_Open 0x1008FF6B
912 #define XF86XK_Paste 0x1008FF6D
913 // which leaves Apollo and OSF systems in the lurch
919 nKeySym
= SunXK_Props
;
925 nKeySym
= SunXK_Front
;
928 nKeySym
= GetServerVendor() == vendor_sun
? SunXK_Copy
: XF86XK_Copy
;
931 nKeySym
= GetServerVendor() == vendor_sun
? SunXK_Open
: XF86XK_Open
;
934 nKeySym
= GetServerVendor() == vendor_sun
? SunXK_Paste
: XF86XK_Paste
;
940 nKeySym
= GetServerVendor() == vendor_sun
? SunXK_Cut
: XF86XK_Cut
;
941 /* The original code here had:
942 nKeySym = GetServerVendor() == vendor_sun ? SunXK_Cut : XK_L10;
943 if anyone can remember which non-vendor_sun system used this
944 XK_L10 keysym, and why this hack only applied to KEY_CUT,
945 then please re-hack this code to put it back
949 aCustomKeyName
= "+";
952 aCustomKeyName
= "-";
955 nKeySym
= XK_asterisk
;
961 aCustomKeyName
= ".";
970 nKeySym
= XK_greater
;
978 case KEY_HANGUL_HANJA
:
979 nKeySym
= XK_Hangul_Hanja
;
982 nKeySym
= XK_asciitilde
;
987 case KEY_BRACKETLEFT
:
988 aCustomKeyName
= "[";
990 case KEY_BRACKETRIGHT
:
991 aCustomKeyName
= "]";
994 aCustomKeyName
= ";";
997 aCustomKeyName
= "'";
1006 OUString aKeyName
= GetKeyNameFromKeySym( nKeySym
);
1007 if( !aKeyName
.isEmpty() )
1009 if( !aStrMap
.isEmpty() )
1011 aStrMap
+= aKeyName
;
1016 else if (!aCustomKeyName
.isEmpty())
1018 // For semicolon, bracket left and bracket right, it's better to use
1019 // their keys than their names. (fdo#32891)
1020 if (!aStrMap
.isEmpty())
1022 aStrMap
+= aCustomKeyName
;
1031 #define IsISOKey( n ) (0x0000FE00==((n)&0xFFFFFF00))
1034 sal_uInt16
SalDisplay::GetKeyCode( KeySym keysym
, char*pcPrintable
) const
1036 sal_uInt16 nKey
= 0;
1038 if( XK_a
<= keysym
&& XK_z
>= keysym
)
1039 nKey
= static_cast<sal_uInt16
>(KEY_A
+ (keysym
- XK_a
));
1040 else if( XK_A
<= keysym
&& XK_Z
>= keysym
)
1041 nKey
= static_cast<sal_uInt16
>(KEY_A
+ (keysym
- XK_A
));
1042 else if( XK_0
<= keysym
&& XK_9
>= keysym
)
1043 nKey
= static_cast<sal_uInt16
>(KEY_0
+ (keysym
- XK_0
));
1044 else if( IsModifierKey( keysym
) )
1046 else if( IsKeypadKey( keysym
) )
1048 if( (keysym
>= XK_KP_0
) && (keysym
<= XK_KP_9
) )
1050 nKey
= static_cast<sal_uInt16
>(KEY_0
+ (keysym
- XK_KP_0
));
1051 *pcPrintable
= '0' + nKey
- KEY_0
;
1053 else if( IsPFKey( keysym
) )
1054 nKey
= static_cast<sal_uInt16
>(KEY_F1
+ (keysym
- XK_KP_F1
));
1055 else switch( keysym
)
1083 case XK_KP_Page_Up
: // XK_KP_Page_Up
1086 case XK_KP_Page_Down
: // XK_KP_Page_Down
1087 nKey
= KEY_PAGEDOWN
;
1102 case XK_KP_Multiply
:
1103 nKey
= KEY_MULTIPLY
;
1110 case XK_KP_Separator
:
1114 case XK_KP_Subtract
:
1115 nKey
= KEY_SUBTRACT
;
1128 else if( IsFunctionKey( keysym
) )
1130 if( bNumLockFromXS_
)
1132 if( keysym
>= XK_F1
&& keysym
<= XK_F26
)
1133 nKey
= static_cast<sal_uInt16
>(KEY_F1
+ keysym
- XK_F1
);
1135 else switch( keysym
)
1137 // - - - - - Sun X-Server keyboard without Cursorblock ??? - - -
1138 case XK_R7
: // XK_F27:
1141 case XK_R8
: // XK_F28:
1144 case XK_R9
: // XK_F29:
1147 case XK_R10
: // XK_F30:
1150 case XK_R11
: // XK_F31:
1151 nKey
= 0; // KEY_F31
1153 case XK_R12
: // XK_F32:
1156 case XK_R13
: // XK_F33:
1159 case XK_R14
: // XK_F34:
1162 case XK_R15
: // XK_F35:
1163 nKey
= KEY_PAGEDOWN
;
1165 // - - - - - Sun X-Server keyboard ??? - - - - - - - - - - - -
1166 case XK_L1
: // XK_F11:
1167 nKey
= KEY_F11
; // on a sun keyboard this actually is usually SunXK_Stop = 0x0000FF69 (XK_Cancel),
1168 // but VCL doesn't have a key definition for that
1170 case XK_L2
: // XK_F12:
1171 if ( GetServerVendor() == vendor_sun
)
1176 case XK_L3
: // XK_F13:
1177 nKey
= KEY_PROPERTIES
; // KEY_F13
1179 case XK_L4
: // XK_F14:
1180 nKey
= KEY_UNDO
; // KEY_F14
1182 case XK_L5
: // XK_F15:
1183 nKey
= KEY_F15
; // KEY_FRONT
1185 case XK_L6
: // XK_F16:
1186 nKey
= KEY_COPY
; // KEY_F16
1188 case XK_L7
: // XK_F17:
1189 nKey
= KEY_F17
; // KEY_OPEN
1191 case XK_L8
: // XK_F18:
1192 nKey
= KEY_PASTE
; // KEY_F18
1194 case XK_L9
: // XK_F19:
1195 nKey
= KEY_F19
; // KEY_FIND
1197 case XK_L10
: // XK_F20:
1198 nKey
= KEY_CUT
; // KEY_F20
1201 if( keysym
>= XK_F1
&& keysym
<= XK_F26
)
1202 nKey
= static_cast<sal_uInt16
>(KEY_F1
+ keysym
- XK_F1
);
1206 else if( IsCursorKey( keysym
) )
1226 case XK_Page_Up
: // XK_Page_Up
1229 case XK_Page_Down
: // XK_Page_Down
1230 nKey
= KEY_PAGEDOWN
;
1237 else if( IsMiscFunctionKey( keysym
) )
1257 nKey
= KEY_CONTEXTMENU
;
1261 else if( IsISOKey( keysym
) ) // XK_ISO_
1265 case 0xFE20: // XK_ISO_Left_Tab:
1270 else switch( keysym
)
1276 nKey
= KEY_BACKSPACE
;
1294 nKey
= KEY_SUBTRACT
;
1297 nKey
= KEY_MULTIPLY
;
1318 case XK_Hangul_Hanja
:
1319 nKey
= KEY_HANGUL_HANJA
;
1326 nKey
= KEY_QUOTELEFT
;
1329 case XK_bracketleft
:
1330 nKey
= KEY_BRACKETLEFT
;
1333 case XK_bracketright
:
1334 nKey
= KEY_BRACKETRIGHT
;
1338 nKey
= KEY_SEMICOLON
;
1342 nKey
= KEY_QUOTERIGHT
;
1343 *pcPrintable
= '\'';
1345 // - - - - - - - - - - - - - Apollo - - - - - - - - - - - - - 0x1000
1346 case 0x1000FF02: // apXK_Copy
1349 case 0x1000FF03: // apXK_Cut
1352 case 0x1000FF04: // apXK_Paste
1355 case 0x1000FF14: // apXK_Repeat
1359 // - - - - - - - - - - - - - - D E C - - - - - - - - - - - - - 0x1000
1363 // - - - - - - - - - - - - - - H P - - - - - - - - - - - - - 0x1000
1364 case 0x1000FF73: // hpXK_DeleteChar
1367 case 0x1000FF74: // hpXK_BackTab
1368 case 0x1000FF75: // hpXK_KP_BackTab
1371 // - - - - - - - - - - - - - - I B M - - - - - - - - - - - - -
1372 // - - - - - - - - - - - - - - O S F - - - - - - - - - - - - - 0x1004
1373 case 0x1004FF02: // osfXK_Copy
1376 case 0x1004FF03: // osfXK_Cut
1379 case 0x1004FF04: // osfXK_Paste
1382 case 0x1004FF07: // osfXK_BackTab
1385 case 0x1004FF08: // osfXK_BackSpace
1386 nKey
= KEY_BACKSPACE
;
1388 case 0x1004FF1B: // osfXK_Escape
1391 // Up, Down, Left, Right, PageUp, PageDown
1392 // - - - - - - - - - - - - - - S C O - - - - - - - - - - - - -
1393 // - - - - - - - - - - - - - - S G I - - - - - - - - - - - - - 0x1007
1394 // - - - - - - - - - - - - - - S N I - - - - - - - - - - - - -
1395 // - - - - - - - - - - - - - - S U N - - - - - - - - - - - - - 0x1005
1396 case 0x1005FF10: // SunXK_F36
1399 case 0x1005FF11: // SunXK_F37
1402 case 0x1005FF70: // SunXK_Props
1403 nKey
= KEY_PROPERTIES
;
1405 case 0x1005FF71: // SunXK_Front
1408 case 0x1005FF72: // SunXK_Copy
1411 case 0x1005FF73: // SunXK_Open
1414 case 0x1005FF74: // SunXK_Paste
1417 case 0x1005FF75: // SunXK_Cut
1424 KeySym
SalDisplay::GetKeySym( XKeyEvent
*pEvent
,
1427 KeySym
*pUnmodifiedKeySym
,
1428 Status
*pStatusReturn
,
1429 XIC aInputContext
) const
1432 memset( pPrintable
, 0, *pLen
);
1435 SalI18N_InputMethod
* const pInputMethod
=
1436 pXLib_
? pXLib_
->GetInputMethod() : nullptr;
1438 // first get the printable of the possibly modified KeySym
1439 if ( (aInputContext
== nullptr)
1440 || (pEvent
->type
== KeyRelease
)
1441 || (pInputMethod
!= nullptr && pInputMethod
->PosixLocale()) )
1443 // XmbLookupString must not be called for KeyRelease events
1444 // Cannot enter space in c locale problem #89616# #88978# btraq #4478197
1445 *pLen
= XLookupString( pEvent
, pPrintable
, 1, &nKeySym
, nullptr );
1449 *pLen
= XmbLookupString( aInputContext
,
1450 pEvent
, pPrintable
, *pLen
- 1, &nKeySym
, pStatusReturn
);
1452 // Lookup the string again, now with appropriate size
1453 if ( *pStatusReturn
== XBufferOverflow
)
1455 pPrintable
[ 0 ] = '\0';
1459 switch ( *pStatusReturn
)
1461 case XBufferOverflow
:
1462 /* unhandled error */
1465 /* unhandled error */
1468 /* this is a strange one: on exceed sometimes
1469 * no printable is returned for the first char entered,
1470 * just to retry lookup solves the problem. The problem
1471 * is not yet fully understood, so restrict 2nd lookup
1472 * to 7bit ascii chars */
1473 if ( (XK_space
<= nKeySym
) && (XK_asciitilde
>= nKeySym
) )
1476 pPrintable
[ 0 ] = static_cast<char>(nKeySym
);
1482 /* nothing to, char already in pPrintable */
1487 if( !bNumLockFromXS_
1488 && (IsCursorKey(nKeySym
)
1489 || IsFunctionKey(nKeySym
)
1490 || IsKeypadKey(nKeySym
)
1491 || XK_Delete
== nKeySym
) )
1493 // For some X-servers special care is needed for Keypad keys.
1494 // For example Solaris XServer:
1495 // 2, 4, 6, 8 are classified as Cursorkeys (Up, Down, Left, Right)
1496 // 1, 3, 5, 9 are classified as Functionkeys (F27,F29,F33,F35)
1497 // 0 as Keypadkey, and the decimal point key not at all (KP_Insert)
1498 KeySym nNewKeySym
= XLookupKeysym( pEvent
, nNumLockIndex_
);
1499 if( nNewKeySym
!= NoSymbol
)
1500 nKeySym
= nNewKeySym
;
1503 // Now get the unmodified KeySym for KeyCode retrieval
1504 // try to strip off modifiers, e.g. Ctrl-$ becomes Ctrl-Shift-4
1505 *pUnmodifiedKeySym
= XkbKeycodeToKeysym( GetDisplay(), pEvent
->keycode
, 0, 0);
1511 static unsigned char nullmask_bits
[] = { 0x00, 0x00, 0x00, 0x00 };
1512 static unsigned char nullcurs_bits
[] = { 0x00, 0x00, 0x00, 0x00 };
1514 #define MAKE_BITMAP( name ) \
1515 XCreateBitmapFromData( pDisp_, \
1516 DefaultRootWindow( pDisp_ ), \
1517 reinterpret_cast<const char*>(name##_bits), \
1521 #define MAKE_CURSOR( name ) \
1522 aCursBitmap = MAKE_BITMAP( name##curs ); \
1523 aMaskBitmap = MAKE_BITMAP( name##mask ); \
1524 nXHot = name##curs_x_hot; \
1525 nYHot = name##curs_y_hot
1527 Cursor
SalDisplay::GetPointer( PointerStyle ePointerStyle
)
1529 Cursor
&aCur
= aPointerCache_
[ePointerStyle
];
1534 Pixmap aCursBitmap
= None
, aMaskBitmap
= None
;
1535 unsigned int nXHot
= 0, nYHot
= 0;
1537 switch( ePointerStyle
)
1539 case PointerStyle::Null
:
1540 MAKE_CURSOR( null
);
1542 case PointerStyle::Arrow
:
1543 aCur
= XCreateFontCursor( pDisp_
, XC_left_ptr
);
1544 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1546 case PointerStyle::Wait
:
1547 aCur
= XCreateFontCursor( pDisp_
, XC_watch
);
1549 case PointerStyle::Text
: // Mouse Pointer is a "I" Beam
1550 aCur
= XCreateFontCursor( pDisp_
, XC_xterm
);
1551 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1553 case PointerStyle::Help
:
1554 aCur
= XCreateFontCursor( pDisp_
, XC_question_arrow
);
1555 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1557 case PointerStyle::Cross
: // Mouse Pointer is a cross
1558 aCur
= XCreateFontCursor( pDisp_
, XC_crosshair
);
1559 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1561 case PointerStyle::NSize
:
1562 aCur
= XCreateFontCursor( pDisp_
, XC_sb_v_double_arrow
);
1563 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1565 case PointerStyle::SSize
:
1566 aCur
= XCreateFontCursor( pDisp_
, XC_sb_v_double_arrow
);
1567 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1569 case PointerStyle::WSize
:
1570 aCur
= XCreateFontCursor( pDisp_
, XC_sb_h_double_arrow
);
1571 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1573 case PointerStyle::ESize
:
1574 aCur
= XCreateFontCursor( pDisp_
, XC_sb_h_double_arrow
);
1575 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1577 case PointerStyle::WindowNSize
:
1578 aCur
= XCreateFontCursor( pDisp_
, XC_top_side
);
1579 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1581 case PointerStyle::WindowSSize
:
1582 aCur
= XCreateFontCursor( pDisp_
, XC_bottom_side
);
1583 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1585 case PointerStyle::WindowWSize
:
1586 aCur
= XCreateFontCursor( pDisp_
, XC_left_side
);
1587 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1589 case PointerStyle::WindowESize
:
1590 aCur
= XCreateFontCursor( pDisp_
, XC_right_side
);
1591 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1593 case PointerStyle::NWSize
:
1594 aCur
= XCreateFontCursor( pDisp_
, XC_top_left_corner
);
1596 case PointerStyle::NESize
:
1597 aCur
= XCreateFontCursor( pDisp_
, XC_top_right_corner
);
1599 case PointerStyle::SWSize
:
1600 aCur
= XCreateFontCursor( pDisp_
, XC_bottom_left_corner
);
1602 case PointerStyle::SESize
:
1603 aCur
= XCreateFontCursor( pDisp_
, XC_bottom_right_corner
);
1605 case PointerStyle::WindowNWSize
:
1606 aCur
= XCreateFontCursor( pDisp_
, XC_top_left_corner
);
1607 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1609 case PointerStyle::WindowNESize
:
1610 aCur
= XCreateFontCursor( pDisp_
, XC_top_right_corner
);
1611 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1613 case PointerStyle::WindowSWSize
:
1614 aCur
= XCreateFontCursor( pDisp_
, XC_bottom_left_corner
);
1615 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1617 case PointerStyle::WindowSESize
:
1618 aCur
= XCreateFontCursor( pDisp_
, XC_bottom_right_corner
);
1619 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1621 case PointerStyle::HSplit
:
1622 aCur
= XCreateFontCursor( pDisp_
, XC_sb_h_double_arrow
);
1624 case PointerStyle::VSplit
:
1625 aCur
= XCreateFontCursor( pDisp_
, XC_sb_v_double_arrow
);
1627 case PointerStyle::HSizeBar
:
1628 aCur
= XCreateFontCursor( pDisp_
, XC_sb_h_double_arrow
); // ???
1629 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1631 case PointerStyle::VSizeBar
:
1632 aCur
= XCreateFontCursor( pDisp_
, XC_sb_v_double_arrow
); // ???
1633 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1635 case PointerStyle::RefHand
:
1636 aCur
= XCreateFontCursor( pDisp_
, XC_hand1
);
1637 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1639 case PointerStyle::Hand
:
1640 aCur
= XCreateFontCursor( pDisp_
, XC_hand2
);
1642 case PointerStyle::Magnify
:
1643 MAKE_CURSOR( magnify_
);
1645 case PointerStyle::Fill
:
1646 MAKE_CURSOR( fill_
);
1648 case PointerStyle::Move
:
1649 aCur
= XCreateFontCursor( pDisp_
, XC_fleur
);
1651 case PointerStyle::MoveData
:
1652 MAKE_CURSOR( movedata_
);
1654 case PointerStyle::CopyData
:
1655 MAKE_CURSOR( copydata_
);
1657 case PointerStyle::MoveFile
:
1658 MAKE_CURSOR( movefile_
);
1660 case PointerStyle::CopyFile
:
1661 MAKE_CURSOR( copyfile_
);
1663 case PointerStyle::MoveFiles
:
1664 MAKE_CURSOR( movefiles_
);
1666 case PointerStyle::CopyFiles
:
1667 MAKE_CURSOR( copyfiles_
);
1669 case PointerStyle::NotAllowed
:
1670 MAKE_CURSOR( nodrop_
);
1672 case PointerStyle::Rotate
:
1673 MAKE_CURSOR( rotate_
);
1675 case PointerStyle::HShear
:
1676 MAKE_CURSOR( hshear_
);
1678 case PointerStyle::VShear
:
1679 MAKE_CURSOR( vshear_
);
1681 case PointerStyle::DrawLine
:
1682 MAKE_CURSOR( drawline_
);
1684 case PointerStyle::DrawRect
:
1685 MAKE_CURSOR( drawrect_
);
1687 case PointerStyle::DrawPolygon
:
1688 MAKE_CURSOR( drawpolygon_
);
1690 case PointerStyle::DrawBezier
:
1691 MAKE_CURSOR( drawbezier_
);
1693 case PointerStyle::DrawArc
:
1694 MAKE_CURSOR( drawarc_
);
1696 case PointerStyle::DrawPie
:
1697 MAKE_CURSOR( drawpie_
);
1699 case PointerStyle::DrawCircleCut
:
1700 MAKE_CURSOR( drawcirclecut_
);
1702 case PointerStyle::DrawEllipse
:
1703 MAKE_CURSOR( drawellipse_
);
1705 case PointerStyle::DrawConnect
:
1706 MAKE_CURSOR( drawconnect_
);
1708 case PointerStyle::DrawText
:
1709 MAKE_CURSOR( drawtext_
);
1711 case PointerStyle::Mirror
:
1712 MAKE_CURSOR( mirror_
);
1714 case PointerStyle::Crook
:
1715 MAKE_CURSOR( crook_
);
1717 case PointerStyle::Crop
:
1718 MAKE_CURSOR( crop_
);
1720 case PointerStyle::MovePoint
:
1721 MAKE_CURSOR( movepoint_
);
1723 case PointerStyle::MoveBezierWeight
:
1724 MAKE_CURSOR( movebezierweight_
);
1726 case PointerStyle::DrawFreehand
:
1727 MAKE_CURSOR( drawfreehand_
);
1729 case PointerStyle::DrawCaption
:
1730 MAKE_CURSOR( drawcaption_
);
1732 case PointerStyle::Pen
: // Mouse Pointer is a pencil
1733 aCur
= XCreateFontCursor( pDisp_
, XC_pencil
);
1734 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1736 case PointerStyle::LinkData
:
1737 MAKE_CURSOR( linkdata_
);
1739 case PointerStyle::MoveDataLink
:
1740 MAKE_CURSOR( movedlnk_
);
1742 case PointerStyle::CopyDataLink
:
1743 MAKE_CURSOR( copydlnk_
);
1745 case PointerStyle::LinkFile
:
1746 MAKE_CURSOR( linkfile_
);
1748 case PointerStyle::MoveFileLink
:
1749 MAKE_CURSOR( moveflnk_
);
1751 case PointerStyle::CopyFileLink
:
1752 MAKE_CURSOR( copyflnk_
);
1754 case PointerStyle::Chart
:
1755 MAKE_CURSOR( chart_
);
1757 case PointerStyle::Detective
:
1758 MAKE_CURSOR( detective_
);
1760 case PointerStyle::PivotCol
:
1761 MAKE_CURSOR( pivotcol_
);
1763 case PointerStyle::PivotRow
:
1764 MAKE_CURSOR( pivotrow_
);
1766 case PointerStyle::PivotField
:
1767 MAKE_CURSOR( pivotfld_
);
1769 case PointerStyle::PivotDelete
:
1770 MAKE_CURSOR( pivotdel_
);
1772 case PointerStyle::Chain
:
1773 MAKE_CURSOR( chain_
);
1775 case PointerStyle::ChainNotAllowed
:
1776 MAKE_CURSOR( chainnot_
);
1778 case PointerStyle::AutoScrollN
:
1781 case PointerStyle::AutoScrollS
:
1782 MAKE_CURSOR( ass_
);
1784 case PointerStyle::AutoScrollW
:
1785 MAKE_CURSOR( asw_
);
1787 case PointerStyle::AutoScrollE
:
1788 MAKE_CURSOR( ase_
);
1790 case PointerStyle::AutoScrollNW
:
1791 MAKE_CURSOR( asnw_
);
1793 case PointerStyle::AutoScrollNE
:
1794 MAKE_CURSOR( asne_
);
1796 case PointerStyle::AutoScrollSW
:
1797 MAKE_CURSOR( assw_
);
1799 case PointerStyle::AutoScrollSE
:
1800 MAKE_CURSOR( asse_
);
1802 case PointerStyle::AutoScrollNS
:
1803 MAKE_CURSOR( asns_
);
1805 case PointerStyle::AutoScrollWE
:
1806 MAKE_CURSOR( aswe_
);
1808 case PointerStyle::AutoScrollNSWE
:
1809 MAKE_CURSOR( asnswe_
);
1811 case PointerStyle::TextVertical
:
1812 MAKE_CURSOR( vertcurs_
);
1815 // #i32329# Enhanced table selection
1816 case PointerStyle::TabSelectS
:
1817 MAKE_CURSOR( tblsels_
);
1819 case PointerStyle::TabSelectE
:
1820 MAKE_CURSOR( tblsele_
);
1822 case PointerStyle::TabSelectSE
:
1823 MAKE_CURSOR( tblselse_
);
1825 case PointerStyle::TabSelectW
:
1826 MAKE_CURSOR( tblselw_
);
1828 case PointerStyle::TabSelectSW
:
1829 MAKE_CURSOR( tblselsw_
);
1832 case PointerStyle::HideWhitespace
:
1833 MAKE_CURSOR( hidewhitespace_
);
1835 case PointerStyle::ShowWhitespace
:
1836 MAKE_CURSOR( showwhitespace_
);
1840 OSL_FAIL("pointer not implemented");
1841 aCur
= XCreateFontCursor( pDisp_
, XC_arrow
);
1847 XColor aBlack
, aWhite
, aDummy
;
1848 Colormap hColormap
= GetColormap(m_nXDefaultScreen
).GetXColormap();
1850 XAllocNamedColor( pDisp_
, hColormap
, "black", &aBlack
, &aDummy
);
1851 XAllocNamedColor( pDisp_
, hColormap
, "white", &aWhite
, &aDummy
);
1853 aCur
= XCreatePixmapCursor( pDisp_
,
1854 aCursBitmap
, aMaskBitmap
,
1858 XFreePixmap( pDisp_
, aCursBitmap
);
1859 XFreePixmap( pDisp_
, aMaskBitmap
);
1865 int SalDisplay::CaptureMouse( SalFrame
*pCapture
)
1867 static const char* pEnv
= getenv( "SAL_NO_MOUSEGRABS" );
1871 m_pCapture
= nullptr;
1872 if( !pEnv
|| !*pEnv
)
1873 XUngrabPointer( GetDisplay(), CurrentTime
);
1874 XFlush( GetDisplay() );
1878 m_pCapture
= nullptr;
1880 // FIXME: get rid of X11SalFrame
1881 const SystemEnvData
* pEnvData
= pCapture
->GetSystemData();
1882 if( !pEnv
|| !*pEnv
)
1884 int ret
= XGrabPointer( GetDisplay(),
1885 static_cast<::Window
>(pEnvData
->GetWindowHandle(pCapture
)),
1887 PointerMotionMask
| ButtonPressMask
|ButtonReleaseMask
,
1891 static_cast<X11SalFrame
*>(pCapture
)->GetCursor(),
1894 if( ret
!= GrabSuccess
)
1896 SAL_WARN("vcl", "SalDisplay::CaptureMouse could not grab pointer: " << ret
);
1901 m_pCapture
= pCapture
;
1907 bool SalX11Display::IsEvent()
1909 if( HasUserEvents() || XEventsQueued( pDisp_
, QueuedAlready
) )
1916 void SalX11Display::Yield()
1918 if( DispatchInternalEvent() )
1922 DBG_ASSERT( GetSalData()->m_pInstance
->GetYieldMutex()->IsCurrentThread(),
1923 "will crash soon since solar mutex not locked in SalDisplay::Yield" );
1925 XNextEvent( pDisp_
, &aEvent
);
1927 // FIXME: under-convinced by Dispatch boolean return value vs. salframe.
1928 Dispatch( &aEvent
);
1931 if( GetX11SalData()->HasXErrorOccurred() )
1934 DbgPrintDisplayEvent("SalDisplay::Yield (WasXError)", &aEvent
);
1937 GetX11SalData()->ResetXErrorOccurred();
1940 bool SalX11Display::Dispatch( XEvent
*pEvent
)
1942 SalI18N_InputMethod
* const pInputMethod
=
1943 pXLib_
? pXLib_
->GetInputMethod() : nullptr;
1947 ::Window aFrameWindow
= None
;
1948 if( pEvent
->type
== KeyPress
|| pEvent
->type
== KeyRelease
)
1950 const ::Window aWindow
= pEvent
->xkey
.window
;
1951 for( auto pSalFrame
: m_aFrames
)
1953 const X11SalFrame
* pFrame
= static_cast< const X11SalFrame
* >( pSalFrame
);
1954 const ::Window aCurFrameWindow
= pFrame
->GetWindow();
1955 if( aCurFrameWindow
== aWindow
|| pFrame
->GetShellWindow() == aWindow
)
1957 aFrameWindow
= aCurFrameWindow
;
1962 if( pInputMethod
->FilterEvent( pEvent
, aFrameWindow
) )
1966 SalInstance
* pInstance
= GetSalData()->m_pInstance
;
1967 pInstance
->CallEventCallback( pEvent
, sizeof( XEvent
) );
1969 switch( pEvent
->type
)
1972 while( XCheckWindowEvent( pEvent
->xany
.display
,
1973 pEvent
->xany
.window
,
1977 m_nLastUserEventTime
= pEvent
->xmotion
.time
;
1979 case PropertyNotify
:
1980 if( pEvent
->xproperty
.atom
== getWMAdaptor()->getAtom( WMAdaptor::VCL_SYSTEM_SETTINGS
) )
1982 for(const ScreenData
& rScreen
: m_aScreens
)
1984 if( pEvent
->xproperty
.window
== rScreen
.m_aRefWindow
)
1986 for (auto pSalFrame
: m_aFrames
)
1987 pSalFrame
->CallCallback( SalEvent::SettingsChanged
, nullptr );
1994 if( MappingModifier
== pEvent
->xmapping
.request
)
1996 XRefreshKeyboardMapping( &pEvent
->xmapping
);
2002 m_nLastUserEventTime
= pEvent
->xbutton
.time
;
2006 m_nLastUserEventTime
= pEvent
->xkey
.time
;
2010 if ( GetKbdExtension()->UseExtension()
2011 && GetKbdExtension()->GetEventBase() == pEvent
->type
)
2013 GetKbdExtension()->Dispatch( pEvent
);
2019 for (auto pSalFrame
: m_aFrames
)
2021 X11SalFrame
* pFrame
= static_cast<X11SalFrame
*>( pSalFrame
);
2023 ::Window aDispatchWindow
= pEvent
->xany
.window
;
2024 if( pFrame
->GetWindow() == aDispatchWindow
2025 || pFrame
->GetShellWindow() == aDispatchWindow
2026 || pFrame
->GetForeignParent() == aDispatchWindow
2029 return pFrame
->Dispatch( pEvent
);
2031 if( pEvent
->type
== ConfigureNotify
&& pEvent
->xconfigure
.window
== pFrame
->GetStackingWindow() )
2033 return pFrame
->Dispatch( pEvent
);
2037 // dispatch to salobjects
2038 X11SalObject::Dispatch( pEvent
);
2040 // is this perhaps a root window that changed size ?
2041 processRandREvent( pEvent
);
2047 void SalDisplay::DbgPrintDisplayEvent(const char *pComment
, const XEvent
*pEvent
) const
2049 static const char* const EventNames
[] =
2088 if( pEvent
->type
<= MappingNotify
)
2090 SAL_INFO("vcl.app", "[" << pComment
<< "] "
2091 << EventNames
[pEvent
->type
]
2092 << " s=" << pEvent
->xany
.send_event
2093 << " w=" << pEvent
->xany
.window
);
2095 switch( pEvent
->type
)
2099 SAL_INFO("vcl.app", "\t\ts=" << pEvent
->xkey
.state
2100 << " c=" << pEvent
->xkey
.keycode
);
2105 SAL_INFO("vcl.app", "\t\ts=" << pEvent
->xbutton
.state
2106 << " b=" << pEvent
->xbutton
.button
2107 << " x=" << pEvent
->xbutton
.x
2108 << " y=" << pEvent
->xbutton
.y
2109 << " rx=" << pEvent
->xbutton
.x_root
2110 << " ry=" << pEvent
->xbutton
.y_root
);
2114 SAL_INFO("vcl.app", "\t\ts=" << pEvent
->xmotion
.state
2115 << " x=" << pEvent
->xmotion
.x
2116 << " y=" << pEvent
->xmotion
.y
);
2121 SAL_INFO("vcl.app", "\t\tm=" << pEvent
->xcrossing
.mode
2122 << " f=" << pEvent
->xcrossing
.focus
2123 << " x=" << pEvent
->xcrossing
.x
2124 << " y=" << pEvent
->xcrossing
.y
);
2129 SAL_INFO("vcl.app", "\t\tm=" << pEvent
->xfocus
.mode
2130 << " d=" << pEvent
->xfocus
.detail
);
2134 case GraphicsExpose
:
2135 SAL_INFO("vcl.app", "\t\tc=" << pEvent
->xexpose
.count
2136 << " " << pEvent
->xexpose
.width
2137 << "*" << pEvent
->xexpose
.height
2138 << " " << pEvent
->xexpose
.x
2139 << "+" << pEvent
->xexpose
.y
);
2142 case VisibilityNotify
:
2143 SAL_INFO("vcl.app", "\t\ts=" << pEvent
->xvisibility
.state
);
2154 case ReparentNotify
:
2155 SAL_INFO("vcl.app", "\t\tp=" << sal::static_int_cast
< int >(
2156 pEvent
->xreparent
.parent
)
2157 << " x=" << pEvent
->xreparent
.x
2158 << " y=" << pEvent
->xreparent
.y
);
2161 case ConfigureNotify
:
2162 SAL_INFO("vcl.app", "\t\tb=" << pEvent
->xconfigure
.border_width
2163 << " " << pEvent
->xconfigure
.width
2164 << "*" << pEvent
->xconfigure
.height
2165 << " " << pEvent
->xconfigure
.x
2166 << "+" << pEvent
->xconfigure
.y
);
2169 case PropertyNotify
:
2170 SAL_INFO("vcl.app", "\t\ta=" << GetAtomName(
2171 pDisp_
, pEvent
->xproperty
.atom
)
2172 << std::showbase
<< std::hex
<< std::uppercase
2173 << " (" << sal::static_int_cast
< unsigned int >(
2174 pEvent
->xproperty
.atom
) << ").");
2177 case ColormapNotify
:
2178 SAL_INFO("vcl.app", "\t\tc=" << pEvent
->xcolormap
.colormap
2179 << " n=" << pEvent
->xcolormap
.c_new
2180 << " s=" << pEvent
->xcolormap
.state
);
2184 SAL_INFO("vcl.app", "\t\ta=" << GetAtomName(
2185 pDisp_
, pEvent
->xclient
.message_type
)
2186 << std::showbase
<< std::hex
<< std::uppercase
2187 << " (" << sal::static_int_cast
< unsigned int >(
2188 pEvent
->xclient
.message_type
) << ")"
2190 << " f=" << pEvent
->xclient
.format
2192 << " [" << pEvent
->xclient
.data
.l
[0]
2193 << "," << pEvent
->xclient
.data
.l
[1]
2194 << "," << pEvent
->xclient
.data
.l
[2]
2195 << "," << pEvent
->xclient
.data
.l
[3]
2196 << "," << pEvent
->xclient
.data
.l
[4]
2201 SAL_INFO("vcl.app", "\t\tr="
2202 << (MappingModifier
== pEvent
->xmapping
.request
?
2204 (MappingKeyboard
== pEvent
->xmapping
.request
?
2205 "MappingKeyboard" : "MappingPointer"))
2212 SAL_INFO("vcl.app", "[" << pComment
<< "] "
2214 << " s=" << pEvent
->xany
.send_event
2215 << " w=" << pEvent
->xany
.window
);
2218 void SalDisplay::PrintInfo() const
2222 SAL_INFO( "vcl", "Environment" );
2223 SAL_INFO( "vcl", "\t$DISPLAY \t\"" << GetEnv( "DISPLAY" ) << "\"");
2224 SAL_INFO( "vcl", "\t$SAL_VISUAL \t\"" << GetEnv( "SAL_VISUAL" ) << "\"");
2225 SAL_INFO( "vcl", "\t$SAL_IGNOREXERRORS\t\"" << GetEnv( "SAL_IGNOREXERRORS" ) << "\"");
2226 SAL_INFO( "vcl", "\t$SAL_PROPERTIES \t\"" << GetEnv( "SAL_PROPERTIES" ) << "\"");
2227 SAL_INFO( "vcl", "\t$SAL_SYNCHRONIZE \t\"" << GetEnv( "SAL_SYNCHRONIZE" ) << "\"");
2229 char sHostname
[ 120 ];
2230 gethostname (sHostname
, 120 );
2231 SAL_INFO( "vcl", "Client" );
2232 SAL_INFO( "vcl", "\tHost \t\"" << sHostname
<< "\"");
2234 SAL_INFO( "vcl", "Display" );
2235 SAL_INFO( "vcl", "\tHost \t\"" << DisplayString(pDisp_
) << "\"");
2236 SAL_INFO( "vcl", "\tVendor (Release) \t\"" << ServerVendor(pDisp_
) << " (" << VendorRelease(pDisp_
) << ")\"");
2237 SAL_INFO( "vcl", "\tProtocol \t" << ProtocolVersion(pDisp_
) << "." << ProtocolRevision(pDisp_
) );
2238 SAL_INFO( "vcl", "\tScreen (count,def)\t" << m_nXDefaultScreen
.getXScreen() << " (" << ScreenCount(pDisp_
) << "," << DefaultScreen(pDisp_
) << ")");
2239 SAL_INFO( "vcl", "\tshift ctrl alt \t" << KeyStr( nShiftKeySym_
) << " (0x" << std::hex
<< sal::static_int_cast
< unsigned int >(nShiftKeySym_
) << ") "
2240 << KeyStr( nCtrlKeySym_
) << " (0x" << sal::static_int_cast
< unsigned int >(nCtrlKeySym_
) << ") "
2241 << KeyStr( nMod1KeySym_
) << " (0x" << sal::static_int_cast
< unsigned int >(nMod1KeySym_
) << ")");
2242 if( XExtendedMaxRequestSize(pDisp_
) != 0 )
2243 SAL_INFO( "vcl", "\tXMaxRequestSize \t" << XMaxRequestSize(pDisp_
) * 4 << " " << XExtendedMaxRequestSize(pDisp_
) * 4 << " [bytes]");
2244 SAL_INFO( "vcl", "\tWMName \t" << getWMAdaptor()->getWindowManagerName() );
2246 SAL_INFO( "vcl", "Screen" );
2247 SAL_INFO( "vcl", "\tResolution/Size \t" << aResolution_
.A() << "*" << aResolution_
.B()
2248 << " " << m_aScreens
[m_nXDefaultScreen
.getXScreen()].m_aSize
.Width() << "*" << m_aScreens
[m_nXDefaultScreen
.getXScreen()].m_aSize
.Height()
2249 << " " << (Hypothenuse( DisplayWidthMM ( pDisp_
, m_nXDefaultScreen
.getXScreen() ),
2250 DisplayHeightMM( pDisp_
, m_nXDefaultScreen
.getXScreen() ) ) / 25.4 ) << "\"" );
2251 SAL_INFO( "vcl", "\tBlack&White \t" << GetColormap(m_nXDefaultScreen
).GetBlackPixel() << " "
2252 << GetColormap(m_nXDefaultScreen
).GetWhitePixel() );
2253 SAL_INFO( "vcl", "\tRGB \t0x" << std::hex
<< GetVisual(m_nXDefaultScreen
).red_mask
2254 << " 0x" << GetVisual(m_nXDefaultScreen
).green_mask
2255 << " 0x" << GetVisual(m_nXDefaultScreen
).blue_mask
);
2259 void SalDisplay::addXineramaScreenUnique( int i
, tools::Long i_nX
, tools::Long i_nY
, tools::Long i_nWidth
, tools::Long i_nHeight
)
2261 // see if any frame buffers are at the same coordinates
2262 // this can happen with weird configuration e.g. on
2263 // XFree86 and Clone displays
2264 const size_t nScreens
= m_aXineramaScreens
.size();
2265 for( size_t n
= 0; n
< nScreens
; n
++ )
2267 if( m_aXineramaScreens
[n
].Left() == i_nX
&&
2268 m_aXineramaScreens
[n
].Top() == i_nY
)
2270 if( m_aXineramaScreens
[n
].GetWidth() < i_nWidth
||
2271 m_aXineramaScreens
[n
].GetHeight() < i_nHeight
)
2273 m_aXineramaScreenIndexMap
[i
] = n
;
2274 m_aXineramaScreens
[n
].SetSize( Size( i_nWidth
, i_nHeight
) );
2279 m_aXineramaScreenIndexMap
[i
] = m_aXineramaScreens
.size();
2280 m_aXineramaScreens
.emplace_back( Point( i_nX
, i_nY
), Size( i_nWidth
, i_nHeight
) );
2283 void SalDisplay::InitXinerama()
2285 if( m_aScreens
.size() > 1 )
2287 m_bXinerama
= false;
2288 return; // multiple screens mean no xinerama
2290 #if defined(USE_XINERAMA_XORG)
2291 if( !XineramaIsActive( pDisp_
) )
2294 int nFramebuffers
= 1;
2295 XineramaScreenInfo
* pScreens
= XineramaQueryScreens( pDisp_
, &nFramebuffers
);
2299 if( nFramebuffers
> 1 )
2301 m_aXineramaScreens
= std::vector
<tools::Rectangle
>();
2302 m_aXineramaScreenIndexMap
= std::vector
<int>(nFramebuffers
);
2303 for( int i
= 0; i
< nFramebuffers
; i
++ )
2305 addXineramaScreenUnique( i
, pScreens
[i
].x_org
,
2308 pScreens
[i
].height
);
2310 m_bXinerama
= m_aXineramaScreens
.size() > 1;
2314 #if OSL_DEBUG_LEVEL > 1
2317 for (auto const& screen
: m_aXineramaScreens
)
2318 SAL_INFO("vcl.app", "Xinerama screen: "
2319 << screen
.GetWidth()
2320 << "x" << screen
.GetHeight()
2321 << "+" << screen
.Left()
2322 << "+" << screen
.Top());
2329 static Bool
timestamp_predicate( Display
*, XEvent
* i_pEvent
, XPointer i_pArg
)
2331 SalDisplay
* pSalDisplay
= reinterpret_cast<SalDisplay
*>(i_pArg
);
2332 if( i_pEvent
->type
== PropertyNotify
&&
2333 i_pEvent
->xproperty
.window
== pSalDisplay
->GetDrawable( pSalDisplay
->GetDefaultXScreen() ) &&
2334 i_pEvent
->xproperty
.atom
== pSalDisplay
->getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT
)
2342 Time
SalDisplay::GetEventTimeImpl( bool i_bAlwaysReget
) const
2344 if( m_nLastUserEventTime
== CurrentTime
|| i_bAlwaysReget
)
2346 // get current server time
2347 unsigned char c
= 0;
2349 Atom nAtom
= getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT
);
2350 XChangeProperty( GetDisplay(), GetDrawable( GetDefaultXScreen() ),
2351 nAtom
, nAtom
, 8, PropModeReplace
, &c
, 1 );
2352 XIfEvent( GetDisplay(), &aEvent
, timestamp_predicate
, reinterpret_cast<XPointer
>(const_cast<SalDisplay
*>(this)));
2353 m_nLastUserEventTime
= aEvent
.xproperty
.time
;
2355 return m_nLastUserEventTime
;
2358 bool SalDisplay::XIfEventWithTimeout( XEvent
* o_pEvent
, XPointer i_pPredicateData
,
2359 X_if_predicate i_pPredicate
) const
2361 /* #i99360# ugly workaround an X11 library bug
2362 this replaces the following call:
2363 XIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData );
2367 if( ! XCheckIfEvent( GetDisplay(), o_pEvent
, i_pPredicate
, i_pPredicateData
) )
2369 // wait for some event to arrive
2371 aFD
.fd
= ConnectionNumber(GetDisplay());
2372 aFD
.events
= POLLIN
;
2374 tools::Long nTimeout
= 1000;
2375 (void)poll(&aFD
, 1, nTimeout
);
2376 if( ! XCheckIfEvent( GetDisplay(), o_pEvent
, i_pPredicate
, i_pPredicateData
) )
2378 (void)poll(&aFD
, 1, nTimeout
); // try once more for a packet of events from the Xserver
2379 if( ! XCheckIfEvent( GetDisplay(), o_pEvent
, i_pPredicate
, i_pPredicateData
) )
2388 SalVisual::SalVisual():
2389 eRGBMode_(SalRGB::RGB
), nRedShift_(0), nGreenShift_(0), nBlueShift_(0), nRedBits_(0), nGreenBits_(0),
2395 SalVisual::SalVisual( const XVisualInfo
* pXVI
)
2397 *static_cast<XVisualInfo
*>(this) = *pXVI
;
2398 if( GetClass() != TrueColor
)
2401 nRedShift_
= sal_Shift( red_mask
);
2402 nGreenShift_
= sal_Shift( green_mask
);
2403 nBlueShift_
= sal_Shift( blue_mask
);
2405 nRedBits_
= sal_significantBits( red_mask
);
2406 nGreenBits_
= sal_significantBits( green_mask
);
2407 nBlueBits_
= sal_significantBits( blue_mask
);
2409 if( GetDepth() == 24 )
2410 if( red_mask
== 0xFF0000 )
2411 if( green_mask
== 0xFF00 )
2412 if( blue_mask
== 0xFF )
2413 eRGBMode_
= SalRGB::RGB
;
2415 eRGBMode_
= SalRGB::otherSalRGB
;
2416 else if( blue_mask
== 0xFF00 )
2417 if( green_mask
== 0xFF )
2418 eRGBMode_
= SalRGB::RBG
;
2420 eRGBMode_
= SalRGB::otherSalRGB
;
2422 eRGBMode_
= SalRGB::otherSalRGB
;
2423 else if( green_mask
== 0xFF0000 )
2424 if( red_mask
== 0xFF00 )
2425 if( blue_mask
== 0xFF )
2426 eRGBMode_
= SalRGB::GRB
;
2428 eRGBMode_
= SalRGB::otherSalRGB
;
2429 else if( blue_mask
== 0xFF00 )
2430 if( red_mask
== 0xFF )
2431 eRGBMode_
= SalRGB::GBR
;
2433 eRGBMode_
= SalRGB::otherSalRGB
;
2435 eRGBMode_
= SalRGB::otherSalRGB
;
2436 else if( blue_mask
== 0xFF0000 )
2437 if( red_mask
== 0xFF00 )
2438 if( green_mask
== 0xFF )
2439 eRGBMode_
= SalRGB::BRG
;
2441 eRGBMode_
= SalRGB::otherSalRGB
;
2442 else if( green_mask
== 0xFF00 )
2443 if( red_mask
== 0xFF )
2444 eRGBMode_
= SalRGB::BGR
;
2446 eRGBMode_
= SalRGB::otherSalRGB
;
2448 eRGBMode_
= SalRGB::otherSalRGB
;
2450 eRGBMode_
= SalRGB::otherSalRGB
;
2452 eRGBMode_
= SalRGB::otherSalRGB
;
2455 // Converts the order of bytes of a Pixel into bytes of a Color
2456 // This is not reversible for the 6 XXXA
2458 // Color is RGB (ABGR) a=0xFF000000, r=0xFF0000, g=0xFF00, b=0xFF
2460 #define SALCOLOR SalRGB::RGB
2461 #define SALCOLORREVERSE SalRGB::BGR
2463 Color
SalVisual::GetTCColor( Pixel nPixel
) const
2465 if( SALCOLOR
== eRGBMode_
)
2466 return static_cast<Color
>(nPixel
);
2468 if( SALCOLORREVERSE
== eRGBMode_
)
2469 return Color( (nPixel
& 0x0000FF),
2470 (nPixel
& 0x00FF00) >> 8,
2471 (nPixel
& 0xFF0000) >> 16);
2473 Pixel r
= nPixel
& red_mask
;
2474 Pixel g
= nPixel
& green_mask
;
2475 Pixel b
= nPixel
& blue_mask
;
2477 if( SalRGB::otherSalRGB
!= eRGBMode_
) // 8+8+8=24
2478 return Color( r
>> nRedShift_
,
2482 if( nRedShift_
> 0 ) r
>>= nRedShift_
; else r
<<= -nRedShift_
;
2483 if( nGreenShift_
> 0 ) g
>>= nGreenShift_
; else g
<<= -nGreenShift_
;
2484 if( nBlueShift_
> 0 ) b
>>= nBlueShift_
; else b
<<= -nBlueShift_
;
2486 if( nRedBits_
!= 8 )
2487 r
|= (r
& 0xff) >> (8-nRedBits_
);
2488 if( nGreenBits_
!= 8 )
2489 g
|= (g
& 0xff) >> (8-nGreenBits_
);
2490 if( nBlueBits_
!= 8 )
2491 b
|= (b
& 0xff) >> (8-nBlueBits_
);
2493 return Color( r
, g
, b
);
2496 Pixel
SalVisual::GetTCPixel( Color nColor
) const
2498 if( SALCOLOR
== eRGBMode_
)
2499 return static_cast<Pixel
>(sal_uInt32(nColor
));
2501 Pixel r
= static_cast<Pixel
>( nColor
.GetRed() );
2502 Pixel g
= static_cast<Pixel
>( nColor
.GetGreen() );
2503 Pixel b
= static_cast<Pixel
>( nColor
.GetBlue() );
2505 if( SALCOLORREVERSE
== eRGBMode_
)
2506 return (b
<< 16) | (g
<< 8) | r
;
2508 if( SalRGB::otherSalRGB
!= eRGBMode_
) // 8+8+8=24
2509 return (r
<< nRedShift_
) | (g
<< nGreenShift_
) | (b
<< nBlueShift_
);
2511 if( nRedShift_
> 0 ) r
<<= nRedShift_
; else r
>>= -nRedShift_
;
2512 if( nGreenShift_
> 0 ) g
<<= nGreenShift_
; else g
>>= -nGreenShift_
;
2513 if( nBlueShift_
> 0 ) b
<<= nBlueShift_
; else b
>>= -nBlueShift_
;
2515 return (r
&red_mask
) | (g
&green_mask
) | (b
&blue_mask
);
2518 SalColormap::SalColormap( const SalDisplay
*pDisplay
, Colormap hColormap
,
2519 SalX11Screen nXScreen
)
2520 : m_pDisplay( pDisplay
),
2521 m_hColormap( hColormap
)
2523 m_aVisual
= m_pDisplay
->GetVisual( nXScreen
);
2527 GetXPixel( aColor
, 0x00, 0x00, 0x00 );
2528 m_nBlackPixel
= aColor
.pixel
;
2530 GetXPixel( aColor
, 0xFF, 0xFF, 0xFF );
2531 m_nWhitePixel
= aColor
.pixel
;
2533 m_nUsed
= 1 << m_aVisual
.GetDepth();
2535 if( m_aVisual
.GetClass() != PseudoColor
)
2540 // black, white, gray, ~gray = 4
2541 GetXPixels( aColor
, 0xC0, 0xC0, 0xC0 );
2543 // light colors: 3 * 2 = 6
2545 GetXPixels( aColor
, 0x00, 0x00, 0xFF );
2546 GetXPixels( aColor
, 0x00, 0xFF, 0x00 );
2547 GetXPixels( aColor
, 0x00, 0xFF, 0xFF );
2549 // standard colors: 7 * 2 = 14
2550 GetXPixels( aColor
, 0x00, 0x00, 0x80 );
2551 GetXPixels( aColor
, 0x00, 0x80, 0x00 );
2552 GetXPixels( aColor
, 0x00, 0x80, 0x80 );
2553 GetXPixels( aColor
, 0x80, 0x00, 0x00 );
2554 GetXPixels( aColor
, 0x80, 0x00, 0x80 );
2555 GetXPixels( aColor
, 0x80, 0x80, 0x00 );
2556 GetXPixels( aColor
, 0x80, 0x80, 0x80 );
2557 GetXPixels( aColor
, 0x00, 0xB8, 0xFF ); // Blue 7
2559 // cube: 6*6*6 - 8 = 208
2560 for( r
= 0; r
< 0x100; r
+= 0x33 ) // 0x33, 0x66, 0x99, 0xCC, 0xFF
2561 for( g
= 0; g
< 0x100; g
+= 0x33 )
2562 for( b
= 0; b
< 0x100; b
+= 0x33 )
2563 GetXPixels( aColor
, r
, g
, b
);
2565 // gray: 16 - 6 = 10
2566 for( g
= 0x11; g
< 0xFF; g
+= 0x11 )
2567 GetXPixels( aColor
, g
, g
, g
);
2569 // green: 16 - 6 = 10
2570 for( g
= 0x11; g
< 0xFF; g
+= 0x11 )
2571 GetXPixels( aColor
, 0, g
, 0 );
2574 for( r
= 0x11; r
< 0xFF; r
+= 0x11 )
2575 GetXPixels( aColor
, r
, 0, 0 );
2577 // blue: 16 - 6 = 10
2578 for( b
= 0x11; b
< 0xFF; b
+= 0x11 )
2579 GetXPixels( aColor
, 0, 0, b
);
2584 SalColormap::SalColormap()
2585 : m_pDisplay( vcl_sal::getSalDisplay(GetGenericUnixSalData()) ),
2586 m_hColormap( None
),
2591 m_aPalette
= std::vector
<Color
>(m_nUsed
);
2593 m_aPalette
[m_nBlackPixel
] = COL_BLACK
;
2594 m_aPalette
[m_nWhitePixel
] = COL_WHITE
;
2598 SalColormap::SalColormap( sal_uInt16 nDepth
)
2599 : m_pDisplay( vcl_sal::getSalDisplay(GetGenericUnixSalData()) ),
2600 m_hColormap( None
),
2601 m_nWhitePixel( (1 << nDepth
) - 1 ),
2602 m_nBlackPixel( 0x00000000 ),
2603 m_nUsed( 1 << nDepth
)
2605 SalX11Screen
nXScreen( vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetDefaultXScreen() );
2606 const SalVisual
*pVisual
= &m_pDisplay
->GetVisual( nXScreen
);
2608 if( pVisual
->GetClass() == TrueColor
&& pVisual
->GetDepth() == nDepth
)
2609 m_aVisual
= *pVisual
;
2614 if( !XMatchVisualInfo( m_pDisplay
->GetDisplay(),
2615 m_pDisplay
->GetDefaultXScreen().getXScreen(),
2620 aVI
.visual
= new Visual
;
2621 aVI
.visualid
= VisualID(-1);
2624 aVI
.c_class
= TrueColor
;
2625 if( 24 == nDepth
) // 888
2627 aVI
.red_mask
= 0xFF0000;
2628 aVI
.green_mask
= 0x00FF00;
2629 aVI
.blue_mask
= 0x0000FF;
2631 else if( 8 == nDepth
) // 332
2633 aVI
.red_mask
= 0x0000E0;
2634 aVI
.green_mask
= 0x00001C;
2635 aVI
.blue_mask
= 0x000003;
2639 aVI
.red_mask
= 0x000000;
2640 aVI
.green_mask
= 0x000000;
2641 aVI
.blue_mask
= 0x000000;
2643 aVI
.colormap_size
= 0;
2644 aVI
.bits_per_rgb
= 8;
2646 aVI
.visual
->ext_data
= nullptr;
2647 aVI
.visual
->visualid
= aVI
.visualid
;
2648 aVI
.visual
->c_class
= aVI
.c_class
;
2649 aVI
.visual
->red_mask
= aVI
.red_mask
;
2650 aVI
.visual
->green_mask
= aVI
.green_mask
;
2651 aVI
.visual
->blue_mask
= aVI
.blue_mask
;
2652 aVI
.visual
->bits_per_rgb
= aVI
.bits_per_rgb
;
2653 aVI
.visual
->map_entries
= aVI
.colormap_size
;
2655 m_aVisual
= SalVisual( &aVI
);
2656 m_aVisualOwnership
.owner
= true;
2659 m_aVisual
= SalVisual( &aVI
);
2663 SalColormap::~SalColormap()
2665 if (m_aVisualOwnership
.owner
)
2667 delete m_aVisual
.visual
;
2671 void SalColormap::GetPalette()
2674 m_aPalette
= std::vector
<Color
>(m_nUsed
);
2676 std::unique_ptr
<XColor
[]> aColor(new XColor
[m_nUsed
]);
2678 for( i
= 0; i
< m_nUsed
; i
++ )
2680 aColor
[i
].red
= aColor
[i
].green
= aColor
[i
].blue
= 0;
2681 aColor
[i
].pixel
= i
;
2684 XQueryColors( m_pDisplay
->GetDisplay(), m_hColormap
, aColor
.get(), m_nUsed
);
2686 for( i
= 0; i
< m_nUsed
; i
++ )
2688 m_aPalette
[i
] = Color( aColor
[i
].red
>> 8,
2689 aColor
[i
].green
>> 8,
2690 aColor
[i
].blue
>> 8 );
2694 static sal_uInt16
sal_Lookup( const std::vector
<Color
>& rPalette
,
2695 int r
, int g
, int b
,
2698 sal_uInt16 nPixel
= 0;
2699 int nBest
= ColorDiff( rPalette
[0], r
, g
, b
);
2701 for( Pixel i
= 1; i
< nUsed
; i
++ )
2703 int n
= ColorDiff( rPalette
[i
], r
, g
, b
);
2717 void SalColormap::GetLookupTable()
2719 m_aLookupTable
= std::vector
<sal_uInt16
>(16*16*16);
2722 for( int r
= 0; r
< 256; r
+= 17 )
2723 for( int g
= 0; g
< 256; g
+= 17 )
2724 for( int b
= 0; b
< 256; b
+= 17 )
2725 m_aLookupTable
[i
++] = sal_Lookup( m_aPalette
, r
, g
, b
, m_nUsed
);
2728 Color
SalColormap::GetColor( Pixel nPixel
) const
2730 if( m_nBlackPixel
== nPixel
) return COL_BLACK
;
2731 if( m_nWhitePixel
== nPixel
) return COL_WHITE
;
2733 if( m_aVisual
.GetVisual() )
2735 if( m_aVisual
.GetClass() == TrueColor
)
2736 return m_aVisual
.GetTCColor( nPixel
);
2738 if( m_aPalette
.empty()
2740 && m_aVisual
.GetDepth() <= 12
2741 && m_aVisual
.GetClass() == PseudoColor
)
2742 const_cast<SalColormap
*>(this)->GetPalette();
2745 if( !m_aPalette
.empty() && nPixel
< m_nUsed
)
2746 return m_aPalette
[nPixel
];
2750 SAL_WARN("vcl", "SalColormap::GetColor() !m_hColormap");
2754 // DirectColor, StaticColor, StaticGray, GrayScale
2757 aColor
.pixel
= nPixel
;
2759 XQueryColor( m_pDisplay
->GetDisplay(), m_hColormap
, &aColor
);
2761 return Color( aColor
.red
>>8, aColor
.green
>>8, aColor
.blue
>>8 );
2764 inline bool SalColormap::GetXPixel( XColor
&rColor
,
2769 rColor
.red
= r
* 257;
2770 rColor
.green
= g
* 257;
2771 rColor
.blue
= b
* 257;
2772 return XAllocColor( GetXDisplay(), m_hColormap
, &rColor
);
2775 bool SalColormap::GetXPixels( XColor
&rColor
,
2780 if( !GetXPixel( rColor
, r
, g
, b
) )
2782 if( rColor
.pixel
& 1 )
2784 return GetXPixel( rColor
, r
^0xFF, g
^0xFF, b
^0xFF );
2787 Pixel
SalColormap::GetPixel( Color nColor
) const
2789 if( SALCOLOR_NONE
== nColor
) return 0;
2790 if( COL_BLACK
== nColor
) return m_nBlackPixel
;
2791 if( COL_WHITE
== nColor
) return m_nWhitePixel
;
2793 if( m_aVisual
.GetClass() == TrueColor
)
2794 return m_aVisual
.GetTCPixel( nColor
);
2796 if( m_aLookupTable
.empty() )
2798 if( m_aPalette
.empty()
2800 && m_aVisual
.GetDepth() <= 12
2801 && m_aVisual
.GetClass() == PseudoColor
) // what else ???
2802 const_cast<SalColormap
*>(this)->GetPalette();
2804 if( !m_aPalette
.empty() )
2805 for( Pixel i
= 0; i
< m_nUsed
; i
++ )
2806 if( m_aPalette
[i
] == nColor
)
2811 // DirectColor, StaticColor, StaticGray, GrayScale (PseudoColor)
2814 if( GetXPixel( aColor
,
2817 nColor
.GetBlue() ) )
2819 if( !m_aPalette
.empty() && m_aPalette
[aColor
.pixel
] == Color(0) )
2821 const_cast<SalColormap
*>(this)->m_aPalette
[aColor
.pixel
] = nColor
;
2823 if( !(aColor
.pixel
& 1) && m_aPalette
[aColor
.pixel
+1] == Color(0) )
2825 XColor aInversColor
;
2827 Color nInversColor
= sal_uInt32(nColor
) ^ 0xFFFFFF;
2829 GetXPixel( aInversColor
,
2830 nInversColor
.GetRed(),
2831 nInversColor
.GetGreen(),
2832 nInversColor
.GetBlue() );
2834 if( m_aPalette
[aInversColor
.pixel
] == Color(0) )
2835 const_cast<SalColormap
*>(this)->m_aPalette
[aInversColor
.pixel
] = nInversColor
;
2838 SAL_INFO("vcl.app", "SalColormap::GetPixel() "
2839 << std::showbase
<< std::setfill('0')
2840 << std::setw(6) << std::hex
2841 << static_cast< unsigned long >(
2845 << aColor
.pixel
<< " "
2846 << std::showbase
<< std::setfill('0')
2847 << std::setw(6) << std::hex
2848 << static_cast< unsigned long >(
2849 sal_uInt32(nInversColor
))
2852 << aInversColor
.pixel
);
2857 return aColor
.pixel
;
2861 SAL_INFO("vcl.app", "SalColormap::GetPixel() !XAllocColor "
2863 << static_cast< unsigned long >(sal_uInt32(nColor
)));
2867 if( m_aPalette
.empty() )
2870 SAL_INFO("vcl.app", "SalColormap::GetPixel() Palette empty "
2872 << static_cast< unsigned long >(sal_uInt32(nColor
)));
2874 return sal_uInt32(nColor
);
2877 const_cast<SalColormap
*>(this)->GetLookupTable();
2880 // color matching via palette
2881 sal_uInt16 r
= nColor
.GetRed();
2882 sal_uInt16 g
= nColor
.GetGreen();
2883 sal_uInt16 b
= nColor
.GetBlue();
2884 return m_aLookupTable
[ (((r
+8)/17) << 8)
2889 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */