If the client is small (< 128 pixels in any ward),
then the shadows overlap and create dark lines behind clients.
This is a problem mosly with pop-up menues. The lines become observable
when the menu has less than three items. The other case is when
the client doesn't restrict its size when resizing.

This fixes a part of the bug:
https://bugs.freedesktop.org/show_bug.cgi?id=78511

Signed-off-by: Marek Chalupa <mchqwe...@gmail.com>
---
 shared/cairo-util.c | 130 ++++++++++++++++++++++++++++++++++------------------
 1 file changed, 85 insertions(+), 45 deletions(-)

diff --git a/shared/cairo-util.c b/shared/cairo-util.c
index 26286c5..e8a749e 100644
--- a/shared/cairo-util.c
+++ b/shared/cairo-util.c
@@ -142,7 +142,7 @@ tile_mask(cairo_t *cr, cairo_surface_t *surface,
 {
        cairo_pattern_t *pattern;
        cairo_matrix_t matrix;
-       int i, fx, fy, vmargin;
+       int i, fx, fy, shadow_height, shadow_width;
 
        cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
        pattern = cairo_pattern_create_for_surface (surface);
@@ -157,63 +157,103 @@ tile_mask(cairo_t *cr, cairo_surface_t *surface,
                                            -y + fy * (128 - height));
                cairo_pattern_set_matrix(pattern, &matrix);
 
-               if (fy)
-                       vmargin = margin;
-               else
-                       vmargin = top_margin;
+               if (fy) {
+                       /* lower corner's margin */
+                       shadow_height = margin;
+               } else {
+                       /* upper corner's margin */
+                       shadow_height = top_margin;
+               }
+
+               if (height < 2 * shadow_height) {
+                       shadow_height = height / 2;
+
+                       /* when the height is odd, we need some part of the
+                        * shadow to be one pixel higher. Let's choose the
+                        * upper one */
+                       if (height % 2 != 0 && !fy)
+                               ++shadow_height;
+               }
+
+               shadow_width = margin;
+               if (width < 2 * shadow_width) {
+                       shadow_width = width / 2;
+
+                       /* the odd width case again */
+                       if (width % 2 != 0 && !fx)
+                               ++shadow_width;
+               }
 
                cairo_reset_clip(cr);
                cairo_rectangle(cr,
-                               x + fx * (width - margin),
-                               y + fy * (height - vmargin),
-                               margin, vmargin);
+                               x + fx * (width - shadow_width),
+                               y + fy * (height - shadow_height),
+                               shadow_width, shadow_height);
                cairo_clip (cr);
                cairo_mask(cr, pattern);
        }
 
+
+       shadow_width = width - 2 * margin;
+       shadow_height = top_margin;
+       if (height < 2 * shadow_height)
+               shadow_height = height / 2;
+
        /* Top stretch */
-       cairo_matrix_init_translate(&matrix, 60, 0);
-       cairo_matrix_scale(&matrix, 8.0 / width, 1);
-       cairo_matrix_translate(&matrix, -x - width / 2, -y);
-       cairo_pattern_set_matrix(pattern, &matrix);
-       cairo_rectangle(cr, x + margin, y, width - 2 * margin, margin);
+       if (shadow_width > 0 && shadow_height) {
+               cairo_matrix_init_translate(&matrix, 60, 0);
+               cairo_matrix_scale(&matrix, 8.0 / width, 1);
+               cairo_matrix_translate(&matrix, -x - width / 2, -y);
+               cairo_pattern_set_matrix(pattern, &matrix);
+               cairo_rectangle(cr, x + margin, y, shadow_width, shadow_height);
 
-       cairo_reset_clip(cr);
-       cairo_rectangle(cr,
-                       x + margin,
-                       y,
-                       width - 2 * margin, margin);
-       cairo_clip (cr);
-       cairo_mask(cr, pattern);
+               cairo_reset_clip(cr);
+               cairo_rectangle(cr,
+                               x + margin, y,
+                               shadow_width, shadow_height);
+               cairo_clip (cr);
+               cairo_mask(cr, pattern);
 
-       /* Bottom stretch */
-       cairo_matrix_translate(&matrix, 0, -height + 128);
-       cairo_pattern_set_matrix(pattern, &matrix);
+               /* Bottom stretch */
+               cairo_matrix_translate(&matrix, 0, -height + 128);
+               cairo_pattern_set_matrix(pattern, &matrix);
 
-       cairo_reset_clip(cr);
-       cairo_rectangle(cr, x + margin, y + height - margin,
-                       width - 2 * margin, margin);
-       cairo_clip (cr);
-       cairo_mask(cr, pattern);
+               cairo_reset_clip(cr);
+               cairo_rectangle(cr, x + margin, y + height - margin,
+                               shadow_width, margin);
+               cairo_clip (cr);
+               cairo_mask(cr, pattern);
+       }
 
-       /* Left stretch */
-       cairo_matrix_init_translate(&matrix, 0, 60);
-       cairo_matrix_scale(&matrix, 1, 8.0 / height);
-       cairo_matrix_translate(&matrix, -x, -y - height / 2);
-       cairo_pattern_set_matrix(pattern, &matrix);
-       cairo_reset_clip(cr);
-       cairo_rectangle(cr, x, y + margin, margin, height - 2 * margin);
-       cairo_clip (cr);
-       cairo_mask(cr, pattern);
+       shadow_width = margin;
+       if (width < 2 * shadow_width)
+               shadow_width = width / 2;
 
-       /* Right stretch */
-       cairo_matrix_translate(&matrix, -width + 128, 0);
-       cairo_pattern_set_matrix(pattern, &matrix);
-       cairo_rectangle(cr, x + width - margin, y + margin,
-                       margin, height - 2 * margin);
-       cairo_reset_clip(cr);
-       cairo_clip (cr);
-       cairo_mask(cr, pattern);
+       shadow_height = height - margin - top_margin;
+
+       /* if height is smaller than sum of margins,
+        * then the shadow is already done by the corners */
+       if (shadow_height > 0 && shadow_width) {
+               /* Left stretch */
+               cairo_matrix_init_translate(&matrix, 0, 60);
+               cairo_matrix_scale(&matrix, 1, 8.0 / height);
+               cairo_matrix_translate(&matrix, -x, -y - height / 2);
+               cairo_pattern_set_matrix(pattern, &matrix);
+               cairo_reset_clip(cr);
+               cairo_rectangle(cr, x, y + top_margin,
+                               shadow_width, shadow_height);
+               cairo_clip (cr);
+               cairo_mask(cr, pattern);
+
+               /* Right stretch */
+               cairo_matrix_translate(&matrix, -width + 128, 0);
+               cairo_pattern_set_matrix(pattern, &matrix);
+               cairo_rectangle(cr, x + width - shadow_width, y + top_margin,
+                               shadow_width, shadow_height);
+               cairo_reset_clip(cr);
+               cairo_clip (cr);
+               cairo_mask(cr, pattern);
+       }
 
        cairo_pattern_destroy(pattern);
        cairo_reset_clip(cr);
-- 
1.9.3

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to