Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WindowClone: Layout in allocate virtual #2082

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
90f494b
Use allocation virtual for layout management
leolost2605 Oct 10, 2024
83c4642
Properly allocate window title
leolost2605 Oct 10, 2024
6e8a992
Cleanup
leolost2605 Oct 10, 2024
fbfdf97
Nicer hover behavior
leolost2605 Oct 10, 2024
98d7c26
Properly allocate clone
leolost2605 Oct 10, 2024
3190129
Fix negative tooltip width
leolost2605 Oct 10, 2024
db16bca
Clamp to pixel
leolost2605 Oct 12, 2024
6ad847e
Merge branch 'main' into leolost/windowclone-allocate
leolost2605 Oct 13, 2024
7c1d48c
Undo temporary fix #2072
leolost2605 Oct 13, 2024
1b1c155
Transform coords to stage space for monitor index
leolost2605 Oct 14, 2024
2719e19
Merge branch 'main' into leolost/windowclone-allocate
leolost2605 Oct 20, 2024
490dc20
Merge branch 'main' into leolost/windowclone-allocate
lenemter Nov 1, 2024
41e9e56
Merge branch 'main' into leolost/windowclone-allocate
lenemter Nov 15, 2024
bb66568
Fix merge
lenemter Nov 15, 2024
7626a96
Merge branch 'main' into leolost/windowclone-allocate
danirabbit Nov 21, 2024
32ea331
Fix coords (they are parent relative)
leolost2605 Nov 23, 2024
3096a71
Use utility method
leolost2605 Nov 23, 2024
da10b4c
Merge branch 'main' into leolost/windowclone-allocate
lenemter Nov 25, 2024
6e0d19a
Set content scaling filters
leolost2605 Nov 25, 2024
a82f28f
Fix build
leolost2605 Nov 25, 2024
0e8d238
Merge branch 'main' into leolost/windowclone-allocate
stsdc Nov 29, 2024
0f60645
Merge branch 'main' into leolost/windowclone-allocate
leolost2605 Dec 3, 2024
acbfa41
Merge branch 'main' into leolost/windowclone-allocate
lenemter Dec 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/InternalUtils.vala
Original file line number Diff line number Diff line change
Expand Up @@ -340,5 +340,16 @@ namespace Gala {
return { 0, 0, (int) screen_width, (int) screen_height };
}
}

public static Clutter.ActorBox actor_box_from_rect (float x, float y, float width, float height, bool clamp_to_pixel = true) {
Copy link
Member

@lenemter lenemter Nov 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't pass clamp_to_pixel as false anywhere in the code. We can assume it's always true :)

var actor_box = Clutter.ActorBox ();
actor_box.init_rect (x, y, width, height);

if (clamp_to_pixel) {
Clutter.ActorBox.clamp_to_pixel (ref actor_box);
}

return actor_box;
}
}
}
23 changes: 0 additions & 23 deletions src/Widgets/Tooltip.vala
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,7 @@ public class Gala.Tooltip : CanvasActor {
*/
private Clutter.Text text_actor;

/**
* Maximum width of the Tooltip.
* @see set_max_width
*/
public float max_width;

construct {
max_width = 200;

#if HAS_MUTTER47
Cogl.Color text_color = {
#else
Expand Down Expand Up @@ -51,21 +43,6 @@ public class Gala.Tooltip : CanvasActor {
text_actor.text = new_text;
}

public void set_max_width (float new_max_width) {
max_width = new_max_width;

queue_relayout ();
}

protected override void allocate (Clutter.ActorBox box) {
if (box.get_width () > max_width) {
box.set_origin (box.get_x () + ((box.get_width () - max_width) / 2), box.get_y ());
box.set_size (max_width, box.get_height ());
}

base.allocate (box);
}

protected override void draw (Cairo.Context ctx, int width, int height) {
ctx.save ();
ctx.set_operator (Cairo.Operator.CLEAR);
Expand Down
157 changes: 65 additions & 92 deletions src/Widgets/WindowClone.vala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
* a close button and a shadow. Used together with the WindowCloneContainer.
*/
public class Gala.WindowClone : Clutter.Actor {
private const int CLOSE_WINDOW_ICON_SIZE = 36;
private const int WINDOW_ICON_SIZE = 64;
private const int ACTIVE_SHAPE_SIZE = 12;
private const int FADE_ANIMATION_DURATION = 200;
Expand Down Expand Up @@ -144,6 +143,11 @@ public class Gala.WindowClone : Clutter.Actor {
reallocate ();

load_clone ();

window.notify["title"].connect (() => window_title.set_text (window.get_title () ?? ""));
window_title.set_text (window.get_title () ?? "");

notify["has-pointer"].connect (() => update_hover_widgets ());
}

~WindowClone () {
Expand Down Expand Up @@ -186,10 +190,10 @@ public class Gala.WindowClone : Clutter.Actor {
private void load_clone (bool was_waiting = false) {
var actor = (Meta.WindowActor) window.get_compositor_private ();
if (actor == null) {
ulong shown_handler = 0;
shown_handler = window.shown.connect (() => {
load_clone (true);
window.disconnect (shown_handler);
Idle.add (() => {
if (window.get_compositor_private () != null)
load_clone (true);
return Source.REMOVE;
});

return;
Expand All @@ -200,6 +204,7 @@ public class Gala.WindowClone : Clutter.Actor {
}

clone = new Clutter.Clone (actor);
clone.set_content_scaling_filters (TRILINEAR, TRILINEAR);
add_child (clone);

set_child_below_sibling (active_shape, clone);
Expand Down Expand Up @@ -287,8 +292,7 @@ public class Gala.WindowClone : Clutter.Actor {
var target_y = outer_rect.y - offset_y;

active = false;
in_slot_animation = true;
place_widgets (outer_rect.width, outer_rect.height, initial_scale);
update_hover_widgets (true);

GestureTracker.OnUpdate on_animation_update = (percentage) => {
var x = GestureTracker.animation_value (initial_x, target_x, percentage);
Expand All @@ -303,7 +307,6 @@ public class Gala.WindowClone : Clutter.Actor {

window_icon.opacity = (uint) opacity;
set_window_icon_position (width, height, scale, false);
place_widgets ((int)width, (int)height, scale);

shadow_opacity = (uint8) opacity;
};
Expand Down Expand Up @@ -342,12 +345,10 @@ public class Gala.WindowClone : Clutter.Actor {
var transition = window_icon.get_transition ("opacity");
if (transition != null) {
transition.completed.connect (() => {
in_slot_animation = false;
place_widgets (outer_rect.width, outer_rect.height, target_scale);
update_hover_widgets (false);
});
} else {
in_slot_animation = false;
place_widgets (outer_rect.width, outer_rect.height, target_scale);
update_hover_widgets (false);
}
};

Expand Down Expand Up @@ -375,8 +376,7 @@ public class Gala.WindowClone : Clutter.Actor {
active = false;
var scale = display.get_monitor_scale (display.get_monitor_index_for_rect (rect));

in_slot_animation = true;
place_widgets (rect.width, rect.height, scale);
update_hover_widgets (true);

GestureTracker.OnUpdate on_animation_update = (percentage) => {
var x = GestureTracker.animation_value (initial_x, rect.x, percentage);
Expand Down Expand Up @@ -422,12 +422,10 @@ public class Gala.WindowClone : Clutter.Actor {
var transition = window_icon.get_transition ("opacity");
if (transition != null) {
transition.completed.connect (() => {
in_slot_animation = false;
place_widgets (rect.width, rect.height, scale);
update_hover_widgets (false);
});
} else {
in_slot_animation = false;
place_widgets (rect.width, rect.height, scale);
update_hover_widgets (false);
}
};

Expand All @@ -438,33 +436,62 @@ public class Gala.WindowClone : Clutter.Actor {
}
}

/**
* Except for the texture clone and the highlight all children are placed
* according to their given allocations. The first two are placed in a way
* that compensates for invisible borders of the texture.
*/
public override void allocate (Clutter.ActorBox box) {
base.allocate (box);

if (clone == null || (drag_action != null && drag_action.dragging)) {
return;
}

var input_rect = window.get_buffer_rect ();
var outer_rect = window.get_frame_rect ();
var scale_factor = width / outer_rect.width;
var clone_scale_factor = width / outer_rect.width;

clone.set_scale (clone_scale_factor, clone_scale_factor);

float clone_width, clone_height;
clone.get_preferred_size (null, null, out clone_width, out clone_height);

// Compensate for invisible borders of the texture
float clone_x = (input_rect.x - outer_rect.x) * clone_scale_factor;
float clone_y = (input_rect.y - outer_rect.y) * clone_scale_factor;

var clone_alloc = InternalUtils.actor_box_from_rect (clone_x, clone_y, clone_width, clone_height);
clone.allocate (clone_alloc);

Clutter.ActorBox shape_alloc = {
-ACTIVE_SHAPE_SIZE,
-ACTIVE_SHAPE_SIZE,
outer_rect.width * scale_factor + ACTIVE_SHAPE_SIZE,
outer_rect.height * scale_factor + ACTIVE_SHAPE_SIZE
box.get_width () + ACTIVE_SHAPE_SIZE,
box.get_height () + ACTIVE_SHAPE_SIZE
};
Clutter.ActorBox.clamp_to_pixel (ref shape_alloc);
active_shape.allocate (shape_alloc);

if (clone == null || (drag_action != null && drag_action.dragging)) {
return;
}
float close_button_width, close_button_height;
close_button.get_preferred_size (null, null, out close_button_width, out close_button_height);

var close_button_x = is_close_button_on_left () ?
-close_button_width * 0.5f : box.get_width () - close_button_width * 0.5f;

var close_button_alloc = InternalUtils.actor_box_from_rect (close_button_x, -close_button_height * 0.33f, close_button_width, close_button_height);
close_button.allocate (close_button_alloc);

var rect = get_transformed_extents ();
var monitor_index = display.get_monitor_index_for_rect (Mtk.Rectangle.from_graphene_rect (rect, ROUND));
var monitor_scale = display.get_monitor_scale (monitor_index);

float window_title_max_width = box.get_width () - InternalUtils.scale_to_int (TITLE_MAX_WIDTH_MARGIN, monitor_scale);
float window_title_height, window_title_nat_width;
window_title.get_preferred_size (null, null, out window_title_nat_width, out window_title_height);

var window_title_width = window_title_nat_width.clamp (0, window_title_max_width);

clone.set_scale (scale_factor, scale_factor);
clone.set_position ((input_rect.x - outer_rect.x) * scale_factor,
(input_rect.y - outer_rect.y) * scale_factor);
float window_title_x = (box.get_width () - window_title_width) / 2;
float window_title_y = box.get_height () - InternalUtils.scale_to_int (WINDOW_ICON_SIZE, monitor_scale) * 0.75f - (window_title_height / 2) - InternalUtils.scale_to_int (18, monitor_scale);

var window_title_alloc = InternalUtils.actor_box_from_rect (window_title_x, window_title_y, window_title_width, window_title_height);
window_title.allocate (window_title_alloc);
}

#if HAS_MUTTER45
Expand All @@ -475,74 +502,26 @@ public class Gala.WindowClone : Clutter.Actor {
return Clutter.EVENT_STOP;
}

#if HAS_MUTTER45
public override bool enter_event (Clutter.Event event) {
#else
public override bool enter_event (Clutter.CrossingEvent event) {
#endif
if (drag_action != null && drag_action.dragging) {
return Clutter.EVENT_PROPAGATE;
private void update_hover_widgets (bool? animating = null) {
if (animating != null) {
in_slot_animation = animating;
}

var duration = AnimationsSettings.get_animation_duration (FADE_ANIMATION_DURATION);

close_button.save_easing_state ();
close_button.set_easing_mode (Clutter.AnimationMode.LINEAR);
close_button.set_easing_duration (duration);
close_button.opacity = in_slot_animation ? 0 : 255;
close_button.restore_easing_state ();

window_title.save_easing_state ();
window_title.set_easing_mode (Clutter.AnimationMode.LINEAR);
window_title.set_easing_duration (duration);
window_title.opacity = in_slot_animation ? 0 : 255;
window_title.restore_easing_state ();

return Clutter.EVENT_PROPAGATE;
}

#if HAS_MUTTER45
public override bool leave_event (Clutter.Event event) {
#else
public override bool leave_event (Clutter.CrossingEvent event) {
#endif
var duration = AnimationsSettings.get_animation_duration (FADE_ANIMATION_DURATION);
var show = has_pointer && !in_slot_animation;

close_button.save_easing_state ();
close_button.set_easing_mode (Clutter.AnimationMode.LINEAR);
close_button.set_easing_duration (duration);
close_button.opacity = 0;
close_button.opacity = show ? 255 : 0;
close_button.restore_easing_state ();

window_title.save_easing_state ();
window_title.set_easing_mode (Clutter.AnimationMode.LINEAR);
window_title.set_easing_duration (duration);
window_title.opacity = 0;
window_title.opacity = show ? 255 : 0;
window_title.restore_easing_state ();

return Clutter.EVENT_PROPAGATE;
}

/**
* Place the widgets, that is the close button and the WindowIcon of the window,
* at their positions inside the actor for a given width and height.
*/
public void place_widgets (int dest_width, int dest_height, float scale_factor) {
var close_button_size = InternalUtils.scale_to_int (CLOSE_WINDOW_ICON_SIZE, scale_factor);
close_button.set_size (close_button_size, close_button_size);

close_button.y = -close_button.height * 0.33f;
close_button.x = is_close_button_on_left () ?
-close_button.width * 0.5f :
dest_width - close_button.width * 0.5f;

bool show = has_pointer && !in_slot_animation;
close_button.opacity = show ? 255 : 0;
window_title.opacity = close_button.opacity;

window_title.set_text (window.get_title () ?? "");
window_title.set_max_width (dest_width - InternalUtils.scale_to_int (TITLE_MAX_WIDTH_MARGIN, scale_factor));
set_window_title_position (dest_width, dest_height, scale_factor);
}

private void toggle_shadow (bool show) {
Expand Down Expand Up @@ -845,12 +824,6 @@ public class Gala.WindowClone : Clutter.Actor {
window_icon.set_position (x, y);
}

private void set_window_title_position (float window_width, float window_height, float scale_factor) {
var x = (int)Math.round ((window_width - window_title.width) / 2);
var y = (int)Math.round (window_height - InternalUtils.scale_to_int (WINDOW_ICON_SIZE, scale_factor) * 0.75f - (window_title.height / 2) - InternalUtils.scale_to_int (18, scale_factor));
window_title.set_position (x, y);
}

private static bool is_close_button_on_left () {
var layout = Meta.Prefs.get_button_layout ();
foreach (var button_function in layout.left_buttons) {
Expand Down
Loading