Subject: Re: bug#5721: Feature request: Function that returns absolute coordinates

From: Andreas Politz <[email-masked]>
Date: Sat, 28 Sep 2013 22:06:40 +0200

I'd like the request to be reopened, because the current function
`window-inside-absolute-pixel-edges' does not provide the requested
behaviour.

Suppose no fringes, and header-line.  All considerations for a GTK build.
 
0--------------------------------------*
|           display                    |
| A----------------------------+       |
| |      [email-masked]         +       |
| |-B------------------------+ +       |
| | |       toolbar          | |       |
| | +------------------------+ |       |
| | |       menubar          | |       |
| | C------------------------+ |       |
| | |                        | |       |
| | |       window           | |       |
| | |   D---------+          | |       |
| | |   | tooltip |          | |       |
| | |   +---------+          | |       |
| | +------------------------+ |       |
| *----------------------------*       |
|                                      |
*--------------------------------------*

We have a buffer position D =
(D.x, D.y) in some window and want to display a tool-tip there. At the
moment,

       (posn-x-y (posn-at-point))

gives us a position relative to C, so we would need it's absolute
position.  

But `window-absolute-pixel-edges' gives the absolute position of

    (C.x - (B.x - A.x), C.y - (B.y - A.y))
  = (A.x , C.y - (B.y - A.y)) ,

that is, it does not account for the width and height (B - A) of the
window managers decorations.  Furthermore these sizes are unknown to the
lisp side, making it impossible to complete the desired task.

So it seems to me that `window-absolute-pixel-edges' should return the
absolute position of C, such that the tool-tip (or other frame) may be
positioned at C + D.

I noticed, that the frame struct already has members x_pixels_diff and
y_pixels_diff, such that

    (x_pixels_diff, y_pixels_diff) = (B.x - A.x, B.y - A.y) ,

such that we may compute C with this values.  So I propose extending
`calc_absolute_offset' by adding these pixel_diff values.  For GTK this
appears to be especially easy, since these diff values already account
for the tool-bar and menu-bar sizes.

=== modified file 'src/window.c'
*** src/window.c	2013-09-20 15:34:36 +0000
--- src/window.c	2013-09-28 19:53:08 +0000
***************
*** 939,945 ****
  calc_absolute_offset (struct window *w, int *add_x, int *add_y)
  {
    struct frame *f = XFRAME (w->frame);
!   *add_y = f->top_pos;
  #ifdef FRAME_MENUBAR_HEIGHT
    *add_y += FRAME_MENUBAR_HEIGHT (f);
  #endif
--- 939,946 ----
  calc_absolute_offset (struct window *w, int *add_x, int *add_y)
  {
    struct frame *f = XFRAME (w->frame);
!   *add_y = f->top_pos + f->y_pixels_diff;
! #ifndef USE_GTK
  #ifdef FRAME_MENUBAR_HEIGHT
    *add_y += FRAME_MENUBAR_HEIGHT (f);
  #endif
***************
*** 951,960 ****
  #ifdef FRAME_NS_TITLEBAR_HEIGHT
    *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
  #endif
!   *add_x = f->left_pos;
  #ifdef FRAME_TOOLBAR_LEFT_WIDTH
    *add_x += FRAME_TOOLBAR_LEFT_WIDTH (f);
  #endif
  }
  
  DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
--- 952,965 ----
  #ifdef FRAME_NS_TITLEBAR_HEIGHT
    *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
  #endif
! #endif
! 
!   *add_x = f->left_pos + f->x_pixels_diff;
! #ifndef USE_GTK
  #ifdef FRAME_TOOLBAR_LEFT_WIDTH
    *add_x += FRAME_TOOLBAR_LEFT_WIDTH (f);
  #endif
+ #endif
  }
  
  DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,

After applying the patch, the following function displays a tool-tip
below the cursor in the current buffer, which is something that is not
possible at the moment (without referring to e.g. xwininfo as the OP
explained). 

(defun tooltip-below-point (msg)
  (let* ((win-pos (posn-x-y (posn-at-point)))
         (offset (let ((e (window-inside-absolute-pixel-edges)))
                   (cons (car e) (cadr e))))
         (char-y-offset (cdr (posn-object-width-height (posn-at-point))))
         (abs-pos (cons (+ (car win-pos)
                           (car offset))
                        (+ (cdr win-pos)
                           (cdr offset)
                           char-y-offset)))
         (tooltip-frame-parameters
          `((left . ,(car abs-pos))
            (top . ,(cdr abs-pos)))))
    (tooltip-show msg)))

-ap