From 09bc36a4a4eebd48aee2d91653f64ce48cf0b792 Mon Sep 17 00:00:00 2001 From: Niclas Overby Date: Wed, 19 Aug 2026 15:13:33 +0200 Subject: [PATCH] fix(cider): four AppKit divergences the testsuite found, and a fifth that was never ours ELEVEN OF THE TWELVE APPKIT CASES PASS NOW, up from six, and the suite goes from 24 to 28 exit-zero of 35 run. Verified under the nested compositor, never headless. THE FIFTH WAS UPSTREAM. test_NSColor_colorUsingColorSpaceNamedevice is fifty lines of commented-out intentions and then exit(1), and CMake does not mark it WILL_FAIL, so it fails in upstream CI exactly as it fails here. Nothing in it touches this AppKit. It sat on the divergence list for a day on the strength of a non-zero exit code, and the generator names it as a placeholder now. AN EXCEPTION THAT EXISTED BUT COULD NOT BE REACHED. The case that would not compile wanted NSColorListNotEditableException, and declaring it beside the class that raises it is wrong twice over: it collides with a real declaration, and the constant was never missing. AppKit/NSErrors.h declares thirty-six exception names and NSErrors.m defines them all, but the header was private and the umbrella never imported it, so all thirty-six were invisible to an application. One move for thirty-six constants. Public headers here come from an explicit header_map in buck/generated and not a glob, so a new one has to be listed there or the umbrella cannot find its own header. A STUB THAT ANSWERED. isEditable was NSUnimplementedMethod and returned NO for everything, while insertColor:key:atIndex: inserted into anything, so an application offering the system palette for editing was told nothing and the edit did not survive. Editability is a real ivar now, YES for a list an application makes and NO for the four the framework builds, and insertColor raises on a refusal. setColor:forKey: stays unguarded on purpose: that is how the framework fills its own lists and how the display backend seeds a catalogue colour it has just answered. TWO LISTS SHIPPED UNDER INVENTED NAMES. macOS ships Apple, Crayons, System and Web Safe Colors; this AppKit shipped Basic, System and Web. Basic IS Apple classic palette and Web is the HTML named colours, so both are renamed, Crayons is new, and colorListNamed for Apple answers for the first time. That mattered more than it looks: the not-editable case asks four lists to refuse an insert, and against a nil list every one of those would have passed while proving nothing. THE SYSTEM LIST IS NOW THE 51 KEYS macOS PUBLISHES and no others. Trimming the older names is safe because a colour class method goes to the DISPLAY for its value and not to this list; the list decides what a colour panel offers and nothing else. Nineteen of the 51 had NO NSColor class method at all, the whole modern system palette plus the five fill levels, and a missing one is an unrecognised selector, which raises, which an application catches, which shows up as a feature that silently does nothing. Three more had a method but no recipe and answered nil, which is worse than wrong: AppKit draws with no colour, so a table simply has no grid. All are in colors.rs now, with an Rgba recipe added because the five fill colours are defined by their alpha. The system palette values are the published ones, transcribed rather than measured off a running macOS, and the twelve Crayons greys are a regular ramp rather than the exact macOS steps. BOTH NSCursor CODER CASES round trip: keyed reads NSImage and NSHotSpot, non-keyed writes float x, float y, image, two signed chars and reads float, float, signed short, image. THE PROOF IS NOT THE EXIT CODES. run.sh caps each case at two lines and an AppKit case spends both on the backend saying hello, so the one case that prints on its happy path looked as silent as one that did nothing. With the cap raised it prints all five refusals by name, System then Apple then Crayons then Web Safe Colors, which is what makes the zeros mean anything. LOOKED AT: Swift Publisher document window is BYTE IDENTICAL to its capture from before the change, so none of this moved a pixel in an application. Seen in that capture and not caused here: its Simulate paper color well and the inspector swatch both draw solid black. --- buck/generated/sdk_framework_buck_src.bzl | 3 +- docs/wayland-port.md | 62 +++++ scripts/gen-testsuite-buck.py | 12 + src/darwin/wayland/colors.rs | 45 ++++ .../cocotron/AppKit/NSColor.subproj/NSColor.m | 76 ++++++ vendor/pins/cocotron/AppKit/NSColorList.m | 255 ++++++++++++++---- vendor/pins/cocotron/AppKit/NSCursor.m | 51 +++- vendor/pins/cocotron/AppKit/NSErrors.m | 2 +- .../cocotron/AppKit/include/AppKit/AppKit.h | 1 + .../cocotron/AppKit/include/AppKit/NSColor.h | 19 ++ .../AppKit/include/AppKit/NSColorList.h | 7 + .../AppKit/{ => include/AppKit}/NSErrors.h | 0 vendor/src/BUCK | 2 + 13 files changed, 475 insertions(+), 60 deletions(-) rename vendor/pins/cocotron/AppKit/{ => include/AppKit}/NSErrors.h (100%) diff --git a/buck/generated/sdk_framework_buck_src.bzl b/buck/generated/sdk_framework_buck_src.bzl index 5458f3f6e..6ffa80c8c 100644 --- a/buck/generated/sdk_framework_buck_src.bzl +++ b/buck/generated/sdk_framework_buck_src.bzl @@ -67,6 +67,7 @@ FRAMEWORKS = { "AppKit/NSDrawer.h": "cocotron/AppKit/include/AppKit/NSDrawer.h", "AppKit/NSDynamicNamedColor.h": "cocotron/AppKit/include/AppKit/NSDynamicNamedColor.h", "AppKit/NSEPSImageRep.h": "cocotron/AppKit/include/AppKit/NSEPSImageRep.h", + "AppKit/NSErrors.h": "cocotron/AppKit/include/AppKit/NSErrors.h", "AppKit/NSEvent.h": "cocotron/AppKit/include/AppKit/NSEvent.h", "AppKit/NSFilePromiseProvider.h": "cocotron/AppKit/include/AppKit/NSFilePromiseProvider.h", "AppKit/NSFileWrapper.h": "cocotron/AppKit/include/AppKit/NSFileWrapper.h", @@ -104,6 +105,7 @@ FRAMEWORKS = { "AppKit/NSMenu.h": "cocotron/AppKit/include/AppKit/NSMenu.h", "AppKit/NSMenuItem.h": "cocotron/AppKit/include/AppKit/NSMenuItem.h", "AppKit/NSMenuItemCell.h": "cocotron/AppKit/include/AppKit/NSMenuItemCell.h", + "AppKit/NSModernAppKitAdditions.h": "cocotron/AppKit/include/AppKit/NSModernAppKitAdditions.h", "AppKit/NSMovie.h": "cocotron/AppKit/include/AppKit/NSMovie.h", "AppKit/NSMovieView.h": "cocotron/AppKit/include/AppKit/NSMovieView.h", "AppKit/NSMutableAttributedString.h": "cocotron/AppKit/include/AppKit/NSMutableAttributedString.h", @@ -211,7 +213,6 @@ FRAMEWORKS = { "AppKit/NSTextTable.h": "cocotron/AppKit/include/AppKit/NSTextTable.h", "AppKit/NSTextTableBlock.h": "cocotron/AppKit/include/AppKit/NSTextTableBlock.h", "AppKit/NSTextView.h": "cocotron/AppKit/include/AppKit/NSTextView.h", - "AppKit/NSModernAppKitAdditions.h": "cocotron/AppKit/include/AppKit/NSModernAppKitAdditions.h", "AppKit/NSTitlebarAccessoryViewController.h": "cocotron/AppKit/include/AppKit/NSTitlebarAccessoryViewController.h", "AppKit/NSTokenAttachment.h": "cocotron/AppKit/include/AppKit/NSTokenAttachment.h", "AppKit/NSTokenField.h": "cocotron/AppKit/include/AppKit/NSTokenField.h", diff --git a/docs/wayland-port.md b/docs/wayland-port.md index eecc690af..f7d324f94 100644 --- a/docs/wayland-port.md +++ b/docs/wayland-port.md @@ -11186,3 +11186,65 @@ One build note: QuartzCore was the entire AppKit build problem, because `AppKit. every case stopped at `QuartzCore/CIImage.h file not found` before saying anything about AppKit. The generator adds that header root and the AppKit dylib **only** for cases under `AppKit.framework` — pulling the GUI framework into a libc test would drag the display path somewhere it has no business. + +### What those five AppKit failures actually were (task #132) + +Four were real and are fixed; the fifth was never ours. **Eleven of the twelve AppKit cases pass +now**, and the suite as a whole goes 24 to 28 exit-zero of 35 run. + +`test_NSColor_colorUsingColorSpaceNamedevice` is fifty lines of commented-out intentions followed by +`exit(1)`, and CMake does not mark it `WILL_FAIL`, so it fails in upstream's own CI exactly as it +fails here. Nothing in it touches this AppKit. It was on the divergence list for a day for no better +reason than a non-zero exit code, and the generator names it as a placeholder now so it does not +come back. + +**The exception that existed but could not be reached.** The case that would not compile wanted +`NSColorListNotEditableException`, and the honest-looking fix is to declare it beside the class that +raises it. That is wrong twice over: it collides with a real declaration (`NSExceptionName` against +`NSString *const`), and the constant was never missing. `AppKit/NSErrors.h` declares thirty-six +exception names and `NSErrors.m` defines them all; the header simply was not public and the umbrella +did not import it, so every one of the thirty-six was invisible to an application. It is public now +and `AppKit.h` imports it, which is one move for thirty-six constants rather than one for one. +Public headers here come from an explicit `header_map` in `buck/generated`, not a glob, so a new one +has to be listed there too or the umbrella cannot find its own header. + +**A stub that answered.** `-[NSColorList isEditable]` was `NSUnimplementedMethod(); return NO;`, and +`insertColor:key:atIndex:` inserted into anything, so an application that offered a user the system +palette to edit was told nothing and the edit did not survive. Editability is a real ivar now, YES +for a list an application creates and NO for the four the framework builds, and `insertColor:` raises +on a refusal. `setColor:forKey:` is deliberately left unguarded: that is how the framework fills its +own lists and how the display backend seeds a catalogue colour it has just answered. + +**Two lists were shipping under invented names.** macOS ships `Apple`, `Crayons`, `System` and +`Web Safe Colors`; this AppKit shipped `Basic`, `System` and `Web`. `Basic` *is* Apple's classic +palette and `Web` is the HTML named colours, so those are renamed, `Crayons` is new (the 36 +chromatic crayons are the documented grid, the 12 greys a regular ramp rather than the exact macOS +steps), and `colorListNamed:@"Apple"` answers for the first time. That mattered more than it looks: +the not-editable test asks four lists to refuse an insert, and against a nil list every one of those +would have "passed" while proving nothing. + +**The System list is the keys macOS publishes**, exactly the 51 and no others. Trimming the older +names it carried is safe because a colour class method goes to the DISPLAY for its value +(`NSColor_catalog` asks `[[NSDisplay currentDisplay] colorWithName:]`), not to this list; what is in +the list decides what a colour panel offers and nothing else. Nineteen of the 51 had no `NSColor` +class method at all — the whole modern `system*Color` palette, the five fill levels, +`quinaryLabelColor` and `findHighlightColor` — and a missing one is an unrecognised selector, which +raises, which most applications catch, which turns a feature off with no message. Three more had a +method but no recipe (`gridColor`, `keyboardFocusIndicatorColor`, +`unemphasizedSelectedTextBackgroundColor`) and so answered nil, which is worse than wrong: AppKit +draws with no colour and a table simply has no grid. All are in `src/darwin/wayland/colors.rs` now, +with an `Rgba` recipe added because the five fill colours are defined by their alpha. + +**The NSCursor coder cases** pin an exact archive layout, and both round trips work now: keyed +coding reads `NSImage` and `NSHotSpot`, and non-keyed writes float x, float y, image, two signed +chars and reads float, float, signed short, image. + +Verified under the nested compositor, and the proof is not the exit codes. `run.sh` caps each case at +two lines of output and an AppKit case spends both on the backend saying hello, so the one case that +prints on its happy path looked as silent as one that did nothing. With the cap raised it prints all +five refusals by name — `color list System is not editable`, then Apple, Crayons and Web Safe Colors +— which is what makes the zeros mean anything. Swift Publisher's document window is **byte-identical** +to its capture from before the change, so none of this moved a pixel in an application. + +Left behind, seen in that capture and not caused here: Swift Publisher's "Simulate paper color" well +and the swatch under the inspector both draw solid black. diff --git a/scripts/gen-testsuite-buck.py b/scripts/gen-testsuite-buck.py index 97fbf696e..6c612c607 100644 --- a/scripts/gen-testsuite-buck.py +++ b/scripts/gen-testsuite-buck.py @@ -110,6 +110,15 @@ def will_fail_cases(): return names +# CASES WHOSE BODY IS A PLACEHOLDER UPSTREAM. test_NSColor_colorUsingColorSpaceNamedevice is fifty +# lines of commented-out intentions and then exit(1), and CMake does NOT mark it WILL_FAIL, so it +# fails in upstream's own CI exactly as it fails here. It was counted as an AppKit divergence of +# this port for a while, which it never was: nothing in it touches our AppKit at all. +UPSTREAM_PLACEHOLDERS = { + "test_NSColor_colorUsingColorSpaceNamedevice", +} + + def main(): want_appkit = "--appkit" in sys.argv if "--willfail" in sys.argv: @@ -142,6 +151,9 @@ def main(): out.append("# BEGIN GENERATED by scripts/gen-testsuite-buck.py -- do not edit by hand.") expect_fail = will_fail_cases() out.append(f"# {len(cases)} cases.") + out.append("# Cases whose body upstream has not written yet (exit(1) and nothing else):") + for n in sorted(UPSTREAM_PLACEHOLDERS): + out.append(f"# {n}") out.append("# Cases upstream marks WILL_FAIL, where a non-zero exit IS the pass:") for n in sorted(expect_fail): out.append(f"# {n}") diff --git a/src/darwin/wayland/colors.rs b/src/darwin/wayland/colors.rs index 863f38454..e8f6f8744 100644 --- a/src/darwin/wayland/colors.rs +++ b/src/darwin/wayland/colors.rs @@ -27,6 +27,10 @@ enum Recipe { /// used for a selection since Aqua, and every selected menu item, every default button and /// every highlighted row was drawn in it. Rgb(f64, f64, f64), + /// [NSColor colorWithCalibratedRed:g:b:alpha:a], for the colours whose ALPHA is the point. + /// The five fill colours are defined as a tint of black at a few percent, so painting them + /// opaque would not be a slightly wrong shade, it would be a black box. + Rgba(f64, f64, f64, f64), } /// The macOS accent blue, which is what a selection is filled with. @@ -90,6 +94,41 @@ fn recipe_for(name: &str) -> Option { "quaternaryLabelColor" => Recipe::Grey(0.7), "placeholderTextColor" => Recipe::Grey(0.6), "systemGrayColor" => Recipe::Grey(0.5), + "quinaryLabelColor" => Recipe::Grey(0.82), + // A NAME WITH A METHOD BUT NO RECIPE ANSWERED nil, which is the failure this table warns + // about at the top: a table drew no grid and a focused control no ring, and neither is + // distinguishable by looking from a control that was never asked to draw one. + "gridColor" => Recipe::Grey(0.8), + "keyboardFocusIndicatorColor" => Recipe::Rgba(0.0, 0.478, 1.0, 0.5), + "unemphasizedSelectedTextBackgroundColor" => Recipe::Grey(0.86), + "alternatingContentBackgroundColor" => Recipe::Grey(0.96), + // The yellow behind the current match in a find bar. + "findHighlightColor" => Recipe::Rgb(1.0, 1.0, 0.0), + // THE FILL HIERARCHY, black at a few percent, lighter with each step down. An application + // fills a control background with these and expects to see what is underneath through them. + "systemFillColor" => Recipe::Rgba(0.0, 0.0, 0.0, 0.10), + "secondarySystemFillColor" => Recipe::Rgba(0.0, 0.0, 0.0, 0.08), + "tertiarySystemFillColor" => Recipe::Rgba(0.0, 0.0, 0.0, 0.05), + "quaternarySystemFillColor" => Recipe::Rgba(0.0, 0.0, 0.0, 0.03), + "quinarySystemFillColor" => Recipe::Rgba(0.0, 0.0, 0.0, 0.02), + // THE MACOS SYSTEM PALETTE, light appearance. These are the published values, transcribed + // rather than measured off a running macOS, and they are what an application means when it + // asks for a colour BY ROLE instead of by value: a red that is the system red, not 1,0,0. + // Until now every one of these was an unrecognised selector, which raises, and a raise + // inside a drawing method is caught by most applications and turns the feature off with no + // message at all. + "systemRedColor" => Recipe::Rgb(1.0, 0.231, 0.188), + "systemOrangeColor" => Recipe::Rgb(1.0, 0.584, 0.0), + "systemYellowColor" => Recipe::Rgb(1.0, 0.8, 0.0), + "systemGreenColor" => Recipe::Rgb(0.157, 0.804, 0.255), + "systemMintColor" => Recipe::Rgb(0.0, 0.78, 0.745), + "systemTealColor" => Recipe::Rgb(0.349, 0.678, 0.769), + "systemCyanColor" => Recipe::Rgb(0.333, 0.745, 0.941), + "systemBlueColor" => Recipe::Rgb(0.0, 0.478, 1.0), + "systemIndigoColor" => Recipe::Rgb(0.345, 0.337, 0.839), + "systemPurpleColor" => Recipe::Rgb(0.686, 0.322, 0.871), + "systemPinkColor" => Recipe::Rgb(1.0, 0.176, 0.333), + "systemBrownColor" => Recipe::Rgb(0.635, 0.518, 0.369), _ => return None, }) } @@ -187,6 +226,12 @@ pub fn color_with_name(name: objc::Object) -> objc::Object { )); objc::msg_send_f64_4(color_cls, sel, r, g, b, 1.0) } + Some(Recipe::Rgba(r, g, b, a)) => { + let sel = objc::sel_registerName(cstr!( + "colorWithCalibratedRed:green:blue:alpha:" + )); + objc::msg_send_f64_4(color_cls, sel, r, g, b, a) + } } } } diff --git a/vendor/pins/cocotron/AppKit/NSColor.subproj/NSColor.m b/vendor/pins/cocotron/AppKit/NSColor.subproj/NSColor.m index 812edc587..9d8585d15 100644 --- a/vendor/pins/cocotron/AppKit/NSColor.subproj/NSColor.m +++ b/vendor/pins/cocotron/AppKit/NSColor.subproj/NSColor.m @@ -508,6 +508,82 @@ NSNotificationName const NSSystemColorsDidChangeNotification = @"NSSystemColorsD return [NSColor colorWithCatalogName: @"System" colorName: @"labelColor"]; } ++ (NSColor *) quinaryLabelColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"quinaryLabelColor"]; +} + ++ (NSColor *) findHighlightColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"findHighlightColor"]; +} + ++ (NSColor *) systemFillColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"systemFillColor"]; +} + ++ (NSColor *) secondarySystemFillColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"secondarySystemFillColor"]; +} + ++ (NSColor *) tertiarySystemFillColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"tertiarySystemFillColor"]; +} + ++ (NSColor *) quaternarySystemFillColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"quaternarySystemFillColor"]; +} + ++ (NSColor *) quinarySystemFillColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"quinarySystemFillColor"]; +} + ++ (NSColor *) systemRedColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"systemRedColor"]; +} + ++ (NSColor *) systemOrangeColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"systemOrangeColor"]; +} + ++ (NSColor *) systemYellowColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"systemYellowColor"]; +} + ++ (NSColor *) systemGreenColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"systemGreenColor"]; +} + ++ (NSColor *) systemMintColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"systemMintColor"]; +} + ++ (NSColor *) systemTealColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"systemTealColor"]; +} + ++ (NSColor *) systemCyanColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"systemCyanColor"]; +} + ++ (NSColor *) systemBlueColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"systemBlueColor"]; +} + ++ (NSColor *) systemIndigoColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"systemIndigoColor"]; +} + ++ (NSColor *) systemPurpleColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"systemPurpleColor"]; +} + ++ (NSColor *) systemPinkColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"systemPinkColor"]; +} + ++ (NSColor *) systemBrownColor { + return [NSColor colorWithCatalogName: @"System" colorName: @"systemBrownColor"]; +} + + (NSColor *) unemphasizedSelectedTextColor { return [NSColor colorWithCatalogName: @"System" colorName: @"unemphasizedSelectedTextColor"]; diff --git a/vendor/pins/cocotron/AppKit/NSColorList.m b/vendor/pins/cocotron/AppKit/NSColorList.m index 1b7406ffa..da35436c7 100644 --- a/vendor/pins/cocotron/AppKit/NSColorList.m +++ b/vendor/pins/cocotron/AppKit/NSColorList.m @@ -174,14 +174,89 @@ static NSMutableDictionary *_namedColorLists = nil; {@"Yellow Green", 0x9ACD32}, {nil, 0x0}}; - NSColorList *basicColorList = - [[[NSColorList alloc] initWithName: @"Basic"] autorelease]; + /* THE FOUR LISTS macOS SHIPS, by the names it ships them under. Two of these already existed + * under names of this framework's own invention, which is why an application asking for the + * standard ones by name got nothing: "Basic" is Apple's classic palette and "Web" is the + * HTML named colours, so the first is renamed and the second takes the slot macOS calls + * "Web Safe Colors". Its CONTENTS are still the HTML names rather than the 216 web safe + * values, which is a difference nothing here checks yet. + * + * Crayons is new. The 36 chromatic crayons are the documented grid (a hue wheel at full + * saturation, then tinted, then shaded); the 12 greys are a regular ramp rather than the + * exact macOS steps, which were not transcribed. */ + NSColorList *appleColorList = + [[[NSColorList alloc] initWithName: @"Apple"] autorelease]; + NSColorList *crayonsColorList = + [[[NSColorList alloc] initWithName: @"Crayons"] autorelease]; NSColorList *systemColorList = [[[NSColorList alloc] initWithName: @"System"] autorelease]; NSColorList *webColorList = - [[[NSColorList alloc] initWithName: @"Web"] autorelease]; + [[[NSColorList alloc] initWithName: @"Web Safe Colors"] autorelease]; int i; + struct { + NSString *name; + unsigned value; + } crayons[] = { + {@"Maraschino", 0xFF0000}, + {@"Tangerine", 0xFF8000}, + {@"Lemon", 0xFFFF00}, + {@"Lime", 0x80FF00}, + {@"Spring", 0x00FF00}, + {@"Sea Foam", 0x00FF80}, + {@"Turquoise", 0x00FFFF}, + {@"Aqua", 0x0080FF}, + {@"Blueberry", 0x0000FF}, + {@"Grape", 0x8000FF}, + {@"Magenta", 0xFF00FF}, + {@"Strawberry", 0xFF0080}, + {@"Salmon", 0xFF6666}, + {@"Cantaloupe", 0xFFCC66}, + {@"Banana", 0xFFFF66}, + {@"Honeydew", 0xCCFF66}, + {@"Flora", 0x66FF66}, + {@"Spindrift", 0x66FFCC}, + {@"Ice", 0x66FFFF}, + {@"Sky", 0x66CCFF}, + {@"Orchid", 0x6666FF}, + {@"Lavender", 0xCC66FF}, + {@"Bubblegum", 0xFF66FF}, + {@"Carnation", 0xFF66CC}, + {@"Cayenne", 0x800000}, + {@"Mocha", 0x804000}, + {@"Asparagus", 0x808000}, + {@"Fern", 0x408000}, + {@"Clover", 0x008000}, + {@"Moss", 0x008040}, + {@"Teal", 0x008080}, + {@"Ocean", 0x004080}, + {@"Midnight", 0x000080}, + {@"Eggplant", 0x400080}, + {@"Plum", 0x800080}, + {@"Maroon", 0x800040}, + {@"Snow", 0xFFFFFF}, + {@"Mercury", 0xE8E8E8}, + {@"Silver", 0xD1D1D1}, + {@"Magnesium", 0xBABABA}, + {@"Aluminum", 0xA2A2A2}, + {@"Nickel", 0x8B8B8B}, + {@"Tin", 0x747474}, + {@"Steel", 0x5D5D5D}, + {@"Tungsten", 0x464646}, + {@"Iron", 0x2E2E2E}, + {@"Lead", 0x171717}, + {@"Licorice", 0x000000}, + {nil, 0x0}}; + + /* THE SYSTEM LISTS ARE NOT EDITABLE, and saying so is the whole point of the flag: an + * application asks before offering to edit, and mutating one raises. setColor:forKey: below + * is deliberately not guarded, because that is how the framework fills them and how the + * display backend seeds a catalogue colour it has just answered. */ + appleColorList->_isEditable = NO; + crayonsColorList->_isEditable = NO; + systemColorList->_isEditable = NO; + webColorList->_isEditable = NO; + for (i = 0; webColors[i].name != nil; i++) { unsigned value = webColors[i].value; CGFloat red = ((value >> 16) & 0xFF) / 255.0; @@ -195,86 +270,143 @@ static NSMutableDictionary *_namedColorLists = nil; [webColorList setColor: color forKey: webColors[i].name]; } - [basicColorList setColor: [NSColor blackColor] forKey: @"Black"]; - [basicColorList setColor: [NSColor blueColor] forKey: @"Blue"]; - [basicColorList setColor: [NSColor brownColor] forKey: @"Brown"]; - [basicColorList setColor: [NSColor cyanColor] forKey: @"Cyan"]; - [basicColorList setColor: [NSColor greenColor] forKey: @"Green"]; - [basicColorList setColor: [NSColor magentaColor] forKey: @"Magenta"]; - [basicColorList setColor: [NSColor orangeColor] forKey: @"Orange"]; - [basicColorList setColor: [NSColor purpleColor] forKey: @"Purple"]; - [basicColorList setColor: [NSColor redColor] forKey: @"Red"]; - [basicColorList setColor: [NSColor yellowColor] forKey: @"Yellow"]; - [basicColorList setColor: [NSColor whiteColor] forKey: @"White"]; - - [systemColorList setColor: [NSColor alternateSelectedControlColor] - forKey: @"alternateSelectedControlColor"]; + for (i = 0; crayons[i].name != nil; i++) { + unsigned value = crayons[i].value; + CGFloat red = ((value >> 16) & 0xFF) / 255.0; + CGFloat green = ((value >> 8) & 0xFF) / 255.0; + CGFloat blue = (value & 0xFF) / 255.0; + + [crayonsColorList setColor: [NSColor colorWithCalibratedRed: red + green: green + blue: blue + alpha: 1.0] + forKey: crayons[i].name]; + } + + [appleColorList setColor: [NSColor blackColor] forKey: @"Black"]; + [appleColorList setColor: [NSColor blueColor] forKey: @"Blue"]; + [appleColorList setColor: [NSColor brownColor] forKey: @"Brown"]; + [appleColorList setColor: [NSColor cyanColor] forKey: @"Cyan"]; + [appleColorList setColor: [NSColor greenColor] forKey: @"Green"]; + [appleColorList setColor: [NSColor magentaColor] forKey: @"Magenta"]; + [appleColorList setColor: [NSColor orangeColor] forKey: @"Orange"]; + [appleColorList setColor: [NSColor purpleColor] forKey: @"Purple"]; + [appleColorList setColor: [NSColor redColor] forKey: @"Red"]; + [appleColorList setColor: [NSColor yellowColor] forKey: @"Yellow"]; + [appleColorList setColor: [NSColor whiteColor] forKey: @"White"]; + + /* THE SYSTEM LIST IS THE KEYS macOS PUBLISHES, exactly these and no others. The older names + * this list used to carry (controlHighlightColor, knobColor, scrollBarColor and the rest) are + * still answered by NSColor: a class method here goes to the DISPLAY for its value, not to + * this list, so what is in the list decides what a colour panel offers and nothing else. */ [systemColorList setColor: [NSColor alternateSelectedControlTextColor] forKey: @"alternateSelectedControlTextColor"]; + [systemColorList setColor: [NSColor alternatingContentBackgroundColor] + forKey: @"alternatingContentBackgroundColor"]; + [systemColorList setColor: [NSColor controlAccentColor] + forKey: @"controlAccentColor"]; [systemColorList setColor: [NSColor controlBackgroundColor] forKey: @"controlBackgroundColor"]; - [systemColorList setColor: [NSColor controlColor] forKey: @"controlColor"]; - [systemColorList setColor: [NSColor controlDarkShadowColor] - forKey: @"controlDarkShadowColor"]; - [systemColorList setColor: [NSColor controlHighlightColor] - forKey: @"controlHighlightColor"]; - [systemColorList setColor: [NSColor controlLightHighlightColor] - forKey: @"controlLightHighlightColor"]; - [systemColorList setColor: [NSColor controlShadowColor] - forKey: @"controlShadowColor"]; + [systemColorList setColor: [NSColor controlColor] + forKey: @"controlColor"]; [systemColorList setColor: [NSColor controlTextColor] forKey: @"controlTextColor"]; [systemColorList setColor: [NSColor disabledControlTextColor] forKey: @"disabledControlTextColor"]; - [systemColorList setColor: [NSColor gridColor] forKey: @"gridColor"]; - [systemColorList setColor: [NSColor headerColor] forKey: @"headerColor"]; + [systemColorList setColor: [NSColor findHighlightColor] + forKey: @"findHighlightColor"]; + [systemColorList setColor: [NSColor gridColor] + forKey: @"gridColor"]; [systemColorList setColor: [NSColor headerTextColor] forKey: @"headerTextColor"]; - [systemColorList setColor: [NSColor highlightColor] - forKey: @"highlightColor"]; [systemColorList setColor: [NSColor keyboardFocusIndicatorColor] forKey: @"keyboardFocusIndicatorColor"]; - [systemColorList setColor: [NSColor knobColor] forKey: @"knobColor"]; - [systemColorList setColor: [NSColor scrollBarColor] - forKey: @"scrollBarColor"]; - [systemColorList setColor: [NSColor secondarySelectedControlColor] - forKey: @"secondarySelectedControlColor"]; + [systemColorList setColor: [NSColor labelColor] + forKey: @"labelColor"]; + [systemColorList setColor: [NSColor linkColor] + forKey: @"linkColor"]; + [systemColorList setColor: [NSColor placeholderTextColor] + forKey: @"placeholderTextColor"]; + [systemColorList setColor: [NSColor quaternaryLabelColor] + forKey: @"quaternaryLabelColor"]; + [systemColorList setColor: [NSColor quaternarySystemFillColor] + forKey: @"quaternarySystemFillColor"]; + [systemColorList setColor: [NSColor quinaryLabelColor] + forKey: @"quinaryLabelColor"]; + [systemColorList setColor: [NSColor quinarySystemFillColor] + forKey: @"quinarySystemFillColor"]; + [systemColorList setColor: [NSColor secondaryLabelColor] + forKey: @"secondaryLabelColor"]; + [systemColorList setColor: [NSColor secondarySystemFillColor] + forKey: @"secondarySystemFillColor"]; + [systemColorList setColor: [NSColor selectedContentBackgroundColor] + forKey: @"selectedContentBackgroundColor"]; [systemColorList setColor: [NSColor selectedControlColor] forKey: @"selectedControlColor"]; [systemColorList setColor: [NSColor selectedControlTextColor] forKey: @"selectedControlTextColor"]; - [systemColorList setColor: [NSColor selectedKnobColor] - forKey: @"selectedKnobColor"]; - [systemColorList setColor: [NSColor selectedMenuItemColor] - forKey: @"selectedMenuItemColor"]; [systemColorList setColor: [NSColor selectedMenuItemTextColor] forKey: @"selectedMenuItemTextColor"]; [systemColorList setColor: [NSColor selectedTextBackgroundColor] forKey: @"selectedTextBackgroundColor"]; [systemColorList setColor: [NSColor selectedTextColor] forKey: @"selectedTextColor"]; - [systemColorList setColor: [NSColor shadowColor] forKey: @"shadowColor"]; + [systemColorList setColor: [NSColor separatorColor] + forKey: @"separatorColor"]; + [systemColorList setColor: [NSColor systemBlueColor] + forKey: @"systemBlueColor"]; + [systemColorList setColor: [NSColor systemBrownColor] + forKey: @"systemBrownColor"]; + [systemColorList setColor: [NSColor systemCyanColor] + forKey: @"systemCyanColor"]; + [systemColorList setColor: [NSColor systemFillColor] + forKey: @"systemFillColor"]; + [systemColorList setColor: [NSColor systemGrayColor] + forKey: @"systemGrayColor"]; + [systemColorList setColor: [NSColor systemGreenColor] + forKey: @"systemGreenColor"]; + [systemColorList setColor: [NSColor systemIndigoColor] + forKey: @"systemIndigoColor"]; + [systemColorList setColor: [NSColor systemMintColor] + forKey: @"systemMintColor"]; + [systemColorList setColor: [NSColor systemOrangeColor] + forKey: @"systemOrangeColor"]; + [systemColorList setColor: [NSColor systemPinkColor] + forKey: @"systemPinkColor"]; + [systemColorList setColor: [NSColor systemPurpleColor] + forKey: @"systemPurpleColor"]; + [systemColorList setColor: [NSColor systemRedColor] + forKey: @"systemRedColor"]; + [systemColorList setColor: [NSColor systemTealColor] + forKey: @"systemTealColor"]; + [systemColorList setColor: [NSColor systemYellowColor] + forKey: @"systemYellowColor"]; + [systemColorList setColor: [NSColor tertiaryLabelColor] + forKey: @"tertiaryLabelColor"]; + [systemColorList setColor: [NSColor tertiarySystemFillColor] + forKey: @"tertiarySystemFillColor"]; [systemColorList setColor: [NSColor textBackgroundColor] forKey: @"textBackgroundColor"]; - [systemColorList setColor: [NSColor textColor] forKey: @"textColor"]; - [systemColorList setColor: [NSColor windowBackgroundColor] - forKey: @"windowBackgroundColor"]; - [systemColorList setColor: [NSColor windowFrameColor] - forKey: @"windowFrameColor"]; - [systemColorList setColor: [NSColor labelColor] forKey: @"labelColor"]; - [systemColorList setColor: [NSColor linkColor] forKey: @"linkColor"]; + [systemColorList setColor: [NSColor textColor] + forKey: @"textColor"]; + [systemColorList setColor: [NSColor underPageBackgroundColor] + forKey: @"underPageBackgroundColor"]; + [systemColorList setColor: [NSColor unemphasizedSelectedContentBackgroundColor] + forKey: @"unemphasizedSelectedContentBackgroundColor"]; + [systemColorList setColor: [NSColor unemphasizedSelectedTextBackgroundColor] + forKey: @"unemphasizedSelectedTextBackgroundColor"]; [systemColorList setColor: [NSColor unemphasizedSelectedTextColor] forKey: @"unemphasizedSelectedTextColor"]; - [systemColorList setColor: [NSColor selectedContentBackgroundColor] - forKey: @"selectedContentBackgroundColor"]; - [systemColorList - setColor: [NSColor unemphasizedSelectedContentBackgroundColor] - forKey: @"unemphasizedSelectedContentBackgroundColor"]; + [systemColorList setColor: [NSColor windowBackgroundColor] + forKey: @"windowBackgroundColor"]; + [systemColorList setColor: [NSColor windowFrameTextColor] + forKey: @"windowFrameTextColor"]; _namedColorLists = [[NSMutableDictionary alloc] init]; - [_namedColorLists setObject: basicColorList forKey: @"Basic"]; + [_namedColorLists setObject: appleColorList forKey: @"Apple"]; + [_namedColorLists setObject: crayonsColorList forKey: @"Crayons"]; [_namedColorLists setObject: systemColorList forKey: @"System"]; - [_namedColorLists setObject: webColorList forKey: @"Web"]; + [_namedColorLists setObject: webColorList forKey: @"Web Safe Colors"]; } + (NSArray *) availableColorLists { @@ -289,6 +421,9 @@ static NSMutableDictionary *_namedColorLists = nil; _colors = [[NSMutableArray alloc] init]; _name = [name copy]; _path = [path copy]; + /* Editable by default: an application that makes a list means to fill it. The framework marks + * its own system lists otherwise, just below. */ + _isEditable = YES; if (_path != nil) { // FIX, file loading doesnt work for NSColorList @@ -319,8 +454,7 @@ static NSMutableDictionary *_namedColorLists = nil; } - (BOOL) isEditable { - NSUnimplementedMethod(); - return NO; + return _isEditable; } - (NSString *) name { @@ -386,6 +520,15 @@ static NSMutableDictionary *_namedColorLists = nil; key: (NSString *) key atIndex: (unsigned) index { + /* A SYSTEM LIST REFUSES BY RAISING, which is how an application learns it may not edit one. + * Ours inserted into it happily, so a caller that offered the user an editable list of system + * colours was told nothing at all and the edit simply did not survive. */ + if (![self isEditable]) { + [NSException raise: NSColorListNotEditableException + format: @"color list %@ is not editable", _name]; + return; + } + [_colors insertObject: color atIndex: index]; [_keys insertObject: key atIndex: index]; diff --git a/vendor/pins/cocotron/AppKit/NSCursor.m b/vendor/pins/cocotron/AppKit/NSCursor.m index 4cd74633a..f0b7ca3fd 100644 --- a/vendor/pins/cocotron/AppKit/NSCursor.m +++ b/vendor/pins/cocotron/AppKit/NSCursor.m @@ -189,13 +189,60 @@ static NSMutableArray *_cursorStack = nil; return [[[_cursorStack lastObject] retain] autorelease]; } +/* + * THE ARCHIVE LAYOUT IS PINNED BY TWO TESTS, and it is asymmetric in a way worth writing down. + * + * darling-testsuite drives a mock coder and asserts the exact sequence, so this is observed macOS + * behaviour rather than a guess: + * + * encode, five items: float x, float y, the image, then TWO signed chars + * decode, four items: float x, float y, ONE signed short, then the image + * + * The short and the pair of chars are the same two bytes, read either way round, which is how old + * NeXT archives carried a pair of flags. The two flags this class has are the mouse entered and + * exited ones, and neither test verifies them, so they are carried byte for byte and not + * reinterpreted beyond that. + */ - initWithCoder: (NSCoder *) coder { - // TODO: Need to implement + if ([coder allowsKeyedCoding]) { + _image = [[coder decodeObjectForKey: @"NSImage"] retain]; + _hotSpot = [coder decodePointForKey: @"NSHotSpot"]; + return self; + } + + float x = 0.0f; + float y = 0.0f; + signed short flags = 0; + + [coder decodeValueOfObjCType: @encode(float) at: &x]; + [coder decodeValueOfObjCType: @encode(float) at: &y]; + [coder decodeValueOfObjCType: @encode(signed short) at: &flags]; + + _hotSpot = NSMakePoint(x, y); + _image = [[coder decodeObject] retain]; + _isSetOnMouseEntered = (flags & 0x00ff) ? YES : NO; + _isSetOnMouseExited = (flags & 0xff00) ? YES : NO; + return self; } - (void) encodeWithCoder: (NSCoder *) coder { - NSUnimplementedMethod(); + if ([coder allowsKeyedCoding]) { + [coder encodeObject: _image forKey: @"NSImage"]; + [coder encodePoint: _hotSpot forKey: @"NSHotSpot"]; + return; + } + + float x = (float) _hotSpot.x; + float y = (float) _hotSpot.y; + signed char entered = _isSetOnMouseEntered ? 1 : 0; + signed char exited = _isSetOnMouseExited ? 1 : 0; + + [coder encodeValueOfObjCType: @encode(float) at: &x]; + [coder encodeValueOfObjCType: @encode(float) at: &y]; + [coder encodeObject: _image]; + [coder encodeValueOfObjCType: @encode(signed char) at: &entered]; + [coder encodeValueOfObjCType: @encode(signed char) at: &exited]; } - initWithName: (NSString *) name { diff --git a/vendor/pins/cocotron/AppKit/NSErrors.m b/vendor/pins/cocotron/AppKit/NSErrors.m index 6fd70333a..71b6bd5d6 100644 --- a/vendor/pins/cocotron/AppKit/NSErrors.m +++ b/vendor/pins/cocotron/AppKit/NSErrors.m @@ -1,4 +1,4 @@ -#import "NSErrors.h" +#import NSExceptionName NSTextLineTooLongException = @"NSTextLineTooLongException"; NSExceptionName NSTextNoSelectionException = @"NSTextNoSelectionException"; diff --git a/vendor/pins/cocotron/AppKit/include/AppKit/AppKit.h b/vendor/pins/cocotron/AppKit/include/AppKit/AppKit.h index 03a79ea96..a3ac72d1e 100644 --- a/vendor/pins/cocotron/AppKit/include/AppKit/AppKit.h +++ b/vendor/pins/cocotron/AppKit/include/AppKit/AppKit.h @@ -48,6 +48,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import #import +#import #import #import #import diff --git a/vendor/pins/cocotron/AppKit/include/AppKit/NSColor.h b/vendor/pins/cocotron/AppKit/include/AppKit/NSColor.h index cc5839328..20042ad23 100644 --- a/vendor/pins/cocotron/AppKit/include/AppKit/NSColor.h +++ b/vendor/pins/cocotron/AppKit/include/AppKit/NSColor.h @@ -46,6 +46,25 @@ typedef NSString *NSColorSpaceName; @property(class, strong, readonly) NSColor *placeholderTextColor; @property(class, strong, readonly) NSColor *systemGrayColor; @property(class, strong, readonly) NSColor *labelColor; +@property(class, strong, readonly) NSColor *quinaryLabelColor; +@property(class, strong, readonly) NSColor *findHighlightColor; +@property(class, strong, readonly) NSColor *systemFillColor; +@property(class, strong, readonly) NSColor *secondarySystemFillColor; +@property(class, strong, readonly) NSColor *tertiarySystemFillColor; +@property(class, strong, readonly) NSColor *quaternarySystemFillColor; +@property(class, strong, readonly) NSColor *quinarySystemFillColor; +@property(class, strong, readonly) NSColor *systemRedColor; +@property(class, strong, readonly) NSColor *systemOrangeColor; +@property(class, strong, readonly) NSColor *systemYellowColor; +@property(class, strong, readonly) NSColor *systemGreenColor; +@property(class, strong, readonly) NSColor *systemMintColor; +@property(class, strong, readonly) NSColor *systemTealColor; +@property(class, strong, readonly) NSColor *systemCyanColor; +@property(class, strong, readonly) NSColor *systemBlueColor; +@property(class, strong, readonly) NSColor *systemIndigoColor; +@property(class, strong, readonly) NSColor *systemPurpleColor; +@property(class, strong, readonly) NSColor *systemPinkColor; +@property(class, strong, readonly) NSColor *systemBrownColor; @property(class, strong, readonly) NSColor *textColor; @property(class, strong, readonly) NSColor *selectedTextColor; diff --git a/vendor/pins/cocotron/AppKit/include/AppKit/NSColorList.h b/vendor/pins/cocotron/AppKit/include/AppKit/NSColorList.h index 7192c0e71..f4f0aed03 100644 --- a/vendor/pins/cocotron/AppKit/include/AppKit/NSColorList.h +++ b/vendor/pins/cocotron/AppKit/include/AppKit/NSColorList.h @@ -23,11 +23,18 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ APPKIT_EXPORT NSString *const NSColorListDidChangeNotification; +/* Raised by the mutating methods when the receiver is not editable, which the system lists are not. + * An application that offers to edit a colour list catches this to tell the user why it cannot. */ + @interface NSColorList : NSObject { NSMutableArray *_keys; NSMutableArray *_colors; NSString *_name; NSString *_path; + /* Whether the mutating methods will do anything. The lists this framework builds for itself are + * the system ones and are not; a list an application creates is, which is what AppKit documents + * and what a colour panel relies on to know which lists it may offer to edit. */ + BOOL _isEditable; } + (NSArray *) availableColorLists; diff --git a/vendor/pins/cocotron/AppKit/NSErrors.h b/vendor/pins/cocotron/AppKit/include/AppKit/NSErrors.h similarity index 100% rename from vendor/pins/cocotron/AppKit/NSErrors.h rename to vendor/pins/cocotron/AppKit/include/AppKit/NSErrors.h diff --git a/vendor/src/BUCK b/vendor/src/BUCK index 5b99ca283..849058390 100644 --- a/vendor/src/BUCK +++ b/vendor/src/BUCK @@ -63532,6 +63532,8 @@ cc_objects( # BEGIN GENERATED by scripts/gen-testsuite-buck.py -- do not edit by hand. # 69 cases. +# Cases whose body upstream has not written yet (exit(1) and nothing else): +# test_NSColor_colorUsingColorSpaceNamedevice # Cases upstream marks WILL_FAIL, where a non-zero exit IS the pass: # test_exit_return_1 -- 2.51.2