macintosh_events.hpp
Go to the documentation of this file.
00001 /* 00002 Copyright 2005-2007 Adobe Systems Incorporated 00003 Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt 00004 or a copy at http://stlab.adobe.com/licenses.html) 00005 */ 00006 00007 /**************************************************************************************************/ 00008 00009 #ifndef ADOBE_MACINTOSH_EVENTS_HPP 00010 #define ADOBE_MACINTOSH_EVENTS_HPP 00011 00012 /**************************************************************************************************/ 00013 00014 #if __LP64__ 00015 #error "Carbon is not supported in 64 bit environments." 00016 #else 00017 00018 /**************************************************************************************************/ 00019 00020 #include <adobe/algorithm/lower_bound.hpp> 00021 #include <adobe/algorithm/sort.hpp> 00022 #include <adobe/algorithm/unique.hpp> 00023 #include <adobe/future/macintosh_error.hpp> 00024 #include <adobe/macintosh_carbon_safe.hpp> 00025 #include <adobe/macintosh_memory.hpp> 00026 00027 #include <boost/noncopyable.hpp> 00028 #include <boost/static_assert.hpp> 00029 #include <boost/type_traits.hpp> 00030 00031 #include <iterator> 00032 #include <vector> 00033 00034 /**************************************************************************************************/ 00035 00036 inline bool operator == (const ::EventTypeSpec& x, const ::EventTypeSpec& y) 00037 { return x.eventClass == y.eventClass && x.eventKind == y.eventKind; } 00038 00039 inline bool operator < (const ::EventTypeSpec& x, const ::EventTypeSpec& y) 00040 { return x.eventClass < y.eventClass || x.eventClass == y.eventClass && x.eventKind < y.eventKind; } 00041 00042 /**************************************************************************************************/ 00043 00044 namespace adobe { 00045 00046 /**************************************************************************************************/ 00047 00048 template <typename T> struct event_param_type; 00049 00050 #define ADOBE_EVENT_PARAM_TYPE_HELPER(type, event_type) \ 00051 template <> struct event_param_type< type > { static const ::EventParamType value = event_type; } 00052 00053 ADOBE_EVENT_PARAM_TYPE_HELPER(::CFArrayRef, typeCFArrayRef); 00054 ADOBE_EVENT_PARAM_TYPE_HELPER(::CFDictionaryRef, typeCFDictionaryRef); 00055 ADOBE_EVENT_PARAM_TYPE_HELPER(::CFMutableArrayRef, typeCFMutableArrayRef); 00056 ADOBE_EVENT_PARAM_TYPE_HELPER(::CFMutableDictionaryRef, typeCFMutableDictionaryRef); 00057 ADOBE_EVENT_PARAM_TYPE_HELPER(::CFMutableStringRef, typeCFMutableStringRef); 00058 ADOBE_EVENT_PARAM_TYPE_HELPER(::CFStringRef, typeCFStringRef); 00059 ADOBE_EVENT_PARAM_TYPE_HELPER(::CFTypeRef, typeCFTypeRef); 00060 ADOBE_EVENT_PARAM_TYPE_HELPER(::ControlPartCode, typeControlPartCode); 00061 ADOBE_EVENT_PARAM_TYPE_HELPER(::DragRef, typeDragRef); 00062 ADOBE_EVENT_PARAM_TYPE_HELPER(::EventMouseWheelAxis, typeMouseWheelAxis); 00063 ADOBE_EVENT_PARAM_TYPE_HELPER(::EventTargetRef, typeEventTargetRef); 00064 ADOBE_EVENT_PARAM_TYPE_HELPER(::HICommand, typeHICommand); 00065 ADOBE_EVENT_PARAM_TYPE_HELPER(::HIPoint, typeHIPoint); 00066 ADOBE_EVENT_PARAM_TYPE_HELPER(::SInt32, typeLongInteger); 00067 ADOBE_EVENT_PARAM_TYPE_HELPER(::TabletPointRec, typeTabletPointRec); 00068 ADOBE_EVENT_PARAM_TYPE_HELPER(::TabletProximityRec, typeTabletProximityRec); 00069 ADOBE_EVENT_PARAM_TYPE_HELPER(::UInt32, typeUInt32); 00070 ADOBE_EVENT_PARAM_TYPE_HELPER(::WindowRef, typeWindowRef); 00071 ADOBE_EVENT_PARAM_TYPE_HELPER(bool, typeBoolean); 00072 00073 #undef ADOBE_EVENT_PARAM_TYPE_HELPER 00074 00075 /**************************************************************************************************/ 00076 00077 template < ::EventParamName name, typename T > 00078 bool get_event_parameter(::EventRef the_event, 00079 T& value, 00080 ::EventParamType type = event_param_type<T>::value) 00081 { 00082 ::EventParamType actual_type; 00083 ::UInt32 actual_size; 00084 ::OSStatus err(::GetEventParameter(the_event, 00085 name, 00086 type, 00087 &actual_type, 00088 sizeof(T), 00089 &actual_size, 00090 &value)); 00091 00092 return err == noErr && actual_type == type && actual_size == sizeof(T); 00093 } 00094 00095 /**************************************************************************************************/ 00096 00097 template < ::EventParamName name, typename T > 00098 bool set_event_parameter(::EventRef the_event, 00099 const T& value, 00100 ::EventParamType type = event_param_type<T>::value) 00101 { 00102 ::OSStatus err(::SetEventParameter(the_event, 00103 name, 00104 type, 00105 sizeof(T), 00106 &value)); 00107 00108 return err == noErr; 00109 } 00110 00111 /**************************************************************************************************/ 00112 00113 template <typename Target> 00114 ::EventTargetRef get_event_target(Target target); 00115 00116 #define ADOBE_GET_EVENT_TARGET_HELPER(type, proc) \ 00117 template <> inline ::EventTargetRef get_event_target<>(type target) { return proc(target); } 00118 00119 ADOBE_GET_EVENT_TARGET_HELPER(::WindowRef, ::GetWindowEventTarget) 00120 ADOBE_GET_EVENT_TARGET_HELPER(::ControlRef, ::GetControlEventTarget) 00121 ADOBE_GET_EVENT_TARGET_HELPER(::MenuRef, ::GetMenuEventTarget) 00122 ADOBE_GET_EVENT_TARGET_HELPER(::EventTargetRef, ::EventTargetRef) 00123 00124 #undef ADOBE_GET_EVENT_TARGET_HELPER 00125 00126 /**************************************************************************************************/ 00127 00128 class event_handler_t : boost::noncopyable 00129 { 00130 public: 00131 typedef boost::function< ::OSStatus (::EventHandlerCallRef, ::EventRef) > monitor_proc_t; 00132 00133 event_handler_t(); 00134 00135 template <typename Target> 00136 void install(Target target) 00137 { install(get_event_target(target)); } 00138 00139 void install(::EventTargetRef target); 00140 00141 void uninstall(); 00142 00143 bool is_installed() const 00144 { return ref_m.get() != 0; } 00145 00146 void insert(const ::EventTypeSpec& event_spec); 00147 00148 void insert(::UInt32 event_class, ::UInt32 event_kind) 00149 { ::EventTypeSpec event = { event_class, event_kind }; insert(event); } 00150 00151 template <typename ForwardIterator> 00152 void insert(const ForwardIterator first, const ForwardIterator last) 00153 { 00154 typedef typename std::iterator_traits<ForwardIterator>::value_type value_type; 00155 typedef typename std::iterator_traits<ForwardIterator>::iterator_category iterator_category; 00156 00157 BOOST_STATIC_ASSERT((boost::is_convertible<value_type, ::EventTypeSpec>::value)); 00158 00159 insert(first, last, iterator_category()); 00160 } 00161 00162 void erase(const ::EventTypeSpec& event_spec); 00163 00164 void erase(::UInt32 event_class, ::UInt32 event_kind) 00165 { ::EventTypeSpec event = { event_class, event_kind }; erase(event); } 00166 00167 template <typename ForwardIterator> 00168 void erase(const ForwardIterator first, const ForwardIterator last) 00169 { 00170 typedef typename std::iterator_traits<ForwardIterator>::value_type value_type; 00171 typedef typename std::iterator_traits<ForwardIterator>::iterator_category iterator_category; 00172 00173 BOOST_STATIC_ASSERT((boost::is_convertible<value_type, ::EventTypeSpec>::value)); 00174 00175 erase(first, last, iterator_category()); 00176 } 00177 00178 monitor_proc_t monitor_proc_m; // no need to be private 00179 00180 private: 00181 template <typename ForwardIterator> 00182 void insert(const ForwardIterator first, 00183 const ForwardIterator last, 00184 std::forward_iterator_tag); 00185 00186 template <typename ForwardIterator> 00187 void insert(const ForwardIterator first, 00188 const ForwardIterator last, 00189 std::random_access_iterator_tag); 00190 00191 template <typename ForwardIterator> 00192 void erase(const ForwardIterator first, 00193 const ForwardIterator last, 00194 std::forward_iterator_tag); 00195 00196 template <typename ForwardIterator> 00197 void erase(const ForwardIterator first, 00198 const ForwardIterator last, 00199 std::random_access_iterator_tag); 00200 00201 typedef adobe::auto_resource< ::EventHandlerRef > auto_ref_t; 00202 typedef adobe::auto_resource< ::EventHandlerUPP > auto_upp_t; 00203 typedef std::vector< ::EventTypeSpec > event_type_set_t; 00204 00205 auto_ref_t ref_m; 00206 auto_upp_t upp_m; 00207 event_type_set_t event_type_set_m; 00208 }; 00209 00210 /**************************************************************************************************/ 00211 00212 template <typename ForwardIterator> 00213 void event_handler_t::insert(const ForwardIterator first, 00214 const ForwardIterator last, 00215 std::forward_iterator_tag) 00216 { 00217 typedef void (event_handler_t::*proc_type)(const ::EventTypeSpec&); 00218 00219 proc_type proc(&event_handler_t::insert); 00220 00221 std::for_each(first, last, boost::bind(proc, boost::ref(*this), _1)); 00222 } 00223 00224 /**************************************************************************************************/ 00225 00226 template <typename ForwardIterator> 00227 void event_handler_t::insert(const ForwardIterator first, 00228 const ForwardIterator last, 00229 std::random_access_iterator_tag) 00230 { 00231 std::size_t n(std::distance(first, last)); 00232 00233 // this will fill the event_type_set_m vector with new 00234 // events without duplicating ones already present. 00235 event_type_set_m.insert(event_type_set_m.end(), first, last); 00236 adobe::sort(event_type_set_m); 00237 event_type_set_m.erase(adobe::unique(event_type_set_m), event_type_set_m.end()); 00238 00239 if (!is_installed()) 00240 return; 00241 00242 // now add the event set to the handler. 00243 ::ADOBE_REQUIRE_STATUS(::AddEventTypesToHandler(ref_m.get(), n, first)); 00244 } 00245 00246 /**************************************************************************************************/ 00247 00248 template <typename ForwardIterator> 00249 void event_handler_t::erase(const ForwardIterator first, 00250 const ForwardIterator last, 00251 std::forward_iterator_tag) 00252 { 00253 typedef void (event_handler_t::*proc_type)(const ::EventTypeSpec&); 00254 00255 proc_type proc(&event_handler_t::erase); 00256 00257 std::for_each(first, last, boost::bind(proc, boost::ref(*this), _1)); 00258 } 00259 00260 /**************************************************************************************************/ 00261 00262 template <typename ForwardIterator> 00263 void event_handler_t::erase(const ForwardIterator first, 00264 const ForwardIterator last, 00265 std::random_access_iterator_tag) 00266 { 00267 std::size_t n(std::distance(first, last)); 00268 00269 adobe::sort(event_type_set_m); 00270 00271 for (ForwardIterator iter(first); iter != last; ++iter) 00272 { 00273 ForwardIterator found(adobe::lower_bound(event_type_set_m, *iter)); 00274 00275 if (found != event_type_set_m.end() && *found == *iter) 00276 event_type_set_m.erase(found); 00277 } 00278 00279 if (!is_installed()) 00280 return; 00281 00282 // now remove the event set from the handler. 00283 ::ADOBE_REQUIRE_STATUS(::RemoveEventTypesFromHandler(ref_m.get(), n, first)); 00284 } 00285 00286 /**************************************************************************************************/ 00287 00288 } // namespace adobe 00289 00290 /**************************************************************************************************/ 00291 00292 #endif 00293 00294 /**************************************************************************************************/ 00295 00296 #endif 00297 00298 /**************************************************************************************************/ |