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.
This commit is contained in:
Po Lu 2021-11-22 10:42:46 +08:00
parent 536e7bf03b
commit 9324efac48
5 changed files with 50 additions and 17 deletions

View file

@ -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

View file

@ -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'.

View file

@ -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."

View file

@ -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

View file

@ -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);