Subject: bug#24 closed by Jason Rumney <[email-masked]> (Re: Broken tooltips with dual-head on MS Windows)

From: [email-masked] (Emacs bug Tracking System)

This is an automatic notification regarding your bug report
which was filed against the emacs package:

#24: Broken tooltips with dual-head on MS Windows

It has been closed by Jason Rumney <[email-masked]>.

Their explanation is attached below along with your original report.
If this explanation is unsatisfactory and you have not received a
better one in a separate message then please contact Jason Rumney <[email-masked]> by
replying to this email.

-- 
24: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=24
Emacs Bug Tracking System
Contact [email-masked] with problems
>From [email-masked] Fri Mar 14 09:11:43 2008
Date: Fri, 14 Mar 2008 16:11:07 +0000
From: Jason Rumney <[email-masked]>
To: [email-masked]
Subject: Re: Broken tooltips with dual-head on MS Windows

I've applied a similar patch to Emacs 23 (trunk).

>From [email-masked] Fri Feb 29 01:03:40 2008
Resent-From: Jason Rumney <[email-masked]>
Resent-To: [email-masked]
Resent-Date: Fri, 29 Feb 2008 09:03:08 +0000
Resent-Message-Id: <[email-masked]>
Resent-User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.12) Gecko/20080213 Thunderbird/2.0.0.12
Date: Sat, 21 Jul 2007 12:24:51 +0100
From: Neil Roberts <[email-masked]>
To: [email-masked]
Subject: Broken tooltips with dual-head on MS Windows
Sender: bug-gnu-emacs-bounces+jasonr=[email-masked]

--zYM0uCDKw75PZbzx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,

I found a few problems with the positioning of tooltips when more than
one monitor is used under Windows. The current code seems to only take
into account the dimensions of the primary display so that for example
if the cursor is to the right of the primary display then it will
always think the tooltip doesn't fit and it will always move it to the
left of the cursor. Also, if there is a display to the left of the
primary display then all of the coordinates on that display are
negative but Emacs won't let the tooltip be positioned at a
co-ordinate less than zero so the tooltip is placed in the wrong
display.

I've made a little patch to the compute_tip_xy function to make it use
the multi-monitor API so that it can correctly position the tooltip
within the display containing the cursor. The API is checked for
dynamically using GetProcAddress so that it can still work under
Windows 95 where it isn't available. I'm not sure if the rest of Emacs
still supports Win95 so it could be tidied up if this isn't necessary.

Regards,
- Neil

--zYM0uCDKw75PZbzx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="wintooltip.patch"

Index: src/w32fns.c
===================================================================
RCS file: /sources/emacs/emacs/src/w32fns.c,v
retrieving revision 1.290
diff -c -r1.290 w32fns.c
*** src/w32fns.c	15 Jul 2007 01:50:54 -0000	1.290
--- src/w32fns.c	21 Jul 2007 10:02:15 -0000
***************
*** 7458,7463 ****
--- 7458,7464 ----
       int *root_x, *root_y;
  {
    Lisp_Object left, top;
+   RECT monitor_rect;
  
    /* User-specified position?  */
    left = Fcdr (Fassq (Qleft, parms));
***************
*** 7468,7508 ****
    if (!INTEGERP (left) || !INTEGERP (top))
      {
        POINT pt;
  
        BLOCK_INPUT;
        GetCursorPos (&pt);
        *root_x = pt.x;
        *root_y = pt.y;
        UNBLOCK_INPUT;
      }
  
    if (INTEGERP (top))
      *root_y = XINT (top);
!   else if (*root_y + XINT (dy) <= 0)
!     *root_y = 0; /* Can happen for negative dy */
!   else if (*root_y + XINT (dy) + height <= FRAME_W32_DISPLAY_INFO (f)->height)
      /* It fits below the pointer */
!       *root_y += XINT (dy);
!   else if (height + XINT (dy) <= *root_y)
      /* It fits above the pointer.  */
      *root_y -= height + XINT (dy);
    else
      /* Put it on the top.  */
!     *root_y = 0;
  
    if (INTEGERP (left))
      *root_x = XINT (left);
!   else if (*root_x + XINT (dx) <= 0)
!     *root_x = 0; /* Can happen for negative dx */
!   else if (*root_x + XINT (dx) + width <= FRAME_W32_DISPLAY_INFO (f)->width)
      /* It fits to the right of the pointer.  */
      *root_x += XINT (dx);
!   else if (width + XINT (dx) <= *root_x)
      /* It fits to the left of the pointer.  */
      *root_x -= width + XINT (dx);
    else
      /* Put it left justified on the screen -- it ought to fit that way.  */
!     *root_x = 0;
  }

--- 7469,7538 ----
    if (!INTEGERP (left) || !INTEGERP (top))
      {
        POINT pt;
+       HMODULE user32;
+       void *(WINAPI * monitor_from_point) (POINT, DWORD);
+       BOOL (WINAPI * get_monitor_info) (void *, void *);
  
        BLOCK_INPUT;
        GetCursorPos (&pt);
        *root_x = pt.x;
        *root_y = pt.y;
+ 
+       /* Try to get the rectangle for the monitor around the point. If
+ 	 the monitor API is not available (eg, on Windows 95) then
+ 	 just assume there is only one monitor */
+       monitor_rect.left = 0;
+       monitor_rect.right = FRAME_W32_DISPLAY_INFO (f)->width;
+       monitor_rect.top = 0;
+       monitor_rect.bottom = FRAME_W32_DISPLAY_INFO (f)->height;
+       if ((user32 = LoadLibrary ("user32")))
+ 	{
+ 	  if ((monitor_from_point = (void *(WINAPI *) (POINT, DWORD))
+ 	       GetProcAddress (user32, "MonitorFromPoint"))
+ 	      && (get_monitor_info = (BOOL (WINAPI *) (void *, void*))
+ 		  GetProcAddress (user32, "GetMonitorInfoA")))
+ 	    {
+ 	      void *monitor;
+ 	      char buf[40 /* sizeof (MONITORINFO) */];
+ 	      *(DWORD *) buf = 40; /* set cbSize */
+ 	      monitor = (* monitor_from_point) (pt, 2 /* MONITOR_DEFAULTTONEAREST */);
+ 	      if ((* get_monitor_info) (monitor, buf))
+ 		monitor_rect = *(RECT *) (buf + sizeof (DWORD));
+ 	    }
+       
+ 	  FreeLibrary (user32);
+ 	}
+ 
        UNBLOCK_INPUT;
      }
  
    if (INTEGERP (top))
      *root_y = XINT (top);
!   else if (*root_y + XINT (dy) <= monitor_rect.top)
!     *root_y = monitor_rect.top; /* Can happen for negative dy */
!   else if (*root_y + XINT (dy) + height <= monitor_rect.bottom)
      /* It fits below the pointer */
!     *root_y += XINT (dy);
!   else if (*root_y - XINT (dy) - height >= monitor_rect.top)
      /* It fits above the pointer.  */
      *root_y -= height + XINT (dy);
    else
      /* Put it on the top.  */
!     *root_y = monitor_rect.top;
  
    if (INTEGERP (left))
      *root_x = XINT (left);
!   else if (*root_x + XINT (dx) <= monitor_rect.left)
!     *root_x = monitor_rect.left; /* Can happen for negative dx */
!   else if (*root_x + XINT (dx) + width <= monitor_rect.right)
      /* It fits to the right of the pointer.  */
      *root_x += XINT (dx);
!   else if (*root_x - width - XINT (dx) >= monitor_rect.left)
      /* It fits to the left of the pointer.  */
      *root_x -= width + XINT (dx);
    else
      /* Put it left justified on the screen -- it ought to fit that way.  */
!     *root_x = monitor_rect.left;
  }

--zYM0uCDKw75PZbzx
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
bug-gnu-emacs mailing list
[email-masked]
http://lists.gnu.org/mailman/listinfo/bug-gnu-emacs

--zYM0uCDKw75PZbzx--