diff --git a/qt/mac/AnkiHelper.m b/qt/mac/AnkiHelper.m deleted file mode 100644 index 2b461ee82..000000000 --- a/qt/mac/AnkiHelper.m +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright: Ankitects Pty Ltd and contributors -// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html - -@import Foundation; -@import AppKit; - -/// Force our app to be either light or dark mode. -void set_darkmode_enabled(BOOL enabled) { - NSAppearance *appearance; - if (enabled) { - appearance = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua]; - } else { - appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua]; - } - - [NSApplication sharedApplication].appearance = appearance; -} - -/// True if the system is set to dark mode. -BOOL system_is_dark(void) { - BOOL styleSet = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleInterfaceStyle"] != nil; - return styleSet; - // FIXME: confirm whether this is required on 10.15/16 (it - // does not appear to be on 11) - - // BOOL autoSwitch = [[NSUserDefaults standardUserDefaults] boolForKey:@"AppleInterfaceStyleSwitchesAutomatically"]; - // - // if (@available(macOS 10.15, *)) { - // return autoSwitch ? !styleSet : styleSet; - // } else { - // return styleSet; - // } - -} diff --git a/qt/mac/BUILD.bazel b/qt/mac/BUILD.bazel index ef9684fab..45948e07d 100644 --- a/qt/mac/BUILD.bazel +++ b/qt/mac/BUILD.bazel @@ -1,20 +1,15 @@ -load("@rules_cc//cc:defs.bzl", "objc_library") - -objc_library( - name = "helper_static", - srcs = ["AnkiHelper.m"], - enable_modules = True, - sdk_frameworks = ["AppKit"], +py_binary( + name = "helper_build", + srcs = ["helper_build.py"], tags = ["manual"], - alwayslink = True, ) -apple_binary( +genrule( name = "helper_dylib", - binary_type = "dylib", - minimum_os_version = "10.14", - platform_type = "macos", + srcs = glob(["*.swift"]), + outs = ["libankihelper.dylib"], + cmd = "$(location :helper_build) $@ $(COMPILATION_MODE) $(SRCS)", tags = ["manual"], + tools = [":helper_build"], visibility = ["//qt:__subpackages__"], - deps = ["helper_static"], ) diff --git a/qt/mac/README.md b/qt/mac/README.md index eda236ff6..b1c8d6240 100644 --- a/qt/mac/README.md +++ b/qt/mac/README.md @@ -1 +1 @@ -Tiny helper library to set dark mode on and off on Macs. +Helper library for macOS-specific functionality. diff --git a/qt/mac/ankihelper.xcodeproj/project.pbxproj b/qt/mac/ankihelper.xcodeproj/project.pbxproj index d03fb4567..637f03e40 100644 --- a/qt/mac/ankihelper.xcodeproj/project.pbxproj +++ b/qt/mac/ankihelper.xcodeproj/project.pbxproj @@ -7,11 +7,11 @@ objects = { /* Begin PBXBuildFile section */ - 1327600A274613D9001D63D7 /* AnkiHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 13276009274613D8001D63D7 /* AnkiHelper.m */; }; + 137892AC275D90FC009D0B6E /* theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 137892AB275D90FC009D0B6E /* theme.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 13276009274613D8001D63D7 /* AnkiHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AnkiHelper.m; sourceTree = ""; }; + 137892AB275D90FC009D0B6E /* theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = theme.swift; sourceTree = ""; }; 138B770F2746137F003A3E4F /* libankihelper.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libankihelper.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -29,7 +29,7 @@ 138B77062746137F003A3E4F = { isa = PBXGroup; children = ( - 13276009274613D8001D63D7 /* AnkiHelper.m */, + 137892AB275D90FC009D0B6E /* theme.swift */, 138B77102746137F003A3E4F /* Products */, ); sourceTree = ""; @@ -83,6 +83,7 @@ TargetAttributes = { 138B770E2746137F003A3E4F = { CreatedOnToolsVersion = 13.1; + LastSwiftMigration = 1310; }; }; }; @@ -109,7 +110,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1327600A274613D9001D63D7 /* AnkiHelper.m in Sources */, + 137892AC275D90FC009D0B6E /* theme.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -230,26 +231,41 @@ 138B77192746137F003A3E4F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 7ZM8SLJM4P; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; EXECUTABLE_PREFIX = lib; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Debug; }; 138B771A2746137F003A3E4F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 7ZM8SLJM4P; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; EXECUTABLE_PREFIX = lib; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/qt/mac/ankihelper.xcodeproj/project.xcworkspace/xcuserdata/dae.xcuserdatad/UserInterfaceState.xcuserstate b/qt/mac/ankihelper.xcodeproj/project.xcworkspace/xcuserdata/dae.xcuserdatad/UserInterfaceState.xcuserstate index 255052f65..ca596a1eb 100644 Binary files a/qt/mac/ankihelper.xcodeproj/project.xcworkspace/xcuserdata/dae.xcuserdatad/UserInterfaceState.xcuserstate and b/qt/mac/ankihelper.xcodeproj/project.xcworkspace/xcuserdata/dae.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/qt/mac/ankihelper.xcodeproj/project.xcworkspace/xcuserdata/dae.xcuserdatad/xcschemes/xcschememanagement.plist b/qt/mac/ankihelper.xcodeproj/project.xcworkspace/xcuserdata/dae.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 000000000..ee3458dd7 --- /dev/null +++ b/qt/mac/ankihelper.xcodeproj/project.xcworkspace/xcuserdata/dae.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/qt/mac/ankihelper.xcodeproj/xcuserdata/dae.xcuserdatad/xcschemes/xcschememanagement.plist b/qt/mac/ankihelper.xcodeproj/xcuserdata/dae.xcuserdatad/xcschemes/xcschememanagement.plist index 7b914bfe3..888e2b255 100644 --- a/qt/mac/ankihelper.xcodeproj/xcuserdata/dae.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/qt/mac/ankihelper.xcodeproj/xcuserdata/dae.xcuserdatad/xcschemes/xcschememanagement.plist @@ -4,7 +4,7 @@ SchemeUserState - ankihelper.xcscheme_^#shared#^_ + ankihelper.xcscheme orderHint 0 diff --git a/qt/mac/helper_build.py b/qt/mac/helper_build.py new file mode 100644 index 000000000..86a369d78 --- /dev/null +++ b/qt/mac/helper_build.py @@ -0,0 +1,29 @@ +# Copyright: Ankitects Pty Ltd and contributors +# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html + +import subprocess +import sys +import platform +from pathlib import Path + +out_dylib, compile_mode, *src_files = sys.argv[1:] +out_dir = Path(out_dylib).parent.resolve() +src_dir = Path(src_files[0]).parent.resolve() + +if platform.machine() == "arm64": + target = "arm64-apple-macos11" +else: + target = "x86_64-apple-macos10.14" + +args = [ + "swiftc", + "-target", + target, + "-emit-library", + "-module-name", + "ankihelper", +] +if compile_mode == "opt": + args.append("-O") +args.extend(src_dir / Path(file).name for file in src_files) +subprocess.run(args, check=True, cwd=out_dir) diff --git a/qt/mac/theme.swift b/qt/mac/theme.swift new file mode 100644 index 000000000..dda9d6e35 --- /dev/null +++ b/qt/mac/theme.swift @@ -0,0 +1,18 @@ +// Copyright: Ankitects Pty Ltd and contributors +// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html + +import AppKit +import Foundation + +/// Force our app to be either light or dark mode. +@_cdecl("set_darkmode_enabled") +public func setDarkmodeEnabled(_ enabled: Bool) { + NSApplication.shared.appearance = NSAppearance(named: enabled ? .darkAqua : .aqua) +} + +/// True if the system is set to dark mode. +@_cdecl("system_is_dark") +public func systemIsDark() -> Bool { + let styleSet = UserDefaults.standard.object(forKey: "AppleInterfaceStyle") != nil + return styleSet +}