static void x_frame_rehighlight (struct x_display_info *);
static void x_clip_to_row (struct window *, struct glyph_row *,
- enum glyph_row_area, GC);
+ enum glyph_row_area, GC, XRectangle *);
static struct scroll_bar *x_window_to_scroll_bar (Display *, Window, int);
static struct frame *x_window_to_frame (struct x_display_info *, int);
static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
Display *display = FRAME_X_DISPLAY (f);
GC gc = f->output_data.x->normal_gc;
struct face *face = p->face;
+ XRectangle clip_rect;
/* Must clip because of partially visible lines. */
- x_clip_to_row (w, row, ANY_AREA, gc);
+ x_clip_to_row (w, row, ANY_AREA, gc, &clip_rect);
if (p->bx >= 0 && !p->overlay_p)
{
memset (&attrs, 0, sizeof attrs);
#endif
+ XRectangle image_rect, dest;
+ int window_x, window_y, window_width;
+ int px, py, pwidth, pheight;
+
+ /* Intersect the destination rectangle with that of the row.
+ Setting a clip mask overrides the clip rectangles provided by
+ x_clip_to_row, so clipping must be performed by hand. */
+
+ image_rect.x = p->x;
+ image_rect.y = p->y;
+ image_rect.width = p->wd;
+ image_rect.height = p->h;
+
+ if (!gui_intersect_rectangles (&clip_rect, &image_rect, &dest))
+ /* The entire destination rectangle falls outside the row. */
+ goto undo_clip;
+
+ /* Extrapolate the source rectangle from the difference between
+ the destination and image rectangles. */
+
+ px = dest.x - image_rect.x;
+ py = dest.y - image_rect.y;
+ pwidth = dest.width;
+ pheight = dest.height;
if (p->wd > 8)
bits = (char *) (p->bits + p->dh);
x_xr_apply_ext_clip (f, gc);
XRenderComposite (display, PictOpSrc, picture,
None, FRAME_X_PICTURE (f),
- 0, 0, 0, 0, p->x, p->y, p->wd, p->h);
+ px, py, px, py, dest.x, dest.y,
+ pwidth, pheight);
x_xr_reset_ext_clip (f);
XRenderFreePicture (display, picture);
}
else
#endif
- XCopyArea (display, pixmap, drawable, gc, 0, 0,
- p->wd, p->h, p->x, p->y);
+ XCopyArea (display, pixmap, drawable, gc, px, py,
+ pwidth, pheight, dest.x, dest.y);
XFreePixmap (display, pixmap);
if (p->overlay_p)
XFreePixmap (display, clipmask);
}
}
+
+ undo_clip:
#endif /* not USE_CAIRO */
x_reset_clip_rectangles (f, gc);
/* Set clipping for output in glyph row ROW. W is the window in which
we operate. GC is the graphics context to set clipping in.
+ If RECT_RETURN is non-NULL, return the clip rectangle within
+ *RECT_RETURN.
+
ROW may be a text row or, e.g., a mode line. Text rows must be
clipped to the interior of the window dedicated to text display,
mode lines must be clipped to the whole window. */
static void
x_clip_to_row (struct window *w, struct glyph_row *row,
- enum glyph_row_area area, GC gc)
+ enum glyph_row_area area, GC gc,
+ XRectangle *rect_return)
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
XRectangle clip_rect;
clip_rect.height = row->visible_height;
x_set_clip_rectangles (f, gc, &clip_rect, 1);
+
+ if (rect_return)
+ *rect_return = clip_rect;
}
wd -= 1;
}
/* Set clipping, draw the rectangle, and reset clipping again. */
- x_clip_to_row (w, row, TEXT_AREA, gc);
+ x_clip_to_row (w, row, TEXT_AREA, gc, NULL);
x_draw_rectangle (f, gc, x, y, wd, h - 1);
x_reset_clip_rectangles (f, gc);
}
FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
}
- x_clip_to_row (w, row, TEXT_AREA, gc);
+ x_clip_to_row (w, row, TEXT_AREA, gc, NULL);
if (kind == BAR_CURSOR)
{