wndtrack.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  1. #include <precomp.h>
  2. #include <bfc/ptrlist.h>
  3. #include <api/wnd/basewnd.h>
  4. #include <bfc/util/findopenrect.h>
  5. #include <bfc/bfc_assert.h>
  6. #include <api/wndmgr/resize.h>
  7. #include <api/wnd/wndtrack.h>
  8. #include <api/config/items/attrint.h>
  9. #include <api/config/items/attrbool.h>
  10. #include <bfc/wasabi_std_wnd.h>
  11. #ifdef WASABI_COMPILE_WNDMGR
  12. #include <api/wndmgr/snappnt.h>
  13. #endif
  14. #ifdef WASABI_COMPILE_SCRIPT
  15. #include <api/script/scriptobj.h>
  16. #include <api/script/scriptguid.h>
  17. #include <api/wnd/wndclass/guiobjwnd.h> // for appbar define
  18. #endif
  19. #ifdef WASABI_COMPILE_WNDMGR
  20. #include <api/wndmgr/layout.h>
  21. #include <api/wnd/popexitcb.h>
  22. #endif
  23. #ifdef WASABI_COMPILE_SYSCB
  24. //#include <api/syscb/cbmgr.h>
  25. #endif
  26. WindowTracker *windowTracker;
  27. WindowTracker::WindowTracker()
  28. : coopcache(0),
  29. coopcachewnd(NULL)
  30. {
  31. wascoop = 0;
  32. disabledock = 0;
  33. dock_enabled = 1;
  34. }
  35. WindowTracker::~WindowTracker()
  36. {
  37. coopList.deleteAll();
  38. }
  39. void WindowTracker::addWindow(ifc_window *wnd)
  40. {
  41. ASSERT(wnd);
  42. desktopwnds.addItem(wnd);
  43. }
  44. void WindowTracker::removeWindow(ifc_window *wnd)
  45. {
  46. ASSERT(wnd);
  47. ASSERTPR(desktopwnds.haveItem(wnd), "removewindow on invalid wnd");
  48. desktopwnds.removeItem(wnd);
  49. }
  50. int WindowTracker::checkWindow(ifc_window *wnd)
  51. {
  52. return allWnd.haveItem(wnd);
  53. }
  54. ifc_window *WindowTracker::enumWindows(int n)
  55. {
  56. return desktopwnds.enumItem(n);
  57. }
  58. ifc_window *WindowTracker::getNextDesktopWindow(ifc_window *w, int next)
  59. {
  60. ifc_window *nw = NULL;
  61. if (w == NULL) nw = desktopwnds.getFirst();
  62. else
  63. {
  64. w = w->getDesktopParent();
  65. int pos = desktopwnds.searchItem(w);
  66. if (pos == -1) nw = desktopwnds.getFirst();
  67. else
  68. {
  69. pos += next;
  70. if (pos > desktopwnds.getNumItems() - 1) pos = 0;
  71. if (pos == -1) pos = desktopwnds.getNumItems() - 1;
  72. nw = desktopwnds.enumItem(pos);
  73. }
  74. }
  75. if (nw == w) return w;
  76. if (!nw->isVisible()) return getNextDesktopWindow(nw, next);
  77. return nw;
  78. }
  79. ifc_window *WindowTracker::enumAllWindows(int n)
  80. {
  81. return allWnd.enumItem(n);
  82. }
  83. int WindowTracker::getNumWindows()
  84. {
  85. return desktopwnds.getNumItems();
  86. }
  87. int WindowTracker::getNumAllWindows()
  88. {
  89. return allWnd.getNumItems();
  90. }
  91. void WindowTracker::invalidateAllWindows()
  92. {
  93. for (int i = allWnd.getNumItems() - 1;i >= 0;i--)
  94. {
  95. ifc_window *w = allWnd[i];
  96. w->triggerEvent(TRIGGER_INVALIDATE);
  97. w->invalidate();
  98. if (!w->isVirtual()) continue;
  99. w->triggerEvent(TRIGGER_ONRESIZE);
  100. }
  101. }
  102. RECT WindowTracker::findOpenRect(const RECT &prev, ifc_window *exclude)
  103. {
  104. POINT pp = { 0, 0 };
  105. //CUT if (prev != NULL) {
  106. pp.x = prev.left;
  107. pp.y = prev.top;
  108. //CUT }
  109. RECT vr; // viewport rect
  110. Wasabi::Std::getViewport(&vr, &pp);
  111. // make a rect list
  112. PtrList<RECT> list;
  113. for (int i = 0; ; i++)
  114. {
  115. ifc_window *wnd = enumWindows(i);
  116. if (wnd == NULL) break;
  117. if (wnd == exclude) continue;
  118. if (!wnd->isPostOnInit() && !wnd->isVisible()) continue;
  119. RECT *r = new RECT;
  120. wnd->getWindowRect(r);
  121. snapAdjustWindowRect(wnd, r);
  122. list.addItem(r);
  123. }
  124. FindOpenRect fr;
  125. RECT ret = fr.find(vr, list, prev);
  126. list.deleteAll();
  127. return ret;
  128. }
  129. void WindowTracker::setDockDistance(int dd)
  130. {
  131. dockDist = MINMAX(dd, MIN_DOCK_DIST, MAX_DOCK_DIST);
  132. }
  133. int WindowTracker::getDockDistance()
  134. {
  135. if (dock_enabled) return dockDist;
  136. return 0;
  137. }
  138. void WindowTracker::setEnableDocking(int ed)
  139. {
  140. dock_enabled = ed;
  141. }
  142. bool WindowTracker::touches(const RECT &r2, const RECT &r1)
  143. {
  144. if (r2.left == r1.right || r2.right == r1.left || r2.right == r1.right || r2.left == r1.left)
  145. {
  146. if (r2.bottom >= r1.top && r2.top <= r1.bottom)
  147. return true;
  148. }
  149. if (r2.top == r1.bottom || r2.bottom == r1.top || r2.bottom == r1.bottom || r2.top == r1.top)
  150. {
  151. if (r2.right >= r1.left && r2.left <= r1.right)
  152. return true;
  153. }
  154. return false;
  155. }
  156. void WindowTracker::endCooperativeMove()
  157. {
  158. wascoop = 1;
  159. flushCoopWnds();
  160. coopWnd = NULL;
  161. recursList.removeAll();
  162. }
  163. void WindowTracker::startCooperativeMove(ifc_window *thiswnd)
  164. {
  165. coopWnd = thiswnd;
  166. wascoop = 1;
  167. flushCoopWnds();
  168. if (recursList.getNumItems() > 0) recursList.removeAll();
  169. addCooperative(thiswnd);
  170. foreach_reverse(recursList)
  171. // FG> we need to prevent windows from excessively activating our windows or focus is gonna blow up
  172. // thiswnd->bringToFront();
  173. #ifdef WIN32
  174. SetWindowPos(recursList.getfor()->gethWnd(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
  175. #else
  176. recursList.getfor()->bringToFront();
  177. #endif
  178. endfor;
  179. }
  180. int WindowTracker::getNumDocked()
  181. {
  182. return recursList.getNumItems();
  183. }
  184. ifc_window *WindowTracker::enumDocked(int n)
  185. {
  186. return recursList.enumItem(n);
  187. }
  188. void WindowTracker::addCooperative(ifc_window *thiswnd)
  189. {
  190. int i;
  191. RECT r;
  192. RECT thisr;
  193. bool forceall = false;
  194. if (Std::keyModifier(STDKEY_ALT))
  195. {
  196. forceall = TRUE;
  197. }
  198. #ifdef WASABI_COMPILE_WNDMGR
  199. Layout *l = static_cast<Layout *>(thiswnd->getInterface(layoutGuid));
  200. if (l)
  201. {
  202. for (int i = 0; i < l->getNumLockedLayouts(); i++)
  203. {
  204. ifc_window *wnd = l->enumLockedLayout(i);
  205. addCoopWnd(wnd, 1);
  206. addCooperative(wnd);
  207. }
  208. }
  209. #endif
  210. if (recursList.searchItem(thiswnd) != -1) return ;
  211. recursList.addItem(thiswnd);
  212. if (Std::keyModifier(STDKEY_SHIFT)) return ;
  213. thiswnd->getWindowRect(&thisr);
  214. snapAdjustWindowRect(thiswnd, &thisr);
  215. for (i = 0; i < desktopwnds.getNumItems(); i++)
  216. {
  217. ifc_window *wnd = desktopwnds.enumItem(i);
  218. if (!wnd->isVisible()) continue;
  219. if (hasCoopWnd(wnd)) continue;
  220. if (wnd == thiswnd) continue;
  221. Layout *l = (Layout*)wnd->getInterface(layoutGuid);
  222. if (l && (l->getNoDock()
  223. #ifdef USEAPPBAR
  224. || l->appbar_isDocked()
  225. #endif
  226. )) continue;
  227. wnd->getWindowRect(&r);
  228. snapAdjustWindowRect(wnd, &r);
  229. #ifdef WASABI_COMPILE_WNDMGR
  230. int snap = SnapPoint::match(thiswnd, NULL, wnd, KEEPSIZE, NULL, NULL, 0, 0);
  231. if (forceall || snap || (touches(r, thisr) && !Wasabi::Std::rectIntersect(r, thisr)))
  232. {
  233. #else
  234. if (forceall || (touches(r, thisr) && !Std::rectIntersect(r, thisr)))
  235. {
  236. #endif
  237. addCoopWnd(wnd);
  238. addCooperative(wnd);
  239. }
  240. }
  241. }
  242. bool WindowTracker::autoDock(ifc_window *thishWnd, RECT *newPosition, int mask)
  243. {
  244. return autoDock(thishWnd, newPosition, NULL, mask);
  245. }
  246. bool WindowTracker::autoDock(ifc_window *thiswnd, RECT *z, RECT *_oldPosition, int mask)
  247. {
  248. int i = 0;
  249. RECT r = {0};
  250. #ifdef WASABI_COMPILE_CONFIG
  251. extern _bool cfg_options_docking;
  252. extern _int cfg_options_dockingdistance;
  253. dockDist = cfg_options_dockingdistance;
  254. dock_enabled = cfg_options_docking;
  255. #else
  256. #warning check these values
  257. dockDist = 4;
  258. dock_enabled = 4;
  259. #endif
  260. #ifdef USEAPPBAR
  261. // Layout *_l = static_cast<Layout *>(thiswnd->getInterface(layoutGuid));
  262. // if (_l->appbar_isDocked()) return 0;
  263. #endif
  264. RECT z_snapAdjust = {0};
  265. snapAdjustWindowRect(thiswnd, z, &z_snapAdjust);
  266. RECT *oldPosition = _oldPosition;
  267. if (oldPosition)
  268. {
  269. oldPosition->left += z_snapAdjust.left;
  270. oldPosition->top += z_snapAdjust.top;
  271. }
  272. if (!coopWnd)
  273. wascoop = 0;
  274. disabledock = 0;
  275. if (Std::keyModifier(STDKEY_SHIFT))
  276. {
  277. for (int i = 0;i < coopList.getNumItems();i++)
  278. {
  279. coopEntry *e = coopList.enumItem(i);
  280. if (!e->locked)
  281. {
  282. delete e;
  283. coopList.removeByPos(i);
  284. coopcachewnd = NULL;
  285. i--;
  286. }
  287. }
  288. disabledock = 1;
  289. }
  290. int f = 0, s = 0;
  291. int w = z->right - z->left;
  292. int h = z->bottom - z->top;
  293. POINT done = {0};
  294. if (!disabledock)
  295. {
  296. ifc_window *wnd = NULL;
  297. for (i = desktopwnds.getNumItems(); i > -1; i--)
  298. {
  299. if (i == desktopwnds.getNumItems())
  300. {
  301. #ifdef USEAPPBAR
  302. Layout *l = static_cast<Layout *>(thiswnd->getInterface(layoutGuid));
  303. if (l->appbar_isDocked()) continue;
  304. #endif
  305. Wasabi::Std::getViewport(&r, thiswnd->gethWnd());
  306. wnd = NULL;
  307. }
  308. else
  309. {
  310. wnd = desktopwnds.enumItem(i);
  311. if (coopWnd != NULL && hasCoopWnd(wnd)) continue;
  312. Layout *l = (Layout*)wnd->getInterface(layoutGuid);
  313. if (l && (l->getNoDock()
  314. #ifdef USEAPPBAR
  315. || l->appbar_isDocked()
  316. #endif
  317. )) continue;
  318. if (wnd->isVisible())
  319. {
  320. wnd->getWindowRect(&r);
  321. snapAdjustWindowRect(wnd, &r);
  322. }
  323. else continue;
  324. }
  325. if (coopWnd != NULL && coopWnd == wnd || (i >= 0 && hasCoopWnd(desktopwnds.enumItem(i)))) continue;
  326. if (thiswnd == wnd) continue;
  327. RECT oz = *z;
  328. POINT thisdone = {0};
  329. #ifdef WASABI_COMPILE_WNDMGR
  330. if (SnapPoint::match(thiswnd, z, wnd, mask, (int *)&thisdone.x, (int *)&thisdone.y, w, h)) s++;
  331. #endif
  332. if (z->left > r.left - getDockDistance() && z->left < r.left + getDockDistance() && (mask & LEFT) && !thisdone.x)
  333. {
  334. z->left = r.left;
  335. thisdone.x = 1;
  336. if (mask & KEEPSIZE) z->right = r.left + w;
  337. f++;
  338. }
  339. if (i != desktopwnds.getNumItems() && z->right > r.left - getDockDistance() && z->right < r.left + getDockDistance() && (mask & RIGHT) && !thisdone.x)
  340. {
  341. z->right = r.left;
  342. thisdone.x = 1;
  343. if (mask & KEEPSIZE) z->left = r.left - w;
  344. f++;
  345. }
  346. if (z->top > r.top - getDockDistance() && z->top < r.top + getDockDistance() && (mask & TOP) && !thisdone.y)
  347. {
  348. z->top = r.top;
  349. thisdone.y = 1;
  350. if (mask & KEEPSIZE) z->bottom = r.top + h;
  351. f++;
  352. }
  353. if (i != desktopwnds.getNumItems() && z->bottom > r.top - getDockDistance() && z->bottom < r.top + getDockDistance() && (mask & BOTTOM) && !thisdone.y)
  354. {
  355. z->bottom = r.top;
  356. thisdone.y = 1;
  357. if (mask & KEEPSIZE) z->top = r.top - h;
  358. f++;
  359. }
  360. if (z->right > r.right - getDockDistance() && z->right < r.right + getDockDistance() && (mask & RIGHT) && !thisdone.x)
  361. {
  362. z->right = r.right;
  363. thisdone.x = 1;
  364. if (mask & KEEPSIZE) z->left = r.right - w;
  365. f++;
  366. }
  367. if (i != desktopwnds.getNumItems() && z->left > r.right - getDockDistance() && z->left < r.right + getDockDistance() && (mask & LEFT) && !thisdone.x)
  368. {
  369. z->left = r.right;
  370. thisdone.x = 1;
  371. if (mask & KEEPSIZE) z->right = r.right + w;
  372. f++;
  373. }
  374. if (z->bottom > r.bottom - getDockDistance() && z->bottom < r.bottom + getDockDistance() && (mask & BOTTOM) && !thisdone.y)
  375. {
  376. z->bottom = r.bottom;
  377. thisdone.y = 1;
  378. if (mask & KEEPSIZE) z->top = r.bottom - h;
  379. f++;
  380. }
  381. if (i != desktopwnds.getNumItems() && z->top > r.bottom - getDockDistance() && z->top < r.bottom + getDockDistance() && (mask & TOP) && !thisdone.y)
  382. {
  383. z->top = r.bottom;
  384. thisdone.y = 1;
  385. if (mask & KEEPSIZE) z->bottom = r.bottom + h;
  386. f++;
  387. }
  388. if (((wnd != NULL && (mask & NOINTERSECT) && Wasabi::Std::rectIntersect(*z, r)) || !touches(*z, r)) && !s)
  389. {
  390. *z = oz;
  391. thisdone.x = 0;
  392. thisdone.y = 0;
  393. }
  394. done.x |= thisdone.x;
  395. done.y |= thisdone.y;
  396. }
  397. }
  398. if (coopWnd == thiswnd && oldPosition)
  399. {
  400. POINT s = {0}, redock = {0};
  401. TList<RECT> rlist;
  402. s.x = z->left - oldPosition->left;
  403. s.y = z->top - oldPosition->top;
  404. for (i = 0;i < coopList.getNumItems();i++)
  405. {
  406. RECT r = {0};
  407. ifc_window *W = coopList.enumItem(i)->wnd;
  408. if (!checkWindow(W)) { coopEntry *e = coopList.enumItem(i); delete e; coopList.removeByPos(i); i--; continue; }
  409. if (W != (BaseWnd*) - 1)
  410. {
  411. W->getWindowRect(&r);
  412. //snapAdjustWindowRect(W, &r);
  413. }
  414. #ifdef WIN32
  415. else
  416. GetWindowRect(WASABI_API_WND->main_getRootWnd()->gethWnd(), &r);
  417. #endif
  418. int w = r.right - r.left, h = r.bottom - r.top;
  419. r.left += s.x;
  420. r.top += s.y;
  421. r.right = r.left + w;
  422. r.bottom = r.top + h;
  423. RECT cr = r;
  424. if (autoDock(W, &cr, LEFT | RIGHT | TOP | BOTTOM | NOINTERSECT | KEEPSIZE))
  425. {
  426. if (redock.x == 0) redock.x = cr.left - r.left;
  427. if (redock.y == 0) redock.y = cr.top - r.top;
  428. }
  429. rlist.addItem(r);
  430. }
  431. if (redock.x || redock.y)
  432. {
  433. Wasabi::Std::offsetRect(z, redock.x, redock.y);
  434. f++;
  435. }
  436. #ifdef WIN32
  437. HDWP hd = NULL;
  438. if (coopList.getNumItems() > 0) hd = BeginDeferWindowPos(coopList.getNumItems());
  439. #endif
  440. for (i = 0;i < coopList.getNumItems();i++)
  441. {
  442. RECT r = rlist.enumItem(i);
  443. ifc_window *W = coopList.enumItem(i)->wnd;
  444. r.left += redock.x;
  445. r.top += redock.y;
  446. //unsnapAdjustWindowRect(W, &r);
  447. #ifdef WIN32
  448. W->notifyDeferredMove(r.left, r.top);
  449. //if (GetWindow(W->gethWnd(), GW_OWNER))
  450. // SetWindowPos(W->gethWnd(), NULL, r.left, r.top, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER);
  451. // else
  452. hd = DeferWindowPos(hd, W->gethWnd(), NULL, r.left, r.top, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER);
  453. #else
  454. W->move( r.left, r.top );
  455. #endif
  456. }
  457. foreach(coopList)
  458. ifc_window *w = coopList.getfor()->wnd;
  459. if (w != coopWnd)
  460. {
  461. Layout *l = static_cast<Layout *>(w->getInterface(layoutGuid));
  462. if (l)
  463. {
  464. l->beginMove();
  465. }
  466. }
  467. endfor;
  468. #ifdef WIN32
  469. if (coopList.getNumItems() > 0) EndDeferWindowPos(hd);
  470. #endif
  471. foreach(coopList)
  472. ifc_window *w = coopList.getfor()->wnd;
  473. if (w != coopWnd)
  474. {
  475. Layout *l = static_cast<Layout *>(w->getInterface(layoutGuid));
  476. if (l)
  477. {
  478. l->onMove();
  479. l->endMove();
  480. }
  481. }
  482. endfor;
  483. rlist.removeAll();
  484. }
  485. z->left -= z_snapAdjust.left;
  486. z->top -= z_snapAdjust.top;
  487. z->right += z_snapAdjust.right;
  488. z->bottom += z_snapAdjust.bottom;
  489. return ((f + s) != 0);
  490. }
  491. int WindowTracker::hasCoopWnd(ifc_window *w)
  492. {
  493. if (coopcachewnd == w) return coopcache;
  494. coopcachewnd = w;
  495. coopcache = 0;
  496. for (int i = 0;i < coopList.getNumItems();i++)
  497. if (coopList.enumItem(i)->wnd == w)
  498. {
  499. coopcache = 1;
  500. break;
  501. }
  502. return coopcache;
  503. }
  504. void WindowTracker::addCoopWnd(ifc_window *w, int forced)
  505. {
  506. coopList.addItem(new coopEntry(w, forced));
  507. coopcachewnd = NULL;
  508. }
  509. void WindowTracker::flushCoopWnds()
  510. {
  511. coopList.deleteAll();
  512. coopcachewnd = NULL;
  513. }
  514. void WindowTracker::addRootWnd(ifc_window *wnd)
  515. {
  516. ASSERT(!allWnd.haveItem(wnd));
  517. allWnd.addItem(wnd);
  518. if (!wnd->isVirtual())
  519. {
  520. ASSERT(!nonvirtuals.haveItem(wnd));
  521. nonvirtuals.addItem(wnd);
  522. }
  523. }
  524. void WindowTracker::removeRootWnd(ifc_window *wnd)
  525. {
  526. allWnd.delItem(wnd);
  527. if (allWnd.getNumItems() == 0) allWnd.deleteAll(); // avoid fortify fals alarm on static
  528. int n = nonvirtuals.searchItem(wnd);
  529. if (n > -1) nonvirtuals.removeByPos(n);
  530. }
  531. ifc_window *WindowTracker::rootWndFromPoint(POINT *pt)
  532. {
  533. /* api_window *last = NULL;
  534. api_window *last_parent = NULL;
  535. for (int i=0;i<allWnd.getNumItems();i++) {
  536. api_window *w = allWnd[i];
  537. if (last && w->getRootWndParent() != last_parent)
  538. return checkGhost(last, (signed short)pt->x, (signed short)pt->y);
  539. if (w->pointInWnd(pt)) {
  540. if (!w->getRootWndParent() || w->gethWnd() != w->getRootWndParent()->gethWnd()) return checkGhost(w, (signed short)pt->x, (signed short)pt->y);
  541. last = w;
  542. last_parent = w->getRootWndParent();
  543. }
  544. }
  545. return NULL;*/
  546. // Get window's top level window for pt
  547. #ifdef _WIN32
  548. OSWINDOWHANDLE t = WindowFromPoint(*pt);
  549. if (!t) return NULL;
  550. //CHECK IF SAFE ! if (!rootWndFromHwnd(t)) return NULL;
  551. // Find its rootWnd
  552. for (int i = nonvirtuals.getNumItems() - 1;i >= 0;i--)
  553. {
  554. ifc_window *r = nonvirtuals[i];
  555. if (r->gethWnd() == t)
  556. {
  557. POINT p = *pt;
  558. r->screenToClient((int*)&p.x, (int *)&p.y);
  559. return r->findRootWndChild(p.x, p.y);
  560. }
  561. }
  562. #else
  563. #warning port me!
  564. #endif
  565. return NULL;
  566. }
  567. ifc_window *WindowTracker::rootWndFromHwnd(OSWINDOWHANDLE h)
  568. {
  569. if (!h) return NULL;
  570. // Find its rootWnd
  571. for (int i = 0;i < allWnd.getNumItems();i++)
  572. {
  573. ifc_window *r = allWnd[i];
  574. if (r->gethWnd() == h) return r;
  575. }
  576. return NULL;
  577. }
  578. int WindowTracker::wasCooperativeMove()
  579. {
  580. return wascoop;
  581. }
  582. // TODO: can be moved to a static function - doesn't seem to use any class data
  583. void WindowTracker::snapAdjustWindowRect(ifc_window *w, RECT *r, RECT *adjustvals)
  584. {
  585. #ifdef WASABI_COMPILE_WNDMGR
  586. if (w->getInterface(layoutGuid))
  587. {
  588. RECT snapAdjust = {0};
  589. static_cast<Layout *>(w)->getSnapAdjust(&snapAdjust);
  590. double rr = w->getRenderRatio();
  591. if (rr != 1.0)
  592. {
  593. snapAdjust.left = (int)((double)(snapAdjust.left) * rr);
  594. snapAdjust.top = (int)((double)(snapAdjust.top) * rr);
  595. snapAdjust.right = (int)((double)(snapAdjust.right) * rr);
  596. snapAdjust.bottom = (int)((double)(snapAdjust.bottom) * rr);
  597. }
  598. r->left += snapAdjust.left;
  599. r->top += snapAdjust.top;
  600. r->right -= snapAdjust.right;
  601. r->bottom -= snapAdjust.bottom;
  602. if (adjustvals) *adjustvals = snapAdjust;
  603. }
  604. else { adjustvals = NULL; }
  605. #else
  606. if (adjustvals) MEMSET(adjustvals, 0, sizeof(RECT));
  607. #endif
  608. }
  609. void WindowTracker::unsnapAdjustWindowRect(ifc_window *w, RECT *r, RECT *adjustvals)
  610. {
  611. #ifdef WASABI_COMPILE_WNDMGR
  612. if (w->getInterface(layoutGuid))
  613. {
  614. RECT snapAdjust = {0};
  615. static_cast<Layout *>(w)->getSnapAdjust(&snapAdjust);
  616. if (w->getRenderRatio() != 1.0)
  617. {
  618. double rr = w->getRenderRatio();
  619. snapAdjust.left = (int)((double)(snapAdjust.left) * rr);
  620. snapAdjust.top = (int)((double)(snapAdjust.top) * rr);
  621. snapAdjust.right = (int)((double)(snapAdjust.right) * rr);
  622. snapAdjust.bottom = (int)((double)(snapAdjust.bottom) * rr);
  623. }
  624. r->left -= snapAdjust.left;
  625. r->top -= snapAdjust.top;
  626. r->right += snapAdjust.right;
  627. r->bottom += snapAdjust.bottom;
  628. if (adjustvals) *adjustvals = snapAdjust;
  629. }
  630. else { adjustvals = NULL; }
  631. #else
  632. if (adjustvals) MEMSET(adjustvals, 0, sizeof(RECT));
  633. #endif
  634. }
  635. void WindowTracker::recursAddToMoveWindows(ifc_window *wnd, redock_struct *rs, int v)
  636. {
  637. if (!rs) return ;
  638. RECT r1;
  639. if (wnd != NULL)
  640. {
  641. wnd->getWindowRect(&r1);
  642. snapAdjustWindowRect(wnd, &r1);
  643. }
  644. else
  645. {
  646. wnd = rs->l;
  647. r1 = rs->original_rect;
  648. if (!WASABI_API_WND->rootwndIsValid(wnd)) return ;
  649. }
  650. {
  651. Layout *l = (Layout*)wnd->getInterface(layoutGuid);
  652. if (l && (l->getNoDock()
  653. #ifdef USEAPPBAR
  654. || l->appbar_isDocked()
  655. #endif
  656. )) return ;
  657. }
  658. // add all touching windows
  659. for (int i = 0; i < desktopwnds.getNumItems(); i++)
  660. {
  661. ifc_window *w = desktopwnds[i];
  662. if (!w->isVisible()) continue;
  663. if (w == wnd) continue;
  664. Layout *l = (Layout*)w->getInterface(layoutGuid);
  665. if (l && (l->getNoDock()
  666. #ifdef USEAPPBAR
  667. || l->appbar_isDocked()
  668. #endif
  669. )) continue;
  670. RECT r2;
  671. w->getWindowRect(&r2);
  672. snapAdjustWindowRect(w, &r2);
  673. // check for bottom touch
  674. if ((v == 1 || v == -1) && r2.top == r1.bottom && !tomoveWindows_bottom.haveItem(w))
  675. {
  676. if (r2.right >= r1.left && r2.left <= r1.right)
  677. {
  678. tomoveWindows_bottom.addItem(w);
  679. recursAddToMoveWindows(w, rs, 1);
  680. }
  681. }
  682. // check for right touch
  683. if ((v == 0 || v == -1) && r2.left == r1.right && !tomoveWindows_right.haveItem(w))
  684. {
  685. if (r2.bottom >= r1.top && r2.top <= r1.bottom)
  686. {
  687. tomoveWindows_right.addItem(w);
  688. recursAddToMoveWindows(w, rs, 0);
  689. }
  690. }
  691. // check for left touch
  692. if ((v == 0 || v == -1) && r2.right == r1.left && !tomoveWindows_left.haveItem(w))
  693. {
  694. if (r2.bottom >= r1.top && r2.top <= r1.bottom)
  695. {
  696. tomoveWindows_left.addItem(w);
  697. recursAddToMoveWindows(w, rs, 0);
  698. }
  699. }
  700. // check for top touch
  701. if ((v == 1 || v == -1) && r2.bottom == r1.top && !tomoveWindows_top.haveItem(w))
  702. {
  703. if (r2.right >= r1.left && r2.left <= r1.right)
  704. {
  705. tomoveWindows_top.addItem(w);
  706. recursAddToMoveWindows(w, rs, 1);
  707. }
  708. }
  709. }
  710. }
  711. void WindowTracker::beforeRedock(Layout *l, redock_struct *rs)
  712. {
  713. if (!l) return ;
  714. rs->l = l;
  715. l->getWindowRect(&rs->original_rect);
  716. snapAdjustWindowRect(rs->l, &rs->original_rect);
  717. }
  718. void WindowTracker::afterRedock(Layout *l, redock_struct *rs)
  719. {
  720. RECT nr;
  721. if (!rs) return ;
  722. if (!WASABI_API_WND->rootwndIsValid(l)) return ;
  723. if (!WASABI_API_WND->rootwndIsValid(rs->l)) return ;
  724. recursAddToMoveWindows(NULL, rs);
  725. l->getWindowRect(&nr);
  726. snapAdjustWindowRect(l, &nr);
  727. if (l->isUnlinked() || rs->l->isUnlinked()) return ;
  728. #ifdef WIN32
  729. HDWP hdwp = BeginDeferWindowPos(desktopwnds.getNumItems());
  730. #endif
  731. PtrList<Layout> toendmove;
  732. int diff = rs->original_rect.bottom - nr.bottom;
  733. if (diff)
  734. { // check for bottom side dock changes
  735. for (int i = 0;i < tomoveWindows_bottom.getNumItems();i++)
  736. {
  737. ifc_window *w = tomoveWindows_bottom[i];
  738. if (w == l) continue;
  739. if (w == rs->l) continue;
  740. if (!allWnd.haveItem(w)) continue;
  741. RECT r;
  742. w->getWindowRect(&r);
  743. r.top -= diff;
  744. r.bottom -= diff;
  745. #ifdef WIN32
  746. w->notifyDeferredMove(r.left, r.top);
  747. DeferWindowPos(hdwp, w->gethWnd(), NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE);
  748. #else
  749. w->move( r.left, r.top );
  750. #endif
  751. Layout *l = static_cast<Layout *>(w->getInterface(layoutGuid));
  752. if (l) toendmove.addItem(l);
  753. }
  754. }
  755. diff = rs->original_rect.top - nr.top;
  756. if (diff)
  757. { // check for top side dock changes
  758. for (int i = 0;i < tomoveWindows_top.getNumItems();i++)
  759. {
  760. ifc_window *w = tomoveWindows_top[i];
  761. if (w == l) continue;
  762. if (w == rs->l) continue;
  763. if (!allWnd.haveItem(w)) continue;
  764. RECT r;
  765. w->getWindowRect(&r);
  766. r.top -= diff;
  767. r.bottom -= diff;
  768. #ifdef WIN32
  769. w->notifyDeferredMove(r.left, r.top);
  770. DeferWindowPos(hdwp, w->gethWnd(), NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE);
  771. #else
  772. w->move( r.left, r.top );
  773. #endif
  774. Layout *l = static_cast<Layout *>(w->getInterface(layoutGuid));
  775. if (l) toendmove.addItem(l);
  776. }
  777. }
  778. diff = rs->original_rect.right - nr.right;
  779. if (diff)
  780. { // check for right side dock changes
  781. for (int i = 0;i < tomoveWindows_right.getNumItems();i++)
  782. {
  783. ifc_window *w = tomoveWindows_right[i];
  784. if (w == l) continue;
  785. if (w == rs->l) continue;
  786. if (!allWnd.haveItem(w)) continue;
  787. RECT r;
  788. w->getWindowRect(&r);
  789. r.left -= diff;
  790. r.right -= diff;
  791. Layout *l = static_cast<Layout *>(w->getInterface(layoutGuid));
  792. if (l) l->beginMove();
  793. #ifdef WIN32
  794. w->notifyDeferredMove(r.left, r.top);
  795. DeferWindowPos(hdwp, w->gethWnd(), NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE);
  796. #else
  797. w->move( r.left, r.top );
  798. #endif
  799. if (l) toendmove.addItem(l);
  800. }
  801. }
  802. diff = rs->original_rect.left - nr.left;
  803. if (diff)
  804. { // check for left side dock changes
  805. for (int i = 0;i < tomoveWindows_left.getNumItems();i++)
  806. {
  807. ifc_window *w = tomoveWindows_left[i];
  808. if (w == l) continue;
  809. if (w == rs->l) continue;
  810. if (!allWnd.haveItem(w)) continue;
  811. RECT r;
  812. w->getWindowRect(&r);
  813. r.left -= diff;
  814. r.right -= diff;
  815. Layout *l = static_cast<Layout *>(w->getInterface(layoutGuid));
  816. if (l) l->beginMove();
  817. #ifdef WIN32
  818. w->notifyDeferredMove(r.left, r.top);
  819. DeferWindowPos(hdwp, w->gethWnd(), NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE);
  820. #else
  821. w->move( r.left, r.top );
  822. #endif
  823. if (l) toendmove.addItem(l);
  824. }
  825. }
  826. #ifdef WIN32
  827. EndDeferWindowPos(hdwp);
  828. #endif
  829. tomoveWindows_left.removeAll();
  830. tomoveWindows_top.removeAll();
  831. tomoveWindows_right.removeAll();
  832. tomoveWindows_bottom.removeAll();
  833. rs->l = NULL;
  834. foreach(toendmove)
  835. toendmove.getfor()->onMove();
  836. toendmove.getfor()->endMove();
  837. endfor;
  838. }
  839. void WindowTracker::layoutChanged(Layout *previouswnd, Layout *newwnd)
  840. {
  841. redock_struct rs;
  842. beforeRedock(previouswnd, &rs);
  843. afterRedock(newwnd, &rs);
  844. }
  845. ifc_window *WindowTracker::coopWnd = NULL;
  846. PtrList<ifc_window> WindowTracker::desktopwnds;
  847. PtrList<ifc_window> WindowTracker::nonvirtuals;
  848. PtrList<coopEntry> WindowTracker::coopList;
  849. PtrList<ifc_window> WindowTracker::recursList;
  850. PtrList<ifc_window> WindowTracker::tomoveWindows_left;
  851. PtrList<ifc_window> WindowTracker::tomoveWindows_top;
  852. PtrList<ifc_window> WindowTracker::tomoveWindows_right;
  853. PtrList<ifc_window> WindowTracker::tomoveWindows_bottom;
  854. PtrList<ifc_window> WindowTracker::allWnd;
  855. int WindowTracker::dockDist = DEFAULT_DOCK_DIST;
  856. int WindowTracker::dock_enabled = 1;