127 lines
6.2 KiB
C++
127 lines
6.2 KiB
C++
/* How the front end hands a tool to the engine.
|
|
*
|
|
* A tool implemented in C++ is an ordinary cst_tool_def_t: the engine owns a
|
|
* copy of the definition, so a static (or stack) value is enough, and
|
|
* `ud`/`run_ex` keep pointing at the front end's state. The callback runs on
|
|
* the turn's worker thread -- touch Qt objects only through queued signals.
|
|
*
|
|
* See app/src/platform/linux/NotifyTool.cpp for a worked example, and
|
|
* tests/test_embed.c for the same contract without Qt.
|
|
*/
|
|
|
|
#ifndef CST_APP_TOOLPROVIDER_H
|
|
#define CST_APP_TOOLPROVIDER_H
|
|
|
|
#include <QString>
|
|
|
|
#include "cst_tools.h"
|
|
|
|
/* The engine wrapper of the front end (core/AgentCore.h). Only a pointer
|
|
* travels through this header, so the class stays incomplete here. */
|
|
class AgentCore;
|
|
/* Same for the document md_to_pdf lays out (PdfTools.cpp): the caller owns
|
|
* it, and the test in ui/UiTest.cpp inspects how it draws. */
|
|
class QTextDocument;
|
|
|
|
namespace app {
|
|
|
|
/* Fill a definition in one place, so every front-end tool carries the same
|
|
* metadata (class + policy name + platform list + probe). */
|
|
inline void setMeta(cst_tool_def_t *def, const char *name, const char *desc,
|
|
cst_tool_perm_t perm, const char *perm_name,
|
|
const char *const *platforms,
|
|
int (*available)(char *, size_t)) {
|
|
def->name = name;
|
|
def->desc = desc;
|
|
def->perm = perm;
|
|
def->perm_name = perm_name;
|
|
def->platforms = platforms;
|
|
def->available = available;
|
|
}
|
|
|
|
/* Tools that only work on the phone. */
|
|
extern const char *const kAndroidOnly[];
|
|
/* Tools that only work on a desktop (linux / win / macos). */
|
|
extern const char *const kDesktopOnly[];
|
|
|
|
/* The platform tools this app provides. Called once the engine exists;
|
|
* returns how many were registered. */
|
|
int registerPlatformTools(AgentCore *core);
|
|
/* The tools this front end provides that are the same on every platform
|
|
* (they are Qt, not a platform API): today md_to_pdf, owned by "app:qt".
|
|
* Called next to registerPlatformTools(). */
|
|
int registerQtTools(AgentCore *core);
|
|
/* The document md_to_pdf lays out from `html`: the page's own defaults
|
|
* applied (text with no colour of its own is black, not the window's palette
|
|
* colour). The caller owns the result. */
|
|
QTextDocument *paperDocument(const QString &html);
|
|
/* Drop them again (they belong to the owners "app:*"). */
|
|
void unregisterPlatformTools(AgentCore *core);
|
|
|
|
/* One entry point per platform, implemented by the file under
|
|
* src/platform/<os>/; ToolProvider.cpp picks one at compile time. */
|
|
int platformRegisterLinux(AgentCore *core);
|
|
int platformRegisterMac(AgentCore *core);
|
|
int platformRegisterWindows(AgentCore *core);
|
|
int platformRegisterAndroid(AgentCore *core);
|
|
|
|
/* Hand a file of the session's store to the system: a phone opens it with
|
|
* ACTION_VIEW through the app's FileProvider, a desktop gives it to whatever
|
|
* the desktop uses. `title` is the name a person knows the file by (the
|
|
* stored copy is named by its id, which means nothing outside), used for the
|
|
* status line. Both return "" on success and a reason to show the user
|
|
* otherwise; *status (optional) gets the line to put in the header.
|
|
* CST_APP_NO_OPEN=1 makes both do nothing (--uitest drives the window without
|
|
* opening anything for real). */
|
|
QString openLocalFile(const QString &path, const QString &title, QString *status);
|
|
/* The same file through the share sheet where there is one (Android); a
|
|
* desktop has no share sheet, so the path goes to the clipboard. */
|
|
QString shareLocalFile(const QString &path, const QString &title,
|
|
QString *status);
|
|
/* Hold the machine while a turn runs, so it survives the app leaving the
|
|
* screen: a phone starts a foreground service with a partial wake lock (the
|
|
* process is one Android will not freeze or kill, and the CPU keeps going
|
|
* with the screen off) and shows a notification naming the work; a desktop
|
|
* does nothing -- the window *is* the app there. Returns "" when the hold is
|
|
* in place (or when the platform has nothing to do), a reason otherwise; the
|
|
* turn runs either way. `text` is what the phone's notification says. */
|
|
QString holdForeground(const QString &text);
|
|
/* Drop it again, at the end of the turn (a phone: the notification goes). */
|
|
void releaseForeground();
|
|
|
|
/* Turn what a file chooser handed over into a path the engine can open. A
|
|
* desktop picker gives a path and nothing happens; a phone's is a SAF
|
|
* content:// URI, which the app copies into its own directory first (the
|
|
* grant travels with the URI, so no permission is involved -- and without
|
|
* the copy the engine, which opens files by path, would fail with "cannot
|
|
* read"). Returns the path to read, or "" with *err filled. */
|
|
QString materializeAttachment(const QString &pathOrUri, QString *err);
|
|
/* Does this app have "all files access" (Android 11+)? A desktop always
|
|
* does. Without it the app still attaches whatever the picker handed it; what
|
|
* it cannot do is read shared storage by path. */
|
|
bool hasAllFilesAccess();
|
|
/* Ask for it, through the one screen Android offers (there is no runtime
|
|
* dialog for it). A desktop, a phone that already has it or one too old to
|
|
* know about it returns "" and nothing opens. */
|
|
QString requestAllFilesAccess();
|
|
/* Take the whole screen. A phone's status bar -- and a tablet's taskbar, which
|
|
* is a status bar with icons in it -- is drawn *over* the window, and the
|
|
* window here draws from its own first pixel, so the bars sit on the app's top
|
|
* row and the controls there cannot be touched. Hiding them is what "full
|
|
* screen" means on a phone; a desktop has no such bars to ask about and
|
|
* returns "". Asking is repeatable and cheap: the bars come back with a swipe
|
|
* from the edge or a switch to another app, so the front end asks again every
|
|
* time the window comes to the front. Returns "" once they are gone, a reason
|
|
* otherwise (which the front end logs). */
|
|
QString requestFullscreen();
|
|
/* The arguments the Android activity was started with (the
|
|
* "applicationArguments" intent extra): the way
|
|
* `cst-agent-app --uitest --workspace DIR` is reachable on a device, since
|
|
* Qt's own plumbing for that extra does not reach this build. Empty
|
|
* everywhere else, and empty on a device that was not started with any. */
|
|
QStringList activityArguments();
|
|
|
|
} // namespace app
|
|
|
|
#endif /* CST_APP_TOOLPROVIDER_H */
|