diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/api/wnd/wndtrack.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/wnd/wndtrack.cpp')
-rw-r--r-- | Src/Wasabi/api/wnd/wndtrack.cpp | 945 |
1 files changed, 945 insertions, 0 deletions
diff --git a/Src/Wasabi/api/wnd/wndtrack.cpp b/Src/Wasabi/api/wnd/wndtrack.cpp new file mode 100644 index 00000000..c378550e --- /dev/null +++ b/Src/Wasabi/api/wnd/wndtrack.cpp @@ -0,0 +1,945 @@ +#include <precomp.h> +#include <bfc/ptrlist.h> +#include <api/wnd/basewnd.h> +#include <bfc/util/findopenrect.h> +#include <bfc/bfc_assert.h> +#include <api/wndmgr/resize.h> +#include <api/wnd/wndtrack.h> +#include <api/config/items/attrint.h> +#include <api/config/items/attrbool.h> +#include <bfc/wasabi_std_wnd.h> +#ifdef WASABI_COMPILE_WNDMGR +#include <api/wndmgr/snappnt.h> +#endif + +#ifdef WASABI_COMPILE_SCRIPT +#include <api/script/scriptobj.h> +#include <api/script/scriptguid.h> +#include <api/wnd/wndclass/guiobjwnd.h> // for appbar define +#endif + +#ifdef WASABI_COMPILE_WNDMGR +#include <api/wndmgr/layout.h> +#include <api/wnd/popexitcb.h> +#endif + +#ifdef WASABI_COMPILE_SYSCB +//#include <api/syscb/cbmgr.h> +#endif + +WindowTracker *windowTracker; + +WindowTracker::WindowTracker() + : coopcache(0), + coopcachewnd(NULL) +{ + wascoop = 0; + disabledock = 0; + dock_enabled = 1; +} + +WindowTracker::~WindowTracker() +{ + coopList.deleteAll(); +} + +void WindowTracker::addWindow(ifc_window *wnd) +{ + ASSERT(wnd); + desktopwnds.addItem(wnd); +} + +void WindowTracker::removeWindow(ifc_window *wnd) +{ + ASSERT(wnd); + ASSERTPR(desktopwnds.haveItem(wnd), "removewindow on invalid wnd"); + desktopwnds.removeItem(wnd); +} + +int WindowTracker::checkWindow(ifc_window *wnd) +{ + return allWnd.haveItem(wnd); +} + +ifc_window *WindowTracker::enumWindows(int n) +{ + return desktopwnds.enumItem(n); +} + +ifc_window *WindowTracker::getNextDesktopWindow(ifc_window *w, int next) +{ + ifc_window *nw = NULL; + if (w == NULL) nw = desktopwnds.getFirst(); + else + { + w = w->getDesktopParent(); + int pos = desktopwnds.searchItem(w); + if (pos == -1) nw = desktopwnds.getFirst(); + else + { + pos += next; + if (pos > desktopwnds.getNumItems() - 1) pos = 0; + if (pos == -1) pos = desktopwnds.getNumItems() - 1; + nw = desktopwnds.enumItem(pos); + } + } + if (nw == w) return w; + if (!nw->isVisible()) return getNextDesktopWindow(nw, next); + return nw; +} + +ifc_window *WindowTracker::enumAllWindows(int n) +{ + return allWnd.enumItem(n); +} + +int WindowTracker::getNumWindows() +{ + return desktopwnds.getNumItems(); +} + +int WindowTracker::getNumAllWindows() +{ + return allWnd.getNumItems(); +} + +void WindowTracker::invalidateAllWindows() +{ + for (int i = allWnd.getNumItems() - 1;i >= 0;i--) + { + ifc_window *w = allWnd[i]; + w->triggerEvent(TRIGGER_INVALIDATE); + w->invalidate(); + if (!w->isVirtual()) continue; + w->triggerEvent(TRIGGER_ONRESIZE); + } +} + +RECT WindowTracker::findOpenRect(const RECT &prev, ifc_window *exclude) +{ + POINT pp = { 0, 0 }; + //CUT if (prev != NULL) { + pp.x = prev.left; + pp.y = prev.top; + //CUT } + RECT vr; // viewport rect + Wasabi::Std::getViewport(&vr, &pp); + + // make a rect list + PtrList<RECT> list; + for (int i = 0; ; i++) + { + ifc_window *wnd = enumWindows(i); + if (wnd == NULL) break; + if (wnd == exclude) continue; + if (!wnd->isPostOnInit() && !wnd->isVisible()) continue; + RECT *r = new RECT; + wnd->getWindowRect(r); + snapAdjustWindowRect(wnd, r); + list.addItem(r); + } + + FindOpenRect fr; + RECT ret = fr.find(vr, list, prev); + list.deleteAll(); + return ret; +} + +void WindowTracker::setDockDistance(int dd) +{ + dockDist = MINMAX(dd, MIN_DOCK_DIST, MAX_DOCK_DIST); +} + +int WindowTracker::getDockDistance() +{ + if (dock_enabled) return dockDist; + return 0; +} + +void WindowTracker::setEnableDocking(int ed) +{ + dock_enabled = ed; +} + +bool WindowTracker::touches(const RECT &r2, const RECT &r1) +{ + if (r2.left == r1.right || r2.right == r1.left || r2.right == r1.right || r2.left == r1.left) + { + if (r2.bottom >= r1.top && r2.top <= r1.bottom) + return true; + } + if (r2.top == r1.bottom || r2.bottom == r1.top || r2.bottom == r1.bottom || r2.top == r1.top) + { + if (r2.right >= r1.left && r2.left <= r1.right) + return true; + } + return false; +} + +void WindowTracker::endCooperativeMove() +{ + wascoop = 1; + flushCoopWnds(); + coopWnd = NULL; + recursList.removeAll(); +} + +void WindowTracker::startCooperativeMove(ifc_window *thiswnd) +{ + coopWnd = thiswnd; + wascoop = 1; + flushCoopWnds(); + if (recursList.getNumItems() > 0) recursList.removeAll(); + addCooperative(thiswnd); + foreach_reverse(recursList) + // FG> we need to prevent windows from excessively activating our windows or focus is gonna blow up + // thiswnd->bringToFront(); +#ifdef WIN32 + SetWindowPos(recursList.getfor()->gethWnd(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); +#else + recursList.getfor()->bringToFront(); +#endif + endfor; +} + +int WindowTracker::getNumDocked() +{ + return recursList.getNumItems(); +} + +ifc_window *WindowTracker::enumDocked(int n) +{ + return recursList.enumItem(n); +} + +void WindowTracker::addCooperative(ifc_window *thiswnd) +{ + int i; + RECT r; + RECT thisr; + bool forceall = false; + + if (Std::keyModifier(STDKEY_ALT)) + { + forceall = TRUE; + } + +#ifdef WASABI_COMPILE_WNDMGR + Layout *l = static_cast<Layout *>(thiswnd->getInterface(layoutGuid)); + if (l) + { + for (int i = 0; i < l->getNumLockedLayouts(); i++) + { + ifc_window *wnd = l->enumLockedLayout(i); + addCoopWnd(wnd, 1); + addCooperative(wnd); + } + } +#endif + + if (recursList.searchItem(thiswnd) != -1) return ; + + recursList.addItem(thiswnd); + + if (Std::keyModifier(STDKEY_SHIFT)) return ; + + thiswnd->getWindowRect(&thisr); + snapAdjustWindowRect(thiswnd, &thisr); + + for (i = 0; i < desktopwnds.getNumItems(); i++) + { + ifc_window *wnd = desktopwnds.enumItem(i); + if (!wnd->isVisible()) continue; + if (hasCoopWnd(wnd)) continue; + if (wnd == thiswnd) continue; + Layout *l = (Layout*)wnd->getInterface(layoutGuid); + if (l && (l->getNoDock() +#ifdef USEAPPBAR + || l->appbar_isDocked() +#endif + )) continue; + wnd->getWindowRect(&r); + snapAdjustWindowRect(wnd, &r); + +#ifdef WASABI_COMPILE_WNDMGR + int snap = SnapPoint::match(thiswnd, NULL, wnd, KEEPSIZE, NULL, NULL, 0, 0); + if (forceall || snap || (touches(r, thisr) && !Wasabi::Std::rectIntersect(r, thisr))) + { +#else + if (forceall || (touches(r, thisr) && !Std::rectIntersect(r, thisr))) + { +#endif + addCoopWnd(wnd); + addCooperative(wnd); + } + } +} + +bool WindowTracker::autoDock(ifc_window *thishWnd, RECT *newPosition, int mask) +{ + return autoDock(thishWnd, newPosition, NULL, mask); +} + +bool WindowTracker::autoDock(ifc_window *thiswnd, RECT *z, RECT *_oldPosition, int mask) +{ + int i = 0; + RECT r = {0}; +#ifdef WASABI_COMPILE_CONFIG + extern _bool cfg_options_docking; + extern _int cfg_options_dockingdistance; + + dockDist = cfg_options_dockingdistance; + dock_enabled = cfg_options_docking; +#else +#warning check these values + dockDist = 4; + dock_enabled = 4; +#endif + +#ifdef USEAPPBAR + // Layout *_l = static_cast<Layout *>(thiswnd->getInterface(layoutGuid)); + // if (_l->appbar_isDocked()) return 0; +#endif + + RECT z_snapAdjust = {0}; + snapAdjustWindowRect(thiswnd, z, &z_snapAdjust); + RECT *oldPosition = _oldPosition; + if (oldPosition) + { + oldPosition->left += z_snapAdjust.left; + oldPosition->top += z_snapAdjust.top; + } + + if (!coopWnd) + wascoop = 0; + + disabledock = 0; + + if (Std::keyModifier(STDKEY_SHIFT)) + { + for (int i = 0;i < coopList.getNumItems();i++) + { + coopEntry *e = coopList.enumItem(i); + if (!e->locked) + { + delete e; + coopList.removeByPos(i); + coopcachewnd = NULL; + i--; + } + } + disabledock = 1; + } + + int f = 0, s = 0; + int w = z->right - z->left; + int h = z->bottom - z->top; + + POINT done = {0}; + + if (!disabledock) + { + ifc_window *wnd = NULL; + for (i = desktopwnds.getNumItems(); i > -1; i--) + { + if (i == desktopwnds.getNumItems()) + { +#ifdef USEAPPBAR + Layout *l = static_cast<Layout *>(thiswnd->getInterface(layoutGuid)); + if (l->appbar_isDocked()) continue; +#endif + Wasabi::Std::getViewport(&r, thiswnd->gethWnd()); + wnd = NULL; + } + else + { + wnd = desktopwnds.enumItem(i); + if (coopWnd != NULL && hasCoopWnd(wnd)) continue; + Layout *l = (Layout*)wnd->getInterface(layoutGuid); + if (l && (l->getNoDock() +#ifdef USEAPPBAR + || l->appbar_isDocked() +#endif + )) continue; + + if (wnd->isVisible()) + { + wnd->getWindowRect(&r); + snapAdjustWindowRect(wnd, &r); + } + else continue; + } + + if (coopWnd != NULL && coopWnd == wnd || (i >= 0 && hasCoopWnd(desktopwnds.enumItem(i)))) continue; + + if (thiswnd == wnd) continue; + + RECT oz = *z; + POINT thisdone = {0}; + +#ifdef WASABI_COMPILE_WNDMGR + if (SnapPoint::match(thiswnd, z, wnd, mask, (int *)&thisdone.x, (int *)&thisdone.y, w, h)) s++; +#endif + if (z->left > r.left - getDockDistance() && z->left < r.left + getDockDistance() && (mask & LEFT) && !thisdone.x) + { + z->left = r.left; + thisdone.x = 1; + if (mask & KEEPSIZE) z->right = r.left + w; + f++; + } + if (i != desktopwnds.getNumItems() && z->right > r.left - getDockDistance() && z->right < r.left + getDockDistance() && (mask & RIGHT) && !thisdone.x) + { + z->right = r.left; + thisdone.x = 1; + if (mask & KEEPSIZE) z->left = r.left - w; + f++; + } + if (z->top > r.top - getDockDistance() && z->top < r.top + getDockDistance() && (mask & TOP) && !thisdone.y) + { + z->top = r.top; + thisdone.y = 1; + if (mask & KEEPSIZE) z->bottom = r.top + h; + f++; + } + if (i != desktopwnds.getNumItems() && z->bottom > r.top - getDockDistance() && z->bottom < r.top + getDockDistance() && (mask & BOTTOM) && !thisdone.y) + { + z->bottom = r.top; + thisdone.y = 1; + if (mask & KEEPSIZE) z->top = r.top - h; + f++; + } + if (z->right > r.right - getDockDistance() && z->right < r.right + getDockDistance() && (mask & RIGHT) && !thisdone.x) + { + z->right = r.right; + thisdone.x = 1; + if (mask & KEEPSIZE) z->left = r.right - w; + f++; + } + if (i != desktopwnds.getNumItems() && z->left > r.right - getDockDistance() && z->left < r.right + getDockDistance() && (mask & LEFT) && !thisdone.x) + { + z->left = r.right; + thisdone.x = 1; + if (mask & KEEPSIZE) z->right = r.right + w; + f++; + } + + if (z->bottom > r.bottom - getDockDistance() && z->bottom < r.bottom + getDockDistance() && (mask & BOTTOM) && !thisdone.y) + { + z->bottom = r.bottom; + thisdone.y = 1; + if (mask & KEEPSIZE) z->top = r.bottom - h; + f++; + } + + if (i != desktopwnds.getNumItems() && z->top > r.bottom - getDockDistance() && z->top < r.bottom + getDockDistance() && (mask & TOP) && !thisdone.y) + { + z->top = r.bottom; + thisdone.y = 1; + if (mask & KEEPSIZE) z->bottom = r.bottom + h; + f++; + } + + if (((wnd != NULL && (mask & NOINTERSECT) && Wasabi::Std::rectIntersect(*z, r)) || !touches(*z, r)) && !s) + { + *z = oz; + thisdone.x = 0; + thisdone.y = 0; + } + + done.x |= thisdone.x; + done.y |= thisdone.y; + } + } + + if (coopWnd == thiswnd && oldPosition) + { + POINT s = {0}, redock = {0}; + TList<RECT> rlist; + s.x = z->left - oldPosition->left; + s.y = z->top - oldPosition->top; + for (i = 0;i < coopList.getNumItems();i++) + { + RECT r = {0}; + ifc_window *W = coopList.enumItem(i)->wnd; + if (!checkWindow(W)) { coopEntry *e = coopList.enumItem(i); delete e; coopList.removeByPos(i); i--; continue; } + if (W != (BaseWnd*) - 1) + { + W->getWindowRect(&r); + //snapAdjustWindowRect(W, &r); + } +#ifdef WIN32 + else + GetWindowRect(WASABI_API_WND->main_getRootWnd()->gethWnd(), &r); +#endif + int w = r.right - r.left, h = r.bottom - r.top; + r.left += s.x; + r.top += s.y; + r.right = r.left + w; + r.bottom = r.top + h; + RECT cr = r; + if (autoDock(W, &cr, LEFT | RIGHT | TOP | BOTTOM | NOINTERSECT | KEEPSIZE)) + { + if (redock.x == 0) redock.x = cr.left - r.left; + if (redock.y == 0) redock.y = cr.top - r.top; + } + rlist.addItem(r); + } + + if (redock.x || redock.y) + { + Wasabi::Std::offsetRect(z, redock.x, redock.y); + f++; + } +#ifdef WIN32 + HDWP hd = NULL; + if (coopList.getNumItems() > 0) hd = BeginDeferWindowPos(coopList.getNumItems()); +#endif + for (i = 0;i < coopList.getNumItems();i++) + { + RECT r = rlist.enumItem(i); + ifc_window *W = coopList.enumItem(i)->wnd; + r.left += redock.x; + r.top += redock.y; + //unsnapAdjustWindowRect(W, &r); +#ifdef WIN32 + W->notifyDeferredMove(r.left, r.top); + //if (GetWindow(W->gethWnd(), GW_OWNER)) +// SetWindowPos(W->gethWnd(), NULL, r.left, r.top, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER); +// else + hd = DeferWindowPos(hd, W->gethWnd(), NULL, r.left, r.top, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER); +#else + W->move( r.left, r.top ); +#endif + } + foreach(coopList) + ifc_window *w = coopList.getfor()->wnd; + if (w != coopWnd) + { + Layout *l = static_cast<Layout *>(w->getInterface(layoutGuid)); + if (l) + { + l->beginMove(); + } + } + endfor; +#ifdef WIN32 + if (coopList.getNumItems() > 0) EndDeferWindowPos(hd); +#endif + foreach(coopList) + ifc_window *w = coopList.getfor()->wnd; + if (w != coopWnd) + { + Layout *l = static_cast<Layout *>(w->getInterface(layoutGuid)); + if (l) + { + l->onMove(); + l->endMove(); + } + } + endfor; + rlist.removeAll(); + } + + z->left -= z_snapAdjust.left; + z->top -= z_snapAdjust.top; + z->right += z_snapAdjust.right; + z->bottom += z_snapAdjust.bottom; + + return ((f + s) != 0); +} + +int WindowTracker::hasCoopWnd(ifc_window *w) +{ + if (coopcachewnd == w) return coopcache; + coopcachewnd = w; + coopcache = 0; + for (int i = 0;i < coopList.getNumItems();i++) + if (coopList.enumItem(i)->wnd == w) + { + coopcache = 1; + break; + } + return coopcache; +} + +void WindowTracker::addCoopWnd(ifc_window *w, int forced) +{ + coopList.addItem(new coopEntry(w, forced)); + coopcachewnd = NULL; +} + +void WindowTracker::flushCoopWnds() +{ + coopList.deleteAll(); + coopcachewnd = NULL; +} + +void WindowTracker::addRootWnd(ifc_window *wnd) +{ + ASSERT(!allWnd.haveItem(wnd)); + allWnd.addItem(wnd); + if (!wnd->isVirtual()) + { + ASSERT(!nonvirtuals.haveItem(wnd)); + nonvirtuals.addItem(wnd); + } +} + +void WindowTracker::removeRootWnd(ifc_window *wnd) +{ + allWnd.delItem(wnd); + if (allWnd.getNumItems() == 0) allWnd.deleteAll(); // avoid fortify fals alarm on static + int n = nonvirtuals.searchItem(wnd); + if (n > -1) nonvirtuals.removeByPos(n); +} + +ifc_window *WindowTracker::rootWndFromPoint(POINT *pt) +{ + /* api_window *last = NULL; + api_window *last_parent = NULL; + for (int i=0;i<allWnd.getNumItems();i++) { + api_window *w = allWnd[i]; + if (last && w->getRootWndParent() != last_parent) + return checkGhost(last, (signed short)pt->x, (signed short)pt->y); + if (w->pointInWnd(pt)) { + if (!w->getRootWndParent() || w->gethWnd() != w->getRootWndParent()->gethWnd()) return checkGhost(w, (signed short)pt->x, (signed short)pt->y); + last = w; + last_parent = w->getRootWndParent(); + } + } + return NULL;*/ + + // Get window's top level window for pt +#ifdef _WIN32 + OSWINDOWHANDLE t = WindowFromPoint(*pt); + if (!t) return NULL; + + //CHECK IF SAFE ! if (!rootWndFromHwnd(t)) return NULL; + + // Find its rootWnd + for (int i = nonvirtuals.getNumItems() - 1;i >= 0;i--) + { + ifc_window *r = nonvirtuals[i]; + if (r->gethWnd() == t) + { + POINT p = *pt; + r->screenToClient((int*)&p.x, (int *)&p.y); + return r->findRootWndChild(p.x, p.y); + } + } +#else +#warning port me! +#endif + return NULL; +} + +ifc_window *WindowTracker::rootWndFromHwnd(OSWINDOWHANDLE h) +{ + if (!h) return NULL; + // Find its rootWnd + for (int i = 0;i < allWnd.getNumItems();i++) + { + ifc_window *r = allWnd[i]; + if (r->gethWnd() == h) return r; + } + return NULL; +} + +int WindowTracker::wasCooperativeMove() +{ + return wascoop; +} + +// TODO: can be moved to a static function - doesn't seem to use any class data +void WindowTracker::snapAdjustWindowRect(ifc_window *w, RECT *r, RECT *adjustvals) +{ +#ifdef WASABI_COMPILE_WNDMGR + if (w->getInterface(layoutGuid)) + { + RECT snapAdjust = {0}; + static_cast<Layout *>(w)->getSnapAdjust(&snapAdjust); + double rr = w->getRenderRatio(); + if (rr != 1.0) + { + snapAdjust.left = (int)((double)(snapAdjust.left) * rr); + snapAdjust.top = (int)((double)(snapAdjust.top) * rr); + snapAdjust.right = (int)((double)(snapAdjust.right) * rr); + snapAdjust.bottom = (int)((double)(snapAdjust.bottom) * rr); + } + r->left += snapAdjust.left; + r->top += snapAdjust.top; + r->right -= snapAdjust.right; + r->bottom -= snapAdjust.bottom; + if (adjustvals) *adjustvals = snapAdjust; + } + else { adjustvals = NULL; } +#else + if (adjustvals) MEMSET(adjustvals, 0, sizeof(RECT)); +#endif +} + +void WindowTracker::unsnapAdjustWindowRect(ifc_window *w, RECT *r, RECT *adjustvals) +{ +#ifdef WASABI_COMPILE_WNDMGR + if (w->getInterface(layoutGuid)) + { + RECT snapAdjust = {0}; + static_cast<Layout *>(w)->getSnapAdjust(&snapAdjust); + if (w->getRenderRatio() != 1.0) + { + double rr = w->getRenderRatio(); + snapAdjust.left = (int)((double)(snapAdjust.left) * rr); + snapAdjust.top = (int)((double)(snapAdjust.top) * rr); + snapAdjust.right = (int)((double)(snapAdjust.right) * rr); + snapAdjust.bottom = (int)((double)(snapAdjust.bottom) * rr); + } + r->left -= snapAdjust.left; + r->top -= snapAdjust.top; + r->right += snapAdjust.right; + r->bottom += snapAdjust.bottom; + if (adjustvals) *adjustvals = snapAdjust; + } + else { adjustvals = NULL; } +#else + if (adjustvals) MEMSET(adjustvals, 0, sizeof(RECT)); +#endif +} + +void WindowTracker::recursAddToMoveWindows(ifc_window *wnd, redock_struct *rs, int v) +{ + if (!rs) return ; + RECT r1; + if (wnd != NULL) + { + wnd->getWindowRect(&r1); + snapAdjustWindowRect(wnd, &r1); + } + else + { + wnd = rs->l; + r1 = rs->original_rect; + if (!WASABI_API_WND->rootwndIsValid(wnd)) return ; + } + + { + Layout *l = (Layout*)wnd->getInterface(layoutGuid); + if (l && (l->getNoDock() +#ifdef USEAPPBAR + || l->appbar_isDocked() +#endif + )) return ; + } + + // add all touching windows + for (int i = 0; i < desktopwnds.getNumItems(); i++) + { + ifc_window *w = desktopwnds[i]; + if (!w->isVisible()) continue; + if (w == wnd) continue; + Layout *l = (Layout*)w->getInterface(layoutGuid); + if (l && (l->getNoDock() +#ifdef USEAPPBAR + || l->appbar_isDocked() +#endif + )) continue; + RECT r2; + w->getWindowRect(&r2); + snapAdjustWindowRect(w, &r2); + // check for bottom touch + if ((v == 1 || v == -1) && r2.top == r1.bottom && !tomoveWindows_bottom.haveItem(w)) + { + if (r2.right >= r1.left && r2.left <= r1.right) + { + tomoveWindows_bottom.addItem(w); + recursAddToMoveWindows(w, rs, 1); + } + } + // check for right touch + if ((v == 0 || v == -1) && r2.left == r1.right && !tomoveWindows_right.haveItem(w)) + { + if (r2.bottom >= r1.top && r2.top <= r1.bottom) + { + tomoveWindows_right.addItem(w); + recursAddToMoveWindows(w, rs, 0); + } + } + // check for left touch + if ((v == 0 || v == -1) && r2.right == r1.left && !tomoveWindows_left.haveItem(w)) + { + if (r2.bottom >= r1.top && r2.top <= r1.bottom) + { + tomoveWindows_left.addItem(w); + recursAddToMoveWindows(w, rs, 0); + } + } + // check for top touch + if ((v == 1 || v == -1) && r2.bottom == r1.top && !tomoveWindows_top.haveItem(w)) + { + if (r2.right >= r1.left && r2.left <= r1.right) + { + tomoveWindows_top.addItem(w); + recursAddToMoveWindows(w, rs, 1); + } + } + } +} + +void WindowTracker::beforeRedock(Layout *l, redock_struct *rs) +{ + if (!l) return ; + rs->l = l; + l->getWindowRect(&rs->original_rect); + snapAdjustWindowRect(rs->l, &rs->original_rect); +} + +void WindowTracker::afterRedock(Layout *l, redock_struct *rs) +{ + RECT nr; + if (!rs) return ; + + if (!WASABI_API_WND->rootwndIsValid(l)) return ; + if (!WASABI_API_WND->rootwndIsValid(rs->l)) return ; + recursAddToMoveWindows(NULL, rs); + + l->getWindowRect(&nr); + snapAdjustWindowRect(l, &nr); + + if (l->isUnlinked() || rs->l->isUnlinked()) return ; + +#ifdef WIN32 + HDWP hdwp = BeginDeferWindowPos(desktopwnds.getNumItems()); +#endif + + PtrList<Layout> toendmove; + + int diff = rs->original_rect.bottom - nr.bottom; + if (diff) + { // check for bottom side dock changes + for (int i = 0;i < tomoveWindows_bottom.getNumItems();i++) + { + ifc_window *w = tomoveWindows_bottom[i]; + if (w == l) continue; + if (w == rs->l) continue; + if (!allWnd.haveItem(w)) continue; + RECT r; + w->getWindowRect(&r); + r.top -= diff; + r.bottom -= diff; +#ifdef WIN32 + w->notifyDeferredMove(r.left, r.top); + DeferWindowPos(hdwp, w->gethWnd(), NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE); +#else + w->move( r.left, r.top ); +#endif + Layout *l = static_cast<Layout *>(w->getInterface(layoutGuid)); + if (l) toendmove.addItem(l); + } + } + + diff = rs->original_rect.top - nr.top; + if (diff) + { // check for top side dock changes + for (int i = 0;i < tomoveWindows_top.getNumItems();i++) + { + ifc_window *w = tomoveWindows_top[i]; + if (w == l) continue; + if (w == rs->l) continue; + if (!allWnd.haveItem(w)) continue; + RECT r; + w->getWindowRect(&r); + r.top -= diff; + r.bottom -= diff; +#ifdef WIN32 + w->notifyDeferredMove(r.left, r.top); + DeferWindowPos(hdwp, w->gethWnd(), NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE); +#else + w->move( r.left, r.top ); +#endif + Layout *l = static_cast<Layout *>(w->getInterface(layoutGuid)); + if (l) toendmove.addItem(l); + } + } + + diff = rs->original_rect.right - nr.right; + if (diff) + { // check for right side dock changes + for (int i = 0;i < tomoveWindows_right.getNumItems();i++) + { + ifc_window *w = tomoveWindows_right[i]; + if (w == l) continue; + if (w == rs->l) continue; + if (!allWnd.haveItem(w)) continue; + RECT r; + w->getWindowRect(&r); + r.left -= diff; + r.right -= diff; + Layout *l = static_cast<Layout *>(w->getInterface(layoutGuid)); + if (l) l->beginMove(); +#ifdef WIN32 + w->notifyDeferredMove(r.left, r.top); + DeferWindowPos(hdwp, w->gethWnd(), NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE); +#else + w->move( r.left, r.top ); +#endif + if (l) toendmove.addItem(l); + } + } + + diff = rs->original_rect.left - nr.left; + if (diff) + { // check for left side dock changes + for (int i = 0;i < tomoveWindows_left.getNumItems();i++) + { + ifc_window *w = tomoveWindows_left[i]; + if (w == l) continue; + if (w == rs->l) continue; + if (!allWnd.haveItem(w)) continue; + RECT r; + w->getWindowRect(&r); + r.left -= diff; + r.right -= diff; + Layout *l = static_cast<Layout *>(w->getInterface(layoutGuid)); + if (l) l->beginMove(); +#ifdef WIN32 + w->notifyDeferredMove(r.left, r.top); + DeferWindowPos(hdwp, w->gethWnd(), NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE); +#else + w->move( r.left, r.top ); +#endif + if (l) toendmove.addItem(l); + } + } + +#ifdef WIN32 + EndDeferWindowPos(hdwp); +#endif + tomoveWindows_left.removeAll(); + tomoveWindows_top.removeAll(); + tomoveWindows_right.removeAll(); + tomoveWindows_bottom.removeAll(); + rs->l = NULL; + foreach(toendmove) + toendmove.getfor()->onMove(); + toendmove.getfor()->endMove(); + endfor; +} + +void WindowTracker::layoutChanged(Layout *previouswnd, Layout *newwnd) +{ + redock_struct rs; + beforeRedock(previouswnd, &rs); + afterRedock(newwnd, &rs); +} + +ifc_window *WindowTracker::coopWnd = NULL; +PtrList<ifc_window> WindowTracker::desktopwnds; +PtrList<ifc_window> WindowTracker::nonvirtuals; +PtrList<coopEntry> WindowTracker::coopList; +PtrList<ifc_window> WindowTracker::recursList; +PtrList<ifc_window> WindowTracker::tomoveWindows_left; +PtrList<ifc_window> WindowTracker::tomoveWindows_top; +PtrList<ifc_window> WindowTracker::tomoveWindows_right; +PtrList<ifc_window> WindowTracker::tomoveWindows_bottom; +PtrList<ifc_window> WindowTracker::allWnd; +int WindowTracker::dockDist = DEFAULT_DOCK_DIST; +int WindowTracker::dock_enabled = 1; |