Support for the macOS platform
[platform/core/uifw/dali-adaptor.git] / dali / internal / system / macos / trigger-event.mm
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #import <Foundation/Foundation.h>
19
20 #include <atomic>
21 #include <string>
22 #include <sstream>
23 #include <type_traits>
24 #include "trigger-event.h"
25
26 namespace
27 {
28 const char *EventName = "Dali::Internal::Adaptor::Triggerevent_";
29 }
30
31 @interface NotificationObserver : NSObject
32
33 -(NotificationObserver *) initTriggerImpl:(Dali::Internal::Adaptor::TriggerEvent::Impl *) impl;
34
35 @end
36
37 namespace Dali::Internal::Adaptor
38 {
39
40 struct TriggerEvent::Impl final
41 {
42   std::unique_ptr<CallbackBase> mCallback;
43   NotificationObserver *mReceiver;
44   NSString *mName;
45   TriggerEventInterface::Options mOptions;
46
47   Impl(CallbackBase *callback, TriggerEventInterface::Options options)
48     : mCallback(callback), mOptions(options)
49   {
50     const auto myId = mNameId.fetch_add(1, std::memory_order_relaxed);
51
52     std::stringstream ss;
53     ss << EventName << myId;
54     mName = [NSString stringWithUTF8String:ss.str().c_str()];
55
56     mReceiver = [[NotificationObserver alloc] initTriggerImpl:this];
57   }
58
59   Impl(Impl &&) = delete;
60   Impl &operator=(Impl &&) = delete;
61
62   ~Impl()
63   {
64     auto *center = [NSNotificationCenter defaultCenter];
65     [center removeObserver:mReceiver];
66   }
67
68   void Trigged()
69   {
70     CallbackBase::Execute( *mCallback );
71   }
72
73 private:
74   // This is incremented each time the class is instatiated to guarantee
75   // an unique notification id
76   static std::atomic_uint64_t mNameId;
77 };
78
79 std::atomic<uint64_t> TriggerEvent::Impl::mNameId{0};
80
81 TriggerEvent::TriggerEvent(CallbackBase *callback, TriggerEventInterface::Options options)
82   : mCallback(callback)
83   , mImpl(std::make_unique<Impl>(MakeCallback(this, &TriggerEvent::Triggered), options))
84 {
85 }
86
87 void TriggerEvent::Trigger()
88 {
89   auto center = [NSDistributedNotificationCenter defaultCenter];
90
91   // Post a notification to the notification center
92   // The run loop will pop the queue and call the notification center
93   [center postNotificationName:mImpl->mName object:nil];
94 }
95
96 void TriggerEvent::Triggered()
97 {
98   CallbackBase::Execute(*mCallback);
99
100   if (mImpl->mOptions == TriggerEventInterface::DELETE_AFTER_TRIGGER)
101   {
102     delete this;
103   }
104 }
105
106 }
107
108 @implementation NotificationObserver
109 {
110   Dali::Internal::Adaptor::TriggerEvent::Impl *mImpl;
111 }
112
113 -(void) ReceiveNotification: (NSNotification *) aNotification
114 {
115   mImpl->Trigged();
116 }
117
118 -(NotificationObserver *) initTriggerImpl:(Dali::Internal::Adaptor::TriggerEvent::Impl *) impl;
119 {
120   self = [super init];
121   if (self)
122   {
123     mImpl = impl;
124     auto center = [NSDistributedNotificationCenter defaultCenter];
125     [center addObserver:self
126                selector:@selector(ReceiveNotification:)
127                    name:impl->mName
128                  object:nil
129      suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
130   }
131
132   return self;
133 }
134
135 @end