Skip to content

Commit

Permalink
macOS: implement the directory watcher
Browse files Browse the repository at this point in the history
  • Loading branch information
eyelash committed Feb 19, 2024
1 parent d6b676a commit f8d84ce
Showing 1 changed file with 52 additions and 7 deletions.
59 changes: 52 additions & 7 deletions gral_macos.m
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ static int utf16_index_to_utf8(CFStringRef string, NSUInteger index) {
return i8;
}

@interface CallbackObject: NSObject {
@public
void (*callback)(void *user_data);
void *user_data;
}
@end
@implementation CallbackObject
- (void)invoke:(id)object {
callback(user_data);
}
@end

/*================
APPLICATION
Expand Down Expand Up @@ -125,7 +136,7 @@ void gral_image_delete(struct gral_image *image) {
}

struct gral_font *gral_font_create(struct gral_window *window, char const *name, float size) {
CFStringRef string = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
CFStringRef string = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingUTF8);
CTFontRef font = CTFontCreateWithName(string, size, NULL);
CFRelease(string);
return (struct gral_font *)font;
Expand All @@ -149,7 +160,7 @@ void gral_font_get_metrics(struct gral_window *window, struct gral_font *font, f
}

struct gral_text *gral_text_create(struct gral_window *window, char const *text, struct gral_font *font) {
CFStringRef string = CFStringCreateWithCString(NULL, text, kCFStringEncodingUTF8);
CFStringRef string = CFStringCreateWithCString(kCFAllocatorDefault, text, kCFStringEncodingUTF8);
CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(NULL, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(attributes, kCTFontAttributeName, font);
CFAttributedStringRef attributed_string = CFAttributedStringCreate(NULL, string, attributes);
Expand Down Expand Up @@ -679,7 +690,7 @@ - (void)invoke:(NSTimer *)timer {
}
@end
struct gral_timer *gral_window_create_timer(struct gral_window *window, int milliseconds, void (*callback)(void *user_data), void *user_data) {
TimerCallbackObject *callback_object = [[TimerCallbackObject alloc] init];
CallbackObject *callback_object = [[CallbackObject alloc] init];
callback_object->callback = callback;
callback_object->user_data = user_data;
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:milliseconds/1000.0 target:callback_object selector:@selector(invoke:) userInfo:nil repeats:YES];
Expand All @@ -703,7 +714,7 @@ - (void)invoke:(id)object {
}
@end
void gral_window_run_on_main_thread(struct gral_window *window, void (*callback)(void *user_data), void *user_data) {
MainThreadCallbackObject *callback_object = [[MainThreadCallbackObject alloc] init];
CallbackObject *callback_object = [[CallbackObject alloc] init];
callback_object->callback = callback;
callback_object->user_data = user_data;
[callback_object performSelectorOnMainThread:@selector(invoke:) withObject:nil waitUntilDone:NO];
Expand Down Expand Up @@ -795,13 +806,47 @@ void gral_directory_remove(char const *path) {
rmdir(path);
}

static void event_stream_callback(ConstFSEventStreamRef streamRef, void *info, size_t numEvents, void *eventPaths, FSEventStreamEventFlags const *eventFlags, FSEventStreamEventId const *eventIds) {
CallbackObject *callback_object = info;
for (size_t i = 0; i < numEvents; i++) {
callback_object->callback(callback_object->user_data);
}
}
static void const *callback_object_retain(void const *info) {
CallbackObject *callback_object = info;
return info;
}
static void callback_object_release(void const *info) {
CallbackObject *callback_object = info;
}

struct gral_directory_watcher *gral_directory_watch(char const *path, void (*callback)(void *user_data), void *user_data) {
// TODO: implement
return NULL;
CallbackObject *callback_object = [[CallbackObject alloc] init];
callback_object->callback = callback;
callback_object->user_data = user_data;
FSEventStreamContext context;
context.copyDescription = NULL;
context.info = callback_object;
context.release = NULL;
context.retain = NULL;
context.version = 0;
CFStringRef string = CFStringCreateWithCString(kCFAllocatorDefault, path, kCFStringEncodingUTF8);
CFArrayRef paths = CFArrayCreate(kCFAllocatorDefault, (void const **)&string, 1, &kCFTypeArrayCallBacks);
CFRelease(string);
FSEventStreamRef event_stream = FSEventStreamCreate(kCFAllocatorDefault, event_stream_callback, &context, paths, kFSEventStreamEventIdSinceNow, 0.0, kFSEventStreamCreateFlagNone);
CFRelease(paths);
[callback_object release];
FSEventStreamScheduleWithRunLoop(event_stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
FSEventStreamStart(event_stream);
return (struct gral_directory_watcher *)event_stream;
}

void gral_directory_watcher_delete(struct gral_directory_watcher *directory_watcher) {
// TODO: implement
FSEventStreamRef event_stream = (FSEventStreamRef)directory_watcher;
FSEventStreamStop(event_stream);
//FSEventStreamUnscheduleFromRunLoop(event_stream, );
FSEventStreamInvalidate(event_stream);
FSEventStreamRelease(event_stream);
}


Expand Down

0 comments on commit f8d84ce

Please sign in to comment.