]>
Commit | Line | Data |
---|---|---|
607667fd | 1 | ///////////////////////////////////////////////////////////////////////////// |
e768548a | 2 | // Name: taskbar.cpp |
607667fd RN |
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 | ||
976f9240 RN |
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 | |
cc3388ae | 28 | // |
976f9240 | 29 | //TODO: |
607667fd RN |
30 | IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler) |
31 | ||
e768548a RD |
32 | pascal OSStatus wxDockEventHandler( EventHandlerCallRef inHandlerCallRef, |
33 | EventRef inEvent, void* pData) | |
607667fd RN |
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 | { | |
976f9240 | 42 | //TODO: |
e768548a | 43 | //TODO: This is a complete copy of |
976f9240 RN |
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: | |
e768548a | 47 | MenuRef hMenu = MAC_WXHMENU(pTB->GetCurrentMenu()->GetHMenu()); |
607667fd RN |
48 | OSStatus result = eventNotHandledErr ; |
49 | ||
50 | HICommand command ; | |
51 | OSErr err; | |
52 | ||
e768548a | 53 | err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, |
607667fd RN |
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 | { | |
e768548a RD |
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 ; | |
607667fd RN |
88 | } |
89 | return result ; | |
90 | } | |
91 | ||
92 | wxASSERT(eventClass == kEventClassApplication && eventKind == kEventAppGetDockTileMenu); | |
e768548a RD |
93 | |
94 | //process the right click event | |
95 | wxTaskBarIconEvent evt(wxEVT_TASKBAR_RIGHT_UP,NULL); | |
96 | pTB->ProcessEvent(evt); | |
97 | ||
a45beea1 RN |
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); | |
607667fd | 112 | |
a45beea1 RN |
113 | //set the actual dock menu |
114 | err = SetEventParameter((EventRef) inEvent, kEventParamMenuRef, | |
e768548a RD |
115 | typeMenuRef, sizeof(MenuRef), |
116 | &hMenu); | |
a45beea1 RN |
117 | wxASSERT(err == 0); |
118 | } | |
119 | ||
e768548a | 120 | return err; |
607667fd RN |
121 | } |
122 | ||
123 | DEFINE_ONE_SHOT_HANDLER_GETTER( wxDockEventHandler ); | |
124 | ||
125 | wxTaskBarIcon::wxTaskBarIcon(const wxTaskBarIconType& nType) | |
a45beea1 | 126 | : m_nType(nType), m_pEventHandlerRef(NULL), m_pMenu(NULL), m_iconAdded(false) |
607667fd RN |
127 | { |
128 | //Register the events that will return the dock menu | |
e768548a | 129 | EventTypeSpec tbEventList[] = { { kEventClassCommand, kEventProcessCommand }, |
607667fd | 130 | { kEventClassApplication, kEventAppGetDockTileMenu } }; |
e768548a | 131 | |
cc3388ae | 132 | #ifdef __WXDEBUG__ |
e768548a | 133 | OSStatus err = |
cc3388ae | 134 | #endif |
e768548a | 135 | InstallApplicationEventHandler( |
607667fd RN |
136 | GetwxDockEventHandlerUPP(), |
137 | GetEventTypeCount(tbEventList), tbEventList, | |
e768548a RD |
138 | this, (&(EventHandlerRef&)m_pEventHandlerRef)); |
139 | ||
140 | wxASSERT(err == noErr); | |
607667fd | 141 | } |
cc3388ae | 142 | |
607667fd RN |
143 | wxTaskBarIcon::~wxTaskBarIcon() |
144 | { | |
cc3388ae | 145 | RemoveEventHandler((EventHandlerRef&)m_pEventHandlerRef); |
607667fd RN |
146 | } |
147 | ||
a45beea1 | 148 | wxMenu* wxTaskBarIcon::GetCurrentMenu() |
607667fd | 149 | { |
a45beea1 | 150 | return m_pMenu; |
607667fd RN |
151 | } |
152 | ||
a45beea1 | 153 | wxMenu* wxTaskBarIcon::DoCreatePopupMenu() |
607667fd | 154 | { |
a45beea1 RN |
155 | if (m_pMenu) |
156 | delete m_pMenu; | |
157 | ||
158 | m_pMenu = CreatePopupMenu(); | |
159 | ||
160 | if (m_pMenu) | |
161 | m_pMenu->SetEventHandler(this); | |
162 | ||
607667fd RN |
163 | return m_pMenu; |
164 | } | |
165 | ||
166 | // Operations: | |
167 | bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip) | |
168 | { | |
e768548a RD |
169 | wxMask* mask = icon.GetMask(); |
170 | if (!mask) | |
171 | { | |
172 | // Make a mask with no transparent pixels | |
173 | wxBitmap bmp(icon.GetWidth(), icon.GetHeight()); | |
174 | wxMemoryDC dc; | |
175 | dc.SelectObject(bmp); | |
176 | dc.SetBackground(*wxBLACK_BRUSH); | |
177 | dc.Clear(); | |
178 | dc.SelectObject(wxNullBitmap); | |
179 | mask = new wxMask(bmp, *wxWHITE); | |
180 | } | |
181 | ||
182 | CGImageRef pImage; | |
607667fd | 183 | |
e768548a RD |
184 | //create the icon from the bitmap and mask bitmap contained within |
185 | OSStatus err = CreateCGImageFromPixMaps( | |
186 | GetGWorldPixMap(MAC_WXHBITMAP(icon.GetHBITMAP())), | |
187 | GetGWorldPixMap(MAC_WXHBITMAP(mask->GetMaskBitmap())), | |
188 | &pImage | |
189 | ); | |
190 | ||
191 | wxASSERT(err == 0); | |
cc3388ae | 192 | |
e768548a RD |
193 | err = SetApplicationDockTileImage(pImage); |
194 | ||
195 | wxASSERT(err == 0); | |
739e35e4 RN |
196 | |
197 | if (pImage != NULL) | |
198 | CGImageRelease(pImage); | |
607667fd | 199 | |
e768548a RD |
200 | if (!icon.GetMask()) |
201 | delete mask; | |
202 | ||
203 | return m_iconAdded = err == noErr; | |
607667fd | 204 | } |
e768548a | 205 | |
607667fd RN |
206 | bool wxTaskBarIcon::RemoveIcon() |
207 | { | |
e768548a RD |
208 | OSStatus err = RestoreApplicationDockTileImage(); |
209 | wxASSERT(err == 0); | |
607667fd | 210 | |
e768548a | 211 | return !(m_iconAdded = !(err == noErr)); |
607667fd | 212 | } |
e768548a | 213 | |
607667fd RN |
214 | bool wxTaskBarIcon::PopupMenu(wxMenu *menu) |
215 | { | |
607667fd RN |
216 | if (m_pMenu) |
217 | delete m_pMenu; | |
a45beea1 | 218 | |
607667fd | 219 | m_pMenu = menu; |
a45beea1 RN |
220 | |
221 | wxASSERT(menu); | |
222 | m_pMenu->SetEventHandler(this); | |
223 | ||
224 | return SetApplicationDockTileMenu(MAC_WXHMENU(menu->GetHMenu())); | |
607667fd RN |
225 | } |
226 | ||
f2641bc2 | 227 | #endif //wxHAS_TASK_BAR_ICON |