diff options
| author | Po Lu | 2022-07-12 10:47:23 +0800 |
|---|---|---|
| committer | Po Lu | 2022-07-12 10:47:51 +0800 |
| commit | 86d128c6c3acca1665addc65aa43ff80572f46e8 (patch) | |
| tree | ef1dd26be80acf43384c8146e3c784a09ab0cb0d /src | |
| parent | 7ac313ea87b4761baf975718e4fa3200f61a0ad9 (diff) | |
| download | emacs-86d128c6c3acca1665addc65aa43ff80572f46e8.tar.gz emacs-86d128c6c3acca1665addc65aa43ff80572f46e8.zip | |
Try to save selections from being disowned during frame deletion
* lisp/cus-start.el (standard): Add
`x-auto-preserve-selections'.
* src/xselect.c (x_clear_frame_selections): Collect deleted
selections into a variable and preserve them.
* src/xterm.c (x_preserve_selections): New function.
(syms_of_xterm): New variable `x-auto-preserve-selections'.
* src/xterm.h: Update prototypes.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xselect.c | 24 | ||||
| -rw-r--r-- | src/xterm.c | 63 | ||||
| -rw-r--r-- | src/xterm.h | 1 |
3 files changed, 81 insertions, 7 deletions
diff --git a/src/xselect.c b/src/xselect.c index 25a75aec917..baab2c5c18f 100644 --- a/src/xselect.c +++ b/src/xselect.c | |||
| @@ -1091,20 +1091,23 @@ x_handle_selection_event (struct selection_input_event *event) | |||
| 1091 | void | 1091 | void |
| 1092 | x_clear_frame_selections (struct frame *f) | 1092 | x_clear_frame_selections (struct frame *f) |
| 1093 | { | 1093 | { |
| 1094 | Lisp_Object frame; | 1094 | Lisp_Object frame, rest, lost; |
| 1095 | Lisp_Object rest; | ||
| 1096 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); | 1095 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); |
| 1097 | struct terminal *t = dpyinfo->terminal; | 1096 | struct terminal *t = dpyinfo->terminal; |
| 1098 | 1097 | ||
| 1099 | XSETFRAME (frame, f); | 1098 | XSETFRAME (frame, f); |
| 1099 | lost = Qnil; | ||
| 1100 | 1100 | ||
| 1101 | /* Delete elements from the beginning of Vselection_alist. */ | 1101 | /* Delete elements from the beginning of Vselection_alist. */ |
| 1102 | while (CONSP (t->Vselection_alist) | 1102 | while (CONSP (t->Vselection_alist) |
| 1103 | && EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (t->Vselection_alist))))))) | 1103 | && EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (t->Vselection_alist))))))) |
| 1104 | { | 1104 | { |
| 1105 | /* Run the `x-lost-selection-functions' abnormal hook. */ | 1105 | if (!x_auto_preserve_selections) |
| 1106 | CALLN (Frun_hook_with_args, Qx_lost_selection_functions, | 1106 | /* Run the `x-lost-selection-functions' abnormal hook. */ |
| 1107 | Fcar (Fcar (t->Vselection_alist))); | 1107 | CALLN (Frun_hook_with_args, Qx_lost_selection_functions, |
| 1108 | Fcar (Fcar (t->Vselection_alist))); | ||
| 1109 | else | ||
| 1110 | lost = Fcons (Fcar (t->Vselection_alist), lost); | ||
| 1108 | 1111 | ||
| 1109 | tset_selection_alist (t, XCDR (t->Vselection_alist)); | 1112 | tset_selection_alist (t, XCDR (t->Vselection_alist)); |
| 1110 | } | 1113 | } |
| @@ -1114,11 +1117,18 @@ x_clear_frame_selections (struct frame *f) | |||
| 1114 | if (CONSP (XCDR (rest)) | 1117 | if (CONSP (XCDR (rest)) |
| 1115 | && EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (XCDR (rest)))))))) | 1118 | && EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (XCDR (rest)))))))) |
| 1116 | { | 1119 | { |
| 1117 | CALLN (Frun_hook_with_args, Qx_lost_selection_functions, | 1120 | if (!x_auto_preserve_selections) |
| 1118 | XCAR (XCAR (XCDR (rest)))); | 1121 | CALLN (Frun_hook_with_args, Qx_lost_selection_functions, |
| 1122 | XCAR (XCAR (XCDR (rest)))); | ||
| 1123 | else | ||
| 1124 | lost = Fcons (XCAR (XCDR (rest)), lost); | ||
| 1125 | |||
| 1119 | XSETCDR (rest, XCDR (XCDR (rest))); | 1126 | XSETCDR (rest, XCDR (XCDR (rest))); |
| 1120 | break; | 1127 | break; |
| 1121 | } | 1128 | } |
| 1129 | |||
| 1130 | if (x_auto_preserve_selections) | ||
| 1131 | x_preserve_selections (dpyinfo, lost); | ||
| 1122 | } | 1132 | } |
| 1123 | 1133 | ||
| 1124 | /* True if any properties for DISPLAY and WINDOW | 1134 | /* True if any properties for DISPLAY and WINDOW |
diff --git a/src/xterm.c b/src/xterm.c index 2b83efb2288..f86e4708ec5 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -27951,6 +27951,62 @@ x_uncatch_errors_for_lisp (struct x_display_info *dpyinfo) | |||
| 27951 | x_stop_ignoring_errors (dpyinfo); | 27951 | x_stop_ignoring_errors (dpyinfo); |
| 27952 | } | 27952 | } |
| 27953 | 27953 | ||
| 27954 | /* Preserve the selections in LOST in another frame on DPYINFO. LOST | ||
| 27955 | is a list of local selections that were lost, due to their frame | ||
| 27956 | being deleted. */ | ||
| 27957 | |||
| 27958 | void | ||
| 27959 | x_preserve_selections (struct x_display_info *dpyinfo, Lisp_Object lost) | ||
| 27960 | { | ||
| 27961 | Lisp_Object tail, frame, new_owner, tem; | ||
| 27962 | Time timestamp; | ||
| 27963 | Window owner; | ||
| 27964 | |||
| 27965 | new_owner = Qnil; | ||
| 27966 | |||
| 27967 | FOR_EACH_FRAME (tail, frame) | ||
| 27968 | { | ||
| 27969 | if (FRAME_X_P (XFRAME (frame)) | ||
| 27970 | && FRAME_DISPLAY_INFO (XFRAME (frame)) == dpyinfo) | ||
| 27971 | { | ||
| 27972 | new_owner = frame; | ||
| 27973 | break; | ||
| 27974 | } | ||
| 27975 | } | ||
| 27976 | |||
| 27977 | tail = lost; | ||
| 27978 | |||
| 27979 | FOR_EACH_TAIL_SAFE (tail) | ||
| 27980 | { | ||
| 27981 | tem = XCAR (tail); | ||
| 27982 | |||
| 27983 | /* The selection is really lost (since we cannot find a new | ||
| 27984 | owner), so run the appropriate hooks. */ | ||
| 27985 | if (NILP (new_owner)) | ||
| 27986 | CALLN (Frun_hook_with_args, Qx_lost_selection_functions, | ||
| 27987 | XCAR (tem)); | ||
| 27988 | else | ||
| 27989 | { | ||
| 27990 | CONS_TO_INTEGER (XCAR (XCDR (XCDR (tem))), Time, timestamp); | ||
| 27991 | |||
| 27992 | /* This shouldn't be able to signal any errors, despite the | ||
| 27993 | call to `x_check_errors' inside. */ | ||
| 27994 | x_own_selection (XCAR (tem), XCAR (XCDR (tem)), | ||
| 27995 | new_owner, XCAR (XCDR (XCDR (XCDR (XCDR (tem))))), | ||
| 27996 | timestamp); | ||
| 27997 | |||
| 27998 | /* Now check if we still don't own that selection, which can | ||
| 27999 | happen if another program set itself as the owner. */ | ||
| 28000 | owner = XGetSelectionOwner (dpyinfo->display, | ||
| 28001 | symbol_to_x_atom (dpyinfo, XCAR (tem))); | ||
| 28002 | |||
| 28003 | if (owner != FRAME_X_WINDOW (XFRAME (new_owner))) | ||
| 28004 | CALLN (Frun_hook_with_args, Qx_lost_selection_functions, | ||
| 28005 | XCAR (tem)); | ||
| 28006 | } | ||
| 28007 | } | ||
| 28008 | } | ||
| 28009 | |||
| 27954 | void | 28010 | void |
| 27955 | syms_of_xterm (void) | 28011 | syms_of_xterm (void) |
| 27956 | { | 28012 | { |
| @@ -28265,4 +28321,11 @@ reply from the X server, and signal any errors that occurred while | |||
| 28265 | executing the protocol request. Otherwise, errors will be silently | 28321 | executing the protocol request. Otherwise, errors will be silently |
| 28266 | ignored without waiting, which is generally faster. */); | 28322 | ignored without waiting, which is generally faster. */); |
| 28267 | x_fast_protocol_requests = false; | 28323 | x_fast_protocol_requests = false; |
| 28324 | |||
| 28325 | DEFVAR_BOOL ("x-auto-preserve-selections", x_auto_preserve_selections, | ||
| 28326 | doc: /* Whether or not to transfer selection ownership when deleting a frame. | ||
| 28327 | When non-nil, deleting a frame that is currently the owner of a | ||
| 28328 | selection will cause its ownership to be transferred to another frame | ||
| 28329 | on the same display. */); | ||
| 28330 | x_auto_preserve_selections = true; | ||
| 28268 | } | 28331 | } |
diff --git a/src/xterm.h b/src/xterm.h index a1ddf13463c..9b91ee45569 100644 --- a/src/xterm.h +++ b/src/xterm.h | |||
| @@ -1643,6 +1643,7 @@ extern void xic_set_statusarea (struct frame *); | |||
| 1643 | extern void xic_set_xfontset (struct frame *, const char *); | 1643 | extern void xic_set_xfontset (struct frame *, const char *); |
| 1644 | extern bool x_defined_color (struct frame *, const char *, Emacs_Color *, | 1644 | extern bool x_defined_color (struct frame *, const char *, Emacs_Color *, |
| 1645 | bool, bool); | 1645 | bool, bool); |
| 1646 | extern void x_preserve_selections (struct x_display_info *, Lisp_Object); | ||
| 1646 | #ifdef HAVE_X_I18N | 1647 | #ifdef HAVE_X_I18N |
| 1647 | extern void free_frame_xic (struct frame *); | 1648 | extern void free_frame_xic (struct frame *); |
| 1648 | # if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT | 1649 | # if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT |