2022-07-15 15:37:19 +00:00
# include "WebView.hpp"
# include "slic3r/GUI/GUI_App.hpp"
2022-08-02 09:59:28 +00:00
# include "slic3r/Utils/MacDarkMode.hpp"
2022-07-15 15:37:19 +00:00
# include <wx/webviewarchivehandler.h>
# include <wx/webviewfshandler.h>
2022-12-16 00:07:22 +00:00
# if wxUSE_WEBVIEW_EDGE
2022-07-15 15:37:19 +00:00
# include <wx/msw/webview_edge.h>
2022-12-16 00:07:22 +00:00
# endif
2022-07-15 15:37:19 +00:00
# include <wx/uri.h>
2022-12-16 00:07:22 +00:00
# if defined(__WIN32__) || defined(__WXMAC__)
2022-08-02 09:59:28 +00:00
# include "wx/private/jsscriptwrapper.h"
2022-12-16 00:07:22 +00:00
# endif
2022-07-15 15:37:19 +00:00
# ifdef __WIN32__
2022-12-09 09:34:28 +00:00
# include <WebView2.h>
2022-09-29 02:12:48 +00:00
# elif defined __linux__
# include <gtk/gtk.h>
# define WEBKIT_API
struct WebKitWebView ;
struct WebKitJavascriptResult ;
extern " C " {
WEBKIT_API void
webkit_web_view_run_javascript ( WebKitWebView * web_view ,
const gchar * script ,
GCancellable * cancellable ,
GAsyncReadyCallback callback ,
gpointer user_data ) ;
WEBKIT_API WebKitJavascriptResult *
webkit_web_view_run_javascript_finish ( WebKitWebView * web_view ,
GAsyncResult * result ,
GError * * error ) ;
WEBKIT_API void
webkit_javascript_result_unref ( WebKitJavascriptResult * js_result ) ;
}
2022-07-15 15:37:19 +00:00
# endif
2022-12-09 02:35:36 +00:00
# ifdef __WIN32__
class WebViewEdge : public wxWebViewEdge
{
public :
bool SetUserAgent ( const wxString & userAgent )
{
ICoreWebView2 * webView2 = ( ICoreWebView2 * ) GetNativeBackend ( ) ;
if ( webView2 ) {
ICoreWebView2Settings * settings ;
HRESULT hr = webView2 - > get_Settings ( & settings ) ;
if ( hr = = S_OK ) {
ICoreWebView2Settings2 * settings2 ;
hr = settings - > QueryInterface ( & settings2 ) ;
if ( hr = = S_OK ) {
settings2 - > put_UserAgent ( userAgent . wc_str ( ) ) ;
settings2 - > Release ( ) ;
return true ;
}
}
return false ;
}
pendingUserAgent = userAgent ;
return true ;
}
void DoGetClientSize ( int * x , int * y ) const override
{
if ( ! pendingUserAgent . empty ( ) ) {
auto thiz = const_cast < WebViewEdge * > ( this ) ;
auto userAgent = std : : move ( thiz - > pendingUserAgent ) ;
thiz - > pendingUserAgent . clear ( ) ;
thiz - > SetUserAgent ( userAgent ) ;
}
wxWebViewEdge : : DoGetClientSize ( x , y ) ;
} ;
private :
wxString pendingUserAgent ;
} ;
# endif
2022-07-15 15:37:19 +00:00
class FakeWebView : public wxWebView
{
virtual bool Create ( wxWindow * parent , wxWindowID id , const wxString & url , const wxPoint & pos , const wxSize & size , long style , const wxString & name ) override { return false ; }
virtual wxString GetCurrentTitle ( ) const override { return wxString ( ) ; }
virtual wxString GetCurrentURL ( ) const override { return wxString ( ) ; }
virtual bool IsBusy ( ) const override { return false ; }
virtual bool IsEditable ( ) const override { return false ; }
virtual void LoadURL ( const wxString & url ) override { }
virtual void Print ( ) override { }
virtual void RegisterHandler ( wxSharedPtr < wxWebViewHandler > handler ) override { }
virtual void Reload ( wxWebViewReloadFlags flags = wxWEBVIEW_RELOAD_DEFAULT ) override { }
virtual bool RunScript ( const wxString & javascript , wxString * output = NULL ) const override { return false ; }
virtual void SetEditable ( bool enable = true ) override { }
virtual void Stop ( ) override { }
virtual bool CanGoBack ( ) const override { return false ; }
virtual bool CanGoForward ( ) const override { return false ; }
virtual void GoBack ( ) override { }
virtual void GoForward ( ) override { }
virtual void ClearHistory ( ) override { }
virtual void EnableHistory ( bool enable = true ) override { }
virtual wxVector < wxSharedPtr < wxWebViewHistoryItem > > GetBackwardHistory ( ) override { return { } ; }
virtual wxVector < wxSharedPtr < wxWebViewHistoryItem > > GetForwardHistory ( ) override { return { } ; }
virtual void LoadHistoryItem ( wxSharedPtr < wxWebViewHistoryItem > item ) override { }
virtual bool CanSetZoomType ( wxWebViewZoomType type ) const override { return false ; }
virtual float GetZoomFactor ( ) const override { return 0.0f ; }
virtual wxWebViewZoomType GetZoomType ( ) const override { return wxWebViewZoomType ( ) ; }
virtual void SetZoomFactor ( float zoom ) override { }
virtual void SetZoomType ( wxWebViewZoomType zoomType ) override { }
virtual bool CanUndo ( ) const override { return false ; }
virtual bool CanRedo ( ) const override { return false ; }
virtual void Undo ( ) override { }
virtual void Redo ( ) override { }
virtual void * GetNativeBackend ( ) const override { return nullptr ; }
virtual void DoSetPage ( const wxString & html , const wxString & baseUrl ) override { }
} ;
2022-11-11 01:48:51 +00:00
wxDEFINE_EVENT ( EVT_WEBVIEW_RECREATED , wxCommandEvent ) ;
static std : : vector < wxWebView * > g_webviews ;
class WebViewRef : public wxObjectRefData
{
public :
WebViewRef ( wxWebView * webView ) : m_webView ( webView ) { }
~ WebViewRef ( ) {
auto iter = std : : find ( g_webviews . begin ( ) , g_webviews . end ( ) , m_webView ) ;
assert ( iter ! = g_webviews . end ( ) ) ;
if ( iter ! = g_webviews . end ( ) )
g_webviews . erase ( iter ) ;
}
wxWebView * m_webView ;
} ;
2022-07-15 15:37:19 +00:00
wxWebView * WebView : : CreateWebView ( wxWindow * parent , wxString const & url )
{
# if wxUSE_WEBVIEW_EDGE
// Check if a fixed version of edge is present in
// $executable_path/edge_fixed and use it
wxFileName edgeFixedDir ( wxStandardPaths : : Get ( ) . GetExecutablePath ( ) ) ;
edgeFixedDir . SetFullName ( " " ) ;
edgeFixedDir . AppendDir ( " edge_fixed " ) ;
if ( edgeFixedDir . DirExists ( ) ) {
wxWebViewEdge : : MSWSetBrowserExecutableDir ( edgeFixedDir . GetFullPath ( ) ) ;
wxLogMessage ( " Using fixed edge version " ) ;
}
# endif
auto url2 = url ;
# ifdef __WIN32__
url2 . Replace ( " \\ " , " / " ) ;
# endif
if ( ! url2 . empty ( ) ) { url2 = wxURI ( url2 ) . BuildURI ( ) ; }
2022-11-30 01:20:04 +00:00
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " : " < < url2 . ToUTF8 ( ) ;
2022-07-15 15:37:19 +00:00
2022-12-09 02:35:36 +00:00
# ifdef __WIN32__
wxWebView * webView = new WebViewEdge ;
# else
2022-07-15 15:37:19 +00:00
auto webView = wxWebView : : New ( ) ;
2022-12-09 02:35:36 +00:00
# endif
2022-07-15 15:37:19 +00:00
if ( webView ) {
2022-12-05 05:45:34 +00:00
webView - > SetBackgroundColour ( StateColor : : darkModeColorFor ( * wxWHITE ) ) ;
2022-07-15 15:37:19 +00:00
# ifdef __WIN32__
2022-11-11 01:48:51 +00:00
webView - > SetUserAgent ( wxString : : Format ( " BBL-Slicer/v%s (%s) Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
" AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.52 " , SLIC3R_VERSION ,
Slic3r : : GUI : : wxGetApp ( ) . dark_mode ( ) ? " dark " : " light " ) ) ;
2022-11-22 09:30:37 +00:00
webView - > Create ( parent , wxID_ANY , url2 , wxDefaultPosition , wxDefaultSize , wxBORDER_NONE ) ;
2022-11-11 01:48:51 +00:00
// We register the wxfs:// protocol for testing purposes
2022-07-15 15:37:19 +00:00
webView - > RegisterHandler ( wxSharedPtr < wxWebViewHandler > ( new wxWebViewArchiveHandler ( " bbl " ) ) ) ;
2022-11-11 01:48:51 +00:00
// And the memory: file system
2022-07-15 15:37:19 +00:00
webView - > RegisterHandler ( wxSharedPtr < wxWebViewHandler > ( new wxWebViewFSHandler ( " memory " ) ) ) ;
# else
// With WKWebView handlers need to be registered before creation
webView - > RegisterHandler ( wxSharedPtr < wxWebViewHandler > ( new wxWebViewArchiveHandler ( " wxfs " ) ) ) ;
// And the memory: file system
webView - > RegisterHandler ( wxSharedPtr < wxWebViewHandler > ( new wxWebViewFSHandler ( " memory " ) ) ) ;
2022-11-22 09:30:37 +00:00
webView - > Create ( parent , wxID_ANY , url2 , wxDefaultPosition , wxDefaultSize , wxBORDER_NONE ) ;
2022-11-11 01:48:51 +00:00
webView - > SetUserAgent ( wxString : : Format ( " BBL-Slicer/v%s (%s) Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) " , SLIC3R_VERSION ,
Slic3r : : GUI : : wxGetApp ( ) . dark_mode ( ) ? " dark " : " light " ) ) ;
2022-07-15 15:37:19 +00:00
# endif
2022-12-07 02:05:37 +00:00
# ifdef __WXMAC__
WKWebView * wkWebView = ( WKWebView * ) webView - > GetNativeBackend ( ) ;
Slic3r : : GUI : : WKWebView_setTransparentBackground ( wkWebView ) ;
# endif
2022-09-29 02:12:48 +00:00
# ifndef __WIN32__
2022-07-15 15:37:19 +00:00
Slic3r : : GUI : : wxGetApp ( ) . CallAfter ( [ webView ] {
# endif
2022-10-09 01:40:38 +00:00
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " : begin to add script message handler for wx. " ;
Slic3r : : GUI : : wxGetApp ( ) . set_adding_script_handler ( true ) ;
2022-07-15 15:37:19 +00:00
if ( ! webView - > AddScriptMessageHandler ( " wx " ) )
wxLogError ( " Could not add script message handler " ) ;
2022-10-09 01:40:38 +00:00
Slic3r : : GUI : : wxGetApp ( ) . set_adding_script_handler ( false ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " : finished add script message handler for wx. " ;
2022-09-29 02:12:48 +00:00
# ifndef __WIN32__
} ) ;
2022-07-15 15:37:19 +00:00
# endif
webView - > EnableContextMenu ( false ) ;
} else {
2022-07-27 08:55:55 +00:00
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " : failed. Use fake web view. " ;
2022-07-15 15:37:19 +00:00
webView = new FakeWebView ;
}
2022-11-11 01:48:51 +00:00
webView - > SetRefData ( new WebViewRef ( webView ) ) ;
g_webviews . push_back ( webView ) ;
2022-07-15 15:37:19 +00:00
return webView ;
}
2022-07-25 07:37:22 +00:00
void WebView : : LoadUrl ( wxWebView * webView , wxString const & url )
{
auto url2 = url ;
# ifdef __WIN32__
url2 . Replace ( " \\ " , " / " ) ;
# endif
if ( ! url2 . empty ( ) ) { url2 = wxURI ( url2 ) . BuildURI ( ) ; }
2022-07-27 08:55:55 +00:00
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < url2 . ToUTF8 ( ) ;
2022-07-25 07:37:22 +00:00
webView - > LoadURL ( url2 ) ;
}
2022-07-15 15:37:19 +00:00
bool WebView : : RunScript ( wxWebView * webView , wxString const & javascript )
{
if ( Slic3r : : GUI : : wxGetApp ( ) . get_mode ( ) = = Slic3r : : comDevelop )
wxLogMessage ( " Running JavaScript: \n %s \n " , javascript ) ;
try {
# ifdef __WIN32__
ICoreWebView2 * webView2 = ( ICoreWebView2 * ) webView - > GetNativeBackend ( ) ;
if ( webView2 = = nullptr )
return false ;
int count = 0 ;
wxJSScriptWrapper wrapJS ( javascript , & count ) ;
return webView2 - > ExecuteScript ( wrapJS . GetWrappedCode ( ) , NULL ) = = 0 ;
2022-08-02 09:59:28 +00:00
# elif defined __WXMAC__
WKWebView * wkWebView = ( WKWebView * ) webView - > GetNativeBackend ( ) ;
int count = 0 ;
wxJSScriptWrapper wrapJS ( javascript , & count ) ;
Slic3r : : GUI : : WKWebView_evaluateJavaScript ( wkWebView , wrapJS . GetWrappedCode ( ) , nullptr ) ;
return true ;
2022-07-15 15:37:19 +00:00
# else
2022-09-29 02:12:48 +00:00
WebKitWebView * wkWebView = ( WebKitWebView * ) webView - > GetNativeBackend ( ) ;
webkit_web_view_run_javascript (
wkWebView , javascript . utf8_str ( ) , NULL ,
[ ] ( GObject * wkWebView , GAsyncResult * res , void * ) {
GError * error = NULL ;
auto result = webkit_web_view_run_javascript_finish ( ( WebKitWebView * ) wkWebView , res , & error ) ;
if ( ! result )
g_error_free ( error ) ;
else
webkit_javascript_result_unref ( result ) ;
} , NULL ) ;
return true ;
2022-07-15 15:37:19 +00:00
# endif
} catch ( std : : exception & e ) {
return false ;
}
}
2022-11-11 01:48:51 +00:00
void WebView : : RecreateAll ( )
{
for ( auto webView : g_webviews ) {
webView - > SetUserAgent ( wxString : : Format ( " BBL-Slicer/v%s (%s) Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) " , SLIC3R_VERSION ,
Slic3r : : GUI : : wxGetApp ( ) . dark_mode ( ) ? " dark " : " light " ) ) ;
webView - > Reload ( ) ;
}
}