Mercurial > dwindows
comparison gtk4/dw.c @ 2978:d84182f0054e
GTK4: Support for dw_html_javascript_add() and DW_SIGNAL_HTML_MESSAGE.
Also add support for the stable WebKitGTK 6.0 for GTK4.
They changed a lot including the package name, add USE_WEBKIT6 for this.
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Fri, 24 Mar 2023 23:04:39 +0000 |
parents | 0577a97fe36d |
children | 7e273fec75ae |
comparison
equal
deleted
inserted
replaced
2977:7d6773c474d0 | 2978:d84182f0054e |
---|---|
32 #ifdef GDK_WINDOWING_X11 | 32 #ifdef GDK_WINDOWING_X11 |
33 #include <gdk/x11/gdkx.h> | 33 #include <gdk/x11/gdkx.h> |
34 #endif | 34 #endif |
35 | 35 |
36 #ifdef USE_WEBKIT | 36 #ifdef USE_WEBKIT |
37 #ifdef USE_WEBKIT6 | |
38 #include <webkit/webkit.h> | |
39 #else | |
37 #include <webkit2/webkit2.h> | 40 #include <webkit2/webkit2.h> |
41 #endif | |
38 #endif | 42 #endif |
39 | 43 |
40 #include <gdk-pixbuf/gdk-pixbuf.h> | 44 #include <gdk-pixbuf/gdk-pixbuf.h> |
41 | 45 |
42 #ifdef __FreeBSD__ | 46 #ifdef __FreeBSD__ |
475 static gint _dw_switch_page_event(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer data); | 479 static gint _dw_switch_page_event(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer data); |
476 static gint _dw_column_click_event(GtkWidget *widget, gpointer data); | 480 static gint _dw_column_click_event(GtkWidget *widget, gpointer data); |
477 #ifdef USE_WEBKIT | 481 #ifdef USE_WEBKIT |
478 static void _dw_html_result_event(GObject *object, GAsyncResult *result, gpointer script_data); | 482 static void _dw_html_result_event(GObject *object, GAsyncResult *result, gpointer script_data); |
479 static void _dw_html_changed_event(WebKitWebView *web_view, WebKitLoadEvent load_event, gpointer data); | 483 static void _dw_html_changed_event(WebKitWebView *web_view, WebKitLoadEvent load_event, gpointer data); |
484 #ifdef USE_WEBKIT6 | |
485 static void _dw_html_message_event(WebKitUserContentManager *manager, JSCValue *result, gpointer *data); | |
486 #else | |
487 static void _dw_html_message_event(WebKitUserContentManager *manager, WebKitJavascriptResult *result, gpointer *data); | |
488 #endif | |
480 #endif | 489 #endif |
481 static void _dw_signal_disconnect(gpointer data, GClosure *closure); | 490 static void _dw_signal_disconnect(gpointer data, GClosure *closure); |
482 static void _dw_event_coordinates_to_window(GtkWidget *widget, double *x, double *y); | 491 static void _dw_event_coordinates_to_window(GtkWidget *widget, double *x, double *y); |
483 | 492 |
484 GObject *_DWObject = NULL; | 493 GObject *_DWObject = NULL; |
520 gint cid; | 529 gint cid; |
521 void *intfunc; | 530 void *intfunc; |
522 | 531 |
523 } DWSignalHandler; | 532 } DWSignalHandler; |
524 | 533 |
525 /* A list of signal forwarders, to account for paramater differences. */ | 534 /* A list of signal forwarders, to account for parameter differences. */ |
526 static DWSignalList DWSignalTranslate[] = { | 535 static DWSignalList DWSignalTranslate[] = { |
527 { _dw_configure_event, DW_SIGNAL_CONFIGURE, "resize", NULL }, | 536 { _dw_configure_event, DW_SIGNAL_CONFIGURE, "resize", NULL }, |
528 { _dw_key_press_event, DW_SIGNAL_KEY_PRESS, "key-pressed", _dw_key_setup }, | 537 { _dw_key_press_event, DW_SIGNAL_KEY_PRESS, "key-pressed", _dw_key_setup }, |
529 { _dw_button_press_event, DW_SIGNAL_BUTTON_PRESS, "pressed", _dw_mouse_setup }, | 538 { _dw_button_press_event, DW_SIGNAL_BUTTON_PRESS, "pressed", _dw_mouse_setup }, |
530 { _dw_button_release_event, DW_SIGNAL_BUTTON_RELEASE, "released", _dw_mouse_setup }, | 539 { _dw_button_release_event, DW_SIGNAL_BUTTON_RELEASE, "released", _dw_mouse_setup }, |
542 { _dw_column_click_event, DW_SIGNAL_COLUMN_CLICK, "activate", _dw_tree_setup }, | 551 { _dw_column_click_event, DW_SIGNAL_COLUMN_CLICK, "activate", _dw_tree_setup }, |
543 { _dw_tree_expand_event, DW_SIGNAL_TREE_EXPAND, "row-expanded", NULL }, | 552 { _dw_tree_expand_event, DW_SIGNAL_TREE_EXPAND, "row-expanded", NULL }, |
544 #ifdef USE_WEBKIT | 553 #ifdef USE_WEBKIT |
545 { _dw_html_changed_event, DW_SIGNAL_HTML_CHANGED, "load-changed", NULL }, | 554 { _dw_html_changed_event, DW_SIGNAL_HTML_CHANGED, "load-changed", NULL }, |
546 { _dw_html_result_event, DW_SIGNAL_HTML_RESULT, "", _dw_html_setup }, | 555 { _dw_html_result_event, DW_SIGNAL_HTML_RESULT, "", _dw_html_setup }, |
556 { _dw_html_message_event, DW_SIGNAL_HTML_MESSAGE, "", _dw_html_setup }, | |
547 #endif | 557 #endif |
548 { NULL, "", "", NULL } | 558 { NULL, "", "", NULL } |
549 }; | 559 }; |
550 | 560 |
551 /* Alignment flags */ | 561 /* Alignment flags */ |
672 | 682 |
673 #ifdef USE_WEBKIT | 683 #ifdef USE_WEBKIT |
674 static void _dw_html_result_event(GObject *object, GAsyncResult *result, gpointer script_data) | 684 static void _dw_html_result_event(GObject *object, GAsyncResult *result, gpointer script_data) |
675 { | 685 { |
676 pthread_t saved_thread = _dw_thread; | 686 pthread_t saved_thread = _dw_thread; |
687 #ifndef USE_WEBKIT6 | |
677 WebKitJavascriptResult *js_result; | 688 WebKitJavascriptResult *js_result; |
689 #endif | |
678 JSCValue *value; | 690 JSCValue *value; |
679 GError *error = NULL; | 691 GError *error = NULL; |
680 int (*htmlresultfunc)(HWND, int, char *, void *, void *) = NULL; | 692 int (*htmlresultfunc)(HWND, int, char *, void *, void *) = NULL; |
681 gint handlerdata = GPOINTER_TO_INT(g_object_get_data(object, "_dw_html_result_id")); | 693 gint handlerdata = GPOINTER_TO_INT(g_object_get_data(object, "_dw_html_result_id")); |
682 void *user_data = NULL; | 694 void *user_data = NULL; |
683 | 695 |
684 _dw_thread = (pthread_t)-1; | 696 _dw_thread = (pthread_t)-1; |
685 if(handlerdata) | 697 if(handlerdata) |
686 { | 698 { |
687 DWSignalHandler work; | |
688 void *params[3] = { GINT_TO_POINTER(handlerdata-1), 0, object }; | 699 void *params[3] = { GINT_TO_POINTER(handlerdata-1), 0, object }; |
689 | 700 DWSignalHandler work = _dw_get_signal_handler(params); |
690 work = _dw_get_signal_handler(params); | |
691 | 701 |
692 if(work.window) | 702 if(work.window) |
693 { | 703 { |
694 htmlresultfunc = work.func; | 704 htmlresultfunc = work.func; |
695 user_data = work.data; | 705 user_data = work.data; |
696 } | 706 } |
697 } | 707 } |
698 | 708 |
709 #ifdef USE_WEBKIT6 | |
710 if(!(value = webkit_web_view_evaluate_javascript_finish(WEBKIT_WEB_VIEW(object), result, &error))) | |
711 #else | |
699 if(!(js_result = webkit_web_view_run_javascript_finish(WEBKIT_WEB_VIEW(object), result, &error))) | 712 if(!(js_result = webkit_web_view_run_javascript_finish(WEBKIT_WEB_VIEW(object), result, &error))) |
713 #endif | |
700 { | 714 { |
701 if(htmlresultfunc) | 715 if(htmlresultfunc) |
702 htmlresultfunc((HWND)object, DW_ERROR_UNKNOWN, error->message, script_data, user_data); | 716 htmlresultfunc((HWND)object, DW_ERROR_UNKNOWN, error->message, script_data, user_data); |
703 g_error_free (error); | 717 g_error_free (error); |
704 _dw_thread = saved_thread; | 718 _dw_thread = saved_thread; |
705 return; | 719 return; |
706 } | 720 } |
707 | 721 |
722 #ifndef USE_WEBKIT6 | |
708 value = webkit_javascript_result_get_js_value(js_result); | 723 value = webkit_javascript_result_get_js_value(js_result); |
724 #endif | |
709 if(jsc_value_is_string(value)) | 725 if(jsc_value_is_string(value)) |
710 { | 726 { |
711 gchar *str_value = jsc_value_to_string(value); | 727 gchar *str_value = jsc_value_to_string(value); |
712 JSCException *exception = jsc_context_get_exception(jsc_value_get_context(value)); | 728 JSCException *exception = jsc_context_get_exception(jsc_value_get_context(value)); |
713 | 729 |
720 } | 736 } |
721 g_free (str_value); | 737 g_free (str_value); |
722 } | 738 } |
723 else if(htmlresultfunc) | 739 else if(htmlresultfunc) |
724 htmlresultfunc((HWND)object, DW_ERROR_UNKNOWN, NULL, script_data, user_data); | 740 htmlresultfunc((HWND)object, DW_ERROR_UNKNOWN, NULL, script_data, user_data); |
741 #ifndef USE_WEBKIT6 | |
725 webkit_javascript_result_unref (js_result); | 742 webkit_javascript_result_unref (js_result); |
743 #endif | |
726 _dw_thread = saved_thread; | 744 _dw_thread = saved_thread; |
745 } | |
746 | |
747 #ifdef USE_WEBKIT6 | |
748 static void _dw_html_message_event(WebKitUserContentManager *manager, JSCValue *result, gpointer *data) | |
749 #else | |
750 static void _dw_html_message_event(WebKitUserContentManager *manager, WebKitJavascriptResult *result, gpointer *data) | |
751 #endif | |
752 { | |
753 HWND window = (HWND)data[0]; | |
754 int (*htmlmessagefunc)(HWND, char *, char *, void *) = NULL; | |
755 void *user_data = NULL; | |
756 gchar *name = (gchar *)data[1]; | |
757 gint handlerdata; | |
758 | |
759 if(window && (handlerdata = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(window), "_dw_html_message_id")))) | |
760 { | |
761 void *params[3] = { GINT_TO_POINTER(handlerdata-1), 0, window }; | |
762 DWSignalHandler work = _dw_get_signal_handler(params); | |
763 | |
764 if(work.window) | |
765 { | |
766 htmlmessagefunc = work.func; | |
767 user_data = work.data; | |
768 } | |
769 } | |
770 | |
771 if(jsc_value_is_string(result)) | |
772 { | |
773 gchar *str_value = jsc_value_to_string(result); | |
774 JSCException *exception = jsc_context_get_exception(jsc_value_get_context(result)); | |
775 | |
776 if(htmlmessagefunc && !exception) | |
777 htmlmessagefunc(window, name, str_value, user_data); | |
778 | |
779 g_free(str_value); | |
780 | |
781 if(!exception) | |
782 return; | |
783 } | |
784 if(htmlmessagefunc) | |
785 htmlmessagefunc(window, name, NULL, user_data); | |
727 } | 786 } |
728 | 787 |
729 static void _dw_html_changed_event(WebKitWebView *web_view, WebKitLoadEvent load_event, gpointer data) | 788 static void _dw_html_changed_event(WebKitWebView *web_view, WebKitLoadEvent load_event, gpointer data) |
730 { | 789 { |
731 DWSignalHandler work = _dw_get_signal_handler(data); | 790 DWSignalHandler work = _dw_get_signal_handler(data); |
10516 int API dw_html_javascript_run(HWND handle, const char *script, void *scriptdata) | 10575 int API dw_html_javascript_run(HWND handle, const char *script, void *scriptdata) |
10517 { | 10576 { |
10518 #ifdef USE_WEBKIT | 10577 #ifdef USE_WEBKIT |
10519 WebKitWebView *web_view; | 10578 WebKitWebView *web_view; |
10520 | 10579 |
10521 if((web_view = _dw_html_web_view(handle))) | 10580 if(script && (web_view = _dw_html_web_view(handle))) |
10581 #ifdef USE_WEBKIT6 | |
10582 webkit_web_view_evaluate_javascript(web_view, script, strlen(script), NULL, NULL, NULL, _dw_html_result_event, scriptdata); | |
10583 #else | |
10522 webkit_web_view_run_javascript(web_view, script, NULL, _dw_html_result_event, scriptdata); | 10584 webkit_web_view_run_javascript(web_view, script, NULL, _dw_html_result_event, scriptdata); |
10585 #endif | |
10523 return DW_ERROR_NONE; | 10586 return DW_ERROR_NONE; |
10524 #else | 10587 #else |
10525 return DW_ERROR_UNKNOWN; | 10588 return DW_ERROR_UNKNOWN; |
10526 #endif | 10589 #endif |
10590 } | |
10591 | |
10592 /* Free the name when the signal disconnects */ | |
10593 void _dw_html_message_disconnect(gpointer gdata, GClosure *closure) | |
10594 { | |
10595 gpointer *data = (gpointer *)gdata; | |
10596 | |
10597 if(data) | |
10598 { | |
10599 gchar *name = (gchar *)data[1]; | |
10600 | |
10601 if(name) | |
10602 g_free(name); | |
10603 free(data); | |
10604 } | |
10605 } | |
10606 | |
10607 /* | |
10608 * Install a javascript function with name that can call native code. | |
10609 * Parameters: | |
10610 * handle: Handle to the HTML window. | |
10611 * name: Javascript function name. | |
10612 * Notes: A DW_SIGNAL_HTML_MESSAGE event will be raised with scriptdata. | |
10613 * Returns: | |
10614 * DW_ERROR_NONE (0) on success. | |
10615 */ | |
10616 int API dw_html_javascript_add(HWND handle, const char *name) | |
10617 { | |
10618 #ifdef USE_WEBKIT | |
10619 WebKitWebView *web_view= _dw_html_web_view(handle); | |
10620 WebKitUserContentManager *manager; | |
10621 | |
10622 if(web_view && (manager = webkit_web_view_get_user_content_manager(web_view)) && name) | |
10623 { | |
10624 /* Script to inject that will call the handler we are adding */ | |
10625 gchar *script = g_strdup_printf("function %s(body) {window.webkit.messageHandlers.%s.postMessage(body);}", | |
10626 name, name); | |
10627 gchar *signal = g_strdup_printf("script-message-received::%s", name); | |
10628 WebKitUserScript *userscript = webkit_user_script_new(script, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, | |
10629 WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START, NULL, NULL); | |
10630 gpointer *data = calloc(sizeof(gpointer), 2); | |
10631 | |
10632 data[0] = handle; | |
10633 data[1] = g_strdup(name); | |
10634 g_signal_connect_data(manager, signal, G_CALLBACK(_dw_html_message_event), data, _dw_html_message_disconnect, 0); | |
10635 webkit_user_content_manager_register_script_message_handler(manager, name | |
10636 #if USE_WEBKIT6 | |
10637 , NULL | |
10638 #endif | |
10639 ); | |
10640 webkit_user_content_manager_add_script(manager, userscript); | |
10641 | |
10642 g_free(script); | |
10643 g_free(signal); | |
10644 return DW_ERROR_NONE; | |
10645 } | |
10646 #endif | |
10647 return DW_ERROR_UNKNOWN; | |
10527 } | 10648 } |
10528 | 10649 |
10529 /* | 10650 /* |
10530 * Create a new HTML window (widget) to be packed. | 10651 * Create a new HTML window (widget) to be packed. |
10531 * Parameters: | 10652 * Parameters: |
11088 } | 11209 } |
11089 | 11210 |
11090 #ifdef USE_WEBKIT | 11211 #ifdef USE_WEBKIT |
11091 GObject *_dw_html_setup(struct _dw_signal_list *signal, GObject *object, void *sigfunc, void *discfunc, void *data) | 11212 GObject *_dw_html_setup(struct _dw_signal_list *signal, GObject *object, void *sigfunc, void *discfunc, void *data) |
11092 { | 11213 { |
11093 if(WEBKIT_IS_WEB_VIEW(object) && strcmp(signal->name, DW_SIGNAL_HTML_RESULT) == 0) | 11214 if(WEBKIT_IS_WEB_VIEW(object)) |
11094 { | 11215 { |
11095 /* We don't actually need a signal handler here... just need to assign the handler ID | 11216 if(strcmp(signal->name, DW_SIGNAL_HTML_RESULT) == 0) |
11096 * Since the handler is created in dw_html_javasript_run() | 11217 { |
11097 */ | 11218 /* We don't actually need a signal handler here... just need to assign the handler ID |
11098 int sigid = _dw_set_signal_handler(object, (HWND)object, sigfunc, data, signal->func, discfunc); | 11219 * Since the handler is created in dw_html_javasript_run() |
11099 g_object_set_data(object, "_dw_html_result_id", GINT_TO_POINTER(sigid+1)); | 11220 */ |
11100 return NULL; | 11221 int sigid = _dw_set_signal_handler(object, (HWND)object, sigfunc, data, signal->func, discfunc); |
11222 g_object_set_data(object, "_dw_html_result_id", GINT_TO_POINTER(sigid+1)); | |
11223 return NULL; | |
11224 } | |
11225 else if(strcmp(signal->name, DW_SIGNAL_HTML_MESSAGE) == 0) | |
11226 { | |
11227 /* We don't actually need a signal handler here... just need to assign the handler ID | |
11228 * Since the handler is created in dw_html_javasript_add() | |
11229 */ | |
11230 int sigid = _dw_set_signal_handler(object, (HWND)object, sigfunc, data, signal->func, discfunc); | |
11231 g_object_set_data(object, "_dw_html_message_id", GINT_TO_POINTER(sigid+1)); | |
11232 return NULL; | |
11233 } | |
11101 } | 11234 } |
11102 return object; | 11235 return object; |
11103 } | 11236 } |
11104 #endif | 11237 #endif |
11105 | 11238 |