init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled

This commit is contained in:
allhaileris
2026-02-16 15:50:16 +03:00
commit afb81b8278
13816 changed files with 3689732 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#include "webview/platform/linux/webview_linux.h"
#include "base/random.h"
#include "webview/platform/linux/webview_linux_webkitgtk.h"
namespace Webview {
Available Availability() {
return WebKitGTK::Availability();
}
bool SupportsEmbedAfterCreate() {
return true;
}
bool SeparateStorageIdSupported() {
return true;
}
std::unique_ptr<Interface> CreateInstance(Config config) {
return WebKitGTK::CreateInstance(std::move(config));
}
std::string GenerateStorageToken() {
constexpr auto kSize = 16;
auto result = std::string(kSize, ' ');
base::RandomFill(result.data(), result.size());
return result;
}
void ClearStorageDataByToken(const std::string &token) {
}
} // namespace Webview

View File

@@ -0,0 +1,9 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#pragma once
#include "webview/webview_interface.h"

View File

@@ -0,0 +1,306 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#include "webview/platform/linux/webview_linux_compositor.h"
#ifdef DESKTOP_APP_WEBVIEW_WAYLAND_COMPOSITOR
#include "base/flat_map.h"
#include "base/unique_qptr.h"
#include "base/qt_signal_producer.h"
#include "base/event_filter.h"
#include <QtQuickWidgets/QQuickWidget>
#include <QtWaylandCompositor/QWaylandXdgSurface>
#include <QtWaylandCompositor/QWaylandXdgOutputV1>
#include <QtWaylandCompositor/QWaylandQuickOutput>
#include <QtWaylandCompositor/QWaylandQuickShellSurfaceItem>
namespace Webview {
struct Compositor::Private {
Private(Compositor *parent)
: shell(parent)
, xdgOutput(parent) {
}
QPointer<QQuickWidget> widget;
base::unique_qptr<Output> output;
QWaylandXdgShell shell;
QWaylandXdgOutputManagerV1 xdgOutput;
rpl::lifetime lifetime;
};
class Compositor::Chrome : public QWaylandQuickShellSurfaceItem {
public:
Chrome(
Output *output,
QQuickWindow *window,
QWaylandXdgSurface *xdgSurface,
bool windowFollowsSize);
rpl::producer<> surfaceCompleted() const {
return _completed.value()
| rpl::filter(rpl::mappers::_1)
| rpl::to_empty;
}
private:
QQuickItem _moveItem;
rpl::variable<bool> _completed = false;
rpl::lifetime _lifetime;
};
class Compositor::Output : public QWaylandQuickOutput {
public:
Output(Compositor *compositor, QObject *parent = nullptr)
: _xdg(this, &compositor->_private->xdgOutput) {
const auto xdgSurface = qobject_cast<QWaylandXdgSurface*>(parent);
const auto window = qobject_cast<QQuickWindow*>(parent);
setParent(parent);
setCompositor(compositor);
setWindow(window ? window : &_ownedWindow.emplace());
setScaleFactor(this->window()->devicePixelRatio());
setSizeFollowsWindow(true);
this->window()->setProperty("output", QVariant::fromValue(this));
#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
base::install_event_filter(this, this->window(), [=](
not_null<QEvent*> e) {
if (e->type() == QEvent::DevicePixelRatioChange) {
setScaleFactor(this->window()->devicePixelRatio());
}
return base::EventFilterResult::Continue;
});
#endif // Qt >= 6.6.0
rpl::single(rpl::empty) | rpl::then(
rpl::merge(
base::qt_signal_producer(
this,
&QWaylandOutput::geometryChanged
),
base::qt_signal_producer(
this,
&QWaylandOutput::scaleFactorChanged
)
)
) | rpl::map([=] {
return std::make_tuple(geometry(), scaleFactor());
}) | rpl::on_next([=](QRect geometry, int scaleFactor) {
_xdg.setLogicalPosition(geometry.topLeft() / scaleFactor);
_xdg.setLogicalSize(geometry.size() / scaleFactor);
}, _lifetime);
setXdgSurface(xdgSurface);
}
QQuickWindow *window() const {
return static_cast<QQuickWindow*>(QWaylandQuickOutput::window());
}
Chrome *chrome() const {
return _chrome;
}
void setXdgSurface(QWaylandXdgSurface *xdgSurface) {
if (xdgSurface) {
_chrome.emplace(this, window(), xdgSurface, bool(_ownedWindow));
} else {
_chrome.reset();
}
}
private:
QWaylandXdgOutputV1 _xdg;
std::optional<QQuickWindow> _ownedWindow;
base::unique_qptr<Chrome> _chrome;
rpl::lifetime _lifetime;
};
Compositor::Chrome::Chrome(
Output *output,
QQuickWindow *window,
QWaylandXdgSurface *xdgSurface,
bool windowFollowsSize)
: QWaylandQuickShellSurfaceItem(window->contentItem()) {
base::qt_signal_producer(
xdgSurface,
&QObject::destroyed
) | rpl::on_next([=] {
delete this;
}, _lifetime);
rpl::single(rpl::empty) | rpl::then(
base::qt_signal_producer(
view(),
&QWaylandView::surfaceChanged
)
) | rpl::on_next([=] {
setOutput(output);
}, _lifetime);
setShellSurface(xdgSurface);
setAutoCreatePopupItems(false);
setMoveItem(&_moveItem);
_moveItem.setEnabled(false);
xdgSurface->setProperty("window", QVariant::fromValue(window));
base::install_event_filter(this, window, [=](not_null<QEvent*> e) {
if (e->type() != QEvent::Close) {
return base::EventFilterResult::Continue;
}
e->ignore();
if (const auto toplevel = xdgSurface->toplevel()) {
toplevel->sendClose();
} else if (const auto popup = xdgSurface->popup()) {
popup->sendPopupDone();
}
return base::EventFilterResult::Cancel;
});
rpl::single(rpl::empty) | rpl::then(
rpl::merge(
base::qt_signal_producer(
window,
&QWindow::widthChanged
),
base::qt_signal_producer(
window,
&QWindow::heightChanged
)
) | rpl::to_empty
) | rpl::map([=] {
return window->size();
}) | rpl::distinct_until_changed(
) | rpl::filter([=](const QSize &size) {
return !size.isEmpty();
}) | rpl::on_next([=](const QSize &size) {
if (const auto toplevel = xdgSurface->toplevel()) {
toplevel->sendFullscreen(size);
}
}, _lifetime);
rpl::single(rpl::empty) | rpl::then(
rpl::merge(
base::qt_signal_producer(
xdgSurface->surface(),
&QWaylandSurface::destinationSizeChanged
),
base::qt_signal_producer(
xdgSurface,
&QWaylandXdgSurface::windowGeometryChanged
)
)
) | rpl::map([=] {
return xdgSurface->windowGeometry().isValid()
? xdgSurface->windowGeometry()
: QRect(QPoint(), xdgSurface->surface()->destinationSize());
}) | rpl::distinct_until_changed(
) | rpl::filter([=](const QRect &geometry) {
return geometry.isValid();
}) | rpl::on_next([=](const QRect &geometry) {
setX(-geometry.x());
setY(-geometry.y());
if (windowFollowsSize) {
if (xdgSurface->popup()) {
window->setMinimumSize(geometry.size());
window->setMaximumSize(geometry.size());
} else {
window->resize(geometry.size());
}
}
_completed = true;
}, _lifetime);
if (const auto toplevel = xdgSurface->toplevel()) {
rpl::single(rpl::empty) | rpl::then(
base::qt_signal_producer(
toplevel,
&QWaylandXdgToplevel::titleChanged
)
) | rpl::map([=] {
return toplevel->title();
}) | rpl::on_next([=](const QString &title) {
window->setTitle(title);
}, _lifetime);
rpl::single(rpl::empty) | rpl::then(
base::qt_signal_producer(
toplevel,
&QWaylandXdgToplevel::fullscreenChanged
)
) | rpl::map([=] {
return toplevel->fullscreen();
}) | rpl::on_next([=](bool fullscreen) {
if (!fullscreen) {
toplevel->sendFullscreen(window->size());
}
}, _lifetime);
}
}
Compositor::Compositor(const QByteArray &socketName)
: _private(std::make_unique<Private>(this)) {
connect(&_private->shell, &QWaylandXdgShell::toplevelCreated, [=](
QWaylandXdgToplevel *toplevel,
QWaylandXdgSurface *xdgSurface) {
if (!_private->output || _private->output->chrome()) {
const auto output = new Output(this, xdgSurface);
output->chrome()->surfaceCompleted() | rpl::on_next([=] {
output->window()->show();
}, _private->lifetime);
} else {
_private->output->setXdgSurface(xdgSurface);
}
});
connect(&_private->shell, &QWaylandXdgShell::popupCreated, [=](
QWaylandXdgPopup *popup,
QWaylandXdgSurface *xdgSurface) {
const auto widget = _private->widget;
const auto parent = (*static_cast<QQuickWindow * const *>(
popup->parentXdgSurface()->property("window").constData()
));
const auto output = (*static_cast<Output * const *>(
parent->property("output").constData()
));
const auto window = new QQuickWindow;
static_cast<QObject*>(window)->setParent(xdgSurface);
window->setProperty("output", QVariant::fromValue(output));
const auto chrome = new Chrome(output, window, xdgSurface, true);
chrome->surfaceCompleted() | rpl::on_next([=] {
if (widget && parent == widget->quickWindow()) {
window->setTransientParent(widget->window()->windowHandle());
window->setPosition(
popup->unconstrainedPosition()
+ widget->mapToGlobal(QPoint()));
} else {
window->setTransientParent(parent);
window->setPosition(
popup->unconstrainedPosition() + parent->position());
}
window->setFlag(Qt::Popup);
window->setColor(Qt::transparent);
window->show();
}, _private->lifetime);
});
setSocketName(socketName);
create();
}
void Compositor::setWidget(QQuickWidget *widget) {
_private->widget = widget;
if (widget) {
_private->output.emplace(this, widget->quickWindow());
} else {
_private->output.reset();
}
}
} // namespace Webview
#endif // DESKTOP_APP_WEBVIEW_WAYLAND_COMPOSITOR

View File

@@ -0,0 +1,51 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#pragma once
#include <QtCore/QObject>
#if defined QT_QUICKWIDGETS_LIB && defined QT_WAYLANDCOMPOSITOR_LIB
#include <QtWaylandCompositor/qtwaylandcompositor-config.h>
#if QT_CONFIG(wayland_compositor_quick)
#include <QtWaylandCompositor/QWaylandQuickCompositor>
#define DESKTOP_APP_WEBVIEW_WAYLAND_COMPOSITOR
class QQuickWidget;
namespace Webview {
class Compositor : public QWaylandQuickCompositor {
public:
Compositor(const QByteArray &socketName = {});
void setWidget(QQuickWidget *widget);
private:
class Output;
class Chrome;
struct Private;
const std::unique_ptr<Private> _private;
};
} // namespace Webview
#endif // QT_CONFIG(wayland_compositor_quick)
#endif // QT_QUICKWIDGETS_LIB && QT_WAYLANDCOMPOSITOR_LIB
#ifndef DESKTOP_APP_WEBVIEW_WAYLAND_COMPOSITOR
namespace Webview {
class Compositor : public QObject {
public:
Compositor(const QByteArray &socketName = {}) {}
QString socketName() { return {}; }
};
} // namespace Webview
#endif // !DESKTOP_APP_WEBVIEW_WAYLAND_COMPOSITOR

View File

@@ -0,0 +1,189 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#include "webview/platform/linux/webview_linux_http_server.h"
#include <QtCore/QPointer>
#include <QtNetwork/QTcpSocket>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <crl/crl.h>
namespace Webview {
struct HttpServer::Private {
void handleRequest(QTcpSocket *socket);
bool processRedirect(
QTcpSocket *socket,
const QByteArray &id,
const ::base::flat_map<QByteArray, QByteArray> &headers,
const std::shared_ptr<Guard> &guard);
QNetworkAccessManager manager;
QByteArray password;
std::function<void(
QTcpSocket *socket,
const QByteArray &id,
const ::base::flat_map<QByteArray, QByteArray> &headers,
const std::shared_ptr<Guard> &guard)> handler;
};
void HttpServer::Private::handleRequest(QTcpSocket *socket) {
const auto guard = std::make_shared<Guard>(crl::guard(socket, [=] {
QMetaObject::invokeMethod(socket, [=] {
socket->disconnectFromHost();
});
}));
const auto firstLine = socket->readLine().simplified().split(' ');
if (firstLine.size() < 2 || firstLine[0] != "GET") {
return;
}
const auto headers = [&] {
auto result = ::base::flat_map<QByteArray, QByteArray>();
while (true) {
const auto line = socket->readLine();
const auto separator = line.indexOf(':');
if (separator <= 0) {
break;
}
const auto name = line.mid(0, separator).simplified();
const auto value = line.mid(separator + 1).simplified();
result.emplace(name, value);
}
return result;
}();
const auto getHeader = [&](const QByteArray &key) {
const auto it = headers.find(key);
return it != headers.end()
? it->second
: QByteArray();
};
const auto authed = [&] {
const auto auth = getHeader("Authorization");
if (auth.startsWith("Basic ")) {
const auto userPass = QByteArray::fromBase64(auth.mid(6));
if (userPass == ':' + password) {
return true;
}
}
return false;
}();
if (!authed) {
socket->write("HTTP/1.1 401 Unauthorized\r\n");
socket->write("WWW-Authenticate: Basic realm=\"\"\r\n");
socket->write("\r\n");
return;
}
const auto id = firstLine[1].mid(1);
if (processRedirect(socket, id, headers, guard) || !handler) {
return;
}
handler(socket, id, headers, guard);
}
bool HttpServer::Private::processRedirect(
QTcpSocket *socket,
const QByteArray &id,
const ::base::flat_map<QByteArray, QByteArray> &headers,
const std::shared_ptr<Guard> &guard) {
const auto dot = id.indexOf('.');
const auto slash = id.indexOf('/');
if (dot < 0 || slash < 0 || dot > slash) {
return false;
}
auto request = QNetworkRequest();
request.setUrl(QString::fromUtf8("https://" + id));
if (!headers.empty()) {
const auto headersToCopy = {
"Accept",
"User-Agent",
"Accept-Language",
"Accept-Encoding",
};
for (const auto name : headersToCopy) {
const auto it = headers.find(name);
if (it == headers.end()) {
continue;
}
request.setRawHeader(name, it->second.constData());
}
}
// Always set our own Referer
request.setRawHeader("Referer", "http://desktop-app-resource/page.html");
const auto reply = manager.get(request);
connect(socket, &QObject::destroyed, reply, &QObject::deleteLater);
connect(reply, &QNetworkReply::finished, socket, [=] {
(void) guard;
const auto input = reply->readAll();
socket->write("HTTP/1.1 200 OK\r\n");
const auto headersToCopy = {
"Content-Type",
"Content-Encoding",
"Content-Length",
};
for (const auto name : headersToCopy) {
if (!reply->hasRawHeader(name)) {
continue;
}
socket->write(
std::format(
"{}: {}\r\n",
name,
reply->rawHeader(name).toStdString()
).c_str()
);
}
socket->write("Cache-Control: no-store\r\n");
socket->write("\r\n");
socket->write(input);
}, Qt::SingleShotConnection);
return true;
}
HttpServer::HttpServer(
const QByteArray &password,
const std::function<void(
QTcpSocket *socket,
const QByteArray &id,
const ::base::flat_map<QByteArray, QByteArray> &headers,
const std::shared_ptr<Guard> &guard)> &handler)
: _private(std::make_unique<Private>()) {
_private->password = password;
_private->handler = handler;
connect(this, &QTcpServer::newConnection, [=] {
while (const auto socket = nextPendingConnection()) {
connect(
socket,
&QAbstractSocket::disconnected,
socket,
&QObject::deleteLater);
connect(socket, &QIODevice::readyRead, this, [=] {
_private->handleRequest(socket);
}, Qt::SingleShotConnection);
}
});
}
HttpServer::~HttpServer() = default;
} // namespace Webview

View File

@@ -0,0 +1,36 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#pragma once
#include "base/flat_map.h"
#include <QtNetwork/QTcpServer>
#include <gsl/gsl>
namespace Webview {
class HttpServer : public QTcpServer {
public:
using Guard = gsl::final_action<std::function<void()>>;
HttpServer(
const QByteArray &password,
const std::function<void(
QTcpSocket *socket,
const QByteArray &id,
const ::base::flat_map<QByteArray, QByteArray> &headers,
const std::shared_ptr<Guard> &guard)> &handler);
~HttpServer();
private:
struct Private;
const std::unique_ptr<Private> _private;
};
} // namespace Webview

View File

@@ -0,0 +1,74 @@
<node>
<interface name='org.desktop_app.GtkIntegration.Webview.Master'>
<method name='GetStartData'>
<arg type='i' name='platform' direction='out'/>
<arg type='s' name='waylandDisplay' direction='out'/>
<arg type='s' name='appId' direction='out'/>
</method>
<method name='MessageReceived'>
<arg type='ay' name='message' direction='in'/>
</method>
<method name='NavigationStarted'>
<arg type='s' name='uri' direction='in'/>
<arg type='b' name='newWindow' direction='in'/>
<arg type='b' name='result' direction='out'/>
</method>
<method name='NavigationDone'>
<arg type='b' name='success' direction='in'/>
</method>
<method name='ScriptDialog'>
<arg type='i' name='type' direction='in'/>
<arg type='s' name='text' direction='in'/>
<arg type='s' name='value' direction='in'/>
<arg type='b' name='accepted' direction='out'/>
<arg type='s' name='text' direction='out'/>
</method>
<method name='NavigationStateUpdate'>
<arg type='s' name='url' direction='in'/>
<arg type='s' name='title' direction='in'/>
<arg type='b' name='canGoBack' direction='in'/>
<arg type='b' name='canGoForward' direction='in'/>
</method>
<signal name='DataServerStarted'>
<arg type='q' name='port'/>
<arg type='s' name='password'/>
</signal>
</interface>
<interface name='org.desktop_app.GtkIntegration.Webview.Helper'>
<method name='Create'>
<arg type='b' name='debug' direction='in'/>
<arg type='i' name='r' direction='in'/>
<arg type='i' name='g' direction='in'/>
<arg type='i' name='b' direction='in'/>
<arg type='i' name='a' direction='in'/>
<arg type='s' name='path' direction='in'/>
</method>
<method name='Reload'/>
<method name='Resolve'>
<arg type='i' name='result' direction='out'/>
</method>
<method name='Navigate'>
<arg type='s' name='url' direction='in'/>
</method>
<method name='Resize'>
<arg type='i' name='w' direction='in'/>
<arg type='i' name='h' direction='in'/>
</method>
<method name='Init'>
<arg type='ay' name='js' direction='in'/>
</method>
<method name='Eval'>
<arg type='ay' name='js' direction='in'/>
</method>
<method name='SetOpaqueBg'>
<arg type='i' name='r' direction='in'/>
<arg type='i' name='g' direction='in'/>
<arg type='i' name='b' direction='in'/>
<arg type='i' name='a' direction='in'/>
</method>
<method name='GetWinId'>
<arg type='t' name='result' direction='out'/>
</method>
<signal name='Started'/>
</interface>
</node>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#pragma once
#include "webview/platform/linux/webview_linux.h"
namespace Webview::WebKitGTK {
[[nodiscard]] Available Availability();
[[nodiscard]] std::unique_ptr<Interface> CreateInstance(Config config);
int Exec();
void SetSocketPath(const std::string &socketPath);
} // namespace Webview::WebKitGTK

View File

@@ -0,0 +1,107 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#include "webview/platform/linux/webview_linux_webkitgtk_library.h"
#include "base/platform/linux/base_linux_library.h"
namespace Webview::WebKitGTK::Library {
ResolveResult Resolve(const Platform &platform) {
const auto lib = (platform != Platform::X11
? base::Platform::LoadLibrary("libwebkitgtk-6.0.so.4", RTLD_NODELETE)
: nullptr)
?: base::Platform::LoadLibrary("libwebkit2gtk-4.1.so.0", RTLD_NODELETE)
?: base::Platform::LoadLibrary("libwebkit2gtk-4.0.so.37", RTLD_NODELETE);
const auto result = lib
&& LOAD_LIBRARY_SYMBOL(lib, gtk_init_check)
&& LOAD_LIBRARY_SYMBOL(lib, gtk_widget_get_type)
&& (LOAD_LIBRARY_SYMBOL(lib, gtk_window_set_child)
|| (LOAD_LIBRARY_SYMBOL(lib, gtk_container_get_type)
&& LOAD_LIBRARY_SYMBOL(lib, gtk_container_add)))
&& LOAD_LIBRARY_SYMBOL(lib, gtk_window_new)
&& LOAD_LIBRARY_SYMBOL(lib, gtk_scrolled_window_new)
&& (LOAD_LIBRARY_SYMBOL(lib, gtk_window_destroy)
|| LOAD_LIBRARY_SYMBOL(lib, gtk_widget_destroy))
&& LOAD_LIBRARY_SYMBOL(lib, gtk_widget_set_size_request)
&& LOAD_LIBRARY_SYMBOL(lib, gtk_widget_set_visible)
&& LOAD_LIBRARY_SYMBOL(lib, gtk_window_get_type)
&& LOAD_LIBRARY_SYMBOL(lib, gtk_widget_get_display)
&& (LOAD_LIBRARY_SYMBOL(lib, gtk_widget_add_css_class)
|| (LOAD_LIBRARY_SYMBOL(lib, gtk_widget_get_style_context)
&& LOAD_LIBRARY_SYMBOL(lib, gtk_style_context_add_class)))
&& (LOAD_LIBRARY_SYMBOL(lib, gtk_style_context_add_provider_for_display)
|| LOAD_LIBRARY_SYMBOL(lib, gtk_style_context_add_provider_for_screen))
&& LOAD_LIBRARY_SYMBOL(lib, gtk_style_provider_get_type)
&& LOAD_LIBRARY_SYMBOL(lib, gtk_css_provider_new)
&& (LOAD_LIBRARY_SYMBOL(lib, gtk_css_provider_load_from_string)
|| LOAD_LIBRARY_SYMBOL(lib, gtk_css_provider_load_from_data))
&& (platform != Platform::X11
|| (LOAD_LIBRARY_SYMBOL(lib, gtk_plug_new)
&& LOAD_LIBRARY_SYMBOL(lib, gtk_plug_get_id)
&& LOAD_LIBRARY_SYMBOL(lib, gtk_plug_get_type)))
&& LOAD_LIBRARY_SYMBOL(lib, jsc_value_to_string)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_navigation_policy_decision_get_type)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_navigation_policy_decision_get_navigation_action)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_navigation_action_get_request)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_uri_request_get_uri)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_policy_decision_ignore)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_script_dialog_get_dialog_type)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_script_dialog_get_message)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_script_dialog_confirm_set_confirmed)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_script_dialog_prompt_get_default_text)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_script_dialog_prompt_set_text)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_web_view_get_type)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_web_view_get_is_web_process_responsive)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_web_view_get_user_content_manager)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_web_view_get_uri)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_web_view_get_title)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_web_view_can_go_back)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_web_view_can_go_forward)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_user_content_manager_register_script_message_handler)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_web_view_get_settings)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_settings_set_enable_developer_extras)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_web_view_is_loading)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_web_view_load_uri)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_web_view_reload_bypass_cache)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_user_script_new)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_user_content_manager_add_script)
&& (LOAD_LIBRARY_SYMBOL(lib, webkit_web_view_evaluate_javascript)
|| LOAD_LIBRARY_SYMBOL(lib, webkit_web_view_run_javascript))
&& LOAD_LIBRARY_SYMBOL(lib, webkit_web_view_set_background_color)
&& (LOAD_LIBRARY_SYMBOL(lib, webkit_network_session_new)
|| (LOAD_LIBRARY_SYMBOL(lib, webkit_web_view_new_with_context)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_website_data_manager_new)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_web_context_new_with_website_data_manager)))
&& LOAD_LIBRARY_SYMBOL(lib, webkit_authentication_request_authenticate)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_authentication_request_get_host)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_authentication_request_get_port)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_credential_new)
&& LOAD_LIBRARY_SYMBOL(lib, webkit_credential_free);
if (!result) {
return ResolveResult::NoLibrary;
}
LOAD_LIBRARY_SYMBOL(lib, gtk_widget_show_all);
LOAD_LIBRARY_SYMBOL(lib, gtk_widget_get_screen);
LOAD_LIBRARY_SYMBOL(lib, webkit_javascript_result_get_js_value);
LOAD_LIBRARY_SYMBOL(lib, webkit_website_data_manager_new);
LOAD_LIBRARY_SYMBOL(lib, webkit_web_context_new_with_website_data_manager);
if (LOAD_LIBRARY_SYMBOL(lib, gdk_set_allowed_backends)) {
switch (platform) {
case Platform::Wayland:
gdk_set_allowed_backends("wayland");
break;
case Platform::X11:
gdk_set_allowed_backends("x11");
break;
}
}
return gtk_init_check(0, 0)
? ResolveResult::Success
: ResolveResult::CantInit;
}
} // namespace Webview::WebKitGTK::Library

View File

@@ -0,0 +1,288 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#pragma once
#include <gio/gio.h>
#define GTK_TYPE_CONTAINER (gtk_container_get_type ())
#define GTK_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CONTAINER, GtkContainer))
#define GTK_TYPE_WIDGET (gtk_widget_get_type ())
#define GTK_WIDGET(widget) (G_TYPE_CHECK_INSTANCE_CAST ((widget), GTK_TYPE_WIDGET, GtkWidget))
#define GTK_TYPE_WINDOW (gtk_window_get_type ())
#define GTK_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WINDOW, GtkWindow))
#define GTK_TYPE_PLUG (gtk_plug_get_type ())
#define GTK_PLUG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PLUG, GtkPlug))
#define GTK_TYPE_STYLE_PROVIDER (gtk_style_provider_get_type ())
#define GTK_STYLE_PROVIDER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_STYLE_PROVIDER, GtkStyleProvider))
#define GTK_STYLE_PROVIDER_PRIORITY_APPLICATION 600
#define WEBKIT_TYPE_NAVIGATION_POLICY_DECISION (webkit_navigation_policy_decision_get_type())
#define WEBKIT_NAVIGATION_POLICY_DECISION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_NAVIGATION_POLICY_DECISION, WebKitNavigationPolicyDecision))
#define WEBKIT_TYPE_WEB_VIEW (webkit_web_view_get_type())
#define WEBKIT_WEB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_WEB_VIEW, WebKitWebView))
struct _GdkRGBA {
float red;
float green;
float blue;
float alpha;
};
typedef struct _GdkDisplay GdkDisplay;
typedef struct _GdkScreen GdkScreen;
typedef struct _GdkRGBA GdkRGBA;
typedef struct _GtkContainer GtkContainer;
typedef struct _GtkWidget GtkWidget;
typedef struct _GtkWindow GtkWindow;
typedef struct _GtkPlug GtkPlug;
typedef struct _GtkAdjustment GtkAdjustment;
typedef struct _GtkStyleContext GtkStyleContext;
typedef struct _GtkStyleProvider GtkStyleProvider;
typedef struct _GtkCssProvider GtkCssProvider;
typedef struct _JSCValue JSCValue;
typedef struct _WebKitJavascriptResult WebKitJavascriptResult;
typedef struct _WebKitNavigationAction WebKitNavigationAction;
typedef struct _WebKitNavigationPolicyDecision WebKitNavigationPolicyDecision;
typedef struct _WebKitPolicyDecision WebKitPolicyDecision;
typedef struct _WebKitURIRequest WebKitURIRequest;
typedef struct _WebKitUserContentManager WebKitUserContentManager;
typedef struct _WebKitUserScript WebKitUserScript;
typedef struct _WebKitWebView WebKitWebView;
typedef struct _WebKitSettings WebKitSettings;
typedef struct _WebKitScriptDialog WebKitScriptDialog;
typedef struct _WebKitWebsiteDataManager WebKitWebsiteDataManager;
typedef struct _WebKitWebContext WebKitWebContext;
typedef struct _WebKitNetworkSession WebKitNetworkSession;
typedef struct _WebKitAuthenticationRequest WebKitAuthenticationRequest;
typedef struct _WebKitCredential WebKitCredential;
typedef enum {
GTK_WINDOW_TOPLEVEL,
GTK_WINDOW_POPUP,
} GtkWindowType;
typedef enum {
WEBKIT_WEB_PROCESS_CRASHED,
WEBKIT_WEB_PROCESS_EXCEEDED_MEMORY_LIMIT,
WEBKIT_WEB_PROCESS_TERMINATED_BY_API,
} WebKitWebProcessTerminationReason;
typedef enum {
WEBKIT_LOAD_STARTED,
WEBKIT_LOAD_REDIRECTED,
WEBKIT_LOAD_COMMITTED,
WEBKIT_LOAD_FINISHED,
} WebKitLoadEvent;
typedef enum {
WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION,
WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION,
WEBKIT_POLICY_DECISION_TYPE_RESPONSE,
} WebKitPolicyDecisionType;
typedef enum {
WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
WEBKIT_USER_CONTENT_INJECT_TOP_FRAME,
} WebKitUserContentInjectedFrames;
typedef enum {
WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START,
WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END,
} WebKitUserScriptInjectionTime;
typedef enum {
WEBKIT_SCRIPT_DIALOG_ALERT,
WEBKIT_SCRIPT_DIALOG_CONFIRM,
WEBKIT_SCRIPT_DIALOG_PROMPT,
WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM,
} WebKitScriptDialogType;
typedef enum {
WEBKIT_CREDENTIAL_PERSISTENCE_NONE,
WEBKIT_CREDENTIAL_PERSISTENCE_FOR_SESSION,
WEBKIT_CREDENTIAL_PERSISTENCE_PERMANENT,
} WebKitCredentialPersistence;
namespace Webview::WebKitGTK::Library {
inline gboolean (*gtk_init_check)(int *argc, char ***argv);
inline void (*gdk_set_allowed_backends)(const gchar *backends);
inline GType (*gtk_widget_get_type)(void);
inline GType (*gtk_container_get_type)(void);
inline void (*gtk_container_add)(
GtkContainer *container,
GtkWidget *widget);
inline void (*gtk_window_set_child)(
GtkWindow *window,
GtkWidget *child);
inline GtkWidget *(*gtk_window_new)(GtkWindowType type);
inline GtkWidget *(*gtk_scrolled_window_new)(
GtkAdjustment *hadjustment,
GtkAdjustment *vadjustment);
inline void (*gtk_window_destroy)(GtkWindow *widget);
inline void (*gtk_widget_destroy)(GtkWidget *widget);
inline void (*gtk_widget_set_size_request)(
GtkWidget *window,
gint width,
gint height);
inline void (*gtk_widget_set_visible)(GtkWidget *widget, gboolean visible);
inline void (*gtk_widget_show_all)(GtkWidget *widget);
inline GType (*gtk_window_get_type)(void);
inline GdkDisplay *(*gtk_widget_get_display)(GtkWidget *widget);
inline GdkScreen *(*gtk_widget_get_screen)(GtkWidget *widget);
inline GtkStyleContext *(*gtk_widget_get_style_context)(GtkWidget *widget);
inline void (*gtk_widget_add_css_class)(
GtkWidget *widget,
const char *css_class);
inline void (*gtk_style_context_add_provider_for_display)(
GdkDisplay *display,
GtkStyleProvider *provider,
guint priority);
inline void (*gtk_style_context_add_provider_for_screen)(
GdkScreen *screen,
GtkStyleProvider *provider,
guint priority);
inline void (*gtk_style_context_add_class)(
GtkStyleContext *context,
const char *class_name);
inline GType (*gtk_style_provider_get_type)(void);
inline GtkCssProvider *(*gtk_css_provider_new)(void);
inline void (*gtk_css_provider_load_from_string)(
GtkCssProvider *css_provider,
const char *string);
inline void (*gtk_css_provider_load_from_data)(
GtkCssProvider *css_provider,
const gchar *data,
gssize length,
GError **error);
// returns Window that is a typedef to unsigned long,
// but we avoid to include Xlib.h here
inline GtkWidget *(*gtk_plug_new)(unsigned long socket_id);
inline unsigned long (*gtk_plug_get_id)(GtkPlug *plug);
inline GType (*gtk_plug_get_type)(void);
inline char *(*jsc_value_to_string)(JSCValue *value);
inline JSCValue *(*webkit_javascript_result_get_js_value)(
WebKitJavascriptResult *js_result);
inline GType (*webkit_navigation_policy_decision_get_type)(void);
inline WebKitNavigationAction *(*webkit_navigation_policy_decision_get_navigation_action)(
WebKitNavigationPolicyDecision *decision);
inline WebKitURIRequest *(*webkit_navigation_action_get_request)(
WebKitNavigationAction *navigation);
inline const gchar *(*webkit_uri_request_get_uri)(WebKitURIRequest *request);
inline void (*webkit_policy_decision_ignore)(WebKitPolicyDecision *decision);
inline WebKitScriptDialogType (*webkit_script_dialog_get_dialog_type)(
WebKitScriptDialog *dialog);
inline const gchar *(*webkit_script_dialog_get_message)(
WebKitScriptDialog *dialog);
inline void (*webkit_script_dialog_confirm_set_confirmed)(
WebKitScriptDialog *dialog,
gboolean confirmed);
inline const gchar *(*webkit_script_dialog_prompt_get_default_text)(
WebKitScriptDialog *dialog);
inline void (*webkit_script_dialog_prompt_set_text)(
WebKitScriptDialog *dialog,
const gchar *text);
inline GtkWidget *(*webkit_web_view_new_with_context)(WebKitWebContext *context);
inline GType (*webkit_web_view_get_type)(void);
inline gboolean (*webkit_web_view_get_is_web_process_responsive)(
WebKitWebView *web_view);
inline WebKitUserContentManager *(*webkit_web_view_get_user_content_manager)(
WebKitWebView *web_view);
inline const gchar *(*webkit_web_view_get_uri)(WebKitWebView *web_view);
inline const gchar *(*webkit_web_view_get_title)(WebKitWebView *web_view);
inline gboolean (*webkit_web_view_can_go_back)(WebKitWebView *web_view);
inline gboolean (*webkit_web_view_can_go_forward)(WebKitWebView *web_view);
inline gboolean (*webkit_user_content_manager_register_script_message_handler)(
WebKitUserContentManager *manager,
const gchar *name,
const gchar *world_name);
inline WebKitSettings *(*webkit_web_view_get_settings)(
WebKitWebView *web_view);
inline void (*webkit_settings_set_enable_developer_extras)(
WebKitSettings *settings,
gboolean enabled);
inline gboolean (*webkit_web_view_is_loading)(WebKitWebView *web_view);
inline void (*webkit_web_view_load_uri)(
WebKitWebView *web_view,
const gchar *uri);
inline void (*webkit_web_view_reload_bypass_cache)(WebKitWebView *web_view);
inline WebKitUserScript *(*webkit_user_script_new)(
const gchar *source,
WebKitUserContentInjectedFrames injected_frames,
WebKitUserScriptInjectionTime injection_time,
const gchar *const *whitelist,
const gchar *const *blacklist);
inline void (*webkit_user_content_manager_add_script)(
WebKitUserContentManager *manager,
WebKitUserScript *script);
inline void (*webkit_web_view_evaluate_javascript)(
WebKitWebView *web_view,
const gchar *script,
gssize length,
const gchar *world_name,
const gchar *source_uri,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
inline void (*webkit_web_view_run_javascript)(
WebKitWebView *web_view,
const gchar *script,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
inline void (*webkit_web_view_set_background_color)(
WebKitWebView *web_view,
const GdkRGBA *rgba);
inline WebKitWebsiteDataManager *(*webkit_website_data_manager_new)(
const gchar *first_option_name,
...);
inline WebKitWebContext *(*webkit_web_context_new_with_website_data_manager)(
WebKitWebsiteDataManager* manager);
inline WebKitNetworkSession *(*webkit_network_session_new)(
const char* data_directory,
const char* cache_directory);
inline void (*webkit_authentication_request_authenticate)(
WebKitAuthenticationRequest *request,
WebKitCredential *credential);
inline const gchar *(*webkit_authentication_request_get_host)(
WebKitAuthenticationRequest *request);
inline guint (*webkit_authentication_request_get_port)(
WebKitAuthenticationRequest *request);
inline WebKitCredential *(*webkit_credential_new)(
const gchar *username,
const gchar *password,
WebKitCredentialPersistence persistence);
inline void (*webkit_credential_free)(WebKitCredential *credential);
enum class ResolveResult {
Success,
NoLibrary,
CantInit,
IPCFailure,
};
enum class Platform {
Any,
Wayland,
X11,
};
[[nodiscard]] ResolveResult Resolve(const Platform &platform);
} // namespace Webview::WebKitGTK::Library