desktop_mode.cpp 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097
  1. /*
  2. LICENSE
  3. -------
  4. Copyright 2005-2013 Nullsoft, Inc.
  5. All rights reserved.
  6. Redistribution and use in source and binary forms, with or without modification,
  7. are permitted provided that the following conditions are met:
  8. * Redistributions of source code must retain the above copyright notice,
  9. this list of conditions and the following disclaimer.
  10. * Redistributions in binary form must reproduce the above copyright notice,
  11. this list of conditions and the following disclaimer in the documentation
  12. and/or other materials provided with the distribution.
  13. * Neither the name of Nullsoft nor the names of its contributors may be used to
  14. endorse or promote products derived from this software without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  16. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  18. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  21. IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  22. OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. #include "api__vis_milk2.h"
  25. #include "pluginshell.h"
  26. #include "resource.h"
  27. #include "utility.h"
  28. #include "defines.h"
  29. #include <shellapi.h>
  30. //----------------------------------------------------------------------
  31. #define VMS_DESKTOP_DLLNAME (SUBDIR L"data\\vms_desktop.dll")
  32. //----------------------------------------------------------------------
  33. typedef struct _SIMPLEVERTEX
  34. {
  35. float x, y; // screen position
  36. float z; // Z-buffer depth
  37. DWORD Diffuse; // diffuse color. also acts as filler; aligns struct to 16 bytes (good for random access/indexed prims)
  38. } SIMPLEVERTEX, *LPSIMPLEVERTEX;
  39. typedef struct _HELPVERTEX
  40. {
  41. float x, y; // screen position
  42. float z; // Z-buffer depth
  43. DWORD Diffuse; // diffuse color. also acts as filler; aligns struct to 16 bytes (good for random access/indexed prims)
  44. float tu, tv; // texture coordinates for texture #0
  45. } HELPVERTEX, *LPHELPVERTEX;
  46. #define SIMPLE_VERTEX_FORMAT (D3DFVF_XYZ | D3DFVF_DIFFUSE)
  47. #define HELP_VERTEX_FORMAT (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
  48. //----------------------------------------------------------------------
  49. // resides in vms_desktop.dll/lib:
  50. int setHook(HWND hlv,HWND w,int version);
  51. void removeHook();
  52. //----------------------------------------------------------------------
  53. typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
  54. bool IsVistaOrLater()
  55. {
  56. // adapted from "Getting the System Version" on MSDN - http://msdn2.microsoft.com/en-us/library/ms724429.aspx
  57. OSVERSIONINFOEX osvi;
  58. SYSTEM_INFO si;
  59. PGNSI pGNSI;
  60. BOOL bOsVersionInfoEx;
  61. ZeroMemory(&si, sizeof(SYSTEM_INFO));
  62. ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
  63. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  64. if (bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi))
  65. {
  66. // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
  67. pGNSI = (PGNSI) GetProcAddress( GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo" );
  68. if(NULL != pGNSI)
  69. pGNSI(&si);
  70. else
  71. GetSystemInfo(&si);
  72. if ( VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && osvi.dwMajorVersion > 4 )
  73. {
  74. if ( osvi.dwMajorVersion >= 6 )
  75. return true;
  76. }
  77. }
  78. return false;
  79. }
  80. int CPluginShell::InitDesktopMode()
  81. {
  82. if (m_screenmode != DESKTOP)
  83. return false;
  84. // check for Vista - if Vista, don't try to draw desktop icons.
  85. // [ vms_desktop.dll's message posts to the desktop listview window cause explorer to crash...
  86. // whether it sends WM_NULL or WM_USER+516/517. ]
  87. if (m_desktop_show_icons && IsVistaOrLater())
  88. m_desktop_show_icons = false;
  89. if (!m_desktop_show_icons)
  90. return true;
  91. // note: we have to explicitly make sure the DLL is present,
  92. // since we're delay-loading it; otherwise, calling setHook, etc. will crash it.
  93. wchar_t szVmsDesktopDll[MAX_PATH];
  94. swprintf(szVmsDesktopDll, L"%s%s", GetPluginsDirPath(), VMS_DESKTOP_DLLNAME);
  95. if (!GetModuleHandleW(szVmsDesktopDll))
  96. {
  97. if (!LoadLibraryW(szVmsDesktopDll))
  98. {
  99. wchar_t buf[2048];
  100. swprintf(buf, WASABI_API_LNGSTRINGW(IDS_COULD_NOT_FIND_FILE_FOR_DESKTOP_MODE_X), szVmsDesktopDll);
  101. MessageBoxW(GetPluginWindow(),buf,WASABI_API_LNGSTRINGW(IDS_MILKDROP_ERROR_FILE_MISSING), MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  102. //return false;
  103. m_desktop_icons_disabled = 1;
  104. }
  105. else
  106. {
  107. m_vms_desktop_loaded = 1;
  108. }
  109. }
  110. InitializeCriticalSection(&m_desktop_cs);
  111. m_desktop_icon_state = 0;
  112. m_desktop_icon_count = 0;
  113. m_desktop_icon_update_frame = 0;
  114. m_desktop_icon_size = GetDesktopIconSize();
  115. // GDI font for desktop mode:
  116. LOGFONT lf = {0};
  117. wchar_t title[64];
  118. if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0))
  119. {
  120. if (!(m_font_desktop = CreateFontIndirect(&lf)))
  121. {
  122. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_CREATING_GDI_DESKTOP_FONT),
  123. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  124. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  125. return false;
  126. }
  127. }
  128. else
  129. {
  130. if (!(m_font_desktop = CreateFont(14, 0, 0, 0, 0, 0, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH, "Monotype Sans Serif")))
  131. {
  132. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_CREATING_GDI_DESKTOP_FONT),
  133. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  134. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  135. return false;
  136. }
  137. }
  138. // Create D3DX font for drawing icon labels on desktop:
  139. if (pCreateFontW(m_lpDX->m_lpDevice, 14, 0, 0, 0, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH, L"Monotype Sans Serif", &m_d3dx_desktop_font) != D3D_OK)
  140. {
  141. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_CREATING_DESKTOP_FONT),
  142. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  143. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  144. return false;
  145. }
  146. // create first texture for holding icon bitmaps:
  147. // (do it now, to ensure that at least 1 gets created, before
  148. // the plugin does all of its DX9 allocations.)
  149. if (!CreateDesktopIconTexture(&m_desktop_icons_texture[0]))
  150. {
  151. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_CREATING_TEXTURE_FOR_ICON_BITMAPS),
  152. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  153. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  154. }
  155. if (!m_desktop_icons_disabled)
  156. {
  157. int ret = setHook(m_hWndDesktopListView, GetPluginWindow(), 1);
  158. if (ret == 1)
  159. m_desktop_hook_set = 1;
  160. else if (ret == -1)
  161. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_OUTDATED_VMS_DESKTOP_DLL_NEED_TO_REINSTALL),
  162. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  163. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  164. else
  165. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_CREATING_HOOK_PROC_DESKTOP_ICONS_NOT_AVAILABLE),
  166. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  167. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  168. }
  169. return true;
  170. }
  171. //----------------------------------------------------------------------
  172. void CPluginShell::CleanUpDesktopMode()
  173. {
  174. if (m_screenmode != DESKTOP)
  175. return;
  176. if (!m_desktop_show_icons)
  177. return;
  178. if (m_desktop_hook_set)
  179. {
  180. m_desktop_hook_set = 0;
  181. removeHook();
  182. }
  183. for (int i=0; i<MAX_ICON_TEXTURES; i++)
  184. SafeRelease(m_desktop_icons_texture[i]);
  185. SafeRelease(m_d3dx_desktop_font);
  186. if (m_desktop_wc_registered)
  187. {
  188. UnregisterClass(DESKTOP_MODE_KEYBOARD_INPUT_WINDOW_CLASSNAME, m_hInstance);
  189. m_desktop_wc_registered = 0;
  190. }
  191. if (m_font_desktop)
  192. {
  193. DeleteObject(m_font_desktop);
  194. m_font_desktop = 0;
  195. }
  196. m_icon_list.clear();
  197. DeleteCriticalSection(&m_desktop_cs);
  198. if (m_vms_desktop_loaded)
  199. {
  200. char szVmsDesktopDll[MAX_PATH];
  201. sprintf(szVmsDesktopDll, "%s%s", GetPluginsDirPath(), VMS_DESKTOP_DLLNAME);
  202. FreeLibrary(GetModuleHandle(szVmsDesktopDll));
  203. m_vms_desktop_loaded = 0;
  204. }
  205. }
  206. //----------------------------------------------------------------------
  207. int CPluginShell::CreateDesktopIconTexture(IDirect3DTexture9** ppTex)
  208. {
  209. // release old texture (shouldn't really be necessary)
  210. if (*ppTex)
  211. {
  212. (*ppTex)->Release();
  213. *ppTex = NULL;
  214. }
  215. // create new
  216. int ntries = (m_lpDX->m_d3dpp.BackBufferFormat == D3DFMT_R5G6B5) ? 3 : 1;
  217. for (int ntry=0; ntry<ntries; ntry++)
  218. {
  219. D3DFORMAT fmt = m_lpDX->m_d3dpp.BackBufferFormat;
  220. switch(m_lpDX->m_d3dpp.BackBufferFormat)
  221. {
  222. case D3DFMT_R8G8B8:
  223. case D3DFMT_X8R8G8B8:
  224. fmt = D3DFMT_A8R8G8B8;
  225. break;
  226. case D3DFMT_R5G6B5: // <- PROBLEM: NO ALPHA CHANNEL FOR ICONS
  227. if (ntry==0)
  228. switch(m_desktop_555_fix)
  229. {
  230. case 0: fmt = D3DFMT_R5G6B5; break;
  231. case 1: fmt = D3DFMT_A1R5G5B5; break;
  232. case 2: fmt = D3DFMT_A8R8G8B8; break;
  233. }
  234. else if (ntry==1)
  235. switch(m_desktop_555_fix)
  236. {
  237. case 0: fmt = D3DFMT_A1R5G5B5; break;
  238. case 1: fmt = D3DFMT_A8R8G8B8; break;
  239. case 2: fmt = D3DFMT_A1R5G5B5; break;
  240. }
  241. else
  242. switch(m_desktop_555_fix)
  243. {
  244. case 0: fmt = D3DFMT_A8R8G8B8; break;
  245. case 1: fmt = D3DFMT_R5G6B5; break;
  246. case 2: fmt = D3DFMT_R5G6B5; break;
  247. }
  248. break;
  249. case D3DFMT_X1R5G5B5:
  250. fmt = D3DFMT_A1R5G5B5;
  251. break;
  252. }
  253. if (m_lpDX->m_lpDevice->CreateTexture(ICON_TEXTURE_SIZE, ICON_TEXTURE_SIZE, 1, 0, fmt, D3DPOOL_MANAGED, ppTex, NULL) != D3D_OK)
  254. *ppTex = NULL;
  255. else
  256. break;
  257. }
  258. return (*ppTex) ? 1 : 0;
  259. }
  260. //----------------------------------------------------------------------
  261. void CPluginShell::DeselectDesktop()
  262. {
  263. IconList::iterator p;
  264. for (p = m_icon_list.begin(); p != m_icon_list.end(); p++)
  265. p->selected = 0;
  266. }
  267. //----------------------------------------------------------------------
  268. void CPluginShell::UpdateDesktopBitmaps()
  269. {
  270. // update the D3DX textures that hold all the icons:
  271. int idx = 0;
  272. int texnum = 0;
  273. int show_msgs = 1;
  274. // if no icon texture could be created at startup,
  275. // don't bother trying anything here, and don't give them
  276. // any extra error messages.
  277. if (!m_desktop_icons_texture[0])
  278. return;
  279. IconList::iterator p;
  280. for (p = m_icon_list.begin(); p != m_icon_list.end(); p++)
  281. p->icon_bitmap_idx = -1;
  282. do
  283. {
  284. idx = StuffIconBitmaps(idx, texnum++, &show_msgs);
  285. }
  286. while (idx > 0 && texnum < MAX_ICON_TEXTURES);
  287. if (idx > 0)
  288. {
  289. wchar_t title[64];
  290. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS),
  291. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_WARNING, title, 64),
  292. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  293. }
  294. }
  295. //----------------------------------------------------------------------
  296. int CPluginShell::StuffIconBitmaps(int iStartIconIdx, int iTexNum, int *show_msgs)
  297. {
  298. // returns:
  299. // 0 if done (or error), or
  300. // N if the texture is full & we need to start another one,
  301. // where N is the new iStartIconIdx to use.
  302. if (m_screenmode != DESKTOP)
  303. return 0;
  304. wchar_t title[64];
  305. if (!m_desktop_icons_texture[iTexNum])
  306. {
  307. int ret = CreateDesktopIconTexture(&m_desktop_icons_texture[iTexNum]);
  308. if (!ret)
  309. {
  310. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_TOO_MANY_UNIQUE_ICON_BITMAPS),
  311. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_WARNING, title, 64),
  312. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  313. return 0;
  314. }
  315. }
  316. D3DSURFACE_DESC sd;
  317. if (m_desktop_icons_texture[iTexNum]->GetLevelDesc(0, &sd) != D3D_OK)
  318. {
  319. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_COULD_NOT_GET_LEVEL_DESCRIPTION),
  320. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  321. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  322. return 0;
  323. }
  324. D3DLOCKED_RECT lr;
  325. if (m_desktop_icons_texture[iTexNum]->LockRect(0, &lr, NULL, 0) != D3D_OK)
  326. {
  327. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_LOCKRECT_FAILED),
  328. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  329. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  330. return 0;
  331. }
  332. if (lr.pBits == NULL)
  333. {
  334. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_LR_PBITS_IS_NULL),
  335. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  336. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  337. m_desktop_icons_texture[iTexNum]->UnlockRect(0);
  338. return 0;
  339. }
  340. unsigned __int16* p16 = (unsigned __int16*)lr.pBits;
  341. unsigned __int32* p32 = (unsigned __int32*)lr.pBits;
  342. int WIDTH = sd.Width;
  343. int i;
  344. int start;
  345. int bpp;
  346. int rshift[3]; // 1. bits to first shift right r,g,b
  347. int mask[3]; // 2. mask for r, g, b
  348. int lshift[3]; // 3. bits to then shift left r,g,b
  349. switch(sd.Format)
  350. {
  351. case D3DFMT_R8G8B8:
  352. case D3DFMT_A8R8G8B8:
  353. case D3DFMT_X8R8G8B8:
  354. start = 0xFF000000;
  355. bpp = 32;
  356. rshift[0] = 0;
  357. rshift[1] = 0;
  358. rshift[2] = 0;
  359. mask[0] = 0xFF;
  360. mask[1] = 0xFF;
  361. mask[2] = 0xFF;
  362. lshift[0] = 16;
  363. lshift[1] = 8;
  364. lshift[2] = 0;
  365. break;
  366. case D3DFMT_R5G6B5:
  367. start = 0x0000;
  368. bpp = 16;
  369. rshift[0] = 3;
  370. rshift[1] = 2;
  371. rshift[2] = 3;
  372. mask[0] = 0x1F;
  373. mask[1] = 0x3F;
  374. mask[2] = 0x1F;
  375. lshift[0] = 11;
  376. lshift[1] = 5;
  377. lshift[2] = 0;
  378. break;
  379. case D3DFMT_X1R5G5B5:
  380. case D3DFMT_A1R5G5B5:
  381. start = 0x8000;
  382. bpp = 16;
  383. rshift[0] = 3;
  384. rshift[1] = 3;
  385. rshift[2] = 3;
  386. mask[0] = 0x1F;
  387. mask[1] = 0x1F;
  388. mask[2] = 0x1F;
  389. lshift[0] = 10;
  390. lshift[1] = 5;
  391. lshift[2] = 0;
  392. break;
  393. case D3DFMT_A4R4G4B4:
  394. start = 0xF000;
  395. bpp = 16;
  396. rshift[0] = 4;
  397. rshift[1] = 4;
  398. rshift[2] = 4;
  399. mask[0] = 0x0F;
  400. mask[1] = 0x0F;
  401. mask[2] = 0x0F;
  402. lshift[0] = 8;
  403. lshift[1] = 4;
  404. lshift[2] = 0;
  405. break;
  406. default:
  407. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_UNKNOWN_PIXEL_FORMAT),
  408. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  409. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  410. m_desktop_icons_texture[iTexNum]->UnlockRect(0);
  411. return 0;
  412. }
  413. HDC hdc = GetDC(NULL);
  414. if (!hdc)
  415. {
  416. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_COULDNT_GET_HDC),
  417. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  418. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  419. m_desktop_icons_texture[iTexNum]->UnlockRect(0);
  420. return 0;
  421. }
  422. #define MAX_ICON_SIZE 128
  423. unsigned char data[MAX_ICON_SIZE*MAX_ICON_SIZE*4];
  424. int nAcross = ICON_TEXTURE_SIZE/m_desktop_icon_size;
  425. int nDown = ICON_TEXTURE_SIZE/m_desktop_icon_size;
  426. // for each icon, add its bitmap to the texture (if not already there),
  427. // and set 'icon_bitmap_idx'.
  428. IconList::iterator p = m_icon_list.begin();
  429. for (i=0; i < iStartIconIdx; i++)
  430. p++;
  431. int bitmap_idx = 0;
  432. int list_idx = iStartIconIdx;
  433. for ( ; p != m_icon_list.end() && bitmap_idx < nAcross*nDown; p++)
  434. {
  435. // note: 'p' points to the correct icon to start with,
  436. // but 'idx' starts at zero!
  437. // get the icon:
  438. SHFILEINFO sfi;
  439. int flags = SHGFI_ICON|SHGFI_PIDL|SHGFI_SHELLICONSIZE | ((m_desktop_icon_size > 32) ? SHGFI_LARGEICON : 0);
  440. if (SHGetFileInfo((LPCTSTR)p->pidl, 0, &sfi, sizeof(sfi), flags))
  441. {
  442. ICONINFO ii;
  443. if (GetIconInfo(sfi.hIcon, &ii))
  444. {
  445. int x0 = (bitmap_idx%nAcross)*m_desktop_icon_size;
  446. int y0 = (bitmap_idx/nAcross)*m_desktop_icon_size;
  447. int checksum[3] = { 0, 0, 0 };
  448. BITMAPINFO bmi;
  449. // pass 1: get the colors
  450. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  451. bmi.bmiHeader.biWidth = m_desktop_icon_size;
  452. bmi.bmiHeader.biHeight = m_desktop_icon_size;
  453. bmi.bmiHeader.biPlanes = 1;
  454. bmi.bmiHeader.biBitCount = 32;
  455. bmi.bmiHeader.biCompression = BI_RGB;
  456. if (GetDIBits(
  457. hdc, // handle to DC
  458. ii.hbmColor, // handle to bitmap
  459. 0, // first scan line to set
  460. m_desktop_icon_size,// number of scan lines to copy
  461. data, // array for bitmap bits
  462. &bmi, // bitmap data buffer
  463. DIB_RGB_COLORS // RGB or palette index
  464. ))
  465. {
  466. int w = min(bmi.bmiHeader.biWidth , m_desktop_icon_size);
  467. int h = min(bmi.bmiHeader.biHeight, m_desktop_icon_size);
  468. for (int y=0; y<h; y++)
  469. for (int x=0; x<w; x++)
  470. {
  471. int in_offset = ((h-1-y)*w + x)*4;
  472. int r = data[in_offset+2];
  473. int g = data[in_offset+1];
  474. int b = data[in_offset+0];
  475. checksum[0] += r;
  476. checksum[1] += g;
  477. checksum[2] += b;
  478. int out_offset = (y0+y)*WIDTH + (x0+x);
  479. if (bpp==16)
  480. p16[out_offset] = start |
  481. (((r >> rshift[0]) & mask[0]) << lshift[0]) |
  482. (((g >> rshift[1]) & mask[1]) << lshift[1]) |
  483. (((b >> rshift[2]) & mask[2]) << lshift[2]);
  484. else
  485. p32[out_offset] = start |
  486. (((r >> rshift[0]) & mask[0]) << lshift[0]) |
  487. (((g >> rshift[1]) & mask[1]) << lshift[1]) |
  488. (((b >> rshift[2]) & mask[2]) << lshift[2]);
  489. }
  490. }
  491. else
  492. {
  493. if (*show_msgs)
  494. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_CALL_TO_GETDIBITS_FAILED),
  495. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  496. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  497. *show_msgs = 0;
  498. }
  499. // pass 2: get the alpha mask
  500. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  501. bmi.bmiHeader.biWidth = m_desktop_icon_size;
  502. bmi.bmiHeader.biHeight = m_desktop_icon_size;
  503. bmi.bmiHeader.biPlanes = 1;
  504. bmi.bmiHeader.biBitCount = 32;
  505. bmi.bmiHeader.biCompression = BI_RGB;
  506. if (GetDIBits(
  507. hdc, // handle to DC
  508. ii.hbmMask, // handle to bitmap
  509. 0, // first scan line to set
  510. m_desktop_icon_size,// number of scan lines to copy
  511. data, // array for bitmap bits
  512. &bmi, // bitmap data buffer
  513. DIB_RGB_COLORS // RGB or palette index
  514. ))
  515. {
  516. int w = min(bmi.bmiHeader.biWidth , m_desktop_icon_size);
  517. int h = min(bmi.bmiHeader.biHeight, m_desktop_icon_size);
  518. for (int y=0; y<h; y++)
  519. for (int x=0; x<w; x++)
  520. {
  521. int in_offset = ((h-1-y)*w + x)*4;
  522. int r = data[in_offset+2];
  523. int g = data[in_offset+1];
  524. int b = data[in_offset+0];
  525. checksum[0] += r;
  526. checksum[1] += g;
  527. checksum[2] += b;
  528. if (r || g || b)
  529. {
  530. int out_offset = (y0+y)*WIDTH + (x0+x);
  531. if (bpp==16)
  532. p16[out_offset] &= ~start;
  533. else
  534. p32[out_offset] &= ~start;
  535. }
  536. }
  537. }
  538. else
  539. {
  540. if (*show_msgs)
  541. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_CALL_2_TO_GETDIBITS_FAILED),
  542. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  543. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  544. *show_msgs = 0;
  545. }
  546. // check for duplicate icon, and if found, reuse it
  547. int done = 0;
  548. IconList::iterator q;
  549. for (q = m_icon_list.begin(); q != m_icon_list.end() && q != p; q++)
  550. {
  551. if (checksum[0] == q->checksum[0] &&
  552. checksum[1] == q->checksum[1] &&
  553. checksum[2] == q->checksum[2])
  554. {
  555. p->icon_bitmap_idx = q->icon_bitmap_idx;
  556. done = 1;
  557. break;
  558. }
  559. }
  560. // otherwise, keep new icon
  561. if (!done)
  562. {
  563. p->icon_bitmap_idx = nAcross*nDown*iTexNum + bitmap_idx;
  564. p->checksum[0] = checksum[0];
  565. p->checksum[1] = checksum[1];
  566. p->checksum[2] = checksum[2];
  567. bitmap_idx++;
  568. }
  569. DeleteObject(ii.hbmMask);
  570. DeleteObject(ii.hbmColor);
  571. }
  572. else
  573. {
  574. if (*show_msgs)
  575. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_GETICONINFO_FAILED),
  576. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  577. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  578. *show_msgs = 0;
  579. }
  580. DestroyIcon(sfi.hIcon);
  581. }
  582. else
  583. {
  584. if (*show_msgs)
  585. MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_SHGETFILEINFO_FAILED),
  586. WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
  587. MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  588. *show_msgs = 0;
  589. }
  590. list_idx++;
  591. }
  592. ReleaseDC(NULL, hdc);
  593. m_desktop_icons_texture[iTexNum]->UnlockRect(0);
  594. if (bitmap_idx >= nAcross*nDown)
  595. return list_idx;
  596. else
  597. return 0; // all done
  598. }
  599. //----------------------------------------------------------------------
  600. void CPluginShell::RenderDesktop()
  601. {
  602. if (m_screenmode != DESKTOP)
  603. return;
  604. if (!m_desktop_show_icons)
  605. return;
  606. if (m_desktop_icons_disabled)
  607. return;
  608. IconList::iterator p;
  609. EnterCriticalSection(&m_desktop_cs);
  610. int iconcount = static_cast<unsigned long>(SendMessage(m_hWndDesktopListView, LVM_GETITEMCOUNT, 0, 0));
  611. if (iconcount == 0)
  612. {
  613. LeaveCriticalSection(&m_desktop_cs);
  614. return;
  615. }
  616. // if the icons list is empty,
  617. // or if we check it for consistency and an update is recommended (GetDesktopIcons(1)==2),
  618. // update the icons list & the bitmaps:
  619. /*if (m_icon_list.size()==0 || GetDesktopIcons(1)==2)
  620. {
  621. m_icon_list.clear();
  622. GetDesktopIcons(0);
  623. UpdateDesktopBitmaps();
  624. }*/
  625. // check for invalid entries. (if there is an error in getItemData(),
  626. // it will return the icon_t structure anyway, but with empty strings.)
  627. int invalid_entries = 0;
  628. if (m_desktop_icon_state >= 2)
  629. {
  630. for (p = m_icon_list.begin(); p != m_icon_list.end() && !invalid_entries; p++)
  631. {
  632. if (p->name[0]==0)
  633. invalid_entries = 1;
  634. //if (p->pidl[0].mkid.cb==0 && p->pidl[0].mkid.abID[0]==0)
  635. if (p->pidl[0]==0 && p->pidl[1]==0)
  636. invalid_entries = 1;
  637. }
  638. }
  639. if (
  640. (m_desktop_icon_state == 0) ||
  641. (m_desktop_icon_state >= 2 && m_desktop_icon_count != iconcount) ||
  642. (m_desktop_icon_state >= 2 && invalid_entries)
  643. )
  644. {
  645. // begin total refresh
  646. m_desktop_icon_state = 1;
  647. m_desktop_icon_count = iconcount;
  648. m_desktop_icon_update_frame = GetFrame();
  649. m_icon_list.clear();
  650. SendMessage(GetPluginWindow(), WM_USER, 0x80000000 | iconcount, 0);//getItemData(i);
  651. // try to get the desktop window's listview to respond to
  652. // the queries as quickly as possible:
  653. {
  654. LeaveCriticalSection(&m_desktop_cs);
  655. DWORD procid = NULL;
  656. DWORD threadid = GetWindowThreadProcessId(m_hWndDesktopListView, &procid);
  657. HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION, FALSE, procid);
  658. DWORD x = GetPriorityClass(hProcess);
  659. if (x) SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);
  660. for (int i=0; i<5; i++)
  661. {
  662. Sleep(10);
  663. MSG msg;
  664. while(PeekMessage(&msg,GetPluginWindow(),0,0,PM_REMOVE))
  665. {
  666. TranslateMessage(&msg);
  667. DispatchMessage(&msg);
  668. }
  669. }
  670. if (x) SetPriorityClass(hProcess, x);
  671. CloseHandle(hProcess);
  672. EnterCriticalSection(&m_desktop_cs);
  673. }
  674. }
  675. else if (m_desktop_icon_state == 1 &&
  676. m_icon_list.size() < (size_t)m_desktop_icon_count)
  677. {
  678. // waiting for the 'total refresh' to complete
  679. // ...
  680. if (GetFrame() > m_desktop_icon_update_frame+64)
  681. {
  682. m_desktop_icon_state = 0;
  683. }
  684. }
  685. else
  686. if (m_desktop_icon_state == 1 &&
  687. m_icon_list.size() == m_desktop_icon_count)
  688. {
  689. // done with total refresh
  690. m_desktop_icon_state = 2;
  691. m_desktop_icon_update_frame = GetFrame();
  692. UpdateDesktopBitmaps();
  693. }
  694. else if (m_desktop_icon_state == 2)
  695. {
  696. if (GetFrame() > m_desktop_icon_update_frame+4)
  697. {
  698. m_desktop_icon_state = 3; // will mean we're waiting on data to return.
  699. m_desktop_icon_update_frame = GetFrame();
  700. int start = 0;
  701. int len = iconcount;
  702. SendMessage(GetPluginWindow(), WM_USER, start | (len << 16), 0);//getItemData(i);
  703. }
  704. }
  705. else if (m_desktop_icon_state == 3)
  706. {
  707. if (GetFrame() > m_desktop_icon_update_frame+64)
  708. {
  709. // timeout; give up waiting for update message to come back,
  710. // and just request another.
  711. m_desktop_icon_state = 2;
  712. m_desktop_icon_update_frame = GetFrame();
  713. }
  714. }
  715. // get horz. spacing between icons (...determines width of labels)
  716. ICONMETRICS icm;
  717. icm.cbSize = sizeof(icm);
  718. if (!SystemParametersInfo(SPI_GETICONMETRICS, sizeof(icm), &icm, 0))
  719. icm.iHorzSpacing = 68;
  720. /*int font_height = 0;
  721. {
  722. RECT r;
  723. m_d3dx_desktop_font->DrawText(NULL, "M", -1, &r, DT_CALCRECT, 0xFFFFFFFF);
  724. font_height = r.bottom - r.top;
  725. }*/
  726. // display the desktop.
  727. m_lpDX->m_lpDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
  728. m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  729. m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  730. m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  731. m_lpDX->m_lpDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
  732. m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);//D3DTOP_SELECTARG1 );
  733. m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  734. m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
  735. m_lpDX->m_lpDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  736. int nAcross = ICON_TEXTURE_SIZE/m_desktop_icon_size;
  737. int nDown = ICON_TEXTURE_SIZE/m_desktop_icon_size;
  738. // The icon's x and y coordinates (as returned by the
  739. // getIconData/WM_COPYDATA system) are (0,0) at the
  740. // upper-left corner of the rectangle that encompasses
  741. // all the monitors together (m_lpDX->m_all_monitors_rect).
  742. // Note that in 'm_all_monitors_rect', (0,0) represents
  743. // the upper-left corner of the PRIMARY DISPLAY - not necessarily
  744. // the one we're showing the fake desktop on.
  745. // What we have to do here is determine icon_dx and icon_dy,
  746. // which are the transformation from the coordinate space used
  747. // by the desktop itself (as returned in WM_COPYDATA)
  748. // and the coordinates used by Windows itself (where 0,0 is
  749. // the upper-left corner of the PRIMARY DISPLAY, and coordinates
  750. // in other displays can be negative if they are above/left of it).
  751. int upperleft_x = min(m_lpDX->m_all_monitors_rect.left, m_lpDX->m_monitor_rect.left);
  752. int upperleft_y = min(m_lpDX->m_all_monitors_rect.top , m_lpDX->m_monitor_rect.top );
  753. int icon_dx = m_lpDX->m_monitor_rect.left - upperleft_x; // subtract this amount
  754. int icon_dy = m_lpDX->m_monitor_rect.top - upperleft_y; // subtract this amount
  755. if (!m_desktop_manual_icon_scoot)
  756. {
  757. icon_dx -= m_lpDX->m_monitor_rect.left - m_lpDX->m_monitor_work_rect.left;
  758. icon_dy -= m_lpDX->m_monitor_rect.top - m_lpDX->m_monitor_work_rect.top ;
  759. }
  760. // pass 0: draw normal text & icons
  761. // pass 1: redraw icon currently being dragged, transparently
  762. int nPasses = m_desktop_dragging ? 2 : 1;
  763. for (int pass=0; pass<nPasses; pass++)
  764. {
  765. // first, draw [blue backgrounds &] text labels
  766. {
  767. m_lpDX->m_lpDevice->SetVertexShader( NULL );
  768. m_lpDX->m_lpDevice->SetFVF( SIMPLE_VERTEX_FORMAT );
  769. m_lpDX->m_lpDevice->SetTexture(0, NULL);
  770. SIMPLEVERTEX verts[4];
  771. // pass2==0: draw text labels
  772. // pass2==1: draw text overtop
  773. // (separated for speed, so ID3DXFont can get the HDC just once for all the DrawText calls)
  774. for (int pass2=0; pass2<2; pass2++)
  775. {
  776. //if (pass2==1)
  777. //m_d3dx_desktop_font->Begin();
  778. for (p = m_icon_list.begin(); p != m_icon_list.end(); p++)
  779. {
  780. if (pass==0 || (p->selected && m_desktop_dragging))
  781. {
  782. int max_width = icm.iHorzSpacing-5+m_desktop_icon_size-32;//icm.iHorzSpacing-5;
  783. int dx = 0;
  784. int dy = 4;
  785. if (pass>0)
  786. {
  787. dx += m_desktop_drag_curpos.x - m_desktop_drag_startpos.x;
  788. dy += m_desktop_drag_curpos.y - m_desktop_drag_startpos.y;
  789. }
  790. SetRect(&p->label_rect,
  791. p->x + m_desktop_icon_size/2 - icon_dx - max_width/2 + dx,
  792. p->y + m_desktop_icon_size - icon_dy + dy,
  793. p->x + m_desktop_icon_size/2 - icon_dx + max_width/2 + dx,
  794. p->y + m_desktop_icon_size - icon_dy + 0 + dy // will be extended by DT_CALCRECT step!
  795. );
  796. // calculate rect for the text label
  797. DWORD style = DT_CENTER|DT_WORDBREAK|DT_END_ELLIPSIS|DT_WORD_ELLIPSIS;
  798. // these aren't supported by D3DX9:
  799. style &= ~(DT_WORD_ELLIPSIS | DT_END_ELLIPSIS | DT_NOPREFIX);
  800. m_d3dx_desktop_font->DrawText(NULL, p->name, -1, &p->label_rect, style|DT_CALCRECT, 0xFFFFFFFF);
  801. // D3DX doesn't handle text so well if it goes off
  802. // the left edge of the screen, so don't show text labels
  803. // that are mostly off (on the left side):
  804. if ((p->label_rect.left + p->label_rect.right)/2 > 0)
  805. {
  806. // also, if label would go off left edge of screen,
  807. // push it to the right:
  808. if (p->label_rect.left < 0 && p->label_rect.right > 0)
  809. {
  810. p->label_rect.right -= p->label_rect.left;
  811. p->label_rect.left = 0;
  812. }
  813. //if (p->selected) // ...draw blue background around text label
  814. if (pass2==0)
  815. {
  816. if (m_desktop_textlabel_boxes || p->selected)
  817. {
  818. #define EXTEND_LEFT 3
  819. #define EXTEND_RIGHT 2
  820. #define EXTEND_TOP 0
  821. #define EXTEND_BOTTOM 2
  822. for (int i=0; i<4; i++)
  823. {
  824. verts[i].x = (i%2==0) ? (float)(-m_lpDX->m_client_width/2 + p->label_rect.left - EXTEND_LEFT) : (float)(-m_lpDX->m_client_width/2 + p->label_rect.right + EXTEND_RIGHT); // was -2/+3
  825. verts[i].y = (i/2==0) ? (float)(m_lpDX->m_client_height/2 - p->label_rect.top + EXTEND_TOP ) : (float)(m_lpDX->m_client_height/2 - p->label_rect.bottom - EXTEND_BOTTOM); // was +1/-1
  826. verts[i].z = 0;
  827. verts[i].Diffuse = (p->selected) ? m_desktop_sel_color : m_desktop_bk_color;//0xFF000000;
  828. if (pass>0)
  829. verts[i].Diffuse &= 0x7FFFFFFF;
  830. }
  831. m_lpDX->m_lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, verts, sizeof(SIMPLEVERTEX));
  832. }
  833. }
  834. else
  835. {
  836. DWORD text_color = (p->selected) ? m_desktop_sel_text_color : m_desktop_text_color;
  837. if (pass==1)
  838. text_color &= 0x7FFFFFFF;
  839. // these aren't supported by D3DX9:
  840. style &= ~(DT_WORD_ELLIPSIS | DT_END_ELLIPSIS | DT_NOPREFIX);
  841. m_d3dx_desktop_font->DrawText(NULL, p->name, -1, &p->label_rect, style, text_color);
  842. }
  843. }
  844. }
  845. }
  846. //if (pass2==1)
  847. // m_d3dx_desktop_font->End();
  848. }
  849. }
  850. m_lpDX->m_lpDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  851. m_lpDX->m_lpDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
  852. m_lpDX->m_lpDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  853. // second, draw icon bitmaps (overtop)
  854. if (m_desktop_icon_state >= 2)
  855. {
  856. int dx = 0;
  857. int dy = 0;
  858. int iTexNum = 0;
  859. while (m_desktop_icons_texture[iTexNum] && iTexNum < MAX_ICON_TEXTURES)
  860. {
  861. HELPVERTEX verts[4];
  862. m_lpDX->m_lpDevice->SetVertexShader( NULL );
  863. m_lpDX->m_lpDevice->SetFVF( HELP_VERTEX_FORMAT );
  864. m_lpDX->m_lpDevice->SetTexture(0, m_desktop_icons_texture[iTexNum]);
  865. for (p = m_icon_list.begin(); p != m_icon_list.end(); p++)
  866. {
  867. int icon_tex_idx = (p->icon_bitmap_idx==-1) ? 0 : (p->icon_bitmap_idx / (nAcross*nDown));
  868. int icon_bitmap_idx = (p->icon_bitmap_idx==-1) ? 0 : (p->icon_bitmap_idx % (nAcross*nDown));
  869. if (
  870. (icon_tex_idx == iTexNum) &&
  871. (pass==0 || (p->selected && m_desktop_dragging))
  872. )
  873. {
  874. SetRect(&p->icon_rect,
  875. p->x - icon_dx + dx,
  876. p->y - icon_dy + dy,
  877. p->x - icon_dx + dx + m_desktop_icon_size,
  878. p->y - icon_dy + dy + m_desktop_icon_size);
  879. int lookup_x = 0;
  880. int lookup_y = 0;
  881. if (icon_bitmap_idx >= 0) // if -1, means icon didn't fit in the texture
  882. {
  883. lookup_x = icon_bitmap_idx % nAcross;
  884. lookup_y = icon_bitmap_idx / nAcross;
  885. }
  886. for (int i=0; i<4; i++)
  887. {
  888. verts[i].x = (i%2==0) ? (float)(-m_lpDX->m_client_width/2 + p->icon_rect.left) : (float)(-m_lpDX->m_client_width/2 + p->icon_rect.right );
  889. verts[i].y = (i/2==0) ? (float)(m_lpDX->m_client_height/2 - p->icon_rect.top ) : (float)(m_lpDX->m_client_height/2 - p->icon_rect.bottom);
  890. verts[i].z = 0;
  891. verts[i].tu = ((lookup_x + i%2)*m_desktop_icon_size + 0.5f)/(float)ICON_TEXTURE_SIZE;
  892. verts[i].tv = ((lookup_y + i/2)*m_desktop_icon_size + 0.5f)/(float)ICON_TEXTURE_SIZE;
  893. verts[i].Diffuse = (p->selected) ? m_desktop_sel_color : 0xFFFFFFFF;
  894. if (pass>0)
  895. {
  896. verts[i].x += m_desktop_drag_curpos.x - m_desktop_drag_startpos.x;
  897. verts[i].y -= m_desktop_drag_curpos.y - m_desktop_drag_startpos.y;
  898. verts[i].Diffuse &= 0x7FFFFFFF;
  899. }
  900. }
  901. m_lpDX->m_lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, verts, sizeof(HELPVERTEX));
  902. }
  903. }
  904. iTexNum++;
  905. }
  906. }
  907. }
  908. // finally, draw selection box (if user is dragging one)
  909. if (m_desktop_box)
  910. {
  911. m_lpDX->m_lpDevice->SetVertexShader( NULL );
  912. m_lpDX->m_lpDevice->SetFVF( SIMPLE_VERTEX_FORMAT );
  913. m_lpDX->m_lpDevice->SetTexture(0, NULL);
  914. SIMPLEVERTEX verts[5];
  915. for (int i=0; i<4; i++)
  916. {
  917. verts[i].x = (i==1||i==2) ? (float)(-m_lpDX->m_client_width/2 + m_desktop_drag_startpos.x) : (float)(-m_lpDX->m_client_width/2 + m_desktop_drag_curpos.x);
  918. verts[i].y = (i==0||i==1) ? (float)(m_lpDX->m_client_height/2 - m_desktop_drag_startpos.y) : (float)(m_lpDX->m_client_height/2 - m_desktop_drag_curpos.y);
  919. verts[i].z = 0;
  920. verts[i].Diffuse = 0x80FFFFFF;
  921. }
  922. verts[4] = verts[0];
  923. m_lpDX->m_lpDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, 4, verts, sizeof(SIMPLEVERTEX));
  924. }
  925. m_lpDX->m_lpDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
  926. m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  927. m_lpDX->m_lpDevice->SetTexture(0, NULL);
  928. LeaveCriticalSection(&m_desktop_cs);
  929. }
  930. //----------------------------------------------------------------------
  931. /*
  932. NOTES LOG
  933. -problem: you can't click on the 1st monitor's desktop & do stuff
  934. -> fixed if you get rid of m_desktop_focuswnd and
  935. don't block WM_MOUSEACTIVATE.
  936. -> but doing this causes a flash when you click on
  937. the real desktop (in multimon setup) of any windows
  938. that are overtop of the fake desktop, since the
  939. fake desktop rises up in the Z order (activates)
  940. and then, next frame, gets pushed back again.
  941. -> so how do we avoid the flash?
  942. by [conditionally] stopping any z-order changes;
  943. intercept & change WM_WINDOWPOSCHANGING messages
  944. so there's no z-change, unless *we* specifically
  945. requested it (in PushWindowToBack()).
  946. -> new problem: right-click context menu won't go away
  947. until you click something.
  948. -> was fixed by making the plugin window a child
  949. of m_hWndDesktopListView.
  950. */