mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-05 00:15:32 +00:00
feat(mac): install script
First steps towards a clean install script for Keyman for Mac. Some steps still out- of-order for now, particularly opening System Preferences to allow Keyman before Keyman has run for first time.
This commit is contained in:
parent
071dd868f2
commit
f8ea457325
94 changed files with 396 additions and 15 deletions
|
|
@ -17,11 +17,11 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>Keyman $(PRODUCT_VERSION) for macOS</string>
|
||||
<string>13.0.99</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(PRODUCT_VERSION)</string>
|
||||
<string>13.0.99</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -2,8 +2,6 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSAppleEventsUsageDescription</key>
|
||||
<string>Keyman needs to send key events to the target application.</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
|
|
@ -25,6 +23,8 @@
|
|||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>$(GET_INFO_STRING)</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(PRODUCT_VERSION)</string>
|
||||
<string>13.0.99</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
|
@ -51,13 +51,11 @@
|
|||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(PRODUCT_VERSION)</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>$(GET_INFO_STRING)</string>
|
||||
<string>13.0.99</string>
|
||||
<key>Fabric</key>
|
||||
<dict>
|
||||
<key>APIKey</key>
|
||||
<string>68056571ada44ad2d93864380272808ada308b24</string>
|
||||
<string>4efced22a226f98e05442a7e472b377d89fcc294</string>
|
||||
<key>Kits</key>
|
||||
<array>
|
||||
<dict>
|
||||
|
|
@ -80,6 +78,8 @@
|
|||
<true/>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
<key>NSAppleEventsUsageDescription</key>
|
||||
<string>Keyman needs to send key events to the target application.</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>$(COPYRIGHT_STRING)</string>
|
||||
<key>NSMainNibFile</key>
|
||||
|
|
|
|||
|
|
@ -44,11 +44,11 @@ popd > /dev/null
|
|||
|
||||
. $KEYMAN_MACIM_BASE_PATH/../bashHelperFunctions.sh
|
||||
|
||||
KM_APP_NAME="Keyman.app"
|
||||
SOURCE_KM_APP="$KEYMAN_MACIM_BASE_PATH/build/Release/$KM_APP_NAME"
|
||||
KM_APP_NAME="Install Keyman.app"
|
||||
OUTPUT_DIR="$KEYMAN_MACIM_BASE_PATH/output"
|
||||
STAGING_DIR="$OUTPUT_DIR/temp"
|
||||
DEST_DIR="$OUTPUT_DIR/upload"
|
||||
SOURCE_KM_APP="$OUTPUT_DIR/$KM_APP_NAME"
|
||||
ADD_VERSION_TO_DEST_DIR=true
|
||||
TEMPLATE_IMAGE="$KEYMAN_MACIM_BASE_PATH/Keyman-template.dmg"
|
||||
VERBOSITY=""
|
||||
|
|
@ -139,6 +139,8 @@ elif [[ ! -d "$DEST_DIR" ]]; then
|
|||
fail "Destination dir exists but is not a directory: $2"
|
||||
fi
|
||||
|
||||
# TODO: Check that no Keyman volume is already mounted.
|
||||
|
||||
# Step 1 - Copy template to working copy to prevent unintended changes
|
||||
WORKING_COPY_OF_IMAGE="$OUTPUT_DIR/Keyman-temp-$KM_VERSION.dmg"
|
||||
displayInfo "Copying \"$TEMPLATE_IMAGE\" to \"$WORKING_COPY_OF_IMAGE\"..."
|
||||
|
|
@ -165,9 +167,13 @@ fi
|
|||
|
||||
# Step 3 - Replace existing application files with new version
|
||||
displayInfo "Copying files from \"$SOURCE_KM_APP\"..."
|
||||
find "$DEST_KM_APP" -mindepth 1 -maxdepth 1
|
||||
echo "---------"
|
||||
find "$DEST_KM_APP" -mindepth 1 -maxdepth 1 -print0 | xargs -0 rm -rf
|
||||
cp -fR "$SOURCE_KM_APP/" "$DEST_KM_APP"
|
||||
|
||||
ls -la /Volumes/Keyman/background/
|
||||
|
||||
# Step 4 - Detach/unmount the temporary image/staging area
|
||||
displayInfo "Detaching \"$WORKING_COPY_OF_IMAGE\""
|
||||
hdiutil detach $STAGING_DIR $VERBOSITY
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>$(GET_INFO_STRING)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
|
|
@ -15,13 +17,11 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>Keyman Engine $(PRODUCT_VERSION) for macOS</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>$(GET_INFO_STRING)</string>
|
||||
<string>13.0.99</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(PRODUCT_VERSION)</string>
|
||||
<string>13.0.99</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>$(COPYRIGHT_STRING_RIGHTS)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# Include our resource functions; they're pretty useful!
|
||||
. ../resources/shellHelperFunctions.sh
|
||||
|
||||
|
|
@ -445,6 +447,10 @@ if $LOCALDEPLOY ; then
|
|||
elif $PREPRELEASE ; then
|
||||
echo_heading "Preparing files for release deployment..."
|
||||
# Create the disk image
|
||||
pushd setup
|
||||
eval "./build.sh"
|
||||
popd
|
||||
|
||||
eval "$KM4MIM_BASE_PATH/make-km-dmg.sh" -version $KM_VERSION $QUIET_FLAG
|
||||
if [ $? == 0 ]; then
|
||||
displayInfo "Creating disk image succeeded!" ""
|
||||
|
|
|
|||
114
mac/setup/Install Keyman.app/Contents/Info.plist
Normal file
114
mac/setup/Install Keyman.app/Contents/Info.plist
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>18A391019</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>*</string>
|
||||
</array>
|
||||
<key>CFBundleTypeOSTypes</key>
|
||||
<array>
|
||||
<string>****</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>CocoaApplet</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>applet</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.keyman.mac.installKeyman</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Install Keyman</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>aplt</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>11M392v</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>macosx</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>10.15</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>19C38</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>macosx10.15internal</string>
|
||||
<key>DTXcode</key>
|
||||
<string>1100</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>11M392v</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.utilities</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.15</string>
|
||||
<key>NSAppleEventsUsageDescription</key>
|
||||
<string>This script needs to control other applications to run.</string>
|
||||
<key>NSAppleMusicUsageDescription</key>
|
||||
<string>This script needs access to your music to run.</string>
|
||||
<key>NSCalendarsUsageDescription</key>
|
||||
<string>This script needs access to your calendars to run.</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>This script needs access to your camera to run.</string>
|
||||
<key>NSContactsUsageDescription</key>
|
||||
<string>This script needs access to your contacts to run.</string>
|
||||
<key>NSHomeKitUsageDescription</key>
|
||||
<string>This script needs access to your HomeKit Home to run.</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright 2020 SIL International.</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>This script needs access to your microphone to run.</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>This script needs access to your photos to run.</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>NSRemindersUsageDescription</key>
|
||||
<string>This script needs access to your reminders to run.</string>
|
||||
<key>NSSiriUsageDescription</key>
|
||||
<string>This script needs access to Siri to run.</string>
|
||||
<key>NSSystemAdministrationUsageDescription</key>
|
||||
<string>This script needs access to administer this system to run.</string>
|
||||
<key>WindowState</key>
|
||||
<dict>
|
||||
<key>bundleDividerCollapsed</key>
|
||||
<false/>
|
||||
<key>bundlePositionOfDivider</key>
|
||||
<real>1162</real>
|
||||
<key>dividerCollapsed</key>
|
||||
<false/>
|
||||
<key>eventLogLevel</key>
|
||||
<integer>2</integer>
|
||||
<key>name</key>
|
||||
<string>ScriptWindowState</string>
|
||||
<key>positionOfDivider</key>
|
||||
<real>594</real>
|
||||
<key>savedFrame</key>
|
||||
<string>148 235 1461 732 0 0 1920 1057 </string>
|
||||
<key>selectedTab</key>
|
||||
<string>result</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
mac/setup/Install Keyman.app/Contents/MacOS/CocoaApplet
Executable file
BIN
mac/setup/Install Keyman.app/Contents/MacOS/CocoaApplet
Executable file
Binary file not shown.
1
mac/setup/Install Keyman.app/Contents/PkgInfo
Normal file
1
mac/setup/Install Keyman.app/Contents/PkgInfo
Normal file
|
|
@ -0,0 +1 @@
|
|||
APPLaplt
|
||||
BIN
mac/setup/Install Keyman.app/Contents/Resources/Base.lproj/MainMenu.nib
generated
Normal file
BIN
mac/setup/Install Keyman.app/Contents/Resources/Base.lproj/MainMenu.nib
generated
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mac/setup/Install Keyman.app/Contents/Resources/applet.icns
Normal file
BIN
mac/setup/Install Keyman.app/Contents/Resources/applet.icns
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,5 @@
|
|||
{\rtf1\ansi\ansicpg1252\cocoartf2511
|
||||
\cocoatextscaling0\cocoaplatform0{\fonttbl}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
{\*\expandedcolortbl;;}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mac/setup/Install Keyman.app/Contents/Resources/hu.lproj/MainMenu.nib
generated
Normal file
BIN
mac/setup/Install Keyman.app/Contents/Resources/hu.lproj/MainMenu.nib
generated
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mac/setup/Install Keyman.app/Contents/Resources/tr.lproj/MainMenu.nib
generated
Normal file
BIN
mac/setup/Install Keyman.app/Contents/Resources/tr.lproj/MainMenu.nib
generated
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
101
mac/setup/build.sh
Executable file
101
mac/setup/build.sh
Executable file
|
|
@ -0,0 +1,101 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
# Include our resource functions; they're pretty useful!
|
||||
. ../../resources/shellHelperFunctions.sh
|
||||
|
||||
# Please note that this build script (understandably) assumes that it is running on Mac OS X.
|
||||
verify_on_mac
|
||||
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
|
||||
SOURCEAPP="./Install Keyman.app"
|
||||
TARGETPATH=../Keyman4MacIM/output
|
||||
TARGETAPP="$TARGETPATH/Install Keyman.app"
|
||||
KEYMANAPP=../Keyman4MacIM/build/Release/Keyman.app
|
||||
|
||||
#
|
||||
# Build textinputsource
|
||||
#
|
||||
|
||||
pushd textinputsource
|
||||
./build.sh
|
||||
popd
|
||||
|
||||
#
|
||||
# Build install candidate of "Install Keyman"
|
||||
#
|
||||
|
||||
# TODO: get script folder so we can run this from anywhere safely
|
||||
# TODO: set version number in install image
|
||||
|
||||
# Remove old install image
|
||||
mkdir -p "$TARGETPATH"
|
||||
rm -rf "$TARGETAPP" || true
|
||||
|
||||
# Copy new install image to output foldercer
|
||||
cp -R "$SOURCEAPP" "$TARGETPATH/"
|
||||
|
||||
# Copy Keyman.app into install image
|
||||
cp -R "$KEYMANAPP" "$TARGETAPP/Contents/MacOS/Keyman.app"
|
||||
|
||||
# Copy textinputsource into install image
|
||||
cp textinputsource/textinputsource "$TARGETAPP/Contents/MacOS/textinputsource"
|
||||
|
||||
# NOW TO notarize...
|
||||
xattr -rc "$TARGETAPP"
|
||||
codesign --force --options runtime --deep --sign "${CERTIFICATE_ID}" "$TARGETAPP"
|
||||
|
||||
#
|
||||
# Notarize the app (copied from ../build.sh)
|
||||
# TODO: merge notarization into function
|
||||
#
|
||||
|
||||
TARGET_ZIP_PATH="$TARGETPATH/Install Keyman.zip"
|
||||
TARGET_APP_PATH="$TARGETAPP"
|
||||
ALTOOL_LOG_PATH="$TARGETPATH/altool.log"
|
||||
|
||||
echo_heading "Zipping Install Keyman.app for notarization to $TARGET_ZIP_PATH"
|
||||
|
||||
/usr/bin/ditto -c -k --keepParent "$TARGET_APP_PATH" "$TARGET_ZIP_PATH"
|
||||
|
||||
echo_heading "Uploading Install Keyman.zip to Apple for notarization"
|
||||
|
||||
xcrun altool --notarize-app --primary-bundle-id "com.Keyman.install.zip" --asc-provider "$APPSTORECONNECT_PROVIDER" --username "$APPSTORECONNECT_USERNAME" --password @env:APPSTORECONNECT_PASSWORD --file "$TARGET_ZIP_PATH" --output-format xml > $ALTOOL_LOG_PATH || fail "altool failed"
|
||||
cat "$ALTOOL_LOG_PATH"
|
||||
|
||||
ALTOOL_UUID=$(/usr/libexec/PlistBuddy -c "Print notarization-upload:RequestUUID" "$ALTOOL_LOG_PATH")
|
||||
ALTOOL_FINISHED=0
|
||||
|
||||
while [ $ALTOOL_FINISHED -eq 0 ]
|
||||
do
|
||||
# We'll sleep 30 seconds before checking status, to give the altool server time to process the archive
|
||||
echo "Waiting 30 seconds for status"
|
||||
sleep 30
|
||||
xcrun altool --notarization-info "$ALTOOL_UUID" --username "$APPSTORECONNECT_USERNAME" --password @env:APPSTORECONNECT_PASSWORD --output-format xml > "$ALTOOL_LOG_PATH" || fail "altool failed"
|
||||
ALTOOL_STATUS=$(/usr/libexec/PlistBuddy -c "Print notarization-info:Status" "$ALTOOL_LOG_PATH")
|
||||
if [ "$ALTOOL_STATUS" == "success" ]; then
|
||||
ALTOOL_FINISHED=1
|
||||
elif [ "$ALTOOL_STATUS" != "in progress" ]; then
|
||||
# Probably failing with 'invalid'
|
||||
cat "$ALTOOL_LOG_PATH"
|
||||
ALTOOL_LOG_URL=$(/usr/libexec/PlistBuddy -c "Print notarization-info:LogFileURL" "$ALTOOL_LOG_PATH")
|
||||
curl "$ALTOOL_LOG_URL"
|
||||
fail "Notarization failed with $ALTOOL_STATUS; check log at $ALTOOL_LOG_PATH"
|
||||
fi
|
||||
done
|
||||
|
||||
echo_heading "Notarization completed successfully. Review logs below for any warnings."
|
||||
cat "$ALTOOL_LOG_PATH"
|
||||
ALTOOL_LOG_URL=$(/usr/libexec/PlistBuddy -c "Print notarization-info:LogFileURL" "$ALTOOL_LOG_PATH")
|
||||
curl "$ALTOOL_LOG_URL"
|
||||
echo
|
||||
echo_heading "Attempting to staple notarization to Install Keyman.app"
|
||||
xcrun stapler staple "$TARGET_APP_PATH" || fail "stapler failed"
|
||||
|
||||
# Done.
|
||||
# Now, we can add "Install Keyman.app" to the .dmg for distribution!
|
||||
4
mac/setup/textinputsource/build.sh
Executable file
4
mac/setup/textinputsource/build.sh
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
set -u
|
||||
gcc -framework Carbon -o textinputsource main.c
|
||||
144
mac/setup/textinputsource/main.c
Normal file
144
mac/setup/textinputsource/main.c
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
file
|
||||
main.c
|
||||
|
||||
function
|
||||
to manipulate text input source, i.e.,
|
||||
- print currently selected source,
|
||||
- select specified source (enable it as needed)
|
||||
- enable specified source,
|
||||
- disable specified source,
|
||||
- toggle enabled/disabled state of specified source.
|
||||
|
||||
compile
|
||||
gcc -framework Carbon -o textinputsource main.c
|
||||
|
||||
usage e.g.
|
||||
./textinputsource [-s|e|d|t name]
|
||||
|
||||
given no arguments, it will print the current source name.
|
||||
options:
|
||||
-s : select source name (enable it as needed)
|
||||
-e : enable source name
|
||||
-d : disable source name
|
||||
-t : toggle enabled/disabled on source name
|
||||
|
||||
|
||||
Originally found at https://discussions.apple.com/thread/5610262
|
||||
*/
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <libgen.h> // basename
|
||||
|
||||
TISInputSourceRef getInputSourceByName(char *);
|
||||
|
||||
int
|
||||
main (int argc, char * argv[])
|
||||
{
|
||||
int ret = -1;
|
||||
int c;
|
||||
TISInputSourceRef tis;
|
||||
CFStringRef name;
|
||||
OSStatus err = 0;
|
||||
|
||||
while ((c = getopt(argc, argv, "s:e:d:t:h")) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 's':
|
||||
tis = getInputSourceByName(optarg);
|
||||
if (tis)
|
||||
{
|
||||
CFBooleanRef enabled = TISGetInputSourceProperty(tis, kTISPropertyInputSourceIsEnabled);
|
||||
if (enabled == kCFBooleanFalse)
|
||||
TISEnableInputSource(tis);
|
||||
err = TISSelectInputSource(tis);
|
||||
CFRelease(tis);
|
||||
}
|
||||
ret = tis ? (int) err : 1;
|
||||
break;
|
||||
case 'e':
|
||||
tis = getInputSourceByName(optarg);
|
||||
if (tis)
|
||||
{
|
||||
err = TISEnableInputSource(tis);
|
||||
CFRelease(tis);
|
||||
}
|
||||
ret = tis ? (int) err : 1;
|
||||
break;
|
||||
case 'd':
|
||||
tis = getInputSourceByName(optarg);
|
||||
if (tis)
|
||||
{
|
||||
err = TISDisableInputSource(tis);
|
||||
CFRelease(tis);
|
||||
}
|
||||
ret = tis ? (int) err : 1;
|
||||
break;
|
||||
case 't':
|
||||
tis = getInputSourceByName(optarg);
|
||||
if (tis)
|
||||
{
|
||||
CFBooleanRef enabled = TISGetInputSourceProperty(tis, kTISPropertyInputSourceIsEnabled);
|
||||
if (enabled == kCFBooleanTrue)
|
||||
err = TISDisableInputSource(tis);
|
||||
else
|
||||
err = TISEnableInputSource(tis);
|
||||
CFRelease(tis);
|
||||
}
|
||||
ret = tis ? (int) err : 1;
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
fprintf(stderr, "Usage: %s %s\n\t\%s\n\t%s\n\t%s\n\t%s\n\t%s\n",
|
||||
basename(argv[0]),
|
||||
"[-s|e|d|t name]",
|
||||
"-s : select source name (enable it as needed)",
|
||||
"-e : enable source name",
|
||||
"-d : disable source name",
|
||||
"-t : toggle enabled/disabled of source name",
|
||||
"no arguments : print current source name"
|
||||
);
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret == -1) // no args: print current keyboard input source
|
||||
{
|
||||
tis = TISCopyCurrentKeyboardInputSource();
|
||||
name = TISGetInputSourceProperty(tis, kTISPropertyLocalizedName);
|
||||
int len = CFStringGetLength(name) * 4 + 1;
|
||||
char cname[len];
|
||||
bool b = CFStringGetCString(name, cname, len, kCFStringEncodingUTF8);
|
||||
printf("%s\n", b ? cname : "");
|
||||
ret = b ? 0 : 1;
|
||||
}
|
||||
if (err != noErr)
|
||||
fprintf(stderr, "Text Input Source Services error: %d\n", (int) err);
|
||||
return ret;
|
||||
}
|
||||
|
||||
TISInputSourceRef
|
||||
getInputSourceByName(char *cname)
|
||||
{
|
||||
// char *cname : input source name in UTF-8 terminated by null character
|
||||
// return TISInputSourceRef or NULL : text input source reference (retained)
|
||||
|
||||
CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, cname, kCFStringEncodingUTF8);
|
||||
CFStringRef keys[] = { kTISPropertyLocalizedName };
|
||||
CFStringRef values[] = { name };
|
||||
CFDictionaryRef dict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 1, NULL, NULL);
|
||||
CFArrayRef array = TISCreateInputSourceList(dict, true);
|
||||
CFRelease(dict);
|
||||
CFRelease(name);
|
||||
if (!array)
|
||||
{
|
||||
fprintf(stderr, "No such text input source: %s\n", optarg);
|
||||
return NULL;
|
||||
}
|
||||
TISInputSourceRef tis = (TISInputSourceRef) CFArrayGetValueAtIndex(array, 0);
|
||||
CFRetain(tis);
|
||||
CFRelease(array);
|
||||
return tis;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue