2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 /* CFUserNotification.c
24 Copyright 2000-2002, Apple, Inc. All rights reserved.
25 Responsibility: Doug Davidson
28 #include <CoreFoundation/CFUserNotification.h>
29 #include <CoreFoundation/CFPropertyList.h>
30 #include <CoreFoundation/CFNumber.h>
31 #include <CoreFoundation/CFMachPort.h>
32 #include <CoreFoundation/CFRunLoop.h>
33 #include "CFInternal.h"
36 #define __kCFLogUserNotification 20
37 #define CFUserNotificationLog(alertHeader, alertMessage) CFLog(__kCFLogUserNotification, CFSTR("%@: %@"), alertHeader, alertMessage);
40 kCFUserNotificationCancelFlag
= (1 << 3),
41 kCFUserNotificationUpdateFlag
= (1 << 4)
44 CONST_STRING_DECL(kCFUserNotificationTokenKey
, "Token")
45 CONST_STRING_DECL(kCFUserNotificationTimeoutKey
, "Timeout")
46 CONST_STRING_DECL(kCFUserNotificationFlagsKey
, "Flags")
47 CONST_STRING_DECL(kCFUserNotificationIconPathKey
, "IconPath")
48 CONST_STRING_DECL(kCFUserNotificationSoundPathKey
, "SoundPath")
49 CONST_STRING_DECL(kCFUserNotificationLocalizationPathKey
, "LocalizationPath")
50 CONST_STRING_DECL(kCFUserNotificationAlertSourceKey
, "AlertSource")
51 CONST_STRING_DECL(kCFUserNotificationTextFieldLabelsKey
, "TextFieldTitles")
52 CONST_STRING_DECL(kCFUserNotificationCheckBoxLabelsKey
, "CheckBoxTitles")
53 CONST_STRING_DECL(kCFUserNotificationIconURLKey
, "IconURL")
54 CONST_STRING_DECL(kCFUserNotificationSoundURLKey
, "SoundURL")
55 CONST_STRING_DECL(kCFUserNotificationLocalizationURLKey
, "LocalizationURL")
56 CONST_STRING_DECL(kCFUserNotificationAlertHeaderKey
, "AlertHeader")
57 CONST_STRING_DECL(kCFUserNotificationAlertMessageKey
, "AlertMessage")
58 CONST_STRING_DECL(kCFUserNotificationDefaultButtonTitleKey
, "DefaultButtonTitle")
59 CONST_STRING_DECL(kCFUserNotificationAlternateButtonTitleKey
, "AlternateButtonTitle")
60 CONST_STRING_DECL(kCFUserNotificationOtherButtonTitleKey
, "OtherButtonTitle")
61 CONST_STRING_DECL(kCFUserNotificationProgressIndicatorValueKey
, "ProgressIndicatorValue")
62 CONST_STRING_DECL(kCFUserNotificationSessionIDKey
, "SessionID")
63 CONST_STRING_DECL(kCFUserNotificationPopUpTitlesKey
, "PopUpTitles")
64 CONST_STRING_DECL(kCFUserNotificationTextFieldTitlesKey
, "TextFieldTitles")
65 CONST_STRING_DECL(kCFUserNotificationCheckBoxTitlesKey
, "CheckBoxTitles")
66 CONST_STRING_DECL(kCFUserNotificationTextFieldValuesKey
, "TextFieldValues")
67 CONST_STRING_DECL(kCFUserNotificationPopUpSelectionKey
, "PopUpSelection")
69 static CFTypeID __kCFUserNotificationTypeID
= _kCFRuntimeNotATypeID
;
71 struct __CFUserNotification
{
75 CFTimeInterval _timeout
;
76 CFOptionFlags _requestFlags
;
77 CFOptionFlags _responseFlags
;
78 CFStringRef _sessionID
;
79 CFDictionaryRef _responseDictionary
;
81 CFMachPortRef _machPort
;
83 CFUserNotificationCallBack _callout
;
86 static CFStringRef
__CFUserNotificationCopyDescription(CFTypeRef cf
) {
87 CFMutableStringRef result
;
88 result
= CFStringCreateMutable(CFGetAllocator(cf
), 0);
89 CFStringAppendFormat(result
, NULL
, CFSTR("<CFUserNotification 0x%x>"), (UInt32
)cf
);
98 #include <mach/mach.h>
99 #include <mach/error.h>
100 #include <servers/bootstrap.h>
104 #define MAX_STRING_LENGTH PATH_MAX
105 #define MAX_STRING_COUNT 16
106 #define MAX_PORT_NAME_LENGTH 63
107 #define NOTIFICATION_PORT_NAME "com.apple.UNCUserNotification"
108 #define NOTIFICATION_PORT_NAME_OLD "UNCUserNotification"
109 #define NOTIFICATION_PORT_NAME_SUFFIX ".session."
110 #define MESSAGE_TIMEOUT 100
112 #endif /* __MACH__ */
114 static void __CFUserNotificationDeallocate(CFTypeRef cf
);
116 static const CFRuntimeClass __CFUserNotificationClass
= {
118 "CFUserNotification",
121 __CFUserNotificationDeallocate
,
125 __CFUserNotificationCopyDescription
128 __private_extern__
void __CFUserNotificationInitialize(void) {
129 __kCFUserNotificationTypeID
= _CFRuntimeRegisterClass(&__CFUserNotificationClass
);
132 CFTypeID
CFUserNotificationGetTypeID(void) {
133 return __kCFUserNotificationTypeID
;
136 #if defined(__MACH__)
138 static void __CFUserNotificationDeallocate(CFTypeRef cf
) {
139 CFUserNotificationRef userNotification
= (CFUserNotificationRef
)cf
;
140 if (userNotification
->_machPort
) {
141 CFMachPortInvalidate(userNotification
->_machPort
);
142 CFRelease(userNotification
->_machPort
);
143 } else if (MACH_PORT_NULL
!= userNotification
->_replyPort
) {
144 mach_port_destroy(mach_task_self(), userNotification
->_replyPort
);
146 if (userNotification
->_sessionID
) CFRelease(userNotification
->_sessionID
);
147 if (userNotification
->_responseDictionary
) CFRelease(userNotification
->_responseDictionary
);
150 static void _CFUserNotificationAddToDictionary(const void *key
, const void *value
, void *context
) {
151 if (CFGetTypeID(key
) == CFStringGetTypeID()) CFDictionarySetValue((CFMutableDictionaryRef
)context
, key
, value
);
154 static CFDictionaryRef
_CFUserNotificationModifiedDictionary(CFAllocatorRef allocator
, CFDictionaryRef dictionary
, SInt32 token
, SInt32 timeout
, CFStringRef source
) {
155 CFMutableDictionaryRef md
= CFDictionaryCreateMutable(allocator
, 0, &kCFCopyStringDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
156 CFNumberRef tokenNumber
= CFNumberCreate(allocator
, kCFNumberSInt32Type
, &token
);
157 CFNumberRef timeoutNumber
= CFNumberCreate(allocator
, kCFNumberSInt32Type
, &timeout
);
159 CFStringRef path
= NULL
;
161 if (dictionary
) CFDictionaryApplyFunction(dictionary
, _CFUserNotificationAddToDictionary
, md
);
162 if (source
) CFDictionaryAddValue(md
, kCFUserNotificationAlertSourceKey
, source
);
164 CFDictionaryAddValue(md
, kCFUserNotificationTokenKey
, tokenNumber
);
165 CFRelease(tokenNumber
);
168 CFDictionaryAddValue(md
, kCFUserNotificationTimeoutKey
, timeoutNumber
);
169 CFRelease(timeoutNumber
);
172 url
= CFDictionaryGetValue(md
, kCFUserNotificationIconURLKey
);
173 if (url
&& CFGetTypeID((CFTypeRef
)url
) == CFURLGetTypeID()) {
174 url
= CFURLCopyAbsoluteURL(url
);
175 CFDictionaryRemoveValue(md
, kCFUserNotificationIconURLKey
);
176 path
= CFURLCopyFileSystemPath(url
, kCFURLPOSIXPathStyle
);
177 CFDictionaryAddValue(md
, kCFUserNotificationIconPathKey
, path
);
181 url
= CFDictionaryGetValue(md
, kCFUserNotificationSoundURLKey
);
182 if (url
&& CFGetTypeID((CFTypeRef
)url
) == CFURLGetTypeID()) {
183 url
= CFURLCopyAbsoluteURL(url
);
184 CFDictionaryRemoveValue(md
, kCFUserNotificationSoundURLKey
);
185 path
= CFURLCopyFileSystemPath(url
, kCFURLPOSIXPathStyle
);
186 CFDictionaryAddValue(md
, kCFUserNotificationSoundPathKey
, path
);
190 url
= CFDictionaryGetValue(md
, kCFUserNotificationLocalizationURLKey
);
191 if (url
&& CFGetTypeID((CFTypeRef
)url
) == CFURLGetTypeID()) {
192 url
= CFURLCopyAbsoluteURL(url
);
193 CFDictionaryRemoveValue(md
, kCFUserNotificationLocalizationURLKey
);
194 path
= CFURLCopyFileSystemPath(url
, kCFURLPOSIXPathStyle
);
195 CFDictionaryAddValue(md
, kCFUserNotificationLocalizationPathKey
, path
);
202 static SInt32
_CFUserNotificationSendRequest(CFAllocatorRef allocator
, CFStringRef sessionID
, mach_port_t replyPort
, SInt32 token
, CFTimeInterval timeout
, CFOptionFlags flags
, CFDictionaryRef dictionary
) {
203 CFDictionaryRef modifiedDictionary
= NULL
;
204 SInt32 retval
= ERR_SUCCESS
, itimeout
= (timeout
> 0.0 && timeout
< INT_MAX
) ? (SInt32
)timeout
: 0;
206 mach_msg_base_t
*msg
= NULL
;
207 mach_port_t bootstrapPort
= MACH_PORT_NULL
, serverPort
= MACH_PORT_NULL
;
209 char namebuffer
[MAX_PORT_NAME_LENGTH
+ 1], oldnamebuffer
[MAX_PORT_NAME_LENGTH
+ 1];
212 strcpy(namebuffer
, NOTIFICATION_PORT_NAME
);
213 strcpy(oldnamebuffer
, NOTIFICATION_PORT_NAME_OLD
);
215 strcat(namebuffer
, NOTIFICATION_PORT_NAME_SUFFIX
);
216 namelen
= strlen(namebuffer
);
217 CFStringGetBytes(sessionID
, CFRangeMake(0, CFStringGetLength(sessionID
)), kCFStringEncodingUTF8
, 0, false, namebuffer
+ namelen
, MAX_PORT_NAME_LENGTH
- namelen
, &size
);
218 namebuffer
[namelen
+ size
] = '\0';
220 strcat(oldnamebuffer
, NOTIFICATION_PORT_NAME_SUFFIX
);
221 namelen
= strlen(oldnamebuffer
);
222 CFStringGetBytes(sessionID
, CFRangeMake(0, CFStringGetLength(sessionID
)), kCFStringEncodingUTF8
, 0, false, oldnamebuffer
+ namelen
, MAX_PORT_NAME_LENGTH
- namelen
, &size
);
223 oldnamebuffer
[namelen
+ size
] = '\0';
226 retval
= task_get_bootstrap_port(mach_task_self(), &bootstrapPort
);
227 if (ERR_SUCCESS
== retval
&& MACH_PORT_NULL
!= bootstrapPort
) retval
= bootstrap_look_up(bootstrapPort
, namebuffer
, &serverPort
);
228 if (ERR_SUCCESS
!= retval
|| MACH_PORT_NULL
== serverPort
) retval
= bootstrap_look_up(bootstrapPort
, oldnamebuffer
, &serverPort
);
229 if (ERR_SUCCESS
== retval
&& MACH_PORT_NULL
!= serverPort
) {
230 modifiedDictionary
= _CFUserNotificationModifiedDictionary(allocator
, dictionary
, token
, itimeout
, _CFProcessNameString());
231 if (modifiedDictionary
) {
232 data
= CFPropertyListCreateXMLData(allocator
, modifiedDictionary
);
234 size
= sizeof(mach_msg_base_t
) + ((CFDataGetLength(data
) + 3) & (~0x3));
235 msg
= (mach_msg_base_t
*)CFAllocatorAllocate(allocator
, size
, 0);
236 if (__CFOASafe
) __CFSetLastAllocationEventName(msg
, "CFUserNotification (temp)");
238 memset(msg
, 0, size
);
239 msg
->header
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, MACH_MSG_TYPE_MAKE_SEND_ONCE
);
240 msg
->header
.msgh_size
= size
;
241 msg
->header
.msgh_remote_port
= serverPort
;
242 msg
->header
.msgh_local_port
= replyPort
;
243 msg
->header
.msgh_id
= flags
;
244 msg
->body
.msgh_descriptor_count
= 0;
245 CFDataGetBytes(data
, CFRangeMake(0, CFDataGetLength(data
)), (uint8_t *)msg
+ sizeof(mach_msg_base_t
));
246 //CFShow(CFStringCreateWithBytes(NULL, (UInt8 *)msg + sizeof(mach_msg_base_t), CFDataGetLength(data), kCFStringEncodingUTF8, false));
247 retval
= mach_msg((mach_msg_header_t
*)msg
, MACH_SEND_MSG
|MACH_SEND_TIMEOUT
, size
, 0, MACH_PORT_NULL
, MESSAGE_TIMEOUT
, MACH_PORT_NULL
);
248 CFAllocatorDeallocate(allocator
, msg
);
250 retval
= unix_err(ENOMEM
);
254 retval
= unix_err(ENOMEM
);
256 CFRelease(modifiedDictionary
);
258 retval
= unix_err(ENOMEM
);
264 CFUserNotificationRef
CFUserNotificationCreate(CFAllocatorRef allocator
, CFTimeInterval timeout
, CFOptionFlags flags
, SInt32
*error
, CFDictionaryRef dictionary
) {
265 CFUserNotificationRef userNotification
= NULL
;
266 SInt32 retval
= ERR_SUCCESS
;
267 static uint16_t tokenCounter
= 0;
268 SInt32 token
= ((getpid()<<16) | (tokenCounter
++));
269 CFStringRef sessionID
= (dictionary
? CFDictionaryGetValue(dictionary
, kCFUserNotificationSessionIDKey
) : NULL
);
270 mach_port_t replyPort
= MACH_PORT_NULL
;
272 if (!allocator
) allocator
= __CFGetDefaultAllocator();
274 retval
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &replyPort
);
275 if (ERR_SUCCESS
== retval
&& MACH_PORT_NULL
!= replyPort
) retval
= _CFUserNotificationSendRequest(allocator
, sessionID
, replyPort
, token
, timeout
, flags
, dictionary
);
276 if (ERR_SUCCESS
== retval
) {
277 userNotification
= (CFUserNotificationRef
)_CFRuntimeCreateInstance(allocator
, __kCFUserNotificationTypeID
, sizeof(struct __CFUserNotification
) - sizeof(CFRuntimeBase
), NULL
);
278 if (userNotification
) {
279 userNotification
->_replyPort
= replyPort
;
280 userNotification
->_token
= token
;
281 userNotification
->_timeout
= timeout
;
282 userNotification
->_requestFlags
= flags
;
283 userNotification
->_responseFlags
= 0;
284 userNotification
->_sessionID
= NULL
;
285 userNotification
->_responseDictionary
= NULL
;
286 userNotification
->_machPort
= NULL
;
287 userNotification
->_callout
= NULL
;
288 if (sessionID
) userNotification
->_sessionID
= CFStringCreateCopy(allocator
, sessionID
);
290 retval
= unix_err(ENOMEM
);
293 if (dictionary
) CFUserNotificationLog(CFDictionaryGetValue(dictionary
, kCFUserNotificationAlertHeaderKey
), CFDictionaryGetValue(dictionary
, kCFUserNotificationAlertMessageKey
));
295 if (ERR_SUCCESS
!= retval
&& MACH_PORT_NULL
!= replyPort
) mach_port_destroy(mach_task_self(), replyPort
);
296 if (error
) *error
= retval
;
297 return userNotification
;
300 static void _CFUserNotificationMachPortCallBack(CFMachPortRef port
, void *m
, CFIndex size
, void *info
) {
301 CFUserNotificationRef userNotification
= (CFUserNotificationRef
)info
;
302 mach_msg_base_t
*msg
= (mach_msg_base_t
*)m
;
303 CFOptionFlags responseFlags
= msg
->header
.msgh_id
;
304 if (msg
->header
.msgh_size
> sizeof(mach_msg_base_t
)) {
305 CFDataRef responseData
= CFDataCreate(NULL
, (uint8_t *)msg
+ sizeof(mach_msg_base_t
), msg
->header
.msgh_size
- sizeof(mach_msg_base_t
));
307 userNotification
->_responseDictionary
= CFPropertyListCreateFromXMLData(NULL
, responseData
, kCFPropertyListImmutable
, NULL
);
308 CFRelease(responseData
);
311 CFMachPortInvalidate(userNotification
->_machPort
);
312 CFRelease(userNotification
->_machPort
);
313 userNotification
->_machPort
= NULL
;
314 mach_port_destroy(mach_task_self(), userNotification
->_replyPort
);
315 userNotification
->_replyPort
= MACH_PORT_NULL
;
316 userNotification
->_callout(userNotification
, responseFlags
);
319 SInt32
CFUserNotificationReceiveResponse(CFUserNotificationRef userNotification
, CFTimeInterval timeout
, CFOptionFlags
*responseFlags
) {
320 SInt32 retval
= ERR_SUCCESS
;
321 mach_msg_timeout_t msgtime
= (timeout
> 0.0 && 1000.0 * timeout
< INT_MAX
) ? (mach_msg_timeout_t
)(1000.0 * timeout
) : 0;
322 mach_msg_base_t
*msg
= NULL
;
323 CFIndex size
= MAX_STRING_COUNT
* MAX_STRING_LENGTH
;
324 CFDataRef responseData
;
326 if (userNotification
&& MACH_PORT_NULL
!= userNotification
->_replyPort
) {
327 msg
= (mach_msg_base_t
*)CFAllocatorAllocate(CFGetAllocator(userNotification
), size
, 0);
328 if (__CFOASafe
) __CFSetLastAllocationEventName(msg
, "CFUserNotification (temp)");
330 memset(msg
, 0, size
);
331 msg
->header
.msgh_size
= size
;
333 retval
= mach_msg((mach_msg_header_t
*)msg
, MACH_RCV_MSG
|MACH_RCV_TIMEOUT
, 0, size
, userNotification
->_replyPort
, msgtime
, MACH_PORT_NULL
);
335 retval
= mach_msg((mach_msg_header_t
*)msg
, MACH_RCV_MSG
, 0, size
, userNotification
->_replyPort
, 0, MACH_PORT_NULL
);
337 if (ERR_SUCCESS
== retval
) {
338 if (responseFlags
) *responseFlags
= msg
->header
.msgh_id
;
339 if (msg
->header
.msgh_size
> sizeof(mach_msg_base_t
)) {
340 responseData
= CFDataCreate(NULL
, (uint8_t *)msg
+ sizeof(mach_msg_base_t
), msg
->header
.msgh_size
- sizeof(mach_msg_base_t
));
342 userNotification
->_responseDictionary
= CFPropertyListCreateFromXMLData(NULL
, responseData
, kCFPropertyListImmutable
, NULL
);
343 CFRelease(responseData
);
346 if (userNotification
->_machPort
) {
347 CFMachPortInvalidate(userNotification
->_machPort
);
348 CFRelease(userNotification
->_machPort
);
349 userNotification
->_machPort
= NULL
;
351 mach_port_destroy(mach_task_self(), userNotification
->_replyPort
);
352 userNotification
->_replyPort
= MACH_PORT_NULL
;
354 CFAllocatorDeallocate(CFGetAllocator(userNotification
), msg
);
356 retval
= unix_err(ENOMEM
);
362 CFStringRef
CFUserNotificationGetResponseValue(CFUserNotificationRef userNotification
, CFStringRef key
, CFIndex idx
) {
363 CFStringRef retval
= NULL
;
364 CFTypeRef value
= NULL
;
365 if (userNotification
&& userNotification
->_responseDictionary
) {
366 value
= CFDictionaryGetValue(userNotification
->_responseDictionary
, key
);
367 if (CFGetTypeID(value
) == CFStringGetTypeID()) {
369 retval
= (CFStringRef
)value
;
371 } else if (CFGetTypeID(value
) == CFArrayGetTypeID()) {
372 if (0 <= idx
&& idx
< CFArrayGetCount((CFArrayRef
)value
)) {
373 retval
= (CFStringRef
)CFArrayGetValueAtIndex((CFArrayRef
)value
, idx
);
380 CFDictionaryRef
CFUserNotificationGetResponseDictionary(CFUserNotificationRef userNotification
) {
381 return userNotification
? userNotification
->_responseDictionary
: NULL
;
384 SInt32
CFUserNotificationUpdate(CFUserNotificationRef userNotification
, CFTimeInterval timeout
, CFOptionFlags flags
, CFDictionaryRef dictionary
) {
385 SInt32 retval
= ERR_SUCCESS
;
386 if (userNotification
&& MACH_PORT_NULL
!= userNotification
->_replyPort
) {
387 retval
= _CFUserNotificationSendRequest(CFGetAllocator(userNotification
), userNotification
->_sessionID
, userNotification
->_replyPort
, userNotification
->_token
, timeout
, flags
|kCFUserNotificationUpdateFlag
, dictionary
);
392 SInt32
CFUserNotificationCancel(CFUserNotificationRef userNotification
) {
393 SInt32 retval
= ERR_SUCCESS
;
394 if (userNotification
&& MACH_PORT_NULL
!= userNotification
->_replyPort
) {
395 retval
= _CFUserNotificationSendRequest(CFGetAllocator(userNotification
), userNotification
->_sessionID
, userNotification
->_replyPort
, userNotification
->_token
, 0, kCFUserNotificationCancelFlag
, NULL
);
400 CFRunLoopSourceRef
CFUserNotificationCreateRunLoopSource(CFAllocatorRef allocator
, CFUserNotificationRef userNotification
, CFUserNotificationCallBack callout
, CFIndex order
) {
401 CFRunLoopSourceRef source
= NULL
;
402 if (userNotification
&& callout
&& !userNotification
->_machPort
&& MACH_PORT_NULL
!= userNotification
->_replyPort
) {
403 CFMachPortContext context
= {0, userNotification
, NULL
, NULL
, NULL
};
404 userNotification
->_machPort
= CFMachPortCreateWithPort(CFGetAllocator(userNotification
), (mach_port_t
)userNotification
->_replyPort
, _CFUserNotificationMachPortCallBack
, &context
, false);
406 if (userNotification
&& userNotification
->_machPort
) {
407 source
= CFMachPortCreateRunLoopSource(allocator
, userNotification
->_machPort
, order
);
408 userNotification
->_callout
= callout
;
413 SInt32
CFUserNotificationDisplayNotice(CFTimeInterval timeout
, CFOptionFlags flags
, CFURLRef iconURL
, CFURLRef soundURL
, CFURLRef localizationURL
, CFStringRef alertHeader
, CFStringRef alertMessage
, CFStringRef defaultButtonTitle
) {
414 CFUserNotificationRef userNotification
;
415 SInt32 retval
= ERR_SUCCESS
;
416 CFMutableDictionaryRef dict
= CFDictionaryCreateMutable(NULL
, 0, &kCFCopyStringDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
417 if (iconURL
) CFDictionaryAddValue(dict
, kCFUserNotificationIconURLKey
, iconURL
);
418 if (soundURL
) CFDictionaryAddValue(dict
, kCFUserNotificationSoundURLKey
, soundURL
);
419 if (localizationURL
) CFDictionaryAddValue(dict
, kCFUserNotificationLocalizationURLKey
, localizationURL
);
420 if (alertHeader
) CFDictionaryAddValue(dict
, kCFUserNotificationAlertHeaderKey
, alertHeader
);
421 if (alertMessage
) CFDictionaryAddValue(dict
, kCFUserNotificationAlertMessageKey
, alertMessage
);
422 if (defaultButtonTitle
) CFDictionaryAddValue(dict
, kCFUserNotificationDefaultButtonTitleKey
, defaultButtonTitle
);
423 userNotification
= CFUserNotificationCreate(NULL
, timeout
, flags
, &retval
, dict
);
424 if (userNotification
) CFRelease(userNotification
);
429 CF_EXPORT SInt32
CFUserNotificationDisplayAlert(CFTimeInterval timeout
, CFOptionFlags flags
, CFURLRef iconURL
, CFURLRef soundURL
, CFURLRef localizationURL
, CFStringRef alertHeader
, CFStringRef alertMessage
, CFStringRef defaultButtonTitle
, CFStringRef alternateButtonTitle
, CFStringRef otherButtonTitle
, CFOptionFlags
*responseFlags
) {
430 CFUserNotificationRef userNotification
;
431 SInt32 retval
= ERR_SUCCESS
;
432 CFMutableDictionaryRef dict
= CFDictionaryCreateMutable(NULL
, 0, &kCFCopyStringDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
433 if (iconURL
) CFDictionaryAddValue(dict
, kCFUserNotificationIconURLKey
, iconURL
);
434 if (soundURL
) CFDictionaryAddValue(dict
, kCFUserNotificationSoundURLKey
, soundURL
);
435 if (localizationURL
) CFDictionaryAddValue(dict
, kCFUserNotificationLocalizationURLKey
, localizationURL
);
436 if (alertHeader
) CFDictionaryAddValue(dict
, kCFUserNotificationAlertHeaderKey
, alertHeader
);
437 if (alertMessage
) CFDictionaryAddValue(dict
, kCFUserNotificationAlertMessageKey
, alertMessage
);
438 if (defaultButtonTitle
) CFDictionaryAddValue(dict
, kCFUserNotificationDefaultButtonTitleKey
, defaultButtonTitle
);
439 if (alternateButtonTitle
) CFDictionaryAddValue(dict
, kCFUserNotificationAlternateButtonTitleKey
, alternateButtonTitle
);
440 if (otherButtonTitle
) CFDictionaryAddValue(dict
, kCFUserNotificationOtherButtonTitleKey
, otherButtonTitle
);
441 userNotification
= CFUserNotificationCreate(NULL
, timeout
, flags
, &retval
, dict
);
442 if (userNotification
) {
443 retval
= CFUserNotificationReceiveResponse(userNotification
, timeout
, responseFlags
);
444 if (MACH_RCV_TIMED_OUT
== retval
) {
445 retval
= CFUserNotificationCancel(userNotification
);
446 if (responseFlags
) *responseFlags
= kCFUserNotificationCancelResponse
;
448 CFRelease(userNotification
);
456 #warning CFUserNotification functions not fully implemented
458 void __CFUserNotificationDeallocate(CFTypeRef cf
) {
461 CFUserNotificationRef
CFUserNotificationCreate(CFAllocatorRef allocator
, CFTimeInterval timeout
, CFOptionFlags flags
, SInt32
*error
, CFDictionaryRef dictionary
) {
462 CFUserNotificationLog(CFDictionaryGetValue(dictionary
, kCFUserNotificationAlertHeaderKey
), CFDictionaryGetValue(dictionary
, kCFUserNotificationAlertMessageKey
));
466 SInt32
CFUserNotificationReceiveResponse(CFUserNotificationRef userNotification
, CFTimeInterval timeout
, CFOptionFlags
*responseFlags
) {
470 CFDictionaryRef
CFUserNotificationCopyResponseDictionary(CFUserNotificationRef userNotification
) {
474 SInt32
CFUserNotificationUpdate(CFUserNotificationRef userNotification
, CFTimeInterval timeout
, CFOptionFlags flags
, CFDictionaryRef dictionary
) {
478 SInt32
CFUserNotificationCancel(CFUserNotificationRef userNotification
) {
482 CFRunLoopSourceRef
CFUserNotificationCreateRunLoopSource(CFAllocatorRef allocator
, CFUserNotificationRef userNotification
, CFUserNotificationCallBack callout
, CFIndex order
) {
486 SInt32
CFUserNotificationDisplayNotice(CFTimeInterval timeout
, CFOptionFlags flags
, CFURLRef iconURL
, CFURLRef soundURL
, CFURLRef localizationURL
, CFStringRef alertHeader
, CFStringRef alertMessage
, CFStringRef defaultButtonTitle
) {
487 CFUserNotificationLog(alertHeader
, alertMessage
);
491 SInt32
CFUserNotificationDisplayAlert(CFTimeInterval timeout
, CFOptionFlags flags
, CFURLRef iconURL
, CFURLRef soundURL
, CFURLRef localizationURL
, CFStringRef alertHeader
, CFStringRef alertMessage
, CFStringRef defaultButtonTitle
, CFStringRef alternateButtonTitle
, CFStringRef otherButtonTitle
, CFOptionFlags
*responseFlags
) {
492 CFUserNotificationLog(alertHeader
, alertMessage
);
496 #endif /* __MACH__ */
498 #undef __kCFLogUserNotification
499 #undef CFUserNotificationLog
500 #undef MAX_STRING_LENGTH
501 #undef MAX_STRING_COUNT
502 #undef NOTIFICATION_PORT_NAME
503 #undef NOTIFICATION_PORT_NAME_OLD
504 #undef MESSAGE_TIMEOUT