From 8551994fa5a1f3cd8170eccc956097e5dae0b6cf Mon Sep 17 00:00:00 2001 From: Tom Ekander Date: Tue, 28 Jul 2020 22:22:49 +0200 Subject: [PATCH 01/14] feat(native): add initial tray-support for macOS --- examples/Examples.re | 6 +++++ src/Native/ReveryCocoa.h | 4 ++++ src/Native/Revery_Native.re | 1 + src/Native/Tray.re | 5 +++++ src/Native/dune | 1 + src/Native/tray.c | 44 +++++++++++++++++++++++++++++++++++++ src/Native/tray_cocoa.c | 31 ++++++++++++++++++++++++++ 7 files changed, 92 insertions(+) create mode 100644 src/Native/Tray.re create mode 100644 src/Native/tray.c create mode 100644 src/Native/tray_cocoa.c diff --git a/examples/Examples.re b/examples/Examples.re index ac8ca4ec4..4c5cd1292 100644 --- a/examples/Examples.re +++ b/examples/Examples.re @@ -369,6 +369,12 @@ let init = app => { Console.log(Printf.sprintf("Moved: %d x %d", x, y)) ); + Native.Tray.make( + ~title=`Image(Environment.getAssetPath("outrun-logo.png")), + (), + ) + |> ignore; + let _renderFunction = UI.start(window, ); (); diff --git a/src/Native/ReveryCocoa.h b/src/Native/ReveryCocoa.h index 4b041b7ba..9dd3ac558 100644 --- a/src/Native/ReveryCocoa.h +++ b/src/Native/ReveryCocoa.h @@ -14,6 +14,10 @@ void revery_scheduleNotificationFromNow_cocoa(const char *title, int seconds); void *revery_getIconHandle_cocoa(); +/* Tray */ +void *revery_makeTrayHandleText_cocoa(const char *title_v); +void *revery_makeTrayHandleImage_cocoa(const char *title_v); + /* Icon progress bar functions */ void revery_setIconProgress_cocoa(void* dt, double progress); void revery_setIconProgressIndeterminate_cocoa(void *dt); diff --git a/src/Native/Revery_Native.re b/src/Native/Revery_Native.re index 2c8bb334d..fcdd81de5 100644 --- a/src/Native/Revery_Native.re +++ b/src/Native/Revery_Native.re @@ -5,5 +5,6 @@ module Notification = Notification; module Shell = Shell; module Locale = Locale; module Gtk = Gtk; +module Tray = Tray; include Initialization; diff --git a/src/Native/Tray.re b/src/Native/Tray.re new file mode 100644 index 000000000..f60b6eb8b --- /dev/null +++ b/src/Native/Tray.re @@ -0,0 +1,5 @@ +type t; + +type title = [ | `Text(string) | `Image(string)]; + +external make: (~title: title, unit) => t = "revery_makeTrayHandle"; diff --git a/src/Native/dune b/src/Native/dune index db6ec0a52..b095a7a8e 100644 --- a/src/Native/dune +++ b/src/Native/dune @@ -13,6 +13,7 @@ icon icon_cocoa icon_win32 shell shell_cocoa shell_gtk shell_win32 locale locale_cocoa locale_win32 + tray tray_cocoa utilities ReveryGtk ReveryGtk_Widget ReveryAppDelegate ReveryAppDelegate_func diff --git a/src/Native/tray.c b/src/Native/tray.c new file mode 100644 index 000000000..0b7ca5c0a --- /dev/null +++ b/src/Native/tray.c @@ -0,0 +1,44 @@ +#include + +#include +#include +#include +#include + +#include "caml_values.h" + +#define UNUSED(x) (void)(x) + +#include "config.h" +#ifdef USE_WIN32 +#include "ReveryWin32.h" +#elif USE_COCOA +#include "ReveryCocoa.h" +#elif USE_GTK +#include "ReveryGtk.h" +#endif + +CAMLprim value revery_makeTrayHandle(value title_v) { + CAMLparam1(title_v); + + void *ret; +#ifdef USE_COCOA + const char *title; + title = String_val(Field(title_v, 1)); + + if (Field(title_v, 0) == hash_variant("Text")) { + ret = revery_makeTrayHandleText_cocoa(title); + } else { + ret = revery_makeTrayHandleImage_cocoa(title); + }; + + UNUSED(title); +#elif USE_WIN32 + fprintf(stderr, "WARNING: %s is not implemented on this platform.", __func__); + ret = NULL; +#else + fprintf(stderr, "WARNING: %s is not implemented on this platform.", __func__); + ret = NULL; +#endif + CAMLreturn((value)ret); +} diff --git a/src/Native/tray_cocoa.c b/src/Native/tray_cocoa.c new file mode 100644 index 000000000..f8ff6103d --- /dev/null +++ b/src/Native/tray_cocoa.c @@ -0,0 +1,31 @@ +#include "config.h" +#ifdef USE_COCOA +#include + +#import + +void *revery_makeTrayHandleText_cocoa(const char *titleText) { + NSStatusItem *statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength]; + + NSString *nsTitle = + [NSString stringWithCString:titleText encoding:NSUTF8StringEncoding]; + + statusItem.button.title = nsTitle; + + return statusItem; +} + +void *revery_makeTrayHandleImage_cocoa(const char *titleImage) { + NSStatusItem *statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength]; + + NSString *nsImagePath = + [NSString stringWithCString:titleImage encoding:NSUTF8StringEncoding]; + + NSImage *nsImage = [[NSImage alloc]initWithContentsOfFile:nsImagePath]; + + statusItem.button.image = nsImage; + + return statusItem; +} + +#endif From 8505c1ed598722c7b237ac2b62d2c831f499dd27 Mon Sep 17 00:00:00 2001 From: Github Runner Date: Tue, 28 Jul 2020 20:31:59 +0000 Subject: [PATCH 02/14] format, --- src/Native/tray.c | 4 ++-- src/Native/tray_cocoa.c | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Native/tray.c b/src/Native/tray.c index 0b7ca5c0a..cf2b5d16d 100644 --- a/src/Native/tray.c +++ b/src/Native/tray.c @@ -27,9 +27,9 @@ CAMLprim value revery_makeTrayHandle(value title_v) { title = String_val(Field(title_v, 1)); if (Field(title_v, 0) == hash_variant("Text")) { - ret = revery_makeTrayHandleText_cocoa(title); + ret = revery_makeTrayHandleText_cocoa(title); } else { - ret = revery_makeTrayHandleImage_cocoa(title); + ret = revery_makeTrayHandleImage_cocoa(title); }; UNUSED(title); diff --git a/src/Native/tray_cocoa.c b/src/Native/tray_cocoa.c index f8ff6103d..be16d2934 100644 --- a/src/Native/tray_cocoa.c +++ b/src/Native/tray_cocoa.c @@ -5,27 +5,27 @@ #import void *revery_makeTrayHandleText_cocoa(const char *titleText) { - NSStatusItem *statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength]; + NSStatusItem *statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength]; - NSString *nsTitle = - [NSString stringWithCString:titleText encoding:NSUTF8StringEncoding]; + NSString *nsTitle = + [NSString stringWithCString:titleText encoding:NSUTF8StringEncoding]; - statusItem.button.title = nsTitle; + statusItem.button.title = nsTitle; - return statusItem; + return statusItem; } void *revery_makeTrayHandleImage_cocoa(const char *titleImage) { - NSStatusItem *statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength]; + NSStatusItem *statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength]; - NSString *nsImagePath = - [NSString stringWithCString:titleImage encoding:NSUTF8StringEncoding]; + NSString *nsImagePath = + [NSString stringWithCString:titleImage encoding:NSUTF8StringEncoding]; - NSImage *nsImage = [[NSImage alloc]initWithContentsOfFile:nsImagePath]; + NSImage *nsImage = [[NSImage alloc]initWithContentsOfFile:nsImagePath]; - statusItem.button.image = nsImage; + statusItem.button.image = nsImage; - return statusItem; + return statusItem; } #endif From 4ca19bf23d75ce7ab4df597e9165fb4cdf356fce Mon Sep 17 00:00:00 2001 From: Tom Ekander Date: Tue, 28 Jul 2020 22:45:02 +0200 Subject: [PATCH 03/14] chore: add tray interface-file --- src/Native/Tray.rei | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/Native/Tray.rei diff --git a/src/Native/Tray.rei b/src/Native/Tray.rei new file mode 100644 index 000000000..5672400b1 --- /dev/null +++ b/src/Native/Tray.rei @@ -0,0 +1,16 @@ +type t; + +type title = [ | `Text(string) | `Image(string)]; + +/** + * make + * + * Takes a [title] of either `Text(string) or `Image(string). + * Where `Image(string) takes an absolute path to a file. + * + * Examples: + * let tray = Tray.make(~title=`Text("Some Title"), ()); + * Tray.make(~title=`Image("/absolute/path/to/image.png"), ()) |> ignore; + * Tray.make(~title=`Image(Environment.getAssetPath("some_asset_image.png"), ()) |> ignore; + */ +let make: (~title: title, unit) => t; From 3479e14843d4e1c5ac0d545bf3c86d1fe34b475b Mon Sep 17 00:00:00 2001 From: Tom Ekander Date: Fri, 7 Aug 2020 15:56:36 +0200 Subject: [PATCH 04/14] refactor: remove title, only take an imagePath initially --- examples/Examples.re | 2 +- src/Native/Tray.re | 4 +--- src/Native/Tray.rei | 14 ++++++-------- src/Native/tray.c | 23 ++++++++++++----------- 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/examples/Examples.re b/examples/Examples.re index 4c5cd1292..6f5d7edbf 100644 --- a/examples/Examples.re +++ b/examples/Examples.re @@ -370,7 +370,7 @@ let init = app => { ); Native.Tray.make( - ~title=`Image(Environment.getAssetPath("outrun-logo.png")), + ~imagePath=Environment.getAssetPath("outrun-logo.png"), (), ) |> ignore; diff --git a/src/Native/Tray.re b/src/Native/Tray.re index f60b6eb8b..bf98a751e 100644 --- a/src/Native/Tray.re +++ b/src/Native/Tray.re @@ -1,5 +1,3 @@ type t; -type title = [ | `Text(string) | `Image(string)]; - -external make: (~title: title, unit) => t = "revery_makeTrayHandle"; +external make: (~imagePath: string=?, unit) => t = "revery_makeTrayHandle"; diff --git a/src/Native/Tray.rei b/src/Native/Tray.rei index 5672400b1..9278b1cd3 100644 --- a/src/Native/Tray.rei +++ b/src/Native/Tray.rei @@ -1,16 +1,14 @@ type t; -type title = [ | `Text(string) | `Image(string)]; - /** * make * - * Takes a [title] of either `Text(string) or `Image(string). - * Where `Image(string) takes an absolute path to a file. + * Takes an optional [imagePath] which is an absolute path to a in image-file. + * Returns a newly created Tray.t; * * Examples: - * let tray = Tray.make(~title=`Text("Some Title"), ()); - * Tray.make(~title=`Image("/absolute/path/to/image.png"), ()) |> ignore; - * Tray.make(~title=`Image(Environment.getAssetPath("some_asset_image.png"), ()) |> ignore; + * Tray.make(~imagePath="/absolute/path/to/image.png", ()) |> ignore; + * Tray.make(~imagePath=Environment.getAssetPath("some_asset_image.png", ()) |> ignore; + * let tray = Tray.make(); */ -let make: (~title: title, unit) => t; +let make: (~imagePath: string=?, unit) => t; diff --git a/src/Native/tray.c b/src/Native/tray.c index cf2b5d16d..a32da31eb 100644 --- a/src/Native/tray.c +++ b/src/Native/tray.c @@ -18,26 +18,27 @@ #include "ReveryGtk.h" #endif -CAMLprim value revery_makeTrayHandle(value title_v) { - CAMLparam1(title_v); +CAMLprim value revery_makeTrayHandle(value imagePath_v) { + CAMLparam1(imagePath_v); void *ret; #ifdef USE_COCOA - const char *title; - title = String_val(Field(title_v, 1)); + const char *imagePath = String_val(imagePath_v); - if (Field(title_v, 0) == hash_variant("Text")) { - ret = revery_makeTrayHandleText_cocoa(title); + if (imagePath_v == Val_none) { + ret = NULL; } else { - ret = revery_makeTrayHandleImage_cocoa(title); - }; + const char *imagePath = String_val(imagePath_v); + imagePath = String_val(Some_val(imagePath_v)); + ret = revery_makeTrayHandleImage_cocoa(imagePath); + } - UNUSED(title); + UNUSED(imagePath); #elif USE_WIN32 - fprintf(stderr, "WARNING: %s is not implemented on this platform.", __func__); + /* fprintf(stderr, "WARNING: %s is not implemented on this platform.", __func__); */ ret = NULL; #else - fprintf(stderr, "WARNING: %s is not implemented on this platform.", __func__); + /* fprintf(stderr, "WARNING: %s is not implemented on this platform.", __func__); */ ret = NULL; #endif CAMLreturn((value)ret); From 6b192fee86c4d30c4f288e96bd7f32382502727c Mon Sep 17 00:00:00 2001 From: Tom Ekander Date: Mon, 10 Aug 2020 19:57:00 +0200 Subject: [PATCH 05/14] refactor: don't used naked pointers for handle --- examples/Examples.re | 2 ++ src/Native/ReveryCocoa.h | 4 +++ src/Native/Tray.re | 2 ++ src/Native/Tray.rei | 12 +++++++++ src/Native/dune | 1 + src/Native/image_cocoa.c | 16 ++++++++++++ src/Native/tray.c | 56 ++++++++++++++++++++++++++++++---------- 7 files changed, 79 insertions(+), 14 deletions(-) create mode 100644 src/Native/image_cocoa.c diff --git a/examples/Examples.re b/examples/Examples.re index 6f5d7edbf..d2e222c46 100644 --- a/examples/Examples.re +++ b/examples/Examples.re @@ -375,6 +375,8 @@ let init = app => { ) |> ignore; + Native.Tray.make() |> Native.Tray.setTitle(~text="Hello Revery!"); + let _renderFunction = UI.start(window, ); (); diff --git a/src/Native/ReveryCocoa.h b/src/Native/ReveryCocoa.h index 9dd3ac558..b592ee6b5 100644 --- a/src/Native/ReveryCocoa.h +++ b/src/Native/ReveryCocoa.h @@ -17,12 +17,16 @@ void *revery_getIconHandle_cocoa(); /* Tray */ void *revery_makeTrayHandleText_cocoa(const char *title_v); void *revery_makeTrayHandleImage_cocoa(const char *title_v); +void revery_setTrayTitle_cocoa(const char *title_v); /* Icon progress bar functions */ void revery_setIconProgress_cocoa(void* dt, double progress); void revery_setIconProgressIndeterminate_cocoa(void *dt); void revery_hideIconProgress_cocoa(void* ip); +/* Image functions */ +void *revery_makeImageFromAbsolutePath(const char *image_path_v); + /* Open functions */ int revery_openURL_cocoa(const char *url_string); int revery_openFile_cocoa(const char *path_string); diff --git a/src/Native/Tray.re b/src/Native/Tray.re index bf98a751e..afe6b97f2 100644 --- a/src/Native/Tray.re +++ b/src/Native/Tray.re @@ -1,3 +1,5 @@ type t; external make: (~imagePath: string=?, unit) => t = "revery_makeTrayHandle"; + +external setTitle: (t, ~text: string) => unit = "revery_setTrayTitle"; diff --git a/src/Native/Tray.rei b/src/Native/Tray.rei index 9278b1cd3..c74a2303f 100644 --- a/src/Native/Tray.rei +++ b/src/Native/Tray.rei @@ -12,3 +12,15 @@ type t; * let tray = Tray.make(); */ let make: (~imagePath: string=?, unit) => t; + +/** + * setTitle + * + * Takes a [title] of string and sets the tray's text to it. + * * + * Examples: + * tray |> Tray.setTitle(~text="Hello Revery!"); + * Tray.make() |> Tray.setTitle(~text="Hello Revery!"); + * Tray.setTitle(tray, ~text="Hello World!"); + */ +let setTitle: (t, ~text: string) => unit; diff --git a/src/Native/dune b/src/Native/dune index b095a7a8e..cf3ad0842 100644 --- a/src/Native/dune +++ b/src/Native/dune @@ -11,6 +11,7 @@ notification notification_cocoa environment icon icon_cocoa icon_win32 + image_cocoa shell shell_cocoa shell_gtk shell_win32 locale locale_cocoa locale_win32 tray tray_cocoa diff --git a/src/Native/image_cocoa.c b/src/Native/image_cocoa.c new file mode 100644 index 000000000..8c4a2519a --- /dev/null +++ b/src/Native/image_cocoa.c @@ -0,0 +1,16 @@ +#include "config.h" +#ifdef USE_COCOA +#include + +#import + +void *revery_makeImageFromAbsolutePath(const char *imagePath) { + NSString *nsImagePath = + [NSString stringWithCString:imagePath encoding:NSUTF8StringEncoding]; + + NSImage *nsImage = [[NSImage alloc]initWithContentsOfFile:nsImagePath]; + + return nsImage; +} + +#endif diff --git a/src/Native/tray.c b/src/Native/tray.c index a32da31eb..dd742e309 100644 --- a/src/Native/tray.c +++ b/src/Native/tray.c @@ -14,32 +14,60 @@ #include "ReveryWin32.h" #elif USE_COCOA #include "ReveryCocoa.h" +#import #elif USE_GTK #include "ReveryGtk.h" #endif CAMLprim value revery_makeTrayHandle(value imagePath_v) { CAMLparam1(imagePath_v); + CAMLlocal1(result); - void *ret; #ifdef USE_COCOA - const char *imagePath = String_val(imagePath_v); - - if (imagePath_v == Val_none) { - ret = NULL; - } else { - const char *imagePath = String_val(imagePath_v); - imagePath = String_val(Some_val(imagePath_v)); - ret = revery_makeTrayHandleImage_cocoa(imagePath); + const char *imagePath; + + NSStatusItem *statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength]; + + if (imagePath_v != Val_none) { + const char *imagePath = String_val(Some_val(imagePath_v)); + + NSStatusItem *statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength]; + + NSImage *nsImage = revery_makeImageFromAbsolutePath(imagePath); + + statusItem.button.image = nsImage; } + result = caml_alloc(1, Abstract_tag); + Store_field(result, 0, (long)statusItem); + UNUSED(imagePath); + CAMLreturn(result); +#elif USE_WIN32 + result = caml_alloc(sizeof(NULL), Abstract_tag); +#else + result = caml_alloc(sizeof(NULL), Abstract_tag); +#endif + CAMLreturn(result); +} + +void revery_setTrayTitle(value trayHandle_v, value title_v) { + CAMLparam2(trayHandle_v, title_v); +#ifdef USE_COCOA + NSStatusItem* statusItem = (NSStatusItem*)(void*)Field(trayHandle_v, 0); + + const char *title = String_val(title_v); + + NSString *nsTitle = + [NSString stringWithCString:title encoding:NSUTF8StringEncoding]; + + statusItem.button.image = NULL; + statusItem.button.title = nsTitle; + + CAMLreturn0; #elif USE_WIN32 - /* fprintf(stderr, "WARNING: %s is not implemented on this platform.", __func__); */ - ret = NULL; + CAMLreturn0; #else - /* fprintf(stderr, "WARNING: %s is not implemented on this platform.", __func__); */ - ret = NULL; + CAMLreturn0; #endif - CAMLreturn((value)ret); } From 5875b9da3a74df7cb76803065871a8acee9af51e Mon Sep 17 00:00:00 2001 From: Tom Ekander Date: Tue, 11 Aug 2020 15:36:17 +0200 Subject: [PATCH 06/14] chore: remove left-overs --- src/Native/dune | 2 +- src/Native/tray.c | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Native/dune b/src/Native/dune index cf3ad0842..619247535 100644 --- a/src/Native/dune +++ b/src/Native/dune @@ -14,7 +14,7 @@ image_cocoa shell shell_cocoa shell_gtk shell_win32 locale locale_cocoa locale_win32 - tray tray_cocoa + tray utilities ReveryGtk ReveryGtk_Widget ReveryAppDelegate ReveryAppDelegate_func diff --git a/src/Native/tray.c b/src/Native/tray.c index dd742e309..a50eba438 100644 --- a/src/Native/tray.c +++ b/src/Native/tray.c @@ -24,24 +24,21 @@ CAMLprim value revery_makeTrayHandle(value imagePath_v) { CAMLlocal1(result); #ifdef USE_COCOA - const char *imagePath; - NSStatusItem *statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength]; if (imagePath_v != Val_none) { const char *imagePath = String_val(Some_val(imagePath_v)); - NSStatusItem *statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength]; - NSImage *nsImage = revery_makeImageFromAbsolutePath(imagePath); statusItem.button.image = nsImage; + + UNUSED(imagePath); } result = caml_alloc(1, Abstract_tag); Store_field(result, 0, (long)statusItem); - UNUSED(imagePath); CAMLreturn(result); #elif USE_WIN32 result = caml_alloc(sizeof(NULL), Abstract_tag); From 5073247a186bfd432bf779b10f4fb17ff12fc810 Mon Sep 17 00:00:00 2001 From: Tom Ekander Date: Tue, 11 Aug 2020 15:37:27 +0200 Subject: [PATCH 07/14] chore: remove unused functions --- src/Native/ReveryCocoa.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Native/ReveryCocoa.h b/src/Native/ReveryCocoa.h index b592ee6b5..5f2d8be42 100644 --- a/src/Native/ReveryCocoa.h +++ b/src/Native/ReveryCocoa.h @@ -15,8 +15,6 @@ void revery_scheduleNotificationFromNow_cocoa(const char *title, void *revery_getIconHandle_cocoa(); /* Tray */ -void *revery_makeTrayHandleText_cocoa(const char *title_v); -void *revery_makeTrayHandleImage_cocoa(const char *title_v); void revery_setTrayTitle_cocoa(const char *title_v); /* Icon progress bar functions */ From 9e0b01ff746a7b37603c86ba345d7a1b3b3a3d0e Mon Sep 17 00:00:00 2001 From: Tom Ekander Date: Fri, 28 Aug 2020 10:21:55 +0200 Subject: [PATCH 08/14] refactor: cocoa naming-convention --- src/Native/ReveryCocoa.h | 2 +- src/Native/image_cocoa.c | 2 +- src/Native/tray.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Native/ReveryCocoa.h b/src/Native/ReveryCocoa.h index 5f2d8be42..cf092d324 100644 --- a/src/Native/ReveryCocoa.h +++ b/src/Native/ReveryCocoa.h @@ -23,7 +23,7 @@ void revery_setIconProgressIndeterminate_cocoa(void *dt); void revery_hideIconProgress_cocoa(void* ip); /* Image functions */ -void *revery_makeImageFromAbsolutePath(const char *image_path_v); +void *revery_makeImageFromAbsolutePath_cocoa(const char *image_path_v); /* Open functions */ int revery_openURL_cocoa(const char *url_string); diff --git a/src/Native/image_cocoa.c b/src/Native/image_cocoa.c index 8c4a2519a..fed24481c 100644 --- a/src/Native/image_cocoa.c +++ b/src/Native/image_cocoa.c @@ -4,7 +4,7 @@ #import -void *revery_makeImageFromAbsolutePath(const char *imagePath) { +void *revery_makeImageFromAbsolutePath_cocoa(const char *imagePath) { NSString *nsImagePath = [NSString stringWithCString:imagePath encoding:NSUTF8StringEncoding]; diff --git a/src/Native/tray.c b/src/Native/tray.c index a50eba438..7b69ffa6e 100644 --- a/src/Native/tray.c +++ b/src/Native/tray.c @@ -29,7 +29,7 @@ CAMLprim value revery_makeTrayHandle(value imagePath_v) { if (imagePath_v != Val_none) { const char *imagePath = String_val(Some_val(imagePath_v)); - NSImage *nsImage = revery_makeImageFromAbsolutePath(imagePath); + NSImage *nsImage = revery_makeImageFromAbsolutePath_cocoa(imagePath); statusItem.button.image = nsImage; From 873b7b508b6787893e88cae313678b38fd9ef519 Mon Sep 17 00:00:00 2001 From: Tom Ekander Date: Sat, 22 May 2021 14:12:14 +0300 Subject: [PATCH 09/14] Move example to a separate file --- examples/Examples.re | 9 +-------- examples/Tray.re | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 examples/Tray.re diff --git a/examples/Examples.re b/examples/Examples.re index 1f9c3e183..11e363e3c 100644 --- a/examples/Examples.re +++ b/examples/Examples.re @@ -85,6 +85,7 @@ let examples = [ render: _ => NativeMenuExample.render(), source: "NativeMenuExample.re", }, + {name: "Native: Tray", render: _w => Tray.render(), source: "Tray.re"}, { name: "Native: Inputs", render: _ => NativeInputExample.render(), @@ -394,14 +395,6 @@ let init = app => { print_endline(Printf.sprintf("Moved: %d x %d", x, y)) ); - Native.Tray.make( - ~imagePath=Environment.getAssetPath("outrun-logo.png"), - (), - ) - |> ignore; - - Native.Tray.make() |> Native.Tray.setTitle(~text="Hello Revery!"); - print_endline( Printf.sprintf("Operating system: %s", Environment.osString), ); diff --git a/examples/Tray.re b/examples/Tray.re new file mode 100644 index 000000000..c46d68106 --- /dev/null +++ b/examples/Tray.re @@ -0,0 +1,22 @@ +open Revery; +open Revery.UI; +open Revery.UI.Components; + +let make = () => { + Native.Tray.make( + ~imagePath=Environment.getAssetPath("outrun-logo.png"), + (), + ) + |> ignore; + + Native.Tray.make() |> Native.Tray.setTitle(~text="Hello Revery!"); + +
+ +
; +}; + +let render = () => make(); From 3834a8963cc88290786fea1a0c3023207abe3d45 Mon Sep 17 00:00:00 2001 From: Tom Ekander Date: Sat, 29 May 2021 18:58:55 +0300 Subject: [PATCH 10/14] Add remove, use utility-wrapper fn, setTitle returns t --- examples/Tray.re | 28 +++++++++++++++++++++------- src/Native/Tray.re | 4 +++- src/Native/Tray.rei | 20 ++++++++++++++++---- src/Native/tray.c | 28 +++++++++++++++++++++++----- 4 files changed, 63 insertions(+), 17 deletions(-) diff --git a/examples/Tray.re b/examples/Tray.re index c46d68106..69cbb750a 100644 --- a/examples/Tray.re +++ b/examples/Tray.re @@ -2,14 +2,28 @@ open Revery; open Revery.UI; open Revery.UI.Components; -let make = () => { - Native.Tray.make( - ~imagePath=Environment.getAssetPath("outrun-logo.png"), - (), - ) - |> ignore; +let%component make = () => { + let%hook () = + Hooks.effect( + OnMount, + () => { + let trayImage = + Native.Tray.make( + ~imagePath=Environment.getAssetPath("outrun-logo.png"), + (), + ); - Native.Tray.make() |> Native.Tray.setTitle(~text="Hello Revery!"); + let trayText = + Native.Tray.make() |> Native.Tray.setTitle(~text="Hello Revery!"); + + Some( + () => { + trayImage |> Native.Tray.remove; + trayText |> Native.Tray.remove; + }, + ); + }, + );
t = "revery_makeTrayHandle"; -external setTitle: (t, ~text: string) => unit = "revery_setTrayTitle"; +external setTitle: (t, ~text: string) => t = "revery_setTrayTitle"; + +external remove: t => unit = "revery_removeTrayItem"; diff --git a/src/Native/Tray.rei b/src/Native/Tray.rei index c74a2303f..1bc574bd6 100644 --- a/src/Native/Tray.rei +++ b/src/Native/Tray.rei @@ -17,10 +17,22 @@ let make: (~imagePath: string=?, unit) => t; * setTitle * * Takes a [title] of string and sets the tray's text to it. + * Returns the updated tray item. * * * Examples: - * tray |> Tray.setTitle(~text="Hello Revery!"); - * Tray.make() |> Tray.setTitle(~text="Hello Revery!"); - * Tray.setTitle(tray, ~text="Hello World!"); + * tray |> Tray.setTitle(~text="Hello Revery!") |> ignore; + * let tray = Tray.make() |> Tray.setTitle(~text="Hello Revery!"); + * Tray.setTitle(tray, ~text="Hello World!") |> ignore; */ -let setTitle: (t, ~text: string) => unit; +let setTitle: (t, ~text: string) => t; + +/** + * remove + * + * Takes a [t] and removes it. + * * + * Example: + * tray |> Tray.remove; + * Tray.remove(tray); + */ +let remove: t => unit; diff --git a/src/Native/tray.c b/src/Native/tray.c index 7b69ffa6e..f533b3629 100644 --- a/src/Native/tray.c +++ b/src/Native/tray.c @@ -7,8 +7,6 @@ #include "caml_values.h" -#define UNUSED(x) (void)(x) - #include "config.h" #ifdef USE_WIN32 #include "ReveryWin32.h" @@ -19,6 +17,8 @@ #include "ReveryGtk.h" #endif +#include "utilities.h" + CAMLprim value revery_makeTrayHandle(value imagePath_v) { CAMLparam1(imagePath_v); CAMLlocal1(result); @@ -36,8 +36,7 @@ CAMLprim value revery_makeTrayHandle(value imagePath_v) { UNUSED(imagePath); } - result = caml_alloc(1, Abstract_tag); - Store_field(result, 0, (long)statusItem); + result = revery_wrapPointer(statusItem); CAMLreturn(result); #elif USE_WIN32 @@ -48,8 +47,9 @@ CAMLprim value revery_makeTrayHandle(value imagePath_v) { CAMLreturn(result); } -void revery_setTrayTitle(value trayHandle_v, value title_v) { +CAMLprim value revery_setTrayTitle(value trayHandle_v, value title_v) { CAMLparam2(trayHandle_v, title_v); + CAMLlocal1(result); #ifdef USE_COCOA NSStatusItem* statusItem = (NSStatusItem*)(void*)Field(trayHandle_v, 0); @@ -61,6 +61,24 @@ void revery_setTrayTitle(value trayHandle_v, value title_v) { statusItem.button.image = NULL; statusItem.button.title = nsTitle; + result = revery_wrapPointer(statusItem); + + CAMLreturn(result); +#elif USE_WIN32 + result = caml_alloc(sizeof(NULL), Abstract_tag); +#else + result = caml_alloc(sizeof(NULL), Abstract_tag); +#endif + CAMLreturn(result); +} + +void revery_removeTrayItem(value trayHandle_v) { + CAMLparam1(trayHandle_v); +#ifdef USE_COCOA + NSStatusItem* statusItem = (NSStatusItem *)revery_unwrapPointer(trayHandle_v); + + [[NSStatusBar systemStatusBar] removeStatusItem: statusItem]; + CAMLreturn0; #elif USE_WIN32 CAMLreturn0; From 465f015c1a78df6b28704d635c4c4b51e8fb0072 Mon Sep 17 00:00:00 2001 From: Tom Ekander Date: Sat, 29 May 2021 19:02:33 +0300 Subject: [PATCH 11/14] Update docs wording for remove --- src/Native/Tray.rei | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Native/Tray.rei b/src/Native/Tray.rei index 1bc574bd6..5888c9770 100644 --- a/src/Native/Tray.rei +++ b/src/Native/Tray.rei @@ -29,7 +29,7 @@ let setTitle: (t, ~text: string) => t; /** * remove * - * Takes a [t] and removes it. + * Given a [t] removes the tray item from the tray. * * * Example: * tray |> Tray.remove; From 1f53855d1f59d1d651f05ef99052ac8e8ea5d614 Mon Sep 17 00:00:00 2001 From: Tom Ekander Date: Sat, 29 May 2021 19:04:34 +0300 Subject: [PATCH 12/14] Remove unused function --- src/Native/ReveryCocoa.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Native/ReveryCocoa.h b/src/Native/ReveryCocoa.h index 398d14977..2a0c2b220 100644 --- a/src/Native/ReveryCocoa.h +++ b/src/Native/ReveryCocoa.h @@ -14,9 +14,6 @@ void revery_scheduleNotificationFromNow_cocoa(const char *title, int seconds); void *revery_getIconHandle_cocoa(); -/* Tray */ -void revery_setTrayTitle_cocoa(const char *title_v); - /* Icon progress bar functions */ void revery_setIconProgress_cocoa(void* dt, double progress); void revery_setIconProgressIndeterminate_cocoa(void *dt); From 240e45276f6cd69fa7a71ed8989bc6cb9d87662f Mon Sep 17 00:00:00 2001 From: Tom Ekander Date: Sat, 29 May 2021 22:44:51 +0300 Subject: [PATCH 13/14] Move stuff to tray_cocoa, use updated unwrapPointer --- src/Native/ReveryCocoa.h | 4 ++++ src/Native/dune | 2 +- src/Native/tray.c | 30 +++++++++++++----------------- src/Native/tray_cocoa.c | 18 ++++-------------- 4 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/Native/ReveryCocoa.h b/src/Native/ReveryCocoa.h index 2a0c2b220..2a7528308 100644 --- a/src/Native/ReveryCocoa.h +++ b/src/Native/ReveryCocoa.h @@ -19,6 +19,10 @@ void revery_setIconProgress_cocoa(void* dt, double progress); void revery_setIconProgressIndeterminate_cocoa(void *dt); void revery_hideIconProgress_cocoa(void* ip); +/* Tray */ +void *revery_setTrayTitle_cocoa(void *nsStatusItem, const char *titleText); +void revery_removeStatusItem_cocoa(void* nsStatusItem); + /* Image functions */ void *revery_makeImageFromAbsolutePath_cocoa(const char *image_path_v); diff --git a/src/Native/dune b/src/Native/dune index 451ae84ee..1f5571923 100644 --- a/src/Native/dune +++ b/src/Native/dune @@ -13,7 +13,7 @@ (names Revery_Native dialog dialog_cocoa dialog_win32 dialog_gtk notification notification_cocoa environment environment_mac environment_linux environment_windows icon icon_cocoa icon_win32 image_cocoa shell - shell_cocoa shell_gtk shell_win32 tray locale locale_cocoa locale_win32 menu + shell_cocoa shell_gtk shell_win32 tray tray_cocoa locale locale_cocoa locale_win32 menu menu_cocoa input input_cocoa window window_cocoa utilities ReveryGtk ReveryGtk_Widget ReveryAppDelegate ReveryAppDelegate_func ReveryNSObject ReveryNSView ReveryNSViewCoords ReveryMenuItemTarget ReveryButtonTarget diff --git a/src/Native/tray.c b/src/Native/tray.c index f533b3629..568e08651 100644 --- a/src/Native/tray.c +++ b/src/Native/tray.c @@ -19,15 +19,15 @@ #include "utilities.h" -CAMLprim value revery_makeTrayHandle(value imagePath_v) { - CAMLparam1(imagePath_v); +CAMLprim value revery_makeTrayHandle(value vImagePath) { + CAMLparam1(vImagePath); CAMLlocal1(result); #ifdef USE_COCOA NSStatusItem *statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength]; - if (imagePath_v != Val_none) { - const char *imagePath = String_val(Some_val(imagePath_v)); + if (vImagePath != Val_none) { + const char *imagePath = String_val(Some_val(vImagePath)); NSImage *nsImage = revery_makeImageFromAbsolutePath_cocoa(imagePath); @@ -47,19 +47,15 @@ CAMLprim value revery_makeTrayHandle(value imagePath_v) { CAMLreturn(result); } -CAMLprim value revery_setTrayTitle(value trayHandle_v, value title_v) { - CAMLparam2(trayHandle_v, title_v); +CAMLprim value revery_setTrayTitle(value vTrayHandle, value vTitle) { + CAMLparam2(vTrayHandle, vTitle); CAMLlocal1(result); #ifdef USE_COCOA - NSStatusItem* statusItem = (NSStatusItem*)(void*)Field(trayHandle_v, 0); + void* statusItem = revery_unwrapPointer(vTrayHandle); - const char *title = String_val(title_v); + const char *title = String_val(vTitle); - NSString *nsTitle = - [NSString stringWithCString:title encoding:NSUTF8StringEncoding]; - - statusItem.button.image = NULL; - statusItem.button.title = nsTitle; + revery_setTrayTitle_cocoa(statusItem, title); result = revery_wrapPointer(statusItem); @@ -72,12 +68,12 @@ CAMLprim value revery_setTrayTitle(value trayHandle_v, value title_v) { CAMLreturn(result); } -void revery_removeTrayItem(value trayHandle_v) { - CAMLparam1(trayHandle_v); +void revery_removeTrayItem(value vTrayHandle) { + CAMLparam1(vTrayHandle); #ifdef USE_COCOA - NSStatusItem* statusItem = (NSStatusItem *)revery_unwrapPointer(trayHandle_v); + void* statusItem = revery_unwrapPointer(vTrayHandle); - [[NSStatusBar systemStatusBar] removeStatusItem: statusItem]; + revery_removeStatusItem_cocoa(statusItem); CAMLreturn0; #elif USE_WIN32 diff --git a/src/Native/tray_cocoa.c b/src/Native/tray_cocoa.c index be16d2934..2c9b4fb8f 100644 --- a/src/Native/tray_cocoa.c +++ b/src/Native/tray_cocoa.c @@ -4,28 +4,18 @@ #import -void *revery_makeTrayHandleText_cocoa(const char *titleText) { - NSStatusItem *statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength]; - +void *revery_setTrayTitle_cocoa(NSStatusItem* statusItem, const char *titleText) { NSString *nsTitle = [NSString stringWithCString:titleText encoding:NSUTF8StringEncoding]; + statusItem.button.image = NULL; statusItem.button.title = nsTitle; return statusItem; } -void *revery_makeTrayHandleImage_cocoa(const char *titleImage) { - NSStatusItem *statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength]; - - NSString *nsImagePath = - [NSString stringWithCString:titleImage encoding:NSUTF8StringEncoding]; - - NSImage *nsImage = [[NSImage alloc]initWithContentsOfFile:nsImagePath]; - - statusItem.button.image = nsImage; - - return statusItem; +void revery_removeStatusItem_cocoa(NSStatusItem* statusItem) { + [[NSStatusBar systemStatusBar] removeStatusItem: statusItem]; } #endif From 2f2c8624d2e48028947439a813d3e784b5388f0e Mon Sep 17 00:00:00 2001 From: Tom Ekander Date: Mon, 31 May 2021 19:36:31 +0300 Subject: [PATCH 14/14] Add Gc.finalise to make tray-handler --- src/Native/Tray.re | 28 +++++++++++++++++++++++++--- src/Native/tray.c | 1 + 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Native/Tray.re b/src/Native/Tray.re index 7183687cd..7378af283 100644 --- a/src/Native/Tray.re +++ b/src/Native/Tray.re @@ -1,7 +1,29 @@ +%import +"config.h"; + type t; -external make: (~imagePath: string=?, unit) => t = "revery_makeTrayHandle"; +open { + external c_make: (~imagePath: string=?, unit) => t = + "revery_makeTrayHandle"; + external c_setTitle: (t, ~text: string) => t = "revery_setTrayTitle"; + external c_remove: t => unit = "revery_removeTrayItem"; + }; + +%if +defined(USE_COCOA); + +let make = (~imagePath=?, ()) => { + let trayHandle = c_make(~imagePath?, ()); + Gc.finalise(NSObject.release, trayHandle); + trayHandle; +}; + +[%%else]; + +let make = c_make; -external setTitle: (t, ~text: string) => t = "revery_setTrayTitle"; +[%%endif]; -external remove: t => unit = "revery_removeTrayItem"; +let setTitle = c_setTitle; +let remove = c_remove; diff --git a/src/Native/tray.c b/src/Native/tray.c index 568e08651..4724f00b3 100644 --- a/src/Native/tray.c +++ b/src/Native/tray.c @@ -25,6 +25,7 @@ CAMLprim value revery_makeTrayHandle(value vImagePath) { #ifdef USE_COCOA NSStatusItem *statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength]; + [(NSObject *)statusItem retain]; if (vImagePath != Val_none) { const char *imagePath = String_val(Some_val(vImagePath));