@@ -366,3 +366,72 @@ pub fn resize_grab(state: &mut State, button: u32) {
366366 state. schedule_render ( & output) ;
367367 }
368368}
369+
370+ pub fn swap ( state : & mut State , window : WindowElement , target : WindowElement ) {
371+ if state. pinnacle . layout_state . pending_swap {
372+ return ;
373+ }
374+
375+ if window == target {
376+ return ;
377+ }
378+
379+ let output = window. output ( & state. pinnacle ) ;
380+ let target_output = target. output ( & state. pinnacle ) ;
381+
382+ let Some ( ( output, target_output) ) = output. zip ( target_output) else {
383+ tracing:: warn!( "Can't swap windows without output" ) ;
384+ return ;
385+ } ;
386+
387+ tracing:: debug!( "Swapping window positions" ) ;
388+ state. pinnacle . layout_state . pending_swap = true ;
389+
390+ state. pinnacle . swap_window_positions ( & window, & target) ;
391+ if output != target_output {
392+ tracing:: debug!( "Swapping window outputs" ) ;
393+ window. set_tags_to_output ( & target_output) ;
394+ target. set_tags_to_output ( & output) ;
395+ }
396+
397+ // Swap floating attribute. In case of cross-output swap, this prevent window jumping back.
398+ let window_floating_x = window. with_state ( |state| state. floating_x ) ;
399+ let window_floating_y = window. with_state ( |state| state. floating_y ) ;
400+ let window_floating_size = window. with_state ( |state| state. floating_size ) ;
401+
402+ let target_floating_x = target. with_state ( |state| state. floating_x ) ;
403+ let target_floating_y = target. with_state ( |state| state. floating_y ) ;
404+ let target_floating_size = target. with_state ( |state| state. floating_size ) ;
405+
406+ target. with_state_mut ( |state| {
407+ state. floating_x = window_floating_x;
408+ state. floating_y = window_floating_y;
409+ state. floating_size = window_floating_size
410+ } ) ;
411+
412+ window. with_state_mut ( |state| {
413+ state. floating_x = target_floating_x;
414+ state. floating_y = target_floating_y;
415+ state. floating_size = target_floating_size
416+ } ) ;
417+
418+ if window. with_state ( |state| !state. layout_mode . is_tiled ( ) )
419+ || target. with_state ( |state| !state. layout_mode . is_tiled ( ) )
420+ {
421+ tracing:: debug!( "Swapping non tiled window" ) ;
422+ let window_layout_mode = window. with_state ( |state| state. layout_mode ) ;
423+ let target_layout_mode = target. with_state ( |state| state. layout_mode ) ;
424+
425+ state. update_window_layout_mode_and_layout ( & window, |layout| {
426+ layout. apply_mode ( target_layout_mode)
427+ } ) ;
428+ state. update_window_layout_mode_and_layout ( & target, |layout| {
429+ layout. apply_mode ( window_layout_mode)
430+ } ) ;
431+ } else {
432+ state. pinnacle . request_layout ( & output) ;
433+ if output != target_output {
434+ state. pinnacle . request_layout ( & target_output) ;
435+ }
436+ }
437+ }
0 commit comments