diff options
| author | Po Lu | 2022-09-02 17:19:29 +0800 |
|---|---|---|
| committer | Po Lu | 2022-09-02 17:19:51 +0800 |
| commit | 2ff57638365411904e76979ef628534098ce3549 (patch) | |
| tree | 4bc7295290f1dbac1f775da5856723abfa08e064 /src | |
| parent | 0ec831b91cde2a0e1b65f99c1190975c6e6959f9 (diff) | |
| download | emacs-2ff57638365411904e76979ef628534098ce3549.tar.gz emacs-2ff57638365411904e76979ef628534098ce3549.zip | |
Prevent crashes when embedding Emacs in a nonexistent parent
* src/xfns.c (x_window, Fx_create_frame): Handle X errors while
trying to reparent the frame onto an explicitly specified
parent.
* src/xterm.c (handle_one_xevent): Handle unparenting embedded
windows correctly. This only works if the embedder is aware of
the fixes extension and has put the window into the right save
set.
(x_embed_frame): New function.
* src/xterm.h (FRAME_X_EMBEDDED_P): Fix coding style.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xfns.c | 12 | ||||
| -rw-r--r-- | src/xterm.c | 39 | ||||
| -rw-r--r-- | src/xterm.h | 4 |
3 files changed, 48 insertions, 7 deletions
diff --git a/src/xfns.c b/src/xfns.c index 0b1f707e9fc..2da1e7bcf80 100644 --- a/src/xfns.c +++ b/src/xfns.c | |||
| @@ -3955,10 +3955,6 @@ x_window (struct frame *f, long window_prompting) | |||
| 3955 | XtManageChild (pane_widget); | 3955 | XtManageChild (pane_widget); |
| 3956 | XtRealizeWidget (shell_widget); | 3956 | XtRealizeWidget (shell_widget); |
| 3957 | 3957 | ||
| 3958 | if (FRAME_X_EMBEDDED_P (f)) | ||
| 3959 | XReparentWindow (FRAME_X_DISPLAY (f), XtWindow (shell_widget), | ||
| 3960 | f->output_data.x->parent_desc, 0, 0); | ||
| 3961 | |||
| 3962 | FRAME_X_WINDOW (f) = XtWindow (frame_widget); | 3958 | FRAME_X_WINDOW (f) = XtWindow (frame_widget); |
| 3963 | initial_set_up_x_back_buffer (f); | 3959 | initial_set_up_x_back_buffer (f); |
| 3964 | validate_x_resource_name (); | 3960 | validate_x_resource_name (); |
| @@ -4132,7 +4128,7 @@ x_window (struct frame *f) | |||
| 4132 | block_input (); | 4128 | block_input (); |
| 4133 | FRAME_X_WINDOW (f) | 4129 | FRAME_X_WINDOW (f) |
| 4134 | = XCreateWindow (FRAME_X_DISPLAY (f), | 4130 | = XCreateWindow (FRAME_X_DISPLAY (f), |
| 4135 | f->output_data.x->parent_desc, | 4131 | FRAME_DISPLAY_INFO (f)->root_window, |
| 4136 | f->left_pos, | 4132 | f->left_pos, |
| 4137 | f->top_pos, | 4133 | f->top_pos, |
| 4138 | FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), | 4134 | FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), |
| @@ -4958,6 +4954,12 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4958 | x_window (f); | 4954 | x_window (f); |
| 4959 | #endif | 4955 | #endif |
| 4960 | 4956 | ||
| 4957 | #ifndef USE_GTK | ||
| 4958 | if (FRAME_X_EMBEDDED_P (f) | ||
| 4959 | && !x_embed_frame (dpyinfo, f)) | ||
| 4960 | error ("The frame could not be embedded; does the embedder exist?"); | ||
| 4961 | #endif | ||
| 4962 | |||
| 4961 | x_icon (f, parms); | 4963 | x_icon (f, parms); |
| 4962 | x_make_gc (f); | 4964 | x_make_gc (f); |
| 4963 | 4965 | ||
diff --git a/src/xterm.c b/src/xterm.c index 71b84f81747..138fa7ea6c8 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -18416,6 +18416,20 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 18416 | f = x_top_window_to_frame (dpyinfo, event->xreparent.window); | 18416 | f = x_top_window_to_frame (dpyinfo, event->xreparent.window); |
| 18417 | if (f) | 18417 | if (f) |
| 18418 | { | 18418 | { |
| 18419 | #ifndef USE_GTK | ||
| 18420 | if (FRAME_OUTPUT_DATA (f)->parent_desc | ||
| 18421 | && FRAME_X_EMBEDDED_P (f)) | ||
| 18422 | { | ||
| 18423 | /* The frame's embedder was destroyed; mark the frame as | ||
| 18424 | no longer embedded, and map the frame. An | ||
| 18425 | UnmapNotify event must have previously been received | ||
| 18426 | during the start of save-set processing. */ | ||
| 18427 | |||
| 18428 | FRAME_X_OUTPUT (f)->explicit_parent = false; | ||
| 18429 | x_make_frame_visible (f); | ||
| 18430 | } | ||
| 18431 | #endif | ||
| 18432 | |||
| 18419 | /* Maybe we shouldn't set this for child frames ?? */ | 18433 | /* Maybe we shouldn't set this for child frames ?? */ |
| 18420 | f->output_data.x->parent_desc = event->xreparent.parent; | 18434 | f->output_data.x->parent_desc = event->xreparent.parent; |
| 18421 | 18435 | ||
| @@ -27456,6 +27470,31 @@ x_get_atom_name (struct x_display_info *dpyinfo, Atom atom, | |||
| 27456 | return value; | 27470 | return value; |
| 27457 | } | 27471 | } |
| 27458 | 27472 | ||
| 27473 | #ifndef USE_GTK | ||
| 27474 | |||
| 27475 | /* Set up XEmbed for F, and change its save set to handle the parent | ||
| 27476 | being destroyed. */ | ||
| 27477 | |||
| 27478 | bool | ||
| 27479 | x_embed_frame (struct x_display_info *dpyinfo, struct frame *f) | ||
| 27480 | { | ||
| 27481 | bool rc; | ||
| 27482 | |||
| 27483 | x_catch_errors (dpyinfo->display); | ||
| 27484 | /* Catch errors; the target window might no longer exist. */ | ||
| 27485 | XReparentWindow (dpyinfo->display, FRAME_OUTER_WINDOW (f), | ||
| 27486 | FRAME_OUTPUT_DATA (f)->parent_desc, 0, 0); | ||
| 27487 | rc = x_had_errors_p (dpyinfo->display); | ||
| 27488 | x_uncatch_errors_after_check (); | ||
| 27489 | |||
| 27490 | if (rc) | ||
| 27491 | return false; | ||
| 27492 | |||
| 27493 | return true; | ||
| 27494 | } | ||
| 27495 | |||
| 27496 | #endif | ||
| 27497 | |||
| 27459 | 27498 | ||
| 27460 | /* Setting window manager hints. */ | 27499 | /* Setting window manager hints. */ |
| 27461 | 27500 | ||
diff --git a/src/xterm.h b/src/xterm.h index a0ae3a330a9..7c5a889af30 100644 --- a/src/xterm.h +++ b/src/xterm.h | |||
| @@ -1209,7 +1209,6 @@ enum | |||
| 1209 | FOCUS_EXPLICIT = 2 | 1209 | FOCUS_EXPLICIT = 2 |
| 1210 | }; | 1210 | }; |
| 1211 | 1211 | ||
| 1212 | |||
| 1213 | /* Return the X output data for frame F. */ | 1212 | /* Return the X output data for frame F. */ |
| 1214 | #define FRAME_X_OUTPUT(f) ((f)->output_data.x) | 1213 | #define FRAME_X_OUTPUT(f) ((f)->output_data.x) |
| 1215 | #define FRAME_OUTPUT_DATA(f) FRAME_X_OUTPUT (f) | 1214 | #define FRAME_OUTPUT_DATA(f) FRAME_X_OUTPUT (f) |
| @@ -1588,6 +1587,7 @@ extern void x_wm_set_size_hint (struct frame *, long, bool); | |||
| 1588 | && defined HAVE_CLOCK_GETTIME | 1587 | && defined HAVE_CLOCK_GETTIME |
| 1589 | extern void x_sync_init_fences (struct frame *); | 1588 | extern void x_sync_init_fences (struct frame *); |
| 1590 | #endif | 1589 | #endif |
| 1590 | extern bool x_embed_frame (struct x_display_info *, struct frame *); | ||
| 1591 | 1591 | ||
| 1592 | extern void x_delete_terminal (struct terminal *); | 1592 | extern void x_delete_terminal (struct terminal *); |
| 1593 | extern Cursor x_create_font_cursor (struct x_display_info *, int); | 1593 | extern Cursor x_create_font_cursor (struct x_display_info *, int); |
| @@ -1827,7 +1827,7 @@ extern void mark_xterm (void); | |||
| 1827 | 1827 | ||
| 1828 | /* Is the frame embedded into another application? */ | 1828 | /* Is the frame embedded into another application? */ |
| 1829 | 1829 | ||
| 1830 | #define FRAME_X_EMBEDDED_P(f) (FRAME_X_OUTPUT(f)->explicit_parent != 0) | 1830 | #define FRAME_X_EMBEDDED_P(f) (FRAME_X_OUTPUT (f)->explicit_parent != 0) |
| 1831 | 1831 | ||
| 1832 | #define STORE_NATIVE_RECT(nr,rx,ry,rwidth,rheight) \ | 1832 | #define STORE_NATIVE_RECT(nr,rx,ry,rwidth,rheight) \ |
| 1833 | ((nr).x = (rx), \ | 1833 | ((nr).x = (rx), \ |