Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions Sources/Barback/MenuBarToneView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// MenuBarToneView.swift
// Barback
//
// 캡처된 메뉴바 아이콘의 배경 뷰.
// 캡처 이미지는 시스템 외형을 따라간다(라이트=어두운 글리프, 다크=밝은 글리프).
// 배경도 라이트/다크에 맞춰 메뉴바 톤으로 갱신해야 아이콘이 보인다 —
// 다크 고정이면 라이트 모드에서 검정 위 검정이 된다.
//

import Cocoa

@MainActor
final class MenuBarToneView: NSView {
override var wantsUpdateLayer: Bool { true }

override func updateLayer() {
let dark = effectiveAppearance.bestMatch(from: [.aqua, .darkAqua]) == .darkAqua
layer?.backgroundColor = NSColor(calibratedWhite: dark ? 0.12 : 0.96, alpha: 0.98).cgColor
layer?.borderColor = NSColor(calibratedWhite: dark ? 1 : 0, alpha: 0.12).cgColor
}
}
Comment on lines +14 to +22

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

MenuBarToneView는 wantsUpdateLayertrue로 반환하여 레이어 업데이트 방식을 사용하고 있습니다. 이 방식이 올바르게 작동하려면 뷰가 반드시 레이어 기반(layer-backed)이어야 합니다.

호출부(RevealPanel, SettingsWindowController)에서 매번 wantsLayer = true를 수동으로 설정하는 대신, MenuBarToneView 내부 생성자에서 self.wantsLayer = true를 직접 설정하도록 캡슐화하는 것이 더 안전하며 실수를 방지할 수 있습니다.

Suggested change
final class MenuBarToneView: NSView {
override var wantsUpdateLayer: Bool { true }
override func updateLayer() {
let dark = effectiveAppearance.bestMatch(from: [.aqua, .darkAqua]) == .darkAqua
layer?.backgroundColor = NSColor(calibratedWhite: dark ? 0.12 : 0.96, alpha: 0.98).cgColor
layer?.borderColor = NSColor(calibratedWhite: dark ? 1 : 0, alpha: 0.12).cgColor
}
}
final class MenuBarToneView: NSView {
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
self.wantsLayer = true
}
required init?(coder: NSCoder) {
super.init(coder: coder)
self.wantsLayer = true
}
override var wantsUpdateLayer: Bool { true }
override func updateLayer() {
let dark = effectiveAppearance.bestMatch(from: [.aqua, .darkAqua]) == .darkAqua
layer?.backgroundColor = NSColor(calibratedWhite: dark ? 0.12 : 0.96, alpha: 0.98).cgColor
layer?.borderColor = NSColor(calibratedWhite: dark ? 1 : 0, alpha: 0.12).cgColor
}
}

11 changes: 5 additions & 6 deletions Sources/Barback/RevealPanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,13 @@ final class RevealPanel: NSPanel {
let width = padding * 2 + CGFloat(columns) * itemSize + CGFloat(columns - 1) * spacing
let height = padding * 2 + CGFloat(rowCount) * itemSize + CGFloat(max(0, rowCount - 1)) * spacing

// 불투명 어두운 배경 (반투명 비침/메뉴바 ghosting 방지).
let background = NSView(frame: NSRect(x: 0, y: 0, width: width, height: height))
// 거의 불투명한 배경 (반투명 비침/메뉴바 ghosting 방지).
// 색은 MenuBarToneView 가 라이트/다크에 맞춰 갱신한다.
let background = MenuBarToneView(frame: NSRect(x: 0, y: 0, width: width, height: height))
background.wantsLayer = true
Comment on lines +66 to 67

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

MenuBarToneView 내부 생성자에서 wantsLayer = true를 직접 설정하도록 변경하면, 호출부에서 중복으로 wantsLayer를 설정할 필요가 없어 코드가 더 깔끔해집니다.

Suggested change
let background = MenuBarToneView(frame: NSRect(x: 0, y: 0, width: width, height: height))
background.wantsLayer = true
let background = MenuBarToneView(frame: NSRect(x: 0, y: 0, width: width, height: height))

background.layer?.backgroundColor = NSColor(calibratedWhite: 0.12, alpha: 0.98).cgColor
background.layer?.cornerRadius = 14
background.layer?.masksToBounds = true
background.layer?.borderWidth = 0.5
background.layer?.borderColor = NSColor(calibratedWhite: 1, alpha: 0.12).cgColor
background.autoresizingMask = []

if items.isEmpty {
Expand Down Expand Up @@ -102,11 +101,11 @@ final class RevealPanel: NSPanel {
if let image = item.image {
button.image = image
} else {
// 캡처 실패 시 placeholder (어두운 배경에 밝게)
// 캡처 실패 시 placeholder (labelColor 는 라이트/다크 자동 대응)
let ph = NSImage(systemSymbolName: "questionmark.square.dashed", accessibilityDescription: nil)
ph?.isTemplate = true
button.image = ph
button.contentTintColor = .white
button.contentTintColor = .labelColor
}
button.toolTip = item.displayName.isEmpty
? (item.isHidden ? "가려진 아이콘" : "메뉴바 아이콘")
Expand Down
6 changes: 3 additions & 3 deletions Sources/Barback/SettingsWindowController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,11 @@ final class SettingsWindowController: NSObject, NSWindowDelegate, NSTableViewDat
func windowWillClose(_ notification: Notification) {}
}

// MARK: - 행 뷰 (어두운 칩 + 아이콘 + 라벨)
// MARK: - 행 뷰 (메뉴바 톤 칩 + 아이콘 + 라벨)

@MainActor
private final class RowView: NSTableCellView {
private let chip = NSView()
private let chip = MenuBarToneView()
private let icon = NSImageView()
private let label = NSTextField(labelWithString: "")
private let badge = NSTextField(labelWithString: "")
Expand All @@ -178,8 +178,8 @@ private final class RowView: NSTableCellView {
identifier = reuseID

chip.wantsLayer = true
chip.layer?.backgroundColor = NSColor(white: 0.12, alpha: 1).cgColor
chip.layer?.cornerRadius = 6
chip.layer?.borderWidth = 0.5
Comment on lines 180 to +182

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

MenuBarToneView 내부 생성자에서 wantsLayer = true를 직접 설정하도록 변경하면, 호출부에서 중복으로 wantsLayer를 설정할 필요가 없어 코드가 더 깔끔해집니다.

Suggested change
chip.wantsLayer = true
chip.layer?.backgroundColor = NSColor(white: 0.12, alpha: 1).cgColor
chip.layer?.cornerRadius = 6
chip.layer?.borderWidth = 0.5
chip.layer?.cornerRadius = 6
chip.layer?.borderWidth = 0.5

icon.imageScaling = .scaleProportionallyDown
label.font = .systemFont(ofSize: 13)
badge.font = .systemFont(ofSize: 10)
Expand Down