summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2014-03-28 10:03:33 +0100
committerLuboš Luňák <l.lunak@collabora.com>2014-03-28 10:07:26 +0100
commit557e52e8cd90db43416cdd183704d549fcf73ee2 (patch)
tree9501a5a5b298a27c53f150dcd8cbc645a9e2cc91 /vcl
parent019c342c9b69bb437e030d1ad495ebfba5566316 (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.hxx1
-rw-r--r--vcl/unx/generic/app/wmadaptor.cxx1
-rw-r--r--vcl/unx/generic/window/salframe.cxx76
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());
}
}
}