2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/system/macos/timer-impl-mac.h>
22 #include "extern-definitions.h"
24 namespace Dali::Internal::Adaptor
27 * Struct to hide away macOS implementation details
31 Impl(TimerMac* parent, uint32_t milliSec)
32 : mTimer(CreateTimer(parent, milliSec))
41 static void TimerProc(CFRunLoopTimerRef timer, void* info);
45 void Reset(TimerMac* parent, uint32_t milliSec);
47 uint32_t GetInterval() const noexcept
49 return CFRunLoopTimerGetInterval(mTimer.get()) * 1000.0;
52 bool IsRunning() const noexcept
54 return CFRunLoopTimerIsValid(mTimer.get());
58 CFRef<CFRunLoopTimerRef> CreateTimer(TimerMac* parent, uint32_t milliSec);
60 CFRef<CFRunLoopTimerRef> mTimer;
63 void TimerMac::Impl::TimerProc(CFRunLoopTimerRef timer, void* info)
65 auto* pTimer = static_cast<TimerMac*>(info);
69 void TimerMac::Impl::Start()
73 auto runLoop = CFRunLoopGetMain();
74 CFRunLoopAddTimer(runLoop, mTimer.get(), kCFRunLoopDefaultMode);
78 void TimerMac::Impl::Stop()
82 CFRunLoopTimerContext context;
83 CFRunLoopTimerGetContext(mTimer.get(), &context);
84 const auto interval = CFRunLoopTimerGetInterval(mTimer.get());
85 CFRunLoopTimerInvalidate(mTimer.get());
87 // After we invalidate the timer, we can't reuse it, so we create
88 // a new timer for case the user calls Start again
89 const auto fireDate = CFAbsoluteTimeGetCurrent() + interval;
90 mTimer.reset(CFRunLoopTimerCreate(
101 void TimerMac::Impl::Reset(TimerMac* parent, uint32_t milliSec)
104 mTimer = CreateTimer(parent, milliSec);
108 CFRef<CFRunLoopTimerRef>
109 TimerMac::Impl::CreateTimer(TimerMac* parent, uint32_t milliSec)
111 const auto interval = static_cast<CFAbsoluteTime>(milliSec) / 1000;
112 const auto fireDate = CFAbsoluteTimeGetCurrent() + interval;
113 CFRunLoopTimerContext context =
121 return MakeRef(CFRunLoopTimerCreate(
131 TimerMacPtr TimerMac::New(uint32_t milliSec)
133 return new TimerMac(milliSec);
136 TimerMac::TimerMac(uint32_t milliSec)
137 : mImpl(new Impl(this, milliSec))
141 TimerMac::~TimerMac()
150 void TimerMac::Start()
155 void TimerMac::Stop()
160 void TimerMac::Pause()
164 void TimerMac::Resume()
168 void TimerMac::SetInterval(uint32_t interval, bool restart)
170 mImpl->Reset(this, interval);
173 uint32_t TimerMac::GetInterval() const
175 return mImpl->GetInterval();
178 bool TimerMac::Tick()
180 // Guard against destruction during signal emission
181 Dali::Timer handle(this);
185 // Override with new signal if used
186 if(!mTickSignal.Empty())
188 retVal = mTickSignal.Emit();
190 // Timer stops if return value is false
197 retVal = true; // continue emission
200 else // no callbacks registered
202 // periodic timer is started but nobody listens, continue
209 bool TimerMac::IsRunning() const
211 return mImpl->IsRunning();
214 } // namespace Dali::Internal::Adaptor