aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-05-10 16:50:10 +0800
committerPo Lu2022-05-10 16:50:10 +0800
commite8d643eb835e2883e12032a7f25e94a8a3335c87 (patch)
tree965b7b907a805c25fcf04b05e3e8872f5239f590 /src
parentc7b48b61d08f0b6a08584080badc60fe62ba1db1 (diff)
downloademacs-e8d643eb835e2883e12032a7f25e94a8a3335c87.tar.gz
emacs-e8d643eb835e2883e12032a7f25e94a8a3335c87.zip
Fix X11 relief background clearning when hwidth is larger than vwidth
* src/xterm.c (x_fill_triangle, x_make_point, x_inside_rect_p): New functions. (x_draw_relief_rect): Complete rewrite. Use more sensible primitives.
Diffstat (limited to 'src')
-rw-r--r--src/xterm.c212
1 files changed, 140 insertions, 72 deletions
diff --git a/src/xterm.c b/src/xterm.c
index c22a901ff4c..3e5cd45b431 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -7390,20 +7390,62 @@ x_setup_relief_colors (struct glyph_string *s)
7390 } 7390 }
7391} 7391}
7392 7392
7393#ifndef USE_CAIRO
7394static void
7395x_fill_triangle (struct frame *f, GC gc, XPoint point1,
7396 XPoint point2, XPoint point3)
7397{
7398 XPoint abc[3];
7399
7400 abc[0] = point1;
7401 abc[1] = point2;
7402 abc[2] = point3;
7403
7404 XFillPolygon (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
7405 gc, abc, 3, Convex, CoordModeOrigin);
7406}
7407
7408static XPoint
7409x_make_point (int x, int y)
7410{
7411 XPoint pt;
7412
7413 pt.x = x;
7414 pt.y = y;
7415
7416 return pt;
7417}
7418
7419static bool
7420x_inside_rect_p (XRectangle *rects, int nrects, int x, int y)
7421{
7422 int i;
7423
7424 for (i = 0; i < nrects; ++i)
7425 {
7426 if (x >= rects[i].x && y >= rects[i].y
7427 && x < rects[i].x + rects[i].width
7428 && y < rects[i].y + rects[i].height)
7429 return true;
7430 }
7431
7432 return false;
7433}
7434#endif
7393 7435
7394/* Draw a relief on frame F inside the rectangle given by LEFT_X, 7436/* Draw a relief on frame F inside the rectangle given by LEFT_X,
7395 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief 7437 TOP_Y, RIGHT_X, and BOTTOM_Y. VWIDTH and HWIDTH are respectively
7396 to draw, it must be >= 0. RAISED_P means draw a raised 7438 the thickness of the vertical relief (left and right) and
7397 relief. LEFT_P means draw a relief on the left side of 7439 horizontal relief (top and bottom) to draw, it must be >= 0.
7398 the rectangle. RIGHT_P means draw a relief on the right 7440 RAISED_P means draw a raised relief. LEFT_P means draw a relief on
7399 side of the rectangle. CLIP_RECT is the clipping rectangle to use 7441 the left side of the rectangle. RIGHT_P means draw a relief on the
7400 when drawing. */ 7442 right side of the rectangle. CLIP_RECT is the clipping rectangle
7443 to use when drawing. */
7401 7444
7402static void 7445static void
7403x_draw_relief_rect (struct frame *f, 7446x_draw_relief_rect (struct frame *f, int left_x, int top_y, int right_x,
7404 int left_x, int top_y, int right_x, int bottom_y, 7447 int bottom_y, int hwidth, int vwidth, bool raised_p,
7405 int hwidth, int vwidth, bool raised_p, bool top_p, bool bot_p, 7448 bool top_p, bool bot_p, bool left_p, bool right_p,
7406 bool left_p, bool right_p,
7407 XRectangle *clip_rect) 7449 XRectangle *clip_rect)
7408{ 7450{
7409#ifdef USE_CAIRO 7451#ifdef USE_CAIRO
@@ -7479,90 +7521,116 @@ x_draw_relief_rect (struct frame *f,
7479 x_reset_clip_rectangles (f, top_left_gc); 7521 x_reset_clip_rectangles (f, top_left_gc);
7480 x_reset_clip_rectangles (f, bottom_right_gc); 7522 x_reset_clip_rectangles (f, bottom_right_gc);
7481#else 7523#else
7482 Display *dpy = FRAME_X_DISPLAY (f); 7524 GC gc, white_gc, black_gc, normal_gc;
7483 Drawable drawable = FRAME_X_DRAWABLE (f); 7525 Drawable drawable;
7484 int i; 7526 Display *dpy;
7485 GC gc;
7486
7487 if (raised_p)
7488 gc = f->output_data.x->white_relief.gc;
7489 else
7490 gc = f->output_data.x->black_relief.gc;
7491 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
7492 7527
7493 /* This code is more complicated than it has to be, because of two 7528 /* This code is more complicated than it has to be, because of two
7494 minor hacks to make the boxes look nicer: (i) if width > 1, draw 7529 minor hacks to make the boxes look nicer: (i) if width > 1, draw
7495 the outermost line using the black relief. (ii) Omit the four 7530 the outermost line using the black relief. (ii) Omit the four
7496 corner pixels. */ 7531 corner pixels. */
7497 7532
7498 /* Top. */ 7533 white_gc = f->output_data.x->white_relief.gc;
7499 if (top_p) 7534 black_gc = f->output_data.x->black_relief.gc;
7500 { 7535 normal_gc = f->output_data.x->normal_gc;
7501 if (hwidth == 1)
7502 XDrawLine (dpy, drawable, gc,
7503 left_x + left_p, top_y,
7504 right_x + !right_p, top_y);
7505 7536
7506 for (i = 1; i < hwidth; ++i) 7537 drawable = FRAME_X_DRAWABLE (f);
7507 XDrawLine (dpy, drawable, gc, 7538 dpy = FRAME_X_DISPLAY (f);
7508 left_x + i * left_p, top_y + i,
7509 right_x + 1 - i * right_p, top_y + i);
7510 }
7511 7539
7512 /* Left. */ 7540 x_set_clip_rectangles (f, white_gc, clip_rect, 1);
7513 if (left_p) 7541 x_set_clip_rectangles (f, black_gc, clip_rect, 1);
7514 {
7515 if (vwidth == 1)
7516 XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
7517 7542
7518 for (i = 1; i < vwidth; ++i)
7519 XDrawLine (dpy, drawable, gc,
7520 left_x + i, top_y + (i + 1) * top_p,
7521 left_x + i, bottom_y + 1 - (i + 1) * bot_p);
7522 }
7523
7524 XSetClipMask (dpy, gc, None);
7525 if (raised_p) 7543 if (raised_p)
7526 gc = f->output_data.x->black_relief.gc; 7544 gc = white_gc;
7527 else 7545 else
7528 gc = f->output_data.x->white_relief.gc; 7546 gc = black_gc;
7529 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
7530 7547
7531 /* Outermost top line. */ 7548 /* Draw lines. */
7532 if (top_p && hwidth > 1)
7533 XDrawLine (dpy, drawable, gc,
7534 left_x + left_p, top_y,
7535 right_x + !right_p, top_y);
7536 7549
7537 /* Outermost left line. */ 7550 if (top_p)
7538 if (left_p && vwidth > 1) 7551 x_fill_rectangle (f, gc, left_x, top_y,
7539 XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y); 7552 right_x - left_x + 1, hwidth,
7553 false);
7554
7555 if (left_p)
7556 x_fill_rectangle (f, gc, left_x, top_y, vwidth,
7557 bottom_y - top_y + 1, false);
7558
7559 if (raised_p)
7560 gc = black_gc;
7561 else
7562 gc = white_gc;
7540 7563
7541 /* Bottom. */
7542 if (bot_p) 7564 if (bot_p)
7565 x_fill_rectangle (f, gc, left_x, bottom_y - hwidth + 1,
7566 right_x - left_x + 1, hwidth, false);
7567
7568 if (right_p)
7569 x_fill_rectangle (f, gc, right_x - vwidth + 1, top_y,
7570 vwidth, bottom_y - top_y + 1, false);
7571
7572 /* Draw corners. */
7573
7574 if (bot_p && left_p)
7575 x_fill_triangle (f, raised_p ? white_gc : black_gc,
7576 x_make_point (left_x, bottom_y - hwidth),
7577 x_make_point (left_x + vwidth, bottom_y - hwidth),
7578 x_make_point (left_x, bottom_y));
7579
7580 if (top_p && right_p)
7581 x_fill_triangle (f, raised_p ? white_gc : black_gc,
7582 x_make_point (right_x - vwidth, top_y),
7583 x_make_point (right_x, top_y),
7584 x_make_point (right_x - vwidth, top_y + hwidth));
7585
7586 /* Draw outer line. */
7587
7588 if (top_p && left_p && bot_p && right_p
7589 && hwidth > 1 && vwidth > 1)
7590 x_draw_rectangle (f, black_gc, left_x, top_y,
7591 right_x - left_x, top_y - bottom_y);
7592 else
7543 { 7593 {
7544 if (hwidth >= 1) 7594 if (top_p && hwidth > 1)
7545 XDrawLine (dpy, drawable, gc, 7595 XDrawLine (dpy, drawable, black_gc, left_x, top_y,
7546 left_x + left_p, bottom_y, 7596 right_x + 1, top_y);
7547 right_x + !right_p, bottom_y); 7597
7598 if (bot_p && hwidth > 1)
7599 XDrawLine (dpy, drawable, black_gc, left_x, bottom_y,
7600 right_x + 1, bottom_y);
7601
7602 if (left_p && vwidth > 1)
7603 XDrawLine (dpy, drawable, black_gc, left_x, top_y,
7604 left_x, bottom_y + 1);
7548 7605
7549 for (i = 1; i < hwidth; ++i) 7606 if (right_p && vwidth > 1)
7550 XDrawLine (dpy, drawable, gc, 7607 XDrawLine (dpy, drawable, black_gc, right_x, top_y,
7551 left_x + i * left_p, bottom_y - i, 7608 right_x, bottom_y + 1);
7552 right_x + 1 - i * right_p, bottom_y - i);
7553 } 7609 }
7554 7610
7555 /* Right. */ 7611 /* Erase corners. */
7556 if (right_p) 7612
7613 if (hwidth > 1 && vwidth > 1)
7557 { 7614 {
7558 for (i = 0; i < vwidth; ++i) 7615 if (left_p && top_p && x_inside_rect_p (clip_rect, 1,
7559 XDrawLine (dpy, drawable, gc, 7616 left_x, top_y))
7560 right_x - i, top_y + (i + 1) * top_p, 7617 x_clear_rectangle (f, normal_gc, left_x, top_y, 1, 1, false);
7561 right_x - i, bottom_y + 1 - (i + 1) * bot_p);
7562 }
7563 7618
7564 x_reset_clip_rectangles (f, gc); 7619 if (left_p && bot_p && x_inside_rect_p (clip_rect, 1,
7620 left_x, bottom_y))
7621 x_clear_rectangle (f, normal_gc, left_x, bottom_y, 1, 1, false);
7622
7623 if (right_p && top_p && x_inside_rect_p (clip_rect, 1,
7624 right_x, top_y))
7625 x_clear_rectangle (f, normal_gc, right_x, top_y, 1, 1, false);
7626
7627 if (right_p && bot_p && x_inside_rect_p (clip_rect, 1,
7628 right_x, bottom_y))
7629 x_clear_rectangle (f, normal_gc, right_x, bottom_y, 1, 1, false);
7630 }
7565 7631
7632 x_reset_clip_rectangles (f, white_gc);
7633 x_reset_clip_rectangles (f, black_gc);
7566#endif 7634#endif
7567} 7635}
7568 7636