1097 lines
41 KiB
C++
1097 lines
41 KiB
C++
/*
|
|
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.
|
|
*/ |