@@ -67,10 +67,12 @@ public class Gala.WindowClone : Widget, RootTarget {
6767 private ulong check_confirm_dialog_cb = 0 ;
6868
6969 private Clutter . Actor clone_container;
70+ private Clutter . Actor child_clone_container;
7071 private Gala . CloseButton close_button;
7172 private ActiveShape active_shape;
7273 private Clutter . Actor window_icon;
7374 private Tooltip window_title;
75+ private GLib . ListModel window_list_model;
7476
7577 private GestureController gesture_controller;
7678
@@ -131,9 +133,14 @@ public class Gala.WindowClone : Widget, RootTarget {
131133 };
132134 bind_property (" monitor-scale" , active_shape, " monitor-scale" );
133135
134- clone_container = new Clutter .Actor () {
135- pivot_point = { 0.5f , 0.5f }
136- };
136+ window_list_model = new WindowListModel (wm. get_display (), STACKING , true , false , - 1 , null , new ChildFilter (window));
137+ window_list_model. items_changed. connect_after (update_targets);
138+
139+ child_clone_container = new Clutter .Actor ();
140+ child_clone_container. bind_model (window_list_model, create_child_func);
141+
142+ clone_container = new Clutter .Actor ();
143+ clone_container. add_child (child_clone_container);
137144
138145 window_title = new Tooltip (monitor_scale);
139146 bind_property (" monitor-scale" , window_title, " monitor-scale" );
@@ -176,6 +183,18 @@ public class Gala.WindowClone : Widget, RootTarget {
176183 active_shape. restore_easing_state ();
177184 }
178185
186+ private static Clutter . Actor create_child_func (Object obj) requires (obj is Meta . Window ) {
187+ unowned var child_window = (Meta . Window ) obj;
188+ unowned var child_window_actor = (Meta . WindowActor ) child_window. get_compositor_private ();
189+
190+ if (child_window_actor == null ) {
191+ critical (" WindowClone: WindowListModel gave us a bad window" );
192+ return new Clutter .Actor ();
193+ }
194+
195+ return new Clutter .Clone (child_window_actor);
196+ }
197+
179198 private void reallocate () {
180199 window_icon = new WindowIcon (window, WINDOW_ICON_SIZE , (int )Math . round (monitor_scale)) {
181200 visible = mode != SINGLE_APP_OVERVIEW
@@ -197,7 +216,7 @@ public class Gala.WindowClone : Widget, RootTarget {
197216 */
198217 private void load_clone (Meta . WindowActor actor) {
199218 clone = new Clutter .Clone (actor);
200- clone_container. add_child (clone);
219+ clone_container. insert_child_below (clone, null );
201220
202221 check_shadow_requirements ();
203222 }
@@ -276,6 +295,42 @@ public class Gala.WindowClone : Widget, RootTarget {
276295 add_target (new PropertyTarget (MULTITASKING_VIEW , window_title, " opacity" , typeof (uint8 ), (uint8 ) 0u , (uint8 ) 255u ));
277296
278297 add_target (new PropertyTarget (MULTITASKING_VIEW , close_button, " opacity" , typeof (uint8 ), (uint8 ) 0u , (uint8 ) 255u ));
298+
299+ var window_buffer_rect = window. get_buffer_rect ();
300+ var window_shadow_spread_x = window_rect. x - window_buffer_rect. x;
301+ var window_shadow_spread_y = window_rect. y - window_buffer_rect. y;
302+
303+ var i = 0u ;
304+ for (unowned var child_clone = child_clone_container. get_first_child ();
305+ child_clone != null ;
306+ child_clone = child_clone. get_next_sibling ()
307+ ) {
308+ var child_window = (Meta . Window ) window_list_model. get_item (i);
309+
310+ var child_buffer_rect = child_window. get_buffer_rect ();
311+ var child_frame_rect = child_window. get_frame_rect ();
312+
313+ var scale = 1.0f ;
314+ if (child_frame_rect. width > window_rect. width || child_frame_rect. height > window_rect. height) {
315+ scale = float . min ((float ) window_rect. width / child_frame_rect. width, (float ) window_rect. height / child_frame_rect. height);
316+
317+ add_target (new PropertyTarget (MULTITASKING_VIEW , child_clone, " width" , typeof (float ), (float ) child_buffer_rect. width, child_buffer_rect. width * scale));
318+ add_target (new PropertyTarget (MULTITASKING_VIEW , child_clone, " height" , typeof (float ), (float ) child_buffer_rect. height, child_buffer_rect. height * scale));
319+ }
320+
321+ var child_parent_x_diff = child_buffer_rect. x - window_buffer_rect. x;
322+ var child_parent_y_diff = child_buffer_rect. y - window_buffer_rect. y;
323+ // Center the window
324+ var child_shadow_spread_x = (child_frame_rect. x - child_buffer_rect. x) * scale;
325+ var child_shadow_spread_y = (child_frame_rect. y - child_buffer_rect. y) * scale;
326+ var target_x = window_shadow_spread_x - child_shadow_spread_x + (window_rect. width - child_frame_rect. width * scale) / 2.0f ;
327+ var target_y = window_shadow_spread_y - child_shadow_spread_y + (window_rect. height - child_frame_rect. height * scale) / 2.0f ;
328+
329+ add_target (new PropertyTarget (MULTITASKING_VIEW , child_clone, " x" , typeof (float ), (float ) child_parent_x_diff, target_x));
330+ add_target (new PropertyTarget (MULTITASKING_VIEW , child_clone, " y" , typeof (float ), (float ) child_parent_y_diff, target_y));
331+
332+ i++ ;
333+ }
279334 }
280335
281336 public override void update_progress (Gala . GestureAction action, double progress) {
@@ -325,7 +380,7 @@ public class Gala.WindowClone : Widget, RootTarget {
325380
326381 unowned var display = wm. get_display ();
327382
328- clone . set_scale (clone_scale_factor, clone_scale_factor);
383+ clone_container . set_scale (clone_scale_factor, clone_scale_factor);
329384
330385 Clutter . ActorBox shape_alloc = {
331386 - ACTIVE_SHAPE_SIZE ,
@@ -418,14 +473,14 @@ public class Gala.WindowClone : Widget, RootTarget {
418473 drag_action. cancel ();
419474 }
420475
421- if (clone != null ) {
422- clone. destroy ();
423- }
476+ clone? . destroy ();
424477
425478 if (check_confirm_dialog_cb != 0 ) {
426479 SignalHandler . disconnect (window. get_display (), check_confirm_dialog_cb);
427480 check_confirm_dialog_cb = 0 ;
428481 }
482+
483+ child_clone_container. bind_model (null , (Clutter . ActorCreateChildFunc ) null );
429484 }
430485
431486 private void actor_clicked (uint32 button, Clutter . InputDeviceType device_type = POINTER_DEVICE ) {
@@ -443,18 +498,21 @@ public class Gala.WindowClone : Widget, RootTarget {
443498 private Clutter . Actor drag_begin (float click_x, float click_y) requires (drag_handle == null ) {
444499 active_shape. hide ();
445500
446- var scale = window_icon. width / clone . width;
501+ var scale = window_icon. width / clone_container . width;
447502 var duration = Utils . get_animation_duration (FADE_ANIMATION_DURATION );
448503
449504 float abs_x, abs_y;
450- clone. get_transformed_position (out abs_x, out abs_y);
451- clone. save_easing_state ();
452- clone. set_easing_duration (duration);
453- clone. set_easing_mode (Clutter . AnimationMode . EASE_IN_CUBIC );
454- clone. set_pivot_point ((click_x - abs_x) / clone. width, (click_y - abs_y) / clone. height);
455- clone. set_scale (scale, scale);
456- clone. opacity = 0 ;
457- clone. restore_easing_state ();
505+ clone_container. get_transformed_position (out abs_x, out abs_y);
506+ clone_container. save_easing_state ();
507+ clone_container. set_easing_duration (duration);
508+ clone_container. set_easing_mode (Clutter . AnimationMode . EASE_IN_CUBIC );
509+ clone_container. set_pivot_point (
510+ (click_x - abs_x) / clone_container. width,
511+ (click_y - abs_y) / clone_container. height
512+ );
513+ clone_container. set_scale (scale, scale);
514+ clone_container. opacity = 0 ;
515+ clone_container. restore_easing_state ();
458516
459517 get_transformed_position (out abs_x, out abs_y);
460518
@@ -565,13 +623,13 @@ public class Gala.WindowClone : Widget, RootTarget {
565623 drag_handle. set_position (target_x, target_y);
566624 drag_handle. restore_easing_state ();
567625
568- clone . set_pivot_point (0.0f , 0.0f );
569- clone . save_easing_state ();
570- clone . set_easing_duration (duration);
571- clone . set_easing_mode (Clutter . AnimationMode . EASE_OUT_QUAD );
572- clone . set_scale (1 , 1 );
573- clone . opacity = 255 ;
574- clone . restore_easing_state ();
626+ clone_container . set_pivot_point (0.0f , 0.0f );
627+ clone_container . save_easing_state ();
628+ clone_container . set_easing_duration (duration);
629+ clone_container . set_easing_mode (Clutter . AnimationMode . EASE_OUT_QUAD );
630+ clone_container . set_scale (1 , 1 );
631+ clone_container . opacity = 255 ;
632+ clone_container . restore_easing_state ();
575633
576634 close_button. visible = true ;
577635 window_title. visible = true ;
@@ -645,4 +703,17 @@ public class Gala.WindowClone : Widget, RootTarget {
645703 });
646704 }
647705 }
706+
707+ private class ChildFilter : Gtk .Filter {
708+ public Meta . Window parent_window { private get ; construct; }
709+
710+ public ChildFilter (Meta .Window parent_window ) {
711+ Object (parent_window: parent_window);
712+ }
713+
714+ public override bool match (GLib .Object ? item ) requires (item is Meta .Window ) {
715+ unowned var window = (Meta . Window ) item;
716+ return parent_window. is_ancestor_of_transient (window);
717+ }
718+ }
648719}
0 commit comments