diff --git a/xovi-ext/grimoire-injector/GrimoireInjector.cpp b/xovi-ext/grimoire-injector/GrimoireInjector.cpp index 7c7cc38..a3c8690 100644 --- a/xovi-ext/grimoire-injector/GrimoireInjector.cpp +++ b/xovi-ext/grimoire-injector/GrimoireInjector.cpp @@ -77,9 +77,31 @@ static void *watchThreadFunc(void *) { } const char *path = "/tmp/grimoire_strokes.json"; + const char *armedPath = "/tmp/grimoire_armed"; long long lastMod = 0; + int lastArmed = -1; while (true) { + /* Check armed state file */ + FILE *afp = fopen(armedPath, "r"); + if (afp) { + char abuf[16] = {0}; + if (fgets(abuf, sizeof(abuf), afp)) { + char *ap = abuf; + while (*ap == '"' || *ap == ' ' || *ap == '\t') ap++; + int val = atoi(ap); + if (val != lastArmed && g_instance) { + lastArmed = val; + int capturedVal = val; + QMetaObject::invokeMethod(g_instance, [capturedVal]() { + g_instance->setArmed(capturedVal != 0); + }, Qt::QueuedConnection); + grimoire_log("Armed state changed: %d", val); + } + } + fclose(afp); + } + /* Check for hot-reload signal */ if (grimoire_checkReload()) { fprintf(stderr, "[grimoire] Hot-reload signal received! Re-scanning...\n"); @@ -138,6 +160,20 @@ GrimoireInjector::GrimoireInjector(QObject *parent) fprintf(stderr, "[grimoire] Constructor done, watch thread spawned\n"); } +void GrimoireInjector::setArmed(bool armed) { + if (m_armed == armed) return; + m_armed = armed; + + /* Write state file so grimoired can see it */ + FILE *fp = fopen("/tmp/grimoire_armed", "w"); + if (fp) { + fprintf(fp, "%d\n", armed ? 1 : 0); + fclose(fp); + } + grimoire_log("setArmed(%d)", armed); + emit armedChanged(armed); +} + void GrimoireInjector::loadAndInject() { QFileInfo fi(m_watchPath); if (!fi.exists()) return; diff --git a/xovi-ext/grimoire-injector/GrimoireInjector.hpp b/xovi-ext/grimoire-injector/GrimoireInjector.hpp index 09c798d..a1cef1c 100644 --- a/xovi-ext/grimoire-injector/GrimoireInjector.hpp +++ b/xovi-ext/grimoire-injector/GrimoireInjector.hpp @@ -10,6 +10,7 @@ class GrimoireInjector : public QObject { Q_OBJECT + Q_PROPERTY(bool armed READ isArmed WRITE setArmed NOTIFY armedChanged) public: explicit GrimoireInjector(QObject *parent = nullptr); @@ -18,12 +19,19 @@ public: Q_INVOKABLE int itemCount() const { return m_items.size(); } Q_INVOKABLE bool isReady() const { return m_vtableReady; } + bool isArmed() const { return m_armed; } + void setArmed(bool armed); + +signals: + void armedChanged(bool armed); + public slots: void loadAndInject(); private: QList> m_items; bool m_vtableReady = false; + bool m_armed = false; QString m_watchPath = "/tmp/grimoire_strokes.json"; qint64 m_lastModTime = 0; }; diff --git a/xovi-ext/grimoire_toggle.qmd b/xovi-ext/grimoire_toggle.qmd new file mode 100644 index 0000000..ec306bd --- /dev/null +++ b/xovi-ext/grimoire_toggle.qmd @@ -0,0 +1,20 @@ +SLOT rmhConfigToggles INSERT { + property bool rmhGrimoireToggle: false +} END SLOT + +SLOT rmhShareToolFoldoutModel INSERT { + ~&425121728314878811&~.~&432643201877711221&~ { + ~&5972374&~: rmhToggleGrimoire + ~&233748328658231&~: ~&7082020628281&~.rmhDocumentTogglesHack + ~&214632764553&~: ~&6504222003&~("Grimoire") + ~&8399601734642709923&~: "qrc:/ark/icons/open_book" + ~&15640708674084664669&~: ~&6504254477&~.~&15640708674084664669&~ + ~&8400129127120172259&~: ~&6504329801&~ + ~&7713561545874130&~: ~&7082020628281&~.rmhGrimoireToggle + ~&7081629735527&~.~&254529418434902000&~: ~&6504329801&~ + ~&254542236275632405&~: { + ~&7082020628281&~.rmhGrimoireToggle = !~&7082020628281&~.rmhGrimoireToggle; + ~&7082020628281&~.rmhWriteFile("file:///tmp/grimoire_armed", ~&7082020628281&~.rmhGrimoireToggle ? "1" : "0"); + } + } +} END SLOT diff --git a/xovi-ext/grimoired/grimoired.c b/xovi-ext/grimoired/grimoired.c index bfb4e40..89b109c 100644 --- a/xovi-ext/grimoired/grimoired.c +++ b/xovi-ext/grimoired/grimoired.c @@ -1115,10 +1115,13 @@ static void handle_command(const char *line) { static int read_armed_state(void) { FILE *fp = fopen(ARMED_PATH, "r"); if (!fp) return 0; - int val = 0; - fscanf(fp, "%d", &val); + char buf[16] = {0}; + if (!fgets(buf, sizeof(buf), fp)) { fclose(fp); return 0; } fclose(fp); - return val != 0; + /* Handle JSON-quoted values from rmhWriteFile ("1" or "0") */ + char *p = buf; + while (*p == '"' || *p == ' ' || *p == '\t') p++; + return atoi(p) != 0; } /* ─── main loop ──────────────────────────────────────────────────── */