Implemented adding menu items in hook
I still need to figure out why the PLT parsing is messed up on ARM.
This commit is contained in:
52
src/menu.cc
52
src/menu.cc
@@ -31,10 +31,55 @@ static QAction* (*AbstractNickelMenuController_createAction)(void*, QMenu*, QWid
|
|||||||
// a signal handler).
|
// a signal handler).
|
||||||
static void (*ConfirmationDialogFactory_showOKDialog)(QString const&, QString const&);
|
static void (*ConfirmationDialogFactory_showOKDialog)(QString const&, QString const&);
|
||||||
|
|
||||||
|
static nmi_menu_entry_t *_entries;
|
||||||
|
static size_t _entries_n;
|
||||||
|
|
||||||
extern "C" MenuTextItem* AbstractNickelMenuController_createMenuTextItem_hook(void* _this, QMenu* menu, QString const& label, bool checkable, bool checked, QString const& thingy) {
|
extern "C" MenuTextItem* AbstractNickelMenuController_createMenuTextItem_hook(void* _this, QMenu* menu, QString const& label, bool checkable, bool checked, QString const& thingy) {
|
||||||
NMI_LOG("AbstractNickelMenuController::createMenuTextItem(%p, `%s`, %d, %d, `%s`)", menu, qPrintable(label), checkable, checked, qPrintable(thingy));
|
NMI_LOG("AbstractNickelMenuController::createMenuTextItem(%p, `%s`, %d, %d, `%s`)", menu, qPrintable(label), checkable, checked, qPrintable(thingy));
|
||||||
|
|
||||||
// TODO: add items
|
// TODO: test on other locales
|
||||||
|
bool ismm, isrm;
|
||||||
|
if ((ismm = label == "Help" && !checkable))
|
||||||
|
NMI_LOG("Intercepting main menu (label=Help, checkable=false)...");
|
||||||
|
if ((isrm = label == "Dictionary" && !checkable))
|
||||||
|
NMI_LOG("Intercepting reader menu (label=Dictionary, checkable=false)...");
|
||||||
|
|
||||||
|
bool add[_entries_n];
|
||||||
|
for (size_t i = 0; i < _entries_n; i++) {
|
||||||
|
nmi_menu_entry_t *ent = &_entries[i];
|
||||||
|
switch (_entries[i].loc) {
|
||||||
|
case NMI_MENU_LOCATION_MAIN_MENU:
|
||||||
|
add[i] = ismm;
|
||||||
|
case NMI_MENU_LOCATION_READER_MENU:
|
||||||
|
add[i] = isrm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < _entries_n; i++) {
|
||||||
|
nmi_menu_entry_t *ent = &_entries[i];
|
||||||
|
if (add[i]) {
|
||||||
|
NMI_LOG("Adding item '%s'...", ent->lbl);
|
||||||
|
|
||||||
|
QString lbl(ent->lbl);
|
||||||
|
MenuTextItem* item = AbstractNickelMenuController_createMenuTextItem_orig(_this, menu, lbl, false, false, "");
|
||||||
|
QAction* action = AbstractNickelMenuController_createAction(_this, menu, item, true, true, false);
|
||||||
|
|
||||||
|
// note: we're capturing by value, i.e. the pointer to the global variable, rather then the stack variable, so this is safe
|
||||||
|
QObject::connect(action, &QAction::triggered, std::function<void(bool)>([ent](bool checked){
|
||||||
|
NMI_LOG("Item '%s' pressed...", ent->lbl);
|
||||||
|
char *err;
|
||||||
|
if (ent->execute(ent->arg, &err) && err) {
|
||||||
|
NMI_LOG("Got error %s, displaying...", err);
|
||||||
|
QString title("nickel-menu-inject");
|
||||||
|
QString text(err);
|
||||||
|
ConfirmationDialogFactory_showOKDialog(title, text);
|
||||||
|
free(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NMI_LOG("Success!", err);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return AbstractNickelMenuController_createMenuTextItem_orig(_this, menu, label, checkable, checked, thingy);
|
return AbstractNickelMenuController_createMenuTextItem_orig(_this, menu, label, checkable, checked, thingy);
|
||||||
}
|
}
|
||||||
@@ -53,7 +98,8 @@ extern "C" int nmi_menu_hook(void *libnickel, nmi_menu_entry_t *entries, size_t
|
|||||||
reinterpret_cast<void*&>(AbstractNickelMenuController_createMenuTextItem_orig) = nmi_dlhook(libnickel, "_ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_", reinterpret_cast<void*&>(AbstractNickelMenuController_createMenuTextItem_hook), &err);
|
reinterpret_cast<void*&>(AbstractNickelMenuController_createMenuTextItem_orig) = nmi_dlhook(libnickel, "_ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_", reinterpret_cast<void*&>(AbstractNickelMenuController_createMenuTextItem_hook), &err);
|
||||||
NMI_ASSERT(AbstractNickelMenuController_createMenuTextItem_orig, "failed to hook _ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_: %s", err);
|
NMI_ASSERT(AbstractNickelMenuController_createMenuTextItem_orig, "failed to hook _ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_: %s", err);
|
||||||
|
|
||||||
|
_entries = entries;
|
||||||
|
_entries_n = entries_n;
|
||||||
|
|
||||||
#undef NMI_ERR_RET
|
#undef NMI_ERR_RET
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
@@ -22,7 +22,7 @@ typedef struct {
|
|||||||
// and returns 0 on success, or 1 with err_out (if provided) set to the malloc'd
|
// and returns 0 on success, or 1 with err_out (if provided) set to the malloc'd
|
||||||
// error message on error. The provided configuration and all pointers it
|
// error message on error. The provided configuration and all pointers it
|
||||||
// references must remain valid for the lifetime of the program (i.e. not stack
|
// references must remain valid for the lifetime of the program (i.e. not stack
|
||||||
// allocated).
|
// allocated). It MUST NOT be called more than once.
|
||||||
int nmi_menu_hook(void *libnickel, nmi_menu_entry_t *entries, size_t entries_n, char **err_out);
|
int nmi_menu_hook(void *libnickel, nmi_menu_entry_t *entries, size_t entries_n, char **err_out);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
Reference in New Issue
Block a user