summaryrefslogtreecommitdiff
path: root/src/xfns.c
diff options
context:
space:
mode:
authorMartin Rudalics <rudalics@gmx.at>2018-01-18 10:36:47 +0100
committerMartin Rudalics <rudalics@gmx.at>2018-01-18 10:36:47 +0100
commite462308f03c9c16c47abc82d6f339ca9d18898f9 (patch)
tree49cc7306cb35a007eb43a2fe122be881f5cfa13f /src/xfns.c
parent6e9f20b3ff49adfc05a7f4b49b1b92daa4fb1ca9 (diff)
downloademacs-e462308f03c9c16c47abc82d6f339ca9d18898f9.tar.gz
Fix some tooltip related problems
Replace 'tooltip' frame parameter with a 'tooltip' member in the frame structure. For GTK+ builds use 'tip_last_frame' to find the frame for which the currently visible tooltip was made. For modeline help-echoing have tooltips show applicable actions only. * lisp/bindings.el (mode-line-default-help-echo): New function as default value of homonymous option. * src/dispextern.h (tip_frame, tip_window): Remove declarations. * src/frame.c (make_frame): Initialize new frame structure member 'tooltip'. (Fframe_list, other_frames): Rewrite with new macro FRAME_TOOLTIP_P. * src/frame.h (struct frame): New member 'tooltip'. (FRAME_TOOLTIP_P): New macro. * src/gtkutil.c (xg_prepare_tooltip, xg_hide_tooltip): Rewrite using boolean return values. * src/nsfns.m (tip_frame): Remove declaration. * src/w32fns.c (w32_display_monitor_attributes_list) (w32_display_monitor_attributes_list_fallback): Rewrite with new macro FRAME_TOOLTIP_P. (tip_last_string, tip_last_frame, tip_last_parms): New Lisp scalars replacing Lisp vector last_show_tip_args. (x_create_tip_frame): Set new frame's 'tooltip' structure member to true. (x_hide_tip): Additionally test tip_frame for liveness. (Fx_show_tip): Handle last_show_tip_args to tip_last_frame, tip_last_string and tip_last_parms conversion. (syms_of_w32fns): staticpro tip_last_frame, tip_last_string and tip_last_parms instead of last_show_tip_args. * src/w32term.c (w32_read_socket, x_new_font): Rewrite with new macro FRAME_TOOLTIP_P. * src/w32term.h (tip_window): Add external declaration. * src/xdisp.c (x_consider_frame_title, prepare_menu_bars) (should_produce_line_number): Rewrite with new macro FRAME_TOOLTIP_P. (note_mode_line_or_margin_highlight): If `mode-line-default-help-echo' specifies a function, call it to produce help echo string. * src/xfns.c (x_make_monitor_attribute_list) (Fx_display_monitor_attributes_list): Rewrite with new macro FRAME_TOOLTIP_P. (tip_last_string, tip_last_frame, tip_last_parms): New Lisp scalars replacing Lisp vector last_show_tip_args. (x_create_tip_frame): Set new frame's 'tooltip' structure member to true. (x_hide_tip): Rewrite with additional tests of frames for liveness and taking into account that for GTK+ tips the reference frame is now stored in tip_last_frame instead of tip_frame. (Fx_show_tip): Handle last_show_tip_args to tip_last_frame, tip_last_string and tip_last_parms conversion. For GTK+ store FRAME argument in tip_last-frame. (syms_of_xfns): staticpro tip_last_frame, tip_last_string and tip_last_parms instead of last_show_tip_args. * src/xterm.c (x_update_begin, handle_one_xevent, x_new_font) (x_set_window_size): Rewrite with new macro FRAME_TOOLTIP_P. * src/xterm.h (tip_window): Add external declaration. * etc/NEWS: Mention new modeline tooltips behavior.
Diffstat (limited to 'src/xfns.c')
-rw-r--r--src/xfns.c257
1 files changed, 164 insertions, 93 deletions
diff --git a/src/xfns.c b/src/xfns.c
index 12b7d83c383..43c55cca643 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4612,8 +4612,9 @@ x_make_monitor_attribute_list (struct MonitorInfo *monitors,
{
struct frame *f = XFRAME (frame);
- if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo
- && !EQ (frame, tip_frame))
+ if (FRAME_X_P (f)
+ && FRAME_DISPLAY_INFO (f) == dpyinfo
+ && !FRAME_TOOLTIP_P (f))
{
int i = x_get_monitor_for_frame (f, monitors, n_monitors);
ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
@@ -4914,12 +4915,9 @@ Internal use only, use `display-monitor-attributes-list' instead. */)
{
struct frame *f = XFRAME (frame);
- if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo
- && !(EQ (frame, tip_frame)
-#ifdef USE_GTK
- && !NILP (Fframe_parameter (tip_frame, Qtooltip))
-#endif
- ))
+ if (FRAME_X_P (f)
+ && FRAME_DISPLAY_INFO (f) == dpyinfo
+ && !FRAME_TOOLTIP_P (f))
{
GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
@@ -6052,22 +6050,27 @@ Otherwise, the return value is a vector with the following fields:
***********************************************************************/
static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
- Lisp_Object, int, int, int *, int *);
-
-/* The frame of a currently visible tooltip. */
+ Lisp_Object, int, int, int *, int *);
+/* The frame of the currently visible tooltip. */
Lisp_Object tip_frame;
-/* If non-nil, a timer started that hides the last tooltip when it
+/* The window-system window corresponding to the frame of the
+ currently visible tooltip. */
+Window tip_window;
+
+/* A timer that hides or deletes the currently visible tooltip when it
fires. */
+Lisp_Object tip_timer;
-static Lisp_Object tip_timer;
-Window tip_window;
+/* STRING argument of last `x-show-tip' call. */
+Lisp_Object tip_last_string;
-/* If non-nil, a vector of 3 elements containing the last args
- with which x-show-tip was called. See there. */
+/* FRAME argument of last `x-show-tip' call. */
+Lisp_Object tip_last_frame;
-static Lisp_Object last_show_tip_args;
+/* PARMS argument of last `x-show-tip' call. */
+Lisp_Object tip_last_parms;
static void
@@ -6141,6 +6144,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
f->output_data.x->white_relief.pixel = -1;
f->output_data.x->black_relief.pixel = -1;
+ f->tooltip = true;
fset_icon_name (f, Qnil);
FRAME_DISPLAY_INFO (f) = dpyinfo;
f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
@@ -6405,7 +6409,9 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
the display in *ROOT_X, and *ROOT_Y. */
static void
-compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object dy, int width, int height, int *root_x, int *root_y)
+compute_tip_xy (struct frame *f,
+ Lisp_Object parms, Lisp_Object dx, Lisp_Object dy,
+ int width, int height, int *root_x, int *root_y)
{
Lisp_Object left, top, right, bottom;
int win_x, win_y;
@@ -6502,7 +6508,19 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object
}
-/* Hide tooltip. Delete its frame if DELETE is true. */
+/**
+ * x_hide_tip:
+ *
+ * Hide currently visible tooltip and cancel its timer.
+ *
+ * If GTK+ system tooltips are used, this will try to hide the tooltip
+ * referenced by the x_output structure of tooltip_last_frame. For
+ * Emacs tooltips this will try to make tooltip_frame invisible (if
+ * DELETE is false) or delete tooltip_frame (if DELETE is true).
+ *
+ * Return Qt if the tooltip was either deleted or made invisible, Qnil
+ * otherwise.
+ */
static Lisp_Object
x_hide_tip (bool delete)
{
@@ -6512,10 +6530,17 @@ x_hide_tip (bool delete)
tip_timer = Qnil;
}
-
- if (NILP (tip_frame)
- || (!delete && FRAMEP (tip_frame)
- && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
+#ifdef USE_GTK
+ /* The GTK+ system tooltip window can be found via the x_output
+ structure of tip_last_frame, if it still exists. */
+ if (x_gtk_use_system_tooltips && NILP (tip_last_frame))
+ return Qnil;
+ else if (!x_gtk_use_system_tooltips
+ && (NILP (tip_frame)
+ || (!delete
+ && FRAMEP (tip_frame)
+ && FRAME_LIVE_P (XFRAME (tip_frame))
+ && !FRAME_VISIBLE_P (XFRAME (tip_frame)))))
return Qnil;
else
{
@@ -6526,61 +6551,114 @@ x_hide_tip (bool delete)
specbind (Qinhibit_redisplay, Qt);
specbind (Qinhibit_quit, Qt);
-#ifdef USE_GTK
- {
- /* When using system tooltip, tip_frame is the Emacs frame on
- which the tip is shown. */
- struct frame *f = XFRAME (tip_frame);
-
- if (FRAME_LIVE_P (f) && xg_hide_tooltip (f))
- {
- tip_frame = Qnil;
- was_open = Qt;
- }
- }
-#endif
+ if (x_gtk_use_system_tooltips)
+ {
+ /* The GTK+ system tooltip window is stored in the x_output
+ structure of tip_last_frame. */
+ struct frame *f = XFRAME (tip_last_frame);
- if (FRAMEP (tip_frame))
+ if (FRAME_LIVE_P (f))
+ {
+ if (xg_hide_tooltip (f))
+ was_open = Qt;
+ }
+ else
+ tip_last_frame = Qnil;
+ }
+ else
{
- if (delete)
+ if (FRAMEP (tip_frame))
{
- delete_frame (tip_frame, Qnil);
- tip_frame = Qnil;
+ struct frame *f = XFRAME (tip_frame);
+
+ if (FRAME_LIVE_P (f))
+ {
+ if (delete)
+ {
+ delete_frame (tip_frame, Qnil);
+ tip_frame = Qnil;
+ }
+ else
+ x_make_frame_invisible (f);
+
+ was_open = Qt;
+ }
+ else
+ tip_frame = Qnil;
}
else
- x_make_frame_invisible (XFRAME (tip_frame));
+ tip_frame = Qnil;
+ }
+
+ return unbind_to (count, was_open);
+ }
+#else /* not USE_GTK */
+ if (NILP (tip_frame)
+ || (!delete
+ && FRAMEP (tip_frame)
+ && FRAME_LIVE_P (XFRAME (tip_frame))
+ && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
+ return Qnil;
+ else
+ {
+ ptrdiff_t count;
+ Lisp_Object was_open = Qnil;
+
+ count = SPECPDL_INDEX ();
+ specbind (Qinhibit_redisplay, Qt);
+ specbind (Qinhibit_quit, Qt);
+
+ if (FRAMEP (tip_frame))
+ {
+ struct frame *f = XFRAME (tip_frame);
- was_open = Qt;
+ if (FRAME_LIVE_P (f))
+ {
+ if (delete)
+ {
+ delete_frame (tip_frame, Qnil);
+ tip_frame = Qnil;
+ }
+ else
+ x_make_frame_invisible (XFRAME (tip_frame));
#ifdef USE_LUCID
- /* Bloodcurdling hack alert: The Lucid menu bar widget's
- redisplay procedure is not called when a tip frame over
- menu items is unmapped. Redisplay the menu manually... */
- {
- Widget w;
- struct frame *f = SELECTED_FRAME ();
- if (FRAME_X_P (f) && FRAME_LIVE_P (f))
+ /* Bloodcurdling hack alert: The Lucid menu bar widget's
+ redisplay procedure is not called when a tip frame over
+ menu items is unmapped. Redisplay the menu manually... */
{
- w = f->output_data.x->menubar_widget;
+ Widget w;
+ struct frame *f = SELECTED_FRAME ();
- if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen)
- && w != NULL)
+ if (FRAME_X_P (f) && FRAME_LIVE_P (f))
{
- block_input ();
- xlwmenu_redisplay (w);
- unblock_input ();
+ w = f->output_data.x->menubar_widget;
+
+ if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen)
+ && w != NULL)
+ {
+ block_input ();
+ xlwmenu_redisplay (w);
+ unblock_input ();
+ }
}
}
- }
#endif /* USE_LUCID */
+
+ was_open = Qt;
+ }
+ else
+ tip_frame = Qnil;
}
else
tip_frame = Qnil;
return unbind_to (count, was_open);
}
+#endif /* USE_GTK */
}
+
DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
doc: /* Show STRING in a "tooltip" window on frame FRAME.
A tooltip window is a small X window displaying a string.
@@ -6611,7 +6689,8 @@ with offset DY added (default is -10).
A tooltip's maximum size is specified by `x-max-tooltip-size'.
Text larger than the specified size is clipped. */)
- (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
+ (Lisp_Object string, Lisp_Object frame, Lisp_Object parms,
+ Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
{
struct frame *f, *tip_f;
struct window *w;
@@ -6622,8 +6701,7 @@ Text larger than the specified size is clipped. */)
int old_windows_or_buffers_changed = windows_or_buffers_changed;
ptrdiff_t count = SPECPDL_INDEX ();
ptrdiff_t count_1;
- Lisp_Object window, size;
- Lisp_Object tip_buf;
+ Lisp_Object window, size, tip_buf;
AUTO_STRING (tip, " *tip*");
specbind (Qinhibit_redisplay, Qt);
@@ -6662,36 +6740,27 @@ Text larger than the specified size is clipped. */)
{
compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
xg_show_tooltip (f, root_x, root_y);
- /* This is used in Fx_hide_tip. */
- XSETFRAME (tip_frame, f);
+ tip_last_frame = frame;
}
+
unblock_input ();
if (ok) goto start_timer;
}
#endif /* USE_GTK */
- if (NILP (last_show_tip_args))
- last_show_tip_args = Fmake_vector (make_number (3), Qnil);
-
if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)))
{
- Lisp_Object last_string = AREF (last_show_tip_args, 0);
- Lisp_Object last_frame = AREF (last_show_tip_args, 1);
- Lisp_Object last_parms = AREF (last_show_tip_args, 2);
-
if (FRAME_VISIBLE_P (XFRAME (tip_frame))
- && EQ (frame, last_frame)
- && !NILP (Fequal_including_properties (last_string, string))
- && !NILP (Fequal (last_parms, parms)))
+ && EQ (frame, tip_last_frame)
+ && !NILP (Fequal_including_properties (tip_last_string, string))
+ && !NILP (Fequal (tip_last_parms, parms)))
{
/* Only DX and DY have changed. */
tip_f = XFRAME (tip_frame);
if (!NILP (tip_timer))
{
- Lisp_Object timer = tip_timer;
-
+ call1 (Qcancel_timer, tip_timer);
tip_timer = Qnil;
- call1 (Qcancel_timer, timer);
}
block_input ();
@@ -6703,15 +6772,14 @@ Text larger than the specified size is clipped. */)
goto start_timer;
}
- else if (tooltip_reuse_hidden_frame && EQ (frame, last_frame))
+ else if (tooltip_reuse_hidden_frame && EQ (frame, tip_last_frame))
{
bool delete = false;
Lisp_Object tail, elt, parm, last;
/* Check if every parameter in PARMS has the same value in
- last_parms unless it should be ignored by means of
- Vtooltip_reuse_hidden_frame_parameters. This may destruct
- last_parms which, however, will be recreated below. */
+ tip_last_parms. This may destruct tip_last_parms which,
+ however, will be recreated below. */
for (tail = parms; CONSP (tail); tail = XCDR (tail))
{
elt = XCAR (tail);
@@ -6721,7 +6789,7 @@ Text larger than the specified size is clipped. */)
if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
&& !EQ (parm, Qright) && !EQ (parm, Qbottom))
{
- last = Fassq (parm, last_parms);
+ last = Fassq (parm, tip_last_parms);
if (NILP (Fequal (Fcdr (elt), Fcdr (last))))
{
/* We lost, delete the old tooltip. */
@@ -6729,17 +6797,18 @@ Text larger than the specified size is clipped. */)
break;
}
else
- last_parms = call2 (Qassq_delete_all, parm, last_parms);
+ tip_last_parms =
+ call2 (Qassq_delete_all, parm, tip_last_parms);
}
else
- last_parms = call2 (Qassq_delete_all, parm, last_parms);
+ tip_last_parms =
+ call2 (Qassq_delete_all, parm, tip_last_parms);
}
- /* Now check if every parameter in what is left of last_parms
- with a non-nil value has an association in PARMS unless it
- should be ignored by means of
- Vtooltip_reuse_hidden_frame_parameters. */
- for (tail = last_parms; CONSP (tail); tail = XCDR (tail))
+ /* Now check if every parameter in what is left of
+ tip_last_parms with a non-nil value has an association in
+ PARMS. */
+ for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail))
{
elt = XCAR (tail);
parm = Fcar (elt);
@@ -6760,9 +6829,9 @@ Text larger than the specified size is clipped. */)
else
x_hide_tip (true);
- ASET (last_show_tip_args, 0, string);
- ASET (last_show_tip_args, 1, frame);
- ASET (last_show_tip_args, 2, parms);
+ tip_last_frame = frame;
+ tip_last_string = string;
+ tip_last_parms = parms;
if (!FRAMEP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame)))
{
@@ -7823,7 +7892,6 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
defsubr (&Sx_display_list);
defsubr (&Sx_synchronize);
defsubr (&Sx_backspace_delete_keys_p);
-
defsubr (&Sx_show_tip);
defsubr (&Sx_hide_tip);
defsubr (&Sx_double_buffered_p);
@@ -7831,9 +7899,12 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
staticpro (&tip_timer);
tip_frame = Qnil;
staticpro (&tip_frame);
-
- last_show_tip_args = Qnil;
- staticpro (&last_show_tip_args);
+ tip_last_frame = Qnil;
+ staticpro (&tip_last_frame);
+ tip_last_string = Qnil;
+ staticpro (&tip_last_string);
+ tip_last_parms = Qnil;
+ staticpro (&tip_last_parms);
defsubr (&Sx_uses_old_gtk_dialog);
#if defined (USE_MOTIF) || defined (USE_GTK)