From d89647e6d0b9d6d7efde9cb263248773707b4e22 Mon Sep 17 00:00:00 2001 From: falkTX Date: Wed, 25 Sep 2024 15:58:10 +0200 Subject: [PATCH] Delete old webview approach in favour of DPF one Signed-off-by: falkTX --- src/plugin/ChildProcess.hpp | 2 +- src/plugin/DesktopUI.cpp | 48 +-- src/plugin/DistrhoPluginInfo.h | 3 +- src/plugin/Makefile | 21 +- src/plugin/Time.hpp | 127 -------- src/plugin/WebView.hpp | 17 - src/plugin/WebViewCHOC.cpp | 87 ------ src/plugin/WebViewWK.mm | 205 ------------- src/plugin/WebViewX11.cpp | 546 --------------------------------- src/plugin/utils.cpp | 4 +- 10 files changed, 36 insertions(+), 1024 deletions(-) delete mode 100644 src/plugin/Time.hpp delete mode 100644 src/plugin/WebView.hpp delete mode 100644 src/plugin/WebViewCHOC.cpp delete mode 100644 src/plugin/WebViewWK.mm delete mode 100644 src/plugin/WebViewX11.cpp diff --git a/src/plugin/ChildProcess.hpp b/src/plugin/ChildProcess.hpp index 16f76ab..f3c0a93 100644 --- a/src/plugin/ChildProcess.hpp +++ b/src/plugin/ChildProcess.hpp @@ -4,7 +4,7 @@ #pragma once #include "extra/Sleep.hpp" -#include "Time.hpp" +#include "extra/Time.hpp" #ifdef DISTRHO_OS_WINDOWS # include diff --git a/src/plugin/DesktopUI.cpp b/src/plugin/DesktopUI.cpp index 967e5ba..35e4ab6 100644 --- a/src/plugin/DesktopUI.cpp +++ b/src/plugin/DesktopUI.cpp @@ -5,7 +5,7 @@ #include "DistrhoPluginUtils.hpp" #include "NanoButton.hpp" #include "ResizeHandle.hpp" -#include "WebView.hpp" +#include "extra/WebView.hpp" #include "utils.hpp" @@ -24,7 +24,7 @@ class DesktopUI : public UI, String errorDetail; ResizeHandle resizeHandle; int port = 0; - void* webview = nullptr; + WebViewHandle webview = nullptr; public: DesktopUI() @@ -76,7 +76,7 @@ class DesktopUI : public UI, ~DesktopUI() override { if (webview != nullptr) - destroyWebView(webview); + webViewDestroy(webview); } protected: @@ -106,7 +106,7 @@ class DesktopUI : public UI, if (webview != nullptr) { - destroyWebView(webview); + webViewDestroy(webview); webview = nullptr; buttonOpenWebGui.hide(); } @@ -154,7 +154,7 @@ class DesktopUI : public UI, if (webview != nullptr) { - destroyWebView(webview); + webViewDestroy(webview); webview = nullptr; buttonOpenWebGui.hide(); @@ -162,8 +162,25 @@ class DesktopUI : public UI, } port = nport; - d_stderr("webview port is %d", kPortNumOffset + port * 3 + 2); - webview = addWebView(getWindow().getNativeWindowHandle(), getScaleFactor(), kPortNumOffset + port * 3 + 2); + + const double scaleFactor = getScaleFactor(); + + uint offset = kVerticalOffset * scaleFactor; + uint width = getWidth(); + uint height = getHeight() - offset; + + WebViewOptions opts; + opts.offset.y = offset; + + char url[32] = {}; + std::snprintf(url, 31, "http://127.0.0.1:%u/", kPortNumOffset + port * 3 + 2); + + webview = webViewCreate(url, + getWindow().getNativeWindowHandle(), + width, + height, + scaleFactor, + opts); if (webview == nullptr) { @@ -225,7 +242,7 @@ class DesktopUI : public UI, { case 1: if (webview != nullptr) - reloadWebView(webview, kPortNumOffset + port * 3 + 2); + webViewReload(webview); break; case 2: openUserFilesDir(); @@ -244,18 +261,11 @@ class DesktopUI : public UI, return; const double scaleFactor = getScaleFactor(); + const uint offset = kVerticalOffset * scaleFactor; + const uint width = ev.size.getWidth(); + const uint height = ev.size.getHeight() - offset; - uint offset = kVerticalOffset * scaleFactor; - uint width = ev.size.getWidth(); - uint height = ev.size.getHeight() - offset; - - #ifdef DISTRHO_OS_MAC - offset /= scaleFactor; - width /= scaleFactor; - height /= scaleFactor; - #endif - - resizeWebView(webview, offset, width, height); + webViewResize(webview, width, height, scaleFactor); } // ------------------------------------------------------------------------------------------------------- diff --git a/src/plugin/DistrhoPluginInfo.h b/src/plugin/DistrhoPluginInfo.h index 33facb8..59e761e 100644 --- a/src/plugin/DistrhoPluginInfo.h +++ b/src/plugin/DistrhoPluginInfo.h @@ -21,11 +21,12 @@ #define DISTRHO_PLUGIN_WANT_STATE 1 #define DISTRHO_PLUGIN_WANT_FULL_STATE 1 #define DISTRHO_PLUGIN_WANT_WEBVIEW 1 -#define DISTRHO_UI_FILE_BROWSER 0 #define DISTRHO_UI_DEFAULT_WIDTH 1170 #define DISTRHO_UI_DEFAULT_HEIGHT 600 +#define DISTRHO_UI_FILE_BROWSER 0 #define DISTRHO_UI_USE_NANOVG 1 #define DISTRHO_UI_USER_RESIZABLE 1 +#define DISTRHO_UI_WEB_VIEW 1 static const constexpr unsigned int kVerticalOffset = 30; static const constexpr unsigned int kPortNumOffset = 18190; diff --git a/src/plugin/Makefile b/src/plugin/Makefile index c637d41..956df4d 100644 --- a/src/plugin/Makefile +++ b/src/plugin/Makefile @@ -2,8 +2,8 @@ export DISTRHO_NAMESPACE = DesktopDISTRHO export DGL_NAMESPACE = DesktopDGL -export FILE_BROWSER_DISABLED = true export NVG_FONT_TEXTURE_FLAGS = NVG_IMAGE_NEAREST +export USE_WEB_VIEW = true include ../DPF/Makefile.base.mk @@ -23,14 +23,6 @@ FILES_DSP = \ FILES_UI = DesktopUI.cpp NanoButton.cpp utils.cpp -ifeq ($(MACOS),true) -FILES_UI += WebViewWK.mm -else ifeq ($(WINDOWS),true) -FILES_UI += WebViewCHOC.cpp -else -FILES_UI += WebViewX11.cpp -endif - # --------------------------------------------------------------------------------------------------------------------- # Do some magic @@ -44,19 +36,10 @@ TARGETS = features au clap lv2_sep vst2 vst3 BUILD_CXX_FLAGS += -DVERSION='"$(shell cat ../../VERSION)"' BUILD_CXX_FLAGS += -pthread - -ifeq ($(MACOS),true) -else ifeq ($(WINDOWS),true) -BUILD_CXX_FLAGS += -I../CHOC -else -BUILD_CXX_FLAGS += $(shell $(PKG_CONFIG) --cflags Qt5Core) -# -std=gnu++14 -endif - LINK_FLAGS += -pthread ifeq ($(MACOS),true) -LINK_FLAGS += -framework CoreFoundation -framework IOKit -framework WebKit +LINK_FLAGS += -framework CoreFoundation -framework IOKit else ifeq ($(WINDOWS),true) LINK_FLAGS += -lole32 -luuid -lwinmm else diff --git a/src/plugin/Time.hpp b/src/plugin/Time.hpp deleted file mode 100644 index 91a1987..0000000 --- a/src/plugin/Time.hpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2024 Filipe Coelho - * - * Permission to use, copy, modify, and/or distribute this software for any purpose with - * or without fee is hereby granted, provided that the above copyright notice and this - * permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD - * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER - * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef DISTRHO_TIME_HPP_INCLUDED -#define DISTRHO_TIME_HPP_INCLUDED - -#include "DistrhoUtils.hpp" - -#ifdef DISTRHO_OS_WINDOWS -# include -# include -# include -#else -# include -#endif - -START_NAMESPACE_DISTRHO - -// ----------------------------------------------------------------------------------------------------------- -// d_gettime_* - -/* - * Get a monotonically-increasing time in milliseconds. - */ -static inline -uint32_t d_gettime_ms() noexcept -{ - #if defined(DISTRHO_OS_MAC) - static const time_t s = clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1000000; - return (clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1000000) - s; - #elif defined(DISTRHO_OS_WINDOWS) - return static_cast(timeGetTime()); - #else - static struct { - timespec ts; - int r; - uint32_t ms; - } s = { {}, clock_gettime(CLOCK_MONOTONIC, &s.ts), static_cast(s.ts.tv_sec * 1000 + - s.ts.tv_nsec / 1000000) }; - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000) - s.ms; - #endif -} - -/* - * Get a monotonically-increasing time in microseconds. - */ -static inline -uint64_t d_gettime_us() noexcept -{ - #if defined(DISTRHO_OS_MAC) - static const uint64_t s = clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1000; - return (clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1000) - s; - #elif defined(DISTRHO_OS_WINDOWS) - static struct { - LARGE_INTEGER freq; - LARGE_INTEGER counter; - BOOL r1, r2; - } s = { {}, {}, QueryPerformanceFrequency(&s.freq), QueryPerformanceCounter(&s.counter) }; - - LARGE_INTEGER counter; - QueryPerformanceCounter(&counter); - return (counter.QuadPart - s.counter.QuadPart) * 1000000 / s.freq.QuadPart; - #else - static struct { - timespec ts; - int r; - uint64_t us; - } s = { {}, clock_gettime(CLOCK_MONOTONIC, &s.ts), static_cast(s.ts.tv_sec * 1000000 + - s.ts.tv_nsec / 1000) }; - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (ts.tv_sec * 1000000 + ts.tv_nsec / 1000) - s.us; - #endif -} - -/* - * Get a monotonically-increasing time in nanoseconds. - */ -static inline -uint64_t d_gettime_ns() noexcept -{ - #if defined(DISTRHO_OS_MAC) - static const uint64_t s = clock_gettime_nsec_np(CLOCK_UPTIME_RAW); - return clock_gettime_nsec_np(CLOCK_UPTIME_RAW) - s; - #elif defined(DISTRHO_OS_WINDOWS) - static struct { - LARGE_INTEGER freq; - LARGE_INTEGER counter; - BOOL r1, r2; - } s = { {}, {}, QueryPerformanceFrequency(&s.freq), QueryPerformanceCounter(&s.counter) }; - - LARGE_INTEGER counter; - QueryPerformanceCounter(&counter); - return (counter.QuadPart - s.counter.QuadPart) * 1000000000ULL / s.freq.QuadPart; - #else - static struct { - timespec ts; - int r; - uint64_t ns; - } s = { {}, clock_gettime(CLOCK_MONOTONIC, &s.ts), static_cast(s.ts.tv_sec * 1000000000ULL + - s.ts.tv_nsec) }; - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (ts.tv_sec * 1000000000ULL + ts.tv_nsec) - s.ns; - #endif -} - -// ----------------------------------------------------------------------------------------------------------- - -END_NAMESPACE_DISTRHO - -#endif // DISTRHO_TIME_HPP_INCLUDED diff --git a/src/plugin/WebView.hpp b/src/plugin/WebView.hpp deleted file mode 100644 index 1bd95a9..0000000 --- a/src/plugin/WebView.hpp +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-FileCopyrightText: 2023-2024 MOD Audio UG -// SPDX-License-Identifier: AGPL-3.0-or-later - -#include "DistrhoUtils.hpp" - -START_NAMESPACE_DISTRHO - -// ----------------------------------------------------------------------------------------------------------- - -void* addWebView(uintptr_t parentWinId, double scaleFactor, uint port); -void destroyWebView(void* webview); -void reloadWebView(void* webview, uint port); -void resizeWebView(void* webview, uint offset, uint width, uint height); - -// ----------------------------------------------------------------------------------------------------------- - -END_NAMESPACE_DISTRHO diff --git a/src/plugin/WebViewCHOC.cpp b/src/plugin/WebViewCHOC.cpp deleted file mode 100644 index d271235..0000000 --- a/src/plugin/WebViewCHOC.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-FileCopyrightText: 2023-2024 MOD Audio UG -// SPDX-License-Identifier: AGPL-3.0-or-later - -#include "WebView.hpp" -#include "DistrhoPluginInfo.h" - -#define WC_ERR_INVALID_CHARS 0 -#include "gui/choc_WebView.h" - -#ifdef __APPLE__ -# import -#endif - -START_NAMESPACE_DISTRHO - -// ----------------------------------------------------------------------------------------------------------- - -void* addWebView(const uintptr_t parentWinId, const double scaleFactor, const uint port) -{ - std::unique_ptr webview = std::make_unique(); - DISTRHO_SAFE_ASSERT_RETURN(webview->loadedOK(), nullptr); - - void* const handle = webview->getViewHandle(); - DISTRHO_SAFE_ASSERT_RETURN(handle != nullptr, nullptr); - - char url[32] = {}; - std::snprintf(url, 31, "http://127.0.0.1:%u/", port); - webview->navigate(url); - - #if defined(__APPLE__) - NSView* const view = static_cast(handle); - - [reinterpret_cast(parentWinId) addSubview:view]; - [view setFrame:NSMakeRect(0, - kVerticalOffset, - DISTRHO_UI_DEFAULT_WIDTH, - DISTRHO_UI_DEFAULT_HEIGHT - kVerticalOffset)]; - #elif defined(_WIN32) - const HWND hwnd = static_cast(handle); - - LONG_PTR flags = GetWindowLongPtr(hwnd, -16); - flags = (flags & ~WS_POPUP) | WS_CHILD; - SetWindowLongPtr(hwnd, -16, flags); - - SetParent(hwnd, reinterpret_cast(parentWinId)); - SetWindowPos(hwnd, nullptr, - 0, - kVerticalOffset * scaleFactor, - DISTRHO_UI_DEFAULT_WIDTH * scaleFactor, - (DISTRHO_UI_DEFAULT_HEIGHT - kVerticalOffset) * scaleFactor, - SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); - ShowWindow(hwnd, SW_SHOW); - #endif - - return webview.release(); -} - -void destroyWebView(void* const webviewptr) -{ - delete static_cast(webviewptr); -} - -void reloadWebView(void* const webviewptr, const uint port) -{ - choc::ui::WebView* const webview = static_cast(webviewptr); - - char url[32] = {}; - std::snprintf(url, 31, "http://127.0.0.1:%u/", port); - webview->navigate(url); -} - -void resizeWebView(void* const webviewptr, const uint offset, const uint width, const uint height) -{ - choc::ui::WebView* const webview = static_cast(webviewptr); - - #if defined(__APPLE__) - NSView* const view = static_cast(webview->getViewHandle()); - [view setFrame:NSMakeRect(0, offset, width, height)]; - #elif defined(_WIN32) - const HWND hwnd = static_cast(webview->getViewHandle()); - SetWindowPos(hwnd, nullptr, 0, offset, width, height, SWP_NOZORDER | SWP_NOACTIVATE); - #endif -} - -// ----------------------------------------------------------------------------------------------------------- - -END_NAMESPACE_DISTRHO diff --git a/src/plugin/WebViewWK.mm b/src/plugin/WebViewWK.mm deleted file mode 100644 index d5a9583..0000000 --- a/src/plugin/WebViewWK.mm +++ /dev/null @@ -1,205 +0,0 @@ -// SPDX-FileCopyrightText: 2023-2024 MOD Audio UG -// SPDX-License-Identifier: AGPL-3.0-or-later - -#include "WebView.hpp" - -#include "DistrhoPluginInfo.h" - -#import -#import - -// ----------------------------------------------------------------------------------------------------------- - -#define MACRO_NAME2(a, b, c) a ## b ## c -#define MACRO_NAME(a, b, c) MACRO_NAME2(a, b, c) - -#define WEBVIEW_DELEGATE_CLASS_NAME \ - MACRO_NAME(WebViewDelegate_, _, DISTRHO_NAMESPACE) - -@interface WEBVIEW_DELEGATE_CLASS_NAME : NSObject -@end - -@implementation WEBVIEW_DELEGATE_CLASS_NAME - -- (void)webView:(WKWebView*)webview - runJavaScriptAlertPanelWithMessage:(NSString*)message - initiatedByFrame:(WKFrameInfo*)frame - completionHandler:(void (^)(void))completionHandler -{ - NSAlert* const alert = [[NSAlert alloc] init]; - [alert addButtonWithTitle:@"OK"]; - [alert setInformativeText:message]; - [alert setMessageText:@"Alert"]; - - dispatch_async(dispatch_get_main_queue(), ^ - { - [alert beginSheetModalForWindow:[webview window] - completionHandler:^(NSModalResponse) - { - completionHandler(); - [alert release]; - }]; - }); -} - -- (void)webView:(WKWebView*)webview - runJavaScriptConfirmPanelWithMessage:(NSString*)message - initiatedByFrame:(WKFrameInfo*)frame - completionHandler:(void (^)(BOOL))completionHandler -{ - NSAlert* const alert = [[NSAlert alloc] init]; - [alert addButtonWithTitle:@"OK"]; - [alert addButtonWithTitle:@"Cancel"]; - [alert setInformativeText:message]; - [alert setMessageText:@"Confirm"]; - - dispatch_async(dispatch_get_main_queue(), ^ - { - [alert beginSheetModalForWindow:[webview window] - completionHandler:^(NSModalResponse result) - { - completionHandler(result == NSAlertFirstButtonReturn); - [alert release]; - }]; - }); -} - -- (void)webView:(WKWebView*)webview - runJavaScriptTextInputPanelWithPrompt:(NSString*)prompt - defaultText:(NSString*)defaultText - initiatedByFrame:(WKFrameInfo*)frame - completionHandler:(void (^)(NSString*))completionHandler -{ - NSTextField* const input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 250, 30)]; - [input setStringValue:defaultText]; - - NSAlert* const alert = [[NSAlert alloc] init]; - [alert setAccessoryView:input]; - [alert addButtonWithTitle:@"OK"]; - [alert addButtonWithTitle:@"Cancel"]; - [alert setInformativeText:prompt]; - [alert setMessageText: @"Prompt"]; - - dispatch_async(dispatch_get_main_queue(), ^ - { - [alert beginSheetModalForWindow:[webview window] - completionHandler:^(NSModalResponse result) - { - [input validateEditing]; - completionHandler(result == NSAlertFirstButtonReturn ? [input stringValue] : nil); - [alert release]; - }]; - }); -} - -- (void)webView:(WKWebView*)webview - runOpenPanelWithParameters:(WKOpenPanelParameters*)params - initiatedByFrame:(WKFrameInfo*)frame - completionHandler:(void (^)(NSArray*))completionHandler -{ - NSOpenPanel* const panel = [[NSOpenPanel alloc] init]; - - [panel setAllowsMultipleSelection:[params allowsMultipleSelection]]; - // [panel setAllowedFileTypes:(NSArray*)[params _allowedFileExtensions]]; - [panel setCanChooseDirectories:[params allowsDirectories]]; - [panel setCanChooseFiles:![params allowsDirectories]]; - - dispatch_async(dispatch_get_main_queue(), ^ - { - [panel beginSheetModalForWindow:[webview window] - completionHandler:^(NSModalResponse result) - { - completionHandler(result == NSModalResponseOK ? [panel URLs] : nil); - [panel release]; - }]; - }); -} - -@end - -START_NAMESPACE_DISTRHO - -// ----------------------------------------------------------------------------------------------------------- - -struct WebViewImpl { - NSView* const view; - WKWebView* const webview; - NSURLRequest* const urlreq; - WEBVIEW_DELEGATE_CLASS_NAME* const delegate; -}; - -// ----------------------------------------------------------------------------------------------------------- - -void* addWebView(const uintptr_t parentWinId, double, const uint port) -{ - NSView* const view = reinterpret_cast(parentWinId); - - const CGRect rect = CGRectMake(0, - kVerticalOffset, - DISTRHO_UI_DEFAULT_WIDTH, - DISTRHO_UI_DEFAULT_HEIGHT - kVerticalOffset); - - WKPreferences* const prefs = [[WKPreferences alloc] init]; - [prefs setValue:@YES forKey:@"developerExtrasEnabled"]; - - WKWebViewConfiguration* const config = [[WKWebViewConfiguration alloc] init]; - config.preferences = prefs; - - WKWebView* const webview = [[WKWebView alloc] initWithFrame:rect - configuration:config]; - [view addSubview:webview]; - - WEBVIEW_DELEGATE_CLASS_NAME* const delegate = [[WEBVIEW_DELEGATE_CLASS_NAME alloc] init]; - webview.UIDelegate = delegate; - - char url[32]; - std::snprintf(url, 31, "http://127.0.0.1:%u/", port); - NSString* const nsurl = [[NSString alloc] initWithBytes:url - length:std::strlen(url) - encoding:NSUTF8StringEncoding]; - NSURLRequest* const urlreq = [[NSURLRequest alloc] initWithURL: [NSURL URLWithString: nsurl]]; - - [webview loadRequest:urlreq]; - [webview setHidden:NO]; - - [nsurl release]; - [config release]; - [prefs release]; - - return new WebViewImpl{view, webview, urlreq, delegate}; -} - -void destroyWebView(void* const webview) -{ - WebViewImpl* const impl = static_cast(webview); - - [impl->webview setHidden:YES]; - [impl->webview removeFromSuperview]; - [impl->urlreq release]; - [impl->delegate release]; - - delete impl; -} - -void reloadWebView(void* const webview, uint) -{ - WebViewImpl* const impl = static_cast(webview); - - [impl->webview loadRequest:impl->urlreq]; -} - -void resizeWebView(void* const webview, const uint offset, const uint width, const uint height) -{ - WebViewImpl* const impl = static_cast(webview); - - [impl->webview setFrame:CGRectMake(0, offset, width, height)]; -} - -// ----------------------------------------------------------------------------------------------------------- - -END_NAMESPACE_DISTRHO - -// ----------------------------------------------------------------------------------------------------------- - -#undef MACRO_NAME -#undef MACRO_NAME2 diff --git a/src/plugin/WebViewX11.cpp b/src/plugin/WebViewX11.cpp deleted file mode 100644 index 7c0c76d..0000000 --- a/src/plugin/WebViewX11.cpp +++ /dev/null @@ -1,546 +0,0 @@ -// SPDX-FileCopyrightText: 2023-2024 MOD Audio UG -// SPDX-License-Identifier: AGPL-3.0-or-later - -#define QT_NO_VERSION_TAGGING -#include -#include -#include -#undef signals - -#include "WebView.hpp" - -#include "ChildProcess.hpp" -#include "utils.hpp" - -#include "extra/String.hpp" -#include "DistrhoPluginUtils.hpp" - -#include -#include -#include -#include -#include -#include - -START_NAMESPACE_DISTRHO - -// ----------------------------------------------------------------------------------------------------------- - -struct WebViewX11 { - ChildProcess p; - ::Display* display; - ::Window childWindow; - ::Window ourWindow; -}; - -// ----------------------------------------------------------------------------------------------------------- - -void* addWebView(const uintptr_t parentWinId, const double scaleFactor, const uint port) -{ - char ldlinux[PATH_MAX] = {}; - { - Dl_info info = {}; - dladdr(dlsym(nullptr, "_rtld_global"), &info); - - if (info.dli_fname[0] == '.') - { - getcwd(ldlinux, PATH_MAX - 1); - std::strncat(ldlinux, info.dli_fname + 1, PATH_MAX - 1); - } - else if (info.dli_fname[0] != '/') - { - getcwd(ldlinux, PATH_MAX - 1); - std::strncat(ldlinux, "/", PATH_MAX - 1); - std::strncat(ldlinux, info.dli_fname, PATH_MAX - 1); - } - else - { - std::strncpy(ldlinux, info.dli_fname, PATH_MAX - 1); - } - } - const char* const filename = getBinaryFilename(); - - d_stdout("ld-linux is '%s'", ldlinux); - d_stdout("filename is '%s'", filename); - - ::Display* const display = XOpenDisplay(nullptr); - DISTRHO_SAFE_ASSERT_RETURN(display != nullptr, nullptr); - - // set up custom child environment - uint envsize = 0; - while (environ[envsize] != nullptr) - ++envsize; - - char** const envp = new char*[envsize + 5]; - - { - uint i = 0; - for (uint j = 0; j < envsize; ++j) - { - if (std::strncmp(environ[j], "LD_LIBRARY_PATH=", 16) == 0) - continue; - if (std::strncmp(environ[j], "LD_PRELOAD=", 11) == 0) - continue; - envp[i++] = strdup(environ[j]); - } - - for (; i < envsize + 5; ++i) - envp[i] = nullptr; - } - - set_envp_value(envp, "LANG=en_US.UTF-8"); - set_envp_value(envp, "DPF_WEBVIEW_PORT", String(port)); - set_envp_value(envp, "DPF_WEBVIEW_SCALE_FACTOR", String(scaleFactor)); - set_envp_value(envp, "DPF_WEBVIEW_WIN_ID", String(parentWinId)); - - WebViewX11* const ipc = new WebViewX11(); - ipc->display = display; - ipc->childWindow = 0; - ipc->ourWindow = parentWinId; - - const char* const args[] = { ldlinux, filename, "dpf-ld-linux-webview", nullptr }; - ipc->p.start(args, envp); - - for (uint i = 0; envp[i] != nullptr; ++i) - std::free(envp[i]); - delete[] envp; - - return ipc; -} - -void destroyWebView(void* const webviewptr) -{ - WebViewX11* const ipc = static_cast(webviewptr); - - XCloseDisplay(ipc->display); - delete ipc; -} - -void reloadWebView(void* const webviewptr, uint) -{ - WebViewX11* const ipc = static_cast(webviewptr); - - ipc->p.signal(SIGUSR1); -} - -void resizeWebView(void* const webviewptr, const uint offset, const uint width, const uint height) -{ - WebViewX11* const ipc = static_cast(webviewptr); - - if (ipc->childWindow == 0) - { - ::Window rootWindow, parentWindow; - ::Window* childWindows = nullptr; - uint numChildren = 0; - - XFlush(ipc->display); - XQueryTree(ipc->display, ipc->ourWindow, &rootWindow, &parentWindow, &childWindows, &numChildren); - - if (numChildren == 0 || childWindows == nullptr) - return; - - ipc->childWindow = childWindows[0]; - XFree(childWindows); - } - - XMoveResizeWindow(ipc->display, ipc->childWindow, 0, offset, width, height); - XFlush(ipc->display); -} - -// ----------------------------------------------------------------------------------------------------------- - -static std::function reloadFn; - -// ----------------------------------------------------------------------------------------------------------- - -struct GtkContainer; -struct GtkPlug; -struct GtkWidget; -struct GtkWindow; -struct WebKitSettings; -struct WebKitWebView; - -#define GTK_CONTAINER(p) reinterpret_cast(p) -#define GTK_PLUG(p) reinterpret_cast(p) -#define GTK_WINDOW(p) reinterpret_cast(p) -#define WEBKIT_WEB_VIEW(p) reinterpret_cast(p) - -struct QApplication; -struct QUrl; -struct QWebEngineView; -struct QWindow; - -// ----------------------------------------------------------------------------------------------------------- - -#define JOIN(A, B) A ## B - -#define AUTOSYM(S) \ - using JOIN(gtk3_, S) = decltype(&S); \ - JOIN(gtk3_, S) S = reinterpret_cast(dlsym(nullptr, #S)); \ - DISTRHO_SAFE_ASSERT_RETURN(S != nullptr, false); - -#define CSYM(S, NAME) \ - S NAME = reinterpret_cast(dlsym(nullptr, #NAME)); \ - DISTRHO_SAFE_ASSERT_RETURN(NAME != nullptr, false); - -#define CPPSYM(S, NAME, SN) \ - S NAME = reinterpret_cast(dlsym(nullptr, #SN)); \ - DISTRHO_SAFE_ASSERT_RETURN(NAME != nullptr, false); - -// ----------------------------------------------------------------------------------------------------------- -// gtk3 variant - -static bool gtk3(Display* const display, const Window winId, double scaleFactor, const char* const url) -{ - void* lib; - if ((lib = dlopen("libwebkit2gtk-4.0.so.37", RTLD_NOW|RTLD_GLOBAL)) == nullptr || - (lib = dlopen("libwebkit2gtk-4.0.so", RTLD_NOW|RTLD_GLOBAL)) == nullptr) - return false; - - using gdk_set_allowed_backends_t = void (*)(const char*); - using gtk_container_add_t = void (*)(GtkContainer*, GtkWidget*); - using gtk_init_check_t = bool (*)(int*, char***); - using gtk_main_t = void (*)(); - using gtk_plug_get_id_t = Window (*)(GtkPlug*); - using gtk_plug_new_t = GtkWidget* (*)(Window); - using gtk_widget_show_all_t = void (*)(GtkWidget*); - using gtk_window_move_t = void (*)(GtkWindow*, int, int); - using gtk_window_set_default_size_t = void (*)(GtkWindow*, int, int); - using webkit_settings_new_t = WebKitSettings* (*)(); - using webkit_settings_set_hardware_acceleration_policy_t = void (*)(WebKitSettings*, int); - using webkit_settings_set_javascript_can_access_clipboard_t = void (*)(WebKitSettings*, bool); - using webkit_web_view_load_uri_t = void (*)(WebKitWebView*, const char*); - using webkit_web_view_new_with_settings_t = GtkWidget* (*)(WebKitSettings*); - - CSYM(gdk_set_allowed_backends_t, gdk_set_allowed_backends) - CSYM(gtk_container_add_t, gtk_container_add) - CSYM(gtk_init_check_t, gtk_init_check) - CSYM(gtk_main_t, gtk_main) - CSYM(gtk_plug_get_id_t, gtk_plug_get_id) - CSYM(gtk_plug_new_t, gtk_plug_new) - CSYM(gtk_widget_show_all_t, gtk_widget_show_all) - CSYM(gtk_window_move_t, gtk_window_move) - CSYM(gtk_window_set_default_size_t, gtk_window_set_default_size) - CSYM(webkit_settings_new_t, webkit_settings_new) - CSYM(webkit_settings_set_hardware_acceleration_policy_t, webkit_settings_set_hardware_acceleration_policy) - CSYM(webkit_settings_set_javascript_can_access_clipboard_t, webkit_settings_set_javascript_can_access_clipboard) - CSYM(webkit_web_view_load_uri_t, webkit_web_view_load_uri) - CSYM(webkit_web_view_new_with_settings_t, webkit_web_view_new_with_settings) - - const int gdkScale = std::fmod(scaleFactor, 1.0) >= 0.75 - ? static_cast(scaleFactor + 0.5) - : static_cast(scaleFactor); - - if (gdkScale != 1) - { - char scale[8] = {}; - std::snprintf(scale, 7, "%d", gdkScale); - setenv("GDK_SCALE", scale, 1); - - std::snprintf(scale, 7, "%.2f", (1.0 / scaleFactor) * 1.2); - setenv("GDK_DPI_SCALE", scale, 1); - } - else if (scaleFactor > 1.0) - { - char scale[8] = {}; - std::snprintf(scale, 7, "%.2f", (1.0 / scaleFactor) * 1.4); - setenv("GDK_DPI_SCALE", scale, 1); - } - - scaleFactor /= gdkScale; - - gdk_set_allowed_backends("x11"); - - if (! gtk_init_check (nullptr, nullptr)) - return false; - - GtkWidget* const window = gtk_plug_new(winId); - DISTRHO_SAFE_ASSERT_RETURN(window != nullptr, false); - - gtk_window_set_default_size(GTK_WINDOW(window), - DISTRHO_UI_DEFAULT_WIDTH * scaleFactor, - (DISTRHO_UI_DEFAULT_HEIGHT - kVerticalOffset) * scaleFactor); - gtk_window_move(GTK_WINDOW(window), 0, kVerticalOffset * scaleFactor); - - WebKitSettings* const settings = webkit_settings_new(); - DISTRHO_SAFE_ASSERT_RETURN(settings != nullptr, false); - - webkit_settings_set_javascript_can_access_clipboard(settings, true); - webkit_settings_set_hardware_acceleration_policy(settings, 2 /* WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER */); - - GtkWidget* const webview = webkit_web_view_new_with_settings(settings); - DISTRHO_SAFE_ASSERT_RETURN(webview != nullptr, false); - - webkit_web_view_load_uri(WEBKIT_WEB_VIEW (webview), url); - - gtk_container_add(GTK_CONTAINER(window), webview); - - gtk_widget_show_all(window); - - Window wid = gtk_plug_get_id(GTK_PLUG(window)); - XMapWindow(display, wid); - XFlush(display); - - reloadFn = [=](){ - webkit_web_view_load_uri(WEBKIT_WEB_VIEW (webview), url); - }; - - gtk_main(); - - dlclose(lib); - return true; -} - -// ----------------------------------------------------------------------------------------------------------- -// qt5webengine variant - -static bool qt5webengine(const Window winId, const double scaleFactor, const char* const url) -{ - void* lib; - if ((lib = dlopen("libQt5WebEngineWidgets.so.5", RTLD_NOW|RTLD_GLOBAL)) == nullptr || - (lib = dlopen("libQt5WebEngineWidgets.so", RTLD_NOW|RTLD_GLOBAL)) == nullptr) - return false; - - using QApplication__init_t = void (*)(QApplication*, int&, char**, int); - using QApplication_exec_t = void (*)(); - using QApplication_setAttribute_t = void (*)(Qt::ApplicationAttribute, bool); - using QString__init_t = void (*)(void*, const QChar*, ptrdiff_t); - using QUrl__init_t = void (*)(void*, const QString&, int /* QUrl::ParsingMode */); - using QWebEngineView__init_t = void (*)(QWebEngineView*, void*); - using QWebEngineView_move_t = void (*)(QWebEngineView*, const QPoint&); - using QWebEngineView_resize_t = void (*)(QWebEngineView*, const QSize&); - using QWebEngineView_setUrl_t = void (*)(QWebEngineView*, const QUrl&); - using QWebEngineView_show_t = void (*)(QWebEngineView*); - using QWebEngineView_winId_t = ulonglong (*)(QWebEngineView*); - using QWebEngineView_windowHandle_t = QWindow* (*)(QWebEngineView*); - using QWindow_fromWinId_t = QWindow* (*)(ulonglong); - using QWindow_setParent_t = void (*)(QWindow*, void*); - - CPPSYM(QApplication__init_t, QApplication__init, _ZN12QApplicationC1ERiPPci) - CPPSYM(QApplication_exec_t, QApplication_exec, _ZN15QGuiApplication4execEv) - CPPSYM(QApplication_setAttribute_t, QApplication_setAttribute, _ZN16QCoreApplication12setAttributeEN2Qt20ApplicationAttributeEb) - CPPSYM(QString__init_t, QString__init, _ZN7QStringC2EPK5QChari) - CPPSYM(QUrl__init_t, QUrl__init, _ZN4QUrlC1ERK7QStringNS_11ParsingModeE) - CPPSYM(QWebEngineView__init_t, QWebEngineView__init, _ZN14QWebEngineViewC1EP7QWidget) - CPPSYM(QWebEngineView_move_t, QWebEngineView_move, _ZN7QWidget4moveERK6QPoint) - CPPSYM(QWebEngineView_resize_t, QWebEngineView_resize, _ZN7QWidget6resizeERK5QSize) - CPPSYM(QWebEngineView_setUrl_t, QWebEngineView_setUrl, _ZN14QWebEngineView6setUrlERK4QUrl) - CPPSYM(QWebEngineView_show_t, QWebEngineView_show, _ZN7QWidget4showEv) - CPPSYM(QWebEngineView_winId_t, QWebEngineView_winId, _ZNK7QWidget5winIdEv) - CPPSYM(QWebEngineView_windowHandle_t, QWebEngineView_windowHandle, _ZNK7QWidget12windowHandleEv) - CPPSYM(QWindow_fromWinId_t, QWindow_fromWinId, _ZN7QWindow9fromWinIdEy) - CPPSYM(QWindow_setParent_t, QWindow_setParent, _ZN7QWindow9setParentEPS_) - - unsetenv("QT_FONT_DPI"); - unsetenv("QT_SCREEN_SCALE_FACTORS"); - unsetenv("QT_USE_PHYSICAL_DPI"); - setenv("QT_AUTO_SCREEN_SCALE_FACTOR", "0", 1); - - char scale[8] = {}; - std::snprintf(scale, 7, "%.2f", scaleFactor); - 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 }; - - uint8_t _app[64]; // sizeof(QApplication) == 16 - QApplication* const app = reinterpret_cast(_app); - QApplication__init(app, argc, argv, 0); - - uint8_t _qstrurl[32]; // sizeof(QString) == 8 - QString* const qstrurl(reinterpret_cast(_qstrurl)); - - { - const size_t url_len = std::strlen(url); - QChar* const url_qchar = new QChar[url_len + 1]; - - for (size_t i = 0; i < url_len; ++i) - url_qchar[i] = QChar(url[i]); - - url_qchar[url_len] = 0; - - QString__init(qstrurl, url_qchar, url_len); - } - - uint8_t _qurl[32]; // sizeof(QUrl) == 8 - QUrl* const qurl(reinterpret_cast(_qurl)); - QUrl__init(qurl, *qstrurl, 1 /* QUrl::StrictMode */); - - uint8_t _webview[128]; // sizeof(QWebEngineView) == 56 - QWebEngineView* const webview = reinterpret_cast(_webview); - QWebEngineView__init(webview, nullptr); - - QWebEngineView_move(webview, QPoint(0, kVerticalOffset)); - QWebEngineView_resize(webview, QSize(DISTRHO_UI_DEFAULT_WIDTH, DISTRHO_UI_DEFAULT_HEIGHT - kVerticalOffset)); - QWebEngineView_winId(webview); - QWindow_setParent(QWebEngineView_windowHandle(webview), QWindow_fromWinId(winId)); - QWebEngineView_setUrl(webview, *qurl); - QWebEngineView_show(webview); - - reloadFn = [=](){ - QWebEngineView_setUrl(webview, *qurl); - }; - - QApplication_exec(); - - dlclose(lib); - return true; -} - -// ----------------------------------------------------------------------------------------------------------- -// 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) -{ - void* lib; - if ((lib = dlopen("libQt6WebEngineWidgets.so.6", RTLD_NOW|RTLD_GLOBAL)) == nullptr || - (lib = dlopen("libQt6WebEngineWidgets.so", RTLD_NOW|RTLD_GLOBAL)) == nullptr) - return false; - - using QApplication__init_t = void (*)(QApplication*, int&, char**, int); - using QApplication_exec_t = void (*)(); - using QApplication_setAttribute_t = void (*)(Qt::ApplicationAttribute, bool); - using QString__init_t = void (*)(void*, const QChar*, long long); - using QUrl__init_t = void (*)(void*, const QString&, int /* QUrl::ParsingMode */); - using QWebEngineView__init_t = void (*)(QWebEngineView*, void*); - using QWebEngineView_move_t = void (*)(QWebEngineView*, const QPoint&); - using QWebEngineView_resize_t = void (*)(QWebEngineView*, const QSize&); - using QWebEngineView_setUrl_t = void (*)(QWebEngineView*, const QUrl&); - using QWebEngineView_show_t = void (*)(QWebEngineView*); - using QWebEngineView_winId_t = ulonglong (*)(QWebEngineView*); - using QWebEngineView_windowHandle_t = QWindow* (*)(QWebEngineView*); - using QWindow_fromWinId_t = QWindow* (*)(ulonglong); - using QWindow_setParent_t = void (*)(QWindow*, void*); - - CPPSYM(QApplication__init_t, QApplication__init, _ZN12QApplicationC1ERiPPci) - CPPSYM(QApplication_exec_t, QApplication_exec, _ZN15QGuiApplication4execEv) - CPPSYM(QApplication_setAttribute_t, QApplication_setAttribute, _ZN16QCoreApplication12setAttributeEN2Qt20ApplicationAttributeEb) - CPPSYM(QString__init_t, QString__init, _ZN7QStringC2EPK5QCharx) - CPPSYM(QUrl__init_t, QUrl__init, _ZN4QUrlC1ERK7QStringNS_11ParsingModeE) - CPPSYM(QWebEngineView__init_t, QWebEngineView__init, _ZN14QWebEngineViewC1EP7QWidget) - CPPSYM(QWebEngineView_move_t, QWebEngineView_move, _ZN7QWidget4moveERK6QPoint) - CPPSYM(QWebEngineView_resize_t, QWebEngineView_resize, _ZN7QWidget6resizeERK5QSize) - CPPSYM(QWebEngineView_setUrl_t, QWebEngineView_setUrl, _ZN14QWebEngineView6setUrlERK4QUrl) - CPPSYM(QWebEngineView_show_t, QWebEngineView_show, _ZN7QWidget4showEv) - CPPSYM(QWebEngineView_winId_t, QWebEngineView_winId, _ZNK7QWidget5winIdEv) - CPPSYM(QWebEngineView_windowHandle_t, QWebEngineView_windowHandle, _ZNK7QWidget12windowHandleEv) - CPPSYM(QWindow_fromWinId_t, QWindow_fromWinId, _ZN7QWindow9fromWinIdEy) - CPPSYM(QWindow_setParent_t, QWindow_setParent, _ZN7QWindow9setParentEPS_) - - unsetenv("QT_FONT_DPI"); - unsetenv("QT_SCREEN_SCALE_FACTORS"); - unsetenv("QT_USE_PHYSICAL_DPI"); - setenv("QT_AUTO_SCREEN_SCALE_FACTOR", "0", 1); - - char scale[8] = {}; - std::snprintf(scale, 7, "%.2f", scaleFactor); - 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 }; - - uint8_t _app[64]; // sizeof(QApplication) == 16 - QApplication* const app = reinterpret_cast(_app); - QApplication__init(app, argc, argv, 0); - - uint8_t _qstrurl[32]; // sizeof(QString) == 8 - QString* const qstrurl(reinterpret_cast(_qstrurl)); - - { - const size_t url_len = std::strlen(url); - QChar* const url_qchar = new QChar[url_len + 1]; - - for (size_t i = 0; i < url_len; ++i) - url_qchar[i] = QChar(url[i]); - - url_qchar[url_len] = 0; - - QString__init(qstrurl, url_qchar, url_len); - } - - uint8_t _qurl[32]; // sizeof(QUrl) == 8 - QUrl* const qurl(reinterpret_cast(_qurl)); - QUrl__init(qurl, *qstrurl, 1 /* QUrl::StrictMode */); - - uint8_t _webview[128]; // sizeof(QWebEngineView) == 56 - QWebEngineView* const webview = reinterpret_cast(_webview); - QWebEngineView__init(webview, nullptr); - - QWebEngineView_move(webview, QPoint(0, kVerticalOffset)); - QWebEngineView_resize(webview, QSize(DISTRHO_UI_DEFAULT_WIDTH, DISTRHO_UI_DEFAULT_HEIGHT - kVerticalOffset)); - QWebEngineView_winId(webview); - QWindow_setParent(QWebEngineView_windowHandle(webview), QWindow_fromWinId(winId)); - QWebEngineView_setUrl(webview, *qurl); - QWebEngineView_show(webview); - - reloadFn = [=](){ - QWebEngineView_setUrl(webview, *qurl); - }; - - QApplication_exec(); - - dlclose(lib); - return true; -} - -// ----------------------------------------------------------------------------------------------------------- -// startup via ld-linux - -static void signalHandler(const int sig) -{ - DISTRHO_SAFE_ASSERT_RETURN(sig == SIGUSR1,); - - reloadFn(); -} - -int dpf_webview_start(int /* argc */, char** /* argv[] */) -{ - uselocale(newlocale(LC_NUMERIC_MASK, "C", nullptr)); - - const char* const envPort = std::getenv("DPF_WEBVIEW_PORT"); - DISTRHO_SAFE_ASSERT_RETURN(envPort != nullptr, 1); - - const char* const envScaleFactor = std::getenv("DPF_WEBVIEW_SCALE_FACTOR"); - DISTRHO_SAFE_ASSERT_RETURN(envScaleFactor != nullptr, 1); - - const char* const envWinId = std::getenv("DPF_WEBVIEW_WIN_ID"); - DISTRHO_SAFE_ASSERT_RETURN(envWinId != nullptr, 1); - - const Window winId = std::strtoul(envWinId, nullptr, 10); - DISTRHO_SAFE_ASSERT_RETURN(winId != 0, 1); - - const double scaleFactor = std::atof(envScaleFactor); - DISTRHO_SAFE_ASSERT_RETURN(scaleFactor > 0.0, 1); - - Display* const display = XOpenDisplay(nullptr); - DISTRHO_SAFE_ASSERT_RETURN(display != nullptr, 1); - - char url[32] = {}; - std::snprintf(url, 31, "http://127.0.0.1:%s/", envPort); - - struct sigaction sig = {}; - sig.sa_handler = signalHandler; - sig.sa_flags = SA_RESTART; - sigemptyset(&sig.sa_mask); - sigaction(SIGUSR1, &sig, nullptr); - - qt5webengine(winId, scaleFactor, url) || - qt6webengine(winId, scaleFactor, url) || - gtk3(display, winId, scaleFactor, url); - - XCloseDisplay(display); - - return 0; -} - -// ----------------------------------------------------------------------------------------------------------- - -END_NAMESPACE_DISTRHO diff --git a/src/plugin/utils.cpp b/src/plugin/utils.cpp index 1dd5b3d..d205ed0 100644 --- a/src/plugin/utils.cpp +++ b/src/plugin/utils.cpp @@ -96,7 +96,7 @@ static const char* getDataDir() #ifdef _WIN32 static const wchar_t* getAppDirW() { - // return L"Z:\\home\\falktx\\Source\\MOD\\mod-app\\build"; + // return L"Z:\\home\\falktx\\Source\\MOD\\mod-desktop\\build"; static wchar_t appDir[MAX_PATH] = {}; if (appDir[0] == 0) @@ -112,7 +112,7 @@ static const wchar_t* getAppDirW() const char* getAppDir() { #ifdef DISTRHO_OS_MAC - return "/Users/falktx/Source/MOD/mod-app/build/mod-desktop.app/Contents/MacOS"; + // return "/Users/falktx/Source/MOD/mod-desktop/build/mod-desktop.app/Contents/MacOS"; return "/Applications/MOD Desktop.app/Contents/MacOS"; #else static char appDir[PATH_MAX] = {};