Skip to content

Commit

Permalink
fix: better position preview for fullscreen windows (closes #4051)
Browse files Browse the repository at this point in the history
  • Loading branch information
lwouis committed Jan 2, 2025
1 parent bc9f97f commit 3b0cba4
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 27 deletions.
9 changes: 0 additions & 9 deletions src/logic/Window.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ class Window {
var creationOrder = Int.zero
var title: String!
var thumbnail: NSImage?
var thumbnailFullSize: NSSize?
var icon: NSImage? { get { application.icon } }
var shouldShowTheUser = true
var isTabbed: Bool = false
Expand Down Expand Up @@ -99,7 +98,6 @@ class Window {

func refreshThumbnail(_ screenshot: NSImage?) {
thumbnail = screenshot
thumbnailFullSize = screenshot?.size
if App.app.appIsBeingUsed && shouldShowTheUser {
if let index = (Windows.list.firstIndex { $0.cgWindowId == cgWindowId }) {
let view = ThumbnailsView.recycledViews[index]
Expand All @@ -113,13 +111,6 @@ class Window {
}
}

func getPreview() -> (NSImage, NSSize)? {
if let thumbnail = thumbnail, let thumbnailFullSize = thumbnailFullSize {
return (thumbnail, thumbnailFullSize)
}
return nil
}

func canBeClosed() -> Bool {
return !isWindowlessApp
}
Expand Down
21 changes: 9 additions & 12 deletions src/logic/Windows.swift
Original file line number Diff line number Diff line change
Expand Up @@ -147,20 +147,17 @@ class Windows {
}

static func previewFocusedWindowIfNeeded() {
guard
Preferences.previewFocusedWindow,
!Preferences.onlyShowApplications(),
App.app.appIsBeingUsed && App.app.thumbnailsPanel.isKeyWindow,
let window = focusedWindow(),
let id = window.cgWindowId,
let (preview, previewSize) = window.getPreview(),
let position = window.position,
let size = window.size
else {
if Preferences.previewFocusedWindow && !Preferences.onlyShowApplications()
&& App.app.appIsBeingUsed && App.app.thumbnailsPanel.isKeyWindow,
let window = focusedWindow(),
let id = window.cgWindowId,
let thumbnail = window.thumbnail,
let position = window.position,
let size = window.size {
App.app.previewPanel.show(id, thumbnail, position, size)
} else {
App.app.previewPanel.orderOut(nil)
return
}
App.app.previewPanel.show(id, preview, previewSize, position, size)
}

static func voiceOverWindow(_ windowIndex: Int = focusedWindowIndex) {
Expand Down
14 changes: 8 additions & 6 deletions src/ui/main-window/PreviewPanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ class PreviewPanel: NSPanel {
private let borderView = BorderView()
private var currentId: CGWindowID?

/// this allows the window to be above the menubar when its origin.y is set to 0
override func constrainFrameRect(_ frameRect: NSRect, to screen: NSScreen?) -> NSRect {
frameRect
}

convenience init() {
self.init(contentRect: .zero, styleMask: [.nonactivatingPanel, .titled, .fullSizeContentView], backing: .buffered, defer: false)
isFloatingPanel = true
Expand All @@ -18,17 +23,14 @@ class PreviewPanel: NSPanel {
previewView.addSubview(borderView)
// 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
// highest level is .screenSaver but makes drag and drop on top the main window impossible
level = .popUpMenu
// helps filter out this window from the thumbnails
setAccessibilitySubrole(.unknown)
}

func show(_ id: CGWindowID, _ preview: NSImage, _ previewSize: NSSize, _ position: CGPoint, _ size: CGSize) {
func show(_ id: CGWindowID, _ preview: NSImage, _ position: CGPoint, _ size: CGSize) {
if id != currentId {
previewView.image = preview
previewView.image!.size = previewSize
previewView.image!.size = size
var frame = NSRect(origin: position, size: size)
// Flip Y coordinate from Quartz (0,0 at bottom-left) to Cocoa coordinates (0,0 at top-left)
// Always use the primary screen as reference since all coordinates are relative to it
Expand All @@ -48,7 +50,7 @@ class PreviewPanel: NSPanel {
// 2. Select a window in the switcher that is on the same monitor as the thumbnails panel, and whose position overlaps with the thumbnails panel
// 3. For a single frame, the preview of the newly selected window can appear above the thumbnails panel before going back underneath it
// Simply using order(.below) is not sufficient to prevent this brief flicker. We explicitly set the preview panel's window level to be one below the thumbnails panel
App.app.previewPanel.level = NSWindow.Level(rawValue: App.app.previewPanel.level.rawValue - 1)
App.app.previewPanel.level = NSWindow.Level(rawValue: App.app.thumbnailsPanel.level.rawValue - 1)
}
}
}
Expand Down

0 comments on commit 3b0cba4

Please sign in to comment.