From f9e9eed71dc06aa3711eec81973cbe1f16d81e34 Mon Sep 17 00:00:00 2001 From: Leonhard <106322251+leolost2605@users.noreply.github.com> Date: Tue, 28 May 2024 11:57:36 +0200 Subject: [PATCH] ShadowEffect: Dont use Gtk to draw shadows (#1867) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Danielle Foré --- data/gala.css | 67 ---------------- data/gala.gresource.xml | 1 - lib/ShadowEffect.vala | 76 ++++++++++--------- plugins/pip/PopupWindow.vala | 2 +- src/Widgets/IconGroup.vala | 3 +- src/Widgets/WindowClone.vala | 2 +- .../WindowSwitcher/WindowSwitcher.vala | 6 +- src/Widgets/WorkspaceClone.vala | 4 +- src/WindowManager.vala | 4 +- 9 files changed, 52 insertions(+), 113 deletions(-) delete mode 100644 data/gala.css diff --git a/data/gala.css b/data/gala.css deleted file mode 100644 index e3c03e44..00000000 --- a/data/gala.css +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2014 Gala Developers - * Copyright 2022-2023 elementary, Inc. (https://elementary.io) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Authored by: Tom Beckmann - */ - -.decoration { - border-radius: 4px 4px 0 0; - box-shadow: - 0 0 0 1px alpha(#000, 0.3), - 0 14px 20px rgba(0, 0, 0, 0.35), - 0 10px 10px rgba(0, 0, 0, 0.22); -} - -.window-clone.decoration { - border-radius: 0; - box-shadow: - 0 0 0 1px alpha(#000, 0.3), - 0 14px 20px rgba(0, 0, 0, 0.35), - 0 10px 10px rgba(0, 0, 0, 0.22); -} - -.workspace.decoration { - border-radius: 6px; - box-shadow: - 0 0 0 1px alpha(#000, 0.2), - 0 8px 10px 1px alpha(#000, 0.14), - 0 3px 14px 2px alpha(#000, 0.12), - 0 5px 5px -3px alpha(#000, 0.4); -} - -.window-switcher.decoration { - border-radius: 9px; - box-shadow: - 0 8px 10px 1px alpha(#000, 0.14), - 0 3px 14px 2px alpha(#000, 0.12), - 0 5px 5px -3px alpha(#000, 0.4); -} - -.workspace-switcher.decoration { - border-radius: 6px; - box-shadow: - 0 3px 4px alpha(#000, 0.25), - 0 3px 3px -3px alpha(#000, 0.45); -} - -.workspace-switcher-dnd.decoration { - border-radius: 6px; - box-shadow: - 0 8px 10px 1px alpha(#000, 0.14), - 0 3px 14px 2px alpha(#000, 0.12), - 0 5px 5px -3px alpha(#000, 0.4); -} diff --git a/data/gala.gresource.xml b/data/gala.gresource.xml index 2959b72a..a50d83f0 100644 --- a/data/gala.gresource.xml +++ b/data/gala.gresource.xml @@ -21,7 +21,6 @@ resize.svg - gala.css shaders/colorblindness-correction.vert shaders/monochrome.vert diff --git a/lib/ShadowEffect.vala b/lib/ShadowEffect.vala index 3de28db9..0ecf47db 100644 --- a/lib/ShadowEffect.vala +++ b/lib/ShadowEffect.vala @@ -20,34 +20,43 @@ public class Gala.ShadowEffect : Clutter.Effect { private static Gee.HashMap shadow_cache; // Delay the style context creation at render stage as Gtk need to access // the current display. - private static GLib.Once _style_context; static construct { shadow_cache = new Gee.HashMap (); } - private static Gtk.StyleContext create_style_context () { - var style_path = new Gtk.WidgetPath (); - style_path.append_type (typeof (Gtk.Window)); + private string _css_class; + public string css_class { + get { + return _css_class; + } - var style_context = new Gtk.StyleContext (); - style_context.add_provider (Gala.Utils.get_gala_css (), Gtk.STYLE_PROVIDER_PRIORITY_FALLBACK); - style_context.add_class ("decoration"); - style_context.set_path (style_path); - return style_context; + construct set { + _css_class = value; + switch (value) { + case "workspace-switcher": + shadow_size = 6; + break; + case "window": + shadow_size = 55; + break; + default: + shadow_size = 18; + break; + } + } } - public int shadow_size { get; construct; } - public float scale_factor { get; set; default = 1; } public uint8 shadow_opacity { get; set; default = 255; } - public string? css_class { get; set; default = null; } + public int border_radius { get; set; default = 9;} + private int shadow_size; private Cogl.Pipeline pipeline; private string? current_key = null; - public ShadowEffect (int shadow_size) { - Object (shadow_size: shadow_size); + public ShadowEffect (string css_class = "") { + Object (css_class: css_class); } construct { @@ -60,7 +69,7 @@ public class Gala.ShadowEffect : Clutter.Effect { } } - private Cogl.Texture? get_shadow (Cogl.Context context, int width, int height, int shadow_size) { + private Cogl.Texture? get_shadow (Cogl.Context context, int width, int height, int shadow_size, int shadow_spread = 0) { var old_key = current_key; current_key = "%ix%i:%i".printf (width, height, shadow_size); if (old_key == current_key) { @@ -77,26 +86,25 @@ public class Gala.ShadowEffect : Clutter.Effect { return shadow.texture; } + // fill a new texture for this size + var buffer = new Drawing.BufferSurface (width, height); + Drawing.Utilities.cairo_rounded_rectangle ( + buffer.context, + shadow_size - shadow_spread, + shadow_size - shadow_spread, + width - shadow_size * 2 + shadow_spread * 2, + height - shadow_size * 2 + shadow_spread * 2, + border_radius + ); + + buffer.context.set_source_rgba (0, 0, 0, 0.7); + buffer.context.fill (); + + buffer.exponential_blur (shadow_size / 2); + var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, width, height); var cr = new Cairo.Context (surface); - cr.set_source_rgba (0, 0, 0, 0); - cr.fill (); - - cr.set_operator (Cairo.Operator.OVER); - cr.save (); - cr.scale (scale_factor, scale_factor); - unowned var style_context = _style_context.once (create_style_context); - style_context.save (); - if (css_class != null) { - style_context.add_class (css_class); - } - - style_context.set_scale ((int) Math.round (scale_factor)); - var size = shadow_size * scale_factor; - style_context.render_background (cr, shadow_size, shadow_size, (width - size * 2) / scale_factor, (height - size * 2) / scale_factor); - style_context.restore (); - cr.restore (); - + cr.set_source_surface (buffer.surface, 0, 0); cr.paint (); try { @@ -139,7 +147,7 @@ public class Gala.ShadowEffect : Clutter.Effect { pipeline.set_color (alpha); - context.get_framebuffer ().draw_rectangle (pipeline, bounding_box.x1, bounding_box.y1, bounding_box.x2, bounding_box.y2); + context.get_framebuffer ().draw_rectangle (pipeline, bounding_box.x1, bounding_box.y1 + shadow_size / 4, bounding_box.x2, bounding_box.y2 + shadow_size / 4); actor.continue_paint (context); } diff --git a/plugins/pip/PopupWindow.vala b/plugins/pip/PopupWindow.vala index 535ecd26..5d5b74ac 100644 --- a/plugins/pip/PopupWindow.vala +++ b/plugins/pip/PopupWindow.vala @@ -86,7 +86,7 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { container = new Clutter.Actor (); container.reactive = true; container.set_scale (0.35f, 0.35f); - container.add_effect (new ShadowEffect (55) { css_class = "window-clone" }); + container.add_effect (new ShadowEffect ("window") { border_radius = 6}); container.add_child (clone); container.add_action (move_action); diff --git a/src/Widgets/IconGroup.vala b/src/Widgets/IconGroup.vala index 463ae024..b1ecd7d5 100644 --- a/src/Widgets/IconGroup.vala +++ b/src/Widgets/IconGroup.vala @@ -232,7 +232,8 @@ namespace Gala { InternalUtils.scale_to_int (5, scale_factor) ); - var shadow_effect = new ShadowEffect (40) { + var shadow_effect = new ShadowEffect () { + border_radius = InternalUtils.scale_to_int (5, scale_factor), scale_factor = scale_factor }; diff --git a/src/Widgets/WindowClone.vala b/src/Widgets/WindowClone.vala index ba4b4436..6bf10e74 100644 --- a/src/Widgets/WindowClone.vala +++ b/src/Widgets/WindowClone.vala @@ -235,7 +235,7 @@ public class Gala.WindowClone : Clutter.Actor { if (window.fullscreen || window.maximized_horizontally && window.maximized_vertically) { if (shadow_effect == null) { - shadow_effect = new ShadowEffect (55) { css_class = "window-clone" }; + shadow_effect = new ShadowEffect ("window"); shadow_opacity = 0; clone.add_effect_with_name ("shadow", shadow_effect); } diff --git a/src/Widgets/WindowSwitcher/WindowSwitcher.vala b/src/Widgets/WindowSwitcher/WindowSwitcher.vala index 538317e7..3897037f 100644 --- a/src/Widgets/WindowSwitcher/WindowSwitcher.vala +++ b/src/Widgets/WindowSwitcher/WindowSwitcher.vala @@ -84,9 +84,9 @@ public class Gala.WindowSwitcher : CanvasActor { orientation = VERTICAL }; - shadow_effect = new ShadowEffect (40) { - shadow_opacity = 200, - css_class = "window-switcher" + shadow_effect = new ShadowEffect ("window-switcher") { + border_radius = InternalUtils.scale_to_int (9, scaling_factor), + shadow_opacity = 100 }; add_effect (shadow_effect); diff --git a/src/Widgets/WorkspaceClone.vala b/src/Widgets/WorkspaceClone.vala index 1d876c26..8c5a716a 100644 --- a/src/Widgets/WorkspaceClone.vala +++ b/src/Widgets/WorkspaceClone.vala @@ -40,9 +40,7 @@ namespace Gala { var primary = wm.get_display ().get_primary_monitor (); var monitor_geom = wm.get_display ().get_monitor_geometry (primary); - var effect = new ShadowEffect (40) { - css_class = "workspace" - }; + var effect = new ShadowEffect ("workspace"); add_effect (effect); reactive = true; diff --git a/src/WindowManager.vala b/src/WindowManager.vala index 41f25970..80aa321d 100644 --- a/src/WindowManager.vala +++ b/src/WindowManager.vala @@ -1923,12 +1923,12 @@ namespace Gala { ((BackgroundContainer) background_group).set_black_background (false); wallpaper = new Clutter.Clone (background_group); } - wallpaper.add_effect (new Gala.ShadowEffect (40) { css_class = "workspace" }); + wallpaper.add_effect (new Gala.ShadowEffect ("workspace")); tmp_actors.prepend (wallpaper); if (workspace_to != null) { wallpaper_clone = new Clutter.Clone (wallpaper); - wallpaper_clone.add_effect (new Gala.ShadowEffect (40) { css_class = "workspace" }); + wallpaper_clone.add_effect (new Gala.ShadowEffect ("workspace")); tmp_actors.prepend (wallpaper_clone); }