JDK-8286838 : SendTrayMessage(NIM_ADD) returns failure in AwtTrayIcon::WmTaskbarCreated
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 19
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows
  • Submitted: 2022-05-16
  • Updated: 2022-05-19
  • Resolved: 2022-05-19
Related Reports
Relates :  
Relates :  
Description
AwtTrayIcon::WmTaskbarCreated [1] handles the situation where Windows Taskbar is recreated. When an app receives this message, it should re-add all its notification icons.

On Windows 10, this message is also broadcast when the DPI of the main display changes. This situation is handled by JDK-8255439 which calls UpdateImage. This results in SendTrayMessage(NIM_MODIFY) being called, and it returns 1 which indicates success.

At the same time, SendTrayMessage(NIM_ADD) is still called, and it always returns 0 which indicates failure.

So the two cases should be handled separately: if DPI changed, call SendTrayMessage(NIM_MODIFY) only because the Taskbar still has the icon; otherwise call SendTrayMessage(NIM_ADD) to re-add the icon because the taskbar was re-created.


[1] https://github.com/openjdk/jdk/blob/1d8e92ae0d2d0d6740e2171abef45545439e6414/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp#L477
Comments
When [~honkar] and I tested the changes for JDK-8255439, we noticed that SendTrayMessage(NIM_ADD) in AwtTrayIcon::WmTaskbarCreated returns 0. The result of SendTrayMessage(NIM_MODIFY) after UpdateImage is 1. After JDK-8286872, the code of WmTaskbarCreated inside the for-loop will look like this: if (m_bDPIChanged) { item->m_trayIcon->UpdateImage(); } item->m_trayIcon->AddTrayIcon(); The idea of this bug is to change the code like this: if (m_bDPIChanged) { item->m_trayIcon->UpdateImage(); } else { item->m_trayIcon->AddTrayIcon(); } That is to avoid unnecessary call to AddTrayIcon() / SendTrayMessage(NIM_ADD) which fails when DPI changes. Yet there's still a situation where both calls are required. Consider the following scenario. The user changed the DPI of the main monitor. Java received WM_DPICHANGED and set the m_bDPIChanged flag to true. Something happened and explorer.exe process died before it had a chance to broadcast "TaskbarCreated" (possibly while it was processing WM_DPICHANGED). When explorer.exe restarts, it creates the taskbar and broadcasts "TaskbarCreated" message. Java receives it but it will call only UpdateImage() because m_bDPIChanged=true. Since the taskbar restarted, SendTrayMessage(NIM_MODIFY) will fail. In this situation, AddTrayIcon() / SendTrayMessage(NIM_ADD) must be called to re-add the icon. Therefore it's safer to leave the code as it is now and to call AddTrayIcon() unconditionally.
19-05-2022