diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2014-03-28 10:03:33 +0100 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2014-03-28 10:07:26 +0100 |
commit | 557e52e8cd90db43416cdd183704d549fcf73ee2 (patch) | |
tree | 9501a5a5b298a27c53f150dcd8cbc645a9e2cc91 /vcl | |
parent | 019c342c9b69bb437e030d1ad495ebfba5566316 (diff) |
set window icon also as _NET_WM_ICON (fdo#71494)
The old X way of just using WMHints doesn't seem to work at least with KWin,
which just falls back to finding a matching application icon based on WM_CLASS.
Change-Id: Ia014eb106cd370da74099fa750968df87acbda81
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/unx/wmadaptor.hxx | 1 | ||||
-rw-r--r-- | vcl/unx/generic/app/wmadaptor.cxx | 1 | ||||
-rw-r--r-- | vcl/unx/generic/window/salframe.cxx | 76 |
3 files changed, 74 insertions, 4 deletions
diff --git a/vcl/inc/unx/wmadaptor.hxx b/vcl/inc/unx/wmadaptor.hxx index e62ecce3e57e..e2ae8ce08432 100644 --- a/vcl/inc/unx/wmadaptor.hxx +++ b/vcl/inc/unx/wmadaptor.hxx @@ -76,6 +76,7 @@ public: NET_NUMBER_OF_DESKTOPS, NET_CURRENT_DESKTOP, NET_WORKAREA, + NET_WM_ICON, // atoms for Gnome WM hints WIN_SUPPORTING_WM_CHECK, diff --git a/vcl/unx/generic/app/wmadaptor.cxx b/vcl/unx/generic/app/wmadaptor.cxx index 8d705c3a8cc8..a89e21a42cf1 100644 --- a/vcl/unx/generic/app/wmadaptor.cxx +++ b/vcl/unx/generic/app/wmadaptor.cxx @@ -109,6 +109,7 @@ static const WMAdaptorProtocol aProtocolTab[] = { "_NET_CURRENT_DESKTOP", WMAdaptor::NET_CURRENT_DESKTOP }, { "_NET_NUMBER_OF_DESKTOPS", WMAdaptor::NET_NUMBER_OF_DESKTOPS }, { "_NET_WM_DESKTOP", WMAdaptor::NET_WM_DESKTOP }, + { "_NET_WM_ICON", WMAdaptor::NET_WM_ICON }, { "_NET_WM_ICON_NAME", WMAdaptor::NET_WM_ICON_NAME }, { "_NET_WM_PING", WMAdaptor::NET_WM_PING }, { "_NET_WM_STATE", WMAdaptor::NET_WM_STATE }, diff --git a/vcl/unx/generic/window/salframe.cxx b/vcl/unx/generic/window/salframe.cxx index 240a3c97fa24..af6ce24545fd 100644 --- a/vcl/unx/generic/window/salframe.cxx +++ b/vcl/unx/generic/window/salframe.cxx @@ -34,6 +34,7 @@ #include "vcl/layout.hxx" #include "vcl/printerinfomanager.hxx" #include "vcl/settings.hxx" +#include "vcl/bmpacc.hxx" #include <prex.h> #include <X11/Xatom.h> @@ -193,13 +194,69 @@ void X11SalFrame::askForXEmbedFocus( sal_Int32 i_nTimeCode ) GetGenericData()->ErrorTrapPop(); } +typedef std::vector< unsigned long > NetWmIconData; + +static void CreateNetWmAppIcon( sal_uInt16 nIcon, NetWmIconData& netwm_icon ) +{ + const int sizes[ 3 ] = { 48, 32, 16 }; + netwm_icon.resize( 48 * 48 + 32 * 32 + 16 * 16 + 3 * 2 ); + int pos = 0; + for( int i = 0; i < 3; ++i ) + { + int size = sizes[ i ]; + sal_uInt16 nIconSizeOffset; + if( size >= 48 ) + nIconSizeOffset = SV_ICON_SIZE48_START; + else if( size >= 32 ) + nIconSizeOffset = SV_ICON_SIZE32_START; + else + nIconSizeOffset = SV_ICON_SIZE16_START; + BitmapEx aIcon( ResId(nIconSizeOffset + nIcon, *ImplGetResMgr())); + if( aIcon.IsEmpty()) + continue; + Bitmap icon = aIcon.GetBitmap(); + AlphaMask mask; + switch( aIcon.GetTransparentType()) + { + case TRANSPARENT_NONE: + { + sal_uInt8 nTrans = 0; + mask = AlphaMask( icon.GetSizePixel(), &nTrans ); + } + break; + case TRANSPARENT_COLOR: + mask = AlphaMask( icon.CreateMask( aIcon.GetTransparentColor() ) ); + break; + case TRANSPARENT_BITMAP: + mask = aIcon.GetAlpha(); + break; + } + BitmapReadAccess* iconData = icon.AcquireReadAccess(); + BitmapReadAccess* maskData = mask.AcquireReadAccess(); + netwm_icon[ pos++ ] = size; // width + netwm_icon[ pos++ ] = size; // height + for( int y = 0; y < size; ++y ) + for( int x = 0; x < size; ++x ) + { + BitmapColor col = iconData->GetColor( y, x ); + BitmapColor alpha = maskData->GetColor( y, x ); + netwm_icon[ pos++ ] = (((( 255 - alpha.GetBlue()) * 256U ) + col.GetRed()) * 256 + col.GetGreen()) * 256 + col.GetBlue(); + } + icon.ReleaseAccess( iconData ); + mask.ReleaseAccess( maskData ); + } + netwm_icon.resize( pos ); +} + static bool lcl_SelectAppIconPixmap( SalDisplay *pDisplay, SalX11Screen nXScreen, sal_uInt16 nIcon, sal_uInt16 iconSize, - Pixmap& icon_pixmap, Pixmap& icon_mask) + Pixmap& icon_pixmap, Pixmap& icon_mask, NetWmIconData& netwm_icon) { if( ! ImplGetResMgr() ) return false; + CreateNetWmAppIcon( nIcon, netwm_icon ); + sal_uInt16 nIconSizeOffset; if( iconSize >= 48 ) @@ -279,6 +336,7 @@ void X11SalFrame::Init( sal_uLong nSalFrameStyle, SalX11Screen nXScreen, SystemP XWMHints Hints; Hints.flags = InputHint; Hints.input = (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ? False : True; + NetWmIconData netwm_icon; int x = 0, y = 0; unsigned int w = 500, h = 500; @@ -480,7 +538,7 @@ void X11SalFrame::Init( sal_uLong nSalFrameStyle, SalX11Screen nXScreen, SystemP bOk = lcl_SelectAppIconPixmap( pDisplay_, m_nXScreen, mnIconID != 1 ? mnIconID : (mpParent ? mpParent->mnIconID : 1), 32, - Hints.icon_pixmap, Hints.icon_mask ); + Hints.icon_pixmap, Hints.icon_mask, netwm_icon ); } catch( com::sun::star::uno::Exception& ) { @@ -679,6 +737,11 @@ void X11SalFrame::Init( sal_uLong nSalFrameStyle, SalX11Screen nXScreen, SystemP SAL_FRAME_STYLE_PARTIAL_FULLSCREEN) ) == SAL_FRAME_STYLE_DEFAULT ) pDisplay_->getWMAdaptor()->maximizeFrame( this, true, true ); + + if( !netwm_icon.empty() && GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_ICON )) + XChangeProperty( GetXDisplay(), mhWindow, + GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_ICON ), + XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&netwm_icon.front(), netwm_icon.size()); } m_nWorkArea = GetDisplay()->getWMAdaptor()->getCurrentWorkArea(); @@ -1009,15 +1072,16 @@ void X11SalFrame::SetIcon( sal_uInt16 nIcon ) } pHints = &Hints; + NetWmIconData netwm_icon; bool bOk = lcl_SelectAppIconPixmap( GetDisplay(), m_nXScreen, nIcon, iconSize, - pHints->icon_pixmap, pHints->icon_mask ); + pHints->icon_pixmap, pHints->icon_mask, netwm_icon ); if ( !bOk ) { // load default icon (0) bOk = lcl_SelectAppIconPixmap( GetDisplay(), m_nXScreen, 0, iconSize, - pHints->icon_pixmap, pHints->icon_mask ); + pHints->icon_pixmap, pHints->icon_mask, netwm_icon ); } if( bOk ) { @@ -1026,6 +1090,10 @@ void X11SalFrame::SetIcon( sal_uInt16 nIcon ) pHints->flags |= IconMaskHint; XSetWMHints( GetXDisplay(), GetShellWindow(), pHints ); + if( !netwm_icon.empty() && GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_ICON )) + XChangeProperty( GetXDisplay(), mhWindow, + GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_ICON ), + XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&netwm_icon.front(), netwm_icon.size()); } } } |