Skip to content

Commit

Permalink
Windows theming improvements
Browse files Browse the repository at this point in the history
Separates system tray and window theming logic on Windows.
Closes #597
  • Loading branch information
tresf authored Apr 13, 2020
1 parent 35ea73f commit b1e31e8
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 29 deletions.
14 changes: 8 additions & 6 deletions src/qz/common/TrayManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import org.slf4j.LoggerFactory;
import qz.auth.Certificate;
import qz.auth.RequestState;
import qz.installer.WindowsInstaller;
import qz.installer.shortcut.ShortcutCreator;
import qz.ui.*;
import qz.ui.component.IconCache;
Expand Down Expand Up @@ -112,7 +111,7 @@ public TrayManager(boolean isHeadless) {

// OS-specific tray icon handling
if (SystemTray.isSupported()) {
iconCache.fixTrayIcons(SystemUtilities.isDarkMode());
iconCache.fixTrayIcons(SystemUtilities.isDarkTaskbar());
}

// Iterates over all images denoted by IconCache.getTypes() and caches them
Expand Down Expand Up @@ -152,13 +151,16 @@ public TrayManager(boolean isHeadless) {

// Detect theme changes
new Thread(() -> {
boolean darkMode = SystemUtilities.isDarkMode();
boolean darkDesktopMode = SystemUtilities.isDarkDesktop();
boolean darkTaskbarMode = SystemUtilities.isDarkTaskbar();
while(true) {
try {
Thread.sleep(1000);
if (darkMode != SystemUtilities.isDarkMode(true)) {
darkMode = SystemUtilities.isDarkMode();
iconCache.fixTrayIcons(darkMode);
if (darkDesktopMode != SystemUtilities.isDarkDesktop(true) ||
darkTaskbarMode != SystemUtilities.isDarkTaskbar(true)) {
darkDesktopMode = SystemUtilities.isDarkDesktop();
darkTaskbarMode = SystemUtilities.isDarkTaskbar();
iconCache.fixTrayIcons(darkTaskbarMode);
refreshIcon();
SwingUtilities.invokeLater(() -> {
SystemUtilities.setSystemLookAndFeel();
Expand Down
6 changes: 3 additions & 3 deletions src/qz/ui/component/IconCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ public void setBgColor(Icon i, Color bgColor) {
* - macOS masked icons
* - macOS 10.14+ dark mode support
*/
public void fixTrayIcons(boolean darkMode) {
public void fixTrayIcons(boolean darkTaskbar) {
// Fix the tray icon to look proper on Ubuntu
if (SystemUtilities.isUbuntu()) {
UbuntuUtilities.fixTrayIcons(this);
Expand All @@ -269,9 +269,9 @@ public void fixTrayIcons(boolean darkMode) {
BufferedImage clone = clone(images.get(id));
// Even on lite mode desktops, white tray icons were the norm until Windows 10 update 1903
if (SystemUtilities.isWindows() && SystemUtilities.getOSVersion().lessThan(Version.valueOf("10.0.1903"))) {
darkMode = true;
darkTaskbar = true;
}
if (darkMode) {
if (darkTaskbar) {
clone = ColorUtilities.invert(clone);
}
images.put(id.replaceAll("mask", "default"), clone);
Expand Down
42 changes: 29 additions & 13 deletions src/qz/utils/SystemUtilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
package qz.utils;

import com.github.zafarkhaja.semver.Version;
import com.sun.jna.platform.win32.Advapi32Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import qz.common.Constants;
Expand Down Expand Up @@ -39,7 +38,8 @@ public class SystemUtilities {
private static final String OS_NAME = System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
private static final Logger log = LoggerFactory.getLogger(TrayManager.class);

private static Boolean darkMode;
private static Boolean darkDesktop;
private static Boolean darkTaskbar;
private static String uname;
private static String linuxRelease;
private static String classProtocol;
Expand Down Expand Up @@ -283,27 +283,43 @@ public static String getUname() {
return uname;
}

public static boolean isDarkMode() {
return isDarkMode(false);
public static boolean isDarkTaskbar() {
return isDarkTaskbar(false);
}

public static boolean isDarkMode(boolean recheck) {
if (darkMode == null || recheck) {
public static boolean isDarkTaskbar(boolean recheck) {
if(darkTaskbar == null || recheck) {
if (!isWindows()) {
// Mac and Linux don't differentiate; return the cached darkDesktop value
darkTaskbar = isDarkDesktop();
} else {
darkTaskbar = WindowsUtilities.isDarkTaskbar();
}
}
return darkTaskbar.booleanValue();
}

public static boolean isDarkDesktop() {
return isDarkDesktop(false);
}

public static boolean isDarkDesktop(boolean recheck) {
if (darkDesktop == null || recheck) {
// Check for Dark Mode on MacOS
if (isMac()) {
darkMode = MacUtilities.isDarkMode();
darkDesktop = MacUtilities.isDarkMode();
} else if (isWindows()) {
darkMode = WindowsUtilities.isDarkMode();
darkDesktop = WindowsUtilities.isDarkDesktop();
} else {
darkMode = UbuntuUtilities.isDarkMode();
darkDesktop = UbuntuUtilities.isDarkMode();
}
}
return darkMode.booleanValue();
return darkDesktop.booleanValue();
}

public static void adjustThemeColors() {
Constants.WARNING_COLOR = isDarkMode() ? Constants.WARNING_COLOR_DARK : Constants.WARNING_COLOR_LITE;
Constants.TRUSTED_COLOR = isDarkMode() ? Constants.TRUSTED_COLOR_DARK : Constants.TRUSTED_COLOR_LITE;
Constants.WARNING_COLOR = isDarkDesktop() ? Constants.WARNING_COLOR_DARK : Constants.WARNING_COLOR_LITE;
Constants.TRUSTED_COLOR = isDarkDesktop() ? Constants.TRUSTED_COLOR_DARK : Constants.TRUSTED_COLOR_LITE;
}

public static boolean prefersMaskTrayIcon() {
Expand All @@ -324,7 +340,7 @@ public static boolean setSystemLookAndFeel() {
if(!isMac() && (isUnix() && UbuntuUtilities.isDarkMode())) {
darkulaThemeNeeded = false;
}
if(isDarkMode() && darkulaThemeNeeded) {
if(isDarkDesktop() && darkulaThemeNeeded) {
UIManager.setLookAndFeel("com.bulenkov.darcula.DarculaLaf");
} else {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
Expand Down
20 changes: 13 additions & 7 deletions src/qz/utils/WindowsUtilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,29 @@

public class WindowsUtilities {
protected static final Logger log = LoggerFactory.getLogger(WindowsUtilities.class);
private static String THEME_REG_KEY = "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
private static final String AUTHENTICATED_USERS_SID = "S-1-5-11";

public static boolean isDarkMode() {
String key = "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";

public static boolean isDarkDesktop() {
// 0 = Dark Theme. -1/1 = Light Theme
Integer regVal;
if((regVal = getRegInt(HKEY_CURRENT_USER, key, "SystemUsesLightTheme")) != null) {
// Prefer system theme
return regVal == 0;
} else if((regVal = getRegInt(HKEY_CURRENT_USER, key, "AppsUseLightTheme")) != null) {
if((regVal = getRegInt(HKEY_CURRENT_USER, THEME_REG_KEY, "AppsUseLightTheme")) != null) {
// Fallback on apps theme
return regVal == 0;
}
return false;
}

public static boolean isDarkTaskbar() {
// -1/0 = Dark Theme. 1 = Light Theme
Integer regVal;
if((regVal = getRegInt(HKEY_CURRENT_USER, THEME_REG_KEY, "SystemUsesLightTheme")) != null) {
// Prefer system theme
return regVal == 0;
}
return true;
}

public static int getScaleFactor() {
if (Constants.JAVA_VERSION.lessThan(Version.valueOf("9.0.0"))) {
WinDef.HDC hdc = GDI32.INSTANCE.CreateCompatibleDC(null);
Expand Down

0 comments on commit b1e31e8

Please sign in to comment.