Index: src/window.cpp =================================================================== --- src/window.cpp (revision 24916) +++ src/window.cpp (working copy) @@ -1898,10 +1898,13 @@ static EventState HandleWindowDragging() if (_settings_client.gui.window_snap_radius != 0) { const Window *v; + const Window *wt; int hsnap = _settings_client.gui.window_snap_radius; int vsnap = _settings_client.gui.window_snap_radius; int delta; + int a; // Top border of gap + int b; // Bottom border of gap FOR_ALL_WINDOWS_FROM_BACK(v) { if (v == w) continue; // Don't snap at yourself @@ -1910,31 +1913,144 @@ static EventState HandleWindowDragging() /* Your left border <-> other right border */ delta = abs(v->left + v->width - x); if (delta <= hsnap) { - nx = v->left + v->width; - hsnap = delta; + a = w->top; + b = w->top + w->height; + if (v->top > a) a = v->top; + if (v->top + v->height < b) b = v->top + v->height; + FOR_ALL_WINDOWS_FROM_BACK_FROM(wt, v->z_front){ + if (wt == w) break; + if ((wt->left < v->left + v->width) && (wt->left + wt->width > v->left + v->width)){ + if (wt->top > b){continue;} + if (wt->top > a && wt->top + wt->height < b){continue;} + if (wt->top < a && wt->top + wt->height > b){a = 0; b = 0; break;} + if (wt->top > a && wt->top + wt->height >= b){b = wt->top; continue;} + if (wt->top <= a && wt->top + wt->height > a){a = wt->top + wt->height; continue;} + } + } + wt = NULL; + FOR_ALL_WINDOWS_FROM_FRONT_FROM(wt, w->z_front){ + if (wt == v) break; + if ((wt->left < v->left + v->width) && (wt->left + wt->width > v->left + v->width)){ + if (wt->top > b){continue;} + if (wt->top > a && wt->top + wt->height < b){continue;} + if (wt->top < a && wt->top + wt->height > b){a = 0; b = 0; break;} + if (wt->top > a && wt->top + wt->height >= b){b = wt->top; continue;} + if (wt->top <= a && wt->top + wt->height > a){a = wt->top + wt->height; continue;} + } + } + if (a >= b) { + nx = x; + } else { + nx = v->left + v->width; + hsnap = delta; + } } - /* Your right border <-> other left border */ delta = abs(v->left - x - w->width); if (delta <= hsnap) { - nx = v->left - w->width; - hsnap = delta; + a = w->top; + b = w->top + w->height; + if (v->top > a) a = v->top; + if (v->top + v->height < b) b = v->top + v->height; + FOR_ALL_WINDOWS_FROM_BACK_FROM(wt, v->z_front){ + if (wt == w) break; + if ((wt->left < v->left) && (wt->left + wt->width > v->left)){ + if (wt->top > b){continue;} + if (wt->top > a && wt->top + wt->height < b){continue;} + if (wt->top < a && wt->top + wt->height > b){a = 0; b = 0; break;} + if (wt->top > a && wt->top + wt->height >= b){b = wt->top; continue;} + if (wt->top <= a && wt->top + wt->height > a){a = wt->top + wt->height; continue;} + } + } + wt = NULL; + FOR_ALL_WINDOWS_FROM_FRONT_FROM(wt, w->z_front){ + if (wt == v) break; + if ((wt->left < v->left + v->width) && (wt->left + wt->width > v->left + v->width)){ + if (wt->top > b){continue;} + if (wt->top > a && wt->top + wt->height < b){continue;} + if (wt->top < a && wt->top + wt->height > b){a = 0; b = 0; break;} + if (wt->top > a && wt->top + wt->height >= b){b = wt->top; continue;} + if (wt->top <= a && wt->top + wt->height > a){a = wt->top + wt->height; continue;} + } + } + if (a >= b) { + nx = x; + } else { + nx = v->left - w->width; + hsnap = delta; + } } } - if (w->top + w->height >= v->top && w->top <= v->top + v->height) { - /* Your left border <-> other left border */ + /* Your left border <-> other left border */ delta = abs(v->left - x); if (delta <= hsnap) { - nx = v->left; - hsnap = delta; + a = w->top; + b = w->top + w->height; + if (v->top > a) a = v->top; + if (v->top + v->height < b) b = v->top + v->height; + FOR_ALL_WINDOWS_FROM_BACK_FROM(wt, v->z_front){ + if (wt == w) break; + if ((wt->left < v->left) && (wt->left + wt->width > v->left)){ + if (wt->top > b){continue;} + if (wt->top > a && wt->top + wt->height < b){continue;} + if (wt->top < a && wt->top + wt->height > b){a = 0; b = 0; break;} + if (wt->top > a && wt->top + wt->height >= b){b = wt->top; continue;} + if (wt->top <= a && wt->top + wt->height > a){a = wt->top + wt->height; continue;} + } + } + wt = NULL; + FOR_ALL_WINDOWS_FROM_FRONT_FROM(wt, w->z_front){ + if (wt == v) break; + if ((wt->left < v->left + v->width) && (wt->left + wt->width > v->left + v->width)){ + if (wt->top > b){continue;} + if (wt->top > a && wt->top + wt->height < b){continue;} + if (wt->top < a && wt->top + wt->height > b){a = 0; b = 0; break;} + if (wt->top > a && wt->top + wt->height >= b){b = wt->top; continue;} + if (wt->top <= a && wt->top + wt->height > a){a = wt->top + wt->height; continue;} + } + } + if (a >= b) { + nx = x; + } else { + nx = v->left; + hsnap = delta; + } } - /* Your right border <-> other right border */ delta = abs(v->left + v->width - x - w->width); if (delta <= hsnap) { - nx = v->left + v->width - w->width; - hsnap = delta; + a = w->top; + b = w->top + w->height; + if (v->top > a) a = v->top; + if (v->top + v->height < b) b = v->top + v->height; + FOR_ALL_WINDOWS_FROM_BACK_FROM(wt, v->z_front){ + if (wt == w) break; + if ((wt->left < v->left + v->width) && (wt->left + wt->width > v->left + v->width)){ + if (wt->top > b){continue;} + if (wt->top > a && wt->top + wt->height < b){continue;} + if (wt->top < a && wt->top + wt->height > b){a = 0; b = 0; break;} + if (wt->top > a && wt->top + wt->height >= b){b = wt->top; continue;} + if (wt->top <= a && wt->top + wt->height > a){a = wt->top + wt->height; continue;} + } + } + wt = NULL; + FOR_ALL_WINDOWS_FROM_FRONT_FROM(wt, w->z_front){ + if (wt == v) break; + if ((wt->left < v->left + v->width) && (wt->left + wt->width > v->left + v->width)){ + if (wt->top > b){continue;} + if (wt->top > a && wt->top + wt->height < b){continue;} + if (wt->top < a && wt->top + wt->height > b){a = 0; b = 0; break;} + if (wt->top > a && wt->top + wt->height >= b){b = wt->top; continue;} + if (wt->top <= a && wt->top + wt->height > a){a = wt->top + wt->height; continue;} + } + } + if (a >= b) { + nx = x; + } else { + nx = v->left + v->width - w->width; + hsnap = delta; + } } } @@ -1942,15 +2058,72 @@ static EventState HandleWindowDragging() /* Your top border <-> other bottom border */ delta = abs(v->top + v->height - y); if (delta <= vsnap) { - ny = v->top + v->height; - vsnap = delta; + a = w->left; + b = w->left + w->width; + if (v->left > a) a = v->left; + if (v->left + v->width < b) b = v->left + v->width; + FOR_ALL_WINDOWS_FROM_BACK_FROM(wt, v->z_front){ + if (wt == w) break; + if ((wt->top < v->top + v->height) && (wt->top + wt->height > v->top + v->height)){ + if (wt->left > b){continue;} + if (wt->left > a && wt->left + wt->width < b){continue;} + if (wt->left < a && wt->left + wt->width > b){a = 0; b = 0; break;} + if (wt->left > a && wt->left + wt->width >= b){b = wt->left; continue;} + if (wt->left <= a && wt->left + wt->width > a){a = wt->left + wt->width; continue;} + } + } + wt = NULL; + FOR_ALL_WINDOWS_FROM_FRONT_FROM(wt, w->z_front){ + if (wt == v) break; + if ((wt->top < v->top + v->height) && (wt->top + wt->height > v->top + v->height)){ + if (wt->left > b){continue;} + if (wt->left > a && wt->left + wt->width < b){continue;} + if (wt->left < a && wt->left + wt->width > b){a = 0; b = 0; break;} + if (wt->left > a && wt->left + wt->width >= b){b = wt->left; continue;} + if (wt->left <= a && wt->left + wt->width > a){a = wt->left + wt->width; continue;} + } + } + if (a >= b) { + ny = y; + } else { + ny = v->top + v->height; + vsnap = delta; + } } - /* Your bottom border <-> other top border */ delta = abs(v->top - y - w->height); if (delta <= vsnap) { - ny = v->top - w->height; - vsnap = delta; + a = w->left; + b = w->left + w->width; + if (v->left > a) a = v->left; + if (v->left + v->width < b) b = v->left + v->width; + FOR_ALL_WINDOWS_FROM_BACK_FROM(wt, v->z_front){ + if (wt == w) break; + if ((wt->top < v->top) && (wt->top + wt->height > v->top)){ + if (wt->left > b){continue;} + if (wt->left > a && wt->left + wt->width < b){continue;} + if (wt->left < a && wt->left + wt->width > b){a = 0; b = 0; break;} + if (wt->left > a && wt->left + wt->width >= b){b = wt->left; continue;} + if (wt->left <= a && wt->left + wt->width > a){a = wt->left + wt->width; continue;} + } + } + wt = NULL; + FOR_ALL_WINDOWS_FROM_FRONT_FROM(wt, w->z_front){ + if (wt == v) break; + if ((wt->top < v->top + v->height) && (wt->top + wt->height > v->top + v->height)){ + if (wt->left > b){continue;} + if (wt->left > a && wt->left + wt->width < b){continue;} + if (wt->left < a && wt->left + wt->width > b){a = 0; b = 0; break;} + if (wt->left > a && wt->left + wt->width >= b){b = wt->left; continue;} + if (wt->left <= a && wt->left + wt->width > a){a = wt->left + wt->width; continue;} + } + } + if (a >= b) { + ny = y; + } else { + ny = v->top - w->height; + vsnap = delta; + } } } @@ -1958,15 +2131,73 @@ static EventState HandleWindowDragging() /* Your top border <-> other top border */ delta = abs(v->top - y); if (delta <= vsnap) { - ny = v->top; - vsnap = delta; + a = w->left; + b = w->left + w->width; + if (v->left > a) a = v->left; + if (v->left + v->width < b) b = v->left + v->width; + FOR_ALL_WINDOWS_FROM_BACK_FROM(wt, v->z_front){ + if (wt == w) break; + if ((wt->top < v->top) && (wt->top + wt->height > v->top)){ + if (wt->left > b){continue;} + if (wt->left > a && wt->left + wt->width < b){continue;} + if (wt->left < a && wt->left + wt->width > b){a = 0; b = 0; break;} + if (wt->left > a && wt->left + wt->width >= b){b = wt->left; continue;} + if (wt->left <= a && wt->left + wt->width > a){a = wt->left + wt->width; continue;} + } + } + wt = NULL; + FOR_ALL_WINDOWS_FROM_FRONT_FROM(wt, w->z_front){ + if (wt == v) break; + if ((wt->top < v->top + v->height) && (wt->top + wt->height > v->top + v->height)){ + if (wt->left > b){continue;} + if (wt->left > a && wt->left + wt->width < b){continue;} + if (wt->left < a && wt->left + wt->width > b){a = 0; b = 0; break;} + if (wt->left > a && wt->left + wt->width >= b){b = wt->left; continue;} + if (wt->left <= a && wt->left + wt->width > a){a = wt->left + wt->width; continue;} + } + } + if (a >= b) { + ny = y; + } else { + ny = v->top; + vsnap = delta; + } } /* Your bottom border <-> other bottom border */ delta = abs(v->top + v->height - y - w->height); if (delta <= vsnap) { - ny = v->top + v->height - w->height; - vsnap = delta; + a = w->left; + b = w->left + w->width; + if (v->left > a) a = v->left; + if (v->left + v->width < b) b = v->left + v->width; + FOR_ALL_WINDOWS_FROM_BACK_FROM(wt, v->z_front){ + if (wt == w) break; + if ((wt->top < v->top + v->height) && (wt->top + wt->height > v->top + v->height)){ + if (wt->left > b){continue;} + if (wt->left > a && wt->left + wt->width < b){continue;} + if (wt->left < a && wt->left + wt->width > b){a = 0; b = 0; break;} + if (wt->left > a && wt->left + wt->width >= b){b = wt->left; continue;} + if (wt->left <= a && wt->left + wt->width > a){a = wt->left + wt->width; continue;} + } + } + wt = NULL; + FOR_ALL_WINDOWS_FROM_FRONT_FROM(wt, w->z_front){ + if (wt == v) break; + if ((wt->top < v->top + v->height) && (wt->top + wt->height > v->top + v->height)){ + if (wt->left > b){continue;} + if (wt->left > a && wt->left + wt->width < b){continue;} + if (wt->left < a && wt->left + wt->width > b){a = 0; b = 0; break;} + if (wt->left > a && wt->left + wt->width >= b){b = wt->left; continue;} + if (wt->left <= a && wt->left + wt->width > a){a = wt->left + wt->width; continue;} + } + } + if (a >= b) { + ny = y; + } else { + ny = v->top + v->height - w->height; + vsnap = delta; + } } } }