1010public class Gala.WindowCloneContainer : ActorTarget {
1111 public signal void window_selected (Meta .Window window );
1212 public signal void requested_close ();
13- public signal void last_window_closed ();
1413
1514 public int padding_top { get ; set ; default = 12 ; }
1615 public int padding_left { get ; set ; default = 12 ; }
1716 public int padding_right { get ; set ; default = 12 ; }
1817 public int padding_bottom { get ; set ; default = 12 ; }
1918
2019 public WindowManager wm { get ; construct; }
20+ public WindowListModel windows { get ; construct; }
2121 public float monitor_scale { get ; construct set ; }
2222 public bool overview_mode { get ; construct; }
2323
@@ -29,78 +29,54 @@ public class Gala.WindowCloneContainer : ActorTarget {
2929 */
3030 private unowned WindowClone ? current_window = null ;
3131
32- public WindowCloneContainer (WindowManager wm, float monitor_scale, bool overview_mode = false ) {
33- Object (wm: wm, monitor_scale: monitor_scale, overview_mode: overview_mode);
32+ public WindowCloneContainer (WindowManager wm, WindowListModel windows, float monitor_scale, bool overview_mode = false ) {
33+ Object (wm: wm, windows : windows, monitor_scale: monitor_scale, overview_mode: overview_mode);
3434 }
3535
36- /**
37- * Create a WindowClone for a Meta.Window and add it to the group
38- *
39- * @param window The window for which to create the WindowClone for
40- */
41- public void add_window (Meta . Window window) {
42- var windows = new List<Meta . Window > ();
43- windows. append (window);
44- foreach (unowned var clone in (GLib . List<weak WindowClone > ) get_children ()) {
45- windows. append (clone. window);
46- }
47-
48- var new_window = new WindowClone (wm, window, monitor_scale, overview_mode);
49- new_window. selected. connect ((_new_window) = > window_selected (_new_window. window));
50- new_window. request_reposition. connect (() = > reflow (false ));
51- new_window. destroy. connect ((_new_window) = > {
52- // make sure to release reference if the window is selected
53- if (_new_window == current_window) {
54- select_next_window (Meta . MotionDirection . RIGHT , false );
55- }
56-
57- // if window is still selected, reset the selection
58- if (_new_window == current_window) {
59- current_window = null ;
60- }
36+ construct {
37+ on_items_changed (0 , 0 , windows. get_n_items ());
38+ windows. items_changed. connect (on_items_changed);
39+ }
6140
62- reflow (false );
63- });
64- bind_property (" monitor-scale" , new_window, " monitor-scale" );
41+ private void on_items_changed (uint position, uint removed, uint added) {
42+ // Used to make sure we only construct new window clones for windows that are really new
43+ // and not when only the position changed (e.g. when sorted)
44+ var to_remove = new HashTable<Meta . Window , WindowClone > (null , null );
6545
66- unowned Meta . Window ? target = null ;
67- foreach (unowned var w in sort_windows (windows)) {
68- if (w != window) {
69- target = w;
70- continue ;
71- }
72- break ;
46+ for (uint i = 0 ; i < removed; i++ ) {
47+ var window_clone = (WindowClone ) get_child_at_index ((int ) position);
48+ to_remove[window_clone. window] = window_clone;
49+ remove_child (window_clone);
7350 }
7451
75- // top most or no other children
76- if (target == null ) {
77- add_child (new_window);
78- }
52+ for (int i = (int ) position; i < position + added; i++ ) {
53+ var window = (Meta . Window ) windows. get_item (i);
7954
80- foreach (unowned var clone in (GLib . List<weak WindowClone > ) get_children ()) {
81- if (target == clone. window) {
82- insert_child_below (new_window, clone);
83- break ;
55+ WindowClone ? clone = to_remove. take (window);
56+
57+ if (clone == null ) {
58+ clone = new WindowClone (wm, window, monitor_scale, overview_mode);
59+ clone. selected. connect ((_clone) = > window_selected (_clone. window));
60+ clone. request_reposition. connect (() = > reflow (false ));
61+ bind_property (" monitor-scale" , clone, " monitor-scale" );
8462 }
63+
64+ insert_child_at_index (clone, i);
8565 }
8666
87- reflow (false );
88- }
67+ // Make sure we release the reference on the window
68+ if (current_window != null && current_window. window in to_remove) {
69+ select_next_window (RIGHT , false );
8970
90- /**
91- * Find and remove the WindowClone for a MetaWindow
92- */
93- public void remove_window (Meta . Window window) {
94- foreach (unowned var clone in (GLib . List<weak WindowClone > ) get_children ()) {
95- if (clone. window == window) {
96- remove_child (clone);
97- reflow (false );
98- break ;
71+ // There is no next window so select nothing
72+ if (current_window. window in to_remove) {
73+ current_window = null ;
9974 }
10075 }
10176
102- if (get_n_children () == 0 ) {
103- last_window_closed ();
77+ // Don't reflow if only the sorting changed
78+ if (to_remove. size () > 0 || added != removed) {
79+ reflow (false );
10480 }
10581 }
10682
@@ -120,10 +96,10 @@ public class Gala.WindowCloneContainer : ActorTarget {
12096 }
12197 }
12298
123- restack_windows ();
99+ windows . sort ();
124100 reflow (true );
125101 } else if (action == MULTITASKING_VIEW ) { // If we are open we only want to restack when we close
126- restack_windows ();
102+ windows . sort ();
127103 }
128104 }
129105
@@ -142,34 +118,6 @@ public class Gala.WindowCloneContainer : ActorTarget {
142118 }
143119 }
144120
145- /**
146- * Sort the windows z-order by their actual stacking to make intersections
147- * during animations correct.
148- */
149- private void restack_windows () {
150- var children = (GLib . List<weak WindowClone > ) get_children ();
151-
152- var windows = new GLib .List<Meta . Window > ();
153- foreach (unowned var clone in children) {
154- windows. prepend (clone. window);
155- }
156-
157- var windows_ordered = sort_windows (windows);
158- windows_ordered. reverse ();
159-
160- var i = 0 ;
161- foreach (unowned var window in windows_ordered) {
162- foreach (unowned var clone in children) {
163- if (clone. window == window) {
164- set_child_at_index (clone, i);
165- children. remove (clone);
166- i++ ;
167- break ;
168- }
169- }
170- }
171- }
172-
173121 /**
174122 * Recalculate the tiling positions of the windows and animate them to the resulting spots.
175123 */
@@ -350,35 +298,6 @@ public class Gala.WindowCloneContainer : ActorTarget {
350298 current_window = closest;
351299 }
352300
353- /**
354- * Sorts the windows by stacking order so that the window on active workspaces come first.
355- */
356- private GLib . SList<weak Meta . Window > sort_windows (GLib . List<Meta . Window > windows) {
357- unowned var display = wm. get_display ();
358-
359- var windows_on_active_workspace = new GLib .SList<Meta . Window > ();
360- var windows_on_other_workspaces = new GLib .SList<Meta . Window > ();
361- unowned var active_workspace = display. get_workspace_manager (). get_active_workspace ();
362- foreach (unowned var window in windows) {
363- if (window. get_workspace () == active_workspace) {
364- windows_on_active_workspace. append (window);
365- } else {
366- windows_on_other_workspaces. append (window);
367- }
368- }
369-
370- var sorted_windows = new GLib .SList<weak Meta . Window > ();
371- var windows_on_active_workspace_sorted = display. sort_windows_by_stacking (windows_on_active_workspace);
372- windows_on_active_workspace_sorted. reverse ();
373- var windows_on_other_workspaces_sorted = display. sort_windows_by_stacking (windows_on_other_workspaces);
374- windows_on_other_workspaces_sorted. reverse ();
375- sorted_windows. concat ((owned ) windows_on_active_workspace_sorted);
376- sorted_windows. concat ((owned ) windows_on_other_workspaces_sorted);
377-
378- return sorted_windows;
379- }
380-
381-
382301 // Code ported from KWin present windows effect
383302 // https://projects.kde.org/projects/kde/kde-workspace/repository/revisions/master/entry/kwin/effects/presentwindows/presentwindows.cpp
384303
0 commit comments