mirror of
https://github.com/elementary/gala.git
synced 2024-11-23 20:07:21 +03:00
draw a custom shadow around windows, use window textures only which have better filtering when scaled
This commit is contained in:
parent
4debed4fed
commit
4c08373810
@ -39,6 +39,7 @@ gala_VALASOURCES = \
|
||||
PluginManager.vala \
|
||||
ScreenSaver.vala \
|
||||
Settings.vala \
|
||||
ShadowEffect.vala \
|
||||
TextShadowEffect.vala \
|
||||
WindowManager.vala \
|
||||
WorkspaceManager.vala \
|
||||
|
66
src/ShadowEffect.vala
Normal file
66
src/ShadowEffect.vala
Normal file
@ -0,0 +1,66 @@
|
||||
using Clutter;
|
||||
|
||||
namespace Gala
|
||||
{
|
||||
public class ShadowEffect : Effect
|
||||
{
|
||||
// the sizes of the textures often repeat, especially for the background actor
|
||||
// so we keep a cache to avoid creating the same texture all over again.
|
||||
// TODO keep track of user numbers and free shadows
|
||||
static Gee.HashMap<string,Cogl.Texture> shadow_cache;
|
||||
|
||||
public int shadow_size { get; construct; }
|
||||
public int shadow_spread { get; construct; }
|
||||
|
||||
public float scale_factor { get; set; default = 1; }
|
||||
|
||||
Cogl.Texture? shadow = null;
|
||||
|
||||
public ShadowEffect (int actor_width, int actor_height, int shadow_size, int shadow_spread)
|
||||
{
|
||||
Object (shadow_size: shadow_size, shadow_spread: shadow_spread);
|
||||
|
||||
if (shadow_cache == null) {
|
||||
shadow_cache = new Gee.HashMap<string,Cogl.Texture> ();
|
||||
}
|
||||
|
||||
var width = actor_width + shadow_size * 2;
|
||||
var height = actor_height + shadow_size * 2;
|
||||
|
||||
var key = "%ix%i:%i:%i".printf (width, height, shadow_size, shadow_spread);
|
||||
if ((shadow = shadow_cache.@get (key)) != null)
|
||||
return;
|
||||
|
||||
// fill a new texture for this size
|
||||
var buffer = new Granite.Drawing.BufferSurface (width, height);
|
||||
buffer.context.rectangle (shadow_size - shadow_spread, shadow_size - shadow_spread,
|
||||
actor_width + shadow_spread * 2, actor_height + shadow_spread * 2);
|
||||
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_surface (buffer.surface, 0, 0);
|
||||
cr.paint ();
|
||||
|
||||
shadow = new Cogl.Texture.from_data (width, height, 0, Cogl.PixelFormat.BGRA_8888_PRE,
|
||||
Cogl.PixelFormat.ANY, surface.get_stride (), surface.get_data ());
|
||||
|
||||
shadow_cache.@set (key, shadow);
|
||||
}
|
||||
|
||||
public override void paint (EffectPaintFlags flags)
|
||||
{
|
||||
var size = shadow_size * scale_factor;
|
||||
|
||||
Cogl.set_source_texture (shadow);
|
||||
Cogl.rectangle (-size, -size, actor.width + size, actor.height + size);
|
||||
|
||||
actor.continue_paint ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ namespace Gala
|
||||
return;
|
||||
}
|
||||
|
||||
clone = new Clone (actor);
|
||||
clone = new Clone (actor.get_texture ());
|
||||
add_child (clone);
|
||||
|
||||
set_child_below_sibling (active_shape, clone);
|
||||
@ -129,6 +129,8 @@ namespace Gala
|
||||
set_position (outer_rect.x, outer_rect.y);
|
||||
set_size (outer_rect.width, outer_rect.height);
|
||||
|
||||
add_effect_with_name ("shadow", new ShadowEffect (outer_rect.width, outer_rect.height, 40, 5));
|
||||
|
||||
// if we were waiting the view was most probably already opened when our window
|
||||
// finally got available. So we fade-in and make sure we took the took place.
|
||||
// If the slot is not available however, the view was probably closed while this
|
||||
@ -191,6 +193,9 @@ namespace Gala
|
||||
var outer_rect = window.get_outer_rect ();
|
||||
var scale_factor = (float)width / outer_rect.width;
|
||||
|
||||
var shadow_effect = get_effect ("shadow") as ShadowEffect;
|
||||
shadow_effect.scale_factor = scale_factor;
|
||||
|
||||
var alloc = ActorBox ();
|
||||
alloc.set_origin ((input_rect.x - outer_rect.x) * scale_factor,
|
||||
(input_rect.y - outer_rect.y) * scale_factor);
|
||||
@ -300,7 +305,7 @@ namespace Gala
|
||||
return;
|
||||
|
||||
var scale = hovered ? 0.1 : 0.4;
|
||||
var opacity = hovered ? 50 : 255;
|
||||
var opacity = hovered ? 100 : 255;
|
||||
var mode = hovered ? AnimationMode.EASE_IN_OUT_BACK : AnimationMode.EASE_OUT_ELASTIC;
|
||||
|
||||
save_easing_state ();
|
||||
|
@ -9,7 +9,10 @@ namespace Gala
|
||||
base (screen, screen.get_primary_monitor (),
|
||||
BackgroundSettings.get_default ().schema);
|
||||
|
||||
add_effect (new BackgroundShadowEffect (screen));
|
||||
var primary = screen.get_primary_monitor ();
|
||||
var monitor_geom = screen.get_monitor_geometry (primary);
|
||||
|
||||
add_effect (new ShadowEffect (monitor_geom.width, monitor_geom.height, 40, 5));
|
||||
}
|
||||
|
||||
public override void paint ()
|
||||
@ -26,56 +29,6 @@ namespace Gala
|
||||
}
|
||||
}
|
||||
|
||||
class BackgroundShadowEffect : Effect
|
||||
{
|
||||
static Meta.Screen screen;
|
||||
static Cogl.Texture? bitmap;
|
||||
|
||||
const int SHADOW_SIZE = 40;
|
||||
const int SHADOW_OFFSET = 5;
|
||||
|
||||
static int width;
|
||||
static int height;
|
||||
|
||||
public BackgroundShadowEffect (Meta.Screen _screen)
|
||||
{
|
||||
if (bitmap == null) {
|
||||
screen = _screen;
|
||||
|
||||
var primary = screen.get_primary_monitor ();
|
||||
var monitor_geom = screen.get_monitor_geometry (primary);
|
||||
|
||||
width = monitor_geom.width + SHADOW_SIZE * 2;
|
||||
height = monitor_geom.height + SHADOW_SIZE * 2;
|
||||
|
||||
var buffer = new Granite.Drawing.BufferSurface (width, height);
|
||||
buffer.context.rectangle (SHADOW_SIZE - SHADOW_OFFSET, SHADOW_SIZE - SHADOW_OFFSET,
|
||||
monitor_geom.width + SHADOW_OFFSET * 2, monitor_geom.height + SHADOW_OFFSET * 2);
|
||||
buffer.context.set_source_rgba (0, 0, 0, 0.5);
|
||||
buffer.context.fill ();
|
||||
|
||||
buffer.exponential_blur (20);
|
||||
|
||||
var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, width, height);
|
||||
var cr = new Cairo.Context (surface);
|
||||
|
||||
cr.set_source_surface (buffer.surface, 0, 0);
|
||||
cr.paint ();
|
||||
|
||||
bitmap = new Cogl.Texture.from_data (width, height, 0, Cogl.PixelFormat.BGRA_8888_PRE,
|
||||
Cogl.PixelFormat.ANY, surface.get_stride (), surface.get_data ());
|
||||
}
|
||||
}
|
||||
|
||||
public override void paint (EffectPaintFlags flags)
|
||||
{
|
||||
Cogl.set_source_texture (bitmap);
|
||||
Cogl.rectangle (-SHADOW_SIZE, -SHADOW_SIZE, width - SHADOW_SIZE, height - SHADOW_SIZE);
|
||||
|
||||
actor.continue_paint ();
|
||||
}
|
||||
}
|
||||
|
||||
public class WorkspaceClone : Clutter.Actor
|
||||
{
|
||||
public static const int BOTTOM_OFFSET = 100;
|
||||
|
Loading…
Reference in New Issue
Block a user