changeset 111564:8e4172d91b56

Revert changes in revision 102407
author Chong Yidong <cyd@stupidchicken.com>
date Tue, 16 Nov 2010 16:47:43 -0500
parents 29fbcfeb8b02
children 88b67190d0b2
files etc/NEWS src/ChangeLog src/dispnew.c src/keyboard.c src/msdos.c src/w32term.c src/window.c src/window.h src/xdisp.c src/xterm.c
diffstat 10 files changed, 266 insertions(+), 260 deletions(-) [+]
line wrap: on
line diff
--- a/etc/NEWS	Tue Nov 16 16:38:37 2010 -0500
+++ b/etc/NEWS	Tue Nov 16 16:47:43 2010 -0500
@@ -560,11 +560,6 @@
 
 * Incompatible Lisp Changes in Emacs 24.1
 
-** For mouse click input events in the text area, the Y pixel
-coordinate in the POSITION list now counts from the top of the text
-area, excluding any header line.  Previously, it counted from the top
-of the header line.
-
 ** Remove obsolete name `e' (use `float-e' instead).
 
 ** A backquote not followed by a space is now always treated as new-style.
--- a/src/ChangeLog	Tue Nov 16 16:38:37 2010 -0500
+++ b/src/ChangeLog	Tue Nov 16 16:47:43 2010 -0500
@@ -1,35 +1,3 @@
-2010-11-16  Chong Yidong  <cyd@stupidchicken.com>
-
-	* keyboard.c (make_lispy_position): For text area clicks, record Y
-	pixel position relative to the text area, excluding header line.
-	Also change X and Y to Lisp_Objects, not pointers; don't return
-	coordinate values via pointers.  Pass ON_TEXT_AREA coordinate to
-	buffer_posn_from_coords counting from the start of the text area.
-	(Fposn_at_x_y, make_lispy_event): Callers changed.
-
-	* window.c (coordinates_in_window): Change X and Y to ints rather
-	than pointers; don't return coordinates via pointers.
-	(struct check_window_data): Change X and Y from pointers to ints.
-	(window_from_coordinates): Remove args WX and WY; don't return
-	coordinates via pointers.
-	(Fcoordinates_in_window_p, window_from_coordinates):
-	(check_window_containing, Fwindow_at): Callers changed.
-	(window_relative_x_coord): New function.
-
-	* window.h (window_from_coordinates, window_relative_x_coord):
-	Update prototypes.
-
-	* dispnew.c (buffer_posn_from_coords): Assume that X counts from
-	the start of the text area.
-
-	* xdisp.c (remember_mouse_glyph): Change window_from_coordinates
-	call.  Use window_relative_x_coord.
-	(note_mouse_highlight): Change window_from_coordinates call.
-
-	* w32term.c (w32_read_socket):
-	* msdos.c (dos_rawgetc):
-	* xterm.c (handle_one_xevent): Likewise.
-
 2010-11-16  Dan Nicolaescu  <dann@ics.uci.edu>
 
 	* strftime.c (LOCALE_PARAM_DECL): Update for standard C.
--- a/src/dispnew.c	Tue Nov 16 16:38:37 2010 -0500
+++ b/src/dispnew.c	Tue Nov 16 16:47:43 2010 -0500
@@ -5393,7 +5393,7 @@
   BYTEPOS (startp) = min (ZV_BYTE, max (BEGV_BYTE, BYTEPOS (startp)));
   start_display (&it, w, startp);
 
-  x0 = *x;
+  x0 = *x - WINDOW_LEFT_MARGIN_WIDTH (w);
 
   /* First, move to the beginning of the row corresponding to *Y.  We
      need to be in that row to get the correct value of base paragraph
--- a/src/keyboard.c	Tue Nov 16 16:38:37 2010 -0500
+++ b/src/keyboard.c	Tue Nov 16 16:47:43 2010 -0500
@@ -5243,22 +5243,24 @@
 
 int double_click_count;
 
-/* X and Y are frame-relative coordinates for a click or wheel event.
-   Return a Lisp-style event list.  */
+/* Return position of a mouse click or wheel event */
 
 static Lisp_Object
-make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
+make_lispy_position (struct frame *f, Lisp_Object *x, Lisp_Object *y,
 		     unsigned long time)
 {
+  Lisp_Object window;
   enum window_part part;
   Lisp_Object posn = Qnil;
   Lisp_Object extra_info = Qnil;
-  /* Coordinate pixel positions to return.  */
-  int xret = 0, yret = 0;
-  /* The window under frame pixel coordinates (x,y)  */
-  Lisp_Object window = f
-    ? window_from_coordinates (f, XINT (x), XINT (y), &part, 0)
-    : Qnil;
+  int wx, wy;
+
+  /* Set `window' to the window under frame pixel coordinates (x,y)  */
+  if (f)
+    window = window_from_coordinates (f, XINT (*x), XINT (*y),
+				      &part, &wx, &wy, 0);
+  else
+    window = Qnil;
 
   if (WINDOWP (window))
     {
@@ -5266,113 +5268,102 @@
       struct window *w = XWINDOW (window);
       Lisp_Object string_info = Qnil;
       EMACS_INT textpos = -1;
-      int col = -1, row = -1;
-      int dx  = -1, dy  = -1;
+      int rx = -1, ry = -1;
+      int dx = -1, dy = -1;
       int width = -1, height = -1;
       Lisp_Object object = Qnil;
 
-      /* Pixel coordinates relative to the window corner.  */
-      int wx = XINT (x) - WINDOW_LEFT_EDGE_X (w);
-      int wy = XINT (y) - WINDOW_TOP_EDGE_Y (w);
-
-      /* For text area clicks, return X, Y relative to the corner of
-	 this text area.  Note that dX, dY etc are set below, by
-	 buffer_posn_from_coords.  */
+      /* Set event coordinates to window-relative coordinates
+	 for constructing the Lisp event below.  */
+      XSETINT (*x, wx);
+      XSETINT (*y, wy);
+
       if (part == ON_TEXT)
 	{
-	  xret = XINT (x) - window_box_left (w, TEXT_AREA);
-	  yret = wy - WINDOW_HEADER_LINE_HEIGHT (w);
-	}
-      /* For mode line and header line clicks, return X relative to
-	 the left window edge; ignore Y.  Use mode_line_string to look
-	 for a string on the click position.  */
+	  wx += WINDOW_LEFT_MARGIN_WIDTH (w);
+	}
       else if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
 	{
+	  /* Mode line or header line.  Look for a string under
+	     the mouse that may have a `local-map' property.  */
 	  Lisp_Object string;
 	  EMACS_INT charpos;
 
-	  posn = (part == ON_MODE_LINE) ? Qmode_line : Qheader_line;
-	  /* Note that mode_line_string takes COL, ROW as pixels and
-	     converts them to characters.  */
-	  col = wx;
-	  row = wy;
-	  string = mode_line_string (w, part, &col, &row, &charpos,
+	  posn = part == ON_MODE_LINE ? Qmode_line : Qheader_line;
+	  rx = wx, ry = wy;
+	  string = mode_line_string (w, part, &rx, &ry, &charpos,
 				     &object, &dx, &dy, &width, &height);
 	  if (STRINGP (string))
 	    string_info = Fcons (string, make_number (charpos));
-	  textpos = (w == XWINDOW (selected_window)
-		     && current_buffer == XBUFFER (w->buffer))
-	    ? PT : XMARKER (w->pointm)->charpos;
-
-	  xret = wx;
-	}
-      /* For fringes and margins, Y is relative to the area's (and the
-	 window's) top edge, while X is meaningless.  */
+	  if (w == XWINDOW (selected_window)
+	      && current_buffer == XBUFFER (w->buffer))
+	    textpos = PT;
+	  else
+	    textpos = XMARKER (w->pointm)->charpos;
+	}
+      else if (part == ON_VERTICAL_BORDER)
+	{
+	  posn = Qvertical_line;
+	  wx = -1;
+	  dx = 0;
+	  width = 1;
+	}
       else if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
 	{
 	  Lisp_Object string;
 	  EMACS_INT charpos;
 
 	  posn = (part == ON_LEFT_MARGIN) ? Qleft_margin : Qright_margin;
-	  col = wx;
-	  row = wy;
-	  string = marginal_area_string (w, part, &col, &row, &charpos,
+	  rx = wx, ry = wy;
+	  string = marginal_area_string (w, part, &rx, &ry, &charpos,
 					 &object, &dx, &dy, &width, &height);
 	  if (STRINGP (string))
 	    string_info = Fcons (string, make_number (charpos));
-	  yret = wy - WINDOW_HEADER_LINE_HEIGHT (w);
+	  if (part == ON_LEFT_MARGIN)
+	    wx = 0;
+	  else
+	    wx = window_box_right_offset (w, TEXT_AREA) - 1;
 	}
       else if (part == ON_LEFT_FRINGE)
 	{
 	  posn = Qleft_fringe;
-	  col = 0;
-	  dx = wx
-	    - (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
-	       ? 0 : window_box_width (w, LEFT_MARGIN_AREA));
-	  dy = yret = wy - WINDOW_HEADER_LINE_HEIGHT (w);
+	  rx = 0;
+	  dx = wx;
+	  wx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+		? 0
+		: window_box_width (w, LEFT_MARGIN_AREA));
+	  dx -= wx;
 	}
       else if (part == ON_RIGHT_FRINGE)
 	{
 	  posn = Qright_fringe;
-	  col = 0;
-	  dx = wx
-	    - window_box_width (w, LEFT_MARGIN_AREA)
-	    - window_box_width (w, TEXT_AREA)
-	    - (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
-	       ? window_box_width (w, RIGHT_MARGIN_AREA)
-	       : 0);
-	  dy = yret = wy - WINDOW_HEADER_LINE_HEIGHT (w);
-	}
-      else if (part == ON_VERTICAL_BORDER)
-	{
-	  posn = Qvertical_line;
-	  width = 1;
-	  dx = 0;
-	  dy = yret = wy;
-	}
-      /* Nothing special for part == ON_SCROLL_BAR.  */
-
-      /* For clicks in the text area, fringes, or margins, call
-	 buffer_posn_from_coords to extract TEXTPOS, the buffer
-	 position nearest to the click.  */
+	  rx = 0;
+	  dx = wx;
+	  wx = (window_box_width (w, LEFT_MARGIN_AREA)
+		+ window_box_width (w, TEXT_AREA)
+		+ (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+		   ? window_box_width (w, RIGHT_MARGIN_AREA)
+		   : 0));
+	  dx -= wx;
+	}
+      else
+	{
+	  /* Note: We have no special posn for part == ON_SCROLL_BAR.  */
+	  wx = max (WINDOW_LEFT_MARGIN_WIDTH (w), wx);
+	}
+
       if (textpos < 0)
 	{
 	  Lisp_Object string2, object2 = Qnil;
 	  struct display_pos p;
 	  int dx2, dy2;
 	  int width2, height2;
-	  /* The pixel X coordinate passed to buffer_posn_from_coords
-	     is the X coordinate relative to the text area for
-	     text-area clicks, zero otherwise.  */
-	  int x2 = (part == ON_TEXT) ? xret : 0;
-	  int y2 = wy;
-
-	  string2 = buffer_posn_from_coords (w, &x2, &y2, &p,
+	  string2 = buffer_posn_from_coords (w, &wx, &wy, &p,
 					     &object2, &dx2, &dy2,
 					     &width2, &height2);
 	  textpos = CHARPOS (p.pos);
-	  if (col < 0) col = x2;
-	  if (row < 0) row = y2;
+	  if (rx < 0) rx = wx;
+	  if (ry < 0) ry = wy;
 	  if (dx < 0) dx = dx2;
 	  if (dy < 0) dy = dy2;
 	  if (width < 0) width = width2;
@@ -5403,27 +5394,34 @@
 #endif
 
       /* Object info */
-      extra_info
-	= list3 (object,
-		 Fcons (make_number (dx), make_number (dy)),
-		 Fcons (make_number (width), make_number (height)));
+      extra_info = Fcons (object,
+			  Fcons (Fcons (make_number (dx),
+					make_number (dy)),
+				 Fcons (Fcons (make_number (width),
+					       make_number (height)),
+					Qnil)));
 
       /* String info */
       extra_info = Fcons (string_info,
 			  Fcons (make_number (textpos),
-				 Fcons (Fcons (make_number (col),
-					       make_number (row)),
+				 Fcons (Fcons (make_number (rx),
+					       make_number (ry)),
 					extra_info)));
     }
   else if (f != 0)
-    XSETFRAME (window, f);
+    {
+      XSETFRAME (window, f);
+    }
   else
-    window = Qnil;
+    {
+      window = Qnil;
+      XSETFASTINT (*x, 0);
+      XSETFASTINT (*y, 0);
+    }
 
   return Fcons (window,
 		Fcons (posn,
-		       Fcons (Fcons (make_number (xret),
-				     make_number (yret)),
+		       Fcons (Fcons (*x, *y),
 			      Fcons (make_number (time),
 				     extra_info))));
 }
@@ -5612,6 +5610,14 @@
 		int hpos;
 		int i;
 
+#if 0
+		/* Activate the menu bar on the down event.  If the
+		   up event comes in before the menu code can deal with it,
+		   just ignore it.  */
+		if (! (event->modifiers & down_modifier))
+		  return Qnil;
+#endif
+
 		/* Find the menu bar item under `column'.  */
 		item = Qnil;
 		items = FRAME_MENU_BAR_ITEMS (f);
@@ -5643,7 +5649,7 @@
 	      }
 #endif /* not USE_X_TOOLKIT && not USE_GTK && not HAVE_NS */
 
-	    position = make_lispy_position (f, event->x, event->y,
+	    position = make_lispy_position (f, &event->x, &event->y,
 					    event->timestamp);
 	  }
 #ifndef USE_TOOLKIT_SCROLL_BARS
@@ -5743,21 +5749,23 @@
 	      return Qnil;
 
 	    event->modifiers &= ~up_modifier;
-
+#if 0 /* Formerly we treated an up with no down as a click event.  */
+	    if (!CONSP (start_pos))
+	      event->modifiers |= click_modifier;
+	    else
+#endif
 	      {
-		Lisp_Object new_down, down;
+		Lisp_Object down;
 		EMACS_INT xdiff = double_click_fuzz, ydiff = double_click_fuzz;
 
 		/* The third element of every position
 		   should be the (x,y) pair.  */
 		down = Fcar (Fcdr (Fcdr (start_pos)));
-		new_down = Fcar (Fcdr (Fcdr (position)));
-
 		if (CONSP (down)
 		    && INTEGERP (XCAR (down)) && INTEGERP (XCDR (down)))
 		  {
-		    xdiff = XINT (XCAR (new_down)) - XINT (XCAR (down));
-		    ydiff = XINT (XCDR (new_down)) - XINT (XCDR (down));
+		    xdiff = XINT (event->x) - XINT (XCAR (down));
+		    ydiff = XINT (event->y) - XINT (XCDR (down));
 		  }
 
 		if (ignore_mouse_drag_p)
@@ -5840,7 +5848,7 @@
 	if (! FRAME_LIVE_P (f))
 	  return Qnil;
 
-	position = make_lispy_position (f, event->x, event->y,
+	position = make_lispy_position (f, &event->x, &event->y,
 					event->timestamp);
 
 	/* Set double or triple modifiers to indicate the wheel speed.  */
@@ -5860,8 +5868,10 @@
 	  else
 	    abort ();
 
-	  fuzz = FRAME_WINDOW_P (f)
-	    ? double_click_fuzz : double_click_fuzz / 8;
+	  if (FRAME_WINDOW_P (f))
+	    fuzz = double_click_fuzz;
+	  else
+	    fuzz = double_click_fuzz / 8;
 
 	  if (event->modifiers & up_modifier)
 	    {
@@ -5999,7 +6009,7 @@
 	if (! FRAME_LIVE_P (f))
 	  return Qnil;
 
-	position = make_lispy_position (f, event->x, event->y,
+	position = make_lispy_position (f, &event->x, &event->y,
 					event->timestamp);
 
 	head = modify_event_symbol (0, event->modifiers,
@@ -6082,8 +6092,8 @@
 	start_pos_ptr = &AREF (button_down_location, button);
 	start_pos = *start_pos_ptr;
 
-	position = make_lispy_position (f, event->x, event->y,
-					event->timestamp);
+	position = make_lispy_position (f, &event->x, &event->y,
+					    event->timestamp);
 
  	if (event->modifiers & down_modifier)
 	  *start_pos_ptr = Fcopy_alist (position);
@@ -6142,19 +6152,25 @@
 
       part_sym = *scroll_bar_parts[(int) part];
       return Fcons (Qscroll_bar_movement,
-		    Fcons (list5 (bar_window,
-				  Qvertical_scroll_bar,
-				  Fcons (x, y),
-				  make_number (time),
-				  part_sym),
-			   Qnil));
-    }
+		    (Fcons (Fcons (bar_window,
+				   Fcons (Qvertical_scroll_bar,
+					  Fcons (Fcons (x, y),
+						 Fcons (make_number (time),
+							Fcons (part_sym,
+							       Qnil))))),
+			    Qnil)));
+    }
+
   /* Or is it an ordinary mouse movement?  */
   else
     {
       Lisp_Object position;
-      position = make_lispy_position (frame, x, y, time);
-      return list2 (Qmouse_movement, position);
+
+      position = make_lispy_position (frame, &x, &y, time);
+
+      return Fcons (Qmouse_movement,
+		    Fcons (position,
+			   Qnil));
     }
 }
 
@@ -11311,7 +11327,7 @@
 
   CHECK_LIVE_FRAME (frame_or_window);
 
-  return make_lispy_position (XFRAME (frame_or_window), x, y, 0);
+  return make_lispy_position (XFRAME (frame_or_window), &x, &y, 0);
 }
 
 DEFUN ("posn-at-point", Fposn_at_point, Sposn_at_point, 0, 2, 0,
--- a/src/msdos.c	Tue Nov 16 16:38:37 2010 -0500
+++ b/src/msdos.c	Tue Nov 16 16:47:43 2010 -0500
@@ -2698,7 +2698,7 @@
 	      mouse_window = window_from_coordinates (SELECTED_FRAME(),
 						      mouse_last_x,
 						      mouse_last_y,
-						      0, 0);
+						      0, 0, 0, 0);
 	      /* A window will be selected only when it is not
 		 selected now, and the last mouse movement event was
 		 not in it.  A minibuffer window will be selected iff
--- a/src/w32term.c	Tue Nov 16 16:38:37 2010 -0500
+++ b/src/w32term.c	Tue Nov 16 16:47:43 2010 -0500
@@ -4317,7 +4317,7 @@
 		  int x = LOWORD (msg.msg.lParam);
 		  int y = HIWORD (msg.msg.lParam);
 
-		  window = window_from_coordinates (f, x, y, 0, 0);
+		  window = window_from_coordinates (f, x, y, 0, 0, 0, 0);
 
 		  /* Window will be selected only when it is not
 		     selected now and last mouse movement event was
@@ -4396,7 +4396,7 @@
 		    int x = XFASTINT (inev.x);
 		    int y = XFASTINT (inev.y);
 
-                    window = window_from_coordinates (f, x, y, 0, 1);
+                    window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
 
                     if (EQ (window, f->tool_bar_window))
                       {
--- a/src/window.c	Tue Nov 16 16:38:37 2010 -0500
+++ b/src/window.c	Tue Nov 16 16:47:43 2010 -0500
@@ -755,26 +755,32 @@
 			     - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
 }
 
-/* Test if the character at column X, row Y is within window W.
+/* Test if the character at column *X, row *Y is within window W.
    If it is not, return ON_NOTHING;
-   if it is in the window's text area, return ON_TEXT;
+   if it is in the window's text area,
+      set *x and *y to its location relative to the upper left corner
+         of the window, and
+      return ON_TEXT;
    if it is on the window's modeline, return ON_MODE_LINE;
    if it is on the border between the window and its right sibling,
       return ON_VERTICAL_BORDER.
-   if it is on a scroll bar, return ON_SCROLL_BAR.
+   if it is on a scroll bar,
+      return ON_SCROLL_BAR.
    if it is on the window's top line, return ON_HEADER_LINE;
    if it is in left or right fringe of the window,
-      return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
+      return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
+      to window-relative coordinates;
    if it is in the marginal area to the left/right of the window,
-      return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
+      return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
+      to window-relative coordinates.
 
    X and Y are frame relative pixel coordinates.  */
 
 static enum window_part
-coordinates_in_window (register struct window *w, int x, int y)
+coordinates_in_window (register struct window *w, register int *x, register int *y)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  int left_x, right_x;
+  int left_x, right_x, top_y, bottom_y;
   enum window_part part;
   int ux = FRAME_COLUMN_WIDTH (f);
   int x0 = WINDOW_LEFT_EDGE_X (w);
@@ -783,12 +789,6 @@
      (Between mode lines for instance.  */
   int grabbable_width = ux;
   int lmargin_width, rmargin_width, text_left, text_right;
-  int top_y = WINDOW_TOP_EDGE_Y (w);
-  int bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
-
-  /* Outside any interesting row?  */
-  if (y < top_y || y >= bottom_y)
-    return ON_NOTHING;
 
   /* In what's below, we subtract 1 when computing right_x because we
      want the rightmost pixel, which is given by left_pixel+width-1.  */
@@ -796,13 +796,21 @@
     {
       left_x = 0;
       right_x = WINDOW_TOTAL_WIDTH (w) - 1;
+      top_y = WINDOW_TOP_EDGE_Y (w);
+      bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
     }
   else
     {
       left_x = WINDOW_BOX_LEFT_EDGE_X (w);
       right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
+      top_y = WINDOW_TOP_EDGE_Y (w);
+      bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
     }
 
+  /* Outside any interesting row?  */
+  if (*y < top_y || *y >= bottom_y)
+    return ON_NOTHING;
+
   /* On the mode line or header line?  If it's near the start of
      the mode or header line of window that's has a horizontal
      sibling, say it's on the vertical line.  That's to be able
@@ -810,7 +818,7 @@
      scroll bars.  */
 
   if (WINDOW_WANTS_MODELINE_P (w)
-      && y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
+      && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
     {
       part = ON_MODE_LINE;
 
@@ -819,37 +827,60 @@
 	 between mode lines of horizontally adjacent mode lines
 	 as the vertical border.  If scroll bars on the left,
 	 return the right window.  */
-      if ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
-	   || WINDOW_RIGHTMOST_P (w))
-	  && !WINDOW_LEFTMOST_P (w)
-	  && eabs (x - x0) < grabbable_width)
-	return ON_VERTICAL_BORDER;
-
-      /* Make sure we're not at the rightmost position of a
-	 mode-/header-line and there's yet another window on the
-	 right.  (Bug#1372)  */
-      else if ((WINDOW_RIGHTMOST_P (w) || x < x1)
-	       && eabs (x - x1) < grabbable_width)
-	return ON_VERTICAL_BORDER;
-
-      if (x < x0 || x >= x1)
+      if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
+	  || WINDOW_RIGHTMOST_P (w))
+	{
+	  if (!WINDOW_LEFTMOST_P (w) && eabs (*x - x0) < grabbable_width)
+	    {
+	      /* Convert X and Y to window relative coordinates.
+		 Vertical border is at the left edge of window.  */
+	      *x = max (0, *x - x0);
+	      *y -= top_y;
+	      return ON_VERTICAL_BORDER;
+	    }
+	}
+      else
+	{
+	  /* Make sure we're not at the rightmost position of a
+	     mode-/header-line and there's yet another window on
+	     the right.  (Bug#1372)  */
+	  if ((WINDOW_RIGHTMOST_P (w) || *x < x1)
+	      && eabs (*x - x1) < grabbable_width)
+	    {
+	      /* Convert X and Y to window relative coordinates.
+		 Vertical border is at the right edge of window.  */
+	      *x = min (x1, *x) - x0;
+	      *y -= top_y;
+	      return ON_VERTICAL_BORDER;
+	    }
+	}
+
+      if (*x < x0 || *x >= x1)
 	return ON_NOTHING;
 
+      /* Convert X and Y to window relative coordinates.
+	 Mode line starts at left edge of window.  */
+      *x -= x0;
+      *y -= top_y;
       return part;
     }
 
   if (WINDOW_WANTS_HEADER_LINE_P (w)
-      && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
+      && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
     {
       part = ON_HEADER_LINE;
       goto header_vertical_border_check;
     }
 
-  if (x < x0 || x >= x1) return ON_NOTHING;
+  if (*x < x0 || *x >= x1)
+    return ON_NOTHING;
 
   /* Outside any interesting column?  */
-  if (x < left_x || x > right_x)
-    return ON_SCROLL_BAR;
+  if (*x < left_x || *x > right_x)
+    {
+      *y -= top_y;
+      return ON_SCROLL_BAR;
+    }
 
   lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
   rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
@@ -862,79 +893,77 @@
       if (!w->pseudo_window_p
 	  && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
 	  && !WINDOW_RIGHTMOST_P (w)
-	  && (eabs (x - right_x) < grabbable_width))
-	return ON_VERTICAL_BORDER;
+	  && (eabs (*x - right_x) < grabbable_width))
+	{
+	  /* Convert X and Y to window relative coordinates.
+	     Vertical border is at the right edge of window.  */
+	  *x = min (right_x, *x) - left_x;
+	  *y -= top_y;
+	  return ON_VERTICAL_BORDER;
+	}
     }
-  /* Need to say "x > right_x" rather than >=, since on character
-     terminals, the vertical line's x coordinate is right_x.  */
-  else if (!w->pseudo_window_p
-	   && !WINDOW_RIGHTMOST_P (w)
-	   && x > right_x - ux)
-    return ON_VERTICAL_BORDER;
-
-  if (x < text_left)
+  else
+    {
+      /* Need to say "*x > right_x" rather than >=, since on character
+	 terminals, the vertical line's x coordinate is right_x.  */
+      if (!w->pseudo_window_p
+	  && !WINDOW_RIGHTMOST_P (w)
+	  && *x > right_x - ux)
+	{
+	  /* On the border on the right side of the window?  Assume that
+	     this area begins at RIGHT_X minus a canonical char width.  */
+	  *x = min (right_x, *x) - left_x;
+	  *y -= top_y;
+	  return ON_VERTICAL_BORDER;
+	}
+    }
+
+  if (*x < text_left)
     {
       if (lmargin_width > 0
 	  && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
-	      ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
-	      : (x < left_x + lmargin_width)))
-	return ON_LEFT_MARGIN;
-
+	      ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
+	      : (*x < left_x + lmargin_width)))
+	{
+	  *x -= left_x;
+	  if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
+	    *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
+	  *y -= top_y;
+	  return ON_LEFT_MARGIN;
+	}
+
+      /* Convert X and Y to window-relative pixel coordinates.  */
+      *x -= left_x;
+      *y -= top_y;
       return ON_LEFT_FRINGE;
     }
 
-  if (x >= text_right)
+  if (*x >= text_right)
     {
       if (rmargin_width > 0
 	  && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
-	      ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
-	      : (x >= right_x - rmargin_width)))
-	return ON_RIGHT_MARGIN;
-
+	      ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
+	      : (*x >= right_x - rmargin_width)))
+	{
+	  *x -= right_x - rmargin_width;
+	  if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
+	    *x += WINDOW_RIGHT_FRINGE_WIDTH (w);
+	  *y -= top_y;
+	  return ON_RIGHT_MARGIN;
+	}
+
+      /* Convert X and Y to window-relative pixel coordinates.  */
+      *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
+      *y -= top_y;
       return ON_RIGHT_FRINGE;
     }
 
   /* Everything special ruled out - must be on text area */
+  *x -= text_left;
+  *y -= top_y;
   return ON_TEXT;
 }
 
-/* Take X is the frame-relative pixel x-coordinate, and return the
-   x-coordinate relative to part PART of window W. */
-int
-window_relative_x_coord (struct window *w, enum window_part part, int x)
-{
-  int left_x = (w->pseudo_window_p) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w);
-
-  switch (part)
-    {
-    case ON_TEXT:
-      return x - window_box_left (w, TEXT_AREA);
-
-    case ON_LEFT_FRINGE:
-      return x - left_x;
-
-    case ON_RIGHT_FRINGE:
-      return x - left_x - WINDOW_LEFT_FRINGE_WIDTH (w);
-
-    case ON_LEFT_MARGIN:
-      return (x - left_x
-	      - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
-		 ? WINDOW_LEFT_FRINGE_WIDTH (w) : 0));
-
-    case ON_RIGHT_MARGIN:
-      return (x + 1
-	      - ((w->pseudo_window_p)
-		 ? WINDOW_TOTAL_WIDTH (w)
-		 : WINDOW_BOX_RIGHT_EDGE_X (w))
-	      + window_box_width (w, RIGHT_MARGIN_AREA)
-	      + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
-		 ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
-    }
-
-  /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER:  */
-  return 0;
-}
-
 
 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
        Scoordinates_in_window_p, 2, 2, 0,
@@ -971,16 +1000,14 @@
   x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
   y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
 
-  switch (coordinates_in_window (w, x, y))
+  switch (coordinates_in_window (w, &x, &y))
     {
     case ON_NOTHING:
       return Qnil;
 
     case ON_TEXT:
-      /* Convert X and Y to window relative pixel coordinates, and
-	 return the canonical char units.  */
-      x -= window_box_left (w, TEXT_AREA);
-      y -= WINDOW_TOP_EDGE_Y (w);
+      /* X and Y are now window relative pixel coordinates.  Convert
+	 them to canonical char units before returning them.  */
       return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
 		    FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
 
@@ -1027,7 +1054,7 @@
 struct check_window_data
 {
   Lisp_Object *window;
-  int x, y;
+  int *x, *y;
   enum window_part *part;
 };
 
@@ -1054,7 +1081,8 @@
    return it as a Lisp_Object.
 
    If X, Y is on one of the window's special `window_part' elements,
-   set *PART to the id of that element.
+   set *PART to the id of that element, and return X and Y converted
+   to window relative coordinates in WX and WY.
 
    If there is no window under X, Y return nil and leave *PART
    unmodified.  TOOL_BAR_P non-zero means detect tool-bar windows.
@@ -1069,8 +1097,7 @@
    case.  */
 
 Lisp_Object
-window_from_coordinates (struct frame *f, int x, int y,
-			 enum window_part *part, int tool_bar_p)
+window_from_coordinates (struct frame *f, int x, int y, enum window_part *part, int *wx, int *wy, int tool_bar_p)
 {
   Lisp_Object window;
   struct check_window_data cw;
@@ -1080,7 +1107,7 @@
     part = &dummy;
 
   window = Qnil;
-  cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
+  cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
   foreach_window (f, check_window_containing, &cw);
 
   /* If not found above, see if it's in the tool bar window, if a tool
@@ -1089,13 +1116,16 @@
       && tool_bar_p
       && WINDOWP (f->tool_bar_window)
       && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
-      && (coordinates_in_window (XWINDOW (f->tool_bar_window), x, y)
+      && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
 	  != ON_NOTHING))
     {
       *part = ON_TEXT;
       window = f->tool_bar_window;
     }
 
+  if (wx) *wx = x;
+  if (wy) *wy = y;
+
   return window;
 }
 
@@ -1122,7 +1152,7 @@
 				   + FRAME_INTERNAL_BORDER_WIDTH (f)),
 				  (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
 				   + FRAME_INTERNAL_BORDER_WIDTH (f)),
-				  0, 0);
+				  0, 0, 0, 0);
 }
 
 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
--- a/src/window.h	Tue Nov 16 16:38:37 2010 -0500
+++ b/src/window.h	Tue Nov 16 16:47:43 2010 -0500
@@ -788,7 +788,8 @@
 extern Lisp_Object make_window (void);
 extern void delete_window (Lisp_Object);
 extern Lisp_Object window_from_coordinates (struct frame *, int, int,
-                                            enum window_part *, int);
+                                            enum window_part *,
+                                            int *, int*, int);
 EXFUN (Fwindow_dedicated_p, 1);
 extern int window_height (Lisp_Object);
 extern int window_width (Lisp_Object);
@@ -803,7 +804,6 @@
                             void *);
 extern void grow_mini_window (struct window *, int);
 extern void shrink_mini_window (struct window *);
-extern int window_relative_x_coord (struct window *, enum window_part, int);
 
 void run_window_configuration_change_hook (struct frame *f);
 
--- a/src/xdisp.c	Tue Nov 16 16:38:37 2010 -0500
+++ b/src/xdisp.c	Tue Nov 16 16:47:43 2010 -0500
@@ -2218,7 +2218,7 @@
      frame pixel coordinates X/Y on frame F.  */
 
   if (!f->glyphs_initialized_p
-      || (window = window_from_coordinates (f, gx, gy, &part, 0),
+      || (window = window_from_coordinates (f, gx, gy, &part, &x, &y, 0),
 	  NILP (window)))
     {
       width = FRAME_SMALLEST_CHAR_WIDTH (f);
@@ -2230,9 +2230,6 @@
   width = WINDOW_FRAME_COLUMN_WIDTH (w);
   height = WINDOW_FRAME_LINE_HEIGHT (w);
 
-  x = window_relative_x_coord (w, part, gx);
-  y = gy - WINDOW_TOP_EDGE_Y (w);
-
   r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
   end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
 
@@ -25386,7 +25383,7 @@
     }
 
   /* Which window is that in?  */
-  window = window_from_coordinates (f, x, y, &part, 1);
+  window = window_from_coordinates (f, x, y, &part, 0, 0, 1);
 
   /* If we were displaying active text in another window, clear that.
      Also clear if we move out of text area in same window.  */
--- a/src/xterm.c	Tue Nov 16 16:38:37 2010 -0500
+++ b/src/xterm.c	Tue Nov 16 16:47:43 2010 -0500
@@ -6658,7 +6658,7 @@
 
                 window = window_from_coordinates (f,
                                                   event.xmotion.x, event.xmotion.y,
-                                                  0, 0);
+                                                  0, 0, 0, 0);
 
                 /* Window will be selected only when it is not selected now and
                    last mouse movement event was not in it.  Minibuffer window
@@ -6797,7 +6797,7 @@
                 int x = event.xbutton.x;
                 int y = event.xbutton.y;
 
-                window = window_from_coordinates (f, x, y, 0, 1);
+                window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
                 tool_bar_p = EQ (window, f->tool_bar_window);
 
                 if (tool_bar_p && event.xbutton.button < 4)