winamp/Src/Wasabi/api/wnd/wndtrack.cpp
2024-09-24 14:54:57 +02:00

946 lines
23 KiB
C++

#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;