12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097 |
- /*
- LICENSE
- -------
- Copyright 2005-2013 Nullsoft, Inc.
- All rights reserved.
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name of Nullsoft nor the names of its contributors may be used to
- endorse or promote products derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "api__vis_milk2.h"
- #include "pluginshell.h"
- #include "resource.h"
- #include "utility.h"
- #include "defines.h"
- #include <shellapi.h>
- //----------------------------------------------------------------------
- #define VMS_DESKTOP_DLLNAME (SUBDIR L"data\\vms_desktop.dll")
- //----------------------------------------------------------------------
- typedef struct _SIMPLEVERTEX
- {
- float x, y; // screen position
- float z; // Z-buffer depth
- DWORD Diffuse; // diffuse color. also acts as filler; aligns struct to 16 bytes (good for random access/indexed prims)
- } SIMPLEVERTEX, *LPSIMPLEVERTEX;
- typedef struct _HELPVERTEX
- {
- float x, y; // screen position
- float z; // Z-buffer depth
- DWORD Diffuse; // diffuse color. also acts as filler; aligns struct to 16 bytes (good for random access/indexed prims)
- float tu, tv; // texture coordinates for texture #0
- } HELPVERTEX, *LPHELPVERTEX;
- #define SIMPLE_VERTEX_FORMAT (D3DFVF_XYZ | D3DFVF_DIFFUSE)
- #define HELP_VERTEX_FORMAT (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
- //----------------------------------------------------------------------
- // resides in vms_desktop.dll/lib:
- int setHook(HWND hlv,HWND w,int version);
- void removeHook();
- //----------------------------------------------------------------------
- typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
- bool IsVistaOrLater()
- {
- // adapted from "Getting the System Version" on MSDN - http://msdn2.microsoft.com/en-us/library/ms724429.aspx
- OSVERSIONINFOEX osvi;
- SYSTEM_INFO si;
- PGNSI pGNSI;
- BOOL bOsVersionInfoEx;
- ZeroMemory(&si, sizeof(SYSTEM_INFO));
- ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
- if (bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi))
- {
- // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
- pGNSI = (PGNSI) GetProcAddress( GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo" );
- if(NULL != pGNSI)
- pGNSI(&si);
- else
- GetSystemInfo(&si);
- if ( VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && osvi.dwMajorVersion > 4 )
- {
- if ( osvi.dwMajorVersion >= 6 )
- return true;
- }
- }
- return false;
- }
- int CPluginShell::InitDesktopMode()
- {
- if (m_screenmode != DESKTOP)
- return false;
- // check for Vista - if Vista, don't try to draw desktop icons.
- // [ vms_desktop.dll's message posts to the desktop listview window cause explorer to crash...
- // whether it sends WM_NULL or WM_USER+516/517. ]
- if (m_desktop_show_icons && IsVistaOrLater())
- m_desktop_show_icons = false;
- if (!m_desktop_show_icons)
- return true;
- // note: we have to explicitly make sure the DLL is present,
- // since we're delay-loading it; otherwise, calling setHook, etc. will crash it.
- wchar_t szVmsDesktopDll[MAX_PATH];
- swprintf(szVmsDesktopDll, L"%s%s", GetPluginsDirPath(), VMS_DESKTOP_DLLNAME);
- if (!GetModuleHandleW(szVmsDesktopDll))
- {
- if (!LoadLibraryW(szVmsDesktopDll))
- {
- wchar_t buf[2048];
- swprintf(buf, WASABI_API_LNGSTRINGW(IDS_COULD_NOT_FIND_FILE_FOR_DESKTOP_MODE_X), szVmsDesktopDll);
- MessageBoxW(GetPluginWindow(),buf,WASABI_API_LNGSTRINGW(IDS_MILKDROP_ERROR_FILE_MISSING), MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- //return false;
- m_desktop_icons_disabled = 1;
- }
- else
- {
- m_vms_desktop_loaded = 1;
- }
- }
- InitializeCriticalSection(&m_desktop_cs);
- m_desktop_icon_state = 0;
- m_desktop_icon_count = 0;
- m_desktop_icon_update_frame = 0;
- m_desktop_icon_size = GetDesktopIconSize();
- // GDI font for desktop mode:
- LOGFONT lf = {0};
- wchar_t title[64];
- if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0))
- {
- if (!(m_font_desktop = CreateFontIndirect(&lf)))
- {
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_CREATING_GDI_DESKTOP_FONT),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return false;
- }
- }
- else
- {
- 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")))
- {
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_CREATING_GDI_DESKTOP_FONT),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return false;
- }
- }
- // Create D3DX font for drawing icon labels on desktop:
- 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)
- {
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_CREATING_DESKTOP_FONT),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return false;
- }
- // create first texture for holding icon bitmaps:
- // (do it now, to ensure that at least 1 gets created, before
- // the plugin does all of its DX9 allocations.)
- if (!CreateDesktopIconTexture(&m_desktop_icons_texture[0]))
- {
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_CREATING_TEXTURE_FOR_ICON_BITMAPS),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- }
-
- if (!m_desktop_icons_disabled)
- {
- int ret = setHook(m_hWndDesktopListView, GetPluginWindow(), 1);
- if (ret == 1)
- m_desktop_hook_set = 1;
- else if (ret == -1)
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_OUTDATED_VMS_DESKTOP_DLL_NEED_TO_REINSTALL),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- else
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_CREATING_HOOK_PROC_DESKTOP_ICONS_NOT_AVAILABLE),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- }
- return true;
- }
- //----------------------------------------------------------------------
- void CPluginShell::CleanUpDesktopMode()
- {
- if (m_screenmode != DESKTOP)
- return;
- if (!m_desktop_show_icons)
- return;
- if (m_desktop_hook_set)
- {
- m_desktop_hook_set = 0;
- removeHook();
- }
- for (int i=0; i<MAX_ICON_TEXTURES; i++)
- SafeRelease(m_desktop_icons_texture[i]);
- SafeRelease(m_d3dx_desktop_font);
- if (m_desktop_wc_registered)
- {
- UnregisterClass(DESKTOP_MODE_KEYBOARD_INPUT_WINDOW_CLASSNAME, m_hInstance);
- m_desktop_wc_registered = 0;
- }
- if (m_font_desktop)
- {
- DeleteObject(m_font_desktop);
- m_font_desktop = 0;
- }
- m_icon_list.clear();
- DeleteCriticalSection(&m_desktop_cs);
- if (m_vms_desktop_loaded)
- {
- char szVmsDesktopDll[MAX_PATH];
- sprintf(szVmsDesktopDll, "%s%s", GetPluginsDirPath(), VMS_DESKTOP_DLLNAME);
- FreeLibrary(GetModuleHandle(szVmsDesktopDll));
- m_vms_desktop_loaded = 0;
- }
- }
- //----------------------------------------------------------------------
- int CPluginShell::CreateDesktopIconTexture(IDirect3DTexture9** ppTex)
- {
- // release old texture (shouldn't really be necessary)
- if (*ppTex)
- {
- (*ppTex)->Release();
- *ppTex = NULL;
- }
- // create new
- int ntries = (m_lpDX->m_d3dpp.BackBufferFormat == D3DFMT_R5G6B5) ? 3 : 1;
- for (int ntry=0; ntry<ntries; ntry++)
- {
- D3DFORMAT fmt = m_lpDX->m_d3dpp.BackBufferFormat;
- switch(m_lpDX->m_d3dpp.BackBufferFormat)
- {
- case D3DFMT_R8G8B8:
- case D3DFMT_X8R8G8B8:
- fmt = D3DFMT_A8R8G8B8;
- break;
- case D3DFMT_R5G6B5: // <- PROBLEM: NO ALPHA CHANNEL FOR ICONS
- if (ntry==0)
- switch(m_desktop_555_fix)
- {
- case 0: fmt = D3DFMT_R5G6B5; break;
- case 1: fmt = D3DFMT_A1R5G5B5; break;
- case 2: fmt = D3DFMT_A8R8G8B8; break;
- }
- else if (ntry==1)
- switch(m_desktop_555_fix)
- {
- case 0: fmt = D3DFMT_A1R5G5B5; break;
- case 1: fmt = D3DFMT_A8R8G8B8; break;
- case 2: fmt = D3DFMT_A1R5G5B5; break;
- }
- else
- switch(m_desktop_555_fix)
- {
- case 0: fmt = D3DFMT_A8R8G8B8; break;
- case 1: fmt = D3DFMT_R5G6B5; break;
- case 2: fmt = D3DFMT_R5G6B5; break;
- }
- break;
- case D3DFMT_X1R5G5B5:
- fmt = D3DFMT_A1R5G5B5;
- break;
- }
- if (m_lpDX->m_lpDevice->CreateTexture(ICON_TEXTURE_SIZE, ICON_TEXTURE_SIZE, 1, 0, fmt, D3DPOOL_MANAGED, ppTex, NULL) != D3D_OK)
- *ppTex = NULL;
- else
- break;
- }
- return (*ppTex) ? 1 : 0;
- }
- //----------------------------------------------------------------------
- void CPluginShell::DeselectDesktop()
- {
- IconList::iterator p;
- for (p = m_icon_list.begin(); p != m_icon_list.end(); p++)
- p->selected = 0;
- }
- //----------------------------------------------------------------------
- void CPluginShell::UpdateDesktopBitmaps()
- {
- // update the D3DX textures that hold all the icons:
-
- int idx = 0;
- int texnum = 0;
- int show_msgs = 1;
- // if no icon texture could be created at startup,
- // don't bother trying anything here, and don't give them
- // any extra error messages.
- if (!m_desktop_icons_texture[0])
- return;
- IconList::iterator p;
- for (p = m_icon_list.begin(); p != m_icon_list.end(); p++)
- p->icon_bitmap_idx = -1;
-
- do
- {
- idx = StuffIconBitmaps(idx, texnum++, &show_msgs);
- }
- while (idx > 0 && texnum < MAX_ICON_TEXTURES);
- if (idx > 0)
- {
- wchar_t title[64];
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_WARNING, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- }
- }
- //----------------------------------------------------------------------
- int CPluginShell::StuffIconBitmaps(int iStartIconIdx, int iTexNum, int *show_msgs)
- {
- // returns:
- // 0 if done (or error), or
- // N if the texture is full & we need to start another one,
- // where N is the new iStartIconIdx to use.
- if (m_screenmode != DESKTOP)
- return 0;
- wchar_t title[64];
- if (!m_desktop_icons_texture[iTexNum])
- {
- int ret = CreateDesktopIconTexture(&m_desktop_icons_texture[iTexNum]);
- if (!ret)
- {
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_TOO_MANY_UNIQUE_ICON_BITMAPS),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_WARNING, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return 0;
- }
- }
- D3DSURFACE_DESC sd;
- if (m_desktop_icons_texture[iTexNum]->GetLevelDesc(0, &sd) != D3D_OK)
- {
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_COULD_NOT_GET_LEVEL_DESCRIPTION),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return 0;
- }
- D3DLOCKED_RECT lr;
- if (m_desktop_icons_texture[iTexNum]->LockRect(0, &lr, NULL, 0) != D3D_OK)
- {
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_LOCKRECT_FAILED),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return 0;
- }
- if (lr.pBits == NULL)
- {
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_LR_PBITS_IS_NULL),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- m_desktop_icons_texture[iTexNum]->UnlockRect(0);
- return 0;
- }
- unsigned __int16* p16 = (unsigned __int16*)lr.pBits;
- unsigned __int32* p32 = (unsigned __int32*)lr.pBits;
- int WIDTH = sd.Width;
- int i;
- int start;
- int bpp;
- int rshift[3]; // 1. bits to first shift right r,g,b
- int mask[3]; // 2. mask for r, g, b
- int lshift[3]; // 3. bits to then shift left r,g,b
- switch(sd.Format)
- {
- case D3DFMT_R8G8B8:
- case D3DFMT_A8R8G8B8:
- case D3DFMT_X8R8G8B8:
- start = 0xFF000000;
- bpp = 32;
- rshift[0] = 0;
- rshift[1] = 0;
- rshift[2] = 0;
- mask[0] = 0xFF;
- mask[1] = 0xFF;
- mask[2] = 0xFF;
- lshift[0] = 16;
- lshift[1] = 8;
- lshift[2] = 0;
- break;
- case D3DFMT_R5G6B5:
- start = 0x0000;
- bpp = 16;
- rshift[0] = 3;
- rshift[1] = 2;
- rshift[2] = 3;
- mask[0] = 0x1F;
- mask[1] = 0x3F;
- mask[2] = 0x1F;
- lshift[0] = 11;
- lshift[1] = 5;
- lshift[2] = 0;
- break;
- case D3DFMT_X1R5G5B5:
- case D3DFMT_A1R5G5B5:
- start = 0x8000;
- bpp = 16;
- rshift[0] = 3;
- rshift[1] = 3;
- rshift[2] = 3;
- mask[0] = 0x1F;
- mask[1] = 0x1F;
- mask[2] = 0x1F;
- lshift[0] = 10;
- lshift[1] = 5;
- lshift[2] = 0;
- break;
- case D3DFMT_A4R4G4B4:
- start = 0xF000;
- bpp = 16;
- rshift[0] = 4;
- rshift[1] = 4;
- rshift[2] = 4;
- mask[0] = 0x0F;
- mask[1] = 0x0F;
- mask[2] = 0x0F;
- lshift[0] = 8;
- lshift[1] = 4;
- lshift[2] = 0;
- break;
- default:
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_UNKNOWN_PIXEL_FORMAT),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- m_desktop_icons_texture[iTexNum]->UnlockRect(0);
- return 0;
- }
- HDC hdc = GetDC(NULL);
- if (!hdc)
- {
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_COULDNT_GET_HDC),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- m_desktop_icons_texture[iTexNum]->UnlockRect(0);
- return 0;
- }
- #define MAX_ICON_SIZE 128
- unsigned char data[MAX_ICON_SIZE*MAX_ICON_SIZE*4];
- int nAcross = ICON_TEXTURE_SIZE/m_desktop_icon_size;
- int nDown = ICON_TEXTURE_SIZE/m_desktop_icon_size;
- // for each icon, add its bitmap to the texture (if not already there),
- // and set 'icon_bitmap_idx'.
- IconList::iterator p = m_icon_list.begin();
- for (i=0; i < iStartIconIdx; i++)
- p++;
- int bitmap_idx = 0;
- int list_idx = iStartIconIdx;
- for ( ; p != m_icon_list.end() && bitmap_idx < nAcross*nDown; p++)
- {
- // note: 'p' points to the correct icon to start with,
- // but 'idx' starts at zero!
-
- // get the icon:
- SHFILEINFO sfi;
- int flags = SHGFI_ICON|SHGFI_PIDL|SHGFI_SHELLICONSIZE | ((m_desktop_icon_size > 32) ? SHGFI_LARGEICON : 0);
- if (SHGetFileInfo((LPCTSTR)p->pidl, 0, &sfi, sizeof(sfi), flags))
- {
- ICONINFO ii;
- if (GetIconInfo(sfi.hIcon, &ii))
- {
- int x0 = (bitmap_idx%nAcross)*m_desktop_icon_size;
- int y0 = (bitmap_idx/nAcross)*m_desktop_icon_size;
- int checksum[3] = { 0, 0, 0 };
- BITMAPINFO bmi;
- // pass 1: get the colors
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = m_desktop_icon_size;
- bmi.bmiHeader.biHeight = m_desktop_icon_size;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- if (GetDIBits(
- hdc, // handle to DC
- ii.hbmColor, // handle to bitmap
- 0, // first scan line to set
- m_desktop_icon_size,// number of scan lines to copy
- data, // array for bitmap bits
- &bmi, // bitmap data buffer
- DIB_RGB_COLORS // RGB or palette index
- ))
- {
- int w = min(bmi.bmiHeader.biWidth , m_desktop_icon_size);
- int h = min(bmi.bmiHeader.biHeight, m_desktop_icon_size);
- for (int y=0; y<h; y++)
- for (int x=0; x<w; x++)
- {
- int in_offset = ((h-1-y)*w + x)*4;
- int r = data[in_offset+2];
- int g = data[in_offset+1];
- int b = data[in_offset+0];
- checksum[0] += r;
- checksum[1] += g;
- checksum[2] += b;
-
- int out_offset = (y0+y)*WIDTH + (x0+x);
- if (bpp==16)
- p16[out_offset] = start |
- (((r >> rshift[0]) & mask[0]) << lshift[0]) |
- (((g >> rshift[1]) & mask[1]) << lshift[1]) |
- (((b >> rshift[2]) & mask[2]) << lshift[2]);
- else
- p32[out_offset] = start |
- (((r >> rshift[0]) & mask[0]) << lshift[0]) |
- (((g >> rshift[1]) & mask[1]) << lshift[1]) |
- (((b >> rshift[2]) & mask[2]) << lshift[2]);
- }
- }
- else
- {
- if (*show_msgs)
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_CALL_TO_GETDIBITS_FAILED),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- *show_msgs = 0;
- }
- // pass 2: get the alpha mask
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = m_desktop_icon_size;
- bmi.bmiHeader.biHeight = m_desktop_icon_size;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- if (GetDIBits(
- hdc, // handle to DC
- ii.hbmMask, // handle to bitmap
- 0, // first scan line to set
- m_desktop_icon_size,// number of scan lines to copy
- data, // array for bitmap bits
- &bmi, // bitmap data buffer
- DIB_RGB_COLORS // RGB or palette index
- ))
- {
- int w = min(bmi.bmiHeader.biWidth , m_desktop_icon_size);
- int h = min(bmi.bmiHeader.biHeight, m_desktop_icon_size);
- for (int y=0; y<h; y++)
- for (int x=0; x<w; x++)
- {
- int in_offset = ((h-1-y)*w + x)*4;
- int r = data[in_offset+2];
- int g = data[in_offset+1];
- int b = data[in_offset+0];
- checksum[0] += r;
- checksum[1] += g;
- checksum[2] += b;
- if (r || g || b)
- {
- int out_offset = (y0+y)*WIDTH + (x0+x);
- if (bpp==16)
- p16[out_offset] &= ~start;
- else
- p32[out_offset] &= ~start;
- }
- }
- }
- else
- {
- if (*show_msgs)
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_CALL_2_TO_GETDIBITS_FAILED),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- *show_msgs = 0;
- }
- // check for duplicate icon, and if found, reuse it
- int done = 0;
- IconList::iterator q;
- for (q = m_icon_list.begin(); q != m_icon_list.end() && q != p; q++)
- {
- if (checksum[0] == q->checksum[0] &&
- checksum[1] == q->checksum[1] &&
- checksum[2] == q->checksum[2])
- {
- p->icon_bitmap_idx = q->icon_bitmap_idx;
- done = 1;
- break;
- }
- }
- // otherwise, keep new icon
- if (!done)
- {
- p->icon_bitmap_idx = nAcross*nDown*iTexNum + bitmap_idx;
- p->checksum[0] = checksum[0];
- p->checksum[1] = checksum[1];
- p->checksum[2] = checksum[2];
- bitmap_idx++;
- }
- DeleteObject(ii.hbmMask);
- DeleteObject(ii.hbmColor);
- }
- else
- {
- if (*show_msgs)
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_GETICONINFO_FAILED),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- *show_msgs = 0;
- }
- DestroyIcon(sfi.hIcon);
- }
- else
- {
- if (*show_msgs)
- MessageBoxW(GetPluginWindow(), WASABI_API_LNGSTRINGW(IDS_ERROR_UPDATING_ICON_BITMAPS_SHGETFILEINFO_FAILED),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- *show_msgs = 0;
- }
- list_idx++;
- }
- ReleaseDC(NULL, hdc);
- m_desktop_icons_texture[iTexNum]->UnlockRect(0);
- if (bitmap_idx >= nAcross*nDown)
- return list_idx;
- else
- return 0; // all done
- }
- //----------------------------------------------------------------------
- void CPluginShell::RenderDesktop()
- {
- if (m_screenmode != DESKTOP)
- return;
- if (!m_desktop_show_icons)
- return;
- if (m_desktop_icons_disabled)
- return;
- IconList::iterator p;
- EnterCriticalSection(&m_desktop_cs);
- int iconcount = static_cast<unsigned long>(SendMessage(m_hWndDesktopListView, LVM_GETITEMCOUNT, 0, 0));
- if (iconcount == 0)
- {
- LeaveCriticalSection(&m_desktop_cs);
- return;
- }
- // if the icons list is empty,
- // or if we check it for consistency and an update is recommended (GetDesktopIcons(1)==2),
- // update the icons list & the bitmaps:
- /*if (m_icon_list.size()==0 || GetDesktopIcons(1)==2)
- {
- m_icon_list.clear();
- GetDesktopIcons(0);
- UpdateDesktopBitmaps();
- }*/
- // check for invalid entries. (if there is an error in getItemData(),
- // it will return the icon_t structure anyway, but with empty strings.)
- int invalid_entries = 0;
- if (m_desktop_icon_state >= 2)
- {
- for (p = m_icon_list.begin(); p != m_icon_list.end() && !invalid_entries; p++)
- {
- if (p->name[0]==0)
- invalid_entries = 1;
- //if (p->pidl[0].mkid.cb==0 && p->pidl[0].mkid.abID[0]==0)
- if (p->pidl[0]==0 && p->pidl[1]==0)
- invalid_entries = 1;
- }
- }
- if (
- (m_desktop_icon_state == 0) ||
- (m_desktop_icon_state >= 2 && m_desktop_icon_count != iconcount) ||
- (m_desktop_icon_state >= 2 && invalid_entries)
- )
- {
- // begin total refresh
- m_desktop_icon_state = 1;
- m_desktop_icon_count = iconcount;
- m_desktop_icon_update_frame = GetFrame();
- m_icon_list.clear();
- SendMessage(GetPluginWindow(), WM_USER, 0x80000000 | iconcount, 0);//getItemData(i);
- // try to get the desktop window's listview to respond to
- // the queries as quickly as possible:
- {
- LeaveCriticalSection(&m_desktop_cs);
-
- DWORD procid = NULL;
- DWORD threadid = GetWindowThreadProcessId(m_hWndDesktopListView, &procid);
-
- HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION, FALSE, procid);
- DWORD x = GetPriorityClass(hProcess);
- if (x) SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);
-
- for (int i=0; i<5; i++)
- {
- Sleep(10);
- MSG msg;
- while(PeekMessage(&msg,GetPluginWindow(),0,0,PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- if (x) SetPriorityClass(hProcess, x);
- CloseHandle(hProcess);
-
- EnterCriticalSection(&m_desktop_cs);
- }
- }
- else if (m_desktop_icon_state == 1 &&
- m_icon_list.size() < (size_t)m_desktop_icon_count)
- {
- // waiting for the 'total refresh' to complete
- // ...
- if (GetFrame() > m_desktop_icon_update_frame+64)
- {
- m_desktop_icon_state = 0;
- }
- }
- else
- if (m_desktop_icon_state == 1 &&
- m_icon_list.size() == m_desktop_icon_count)
- {
- // done with total refresh
- m_desktop_icon_state = 2;
- m_desktop_icon_update_frame = GetFrame();
- UpdateDesktopBitmaps();
- }
- else if (m_desktop_icon_state == 2)
- {
- if (GetFrame() > m_desktop_icon_update_frame+4)
- {
- m_desktop_icon_state = 3; // will mean we're waiting on data to return.
- m_desktop_icon_update_frame = GetFrame();
- int start = 0;
- int len = iconcount;
- SendMessage(GetPluginWindow(), WM_USER, start | (len << 16), 0);//getItemData(i);
- }
- }
- else if (m_desktop_icon_state == 3)
- {
- if (GetFrame() > m_desktop_icon_update_frame+64)
- {
- // timeout; give up waiting for update message to come back,
- // and just request another.
- m_desktop_icon_state = 2;
- m_desktop_icon_update_frame = GetFrame();
- }
- }
- // get horz. spacing between icons (...determines width of labels)
- ICONMETRICS icm;
- icm.cbSize = sizeof(icm);
- if (!SystemParametersInfo(SPI_GETICONMETRICS, sizeof(icm), &icm, 0))
- icm.iHorzSpacing = 68;
- /*int font_height = 0;
- {
- RECT r;
- m_d3dx_desktop_font->DrawText(NULL, "M", -1, &r, DT_CALCRECT, 0xFFFFFFFF);
- font_height = r.bottom - r.top;
- }*/
- // display the desktop.
- m_lpDX->m_lpDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
- m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
- m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
- m_lpDX->m_lpDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
- m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);//D3DTOP_SELECTARG1 );
- m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
- m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
- m_lpDX->m_lpDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- int nAcross = ICON_TEXTURE_SIZE/m_desktop_icon_size;
- int nDown = ICON_TEXTURE_SIZE/m_desktop_icon_size;
- // The icon's x and y coordinates (as returned by the
- // getIconData/WM_COPYDATA system) are (0,0) at the
- // upper-left corner of the rectangle that encompasses
- // all the monitors together (m_lpDX->m_all_monitors_rect).
- // Note that in 'm_all_monitors_rect', (0,0) represents
- // the upper-left corner of the PRIMARY DISPLAY - not necessarily
- // the one we're showing the fake desktop on.
- // What we have to do here is determine icon_dx and icon_dy,
- // which are the transformation from the coordinate space used
- // by the desktop itself (as returned in WM_COPYDATA)
- // and the coordinates used by Windows itself (where 0,0 is
- // the upper-left corner of the PRIMARY DISPLAY, and coordinates
- // in other displays can be negative if they are above/left of it).
- int upperleft_x = min(m_lpDX->m_all_monitors_rect.left, m_lpDX->m_monitor_rect.left);
- int upperleft_y = min(m_lpDX->m_all_monitors_rect.top , m_lpDX->m_monitor_rect.top );
- int icon_dx = m_lpDX->m_monitor_rect.left - upperleft_x; // subtract this amount
- int icon_dy = m_lpDX->m_monitor_rect.top - upperleft_y; // subtract this amount
- if (!m_desktop_manual_icon_scoot)
- {
- icon_dx -= m_lpDX->m_monitor_rect.left - m_lpDX->m_monitor_work_rect.left;
- icon_dy -= m_lpDX->m_monitor_rect.top - m_lpDX->m_monitor_work_rect.top ;
- }
- // pass 0: draw normal text & icons
- // pass 1: redraw icon currently being dragged, transparently
- int nPasses = m_desktop_dragging ? 2 : 1;
- for (int pass=0; pass<nPasses; pass++)
- {
- // first, draw [blue backgrounds &] text labels
- {
- m_lpDX->m_lpDevice->SetVertexShader( NULL );
- m_lpDX->m_lpDevice->SetFVF( SIMPLE_VERTEX_FORMAT );
- m_lpDX->m_lpDevice->SetTexture(0, NULL);
- SIMPLEVERTEX verts[4];
- // pass2==0: draw text labels
- // pass2==1: draw text overtop
- // (separated for speed, so ID3DXFont can get the HDC just once for all the DrawText calls)
- for (int pass2=0; pass2<2; pass2++)
- {
- //if (pass2==1)
- //m_d3dx_desktop_font->Begin();
- for (p = m_icon_list.begin(); p != m_icon_list.end(); p++)
- {
- if (pass==0 || (p->selected && m_desktop_dragging))
- {
- int max_width = icm.iHorzSpacing-5+m_desktop_icon_size-32;//icm.iHorzSpacing-5;
- int dx = 0;
- int dy = 4;
- if (pass>0)
- {
- dx += m_desktop_drag_curpos.x - m_desktop_drag_startpos.x;
- dy += m_desktop_drag_curpos.y - m_desktop_drag_startpos.y;
- }
- SetRect(&p->label_rect,
- p->x + m_desktop_icon_size/2 - icon_dx - max_width/2 + dx,
- p->y + m_desktop_icon_size - icon_dy + dy,
- p->x + m_desktop_icon_size/2 - icon_dx + max_width/2 + dx,
- p->y + m_desktop_icon_size - icon_dy + 0 + dy // will be extended by DT_CALCRECT step!
- );
- // calculate rect for the text label
- DWORD style = DT_CENTER|DT_WORDBREAK|DT_END_ELLIPSIS|DT_WORD_ELLIPSIS;
- // these aren't supported by D3DX9:
- style &= ~(DT_WORD_ELLIPSIS | DT_END_ELLIPSIS | DT_NOPREFIX);
- m_d3dx_desktop_font->DrawText(NULL, p->name, -1, &p->label_rect, style|DT_CALCRECT, 0xFFFFFFFF);
- // D3DX doesn't handle text so well if it goes off
- // the left edge of the screen, so don't show text labels
- // that are mostly off (on the left side):
- if ((p->label_rect.left + p->label_rect.right)/2 > 0)
- {
- // also, if label would go off left edge of screen,
- // push it to the right:
- if (p->label_rect.left < 0 && p->label_rect.right > 0)
- {
- p->label_rect.right -= p->label_rect.left;
- p->label_rect.left = 0;
- }
- //if (p->selected) // ...draw blue background around text label
- if (pass2==0)
- {
- if (m_desktop_textlabel_boxes || p->selected)
- {
- #define EXTEND_LEFT 3
- #define EXTEND_RIGHT 2
- #define EXTEND_TOP 0
- #define EXTEND_BOTTOM 2
- for (int i=0; i<4; i++)
- {
- 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
- 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
- verts[i].z = 0;
- verts[i].Diffuse = (p->selected) ? m_desktop_sel_color : m_desktop_bk_color;//0xFF000000;
- if (pass>0)
- verts[i].Diffuse &= 0x7FFFFFFF;
- }
- m_lpDX->m_lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, verts, sizeof(SIMPLEVERTEX));
- }
- }
- else
- {
- DWORD text_color = (p->selected) ? m_desktop_sel_text_color : m_desktop_text_color;
- if (pass==1)
- text_color &= 0x7FFFFFFF;
- // these aren't supported by D3DX9:
- style &= ~(DT_WORD_ELLIPSIS | DT_END_ELLIPSIS | DT_NOPREFIX);
- m_d3dx_desktop_font->DrawText(NULL, p->name, -1, &p->label_rect, style, text_color);
- }
- }
- }
- }
- //if (pass2==1)
- // m_d3dx_desktop_font->End();
- }
- }
- m_lpDX->m_lpDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
- m_lpDX->m_lpDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
- m_lpDX->m_lpDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
-
- // second, draw icon bitmaps (overtop)
- if (m_desktop_icon_state >= 2)
- {
- int dx = 0;
- int dy = 0;
- int iTexNum = 0;
-
- while (m_desktop_icons_texture[iTexNum] && iTexNum < MAX_ICON_TEXTURES)
- {
- HELPVERTEX verts[4];
- m_lpDX->m_lpDevice->SetVertexShader( NULL );
- m_lpDX->m_lpDevice->SetFVF( HELP_VERTEX_FORMAT );
- m_lpDX->m_lpDevice->SetTexture(0, m_desktop_icons_texture[iTexNum]);
- for (p = m_icon_list.begin(); p != m_icon_list.end(); p++)
- {
- int icon_tex_idx = (p->icon_bitmap_idx==-1) ? 0 : (p->icon_bitmap_idx / (nAcross*nDown));
- int icon_bitmap_idx = (p->icon_bitmap_idx==-1) ? 0 : (p->icon_bitmap_idx % (nAcross*nDown));
- if (
- (icon_tex_idx == iTexNum) &&
- (pass==0 || (p->selected && m_desktop_dragging))
- )
- {
- SetRect(&p->icon_rect,
- p->x - icon_dx + dx,
- p->y - icon_dy + dy,
- p->x - icon_dx + dx + m_desktop_icon_size,
- p->y - icon_dy + dy + m_desktop_icon_size);
- int lookup_x = 0;
- int lookup_y = 0;
- if (icon_bitmap_idx >= 0) // if -1, means icon didn't fit in the texture
- {
- lookup_x = icon_bitmap_idx % nAcross;
- lookup_y = icon_bitmap_idx / nAcross;
- }
- for (int i=0; i<4; i++)
- {
- 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 );
- 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);
- verts[i].z = 0;
- verts[i].tu = ((lookup_x + i%2)*m_desktop_icon_size + 0.5f)/(float)ICON_TEXTURE_SIZE;
- verts[i].tv = ((lookup_y + i/2)*m_desktop_icon_size + 0.5f)/(float)ICON_TEXTURE_SIZE;
- verts[i].Diffuse = (p->selected) ? m_desktop_sel_color : 0xFFFFFFFF;
- if (pass>0)
- {
- verts[i].x += m_desktop_drag_curpos.x - m_desktop_drag_startpos.x;
- verts[i].y -= m_desktop_drag_curpos.y - m_desktop_drag_startpos.y;
- verts[i].Diffuse &= 0x7FFFFFFF;
- }
- }
- m_lpDX->m_lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, verts, sizeof(HELPVERTEX));
- }
- }
- iTexNum++;
- }
- }
- }
- // finally, draw selection box (if user is dragging one)
- if (m_desktop_box)
- {
- m_lpDX->m_lpDevice->SetVertexShader( NULL );
- m_lpDX->m_lpDevice->SetFVF( SIMPLE_VERTEX_FORMAT );
- m_lpDX->m_lpDevice->SetTexture(0, NULL);
- SIMPLEVERTEX verts[5];
- for (int i=0; i<4; i++)
- {
- 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);
- 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);
- verts[i].z = 0;
- verts[i].Diffuse = 0x80FFFFFF;
- }
- verts[4] = verts[0];
- m_lpDX->m_lpDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, 4, verts, sizeof(SIMPLEVERTEX));
- }
- m_lpDX->m_lpDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
- m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
- m_lpDX->m_lpDevice->SetTexture(0, NULL);
- LeaveCriticalSection(&m_desktop_cs);
- }
- //----------------------------------------------------------------------
- /*
- NOTES LOG
- -problem: you can't click on the 1st monitor's desktop & do stuff
- -> fixed if you get rid of m_desktop_focuswnd and
- don't block WM_MOUSEACTIVATE.
- -> but doing this causes a flash when you click on
- the real desktop (in multimon setup) of any windows
- that are overtop of the fake desktop, since the
- fake desktop rises up in the Z order (activates)
- and then, next frame, gets pushed back again.
- -> so how do we avoid the flash?
- by [conditionally] stopping any z-order changes;
- intercept & change WM_WINDOWPOSCHANGING messages
- so there's no z-change, unless *we* specifically
- requested it (in PushWindowToBack()).
- -> new problem: right-click context menu won't go away
- until you click something.
- -> was fixed by making the plugin window a child
- of m_hWndDesktopListView.
- */
|