changeset 66035:1b9ba63aad7e

(remember_mouse_glyph): New generic version based on glyph_rect and remember_mouse_glyph from xterm.c enhanced to properly handle all different window areas.
author Kim F. Storm <storm@cua.dk>
date Tue, 11 Oct 2005 22:36:46 +0000
parents d1a8711a8c3a
children 699f7f132908
files src/xdisp.c
diffstat 1 files changed, 175 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/xdisp.c	Tue Oct 11 22:36:35 2005 +0000
+++ b/src/xdisp.c	Tue Oct 11 22:36:46 2005 +0000
@@ -2027,6 +2027,181 @@
   return WINDOW_TO_FRAME_PIXEL_Y (w, y);
 }
 
+/*
+ * Remember which glyph the mouse is over.
+ */
+
+void
+remember_mouse_glyph (f, gx, gy, rect)
+     struct frame *f;
+     int gx, gy;
+     NativeRectangle *rect;
+{
+  Lisp_Object window;
+  struct window *w;
+  struct glyph_row *r, *gr, *end_row;
+  enum window_part part;
+  enum glyph_row_area area;
+  int x, y, width, height;
+
+  /* Try to determine frame pixel position and size of the glyph under
+     frame pixel coordinates X/Y on frame F.  */
+
+  window = window_from_coordinates (f, gx, gy, &part, &x, &y, 0);
+  if (NILP (window))
+    {
+      width = FRAME_SMALLEST_CHAR_WIDTH (f);
+      height = FRAME_SMALLEST_FONT_HEIGHT (f);
+      goto virtual_glyph;
+    }
+
+  w = XWINDOW (window);
+  width = WINDOW_FRAME_COLUMN_WIDTH (w);
+  height = WINDOW_FRAME_LINE_HEIGHT (w);
+
+  r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  end_row = r + w->current_matrix->nrows - 1;
+
+  if (w->pseudo_window_p)
+    {
+      area = TEXT_AREA;
+      part = ON_MODE_LINE; /* Don't adjust margin. */
+      goto text_glyph;
+    }
+
+  switch (part)
+    {
+    case ON_LEFT_MARGIN:
+      area = LEFT_MARGIN_AREA;
+      goto text_glyph;
+
+    case ON_RIGHT_MARGIN:
+      area = RIGHT_MARGIN_AREA;
+      goto text_glyph;
+
+    case ON_TEXT:
+    case ON_MODE_LINE:
+    case ON_HEADER_LINE:
+      area = TEXT_AREA;
+
+    text_glyph:
+      gr = 0; gy = 0;
+      for (; r < end_row && r->enabled_p; ++r)
+	if (r->y + r->height > y)
+	  {
+	    gr = r; gy = r->y;
+	    break;
+	  }
+
+      if (gr && gy <= y)
+	{
+	  struct glyph *g = gr->glyphs[area];
+	  struct glyph *end = g + gr->used[area];
+
+	  height = gr->height;
+	  for (gx = gr->x; g < end; gx += g->pixel_width, ++g)
+	    if (gx + g->pixel_width > x)
+	      break;
+
+	  if (g < end)
+	    width = g->pixel_width;
+	  else
+	    {
+	      /* Use nominal char spacing at end of line.  */
+	      x -= gx;
+	      gx += (x / width) * width;
+	    }
+
+	  if (part != ON_MODE_LINE && part != ON_HEADER_LINE)
+	    gx += window_box_left_offset (w, area);
+	}
+      else
+	{
+	  /* Use nominal line height at end of window.  */
+	  gx = (x / width) * width;
+	  y -= gy;
+	  gy += (y / height) * height;
+	}
+      break;
+
+    case ON_LEFT_FRINGE:
+      gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+	    ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
+	    : window_box_right_offset (w, LEFT_MARGIN_AREA));
+      width = WINDOW_LEFT_FRINGE_WIDTH (w);
+      goto row_glyph;
+
+    case ON_RIGHT_FRINGE:
+      gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+	    ? window_box_right_offset (w, RIGHT_MARGIN_AREA)
+	    : window_box_right_offset (w, TEXT_AREA));
+      width = WINDOW_RIGHT_FRINGE_WIDTH (w);
+      goto row_glyph;
+
+    case ON_SCROLL_BAR:
+      gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
+	    ? 0
+	    : (window_box_right_offset (w, RIGHT_MARGIN_AREA)
+	       + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+		  ? WINDOW_RIGHT_FRINGE_WIDTH (w)
+		  : 0)));
+      width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
+
+    row_glyph:
+      gr = 0, gy = 0;
+      for (; r < end_row && r->enabled_p; ++r)
+	if (r->y + r->height > y)
+	  {
+	    gr = r; gy = r->y;
+	    break;
+	  }
+
+      if (gr && gy <= y)
+	height = gr->height;
+      else
+	{
+	  /* Use nominal line height at end of window.  */
+	  y -= gy;
+	  gy += (y / height) * height;
+	}
+      break;
+
+    default:
+      ;
+    virtual_glyph:
+      /* If there is no glyph under the mouse, then we divide the screen
+	 into a grid of the smallest glyph in the frame, and use that
+	 as our "glyph".  */
+
+      /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
+	 round down even for negative values.  */
+      if (gx < 0)
+	gx -= width - 1;
+      if (gy < 0)
+	gy -= height - 1;
+
+      gx = (gx / width) * width;
+      gy = (gy / height) * height;
+
+      goto store_rect;
+    }
+
+  gx += WINDOW_LEFT_EDGE_X (w);
+  gy += WINDOW_TOP_EDGE_Y (w);
+
+ store_rect:
+  STORE_NATIVE_RECT (*rect, gx, gy, width, height);
+
+  /* Visible feedback for debugging.  */
+#if 0
+#if HAVE_X_WINDOWS
+  XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+		  f->output_data.x->normal_gc,
+		  gx, gy, width, height);
+#endif
+#endif
+}
+
 
 #endif /* HAVE_WINDOW_SYSTEM */