All of the above answers are great, unfortunately these solutions do not work well in combination with QuickFix or LocationList windows (I ran in this problem while trying to get the Ale error message buffer to work with this).
Solution
Therefore I added an extra line of code to close all these windows before doing the swap.
exe ':windo if &buftype == "quickfix" || &buftype == "locationlist" | lclose | endif'
The total code looking like;
" Making swapping windows easy
function! SwapWindowBuffers()
exe ':windo if &buftype == "quickfix" || &buftype == "locationlist" | lclose | endif'
if !exists("g:markedWinNum")
" set window marked for swap
let g:markedWinNum = winnr()
:echo "window marked for swap"
else
" mark destination
let curNum = winnr()
let curBuf = bufnr( "%" )
if g:markedWinNum == curNum
:echo "window unmarked for swap"
else
exe g:markedWinNum . "wincmd w"
" switch to source and shuffle dest->source
let markedBuf = bufnr( "%" )
" hide and open so that we aren't prompted and keep history
exe 'hide buf' curBuf
" switch to dest and shuffle source->dest
exe curNum . "wincmd w"
" hide and open so that we aren't prompted and keep history
exe 'hide buf' markedBuf
:echo "windows swapped"
endif
" unset window marked for swap
unlet g:markedWinNum
endif
endfunction
nmap <silent> <leader>mw :call SwapWindowBuffers()<CR>
Credits for the swap function to Brandon Orther
Why it is needed
The reason the swap functions don't work properly without removing all the QuickFix (QF) and LocationList(LL) windows first is because if the parent of the QF/LL buffer the get's hidden (and nowhere shown in a window), the QF/LL window coupled to it is removed. This isn't a problem in itself but when the window hides all the window numbers are reassigned and the swap is messed up since the saved number of the first marked window is does (potentially) not exist any more.
To put this inperspective:
First window mark
____________________
| one | -> winnr = 1 marked first g:markedWinNum=1
| | -> bufnr = 1
|__________________|
| two (QF window | -> winnr = 2
| coupled to one |
|__________________|
| three | -> winnr = 3
| | -> bufnr = 2
|__________________|
Second window mark
____________________
| one | -> winnr = 1 g:markedWinNum=1
| | -> bufnr = 1
|__________________|
| two (QF window | -> winnr = 2
| coupled to one) |
|__________________|
| three | -> winnr = 3 marked second curNum=3
| | -> bufnr = 2 curBuf=2
|__________________|
First buffer switch, window one is filled with the buffer of window three. Thus the QF window is removed since it has no parent window any more. This rearranges the windows numbers. Note that curNum (the number of the secondly selected window) is pointing to a window that does not exist any more.
____________________
| three | -> winnr = 1 g:markedWinNum=1
| | -> bufnr = 2
|__________________|
| three | -> winnr = 2 curNum=3
| | -> bufnr = 2 curBuf=2
|__________________|
So when switching the second buffer, it tries to select the curNum window, which does not exist any more. So it creates it and switches the buffer, resulting in one unwanted window to be open still.
____________________
| three | -> winnr = 1 g:markedWinNum=1
| | -> bufnr = 2
|__________________|
| three | -> winnr = 2
| | -> bufnr = 2
|__________________|
| one | -> winnr = 3 curNum=3
| | -> bufnr = 1 curBuf=2
|__________________|