@@ -24,6 +24,90 @@ static struct wlr_ext_workspace_handle_v1 *find_workspace_by_name(const char *na
2424 return NULL ;
2525}
2626
27+ static struct wlr_box window_target_rect (node_t * n ) {
28+ if (n && n -> client && n -> client -> state == STATE_FLOATING )
29+ return n -> client -> floating_rectangle ;
30+ return n ? n -> client -> tiled_rectangle : (struct wlr_box ){
31+ 0 ,
32+ 0 ,
33+ 0 ,
34+ 0
35+ };
36+ }
37+
38+ typedef struct {
39+ desktop_t * desk ;
40+ node_t * tree_cursor ;
41+ struct toplevel_t * tl_cursor ;
42+ struct xwayland_toplevel_t * xw_cursor ;
43+ } desktop_window_iter_t ;
44+
45+ static bool node_is_outside_tree (node_t * n , desktop_t * d ) {
46+ for (node_t * p = n ; p ; p = p -> parent )
47+ if (p == d -> root )
48+ return false;
49+ return true;
50+ }
51+
52+ static bool desktop_window_iter_advance (desktop_window_iter_t * it , node_t * * out_node ,
53+ struct wlr_scene_tree * * out_tree ) {
54+ if (!it )
55+ return false;
56+
57+ while (true) {
58+ if (it -> tree_cursor ) {
59+ node_t * n = it -> tree_cursor ;
60+ it -> tree_cursor = it -> desk -> root ? next_leaf (n , it -> desk -> root ) : NULL ;
61+ if (n && n -> client ) {
62+ struct wlr_scene_tree * tree = client_get_scene_tree (n -> client );
63+ if (tree ) {
64+ * out_node = n ;
65+ * out_tree = tree ;
66+ return true;
67+ }
68+ }
69+ continue ;
70+ }
71+
72+ if (it -> tl_cursor ) {
73+ struct toplevel_t * tl = it -> tl_cursor ;
74+ it -> tl_cursor = (tl -> link .next == & server .toplevels ) ? NULL : wl_container_of (tl -> link .next , tl ,
75+ link );
76+ if (tl -> mapped && tl -> scene_tree && tl -> node && tl -> node -> client &&
77+ tl -> node -> desktop == it -> desk && node_is_outside_tree (tl -> node , it -> desk )) {
78+ * out_node = tl -> node ;
79+ * out_tree = tl -> scene_tree ;
80+ return true;
81+ }
82+ continue ;
83+ }
84+
85+ if (it -> xw_cursor ) {
86+ struct xwayland_toplevel_t * xw = it -> xw_cursor ;
87+ it -> xw_cursor = (xw -> link .next == & server .xwayland .views ) ? NULL : wl_container_of (xw -> link .next ,
88+ xw , link );
89+ if (xw -> mapped && xw -> scene_tree && xw -> node && xw -> node -> client &&
90+ xw -> node -> desktop == it -> desk && node_is_outside_tree (xw -> node , it -> desk )) {
91+ * out_node = xw -> node ;
92+ * out_tree = xw -> scene_tree ;
93+ return true;
94+ }
95+ continue ;
96+ }
97+
98+ return false;
99+ }
100+ }
101+
102+ static void desktop_window_iter_init (desktop_window_iter_t * it , desktop_t * d ) {
103+ memset (it , 0 , sizeof (* it ));
104+ it -> desk = d ;
105+ if (d && d -> root )
106+ it -> tree_cursor = first_extrema (d -> root );
107+ it -> tl_cursor = wl_container_of (server .toplevels .next , (struct toplevel_t * )0 , link );
108+ it -> xw_cursor = wl_container_of (server .xwayland .views .next , (struct xwayland_toplevel_t * )0 , link );
109+ }
110+
27111struct desktop_t * find_desktop_by_name (const char * name ) {
28112 if (!name || name [0 ] == '\0' )
29113 return NULL ;
@@ -273,28 +357,27 @@ static void workspace_switch_animate(output_t *output, desktop_t *old_desk, desk
273357 }
274358
275359 // create slide-out animations for old desktop windows
276- if (old_desk && old_desk -> root ) {
277- node_t * n = first_extrema (old_desk -> root );
278- while (n ) {
279- if (n -> client ) {
280- struct wlr_scene_tree * tree = client_get_scene_tree (n -> client );
281- if (tree && tree -> node .enabled ) {
282- struct wlr_box from = {
283- tree -> node .x ,
284- tree -> node .y ,
285- 0 ,
286- 0
287- };
288- struct wlr_box to = {
289- from .x + num_steps * dx ,
290- from .y + num_steps * dy ,
291- 0 ,
292- 0
293- };
294- animation_start_workspace_slide (output , n , tree , from , to , true);
295- }
296- }
297- n = next_leaf (n , old_desk -> root );
360+ {
361+ desktop_window_iter_t it ;
362+ desktop_window_iter_init (& it , old_desk );
363+ node_t * n ;
364+ struct wlr_scene_tree * tree ;
365+ while (desktop_window_iter_advance (& it , & n , & tree )) {
366+ if (!tree || !tree -> node .enabled )
367+ continue ;
368+ struct wlr_box from = {
369+ tree -> node .x ,
370+ tree -> node .y ,
371+ 0 ,
372+ 0
373+ };
374+ struct wlr_box to = {
375+ from .x + num_steps * dx ,
376+ from .y + num_steps * dy ,
377+ 0 ,
378+ 0
379+ };
380+ animation_start_workspace_slide (output , n , tree , from , to , true);
298381 }
299382 }
300383
@@ -306,69 +389,64 @@ static void workspace_switch_animate(output_t *output, desktop_t *old_desk, desk
306389 update_all_toplevels_visibility (output , new_desk );
307390
308391 // re-enable old desktop windows for slide-out animation
309- if (old_desk && old_desk -> root ) {
310- node_t * n = first_extrema (old_desk -> root );
311- while (n ) {
312- if (n -> client ) {
313- struct wlr_scene_tree * tree = client_get_scene_tree (n -> client );
314- if (tree ) {
315- n -> client -> flags .shown = true;
316- wlr_scene_node_set_enabled (& tree -> node , true);
317- }
318- }
319- n = next_leaf (n , old_desk -> root );
392+ {
393+ desktop_window_iter_t it ;
394+ desktop_window_iter_init (& it , old_desk );
395+ node_t * n ;
396+ struct wlr_scene_tree * tree ;
397+ while (desktop_window_iter_advance (& it , & n , & tree )) {
398+ if (!tree )
399+ continue ;
400+ n -> client -> flags .shown = true;
401+ wlr_scene_node_set_enabled (& tree -> node , true);
320402 }
321403 }
322404
323405 // enable and animate intermediate desktop windows (between old and new)
324406 int k = 1 ;
325407 desktop_t * intermediate = forward ? old_desk -> prev : old_desk -> next ;
326408 while (intermediate && intermediate != new_desk ) {
327- if (intermediate -> root ) {
328- arrange (output , intermediate , true);
329- node_t * n = first_extrema (intermediate -> root );
330- while (n ) {
331- if (n -> client ) {
332- struct wlr_scene_tree * tree = client_get_scene_tree (n -> client );
333- if (tree ) {
334- n -> client -> flags .shown = true;
335- wlr_scene_node_set_enabled (& tree -> node , true);
336- struct wlr_box target = n -> client -> tiled_rectangle ;
337- struct wlr_box from = {
338- target .x - k * dx ,
339- target .y - k * dy ,
340- 0 ,
341- 0
342- };
343- struct wlr_box to = {
344- target .x + (num_steps - k ) * dx ,
345- target .y + (num_steps - k ) * dy ,
346- 0 ,
347- 0
348- };
349- wlr_scene_node_set_position (& tree -> node , from .x , from .y );
350- animation_start_workspace_slide (output , n , tree , from , to , true);
351- }
352- }
353- n = next_leaf (n , intermediate -> root );
354- }
409+ arrange (output , intermediate , true);
410+ desktop_window_iter_t it ;
411+ desktop_window_iter_init (& it , intermediate );
412+ node_t * n ;
413+ struct wlr_scene_tree * tree ;
414+ while (desktop_window_iter_advance (& it , & n , & tree )) {
415+ if (!tree )
416+ continue ;
417+ n -> client -> flags .shown = true;
418+ wlr_scene_node_set_enabled (& tree -> node , true);
419+ struct wlr_box target = window_target_rect (n );
420+ struct wlr_box from = {
421+ target .x - k * dx ,
422+ target .y - k * dy ,
423+ 0 ,
424+ 0
425+ };
426+ struct wlr_box to = {
427+ target .x + (num_steps - k ) * dx ,
428+ target .y + (num_steps - k ) * dy ,
429+ 0 ,
430+ 0
431+ };
432+ wlr_scene_node_set_position (& tree -> node , from .x , from .y );
433+ animation_start_workspace_slide (output , n , tree , from , to , true);
355434 }
356435 k ++ ;
357436 intermediate = forward ? intermediate -> prev : intermediate -> next ;
358437 }
359438
360- if (new_desk && new_desk -> root ) {
361- node_t * n = first_extrema (new_desk -> root );
362- while (n ) {
363- if (n -> client ) {
364- struct wlr_scene_tree * tree = client_get_scene_tree (n -> client );
365- if (tree ) {
366- wlr_scene_node_set_enabled (& tree -> node , true);
367- wlr_scene_node_set_position (& tree -> node , tree -> node .x - num_steps * dx ,
368- tree -> node .y - num_steps * dy );
369- }
370- }
371- n = next_leaf (n , new_desk -> root );
439+ {
440+ desktop_window_iter_t it ;
441+ desktop_window_iter_init (& it , new_desk );
442+ node_t * n ;
443+ struct wlr_scene_tree * tree ;
444+ while (desktop_window_iter_advance (& it , & n , & tree )) {
445+ if (!tree )
446+ continue ;
447+ wlr_scene_node_set_enabled (& tree -> node , true);
448+ wlr_scene_node_set_position (& tree -> node , tree -> node .x - num_steps * dx ,
449+ tree -> node .y - num_steps * dy );
372450 }
373451 }
374452
@@ -380,24 +458,23 @@ static void workspace_switch_animate(output_t *output, desktop_t *old_desk, desk
380458 }
381459
382460 // override transaction's animation for new windows
383- if (new_desk && new_desk -> root ) {
384- node_t * n = first_extrema (new_desk -> root );
385- while (n ) {
386- if (n -> client ) {
387- struct wlr_scene_tree * tree = client_get_scene_tree (n -> client );
388- if (tree ) {
389- struct wlr_box target = n -> client -> tiled_rectangle ;
390- struct wlr_box from = {
391- target .x - num_steps * dx ,
392- target .y - num_steps * dy ,
393- 0 ,
394- 0
395- };
396- wlr_scene_node_set_position (& tree -> node , from .x , from .y );
397- animation_start_workspace_slide (output , n , tree , from , target , false);
398- }
399- }
400- n = next_leaf (n , new_desk -> root );
461+ {
462+ desktop_window_iter_t it ;
463+ desktop_window_iter_init (& it , new_desk );
464+ node_t * n ;
465+ struct wlr_scene_tree * tree ;
466+ while (desktop_window_iter_advance (& it , & n , & tree )) {
467+ if (!tree )
468+ continue ;
469+ struct wlr_box target = window_target_rect (n );
470+ struct wlr_box from = {
471+ target .x - num_steps * dx ,
472+ target .y - num_steps * dy ,
473+ 0 ,
474+ 0
475+ };
476+ wlr_scene_node_set_position (& tree -> node , from .x , from .y );
477+ animation_start_workspace_slide (output , n , tree , from , target , false);
401478 }
402479 }
403480
0 commit comments