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 <i18nlangtag/languagetag.hxx>
48 #include <tools/debug.hxx>
49 #include <vcl/svapp.hxx>
50 #include <vcl/settings.hxx>
52 #include <sal/log.hxx>
53 #include <sal/types.h>
54 #include <unx/i18n_im.hxx>
55 #include <unx/i18n_xkb.hxx>
56 #include <unx/saldisp.hxx>
57 #include <unx/saldata.hxx>
58 #include <salinst.hxx>
59 #include <unx/salframe.h>
60 #include <vcl/keycodes.hxx>
61 #include <unx/salbmp.h>
62 #include <osl/diagnose.h>
63 #include <unx/salobj.h>
65 #include <unx/wmadaptor.hxx>
66 #include <unx/x11/xrender_peer.hxx>
67 #include <unx/glyphcache.hxx>
73 /* From <X11/Intrinsic.h> */
74 typedef unsigned long Pixel
;
76 using namespace vcl_sal
;
79 static const char *Null( const char *p
) { return p
? p
: ""; }
80 static const char *GetEnv( const char *p
) { return Null( getenv( p
) ); }
81 static const char *KeyStr( KeySym n
) { return Null( XKeysymToString( n
) ); }
83 static const char *GetAtomName( Display
*d
, Atom a
)
84 { return Null( XGetAtomName( d
, a
) ); }
86 static double Hypothenuse( tools::Long w
, tools::Long h
)
87 { return sqrt( static_cast<double>((w
*w
)+(h
*h
)) ); }
90 static int ColorDiff( int r
, int g
, int b
)
91 { return (r
*r
)+(g
*g
)+(b
*b
); }
93 static int ColorDiff( Color c1
, int r
, int g
, int b
)
94 { return ColorDiff( static_cast<int>(c1
.GetRed())-r
,
95 static_cast<int>(c1
.GetGreen())-g
,
96 static_cast<int>(c1
.GetBlue())-b
); }
98 static int sal_Shift( Pixel nMask
)
101 if( nMask
< 0x00010000 ) { nMask
<<= 16; i
-= 16; }
102 if( nMask
< 0x01000000 ) { nMask
<<= 8; i
-= 8; }
103 if( nMask
< 0x10000000 ) { nMask
<<= 4; i
-= 4; }
104 if( nMask
< 0x40000000 ) { nMask
<<= 2; i
-= 2; }
105 if( nMask
< 0x80000000 ) { i
-= 1; }
109 static int sal_significantBits( Pixel nMask
)
111 int nRotate
= sizeof(Pixel
)*4;
122 // check if the resolution is sane
123 static bool sal_ValidDPI(tools::Long nDPI
)
125 return (nDPI
>= 50) && (nDPI
<= 500);
128 static bool sal_GetVisualInfo( Display
*pDisplay
, XID nVID
, XVisualInfo
&rVI
)
131 XVisualInfo aTemplate
;
134 aTemplate
.visualid
= nVID
;
136 pInfo
= XGetVisualInfo( pDisplay
, VisualIDMask
, &aTemplate
, &nInfos
);
143 SAL_WARN_IF( rVI
.visualid
!= nVID
, "vcl",
144 "sal_GetVisualInfo: could not get correct visual by visualId" );
148 extern "C" srv_vendor_t
149 sal_GetServerVendor( Display
*p_display
)
152 srv_vendor_t e_vendor
; // vendor as enum
153 const char* p_name
; // vendor name as returned by VendorString()
154 unsigned int n_len
; // number of chars to compare
157 static const vendor_t vendorlist
[] = {
158 { vendor_sun
, "Sun Microsystems, Inc.", 10 },
161 // handle regular server vendors
162 char *p_name
= ServerVendor( p_display
);
163 for (auto const & vendor
: vendorlist
)
165 if ( strncmp (p_name
, vendor
.p_name
, vendor
.n_len
) == 0 )
166 return vendor
.e_vendor
;
169 // vendor not found in list
170 return vendor_unknown
;
173 bool SalDisplay::BestVisual( Display
*pDisplay
,
177 VisualID nDefVID
= XVisualIDFromVisual( DefaultVisual( pDisplay
, nScreen
) );
179 char *pVID
= getenv( "SAL_VISUAL" );
181 sscanf( pVID
, "%li", &nVID
);
183 if( nVID
&& sal_GetVisualInfo( pDisplay
, nVID
, rVI
) )
184 return rVI
.visualid
== nDefVID
;
187 aVI
.screen
= nScreen
;
190 XVisualInfo
* pVInfos
= XGetVisualInfo( pDisplay
, VisualScreenMask
,
192 // pVInfos should contain at least one visual, otherwise
194 std::vector
<int> aWeights(nVisuals
);
196 for( i
= 0; i
< nVisuals
; i
++ )
198 bool bUsable
= false;
201 if ( pVInfos
[i
].screen
!= nScreen
)
205 else if( pVInfos
[i
].c_class
== TrueColor
)
208 if( pVInfos
[i
].depth
== 24 )
211 else if( pVInfos
[i
].c_class
== PseudoColor
)
215 aWeights
[i
] = bUsable
? nTrueColor
*pVInfos
[i
].depth
: -1024;
216 aWeights
[i
] -= pVInfos
[ i
].visualid
;
220 int nBestWeight
= -1024;
221 for( i
= 0; i
< nVisuals
; i
++ )
223 if (aWeights
[i
] > nBestWeight
)
225 nBestWeight
= aWeights
[i
];
230 rVI
= pVInfos
[ nBestVisual
];
233 return rVI
.visualid
== nDefVID
;
236 SalDisplay::SalDisplay( Display
*display
) :
238 mpKbdExtension( nullptr ),
240 m_nXDefaultScreen( 0 ),
241 nMaxRequestSize_( 0 ),
242 meServerVendor( vendor_unknown
),
243 bNumLockFromXS_( false ),
248 m_bXinerama( false ),
249 m_nLastUserEventTime( CurrentTime
)
251 #if OSL_DEBUG_LEVEL > 1
252 SAL_INFO("vcl.app", "SalDisplay::SalDisplay().");
254 GenericUnixSalData
*pData
= GetGenericUnixSalData();
256 SAL_WARN_IF( pData
->GetDisplay(), "vcl", "Second SalDisplay created !!!" );
257 pData
->SetDisplay( this );
259 m_nXDefaultScreen
= SalX11Screen( DefaultScreen( pDisp_
) );
262 SalDisplay::~SalDisplay()
264 #if OSL_DEBUG_LEVEL > 1
265 SAL_INFO("vcl.app", "SalDisplay::~SalDisplay().");
270 #if OSL_DEBUG_LEVEL > 1
271 SAL_INFO("vcl.app", "display " << pDisp_
<< " closed.");
275 // don't do this in doDestruct since RandR extension adds hooks into Display
276 // that is XCloseDisplay still needs the RandR library if it was used
280 void SalDisplay::doDestruct()
282 GenericUnixSalData
*pData
= GetGenericUnixSalData();
284 m_pWMAdaptor
.reset();
285 X11SalBitmap::ImplDestroyCache();
289 SalDisplay
* pSalDisp
= vcl_sal::getSalDisplay(pData
);
290 Display
* const pX11Disp
= pSalDisp
->GetDisplay();
291 int nMaxScreens
= pSalDisp
->GetXScreenCount();
292 XRenderPeer
& rRenderPeer
= XRenderPeer::GetInstance();
294 for (int i
= 0; i
< nMaxScreens
; i
++)
296 SalDisplay::RenderEntryMap
& rMap
= pSalDisp
->GetRenderEntries(SalX11Screen(i
));
297 for (auto const& elem
: rMap
)
299 if (elem
.second
.m_aPixmap
)
300 ::XFreePixmap(pX11Disp
, elem
.second
.m_aPixmap
);
301 if (elem
.second
.m_aPicture
)
302 rRenderPeer
.FreePicture(elem
.second
.m_aPicture
);
307 FreetypeManager::get().ClearFontCache();
311 delete mpKbdExtension
;
312 mpKbdExtension
= nullptr;
314 for( size_t i
= 0; i
< m_aScreens
.size(); i
++ )
316 ScreenData
& rData
= m_aScreens
[i
];
319 if( rData
.m_aMonoGC
!= rData
.m_aCopyGC
)
320 XFreeGC( pDisp_
, rData
.m_aMonoGC
);
321 XFreeGC( pDisp_
, rData
.m_aCopyGC
);
322 XFreeGC( pDisp_
, rData
.m_aAndInvertedGC
);
323 XFreeGC( pDisp_
, rData
.m_aAndGC
);
324 XFreeGC( pDisp_
, rData
.m_aOrGC
);
325 XFreeGC( pDisp_
, rData
.m_aStippleGC
);
326 XFreePixmap( pDisp_
, rData
.m_hInvert50
);
327 XDestroyWindow( pDisp_
, rData
.m_aRefWindow
);
328 Colormap aColMap
= rData
.m_aColormap
.GetXColormap();
329 if( aColMap
!= None
&& aColMap
!= DefaultColormap( pDisp_
, i
) )
330 XFreeColormap( pDisp_
, aColMap
);
334 for( const Cursor
& aCsr
: aPointerCache_
)
337 XFreeCursor( pDisp_
, aCsr
);
341 pXLib_
->Remove( ConnectionNumber( pDisp_
) );
344 if( pData
->GetDisplay() == static_cast<const SalGenericDisplay
*>( this ) )
345 pData
->SetDisplay( nullptr );
348 static int DisplayHasEvent( int fd
, void * data
)
350 auto pDisplay
= static_cast<SalX11Display
*>(data
);
351 SAL_WARN_IF( ConnectionNumber( pDisplay
->GetDisplay() ) != fd
, "vcl",
352 "wrong fd in DisplayHasEvent" );
353 if( ! pDisplay
->IsDisplay() )
358 SolarMutexGuard aGuard
;
359 result
= pDisplay
->IsEvent();
362 static int DisplayQueue( int fd
, void * data
)
364 auto pDisplay
= static_cast<SalX11Display
*>(data
);
365 SAL_WARN_IF( ConnectionNumber( pDisplay
->GetDisplay() ) != fd
, "vcl",
366 "wrong fd in DisplayHasEvent" );
369 SolarMutexGuard aGuard
;
370 result
= XEventsQueued( pDisplay
->GetDisplay(),
371 QueuedAfterReading
);
374 static int DisplayYield( int fd
, void * data
)
376 auto pDisplay
= static_cast<SalX11Display
*>(data
);
377 SAL_WARN_IF( ConnectionNumber( pDisplay
->GetDisplay() ) != fd
, "vcl",
378 "wrong fd in DisplayHasEvent" );
380 SolarMutexGuard aGuard
;
385 SalX11Display::SalX11Display( Display
*display
)
386 : SalDisplay( display
)
390 pXLib_
= GetX11SalData()->GetLib();
391 pXLib_
->Insert( ConnectionNumber( pDisp_
),
393 reinterpret_cast<YieldFunc
>(DisplayHasEvent
),
394 reinterpret_cast<YieldFunc
>(DisplayQueue
),
395 reinterpret_cast<YieldFunc
>(DisplayYield
) );
398 SalX11Display::~SalX11Display()
400 #if OSL_DEBUG_LEVEL > 1
401 SAL_INFO("vcl.app", "SalX11Display::~SalX11Display().");
406 XCloseDisplay( pDisp_
);
411 void SalX11Display::TriggerUserEventProcessing()
414 pXLib_
->TriggerUserEventProcessing();
417 SalDisplay::ScreenData
*
418 SalDisplay::initScreen( SalX11Screen nXScreen
) const
420 if( nXScreen
.getXScreen() >= m_aScreens
.size() )
421 nXScreen
= m_nXDefaultScreen
;
422 ScreenData
* pSD
= const_cast<ScreenData
*>(&m_aScreens
[nXScreen
.getXScreen()]);
430 if( SalDisplay::BestVisual( pDisp_
, nXScreen
.getXScreen(), aVI
) ) // DefaultVisual
431 aColMap
= DefaultColormap( pDisp_
, nXScreen
.getXScreen() );
433 aColMap
= XCreateColormap( pDisp_
,
434 RootWindow( pDisp_
, nXScreen
.getXScreen() ),
438 Screen
* pScreen
= ScreenOfDisplay( pDisp_
, nXScreen
.getXScreen() );
440 pSD
->m_aSize
= Size( WidthOfScreen( pScreen
), HeightOfScreen( pScreen
) );
441 pSD
->m_aRoot
= RootWindow( pDisp_
, nXScreen
.getXScreen() );
442 pSD
->m_aVisual
= SalVisual( &aVI
);
443 pSD
->m_aColormap
= SalColormap( this, aColMap
, nXScreen
);
445 // we're interested in configure notification of root windows
446 InitRandR( pSD
->m_aRoot
);
448 // - - - - - - - - - - Reference Window/Default Drawable - -
449 XSetWindowAttributes aXWAttributes
;
450 aXWAttributes
.border_pixel
= 0;
451 aXWAttributes
.background_pixel
= 0;
452 aXWAttributes
.colormap
= aColMap
;
453 pSD
->m_aRefWindow
= XCreateWindow( pDisp_
,
456 pSD
->m_aVisual
.GetDepth(),
458 pSD
->m_aVisual
.GetVisual(),
459 CWBorderPixel
|CWBackPixel
|CWColormap
,
462 // set client leader (session id gets set when session is started)
463 if( pSD
->m_aRefWindow
)
465 // client leader must have WM_CLIENT_LEADER pointing to itself
466 XChangeProperty( pDisp_
,
468 XInternAtom( pDisp_
, "WM_CLIENT_LEADER", False
),
472 reinterpret_cast<unsigned char*>(&pSD
->m_aRefWindow
),
476 OString
aExec(OUStringToOString(SessionManagerClient::getExecName(), osl_getThreadTextEncoding()));
478 argv
[0] = aExec
.getStr();
479 XSetCommand( pDisp_
, pSD
->m_aRefWindow
, const_cast<char**>(argv
), 1 );
480 XSelectInput( pDisp_
, pSD
->m_aRefWindow
, PropertyChangeMask
);
482 // - - - - - - - - - - GCs - - - - - - - - - - - - - - - - -
484 values
.graphics_exposures
= False
;
485 values
.fill_style
= FillOpaqueStippled
;
486 values
.background
= (1<<pSD
->m_aVisual
.GetDepth())-1;
487 values
.foreground
= 0;
489 pSD
->m_aCopyGC
= XCreateGC( pDisp_
,
495 pSD
->m_aAndInvertedGC
= XCreateGC( pDisp_
,
501 pSD
->m_aAndGC
= XCreateGC( pDisp_
,
507 pSD
->m_aOrGC
= XCreateGC( pDisp_
,
513 pSD
->m_aStippleGC
= XCreateGC( pDisp_
,
521 XSetFunction( pDisp_
, pSD
->m_aAndInvertedGC
, GXandInverted
);
522 XSetFunction( pDisp_
, pSD
->m_aAndGC
, GXand
);
523 // PowerPC Solaris 2.5 (XSun 3500) Bug: GXor = GXnop
524 XSetFunction( pDisp_
, pSD
->m_aOrGC
, GXxor
);
526 if( 1 == pSD
->m_aVisual
.GetDepth() )
528 XSetFunction( pDisp_
, pSD
->m_aCopyGC
, GXcopyInverted
);
529 pSD
->m_aMonoGC
= pSD
->m_aCopyGC
;
533 Pixmap hPixmap
= XCreatePixmap( pDisp_
, pSD
->m_aRefWindow
, 1, 1, 1 );
534 pSD
->m_aMonoGC
= XCreateGC( pDisp_
,
538 XFreePixmap( pDisp_
, hPixmap
);
540 pSD
->m_hInvert50
= XCreateBitmapFromData( pDisp_
,
542 reinterpret_cast<const char*>(invert50_bits
),
549 void SalDisplay::Init()
551 for( Cursor
& aCsr
: aPointerCache_
)
556 int nDisplayScreens
= ScreenCount( pDisp_
);
557 m_aScreens
= std::vector
<ScreenData
>(nDisplayScreens
);
559 bool bExactResolution
= false;
561 * Xft resolution should take precedence since
562 * it is what modern desktops use.
564 const char* pValStr
= XGetDefault( pDisp_
, "Xft", "dpi" );
565 if( pValStr
!= nullptr )
567 const OString
aValStr( pValStr
);
568 const tools::Long nDPI
= static_cast<tools::Long
>(aValStr
.toDouble());
569 // guard against insane resolution
570 if( sal_ValidDPI(nDPI
) )
572 aResolution_
= Pair( nDPI
, nDPI
);
573 bExactResolution
= true;
576 if( !bExactResolution
)
578 /* if Xft.dpi is not set, try and find the DPI from the
579 * reported screen sizes and resolution. If there are multiple
580 * screens, just fall back to the default 96x96
582 tools::Long xDPI
= 96;
583 tools::Long yDPI
= 96;
584 if (m_aScreens
.size() == 1) {
585 xDPI
= static_cast<tools::Long
>(round(DisplayWidth(pDisp_
, 0)*25.4/DisplayWidthMM(pDisp_
, 0)));
586 yDPI
= static_cast<tools::Long
>(round(DisplayHeight(pDisp_
, 0)*25.4/DisplayHeightMM(pDisp_
, 0)));
587 // if either is invalid set it equal to the other
588 if (!sal_ValidDPI(xDPI
) && sal_ValidDPI(yDPI
))
590 if (!sal_ValidDPI(yDPI
) && sal_ValidDPI(xDPI
))
592 // if both are invalid, reset them to the default
593 if (!sal_ValidDPI(xDPI
) && !sal_ValidDPI(yDPI
))
596 aResolution_
= Pair( xDPI
, yDPI
);
599 nMaxRequestSize_
= XExtendedMaxRequestSize( pDisp_
) * 4;
600 if( !nMaxRequestSize_
)
601 nMaxRequestSize_
= XMaxRequestSize( pDisp_
) * 4;
603 meServerVendor
= sal_GetServerVendor(pDisp_
);
604 X11SalBitmap::ImplCreateCache();
606 // - - - - - - - - - - Synchronize - - - - - - - - - - - - -
607 if( getenv( "SAL_SYNCHRONIZE" ) )
608 XSynchronize( pDisp_
, True
);
610 // - - - - - - - - - - Keyboardmapping - - - - - - - - - - -
613 // - - - - - - - - - - Window Manager - - - - - - - - - - -
614 m_pWMAdaptor
= ::vcl_sal::WMAdaptor::createWMAdaptor( this );
623 void SalX11Display::SetupInput()
625 GetGenericUnixSalData()->ErrorTrapPush();
626 SalI18N_KeyboardExtension
*pKbdExtension
= new SalI18N_KeyboardExtension( pDisp_
);
627 XSync( pDisp_
, False
);
629 bool bError
= GetGenericUnixSalData()->ErrorTrapPop( false );
630 GetGenericUnixSalData()->ErrorTrapPush();
631 pKbdExtension
->UseExtension( ! bError
);
632 GetGenericUnixSalData()->ErrorTrapPop();
634 SetKbdExtension( pKbdExtension
);
638 void SalDisplay::Beep() const
640 XBell( pDisp_
, 100 );
647 bool InitXkb(Display
* dpy
)
649 int nOpcode
, nEvent
, nError
;
650 int nXkbMajor
= XkbMajorVersion
;
651 int nXkbMinor
= XkbMinorVersion
;
653 if (!XkbLibraryVersion(&nXkbMajor
, &nXkbMinor
))
656 return XkbQueryExtension(
657 dpy
, &nOpcode
, &nEvent
, &nError
, &nXkbMajor
, &nXkbMinor
);
660 unsigned int GetKeySymMask(Display
* dpy
, KeySym nKeySym
)
663 XModifierKeymap
* pXmkMap
= XGetModifierMapping(dpy
);
664 KeyCode nKeyCode
= XKeysymToKeycode(dpy
, nKeySym
);
665 if (nKeyCode
== NoSymbol
)
668 for (int i
= 0; i
< 8; ++i
)
670 KeyCode nThisKeyCode
= pXmkMap
->modifiermap
[pXmkMap
->max_keypermod
*i
];
671 if (nThisKeyCode
== nKeyCode
)
674 XFreeModifiermap(pXmkMap
);
680 void SalDisplay::SimulateKeyPress( sal_uInt16 nKeyCode
)
682 if (nKeyCode
!= KEY_CAPSLOCK
)
685 Display
* dpy
= GetDisplay();
689 unsigned int nMask
= GetKeySymMask(dpy
, XK_Caps_Lock
);
690 XkbStateRec xkbState
;
691 XkbGetState(dpy
, XkbUseCoreKbd
, &xkbState
);
692 unsigned int nCapsLockState
= xkbState
.locked_mods
& nMask
;
694 XkbLockModifiers (dpy
, XkbUseCoreKbd
, nMask
, 0);
696 XkbLockModifiers (dpy
, XkbUseCoreKbd
, nMask
, nMask
);
699 KeyIndicatorState
SalDisplay::GetIndicatorState() const
701 unsigned int _state
= 0;
702 KeyIndicatorState nState
= KeyIndicatorState::NONE
;
703 XkbGetIndicatorState(pDisp_
, XkbUseCoreKbd
, &_state
);
705 if (_state
& 0x00000001)
706 nState
|= KeyIndicatorState::CAPSLOCK
;
707 if (_state
& 0x00000002)
708 nState
|= KeyIndicatorState::NUMLOCK
;
709 if (_state
& 0x00000004)
710 nState
|= KeyIndicatorState::SCROLLLOCK
;
715 OUString
SalDisplay::GetKeyNameFromKeySym( KeySym nKeySym
) const
717 OUString aLang
= Application::GetSettings().GetUILanguageTag().getLanguage();
720 // return an empty string for keysyms that are not bound to
722 KeyCode aKeyCode
= XKeysymToKeycode( GetDisplay(), nKeySym
);
723 static_assert(NoSymbol
== 0, "X11 inconsistency");
724 if( aKeyCode
!= NoSymbol
)
730 aRet
= ::vcl_sal::getKeysymReplacementName( aLang
, nKeySym
);
733 const char *pString
= XKeysymToString( nKeySym
);
736 int n
= strlen( pString
);
737 if( n
> 2 && pString
[n
-2] == '_' )
738 aRet
= OUString( pString
, n
-2, RTL_TEXTENCODING_ISO_8859_1
);
740 aRet
= OUString( pString
, n
, RTL_TEXTENCODING_ISO_8859_1
);
750 static KeySym
sal_XModifier2Keysym( Display
*pDisplay
,
751 XModifierKeymap
const *pXModMap
,
754 return XkbKeycodeToKeysym( pDisplay
,
755 pXModMap
->modifiermap
[n
*pXModMap
->max_keypermod
],
759 void SalDisplay::ModifierMapping()
761 XModifierKeymap
*pXModMap
= XGetModifierMapping( pDisp_
);
763 bNumLockFromXS_
= True
;
764 nShiftKeySym_
= sal_XModifier2Keysym( pDisp_
, pXModMap
, ShiftMapIndex
);
765 nCtrlKeySym_
= sal_XModifier2Keysym( pDisp_
, pXModMap
, ControlMapIndex
);
766 nMod1KeySym_
= sal_XModifier2Keysym( pDisp_
, pXModMap
, Mod1MapIndex
);
767 // on Sun and SCO servers XLookupString does not account for NumLock
768 if( GetServerVendor() == vendor_sun
)
770 KeyCode aNumLock
= XKeysymToKeycode( pDisp_
, XK_Num_Lock
);
773 for( int i
= ShiftMapIndex
; i
<= Mod5MapIndex
; i
++ )
775 if( pXModMap
->modifiermap
[i
*pXModMap
->max_keypermod
] == aNumLock
)
777 bNumLockFromXS_
= False
;
784 XFreeModifiermap( pXModMap
);
787 OUString
SalDisplay::GetKeyName( sal_uInt16 nKeyCode
) const
790 OUString aCustomKeyName
;
792 if( nKeyCode
& KEY_MOD1
)
793 aStrMap
+= GetKeyNameFromKeySym( nCtrlKeySym_
);
795 if( nKeyCode
& KEY_MOD2
)
797 if( !aStrMap
.isEmpty() )
799 aStrMap
+= GetKeyNameFromKeySym( nMod1KeySym_
);
802 if( nKeyCode
& KEY_SHIFT
)
804 if( !aStrMap
.isEmpty() )
806 aStrMap
+= GetKeyNameFromKeySym( nShiftKeySym_
);
812 if( KEY_0
<= nKeyCode
&& nKeyCode
<= KEY_9
)
813 nKeySym
= XK_0
+ (nKeyCode
- KEY_0
);
814 else if( KEY_A
<= nKeyCode
&& nKeyCode
<= KEY_Z
)
815 nKeySym
= XK_A
+ (nKeyCode
- KEY_A
);
816 else if( KEY_F1
<= nKeyCode
&& nKeyCode
<= KEY_F26
) // does this key exist?
817 nKeySym
= XK_F1
+ (nKeyCode
- KEY_F1
);
818 else switch( nKeyCode
)
839 nKeySym
= XK_Page_Up
;
842 nKeySym
= XK_Page_Down
;
854 nKeySym
= XK_BackSpace
;
866 #if !defined (SunXK_Undo)
867 // we don't intend to use SunXK_Undo, but if it has not been
868 // defined already, then we _do_ need the following:
869 #define SunXK_Props 0x1005FF70
870 #define SunXK_Front 0x1005FF71
871 #define SunXK_Copy 0x1005FF72
872 #define SunXK_Open 0x1005FF73
873 #define SunXK_Paste 0x1005FF74
874 #define SunXK_Cut 0x1005FF75
876 // the following are for XF86 systems
877 #define XF86XK_Copy 0x1008FF57
878 #define XF86XK_Cut 0x1008FF58
879 #define XF86XK_Open 0x1008FF6B
880 #define XF86XK_Paste 0x1008FF6D
881 // which leaves Apollo and OSF systems in the lurch
887 nKeySym
= SunXK_Props
;
893 nKeySym
= SunXK_Front
;
896 nKeySym
= GetServerVendor() == vendor_sun
? SunXK_Copy
: XF86XK_Copy
;
899 nKeySym
= GetServerVendor() == vendor_sun
? SunXK_Open
: XF86XK_Open
;
902 nKeySym
= GetServerVendor() == vendor_sun
? SunXK_Paste
: XF86XK_Paste
;
908 nKeySym
= GetServerVendor() == vendor_sun
? SunXK_Cut
: XF86XK_Cut
;
909 /* The original code here had:
910 nKeySym = GetServerVendor() == vendor_sun ? SunXK_Cut : XK_L10;
911 if anyone can remember which non-vendor_sun system used this
912 XK_L10 keysym, and why this hack only applied to KEY_CUT,
913 then please re-hack this code to put it back
917 aCustomKeyName
= "+";
920 aCustomKeyName
= "-";
923 nKeySym
= XK_asterisk
;
929 aCustomKeyName
= ".";
938 nKeySym
= XK_greater
;
946 case KEY_HANGUL_HANJA
:
947 nKeySym
= XK_Hangul_Hanja
;
950 nKeySym
= XK_asciitilde
;
955 case KEY_BRACKETLEFT
:
956 aCustomKeyName
= "[";
958 case KEY_BRACKETRIGHT
:
959 aCustomKeyName
= "]";
962 aCustomKeyName
= ";";
965 aCustomKeyName
= "'";
967 case KEY_RIGHTCURLYBRACKET
:
968 aCustomKeyName
= "}";
971 aCustomKeyName
= "#";
974 aCustomKeyName
= ":";
983 OUString aKeyName
= GetKeyNameFromKeySym( nKeySym
);
984 if( !aKeyName
.isEmpty() )
986 if( !aStrMap
.isEmpty() )
993 else if (!aCustomKeyName
.isEmpty())
995 // For semicolon, bracket left and bracket right, it's better to use
996 // their keys than their names. (fdo#32891)
997 if (!aStrMap
.isEmpty())
999 aStrMap
+= aCustomKeyName
;
1008 #define IsISOKey( n ) (0x0000FE00==((n)&0xFFFFFF00))
1011 sal_uInt16
SalDisplay::GetKeyCode( KeySym keysym
, char*pcPrintable
) const
1013 sal_uInt16 nKey
= 0;
1015 if( XK_a
<= keysym
&& XK_z
>= keysym
)
1016 nKey
= static_cast<sal_uInt16
>(KEY_A
+ (keysym
- XK_a
));
1017 else if( XK_A
<= keysym
&& XK_Z
>= keysym
)
1018 nKey
= static_cast<sal_uInt16
>(KEY_A
+ (keysym
- XK_A
));
1019 else if( XK_0
<= keysym
&& XK_9
>= keysym
)
1020 nKey
= static_cast<sal_uInt16
>(KEY_0
+ (keysym
- XK_0
));
1021 else if( IsModifierKey( keysym
) )
1023 else if( IsKeypadKey( keysym
) )
1025 if( (keysym
>= XK_KP_0
) && (keysym
<= XK_KP_9
) )
1027 nKey
= static_cast<sal_uInt16
>(KEY_0
+ (keysym
- XK_KP_0
));
1028 *pcPrintable
= '0' + nKey
- KEY_0
;
1030 else if( IsPFKey( keysym
) )
1031 nKey
= static_cast<sal_uInt16
>(KEY_F1
+ (keysym
- XK_KP_F1
));
1032 else switch( keysym
)
1060 case XK_KP_Page_Up
: // XK_KP_Page_Up
1063 case XK_KP_Page_Down
: // XK_KP_Page_Down
1064 nKey
= KEY_PAGEDOWN
;
1079 case XK_KP_Multiply
:
1080 nKey
= KEY_MULTIPLY
;
1087 case XK_KP_Separator
:
1091 case XK_KP_Subtract
:
1092 nKey
= KEY_SUBTRACT
;
1105 else if( IsFunctionKey( keysym
) )
1107 if( bNumLockFromXS_
)
1109 if( keysym
>= XK_F1
&& keysym
<= XK_F26
)
1110 nKey
= static_cast<sal_uInt16
>(KEY_F1
+ keysym
- XK_F1
);
1112 else switch( keysym
)
1114 // - - - - - Sun X-Server keyboard without Cursorblock ??? - - -
1115 case XK_R7
: // XK_F27:
1118 case XK_R8
: // XK_F28:
1121 case XK_R9
: // XK_F29:
1124 case XK_R10
: // XK_F30:
1127 case XK_R11
: // XK_F31:
1128 nKey
= 0; // KEY_F31
1130 case XK_R12
: // XK_F32:
1133 case XK_R13
: // XK_F33:
1136 case XK_R14
: // XK_F34:
1139 case XK_R15
: // XK_F35:
1140 nKey
= KEY_PAGEDOWN
;
1142 // - - - - - Sun X-Server keyboard ??? - - - - - - - - - - - -
1143 case XK_L1
: // XK_F11:
1144 nKey
= KEY_F11
; // on a sun keyboard this actually is usually SunXK_Stop = 0x0000FF69 (XK_Cancel),
1145 // but VCL doesn't have a key definition for that
1147 case XK_L2
: // XK_F12:
1148 if ( GetServerVendor() == vendor_sun
)
1153 case XK_L3
: // XK_F13:
1154 nKey
= KEY_PROPERTIES
; // KEY_F13
1156 case XK_L4
: // XK_F14:
1157 nKey
= KEY_UNDO
; // KEY_F14
1159 case XK_L5
: // XK_F15:
1160 nKey
= KEY_F15
; // KEY_FRONT
1162 case XK_L6
: // XK_F16:
1163 nKey
= KEY_COPY
; // KEY_F16
1165 case XK_L7
: // XK_F17:
1166 nKey
= KEY_F17
; // KEY_OPEN
1168 case XK_L8
: // XK_F18:
1169 nKey
= KEY_PASTE
; // KEY_F18
1171 case XK_L9
: // XK_F19:
1172 nKey
= KEY_F19
; // KEY_FIND
1174 case XK_L10
: // XK_F20:
1175 nKey
= KEY_CUT
; // KEY_F20
1178 if( keysym
>= XK_F1
&& keysym
<= XK_F26
)
1179 nKey
= static_cast<sal_uInt16
>(KEY_F1
+ keysym
- XK_F1
);
1183 else if( IsCursorKey( keysym
) )
1203 case XK_Page_Up
: // XK_Page_Up
1206 case XK_Page_Down
: // XK_Page_Down
1207 nKey
= KEY_PAGEDOWN
;
1214 else if( IsMiscFunctionKey( keysym
) )
1234 nKey
= KEY_CONTEXTMENU
;
1238 else if( IsISOKey( keysym
) ) // XK_ISO_
1242 case 0xFE20: // XK_ISO_Left_Tab:
1247 else switch( keysym
)
1253 nKey
= KEY_BACKSPACE
;
1271 nKey
= KEY_SUBTRACT
;
1274 nKey
= KEY_MULTIPLY
;
1295 case XK_Hangul_Hanja
:
1296 nKey
= KEY_HANGUL_HANJA
;
1303 nKey
= KEY_QUOTELEFT
;
1306 case XK_bracketleft
:
1307 nKey
= KEY_BRACKETLEFT
;
1310 case XK_bracketright
:
1311 nKey
= KEY_BRACKETRIGHT
;
1315 nKey
= KEY_SEMICOLON
;
1319 nKey
= KEY_QUOTERIGHT
;
1320 *pcPrintable
= '\'';
1323 nKey
= KEY_RIGHTCURLYBRACKET
;
1324 *pcPrintable
= '\'';
1327 nKey
= KEY_NUMBERSIGN
;
1334 // - - - - - - - - - - - - - Apollo - - - - - - - - - - - - - 0x1000
1335 case 0x1000FF02: // apXK_Copy
1338 case 0x1000FF03: // apXK_Cut
1341 case 0x1000FF04: // apXK_Paste
1344 case 0x1000FF14: // apXK_Repeat
1348 // - - - - - - - - - - - - - - D E C - - - - - - - - - - - - - 0x1000
1352 // - - - - - - - - - - - - - - H P - - - - - - - - - - - - - 0x1000
1353 case 0x1000FF73: // hpXK_DeleteChar
1356 case 0x1000FF74: // hpXK_BackTab
1357 case 0x1000FF75: // hpXK_KP_BackTab
1360 // - - - - - - - - - - - - - - I B M - - - - - - - - - - - - -
1361 // - - - - - - - - - - - - - - O S F - - - - - - - - - - - - - 0x1004
1362 case 0x1004FF02: // osfXK_Copy
1365 case 0x1004FF03: // osfXK_Cut
1368 case 0x1004FF04: // osfXK_Paste
1371 case 0x1004FF07: // osfXK_BackTab
1374 case 0x1004FF08: // osfXK_BackSpace
1375 nKey
= KEY_BACKSPACE
;
1377 case 0x1004FF1B: // osfXK_Escape
1380 // Up, Down, Left, Right, PageUp, PageDown
1381 // - - - - - - - - - - - - - - S C O - - - - - - - - - - - - -
1382 // - - - - - - - - - - - - - - S G I - - - - - - - - - - - - - 0x1007
1383 // - - - - - - - - - - - - - - S N I - - - - - - - - - - - - -
1384 // - - - - - - - - - - - - - - S U N - - - - - - - - - - - - - 0x1005
1385 case 0x1005FF10: // SunXK_F36
1388 case 0x1005FF11: // SunXK_F37
1391 case 0x1005FF70: // SunXK_Props
1392 nKey
= KEY_PROPERTIES
;
1394 case 0x1005FF71: // SunXK_Front
1397 case 0x1005FF72: // SunXK_Copy
1400 case 0x1005FF73: // SunXK_Open
1403 case 0x1005FF74: // SunXK_Paste
1406 case 0x1005FF75: // SunXK_Cut
1413 KeySym
SalDisplay::GetKeySym( XKeyEvent
*pEvent
,
1416 KeySym
*pUnmodifiedKeySym
,
1417 Status
*pStatusReturn
,
1418 XIC aInputContext
) const
1421 memset( pPrintable
, 0, *pLen
);
1424 SalI18N_InputMethod
* const pInputMethod
=
1425 pXLib_
? pXLib_
->GetInputMethod() : nullptr;
1427 // first get the printable of the possibly modified KeySym
1428 if ( (aInputContext
== nullptr)
1429 || (pEvent
->type
== KeyRelease
)
1430 || (pInputMethod
!= nullptr && pInputMethod
->PosixLocale()) )
1432 // XmbLookupString must not be called for KeyRelease events
1433 // Cannot enter space in c locale problem #89616# #88978# btraq #4478197
1434 *pLen
= XLookupString( pEvent
, pPrintable
, 1, &nKeySym
, nullptr );
1438 *pLen
= XmbLookupString( aInputContext
,
1439 pEvent
, pPrintable
, *pLen
- 1, &nKeySym
, pStatusReturn
);
1441 // Lookup the string again, now with appropriate size
1442 if ( *pStatusReturn
== XBufferOverflow
)
1444 pPrintable
[ 0 ] = '\0';
1448 switch ( *pStatusReturn
)
1450 case XBufferOverflow
:
1451 /* unhandled error */
1454 /* unhandled error */
1457 /* this is a strange one: on exceed sometimes
1458 * no printable is returned for the first char entered,
1459 * just to retry lookup solves the problem. The problem
1460 * is not yet fully understood, so restrict 2nd lookup
1461 * to 7bit ascii chars */
1462 if ( (XK_space
<= nKeySym
) && (XK_asciitilde
>= nKeySym
) )
1465 pPrintable
[ 0 ] = static_cast<char>(nKeySym
);
1471 /* nothing to, char already in pPrintable */
1476 if( !bNumLockFromXS_
1477 && (IsCursorKey(nKeySym
)
1478 || IsFunctionKey(nKeySym
)
1479 || IsKeypadKey(nKeySym
)
1480 || XK_Delete
== nKeySym
) )
1482 // For some X-servers special care is needed for Keypad keys.
1483 // For example Solaris XServer:
1484 // 2, 4, 6, 8 are classified as Cursorkeys (Up, Down, Left, Right)
1485 // 1, 3, 5, 9 are classified as Functionkeys (F27,F29,F33,F35)
1486 // 0 as Keypadkey, and the decimal point key not at all (KP_Insert)
1487 KeySym nNewKeySym
= XLookupKeysym( pEvent
, nNumLockIndex_
);
1488 if( nNewKeySym
!= NoSymbol
)
1489 nKeySym
= nNewKeySym
;
1492 // Now get the unmodified KeySym for KeyCode retrieval
1493 // try to strip off modifiers, e.g. Ctrl-$ becomes Ctrl-Shift-4
1494 *pUnmodifiedKeySym
= XkbKeycodeToKeysym( GetDisplay(), pEvent
->keycode
, 0, 0);
1500 static unsigned char nullmask_bits
[] = { 0x00, 0x00, 0x00, 0x00 };
1501 static unsigned char nullcurs_bits
[] = { 0x00, 0x00, 0x00, 0x00 };
1503 #define MAKE_BITMAP( name ) \
1504 XCreateBitmapFromData( pDisp_, \
1505 DefaultRootWindow( pDisp_ ), \
1506 reinterpret_cast<const char*>(name##_bits), \
1510 #define MAKE_CURSOR( name ) \
1511 aCursBitmap = MAKE_BITMAP( name##curs ); \
1512 aMaskBitmap = MAKE_BITMAP( name##mask ); \
1513 nXHot = name##curs_x_hot; \
1514 nYHot = name##curs_y_hot
1516 Cursor
SalDisplay::GetPointer( PointerStyle ePointerStyle
)
1518 Cursor
&aCur
= aPointerCache_
[ePointerStyle
];
1523 Pixmap aCursBitmap
= None
, aMaskBitmap
= None
;
1524 unsigned int nXHot
= 0, nYHot
= 0;
1526 switch( ePointerStyle
)
1528 case PointerStyle::Null
:
1529 MAKE_CURSOR( null
);
1531 case PointerStyle::Arrow
:
1532 aCur
= XCreateFontCursor( pDisp_
, XC_left_ptr
);
1533 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1535 case PointerStyle::Wait
:
1536 aCur
= XCreateFontCursor( pDisp_
, XC_watch
);
1538 case PointerStyle::Text
: // Mouse Pointer is a "I" Beam
1539 aCur
= XCreateFontCursor( pDisp_
, XC_xterm
);
1540 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1542 case PointerStyle::Help
:
1543 aCur
= XCreateFontCursor( pDisp_
, XC_question_arrow
);
1544 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1546 case PointerStyle::Cross
: // Mouse Pointer is a cross
1547 aCur
= XCreateFontCursor( pDisp_
, XC_crosshair
);
1548 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1550 case PointerStyle::NSize
:
1551 aCur
= XCreateFontCursor( pDisp_
, XC_sb_v_double_arrow
);
1552 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1554 case PointerStyle::SSize
:
1555 aCur
= XCreateFontCursor( pDisp_
, XC_sb_v_double_arrow
);
1556 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1558 case PointerStyle::WSize
:
1559 aCur
= XCreateFontCursor( pDisp_
, XC_sb_h_double_arrow
);
1560 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1562 case PointerStyle::ESize
:
1563 aCur
= XCreateFontCursor( pDisp_
, XC_sb_h_double_arrow
);
1564 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1566 case PointerStyle::WindowNSize
:
1567 aCur
= XCreateFontCursor( pDisp_
, XC_top_side
);
1568 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1570 case PointerStyle::WindowSSize
:
1571 aCur
= XCreateFontCursor( pDisp_
, XC_bottom_side
);
1572 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1574 case PointerStyle::WindowWSize
:
1575 aCur
= XCreateFontCursor( pDisp_
, XC_left_side
);
1576 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1578 case PointerStyle::WindowESize
:
1579 aCur
= XCreateFontCursor( pDisp_
, XC_right_side
);
1580 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1582 case PointerStyle::NWSize
:
1583 aCur
= XCreateFontCursor( pDisp_
, XC_top_left_corner
);
1585 case PointerStyle::NESize
:
1586 aCur
= XCreateFontCursor( pDisp_
, XC_top_right_corner
);
1588 case PointerStyle::SWSize
:
1589 aCur
= XCreateFontCursor( pDisp_
, XC_bottom_left_corner
);
1591 case PointerStyle::SESize
:
1592 aCur
= XCreateFontCursor( pDisp_
, XC_bottom_right_corner
);
1594 case PointerStyle::WindowNWSize
:
1595 aCur
= XCreateFontCursor( pDisp_
, XC_top_left_corner
);
1596 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1598 case PointerStyle::WindowNESize
:
1599 aCur
= XCreateFontCursor( pDisp_
, XC_top_right_corner
);
1600 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1602 case PointerStyle::WindowSWSize
:
1603 aCur
= XCreateFontCursor( pDisp_
, XC_bottom_left_corner
);
1604 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1606 case PointerStyle::WindowSESize
:
1607 aCur
= XCreateFontCursor( pDisp_
, XC_bottom_right_corner
);
1608 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1610 case PointerStyle::HSplit
:
1611 aCur
= XCreateFontCursor( pDisp_
, XC_sb_h_double_arrow
);
1613 case PointerStyle::VSplit
:
1614 aCur
= XCreateFontCursor( pDisp_
, XC_sb_v_double_arrow
);
1616 case PointerStyle::HSizeBar
:
1617 aCur
= XCreateFontCursor( pDisp_
, XC_sb_h_double_arrow
); // ???
1618 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1620 case PointerStyle::VSizeBar
:
1621 aCur
= XCreateFontCursor( pDisp_
, XC_sb_v_double_arrow
); // ???
1622 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1624 case PointerStyle::RefHand
:
1625 aCur
= XCreateFontCursor( pDisp_
, XC_hand1
);
1626 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1628 case PointerStyle::Hand
:
1629 aCur
= XCreateFontCursor( pDisp_
, XC_hand2
);
1631 case PointerStyle::Magnify
:
1632 MAKE_CURSOR( magnify_
);
1634 case PointerStyle::Fill
:
1635 MAKE_CURSOR( fill_
);
1637 case PointerStyle::Move
:
1638 aCur
= XCreateFontCursor( pDisp_
, XC_fleur
);
1640 case PointerStyle::MoveData
:
1641 MAKE_CURSOR( movedata_
);
1643 case PointerStyle::CopyData
:
1644 MAKE_CURSOR( copydata_
);
1646 case PointerStyle::MoveFile
:
1647 MAKE_CURSOR( movefile_
);
1649 case PointerStyle::CopyFile
:
1650 MAKE_CURSOR( copyfile_
);
1652 case PointerStyle::MoveFiles
:
1653 MAKE_CURSOR( movefiles_
);
1655 case PointerStyle::CopyFiles
:
1656 MAKE_CURSOR( copyfiles_
);
1658 case PointerStyle::NotAllowed
:
1659 MAKE_CURSOR( nodrop_
);
1661 case PointerStyle::Rotate
:
1662 MAKE_CURSOR( rotate_
);
1664 case PointerStyle::HShear
:
1665 MAKE_CURSOR( hshear_
);
1667 case PointerStyle::VShear
:
1668 MAKE_CURSOR( vshear_
);
1670 case PointerStyle::DrawLine
:
1671 MAKE_CURSOR( drawline_
);
1673 case PointerStyle::DrawRect
:
1674 MAKE_CURSOR( drawrect_
);
1676 case PointerStyle::DrawPolygon
:
1677 MAKE_CURSOR( drawpolygon_
);
1679 case PointerStyle::DrawBezier
:
1680 MAKE_CURSOR( drawbezier_
);
1682 case PointerStyle::DrawArc
:
1683 MAKE_CURSOR( drawarc_
);
1685 case PointerStyle::DrawPie
:
1686 MAKE_CURSOR( drawpie_
);
1688 case PointerStyle::DrawCircleCut
:
1689 MAKE_CURSOR( drawcirclecut_
);
1691 case PointerStyle::DrawEllipse
:
1692 MAKE_CURSOR( drawellipse_
);
1694 case PointerStyle::DrawConnect
:
1695 MAKE_CURSOR( drawconnect_
);
1697 case PointerStyle::DrawText
:
1698 MAKE_CURSOR( drawtext_
);
1700 case PointerStyle::Mirror
:
1701 MAKE_CURSOR( mirror_
);
1703 case PointerStyle::Crook
:
1704 MAKE_CURSOR( crook_
);
1706 case PointerStyle::Crop
:
1707 MAKE_CURSOR( crop_
);
1709 case PointerStyle::MovePoint
:
1710 MAKE_CURSOR( movepoint_
);
1712 case PointerStyle::MoveBezierWeight
:
1713 MAKE_CURSOR( movebezierweight_
);
1715 case PointerStyle::DrawFreehand
:
1716 MAKE_CURSOR( drawfreehand_
);
1718 case PointerStyle::DrawCaption
:
1719 MAKE_CURSOR( drawcaption_
);
1721 case PointerStyle::Pen
: // Mouse Pointer is a pencil
1722 aCur
= XCreateFontCursor( pDisp_
, XC_pencil
);
1723 SAL_WARN_IF( aCur
== None
, "vcl", "GetPointer: Could not define cursor" );
1725 case PointerStyle::LinkData
:
1726 MAKE_CURSOR( linkdata_
);
1728 case PointerStyle::MoveDataLink
:
1729 MAKE_CURSOR( movedlnk_
);
1731 case PointerStyle::CopyDataLink
:
1732 MAKE_CURSOR( copydlnk_
);
1734 case PointerStyle::LinkFile
:
1735 MAKE_CURSOR( linkfile_
);
1737 case PointerStyle::MoveFileLink
:
1738 MAKE_CURSOR( moveflnk_
);
1740 case PointerStyle::CopyFileLink
:
1741 MAKE_CURSOR( copyflnk_
);
1743 case PointerStyle::Chart
:
1744 MAKE_CURSOR( chart_
);
1746 case PointerStyle::Detective
:
1747 MAKE_CURSOR( detective_
);
1749 case PointerStyle::PivotCol
:
1750 MAKE_CURSOR( pivotcol_
);
1752 case PointerStyle::PivotRow
:
1753 MAKE_CURSOR( pivotrow_
);
1755 case PointerStyle::PivotField
:
1756 MAKE_CURSOR( pivotfld_
);
1758 case PointerStyle::PivotDelete
:
1759 MAKE_CURSOR( pivotdel_
);
1761 case PointerStyle::Chain
:
1762 MAKE_CURSOR( chain_
);
1764 case PointerStyle::ChainNotAllowed
:
1765 MAKE_CURSOR( chainnot_
);
1767 case PointerStyle::AutoScrollN
:
1770 case PointerStyle::AutoScrollS
:
1771 MAKE_CURSOR( ass_
);
1773 case PointerStyle::AutoScrollW
:
1774 MAKE_CURSOR( asw_
);
1776 case PointerStyle::AutoScrollE
:
1777 MAKE_CURSOR( ase_
);
1779 case PointerStyle::AutoScrollNW
:
1780 MAKE_CURSOR( asnw_
);
1782 case PointerStyle::AutoScrollNE
:
1783 MAKE_CURSOR( asne_
);
1785 case PointerStyle::AutoScrollSW
:
1786 MAKE_CURSOR( assw_
);
1788 case PointerStyle::AutoScrollSE
:
1789 MAKE_CURSOR( asse_
);
1791 case PointerStyle::AutoScrollNS
:
1792 MAKE_CURSOR( asns_
);
1794 case PointerStyle::AutoScrollWE
:
1795 MAKE_CURSOR( aswe_
);
1797 case PointerStyle::AutoScrollNSWE
:
1798 MAKE_CURSOR( asnswe_
);
1800 case PointerStyle::TextVertical
:
1801 MAKE_CURSOR( vertcurs_
);
1804 // #i32329# Enhanced table selection
1805 case PointerStyle::TabSelectS
:
1806 MAKE_CURSOR( tblsels_
);
1808 case PointerStyle::TabSelectE
:
1809 MAKE_CURSOR( tblsele_
);
1811 case PointerStyle::TabSelectSE
:
1812 MAKE_CURSOR( tblselse_
);
1814 case PointerStyle::TabSelectW
:
1815 MAKE_CURSOR( tblselw_
);
1817 case PointerStyle::TabSelectSW
:
1818 MAKE_CURSOR( tblselsw_
);
1821 case PointerStyle::HideWhitespace
:
1822 MAKE_CURSOR( hidewhitespace_
);
1824 case PointerStyle::ShowWhitespace
:
1825 MAKE_CURSOR( showwhitespace_
);
1827 case PointerStyle::FatCross
:
1828 MAKE_CURSOR( fatcross_
);
1832 OSL_FAIL("pointer not implemented");
1833 aCur
= XCreateFontCursor( pDisp_
, XC_arrow
);
1839 XColor aBlack
, aWhite
, aDummy
;
1840 Colormap hColormap
= GetColormap(m_nXDefaultScreen
).GetXColormap();
1842 XAllocNamedColor( pDisp_
, hColormap
, "black", &aBlack
, &aDummy
);
1843 XAllocNamedColor( pDisp_
, hColormap
, "white", &aWhite
, &aDummy
);
1845 aCur
= XCreatePixmapCursor( pDisp_
,
1846 aCursBitmap
, aMaskBitmap
,
1850 XFreePixmap( pDisp_
, aCursBitmap
);
1851 XFreePixmap( pDisp_
, aMaskBitmap
);
1857 int SalDisplay::CaptureMouse( SalFrame
*pCapture
)
1859 static const char* pEnv
= getenv( "SAL_NO_MOUSEGRABS" );
1863 m_pCapture
= nullptr;
1864 if( !pEnv
|| !*pEnv
)
1865 XUngrabPointer( GetDisplay(), CurrentTime
);
1866 XFlush( GetDisplay() );
1870 m_pCapture
= nullptr;
1872 // FIXME: get rid of X11SalFrame
1873 const SystemEnvData
* pEnvData
= pCapture
->GetSystemData();
1874 if( !pEnv
|| !*pEnv
)
1876 int ret
= XGrabPointer( GetDisplay(),
1877 static_cast<::Window
>(pEnvData
->GetWindowHandle(pCapture
)),
1879 PointerMotionMask
| ButtonPressMask
|ButtonReleaseMask
,
1883 static_cast<X11SalFrame
*>(pCapture
)->GetCursor(),
1886 if( ret
!= GrabSuccess
)
1888 SAL_WARN("vcl", "SalDisplay::CaptureMouse could not grab pointer: " << ret
);
1893 m_pCapture
= pCapture
;
1899 bool SalX11Display::IsEvent()
1901 if( HasUserEvents() || XEventsQueued( pDisp_
, QueuedAlready
) )
1908 void SalX11Display::Yield()
1910 if( DispatchInternalEvent() )
1914 DBG_ASSERT(GetSalInstance()->GetYieldMutex()->IsCurrentThread(),
1915 "will crash soon since solar mutex not locked in SalDisplay::Yield" );
1917 XNextEvent( pDisp_
, &aEvent
);
1919 // coverity[overrun-buffer-val : FALSE] - coverity has problems with uno::Sequence
1920 Dispatch( &aEvent
);
1923 if( GetX11SalData()->HasXErrorOccurred() )
1926 DbgPrintDisplayEvent("SalDisplay::Yield (WasXError)", &aEvent
);
1929 GetX11SalData()->ResetXErrorOccurred();
1932 void SalX11Display::Dispatch( XEvent
*pEvent
)
1934 SalI18N_InputMethod
* const pInputMethod
=
1935 pXLib_
? pXLib_
->GetInputMethod() : nullptr;
1939 ::Window aFrameWindow
= None
;
1940 if( pEvent
->type
== KeyPress
|| pEvent
->type
== KeyRelease
)
1942 const ::Window aWindow
= pEvent
->xkey
.window
;
1943 for( auto pSalFrame
: m_aFrames
)
1945 const X11SalFrame
* pFrame
= static_cast< const X11SalFrame
* >( pSalFrame
);
1946 const ::Window aCurFrameWindow
= pFrame
->GetWindow();
1947 if( aCurFrameWindow
== aWindow
|| pFrame
->GetShellWindow() == aWindow
)
1949 aFrameWindow
= aCurFrameWindow
;
1954 if( pInputMethod
->FilterEvent( pEvent
, aFrameWindow
) )
1958 SalInstance
* pInstance
= GetSalInstance();
1959 pInstance
->CallEventCallback( pEvent
, sizeof( XEvent
) );
1961 switch( pEvent
->type
)
1964 while( XCheckWindowEvent( pEvent
->xany
.display
,
1965 pEvent
->xany
.window
,
1969 m_nLastUserEventTime
= pEvent
->xmotion
.time
;
1971 case PropertyNotify
:
1972 if( pEvent
->xproperty
.atom
== getWMAdaptor()->getAtom( WMAdaptor::VCL_SYSTEM_SETTINGS
) )
1974 for(const ScreenData
& rScreen
: m_aScreens
)
1976 if( pEvent
->xproperty
.window
== rScreen
.m_aRefWindow
)
1978 for (auto pSalFrame
: m_aFrames
)
1979 pSalFrame
->CallCallback( SalEvent::SettingsChanged
, nullptr );
1986 if( MappingModifier
== pEvent
->xmapping
.request
)
1988 XRefreshKeyboardMapping( &pEvent
->xmapping
);
1994 m_nLastUserEventTime
= pEvent
->xbutton
.time
;
1998 m_nLastUserEventTime
= pEvent
->xkey
.time
;
2002 if ( GetKbdExtension()->UseExtension()
2003 && GetKbdExtension()->GetEventBase() == pEvent
->type
)
2005 GetKbdExtension()->Dispatch( pEvent
);
2011 for (auto pSalFrame
: m_aFrames
)
2013 X11SalFrame
* pFrame
= static_cast<X11SalFrame
*>( pSalFrame
);
2015 ::Window aDispatchWindow
= pEvent
->xany
.window
;
2016 if( pFrame
->GetWindow() == aDispatchWindow
2017 || pFrame
->GetShellWindow() == aDispatchWindow
2018 || pFrame
->GetForeignParent() == aDispatchWindow
2021 pFrame
->Dispatch( pEvent
);
2024 if( pEvent
->type
== ConfigureNotify
&& pEvent
->xconfigure
.window
== pFrame
->GetStackingWindow() )
2026 pFrame
->Dispatch( pEvent
);
2031 // dispatch to salobjects
2032 X11SalObject::Dispatch( pEvent
);
2034 // is this perhaps a root window that changed size ?
2035 processRandREvent( pEvent
);
2039 void SalDisplay::DbgPrintDisplayEvent(const char *pComment
, const XEvent
*pEvent
) const
2041 static const char* const EventNames
[] =
2080 if( pEvent
->type
<= MappingNotify
)
2082 SAL_INFO("vcl.app", "[" << pComment
<< "] "
2083 << EventNames
[pEvent
->type
]
2084 << " s=" << pEvent
->xany
.send_event
2085 << " w=" << pEvent
->xany
.window
);
2087 switch( pEvent
->type
)
2091 SAL_INFO("vcl.app", "\t\ts=" << pEvent
->xkey
.state
2092 << " c=" << pEvent
->xkey
.keycode
);
2097 SAL_INFO("vcl.app", "\t\ts=" << pEvent
->xbutton
.state
2098 << " b=" << pEvent
->xbutton
.button
2099 << " x=" << pEvent
->xbutton
.x
2100 << " y=" << pEvent
->xbutton
.y
2101 << " rx=" << pEvent
->xbutton
.x_root
2102 << " ry=" << pEvent
->xbutton
.y_root
);
2106 SAL_INFO("vcl.app", "\t\ts=" << pEvent
->xmotion
.state
2107 << " x=" << pEvent
->xmotion
.x
2108 << " y=" << pEvent
->xmotion
.y
);
2113 SAL_INFO("vcl.app", "\t\tm=" << pEvent
->xcrossing
.mode
2114 << " f=" << pEvent
->xcrossing
.focus
2115 << " x=" << pEvent
->xcrossing
.x
2116 << " y=" << pEvent
->xcrossing
.y
);
2121 SAL_INFO("vcl.app", "\t\tm=" << pEvent
->xfocus
.mode
2122 << " d=" << pEvent
->xfocus
.detail
);
2126 case GraphicsExpose
:
2127 SAL_INFO("vcl.app", "\t\tc=" << pEvent
->xexpose
.count
2128 << " " << pEvent
->xexpose
.width
2129 << "*" << pEvent
->xexpose
.height
2130 << " " << pEvent
->xexpose
.x
2131 << "+" << pEvent
->xexpose
.y
);
2134 case VisibilityNotify
:
2135 SAL_INFO("vcl.app", "\t\ts=" << pEvent
->xvisibility
.state
);
2146 case ReparentNotify
:
2147 SAL_INFO("vcl.app", "\t\tp=" << sal::static_int_cast
< int >(
2148 pEvent
->xreparent
.parent
)
2149 << " x=" << pEvent
->xreparent
.x
2150 << " y=" << pEvent
->xreparent
.y
);
2153 case ConfigureNotify
:
2154 SAL_INFO("vcl.app", "\t\tb=" << pEvent
->xconfigure
.border_width
2155 << " " << pEvent
->xconfigure
.width
2156 << "*" << pEvent
->xconfigure
.height
2157 << " " << pEvent
->xconfigure
.x
2158 << "+" << pEvent
->xconfigure
.y
);
2161 case PropertyNotify
:
2162 SAL_INFO("vcl.app", "\t\ta=" << GetAtomName(
2163 pDisp_
, pEvent
->xproperty
.atom
)
2164 << std::showbase
<< std::hex
<< std::uppercase
2165 << " (" << sal::static_int_cast
< unsigned int >(
2166 pEvent
->xproperty
.atom
) << ").");
2169 case ColormapNotify
:
2170 SAL_INFO("vcl.app", "\t\tc=" << pEvent
->xcolormap
.colormap
2171 << " n=" << pEvent
->xcolormap
.c_new
2172 << " s=" << pEvent
->xcolormap
.state
);
2176 SAL_INFO("vcl.app", "\t\ta=" << GetAtomName(
2177 pDisp_
, pEvent
->xclient
.message_type
)
2178 << std::showbase
<< std::hex
<< std::uppercase
2179 << " (" << sal::static_int_cast
< unsigned int >(
2180 pEvent
->xclient
.message_type
) << ")"
2182 << " f=" << pEvent
->xclient
.format
2184 << " [" << pEvent
->xclient
.data
.l
[0]
2185 << "," << pEvent
->xclient
.data
.l
[1]
2186 << "," << pEvent
->xclient
.data
.l
[2]
2187 << "," << pEvent
->xclient
.data
.l
[3]
2188 << "," << pEvent
->xclient
.data
.l
[4]
2193 SAL_INFO("vcl.app", "\t\tr="
2194 << (MappingModifier
== pEvent
->xmapping
.request
?
2196 (MappingKeyboard
== pEvent
->xmapping
.request
?
2197 "MappingKeyboard" : "MappingPointer"))
2204 SAL_INFO("vcl.app", "[" << pComment
<< "] "
2206 << " s=" << pEvent
->xany
.send_event
2207 << " w=" << pEvent
->xany
.window
);
2210 void SalDisplay::PrintInfo() const
2214 SAL_INFO( "vcl", "Environment" );
2215 SAL_INFO( "vcl", "\t$DISPLAY \t\"" << GetEnv( "DISPLAY" ) << "\"");
2216 SAL_INFO( "vcl", "\t$SAL_VISUAL \t\"" << GetEnv( "SAL_VISUAL" ) << "\"");
2217 SAL_INFO( "vcl", "\t$SAL_IGNOREXERRORS\t\"" << GetEnv( "SAL_IGNOREXERRORS" ) << "\"");
2218 SAL_INFO( "vcl", "\t$SAL_PROPERTIES \t\"" << GetEnv( "SAL_PROPERTIES" ) << "\"");
2219 SAL_INFO( "vcl", "\t$SAL_SYNCHRONIZE \t\"" << GetEnv( "SAL_SYNCHRONIZE" ) << "\"");
2221 char sHostname
[ 120 ];
2222 gethostname (sHostname
, 120 );
2223 SAL_INFO( "vcl", "Client" );
2224 SAL_INFO( "vcl", "\tHost \t\"" << sHostname
<< "\"");
2226 SAL_INFO( "vcl", "Display" );
2227 SAL_INFO( "vcl", "\tHost \t\"" << DisplayString(pDisp_
) << "\"");
2228 SAL_INFO( "vcl", "\tVendor (Release) \t\"" << ServerVendor(pDisp_
) << " (" << VendorRelease(pDisp_
) << ")\"");
2229 SAL_INFO( "vcl", "\tProtocol \t" << ProtocolVersion(pDisp_
) << "." << ProtocolRevision(pDisp_
) );
2230 SAL_INFO( "vcl", "\tScreen (count,def)\t" << m_nXDefaultScreen
.getXScreen() << " (" << ScreenCount(pDisp_
) << "," << DefaultScreen(pDisp_
) << ")");
2231 SAL_INFO( "vcl", "\tshift ctrl alt \t" << KeyStr( nShiftKeySym_
) << " (0x" << std::hex
<< sal::static_int_cast
< unsigned int >(nShiftKeySym_
) << ") "
2232 << KeyStr( nCtrlKeySym_
) << " (0x" << sal::static_int_cast
< unsigned int >(nCtrlKeySym_
) << ") "
2233 << KeyStr( nMod1KeySym_
) << " (0x" << sal::static_int_cast
< unsigned int >(nMod1KeySym_
) << ")");
2234 if( XExtendedMaxRequestSize(pDisp_
) != 0 )
2235 SAL_INFO( "vcl", "\tXMaxRequestSize \t" << XMaxRequestSize(pDisp_
) * 4 << " " << XExtendedMaxRequestSize(pDisp_
) * 4 << " [bytes]");
2236 SAL_INFO( "vcl", "\tWMName \t" << getWMAdaptor()->getWindowManagerName() );
2238 SAL_INFO( "vcl", "Screen" );
2239 SAL_INFO( "vcl", "\tResolution/Size \t" << aResolution_
.A() << "*" << aResolution_
.B()
2240 << " " << m_aScreens
[m_nXDefaultScreen
.getXScreen()].m_aSize
.Width() << "*" << m_aScreens
[m_nXDefaultScreen
.getXScreen()].m_aSize
.Height()
2241 << " " << (Hypothenuse( DisplayWidthMM ( pDisp_
, m_nXDefaultScreen
.getXScreen() ),
2242 DisplayHeightMM( pDisp_
, m_nXDefaultScreen
.getXScreen() ) ) / 25.4 ) << "\"" );
2243 SAL_INFO( "vcl", "\tBlack&White \t" << GetColormap(m_nXDefaultScreen
).GetBlackPixel() << " "
2244 << GetColormap(m_nXDefaultScreen
).GetWhitePixel() );
2245 SAL_INFO( "vcl", "\tRGB \t0x" << std::hex
<< GetVisual(m_nXDefaultScreen
).red_mask
2246 << " 0x" << GetVisual(m_nXDefaultScreen
).green_mask
2247 << " 0x" << GetVisual(m_nXDefaultScreen
).blue_mask
);
2251 void SalDisplay::addXineramaScreenUnique( int i
, tools::Long i_nX
, tools::Long i_nY
, tools::Long i_nWidth
, tools::Long i_nHeight
)
2253 // see if any frame buffers are at the same coordinates
2254 // this can happen with weird configuration e.g. on
2255 // XFree86 and Clone displays
2256 const size_t nScreens
= m_aXineramaScreens
.size();
2257 for( size_t n
= 0; n
< nScreens
; n
++ )
2259 if( m_aXineramaScreens
[n
].Left() == i_nX
&&
2260 m_aXineramaScreens
[n
].Top() == i_nY
)
2262 if( m_aXineramaScreens
[n
].GetWidth() < i_nWidth
||
2263 m_aXineramaScreens
[n
].GetHeight() < i_nHeight
)
2265 m_aXineramaScreenIndexMap
[i
] = n
;
2266 m_aXineramaScreens
[n
].SetSize( Size( i_nWidth
, i_nHeight
) );
2271 m_aXineramaScreenIndexMap
[i
] = m_aXineramaScreens
.size();
2272 m_aXineramaScreens
.emplace_back( Point( i_nX
, i_nY
), Size( i_nWidth
, i_nHeight
) );
2275 void SalDisplay::InitXinerama()
2277 if( m_aScreens
.size() > 1 )
2279 m_bXinerama
= false;
2280 return; // multiple screens mean no xinerama
2282 #if defined(USE_XINERAMA_XORG)
2283 if( !XineramaIsActive( pDisp_
) )
2286 int nFramebuffers
= 1;
2287 XineramaScreenInfo
* pScreens
= XineramaQueryScreens( pDisp_
, &nFramebuffers
);
2291 if( nFramebuffers
> 1 )
2293 m_aXineramaScreens
= std::vector
<tools::Rectangle
>();
2294 m_aXineramaScreenIndexMap
= std::vector
<int>(nFramebuffers
);
2295 for( int i
= 0; i
< nFramebuffers
; i
++ )
2297 addXineramaScreenUnique( i
, pScreens
[i
].x_org
,
2300 pScreens
[i
].height
);
2302 m_bXinerama
= m_aXineramaScreens
.size() > 1;
2306 #if OSL_DEBUG_LEVEL > 1
2309 for (auto const& screen
: m_aXineramaScreens
)
2310 SAL_INFO("vcl.app", "Xinerama screen: "
2311 << screen
.GetWidth()
2312 << "x" << screen
.GetHeight()
2313 << "+" << screen
.Left()
2314 << "+" << screen
.Top());
2321 static Bool
timestamp_predicate( Display
*, XEvent
* i_pEvent
, XPointer i_pArg
)
2323 SalDisplay
* pSalDisplay
= reinterpret_cast<SalDisplay
*>(i_pArg
);
2324 if( i_pEvent
->type
== PropertyNotify
&&
2325 i_pEvent
->xproperty
.window
== pSalDisplay
->GetDrawable( pSalDisplay
->GetDefaultXScreen() ) &&
2326 i_pEvent
->xproperty
.atom
== pSalDisplay
->getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT
)
2334 Time
SalDisplay::GetEventTimeImpl( bool i_bAlwaysReget
) const
2336 if( m_nLastUserEventTime
== CurrentTime
|| i_bAlwaysReget
)
2338 // get current server time
2339 unsigned char c
= 0;
2341 Atom nAtom
= getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT
);
2342 XChangeProperty( GetDisplay(), GetDrawable( GetDefaultXScreen() ),
2343 nAtom
, nAtom
, 8, PropModeReplace
, &c
, 1 );
2344 XIfEvent( GetDisplay(), &aEvent
, timestamp_predicate
, reinterpret_cast<XPointer
>(const_cast<SalDisplay
*>(this)));
2345 m_nLastUserEventTime
= aEvent
.xproperty
.time
;
2347 return m_nLastUserEventTime
;
2350 bool SalDisplay::XIfEventWithTimeout( XEvent
* o_pEvent
, XPointer i_pPredicateData
,
2351 X_if_predicate i_pPredicate
) const
2353 /* #i99360# ugly workaround an X11 library bug
2354 this replaces the following call:
2355 XIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData );
2359 if( ! XCheckIfEvent( GetDisplay(), o_pEvent
, i_pPredicate
, i_pPredicateData
) )
2361 // wait for some event to arrive
2363 aFD
.fd
= ConnectionNumber(GetDisplay());
2364 aFD
.events
= POLLIN
;
2366 tools::Long nTimeout
= 1000;
2367 (void)poll(&aFD
, 1, nTimeout
);
2368 if( ! XCheckIfEvent( GetDisplay(), o_pEvent
, i_pPredicate
, i_pPredicateData
) )
2370 (void)poll(&aFD
, 1, nTimeout
); // try once more for a packet of events from the Xserver
2371 if( ! XCheckIfEvent( GetDisplay(), o_pEvent
, i_pPredicate
, i_pPredicateData
) )
2380 SalVisual::SalVisual()
2381 : eRGBMode_(SalRGB::RGB
), nRedShift_(0), nGreenShift_(0), nBlueShift_(0)
2382 , nRedBits_(0), nGreenBits_(0), nBlueBits_(0)
2387 SalVisual::SalVisual( const XVisualInfo
* pXVI
)
2389 *static_cast<XVisualInfo
*>(this) = *pXVI
;
2390 if( GetClass() != TrueColor
)
2392 eRGBMode_
= SalRGB::RGB
;
2393 nRedShift_
= nGreenShift_
= nBlueShift_
= 0;
2394 nRedBits_
= nGreenBits_
= nBlueBits_
= 0;
2398 nRedShift_
= sal_Shift( red_mask
);
2399 nGreenShift_
= sal_Shift( green_mask
);
2400 nBlueShift_
= sal_Shift( blue_mask
);
2402 nRedBits_
= sal_significantBits( red_mask
);
2403 nGreenBits_
= sal_significantBits( green_mask
);
2404 nBlueBits_
= sal_significantBits( blue_mask
);
2406 if( GetDepth() == 24 )
2407 if( red_mask
== 0xFF0000 )
2408 if( green_mask
== 0xFF00 )
2409 if( blue_mask
== 0xFF )
2410 eRGBMode_
= SalRGB::RGB
;
2412 eRGBMode_
= SalRGB::otherSalRGB
;
2413 else if( blue_mask
== 0xFF00 )
2414 if( green_mask
== 0xFF )
2415 eRGBMode_
= SalRGB::RBG
;
2417 eRGBMode_
= SalRGB::otherSalRGB
;
2419 eRGBMode_
= SalRGB::otherSalRGB
;
2420 else if( green_mask
== 0xFF0000 )
2421 if( red_mask
== 0xFF00 )
2422 if( blue_mask
== 0xFF )
2423 eRGBMode_
= SalRGB::GRB
;
2425 eRGBMode_
= SalRGB::otherSalRGB
;
2426 else if( blue_mask
== 0xFF00 )
2427 if( red_mask
== 0xFF )
2428 eRGBMode_
= SalRGB::GBR
;
2430 eRGBMode_
= SalRGB::otherSalRGB
;
2432 eRGBMode_
= SalRGB::otherSalRGB
;
2433 else if( blue_mask
== 0xFF0000 )
2434 if( red_mask
== 0xFF00 )
2435 if( green_mask
== 0xFF )
2436 eRGBMode_
= SalRGB::BRG
;
2438 eRGBMode_
= SalRGB::otherSalRGB
;
2439 else if( green_mask
== 0xFF00 )
2440 if( red_mask
== 0xFF )
2441 eRGBMode_
= SalRGB::BGR
;
2443 eRGBMode_
= SalRGB::otherSalRGB
;
2445 eRGBMode_
= SalRGB::otherSalRGB
;
2447 eRGBMode_
= SalRGB::otherSalRGB
;
2449 eRGBMode_
= SalRGB::otherSalRGB
;
2452 // Converts the order of bytes of a Pixel into bytes of a Color
2453 // This is not reversible for the 6 XXXA
2455 // Color is RGB (ABGR) a=0xFF000000, r=0xFF0000, g=0xFF00, b=0xFF
2457 #define SALCOLOR SalRGB::RGB
2458 #define SALCOLORREVERSE SalRGB::BGR
2460 Color
SalVisual::GetTCColor( Pixel nPixel
) const
2462 if( SALCOLOR
== eRGBMode_
)
2463 return Color(ColorTransparency
, nPixel
);
2465 if( SALCOLORREVERSE
== eRGBMode_
)
2466 return Color( (nPixel
& 0x0000FF),
2467 (nPixel
& 0x00FF00) >> 8,
2468 (nPixel
& 0xFF0000) >> 16);
2470 Pixel r
= nPixel
& red_mask
;
2471 Pixel g
= nPixel
& green_mask
;
2472 Pixel b
= nPixel
& blue_mask
;
2474 if( SalRGB::otherSalRGB
!= eRGBMode_
) // 8+8+8=24
2475 return Color( r
>> nRedShift_
,
2479 if( nRedShift_
> 0 ) r
>>= nRedShift_
; else r
<<= -nRedShift_
;
2480 if( nGreenShift_
> 0 ) g
>>= nGreenShift_
; else g
<<= -nGreenShift_
;
2481 if( nBlueShift_
> 0 ) b
>>= nBlueShift_
; else b
<<= -nBlueShift_
;
2483 if( nRedBits_
!= 8 )
2484 r
|= (r
& 0xff) >> (8-nRedBits_
);
2485 if( nGreenBits_
!= 8 )
2486 g
|= (g
& 0xff) >> (8-nGreenBits_
);
2487 if( nBlueBits_
!= 8 )
2488 b
|= (b
& 0xff) >> (8-nBlueBits_
);
2490 return Color( r
, g
, b
);
2493 Pixel
SalVisual::GetTCPixel( Color nColor
) const
2495 if( SALCOLOR
== eRGBMode_
)
2496 return static_cast<Pixel
>(sal_uInt32(nColor
));
2498 Pixel r
= static_cast<Pixel
>( nColor
.GetRed() );
2499 Pixel g
= static_cast<Pixel
>( nColor
.GetGreen() );
2500 Pixel b
= static_cast<Pixel
>( nColor
.GetBlue() );
2502 if( SALCOLORREVERSE
== eRGBMode_
)
2503 return (b
<< 16) | (g
<< 8) | r
;
2505 if( SalRGB::otherSalRGB
!= eRGBMode_
) // 8+8+8=24
2506 return (r
<< nRedShift_
) | (g
<< nGreenShift_
) | (b
<< nBlueShift_
);
2508 if( nRedShift_
> 0 ) r
<<= nRedShift_
; else r
>>= -nRedShift_
;
2509 if( nGreenShift_
> 0 ) g
<<= nGreenShift_
; else g
>>= -nGreenShift_
;
2510 if( nBlueShift_
> 0 ) b
<<= nBlueShift_
; else b
>>= -nBlueShift_
;
2512 return (r
&red_mask
) | (g
&green_mask
) | (b
&blue_mask
);
2515 SalColormap::SalColormap( const SalDisplay
*pDisplay
, Colormap hColormap
,
2516 SalX11Screen nXScreen
)
2517 : m_pDisplay( pDisplay
),
2518 m_hColormap( hColormap
)
2520 m_aVisual
= m_pDisplay
->GetVisual( nXScreen
);
2524 GetXPixel( aColor
, 0x00, 0x00, 0x00 );
2525 m_nBlackPixel
= aColor
.pixel
;
2527 GetXPixel( aColor
, 0xFF, 0xFF, 0xFF );
2528 m_nWhitePixel
= aColor
.pixel
;
2530 m_nUsed
= 1 << m_aVisual
.GetDepth();
2532 if( m_aVisual
.GetClass() != PseudoColor
)
2537 // black, white, gray, ~gray = 4
2538 GetXPixels( aColor
, 0xC0, 0xC0, 0xC0 );
2540 // light colors: 3 * 2 = 6
2542 GetXPixels( aColor
, 0x00, 0x00, 0xFF );
2543 GetXPixels( aColor
, 0x00, 0xFF, 0x00 );
2544 GetXPixels( aColor
, 0x00, 0xFF, 0xFF );
2546 // standard colors: 7 * 2 = 14
2547 GetXPixels( aColor
, 0x00, 0x00, 0x80 );
2548 GetXPixels( aColor
, 0x00, 0x80, 0x00 );
2549 GetXPixels( aColor
, 0x00, 0x80, 0x80 );
2550 GetXPixels( aColor
, 0x80, 0x00, 0x00 );
2551 GetXPixels( aColor
, 0x80, 0x00, 0x80 );
2552 GetXPixels( aColor
, 0x80, 0x80, 0x00 );
2553 GetXPixels( aColor
, 0x80, 0x80, 0x80 );
2554 GetXPixels( aColor
, 0x00, 0xB8, 0xFF ); // Blue 7
2556 // cube: 6*6*6 - 8 = 208
2557 for( r
= 0; r
< 0x100; r
+= 0x33 ) // 0x33, 0x66, 0x99, 0xCC, 0xFF
2558 for( g
= 0; g
< 0x100; g
+= 0x33 )
2559 for( b
= 0; b
< 0x100; b
+= 0x33 )
2560 GetXPixels( aColor
, r
, g
, b
);
2562 // gray: 16 - 6 = 10
2563 for( g
= 0x11; g
< 0xFF; g
+= 0x11 )
2564 GetXPixels( aColor
, g
, g
, g
);
2566 // green: 16 - 6 = 10
2567 for( g
= 0x11; g
< 0xFF; g
+= 0x11 )
2568 GetXPixels( aColor
, 0, g
, 0 );
2571 for( r
= 0x11; r
< 0xFF; r
+= 0x11 )
2572 GetXPixels( aColor
, r
, 0, 0 );
2574 // blue: 16 - 6 = 10
2575 for( b
= 0x11; b
< 0xFF; b
+= 0x11 )
2576 GetXPixels( aColor
, 0, 0, b
);
2581 SalColormap::SalColormap()
2582 : m_pDisplay( vcl_sal::getSalDisplay(GetGenericUnixSalData()) ),
2583 m_hColormap( None
),
2588 m_aPalette
= std::vector
<Color
>(m_nUsed
);
2590 m_aPalette
[m_nBlackPixel
] = COL_BLACK
;
2591 m_aPalette
[m_nWhitePixel
] = COL_WHITE
;
2595 SalColormap::SalColormap( sal_uInt16 nDepth
)
2596 : m_pDisplay( vcl_sal::getSalDisplay(GetGenericUnixSalData()) ),
2597 m_hColormap( None
),
2598 m_nWhitePixel( (1 << nDepth
) - 1 ),
2599 m_nBlackPixel( 0x00000000 ),
2600 m_nUsed( 1 << nDepth
)
2602 SalX11Screen
nXScreen( vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetDefaultXScreen() );
2603 const SalVisual
*pVisual
= &m_pDisplay
->GetVisual( nXScreen
);
2605 if( pVisual
->GetClass() == TrueColor
&& pVisual
->GetDepth() == nDepth
)
2606 m_aVisual
= *pVisual
;
2611 if( !XMatchVisualInfo( m_pDisplay
->GetDisplay(),
2612 m_pDisplay
->GetDefaultXScreen().getXScreen(),
2617 aVI
.visual
= new Visual
;
2618 aVI
.visualid
= VisualID(-1);
2621 aVI
.c_class
= TrueColor
;
2622 if( 24 == nDepth
) // 888
2624 aVI
.red_mask
= 0xFF0000;
2625 aVI
.green_mask
= 0x00FF00;
2626 aVI
.blue_mask
= 0x0000FF;
2628 else if( 8 == nDepth
) // 332
2630 aVI
.red_mask
= 0x0000E0;
2631 aVI
.green_mask
= 0x00001C;
2632 aVI
.blue_mask
= 0x000003;
2636 aVI
.red_mask
= 0x000000;
2637 aVI
.green_mask
= 0x000000;
2638 aVI
.blue_mask
= 0x000000;
2640 aVI
.colormap_size
= 0;
2641 aVI
.bits_per_rgb
= 8;
2643 aVI
.visual
->ext_data
= nullptr;
2644 aVI
.visual
->visualid
= aVI
.visualid
;
2645 aVI
.visual
->c_class
= aVI
.c_class
;
2646 aVI
.visual
->red_mask
= aVI
.red_mask
;
2647 aVI
.visual
->green_mask
= aVI
.green_mask
;
2648 aVI
.visual
->blue_mask
= aVI
.blue_mask
;
2649 aVI
.visual
->bits_per_rgb
= aVI
.bits_per_rgb
;
2650 aVI
.visual
->map_entries
= aVI
.colormap_size
;
2652 m_aVisual
= SalVisual( &aVI
);
2653 m_aVisualOwnership
.owner
= true;
2656 m_aVisual
= SalVisual( &aVI
);
2660 SalColormap::~SalColormap()
2662 if (m_aVisualOwnership
.owner
)
2664 delete m_aVisual
.visual
;
2668 void SalColormap::GetPalette()
2671 m_aPalette
= std::vector
<Color
>(m_nUsed
);
2673 std::unique_ptr
<XColor
[]> aColor(new XColor
[m_nUsed
]);
2675 for( i
= 0; i
< m_nUsed
; i
++ )
2677 aColor
[i
].red
= aColor
[i
].green
= aColor
[i
].blue
= 0;
2678 aColor
[i
].pixel
= i
;
2681 XQueryColors( m_pDisplay
->GetDisplay(), m_hColormap
, aColor
.get(), m_nUsed
);
2683 for( i
= 0; i
< m_nUsed
; i
++ )
2685 m_aPalette
[i
] = Color( aColor
[i
].red
>> 8,
2686 aColor
[i
].green
>> 8,
2687 aColor
[i
].blue
>> 8 );
2691 static sal_uInt16
sal_Lookup( const std::vector
<Color
>& rPalette
,
2692 int r
, int g
, int b
,
2695 sal_uInt16 nPixel
= 0;
2696 int nBest
= ColorDiff( rPalette
[0], r
, g
, b
);
2698 for( Pixel i
= 1; i
< nUsed
; i
++ )
2700 int n
= ColorDiff( rPalette
[i
], r
, g
, b
);
2714 void SalColormap::GetLookupTable()
2716 m_aLookupTable
= std::vector
<sal_uInt16
>(16*16*16);
2719 for( int r
= 0; r
< 256; r
+= 17 )
2720 for( int g
= 0; g
< 256; g
+= 17 )
2721 for( int b
= 0; b
< 256; b
+= 17 )
2722 m_aLookupTable
[i
++] = sal_Lookup( m_aPalette
, r
, g
, b
, m_nUsed
);
2725 Color
SalColormap::GetColor( Pixel nPixel
) const
2727 if( m_nBlackPixel
== nPixel
) return COL_BLACK
;
2728 if( m_nWhitePixel
== nPixel
) return COL_WHITE
;
2730 if( m_aVisual
.GetVisual() )
2732 if( m_aVisual
.GetClass() == TrueColor
)
2733 return m_aVisual
.GetTCColor( nPixel
);
2735 if( m_aPalette
.empty()
2737 && m_aVisual
.GetDepth() <= 12
2738 && m_aVisual
.GetClass() == PseudoColor
)
2739 const_cast<SalColormap
*>(this)->GetPalette();
2742 if( !m_aPalette
.empty() && nPixel
< m_nUsed
)
2743 return m_aPalette
[nPixel
];
2747 SAL_WARN("vcl", "SalColormap::GetColor() !m_hColormap");
2748 return Color(ColorTransparency
, nPixel
);
2751 // DirectColor, StaticColor, StaticGray, GrayScale
2754 aColor
.pixel
= nPixel
;
2756 XQueryColor( m_pDisplay
->GetDisplay(), m_hColormap
, &aColor
);
2758 return Color( aColor
.red
>>8, aColor
.green
>>8, aColor
.blue
>>8 );
2761 inline bool SalColormap::GetXPixel( XColor
&rColor
,
2766 rColor
.red
= r
* 257;
2767 rColor
.green
= g
* 257;
2768 rColor
.blue
= b
* 257;
2769 return XAllocColor( GetXDisplay(), m_hColormap
, &rColor
);
2772 bool SalColormap::GetXPixels( XColor
&rColor
,
2777 if( !GetXPixel( rColor
, r
, g
, b
) )
2779 if( rColor
.pixel
& 1 )
2781 return GetXPixel( rColor
, r
^0xFF, g
^0xFF, b
^0xFF );
2784 Pixel
SalColormap::GetPixel( Color nColor
) const
2786 if( SALCOLOR_NONE
== nColor
) return 0;
2787 if( COL_BLACK
== nColor
) return m_nBlackPixel
;
2788 if( COL_WHITE
== nColor
) return m_nWhitePixel
;
2790 if( m_aVisual
.GetClass() == TrueColor
)
2791 return m_aVisual
.GetTCPixel( nColor
);
2793 if( m_aLookupTable
.empty() )
2795 if( m_aPalette
.empty()
2797 && m_aVisual
.GetDepth() <= 12
2798 && m_aVisual
.GetClass() == PseudoColor
) // what else ???
2799 const_cast<SalColormap
*>(this)->GetPalette();
2801 if( !m_aPalette
.empty() )
2802 for( Pixel i
= 0; i
< m_nUsed
; i
++ )
2803 if( m_aPalette
[i
] == nColor
)
2808 // DirectColor, StaticColor, StaticGray, GrayScale (PseudoColor)
2811 if( GetXPixel( aColor
,
2814 nColor
.GetBlue() ) )
2816 if( !m_aPalette
.empty() && m_aPalette
[aColor
.pixel
] == Color(0) )
2818 const_cast<SalColormap
*>(this)->m_aPalette
[aColor
.pixel
] = nColor
;
2820 if( !(aColor
.pixel
& 1) && m_aPalette
[aColor
.pixel
+1] == Color(0) )
2822 XColor aInversColor
;
2824 Color
nInversColor(ColorTransparency
, sal_uInt32(nColor
) ^ 0xFFFFFF);
2826 GetXPixel( aInversColor
,
2827 nInversColor
.GetRed(),
2828 nInversColor
.GetGreen(),
2829 nInversColor
.GetBlue() );
2831 if( m_aPalette
[aInversColor
.pixel
] == Color(0) )
2832 const_cast<SalColormap
*>(this)->m_aPalette
[aInversColor
.pixel
] = nInversColor
;
2835 SAL_INFO("vcl.app", "SalColormap::GetPixel() "
2836 << std::showbase
<< std::setfill('0')
2837 << std::setw(6) << std::hex
2838 << static_cast< unsigned long >(
2842 << aColor
.pixel
<< " "
2843 << std::showbase
<< std::setfill('0')
2844 << std::setw(6) << std::hex
2845 << static_cast< unsigned long >(
2846 sal_uInt32(nInversColor
))
2849 << aInversColor
.pixel
);
2854 return aColor
.pixel
;
2858 SAL_INFO("vcl.app", "SalColormap::GetPixel() !XAllocColor "
2860 << static_cast< unsigned long >(sal_uInt32(nColor
)));
2864 if( m_aPalette
.empty() )
2867 SAL_INFO("vcl.app", "SalColormap::GetPixel() Palette empty "
2869 << static_cast< unsigned long >(sal_uInt32(nColor
)));
2871 return sal_uInt32(nColor
);
2874 const_cast<SalColormap
*>(this)->GetLookupTable();
2877 // color matching via palette
2878 sal_uInt16 r
= nColor
.GetRed();
2879 sal_uInt16 g
= nColor
.GetGreen();
2880 sal_uInt16 b
= nColor
.GetBlue();
2881 return m_aLookupTable
[ (((r
+8)/17) << 8)
2886 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */