aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2021-11-12 08:17:41 +0800
committerPo Lu2021-11-12 08:17:41 +0800
commit554a875493680f8b52821267ee88e191d462ea36 (patch)
tree22bd120a4d1cfc3c8cc99bf17a6361437e140399 /src
parenta8fc08085110de00ebcbd67b5273a755a5cb8ea1 (diff)
downloademacs-554a875493680f8b52821267ee88e191d462ea36.tar.gz
emacs-554a875493680f8b52821267ee88e191d462ea36.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/xwidget.c116
-rw-r--r--src/xwidget.h7
2 files changed, 88 insertions, 35 deletions
diff --git a/src/xwidget.c b/src/xwidget.c
index fc05f4f5709..d0cc3b987c9 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -272,6 +272,16 @@ fails. */)
272 return val; 272 return val;
273} 273}
274 274
275DEFUN ("xwidget-live-p", Fxwidget_live_p, Sxwidget_live_p,
276 1, 1, 0, doc: /* Return t if OBJECT is an xwidget that has not been killed.
277Value is nil if OBJECT is not an xwidget or if it has been killed. */)
278 (Lisp_Object object)
279{
280 return ((XWIDGETP (object)
281 && !NILP (XXWIDGET (object)->buffer))
282 ? Qt : Qnil);
283}
284
275#ifdef USE_GTK 285#ifdef USE_GTK
276static void 286static void
277set_widget_if_text_view (GtkWidget *widget, void *data) 287set_widget_if_text_view (GtkWidget *widget, void *data)
@@ -304,7 +314,7 @@ selected frame is not an X-Windows frame. */)
304 GtkWidget *temp = NULL; 314 GtkWidget *temp = NULL;
305#endif 315#endif
306 316
307 CHECK_XWIDGET (xwidget); 317 CHECK_LIVE_XWIDGET (xwidget);
308 xw = XXWIDGET (xwidget); 318 xw = XXWIDGET (xwidget);
309 319
310 if (!NILP (frame)) 320 if (!NILP (frame))
@@ -806,6 +816,9 @@ xwidget_button (struct xwidget_view *view,
806 bool down_p, int x, int y, int button, 816 bool down_p, int x, int y, int button,
807 int modifier_state, Time time) 817 int modifier_state, Time time)
808{ 818{
819 if (NILP (XXWIDGET (view->model)->buffer))
820 return;
821
809 record_osr_embedder (view); 822 record_osr_embedder (view);
810 823
811 if (button < 4 || button > 8) 824 if (button < 4 || button > 8)
@@ -856,22 +869,29 @@ xwidget_button (struct xwidget_view *view,
856void 869void
857xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event) 870xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event)
858{ 871{
859 GdkEvent *xg_event = gdk_event_new (event->type == MotionNotify 872 GdkEvent *xg_event;
860 ? GDK_MOTION_NOTIFY
861 : (event->type == LeaveNotify
862 ? GDK_LEAVE_NOTIFY
863 : GDK_ENTER_NOTIFY));
864 struct xwidget *model = XXWIDGET (view->model); 873 struct xwidget *model = XXWIDGET (view->model);
865 int x; 874 int x;
866 int y; 875 int y;
867 GtkWidget *target = find_widget_at_pos (model->widgetwindow_osr, 876 GtkWidget *target;
868 (event->type == MotionNotify 877
869 ? event->xmotion.x + view->clip_left 878 if (NILP (model->buffer))
870 : event->xcrossing.x + view->clip_left), 879 return;
871 (event->type == MotionNotify 880
872 ? event->xmotion.y + view->clip_top 881 xg_event = gdk_event_new (event->type == MotionNotify
873 : event->xcrossing.y + view->clip_top), 882 ? GDK_MOTION_NOTIFY
874 &x, &y); 883 : (event->type == LeaveNotify
884 ? GDK_LEAVE_NOTIFY
885 : GDK_ENTER_NOTIFY));
886
887 target = find_widget_at_pos (model->widgetwindow_osr,
888 (event->type == MotionNotify
889 ? event->xmotion.x + view->clip_left
890 : event->xcrossing.x + view->clip_left),
891 (event->type == MotionNotify
892 ? event->xmotion.y + view->clip_top
893 : event->xcrossing.y + view->clip_top),
894 &x, &y);
875 895
876 if (!target) 896 if (!target)
877 target = model->widget_osr; 897 target = model->widget_osr;
@@ -968,6 +988,13 @@ xv_do_draw (struct xwidget_view *xw, struct xwidget *w)
968{ 988{
969 GtkOffscreenWindow *wnd; 989 GtkOffscreenWindow *wnd;
970 cairo_surface_t *surface; 990 cairo_surface_t *surface;
991
992 if (NILP (w->buffer))
993 {
994 XClearWindow (xw->dpy, xw->wdesc);
995 return;
996 }
997
971 block_input (); 998 block_input ();
972 wnd = GTK_OFFSCREEN_WINDOW (w->widgetwindow_osr); 999 wnd = GTK_OFFSCREEN_WINDOW (w->widgetwindow_osr);
973 surface = gtk_offscreen_window_get_surface (wnd); 1000 surface = gtk_offscreen_window_get_surface (wnd);
@@ -1650,14 +1677,25 @@ x_draw_xwidget_glyph_string (struct glyph_string *s)
1650 a redraw. It seems its possible to get out of sync with emacs 1677 a redraw. It seems its possible to get out of sync with emacs
1651 redraws so emacs background sometimes shows up instead of the 1678 redraws so emacs background sometimes shows up instead of the
1652 xwidgets background. It's just a visual glitch though. */ 1679 xwidgets background. It's just a visual glitch though. */
1653 if (!xwidget_hidden (xv)) 1680 /* When xww->buffer is nil, that means the xwidget has been killed. */
1681 if (!NILP (xww->buffer))
1654 { 1682 {
1683 if (!xwidget_hidden (xv))
1684 {
1655#ifdef USE_GTK 1685#ifdef USE_GTK
1656 gtk_widget_queue_draw (xww->widget_osr); 1686 gtk_widget_queue_draw (xww->widget_osr);
1657#elif defined NS_IMPL_COCOA 1687#elif defined NS_IMPL_COCOA
1658 nsxwidget_set_needsdisplay (xv); 1688 nsxwidget_set_needsdisplay (xv);
1659#endif 1689#endif
1690 }
1691 }
1692#ifdef USE_GTK
1693 else
1694 {
1695 XSetWindowBackground (xv->dpy, xv->wdesc,
1696 FRAME_BACKGROUND_PIXEL (s->f));
1660 } 1697 }
1698#endif
1661 1699
1662#ifdef USE_GTK 1700#ifdef USE_GTK
1663 unblock_input (); 1701 unblock_input ();
@@ -1676,7 +1714,7 @@ xwidget_is_web_view (struct xwidget *xw)
1676 1714
1677/* Macro that checks xwidget hold webkit web view first. */ 1715/* Macro that checks xwidget hold webkit web view first. */
1678#define WEBKIT_FN_INIT() \ 1716#define WEBKIT_FN_INIT() \
1679 CHECK_XWIDGET (xwidget); \ 1717 CHECK_LIVE_XWIDGET (xwidget); \
1680 struct xwidget *xw = XXWIDGET (xwidget); \ 1718 struct xwidget *xw = XXWIDGET (xwidget); \
1681 if (!xwidget_is_web_view (xw)) \ 1719 if (!xwidget_is_web_view (xw)) \
1682 { \ 1720 { \
@@ -1855,7 +1893,7 @@ DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0,
1855 doc: /* Resize XWIDGET to NEW_WIDTH, NEW_HEIGHT. */ ) 1893 doc: /* Resize XWIDGET to NEW_WIDTH, NEW_HEIGHT. */ )
1856 (Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height) 1894 (Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height)
1857{ 1895{
1858 CHECK_XWIDGET (xwidget); 1896 CHECK_LIVE_XWIDGET (xwidget);
1859 int w = check_integer_range (new_width, 0, INT_MAX); 1897 int w = check_integer_range (new_width, 0, INT_MAX);
1860 int h = check_integer_range (new_height, 0, INT_MAX); 1898 int h = check_integer_range (new_height, 0, INT_MAX);
1861 struct xwidget *xw = XXWIDGET (xwidget); 1899 struct xwidget *xw = XXWIDGET (xwidget);
@@ -1906,7 +1944,7 @@ This can be used to read the xwidget desired size, and resizes the
1906Emacs allocated area accordingly. */) 1944Emacs allocated area accordingly. */)
1907 (Lisp_Object xwidget) 1945 (Lisp_Object xwidget)
1908{ 1946{
1909 CHECK_XWIDGET (xwidget); 1947 CHECK_LIVE_XWIDGET (xwidget);
1910#ifdef USE_GTK 1948#ifdef USE_GTK
1911 GtkRequisition requisition; 1949 GtkRequisition requisition;
1912 gtk_widget_size_request (XXWIDGET (xwidget)->widget_osr, &requisition); 1950 gtk_widget_size_request (XXWIDGET (xwidget)->widget_osr, &requisition);
@@ -1941,7 +1979,7 @@ DEFUN ("xwidget-info",
1941Currently [TYPE TITLE WIDTH HEIGHT]. */) 1979Currently [TYPE TITLE WIDTH HEIGHT]. */)
1942 (Lisp_Object xwidget) 1980 (Lisp_Object xwidget)
1943{ 1981{
1944 CHECK_XWIDGET (xwidget); 1982 CHECK_LIVE_XWIDGET (xwidget);
1945 struct xwidget *xw = XXWIDGET (xwidget); 1983 struct xwidget *xw = XXWIDGET (xwidget);
1946 return CALLN (Fvector, xw->type, xw->title, 1984 return CALLN (Fvector, xw->type, xw->title,
1947 make_fixed_natnum (xw->width), make_fixed_natnum (xw->height)); 1985 make_fixed_natnum (xw->width), make_fixed_natnum (xw->height));
@@ -2004,7 +2042,7 @@ DEFUN ("delete-xwidget-view",
2004 unblock_input (); 2042 unblock_input ();
2005 } 2043 }
2006 2044
2007 if (xw->embedder_view == xv) 2045 if (xw->embedder_view == xv && !NILP (xw->buffer))
2008 { 2046 {
2009 w = gtk_widget_get_window (xw->widgetwindow_osr); 2047 w = gtk_widget_get_window (xw->widgetwindow_osr);
2010 2048
@@ -2053,7 +2091,7 @@ DEFUN ("xwidget-plist",
2053 doc: /* Return the plist of XWIDGET. */) 2091 doc: /* Return the plist of XWIDGET. */)
2054 (Lisp_Object xwidget) 2092 (Lisp_Object xwidget)
2055{ 2093{
2056 CHECK_XWIDGET (xwidget); 2094 CHECK_LIVE_XWIDGET (xwidget);
2057 return XXWIDGET (xwidget)->plist; 2095 return XXWIDGET (xwidget)->plist;
2058} 2096}
2059 2097
@@ -2073,7 +2111,7 @@ DEFUN ("set-xwidget-buffer",
2073 doc: /* Set XWIDGET's buffer to BUFFER. */) 2111 doc: /* Set XWIDGET's buffer to BUFFER. */)
2074 (Lisp_Object xwidget, Lisp_Object buffer) 2112 (Lisp_Object xwidget, Lisp_Object buffer)
2075{ 2113{
2076 CHECK_XWIDGET (xwidget); 2114 CHECK_LIVE_XWIDGET (xwidget);
2077 CHECK_BUFFER (buffer); 2115 CHECK_BUFFER (buffer);
2078 2116
2079 XXWIDGET (xwidget)->buffer = buffer; 2117 XXWIDGET (xwidget)->buffer = buffer;
@@ -2087,7 +2125,7 @@ DEFUN ("set-xwidget-plist",
2087Returns PLIST. */) 2125Returns PLIST. */)
2088 (Lisp_Object xwidget, Lisp_Object plist) 2126 (Lisp_Object xwidget, Lisp_Object plist)
2089{ 2127{
2090 CHECK_XWIDGET (xwidget); 2128 CHECK_LIVE_XWIDGET (xwidget);
2091 CHECK_LIST (plist); 2129 CHECK_LIST (plist);
2092 2130
2093 XXWIDGET (xwidget)->plist = plist; 2131 XXWIDGET (xwidget)->plist = plist;
@@ -2103,7 +2141,7 @@ exiting or killing a buffer if XWIDGET is running.
2103This function returns FLAG. */) 2141This function returns FLAG. */)
2104 (Lisp_Object xwidget, Lisp_Object flag) 2142 (Lisp_Object xwidget, Lisp_Object flag)
2105{ 2143{
2106 CHECK_XWIDGET (xwidget); 2144 CHECK_LIVE_XWIDGET (xwidget);
2107 XXWIDGET (xwidget)->kill_without_query = NILP (flag); 2145 XXWIDGET (xwidget)->kill_without_query = NILP (flag);
2108 return flag; 2146 return flag;
2109} 2147}
@@ -2114,7 +2152,7 @@ DEFUN ("xwidget-query-on-exit-flag",
2114 doc: /* Return the current value of the query-on-exit flag for XWIDGET. */) 2152 doc: /* Return the current value of the query-on-exit flag for XWIDGET. */)
2115 (Lisp_Object xwidget) 2153 (Lisp_Object xwidget)
2116{ 2154{
2117 CHECK_XWIDGET (xwidget); 2155 CHECK_LIVE_XWIDGET (xwidget);
2118 return (XXWIDGET (xwidget)->kill_without_query ? Qnil : Qt); 2156 return (XXWIDGET (xwidget)->kill_without_query ? Qnil : Qt);
2119} 2157}
2120 2158
@@ -2147,7 +2185,7 @@ with QUERY. */)
2147#endif 2185#endif
2148 2186
2149 CHECK_STRING (query); 2187 CHECK_STRING (query);
2150 CHECK_XWIDGET (xwidget); 2188 CHECK_LIVE_XWIDGET (xwidget);
2151 2189
2152#ifdef USE_GTK 2190#ifdef USE_GTK
2153 xw = XXWIDGET (xwidget); 2191 xw = XXWIDGET (xwidget);
@@ -2191,7 +2229,7 @@ using `xwidget-webkit-search'. */)
2191 WebKitFindController *controller; 2229 WebKitFindController *controller;
2192#endif 2230#endif
2193 2231
2194 CHECK_XWIDGET (xwidget); 2232 CHECK_LIVE_XWIDGET (xwidget);
2195 xw = XXWIDGET (xwidget); 2233 xw = XXWIDGET (xwidget);
2196 2234
2197 if (!xw->find_text) 2235 if (!xw->find_text)
@@ -2223,7 +2261,7 @@ using `xwidget-webkit-search'. */)
2223 WebKitFindController *controller; 2261 WebKitFindController *controller;
2224#endif 2262#endif
2225 2263
2226 CHECK_XWIDGET (xwidget); 2264 CHECK_LIVE_XWIDGET (xwidget);
2227 xw = XXWIDGET (xwidget); 2265 xw = XXWIDGET (xwidget);
2228 2266
2229 if (!xw->find_text) 2267 if (!xw->find_text)
@@ -2255,7 +2293,7 @@ using `xwidget-webkit-search'. */)
2255 WebKitFindController *controller; 2293 WebKitFindController *controller;
2256#endif 2294#endif
2257 2295
2258 CHECK_XWIDGET (xwidget); 2296 CHECK_LIVE_XWIDGET (xwidget);
2259 xw = XXWIDGET (xwidget); 2297 xw = XXWIDGET (xwidget);
2260 2298
2261 if (!xw->find_text) 2299 if (!xw->find_text)
@@ -2293,7 +2331,7 @@ to "about:blank". */)
2293 WebKitWebView *webview; 2331 WebKitWebView *webview;
2294 char *data, *uri; 2332 char *data, *uri;
2295 2333
2296 CHECK_XWIDGET (xwidget); 2334 CHECK_LIVE_XWIDGET (xwidget);
2297 CHECK_STRING (text); 2335 CHECK_STRING (text);
2298 if (NILP (base_uri)) 2336 if (NILP (base_uri))
2299 base_uri = build_string ("about:blank"); 2337 base_uri = build_string ("about:blank");
@@ -2321,7 +2359,9 @@ syms_of_xwidget (void)
2321{ 2359{
2322 defsubr (&Smake_xwidget); 2360 defsubr (&Smake_xwidget);
2323 defsubr (&Sxwidgetp); 2361 defsubr (&Sxwidgetp);
2362 defsubr (&Sxwidget_live_p);
2324 DEFSYM (Qxwidgetp, "xwidgetp"); 2363 DEFSYM (Qxwidgetp, "xwidgetp");
2364 DEFSYM (Qxwidget_live_p, "xwidget-live-p");
2325 defsubr (&Sxwidget_view_p); 2365 defsubr (&Sxwidget_view_p);
2326 DEFSYM (Qxwidget_view_p, "xwidget-view-p"); 2366 DEFSYM (Qxwidget_view_p, "xwidget-view-p");
2327 defsubr (&Sxwidget_info); 2367 defsubr (&Sxwidget_info);
@@ -2379,7 +2419,8 @@ syms_of_xwidget (void)
2379 2419
2380 Fprovide (intern ("xwidget-internal"), Qnil); 2420 Fprovide (intern ("xwidget-internal"), Qnil);
2381 2421
2382 id_to_xwidget_map = CALLN (Fmake_hash_table, QCtest, Qeq); 2422 id_to_xwidget_map = CALLN (Fmake_hash_table, QCtest, Qeq,
2423 QCweakness, Qvalue);
2383 staticpro (&id_to_xwidget_map); 2424 staticpro (&id_to_xwidget_map);
2384 2425
2385#ifdef USE_GTK 2426#ifdef USE_GTK
@@ -2605,9 +2646,10 @@ kill_buffer_xwidgets (Lisp_Object buffer)
2605 Vxwidget_list = Fdelq (xwidget, Vxwidget_list); 2646 Vxwidget_list = Fdelq (xwidget, Vxwidget_list);
2606 /* TODO free the GTK things in xw. */ 2647 /* TODO free the GTK things in xw. */
2607 { 2648 {
2608 CHECK_XWIDGET (xwidget); 2649 CHECK_LIVE_XWIDGET (xwidget);
2609 struct xwidget *xw = XXWIDGET (xwidget); 2650 struct xwidget *xw = XXWIDGET (xwidget);
2610 Fremhash (make_fixnum (xw->xwidget_id), id_to_xwidget_map); 2651 xw->buffer = Qnil;
2652
2611#ifdef USE_GTK 2653#ifdef USE_GTK
2612 if (xw->widget_osr && xw->widgetwindow_osr) 2654 if (xw->widget_osr && xw->widgetwindow_osr)
2613 { 2655 {
@@ -2624,6 +2666,10 @@ kill_buffer_xwidgets (Lisp_Object buffer)
2624 xfree (xmint_pointer (XCAR (cb))); 2666 xfree (xmint_pointer (XCAR (cb)));
2625 ASET (xw->script_callbacks, idx, Qnil); 2667 ASET (xw->script_callbacks, idx, Qnil);
2626 } 2668 }
2669
2670 xw->widget_osr = NULL;
2671 xw->widgetwindow_osr = NULL;
2672 xw->find_text = NULL;
2627#elif defined NS_IMPL_COCOA 2673#elif defined NS_IMPL_COCOA
2628 nsxwidget_kill (xw); 2674 nsxwidget_kill (xw);
2629#endif 2675#endif
diff --git a/src/xwidget.h b/src/xwidget.h
index 6e6b39c8b4f..4377b50e840 100644
--- a/src/xwidget.h
+++ b/src/xwidget.h
@@ -138,9 +138,16 @@ struct xwidget_view
138#define XXWIDGET(a) (eassert (XWIDGETP (a)), \ 138#define XXWIDGET(a) (eassert (XWIDGETP (a)), \
139 XUNTAG (a, Lisp_Vectorlike, struct xwidget)) 139 XUNTAG (a, Lisp_Vectorlike, struct xwidget))
140 140
141#define XWIDGET_LIVE_P(w) (!NILP ((w)->buffer))
142
141#define CHECK_XWIDGET(x) \ 143#define CHECK_XWIDGET(x) \
142 CHECK_TYPE (XWIDGETP (x), Qxwidgetp, x) 144 CHECK_TYPE (XWIDGETP (x), Qxwidgetp, x)
143 145
146#define CHECK_LIVE_XWIDGET(x) \
147 CHECK_TYPE ((XWIDGETP (x) \
148 && XWIDGET_LIVE_P (XXWIDGET (x))), \
149 Qxwidget_live_p, x)
150
144/* Test for xwidget_view pseudovector. */ 151/* Test for xwidget_view pseudovector. */
145#define XWIDGET_VIEW_P(x) PSEUDOVECTORP (x, PVEC_XWIDGET_VIEW) 152#define XWIDGET_VIEW_P(x) PSEUDOVECTORP (x, PVEC_XWIDGET_VIEW)
146#define XXWIDGET_VIEW(a) (eassert (XWIDGET_VIEW_P (a)), \ 153#define XXWIDGET_VIEW(a) (eassert (XWIDGET_VIEW_P (a)), \