From: Qiantan Hong <qthong@stanford.edu>
To: Po Lu <luangruo@yahoo.com>, Andrew De Angelis <bobodeangelis@gmail.com>
Cc: "emacs-devel@gnu.org" <emacs-devel@gnu.org>
Subject: Re: [PATCH] Add user content APIs for WebKit Xwidgets
Date: Sun, 23 Oct 2022 09:11:39 +0000 [thread overview]
Message-ID: <B9632193-A02B-41C9-9443-C6B390A025AA@stanford.edu> (raw)
In-Reply-To: <877d10mfsw.fsf@yahoo.com>
[-- Attachment #1.1: Type: text/plain, Size: 1543 bytes --]
Hi Po,
I tried to fix these problems, and I've attached my updated patch.
Some remaining questions/issues:
1. I think that connecting signal to scriptor (now called manager)
doesn't require xw to be marked, because it is also destroyed when xw
is killed? Suppose that now I reference count correctly, manager
should be owned by xw, just like the WebKitWebContext at line 363.
2. I didn't fix the ARC assumption in NS port. I hope it can be fixed
in one batch by Andrew. Thank you Andrew!
Best,
Qiantan
> On Oct 15, 2022, at 11:41 PM, Po Lu <luangruo@yahoo.com> wrote:
>
> Qiantan Hong <qthong@stanford.edu> writes:
>
>> Yes I’m aware. I was fixing them one by one.
>
> Thanks.
>
>> It seems that existing code is connecting signal without adding the marking
>> code, guess that should be fixed too...
>
> Where? Existing code should not connect signals to anything other than
> `widget_osr' which is destroyed upon the xwidget being killed, a
> prerequisite for being marked by GC.
>
>> Those two problems above, I don’t have any existing code to imitate, so it
>> would take a while to learn the codebase for me to be able to fix them.
>> I’m also not sure if I should just make my part conforming or also fix all existing code.
>> Is it acceptable that I submit a patch (with other problems fixed) first,
>> and work on fixing these two classes of problems later?
>
> I'd rather not install code with known memory management issues,
> especially not this close to the Emacs 29 release.
[-- Attachment #1.2: Type: text/html, Size: 2196 bytes --]
[-- Attachment #2: 0001-Implement-WebKit-user-scripts-and-script-message-han.txt --]
[-- Type: text/plain, Size: 20864 bytes --]
From fb375e5e3582a5c9cfe3d11c1036fe9affe1b12f Mon Sep 17 00:00:00 2001
From: Qiantan Hong <qhong@alum.mit.edu>
Date: Sun, 23 Oct 2022 01:55:53 -0700
Subject: [PATCH] Implement WebKit user scripts and script message handlers.
* src/xwidget.h (store_xwidget_script_message_event): store script
message event into event queue
* src/xwidget.c (store_xwidget_script_message_event):
(Fxwidget_webkit_add_user_script):
(Fxwidget_webkit_remove_all_user_scripts): user script primitives
(Fxwidget_webkit_register_script_message):
(Fxwidget_webkit_unregister_script_message): script message handler
primitives.
* src/nsxwidget.c (nsxwidget_webkit_add_user_script):
(nsxwidget_webkit_remove_all_user_scripts):
(nsxwidget_webkit_register_script_message):
(nsxwidget_webkit_unregister_script_message): NS implementation of
user script and script message handler. Changed naming of a previous
used script message handler to avoid namespace pollution.
* src/nsxwidget.h (nsxwidget_webkit_add_user_script):
(nsxwidget_webkit_remove_all_user_scripts):
(nsxwidget_webkit_register_script_message):
(nsxwidget_webkit_unregister_script_message):
* lisp/xwidget.el (xwidget-webkit-callback):
(xwidget-webkit-push-script-message-handler):
(xwidget-webkit-pop-script-message-handler): let lisp recognize and
dispatch script message events
* doc/lispref/display.texi: document user script and script message
handler
---
doc/lispref/display.texi | 52 +++++++++++
lisp/xwidget.el | 36 +++++++-
src/nsxwidget.h | 5 +
src/nsxwidget.m | 80 ++++++++++++++--
src/xwidget.c | 192 +++++++++++++++++++++++++++++++++++++++
src/xwidget.h | 4 +
6 files changed, 361 insertions(+), 8 deletions(-)
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 15cd5518d9..48b38ff837 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -7279,6 +7279,58 @@ Xwidgets
@var{default} was omitted.
@end defun
+@defun xwidget-webkit-add-user-script xwidget script when main-frame-only
+This function adds the specified user script @code{script} to the
+browser widget specified by @var{xwidget}.
+
+User scripts are custom JavaScript code that is automatically run in
+the pages of the browser widget. The @var{when} argument specifies
+when @var{script} is run, it can be one of the following:
+
+@table @code
+@item start
+@var{script} is run upon first loading a document.
+@item end
+@var{script} is run after a document loads.
+@end table
+
+The @var{main-frame-only} argument specifies which HTML frames run
+@var{script}. If @var{main-frame-only} is @code{nil}, @var{script} is
+run in all HTML frames. Otherwise, @var{script} is only run in
+top-level HTML frames.
+@end defun
+
+@defun xwidget-webkit-remove-all-user-scripts xwidget
+This functions removes all user scripts from the browser widget
+specified by @var{xwidget}.
+@end defun
+
+@defun xwidget-webkit-push-script-message-handler xwidget name handler
+This function registers @var{handler} to handle script messages with
+namespace specified by string @var{name} for the browser widget
+specified by @var{xwidget}.
+
+Script message enables JavaScript code run in browser widgets to pass
+data to Emacs. After @var{handler} is registered with @var{name},
+running the following JavaScript code
+
+@example
+window.webkit.messageHandlers.@var{name}.postMessage(@var{JSObject});
+@end example
+
+@noindent causes @var{handler} to be called with two arguments: @var{xwidget}
+and @var{JSObject} converted to a Lisp object.
+@end defun
+
+@defun xwidget-webkit-pop-script-message-handler
+This functions removes a handler registered with namespace specified
+by string @var{name} for the browser widget specified by
+@var{xwidget}.
+
+The returned value is the removed handler function, or @code{nil} if
+no such handler is found.
+@end defun
+
@defun xwidget-webkit-get-title xwidget
This function returns the title of @var{xwidget} as a string.
@end defun
diff --git a/lisp/xwidget.el b/lisp/xwidget.el
index 41a1190c64..418a9f3acc 100644
--- a/lisp/xwidget.el
+++ b/lisp/xwidget.el
@@ -485,7 +485,41 @@ xwidget-webkit-callback
(let ((proc (nth 3 last-input-event))
(arg (nth 4 last-input-event)))
(funcall proc arg)))
- (t (xwidget-log "unhandled event:%s" xwidget-event-type)))))
+ ((eq xwidget-event-type 'script-message)
+ (let ((name (nth 3 last-input-event))
+ (value (nth 4 last-input-event)))
+ (let ((handler-pair (assoc name (xwidget-get xwidget 'script-message-handlers))))
+ (if handler-pair
+ (funcall (cdr handler-pair) xwidget value)
+ (xwidget-log "unhandled script message: %s" name)))))
+ (t (xwidget-log "unhandled event: %s" xwidget-event-type)))))
+
+(defun xwidget-webkit-push-script-message-handler (xwidget name handler)
+ "Register HANDLER to handle script messages with NAME for WebKit XWIDGET.
+
+HANDLER will be called with two arguments: the WebKit XWIDGET and
+the JavaScript object passed from the script message converted to
+a Lisp object."
+ (let ((old-alist (xwidget-get xwidget 'script-message-handlers)))
+ (unless (assoc name old-alist)
+ (xwidget-webkit-register-script-message (xwidget-webkit-current-session) name))
+ (xwidget-put xwidget 'script-message-handlers
+ (cons (cons name handler) old-alist)))
+ name)
+
+(defun xwidget-webkit-pop-script-message-handler (xwidget name)
+ "Remove a handler registered with NAME for WebKit XWIDGET.
+
+Return the removed handler function, or NIL if no such handler is
+found."
+ (let* ((old-alist (xwidget-get xwidget 'script-message-handlers))
+ (handler-pair (assoc name old-alist)))
+ (when handler-pair
+ (let ((new-alist (delq handler-pair old-alist)))
+ (xwidget-put xwidget 'script-message-handlers new-alist)
+ (unless (assoc name new-alist)
+ (xwidget-webkit-unregister-script-message (xwidget-webkit-current-session) name)))
+ (cdr handler-pair))))
(defvar bookmark-make-record-function)
(when (memq window-system '(mac ns))
diff --git a/src/nsxwidget.h b/src/nsxwidget.h
index 666509744a..cd1dc1bc2c 100644
--- a/src/nsxwidget.h
+++ b/src/nsxwidget.h
@@ -40,6 +40,11 @@ #define NSXWIDGET_H_INCLUDED
void nsxwidget_webkit_execute_script (struct xwidget *xw, const char *script,
Lisp_Object fun);
+void nsxwidget_webkit_add_user_script (struct xwidget *xw, const char *script,
+ int injection_time_start, int main_frame_only);
+void nsxwidget_webkit_remove_all_user_scripts (struct xwidget *xw);
+Lisp_Object nsxwidget_webkit_register_script_message (struct xwidget *xw, const char *name);
+void nsxwidget_webkit_unregister_script_message (struct xwidget *xw, const char *name);
/* Functions for xwidget model. */
#ifdef __OBJC__
diff --git a/src/nsxwidget.m b/src/nsxwidget.m
index be0eba0bcb..901277f9a3 100644
--- a/src/nsxwidget.m
+++ b/src/nsxwidget.m
@@ -88,7 +88,7 @@ - (id)initWithFrame:(CGRect)frame
@"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)"
@" AppleWebKit/603.3.8 (KHTML, like Gecko)"
@" Version/11.0.1 Safari/603.3.8";
- [scriptor addScriptMessageHandler:self name:@"keyDown"];
+ [scriptor addScriptMessageHandler:self name:@"__xwidget_internal_keyDown"];
[scriptor addUserScript:[[WKUserScript alloc]
initWithSource:xwScript
injectionTime:
@@ -275,23 +275,34 @@ + (void)initialize
@"}"
@"function xwKeyDown(event) {"
@" if (event.ctrlKey && event.key == 'g') {"
- @" window.webkit.messageHandlers.keyDown.postMessage('C-g');"
+ @" window.webkit.messageHandlers.__xwidget_internal_keyDown.postMessage('C-g');"
@" }"
@"}"
@"document.addEventListener('keydown', xwKeyDown);"
;
}
+static Lisp_Object js_to_lisp (id value);
+
/* Confirming to WKScriptMessageHandler, listens concerning keyDown in
webkit. Currently 'C-g'. */
- (void)userContentController:(WKUserContentController *)userContentController
didReceiveScriptMessage:(WKScriptMessage *)message
{
- if ([message.body isEqualToString:@"C-g"])
+ if ([message.name isEqualToString:@"__xwidget_internal_keyDown"])
{
- /* Just give up focus, no relay "C-g" to emacs, another "C-g"
- follows will be handled by emacs. */
- [self.window makeFirstResponder:self.xw->xv->emacswindow];
+ if ([message.body isEqualToString:@"C-g"])
+ {
+ /* Just give up focus, no relay "C-g" to emacs, another "C-g"
+ follows will be handled by emacs. */
+ [self.window makeFirstResponder:self.xw->xv->emacswindow];
+ }
+ }
+ else
+ {
+ store_xwidget_script_message_event (self.xw,
+ message.name.UTF8String,
+ js_to_lisp (message.body));
}
}
@@ -437,6 +448,61 @@ - (void)userContentController:(WKUserContentController *)userContentController
}];
}
+void
+nsxwidget_webkit_add_user_script (struct xwidget *xw, const char *script,
+ int injection_time_start, int main_frame_only)
+{
+ XwWebView *xwWebView = (XwWebView *) xw->xwWidget;
+ WKUserContentController *scriptor = xwWebView.configuration.userContentController;
+
+ NSString *javascriptString = [NSString stringWithUTF8String:script];
+ WKUserScriptInjectionTime injectionTime = injection_time_start?
+ WKUserScriptInjectionTimeAtDocumentStart : WKUserScriptInjectionTimeAtDocumentEnd;
+ WKUserScript *userScript = [[WKUserScript alloc]
+ initWithSource: javascriptString
+ injectionTime: injectionTime
+ forMainFrameOnly: main_frame_only];
+ [scriptor addUserScript: userScript];
+}
+
+void
+nsxwidget_webkit_remove_all_user_scripts (struct xwidget *xw)
+{
+ XwWebView *xwWebView = (XwWebView *) xw->xwWidget;
+ WKUserContentController *scriptor = xwWebView.configuration.userContentController;
+
+ [scriptor removeAllUserScripts];
+}
+
+Lisp_Object
+nsxwidget_webkit_register_script_message (struct xwidget *xw, const char *name)
+{
+ XwWebView *xwWebView = (XwWebView *) xw->xwWidget;
+ WKUserContentController *scriptor = xwWebView.configuration.userContentController;
+
+ NSString *messageName = [NSString stringWithUTF8String:name];
+
+ @try
+ {
+ [scriptor addScriptMessageHandler:xwWebView name:messageName];
+ }
+ @catch (NSException *e)
+ {
+ error ("Failed to register WebKit script message handler");
+ }
+ return Qnil;
+}
+
+void
+nsxwidget_webkit_unregister_script_message (struct xwidget *xw, const char *name)
+{
+ XwWebView *xwWebView = (XwWebView *) xw->xwWidget;
+ WKUserContentController *scriptor = xwWebView.configuration.userContentController;
+
+ NSString *messageName = [NSString stringWithUTF8String:name];
+ [scriptor removeScriptMessageHandlerForName:messageName];
+}
+
/* Window containing an xwidget. */
@implementation XwWindow
@@ -469,7 +535,7 @@ - (BOOL)isFlipped { return YES; }
WKUserContentController *scriptor =
((XwWebView *) xw->xwWidget).configuration.userContentController;
[scriptor removeAllUserScripts];
- [scriptor removeScriptMessageHandlerForName:@"keyDown"];
+ [scriptor removeScriptMessageHandlerForName:@"__xwidget_internal_keyDown"];
[scriptor release];
if (xw->xv)
xw->xv->model = Qnil; /* Make sure related view stale. */
diff --git a/src/xwidget.c b/src/xwidget.c
index 8bdfab02fd..3cdd95f970 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -126,6 +126,11 @@ webkit_decide_policy_cb (WebKitWebView *,
};
static void find_widget (GtkWidget *t, struct widget_search_data *);
+
+static void webkit_script_message_cb (WebKitUserContentManager *,
+ WebKitJavascriptResult *,
+ gpointer);
+
#endif
#ifdef HAVE_PGTK
@@ -380,6 +385,9 @@ DEFUN ("make-xwidget",
settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (xw->widget_osr));
g_object_set (G_OBJECT (settings), "enable-developer-extras", TRUE, NULL);
}
+ WebKitUserContentManager *manager = webkit_user_content_manager_new ();
+ xw->widget_osr = webkit_web_view_new_with_user_content_manager (manager);
+ g_object_unref (manager);
gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width,
xw->height);
@@ -2308,6 +2316,21 @@ store_xwidget_js_callback_event (struct xwidget *xw,
kbd_buffer_store_event (&event);
}
+void
+store_xwidget_script_message_event (struct xwidget *xw,
+ const char *name,
+ Lisp_Object body)
+{
+ struct input_event event;
+ Lisp_Object xwl;
+ XSETXWIDGET (xwl, xw);
+ EVENT_INIT (event);
+ event.kind = XWIDGET_EVENT;
+ event.frame_or_window = Qnil;
+ event.arg = list4 (Qscript_message, xwl, build_string (name), body);
+ kbd_buffer_store_event (&event);
+}
+
#ifdef USE_GTK
static void
@@ -2622,6 +2645,21 @@ webkit_decide_policy_cb (WebKitWebView *webView,
}
}
+static void
+webkit_script_message_cb (WebKitUserContentManager *manager,
+ WebKitJavascriptResult *js_result,
+ gpointer data)
+{
+ struct xwidget *xw = g_object_get_data (G_OBJECT (manager),
+ XG_XWIDGET);
+ JSCValue *value = webkit_javascript_result_get_js_value (js_result);
+ const char *arg = data;
+ Lisp_Object lisp_value = webkit_js_to_lisp (value);
+ store_xwidget_script_message_event (xw, arg, lisp_value);
+
+ webkit_javascript_result_unref (js_result);
+}
+
static gboolean
webkit_script_dialog_cb (WebKitWebView *webview,
WebKitScriptDialog *script_dialog,
@@ -3198,6 +3236,151 @@ DEFUN ("xwidget-webkit-execute-script",
return Qnil;
}
+DEFUN ("xwidget-webkit-add-user-script",
+ Fxwidget_webkit_add_user_script, Sxwidget_webkit_add_user_script,
+ 4, 4, 0,
+ doc: /* Add the user script SCRIPT to the WebKit XWIDGET.
+
+WHEN is one of the following values, and specifies when the script is
+run:
+- `start', which means the script is run upon first loading a document.
+- `end', which means the script is run after a document loads.
+
+If MAIN_FRAME_ONLY is nil, SCRIPT is run in all HTML frames.
+Otherwise, SCRIPT is only run in top-level HTML frames. */)
+ (Lisp_Object xwidget, Lisp_Object script,
+ Lisp_Object when, Lisp_Object main_frame_only)
+{
+ WEBKIT_FN_INIT ();
+ CHECK_STRING (script);
+ CHECK_SYMBOL (when);
+
+ script = ENCODE_UTF_8 (script);
+
+ Bool start;
+ if (EQ (when, Qstart))
+ start = true;
+ else if (EQ (when, Qend))
+ start = false;
+ else
+ error ("Unknown Xwidget Webkit user script injection time: %s",
+ SDATA (SYMBOL_NAME (when)));
+
+#ifdef USE_GTK
+ WebKitWebView *view = WEBKIT_WEB_VIEW (xw->widget_osr);
+ WebKitUserContentManager *manager = webkit_web_view_get_user_content_manager (view);
+
+ WebKitUserContentInjectedFrames webkit_injected_frames
+ = (!NILP (main_frame_only))
+ ? WEBKIT_USER_CONTENT_INJECT_TOP_FRAME
+ : WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES;
+ WebKitUserScriptInjectionTime webkit_injection_time = start
+ ? WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START
+ : WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END;
+ WebKitUserScript *user_script
+ = webkit_user_script_new (SSDATA (script),
+ webkit_injected_frames,
+ webkit_injection_time,
+ NULL, NULL);
+ webkit_user_content_manager_add_script (manager, user_script);
+ webkit_user_script_unref (user_script);
+#elif defined NS_IMPL_COCOA
+ nsxwidget_webkit_add_user_script (xw, SSDATA (script), injection_time_start, mfo);
+#endif
+ return Qnil;
+}
+
+DEFUN ("xwidget-webkit-remove-all-user-scripts",
+ Fxwidget_webkit_remove_all_user_scripts, Sxwidget_webkit_remove_all_user_scripts,
+ 1, 1, 0,
+ doc: /* Remove all user scripts from WebKit XWIDGET. */)
+ (Lisp_Object xwidget)
+{
+ WEBKIT_FN_INIT ();
+
+#ifdef USE_GTK
+ WebKitWebView *view = WEBKIT_WEB_VIEW (xw->widget_osr);
+ WebKitUserContentManager *manager = webkit_web_view_get_user_content_manager (view);
+
+ webkit_user_content_manager_remove_all_scripts (manager);
+#elif defined NS_IMPL_COCOA
+ nsxwidget_webkit_remove_all_user_scripts(xw);
+#endif
+ return Qnil;
+}
+
+DEFUN ("xwidget-webkit-register-script-message",
+ Fxwidget_webkit_register_script_message, Sxwidget_webkit_register_script_message,
+ 2, 2, 0,
+ doc: /* Register script message with NAME in WebKit XWIDGET.
+
+This operation fails if NAME has already been registered for XWIDGET. */)
+ (Lisp_Object xwidget, Lisp_Object name)
+{
+ WEBKIT_FN_INIT ();
+ CHECK_STRING (name);
+ char *sname = xlispstrdup (name);
+
+#ifdef USE_GTK
+ WebKitWebView *view = WEBKIT_WEB_VIEW (xw->widget_osr);
+ WebKitUserContentManager *manager = webkit_web_view_get_user_content_manager (view);
+
+ USE_SAFE_ALLOCA;
+ gchar *signal_name = SAFE_ALLOCA (strlen ("script-message-received::") + strlen (sname) + 1);
+ stpcpy (stpcpy (signal_name, "script-message-received::"), sname);
+ g_signal_connect_data (manager, signal_name, G_CALLBACK (webkit_script_message_cb),
+ sname, (GClosureNotify) xfree, 0);
+ SAFE_FREE ();
+
+ if (webkit_user_content_manager_register_script_message_handler (manager, sname))
+ {
+ g_object_set_data (G_OBJECT (manager), XG_XWIDGET, xw);
+ }
+ else
+ {
+ g_signal_handlers_disconnect_matched (manager,
+ G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, sname);
+ error ("Failed to register WebKit script message handler");
+ }
+#elif defined NS_IMPL_COCOA
+ nsxwidget_webkit_register_script_message (xw, sname);
+ xfree (sname);
+#endif
+ return Qnil;
+}
+
+DEFUN ("xwidget-webkit-unregister-script-message",
+ Fxwidget_webkit_unregister_script_message, Sxwidget_webkit_unregister_script_message,
+ 2, 2, 0,
+ doc: /* Unregister script message with NAME in Webkit XWIDGET. */)
+ (Lisp_Object xwidget, Lisp_Object name)
+{
+ WEBKIT_FN_INIT ();
+ CHECK_STRING (name);
+
+ USE_SAFE_ALLOCA;
+ char *sname;
+ SAFE_ALLOCA_STRING (sname, name);
+
+#ifdef USE_GTK
+ WebKitWebView *view = WEBKIT_WEB_VIEW (xw->widget_osr);
+ WebKitUserContentManager *manager
+ = webkit_web_view_get_user_content_manager (view);
+
+ webkit_user_content_manager_unregister_script_message_handler (manager, sname);
+ g_signal_handlers_disconnect_matched (manager,
+ G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DETAIL,
+ 0, g_quark_from_string (sname), 0,
+ G_CALLBACK (webkit_script_message_cb), 0);
+#elif defined NS_IMPL_COCOA
+ nsxwidget_webkit_unregister_script_message(xw, sname);
+#endif
+
+ SAFE_FREE();
+ return Qnil;
+}
+
DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0,
doc: /* Resize XWIDGET to NEW_WIDTH, NEW_HEIGHT. */ )
(Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height)
@@ -3919,6 +4102,15 @@ syms_of_xwidget (void)
defsubr (&Sxwidget_webkit_execute_script);
DEFSYM (Qwebkit, "webkit");
+ defsubr (&Sxwidget_webkit_add_user_script);
+ DEFSYM (Qstart, "start");
+ DEFSYM (Qend, "end");
+ defsubr (&Sxwidget_webkit_remove_all_user_scripts);
+
+ DEFSYM (Qscript_message, "script-message");
+ defsubr (&Sxwidget_webkit_register_script_message);
+ defsubr (&Sxwidget_webkit_unregister_script_message);
+
defsubr (&Sxwidget_size_request);
defsubr (&Sdelete_xwidget_view);
diff --git a/src/xwidget.h b/src/xwidget.h
index 502beb6765..e835f700bc 100644
--- a/src/xwidget.h
+++ b/src/xwidget.h
@@ -203,6 +203,10 @@ #define XG_XWIDGET_VIEW "emacs_xwidget_view"
Lisp_Object proc,
Lisp_Object argument);
+void store_xwidget_script_message_event (struct xwidget *xw,
+ const char *name,
+ Lisp_Object value);
+
extern struct xwidget *xwidget_from_id (uint32_t id);
#ifdef HAVE_X_WINDOWS
--
2.32.1 (Apple Git-133)
next prev parent reply other threads:[~2022-10-23 9:11 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-14 6:34 [PATCH] Add user content APIs for WebKit Xwidgets Qiantan Hong
2022-10-14 7:01 ` Po Lu
2022-10-14 7:12 ` Qiantan Hong
2022-10-14 7:35 ` Po Lu
2022-10-14 21:13 ` Qiantan Hong
2022-10-15 1:37 ` Qiantan Hong
2022-10-15 7:53 ` Qiantan Hong
2022-10-15 11:23 ` Po Lu
2022-10-15 18:29 ` Qiantan Hong
2022-10-16 0:26 ` Po Lu
2022-10-15 23:33 ` Qiantan Hong
2022-10-16 4:32 ` Po Lu
2022-10-16 6:29 ` Qiantan Hong
2022-10-16 6:41 ` Po Lu
2022-10-16 6:45 ` Po Lu
2022-10-23 9:11 ` Qiantan Hong [this message]
2022-10-23 10:58 ` Po Lu
2022-10-23 22:16 ` Qiantan Hong
2022-10-24 0:30 ` Po Lu
2022-10-24 4:17 ` Qiantan Hong
2022-10-24 5:38 ` Po Lu
2022-10-24 5:44 ` Qiantan Hong
2022-10-24 7:20 ` Po Lu
2022-10-16 20:51 ` [PATCH] Add user extension " Richard Stallman
2022-10-16 21:13 ` Alan Mackenzie
2022-10-18 11:58 ` Richard Stallman
2022-10-17 5:31 ` Eli Zaretskii
2022-10-17 8:28 ` Jean Louis
2022-10-19 17:04 ` Richard Stallman
2022-10-19 19:06 ` Eli Zaretskii
2022-10-20 19:46 ` Richard Stallman
2022-10-21 5:51 ` Eli Zaretskii
2022-10-21 6:02 ` Po Lu
2022-10-23 19:14 ` Richard Stallman
-- strict thread matches above, loose matches on Subject: below --
2020-08-28 2:25 [PATCH] Add user content " Qiantan Hong
2020-08-28 14:37 ` Lars Ingebrigtsen
2020-08-28 15:41 ` Qiantan Hong
2020-08-30 13:43 ` Lars Ingebrigtsen
2020-08-29 4:07 ` Richard Stallman
2020-08-29 4:10 ` Richard Stallman
2020-08-29 4:45 ` Qiantan Hong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=B9632193-A02B-41C9-9443-C6B390A025AA@stanford.edu \
--to=qthong@stanford.edu \
--cc=bobodeangelis@gmail.com \
--cc=emacs-devel@gnu.org \
--cc=luangruo@yahoo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.