mirror of
https://github.com/elementary/gala.git
synced 2024-09-11 15:15:39 +03:00
Reimplement "shadow-effect" used by Window- and WorkspaceClone
Based on patch by "Diego Rocha (diego-rocha-comp)"
This commit is contained in:
parent
39cd6f5f03
commit
e2e817af42
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 ();
|
||||
|
@ -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 ()
|
||||
|
Loading…
Reference in New Issue
Block a user