Backends: OSX, Metal: Tweaks. Use preferred method of obtaining a timestamp. (#4821)

+ Rename ImGuiFocusObserver. Docking branch will use it for more than focus.
diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm
index 744f590..6d369bf 100644
--- a/backends/imgui_impl_metal.mm
+++ b/backends/imgui_impl_metal.mm
@@ -27,17 +27,15 @@
 
 #include "imgui.h"
 #include "imgui_impl_metal.h"
-
+#import <time.h>
 #import <Metal/Metal.h>
-// #import <QuartzCore/CAMetalLayer.h> // Not supported in XCode 9.2. Maybe a macro to detect the SDK version can be used (something like #if MACOS_SDK >= 10.13 ...)
-#import <simd/simd.h>
 
 #pragma mark - Support classes
 
 // A wrapper around a MTLBuffer object that knows the last time it was reused
 @interface MetalBuffer : NSObject
 @property (nonatomic, strong) id<MTLBuffer> buffer;
-@property (nonatomic, assign) NSTimeInterval lastReuseTime;
+@property (nonatomic, assign) double lastReuseTime;
 - (instancetype)initWithBuffer:(id<MTLBuffer>)buffer;
 @end
 
@@ -61,7 +59,7 @@
 @property (nonatomic, strong) NSMutableDictionary *renderPipelineStateCache; // pipeline cache; keyed on framebuffer descriptors
 @property (nonatomic, strong, nullable) id<MTLTexture> fontTexture;
 @property (nonatomic, strong) NSMutableArray<MetalBuffer *> *bufferCache;
-@property (nonatomic, assign) NSTimeInterval lastBufferCachePurge;
+@property (nonatomic, assign) double lastBufferCachePurge;
 - (void)makeDeviceObjectsWithDevice:(id<MTLDevice>)device;
 - (void)makeFontTextureWithDevice:(id<MTLDevice>)device;
 - (MetalBuffer *)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device;
@@ -90,6 +88,8 @@
 static ImGui_ImplMetal_Data*     ImGui_ImplMetal_GetBackendData()     { return ImGui::GetCurrentContext() ? (ImGui_ImplMetal_Data*)ImGui::GetIO().BackendRendererUserData : NULL; }
 static void                      ImGui_ImplMetal_DestroyBackendData() { IM_DELETE(ImGui_ImplMetal_GetBackendData()); }
 
+static inline CFTimeInterval     GetMachAbsoluteTimeInSeconds()       { return static_cast<CFTimeInterval>(static_cast<double>(clock_gettime_nsec_np(CLOCK_UPTIME_RAW)) / 1e9); }
+
 #ifdef IMGUI_IMPL_METAL_CPP
 
 #pragma mark - Dear ImGui Metal C++ Backend API
@@ -207,7 +207,7 @@
     if ((self = [super init]))
     {
         _buffer = buffer;
-        _lastReuseTime = [NSDate date].timeIntervalSince1970;
+        _lastReuseTime = GetMachAbsoluteTimeInSeconds();
     }
     return self;
 }
@@ -269,7 +269,7 @@
     {
         _renderPipelineStateCache = [NSMutableDictionary dictionary];
         _bufferCache = [NSMutableArray array];
-        _lastBufferCachePurge = [NSDate date].timeIntervalSince1970;
+        _lastBufferCachePurge = GetMachAbsoluteTimeInSeconds();
     }
     return self;
 }
@@ -309,7 +309,7 @@
 
 - (MetalBuffer *)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device
 {
-    NSTimeInterval now = [NSDate date].timeIntervalSince1970;
+    uint64_t now = GetMachAbsoluteTimeInSeconds();
 
     // Purge old buffers that haven't been useful for a while
     if (now - self.lastBufferCachePurge > 1.0)
diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm
index e733541..59c34a1 100644
--- a/backends/imgui_impl_osx.mm
+++ b/backends/imgui_impl_osx.mm
@@ -17,9 +17,9 @@
 #import "imgui.h"
 #import "imgui_impl_osx.h"
 #import <Cocoa/Cocoa.h>
-#import <mach/mach_time.h>
 #import <Carbon/Carbon.h>
 #import <GameController/GameController.h>
+#import <time.h>
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
@@ -54,17 +54,16 @@
 #define APPLE_HAS_CONTROLLER     (__IPHONE_OS_VERSION_MIN_REQUIRED >= 140000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 110000 || __TV_OS_VERSION_MIN_REQUIRED >= 140000)
 #define APPLE_HAS_THUMBSTICKS    (__IPHONE_OS_VERSION_MIN_REQUIRED >= 120100 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101401 || __TV_OS_VERSION_MIN_REQUIRED >= 120100)
 
-@class ImFocusObserver;
+@class ImGuiObserver;
 @class KeyEventResponder;
 
 // Data
 struct ImGui_ImplOSX_Data
 {
-    double                  HostClockPeriod;
-    double                  Time;
+    CFTimeInterval          Time;
     NSCursor*               MouseCursors[ImGuiMouseCursor_COUNT];
     bool                    MouseCursorHidden;
-    ImFocusObserver*        FocusObserver;
+    ImGuiObserver*          Observer;
     KeyEventResponder*      KeyEventResponder;
     NSTextInputContext*     InputContext;
 
@@ -75,6 +74,8 @@
 static ImGui_ImplOSX_Data*  ImGui_ImplOSX_GetBackendData()     { return (ImGui_ImplOSX_Data*)ImGui::GetIO().BackendPlatformUserData; }
 static void                 ImGui_ImplOSX_DestroyBackendData() { IM_DELETE(ImGui_ImplOSX_GetBackendData()); }
 
+static inline CFTimeInterval GetMachAbsoluteTimeInSeconds()    { return static_cast<CFTimeInterval>(static_cast<double>(clock_gettime_nsec_np(CLOCK_UPTIME_RAW)) / 1e9); }
+
 // Undocumented methods for creating cursors.
 @interface NSCursor()
 + (id)_windowResizeNorthWestSouthEastCursor;
@@ -83,20 +84,6 @@
 + (id)_windowResizeEastWestCursor;
 @end
 
-static void InitHostClockPeriod()
-{
-    ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
-    struct mach_timebase_info info;
-    mach_timebase_info(&info);
-    bd->HostClockPeriod = 1e-9 * ((double)info.denom / (double)info.numer); // Period is the reciprocal of frequency.
-}
-
-static double GetMachAbsoluteTimeInSeconds()
-{
-    ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
-    return (double)mach_absolute_time() * bd->HostClockPeriod;
-}
-
 /**
  KeyEventResponder implements the NSTextInputClient protocol as is required by the macOS text input manager.
 
@@ -225,14 +212,14 @@
 
 @end
 
-@interface ImFocusObserver : NSObject
+@interface ImGuiObserver : NSObject
 
 - (void)onApplicationBecomeActive:(NSNotification*)aNotification;
 - (void)onApplicationBecomeInactive:(NSNotification*)aNotification;
 
 @end
 
-@implementation ImFocusObserver
+@implementation ImGuiObserver
 
 - (void)onApplicationBecomeActive:(NSNotification*)aNotification
 {
@@ -385,6 +372,8 @@
     //io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can set io.MouseHoveredViewport correctly (optional, not easy)
     io.BackendPlatformName = "imgui_impl_osx";
 
+    bd->Observer = [ImGuiObserver new];
+
     // Load cursors. Some of them are undocumented.
     bd->MouseCursorHidden = false;
     bd->MouseCursors[ImGuiMouseCursor_Arrow] = [NSCursor arrowCursor];
@@ -426,12 +415,11 @@
         return s_clipboard.Data;
     };
 
-    bd->FocusObserver = [[ImFocusObserver alloc] init];
-    [[NSNotificationCenter defaultCenter] addObserver:bd->FocusObserver
+    [[NSNotificationCenter defaultCenter] addObserver:bd->Observer
                                              selector:@selector(onApplicationBecomeActive:)
                                                  name:NSApplicationDidBecomeActiveNotification
                                                object:nil];
-    [[NSNotificationCenter defaultCenter] addObserver:bd->FocusObserver
+    [[NSNotificationCenter defaultCenter] addObserver:bd->Observer
                                              selector:@selector(onApplicationBecomeInactive:)
                                                  name:NSApplicationDidResignActiveNotification
                                                object:nil];
@@ -473,7 +461,7 @@
 void ImGui_ImplOSX_Shutdown()
 {
     ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
-    bd->FocusObserver = NULL;
+    bd->Observer = NULL;
     ImGui_ImplOSX_DestroyBackendData();
 }
 
@@ -592,10 +580,8 @@
 
     // Setup time step
     if (bd->Time == 0.0)
-    {
-        InitHostClockPeriod();
         bd->Time = GetMachAbsoluteTimeInSeconds();
-    }
+
     double current_time = GetMachAbsoluteTimeInSeconds();
     io.DeltaTime = (float)(current_time - bd->Time);
     bd->Time = current_time;
diff --git a/examples/example_apple_metal/main.mm b/examples/example_apple_metal/main.mm
index d92fc6b..db1ef3a 100644
--- a/examples/example_apple_metal/main.mm
+++ b/examples/example_apple_metal/main.mm
@@ -125,8 +125,6 @@
 #endif
     io.DisplayFramebufferScale = ImVec2(framebufferScale, framebufferScale);
 
-    io.DeltaTime = 1 / float(view.preferredFramesPerSecond ?: 60);
-
     id<MTLCommandBuffer> commandBuffer = [self.commandQueue commandBuffer];
 
     MTLRenderPassDescriptor* renderPassDescriptor = view.currentRenderPassDescriptor;