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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ pom.xml.versionsBackup
.idea/compiler.xml
.idea/jarRepositories.xml
*.iml

# MacOS
.DS_Store

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
import org.cryptomator.integrations.keychain.KeychainAccessProvider;
import org.cryptomator.integrations.revealpath.RevealPathService;
import org.cryptomator.integrations.tray.TrayIntegrationProvider;
import org.cryptomator.integrations.tray.TrayMenuController;
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
import org.cryptomator.integrations.update.UpdateMechanism;
import org.cryptomator.macos.autostart.MacAutoStartProvider;
import org.cryptomator.macos.keychain.MacSystemKeychainAccess;
import org.cryptomator.macos.keychain.TouchIdKeychainAccess;
import org.cryptomator.macos.revealpath.OpenCmdRevealPathService;
import org.cryptomator.macos.tray.MacTrayIntegrationProvider;
import org.cryptomator.macos.tray.MacTrayMenuController;
import org.cryptomator.macos.uiappearance.MacUiAppearanceProvider;
import org.cryptomator.macos.update.DmgUpdateMechanism;

Expand All @@ -20,6 +22,7 @@
provides KeychainAccessProvider with MacSystemKeychainAccess, TouchIdKeychainAccess;
provides RevealPathService with OpenCmdRevealPathService;
provides TrayIntegrationProvider with MacTrayIntegrationProvider;
provides TrayMenuController with MacTrayMenuController;
provides UiAppearanceProvider with MacUiAppearanceProvider;
provides UpdateMechanism with DmgUpdateMechanism;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package org.cryptomator.macos.tray;

import org.cryptomator.integrations.common.OperatingSystem;
import org.cryptomator.integrations.common.Priority;
import org.cryptomator.integrations.tray.ActionItem;
import org.cryptomator.integrations.tray.SeparatorItem;
import org.cryptomator.integrations.tray.SubMenuItem;
import org.cryptomator.integrations.tray.TrayIconLoader;
import org.cryptomator.integrations.tray.TrayMenuController;
import org.cryptomator.integrations.tray.TrayMenuException;
import org.cryptomator.integrations.tray.TrayMenuItem;
import org.cryptomator.macos.common.NativeLibLoader;

import java.util.List;
import java.util.function.Consumer;

@Priority(1000)
@OperatingSystem(OperatingSystem.Value.MAC)
public class MacTrayMenuController implements TrayMenuController {

@Override
public void showTrayIcon(Consumer<TrayIconLoader> iconLoader, Runnable defaultAction, String tooltip) throws TrayMenuException {
Native.INSTANCE.showTrayIcon(loadPng(iconLoader), tooltip, defaultAction);
}
Comment thread
oc7o marked this conversation as resolved.

@Override
public void updateTrayIcon(Consumer<TrayIconLoader> iconLoader) {
Native.INSTANCE.updateTrayIcon(loadPng(iconLoader));
}

@Override
public void updateTrayMenu(List<TrayMenuItem> items) {
Native.INSTANCE.clearMenu();
buildMenu(Native.ROOT_MENU, items);
}

@Override
public void onBeforeOpenMenu(Runnable listener) {
Native.INSTANCE.setBeforeOpenMenuListener(listener);
}

private static byte[] loadPng(Consumer<TrayIconLoader> iconLoader) {
byte[][] holder = {null};
iconLoader.accept((TrayIconLoader.PngData) data -> holder[0] = data);
if (holder[0] == null) {
throw new IllegalStateException("Icon loader did not provide PNG data");
}
return holder[0];
}
Comment thread
oc7o marked this conversation as resolved.

private void buildMenu(long menuHandle, List<TrayMenuItem> items) {
for (var item : items) {
switch (item) {
case ActionItem a -> Native.INSTANCE.addActionItem(menuHandle, a.title(), a.enabled(), a.action());
case SeparatorItem ignored -> Native.INSTANCE.addSeparator(menuHandle);
case SubMenuItem s -> {
long submenuHandle = Native.INSTANCE.addSubMenuItem(menuHandle, s.title());
buildMenu(submenuHandle, s.items());
}
}
}
}

private static final class Native {

static final long ROOT_MENU = 0L;
static final Native INSTANCE = new Native();

private Native() {
NativeLibLoader.loadLib();
}

native void showTrayIcon(byte[] pngData, String tooltip, Runnable defaultAction);

native void updateTrayIcon(byte[] pngData);

native void clearMenu();

native void addActionItem(long menuHandle, String title, boolean enabled, Runnable action);

native void addSeparator(long menuHandle);

native long addSubMenuItem(long menuHandle, String title);

native void setBeforeOpenMenuListener(Runnable listener);
}
}
4 changes: 4 additions & 0 deletions src/main/native/Integrations.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
06B9771B2FB9FC7200949F2E /* org_cryptomator_macos_tray_MacTrayMenuController_Native.m in Sources */ = {isa = PBXBuildFile; fileRef = 06B9771A2FB9FC7200949F2E /* org_cryptomator_macos_tray_MacTrayMenuController_Native.m */; };
74BEF1852C0384FB006731AC /* SKYLaunchService.m in Sources */ = {isa = PBXBuildFile; fileRef = 74BEF1842C0384FB006731AC /* SKYLaunchService.m */; };
74BEF1862C0384FB006731AC /* SKYLaunchService.h in Headers */ = {isa = PBXBuildFile; fileRef = 74BEF1832C0384FB006731AC /* SKYLaunchService.h */; };
74CF2E7B254C295A006266D6 /* org_cryptomator_macos_autostart_MacLaunchServices_Native.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CF2E7A254C295A006266D6 /* org_cryptomator_macos_autostart_MacLaunchServices_Native.m */; };
Expand All @@ -21,6 +22,7 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
06B9771A2FB9FC7200949F2E /* org_cryptomator_macos_tray_MacTrayMenuController_Native.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = org_cryptomator_macos_tray_MacTrayMenuController_Native.m; sourceTree = "<group>"; };
74BEF1832C0384FB006731AC /* SKYLaunchService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SKYLaunchService.h; sourceTree = "<group>"; };
74BEF1842C0384FB006731AC /* SKYLaunchService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SKYLaunchService.m; sourceTree = "<group>"; };
74CF2E7A254C295A006266D6 /* org_cryptomator_macos_autostart_MacLaunchServices_Native.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = org_cryptomator_macos_autostart_MacLaunchServices_Native.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -49,6 +51,7 @@
9E0819AE1D748ECC000C89E6 = {
isa = PBXGroup;
children = (
06B9771A2FB9FC7200949F2E /* org_cryptomator_macos_tray_MacTrayMenuController_Native.m */,
74CF2E7A254C295A006266D6 /* org_cryptomator_macos_autostart_MacLaunchServices_Native.m */,
9E0819C71D75CABC000C89E6 /* org_cryptomator_macos_keychain_MacKeychain_Native.m */,
9EACB1B325557865000F3214 /* org_cryptomator_macos_tray_ActivationPolicy_Native.m */,
Expand Down Expand Up @@ -145,6 +148,7 @@
74BEF1852C0384FB006731AC /* SKYLaunchService.m in Sources */,
9EACB1B425557865000F3214 /* org_cryptomator_macos_tray_ActivationPolicy_Native.m in Sources */,
74CF2E7B254C295A006266D6 /* org_cryptomator_macos_autostart_MacLaunchServices_Native.m in Sources */,
06B9771B2FB9FC7200949F2E /* org_cryptomator_macos_tray_MacTrayMenuController_Native.m in Sources */,
9E21340C255429CA006EA872 /* SKYAppearanceObserver.m in Sources */,
9E21340025542735006EA872 /* org_cryptomator_macos_uiappearance_AppAppearance_Native.m in Sources */,
9E21341225542ECE006EA872 /* SKYAppearanceNotifier.m in Sources */,
Expand Down
Loading