adding taskbar implementation for statusitem (menubar) and dock, fixes #12838

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@67084 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Stefan Csomor
2011-02-28 10:12:06 +00:00
parent a5d0c88a85
commit b59cd6c433
2 changed files with 200 additions and 144 deletions

View File

@@ -26,14 +26,22 @@ public:
#if wxOSX_USE_COCOA #if wxOSX_USE_COCOA
, CUSTOM_STATUSITEM , CUSTOM_STATUSITEM
#endif #endif
// , STATUSITEM #if wxOSX_USE_COCOA
// , MENUEXTRA , DEFAULT_TYPE = CUSTOM_STATUSITEM
#else
, DEFAULT_TYPE = DOCK , DEFAULT_TYPE = DOCK
#endif
}; };
wxTaskBarIcon(wxTaskBarIconType iconType = DEFAULT_TYPE); wxTaskBarIcon(wxTaskBarIconType iconType = DEFAULT_TYPE);
virtual ~wxTaskBarIcon(); virtual ~wxTaskBarIcon();
// returns true if the taskbaricon is in the global menubar
#if wxOSX_USE_COCOA
bool OSXIsStatusItem();
#else
bool OSXIsStatusItem() { return false; }
#endif
bool IsOk() const { return true; } bool IsOk() const { return true; }
bool IsIconInstalled() const; bool IsIconInstalled() const;
@@ -42,6 +50,7 @@ public:
bool PopupMenu(wxMenu *menu); bool PopupMenu(wxMenu *menu);
protected: protected:
wxTaskBarIconType m_type;
class wxTaskBarIconImpl* m_impl; class wxTaskBarIconImpl* m_impl;
friend class wxTaskBarIconImpl; friend class wxTaskBarIconImpl;
}; };

View File

@@ -1,11 +1,11 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// File: src/osx/cocoa/taskbar.mm // File: src/osx/cocoa/taskbar.mm
// Purpose: Implements wxTaskBarIcon class // Purpose: Implements wxTaskBarIcon class
// Author: David Elliott // Author: David Elliott, Stefan Csomor
// Modified by: // Modified by:
// Created: 2004/01/24 // Created: 2004/01/24
// RCS-ID: $Id: taskbar.mm 35650 2005-09-23 12:56:45Z MR $ // RCS-ID: $Id: taskbar.mm 35650 2005-09-23 12:56:45Z MR $
// Copyright: (c) 2004 David Elliott // Copyright: (c) 2004 David Elliott, Stefan Csomor
// Licence: wxWindows licence // Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
@@ -23,13 +23,30 @@
#include "wx/osx/private.h" #include "wx/osx/private.h"
// A category for methods that are only present in Panther's SDK
@interface NSStatusItem(wxNSStatusItemPrePantherCompatibility)
- (void)popUpStatusItemMenu:(NSMenu *)menu;
@end
class wxTaskBarIconWindow; class wxTaskBarIconWindow;
//-----------------------------------------------------------------------------
//
// wxTaskBarIconWindow
//
// Event handler for menus
// NB: Since wxWindows in Mac HAVE to have parents we need this to be
// a top level window...
//-----------------------------------------------------------------------------
class wxTaskBarIconWindow : public wxTopLevelWindow
{
public:
wxTaskBarIconWindow(wxTaskBarIconImpl *impl);
void OnMenuEvent(wxCommandEvent& event);
void OnUpdateUIEvent(wxUpdateUIEvent& event);
private:
wxTaskBarIconImpl *m_impl;
DECLARE_EVENT_TABLE()
};
// ============================================================================ // ============================================================================
// wxTaskBarIconImpl // wxTaskBarIconImpl
// Base class for the various Cocoa implementations. // Base class for the various Cocoa implementations.
@@ -37,12 +54,15 @@ class wxTaskBarIconWindow;
class wxTaskBarIconImpl class wxTaskBarIconImpl
{ {
public: public:
wxTaskBarIconImpl(wxTaskBarIcon *taskBarIcon) wxTaskBarIconImpl(wxTaskBarIcon *taskBarIcon);
: m_taskBarIcon(taskBarIcon)
, m_iconWindow(NULL) virtual bool IsStatusItem() const { return false; }
{}
virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString) = 0; virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString) = 0;
virtual bool RemoveIcon() = 0; virtual bool RemoveIcon() = 0;
bool IsIconInstalled() const { return m_icon.Ok(); }
virtual bool PopupMenu(wxMenu *menu) = 0; virtual bool PopupMenu(wxMenu *menu) = 0;
virtual ~wxTaskBarIconImpl(); virtual ~wxTaskBarIconImpl();
inline wxTaskBarIcon* GetTaskBarIcon() { return m_taskBarIcon; } inline wxTaskBarIcon* GetTaskBarIcon() { return m_taskBarIcon; }
@@ -53,7 +73,8 @@ public:
protected: protected:
wxTaskBarIcon *m_taskBarIcon; wxTaskBarIcon *m_taskBarIcon;
wxTaskBarIconWindow *m_iconWindow; wxBitmap m_icon;
wxTaskBarIconWindow *m_eventWindow;
private: private:
wxTaskBarIconImpl(); wxTaskBarIconImpl();
}; };
@@ -71,16 +92,24 @@ public:
virtual bool RemoveIcon(); virtual bool RemoveIcon();
virtual bool PopupMenu(wxMenu *menu); virtual bool PopupMenu(wxMenu *menu);
static WX_NSMenu CocoaGetDockNSMenu(); static WX_NSMenu OSXGetDockHMenu();
protected: protected:
WX_NSMenu CocoaDoGetDockNSMenu(); WX_NSMenu OSXDoGetDockHMenu();
WX_NSImage m_originalDockIcon;
// There can be only one Dock icon, so make sure we keep it that way // There can be only one Dock icon, so make sure we keep it that way
static wxTaskBarIconDockImpl *sm_dockIcon; static wxTaskBarIconDockImpl *sm_dockIcon;
private: private:
wxTaskBarIconDockImpl(); wxTaskBarIconDockImpl();
wxMenu *m_pMenu;
}; };
class wxTaskBarIconCustomStatusItemImpl;
@interface wxOSXStatusItemTarget : NSObject
{
wxTaskBarIconCustomStatusItemImpl* impl;
}
@end
// ============================================================================ // ============================================================================
// wxTaskBarIconCustomStatusItemImpl // wxTaskBarIconCustomStatusItemImpl
// An implementation using an NSStatusItem with a custom NSView // An implementation using an NSStatusItem with a custom NSView
@@ -90,52 +119,19 @@ class wxTaskBarIconCustomStatusItemImpl: public wxTaskBarIconImpl
public: public:
wxTaskBarIconCustomStatusItemImpl(wxTaskBarIcon *taskBarIcon); wxTaskBarIconCustomStatusItemImpl(wxTaskBarIcon *taskBarIcon);
virtual ~wxTaskBarIconCustomStatusItemImpl(); virtual ~wxTaskBarIconCustomStatusItemImpl();
virtual bool IsStatusItem() const { return true; }
virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString); virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString);
virtual bool RemoveIcon(); virtual bool RemoveIcon();
virtual bool PopupMenu(wxMenu *menu); virtual bool PopupMenu(wxMenu *menu);
protected: protected:
NSStatusItem *m_cocoaNSStatusItem; NSStatusItem *m_statusItem;
wxOSXStatusItemTarget *m_target;
private: private:
wxTaskBarIconCustomStatusItemImpl(); wxTaskBarIconCustomStatusItemImpl();
}; };
// ============================================================================
// wxTaskBarIconWindow
// Used by all implementations to forward events from the wxMenu
// ============================================================================
class wxTaskBarIconWindow: public wxWindow
{
DECLARE_EVENT_TABLE()
public:
wxTaskBarIconWindow(wxTaskBarIconImpl *taskBarIconImpl)
: wxWindow(NULL,-1)
, m_taskBarIconImpl(taskBarIconImpl)
{ wxASSERT(m_taskBarIconImpl); }
void OnMenuEvent(wxCommandEvent& event);
protected:
wxTaskBarIconImpl *m_taskBarIconImpl;
};
// ============================================================================
// wxTaskBarIconWindowCustom
// Used by the CustomStatusIcon implementation for the custom NSView.
// ============================================================================
class wxTaskBarIconWindowCustom: public wxTaskBarIconWindow
{
DECLARE_EVENT_TABLE()
public:
wxTaskBarIconWindowCustom(wxTaskBarIconImpl *taskBarIconImpl)
: wxTaskBarIconWindow(taskBarIconImpl)
{}
void SetIcon(const wxIcon& icon)
{ m_icon = icon; }
void OnMouseEvent(wxMouseEvent &event);
void OnPaint(wxPaintEvent &event);
protected:
wxIcon m_icon;
};
// ============================================================================ // ============================================================================
// wxTaskBarIcon implementation // wxTaskBarIcon implementation
// The facade class. // The facade class.
@@ -156,39 +152,69 @@ wxTaskBarIcon::wxTaskBarIcon(wxTaskBarIconType iconType)
wxTaskBarIcon::~wxTaskBarIcon() wxTaskBarIcon::~wxTaskBarIcon()
{ {
delete m_impl; if ( m_impl )
{
if ( m_impl->IsIconInstalled() )
m_impl->RemoveIcon();
delete m_impl;
m_impl = NULL;
}
}
bool wxTaskBarIcon::OSXIsStatusItem()
{
if ( m_impl )
return m_impl->IsStatusItem();
return false;
} }
// Operations // Operations
bool wxTaskBarIcon::IsIconInstalled() const bool wxTaskBarIcon::IsIconInstalled() const
{ {
if ( m_impl )
return m_impl->IsIconInstalled();
return false; return false;
} }
bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip) bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
{ {
return m_impl->SetIcon(icon,tooltip); if ( m_impl )
return m_impl->SetIcon(icon,tooltip);
return false;
} }
bool wxTaskBarIcon::RemoveIcon() bool wxTaskBarIcon::RemoveIcon()
{ {
return m_impl->RemoveIcon(); if ( m_impl )
return m_impl->RemoveIcon();
return false;
} }
bool wxTaskBarIcon::PopupMenu(wxMenu *menu) bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
{ {
return m_impl->PopupMenu(menu); if ( m_impl )
return m_impl->PopupMenu(menu);
return false;
} }
// ============================================================================ // ============================================================================
// wxTaskBarIconImpl // wxTaskBarIconImpl
// ============================================================================ // ============================================================================
wxTaskBarIconImpl::wxTaskBarIconImpl(wxTaskBarIcon* taskBarIcon)
: m_taskBarIcon(taskBarIcon), m_eventWindow(new wxTaskBarIconWindow(this))
{
}
wxTaskBarIconImpl::~wxTaskBarIconImpl() wxTaskBarIconImpl::~wxTaskBarIconImpl()
{ {
// wxAutoNSAutoreleasePool pool; delete m_eventWindow;
delete m_iconWindow;
} }
// ============================================================================ // ============================================================================
@@ -199,50 +225,55 @@ wxTaskBarIconDockImpl *wxTaskBarIconDockImpl::sm_dockIcon = NULL;
wxTaskBarIconDockImpl::wxTaskBarIconDockImpl(wxTaskBarIcon *taskBarIcon) wxTaskBarIconDockImpl::wxTaskBarIconDockImpl(wxTaskBarIcon *taskBarIcon)
: wxTaskBarIconImpl(taskBarIcon) : wxTaskBarIconImpl(taskBarIcon)
{ {
m_originalDockIcon = nil;
wxASSERT_MSG(!sm_dockIcon, wxT("You should never have more than one dock icon!")); wxASSERT_MSG(!sm_dockIcon, wxT("You should never have more than one dock icon!"));
sm_dockIcon = this; sm_dockIcon = this;
m_pMenu = NULL;
} }
wxTaskBarIconDockImpl::~wxTaskBarIconDockImpl() wxTaskBarIconDockImpl::~wxTaskBarIconDockImpl()
{ {
// wxAutoNSAutoreleasePool pool;
if(sm_dockIcon == this) if(sm_dockIcon == this)
sm_dockIcon = NULL; sm_dockIcon = NULL;
} }
WX_NSMenu wxTaskBarIconDockImpl::CocoaGetDockNSMenu() WX_NSMenu wxTaskBarIconDockImpl::OSXGetDockHMenu()
{ {
if(sm_dockIcon) if(sm_dockIcon)
return sm_dockIcon->CocoaDoGetDockNSMenu(); return sm_dockIcon->OSXDoGetDockHMenu();
return nil; return nil;
} }
WX_NSMenu wxTaskBarIconDockImpl::CocoaDoGetDockNSMenu() WX_NSMenu wxTaskBarIconDockImpl::OSXDoGetDockHMenu()
{ {
wxMenu *dockMenu = CreatePopupMenu(); wxMenu *dockMenu = CreatePopupMenu();
if(!dockMenu) if(!dockMenu)
return nil; return nil;
if(!m_iconWindow)
m_iconWindow = new wxTaskBarIconWindow(this); wxDELETE(m_pMenu);
dockMenu->SetInvokingWindow(m_iconWindow);
dockMenu->UpdateUI(); m_pMenu = dockMenu;
//dockMenu->SetCocoaDeletes(true);
m_pMenu->SetInvokingWindow(m_eventWindow);
m_pMenu->UpdateUI();
return (WX_NSMenu)dockMenu->GetHMenu(); return (WX_NSMenu)dockMenu->GetHMenu();
} }
bool wxTaskBarIconDockImpl::SetIcon(const wxIcon& WXUNUSED(icon), const wxString& WXUNUSED(tooltip)) bool wxTaskBarIconDockImpl::SetIcon(const wxIcon& icon, const wxString& WXUNUSED(tooltip))
{ {
wxMacAutoreleasePool pool; m_icon.CopyFromIcon(icon);
m_originalDockIcon = [[[NSApplication sharedApplication] applicationIconImage] retain]; [[NSApplication sharedApplication] setApplicationIconImage:m_icon.GetNSImage()];
//[[NSApplication sharedApplication] setApplicationIconImage:icon.GetNSImage()];
return true; return true;
} }
bool wxTaskBarIconDockImpl::RemoveIcon() bool wxTaskBarIconDockImpl::RemoveIcon()
{ {
[[NSApplication sharedApplication] setApplicationIconImage:m_originalDockIcon]; wxDELETE(m_pMenu);
[m_originalDockIcon release]; m_icon = wxBitmap();
[[NSApplication sharedApplication] setApplicationIconImage:nil];
return true; return true;
} }
@@ -252,14 +283,51 @@ bool wxTaskBarIconDockImpl::PopupMenu(wxMenu *WXUNUSED(menu))
return false; return false;
} }
@interface wxNSAppController(wxTaskBarIconNSApplicationDelegateCategory)
- (NSMenu*)applicationDockMenu:(NSApplication *)sender;
@end
@implementation wxNSAppController(wxTaskBarIconNSApplicationDelegateCategory)
- (NSMenu*)applicationDockMenu:(NSApplication *)sender
{
return wxTaskBarIconDockImpl::OSXGetDockHMenu();
}
@end
// ============================================================================ // ============================================================================
// wxTaskBarIconCustomStatusItemImpl // wxTaskBarIconCustomStatusItemImpl
// ============================================================================ // ============================================================================
@implementation wxOSXStatusItemTarget
- (void) clickedAction: (id) sender
{
wxMenu *menu = impl->CreatePopupMenu();
if (menu)
{
impl->PopupMenu(menu);
delete menu;
}
}
- (void)setImplementation: (wxTaskBarIconCustomStatusItemImpl *) theImplementation
{
impl = theImplementation;
}
- (wxTaskBarIconCustomStatusItemImpl*) implementation
{
return impl;
}
@end
wxTaskBarIconCustomStatusItemImpl::wxTaskBarIconCustomStatusItemImpl(wxTaskBarIcon *taskBarIcon) wxTaskBarIconCustomStatusItemImpl::wxTaskBarIconCustomStatusItemImpl(wxTaskBarIcon *taskBarIcon)
: wxTaskBarIconImpl(taskBarIcon) : wxTaskBarIconImpl(taskBarIcon)
{ {
m_cocoaNSStatusItem = nil; m_statusItem = nil;
m_target = nil;
} }
wxTaskBarIconCustomStatusItemImpl::~wxTaskBarIconCustomStatusItemImpl() wxTaskBarIconCustomStatusItemImpl::~wxTaskBarIconCustomStatusItemImpl()
@@ -268,50 +336,57 @@ wxTaskBarIconCustomStatusItemImpl::~wxTaskBarIconCustomStatusItemImpl()
bool wxTaskBarIconCustomStatusItemImpl::SetIcon(const wxIcon& icon, const wxString& WXUNUSED(tooltip)) bool wxTaskBarIconCustomStatusItemImpl::SetIcon(const wxIcon& icon, const wxString& WXUNUSED(tooltip))
{ {
wxMacAutoreleasePool pool; if(!m_statusItem)
if(!m_cocoaNSStatusItem)
{ {
m_cocoaNSStatusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength]; m_statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
[m_cocoaNSStatusItem retain]; [m_statusItem retain];
m_target = [[wxOSXStatusItemTarget alloc] init];
[m_target setImplementation:this];
[m_statusItem setTarget:m_target];
[m_statusItem setAction:@selector(clickedAction:)];
[m_statusItem sendActionOn:NSLeftMouseDownMask];
} }
if(!m_iconWindow)
m_iconWindow= new wxTaskBarIconWindowCustom(this); m_icon.CopyFromIcon(icon);
static_cast<wxTaskBarIconWindowCustom*>(m_iconWindow)->SetIcon(icon);
// FIXME: no less than 10 because most icon types don't work yet // status item doesn't scale automatically
// and this allows us to see how task bar icons would work
[(NSView*)m_iconWindow->GetHandle() setFrame:NSMakeRect(0.0,0.0,wxMax(10,icon.GetWidth()),[[NSStatusBar systemStatusBar] thickness])]; int dimension = m_icon.GetHeight();
[m_cocoaNSStatusItem setView:(NSView*)m_iconWindow->GetHandle()]; if ( m_icon.GetWidth() > dimension )
dimension = m_icon.GetWidth();
if ( dimension > 16 )
{
wxImage img = m_icon.ConvertToImage();
int factor = (dimension+15)/16;
m_icon = img.ShrinkBy(factor, factor);
}
[m_statusItem setImage:m_icon.GetNSImage()];
return true; return true;
} }
bool wxTaskBarIconCustomStatusItemImpl::RemoveIcon() bool wxTaskBarIconCustomStatusItemImpl::RemoveIcon()
{ {
[m_cocoaNSStatusItem release]; [m_statusItem release];
m_cocoaNSStatusItem = nil; m_statusItem = nil;
delete m_iconWindow; [m_target release];
m_iconWindow = NULL; m_target = nil;
m_icon = wxBitmap();
return true; return true;
} }
bool wxTaskBarIconCustomStatusItemImpl::PopupMenu(wxMenu *menu) bool wxTaskBarIconCustomStatusItemImpl::PopupMenu(wxMenu *menu)
{ {
wxASSERT(menu); wxASSERT(menu);
menu->SetInvokingWindow(m_iconWindow);
menu->SetInvokingWindow(m_eventWindow);
menu->UpdateUI(); menu->UpdateUI();
if([m_cocoaNSStatusItem respondsToSelector:@selector(popUpStatusItemMenu:)]) [m_statusItem popUpStatusItemMenu:(NSMenu*)menu->GetHMenu()];
{ // OS X >= 10.3
[m_cocoaNSStatusItem popUpStatusItemMenu:(NSMenu*)menu->GetHMenu()];
}
else
{ // pretty good fake for OS X < 10.3
NSEvent *nsevent = [NSEvent mouseEventWithType:NSLeftMouseDown
location:NSMakePoint(-1.0,-4.0) modifierFlags:0 timestamp:0
windowNumber:[[(NSView*)m_iconWindow->GetHandle() window] windowNumber]
context:[NSGraphicsContext currentContext]
eventNumber:0 clickCount:1 pressure:0.0];
[NSMenu popUpContextMenu:menu->GetHMenu() withEvent:nsevent forView:(NSView*)m_iconWindow->GetHandle()];
}
menu->SetInvokingWindow(NULL); menu->SetInvokingWindow(NULL);
return true; return true;
} }
@@ -319,53 +394,25 @@ bool wxTaskBarIconCustomStatusItemImpl::PopupMenu(wxMenu *menu)
// ============================================================================ // ============================================================================
// wxTaskBarIconWindow // wxTaskBarIconWindow
// ============================================================================ // ============================================================================
BEGIN_EVENT_TABLE(wxTaskBarIconWindow, wxWindow) BEGIN_EVENT_TABLE(wxTaskBarIconWindow, wxWindow)
EVT_MENU(-1, wxTaskBarIconWindow::OnMenuEvent) EVT_MENU(-1, wxTaskBarIconWindow::OnMenuEvent)
EVT_UPDATE_UI(-1, wxTaskBarIconWindow::OnUpdateUIEvent)
END_EVENT_TABLE() END_EVENT_TABLE()
void wxTaskBarIconWindow::OnMenuEvent(wxCommandEvent &event) wxTaskBarIconWindow::wxTaskBarIconWindow(wxTaskBarIconImpl *impl)
: m_impl(impl)
{ {
m_taskBarIconImpl->GetTaskBarIcon()->ProcessEvent(event);
} }
// ============================================================================ void wxTaskBarIconWindow::OnMenuEvent(wxCommandEvent& event)
// wxTaskBarIconWindowCustom
// ============================================================================
BEGIN_EVENT_TABLE(wxTaskBarIconWindowCustom, wxTaskBarIconWindow)
EVT_MOUSE_EVENTS(wxTaskBarIconWindowCustom::OnMouseEvent)
EVT_PAINT(wxTaskBarIconWindowCustom::OnPaint)
END_EVENT_TABLE()
void wxTaskBarIconWindowCustom::OnMouseEvent(wxMouseEvent &event)
{ {
wxEventType tbEventType = 0; m_impl->GetTaskBarIcon()->ProcessEvent(event);
if(event.GetEventType() == wxEVT_MOTION)
tbEventType = wxEVT_TASKBAR_MOVE;
else if(event.GetEventType() == wxEVT_LEFT_DOWN)
tbEventType = wxEVT_TASKBAR_LEFT_DOWN;
else if(event.GetEventType() == wxEVT_LEFT_UP)
tbEventType = wxEVT_TASKBAR_LEFT_UP;
else if(event.GetEventType() == wxEVT_RIGHT_DOWN)
tbEventType = wxEVT_TASKBAR_RIGHT_DOWN;
else if(event.GetEventType() == wxEVT_RIGHT_UP)
tbEventType = wxEVT_TASKBAR_RIGHT_UP;
else if(event.GetEventType() == wxEVT_LEFT_DCLICK)
tbEventType = wxEVT_TASKBAR_LEFT_DCLICK;
else if(event.GetEventType() == wxEVT_RIGHT_DCLICK)
tbEventType = wxEVT_TASKBAR_RIGHT_DCLICK;
else
return;
wxTaskBarIconEvent tbiEvent(tbEventType,m_taskBarIconImpl->GetTaskBarIcon());
m_taskBarIconImpl->GetTaskBarIcon()->ProcessEvent(tbiEvent);
} }
void wxTaskBarIconWindowCustom::OnPaint(wxPaintEvent &WXUNUSED(event)) void wxTaskBarIconWindow::OnUpdateUIEvent(wxUpdateUIEvent& event)
{ {
wxPaintDC dc(this); m_impl->GetTaskBarIcon()->ProcessEvent(event);
// FIXME: This is a temporary hack until we can see real icons
dc.SetBackground(wxBrush(*wxBLUE));
dc.Clear();
dc.DrawIcon(m_icon,0,0);
} }
#endif //def wxHAS_TASK_BAR_ICON #endif //def wxHAS_TASK_BAR_ICON