Reimplement "shadow-effect" used by Window- and WorkspaceClone

Based on patch by "Diego Rocha (diego-rocha-comp)"
This commit is contained in:
Rico Tzschichholz 2016-02-16 19:05:29 +01:00
parent 39cd6f5f03
commit e2e817af42
3 changed files with 67 additions and 74 deletions

View File

@ -50,13 +50,14 @@ namespace Gala
Cogl.Material material;
string? current_key = null;
public ShadowEffect (int actor_width, int actor_height, int shadow_size, int shadow_spread)
public ShadowEffect (int shadow_size, int shadow_spread)
{
Object (shadow_size: shadow_size, shadow_spread: shadow_spread);
}
construct
{
material = new Cogl.Material ();
update_size (actor_width, actor_height);
}
~ShadowEffect ()
@ -65,24 +66,18 @@ namespace Gala
decrement_shadow_users (current_key);
}
public void update_size (int actor_width, int actor_height)
Cogl.Texture? get_shadow (int width, int height, int shadow_size, int shadow_spread)
{
var shadow = get_shadow (actor_width, actor_height, shadow_size, shadow_spread);
material.set_layer (0, shadow);
}
Cogl.Texture get_shadow (int actor_width, int actor_height, int shadow_size, int shadow_spread)
{
if (current_key != null) {
decrement_shadow_users (current_key);
}
Shadow? shadow = null;
var width = actor_width + shadow_size * 2;
var height = actor_height + shadow_size * 2;
var old_key = current_key;
current_key = "%ix%i:%i:%i".printf (width, height, shadow_size, shadow_spread);
if (old_key == current_key)
return null;
if (old_key != null)
decrement_shadow_users (old_key);
Shadow? shadow = null;
if ((shadow = shadow_cache.@get (current_key)) != null) {
shadow.users++;
return shadow.texture;
@ -91,7 +86,7 @@ namespace Gala
// 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);
width - shadow_size * 2 + shadow_spread * 2, height - shadow_size * 2 + shadow_spread * 2);
buffer.context.set_source_rgba (0, 0, 0, 0.7);
buffer.context.fill ();
@ -124,7 +119,12 @@ namespace Gala
public override void paint (EffectPaintFlags flags)
{
var size = shadow_size * scale_factor;
var bounding_box = get_bounding_box ();
var shadow = get_shadow ((int) (bounding_box.x2 - bounding_box.x1), (int) (bounding_box.y2 - bounding_box.y1),
shadow_size, shadow_spread);
if (shadow != null)
material.set_layer (0, shadow);
var opacity = actor.get_paint_opacity () * shadow_opacity / 255;
var alpha = Cogl.Color.from_4ub (255, 255, 255, opacity);
@ -133,10 +133,20 @@ namespace Gala
material.set_color (alpha);
Cogl.set_source (material);
Cogl.rectangle (-size, -size, actor.width + size, actor.height + size);
Cogl.rectangle (bounding_box.x1, bounding_box.y1, bounding_box.x2, bounding_box.y2);
actor.continue_paint ();
}
public virtual ActorBox get_bounding_box ()
{
var size = shadow_size * scale_factor;
var bounding_box = ActorBox ();
bounding_box.set_origin (-size, -size);
bounding_box.set_size (actor.width + size * 2, actor.height + size * 2);
return bounding_box;
}
}
}

View File

@ -20,6 +20,31 @@ using Meta;
namespace Gala
{
class WindowShadowEffect : ShadowEffect
{
public Meta.Window window { get; construct; }
public WindowShadowEffect (Meta.Window window, int shadow_size, int shadow_spread)
{
Object (window: window, shadow_size: shadow_size, shadow_spread: shadow_spread, shadow_opacity: 255);
}
public override ActorBox get_bounding_box ()
{
var size = shadow_size * scale_factor;
var input_rect = window.get_buffer_rect ();
var outer_rect = window.get_frame_rect ();
// Occupy only window frame area plus shadow size
var bounding_box = ActorBox ();
bounding_box.set_origin (-(input_rect.x - outer_rect.x) - size, -(input_rect.y - outer_rect.y) - size);
bounding_box.set_size (outer_rect.width + size * 2, outer_rect.height + size * 2);
return bounding_box;
}
}
/**
* A container for a clone of the texture of a MetaWindow, a WindowIcon,
* a close button and a shadow. Used together with the WindowCloneContainer.
@ -159,8 +184,6 @@ namespace Gala
if (shadow_update_timeout != 0)
Source.remove (shadow_update_timeout);
window.size_changed.disconnect (update_shadow_size);
}
/**
@ -198,10 +221,8 @@ namespace Gala
transition_to_original_state (false);
var outer_rect = window.get_frame_rect ();
shadow_effect = new ShadowEffect (outer_rect.width, outer_rect.height, 40, 5);
add_effect_with_name ("shadow", shadow_effect);
window.size_changed.connect (update_shadow_size);
shadow_effect = new WindowShadowEffect (window, 40, 5);
clone.add_effect_with_name ("shadow", shadow_effect);
if (should_fade ())
opacity = 0;
@ -229,30 +250,6 @@ namespace Gala
&& window.get_workspace () != window.get_screen ().get_active_workspace ();
}
/**
* Sets a timeout of 500ms after which, if no new resize action reset it,
* the shadow will be resized and a request_reposition() will be emitted to
* make the WindowCloneContainer calculate a new layout to honor the new size.
*/
void update_shadow_size ()
{
if (shadow_update_timeout != 0)
Source.remove (shadow_update_timeout);
shadow_update_timeout = Timeout.add (500, () => {
var rect = window.get_frame_rect ();
var effect = get_effect ("shadow") as ShadowEffect;
effect.update_size (rect.width, rect.height);
shadow_update_timeout = 0;
// if there was a size change it makes sense to recalculate the positions
request_reposition ();
return false;
});
}
void on_all_workspaces_changed ()
{
// we don't display windows that are on all workspaces
@ -344,18 +341,15 @@ namespace Gala
};
active_shape.allocate (shape_alloc, flags);
if (clone == null)
if (clone == null || dragging)
return;
var actor = window.get_compositor_private () as WindowActor;
var actor = (WindowActor) window.get_compositor_private ();
var input_rect = window.get_buffer_rect ();
var outer_rect = window.get_frame_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 ();
ActorBox alloc = {};
alloc.set_origin ((input_rect.x - outer_rect.x) * scale_factor,
(input_rect.y - outer_rect.y) * scale_factor);
alloc.set_size (actor.width * scale_factor, actor.height * scale_factor);
@ -427,9 +421,9 @@ namespace Gala
shadow_transition.progress_mode = MultitaskingView.ANIMATION_MODE;
if (show)
shadow_transition.interval = new Clutter.Interval (typeof (uint8), 0, 255);
shadow_transition.interval = new Clutter.Interval (typeof (uint8), shadow_effect.shadow_opacity, 255);
else
shadow_transition.interval = new Clutter.Interval (typeof (uint8), 255, 0);
shadow_transition.interval = new Clutter.Interval (typeof (uint8), shadow_effect.shadow_opacity, 0);
add_transition ("shadow-opacity", shadow_transition);
}
@ -518,8 +512,6 @@ namespace Gala
var scale = window_icon.width / clone.width;
((ShadowEffect) get_effect ("shadow")).shadow_opacity = 0;
clone.get_transformed_position (out abs_x, out abs_y);
clone.save_easing_state ();
clone.set_easing_duration (200);
@ -674,22 +666,13 @@ namespace Gala
get_parent ().remove_child (this);
prev_parent.insert_child_at_index (this, prev_index);
clone.set_pivot_point (0, 0);
clone.save_easing_state ();
clone.set_easing_duration (250);
clone.set_easing_mode (AnimationMode.EASE_OUT_QUAD);
clone.set_scale (1, 1);
clone.opacity = 255;
Clutter.Callback finished = () => {
((ShadowEffect) get_effect ("shadow")).shadow_opacity = 255;
};
var transition = clone.get_transition ("scale-x");
if (transition != null)
transition.completed.connect (() => finished (this));
else
finished (this);
clone.restore_easing_state ();
request_reposition ();

View File

@ -35,7 +35,7 @@ namespace Gala
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));
add_effect (new ShadowEffect (40, 5));
}
public override void paint ()