From b0315e1df8118c5e05fd44553aac7db65c03cc4e Mon Sep 17 00:00:00 2001 From: "Timothy J. Wood" Date: Fri, 4 Feb 2011 11:55:08 -0800 Subject: [PATCH 1/6] Ignore Xcode 4 cruft. --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3238e1f --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.mode1v3 +*.pbxuser +*.xcworkspace +xcuserdata From fa4f2a216f0c77abed28a20868fe4b92472ac28a Mon Sep 17 00:00:00 2001 From: "Timothy J. Wood" Date: Fri, 4 Feb 2011 14:39:42 -0800 Subject: [PATCH 2/6] Updated with slight installation instruction change for Xcode 4. --- README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.markdown b/README.markdown index 8ce89dd..e875f77 100644 --- a/README.markdown +++ b/README.markdown @@ -1,7 +1,7 @@ XcodeSelectionColorFix =========== -When an Xcode editor is in a non-key window, it draws with `+secondarySelectedControlColor` as the background color for selected text. But, if you prefer to use a dark theme (like the included Midnight), this is illegible since the light text color and light background color are too similar. +When an Xcode 4 editor is in a non-key window, it draws with `+secondarySelectedControlColor` as the background color for selected text. But, if you prefer to use a dark theme (like the included Midnight), this is illegible since the light text color and light background color are too similar. This Xcode plugin hacks around and makes Xcode draw using a 50/50 mixture of the background color and selection color you specified in your theme. @@ -11,6 +11,6 @@ Installation - Build and install the bundle where ever you like - Inform Xcode of its location with: - defaults write com.apple.Xcode ExtraPlugInFolders -array-add "/path/to/folder/containing/plugin" + defaults write com.apple.dt.Xcode ExtraPlugInFolders -array-add "/path/to/folder/containing/plugin" -- Relaunch Xcode +- Relaunch Xcode 4 From 325db280e4d935fef2adcf93194c99f04e4803b4 Mon Sep 17 00:00:00 2001 From: "Timothy J. Wood" Date: Fri, 4 Feb 2011 15:06:17 -0800 Subject: [PATCH 3/6] Updated for Xcode 4's theme/layout system. --- main.m | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/main.m b/main.m index 0601ff2..ce1bf18 100644 --- a/main.m +++ b/main.m @@ -12,22 +12,30 @@ @implementation com_omnigroup_XcodeSelectionColorFix static void (*original_drawBackgroundForGlyphRange)(id self, SEL _cmd, NSRange glyphsToShow, NSPoint origin) = NULL; static int32_t drawBackgroundForGlyphRangeNesting = 0; -static Class XCLayoutManager = Nil; -static Class XCTextView = Nil; +static Class DVTLayoutManager = Nil; +static Class DVTFontAndColorTheme = Nil; #define REQUIRE_CLASS(x) \ do { \ x = NSClassFromString((id)CFSTR(#x)); \ if (!x) { \ - NSLog(@"%s: Unable to find class '%s'!", __PRETTY_FUNCTION__, #x); \ + NSLog(@"%s: Unable to find class \"%s\"!", __PRETTY_FUNCTION__, #x); \ return; \ } \ } while (0) -#define REQUIRE_METHOD(object, name) \ +#define REQUIRE_CLASS_METHOD(cls, name) \ do { \ - if (![object respondsToSelector:@selector(name)]) { \ - NSLog(@"%s: '%s' doesn't respond to '%s'.", __PRETTY_FUNCTION__, #object, #name); \ + if (![cls respondsToSelector:@selector(name)]) { \ + NSLog(@"%s: \"%s\" doesn't respond to +%s.", __PRETTY_FUNCTION__, #cls, #name); \ + return; \ + } \ +} while (0) + +#define REQUIRE_INSTANCE_METHOD(cls, name) \ +do { \ + if (![cls instancesRespondToSelector:@selector(name)]) { \ + NSLog(@"%s: Instances of \"%s\" don't respond to -%s.", __PRETTY_FUNCTION__, #cls, #name); \ return; \ } \ } while (0) @@ -41,11 +49,12 @@ + (void)load; return; // Could also check the superclasses of these, but that seems like overkill - REQUIRE_CLASS(XCLayoutManager); + REQUIRE_CLASS(DVTLayoutManager); - REQUIRE_CLASS(XCTextView); - REQUIRE_METHOD(XCTextView, textEditorBackgroundColor); - REQUIRE_METHOD(XCTextView, textEditorSelectionBackgroundColor); + REQUIRE_CLASS(DVTFontAndColorTheme); + REQUIRE_CLASS_METHOD(DVTFontAndColorTheme, currentTheme); + REQUIRE_INSTANCE_METHOD(DVTFontAndColorTheme, sourceTextSelectionColor); + REQUIRE_INSTANCE_METHOD(DVTFontAndColorTheme, consoleTextSelectionColor); original_secondarySelectedControlColor = (typeof(original_secondarySelectedControlColor))OBReplaceMethodImplementationWithSelectorOnClass(object_getClass([NSColor class]), @selector(secondarySelectedControlColor), self, @selector(replacement_secondarySelectedControlColor)); if (!original_secondarySelectedControlColor) { @@ -53,7 +62,7 @@ + (void)load; return; } - original_drawBackgroundForGlyphRange = (typeof(original_drawBackgroundForGlyphRange))OBReplaceMethodImplementationWithSelectorOnClass(XCLayoutManager, @selector(drawBackgroundForGlyphRange:atPoint:), self, @selector(replacement_drawBackgroundForGlyphRange:atPoint:)); + original_drawBackgroundForGlyphRange = (typeof(original_drawBackgroundForGlyphRange))OBReplaceMethodImplementationWithSelectorOnClass(DVTLayoutManager, @selector(drawBackgroundForGlyphRange:atPoint:), self, @selector(replacement_drawBackgroundForGlyphRange:atPoint:)); if (!original_drawBackgroundForGlyphRange) { NSLog(@"Unable to replace method."); return; @@ -66,9 +75,10 @@ - (NSColor *)replacement_secondarySelectedControlColor; return original_secondarySelectedControlColor(self, _cmd); // Return a color interpolated between the user's background color and selection color. - NSColor *color0 = [[XCTextView performSelector:@selector(textEditorBackgroundColor)] colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; - NSColor *color1 = [[XCTextView performSelector:@selector(textEditorSelectionBackgroundColor)] colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; - + id theme = [DVTFontAndColorTheme performSelector:@selector(currentTheme)]; + NSColor *color0 = [[theme performSelector:@selector(sourceTextSelectionColor)] colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; + NSColor *color1 = [[theme performSelector:@selector(sourceTextBackgroundColor)] colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; + return [color0 blendedColorWithFraction:0.5 ofColor:color1]; } From c29238f3fbfd4a7514ed589b0d8f93f5aaae183a Mon Sep 17 00:00:00 2001 From: "Timothy J. Wood" Date: Wed, 9 Feb 2011 15:00:23 -0800 Subject: [PATCH 4/6] Replace the source editor's text cursor with a white one. This is really only applicable for dark themes; better would be to detect the brightness of the background or mask with the text color. Anyway, works better for me. --- Info.plist | 14 +++----- .../project.pbxproj | 8 +++++ cursor.png | Bin 0 -> 943 bytes main.m | 33 ++++++++++++++++++ 4 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 cursor.png diff --git a/Info.plist b/Info.plist index ac47f95..c240782 100644 --- a/Info.plist +++ b/Info.plist @@ -6,26 +6,22 @@ English CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleName - ${PRODUCT_NAME} CFBundleIconFile CFBundleIdentifier - com.yourcompany.${PRODUCT_NAME:rfc1034Identifier} + com.omnigroup.${PRODUCT_NAME:rfc1034Identifier} CFBundleInfoDictionaryVersion 6.0 + CFBundleName + ${PRODUCT_NAME} CFBundlePackageType BNDL + CFBundleShortVersionString + 1.0 CFBundleSignature ???? CFBundleVersion 1 - CFBundleShortVersionString - 1.0 - LoadAtLaunch YES XCGCReady diff --git a/XcodeSelectionColorFix.xcodeproj/project.pbxproj b/XcodeSelectionColorFix.xcodeproj/project.pbxproj index 6b54eaf..c46351f 100644 --- a/XcodeSelectionColorFix.xcodeproj/project.pbxproj +++ b/XcodeSelectionColorFix.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 344DC542101A2768003A6019 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 344DC541101A2768003A6019 /* main.m */; }; 34849A9B101A51FE003602A4 /* OBMethodReplacement.m in Sources */ = {isa = PBXBuildFile; fileRef = 34849A9A101A51FE003602A4 /* OBMethodReplacement.m */; }; 34849ADE101A56FE003602A4 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34849ADD101A56FE003602A4 /* Cocoa.framework */; }; + 34C076AA130350E60075B54B /* cursor.png in Resources */ = {isa = PBXBuildFile; fileRef = 34C076A9130350E60075B54B /* cursor.png */; }; 8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8D5B49A704867FD3000E48DA /* InfoPlist.strings */; }; /* End PBXBuildFile section */ @@ -20,6 +21,7 @@ 34849A99101A51FE003602A4 /* OBMethodReplacement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OBMethodReplacement.h; sourceTree = ""; }; 34849A9A101A51FE003602A4 /* OBMethodReplacement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OBMethodReplacement.m; sourceTree = ""; }; 34849ADD101A56FE003602A4 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; + 34C076A9130350E60075B54B /* cursor.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = cursor.png; sourceTree = ""; }; 8D576316048677EA00EA77CD /* XcodeSelectionColorFix.xcplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XcodeSelectionColorFix.xcplugin; sourceTree = BUILT_PRODUCTS_DIR; }; 8D576317048677EA00EA77CD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ @@ -60,6 +62,7 @@ isa = PBXGroup; children = ( 8D576317048677EA00EA77CD /* Info.plist */, + 34C076A9130350E60075B54B /* cursor.png */, 8D5B49A704867FD3000E48DA /* InfoPlist.strings */, ); name = Resources; @@ -111,7 +114,11 @@ isa = PBXProject; buildConfigurationList = 1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "XcodeSelectionColorFix" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; + knownRegions = ( + en, + ); mainGroup = 089C166AFE841209C02AAC07 /* XcodeSelectionColorFix */; projectDirPath = ""; projectRoot = ""; @@ -127,6 +134,7 @@ buildActionMask = 2147483647; files = ( 8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */, + 34C076AA130350E60075B54B /* cursor.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/cursor.png b/cursor.png new file mode 100644 index 0000000000000000000000000000000000000000..90a7a7215f4eac8582bed5c0e7a9c57edf1b69e6 GIT binary patch literal 943 zcmV;g15o^lP)4Tx0C)j~RL^S@K@|QrZmG~B2wH0nvUrdpNm;9CMbtL^5n^i$+aIn^?(HA4aZWV5ov6ELTdbo0FI&wK{O>*+w4vx20?>!`FrQsdJlnHR>OPy zcd~b_n$otK2Za4V;76L-DzNVtaSB-y0*E}{p()372;bw_^6ZZ}PI-92wGS&j#91PI zKs7DSe@(bk%_Y-7gGe}(^>I=@oY#w#*Bu9GZf3^F5WP>3rn}7Ut74&?PWBFvy`A)a zPP5)V!Xd&78LdA?xQ(9mjMYElVd13a#D+Z_7&Y|xU=_C-srWU*6kiZcC!$nw*)9$7 zn6CX+@=AhmkT}X@VSsa5NKe;HZuq)~1$`#h6R+ZTR#D-3j}vF!)ZOnz+5)dI4jl{{ z44Mr{P!L4~VVJN`K!!XTF*LGrKO?IK8z<8w`3e3jI8lUGNUta*C8 zn(P`s>{pjD=7Kek#B;Fw@hxAK%$F&Q6vg9J^Xf~4by_hu-=A!MJ3Znq&n~srbFGPs zH&&aMXZ>nO`|hf|ljc?VPhR!${AbO?W8x_>CU%PFA&Hm8F7cAsOREdwU~R_;ot1_u z(ruCYB-LPGn!NQdT|ZlRy+(fw^-+`=%+gee_kY4FWHg<*4sZI8+sFJD270UUORdLHO0nA4V) z%{fwsET5CQ>B?eK%uw4yQc~9?*JVo2}ze(;aRcp*ceL#HUJSllrgm5wQKR zQu+C;QrUh^8rFfA`ftFz{YAidi-`aL010qNS#tmY3ljhU3ljkVnw%H_003u6L_t(I z5$%)R3cw%;g>BF0+v@wdWPD>q8@1~MJLVs84wZ-ycMqwiswFXPl)Eb3nG0|;t6>O8 z{tNG6npTE$=I9=@eBBGAB@ykxDMpbG+%itl);2+2A_RiZ+FM+*fNX!h^9g{M+$n&e RSJ40f002ovPDHLkV1mt9y}|$h literal 0 HcmV?d00001 diff --git a/main.m b/main.m index ce1bf18..36281d1 100644 --- a/main.m +++ b/main.m @@ -12,8 +12,11 @@ @implementation com_omnigroup_XcodeSelectionColorFix static void (*original_drawBackgroundForGlyphRange)(id self, SEL _cmd, NSRange glyphsToShow, NSPoint origin) = NULL; static int32_t drawBackgroundForGlyphRangeNesting = 0; +static void (*original_mouseInside)(id self, SEL _cmd, NSEvent *event) = NULL; + static Class DVTLayoutManager = Nil; static Class DVTFontAndColorTheme = Nil; +static Class DVTSourceTextView = Nil; #define REQUIRE_CLASS(x) \ do { \ @@ -56,6 +59,8 @@ + (void)load; REQUIRE_INSTANCE_METHOD(DVTFontAndColorTheme, sourceTextSelectionColor); REQUIRE_INSTANCE_METHOD(DVTFontAndColorTheme, consoleTextSelectionColor); + REQUIRE_CLASS(DVTSourceTextView); + original_secondarySelectedControlColor = (typeof(original_secondarySelectedControlColor))OBReplaceMethodImplementationWithSelectorOnClass(object_getClass([NSColor class]), @selector(secondarySelectedControlColor), self, @selector(replacement_secondarySelectedControlColor)); if (!original_secondarySelectedControlColor) { NSLog(@"Unable to replace method."); @@ -67,6 +72,12 @@ + (void)load; NSLog(@"Unable to replace method."); return; } + + original_mouseInside = (typeof(original_mouseInside))OBReplaceMethodImplementationWithSelectorOnClass(DVTSourceTextView, @selector(_mouseInside:), self, @selector(_mouseInside:)); + if (!original_mouseInside) { + NSLog(@"Unable to replace method."); + return; + } } - (NSColor *)replacement_secondarySelectedControlColor; @@ -92,4 +103,26 @@ - (void)replacement_drawBackgroundForGlyphRange:(NSRange)glyphsToShow atPoint:(N } } +// Normally the IBeamCursor is set by this hitting a implementation on NSTextView. I'm hooking it on DVTSourceTextView for now, but it might need to be more tightly tuned. +- (void)_mouseInside:(NSEvent *)event; +{ + static NSCursor *cursor = nil; + + if (!cursor) { + NSString *imagePath = [[NSBundle bundleWithIdentifier:@"com.omnigroup.XcodeSelectionColorFix"] pathForImageResource:@"cursor"]; + if (!imagePath) { + NSLog(@"No cursor image found!"); + } else { + NSImage *image = [[NSImage alloc] initWithContentsOfFile:imagePath]; + if (!image) + NSLog(@"Unable to load cursor image"); + else + cursor = [[NSCursor alloc] initWithImage:image hotSpot:[[NSCursor IBeamCursor] hotSpot]]; + } + if (!cursor) + cursor = [[NSCursor IBeamCursor] retain]; + } + [cursor set]; +} + @end From 72fb86a3cd7dcf369c76a515d756837b3da20fa8 Mon Sep 17 00:00:00 2001 From: "Timothy J. Wood" Date: Wed, 9 Feb 2011 15:24:21 -0800 Subject: [PATCH 5/6] Apply the light i-beam cursor to the debug console too. --- main.m | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/main.m b/main.m index 36281d1..5c05729 100644 --- a/main.m +++ b/main.m @@ -12,11 +12,10 @@ @implementation com_omnigroup_XcodeSelectionColorFix static void (*original_drawBackgroundForGlyphRange)(id self, SEL _cmd, NSRange glyphsToShow, NSPoint origin) = NULL; static int32_t drawBackgroundForGlyphRangeNesting = 0; -static void (*original_mouseInside)(id self, SEL _cmd, NSEvent *event) = NULL; - static Class DVTLayoutManager = Nil; static Class DVTFontAndColorTheme = Nil; static Class DVTSourceTextView = Nil; +static Class IDEConsoleTextView = Nil; #define REQUIRE_CLASS(x) \ do { \ @@ -60,6 +59,7 @@ + (void)load; REQUIRE_INSTANCE_METHOD(DVTFontAndColorTheme, consoleTextSelectionColor); REQUIRE_CLASS(DVTSourceTextView); + REQUIRE_CLASS(IDEConsoleTextView); original_secondarySelectedControlColor = (typeof(original_secondarySelectedControlColor))OBReplaceMethodImplementationWithSelectorOnClass(object_getClass([NSColor class]), @selector(secondarySelectedControlColor), self, @selector(replacement_secondarySelectedControlColor)); if (!original_secondarySelectedControlColor) { @@ -73,8 +73,12 @@ + (void)load; return; } - original_mouseInside = (typeof(original_mouseInside))OBReplaceMethodImplementationWithSelectorOnClass(DVTSourceTextView, @selector(_mouseInside:), self, @selector(_mouseInside:)); - if (!original_mouseInside) { + // Install light-mode cursors for the source and debug console + if (!OBReplaceMethodImplementationWithSelectorOnClass(DVTSourceTextView, @selector(_mouseInside:), self, @selector(_mouseInside:))) { + NSLog(@"Unable to replace method."); + return; + } + if (!OBReplaceMethodImplementationWithSelectorOnClass(IDEConsoleTextView, @selector(_mouseInside:), self, @selector(_mouseInside:))) { NSLog(@"Unable to replace method."); return; } From d037de7e3ab56ec050eb494d35a55782367f5cc6 Mon Sep 17 00:00:00 2001 From: "Timothy J. Wood" Date: Fri, 4 Mar 2011 11:29:57 -0800 Subject: [PATCH 6/6] Mark this plugin as Xcode 4 compatible. --- Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Info.plist b/Info.plist index c240782..dc82a7c 100644 --- a/Info.plist +++ b/Info.plist @@ -28,5 +28,7 @@ YES XCPluginHasUI NO + XC4Compatible +