Skip to content

Commit

Permalink
Repo // Add a Settings window to help users change keyLayouts.
Browse files Browse the repository at this point in the history
  • Loading branch information
ShikiSuen committed Oct 8, 2022
1 parent f6d4b82 commit 79f80ee
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 32 deletions.
11 changes: 1 addition & 10 deletions 3rdParty/vChewingProject/IMKUtils4RIME/IMKHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,7 @@ public enum IMKHelper {
public static let arrDynamicBasicKeyLayouts: [String] = [
"com.apple.keylayout.ZhuyinBopomofo",
"com.apple.keylayout.ZhuyinEten",
"org.atelierInmu.vChewing.keyLayouts.vchewingdachen",
"org.atelierInmu.vChewing.keyLayouts.vchewingmitac",
"org.atelierInmu.vChewing.keyLayouts.vchewingibm",
"org.atelierInmu.vChewing.keyLayouts.vchewingseigyou",
"org.atelierInmu.vChewing.keyLayouts.vchewingeten",
"org.unknown.keylayout.vChewingDachen",
"org.unknown.keylayout.vChewingFakeSeigyou",
"org.unknown.keylayout.vChewingETen",
"org.unknown.keylayout.vChewingIBM",
"org.unknown.keylayout.vChewingMiTAC",
// 不是威注音输入法,就不用插入威注音自己的 keylayouts 了。
]

public static var currentBasicKeyboardLayout: String {
Expand Down
3 changes: 2 additions & 1 deletion Properties.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import Foundation

@objc public class Properties: NSObject {
@objc public static let shared = Properties()
public static let kDefaultBasicKeyboardLayout = "com.apple.keylayout.ABC"

@AppProperty(key: "BasicKeyboardLayout", defaultValue: "")
@AppProperty(key: "BasicKeyboardLayout", defaultValue: "kDefaultBasicKeyboardLayout")
public var basicKeyboardLayout: String
}
8 changes: 8 additions & 0 deletions Squirrel.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
5B511F2F28EEC27A0019E25B /* TISInputSourceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B511F2728EEC27A0019E25B /* TISInputSourceExtension.swift */; };
5BA2241228EECC5C004DCA14 /* SquirrelInputController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA2241128EECC5C004DCA14 /* SquirrelInputController.swift */; };
5BA2241428EED286004DCA14 /* Properties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA2241328EED286004DCA14 /* Properties.swift */; };
5BB868C528F08081002FAEEC /* SquirrelSettingsWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB868C328F08081002FAEEC /* SquirrelSettingsWindow.swift */; };
5BB868C628F08081002FAEEC /* SquirrelSettingsWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BB868C428F08081002FAEEC /* SquirrelSettingsWindow.xib */; };
77AA68142588916F00A592E2 /* hk2s.json in Copy opencc Files */ = {isa = PBXBuildFile; fileRef = 77AA67E22588916300A592E2 /* hk2s.json */; };
77AA68152588916F00A592E2 /* HKVariants.ocd2 in Copy opencc Files */ = {isa = PBXBuildFile; fileRef = 77AA67DC2588916300A592E2 /* HKVariants.ocd2 */; };
77AA68162588916F00A592E2 /* HKVariantsRev.ocd2 in Copy opencc Files */ = {isa = PBXBuildFile; fileRef = 77AA67E02588916300A592E2 /* HKVariantsRev.ocd2 */; };
Expand Down Expand Up @@ -257,6 +259,8 @@
5B511F2728EEC27A0019E25B /* TISInputSourceExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TISInputSourceExtension.swift; sourceTree = "<group>"; };
5BA2241128EECC5C004DCA14 /* SquirrelInputController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SquirrelInputController.swift; sourceTree = "<group>"; };
5BA2241328EED286004DCA14 /* Properties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Properties.swift; sourceTree = "<group>"; };
5BB868C328F08081002FAEEC /* SquirrelSettingsWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SquirrelSettingsWindow.swift; sourceTree = "<group>"; };
5BB868C428F08081002FAEEC /* SquirrelSettingsWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SquirrelSettingsWindow.xib; sourceTree = "<group>"; };
77AA67DC2588916300A592E2 /* HKVariants.ocd2 */ = {isa = PBXFileReference; lastKnownFileType = file; path = HKVariants.ocd2; sourceTree = "<group>"; };
77AA67DD2588916300A592E2 /* t2s.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = t2s.json; sourceTree = "<group>"; };
77AA67DE2588916300A592E2 /* t2tw.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = t2tw.json; sourceTree = "<group>"; };
Expand Down Expand Up @@ -403,6 +407,8 @@
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
A45578F41146A75200592C6E /* MainMenu.xib */,
446C01D61F767BD400A6C23E /* Assets.xcassets */,
5BB868C328F08081002FAEEC /* SquirrelSettingsWindow.swift */,
5BB868C428F08081002FAEEC /* SquirrelSettingsWindow.xib */,
);
name = Resources;
sourceTree = "<group>";
Expand Down Expand Up @@ -631,6 +637,7 @@
A4FC48CB0F6530EF0069BE81 /* Localizable.strings in Resources */,
44986A95184B421700B3278D /* LICENSE.txt in Resources */,
44986A96184B421700B3278D /* README.md in Resources */,
5BB868C628F08081002FAEEC /* SquirrelSettingsWindow.xib in Resources */,
44F7708F152B3334005CF491 /* dsa_pub.pem in Resources */,
44CD7D9F1828D981006E9222 /* rime.pdf in Resources */,
);
Expand All @@ -654,6 +661,7 @@
5BA2241428EED286004DCA14 /* Properties.swift in Sources */,
5B511F1C28EEC25D0019E25B /* SquirrelInputController.swift in Sources */,
4443A83A1828CC5100731305 /* input_source.m in Sources */,
5BB868C528F08081002FAEEC /* SquirrelSettingsWindow.swift in Sources */,
5B511F2F28EEC27A0019E25B /* TISInputSourceExtension.swift in Sources */,
5B511F2A28EEC27A0019E25B /* CocoaExtension_Misc.swift in Sources */,
5BA2241228EECC5C004DCA14 /* SquirrelInputController.swift in Sources */,
Expand Down
2 changes: 2 additions & 0 deletions SquirrelApplicationDelegate.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "SquirrelApplicationDelegate.h"

#import <rime_api.h>
#import "Squirrel-Swift.h"
#import "SquirrelConfig.h"
#import "SquirrelPanel.h"

Expand All @@ -25,6 +26,7 @@ -(IBAction)syncUserData:(id)sender
-(IBAction)configure:(id)sender
{
[[NSWorkspace sharedWorkspace] openFile:(@"~/Library/Rime").stringByStandardizingPath];
[SquirrelSettingsWindow show];
}

-(IBAction)openWiki:(id)sender
Expand Down
19 changes: 6 additions & 13 deletions SquirrelInputController.m
Original file line number Diff line number Diff line change
Expand Up @@ -271,23 +271,13 @@ -(NSUInteger)recognizedEvents:(id)sender

-(void)activateServer:(id)sender
{
// activateServer() 與 setValue() 是組合拳,前者執行之後必定會立刻執行後者。
// 所以千萬不要讓前者做後者會做的事情,否則很容易會出現重複計算、乃至迴圈計算。
// 同一個客體應用之間切換輸入法的時候,可能會出現僅觸發 setValue 的情況。
//NSLog(@"activateServer:");
[self overrideKeyboard];
_preeditString = @"";
}

- (void)setValue:(id)value forTag:(long)tag client:(id)sender
{
//NSLog(@"setValue:");

// 以防萬一:讓 setValue 的行為僅對自身起作用。
if ([value isKindOfClass:[NSString class]] && [value containsString: [NSBundle mainBundle].bundleIdentifier]) {
if ([NSApp.squirrelAppDelegate.config getBool:@"us_keyboard_layout"]) {
[self overrideKeyboard];
}
}

_preeditString = @"";
}

-(instancetype)initWithServer:(IMKServer*)server delegate:(id)delegate client:(id)inputClient
Expand All @@ -297,6 +287,8 @@ -(instancetype)initWithServer:(IMKServer*)server delegate:(id)delegate client:(i
_currentClient = inputClient;
[self createSession];
}
[self registerSessionControllerIntoSet];

return self;
}

Expand Down Expand Up @@ -372,6 +364,7 @@ -(NSArray*)candidates:(id)sender

-(void)dealloc
{
[self removeSessionControllerFromSet];
[self destroySession];
}

Expand Down
33 changes: 25 additions & 8 deletions SquirrelInputController.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
import Foundation

@objc public extension SquirrelInputController { static var basicKeyboardLayoutNameVerified: String {
let result = Properties.shared.basicKeyboardLayout
return (TISInputSource.generate(from: result) != nil) ? result : "com.apple.keylayout.ABC"
}
public var sessionControllers: Set<SquirrelInputController> = .init()

func overrideKeyboard() {
DispatchQueue.main.async { [self] in
self.client()?.overrideKeyboard(withKeyboardNamed: Self.basicKeyboardLayoutNameVerified)
@objc public extension SquirrelInputController {
static var isBasicKeyboardLayoutDefinedValidInPlist: Bool {
TISInputSource.generate(from: Properties.shared.basicKeyboardLayout) != nil
}

static var basicKeyboardLayoutNameVerified: String? {
let result = Properties.shared.basicKeyboardLayout
return (TISInputSource.generate(from: result) != nil) ? result : nil
}

func overrideKeyboard() {
DispatchQueue.main.async { [self] in
if let verified = Self.basicKeyboardLayoutNameVerified {
client()?.overrideKeyboard(withKeyboardNamed: verified)
}
}
}

func registerSessionControllerIntoSet() {
sessionControllers.insert(self)
}

func removeSessionControllerFromSet() {
sessionControllers.remove(self)
}
}
}
62 changes: 62 additions & 0 deletions SquirrelSettingsWindow.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import Cocoa

@objc class SquirrelSettingsWindow: NSWindowController {
@IBOutlet var basicKeyboardLayoutButton: NSPopUpButton!
@IBOutlet var theWindow: NSWindow!

@objc static var shared: SquirrelSettingsWindow?

override func windowDidLoad() {
super.windowDidLoad()
window = theWindow
initiateKeyLayoutDropdownButton()
}

@objc static func show() {
if shared == nil {
shared = .init(windowNibName: "SquirrelSettingsWindow")
}
guard let shared = shared else { return }
shared.window?.center()
shared.window?.orderFrontRegardless() // 逼著屬性視窗往最前方顯示
shared.window?.level = .statusBar
if #available(macOS 10.10, *) {
shared.window?.titlebarAppearsTransparent = true
}
NSApp.setActivationPolicy(.accessory)
NSApp.activate(ignoringOtherApps: true)
}
}

extension SquirrelSettingsWindow {
func initiateKeyLayoutDropdownButton() {
var usKeyboardLayoutItem: NSMenuItem?
var chosenBaseKeyboardLayoutItem: NSMenuItem?
basicKeyboardLayoutButton.menu?.removeAllItems()
let basicKeyboardLayoutID = Properties.shared.basicKeyboardLayout

for source in IMKHelper.allowedBasicLayoutsAsTISInputSources {
guard let source = source else {
basicKeyboardLayoutButton.menu?.addItem(NSMenuItem.separator())
continue
}
let menuItem = NSMenuItem()
menuItem.title = source.vChewingLocalizedName
menuItem.representedObject = source.identifier
if source.identifier == "com.apple.keylayout.US" { usKeyboardLayoutItem = menuItem }
if basicKeyboardLayoutID == source.identifier { chosenBaseKeyboardLayoutItem = menuItem }
basicKeyboardLayoutButton.menu?.addItem(menuItem)
}

basicKeyboardLayoutButton.select(chosenBaseKeyboardLayoutItem ?? usKeyboardLayoutItem)
}

@IBAction func updateBasicKeyboardLayoutAction(_: Any) {
if let sourceID = basicKeyboardLayoutButton.selectedItem?.representedObject as? String {
Properties.shared.basicKeyboardLayout = sourceID
sessionControllers.forEach {
$0.overrideKeyboard()
}
}
}
}
66 changes: 66 additions & 0 deletions SquirrelSettingsWindow.xib
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21225" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21225"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="SquirrelSettingsWindow" customModule="Squirrel" customModuleProvider="target">
<connections>
<outlet property="basicKeyboardLayoutButton" destination="SAs-ky-Hj4" id="Cm4-11-q9O"/>
<outlet property="theWindow" destination="F0z-JX-Cv5" id="Y9w-af-H2Y"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Squirrel Settings" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" titlebarAppearsTransparent="YES" id="F0z-JX-Cv5" userLabel="SquirrelSettingsWindow">
<windowStyleMask key="styleMask" titled="YES" closable="YES" fullSizeContentView="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="381" height="82"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="875"/>
<view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="381" height="82"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<stackView distribution="fill" orientation="horizontal" alignment="top" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" fixedFrame="YES" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="icc-tr-Rcw">
<rect key="frame" x="20" y="20" width="330" height="20"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="1E1-vm-e4q">
<rect key="frame" x="-2" y="4" width="71" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="KeyLayout:" id="5TS-Z1-9jq">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="SAs-ky-Hj4">
<rect key="frame" x="72" y="-4" width="262" height="25"/>
<constraints>
<constraint firstAttribute="width" constant="255" id="rSG-jt-qHe"/>
</constraints>
<popUpButtonCell key="cell" type="push" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" id="EYT-Eu-Ij3">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="EN3-AD-X99"/>
</popUpButtonCell>
<connections>
<action selector="updateBasicKeyboardLayoutAction:" target="-2" id="omK-oP-bLn"/>
</connections>
</popUpButton>
</subviews>
<visibilityPriorities>
<integer value="1000"/>
<integer value="1000"/>
</visibilityPriorities>
<customSpacing>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
</customSpacing>
</stackView>
</subviews>
</view>
<point key="canvasLocation" x="-1.5" y="16"/>
</window>
</objects>
</document>

0 comments on commit 79f80ee

Please sign in to comment.