// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef PPAPI_CPP_EXTENSIONS_EVENT_BASE_H_ #define PPAPI_CPP_EXTENSIONS_EVENT_BASE_H_ #include "ppapi/c/extensions/dev/ppb_ext_events_dev.h" #include "ppapi/c/pp_macros.h" #include "ppapi/c/pp_stdint.h" #include "ppapi/c/pp_var.h" #include "ppapi/cpp/extensions/from_var_converter.h" #include "ppapi/cpp/instance_handle.h" #include "ppapi/cpp/logging.h" namespace pp { namespace ext { namespace internal { // This file contains base classes for events. Usually you don't need to use // them directly. // // For each event type, there is a corresponding event class derived from // EventBase[0-3]. The event class defines a Listener interface and exposes the // public methods of GenericEventBase. // // Take pp::ext::alarms::OnAlarmEvent_Dev as example, your code to listen to the // event would look like this: // // class MyListener : public pp::ext::alarms::OnAlarmEvent_Dev { // ... // // The parameter is a non-const reference so you could directly modify it // // if necessary. // virtual void OnAlarm(Alarm_Dev& alarm) { // ...handle the event... // } // }; // // MyListener on_alarm_listener; // // The listener is not owned by the event and must outlive it. // pp::ext::alarms::OnAlarmEvent_Dev on_alarm(instance, &on_alarm_listener); // on_alarm.StartListening(); // ... // // It is guaranteed that |on_alarm_listener| won't get called after // // |on_alarm| goes away. So this step is optional. // on_alarm.StopListening(); class GenericEventBase { public: bool StartListening(); void StopListening(); bool IsListening() const { return listener_id_ != 0; } uint32_t listener_id() const { return listener_id_; } protected: GenericEventBase(const InstanceHandle& instance, const PP_Ext_EventListener& pp_listener); ~GenericEventBase(); InstanceHandle instance_; uint32_t listener_id_; const PP_Ext_EventListener pp_listener_; private: // Disallow copying and assignment. GenericEventBase(const GenericEventBase&); GenericEventBase& operator=(const GenericEventBase&); }; // EventBase[0-3] are event base classes which can be instantiated with a // pointer to a PP_Ext_EventListener creation function and the input parameter // types of the listener callback. // // For example, EvenBase1 deals with // the event type defined by the PP_Ext_Alarms_OnAlarm_Dev function pointer. And // it defines a pure virtual method as the listener callback: // virtual void Callback(Alarm_Dev&) = 0; typedef PP_Ext_EventListener (*CreatePPEventListener0)( void (*)(uint32_t, void*), void*); template class EventBase0 : public GenericEventBase { public: explicit EventBase0(const InstanceHandle& instance) : PP_ALLOW_THIS_IN_INITIALIZER_LIST( GenericEventBase(instance, kCreatePPEventListener0(&CallbackThunk, this))) { } virtual ~EventBase0() {} private: virtual void Callback() = 0; static void CallbackThunk(uint32_t listener_id, void* user_data) { EventBase0* event_base = static_cast*>(user_data); PP_DCHECK(listener_id == event_base->listener_id_); // Suppress unused variable warnings. static_cast(listener_id); event_base->Callback(); } // Disallow copying and assignment. EventBase0(const EventBase0&); EventBase0& operator=( const EventBase0&); }; typedef PP_Ext_EventListener (*CreatePPEventListener1)( void (*)(uint32_t, void*, PP_Var), void*); template class EventBase1 : public GenericEventBase { public: explicit EventBase1(const InstanceHandle& instance) : PP_ALLOW_THIS_IN_INITIALIZER_LIST( GenericEventBase(instance, kCreatePPEventListener1(&CallbackThunk, this))) { } virtual ~EventBase1() {} private: virtual void Callback(A&) = 0; static void CallbackThunk(uint32_t listener_id, void* user_data, PP_Var var_a) { EventBase1* event_base = static_cast*>(user_data); PP_DCHECK(listener_id == event_base->listener_id_); // Suppress unused variable warnings. static_cast(listener_id); FromVarConverter a(var_a); event_base->Callback(a.value()); } // Disallow copying and assignment. EventBase1(const EventBase1&); EventBase1& operator=( const EventBase1&); }; typedef PP_Ext_EventListener (*CreatePPEventListener2)( void (*)(uint32_t, void*, PP_Var, PP_Var), void*); template class EventBase2 : public GenericEventBase { public: explicit EventBase2(const InstanceHandle& instance) : PP_ALLOW_THIS_IN_INITIALIZER_LIST( GenericEventBase(instance, kCreatePPEventListener2(&CallbackThunk, this))) { } virtual ~EventBase2() {} private: virtual void Callback(A&, B&) = 0; static void CallbackThunk(uint32_t listener_id, void* user_data, PP_Var var_a, PP_Var var_b) { EventBase2* event_base = static_cast*>(user_data); PP_DCHECK(listener_id == event_base->listener_id_); // Suppress unused variable warnings. static_cast(listener_id); FromVarConverter a(var_a); FromVarConverter b(var_b); event_base->Callback(a.value(), b.value()); } // Disallow copying and assignment. EventBase2(const EventBase2&); EventBase2& operator=( const EventBase2&); }; typedef PP_Ext_EventListener (*CreatePPEventListener3)( void (*)(uint32_t, void*, PP_Var, PP_Var, PP_Var), void*); template class EventBase3 : public GenericEventBase { public: explicit EventBase3(const InstanceHandle& instance) : PP_ALLOW_THIS_IN_INITIALIZER_LIST( GenericEventBase(instance, kCreatePPEventListener3(&CallbackThunk, this))) { } virtual ~EventBase3() {} private: virtual void Callback(A&, B&, C&) = 0; static void CallbackThunk(uint32_t listener_id, void* user_data, PP_Var var_a, PP_Var var_b, PP_Var var_c) { EventBase3* event_base = static_cast*>(user_data); PP_DCHECK(listener_id == event_base->listener_id_); // Suppress unused variable warnings. static_cast(listener_id); FromVarConverter a(var_a); FromVarConverter b(var_b); FromVarConverter c(var_c); event_base->Callback(a.value(), b.value(), c.value()); } // Disallow copying and assignment. EventBase3(const EventBase3&); EventBase3& operator=( const EventBase3&); }; } // namespace internal } // namespace ext } // namespace pp #endif // PPAPI_CPP_EXTENSIONS_EVENT_BASE_H_