diff --git a/CMakeLists.txt b/CMakeLists.txt index 063e241..a012870 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,7 @@ target_link_libraries(rktwebview_prg PRIVATE Qt${QT_VERSION_MAJOR}::Widgets) target_link_libraries(rktwebview_prg PRIVATE Qt${QT_VERSION_MAJOR}::WebEngineWidgets) target_compile_definitions(rktwebview PRIVATE RKTWEBVIEW_LIBRARY) +target_compile_definitions(rktwebview_prg PRIVATE RKTWEBVIEW_PRG_EXE) target_link_Libraries(rktwebview_test PRIVATE rktwebview) diff --git a/main.cpp b/main.cpp index 30ab860..0230e2a 100644 --- a/main.cpp +++ b/main.cpp @@ -13,6 +13,12 @@ #include "rktwebview_qt.h" +#ifdef DEBUG_RKT_WEBVIEW +#define WAIT_TIME (300 * 1000) +#else +#define WAIT_TIME (10 * 1000) +#endif + static void free_data(rkt_data_t *d) { do_free_data(d); @@ -163,7 +169,7 @@ int main(int argc, char *argv[]) void Handler::run() { - int wait_ms = 10 * 1000; // 10 seconds. + int wait_ms = WAIT_TIME; // 10 seconds. while (!quit) { int cmd; std::string data; @@ -350,7 +356,7 @@ void Handler::run() } break; case CMD_TRAY_SET_ICON: { - int tray = data_obj["tray"].toInt(); + int tray = data_obj["wv"].toInt(); QString icon_file = data_obj["icon"].toString(); result_t r = webview_handler->rktTraySetIcon(tray, @@ -359,7 +365,7 @@ void Handler::run() } break; case CMD_TRAY_SET_TOOLTIP: { - int tray = data_obj["tray"].toInt(); + int tray = data_obj["wv"].toInt(); QString tooltip = data_obj["tooltip"].toString(); result_t r = webview_handler->rktTraySetTooltip(tray, @@ -368,7 +374,7 @@ void Handler::run() } break; case CMD_TRAY_SHOW_MESSAGE: { - int tray = data_obj["tray"].toInt(); + int tray = data_obj["wv"].toInt(); QString title = data_obj["title"].toString(); QString message = data_obj["message"].toString(); @@ -379,7 +385,7 @@ void Handler::run() } break; case CMD_TRAY_SET_MENU: { - int tray = data_obj["tray"].toInt(); + int tray = data_obj["wv"].toInt(); QString menu_json = data_obj["menu_json"].toString(); result_t r = webview_handler->rktTraySetMenu(tray, @@ -455,7 +461,7 @@ void Handler::run() void Alive::run() { - int wait_ms = 10 * 1000; + int wait_ms = WAIT_TIME; int ping_no; std::string data; bool go_on = true; diff --git a/resource/rktplayer.png b/resource/rktplayer.png new file mode 100644 index 0000000..429a5cc Binary files /dev/null and b/resource/rktplayer.png differ diff --git a/rktwebview.cpp b/rktwebview.cpp index 09babf4..65298fa 100644 --- a/rktwebview.cpp +++ b/rktwebview.cpp @@ -38,8 +38,6 @@ #define sleep_ms(ms) Sleep(static_cast(ms)) #endif -//#define DEBUG - #ifdef __linux static int sleep_ms(long msec) { @@ -232,7 +230,12 @@ bool runRktWebview(Handle_t *handler) #define WAIT_ON_EVENT_MS (2 * 1000) #define ALIVE_MESSAGE_INTERVAL_S 5 // Should be smaller than 10 seconds #define MAX_WAIT_RESULT (2 * 1000) // Maximum wait in milliseconds for a result per time + +#ifdef DEBUG_RKT_WEBVIEW +#define MAX_ALIVE_ACK_TIME (300 * 1000) +#else #define MAX_ALIVE_ACK_TIME (10 * 1000) +#endif void rkt_evt_guard(void) { @@ -396,7 +399,7 @@ void rkt_webview_init(const char *from) INFO1("rkt_webview_init called from %s\n", from); char buf[1024]; -#ifdef DEBUG +#ifdef DEBUG_RKT_WEBVIEW sprintf(buf, "rktwebview-dbg"); #else #ifdef _WIN32 @@ -426,7 +429,7 @@ void rkt_webview_init(const char *from) handler->alive_ack_queue = new ShmQueue(handler->shm, ALIVE_ACK_SLOT, true); // Start rktwebview_prg application with the right information -#ifndef DEBUG +#ifndef DEBUG_RKT_WEBVIEW handler->rkt_webview_prg_started = runRktWebview(handler); if (!handler->rkt_webview_prg_started) { handler->valid = false; } #endif @@ -551,28 +554,70 @@ void rkt_webview_close(rktwebview_t wv) handler->command_queue->enqueue(CMD_CLOSE_WV, j.dump()); } -#define CMDRES4(cmd, wv, key, val, key2, val2, key3, val3, key4, val4) \ - RKT_WEBVIEW_INIT; \ - FAIL_HANDLE \ - JSON j; \ - j["wv"] = wv; \ - j[key] = val; \ - j[key2] = val2; \ - j[key3] = val3; \ - j[key4] = val4; \ - handler->command_queue->enqueue(cmd, j.dump()); \ - int result; \ - std::string json_result; \ - while (!handler->command_result_queue->dequeue(result, json_result, MAX_WAIT_RESULT)) { \ - if (handler->alive_error) { \ - return result_t::failed; \ - } \ - } \ - result_t r = static_cast(result); \ +static inline result_t DO_CMDRES(int cmd, rktwebview_t wv, const JSON &j) +{ + RKT_WEBVIEW_INIT; + FAIL_HANDLE + std::string json_str = j.dump(); + handler->command_queue->enqueue(cmd, json_str); + int result; + std::string json_result; + while (!handler->command_result_queue->dequeue(result, json_result, MAX_WAIT_RESULT)) { + if (handler->alive_error) { + return result_t::failed; + } + } + result_t r = static_cast(result); return r; +} + +static inline result_t CMDRES4(int cmd, rktwebview_t wv, + const char *key, const char *val, + const char *key2, const char *val2, + const char *key3, const char *val3, + const char *key4, const char *val4) +{ + JSON j; + j["wv"] = wv; + j[key] = val; + j[key2] = val2; + j[key3] = val3; + j[key4] = val4; + return DO_CMDRES(cmd, wv, j); +} + +static inline result_t CMDRES4(int cmd, rktwebview_t wv, + const char *key, int val, + const char *key2, int val2, + const char *key3, const char *val3, + const char *key4, const char *val4) +{ + JSON j; + j["wv"] = wv; + j[key] = val; + j[key2] = val2; + j[key3] = val3; + j[key4] = val4; + return DO_CMDRES(cmd, wv, j); +} + +static inline result_t CMDRES4(int cmd, rktwebview_t wv, + const char *key, const char *val, + const char *key2, const char *val2, + const char *key3, const char *val3, + const char *key4, int val4) +{ + JSON j; + j["wv"] = wv; + j[key] = val; + j[key2] = val2; + j[key3] = val3; + j[key4] = val4; + return DO_CMDRES(cmd, wv, j); +} #define CMDRES3(cmd, wv, key, val, key2, val2, key3, val3) \ - CMDRES4(cmd, wv, key, val, key2, val2, key3, val3, "nil3", "none") +return CMDRES4(cmd, wv, key, val, key2, val2, key3, val3, "nil3", "none"); #define CMDRES2(cmd, wv, key, val, key2, val2) \ CMDRES3(cmd, wv, key, val, key2, val2, "nil2", "none") @@ -585,7 +630,7 @@ void rkt_webview_close(rktwebview_t wv) result_t rkt_webview_set_url(rktwebview_t wv, const char *url) { - CMDRES(CMD_SET_URL, wv, "url", url) + CMDRES(CMD_SET_URL, wv, "url", url); } result_t rkt_webview_set_html(rktwebview_t wv, const char *html) @@ -764,7 +809,7 @@ rkt_data_t *rkt_webview_version() result_t rkt_webview_message_box(rktwebview_t w, const char *title, const char *message, const char *submessage, rkt_messagetype_t type) { - CMDRES4(CMD_MSG_BOX, w, "title", title, "message", message, "submessage", submessage, "type", static_cast(type)) + return CMDRES4(CMD_MSG_BOX, w, "title", title, "message", message, "submessage", submessage, "type", static_cast(type)); } int rkt_webview_events_waiting() diff --git a/rktwebview_qt.cpp b/rktwebview_qt.cpp index 2a5e4fa..5dca7eb 100644 --- a/rktwebview_qt.cpp +++ b/rktwebview_qt.cpp @@ -200,6 +200,7 @@ void Rktwebview_qt::processCommand(Command *cmd) } tray->hide(); + _view_js_callbacks.remove(wv); delete tray; cmd->result = true; } else { @@ -499,26 +500,21 @@ void Rktwebview_qt::processCommand(Command *cmd) QString icon_file = cmd->args[0].toString(); QString tooltip = cmd->args[1].toString(); + void *f = cmd->args[2].value(); + event_cb_t js_event_cb = reinterpret_cast (f); + int id = nextHandle(); QSystemTrayIcon *tray = new QSystemTrayIcon(this); tray->setIcon(QIcon(icon_file)); tray->setToolTip(tooltip); + tray->setProperty("tray-id", id); - connect(tray, &QSystemTrayIcon::activated, - this, [this, id](QSystemTrayIcon::ActivationReason reason) { - EventContainer e("tray-activated"); - e["reason"] = activationReasonToString(reason); - this->triggerEvent(id, e); - }); - - connect(tray, &QSystemTrayIcon::messageClicked, - this, [this, id]() { - EventContainer e("tray-message-clicked"); - this->triggerEvent(id, e); - }); + connect(tray, &QSystemTrayIcon::activated, this, &Rktwebview_qt::handleTrayActivation); + connect(tray, &QSystemTrayIcon::messageClicked, this, &Rktwebview_qt::handleTrayMessageClick); _trays[id] = tray; + _view_js_callbacks[id] = js_event_cb; tray->show(); @@ -606,6 +602,36 @@ void Rktwebview_qt::processCommand(Command *cmd) } } +void Rktwebview_qt::handleTrayActivation(QSystemTrayIcon::ActivationReason reason) +{ + QObject *obj = sender(); + + int tray_wv = obj->property("tray-id").toInt(); + QString evt = "tray-activated"; + QString reason_str = activationReasonToString(reason); + + //INFO3("triggering event: %s for tray %d with reason %s\n", + // evt.toUtf8().constData(), tray_wv, reason_str.toUtf8().constData()); + + EventContainer e(evt); + e["reason"] = reason_str; + + this->triggerEvent(tray_wv, e); +} + +void Rktwebview_qt::handleTrayMessageClick() +{ + QObject *obj = sender(); + + //INFO0("triggering message click\n"); + + int tray_wv = obj->property("tray-id").toInt(); + QString evt = "tray-message-clicked"; + + EventContainer e(evt); + this->triggerEvent(tray_wv, e); +} + void Rktwebview_qt::removeView(int id) { if (_views.contains(id)) { @@ -1066,6 +1092,8 @@ result_t Rktwebview_qt::rktTraySetIcon(rktwebview_t tray, const char *icon_file) result_t Rktwebview_qt::rktTraySetTooltip(rktwebview_t tray, const char *tooltip) { + //INFO2("rktTraySetTooltip: %d %s\n", tray, tooltip); + Command c(COMMAND_TRAY_SET_TOOLTIP); c.args.push_back(tray); c.args.push_back(tooltip); @@ -1073,6 +1101,8 @@ result_t Rktwebview_qt::rktTraySetTooltip(rktwebview_t tray, const char *tooltip postCommand(&c); while(!c.done) { doEvents(); } + //INFO1("rktTraySetTooltip done: %s\n", tooltip); + return c.result.toBool() ? result_t::oke : result_t::failed; } diff --git a/rktwebview_qt.h b/rktwebview_qt.h index d978107..b4f5672 100644 --- a/rktwebview_qt.h +++ b/rktwebview_qt.h @@ -13,6 +13,7 @@ #include #include #include +#include class WebViewQt; @@ -50,6 +51,8 @@ private: private slots: void stopEventloop(); + void handleTrayActivation(QSystemTrayIcon::ActivationReason reason); + void handleTrayMessageClick(); private: void postCommand(Command *cmd); diff --git a/rktwebview_test.cpp b/rktwebview_test.cpp index 1e08b31..b5fa890 100644 --- a/rktwebview_test.cpp +++ b/rktwebview_test.cpp @@ -35,9 +35,21 @@ int main(int argc, char *argv[]) setenv("LD_LIBRARY_PATH", loc.c_str(), true); #endif + rkt_webview_init(__FUNCTION__); + int context = rkt_webview_new_context("", nullptr); rkt_webview_set_loglevel(rkt_webview_loglevel_t::log_debug); + const char *icon_file = "../../resource/rktplayer.png"; + FILE *f = fopen(icon_file, "rb"); + if (f == nullptr) { + WARN1("Cannot find icon file %s\n", icon_file); + } else { + fclose(f); + } + int tray_wv = rkt_webview_tray_create(icon_file, "This is a test tray icon"); + INFO1("tray_wv = %d\n", tray_wv); + rkt_webview_register_evt_callback(evt_cb); int wv = rkt_webview_create(context, 0); @@ -60,7 +72,9 @@ int main(int argc, char *argv[]) rkt_webview_free_data(d); } #ifdef _WIN32 - Sleep(30000); + Sleep(15000); + rkt_webview_tray_show_message(tray_wv, "This is a title", "This is a message to display
Hopefully it does display."); + Sleep(15000); #else sleep(30 ); @@ -73,5 +87,7 @@ int main(int argc, char *argv[]) d = rkt_webview_info(); rkt_webview_free_data(d); + rkt_webview_close(tray_wv); + rkt_webview_cleanup(); } diff --git a/utils.cpp b/utils.cpp index 33b70e6..a701588 100644 --- a/utils.cpp +++ b/utils.cpp @@ -13,6 +13,7 @@ static timer *_timer = nullptr; +extern "C" { int logLevel() { return _log_level; @@ -49,3 +50,4 @@ void logElapsed() .count(); fprintf(stderr, "%8.3lf: ", milliseconds/ 1000.0); } +} diff --git a/utils.h b/utils.h index d7ccabc..f8a0399 100644 --- a/utils.h +++ b/utils.h @@ -1,7 +1,10 @@ #ifndef UTILS_H #define UTILS_H +//#define DEBUG_RKT_WEBVIEW + #include +#include "rktwebview_global.h" #include "rktwebview_types.h" inline std::string basedir(const std::string &path) @@ -26,11 +29,17 @@ inline std::string basedir(const std::string &path) } return r; } +extern "C" { +#ifdef RKTWEBVIEW_PRG_EXE +#undef RKTWEBVIEW_EXPORT +#define RKTWEBVIEW_EXPORT +#endif -int logLevel(); -void setLogLevel(int l); -void logElapsed(); -const char *logIndicator(int l); +RKTWEBVIEW_EXPORT int logLevel(); +RKTWEBVIEW_EXPORT void setLogLevel(int l); +RKTWEBVIEW_EXPORT void logElapsed(); +RKTWEBVIEW_EXPORT const char *logIndicator(int l); +} #define LOG_ERROR 1 #define LOG_WARNING 2 @@ -41,6 +50,7 @@ const char *logIndicator(int l); #define MKL0(level, msg) MKLOGSTMT(level, fprintf(stderr, msg)) #define MKL1(level, msg, a) MKLOGSTMT(level, fprintf(stderr, msg, a)) #define MKL2(level, msg, a, b) MKLOGSTMT(level, fprintf(stderr, msg, a, b)) +#define MKL3(level, msg, a, b, c) MKLOGSTMT(level, fprintf(stderr, msg, a, b, c)) #define ERROR0(msg) MKL0(LOG_ERROR, msg) #define WARN0(msg) MKL0(LOG_WARNING, msg) @@ -57,6 +67,8 @@ const char *logIndicator(int l); #define INFO2(msg, a, b) MKL2(LOG_INFO, msg, a, b) #define DEBUG2(msg, a, b) MKL2(LOG_DEBUG, msg, a, b) +#define INFO3(msg, a, b, c) MKL3(LOG_INFO, msg, a, b, c) + inline void do_free_data(rkt_data_t *d) { if (d == nullptr) { return; }