]> git.saurik.com Git - wxWidgets.git/blob - src/osx/cocoa/taskbar.mm
disable cursorRects for global busy state
[wxWidgets.git] / src / osx / cocoa / taskbar.mm
1 /////////////////////////////////////////////////////////////////////////
2 // File: src/osx/cocoa/taskbar.mm
3 // Purpose: Implements wxTaskBarIcon class
4 // Author: David Elliott, Stefan Csomor
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, Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13 #if wxUSE_TASKBARICON
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
24 #include "wx/osx/private.h"
25
26 class wxTaskBarIconWindow;
27
28 //-----------------------------------------------------------------------------
29 //
30 // wxTaskBarIconWindow
31 //
32 // Event handler for menus
33 // NB: Since wxWindows in Mac HAVE to have parents we need this to be
34 // a top level window...
35 //-----------------------------------------------------------------------------
36
37 class wxTaskBarIconWindow : public wxTopLevelWindow
38 {
39 public:
40 wxTaskBarIconWindow(wxTaskBarIconImpl *impl);
41
42 void OnMenuEvent(wxCommandEvent& event);
43 void OnUpdateUIEvent(wxUpdateUIEvent& event);
44
45 private:
46 wxTaskBarIconImpl *m_impl;
47 DECLARE_EVENT_TABLE()
48 };
49
50 // ============================================================================
51 // wxTaskBarIconImpl
52 // Base class for the various Cocoa implementations.
53 // ============================================================================
54 class wxTaskBarIconImpl
55 {
56 public:
57 wxTaskBarIconImpl(wxTaskBarIcon *taskBarIcon);
58
59 virtual bool IsStatusItem() const { return false; }
60
61 virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString) = 0;
62 virtual bool RemoveIcon() = 0;
63
64 bool IsIconInstalled() const { return m_icon.Ok(); }
65
66 virtual bool PopupMenu(wxMenu *menu) = 0;
67 virtual ~wxTaskBarIconImpl();
68 inline wxTaskBarIcon* GetTaskBarIcon() { return m_taskBarIcon; }
69 wxMenu * CreatePopupMenu()
70 { return m_taskBarIcon->CreatePopupMenu(); }
71
72 wxDECLARE_NO_COPY_CLASS(wxTaskBarIconImpl);
73
74 protected:
75 wxTaskBarIcon *m_taskBarIcon;
76 wxBitmap m_icon;
77 wxTaskBarIconWindow *m_eventWindow;
78 private:
79 wxTaskBarIconImpl();
80 };
81
82 // ============================================================================
83 // wxTaskBarIconDockImpl
84 // An implementation using the Dock icon.
85 // ============================================================================
86 class wxTaskBarIconDockImpl: public wxTaskBarIconImpl
87 {
88 public:
89 wxTaskBarIconDockImpl(wxTaskBarIcon *taskBarIcon);
90 virtual ~wxTaskBarIconDockImpl();
91 virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString);
92 virtual bool RemoveIcon();
93 virtual bool PopupMenu(wxMenu *menu);
94
95 static WX_NSMenu OSXGetDockHMenu();
96 protected:
97 WX_NSMenu OSXDoGetDockHMenu();
98 // There can be only one Dock icon, so make sure we keep it that way
99 static wxTaskBarIconDockImpl *sm_dockIcon;
100 private:
101 wxTaskBarIconDockImpl();
102 wxMenu *m_pMenu;
103 };
104
105 class wxTaskBarIconCustomStatusItemImpl;
106
107 @interface wxOSXStatusItemTarget : NSObject
108 {
109 wxTaskBarIconCustomStatusItemImpl* impl;
110 }
111 @end
112
113 // ============================================================================
114 // wxTaskBarIconCustomStatusItemImpl
115 // An implementation using an NSStatusItem with a custom NSView
116 // ============================================================================
117 class wxTaskBarIconCustomStatusItemImpl: public wxTaskBarIconImpl
118 {
119 public:
120 wxTaskBarIconCustomStatusItemImpl(wxTaskBarIcon *taskBarIcon);
121 virtual ~wxTaskBarIconCustomStatusItemImpl();
122
123 virtual bool IsStatusItem() const { return true; }
124
125 virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString);
126 virtual bool RemoveIcon();
127 virtual bool PopupMenu(wxMenu *menu);
128 protected:
129 NSStatusItem *m_statusItem;
130 wxOSXStatusItemTarget *m_target;
131 private:
132 wxTaskBarIconCustomStatusItemImpl();
133 };
134
135 // ============================================================================
136 // wxTaskBarIcon implementation
137 // The facade class.
138 // ============================================================================
139 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
140
141 wxTaskBarIcon::wxTaskBarIcon(wxTaskBarIconType iconType)
142 {
143 if(iconType == DOCK)
144 m_impl = new wxTaskBarIconDockImpl(this);
145 else if(iconType == CUSTOM_STATUSITEM)
146 m_impl = new wxTaskBarIconCustomStatusItemImpl(this);
147 else
148 { m_impl = NULL;
149 wxFAIL_MSG(wxT("Invalid wxTaskBarIcon type"));
150 }
151 }
152
153 wxTaskBarIcon::~wxTaskBarIcon()
154 {
155 if ( m_impl )
156 {
157 if ( m_impl->IsIconInstalled() )
158 m_impl->RemoveIcon();
159 delete m_impl;
160 m_impl = NULL;
161 }
162 }
163
164 bool wxTaskBarIcon::OSXIsStatusItem()
165 {
166 if ( m_impl )
167 return m_impl->IsStatusItem();
168
169 return false;
170 }
171
172 // Operations
173
174 bool wxTaskBarIcon::IsIconInstalled() const
175 {
176 if ( m_impl )
177 return m_impl->IsIconInstalled();
178
179 return false;
180 }
181
182 bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
183 {
184 if ( m_impl )
185 return m_impl->SetIcon(icon,tooltip);
186
187 return false;
188 }
189
190 bool wxTaskBarIcon::RemoveIcon()
191 {
192 if ( m_impl )
193 return m_impl->RemoveIcon();
194
195 return false;
196 }
197
198 bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
199 {
200 if ( m_impl )
201 return m_impl->PopupMenu(menu);
202
203 return false;
204 }
205
206 // ============================================================================
207 // wxTaskBarIconImpl
208 // ============================================================================
209
210 wxTaskBarIconImpl::wxTaskBarIconImpl(wxTaskBarIcon* taskBarIcon)
211 : m_taskBarIcon(taskBarIcon), m_eventWindow(new wxTaskBarIconWindow(this))
212 {
213 }
214
215 wxTaskBarIconImpl::~wxTaskBarIconImpl()
216 {
217 delete m_eventWindow;
218 }
219
220 // ============================================================================
221 // wxTaskBarIconDockImpl
222 // ============================================================================
223 wxTaskBarIconDockImpl *wxTaskBarIconDockImpl::sm_dockIcon = NULL;
224
225 wxTaskBarIconDockImpl::wxTaskBarIconDockImpl(wxTaskBarIcon *taskBarIcon)
226 : wxTaskBarIconImpl(taskBarIcon)
227 {
228 wxASSERT_MSG(!sm_dockIcon, wxT("You should never have more than one dock icon!"));
229 sm_dockIcon = this;
230 m_pMenu = NULL;
231 }
232
233 wxTaskBarIconDockImpl::~wxTaskBarIconDockImpl()
234 {
235 if(sm_dockIcon == this)
236 sm_dockIcon = NULL;
237 }
238
239 WX_NSMenu wxTaskBarIconDockImpl::OSXGetDockHMenu()
240 {
241 if(sm_dockIcon)
242 return sm_dockIcon->OSXDoGetDockHMenu();
243
244 return nil;
245 }
246
247 WX_NSMenu wxTaskBarIconDockImpl::OSXDoGetDockHMenu()
248 {
249 wxMenu *dockMenu = CreatePopupMenu();
250
251 if(!dockMenu)
252 return nil;
253
254 wxDELETE(m_pMenu);
255
256 m_pMenu = dockMenu;
257
258 m_pMenu->SetInvokingWindow(m_eventWindow);
259
260 m_pMenu->UpdateUI();
261
262 return (WX_NSMenu)dockMenu->GetHMenu();
263 }
264
265 bool wxTaskBarIconDockImpl::SetIcon(const wxIcon& icon, const wxString& WXUNUSED(tooltip))
266 {
267 m_icon.CopyFromIcon(icon);
268 [[NSApplication sharedApplication] setApplicationIconImage:m_icon.GetNSImage()];
269 return true;
270 }
271
272 bool wxTaskBarIconDockImpl::RemoveIcon()
273 {
274 wxDELETE(m_pMenu);
275 m_icon = wxBitmap();
276 [[NSApplication sharedApplication] setApplicationIconImage:nil];
277 return true;
278 }
279
280 bool wxTaskBarIconDockImpl::PopupMenu(wxMenu *WXUNUSED(menu))
281 {
282 wxFAIL_MSG(wxT("You cannot force the Dock icon menu to popup"));
283 return false;
284 }
285
286 @interface wxNSAppController(wxTaskBarIconNSApplicationDelegateCategory)
287 - (NSMenu*)applicationDockMenu:(NSApplication *)sender;
288 @end
289
290 @implementation wxNSAppController(wxTaskBarIconNSApplicationDelegateCategory)
291 - (NSMenu*)applicationDockMenu:(NSApplication *)sender
292 {
293 return wxTaskBarIconDockImpl::OSXGetDockHMenu();
294 }
295 @end
296
297 // ============================================================================
298 // wxTaskBarIconCustomStatusItemImpl
299 // ============================================================================
300
301 @implementation wxOSXStatusItemTarget
302
303 - (void) clickedAction: (id) sender
304 {
305 wxMenu *menu = impl->CreatePopupMenu();
306 if (menu)
307 {
308 impl->PopupMenu(menu);
309 delete menu;
310 }
311 }
312
313 - (void)setImplementation: (wxTaskBarIconCustomStatusItemImpl *) theImplementation
314 {
315 impl = theImplementation;
316 }
317
318 - (wxTaskBarIconCustomStatusItemImpl*) implementation
319 {
320 return impl;
321 }
322
323 @end
324
325
326 wxTaskBarIconCustomStatusItemImpl::wxTaskBarIconCustomStatusItemImpl(wxTaskBarIcon *taskBarIcon)
327 : wxTaskBarIconImpl(taskBarIcon)
328 {
329 m_statusItem = nil;
330 m_target = nil;
331 }
332
333 wxTaskBarIconCustomStatusItemImpl::~wxTaskBarIconCustomStatusItemImpl()
334 {
335 }
336
337 bool wxTaskBarIconCustomStatusItemImpl::SetIcon(const wxIcon& icon, const wxString& WXUNUSED(tooltip))
338 {
339 if(!m_statusItem)
340 {
341 m_statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
342 [m_statusItem retain];
343
344 m_target = [[wxOSXStatusItemTarget alloc] init];
345 [m_target setImplementation:this];
346 [m_statusItem setTarget:m_target];
347 [m_statusItem setAction:@selector(clickedAction:)];
348 [m_statusItem sendActionOn:NSLeftMouseDownMask];
349 }
350
351 m_icon.CopyFromIcon(icon);
352
353 // status item doesn't scale automatically
354
355 int dimension = m_icon.GetHeight();
356 if ( m_icon.GetWidth() > dimension )
357 dimension = m_icon.GetWidth();
358 if ( dimension > 16 )
359 {
360 wxImage img = m_icon.ConvertToImage();
361 int factor = (dimension+15)/16;
362 m_icon = img.ShrinkBy(factor, factor);
363 }
364
365 [m_statusItem setImage:m_icon.GetNSImage()];
366 return true;
367 }
368
369 bool wxTaskBarIconCustomStatusItemImpl::RemoveIcon()
370 {
371 [m_statusItem release];
372 m_statusItem = nil;
373 [m_target release];
374 m_target = nil;
375
376 m_icon = wxBitmap();
377
378 return true;
379 }
380
381 bool wxTaskBarIconCustomStatusItemImpl::PopupMenu(wxMenu *menu)
382 {
383 wxASSERT(menu);
384
385 menu->SetInvokingWindow(m_eventWindow);
386 menu->UpdateUI();
387
388 [m_statusItem popUpStatusItemMenu:(NSMenu*)menu->GetHMenu()];
389
390 menu->SetInvokingWindow(NULL);
391 return true;
392 }
393
394 // ============================================================================
395 // wxTaskBarIconWindow
396 // ============================================================================
397
398 BEGIN_EVENT_TABLE(wxTaskBarIconWindow, wxWindow)
399 EVT_MENU(-1, wxTaskBarIconWindow::OnMenuEvent)
400 EVT_UPDATE_UI(-1, wxTaskBarIconWindow::OnUpdateUIEvent)
401 END_EVENT_TABLE()
402
403 wxTaskBarIconWindow::wxTaskBarIconWindow(wxTaskBarIconImpl *impl)
404 : m_impl(impl)
405 {
406 }
407
408 void wxTaskBarIconWindow::OnMenuEvent(wxCommandEvent& event)
409 {
410 m_impl->GetTaskBarIcon()->ProcessEvent(event);
411 }
412
413 void wxTaskBarIconWindow::OnUpdateUIEvent(wxUpdateUIEvent& event)
414 {
415 m_impl->GetTaskBarIcon()->ProcessEvent(event);
416 }
417
418 #endif //def wxHAS_TASK_BAR_ICON