]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/taskbar.cpp
Lots of fixes/cleanups for OSX taskbar
[wxWidgets.git] / src / mac / carbon / taskbar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: taskbar.cpp
3 // Purpose: wxTaskBarIcon OSX Implementation
4 // Author: Ryan Norton
5 // Modified by:
6 // Created: 09/25/2004
7 // RCS-ID: $Id$
8 // Copyright: (c) 2004 Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #include "wx/defs.h"
15
16 #ifdef wxHAS_TASK_BAR_ICON
17
18 #include "wx/mac/private.h"
19
20 #include "wx/taskbar.h"
21 #include "wx/menu.h"
22 #include "wx/icon.h"
23
24 //
25 //TODO: Implement Apple Software Guidelines - show the top window it it's not shown,
26 //and force it to be unminimized - and all unminimized windows should be brought to
27 //the front
28 //
29 //TODO:
30 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
31
32 pascal OSStatus wxDockEventHandler( EventHandlerCallRef inHandlerCallRef,
33 EventRef inEvent, void* pData)
34 {
35 wxTaskBarIcon*& pTB = (wxTaskBarIcon*&) pData;
36
37 const UInt32 eventClass = GetEventClass(inEvent);
38 const UInt32 eventKind = GetEventKind(inEvent);
39
40 if (eventClass == kEventClassCommand && eventKind == kEventCommandProcess)
41 {
42 //TODO:
43 //TODO: This is a complete copy of
44 //static pascal OSStatus wxMacAppCommandEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
45 //FIND A WAY TO EXTERN THIS AND USE THAT HERE INSTEAD!!
46 //TODO:
47 MenuRef hMenu = MAC_WXHMENU(pTB->GetCurrentMenu()->GetHMenu());
48 OSStatus result = eventNotHandledErr ;
49
50 HICommand command ;
51 OSErr err;
52
53 err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand,
54 NULL, sizeof(HICommand), NULL, &command);
55 wxASSERT(err == noErr);
56
57 MenuItemIndex menuItemIndex;
58 err = GetIndMenuItemWithCommandID(hMenu, command.commandID, 1, NULL, &menuItemIndex);
59 wxASSERT(err == noErr);
60
61
62 MenuCommand id = command.commandID ;
63 wxMenuItem* item = NULL;
64 // for items we don't really control
65 if ( id == kHICommandPreferences )
66 {
67 id = wxApp::s_macPreferencesMenuItemId ;
68
69 wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ;
70 if ( mbar )
71 {
72 wxMenu* menu = NULL ;
73 item = mbar->FindItem( id , &menu ) ;
74 }
75 }
76 else if (id != 0)
77 GetMenuItemRefCon( hMenu , menuItemIndex , (UInt32*) &item ) ;
78
79 if ( item )
80 {
81 if (item->IsCheckable())
82 {
83 item->Check( !item->IsChecked() ) ;
84 }
85
86 item->GetMenu()->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ;
87 result = noErr ;
88 }
89 return result ;
90 }
91
92 wxASSERT(eventClass == kEventClassApplication && eventKind == kEventAppGetDockTileMenu);
93
94 //process the right click event
95 wxTaskBarIconEvent evt(wxEVT_TASKBAR_RIGHT_UP,NULL);
96 pTB->ProcessEvent(evt);
97
98 //create popup menu
99 wxMenu* menu = pTB->DoCreatePopupMenu();
100
101 OSStatus err = noErr;
102
103 if(menu)
104 {
105 //note to self - a MenuRef IS A MenuHandle
106 MenuRef hMenu = MAC_WXHMENU(menu->GetHMenu());
107
108 //When we call SetEventParameter it will decrement
109 //the reference count of the menu - we need to make
110 //sure it stays around in the wxMenu class here
111 RetainMenu(hMenu);
112
113 //set the actual dock menu
114 err = SetEventParameter((EventRef) inEvent, kEventParamMenuRef,
115 typeMenuRef, sizeof(MenuRef),
116 &hMenu);
117 wxASSERT(err == 0);
118 }
119
120 return err;
121 }
122
123 DEFINE_ONE_SHOT_HANDLER_GETTER( wxDockEventHandler );
124
125 wxTaskBarIcon::wxTaskBarIcon(const wxTaskBarIconType& nType)
126 : m_nType(nType), m_pEventHandlerRef(NULL), m_pMenu(NULL), m_iconAdded(false)
127 {
128 //Register the events that will return the dock menu
129 EventTypeSpec tbEventList[] = { { kEventClassCommand, kEventProcessCommand },
130 { kEventClassApplication, kEventAppGetDockTileMenu } };
131
132 #ifdef __WXDEBUG__
133 OSStatus err =
134 #endif
135 InstallApplicationEventHandler(
136 GetwxDockEventHandlerUPP(),
137 GetEventTypeCount(tbEventList), tbEventList,
138 this, (&(EventHandlerRef&)m_pEventHandlerRef));
139
140 wxASSERT(err == noErr);
141 }
142
143 wxTaskBarIcon::~wxTaskBarIcon()
144 {
145 RemoveEventHandler((EventHandlerRef&)m_pEventHandlerRef);
146 }
147
148 wxMenu* wxTaskBarIcon::GetCurrentMenu()
149 {
150 return m_pMenu;
151 }
152
153 wxMenu* wxTaskBarIcon::DoCreatePopupMenu()
154 {
155 if (m_pMenu)
156 delete m_pMenu;
157
158 m_pMenu = CreatePopupMenu();
159
160 if (m_pMenu)
161 m_pMenu->SetEventHandler(this);
162
163 return m_pMenu;
164 }
165
166 // Operations:
167 bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
168 {
169 //TODO: (IT WORKS!) Make work without mask - mayby by using a wxDC?
170
171 wxASSERT(icon.GetMask() != NULL);
172
173 CGImageRef pImage;
174 //create the icon from the bitmap and mask bitmap contained within
175 OSStatus err = CreateCGImageFromPixMaps(
176 GetGWorldPixMap(MAC_WXHBITMAP(icon.GetHBITMAP())),
177 GetGWorldPixMap(MAC_WXHBITMAP(icon.GetMask()->GetMaskBitmap())),
178 &pImage
179 );
180
181 wxASSERT(err == 0);
182
183 err = SetApplicationDockTileImage(pImage);
184
185 wxASSERT(err == 0);
186
187 if (pImage != NULL)
188 CGImageRelease(pImage);
189
190 return m_iconAdded = err == noErr;
191 }
192
193 bool wxTaskBarIcon::RemoveIcon()
194 {
195 OSStatus err = RestoreApplicationDockTileImage();
196 wxASSERT(err == 0);
197
198 return !(m_iconAdded = !(err == noErr));
199 }
200
201 bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
202 {
203 if (m_pMenu)
204 delete m_pMenu;
205
206 m_pMenu = menu;
207
208 wxASSERT(menu);
209 m_pMenu->SetEventHandler(this);
210
211 return SetApplicationDockTileMenu(MAC_WXHMENU(menu->GetHMenu()));
212 }
213
214 #endif //wxHAS_TASK_BAR_ICON