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