From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Po Lu Newsgroups: gmane.emacs.devel Subject: Introduce "killed" state for xwidgets (Re: shr using `make-xwidget' incorrectly) Date: Thu, 11 Nov 2021 14:37:49 +0800 Message-ID: <87tugjxkn6.fsf_-_@yahoo.com> References: <87sfw31mok.fsf.ref@yahoo.com> <87sfw31mok.fsf@yahoo.com> <87fss3e5kc.fsf@gnus.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="28302"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.60 (gnu/linux) Cc: emacs-devel@gnu.org To: Lars Ingebrigtsen Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Thu Nov 11 07:46:47 2021 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1ml3rC-0007Bf-Vh for ged-emacs-devel@m.gmane-mx.org; Thu, 11 Nov 2021 07:46:47 +0100 Original-Received: from localhost ([::1]:43190 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ml3rB-0003DC-RY for ged-emacs-devel@m.gmane-mx.org; Thu, 11 Nov 2021 01:46:45 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:54588) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ml3ik-0000i0-TU for emacs-devel@gnu.org; Thu, 11 Nov 2021 01:38:02 -0500 Original-Received: from sonic316-22.consmr.mail.ne1.yahoo.com ([66.163.187.148]:37963) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ml3ih-0008Be-9m for emacs-devel@gnu.org; Thu, 11 Nov 2021 01:38:02 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1636612677; bh=KG9sgb/onGKmJmjPiJI579ri3T1NmchTh1z+WLJcjv4=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From:Subject:Reply-To; b=XrwtnpVL3/ZvCS6sZwqqO+BieCclcHyARAeK7DDNlHfrmLE2BLZ7ANkixz6SZP2cbpEW4fnLU54ax4d5d5DGi/bnJtk04H7JTaogb2Xh/GMR6qBqRWKUuuhZ08+ALduYZtixqykAZ5XSlFpKx29alHAYtDDVkymIk6mBzy1RO6fgwD579f+WhsK8i30NoaewTQtix6GQHAYxEWJbWeBvrc11X1/zDa0pm7TNfev3WCRnOqkvlggUrQyx3F5tL/qEefpYXJ8lAD1AF0dR+ZWyLmTe1v8wuR/IRUUdoin8SlL9UTu4KC2OXjOHXbYkhqAHRb1ZOJ/syy7ZDLhiYTJiyg== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1636612677; bh=mVyxSL1J2hfoGv28nZMJwYitN+yjQDDbCJY4iQ/Y8YY=; h=X-Sonic-MF:From:To:Subject:Date:From:Subject; b=lZdV3nC3Vk6C657HzHU7RD0NRTd1UACRwF5uk3N/psZgog87cIXhxFnrnYwsE97eixs+ZiZ1K0N6Nir6Ru6AmJS+M9Go0gCmmXljPmn/hmUqV34QmoX6Ml2WByysnR6txfWh9BiLXVtPR3ubcozY1+MjcM/gh3lr5hkbuleKNylyYCJuVo7uLMqOkPp/fqcdtFDrCDOBafkmWCqB0m16AaliYVYMnTCm2y+PmltaGGGME0o4TfUIZ0YCZZkT4ZsoGNhCh44Y/fNWpL/d6i3/0ygzYpI3tXfH/lxmNicgYVBRFU+8vPM1il97AzXmw5w1VLmBaKGJBgvuNgQzkhjcsQ== X-YMail-OSG: BRu1yQoVM1mqbL7F0rUVatruthmxSkxaFFj5uC_15bxtGnh75gmXO9DRq.b2Dm6 fH.wZFbthtZn21.pBTmcuJp5kwkklbsWARbuCgyGxoFcds40u66xbgLPo5WDehw5IeKgYSmU.0qz rf3AzxwPDV.RKTqSp.n9REPEhNWx0SBFRIR7kxvqohvySEkYCbopTINe0tgrpRQ38QB8PXp.k0v7 AY9zJ0hKGzSEllplys5SGByULan9yc2hY3CgW293bGLLRXHzgA2nkdAmKaNY.W_UANIBonRqhNuh C4cVS0qli865ng865kGMrihewioogGe8S7Bj32stCFgyVQeFwuEbL1X.tFfpnbk.vIbWMD.6j3t3 bU_2u_0tTGQlEXHLvW5L_kFKZPLC698of_mNkwnaMFNxbclYwm8xLYlmQL.kjPZyJBPymsWcvt68 0pOIIja4V4wIOdCjccUmkAiWgkirDG63EgXts4I8YyNhY3GUT8w4rdO40fMlGMge7C7yIWuuJAdi sa9Giawo6RxaqtD4XEbr.F8BO4l3vgzAbF7YxsleJZ2l.w.wG76Gvcn9SWPkiHFGOCgtbQgknT9n 0KTTuZ0VStdCDRdImRhAqU996xRhGsIzca8685ViGLsB5ToEB7zu_.nnnP0ZrN31G5aaNfyvD0KL wItQ1WIPGpuVD3PH5tuLIj5PtUxKwSTqGpycT2UlBTBwMQYQl.gkO6kmoCT97RKckwVSvEWVCZuU jy5bvvzNd5g.EEfBv5ezZZDcybO1c6EwQtUnTIYY1k7V7bIbGkzHcemfbTjH5RjtjS2HZnKYUdU. LZCtXdllYzi3LVNjf4ZKHwN4Z1RPTZXK2GyetsCjkJ X-Sonic-MF: Original-Received: from sonic.gate.mail.ne1.yahoo.com by sonic316.consmr.mail.ne1.yahoo.com with HTTP; Thu, 11 Nov 2021 06:37:57 +0000 Original-Received: by kubenode508.mail-prod1.omega.sg3.yahoo.com (VZM Hermes SMTP Server) with ESMTPA ID 8a787bc206eb185385667a516a962ad5; Thu, 11 Nov 2021 06:37:52 +0000 (UTC) In-Reply-To: <87fss3e5kc.fsf@gnus.org> (Lars Ingebrigtsen's message of "Thu, 11 Nov 2021 04:26:11 +0100") X-Mailer: WebService/1.1.19306 mail.backend.jedi.jws.acl:role.jedi.acl.token.atz.jws.hermes.yahoo Received-SPF: pass client-ip=66.163.187.148; envelope-from=luangruo@yahoo.com; helo=sonic316-22.consmr.mail.ne1.yahoo.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:279224 Archived-At: --=-=-= Content-Type: text/plain Lars Ingebrigtsen writes: >> I think the best thing to do in this case would be to introduce a >> `dead' state for xwidgets, not unlike killed buffers and dead frames, >> which an xwidget is set to after being killed. >> >> Then, performing any sort of operation on a killed xwidget can either >> throw an error, or do nothing. > Sounds good to me. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Prevent-crashes-in-xwidgets-whose-buffers-have-been-.patch >From 7db8a74c8eb463db9b4db20fb5c3964b28f1c521 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Thu, 11 Nov 2021 14:29:12 +0800 Subject: [PATCH] Prevent crashes in xwidgets whose buffers have been killed * doc/lispref/display.texi (Xwidgets): Explain meaning of killed xwidgets. * src/xwidget.c (Fxwidget_live_p): New function. (Fxwidget_perform_lispy_event, WEBKIT_FN_INIT) (Fxwidget_resize, Fxwidget_size_request) (Fxwidget_info, Fxwidget_plist) (Fset_xwidget_buffer, Fset_xwidget_plist) (Fset_xwidget_query_on_exit_flag) (Fxwidget_query_on_exit_flag) (Fxwidget_webkit_search) (Fxwidget_webkit_next_result) (Fxwidget_webkit_previous_result) (Fxwidget_webkit_finish_search) (Fxwidget_webkit_load_html): Check for live xwidgets instead of just xwidgets. (xwidget_button, xwidget_motion_or_crossing) (xv_do_draw, x_draw_xwidget_glyph_string) (Fdelete_xwidget_view): Ignore killed xwidgets. (syms_of_xwidget): Define new symbols and subrs and define appropriate weakness of id_to_xwidget map. (kill_buffer_xwidgets): Check live xwidgets instead of killed xwidgets, set xwidget buffer to nil, and rely on GC to free the hash table for us instead. * src/xwidget.h (XWIDGET_LIVE_P, CHECK_LIVE_XWIDGET): New macros. --- doc/lispref/display.texi | 14 ++++- src/xwidget.c | 116 +++++++++++++++++++++++++++------------ src/xwidget.h | 7 +++ 3 files changed, 101 insertions(+), 36 deletions(-) diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 094bb5a5f3..63d2838eaa 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -6804,6 +6804,12 @@ Xwidgets is used internally by the WebKit widget, and specifies another WebKit widget that the newly created widget should share settings and subprocesses with. + +The xwidget that is returned will be killed alongside its buffer +(@pxref{Killing Buffers}). Once it is killed, the xwidget may +continue to exist as a Lisp object and act as a @code{display} +property until all references to it are gone, but most actions that +can be performed on live xwidgets will no longer be available. @end defun @defun xwidgetp object @@ -6811,6 +6817,11 @@ Xwidgets @code{nil} otherwise. @end defun +@defun xwidget-live-p object +This function returns @code{t} if @var{object} is an xwidget that +hasn't been killed, and @code{nil} otherwise. +@end defun + @defun xwidget-plist xwidget This function returns the property list of @var{xwidget}. @end defun @@ -6821,7 +6832,8 @@ Xwidgets @end defun @defun xwidget-buffer xwidget -This function returns the buffer of @var{xwidget}. +This function returns the buffer of @var{xwidget}. If @var{xwidget} +has been killed, it returns @code{nil}. @end defun @defun set-xwidget-buffer xwidget buffer diff --git a/src/xwidget.c b/src/xwidget.c index ace63e3742..4c18c531b9 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -273,6 +273,16 @@ DEFUN ("make-xwidget", return val; } +DEFUN ("xwidget-live-p", Fxwidget_live_p, Sxwidget_live_p, + 1, 1, 0, doc: /* Return t if OBJECT is an xwidget that has not been killed. +Value is nil if OBJECT is not an xwidget or if it has been killed. */) + (Lisp_Object object) +{ + return ((XWIDGETP (object) + && !NILP (XXWIDGET (object)->buffer)) + ? Qt : Qnil); +} + #ifdef USE_GTK static void set_widget_if_text_view (GtkWidget *widget, void *data) @@ -305,7 +315,7 @@ DEFUN ("xwidget-perform-lispy-event", GtkWidget *temp = NULL; #endif - CHECK_XWIDGET (xwidget); + CHECK_LIVE_XWIDGET (xwidget); xw = XXWIDGET (xwidget); if (!NILP (frame)) @@ -807,6 +817,9 @@ xwidget_button (struct xwidget_view *view, bool down_p, int x, int y, int button, int modifier_state, Time time) { + if (NILP (XXWIDGET (view->model)->buffer)) + return; + record_osr_embedder (view); if (button < 4 || button > 8) @@ -857,22 +870,29 @@ xwidget_button (struct xwidget_view *view, void xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event) { - GdkEvent *xg_event = gdk_event_new (event->type == MotionNotify - ? GDK_MOTION_NOTIFY - : (event->type == LeaveNotify - ? GDK_LEAVE_NOTIFY - : GDK_ENTER_NOTIFY)); + GdkEvent *xg_event; struct xwidget *model = XXWIDGET (view->model); int x; int y; - GtkWidget *target = find_widget_at_pos (model->widgetwindow_osr, - (event->type == MotionNotify - ? event->xmotion.x + view->clip_left - : event->xcrossing.x + view->clip_left), - (event->type == MotionNotify - ? event->xmotion.y + view->clip_top - : event->xcrossing.y + view->clip_top), - &x, &y); + GtkWidget *target; + + if (NILP (model->buffer)) + return; + + xg_event = gdk_event_new (event->type == MotionNotify + ? GDK_MOTION_NOTIFY + : (event->type == LeaveNotify + ? GDK_LEAVE_NOTIFY + : GDK_ENTER_NOTIFY)); + + target = find_widget_at_pos (model->widgetwindow_osr, + (event->type == MotionNotify + ? event->xmotion.x + view->clip_left + : event->xcrossing.x + view->clip_left), + (event->type == MotionNotify + ? event->xmotion.y + view->clip_top + : event->xcrossing.y + view->clip_top), + &x, &y); if (!target) target = model->widget_osr; @@ -969,6 +989,13 @@ xv_do_draw (struct xwidget_view *xw, struct xwidget *w) { GtkOffscreenWindow *wnd; cairo_surface_t *surface; + + if (NILP (w->buffer)) + { + XClearWindow (xw->dpy, xw->wdesc); + return; + } + block_input (); wnd = GTK_OFFSCREEN_WINDOW (w->widgetwindow_osr); surface = gtk_offscreen_window_get_surface (wnd); @@ -1651,14 +1678,25 @@ x_draw_xwidget_glyph_string (struct glyph_string *s) a redraw. It seems its possible to get out of sync with emacs redraws so emacs background sometimes shows up instead of the xwidgets background. It's just a visual glitch though. */ - if (!xwidget_hidden (xv)) + /* When xww->buffer is nil, that means the xwidget has been killed. */ + if (!NILP (xww->buffer)) { + if (!xwidget_hidden (xv)) + { #ifdef USE_GTK - gtk_widget_queue_draw (xww->widget_osr); + gtk_widget_queue_draw (xww->widget_osr); #elif defined NS_IMPL_COCOA - nsxwidget_set_needsdisplay (xv); + nsxwidget_set_needsdisplay (xv); #endif + } + } +#ifdef USE_GTK + else + { + XSetWindowBackground (xv->dpy, xv->wdesc, + FRAME_BACKGROUND_PIXEL (s->f)); } +#endif #ifdef USE_GTK unblock_input (); @@ -1677,7 +1715,7 @@ xwidget_is_web_view (struct xwidget *xw) /* Macro that checks xwidget hold webkit web view first. */ #define WEBKIT_FN_INIT() \ - CHECK_XWIDGET (xwidget); \ + CHECK_LIVE_XWIDGET (xwidget); \ struct xwidget *xw = XXWIDGET (xwidget); \ if (!xwidget_is_web_view (xw)) \ { \ @@ -1856,7 +1894,7 @@ 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) { - CHECK_XWIDGET (xwidget); + CHECK_LIVE_XWIDGET (xwidget); int w = check_integer_range (new_width, 0, INT_MAX); int h = check_integer_range (new_height, 0, INT_MAX); struct xwidget *xw = XXWIDGET (xwidget); @@ -1907,7 +1945,7 @@ DEFUN ("xwidget-size-request", Emacs allocated area accordingly. */) (Lisp_Object xwidget) { - CHECK_XWIDGET (xwidget); + CHECK_LIVE_XWIDGET (xwidget); #ifdef USE_GTK GtkRequisition requisition; gtk_widget_size_request (XXWIDGET (xwidget)->widget_osr, &requisition); @@ -1942,7 +1980,7 @@ DEFUN ("xwidget-info", Currently [TYPE TITLE WIDTH HEIGHT]. */) (Lisp_Object xwidget) { - CHECK_XWIDGET (xwidget); + CHECK_LIVE_XWIDGET (xwidget); struct xwidget *xw = XXWIDGET (xwidget); return CALLN (Fvector, xw->type, xw->title, make_fixed_natnum (xw->width), make_fixed_natnum (xw->height)); @@ -2005,7 +2043,7 @@ DEFUN ("delete-xwidget-view", unblock_input (); } - if (xw->embedder_view == xv) + if (xw->embedder_view == xv && !NILP (xw->buffer)) { w = gtk_widget_get_window (xw->widgetwindow_osr); @@ -2054,7 +2092,7 @@ DEFUN ("xwidget-plist", doc: /* Return the plist of XWIDGET. */) (Lisp_Object xwidget) { - CHECK_XWIDGET (xwidget); + CHECK_LIVE_XWIDGET (xwidget); return XXWIDGET (xwidget)->plist; } @@ -2074,7 +2112,7 @@ DEFUN ("set-xwidget-buffer", doc: /* Set XWIDGET's buffer to BUFFER. */) (Lisp_Object xwidget, Lisp_Object buffer) { - CHECK_XWIDGET (xwidget); + CHECK_LIVE_XWIDGET (xwidget); CHECK_BUFFER (buffer); XXWIDGET (xwidget)->buffer = buffer; @@ -2088,7 +2126,7 @@ DEFUN ("set-xwidget-plist", Returns PLIST. */) (Lisp_Object xwidget, Lisp_Object plist) { - CHECK_XWIDGET (xwidget); + CHECK_LIVE_XWIDGET (xwidget); CHECK_LIST (plist); XXWIDGET (xwidget)->plist = plist; @@ -2104,7 +2142,7 @@ DEFUN ("set-xwidget-query-on-exit-flag", This function returns FLAG. */) (Lisp_Object xwidget, Lisp_Object flag) { - CHECK_XWIDGET (xwidget); + CHECK_LIVE_XWIDGET (xwidget); XXWIDGET (xwidget)->kill_without_query = NILP (flag); return flag; } @@ -2115,7 +2153,7 @@ DEFUN ("xwidget-query-on-exit-flag", doc: /* Return the current value of the query-on-exit flag for XWIDGET. */) (Lisp_Object xwidget) { - CHECK_XWIDGET (xwidget); + CHECK_LIVE_XWIDGET (xwidget); return (XXWIDGET (xwidget)->kill_without_query ? Qnil : Qt); } @@ -2148,7 +2186,7 @@ DEFUN ("xwidget-webkit-search", Fxwidget_webkit_search, Sxwidget_webkit_search, #endif CHECK_STRING (query); - CHECK_XWIDGET (xwidget); + CHECK_LIVE_XWIDGET (xwidget); #ifdef USE_GTK xw = XXWIDGET (xwidget); @@ -2192,7 +2230,7 @@ DEFUN ("xwidget-webkit-next-result", Fxwidget_webkit_next_result, WebKitFindController *controller; #endif - CHECK_XWIDGET (xwidget); + CHECK_LIVE_XWIDGET (xwidget); xw = XXWIDGET (xwidget); if (!xw->find_text) @@ -2224,7 +2262,7 @@ DEFUN ("xwidget-webkit-previous-result", Fxwidget_webkit_previous_result, WebKitFindController *controller; #endif - CHECK_XWIDGET (xwidget); + CHECK_LIVE_XWIDGET (xwidget); xw = XXWIDGET (xwidget); if (!xw->find_text) @@ -2256,7 +2294,7 @@ DEFUN ("xwidget-webkit-finish-search", Fxwidget_webkit_finish_search, WebKitFindController *controller; #endif - CHECK_XWIDGET (xwidget); + CHECK_LIVE_XWIDGET (xwidget); xw = XXWIDGET (xwidget); if (!xw->find_text) @@ -2294,7 +2332,7 @@ DEFUN ("xwidget-webkit-load-html", Fxwidget_webkit_load_html, WebKitWebView *webview; char *data, *uri; - CHECK_XWIDGET (xwidget); + CHECK_LIVE_XWIDGET (xwidget); CHECK_STRING (text); if (NILP (base_uri)) base_uri = build_string ("about:blank"); @@ -2415,7 +2453,9 @@ syms_of_xwidget (void) { defsubr (&Smake_xwidget); defsubr (&Sxwidgetp); + defsubr (&Sxwidget_live_p); DEFSYM (Qxwidgetp, "xwidgetp"); + DEFSYM (Qxwidget_live_p, "xwidget-live-p"); defsubr (&Sxwidget_view_p); DEFSYM (Qxwidget_view_p, "xwidget-view-p"); defsubr (&Sxwidget_info); @@ -2474,7 +2514,8 @@ syms_of_xwidget (void) Fprovide (intern ("xwidget-internal"), Qnil); - id_to_xwidget_map = CALLN (Fmake_hash_table, QCtest, Qeq); + id_to_xwidget_map = CALLN (Fmake_hash_table, QCtest, Qeq, + QCweakness, Qvalue); staticpro (&id_to_xwidget_map); #ifdef USE_GTK @@ -2700,9 +2741,10 @@ kill_buffer_xwidgets (Lisp_Object buffer) Vxwidget_list = Fdelq (xwidget, Vxwidget_list); /* TODO free the GTK things in xw. */ { - CHECK_XWIDGET (xwidget); + CHECK_LIVE_XWIDGET (xwidget); struct xwidget *xw = XXWIDGET (xwidget); - Fremhash (make_fixnum (xw->xwidget_id), id_to_xwidget_map); + xw->buffer = Qnil; + #ifdef USE_GTK if (xw->widget_osr && xw->widgetwindow_osr) { @@ -2719,6 +2761,10 @@ kill_buffer_xwidgets (Lisp_Object buffer) xfree (xmint_pointer (XCAR (cb))); ASET (xw->script_callbacks, idx, Qnil); } + + xw->widget_osr = NULL; + xw->widgetwindow_osr = NULL; + xw->find_text = NULL; #elif defined NS_IMPL_COCOA nsxwidget_kill (xw); #endif diff --git a/src/xwidget.h b/src/xwidget.h index 6e6b39c8b4..4377b50e84 100644 --- a/src/xwidget.h +++ b/src/xwidget.h @@ -138,9 +138,16 @@ #define XWIDGETP(x) PSEUDOVECTORP (x, PVEC_XWIDGET) #define XXWIDGET(a) (eassert (XWIDGETP (a)), \ XUNTAG (a, Lisp_Vectorlike, struct xwidget)) +#define XWIDGET_LIVE_P(w) (!NILP ((w)->buffer)) + #define CHECK_XWIDGET(x) \ CHECK_TYPE (XWIDGETP (x), Qxwidgetp, x) +#define CHECK_LIVE_XWIDGET(x) \ + CHECK_TYPE ((XWIDGETP (x) \ + && XWIDGET_LIVE_P (XXWIDGET (x))), \ + Qxwidget_live_p, x) + /* Test for xwidget_view pseudovector. */ #define XWIDGET_VIEW_P(x) PSEUDOVECTORP (x, PVEC_XWIDGET_VIEW) #define XXWIDGET_VIEW(a) (eassert (XWIDGET_VIEW_P (a)), \ -- 2.31.1 --=-=-= Content-Type: text/plain Thanks, how does this look to you? And perhaps Eli has something to say about it as well. Thanks in advance. --=-=-=--