[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 0be966f 30/35: Make "open in new window" from an xwidget's contex
From: |
Lars Ingebrigtsen |
Subject: |
master 0be966f 30/35: Make "open in new window" from an xwidget's context menu work |
Date: |
Sat, 6 Nov 2021 22:02:00 -0400 (EDT) |
branch: master
commit 0be966f97e3bda057318d971d022515cfa6eb37b
Author: Po Lu <luangruo@yahoo.com>
Commit: Lars Ingebrigtsen <larsi@gnus.org>
Make "open in new window" from an xwidget's context menu work
* doc/lispref/commands.texi (Xwidget Events): Document new event type.
* doc/lisprefdisplay.texi (Xwidgets): Document new argument to
make-xwidget, and new function.
* etc/NEWS: Document changes.
* lisp/xwidget.el: Bind xwidget-display-event to
xwidget-webkit-display-event.
(xwidget-webkit-import-widget): New function.
(xwidget-webkit-display-event): New command.
* src/keyboard.c (kbd_buffer_get_event): New event type.
(make_lispy_event): Handle XWIDGET_DISPLAY_EVENTs.
(syms_f_keyboard): Define new symbol.
* src/termhooks.h (enum event_kind): New enum XWIDGET_DISPLAY_EVENT.
* src/xwidget.c (webkit_create_cb)
(store_xwidget_display_event)
(webkit_ready_to_show)
(webkit_create_cb_1, webkit_create_cb)
(Fset_xwidget_buffer): New functions.
(Fmake_xwidget): Add internal argument RELATED and connect create
signal.
(syms_of_xwidget): Define now subrs.
---
doc/lispref/commands.texi | 9 +++
doc/lispref/display.texi | 10 ++-
etc/NEWS | 12 ++++
lisp/xwidget.el | 24 ++++++++
src/keyboard.c | 7 +++
src/termhooks.h | 2 +
src/xwidget.c | 154 ++++++++++++++++++++++++++++++++++++++++------
7 files changed, 196 insertions(+), 22 deletions(-)
diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index ca59475..832b570 100644
--- a/doc/lispref/commands.texi
+++ b/doc/lispref/commands.texi
@@ -1931,6 +1931,15 @@ An event with @var{kind} set to
@code{javascript-callback} contains
JavaScript callback data. These events are used internally by
@code{xwidget-webkit-execute-script}.
+@cindex @code{xwidget-display-event} event
+@item (xwidget-display-event @var{xwidget})
+This event is sent whenever an xwidget requests that another xwidget
+be displayed. @var{xwidget} is the xwidget that should be displayed.
+
+@var{xwidget}'s buffer will be set to a temporary buffer. When
+displaying the widget, care should be taken to replace the buffer with
+the buffer in which the xwidget will be displayed, using
+@code{set-xwidget-buffer} (@pxref{Xwidgets}).
@end table
@node Misc Events
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index b780263..37f07c4 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -6787,7 +6787,7 @@ Property}).
Embedded widgets can send events notifying Lisp code about changes
occurring within them. (@pxref{Xwidget Events}).
-@defun make-xwidget type title width height arguments &optional buffer
+@defun make-xwidget type title width height arguments &optional buffer related
This creates and returns an xwidget object. If
@var{buffer} is omitted or @code{nil}, it defaults to the current
buffer. If @var{buffer} names a buffer that doesn't exist, it will be
@@ -6800,7 +6800,9 @@ The WebKit component.
@end table
The @var{width} and @var{height} arguments specify the widget size in
-pixels, and @var{title}, a string, specifies its title.
+pixels, and @var{title}, a string, specifies its title. @var{related}
+is used internally by the WebKit widget, and is not of interest to the
+programmer.
@end defun
@defun xwidgetp object
@@ -6821,6 +6823,10 @@ property list given by @var{plist}.
This function returns the buffer of @var{xwidget}.
@end defun
+@defun set-xwidget-buffer xwidget buffer
+This function sets the buffer of @var{xwidget} to @var{buffer}.
+@end defun
+
@defun get-buffer-xwidgets buffer
This function returns a list of xwidget objects associated with the
@var{buffer}, which can be specified as a buffer object or a name of
diff --git a/etc/NEWS b/etc/NEWS
index 0cbddeb..0e5caa4 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -514,6 +514,12 @@ to `C-s' and `C-r'.
To access the inspector, right click on the widget and select "Inspect
Element".
+---
+*** "Open in New Window" in a WebKit widget's context menu now works.
+The newly created buffer will be displayed via display-buffer, which
+can be customized through the usual mechanism of display-buffer-alist
+and friends.
+
* New Modes and Packages in Emacs 29.1
@@ -759,6 +765,12 @@ completed, `load-started' when a load first starts,
`load-redirected'
after a redirect, and `load-committed' when the WebKit widget first
commits to the load.
++++
+** New event type `xwidget-display-event'.
+These events are sent whenever an xwidget requests that Emacs display
+another. The only argument to this event is the xwidget that should
+be displayed.
+
* Changes in Emacs 29.1 on Non-Free Operating Systems
diff --git a/lisp/xwidget.el b/lisp/xwidget.el
index bd3c087..d427e70 100644
--- a/lisp/xwidget.el
+++ b/lisp/xwidget.el
@@ -37,6 +37,7 @@
(declare-function make-xwidget "xwidget.c"
(type title width height arguments &optional buffer))
(declare-function xwidget-buffer "xwidget.c" (xwidget))
+(declare-function set-xwidget-buffer "xwidget.c" (xwidget buffer))
(declare-function xwidget-size-request "xwidget.c" (xwidget))
(declare-function xwidget-resize "xwidget.c" (xwidget new-width new-height))
(declare-function xwidget-webkit-execute-script "xwidget.c"
@@ -701,6 +702,29 @@ For example, use this to display an anchor."
(xwidget-webkit-mode)
(xwidget-webkit-goto-uri (xwidget-webkit-last-session) url)))
+(defun xwidget-webkit-import-widget (xwidget)
+ "Create a new webkit session buffer from XWIDGET, an existing xwidget.
+Return the buffer."
+ (let* ((bufname (generate-new-buffer-name "*xwidget-webkit*"))
+ (callback #'xwidget-webkit-callback)
+ (buffer (get-buffer-create bufname)))
+ (with-current-buffer buffer
+ (save-excursion
+ (erase-buffer)
+ (insert ".")
+ (put-text-property (point-min) (point-max)
+ 'display (list 'xwidget :xwidget xwidget)))
+ (xwidget-put xwidget 'callback callback)
+ (set-xwidget-buffer xwidget buffer)
+ (xwidget-webkit-mode))
+ buffer))
+
+(defun xwidget-webkit-display-event (event)
+ "Import the xwidget inside EVENT and display it."
+ (interactive "e")
+ (display-buffer (xwidget-webkit-import-widget (nth 1 event))))
+
+(global-set-key [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 46dce57..c4a5671 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -3993,6 +3993,7 @@ kbd_buffer_get_event (KBOARD **kbp,
#endif
#ifdef HAVE_XWIDGETS
case XWIDGET_EVENT:
+ case XWIDGET_DISPLAY_EVENT:
#endif
case SAVE_SESSION_EVENT:
case NO_EVENT:
@@ -6139,6 +6140,11 @@ make_lispy_event (struct input_event *event)
{
return Fcons (Qxwidget_event, event->arg);
}
+
+ case XWIDGET_DISPLAY_EVENT:
+ {
+ return list2 (Qxwidget_display_event, event->arg);
+ }
#endif
#ifdef USE_FILE_NOTIFY
@@ -11732,6 +11738,7 @@ syms_of_keyboard (void)
#ifdef HAVE_XWIDGETS
DEFSYM (Qxwidget_event, "xwidget-event");
+ DEFSYM (Qxwidget_display_event, "xwidget-display-event");
#endif
#ifdef USE_FILE_NOTIFY
diff --git a/src/termhooks.h b/src/termhooks.h
index 1d3cdc8..e7539bb 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -255,6 +255,8 @@ enum event_kind
#ifdef HAVE_XWIDGETS
/* events generated by xwidgets*/
, XWIDGET_EVENT
+ /* Event generated when WebKit asks us to display another widget. */
+ , XWIDGET_DISPLAY_EVENT
#endif
#ifdef USE_FILE_NOTIFY
diff --git a/src/xwidget.c b/src/xwidget.c
index 10bb4ac..0a6d95a 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -19,6 +19,7 @@ along with GNU Emacs. If not, see
<https://www.gnu.org/licenses/>. */
#include <config.h>
+#include "buffer.h"
#include "xwidget.h"
#include "lisp.h"
@@ -76,7 +77,7 @@ static void webkit_javascript_finished_cb (GObject *,
GAsyncResult *,
gpointer);
static gboolean webkit_download_cb (WebKitWebContext *, WebKitDownload *,
gpointer);
-
+static GtkWidget *webkit_create_cb (WebKitWebView *, WebKitNavigationAction *,
gpointer);
static gboolean
webkit_decide_policy_cb (WebKitWebView *,
WebKitPolicyDecision *,
@@ -101,7 +102,7 @@ static void mouse_target_changed (WebKitWebView *,
WebKitHitTestResult *, guint,
DEFUN ("make-xwidget",
Fmake_xwidget, Smake_xwidget,
- 5, 6, 0,
+ 5, 7, 0,
doc: /* Make an xwidget of TYPE.
If BUFFER is nil, use the current buffer.
If BUFFER is a string and no such buffer exists, create it.
@@ -109,10 +110,12 @@ TYPE is a symbol which can take one of the following
values:
- webkit
-Returns the newly constructed xwidget, or nil if construction fails. */)
+RELATED is nil, or an xwidget. This argument is used internally.
+Returns the newly constructed xwidget, or nil if construction
+fails. */)
(Lisp_Object type,
Lisp_Object title, Lisp_Object width, Lisp_Object height,
- Lisp_Object arguments, Lisp_Object buffer)
+ Lisp_Object arguments, Lisp_Object buffer, Lisp_Object related)
{
#ifdef USE_GTK
if (!xg_gtk_initialized)
@@ -160,22 +163,33 @@ Returns the newly constructed xwidget, or nil if
construction fails. */)
if (EQ (xw->type, Qwebkit))
{
- xw->widget_osr = webkit_web_view_new ();
-
- /* Enable the developer extras */
- settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW
(xw->widget_osr));
- g_object_set (G_OBJECT (settings), "enable-developer-extras", TRUE,
NULL);
-
- /* webkitgtk uses GSubprocess which sets sigaction causing
- Emacs to not catch SIGCHLD with its usual handle setup in
- catch_child_signal(). This resets the SIGCHLD
- sigaction. */
- struct sigaction old_action;
- sigaction (SIGCHLD, NULL, &old_action);
- webkit_web_view_load_uri(WEBKIT_WEB_VIEW (xw->widget_osr),
- "about:blank");
- sigaction (SIGCHLD, &old_action, NULL);
- }
+ WebKitWebView *related_view;
+
+ if (NILP (related)
+ || !XWIDGETP (related)
+ || !EQ (XXWIDGET (related)->type, Qwebkit))
+ {
+ /* Enable the developer extras */
+ settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW
(xw->widget_osr));
+ g_object_set (G_OBJECT (settings), "enable-developer-extras",
TRUE, NULL);
+ xw->widget_osr = webkit_web_view_new ();
+
+ /* webkitgtk uses GSubprocess which sets sigaction causing
+ Emacs to not catch SIGCHLD with its usual handle setup in
+ catch_child_signal(). This resets the SIGCHLD
+ sigaction. */
+ struct sigaction old_action;
+ sigaction (SIGCHLD, NULL, &old_action);
+ webkit_web_view_load_uri (WEBKIT_WEB_VIEW (xw->widget_osr),
+ "about:blank");
+ sigaction (SIGCHLD, &old_action, NULL);
+ }
+ else
+ {
+ related_view = WEBKIT_WEB_VIEW (XXWIDGET (related)->widget_osr);
+ xw->widget_osr = webkit_web_view_new_with_related_view
(related_view);
+ }
+ }
gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width,
xw->height);
@@ -221,6 +235,10 @@ Returns the newly constructed xwidget, or nil if
construction fails. */)
"mouse-target-changed",
G_CALLBACK (mouse_target_changed),
xw);
+ g_signal_connect (G_OBJECT (xw->widget_osr),
+ "create",
+ G_CALLBACK (webkit_create_cb),
+ xw);
}
g_signal_connect (G_OBJECT (xw->widgetwindow_osr), "damage-event",
@@ -927,6 +945,88 @@ store_xwidget_js_callback_event (struct xwidget *xw,
#ifdef USE_GTK
+static void
+store_xwidget_display_event (struct xwidget *xw)
+{
+ struct input_event evt;
+ Lisp_Object val;
+
+ XSETXWIDGET (val, xw);
+ EVENT_INIT (evt);
+ evt.kind = XWIDGET_DISPLAY_EVENT;
+ evt.frame_or_window = Qnil;
+ evt.arg = val;
+ kbd_buffer_store_event (&evt);
+}
+
+static void
+webkit_ready_to_show (WebKitWebView *new_view,
+ gpointer user_data)
+{
+ Lisp_Object tem;
+ struct xwidget *xw;
+
+ for (tem = Vxwidget_list; CONSP (tem); tem = XCDR (tem))
+ {
+ if (XWIDGETP (XCAR (tem)))
+ {
+ xw = XXWIDGET (XCAR (tem));
+
+ if (EQ (xw->type, Qwebkit)
+ && WEBKIT_WEB_VIEW (xw->widget_osr) == new_view)
+ store_xwidget_display_event (xw);
+ }
+ }
+}
+
+static GtkWidget *
+webkit_create_cb_1 (WebKitWebView *webview,
+ struct xwidget_view *xv)
+{
+ Lisp_Object related;
+ Lisp_Object xwidget;
+ GtkWidget *widget;
+
+ XSETXWIDGET (related, xv);
+ xwidget = Fmake_xwidget (Qwebkit, Qnil, make_fixnum (0),
+ make_fixnum (0), Qnil,
+ build_string (" *detached xwidget buffer*"),
+ related);
+
+ if (NILP (xwidget))
+ return NULL;
+
+ widget = XXWIDGET (xwidget)->widget_osr;
+
+ g_signal_connect (G_OBJECT (widget), "ready-to-show",
+ G_CALLBACK (webkit_ready_to_show), NULL);
+
+ return widget;
+}
+
+static GtkWidget *
+webkit_create_cb (WebKitWebView *webview,
+ WebKitNavigationAction *nav_action,
+ gpointer user_data)
+{
+ switch (webkit_navigation_action_get_navigation_type (nav_action))
+ {
+ case WEBKIT_NAVIGATION_TYPE_OTHER:
+ if (webkit_navigation_action_is_user_gesture (nav_action))
+ return NULL;
+
+ return webkit_create_cb_1 (webview, user_data);
+ case WEBKIT_NAVIGATION_TYPE_LINK_CLICKED:
+ case WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED:
+ case WEBKIT_NAVIGATION_TYPE_BACK_FORWARD:
+ case WEBKIT_NAVIGATION_TYPE_RELOAD:
+ case WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED:
+ return webkit_create_cb_1 (webview, user_data);
+ default:
+ return NULL;
+ }
+}
+
void
webkit_view_load_changed_cb (WebKitWebView *webkitwebview,
WebKitLoadEvent load_event,
@@ -1722,6 +1822,19 @@ DEFUN ("xwidget-buffer",
return XXWIDGET (xwidget)->buffer;
}
+DEFUN ("set-xwidget-buffer",
+ Fset_xwidget_buffer, Sset_xwidget_buffer,
+ 2, 2, 0,
+ doc: /* Set XWIDGET's buffer to BUFFER. */)
+ (Lisp_Object xwidget, Lisp_Object buffer)
+{
+ CHECK_XWIDGET (xwidget);
+ CHECK_BUFFER (buffer);
+
+ XXWIDGET (xwidget)->buffer = buffer;
+ return Qnil;
+}
+
DEFUN ("set-xwidget-plist",
Fset_xwidget_plist, Sset_xwidget_plist,
2, 2, 0,
@@ -1957,6 +2070,7 @@ syms_of_xwidget (void)
defsubr (&Sxwidget_webkit_finish_search);
defsubr (&Sxwidget_webkit_next_result);
defsubr (&Sxwidget_webkit_previous_result);
+ defsubr (&Sset_xwidget_buffer);
DEFSYM (QCxwidget, ":xwidget");
DEFSYM (QCtitle, ":title");
- master 49ed706 15/35: Select window when clicking on an xwidget view, (continued)
- master 49ed706 15/35: Select window when clicking on an xwidget view, Lars Ingebrigtsen, 2021/11/06
- master d97718c 17/35: Add a menu to xwidget-webkit, Lars Ingebrigtsen, 2021/11/06
- master f1fbf87 20/35: Make the WebKit inspector available, Lars Ingebrigtsen, 2021/11/06
- master 7269bdd 21/35: Improve detail of load-changed xwidget events, Lars Ingebrigtsen, 2021/11/06
- master 32ec485 16/35: Redisplay xwidget view windows instead of just setting their size, Lars Ingebrigtsen, 2021/11/06
- master cd7158e 18/35: Add new tool-bar items to xwidget-webkit, Lars Ingebrigtsen, 2021/11/06
- master 8729ae2 19/35: Add xwidget-webkit-copy-selection-as-kill to the menu bar, Lars Ingebrigtsen, 2021/11/06
- master 1cc19d0 23/35: Add support for cursors in xwidget views, Lars Ingebrigtsen, 2021/11/06
- master cb45114 26/35: Make it safe to have non-xwidget views in xwidget-view-list, Lars Ingebrigtsen, 2021/11/06
- master 286467a 27/35: Add functions for performing searches on xwidgets, Lars Ingebrigtsen, 2021/11/06
- master 0be966f 30/35: Make "open in new window" from an xwidget's context menu work,
Lars Ingebrigtsen <=
- master 686ce50 31/35: Rationalize creation decisions, Lars Ingebrigtsen, 2021/11/06
- master 3e04f1f 33/35: Fix web inspector, Lars Ingebrigtsen, 2021/11/06
- master 969ce9d 34/35: Improve xwidget isearch visuals, Lars Ingebrigtsen, 2021/11/06
- master cd1f02e 25/35: Make xwidgets print nicer, Lars Ingebrigtsen, 2021/11/06
- master eabd735 32/35: Default to creating new related sessions, Lars Ingebrigtsen, 2021/11/06
- master 5b7ab89 35/35: Fix build on nextstep, Lars Ingebrigtsen, 2021/11/06