Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
340 changes: 185 additions & 155 deletions Src/StartMenu/StartMenuDLL/ItemManager.cpp

Large diffs are not rendered by default.

11 changes: 7 additions & 4 deletions Src/StartMenu/StartMenuDLL/ItemManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class CItemManager
void ResetTempIcons( void );
void LoadCacheFile( void );
void SaveCacheFile( void );
void ClearCache( void );
bool ClearCache( void );

static int GetDPI( bool bOverride ) { return (bOverride && s_DPIOverride)?s_DPIOverride:s_DPI; }
static bool GetDPIOverride( void ) { return s_DPIOverride!=0; }
Expand Down Expand Up @@ -178,9 +178,10 @@ class CItemManager
const ItemInfo* GetLinkIcon(IShellLink* link, TIconSizeType iconSizeType);
const ItemInfo *GetMetroAppInfo10( const wchar_t *appid );
void UpdateItemInfo( const ItemInfo *pInfo, int refreshFlags, bool bHasWriteLock=false );
void WaitForShortcuts( const POINT &balloonPos );
bool IsTaskbarPinned( const wchar_t *appid );
void UpdateNewPrograms( const POINT &balloonPos );
void ResetNewPrograms( void );
bool AreShortcutsReady( void ) const;
void UpdateNewPrograms( void );
bool IsNewProgram( PIDLIST_ABSOLUTE pidl, bool bFolder, bool bMetroApp );
bool HasNewPrograms( bool bReal ) { return m_bHasNewPrograms[bReal?0:1]; }
bool HasNewApps( bool bReal ) { return m_bHasNewApps[bReal?0:1]; }
Expand Down Expand Up @@ -270,14 +271,16 @@ class CItemManager
HANDLE m_PreloadItemsThread;
HANDLE m_RefreshInfoThread;
HANDLE m_SaveCacheThread;
bool m_CacheCleared=false;
DWORD m_MainThreadId, m_PreloadItemsThreadId, m_RefreshInfoThreadId;

// per-thread info used to load icons
struct LoadIconData
{
int m_IconSizes[ICON_SIZE_COUNT];
HIMAGELIST m_TempLists[ICON_SIZE_COUNT];
HIMAGELIST m_TempLists[ICON_SIZE_COUNT]={};
CComPtr<IImageList2> m_pTempLists[ICON_SIZE_COUNT];
IImageList2 *GetTempList( int index );
CComPtr<IWICImagingFactory> m_pFactory;

void Init( void );
Expand Down
74 changes: 55 additions & 19 deletions Src/StartMenu/StartMenuDLL/MenuContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2015,8 +2015,6 @@ void CMenuContainer::GetRecentPrograms( std::vector<MenuItem> &items, int maxCou
// sort by rank
std::sort(uaItems.begin(),uaItems.end());

g_ItemManager.WaitForShortcuts(CPoint((s_StartRect.left+s_StartRect.right)/2,(s_StartRect.top+s_StartRect.bottom)/2));

// create a menu item for each program
for (int i=0;i<(int)uaItems.size();i++)
{
Expand Down Expand Up @@ -3284,22 +3282,8 @@ void CMenuContainer::InitWindowInternal( bool bDontShrink, const POINT &corner,
if (column==1 && columnWidths.size()==1)
columnWidths.push_back(0);
}
if (item.id!=MENU_RECENT && !(m_Options&CONTAINER_SEARCH) && s_Skin.bHasNewItem && i<m_OriginalCount)
{
if (item.id==MENU_PROGRAMS)
{
if (s_bWin7Style && GetWinVersion()>=WIN_VER_WIN8 && GetSettingBool(L"AllProgramsMetro"))
item.bNew=g_ItemManager.HasNewPrograms(false) || g_ItemManager.HasNewApps(false);
else
item.bNew=g_ItemManager.HasNewPrograms(false);
}
else if (item.id==MENU_APPS)
item.bNew=g_ItemManager.HasNewApps(false);
else if (item.bFolder)
item.bNew=(item.pItem1 && g_ItemManager.IsNewProgram(item.pItem1,true,false)) || (item.pItem2 && g_ItemManager.IsNewProgram(item.pItem2,true,false));
else if (item.pItemInfo)
item.bNew=(item.pItem1 && g_ItemManager.IsNewProgram(item.pItem1,false,item.bMetroApp));
}
if (i<m_OriginalCount)
item.bNew=IsNewMenuItem(item);
if (item.id==MENU_SHUTDOWN_BUTTON)
{
if (s_MenuMode==MODE_SEARCH)
Expand Down Expand Up @@ -5238,8 +5222,58 @@ LRESULT CMenuContainer::OnWorkAreaChanged( UINT uMsg, WPARAM wParam, LPARAM lPar
return 0;
}

bool CMenuContainer::IsNewMenuItem( const MenuItem &item ) const
{
if (item.id==MENU_RECENT || (m_Options&CONTAINER_SEARCH) || !s_Skin.bHasNewItem)
return false;
if (item.id==MENU_PROGRAMS)
return g_ItemManager.HasNewPrograms(false) ||
(s_bWin7Style && GetWinVersion()>=WIN_VER_WIN8 && GetSettingBool(L"AllProgramsMetro") && g_ItemManager.HasNewApps(false));
if (item.id==MENU_APPS)
return g_ItemManager.HasNewApps(false);
if (item.bFolder)
return (item.pItem1 && g_ItemManager.IsNewProgram(item.pItem1,true,false)) ||
(item.pItem2 && g_ItemManager.IsNewProgram(item.pItem2,true,false));
return item.pItemInfo && item.pItem1 && g_ItemManager.IsNewProgram(item.pItem1,false,item.bMetroApp);
}

void CMenuContainer::RefreshNewPrograms( void )
{
for (int i=0;i<m_OriginalCount && i<(int)m_Items.size();i++)
{
MenuItem &item=m_Items[i];
item.bNew=IsNewMenuItem(item);
// Update the drawing style without rebuilding or reselecting menu items.
switch (item.drawType)
{
case MenuSkin::PROGRAMS_BUTTON: item.drawType=item.bNew?MenuSkin::PROGRAMS_BUTTON_NEW:item.drawType; break;
case MenuSkin::PROGRAMS_CASCADING: item.drawType=item.bNew?MenuSkin::PROGRAMS_CASCADING_NEW:item.drawType; break;
case MenuSkin::COLUMN1_ITEM: item.drawType=item.bNew?MenuSkin::COLUMN1_NEW:item.drawType; break;
case MenuSkin::COLUMN2_ITEM: item.drawType=item.bNew?MenuSkin::COLUMN2_NEW:item.drawType; break;
case MenuSkin::SUBMENU_ITEM: item.drawType=item.bNew?MenuSkin::SUBMENU_NEW:item.drawType; break;
}
}
if (m_pProgramsTree && m_pProgramsTree->IsWindow())
m_pProgramsTree->RefreshNewPrograms();
Invalidate(FALSE);
}

LRESULT CMenuContainer::OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
if (wParam==TIMER_NEW_PROGRAMS)
{
if (!g_ItemManager.AreShortcutsReady()) return 0;
KillTimer(TIMER_NEW_PROGRAMS);
CComPtr<IDropTarget> keepAlive(static_cast<IDropTarget*>(this));
g_ItemManager.UpdateNewPrograms();
if (!m_bDestroyed)
{
for (CMenuContainer *menu : s_Menus)
if (!menu->m_bDestroyed) menu->RefreshNewPrograms();
}
return 0;
}

if (wParam==TIMER_HOVER)
{
LOG_MENU(LOG_MOUSE,L"End Hover, hover=%d%s, hot=%d, submenu=%d",m_HoverItem,m_bHoverArrow?L"(arrow)":L"",m_HotItem,m_Submenu);
Expand Down Expand Up @@ -8559,7 +8593,7 @@ HWND CMenuContainer::ToggleStartMenu( int taskbarId, bool bKeyboard, bool bAllPr

pStartMenu->InitItems();
pStartMenu->m_MaxWidth=s_MainMenuLimits.right-s_MainMenuLimits.left;
g_ItemManager.UpdateNewPrograms(CPoint((s_StartRect.left+s_StartRect.right)/2,(s_StartRect.top+s_StartRect.bottom)/2));
g_ItemManager.ResetNewPrograms();

pStartMenu->InitWindow();
pStartMenu->SetHotItem((bKeyboard && bAllPrograms)?0:-1);
Expand Down Expand Up @@ -8615,6 +8649,8 @@ HWND CMenuContainer::ToggleStartMenu( int taskbarId, bool bKeyboard, bool bAllPr
if (!bAllPrograms)
pStartMenu->SetHotItem(-1);
}
if (GetSettingBool(L"HighlightNew"))
pStartMenu->SetTimer(TIMER_NEW_PROGRAMS,100);
SetForegroundWindow(pStartMenu->m_hWnd);
SwitchToThisWindow(pStartMenu->m_hWnd,FALSE); // just in case
if (s_TaskBar && s_bBehindTaskbar)
Expand Down
3 changes: 3 additions & 0 deletions Src/StartMenu/StartMenuDLL/MenuContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,7 @@ class CMenuContainer: public IDropTarget, public IFrameworkInputPaneHandler, pub
TIMER_BALLOON_HIDE=6,
TIMER_SEARCH=7,
TIMER_DRAG=8,
TIMER_NEW_PROGRAMS=9,

MCM_REFRESH=WM_USER+10, // posted to force the container to refresh its contents
MCM_SETCONTEXTITEM=WM_USER+11, // sets the item for the context menu. wParam is the nameHash of the item
Expand Down Expand Up @@ -801,6 +802,8 @@ class CMenuContainer: public IDropTarget, public IFrameworkInputPaneHandler, pub
void InitItems( void );
bool InitSearchItems( void );
void InitWindow( bool bDontShrink=false );
bool IsNewMenuItem( const MenuItem &item ) const;
void RefreshNewPrograms( void );
void InitWindowInternal( bool bDontShrink, const POINT &corner, RECT &menuRect );
void InitWindowFinalize( const RECT &menuRect );

Expand Down
26 changes: 26 additions & 0 deletions Src/StartMenu/StartMenuDLL/ProgramsTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,32 @@ bool CProgramsTree::s_bFoldersFirst;

const wchar_t *ORDER_PREFIX=L"#";

void CProgramsTree::RefreshNewPrograms( void )
{
for (HTREEITEM node=TreeView_GetRoot(m_hWnd);node;)
{
TVITEM item={TVIF_PARAM};
item.hItem=node;
if (TreeView_GetItem(m_hWnd,&item) && item.lParam)
{
CTreeItem *data=reinterpret_cast<CTreeItem*>(item.lParam);
data->bNew=data->bApps?g_ItemManager.HasNewApps(false):
(data->pItemInfo1 && g_ItemManager.IsNewProgram(data->pItemInfo1->GetPidl(),data->bFolder,data->bApp)) ||
(data->pItemInfo2 && g_ItemManager.IsNewProgram(data->pItemInfo2->GetPidl(),data->bFolder,false));
}
HTREEITEM child=TreeView_GetChild(m_hWnd,node);
if (child)
node=child;
else
{
while (node && !TreeView_GetNextSibling(m_hWnd,node))
node=TreeView_GetParent(m_hWnd,node);
if (node) node=TreeView_GetNextSibling(m_hWnd,node);
}
}
Invalidate(FALSE);
}

CProgramsTree::CProgramsTree( void )
{
m_RefCount=1;
Expand Down
1 change: 1 addition & 0 deletions Src/StartMenu/StartMenuDLL/ProgramsTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class CProgramsTree: public IDropTarget, public CWindowImpl<CProgramsTree>
Assert(m_RefCount==0);
}
void Create( CMenuContainer *pOwner );
void RefreshNewPrograms( void );

virtual WNDPROC GetWindowProc( void ) { return CustomWindowProc; }
static LRESULT CALLBACK CustomWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
Expand Down
23 changes: 16 additions & 7 deletions Src/StartMenu/StartMenuDLL/SearchManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,29 @@ void CSearchManager::Init( void )
InitializeCriticalSection(&m_CriticalSections[i]);
m_SearchEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
m_ExitEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
for (int i=0;i<_countof(m_SearchThreads);i++)
m_SearchThreads[i]=CreateThread(NULL,0,StaticSearchThread,this,0,NULL);
if (m_SearchEvent && m_ExitEvent)
{
for (int i=0;i<_countof(m_SearchThreads);i++)
m_SearchThreads[i]=CreateThread(NULL,0,StaticSearchThread,this,0,NULL);
}
m_MainThreadId=GetCurrentThreadId();
LoadItemRanks();
}

void CSearchManager::Close( void )
{
if (!m_bInitialized) return;
SetEvent(m_ExitEvent);
WaitForMultipleObjects(_countof(m_SearchThreads),m_SearchThreads,TRUE,INFINITE);
CloseHandle(m_SearchEvent);
for (int i=0;i<_countof(m_SearchThreads);i++)
CloseHandle(m_SearchThreads[i]);
if (m_ExitEvent) SetEvent(m_ExitEvent);
for (HANDLE &thread : m_SearchThreads)
{
if (!thread) continue;
WaitForSingleObject(thread,INFINITE);
CloseHandle(thread);
thread=NULL;
}
if (m_SearchEvent) CloseHandle(m_SearchEvent);
if (m_ExitEvent) CloseHandle(m_ExitEvent);
m_SearchEvent=m_ExitEvent=NULL;
for (int i=0;i<LOCK_COUNT;i++)
DeleteCriticalSection(&m_CriticalSections[i]);
m_bInitialized=false;
Expand Down
4 changes: 3 additions & 1 deletion Src/StartMenu/StartMenuDLL/SettingsUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5148,7 +5148,9 @@ void MenuCustomSettings::ExecuteBackupMenu( int id )
{
if (id==m_FirstId)
{
g_ItemManager.ClearCache();
bool cleared=g_ItemManager.ClearCache();
MessageBox(GetActiveWindow(),LoadStringEx(cleared?IDS_CLEAR_CACHE_RESTART:IDS_CLEAR_CACHE_FAILED),
LoadStringEx(IDS_APP_TITLE),MB_OK|(cleared?MB_ICONINFORMATION:MB_ICONERROR));
}
}

Expand Down
2 changes: 2 additions & 0 deletions Src/StartMenu/StartMenuDLL/StartMenuDLL.rc
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,8 @@ BEGIN
IDS_SELECT_LAST "Select the last item in shutdown menu"
IDS_SELECT_LAST_TIP "When this is checked, the last item will be selected by default when the shutdown menu is opened with the keyboard"
IDS_CLEAR_CACHE "Clear cached information"
IDS_CLEAR_CACHE_RESTART "The saved cache has been cleared. Open-Shell will rebuild it the next time it starts."
IDS_CLEAR_CACHE_FAILED "Open-Shell could not clear the saved cache."
END

STRINGTABLE
Expand Down
2 changes: 2 additions & 0 deletions Src/StartMenu/StartMenuDLL/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,8 @@
#define IDS_STRING7109 7109
#define IDS_STRING7110 7110
#define IDS_STRING7111 7111
#define IDS_CLEAR_CACHE_RESTART 7112
#define IDS_CLEAR_CACHE_FAILED 7113

// Next default values for new objects
//
Expand Down