From 9324efac480df3cd78af112da2b12a0d2bd18e02 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 22 Nov 2021 10:42:46 +0800 Subject: [PATCH] Make `xwidget-display-event' a special event as well * doc/lispref/commands.texi (Xwidget Events): Document that `xwidget-display-event' is a special event, and that it should be handled through callbacks. * etc/NEWS: Update NEWS entry. * lisp/xwidget.el (xwidget-webkit-new-session) (xwidget-webkit-import-widget): Attach display callback. (xwidget-webkit-display-event): Call display callback instead. (xwidget-webkit-display-callback): New function. * src/keyboard.c (make_lispy_event): Store source information for XWIDGET_DISPLAY_EVENT correctly. * src/xwidget.c (store_xwidget_display_event): Store source of the display request. (webkit_ready_to_show): Store source if available. (webkit_create_cb_1): Store source if available. (kill_xwidget): Remove dead widget from internal_xwidget_list. --- doc/lispref/commands.texi | 10 ++++++++-- etc/NEWS | 4 ++-- lisp/xwidget.el | 17 ++++++++++++++--- src/keyboard.c | 2 +- src/xwidget.c | 34 +++++++++++++++++++++++++--------- 5 files changed, 50 insertions(+), 17 deletions(-) diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 5fd7b55a60b..c12a97cc7df 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -1950,9 +1950,15 @@ internally by @code{xwidget-webkit-execute-script}. @end table @cindex @code{xwidget-display-event} event -@item (xwidget-display-event @var{xwidget}) +@item (xwidget-display-event @var{xwidget} @var{source}) This event is sent whenever an xwidget requests that another xwidget -be displayed. @var{xwidget} is the xwidget that should be displayed. +be displayed. @var{xwidget} is the xwidget that should be displayed, +and @var{source} is the xwidget that asked to display @var{xwidget}. + +It is also a special event which should be handled through callbacks. +You can add such a callback by setting the @code{display-callback} of +@var{source}'s property list, which should be a function that accepts +@var{xwidget} and @var{source} as arguments. @var{xwidget}'s buffer will be set to a temporary buffer. When displaying the widget, care should be taken to replace the buffer with diff --git a/etc/NEWS b/etc/NEWS index bfea4da8b9e..6fa5de0116d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -927,8 +927,8 @@ commits to the load. +++ *** New event type 'xwidget-display-event'. These events are sent whenever an xwidget requests that Emacs display -another xwidget. The only argument to this event is the xwidget that -should be displayed. +another xwidget. The only arguments to this event are the xwidget +that should be displayed, and the xwidget that asked to display it. +++ *** New function 'xwidget-webkit-set-cookie-storage-file'. diff --git a/lisp/xwidget.el b/lisp/xwidget.el index 160da67cb21..cf4396fec2d 100644 --- a/lisp/xwidget.el +++ b/lisp/xwidget.el @@ -818,6 +818,7 @@ For example, use this to display an anchor." (xwidget-webkit-set-cookie-storage-file xw (expand-file-name xwidget-webkit-cookie-file))) (xwidget-put xw 'callback callback) + (xwidget-put xw 'display-callback #'xwidget-webkit-display-callback) (xwidget-webkit-mode) (xwidget-webkit-goto-uri (xwidget-webkit-last-session) url))) @@ -840,16 +841,26 @@ Return the buffer." (put-text-property (point-min) (point-max) 'display (list 'xwidget :xwidget xwidget))) (xwidget-put xwidget 'callback callback) + (xwidget-put xwidget 'display-callback + #'xwidget-webkit-display-callback) (set-xwidget-buffer xwidget buffer) (xwidget-webkit-mode)) buffer)) (defun xwidget-webkit-display-event (event) - "Import the xwidget inside EVENT and display it." + "Trigger display callback for EVENT." (interactive "e") - (display-buffer (xwidget-webkit-import-widget (nth 1 event)))) + (let ((xwidget (cadr event)) + (source (caddr event))) + (when (xwidget-get source 'display-callback) + (funcall (xwidget-get source 'display-callback) + xwidget source)))) -(global-set-key [xwidget-display-event] 'xwidget-webkit-display-event) +(defun xwidget-webkit-display-callback (xwidget _source) + "Import XWIDGET and display it." + (display-buffer (xwidget-webkit-import-widget xwidget))) + +(define-key special-event-map [xwidget-display-event] 'xwidget-webkit-display-event) (defun xwidget-webkit-goto-url (url) "Goto URL with xwidget webkit." diff --git a/src/keyboard.c b/src/keyboard.c index 982854c41e1..c98175aea0d 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -6141,7 +6141,7 @@ make_lispy_event (struct input_event *event) return Fcons (Qxwidget_event, event->arg); case XWIDGET_DISPLAY_EVENT: - return list2 (Qxwidget_display_event, event->arg); + return Fcons (Qxwidget_display_event, event->arg); #endif #ifdef USE_FILE_NOTIFY diff --git a/src/xwidget.c b/src/xwidget.c index d88270dbe97..5da2aa1743b 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -1316,16 +1316,18 @@ store_xwidget_js_callback_event (struct xwidget *xw, #ifdef USE_GTK static void -store_xwidget_display_event (struct xwidget *xw) +store_xwidget_display_event (struct xwidget *xw, + struct xwidget *src) { struct input_event evt; - Lisp_Object val; + Lisp_Object val, src_val; XSETXWIDGET (val, xw); + XSETXWIDGET (src_val, src); EVENT_INIT (evt); evt.kind = XWIDGET_DISPLAY_EVENT; evt.frame_or_window = Qnil; - evt.arg = val; + evt.arg = list2 (val, src_val); kbd_buffer_store_event (&evt); } @@ -1335,6 +1337,9 @@ webkit_ready_to_show (WebKitWebView *new_view, { Lisp_Object tem; struct xwidget *xw; + struct xwidget *src; + + src = find_xwidget_for_offscreen_window (GDK_WINDOW (user_data)); for (tem = internal_xwidget_list; CONSP (tem); tem = XCDR (tem)) { @@ -1344,14 +1349,21 @@ webkit_ready_to_show (WebKitWebView *new_view, if (EQ (xw->type, Qwebkit) && WEBKIT_WEB_VIEW (xw->widget_osr) == new_view) - store_xwidget_display_event (xw); + { + /* The source widget was destroyed before we had a + chance to display the new widget. */ + if (!src) + kill_xwidget (xw); + else + store_xwidget_display_event (xw, src); + } } } } static GtkWidget * webkit_create_cb_1 (WebKitWebView *webview, - struct xwidget_view *xv) + struct xwidget *xv) { Lisp_Object related; Lisp_Object xwidget; @@ -1369,7 +1381,8 @@ webkit_create_cb_1 (WebKitWebView *webview, widget = XXWIDGET (xwidget)->widget_osr; g_signal_connect (G_OBJECT (widget), "ready-to-show", - G_CALLBACK (webkit_ready_to_show), NULL); + G_CALLBACK (webkit_ready_to_show), + gtk_widget_get_window (xv->widgetwindow_osr)); return widget; } @@ -1591,7 +1604,7 @@ webkit_decide_policy_cb (WebKitWebView *webView, newview = WEBKIT_WEB_VIEW (XXWIDGET (new_xwidget)->widget_osr); webkit_web_view_load_request (newview, request); - store_xwidget_display_event (XXWIDGET (new_xwidget)); + store_xwidget_display_event (XXWIDGET (new_xwidget), xw); return TRUE; } case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION: @@ -3106,6 +3119,11 @@ kill_frame_xwidget_views (struct frame *f) static void kill_xwidget (struct xwidget *xw) { + Lisp_Object val; + XSETXWIDGET (val, xw); + + internal_xwidget_list = Fdelq (val, internal_xwidget_list); + Vxwidget_list = Fcopy_sequence (internal_xwidget_list); #ifdef USE_GTK xw->buffer = Qnil; @@ -3145,8 +3163,6 @@ kill_buffer_xwidgets (Lisp_Object buffer) for (tail = Fget_buffer_xwidgets (buffer); CONSP (tail); tail = XCDR (tail)) { xwidget = XCAR (tail); - internal_xwidget_list = Fdelq (xwidget, internal_xwidget_list); - Vxwidget_list = Fcopy_sequence (internal_xwidget_list); { CHECK_LIVE_XWIDGET (xwidget); struct xwidget *xw = XXWIDGET (xwidget); -- 2.39.5