From c56f2d3c8d115faccb974d32daa3007c9f2923d0 Mon Sep 17 00:00:00 2001
From: "Colin T.A. Gray"
Date: Wed, 27 Feb 2019 10:58:43 -0500
Subject: [PATCH 1/6] adds 'Mods only' visualizer
---
keycastr/KeyCastr.xcodeproj/project.pbxproj | 170 ++++++++++++++++
keycastr/Mods-Info.plist | 22 +++
keycastr/Mods.nib/designable.nib | 23 +++
keycastr/Mods.nib/keyedobjects.nib | Bin 0 -> 1396 bytes
keycastr/ModsVisualizer.h | 61 ++++++
keycastr/ModsVisualizer.m | 207 ++++++++++++++++++++
6 files changed, 483 insertions(+)
create mode 100644 keycastr/Mods-Info.plist
create mode 100644 keycastr/Mods.nib/designable.nib
create mode 100644 keycastr/Mods.nib/keyedobjects.nib
create mode 100644 keycastr/ModsVisualizer.h
create mode 100644 keycastr/ModsVisualizer.m
diff --git a/keycastr/KeyCastr.xcodeproj/project.pbxproj b/keycastr/KeyCastr.xcodeproj/project.pbxproj
index 8b3e3bb..5c363ec 100644
--- a/keycastr/KeyCastr.xcodeproj/project.pbxproj
+++ b/keycastr/KeyCastr.xcodeproj/project.pbxproj
@@ -7,6 +7,13 @@
objects = {
/* Begin PBXBuildFile section */
+ 1DB8252B2226E86500E123AA /* ModsVisualizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1DB825272226E86500E123AA /* ModsVisualizer.h */; };
+ 1DB8252C2226E86500E123AA /* Mods.nib in Resources */ = {isa = PBXBuildFile; fileRef = 1DB825282226E86500E123AA /* Mods.nib */; };
+ 1DB8252D2226E86500E123AA /* Mods-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 1DB825292226E86500E123AA /* Mods-Info.plist */; };
+ 1DB8252E2226E86500E123AA /* ModsVisualizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1DB8252A2226E86500E123AA /* ModsVisualizer.m */; };
+ 1DB8253E2226E8D100E123AA /* ModsVisualizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1DB8252A2226E86500E123AA /* ModsVisualizer.m */; };
+ 1DB8253F2226E8DA00E123AA /* Mods.nib in Resources */ = {isa = PBXBuildFile; fileRef = 1DB825282226E86500E123AA /* Mods.nib */; };
+ 1DB825402226EC2100E123AA /* Mods.kcplugin in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1DB8253C2226E8A000E123AA /* Mods.kcplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
324AD25E40F9EFA6F54FA36A /* KCKeycastrEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 324AD6721F5E3C6D50AE104A /* KCKeycastrEvent.h */; };
324AD36C18A447EB8EDCE7B7 /* KCDefaultVisualizer.nib in Resources */ = {isa = PBXBuildFile; fileRef = 324AD93D2D9827CC6B6996A8 /* KCDefaultVisualizer.nib */; };
324AD7AC994A031550F38591 /* KCKeycastrEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 324ADBA0D37774E36EA35A2E /* KCKeycastrEvent.m */; };
@@ -71,6 +78,13 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
+ 1DB825412226EC3200E123AA /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 1DB8252F2226E8A000E123AA;
+ remoteInfo = Mods;
+ };
3D1646D40F43DCB200CA65AD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
@@ -297,6 +311,7 @@
dstPath = "";
dstSubfolderSpec = 13;
files = (
+ 1DB825402226EC2100E123AA /* Mods.kcplugin in CopyFiles */,
3D1648C20F451EDB00CA65AD /* Svelte.kcplugin in CopyFiles */,
3D1646690F43D76D00CA65AD /* KCDefaultVisualizer.kcplugin in CopyFiles */,
);
@@ -329,6 +344,11 @@
/* Begin PBXFileReference section */
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; };
+ 1DB825272226E86500E123AA /* ModsVisualizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModsVisualizer.h; sourceTree = ""; };
+ 1DB825282226E86500E123AA /* Mods.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; path = Mods.nib; sourceTree = ""; };
+ 1DB825292226E86500E123AA /* Mods-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Mods-Info.plist"; sourceTree = ""; };
+ 1DB8252A2226E86500E123AA /* ModsVisualizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ModsVisualizer.m; sourceTree = ""; };
+ 1DB8253C2226E8A000E123AA /* Mods.kcplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Mods.kcplugin; sourceTree = BUILT_PRODUCTS_DIR; };
29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; };
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; };
@@ -471,10 +491,21 @@
3D1646B60F43DBD700CA65AD /* KCVisualizer.framework */,
3D1648AC0F451D4500CA65AD /* Svelte.kcplugin */,
AFC172192377CFF500292155 /* KCVisualizerTests.xctest */,
+ 1DB8253C2226E8A000E123AA /* Mods.kcplugin */,
);
name = Products;
sourceTree = "";
};
+ 1DB825262226E85800E123AA /* Mods */ = {
+ isa = PBXGroup;
+ children = (
+ 1DB825282226E86500E123AA /* Mods.nib */,
+ 1DB825272226E86500E123AA /* ModsVisualizer.h */,
+ 1DB8252A2226E86500E123AA /* ModsVisualizer.m */,
+ );
+ name = Mods;
+ sourceTree = "";
+ };
29B97314FDCFA39411CA2CEA /* KeyCastr */ = {
isa = PBXGroup;
children = (
@@ -486,6 +517,7 @@
AF6DD3FB2586E00500EDC9D4 /* Externals */,
29B97323FDCFA39411CA2CEA /* Frameworks */,
19C28FACFE9D520D11CA2CBB /* Products */,
+ 1DB825292226E86500E123AA /* Mods-Info.plist */,
);
name = KeyCastr;
sourceTree = "";
@@ -550,6 +582,7 @@
3D1646530F43D6B800CA65AD /* Visualizers */ = {
isa = PBXGroup;
children = (
+ 1DB825262226E85800E123AA /* Mods */,
3D1648A30F451CDA00CA65AD /* Svelte */,
324AD7A5D37DE702839F52C6 /* Mouse */,
324ADFFC6CB5410AEFDEF479 /* Default */,
@@ -674,12 +707,31 @@
324ADBC2EAD3FC5FD3C369FE /* KCMouseEventVisualizer.h in Headers */,
324ADBB15522719676E80D5F /* KCMouseEvent.h in Headers */,
324AD25E40F9EFA6F54FA36A /* KCKeycastrEvent.h in Headers */,
+ 1DB8252B2226E86500E123AA /* ModsVisualizer.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
+ 1DB8252F2226E8A000E123AA /* Mods */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DB825382226E8A000E123AA /* Build configuration list for PBXNativeTarget "Mods" */;
+ buildPhases = (
+ 1DB825322226E8A000E123AA /* Resources */,
+ 1DB825342226E8A000E123AA /* Sources */,
+ 3D1646580F43D6E700CA65AD /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 1DB825302226E8A000E123AA /* PBXTargetDependency */,
+ );
+ name = Mods;
+ productName = Svelte;
+ productReference = 1DB8253C2226E8A000E123AA /* Mods.kcplugin */;
+ productType = "com.apple.product-type.bundle";
+ };
3D1646590F43D6E700CA65AD /* KCDefaultVisualizer */ = {
isa = PBXNativeTarget;
buildConfigurationList = 3D16465E0F43D6E800CA65AD /* Build configuration list for PBXNativeTarget "KCDefaultVisualizer" */;
@@ -752,6 +804,7 @@
AF6DD4372586E0BA00EDC9D4 /* PBXTargetDependency */,
AF6DD4342586E0A700EDC9D4 /* PBXTargetDependency */,
3D1646D50F43DCB200CA65AD /* PBXTargetDependency */,
+ 1DB825422226EC3200E123AA /* PBXTargetDependency */,
);
name = KeyCastr;
productInstallPath = "$(HOME)/Applications";
@@ -828,6 +881,7 @@
projectRoot = "";
targets = (
3D1646B50F43DBD700CA65AD /* KCVisualizer */,
+ 1DB8252F2226E8A000E123AA /* Mods */,
3D1648AB0F451D4500CA65AD /* Svelte */,
3D1646590F43D6E700CA65AD /* KCDefaultVisualizer */,
8D1107260486CEB800E47090 /* KeyCastr */,
@@ -987,6 +1041,14 @@
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
+ 1DB825322226E8A000E123AA /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1DB8253F2226E8DA00E123AA /* Mods.nib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
3D1646560F43D6E700CA65AD /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -999,6 +1061,8 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 1DB8252C2226E86500E123AA /* Mods.nib in Resources */,
+ 1DB8252D2226E86500E123AA /* Mods-Info.plist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1041,6 +1105,14 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
+ 1DB825342226E8A000E123AA /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1DB8253E2226E8D100E123AA /* ModsVisualizer.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
3D1646570F43D6E700CA65AD /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -1054,6 +1126,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 1DB8252E2226E86500E123AA /* ModsVisualizer.m in Sources */,
3D1646C20F43DC4700CA65AD /* KCVisualizer.m in Sources */,
AF5457292C0CDB2E00064C82 /* KCColorValueTransformer.m in Sources */,
AF7B1CF32C22376100C8C145 /* NSUserDefaults+Utility.m in Sources */,
@@ -1099,6 +1172,11 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
+ 1DB825422226EC3200E123AA /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 1DB8252F2226E8A000E123AA /* Mods */;
+ targetProxy = 1DB825412226EC3200E123AA /* PBXContainerItemProxy */;
+ };
3D1646D50F43DCB200CA65AD /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 3D1646B50F43DBD700CA65AD /* KCVisualizer */;
@@ -1171,6 +1249,88 @@
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
+ 1DB825392226E8A000E123AA /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
+ INFOPLIST_FILE = "Mods-Info.plist";
+ INSTALL_PATH = "$(HOME)/Library/Bundles";
+ OTHER_LDFLAGS = (
+ "-framework",
+ Foundation,
+ "-framework",
+ AppKit,
+ );
+ PREBINDING = NO;
+ PRODUCT_BUNDLE_IDENTIFIER = net.stephendeken.KeyCastr.Mods;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ WRAPPER_EXTENSION = kcplugin;
+ ZERO_LINK = YES;
+ };
+ name = Debug;
+ };
+ 1DB8253A2226E8A000E123AA /* Code Coverage */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_GENERATE_TEST_COVERAGE_FILES = YES;
+ GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
+ INFOPLIST_FILE = "Mods-Info.plist";
+ INSTALL_PATH = "$(HOME)/Library/Bundles";
+ OTHER_LDFLAGS = (
+ "-framework",
+ Foundation,
+ "-framework",
+ AppKit,
+ );
+ PREBINDING = NO;
+ PRODUCT_BUNDLE_IDENTIFIER = net.stephendeken.KeyCastr.Mods;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ WRAPPER_EXTENSION = kcplugin;
+ ZERO_LINK = NO;
+ };
+ name = "Code Coverage";
+ };
+ 1DB8253B2226E8A000E123AA /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
+ INFOPLIST_FILE = "Mods-Info.plist";
+ INSTALL_PATH = "$(HOME)/Library/Bundles";
+ OTHER_LDFLAGS = (
+ "-framework",
+ Foundation,
+ "-framework",
+ AppKit,
+ );
+ PREBINDING = NO;
+ PRODUCT_BUNDLE_IDENTIFIER = net.stephendeken.KeyCastr.Mods;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ WRAPPER_EXTENSION = kcplugin;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
3D16465C0F43D6E800CA65AD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -1609,6 +1769,16 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
+ 1DB825382226E8A000E123AA /* Build configuration list for PBXNativeTarget "Mods" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DB825392226E8A000E123AA /* Debug */,
+ 1DB8253A2226E8A000E123AA /* Code Coverage */,
+ 1DB8253B2226E8A000E123AA /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
3D16465E0F43D6E800CA65AD /* Build configuration list for PBXNativeTarget "KCDefaultVisualizer" */ = {
isa = XCConfigurationList;
buildConfigurations = (
diff --git a/keycastr/Mods-Info.plist b/keycastr/Mods-Info.plist
new file mode 100644
index 0000000..5a6a411
--- /dev/null
+++ b/keycastr/Mods-Info.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleExecutable
+ ${EXECUTABLE_NAME}
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ BNDL
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1.0
+ NSPrincipalClass
+ ModsVisualizerFactory
+
+
diff --git a/keycastr/Mods.nib/designable.nib b/keycastr/Mods.nib/designable.nib
new file mode 100644
index 0000000..98351db
--- /dev/null
+++ b/keycastr/Mods.nib/designable.nib
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/keycastr/Mods.nib/keyedobjects.nib b/keycastr/Mods.nib/keyedobjects.nib
new file mode 100644
index 0000000000000000000000000000000000000000..c6700ccb681483b50913dabc24d7ea03f7415352
GIT binary patch
literal 1396
zcmZuwTWl0n7@q(9TiVjwblK92KnrXOtEIG*+BOwo+fuBQt#rEE?RA~*p3=eTPMw)8
zRKy-qZi)&bf@ypxU5OGe#NZ`Le9@42ec2Gy5FSj7iHV6m852X|zZV-Hn90mJ=Rg1D
z`@a92@o8PN?E3m!z|fJk;+6A3_Y5~J&4>ow#`r-Vwyi<8YKA8@GWWY}W7;Xf$;E5(
z`s|#_jqV5Qwmtl4_v3q?*zX?M?GG3!VqpC|*#Fs*<)tgDtalm?dc
z7EEM|GO=37qEckhw@y@v(nOVW{f1#8ll1nfQ(T~Mgk)Kn;kwNUNlewXXSkWDuGzGC
zD4jG)Zo%}FTVoU(vutB3&2VXxC-@)R#6!;7Erg&h(~m{5g3@fQC$;v)Y?UY~+>UQ;
z@c4ZS&B(p6>GF1wBZ_V{x3oH4ZIA4rT#6Ah!<;1Sx2BC~gqy^#%OubWF`-00ZM@%zg(urplk(4W>FNPX
zNMfbPqkn!eEWvhfKSGcIeq!yCPe2U-V
zW+$IeW4dh-0^2lnotyE=gPtVWWdj8S^`)SPYDdT7E|-gRPrfB&u*a^r2+ej{rUB)o
z%+HQpIr`k3I3~(Pg?K=$5o<+>3^J2ZcF0*2_k7c$D5CMju|*1~t~q;-NO!lVPf@38
zt4n7+sZP?_b@A}3zGF#lReuIO&Bvt})uPjwMU|8zv9vzosBqqLPiZ)8*jNI6om
zR3UAYwn*EgW@%VbrNh#k^pdn7y(@ht-Ijg>gi5G^255vPXogm3gB`FFywCx=VGr~`
z5Qbm`46tDiPQxWwfH=Gj*Wp9>7;eB<@Es)J2lxr@z+Lzi{(yTdi)FK1md6TM1*>H(
ztc&%s{Y+tgHoyki2%BJ2%w%)yI6K2Gv8(KTc9VV0eq?vq@9a
+#import "KCVisualizer.h"
+
+@interface ModsVisualizerFactory : KCVisualizerFactory
+{
+}
+
+-(NSString*) visualizerNibName;
+-(Class) visualizerClass;
+-(NSString*) visualizerName;
+
+@end
+
+@interface ModsVisualizerView : NSView
+{
+ uint32_t _flags;
+}
+
+-(void) noteFlagsChanged:(uint32_t)flags;
+
+@end
+
+@interface ModsVisualizer : KCVisualizer
+{
+ NSWindow* _visualizerWindow;
+ ModsVisualizerView* _visualizerView;
+}
+
+-(NSString*) visualizerName;
+-(void) deactivateVisualizer:(id)sender;
+
+-(void) noteFlagsChanged:(uint32_t)flags;
+
+@end
diff --git a/keycastr/ModsVisualizer.m b/keycastr/ModsVisualizer.m
new file mode 100644
index 0000000..2877972
--- /dev/null
+++ b/keycastr/ModsVisualizer.m
@@ -0,0 +1,207 @@
+// Copyright (c) 2009 Stephen Deken
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name KeyCastr nor the names of its contributors may be used to
+// endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#import "ModsVisualizer.h"
+#import "NSBezierPath+RoundedRect.h"
+
+@implementation ModsVisualizerFactory
+
+-(NSString*) visualizerNibName
+{
+ return @"Mods";
+}
+
+-(Class) visualizerClass
+{
+ return [ModsVisualizer class];
+}
+
+-(NSString*) visualizerName
+{
+ return @"Mods";
+}
+
+@end
+
+@implementation ModsVisualizerView
+
+-(void) drawRect:(NSRect)rect
+{
+ NSRect frame = [self frame];
+ NSRect bgFrame = [self frame];
+ float oneQuarter = floorf(frame.size.width / 4);
+ bgFrame.size.width = 0;
+ CGFloat x = frame.size.width, y;
+ NSSize size;
+
+ bgFrame.origin.x = frame.size.width;
+ [[NSColor clearColor] setFill];
+ NSRectFill(frame);
+
+ if (_flags & NSShiftKeyMask) {
+ bgFrame.size.width += oneQuarter;
+ bgFrame.origin.x -= oneQuarter;
+ }
+
+ if (_flags & NSControlKeyMask) {
+ bgFrame.size.width += oneQuarter;
+ bgFrame.origin.x -= oneQuarter;
+ }
+
+ if (_flags & NSAlternateKeyMask) {
+ bgFrame.size.width += oneQuarter;
+ bgFrame.origin.x -= oneQuarter;
+ }
+
+ if (_flags & NSCommandKeyMask) {
+ bgFrame.size.width += oneQuarter;
+ bgFrame.origin.x -= oneQuarter;
+ }
+
+ if (bgFrame.size.width > 0) {
+ [[NSColor colorWithCalibratedWhite:0 alpha:0.75] setFill];
+ NSBezierPath* bp = [NSBezierPath bezierPath];
+ [bp appendRoundedRect:bgFrame radius:10];
+ [bp fill];
+ }
+
+ NSMutableParagraphStyle* ps = [[NSMutableParagraphStyle alloc] init];
+ [ps setAlignment:NSCenterTextAlignment];
+
+ NSString* shiftKeyString = [NSString stringWithUTF8String:"\xe2\x87\xa7\x01"];
+ NSString* controlKeyString = [NSString stringWithUTF8String:"\xe2\x8c\x83\x01"];
+ NSString* altKeyString = [NSString stringWithUTF8String:"\xe2\x8c\xa5\x01"];
+ NSString* commandKeyString = [NSString stringWithUTF8String:"\xe2\x8c\x98\x01"];
+ NSShadow* shadow = [[[NSShadow alloc] init] autorelease];
+ [shadow setShadowColor:[NSColor blackColor]];
+ [shadow setShadowBlurRadius:2];
+ [shadow setShadowOffset:NSMakeSize(2,-2)];
+
+ NSMutableDictionary* attr = [@{
+ NSFontAttributeName: [NSFont boldSystemFontOfSize:80],
+ NSForegroundColorAttributeName: [NSColor colorWithCalibratedWhite:1 alpha:0.8],
+ NSShadowAttributeName: shadow,
+ NSParagraphStyleAttributeName: [ps autorelease]
+ } mutableCopy];
+
+ if (_flags & NSShiftKeyMask) {
+ size = [shiftKeyString sizeWithAttributes:attr];
+ y = (frame.size.height - size.height) / 2.0;
+ x -= oneQuarter;
+ [shiftKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
+ }
+
+ if (_flags & NSControlKeyMask) {
+ size = [controlKeyString sizeWithAttributes:attr];
+ y = (frame.size.height - size.height) / 2.0;
+ x -= oneQuarter;
+ [controlKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
+ }
+
+ if (_flags & NSAlternateKeyMask) {
+ size = [altKeyString sizeWithAttributes:attr];
+ y = (frame.size.height - size.height) / 2.0;
+ x -= oneQuarter;
+ [altKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
+ }
+
+ if (_flags & NSCommandKeyMask) {
+ size = [commandKeyString sizeWithAttributes:attr];
+ y = (frame.size.height - size.height) / 2.0;
+ x -= oneQuarter;
+ [commandKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
+ }
+}
+
+-(void) noteFlagsChanged:(uint32_t)flags
+{
+ _flags = flags;
+ [self setNeedsDisplay:YES];
+}
+
+@end
+
+
+@implementation ModsVisualizer
+
+-(NSString*) visualizerName
+{
+ return @"Mods";
+}
+
+-(id) init
+{
+ if (!(self = [super init]))
+ return nil;
+
+ NSRect r = { 10, 10, 400, 100 };
+ _visualizerWindow = [[NSWindow alloc]
+ initWithContentRect:r
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:NO];
+ [_visualizerWindow setLevel:NSScreenSaverWindowLevel];
+ [_visualizerWindow setBackgroundColor:[NSColor clearColor]];
+ [_visualizerWindow setMovableByWindowBackground:YES];
+ [_visualizerWindow setFrame:r display:NO];
+ [_visualizerWindow setFrameAutosaveName:@"mods visualizerFrame"];
+ [_visualizerWindow setFrameUsingName:@"mods visualizerFrame"];
+ [_visualizerWindow setOpaque:NO];
+
+ _visualizerView = [[ModsVisualizerView alloc] initWithFrame:r];
+ [_visualizerWindow setContentView:_visualizerView];
+
+ return self;
+}
+
+- (void)dealloc {
+ [_visualizerWindow release];
+ [_visualizerView release];
+ [super dealloc];
+}
+
+-(void) showVisualizer:(id)sender
+{
+ [_visualizerWindow orderFront:self];
+}
+
+-(void) hideVisualizer:(id)sender
+{
+ [_visualizerWindow orderOut:self];
+}
+
+-(void) deactivateVisualizer:(id)sender
+{
+ [_visualizerWindow orderOut:self];
+}
+
+-(void) noteFlagsChanged:(uint32_t)flags
+{
+ [_visualizerView noteFlagsChanged:flags];
+}
+
+@end
From 43f8fa0c1f91b8228253e4d9c93376cac2df03cd Mon Sep 17 00:00:00 2001
From: "Colin T.A. Gray"
Date: Tue, 17 Oct 2023 14:37:52 -0400
Subject: [PATCH 2/6] updates for Sonoma to ignore mouse events (resize frame
on mods change)
---
keycastr/ModsVisualizer.m | 113 ++++++++++++++++++++++----------------
1 file changed, 66 insertions(+), 47 deletions(-)
diff --git a/keycastr/ModsVisualizer.m b/keycastr/ModsVisualizer.m
index 2877972..538d594 100644
--- a/keycastr/ModsVisualizer.m
+++ b/keycastr/ModsVisualizer.m
@@ -24,9 +24,11 @@
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#define MODS_WIDTH 400
#import "ModsVisualizer.h"
#import "NSBezierPath+RoundedRect.h"
+#import "KCKeystroke.h"
@implementation ModsVisualizerFactory
@@ -49,53 +51,50 @@ -(NSString*) visualizerName
@implementation ModsVisualizerView
+- (unsigned short) flagsCount {
+ unsigned short count = 0;
+
+ if (_flags & NSEventModifierFlagShift) {
+ count += 1;
+ }
+
+ if (_flags & NSEventModifierFlagControl) {
+ count += 1;
+ }
+
+ if (_flags & NSEventModifierFlagOption) {
+ count += 1;
+ }
+
+ if (_flags & NSEventModifierFlagCommand) {
+ count += 1;
+ }
+
+ return count;
+}
+
-(void) drawRect:(NSRect)rect
{
NSRect frame = [self frame];
NSRect bgFrame = [self frame];
- float oneQuarter = floorf(frame.size.width / 4);
- bgFrame.size.width = 0;
+ float oneQuarter = floorf(MODS_WIDTH / 4);
+
CGFloat x = frame.size.width, y;
NSSize size;
- bgFrame.origin.x = frame.size.width;
[[NSColor clearColor] setFill];
NSRectFill(frame);
- if (_flags & NSShiftKeyMask) {
- bgFrame.size.width += oneQuarter;
- bgFrame.origin.x -= oneQuarter;
- }
-
- if (_flags & NSControlKeyMask) {
- bgFrame.size.width += oneQuarter;
- bgFrame.origin.x -= oneQuarter;
- }
-
- if (_flags & NSAlternateKeyMask) {
- bgFrame.size.width += oneQuarter;
- bgFrame.origin.x -= oneQuarter;
- }
-
- if (_flags & NSCommandKeyMask) {
- bgFrame.size.width += oneQuarter;
- bgFrame.origin.x -= oneQuarter;
- }
-
if (bgFrame.size.width > 0) {
- [[NSColor colorWithCalibratedWhite:0 alpha:0.75] setFill];
- NSBezierPath* bp = [NSBezierPath bezierPath];
- [bp appendRoundedRect:bgFrame radius:10];
- [bp fill];
+ [[NSColor colorWithCalibratedWhite:0 alpha:0.75] setFill];
+ NSBezierPath* bp = [NSBezierPath bezierPath];
+ [bp appendRoundedRect:bgFrame radius:10];
+ [bp fill];
}
NSMutableParagraphStyle* ps = [[NSMutableParagraphStyle alloc] init];
- [ps setAlignment:NSCenterTextAlignment];
+ [ps setAlignment:NSTextAlignmentCenter];
- NSString* shiftKeyString = [NSString stringWithUTF8String:"\xe2\x87\xa7\x01"];
- NSString* controlKeyString = [NSString stringWithUTF8String:"\xe2\x8c\x83\x01"];
- NSString* altKeyString = [NSString stringWithUTF8String:"\xe2\x8c\xa5\x01"];
- NSString* commandKeyString = [NSString stringWithUTF8String:"\xe2\x8c\x98\x01"];
NSShadow* shadow = [[[NSShadow alloc] init] autorelease];
[shadow setShadowColor:[NSColor blackColor]];
[shadow setShadowBlurRadius:2];
@@ -108,28 +107,32 @@ -(void) drawRect:(NSRect)rect
NSParagraphStyleAttributeName: [ps autorelease]
} mutableCopy];
- if (_flags & NSShiftKeyMask) {
+ if (_flags & NSEventModifierFlagShift) {
+ NSString* shiftKeyString = [NSString stringWithUTF8String:"\xe2\x87\xa7\x01"];
size = [shiftKeyString sizeWithAttributes:attr];
y = (frame.size.height - size.height) / 2.0;
x -= oneQuarter;
[shiftKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
}
- if (_flags & NSControlKeyMask) {
+ if (_flags & NSEventModifierFlagControl) {
+ NSString* controlKeyString = [NSString stringWithUTF8String:"\xe2\x8c\x83\x01"];
size = [controlKeyString sizeWithAttributes:attr];
y = (frame.size.height - size.height) / 2.0;
x -= oneQuarter;
[controlKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
}
- if (_flags & NSAlternateKeyMask) {
+ if (_flags & NSEventModifierFlagOption) {
+ NSString* altKeyString = [NSString stringWithUTF8String:"\xe2\x8c\xa5\x01"];
size = [altKeyString sizeWithAttributes:attr];
y = (frame.size.height - size.height) / 2.0;
x -= oneQuarter;
[altKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
}
- if (_flags & NSCommandKeyMask) {
+ if (_flags & NSEventModifierFlagCommand) {
+ NSString* commandKeyString = [NSString stringWithUTF8String:"\xe2\x8c\x98\x01"];
size = [commandKeyString sizeWithAttributes:attr];
y = (frame.size.height - size.height) / 2.0;
x -= oneQuarter;
@@ -139,8 +142,11 @@ -(void) drawRect:(NSRect)rect
-(void) noteFlagsChanged:(uint32_t)flags
{
- _flags = flags;
- [self setNeedsDisplay:YES];
+ _flags = flags;
+ NSRect frame = self.frame;
+ frame.size.width = MODS_WIDTH / 4 * (CGFloat)[self flagsCount];
+ self.frame = frame;
+ [self setNeedsDisplay:YES];
}
@end
@@ -158,30 +164,30 @@ -(id) init
if (!(self = [super init]))
return nil;
- NSRect r = { 10, 10, 400, 100 };
+ NSRect windowFrame = { MODS_WIDTH, 100, 0, 100 };
_visualizerWindow = [[NSWindow alloc]
- initWithContentRect:r
- styleMask:NSBorderlessWindowMask
+ initWithContentRect:windowFrame
+ styleMask:NSWindowStyleMaskBorderless
backing:NSBackingStoreBuffered
defer:NO];
[_visualizerWindow setLevel:NSScreenSaverWindowLevel];
[_visualizerWindow setBackgroundColor:[NSColor clearColor]];
[_visualizerWindow setMovableByWindowBackground:YES];
- [_visualizerWindow setFrame:r display:NO];
[_visualizerWindow setFrameAutosaveName:@"mods visualizerFrame"];
- [_visualizerWindow setFrameUsingName:@"mods visualizerFrame"];
+ [_visualizerWindow setFrameUsingName:@"mods visualizerFrame" force:YES];
[_visualizerWindow setOpaque:NO];
- _visualizerView = [[ModsVisualizerView alloc] initWithFrame:r];
+ _visualizerView = [[ModsVisualizerView alloc] init];
[_visualizerWindow setContentView:_visualizerView];
+ [_visualizerView noteFlagsChanged:0];
return self;
}
- (void)dealloc {
- [_visualizerWindow release];
- [_visualizerView release];
- [super dealloc];
+ [_visualizerWindow release];
+ [_visualizerView release];
+ [super dealloc];
}
-(void) showVisualizer:(id)sender
@@ -202,6 +208,19 @@ -(void) deactivateVisualizer:(id)sender
-(void) noteFlagsChanged:(uint32_t)flags
{
[_visualizerView noteFlagsChanged:flags];
+ NSRect r = _visualizerWindow.frame;
+ CGFloat right = r.origin.x + r.size.width;
+ r.size.width = _visualizerView.frame.size.width;
+ r.origin.x = right - r.size.width;
+ [_visualizerWindow setFrame:r display:NO];
+}
+
+- (void)noteKeyEvent:(KCKeystroke *)keystroke {}
+
+- (void)noteMouseEvent:(KCMouseEvent *)mouseEvent {}
+
++ (NSDictionary *)visualizerDefaults {
+ return @{};
}
@end
From 064f574dd30df309b49c524dea2141a50ee20c21 Mon Sep 17 00:00:00 2001
From: "Colin T.A. Gray"
Date: Fri, 20 Oct 2023 11:51:09 -0400
Subject: [PATCH 3/6] =?UTF-8?q?code=20style=20changes,=20and=20ordered=20m?=
=?UTF-8?q?odifiers=20'=E2=8C=83=E2=8C=A5=E2=87=A7=E2=8C=98'?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
keycastr/ModsVisualizer.h | 64 ++++----
keycastr/ModsVisualizer.m | 332 ++++++++++++++++++--------------------
2 files changed, 192 insertions(+), 204 deletions(-)
diff --git a/keycastr/ModsVisualizer.h b/keycastr/ModsVisualizer.h
index aa6a6fb..5a5db10 100644
--- a/keycastr/ModsVisualizer.h
+++ b/keycastr/ModsVisualizer.h
@@ -1,28 +1,28 @@
-// Copyright (c) 2009 Stephen Deken
-// All rights reserved.
+// Copyright (c) 2023 Colin Gray
+// All rights reserved.
//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
//
-// * Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name KeyCastr nor the names of its contributors may be used to
-// endorse or promote products derived from this software without specific
-// prior written permission.
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name KeyCastr nor the names of its contributors may be used to
+// endorse or promote products derived from this software without specific
+// prior written permission.
//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import
@@ -32,30 +32,30 @@
{
}
--(NSString*) visualizerNibName;
--(Class) visualizerClass;
--(NSString*) visualizerName;
+- (NSString*)visualizerNibName;
+- (Class)visualizerClass;
+- (NSString*)visualizerName;
@end
@interface ModsVisualizerView : NSView
{
- uint32_t _flags;
+ uint32_t _flags;
}
--(void) noteFlagsChanged:(uint32_t)flags;
+- (void)noteFlagsChanged:(uint32_t)flags;
@end
@interface ModsVisualizer : KCVisualizer
{
- NSWindow* _visualizerWindow;
- ModsVisualizerView* _visualizerView;
+ NSWindow* _visualizerWindow;
+ ModsVisualizerView* _visualizerView;
}
--(NSString*) visualizerName;
--(void) deactivateVisualizer:(id)sender;
+- (NSString*)visualizerName;
+- (void)deactivateVisualizer:(id)sender;
--(void) noteFlagsChanged:(uint32_t)flags;
+- (void)noteFlagsChanged:(uint32_t)flags;
@end
diff --git a/keycastr/ModsVisualizer.m b/keycastr/ModsVisualizer.m
index 538d594..ed2af79 100644
--- a/keycastr/ModsVisualizer.m
+++ b/keycastr/ModsVisualizer.m
@@ -1,28 +1,28 @@
-// Copyright (c) 2009 Stephen Deken
-// All rights reserved.
+// Copyright (c) 2023 Colin Gray
+// All rights reserved.
//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
//
-// * Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name KeyCastr nor the names of its contributors may be used to
-// endorse or promote products derived from this software without specific
-// prior written permission.
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name KeyCastr nor the names of its contributors may be used to
+// endorse or promote products derived from this software without specific
+// prior written permission.
//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define MODS_WIDTH 400
@@ -32,190 +32,178 @@
@implementation ModsVisualizerFactory
--(NSString*) visualizerNibName
-{
- return @"Mods";
+- (NSString *)visualizerNibName {
+ return @"Mods";
}
--(Class) visualizerClass
-{
- return [ModsVisualizer class];
+- (Class)visualizerClass {
+ return [ModsVisualizer class];
}
--(NSString*) visualizerName
-{
- return @"Mods";
+- (NSString *)visualizerName {
+ return @"Mods";
}
@end
@implementation ModsVisualizerView
-- (unsigned short) flagsCount {
- unsigned short count = 0;
-
- if (_flags & NSEventModifierFlagShift) {
- count += 1;
- }
-
- if (_flags & NSEventModifierFlagControl) {
- count += 1;
- }
-
- if (_flags & NSEventModifierFlagOption) {
- count += 1;
- }
-
- if (_flags & NSEventModifierFlagCommand) {
- count += 1;
- }
-
- return count;
+- (unsigned short)flagsCount {
+ unsigned short count = 0;
+
+ if (_flags & NSEventModifierFlagControl) {
+ count += 1;
+ }
+
+ if (_flags & NSEventModifierFlagOption) {
+ count += 1;
+ }
+
+ if (_flags & NSEventModifierFlagShift) {
+ count += 1;
+ }
+
+ if (_flags & NSEventModifierFlagCommand) {
+ count += 1;
+ }
+
+ return count;
}
--(void) drawRect:(NSRect)rect
-{
- NSRect frame = [self frame];
- NSRect bgFrame = [self frame];
- float oneQuarter = floorf(MODS_WIDTH / 4);
-
- CGFloat x = frame.size.width, y;
- NSSize size;
-
- [[NSColor clearColor] setFill];
- NSRectFill(frame);
-
- if (bgFrame.size.width > 0) {
- [[NSColor colorWithCalibratedWhite:0 alpha:0.75] setFill];
- NSBezierPath* bp = [NSBezierPath bezierPath];
- [bp appendRoundedRect:bgFrame radius:10];
- [bp fill];
- }
-
- NSMutableParagraphStyle* ps = [[NSMutableParagraphStyle alloc] init];
- [ps setAlignment:NSTextAlignmentCenter];
-
- NSShadow* shadow = [[[NSShadow alloc] init] autorelease];
- [shadow setShadowColor:[NSColor blackColor]];
- [shadow setShadowBlurRadius:2];
- [shadow setShadowOffset:NSMakeSize(2,-2)];
-
- NSMutableDictionary* attr = [@{
- NSFontAttributeName: [NSFont boldSystemFontOfSize:80],
- NSForegroundColorAttributeName: [NSColor colorWithCalibratedWhite:1 alpha:0.8],
- NSShadowAttributeName: shadow,
- NSParagraphStyleAttributeName: [ps autorelease]
- } mutableCopy];
-
- if (_flags & NSEventModifierFlagShift) {
- NSString* shiftKeyString = [NSString stringWithUTF8String:"\xe2\x87\xa7\x01"];
- size = [shiftKeyString sizeWithAttributes:attr];
- y = (frame.size.height - size.height) / 2.0;
- x -= oneQuarter;
- [shiftKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
- }
-
- if (_flags & NSEventModifierFlagControl) {
- NSString* controlKeyString = [NSString stringWithUTF8String:"\xe2\x8c\x83\x01"];
- size = [controlKeyString sizeWithAttributes:attr];
- y = (frame.size.height - size.height) / 2.0;
- x -= oneQuarter;
- [controlKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
- }
-
- if (_flags & NSEventModifierFlagOption) {
- NSString* altKeyString = [NSString stringWithUTF8String:"\xe2\x8c\xa5\x01"];
- size = [altKeyString sizeWithAttributes:attr];
- y = (frame.size.height - size.height) / 2.0;
- x -= oneQuarter;
- [altKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
- }
-
- if (_flags & NSEventModifierFlagCommand) {
- NSString* commandKeyString = [NSString stringWithUTF8String:"\xe2\x8c\x98\x01"];
- size = [commandKeyString sizeWithAttributes:attr];
- y = (frame.size.height - size.height) / 2.0;
- x -= oneQuarter;
- [commandKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
- }
+- (void)drawRect:(NSRect)rect {
+ NSRect frame = [self frame];
+ NSRect bgFrame = [self frame];
+ float oneQuarter = floorf(MODS_WIDTH / 4);
+
+ CGFloat x = frame.size.width, y;
+ NSSize size;
+
+ [[NSColor clearColor] setFill];
+ NSRectFill(frame);
+
+ if (bgFrame.size.width > 0) {
+ [[NSColor colorWithCalibratedWhite:0 alpha:0.75] setFill];
+ NSBezierPath* bp = [NSBezierPath bezierPath];
+ [bp appendRoundedRect:bgFrame radius:10];
+ [bp fill];
+ }
+
+ NSMutableParagraphStyle* ps = [[NSMutableParagraphStyle alloc] init];
+ [ps setAlignment:NSTextAlignmentCenter];
+
+ NSShadow* shadow = [[[NSShadow alloc] init] autorelease];
+ [shadow setShadowColor:[NSColor blackColor]];
+ [shadow setShadowBlurRadius:2];
+ [shadow setShadowOffset:NSMakeSize(2,-2)];
+
+ NSMutableDictionary* attr = [@{
+ NSFontAttributeName: [NSFont boldSystemFontOfSize:80],
+ NSForegroundColorAttributeName: [NSColor colorWithCalibratedWhite:1 alpha:0.8],
+ NSShadowAttributeName: shadow,
+ NSParagraphStyleAttributeName: [ps autorelease]
+ } mutableCopy];
+
+ if (_flags & NSEventModifierFlagControl) {
+ NSString* controlKeyString = [NSString stringWithUTF8String:"\xe2\x8c\x83\x01"];
+ size = [controlKeyString sizeWithAttributes:attr];
+ y = (frame.size.height - size.height) / 2.0;
+ x -= oneQuarter;
+ [controlKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
+ }
+
+ if (_flags & NSEventModifierFlagOption) {
+ NSString* altKeyString = [NSString stringWithUTF8String:"\xe2\x8c\xa5\x01"];
+ size = [altKeyString sizeWithAttributes:attr];
+ y = (frame.size.height - size.height) / 2.0;
+ x -= oneQuarter;
+ [altKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
+ }
+
+ if (_flags & NSEventModifierFlagShift) {
+ NSString* shiftKeyString = [NSString stringWithUTF8String:"\xe2\x87\xa7\x01"];
+ size = [shiftKeyString sizeWithAttributes:attr];
+ y = (frame.size.height - size.height) / 2.0;
+ x -= oneQuarter;
+ [shiftKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
+ }
+
+ if (_flags & NSEventModifierFlagCommand) {
+ NSString* commandKeyString = [NSString stringWithUTF8String:"\xe2\x8c\x98\x01"];
+ size = [commandKeyString sizeWithAttributes:attr];
+ y = (frame.size.height - size.height) / 2.0;
+ x -= oneQuarter;
+ [commandKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
+ }
}
--(void) noteFlagsChanged:(uint32_t)flags
-{
- _flags = flags;
- NSRect frame = self.frame;
- frame.size.width = MODS_WIDTH / 4 * (CGFloat)[self flagsCount];
- self.frame = frame;
- [self setNeedsDisplay:YES];
+- (void)noteFlagsChanged:(uint32_t)flags {
+ _flags = flags;
+ NSRect frame = self.frame;
+ frame.size.width = MODS_WIDTH / 4 * (CGFloat)[self flagsCount];
+ self.frame = frame;
+ [self setNeedsDisplay:YES];
}
@end
-
@implementation ModsVisualizer
--(NSString*) visualizerName
-{
- return @"Mods";
+- (NSString *)visualizerName {
+ return @"Mods";
}
--(id) init
-{
- if (!(self = [super init]))
- return nil;
-
- NSRect windowFrame = { MODS_WIDTH, 100, 0, 100 };
- _visualizerWindow = [[NSWindow alloc]
- initWithContentRect:windowFrame
- styleMask:NSWindowStyleMaskBorderless
- backing:NSBackingStoreBuffered
- defer:NO];
- [_visualizerWindow setLevel:NSScreenSaverWindowLevel];
- [_visualizerWindow setBackgroundColor:[NSColor clearColor]];
- [_visualizerWindow setMovableByWindowBackground:YES];
- [_visualizerWindow setFrameAutosaveName:@"mods visualizerFrame"];
- [_visualizerWindow setFrameUsingName:@"mods visualizerFrame" force:YES];
- [_visualizerWindow setOpaque:NO];
-
- _visualizerView = [[ModsVisualizerView alloc] init];
- [_visualizerWindow setContentView:_visualizerView];
- [_visualizerView noteFlagsChanged:0];
-
- return self;
+- (id)init {
+ if (!(self = [super init]))
+ return nil;
+
+ NSRect windowFrame = { MODS_WIDTH, 100, 0, 100 };
+ _visualizerWindow = [[NSWindow alloc]
+ initWithContentRect:windowFrame
+ styleMask:NSWindowStyleMaskBorderless
+ backing:NSBackingStoreBuffered
+ defer:NO];
+ [_visualizerWindow setLevel:NSScreenSaverWindowLevel];
+ [_visualizerWindow setBackgroundColor:[NSColor clearColor]];
+ [_visualizerWindow setMovableByWindowBackground:YES];
+ [_visualizerWindow setFrameAutosaveName:@"mods visualizerFrame"];
+ [_visualizerWindow setFrameUsingName:@"mods visualizerFrame" force:YES];
+ [_visualizerWindow setOpaque:NO];
+
+ _visualizerView = [[ModsVisualizerView alloc] init];
+ [_visualizerWindow setContentView:_visualizerView];
+ [_visualizerView noteFlagsChanged:0];
+
+ return self;
}
-- (void)dealloc {
- [_visualizerWindow release];
- [_visualizerView release];
- [super dealloc];
+- (void)dealloc {
+ [_visualizerWindow release];
+ [_visualizerView release];
+ [super dealloc];
}
--(void) showVisualizer:(id)sender
-{
- [_visualizerWindow orderFront:self];
+- (void)showVisualizer:(id)sender {
+ [_visualizerWindow orderFront:self];
}
--(void) hideVisualizer:(id)sender
-{
- [_visualizerWindow orderOut:self];
+- (void)hideVisualizer:(id)sender {
+ [_visualizerWindow orderOut:self];
}
--(void) deactivateVisualizer:(id)sender
-{
- [_visualizerWindow orderOut:self];
+- (void)deactivateVisualizer:(id)sender {
+ [_visualizerWindow orderOut:self];
}
--(void) noteFlagsChanged:(uint32_t)flags
-{
- [_visualizerView noteFlagsChanged:flags];
- NSRect r = _visualizerWindow.frame;
- CGFloat right = r.origin.x + r.size.width;
- r.size.width = _visualizerView.frame.size.width;
- r.origin.x = right - r.size.width;
- [_visualizerWindow setFrame:r display:NO];
+- (void)noteFlagsChanged:(uint32_t)flags {
+ [_visualizerView noteFlagsChanged:flags];
+ NSRect r = _visualizerWindow.frame;
+ CGFloat right = r.origin.x + r.size.width;
+ r.size.width = _visualizerView.frame.size.width;
+ r.origin.x = right - r.size.width;
+ [_visualizerWindow setFrame:r display:NO];
}
-- (void)noteKeyEvent:(KCKeystroke *)keystroke {}
+- (void)noteKeyEvent:(KCKeystroke *)keystroke {}
- (void)noteMouseEvent:(KCMouseEvent *)mouseEvent {}
From 66811447aa83b5228d60a33811a5f46aa5cc9dc4 Mon Sep 17 00:00:00 2001
From: "Colin T.A. Gray"
Date: Thu, 2 Nov 2023 12:12:38 -0400
Subject: [PATCH 4/6] supports 'FN' key, and I had the order flipped on
modifiers
---
keycastr/KCEventTap.m | 3 ++
keycastr/ModsVisualizer.m | 64 +++++++++++++++++++++++----------------
2 files changed, 41 insertions(+), 26 deletions(-)
diff --git a/keycastr/KCEventTap.m b/keycastr/KCEventTap.m
index c6ed8f1..873e12d 100644
--- a/keycastr/KCEventTap.m
+++ b/keycastr/KCEventTap.m
@@ -218,6 +218,9 @@ -(void) _noteFlagsChanged:(CGEventRef)event
if (f & kCGEventFlagMaskAlternate)
modifiers |= NSEventModifierFlagOption;
+
+ if (f & kCGEventFlagMaskSecondaryFn)
+ modifiers |= NSEventModifierFlagFunction;
[self noteFlagsChanged:modifiers];
}
diff --git a/keycastr/ModsVisualizer.m b/keycastr/ModsVisualizer.m
index ed2af79..5e96200 100644
--- a/keycastr/ModsVisualizer.m
+++ b/keycastr/ModsVisualizer.m
@@ -24,7 +24,7 @@
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#define MODS_WIDTH 400
+#define MODS_WIDTH 100
#import "ModsVisualizer.h"
#import "NSBezierPath+RoundedRect.h"
@@ -51,6 +51,10 @@ @implementation ModsVisualizerView
- (unsigned short)flagsCount {
unsigned short count = 0;
+ if (_flags & NSEventModifierFlagFunction) {
+ count += 1;
+ }
+
if (_flags & NSEventModifierFlagControl) {
count += 1;
}
@@ -73,7 +77,7 @@ - (unsigned short)flagsCount {
- (void)drawRect:(NSRect)rect {
NSRect frame = [self frame];
NSRect bgFrame = [self frame];
- float oneQuarter = floorf(MODS_WIDTH / 4);
+ float oneQuarter = floorf(MODS_WIDTH);
CGFloat x = frame.size.width, y;
NSSize size;
@@ -103,13 +107,21 @@ - (void)drawRect:(NSRect)rect {
NSParagraphStyleAttributeName: [ps autorelease]
} mutableCopy];
- if (_flags & NSEventModifierFlagControl) {
- NSString* controlKeyString = [NSString stringWithUTF8String:"\xe2\x8c\x83\x01"];
- size = [controlKeyString sizeWithAttributes:attr];
- y = (frame.size.height - size.height) / 2.0;
- x -= oneQuarter;
- [controlKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
- }
+ if (_flags & NSEventModifierFlagCommand) {
+ NSString* commandKeyString = [NSString stringWithUTF8String:"\xe2\x8c\x98\x01"];
+ size = [commandKeyString sizeWithAttributes:attr];
+ y = (frame.size.height - size.height) / 2.0;
+ x -= oneQuarter;
+ [commandKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
+ }
+
+ if (_flags & NSEventModifierFlagShift) {
+ NSString* shiftKeyString = [NSString stringWithUTF8String:"\xe2\x87\xa7\x01"];
+ size = [shiftKeyString sizeWithAttributes:attr];
+ y = (frame.size.height - size.height) / 2.0;
+ x -= oneQuarter;
+ [shiftKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
+ }
if (_flags & NSEventModifierFlagOption) {
NSString* altKeyString = [NSString stringWithUTF8String:"\xe2\x8c\xa5\x01"];
@@ -119,27 +131,27 @@ - (void)drawRect:(NSRect)rect {
[altKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
}
- if (_flags & NSEventModifierFlagShift) {
- NSString* shiftKeyString = [NSString stringWithUTF8String:"\xe2\x87\xa7\x01"];
- size = [shiftKeyString sizeWithAttributes:attr];
- y = (frame.size.height - size.height) / 2.0;
- x -= oneQuarter;
- [shiftKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
- }
-
- if (_flags & NSEventModifierFlagCommand) {
- NSString* commandKeyString = [NSString stringWithUTF8String:"\xe2\x8c\x98\x01"];
- size = [commandKeyString sizeWithAttributes:attr];
- y = (frame.size.height - size.height) / 2.0;
- x -= oneQuarter;
- [commandKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
- }
+ if (_flags & NSEventModifierFlagControl) {
+ NSString* controlKeyString = [NSString stringWithUTF8String:"\xe2\x8c\x83\x01"];
+ size = [controlKeyString sizeWithAttributes:attr];
+ y = (frame.size.height - size.height) / 2.0;
+ x -= oneQuarter;
+ [controlKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
+ }
+
+ if (_flags & NSEventModifierFlagFunction) {
+ NSString* controlKeyString = [NSString stringWithUTF8String:"fn"];
+ size = [controlKeyString sizeWithAttributes:attr];
+ y = (frame.size.height - size.height) / 2.0;
+ x -= oneQuarter;
+ [controlKeyString drawInRect:NSMakeRect(x, y, oneQuarter, size.height) withAttributes:attr];
+ }
}
- (void)noteFlagsChanged:(uint32_t)flags {
_flags = flags;
NSRect frame = self.frame;
- frame.size.width = MODS_WIDTH / 4 * (CGFloat)[self flagsCount];
+ frame.size.width = MODS_WIDTH * (CGFloat)[self flagsCount];
self.frame = frame;
[self setNeedsDisplay:YES];
}
@@ -203,7 +215,7 @@ - (void)noteFlagsChanged:(uint32_t)flags {
[_visualizerWindow setFrame:r display:NO];
}
-- (void)noteKeyEvent:(KCKeystroke *)keystroke {}
+- (void)noteKeyEvent:(KCKeycastrEvent *)event {}
- (void)noteMouseEvent:(KCMouseEvent *)mouseEvent {}
From 7761adce29739df571afc33e2f7038893df17ee7 Mon Sep 17 00:00:00 2001
From: "Colin T.A. Gray"
Date: Thu, 26 Sep 2024 10:34:00 -0400
Subject: [PATCH 5/6] giving up on autosave frame, using defaults directly
---
keycastr/ModsVisualizer.m | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/keycastr/ModsVisualizer.m b/keycastr/ModsVisualizer.m
index 5e96200..20e4557 100644
--- a/keycastr/ModsVisualizer.m
+++ b/keycastr/ModsVisualizer.m
@@ -168,7 +168,14 @@ - (id)init {
if (!(self = [super init]))
return nil;
+ // autosave frame was not working, despite best efforts. Easy workaround to use defaults instead.
+ // (and autosave frame _uses_ defaults anyway so same thing in the end?)
+ NSString *frameValue = [[NSUserDefaults standardUserDefaults] stringForKey:@"mods.savedFrame"];
NSRect windowFrame = { MODS_WIDTH, 100, 0, 100 };
+ if (frameValue) {
+ windowFrame = NSRectFromString(frameValue);
+ }
+
_visualizerWindow = [[NSWindow alloc]
initWithContentRect:windowFrame
styleMask:NSWindowStyleMaskBorderless
@@ -177,13 +184,13 @@ - (id)init {
[_visualizerWindow setLevel:NSScreenSaverWindowLevel];
[_visualizerWindow setBackgroundColor:[NSColor clearColor]];
[_visualizerWindow setMovableByWindowBackground:YES];
- [_visualizerWindow setFrameAutosaveName:@"mods visualizerFrame"];
- [_visualizerWindow setFrameUsingName:@"mods visualizerFrame" force:YES];
+ [_visualizerWindow setFrame:windowFrame display:NO];
[_visualizerWindow setOpaque:NO];
+ [_visualizerWindow setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces];
_visualizerView = [[ModsVisualizerView alloc] init];
- [_visualizerWindow setContentView:_visualizerView];
[_visualizerView noteFlagsChanged:0];
+ [_visualizerWindow setContentView:_visualizerView];
return self;
}
@@ -213,6 +220,7 @@ - (void)noteFlagsChanged:(uint32_t)flags {
r.size.width = _visualizerView.frame.size.width;
r.origin.x = right - r.size.width;
[_visualizerWindow setFrame:r display:NO];
+ [[NSUserDefaults standardUserDefaults] setValue:NSStringFromRect(_visualizerWindow.frame) forKey:@"mods.savedFrame"];
}
- (void)noteKeyEvent:(KCKeycastrEvent *)event {}
From 208c648751e099863ef630b5d80e7fe91387f1ac Mon Sep 17 00:00:00 2001
From: "Colin T.A. Gray"
Date: Thu, 26 Sep 2024 10:48:50 -0400
Subject: [PATCH 6/6] if frame.origin.x is on left side of window, grow to the
right. Otherwise grow to the left.
---
keycastr/ModsVisualizer.m | 30 +++++++++++++++++++++++++-----
1 file changed, 25 insertions(+), 5 deletions(-)
diff --git a/keycastr/ModsVisualizer.m b/keycastr/ModsVisualizer.m
index 20e4557..aac9bfc 100644
--- a/keycastr/ModsVisualizer.m
+++ b/keycastr/ModsVisualizer.m
@@ -215,11 +215,31 @@ - (void)deactivateVisualizer:(id)sender {
- (void)noteFlagsChanged:(uint32_t)flags {
[_visualizerView noteFlagsChanged:flags];
- NSRect r = _visualizerWindow.frame;
- CGFloat right = r.origin.x + r.size.width;
- r.size.width = _visualizerView.frame.size.width;
- r.origin.x = right - r.size.width;
- [_visualizerWindow setFrame:r display:NO];
+ NSRect windowFrame = _visualizerWindow.frame;
+ NSScreen *screen = _visualizerWindow.screen;
+ if (!screen) {
+ for (NSScreen *s in NSScreen.screens) {
+ if (CGRectContainsPoint(s.frame, windowFrame.origin)) {
+ screen = s;
+ break;
+ }
+ }
+
+ if (!screen) {
+ screen = NSScreen.screens.firstObject;
+ }
+ }
+
+ NSRect screenFrame = screen.frame;
+ CGFloat screenX = windowFrame.origin.x - screenFrame.origin.x;
+ if (screenX > screenFrame.size.width / 2) {
+ CGFloat right = windowFrame.origin.x + windowFrame.size.width;
+ windowFrame.size.width = _visualizerView.frame.size.width;
+ windowFrame.origin.x = right - windowFrame.size.width;
+ } else {
+ windowFrame.size.width = _visualizerView.frame.size.width;
+ }
+ [_visualizerWindow setFrame:windowFrame display:NO];
[[NSUserDefaults standardUserDefaults] setValue:NSStringFromRect(_visualizerWindow.frame) forKey:@"mods.savedFrame"];
}