1
0

Improved extensibility of nickel_setting, split browser stuff into nickel_browser action (closes #59) (#60)

* Split browser actions from nickel_extra into nickel_browser

* Improved extensibility of nickel_setting action

Instead of nickel_setting:<setting> for toggling a setting and
nickel_setting:<setting>:<bool> for setting it explicitly, use
nickel_setting:<action>:<setting>.
This commit is contained in:
Patrick Gaskin
2020-07-02 00:25:00 -04:00
committed by GitHub
parent 7019745ff7
commit cb2caff551
3 changed files with 146 additions and 145 deletions

33
res/doc
View File

@@ -29,6 +29,7 @@
# kfmon - triggers a kfmon action # kfmon - triggers a kfmon action
# nickel_setting - toggles a boolean setting # nickel_setting - toggles a boolean setting
# nickel_extras - opens one of the beta features # nickel_extras - opens one of the beta features
# nickel_browser - opens the browser
# nickel_misc - other stuff which isn't significant enough for its own category # nickel_misc - other stuff which isn't significant enough for its own category
# nickel_open - opens a view # nickel_open - opens a view
# nickel_wifi - controls wifi (note: it doesn't wait for it to connect or disconnect, neither does it check for success) # nickel_wifi - controls wifi (note: it doesn't wait for it to connect or disconnect, neither does it check for success)
@@ -46,27 +47,29 @@
# kfmon - the filename of the KFMon watched item to launch. # kfmon - the filename of the KFMon watched item to launch.
# This is actually the basename of the watch's filename as specified in its KFMon config (i.e., the png). # This is actually the basename of the watch's filename as specified in its KFMon config (i.e., the png).
# You can also check the output of the 'list' command via the kfmon-ipc tool. # You can also check the output of the 'list' command via the kfmon-ipc tool.
# nickel_setting - one of: # nickel_setting - <action>:<setting>
# invert - toggles FeatureSettings.InvertScreen # action if one of:
# invert:<value> - ^ same, but sets it to 'true'/'enabled'/'yes'/'on'/'1' or 'false'/'disabled'/'no'/'off'/'0' # toggle - toggles between true/false
# lockscreen - toggles PowerSettings.UnlockEnabled (4.12.12111+) # enable - sets to true
# lockscreen:<value> - ^ ... # disable - sets to false
# screenshots - toggles FeatureSettings.Screenshots # setting is one of:
# screenshots:<value> - ^ ... # invert - FeatureSettings.InvertScreen
# force_wifi - toggles DeveloperSettings.ForceWifiOn (note: the setting doesn't apply until you toggle WiFi) # lockscreen - PowerSettings.UnlockEnabled (4.12.12111+)
# force_wifi:<value> - ^ ... # screenshots - FeatureSettings.Screenshots
# force_wifi - DeveloperSettings.ForceWifiOn (note: the setting doesn't apply until you toggle WiFi)
# nickel_extras - the mimetype of the plugin, or one of: # nickel_extras - the mimetype of the plugin, or one of:
# web_browser - opens the web browser to the default homepage
# web_browser:<url> - opens the web browser to the specified URL
# web_browser:<url> <css> - opens the web browser to the specified URL and injects the specified CSS (which can contain spaces and colons) into all pages
# web_browser:modal - opens the web browser to the default homepage as a pop-up window
# web_browser:modal:<url> - see above
# web_browser:modal:<url> <css> - see above
# unblock_it # unblock_it
# sketch_pad # sketch_pad
# solitaire # solitaire
# sudoku # sudoku
# word_scramble # word_scramble
# nickel_browser - one of:
# - opens the web browser to the default homepage (note that the line should end with a colon even though the argument is blank)
# <url> - opens the web browser to the specified URL
# <url> <css> - opens the web browser to the specified URL and injects the specified CSS (which can contain spaces and colons) into all pages
# modal - opens the web browser to the default homepage as a pop-up window
# modal:<url> - see above
# modal:<url> <css> - see above
# nickel_misc - one of: # nickel_misc - one of:
# home - goes to the home screen # home - goes to the home screen
# force_usb_connection - forces a usb connection dialog to be shown # force_usb_connection - forces a usb connection dialog to be shown

View File

@@ -43,6 +43,7 @@ void nm_action_result_free(nm_action_result_t *res);
X(kfmon_id) \ X(kfmon_id) \
X(nickel_setting) \ X(nickel_setting) \
X(nickel_extras) \ X(nickel_extras) \
X(nickel_browser) \
X(nickel_misc) \ X(nickel_misc) \
X(nickel_open) \ X(nickel_open) \
X(nickel_wifi) \ X(nickel_wifi) \

View File

@@ -126,6 +126,26 @@ NM_ACTION_(nickel_open) {
NM_ACTION_(nickel_setting) { NM_ACTION_(nickel_setting) {
#define NM_ERR_RET nullptr #define NM_ERR_RET nullptr
enum {
mode_toggle,
mode_enable,
mode_disable,
} mode;
char *tmp1 = strdupa(arg); // strsep and strtrim will modify it
char *arg1 = strtrim(strsep(&tmp1, ":"));
char *arg2 = strtrim(tmp1);
NM_ASSERT(arg2, "could not find a : in the argument");
if (!strcmp(arg1, "toggle"))
mode = mode_toggle;
else if (!strcmp(arg1, "enable"))
mode = mode_enable;
else if (!strcmp(arg1, "disable"))
mode = mode_disable;
else
NM_RETURN_ERR("unknown action '%s' for nickel_setting: expected 'toggle', 'enable', or 'disable'", arg1);
//libnickel 4.6 * _ZN6Device16getCurrentDeviceEv //libnickel 4.6 * _ZN6Device16getCurrentDeviceEv
Device *(*Device_getCurrentDevice)(); Device *(*Device_getCurrentDevice)();
reinterpret_cast<void*&>(Device_getCurrentDevice) = dlsym(RTLD_DEFAULT, "_ZN6Device16getCurrentDeviceEv"); reinterpret_cast<void*&>(Device_getCurrentDevice) = dlsym(RTLD_DEFAULT, "_ZN6Device16getCurrentDeviceEv");
@@ -188,30 +208,15 @@ NM_ACTION_(nickel_setting) {
NM_ASSERT(Settings_vtable, "could not dlsym the vtable for Settings"); NM_ASSERT(Settings_vtable, "could not dlsym the vtable for Settings");
NM_ASSERT(vtable_ptr(settings) == vtable_target(Settings_vtable), "unexpected vtable layout (expected class to start with a pointer to 8 bytes into the vtable)"); NM_ASSERT(vtable_ptr(settings) == vtable_target(Settings_vtable), "unexpected vtable layout (expected class to start with a pointer to 8 bytes into the vtable)");
bool v = false; bool v = mode == mode_disable; // this gets inverted
char *tmp1 = strdupa(arg); // strsep and strtrim will modify it if (!strcmp(arg2, "invert") || !strcmp(arg2, "screenshots")) {
char *arg1 = strtrim(strsep(&tmp1, ":"));
char *arg2 = strtrim(tmp1);
if (arg2) {
// note: v gets inverted when setting the setting below
if (!strcmp(arg2, "true") || !strcmp(arg2, "enabled") || !strcmp(arg2, "yes") || !strcmp(arg2, "on") || !strcmp(arg2, "1")) {
v = false;
} else if (!strcmp(arg2, "false") || !strcmp(arg2, "disabled") || !strcmp(arg2, "no") || !strcmp(arg2, "off") || !strcmp(arg2, "0")) {
v = true;
} else {
NM_RETURN_ERR("invalid value '%s' for setting '%s', must be 'true'/'enabled'/'yes'/'on'/'1' or 'false'/'disabled'/'no'/'off'/'0' (arg: '%s')", arg2, arg1, arg);
}
}
if (!strcmp(arg1, "invert") || !strcmp(arg1, "screenshots")) {
//libnickel 4.6 * _ZTV15FeatureSettings //libnickel 4.6 * _ZTV15FeatureSettings
void *FeatureSettings_vtable = dlsym(RTLD_DEFAULT, "_ZTV15FeatureSettings"); void *FeatureSettings_vtable = dlsym(RTLD_DEFAULT, "_ZTV15FeatureSettings");
NM_ASSERT(FeatureSettings_vtable, "could not dlsym the vtable for FeatureSettings"); NM_ASSERT(FeatureSettings_vtable, "could not dlsym the vtable for FeatureSettings");
vtable_ptr(settings) = vtable_target(FeatureSettings_vtable); vtable_ptr(settings) = vtable_target(FeatureSettings_vtable);
if (!strcmp(arg1, "invert")) { if (!strcmp(arg2, "invert")) {
//libnickel 4.6 * _ZN15FeatureSettings12invertScreenEv //libnickel 4.6 * _ZN15FeatureSettings12invertScreenEv
bool (*FeatureSettings_invertScreen)(Settings*); bool (*FeatureSettings_invertScreen)(Settings*);
reinterpret_cast<void*&>(FeatureSettings_invertScreen) = dlsym(RTLD_DEFAULT, "_ZN15FeatureSettings12invertScreenEv"); reinterpret_cast<void*&>(FeatureSettings_invertScreen) = dlsym(RTLD_DEFAULT, "_ZN15FeatureSettings12invertScreenEv");
@@ -222,7 +227,7 @@ NM_ACTION_(nickel_setting) {
reinterpret_cast<void*&>(FeatureSettings_setInvertScreen) = dlsym(RTLD_DEFAULT, "_ZN15FeatureSettings15setInvertScreenEb"); reinterpret_cast<void*&>(FeatureSettings_setInvertScreen) = dlsym(RTLD_DEFAULT, "_ZN15FeatureSettings15setInvertScreenEb");
NM_ASSERT(FeatureSettings_setInvertScreen, "could not dlsym FeatureSettings::setInvertScreen"); NM_ASSERT(FeatureSettings_setInvertScreen, "could not dlsym FeatureSettings::setInvertScreen");
if (!arg2) { if (mode == mode_toggle) {
v = FeatureSettings_invertScreen(settings); v = FeatureSettings_invertScreen(settings);
vtable_ptr(settings) = vtable_target(FeatureSettings_vtable); vtable_ptr(settings) = vtable_target(FeatureSettings_vtable);
} }
@@ -237,8 +242,8 @@ NM_ACTION_(nickel_setting) {
NM_LOG("updating top-level window %p after invert", w); NM_LOG("updating top-level window %p after invert", w);
if (w) if (w)
w->update(); // TODO: figure out how to make it update _after_ the menu item redraws itself w->update(); // TODO: figure out how to make it update _after_ the menu item redraws itself
} else if (!strcmp(arg1, "screenshots")) { } else if (!strcmp(arg2, "screenshots")) {
if (!arg2) { if (mode == mode_toggle) {
QVariant v1 = Settings_getSetting(settings, QStringLiteral("Screenshots"), QVariant(false)); QVariant v1 = Settings_getSetting(settings, QStringLiteral("Screenshots"), QVariant(false));
vtable_ptr(settings) = vtable_target(FeatureSettings_vtable); vtable_ptr(settings) = vtable_target(FeatureSettings_vtable);
v = v1.toBool(); v = v1.toBool();
@@ -250,54 +255,50 @@ NM_ACTION_(nickel_setting) {
QVariant v2 = Settings_getSetting(settings, QStringLiteral("Screenshots"), QVariant(false)); QVariant v2 = Settings_getSetting(settings, QStringLiteral("Screenshots"), QVariant(false));
vtable_ptr(settings) = vtable_target(FeatureSettings_vtable); vtable_ptr(settings) = vtable_target(FeatureSettings_vtable);
} }
} else if (!strcmp(arg1, "lockscreen")) { } else if (!strcmp(arg2, "lockscreen")) {
void *PowerSettings_vtable = dlsym(RTLD_DEFAULT, "_ZTV13PowerSettings"); void *PowerSettings_vtable = dlsym(RTLD_DEFAULT, "_ZTV13PowerSettings");
NM_ASSERT(PowerSettings_vtable, "could not dlsym the vtable for PowerSettings"); NM_ASSERT(PowerSettings_vtable, "could not dlsym the vtable for PowerSettings");
vtable_ptr(settings) = vtable_target(PowerSettings_vtable); vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
if (!strcmp(arg1, "lockscreen")) { //libnickel 4.12.12111 * _ZN13PowerSettings16getUnlockEnabledEv
//libnickel 4.12.12111 * _ZN13PowerSettings16getUnlockEnabledEv bool (*PowerSettings__getUnlockEnabled)(Settings*);
bool (*PowerSettings__getUnlockEnabled)(Settings*); reinterpret_cast<void*&>(PowerSettings__getUnlockEnabled) = dlsym(RTLD_DEFAULT, "_ZN13PowerSettings16getUnlockEnabledEv");
reinterpret_cast<void*&>(PowerSettings__getUnlockEnabled) = dlsym(RTLD_DEFAULT, "_ZN13PowerSettings16getUnlockEnabledEv"); NM_ASSERT(PowerSettings__getUnlockEnabled, "could not dlsym PowerSettings::getUnlockEnabled");
NM_ASSERT(PowerSettings__getUnlockEnabled, "could not dlsym PowerSettings::getUnlockEnabled");
//libnickel 4.12.12111 * _ZN13PowerSettings16setUnlockEnabledEb //libnickel 4.12.12111 * _ZN13PowerSettings16setUnlockEnabledEb
bool (*PowerSettings__setUnlockEnabled)(Settings*, bool); bool (*PowerSettings__setUnlockEnabled)(Settings*, bool);
reinterpret_cast<void*&>(PowerSettings__setUnlockEnabled) = dlsym(RTLD_DEFAULT, "_ZN13PowerSettings16setUnlockEnabledEb"); reinterpret_cast<void*&>(PowerSettings__setUnlockEnabled) = dlsym(RTLD_DEFAULT, "_ZN13PowerSettings16setUnlockEnabledEb");
NM_ASSERT(PowerSettings__setUnlockEnabled, "could not dlsym PowerSettings::setUnlockEnabled"); NM_ASSERT(PowerSettings__setUnlockEnabled, "could not dlsym PowerSettings::setUnlockEnabled");
if (!arg2) { if (mode == mode_toggle) {
v = PowerSettings__getUnlockEnabled(settings); v = PowerSettings__getUnlockEnabled(settings);
vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
}
PowerSettings__setUnlockEnabled(settings, !v);
vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
NM_ASSERT(PowerSettings__getUnlockEnabled(settings) == !v, "failed to set setting");
vtable_ptr(settings) = vtable_target(PowerSettings_vtable); vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
} }
} else if (!strcmp(arg1, "force_wifi")) {
PowerSettings__setUnlockEnabled(settings, !v);
vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
NM_ASSERT(PowerSettings__getUnlockEnabled(settings) == !v, "failed to set setting");
vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
} else if (!strcmp(arg2, "force_wifi")) {
//libnickel 4.6 * _ZTV11DevSettings //libnickel 4.6 * _ZTV11DevSettings
void *PowerSettings_vtable = dlsym(RTLD_DEFAULT, "_ZTV11DevSettings"); void *PowerSettings_vtable = dlsym(RTLD_DEFAULT, "_ZTV11DevSettings");
NM_ASSERT(PowerSettings_vtable, "could not dlsym the vtable for DevSettings"); NM_ASSERT(PowerSettings_vtable, "could not dlsym the vtable for DevSettings");
vtable_ptr(settings) = vtable_target(PowerSettings_vtable); vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
if (!strcmp(arg1, "force_wifi")) { if (mode == mode_toggle) {
if (!arg2) { QVariant v1 = Settings_getSetting(settings, QStringLiteral("ForceWifiOn"), QVariant(false));
QVariant v1 = Settings_getSetting(settings, QStringLiteral("ForceWifiOn"), QVariant(false));
vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
v = v1.toBool();
}
Settings_saveSetting(settings, QStringLiteral("ForceWifiOn"), QVariant(!v), false);
vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
QVariant v2 = Settings_getSetting(settings, QStringLiteral("ForceWifiOn"), QVariant(false));
vtable_ptr(settings) = vtable_target(PowerSettings_vtable); vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
v = v1.toBool();
} }
Settings_saveSetting(settings, QStringLiteral("ForceWifiOn"), QVariant(!v), false);
vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
QVariant v2 = Settings_getSetting(settings, QStringLiteral("ForceWifiOn"), QVariant(false));
vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
} else { } else {
// TODO: more settings // TODO: more settings?
Settings_SettingsD(settings); Settings_SettingsD(settings);
NM_RETURN_ERR("unknown setting name '%s' (arg: '%s')", arg1, arg); NM_RETURN_ERR("unknown setting name '%s' (arg: '%s')", arg1, arg);
} }
@@ -307,7 +308,7 @@ NM_ACTION_(nickel_setting) {
Settings_SettingsD(settings); Settings_SettingsD(settings);
NM_RETURN_OK(strcmp(arg1, "invert") // invert is obvious NM_RETURN_OK(strcmp(arg2, "invert") // invert is obvious
? nm_action_result_toast("%s %s", v ? "disabled" : "enabled", arg1) ? nm_action_result_toast("%s %s", v ? "disabled" : "enabled", arg1)
: nm_action_result_silent()); : nm_action_result_silent());
#undef NM_ERR_RET #undef NM_ERR_RET
@@ -316,82 +317,6 @@ NM_ACTION_(nickel_setting) {
NM_ACTION_(nickel_extras) { NM_ACTION_(nickel_extras) {
#define NM_ERR_RET nullptr #define NM_ERR_RET nullptr
if (!strncmp(arg, "web_browser", 11)) {
bool modal;
QUrl *url;
QString *css;
if (!strcmp(arg, "web_browser")) {
modal = false;
url = new QUrl();
css = new QString("");
} else {
char *tmp1 = strdupa(arg); // strsep and strtrim will modify it
char *arg1 = strtrim(strsep(&tmp1, ":"));
char *arg2 = strtrim(tmp1);
if (!arg2 || strcmp(arg1, "web_browser"))
NM_RETURN_ERR("unknown beta feature name or plugin mimetype '%s' (split: '%s')", arg, arg1);
QString tmp = QString::fromUtf8(arg2).trimmed();
if (tmp.section(':', 0, 0).trimmed() == "modal") {
modal = true;
tmp = tmp.section(':', 1).trimmed();
} else {
modal = false;
}
if (tmp.contains(' ')) {
css = new QString(tmp.section(' ', 1).trimmed());
url = new QUrl(tmp.section(' ', 0, 0).trimmed(), QUrl::ParsingMode::StrictMode);
if (!url->isValid() || url->isRelative())
NM_RETURN_ERR("invalid url '%s' (argument: '%s') (note: if your url has spaces, they need to be escaped)", qPrintable(tmp.section(' ', 0, 0)), arg);
} else if (tmp.length()) {
url = new QUrl(tmp, QUrl::ParsingMode::StrictMode);
css = new QString("");
if (!url->isValid() || url->isRelative())
NM_RETURN_ERR("invalid url '%s' (argument: '%s') (note: if your url has spaces, they need to be escaped)", qPrintable(tmp.section(' ', 0, 0)), arg);
} else {
url = new QUrl();
css = new QString("");
}
}
NM_LOG("web browser '%s' (modal=%d, url='%s', css='%s')", arg, modal, url->isValid() ? qPrintable(url->toString()) : "(home)", qPrintable(*css));
//libnickel 4.6 * _ZN22BrowserWorkflowManager14sharedInstanceEv _ZN22BrowserWorkflowManagerC1EP7QObject
BrowserWorkflowManager *(*BrowserWorkflowManager_sharedInstance)();
void (*BrowserWorkflowManager_BrowserWorkflowManager)(BrowserWorkflowManager*, QObject*); // 4.11.11911+
reinterpret_cast<void*&>(BrowserWorkflowManager_sharedInstance) = dlsym(RTLD_DEFAULT, "_ZN22BrowserWorkflowManager14sharedInstanceEv");
reinterpret_cast<void*&>(BrowserWorkflowManager_BrowserWorkflowManager) = dlsym(RTLD_DEFAULT, "_ZN22BrowserWorkflowManagerC1EP7QObject");
NM_ASSERT(BrowserWorkflowManager_sharedInstance || BrowserWorkflowManager_BrowserWorkflowManager, "could not dlsym BrowserWorkflowManager constructor (4.11.11911+) or sharedInstance");
//libnickel 4.6 * _ZN22BrowserWorkflowManager11openBrowserEbRK4QUrlRK7QString
void (*BrowserWorkflowManager_openBrowser)(BrowserWorkflowManager*, bool, QUrl*, QString*); // the bool is whether to open it as a modal, the QUrl is the URL to load(if !QUrl::isValid(), it loads the homepage), the string is CSS to inject
reinterpret_cast<void*&>(BrowserWorkflowManager_openBrowser) = dlsym(RTLD_DEFAULT, "_ZN22BrowserWorkflowManager11openBrowserEbRK4QUrlRK7QString");
NM_ASSERT(BrowserWorkflowManager_openBrowser, "could not dlsym BrowserWorkflowManager::openBrowser");
// note: everything must be on the heap since if it isn't connected, it
// passes it as-is to the connected signal, which will be used
// after this action returns.
BrowserWorkflowManager *bwm;
if (BrowserWorkflowManager_BrowserWorkflowManager) {
bwm = calloc(1, 128); // as of 4.20.14622, it's actually 20 bytes, but we're going to stay on the safe side
NM_ASSERT(bwm, "could not allocate memory for BrowserWorkflowManager");
BrowserWorkflowManager_BrowserWorkflowManager(bwm, nullptr);
} else {
bwm = BrowserWorkflowManager_sharedInstance();
NM_ASSERT(bwm, "could not get shared browser workflow manager pointer");
}
BrowserWorkflowManager_openBrowser(bwm, modal, url, css);
NM_RETURN_OK(nm_action_result_silent());
}
const char* mimetype; const char* mimetype;
if (strchr(arg, '/')) mimetype = arg; if (strchr(arg, '/')) mimetype = arg;
else if (!strcmp(arg, "unblock_it")) mimetype = "application/x-games-RushHour"; else if (!strcmp(arg, "unblock_it")) mimetype = "application/x-games-RushHour";
@@ -411,6 +336,78 @@ NM_ACTION_(nickel_extras) {
#undef NM_ERR_RET #undef NM_ERR_RET
} }
NM_ACTION_(nickel_browser) {
#define NM_ERR_RET nullptr
bool modal;
QUrl *url;
QString *css;
if (!arg || !*arg) {
modal = false;
url = new QUrl();
css = new QString("");
} else {
QString tmp = QString::fromUtf8(arg).trimmed();
if (tmp.section(':', 0, 0).trimmed() == "modal") {
modal = true;
tmp = tmp.section(':', 1).trimmed();
} else {
modal = false;
}
if (tmp.contains(' ')) {
css = new QString(tmp.section(' ', 1).trimmed());
url = new QUrl(tmp.section(' ', 0, 0).trimmed(), QUrl::ParsingMode::StrictMode);
if (!url->isValid() || url->isRelative())
NM_RETURN_ERR("invalid url '%s' (argument: '%s') (note: if your url has spaces, they need to be escaped)", qPrintable(tmp.section(' ', 0, 0)), arg);
} else if (tmp.length()) {
url = new QUrl(tmp, QUrl::ParsingMode::StrictMode);
css = new QString("");
if (!url->isValid() || url->isRelative())
NM_RETURN_ERR("invalid url '%s' (argument: '%s') (note: if your url has spaces, they need to be escaped)", qPrintable(tmp.section(' ', 0, 0)), arg);
} else {
url = new QUrl();
css = new QString("");
}
}
NM_LOG("web browser '%s' (modal=%d, url='%s', css='%s')", arg, modal, url->isValid() ? qPrintable(url->toString()) : "(home)", qPrintable(*css));
//libnickel 4.6 * _ZN22BrowserWorkflowManager14sharedInstanceEv _ZN22BrowserWorkflowManagerC1EP7QObject
BrowserWorkflowManager *(*BrowserWorkflowManager_sharedInstance)();
void (*BrowserWorkflowManager_BrowserWorkflowManager)(BrowserWorkflowManager*, QObject*); // 4.11.11911+
reinterpret_cast<void*&>(BrowserWorkflowManager_sharedInstance) = dlsym(RTLD_DEFAULT, "_ZN22BrowserWorkflowManager14sharedInstanceEv");
reinterpret_cast<void*&>(BrowserWorkflowManager_BrowserWorkflowManager) = dlsym(RTLD_DEFAULT, "_ZN22BrowserWorkflowManagerC1EP7QObject");
NM_ASSERT(BrowserWorkflowManager_sharedInstance || BrowserWorkflowManager_BrowserWorkflowManager, "could not dlsym BrowserWorkflowManager constructor (4.11.11911+) or sharedInstance");
//libnickel 4.6 * _ZN22BrowserWorkflowManager11openBrowserEbRK4QUrlRK7QString
void (*BrowserWorkflowManager_openBrowser)(BrowserWorkflowManager*, bool, QUrl*, QString*); // the bool is whether to open it as a modal, the QUrl is the URL to load(if !QUrl::isValid(), it loads the homepage), the string is CSS to inject
reinterpret_cast<void*&>(BrowserWorkflowManager_openBrowser) = dlsym(RTLD_DEFAULT, "_ZN22BrowserWorkflowManager11openBrowserEbRK4QUrlRK7QString");
NM_ASSERT(BrowserWorkflowManager_openBrowser, "could not dlsym BrowserWorkflowManager::openBrowser");
// note: everything must be on the heap since if it isn't connected, it
// passes it as-is to the connected signal, which will be used
// after this action returns.
BrowserWorkflowManager *bwm;
if (BrowserWorkflowManager_BrowserWorkflowManager) {
bwm = calloc(1, 128); // as of 4.20.14622, it's actually 20 bytes, but we're going to stay on the safe side
NM_ASSERT(bwm, "could not allocate memory for BrowserWorkflowManager");
BrowserWorkflowManager_BrowserWorkflowManager(bwm, nullptr);
} else {
bwm = BrowserWorkflowManager_sharedInstance();
NM_ASSERT(bwm, "could not get shared browser workflow manager pointer");
}
BrowserWorkflowManager_openBrowser(bwm, modal, url, css);
NM_RETURN_OK(nm_action_result_silent());
#undef NM_ERR_RET
}
NM_ACTION_(nickel_misc) { NM_ACTION_(nickel_misc) {
#define NM_ERR_RET nullptr #define NM_ERR_RET nullptr
if (!strcmp(arg, "home")) { if (!strcmp(arg, "home")) {