diff ios/dw.m @ 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 7d12fd73ef54
children 81f9399b11c8
line wrap: on
line diff
--- 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: