]> git.saurik.com Git - wxWidgets.git/blame - src/osx/cocoa/taskbar.mm
Test m_nowpeer pointer before using it.
[wxWidgets.git] / src / osx / cocoa / taskbar.mm
CommitLineData
01250f9b 1/////////////////////////////////////////////////////////////////////////
7ac5e1c9 2// File: src/osx/cocoa/taskbar.mm
01250f9b
KO
3// Purpose: Implements wxTaskBarIcon class
4// Author: David Elliott
5// Modified by:
6// Created: 2004/01/24
7// RCS-ID: $Id: taskbar.mm 35650 2005-09-23 12:56:45Z MR $
8// Copyright: (c) 2004 David Elliott
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////
11
12#include "wx/wxprec.h"
f1d7af8f 13#if wxUSE_TASKBARICON
01250f9b
KO
14
15#ifndef WX_PRECOMP
16 #include "wx/menu.h"
17 #include "wx/icon.h"
18 #include "wx/log.h"
19 #include "wx/dcclient.h"
20#endif
21
22#include "wx/taskbar.h"
23
7ac5e1c9 24#include "wx/osx/private.h"
01250f9b
KO
25
26// A category for methods that are only present in Panther's SDK
27@interface NSStatusItem(wxNSStatusItemPrePantherCompatibility)
28- (void)popUpStatusItemMenu:(NSMenu *)menu;
29@end
30
31class wxTaskBarIconWindow;
32
33// ============================================================================
34// wxTaskBarIconImpl
35// Base class for the various Cocoa implementations.
36// ============================================================================
37class wxTaskBarIconImpl
38{
39public:
40 wxTaskBarIconImpl(wxTaskBarIcon *taskBarIcon)
41 : m_taskBarIcon(taskBarIcon)
42 , m_iconWindow(NULL)
43 {}
44 virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString) = 0;
45 virtual bool RemoveIcon() = 0;
46 virtual bool PopupMenu(wxMenu *menu) = 0;
47 virtual ~wxTaskBarIconImpl();
48 inline wxTaskBarIcon* GetTaskBarIcon() { return m_taskBarIcon; }
49 wxMenu * CreatePopupMenu()
50 { return m_taskBarIcon->CreatePopupMenu(); }
03647350 51
c0c133e1 52 wxDECLARE_NO_COPY_CLASS(wxTaskBarIconImpl);
03647350 53
01250f9b
KO
54protected:
55 wxTaskBarIcon *m_taskBarIcon;
56 wxTaskBarIconWindow *m_iconWindow;
57private:
58 wxTaskBarIconImpl();
59};
60
61// ============================================================================
62// wxTaskBarIconDockImpl
63// An implementation using the Dock icon.
64// ============================================================================
65class wxTaskBarIconDockImpl: public wxTaskBarIconImpl
66{
67public:
68 wxTaskBarIconDockImpl(wxTaskBarIcon *taskBarIcon);
69 virtual ~wxTaskBarIconDockImpl();
70 virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString);
71 virtual bool RemoveIcon();
72 virtual bool PopupMenu(wxMenu *menu);
73
74 static WX_NSMenu CocoaGetDockNSMenu();
75protected:
76 WX_NSMenu CocoaDoGetDockNSMenu();
77 WX_NSImage m_originalDockIcon;
78 // There can be only one Dock icon, so make sure we keep it that way
79 static wxTaskBarIconDockImpl *sm_dockIcon;
80private:
81 wxTaskBarIconDockImpl();
82};
83
84// ============================================================================
85// wxTaskBarIconCustomStatusItemImpl
86// An implementation using an NSStatusItem with a custom NSView
87// ============================================================================
88class wxTaskBarIconCustomStatusItemImpl: public wxTaskBarIconImpl
89{
90public:
91 wxTaskBarIconCustomStatusItemImpl(wxTaskBarIcon *taskBarIcon);
92 virtual ~wxTaskBarIconCustomStatusItemImpl();
93 virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString);
94 virtual bool RemoveIcon();
95 virtual bool PopupMenu(wxMenu *menu);
96protected:
97 NSStatusItem *m_cocoaNSStatusItem;
98private:
99 wxTaskBarIconCustomStatusItemImpl();
100};
101
102// ============================================================================
103// wxTaskBarIconWindow
104// Used by all implementations to forward events from the wxMenu
105// ============================================================================
106class wxTaskBarIconWindow: public wxWindow
107{
108 DECLARE_EVENT_TABLE()
109public:
110 wxTaskBarIconWindow(wxTaskBarIconImpl *taskBarIconImpl)
111 : wxWindow(NULL,-1)
112 , m_taskBarIconImpl(taskBarIconImpl)
113 { wxASSERT(m_taskBarIconImpl); }
114
115 void OnMenuEvent(wxCommandEvent& event);
116protected:
117 wxTaskBarIconImpl *m_taskBarIconImpl;
118};
119
120// ============================================================================
121// wxTaskBarIconWindowCustom
122// Used by the CustomStatusIcon implementation for the custom NSView.
123// ============================================================================
124class wxTaskBarIconWindowCustom: public wxTaskBarIconWindow
125{
126 DECLARE_EVENT_TABLE()
127public:
128 wxTaskBarIconWindowCustom(wxTaskBarIconImpl *taskBarIconImpl)
129 : wxTaskBarIconWindow(taskBarIconImpl)
130 {}
131 void SetIcon(const wxIcon& icon)
132 { m_icon = icon; }
133 void OnMouseEvent(wxMouseEvent &event);
134 void OnPaint(wxPaintEvent &event);
135protected:
136 wxIcon m_icon;
137};
138
139// ============================================================================
140// wxTaskBarIcon implementation
141// The facade class.
142// ============================================================================
143IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
144
145wxTaskBarIcon::wxTaskBarIcon(wxTaskBarIconType iconType)
146{
147 if(iconType == DOCK)
148 m_impl = new wxTaskBarIconDockImpl(this);
149 else if(iconType == CUSTOM_STATUSITEM)
150 m_impl = new wxTaskBarIconCustomStatusItemImpl(this);
151 else
152 { m_impl = NULL;
153 wxFAIL_MSG(wxT("Invalid wxTaskBarIcon type"));
154 }
155}
156
157wxTaskBarIcon::~wxTaskBarIcon()
158{
159 delete m_impl;
160}
161
162// Operations
163
164bool wxTaskBarIcon::IsIconInstalled() const
03647350 165{
01250f9b
KO
166 return false;
167}
168
169bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
170{
171 return m_impl->SetIcon(icon,tooltip);
172}
173
174bool wxTaskBarIcon::RemoveIcon()
175{
176 return m_impl->RemoveIcon();
177}
178
179bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
180{
181 return m_impl->PopupMenu(menu);
182}
183
184// ============================================================================
185// wxTaskBarIconImpl
186// ============================================================================
187
188wxTaskBarIconImpl::~wxTaskBarIconImpl()
189{
190// wxAutoNSAutoreleasePool pool;
191 delete m_iconWindow;
192}
193
194// ============================================================================
195// wxTaskBarIconDockImpl
196// ============================================================================
197wxTaskBarIconDockImpl *wxTaskBarIconDockImpl::sm_dockIcon = NULL;
198
199wxTaskBarIconDockImpl::wxTaskBarIconDockImpl(wxTaskBarIcon *taskBarIcon)
200: wxTaskBarIconImpl(taskBarIcon)
201{
202 m_originalDockIcon = nil;
203 wxASSERT_MSG(!sm_dockIcon, wxT("You should never have more than one dock icon!"));
204 sm_dockIcon = this;
205}
206
207wxTaskBarIconDockImpl::~wxTaskBarIconDockImpl()
208{
209// wxAutoNSAutoreleasePool pool;
210 if(sm_dockIcon == this)
211 sm_dockIcon = NULL;
212}
213
214WX_NSMenu wxTaskBarIconDockImpl::CocoaGetDockNSMenu()
215{
216 if(sm_dockIcon)
217 return sm_dockIcon->CocoaDoGetDockNSMenu();
218 return nil;
219}
220
221WX_NSMenu wxTaskBarIconDockImpl::CocoaDoGetDockNSMenu()
222{
223 wxMenu *dockMenu = CreatePopupMenu();
224 if(!dockMenu)
225 return nil;
226 if(!m_iconWindow)
227 m_iconWindow = new wxTaskBarIconWindow(this);
228 dockMenu->SetInvokingWindow(m_iconWindow);
229 dockMenu->UpdateUI();
230 //dockMenu->SetCocoaDeletes(true);
231 return (WX_NSMenu)dockMenu->GetHMenu();
232}
233
d8207702 234bool wxTaskBarIconDockImpl::SetIcon(const wxIcon& WXUNUSED(icon), const wxString& WXUNUSED(tooltip))
01250f9b 235{
7ac5e1c9 236 wxMacAutoreleasePool pool;
01250f9b
KO
237 m_originalDockIcon = [[[NSApplication sharedApplication] applicationIconImage] retain];
238 //[[NSApplication sharedApplication] setApplicationIconImage:icon.GetNSImage()];
239 return true;
240}
241
242bool wxTaskBarIconDockImpl::RemoveIcon()
243{
244 [[NSApplication sharedApplication] setApplicationIconImage:m_originalDockIcon];
245 [m_originalDockIcon release];
246 return true;
247}
248
d8207702 249bool wxTaskBarIconDockImpl::PopupMenu(wxMenu *WXUNUSED(menu))
01250f9b
KO
250{
251 wxFAIL_MSG(wxT("You cannot force the Dock icon menu to popup"));
252 return false;
253}
254
255
256// ============================================================================
257// wxTaskBarIconCustomStatusItemImpl
258// ============================================================================
259wxTaskBarIconCustomStatusItemImpl::wxTaskBarIconCustomStatusItemImpl(wxTaskBarIcon *taskBarIcon)
260: wxTaskBarIconImpl(taskBarIcon)
261{
262 m_cocoaNSStatusItem = nil;
263}
264
265wxTaskBarIconCustomStatusItemImpl::~wxTaskBarIconCustomStatusItemImpl()
266{
267}
268
d8207702 269bool wxTaskBarIconCustomStatusItemImpl::SetIcon(const wxIcon& icon, const wxString& WXUNUSED(tooltip))
01250f9b 270{
7ac5e1c9 271 wxMacAutoreleasePool pool;
01250f9b
KO
272 if(!m_cocoaNSStatusItem)
273 {
274 m_cocoaNSStatusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
275 [m_cocoaNSStatusItem retain];
276 }
277 if(!m_iconWindow)
278 m_iconWindow= new wxTaskBarIconWindowCustom(this);
279 static_cast<wxTaskBarIconWindowCustom*>(m_iconWindow)->SetIcon(icon);
280 // FIXME: no less than 10 because most icon types don't work yet
281 // and this allows us to see how task bar icons would work
282 [(NSView*)m_iconWindow->GetHandle() setFrame:NSMakeRect(0.0,0.0,wxMax(10,icon.GetWidth()),[[NSStatusBar systemStatusBar] thickness])];
283 [m_cocoaNSStatusItem setView:(NSView*)m_iconWindow->GetHandle()];
284 return true;
285}
286
287bool wxTaskBarIconCustomStatusItemImpl::RemoveIcon()
288{
289 [m_cocoaNSStatusItem release];
290 m_cocoaNSStatusItem = nil;
291 delete m_iconWindow;
292 m_iconWindow = NULL;
293 return true;
294}
295
296bool wxTaskBarIconCustomStatusItemImpl::PopupMenu(wxMenu *menu)
297{
298 wxASSERT(menu);
299 menu->SetInvokingWindow(m_iconWindow);
300 menu->UpdateUI();
301
302 if([m_cocoaNSStatusItem respondsToSelector:@selector(popUpStatusItemMenu:)])
303 { // OS X >= 10.3
304 [m_cocoaNSStatusItem popUpStatusItemMenu:(NSMenu*)menu->GetHMenu()];
305 }
306 else
307 { // pretty good fake for OS X < 10.3
308 NSEvent *nsevent = [NSEvent mouseEventWithType:NSLeftMouseDown
309 location:NSMakePoint(-1.0,-4.0) modifierFlags:0 timestamp:0
310 windowNumber:[[(NSView*)m_iconWindow->GetHandle() window] windowNumber]
311 context:[NSGraphicsContext currentContext]
312 eventNumber:0 clickCount:1 pressure:0.0];
313 [NSMenu popUpContextMenu:menu->GetHMenu() withEvent:nsevent forView:(NSView*)m_iconWindow->GetHandle()];
314 }
315 menu->SetInvokingWindow(NULL);
316 return true;
317}
318
319// ============================================================================
320// wxTaskBarIconWindow
321// ============================================================================
322BEGIN_EVENT_TABLE(wxTaskBarIconWindow, wxWindow)
323 EVT_MENU(-1, wxTaskBarIconWindow::OnMenuEvent)
324END_EVENT_TABLE()
325
326void wxTaskBarIconWindow::OnMenuEvent(wxCommandEvent &event)
327{
328 m_taskBarIconImpl->GetTaskBarIcon()->ProcessEvent(event);
329}
330
331// ============================================================================
332// wxTaskBarIconWindowCustom
333// ============================================================================
334BEGIN_EVENT_TABLE(wxTaskBarIconWindowCustom, wxTaskBarIconWindow)
335 EVT_MOUSE_EVENTS(wxTaskBarIconWindowCustom::OnMouseEvent)
336 EVT_PAINT(wxTaskBarIconWindowCustom::OnPaint)
337END_EVENT_TABLE()
338
339void wxTaskBarIconWindowCustom::OnMouseEvent(wxMouseEvent &event)
340{
341 wxEventType tbEventType = 0;
342 if(event.GetEventType() == wxEVT_MOTION)
343 tbEventType = wxEVT_TASKBAR_MOVE;
344 else if(event.GetEventType() == wxEVT_LEFT_DOWN)
345 tbEventType = wxEVT_TASKBAR_LEFT_DOWN;
346 else if(event.GetEventType() == wxEVT_LEFT_UP)
347 tbEventType = wxEVT_TASKBAR_LEFT_UP;
348 else if(event.GetEventType() == wxEVT_RIGHT_DOWN)
349 tbEventType = wxEVT_TASKBAR_RIGHT_DOWN;
350 else if(event.GetEventType() == wxEVT_RIGHT_UP)
351 tbEventType = wxEVT_TASKBAR_RIGHT_UP;
352 else if(event.GetEventType() == wxEVT_LEFT_DCLICK)
353 tbEventType = wxEVT_TASKBAR_LEFT_DCLICK;
354 else if(event.GetEventType() == wxEVT_RIGHT_DCLICK)
355 tbEventType = wxEVT_TASKBAR_RIGHT_DCLICK;
356 else
357 return;
358 wxTaskBarIconEvent tbiEvent(tbEventType,m_taskBarIconImpl->GetTaskBarIcon());
359 m_taskBarIconImpl->GetTaskBarIcon()->ProcessEvent(tbiEvent);
360}
361
d8207702 362void wxTaskBarIconWindowCustom::OnPaint(wxPaintEvent &WXUNUSED(event))
01250f9b
KO
363{
364 wxPaintDC dc(this);
365 // FIXME: This is a temporary hack until we can see real icons
366 dc.SetBackground(wxBrush(*wxBLUE));
367 dc.Clear();
368 dc.DrawIcon(m_icon,0,0);
369}
370
01250f9b 371#endif //def wxHAS_TASK_BAR_ICON