Mercurial > dwindows
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. |