Skip to content

Commit

Permalink
Fixed start up for the MacOS Ventura
Browse files Browse the repository at this point in the history
  • Loading branch information
3t0n committed Nov 22, 2022
1 parent 009d709 commit ef66d69
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 49 deletions.
Binary file modified LayoutSwitcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 20 additions & 12 deletions LayoutSwitcher.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_ENTITLEMENTS = LayoutSwitcherLauncher/LayoutSwitcherLauncher.entitlements;
CODE_SIGN_IDENTITY = "-";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
Expand All @@ -254,14 +255,15 @@
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = LayoutSwitcherLauncher/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0;
ONLY_ACTIVE_ARCH = YES;
MARKETING_VERSION = 1.3;
ONLY_ACTIVE_ARCH = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.triton.layoutswitcherlauncher;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
Expand All @@ -278,23 +280,25 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_ENTITLEMENTS = LayoutSwitcherLauncher/LayoutSwitcherLauncher.entitlements;
CODE_SIGN_IDENTITY = "-";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = 864YL5794R;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = LayoutSwitcherLauncher/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0;
MARKETING_VERSION = 1.3;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.triton.layoutswitcherlauncher;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down Expand Up @@ -359,7 +363,7 @@
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
ONLY_ACTIVE_ARCH = NO;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
Expand Down Expand Up @@ -431,22 +435,24 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CODE_SIGN_ENTITLEMENTS = LayoutSwitcher/LayoutSwitcher.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 6;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = KCW5Y524DQ;
DEVELOPMENT_TEAM = 864YL5794R;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = LayoutSwitcher/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 2.0;
ONLY_ACTIVE_ARCH = YES;
MARKETING_VERSION = 1.3;
ONLY_ACTIVE_ARCH = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.triton.layoutswitcher;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand All @@ -461,22 +467,24 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CODE_SIGN_ENTITLEMENTS = LayoutSwitcher/LayoutSwitcherRelease.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Manual;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 6;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = 864YL5794R;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = LayoutSwitcher/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 2.0;
MARKETING_VERSION = 1.3;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.triton.layoutswitcher;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down
73 changes: 44 additions & 29 deletions LayoutSwitcher/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ class AppDelegate: NSObject, NSApplicationDelegate {
static var spaceKeyCode: CGKeyCode = 0x31
}

func applicationDidFinishLaunching(_ aNotification: Notification) {
public func applicationDidFinishLaunching(_ aNotification: Notification) {
// Init application menu and icon
initMenu()

// Check security access to init event monitor
if isApplicationHasSecurityAccess() {
//initLanSwitchEventMonitor()
initLanSwitchEventMonitor()
initWinEditEventMonitor()
} else {
let securityAlert = NSAlert()
Expand All @@ -49,12 +49,12 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}

func applicationWillTerminate(_ aNotification: Notification) {
public func applicationWillTerminate(_ aNotification: Notification) {
deinitLangEventMonitor()
deinitEditEventMonitor()
}

func updateEditMenuState(editkeysMenu: NSMenuItem){
private func updateEditMenuState(editkeysMenu: NSMenuItem){
let submenu = editkeysMenu.submenu
var hotkeysState: NSControl.StateValue = .off
submenu?.items.forEach {
Expand All @@ -77,7 +77,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
editkeysMenu.state = hotkeysState
}

func newEditMenuItem(_ title: String, key: String, tag:EditHotKeys) -> NSMenuItem {
private func newEditMenuItem(_ title: String, key: String, tag:EditHotKeys) -> NSMenuItem {
let menuItem = NSMenuItem()
menuItem.title = title
menuItem.action = #selector(applicationSetWinEditKey)
Expand All @@ -87,7 +87,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
return menuItem
}

func initMenu() {
private func initMenu() {
// Define application's tray icon
if let menuBarButton = menuBarItem.button {
menuBarButton.image = #imageLiteral(resourceName: "MenuBarIcon")
Expand Down Expand Up @@ -131,8 +131,8 @@ class AppDelegate: NSObject, NSApplicationDelegate {

// Define main menu
let editkeysMenu = statusBarMenu.addItem(withTitle: "Edit shortcuts", action: nil, keyEquivalent: "")
// Assign submenu to main menu

// Assign submenu to main menu
editkeysMenu.submenu = editHotkeysSubmenu
updateEditMenuState(editkeysMenu: editkeysMenu)

Expand All @@ -150,7 +150,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
menuBarItem.menu = statusBarMenu
}

func initLanSwitchEventMonitor() {
private func initLanSwitchEventMonitor() {
// Get second modifier key, according to menu
let secondModifierFlag = arrayLangHotKeys[SettingsHelper.shared.checkedHotKeyIndex]

Expand All @@ -163,8 +163,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}

func initWinEditEventMonitor() {

private func initWinEditEventMonitor() {
for hotkeyType in editKeysState.elements() {
enabledEditKeysValues.append(contentsOf: editHotkeysValues[hotkeyType.rawValue] ?? [])
}
Expand All @@ -182,38 +181,38 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}

func deinitLangEventMonitor() {
private func deinitLangEventMonitor() {
guard langEventMonitor != nil else {return}
NSEvent.removeMonitor(langEventMonitor!)
}

func deinitEditEventMonitor() {
private func deinitEditEventMonitor() {
guard editEventMonitor != nil else {return}
NSEvent.removeMonitor(editEventMonitor!)
}

func updateLangEventMonitor() {
private func updateLangEventMonitor() {
deinitLangEventMonitor()
initLanSwitchEventMonitor()
}

func updateEditEventMonitor() {
private func updateEditEventMonitor() {
deinitEditEventMonitor()
initWinEditEventMonitor()
}

func isApplicationHasSecurityAccess() -> Bool {
private func isApplicationHasSecurityAccess() -> Bool {
let options: NSDictionary = [kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String : true]
return AXIsProcessTrustedWithOptions(options)
}

func openPrivacySettings() {
private func openPrivacySettings() {
URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility")
.flatMap { _ = NSWorkspace.shared.open($0) }
}

// TODO: To add some more combinations for different use-cases
func sendDefaultChangeLayoutHotkey() {
private func sendDefaultChangeLayoutHotkey() {
// Create a native system 'Control + Space' event
// TODO: maybe better to read system's layout hotkeys instead of hardcoding
let src = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
Expand All @@ -230,10 +229,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
spaceUp?.post(tap: loc)
}

func sendDefaultEditHotkey(_ key:String, code:UInt16) {
//print("\(String(describing: key)) is pressed")


private func sendDefaultEditHotkey(_ key:String, code:UInt16) {
// Create a native system 'Control + Space' event
// TODO: maybe better to read system's layout hotkeys instead of hardcoding
let src = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
Expand All @@ -250,7 +246,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
keyUp?.post(tap: loc)
}

@objc func applicationChangeHotkey(_ sender: NSMenuItem) {
@objc private func applicationChangeHotkey(_ sender: NSMenuItem) {
// Update the checked state of menu item and save it
sender.state = sender.state == .on ? .off : .on
SettingsHelper.shared.checkedHotKeyIndex = sender.menu!.index(of: sender)
Expand All @@ -266,7 +262,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}

@objc func applicationSetWinEditKey(_ sender: NSMenuItem) {
@objc private func applicationSetWinEditKey(_ sender: NSMenuItem) {
// Update the checked state of menu item and save it
sender.state = sender.state == .on ? .off : .on

Expand All @@ -288,7 +284,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {

}

@objc func applicationDisable(_ sender: NSMenuItem) {
@objc private func applicationDisable(_ sender: NSMenuItem) {
// Update menu item checkbox
sender.state = sender.state == .on ? .off : .on

Expand All @@ -305,15 +301,34 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}

@objc func applicationAutostart(_ sender: NSMenuItem) {
private func launchAtLogin(_ newState: Bool) -> Bool {
var result = false

if #available(macOS 13.0, *) {
if newState == true {
try? SMAppService.mainApp.register()
} else {
try? SMAppService.mainApp.unregister()
}

// FIXME: temporary hardcoded, get the status above
result = true
} else {
result = SMLoginItemSetEnabled(Constants.helperBundleID as CFString, newState)
}

return result
}

@objc private func applicationAutostart(_ sender: NSMenuItem) {
// Update menu item checkbox
sender.state = sender.state == .on ? .off : .on

// Get the new state based on the menu item checkbox
let newState = sender.state == .on ? true : false

// Run helping application to enable autostart
let setupResult = SMLoginItemSetEnabled(Constants.helperBundleID as CFString, newState)
let setupResult = launchAtLogin(newState)

// Save settings if action takes effect
if setupResult == true {
Expand All @@ -328,7 +343,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}

@objc func applicationAbout() {
@objc private func applicationAbout() {
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
let aboutAlert = NSAlert()

Expand All @@ -339,7 +354,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
aboutAlert.runModal()
}

@objc func applicationQuit() {
@objc private func applicationQuit() {
exit(0)
}
}
Expand Down
7 changes: 4 additions & 3 deletions LayoutSwitcher/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19529"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
</dependencies>
<scenes>
<!--Application-->
Expand Down Expand Up @@ -673,7 +674,7 @@
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
</connections>
</application>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModuleProvider="target"/>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="LayoutSwitcher" customModuleProvider="target"/>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
Expand Down
2 changes: 0 additions & 2 deletions LayoutSwitcher/LayoutSwitcher.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.device.bluetooth</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
</dict>
Expand Down
2 changes: 0 additions & 2 deletions LayoutSwitcher/LayoutSwitcherRelease.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.device.bluetooth</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
</dict>
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ LayoutSwitcher is open-source application that allows you to change keyboard lay
2. Drag'n'drop LayoutSwitcher application from dmg-file to your Applications folder
3. Make sure that you are using MacOs default shortcut (Control ⌃ + Space). You can check that by "Settings -> Keyboard -> Shortcuts". That is needed, because application emulates this shortcut in order to switch keybourd layout.
4. Run the application. You could be asked for provide permissions to run it, since it was downloaded not from the App Store. You can provide permissions by clicking allow button at "Settings -> Security & Privacy -> General"
5. At the first run application will ask you to add LayoutSwitcher to "Settings -> Security & Privacy -> Privacy -> Accessibility" in order to work properly. This is needed to be able globally monitor shortcut that you chosen to switch keyboard layout.
5. At the first run application will ask you to add LayoutSwitcher to "Settings -> Security & Privacy -> Privacy -> Accessibility" in order to work properly. This is needed to be able globally monitor shortcut that you chosen to switch keyboard layout.
6. Since Mac OS Ventura Apple removed the option “Allow applications downloaded from anywhere” from the system settings. You can understand that if you will see "Application can't be opened because Apple cannot check it for malicious software". To fix that you should open Terminal and type `sudo spctl --master-disable`

# Downloads
* GitHub: https://github.com/3t0n/LayoutSwitcher/releases/
Expand Down

0 comments on commit ef66d69

Please sign in to comment.