Full Code of jordanbaird/Ice for AI

main 11edd39115f3 cached
152 files
677.5 KB
154.5k tokens
1 requests
Download .txt
Showing preview only (723K chars total). Download the full file or copy to clipboard to get everything.
Repository: jordanbaird/Ice
Branch: main
Commit: 11edd39115f3
Files: 152
Total size: 677.5 KB

Directory structure:
gitextract_awypvfy4/

├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   ├── config.yml
│   │   └── feature_request.yml
│   └── workflows/
│       └── lint.yml
├── .gitignore
├── .swiftlint.yml
├── CODE_OF_CONDUCT.md
├── FREQUENT_ISSUES.md
├── Ice/
│   ├── Assets.xcassets/
│   │   ├── AccentColor.colorset/
│   │   │   └── Contents.json
│   │   ├── AppIcon.appiconset/
│   │   │   └── Contents.json
│   │   ├── Contents.json
│   │   ├── ControlItemImages/
│   │   │   ├── Contents.json
│   │   │   ├── Dot/
│   │   │   │   ├── Contents.json
│   │   │   │   ├── DotFill.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   └── DotStroke.imageset/
│   │   │   │       └── Contents.json
│   │   │   ├── Ellipsis/
│   │   │   │   ├── Contents.json
│   │   │   │   ├── EllipsisFill.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   └── EllipsisStroke.imageset/
│   │   │   │       └── Contents.json
│   │   │   └── IceCube/
│   │   │       ├── Contents.json
│   │   │       ├── IceCubeFill.imageset/
│   │   │       │   └── Contents.json
│   │   │       └── IceCubeStroke.imageset/
│   │   │           └── Contents.json
│   │   ├── DefaultLayoutBarColor.colorset/
│   │   │   └── Contents.json
│   │   └── Warning.imageset/
│   │       └── Contents.json
│   ├── Bridging/
│   │   ├── Bridging.swift
│   │   └── Shims/
│   │       ├── Deprecated.swift
│   │       └── Private.swift
│   ├── Events/
│   │   ├── EventManager.swift
│   │   ├── EventMonitors/
│   │   │   ├── GlobalEventMonitor.swift
│   │   │   ├── LocalEventMonitor.swift
│   │   │   ├── RunLoopLocalEventMonitor.swift
│   │   │   └── UniversalEventMonitor.swift
│   │   └── EventTap.swift
│   ├── Hotkeys/
│   │   ├── Hotkey.swift
│   │   ├── HotkeyAction.swift
│   │   ├── HotkeyRegistry.swift
│   │   ├── KeyCode.swift
│   │   ├── KeyCombination.swift
│   │   └── Modifiers.swift
│   ├── Ice.entitlements
│   ├── Info.plist
│   ├── Main/
│   │   ├── AppDelegate.swift
│   │   ├── AppState.swift
│   │   ├── IceApp.swift
│   │   └── Navigation/
│   │       ├── AppNavigationState.swift
│   │       └── NavigationIdentifiers/
│   │           ├── NavigationIdentifier.swift
│   │           └── SettingsNavigationIdentifier.swift
│   ├── MenuBar/
│   │   ├── Appearance/
│   │   │   ├── Configurations/
│   │   │   │   ├── MenuBarAppearanceConfigurationV1.swift
│   │   │   │   └── MenuBarAppearanceConfigurationV2.swift
│   │   │   ├── MenuBarAppearanceEditor/
│   │   │   │   ├── MenuBarAppearanceEditor.swift
│   │   │   │   ├── MenuBarAppearanceEditorPanel.swift
│   │   │   │   └── MenuBarShapePicker.swift
│   │   │   ├── MenuBarAppearanceManager.swift
│   │   │   ├── MenuBarOverlayPanel.swift
│   │   │   ├── MenuBarShape.swift
│   │   │   └── MenuBarTintKind.swift
│   │   ├── ControlItem/
│   │   │   ├── ControlItem.swift
│   │   │   ├── ControlItemImage.swift
│   │   │   └── ControlItemImageSet.swift
│   │   ├── MenuBarItems/
│   │   │   ├── MenuBarItem.swift
│   │   │   ├── MenuBarItemImageCache.swift
│   │   │   ├── MenuBarItemInfo.swift
│   │   │   └── MenuBarItemManager.swift
│   │   ├── MenuBarManager.swift
│   │   ├── MenuBarSection.swift
│   │   ├── Search/
│   │   │   └── MenuBarSearchPanel.swift
│   │   └── Spacing/
│   │       └── MenuBarItemSpacingManager.swift
│   ├── Permissions/
│   │   ├── Permission.swift
│   │   ├── PermissionsManager.swift
│   │   ├── PermissionsView.swift
│   │   └── PermissionsWindow.swift
│   ├── Resources/
│   │   └── Acknowledgements.rtf
│   ├── Settings/
│   │   ├── SettingsManagers/
│   │   │   ├── AdvancedSettingsManager.swift
│   │   │   ├── GeneralSettingsManager.swift
│   │   │   ├── HotkeySettingsManager.swift
│   │   │   └── SettingsManager.swift
│   │   ├── SettingsPanes/
│   │   │   ├── AboutSettingsPane.swift
│   │   │   ├── AdvancedSettingsPane.swift
│   │   │   ├── GeneralSettingsPane.swift
│   │   │   ├── HotkeysSettingsPane.swift
│   │   │   ├── MenuBarAppearanceSettingsPane.swift
│   │   │   └── MenuBarLayoutSettingsPane.swift
│   │   ├── SettingsView.swift
│   │   └── SettingsWindow.swift
│   ├── Swizzling/
│   │   └── NSSplitViewItem+swizzledCanCollapse.swift
│   ├── UI/
│   │   ├── HotkeyRecorder/
│   │   │   ├── HotkeyRecorder.swift
│   │   │   └── HotkeyRecorderModel.swift
│   │   ├── IceBar/
│   │   │   ├── IceBar.swift
│   │   │   ├── IceBarColorManager.swift
│   │   │   └── IceBarLocation.swift
│   │   ├── IceUI/
│   │   │   ├── IceForm.swift
│   │   │   ├── IceGroupBox.swift
│   │   │   ├── IceLabeledContent.swift
│   │   │   ├── IceMenu.swift
│   │   │   ├── IcePicker.swift
│   │   │   ├── IceSection.swift
│   │   │   └── IceSlider.swift
│   │   ├── LayoutBar/
│   │   │   ├── LayoutBar.swift
│   │   │   ├── LayoutBarContainer.swift
│   │   │   ├── LayoutBarItemView.swift
│   │   │   ├── LayoutBarPaddingView.swift
│   │   │   └── LayoutBarScrollView.swift
│   │   ├── Pickers/
│   │   │   ├── CustomColorPicker/
│   │   │   │   └── CustomColorPicker.swift
│   │   │   └── CustomGradientPicker/
│   │   │       ├── ColorStop.swift
│   │   │       ├── CustomGradient.swift
│   │   │       └── CustomGradientPicker.swift
│   │   ├── Shapes/
│   │   │   └── AnyInsettableShape.swift
│   │   ├── ViewModifiers/
│   │   │   ├── BottomBar.swift
│   │   │   ├── ErasedToAnyView.swift
│   │   │   ├── LayoutBarStyle.swift
│   │   │   ├── LocalEventMonitorModifier.swift
│   │   │   ├── OnFrameChange.swift
│   │   │   ├── OnKeyDown.swift
│   │   │   ├── Once.swift
│   │   │   ├── ReadWindow.swift
│   │   │   └── RemoveSidebarToggle.swift
│   │   └── Views/
│   │       ├── AnnotationView.swift
│   │       ├── BetaBadge.swift
│   │       ├── SectionedList.swift
│   │       └── VisualEffectView.swift
│   ├── Updates/
│   │   └── UpdatesManager.swift
│   ├── UserNotifications/
│   │   ├── UserNotificationIdentifier.swift
│   │   └── UserNotificationManager.swift
│   └── Utilities/
│       ├── BindingExposable.swift
│       ├── CodableColor.swift
│       ├── Constants.swift
│       ├── Defaults.swift
│       ├── Extensions.swift
│       ├── IconResource.swift
│       ├── Injection.swift
│       ├── LocalizedErrorWrapper.swift
│       ├── Logging.swift
│       ├── MigrationManager.swift
│       ├── MouseCursor.swift
│       ├── Notifications.swift
│       ├── ObjectStorage.swift
│       ├── Predicates.swift
│       ├── RehideStrategy.swift
│       ├── ScreenCapture.swift
│       ├── StatusItemDefaults.swift
│       ├── SystemAppearance.swift
│       ├── TaskTimeout.swift
│       └── WindowInfo.swift
├── Ice.xcodeproj/
│   ├── project.pbxproj
│   ├── project.xcworkspace/
│   │   ├── contents.xcworkspacedata
│   │   └── xcshareddata/
│   │       ├── IDEWorkspaceChecks.plist
│   │       └── swiftpm/
│   │           └── Package.resolved
│   └── xcshareddata/
│       └── xcschemes/
│           └── Ice.xcscheme
├── LICENSE
├── README.md
└── Resources/
    └── Icon.fig

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
*.rtf linguist-vendored


================================================
FILE: .github/FUNDING.yml
================================================
github: jordanbaird
buy_me_a_coffee: jordanbaird


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: Bug Report
description: Submit a bug report.
title: "[Bug]: "
labels: Bug
body:
  - type: checkboxes
    attributes:
      label: Search for Similar Reports
      description: |
        Please use the search feature on the repository's [Issues](https://github.com/jordanbaird/Ice/issues) page to see if a report already exists for the bug you encountered. Make sure to include both open and closed issues in your search.

        **Important**: Only submit a new issue if the bug you encountered hasn't been reported in an existing open issue, or if a regression has occurred with a previously closed issue.
      options:
        - label: I have searched existing issues for similar reports
          required: true
  - type: textarea
    attributes:
      label: Description
      placeholder: A clear and concise description of the bug...
    validations:
      required: true
  - type: textarea
    attributes:
      label: Steps to Reproduce
      description: Steps to reliably reproduce the behavior.
      placeholder: |
        1. Go to '...'
        2. Click on '....'
        3. Scroll down to '....'
        4. See error
    validations:
      required: true
  - type: input
    id: app_version
    attributes:
      label: App Version
      placeholder: e.g. 1.2.3
    validations:
      required: true
  - type: input
    id: macos_version
    attributes:
      label: macOS Version
      placeholder: e.g. 15.3.2
    validations:
      required: true
  - type: textarea
    attributes:
      label: Additional Information
      placeholder: Screenshots, screen recordings, logs, crash reports, or anything else you think might be helpful...


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
name: Feature Request
description: Request a feature or suggest an idea.
title: "[Feature Request]: "
labels: Feature
body:
  - type: checkboxes
    attributes:
      label: Search for Similar Requests
      description: |
        Please use the search feature on the repository's [Issues](https://github.com/jordanbaird/Ice/issues) page to see if this feature has already been requested. Make sure to include both open and closed issues in your search.

        **Important**: Only submit a new issue if the feature you want hasn't been requested in another issue.
      options:
        - label: I have searched existing issues for similar requests
          required: true
  - type: textarea
    attributes:
      label: Description
      placeholder: A clear and concise description of the feature...
    validations:
      required: true
  - type: textarea
    attributes:
      label: Additional Information
      placeholder: Screenshots, screen recordings, mockups, or anything else you think might be helpful...


================================================
FILE: .github/workflows/lint.yml
================================================
name: Lint Swift Files
on:
  push:
    branches: [ "main" ]
    paths:
      - ".github/workflows/lint.yml"
      - ".swiftlint.yml"
      - "**/*.swift"
  pull_request:
    paths:
      - ".github/workflows/lint.yml"
      - ".swiftlint.yml"
      - "**/*.swift"
jobs:
  swiftlint:
    if: '!github.event.pull_request.merged'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run SwiftLint
        uses: norio-nomura/action-swiftlint@3.2.1
        with:
          args: --strict


================================================
FILE: .gitignore
================================================
.DS_Store
build/
xcuserdata/


================================================
FILE: .swiftlint.yml
================================================
included:
  - Ice

disabled_rules:
  - cyclomatic_complexity
  - file_length
  - function_body_length
  - function_parameter_count
  - generic_type_name
  - identifier_name
  - large_tuple
  - line_length
  - nesting
  - opening_brace
  - todo
  - type_body_length

opt_in_rules:
  - closure_end_indentation
  - closure_spacing
  - collection_alignment
  - convenience_type
  - discouraged_object_literal
  - empty_count
  - fatal_error_message
  - file_header
  - force_unwrapping
  - implicitly_unwrapped_optional
  - indentation_width
  - literal_expression_end_indentation
  - lower_acl_than_parent
  - modifier_order
  - multiline_arguments
  - multiline_arguments_brackets
  - multiline_literal_brackets
  - multiline_parameters
  - multiline_parameters_brackets
  - period_spacing
  - unavailable_function
  - vertical_parameter_alignment_on_call
  - vertical_whitespace_closing_braces
  - yoda_condition

custom_rules:
  objc_dynamic:
    name: "@objc dynamic"
    message: "`dynamic` modifier should immediately follow `@objc` attribute"
    regex: '@objc\b(\(\w*\))?+\s*(\S+|\v+\S*)\s*\bdynamic'
    match_kinds: attribute.builtin
  prefer_spaces_over_tabs:
    name: Prefer Spaces Over Tabs
    message: "Indentation should use 4 spaces per indentation level instead of tabs"
    regex: ^\t

file_header:
  required_pattern: |
    //
    //  SWIFTLINT_CURRENT_FILENAME
    //  Ice
    //

modifier_order:
  preferred_modifier_order:
    - acl
    - setterACL
    - override
    - mutators
    - lazy
    - final
    - required
    - convenience
    - typeMethods
    - owned

trailing_comma:
  mandatory_comma: true


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

* The use of sexualized language or imagery, and sexual attention or
  advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
  address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
jordanbaird.dev@gmail.com.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior,  harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.


================================================
FILE: FREQUENT_ISSUES.md
================================================
# Frequent Issues <!-- omit in toc -->

- [Items are moved to the always-hidden section](#items-are-moved-to-the-always-hidden-section)
- [Ice removed an item](#ice-removed-an-item)
- [Ice does not remember the order of items](#ice-does-not-remember-the-order-of-items)
- [How do I solve the `Ice cannot arrange menu bar items in automatically hidden menu bars` error?](#how-do-i-solve-the-ice-cannot-arrange-menu-bar-items-in-automatically-hidden-menu-bars-error)

## Items are moved to the always-hidden section

By default, macOS adds new items to the far left of the menu bar, which is also the location of Ice's always-hidden section. Most apps are configured
to remember the positions of their items, but some are not. macOS treats the items of these apps as new items each time they appear. This results in
these items appearing in the always-hidden section, even if they have been previously been moved.

Ice does not currently manage individual items, and in fact cannot, as of the current release. Once issues
[#6](https://github.com/jordanbaird/Ice/issues/6) and [#26](https://github.com/jordanbaird/Ice/issues/26) are implemented, Ice will be able to
monitor the items in the menu bar, and move the ones it recognizes to their previous locations, even if macOS rearranges them.

## Ice removed an item

Ice does not have the ability to move or remove items. It likely got placed in the always-hidden section by macOS. Option + click the Ice icon to show
the always-hidden section, then Command + drag the item into a different section.

## Ice does not remember the order of items

This is not a bug, but a missing feature. It is being tracked in [#26](https://github.com/jordanbaird/Ice/issues/26).

## How do I solve the `Ice cannot arrange menu bar items in automatically hidden menu bars` error?

1. Open `System Settings` on your Mac
2. Go to `Control Center`
3. Select `Never` as shown in the image below
4. Update your `Menu Bar Items` in `Ice`
5. Return `Automatically hide and show the menu bar` to your preferred settings

![Disable Menu Bar Hiding](https://github.com/user-attachments/assets/74c1fde6-d310-4fe3-9f2b-703d8ccb636a)


================================================
FILE: Ice/Assets.xcassets/AccentColor.colorset/Contents.json
================================================
{
  "colors" : [
    {
      "idiom" : "universal"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: Ice/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "filename" : "icon_16x16.png",
      "idiom" : "mac",
      "scale" : "1x",
      "size" : "16x16"
    },
    {
      "filename" : "icon_16x16@2x.png",
      "idiom" : "mac",
      "scale" : "2x",
      "size" : "16x16"
    },
    {
      "filename" : "icon_32x32.png",
      "idiom" : "mac",
      "scale" : "1x",
      "size" : "32x32"
    },
    {
      "filename" : "icon_32x32@2x.png",
      "idiom" : "mac",
      "scale" : "2x",
      "size" : "32x32"
    },
    {
      "filename" : "icon_128x128.png",
      "idiom" : "mac",
      "scale" : "1x",
      "size" : "128x128"
    },
    {
      "filename" : "icon_128x128@2x.png",
      "idiom" : "mac",
      "scale" : "2x",
      "size" : "128x128"
    },
    {
      "filename" : "icon_256x256.png",
      "idiom" : "mac",
      "scale" : "1x",
      "size" : "256x256"
    },
    {
      "filename" : "icon_256x256@2x.png",
      "idiom" : "mac",
      "scale" : "2x",
      "size" : "256x256"
    },
    {
      "filename" : "icon_512x512.png",
      "idiom" : "mac",
      "scale" : "1x",
      "size" : "512x512"
    },
    {
      "filename" : "icon_512x512@2x.png",
      "idiom" : "mac",
      "scale" : "2x",
      "size" : "512x512"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: Ice/Assets.xcassets/Contents.json
================================================
{
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: Ice/Assets.xcassets/ControlItemImages/Contents.json
================================================
{
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: Ice/Assets.xcassets/ControlItemImages/Dot/Contents.json
================================================
{
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: Ice/Assets.xcassets/ControlItemImages/Dot/DotFill.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "filename" : "DotFill.png",
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  },
  "properties" : {
    "template-rendering-intent" : "template"
  }
}


================================================
FILE: Ice/Assets.xcassets/ControlItemImages/Dot/DotStroke.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "filename" : "DotStroke.png",
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  },
  "properties" : {
    "template-rendering-intent" : "template"
  }
}


================================================
FILE: Ice/Assets.xcassets/ControlItemImages/Ellipsis/Contents.json
================================================
{
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: Ice/Assets.xcassets/ControlItemImages/Ellipsis/EllipsisFill.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "filename" : "EllipsisFill.png",
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  },
  "properties" : {
    "template-rendering-intent" : "template"
  }
}


================================================
FILE: Ice/Assets.xcassets/ControlItemImages/Ellipsis/EllipsisStroke.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "filename" : "EllipsisStroke.png",
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  },
  "properties" : {
    "template-rendering-intent" : "template"
  }
}


================================================
FILE: Ice/Assets.xcassets/ControlItemImages/IceCube/Contents.json
================================================
{
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: Ice/Assets.xcassets/ControlItemImages/IceCube/IceCubeFill.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "filename" : "IceCubeFill.png",
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  },
  "properties" : {
    "template-rendering-intent" : "template"
  }
}


================================================
FILE: Ice/Assets.xcassets/ControlItemImages/IceCube/IceCubeStroke.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "filename" : "IceCubeStroke.png",
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  },
  "properties" : {
    "template-rendering-intent" : "template"
  }
}


================================================
FILE: Ice/Assets.xcassets/DefaultLayoutBarColor.colorset/Contents.json
================================================
{
  "colors" : [
    {
      "color" : {
        "color-space" : "display-p3",
        "components" : {
          "alpha" : "0.170",
          "blue" : "0.000",
          "green" : "0.000",
          "red" : "0.000"
        }
      },
      "idiom" : "universal"
    },
    {
      "appearances" : [
        {
          "appearance" : "luminosity",
          "value" : "dark"
        }
      ],
      "color" : {
        "color-space" : "display-p3",
        "components" : {
          "alpha" : "0.070",
          "blue" : "1.000",
          "green" : "1.000",
          "red" : "1.000"
        }
      },
      "idiom" : "universal"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: Ice/Assets.xcassets/Warning.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "filename" : "Warning.png",
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: Ice/Bridging/Bridging.swift
================================================
//
//  Bridging.swift
//  Ice
//

import Cocoa

/// A namespace for bridged functionality.
enum Bridging { }

// MARK: - CGSConnection

extension Bridging {
    /// Sets a value for the given key in the current connection to the window server.
    ///
    /// - Parameters:
    ///   - value: The value to set for `key`.
    ///   - key: A key associated with the current connection to the window server.
    static func setConnectionProperty(_ value: Any?, forKey key: String) {
        let result = CGSSetConnectionProperty(
            CGSMainConnectionID(),
            CGSMainConnectionID(),
            key as CFString,
            value as CFTypeRef
        )
        if result != .success {
            Logger.bridging.error("CGSSetConnectionProperty failed with error \(result.logString)")
        }
    }

    /// Returns the value for the given key in the current connection to the window server.
    ///
    /// - Parameter key: A key associated with the current connection to the window server.
    /// - Returns: The value associated with `key` in the current connection to the window server.
    static func getConnectionProperty(forKey key: String) -> Any? {
        var value: Unmanaged<CFTypeRef>?
        let result = CGSCopyConnectionProperty(
            CGSMainConnectionID(),
            CGSMainConnectionID(),
            key as CFString,
            &value
        )
        if result != .success {
            Logger.bridging.error("CGSCopyConnectionProperty failed with error \(result.logString)")
        }
        return value?.takeRetainedValue()
    }
}

// MARK: - CGSWindow

extension Bridging {
    /// Returns the frame for the window with the specified identifier.
    ///
    /// - Parameter windowID: An identifier for a window.
    /// - Returns: The frame -- specified in screen coordinates -- of the window associated
    ///   with `windowID`, or `nil` if the operation failed.
    static func getWindowFrame(for windowID: CGWindowID) -> CGRect? {
        var rect = CGRect.zero
        let result = CGSGetScreenRectForWindow(CGSMainConnectionID(), windowID, &rect)
        guard result == .success else {
            Logger.bridging.error("CGSGetScreenRectForWindow failed with error \(result.logString)")
            return nil
        }
        return rect
    }
}

// MARK: Private Window List Helpers
extension Bridging {
    private static func getWindowCount() -> Int {
        var count: Int32 = 0
        let result = CGSGetWindowCount(CGSMainConnectionID(), 0, &count)
        if result != .success {
            Logger.bridging.error("CGSGetWindowCount failed with error \(result.logString)")
        }
        return Int(count)
    }

    private static func getOnScreenWindowCount() -> Int {
        var count: Int32 = 0
        let result = CGSGetOnScreenWindowCount(CGSMainConnectionID(), 0, &count)
        if result != .success {
            Logger.bridging.error("CGSGetOnScreenWindowCount failed with error \(result.logString)")
        }
        return Int(count)
    }

    private static func getWindowList() -> [CGWindowID] {
        let windowCount = getWindowCount()
        var list = [CGWindowID](repeating: 0, count: windowCount)
        var realCount: Int32 = 0
        let result = CGSGetWindowList(
            CGSMainConnectionID(),
            0,
            Int32(windowCount),
            &list,
            &realCount
        )
        guard result == .success else {
            Logger.bridging.error("CGSGetWindowList failed with error \(result.logString)")
            return []
        }
        return [CGWindowID](list[..<Int(realCount)])
    }

    private static func getOnScreenWindowList() -> [CGWindowID] {
        let windowCount = getOnScreenWindowCount()
        var list = [CGWindowID](repeating: 0, count: windowCount)
        var realCount: Int32 = 0
        let result = CGSGetOnScreenWindowList(
            CGSMainConnectionID(),
            0,
            Int32(windowCount),
            &list,
            &realCount
        )
        guard result == .success else {
            Logger.bridging.error("CGSGetOnScreenWindowList failed with error \(result.logString)")
            return []
        }
        return [CGWindowID](list[..<Int(realCount)])
    }

    private static func getMenuBarWindowList() -> [CGWindowID] {
        let windowCount = getWindowCount()
        var list = [CGWindowID](repeating: 0, count: windowCount)
        var realCount: Int32 = 0
        let result = CGSGetProcessMenuBarWindowList(
            CGSMainConnectionID(),
            0,
            Int32(windowCount),
            &list,
            &realCount
        )
        guard result == .success else {
            Logger.bridging.error("CGSGetProcessMenuBarWindowList failed with error \(result.logString)")
            return []
        }
        return [CGWindowID](list[..<Int(realCount)])
    }

    private static func getOnScreenMenuBarWindowList() -> [CGWindowID] {
        let onScreenList = Set(getOnScreenWindowList())
        return getMenuBarWindowList().filter(onScreenList.contains)
    }
}

// MARK: Public Window List API
extension Bridging {
    /// Options that determine the window identifiers to return in a window list.
    struct WindowListOption: OptionSet {
        let rawValue: Int

        /// Specifies windows that are currently on-screen.
        static let onScreen = WindowListOption(rawValue: 1 << 0)

        /// Specifies windows that represent items in the menu bar.
        static let menuBarItems = WindowListOption(rawValue: 1 << 1)

        /// Specifies windows on the currently active space.
        static let activeSpace = WindowListOption(rawValue: 1 << 2)
    }

    /// The total number of windows.
    static var windowCount: Int {
        getWindowCount()
    }

    /// The number of windows currently on-screen.
    static var onScreenWindowCount: Int {
        getOnScreenWindowCount()
    }

    /// Returns a list of window identifiers using the given options.
    ///
    /// - Parameter option: Options that filter the returned list.
    static func getWindowList(option: WindowListOption = []) -> [CGWindowID] {
        let list = if option.contains(.menuBarItems) {
            if option.contains(.onScreen) {
                getOnScreenMenuBarWindowList()
            } else {
                getMenuBarWindowList()
            }
        } else if option.contains(.onScreen) {
            getOnScreenWindowList()
        } else {
            getWindowList()
        }
        return if option.contains(.activeSpace) {
            list.filter(isWindowOnActiveSpace)
        } else {
            list
        }
    }
}

// MARK: - CGSSpace

extension Bridging {
    /// Options that determine the space identifiers to return in a space list.
    enum SpaceListOption {
        case allSpaces, visibleSpaces
    }

    /// The identifier of the active space.
    static var activeSpaceID: CGSSpaceID {
        CGSGetActiveSpace(CGSMainConnectionID())
    }

    /// Returns an array of identifiers for the spaces containing the window with
    /// the given identifier.
    ///
    /// - Parameter windowID: An identifier for a window.
    static func getSpaceList(for windowID: CGWindowID, option: SpaceListOption) -> [CGSSpaceID] {
        let mask: CGSSpaceMask = switch option {
        case .allSpaces: .allSpaces
        case .visibleSpaces: .allVisibleSpaces
        }
        guard let spaces = CGSCopySpacesForWindows(CGSMainConnectionID(), mask, [windowID] as CFArray) else {
            Logger.bridging.error("CGSCopySpacesForWindows failed")
            return []
        }
        guard let spaceIDs = spaces.takeRetainedValue() as? [CGSSpaceID] else {
            Logger.bridging.error("CGSCopySpacesForWindows returned array of unexpected type")
            return []
        }
        return spaceIDs
    }

    /// Returns a Boolean value that indicates whether the window with the
    /// given identifier is on the active space.
    ///
    /// - Parameter windowID: An identifier for a window.
    static func isWindowOnActiveSpace(_ windowID: CGWindowID) -> Bool {
        getSpaceList(for: windowID, option: .allSpaces).contains(activeSpaceID)
    }

    /// Returns a Boolean value that indicates whether the space with the given
    /// identifier is a fullscreen space.
    ///
    /// - Parameter spaceID: An identifier for a space.
    static func isSpaceFullscreen(_ spaceID: CGSSpaceID) -> Bool {
        let type = CGSSpaceGetType(CGSMainConnectionID(), spaceID)
        return type == .fullscreen
    }
}

// MARK: - Process Responsivity

extension Bridging {
    /// Constants that indicate the responsivity of an app.
    enum Responsivity {
        case responsive, unresponsive, unknown
    }

    /// Returns the responsivity of the given process.
    ///
    /// - Parameter pid: The Unix process identifier of the process to check.
    static func responsivity(for pid: pid_t) -> Responsivity {
        var psn = ProcessSerialNumber()
        let result = GetProcessForPID(pid, &psn)
        guard result == noErr else {
            Logger.bridging.error("GetProcessForPID failed with error \(result)")
            return .unknown
        }
        if CGSEventIsAppUnresponsive(CGSMainConnectionID(), &psn) {
            return .unresponsive
        }
        return .responsive
    }
}

// MARK: - Logger
private extension Logger {
    static let bridging = Logger(category: "Bridging")
}


================================================
FILE: Ice/Bridging/Shims/Deprecated.swift
================================================
//
//  Deprecated.swift
//  Ice
//

import ApplicationServices

/// Returns a PSN for a given PID.
@_silgen_name("GetProcessForPID")
func GetProcessForPID(
    _ pid: pid_t,
    _ psn: inout ProcessSerialNumber
) -> OSStatus


================================================
FILE: Ice/Bridging/Shims/Private.swift
================================================
//
//  Private.swift
//  Ice
//

import CoreGraphics

// MARK: - Bridged Types

typealias CGSConnectionID = Int32
typealias CGSSpaceID = size_t

enum CGSSpaceType: UInt32 {
    case user = 0
    case system = 2
    case fullscreen = 4
}

struct CGSSpaceMask: OptionSet {
    let rawValue: UInt32

    static let includesCurrent = CGSSpaceMask(rawValue: 1 << 0)
    static let includesOthers = CGSSpaceMask(rawValue: 1 << 1)
    static let includesUser = CGSSpaceMask(rawValue: 1 << 2)

    static let includesVisible = CGSSpaceMask(rawValue: 1 << 16)

    static let currentSpace: CGSSpaceMask = [.includesUser, .includesCurrent]
    static let otherSpaces: CGSSpaceMask = [.includesOthers, .includesCurrent]
    static let allSpaces: CGSSpaceMask = [.includesUser, .includesOthers, .includesCurrent]
    static let allVisibleSpaces: CGSSpaceMask = [.includesVisible, .allSpaces]
}

// MARK: - CGSConnection Functions

@_silgen_name("CGSMainConnectionID")
func CGSMainConnectionID() -> CGSConnectionID

@_silgen_name("CGSCopyConnectionProperty")
func CGSCopyConnectionProperty(
    _ cid: CGSConnectionID,
    _ targetCID: CGSConnectionID,
    _ key: CFString,
    _ outValue: inout Unmanaged<CFTypeRef>?
) -> CGError

@_silgen_name("CGSSetConnectionProperty")
func CGSSetConnectionProperty(
    _ cid: CGSConnectionID,
    _ targetCID: CGSConnectionID,
    _ key: CFString,
    _ value: CFTypeRef
) -> CGError

// MARK: - CGSEvent Functions

@_silgen_name("CGSEventIsAppUnresponsive")
func CGSEventIsAppUnresponsive(
    _ cid: CGSConnectionID,
    _ psn: inout ProcessSerialNumber
) -> Bool

// MARK: - CGSSpace Functions

@_silgen_name("CGSGetActiveSpace")
func CGSGetActiveSpace(_ cid: CGSConnectionID) -> CGSSpaceID

@_silgen_name("CGSCopySpacesForWindows")
func CGSCopySpacesForWindows(
    _ cid: CGSConnectionID,
    _ mask: CGSSpaceMask,
    _ windowIDs: CFArray
) -> Unmanaged<CFArray>?

@_silgen_name("CGSSpaceGetType")
func CGSSpaceGetType(
    _ cid: CGSConnectionID,
    _ sid: CGSSpaceID
) -> CGSSpaceType

// MARK: - CGSWindow Functions

@_silgen_name("CGSGetWindowList")
func CGSGetWindowList(
    _ cid: CGSConnectionID,
    _ targetCID: CGSConnectionID,
    _ count: Int32,
    _ list: UnsafeMutablePointer<CGWindowID>,
    _ outCount: inout Int32
) -> CGError

@_silgen_name("CGSGetOnScreenWindowList")
func CGSGetOnScreenWindowList(
    _ cid: CGSConnectionID,
    _ targetCID: CGSConnectionID,
    _ count: Int32,
    _ list: UnsafeMutablePointer<CGWindowID>,
    _ outCount: inout Int32
) -> CGError

@_silgen_name("CGSGetProcessMenuBarWindowList")
func CGSGetProcessMenuBarWindowList(
    _ cid: CGSConnectionID,
    _ targetCID: CGSConnectionID,
    _ count: Int32,
    _ list: UnsafeMutablePointer<CGWindowID>,
    _ outCount: inout Int32
) -> CGError

@_silgen_name("CGSGetWindowCount")
func CGSGetWindowCount(
    _ cid: CGSConnectionID,
    _ targetCID: CGSConnectionID,
    _ outCount: inout Int32
) -> CGError

@_silgen_name("CGSGetOnScreenWindowCount")
func CGSGetOnScreenWindowCount(
    _ cid: CGSConnectionID,
    _ targetCID: CGSConnectionID,
    _ outCount: inout Int32
) -> CGError

@_silgen_name("CGSGetScreenRectForWindow")
func CGSGetScreenRectForWindow(
    _ cid: CGSConnectionID,
    _ wid: CGWindowID,
    _ outRect: inout CGRect
) -> CGError


================================================
FILE: Ice/Events/EventManager.swift
================================================
//
//  EventManager.swift
//  Ice
//

import Cocoa
import Combine

/// Manager for the various event monitors maintained by the app.
@MainActor
final class EventManager {
    /// The shared app state.
    private weak var appState: AppState?

    /// Storage for internal observers.
    private var cancellables = Set<AnyCancellable>()

    // MARK: Monitors

    /// Monitor for mouse down events.
    private(set) lazy var mouseDownMonitor = UniversalEventMonitor(
        mask: [.leftMouseDown, .rightMouseDown]
    ) { [weak self] event in
        guard let self else {
            return event
        }
        switch event.type {
        case .leftMouseDown:
            handleShowOnClick()
            handleSmartRehide(with: event)
        case .rightMouseDown:
            handleShowRightClickMenu()
        default:
            break
        }
        handlePreventShowOnHover(with: event)
        return event
    }

    /// Monitor for mouse up events.
    private(set) lazy var mouseUpMonitor = UniversalEventMonitor(
        mask: .leftMouseUp
    ) { [weak self] event in
        self?.handleLeftMouseUp()
        return event
    }

    /// Monitor for mouse dragged events.
    private(set) lazy var mouseDraggedMonitor = UniversalEventMonitor(
        mask: .leftMouseDragged
    ) { [weak self] event in
        self?.handleLeftMouseDragged(with: event)
        return event
    }

    /// Monitor for mouse moved events.
    private(set) lazy var mouseMovedMonitor = UniversalEventMonitor(
        mask: .mouseMoved
    ) { [weak self] event in
        self?.handleShowOnHover()
        return event
    }

    /// Monitor for scroll wheel events.
    private(set) lazy var scrollWheelMonitor = UniversalEventMonitor(
        mask: .scrollWheel
    ) { [weak self] event in
        self?.handleShowOnScroll(with: event)
        return event
    }

    // MARK: All Monitors

    /// All monitors maintained by the app.
    private lazy var allMonitors = [
        mouseDownMonitor,
        mouseUpMonitor,
        mouseDraggedMonitor,
        mouseMovedMonitor,
        scrollWheelMonitor,
    ]

    // MARK: Initializers

    /// Creates an event manager with the given app state.
    init(appState: AppState) {
        self.appState = appState
    }

    /// Sets up the manager.
    func performSetup() {
        startAll()
        configureCancellables()
    }

    /// Configures the internal observers for the manager.
    private func configureCancellables() {
        var c = Set<AnyCancellable>()

        if let appState {
            if let hiddenSection = appState.menuBarManager.section(withName: .hidden) {
                // In fullscreen mode, the menu bar slides down from the top on hover. Observe
                // the frame of the hidden section's control item, which we know will always be
                // in the menu bar, and run the show-on-hover check when it changes.
                Publishers.CombineLatest(
                    hiddenSection.controlItem.$windowFrame,
                    appState.$isActiveSpaceFullscreen
                )
                .sink { [weak self] _, isFullscreen in
                    guard
                        let self,
                        isFullscreen
                    else {
                        return
                    }
                    handleShowOnHover()
                }
                .store(in: &c)
            }
        }

        cancellables = c
    }

    // MARK: Start/Stop

    /// Starts all monitors.
    func startAll() {
        for monitor in allMonitors {
            monitor.start()
        }
    }

    /// Stops all monitors.
    func stopAll() {
        for monitor in allMonitors {
            monitor.stop()
        }
    }
}

// MARK: - Handlers

extension EventManager {

    // MARK: Handle Show On Click

    private func handleShowOnClick() {
        guard
            let appState,
            appState.settingsManager.generalSettingsManager.showOnClick,
            isMouseInsideEmptyMenuBarSpace
        else {
            return
        }

        Task {
            // Short delay helps the toggle action feel more natural.
            try? await Task.sleep(for: .milliseconds(50))

            if NSEvent.modifierFlags == .control {
                handleShowRightClickMenu()
            } else if
                NSEvent.modifierFlags == .option,
                appState.settingsManager.advancedSettingsManager.canToggleAlwaysHiddenSection
            {
                if let alwaysHiddenSection = appState.menuBarManager.section(withName: .alwaysHidden) {
                    alwaysHiddenSection.toggle()
                }
            } else {
                if let hiddenSection = appState.menuBarManager.section(withName: .hidden) {
                    hiddenSection.toggle()
                }
            }
        }
    }

    // MARK: Handle Smart Rehide

    private func handleSmartRehide(with event: NSEvent) {
        guard
            let appState,
            appState.settingsManager.generalSettingsManager.autoRehide,
            case .smart = appState.settingsManager.generalSettingsManager.rehideStrategy
        else {
            return
        }

        if let visibleSection = appState.menuBarManager.section(withName: .visible) {
            guard event.window !== visibleSection.controlItem.window else {
                return
            }
        }

        // Make sure clicking the Ice Bar doesn't trigger rehide.
        guard event.window !== appState.menuBarManager.iceBarPanel else {
            return
        }

        // Only continue if a section is currently visible.
        guard appState.menuBarManager.sections.contains(where: { !$0.isHidden }) else {
            return
        }

        // Make sure the mouse is not in the menu bar.
        guard !isMouseInsideMenuBar else {
            return
        }

        Task {
            let initialSpaceID = Bridging.activeSpaceID

            // Sleep for a bit to give the window under the mouse a chance to focus.
            try? await Task.sleep(for: .seconds(0.25))

            // If clicking caused a space change, don't bother with the window check.
            if Bridging.activeSpaceID != initialSpaceID {
                for section in appState.menuBarManager.sections {
                    section.hide()
                }
                return
            }

            // Get the window that the user has clicked into.
            guard
                let mouseLocation = MouseCursor.locationCoreGraphics,
                let windowUnderMouse = WindowInfo.getOnScreenWindows(excludeDesktopWindows: false)
                    .filter({ $0.layer < CGWindowLevelForKey(.cursorWindow) })
                    .first(where: { $0.frame.contains(mouseLocation) && $0.title?.isEmpty == false }),
                let owningApplication = windowUnderMouse.owningApplication
            else {
                return
            }

            // The dock is an exception to the following check.
            if owningApplication.bundleIdentifier != "com.apple.dock" {
                // Only continue if the user has clicked into an active window with
                // a regular activation policy.
                guard
                    owningApplication.isActive,
                    owningApplication.activationPolicy == .regular
                else {
                    return
                }
            }

            // If all the above checks have passed, hide all sections.
            for section in appState.menuBarManager.sections {
                section.hide()
            }
        }
    }

    // MARK: Handle Show Right Click Menu

    private func handleShowRightClickMenu() {
        guard
            let appState,
            appState.settingsManager.advancedSettingsManager.showContextMenuOnRightClick,
            isMouseInsideEmptyMenuBarSpace,
            let mouseLocation = MouseCursor.locationAppKit
        else {
            return
        }
        appState.menuBarManager.showRightClickMenu(at: mouseLocation)
    }

    // MARK: Handle Prevent Show On Hover

    private func handlePreventShowOnHover(with event: NSEvent) {
        guard
            let appState,
            appState.settingsManager.generalSettingsManager.showOnHover,
            !appState.settingsManager.generalSettingsManager.useIceBar,
            isMouseInsideMenuBar
        else {
            return
        }

        if isMouseInsideMenuBarItem {
            switch event.type {
            case .leftMouseDown:
                if appState.menuBarManager.sections.contains(where: { !$0.isHidden }) || isMouseInsideIceIcon {
                    // We have a left click that is inside the menu bar while at least one
                    // section is visible or the mouse is inside the Ice icon.
                    appState.preventShowOnHover()
                }
            case .rightMouseDown:
                if appState.menuBarManager.sections.contains(where: { !$0.isHidden }) {
                    // We have a right click that is inside the menu bar while at least one
                    // section is visible.
                    appState.preventShowOnHover()
                }
            default:
                break
            }
        } else if !isMouseInsideApplicationMenu {
            // We have a left or right click that is inside the menu bar, outside
            // a menu bar item, and outside the application menu, so it _must_ be
            // inside an empty menu bar space.
            appState.preventShowOnHover()
        }
    }

    // MARK: Handle Left Mouse Up

    private func handleLeftMouseUp() {
        guard let appearanceManager = appState?.appearanceManager else {
            return
        }
        appearanceManager.setIsDraggingMenuBarItem(false)
    }

    // MARK: Handle Left Mouse Dragged

    private func handleLeftMouseDragged(with event: NSEvent) {
        guard
            let appState,
            event.modifierFlags.contains(.command),
            isMouseInsideMenuBar
        else {
            return
        }

        // Notify each overlay panel that a menu bar item is being dragged.
        appState.appearanceManager.setIsDraggingMenuBarItem(true)

        // Don't continue if the setting to show the sections is disabled.
        guard appState.settingsManager.advancedSettingsManager.showAllSectionsOnUserDrag else {
            return
        }

        // Show all items, including section dividers.
        for section in appState.menuBarManager.sections {
            section.controlItem.state = .showItems
            guard
                section.controlItem.isSectionDivider,
                !section.controlItem.isVisible
            else {
                continue
            }
            section.controlItem.isVisible = true
        }
    }

    // MARK: Handle Show On Hover

    private func handleShowOnHover() {
        guard let appState else {
            return
        }

        // Make sure the "ShowOnHover" feature is enabled and not prevented.
        guard
            appState.settingsManager.generalSettingsManager.showOnHover,
            !appState.isShowOnHoverPrevented
        else {
            return
        }

        // Only continue if we have a hidden section (we should).
        guard let hiddenSection = appState.menuBarManager.section(withName: .hidden) else {
            return
        }

        let delay = appState.settingsManager.advancedSettingsManager.showOnHoverDelay

        Task {
            if hiddenSection.isHidden {
                guard self.isMouseInsideEmptyMenuBarSpace else {
                    return
                }
                try? await Task.sleep(for: .seconds(delay))
                // Make sure the mouse is still inside.
                guard self.isMouseInsideEmptyMenuBarSpace else {
                    return
                }
                hiddenSection.show()
            } else {
                guard
                    !self.isMouseInsideMenuBar,
                    !self.isMouseInsideIceBar
                else {
                    return
                }
                try? await Task.sleep(for: .seconds(delay))
                // Make sure the mouse is still outside.
                guard
                    !self.isMouseInsideMenuBar,
                    !self.isMouseInsideIceBar
                else {
                    return
                }
                hiddenSection.hide()
            }
        }
    }

    // MARK: Handle Show On Scroll

    private func handleShowOnScroll(with event: NSEvent) {
        guard let appState else {
            return
        }

        // Make sure the "ShowOnScroll" feature is enabled.
        guard appState.settingsManager.generalSettingsManager.showOnScroll else {
            return
        }

        // Make sure the mouse is inside the menu bar.
        guard isMouseInsideMenuBar else {
            return
        }

        // Only continue if we have a hidden section (we should).
        guard let hiddenSection = appState.menuBarManager.section(withName: .hidden) else {
            return
        }

        let averageDelta = (event.scrollingDeltaX + event.scrollingDeltaY) / 2

        if averageDelta > 5 {
            hiddenSection.show()
        } else if averageDelta < -5 {
            hiddenSection.hide()
        }
    }
}

// MARK: - Helpers

extension EventManager {
    /// Returns the best screen to use for event manager calculations.
    var bestScreen: NSScreen? {
        guard let appState else {
            return nil
        }
        if appState.isActiveSpaceFullscreen {
            return NSScreen.screenWithMouse ?? NSScreen.main
        } else {
            return NSScreen.main
        }
    }

    /// A Boolean value that indicates whether the mouse pointer is within
    /// the bounds of the menu bar.
    var isMouseInsideMenuBar: Bool {
        guard
            let screen = bestScreen,
            let appState
        else {
            return false
        }
        if appState.menuBarManager.isMenuBarHiddenBySystem || appState.isActiveSpaceFullscreen {
            if
                let mouseLocation = MouseCursor.locationCoreGraphics,
                let menuBarWindow = WindowInfo.getMenuBarWindow(for: screen.displayID)
            {
                return menuBarWindow.frame.contains(mouseLocation)
            }
        } else if let mouseLocation = MouseCursor.locationAppKit {
            return mouseLocation.y > screen.visibleFrame.maxY && mouseLocation.y <= screen.frame.maxY
        }
        return false
    }

    /// A Boolean value that indicates whether the mouse pointer is within
    /// the bounds of the current application menu.
    var isMouseInsideApplicationMenu: Bool {
        guard
            let mouseLocation = MouseCursor.locationCoreGraphics,
            let screen = bestScreen,
            let appState,
            var applicationMenuFrame = appState.menuBarManager.getApplicationMenuFrame(for: screen.displayID)
        else {
            return false
        }
        applicationMenuFrame.size.width += applicationMenuFrame.origin.x - screen.frame.origin.x
        applicationMenuFrame.origin.x = screen.frame.origin.x
        return applicationMenuFrame.contains(mouseLocation)
    }

    /// A Boolean value that indicates whether the mouse pointer is within
    /// the bounds of a menu bar item.
    var isMouseInsideMenuBarItem: Bool {
        guard
            let screen = bestScreen,
            let mouseLocation = MouseCursor.locationCoreGraphics
        else {
            return false
        }
        let menuBarItems = MenuBarItem.getMenuBarItems(on: screen.displayID, onScreenOnly: true, activeSpaceOnly: true)
        return menuBarItems.contains { $0.frame.contains(mouseLocation) }
    }

    /// A Boolean value that indicates whether the mouse pointer is within
    /// the bounds of the screen's notch, if it has one.
    ///
    /// If the screen returned from ``bestScreen`` does not have a notch,
    /// this property returns `false`.
    var isMouseInsideNotch: Bool {
        guard
            let screen = bestScreen,
            let mouseLocation = MouseCursor.locationAppKit,
            let frameOfNotch = screen.frameOfNotch
        else {
            return false
        }
        return frameOfNotch.contains(mouseLocation)
    }

    /// A Boolean value that indicates whether the mouse pointer is within
    /// the bounds of an empty space in the menu bar.
    var isMouseInsideEmptyMenuBarSpace: Bool {
        isMouseInsideMenuBar &&
        !isMouseInsideApplicationMenu &&
        !isMouseInsideMenuBarItem &&
        !isMouseInsideNotch
    }

    /// A Boolean value that indicates whether the mouse pointer is within
    /// the bounds of the Ice Bar panel.
    var isMouseInsideIceBar: Bool {
        guard
            let appState,
            let mouseLocation = MouseCursor.locationAppKit
        else {
            return false
        }
        let panel = appState.menuBarManager.iceBarPanel
        // Pad the frame to be more forgiving if the user accidentally
        // moves their mouse outside of the Ice Bar.
        let paddedFrame = panel.frame.insetBy(dx: -10, dy: -10)
        return paddedFrame.contains(mouseLocation)
    }

    /// A Boolean value that indicates whether the mouse pointer is within
    /// the bounds of the Ice icon.
    var isMouseInsideIceIcon: Bool {
        guard
            let appState,
            let visibleSection = appState.menuBarManager.section(withName: .visible),
            let iceIconFrame = visibleSection.controlItem.windowFrame,
            let mouseLocation = MouseCursor.locationAppKit
        else {
            return false
        }
        return iceIconFrame.contains(mouseLocation)
    }
}

// MARK: - Logger
private extension Logger {
    static let eventManager = Logger(category: "EventManager")
}


================================================
FILE: Ice/Events/EventMonitors/GlobalEventMonitor.swift
================================================
//
//  GlobalEventMonitor.swift
//  Ice
//

import Cocoa
import Combine

/// A type that monitors for events outside the scope of the current process.
final class GlobalEventMonitor {
    private let mask: NSEvent.EventTypeMask
    private let handler: (NSEvent) -> Void
    private var monitor: Any?

    /// Creates an event monitor with the given event type mask and handler.
    ///
    /// - Parameters:
    ///   - mask: An event type mask specifying which events to monitor.
    ///   - handler: A handler to execute when the event monitor receives
    ///     an event corresponding to the event types in `mask`.
    init(mask: NSEvent.EventTypeMask, handler: @escaping (_ event: NSEvent) -> Void) {
        self.mask = mask
        self.handler = handler
    }

    deinit {
        stop()
    }

    /// Starts monitoring for events.
    func start() {
        guard monitor == nil else {
            return
        }
        monitor = NSEvent.addGlobalMonitorForEvents(
            matching: mask,
            handler: handler
        )
    }

    /// Stops monitoring for events.
    func stop() {
        guard let monitor else {
            return
        }
        NSEvent.removeMonitor(monitor)
        self.monitor = nil
    }
}

extension GlobalEventMonitor {
    /// A publisher that emits global events for an event type mask.
    struct GlobalEventPublisher: Publisher {
        typealias Output = NSEvent
        typealias Failure = Never

        let mask: NSEvent.EventTypeMask

        func receive<S: Subscriber<Output, Failure>>(subscriber: S) {
            let subscription = GlobalEventSubscription(mask: mask, subscriber: subscriber)
            subscriber.receive(subscription: subscription)
        }
    }

    /// Returns a publisher that emits global events for the given event type mask.
    ///
    /// - Parameter mask: An event type mask specifying which events to publish.
    static func publisher(for mask: NSEvent.EventTypeMask) -> GlobalEventPublisher {
        GlobalEventPublisher(mask: mask)
    }
}

extension GlobalEventMonitor.GlobalEventPublisher {
    private final class GlobalEventSubscription<S: Subscriber<Output, Failure>>: Subscription {
        var subscriber: S?
        let monitor: GlobalEventMonitor

        init(mask: NSEvent.EventTypeMask, subscriber: S) {
            self.subscriber = subscriber
            self.monitor = GlobalEventMonitor(mask: mask) { event in
                _ = subscriber.receive(event)
            }
            monitor.start()
        }

        func request(_ demand: Subscribers.Demand) { }

        func cancel() {
            monitor.stop()
            subscriber = nil
        }
    }
}


================================================
FILE: Ice/Events/EventMonitors/LocalEventMonitor.swift
================================================
//
//  LocalEventMonitor.swift
//  Ice
//

import Cocoa
import Combine

/// A type that monitors for events within the scope of the current process.
final class LocalEventMonitor {
    private let mask: NSEvent.EventTypeMask
    private let handler: (NSEvent) -> NSEvent?
    private var monitor: Any?

    /// Creates an event monitor with the given event type mask and handler.
    ///
    /// - Parameters:
    ///   - mask: An event type mask specifying which events to monitor.
    ///   - handler: A handler to execute when the event monitor receives
    ///     an event corresponding to the event types in `mask`.
    init(mask: NSEvent.EventTypeMask, handler: @escaping (_ event: NSEvent) -> NSEvent?) {
        self.mask = mask
        self.handler = handler
    }

    deinit {
        stop()
    }

    /// Starts monitoring for events.
    func start() {
        guard monitor == nil else {
            return
        }
        monitor = NSEvent.addLocalMonitorForEvents(
            matching: mask,
            handler: handler
        )
    }

    /// Stops monitoring for events.
    func stop() {
        guard let monitor else {
            return
        }
        NSEvent.removeMonitor(monitor)
        self.monitor = nil
    }
}

extension LocalEventMonitor {
    /// A publisher that emits local events for an event type mask.
    struct LocalEventPublisher: Publisher {
        typealias Output = NSEvent
        typealias Failure = Never

        let mask: NSEvent.EventTypeMask

        func receive<S: Subscriber<Output, Failure>>(subscriber: S) {
            let subscription = LocalEventSubscription(mask: mask, subscriber: subscriber)
            subscriber.receive(subscription: subscription)
        }
    }

    /// Returns a publisher that emits local events for the given event type mask.
    ///
    /// - Parameter mask: An event type mask specifying which events to publish.
    static func publisher(for mask: NSEvent.EventTypeMask) -> LocalEventPublisher {
        LocalEventPublisher(mask: mask)
    }
}

extension LocalEventMonitor.LocalEventPublisher {
    private final class LocalEventSubscription<S: Subscriber<Output, Failure>>: Subscription {
        var subscriber: S?
        let monitor: LocalEventMonitor

        init(mask: NSEvent.EventTypeMask, subscriber: S) {
            self.subscriber = subscriber
            self.monitor = LocalEventMonitor(mask: mask) { event in
                _ = subscriber.receive(event)
                return event
            }
            monitor.start()
        }

        func request(_ demand: Subscribers.Demand) { }

        func cancel() {
            monitor.stop()
            subscriber = nil
        }
    }
}


================================================
FILE: Ice/Events/EventMonitors/RunLoopLocalEventMonitor.swift
================================================
//
//  RunLoopLocalEventMonitor.swift
//  Ice
//

import Cocoa
import Combine

final class RunLoopLocalEventMonitor {
    private let runLoop = CFRunLoopGetCurrent()
    private let mode: RunLoop.Mode
    private let handler: (NSEvent) -> NSEvent?
    private let observer: CFRunLoopObserver

    /// Creates an event monitor with the given event type mask and handler.
    ///
    /// - Parameters:
    ///   - mask: An event type mask specifying which events to monitor.
    ///   - handler: A handler to execute when the event monitor receives
    ///     an event corresponding to the event types in `mask`.
    init(
        mask: NSEvent.EventTypeMask,
        mode: RunLoop.Mode,
        handler: @escaping (_ event: NSEvent) -> NSEvent?
    ) {
        self.mode = mode
        self.handler = handler
        self.observer = CFRunLoopObserverCreateWithHandler(
            kCFAllocatorDefault,
            CFRunLoopActivity.beforeSources.rawValue,
            true,
            0
        ) { _, _ in
            var events = [NSEvent]()

            while let event = NSApp.nextEvent(matching: .any, until: nil, inMode: .default, dequeue: true) {
                events.append(event)
            }

            for event in events {
                var handledEvent: NSEvent?

                if !mask.contains(NSEvent.EventTypeMask(rawValue: 1 << event.type.rawValue)) {
                    handledEvent = event
                } else if let eventFromHandler = handler(event) {
                    handledEvent = eventFromHandler
                }

                guard let handledEvent else {
                    continue
                }

                NSApp.postEvent(handledEvent, atStart: false)
            }
        }
    }

    deinit {
        stop()
    }

    func start() {
        CFRunLoopAddObserver(
            runLoop,
            observer,
            CFRunLoopMode(mode.rawValue as CFString)
        )
    }

    func stop() {
        CFRunLoopRemoveObserver(
            runLoop,
            observer,
            CFRunLoopMode(mode.rawValue as CFString)
        )
    }
}

extension RunLoopLocalEventMonitor {
    /// A publisher that emits local events for an event type mask.
    struct RunLoopLocalEventPublisher: Publisher {
        typealias Output = NSEvent
        typealias Failure = Never

        let mask: NSEvent.EventTypeMask
        let mode: RunLoop.Mode

        func receive<S: Subscriber<Output, Failure>>(subscriber: S) {
            let subscription = RunLoopLocalEventSubscription(mask: mask, mode: mode, subscriber: subscriber)
            subscriber.receive(subscription: subscription)
        }
    }

    /// Returns a publisher that emits local events for the given event type mask.
    ///
    /// - Parameter mask: An event type mask specifying which events to publish.
    static func publisher(for mask: NSEvent.EventTypeMask, mode: RunLoop.Mode) -> RunLoopLocalEventPublisher {
        RunLoopLocalEventPublisher(mask: mask, mode: mode)
    }
}

extension RunLoopLocalEventMonitor.RunLoopLocalEventPublisher {
    private final class RunLoopLocalEventSubscription<S: Subscriber<Output, Failure>>: Subscription {
        var subscriber: S?
        let monitor: RunLoopLocalEventMonitor

        init(mask: NSEvent.EventTypeMask, mode: RunLoop.Mode, subscriber: S) {
            self.subscriber = subscriber
            self.monitor = RunLoopLocalEventMonitor(mask: mask, mode: mode) { event in
                _ = subscriber.receive(event)
                return event
            }
            monitor.start()
        }

        func request(_ demand: Subscribers.Demand) { }

        func cancel() {
            monitor.stop()
            subscriber = nil
        }
    }
}


================================================
FILE: Ice/Events/EventMonitors/UniversalEventMonitor.swift
================================================
//
//  UniversalEventMonitor.swift
//  Ice
//

import Cocoa
import Combine

/// A type that monitors for local and global events.
final class UniversalEventMonitor {
    private let local: LocalEventMonitor
    private let global: GlobalEventMonitor

    /// Creates an event monitor with the given event type mask and handler.
    ///
    /// - Parameters:
    ///   - mask: An event type mask specifying which events to monitor.
    ///   - handler: A handler to execute when the event monitor receives
    ///     an event corresponding to the event types in `mask`.
    init(mask: NSEvent.EventTypeMask, handler: @escaping (_ event: NSEvent) -> NSEvent?) {
        self.local = LocalEventMonitor(mask: mask, handler: handler)
        self.global = GlobalEventMonitor(mask: mask, handler: { _ = handler($0) })
    }

    deinit {
        stop()
    }

    /// Starts monitoring for events.
    func start() {
        local.start()
        global.start()
    }

    /// Stops monitoring for events.
    func stop() {
        local.stop()
        global.stop()
    }
}

extension UniversalEventMonitor {
    /// A publisher that emits local and global events for an event type mask.
    struct UniversalEventPublisher: Publisher {
        typealias Output = NSEvent
        typealias Failure = Never

        let mask: NSEvent.EventTypeMask

        func receive<S: Subscriber<Output, Failure>>(subscriber: S) {
            let subscription = UniversalEventSubscription(mask: mask, subscriber: subscriber)
            subscriber.receive(subscription: subscription)
        }
    }

    /// Returns a publisher that emits local and global events for the given
    /// event type mask.
    ///
    /// - Parameter mask: An event type mask specifying which events to publish.
    static func publisher(for mask: NSEvent.EventTypeMask) -> UniversalEventPublisher {
        UniversalEventPublisher(mask: mask)
    }
}

extension UniversalEventMonitor.UniversalEventPublisher {
    private final class UniversalEventSubscription<S: Subscriber<Output, Failure>>: Subscription {
        var subscriber: S?
        let monitor: UniversalEventMonitor

        init(mask: NSEvent.EventTypeMask, subscriber: S) {
            self.subscriber = subscriber
            self.monitor = UniversalEventMonitor(mask: mask) { event in
                _ = subscriber.receive(event)
                return event
            }
            monitor.start()
        }

        func request(_ demand: Subscribers.Demand) { }

        func cancel() {
            monitor.stop()
            subscriber = nil
        }
    }
}


================================================
FILE: Ice/Events/EventTap.swift
================================================
//
//  EventTap.swift
//  Ice
//

import Cocoa

/// A type that receives system events from various locations within the
/// event stream.
@MainActor
final class EventTap {
    /// Constants that specify the possible tapping locations for events.
    enum Location {
        /// The location where HID system events enter the window server.
        case hidEventTap

        /// The location where HID system and remote control events enter
        /// a login session.
        case sessionEventTap

        /// The location where session events have been annotated to flow
        /// to an application.
        case annotatedSessionEventTap

        /// The location where annotated events are delivered to a specific
        /// process.
        case pid(pid_t)

        var logString: String {
            switch self {
            case .hidEventTap: "HID event tap"
            case .sessionEventTap: "session event tap"
            case .annotatedSessionEventTap: "annotated session event tap"
            case .pid(let pid): "PID \(pid)"
            }
        }
    }

    /// A proxy for an event tap.
    ///
    /// Event tap proxies are passed to an event tap's callback, and can be
    /// used to post additional events to the tap before the callback returns
    /// or to disable the tap from within the callback.
    @MainActor
    struct Proxy {
        private let tap: EventTap
        private let pointer: CGEventTapProxy

        /// The label associated with the event tap.
        var label: String {
            tap.label
        }

        /// A Boolean value that indicates whether the event tap is enabled.
        var isEnabled: Bool {
            tap.isEnabled
        }

        fileprivate init(tap: EventTap, pointer: CGEventTapProxy) {
            self.tap = tap
            self.pointer = pointer
        }

        /// Posts an event into the event stream from the location of this tap.
        func postEvent(_ event: CGEvent) {
            event.tapPostEvent(pointer)
        }

        /// Enables the event tap.
        func enable() {
            tap.enable()
        }

        /// Enables the event tap with the given timeout.
        func enable(timeout: Duration, onTimeout: @escaping () -> Void) {
            tap.enable(timeout: timeout, onTimeout: onTimeout)
        }

        /// Disables the event tap.
        func disable() {
            tap.disable()
        }
    }

    private let runLoop = CFRunLoopGetCurrent()
    private let mode: CFRunLoopMode = .commonModes
    private nonisolated let callback: (EventTap, CGEventTapProxy, CGEventType, CGEvent) -> Unmanaged<CGEvent>?

    private var machPort: CFMachPort?
    private var source: CFRunLoopSource?

    /// The label associated with the event tap.
    let label: String

    /// A Boolean value that indicates whether the event tap is enabled.
    var isEnabled: Bool {
        guard let machPort else {
            return false
        }
        return CGEvent.tapIsEnabled(tap: machPort)
    }

    /// Creates a new event tap.
    ///
    /// - Parameters:
    ///   - label: The label associated with the tap.
    ///   - kind: The kind of tap to create.
    ///   - location: The location to listen for events.
    ///   - placement: The placement of the tap relative to other active taps.
    ///   - types: The event types to listen for.
    ///   - callback: A callback function to perform when the tap receives events.
    init(
        label: String = #function,
        options: CGEventTapOptions,
        location: Location,
        place: CGEventTapPlacement,
        types: [CGEventType],
        callback: @MainActor @escaping (_ proxy: Proxy, _ type: CGEventType, _ event: CGEvent) -> CGEvent?
    ) {
        self.label = label
        self.callback = { @MainActor tap, pointer, type, event in
            callback(Proxy(tap: tap, pointer: pointer), type, event).map(Unmanaged.passUnretained)
        }
        guard let machPort = Self.createTapMachPort(
            location: location,
            place: place,
            options: options,
            eventsOfInterest: types.reduce(into: 0) { $0 |= 1 << $1.rawValue },
            callback: handleEvent,
            userInfo: Unmanaged.passUnretained(self).toOpaque()
        ) else {
            Logger.eventTap.error("Error creating mach port for event tap \"\(self.label)\"")
            return
        }
        guard let source = CFMachPortCreateRunLoopSource(nil, machPort, 0) else {
            Logger.eventTap.error("Error creating run loop source for event tap \"\(self.label)\"")
            return
        }
        self.machPort = machPort
        self.source = source
    }

    deinit {
        guard let machPort else {
            return
        }
        CFRunLoopRemoveSource(runLoop, source, mode)
        CGEvent.tapEnable(tap: machPort, enable: false)
        CFMachPortInvalidate(machPort)
    }

    fileprivate nonisolated static func performCallback(
        for eventTap: EventTap,
        proxy: CGEventTapProxy,
        type: CGEventType,
        event: CGEvent
    ) -> Unmanaged<CGEvent>? {
        let callback = eventTap.callback
        return callback(eventTap, proxy, type, event)
    }

    private static func createTapMachPort(
        location: Location,
        place: CGEventTapPlacement,
        options: CGEventTapOptions,
        eventsOfInterest: CGEventMask,
        callback: CGEventTapCallBack,
        userInfo: UnsafeMutableRawPointer?
    ) -> CFMachPort? {
        if case .pid(let pid) = location {
            return CGEvent.tapCreateForPid(
                pid: pid,
                place: place,
                options: options,
                eventsOfInterest: eventsOfInterest,
                callback: callback,
                userInfo: userInfo
            )
        }

        let tap: CGEventTapLocation? = switch location {
        case .hidEventTap: .cghidEventTap
        case .sessionEventTap: .cgSessionEventTap
        case .annotatedSessionEventTap: .cgAnnotatedSessionEventTap
        case .pid: nil
        }

        guard let tap else {
            return nil
        }

        return CGEvent.tapCreate(
            tap: tap,
            place: place,
            options: options,
            eventsOfInterest: eventsOfInterest,
            callback: callback,
            userInfo: userInfo
        )
    }

    private func withUnwrappedComponents(body: @MainActor (CFRunLoop, CFRunLoopSource, CFMachPort) -> Void) {
        guard let runLoop else {
            Logger.eventTap.error("Missing run loop for event tap \"\(self.label)\"")
            return
        }
        guard let source else {
            Logger.eventTap.error("Missing run loop source for event tap \"\(self.label)\"")
            return
        }
        guard let machPort else {
            Logger.eventTap.error("Missing mach port for event tap \"\(self.label)\"")
            return
        }
        body(runLoop, source, machPort)
    }

    /// Enables the event tap.
    func enable() {
        withUnwrappedComponents { runLoop, source, machPort in
            CFRunLoopAddSource(runLoop, source, mode)
            CGEvent.tapEnable(tap: machPort, enable: true)
        }
    }

    /// Enables the event tap with the given timeout.
    func enable(timeout: Duration, onTimeout: @escaping () -> Void) {
        enable()
        Task { [weak self] in
            try await Task.sleep(for: timeout)
            if self?.isEnabled == true {
                onTimeout()
            }
        }
    }

    /// Disables the event tap.
    func disable() {
        withUnwrappedComponents { runLoop, source, machPort in
            CFRunLoopRemoveSource(runLoop, source, mode)
            CGEvent.tapEnable(tap: machPort, enable: false)
        }
    }
}

// MARK: - Handle Event
private func handleEvent(
    proxy: CGEventTapProxy,
    type: CGEventType,
    event: CGEvent,
    refcon: UnsafeMutableRawPointer?
) -> Unmanaged<CGEvent>? {
    guard let refcon else {
        return Unmanaged.passRetained(event)
    }
    let eventTap = Unmanaged<EventTap>.fromOpaque(refcon).takeUnretainedValue()
    return EventTap.performCallback(for: eventTap, proxy: proxy, type: type, event: event)
}

// MARK: - Logger
private extension Logger {
    static let eventTap = Logger(category: "EventTap")
}


================================================
FILE: Ice/Hotkeys/Hotkey.swift
================================================
//
//  Hotkey.swift
//  Ice
//

import Combine

/// A combination of a key and modifiers that can be used to
/// trigger actions on system-wide key-up or key-down events.
final class Hotkey: ObservableObject {
    private weak var appState: AppState?

    private var listener: Listener?

    let action: HotkeyAction

    @Published var keyCombination: KeyCombination? {
        didSet {
            enable()
        }
    }

    var isEnabled: Bool {
        listener != nil
    }

    init(keyCombination: KeyCombination?, action: HotkeyAction) {
        self.keyCombination = keyCombination
        self.action = action
    }

    func assignAppState(_ appState: AppState) {
        self.appState = appState
        enable()
    }

    func enable() {
        disable()
        listener = Listener(hotkey: self, eventKind: .keyDown, appState: appState)
    }

    func disable() {
        listener?.invalidate()
        listener = nil
    }
}

extension Hotkey {
    /// An object that manges the lifetime of a hotkey observation.
    private final class Listener {
        private weak var appState: AppState?

        private var id: UInt32?

        var isValid: Bool {
            id != nil
        }

        init?(hotkey: Hotkey, eventKind: HotkeyRegistry.EventKind, appState: AppState?) {
            guard
                let appState,
                hotkey.keyCombination != nil
            else {
                return nil
            }
            let id = appState.hotkeyRegistry.register(
                hotkey: hotkey,
                eventKind: eventKind
            ) { [weak appState] in
                guard let appState else {
                    return
                }
                Task {
                    await hotkey.action.perform(appState: appState)
                }
            }
            guard let id else {
                return nil
            }
            self.appState = appState
            self.id = id
        }

        deinit {
            invalidate()
        }

        func invalidate() {
            guard isValid else {
                return
            }
            guard let appState else {
                Logger.hotkey.error("Error invalidating hotkey: Missing AppState")
                return
            }
            defer {
                id = nil
            }
            if let id {
                appState.hotkeyRegistry.unregister(id)
            }
        }
    }
}

// MARK: Hotkey: Codable
extension Hotkey: Codable {
    private enum CodingKeys: CodingKey {
        case keyCombination
        case action
    }

    convenience init(from decoder: any Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        try self.init(
            keyCombination: container.decode(KeyCombination?.self, forKey: .keyCombination),
            action: container.decode(HotkeyAction.self, forKey: .action)
        )
    }

    func encode(to encoder: any Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(keyCombination, forKey: .keyCombination)
        try container.encode(action, forKey: .action)
    }
}

// MARK: Hotkey: Equatable
extension Hotkey: Equatable {
    static func == (lhs: Hotkey, rhs: Hotkey) -> Bool {
        lhs.keyCombination == rhs.keyCombination &&
        lhs.action == rhs.action
    }
}

// MARK: Hotkey: Hashable
extension Hotkey: Hashable {
    func hash(into hasher: inout Hasher) {
        hasher.combine(keyCombination)
        hasher.combine(action)
    }
}

// MARK: - Logger
private extension Logger {
    static let hotkey = Logger(category: "Hotkey")
}


================================================
FILE: Ice/Hotkeys/HotkeyAction.swift
================================================
//
//  HotkeyAction.swift
//  Ice
//

enum HotkeyAction: String, Codable, CaseIterable {
    // Menu Bar Sections
    case toggleHiddenSection = "ToggleHiddenSection"
    case toggleAlwaysHiddenSection = "ToggleAlwaysHiddenSection"

    // Menu Bar Items
    case searchMenuBarItems = "SearchMenuBarItems"

    // Other
    case enableIceBar = "EnableIceBar"
    case showSectionDividers = "ShowSectionDividers"
    case toggleApplicationMenus = "ToggleApplicationMenus"

    @MainActor
    func perform(appState: AppState) async {
        switch self {
        case .toggleHiddenSection:
            guard let section = appState.menuBarManager.section(withName: .hidden) else {
                return
            }
            section.toggle()
            // Prevent the section from automatically rehiding after mouse movement.
            if !section.isHidden {
                appState.preventShowOnHover()
            }
        case .toggleAlwaysHiddenSection:
            guard let section = appState.menuBarManager.section(withName: .alwaysHidden) else {
                return
            }
            section.toggle()
            // Prevent the section from automatically rehiding after mouse movement.
            if !section.isHidden {
                appState.preventShowOnHover()
            }
        case .searchMenuBarItems:
            await appState.menuBarManager.searchPanel.toggle()
        case .enableIceBar:
            appState.settingsManager.generalSettingsManager.useIceBar.toggle()
        case .showSectionDividers:
            appState.settingsManager.advancedSettingsManager.showSectionDividers.toggle()
        case .toggleApplicationMenus:
            appState.menuBarManager.toggleApplicationMenus()
        }
    }
}


================================================
FILE: Ice/Hotkeys/HotkeyRegistry.swift
================================================
//
//  HotkeyRegistry.swift
//  Ice
//

import Carbon.HIToolbox
import Cocoa
import Combine

/// An object that manages the registration, storage, and unregistration of hotkeys.
final class HotkeyRegistry {
    /// The event kinds that a hotkey can be registered for.
    enum EventKind {
        case keyUp
        case keyDown

        fileprivate init?(event: EventRef) {
            switch Int(GetEventKind(event)) {
            case kEventHotKeyPressed:
                self = .keyDown
            case kEventHotKeyReleased:
                self = .keyUp
            default:
                return nil
            }
        }
    }

    /// An object that stores the information needed to cancel a registration.
    private final class Registration {
        let eventKind: EventKind
        let key: KeyCode
        let modifiers: Modifiers
        let hotKeyID: EventHotKeyID
        var hotKeyRef: EventHotKeyRef?
        let handler: () -> Void

        init(
            eventKind: EventKind,
            key: KeyCode,
            modifiers: Modifiers,
            hotKeyID: EventHotKeyID,
            hotKeyRef: EventHotKeyRef,
            handler: @escaping () -> Void
        ) {
            self.eventKind = eventKind
            self.key = key
            self.modifiers = modifiers
            self.hotKeyID = hotKeyID
            self.hotKeyRef = hotKeyRef
            self.handler = handler
        }
    }

    private let signature = OSType(1231250720) // OSType for Ice

    private var eventHandlerRef: EventHandlerRef?

    private var registrations = [UInt32: Registration]()

    private var cancellables = Set<AnyCancellable>()

    /// Installs the global event handler reference, if it isn't already installed.
    private func installIfNeeded() -> OSStatus {
        guard eventHandlerRef == nil else {
            return noErr
        }

        NotificationCenter.default
            .publisher(for: NSMenu.didBeginTrackingNotification)
            .sink { [weak self] _ in
                self?.unregisterAndRetainAll()
            }
            .store(in: &cancellables)

        NotificationCenter.default
            .publisher(for: NSMenu.didEndTrackingNotification)
            .sink { [weak self] _ in
                self?.registerAllRetained()
            }
            .store(in: &cancellables)

        let handler: EventHandlerUPP = { _, event, userData in
            guard
                let event,
                let userData
            else {
                return OSStatus(eventNotHandledErr)
            }
            let registry = Unmanaged<HotkeyRegistry>.fromOpaque(userData).takeUnretainedValue()
            return registry.performEventHandler(for: event)
        }

        let eventTypes: [EventTypeSpec] = [
            EventTypeSpec(eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyPressed)),
            EventTypeSpec(eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyReleased)),
        ]

        return InstallEventHandler(
            GetEventDispatcherTarget(),
            handler,
            eventTypes.count,
            eventTypes,
            Unmanaged.passUnretained(self).toOpaque(),
            &eventHandlerRef
        )
    }

    /// Registers the given hotkey for the given event kind and returns the
    /// identifier of the registration on success.
    ///
    /// The returned identifier can be used to unregister the hotkey using
    /// the ``unregister(_:)`` function.
    ///
    /// - Parameters:
    ///   - hotkey: The hotkey to register the handler with.
    ///   - eventKind: The event kind to register the handler with.
    ///   - handler: The handler to perform when `hotkey` is triggered with
    ///     the event kind specified by `eventKind`.
    ///
    /// - Returns: The registration's identifier on success, `nil` on failure.
    func register(hotkey: Hotkey, eventKind: EventKind, handler: @escaping () -> Void) -> UInt32? {
        enum Context {
            static var currentID: UInt32 = 0
        }

        defer {
            Context.currentID += 1
        }

        guard let keyCombination = hotkey.keyCombination else {
            Logger.hotkeyRegistry.error("Hotkey does not have a valid key combination")
            return nil
        }

        var status = installIfNeeded()

        guard status == noErr else {
            Logger.hotkeyRegistry.error("Hotkey event handler installation failed with status \(status)")
            return nil
        }

        let id = Context.currentID

        guard registrations[id] == nil else {
            Logger.hotkeyRegistry.error("Hotkey already registered for id \(id)")
            return nil
        }

        let hotKeyID = EventHotKeyID(signature: signature, id: id)
        var hotKeyRef: EventHotKeyRef?
        status = RegisterEventHotKey(
            UInt32(keyCombination.key.rawValue),
            UInt32(keyCombination.modifiers.carbonFlags),
            hotKeyID,
            GetEventDispatcherTarget(),
            0,
            &hotKeyRef
        )

        guard status == noErr else {
            Logger.hotkeyRegistry.error("Hotkey registration failed with status \(status)")
            return nil
        }

        guard let hotKeyRef else {
            Logger.hotkeyRegistry.error("Hotkey registration failed due to invalid EventHotKeyRef")
            return nil
        }

        let registration = Registration(
            eventKind: eventKind,
            key: keyCombination.key,
            modifiers: keyCombination.modifiers,
            hotKeyID: hotKeyID,
            hotKeyRef: hotKeyRef,
            handler: handler
        )
        registrations[id] = registration

        return id
    }

    /// Unregisters the key combination with the given identifier, retaining
    /// its registration in an inactive state.
    private func retainedUnregister(_ id: UInt32) {
        guard let registration = registrations[id] else {
            Logger.hotkeyRegistry.error("No registered key combination for id \(id)")
            return
        }
        let status = UnregisterEventHotKey(registration.hotKeyRef)
        guard status == noErr else {
            Logger.hotkeyRegistry.error("Hotkey unregistration failed with status \(status)")
            return
        }
        registration.hotKeyRef = nil
    }

    /// Unregisters the key combination with the given identifier.
    ///
    /// - Parameter id: An identifier returned from a call to the
    ///   ``register(hotkey:eventKind:handler:)`` function.
    func unregister(_ id: UInt32) {
        retainedUnregister(id)
        registrations.removeValue(forKey: id)
    }

    /// Unregisters all key combinations, retaining their registrations
    /// in an inactive state.
    private func unregisterAndRetainAll() {
        for (id, _) in registrations {
            retainedUnregister(id)
        }
    }

    /// Registers all registrations that were retained during a call to
    /// ``retainedUnregister(_:)``
    private func registerAllRetained() {
        for registration in registrations.values {
            guard registration.hotKeyRef == nil else {
                continue
            }

            var hotKeyRef: EventHotKeyRef?
            let status = RegisterEventHotKey(
                UInt32(registration.key.rawValue),
                UInt32(registration.modifiers.carbonFlags),
                registration.hotKeyID,
                GetEventDispatcherTarget(),
                0,
                &hotKeyRef
            )

            guard
                status == noErr,
                let hotKeyRef
            else {
                registrations.removeValue(forKey: registration.hotKeyID.id)
                Logger.hotkeyRegistry.error("Hotkey registration failed with status \(status)")
                continue
            }

            registration.hotKeyRef = hotKeyRef
        }
    }

    /// Retrieves and performs the event handler stored under the
    /// identifier for the specified event.
    private func performEventHandler(for event: EventRef?) -> OSStatus {
        guard let event else {
            return OSStatus(eventNotHandledErr)
        }

        // create a hot key id from the event
        var hotKeyID = EventHotKeyID()
        let status = GetEventParameter(
            event,
            EventParamName(kEventParamDirectObject),
            EventParamType(typeEventHotKeyID),
            nil,
            MemoryLayout<EventHotKeyID>.size,
            nil,
            &hotKeyID
        )

        // make sure creation was successful
        guard status == noErr else {
            return status
        }

        // make sure the event signature matches our signature and
        // that an event handler is registered for the event
        guard
            hotKeyID.signature == signature,
            let registration = registrations[hotKeyID.id],
            registration.eventKind == EventKind(event: event)
        else {
            return OSStatus(eventNotHandledErr)
        }

        // all checks passed; perform the event handler
        registration.handler()

        return noErr
    }
}

// MARK: - Logger
private extension Logger {
    static let hotkeyRegistry = Logger(category: "HotkeyRegistry")
}


================================================
FILE: Ice/Hotkeys/KeyCode.swift
================================================
//
//  KeyCode.swift
//  Ice
//

import Carbon.HIToolbox

/// Representation of a physical key on a keyboard.
struct KeyCode: Codable, Hashable, RawRepresentable {
    let rawValue: Int

    // MARK: Letters

    static let a = KeyCode(rawValue: kVK_ANSI_A)
    static let b = KeyCode(rawValue: kVK_ANSI_B)
    static let c = KeyCode(rawValue: kVK_ANSI_C)
    static let d = KeyCode(rawValue: kVK_ANSI_D)
    static let e = KeyCode(rawValue: kVK_ANSI_E)
    static let f = KeyCode(rawValue: kVK_ANSI_F)
    static let g = KeyCode(rawValue: kVK_ANSI_G)
    static let h = KeyCode(rawValue: kVK_ANSI_H)
    static let i = KeyCode(rawValue: kVK_ANSI_I)
    static let j = KeyCode(rawValue: kVK_ANSI_J)
    static let k = KeyCode(rawValue: kVK_ANSI_K)
    static let l = KeyCode(rawValue: kVK_ANSI_L)
    static let m = KeyCode(rawValue: kVK_ANSI_M)
    static let n = KeyCode(rawValue: kVK_ANSI_N)
    static let o = KeyCode(rawValue: kVK_ANSI_O)
    static let p = KeyCode(rawValue: kVK_ANSI_P)
    static let q = KeyCode(rawValue: kVK_ANSI_Q)
    static let r = KeyCode(rawValue: kVK_ANSI_R)
    static let s = KeyCode(rawValue: kVK_ANSI_S)
    static let t = KeyCode(rawValue: kVK_ANSI_T)
    static let u = KeyCode(rawValue: kVK_ANSI_U)
    static let v = KeyCode(rawValue: kVK_ANSI_V)
    static let w = KeyCode(rawValue: kVK_ANSI_W)
    static let x = KeyCode(rawValue: kVK_ANSI_X)
    static let y = KeyCode(rawValue: kVK_ANSI_Y)
    static let z = KeyCode(rawValue: kVK_ANSI_Z)

    // MARK: Numbers

    static let zero = KeyCode(rawValue: kVK_ANSI_0)
    static let one = KeyCode(rawValue: kVK_ANSI_1)
    static let two = KeyCode(rawValue: kVK_ANSI_2)
    static let three = KeyCode(rawValue: kVK_ANSI_3)
    static let four = KeyCode(rawValue: kVK_ANSI_4)
    static let five = KeyCode(rawValue: kVK_ANSI_5)
    static let six = KeyCode(rawValue: kVK_ANSI_6)
    static let seven = KeyCode(rawValue: kVK_ANSI_7)
    static let eight = KeyCode(rawValue: kVK_ANSI_8)
    static let nine = KeyCode(rawValue: kVK_ANSI_9)

    // MARK: Symbols

    static let equal = KeyCode(rawValue: kVK_ANSI_Equal)
    static let minus = KeyCode(rawValue: kVK_ANSI_Minus)
    static let rightBracket = KeyCode(rawValue: kVK_ANSI_RightBracket)
    static let leftBracket = KeyCode(rawValue: kVK_ANSI_LeftBracket)
    static let quote = KeyCode(rawValue: kVK_ANSI_Quote)
    static let semicolon = KeyCode(rawValue: kVK_ANSI_Semicolon)
    static let backslash = KeyCode(rawValue: kVK_ANSI_Backslash)
    static let comma = KeyCode(rawValue: kVK_ANSI_Comma)
    static let slash = KeyCode(rawValue: kVK_ANSI_Slash)
    static let period = KeyCode(rawValue: kVK_ANSI_Period)
    static let grave = KeyCode(rawValue: kVK_ANSI_Grave)

    // MARK: Keypad

    static let keypad0 = KeyCode(rawValue: kVK_ANSI_Keypad0)
    static let keypad1 = KeyCode(rawValue: kVK_ANSI_Keypad1)
    static let keypad2 = KeyCode(rawValue: kVK_ANSI_Keypad2)
    static let keypad3 = KeyCode(rawValue: kVK_ANSI_Keypad3)
    static let keypad4 = KeyCode(rawValue: kVK_ANSI_Keypad4)
    static let keypad5 = KeyCode(rawValue: kVK_ANSI_Keypad5)
    static let keypad6 = KeyCode(rawValue: kVK_ANSI_Keypad6)
    static let keypad7 = KeyCode(rawValue: kVK_ANSI_Keypad7)
    static let keypad8 = KeyCode(rawValue: kVK_ANSI_Keypad8)
    static let keypad9 = KeyCode(rawValue: kVK_ANSI_Keypad9)
    static let keypadDecimal = KeyCode(rawValue: kVK_ANSI_KeypadDecimal)
    static let keypadMultiply = KeyCode(rawValue: kVK_ANSI_KeypadMultiply)
    static let keypadPlus = KeyCode(rawValue: kVK_ANSI_KeypadPlus)
    static let keypadClear = KeyCode(rawValue: kVK_ANSI_KeypadClear)
    static let keypadDivide = KeyCode(rawValue: kVK_ANSI_KeypadDivide)
    static let keypadEnter = KeyCode(rawValue: kVK_ANSI_KeypadEnter)
    static let keypadMinus = KeyCode(rawValue: kVK_ANSI_KeypadMinus)
    static let keypadEquals = KeyCode(rawValue: kVK_ANSI_KeypadEquals)

    // MARK: Editing

    static let space = KeyCode(rawValue: kVK_Space)
    static let tab = KeyCode(rawValue: kVK_Tab)
    static let `return` = KeyCode(rawValue: kVK_Return)
    static let delete = KeyCode(rawValue: kVK_Delete)
    static let forwardDelete = KeyCode(rawValue: kVK_ForwardDelete)

    // MARK: Modifiers

    static let control = KeyCode(rawValue: kVK_Control)
    static let option = KeyCode(rawValue: kVK_Option)
    static let shift = KeyCode(rawValue: kVK_Shift)
    static let command = KeyCode(rawValue: kVK_Command)
    static let rightControl = KeyCode(rawValue: kVK_RightControl)
    static let rightOption = KeyCode(rawValue: kVK_RightOption)
    static let rightShift = KeyCode(rawValue: kVK_RightShift)
    static let rightCommand = KeyCode(rawValue: kVK_RightCommand)
    static let capsLock = KeyCode(rawValue: kVK_CapsLock)
    static let function = KeyCode(rawValue: kVK_Function)

    // MARK: Function

    static let f1 = KeyCode(rawValue: kVK_F1)
    static let f2 = KeyCode(rawValue: kVK_F2)
    static let f3 = KeyCode(rawValue: kVK_F3)
    static let f4 = KeyCode(rawValue: kVK_F4)
    static let f5 = KeyCode(rawValue: kVK_F5)
    static let f6 = KeyCode(rawValue: kVK_F6)
    static let f7 = KeyCode(rawValue: kVK_F7)
    static let f8 = KeyCode(rawValue: kVK_F8)
    static let f9 = KeyCode(rawValue: kVK_F9)
    static let f10 = KeyCode(rawValue: kVK_F10)
    static let f11 = KeyCode(rawValue: kVK_F11)
    static let f12 = KeyCode(rawValue: kVK_F12)
    static let f13 = KeyCode(rawValue: kVK_F13)
    static let f14 = KeyCode(rawValue: kVK_F14)
    static let f15 = KeyCode(rawValue: kVK_F15)
    static let f16 = KeyCode(rawValue: kVK_F16)
    static let f17 = KeyCode(rawValue: kVK_F17)
    static let f18 = KeyCode(rawValue: kVK_F18)
    static let f19 = KeyCode(rawValue: kVK_F19)
    static let f20 = KeyCode(rawValue: kVK_F20)

    // MARK: Navigation

    static let pageUp = KeyCode(rawValue: kVK_PageUp)
    static let pageDown = KeyCode(rawValue: kVK_PageDown)
    static let home = KeyCode(rawValue: kVK_Home)
    static let end = KeyCode(rawValue: kVK_End)
    static let escape = KeyCode(rawValue: kVK_Escape)
    static let help = KeyCode(rawValue: kVK_Help)
    static let leftArrow = KeyCode(rawValue: kVK_LeftArrow)
    static let rightArrow = KeyCode(rawValue: kVK_RightArrow)
    static let downArrow = KeyCode(rawValue: kVK_DownArrow)
    static let upArrow = KeyCode(rawValue: kVK_UpArrow)

    // MARK: Media

    static let volumeUp = KeyCode(rawValue: kVK_VolumeUp)
    static let volumeDown = KeyCode(rawValue: kVK_VolumeDown)
    static let mute = KeyCode(rawValue: kVK_Mute)
}

// MARK: Key Equivalent
extension KeyCode {
    /// System representation.
    var keyEquivalent: String {
        guard
            let inputSource = TISCopyCurrentASCIICapableKeyboardLayoutInputSource()?.takeRetainedValue(),
            let layoutData = TISGetInputSourceProperty(inputSource, kTISPropertyUnicodeKeyLayoutData)
        else {
            return ""
        }

        let layoutBytes = CFDataGetBytePtr(unsafeBitCast(layoutData, to: CFData.self))
        let layoutPtr = unsafeBitCast(layoutBytes, to: UnsafePointer<UCKeyboardLayout>.self)

        let modifierKeyState: UInt32 = 0 // empty modifier key state
        var deadKeyState: UInt32 = 0
        let maxLength = 4
        var actualLength = 0
        var codeUnits = [UniChar](repeating: 0, count: maxLength)

        let status = UCKeyTranslate(
            layoutPtr,
            UInt16(rawValue),
            UInt16(kUCKeyActionDisplay),
            modifierKeyState,
            UInt32(LMGetKbdType()),
            OptionBits(kUCKeyTranslateNoDeadKeysBit),
            &deadKeyState,
            maxLength,
            &actualLength,
            &codeUnits
        )

        guard status == noErr else {
            return ""
        }

        return String(utf16CodeUnits: codeUnits, count: actualLength)
    }
}

// MARK: Custom String Mappings
private let customStringMappings = [
    // standard keys
    KeyCode.space: "Space",
    KeyCode.tab: "⇥",
    KeyCode.return: "⏎",
    KeyCode.delete: "⌫",
    KeyCode.forwardDelete: "⌦",
    KeyCode.f1: "F1",
    KeyCode.f2: "F2",
    KeyCode.f3: "F3",
    KeyCode.f4: "F4",
    KeyCode.f5: "F5",
    KeyCode.f6: "F6",
    KeyCode.f7: "F7",
    KeyCode.f8: "F8",
    KeyCode.f9: "F9",
    KeyCode.f10: "F10",
    KeyCode.f11: "F11",
    KeyCode.f12: "F12",
    KeyCode.f13: "F13",
    KeyCode.f14: "F14",
    KeyCode.f15: "F15",
    KeyCode.f16: "F16",
    KeyCode.f17: "F17",
    KeyCode.f18: "F18",
    KeyCode.f19: "F19",
    KeyCode.f20: "F20",
    KeyCode.pageUp: "⇞",
    KeyCode.pageDown: "⇟",
    KeyCode.home: "↖",
    KeyCode.end: "↘",
    KeyCode.escape: "⎋",
    KeyCode.leftArrow: "←",
    KeyCode.rightArrow: "→",
    KeyCode.downArrow: "↓",
    KeyCode.upArrow: "↑",
    KeyCode.capsLock: "⇪",
    KeyCode.control: "⌃",
    KeyCode.option: "⌥",
    KeyCode.shift: "⇧",
    KeyCode.command: "⌘",
    KeyCode.rightControl: "⌃",
    KeyCode.rightOption: "⌥",
    KeyCode.rightShift: "⇧",
    KeyCode.rightCommand: "⌘",
    KeyCode.keypadClear: "⌧",
    KeyCode.keypadEnter: "⌤",
    // media keys
    KeyCode.volumeUp: "\u{1F50A}",   // 'SPEAKER WITH THREE SOUND WAVES'
    KeyCode.volumeDown: "\u{1F509}", // 'SPEAKER WITH ONE SOUND WAVE'
    KeyCode.mute: "\u{1F507}",       // 'SPEAKER WITH CANCELLATION STROKE'
    // keypad keys
    KeyCode.keypad0: "0⃣",
    KeyCode.keypad1: "1⃣",
    KeyCode.keypad2: "2⃣",
    KeyCode.keypad3: "3⃣",
    KeyCode.keypad4: "4⃣",
    KeyCode.keypad5: "5⃣",
    KeyCode.keypad6: "6⃣",
    KeyCode.keypad7: "7⃣",
    KeyCode.keypad8: "8⃣",
    KeyCode.keypad9: "9⃣",
    KeyCode.keypadDecimal: ".⃣",
    KeyCode.keypadDivide: "/⃣",
    KeyCode.keypadEquals: "=⃣",
    KeyCode.keypadMinus: "-⃣",
    KeyCode.keypadMultiply: "*⃣",
    KeyCode.keypadPlus: "+⃣",
    // other keys
    KeyCode.function: "🌐︎︎",
    KeyCode.help: "?⃝",
]

// MARK: String Value
extension KeyCode {
    /// Custom string representation.
    var stringValue: String {
        customStringMappings[self, default: keyEquivalent]
    }
}


================================================
FILE: Ice/Hotkeys/KeyCombination.swift
================================================
//
//  KeyCombination.swift
//  Ice
//

import Carbon.HIToolbox
import Cocoa

struct KeyCombination: Hashable {
    let key: KeyCode
    let modifiers: Modifiers

    var stringValue: String {
        modifiers.symbolicValue + key.stringValue
    }

    init(key: KeyCode, modifiers: Modifiers) {
        self.key = key
        self.modifiers = modifiers
    }

    init(event: NSEvent) {
        let key = KeyCode(rawValue: Int(event.keyCode))
        let modifiers = Modifiers(nsEventFlags: event.modifierFlags)
        self.init(key: key, modifiers: modifiers)
    }
}

private func getSystemReservedKeyCombinations() -> [KeyCombination] {
    var symbolicHotkeys: Unmanaged<CFArray>?
    let status = CopySymbolicHotKeys(&symbolicHotkeys)

    guard status == noErr else {
        Logger.keyCombination.error("CopySymbolicHotKeys returned invalid status: \(status)")
        return []
    }
    guard let reservedHotkeys = symbolicHotkeys?.takeRetainedValue() as? [[String: Any]] else {
        Logger.keyCombination.error("Failed to serialize symbolic hotkeys")
        return []
    }

    return reservedHotkeys.compactMap { hotkey in
        guard
            hotkey[kHISymbolicHotKeyEnabled] as? Bool == true,
            let keyCode = hotkey[kHISymbolicHotKeyCode] as? Int,
            let modifiers = hotkey[kHISymbolicHotKeyModifiers] as? Int
        else {
            return nil
        }
        return KeyCombination(
            key: KeyCode(rawValue: keyCode),
            modifiers: Modifiers(carbonFlags: modifiers)
        )
    }
}

extension KeyCombination {
    /// Returns a Boolean value that indicates whether this key
    /// combination is reserved for system use.
    var isReservedBySystem: Bool {
        getSystemReservedKeyCombinations().contains(self)
    }
}

extension KeyCombination: Codable {
    init(from decoder: any Decoder) throws {
        var container = try decoder.unkeyedContainer()
        guard container.count == 2 else {
            throw DecodingError.dataCorrupted(
                DecodingError.Context(
                    codingPath: decoder.codingPath,
                    debugDescription: "Expected 2 encoded values, found \(container.count ?? 0)"
                )
            )
        }
        self.key = try KeyCode(rawValue: container.decode(Int.self))
        self.modifiers = try Modifiers(rawValue: container.decode(Int.self))
    }

    func encode(to encoder: any Encoder) throws {
        var container = encoder.unkeyedContainer()
        try container.encode(key.rawValue)
        try container.encode(modifiers.rawValue)
    }
}

// MARK: - Logger
private extension Logger {
    static let keyCombination = Logger(category: "KeyCombination")
}


================================================
FILE: Ice/Hotkeys/Modifiers.swift
================================================
//
//  Modifiers.swift
//  Ice
//

import Carbon.HIToolbox
import Cocoa

/// A bit mask containing the modifier keys for a hotkey.
struct Modifiers: OptionSet, Codable, Hashable {
    let rawValue: Int

    static let control = Modifiers(rawValue: 1 << 0)
    static let option = Modifiers(rawValue: 1 << 1)
    static let shift = Modifiers(rawValue: 1 << 2)
    static let command = Modifiers(rawValue: 1 << 3)
}

extension Modifiers {
    /// All modifiers in the order displayed by the system,
    /// according to Apple's style guide.
    static let canonicalOrder = [control, option, shift, command]

    /// A symbolic string representation of the modifiers.
    var symbolicValue: String {
        var result = ""
        if contains(.control) {
            result.append("⌃")
        }
        if contains(.option) {
            result.append("⌥")
        }
        if contains(.shift) {
            result.append("⇧")
        }
        if contains(.command) {
            result.append("⌘")
        }
        return result
    }

    /// A string representation of the modifiers that is
    /// suitable for display in a label.
    var labelValue: String {
        var result = [String]()
        if contains(.control) {
            result.append("Control")
        }
        if contains(.option) {
            result.append("Option")
        }
        if contains(.shift) {
            result.append("Shift")
        }
        if contains(.command) {
            result.append("Command")
        }
        return result.joined(separator: " + ")
    }

    /// A combined string representation of the modifiers
    /// that is suitable for display.
    var combinedValue: String {
        "\(labelValue) (\(symbolicValue))"
    }

    /// Cocoa flags.
    var nsEventFlags: NSEvent.ModifierFlags {
        var result: NSEvent.ModifierFlags = []
        if contains(.control) {
            result.insert(.control)
        }
        if contains(.option) {
            result.insert(.option)
        }
        if contains(.shift) {
            result.insert(.shift)
        }
        if contains(.command) {
            result.insert(.command)
        }
        return result
    }

    /// CoreGraphics flags.
    var cgEventFlags: CGEventFlags {
        var result: CGEventFlags = []
        if contains(.control) {
            result.insert(.maskControl)
        }
        if contains(.option) {
            result.insert(.maskAlternate)
        }
        if contains(.shift) {
            result.insert(.maskShift)
        }
        if contains(.command) {
            result.insert(.maskCommand)
        }
        return result
    }

    /// Raw Carbon flags.
    var carbonFlags: Int {
        var result = 0
        if contains(.control) {
            result |= controlKey
        }
        if contains(.option) {
            result |= optionKey
        }
        if contains(.shift) {
            result |= shiftKey
        }
        if contains(.command) {
            result |= cmdKey
        }
        return result
    }

    init(nsEventFlags: NSEvent.ModifierFlags) {
        self.init()
        if nsEventFlags.contains(.control) {
            insert(.control)
        }
        if nsEventFlags.contains(.option) {
            insert(.option)
        }
        if nsEventFlags.contains(.shift) {
            insert(.shift)
        }
        if nsEventFlags.contains(.command) {
            insert(.command)
        }
    }

    init(cgEventFlags: CGEventFlags) {
        self.init()
        if cgEventFlags.contains(.maskControl) {
            insert(.control)
        }
        if cgEventFlags.contains(.maskAlternate) {
            insert(.option)
        }
        if cgEventFlags.contains(.maskShift) {
            insert(.shift)
        }
        if cgEventFlags.contains(.maskCommand) {
            insert(.command)
        }
    }

    init(carbonFlags: Int) {
        self.init()
        if carbonFlags & controlKey == controlKey {
            insert(.control)
        }
        if carbonFlags & optionKey == optionKey {
            insert(.option)
        }
        if carbonFlags & shiftKey == shiftKey {
            insert(.shift)
        }
        if carbonFlags & cmdKey == cmdKey {
            insert(.command)
        }
    }
}


================================================
FILE: Ice/Ice.entitlements
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.security.app-sandbox</key>
	<false/>
	<key>com.apple.security.files.user-selected.read-only</key>
	<true/>
</dict>
</plist>


================================================
FILE: Ice/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>SUFeedURL</key>
	<string>https://jordanbaird.github.io/ice-releases/appcast.xml</string>
	<key>SUPublicEDKey</key>
	<string>3nfIGMOD8DALPE8vIdFo2tUOIVc2MVbzhc+2J9JLn+Q=</string>
</dict>
</plist>


================================================
FILE: Ice/Main/AppDelegate.swift
================================================
//
//  AppDelegate.swift
//  Ice
//

import SwiftUI

@MainActor
final class AppDelegate: NSObject, NSApplicationDelegate {
    private weak var appState: AppState?

    // MARK: NSApplicationDelegate Methods

    func applicationWillFinishLaunching(_ notification: Notification) {
        guard let appState else {
            Logger.appDelegate.warning("Missing app state in applicationWillFinishLaunching")
            return
        }

        // Assign the delegate to the shared app state.
        appState.assignAppDelegate(self)

        // Allow the app to set the cursor in the background.
        appState.setsCursorInBackground = true
    }

    func applicationDidFinishLaunching(_ notification: Notification) {
        guard let appState else {
            Logger.appDelegate.warning("Missing app state in applicationDidFinishLaunching")
            return
        }

        // Dismiss the windows.
        appState.dismissSettingsWindow()
        appState.dismissPermissionsWindow()

        // Hide the main menu to make more space in the menu bar.
        if let mainMenu = NSApp.mainMenu {
            for item in mainMenu.items {
                item.isHidden = true
            }
        }

        // Perform setup after a small delay to ensure that the settings window
        // has been assigned.
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            guard !appState.isPreview else {
                return
            }
            // If we have the required permissions, set up the shared app state.
            // Otherwise, open the permissions window.
            switch appState.permissionsManager.permissionsState {
            case .hasAllPermissions, .hasRequiredPermissions:
                appState.performSetup()
            case .missingPermissions:
                appState.activate(withPolicy: .regular)
                appState.openPermissionsWindow()
            }
        }
    }

    func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
        // Deactivate and set the policy to accessory when all windows are closed.
        appState?.deactivate(withPolicy: .accessory)
        return false
    }

    func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
        return true
    }

    // MARK: Other Methods

    /// Assigns the app state to the delegate.
    func assignAppState(_ appState: AppState) {
        guard self.appState == nil else {
            Logger.appDelegate.warning("Multiple attempts made to assign app state")
            return
        }
        self.appState = appState
    }

    /// Opens the settings window and activates the app.
    @objc func openSettingsWindow() {
        guard let appState else {
            Logger.appDelegate.error("Failed to open settings window")
            return
        }
        // Small delay makes this more reliable.
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            appState.activate(withPolicy: .regular)
            appState.openSettingsWindow()
        }
    }
}

// MARK: - Logger
private extension Logger {
    static let appDelegate = Logger(category: "AppDelegate")
}


================================================
FILE: Ice/Main/AppState.swift
================================================
//
//  AppState.swift
//  Ice
//

import Combine
import SwiftUI

/// The model for app-wide state.
@MainActor
final class AppState: ObservableObject {
    /// A Boolean value that indicates whether the active space is fullscreen.
    @Published private(set) var isActiveSpaceFullscreen = Bridging.isSpaceFullscreen(Bridging.activeSpaceID)

    /// Manager for the menu bar's appearance.
    private(set) lazy var appearanceManager = MenuBarAppearanceManager(appState: self)

    /// Manager for events received by the app.
    private(set) lazy var eventManager = EventManager(appState: self)

    /// Manager for menu bar items.
    private(set) lazy var itemManager = MenuBarItemManager(appState: self)

    /// Manager for the state of the menu bar.
    private(set) lazy var menuBarManager = MenuBarManager(appState: self)

    /// Manager for app permissions.
    private(set) lazy var permissionsManager = PermissionsManager(appState: self)

    /// Manager for the app's settings.
    private(set) lazy var settingsManager = SettingsManager(appState: self)

    /// Manager for app updates.
    private(set) lazy var updatesManager = UpdatesManager(appState: self)

    /// Manager for user notifications.
    private(set) lazy var userNotificationManager = UserNotificationManager(appState: self)

    /// Global cache for menu bar item images.
    private(set) lazy var imageCache = MenuBarItemImageCache(appState: self)

    /// Manager for menu bar item spacing.
    let spacingManager = MenuBarItemSpacingManager()

    /// Model for app-wide navigation.
    let navigationState = AppNavigationState()

    /// The app's hotkey registry.
    nonisolated let hotkeyRegistry = HotkeyRegistry()

    /// The app's delegate.
    private(set) weak var appDelegate: AppDelegate?

    /// The window that contains the settings interface.
    private(set) weak var settingsWindow: NSWindow?

    /// The window that contains the permissions interface.
    private(set) weak var permissionsWindow: NSWindow?

    /// A Boolean value that indicates whether the "ShowOnHover" feature is prevented.
    private(set) var isShowOnHoverPrevented = false

    /// Storage for internal observers.
    private var cancellables = Set<AnyCancellable>()

    /// A Boolean value that indicates whether the app is running as a SwiftUI preview.
    let isPreview: Bool = {
        #if DEBUG
        let environment = ProcessInfo.processInfo.environment
        let key = "XCODE_RUNNING_FOR_PREVIEWS"
        return environment[key] != nil
        #else
        return false
        #endif
    }()

    /// A Boolean value that indicates whether the application can set the cursor
    /// in the background.
    var setsCursorInBackground: Bool {
        get { Bridging.getConnectionProperty(forKey: "SetsCursorInBackground") as? Bool ?? false }
        set { Bridging.setConnectionProperty(newValue, forKey: "SetsCursorInBackground") }
    }

    /// Configures the internal observers for the app state.
    private func configureCancellables() {
        var c = Set<AnyCancellable>()

        Publishers.Merge3(
            NSWorkspace.shared.notificationCenter
                .publisher(for: NSWorkspace.activeSpaceDidChangeNotification)
                .mapToVoid(),
            // Frontmost application change can indicate a space change from one display to
            // another, which gets ignored by NSWorkspace.activeSpaceDidChangeNotification.
            NSWorkspace.shared
                .publisher(for: \.frontmostApplication)
                .mapToVoid(),
            // Clicking into a fullscreen space from another space is also ignored.
            UniversalEventMonitor
                .publisher(for: .leftMouseDown)
                .delay(for: 0.1, scheduler: DispatchQueue.main)
                .mapToVoid()
        )
        .receive(on: DispatchQueue.main)
        .sink { [weak self] _ in
            guard let self else {
                return
            }
            isActiveSpaceFullscreen = Bridging.isSpaceFullscreen(Bridging.activeSpaceID)
        }
        .store(in: &c)

        NSWorkspace.shared.publisher(for: \.frontmostApplication)
            .receive(on: DispatchQueue.main)
            .sink { [weak self] frontmostApplication in
                guard let self else {
                    return
                }
                navigationState.isAppFrontmost = frontmostApplication == .current
            }
            .store(in: &c)

        if let settingsWindow {
            settingsWindow.publisher(for: \.isVisible)
                .debounce(for: 0.05, scheduler: DispatchQueue.main)
                .sink { [weak self] isVisible in
                    guard let self else {
                        return
                    }
                    navigationState.isSettingsPresented = isVisible
                }
                .store(in: &c)
        } else {
            Logger.appState.warning("No settings window!")
        }

        Publishers.Merge(
            navigationState.$isAppFrontmost,
            navigationState.$isSettingsPresented
        )
        .debounce(for: 0.1, scheduler: DispatchQueue.main)
        .sink { [weak self] shouldUpdate in
            guard
                let self,
                shouldUpdate
            else {
                return
            }
            Task.detached {
                if ScreenCapture.cachedCheckPermissions(reset: true) {
                    await self.imageCache.updateCacheWithoutChecks(sections: MenuBarSection.Name.allCases)
                }
            }
        }
        .store(in: &c)

        menuBarManager.objectWillChange
            .sink { [weak self] in
                self?.objectWillChange.send()
            }
            .store(in: &c)
        permissionsManager.objectWillChange
            .sink { [weak self] in
                self?.objectWillChange.send()
            }
            .store(in: &c)
        settingsManager.objectWillChange
            .sink { [weak self] in
                self?.objectWillChange.send()
            }
            .store(in: &c)
        updatesManager.objectWillChange
            .sink { [weak self] in
                self?.objectWillChange.send()
            }
            .store(in: &c)

        cancellables = c
    }

    /// Sets up the app state.
    func performSetup() {
        configureCancellables()
        permissionsManager.stopAllChecks()
        menuBarManager.performSetup()
        appearanceManager.performSetup()
        eventManager.performSetup()
        settingsManager.performSetup()
        itemManager.performSetup()
        imageCache.performSetup()
        updatesManager.performSetup()
        userNotificationManager.performSetup()
    }

    /// Assigns the app delegate to the app state.
    func assignAppDelegate(_ appDelegate: AppDelegate) {
        guard self.appDelegate == nil else {
            Logger.appState.warning("Multiple attempts made to assign app delegate")
            return
        }
        self.appDelegate = appDelegate
    }

    /// Assigns the settings window to the app state.
    func assignSettingsWindow(_ window: NSWindow) {
        guard window.identifier?.rawValue == Constants.settingsWindowID else {
            Logger.appState.warning("Window \(window.identifier?.rawValue ?? "<NIL>") is not the settings window!")
            return
        }
        settingsWindow = window
        configureCancellables()
    }

    /// Assigns the permissions window to the app state.
    func assignPermissionsWindow(_ window: NSWindow) {
        guard window.identifier?.rawValue == Constants.permissionsWindowID else {
            Logger.appState.warning("Window \(window.identifier?.rawValue ?? "<NIL>") is not the permissions window!")
            return
        }
        permissionsWindow = window
        configureCancellables()
    }

    /// Opens the settings window.
    func openSettingsWindow() {
        with(EnvironmentValues()) { environment in
            environment.openWindow(id: Constants.settingsWindowID)
        }
    }

    /// Dismisses the settings window.
    func dismissSettingsWindow() {
        with(EnvironmentValues()) { environment in
            environment.dismissWindow(id: Constants.settingsWindowID)
        }
    }

    /// Opens the permissions window.
    func openPermissionsWindow() {
        with(EnvironmentValues()) { environment in
            environment.openWindow(id: Constants.permissionsWindowID)
        }
    }

    /// Dismisses the permissions window.
    func dismissPermissionsWindow() {
        with(EnvironmentValues()) { environment in
            environment.dismissWindow(id: Constants.permissionsWindowID)
        }
    }

    /// Activates the app and sets its activation policy to the given value.
    func activate(withPolicy policy: NSApplication.ActivationPolicy) {
        // Store whether the app has previously activated inside an internal
        // context to keep it isolated.
        enum Context {
            static let hasActivated = ObjectStorage<Bool>()
        }

        func activate() {
            if let frontApp = NSWorkspace.shared.frontmostApplication {
                NSRunningApplication.current.activate(from: frontApp)
            } else {
                NSApp.activate()
            }
            NSApp.setActivationPolicy(policy)
        }

        if Context.hasActivated.value(for: self) == true {
            activate()
        } else {
            Context.hasActivated.set(true, for: self)
            Logger.appState.debug("First time activating app, so going through Dock")
            // Hack to make sure the app properly activates for the first time.
            NSRunningApplication.runningApplications(withBundleIdentifier: "com.apple.dock").first?.activate()
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                activate()
            }
        }
    }

    /// Deactivates the app and sets its activation policy to the given value.
    func deactivate(withPolicy policy: NSApplication.ActivationPolicy) {
        if let nextApp = NSWorkspace.shared.runningApplications.first(where: { $0 != .current }) {
            NSApp.yieldActivation(to: nextApp)
        } else {
            NSApp.deactivate()
        }
        NSApp.setActivationPolicy(policy)
    }

    /// Prevents the "ShowOnHover" feature.
    func preventShowOnHover() {
        isShowOnHoverPrevented = true
    }

    /// Allows the "ShowOnHover" feature.
    func allowShowOnHover() {
        isShowOnHoverPrevented = false
    }
}

// MARK: AppState: BindingExposable
extension AppState: BindingExposable { }

// MARK: - Logger
private extension Logger {
    /// The logger to use for the app state.
    static let appState = Logger(category: "AppState")
}


================================================
FILE: Ice/Main/IceApp.swift
================================================
//
//  IceApp.swift
//  Ice
//

import SwiftUI

@main
struct IceApp: App {
    @NSApplicationDelegateAdaptor var appDelegate: AppDelegate
    @ObservedObject var appState = AppState()

    init() {
        NSSplitViewItem.swizzle()
        MigrationManager.migrateAll(appState: appState)
        appDelegate.assignAppState(appState)
    }

    var body: some Scene {
        SettingsWindow(appState: appState)
        PermissionsWindow(appState: appState)
    }
}


================================================
FILE: Ice/Main/Navigation/AppNavigationState.swift
================================================
//
//  AppNavigationState.swift
//  Ice
//

import Combine

/// The model for app-wide navigation.
@MainActor
final class AppNavigationState: ObservableObject {
    @Published var isAppFrontmost = false
    @Published var isSettingsPresented = false
    @Published var isIceBarPresented = false
    @Published var isSearchPresented = false
    @Published var settingsNavigationIdentifier: SettingsNavigationIdentifier = .general
}


================================================
FILE: Ice/Main/Navigation/NavigationIdentifiers/NavigationIdentifier.swift
================================================
//
//  NavigationIdentifier.swift
//  Ice
//

import SwiftUI

/// A type that represents an identifier used for navigation in a user interface.
protocol NavigationIdentifier: CaseIterable, Hashable, Identifiable, RawRepresentable {
    /// A localized description of the identifier that can be presented to the user.
    var localized: LocalizedStringKey { get }
}

extension NavigationIdentifier where ID == Int {
    var id: Int { hashValue }
}

extension NavigationIdentifier where RawValue == String {
    var localized: LocalizedStringKey { LocalizedStringKey(rawValue) }
}


================================================
FILE: Ice/Main/Navigation/NavigationIdentifiers/SettingsNavigationIdentifier.swift
================================================
//
//  SettingsNavigationIdentifier.swift
//  Ice
//

/// An identifier used for navigation in the settings interface.
enum SettingsNavigationIdentifier: String, NavigationIdentifier {
    case general = "General"
    case menuBarLayout = "Menu Bar Layout"
    case menuBarAppearance = "Menu Bar Appearance"
    case hotkeys = "Hotkeys"
    case advanced = "Advanced"
    case about = "About"
}


================================================
FILE: Ice/MenuBar/Appearance/Configurations/MenuBarAppearanceConfigurationV1.swift
================================================
//
//  MenuBarAppearanceConfigurationV1.swift
//  Ice
//

import CoreGraphics
import Foundation

/// Configuration for the menu bar's appearance.
struct MenuBarAppearanceConfigurationV1: Hashable {
    var hasShadow: Bool
    var hasBorder: Bool
    var isInset: Bool
    var borderColor: CGColor
    var borderWidth: Double
    var shapeKind: MenuBarShapeKind
    var fullShapeInfo: MenuBarFullShapeInfo
    var splitShapeInfo: MenuBarSplitShapeInfo
    var tintKind: MenuBarTintKind
    var tintColor: CGColor
    var tintGradient: CustomGradient

    var hasRoundedShape: Bool {
        switch shapeKind {
        case .none: false
        case .full: fullShapeInfo.hasRoundedShape
        case .split: splitShapeInfo.hasRoundedShape
        }
    }

    /// Creates a configuration by migrating from the deprecated appearance-related
    /// keys stored in `UserDefaults`, storing the new configuration and deleting
    /// the deprecated keys.
    static func migrate(encoder: JSONEncoder, decoder: JSONDecoder) throws -> Self {
        // Try to load an already migrated configuration first. Otherwise, load each
        // value from the deprecated keys.
        if let data = Defaults.data(forKey: .menuBarAppearanceConfiguration) {
            return try decoder.decode(Self.self, from: data)
        } else {
            var configuration = Self.defaultConfiguration

            Defaults.ifPresent(key: .menuBarHasShadow, assign: &configuration.hasShadow)
            Defaults.ifPresent(key: .menuBarHasBorder, assign: &configuration.hasBorder)
            Defaults.ifPresent(key: .menuBarBorderWidth, assign: &configuration.borderWidth)
            Defaults.ifPresent(key: .menuBarTintKind) { rawValue in
                if let tintKind = MenuBarTintKind(rawValue: rawValue) {
                    configuration.tintKind = tintKind
                }
            }

            if let borderColorData = Defaults.data(forKey: .menuBarBorderColor) {
                configuration.borderColor = try decoder.decode(CodableColor.self, from: borderColorData).cgColor
            }
            if let tintColorData = Defaults.data(forKey: .menuBarTintColor) {
                configuration.tintColor = try decoder.decode(CodableColor.self, from: tintColorData).cgColor
            }
            if let tintGradientData = Defaults.data(forKey: .menuBarTintGradient) {
                configuration.tintGradient = try decoder.decode(CustomGradient.self, from: tintGradientData)
            }
            if let shapeKindData = Defaults.data(forKey: .menuBarShapeKind) {
                configuration.shapeKind = try decoder.decode(MenuBarShapeKind.self, from: shapeKindData)
            }
            if let fullShapeData = Defaults.data(forKey: .menuBarFullShapeInfo) {
                configuration.fullShapeInfo = try decoder.decode(MenuBarFullShapeInfo.self, from: fullShapeData)
            }
            if let splitShapeData = Defaults.data(forKey: .menuBarSplitShapeInfo) {
                configuration.splitShapeInfo = try decoder.decode(MenuBarSplitShapeInfo.self, from: splitShapeData)
            }

            // Store the configuration to complete the migration.
            let configurationData = try encoder.encode(configuration)
            Defaults.set(configurationData, forKey: .menuBarAppearanceConfiguration)

            // Remove the deprecated keys.
            let keys: [Defaults.Key] = [
                .menuBarHasShadow,
                .menuBarHasBorder,
                .menuBarBorderWidth,
                .menuBarTintKind,
                .menuBarBorderColor,
                .menuBarTintColor,
                .menuBarTintGradient,
                .menuBarShapeKind,
                .menuBarFullShapeInfo,
                .menuBarSplitShapeInfo,
            ]
            for key in keys {
                Defaults.removeObject(forKey: key)
            }

            return configuration
        }
    }
}

// MARK: Default Configuration
extension MenuBarAppearanceConfigurationV1 {
    static let defaultConfiguration = MenuBarAppearanceConfigurationV1(
        hasShadow: false,
        hasBorder: false,
        isInset: true,
        borderColor: .black,
        borderWidth: 1,
        shapeKind: .none,
        fullShapeInfo: .default,
        splitShapeInfo: .default,
        tintKind: .none,
        tintColor: .black,
        tintGradient: .defaultMenuBarTint
    )
}

// MARK: MenuBarAppearanceConfigurationV1: Codable
extension MenuBarAppearanceConfigurationV1: Codable {
    private enum CodingKeys: CodingKey {
        case hasShadow
        case hasBorder
        case isInset
        case borderColor
        case borderWidth
        case shapeKind
        case fullShapeInfo
        case splitShapeInfo
        case tintKind
        case tintColor
        case tintGradient
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        try self.init(
            hasShadow: container.decodeIfPresent(Bool.self, forKey: .hasShadow) ?? Self.defaultConfiguration.hasShadow,
            hasBorder: container.decodeIfPresent(Bool.self, forKey: .hasBorder) ?? Self.defaultConfiguration.hasBorder,
            isInset: container.decodeIfPresent(Bool.self, forKey: .isInset) ?? Self.defaultConfiguration.isInset,
            borderColor: container.decodeIfPresent(CodableColor.self, forKey: .borderColor)?.cgColor ?? Self.defaultConfiguration.borderColor,
            borderWidth: container.decodeIfPresent(Double.self, forKey: .borderWidth) ?? Self.defaultConfiguration.borderWidth,
            shapeKind: container.decodeIfPresent(MenuBarShapeKind.self, forKey: .shapeKind) ?? Self.defaultConfiguration.shapeKind,
            fullShapeInfo: container.decodeIfPresent(MenuBarFullShapeInfo.self, forKey: .fullShapeInfo) ?? Self.defaultConfiguration.fullShapeInfo,
            splitShapeInfo: container.decodeIfPresent(MenuBarSplitShapeInfo.self, forKey: .splitShapeInfo) ?? Self.defaultConfiguration.splitShapeInfo,
            tintKind: container.decodeIfPresent(MenuBarTintKind.self, forKey: .tintKind) ?? Self.defaultConfiguration.tintKind,
            tintColor: container.decodeIfPresent(CodableColor.self, forKey: .tintColor)?.cgColor ?? Self.defaultConfiguration.tintColor,
            tintGradient: container.decodeIfPresent(CustomGradient.self, forKey: .tintGradient) ?? Self.defaultConfiguration.tintGradient
        )
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(hasShadow, forKey: .hasShadow)
        try container.encode(hasBorder, forKey: .hasBorder)
        try container.encode(isInset, forKey: .isInset)
        try container.encode(CodableColor(cgColor: borderColor), forKey: .borderColor)
        try container.encode(borderWidth, forKey: .borderWidth)
        try container.encode(shapeKind, forKey: .shapeKind)
        try container.encode(fullShapeInfo, forKey: .fullShapeInfo)
        try container.encode(splitShapeInfo, forKey: .splitShapeInfo)
        try container.encode(tintKind, forKey: .tintKind)
        try container.encode(CodableColor(cgColor: tintColor), forKey: .tintColor)
        try container.encode(tintGradient, forKey: .tintGradient)
    }
}


================================================
FILE: Ice/MenuBar/Appearance/Configurations/MenuBarAppearanceConfigurationV2.swift
================================================
//
//  MenuBarAppearanceConfigurationV2.swift
//  Ice
//

import CoreGraphics
import Foundation

struct MenuBarAppearanceConfigurationV2: Hashable {
    var lightModeConfiguration: MenuBarAppearancePartialConfiguration
    var darkModeConfiguration: MenuBarAppearancePartialConfiguration
    var staticConfiguration: MenuBarAppearancePartialConfiguration
    var shapeKind: MenuBarShapeKind
    var fullShapeInfo: MenuBarFullShapeInfo
    var splitShapeInfo: MenuBarSplitShapeInfo
    var isInset: Bool
    var isDynamic: Bool

    var hasRoundedShape: Bool {
        switch shapeKind {
        case .none: false
        case .full: fullShapeInfo.hasRoundedShape
        case .split: splitShapeInfo.hasRoundedShape
        }
    }

    var current: MenuBarAppearancePartialConfiguration {
        if isDynamic {
            switch SystemAppearance.current {
            case .light: lightModeConfiguration
            case .dark: darkModeConfiguration
            }
        } else {
            staticConfiguration
        }
    }
}

// MARK: Default Configuration
extension MenuBarAppearanceConfigurationV2 {
    static let defaultConfiguration = MenuBarAppearanceConfigurationV2(
        lightModeConfiguration: .defaultConfiguration,
        darkModeConfiguration: .defaultConfiguration,
        staticConfiguration: .defaultConfiguration,
        shapeKind: .none,
        fullShapeInfo: .default,
        splitShapeInfo: .default,
        isInset: true,
        isDynamic: false
    )
}

extension MenuBarAppearanceConfigurationV2: Codable {
    private enum CodingKeys: CodingKey {
        case lightModeConfiguration
        case darkModeConfiguration
        case staticConfiguration
        case shapeKind
        case fullShapeInfo
        case splitShapeInfo
        case isInset
        case isDynamic
    }

    init(from decoder: any Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        try self.init(
            lightModeConfiguration: container.decodeIfPresent(MenuBarAppearancePartialConfiguration.self, forKey: .lightModeConfiguration) ?? Self.defaultConfiguration.lightModeConfiguration,
            darkModeConfiguration: container.decodeIfPresent(MenuBarAppearancePartialConfiguration.self, forKey: .darkModeConfiguration) ?? Self.defaultConfiguration.darkModeConfiguration,
            staticConfiguration: container.decodeIfPresent(MenuBarAppearancePartialConfiguration.self, forKey: .staticConfiguration) ?? Self.defaultConfiguration.staticConfiguration,
            shapeKind: container.decodeIfPresent(MenuBarShapeKind.self, forKey: .shapeKind) ?? Self.defaultConfiguration.shapeKind,
            fullShapeInfo: container.decodeIfPresent(MenuBarFullShapeInfo.self, forKey: .fullShapeInfo) ?? Self.defaultConfiguration.fullShapeInfo,
            splitShapeInfo: container.decodeIfPresent(MenuBarSplitShapeInfo.self, forKey: .splitShapeInfo) ?? Self.defaultConfiguration.splitShapeInfo,
            isInset: container.decodeIfPresent(Bool.self, forKey: .isInset) ?? Self.defaultConfiguration.isInset,
            isDynamic: container.decodeIfPresent(Bool.self, forKey: .isDynamic) ?? Self.defaultConfiguration.isDynamic
        )
    }

    func encode(to encoder: any Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(lightModeConfiguration, forKey: .lightModeConfiguration)
        try container.encode(darkModeConfiguration, forKey: .darkModeConfiguration)
        try container.encode(staticConfiguration, forKey: .staticConfiguration)
        try container.encode(shapeKind, forKey: .shapeKind)
        try container.encode(fullShapeInfo, forKey: .fullShapeInfo)
        try container.encode(splitShapeInfo, forKey: .splitShapeInfo)
        try container.encode(isInset, forKey: .isInset)
        try container.encode(isDynamic, forKey: .isDynamic)
    }
}

// MARK: - MenuBarAppearancePartialConfiguration

struct MenuBarAppearancePartialConfiguration: Hashable {
    var hasShadow: Bool
    var hasBorder: Bool
    var borderColor: CGColor
    var borderWidth: Double
    var tintKind: MenuBarTintKind
    var tintColor: CGColor
    var tintGradient: CustomGradient
}

// MARK: Default Partial Configuration
extension MenuBarAppearancePartialConfiguration {
    static let defaultConfiguration = MenuBarAppearancePartialConfiguration(
        hasShadow: false,
        hasBorder: false,
        borderColor: .black,
        borderWidth: 1,
        tintKind: .none,
        tintColor: .black,
        tintGradient: .defaultMenuBarTint
    )
}

// MARK: MenuBarAppearancePartialConfiguration: Codable
extension MenuBarAppearancePartialConfiguration: Codable {
    private enum CodingKeys: CodingKey {
        case hasShadow
        case hasBorder
        case borderColor
        case borderWidth
        case shapeKind
        case fullShapeInfo
        case splitShapeInfo
        case tintKind
        case tintColor
        case tintGradient
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        try self.init(
            hasShadow: container.decodeIfPresent(Bool.self, forKey: .hasShadow) ?? Self.defaultConfiguration.hasShadow,
            hasBorder: container.decodeIfPresent(Bool.self, forKey: .hasBorder) ?? Self.defaultConfiguration.hasBorder,
            borderColor: container.decodeIfPresent(CodableColor.self, forKey: .borderColor)?.cgColor ?? Self.defaultConfiguration.borderColor,
            borderWidth: container.decodeIfPresent(Double.self, forKey: .borderWidth) ?? Self.defaultConfiguration.borderWidth,
            tintKind: container.decodeIfPresent(MenuBarTintKind.self, forKey: .tintKind) ?? Self.defaultConfiguration.tintKind,
            tintColor: container.decodeIfPresent(CodableColor.self, forKey: .tintColor)?.cgColor ?? Self.defaultConfiguration.tintColor,
            tintGradient: container.decodeIfPresent(CustomGradient.self, forKey: .tintGradient) ?? Self.defaultConfiguration.tintGradient
        )
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(hasShadow, forKey: .hasShadow)
        try container.encode(hasBorder, forKey: .hasBorder)
        try container.encode(CodableColor(cgColor: borderColor), forKey: .borderColor)
        try container.encode(borderWidth, forKey: .borderWidth)
        try container.encode(tintKind, forKey: .tintKind)
        try container.encode(CodableColor(cgColor: tintColor), forKey: .tintColor)
        try container.encode(tintGradient, forKey: .tintGradient)
    }
}


================================================
FILE: Ice/MenuBar/Appearance/MenuBarAppearanceEditor/MenuBarAppearanceEditor.swift
================================================
//
//  MenuBarAppearanceEditor.swift
//  Ice
//

import SwiftUI

struct MenuBarAppearanceEditor: View {
    enum Location {
        case settings
        case popover(closePopover: () -> Void)
    }

    @EnvironmentObject var appState: AppState
    @EnvironmentObject var appearanceManager: MenuBarAppearanceManager

    let location: Location

    private var mainFormPadding: EdgeInsets {
        with(EdgeInsets(all: 20)) { insets in
            switch location {
            case .settings: break
            case .popover: insets.top = 0
            }
        }
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 0) {
            stackHeader
            stackBody
        }
    }

    @ViewBuilder
    private var stackHeader: some View {
        if case .popover(let closePopover) = location {
            ZStack {
                Text("Menu Bar Appearance")
                    .font(.title2)
                    .frame(maxWidth: .infinity, alignment: .center)
                Button("Done", action: closePopover)
                    .controlSize(.large)
                    .frame(maxWidth: .infinity, alignment: .trailing)
            }
            .padding(20)
        }
    }

    @ViewBuilder
    private var stackBody: some View {
        if appState.menuBarManager.isMenuBarHiddenBySystemUserDefaults {
            cannotEdit
        } else {
            mainForm
        }
    }

    @ViewBuilder
    private var mainForm: some View {
        IceForm(padding: mainFormPadding) {
            IceSection {
                isDynamicToggle
            }
            if appearanceManager.configuration.isDynamic {
                LabeledPartialEditor(appearance: .light)
                LabeledPartialEditor(appearance: .dark)
            } else {
                StaticPartialEditor()
            }
            IceSection("Menu Bar Shape") {
                shapePicker
                isInset
            }
            if case .settings = location {
                IceGroupBox {
                    AnnotationView(
                        alignment: .center,
                        font: .callout.bold()
                    ) {
                        Label {
                            Text("Tip: you can also edit these settings by right-clicking in an empty area of the menu bar")
                        } icon: {
                            Image(systemName: "lightbulb")
                        }
                    }
                }
            }
            if
                !appState.menuBarManager.isMenuBarHiddenBySystemUserDefaults,
                appearanceManager.configuration != .defaultConfiguration
            {
                Button("Reset") {
                    appearanceManager.configuration = .defaultConfiguration
                }
                .controlSize(.large)
                .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomLeading)
            }
        }
    }

    @ViewBuilder
    private var isDynamicToggle: some View {
        Toggle("Use dynamic appearance", isOn: appearanceManager.bindings.configuration.isDynamic)
            .annotation("Apply different settings based on the current system appearance")
    }

    @ViewBuilder
    private var cannotEdit: some View {
        Text("Ice cannot edit the appearance of automatically hidden menu bars")
            .font(.title3)
            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
    }

    @ViewBuilder
    private var shapePicker: some View {
        MenuBarShapePicker()
            .fixedSize(horizontal: false, vertical: true)
    }

    @ViewBuilder
    private var isInset: some View {
        if appearanceManager.configuration.shapeKind != .none {
            Toggle(
                "Use inset shape on screens with notch",
                isOn: appearanceManager.bindings.configuration.isInset
            )
        }
    }
}

private struct UnlabeledPartialEditor: View {
    @Binding var configuration: MenuBarAppearancePartialConfiguration

    var body: some View {
        IceSection {
            tintPicker
            shadowToggle
        }
        IceSection {
            borderToggle
            borderColor
            borderWidth
        }
    }

    @ViewBuilder
    private var tintPicker: some View {
        IceLabeledContent("Tint") {
            HStack {
                IcePicker("Tint", selection: $configuration.tintKind) {
                    ForEach(MenuBarTintKind.allCases) { tintKind in
                        Text(tintKind.localized).tag(tintKind)
                    }
                }
                .labelsHidden()

                switch configuration.tintKind {
                case .none:
                    EmptyView()
                case .solid:
                    CustomColorPicker(
                        selection: $configuration.tintColor,
                        supportsOpacity: false,
                        mode: .crayon
                    )
                case .gradient:
                    CustomGradientPicker(
                        gradient: $configuration.tintGradient,
                        supportsOpacity: false,
                        allowsEmptySelections: false,
                        mode: .crayon
                    )
                }
            }
            .frame(height: 24)
        }
    }

    @ViewBuilder
    private var shadowToggle: some View {
        Toggle("Shadow", isOn: $configuration.hasShadow)
    }

    @ViewBuilder
    private var borderToggle: some View {
        Toggle("Border", isOn: $configuration.hasBorder)
    }

    @ViewBuilder
    private var borderColor: some View {
        if configuration.hasBorder {
            IceLabeledContent("Border Color") {
                CustomColorPicker(
                    selection: $configuration.borderColor,
                    supportsOpacity: true,
                    mode: .crayon
                )
            }
        }
    }

    @ViewBuilder
    private var borderWidth: some View {
        if configuration.hasBorder {
            IcePicker(
                "Border Width",
                selection: $configuration.borderWidth
            ) {
                Text("1").tag(1.0)
                Text("2").tag(2.0)
                Text("3").tag(3.0)
            }
        }
    }
}

private struct LabeledPartialEditor: View {
    @EnvironmentObject var appearanceManager: MenuBarAppearanceManager
    @State private var currentAppearance = SystemAppearance.current
    @State private var textFrame = CGRect.zero

    let appearance: SystemAppearance

    var body: some View {
        IceSection(options: .plain) {
            labelStack
        } content: {
            partialEditor
        }
        .onReceive(NSApp.publisher(for: \.effectiveAppearance)) { _ in
            currentAppearance = .current
        }
    }

    @ViewBuilder
    private var labelStack: some View {
        HStack {
            Text(appearance.titleKey)
                .font(.headline)
                .onFrameChange(update: $textFrame)

            if currentAppearance != appearance {
                previewButton
            }
        }
        .frame(height: textFrame.height)
    }

    @ViewBuilder
    private var previewButton: some View {
        switch appearance {
        case .light:
            PreviewButton(configuration: appearanceManager.configuration.lightModeConfiguration)
        case .dark:
            PreviewButton(configuration: appearanceManager.configuration.darkModeConfiguration)
        }
    }

    @ViewBuilder
    private var partialEditor: some View {
        switch appearance {
        case .light:
            UnlabeledPartialEditor(configuration: appearanceManager.bindings.configuration.lightModeConfiguration)
        case .dark:
            UnlabeledPartialEditor(configuration: appearanceManager.bindings.configuration.darkModeConfiguration)
        }
    }
}

private struct StaticPartialEditor: View {
    @EnvironmentObject var appearanceManager: MenuBarAppearanceManager

    var body: some View {
        UnlabeledPartialEditor(configuration: appearanceManager.bindings.configuration.staticConfiguration)
    }
}

private struct PreviewButton: View {
    private struct DummyButton: NSViewRepresentable {
        @Binding var isPressed: Bool

        func makeNSView(context: Context) -> NSButton {
            let button = NSButton()
            button.title = ""
            button.bezelStyle = .accessoryBarAction
            return button
        }

        func updateNSView(_ nsView: NSButton, context: Context) {
            nsView.isHighlighted = isPressed
        }
    }

    @EnvironmentObject var appearanceManager: MenuBarAppearanceManager

    @State private var frame = CGRect.zero
    @State private var isPressed = false

    let configuration: MenuBarAppearancePartialConfiguration

    var body: some View {
        ZStack {
            DummyButton(isPressed: $isPressed)
                .allowsHitTesting(false)
            Text("Hold to Preview")
                .baselineOffset(1.5)
                .padding(.horizontal, 10)
                .contentShape(Rectangle())
        }
        .fixedSize()
        .simultaneousGesture(
            DragGesture(minimumDistance: 0)
                .onChanged { value in
                    isPressed = frame.contains(value.location)
                }
                .onEnded { _ in
                    isPressed = false
                }
        )
        .onChange(of: isPressed) { _, newValue in
            appearanceManager.previewConfiguration = newValue ? configuration : nil
        }
        .onFrameChange(update: $frame)
    }
}


================================================
FILE: Ice/MenuBar/Appearance/MenuBarAppearanceEditor/MenuBarAppearanceEditorPanel.swift
================================================
//
//  MenuBarAppearanceEditorPanel.swift
//  Ice
//

import Combine
import SwiftUI

// MARK: - MenuBarAppearanceEditorPanel

/// A panel that manages the appearance editor popover.
final class MenuBarAppearanceEditorPanel: NSPanel {
    /// The shared app state.
    private weak var appState: AppState?

    /// Storage for internal observers.
    private var cancellables = Set<AnyCancellable>()

    init(appState: AppState) {
        super.init(
            contentRect: CGRect(x: 0, y: 0, width: 1, height: 1),
            styleMask: [.borderless, .nonactivatingPanel],
            backing: .buffered,
            defer: false
        )
        self.appState = appState
        self.isFloatingPanel = true
        self.backgroundColor = .clear
        configureCancellables()
    }

    private func configureCancellables() {
        var c = Set<AnyCancellable>()

        NSWorkspace.shared.notificationCenter
            .publisher(for: NSWorkspace.activeSpaceDidChangeNotification)
            .sink { [weak self] _ in
                self?.orderOut(self)
                NSColorPanel.shared.close()
                NSColorPanel.shared.hidesOnDeactivate = true
            }
            .store(in: &c)

        cancellables = c
    }

    /// Shows the appearance editor popover.
    func showAppearanceEditorPopover() {
        guard
            let appState,
            let contentView,
            let screen = NSScreen.screens.first(where: { $0.frame.contains(NSEvent.mouseLocation) }),
            let menuBarHeight = NSApp.mainMenu?.menuBarHeight
        else {
            return
        }
        setFrameOrigin(CGPoint(x: screen.frame.midX - frame.width / 2, y: screen.frame.maxY - menuBarHeight))
        let popover = MenuBarAppearanceEditorPopover(appState: appState)
        popover.delegate = self
        popover.show(relativeTo: .zero, of: contentView, preferredEdge: .minY)
        popover.contentViewController?.view.window?.makeKey()
        NSColorPanel.shared.hidesOnDeactivate = false
    }
}

// MARK: MenuBarAppearanceEditorPanel: NSPopoverDelegate
extension MenuBarAppearanceEditorPanel: NSPopoverDelegate {
    func popoverDidClose(_ notification: Notification) {
        if let popover = notification.object as? MenuBarAppearanceEditorPopover {
            popover.mouseDownMonitor.stop()
            orderOut(popover)
            NSColorPanel.shared.close()
            NSColorPanel.shared.hidesOnDeactivate = true
        }
    }
}

// MARK: - MenuBarAppearanceEditorPopover

/// A popover that displays the menu bar appearance editor
/// at a centered location under the menu bar.
private final class MenuBarAppearanceEditorPopover: NSPopover {
    private weak var appState: AppState?

    private(set) lazy var mouseDownMonitor = GlobalEventMonitor(mask: .leftMouseDown) { [weak self] _ in
        self?.performClose(self)
    }

    @ViewBuilder
    private var contentView: some View {
        if let appState {
            MenuBarAppearanceEditor(
                location: .popover(closePopover: { [weak self] in
                    self?.performClose(self)
                })
            )
            .environmentObject(appState)
            .environmentObject(appState.appearanceManager)
        }
    }

    init(appState: AppState) {
        super.init()
        self.appState = appState
        self.contentViewController = NSHostingController(rootView: contentView)
        self.contentSize = CGSize(width: 550, height: 600)
        self.behavior = .applicationDefined
        self.mouseDownMonitor.start()
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}


================================================
FILE: Ice/MenuBar/Appearance/MenuBarAppearanceEditor/MenuBarShapePicker.swift
================================================
//
//  MenuBarShapePicker.swift
//  Ice
//

import SwiftUI

struct MenuBarShapePicker: View {
    @EnvironmentObject var appearanceManager: MenuBarAppearanceManager
    @Environment(\.colorScheme) private var colorScheme

    var body: some View {
        shapeKindPicker
        exampleView
    }

    @ViewBuilder
    private var shapeKindPicker: some View {
        IcePicker("Shape Kind", selection: appearanceManager.bindings.configuration.shapeKind) {
            ForEach(MenuBarShapeKind.allCases, id: \.self) { shape in
                switch shape {
                case .none:
                    Text("None").tag(shape)
                case .full:
                    Text("Full").tag(shape)
                case .split:
                    Text("Split").tag(shape)
                }
            }
        }
    }

    @ViewBuilder
    private var exampleView: some View {
        switch appearanceManager.configuration.shapeKind {
        case .none:
            Text("No shape kind selected")
                .foregroundStyle(.secondary)
                .frame(maxWidth: .infinity, alignment: .center)
        case .full:
            MenuBarFullShapeExampleView(info: appearanceManager.bindings.configuration.fullShapeInfo)
                .equatable()
                .foregroundStyle(colorScheme == .dark ? .primary : .secondary)
        case .split:
            MenuBarSplitShapeExampleView(info: appearanceManager.bindings.configuration.splitShapeInfo)
                .equatable()
                .foregroundStyle(colorScheme == .dark ? .primary : .secondary)
        }
    }
}

private struct MenuBarFullShapeExampleView: View, Equatable {
    @Binding var info: MenuBarFullShapeInfo

    var body: some View {
        VStack {
            pickerStack
            exampleStack
        }
    }

    @ViewBuilder
    private var pickerStack: some View {
        HStack(spacing: 0) {
            leadingEndCapPicker
            Spacer()
            trailingEndCapPicker
        }
        .labelsHidden()
        .pickerStyle(.segmented)
    }

    @ViewBuilder
    private var exampleStack: some View {
        HStack(spacing: 0) {
            leadingEndCapExample
            Rectangle()
            trailingEndCapExample
        }
        .frame(height: 24)
    }

    @ViewBuilder
    private func endCapPickerContentView(endCap: MenuBarEndCap, edge: HorizontalEdge) -> some View {
        switch endCap {
        case .square:
            Image(size: CGSize(width: 12, height: 12)) { context in
                context.fill(Path(context.clipBoundingRect), with: .foreground)
            }
            .resizable()
            .help("Square Cap")
            .tag(endCap)
        case .round:
            Image(size: CGSize(width: 12, height: 12)) { context in
                let remainder = context.clipBoundingRect
                    .divided(atDistance: context.clipBoundingRect.width / 2, from: cgRectEdge(for: edge))
                    .remainder
                let path1 = Path(remainder)
                let path2 = Path(ellipseIn: context.clipBoundingRect)
                context.fill(path1.union(path2), with: .foreground)
            }
            .resizable()
            .help("Round Cap")
            .tag(endCap)
        }
    }

    @ViewBuilder
    private var leadingEndCapPicker: some View {
        Picker("Leading End Cap", selection: $info.leadingEndCap) {
            ForEach(MenuBarEndCap.allCases.reversed(), id: \.self) { endCap in
                endCapPickerContentView(endCap: endCap, edge: .leading)
            }
        }
        .fixedSize()
    }

    @ViewBuilder
    private var trailingEndCapPicker: some View {
        Picker("Trailing End Cap", selection: $info.trailingEndCap) {
            ForEach(MenuBarEndCap.allCases, id: \.self) { endCap in
                endCapPickerContentView(endCap: endCap, edge: .trailing)
            }
        }
        .fixedSize()
    }

    @ViewBuilder
    private var leadingEndCapExample: some View {
        MenuBarEndCapExampleView(
            endCap: info.leadingEndCap,
            edge: .leading
        )
    }

    @ViewBuilder
    private var trailingEndCapExample: some View {
        MenuBarEndCapExampleView(
            endCap: info.trailingEndCap,
            edge: .trailing
        )
    }

    static func == (lhs: Self, rhs: Self) -> Bool {
        lhs.info == rhs.info
    }

    private func cgRectEdge(for edge: HorizontalEdge) -> CGRectEdge {
        switch edge {
        case .leading: .minXEdge
        case .trailing: .maxXEdge
        }
    }
}

private struct MenuBarEndCapExampleView: View {
    @State private var radius: CGFloat = 0

    let endCap: MenuBarEndCap
    let edge: HorizontalEdge

    var body: some View {
        switch endCap {
        case .square:
            Rectangle()
        case .round:
            switch edge {
            case .leading:
                UnevenRoundedRectangle(
                    topLeadingRadius: radius,
                    bottomLeadingRadius: radius,
                    style: .circular
                )
                .onFrameChange { frame in
                    radius = frame.height / 2
                }
            case .trailing:
                UnevenRoundedRectangle(
                    bottomTrailingRadius: radius,
                    topTrailingRadius: radius,
                    style: .circular
                )
                .onFrameChange { frame in
                    radius = frame.height / 2
                }
            }
        }
    }
}

private struct MenuBarSplitShapeExampleView: View, Equatable {
    @Binding var info: MenuBarSplitShapeInfo

    var body: some View {
        HStack {
            MenuBarFullShapeExampleView(info: $info.leading)
                .equatable()
            Divider()
                .padding(.horizontal)
            MenuBarFullShapeExampleView(info: $info.trailing)
                .equatable()
        }
    }

    static func == (lhs: Self, rhs: Self) -> Bool {
        lhs.info == rhs.info
    }
}


================================================
FILE: Ice/MenuBar/Appearance/MenuBarAppearanceManager.swift
================================================
//
//  MenuBarAppearanceManager.swift
//  Ice
//

import Cocoa
import Combine

/// A manager for the appearance of the menu bar.
@MainActor
final class MenuBarAppearanceManager: ObservableObject {
    /// The current menu bar appearance configuration.
    @Published var configuration: MenuBarAppearanceConfigurationV2 = .defaultConfiguration

    /// The currently previewed partial configuration.
    @Published var previewConfiguration: MenuBarAppearancePartialConfiguration?

    /// The shared app state.
    private weak var appState: AppState?

    /// Encoder for UserDefaults values.
    private let encoder = JSONEncoder()

    /// Decoder for UserDefaults values.
    private let decoder = JSONDecoder()

    /// Storage for internal observers.
    private var cancellables = Set<AnyCancellable>()

    /// The currently managed menu bar overlay panels.
    private(set) var overlayPanels = Set<MenuBarOverlayPanel>()

    /// The amount to inset the menu bar if called for by the configuration.
    let menuBarInsetAmount: CGFloat = 5

    /// Creates a manager with the given app state.
    init(appState: AppState) {
        self.appState = appState
    }

    /// Performs initial setup of the manager.
    func performSetup() {
        loadInitialState()
        configureCancellables()
    }

    /// Loads the initial values for the configuration.
    private func loadInitialState() {
        do {
            if let data = Defaults.data(forKey: .menuBarAppearanceConfigurationV2) {
                configuration = try decoder.decode(MenuBarAppearanceConfigurationV2.self, from: data)
            }
        } catch {
            Logger.appearanceManager.error("Error decoding configuration: \(error)")
        }
    }

    /// Configures the internal observers for the manager.
    private func configureCancellables() {
        var c = Set<AnyCancellable>()

        NotificationCenter.default
            .publisher(for: NSApplication.didChangeScreenParametersNotification)
            .debounce(for: 0.1, scheduler: DispatchQueue.main)
            .sink { [weak self] _ in
                guard let self else {
                    return
                }
                while let panel = overlayPanels.popFirst() {
                    panel.orderOut(self)
                }
                if Set(overlayPanels.map { $0.owningScreen }) != Set(NSScreen.screens) {
                    configureOverlayPanels(with: configuration)
                }
            }
            .store(in: &c)

        $configuration
            .encode(encoder: encoder)
            .receive(on: DispatchQueue.main)
            .sink { completion in
                if case .failure(let error) = completion {
                    Logger.appearanceManager.error("Error encoding configuration: \(error)")
                }
            } receiveValue: { data in
                Defaults.set(data, forKey: .menuBarAppearanceConfigurationV2)
            }
            .store(in: &c)

        $configuration
            .throttle(for: 0.1, scheduler: DispatchQueue.main, latest: true)
            .sink { [weak self] configuration in
                guard let self else {
                    return
                }
                // The overlay panels may not have been configured yet. Since some of the
                // properties on the manager might call for them, try to configure now.
                if overlayPanels.isEmpty {
                    configureOverlayPanels(with: configuration)
                }
            }
            .store(in: &c)

        cancellables = c
    }

    /// Returns a Boolean value that indicates whether a set of overlay panels
    /// is needed for the given configuration.
    private func needsOverlayPanels(for configuration: MenuBarAppearanceConfigurationV2) -> Bool {
        let current = configuration.current
        if current.hasShadow {
            return true
        }
        if current.hasBorder {
            return true
        }
        if configuration.shapeKind != .none {
            return true
        }
        if current.tintKind != .none {
            return true
        }
        return false
    }

    /// Configures the manager's overlay panels, if required by the given configuration.
    private func configureOverlayPanels(with configuration: MenuBarAppearanceConfigurationV2) {
        guard
            let appState,
            needsOverlayPanels(for: configuration)
        else {
            while let panel = overlayPanels.popFirst() {
                panel.close()
            }
            return
        }

        var overlayPanels = Set<MenuBarOverlayPanel>()
        for screen in NSScreen.screens {
            let panel = MenuBarOverlayPanel(appState: appState, owningScreen: screen)
            overlayPanels.insert(panel)
            panel.needsShow = true
        }

        self.overlayPanels = overlayPanels
    }

    /// Sets the value of ``MenuBarOverlayPanel/isDraggingMenuBarItem`` for each
    /// of the manager's overlay panels.
    func setIsDraggingMenuBarItem(_ isDragging: Bool) {
        for panel in overlayPanels {
            panel.isDraggingMenuBarItem = isDragging
        }
    }
}

// MARK: MenuBarAppearanceManager: BindingExposable
extension MenuBarAppearanceManager: BindingExposable { }

// MARK: - Logger
private extension Logger {
    /// The logger to use for the menu bar appearance manager.
    static let appearanceManager = Logger(category: "MenuBarAppearanceManager")
}


================================================
FILE: Ice/MenuBar/Appearance/MenuBarOverlayPanel.swift
================================================
//
//  MenuBarOverlayPanel.swift
//  Ice
//

import Cocoa
import Combine

// MARK: - Overlay Panel

/// A subclass of `NSPanel` that sits atop the menu bar to alter its appearance.
final class MenuBarOverlayPanel: NSPanel {
    /// Flags representing the updatable components of a panel.
    enum UpdateFlag: String, CustomStringConvertible {
        case applicationMenuFrame
        case desktopWallpaper

        var description: String { rawValue }
    }

    /// The kind of validation that occurs before an update.
    private enum ValidationKind {
        case showing
        case updates
    }

    /// A context that manages panel update tasks.
    private final class UpdateTaskContext {
        private var tasks = [UpdateFlag: Task<Void, any Error>]()

        /// Sets the task for the given update flag.
        ///
        /// Setting the task cancels the previous task for the flag, if there is one.
        ///
        /// - Parameters:
        ///   - flag: The update flag to set the task for.
        ///   - timeout: The timeout of the task.
        ///   - operation: The operation for the task to perform.
        func setTask(for flag: UpdateFlag, timeout: Duration, operation: @escaping () async throws -> Void) {
            cancelTask(for: flag)
            tasks[flag] = Task.detached(timeout: timeout) {
                try await operation()
            }
        }

        /// Cancels the task for the given update flag.
        ///
        /// - Parameter flag: The update flag to cancel the task for.
        func cancelTask(for flag: UpdateFlag) {
            tasks.removeValue(forKey: flag)?.cancel()
        }
    }

    /// A Boolean value that indicates whether the panel needs to be shown.
    @Published var needsShow = false

    /// A Boolean value that indicates whether the user is dragging a menu bar item.
    @Published var isDraggingMenuBarItem = false

    /// Flags representing the components of the panel currently in need of an update.
    @Published private(set) var updateFlags = Set<UpdateFlag>()

    /// The frame of the application menu.
    @Published private(set) var applicationMenuFrame: CGRect?

    /// The current desktop wallpaper, clipped to the bounds of the menu bar.
    @Published private(set) var desktopWallpaper: CGImage?

    /// Storage for internal observers.
    private var cancellables = Set<AnyCancellable>()

    /// The context that manages panel update tasks.
    private let updateTaskContext = UpdateTaskContext()

    /// The shared app state.
    private(set) weak var appState: AppState?

    /// The screen that owns the panel.
    let owningScreen: NSScreen

    /// Creates an overlay panel with the given app state and owning screen.
    init(appState: AppState, owningScreen: NSScreen) {
        self.appState = appState
        self.owningScreen = owningScreen
        super.init(
            contentRect: .zero,
            styleMask: [.borderless, .fullSizeContentView, .nonactivatingPanel],
            backing: .buffered,
            defer: false
        )
        self.level = .statusBar
        self.title = "Menu Bar Overlay"
        self.backgroundColor = .clear
        self.hasShadow = false
        self.ignoresMouseEvents = true
        self.collectionBehavior = [.fullScreenNone, .ignoresCycle, .moveToActiveSpace]
        self.contentView = MenuBarOverlayPanelContentView()
        configureCancellables()
    }

    private func configureCancellables() {
        var c = Set<AnyCancellable>()

        // Show the panel on the active space.
        NSWorkspace.shared.notificationCenter
            .publisher(for: NSWorkspace.activeSpaceDidChangeNotification)
            .debounce(for: 0.1, scheduler: DispatchQueue.main)
            .sink { [weak self] _ in
                self?.needsShow = true
            }
            .store(in: &c)

        // Update when light/dark mode changes.
        DistributedNotificationCenter.default()
            .publisher(for: DistributedNotificationCenter.interfaceThemeChangedNotification)
            .debounce(for: 0.1, scheduler: DispatchQueue.main)
            .sink { [weak self] _ in
                guard let self else {
                    return
                }
                updateTaskContext.setTask(for: .desktopWallpaper, timeout: .seconds(5)) {
                    while true {
                        try Task.checkCancellation()
                        self.insertUpdateFlag(.desktopWallpaper)
                        try await Task.sleep(for: .seconds(1))
                    }
                }
            }
            .store(in: &c)

        // Update application menu frame when the menu bar owning or frontmost app changes.
        Publishers.Merge(
            NSWorkspace.shared.publisher(for: \.menuBarOwningApplication, options: .old)
                .combineLatest(NSWorkspace.shared.publisher(for: \.menuBarOwningApplication, options: .new))
                .compactMap { $0 == $1 ? nil : $0 },
            NSWorkspace.shared.publisher(for: \.frontmostApplication, options: .old)
                .combineLatest(NSWorkspace.shared.publisher(for: \.frontmostApplication, options: .new))
                .compactMap { $0 == $1 ? nil : $0 }
        )
        .removeDuplicates()
        .sink { [weak self] _ in
            guard
                let self,
                let appState
            else {
                return
            }
            let displayID = owningScreen.displayID
            updateTaskContext.setTask(for: .applicationMenuFrame, timeout: .seconds(10)) {
                var hasDoneInitialUpdate = false
                while true {
                    try Task.checkCancellation()
                    guard
                        let latestFrame = appState.menuBarManager.getApplicationMenuFrame(for: displayID),
                        latestFrame != self.applicationMenuFrame
                    else {
                        if hasDoneInitialUpdate {
                            try await Task.sleep(for: .seconds(1))
                        } else {
                            try await Task.sleep(for: .milliseconds(1))
                        }
                        continue
                    }
                    self.insertUpdateFlag(.applicationMenuFrame)
                    hasDoneInitialUpdate = true
                }
            }
            Task {
                try? await Task.sleep(for: .milliseconds(100))
                if self.owningScreen != NSScreen.main {
                    self.updateTaskContext.cancelTask(for: .applicationMenuFrame)
                }
            }
        }
        .store(in: &c)

        // Special cases for when the user drags an app onto or clicks into another space.
        Publishers.Merge(
            publisher(for: \.isOnActiveSpace)
                .receive(on: DispatchQueue.main)
                .mapToVoid(),
            UniversalEventMonitor.publisher(for: .leftMouseUp)
                .filter { [weak self] _ in self?.isOnActiveSpace ?? false }
                .mapToVoid()
        )
        .debounce(for: 0.05, scheduler: DispatchQueue.main)
        .sink { [weak self] in
            self?.insertUpdateFlag(.applicationMenuFrame)
        }
        .store(in: &c)

        // Continually update the desktop wallpaper. Ideally, we would set up an observer
        // for a wallpaper change notification, but macOS doesn't post one anymore.
        Timer.publish(every: 5, on: .main, in: .default)
            .autoconnect()
            .sink { [weak self] _ in
                self?.insertUpdateFlag(.desktopWallpaper)
            }
            .store(in: &c)

        Timer.publish(every: 10, on: .main, in: .default)
            .autoconnect()
            .sink { [weak self] _ in
                self?.insertUpdateFlag(.applicationMenuFrame)
            }
            .store(in: &c)

        $needsShow
            .debounce(for: 0.05, scheduler: DispatchQueue.main)
            .sink { [weak self] needsShow in
                guard let self, needsShow else {
                    return
                }
                defer {
                    self.needsShow = false
                }
                show()
            }
            .store(in: &c)

        $updateFlags
            .sink { [weak self] flags in
                guard let self, !flags.isEmpty else {
                    return
                }
                Task {
                    // Must be run async, or this will not remove the flags.
                    self.updateFlags.removeAll()
                }
                let windows = WindowInfo.getOnScreenWindows()
                guard let owningDisplay = self.validate(for: .updates, with: windows) else {
                    return
                }
                performUpdates(for: flags, windows: windows, display: owningDisplay)
            }
            .store(in: &c)

        if let appState {
            appState.menuBarManager.$isMenuBarHiddenBySystem
                .sink { [weak self] isHidden in
                    self?.alphaValue = isHidden ? 0 : 1
                }
                .store(in: &c)
        }

        cancellables = c
    }

    /// Inserts the given update flag into the panel's current list of update flags.
    private func insertUpdateFlag(_ flag: UpdateFlag) {
        updateFlags.insert(flag)
    }

    /// Performs validation for the given validation kind. Returns the panel's
    /// owning display if successful. Returns `nil` on failure.
    private func validate(for kind: ValidationKind, with windows: [WindowInfo]) -> CGDirectDisplayID? {
        lazy var actionMessage = switch kind {
        case .showing: "Preventing overlay panel from showing."
        case .updates: "Preventing overlay panel from updating."
        }
        guard let appState else {
            Logger.overlayPanel.debug("No app state. \(actionMessage)")
            return nil
        }
        guard !appState.menuBarManager.isMenuBarHiddenBySystemUserDefaults else {
            Logger.overlayPanel.debug("Menu bar is hidden by system. \(actionMessage)")
            return nil
        }
        guard !appState.isActiveSpaceFullscreen else {
            Logger.overlayPanel.debug("Active space is fullscreen. \(actionMessage)")
            return nil
        }
        let owningDisplay = owningScreen.displayID
        guard appState.menuBarManager.hasValidMenuBar(in: windows, for: owningDisplay) else {
            Logger.overlayPanel.debug("No valid menu bar found. \(actionMessage)")
            return nil
        }
        return owningDisplay
    }

    /// Stores the frame of the menu bar's application menu.
    private func updateApplicationMenuFrame(for display: CGDirectDisplayID) {
        guard
            let menuBarManager = appState?.menuBarManager,
            !menuBarManager.isMenuBarHiddenBySystem
        else {
            return
        }
        applicationMenuFrame = menuBarManager.getApplicationMenuFrame(for: display)
    }

    /// Stores the area of the desktop wallpaper that is under the menu bar
    /// of the given display.
    private func updateDesktopWallpaper(for display: CGDirectDisplayID, with windows: [WindowInfo]) {
        guard
            let wallpaperWindow = WindowInfo.getWallpaperWindow(from: windows, for: display),
            let menuBarWindow = WindowInfo.getMenuBarWindow(from: windows, for: display)
        else {
            return
        }
        let wallpaper = ScreenCapture.captureWindow(wallpaperWindow.windowID, screenBounds: menuBarWindow.frame)
        if desktopWallpaper?.dataProvider?.data != wallpaper?.dataProvider?.data {
            desktopWallpaper = wallpaper
        }
    }

    /// Updates the panel to prepare for display.
    private func performUpdates(for flags: Set<UpdateFlag>, windows: [WindowInfo], display: CGDirectDisplayID) {
        if flags.contains(.applicationMenuFrame) {
            updateApplicationMenuFrame(for: display)
        }
        if flags.contains(.desktopWallpaper) {
            updateDesktopWallpaper(for: display, with: windows)
        }
    }

    /// Shows the panel.
    private func show() {
        guard
            let appState,
            !appState.isPreview
        else {
            return
        }

        guard appState.appearanceManager.overlayPanels.contains(self) else {
            Logger.overlayPanel.warning("Overlay panel \(self) not retained")
            return
        }

        guard let menuBarHeight = owningScreen.getMenuBarHeight() else {
            return
        }

        let newFrame = CGRect(
            x: owningScreen.frame.minX,
            y: (owningScreen.frame.maxY - menuBarHeight) - 5,
            width: owningScreen.frame.width,
            height: menuBarHeight + 5
        )

        alphaValue = 0
        setFrame(newFrame, display: false)
        orderFrontRegardless()

        updateFlags = [.applicationMenuFrame, .desktopWallpaper]

        if !appState.menuBarManager.isMenuBarHiddenBySystem {
            animator().alphaValue = 1
        }
    }

    override func isAccessibilityElement() -> Bool {
        return false
    }
}

// MARK: - Content View

private final class MenuBarOverlayPanelContentView: NSView {
    @Published private var fullConfiguration: MenuBarAppearanceConfigurationV2 = .defaultConfiguration

    @Published private var previewConfiguration: MenuBarAppearancePartialConfiguration?

    private var cancellables = Set<AnyCancellable>()

    /// The overlay panel that contains the content view.
    private var overlayPanel: MenuBarOverlayPanel? {
        window as? MenuBarOverlayPanel
    }

    /// The currently displayed configuration.
    private var configuration: MenuBarAppearancePartialConfiguration {
        previewConfiguration ?? fullConfiguration.current
    }

    override func viewDidMoveToWindow() {
        super.viewDidMoveToWindow()
        configureCancellables()
    }

    private func configureCancellables() {
        var c = Set<AnyCancellable>()

        if let overlayPanel {
            if let appState = overlayPanel.appState {
                appState.appearanceManager.$configuration
                    .removeDuplicates()
                    .assign(to: &$fullConfiguration)

                appState.appearanceManager.$previewConfiguration
                    .removeDuplicates()
                    .assign(to: &$previewConfiguration)

                for section in appState.menuBarManager.sections {
                    // Redraw whenever the window frame of a control item changes.
                    //
                    // - NOTE: A previous attempt was made to redraw the view when the
                    //   section's `isHidden` property was changed. This would be semantically
                    //   ideal, but the property sometimes changes before the menu bar items
                    //   are actually updated on-screen. Since the view's drawing process relies
                    //   on getting an accurate position of each menu bar item, we need to use
                    //   something that publishes its changes only after the items are updated.
                    section.controlItem.$windowFrame
                        .receive(on: DispatchQueue.main)
                        .sink { [weak self] _ in
                            self?.needsDisplay = true
                        }
                        .store(in: &c)

                    // Redraw whenever the visibility of a control item changes.
                    //
                    // - NOTE: If the "ShowSectionDividers" setting is disabled, the window
                    //   frame does not update when the section is hidden or shown, but the
                    //   visibility does. We observe both to ensure the update occurs.
                    section.controlItem.$isVisible
                        .receive(on: DispatchQueue.main)
                        .sink { [weak self] _ in
                            self?.needsDisplay = true
                        }
                        .store(in: &c)
                }
            }

            // Fade out whenever a menu bar item is being dragged.
            overlayPanel.$isDraggingMenuBarItem
                .removeDuplicates()
                .sink { [weak self] isDragging in
                    if isDragging {
                        self?.animator().alphaValue = 0
                    } else {
                        self?.animator().alphaValue = 1
                    }
                }
                .store(in: &c)
            // Redraw whenever the application menu frame changes.
            overlayPanel.$applicationMenuFrame
                .sink { [weak self] _ in
                    self?.needsDisplay = true
                }
                .store(in: &c)
            // Redraw whenever the desktop wallpaper changes.
            overlayPanel.$desktopWallpaper
                .sink { [weak self] _ in
                    self?.needsDisplay = true
                }
                .store(in: &c)
        }

        // Redraw whenever the configurations change.
        $fullConfiguration.mapToVoid()
            .merge(with: $previewConfiguration.mapToVoid())
            .sink { [weak self] _ in
                self?.needsDisplay = true
            }
            .store(in: &c)

        cancellables = c
    }

    /// Returns a path in the given rectangle, with the given end caps,
    /// and inset by the given amounts.
    private func shapePath(in rect: CGRect, leadingEndCap: MenuBarEndCap, trailingEndCap: MenuBarEndCap, screen: NSScreen) -> NSBezierPath {
        let insetRect: CGRect = if !screen.hasNotch {
            switch (leadingEndCap, trailingEndCap) {
            case (.square, .square):
                CGRect(x: rect.origin.x, y: rect.origin.y + 1, width: rect.width, height: rect.height - 2)
            case (.square, .round):
                CGRect(x: rect.origin.x, y: rect.origin.y + 1, width: rect.width - 1, height: rect.height - 2)
            case (.round, .square):
                CGRect(x: rect.origin.x + 1, y: rect.origin.y + 1, width: rect.width - 1, height: rect.height - 2)
            case (.round, .round):
                CGRect(x: rect.origin.x + 1, y: rect.origin.y + 1, width: rect.width - 2, height: rect.height - 2)
            }
        } else {
            rect
        }

        let shapeBounds = CGRect(
            x: insetRect.minX + insetRect.height / 2,
            y: insetRect.minY,
            width: insetRect.width - insetRect.height,
            height: insetRect.height
        )
        let leadingEndCapBounds = CGRect(
            x: insetRect.minX,
            y: insetRect.minY,
            width: insetRect.height,
            height: insetRect.height
        )
        let trailingEndCapBounds = CGRect(
            x: insetRect.maxX - insetRect.height,
            y: insetRect.minY,
            width: insetRect.height,
            height: insetRect.height
        )

        var path = NSBezierPath(rect: shapeBounds)

        path = switch leadingEndCap {
        case .square: path.union(NSBezierPath(rect: leadingEndCapBounds))
        case .round: path.union(NSBezierPath(ovalIn: leadingEndCapBounds))
        }

        path = switch trailingEndCap {
        case .square: path.union(NSBezierPath(rect: trailingEndCapBounds))
        case .round: path.union(NSBezierPath(ovalIn: trailingEndCapBounds))
        }

        return path
    }

    /// Returns a path for the ``MenuBarShapeKind/full`` shape kind.
    private func pathForFullShape(in rect: CGRect, info: MenuBarFullShapeInfo, isInset: Bool, screen: NSScreen) -> NSBezierPath {
        guard let appearanceManager = overlayPanel?.appState?.appearanceManager else {
            return NSBezierPath()
        }
        var rect = rect
        let shouldInset = isInset && screen.hasNotch
        if shouldInset {
            rect = rect.insetBy(dx: 0, dy: appearanceManager.menuBarInsetAmount)
            if info.leadingEndCap == .round {
                rect.origin.x += appearanceManager.menuBarInsetAmount
                rect.size.width -= appearanceManager.menuBarInsetAmount
            }
            if info.trailingEndCap == .round {
                rect.size.width -= appearanceManager.menuBarInsetAmount
            }
        }
        return shapePath(
            in: rect,
            leadingEndCap: info.leadingEndCap,
            trailingEndCap: info.trailingEndCap,
            screen: screen
        )
    }

    /// Returns a path for the ``MenuBarShapeKind/split`` shape kind.
    private func pathForSplitShape(in rect: CGRect, info: MenuBarSplitShapeInfo, isInset: Bool, screen: NSScreen) -> NSBezierPath {
        guard let appearanceManager = overlayPanel?.appState?.appearanceManager else {
            return NSBezierPath()
        }
        var rect = rect
        let shouldInset = isInset && screen.hasNotch
        if shouldInset {
            rect = rect.insetBy(dx: 0, dy: appearanceManager.menuBarInsetAmount)
            if info.leading.leadingEndCap == .round {
                rect.origin.x += appearanceManager.menuBarInsetAmount
                rect.size.width -= appearanceManager.menuBarInsetAmount
            }
            if info.trailing.trailingEndCap == .round {
                rect.size.width -= appearanceManager.menuBarInsetAmount
            }
        }
        let leadingPathBounds: CGRect = {
            guard
                var maxX = overlayPanel?.applicationMenuFrame?.width,
                maxX > 0
            else {
                return .zero
            }
            if shouldInset {
                maxX += 10
                if info.leading.leadingEndCap == .square {
                    maxX += appearanceManager.menuBarInsetAmount
                }
            } else {
                maxX += 20
            }
            return CGRect(x: rect.minX, y: rect.minY, width: maxX, height: rect.height)
        }()
        let trailingPathBounds: CGRect = {
            let items = MenuBarItem.getMenuBarItems(on: screen.displayID, onScreenOnly: true, activeSpaceOnly: false)
            guard !items.isEmpty else {
                return .zero
            }
            let totalWidth = items.reduce(into: 0) { width, item in
                width += item.frame.width
            }
            var position = rect.maxX - totalWidth
            if shouldInset {
                position += 4
                if info.trailing.trailingEndCap == .square {
                    position -= appearanceManager.menuBarInsetAmount
                }
            } else {
                position -= 7
            }
            return CGRect(x: position, y: rect.minY, width: rect.maxX - position, height: rect.height)
        }()

        if leadingPathBounds == .zero || trailingPathBounds == .zero || leadingPathBounds.intersects(trailingPathBounds) {
            return shapePath(
                in: rect,
                leadingEndCap: info.leading.leadingEndCap,
                trailingEndCap: info.trailing.trailingEndCap,
                screen: screen
            )
        } else {
            let leadingPath = shapePath(
                in: leadingPathBounds,
                leadingEndCap: info.leading.leadingEndCap,
                trailingEndCap: info.leading.trailingEndCap,
                screen: screen
            )
            let trailingPath = shapePath(
                in: trailingPathBounds,
                leadingEndCap: info.trailing.leadingEndCap,
                trailingEndCap: info.trailing.trailingEndCap,
                screen: screen
            )
            let path = NSBezierPath()
            path.append(leadingPath)
            path.append(trailingPath)
            return path
        }
    }

    /// Returns the bounds that the view's drawn content can occupy.
    private func getDrawableBounds() -> CGRect {
        return CGRect(
            x: bounds.origin.x,
            y: bounds.origin.y + 5,
            width: bounds.width,
            height: bounds.height - 5
        )
    }

    /// Draws the tint defined by the given configuration in the given rectangle.
    private func drawTint(in rect: CGRect) {
        switch configuration.tintKind {
        case .none:
            break
        case .solid:
            if let tintColor = NSColor(cgColor: configuration.tintColor)?.withAlphaComponent(0.2) {
                tintColor.setFill()
                rect.fill()
            }
        case .gradient:
            if let tintGradient = configuration.tintGradient.withAlphaComponent(0.2).nsGradient {
                tintGradient.draw(in: rect, angle: 0)
            }
        }
    }

    override func draw(_ dirtyRect: NSRect) {
        guard
            let overlayPanel,
            let context = NSGraphicsContext.current
        else {
            return
        }

        let drawableBounds = getDrawableBounds()

        let shapePath = switch fullConfiguration.shapeKind {
        case .none:
            NSBezierPath(rect: drawableBounds)
        case .full:
            pathForFullShape(
                in: drawableBounds,
                info: fullConfiguration.fullShapeInfo,
                isInset: fullConfiguration.isInset,
                screen: overlayPanel.owningScreen
            )
        case .split:
            pathForSplitShape(
                in: drawableBounds,
                info: fullConfiguration.splitShapeInfo,
                isInset: fullConfiguration.isInset,
                screen: overlayPanel.owningScreen
            )
        }

        var hasBorder = false

        switch fullConfiguration.shapeKind {
        case .none:
            if configuration.hasShadow {
                let gradient = NSGradient(
                    colors: [
                        NSColor(white: 0.0, alpha: 0.0),
                        NSColor(white: 0.0, alpha: 0.2),
                    ]
                )
                let shadowBounds = CGRect(
                    x: bounds.minX,
                    y: bounds.minY,
                    width: bounds.width,
                    height: 5
                )
                gradient?.draw(in: shadowBounds, angle: 90)
            }

            drawTint(in: drawableBounds)

            if configuration.hasBorder {
                let borderBounds = CGRect(
                    x: bounds.minX,
                    y: bounds.minY + 5,
                    width: bounds.width,
                    height: configuration.borderWidth
                )
                NSColor(cgColor: configuration.borderColor)?.setFill()
                NSBezierPath(rect: borderBounds).fill()
            }
        case .full, .split:
            if let desktopWallpaper = overlayPanel.desktopWallpaper {
                context.saveGraphicsState()
                defer {
                    context.restoreGraphicsState()
                }

                let invertedClipPath = NSBezierPath(rect: drawableBounds)
                invertedClipPath.append(shapePath.reversed)
                invertedClipPath.setClip()

                context.cgContext.draw(desktopWallpaper, in: drawableBounds)
            }

            if configuration.hasShadow {
                context.saveGraphicsState()
                defer {
                    context.restoreGraphicsState()
                }

                let shadowClipPath = NSBezierPath(rect: bounds)
                shadowClipPath.append(shapePath.reversed)
                shadowClipPath.setClip()

                shapePath.drawShadow(color: .black.withAlphaComponent(0.5), radius: 5)
            }

            if configuration.hasBorder {
                hasBorder = true
            }

            do {
                context.saveGraphicsState()
                defer {
                    context.restoreGraphicsState()
                }

                shapePath.setClip()

                drawTint(in: drawableBounds)
            }

            if
                hasBorder,
                let borderColor = NSColor(cgColor: configuration.borderColor)
            {
                context.saveGraphicsState()
                defer {
                    context.restoreGraphicsState()
                }

                let borderPath = switch fullConfiguration.shapeKind {
                case .none:
                    NSBezierPath(rect: drawableBounds)
                case .full:
                    pathForFullShape(
                        in: drawableBounds,
                        info: fullConfiguration.fullShapeInfo,
                        isInset: fullConfiguration.isInset,
                        screen: overlayPanel.owningScreen
                    )
                case .split:
                    pathForSplitShape(
                        in: drawableBounds,
                        info: fullConfiguration.splitShapeInfo,
                        isInset: fullConfiguration.isInset,
                        screen: overlayPanel.owningScreen
                    )
                }

                // HACK: Insetting a path to get an "inside" stroke is surprisingly
                // difficult. We can fake the correct line width by doubling it, as
                // anything outside the shape path will be clipped.
                borderPath.lineWidth = configuration.borderWidth * 2
                borderPath.setClip()

                borderColor.setStroke()
                borderPath.stroke()
            }
        }
    }
}

// MARK: - Logger
private extension Logger {
    static let overlayPanel = Logger(category: "MenuBarOverlayPanel")
}


================================================
FILE: Ice/MenuBar/Appearance/MenuBarShape.swift
================================================
//
//  MenuBarShape.swift
//  Ice
//

import CoreGraphics

/// An end cap in a menu bar shape.
enum MenuBarEndCap: Int, Codable, Hashable, CaseIterable {
    /// An end cap with a square shape.
    case square = 0
    /// An end cap with a rounded shape.
    case round = 1
}

/// A type that specifies a custom shape kind for the menu bar.
enum MenuBarShapeKind: Int, Codable, Hashable, CaseIterable {
    /// The menu bar does not use a custom shape.
    case none = 0
    /// A custom shape that takes up the full menu bar.
    case full = 1
    /// A custom shape that splits the menu bar between
    /// its leading and trailing sides.
    case split = 2
}

/// Information for the ``MenuBarShapeKind/full`` menu bar
/// shape kind.
struct MenuBarFullShapeInfo: Codable, Hashable {
    /// The leading end cap of the shape.
    var leadingEndCap: MenuBarEndCap
    /// The trailing end cap of the shape.
    var trailingEndCap: MenuBarEndCap
}

extension MenuBarFullShapeInfo {
    var hasRoundedShape: Bool {
        leadingEndCap == .round || trailingEndCap == .round
    }
}

extension MenuBarFullShapeInfo {
    static let `default` = MenuBarFullShapeInfo(leadingEndCap: .round, trailingEndCap: .round)
}

/// Information for the ``MenuBarShapeKind/split`` menu bar
/// shape kind.
struct MenuBarSplitShapeInfo: Codable, Hashable {
    /// The leading information of the shape.
    var leading: MenuBarFullShapeInfo
    /// The trailing information of the shape.
    var trailing: MenuBarFullShapeInfo
}

extension MenuBarSplitShapeInfo {
    var hasRoundedShape: Bool {
        leading.hasRoundedShape || trailing.hasRoundedShape
    }
}

extension MenuBarSplitShapeInfo {
    static let `default` = MenuBarSplitShapeInfo(leading: .default, trailing: .default)
}


================================================
FILE: Ice/MenuBar/Appearance/MenuBarTintKind.swift
================================================
//
//  MenuBarTintKind.swift
//  Ice
//

import SwiftUI

/// A type that specifies how the menu bar is tinted.
enum MenuBarTintKind: Int, CaseIterable, Codable, Identifiable {
    /// The menu bar is not tinted.
    case none = 0
    /// The menu bar is tinted with a solid color.
    case solid = 1
    /// The menu bar is tinted with a gradient.
    case gradient = 2

    var id: Int { rawValue }

    /// Localized string key representation.
    var localized: LocalizedStringKey {
        switch self {
        case .none: "None"
        case .solid: "Solid"
        case .gradient: "Gradient"
        }
    }
}


================================================
FILE: Ice/MenuBar/ControlItem/ControlItem.swift
================================================
//
//  ControlItem.swift
//  Ice
//

import Cocoa
import Combine

/// A status item that controls a section in the menu bar.
@MainActor
final class ControlItem {
    /// Possible identifiers for control items.
    enum Identifier: String, CaseIterable {
        case iceIcon = "SItem"
        case hidden = "HItem"
        case alwaysHidden = "AHItem"
    }

    /// Possible hiding states for control items.
    enum HidingState {
        case hideItems, showItems
    }

    /// Possible lengths for control items.
    enum Lengths {
        static let standard: CGFloat = NSStatusItem.variableLength
        static let expanded: CGFloat = 10_000
    }

    /// The control item's hiding state (`@Published`).
    @Published var state = HidingState.hideItems

    /// A Boolean value that indicates whether the control item is visible (`@Published`).
    @Published var isVisible = true

    /// The frame of the control item's window (`@Published`).
    @Published private(set) var windowFrame: CGRect?

    /// The shared app state.
    private weak var appState: AppState?

    /// The control item's underlying status item.
    private let statusItem: NSStatusItem

    /// A horizontal constraint for the control item's content view.
    private let constraint: NSLayoutConstraint?

    /// The control item's identifier.
    private let identifier: Identifier

    /// Storage for internal observers.
    private var cancellables = Set<AnyCancellable>()

    /// The menu bar section associated with the control item.
    private weak var section: MenuBarSection? {
        appState?.menuBarManager.sections.first { $0.controlItem === self }
    }

    /// The control item's window.
    var window: NSWindow? {
        statusItem.button?.window
    }

    /// The identifier of the control item's window.
    var windowID: CGWindowID? {
        guard let window else {
            return nil
        }
        return CGWindowID(window.windowNumber)
    }

    /// A Boolean value that indicates whether the control item serves as
    /// a divider between sections.
    var isSectionDivider: Bool {
        identifier != .iceIcon
    }

    /// A Boolean value that indicates whether the control item is currently
    /// displayed in the menu bar.
    var isAddedToMenuBar: Bool {
        statusItem.isVisible
    }

    /// Creates a control item with the given identifier and app state.
    init(identifier: Identifier, appState: AppState) {
        let autosaveName = identifier.rawValue

        // If the status item doesn't have a preferred position, set it
        // according to the identifier.
        if StatusItemDefaults[.preferredPosition, autosaveName] == nil {
            switch identifier {
            case .iceIcon:
                StatusItemDefaults[.preferredPosition, autosaveName] = 0
            case .hidden:
                StatusItemDefaults[.preferredPosition, autosaveName] = 1
            case .alwaysHidden:
                break
            }
        }

        self.statusItem = NSStatusBar.system.statusItem(withLength: 0)
        self.statusItem.autosaveName = autosaveName
        self.identifier = identifier
        self.appState = appState

        // This could break in a new macOS release, but we need this constraint in order to be
        // able to hide the control item when the `ShowSectionDividers` setting is disabled. A
        // previous implementation used the status item's `isVisible` property, which was more
        // robust, but would completel
Download .txt
gitextract_awypvfy4/

├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   ├── config.yml
│   │   └── feature_request.yml
│   └── workflows/
│       └── lint.yml
├── .gitignore
├── .swiftlint.yml
├── CODE_OF_CONDUCT.md
├── FREQUENT_ISSUES.md
├── Ice/
│   ├── Assets.xcassets/
│   │   ├── AccentColor.colorset/
│   │   │   └── Contents.json
│   │   ├── AppIcon.appiconset/
│   │   │   └── Contents.json
│   │   ├── Contents.json
│   │   ├── ControlItemImages/
│   │   │   ├── Contents.json
│   │   │   ├── Dot/
│   │   │   │   ├── Contents.json
│   │   │   │   ├── DotFill.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   └── DotStroke.imageset/
│   │   │   │       └── Contents.json
│   │   │   ├── Ellipsis/
│   │   │   │   ├── Contents.json
│   │   │   │   ├── EllipsisFill.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   └── EllipsisStroke.imageset/
│   │   │   │       └── Contents.json
│   │   │   └── IceCube/
│   │   │       ├── Contents.json
│   │   │       ├── IceCubeFill.imageset/
│   │   │       │   └── Contents.json
│   │   │       └── IceCubeStroke.imageset/
│   │   │           └── Contents.json
│   │   ├── DefaultLayoutBarColor.colorset/
│   │   │   └── Contents.json
│   │   └── Warning.imageset/
│   │       └── Contents.json
│   ├── Bridging/
│   │   ├── Bridging.swift
│   │   └── Shims/
│   │       ├── Deprecated.swift
│   │       └── Private.swift
│   ├── Events/
│   │   ├── EventManager.swift
│   │   ├── EventMonitors/
│   │   │   ├── GlobalEventMonitor.swift
│   │   │   ├── LocalEventMonitor.swift
│   │   │   ├── RunLoopLocalEventMonitor.swift
│   │   │   └── UniversalEventMonitor.swift
│   │   └── EventTap.swift
│   ├── Hotkeys/
│   │   ├── Hotkey.swift
│   │   ├── HotkeyAction.swift
│   │   ├── HotkeyRegistry.swift
│   │   ├── KeyCode.swift
│   │   ├── KeyCombination.swift
│   │   └── Modifiers.swift
│   ├── Ice.entitlements
│   ├── Info.plist
│   ├── Main/
│   │   ├── AppDelegate.swift
│   │   ├── AppState.swift
│   │   ├── IceApp.swift
│   │   └── Navigation/
│   │       ├── AppNavigationState.swift
│   │       └── NavigationIdentifiers/
│   │           ├── NavigationIdentifier.swift
│   │           └── SettingsNavigationIdentifier.swift
│   ├── MenuBar/
│   │   ├── Appearance/
│   │   │   ├── Configurations/
│   │   │   │   ├── MenuBarAppearanceConfigurationV1.swift
│   │   │   │   └── MenuBarAppearanceConfigurationV2.swift
│   │   │   ├── MenuBarAppearanceEditor/
│   │   │   │   ├── MenuBarAppearanceEditor.swift
│   │   │   │   ├── MenuBarAppearanceEditorPanel.swift
│   │   │   │   └── MenuBarShapePicker.swift
│   │   │   ├── MenuBarAppearanceManager.swift
│   │   │   ├── MenuBarOverlayPanel.swift
│   │   │   ├── MenuBarShape.swift
│   │   │   └── MenuBarTintKind.swift
│   │   ├── ControlItem/
│   │   │   ├── ControlItem.swift
│   │   │   ├── ControlItemImage.swift
│   │   │   └── ControlItemImageSet.swift
│   │   ├── MenuBarItems/
│   │   │   ├── MenuBarItem.swift
│   │   │   ├── MenuBarItemImageCache.swift
│   │   │   ├── MenuBarItemInfo.swift
│   │   │   └── MenuBarItemManager.swift
│   │   ├── MenuBarManager.swift
│   │   ├── MenuBarSection.swift
│   │   ├── Search/
│   │   │   └── MenuBarSearchPanel.swift
│   │   └── Spacing/
│   │       └── MenuBarItemSpacingManager.swift
│   ├── Permissions/
│   │   ├── Permission.swift
│   │   ├── PermissionsManager.swift
│   │   ├── PermissionsView.swift
│   │   └── PermissionsWindow.swift
│   ├── Resources/
│   │   └── Acknowledgements.rtf
│   ├── Settings/
│   │   ├── SettingsManagers/
│   │   │   ├── AdvancedSettingsManager.swift
│   │   │   ├── GeneralSettingsManager.swift
│   │   │   ├── HotkeySettingsManager.swift
│   │   │   └── SettingsManager.swift
│   │   ├── SettingsPanes/
│   │   │   ├── AboutSettingsPane.swift
│   │   │   ├── AdvancedSettingsPane.swift
│   │   │   ├── GeneralSettingsPane.swift
│   │   │   ├── HotkeysSettingsPane.swift
│   │   │   ├── MenuBarAppearanceSettingsPane.swift
│   │   │   └── MenuBarLayoutSettingsPane.swift
│   │   ├── SettingsView.swift
│   │   └── SettingsWindow.swift
│   ├── Swizzling/
│   │   └── NSSplitViewItem+swizzledCanCollapse.swift
│   ├── UI/
│   │   ├── HotkeyRecorder/
│   │   │   ├── HotkeyRecorder.swift
│   │   │   └── HotkeyRecorderModel.swift
│   │   ├── IceBar/
│   │   │   ├── IceBar.swift
│   │   │   ├── IceBarColorManager.swift
│   │   │   └── IceBarLocation.swift
│   │   ├── IceUI/
│   │   │   ├── IceForm.swift
│   │   │   ├── IceGroupBox.swift
│   │   │   ├── IceLabeledContent.swift
│   │   │   ├── IceMenu.swift
│   │   │   ├── IcePicker.swift
│   │   │   ├── IceSection.swift
│   │   │   └── IceSlider.swift
│   │   ├── LayoutBar/
│   │   │   ├── LayoutBar.swift
│   │   │   ├── LayoutBarContainer.swift
│   │   │   ├── LayoutBarItemView.swift
│   │   │   ├── LayoutBarPaddingView.swift
│   │   │   └── LayoutBarScrollView.swift
│   │   ├── Pickers/
│   │   │   ├── CustomColorPicker/
│   │   │   │   └── CustomColorPicker.swift
│   │   │   └── CustomGradientPicker/
│   │   │       ├── ColorStop.swift
│   │   │       ├── CustomGradient.swift
│   │   │       └── CustomGradientPicker.swift
│   │   ├── Shapes/
│   │   │   └── AnyInsettableShape.swift
│   │   ├── ViewModifiers/
│   │   │   ├── BottomBar.swift
│   │   │   ├── ErasedToAnyView.swift
│   │   │   ├── LayoutBarStyle.swift
│   │   │   ├── LocalEventMonitorModifier.swift
│   │   │   ├── OnFrameChange.swift
│   │   │   ├── OnKeyDown.swift
│   │   │   ├── Once.swift
│   │   │   ├── ReadWindow.swift
│   │   │   └── RemoveSidebarToggle.swift
│   │   └── Views/
│   │       ├── AnnotationView.swift
│   │       ├── BetaBadge.swift
│   │       ├── SectionedList.swift
│   │       └── VisualEffectView.swift
│   ├── Updates/
│   │   └── UpdatesManager.swift
│   ├── UserNotifications/
│   │   ├── UserNotificationIdentifier.swift
│   │   └── UserNotificationManager.swift
│   └── Utilities/
│       ├── BindingExposable.swift
│       ├── CodableColor.swift
│       ├── Constants.swift
│       ├── Defaults.swift
│       ├── Extensions.swift
│       ├── IconResource.swift
│       ├── Injection.swift
│       ├── LocalizedErrorWrapper.swift
│       ├── Logging.swift
│       ├── MigrationManager.swift
│       ├── MouseCursor.swift
│       ├── Notifications.swift
│       ├── ObjectStorage.swift
│       ├── Predicates.swift
│       ├── RehideStrategy.swift
│       ├── ScreenCapture.swift
│       ├── StatusItemDefaults.swift
│       ├── SystemAppearance.swift
│       ├── TaskTimeout.swift
│       └── WindowInfo.swift
├── Ice.xcodeproj/
│   ├── project.pbxproj
│   ├── project.xcworkspace/
│   │   ├── contents.xcworkspacedata
│   │   └── xcshareddata/
│   │       ├── IDEWorkspaceChecks.plist
│   │       └── swiftpm/
│   │           └── Package.resolved
│   └── xcshareddata/
│       └── xcschemes/
│           └── Ice.xcscheme
├── LICENSE
├── README.md
└── Resources/
    └── Icon.fig
Condensed preview — 152 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (730K chars).
[
  {
    "path": ".gitattributes",
    "chars": 24,
    "preview": "*.rtf linguist-vendored\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 49,
    "preview": "github: jordanbaird\nbuy_me_a_coffee: jordanbaird\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "chars": 1662,
    "preview": "name: Bug Report\ndescription: Submit a bug report.\ntitle: \"[Bug]: \"\nlabels: Bug\nbody:\n  - type: checkboxes\n    attribute"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 28,
    "preview": "blank_issues_enabled: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "chars": 1021,
    "preview": "name: Feature Request\ndescription: Request a feature or suggest an idea.\ntitle: \"[Feature Request]: \"\nlabels: Feature\nbo"
  },
  {
    "path": ".github/workflows/lint.yml",
    "chars": 516,
    "preview": "name: Lint Swift Files\non:\n  push:\n    branches: [ \"main\" ]\n    paths:\n      - \".github/workflows/lint.yml\"\n      - \".sw"
  },
  {
    "path": ".gitignore",
    "chars": 29,
    "preview": ".DS_Store\nbuild/\nxcuserdata/\n"
  },
  {
    "path": ".swiftlint.yml",
    "chars": 1627,
    "preview": "included:\n  - Ice\n\ndisabled_rules:\n  - cyclomatic_complexity\n  - file_length\n  - function_body_length\n  - function_param"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5227,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": "FREQUENT_ISSUES.md",
    "chars": 2153,
    "preview": "# Frequent Issues <!-- omit in toc -->\n\n- [Items are moved to the always-hidden section](#items-are-moved-to-the-always-"
  },
  {
    "path": "Ice/Assets.xcassets/AccentColor.colorset/Contents.json",
    "chars": 123,
    "preview": "{\n  \"colors\" : [\n    {\n      \"idiom\" : \"universal\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }"
  },
  {
    "path": "Ice/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 1301,
    "preview": "{\n  \"images\" : [\n    {\n      \"filename\" : \"icon_16x16.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"1x\",\n      \"size\" : "
  },
  {
    "path": "Ice/Assets.xcassets/Contents.json",
    "chars": 63,
    "preview": "{\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "Ice/Assets.xcassets/ControlItemImages/Contents.json",
    "chars": 63,
    "preview": "{\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "Ice/Assets.xcassets/ControlItemImages/Dot/Contents.json",
    "chars": 63,
    "preview": "{\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "Ice/Assets.xcassets/ControlItemImages/Dot/DotFill.imageset/Contents.json",
    "chars": 374,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"filename\" : \"DotFill.png\",\n"
  },
  {
    "path": "Ice/Assets.xcassets/ControlItemImages/Dot/DotStroke.imageset/Contents.json",
    "chars": 376,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"filename\" : \"DotStroke.png\""
  },
  {
    "path": "Ice/Assets.xcassets/ControlItemImages/Ellipsis/Contents.json",
    "chars": 63,
    "preview": "{\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "Ice/Assets.xcassets/ControlItemImages/Ellipsis/EllipsisFill.imageset/Contents.json",
    "chars": 379,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"filename\" : \"EllipsisFill.p"
  },
  {
    "path": "Ice/Assets.xcassets/ControlItemImages/Ellipsis/EllipsisStroke.imageset/Contents.json",
    "chars": 381,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"filename\" : \"EllipsisStroke"
  },
  {
    "path": "Ice/Assets.xcassets/ControlItemImages/IceCube/Contents.json",
    "chars": 63,
    "preview": "{\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "Ice/Assets.xcassets/ControlItemImages/IceCube/IceCubeFill.imageset/Contents.json",
    "chars": 378,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"filename\" : \"IceCubeFill.pn"
  },
  {
    "path": "Ice/Assets.xcassets/ControlItemImages/IceCube/IceCubeStroke.imageset/Contents.json",
    "chars": 380,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"filename\" : \"IceCubeStroke."
  },
  {
    "path": "Ice/Assets.xcassets/DefaultLayoutBarColor.colorset/Contents.json",
    "chars": 707,
    "preview": "{\n  \"colors\" : [\n    {\n      \"color\" : {\n        \"color-space\" : \"display-p3\",\n        \"components\" : {\n          \"alpha"
  },
  {
    "path": "Ice/Assets.xcassets/Warning.imageset/Contents.json",
    "chars": 305,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"filename\" : \"Warning.png\",\n"
  },
  {
    "path": "Ice/Bridging/Bridging.swift",
    "chars": 9475,
    "preview": "//\n//  Bridging.swift\n//  Ice\n//\n\nimport Cocoa\n\n/// A namespace for bridged functionality.\nenum Bridging { }\n\n// MARK: -"
  },
  {
    "path": "Ice/Bridging/Shims/Deprecated.swift",
    "chars": 225,
    "preview": "//\n//  Deprecated.swift\n//  Ice\n//\n\nimport ApplicationServices\n\n/// Returns a PSN for a given PID.\n@_silgen_name(\"GetPro"
  },
  {
    "path": "Ice/Bridging/Shims/Private.swift",
    "chars": 3288,
    "preview": "//\n//  Private.swift\n//  Ice\n//\n\nimport CoreGraphics\n\n// MARK: - Bridged Types\n\ntypealias CGSConnectionID = Int32\ntypeal"
  },
  {
    "path": "Ice/Events/EventManager.swift",
    "chars": 18008,
    "preview": "//\n//  EventManager.swift\n//  Ice\n//\n\nimport Cocoa\nimport Combine\n\n/// Manager for the various event monitors maintained"
  },
  {
    "path": "Ice/Events/EventMonitors/GlobalEventMonitor.swift",
    "chars": 2686,
    "preview": "//\n//  GlobalEventMonitor.swift\n//  Ice\n//\n\nimport Cocoa\nimport Combine\n\n/// A type that monitors for events outside the"
  },
  {
    "path": "Ice/Events/EventMonitors/LocalEventMonitor.swift",
    "chars": 2707,
    "preview": "//\n//  LocalEventMonitor.swift\n//  Ice\n//\n\nimport Cocoa\nimport Combine\n\n/// A type that monitors for events within the s"
  },
  {
    "path": "Ice/Events/EventMonitors/RunLoopLocalEventMonitor.swift",
    "chars": 3741,
    "preview": "//\n//  RunLoopLocalEventMonitor.swift\n//  Ice\n//\n\nimport Cocoa\nimport Combine\n\nfinal class RunLoopLocalEventMonitor {\n  "
  },
  {
    "path": "Ice/Events/EventMonitors/UniversalEventMonitor.swift",
    "chars": 2597,
    "preview": "//\n//  UniversalEventMonitor.swift\n//  Ice\n//\n\nimport Cocoa\nimport Combine\n\n/// A type that monitors for local and globa"
  },
  {
    "path": "Ice/Events/EventTap.swift",
    "chars": 8335,
    "preview": "//\n//  EventTap.swift\n//  Ice\n//\n\nimport Cocoa\n\n/// A type that receives system events from various locations within the"
  },
  {
    "path": "Ice/Hotkeys/Hotkey.swift",
    "chars": 3665,
    "preview": "//\n//  Hotkey.swift\n//  Ice\n//\n\nimport Combine\n\n/// A combination of a key and modifiers that can be used to\n/// trigger"
  },
  {
    "path": "Ice/Hotkeys/HotkeyAction.swift",
    "chars": 1754,
    "preview": "//\n//  HotkeyAction.swift\n//  Ice\n//\n\nenum HotkeyAction: String, Codable, CaseIterable {\n    // Menu Bar Sections\n    ca"
  },
  {
    "path": "Ice/Hotkeys/HotkeyRegistry.swift",
    "chars": 9301,
    "preview": "//\n//  HotkeyRegistry.swift\n//  Ice\n//\n\nimport Carbon.HIToolbox\nimport Cocoa\nimport Combine\n\n/// An object that manages "
  },
  {
    "path": "Ice/Hotkeys/KeyCode.swift",
    "chars": 10063,
    "preview": "//\n//  KeyCode.swift\n//  Ice\n//\n\nimport Carbon.HIToolbox\n\n/// Representation of a physical key on a keyboard.\nstruct Key"
  },
  {
    "path": "Ice/Hotkeys/KeyCombination.swift",
    "chars": 2720,
    "preview": "//\n//  KeyCombination.swift\n//  Ice\n//\n\nimport Carbon.HIToolbox\nimport Cocoa\n\nstruct KeyCombination: Hashable {\n    let "
  },
  {
    "path": "Ice/Hotkeys/Modifiers.swift",
    "chars": 4265,
    "preview": "//\n//  Modifiers.swift\n//  Ice\n//\n\nimport Carbon.HIToolbox\nimport Cocoa\n\n/// A bit mask containing the modifier keys for"
  },
  {
    "path": "Ice/Ice.entitlements",
    "chars": 311,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Ice/Info.plist",
    "chars": 372,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Ice/Main/AppDelegate.swift",
    "chars": 3192,
    "preview": "//\n//  AppDelegate.swift\n//  Ice\n//\n\nimport SwiftUI\n\n@MainActor\nfinal class AppDelegate: NSObject, NSApplicationDelegate"
  },
  {
    "path": "Ice/Main/AppState.swift",
    "chars": 10797,
    "preview": "//\n//  AppState.swift\n//  Ice\n//\n\nimport Combine\nimport SwiftUI\n\n/// The model for app-wide state.\n@MainActor\nfinal clas"
  },
  {
    "path": "Ice/Main/IceApp.swift",
    "chars": 464,
    "preview": "//\n//  IceApp.swift\n//  Ice\n//\n\nimport SwiftUI\n\n@main\nstruct IceApp: App {\n    @NSApplicationDelegateAdaptor var appDele"
  },
  {
    "path": "Ice/Main/Navigation/AppNavigationState.swift",
    "chars": 431,
    "preview": "//\n//  AppNavigationState.swift\n//  Ice\n//\n\nimport Combine\n\n/// The model for app-wide navigation.\n@MainActor\nfinal clas"
  },
  {
    "path": "Ice/Main/Navigation/NavigationIdentifiers/NavigationIdentifier.swift",
    "chars": 579,
    "preview": "//\n//  NavigationIdentifier.swift\n//  Ice\n//\n\nimport SwiftUI\n\n/// A type that represents an identifier used for navigati"
  },
  {
    "path": "Ice/Main/Navigation/NavigationIdentifiers/SettingsNavigationIdentifier.swift",
    "chars": 395,
    "preview": "//\n//  SettingsNavigationIdentifier.swift\n//  Ice\n//\n\n/// An identifier used for navigation in the settings interface.\ne"
  },
  {
    "path": "Ice/MenuBar/Appearance/Configurations/MenuBarAppearanceConfigurationV1.swift",
    "chars": 7305,
    "preview": "//\n//  MenuBarAppearanceConfigurationV1.swift\n//  Ice\n//\n\nimport CoreGraphics\nimport Foundation\n\n/// Configuration for t"
  },
  {
    "path": "Ice/MenuBar/Appearance/Configurations/MenuBarAppearanceConfigurationV2.swift",
    "chars": 6660,
    "preview": "//\n//  MenuBarAppearanceConfigurationV2.swift\n//  Ice\n//\n\nimport CoreGraphics\nimport Foundation\n\nstruct MenuBarAppearanc"
  },
  {
    "path": "Ice/MenuBar/Appearance/MenuBarAppearanceEditor/MenuBarAppearanceEditor.swift",
    "chars": 9700,
    "preview": "//\n//  MenuBarAppearanceEditor.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct MenuBarAppearanceEditor: View {\n    enum Locatio"
  },
  {
    "path": "Ice/MenuBar/Appearance/MenuBarAppearanceEditor/MenuBarAppearanceEditorPanel.swift",
    "chars": 3703,
    "preview": "//\n//  MenuBarAppearanceEditorPanel.swift\n//  Ice\n//\n\nimport Combine\nimport SwiftUI\n\n// MARK: - MenuBarAppearanceEditorP"
  },
  {
    "path": "Ice/MenuBar/Appearance/MenuBarAppearanceEditor/MenuBarShapePicker.swift",
    "chars": 6050,
    "preview": "//\n//  MenuBarShapePicker.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct MenuBarShapePicker: View {\n    @EnvironmentObject var"
  },
  {
    "path": "Ice/MenuBar/Appearance/MenuBarAppearanceManager.swift",
    "chars": 5495,
    "preview": "//\n//  MenuBarAppearanceManager.swift\n//  Ice\n//\n\nimport Cocoa\nimport Combine\n\n/// A manager for the appearance of the m"
  },
  {
    "path": "Ice/MenuBar/Appearance/MenuBarOverlayPanel.swift",
    "chars": 29649,
    "preview": "//\n//  MenuBarOverlayPanel.swift\n//  Ice\n//\n\nimport Cocoa\nimport Combine\n\n// MARK: - Overlay Panel\n\n/// A subclass of `N"
  },
  {
    "path": "Ice/MenuBar/Appearance/MenuBarShape.swift",
    "chars": 1773,
    "preview": "//\n//  MenuBarShape.swift\n//  Ice\n//\n\nimport CoreGraphics\n\n/// An end cap in a menu bar shape.\nenum MenuBarEndCap: Int, "
  },
  {
    "path": "Ice/MenuBar/Appearance/MenuBarTintKind.swift",
    "chars": 617,
    "preview": "//\n//  MenuBarTintKind.swift\n//  Ice\n//\n\nimport SwiftUI\n\n/// A type that specifies how the menu bar is tinted.\nenum Menu"
  },
  {
    "path": "Ice/MenuBar/ControlItem/ControlItem.swift",
    "chars": 20390,
    "preview": "//\n//  ControlItem.swift\n//  Ice\n//\n\nimport Cocoa\nimport Combine\n\n/// A status item that controls a section in the menu "
  },
  {
    "path": "Ice/MenuBar/ControlItem/ControlItemImage.swift",
    "chars": 3617,
    "preview": "//\n//  ControlItemImage.swift\n//  Ice\n//\n\nimport Cocoa\n\n/// A Codable image for a control item.\nenum ControlItemImage: C"
  },
  {
    "path": "Ice/MenuBar/ControlItem/ControlItemImageSet.swift",
    "chars": 2465,
    "preview": "//\n//  ControlItemImageSet.swift\n//  Ice\n//\n\n/// A named set of images that are used by control items.\n///\n/// An image "
  },
  {
    "path": "Ice/MenuBar/MenuBarItems/MenuBarItem.swift",
    "chars": 8015,
    "preview": "//\n//  MenuBarItem.swift\n//  Ice\n//\n\nimport Cocoa\n\n// MARK: - MenuBarItem\n\n/// A representation of an item in the menu b"
  },
  {
    "path": "Ice/MenuBar/MenuBarItems/MenuBarItemImageCache.swift",
    "chars": 10080,
    "preview": "//\n//  MenuBarItemImageCache.swift\n//  Ice\n//\n\nimport Cocoa\nimport Combine\n\n/// Cache for menu bar item images.\nfinal cl"
  },
  {
    "path": "Ice/MenuBar/MenuBarItems/MenuBarItemInfo.swift",
    "chars": 6884,
    "preview": "//\n//  MenuBarItemInfo.swift\n//  Ice\n//\n\n/// A simplified version of a menu bar item.\nstruct MenuBarItemInfo: Hashable, "
  },
  {
    "path": "Ice/MenuBar/MenuBarItems/MenuBarItemManager.swift",
    "chars": 62421,
    "preview": "//\n//  MenuBarItemManager.swift\n//  Ice\n//\n\nimport Cocoa\nimport Combine\n\n/// Manager for menu bar items.\n@MainActor\nfina"
  },
  {
    "path": "Ice/MenuBar/MenuBarManager.swift",
    "chars": 15317,
    "preview": "//\n//  MenuBarManager.swift\n//  Ice\n//\n\nimport AXSwift\nimport Combine\nimport SwiftUI\n\n/// Manager for the state of the m"
  },
  {
    "path": "Ice/MenuBar/MenuBarSection.swift",
    "chars": 9928,
    "preview": "//\n//  MenuBarSection.swift\n//  Ice\n//\n\nimport Cocoa\n\n/// A representation of a section in a menu bar.\n@MainActor\nfinal "
  },
  {
    "path": "Ice/MenuBar/Search/MenuBarSearchPanel.swift",
    "chars": 14536,
    "preview": "//\n//  MenuBarSearchPanel.swift\n//  Ice\n//\n\nimport Combine\nimport Ifrit\nimport SwiftUI\n\n/// A panel that contains the me"
  },
  {
    "path": "Ice/MenuBar/Spacing/MenuBarItemSpacingManager.swift",
    "chars": 7905,
    "preview": "//\n//  MenuBarItemSpacingManager.swift\n//  Ice\n//\n\nimport Cocoa\nimport Combine\n\n/// Manager for menu bar item spacing.\n@"
  },
  {
    "path": "Ice/Permissions/Permission.swift",
    "chars": 4807,
    "preview": "//\n//  Permission.swift\n//  Ice\n//\n\nimport AXSwift\nimport Combine\nimport Cocoa\nimport ScreenCaptureKit\n\n// MARK: - Permi"
  },
  {
    "path": "Ice/Permissions/PermissionsManager.swift",
    "chars": 2200,
    "preview": "//\n//  PermissionsManager.swift\n//  Ice\n//\n\nimport Combine\nimport Foundation\n\n/// A type that manages the permissions of"
  },
  {
    "path": "Ice/Permissions/PermissionsView.swift",
    "chars": 5974,
    "preview": "//\n//  PermissionsView.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct PermissionsView: View {\n    @EnvironmentObject var permi"
  },
  {
    "path": "Ice/Permissions/PermissionsWindow.swift",
    "chars": 650,
    "preview": "//\n//  PermissionsWindow.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct PermissionsWindow: Scene {\n    @ObservedObject var app"
  },
  {
    "path": "Ice/Resources/Acknowledgements.rtf",
    "chars": 12506,
    "preview": "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue-Bold;\\f1"
  },
  {
    "path": "Ice/Settings/SettingsManagers/AdvancedSettingsManager.swift",
    "chars": 4355,
    "preview": "//\n//  AdvancedSettingsManager.swift\n//  Ice\n//\n\nimport Combine\nimport Foundation\n\n@MainActor\nfinal class AdvancedSettin"
  },
  {
    "path": "Ice/Settings/SettingsManagers/GeneralSettingsManager.swift",
    "chars": 7445,
    "preview": "//\n//  GeneralSettingsManager.swift\n//  Ice\n//\n\nimport Combine\nimport Foundation\n\n@MainActor\nfinal class GeneralSettings"
  },
  {
    "path": "Ice/Settings/SettingsManagers/HotkeySettingsManager.swift",
    "chars": 2531,
    "preview": "//\n//  HotkeySettingsManager.swift\n//  Ice\n//\n\nimport Combine\nimport Foundation\n\n@MainActor\nfinal class HotkeySettingsMa"
  },
  {
    "path": "Ice/Settings/SettingsManagers/SettingsManager.swift",
    "chars": 1816,
    "preview": "//\n//  SettingsManager.swift\n//  Ice\n//\n\nimport Combine\n\n@MainActor\nfinal class SettingsManager: ObservableObject {\n    "
  },
  {
    "path": "Ice/Settings/SettingsPanes/AboutSettingsPane.swift",
    "chars": 5342,
    "preview": "//\n//  AboutSettingsPane.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct AboutSettingsPane: View {\n    @EnvironmentObject var a"
  },
  {
    "path": "Ice/Settings/SettingsPanes/AdvancedSettingsPane.swift",
    "chars": 6023,
    "preview": "//\n//  AdvancedSettingsPane.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct AdvancedSettingsPane: View {\n    @EnvironmentObject"
  },
  {
    "path": "Ice/Settings/SettingsPanes/GeneralSettingsPane.swift",
    "chars": 11573,
    "preview": "//\n//  GeneralSettingsPane.swift\n//  Ice\n//\n\nimport LaunchAtLogin\nimport SwiftUI\n\nstruct GeneralSettingsPane: View {\n   "
  },
  {
    "path": "Ice/Settings/SettingsPanes/HotkeysSettingsPane.swift",
    "chars": 2161,
    "preview": "//\n//  HotkeysSettingsPane.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct HotkeysSettingsPane: View {\n    @EnvironmentObject v"
  },
  {
    "path": "Ice/Settings/SettingsPanes/MenuBarAppearanceSettingsPane.swift",
    "chars": 398,
    "preview": "//\n//  MenuBarAppearanceSettingsPane.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct MenuBarAppearanceSettingsPane: View {\n    "
  },
  {
    "path": "Ice/Settings/SettingsPanes/MenuBarLayoutSettingsPane.swift",
    "chars": 2568,
    "preview": "//\n//  MenuBarLayoutSettingsPane.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct MenuBarLayoutSettingsPane: View {\n    @Environ"
  },
  {
    "path": "Ice/Settings/SettingsView.swift",
    "chars": 3054,
    "preview": "//\n//  SettingsView.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct SettingsView: View {\n    @EnvironmentObject var navigationS"
  },
  {
    "path": "Ice/Settings/SettingsWindow.swift",
    "chars": 755,
    "preview": "//\n//  SettingsWindow.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct SettingsWindow: Scene {\n    @ObservedObject var appState:"
  },
  {
    "path": "Ice/Swizzling/NSSplitViewItem+swizzledCanCollapse.swift",
    "chars": 1020,
    "preview": "//\n//  NSSplitViewItem+swizzledCanCollapse.swift\n//  Ice\n//\n\nimport Cocoa\n\nextension NSSplitViewItem {\n    @nonobjc priv"
  },
  {
    "path": "Ice/UI/HotkeyRecorder/HotkeyRecorder.swift",
    "chars": 4588,
    "preview": "//\n//  HotkeyRecorder.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct HotkeyRecorder<Label: View>: View {\n    @StateObject priv"
  },
  {
    "path": "Ice/UI/HotkeyRecorder/HotkeyRecorderModel.swift",
    "chars": 1974,
    "preview": "//\n//  HotkeyRecorderModel.swift\n//  Ice\n//\n\nimport Combine\nimport SwiftUI\n\n@MainActor\nfinal class HotkeyRecorderModel: "
  },
  {
    "path": "Ice/UI/IceBar/IceBar.swift",
    "chars": 16864,
    "preview": "//\n//  IceBar.swift\n//  Ice\n//\n\nimport Combine\nimport SwiftUI\n\n// MARK: - IceBarPanel\n\nfinal class IceBarPanel: NSPanel "
  },
  {
    "path": "Ice/UI/IceBar/IceBarColorManager.swift",
    "chars": 4426,
    "preview": "//\n//  IceBarColorManager.swift\n//  Ice\n//\n\nimport Cocoa\nimport Combine\n\nfinal class IceBarColorManager: ObservableObjec"
  },
  {
    "path": "Ice/UI/IceBar/IceBarLocation.swift",
    "chars": 692,
    "preview": "//\n//  IceBarLocation.swift\n//  Ice\n//\n\nimport SwiftUI\n\n/// Locations where the Ice Bar can appear.\nenum IceBarLocation:"
  },
  {
    "path": "Ice/UI/IceUI/IceForm.swift",
    "chars": 2203,
    "preview": "//\n//  IceForm.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct IceForm<Content: View>: View {\n    @Environment(\\.isScrollEnable"
  },
  {
    "path": "Ice/UI/IceUI/IceGroupBox.swift",
    "chars": 2435,
    "preview": "//\n//  IceGroupBox.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct IceGroupBox<Header: View, Content: View, Footer: View>: View"
  },
  {
    "path": "Ice/UI/IceUI/IceLabeledContent.swift",
    "chars": 843,
    "preview": "//\n//  IceLabeledContent.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct IceLabeledContent<Label: View, Content: View>: View {\n"
  },
  {
    "path": "Ice/UI/IceUI/IceMenu.swift",
    "chars": 1706,
    "preview": "//\n//  IceMenu.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct IceMenu<Title: View, Label: View, Content: View>: View {\n    pri"
  },
  {
    "path": "Ice/UI/IceUI/IcePicker.swift",
    "chars": 1215,
    "preview": "//\n//  IcePicker.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct IcePicker<Label: View, SelectionValue: Hashable, Content: View"
  },
  {
    "path": "Ice/UI/IceUI/IceSection.swift",
    "chars": 3861,
    "preview": "//\n//  IceSection.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct IceSectionOptions: OptionSet {\n    let rawValue: Int\n\n    sta"
  },
  {
    "path": "Ice/UI/IceUI/IceSlider.swift",
    "chars": 1640,
    "preview": "//\n//  IceSlider.swift\n//  Ice\n//\n\nimport CompactSlider\nimport SwiftUI\n\nstruct IceSlider<Value: BinaryFloatingPoint, Val"
  },
  {
    "path": "Ice/UI/LayoutBar/LayoutBar.swift",
    "chars": 1808,
    "preview": "//\n//  LayoutBar.swift\n//  Ice\n//\n\nimport SwiftUI\n\nstruct LayoutBar: View {\n    private struct Representable: NSViewRepr"
  },
  {
    "path": "Ice/UI/LayoutBar/LayoutBarContainer.swift",
    "chars": 11252,
    "preview": "//\n//  LayoutBarContainer.swift\n//  Ice\n//\n\nimport Cocoa\nimport Combine\n\n/// A container for the items in the menu bar l"
  },
  {
    "path": "Ice/UI/LayoutBar/LayoutBarItemView.swift",
    "chars": 8387,
    "preview": "//\n//  LayoutBarItemView.swift\n//  Ice\n//\n\nimport Cocoa\nimport Combine\n\n// MARK: - LayoutBarItemView\n\n/// A view that di"
  },
  {
    "path": "Ice/UI/LayoutBar/LayoutBarPaddingView.swift",
    "chars": 5696,
    "preview": "//\n//  LayoutBarPaddingView.swift\n//  Ice\n//\n\nimport Cocoa\nimport Combine\n\n/// A Cocoa view that manages the menu bar la"
  },
  {
    "path": "Ice/UI/LayoutBar/LayoutBarScrollView.swift",
    "chars": 3160,
    "preview": "//\n//  LayoutBarScrollView.swift\n//  Ice\n//\n\nimport Cocoa\n\nfinal class LayoutBarScrollView: NSScrollView {\n    private l"
  },
  {
    "path": "Ice/UI/Pickers/CustomColorPicker/CustomColorPicker.swift",
    "chars": 3684,
    "preview": "//\n//  CustomColorPicker.swift\n//  Ice\n//\n\nimport Combine\nimport SwiftUI\n\nstruct CustomColorPicker: NSViewRepresentable "
  },
  {
    "path": "Ice/UI/Pickers/CustomGradientPicker/ColorStop.swift",
    "chars": 1211,
    "preview": "//\n//  ColorStop.swift\n//  Ice\n//\n\nimport CoreGraphics\n\n/// A color stop in a gradient.\nstruct ColorStop: Hashable {\n   "
  },
  {
    "path": "Ice/UI/Pickers/CustomGradientPicker/CustomGradient.swift",
    "chars": 3321,
    "preview": "//\n//  CustomGradient.swift\n//  Ice\n//\n\nimport SwiftUI\n\n/// A custom gradient for use with a ``GradientPicker``.\nstruct "
  },
  {
    "path": "Ice/UI/Pickers/CustomGradientPicker/CustomGradientPicker.swift",
    "chars": 14022,
    "preview": "//\n//  CustomGradientPicker.swift\n//  Ice\n//\n\nimport Combine\nimport SwiftUI\n\nstruct CustomGradientPicker: View {\n    @Bi"
  },
  {
    "path": "Ice/UI/Shapes/AnyInsettableShape.swift",
    "chars": 547,
    "preview": "//\n//  AnyInsettableShape.swift\n//  Ice\n//\n\nimport SwiftUI\n\n/// A type-erased insettable shape.\nstruct AnyInsettableShap"
  },
  {
    "path": "Ice/UI/ViewModifiers/BottomBar.swift",
    "chars": 580,
    "preview": "//\n//  BottomBar.swift\n//  Ice\n//\n\nimport SwiftUI\n\nextension View {\n    /// Adds the given view as a bottom bar to the c"
  },
  {
    "path": "Ice/UI/ViewModifiers/ErasedToAnyView.swift",
    "chars": 220,
    "preview": "//\n//  ErasedToAnyView.swift\n//  Ice\n//\n\nimport SwiftUI\n\nextension View {\n    /// Returns a view that has been erased to"
  },
  {
    "path": "Ice/UI/ViewModifiers/LayoutBarStyle.swift",
    "chars": 1961,
    "preview": "//\n//  LayoutBarStyle.swift\n//  Ice\n//\n\nimport SwiftUI\n\nextension View {\n    /// Returns a view that is drawn in the sty"
  },
  {
    "path": "Ice/UI/ViewModifiers/LocalEventMonitorModifier.swift",
    "chars": 1413,
    "preview": "//\n//  LocalEventMonitorModifier.swift\n//  Ice\n//\n\nimport SwiftUI\n\nprivate final class LocalEventMonitorModifierState: O"
  },
  {
    "path": "Ice/UI/ViewModifiers/OnFrameChange.swift",
    "chars": 1889,
    "preview": "//\n//  OnFrameChange.swift\n//  Ice\n//\n\nimport SwiftUI\n\nprivate struct FramePreferenceKey: PreferenceKey {\n    static let"
  },
  {
    "path": "Ice/UI/ViewModifiers/OnKeyDown.swift",
    "chars": 452,
    "preview": "//\n//  OnKeyDown.swift\n//  Ice\n//\n\nimport SwiftUI\n\nextension View {\n    /// Returns a view that performs the given actio"
  },
  {
    "path": "Ice/UI/ViewModifiers/Once.swift",
    "chars": 659,
    "preview": "//\n//  Once.swift\n//  Ice\n//\n\nimport SwiftUI\n\nprivate struct OnceModifier: ViewModifier {\n    @State private var hasAppe"
  },
  {
    "path": "Ice/UI/ViewModifiers/ReadWindow.swift",
    "chars": 1586,
    "preview": "//\n//  ReadWindow.swift\n//  Ice\n//\n\nimport Combine\nimport SwiftUI\n\nprivate struct WindowReader: NSViewRepresentable {\n  "
  },
  {
    "path": "Ice/UI/ViewModifiers/RemoveSidebarToggle.swift",
    "chars": 299,
    "preview": "//\n//  RemoveSidebarToggle.swift\n//  Ice\n//\n\nimport SwiftUI\n\nextension View {\n    /// Removes the sidebar toggle button "
  },
  {
    "path": "Ice/UI/Views/AnnotationView.swift",
    "chars": 6945,
    "preview": "//\n//  AnnotationView.swift\n//  Ice\n//\n\nimport SwiftUI\n\n/// A view that displays content as an annotation below a parent"
  },
  {
    "path": "Ice/UI/Views/BetaBadge.swift",
    "chars": 412,
    "preview": "//\n//  BetaBadge.swift\n//  Ice\n//\n\nimport SwiftUI\n\n/// A view that displays a badge indicating a beta feature.\nstruct Be"
  },
  {
    "path": "Ice/UI/Views/SectionedList.swift",
    "chars": 6823,
    "preview": "//\n//  SectionedList.swift\n//  Ice\n//\n\nimport SwiftUI\n\n// MARK: - SectionedList\n\n/// A scrollable list of items broken u"
  },
  {
    "path": "Ice/UI/Views/VisualEffectView.swift",
    "chars": 786,
    "preview": "//\n//  VisualEffectView.swift\n//  Ice\n//\n\nimport SwiftUI\n\n/// A SwiftUI view that wraps an `NSVisualEffectView`.\nstruct "
  },
  {
    "path": "Ice/Updates/UpdatesManager.swift",
    "chars": 4275,
    "preview": "//\n//  UpdatesManager.swift\n//  Ice\n//\n\nimport Sparkle\nimport SwiftUI\n\n/// Manager for app updates.\n@MainActor\nfinal cla"
  },
  {
    "path": "Ice/UserNotifications/UserNotificationIdentifier.swift",
    "chars": 176,
    "preview": "//\n//  UserNotificationIdentifier.swift\n//  Ice\n//\n\n/// An identifier for a user notification.\nenum UserNotificationIden"
  },
  {
    "path": "Ice/UserNotifications/UserNotificationManager.swift",
    "chars": 2753,
    "preview": "//\n//  UserNotificationManager.swift\n//  Ice\n//\n\nimport UserNotifications\n\n/// Manager for user notifications.\n@MainActo"
  },
  {
    "path": "Ice/Utilities/BindingExposable.swift",
    "chars": 1350,
    "preview": "//\n//  BindingExposable.swift\n//  Ice\n//\n\nimport SwiftUI\n\n/// A type that exposes its writable properties as bindings.\np"
  },
  {
    "path": "Ice/Utilities/CodableColor.swift",
    "chars": 2547,
    "preview": "//\n//  CodableColor.swift\n//  Ice\n//\n\nimport CoreGraphics\nimport Foundation\n\n/// A Codable wrapper around a CGColor.\nstr"
  },
  {
    "path": "Ice/Utilities/Constants.swift",
    "chars": 994,
    "preview": "//\n//  Constants.swift\n//  Ice\n//\n\nimport Foundation\n\nenum Constants {\n    // swiftlint:disable force_unwrapping\n    ///"
  },
  {
    "path": "Ice/Utilities/Defaults.swift",
    "chars": 6968,
    "preview": "//\n//  Defaults.swift\n//  Ice\n//\n\nimport Foundation\n\nenum Defaults {\n    /// Returns a dictionary containing the keys an"
  },
  {
    "path": "Ice/Utilities/Extensions.swift",
    "chars": 17204,
    "preview": "//\n//  Extensions.swift\n//  Ice\n//\n\nimport Combine\nimport SwiftUI\n\n// MARK: - Bundle\n\nextension Bundle {\n    /// The bun"
  },
  {
    "path": "Ice/Utilities/IconResource.swift",
    "chars": 761,
    "preview": "//\n//  IconResource.swift\n//  Ice\n//\n\nimport SwiftUI\n\n/// A type that produces a view representing an icon.\nenum IconRes"
  },
  {
    "path": "Ice/Utilities/Injection.swift",
    "chars": 1106,
    "preview": "//\n//  Injection.swift\n//  Ice\n//\n\n/// Updates the given value in place using a closure.\n///\n/// Use this function to re"
  },
  {
    "path": "Ice/Utilities/LocalizedErrorWrapper.swift",
    "chars": 1081,
    "preview": "//\n//  LocalizedErrorWrapper.swift\n//  Ice\n//\n\nimport Foundation\n\n/// A type that wraps the information of any error ins"
  },
  {
    "path": "Ice/Utilities/Logging.swift",
    "chars": 989,
    "preview": "//\n//  Logging.swift\n//  Ice\n//\n\nimport OSLog\n\n/// A type that encapsulates logging behavior for Ice.\nstruct Logger {\n  "
  },
  {
    "path": "Ice/Utilities/MigrationManager.swift",
    "chars": 14666,
    "preview": "//\n//  MigrationManager.swift\n//  Ice\n//\n\nimport Cocoa\n\n@MainActor\nstruct MigrationManager {\n    let appState: AppState\n"
  },
  {
    "path": "Ice/Utilities/MouseCursor.swift",
    "chars": 1798,
    "preview": "//\n//  MouseCursor.swift\n//  Ice\n//\n\nimport CoreGraphics\n\n/// A namespace for mouse cursor operations.\nenum MouseCursor "
  },
  {
    "path": "Ice/Utilities/Notifications.swift",
    "chars": 293,
    "preview": "//\n//  Notifications.swift\n//  Ice\n//\n\nimport Foundation\n\nextension DistributedNotificationCenter {\n    /// A notificati"
  },
  {
    "path": "Ice/Utilities/ObjectStorage.swift",
    "chars": 2326,
    "preview": "//\n//  ObjectStorage.swift\n//  Ice\n//\n\nimport ObjectiveC\n\n// MARK: - Object Storage\n\n/// A type that uses the Objective-"
  },
  {
    "path": "Ice/Utilities/Predicates.swift",
    "chars": 5107,
    "preview": "//\n//  Predicates.swift\n//  Ice\n//\n\nimport Cocoa\n\n/// A namespace for predicates.\nenum Predicates<Input> {\n    /// A thr"
  },
  {
    "path": "Ice/Utilities/RehideStrategy.swift",
    "chars": 681,
    "preview": "//\n//  RehideStrategy.swift\n//  Ice\n//\n\nimport SwiftUI\n\n/// A type that determines how the auto-rehide feature works.\nen"
  },
  {
    "path": "Ice/Utilities/ScreenCapture.swift",
    "chars": 4243,
    "preview": "//\n//  ScreenCapture.swift\n//  Ice\n//\n\nimport CoreGraphics\nimport ScreenCaptureKit\n\n/// A namespace for screen capture o"
  },
  {
    "path": "Ice/Utilities/StatusItemDefaults.swift",
    "chars": 1864,
    "preview": "//\n//  StatusItemDefaults.swift\n//  Ice\n//\n\nimport Cocoa\n\n// MARK: - StatusItemDefaults\n\n/// Proxy getters and setters f"
  },
  {
    "path": "Ice/Utilities/SystemAppearance.swift",
    "chars": 2610,
    "preview": "//\n//  SystemAppearance.swift\n//  Ice\n//\n\nimport SwiftUI\n\n/// A value corresponding to a light or dark appearance.\nenum "
  },
  {
    "path": "Ice/Utilities/TaskTimeout.swift",
    "chars": 3023,
    "preview": "//\n//  TaskTimeout.swift\n//  Ice\n//\n\nimport Foundation\n\nextension Task where Failure == any Error {\n    /// Runs the giv"
  },
  {
    "path": "Ice/Utilities/WindowInfo.swift",
    "chars": 12119,
    "preview": "//\n//  WindowInfo.swift\n//  Ice\n//\n\nimport Cocoa\n\n/// Information for a window.\nstruct WindowInfo {\n    /// The window i"
  },
  {
    "path": "Ice.xcodeproj/project.pbxproj",
    "chars": 16844,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 70;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "Ice.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 135,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef"
  },
  {
    "path": "Ice.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Ice.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved",
    "chars": 1449,
    "preview": "{\n  \"originHash\" : \"a7567d11f06745371832127a8ce2132148ef6a89fb55ecc72d6c313b688387fa\",\n  \"pins\" : [\n    {\n      \"identit"
  },
  {
    "path": "Ice.xcodeproj/xcshareddata/xcschemes/Ice.xcscheme",
    "chars": 2806,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1640\"\n   version = \"1.7\">\n   <BuildAction\n      "
  },
  {
    "path": "LICENSE",
    "chars": 35100,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "README.md",
    "chars": 4319,
    "preview": "<div align=\"center\">\n    <img src=\"Ice/Assets.xcassets/AppIcon.appiconset/icon_256x256.png\" width=200 height=200>\n    <h"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the jordanbaird/Ice GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 152 files (677.5 KB), approximately 154.5k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!