comparison mac/dw.m @ 2974:fffb4904c90b

Mac: Initial support for dw_html_javascript_add() and DW_SIGNAL_HTML_MESSAGE for callbacks into native code. Code for iOS next... Then GTK3/4, Windows and Android in that order. Also implemented simple rawhtml tests in the test programs. C++: Added HTML class support for the message callbacks.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Fri, 24 Mar 2023 11:39:24 +0000
parents 7d12fd73ef54
children ae4d6856b983
comparison
equal deleted inserted replaced
2973:ac880987a2c4 2974:fffb4904c90b
590 char name[30]; 590 char name[30];
591 591
592 } DWSignalList; 592 } DWSignalList;
593 593
594 /* List of signals */ 594 /* List of signals */
595 #define SIGNALMAX 19 595 static DWSignalList DWSignalTranslate[] = {
596
597 static DWSignalList DWSignalTranslate[SIGNALMAX] = {
598 { _DW_EVENT_CONFIGURE, DW_SIGNAL_CONFIGURE }, 596 { _DW_EVENT_CONFIGURE, DW_SIGNAL_CONFIGURE },
599 { _DW_EVENT_KEY_PRESS, DW_SIGNAL_KEY_PRESS }, 597 { _DW_EVENT_KEY_PRESS, DW_SIGNAL_KEY_PRESS },
600 { _DW_EVENT_BUTTON_PRESS, DW_SIGNAL_BUTTON_PRESS }, 598 { _DW_EVENT_BUTTON_PRESS, DW_SIGNAL_BUTTON_PRESS },
601 { _DW_EVENT_BUTTON_RELEASE, DW_SIGNAL_BUTTON_RELEASE }, 599 { _DW_EVENT_BUTTON_RELEASE, DW_SIGNAL_BUTTON_RELEASE },
602 { _DW_EVENT_MOTION_NOTIFY, DW_SIGNAL_MOTION_NOTIFY }, 600 { _DW_EVENT_MOTION_NOTIFY, DW_SIGNAL_MOTION_NOTIFY },
611 { _DW_EVENT_VALUE_CHANGED, DW_SIGNAL_VALUE_CHANGED }, 609 { _DW_EVENT_VALUE_CHANGED, DW_SIGNAL_VALUE_CHANGED },
612 { _DW_EVENT_SWITCH_PAGE, DW_SIGNAL_SWITCH_PAGE }, 610 { _DW_EVENT_SWITCH_PAGE, DW_SIGNAL_SWITCH_PAGE },
613 { _DW_EVENT_TREE_EXPAND, DW_SIGNAL_TREE_EXPAND }, 611 { _DW_EVENT_TREE_EXPAND, DW_SIGNAL_TREE_EXPAND },
614 { _DW_EVENT_COLUMN_CLICK, DW_SIGNAL_COLUMN_CLICK }, 612 { _DW_EVENT_COLUMN_CLICK, DW_SIGNAL_COLUMN_CLICK },
615 { _DW_EVENT_HTML_RESULT, DW_SIGNAL_HTML_RESULT }, 613 { _DW_EVENT_HTML_RESULT, DW_SIGNAL_HTML_RESULT },
616 { _DW_EVENT_HTML_CHANGED, DW_SIGNAL_HTML_CHANGED } 614 { _DW_EVENT_HTML_CHANGED, DW_SIGNAL_HTML_CHANGED },
615 { _DW_EVENT_HTML_MESSAGE, DW_SIGNAL_HTML_MESSAGE }
617 }; 616 };
618 617
619 int _dw_event_handler1(id object, NSEvent *event, int message) 618 int _dw_event_handler1(id object, NSEvent *event, int message)
620 { 619 {
621 DWSignalHandler *handler = _dw_get_handler(object, message); 620 DWSignalHandler *handler = _dw_get_handler(object, message);
875 { 874 {
876 int (* API htmlresultfunc)(HWND, int, char *, void *, void *) = handler->signalfunction; 875 int (* API htmlresultfunc)(HWND, int, char *, void *, void *) = handler->signalfunction;
877 void **params = (void **)event; 876 void **params = (void **)event;
878 NSString *result = params[0]; 877 NSString *result = params[0];
879 878
880 return htmlresultfunc(handler->window, [result length] ? DW_ERROR_NONE : DW_ERROR_UNKNOWN, [result length] ? (char *)[result UTF8String] : NULL, params[1], handler->data); 879 return htmlresultfunc(handler->window, [result length] ? DW_ERROR_NONE : DW_ERROR_UNKNOWN, [result length] ?
880 (char *)[result UTF8String] : NULL, params[1], handler->data);
881 } 881 }
882 /* HTML changed event */ 882 /* HTML changed event */
883 case _DW_EVENT_HTML_CHANGED: 883 case _DW_EVENT_HTML_CHANGED:
884 { 884 {
885 int (* API htmlchangedfunc)(HWND, int, char *, void *) = handler->signalfunction; 885 int (* API htmlchangedfunc)(HWND, int, char *, void *) = handler->signalfunction;
886 void **params = (void **)event; 886 void **params = (void **)event;
887 NSString *uri = params[1]; 887 NSString *uri = params[1];
888 888
889 return htmlchangedfunc(handler->window, DW_POINTER_TO_INT(params[0]), (char *)[uri UTF8String], handler->data); 889 return htmlchangedfunc(handler->window, DW_POINTER_TO_INT(params[0]), (char *)[uri UTF8String], handler->data);
890 }
891 /* HTML message event */
892 case _DW_EVENT_HTML_MESSAGE:
893 {
894 int (* API htmlmessagefunc)(HWND, char *, char *, void *) = handler->signalfunction;
895 WKScriptMessage *message = (WKScriptMessage *)event;
896
897 return htmlmessagefunc(handler->window, (char *)[[message name] UTF8String], [[message body] isKindOfClass:[NSString class]] ?
898 (char *)[[message body] UTF8String] : NULL, handler->data);
890 } 899 }
891 } 900 }
892 } 901 }
893 return -1; 902 return -1;
894 } 903 }
1445 /* Apparently the WKWebKit API is only enabled on intel 64bit... 1454 /* Apparently the WKWebKit API is only enabled on intel 64bit...
1446 * Causing build failures on 32bit builds, so this should allow 1455 * Causing build failures on 32bit builds, so this should allow
1447 * WKWebKit on intel 64 and the old WebKit on intel 32 bit and earlier. 1456 * WKWebKit on intel 64 and the old WebKit on intel 32 bit and earlier.
1448 */ 1457 */
1449 #if WK_API_ENABLED 1458 #if WK_API_ENABLED
1450 @interface DWWebView : WKWebView <WKNavigationDelegate> 1459 @interface DWWebView : WKWebView <WKNavigationDelegate, WKScriptMessageHandler>
1451 { 1460 {
1452 void *userdata; 1461 void *userdata;
1453 } 1462 }
1454 -(void *)userdata; 1463 -(void *)userdata;
1455 -(void)setUserdata:(void *)input; 1464 -(void)setUserdata:(void *)input;
1456 -(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation; 1465 -(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation;
1457 -(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation; 1466 -(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;
1458 -(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation; 1467 -(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation;
1459 -(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation; 1468 -(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation;
1469 -(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
1460 @end 1470 @end
1461 1471
1462 @implementation DWWebView : WKWebView 1472 @implementation DWWebView : WKWebView
1463 -(void *)userdata { return userdata; } 1473 -(void *)userdata { return userdata; }
1464 -(void)setUserdata:(void *)input { userdata = input; } 1474 -(void)setUserdata:(void *)input { userdata = input; }
1479 } 1489 }
1480 -(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation 1490 -(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation
1481 { 1491 {
1482 void *params[2] = { DW_INT_TO_POINTER(DW_HTML_CHANGE_REDIRECT), [[self URL] absoluteString] }; 1492 void *params[2] = { DW_INT_TO_POINTER(DW_HTML_CHANGE_REDIRECT), [[self URL] absoluteString] };
1483 _dw_event_handler(self, (NSEvent *)params, _DW_EVENT_HTML_CHANGED); 1493 _dw_event_handler(self, (NSEvent *)params, _DW_EVENT_HTML_CHANGED);
1494 }
1495 -(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
1496 {
1497 _dw_event_handler(self, (NSEvent *)message, _DW_EVENT_HTML_MESSAGE);
1484 } 1498 }
1485 -(void)dealloc { UserData *root = userdata; _dw_remove_userdata(&root, NULL, TRUE); dw_signal_disconnect_by_window(self); [super dealloc]; } 1499 -(void)dealloc { UserData *root = userdata; _dw_remove_userdata(&root, NULL, TRUE); dw_signal_disconnect_by_window(self); [super dealloc]; }
1486 @end 1500 @end
1487 #else 1501 #else
1488 @interface DWWebView : WebView 1502 @interface DWWebView : WebView
3693 /* Finds the message number for a given signal name */ 3707 /* Finds the message number for a given signal name */
3694 ULONG _dw_findsigmessage(const char *signame) 3708 ULONG _dw_findsigmessage(const char *signame)
3695 { 3709 {
3696 int z; 3710 int z;
3697 3711
3698 for(z=0;z<SIGNALMAX;z++) 3712 for(z=0;z<(_DW_EVENT_MAX-1);z++)
3699 { 3713 {
3700 if(strcasecmp(signame, DWSignalTranslate[z].name) == 0) 3714 if(strcasecmp(signame, DWSignalTranslate[z].name) == 0)
3701 return DWSignalTranslate[z].message; 3715 return DWSignalTranslate[z].message;
3702 } 3716 }
3703 return 0L; 3717 return 0L;
9466 DW_LOCAL_POOL_OUT; 9480 DW_LOCAL_POOL_OUT;
9467 return DW_ERROR_NONE; 9481 return DW_ERROR_NONE;
9468 } 9482 }
9469 9483
9470 /* 9484 /*
9485 * Install a javascript function with name that can call native code.
9486 * Parameters:
9487 * handle: Handle to the HTML window.
9488 * name: Javascript function name.
9489 * Notes: A DW_SIGNAL_HTML_MESSAGE event will be raised with scriptdata.
9490 * Returns:
9491 * DW_ERROR_NONE (0) on success.
9492 */
9493 int API dw_html_javascript_add(HWND handle, const char *name)
9494 {
9495 #if WK_API_ENABLED
9496 DWWebView *html = handle;
9497 WKUserContentController *controller = [[html configuration] userContentController];
9498
9499 if(controller && name)
9500 {
9501 DW_LOCAL_POOL_IN;
9502 /* Script to inject that will call the handler we are adding */
9503 NSString *script = [NSString stringWithFormat:@"function %s(body) {window.webkit.messageHandlers.%s.postMessage(body);}",
9504 name, name];
9505 [controller addScriptMessageHandler:handle name:[NSString stringWithUTF8String:name]];
9506 [controller addUserScript:[[WKUserScript alloc] initWithSource:script
9507 injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]];
9508 DW_LOCAL_POOL_OUT;
9509 return DW_ERROR_NONE;
9510 }
9511 #endif
9512 return DW_ERROR_UNKNOWN;
9513 }
9514
9515
9516 /*
9471 * Create a new HTML window (widget) to be packed. 9517 * Create a new HTML window (widget) to be packed.
9472 * Not available under OS/2, eCS 9518 * Not available under OS/2, eCS
9473 * Parameters: 9519 * Parameters:
9474 * text: The default text to be in the entryfield widget. 9520 * text: The default text to be in the entryfield widget.
9475 * id: An ID to be used with dw_window_from_id() or 0L. 9521 * id: An ID to be used with dw_window_from_id() or 0L.