29#define WEBVIEW_API extern 
   32#ifndef WEBVIEW_VERSION_MAJOR 
   34#define WEBVIEW_VERSION_MAJOR 0 
   37#ifndef WEBVIEW_VERSION_MINOR 
   39#define WEBVIEW_VERSION_MINOR 10 
   42#ifndef WEBVIEW_VERSION_PATCH 
   44#define WEBVIEW_VERSION_PATCH 0 
   47#ifndef WEBVIEW_VERSION_PRE_RELEASE 
   49#define WEBVIEW_VERSION_PRE_RELEASE "" 
   52#ifndef WEBVIEW_VERSION_BUILD_METADATA 
   54#define WEBVIEW_VERSION_BUILD_METADATA "" 
   58#define WEBVIEW_STRINGIFY(x) #x 
   61#define WEBVIEW_EXPAND_AND_STRINGIFY(x) WEBVIEW_STRINGIFY(x) 
   64#define WEBVIEW_VERSION_NUMBER                                                                \ 
   65  WEBVIEW_EXPAND_AND_STRINGIFY(WEBVIEW_VERSION_MAJOR)                                       \ 
   66  "." WEBVIEW_EXPAND_AND_STRINGIFY(WEBVIEW_VERSION_MINOR) "." WEBVIEW_EXPAND_AND_STRINGIFY( \ 
   67      WEBVIEW_VERSION_PATCH) 
   86  char version_number[32];
 
   91  char build_metadata[48];
 
 
   99  typedef void* webview_t;
 
  109  WEBVIEW_API webview_t webview_create(
int debug, 
void* window);
 
  112  WEBVIEW_API 
void webview_destroy(webview_t w);
 
  116  WEBVIEW_API 
void webview_run(webview_t w);
 
  120  WEBVIEW_API 
void webview_terminate(webview_t w);
 
  124  WEBVIEW_API 
void webview_dispatch(webview_t w, 
void (*fn)(webview_t w, 
void* arg), 
void* arg);
 
  129  WEBVIEW_API 
void* webview_get_window(webview_t w);
 
  132  WEBVIEW_API 
void webview_set_title(webview_t w, 
const char* title);
 
  135#define WEBVIEW_HINT_NONE 0   
  136#define WEBVIEW_HINT_MIN 1    
  137#define WEBVIEW_HINT_MAX 2    
  138#define WEBVIEW_HINT_FIXED 3  
  140  WEBVIEW_API 
void webview_set_size(webview_t w, 
int width, 
int height, 
int hints);
 
  147  WEBVIEW_API 
void webview_navigate(webview_t w, 
const char* url);
 
  151  WEBVIEW_API 
void webview_set_html(webview_t w, 
const char* html);
 
  156  WEBVIEW_API 
void webview_init(webview_t w, 
const char* js);
 
  161  WEBVIEW_API 
void webview_eval(webview_t w, 
const char* js);
 
  168  WEBVIEW_API 
void webview_bind(webview_t w, 
const char* name,
 
  169                                void (*fn)(
const char* seq, 
const char* req, 
void* arg),
 
  173  WEBVIEW_API 
void webview_unbind(webview_t w, 
const char* name);
 
  179  WEBVIEW_API 
void webview_return(webview_t w, 
const char* seq, 
int status, 
const char* result);
 
  188#ifndef WEBVIEW_HEADER 
  190#if !defined(WEBVIEW_GTK) && !defined(WEBVIEW_COCOA) && !defined(WEBVIEW_EDGE) 
  191#if defined(__APPLE__) 
  193#elif defined(__unix__) 
  198#error "please, specify webview backend" 
  202#ifndef WEBVIEW_DEPRECATED 
  203#if __cplusplus >= 201402L 
  204#define WEBVIEW_DEPRECATED(reason) [[deprecated(reason)]] 
  205#elif defined(_MSC_VER) 
  206#define WEBVIEW_DEPRECATED(reason) __declspec(deprecated(reason)) 
  208#define WEBVIEW_DEPRECATED(reason) __attribute__((deprecated(reason))) 
  212#ifndef WEBVIEW_DEPRECATED_PRIVATE 
  213#define WEBVIEW_DEPRECATED_PRIVATE WEBVIEW_DEPRECATED("Private API should not be used") 
  231  using dispatch_fn_t = std::function<void()>;
 
  238      { WEBVIEW_VERSION_MAJOR, WEBVIEW_VERSION_MINOR, WEBVIEW_VERSION_PATCH },
 
  239      WEBVIEW_VERSION_NUMBER,
 
  240      WEBVIEW_VERSION_PRE_RELEASE,
 
  241      WEBVIEW_VERSION_BUILD_METADATA
 
  244    inline int json_parse_c(
const char* s, 
size_t sz, 
const char* key, 
size_t keysz,
 
  245                            const char** value, 
size_t* valuesz)
 
  254      } state = JSON_STATE_VALUE;
 
  255      const char* k = 
nullptr;
 
  265        index = 
static_cast<decltype(index)
>(keysz);
 
  273      for (; sz > 0; s++, sz--)
 
  280          JSON_ACTION_START_STRUCT,
 
  281          JSON_ACTION_END_STRUCT
 
  282        } action = JSON_ACTION_NONE;
 
  283        auto c = 
static_cast<unsigned char>(*s);
 
  286          case JSON_STATE_VALUE:
 
  287            if (c == 
' ' || c == 
'\t' || c == 
'\n' || c == 
'\r' || c == 
',' || c == 
':')
 
  293              action = JSON_ACTION_START;
 
  294              state = JSON_STATE_STRING;
 
  296            else if (c == 
'{' || c == 
'[')
 
  298              action = JSON_ACTION_START_STRUCT;
 
  300            else if (c == 
'}' || c == 
']')
 
  302              action = JSON_ACTION_END_STRUCT;
 
  304            else if (c == 
't' || c == 
'f' || c == 
'n' || c == 
'-' ||
 
  305                     (c >= 
'0' && c <= 
'9'))
 
  307              action = JSON_ACTION_START;
 
  308              state = JSON_STATE_LITERAL;
 
  315          case JSON_STATE_LITERAL:
 
  316            if (c == 
' ' || c == 
'\t' || c == 
'\n' || c == 
'\r' || c == 
',' ||
 
  317                c == 
']' || c == 
'}' || c == 
':')
 
  319              state = JSON_STATE_VALUE;
 
  322              action = JSON_ACTION_END;
 
  324            else if (c < 32 || c > 126)
 
  328          case JSON_STATE_STRING:
 
  329            if (c < 32 || (c > 126 && c < 192))
 
  335              action = JSON_ACTION_END;
 
  336              state = JSON_STATE_VALUE;
 
  340              state = JSON_STATE_ESCAPE;
 
  342            else if (c >= 192 && c < 224)
 
  345              state = JSON_STATE_UTF8;
 
  347            else if (c >= 224 && c < 240)
 
  350              state = JSON_STATE_UTF8;
 
  352            else if (c >= 240 && c < 247)
 
  355              state = JSON_STATE_UTF8;
 
  357            else if (c >= 128 && c < 192)
 
  362          case JSON_STATE_ESCAPE:
 
  363            if (c == 
'"' || c == 
'\\' || c == 
'/' || c == 
'b' || c == 
'f' || c == 
'n' ||
 
  364                c == 
'r' || c == 
't' || c == 
'u')
 
  366              state = JSON_STATE_STRING;
 
  373          case JSON_STATE_UTF8:
 
  374            if (c < 128 || c > 191)
 
  381              state = JSON_STATE_STRING;
 
  388        if (action == JSON_ACTION_END_STRUCT)
 
  395          if (action == JSON_ACTION_START || action == JSON_ACTION_START_STRUCT)
 
  401            else if (keysz > 0 && index == 1)
 
  410          else if (action == JSON_ACTION_END || action == JSON_ACTION_END_STRUCT)
 
  412            if (*value != 
nullptr && index == 0)
 
  414              *valuesz = (size_t)(s + 1 - *value);
 
  417            else if (keysz > 0 && k != 
nullptr)
 
  419              if (keysz == (
size_t)(s - k - 1) && memcmp(key, k + 1, keysz) == 0)
 
  432        if (action == JSON_ACTION_START_STRUCT)
 
  440    inline std::string json_escape(
const std::string& s)
 
  443      return '"' + s + 
'"';
 
  446    inline int json_unescape(
const char* s, 
size_t n, 
char* out)
 
  509    inline std::string json_parse(
const std::string& s, 
const std::string& key, 
const int index)
 
  511      const char* value = 
nullptr;
 
  515        json_parse_c(s.c_str(), s.length(), 
nullptr, index, &value, &value_sz);
 
  519        json_parse_c(s.c_str(), s.length(), key.c_str(), key.length(), &value, &value_sz);
 
  521      if (value != 
nullptr)
 
  525          return { value, value_sz };
 
  527        int n = json_unescape(value, value_sz, 
nullptr);
 
  530          char* decoded = 
new char[1ull + n];
 
  531          json_unescape(value, value_sz, decoded);
 
  532          std::string result(decoded, n);
 
  542  WEBVIEW_DEPRECATED_PRIVATE
 
  543  inline int json_parse_c(
const char* s, 
size_t sz, 
const char* key, 
size_t keysz,
 
  544                          const char** value, 
size_t* valuesz)
 
  546    return detail::json_parse_c(s, sz, key, keysz, value, valuesz);
 
  549  WEBVIEW_DEPRECATED_PRIVATE
 
  550  inline std::string json_escape(
const std::string& s)
 
  552    return detail::json_escape(s);
 
  555  WEBVIEW_DEPRECATED_PRIVATE
 
  556  inline int json_unescape(
const char* s, 
size_t n, 
char* out)
 
  558    return detail::json_unescape(s, n, out);
 
  561  WEBVIEW_DEPRECATED_PRIVATE
 
  562  inline std::string json_parse(
const std::string& s, 
const std::string& key, 
const int index)
 
  564    return detail::json_parse(s, key, index);
 
  569#if defined(WEBVIEW_GTK) 
  580#include <JavaScriptCore/JavaScript.h> 
  582#include <webkit2/webkit2.h> 
  589    class gtk_webkit_engine
 
  592      gtk_webkit_engine(
bool debug, 
void* window) : m_window(static_cast<GtkWidget*>(window))
 
  594        if (gtk_init_check(
nullptr, 
nullptr) == FALSE)
 
  598        m_window = 
static_cast<GtkWidget*
>(window);
 
  599        if (m_window == 
nullptr)
 
  601          m_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
  603        g_signal_connect(G_OBJECT(m_window), 
"destroy",
 
  604                         G_CALLBACK(+[](GtkWidget*, gpointer arg)
 
  605                                    { 
static_cast<gtk_webkit_engine*
>(arg)->terminate(); }),
 
  608        m_webview = webkit_web_view_new();
 
  609        WebKitUserContentManager* manager =
 
  610            webkit_web_view_get_user_content_manager(WEBKIT_WEB_VIEW(m_webview));
 
  611        g_signal_connect(manager, 
"script-message-received::external",
 
  612                         G_CALLBACK(+[](WebKitUserContentManager*,
 
  613                                        WebKitJavascriptResult* r, gpointer arg)
 
  615                                      auto* w = 
static_cast<gtk_webkit_engine*
>(arg);
 
  616                                      char* s = get_string_from_js_result(r);
 
  621        webkit_user_content_manager_register_script_message_handler(manager, 
"external");
 
  622        init(
"window.external={invoke:function(s){window.webkit.messageHandlers." 
  623             "external.postMessage(s);}}");
 
  625        gtk_container_add(GTK_CONTAINER(m_window), GTK_WIDGET(m_webview));
 
  626        gtk_widget_grab_focus(GTK_WIDGET(m_webview));
 
  628        WebKitSettings* settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(m_webview));
 
  629        webkit_settings_set_javascript_can_access_clipboard(settings, 
true);
 
  632          webkit_settings_set_enable_write_console_messages_to_stdout(settings, 
true);
 
  633          webkit_settings_set_enable_developer_extras(settings, 
true);
 
  636        gtk_widget_show_all(m_window);
 
  638      virtual ~gtk_webkit_engine() = 
default;
 
  641        return (
void*)m_window;
 
  651      void dispatch(std::function<
void()> f)
 
  653        g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)([](
void* f) -> 
int {
 
  654                          (*
static_cast<dispatch_fn_t*
>(f))();
 
  655                          return G_SOURCE_REMOVE;
 
  657                        new std::function<
void()>(f),
 
  658                        [](
void* f) { 
delete static_cast<dispatch_fn_t*
>(f); });
 
  661      void set_title(
const std::string& title)
 
  663        gtk_window_set_title(GTK_WINDOW(m_window), title.c_str());
 
  666      void set_size(
int width, 
int height, 
int hints)
 
  668        gtk_window_set_resizable(GTK_WINDOW(m_window), hints != WEBVIEW_HINT_FIXED);
 
  669        if (hints == WEBVIEW_HINT_NONE)
 
  671          gtk_window_resize(GTK_WINDOW(m_window), width, height);
 
  673        else if (hints == WEBVIEW_HINT_FIXED)
 
  675          gtk_widget_set_size_request(m_window, width, height);
 
  680          g.min_width = g.max_width = width;
 
  681          g.min_height = g.max_height = height;
 
  683              (hints == WEBVIEW_HINT_MIN ? GDK_HINT_MIN_SIZE : GDK_HINT_MAX_SIZE);
 
  685          gtk_window_set_geometry_hints(GTK_WINDOW(m_window), 
nullptr, &g, h);
 
  689      void navigate(
const std::string& url)
 
  691        webkit_web_view_load_uri(WEBKIT_WEB_VIEW(m_webview), url.c_str());
 
  694      void add_navigate_listener(std::function<
void(
const std::string&, 
void*)> callback,
 
  697        g_signal_connect(WEBKIT_WEB_VIEW(m_webview), 
"load-changed",
 
  698                         G_CALLBACK(on_load_changed), 
this);
 
  699        navigateCallbackArg = arg;
 
  700        navigateCallback = std::move(callback);
 
  703      void add_scheme_handler(
const std::string& scheme,
 
  704                              std::function<
void(
const std::string&, 
void*)> callback,
 
  707        auto view = WEBKIT_WEB_VIEW(m_webview);
 
  708        auto context = webkit_web_view_get_context(view);
 
  710        scheme_handlers.insert({ scheme, { .arg = arg, .fkt = callback } });
 
  711        webkit_web_context_register_uri_scheme(context, scheme.c_str(), scheme_handler,
 
  712                                               static_cast<gpointer
>(
this), 
nullptr);
 
  715      void set_html(
const std::string& html)
 
  717        webkit_web_view_load_html(WEBKIT_WEB_VIEW(m_webview), html.c_str(), 
nullptr);
 
  720      void init(
const std::string& js)
 
  722        WebKitUserContentManager* manager =
 
  723            webkit_web_view_get_user_content_manager(WEBKIT_WEB_VIEW(m_webview));
 
  724        webkit_user_content_manager_add_script(
 
  725            manager, webkit_user_script_new(
 
  726                         js.c_str(), WEBKIT_USER_CONTENT_INJECT_TOP_FRAME,
 
  727                         WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START, 
nullptr, 
nullptr));
 
  730      void eval(
const std::string& js)
 
  732        webkit_web_view_run_javascript(WEBKIT_WEB_VIEW(m_webview), js.c_str(), 
nullptr,
 
  737      virtual void on_message(
const std::string& msg) = 0;
 
  742        std::function<void(
const std::string&, 
void*)> fkt;
 
  745      std::map<std::string, handler_t> scheme_handlers;
 
  747      void scheme_handler_call(
const std::string& scheme, 
const std::string& url)
 
  749        auto handler = scheme_handlers.find(scheme);
 
  750        if (handler != scheme_handlers.end())
 
  752          const auto& arg = handler->second;
 
  753          arg.fkt(url, arg.arg);
 
  757      static void scheme_handler(WebKitURISchemeRequest* request, gpointer user_data)
 
  759        auto _this = 
static_cast<gtk_webkit_engine*
>(user_data);
 
  761        auto scheme = webkit_uri_scheme_request_get_scheme(request);
 
  762        auto uri = webkit_uri_scheme_request_get_uri(request);
 
  763        _this->scheme_handler_call(scheme, uri);
 
  766      static char* get_string_from_js_result(WebKitJavascriptResult* r)
 
  769#if WEBKIT_MAJOR_VERSION >= 2 && WEBKIT_MINOR_VERSION >= 22 
  770        JSCValue* value = webkit_javascript_result_get_js_value(r);
 
  771        s = jsc_value_to_string(value);
 
  773        JSGlobalContextRef ctx = webkit_javascript_result_get_global_context(r);
 
  774        JSValueRef value = webkit_javascript_result_get_value(r);
 
  775        JSStringRef js = JSValueToStringCopy(ctx, value, 
nullptr);
 
  776        size_t n = JSStringGetMaximumUTF8CStringSize(js);
 
  778        JSStringGetUTF8CString(js, s, n);
 
  785      GtkWidget* m_webview;
 
  787      void* navigateCallbackArg = 
nullptr;
 
  788      std::function<void(
const std::string&, 
void*)> navigateCallback = 
nullptr;
 
  790      static void on_load_changed(WebKitWebView* web_view, WebKitLoadEvent load_event,
 
  793        if (load_event == WEBKIT_LOAD_FINISHED)
 
  795          auto inst = 
static_cast<gtk_webkit_engine*
>(arg);
 
  796          inst->navigateCallback(webkit_web_view_get_uri(web_view),
 
  797                                 inst->navigateCallbackArg);
 
  804  using browser_engine = detail::gtk_webkit_engine;
 
  808#elif defined(WEBVIEW_COCOA) 
  820#include <CoreGraphics/CoreGraphics.h> 
  821#include <objc/NSObjCRuntime.h> 
  822#include <objc/objc-runtime.h> 
  836      template <
typename Result, 
typename Callable, 
typename... Args>
 
  837      Result invoke(Callable callable, Args... args) 
noexcept 
  839        return reinterpret_cast<Result (*)(Args...)
>(callable)(args...);
 
  843      template <
typename Result, 
typename... Args> Result msg_send(Args... args) 
noexcept 
  845        return invoke<Result>(objc_msgSend, args...);
 
  850    enum NSBackingStoreType : NSUInteger
 
  852      NSBackingStoreBuffered = 2
 
  855    enum NSWindowStyleMask : NSUInteger
 
  857      NSWindowStyleMaskTitled = 1,
 
  858      NSWindowStyleMaskClosable = 2,
 
  859      NSWindowStyleMaskMiniaturizable = 4,
 
  860      NSWindowStyleMaskResizable = 8
 
  863    enum NSApplicationActivationPolicy : NSInteger
 
  865      NSApplicationActivationPolicyRegular = 0
 
  868    enum WKUserScriptInjectionTime : NSInteger
 
  870      WKUserScriptInjectionTimeAtDocumentStart = 0
 
  873    enum NSModalResponse : NSInteger
 
  875      NSModalResponseOK = 1
 
  879    inline id operator"" _cls(
const char* s, std::size_t)
 
  881      return (
id)objc_getClass(s);
 
  883    inline SEL operator"" _sel(
const char* s, std::size_t)
 
  885      return sel_registerName(s);
 
  887    inline id operator"" _str(
const char* s, std::size_t)
 
  889      return objc::msg_send<id>(
"NSString"_cls, 
"stringWithUTF8String:"_sel, s);
 
  892    class cocoa_wkwebview_engine
 
  895      cocoa_wkwebview_engine(
bool debug, 
void* window)
 
  896          : m_debug{ debug }, m_parent_window{ window }
 
  898        auto app = get_shared_application();
 
  899        auto delegate = create_app_delegate();
 
  900        objc_setAssociatedObject(delegate, 
"webview", (
id)
this, OBJC_ASSOCIATION_ASSIGN);
 
  901        objc::msg_send<void>(app, 
"setDelegate:"_sel, delegate);
 
  906          on_application_did_finish_launching(delegate, app);
 
  915          objc::msg_send<void>(app, 
"run"_sel);
 
  918      virtual ~cocoa_wkwebview_engine() = 
default;
 
  921        return (
void*)m_window;
 
  925        auto app = get_shared_application();
 
  926        objc::msg_send<void>(app, 
"terminate:"_sel, 
nullptr);
 
  930        auto app = get_shared_application();
 
  931        objc::msg_send<void>(app, 
"run"_sel);
 
  933      void dispatch(std::function<
void()> f)
 
  935        dispatch_async_f(dispatch_get_main_queue(), 
new dispatch_fn_t(f),
 
  936                         (dispatch_function_t)([](
void* arg) {
 
  937                           auto f = 
static_cast<dispatch_fn_t*
>(arg);
 
  942      void set_title(
const std::string& title)
 
  944        objc::msg_send<void>(
 
  945            m_window, 
"setTitle:"_sel,
 
  946            objc::msg_send<id>(
"NSString"_cls, 
"stringWithUTF8String:"_sel, title.c_str()));
 
  948      void set_size(
int width, 
int height, 
int hints)
 
  950        auto style = 
static_cast<NSWindowStyleMask
>(NSWindowStyleMaskTitled |
 
  951                                                    NSWindowStyleMaskClosable |
 
  952                                                    NSWindowStyleMaskMiniaturizable);
 
  953        if (hints != WEBVIEW_HINT_FIXED)
 
  955          style = 
static_cast<NSWindowStyleMask
>(style | NSWindowStyleMaskResizable);
 
  957        objc::msg_send<void>(m_window, 
"setStyleMask:"_sel, style);
 
  959        if (hints == WEBVIEW_HINT_MIN)
 
  961          objc::msg_send<void>(m_window, 
"setContentMinSize:"_sel,
 
  962                               CGSizeMake(width, height));
 
  964        else if (hints == WEBVIEW_HINT_MAX)
 
  966          objc::msg_send<void>(m_window, 
"setContentMaxSize:"_sel,
 
  967                               CGSizeMake(width, height));
 
  971          objc::msg_send<void>(m_window, 
"setFrame:display:animate:"_sel,
 
  972                               CGRectMake(0, 0, width, height), YES, NO);
 
  974        objc::msg_send<void>(m_window, 
"center"_sel);
 
  976      void navigate(
const std::string& url)
 
  978        auto nsurl = objc::msg_send<id>(
 
  979            "NSURL"_cls, 
"URLWithString:"_sel,
 
  980            objc::msg_send<id>(
"NSString"_cls, 
"stringWithUTF8String:"_sel, url.c_str()));
 
  982        objc::msg_send<void>(
 
  983            m_webview, 
"loadRequest:"_sel,
 
  984            objc::msg_send<id>(
"NSURLRequest"_cls, 
"requestWithURL:"_sel, nsurl));
 
  987      void add_navigate_listener(std::function<
void(
const std::string&, 
void*)> callback,
 
  990        m_navigateCallback = callback;
 
  991        m_navigateCallbackArg = arg;
 
  994      void add_scheme_handler(
const std::string& scheme,
 
  995                              std::function<
void(
const std::string&, 
void*)> callback,
 
 1001      void set_html(
const std::string& html)
 
 1003        objc::msg_send<void>(
 
 1004            m_webview, 
"loadHTMLString:baseURL:"_sel,
 
 1005            objc::msg_send<id>(
"NSString"_cls, 
"stringWithUTF8String:"_sel, html.c_str()),
 
 1008      void init(
const std::string& js)
 
 1014        objc::msg_send<void>(
 
 1015            m_manager, 
"addUserScript:"_sel,
 
 1017                objc::msg_send<id>(
"WKUserScript"_cls, 
"alloc"_sel),
 
 1018                "initWithSource:injectionTime:forMainFrameOnly:"_sel,
 
 1019                objc::msg_send<id>(
"NSString"_cls, 
"stringWithUTF8String:"_sel, js.c_str()),
 
 1020                WKUserScriptInjectionTimeAtDocumentStart, YES));
 
 1022      void eval(
const std::string& js)
 
 1024        objc::msg_send<void>(
 
 1025            m_webview, 
"evaluateJavaScript:completionHandler:"_sel,
 
 1026            objc::msg_send<id>(
"NSString"_cls, 
"stringWithUTF8String:"_sel, js.c_str()),
 
 1031      virtual void on_message(
const std::string& msg) = 0;
 
 1032      id create_app_delegate()
 
 1038            objc_allocateClassPair((Class) 
"NSResponder"_cls, 
"WebviewAppDelegate", 0);
 
 1039        class_addProtocol(cls, objc_getProtocol(
"NSTouchBarProvider"));
 
 1040        class_addMethod(cls, 
"applicationShouldTerminateAfterLastWindowClosed:"_sel,
 
 1041                        (IMP)(+[](
id, 
SEL, 
id) -> BOOL { 
return 1; }), 
"c@:@");
 
 1046        if (!m_parent_window)
 
 1048          class_addMethod(cls, 
"applicationDidFinishLaunching:"_sel,
 
 1049                          (IMP)(+[](
id self, 
SEL, 
id notification)
 
 1052                                      objc::msg_send<id>(notification, 
"object"_sel);
 
 1053                                  auto w = get_associated_webview(self);
 
 1054                                  w->on_application_did_finish_launching(self, app);
 
 1058        objc_registerClassPair(cls);
 
 1059        return objc::msg_send<id>((
id)cls, 
"new"_sel);
 
 1061      id create_script_message_handler()
 
 1063        auto cls = objc_allocateClassPair((Class) 
"NSResponder"_cls,
 
 1064                                          "WebkitScriptMessageHandler", 0);
 
 1065        class_addProtocol(cls, objc_getProtocol(
"WKScriptMessageHandler"));
 
 1067            cls, 
"userContentController:didReceiveScriptMessage:"_sel,
 
 1068            (IMP)(+[](
id self, 
SEL, 
id, 
id msg)
 
 1070                    auto w = get_associated_webview(self);
 
 1071                    w->on_message(objc::msg_send<const char*>(
 
 1072                        objc::msg_send<id>(msg, 
"body"_sel), 
"UTF8String"_sel));
 
 1075        objc_registerClassPair(cls);
 
 1076        auto instance = objc::msg_send<id>((
id)cls, 
"new"_sel);
 
 1077        objc_setAssociatedObject(instance, 
"webview", (
id)
this, OBJC_ASSOCIATION_ASSIGN);
 
 1080      static id create_webkit_ui_delegate()
 
 1082        auto cls = objc_allocateClassPair((Class) 
"NSObject"_cls, 
"WebkitUIDelegate", 0);
 
 1083        class_addProtocol(cls, objc_getProtocol(
"WKUIDelegate"));
 
 1086            "webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:"_sel,
 
 1087            (IMP)(+[](
id, 
SEL, 
id, 
id parameters, 
id, 
id completion_handler)
 
 1089                    auto allows_multiple_selection =
 
 1090                        objc::msg_send<BOOL>(parameters, 
"allowsMultipleSelection"_sel);
 
 1091                    auto allows_directories =
 
 1092                        objc::msg_send<BOOL>(parameters, 
"allowsDirectories"_sel);
 
 1095                    auto panel = objc::msg_send<id>(
"NSOpenPanel"_cls, 
"openPanel"_sel);
 
 1096                    objc::msg_send<void>(panel, 
"setCanChooseFiles:"_sel, YES);
 
 1097                    objc::msg_send<void>(panel, 
"setCanChooseDirectories:"_sel,
 
 1098                                         allows_directories);
 
 1099                    objc::msg_send<void>(panel, 
"setAllowsMultipleSelection:"_sel,
 
 1100                                         allows_multiple_selection);
 
 1101                    auto modal_response =
 
 1102                        objc::msg_send<NSModalResponse>(panel, 
"runModal"_sel);
 
 1107                    id urls = modal_response == NSModalResponseOK
 
 1108                                  ? objc::msg_send<id>(panel, 
"URLs"_sel)
 
 1112                    auto sig = objc::msg_send<id>(
"NSMethodSignature"_cls,
 
 1113                                                  "signatureWithObjCTypes:"_sel, 
"v@?@");
 
 1114                    auto invocation = objc::msg_send<id>(
 
 1115                        "NSInvocation"_cls, 
"invocationWithMethodSignature:"_sel, sig);
 
 1116                    objc::msg_send<void>(invocation, 
"setTarget:"_sel,
 
 1117                                         completion_handler);
 
 1118                    objc::msg_send<void>(invocation, 
"setArgument:atIndex:"_sel, &urls,
 
 1120                    objc::msg_send<void>(invocation, 
"invoke"_sel);
 
 1123        objc_registerClassPair(cls);
 
 1124        return objc::msg_send<id>((
id)cls, 
"new"_sel);
 
 1126      id create_webkit_navigation_delegate()
 
 1129            objc_allocateClassPair((Class) 
"NSObject"_cls, 
"WebkitNavigationDelegate", 0);
 
 1130        class_addProtocol(cls, objc_getProtocol(
"WKNavigationDelegate"));
 
 1131        class_addMethod(cls, 
"webView:didFinishNavigation:"_sel,
 
 1132                        (IMP)(+[](
id delegate, 
SEL sel, 
id webview, 
id navigation)
 
 1134                                auto w = get_associated_webview(delegate);
 
 1135                                auto url = objc::msg_send<id>(webview, 
"URL"_sel);
 
 1136                                auto nstr = objc::msg_send<id>(url, 
"absoluteString"_sel);
 
 1137                                auto str = objc::msg_send<char*>(nstr, 
"UTF8String"_sel);
 
 1138                                w->m_navigateCallback(str, w->m_navigateCallbackArg);
 
 1141        objc_registerClassPair(cls);
 
 1142        auto instance = objc::msg_send<id>((
id)cls, 
"new"_sel);
 
 1143        objc_setAssociatedObject(instance, 
"webview", (
id)
this, OBJC_ASSOCIATION_ASSIGN);
 
 1146      static id get_shared_application()
 
 1148        return objc::msg_send<id>(
"NSApplication"_cls, 
"sharedApplication"_sel);
 
 1150      static cocoa_wkwebview_engine* get_associated_webview(
id object)
 
 1152        auto w = (cocoa_wkwebview_engine*)objc_getAssociatedObject(
object, 
"webview");
 
 1156      static id get_main_bundle() noexcept
 
 1158        return objc::msg_send<id>(
"NSBundle"_cls, 
"mainBundle"_sel);
 
 1160      static bool is_app_bundled() noexcept
 
 1162        auto bundle = get_main_bundle();
 
 1167        auto bundle_path = objc::msg_send<id>(bundle, 
"bundlePath"_sel);
 
 1168        auto bundled = objc::msg_send<BOOL>(bundle_path, 
"hasSuffix:"_sel, 
".app"_str);
 
 1171      void on_application_did_finish_launching(
id , 
id app)
 
 1174        if (!m_parent_window)
 
 1178          objc::msg_send<void>(app, 
"stop:"_sel, 
nullptr);
 
 1189        if (!is_app_bundled())
 
 1193          objc::msg_send<void>(app, 
"setActivationPolicy:"_sel,
 
 1194                               NSApplicationActivationPolicyRegular);
 
 1197          objc::msg_send<void>(app, 
"activateIgnoringOtherApps:"_sel, YES);
 
 1201        if (!m_parent_window)
 
 1203          m_window = objc::msg_send<id>(
"NSWindow"_cls, 
"alloc"_sel);
 
 1204          auto style = NSWindowStyleMaskTitled;
 
 1205          m_window = objc::msg_send<id>(
 
 1206              m_window, 
"initWithContentRect:styleMask:backing:defer:"_sel,
 
 1207              CGRectMake(0, 0, 0, 0), style, NSBackingStoreBuffered, NO);
 
 1211          m_window = (id)m_parent_window;
 
 1215        auto config = objc::msg_send<id>(
"WKWebViewConfiguration"_cls, 
"new"_sel);
 
 1216        m_manager = objc::msg_send<id>(config, 
"userContentController"_sel);
 
 1217        m_webview = objc::msg_send<id>(
"WKWebView"_cls, 
"alloc"_sel);
 
 1224              objc::msg_send<id>(config, 
"preferences"_sel), 
"setValue:forKey:"_sel,
 
 1225              objc::msg_send<id>(
"NSNumber"_cls, 
"numberWithBool:"_sel, YES),
 
 1226              "developerExtrasEnabled"_str);
 
 1231        objc::msg_send<id>(objc::msg_send<id>(config, 
"preferences"_sel),
 
 1232                           "setValue:forKey:"_sel,
 
 1233                           objc::msg_send<id>(
"NSNumber"_cls, 
"numberWithBool:"_sel, YES),
 
 1234                           "fullScreenEnabled"_str);
 
 1238        objc::msg_send<id>(objc::msg_send<id>(config, 
"preferences"_sel),
 
 1239                           "setValue:forKey:"_sel,
 
 1240                           objc::msg_send<id>(
"NSNumber"_cls, 
"numberWithBool:"_sel, YES),
 
 1241                           "javaScriptCanAccessClipboard"_str);
 
 1245        objc::msg_send<id>(objc::msg_send<id>(config, 
"preferences"_sel),
 
 1246                           "setValue:forKey:"_sel,
 
 1247                           objc::msg_send<id>(
"NSNumber"_cls, 
"numberWithBool:"_sel, YES),
 
 1248                           "DOMPasteAllowed"_str);
 
 1250        auto ui_delegate = create_webkit_ui_delegate();
 
 1251        objc::msg_send<void>(m_webview, 
"initWithFrame:configuration:"_sel,
 
 1252                             CGRectMake(0, 0, 0, 0), config);
 
 1253        objc::msg_send<void>(m_webview, 
"setUIDelegate:"_sel, ui_delegate);
 
 1255        auto navigation_delegate = create_webkit_navigation_delegate();
 
 1256        objc::msg_send<void>(m_webview, 
"setNavigationDelegate:"_sel, navigation_delegate);
 
 1257        auto script_message_handler = create_script_message_handler();
 
 1258        objc::msg_send<void>(m_manager, 
"addScriptMessageHandler:name:"_sel,
 
 1259                             script_message_handler, 
"external"_str);
 
 1263        invoke: function(s) { 
 1264          window.webkit.messageHandlers.external.postMessage(s); 
 1268        objc::msg_send<void>(m_window, "setContentView:"_sel, m_webview);
 
 1269        objc::msg_send<void>(m_window, 
"makeKeyAndOrderFront:"_sel, 
nullptr);
 
 1272      void* m_parent_window;
 
 1276      void* m_navigateCallbackArg = 
nullptr;
 
 1277      std::function<void(
const std::string&, 
void*)> m_navigateCallback = 0;
 
 1282  using browser_engine = detail::cocoa_wkwebview_engine;
 
 1286#elif defined(WEBVIEW_EDGE) 
 1297#define WIN32_LEAN_AND_MEAN 
 1303#include "WebView2.h" 
 1306#pragma comment(lib, "advapi32.lib") 
 1307#pragma comment(lib, "ole32.lib") 
 1308#pragma comment(lib, "shell32.lib") 
 1309#pragma comment(lib, "shlwapi.lib") 
 1310#pragma comment(lib, "user32.lib") 
 1311#pragma comment(lib, "version.lib") 
 1319    using msg_cb_t = std::function<void(
const std::string)>;
 
 1322    inline std::wstring widen_string(
const std::string& input)
 
 1326        return std::wstring();
 
 1329      DWORD flags = MB_ERR_INVALID_CHARS;
 
 1330      auto input_c = input.c_str();
 
 1331      auto input_length = 
static_cast<int>(input.size());
 
 1332      auto required_length =
 
 1333          MultiByteToWideChar(cp, flags, input_c, input_length, 
nullptr, 0);
 
 1334      if (required_length > 0)
 
 1336        std::wstring output(
static_cast<std::size_t
>(required_length), L
'\0');
 
 1337        if (MultiByteToWideChar(cp, flags, input_c, input_length, &output[0],
 
 1338                                required_length) > 0)
 
 1344      return std::wstring();
 
 1348    inline std::string narrow_string(
const std::wstring& input)
 
 1352        return std::string();
 
 1355      DWORD flags = WC_ERR_INVALID_CHARS;
 
 1356      auto input_c = input.c_str();
 
 1357      auto input_length = 
static_cast<int>(input.size());
 
 1358      auto required_length =
 
 1359          WideCharToMultiByte(cp, flags, input_c, input_length, 
nullptr, 0, 
nullptr, 
nullptr);
 
 1360      if (required_length > 0)
 
 1362        std::string output(
static_cast<std::size_t
>(required_length), 
'\0');
 
 1363        if (WideCharToMultiByte(cp, flags, input_c, input_length, &output[0],
 
 1364                                required_length, 
nullptr, 
nullptr) > 0)
 
 1370      return std::string();
 
 1375    template <
typename T>
 
 1376    std::array<unsigned int, 4> parse_version(
const std::basic_string<T>& version) 
noexcept 
 1378      auto parse_component = [](
auto sb, 
auto se) -> 
unsigned int 
 1382          auto n = std::stol(std::basic_string<T>(sb, se));
 
 1383          return n < 0 ? 0 : n;
 
 1385        catch (std::exception&)
 
 1390      auto end = version.end();
 
 1391      auto sb = version.begin(); 
 
 1393      unsigned int ci = 0;       
 
 1394      std::array<unsigned int, 4> components{};
 
 1395      while (sb != end && se != end && ci < components.size())
 
 1397        if (*se == 
static_cast<T
>(
'.'))
 
 1399          components[ci++] = parse_component(sb, se);
 
 1405      if (sb < se && ci < components.size())
 
 1407        components[ci] = parse_component(sb, se);
 
 1412    template <
typename T, std::
size_t Length>
 
 1413    auto parse_version(
const T (&version)[Length]) 
noexcept 
 1415      return parse_version(std::basic_string<T>(version, Length));
 
 1418    std::wstring get_file_version_string(
const std::wstring& file_path) 
noexcept 
 1421      DWORD info_buffer_length = GetFileVersionInfoSizeW(file_path.c_str(), &dummy_handle);
 
 1422      if (info_buffer_length == 0)
 
 1424        return std::wstring();
 
 1426      std::vector<char> info_buffer;
 
 1427      info_buffer.reserve(info_buffer_length);
 
 1428      if (!GetFileVersionInfoW(file_path.c_str(), 0, info_buffer_length, info_buffer.data()))
 
 1430        return std::wstring();
 
 1432      auto sub_block = L
"\\StringFileInfo\\040904B0\\ProductVersion";
 
 1433      LPWSTR version = 
nullptr;
 
 1434      unsigned int version_length = 0;
 
 1435      if (!VerQueryValueW(info_buffer.data(), sub_block, 
reinterpret_cast<LPVOID*
>(&version),
 
 1438        return std::wstring();
 
 1440      if (!version || version_length == 0)
 
 1442        return std::wstring();
 
 1444      return std::wstring(version, version_length);
 
 1449    class com_init_wrapper
 
 1452      com_init_wrapper(DWORD dwCoInit)
 
 1458        switch (CoInitializeEx(
nullptr, dwCoInit))
 
 1462            m_initialized = 
true;
 
 1472          m_initialized = 
false;
 
 1476      com_init_wrapper(
const com_init_wrapper& other) = 
delete;
 
 1477      com_init_wrapper& operator=(
const com_init_wrapper& other) = 
delete;
 
 1478      com_init_wrapper(com_init_wrapper&& other) = 
delete;
 
 1479      com_init_wrapper& operator=(com_init_wrapper&& other) = 
delete;
 
 1481      bool is_initialized()
 const 
 1483        return m_initialized;
 
 1487      bool m_initialized = 
false;
 
 1491    template <
typename T> 
class library_symbol
 
 1496      constexpr explicit library_symbol(
const char* name) : m_name(name)
 
 1499      constexpr const char* get_name()
 const 
 1510    class native_library
 
 1513      explicit native_library(
const wchar_t* name) : m_handle(LoadLibraryW(name))
 
 1521          FreeLibrary(m_handle);
 
 1526      native_library(
const native_library& other) = 
delete;
 
 1527      native_library& operator=(
const native_library& other) = 
delete;
 
 1528      native_library(native_library&& other) = 
default;
 
 1529      native_library& operator=(native_library&& other) = 
default;
 
 1532      operator bool()
 const 
 1538      template <
typename Symbol> 
typename Symbol::type get(
const Symbol& symbol)
 const 
 1542          return reinterpret_cast<typename Symbol::type
>(
 
 1543              GetProcAddress(m_handle, symbol.get_name()));
 
 1549      bool is_loaded()
 const 
 1560      HMODULE m_handle = 
nullptr;
 
 1563    struct user32_symbols
 
 1565      using DPI_AWARENESS_CONTEXT = HANDLE;
 
 1566      using SetProcessDpiAwarenessContext_t = BOOL(WINAPI*)(DPI_AWARENESS_CONTEXT);
 
 1567      using SetProcessDPIAware_t = BOOL(WINAPI*)();
 
 1569      static constexpr auto SetProcessDpiAwarenessContext =
 
 1570          library_symbol<SetProcessDpiAwarenessContext_t>(
"SetProcessDpiAwarenessContext");
 
 1571      static constexpr auto SetProcessDPIAware =
 
 1572          library_symbol<SetProcessDPIAware_t>(
"SetProcessDPIAware");
 
 1575    struct shcore_symbols
 
 1579        PROCESS_PER_MONITOR_DPI_AWARE = 2
 
 1580      } PROCESS_DPI_AWARENESS;
 
 1581      using SetProcessDpiAwareness_t = HRESULT(WINAPI*)(PROCESS_DPI_AWARENESS);
 
 1583      static constexpr auto SetProcessDpiAwareness =
 
 1584          library_symbol<SetProcessDpiAwareness_t>(
"SetProcessDpiAwareness");
 
 1590      explicit reg_key(HKEY root_key, 
const wchar_t* sub_key, DWORD options,
 
 1594        auto status = RegOpenKeyExW(root_key, sub_key, options, sam_desired, &handle);
 
 1595        if (status == ERROR_SUCCESS)
 
 1601      explicit reg_key(HKEY root_key, 
const std::wstring& sub_key, DWORD options,
 
 1603          : reg_key(root_key, sub_key.c_str(), options, sam_desired)
 
 1611          RegCloseKey(m_handle);
 
 1616      reg_key(
const reg_key& other) = 
delete;
 
 1617      reg_key& operator=(
const reg_key& other) = 
delete;
 
 1618      reg_key(reg_key&& other) = 
delete;
 
 1619      reg_key& operator=(reg_key&& other) = 
delete;
 
 1621      bool is_open()
 const 
 1625      bool get_handle()
 const 
 1630      std::wstring query_string(
const wchar_t* name)
 const 
 1632        DWORD buf_length = 0;
 
 1635            RegQueryValueExW(m_handle, name, 
nullptr, 
nullptr, 
nullptr, &buf_length);
 
 1636        if (status != ERROR_SUCCESS && status != ERROR_MORE_DATA)
 
 1638          return std::wstring();
 
 1641        std::wstring result(buf_length / 
sizeof(
wchar_t), 0);
 
 1642        auto buf = 
reinterpret_cast<LPBYTE
>(&result[0]);
 
 1643        status = RegQueryValueExW(m_handle, name, 
nullptr, 
nullptr, buf, &buf_length);
 
 1644        if (status != ERROR_SUCCESS)
 
 1646          return std::wstring();
 
 1649        for (std::size_t length = result.size(); length > 0; --length)
 
 1651          if (result[length - 1] != 0)
 
 1653            result.resize(length);
 
 1661      HKEY m_handle = 
nullptr;
 
 1664    inline bool enable_dpi_awareness()
 
 1666      auto user32 = native_library(L
"user32.dll");
 
 1667      if (
auto fn = user32.get(user32_symbols::SetProcessDpiAwarenessContext))
 
 1669        if (fn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
 
 1673        return GetLastError() == ERROR_ACCESS_DENIED;
 
 1675      if (
auto shcore = native_library(L
"shcore.dll"))
 
 1677        if (
auto fn = shcore.get(shcore_symbols::SetProcessDpiAwareness))
 
 1679          auto result = fn(shcore_symbols::PROCESS_PER_MONITOR_DPI_AWARE);
 
 1680          return result == S_OK || result == E_ACCESSDENIED;
 
 1683      if (
auto fn = user32.get(user32_symbols::SetProcessDPIAware))
 
 1691#ifndef WEBVIEW_MSWEBVIEW2_BUILTIN_IMPL 
 1692#define WEBVIEW_MSWEBVIEW2_BUILTIN_IMPL 1 
 1697#ifndef WEBVIEW_MSWEBVIEW2_EXPLICIT_LINK 
 1698#define WEBVIEW_MSWEBVIEW2_EXPLICIT_LINK WEBVIEW_MSWEBVIEW2_BUILTIN_IMPL 
 1703#if WEBVIEW_MSWEBVIEW2_BUILTIN_IMPL == 1 && WEBVIEW_MSWEBVIEW2_EXPLICIT_LINK != 1 
 1704#undef WEBVIEW_MSWEBVIEW2_EXPLICIT_LINK 
 1705#error Please set WEBVIEW_MSWEBVIEW2_EXPLICIT_LINK=1. 
 1708#if WEBVIEW_MSWEBVIEW2_BUILTIN_IMPL == 1 
 1711    template <
typename T>
 
 1712    std::basic_string<T> get_last_native_path_component(
const std::basic_string<T>& path)
 
 1714      if (
auto pos = path.find_last_of(
static_cast<T
>(
'\\'));
 
 1715          pos != std::basic_string<T>::npos)
 
 1717        return path.substr(pos + 1);
 
 1719      return std::basic_string<T>();
 
 1723    template <
typename T> 
struct cast_info_t
 
 1729    namespace mswebview2
 
 1731      static constexpr IID IID_ICoreWebView2CreateCoreWebView2ControllerCompletedHandler{
 
 1732        0x6C4819F3, 0xC9B7, 0x4260, 0x81, 0x27, 0xC9, 0xF5, 0xBD, 0xE7, 0xF6, 0x8C
 
 1734      static constexpr IID IID_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler{
 
 1735        0x4E8A3389, 0xC9D8, 0x4BD2, 0xB6, 0xB5, 0x12, 0x4F, 0xEE, 0x6C, 0xC1, 0x4D
 
 1737      static constexpr IID IID_ICoreWebView2PermissionRequestedEventHandler{
 
 1738        0x15E1C6A3, 0xC72A, 0x4DF3, 0x91, 0xD7, 0xD0, 0x97, 0xFB, 0xEC, 0x6B, 0xFD
 
 1740      static constexpr IID IID_ICoreWebView2WebMessageReceivedEventHandler{
 
 1741        0x57213F19, 0x00E6, 0x49FA, 0x8E, 0x07, 0x89, 0x8E, 0xA0, 0x1E, 0xCB, 0xD2
 
 1744#if WEBVIEW_MSWEBVIEW2_BUILTIN_IMPL == 1 
 1745      enum class webview2_runtime_type
 
 1751      namespace webview2_symbols
 
 1753        using CreateWebViewEnvironmentWithOptionsInternal_t = HRESULT(STDMETHODCALLTYPE*)(
 
 1754            bool, webview2_runtime_type, PCWSTR, IUnknown*,
 
 1755            ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler*);
 
 1756        using DllCanUnloadNow_t = HRESULT(STDMETHODCALLTYPE*)();
 
 1758        static constexpr auto CreateWebViewEnvironmentWithOptionsInternal =
 
 1759            library_symbol<CreateWebViewEnvironmentWithOptionsInternal_t>(
 
 1760                "CreateWebViewEnvironmentWithOptionsInternal");
 
 1761        static constexpr auto DllCanUnloadNow =
 
 1762            library_symbol<DllCanUnloadNow_t>(
"DllCanUnloadNow");
 
 1766#if WEBVIEW_MSWEBVIEW2_EXPLICIT_LINK == 1 
 1767      namespace webview2_symbols
 
 1769        using CreateCoreWebView2EnvironmentWithOptions_t = HRESULT(STDMETHODCALLTYPE*)(
 
 1770            PCWSTR, PCWSTR, ICoreWebView2EnvironmentOptions*,
 
 1771            ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler*);
 
 1772        using GetAvailableCoreWebView2BrowserVersionString_t =
 
 1773            HRESULT(STDMETHODCALLTYPE*)(PCWSTR, LPWSTR*);
 
 1775        static constexpr auto CreateCoreWebView2EnvironmentWithOptions =
 
 1776            library_symbol<CreateCoreWebView2EnvironmentWithOptions_t>(
 
 1777                "CreateCoreWebView2EnvironmentWithOptions");
 
 1778        static constexpr auto GetAvailableCoreWebView2BrowserVersionString =
 
 1779            library_symbol<GetAvailableCoreWebView2BrowserVersionString_t>(
 
 1780                "GetAvailableCoreWebView2BrowserVersionString");
 
 1787        HRESULT create_environment_with_options(
 
 1788            PCWSTR browser_dir, PCWSTR user_data_dir,
 
 1789            ICoreWebView2EnvironmentOptions* env_options,
 
 1790            ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler* created_handler)
 
 1793#if WEBVIEW_MSWEBVIEW2_EXPLICIT_LINK == 1 
 1794          if (m_lib.is_loaded())
 
 1796            if (
auto fn = m_lib.get(
 
 1797                    webview2_symbols::CreateCoreWebView2EnvironmentWithOptions))
 
 1799              return fn(browser_dir, user_data_dir, env_options, created_handler);
 
 1802#if WEBVIEW_MSWEBVIEW2_BUILTIN_IMPL == 1 
 1803          return create_environment_with_options_impl(browser_dir, user_data_dir,
 
 1804                                                      env_options, created_handler);
 
 1809          return ::CreateCoreWebView2EnvironmentWithOptions(browser_dir, user_data_dir,
 
 1810                                                            env_options, created_handler);
 
 1815        get_available_browser_version_string(PCWSTR browser_dir, LPWSTR* version)
 const 
 1817#if WEBVIEW_MSWEBVIEW2_EXPLICIT_LINK == 1 
 1818          if (m_lib.is_loaded())
 
 1820            if (
auto fn = m_lib.get(
 
 1821                    webview2_symbols::GetAvailableCoreWebView2BrowserVersionString))
 
 1823              return fn(browser_dir, version);
 
 1826#if WEBVIEW_MSWEBVIEW2_BUILTIN_IMPL == 1 
 1827          return get_available_browser_version_string_impl(browser_dir, version);
 
 1832          return ::GetAvailableCoreWebView2BrowserVersionString(browser_dir, version);
 
 1837#if WEBVIEW_MSWEBVIEW2_BUILTIN_IMPL == 1 
 1838        struct client_info_t
 
 1841          std::wstring dll_path;
 
 1842          std::wstring version;
 
 1843          webview2_runtime_type runtime_type;
 
 1846        HRESULT create_environment_with_options_impl(
 
 1847            PCWSTR browser_dir, PCWSTR user_data_dir,
 
 1848            ICoreWebView2EnvironmentOptions* env_options,
 
 1849            ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler* created_handler)
 
 1852          auto found_client = find_available_client(browser_dir);
 
 1853          if (!found_client.found)
 
 1857          auto client_dll = native_library(found_client.dll_path.c_str());
 
 1858          if (
auto fn = client_dll.get(
 
 1859                  webview2_symbols::CreateWebViewEnvironmentWithOptionsInternal))
 
 1861            return fn(
true, found_client.runtime_type, user_data_dir, env_options,
 
 1864          if (
auto fn = client_dll.get(webview2_symbols::DllCanUnloadNow))
 
 1868              client_dll.detach();
 
 1871          return ERROR_SUCCESS;
 
 1875        get_available_browser_version_string_impl(PCWSTR browser_dir, LPWSTR* version)
 const 
 1881          auto found_client = find_available_client(browser_dir);
 
 1882          if (!found_client.found)
 
 1886          auto info_length_bytes =
 
 1887              found_client.version.size() * 
sizeof(found_client.version[0]);
 
 1888          auto info = 
static_cast<LPWSTR
>(CoTaskMemAlloc(info_length_bytes));
 
 1893          CopyMemory(info, found_client.version.c_str(), info_length_bytes);
 
 1898        client_info_t find_available_client(PCWSTR browser_dir)
 const 
 1902            return find_embedded_client(api_version, browser_dir);
 
 1905              find_installed_client(api_version, 
true, default_release_channel_guid);
 
 1906          if (!found_client.found)
 
 1909                find_installed_client(api_version, 
false, default_release_channel_guid);
 
 1911          return found_client;
 
 1914        std::wstring make_client_dll_path(
const std::wstring& dir)
 const 
 1916          auto dll_path = dir;
 
 1917          if (!dll_path.empty())
 
 1919            auto last_char = dir[dir.size() - 1];
 
 1920            if (last_char != L
'\\' && last_char != L
'/')
 
 1925          dll_path += L
"EBWebView\\";
 
 1926#if defined(_M_X64) || defined(__x86_64__) 
 1928#elif defined(_M_IX86) || defined(__i386__) 
 1930#elif defined(_M_ARM64) || defined(__aarch64__) 
 1931          dll_path += L
"arm64";
 
 1933#error WebView2 integration for this platform is not yet supported. 
 1935          dll_path += L
"\\EmbeddedBrowserWebView.dll";
 
 1939        client_info_t find_installed_client(
unsigned int min_api_version, 
bool system,
 
 1940                                            const std::wstring& release_channel)
 const 
 1942          std::wstring sub_key = client_state_reg_sub_key;
 
 1943          sub_key += release_channel;
 
 1944          auto root_key = system ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
 
 1945          reg_key key(root_key, sub_key, 0, KEY_READ | KEY_WOW64_32KEY);
 
 1950          auto ebwebview_value = key.query_string(L
"EBWebView");
 
 1952          auto client_version_string = get_last_native_path_component(ebwebview_value);
 
 1953          auto client_version = parse_version(client_version_string);
 
 1954          if (client_version[2] < min_api_version)
 
 1960          auto client_dll_path = make_client_dll_path(ebwebview_value);
 
 1961          return { 
true, client_dll_path, client_version_string,
 
 1962                 webview2_runtime_type::installed };
 
 1965        client_info_t find_embedded_client(
unsigned int min_api_version,
 
 1966                                           const std::wstring& dir)
 const 
 1968          auto client_dll_path = make_client_dll_path(dir);
 
 1970          auto client_version_string = get_file_version_string(client_dll_path);
 
 1971          auto client_version = parse_version(client_version_string);
 
 1972          if (client_version[2] < min_api_version)
 
 1978          return { 
true, client_dll_path, client_version_string,
 
 1979                 webview2_runtime_type::embedded };
 
 1987        static constexpr unsigned int api_version = 1150;
 
 1989        static constexpr auto client_state_reg_sub_key =
 
 1990            L
"SOFTWARE\\Microsoft\\EdgeUpdate\\ClientState\\";
 
 1993        static constexpr auto stable_release_guid =
 
 1994            L
"{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}";
 
 1996        static constexpr auto default_release_channel_guid = stable_release_guid;
 
 1999#if WEBVIEW_MSWEBVIEW2_EXPLICIT_LINK == 1 
 2000        native_library m_lib{ L
"WebView2Loader.dll" };
 
 2006        static constexpr auto controller_completed =
 
 2007            cast_info_t<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>{
 
 2008              IID_ICoreWebView2CreateCoreWebView2ControllerCompletedHandler
 
 2011        static constexpr auto environment_completed =
 
 2012            cast_info_t<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>{
 
 2013              IID_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
 
 2016        static constexpr auto message_received =
 
 2017            cast_info_t<ICoreWebView2WebMessageReceivedEventHandler>{
 
 2018              IID_ICoreWebView2WebMessageReceivedEventHandler
 
 2021        static constexpr auto permission_requested =
 
 2022            cast_info_t<ICoreWebView2PermissionRequestedEventHandler>{
 
 2023              IID_ICoreWebView2PermissionRequestedEventHandler
 
 2028    class webview2_com_handler
 
 2029        : 
public ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler,
 
 2030          public ICoreWebView2CreateCoreWebView2ControllerCompletedHandler,
 
 2031          public ICoreWebView2WebMessageReceivedEventHandler,
 
 2032          public ICoreWebView2PermissionRequestedEventHandler,
 
 2033          public ICoreWebView2NavigationCompletedEventHandler
 
 2035      using webview2_com_handler_cb_t =
 
 2036          std::function<void(ICoreWebView2Controller*, ICoreWebView2* webview)>;
 
 2039      webview2_com_handler(HWND hwnd, msg_cb_t msgCb, webview2_com_handler_cb_t cb)
 
 2040          : m_window(hwnd), m_msgCb(msgCb), m_cb(cb)
 
 2044      virtual ~webview2_com_handler() = 
default;
 
 2045      webview2_com_handler(
const webview2_com_handler& other) = 
delete;
 
 2046      webview2_com_handler& operator=(
const webview2_com_handler& other) = 
delete;
 
 2047      webview2_com_handler(webview2_com_handler&& other) = 
delete;
 
 2048      webview2_com_handler& operator=(webview2_com_handler&& other) = 
delete;
 
 2050      ULONG STDMETHODCALLTYPE AddRef()
 
 2052        return ++m_ref_count;
 
 2054      ULONG STDMETHODCALLTYPE Release()
 
 2056        if (m_ref_count > 1)
 
 2058          return --m_ref_count;
 
 2063      HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppv)
 
 2065        using namespace mswebview2::cast_info;
 
 2082        if (cast_if_equal_iid(riid, controller_completed, ppv) ||
 
 2083            cast_if_equal_iid(riid, environment_completed, ppv) ||
 
 2084            cast_if_equal_iid(riid, message_received, ppv) ||
 
 2085            cast_if_equal_iid(riid, permission_requested, ppv))
 
 2090        return E_NOINTERFACE;
 
 2092      HRESULT STDMETHODCALLTYPE Invoke(HRESULT res, ICoreWebView2Environment* env)
 
 2096          res = env->CreateCoreWebView2Controller(m_window, 
this);
 
 2102        try_create_environment();
 
 2105      HRESULT STDMETHODCALLTYPE Invoke(HRESULT res, ICoreWebView2Controller* controller)
 
 2114            case HRESULT_FROM_WIN32(ERROR_INVALID_STATE):
 
 2118          try_create_environment();
 
 2122        ICoreWebView2* webview;
 
 2123        ::EventRegistrationToken token;
 
 2124        controller->get_CoreWebView2(&webview);
 
 2125        webview->add_WebMessageReceived(
this, &token);
 
 2126        webview->add_PermissionRequested(
this, &token);
 
 2127        webview->add_NavigationCompleted(
this, &token);
 
 2129        m_cb(controller, webview);
 
 2132      HRESULT STDMETHODCALLTYPE Invoke(ICoreWebView2* sender,
 
 2133                                       ICoreWebView2WebMessageReceivedEventArgs* args)
 
 2136        args->TryGetWebMessageAsString(&message);
 
 2137        m_msgCb(narrow_string(message));
 
 2138        sender->PostWebMessageAsString(message);
 
 2140        CoTaskMemFree(message);
 
 2143      HRESULT STDMETHODCALLTYPE Invoke(ICoreWebView2* sender,
 
 2144                                       ICoreWebView2PermissionRequestedEventArgs* args)
 
 2146        COREWEBVIEW2_PERMISSION_KIND kind;
 
 2147        args->get_PermissionKind(&kind);
 
 2148        if (kind == COREWEBVIEW2_PERMISSION_KIND_CLIPBOARD_READ)
 
 2150          args->put_State(COREWEBVIEW2_PERMISSION_STATE_ALLOW);
 
 2154      HRESULT STDMETHODCALLTYPE Invoke(ICoreWebView2* sender,
 
 2155                                       ICoreWebView2NavigationCompletedEventArgs* args)
 
 2157        PWSTR uri = 
nullptr;
 
 2158        auto hr = sender->get_Source(&uri);
 
 2161          auto curi = std::wstring_convert<std::codecvt_utf8<wchar_t> >().to_bytes(uri);
 
 2162          if (navigateCallback)
 
 2163            navigateCallback(curi, navigateCallbackArg);
 
 2173      template <
typename T>
 
 2174      T* cast_if_equal_iid(REFIID riid, 
const cast_info_t<T>& info,
 
 2175                           LPVOID* ppv = 
nullptr) noexcept
 
 2178        if (IsEqualIID(riid, info.iid))
 
 2180          ptr = 
static_cast<T*
>(
this);
 
 2192      void set_attempt_handler(std::function<HRESULT()> attempt_handler) 
noexcept 
 2194        m_attempt_handler = attempt_handler;
 
 2200      void try_create_environment() noexcept
 
 2207        if (m_attempts < m_max_attempts)
 
 2210          auto res = m_attempt_handler();
 
 2217          if (res == HRESULT_FROM_WIN32(ERROR_INVALID_STATE))
 
 2221          try_create_environment();
 
 2225        m_cb(
nullptr, 
nullptr);
 
 2228      void STDMETHODCALLTYPE add_navigate_listener(
 
 2229          std::function<
void(
const std::string&, 
void*)> callback, 
void* arg)
 
 2231        navigateCallback = std::move(callback);
 
 2232        navigateCallbackArg = arg;
 
 2238      webview2_com_handler_cb_t m_cb;
 
 2239      std::atomic<ULONG> m_ref_count{ 1 };
 
 2240      std::function<HRESULT()> m_attempt_handler;
 
 2241      unsigned int m_max_attempts = 5;
 
 2242      unsigned int m_attempts = 0;
 
 2243      void* navigateCallbackArg = 
nullptr;
 
 2244      std::function<void(
const std::string&, 
void*)> navigateCallback = 0;
 
 2247    class win32_edge_engine
 
 2250      win32_edge_engine(
bool debug, 
void* window)
 
 2252        if (!is_webview2_available())
 
 2256        if (!m_com_init.is_initialized())
 
 2260        enable_dpi_awareness();
 
 2261        if (window == 
nullptr)
 
 2263          HINSTANCE hInstance = GetModuleHandle(
nullptr);
 
 2264          HICON icon = (HICON)LoadImage(hInstance, IDI_APPLICATION, IMAGE_ICON,
 
 2265                                        GetSystemMetrics(SM_CXICON),
 
 2266                                        GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
 
 2269          ZeroMemory(&wc, 
sizeof(WNDCLASSEX));
 
 2270          wc.cbSize = 
sizeof(WNDCLASSEX);
 
 2271          wc.hInstance = hInstance;
 
 2272          wc.lpszClassName = L
"webview";
 
 2275              (WNDPROC)(+[](HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) -> LRESULT
 
 2278                              (win32_edge_engine*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
 
 2285                              DestroyWindow(hwnd);
 
 2290                            case WM_GETMINMAXINFO:
 
 2292                              auto lpmmi = (LPMINMAXINFO)lp;
 
 2297                              if (w->m_maxsz.x > 0 && w->m_maxsz.y > 0)
 
 2299                                lpmmi->ptMaxSize = w->m_maxsz;
 
 2300                                lpmmi->ptMaxTrackSize = w->m_maxsz;
 
 2302                              if (w->m_minsz.x > 0 && w->m_minsz.y > 0)
 
 2304                                lpmmi->ptMinTrackSize = w->m_minsz;
 
 2309                              return DefWindowProcW(hwnd, msg, wp, lp);
 
 2313          RegisterClassExW(&wc);
 
 2314          m_window = CreateWindowW(L
"webview", L
"", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
 
 2315                                   CW_USEDEFAULT, 640, 480, 
nullptr, 
nullptr, hInstance,
 
 2317          if (m_window == 
nullptr)
 
 2321          SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR)
this);
 
 2325          m_window = *(
static_cast<HWND*
>(window));
 
 2328        ShowWindow(m_window, SW_SHOW);
 
 2329        UpdateWindow(m_window);
 
 2332        auto cb = std::bind(&win32_edge_engine::on_message, 
this, std::placeholders::_1);
 
 2334        embed(m_window, debug, cb);
 
 2336        m_controller->MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC);
 
 2339      virtual ~win32_edge_engine()
 
 2343          m_com_handler->Release();
 
 2344          m_com_handler = 
nullptr;
 
 2348          m_webview->Release();
 
 2349          m_webview = 
nullptr;
 
 2353          m_controller->Release();
 
 2354          m_controller = 
nullptr;
 
 2358      win32_edge_engine(
const win32_edge_engine& other) = 
delete;
 
 2359      win32_edge_engine& operator=(
const win32_edge_engine& other) = 
delete;
 
 2360      win32_edge_engine(win32_edge_engine&& other) = 
delete;
 
 2361      win32_edge_engine& operator=(win32_edge_engine&& other) = 
delete;
 
 2367        while ((res = GetMessage(&msg, 
nullptr, 0, 0)) != -1)
 
 2371            TranslateMessage(&msg);
 
 2372            DispatchMessage(&msg);
 
 2375          if (msg.message == WM_APP)
 
 2377            auto f = (dispatch_fn_t*)(msg.lParam);
 
 2381          else if (msg.message == WM_QUIT)
 
 2389        return (
void*)m_window;
 
 2395      void dispatch(dispatch_fn_t f)
 
 2397        PostThreadMessage(m_main_thread, WM_APP, 0, (LPARAM) 
new dispatch_fn_t(f));
 
 2400      void set_title(
const std::string& title)
 
 2402        SetWindowTextW(m_window, widen_string(title).c_str());
 
 2405      void set_size(
int width, 
int height, 
int hints)
 
 2407        auto style = GetWindowLong(m_window, GWL_STYLE);
 
 2408        if (hints == WEBVIEW_HINT_FIXED)
 
 2410          style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
 
 2414          style |= (WS_THICKFRAME | WS_MAXIMIZEBOX);
 
 2416        SetWindowLong(m_window, GWL_STYLE, style);
 
 2418        if (hints == WEBVIEW_HINT_MAX)
 
 2423        else if (hints == WEBVIEW_HINT_MIN)
 
 2434          AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, 0);
 
 2435          SetWindowPos(m_window, 
nullptr, r.left, r.top, r.right - r.left,
 
 2437                       SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE | SWP_FRAMECHANGED);
 
 2442      void navigate(
const std::string& url)
 
 2444        auto wurl = widen_string(url);
 
 2445        m_webview->Navigate(wurl.c_str());
 
 2448      void init(
const std::string& js)
 
 2450        auto wjs = widen_string(js);
 
 2451        m_webview->AddScriptToExecuteOnDocumentCreated(wjs.c_str(), 
nullptr);
 
 2454      void eval(
const std::string& js)
 
 2456        auto wjs = widen_string(js);
 
 2457        m_webview->ExecuteScript(wjs.c_str(), 
nullptr);
 
 2460      void add_navigate_listener(std::function<
void(
const std::string&, 
void*)> callback,
 
 2463        m_com_handler->add_navigate_listener(callback, arg);
 
 2466      void add_scheme_handler(
const std::string& scheme,
 
 2467                              std::function<
void(
const std::string&, 
void*)> callback,
 
 2473      void set_html(
const std::string& html)
 
 2475        m_webview->NavigateToString(widen_string(html).c_str());
 
 2479      bool embed(HWND wnd, 
bool debug, msg_cb_t cb)
 
 2481        std::atomic_flag flag = ATOMIC_FLAG_INIT;
 
 2482        flag.test_and_set();
 
 2484        wchar_t currentExePath[MAX_PATH];
 
 2485        GetModuleFileNameW(
nullptr, currentExePath, MAX_PATH);
 
 2486        wchar_t* currentExeName = PathFindFileNameW(currentExePath);
 
 2488        wchar_t dataPath[MAX_PATH];
 
 2489        if (!SUCCEEDED(SHGetFolderPathW(
nullptr, CSIDL_APPDATA, 
nullptr, 0, dataPath)))
 
 2493        wchar_t userDataFolder[MAX_PATH];
 
 2494        PathCombineW(userDataFolder, dataPath, currentExeName);
 
 2496        m_com_handler = 
new webview2_com_handler(
 
 2498            [&](ICoreWebView2Controller* controller, ICoreWebView2* webview)
 
 2500              if (!controller || !webview)
 
 2505              controller->AddRef();
 
 2507              m_controller = controller;
 
 2508              m_webview = webview;
 
 2512        m_com_handler->set_attempt_handler(
 
 2515              return m_webview2_loader.create_environment_with_options(
 
 2516                  nullptr, userDataFolder, 
nullptr, m_com_handler);
 
 2518        m_com_handler->try_create_environment();
 
 2521        while (flag.test_and_set() && GetMessage(&msg, 
nullptr, 0, 0))
 
 2523          TranslateMessage(&msg);
 
 2524          DispatchMessage(&msg);
 
 2526        if (!m_controller || !m_webview)
 
 2530        ICoreWebView2Settings* settings = 
nullptr;
 
 2531        auto res = m_webview->get_Settings(&settings);
 
 2536        res = settings->put_AreDevToolsEnabled(debug ? TRUE : FALSE);
 
 2541        init(
"window.external={invoke:s=>window.chrome.webview.postMessage(s)}");
 
 2545      void resize(HWND wnd)
 
 2547        if (m_controller == 
nullptr)
 
 2552        GetClientRect(wnd, &bounds);
 
 2553        m_controller->put_Bounds(bounds);
 
 2556      bool is_webview2_available() const noexcept
 
 2558        LPWSTR version_info = 
nullptr;
 
 2560            m_webview2_loader.get_available_browser_version_string(
nullptr, &version_info);
 
 2563        auto ok = SUCCEEDED(res) && version_info;
 
 2566          CoTaskMemFree(version_info);
 
 2571      virtual void on_message(
const std::string& msg) = 0;
 
 2577      com_init_wrapper m_com_init{ COINIT_APARTMENTTHREADED };
 
 2578      HWND m_window = 
nullptr;
 
 2579      POINT m_minsz = POINT{ 0, 0 };
 
 2580      POINT m_maxsz = POINT{ 0, 0 };
 
 2581      DWORD m_main_thread = GetCurrentThreadId();
 
 2582      ICoreWebView2* m_webview = 
nullptr;
 
 2583      ICoreWebView2Controller* m_controller = 
nullptr;
 
 2584      webview2_com_handler* m_com_handler = 
nullptr;
 
 2585      mswebview2::loader m_webview2_loader;
 
 2590  using browser_engine = detail::win32_edge_engine;
 
 2599  class webview : 
public browser_engine
 
 2602    webview(
bool debug = 
false, 
void* wnd = 
nullptr) : browser_engine(debug, wnd)
 
 2606    void navigate(
const std::string& url)
 
 2610        browser_engine::navigate(
"about:blank");
 
 2613      browser_engine::navigate(url);
 
 2616    using binding_t = std::function<void(std::string, std::string, 
void*)>;
 
 2620      binding_ctx_t(binding_t callback, 
void* arg) : callback(callback), arg(arg)
 
 2629    using sync_binding_t = std::function<std::string(std::string)>;
 
 2632    void bind(
const std::string& name, sync_binding_t fn)
 
 2634      auto wrapper = [
this, fn](
const std::string& seq, 
const std::string& req, 
void* )
 
 2635      { resolve(seq, 0, fn(req)); };
 
 2636      bind(name, wrapper, 
nullptr);
 
 2640    void bind(
const std::string& name, binding_t fn, 
void* arg)
 
 2642      if (bindings.count(name) > 0)
 
 2646      bindings.emplace(name, binding_ctx_t(fn, arg));
 
 2647      auto js = 
"(function() { var name = '" + name + 
"';" + R
""( 
 2648      var RPC = window._rpc = (window._rpc || {nextSeq: 1}); 
 2649      window[name] = function() { 
 2650        var seq = RPC.nextSeq++; 
 2651        var promise = new Promise(function(resolve, reject) { 
 2657        window.external.invoke(JSON.stringify({ 
 2660          params: Array.prototype.slice.call(arguments), 
 2669    void unbind(
const std::string& name)
 
 2671      auto found = bindings.find(name);
 
 2672      if (found != bindings.end())
 
 2674        auto js = 
"delete window['" + name + 
"'];";
 
 2677        bindings.erase(found);
 
 2681    void resolve(
const std::string& seq, 
int status, 
const std::string& result)
 
 2684          [seq, status, result, 
this]()
 
 2688              eval(
"window._rpc[" + seq + 
"].resolve(" + result +
 
 2689                   "); delete window._rpc[" + seq + 
"]");
 
 2693              eval(
"window._rpc[" + seq + 
"].reject(" + result +
 
 2694                   "); delete window._rpc[" + seq + 
"]");
 
 2700    void on_message(
const std::string& msg)
 override 
 2702      auto seq = detail::json_parse(msg, 
"id", 0);
 
 2703      auto name = detail::json_parse(msg, 
"method", 0);
 
 2704      auto args = detail::json_parse(msg, 
"params", 0);
 
 2705      auto found = bindings.find(name);
 
 2706      if (found == bindings.end())
 
 2710      const auto& context = found->second;
 
 2711      context.callback(seq, args, context.arg);
 
 2714    std::map<std::string, binding_ctx_t> bindings;
 
 2718WEBVIEW_API webview_t webview_create(
int debug, 
void* wnd)
 
 2720  auto w = 
new webview::webview(debug, wnd);
 
 2729WEBVIEW_API 
void webview_destroy(webview_t w)
 
 2731  delete static_cast<webview::webview*
>(w);
 
 2734WEBVIEW_API 
void webview_run(webview_t w)
 
 2736  static_cast<webview::webview*
>(w)->run();
 
 2739WEBVIEW_API 
void webview_terminate(webview_t w)
 
 2741  static_cast<webview::webview*
>(w)->terminate();
 
 2744WEBVIEW_API 
void webview_dispatch(webview_t w, 
void (*fn)(webview_t, 
void*), 
void* arg)
 
 2746  static_cast<webview::webview*
>(w)->dispatch([=]() { fn(w, arg); });
 
 2749WEBVIEW_API 
void* webview_get_window(webview_t w)
 
 2751  return static_cast<webview::webview*
>(w)->window();
 
 2754WEBVIEW_API 
void webview_set_title(webview_t w, 
const char* title)
 
 2756  static_cast<webview::webview*
>(w)->set_title(title);
 
 2759WEBVIEW_API 
void webview_set_size(webview_t w, 
int width, 
int height, 
int hints)
 
 2761  static_cast<webview::webview*
>(w)->set_size(width, height, hints);
 
 2764WEBVIEW_API 
void webview_navigate(webview_t w, 
const char* url)
 
 2766  static_cast<webview::webview*
>(w)->navigate(url);
 
 2769WEBVIEW_API 
void webview_set_html(webview_t w, 
const char* html)
 
 2771  static_cast<webview::webview*
>(w)->set_html(html);
 
 2774WEBVIEW_API 
void webview_init(webview_t w, 
const char* js)
 
 2776  static_cast<webview::webview*
>(w)->init(js);
 
 2779WEBVIEW_API 
void webview_eval(webview_t w, 
const char* js)
 
 2781  static_cast<webview::webview*
>(w)->eval(js);
 
 2784WEBVIEW_API 
void webview_bind(webview_t w, 
const char* name,
 
 2785                              void (*fn)(
const char* seq, 
const char* req, 
void* arg), 
void* arg)
 
 2787  static_cast<webview::webview*
>(w)->bind(
 
 2789      [=](
const std::string& seq, 
const std::string& req, 
void* arg)
 
 2790      { fn(seq.c_str(), req.c_str(), arg); },
 
 2794WEBVIEW_API 
void webview_unbind(webview_t w, 
const char* name)
 
 2796  static_cast<webview::webview*
>(w)->unbind(name);
 
 2799WEBVIEW_API 
void webview_return(webview_t w, 
const char* seq, 
int status, 
const char* result)
 
 2801  static_cast<webview::webview*
>(w)->resolve(seq, status, result);
 
 2806  return &webview::detail::library_version_info;