unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Fix some tooltip related problems
@ 2018-01-08  9:53 martin rudalics
  2018-01-08 14:41 ` Drew Adams
                   ` (2 more replies)
  0 siblings, 3 replies; 40+ messages in thread
From: martin rudalics @ 2018-01-08  9:53 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 3082 bytes --]

I intend to apply the attached patch to master.  Its ChangeLog goes
as below.  Comments and suggestions welcome.

Thanks, martin

-------------------------------------------------------------------

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.
(syms_of_frame): Remove Qtooltip.
* 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, remove setting of Qtooltip frame parameter.
(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, remove setting of Qtooltip frame parameter.
(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.

[-- Attachment #2: tooltip.diff --]
[-- Type: text/plain, Size: 40586 bytes --]

diff --git a/lisp/bindings.el b/lisp/bindings.el
index 8375bb9..c806cae 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -124,17 +124,56 @@ mode-line-eol-desc
 \f
 ;;; Mode line contents

-(defcustom mode-line-default-help-echo
-  "mouse-1: Select (drag to resize)\n\
-mouse-2: Make current window occupy the whole frame\n\
-mouse-3: Remove current window from display"
+(defun mode-line-default-help-echo (window)
+  "Return default help echo text for WINDOW's mode-line."
+  (let* ((frame (window-frame window))
+         (line-1a
+          ;; Show text to select window only if the window is not
+          ;; selected.
+          (not (eq window (frame-selected-window frame))))
+         (line-1b
+          ;; Show text to drag modeline if and only if it can be done.
+          (or (window-in-direction 'below window)
+              (let ((mini-window (minibuffer-window frame)))
+                (and (eq frame (window-frame mini-window))
+                     (or (minibuffer-window-active-p mini-window)
+                         (not resize-mini-windows))))))
+         (line-2
+          ;; Show text make window occupy the whole frame
+          ;; only if it doesn't already do that.
+          (not (eq window (frame-root-window frame))))
+         (line-3
+          ;; Show text to delete window only if that's possible.
+          (not (eq window (frame-root-window frame)))))
+    (when (or line-1a line-1b line-2 line-3)
+      (concat
+       (when (or line-1a line-1b)
+         (concat
+          "mouse-1: "
+          (when line-1a "Select")
+          (when line-1b
+            (if line-1a " (drag to resize)" "Drag to resize"))
+          (when (or line-2 line-3) "\n")))
+       (when line-2
+         (concat
+          "mouse-2: Make window occupy whole frame"
+          (when line-3 "\n")))
+       (when line-3
+         "mouse-3: Remove window from frame")))))
+
+(defcustom mode-line-default-help-echo #'mode-line-default-help-echo
   "Default help text for the mode line.
 If the value is a string, it specifies the tooltip or echo area
 message to display when the mouse is moved over the mode line.
-If the text at the mouse position has a `help-echo' text
-property, that overrides this variable."
-  :type '(choice (const :tag "No help" :value nil) string)
-  :version "24.3"
+If the value is a function, call that function with one argument
+- the window whose mode-line to display.  If the text at the
+mouse position has a `help-echo' text property, that overrides
+this variable."
+  :type '(choice
+          (const :tag "No help" :value nil)
+          function
+          string)
+  :version "27.1"
   :group 'mode-line)

 (defvar mode-line-front-space '(:eval (if (display-graphic-p) " " "-"))
diff --git a/src/dispextern.h b/src/dispextern.h
index 25bd6b2..441361b 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3452,15 +3452,6 @@ int face_at_string_position (struct window *, Lisp_Object, ptrdiff_t, ptrdiff_t,
 void x_implicitly_set_name (struct frame *, Lisp_Object, Lisp_Object);
 void x_change_tool_bar_height (struct frame *f, int);

-/* The frame used to display a tooltip.
-
-   Note: In a GTK build with non-zero x_gtk_use_system_tooltips, this
-   variable holds the frame that shows the tooltip, not the frame of
-   the tooltip itself, so checking whether a frame is a tooltip frame
-   cannot just compare the frame to what this variable holds.  */
-extern Lisp_Object tip_frame;
-
-extern Window tip_window;
 extern frame_parm_handler x_frame_parm_handlers[];

 extern void start_hourglass (void);
diff --git a/src/frame.c b/src/frame.c
index 1c6289a..73b4b4e 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -832,6 +832,7 @@ struct frame *
   f->no_focus_on_map = false;
   f->no_accept_focus = false;
   f->z_group = z_group_none;
+  f->tooltip = false;
 #if ! defined (USE_GTK) && ! defined (HAVE_NS)
   f->last_tool_bar_item = -1;
 #endif
@@ -1467,20 +1468,21 @@ of them (the selected terminal frame) is actually displayed.
 \f
 DEFUN ("frame-list", Fframe_list, Sframe_list,
        0, 0, 0,
-       doc: /* Return a list of all live frames.  */)
+       doc: /* Return a list of all live frames.
+The return value does not include any tooltip frame.  */)
   (void)
 {
-  Lisp_Object frames;
-  frames = Fcopy_sequence (Vframe_list);
 #ifdef HAVE_WINDOW_SYSTEM
-  if (FRAMEP (tip_frame)
-#ifdef USE_GTK
-      && !NILP (Fframe_parameter (tip_frame, Qtooltip))
-#endif
-      )
-    frames = Fdelq (tip_frame, frames);
-#endif
-  return frames;
+  Lisp_Object list = Qnil, tail, frame;
+
+  FOR_EACH_FRAME (tail, frame)
+    if (!FRAME_TOOLTIP_P (XFRAME (frame)))
+      list = Fcons (frame, list);
+  /* Reverse list for consistency with the !HAVE_WINDOW_SYSTEM case.  */
+  return Fnreverse (list);
+#else /* !HAVE_WINDOW_SYSTEM */
+  return Fcopy_sequence (Vframe_list);
+#endif /* HAVE_WINDOW_SYSTEM */
 }

 DEFUN ("frame-parent", Fframe_parent, Sframe_parent,
@@ -1711,7 +1713,8 @@ of them (the selected terminal frame) is actually displayed.
  * other_frames:
  *
  * Return true if there exists at least one visible or iconified frame
- * but F.  Return false otherwise.
+ * but F.  Tooltip frames do not qualify as candidates.  Return false
+ * if no such frame exists.
  *
  * INVISIBLE true means we are called from make_frame_invisible where
  * such a frame must be visible or iconified.  INVISIBLE nil means we
@@ -1725,7 +1728,6 @@ of them (the selected terminal frame) is actually displayed.
 other_frames (struct frame *f, bool invisible, bool force)
 {
   Lisp_Object frames, frame, frame1;
-  struct frame *f1;
   Lisp_Object minibuffer_window = FRAME_MINIBUF_WINDOW (f);

   XSETFRAME (frame, f);
@@ -1735,7 +1737,8 @@ of them (the selected terminal frame) is actually displayed.

   FOR_EACH_FRAME (frames, frame1)
     {
-      f1 = XFRAME (frame1);
+      struct frame *f1 = XFRAME (frame1);
+
       if (f != f1)
 	{
 	  /* Verify that we can still talk to the frame's X window, and
@@ -1744,7 +1747,7 @@ of them (the selected terminal frame) is actually displayed.
 	  if (FRAME_WINDOW_P (f1))
 	    x_sync (f1);
 #endif
-	  if (NILP (Fframe_parameter (frame1, Qtooltip))
+	  if (!FRAME_TOOLTIP_P (f1)
 	      /* Tooltips and child frames count neither for
 		 invisibility nor for deletions.  */
 	      && !FRAME_PARENT_FRAME (f1)
@@ -1877,7 +1880,7 @@ of them (the selected terminal frame) is actually displayed.
 	}
     }

-  is_tooltip_frame = !NILP (Fframe_parameter (frame, Qtooltip));
+  is_tooltip_frame = FRAME_TOOLTIP_P (f);

   /* Run `delete-frame-functions' unless FORCE is `noelisp' or
      frame is a tooltip.  FORCE is set to `noelisp' when handling
@@ -1925,27 +1928,31 @@ of them (the selected terminal frame) is actually displayed.
 	 Do not call next_frame here because it may loop forever.
 	 See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=15025.  */
       FOR_EACH_FRAME (tail, frame1)
-	if (!EQ (frame, frame1)
-	    && NILP (Fframe_parameter (frame1, Qtooltip))
-	    && (FRAME_TERMINAL (XFRAME (frame))
-		== FRAME_TERMINAL (XFRAME (frame1)))
-	    && FRAME_VISIBLE_P (XFRAME (frame1)))
-         break;
+	{
+	  struct frame *f1 = XFRAME (frame1);
+
+	  if (!EQ (frame, frame1)
+	      && !FRAME_TOOLTIP_P (f1)
+	      && FRAME_TERMINAL (f) == FRAME_TERMINAL (f1)
+	      && FRAME_VISIBLE_P (f1))
+	    break;
+	}

       /* If there is none, find *some* other frame.  */
       if (NILP (frame1) || EQ (frame1, frame))
 	{
 	  FOR_EACH_FRAME (tail, frame1)
 	    {
+	      struct frame *f1 = XFRAME (frame1);
+
 	      if (!EQ (frame, frame1)
-		  && FRAME_LIVE_P (XFRAME (frame1))
-		  && NILP (Fframe_parameter (frame1, Qtooltip)))
+		  && FRAME_LIVE_P (f1)
+		  && !FRAME_TOOLTIP_P (f1))
 		{
-		  /* Do not change a text terminal's top-frame.  */
-		  struct frame *f1 = XFRAME (frame1);
 		  if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1))
 		    {
 		      Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
+
 		      if (!EQ (top_frame, frame))
 			frame1 = top_frame;
 		    }
@@ -5617,7 +5624,6 @@ or a list (- N) meaning -N pixels relative to bottom/right corner.
   DEFSYM (Qgeometry, "geometry");
   DEFSYM (Qicon_left, "icon-left");
   DEFSYM (Qicon_top, "icon-top");
-  DEFSYM (Qtooltip, "tooltip");
   DEFSYM (Quser_position, "user-position");
   DEFSYM (Quser_size, "user-size");
   DEFSYM (Qwindow_id, "window-id");
diff --git a/src/frame.h b/src/frame.h
index 402d6c0..2c9c414 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -342,6 +342,9 @@ struct frame
   ENUM_BF (output_method) output_method : 3;

 #ifdef HAVE_WINDOW_SYSTEM
+  /* True if this frame is a tooltip frame.  */
+  bool_bf tooltip : 1;
+
   /* See FULLSCREEN_ enum on top.  */
   ENUM_BF (fullscreen_type) want_fullscreen : 4;

@@ -351,9 +354,7 @@ struct frame

   /* Nonzero if we should actually display horizontal scroll bars on this frame.  */
   bool_bf horizontal_scroll_bars : 1;
-#endif /* HAVE_WINDOW_SYSTEM */

-#if defined (HAVE_WINDOW_SYSTEM)
   /* True if this is an undecorated frame.  */
   bool_bf undecorated : 1;

@@ -967,6 +968,7 @@ struct frame
 #define FRAME_Z_GROUP_ABOVE_SUSPENDED(f)	\
   ((f)->z_group == z_group_above_suspended)
 #define FRAME_Z_GROUP_BELOW(f) ((f)->z_group == z_group_below)
+#define FRAME_TOOLTIP_P(f) ((f)->tooltip)
 #ifdef NS_IMPL_COCOA
 #define FRAME_NS_APPEARANCE(f) ((f)->ns_appearance)
 #define FRAME_NS_TRANSPARENT_TITLEBAR(f) ((f)->ns_transparent_titlebar)
@@ -983,6 +985,7 @@ struct frame
 #define FRAME_Z_GROUP_NONE(f) ((void) (f), true)
 #define FRAME_Z_GROUP_ABOVE(f) ((void) (f), false)
 #define FRAME_Z_GROUP_BELOW(f) ((void) (f), false)
+#define FRAME_TOOLTIP_P(f) ((void) f, false)
 #endif /* HAVE_WINDOW_SYSTEM */

 /* Whether horizontal scroll bars are currently enabled for frame F.  */
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 047417f..34c0fcc 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -687,6 +687,7 @@ struct xg_frame_tb_info
       g_signal_connect (x->ttip_lbl, "hierarchy-changed",
                         G_CALLBACK (hierarchy_ch_cb), f);
     }
+
   return FALSE;
 }

@@ -713,7 +714,8 @@ struct xg_frame_tb_info
   GtkRequisition req;
   Lisp_Object encoded_string;

-  if (!x->ttip_lbl) return 0;
+  if (!x->ttip_lbl)
+    return FALSE;

   block_input ();
   encoded_string = ENCODE_UTF_8 (string);
@@ -745,7 +747,7 @@ struct xg_frame_tb_info

   unblock_input ();

-  return 1;
+  return TRUE;
 #endif /* USE_GTK_TOOLTIP */
 }

@@ -768,18 +770,18 @@ struct xg_frame_tb_info
 #endif
 }

+
 /* Hide tooltip if shown.  Do nothing if not shown.
    Return true if tip was hidden, false if not (i.e. not using
    system tooltips).  */
-
 bool
 xg_hide_tooltip (struct frame *f)
 {
-  bool ret = 0;
 #ifdef USE_GTK_TOOLTIP
   if (f->output_data.x->ttip_window)
     {
       GtkWindow *win = f->output_data.x->ttip_window;
+
       block_input ();
       gtk_widget_hide (GTK_WIDGET (win));

@@ -792,10 +794,10 @@ struct xg_frame_tb_info
         }
       unblock_input ();

-      ret = 1;
+      return TRUE;
     }
 #endif
-  return ret;
+  return FALSE;
 }

 \f
diff --git a/src/nsfns.m b/src/nsfns.m
index d5049a7..4c8376e 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -2753,10 +2753,6 @@ and GNUstep implementations ("distributor-specific release
   return make_number (1 << min (dpyinfo->n_planes, 24));
 }

-
-/* Unused dummy def needed for compatibility. */
-Lisp_Object tip_frame;
-
 /* TODO: move to xdisp or similar */
 static void
 compute_tip_xy (struct frame *f,
diff --git a/src/w32fns.c b/src/w32fns.c
index ed375cd..55db4d5 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -6423,7 +6423,7 @@ DISPLAY should be either a frame or a display name (a string).
     {
       struct frame *f = XFRAME (frame);

-      if (FRAME_W32_P (f) && !EQ (frame, tip_frame))
+      if (FRAME_W32_P (f) && !FRAME_TOOLTIP_P (f))
 	{
 	  HMONITOR monitor =
 	    monitor_from_window_fn (FRAME_W32_WINDOW (f),
@@ -6510,7 +6510,7 @@ DISPLAY should be either a frame or a display name (a string).
     {
       struct frame *f = XFRAME (frame);

-      if (FRAME_W32_P (f) && !EQ (frame, tip_frame))
+      if (FRAME_W32_P (f) && !FRAME_TOOLTIP_P (f))
 	frames = Fcons (frame, frames);
     }
   attributes = Fcons (Fcons (Qframes, frames), attributes);
@@ -6916,20 +6916,25 @@ no value of TYPE (always string in the MS Windows case).  */)
 static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
 			    Lisp_Object, int, int, int *, int *);

-/* The frame of a currently visible tooltip.  */
-
+/* The frame of the currently visible tooltip.  */
 Lisp_Object tip_frame;

-/* If non-nil, a timer started that hides the last tooltip when it
-   fires.  */
+/* 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;
-Window tip_window;

-/* If non-nil, a vector of 3 elements containing the last args
-   with which x-show-tip was called.  See there.  */
+/* STRING argument of last `x-show-tip' call.  */
+Lisp_Object tip_last_string;

-Lisp_Object last_show_tip_args;
+/* FRAME argument of last `x-show-tip' call.  */
+Lisp_Object tip_last_frame;
+
+/* PARMS argument of last `x-show-tip' call.  */
+Lisp_Object tip_last_parms;


 static void
@@ -7002,6 +7007,7 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,

   FRAME_FONTSET (f)  = -1;
   fset_icon_name (f, Qnil);
+  f->tooltip = true;

 #ifdef GLYPH_DEBUG
   image_cache_refcount =
@@ -7113,9 +7119,6 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
   SET_FRAME_LINES (f, 0);
   adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f),
 		     height * FRAME_LINE_HEIGHT (f), 0, true, Qtip_frame);
-  /* Add `tooltip' frame parameter's default value. */
-  if (NILP (Fframe_parameter (frame, Qtooltip)))
-    Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil));

   /* Set up faces after all frame parameters are known.  This call
      also merges in face attributes specified for new frames.
@@ -7261,7 +7264,17 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
     *root_x = min_x;
 }

-/* Hide tooltip.  Delete its frame if DELETE is true.  */
+/**
+ * x_hide_tip:
+ *
+ * Hide currently visible tooltip and cancel its timer.
+ *
+ * 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)
 {
@@ -7286,15 +7299,20 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,

       if (FRAMEP (tip_frame))
 	{
-	  if (delete)
+	  if (FRAME_LIVE_P (XFRAME (tip_frame)))
 	    {
-	      delete_frame (tip_frame, Qnil);
-	      tip_frame = Qnil;
+	      if (delete)
+		{
+		  delete_frame (tip_frame, Qnil);
+		  tip_frame = Qnil;
+		}
+	      else
+		x_make_frame_invisible (XFRAME (tip_frame));
+
+	      was_open = Qt;
 	    }
 	  else
-	    x_make_frame_invisible (XFRAME (tip_frame));
-
-	  was_open = Qt;
+	    tip_frame = Qnil;
 	}
       else
 	tip_frame = Qnil;
@@ -7334,7 +7352,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 *tip_f;
   struct window *w;
@@ -7345,8 +7364,7 @@ with offset DY added (default is -10).
   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);
@@ -7368,19 +7386,12 @@ with offset DY added (default is -10).
   else
     CHECK_NUMBER (dy);

-  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 (string, tip_last_string))
+	  && !NILP (Fequal (parms, tip_last_parms)))
 	{
 	  /* Only DX and DY have changed.  */
 	  tip_f = XFRAME (tip_frame);
@@ -7414,14 +7425,14 @@ with offset DY added (default is -10).

 	  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.  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);
@@ -7431,7 +7442,7 @@ with offset DY added (default is -10).
 	      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.  */
@@ -7439,15 +7450,17 @@ with offset DY added (default is -10).
 		      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 there's a parameter left in last_parms with a
+	  /* Now check if there's a parameter left in tip_last_parms with a
 	     non-nil value.  */
-	  for (tail = last_parms; CONSP (tail); tail = XCDR (tail))
+	  for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail))
 	    {
 	      elt = XCAR (tail);
 	      parm = Fcar (elt);
@@ -7468,9 +7481,9 @@ with offset DY added (default is -10).
   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;

   /* Block input until the tip has been fully drawn, to avoid crashes
      when drawing tips in menus.  */
@@ -7486,7 +7499,8 @@ with offset DY added (default is -10).
       if (NILP (Fassq (Qborder_width, parms)))
 	parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
       if (NILP (Fassq (Qborder_color, parms)))
-	parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
+	parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")),
+		       parms);
       if (NILP (Fassq (Qbackground_color, parms)))
 	parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
 		       parms);
@@ -10805,9 +10819,12 @@ successive mouse move (or scroll bar drag) events before they are
   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_file_dialog);
 #ifdef WINDOWSNT
diff --git a/src/w32term.c b/src/w32term.c
index db4ccf5..137c798 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -5569,7 +5569,7 @@ static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object
 	struct frame *f = XFRAME (frame);
 	/* The tooltip has been drawn already.  Avoid the
 	   SET_FRAME_GARBAGED below.  */
-	if (EQ (frame, tip_frame))
+	if (FRAME_TOOLTIP_P (f))
 	  continue;

 	/* Check "visible" frames and mark each as obscured or not.
@@ -6046,7 +6046,7 @@ static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object
       /* Don't change the size of a tip frame; there's no point in
 	 doing it because it's done in Fx_show_tip, and it leads to
 	 problems because the tip frame has no widget.  */
-      if (NILP (tip_frame) || XFRAME (tip_frame) != f)
+      if (!FRAME_TOOLTIP_P (f))
 	adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
 			   FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3,
 			   false, Qfont);
diff --git a/src/w32term.h b/src/w32term.h
index e500b73..c69bebe 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -817,6 +817,8 @@ typedef BOOL (WINAPI * AppendMenuW_Proc) (
 extern int w32_system_caret_hdr_height;
 extern int w32_system_caret_mode_height;

+extern Window tip_window;
+
 #ifdef _MSC_VER
 #ifndef EnumSystemLocales
 /* MSVC headers define these only for _WIN32_WINNT >= 0x0500.  */
diff --git a/src/xdisp.c b/src/xdisp.c
index 59fa00e..d2bb47f 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -11866,7 +11866,7 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
   if ((FRAME_WINDOW_P (f)
        || FRAME_MINIBUF_ONLY_P (f)
        || f->explicit_name)
-      && NILP (Fframe_parameter (frame, Qtooltip)))
+      && !FRAME_TOOLTIP_P (f))
     {
       /* Do we have more than one visible frame on this X display?  */
       Lisp_Object tail, other_frame, fmt;
@@ -11883,8 +11883,8 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
 	  if (tf != f
 	      && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
 	      && !FRAME_MINIBUF_ONLY_P (tf)
-	      && !EQ (other_frame, tip_frame)
 	      && !FRAME_PARENT_FRAME (tf)
+	      && !FRAME_TOOLTIP_P (tf)
 	      && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
 	    break;
 	}
@@ -11953,13 +11953,6 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
 {
   bool all_windows = windows_or_buffers_changed || update_mode_lines;
   bool some_windows = REDISPLAY_SOME_P ();
-  Lisp_Object tooltip_frame;
-
-#ifdef HAVE_WINDOW_SYSTEM
-  tooltip_frame = tip_frame;
-#else
-  tooltip_frame = Qnil;
-#endif

   if (FUNCTIONP (Vpre_redisplay_function))
     {
@@ -12000,7 +11993,7 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
 	      && !XBUFFER (w->contents)->text->redisplay)
 	    continue;

-	  if (!EQ (frame, tooltip_frame)
+	  if (!FRAME_TOOLTIP_P (f)
 	      && !FRAME_PARENT_FRAME (f)
 	      && (FRAME_ICONIFIED_P (f)
 		  || FRAME_VISIBLE_P (f) == 1
@@ -12038,7 +12031,7 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
 	  struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));

 	  /* Ignore tooltip frame.  */
-	  if (EQ (frame, tooltip_frame))
+	  if (FRAME_TOOLTIP_P (f))
 	    continue;

 	  if (some_windows
@@ -21160,13 +21153,7 @@ struct glyph_row *

 #ifdef HAVE_WINDOW_SYSTEM
   /* Don't display line number in tooltip frames.  */
-  if (FRAMEP (tip_frame) && EQ (WINDOW_FRAME (it->w), tip_frame)
-#ifdef USE_GTK
-      /* GTK builds store in tip_frame the frame that shows the tip,
-	 so we need an additional test.  */
-      && !NILP (Fframe_parameter (tip_frame, Qtooltip))
-#endif
-      )
+  if (FRAME_TOOLTIP_P (XFRAME (WINDOW_FRAME (it->w))))
     return false;
 #endif

@@ -30841,9 +30828,11 @@ A polygon is a cons (poly . [x0 y0 x1 y1 ...]) where each pair in the
 		= buffer_local_value (Qmode_line_default_help_echo,
 				      w->contents);

-	      if (STRINGP (default_help))
+	      if (FUNCTIONP (default_help) || STRINGP (default_help))
 		{
-		  help_echo_string = default_help;
+		  help_echo_string = (FUNCTIONP (default_help)
+				      ? safe_call1 (default_help, window)
+				      : default_help);
 		  XSETWINDOW (help_echo_window, w);
 		  help_echo_object = Qnil;
 		  help_echo_pos = -1;
diff --git a/src/xfns.c b/src/xfns.c
index 12b7d83..0176e2b 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4612,8 +4612,9 @@ struct mouse_cursor_data {
     {
       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 @@ struct mouse_cursor_data {
     {
       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 @@ no value of TYPE (always string in the MS Windows case).  */)
  ***********************************************************************/

 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 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
   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;
@@ -6324,13 +6328,6 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
   SET_FRAME_LINES (f, 0);
   change_frame_size (f, width, height, true, false, false, false);

-  /* Add `tooltip' frame parameter's default value. */
-  if (NILP (Fframe_parameter (frame, Qtooltip)))
-    {
-      AUTO_FRAME_ARG (arg, Qtooltip, Qt);
-      Fmodify_frame_parameters (frame, arg);
-    }
-
   /* FIXME - can this be done in a similar way to normal frames?
      https://lists.gnu.org/r/emacs-devel/2007-10/msg00641.html */

@@ -6405,7 +6402,9 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
    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 +6501,19 @@ static void compute_tip_xy (struct frame *, Lisp_Object, 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 +6523,17 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
       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 +6544,114 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
       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 +6682,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 +6694,7 @@ with offset DY added (default is -10).
   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 +6733,27 @@ with offset DY added (default is -10).
         {
 	  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 +6765,14 @@ with offset DY added (default is -10).

 	  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 +6782,7 @@ with offset DY added (default is -10).
 	      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 +6790,18 @@ with offset DY added (default is -10).
 		      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 +6822,9 @@ with offset DY added (default is -10).
   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 +7885,6 @@ FRAMES should be nil (the selected frame), a frame, or a list of
   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 +7892,12 @@ FRAMES should be nil (the selected frame), a frame, or a list of
   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)
diff --git a/src/xterm.c b/src/xterm.c
index f771631..0a2068d 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -996,12 +996,7 @@ struct x_display_info *
 x_update_begin (struct frame *f)
 {
 #ifdef USE_CAIRO
-  if (! NILP (tip_frame) && XFRAME (tip_frame) == f
-      && ! FRAME_VISIBLE_P (f)
-#ifdef USE_GTK
-      && !NILP (Fframe_parameter (tip_frame, Qtooltip))
-#endif
-      )
+  if (FRAME_TOOLTIP_P (f) && !FRAME_VISIBLE_P (f))
     return;

   if (! FRAME_CR_SURFACE (f))
@@ -8091,7 +8086,7 @@ static void xembed_send_message (struct frame *f, Time,
       /* Redo the mouse-highlight after the tooltip has gone.  */
       if (event->xunmap.window == tip_window)
         {
-          tip_window = 0;
+          tip_window = None;
           x_redo_mouse_highlight (dpyinfo);
         }

@@ -8733,7 +8728,7 @@ static void xembed_send_message (struct frame *f, Time,

 #ifdef USE_X_TOOLKIT
           /* Tip frames are pure X window, set size for them.  */
-          if (! NILP (tip_frame) && XFRAME (tip_frame) == f)
+          if (FRAME_TOOLTIP_P (f))
             {
               if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height
                   || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width)
@@ -9971,11 +9966,7 @@ struct x_error_message_stack {
       /* Don't change the size of a tip frame; there's no point in
 	 doing it because it's done in Fx_show_tip, and it leads to
 	 problems because the tip frame has no widget.  */
-      if (NILP (tip_frame) || XFRAME (tip_frame) != f
-#ifdef USE_GTK
-	  || NILP (Fframe_parameter (tip_frame, Qtooltip))
-#endif
-	  )
+      if (!FRAME_TOOLTIP_P (f))
 	{
 	  adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
 			     FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3,
@@ -11204,7 +11195,7 @@ struct x_error_message_stack {
   /* The following breaks our calculations.  If it's really needed,
      think of something else.  */
 #if false
-  if (NILP (tip_frame) || XFRAME (tip_frame) != f)
+  if (!FRAME_TOOLTIP_P (f))
     {
       int text_width, text_height;

diff --git a/src/xterm.h b/src/xterm.h
index f73dd0e..1849a5c 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -503,6 +503,8 @@ struct x_display_info

 extern void select_visual (struct x_display_info *);

+extern Window tip_window;
+
 /* Each X frame object points to its own struct x_output object
    in the output_data.x field.  The x_output structure contains
    the information that is specific to X windows.  */

^ permalink raw reply related	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2018-01-19 18:54 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-01-08  9:53 Fix some tooltip related problems martin rudalics
2018-01-08 14:41 ` Drew Adams
2018-01-08 18:19   ` martin rudalics
2018-01-08 18:50     ` Drew Adams
2018-01-09  9:42       ` martin rudalics
2018-01-09 15:08         ` Drew Adams
2018-01-10 10:20           ` martin rudalics
2018-01-10 15:55             ` Drew Adams
2018-01-10 19:17               ` Alan Third
2018-01-10 21:02                 ` Drew Adams
2018-01-10 23:04                   ` Alan Third
2018-01-10 23:26                     ` Drew Adams
2018-01-11  3:39                   ` Eli Zaretskii
2018-01-11  7:03                 ` Yuri Khan
2018-01-11 14:32                   ` Drew Adams
2018-01-11 10:56               ` martin rudalics
2018-01-11 14:42                 ` Drew Adams
2018-01-11 17:06                   ` martin rudalics
2018-01-11 17:19                     ` Robert Pluim
2018-01-11 17:59                       ` Eli Zaretskii
2018-01-11 18:20                         ` martin rudalics
2018-01-11 23:33                         ` Daniele Nicolodi
2018-01-12  8:38                           ` Eli Zaretskii
2018-01-12  8:40                         ` Robert Pluim
2018-01-12  9:55                           ` Eli Zaretskii
2018-01-12 13:57                             ` Robert Pluim
2018-01-12 14:15                               ` Philipp Stephani
2018-01-11 19:54                       ` Richard Stallman
2018-01-11 23:26                       ` Stefan Monnier
2018-01-12  8:48                         ` Robert Pluim
2018-01-11 18:09                     ` Drew Adams
2018-01-11 18:54                       ` martin rudalics
2018-01-11 19:50                         ` Drew Adams
2018-01-12  8:47                           ` martin rudalics
2018-01-12 16:43                             ` Drew Adams
2018-01-08 18:47 ` Eli Zaretskii
2018-01-08 19:06   ` martin rudalics
2018-01-08 19:22     ` Eli Zaretskii
2018-01-09  9:42       ` martin rudalics
2018-01-19 18:54 ` martin rudalics

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).