diff --git a/.gitignore b/.gitignore index df797ae..40579c1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build/* -.DS_Store \ No newline at end of file +.DS_Store +src/rsrc.hpp \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index e13c472..db1e3c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,11 @@ cmake_minimum_required (VERSION 3.8) +include("cmake/create_resources.cmake") if(APPLE) project ("globalRPC" LANGUAGES C CXX OBJCXX) else() project ("globalRPC" LANGUAGES C CXX) endif() +create_resources("rsrc" "src/rsrc.hpp") file(GLOB_RECURSE SOURCES "src/*.cpp") add_executable (rpc ${SOURCES}) set_property(TARGET rpc PROPERTY CXX_STANDARD 20) diff --git a/cmake/create_resources.cmake b/cmake/create_resources.cmake new file mode 100644 index 0000000..ba99d0a --- /dev/null +++ b/cmake/create_resources.cmake @@ -0,0 +1,11 @@ +function(create_resources dir output) + file(WRITE ${output} "") + file(GLOB bins ${dir}/*) + foreach(bin ${bins}) + string(REGEX MATCH "([^/]+)$" filename ${bin}) + string(REGEX REPLACE "\\.| |-" "_" filename ${filename}) + file(READ ${bin} filedata HEX) + string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," filedata ${filedata}) + file(APPEND ${output} "inline const unsigned char ${filename}[] = {${filedata}};\ninline const unsigned ${filename}_size = sizeof(${filename});\n") + endforeach() +endfunction() \ No newline at end of file diff --git a/rsrc/icon.png b/rsrc/icon.png new file mode 100644 index 0000000..3539f3f Binary files /dev/null and b/rsrc/icon.png differ diff --git a/src/main.cpp b/src/main.cpp index 098bcda..5b4b4ae 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,7 @@ #include +#include +#include +#include #include #include @@ -7,6 +10,7 @@ #include #include "backend.hpp" +#include "rsrc.hpp" #include "utils.hpp" std::string lastPlayingSong = ""; @@ -98,14 +102,48 @@ void handleMediaTasks() { Discord_UpdatePresence(&activity); } } +class MyTaskBarIcon : public wxTaskBarIcon { +public: + MyTaskBarIcon(wxFrame* mainFrame) : m_mainFrame(mainFrame) {} + + void OnMenuOpen(wxCommandEvent& evt) { m_mainFrame->Show(true); } + + void OnMenuExit(wxCommandEvent& evt) { m_mainFrame->Close(true); } + +protected: + virtual wxMenu* CreatePopupMenu() override { + wxMenu* menu = new wxMenu; + menu->Append(10001, "Open"); + menu->AppendSeparator(); + menu->Append(10002, "Quit"); + Bind(wxEVT_MENU, &MyTaskBarIcon::OnMenuOpen, this, 10001); + Bind(wxEVT_MENU, &MyTaskBarIcon::OnMenuExit, this, 10002); + return menu; + } + +private: + wxFrame* m_mainFrame; +}; class MyApp : public wxApp { public: virtual bool OnInit() override { + wxInitAllImageHandlers(); wxFrame* frame = new wxFrame(nullptr, wxID_ANY, "Hello wxWidgets", wxDefaultPosition, wxSize(400, 300)); + trayIcon = new MyTaskBarIcon(frame); + frame->Bind(wxEVT_CLOSE_WINDOW, [=](wxCloseEvent& event) { + trayIcon->RemoveIcon(); + trayIcon->Destroy(); + event.Skip(); + }); + wxIcon icon = utils::loadIconFromMemory(icon_png, icon_png_size); + trayIcon->SetIcon(icon, "My App"); wxStaticText* text = new wxStaticText(frame, wxID_ANY, "Hello World", wxPoint(150, 130)); frame->Show(true); return true; } + +private: + MyTaskBarIcon* trayIcon; }; wxIMPLEMENT_APP_NO_MAIN(MyApp); diff --git a/src/utils.hpp b/src/utils.hpp index 234ba0d..770c232 100644 --- a/src/utils.hpp +++ b/src/utils.hpp @@ -1,6 +1,8 @@ #ifndef _UTILS_ #define _UTILS_ #include +#include +#include #include #include @@ -13,6 +15,17 @@ #define CONFIG_FILENAME "known.json" namespace utils { + inline wxIcon loadIconFromMemory(const unsigned char* data, size_t size) { + wxMemoryInputStream stream(data, size); + wxImage img(stream, wxBITMAP_TYPE_PNG); + if (img.IsOk()) { + wxBitmap bmp(img); + wxIcon icon; + icon.CopyFromBitmap(bmp); + return icon; + } + return wxNullIcon; + } inline std::string ltrim(std::string& s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); return s;