Fix tooltip tracking lifetime and shortcut lag
This commit is contained in:
parent
4de975e6a4
commit
9e8a401e3c
12 changed files with 139 additions and 104 deletions
|
|
@ -70,6 +70,13 @@ final class WindowBrowserHostView: NSView {
|
|||
private var activeDividerCursorKind: DividerCursorKind?
|
||||
private var hostedInspectorDividerDrag: HostedInspectorDividerDragState?
|
||||
|
||||
deinit {
|
||||
if let trackingArea {
|
||||
removeTrackingArea(trackingArea)
|
||||
}
|
||||
clearActiveDividerCursor(restoreArrow: false)
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
private static func shouldLogPointerEvent(_ event: NSEvent?) -> Bool {
|
||||
switch event?.type {
|
||||
|
|
|
|||
|
|
@ -2209,7 +2209,7 @@ struct ContentView: View {
|
|||
)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.help(String(localized: "workspace.page.new.tooltip", defaultValue: "New Page"))
|
||||
.safeHelp(String(localized: "workspace.page.new.tooltip", defaultValue: "New Page"))
|
||||
.accessibilityIdentifier("titlebarPageNewButton")
|
||||
.transition(.opacity)
|
||||
}
|
||||
|
|
@ -2282,7 +2282,7 @@ struct ContentView: View {
|
|||
)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.help(page.title)
|
||||
.safeHelp(page.title)
|
||||
.accessibilityIdentifier(titlebarPageButtonAccessibilityIdentifier(pageId: page.id, isActive: isActive))
|
||||
|
||||
HStack(spacing: 4) {
|
||||
|
|
@ -9091,7 +9091,7 @@ private struct SidebarHelpMenuButton: View {
|
|||
helpPopover
|
||||
}
|
||||
.accessibilityElement(children: .ignore)
|
||||
.help(helpTitle)
|
||||
.safeHelp(helpTitle)
|
||||
.accessibilityLabel(helpTitle)
|
||||
.accessibilityIdentifier("SidebarHelpMenuButton")
|
||||
}
|
||||
|
|
@ -9717,7 +9717,7 @@ private struct TabItemView: View {
|
|||
.foregroundColor(activeSecondaryColor(0.7))
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.help(KeyboardShortcutSettings.Action.closeWorkspace.tooltip(closeWorkspaceTooltip))
|
||||
.safeHelp(KeyboardShortcutSettings.Action.closeWorkspace.tooltip(closeWorkspaceTooltip))
|
||||
.frame(width: 16, height: 16, alignment: .center)
|
||||
.opacity(showCloseButton && !showsWorkspaceShortcutHint ? 1 : 0)
|
||||
.allowsHitTesting(showCloseButton && !showsWorkspaceShortcutHint)
|
||||
|
|
@ -9890,7 +9890,7 @@ private struct TabItemView: View {
|
|||
.foregroundColor(pullRequestForegroundColor)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.help(String(localized: "sidebar.pullRequest.openTooltip", defaultValue: "Open \(pullRequest.label) #\(pullRequest.number)"))
|
||||
.safeHelp(String(localized: "sidebar.pullRequest.openTooltip", defaultValue: "Open \(pullRequest.label) #\(pullRequest.number)"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10757,7 +10757,7 @@ private struct SidebarMetadataRows: View {
|
|||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
}
|
||||
.help(helpText)
|
||||
.safeHelp(helpText)
|
||||
}
|
||||
|
||||
private var activeSecondaryTextColor: Color {
|
||||
|
|
@ -10797,7 +10797,7 @@ private struct SidebarMetadataEntryRow: View {
|
|||
rowContent(underlined: true)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.help(url.absoluteString)
|
||||
.safeHelp(url.absoluteString)
|
||||
} else {
|
||||
rowContent(underlined: false)
|
||||
.contentShape(Rectangle())
|
||||
|
|
@ -11972,7 +11972,7 @@ private struct DraggableFolderIcon: View {
|
|||
var body: some View {
|
||||
DraggableFolderIconRepresentable(directory: directory)
|
||||
.frame(width: 16, height: 16)
|
||||
.help(String(localized: "sidebar.folderIcon.dragHint", defaultValue: "Drag to open in Finder or another app"))
|
||||
.safeHelp(String(localized: "sidebar.folderIcon.dragHint", defaultValue: "Drag to open in Finder or another app"))
|
||||
.onTapGesture(count: 2) {
|
||||
NSWorkspace.shared.selectFile(nil, inFileViewerRootedAtPath: directory)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ struct BrowserSearchOverlay: View {
|
|||
Image(systemName: "chevron.up")
|
||||
}
|
||||
.buttonStyle(SearchButtonStyle())
|
||||
.help("Next match (Return)")
|
||||
.safeHelp("Next match (Return)")
|
||||
|
||||
Button(action: {
|
||||
#if DEBUG
|
||||
|
|
@ -84,7 +84,7 @@ struct BrowserSearchOverlay: View {
|
|||
Image(systemName: "chevron.down")
|
||||
}
|
||||
.buttonStyle(SearchButtonStyle())
|
||||
.help("Previous match (Shift+Return)")
|
||||
.safeHelp("Previous match (Shift+Return)")
|
||||
|
||||
Button(action: {
|
||||
#if DEBUG
|
||||
|
|
@ -95,7 +95,7 @@ struct BrowserSearchOverlay: View {
|
|||
Image(systemName: "xmark")
|
||||
}
|
||||
.buttonStyle(SearchButtonStyle())
|
||||
.help("Close (Esc)")
|
||||
.safeHelp("Close (Esc)")
|
||||
}
|
||||
.padding(8)
|
||||
.background(.background)
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ struct SurfaceSearchOverlay: View {
|
|||
Image(systemName: "chevron.up")
|
||||
}
|
||||
.buttonStyle(SearchButtonStyle())
|
||||
.help(String(localized: "search.nextMatch.help", defaultValue: "Next match (Return)"))
|
||||
.safeHelp(String(localized: "search.nextMatch.help", defaultValue: "Next match (Return)"))
|
||||
|
||||
Button(action: {
|
||||
#if DEBUG
|
||||
|
|
@ -99,7 +99,7 @@ struct SurfaceSearchOverlay: View {
|
|||
Image(systemName: "chevron.down")
|
||||
}
|
||||
.buttonStyle(SearchButtonStyle())
|
||||
.help(String(localized: "search.previousMatch.help", defaultValue: "Previous match (Shift+Return)"))
|
||||
.safeHelp(String(localized: "search.previousMatch.help", defaultValue: "Previous match (Shift+Return)"))
|
||||
|
||||
Button(action: {
|
||||
#if DEBUG
|
||||
|
|
@ -110,7 +110,7 @@ struct SurfaceSearchOverlay: View {
|
|||
Image(systemName: "xmark")
|
||||
}
|
||||
.buttonStyle(SearchButtonStyle())
|
||||
.help(String(localized: "search.close.help", defaultValue: "Close (Esc)"))
|
||||
.safeHelp(String(localized: "search.close.help", defaultValue: "Close (Esc)"))
|
||||
}
|
||||
.padding(8)
|
||||
.background(.background)
|
||||
|
|
|
|||
|
|
@ -4688,6 +4688,9 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations {
|
|||
if let windowObserver {
|
||||
NotificationCenter.default.removeObserver(windowObserver)
|
||||
}
|
||||
if let trackingArea {
|
||||
removeTrackingArea(trackingArea)
|
||||
}
|
||||
terminalSurface = nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import Bonsplit
|
||||
import SwiftUI
|
||||
|
||||
struct NotificationsPage: View {
|
||||
|
|
@ -113,7 +114,7 @@ struct NotificationsPage: View {
|
|||
}
|
||||
.buttonStyle(.bordered)
|
||||
.keyboardShortcut(key, modifiers: jumpToUnreadShortcut.eventModifiers)
|
||||
.help(KeyboardShortcutSettings.Action.jumpToUnread.tooltip(String(localized: "notifications.jumpToLatestUnread", defaultValue: "Jump to Latest Unread")))
|
||||
.safeHelp(KeyboardShortcutSettings.Action.jumpToUnread.tooltip(String(localized: "notifications.jumpToLatestUnread", defaultValue: "Jump to Latest Unread")))
|
||||
.disabled(!hasUnreadNotifications)
|
||||
} else {
|
||||
Button(action: {
|
||||
|
|
@ -125,7 +126,7 @@ struct NotificationsPage: View {
|
|||
}
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.help(KeyboardShortcutSettings.Action.jumpToUnread.tooltip(String(localized: "notifications.jumpToLatestUnread", defaultValue: "Jump to Latest Unread")))
|
||||
.safeHelp(KeyboardShortcutSettings.Action.jumpToUnread.tooltip(String(localized: "notifications.jumpToLatestUnread", defaultValue: "Jump to Latest Unread")))
|
||||
.disabled(!hasUnreadNotifications)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -538,7 +538,7 @@ struct BrowserPanelView: View {
|
|||
.buttonStyle(OmnibarAddressButtonStyle())
|
||||
.disabled(!panel.canGoBack)
|
||||
.opacity(panel.canGoBack ? 1.0 : 0.4)
|
||||
.help(String(localized: "browser.goBack", defaultValue: "Go Back"))
|
||||
.safeHelp(String(localized: "browser.goBack", defaultValue: "Go Back"))
|
||||
|
||||
Button(action: {
|
||||
#if DEBUG
|
||||
|
|
@ -554,7 +554,7 @@ struct BrowserPanelView: View {
|
|||
.buttonStyle(OmnibarAddressButtonStyle())
|
||||
.disabled(!panel.canGoForward)
|
||||
.opacity(panel.canGoForward ? 1.0 : 0.4)
|
||||
.help(String(localized: "browser.goForward", defaultValue: "Go Forward"))
|
||||
.safeHelp(String(localized: "browser.goForward", defaultValue: "Go Forward"))
|
||||
|
||||
Button(action: {
|
||||
if panel.isLoading {
|
||||
|
|
@ -575,7 +575,7 @@ struct BrowserPanelView: View {
|
|||
.contentShape(Rectangle())
|
||||
}
|
||||
.buttonStyle(OmnibarAddressButtonStyle())
|
||||
.help(panel.isLoading ? String(localized: "browser.stop", defaultValue: "Stop") : String(localized: "browser.reload", defaultValue: "Reload"))
|
||||
.safeHelp(panel.isLoading ? String(localized: "browser.stop", defaultValue: "Stop") : String(localized: "browser.reload", defaultValue: "Reload"))
|
||||
|
||||
if panel.isDownloading {
|
||||
HStack(spacing: 4) {
|
||||
|
|
@ -586,7 +586,7 @@ struct BrowserPanelView: View {
|
|||
.foregroundStyle(.secondary)
|
||||
}
|
||||
.padding(.leading, 6)
|
||||
.help(String(localized: "browser.downloadInProgress", defaultValue: "Download in progress"))
|
||||
.safeHelp(String(localized: "browser.downloadInProgress", defaultValue: "Download in progress"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -604,7 +604,7 @@ struct BrowserPanelView: View {
|
|||
}
|
||||
.buttonStyle(OmnibarAddressButtonStyle())
|
||||
.frame(width: addressBarButtonSize, height: addressBarButtonSize, alignment: .center)
|
||||
.help(KeyboardShortcutSettings.Action.toggleBrowserDeveloperTools.tooltip(String(localized: "browser.toggleDevTools", defaultValue: "Toggle Developer Tools")))
|
||||
.safeHelp(KeyboardShortcutSettings.Action.toggleBrowserDeveloperTools.tooltip(String(localized: "browser.toggleDevTools", defaultValue: "Toggle Developer Tools")))
|
||||
.accessibilityIdentifier("BrowserToggleDevToolsButton")
|
||||
}
|
||||
|
||||
|
|
@ -624,7 +624,7 @@ struct BrowserPanelView: View {
|
|||
.popover(isPresented: $isBrowserThemeMenuPresented, arrowEdge: .bottom) {
|
||||
browserThemeModePopover
|
||||
}
|
||||
.help("Browser Theme: \(browserThemeMode.displayName)")
|
||||
.safeHelp("Browser Theme: \(browserThemeMode.displayName)")
|
||||
.accessibilityIdentifier("BrowserThemeModeButton")
|
||||
}
|
||||
|
||||
|
|
@ -3139,6 +3139,13 @@ struct WebViewRepresentable: NSViewRepresentable {
|
|||
private var hasLoggedMissingHostedInspectorCandidate = false
|
||||
#endif
|
||||
|
||||
deinit {
|
||||
if let trackingArea {
|
||||
removeTrackingArea(trackingArea)
|
||||
}
|
||||
clearActiveDividerCursor(restoreArrow: false)
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
private static func shouldLogPointerEvent(_ event: NSEvent?) -> Bool {
|
||||
switch event?.type {
|
||||
|
|
|
|||
|
|
@ -10238,81 +10238,91 @@ class TerminalController {
|
|||
return "OK"
|
||||
}
|
||||
|
||||
private func simulateShortcut(_ args: String) -> String {
|
||||
let combo = args.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !combo.isEmpty else {
|
||||
return "ERROR: Usage: simulate_shortcut <combo>"
|
||||
}
|
||||
guard let parsed = parseShortcutCombo(combo) else {
|
||||
return "ERROR: Invalid combo. Example: cmd+ctrl+h"
|
||||
}
|
||||
private func prepareWindowForSyntheticInput(_ window: NSWindow?) {
|
||||
guard let window else { return }
|
||||
|
||||
// Stamp at socket-handler arrival so event.timestamp includes any wait
|
||||
// before the main-thread event dispatch.
|
||||
let requestTimestamp = ProcessInfo.processInfo.systemUptime
|
||||
|
||||
var result = "ERROR: Failed to create event"
|
||||
DispatchQueue.main.sync {
|
||||
// Prefer the current active-tab-manager window so shortcut simulation stays
|
||||
// scoped to the intended window even when NSApp.keyWindow is stale.
|
||||
let targetWindow: NSWindow? = {
|
||||
if let activeTabManager = self.tabManager,
|
||||
let windowId = AppDelegate.shared?.windowId(for: activeTabManager),
|
||||
let window = AppDelegate.shared?.mainWindow(for: windowId) {
|
||||
return window
|
||||
}
|
||||
return NSApp.keyWindow
|
||||
?? NSApp.mainWindow
|
||||
?? NSApp.windows.first(where: { $0.isVisible })
|
||||
?? NSApp.windows.first
|
||||
}()
|
||||
if let targetWindow {
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
targetWindow.makeKeyAndOrderFront(nil)
|
||||
}
|
||||
let windowNumber = targetWindow?.windowNumber ?? 0
|
||||
guard let keyDownEvent = NSEvent.keyEvent(
|
||||
with: .keyDown,
|
||||
location: .zero,
|
||||
modifierFlags: parsed.modifierFlags,
|
||||
timestamp: requestTimestamp,
|
||||
windowNumber: windowNumber,
|
||||
context: nil,
|
||||
characters: parsed.characters,
|
||||
charactersIgnoringModifiers: parsed.charactersIgnoringModifiers,
|
||||
isARepeat: false,
|
||||
keyCode: parsed.keyCode
|
||||
) else {
|
||||
result = "ERROR: NSEvent.keyEvent returned nil"
|
||||
return
|
||||
}
|
||||
let keyUpEvent = NSEvent.keyEvent(
|
||||
with: .keyUp,
|
||||
location: .zero,
|
||||
modifierFlags: parsed.modifierFlags,
|
||||
timestamp: requestTimestamp + 0.0001,
|
||||
windowNumber: windowNumber,
|
||||
context: nil,
|
||||
characters: parsed.characters,
|
||||
charactersIgnoringModifiers: parsed.charactersIgnoringModifiers,
|
||||
isARepeat: false,
|
||||
keyCode: parsed.keyCode
|
||||
)
|
||||
// Socket-driven shortcut simulation should reuse the exact same matching logic as the
|
||||
// app-level shortcut monitor (so tests are hermetic), while still falling back to the
|
||||
// normal responder chain for plain typing.
|
||||
if let delegate = AppDelegate.shared, delegate.debugHandleCustomShortcut(event: keyDownEvent) {
|
||||
result = "OK"
|
||||
return
|
||||
}
|
||||
NSApp.sendEvent(keyDownEvent)
|
||||
if let keyUpEvent {
|
||||
NSApp.sendEvent(keyUpEvent)
|
||||
}
|
||||
result = "OK"
|
||||
}
|
||||
return result
|
||||
}
|
||||
// Keep socket-driven input simulation focused on the intended window without
|
||||
// paying repeated activation/order-front costs for every synthetic key event.
|
||||
if !NSApp.isActive {
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
}
|
||||
if !window.isKeyWindow || !window.isVisible {
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func simulateShortcut(_ args: String) -> String {
|
||||
let combo = args.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !combo.isEmpty else {
|
||||
return "ERROR: Usage: simulate_shortcut <combo>"
|
||||
}
|
||||
guard let parsed = parseShortcutCombo(combo) else {
|
||||
return "ERROR: Invalid combo. Example: cmd+ctrl+h"
|
||||
}
|
||||
|
||||
// Stamp at socket-handler arrival so event.timestamp includes any wait
|
||||
// before the main-thread event dispatch.
|
||||
let requestTimestamp = ProcessInfo.processInfo.systemUptime
|
||||
|
||||
var result = "ERROR: Failed to create event"
|
||||
DispatchQueue.main.sync {
|
||||
// Prefer the current active-tab-manager window so shortcut simulation stays
|
||||
// scoped to the intended window even when NSApp.keyWindow is stale.
|
||||
let targetWindow: NSWindow? = {
|
||||
if let activeTabManager = self.tabManager,
|
||||
let windowId = AppDelegate.shared?.windowId(for: activeTabManager),
|
||||
let window = AppDelegate.shared?.mainWindow(for: windowId) {
|
||||
return window
|
||||
}
|
||||
return NSApp.keyWindow
|
||||
?? NSApp.mainWindow
|
||||
?? NSApp.windows.first(where: { $0.isVisible })
|
||||
?? NSApp.windows.first
|
||||
}()
|
||||
prepareWindowForSyntheticInput(targetWindow)
|
||||
let windowNumber = targetWindow?.windowNumber ?? 0
|
||||
guard let keyDownEvent = NSEvent.keyEvent(
|
||||
with: .keyDown,
|
||||
location: .zero,
|
||||
modifierFlags: parsed.modifierFlags,
|
||||
timestamp: requestTimestamp,
|
||||
windowNumber: windowNumber,
|
||||
context: nil,
|
||||
characters: parsed.characters,
|
||||
charactersIgnoringModifiers: parsed.charactersIgnoringModifiers,
|
||||
isARepeat: false,
|
||||
keyCode: parsed.keyCode
|
||||
) else {
|
||||
result = "ERROR: NSEvent.keyEvent returned nil"
|
||||
return
|
||||
}
|
||||
let keyUpEvent = NSEvent.keyEvent(
|
||||
with: .keyUp,
|
||||
location: .zero,
|
||||
modifierFlags: parsed.modifierFlags,
|
||||
timestamp: requestTimestamp + 0.0001,
|
||||
windowNumber: windowNumber,
|
||||
context: nil,
|
||||
characters: parsed.characters,
|
||||
charactersIgnoringModifiers: parsed.charactersIgnoringModifiers,
|
||||
isARepeat: false,
|
||||
keyCode: parsed.keyCode
|
||||
)
|
||||
// Socket-driven shortcut simulation should reuse the exact same matching logic as the
|
||||
// app-level shortcut monitor (so tests are hermetic), while still falling back to the
|
||||
// normal responder chain for plain typing.
|
||||
if let delegate = AppDelegate.shared, delegate.debugHandleCustomShortcut(event: keyDownEvent) {
|
||||
result = "OK"
|
||||
return
|
||||
}
|
||||
NSApp.sendEvent(keyDownEvent)
|
||||
if let keyUpEvent {
|
||||
NSApp.sendEvent(keyUpEvent)
|
||||
}
|
||||
result = "OK"
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private func activateApp() -> String {
|
||||
DispatchQueue.main.sync {
|
||||
|
|
@ -10357,8 +10367,7 @@ class TerminalController {
|
|||
?? NSApp.mainWindow
|
||||
?? NSApp.windows.first(where: { $0.isVisible })
|
||||
?? NSApp.windows.first else { return }
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
prepareWindowForSyntheticInput(window)
|
||||
guard let fr = window.firstResponder else {
|
||||
result = "ERROR: No first responder"
|
||||
return
|
||||
|
|
|
|||
|
|
@ -54,6 +54,13 @@ final class WindowTerminalHostView: NSView {
|
|||
private var lastDragRouteSignature: String?
|
||||
#endif
|
||||
|
||||
deinit {
|
||||
if let trackingArea {
|
||||
removeTrackingArea(trackingArea)
|
||||
}
|
||||
clearActiveDividerCursor(restoreArrow: false)
|
||||
}
|
||||
|
||||
override func viewDidMoveToWindow() {
|
||||
super.viewDidMoveToWindow()
|
||||
if window == nil {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import AppKit
|
||||
import Bonsplit
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ struct UpdatePill: View {
|
|||
.contentShape(Capsule())
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.help(model.text)
|
||||
.safeHelp(model.text)
|
||||
.accessibilityLabel(model.text)
|
||||
.accessibilityIdentifier("UpdatePill")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ struct TitlebarControlsView: View {
|
|||
}
|
||||
|
||||
var body: some View {
|
||||
// Force the `.help(...)` tooltips to re-evaluate when shortcuts are changed in settings.
|
||||
// Force the `.safeHelp(...)` tooltips to re-evaluate when shortcuts are changed in settings.
|
||||
// (The titlebar controls don't otherwise re-render on UserDefaults changes.)
|
||||
let _ = shortcutRefreshTick
|
||||
let style = TitlebarControlsStyle(rawValue: styleRawValue) ?? .classic
|
||||
|
|
@ -321,7 +321,7 @@ struct TitlebarControlsView: View {
|
|||
}
|
||||
.accessibilityIdentifier("titlebarControl.toggleSidebar")
|
||||
.accessibilityLabel(String(localized: "titlebar.sidebar.accessibilityLabel", defaultValue: "Toggle Sidebar"))
|
||||
.help(KeyboardShortcutSettings.Action.toggleSidebar.tooltip(String(localized: "titlebar.sidebar.tooltip", defaultValue: "Show or hide the sidebar")))
|
||||
.safeHelp(KeyboardShortcutSettings.Action.toggleSidebar.tooltip(String(localized: "titlebar.sidebar.tooltip", defaultValue: "Show or hide the sidebar")))
|
||||
|
||||
TitlebarControlButton(config: config, action: {
|
||||
#if DEBUG
|
||||
|
|
@ -348,7 +348,7 @@ struct TitlebarControlsView: View {
|
|||
.accessibilityIdentifier("titlebarControl.showNotifications")
|
||||
.background(NotificationsAnchorView { viewModel.notificationsAnchorView = $0 })
|
||||
.accessibilityLabel(String(localized: "titlebar.notifications.accessibilityLabel", defaultValue: "Notifications"))
|
||||
.help(KeyboardShortcutSettings.Action.showNotifications.tooltip(String(localized: "titlebar.notifications.tooltip", defaultValue: "Show notifications")))
|
||||
.safeHelp(KeyboardShortcutSettings.Action.showNotifications.tooltip(String(localized: "titlebar.notifications.tooltip", defaultValue: "Show notifications")))
|
||||
|
||||
TitlebarControlButton(config: config, action: {
|
||||
#if DEBUG
|
||||
|
|
@ -360,7 +360,7 @@ struct TitlebarControlsView: View {
|
|||
}
|
||||
.accessibilityIdentifier("titlebarControl.newTab")
|
||||
.accessibilityLabel(String(localized: "titlebar.newWorkspace.accessibilityLabel", defaultValue: "New Workspace"))
|
||||
.help(KeyboardShortcutSettings.Action.newTab.tooltip(String(localized: "titlebar.newWorkspace.tooltip", defaultValue: "New workspace")))
|
||||
.safeHelp(KeyboardShortcutSettings.Action.newTab.tooltip(String(localized: "titlebar.newWorkspace.tooltip", defaultValue: "New workspace")))
|
||||
}
|
||||
|
||||
let paddedContent = content.padding(config.groupPadding)
|
||||
|
|
|
|||
2
vendor/bonsplit
vendored
2
vendor/bonsplit
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit 89a4fd1288a706ae4b766f323191d6570b7123aa
|
||||
Subproject commit c5b3dd4cd314f7452bd27ffacd00ebeb19d96d17
|
||||
Loading…
Add table
Add a link
Reference in a new issue