aboutsummaryrefslogtreecommitdiffstats
path: root/src/xterm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xterm.c')
-rw-r--r--src/xterm.c153
1 files changed, 152 insertions, 1 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 3cc730c4eeb..557555e7a4d 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1104,6 +1104,13 @@ struct frame *x_dnd_finish_frame;
1104 important information. */ 1104 important information. */
1105bool x_dnd_waiting_for_finish; 1105bool x_dnd_waiting_for_finish;
1106 1106
1107/* Whether or not to move the tooltip along with the mouse pointer
1108 during drag-and-drop. */
1109static bool x_dnd_update_tooltip;
1110
1111/* Monitor attribute list used for updating the tooltip position. */
1112static Lisp_Object x_dnd_monitors;
1113
1107/* The display the drop target that is supposed to send information is 1114/* The display the drop target that is supposed to send information is
1108 on. */ 1115 on. */
1109static Display *x_dnd_finish_display; 1116static Display *x_dnd_finish_display;
@@ -4190,6 +4197,12 @@ x_free_dnd_targets (void)
4190} 4197}
4191 4198
4192static void 4199static void
4200x_clear_dnd_monitors (void)
4201{
4202 x_dnd_monitors = Qnil;
4203}
4204
4205static void
4193x_free_dnd_toplevels (void) 4206x_free_dnd_toplevels (void)
4194{ 4207{
4195 if (!x_dnd_use_toplevels || !x_dnd_toplevels) 4208 if (!x_dnd_use_toplevels || !x_dnd_toplevels)
@@ -10738,7 +10751,8 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
10738 Lisp_Object return_frame, Atom *ask_action_list, 10751 Lisp_Object return_frame, Atom *ask_action_list,
10739 const char **ask_action_names, size_t n_ask_actions, 10752 const char **ask_action_names, size_t n_ask_actions,
10740 bool allow_current_frame, Atom *target_atoms, 10753 bool allow_current_frame, Atom *target_atoms,
10741 int ntargets, Lisp_Object selection_target_list) 10754 int ntargets, Lisp_Object selection_target_list,
10755 bool follow_tooltip)
10742{ 10756{
10743#ifndef USE_GTK 10757#ifndef USE_GTK
10744 XEvent next_event; 10758 XEvent next_event;
@@ -10941,6 +10955,15 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
10941 unblock_input (); 10955 unblock_input ();
10942 } 10956 }
10943 10957
10958 if (follow_tooltip)
10959 {
10960 x_dnd_monitors
10961 = Fx_display_monitor_attributes_list (frame);
10962 record_unwind_protect_void (x_clear_dnd_monitors);
10963 }
10964
10965 x_dnd_update_tooltip = follow_tooltip;
10966
10944 /* This shouldn't happen. */ 10967 /* This shouldn't happen. */
10945 if (x_dnd_toplevels) 10968 if (x_dnd_toplevels)
10946 x_dnd_free_toplevels (true); 10969 x_dnd_free_toplevels (true);
@@ -15131,6 +15154,106 @@ mouse_or_wdesc_frame (struct x_display_info *dpyinfo, int wdesc)
15131 } 15154 }
15132} 15155}
15133 15156
15157static void
15158x_dnd_compute_tip_xy (int *root_x, int *root_y, Lisp_Object attributes)
15159{
15160 Lisp_Object monitor, geometry;
15161 int min_x, min_y, max_x, max_y;
15162 int width, height;
15163
15164 width = FRAME_PIXEL_WIDTH (XFRAME (tip_frame));
15165 height = FRAME_PIXEL_HEIGHT (XFRAME (tip_frame));
15166
15167 max_y = -1;
15168
15169 /* Try to determine the monitor where the mouse pointer is and
15170 its geometry. See bug#22549. */
15171 while (CONSP (attributes))
15172 {
15173 monitor = XCAR (attributes);
15174 geometry = assq_no_quit (Qgeometry, monitor);
15175
15176 if (CONSP (geometry))
15177 {
15178 min_x = XFIXNUM (Fnth (make_fixnum (1), geometry));
15179 min_y = XFIXNUM (Fnth (make_fixnum (2), geometry));
15180 max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry));
15181 max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry));
15182
15183 if (min_x <= *root_x && *root_x < max_x
15184 && min_y <= *root_y && *root_y < max_y)
15185 break;
15186
15187 max_y = -1;
15188 }
15189
15190 attributes = XCDR (attributes);
15191 }
15192
15193 /* It was not possible to determine the monitor's geometry, so we
15194 assign some sane defaults here: */
15195 if (max_y < 0)
15196 {
15197 min_x = 0;
15198 min_y = 0;
15199 max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (x_dnd_frame));
15200 max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (x_dnd_frame));
15201 }
15202
15203 if (*root_y + XFIXNUM (tip_dy) <= min_y)
15204 *root_y = min_y; /* Can happen for negative dy */
15205 else if (*root_y + XFIXNUM (tip_dy) + height <= max_y)
15206 /* It fits below the pointer */
15207 *root_y += XFIXNUM (tip_dy);
15208 else if (height + XFIXNUM (tip_dy) + min_y <= *root_y)
15209 /* It fits above the pointer. */
15210 *root_y -= height + XFIXNUM (tip_dy);
15211 else
15212 /* Put it on the top. */
15213 *root_y = min_y;
15214
15215 if (*root_x + XFIXNUM (tip_dx) <= min_x)
15216 *root_x = 0; /* Can happen for negative dx */
15217 else if (*root_x + XFIXNUM (tip_dx) + width <= max_x)
15218 /* It fits to the right of the pointer. */
15219 *root_x += XFIXNUM (tip_dx);
15220 else if (width + XFIXNUM (tip_dx) + min_x <= *root_x)
15221 /* It fits to the left of the pointer. */
15222 *root_x -= width + XFIXNUM (tip_dx);
15223 else
15224 /* Put it left justified on the screen -- it ought to fit that way. */
15225 *root_x = min_x;
15226}
15227
15228static void
15229x_dnd_update_tooltip_position (int root_x, int root_y)
15230{
15231 struct frame *tip_f;
15232
15233 if (!x_dnd_in_progress || !x_dnd_update_tooltip)
15234 return;
15235
15236 if (!FRAMEP (tip_frame))
15237 return;
15238
15239 tip_f = XFRAME (tip_frame);
15240
15241 if (!FRAME_LIVE_P (tip_f)
15242 || (FRAME_X_DISPLAY (tip_f)
15243 != FRAME_X_DISPLAY (x_dnd_frame)))
15244 return;
15245
15246 if (tip_window != None
15247 && FIXNUMP (tip_dx) && FIXNUMP (tip_dy))
15248 {
15249 x_dnd_compute_tip_xy (&root_x, &root_y,
15250 x_dnd_monitors);
15251
15252 XMoveWindow (FRAME_X_DISPLAY (x_dnd_frame),
15253 tip_window, root_x, root_y);
15254 }
15255}
15256
15134/* Get the window underneath the pointer, see if it moved, and update 15257/* Get the window underneath the pointer, see if it moved, and update
15135 the DND state accordingly. */ 15258 the DND state accordingly. */
15136static void 15259static void
@@ -15292,6 +15415,8 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp)
15292 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame), 15415 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
15293 target, &dmsg); 15416 target, &dmsg);
15294 } 15417 }
15418
15419 x_dnd_update_tooltip_position (root_x, root_y);
15295 } 15420 }
15296 /* The pointer moved out of the screen. */ 15421 /* The pointer moved out of the screen. */
15297 else if (x_dnd_last_protocol_version != -1) 15422 else if (x_dnd_last_protocol_version != -1)
@@ -17462,6 +17587,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
17462 target, &dmsg); 17587 target, &dmsg);
17463 } 17588 }
17464 17589
17590 x_dnd_update_tooltip_position (event->xmotion.x_root,
17591 event->xmotion.y_root);
17592
17465 goto OTHER; 17593 goto OTHER;
17466 } 17594 }
17467 17595
@@ -17966,6 +18094,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
17966 { 18094 {
17967 x_dnd_end_window = x_dnd_last_seen_window; 18095 x_dnd_end_window = x_dnd_last_seen_window;
17968 x_dnd_in_progress = false; 18096 x_dnd_in_progress = false;
18097
18098 if (x_dnd_update_tooltip
18099 && FRAMEP (tip_frame)
18100 && FRAME_LIVE_P (XFRAME (tip_frame))
18101 && (FRAME_X_DISPLAY (XFRAME (tip_frame))
18102 == FRAME_X_DISPLAY (x_dnd_frame)))
18103 Fx_hide_tip ();
18104
17969 x_dnd_finish_frame = x_dnd_frame; 18105 x_dnd_finish_frame = x_dnd_frame;
17970 18106
17971 if (x_dnd_last_seen_window != None 18107 if (x_dnd_last_seen_window != None
@@ -19172,6 +19308,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
19172 target, &dmsg); 19308 target, &dmsg);
19173 } 19309 }
19174 19310
19311 x_dnd_update_tooltip_position (xev->root_x, xev->root_y);
19312
19175 goto XI_OTHER; 19313 goto XI_OTHER;
19176 } 19314 }
19177 19315
@@ -19332,6 +19470,16 @@ handle_one_xevent (struct x_display_info *dpyinfo,
19332 x_dnd_end_window = x_dnd_last_seen_window; 19470 x_dnd_end_window = x_dnd_last_seen_window;
19333 x_dnd_in_progress = false; 19471 x_dnd_in_progress = false;
19334 19472
19473 /* If a tooltip that we're following is
19474 displayed, hide it now. */
19475
19476 if (x_dnd_update_tooltip
19477 && FRAMEP (tip_frame)
19478 && FRAME_LIVE_P (XFRAME (tip_frame))
19479 && (FRAME_X_DISPLAY (XFRAME (tip_frame))
19480 == FRAME_X_DISPLAY (x_dnd_frame)))
19481 Fx_hide_tip ();
19482
19335 /* This doesn't have to be marked since it 19483 /* This doesn't have to be marked since it
19336 is only accessed if 19484 is only accessed if
19337 x_dnd_waiting_for_finish is true, which 19485 x_dnd_waiting_for_finish is true, which
@@ -26645,6 +26793,9 @@ syms_of_xterm (void)
26645 x_error_message = NULL; 26793 x_error_message = NULL;
26646 PDUMPER_IGNORE (x_error_message); 26794 PDUMPER_IGNORE (x_error_message);
26647 26795
26796 x_dnd_monitors = Qnil;
26797 staticpro (&x_dnd_monitors);
26798
26648 DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms"); 26799 DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
26649 DEFSYM (Qlatin_1, "latin-1"); 26800 DEFSYM (Qlatin_1, "latin-1");
26650 DEFSYM (Qnow, "now"); 26801 DEFSYM (Qnow, "now");