https://git.reactos.org/?p=reactos.git;a=commitdiff;h=74e58d938eade6b2412f8…
commit 74e58d938eade6b2412f828289b81776a83af534
Author: David Quintana <gigaherz(a)gmail.com>
AuthorDate: Tue Jan 16 22:11:14 2018 +0100
Commit: Giannis Adamopoulos <gadamopoulos(a)reactos.org>
CommitDate: Thu Jan 18 02:20:20 2018 +0200
[EXPLORER] Fix some issues with the notification area code,
and implement NIS_SHAREDICON while at it.
---
base/shell/explorer/trayntfy.cpp | 177 +++++++++++++++++++++++++++++----------
1 file changed, 131 insertions(+), 46 deletions(-)
diff --git a/base/shell/explorer/trayntfy.cpp b/base/shell/explorer/trayntfy.cpp
index 95c40aa723..c6bea2976e 100644
--- a/base/shell/explorer/trayntfy.cpp
+++ b/base/shell/explorer/trayntfy.cpp
@@ -77,16 +77,41 @@ public:
return -1;
}
+ int FindExistingSharedIcon(HICON handle)
+ {
+ int count = GetButtonCount();
+ for (int i = 0; i < count; i++)
+ {
+ NOTIFYICONDATA * data = GetItemData(i);
+ if (data->hIcon == handle)
+ {
+ TBBUTTON btn;
+ GetButton(i, &btn);
+ return btn.iBitmap;
+ }
+ }
+
+ return -1;
+ }
+
BOOL AddButton(IN CONST NOTIFYICONDATA *iconData)
{
TBBUTTON tbBtn;
NOTIFYICONDATA * notifyItem;
WCHAR text[] = L"";
+ TRACE("Adding icon %d from hWnd %08x flags%s%s state%s%s",
+ iconData->uID, iconData->hWnd,
+ (iconData->uFlags & NIF_ICON) ? " ICON" : "",
+ (iconData->uFlags & NIF_STATE) ? " STATE" : "",
+ (iconData->dwState & NIS_HIDDEN) ? " HIDDEN" :
"",
+ (iconData->dwState & NIS_SHAREDICON) ? " SHARED" :
"");
+
int index = FindItemByIconData(iconData, ¬ifyItem);
if (index >= 0)
{
- return UpdateButton(iconData);
+ TRACE("Icon %d from hWnd %08x ALREADY EXISTS!", iconData->uID,
iconData->hWnd);
+ return FALSE;
}
notifyItem = new NOTIFYICONDATA();
@@ -101,6 +126,11 @@ public:
tbBtn.iString = (INT_PTR) text;
tbBtn.idCommand = GetButtonCount();
+ if (iconData->uFlags & NIF_STATE)
+ {
+ notifyItem->dwState = iconData->dwState &
iconData->dwStateMask;
+ }
+
if (iconData->uFlags & NIF_MESSAGE)
{
notifyItem->uCallbackMessage = iconData->uCallbackMessage;
@@ -108,8 +138,22 @@ public:
if (iconData->uFlags & NIF_ICON)
{
- notifyItem->hIcon = (HICON)CopyImage(iconData->hIcon, IMAGE_ICON, 0, 0,
0);
- tbBtn.iBitmap = ImageList_AddIcon(m_ImageList, iconData->hIcon);
+ notifyItem->hIcon = iconData->hIcon;
+ BOOL hasSharedIcon = notifyItem->dwState & NIS_SHAREDICON;
+ if (hasSharedIcon)
+ {
+ INT iIcon = FindExistingSharedIcon(notifyItem->hIcon);
+ if (iIcon < 0)
+ {
+ notifyItem->hIcon = NULL;
+ TRACE("Shared icon requested, but HICON not found!!!");
+ }
+ tbBtn.iBitmap = iIcon;
+ }
+ else
+ {
+ tbBtn.iBitmap = ImageList_AddIcon(m_ImageList, notifyItem->hIcon);
+ }
}
if (iconData->uFlags & NIF_TIP)
@@ -118,15 +162,10 @@ public:
}
m_VisibleButtonCount++;
- if (iconData->uFlags & NIF_STATE)
+ if (notifyItem->dwState & NIS_HIDDEN)
{
- notifyItem->dwState &= ~iconData->dwStateMask;
- notifyItem->dwState |= (iconData->dwState &
iconData->dwStateMask);
- if (notifyItem->dwState & NIS_HIDDEN)
- {
- tbBtn.fsState |= TBSTATE_HIDDEN;
- m_VisibleButtonCount--;
- }
+ tbBtn.fsState |= TBSTATE_HIDDEN;
+ m_VisibleButtonCount--;
}
/* TODO: support NIF_INFO, NIF_GUID, NIF_REALTIME, NIF_SHOWTIP */
@@ -142,34 +181,28 @@ public:
NOTIFYICONDATA * notifyItem;
TBBUTTONINFO tbbi = { 0 };
+ TRACE("Updating icon %d from hWnd %08x flags%s%s state%s%s",
+ iconData->uID, iconData->hWnd,
+ (iconData->uFlags & NIF_ICON) ? " ICON" : "",
+ (iconData->uFlags & NIF_STATE) ? " STATE" : "",
+ (iconData->dwState & NIS_HIDDEN) ? " HIDDEN" :
"",
+ (iconData->dwState & NIS_SHAREDICON) ? " SHARED" :
"");
+
int index = FindItemByIconData(iconData, ¬ifyItem);
if (index < 0)
{
+ WARN("Icon %d from hWnd %08x DOES NOT EXIST!", iconData->uID,
iconData->hWnd);
return AddButton(iconData);
}
+ TBBUTTON btn;
+ GetButton(index, &btn);
+ int oldIconIndex = btn.iBitmap;
+
tbbi.cbSize = sizeof(tbbi);
tbbi.dwMask = TBIF_BYINDEX | TBIF_COMMAND;
tbbi.idCommand = index;
- if (iconData->uFlags & NIF_MESSAGE)
- {
- notifyItem->uCallbackMessage = iconData->uCallbackMessage;
- }
-
- if (iconData->uFlags & NIF_ICON)
- {
- DestroyIcon(notifyItem->hIcon);
- notifyItem->hIcon = (HICON)CopyImage(iconData->hIcon, IMAGE_ICON, 0, 0,
0);
- tbbi.dwMask |= TBIF_IMAGE;
- tbbi.iImage = ImageList_ReplaceIcon(m_ImageList, index, iconData->hIcon);
- }
-
- if (iconData->uFlags & NIF_TIP)
- {
- StringCchCopy(notifyItem->szTip, _countof(notifyItem->szTip),
iconData->szTip);
- }
-
if (iconData->uFlags & NIF_STATE)
{
if (iconData->dwStateMask & NIS_HIDDEN &&
@@ -192,6 +225,41 @@ public:
notifyItem->dwState |= (iconData->dwState &
iconData->dwStateMask);
}
+ if (iconData->uFlags & NIF_MESSAGE)
+ {
+ notifyItem->uCallbackMessage = iconData->uCallbackMessage;
+ }
+
+ if (iconData->uFlags & NIF_ICON)
+ {
+ BOOL hasSharedIcon = notifyItem->dwState & NIS_SHAREDICON;
+ if (hasSharedIcon)
+ {
+ INT iIcon = FindExistingSharedIcon(iconData->hIcon);
+ if (iIcon >= 0)
+ {
+ notifyItem->hIcon = iconData->hIcon;
+ tbbi.dwMask |= TBIF_IMAGE;
+ tbbi.iImage = iIcon;
+ }
+ else
+ {
+ TRACE("Shared icon requested, but HICON not found!!!
IGNORING!");
+ }
+ }
+ else
+ {
+ notifyItem->hIcon = iconData->hIcon;
+ tbbi.dwMask |= TBIF_IMAGE;
+ tbbi.iImage = ImageList_ReplaceIcon(m_ImageList, oldIconIndex,
notifyItem->hIcon);
+ }
+ }
+
+ if (iconData->uFlags & NIF_TIP)
+ {
+ StringCchCopy(notifyItem->szTip, _countof(notifyItem->szTip),
iconData->szTip);
+ }
+
/* TODO: support NIF_INFO, NIF_GUID, NIF_REALTIME, NIF_SHOWTIP */
SetButtonInfo(index, &tbbi);
@@ -203,34 +271,48 @@ public:
{
NOTIFYICONDATA * notifyItem;
+ TRACE("Removing icon %d from hWnd %08x", iconData->uID,
iconData->hWnd);
+
int index = FindItemByIconData(iconData, ¬ifyItem);
if (index < 0)
+ {
+ TRACE("Icon %d from hWnd %08x ALREADY MISSING!", iconData->uID,
iconData->hWnd);
+
return FALSE;
+ }
if (!(notifyItem->dwState & NIS_HIDDEN))
{
m_VisibleButtonCount--;
}
- DestroyIcon(notifyItem->hIcon);
-
- delete notifyItem;
-
- ImageList_Remove(m_ImageList, index);
+ if (!(notifyItem->dwState & NIS_SHAREDICON))
+ {
+ TBBUTTON btn;
+ GetButton(index, &btn);
+ int oldIconIndex = btn.iBitmap;
+ ImageList_Remove(m_ImageList, oldIconIndex);
- int count = GetButtonCount();
+ // Update other icons!
+ int count = GetButtonCount();
+ for (int i = 0; i < count; i++)
+ {
+ TBBUTTON btn;
+ GetButton(i, &btn);
- /* shift all buttons one index to the left -- starting one index right
- from item to delete -- to preserve their correct icon and tip */
- for (int i = index; i < count - 1; i++)
- {
- notifyItem = GetItemData(i + 1);
- SetItemData(i, notifyItem);
- UpdateButton(notifyItem);
+ if (btn.iBitmap > oldIconIndex)
+ {
+ TBBUTTONINFO tbbi2 = { 0 };
+ tbbi2.cbSize = sizeof(tbbi2);
+ tbbi2.dwMask = TBIF_BYINDEX | TBIF_IMAGE;
+ tbbi2.iImage = btn.iBitmap-1;
+ SetButtonInfo(i, &tbbi2);
+ }
+ }
}
- /* Delete the right-most, now obsolete button */
- DeleteButton(count - 1);
+ delete notifyItem;
+ DeleteButton(index);
return TRUE;
}
@@ -269,7 +351,10 @@ public:
for (int i = 0; i < count; i++)
{
NOTIFYICONDATA * data = GetItemData(i);
- INT iIcon = ImageList_AddIcon(iml, data->hIcon);
+ BOOL hasSharedIcon = data->dwState & NIS_SHAREDICON;
+ INT iIcon = hasSharedIcon ? FindExistingSharedIcon(data->hIcon) : -1;
+ if (iIcon < 0)
+ iIcon = ImageList_AddIcon(iml, data->hIcon);
TBBUTTONINFO tbbi = { sizeof(tbbi), TBIF_BYINDEX | TBIF_IMAGE, 0, iIcon};
SetButtonInfo(i, &tbbi);
}
@@ -304,7 +389,7 @@ private:
{
// We detect and destroy icons with invalid handles only on mouse move over
systray, same as MS does.
// Alternatively we could search for them periodically (would waste more
resources).
- TRACE("destroying icon with invalid handle\n");
+ TRACE("Destroying icon %d with invalid handle hWnd=%08x\n",
notifyItem->uID, notifyItem->hWnd);
HWND parentHWND = GetParent();
parentHWND = ::GetParent(parentHWND);