mirror of
https://github.com/lwouis/alt-tab-macos.git
synced 2026-05-24 11:20:36 +00:00
feat: support voiceover + "speak items under the cursor" (closes #1070)
This commit is contained in:
@@ -72,6 +72,15 @@ class Windows {
|
||||
let focusedView = ThumbnailsView.recycledViews[focusedWindowIndex]
|
||||
focusedView.highlight(true)
|
||||
App.app.thumbnailsPanel.thumbnailsView.scrollView.contentView.scrollToVisible(focusedView.frame)
|
||||
voiceOverFocusedWindow()
|
||||
}
|
||||
|
||||
static func voiceOverFocusedWindow() {
|
||||
guard App.app.appIsBeingUsed && App.app.thumbnailsPanel.isKeyWindow else { return }
|
||||
let window = ThumbnailsView.recycledViews[focusedWindowIndex]
|
||||
if window.window_ != nil && window.window != nil {
|
||||
App.app.thumbnailsPanel.makeFirstResponder(window)
|
||||
}
|
||||
}
|
||||
|
||||
static func focusedWindow() -> Window? {
|
||||
|
||||
@@ -217,6 +217,7 @@ class App: AppCenterApplication, NSApplicationDelegate {
|
||||
thumbnailsPanel.thumbnailsView.updateItemsAndLayout(currentScreen)
|
||||
guard appIsBeingUsed else { return }
|
||||
thumbnailsPanel.setContentSize(thumbnailsPanel.thumbnailsView.frame.size)
|
||||
Windows.voiceOverFocusedWindow() // at this point ThumbnailViews are assigned to the window, and ready
|
||||
thumbnailsPanel.display()
|
||||
guard appIsBeingUsed else { return }
|
||||
currentScreen.repositionPanel(thumbnailsPanel, .appleCentered)
|
||||
|
||||
@@ -22,6 +22,12 @@ class ThumbnailView: NSStackView {
|
||||
var isShowingWindowControls = false
|
||||
var windowlessIcon = FontIcon(.newWindow)
|
||||
|
||||
// for VoiceOver cursor
|
||||
override var canBecomeKeyView: Bool { true }
|
||||
override var acceptsFirstResponder: Bool { true }
|
||||
|
||||
override func isAccessibilityElement() -> Bool { true }
|
||||
|
||||
convenience init() {
|
||||
self.init(frame: .zero)
|
||||
setupView()
|
||||
@@ -44,6 +50,7 @@ class ThumbnailView: NSStackView {
|
||||
addWindowControls()
|
||||
addDockLabelIcon()
|
||||
thumbnail.addSubview(windowlessIcon, positioned: .above, relativeTo: nil)
|
||||
setAccessibilityChildren([])
|
||||
}
|
||||
|
||||
private func addDockLabelIcon() {
|
||||
@@ -109,6 +116,7 @@ class ThumbnailView: NSStackView {
|
||||
let thumbnailSize = NSSize(width: thumbnailWidth.rounded(), height: thumbnailHeight.rounded())
|
||||
thumbnail.image?.size = thumbnailSize
|
||||
thumbnail.frame.size = thumbnailSize
|
||||
thumbnail.setAccessibilityLabel(element.title)
|
||||
}
|
||||
assignIfDifferent(&spacing, Preferences.hideThumbnails ? 0 : Preferences.intraCellPadding)
|
||||
assignIfDifferent(&hStackView.spacing, Preferences.fontHeight == 0 ? 0 : Preferences.intraCellPadding)
|
||||
@@ -117,12 +125,14 @@ class ThumbnailView: NSStackView {
|
||||
let appIconSize = NSSize(width: Preferences.iconSize, height: Preferences.iconSize)
|
||||
appIcon.image?.size = appIconSize
|
||||
appIcon.frame.size = appIconSize
|
||||
appIcon.setAccessibilityTitle(element.application.runningApplication.localizedName)
|
||||
}
|
||||
let labelChanged = label.string != element.title
|
||||
if labelChanged {
|
||||
label.string = element.title
|
||||
// workaround: setting string on NSTextView changes the font (most likely a Cocoa bug)
|
||||
label.font = Preferences.font
|
||||
setAccessibilityTitle(element.title)
|
||||
}
|
||||
assignIfDifferent(&hiddenIcon.isHidden, !element.isHidden || Preferences.hideStatusIcons)
|
||||
assignIfDifferent(&fullscreenIcon.isHidden, !element.isFullscreen || Preferences.hideStatusIcons)
|
||||
@@ -169,8 +179,10 @@ class ThumbnailView: NSStackView {
|
||||
let view = dockLabelIcon.subviews[1] as! ThumbnailFontIconView
|
||||
if dockLabel > 30 {
|
||||
view.setFilledStar()
|
||||
view.setAccessibilityLabel("Red badge with star")
|
||||
} else {
|
||||
view.setNumber(dockLabel, true)
|
||||
view.setAccessibilityLabel("Red badge with number \(dockLabel)")
|
||||
}
|
||||
dockLabelIcon.setFrameOrigin(NSPoint(x: appIcon.frame.maxX - dockLabelIcon.fittingSize.width - 1, y: appIcon.frame.maxY - dockLabelIcon.fittingSize.height + 4))
|
||||
}
|
||||
|
||||
@@ -14,8 +14,6 @@ class ThumbnailsPanel: NSPanel, NSWindowDelegate {
|
||||
titleVisibility = .hidden
|
||||
backgroundColor = .clear
|
||||
contentView!.addSubview(thumbnailsView)
|
||||
preservesContentDuringLiveResize = false
|
||||
disableSnapshotRestoration()
|
||||
// triggering AltTab before or during Space transition animation brings the window on the Space post-transition
|
||||
collectionBehavior = .canJoinAllSpaces
|
||||
// 2nd highest level possible; this allows the app to go on top of context menus
|
||||
@@ -23,6 +21,8 @@ class ThumbnailsPanel: NSPanel, NSWindowDelegate {
|
||||
level = .popUpMenu
|
||||
// helps filter out this window from the thumbnails
|
||||
setAccessibilitySubrole(.unknown)
|
||||
// for VoiceOver
|
||||
setAccessibilityLabel(App.name)
|
||||
}
|
||||
|
||||
func windowDidResignKey(_ notification: Notification) {
|
||||
|
||||
@@ -14,6 +14,8 @@ class WindowControlView: NSImageView {
|
||||
originalImage = image
|
||||
hoveredImage = image.tinted(.init(white: 0, alpha: 0.25))
|
||||
hovered(false)
|
||||
setAccessibilityLabel(imageName)
|
||||
setAccessibilityRole(.button)
|
||||
}
|
||||
|
||||
func hovered(_ isHovered: Bool) {
|
||||
|
||||
Reference in New Issue
Block a user