From ed8326659ec523e3714453e8dd78a785b24d10e9 Mon Sep 17 00:00:00 2001 From: Akin Date: Tue, 5 Feb 2019 19:01:54 +0000 Subject: [PATCH] Add linux alert (#294) Very early WIP implementation of gtk dialog alert to fix #278 (please ignore the commented out code etc. just trying to get stuff working) Progress so far: No longer chokes on `#include ` - currently need to tweak the borrowed snippet from #278 as an example to create an alert doesn't work as is, I think Things to note/note to self: - [x] I have to rework the `discover.ml` so it can use the pkg_config functionality on linux but behave as normal on other systems - [x] Fix GTK crash on opening dialog - things compile but the function to open a dialog causes a crash, note this also happens in a separate project when I try and create a dialog with the same function (might be specific to my machine or more likely a bug in the code) --- azure-pipelines.yml | 2 +- src/Native/ReveryGtk.h | 3 ++ src/Native/config/discover.ml | 52 ++++++++++++++++++++---------- src/Native/dialog.cpp | 60 +++++++++++++++++++---------------- src/Native/dialog_gtk.c | 33 +++++++++++++++++++ src/Native/dune | 5 +-- 6 files changed, 108 insertions(+), 47 deletions(-) create mode 100644 src/Native/ReveryGtk.h create mode 100644 src/Native/dialog_gtk.c diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e91075468..0cce92e51 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -18,7 +18,7 @@ jobs: # ESY__NPM_ROOT: /opt/hostedtoolcache/node/8.14.0/x64/lib/node_modules/esy steps: - - script: sudo apt-get install -y libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libegl1-mesa-dev mesa-utils mesa-utils-extra ragel + - script: sudo apt-get install -y libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libegl1-mesa-dev mesa-utils mesa-utils-extra ragel libgtk-3-dev - template: .ci/use-node.yml - template: .ci/restore-build-cache.yml - template: .ci/esy-build-steps.yml diff --git a/src/Native/ReveryGtk.h b/src/Native/ReveryGtk.h new file mode 100644 index 000000000..ceaaa245b --- /dev/null +++ b/src/Native/ReveryGtk.h @@ -0,0 +1,3 @@ +extern "C" { +void revery_alert_gtk(void *pWin, const char *szMessage); +} diff --git a/src/Native/config/discover.ml b/src/Native/config/discover.ml index e89103a6a..36fbbcc20 100644 --- a/src/Native/config/discover.ml +++ b/src/Native/config/discover.ml @@ -1,21 +1,41 @@ -type os = - | Windows - | Mac - | Linux - | Unknown +module C = Configurator.V1 + +type os = Windows | Mac | Linux | Unknown + +type config = {libs: string list; cflags: string list; flags: string list} + +let get_mac_config () = + {cflags= ["-I"; "."; "-x"; "objective-c"]; libs= []; flags= []} + +let get_linux_config c = + let default = {libs= []; cflags= []; flags= []} in + match C.Pkg_config.get c with + | None -> default + | Some pc -> ( + match C.Pkg_config.query pc ~package:"gtk+-3.0" with + | None -> default + | Some conf -> {libs= conf.libs; cflags= conf.cflags; flags= []} ) + let uname () = let ic = Unix.open_process_in "uname" in - let uname = input_line ic in let () = close_in ic in uname + let uname = input_line ic in + let () = close_in ic in + uname + let get_os = match Sys.os_type with | "Win32" -> Windows - | _ -> - (match uname () with - | "Darwin" -> Mac - | "Linux" -> Linux - | _ -> Unknown) -let c_flags = - match get_os with | Mac -> ["-I"; "."; "-x"; "objective-c"] | _ -> [] -let flags = [] -;;Configurator.V1.Flags.write_sexp "c_flags.sexp" c_flags; - Configurator.V1.Flags.write_sexp "flags.sexp" flags \ No newline at end of file + | _ -> ( + match uname () with "Darwin" -> Mac | "Linux" -> Linux | _ -> Unknown ) + +let () = + C.main ~name:"discover" (fun c -> + let conf = + match get_os with + | Mac -> get_mac_config () + | Linux -> get_linux_config c + | _ -> {libs= []; flags= []; cflags= []} + in + C.Flags.write_sexp "flags.sexp" conf.flags ; + C.Flags.write_sexp "c_flags.sexp" conf.cflags ; + C.Flags.write_sexp "c_library_flags.sexp" conf.libs ) diff --git a/src/Native/dialog.cpp b/src/Native/dialog.cpp index cf611fb33..8b27795b0 100644 --- a/src/Native/dialog.cpp +++ b/src/Native/dialog.cpp @@ -1,41 +1,45 @@ #include -#include -#include #include #include +#include +#include #ifdef WIN32 - #include "ReveryWin32.h" +#include "ReveryWin32.h" #elif __APPLE__ - #include "ReveryCocoa.h" +#include "ReveryCocoa.h" +#else +#include "ReveryGtk.h" #endif extern "C" { - CAMLprim value - revery_alertSupported() { - #ifdef WIN32 - return Val_true; - #elif __APPLE__ - return Val_true; - #else - return Val_false; - #endif - } +CAMLprim value revery_alertSupported() { +#ifdef WIN32 + return Val_true; +#elif __APPLE__ + return Val_true; +#elif __linux__ + return Val_true; +#else + return Val_false; +#endif +} - CAMLprim value - revery_alert(value vWindow, value vMessage) { - CAMLparam2(vWindow, vMessage); - const char *szMessage = String_val(vMessage); - void* pWin = (void *)vWindow; +CAMLprim value revery_alert(value vWindow, value vMessage) { + CAMLparam2(vWindow, vMessage); + const char *szMessage = String_val(vMessage); + void *pWin = (void *)vWindow; - #ifdef WIN32 - revery_alert_win32(pWin, szMessage); - #elif __APPLE__ - revery_alert_cocoa(pWin, szMessage); - #else - printf("WARNING - Not implemented: alert"); - #endif - return Val_unit; - } +#ifdef WIN32 + revery_alert_win32(pWin, szMessage); +#elif __APPLE__ + revery_alert_cocoa(pWin, szMessage); +#elif __linux__ + revery_alert_gtk(pWin, szMessage); +#else + printf("WARNING - Not implemented: alert"); +#endif + return Val_unit; +} } diff --git a/src/Native/dialog_gtk.c b/src/Native/dialog_gtk.c new file mode 100644 index 000000000..431cc210d --- /dev/null +++ b/src/Native/dialog_gtk.c @@ -0,0 +1,33 @@ +#ifdef __linux__ +#include + +// The callback to g_signal_connect MUST be an `activate` function +static void activate(GtkApplication *app, const char *user_data) { + GtkWidget *dialog; + + GtkDialogFlags flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT; + dialog = gtk_message_dialog_new(NULL, flags, GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, user_data); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); +} + +void revery_alert_gtk(void *pWin, const char *szMessage) { + /* + * TODO: + * 1. figure out how to convert the pointer from an X11 window handle + * to a GTK window, see (for inspiration): + * https://gist.github.com/mmozeiko/2401933b1fa89e5d5bd238b33eab0465 + * + * 2. Get reference to revery application, is there an existing + * gtk application reference when a glfw window is created that can be reused? + */ + GtkApplication *app; + app = gtk_application_new("org.gtk.revery", G_APPLICATION_FLAGS_NONE); + g_signal_connect(app, "activate", G_CALLBACK(activate), (gpointer)szMessage); + /* argv the final argument to run can be set to NULL in which case argc should + * be set to 0 */ + g_application_run(G_APPLICATION(app), 0, NULL); + g_object_unref(app); +} +#endif diff --git a/src/Native/dune b/src/Native/dune index 590349d04..ca6ed56f4 100644 --- a/src/Native/dune +++ b/src/Native/dune @@ -4,12 +4,13 @@ (preprocess (pps lwt_ppx)) (library_flags (:include flags.sexp)) (js_of_ocaml (javascript_files dialog.js)) - (c_names dialog_cocoa dialog_win32) + (c_names dialog_cocoa dialog_win32 dialog_gtk) (cxx_names dialog) (c_flags (:include c_flags.sexp)) + (c_library_flags (:include c_library_flags.sexp)) (libraries reglfw)) (rule -(targets c_flags.sexp flags.sexp) +(targets flags.sexp c_flags.sexp c_library_flags.sexp) (deps (:discover config/discover.exe)) (action (run %{discover})))