Subject: bug#29627: 25.3; x-show-tip does not display text when x-gtk-use-tooltips is nil and left/right-margin-width is set

From: Eli Zaretskii <[email-masked]>
Date: Sun, 10 Dec 2017 16:08:30 +0200

> Date: Sun, 10 Dec 2017 10:52:43 +0100
> From: martin rudalics <[email-masked]>
> 
>  > Thanks, fixed on the emacs-26 branch.
> 
> Could you please tell why such a harsh treatment was necessary?  In
> particular why (1) showing the margins initially failed and (2) instead
> of just forcing the window margins have zero width you made the window a
> pseudo-window.

First, I didn't make the window a pseudo-window; it was always a
pseudo-window.  The line

  w->pseudo_window_p = true;

existed in x-show-tip ever since Emacs 21.  I didn't feel comfortable
with changing that now, certainly not on the release branch.

The bug happened because pseudo-windows cannot have display margins,
an assumption that is in the display code all over the place.  Here's
a typical example:

  static void
  frame_to_window_pixel_xy (struct window *w, int *x, int *y)
  {
    if (w->pseudo_window_p)
      {
	/* A pseudo-window is always full-width, and starts at the
	   left edge of the frame, plus a frame border.  */
	struct frame *f = XFRAME (w->frame);
	*x -= FRAME_INTERNAL_BORDER_WIDTH (f);
	*y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
      }

The actual root cause for this bug was that update_marginal_area, when
does this:

  output_cursor_to (w, vpos, 0, desired_row->y, 0);
  if (desired_row->used[area])
    rif->write_glyphs (w, updated_row, desired_row->glyphs[area],
		       area, desired_row->used[area]);
  rif->clear_end_of_line (w, updated_row, area, -1);

which in case in point avoided calling the write_glyphs method when
called for area = RIGHT_MARGIN_AREA (because the 'used' count is of
course zero).  That left the output cursor at the beginning of the
glyph row, and then clear_end_of_line method cleared the text which
was already displayed, because of this snippet:

  from_x = w->output_cursor.x;

  /* Translate to frame coordinates.  */
  if (updated_row->full_width_p)
    {
      from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
      to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
    }
  else
    {
      int area_left = window_box_left (w, updated_area);
      from_x += area_left;
      to_x += area_left;
    }

And you will see that window_box_left does this for pseudo-windows:

  if (w->pseudo_window_p)
    return FRAME_INTERNAL_BORDER_WIDTH (f);

which is just another example of the above-mentioned assumption about
pseudo-windows being margin-less.

So from_x remained (almost) zero, unlike in normal windows, and the
already displayed text was deleted.

For some reason that I cannot identify, and don't really care about,
the original recipe did work until Emacs 24.3.  But it could only work
by sheer luck, or maybe something else was preventing the window of
the tooltip frame to acquire display margins.  I just made this
official with my changes, that's all.

As for why I forced the tip buffer have zero margins, instead of doing
the same with the window in which that buffer is displayed, then:

  . why does it matter? the buffer is a temporary buffer generated
    specifically for showing the tip text;
  . I thought doing that with the window is more complex, what with
    all the different ways one can affect a window's parameters

Having said all that, if you see problem(s) caused by my change,
please describe them; I'm not married to the fix I pushed.