Skip to content

Commit 903bc3f

Browse files
leolost2605lenemterdanirabbitstsdc
authored
WindowClone: Layout in allocate virtual (#2082)
Co-authored-by: Leo <[email protected]> Co-authored-by: Danielle Foré <[email protected]> Co-authored-by: Stanisław <[email protected]>
1 parent f36b4be commit 903bc3f

File tree

3 files changed

+71
-112
lines changed

3 files changed

+71
-112
lines changed

src/InternalUtils.vala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,5 +340,13 @@ namespace Gala {
340340
return { 0, 0, (int) screen_width, (int) screen_height };
341341
}
342342
}
343+
344+
public static Clutter.ActorBox actor_box_from_rect (float x, float y, float width, float height) {
345+
var actor_box = Clutter.ActorBox ();
346+
actor_box.init_rect (x, y, width, height);
347+
Clutter.ActorBox.clamp_to_pixel (ref actor_box);
348+
349+
return actor_box;
350+
}
343351
}
344352
}

src/Widgets/Tooltip.vala

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,7 @@ public class Gala.Tooltip : CanvasActor {
1313
*/
1414
private Clutter.Text text_actor;
1515

16-
/**
17-
* Maximum width of the Tooltip.
18-
* @see set_max_width
19-
*/
20-
public float max_width;
21-
2216
construct {
23-
max_width = 200;
24-
2517
#if HAS_MUTTER47
2618
Cogl.Color text_color = {
2719
#else
@@ -51,21 +43,6 @@ public class Gala.Tooltip : CanvasActor {
5143
text_actor.text = new_text;
5244
}
5345

54-
public void set_max_width (float new_max_width) {
55-
max_width = new_max_width;
56-
57-
queue_relayout ();
58-
}
59-
60-
protected override void allocate (Clutter.ActorBox box) {
61-
if (box.get_width () > max_width) {
62-
box.set_origin (box.get_x () + ((box.get_width () - max_width) / 2), box.get_y ());
63-
box.set_size (max_width, box.get_height ());
64-
}
65-
66-
base.allocate (box);
67-
}
68-
6946
protected override void draw (Cairo.Context ctx, int width, int height) {
7047
ctx.save ();
7148
ctx.set_operator (Cairo.Operator.CLEAR);

src/Widgets/WindowClone.vala

Lines changed: 63 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
* a close button and a shadow. Used together with the WindowCloneContainer.
1010
*/
1111
public class Gala.WindowClone : Clutter.Actor {
12-
private const int CLOSE_WINDOW_ICON_SIZE = 36;
1312
private const int WINDOW_ICON_SIZE = 64;
1413
private const int ACTIVE_SHAPE_SIZE = 12;
1514
private const int FADE_ANIMATION_DURATION = 200;
@@ -144,6 +143,11 @@ public class Gala.WindowClone : Clutter.Actor {
144143
reallocate ();
145144

146145
load_clone ();
146+
147+
window.notify["title"].connect (() => window_title.set_text (window.get_title () ?? ""));
148+
window_title.set_text (window.get_title () ?? "");
149+
150+
notify["has-pointer"].connect (() => update_hover_widgets ());
147151
}
148152

149153
~WindowClone () {
@@ -186,10 +190,10 @@ public class Gala.WindowClone : Clutter.Actor {
186190
private void load_clone (bool was_waiting = false) {
187191
var actor = (Meta.WindowActor) window.get_compositor_private ();
188192
if (actor == null) {
189-
ulong shown_handler = 0;
190-
shown_handler = window.shown.connect (() => {
191-
load_clone (true);
192-
window.disconnect (shown_handler);
193+
Idle.add (() => {
194+
if (window.get_compositor_private () != null)
195+
load_clone (true);
196+
return Source.REMOVE;
193197
});
194198

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

202206
clone = new Clutter.Clone (actor);
207+
clone.set_content_scaling_filters (TRILINEAR, TRILINEAR);
203208
add_child (clone);
204209

205210
set_child_below_sibling (active_shape, clone);
@@ -283,17 +288,15 @@ public class Gala.WindowClone : Clutter.Actor {
283288
var target_y = outer_rect.y - offset_y;
284289

285290
active = false;
286-
in_slot_animation = true;
287-
place_widgets (outer_rect.width, outer_rect.height, initial_scale);
291+
update_hover_widgets (true);
288292

289293
new GesturePropertyTransition (this, gesture_tracker, "x", null, (float) target_x).start (with_gesture);
290294
new GesturePropertyTransition (this, gesture_tracker, "y", null, (float) target_y).start (with_gesture);
291295
new GesturePropertyTransition (this, gesture_tracker, "width", null, (float) outer_rect.width).start (with_gesture);
292296
new GesturePropertyTransition (this, gesture_tracker, "height", null, (float) outer_rect.height).start (with_gesture);
293297
new GesturePropertyTransition (this, gesture_tracker, "shadow-opacity", (uint8) 255, (uint8) 0).start (with_gesture);
294298
new GesturePropertyTransition (window_icon, gesture_tracker, "opacity", 255u, 0u).start (with_gesture, () => {
295-
in_slot_animation = false;
296-
place_widgets (outer_rect.width, outer_rect.height, target_scale);
299+
update_hover_widgets (false);
297300
});
298301

299302
GestureTracker.OnUpdate on_animation_update = (percentage) => {
@@ -302,7 +305,6 @@ public class Gala.WindowClone : Clutter.Actor {
302305
var scale = GestureTracker.animation_value (initial_scale, target_scale, percentage);
303306

304307
set_window_icon_position (width, height, scale, false);
305-
place_widgets ((int)width, (int)height, scale);
306308
};
307309

308310
GestureTracker.OnEnd on_animation_end = (percentage, cancel_action) => {
@@ -335,8 +337,6 @@ public class Gala.WindowClone : Clutter.Actor {
335337
public void take_slot (Meta.Rectangle rect, bool from_window_position, bool with_gesture = false, bool is_cancel_animation = false) {
336338
#endif
337339
slot = rect;
338-
in_slot_animation = true;
339-
340340
active = false;
341341

342342
var outer_rect = window.get_frame_rect ();
@@ -349,8 +349,8 @@ public class Gala.WindowClone : Clutter.Actor {
349349
float intial_y = from_window_position ? outer_rect.y - monitor_geom.y : y;
350350

351351
var scale = display.get_monitor_scale (display.get_monitor_index_for_rect (rect));
352-
place_widgets (rect.width, rect.height, scale);
353352

353+
update_hover_widgets (true);
354354
set_window_icon_position (initial_width, initial_height, scale);
355355

356356
new GesturePropertyTransition (this, gesture_tracker, "x", intial_x, (float) rect.x).start (with_gesture);
@@ -359,8 +359,7 @@ public class Gala.WindowClone : Clutter.Actor {
359359
new GesturePropertyTransition (this, gesture_tracker, "height", (float) initial_height, (float) rect.height).start (with_gesture);
360360
new GesturePropertyTransition (this, gesture_tracker, "shadow-opacity", (uint8) 0, (uint8) 255).start (with_gesture);
361361
new GesturePropertyTransition (window_icon, gesture_tracker, "opacity", 0u, 255u).start (with_gesture, () => {
362-
in_slot_animation = false;
363-
place_widgets (rect.width, rect.height, scale);
362+
update_hover_widgets (false);
364363
});
365364

366365
GestureTracker.OnUpdate on_animation_update = (percentage) => {
@@ -393,33 +392,62 @@ public class Gala.WindowClone : Clutter.Actor {
393392
}
394393
}
395394

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

398+
if (clone == null || (drag_action != null && drag_action.dragging)) {
399+
return;
400+
}
401+
404402
var input_rect = window.get_buffer_rect ();
405403
var outer_rect = window.get_frame_rect ();
406-
var scale_factor = width / outer_rect.width;
404+
var clone_scale_factor = width / outer_rect.width;
405+
406+
clone.set_scale (clone_scale_factor, clone_scale_factor);
407+
408+
float clone_width, clone_height;
409+
clone.get_preferred_size (null, null, out clone_width, out clone_height);
410+
411+
// Compensate for invisible borders of the texture
412+
float clone_x = (input_rect.x - outer_rect.x) * clone_scale_factor;
413+
float clone_y = (input_rect.y - outer_rect.y) * clone_scale_factor;
414+
415+
var clone_alloc = InternalUtils.actor_box_from_rect (clone_x, clone_y, clone_width, clone_height);
416+
clone.allocate (clone_alloc);
407417

408418
Clutter.ActorBox shape_alloc = {
409419
-ACTIVE_SHAPE_SIZE,
410420
-ACTIVE_SHAPE_SIZE,
411-
outer_rect.width * scale_factor + ACTIVE_SHAPE_SIZE,
412-
outer_rect.height * scale_factor + ACTIVE_SHAPE_SIZE
421+
box.get_width () + ACTIVE_SHAPE_SIZE,
422+
box.get_height () + ACTIVE_SHAPE_SIZE
413423
};
424+
Clutter.ActorBox.clamp_to_pixel (ref shape_alloc);
414425
active_shape.allocate (shape_alloc);
415426

416-
if (clone == null || (drag_action != null && drag_action.dragging)) {
417-
return;
418-
}
427+
float close_button_width, close_button_height;
428+
close_button.get_preferred_size (null, null, out close_button_width, out close_button_height);
429+
430+
var close_button_x = is_close_button_on_left () ?
431+
-close_button_width * 0.5f : box.get_width () - close_button_width * 0.5f;
432+
433+
var close_button_alloc = InternalUtils.actor_box_from_rect (close_button_x, -close_button_height * 0.33f, close_button_width, close_button_height);
434+
close_button.allocate (close_button_alloc);
435+
436+
var rect = get_transformed_extents ();
437+
var monitor_index = display.get_monitor_index_for_rect (Mtk.Rectangle.from_graphene_rect (rect, ROUND));
438+
var monitor_scale = display.get_monitor_scale (monitor_index);
439+
440+
float window_title_max_width = box.get_width () - InternalUtils.scale_to_int (TITLE_MAX_WIDTH_MARGIN, monitor_scale);
441+
float window_title_height, window_title_nat_width;
442+
window_title.get_preferred_size (null, null, out window_title_nat_width, out window_title_height);
419443

420-
clone.set_scale (scale_factor, scale_factor);
421-
clone.set_position ((input_rect.x - outer_rect.x) * scale_factor,
422-
(input_rect.y - outer_rect.y) * scale_factor);
444+
var window_title_width = window_title_nat_width.clamp (0, window_title_max_width);
445+
446+
float window_title_x = (box.get_width () - window_title_width) / 2;
447+
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);
448+
449+
var window_title_alloc = InternalUtils.actor_box_from_rect (window_title_x, window_title_y, window_title_width, window_title_height);
450+
window_title.allocate (window_title_alloc);
423451
}
424452

425453
#if HAS_MUTTER45
@@ -430,74 +458,26 @@ public class Gala.WindowClone : Clutter.Actor {
430458
return Clutter.EVENT_STOP;
431459
}
432460

433-
#if HAS_MUTTER45
434-
public override bool enter_event (Clutter.Event event) {
435-
#else
436-
public override bool enter_event (Clutter.CrossingEvent event) {
437-
#endif
438-
if (drag_action != null && drag_action.dragging) {
439-
return Clutter.EVENT_PROPAGATE;
461+
private void update_hover_widgets (bool? animating = null) {
462+
if (animating != null) {
463+
in_slot_animation = animating;
440464
}
441465

442466
var duration = AnimationsSettings.get_animation_duration (FADE_ANIMATION_DURATION);
443467

444-
close_button.save_easing_state ();
445-
close_button.set_easing_mode (Clutter.AnimationMode.LINEAR);
446-
close_button.set_easing_duration (duration);
447-
close_button.opacity = in_slot_animation ? 0 : 255;
448-
close_button.restore_easing_state ();
449-
450-
window_title.save_easing_state ();
451-
window_title.set_easing_mode (Clutter.AnimationMode.LINEAR);
452-
window_title.set_easing_duration (duration);
453-
window_title.opacity = in_slot_animation ? 0 : 255;
454-
window_title.restore_easing_state ();
455-
456-
return Clutter.EVENT_PROPAGATE;
457-
}
458-
459-
#if HAS_MUTTER45
460-
public override bool leave_event (Clutter.Event event) {
461-
#else
462-
public override bool leave_event (Clutter.CrossingEvent event) {
463-
#endif
464-
var duration = AnimationsSettings.get_animation_duration (FADE_ANIMATION_DURATION);
468+
var show = has_pointer && !in_slot_animation;
465469

466470
close_button.save_easing_state ();
467471
close_button.set_easing_mode (Clutter.AnimationMode.LINEAR);
468472
close_button.set_easing_duration (duration);
469-
close_button.opacity = 0;
473+
close_button.opacity = show ? 255 : 0;
470474
close_button.restore_easing_state ();
471475

472476
window_title.save_easing_state ();
473477
window_title.set_easing_mode (Clutter.AnimationMode.LINEAR);
474478
window_title.set_easing_duration (duration);
475-
window_title.opacity = 0;
479+
window_title.opacity = show ? 255 : 0;
476480
window_title.restore_easing_state ();
477-
478-
return Clutter.EVENT_PROPAGATE;
479-
}
480-
481-
/**
482-
* Place the widgets, that is the close button and the WindowIcon of the window,
483-
* at their positions inside the actor for a given width and height.
484-
*/
485-
public void place_widgets (int dest_width, int dest_height, float scale_factor) {
486-
var close_button_size = InternalUtils.scale_to_int (CLOSE_WINDOW_ICON_SIZE, scale_factor);
487-
close_button.set_size (close_button_size, close_button_size);
488-
489-
close_button.y = -close_button.height * 0.33f;
490-
close_button.x = is_close_button_on_left () ?
491-
-close_button.width * 0.5f :
492-
dest_width - close_button.width * 0.5f;
493-
494-
bool show = has_pointer && !in_slot_animation;
495-
close_button.opacity = show ? 255 : 0;
496-
window_title.opacity = close_button.opacity;
497-
498-
window_title.set_text (window.get_title () ?? "");
499-
window_title.set_max_width (dest_width - InternalUtils.scale_to_int (TITLE_MAX_WIDTH_MARGIN, scale_factor));
500-
set_window_title_position (dest_width, dest_height, scale_factor);
501481
}
502482

503483
private void toggle_shadow (bool show) {
@@ -800,12 +780,6 @@ public class Gala.WindowClone : Clutter.Actor {
800780
window_icon.set_position (x, y);
801781
}
802782

803-
private void set_window_title_position (float window_width, float window_height, float scale_factor) {
804-
var x = (int)Math.round ((window_width - window_title.width) / 2);
805-
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));
806-
window_title.set_position (x, y);
807-
}
808-
809783
private static bool is_close_button_on_left () {
810784
var layout = Meta.Prefs.get_button_layout ();
811785
foreach (var button_function in layout.left_buttons) {

0 commit comments

Comments
 (0)