From a5d2b5ed451ca8414bc3a82288fbbf63fcc97070 Mon Sep 17 00:00:00 2001 From: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> Date: Thu, 3 Nov 2022 08:16:03 +0100 Subject: libdecor: update from source git repo (commit e87dcfda) This brings the GTK plugin inside the master libdecor git repo. --- libdecor/build/Makefile | 6 +- libdecor/demo/demo.c | 14 +- libdecor/demo/egl.c | 1 + libdecor/src/cursor-settings.c | 25 +++ libdecor/src/cursor-settings.h | 25 +++ libdecor/src/libdecor.h | 1 + libdecor/src/os-compatibility.c | 21 +- libdecor/src/plugins/cairo/libdecor-cairo-blur.c | 255 ---------------------- libdecor/src/plugins/cairo/libdecor-cairo-blur.h | 10 - libdecor/src/plugins/cairo/libdecor-cairo.c | 3 +- libdecor/src/plugins/common/libdecor-cairo-blur.c | 255 ++++++++++++++++++++++ libdecor/src/plugins/common/libdecor-cairo-blur.h | 10 + libdecor/src/plugins/gtk/libdecor-gtk.c | 4 +- 13 files changed, 350 insertions(+), 280 deletions(-) delete mode 100644 libdecor/src/plugins/cairo/libdecor-cairo-blur.c delete mode 100644 libdecor/src/plugins/cairo/libdecor-cairo-blur.h create mode 100644 libdecor/src/plugins/common/libdecor-cairo-blur.c create mode 100644 libdecor/src/plugins/common/libdecor-cairo-blur.h (limited to 'libdecor') diff --git a/libdecor/build/Makefile b/libdecor/build/Makefile index b391e6bc6..8d7b8b673 100644 --- a/libdecor/build/Makefile +++ b/libdecor/build/Makefile @@ -31,7 +31,7 @@ Linux_CFLAGS = FreeBSD_CFLAGS = -I/usr/local/include EXTRA_DECOR = ${${UNAME}_CFLAGS} -CFLAGS_DECOR = -I. -I../.. -I../../src -I../src $(EXTRA_DECOR) -fPIC -D_GNU_SOURCE \ +CFLAGS_DECOR = -I. -I../.. -I../../src -I../src -I../src/plugins $(EXTRA_DECOR) -fPIC -D_GNU_SOURCE \ -DUSE_SYSTEM_LIBDECOR=0 -DHAVE_MEMFD_CREATE -DHAVE_MKOSTEMP -DHAVE_POSIX_FALLOCATE Linux_NOPIE = -no-pie @@ -49,8 +49,8 @@ fl_libdecor.o : fl_libdecor.c ../src/libdecor.c ../../src/xdg-shell-protocol.c . fl_libdecor-plugins.o : fl_libdecor-plugins.c ../src/plugins/cairo/libdecor-cairo.c $(CC) $(CFLAGS) $(CFLAGS_DECOR) -c fl_libdecor-plugins.c -DLIBDECOR_PLUGIN_API_VERSION=1 -DLIBDECOR_PLUGIN_DIR=\"\" -libdecor-cairo-blur.o : ../src/plugins/cairo/libdecor-cairo-blur.c - $(CC) $(CFLAGS_DECOR) -c ../src/plugins/cairo/libdecor-cairo-blur.c +libdecor-cairo-blur.o : ../src/plugins/common/libdecor-cairo-blur.c + $(CC) $(CFLAGS_DECOR) -c ../src/plugins/common/libdecor-cairo-blur.c os-compatibility.o : ../src/os-compatibility.c $(CC) $(CFLAGS_DECOR) -c ../src/os-compatibility.c diff --git a/libdecor/demo/demo.c b/libdecor/demo/demo.c index ff285cc2f..26d955c18 100644 --- a/libdecor/demo/demo.c +++ b/libdecor/demo/demo.c @@ -2,6 +2,7 @@ * Copyright © 2011 Benjamin Franzke * Copyright © 2010 Intel Corporation * Copyright © 2018 Jonas Ådahl + * Copyright © 2019 Christian Rauch * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -1117,6 +1118,13 @@ handle_configure(struct libdecor_frame *frame, enum libdecor_window_state window_state; struct libdecor_state *state; + /* Update window state first for the correct calculations */ + if (!libdecor_configuration_get_window_state(configuration, + &window_state)) + window_state = LIBDECOR_WINDOW_STATE_NONE; + + window->window_state = window_state; + if (!libdecor_configuration_get_content_size(configuration, frame, &width, &height)) { width = window->content_width; @@ -1129,12 +1137,6 @@ handle_configure(struct libdecor_frame *frame, window->configured_width = width; window->configured_height = height; - if (!libdecor_configuration_get_window_state(configuration, - &window_state)) - window_state = LIBDECOR_WINDOW_STATE_NONE; - - window->window_state = window_state; - state = libdecor_state_new(width, height); libdecor_frame_commit(frame, state, configuration); libdecor_state_free(state); diff --git a/libdecor/demo/egl.c b/libdecor/demo/egl.c index 3d7331645..8963ea457 100644 --- a/libdecor/demo/egl.c +++ b/libdecor/demo/egl.c @@ -2,6 +2,7 @@ * Copyright © 2011 Benjamin Franzke * Copyright © 2010 Intel Corporation * Copyright © 2018 Jonas Ådahl + * Copyright © 2019 Christian Rauch * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/libdecor/src/cursor-settings.c b/libdecor/src/cursor-settings.c index b94623fd6..225034cdd 100644 --- a/libdecor/src/cursor-settings.c +++ b/libdecor/src/cursor-settings.c @@ -1,3 +1,28 @@ +/* + * Copyright © 2019 Christian Rauch + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + #include "cursor-settings.h" #include #include diff --git a/libdecor/src/cursor-settings.h b/libdecor/src/cursor-settings.h index 700bb4f30..0cc1cb6bf 100644 --- a/libdecor/src/cursor-settings.h +++ b/libdecor/src/cursor-settings.h @@ -1,3 +1,28 @@ +/* + * Copyright © 2019 Christian Rauch + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + #pragma once #include diff --git a/libdecor/src/libdecor.h b/libdecor/src/libdecor.h index d3ccea181..078169771 100644 --- a/libdecor/src/libdecor.h +++ b/libdecor/src/libdecor.h @@ -1,6 +1,7 @@ /* * Copyright © 2017-2018 Red Hat Inc. * Copyright © 2018 Jonas Ådahl + * Copyright © 2019 Christian Rauch * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/libdecor/src/os-compatibility.c b/libdecor/src/os-compatibility.c index 50beb79f8..8287da0e6 100644 --- a/libdecor/src/os-compatibility.c +++ b/libdecor/src/os-compatibility.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -86,11 +87,27 @@ static int os_resize_anonymous_file(int fd, off_t size) { #ifdef HAVE_POSIX_FALLOCATE + sigset_t mask; + sigset_t old_mask; + + /* posix_fallocate() might be interrupted, so we need to check + * for EINTR and retry in that case. + * However, in the presence of an alarm, the interrupt may trigger + * repeatedly and prevent a large posix_fallocate() to ever complete + * successfully, so we need to first block SIGALRM to prevent + * this. + */ + sigemptyset(&mask); + sigaddset(&mask, SIGALRM); + sigprocmask(SIG_BLOCK, &mask, &old_mask); /* - * Filesystems that do support fallocate will return EINVAL or + * Filesystems that do not support fallocate will return EINVAL or * EOPNOTSUPP. In this case we need to fall back to ftruncate */ - errno = posix_fallocate(fd, 0, size); + do { + errno = posix_fallocate(fd, 0, size); + } while (errno == EINTR); + sigprocmask(SIG_SETMASK, &old_mask, NULL); if (errno == 0) return 0; else if (errno != EINVAL && errno != EOPNOTSUPP) diff --git a/libdecor/src/plugins/cairo/libdecor-cairo-blur.c b/libdecor/src/plugins/cairo/libdecor-cairo-blur.c deleted file mode 100644 index 2cddc7a23..000000000 --- a/libdecor/src/plugins/cairo/libdecor-cairo-blur.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * Copyright © 2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * functions 'blur_surface' and 'render_shadow' from weston project: - * https://gitlab.freedesktop.org/wayland/weston/raw/master/shared/cairo-util.c - */ - -#include "libdecor-cairo-blur.h" -#include -#include -#include - -/** - * Compile-time computation of number of items in a hardcoded array. - * - * @param a the array being measured. - * @return the number of items hardcoded into the array. - */ -#ifndef ARRAY_LENGTH -#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) -#endif - -int -blur_surface(cairo_surface_t *surface, int margin) -{ - int32_t width, height, stride, x, y, z, w; - uint8_t *src, *dst; - uint32_t *s, *d, a, p; - int i, j, k, size, half; - uint32_t kernel[71]; - double f; - - size = ARRAY_LENGTH(kernel); - width = cairo_image_surface_get_width(surface); - height = cairo_image_surface_get_height(surface); - stride = cairo_image_surface_get_stride(surface); - src = cairo_image_surface_get_data(surface); - - dst = malloc(height * stride); - if (dst == NULL) - return -1; - - half = size / 2; - a = 0; - for (i = 0; i < size; i++) { - f = (i - half); - kernel[i] = exp(- f * f / ARRAY_LENGTH(kernel)) * 10000; - a += kernel[i]; - } - - for (i = 0; i < height; i++) { - s = (uint32_t *) (src + i * stride); - d = (uint32_t *) (dst + i * stride); - for (j = 0; j < width; j++) { - if (margin < j && j < width - margin) { - d[j] = s[j]; - continue; - } - - x = 0; - y = 0; - z = 0; - w = 0; - for (k = 0; k < size; k++) { - if (j - half + k < 0 || j - half + k >= width) - continue; - p = s[j - half + k]; - - x += (p >> 24) * kernel[k]; - y += ((p >> 16) & 0xff) * kernel[k]; - z += ((p >> 8) & 0xff) * kernel[k]; - w += (p & 0xff) * kernel[k]; - } - d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a; - } - } - - for (i = 0; i < height; i++) { - s = (uint32_t *) (dst + i * stride); - d = (uint32_t *) (src + i * stride); - for (j = 0; j < width; j++) { - if (margin <= i && i < height - margin) { - d[j] = s[j]; - continue; - } - - x = 0; - y = 0; - z = 0; - w = 0; - for (k = 0; k < size; k++) { - if (i - half + k < 0 || i - half + k >= height) - continue; - s = (uint32_t *) (dst + (i - half + k) * stride); - p = s[j]; - - x += (p >> 24) * kernel[k]; - y += ((p >> 16) & 0xff) * kernel[k]; - z += ((p >> 8) & 0xff) * kernel[k]; - w += (p & 0xff) * kernel[k]; - } - d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a; - } - } - - free(dst); - cairo_surface_mark_dirty(surface); - - return 0; -} - -void -render_shadow(cairo_t *cr, cairo_surface_t *surface, - int x, int y, int width, int height, int margin, int top_margin) -{ - cairo_pattern_t *pattern; - cairo_matrix_t matrix; - int i, fx, fy, shadow_height, shadow_width; - - cairo_set_source_rgba(cr, 0, 0, 0, 0.45); - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - pattern = cairo_pattern_create_for_surface (surface); - cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST); - - for (i = 0; i < 4; i++) { - /* when fy is set, then we are working with lower corners, - * when fx is set, then we are working with right corners - * - * 00 ------- 01 - * | | - * | | - * 10 ------- 11 - */ - fx = i & 1; - fy = i >> 1; - - cairo_matrix_init_translate(&matrix, - -x + fx * (128 - width), - -y + fy * (128 - height)); - cairo_pattern_set_matrix(pattern, &matrix); - - shadow_width = margin; - shadow_height = fy ? margin : top_margin; - - /* if the shadows together are greater than the surface, we need - * to fix it - set the shadow size to the half of - * the size of surface. Also handle the case when the size is - * not divisible by 2. In that case we need one part of the - * shadow to be one pixel greater. !fy or !fx, respectively, - * will do the work. - */ - if (height < 2 * shadow_height) - shadow_height = (height + !fy) / 2; - - if (width < 2 * shadow_width) - shadow_width = (width + !fx) / 2; - - cairo_reset_clip(cr); - cairo_rectangle(cr, - 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; - - if (shadow_width > 0 && shadow_height) { - /* 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, shadow_width, shadow_height); - - 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); - - cairo_reset_clip(cr); - cairo_rectangle(cr, x + margin, y + height - margin, - shadow_width, margin); - cairo_clip (cr); - cairo_mask(cr, pattern); - } - - shadow_width = margin; - if (width < 2 * shadow_width) - shadow_width = width / 2; - - 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); -} diff --git a/libdecor/src/plugins/cairo/libdecor-cairo-blur.h b/libdecor/src/plugins/cairo/libdecor-cairo-blur.h deleted file mode 100644 index d48e9dd3d..000000000 --- a/libdecor/src/plugins/cairo/libdecor-cairo-blur.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include - -int -blur_surface(cairo_surface_t *surface, int margin); - -void -render_shadow(cairo_t *cr, cairo_surface_t *surface, - int x, int y, int width, int height, int margin, int top_margin); diff --git a/libdecor/src/plugins/cairo/libdecor-cairo.c b/libdecor/src/plugins/cairo/libdecor-cairo.c index 12af8aacb..0cc0ce0dd 100644 --- a/libdecor/src/plugins/cairo/libdecor-cairo.c +++ b/libdecor/src/plugins/cairo/libdecor-cairo.c @@ -1,5 +1,6 @@ /* * Copyright © 2018 Jonas Ådahl + * Copyright © 2019 Christian Rauch * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -44,7 +45,7 @@ #include #include -#include "libdecor-cairo-blur.h" +#include "common/libdecor-cairo-blur.h" static const size_t SHADOW_MARGIN = 24; /* graspable part of the border */ static const size_t TITLE_HEIGHT = 24; diff --git a/libdecor/src/plugins/common/libdecor-cairo-blur.c b/libdecor/src/plugins/common/libdecor-cairo-blur.c new file mode 100644 index 000000000..2cddc7a23 --- /dev/null +++ b/libdecor/src/plugins/common/libdecor-cairo-blur.c @@ -0,0 +1,255 @@ +/* + * Copyright © 2008 Kristian Høgsberg + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * functions 'blur_surface' and 'render_shadow' from weston project: + * https://gitlab.freedesktop.org/wayland/weston/raw/master/shared/cairo-util.c + */ + +#include "libdecor-cairo-blur.h" +#include +#include +#include + +/** + * Compile-time computation of number of items in a hardcoded array. + * + * @param a the array being measured. + * @return the number of items hardcoded into the array. + */ +#ifndef ARRAY_LENGTH +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) +#endif + +int +blur_surface(cairo_surface_t *surface, int margin) +{ + int32_t width, height, stride, x, y, z, w; + uint8_t *src, *dst; + uint32_t *s, *d, a, p; + int i, j, k, size, half; + uint32_t kernel[71]; + double f; + + size = ARRAY_LENGTH(kernel); + width = cairo_image_surface_get_width(surface); + height = cairo_image_surface_get_height(surface); + stride = cairo_image_surface_get_stride(surface); + src = cairo_image_surface_get_data(surface); + + dst = malloc(height * stride); + if (dst == NULL) + return -1; + + half = size / 2; + a = 0; + for (i = 0; i < size; i++) { + f = (i - half); + kernel[i] = exp(- f * f / ARRAY_LENGTH(kernel)) * 10000; + a += kernel[i]; + } + + for (i = 0; i < height; i++) { + s = (uint32_t *) (src + i * stride); + d = (uint32_t *) (dst + i * stride); + for (j = 0; j < width; j++) { + if (margin < j && j < width - margin) { + d[j] = s[j]; + continue; + } + + x = 0; + y = 0; + z = 0; + w = 0; + for (k = 0; k < size; k++) { + if (j - half + k < 0 || j - half + k >= width) + continue; + p = s[j - half + k]; + + x += (p >> 24) * kernel[k]; + y += ((p >> 16) & 0xff) * kernel[k]; + z += ((p >> 8) & 0xff) * kernel[k]; + w += (p & 0xff) * kernel[k]; + } + d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a; + } + } + + for (i = 0; i < height; i++) { + s = (uint32_t *) (dst + i * stride); + d = (uint32_t *) (src + i * stride); + for (j = 0; j < width; j++) { + if (margin <= i && i < height - margin) { + d[j] = s[j]; + continue; + } + + x = 0; + y = 0; + z = 0; + w = 0; + for (k = 0; k < size; k++) { + if (i - half + k < 0 || i - half + k >= height) + continue; + s = (uint32_t *) (dst + (i - half + k) * stride); + p = s[j]; + + x += (p >> 24) * kernel[k]; + y += ((p >> 16) & 0xff) * kernel[k]; + z += ((p >> 8) & 0xff) * kernel[k]; + w += (p & 0xff) * kernel[k]; + } + d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a; + } + } + + free(dst); + cairo_surface_mark_dirty(surface); + + return 0; +} + +void +render_shadow(cairo_t *cr, cairo_surface_t *surface, + int x, int y, int width, int height, int margin, int top_margin) +{ + cairo_pattern_t *pattern; + cairo_matrix_t matrix; + int i, fx, fy, shadow_height, shadow_width; + + cairo_set_source_rgba(cr, 0, 0, 0, 0.45); + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + pattern = cairo_pattern_create_for_surface (surface); + cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST); + + for (i = 0; i < 4; i++) { + /* when fy is set, then we are working with lower corners, + * when fx is set, then we are working with right corners + * + * 00 ------- 01 + * | | + * | | + * 10 ------- 11 + */ + fx = i & 1; + fy = i >> 1; + + cairo_matrix_init_translate(&matrix, + -x + fx * (128 - width), + -y + fy * (128 - height)); + cairo_pattern_set_matrix(pattern, &matrix); + + shadow_width = margin; + shadow_height = fy ? margin : top_margin; + + /* if the shadows together are greater than the surface, we need + * to fix it - set the shadow size to the half of + * the size of surface. Also handle the case when the size is + * not divisible by 2. In that case we need one part of the + * shadow to be one pixel greater. !fy or !fx, respectively, + * will do the work. + */ + if (height < 2 * shadow_height) + shadow_height = (height + !fy) / 2; + + if (width < 2 * shadow_width) + shadow_width = (width + !fx) / 2; + + cairo_reset_clip(cr); + cairo_rectangle(cr, + 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; + + if (shadow_width > 0 && shadow_height) { + /* 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, shadow_width, shadow_height); + + 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); + + cairo_reset_clip(cr); + cairo_rectangle(cr, x + margin, y + height - margin, + shadow_width, margin); + cairo_clip (cr); + cairo_mask(cr, pattern); + } + + shadow_width = margin; + if (width < 2 * shadow_width) + shadow_width = width / 2; + + 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); +} diff --git a/libdecor/src/plugins/common/libdecor-cairo-blur.h b/libdecor/src/plugins/common/libdecor-cairo-blur.h new file mode 100644 index 000000000..d48e9dd3d --- /dev/null +++ b/libdecor/src/plugins/common/libdecor-cairo-blur.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +int +blur_surface(cairo_surface_t *surface, int margin); + +void +render_shadow(cairo_t *cr, cairo_surface_t *surface, + int x, int y, int width, int height, int margin, int top_margin); diff --git a/libdecor/src/plugins/gtk/libdecor-gtk.c b/libdecor/src/plugins/gtk/libdecor-gtk.c index a2019d5af..448fdb855 100644 --- a/libdecor/src/plugins/gtk/libdecor-gtk.c +++ b/libdecor/src/plugins/gtk/libdecor-gtk.c @@ -42,9 +42,7 @@ #include -/* Note for FLTK: This header file changes location, while its content stays unchanged, - between the master and gtk_cairo_single branches */ -#include "../cairo/libdecor-cairo-blur.h" +#include "common/libdecor-cairo-blur.h" #include #include -- cgit v1.2.3