roundabout,
created on Tuesday, 20 May 2025, 15:57:53 (1747756673),
received on Tuesday, 20 May 2025, 15:57:57 (1747756677)
Author identity: vlad <vlad.muntoiu@gmail.com>
f949af4edce315aaf269fdfec8c7ae914c493bcb
.gitignore
@@ -1 +1,2 @@
/cmake-build-debug/
/cmake-build-debug.bak/
CMakeLists.txt
@@ -2,8 +2,11 @@ cmake_minimum_required(VERSION 3.30)
project(gpanthera)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--export-dynamic")
add_library(gpanthera SHARED gpanthera.cc)
add_library(test_plugin SHARED test_plugin.cc)
add_executable(panthera-www panthera-www.cc)
target_link_libraries(panthera-www gpanthera)
@@ -15,7 +18,10 @@ pkg_check_modules(GTKMM REQUIRED gtkmm-4.0)
pkg_check_modules(WebKit REQUIRED webkitgtk-6.0)
find_package(nlohmann_json 3.10.0 REQUIRED)
include_directories(${GTKMM_INCLUDE_DIRS})
include_directories(
${GTKMM_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}
)
link_directories(${GTKMM_LIBRARY_DIRS})
include_directories(${WebKit_INCLUDE_DIRS})
panthera-www.cc
@@ -13,6 +13,10 @@
#include <nlohmann/json.hpp>
#include <iomanip>
#include <sstream>
#include <dlfcn.h>
#include "plugin_api.h"
using plugin_entrypoint_type = void(*)(void);
std::string url_encode(const std::string &value) {
// Thanks https://stackoverflow.com/a/17708801
@@ -44,7 +48,7 @@ struct SearchEngine {
if(pos == Glib::ustring::npos) {
throw std::runtime_error("Invalid search engine URL: missing '%s' placeholder");
}
auto new_url = url.substr(0, pos);
auto new_url = url;
new_url.replace(pos, 2, url_encode(query));
return new_url;
}
@@ -410,6 +414,24 @@ protected:
});
add_action(close_tab_action);
set_accels_for_action("app.close_tab", {"<Primary>W"});
// Load plugins
std::ifstream plugin_file_in("plugins.json");
if(plugin_file_in) {
std::string plugin_json((std::istreambuf_iterator<char>(plugin_file_in)), std::istreambuf_iterator<char>());
plugin_file_in.close();
auto json = nlohmann::json::parse(plugin_json);
for(auto &plugin : json) {
auto plugin_path = plugin["path"].get<std::string>();
load_plugin(plugin_path);
}
} else {
plugin_file_in.close();
auto empty_json = nlohmann::json::array();
std::ofstream plugin_file_out("plugins.json");
plugin_file_out << empty_json.dump(4);
plugin_file_out.close();
}
}
void on_activate() override {
@@ -439,10 +461,50 @@ public:
static Glib::RefPtr<PantheraWww> create() {
return Glib::make_refptr_for_instance<PantheraWww>(new PantheraWww());
}
std::shared_ptr<gPanthera::LayoutManager> get_layout_manager() {
return layout_manager;
}
std::shared_ptr<gPanthera::ContentManager> get_content_manager() {
return content_manager;
}
void load_plugin(const std::string &plugin_path) {
void *handle = dlopen(plugin_path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
if(!handle) {
std::cerr << "Failed to load plugin: " << dlerror() << std::endl;
return;
}
auto entrypoint = (plugin_entrypoint_type)dlsym(handle, "plugin_init");
if(!entrypoint) {
std::cerr << "Failed to find entrypoint in plugin: " << dlerror() << std::endl;
dlclose(handle);
return;
}
entrypoint();
}
};
Glib::RefPtr<PantheraWww> app = nullptr;
extern "C" {
void panthera_log(const char *message) {
std::cerr << message << std::endl;
}
void panthera_add_pane(const char *id, const char *label, GtkImage *icon, GtkWidget *pane) {
auto pane_child = Glib::wrap(pane);
auto icon_cc = Glib::wrap(icon);
auto label_cc = Glib::ustring(label);
auto id_cc = Glib::ustring(id);
auto new_pane = Gtk::make_managed<gPanthera::DockablePane>(app->get_layout_manager(), *pane_child, id_cc, label_cc, icon_cc);
app->get_layout_manager()->add_pane(new_pane);
}
}
int main(int argc, char *argv[]) {
gPanthera::init();
auto app = PantheraWww::create();
app = PantheraWww::create();
return app->run(argc, argv);
}
plugin_api.h
@@ -0,0 +1,15 @@
#ifndef PLUGIN_API_H
#define PLUGIN_API_H
#include <gtk/gtk.h>
#ifdef __cplusplus
extern "C" {
#endif
void panthera_add_pane(const char *id, const char *label, GtkImage *icon, GtkWidget *pane);
void panthera_log(const char *message);
#ifdef __cplusplus
}
#endif
#endif
test_plugin.cc
@@ -0,0 +1,5 @@
#include "plugin_api.h"
extern "C" void plugin_init() {
panthera_log("Plugin loaded");
}