Added cffi/* module for third-party advanced modules
parent
6ae354f564
commit
088ca6b963
|
@ -1,39 +0,0 @@
|
||||||
#include <gtk/gtk.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
GtkContainer* root;
|
|
||||||
GtkBox* container;
|
|
||||||
GtkLabel* label;
|
|
||||||
GtkButton* button;
|
|
||||||
} Instance;
|
|
||||||
|
|
||||||
//
|
|
||||||
const size_t wbcabi_version = 1;
|
|
||||||
|
|
||||||
void onclicked() { printf("You clicked the button\n"); }
|
|
||||||
|
|
||||||
void* wbcabi_init(GtkContainer* root) {
|
|
||||||
// Allocate the instance object
|
|
||||||
Instance* inst = malloc(sizeof(Instance));
|
|
||||||
inst->root = root;
|
|
||||||
|
|
||||||
// Add a container for displaying the next widgets
|
|
||||||
inst->container = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5));
|
|
||||||
gtk_container_add(GTK_CONTAINER(inst->root), GTK_WIDGET(inst->container));
|
|
||||||
|
|
||||||
// Add a label
|
|
||||||
inst->label = GTK_LABEL(gtk_label_new("This is a button:"));
|
|
||||||
gtk_container_add(GTK_CONTAINER(inst->container), GTK_WIDGET(inst->label));
|
|
||||||
|
|
||||||
// Add a button
|
|
||||||
inst->button = GTK_BUTTON(gtk_button_new_with_label("click me !"));
|
|
||||||
g_signal_connect(inst->button, "clicked", G_CALLBACK(onclicked), NULL);
|
|
||||||
gtk_container_add(GTK_CONTAINER(inst->container), GTK_WIDGET(inst->button));
|
|
||||||
|
|
||||||
// Return instance object
|
|
||||||
return inst;
|
|
||||||
}
|
|
||||||
void wbcabi_deinit(void* instance) { free(instance); }
|
|
||||||
|
|
||||||
char* wbcabi_last_error_str(void* instance) { return NULL; }
|
|
|
@ -1,21 +0,0 @@
|
||||||
project(
|
|
||||||
'waybar_cabi_c_example', 'c',
|
|
||||||
version: '0.1.0',
|
|
||||||
license: 'MIT',
|
|
||||||
)
|
|
||||||
|
|
||||||
compiler = meson.get_compiler('c')
|
|
||||||
|
|
||||||
|
|
||||||
shared_library('waybar_cabi_c_example',
|
|
||||||
[
|
|
||||||
'main.c',
|
|
||||||
],
|
|
||||||
dependencies: [
|
|
||||||
dependency('gtk+-3.0', version : ['>=3.22.0'])
|
|
||||||
]
|
|
||||||
# include_directories: include_directories(['../../../include']),
|
|
||||||
# dependencies: [],
|
|
||||||
# install: true,
|
|
||||||
# install_dir: 'plugins',
|
|
||||||
)
|
|
|
@ -91,7 +91,7 @@
|
||||||
#include "modules/cava.hpp"
|
#include "modules/cava.hpp"
|
||||||
#endif
|
#endif
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "modules/cabi.hpp"
|
#include "modules/cffi.hpp"
|
||||||
#include "modules/custom.hpp"
|
#include "modules/custom.hpp"
|
||||||
#include "modules/image.hpp"
|
#include "modules/image.hpp"
|
||||||
#include "modules/temperature.hpp"
|
#include "modules/temperature.hpp"
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <fmt/format.h>
|
|
||||||
|
|
||||||
#include <csignal>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "AModule.hpp"
|
|
||||||
#include "util/command.hpp"
|
|
||||||
#include "util/json.hpp"
|
|
||||||
#include "util/sleeper_thread.hpp"
|
|
||||||
|
|
||||||
namespace waybar::modules {
|
|
||||||
|
|
||||||
class CABI : public AModule {
|
|
||||||
public:
|
|
||||||
CABI(const std::string&, const std::string&, const Json::Value&);
|
|
||||||
virtual ~CABI();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void* cabi_instance_ = nullptr;
|
|
||||||
|
|
||||||
std::function<void*(GtkContainer*)> wbcabi_init_ = nullptr;
|
|
||||||
std::function<void(void*)> wbcabi_deinit_ = [](void*) {};
|
|
||||||
std::function<const char*(void*)> wbcabi_last_error_str_ = [](void*) { return nullptr; };
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace waybar::modules
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "AModule.hpp"
|
||||||
|
#include "util/command.hpp"
|
||||||
|
#include "util/json.hpp"
|
||||||
|
#include "util/sleeper_thread.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules {
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
// C ABI representation of a config key/value pair
|
||||||
|
struct wbcffi_config_entry {
|
||||||
|
const char* key;
|
||||||
|
const char* value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class CFFI : public AModule {
|
||||||
|
public:
|
||||||
|
CFFI(const std::string&, const std::string&, const Json::Value&);
|
||||||
|
virtual ~CFFI();
|
||||||
|
|
||||||
|
// virtual auto update() -> void override;
|
||||||
|
// virtual operator Gtk::Widget&() override;
|
||||||
|
|
||||||
|
virtual auto refresh(int signal) -> void override;
|
||||||
|
virtual auto doAction(const std::string& name) -> void override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
///
|
||||||
|
void* cffi_instance_ = nullptr;
|
||||||
|
|
||||||
|
typedef void*(InitFn)(GtkContainer*, const struct wbcffi_config_entry* config_entries,
|
||||||
|
size_t config_entries_len);
|
||||||
|
typedef void(DenitFn)(void* instance);
|
||||||
|
typedef void(RefreshFn)(void* instance, int signal);
|
||||||
|
typedef void(DoActionFn)(void* instance, const char* name);
|
||||||
|
|
||||||
|
// FFI hooks
|
||||||
|
struct {
|
||||||
|
std::function<InitFn> init = nullptr;
|
||||||
|
std::function<DenitFn> deinit = nullptr;
|
||||||
|
std::function<RefreshFn> refresh = [](void*, int) {};
|
||||||
|
std::function<DoActionFn> doAction = [](void*, const char*) {};
|
||||||
|
} hooks_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules
|
|
@ -190,7 +190,7 @@ if is_linux
|
||||||
add_project_arguments('-DHAVE_MEMORY_LINUX', language: 'cpp')
|
add_project_arguments('-DHAVE_MEMORY_LINUX', language: 'cpp')
|
||||||
src_files += files(
|
src_files += files(
|
||||||
'src/modules/battery.cpp',
|
'src/modules/battery.cpp',
|
||||||
'src/modules/cabi.cpp',
|
'src/modules/cffi.cpp',
|
||||||
'src/modules/cpu.cpp',
|
'src/modules/cpu.cpp',
|
||||||
'src/modules/cpu_frequency/common.cpp',
|
'src/modules/cpu_frequency/common.cpp',
|
||||||
'src/modules/cpu_frequency/linux.cpp',
|
'src/modules/cpu_frequency/linux.cpp',
|
||||||
|
@ -203,7 +203,7 @@ elif is_dragonfly or is_freebsd or is_netbsd or is_openbsd
|
||||||
add_project_arguments('-DHAVE_CPU_BSD', language: 'cpp')
|
add_project_arguments('-DHAVE_CPU_BSD', language: 'cpp')
|
||||||
add_project_arguments('-DHAVE_MEMORY_BSD', language: 'cpp')
|
add_project_arguments('-DHAVE_MEMORY_BSD', language: 'cpp')
|
||||||
src_files += files(
|
src_files += files(
|
||||||
'src/modules/cabi.cpp',
|
'src/modules/cffi.cpp',
|
||||||
'src/modules/cpu.cpp',
|
'src/modules/cpu.cpp',
|
||||||
'src/modules/cpu_frequency/bsd.cpp',
|
'src/modules/cpu_frequency/bsd.cpp',
|
||||||
'src/modules/cpu_frequency/common.cpp',
|
'src/modules/cpu_frequency/common.cpp',
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
.cache/
|
|
@ -0,0 +1,35 @@
|
||||||
|
# C FFI module
|
||||||
|
|
||||||
|
A C FFI module is a dynamic library that exposes standard C functions and
|
||||||
|
constants, that Waybar can load and execute to create custom advanced widgets.
|
||||||
|
|
||||||
|
Most language can implement the required functions and constants (C, C++, Rust,
|
||||||
|
Go, Python, ...), meaning you can develop custom modules using your language of
|
||||||
|
choice, as long as there's GTK bindings.
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
## Building this module
|
||||||
|
|
||||||
|
```bash
|
||||||
|
meson setup build
|
||||||
|
meson compile -C build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Load the module
|
||||||
|
|
||||||
|
Edit your waybar config:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
"modules-center": [
|
||||||
|
// ...
|
||||||
|
"cffi/c_example"
|
||||||
|
],
|
||||||
|
// ...
|
||||||
|
"cffi/c_example": {
|
||||||
|
// Path to the compiled dynamic library file
|
||||||
|
"module_path": "resources/custom_modules/cffi_example/build/wb_cffi_example.so"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
|
@ -0,0 +1,63 @@
|
||||||
|
|
||||||
|
#include "waybar_cffi_module.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GtkContainer* root;
|
||||||
|
GtkBox* container;
|
||||||
|
GtkButton* button;
|
||||||
|
} Instance;
|
||||||
|
|
||||||
|
// This static variable is shared between all instances of this module
|
||||||
|
static int instance_count = 0;
|
||||||
|
|
||||||
|
void onclicked(GtkButton* button) {
|
||||||
|
char text[256];
|
||||||
|
snprintf(text, 256, "Dice throw result: %d", rand() % 6 + 1);
|
||||||
|
gtk_button_set_label(button, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// You must
|
||||||
|
const size_t wbcffi_version = 1;
|
||||||
|
|
||||||
|
void* wbcffi_init(GtkContainer* root, const struct wbcffi_config_entry* config_entries,
|
||||||
|
size_t config_entries_len) {
|
||||||
|
printf("cffi_example: init config:\n");
|
||||||
|
for (size_t i = 0; i < config_entries_len; i++) {
|
||||||
|
printf(" %s = %s\n", config_entries[i].key, config_entries[i].value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate the instance object
|
||||||
|
Instance* inst = malloc(sizeof(Instance));
|
||||||
|
inst->root = root;
|
||||||
|
|
||||||
|
// Add a container for displaying the next widgets
|
||||||
|
inst->container = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5));
|
||||||
|
gtk_container_add(GTK_CONTAINER(inst->root), GTK_WIDGET(inst->container));
|
||||||
|
|
||||||
|
// Add a label
|
||||||
|
GtkLabel* label = GTK_LABEL(gtk_label_new("[Example C FFI Module:"));
|
||||||
|
gtk_container_add(GTK_CONTAINER(inst->container), GTK_WIDGET(label));
|
||||||
|
|
||||||
|
// Add a button
|
||||||
|
inst->button = GTK_BUTTON(gtk_button_new_with_label("click me !"));
|
||||||
|
g_signal_connect(inst->button, "clicked", G_CALLBACK(onclicked), NULL);
|
||||||
|
gtk_container_add(GTK_CONTAINER(inst->container), GTK_WIDGET(inst->button));
|
||||||
|
|
||||||
|
// Add a label
|
||||||
|
label = GTK_LABEL(gtk_label_new("]"));
|
||||||
|
gtk_container_add(GTK_CONTAINER(inst->container), GTK_WIDGET(label));
|
||||||
|
|
||||||
|
// Return instance object
|
||||||
|
printf("cffi_example inst=%p: init success ! (%d total instances)\n", inst, ++instance_count);
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
void wbcffi_deinit(void* instance) {
|
||||||
|
printf("cffi_example inst=%p: free memory\n", instance);
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
void wbcffi_refresh(void* instance, int signal) {
|
||||||
|
printf("cffi_example inst=%p: Received refresh signal %d\n", instance, signal);
|
||||||
|
}
|
||||||
|
void wbcffi_doaction(void* instance, const char* name) {
|
||||||
|
printf("cffi_example inst=%p: doAction(%s)\n", instance, name);
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
project(
|
||||||
|
'waybar_cffi_example', 'c',
|
||||||
|
version: '0.1.0',
|
||||||
|
license: 'MIT',
|
||||||
|
)
|
||||||
|
|
||||||
|
shared_library('wb_cffi_example',
|
||||||
|
['main.c'],
|
||||||
|
dependencies: [
|
||||||
|
dependency('gtk+-3.0', version : ['>=3.22.0'])
|
||||||
|
],
|
||||||
|
name_prefix: ''
|
||||||
|
)
|
|
@ -0,0 +1,59 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Waybar ABI version. 1 is the latest version
|
||||||
|
extern const size_t wbcffi_version;
|
||||||
|
|
||||||
|
/// Config key-value pair
|
||||||
|
struct wbcffi_config_entry {
|
||||||
|
/// Entry key
|
||||||
|
const char* key;
|
||||||
|
/// Entry value as string. JSON object and arrays are serialized.
|
||||||
|
const char* value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Module init/new function, called on module instantiation
|
||||||
|
///
|
||||||
|
/// MANDATORY CFFI function
|
||||||
|
///
|
||||||
|
/// @param root_widget Root GTK widget instantiated by Waybar
|
||||||
|
/// @param config_entries Flat representation of the module JSON config. The data only available
|
||||||
|
/// during wbcffi_init call.
|
||||||
|
/// @param config_entries_len Number of entries in `config_entries`
|
||||||
|
///
|
||||||
|
/// @return A untyped pointer to module data, NULL if the module failed to load.
|
||||||
|
void* wbcffi_init(GtkContainer* root_widget, const struct wbcffi_config_entry* config_entries,
|
||||||
|
size_t config_entries_len);
|
||||||
|
|
||||||
|
/// Module deinit/delete function, called when Waybar is closed or when the module is removed
|
||||||
|
///
|
||||||
|
/// MANDATORY CFFI function
|
||||||
|
///
|
||||||
|
/// @param instance Module instance data (as returned by `wbcffi_init`)
|
||||||
|
void wbcffi_deinit(void* instance);
|
||||||
|
|
||||||
|
/// When Waybar receives a POSIX signal, it forwards the signal to each module, calling this
|
||||||
|
/// function
|
||||||
|
///
|
||||||
|
/// Optional CFFI function
|
||||||
|
///
|
||||||
|
/// @param instance Module instance data (as returned by `wbcffi_init`)
|
||||||
|
/// @param signal Signal ID
|
||||||
|
void wbcffi_refresh(void* instance, int signal);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Optional CFFI function
|
||||||
|
///
|
||||||
|
/// @param instance Module instance data (as returned by `wbcffi_init`)
|
||||||
|
/// @param name Action name
|
||||||
|
void wbcffi_doaction(void* instance, const char* name);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -201,8 +201,8 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
||||||
if (ref.compare(0, 7, "custom/") == 0 && ref.size() > 7) {
|
if (ref.compare(0, 7, "custom/") == 0 && ref.size() > 7) {
|
||||||
return new waybar::modules::Custom(ref.substr(7), id, config_[name]);
|
return new waybar::modules::Custom(ref.substr(7), id, config_[name]);
|
||||||
}
|
}
|
||||||
if (ref.compare(0, 5, "cabi/") == 0 && ref.size() > 5) {
|
if (ref.compare(0, 5, "cffi/") == 0 && ref.size() > 5) {
|
||||||
return new waybar::modules::CABI(ref.substr(5), id, config_[name]);
|
return new waybar::modules::CFFI(ref.substr(5), id, config_[name]);
|
||||||
}
|
}
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
auto err = fmt::format("Disabling module \"{}\", {}", name, e.what());
|
auto err = fmt::format("Disabling module \"{}\", {}", name, e.what());
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
#include "modules/cabi.hpp"
|
|
||||||
|
|
||||||
#include <dlfcn.h>
|
|
||||||
|
|
||||||
namespace waybar::modules {
|
|
||||||
|
|
||||||
CABI::CABI(const std::string& name, const std::string& id, const Json::Value& config)
|
|
||||||
: AModule(config, name, id, true, true) {
|
|
||||||
const auto dynlib_path = config_["path"].asString();
|
|
||||||
|
|
||||||
void* handle = dlopen(dynlib_path.c_str(), RTLD_LAZY);
|
|
||||||
if (handle == nullptr) {
|
|
||||||
throw std::runtime_error{dlerror()};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch ABI version
|
|
||||||
auto wbcabi_version = reinterpret_cast<size_t*>(dlsym(handle, "wbcabi_version"));
|
|
||||||
if (wbcabi_version == nullptr) {
|
|
||||||
throw std::runtime_error{"Missing wbcabi_version"};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch functions
|
|
||||||
if (*wbcabi_version == 1) {
|
|
||||||
wbcabi_init_ = reinterpret_cast<void* (*)(GtkContainer*)>(dlsym(handle, "wbcabi_init"));
|
|
||||||
if (wbcabi_init_ == nullptr) {
|
|
||||||
throw std::runtime_error{"Missing wbcabi_init function"};
|
|
||||||
}
|
|
||||||
if (auto fn = reinterpret_cast<void (*)(void*)>(dlsym(handle, "wbcabi_deinit")))
|
|
||||||
wbcabi_deinit_ = fn;
|
|
||||||
if (auto fn = reinterpret_cast<const char* (*)(void*)>(dlsym(handle, "wbcabi_last_error_str")))
|
|
||||||
wbcabi_last_error_str_ = fn;
|
|
||||||
} else {
|
|
||||||
throw std::runtime_error{"Unknown wbcabi_version " + std::to_string(*wbcabi_version)};
|
|
||||||
}
|
|
||||||
|
|
||||||
cabi_instance_ = wbcabi_init_(dynamic_cast<Gtk::Container*>(&event_box_)->gobj());
|
|
||||||
if (cabi_instance_ == nullptr) {
|
|
||||||
const auto err_str = wbcabi_last_error_str_(cabi_instance_);
|
|
||||||
throw std::runtime_error{std::string{"Failed to initialize C ABI plugin: "} +
|
|
||||||
(err_str != nullptr ? err_str : "unknown error")};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CABI::~CABI() {
|
|
||||||
if (cabi_instance_ != nullptr) {
|
|
||||||
wbcabi_deinit_(cabi_instance_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace waybar::modules
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
#include "modules/cffi.hpp"
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <json/value.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace waybar::modules {
|
||||||
|
|
||||||
|
CFFI::CFFI(const std::string& name, const std::string& id, const Json::Value& config)
|
||||||
|
: AModule(config, name, id, true, true) {
|
||||||
|
const auto dynlib_path = config_["module_path"].asString();
|
||||||
|
if (dynlib_path.empty()) {
|
||||||
|
throw std::runtime_error{"Missing or empty 'module_path' in module config"};
|
||||||
|
}
|
||||||
|
|
||||||
|
void* handle = dlopen(dynlib_path.c_str(), RTLD_LAZY);
|
||||||
|
if (handle == nullptr) {
|
||||||
|
throw std::runtime_error{std::string{"Failed to load CFFI module: "} + dlerror()};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch ABI version
|
||||||
|
auto wbcffi_version = reinterpret_cast<size_t*>(dlsym(handle, "wbcffi_version"));
|
||||||
|
if (wbcffi_version == nullptr) {
|
||||||
|
throw std::runtime_error{std::string{"Missing wbcffi_version function: "} + dlerror()};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch functions
|
||||||
|
if (*wbcffi_version == 1) {
|
||||||
|
// Mandatory functions
|
||||||
|
hooks_.init = reinterpret_cast<InitFn*>(dlsym(handle, "wbcffi_init"));
|
||||||
|
if (!hooks_.init) {
|
||||||
|
throw std::runtime_error{std::string{"Missing wbcffi_init function: "} + dlerror()};
|
||||||
|
}
|
||||||
|
hooks_.deinit = reinterpret_cast<DenitFn*>(dlsym(handle, "wbcffi_deinit"));
|
||||||
|
if (!hooks_.init) {
|
||||||
|
throw std::runtime_error{std::string{"Missing wbcffi_deinit function: "} + dlerror()};
|
||||||
|
}
|
||||||
|
// Optional functions
|
||||||
|
if (auto fn = reinterpret_cast<RefreshFn*>(dlsym(handle, "wbcffi_refresh"))) {
|
||||||
|
hooks_.refresh = fn;
|
||||||
|
}
|
||||||
|
if (auto fn = reinterpret_cast<DoActionFn*>(dlsym(handle, "wbcffi_doaction"))) {
|
||||||
|
hooks_.doAction = fn;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error{"Unknown wbcffi_version " + std::to_string(*wbcffi_version)};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare init() arguments
|
||||||
|
// Convert JSON values to string
|
||||||
|
std::vector<std::string> config_entries_stringstor;
|
||||||
|
const auto& keys = config.getMemberNames();
|
||||||
|
for (size_t i = 0; i < keys.size(); i++) {
|
||||||
|
const auto& value = config[keys[i]];
|
||||||
|
if (value.isConvertibleTo(Json::ValueType::stringValue)) {
|
||||||
|
config_entries_stringstor.push_back(config[keys[i]].asString());
|
||||||
|
} else {
|
||||||
|
config_entries_stringstor.push_back(config[keys[i]].toStyledString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare config_entries array
|
||||||
|
std::vector<struct wbcffi_config_entry> config_entries;
|
||||||
|
for (size_t i = 0; i < keys.size(); i++) {
|
||||||
|
config_entries.push_back(
|
||||||
|
wbcffi_config_entry{keys[i].c_str(), config_entries_stringstor[i].c_str()});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call init
|
||||||
|
cffi_instance_ = hooks_.init(dynamic_cast<Gtk::Container*>(&event_box_)->gobj(),
|
||||||
|
config_entries.data(), config_entries.size());
|
||||||
|
|
||||||
|
// Handle init failures
|
||||||
|
if (cffi_instance_ == nullptr) {
|
||||||
|
throw std::runtime_error{"Failed to initialize C ABI module"};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CFFI::~CFFI() {
|
||||||
|
if (cffi_instance_ != nullptr) {
|
||||||
|
hooks_.deinit(cffi_instance_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto CFFI::refresh(int signal) -> void {
|
||||||
|
assert(cffi_instance_ != nullptr);
|
||||||
|
hooks_.refresh(cffi_instance_, signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto CFFI::doAction(const std::string& name) -> void {
|
||||||
|
assert(cffi_instance_ != nullptr);
|
||||||
|
if (!name.empty()) {
|
||||||
|
// TODO: Make a decision
|
||||||
|
// Calling AModule::doAction and hooks_.doAction will execute the action twice if it is
|
||||||
|
// configured in AModule::eventActionMap_ and implemented in the CFFI module.
|
||||||
|
//
|
||||||
|
// Should we block AModule::doAction() if the action is implemented in hooks_.doAction() ?
|
||||||
|
// (doAction could return true if the action has been processed)
|
||||||
|
//
|
||||||
|
hooks_.doAction(cffi_instance_, name.c_str());
|
||||||
|
AModule::doAction(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules
|
Loading…
Reference in New Issue