Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TrayIcon should support "template" icons #146

Closed
tresf opened this issue Jul 20, 2020 · 15 comments
Closed

TrayIcon should support "template" icons #146

tresf opened this issue Jul 20, 2020 · 15 comments
Labels
enhancement New feature or request

Comments

@tresf
Copy link

tresf commented Jul 20, 2020

Starting with macOS (10.16 "Beta"/11.0) "Big Sur", the menu-bar and system tray no longer honor the Desktop dark-mode preference, making it difficult to properly theme a system tray icon for this Desktop.

For frameworks such as Qt, they use a "template" mode flag which tells the NSImage that the image can be effectively treated as mask icon, however Java doesn't have a way to set this.

Please observe the system tray area in this video below. It illustrates that starting with MacOS 10.16(beta)/11.0 "Big Sur", the System Tray changes based on wallpaper -- NOT based on Dark/Light desktop theme.

Please observe the wifi, battery icons. They switch from white to black regardless of the desktop theme.

Same question, posted elsewhere:

sANZm

Similarly, Windows could also benefit from System Tray "template" support: https://stackoverflow.com/questions/60837862

Steps to reproduce

  1. Create an all-black System Tray icon
  2. Use AdoptOpenJDK 11.0.8 or lower (all JDKs appear to be affected by this change)
  3. Construct a new Tray Icon using it
  4. Change the wallpaper

Expected vs. Actual results

Since this is a new OS behavior, the expected results are the actual results, however it can be "expected" that the TrayIcon has an option to be treated as a template image to handle this common scenario.

Triaging info

Java version:

openjdk version "11.0.8" 2020-07-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.8+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.8+10, mixed mode)

Your operating system and platform:

macOS 10.15.6 Beta (19G60d)
3.5 GHz Dual-Core Intel Core i7
@tresf tresf added the bug Something isn't working label Jul 20, 2020
@aahlenst
Copy link
Contributor

I haven't fully grasped the issue yet. Can it be explained by Java opting out of dark mode? See #120.

@tresf
Copy link
Author

tresf commented Jul 20, 2020

@aahlenst no but let me go into detail...

  1. I use a Darkula L&F, so the dark-table-headers aren't present on my builds, nor would I consider them related to this "bug".
  2. Dark mode in general isn't related to this bug. The reason it's mentioned is I had previously used Dark Mode to detect what color the Tray Icon should be (black or white) since prior to 10.16/11.0 "Big Sur" dark mode influenced the color of the system menu bar at the top of the screen. However, starting with "Big Sur", the system menu bar is white/black based on wallpaper color, which can't easily be detected.
    • Previously, simply detecting "Dark Mode" programmatically would allow a programmer to at least workaround the tray-icon color.
    • Now, since the system menu bar isn't influenced by Dark Mode, but rather the wallpaper, Java needs to use the same technique as Qt and just have an API that allows the template flag to be set to true. This is also the proposed solution in this similar StackOverflow question: https://stackoverflow.com/a/25498025/3196753
  3. Worse, Windows is suffering a similar fate. Windows system tray icons have also gone black/white influenced by Desktop theming changes, so this "isTemplate" flag is warranted and needed if Java intends to continue to support the System Tray in general. At time of posting this, I'm unsure if win32 provides a similar "template" image API as Mac but at least for now on Windows, a platform-specific workaround still exist.

So in summary, the need for template images isn't new, but rather, it's at a point where there's no longer a workaround that's viable on MacOS. A hypothetical Robot technique sort-of works, but comes with both security as well as reliability issues since it requires elevated permissions to record the screen as well as causes inconsistencies for certain wallpapers.

@aahlenst aahlenst added enhancement New feature or request and removed bug Something isn't working labels Jul 24, 2020
@aahlenst
Copy link
Contributor

aahlenst commented Aug 1, 2020

@tresf I'm still trying to figure out a successful way to communicate those things to OpenJDK. At least for issues that are a problem in the newest versions (15, 16 at the moment), it might make sense to try https://bugreport.java.com/bugreport/. Once a report has been triaged by Oracle, it should end up in JBS. Would you be willing to give it a shot?

@karianna karianna added the jbs:needs-report Waiting for someone from our org to report to OpenJDK label Aug 2, 2020
@tresf
Copy link
Author

tresf commented Aug 3, 2020

@tresf I'm still trying to figure out a successful way to communicate those things to OpenJDK. At least for issues that are a problem in the newest versions (15, 16 at the moment), it might make sense to try https://bugreport.java.com/bugreport/. Once a report has been triaged by Oracle, it should end up in JBS. Would you be willing to give it a shot?

Ok, I've done this in the past and it takes a considerable amount of time to make it into the tracker, but I'll do just that.

To that point, my developer's working directly with the OpenJDK11 source code and he's making a proof of concept change to awt to support this new technique (since MacOS 10.10). The JDK11 roadmap seems like this won't break anything, but we'll need to expand the API to allow the template: true flag. Since we've never submitted a code change to openjdk any advice along the way is appreciated. PM on Slack is fine too if there are nuances that are too large or too specific to type into a bug report. ❤️

@tresf
Copy link
Author

tresf commented Aug 4, 2020

Submitted. Review ID: 9066316. Hopefully it's accepted. The description -- for those interested:

Review ID: 9066316 (click to expand)

java.awt.TrayIcon requires updates for template images

According to Apple's human interface guidelines, developers should:

[...] use a template image to represent your menu bar extra. A template image discards color information and uses a mask to produce the appearance you see onscreen. Template images automatically adapt to the user’s appearance settings, so they look good on both dark and light menu bars, and when your menu bar extra is selected."

These template images could be effectively simulated in appearance prior to MacOS 11.0 "Big Sur" by using platform-specific workarounds to predict the color of the icon, however starting with 11.0 "Big Sur", workarounds are ineffective as described here: (AdoptOpenJDK) #146

Supporting template icons requires an API change to java.awt.TrayIcon, specifically a boolean flag to represent if the icon provided can be used as a "template" icon. This API can and should be implemented to any other platforms (e.g. Windows 10), assuming a similar API -- or simulation thereof -- can exist. See also Qt's API example setIsMask which offers this functionality: https://github.com/qt/qtbase/blob/471e4fcb226c4523efe93b1bdaf0db026495da94/src/gui/image/qicon.cpp#L1341-L1355

In order for this feature to be implemented, Java will need to change the AWTTrayIconView to use a button (not a view) instead as the existing AWTTrayIconView implementation manually blits the image using AWTTrayIconView.drawRect(), preventing control over NSImage::isTemplate from being used.

Due to the introduction of macOS 11.0 in fall of 2020 combined with the state of Java 11 being LTS until 2023, java.awt.TrayIcon should be enhanced to support template icons to be consistent with Apple's human interface guidelines so that Java developers can continue to develop and use java.awt.TrayIcon in accordance with Apple's standards.

@karianna karianna added jbs:reported Someone from our org has reported it to OpenJDK and removed jbs:needs-report Waiting for someone from our org to report to OpenJDK labels Aug 6, 2020
@tresf
Copy link
Author

tresf commented Aug 17, 2020

Review ID: 9066316 wasn't explicitly approved or rejected, I got this response from Oracle:

Subject: Re: Incident Report 9154374 : java.awt.TrayIcon requires updates for template images

We request you to post an enhancement request to [email protected]

  • Is anyone familiar with this (enhancement request to a mailing list) process?
  • Why did my Review ID number change from 9066316 to 9154374?
  • How do I get back to my submission? Do I have to write it all up again? It had details that were compiled from various sources, reproducing this effort for an email to the awt team is disconcerting.

@tresf
Copy link
Author

tresf commented Aug 19, 2020

OpenJDK has accepted the bug report here: https://bugs.openjdk.java.net/browse/JDK-8252015. Next is engaging the awt team.

@tresf
Copy link
Author

tresf commented Sep 16, 2020

The awt team has replied asking for us to submit a PR. Our JDK support provider has helped in warning us about awt API changes (to avoid them) so we're moving some flags to system properties instead. The conversation can be tracked here: https://mail.openjdk.java.net/pipermail/awt-dev/2020-September/016085.html

A pull request will be issued against openjdk with this feature in the next week or so, just wrapping up the Objective-C and JNI calls.

@tresf
Copy link
Author

tresf commented Sep 23, 2020

Here's our code which adds a new system property to the JDK allowing a monochrome template image in the System Tray for macOS: AdoptOpenJDK/openjdk-jdk11u@master...qzind:trayicon

The code which toggles the template image on/off is here which calls NSImage::setTemplate(true). Unfortunately the old TrayIcon didn't honor this flag, so the majority of the PR is simply switching the JDK away from a view (using drawRect) to a button (with native NSImage:isTemplate support) so that this boolean flag can be honored.

To use this JDK:

  1. Clone this branch and compile the JDK: https://github.com/qzind/openjdk-jdk11u/tree/trayicon

  2. Toggle template images using system property sun.awt.enableTemplateImages
    ... e.g.

    java -Dsun.awt.enableTemplateImages=true -jar myapp.jar

    ⚠️ WARNING: This property name hasn't yet been approved by awt-dev and is subject to change.

A pull request will be issued against openjdk with this feature in the next week or so

Slight correction: the vendor will be doing this on our behalf. We'll update accordingly.

@tresf
Copy link
Author

tresf commented Oct 2, 2020

PR initiated upstream: openjdk/jdk#481

@tresf
Copy link
Author

tresf commented Jan 12, 2021

Merged upstream via openjdk/jdk@400dc76, awaiting backport for OpenJDK11.

@tresf
Copy link
Author

tresf commented Jan 25, 2021

Thanks to @dyorgio for sharing a workaround while we await the backport: https://github.com/dyorgio/macos-tray-icon-fixer

@karianna karianna modified the milestones: January 2021, February 2021 Feb 3, 2021
@karianna karianna modified the milestones: February 2021, March 2021 Mar 8, 2021
@karianna karianna modified the milestones: March 2021, April 2021 Apr 16, 2021
@karianna karianna modified the milestones: April 2021, June 2021 Jun 7, 2021
@karianna karianna removed this from the June 2021 milestone Jul 19, 2021
@github-actions
Copy link

github-actions bot commented May 8, 2022

We are marking this issue as stale because it has not been updated for a while. This is just a way to keep the support issues queue manageable.
It will be closed soon unless the stale label is removed by a committer, or a new comment is made.

@github-actions github-actions bot added the stale label May 8, 2022
@karianna
Copy link
Contributor

karianna commented May 9, 2022

https://bugs.openjdk.java.net/browse/JDK-8252015 is the upstream issue. It has not been backported and may not be due to the CSR involvment.

@karianna karianna added jbs:needs-backport-to-11 We need to backport to OpenJDK 11 and removed jbs:reported Someone from our org has reported it to OpenJDK stale labels May 9, 2022
@tresf
Copy link
Author

tresf commented May 9, 2022

@karianna as the original submitter, I'm perfectly fine closing this out. JDK17 is available and LTS now, so there's a fix available. Furthermore, the workaround even works on Apple Silicon since JNA added support for that hardware so tracking this over at Adoptium seems like a futile effort at this point. ❤️

@karianna karianna closed this as completed May 9, 2022
@gdams gdams removed the jbs:needs-backport-to-11 We need to backport to OpenJDK 11 label Jul 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants