diff options
author | Martin Rudalics <rudalics@gmx.at> | 2018-01-18 10:36:47 +0100 |
---|---|---|
committer | Martin Rudalics <rudalics@gmx.at> | 2018-01-18 10:36:47 +0100 |
commit | e462308f03c9c16c47abc82d6f339ca9d18898f9 (patch) | |
tree | 49cc7306cb35a007eb43a2fe122be881f5cfa13f /src/xfns.c | |
parent | 6e9f20b3ff49adfc05a7f4b49b1b92daa4fb1ca9 (diff) | |
download | emacs-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.c | 257 |
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) |