appbarwnd.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113
  1. #include "precomp.h"
  2. #include "appbarwnd.h"
  3. #include <tataki/region/region.h>
  4. #include <api/wnd/resizable.h>
  5. #include <api/wndmgr/layout.h>
  6. #include <api/config/items/cfgitem.h>
  7. #include <api/config/items/attrint.h>
  8. #include "../../../../Plugins/General/gen_ff/wa2cfgitems.h"
  9. #define CB_CHECK 0x101
  10. #define DOCK_DISTANCE_X 5
  11. #define DOCK_DISTANCE_Y 5
  12. #ifndef WIN32
  13. #error port me or remove me from the inheritance on this platform !
  14. #endif
  15. #include <windows.h>
  16. #include <windowsx.h>
  17. #include <shlobj.h>
  18. #include "../../../../Plugins/General/gen_ff/main.h"
  19. #include "appbarwnd.h"
  20. extern _int cfg_options_appbardockingdistance;
  21. // -----------------------------------------------------------------------
  22. AppBarWnd::AppBarWnd() {
  23. m_registered = 0;
  24. m_side = APPBAR_NOTDOCKED;
  25. m_enabled = 0;
  26. m_cur_side = APPBAR_NOTDOCKED;
  27. m_cur_autohide = 0;
  28. m_cur_hiding = 0;
  29. m_oldZOrder = NULL;
  30. m_destroying = FALSE;
  31. m_norestore = 0;
  32. m_sliding = 0;
  33. m_autounhide_timer_set = 0;
  34. m_autohide_timer_set = 0;
  35. m_suspended = 0;
  36. m_fs = 0;
  37. m_wahidden = 0;
  38. }
  39. // -----------------------------------------------------------------------
  40. AppBarWnd::~AppBarWnd() {
  41. m_destroying = TRUE;
  42. if (m_cur_side != APPBAR_NOTDOCKED) unDock();
  43. unregisterWinAppBar();
  44. }
  45. // -----------------------------------------------------------------------
  46. int AppBarWnd::registerWinAppBar()
  47. {
  48. if (m_registered)
  49. unregisterWinAppBar();
  50. APPBARDATA abd;
  51. abd.cbSize = sizeof(APPBARDATA);
  52. abd.hWnd = getOsWindowHandle();
  53. abd.uCallbackMessage = APPBAR_CALLBACK;
  54. m_registered = (int)SHAppBarMessage(ABM_NEW, &abd);
  55. return m_registered;
  56. }
  57. // -----------------------------------------------------------------------
  58. void AppBarWnd::unregisterWinAppBar() {
  59. if (m_registered) {
  60. APPBARDATA abd;
  61. abd.cbSize = sizeof(APPBARDATA);
  62. abd.hWnd = getOsWindowHandle();
  63. SHAppBarMessage(ABM_REMOVE, &abd);
  64. m_registered = 0;
  65. }
  66. }
  67. // -----------------------------------------------------------------------
  68. void AppBarWnd::appbar_dock(int side) {
  69. m_side = side;
  70. updateDocking();
  71. }
  72. // -----------------------------------------------------------------------
  73. int AppBarWnd::appbar_isDocked() {
  74. return m_side != APPBAR_NOTDOCKED;
  75. }
  76. // -----------------------------------------------------------------------
  77. int AppBarWnd::appbar_getSide() {
  78. return m_side;
  79. }
  80. // -----------------------------------------------------------------------
  81. void AppBarWnd::appbar_setEnabledSides(int mask) {
  82. m_enabled = mask;
  83. }
  84. // -----------------------------------------------------------------------
  85. int AppBarWnd::appbar_getEnabledSides() {
  86. return m_enabled;
  87. }
  88. // -----------------------------------------------------------------------
  89. int AppBarWnd::appbar_isSideEnabled(int side) {
  90. if (side == APPBAR_LEFT && !(m_enabled & APPBAR_LEFT_ENABLED)) return 0;
  91. if (side == APPBAR_TOP && !(m_enabled & APPBAR_TOP_ENABLED)) return 0;
  92. if (side == APPBAR_RIGHT && !(m_enabled & APPBAR_RIGHT_ENABLED)) return 0;
  93. if (side == APPBAR_BOTTOM && !(m_enabled & APPBAR_BOTTOM_ENABLED)) return 0;
  94. return 1;
  95. }
  96. // -----------------------------------------------------------------------
  97. int AppBarWnd::appbar_isSideAutoHideSafe(int side) {
  98. OSWINDOWHANDLE cur = getCurAutoHide(side);
  99. if (cur == NULL || cur == getOsWindowHandle()) {
  100. RECT primary = {0};
  101. Wasabi::Std::getViewport(&primary, hwnd, 1);
  102. DebugStringW( L"primary screen coords = %d,%d -> %d,%d (%dx%d)\n", primary.left, primary.top, primary.right, primary.bottom, primary.right - primary.left, primary.bottom - primary.top );
  103. int monitor = 0;
  104. //int g = 0;
  105. while (1) {
  106. RECT r;
  107. int ret = Wasabi::Std::enumViewports(monitor++, &r, 1);
  108. if (ret == 0) break;
  109. if (Wasabi::Std::rectEqual(&primary, &r)) continue;
  110. DebugStringW(L"secondary screen = %d,%d -> %d,%d (%dx%d)\n", r.left, r.top, r.right, r.bottom, r.right-r.left, r.bottom-r.top);
  111. if (r.right <= primary.left && side == APPBAR_LEFT) return 0;
  112. if (r.bottom <= primary.top && side == APPBAR_TOP) return 0;
  113. if (r.left >= primary.right && side == APPBAR_RIGHT) return 0;
  114. if (r.top >= primary.bottom && side == APPBAR_BOTTOM) return 0;
  115. }
  116. }
  117. else
  118. return 0;
  119. return 1;
  120. }
  121. // -----------------------------------------------------------------------
  122. OSWINDOWHANDLE AppBarWnd::getCurAutoHide(int side) {
  123. APPBARDATA abd;
  124. abd.cbSize = sizeof(APPBARDATA);
  125. abd.hWnd = getOsWindowHandle();
  126. abd.uEdge = side;
  127. return (OSWINDOWHANDLE)SHAppBarMessage(ABM_GETAUTOHIDEBAR, &abd);
  128. }
  129. // -----------------------------------------------------------------------
  130. int AppBarWnd::appbar_testDock(int x, int y, RECT *dockrect) {
  131. POINT ptCursor = {x, y};
  132. LONG cxScreen, cyScreen;
  133. int dx=999999, dy=999999;
  134. int horiz=-1, vert=-1;
  135. RECT viewRect = {0};
  136. Wasabi::Std::getViewport(&viewRect, hwnd, 1);
  137. // Find out which edge of the screen we're closest to
  138. cxScreen = viewRect.right;
  139. cyScreen = viewRect.bottom;
  140. if (x < viewRect.left || x > cxScreen || y < viewRect.top || y > cyScreen) return APPBAR_NOTDOCKED;
  141. if (ptCursor.x < (cxScreen / 2)) {
  142. if (m_enabled & APPBAR_LEFT_ENABLED) {
  143. dx = ptCursor.x;
  144. horiz = APPBAR_LEFT;
  145. }
  146. }
  147. else {
  148. if (m_enabled & APPBAR_RIGHT_ENABLED) {
  149. dx = cxScreen - ptCursor.x;
  150. horiz = APPBAR_RIGHT;
  151. }
  152. }
  153. if (ptCursor.y < (cyScreen / 2)) {
  154. if (m_enabled & APPBAR_TOP_ENABLED) {
  155. dy = ptCursor.y;
  156. vert = APPBAR_TOP;
  157. }
  158. }
  159. else {
  160. if (m_enabled & APPBAR_BOTTOM_ENABLED) {
  161. dy = cyScreen - ptCursor.y;
  162. vert = APPBAR_BOTTOM;
  163. }
  164. }
  165. int ret = -1;
  166. #ifdef GEN_FF
  167. int dockdist = cfg_options_appbardockingdistance;
  168. #else
  169. // TODO: do a config lookup, but make it not so slow
  170. /*
  171. const GUID options_guid =
  172. { 0x280876cf, 0x48c0, 0x40bc, { 0x8e, 0x86, 0x73, 0xce, 0x6b, 0xb4, 0x62, 0xe5 } };
  173. int dockdist = _intVal(WASABI_API_CONFIG->config_getCfgItemByGuid(options_guid), L"Appbars Docking Distance", 5);*/
  174. int dockdist = 5;
  175. #endif
  176. if ((cxScreen * dy) > (cyScreen * dx))
  177. if (dx <= dockdist)
  178. ret = horiz;
  179. if (dy <= dockdist)
  180. ret = vert;
  181. if (dockrect && ret != -1) {
  182. getDockRect(ret, dockrect);
  183. }
  184. return ret;
  185. }
  186. // -----------------------------------------------------------------------
  187. void AppBarWnd::getDockRect(int side, RECT *rect) {
  188. LONG cxScreen, cyScreen;
  189. RECT viewRect = {0};
  190. Wasabi::Std::getViewport(&viewRect, hwnd, 1);
  191. cxScreen = viewRect.right;
  192. cyScreen = viewRect.bottom;
  193. if (isMaximized()) {
  194. getRestoredRect(rect);
  195. if (renderRatioActive()) multRatio(rect);
  196. }
  197. else getWindowRect(rect);
  198. Layout *l = (Layout *)getInterface(layoutGuid);
  199. if (l) {
  200. RECT adj;
  201. l->getSnapAdjust(&adj);
  202. if (renderRatioActive()) {
  203. multRatio((int *)&adj.left, (int *)&adj.top);
  204. multRatio((int *)&adj.right, (int *)&adj.bottom);
  205. }
  206. int h = rect->bottom - rect->top;
  207. int w = rect->right - rect->left;
  208. h -= adj.top + adj.bottom;
  209. w -= adj.left + adj.right;
  210. rect->left += adj.left;
  211. rect->top += adj.top;
  212. rect->bottom = rect->top + h;
  213. rect->right = rect->left + w;
  214. }
  215. switch (side) {
  216. case APPBAR_TOP:
  217. case APPBAR_LEFT:
  218. OffsetRect(rect, -rect->left, -rect->top);
  219. break;
  220. case APPBAR_BOTTOM:
  221. case APPBAR_RIGHT:
  222. OffsetRect(rect, cxScreen-rect->right, cyScreen-rect->bottom);
  223. break;
  224. }
  225. switch (side) {
  226. case APPBAR_TOP:
  227. case APPBAR_BOTTOM:
  228. rect->left = viewRect.left;
  229. rect->right = cxScreen;
  230. break;
  231. case APPBAR_LEFT:
  232. case APPBAR_RIGHT:
  233. rect->top = viewRect.top;
  234. rect->bottom = cyScreen;
  235. break;
  236. }
  237. OSWINDOWHANDLE cur = getCurAutoHide(side);
  238. int safeah = appbar_isSideAutoHideSafe(side);
  239. if (!safeah || !(appbar_wantAutoHide() && (!cur || cur == getOsWindowHandle()))) {
  240. straightenRect(side, rect);
  241. }
  242. }
  243. // -----------------------------------------------------------------------
  244. void AppBarWnd::updateDocking() {
  245. if (!isVisible()) {
  246. m_suspended = 1;
  247. return;
  248. }
  249. updateSide();
  250. appbar_updateAutoHide();
  251. appbar_updateAlwaysOnTop();
  252. updateTimers();
  253. }
  254. // -----------------------------------------------------------------------
  255. void AppBarWnd::updateTimers() {
  256. if (m_cur_autohide) {
  257. if (m_cur_hiding) {
  258. resetAutoHideTimer();
  259. setAutoUnHideTimer();
  260. }
  261. else {
  262. resetAutoUnHideTimer();
  263. setAutoHideTimer();
  264. }
  265. }
  266. }
  267. // -----------------------------------------------------------------------
  268. int AppBarWnd::appbar_updateAlwaysOnTop() {
  269. if (m_side == APPBAR_NOTDOCKED) return 0;
  270. SetWindowPos(getOsWindowHandle(), appbar_wantAlwaysOnTop() ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  271. return 1;
  272. }
  273. // -----------------------------------------------------------------------
  274. int AppBarWnd::appbar_updateAutoHide() {
  275. int autohide = appbar_wantAutoHide();
  276. if (m_cur_autohide == autohide) return 0;
  277. if (autohide && !appbar_isSideAutoHideSafe(m_cur_side)) autohide = 0;
  278. if (m_cur_autohide == autohide) return 0;
  279. if (autohide) {
  280. // cur_autohide is off, turn it on
  281. m_cur_hiding = 0;
  282. setAutoHideTimer();
  283. }
  284. else {
  285. // cur_autohide is on, turn it off
  286. if (m_cur_hiding) resetAutoUnHideTimer();
  287. else resetAutoHideTimer();
  288. }
  289. m_cur_autohide = autohide;
  290. dock(m_cur_side);
  291. return 1;
  292. }
  293. // -----------------------------------------------------------------------
  294. void AppBarWnd::onAfterReinit() {
  295. APPBARWND_PARENT::onAfterReinit();
  296. m_autohide_timer_set = 0;
  297. m_autounhide_timer_set = 0;
  298. updateTimers();
  299. }
  300. // -----------------------------------------------------------------------
  301. void AppBarWnd::setAutoHideTimer(){
  302. if (!m_autohide_timer_set) {
  303. SetTimer(getOsWindowHandle(), IDT_AUTOHIDE, cfg_uioptions_appbarshidetime, NULL);
  304. m_autohide_timer_set = 1;
  305. }
  306. }
  307. // -----------------------------------------------------------------------
  308. void AppBarWnd::setAutoUnHideTimer(){
  309. if (!m_autounhide_timer_set) {
  310. SetTimer(getOsWindowHandle(), IDT_AUTOUNHIDE, cfg_uioptions_appbarsshowtime, NULL);
  311. m_autounhide_timer_set = 1;
  312. }
  313. }
  314. // -----------------------------------------------------------------------
  315. void AppBarWnd::resetAutoHideTimer(){
  316. if (m_autohide_timer_set) {
  317. KillTimer(getOsWindowHandle(), IDT_AUTOHIDE);
  318. m_autohide_timer_set = 0;
  319. }
  320. }
  321. // -----------------------------------------------------------------------
  322. void AppBarWnd::resetAutoUnHideTimer() {
  323. if (m_autounhide_timer_set) {
  324. KillTimer(getOsWindowHandle(), IDT_AUTOUNHIDE);
  325. m_autounhide_timer_set = 0;
  326. }
  327. }
  328. // -----------------------------------------------------------------------
  329. void AppBarWnd::updateSide() {
  330. if (m_cur_side == m_side) return;
  331. if (m_side != m_cur_side && m_cur_side != APPBAR_NOTDOCKED && m_side != APPBAR_NOTDOCKED && m_cur_autohide) {
  332. resetAutoHideSide(m_cur_side);
  333. }
  334. if (m_side == APPBAR_NOTDOCKED) unDock();
  335. else dock(m_side);
  336. }
  337. // -----------------------------------------------------------------------
  338. void AppBarWnd::resetAutoHideSide(int side) {
  339. HWND cur = getCurAutoHide(side);
  340. if (cur == getOsWindowHandle()) {
  341. APPBARDATA abd;
  342. abd.cbSize = sizeof(APPBARDATA);
  343. abd.hWnd = cur;
  344. abd.uEdge = side;
  345. abd.lParam = FALSE;
  346. SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd);
  347. }
  348. }
  349. // -----------------------------------------------------------------------
  350. void AppBarWnd::setAutoHideSide(int side) {
  351. APPBARDATA abd;
  352. abd.cbSize = sizeof(APPBARDATA);
  353. abd.hWnd = getOsWindowHandle();
  354. abd.uEdge = side;
  355. abd.lParam = TRUE;
  356. SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd);
  357. }
  358. // -----------------------------------------------------------------------
  359. void AppBarWnd::dock(int side) {
  360. unOwn();
  361. if (!registerWinAppBar()) {
  362. reOwn();
  363. m_side = APPBAR_NOTDOCKED;
  364. m_cur_side = APPBAR_NOTDOCKED;
  365. m_cur_autohide = 0;
  366. }
  367. maximize(0);
  368. RECT rect;
  369. getDockRect(side, &rect);
  370. {
  371. RECT adj = rect;
  372. if (ABS(getRenderRatio() - 1.0) > 0.01f) {
  373. int _w = adj.right-adj.left;
  374. int _h = adj.bottom-adj.top;
  375. double rr = getRenderRatio();
  376. _w = (int)((double)(_w) / rr + 0.5);
  377. _h = (int)((double)(_h) / rr + 0.5);
  378. adj.right = adj.left + _w;
  379. adj.bottom = adj.top + _h;
  380. }
  381. snapAdjust(&adj, 1);
  382. resizeToRect(&adj);
  383. }
  384. if (!appbar_wantAutoHide() || !appbar_isSideAutoHideSafe(side)) {
  385. notifyWinAppBarPosition(side, rect);
  386. }
  387. else {
  388. getEdge(side, &rect);
  389. notifyWinAppBarPosition(side, rect);
  390. setAutoHideSide(side);
  391. m_cur_hiding = 0;
  392. }
  393. if (!m_suspended) appbar_onDock(side);
  394. #ifdef WASABI_APPBAR_ONDOCKCHANGED
  395. WASABI_APPBAR_ONDOCKCHANGED(this)
  396. #endif
  397. }
  398. // -----------------------------------------------------------------------
  399. void AppBarWnd::unDock() {
  400. if (m_cur_side != APPBAR_NOTDOCKED) {
  401. resetAutoHideSide(m_cur_side);
  402. unregisterWinAppBar();
  403. if (!m_destroying) {
  404. reOwn();
  405. if (!m_norestore) restore();
  406. #ifdef WASABI_APPBAR_ONDOCKCHANGED
  407. WASABI_APPBAR_ONDOCKCHANGED(this)
  408. #endif
  409. }
  410. m_cur_side = APPBAR_NOTDOCKED;
  411. if (!m_suspended) appbar_onUnDock();
  412. }
  413. }
  414. // -----------------------------------------------------------------------
  415. void AppBarWnd::notifyWinAppBarPosition(int side, RECT rect) {
  416. APPBARDATA abd;
  417. abd.cbSize = sizeof(APPBARDATA);
  418. abd.hWnd = getOsWindowHandle();
  419. abd.rc = rect;
  420. abd.uEdge = side;
  421. SHAppBarMessage(ABM_SETPOS, &abd);
  422. m_cur_side = side;
  423. }
  424. // -----------------------------------------------------------------------
  425. int AppBarWnd::appbar_isHiding() {
  426. return m_cur_hiding;
  427. }
  428. // -----------------------------------------------------------------------
  429. int AppBarWnd::appbar_isAutoHiding() {
  430. return m_cur_autohide;
  431. }
  432. // -----------------------------------------------------------------------
  433. void AppBarWnd::appbar_posChanged() {
  434. if (m_side == APPBAR_NOTDOCKED) return;
  435. RECT wr;
  436. getWindowRect(&wr);
  437. int w = wr.right-wr.left;
  438. int h = wr.bottom-wr.top;
  439. if (m_cur_autohide && m_cur_side != APPBAR_NOTDOCKED && !appbar_isSideAutoHideSafe(m_cur_side))
  440. m_cur_autohide = 0;
  441. RECT rc;
  442. getDockRect(m_cur_side, &rc);
  443. if (!m_cur_autohide) {
  444. {
  445. RECT adj = rc;
  446. if (ABS(getRenderRatio() - 1.0) > 0.01f) {
  447. int _w = adj.right-adj.left;
  448. int _h = adj.bottom-adj.top;
  449. double rr = getRenderRatio();
  450. _w = (int)((double)(_w) / rr + 0.5);
  451. _h = (int)((double)(_h) / rr + 0.5);
  452. adj.right = adj.left + _w;
  453. adj.bottom = adj.top + _h;
  454. }
  455. snapAdjust(&adj, 1);
  456. resizeToRect(&adj);
  457. }
  458. notifyWinAppBarPosition(m_cur_side, rc);
  459. }
  460. else {
  461. int aaw = appbar_getAutoHideWidthHeight();
  462. RECT er;
  463. getEdge(m_cur_side, &er);
  464. notifyWinAppBarPosition(m_cur_side, er);
  465. RECT adj = {0,0,0,0};
  466. Layout *l = (Layout *)getInterface(layoutGuid);
  467. if (l) l->getSnapAdjust(&adj);
  468. if (renderRatioActive()) multRatio(&adj);
  469. if (m_cur_hiding) {
  470. switch (m_cur_side) {
  471. case APPBAR_TOP:
  472. rc.bottom = er.top + aaw + adj.bottom;
  473. rc.top = rc.bottom - h;
  474. break;
  475. case APPBAR_BOTTOM:
  476. rc.top = er.bottom - aaw - adj.top;
  477. rc.bottom = rc.top + h;
  478. break;
  479. case APPBAR_LEFT:
  480. rc.right = er.left + aaw + adj.right;
  481. rc.left = rc.right - w;
  482. break;
  483. case APPBAR_RIGHT:
  484. rc.left = er.right - aaw - adj.left;
  485. rc.right = rc.left + w;
  486. break;
  487. }
  488. }
  489. if (ABS(getRenderRatio() - 1.0) > 0.01f) {
  490. int _w = rc.right-rc.left;
  491. int _h = rc.bottom-rc.top;
  492. double rr = getRenderRatio();
  493. _w = (int)((double)(_w) / rr + 0.5);
  494. _h = (int)((double)(_h) / rr + 0.5);
  495. rc.right = rc.left + _w;
  496. rc.bottom = rc.top + _h;
  497. }
  498. resizeToRect(&rc);
  499. }
  500. }
  501. // -----------------------------------------------------------------------
  502. void AppBarWnd::getEdge(int side, RECT *rc) {
  503. ASSERT(rc != NULL);
  504. Wasabi::Std::getViewport(rc, hwnd, 1);
  505. switch (side) {
  506. case APPBAR_TOP:
  507. rc->bottom = rc->top; break;
  508. case APPBAR_BOTTOM:
  509. rc->top = rc->bottom; break;
  510. case APPBAR_LEFT:
  511. rc->right = rc->left; break;
  512. case APPBAR_RIGHT:
  513. rc->left = rc->right; break;
  514. }
  515. }
  516. // -----------------------------------------------------------------------
  517. void AppBarWnd::appBarCallback(UINT uMsg, WPARAM wParam, LPARAM lParam) {
  518. APPBARDATA abd = {0};
  519. if (m_registered) {
  520. abd.cbSize = sizeof(abd);
  521. abd.hWnd = getOsWindowHandle();
  522. switch (wParam)
  523. {
  524. // the taskbar's autohide or always-on-top state has changed.
  525. case ABN_STATECHANGE:
  526. DebugString("AppBarCallback: ABN_STATECHANGE\n");
  527. break;
  528. // a full screen application is opening or closing. we must drop
  529. // to the bottom of the Z-Order and restore it later.
  530. case ABN_FULLSCREENAPP:
  531. DebugString("AppBarCallback: ABN_FULLSCREENAPP\n");
  532. if (lParam && !m_fs) {
  533. m_fs=1;
  534. m_oldZOrder = GetWindow(getOsWindowHandle(), GW_HWNDPREV);
  535. SetWindowPos(getOsWindowHandle(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  536. }
  537. else if (!lParam && m_fs) {
  538. m_fs = 0;
  539. SetWindowPos(getOsWindowHandle(), appbar_wantAlwaysOnTop() ? HWND_TOPMOST : m_oldZOrder, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  540. m_oldZOrder = NULL;
  541. }
  542. break;
  543. // something changed that may have modified the possible appbar's positions
  544. case ABN_POSCHANGED:
  545. DebugString("AppBarCallback: ABN_POSCHANGED\n");
  546. appbar_posChanged();
  547. break;
  548. case ABN_WINDOWARRANGE:
  549. if (lParam && !m_wahidden) {
  550. m_wahidden = 1;
  551. ShowWindow(getOsWindowHandle(), SW_HIDE);
  552. }
  553. else if (!lParam && m_wahidden) {
  554. m_wahidden = 0;
  555. ShowWindow(getOsWindowHandle(), SW_NORMAL);
  556. }
  557. break;
  558. }
  559. }
  560. }
  561. // -----------------------------------------------------------------------
  562. LRESULT AppBarWnd::wndProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
  563. {
  564. if ( m_registered )
  565. {
  566. switch ( msg )
  567. {
  568. case WM_MOVE:
  569. {
  570. //DebugString("WM_MOVE\n");
  571. return 0;
  572. }
  573. case WM_WINDOWPOSCHANGED:
  574. {
  575. //DebugString("WM_WINDOWPOSCHANGED\n");
  576. //LPWINDOWPOS lpwpos = (LPWINDOWPOS)lparam;
  577. APPBARDATA abd = { 0 };
  578. abd.cbSize = sizeof( APPBARDATA );
  579. abd.hWnd = getOsWindowHandle();
  580. SHAppBarMessage( ABM_WINDOWPOSCHANGED, &abd );
  581. }
  582. case APPBAR_CALLBACK:
  583. {
  584. if ( !m_destroying ) appBarCallback( msg, wparam, lparam );
  585. return 0;
  586. }
  587. case WM_DISPLAYCHANGE:
  588. {
  589. DebugString( "WM_DISPLAYCHANGE\n" );
  590. appbar_posChanged();
  591. }
  592. case WM_TIMER:
  593. { // // not using multiplexed timer for independent speed
  594. switch ( wparam )
  595. {
  596. case IDT_AUTOHIDE:
  597. onAutoHideTimer();
  598. break;
  599. case IDT_AUTOUNHIDE:
  600. onAutoUnHideTimer();
  601. break;
  602. }
  603. }
  604. case WM_COMMAND:
  605. {
  606. // forward onto the main Winamp window and let it do it
  607. if ( HIWORD( wparam ) == THBN_CLICKED )
  608. {
  609. SendMessageW( plugin.hwndParent, msg, wparam, lparam );
  610. }
  611. }
  612. }
  613. }
  614. return APPBARWND_PARENT::wndProc( hwnd, msg, wparam, lparam );
  615. }
  616. // -----------------------------------------------------------------------
  617. void AppBarWnd::onAutoHideTimer() {
  618. HWND me = getOsWindowHandle();
  619. POINT pt;
  620. RECT rc;
  621. HWND hact;
  622. if (m_cur_autohide) {
  623. if (!m_cur_hiding) {
  624. GetCursorPos(&pt);
  625. GetWindowRect(hwnd, &rc);
  626. snapAdjust(&rc, -1);
  627. hact = GetForegroundWindow();
  628. if ((!PtInRect(&rc, pt) || screenCorner(&pt)) && (hact != me) && /*(hact!= NULL) && */(GetWindowOwner(hact) != me)) {
  629. resetAutoHideTimer();
  630. autoHide();
  631. setAutoUnHideTimer();
  632. }
  633. }
  634. else {
  635. resetAutoHideTimer();
  636. setAutoUnHideTimer();
  637. }
  638. }
  639. }
  640. // -----------------------------------------------------------------------
  641. void AppBarWnd::onAutoUnHideTimer() {
  642. RECT rc;
  643. POINT pt;
  644. HWND me = getOsWindowHandle();
  645. GetWindowRect(me, &rc);
  646. snapAdjust(&rc, -1);
  647. if (m_cur_autohide) {
  648. if (m_cur_hiding) {
  649. GetCursorPos(&pt);
  650. if (PtInRect(&rc, pt) && !screenCorner(&pt)) {
  651. resetAutoUnHideTimer();
  652. autoUnHide();
  653. setAutoHideTimer();
  654. }
  655. }
  656. else {
  657. resetAutoUnHideTimer();
  658. setAutoHideTimer();
  659. }
  660. }
  661. }
  662. // -----------------------------------------------------------------------
  663. void AppBarWnd::autoHide() {
  664. if (m_cur_autohide) {
  665. if (!m_cur_hiding) {
  666. RECT rc;
  667. getWindowRect(&rc);
  668. int h = rc.bottom-rc.top;
  669. int w = rc.right-rc.left;
  670. int aaw = appbar_getAutoHideWidthHeight();
  671. RECT adj={0,0,0,0};
  672. Layout *l = static_cast<Layout*>(getInterface(layoutGuid));
  673. l->getSnapAdjust(&adj);
  674. if (renderRatioActive()) multRatio(&adj);
  675. RECT viewRect = {0};
  676. Wasabi::Std::getViewport(&viewRect, hwnd, 1);
  677. switch (m_side) {
  678. case APPBAR_TOP:
  679. rc.top = -(h - aaw + adj.top - adj.bottom);
  680. break;
  681. case APPBAR_BOTTOM:
  682. rc.top = (viewRect.bottom - viewRect.top) - aaw - adj.top;
  683. break;
  684. case APPBAR_LEFT:
  685. rc.left = -(w - aaw + adj.left - adj.right);
  686. break;
  687. case APPBAR_RIGHT:
  688. rc.left = viewRect.right - aaw - adj.left;
  689. break;
  690. }
  691. switch (m_side) {
  692. case APPBAR_TOP:
  693. case APPBAR_BOTTOM:
  694. rc.bottom = rc.top + h;
  695. break;
  696. case APPBAR_LEFT:
  697. case APPBAR_RIGHT:
  698. rc.right = rc.left + w;
  699. break;
  700. }
  701. slideWindow(&rc);
  702. m_cur_hiding = 1;
  703. }
  704. }
  705. }
  706. // -----------------------------------------------------------------------
  707. void AppBarWnd::autoUnHide() {
  708. if (m_cur_autohide) {
  709. if (m_cur_hiding) {
  710. m_cur_hiding = 0;
  711. RECT rc;
  712. getWindowRect(&rc);
  713. int h = rc.bottom-rc.top;
  714. int w = rc.right-rc.left;
  715. int aaw = appbar_getAutoHideWidthHeight();
  716. RECT adj={0,0,0,0};
  717. Layout *l = static_cast<Layout*>(getInterface(layoutGuid));
  718. l->getSnapAdjust(&adj);
  719. if (renderRatioActive()) multRatio(&adj);
  720. switch (m_side) {
  721. case APPBAR_TOP:
  722. rc.top += (h - aaw) - (adj.top + adj.bottom);
  723. rc.bottom += (h - aaw) - (adj.top + adj.bottom);
  724. break;
  725. case APPBAR_BOTTOM:
  726. rc.top -= (h - aaw) - (adj.top + adj.bottom);
  727. rc.bottom -= (h - aaw) - (adj.top + adj.bottom);
  728. break;
  729. case APPBAR_LEFT:
  730. rc.right += (w - aaw) - (adj.left + adj.right);
  731. rc.left += (w - aaw) - (adj.left + adj.right);
  732. break;
  733. case APPBAR_RIGHT:
  734. rc.left -= (w - aaw) - (adj.left + adj.right);
  735. rc.right -= (w - aaw) - (adj.left + adj.right);
  736. break;
  737. }
  738. slideWindow(&rc);
  739. }
  740. }
  741. }
  742. // -----------------------------------------------------------------------
  743. const int g_dtSlideHide = 400;
  744. const int g_dtSlideShow = 200;
  745. // -----------------------------------------------------------------------
  746. void AppBarWnd::slideWindow(RECT *prc) {
  747. if (m_cur_autohide) {
  748. m_sliding = 1;
  749. RECT rcOld;
  750. RECT rcNew;
  751. int x, y, dx, dy, dt, t, t0;
  752. BOOL fShow;
  753. HANDLE hThreadMe;
  754. int priority;
  755. HWND hwnd = getOsWindowHandle();
  756. rcNew = *prc;
  757. /*DebugString("rcNew : left=%d, top=%d, "
  758. "right=%d, bottom=%d\n", rcNew.left,
  759. rcNew.top, rcNew.right, rcNew.bottom);*/
  760. if ((g_dtSlideShow > 0) && (g_dtSlideHide > 0)) {
  761. GetWindowRect(hwnd, &rcOld);
  762. fShow = TRUE;/*(rcNew.bottom - rcNew.top) > (rcOld.bottom - rcOld.top) ||
  763. (rcNew.right - rcNew.left) > (rcOld.right - rcOld.left);*/
  764. dx = (rcNew.left - rcOld.left);
  765. dy = (rcNew.top - rcOld.top);
  766. if (fShow) {
  767. rcOld = rcNew;
  768. OffsetRect(&rcOld, -dx, -dy);
  769. //DebugString("appbar_slideWindow %d %d\n", rcOld.left, rcOld.top);
  770. move(rcOld.left, rcOld.top);
  771. dt = g_dtSlideShow;
  772. }
  773. else {
  774. dt = g_dtSlideHide;
  775. }
  776. hThreadMe = GetCurrentThread();
  777. priority = GetThreadPriority(hThreadMe);
  778. SetThreadPriority(hThreadMe, THREAD_PRIORITY_HIGHEST);
  779. t0 = GetTickCount();
  780. while ((t = GetTickCount()) < t0 + dt) {
  781. x = rcOld.left + dx * (t - t0) / dt;
  782. y = rcOld.top + dy * (t - t0) / dt;
  783. //DebugString("appbar_slideWindow(2) %d %d\n", x, y);
  784. move(x, y);
  785. //SetWindowPos(hwnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  786. if (fShow) {
  787. UpdateWindow(hwnd);
  788. //invalidateWindowRegion();
  789. //updateWindowRegion();
  790. }
  791. else UpdateWindow(GetDesktopWindow());
  792. }
  793. SetThreadPriority(hThreadMe, priority);
  794. }
  795. //DebugString("appbar_slideWindow(3) %d %d\n", rcNew.left, rcNew.top);
  796. move(rcNew.left, rcNew.top);
  797. appbar_onSlide();
  798. }
  799. WASABI_API_MAKI->vcpu_setComplete();
  800. m_sliding = 0;
  801. }
  802. // -----------------------------------------------------------------------
  803. void AppBarWnd::unOwn()
  804. {
  805. // registration was successful, we should reparent the window to NULL so that minimizing the app or changing the main AOT flag does
  806. // nothing to this window
  807. Layout *l = static_cast<Layout*>(getInterface(layoutGuid));
  808. if (l) {
  809. if (!l->getNoParent()) {
  810. l->setNoParent(2);
  811. // whoaaah!
  812. reinit();
  813. }
  814. }
  815. }
  816. // -----------------------------------------------------------------------
  817. void AppBarWnd::reOwn() {
  818. OSWINDOWHANDLE mw = WASABI_API_WND->main_getRootWnd()->getOsWindowHandle();
  819. if (IsIconic(mw)) ShowWindow(mw, SW_RESTORE);
  820. // undock was successful, we should re-own the window to what it was previously. if the old owner is minimized, we should restore it first
  821. OSWINDOWHANDLE oldparent = WASABI_API_WND->main_getRootWnd()->getOsWindowHandle();
  822. if (IsIconic(oldparent)) ShowWindow(oldparent, SW_RESTORE);
  823. Layout *l = static_cast<Layout *>(getInterface(layoutGuid));
  824. if (l) {
  825. int oldnp = l->getNoParent();
  826. const wchar_t *np = l->getGuiObject()->guiobject_getXmlParam(L"noparent");
  827. int newnp = WTOI(np);
  828. if (oldnp != newnp)
  829. {
  830. l->setNoParent(newnp);
  831. // whoaaah!
  832. reinit();
  833. }
  834. }
  835. }
  836. // -----------------------------------------------------------------------
  837. void AppBarWnd::straightenRect(int side, RECT *r) {
  838. int w=0, h=0;
  839. int wasregistered = m_registered;
  840. if (!m_registered) registerWinAppBar();
  841. APPBARDATA abd;
  842. abd.hWnd = hwnd;
  843. abd.cbSize = sizeof(APPBARDATA);
  844. abd.rc = *r;
  845. abd.uEdge = side;
  846. RECT viewRect = {0};
  847. Wasabi::Std::getViewport(&viewRect, hwnd, 1);
  848. switch (side) {
  849. case APPBAR_LEFT:
  850. case APPBAR_RIGHT:
  851. w = abd.rc.right - abd.rc.left;
  852. abd.rc.top = viewRect.top;
  853. abd.rc.bottom = viewRect.bottom;
  854. break;
  855. case APPBAR_TOP:
  856. case APPBAR_BOTTOM:
  857. h = abd.rc.bottom - abd.rc.top;
  858. abd.rc.left = viewRect.left;
  859. abd.rc.right = viewRect.right;
  860. break;
  861. }
  862. SHAppBarMessage(ABM_QUERYPOS, &abd);
  863. switch (abd.uEdge) {
  864. case APPBAR_LEFT:
  865. abd.rc.right = abd.rc.left + w;
  866. break;
  867. case APPBAR_RIGHT:
  868. abd.rc.left = abd.rc.right - w;
  869. break;
  870. case APPBAR_TOP:
  871. abd.rc.bottom = abd.rc.top + h;
  872. break;
  873. case APPBAR_BOTTOM:
  874. abd.rc.top = abd.rc.bottom - h;
  875. break;
  876. }
  877. if (!wasregistered) unregisterWinAppBar();
  878. *r = abd.rc;
  879. }
  880. // -----------------------------------------------------------------------
  881. void AppBarWnd::appbar_setNoRestore(int no) {
  882. m_norestore = no;
  883. }
  884. // -----------------------------------------------------------------------
  885. void AppBarWnd::onSetVisible( int show )
  886. {
  887. if ( !show && m_side != APPBAR_NOTDOCKED && !m_suspended )
  888. {
  889. if ( m_cur_autohide )
  890. {
  891. resetAutoHideSide( m_cur_side );
  892. if ( m_cur_hiding )
  893. resetAutoUnHideTimer();
  894. else
  895. resetAutoHideTimer();
  896. }
  897. m_suspended = 1;
  898. unDock();
  899. APPBARWND_PARENT::onSetVisible( show );
  900. return;
  901. }
  902. else if ( show && m_suspended )
  903. {
  904. APPBARWND_PARENT::onSetVisible( show );
  905. m_suspended = 0;
  906. updateDocking();
  907. return;
  908. }
  909. APPBARWND_PARENT::onSetVisible( show );
  910. }
  911. // -----------------------------------------------------------------------
  912. int AppBarWnd::screenCorner(POINT *pt) {
  913. RECT primary = {0};
  914. Wasabi::Std::getViewport(&primary, hwnd, 1);
  915. if (pt->x > primary.right-2 && pt->x <= primary.right) {
  916. if (pt->y > primary.bottom-2 && pt->y <= primary.bottom) {
  917. // bottom right corner
  918. return 1;
  919. }
  920. else if (pt->y < primary.top+2 && pt->y >= primary.top) {
  921. // top right corner
  922. return 1;
  923. }
  924. }
  925. else if (pt->x < primary.left+2 && pt->x >= primary.left) {
  926. if (pt->y > primary.bottom-2 && pt->y <= primary.bottom) {
  927. // bottom left corner
  928. return 1;
  929. }
  930. else if (pt->y < primary.top+2 && pt->y >= primary.top) {
  931. // top left corner
  932. return 1;
  933. }
  934. }
  935. return 0;
  936. }
  937. // -----------------------------------------------------------------------
  938. void AppBarWnd::snapAdjust(RECT *r, int way)
  939. {
  940. RECT s;
  941. Layout *l = static_cast<Layout*>(getInterface(layoutGuid));
  942. if (!l) return;
  943. l->getSnapAdjust(&s);
  944. int h = r->bottom - r->top;
  945. int w = r->right - r->left;
  946. if (way == 1) {
  947. h += s.top + s.bottom;
  948. w += s.left + s.right;
  949. r->left -= s.left;
  950. r->top -= s.top;
  951. r->bottom = r->top + h;
  952. r->right = r->left + w;
  953. }
  954. else if (way == -1) {
  955. h -= s.top + s.bottom;
  956. w -= s.left + s.right;
  957. r->left += s.left;
  958. r->top += s.top;
  959. r->bottom = r->top + h;
  960. r->right = r->left + w;
  961. }
  962. }
  963. // -----------------------------------------------------------------------
  964. void AppBarWnd::onRatioChanged()
  965. {
  966. APPBARWND_PARENT::onRatioChanged();
  967. if (m_side != APPBAR_NOTDOCKED) appbar_posChanged();
  968. }