Improvements to xwidget on macOS (bug#60703)

* src/nsxwidget.m ()
([XwWebView initWithFrame:configuration:xwidget:])
(nsxwidget_init):  Fixed memory leaks: when sending an alloc
message to an object, send an autorelease message to any objects
we won't explictly release.
([XwWebView webView:didFinishNavigation:]): Second string to
store in 'store_xwidget_event_string' is "load finished" rather
than empty string.
([XwWebView webView:didStartProvisionalNavigation:])
([XwWebView webView:didReceiveServerRedirectForProvisionalNavigation:])
([XwWebView webView:didCommitNavigation:]): New functions.
(nsxwidget_webkit_estimated_load_progress): New function.
(nsxwidget_webkit_stop_loading): New function.
* src/xwidget.c (Fxwidget_webkit_estimated_load_progress): Call
'nsxwidget_webkit_estimated_load_progress' if we're on MacOS.
(Fxwidget_webkit_stop_loading): Call 'nsxwidget_webkit_stop_loading'
if we're on MacOS.
(syms_of_xwidget): Define symbol for function.
'xwidget_webkit_estimated_load_progress' if we're on MacOS.
* src/nsxwidget.h: Signature for functions
'nsxwidget_webkit_estimated_load_progress' and
'nsxwidget_webkit_stop_loading'.
* lisp/xwidget.el (xwidget-webkit-current-url): Message URL rather
than return value of 'kill-new' (which is always nil).
This commit is contained in:
Andrew De Angelis 2023-02-23 22:47:41 -05:00 committed by Eli Zaretskii
parent 3f43a16bc6
commit a137f71c67
4 changed files with 114 additions and 54 deletions

View file

@ -925,7 +925,8 @@ Return the buffer."
"Display the current xwidget webkit URL and place it on the `kill-ring'." "Display the current xwidget webkit URL and place it on the `kill-ring'."
(interactive nil xwidget-webkit-mode) (interactive nil xwidget-webkit-mode)
(let ((url (xwidget-webkit-uri (xwidget-webkit-current-session)))) (let ((url (xwidget-webkit-uri (xwidget-webkit-current-session))))
(message "URL: %s" (kill-new (or url ""))))) (when url (kill-new url))
(message "URL: %s" url)))
(defun xwidget-webkit-browse-history () (defun xwidget-webkit-browse-history ()
"Display a buffer containing the history of page loads." "Display a buffer containing the history of page loads."

View file

@ -36,6 +36,8 @@ Lisp_Object nsxwidget_webkit_uri (struct xwidget *xw);
Lisp_Object nsxwidget_webkit_title (struct xwidget *xw); Lisp_Object nsxwidget_webkit_title (struct xwidget *xw);
void nsxwidget_webkit_goto_uri (struct xwidget *xw, const char *uri); void nsxwidget_webkit_goto_uri (struct xwidget *xw, const char *uri);
void nsxwidget_webkit_goto_history (struct xwidget *xw, int rel_pos); void nsxwidget_webkit_goto_history (struct xwidget *xw, int rel_pos);
double nsxwidget_webkit_estimated_load_progress(struct xwidget *xw);
void nsxwidget_webkit_stop_loading (struct xwidget *xw);
void nsxwidget_webkit_zoom (struct xwidget *xw, double zoom_change); void nsxwidget_webkit_zoom (struct xwidget *xw, double zoom_change);
void nsxwidget_webkit_execute_script (struct xwidget *xw, const char *script, void nsxwidget_webkit_execute_script (struct xwidget *xw, const char *script,
Lisp_Object fun); Lisp_Object fun);

View file

@ -62,7 +62,8 @@ - (id)initWithFrame:(CGRect)frame
xwidget:(struct xwidget *)xw xwidget:(struct xwidget *)xw
{ {
/* Script controller to add script message handler and user script. */ /* Script controller to add script message handler and user script. */
WKUserContentController *scriptor = [[WKUserContentController alloc] init]; WKUserContentController *scriptor = [[[WKUserContentController alloc] init]
autorelease];
configuration.userContentController = scriptor; configuration.userContentController = scriptor;
/* Enable inspect element context menu item for debugging. */ /* Enable inspect element context menu item for debugging. */
@ -81,7 +82,8 @@ - (id)initWithFrame:(CGRect)frame
if (self) if (self)
{ {
self.xw = xw; self.xw = xw;
self.urlScriptBlocked = [[NSMutableDictionary alloc] init]; self.urlScriptBlocked = [[[NSMutableDictionary alloc] init]
autorelease];
self.navigationDelegate = self; self.navigationDelegate = self;
self.UIDelegate = self; self.UIDelegate = self;
self.customUserAgent = self.customUserAgent =
@ -89,20 +91,45 @@ - (id)initWithFrame:(CGRect)frame
@" AppleWebKit/603.3.8 (KHTML, like Gecko)" @" AppleWebKit/603.3.8 (KHTML, like Gecko)"
@" Version/11.0.1 Safari/603.3.8"; @" Version/11.0.1 Safari/603.3.8";
[scriptor addScriptMessageHandler:self name:@"keyDown"]; [scriptor addScriptMessageHandler:self name:@"keyDown"];
[scriptor addUserScript:[[WKUserScript alloc] WKUserScript *userScript = [[[WKUserScript alloc]
initWithSource:xwScript initWithSource:xwScript
injectionTime: injectionTime:
WKUserScriptInjectionTimeAtDocumentStart WKUserScriptInjectionTimeAtDocumentStart
forMainFrameOnly:NO]]; forMainFrameOnly:NO] autorelease];
[scriptor addUserScript:userScript];
} }
return self; return self;
} }
/* These 4 functions emulate the behavior of webkit_view_load_changed_cb
in the GTK implementation*/
- (void) webView:(WKWebView *)webView - (void) webView:(WKWebView *)webView
didFinishNavigation:(WKNavigation *)navigation didFinishNavigation:(WKNavigation *)navigation
{ {
if (EQ (Fbuffer_live_p (self.xw->buffer), Qt)) if (EQ (Fbuffer_live_p (self.xw->buffer), Qt))
store_xwidget_event_string (self.xw, "load-changed", ""); store_xwidget_event_string (self.xw, "load-changed", "load-finished");
}
- (void) webView:(WKWebView *)webView
didStartProvisionalNavigation:(WKNavigation *)navigation
{
if (EQ (Fbuffer_live_p (self.xw->buffer), Qt))
store_xwidget_event_string (self.xw, "load-changed", "load-started");
}
- (void) webView:(WKWebView *)webView
didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation
{
if (EQ (Fbuffer_live_p (self.xw->buffer), Qt))
store_xwidget_event_string (self.xw, "load-changed", "load-redirected");
}
/* Start loading WKWebView */
- (void) webView:(WKWebView *)webView
didCommitNavigation:(WKNavigation *)navigation
{
if (EQ (Fbuffer_live_p (self.xw->buffer), Qt))
store_xwidget_event_string (self.xw, "load-changed", "load-committed");
} }
- (void) webView:(WKWebView *)webView - (void) webView:(WKWebView *)webView
@ -114,7 +141,7 @@ - (void)webView:(WKWebView *)webView
decisionHandler (WKNavigationActionPolicyAllow); decisionHandler (WKNavigationActionPolicyAllow);
break; break;
default: default:
// decisionHandler (WKNavigationActionPolicyCancel); /* decisionHandler (WKNavigationActionPolicyCancel); */
decisionHandler (WKNavigationActionPolicyAllow); decisionHandler (WKNavigationActionPolicyAllow);
break; break;
} }
@ -343,6 +370,20 @@ - (void)userContentController:(WKUserContentController *)userContentController
} }
} }
double
nsxwidget_webkit_estimated_load_progress (struct xwidget *xw)
{
XwWebView *xwWebView = (XwWebView *) xw->xwWidget;
return xwWebView.estimatedProgress;
}
void
nsxwidget_webkit_stop_loading (struct xwidget *xw)
{
XwWebView *xwWebView = (XwWebView *) xw->xwWidget;
[xwWebView stopLoading];
}
void void
nsxwidget_webkit_zoom (struct xwidget *xw, double zoom_change) nsxwidget_webkit_zoom (struct xwidget *xw, double zoom_change)
{ {
@ -430,7 +471,7 @@ - (void)userContentController:(WKUserContentController *)userContentController
} }
else if (result && FUNCTIONP (fun)) else if (result && FUNCTIONP (fun))
{ {
// NSLog (@"result=%@, type=%@", result, [result class]); /* NSLog (@"result=%@, type=%@", result, [result class]); */
Lisp_Object lisp_value = js_to_lisp (result); Lisp_Object lisp_value = js_to_lisp (result);
store_xwidget_js_callback_event (xw, fun, lisp_value); store_xwidget_js_callback_event (xw, fun, lisp_value);
} }
@ -452,7 +493,8 @@ - (BOOL)isFlipped { return YES; }
NSRect rect = NSMakeRect (0, 0, xw->width, xw->height); NSRect rect = NSMakeRect (0, 0, xw->width, xw->height);
xw->xwWidget = [[XwWebView alloc] xw->xwWidget = [[XwWebView alloc]
initWithFrame:rect initWithFrame:rect
configuration:[[WKWebViewConfiguration alloc] init] configuration:[[[WKWebViewConfiguration alloc] init]
autorelease]
xwidget:xw]; xwidget:xw];
xw->xwWindow = [[XwWindow alloc] xw->xwWindow = [[XwWindow alloc]
initWithFrame:rect]; initWithFrame:rect];
@ -470,16 +512,18 @@ - (BOOL)isFlipped { return YES; }
((XwWebView *) xw->xwWidget).configuration.userContentController; ((XwWebView *) xw->xwWidget).configuration.userContentController;
[scriptor removeAllUserScripts]; [scriptor removeAllUserScripts];
[scriptor removeScriptMessageHandlerForName:@"keyDown"]; [scriptor removeScriptMessageHandlerForName:@"keyDown"];
[scriptor release];
if (xw->xv) if (xw->xv)
xw->xv->model = Qnil; /* Make sure related view stale. */ xw->xv->model = Qnil; /* Make sure related view stale. */
/* This stops playing audio when a xwidget-webkit buffer is /* This stops playing audio when a xwidget-webkit buffer is
killed. I could not find other solution. */ killed. I could not find other solution.
TODO: improve this */
nsxwidget_webkit_goto_uri (xw, "about:blank"); nsxwidget_webkit_goto_uri (xw, "about:blank");
[((XwWebView *) xw->xwWidget).urlScriptBlocked release]; [((XwWebView *) xw->xwWidget).urlScriptBlocked release];
[xw->xwWidget removeFromSuperviewWithoutNeedingDisplay]; [xw->xwWidget removeFromSuperviewWithoutNeedingDisplay];
[xw->xwWidget release]; [xw->xwWidget release];
[xw->xwWindow removeFromSuperviewWithoutNeedingDisplay]; [xw->xwWindow removeFromSuperviewWithoutNeedingDisplay];
[xw->xwWindow release]; [xw->xwWindow release];

View file

@ -3063,6 +3063,36 @@ DEFUN ("xwidget-webkit-title",
#endif #endif
} }
DEFUN ("xwidget-webkit-estimated-load-progress",
Fxwidget_webkit_estimated_load_progress, Sxwidget_webkit_estimated_load_progress,
1, 1, 0, doc: /* Get the estimated load progress of XWIDGET, a WebKit widget.
Return a value ranging from 0.0 to 1.0, based on how close XWIDGET
is to completely loading its page. */)
(Lisp_Object xwidget)
{
struct xwidget *xw;
#ifdef USE_GTK
WebKitWebView *webview;
#endif
double value;
CHECK_LIVE_XWIDGET (xwidget);
xw = XXWIDGET (xwidget);
CHECK_WEBKIT_WIDGET (xw);
block_input ();
#ifdef USE_GTK
webview = WEBKIT_WEB_VIEW (xw->widget_osr);
value = webkit_web_view_get_estimated_load_progress (webview);
#elif defined NS_IMPL_COCOA
value = nsxwidget_webkit_estimated_load_progress (xw);
#endif
unblock_input ();
return make_float (value);
}
DEFUN ("xwidget-webkit-goto-uri", DEFUN ("xwidget-webkit-goto-uri",
Fxwidget_webkit_goto_uri, Sxwidget_webkit_goto_uri, Fxwidget_webkit_goto_uri, Sxwidget_webkit_goto_uri,
2, 2, 0, 2, 2, 0,
@ -3810,28 +3840,6 @@ LIMIT is not specified or nil, it is treated as `50'. */)
return list3 (back, here, forward); return list3 (back, here, forward);
} }
DEFUN ("xwidget-webkit-estimated-load-progress",
Fxwidget_webkit_estimated_load_progress, Sxwidget_webkit_estimated_load_progress,
1, 1, 0, doc: /* Get the estimated load progress of XWIDGET, a WebKit widget.
Return a value ranging from 0.0 to 1.0, based on how close XWIDGET
is to completely loading its page. */)
(Lisp_Object xwidget)
{
struct xwidget *xw;
WebKitWebView *webview;
double value;
CHECK_LIVE_XWIDGET (xwidget);
xw = XXWIDGET (xwidget);
CHECK_WEBKIT_WIDGET (xw);
block_input ();
webview = WEBKIT_WEB_VIEW (xw->widget_osr);
value = webkit_web_view_get_estimated_load_progress (webview);
unblock_input ();
return make_float (value);
}
#endif #endif
DEFUN ("xwidget-webkit-set-cookie-storage-file", DEFUN ("xwidget-webkit-set-cookie-storage-file",
@ -3874,19 +3882,23 @@ This will stop any data transfer that may still be in progress inside
XWIDGET as part of loading a page. */) XWIDGET as part of loading a page. */)
(Lisp_Object xwidget) (Lisp_Object xwidget)
{ {
#ifdef USE_GTK
struct xwidget *xw; struct xwidget *xw;
#ifdef USE_GTK
WebKitWebView *webview; WebKitWebView *webview;
#endif
CHECK_LIVE_XWIDGET (xwidget); CHECK_LIVE_XWIDGET (xwidget);
xw = XXWIDGET (xwidget); xw = XXWIDGET (xwidget);
CHECK_WEBKIT_WIDGET (xw); CHECK_WEBKIT_WIDGET (xw);
block_input (); block_input ();
#ifdef USE_GTK
webview = WEBKIT_WEB_VIEW (xw->widget_osr); webview = WEBKIT_WEB_VIEW (xw->widget_osr);
webkit_web_view_stop_loading (webview); webkit_web_view_stop_loading (webview);
unblock_input (); #elif defined NS_IMPL_COCOA
nsxwidget_webkit_stop_loading (xw);
#endif #endif
unblock_input ();
return Qnil; return Qnil;
} }
@ -3936,8 +3948,9 @@ syms_of_xwidget (void)
#ifdef USE_GTK #ifdef USE_GTK
defsubr (&Sxwidget_webkit_load_html); defsubr (&Sxwidget_webkit_load_html);
defsubr (&Sxwidget_webkit_back_forward_list); defsubr (&Sxwidget_webkit_back_forward_list);
defsubr (&Sxwidget_webkit_estimated_load_progress);
#endif #endif
defsubr (&Sxwidget_webkit_estimated_load_progress);
defsubr (&Skill_xwidget); defsubr (&Skill_xwidget);
DEFSYM (QCxwidget, ":xwidget"); DEFSYM (QCxwidget, ":xwidget");