aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-07-12 10:47:23 +0800
committerPo Lu2022-07-12 10:47:51 +0800
commit86d128c6c3acca1665addc65aa43ff80572f46e8 (patch)
treeef1dd26be80acf43384c8146e3c784a09ab0cb0d /src
parent7ac313ea87b4761baf975718e4fa3200f61a0ad9 (diff)
downloademacs-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.c24
-rw-r--r--src/xterm.c63
-rw-r--r--src/xterm.h1
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)
1091void 1091void
1092x_clear_frame_selections (struct frame *f) 1092x_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
27958void
27959x_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
27954void 28010void
27955syms_of_xterm (void) 28011syms_of_xterm (void)
27956{ 28012{
@@ -28265,4 +28321,11 @@ reply from the X server, and signal any errors that occurred while
28265executing the protocol request. Otherwise, errors will be silently 28321executing the protocol request. Otherwise, errors will be silently
28266ignored without waiting, which is generally faster. */); 28322ignored 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.
28327When non-nil, deleting a frame that is currently the owner of a
28328selection will cause its ownership to be transferred to another frame
28329on 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 *);
1643extern void xic_set_xfontset (struct frame *, const char *); 1643extern void xic_set_xfontset (struct frame *, const char *);
1644extern bool x_defined_color (struct frame *, const char *, Emacs_Color *, 1644extern bool x_defined_color (struct frame *, const char *, Emacs_Color *,
1645 bool, bool); 1645 bool, bool);
1646extern void x_preserve_selections (struct x_display_info *, Lisp_Object);
1646#ifdef HAVE_X_I18N 1647#ifdef HAVE_X_I18N
1647extern void free_frame_xic (struct frame *); 1648extern 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