Skip to content

Commit

Permalink
feat: windows on mouse screen, implements lwouis#28
Browse files Browse the repository at this point in the history
- adds a new Preference to use the main screen (keyboard focus) or mouse location screen
- honors that preference for thumbnail generation and display of all panels
- increases the Preferences version
- widens PreferencesPanel width and input sizing to allow 3 characters, issue lwouis#59 minimal adjustment
  • Loading branch information
gingerr committed Oct 30, 2019
1 parent 83ddb35 commit c458396
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 13 deletions.
18 changes: 16 additions & 2 deletions alt-tab-macos/logic/Preferences.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,23 @@ import Foundation
import Cocoa
import Carbon.HIToolbox.Events

enum ShowOnScreenPreference {
case MAIN
case MOUSE
}

class Preferences {
static var defaults: [String: String] = [
"version": "2", // bump this anytime the dictionary is changed
"version": "3", // bump this anytime the dictionary is changed
"maxScreenUsage": "80",
"maxThumbnailsPerRow": "4",
"iconSize": "32",
"fontHeight": "15",
"tabKeyCode": String(kVK_Tab),
"metaKey": metaKeyMacro.macros[0].label,
"windowDisplayDelay": "0",
"theme": themeMacro.macros[0].label
"theme": themeMacro.macros[0].label,
"showOnScreen": showOnScreenMacro.macros[0].label
]
static var rawValues = [String: String]()
static var thumbnailMaxWidth: CGFloat = 200
Expand All @@ -37,6 +43,7 @@ class Preferences {
static var windowDisplayDelay: DispatchTimeInterval?
static var windowCornerRadius: CGFloat?
static var font: NSFont?
static var showOnScreen: ShowOnScreenPreference?
static var themeMacro = MacroPreferenceHelper<(CGFloat, CGFloat, CGFloat, NSColor, NSColor)>([
MacroPreference(" macOS", (0, 5, 20, .clear, NSColor(red: 0, green: 0, blue: 0, alpha: 0.3))),
MacroPreference("❖ Windows 10", (2, 0, 0, .white, .clear))
Expand All @@ -46,6 +53,10 @@ class Preferences {
MacroPreference("⌃ control", ([kVK_Control, kVK_RightControl], .control)),
MacroPreference("⌘ command", ([kVK_Command, kVK_RightCommand], .command))
])
static var showOnScreenMacro = MacroPreferenceHelper<(ShowOnScreenPreference)>([
MacroPreference("with keyboard focus", (ShowOnScreenPreference.MAIN)),
MacroPreference("with mouse pointer", (ShowOnScreenPreference.MOUSE)),
])

private static let defaultsFile = fileFromPreferencesFolder("alt-tab-macos-defaults.json")
private static let userFile = fileFromPreferencesFolder("alt-tab-macos.json")
Expand Down Expand Up @@ -89,6 +100,9 @@ class Preferences {
highlightBackgroundColor = p.preferences.4
case "windowDisplayDelay":
windowDisplayDelay = DispatchTimeInterval.milliseconds(try Int(value).orThrow())
case "showOnScreen":
let p = try showOnScreenMacro.labelToMacro[value].orThrow()
showOnScreen = p.preferences
default:
throw "Tried to update an unknown preference: '\(valueName)' = '\(value)'"
}
Expand Down
18 changes: 16 additions & 2 deletions alt-tab-macos/logic/Screen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,23 @@ class Screen {

static func updateThumbnailMaxSize() -> Void {
if Preferences.thumbnailMaxWidth == 200 && Preferences.thumbnailMaxHeight == 200 {
let main = NSScreen.main!.frame
let screenFrame = getPreferredScreen().frame
Preferences.thumbnailMaxWidth = (NSScreen.main!.frame.size.width * Preferences.maxScreenUsage! - Preferences.windowPadding * 2) / Preferences.maxThumbnailsPerRow! - Preferences.interItemPadding
Preferences.thumbnailMaxHeight = Preferences.thumbnailMaxWidth * (main.height / main.width)
Preferences.thumbnailMaxHeight = Preferences.thumbnailMaxWidth * (screenFrame.height / screenFrame.width)
}
}

static func getPreferredScreen() -> NSScreen {
switch Preferences.showOnScreen! {
case .MOUSE:
return getScreenWithMouse() ?? NSScreen.main!; // .main as fail-safe
default: // no case for .MAIN since its currently the same as default case
return NSScreen.main!;
}
}

// https://stackoverflow.com/a/49624487/4767781
static func getScreenWithMouse() -> NSScreen? {
return NSScreen.screens.first { NSMouseInRect(NSEvent.mouseLocation, $0.frame, false) }
}
}
13 changes: 8 additions & 5 deletions alt-tab-macos/ui/Application.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,13 @@ class Application: NSApplication, NSApplicationDelegate, NSWindowDelegate {
}

@objc func showCenteredPreferencesPanel() {
showCenteredPanel(preferencesPanel!)
showCenteredFrontPanel(preferencesPanel!)
}

func showCenteredPanel(_ panel: NSPanel) {
panel.center()
func showCenteredFrontPanel(_ panel: NSPanel, _ screenOverride: NSScreen? = nil) {
let preferredScreen = screenOverride ?? Screen.getPreferredScreen() // use optional provided screen or determine it just in time
let centerPosition = NSPoint(x: preferredScreen.visibleFrame.midX - panel.frame.width / 2, y: preferredScreen.visibleFrame.midY - panel.frame.height / 2)
panel.setFrameOrigin(centerPosition)
panel.makeKeyAndOrderFront(nil)
Application.shared.arrangeInFront(nil)
}
Expand Down Expand Up @@ -109,11 +111,12 @@ class Application: NSApplication, NSApplicationDelegate, NSWindowDelegate {
return
}
selectedOpenWindow = cellWithStep(step)
let preferredScreen = Screen.getPreferredScreen() // we want the thumbnail computation and panel display use the same screen (in case mouse movements switching screens etc.)
var workItem: DispatchWorkItem!
workItem = DispatchWorkItem {
if !workItem.isCancelled { self.thumbnailsPanel!.computeThumbnails() }
if !workItem.isCancelled { self.thumbnailsPanel!.computeThumbnails(preferredScreen) }
if !workItem.isCancelled { self.thumbnailsPanel!.highlightCellAt(step) }
if !workItem.isCancelled { self.showCenteredPanel(self.thumbnailsPanel!) }
if !workItem.isCancelled { self.showCenteredFrontPanel(self.thumbnailsPanel!, preferredScreen) }
}
workItems.append(workItem)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Preferences.windowDisplayDelay!, execute: workItem)
Expand Down
8 changes: 6 additions & 2 deletions alt-tab-macos/ui/PreferencesPanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class PreferencesPanel: NSPanel, NSTextViewDelegate {
var windowDisplayDelay: NSTextView?
var metaKey: NSPopUpButton?
var theme: NSPopUpButton?
var showOnScreen: NSPopUpButton?
var inputsMap = [NSTextView: String]()

override init(contentRect: NSRect, styleMask style: StyleMask, backing backingStoreType: BackingStoreType, defer flag: Bool) {
Expand All @@ -34,14 +35,15 @@ class PreferencesPanel: NSPanel, NSTextViewDelegate {
makeLabelWithInput(\PreferencesPanel.iconSize, "Apps icon size (px)", "iconSize"),
makeLabelWithInput(\PreferencesPanel.fontHeight, "Font size (px)", "fontHeight"),
makeLabelWithInput(\PreferencesPanel.windowDisplayDelay, "Window apparition delay (ms)", "windowDisplayDelay"),
makeLabelWithDropdown(\PreferencesPanel.showOnScreen, "Show on Screen", "showOnScreen", Preferences.showOnScreenMacro.labels)
]
}

private func makeGridView(_ rows: [[NSView]], _ warningLabel: BaseLabel) -> NSGridView {
let gridView = NSGridView(views: rows)
gridView.setContentHuggingPriority(.defaultLow, for: .horizontal)
gridView.setContentHuggingPriority(.defaultLow, for: .vertical)
gridView.widthAnchor.constraint(greaterThanOrEqualToConstant: 360).isActive = true
gridView.widthAnchor.constraint(greaterThanOrEqualToConstant: 380).isActive = true
gridView.addRow(with: [warningLabel, NSGridCell.emptyContentView])
gridView.mergeCells(inHorizontalRange: NSRange(location: 0, length: 2), verticalRange: NSRange(location: gridView.numberOfRows - 1, length: 1))
return gridView
Expand All @@ -61,7 +63,7 @@ class PreferencesPanel: NSPanel, NSTextViewDelegate {
input.delegate = self
input.font = Preferences.font
input.string = Preferences.rawValues[rawName]!
input.widthAnchor.constraint(equalToConstant: 32).isActive = true
input.widthAnchor.constraint(equalToConstant: 40).isActive = true
self[keyPath: keyPath] = input
inputsMap[input] = rawName
return [label, input]
Expand All @@ -86,6 +88,8 @@ class PreferencesPanel: NSPanel, NSTextViewDelegate {
try! Preferences.updateAndValidateFromString("theme", popUpButton.titleOfSelectedItem!)
case metaKey:
try! Preferences.updateAndValidateFromString("metaKey", popUpButton.titleOfSelectedItem!)
case showOnScreen:
try! Preferences.updateAndValidateFromString("showOnScreen", popUpButton.titleOfSelectedItem!)
default:
throw "Tried to update an unknown popUpButton: '\(popUpButton)' = '\(popUpButton.titleOfSelectedItem!)'"
}
Expand Down
5 changes: 3 additions & 2 deletions alt-tab-macos/ui/ThumbnailsPanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,9 @@ class ThumbnailsPanel: NSPanel, NSCollectionViewDataSource, NSCollectionViewDele
}
}

func computeThumbnails() {
let maxSize = NSSize(width: NSScreen.main!.frame.width * Preferences.maxScreenUsage!, height: NSScreen.main!.frame.height * Preferences.maxScreenUsage!)
func computeThumbnails(_ screenOverride: NSScreen? = nil) {
let preferredScreen = screenOverride ?? Screen.getPreferredScreen() // use optional provided screen or determine it just in time
let maxSize = NSSize(width: preferredScreen.frame.width * Preferences.maxScreenUsage!, height: preferredScreen.frame.height * Preferences.maxScreenUsage!)
collectionView_!.setFrameSize(maxSize)
collectionView_!.collectionViewLayout!.invalidateLayout()
collectionView_!.reloadData()
Expand Down

0 comments on commit c458396

Please sign in to comment.