Browse Source

webview: get Qt working again, cleanup

Signed-off-by: falkTX <falktx@falktx.com>
pull/467/head
falkTX 8 months ago
parent
commit
2745ee9601
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
1 changed files with 258 additions and 63 deletions
  1. +258
    -63
      distrho/extra/WebViewImpl.cpp

+ 258
- 63
distrho/extra/WebViewImpl.cpp View File

@@ -21,6 +21,19 @@
# error bad usage # error bad usage
#endif #endif


// #undef Bool
// #undef CursorShape
// #undef Expose
// #undef FocusIn
// #undef FocusOut
// #undef FontChange
// #undef KeyPress
// #undef KeyRelease
// #undef None
// #undef Status
// #include <QGuiApplication>
// #include <QEvent>

// #include <gtk/gtk.h> // #include <gtk/gtk.h>
// #include <gtk/gtkx.h> // #include <gtk/gtkx.h>
// #include <webkit2/webkit2.h> // #include <webkit2/webkit2.h>
@@ -818,6 +831,7 @@ void webViewResize(const WebViewHandle handle, const uint width, const uint heig


// ----------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------


static bool running = false;
static std::function<void(const char* js)> evaluateFn; static std::function<void(const char* js)> evaluateFn;
static std::function<void()> reloadFn; static std::function<void()> reloadFn;
static std::function<void()> terminateFn; static std::function<void()> terminateFn;
@@ -843,10 +857,25 @@ typedef int gboolean;
#define GTK_WINDOW(p) reinterpret_cast<GtkWindow*>(p) #define GTK_WINDOW(p) reinterpret_cast<GtkWindow*>(p)
#define WEBKIT_WEB_VIEW(p) reinterpret_cast<WebKitWebView*>(p) #define WEBKIT_WEB_VIEW(p) reinterpret_cast<WebKitWebView*>(p)


// struct QApplication;
// struct QUrl;
// struct QWebEngineView;
// struct QWindow;
// -----------------------------------------------------------------------------------------------------------

class QApplication;
class QChar;
class QEvent;
class QMetaMethod;
class QMetaObject;
class QString;
class QUrl;
class QWebEngineView;
class QWindow;

struct QPoint {
int x, y;
};

struct QSize {
int w, h;
};


// ----------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------


@@ -865,10 +894,7 @@ typedef int gboolean;
S NAME = reinterpret_cast<S>(dlsym(nullptr, #SN)); \ S NAME = reinterpret_cast<S>(dlsym(nullptr, #SN)); \
DISTRHO_SAFE_ASSERT_RETURN(NAME != nullptr, false); DISTRHO_SAFE_ASSERT_RETURN(NAME != nullptr, false);


// -----------------------------------------------------------------------------------------------------------
// gtk3 variant

static void gtk3_idle(void* const ptr)
static void web_wake_idle(void* const ptr)
{ {
WebViewRingBuffer* const shmptr = static_cast<WebViewRingBuffer*>(ptr); WebViewRingBuffer* const shmptr = static_cast<WebViewRingBuffer*>(ptr);


@@ -918,6 +944,9 @@ static void gtk3_idle(void* const ptr)
free(buffer); free(buffer);
} }


// -----------------------------------------------------------------------------------------------------------
// gtk3 variant

static int gtk3_js_cb(WebKitUserContentManager*, WebKitJavascriptResult* const result, void* const arg) static int gtk3_js_cb(WebKitUserContentManager*, WebKitJavascriptResult* const result, void* const arg)
{ {
WebViewRingBuffer* const shmptr = static_cast<WebViewRingBuffer*>(arg); WebViewRingBuffer* const shmptr = static_cast<WebViewRingBuffer*>(arg);
@@ -962,9 +991,12 @@ static bool gtk3(Display* const display,
WebViewRingBuffer* const shmptr) WebViewRingBuffer* const shmptr)
{ {
void* lib; void* lib;
if ((lib = dlopen("libwebkit2gtk-4.0.so.37", RTLD_NOW|RTLD_GLOBAL)) == nullptr ||
if ((lib = dlopen("libwebkit2gtk-4.0.so.37", RTLD_NOW|RTLD_GLOBAL)) == nullptr &&
(lib = dlopen("libwebkit2gtk-4.0.so", RTLD_NOW|RTLD_GLOBAL)) == nullptr) (lib = dlopen("libwebkit2gtk-4.0.so", RTLD_NOW|RTLD_GLOBAL)) == nullptr)
{
d_stdout("WebView gtk3 platform not available: %s", dlerror());
return false; return false;
}


using g_main_context_invoke_t = void (*)(void*, void*, void*); using g_main_context_invoke_t = void (*)(void*, void*, void*);
using g_signal_connect_data_t = ulong (*)(void*, const char*, void*, void*, void*, int); using g_signal_connect_data_t = ulong (*)(void*, const char*, void*, void*, void*, int);
@@ -1047,8 +1079,11 @@ static bool gtk3(Display* const display,


gdk_set_allowed_backends("x11"); gdk_set_allowed_backends("x11");


if (! gtk_init_check (nullptr, nullptr))
if (! gtk_init_check(nullptr, nullptr))
{
d_stderr("WebView gtk_init_check failed");
return false; return false;
}


GtkWidget* const window = gtk_plug_new(winId); GtkWidget* const window = gtk_plug_new(winId);
DISTRHO_SAFE_ASSERT_RETURN(window != nullptr, false); DISTRHO_SAFE_ASSERT_RETURN(window != nullptr, false);
@@ -1116,43 +1151,113 @@ static bool gtk3(Display* const display,
}; };


terminateFn = [=](){ terminateFn = [=](){
d_stdout("terminateFn");
static bool quit = true;
if (quit)
if (running)
{ {
quit = false;
running = false;
webview_wake(&shmptr->client.sem);
gtk_main_quit(); gtk_main_quit();
} }
}; };


wakeFn = [=](WebViewRingBuffer* const rb){ wakeFn = [=](WebViewRingBuffer* const rb){
g_main_context_invoke(NULL, G_CALLBACK(gtk3_idle), rb);
g_main_context_invoke(NULL, G_CALLBACK(web_wake_idle), rb);
}; };


// notify server we started ok // notify server we started ok
webview_wake(&shmptr->server.sem); webview_wake(&shmptr->server.sem);


d_stdout("WebView gtk3 main loop started");

gtk_main(); gtk_main();
d_stdout("quit");

d_stdout("WebView gtk3 main loop quit");


dlclose(lib); dlclose(lib);
return true; return true;
} }


#if 0
// -----------------------------------------------------------------------------------------------------------
// qt common code

// VTable compatible with real QObject
class QObject
{
public:
using QObject__init_t = void (*)(QObject*, QObject*);

QObject(const QObject__init_t init)
{
init(this, nullptr);
}

virtual const QMetaObject* metaObject() const
{
static const uint8_t mdata[56 * 2] = {}; // sizeof(QMetaObject) == 56
return static_cast<const QMetaObject*>(static_cast<const void*>(mdata));
}

virtual void* qt_metacast(const char*) { return 0; }
virtual int qt_metacall(void* /* QMetaObject::Call */, int, void**) { return 0; }
virtual ~QObject() {}
virtual bool event(QEvent *e) { return false; }
virtual bool eventFilter(QObject*, QEvent*) { return false; }
virtual void timerEvent(void*) {}
virtual void childEvent(void*) {}
virtual void customEvent(void*) {}
virtual void connectNotify(const QMetaMethod&) {}
virtual void disconnectNotify(const QMetaMethod&) {}

private:
uint8_t _[8 * 2];
};

// QObject subclass for receiving events on main thread
class EventFilterQObject : public QObject
{
WebViewRingBuffer* const _rb;

public:
EventFilterQObject(const QObject__init_t init, WebViewRingBuffer* const rb)
: QObject(init),
_rb(rb) {}

bool event(QEvent * e) override
{
printf("custom event YES\n");
web_wake_idle(_rb);
return false;
}
};

// ----------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------
// qt5webengine variant // qt5webengine variant


static bool qt5webengine(const Window winId, const double scaleFactor, const char* const url)
static bool qt5webengine(Display* const display,
const Window winId,
const int x,
const int y,
const uint width,
const uint height,
double scaleFactor,
const char* const url,
const char* const initialJS,
WebViewRingBuffer* const shmptr)
{ {
void* lib; void* lib;
if ((lib = dlopen("libQt5WebEngineWidgets.so.5", RTLD_NOW|RTLD_GLOBAL)) == nullptr ||
if ((lib = dlopen("libQt5WebEngineWidgets.so.5", RTLD_NOW|RTLD_GLOBAL)) == nullptr &&
(lib = dlopen("libQt5WebEngineWidgets.so", RTLD_NOW|RTLD_GLOBAL)) == nullptr) (lib = dlopen("libQt5WebEngineWidgets.so", RTLD_NOW|RTLD_GLOBAL)) == nullptr)
{
d_stdout("WebView Qt5 platform not available: %s", dlerror());
return false; return false;
}


using QApplication__init_t = void (*)(QApplication*, int&, char**, int); using QApplication__init_t = void (*)(QApplication*, int&, char**, int);
using QApplication_exec_t = void (*)(); using QApplication_exec_t = void (*)();
using QApplication_setAttribute_t = void (*)(Qt::ApplicationAttribute, bool);
using QApplication_postEvent_t = void (*)(QObject*, QEvent*, int);
using QApplication_quit_t = void (*)();
using QApplication_setAttribute_t = void (*)(int, bool);
using QEvent__init_t = void (*)(QEvent*, int);
using QObject__init_t = void (*)(QObject*, QObject*);
using QString__init_t = void (*)(void*, const QChar*, ptrdiff_t); using QString__init_t = void (*)(void*, const QChar*, ptrdiff_t);
using QUrl__init_t = void (*)(void*, const QString&, int /* QUrl::ParsingMode */); using QUrl__init_t = void (*)(void*, const QString&, int /* QUrl::ParsingMode */);
using QWebEngineView__init_t = void (*)(QWebEngineView*, void*); using QWebEngineView__init_t = void (*)(QWebEngineView*, void*);
@@ -1167,7 +1272,11 @@ static bool qt5webengine(const Window winId, const double scaleFactor, const cha


CPPSYM(QApplication__init_t, QApplication__init, _ZN12QApplicationC1ERiPPci) CPPSYM(QApplication__init_t, QApplication__init, _ZN12QApplicationC1ERiPPci)
CPPSYM(QApplication_exec_t, QApplication_exec, _ZN15QGuiApplication4execEv) CPPSYM(QApplication_exec_t, QApplication_exec, _ZN15QGuiApplication4execEv)
CPPSYM(QApplication_postEvent_t, QApplication_postEvent, _ZN16QCoreApplication9postEventEP7QObjectP6QEventi)
CPPSYM(QApplication_quit_t, QApplication_quit, _ZN16QCoreApplication4quitEv)
CPPSYM(QApplication_setAttribute_t, QApplication_setAttribute, _ZN16QCoreApplication12setAttributeEN2Qt20ApplicationAttributeEb) CPPSYM(QApplication_setAttribute_t, QApplication_setAttribute, _ZN16QCoreApplication12setAttributeEN2Qt20ApplicationAttributeEb)
CPPSYM(QEvent__init_t, QEvent__init, _ZN6QEventC1ENS_4TypeE)
CPPSYM(QObject__init_t, QObject__init, _ZN7QObjectC1EPS_)
CPPSYM(QString__init_t, QString__init, _ZN7QStringC2EPK5QChari) CPPSYM(QString__init_t, QString__init, _ZN7QStringC2EPK5QChari)
CPPSYM(QUrl__init_t, QUrl__init, _ZN4QUrlC1ERK7QStringNS_11ParsingModeE) CPPSYM(QUrl__init_t, QUrl__init, _ZN4QUrlC1ERK7QStringNS_11ParsingModeE)
CPPSYM(QWebEngineView__init_t, QWebEngineView__init, _ZN14QWebEngineViewC1EP7QWidget) CPPSYM(QWebEngineView__init_t, QWebEngineView__init, _ZN14QWebEngineViewC1EP7QWidget)
@@ -1184,17 +1293,19 @@ static bool qt5webengine(const Window winId, const double scaleFactor, const cha
unsetenv("QT_SCREEN_SCALE_FACTORS"); unsetenv("QT_SCREEN_SCALE_FACTORS");
unsetenv("QT_USE_PHYSICAL_DPI"); unsetenv("QT_USE_PHYSICAL_DPI");
setenv("QT_AUTO_SCREEN_SCALE_FACTOR", "0", 1); setenv("QT_AUTO_SCREEN_SCALE_FACTOR", "0", 1);
setenv("QT_QPA_PLATFORM", "xcb", 1);


char scale[8] = {}; char scale[8] = {};
std::snprintf(scale, 7, "%.2f", scaleFactor); std::snprintf(scale, 7, "%.2f", scaleFactor);
setenv("QT_SCALE_FACTOR", scale, 1); setenv("QT_SCALE_FACTOR", scale, 1);


QApplication_setAttribute(Qt::AA_X11InitThreads, true);
QApplication_setAttribute(Qt::AA_EnableHighDpiScaling, true);
QApplication_setAttribute(Qt::AA_UseHighDpiPixmaps, true);
QApplication_setAttribute(10 /* Qt::AA_X11InitThreads */, true);
QApplication_setAttribute(13 /* Qt::AA_UseHighDpiPixmaps */, true);
QApplication_setAttribute(20 /* Qt::AA_EnableHighDpiScaling */, true);


static int argc = 0;
static char* argv[] = { nullptr };
static int argc = 1;
static char argv0[] = "dpf-webview";
static char* argv[] = { argv0, nullptr };


uint8_t _app[64]; // sizeof(QApplication) == 16 uint8_t _app[64]; // sizeof(QApplication) == 16
QApplication* const app = reinterpret_cast<QApplication*>(_app); QApplication* const app = reinterpret_cast<QApplication*>(_app);
@@ -1205,41 +1316,69 @@ static bool qt5webengine(const Window winId, const double scaleFactor, const cha


{ {
const size_t url_len = std::strlen(url); const size_t url_len = std::strlen(url);
QChar* const url_qchar = new QChar[url_len + 1];
ushort* const url_qchar = new ushort[url_len + 1];


for (size_t i = 0; i < url_len; ++i) for (size_t i = 0; i < url_len; ++i)
url_qchar[i] = QChar(url[i]);
url_qchar[i] = url[i];


url_qchar[url_len] = 0; url_qchar[url_len] = 0;


QString__init(qstrurl, url_qchar, url_len);
QString__init(qstrurl, reinterpret_cast<QChar*>(url_qchar), url_len);
} }


uint8_t _qurl[32]; // sizeof(QUrl) == 8 uint8_t _qurl[32]; // sizeof(QUrl) == 8
QUrl* const qurl(reinterpret_cast<QUrl*>(_qurl)); QUrl* const qurl(reinterpret_cast<QUrl*>(_qurl));
QUrl__init(qurl, *qstrurl, 1 /* QUrl::StrictMode */); QUrl__init(qurl, *qstrurl, 1 /* QUrl::StrictMode */);


EventFilterQObject eventFilter(QObject__init, shmptr);
EventFilterQObject* const eventFilterPtr = &eventFilter;

uint8_t _webview[128]; // sizeof(QWebEngineView) == 56 uint8_t _webview[128]; // sizeof(QWebEngineView) == 56
QWebEngineView* const webview = reinterpret_cast<QWebEngineView*>(_webview); QWebEngineView* const webview = reinterpret_cast<QWebEngineView*>(_webview);
QWebEngineView__init(webview, nullptr); QWebEngineView__init(webview, nullptr);

QWebEngineView_move(webview, QPoint(0, kVerticalOffset));
QWebEngineView_resize(webview, QSize(DISTRHO_UI_DEFAULT_WIDTH, DISTRHO_UI_DEFAULT_HEIGHT - kVerticalOffset));
QWebEngineView_move(webview, QPoint{x, y});
QWebEngineView_resize(webview, QSize{DISTRHO_UI_DEFAULT_WIDTH, DISTRHO_UI_DEFAULT_HEIGHT});
QWebEngineView_winId(webview); QWebEngineView_winId(webview);
QWindow_setParent(QWebEngineView_windowHandle(webview), QWindow_fromWinId(winId)); QWindow_setParent(QWebEngineView_windowHandle(webview), QWindow_fromWinId(winId));
QWebEngineView_setUrl(webview, *qurl); QWebEngineView_setUrl(webview, *qurl);
QWebEngineView_show(webview); QWebEngineView_show(webview);


evaluateFn = [=](const char* const js){
// TODO
};

reloadFn = [=](){ reloadFn = [=](){
QWebEngineView_setUrl(webview, *qurl); QWebEngineView_setUrl(webview, *qurl);
}; };


terminateFn = [=](){ terminateFn = [=](){
// TODO
if (running)
{
running = false;
webview_wake(&shmptr->client.sem);
QApplication_quit();
}
};

wakeFn = [=](WebViewRingBuffer* const rb){
d_stdout("wakeFn");
// NOTE event pointer is deleted by Qt
typedef struct { uint8_t _[16 * 2]; } uint8_64_t; // sizeof(QEvent) == 16
QEvent* const qevent = reinterpret_cast<QEvent*>(new uint8_64_t);
QEvent__init(qevent, 1000 /* QEvent::User */);

QApplication_postEvent(eventFilterPtr, qevent, 1 /* Qt::HighEventPriority */);
}; };


// notify server we started ok
webview_wake(&shmptr->server.sem);

d_stdout("WebView Qt5 main loop started");

QApplication_exec(); QApplication_exec();


d_stdout("WebView Qt5 main loop quit");

dlclose(lib); dlclose(lib);
return true; return true;
} }
@@ -1247,17 +1386,32 @@ static bool qt5webengine(const Window winId, const double scaleFactor, const cha
// ----------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------
// qt6webengine variant (same as qt5 but `QString__init_t` has different arguments) // qt6webengine variant (same as qt5 but `QString__init_t` has different arguments)


static bool qt6webengine(const Window winId, const double scaleFactor, const char* const url)
static bool qt6webengine(Display* const display,
const Window winId,
const int x,
const int y,
const uint width,
const uint height,
double scaleFactor,
const char* const url,
const char* const initialJS,
WebViewRingBuffer* const shmptr)
{ {
void* lib; void* lib;
if ((lib = dlopen("libQt6WebEngineWidgets.so.6", RTLD_NOW|RTLD_GLOBAL)) == nullptr ||
if ((lib = dlopen("libQt6WebEngineWidgets.so.6", RTLD_NOW|RTLD_GLOBAL)) == nullptr &&
(lib = dlopen("libQt6WebEngineWidgets.so", RTLD_NOW|RTLD_GLOBAL)) == nullptr) (lib = dlopen("libQt6WebEngineWidgets.so", RTLD_NOW|RTLD_GLOBAL)) == nullptr)
{
d_stdout("WebView Qt6 platform not available: %s", dlerror());
return false; return false;
}


using QApplication__init_t = void (*)(QApplication*, int&, char**, int); using QApplication__init_t = void (*)(QApplication*, int&, char**, int);
using QApplication_exec_t = void (*)(); using QApplication_exec_t = void (*)();
using QApplication_setAttribute_t = void (*)(Qt::ApplicationAttribute, bool);
using QString__init_t = void (*)(void*, const QChar*, long long);
using QApplication_postEvent_t = void (*)(QObject*, QEvent*, int);
using QApplication_quit_t = void (*)();
using QEvent__init_t = void (*)(QEvent*, int);
using QObject__init_t = void (*)(QObject*, QObject*);
using QString__init_t = void (*)(QString*, const QChar*, long long);
using QUrl__init_t = void (*)(void*, const QString&, int /* QUrl::ParsingMode */); using QUrl__init_t = void (*)(void*, const QString&, int /* QUrl::ParsingMode */);
using QWebEngineView__init_t = void (*)(QWebEngineView*, void*); using QWebEngineView__init_t = void (*)(QWebEngineView*, void*);
using QWebEngineView_move_t = void (*)(QWebEngineView*, const QPoint&); using QWebEngineView_move_t = void (*)(QWebEngineView*, const QPoint&);
@@ -1271,7 +1425,10 @@ static bool qt6webengine(const Window winId, const double scaleFactor, const cha


CPPSYM(QApplication__init_t, QApplication__init, _ZN12QApplicationC1ERiPPci) CPPSYM(QApplication__init_t, QApplication__init, _ZN12QApplicationC1ERiPPci)
CPPSYM(QApplication_exec_t, QApplication_exec, _ZN15QGuiApplication4execEv) CPPSYM(QApplication_exec_t, QApplication_exec, _ZN15QGuiApplication4execEv)
CPPSYM(QApplication_setAttribute_t, QApplication_setAttribute, _ZN16QCoreApplication12setAttributeEN2Qt20ApplicationAttributeEb)
CPPSYM(QApplication_postEvent_t, QApplication_postEvent, _ZN16QCoreApplication9postEventEP7QObjectP6QEventi)
CPPSYM(QApplication_quit_t, QApplication_quit, _ZN16QCoreApplication4quitEv)
CPPSYM(QEvent__init_t, QEvent__init, _ZN6QEventC1ENS_4TypeE)
CPPSYM(QObject__init_t, QObject__init, _ZN7QObjectC1EPS_)
CPPSYM(QString__init_t, QString__init, _ZN7QStringC2EPK5QCharx) CPPSYM(QString__init_t, QString__init, _ZN7QStringC2EPK5QCharx)
CPPSYM(QUrl__init_t, QUrl__init, _ZN4QUrlC1ERK7QStringNS_11ParsingModeE) CPPSYM(QUrl__init_t, QUrl__init, _ZN4QUrlC1ERK7QStringNS_11ParsingModeE)
CPPSYM(QWebEngineView__init_t, QWebEngineView__init, _ZN14QWebEngineViewC1EP7QWidget) CPPSYM(QWebEngineView__init_t, QWebEngineView__init, _ZN14QWebEngineViewC1EP7QWidget)
@@ -1287,18 +1444,16 @@ static bool qt6webengine(const Window winId, const double scaleFactor, const cha
unsetenv("QT_FONT_DPI"); unsetenv("QT_FONT_DPI");
unsetenv("QT_SCREEN_SCALE_FACTORS"); unsetenv("QT_SCREEN_SCALE_FACTORS");
unsetenv("QT_USE_PHYSICAL_DPI"); unsetenv("QT_USE_PHYSICAL_DPI");
setenv("QT_AUTO_SCREEN_SCALE_FACTOR", "0", 1);
setenv("QT_ENABLE_HIGHDPI_SCALING", "0", 1);
setenv("QT_QPA_PLATFORM", "xcb", 1);


char scale[8] = {}; char scale[8] = {};
std::snprintf(scale, 7, "%.2f", scaleFactor); std::snprintf(scale, 7, "%.2f", scaleFactor);
setenv("QT_SCALE_FACTOR", scale, 1); setenv("QT_SCALE_FACTOR", scale, 1);


QApplication_setAttribute(Qt::AA_X11InitThreads, true);
QApplication_setAttribute(Qt::AA_EnableHighDpiScaling, true);
QApplication_setAttribute(Qt::AA_UseHighDpiPixmaps, true);

static int argc = 0;
static char* argv[] = { nullptr };
static int argc = 1;
static char argv0[] = "dpf-webview";
static char* argv[] = { argv0, nullptr };


uint8_t _app[64]; // sizeof(QApplication) == 16 uint8_t _app[64]; // sizeof(QApplication) == 16
QApplication* const app = reinterpret_cast<QApplication*>(_app); QApplication* const app = reinterpret_cast<QApplication*>(_app);
@@ -1309,45 +1464,78 @@ static bool qt6webengine(const Window winId, const double scaleFactor, const cha


{ {
const size_t url_len = std::strlen(url); const size_t url_len = std::strlen(url);
QChar* const url_qchar = new QChar[url_len + 1];
ushort* const url_qchar = new ushort[url_len + 1];


for (size_t i = 0; i < url_len; ++i) for (size_t i = 0; i < url_len; ++i)
url_qchar[i] = QChar(url[i]);
url_qchar[i] = url[i];


url_qchar[url_len] = 0; url_qchar[url_len] = 0;


QString__init(qstrurl, url_qchar, url_len);
QString__init(qstrurl, reinterpret_cast<QChar*>(url_qchar), url_len);
} }


uint8_t _qurl[32]; // sizeof(QUrl) == 8 uint8_t _qurl[32]; // sizeof(QUrl) == 8
QUrl* const qurl(reinterpret_cast<QUrl*>(_qurl)); QUrl* const qurl(reinterpret_cast<QUrl*>(_qurl));
QUrl__init(qurl, *qstrurl, 1 /* QUrl::StrictMode */); QUrl__init(qurl, *qstrurl, 1 /* QUrl::StrictMode */);


EventFilterQObject eventFilter(QObject__init, shmptr);
EventFilterQObject* const eventFilterPtr = &eventFilter;

uint8_t _webview[128]; // sizeof(QWebEngineView) == 56 uint8_t _webview[128]; // sizeof(QWebEngineView) == 56
QWebEngineView* const webview = reinterpret_cast<QWebEngineView*>(_webview); QWebEngineView* const webview = reinterpret_cast<QWebEngineView*>(_webview);
QWebEngineView__init(webview, nullptr); QWebEngineView__init(webview, nullptr);


QWebEngineView_move(webview, QPoint(0, kVerticalOffset));
QWebEngineView_resize(webview, QSize(DISTRHO_UI_DEFAULT_WIDTH, DISTRHO_UI_DEFAULT_HEIGHT - kVerticalOffset));
QWebEngineView_move(webview, QPoint{x, y});
QWebEngineView_resize(webview, QSize{DISTRHO_UI_DEFAULT_WIDTH, DISTRHO_UI_DEFAULT_HEIGHT});
QWebEngineView_winId(webview); QWebEngineView_winId(webview);
QWindow_setParent(QWebEngineView_windowHandle(webview), QWindow_fromWinId(winId)); QWindow_setParent(QWebEngineView_windowHandle(webview), QWindow_fromWinId(winId));
QWebEngineView_setUrl(webview, *qurl); QWebEngineView_setUrl(webview, *qurl);

// FIXME Qt6 seems to need some forcing..
XReparentWindow(display, QWebEngineView_winId(webview), winId, x, y);
XFlush(display);

QWebEngineView_show(webview); QWebEngineView_show(webview);


evaluateFn = [=](const char* const js){
// TODO
};

reloadFn = [=](){ reloadFn = [=](){
QWebEngineView_setUrl(webview, *qurl); QWebEngineView_setUrl(webview, *qurl);
}; };


terminateFn = [=](){ terminateFn = [=](){
// TODO
if (running)
{
running = false;
webview_wake(&shmptr->client.sem);
QApplication_quit();
}
};

wakeFn = [=](WebViewRingBuffer* const rb){
d_stdout("wakeFn");
// NOTE event pointer is deleted by Qt
typedef struct { uint8_t _[16 * 2]; } uint8_64_t; // sizeof(QEvent) == 16
QEvent* const qevent = reinterpret_cast<QEvent*>(new uint8_64_t);
QEvent__init(qevent, 1000 /* QEvent::User */);

QApplication_postEvent(eventFilterPtr, qevent, 1 /* Qt::HighEventPriority */);
}; };


// notify server we started ok
webview_wake(&shmptr->server.sem);

d_stdout("WebView Qt6 main loop started");

QApplication_exec(); QApplication_exec();


d_stdout("WebView Qt6 main loop quit");

dlclose(lib); dlclose(lib);
return true; return true;
} }
#endif


// ----------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------
// startup via ld-linux // startup via ld-linux
@@ -1366,12 +1554,9 @@ static void* threadHandler(void* const ptr)
{ {
WebViewRingBuffer* const shmptr = static_cast<WebViewRingBuffer*>(ptr); WebViewRingBuffer* const shmptr = static_cast<WebViewRingBuffer*>(ptr);


// TODO wait until page is loaded, or something better
d_sleep(1);

while (shmptr->valid)
while (running && shmptr->valid)
{ {
if (webview_timedwait(&shmptr->client.sem))
if (webview_timedwait(&shmptr->client.sem) && running)
wakeFn(shmptr); wakeFn(shmptr);
} }


@@ -1380,14 +1565,14 @@ static void* threadHandler(void* const ptr)


int dpf_webview_start(const int argc, char* argv[]) int dpf_webview_start(const int argc, char* argv[])
{ {
d_stdout("started %d %s", argc, argv[1]);

if (argc != 3) if (argc != 3)
{ {
d_stderr("WebView entry point, nothing to see here! ;)"); d_stderr("WebView entry point, nothing to see here! ;)");
return 1; return 1;
} }


d_stdout("starting... %d '%s' '%s'", argc, argv[1], argv[2]);

uselocale(newlocale(LC_NUMERIC_MASK, "C", nullptr)); uselocale(newlocale(LC_NUMERIC_MASK, "C", nullptr));


Display* const display = XOpenDisplay(nullptr); Display* const display = XOpenDisplay(nullptr);
@@ -1431,7 +1616,7 @@ int dpf_webview_start(const int argc, char* argv[])
{ {
DISTRHO_SAFE_ASSERT_RETURN(rbctrl.readUInt() == kWebViewMessageInitData, 1); DISTRHO_SAFE_ASSERT_RETURN(rbctrl.readUInt() == kWebViewMessageInitData, 1);


hasInitialData = true;
hasInitialData = running = true;
winId = rbctrl.readULong(); winId = rbctrl.readULong();
width = rbctrl.readUInt(); width = rbctrl.readUInt();
height = rbctrl.readUInt(); height = rbctrl.readUInt();
@@ -1454,20 +1639,30 @@ int dpf_webview_start(const int argc, char* argv[])
pthread_t thread; pthread_t thread;
if (hasInitialData && pthread_create(&thread, nullptr, threadHandler, shmptr) == 0) if (hasInitialData && pthread_create(&thread, nullptr, threadHandler, shmptr) == 0)
{ {
d_stdout("WebView IPC in place, starting engine...");

struct sigaction sig = {}; struct sigaction sig = {};
sig.sa_handler = signalHandler; sig.sa_handler = signalHandler;
sig.sa_flags = SA_RESTART; sig.sa_flags = SA_RESTART;
sigemptyset(&sig.sa_mask); sigemptyset(&sig.sa_mask);
sigaction(SIGTERM, &sig, nullptr); sigaction(SIGTERM, &sig, nullptr);


// qt5webengine(winId, scaleFactor, url) ||
// qt6webengine(winId, scaleFactor, url) ||
gtk3(display, winId, x, y, width, height, scaleFactor, url, initJS, shmptr);
if (! qt5webengine(display, winId, x, y, width, height, scaleFactor, url, initJS, shmptr) &&
! qt6webengine(display, winId, x, y, width, height, scaleFactor, url, initJS, shmptr) &&
! gtk3(display, winId, x, y, width, height, scaleFactor, url, initJS, shmptr))
{
d_stderr("Failed to find usable WebView platform");
}


shmptr->valid = false;
shmptr->valid = running = false;
pthread_join(thread, nullptr); pthread_join(thread, nullptr);
} }
else
{
d_stderr("Failed to setup WebView IPC");
}


std::free(initJS);
munmap(shmptr, sizeof(WebViewRingBuffer)); munmap(shmptr, sizeof(WebViewRingBuffer));
close(shmfd); close(shmfd);




Loading…
Cancel
Save