wxCocoa: Added wxTaskBarIcon

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@29901 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
David Elliott 2004-10-15 22:52:28 +00:00
parent c9f52ac517
commit f1d9e1ec6b
6 changed files with 472 additions and 4 deletions

View File

@ -2200,6 +2200,14 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
wx/mac/carbon/taskbarosx.h
</set>
<set var="ADVANCED_COCOA_SRC" hints="files">
src/cocoa/taskbar.mm
src/common/taskbarcmn.cpp
</set>
<set var="ADVANCED_COCOA_HDR" hints="files">
include/wx/cocoa/taskbar.h
</set>
<set var="ADVANCED_OS2_SRC" hints="files">
src/os2/joystick.cpp
src/os2/sound.cpp
@ -2580,6 +2588,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
<if cond="TOOLKIT=='MSW'">$(ADVANCED_MSW_SRC) $(ADVANCED_MSW_ONLY_SRC)</if>
<if cond="TOOLKIT=='WINCE'">$(ADVANCED_MSW_SRC)</if>
<if cond="TOOLKIT=='MAC'">$(ADVANCED_MAC_SRC)</if>
<if cond="TOOLKIT=='COCOA'">$(ADVANCED_COCOA_SRC)</if>
<if cond="TOOLKIT=='MOTIF'">$(ADVANCED_UNIX_SRC)</if>
<if cond="TOOLKIT=='GTK'">$(ADVANCED_UNIX_SRC) $(ADVANCED_GTK_SRC)</if>
<if cond="TOOLKIT=='X11'">$(ADVANCED_UNIX_SRC)</if>
@ -2589,6 +2598,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
<if cond="TOOLKIT=='MSW'">$(ADVANCED_MSW_HDR) $(ADVANCED_MSW_ONLY_HDR)</if>
<if cond="TOOLKIT=='WINCE'">$(ADVANCED_MSW_HDR)</if>
<if cond="TOOLKIT=='MAC'">$(ADVANCED_MAC_HDR)</if>
<if cond="TOOLKIT=='COCOA'">$(ADVANCED_COCOA_HDR)</if>
<if cond="TOOLKIT=='MOTIF'">$(ADVANCED_UNIX_HDR)</if>
<if cond="TOOLKIT=='GTK'">$(ADVANCED_GTK_HDR) $(ADVANCED_UNIX_HDR)</if>
<if cond="TOOLKIT=='X11'">$(ADVANCED_UNIX_HDR)</if>

View File

@ -5610,7 +5610,7 @@ fi
if test "$wxUSE_SYSTEM_OPTIONS" = "yes"; then
AC_DEFINE(wxUSE_SYSTEM_OPTIONS)
if test "$TOOLKIT" = "MSW" -o "$TOOLKIT" = "GTK" -o "$TOOLKIT" = "X11" -o \
"$TOOLKIT" = "MOTIF"; then
"$TOOLKIT" = "MOTIF" -o "$TOOLKIT" = "COCOA"; then
SAMPLES_SUBDIRS="$SAMPLES_SUBDIRS taskbar"
fi
fi

View File

@ -0,0 +1,53 @@
/////////////////////////////////////////////////////////////////////////
// File: wx/cocoa/taskbar.h
// Purpose: Defines wxTaskBarIcon class
// Author: David Elliott
// Modified by:
// Created: 2004/01/24
// RCS-ID: $Id$
// Copyright: (c) 2004 David Elliott
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////
#ifndef _WX_COCOA_TASKBAR_H__
#define _WX_COCOA_TASKBAR_H__
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma interface "taskbar.h"
#endif
#include "wx/icon.h"
class WXDLLEXPORT wxIcon;
class WXDLLEXPORT wxMenu;
class wxTaskBarIconCocoaImpl;
class wxTaskBarIconDockImpl;
class WXDLLEXPORT wxTaskBarIcon : public wxTaskBarIconBase
{
friend class wxTaskBarIconDockImpl;
DECLARE_DYNAMIC_CLASS_NO_COPY(wxTaskBarIcon)
public:
//type of taskbar item to create (currently only DOCK is implemented)
enum wxTaskBarIconType
{ DOCK
, CUSTOM_STATUSITEM
// , STATUSITEM // TODO: Implement using NSStatusItem w/o custom NSView
// , MENUEXTRA // Menu extras require undocumented hacks
, DEFAULT_TYPE = CUSTOM_STATUSITEM
};
// Only one wxTaskBarIcon can be of the Dock type so by default
// create NSStatusItem for maximum source compatibility.
wxTaskBarIcon(wxTaskBarIconType iconType = DEFAULT_TYPE);
virtual ~wxTaskBarIcon();
bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString);
bool RemoveIcon();
bool PopupMenu(wxMenu *menu); //, int x, int y);
protected:
wxTaskBarIconCocoaImpl *m_impl;
};
#endif // _WX_COCOA_TASKBAR_H__

View File

@ -30,8 +30,9 @@
#endif
/* taskbar is implemented in the major ports */
#if defined(__WXMSW__) || \
defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__) || defined(__WXMAC_OSX__)
#if defined(__WXMSW__) || defined(__WXCOCOA__) || \
defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__) || \
(defined(__WXMAC__) && __WXMAC_OSX__) || defined(__WXCOCOA__)
#define wxHAS_TASK_BAR_ICON
#else
#undef wxHAS_TASK_BAR_ICON

View File

@ -45,8 +45,10 @@ private:
#include "wx/msw/taskbar.h"
#elif defined(__WXGTK__) || defined(__WXX11__) || defined(__WXMOTIF__)
#include "wx/unix/taskbarx11.h"
#elif defined(__DARWIN__)
#elif defined (__WXMAC__) && __WXMAC_OSX__
#include "wx/mac/taskbarosx.h"
#elif defined (__WXCOCOA__)
#include "wx/cocoa/taskbar.h"
#endif
// ----------------------------------------------------------------------------

402
src/cocoa/taskbar.mm Normal file
View File

@ -0,0 +1,402 @@
/////////////////////////////////////////////////////////////////////////
// File: src/cocoa/taskbar.mm
// Purpose: Implements wxTaskBarIcon class
// Author: David Elliott
// Modified by:
// Created: 2004/01/24
// RCS-ID: $Id$
// Copyright: (c) 2004 David Elliott
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "taskbar.h"
#endif
#include "wx/wxprec.h"
#ifdef wxHAS_TASK_BAR_ICON
#ifndef WX_PRECOMP
#include "wx/menu.h"
#include "wx/icon.h"
#include "wx/log.h"
#include "wx/dcclient.h"
#endif
#include "wx/taskbar.h"
#import <AppKit/NSApplication.h>
#import <AppKit/NSImage.h>
#import <AppKit/NSMenu.h>
#import <AppKit/NSMenuItem.h>
#import <AppKit/NSStatusBar.h>
#import <AppKit/NSStatusItem.h>
#import <AppKit/NSView.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSEnumerator.h>
#import <AppKit/NSEvent.h>
#import <AppKit/NSWindow.h>
#import <AppKit/NSGraphicsContext.h>
#include "wx/cocoa/NSApplication.h"
#include "wx/cocoa/autorelease.h"
class wxTaskBarIconWindow;
// ============================================================================
// wxTaskBarIconCocoaImpl
// Base class for the various Cocoa implementations.
// ============================================================================
class wxTaskBarIconCocoaImpl
{
public:
wxTaskBarIconCocoaImpl(wxTaskBarIcon *taskBarIcon)
: m_taskBarIcon(taskBarIcon)
, m_iconWindow(NULL)
{}
virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString) = 0;
virtual bool RemoveIcon() = 0;
virtual bool PopupMenu(wxMenu *menu) = 0;
virtual ~wxTaskBarIconCocoaImpl();
inline wxTaskBarIcon* GetTaskBarIcon() { return m_taskBarIcon; }
protected:
wxTaskBarIcon *m_taskBarIcon;
wxTaskBarIconWindow *m_iconWindow;
private:
wxTaskBarIconCocoaImpl();
};
// ============================================================================
// wxTaskBarIconDockImpl
// An implementation using the Dock icon.
// ============================================================================
class wxTaskBarIconDockImpl: public wxTaskBarIconCocoaImpl
{
public:
wxTaskBarIconDockImpl(wxTaskBarIcon *taskBarIcon);
virtual ~wxTaskBarIconDockImpl();
virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString);
virtual bool RemoveIcon();
virtual bool PopupMenu(wxMenu *menu);
static WX_NSMenu CocoaGetDockNSMenu();
protected:
WX_NSMenu CocoaDoGetDockNSMenu();
WX_NSImage m_originalDockIcon;
// There can be only one Dock icon, so make sure we keep it that way
static wxTaskBarIconDockImpl *sm_dockIcon;
private:
wxTaskBarIconDockImpl();
};
// ============================================================================
// wxTaskBarIconCustomStatusItemImpl
// An implementation using an NSStatusItem with a custom NSView
// ============================================================================
class wxTaskBarIconCustomStatusItemImpl: public wxTaskBarIconCocoaImpl
{
public:
wxTaskBarIconCustomStatusItemImpl(wxTaskBarIcon *taskBarIcon);
virtual ~wxTaskBarIconCustomStatusItemImpl();
virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString);
virtual bool RemoveIcon();
virtual bool PopupMenu(wxMenu *menu);
protected:
NSStatusItem *m_cocoaNSStatusItem;
private:
wxTaskBarIconCustomStatusItemImpl();
};
// ============================================================================
// wxTaskBarIconWindow
// Used by all implementations to forward events from the wxMenu
// ============================================================================
class wxTaskBarIconWindow: public wxWindow
{
DECLARE_EVENT_TABLE()
public:
wxTaskBarIconWindow(wxTaskBarIconCocoaImpl *taskBarIconImpl)
: wxWindow(NULL,-1)
, m_taskBarIconImpl(taskBarIconImpl)
{ wxASSERT(m_taskBarIconImpl); }
void OnMenuEvent(wxCommandEvent& event);
protected:
wxTaskBarIconCocoaImpl *m_taskBarIconImpl;
};
// ============================================================================
// wxTaskBarIconWindowCustom
// Used by the CustomStatusIcon implementation for the custom NSView.
// ============================================================================
class wxTaskBarIconWindowCustom: public wxTaskBarIconWindow
{
DECLARE_EVENT_TABLE()
public:
wxTaskBarIconWindowCustom(wxTaskBarIconCocoaImpl *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
// The facade class.
// ============================================================================
IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
wxTaskBarIcon::wxTaskBarIcon(wxTaskBarIconType iconType)
{
if(iconType == DOCK)
m_impl = new wxTaskBarIconDockImpl(this);
else if(iconType == CUSTOM_STATUSITEM)
m_impl = new wxTaskBarIconCustomStatusItemImpl(this);
else
{ m_impl = NULL;
wxFAIL_MSG(wxT("Invalid wxTaskBarIcon type"));
}
}
wxTaskBarIcon::~wxTaskBarIcon()
{
delete m_impl;
}
// Operations
bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
{
return m_impl->SetIcon(icon,tooltip);
}
bool wxTaskBarIcon::RemoveIcon()
{
return m_impl->RemoveIcon();
}
bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
{
return m_impl->PopupMenu(menu);
}
// ============================================================================
// wxTaskBarIconCocoaImpl
// ============================================================================
#if 0
wxTaskBarIconCocoaImpl::wxTaskBarIconCocoaImpl(wxTaskBarIcon *taskBarIcon)
: m_taskBarIcon(taskBarIcon)
, m_iconWindow(NULL)
{
}
#endif
wxTaskBarIconCocoaImpl::~wxTaskBarIconCocoaImpl()
{
// wxAutoNSAutoreleasePool pool;
delete m_iconWindow;
}
// ============================================================================
// wxTaskBarIconDockImpl
// ============================================================================
wxTaskBarIconDockImpl *wxTaskBarIconDockImpl::sm_dockIcon = NULL;
wxTaskBarIconDockImpl::wxTaskBarIconDockImpl(wxTaskBarIcon *taskBarIcon)
: wxTaskBarIconCocoaImpl(taskBarIcon)
{
m_originalDockIcon = nil;
wxASSERT_MSG(!sm_dockIcon,"You should never have more than one dock icon!");
sm_dockIcon = this;
}
wxTaskBarIconDockImpl::~wxTaskBarIconDockImpl()
{
// wxAutoNSAutoreleasePool pool;
if(sm_dockIcon == this)
sm_dockIcon = NULL;
}
WX_NSMenu wxTaskBarIconDockImpl::CocoaGetDockNSMenu()
{
if(sm_dockIcon)
return sm_dockIcon->CocoaDoGetDockNSMenu();
return nil;
}
WX_NSMenu wxTaskBarIconDockImpl::CocoaDoGetDockNSMenu()
{
wxMenu *dockMenu = m_taskBarIcon->CreatePopupMenu();
if(!dockMenu)
return nil;
if(!m_iconWindow)
m_iconWindow = new wxTaskBarIconWindow(this);
dockMenu->SetInvokingWindow(m_iconWindow);
dockMenu->UpdateUI();
dockMenu->SetCocoaDeletes(true);
return dockMenu->GetNSMenu();
}
bool wxTaskBarIconDockImpl::SetIcon(const wxIcon& icon, const wxString& tooltip)
{
wxAutoNSAutoreleasePool pool;
m_originalDockIcon = [[[NSApplication sharedApplication] applicationIconImage] retain];
[[NSApplication sharedApplication] setApplicationIconImage:icon.GetNSImage()];
return true;
}
bool wxTaskBarIconDockImpl::RemoveIcon()
{
[[NSApplication sharedApplication] setApplicationIconImage:m_originalDockIcon];
[m_originalDockIcon release];
return true;
}
bool wxTaskBarIconDockImpl::PopupMenu(wxMenu *menu)
{
wxFAIL_MSG(wxT("You cannot force the Dock icon menu to popup"));
return false;
}
// ============================================================================
// wxTaskBarIconCustomStatusItemImpl
// ============================================================================
wxTaskBarIconCustomStatusItemImpl::wxTaskBarIconCustomStatusItemImpl(wxTaskBarIcon *taskBarIcon)
: wxTaskBarIconCocoaImpl(taskBarIcon)
{
m_cocoaNSStatusItem = nil;
}
wxTaskBarIconCustomStatusItemImpl::~wxTaskBarIconCustomStatusItemImpl()
{
}
bool wxTaskBarIconCustomStatusItemImpl::SetIcon(const wxIcon& icon, const wxString& tooltip)
{
wxAutoNSAutoreleasePool pool;
if(!m_cocoaNSStatusItem)
{
m_cocoaNSStatusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
[m_cocoaNSStatusItem retain];
}
if(!m_iconWindow)
m_iconWindow= new wxTaskBarIconWindowCustom(this);
static_cast<wxTaskBarIconWindowCustom*>(m_iconWindow)->SetIcon(icon);
// FIXME: no less than 10 because most icon types don't work yet
// and this allows us to see how task bar icons would work
[m_iconWindow->GetNSView() setFrame:NSMakeRect(0.0,0.0,wxMax(10,icon.GetWidth()),[[NSStatusBar systemStatusBar] thickness])];
[m_cocoaNSStatusItem setView:m_iconWindow->GetNSView()];
return true;
}
bool wxTaskBarIconCustomStatusItemImpl::RemoveIcon()
{
[m_cocoaNSStatusItem release];
m_cocoaNSStatusItem = nil;
delete m_iconWindow;
m_iconWindow = NULL;
return true;
}
bool wxTaskBarIconCustomStatusItemImpl::PopupMenu(wxMenu *menu)
{
wxASSERT(menu);
menu->SetInvokingWindow(m_iconWindow);
menu->UpdateUI();
if([m_cocoaNSStatusItem respondsToSelector:@selector(popUpStatusItemMenu:)])
{ // OS X >= 10.3
[m_cocoaNSStatusItem popUpStatusItemMenu:menu->GetNSMenu()];
}
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:[[m_iconWindow->GetNSView() window] windowNumber]
context:[NSGraphicsContext currentContext]
eventNumber:0 clickCount:1 pressure:0.0];
[NSMenu popUpContextMenu:menu->GetNSMenu() withEvent:nsevent forView:m_iconWindow->GetNSView()];
}
menu->SetInvokingWindow(NULL);
return true;
}
// ============================================================================
// wxTaskBarIconWindow
// ============================================================================
BEGIN_EVENT_TABLE(wxTaskBarIconWindow, wxWindow)
EVT_MENU(-1, wxTaskBarIconWindow::OnMenuEvent)
END_EVENT_TABLE()
void wxTaskBarIconWindow::OnMenuEvent(wxCommandEvent &event)
{
m_taskBarIconImpl->GetTaskBarIcon()->ProcessEvent(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;
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 &event)
{
wxPaintDC dc(this);
// FIXME: This is a temporary hack until we can see real icons
dc.SetBackground(wxBrush(*wxBLUE));
dc.Clear();
dc.DrawIcon(m_icon,0,0);
}
// ============================================================================
// wxTaskBarIconNSApplicationDelegateCategory
// ============================================================================
// This neatly solves the problem of DLL separation. If the wxAdvanced
// library (which this file is part of) is loaded then this category is
// defined and we get dock menu behavior without app.mm ever having to
// know we exist. C++ did sucketh so. :-)
@interface wxNSApplicationDelegate(wxTaskBarIconNSApplicationDelegateCategory)
- (NSMenu*)applicationDockMenu:(NSApplication *)sender;
@end
@implementation wxNSApplicationDelegate(wxTaskBarIconNSApplicationDelegateCategory)
- (NSMenu*)applicationDockMenu:(NSApplication *)sender
{
return wxTaskBarIconDockImpl::CocoaGetDockNSMenu();
}
@end
#endif //def wxHAS_TASK_BAR_ICON