From 28f0fdb5208fe5c3b5bb77f3766b289d7d3fcec4 Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Wed, 26 Nov 2025 22:31:09 +0100 Subject: [PATCH] osx --- gtk-imports.c | 4 ++++ gtkloader.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++++- gtkloader.h | 2 ++ info_over_me.cpp | 21 ++++++++++++++++----- main.cpp | 14 ++++++++++---- yellownotes.cpp | 37 +++++++++++++++++++++++++++--------- yellownotes.h | 4 +++- 7 files changed, 111 insertions(+), 20 deletions(-) diff --git a/gtk-imports.c b/gtk-imports.c index bec745c..8565ec6 100644 --- a/gtk-imports.c +++ b/gtk-imports.c @@ -1,4 +1,8 @@ +#ifdef TARGET_OS_OSX +#include +#else #include +#endif #define GTK_DECLARE_FUNCS #include "gtk-imports.h" diff --git a/gtkloader.cpp b/gtkloader.cpp index 6685ef7..09ae5b8 100644 --- a/gtkloader.cpp +++ b/gtkloader.cpp @@ -11,7 +11,7 @@ extern "C" { #include #endif -#ifdef __linux +#if defined(__linux) || defined(TARGET_OS_OSX) #include #endif @@ -60,6 +60,33 @@ void GtkLoader::loadLibraryLinux(const char *lib, void **handle) #endif } +void GtkLoader::loadLibraryOSX(const char *lib, void **handle) +{ +#ifdef TARGET_OS_OSX + std::string full_lib_path = std::string("/opt/homebrew/lib/") + lib; + *handle = ::dlopen(full_lib_path.c_str(), RTLD_LAZY); + if (*handle == NULL) { + throw std::string("Cannot load library '") + lib + "'"; + } +#endif +} + +void GtkLoader::loadFunctionOSX(const char *func, void **func_ptr) +{ +#ifdef TARGET_OS_OSX + *func_ptr = nullptr; + std::list::const_iterator it = library_handles.begin(); + while(*func_ptr == nullptr && it != library_handles.end()) { + void *handle = *it; + *func_ptr = dlsym(handle, func); + it++; + } + if (*func_ptr == nullptr) { + throw std::string("Cannot load function '") + func; + } +#endif +} + void GtkLoader::loadFunctionWin64(const char *func, void **func_ptr) { #ifdef _WIN32 @@ -132,6 +159,23 @@ void GtkLoader::dlopen() loadLibraryLinux(libs[i], &lib); if (lib) { library_handles.push_back(lib); } } +#endif +#ifdef TARGET_OS_OSX + const char *libs[] = { + "libgtk-3.0.dylib", + "libgobject-2.0.dylib", + "libgio-2.0.dylib", + "libglib-2.0.dylib", + "libgdk-3.dylib", + "libgdk_pixbuf-2.0.dylib", + NULL + }; + int i; + for(i = 0; libs[i] != NULL; i++) { + void *lib; + loadLibraryOSX(libs[i], &lib); + if (lib) { library_handles.push_back(lib); } + } #endif } } @@ -144,6 +188,9 @@ void GtkLoader::loadFunction(const char *func, void **func_ptr) #ifdef __linux loadFunctionLinux(func, func_ptr); #endif +#ifdef TARGET_OS_OSX + loadFunctionOSX(func, func_ptr); +#endif } static void loader(const char *func, void **func_ptr, void *user_data) diff --git a/gtkloader.h b/gtkloader.h index 8cab61a..22a5c59 100644 --- a/gtkloader.h +++ b/gtkloader.h @@ -13,6 +13,8 @@ private: void loadFunctionWin64(const char *func, void **func_ptr); void loadLibraryLinux(const char *lib, void **handle); void loadFunctionLinux(const char *func, void **func_ptr); + void loadLibraryOSX(const char *lib, void **handle); + void loadFunctionOSX(const char *func, void **func_ptr); public: void dlopen(); diff --git a/info_over_me.cpp b/info_over_me.cpp index d3d2449..535afb5 100644 --- a/info_over_me.cpp +++ b/info_over_me.cpp @@ -3,7 +3,7 @@ #include "utils/whereami.h" #include -#ifdef __linux +#if defined(__linux) || defined(TARGET_OS_OSX) #include #endif @@ -15,6 +15,7 @@ extern "C" { #include "gtk-imports.h" } #include +#include std::string InfoOverMe::containingFolder() { @@ -24,15 +25,21 @@ std::string InfoOverMe::containingFolder() wai_getExecutablePath(path, len, NULL); path[len] = '\0'; - std::string p(path); - std::cout << p << std::endl; - return p; + std::filesystem::path p(path); + if (std::filesystem::is_regular_file(p)) { + std::filesystem::path pp = p.parent_path(); + std::cout << pp << std::endl; + return pp.string(); + } else { + std::cout << p << std::endl; + return p.string(); + } } std::string InfoOverMe::myHostname() { char buf[10240]; -#ifdef __linux +#if defined(__linux) || defined(TARGET_OS_OSX) int r = gethostname(buf, 10240); #endif #ifdef _WIN32 @@ -53,9 +60,13 @@ std::string InfoOverMe::myOsHostname() #else #ifdef _WIN32 os = "windows"; +#else +#ifdef TARGET_OS_OSX + os = "osx"; #else os = "unknown"; #endif +#endif #endif return os + "_" + myHostname(); } diff --git a/main.cpp b/main.cpp index 513696f..cfa4ab9 100644 --- a/main.cpp +++ b/main.cpp @@ -8,8 +8,11 @@ extern "C" { #include "yellownotes.h" #include "info_over_me.h" -SIGNAL(YellowNotes, on_tray_activate, popupTrayMenu) - +#ifndef TARGET_OS_OSX +SIGNAL(YellowNotes, on_tray_activate, popupTrayMenu); +#else +BSIGNAL2(YellowNotes, on_tray_btn, popupTrayMenuBtn, GdkEventButton); +#endif static void activate (GtkApplication* app, gpointer user_data) { GtkWidget *window; @@ -17,7 +20,11 @@ static void activate (GtkApplication* app, gpointer user_data) std::string img_file = notes->imageFile("yellownotes"); GtkStatusIcon *tray = gtk_status_icon_new_from_file(img_file.c_str()); +#ifdef TARGET_OS_OSX + g_signal_connect(tray, "button_press_event", on_tray_btn, notes); +#else g_signal_connect(tray, "activate", on_tray_activate, notes); +#endif } int main(int argc, char **argv) @@ -29,12 +36,11 @@ int main(int argc, char **argv) srand(time(NULL)); // seed with current time - std::string my_path = w.containingFolder(); - try { l.loadGtk(); } catch(std::string msg) { std::cerr << msg << std::endl; + exit(2); } GtkApplication *app; diff --git a/yellownotes.cpp b/yellownotes.cpp index 0c49479..5e797c9 100644 --- a/yellownotes.cpp +++ b/yellownotes.cpp @@ -4,7 +4,7 @@ #include #include -#ifdef __linux +#if defined(__linux) || defined(TARGET_OS_OSX) #include #include #include @@ -259,22 +259,31 @@ SIGNAL(YellowNotes, on_monitors_changed, monitorsChanged); std::string YellowNotes::imageFile(const char *name) { -#ifdef _WIN32 +#if defined(_WIN32) || defined(TARGET_OS_OSX) std::string ext = ".png"; #else std::string ext = ".svg"; #endif - return appDir() + "/" + name + ext; + + std::string file = name + ext; + std::string path1 = appDir() + "/images/" + file; + if (std::filesystem::is_regular_file(path1)) { + return path1; + } else { + std::string path2 = appDir() + "/../../" + file; + if (std::filesystem::is_regular_file(path2)) { + return path2; + } else { + std::cerr << "No such image file: " << path2 << std::endl; + throw std::string("No such image file: " + file); + } + } } std::string YellowNotes::appDir() { -#ifdef __linux - std::string base = "/home/hans/src/yellownotes"; -#endif -#ifdef _WIN32 - std::string base = "c:/devel/yellownotes"; -#endif + InfoOverMe info; + std::string base = info.containingFolder(); return base; } @@ -290,6 +299,11 @@ std::string YellowNotes::notesDir() snprintf(homedir, 10240, "%s%s", getenv("HOMEDRIVE"), getenv("HOMEPATH")); #endif +#ifdef TARGET_OS_OSX + struct passwd *pw = getpwuid(getuid()); + const char *homedir = pw->pw_dir; +#endif + std::string home_dir = homedir; std::string notes_dir = home_dir + "/yellownotes"; @@ -488,6 +502,11 @@ int YellowNotes::iconSize() return _font_size * 1.5; } +bool YellowNotes::popupTrayMenuBtn(void *sender, GdkEventButton *evt) +{ + popupTrayMenu(sender); + return true; +} void YellowNotes::popupTrayMenu(void *sender) { diff --git a/yellownotes.h b/yellownotes.h index 2a754d2..8affdeb 100644 --- a/yellownotes.h +++ b/yellownotes.h @@ -67,6 +67,7 @@ public: public: void popupTrayMenu(void *sender); + bool popupTrayMenuBtn(void *sender, GdkEventButton *evt); void newNote(void *sender); void showNotes(void *sender); void notesToDesktop(void *sender); @@ -113,6 +114,7 @@ public: static void func(GObject *obj, void *arg, gpointer user_data) { type *o = reinterpret_cast(user_data); o->member(obj, reinterpret_cast(arg)); } #define BSIGNAL2(type, func, member, argtype) \ - static gboolean func(GObject *obj, void *arg, gpointer user_data) { type *o = reinterpret_cast(user_data); return o->member(obj, reinterpret_cast(arg)); } + static gboolean func(GObject *obj, void *arg, gpointer user_data) { \ + type *o = reinterpret_cast(user_data); return o->member(obj, reinterpret_cast(arg)); } #endif // YELLOWNOTES_H