changeset 2975:ae4d6856b983

iOS: Support for dw_html_javascript_add() and DW_SIGNAL_HTML_MESSAGE. Add DW_FEATURE_HTML_MESSAGE feature test and display in dwtest(oo). Mac: Make sure code is in WK_API_ENABLED tests so old MacOS versions are still supported.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Fri, 24 Mar 2023 17:15:59 +0000
parents fffb4904c90b
children b40adda4a129
files dw.h dwtest.c dwtestoo.cpp ios/dw.m mac/dw.m
diffstat 5 files changed, 68 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/dw.h	Fri Mar 24 11:39:24 2023 +0000
+++ b/dw.h	Fri Mar 24 17:15:59 2023 +0000
@@ -1847,6 +1847,7 @@
     DW_FEATURE_TREE,                    /* Supports the Tree Widget */
     DW_FEATURE_WINDOW_PLACEMENT,        /* Supports arbitrary window placement */
     DW_FEATURE_CONTAINER_MODE,          /* Supports alternate container view modes */
+    DW_FEATURE_HTML_MESSAGE,            /* Supports the DW_SIGNAL_HTML_MESSAGE callback */
     DW_FEATURE_MAX
 } DWFEATURE;
 
--- a/dwtest.c	Fri Mar 24 11:39:24 2023 +0000
+++ b/dwtest.c	Fri Mar 24 17:15:59 2023 +0000
@@ -2169,6 +2169,7 @@
     "Supports the Tree Widget",
     "Supports arbitrary window placement",
     "Supports alternate container view modes",
+    "Supports the DW_SIGNAL_HTML_MESSAGE callback",
     NULL };
 
 /*
--- a/dwtestoo.cpp	Fri Mar 24 11:39:24 2023 +0000
+++ b/dwtestoo.cpp	Fri Mar 24 17:15:59 2023 +0000
@@ -1964,7 +1964,8 @@
     "Supports icons in the taskbar or similar system widget",
     "Supports the Tree Widget",
     "Supports arbitrary window placement",
-    "Supports alternate container view modes"
+    "Supports alternate container view modes",
+    "Supports the DW_SIGNAL_HTML_MESSAGE callback"
 };
 
 // Let's demonstrate the functionality of this library. :)
--- a/ios/dw.m	Fri Mar 24 11:39:24 2023 +0000
+++ b/ios/dw.m	Fri Mar 24 17:15:59 2023 +0000
@@ -354,9 +354,7 @@
 } DWSignalList;
 
 /* List of signals */
-#define SIGNALMAX 19
-
-static DWSignalList DWSignalTranslate[SIGNALMAX] = {
+static DWSignalList DWSignalTranslate[] = {
     { _DW_EVENT_CONFIGURE,       DW_SIGNAL_CONFIGURE },
     { _DW_EVENT_KEY_PRESS,       DW_SIGNAL_KEY_PRESS },
     { _DW_EVENT_BUTTON_PRESS,    DW_SIGNAL_BUTTON_PRESS },
@@ -375,7 +373,8 @@
     { _DW_EVENT_TREE_EXPAND,     DW_SIGNAL_TREE_EXPAND },
     { _DW_EVENT_COLUMN_CLICK,    DW_SIGNAL_COLUMN_CLICK },
     { _DW_EVENT_HTML_RESULT,     DW_SIGNAL_HTML_RESULT },
-    { _DW_EVENT_HTML_CHANGED,    DW_SIGNAL_HTML_CHANGED }
+    { _DW_EVENT_HTML_CHANGED,    DW_SIGNAL_HTML_CHANGED },
+    { _DW_EVENT_HTML_MESSAGE,    DW_SIGNAL_HTML_MESSAGE }
 };
 
 int _dw_event_handler1(id object, id event, int message)
@@ -619,7 +618,8 @@
                 void **params = (void **)event;
                 NSString *result = params[0];
 
-                return htmlresultfunc(handler->window, [result length] ? DW_ERROR_NONE : DW_ERROR_UNKNOWN, [result length] ? (char *)[result UTF8String] : NULL, params[1], handler->data);
+                return htmlresultfunc(handler->window, [result length] ? DW_ERROR_NONE : DW_ERROR_UNKNOWN, [result length] ?
+                                      (char *)[result UTF8String] : NULL, params[1], handler->data);
             }
             /* HTML changed event */
             case _DW_EVENT_HTML_CHANGED:
@@ -630,6 +630,15 @@
 
                 return htmlchangedfunc(handler->window, DW_POINTER_TO_INT(params[0]), (char *)[uri UTF8String], handler->data);
             }
+            /* HTML message event */
+            case _DW_EVENT_HTML_MESSAGE:
+            {
+                int (* API htmlmessagefunc)(HWND, char *, char *, void *) = handler->signalfunction;
+                WKScriptMessage *message = (WKScriptMessage *)event;
+
+                return htmlmessagefunc(handler->window, (char *)[[message name] UTF8String], [[message body] isKindOfClass:[NSString class]] ?
+                                       (char *)[[message body] UTF8String] : NULL, handler->data);
+                }
         }
     }
     return -1;
@@ -1512,7 +1521,7 @@
     return NO;
 }
 
-@interface DWWebView : WKWebView <WKNavigationDelegate>
+@interface DWWebView : WKWebView <WKNavigationDelegate, WKScriptMessageHandler>
 {
     void *userdata;
 }
@@ -1522,6 +1531,7 @@
 -(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;
 -(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation;
 -(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation;
+-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
 @end
 
 @implementation DWWebView : WKWebView
@@ -1547,6 +1557,10 @@
     void *params[2] = { DW_INT_TO_POINTER(DW_HTML_CHANGE_REDIRECT), [[self URL] absoluteString] };
     _dw_event_handler(self, (id)params, _DW_EVENT_HTML_CHANGED);
 }
+-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
+{
+    _dw_event_handler(self, (id)message, _DW_EVENT_HTML_MESSAGE);
+}
 -(void)dealloc { UserData *root = userdata; _dw_remove_userdata(&root, NULL, TRUE); dw_signal_disconnect_by_window(self); [super dealloc]; }
 @end
 
@@ -3821,7 +3835,7 @@
 {
     int z;
 
-    for(z=0;z<SIGNALMAX;z++)
+    for(z=0;z<(_DW_EVENT_MAX-1);z++)
     {
         if(strcasecmp(signame, DWSignalTranslate[z].name) == 0)
             return DWSignalTranslate[z].message;
@@ -8756,6 +8770,39 @@
 }
 
 /*
+ * Install a javascript function with name that can call native code.
+ * Parameters:
+ *       handle: Handle to the HTML window.
+ *       name: Javascript function name.
+ * Notes: A DW_SIGNAL_HTML_MESSAGE event will be raised with scriptdata.
+ * Returns:
+ *       DW_ERROR_NONE (0) on success.
+ */
+DW_FUNCTION_DEFINITION(dw_html_javascript_add, int, HWND handle, const char *name)
+DW_FUNCTION_ADD_PARAM2(handle, name)
+DW_FUNCTION_RETURN(dw_html_javascript_add, int)
+DW_FUNCTION_RESTORE_PARAM2(handle, HWND, name, const char *)
+{
+    DWWebView *html = handle;
+    WKUserContentController *controller = [[html configuration] userContentController];
+    int retval = DW_ERROR_UNKNOWN;
+
+    if(controller && name)
+    {
+        DW_LOCAL_POOL_IN;
+        /* Script to inject that will call the handler we are adding */
+        NSString *script = [NSString stringWithFormat:@"function %s(body) {window.webkit.messageHandlers.%s.postMessage(body);}",
+                            name, name];
+        [controller addScriptMessageHandler:handle name:[NSString stringWithUTF8String:name]];
+        [controller addUserScript:[[WKUserScript alloc] initWithSource:script
+                injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]];
+        DW_LOCAL_POOL_OUT;
+        retval = DW_ERROR_NONE;
+    }
+    DW_FUNCTION_RETURN_THIS(retval);
+}
+
+/*
  * Create a new HTML window (widget) to be packed.
  * Not available under OS/2, eCS
  * Parameters:
@@ -12210,6 +12257,7 @@
         case DW_FEATURE_MLE_AUTO_COMPLETE:
         case DW_FEATURE_HTML:
         case DW_FEATURE_HTML_RESULT:
+        case DW_FEATURE_HTML_MESSAGE:
         case DW_FEATURE_CONTAINER_STRIPE:
         case DW_FEATURE_MLE_WORD_WRAP:
         case DW_FEATURE_UTF8_UNICODE:
@@ -12260,6 +12308,7 @@
         case DW_FEATURE_MLE_AUTO_COMPLETE:
         case DW_FEATURE_HTML:
         case DW_FEATURE_HTML_RESULT:
+        case DW_FEATURE_HTML_MESSAGE:
         case DW_FEATURE_CONTAINER_STRIPE:
         case DW_FEATURE_MLE_WORD_WRAP:
         case DW_FEATURE_UTF8_UNICODE:
--- a/mac/dw.m	Fri Mar 24 11:39:24 2023 +0000
+++ b/mac/dw.m	Fri Mar 24 17:15:59 2023 +0000
@@ -888,6 +888,7 @@
 
                 return htmlchangedfunc(handler->window, DW_POINTER_TO_INT(params[0]), (char *)[uri UTF8String], handler->data);
             }
+#if WK_API_ENABLED
             /* HTML message event */
             case _DW_EVENT_HTML_MESSAGE:
             {
@@ -897,6 +898,7 @@
                 return htmlmessagefunc(handler->window, (char *)[[message name] UTF8String], [[message body] isKindOfClass:[NSString class]] ?
                                        (char *)[[message body] UTF8String] : NULL, handler->data);
             }
+#endif
         }
     }
     return -1;
@@ -13467,6 +13469,9 @@
 #endif
         case DW_FEATURE_HTML:
         case DW_FEATURE_HTML_RESULT:
+#if WK_API_ENABLED
+        case DW_FEATURE_HTML_MESSAGE:
+#endif
         case DW_FEATURE_CONTAINER_STRIPE:
         case DW_FEATURE_MLE_WORD_WRAP:
         case DW_FEATURE_UTF8_UNICODE:
@@ -13548,6 +13553,9 @@
 #endif
         case DW_FEATURE_HTML:
         case DW_FEATURE_HTML_RESULT:
+#if WK_API_ENABLED
+        case DW_FEATURE_HTML_MESSAGE:
+#endif
         case DW_FEATURE_CONTAINER_STRIPE:
         case DW_FEATURE_MLE_WORD_WRAP:
         case DW_FEATURE_UTF8_UNICODE: