git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

commit 58bd40b833eeb96d92a65e146de52adaaf9c6fba
parent cbaf5c4c4a385ae5f3c79a9520efe527d89ead76
Author: Lior Halphon <LIJI32@gmail.com>
Date:   Tue, 24 Jun 2025 21:29:58 +0300

Work around gazillion Solarium bugs

Diffstat:
MCocoa/Document.xib42++++++++++++++++++++++++------------------
ACocoa/GBToolbarFieldCell.h5+++++
ACocoa/GBToolbarFieldCell.m23+++++++++++++++++++++++
DCocoa/NSControl+SolariumFixer.m108-------------------------------------------------------------------------------
ACocoa/SolariumFixer.m156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MHexFiend/HFController.m2+-
6 files changed, 209 insertions(+), 127 deletions(-)

diff --git a/Cocoa/Document.xib b/Cocoa/Document.xib @@ -162,7 +162,7 @@ <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/> <subviews> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ybQ-jy-NgI" customClass="GBDebuggerButton"> - <rect key="frame" x="0.0" y="0.0" width="26" height="26"/> + <rect key="frame" x="4" y="0.0" width="26" height="26"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <buttonCell key="cell" type="bevel" title="Interrupt" alternateTitle="interrupt" bezelStyle="rounded" image="InterruptTemplate" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="Yd7-kY-21r"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> @@ -175,7 +175,7 @@ </connections> </button> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jdD-yP-Nr6" customClass="GBDebuggerButton"> - <rect key="frame" x="76" y="0.0" width="26" height="26"/> + <rect key="frame" x="80" y="0.0" width="26" height="26"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <buttonCell key="cell" type="bevel" title="Step Out" alternateTitle="finish" bezelStyle="rounded" image="FinishTemplate" imagePosition="only" alignment="center" enabled="NO" imageScaling="proportionallyDown" inset="2" id="16t-ix-lOh"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> @@ -187,7 +187,7 @@ </connections> </button> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tTP-Zs-Ohu" customClass="GBDebuggerButton"> - <rect key="frame" x="26" y="0.0" width="26" height="26"/> + <rect key="frame" x="30" y="0.0" width="26" height="26"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <buttonCell key="cell" type="bevel" title="Step Over" alternateTitle="next" bezelStyle="rounded" image="NextTemplate" imagePosition="only" alignment="center" enabled="NO" imageScaling="proportionallyDown" inset="2" id="835-qy-CNq"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> @@ -199,7 +199,7 @@ </connections> </button> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="E87-Uq-f2l" customClass="GBDebuggerButton"> - <rect key="frame" x="100" y="0.0" width="26" height="26"/> + <rect key="frame" x="104" y="0.0" width="26" height="26"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <buttonCell key="cell" type="bevel" title="Step Backward" alternateTitle="backstep" bezelStyle="rounded" image="BackstepTemplate" imagePosition="only" alignment="center" enabled="NO" imageScaling="proportionallyDown" inset="2" id="yr5-aU-Fli"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> @@ -211,7 +211,7 @@ </connections> </button> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fsQ-dD-A8C" customClass="GBDebuggerButton"> - <rect key="frame" x="52" y="0.0" width="26" height="26"/> + <rect key="frame" x="56" y="0.0" width="26" height="26"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <buttonCell key="cell" type="bevel" title="Step Into" alternateTitle="step" bezelStyle="rounded" image="StepTemplate" imagePosition="only" alignment="center" enabled="NO" imageScaling="proportionallyDown" inset="2" id="lau-41-TYH"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> @@ -231,7 +231,7 @@ <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/> </box> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0Jt-TO-8CM" customClass="GBDebuggerButton"> - <rect key="frame" x="565" y="0.0" width="26" height="26"/> + <rect key="frame" x="561" y="0.0" width="26" height="26"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/> <buttonCell key="cell" type="bevel" title="Help" alternateTitle="help" bezelStyle="rounded" image="HelpTemplate" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="fVh-bT-eYs"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> @@ -376,11 +376,11 @@ <toolbarItem implicitItemIdentifier="NSToolbarFlexibleSpaceItem" id="E3z-um-6KG"/> <toolbarItem implicitItemIdentifier="4F6AAE25-1E9D-4111-9E5B-91F0792E56CD" label="Address Space" paletteLabel="Address Space" id="VTy-lj-K0H"> <nil key="toolTip"/> - <size key="minSize" width="100" height="25"/> + <size key="minSize" width="160" height="25"/> <size key="maxSize" width="160" height="25"/> <popUpButton key="view" verticalHuggingPriority="750" id="vfJ-vu-gqJ"> <rect key="frame" x="0.0" y="14" width="160" height="25"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/> <popUpButtonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="bpD-j9-omo"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> <font key="font" metaFont="message"/> @@ -402,31 +402,37 @@ <toolbarItem implicitItemIdentifier="D16C64D2-2F0D-4033-A1EC-A1E699522ECE" label="Bank" paletteLabel="Bank" id="bWC-FW-IYP"> <nil key="toolTip"/> <size key="minSize" width="64" height="22"/> - <size key="maxSize" width="64" height="22"/> + <size key="maxSize" width="80" height="22"/> <textField key="view" focusRingType="none" verticalHuggingPriority="750" id="rdV-q6-hc6"> <rect key="frame" x="0.0" y="14" width="64" height="22"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="JCn-Y1-eHS"> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="NO" state="on" borderStyle="bezel" placeholderString="Bank" drawsBackground="YES" id="JCn-Y1-eHS" customClass="GBToolbarFieldCell"> <font key="font" metaFont="system"/> <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="boolean" keyPath="sendsWholeSearchString" value="YES"/> + </userDefinedRuntimeAttributes> </textFieldCell> <connections> <action selector="hexUpdateBank:" target="-2" id="Mx9-WI-wgO"/> </connections> </textField> </toolbarItem> - <toolbarItem implicitItemIdentifier="F9723DA8-D79F-43AB-876B-783DD0204AA6" label="Go to" paletteLabel="Go to" id="rLO-D7-zRG"> + <toolbarItem implicitItemIdentifier="F9723DA8-D79F-43AB-876B-783DD0204AA6" label="Go To" paletteLabel="Go To" id="rLO-D7-zRG"> <nil key="toolTip"/> - <size key="minSize" width="96" height="22"/> - <size key="maxSize" width="128" height="22"/> + <size key="minSize" width="160" height="22"/> + <size key="maxSize" width="160" height="22"/> <textField key="view" focusRingType="none" verticalHuggingPriority="750" id="EJd-jG-hmH"> - <rect key="frame" x="0.0" y="14" width="96" height="22"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" bezelStyle="round" id="vg5-Nn-abb"> + <rect key="frame" x="0.0" y="14" width="160" height="22"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES"/> + <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="NO" state="on" borderStyle="bezel" placeholderString="Address" bezelStyle="round" id="vg5-Nn-abb" customClass="GBToolbarFieldCell"> <font key="font" metaFont="system"/> <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="boolean" keyPath="sendsWholeSearchString" value="YES"/> + </userDefinedRuntimeAttributes> </textFieldCell> <connections> <action selector="hexGoTo:" target="-2" id="7WG-8C-SK8"/> @@ -1000,7 +1006,7 @@ </connections> </button> <box horizontalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="P90-u5-8ko"> - <rect key="frame" x="304" y="12" width="5" height="123"/> + <rect key="frame" x="302" y="12" width="5" height="123"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/> </box> </subviews> diff --git a/Cocoa/GBToolbarFieldCell.h b/Cocoa/GBToolbarFieldCell.h @@ -0,0 +1,5 @@ +#import <Cocoa/Cocoa.h> + +@interface GBToolbarFieldCell : NSSearchFieldCell + +@end diff --git a/Cocoa/GBToolbarFieldCell.m b/Cocoa/GBToolbarFieldCell.m @@ -0,0 +1,23 @@ +#import "GBToolbarFieldCell.h" +#import <objc/runtime.h> + +@interface NSTextFieldCell() +- (void)textDidChange:(id)sender; +@end + +@implementation GBToolbarFieldCell + +- (void)textDidChange:(id)sender +{ + IMP imp = [NSTextFieldCell instanceMethodForSelector:_cmd]; + method_setImplementation(class_getInstanceMethod([GBToolbarFieldCell class], _cmd), imp); + ((void(*)(id, SEL, id))imp)(self, _cmd, sender); +} + +- (void)endEditing:(NSText *)textObj +{ + IMP imp = [NSTextFieldCell instanceMethodForSelector:_cmd]; + method_setImplementation(class_getInstanceMethod([GBToolbarFieldCell class], _cmd), imp); + ((void(*)(id, SEL, id))imp)(self, _cmd, textObj); +} +@end diff --git a/Cocoa/NSControl+SolariumFixer.m b/Cocoa/NSControl+SolariumFixer.m @@ -1,108 +0,0 @@ -#import <Cocoa/Cocoa.h> -#import <objc/runtime.h> - -// Uncomment to debug -#define NSLog(...) - -// Solarium has weird proportions, we need to fix them. -@implementation NSControl (SolariumFixer) - -- (void)awakeFromNib -{ - if (@available(macOS 26.0, *)) { - if ([self.superview isKindOfClass:objc_getClass("NSToolbarItemViewer")]) return; - - if ([self isKindOfClass:[NSStepper class]]) { - NSLog(@"Stepper needs adjustment: %s in window %@", sel_getName(self.action), self.window.title); - CGRect frame = self.frame; - frame.origin.y += 1; - self.frame = frame; - return; - } - if (self.controlSize != NSControlSizeRegular) return; - - if ([self isKindOfClass:[NSPopUpButton class]] ) { - NSLog(@"Popup button needs adjustment: %@ in window %@", ((NSButton *)self).title, self.window.title); - CGRect frame = self.frame; - if (frame.size.height != 25) { - NSLog(@"%@ in window %@ has the wrong height!", ((NSButton *)self).title, self.window.title); - return; - } - frame.size.width -= 2 + 5; // Remove 5 from the right and 2 from the left - frame.origin.x += 2; - frame.origin.y += 2; - self.frame = frame; - } - else if ([self isKindOfClass:[NSSegmentedControl class]] ) { - NSLog(@"Segmented button needs adjustment: %s in window %@", sel_getName(self.action), self.window.title); - CGRect frame = self.frame; - if (frame.size.height != 25) { - NSLog(@"%s in window %@ has the wrong height!", sel_getName(self.action), self.window.title); - return; - } - frame.origin.x += 8; - frame.origin.y += 1; - self.frame = frame; - } - else if ([self isKindOfClass:[NSTextField class]]) { - NSTextField *field = (id)self; - if (![field isBezeled]) return; - NSLog(@"Text field needs adjustment: %@ in window %@", ((NSTextField *)self).placeholderString, self.window.title); - CGRect frame = self.frame; - if (frame.size.height == 21) { - frame.size.height = 24; - } - else { - NSLog(@"%@ in window %@ has the wrong height!", ((NSTextField *)self).placeholderString, self.window.title); - return; - } - frame.size.width -= 1 + 1; // Remove 1 from the right and 1 from the left - frame.origin.x += 1; - frame.origin.y -= 1; - - self.frame = frame; - } - else if ([self isKindOfClass:[NSButton class]]) { - NSLog(@"Button: %@ in window %@", @(sel_getName(self.action)), self.window.title); - NSButton *button = (id)self; - if (!button.isBordered) return; - if (button.bezelStyle == NSBezelStylePush) { - NSLog(@"Button needs adjustment: %@ in window %@", @(sel_getName(self.action)), self.window.title); - CGRect frame = self.frame; - frame.size.width -= 7 + 7; // Remove 7 from the right and 7 from the left - frame.origin.x += 7; - frame.origin.y += 5; - if (frame.size.height == 32) { - frame.size.height = 25; - } - else { - NSLog(@"%@ in window %@ has the wrong height!", @(sel_getName(self.action)), self.window.title); - } self.frame = frame; - } - else if (button.bezelStyle == NSBezelStyleRegularSquare) { - CGRect frame = self.frame; - if (frame.size.height != 18) return; - NSLog(@"Check/Radio needs adjustment: %@ in window %@", ((NSButton *)self).title, self.window.title); - frame.size.width -= 2; - frame.origin.x += 2; - frame.origin.y += 1; - frame.size.height = 16; - self.frame = frame; - } - else if (button.bezelStyle == NSBezelStyleHelpButton) { - CGRect frame = self.frame; - NSLog(@"Help button needs adjustment: %@ in window %@", ((NSButton *)self).title, self.window.title); - frame.origin.y += 2; - self.frame = frame; - } - } - else if ([self isKindOfClass:[NSSlider class]]) { - NSLog(@"Slider needs adjustment: %s in window %@", sel_getName(self.action), self.window.title); - CGRect frame = self.frame; - frame.origin.y += 3; - self.frame = frame; - } - } -} - -@end diff --git a/Cocoa/SolariumFixer.m b/Cocoa/SolariumFixer.m @@ -0,0 +1,156 @@ +#import <Cocoa/Cocoa.h> +#import <objc/runtime.h> + +// Comment out to debug +#define NSLog(...) + +// Solarium has weird proportions, we need to fix them. +@implementation NSControl (SolariumFixer) + +- (void)awakeFromNib +{ + if (@available(macOS 26.0, *)) { + if ([self.superview isKindOfClass:objc_getClass("NSToolbarItemViewer")]) return; + + if ([self isKindOfClass:[NSStepper class]]) { + NSLog(@"Stepper needs adjustment: %s in window %@", sel_getName(self.action), self.window.title); + CGRect frame = self.frame; + frame.origin.y += 1; + self.frame = frame; + return; + } + if (self.controlSize != NSControlSizeRegular) return; + + if ([self isKindOfClass:[NSPopUpButton class]] ) { + NSLog(@"Popup button needs adjustment: %@ in window %@", ((NSButton *)self).title, self.window.title); + CGRect frame = self.frame; + if (frame.size.height != 25) { + NSLog(@"%@ in window %@ has the wrong height!", ((NSButton *)self).title, self.window.title); + return; + } + frame.size.width -= 2 + 5; // Remove 5 from the right and 2 from the left + frame.origin.x += 2; + frame.origin.y += 2; + self.frame = frame; + } + else if ([self isKindOfClass:[NSSegmentedControl class]] ) { + NSLog(@"Segmented button needs adjustment: %s in window %@", sel_getName(self.action), self.window.title); + CGRect frame = self.frame; + if (frame.size.height != 25) { + NSLog(@"%s in window %@ has the wrong height!", sel_getName(self.action), self.window.title); + return; + } + frame.origin.x += 8; + frame.origin.y += 1; + self.frame = frame; + } + else if ([self isKindOfClass:[NSTextField class]]) { + NSTextField *field = (id)self; + if (![field isBezeled]) return; + NSLog(@"Text field needs adjustment: %@ in window %@", ((NSTextField *)self).placeholderString, self.window.title); + CGRect frame = self.frame; + if (frame.size.height == 21) { + frame.size.height = 24; + } + else { + NSLog(@"%@ in window %@ has the wrong height!", ((NSTextField *)self).placeholderString, self.window.title); + return; + } + frame.size.width -= 1 + 1; // Remove 1 from the right and 1 from the left + frame.origin.x += 1; + frame.origin.y -= 1; + + self.frame = frame; + } + else if ([self isKindOfClass:[NSButton class]]) { + NSLog(@"Button: %@ in window %@", @(sel_getName(self.action)), self.window.title); + NSButton *button = (id)self; + if (!button.isBordered) return; + if (button.bezelStyle == NSBezelStylePush) { + NSLog(@"Button needs adjustment: %@ in window %@", @(sel_getName(self.action)), self.window.title); + CGRect frame = self.frame; + frame.size.width -= 7 + 7; // Remove 7 from the right and 7 from the left + frame.origin.x += 7; + frame.origin.y += 5; + if (frame.size.height == 32) { + frame.size.height = 25; + } + else { + NSLog(@"%@ in window %@ has the wrong height!", @(sel_getName(self.action)), self.window.title); + } self.frame = frame; + } + else if (button.bezelStyle == NSBezelStyleRegularSquare) { + CGRect frame = self.frame; + if (frame.size.height != 18) return; + NSLog(@"Check/Radio needs adjustment: %@ in window %@", ((NSButton *)self).title, self.window.title); + frame.size.width -= 2; + frame.origin.x += 2; + frame.origin.y += 1; + frame.size.height = 16; + self.frame = frame; + } + else if (button.bezelStyle == NSBezelStyleHelpButton) { + CGRect frame = self.frame; + NSLog(@"Help button needs adjustment: %@ in window %@", ((NSButton *)self).title, self.window.title); + frame.origin.y += 2; + self.frame = frame; + } + } + else if ([self isKindOfClass:[NSSlider class]]) { + NSLog(@"Slider needs adjustment: %s in window %@", sel_getName(self.action), self.window.title); + CGRect frame = self.frame; + frame.origin.y += 3; + self.frame = frame; + } + } +} + +@end + +@implementation NSToolbarItem (SolariumFixer) + +- (void)awakeFromNib +{ + if (@available(macOS 26.0, *)) { + NSLog(@"Toolbar item %@ has view %@", self.label, self.view); + if ([self.view isKindOfClass:[NSTextField class]]) { + NSLog(@"Handling (Text field)"); + self.bordered = true; + + NSSize maxSize = self.maxSize; + maxSize.height = 36; + self.maxSize = maxSize; + + NSSize minSize = self.minSize; + minSize.height = 36; + self.minSize = minSize; + + ((NSTextField *)self.view).backgroundColor = [NSColor clearColor]; + ((NSTextField *)self.view).bezeled = false; + ((NSTextField *)self.view).bordered = true; + + // Work around even more AppKit bugs + self.toolbar.displayMode++; + self.toolbar.displayMode--; + } + else if ([self.view isKindOfClass:[NSPopUpButton class]]) { + NSLog(@"Handling (Pop up button)"); + self.bordered = true; + + NSSize maxSize = self.maxSize; + maxSize.height = 28; + self.maxSize = maxSize; + + NSSize minSize = self.minSize; + minSize.height = 28; + self.minSize = minSize; + } + } + else if (@available(macOS 11.0, *)) { // While at it, make macOS 11-15 a bit more consistent + if ([self.view isKindOfClass:[NSTextField class]]) { + ((NSTextField *)self.view).bezelStyle = NSTextFieldRoundedBezel; + } + } +} + +@end diff --git a/HexFiend/HFController.m b/HexFiend/HFController.m @@ -473,7 +473,7 @@ static inline Class preferredByteArrayClass(void) { } - (void)_setSingleSelectedContentsRange:(HFRange)newSelection { - HFASSERT(HFRangeIsSubrangeOfRange(newSelection, HFRangeMake(0, [self contentsLength]))); + if (!HFRangeIsSubrangeOfRange(newSelection, HFRangeMake(0, [self contentsLength]))) return; BOOL selectionChanged; if ([selectedContentsRanges count] == 1) { selectionChanged = ! HFRangeEqualsRange([selectedContentsRanges[0] HFRange], newSelection);

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.