Skip to content

Commit 3bca007

Browse files
committed
WindowClone: display modal dialogs on top of parent window
1 parent f53af32 commit 3bca007

File tree

2 files changed

+99
-34
lines changed

2 files changed

+99
-34
lines changed

src/Widgets/MultitaskingView/WindowClone.vala

Lines changed: 98 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,12 @@ public class Gala.WindowClone : ActorTarget, RootTarget {
7575
private bool in_slot_animation = false;
7676

7777
private Clutter.Clone clone;
78+
private Clutter.Actor windows_container;
7879
private Gala.CloseButton close_button;
7980
private ActiveShape active_shape;
8081
private Clutter.Actor window_icon;
8182
private Tooltip window_title;
83+
private HashTable<Meta.Window, Clutter.Clone> child_clones = new HashTable<Meta.Window, Clutter.Clone> (null, null);
8284

8385
private GestureController gesture_controller;
8486

@@ -132,10 +134,13 @@ public class Gala.WindowClone : ActorTarget, RootTarget {
132134

133135
clone = new Clutter.Clone ((Meta.WindowActor) window.get_compositor_private ());
134136

137+
windows_container = new Clutter.Actor ();
138+
windows_container.add_child (clone);
139+
135140
window_title = new Tooltip ();
136141

137142
add_child (active_shape);
138-
add_child (clone);
143+
add_child (windows_container);
139144
add_child (window_title);
140145

141146
notify["monitor-scale"].connect (reallocate);
@@ -147,6 +152,39 @@ public class Gala.WindowClone : ActorTarget, RootTarget {
147152
window_title.set_text (window.get_title () ?? "");
148153

149154
notify["has-pointer"].connect (() => update_hover_widgets ());
155+
156+
unowned var display = wm.get_display ();
157+
foreach (unowned var child_window in display.list_all_windows ()) {
158+
InternalUtils.wait_for_window_actor_visible (
159+
child_window,
160+
(window_actor) => add_child_window (window_actor.meta_window)
161+
);
162+
}
163+
164+
display.window_created.connect (
165+
(new_window) => InternalUtils.wait_for_window_actor_visible (
166+
new_window,
167+
(window_actor) => add_child_window (window_actor.meta_window)
168+
)
169+
);
170+
}
171+
172+
private void add_child_window (Meta.Window new_window) requires (new_window.get_compositor_private () != null) {
173+
if (new_window == window || !window.is_ancestor_of_transient (new_window) && new_window.find_root_ancestor () != window) {
174+
return;
175+
}
176+
177+
unowned var new_window_actor = (Meta.WindowActor) new_window.get_compositor_private ();
178+
var actor_clone = new Clutter.Clone (new_window_actor);
179+
windows_container.add_child (actor_clone);
180+
181+
child_clones.insert (new_window, actor_clone);
182+
183+
new_window.unmanaged.connect ((new_window) => {
184+
windows_container.remove_child (child_clones.take (new_window));
185+
});
186+
187+
update_targets ();
150188
}
151189

152190
~WindowClone () {
@@ -242,6 +280,35 @@ public class Gala.WindowClone : ActorTarget, RootTarget {
242280
add_target (new PropertyTarget (MULTITASKING_VIEW, window_icon, "opacity", typeof (uint), 0u, 255u));
243281

244282
add_target (new PropertyTarget (MULTITASKING_VIEW, window_title, "opacity", typeof (uint), 0u, 255u));
283+
284+
var window_buffer_rect = window.get_buffer_rect ();
285+
var window_shadow_spread_x = window_rect.x - window_buffer_rect.x;
286+
var window_shadow_spread_y = window_rect.y - window_buffer_rect.y;
287+
288+
child_clones.foreach ((child_window, child_clone) => {
289+
var child_buffer_rect = child_window.get_buffer_rect ();
290+
var child_frame_rect = child_window.get_frame_rect ();
291+
292+
var scale = 1.0f;
293+
if (child_frame_rect.width > window_rect.width || child_frame_rect.height > window_rect.height) {
294+
scale = float.min ((float) window_rect.width / child_frame_rect.width, (float) window_rect.height / child_frame_rect.height);
295+
296+
add_target (new PropertyTarget (MULTITASKING_VIEW, child_clone, "width", typeof (float), (float) child_buffer_rect.width, child_buffer_rect.width * scale));
297+
add_target (new PropertyTarget (MULTITASKING_VIEW, child_clone, "height", typeof (float), (float) child_buffer_rect.height, child_buffer_rect.height * scale));
298+
}
299+
300+
var child_parent_x_diff = child_buffer_rect.x - window_buffer_rect.x;
301+
var child_parent_y_diff = child_buffer_rect.y - window_buffer_rect.y;
302+
303+
// Center the window
304+
var child_shadow_spread_x = (child_frame_rect.x - child_buffer_rect.x) * scale;
305+
var child_shadow_spread_y = (child_frame_rect.y - child_buffer_rect.y) * scale;
306+
var target_x = window_shadow_spread_x - child_shadow_spread_x + (window_rect.width - child_frame_rect.width * scale) / 2.0f;
307+
var target_y = window_shadow_spread_y - child_shadow_spread_y + (window_rect.height - child_frame_rect.height * scale) / 2.0f;
308+
309+
add_target (new PropertyTarget (MULTITASKING_VIEW, child_clone, "x", typeof (float), (float) child_parent_x_diff, target_x));
310+
add_target (new PropertyTarget (MULTITASKING_VIEW, child_clone, "y", typeof (float), (float) child_parent_y_diff, target_y));
311+
});
245312
}
246313

247314
public override void start_progress (GestureAction action) {
@@ -256,8 +323,8 @@ public class Gala.WindowClone : ActorTarget, RootTarget {
256323
var target_translation_y = (float) (-CLOSE_TRANSLATION * monitor_scale * progress);
257324
var target_opacity = (uint) (255 * (1 - progress));
258325

259-
clone.translation_y = target_translation_y;
260-
clone.opacity = target_opacity;
326+
windows_container.translation_y = target_translation_y;
327+
windows_container.opacity = target_opacity;
261328

262329
window_icon.translation_y = target_translation_y;
263330
window_icon.opacity = target_opacity;
@@ -284,21 +351,19 @@ public class Gala.WindowClone : ActorTarget, RootTarget {
284351
return;
285352
}
286353

287-
var input_rect = window.get_buffer_rect ();
288-
var outer_rect = window.get_frame_rect ();
289-
var clone_scale_factor = width / outer_rect.width;
290-
291-
clone.set_scale (clone_scale_factor, clone_scale_factor);
292-
293-
float clone_width, clone_height;
294-
clone.get_preferred_size (null, null, out clone_width, out clone_height);
354+
var buffer_rect = window.get_buffer_rect ();
355+
var frame_rect = window.get_frame_rect ();
356+
var scale_factor = width / frame_rect.width;
295357

296358
// Compensate for invisible borders of the texture
297-
float clone_x = (input_rect.x - outer_rect.x) * clone_scale_factor;
298-
float clone_y = (input_rect.y - outer_rect.y) * clone_scale_factor;
359+
var shadow_offset_x = buffer_rect.x - frame_rect.x;
360+
var shadow_offset_y = buffer_rect.y - frame_rect.y;
361+
362+
windows_container.set_scale (scale_factor, scale_factor);
363+
float preferred_width, preferred_height;
364+
windows_container.get_preferred_size (null, null, out preferred_width, out preferred_height);
299365

300-
var clone_alloc = InternalUtils.actor_box_from_rect (clone_x, clone_y, clone_width, clone_height);
301-
clone.allocate (clone_alloc);
366+
windows_container.allocate (InternalUtils.actor_box_from_rect (shadow_offset_x * scale_factor, shadow_offset_y * scale_factor, preferred_width, preferred_height));
302367

303368
Clutter.ActorBox shape_alloc = {
304369
-ACTIVE_SHAPE_SIZE,
@@ -442,17 +507,17 @@ public class Gala.WindowClone : ActorTarget, RootTarget {
442507

443508
active_shape.hide ();
444509

445-
var scale = window_icon.width / clone.width;
510+
var scale = window_icon.width / windows_container.width;
446511
var duration = Utils.get_animation_duration (FADE_ANIMATION_DURATION);
447512

448-
clone.get_transformed_position (out abs_x, out abs_y);
449-
clone.save_easing_state ();
450-
clone.set_easing_duration (duration);
451-
clone.set_easing_mode (Clutter.AnimationMode.EASE_IN_CUBIC);
452-
clone.set_pivot_point ((click_x - abs_x) / clone.width, (click_y - abs_y) / clone.height);
453-
clone.set_scale (scale, scale);
454-
clone.opacity = 0;
455-
clone.restore_easing_state ();
513+
windows_container.get_transformed_position (out abs_x, out abs_y);
514+
windows_container.save_easing_state ();
515+
windows_container.set_easing_duration (duration);
516+
windows_container.set_easing_mode (Clutter.AnimationMode.EASE_IN_CUBIC);
517+
windows_container.set_pivot_point ((click_x - abs_x) / windows_container.width, (click_y - abs_y) / windows_container.height);
518+
windows_container.set_scale (scale, scale);
519+
windows_container.opacity = 0;
520+
windows_container.restore_easing_state ();
456521

457522
request_reposition ();
458523

@@ -567,23 +632,23 @@ public class Gala.WindowClone : ActorTarget, RootTarget {
567632
prev_parent.add_child (this); // Add above so that it is above while it animates back to its place
568633
restore_easing_state ();
569634

570-
clone.set_pivot_point (0.0f, 0.0f);
571-
clone.save_easing_state ();
572-
clone.set_easing_duration (duration);
573-
clone.set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD);
574-
clone.set_scale (1, 1);
575-
clone.opacity = 255;
576-
clone.restore_easing_state ();
635+
windows_container.set_pivot_point (0.0f, 0.0f);
636+
windows_container.save_easing_state ();
637+
windows_container.set_easing_duration (duration);
638+
windows_container.set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD);
639+
windows_container.set_scale (1, 1);
640+
windows_container.opacity = 255;
641+
windows_container.restore_easing_state ();
577642

578643
request_reposition ();
579644

580645
wm.get_display ().set_cursor (Meta.Cursor.DEFAULT);
581646

582647
if (duration > 0) {
583648
ulong handler = 0;
584-
handler = clone.transitions_completed.connect (() => {
649+
handler = windows_container.transitions_completed.connect (() => {
585650
prev_parent.set_child_at_index (this, prev_index); // Set the correct index so that correct stacking order is kept
586-
clone.disconnect (handler);
651+
windows_container.disconnect (handler);
587652
});
588653
} else {
589654
prev_parent.set_child_at_index (this, prev_index); // Set the correct index so that correct stacking order is kept

src/Widgets/MultitaskingView/WindowCloneContainer.vala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public class Gala.WindowCloneContainer : ActorTarget {
4545
private void _add_child (Meta.WindowActor window_actor) {
4646
unowned var window = window_actor.meta_window;
4747

48-
if (window.window_type != NORMAL) {
48+
if (window.window_type != NORMAL || window.skip_taskbar || window.find_root_ancestor () != window) {
4949
return;
5050
}
5151

0 commit comments

Comments
 (0)