Skip to content

Commit 9d6dfef

Browse files
committed
Use a postinstall script to activate after install/upgrade
1 parent c126499 commit 9d6dfef

7 files changed

Lines changed: 285 additions & 14 deletions

File tree

DEVELOPMENT.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ The project has the following targets:
44
* MathSymbolsInput: the core input method, installed in `/Library/Input Methods`
55
* MathSymbolsInputPreferences: a GUI app for the "Preferences..." menu, installed in
66
`/Applications`
7+
* activate: a command-line tool to enable and select the input method after an install
8+
or upgrade
79

810
These are configured to build into the `build/` directory. The preferences app
911
can be run normally from Xcode during development. The others require a bit more

MathSymbolsInput.xcodeproj/project.pbxproj

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,24 @@
1818
1A695F26229F8FDD008DEC0F /* commands.txt in Resources */ = {isa = PBXBuildFile; fileRef = 1A695F25229F8FDD008DEC0F /* commands.txt */; };
1919
1A6DBD6223B969C600AA8924 /* DefaultCommandsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A6DBD6023B966B900AA8924 /* DefaultCommandsController.swift */; };
2020
1A6DBD6623B9A63C00AA8924 /* AboutController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A6DBD6523B9A63C00AA8924 /* AboutController.swift */; };
21+
1A8EF34F296B6A030006D7FC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A8EF34E296B6A030006D7FC /* main.m */; };
2122
1AC14D8B22AE875100549402 /* icon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 1AC14D8A22AE875100549402 /* icon.pdf */; };
2223
1AC76A9D23B6D9D0009BD2D7 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1AC76A9B23B6D9D0009BD2D7 /* InfoPlist.strings */; };
2324
F61A7AD61E818BF300EBF660 /* InputMethodKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F61A7AD51E818BF300EBF660 /* InputMethodKit.framework */; };
2425
/* End PBXBuildFile section */
2526

27+
/* Begin PBXCopyFilesBuildPhase section */
28+
1A8EF34A296B6A030006D7FC /* CopyFiles */ = {
29+
isa = PBXCopyFilesBuildPhase;
30+
buildActionMask = 2147483647;
31+
dstPath = /usr/share/man/man1/;
32+
dstSubfolderSpec = 0;
33+
files = (
34+
);
35+
runOnlyForDeploymentPostprocessing = 1;
36+
};
37+
/* End PBXCopyFilesBuildPhase section */
38+
2639
/* Begin PBXFileReference section */
2740
1A10FC3423BD7EBE00556BCE /* uninstall.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = uninstall.sh; sourceTree = "<group>"; };
2841
1A10FC3523BD824C00556BCE /* MathSymbolsInputPreferences-components.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "MathSymbolsInputPreferences-components.plist"; sourceTree = "<group>"; };
@@ -48,6 +61,8 @@
4861
1A6DBD9C23BA62EC00AA8924 /* package.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = package.sh; sourceTree = "<group>"; };
4962
1A6DBD9D23BA666B00AA8924 /* DEVELOPMENT.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = DEVELOPMENT.md; sourceTree = "<group>"; };
5063
1A6DBD9E23BA6F3500AA8924 /* InstallerSections.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = InstallerSections.plist; sourceTree = "<group>"; };
64+
1A8EF34C296B6A030006D7FC /* activate */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = activate; sourceTree = BUILT_PRODUCTS_DIR; };
65+
1A8EF34E296B6A030006D7FC /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
5166
1AC14D8A22AE875100549402 /* icon.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = icon.pdf; sourceTree = "<group>"; };
5267
1AC76A9C23B6D9D0009BD2D7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/InfoPlist.strings; sourceTree = "<group>"; };
5368
1AC9635C23BCFB7F00A67BC1 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
@@ -65,6 +80,13 @@
6580
);
6681
runOnlyForDeploymentPostprocessing = 0;
6782
};
83+
1A8EF349296B6A030006D7FC /* Frameworks */ = {
84+
isa = PBXFrameworksBuildPhase;
85+
buildActionMask = 2147483647;
86+
files = (
87+
);
88+
runOnlyForDeploymentPostprocessing = 0;
89+
};
6890
F61A7AB81E8182C100EBF660 /* Frameworks */ = {
6991
isa = PBXFrameworksBuildPhase;
7092
buildActionMask = 2147483647;
@@ -91,6 +113,14 @@
91113
path = MathSymbolsInputPreferences;
92114
sourceTree = "<group>";
93115
};
116+
1A8EF34D296B6A030006D7FC /* activate */ = {
117+
isa = PBXGroup;
118+
children = (
119+
1A8EF34E296B6A030006D7FC /* main.m */,
120+
);
121+
path = activate;
122+
sourceTree = "<group>";
123+
};
94124
F61A7AB21E8182C100EBF660 = {
95125
isa = PBXGroup;
96126
children = (
@@ -107,6 +137,7 @@
107137
1A6DBD9B23BA62EC00AA8924 /* distribution.xml */,
108138
F61A7ABD1E8182C100EBF660 /* MathSymbolsInput */,
109139
1A16BB4723B907E000E667C4 /* MathSymbolsInputPreferences */,
140+
1A8EF34D296B6A030006D7FC /* activate */,
110141
F61A7ABC1E8182C100EBF660 /* Products */,
111142
F61A7AD41E818BF300EBF660 /* Frameworks */,
112143
);
@@ -117,6 +148,7 @@
117148
children = (
118149
F61A7ABB1E8182C100EBF660 /* Math Symbols Input.app */,
119150
1A16BB4623B907E000E667C4 /* Math Symbols Input - Preferences.app */,
151+
1A8EF34C296B6A030006D7FC /* activate */,
120152
);
121153
name = Products;
122154
sourceTree = "<group>";
@@ -165,6 +197,23 @@
165197
productReference = 1A16BB4623B907E000E667C4 /* Math Symbols Input - Preferences.app */;
166198
productType = "com.apple.product-type.application";
167199
};
200+
1A8EF34B296B6A030006D7FC /* activate */ = {
201+
isa = PBXNativeTarget;
202+
buildConfigurationList = 1A8EF352296B6A030006D7FC /* Build configuration list for PBXNativeTarget "activate" */;
203+
buildPhases = (
204+
1A8EF348296B6A030006D7FC /* Sources */,
205+
1A8EF349296B6A030006D7FC /* Frameworks */,
206+
1A8EF34A296B6A030006D7FC /* CopyFiles */,
207+
);
208+
buildRules = (
209+
);
210+
dependencies = (
211+
);
212+
name = activate;
213+
productName = activate;
214+
productReference = 1A8EF34C296B6A030006D7FC /* activate */;
215+
productType = "com.apple.product-type.tool";
216+
};
168217
F61A7ABA1E8182C100EBF660 /* Math Symbols Input */ = {
169218
isa = PBXNativeTarget;
170219
buildConfigurationList = F61A7ACF1E8182C100EBF660 /* Build configuration list for PBXNativeTarget "Math Symbols Input" */;
@@ -189,7 +238,7 @@
189238
isa = PBXProject;
190239
attributes = {
191240
LastSwiftUpdateCheck = 1030;
192-
LastUpgradeCheck = 1200;
241+
LastUpgradeCheck = 1320;
193242
ORGANIZATIONNAME = "";
194243
TargetAttributes = {
195244
1A16BB4523B907E000E667C4 = {
@@ -200,6 +249,9 @@
200249
};
201250
};
202251
};
252+
1A8EF34B296B6A030006D7FC = {
253+
CreatedOnToolsVersion = 13.2.1;
254+
};
203255
F61A7ABA1E8182C100EBF660 = {
204256
CreatedOnToolsVersion = 8.2.1;
205257
LastSwiftMigration = 1320;
@@ -222,6 +274,7 @@
222274
targets = (
223275
F61A7ABA1E8182C100EBF660 /* Math Symbols Input */,
224276
1A16BB4523B907E000E667C4 /* Math Symbols Input - Preferences */,
277+
1A8EF34B296B6A030006D7FC /* activate */,
225278
);
226279
};
227280
/* End PBXProject section */
@@ -261,6 +314,14 @@
261314
);
262315
runOnlyForDeploymentPostprocessing = 0;
263316
};
317+
1A8EF348296B6A030006D7FC /* Sources */ = {
318+
isa = PBXSourcesBuildPhase;
319+
buildActionMask = 2147483647;
320+
files = (
321+
1A8EF34F296B6A030006D7FC /* main.m in Sources */,
322+
);
323+
runOnlyForDeploymentPostprocessing = 0;
324+
};
264325
F61A7AB71E8182C100EBF660 /* Sources */ = {
265326
isa = PBXSourcesBuildPhase;
266327
buildActionMask = 2147483647;
@@ -349,6 +410,39 @@
349410
};
350411
name = Release;
351412
};
413+
1A8EF350296B6A030006D7FC /* Debug */ = {
414+
isa = XCBuildConfiguration;
415+
buildSettings = {
416+
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
417+
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
418+
CLANG_ENABLE_OBJC_WEAK = YES;
419+
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
420+
CODE_SIGN_IDENTITY = "-";
421+
CODE_SIGN_STYLE = Automatic;
422+
GCC_C_LANGUAGE_STANDARD = gnu11;
423+
MACOSX_DEPLOYMENT_TARGET = 11.6;
424+
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
425+
MTL_FAST_MATH = YES;
426+
PRODUCT_NAME = "$(TARGET_NAME)";
427+
};
428+
name = Debug;
429+
};
430+
1A8EF351296B6A030006D7FC /* Release */ = {
431+
isa = XCBuildConfiguration;
432+
buildSettings = {
433+
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
434+
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
435+
CLANG_ENABLE_OBJC_WEAK = YES;
436+
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
437+
CODE_SIGN_IDENTITY = "-";
438+
CODE_SIGN_STYLE = Automatic;
439+
GCC_C_LANGUAGE_STANDARD = gnu11;
440+
MACOSX_DEPLOYMENT_TARGET = 11.6;
441+
MTL_FAST_MATH = YES;
442+
PRODUCT_NAME = "$(TARGET_NAME)";
443+
};
444+
name = Release;
445+
};
352446
F61A7ACD1E8182C100EBF660 /* Debug */ = {
353447
isa = XCBuildConfiguration;
354448
buildSettings = {
@@ -509,6 +603,15 @@
509603
defaultConfigurationIsVisible = 0;
510604
defaultConfigurationName = Release;
511605
};
606+
1A8EF352296B6A030006D7FC /* Build configuration list for PBXNativeTarget "activate" */ = {
607+
isa = XCConfigurationList;
608+
buildConfigurations = (
609+
1A8EF350296B6A030006D7FC /* Debug */,
610+
1A8EF351296B6A030006D7FC /* Release */,
611+
);
612+
defaultConfigurationIsVisible = 0;
613+
defaultConfigurationName = Release;
614+
};
512615
F61A7AB61E8182C100EBF660 /* Build configuration list for PBXProject "MathSymbolsInput" */ = {
513616
isa = XCConfigurationList;
514617
buildConfigurations = (

MathSymbolsInput.xcodeproj/xcshareddata/xcschemes/MathSymbolsInput.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1200"
3+
LastUpgradeVersion = "1320"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"

MathSymbolsInput.xcodeproj/xcshareddata/xcschemes/MathSymbolsInputPreferences.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1200"
3+
LastUpgradeVersion = "1320"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "1320"
4+
version = "1.3">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES">
8+
<BuildActionEntries>
9+
<BuildActionEntry
10+
buildForTesting = "YES"
11+
buildForRunning = "YES"
12+
buildForProfiling = "YES"
13+
buildForArchiving = "YES"
14+
buildForAnalyzing = "YES">
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "1A8EF34B296B6A030006D7FC"
18+
BuildableName = "activate"
19+
BlueprintName = "activate"
20+
ReferencedContainer = "container:MathSymbolsInput.xcodeproj">
21+
</BuildableReference>
22+
</BuildActionEntry>
23+
</BuildActionEntries>
24+
</BuildAction>
25+
<TestAction
26+
buildConfiguration = "Debug"
27+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29+
shouldUseLaunchSchemeArgsEnv = "YES">
30+
<Testables>
31+
</Testables>
32+
</TestAction>
33+
<LaunchAction
34+
buildConfiguration = "Debug"
35+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
36+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
37+
launchStyle = "0"
38+
useCustomWorkingDirectory = "NO"
39+
ignoresPersistentStateOnLaunch = "NO"
40+
debugDocumentVersioning = "YES"
41+
debugServiceExtension = "internal"
42+
allowLocationSimulation = "YES">
43+
<BuildableProductRunnable
44+
runnableDebuggingMode = "0">
45+
<BuildableReference
46+
BuildableIdentifier = "primary"
47+
BlueprintIdentifier = "1A8EF34B296B6A030006D7FC"
48+
BuildableName = "activate"
49+
BlueprintName = "activate"
50+
ReferencedContainer = "container:MathSymbolsInput.xcodeproj">
51+
</BuildableReference>
52+
</BuildableProductRunnable>
53+
</LaunchAction>
54+
<ProfileAction
55+
buildConfiguration = "Release"
56+
shouldUseLaunchSchemeArgsEnv = "YES"
57+
savedToolIdentifier = ""
58+
useCustomWorkingDirectory = "NO"
59+
debugDocumentVersioning = "YES">
60+
<BuildableProductRunnable
61+
runnableDebuggingMode = "0">
62+
<BuildableReference
63+
BuildableIdentifier = "primary"
64+
BlueprintIdentifier = "1A8EF34B296B6A030006D7FC"
65+
BuildableName = "activate"
66+
BlueprintName = "activate"
67+
ReferencedContainer = "container:MathSymbolsInput.xcodeproj">
68+
</BuildableReference>
69+
</BuildableProductRunnable>
70+
</ProfileAction>
71+
<AnalyzeAction
72+
buildConfiguration = "Debug">
73+
</AnalyzeAction>
74+
<ArchiveAction
75+
buildConfiguration = "Release"
76+
revealArchiveInOrganizer = "YES">
77+
</ArchiveAction>
78+
</Scheme>

activate/main.m

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#import <Carbon/Carbon.h>
2+
3+
static const char *kInstallLocation = "/Library/Input Methods/Math Symbols Input.app";
4+
static NSString *kProcessName = @"Math Symbols Input";
5+
static NSString *kSourceID = @"com.mathsymbolsinput.inputmethod.MathSymbolsInput";
6+
7+
static void logIfError(OSStatus status, NSString *message) {
8+
if (status != noErr) {
9+
NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil];
10+
NSLog(@"%@: %@", message, [error localizedDescription]);
11+
}
12+
}
13+
14+
// Enables and selects the input method after an install or upgrade.
15+
//
16+
// We sleep for a bit between steps because it seems like many things happen in
17+
// the background, and if we do some steps too quickly then things could be
18+
// left in an inconsistent state.
19+
int main(int argc, const char *argv[]) {
20+
@autoreleasepool {
21+
22+
// Running as root won't actually activate the input method and seems to
23+
// leave things broken until the next reboot.
24+
if (geteuid() == 0) {
25+
NSLog(@"Activate script should not be run as root, aborting");
26+
return 1;
27+
}
28+
29+
CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8 *) kInstallLocation, strlen(kInstallLocation), NO);
30+
NSLog(@"Registering input source %s", kInstallLocation);
31+
logIfError(TISRegisterInputSource(url), @"Could not register input source");
32+
CFRelease(url);
33+
[NSThread sleepForTimeInterval:1.0];
34+
35+
// Find our input method.
36+
TISInputSourceRef inputMethod = nil;
37+
CFArrayRef inputSources = TISCreateInputSourceList(NULL, YES);
38+
for (int i = 0; i < CFArrayGetCount(inputSources); i++) {
39+
TISInputSourceRef inputSource = (TISInputSourceRef) CFArrayGetValueAtIndex(inputSources, i);
40+
NSString *sourceID = (__bridge NSString *) TISGetInputSourceProperty(inputSource, kTISPropertyInputSourceID);
41+
if ([sourceID isEqualToString:kSourceID]) {
42+
inputMethod = inputSource;
43+
break;
44+
}
45+
}
46+
if (inputMethod == nil) {
47+
NSLog(@"Could not find input source %@", kSourceID);
48+
return 1;
49+
}
50+
51+
// We shouldn't kill an input method while it's active, so we disable it first.
52+
if (CFBooleanGetValue(TISGetInputSourceProperty(inputMethod, kTISPropertyInputSourceIsEnabled))) {
53+
NSLog(@"Disabling input source %@", kSourceID);
54+
logIfError(TISDisableInputSource(inputMethod), @"Could not disable input source");
55+
[NSThread sleepForTimeInterval:1.0];
56+
}
57+
58+
// We have to kill the old process for the new version to take effect. The
59+
// new process will be started automatically.
60+
NSLog(@"Killing process %@", kProcessName);
61+
NSTask *task = [NSTask launchedTaskWithLaunchPath:@"/usr/bin/killall" arguments:@[kProcessName]];
62+
[task waitUntilExit];
63+
[NSThread sleepForTimeInterval:1.0];
64+
65+
NSLog(@"Enabling input source %@", kSourceID);
66+
logIfError(TISEnableInputSource(inputMethod), @"Could not enable input source");
67+
[NSThread sleepForTimeInterval:1.0];
68+
69+
NSLog(@"Selecting input source %@", kSourceID);
70+
logIfError(TISSelectInputSource(inputMethod), @"Could not select input source");
71+
72+
CFRelease(inputSources);
73+
}
74+
return 0;
75+
}

0 commit comments

Comments
 (0)