Skip to content

Commit

Permalink
Implement webview for windows, custom choc fork
Browse files Browse the repository at this point in the history
Signed-off-by: falkTX <[email protected]>
  • Loading branch information
falkTX committed May 15, 2024
1 parent bcd834c commit 802774a
Show file tree
Hide file tree
Showing 14 changed files with 8,734 additions and 91 deletions.
9 changes: 9 additions & 0 deletions Makefile.plugins.mk
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ else ifeq ($(UI_TYPE),opengl3)
USE_OPENGL3 = true
else ifeq ($(UI_TYPE),vulkan)
else ifeq ($(UI_TYPE),webview)
USE_CLAP_BUNDLE = true
USE_VST2_BUNDLE = true
USE_WEB_VIEW = true
else
$(error unknown UI_TYPE $(UI_TYPE))
Expand Down Expand Up @@ -186,6 +188,8 @@ OBJS_UI = $(FILES_UI:%=$(BUILD_DIR)/%.o)

ifeq ($(MACOS),true)
OBJS_UI += $(BUILD_DIR)/DistrhoUI_macOS_$(NAME).mm.o
else ifeq ($(WINDOWS)$(USE_WEB_VIEW),truetrue)
OBJS_UI += $(BUILD_DIR)/DistrhoUI_win32.cpp.o
endif

# ---------------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -528,6 +532,11 @@ $(BUILD_DIR)/DistrhoUI_macOS_%.mm.o: $(DPF_PATH)/distrho/DistrhoUI_macOS.mm $(EX
@echo "Compiling DistrhoUI_macOS.mm ($*)"
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@

$(BUILD_DIR)/DistrhoUI_win32.cpp.o: $(DPF_PATH)/distrho/DistrhoUI_win32.cpp $(EXTRA_DEPENDENCIES) $(EXTRA_UI_DEPENDENCIES)
-@mkdir -p $(BUILD_DIR)
@echo "Compiling DistrhoUI_win32.cpp ($*)"
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -std=gnu++17 -c -o $@

$(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o: BUILD_CXX_FLAGS += $(JACK_FLAGS)

$(BUILD_DIR)/DistrhoPluginMain_AU.cpp.o: BUILD_CXX_FLAGS += -ObjC++
Expand Down
27 changes: 27 additions & 0 deletions distrho/DistrhoUI_win32.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2024 Filipe Coelho <[email protected]>
*
* 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.
*/

// Include CHOC separately because it requires C++17

#include "DistrhoDetails.hpp"
#include "src/DistrhoPluginChecks.h"
#include "src/DistrhoDefines.h"

#if DISTRHO_UI_WEB_VIEW
# define DISTRHO_WEB_VIEW_INCLUDE_IMPLEMENTATION
# include "extra/WebView.hpp"
# include "extra/WebViewWin32.hpp"
#endif
115 changes: 34 additions & 81 deletions distrho/extra/WebViewImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,32 +25,27 @@
// #include <gtk/gtkx.h>
// #include <webkit2/webkit2.h>

#ifndef WEB_VIEW_USING_CHOC
# define WEB_VIEW_USING_CHOC 0
#elif WEB_VIEW_USING_CHOC && !(defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS))
# undef WEB_VIEW_USING_CHOC
# define WEB_VIEW_USING_CHOC 0
#endif

#if defined(DISTRHO_OS_MAC) && !WEB_VIEW_USING_CHOC
# undef WEB_VIEW_USING_MACOS_WEBKIT
#ifdef DISTRHO_OS_MAC
# define WEB_VIEW_USING_MACOS_WEBKIT 1
#else
# undef WEB_VIEW_USING_MACOS_WEBKIT
# define WEB_VIEW_USING_MACOS_WEBKIT 0
#endif

#ifdef DISTRHO_OS_WINDOWS
# define WEB_VIEW_USING_CHOC 1
#else
# define WEB_VIEW_USING_CHOC 0
#endif

#if defined(HAVE_X11) && defined(DISTRHO_OS_LINUX)
# undef WEB_VIEW_USING_X11_IPC
# define WEB_VIEW_USING_X11_IPC 1
#else
# undef WEB_VIEW_USING_X11_IPC
# define WEB_VIEW_USING_X11_IPC 0
#endif

#if WEB_VIEW_USING_CHOC
# define WC_ERR_INVALID_CHARS 0
# include "../CHOC/gui/choc_WebView.h"
# include "WebViewWin32.hpp"
# include "String.hpp"
#elif WEB_VIEW_USING_MACOS_WEBKIT
# include <Cocoa/Cocoa.h>
# include <WebKit/WebKit.h>
Expand Down Expand Up @@ -217,8 +212,6 @@

@end

#elif WEB_VIEW_USING_X11_IPC

#endif // WEB_VIEW_USING_MACOS_WEBKIT

// -----------------------------------------------------------------------------------------------------------
Expand All @@ -233,6 +226,7 @@ START_NAMESPACE_DISTRHO
// -----------------------------------------------------------------------------------------------------------

#if WEB_VIEW_USING_X11_IPC

#ifdef __linux__
typedef int32_t ipc_sem_t;
#else
Expand Down Expand Up @@ -329,14 +323,15 @@ static void getFilenameFromFunctionPtr(char filename[PATH_MAX], const void* cons
std::strncpy(filename, info.dli_fname, PATH_MAX - 1);
}
}
#endif

#endif // WEB_VIEW_USING_X11_IPC

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

struct WebViewData {
#if WEB_VIEW_USING_CHOC
choc::ui::WebView* webview;
WebViewMessageCallback callback;
void* callbackPtr;
std::string url;
WebView* webview;
String url;
#elif WEB_VIEW_USING_MACOS_WEBKIT
NSView* view;
WKWebView* webview;
Expand Down Expand Up @@ -368,46 +363,11 @@ WebViewHandle webViewCreate(const char* const url,
const WebViewOptions& options)
{
#if WEB_VIEW_USING_CHOC
choc::ui::WebView::Options woptions;
woptions.acceptsFirstMouseClick = true;
woptions.enableDebugMode = true;

std::unique_ptr<choc::ui::WebView> webview = std::make_unique<choc::ui::WebView>(woptions);
DISTRHO_SAFE_ASSERT_RETURN(webview->loadedOK(), nullptr);

void* const handle = webview->getViewHandle();
DISTRHO_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);

if (const WebViewMessageCallback callback = options.callback)
{
webview->addInitScript("function postMessage(m) { js2cpp(m); }");

void* const callbackPtr = options.callbackPtr;
webview->bind("js2cpp", [callback, callbackPtr](const choc::value::ValueView& args) -> choc::value::Value {
callback(callbackPtr, args[0].toString().data());
return {};
});
}
else
{
webview->addInitScript("function postMessage(m) {}");
}

if (options.initialJS != nullptr)
webview->addInitScript(options.initialJS);

webview->navigate(url);
WebView* const webview = webview_choc_create(options);
if (webview == nullptr)
return nullptr;

#ifdef DISTRHO_OS_MAC
NSView* const view = static_cast<NSView*>(handle);

[reinterpret_cast<NSView*>(windowId) addSubview:view];
[view setFrame:NSMakeRect(options.offset.x,
options.offset.y,
DISTRHO_UI_DEFAULT_WIDTH - options.offset.x,
DISTRHO_UI_DEFAULT_HEIGHT - options.offset.y)];
#else
const HWND hwnd = static_cast<HWND>(handle);
const HWND hwnd = static_cast<HWND>(webview_choc_handle(webview));

LONG_PTR flags = GetWindowLongPtr(hwnd, -16);
flags = (flags & ~WS_POPUP) | WS_CHILD;
Expand All @@ -421,13 +381,13 @@ WebViewHandle webViewCreate(const char* const url,
initialHeight - options.offset.y,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
ShowWindow(hwnd, SW_SHOW);
#endif

WebViewData* const whandle = new WebViewData;
whandle->webview = webview.release();
whandle->callback = options.callback;
whandle->callbackPtr = options.callbackPtr;
whandle->webview = webview;
whandle->url = url;

webview_choc_navigate(webview, url);

return whandle;
#elif WEB_VIEW_USING_MACOS_WEBKIT
NSView* const view = reinterpret_cast<NSView*>(windowId);
Expand Down Expand Up @@ -470,7 +430,7 @@ WebViewHandle webViewCreate(const char* const url,
WKUserScript* const mscript = [[WKUserScript alloc]
initWithSource:(options.callback != nullptr
? @"function postMessage(m){window.webkit.messageHandlers.external.postMessage(m)}"
: @"function postMessage(m){}}")
: @"function postMessage(m){}")
injectionTime:WKUserScriptInjectionTimeAtDocumentStart
forMainFrameOnly:true
];
Expand Down Expand Up @@ -711,7 +671,7 @@ WebViewHandle webViewCreate(const char* const url,
void webViewDestroy(const WebViewHandle handle)
{
#if WEB_VIEW_USING_CHOC
delete handle->webview;
webview_choc_destroy(handle->webview);
#elif WEB_VIEW_USING_MACOS_WEBKIT
[handle->webview setHidden:YES];
[handle->webview removeFromSuperview];
Expand Down Expand Up @@ -780,7 +740,7 @@ void webViewIdle(const WebViewHandle handle)
void webViewEvaluateJS(const WebViewHandle handle, const char* const js)
{
#if WEB_VIEW_USING_CHOC
handle->webview->evaluateJavascript(js);
webview_choc_eval(handle->webview, js);
#elif WEB_VIEW_USING_MACOS_WEBKIT
NSString* const nsjs = [[NSString alloc] initWithBytes:js
length:std::strlen(js)
Expand All @@ -805,7 +765,7 @@ void webViewEvaluateJS(const WebViewHandle handle, const char* const js)
void webViewReload(const WebViewHandle handle)
{
#if WEB_VIEW_USING_CHOC
handle->webview->navigate(handle->url);
webview_choc_navigate(handle->webview, handle->url);
#elif WEB_VIEW_USING_MACOS_WEBKIT
[handle->webview loadRequest:handle->urlreq];
#elif WEB_VIEW_USING_X11_IPC
Expand All @@ -821,19 +781,12 @@ void webViewReload(const WebViewHandle handle)

void webViewResize(const WebViewHandle handle, const uint width, const uint height, const double scaleFactor)
{
#if WEB_VIEW_USING_CHOC
#ifdef DISTRHO_OS_MAC
NSView* const view = static_cast<NSView*>(handle->webview->getViewHandle());
[view setFrameSize:NSMakeSize(width / scaleFactor, height / scaleFactor)];
#else
const HWND hwnd = static_cast<HWND>(handle->webview->getViewHandle());
SetWindowPos(hwnd, nullptr, 0, 0,
width, height,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
#endif
#elif WEB_VIEW_USING_MACOS_WEBKIT
#if WEB_VIEW_USING_CHOC
const HWND hwnd = static_cast<HWND>(webview_choc_handle(handle->webview));
SetWindowPos(hwnd, nullptr, 0, 0, width, height, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
#elif WEB_VIEW_USING_MACOS_WEBKIT
[handle->webview setFrameSize:NSMakeSize(width / scaleFactor, height / scaleFactor)];
#elif WEB_VIEW_USING_X11_IPC
#elif WEB_VIEW_USING_X11_IPC
if (handle->childWindow == 0)
{
::Window rootWindow, parentWindow;
Expand All @@ -852,7 +805,7 @@ void webViewResize(const WebViewHandle handle, const uint width, const uint heig

XResizeWindow(handle->display, handle->childWindow, width, height);
XFlush(handle->display);
#endif
#endif

// maybe unused
(void)handle;
Expand Down
101 changes: 101 additions & 0 deletions distrho/extra/WebViewWin32.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2024 Filipe Coelho <[email protected]>
*
* 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.
*/

#if !defined(DISTRHO_WEB_VIEW_HPP_INCLUDED) && !defined(DGL_WEB_VIEW_HPP_INCLUDED)
# define DISTRHO_WEB_VIEW_INCLUDE_IMPLEMENTATION
# include "WebView.hpp"
#endif

// --------------------------------------------------------------------------------------------------------------------
// Web View stuff

START_NAMESPACE_DISTRHO

struct WebView;

WebView* webview_choc_create(const WebViewOptions& opts);
void webview_choc_destroy(WebView*);
void* webview_choc_handle(WebView*);
void webview_choc_eval(WebView*, const char* js);
void webview_choc_navigate(WebView*, const char* url);

END_NAMESPACE_DISTRHO

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

#ifdef DISTRHO_WEB_VIEW_INCLUDE_IMPLEMENTATION

# define WC_ERR_INVALID_CHARS 0
# include "choc/choc_WebView.h"

START_NAMESPACE_DISTRHO

WebView* webview_choc_create(const WebViewOptions& opts)
{
WebView::Options wopts;
wopts.acceptsFirstMouseClick = true;
wopts.enableDebugMode = true;

std::unique_ptr<WebView> webview = std::make_unique<WebView>(wopts);
DISTRHO_SAFE_ASSERT_RETURN(webview->loadedOK(), nullptr);

if (const WebViewMessageCallback callback = opts.callback)
{
webview->addInitScript("function postMessage(m){window.chrome.webview.postMessage(m);}");

void* const callbackPtr = opts.callbackPtr;
webview->bind([callback, callbackPtr](const std::string& value) {
char* const data = strdup(value.data());
callback(callbackPtr, data);
std::free(data);
});
}
else
{
webview->addInitScript("function postMessage(m){}");
}

if (opts.initialJS != nullptr)
webview->addInitScript(opts.initialJS);

return webview.release();
}

void webview_choc_destroy(WebView* const webview)
{
delete webview;
}

void* webview_choc_handle(WebView* const webview)
{
return webview->getViewHandle();
}

void webview_choc_eval(WebView* const webview, const char* const js)
{
webview->evaluateJavascript(js);
}

void webview_choc_navigate(WebView* const webview, const char* const url)
{
webview->navigate(url);
}

END_NAMESPACE_DISTRHO

#endif // DISTRHO_WEB_VIEW_INCLUDE_IMPLEMENTATION

// --------------------------------------------------------------------------------------------------------------------
15 changes: 15 additions & 0 deletions distrho/extra/choc/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## CHOC: licensing

I'd like anyone to feel able to use this library code without worrying about the legal implications, so it's released under the permissive ISC license:

----

**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.**

https://en.wikipedia.org/wiki/ISC_license

----

Note that if you use the `choc::ui::WebView` class on Windows, it embeds some Microsoft redistributable code which has its own (permissive) license that you should be aware of. See inside the file `choc_WebView.h` for more details.
Loading

0 comments on commit 802774a

Please sign in to comment.