1
0
mirror of https://github.com/mpv-player/mpv synced 2025-04-11 04:01:31 +00:00
mpv/osdep/mac/swift_extensions.swift
der richter f7a32b5f29 mac: make display-names unique to allow specific selection
the Screen property localizedName returns a none unique dynamic name
that doesn't allow a specific selection of a Screen on every OS boot.
the name consists of the vendor name and model name (eg DELL U2723QE).
if the same model display is connected to the system several times,
macOS starts to add numbers to the localizedName (eg DELL U2723QE (1)),
that may not be associated to the same Screen on every OS boot or
connecting the display. it also changes the name of the first connected
display by adding that numeration. this makes it impossible specify the
proper screen with the screen-name option every time.

to circumvent this we remove the enumeration from the name and instead
add the serial number to the display-names property. this makes the
actual Screen unique and none dynamic. furthermore the selection of a
screen by name will check for equality for the old localizedName, simple
name without enumeration, serial number and the combined name with
serial number. this makes it possible to select the screen by either of
those names and identifiers, and keeps backwards compatibility with the
old behaviour.

Examples:
localized name (System Settings name): DELL U2723QE, DELL U2723QE (1)
simple name: DELL U2723QE
serial number: 123456789
combined name: DELL U2723QE (123456789)
2024-04-24 20:35:38 +02:00

118 lines
4.0 KiB
Swift

/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
import Cocoa
import IOKit.hidsystem
extension NSDeviceDescriptionKey {
static let screenNumber = NSDeviceDescriptionKey("NSScreenNumber")
}
extension NSScreen {
public var displayID: CGDirectDisplayID {
get {
return deviceDescription[.screenNumber] as? CGDirectDisplayID ?? 0
}
}
public var serialNumber: String {
get {
return String(CGDisplaySerialNumber(displayID))
}
}
public var name: String {
get {
// force unwrapping is fine here, regex is guaranteed to be valid
let regex = try! NSRegularExpression(pattern: " \\(\\d+\\)$", options: .caseInsensitive)
return regex.stringByReplacingMatches(
in: localizedName,
range: NSRange(location: 0, length: localizedName.count),
withTemplate: ""
)
}
}
public var uniqueName: String {
get {
return name + " (\(serialNumber))"
}
}
}
extension NSColor {
convenience init(hex: String) {
let int = Int(hex.dropFirst(), radix: 16) ?? 0
let alpha = CGFloat((int >> 24) & 0x000000FF)/255
let red = CGFloat((int >> 16) & 0x000000FF)/255
let green = CGFloat((int >> 8) & 0x000000FF)/255
let blue = CGFloat((int) & 0x000000FF)/255
self.init(calibratedRed: red, green: green, blue: blue, alpha: alpha)
}
}
extension NSEvent.ModifierFlags {
public static var optionLeft: NSEvent.ModifierFlags = .init(rawValue: UInt(NX_DEVICELALTKEYMASK))
public static var optionRight: NSEvent.ModifierFlags = .init(rawValue: UInt(NX_DEVICERALTKEYMASK))
}
extension mp_keymap {
init(_ f: Int, _ t: Int32) {
self.init(from: Int32(f), to: t)
}
}
extension mpv_event_id: CustomStringConvertible {
public var description: String {
switch self {
case MPV_EVENT_NONE: return "MPV_EVENT_NONE2"
case MPV_EVENT_SHUTDOWN: return "MPV_EVENT_SHUTDOWN"
case MPV_EVENT_LOG_MESSAGE: return "MPV_EVENT_LOG_MESSAGE"
case MPV_EVENT_GET_PROPERTY_REPLY: return "MPV_EVENT_GET_PROPERTY_REPLY"
case MPV_EVENT_SET_PROPERTY_REPLY: return "MPV_EVENT_SET_PROPERTY_REPLY"
case MPV_EVENT_COMMAND_REPLY: return "MPV_EVENT_COMMAND_REPLY"
case MPV_EVENT_START_FILE: return "MPV_EVENT_START_FILE"
case MPV_EVENT_END_FILE: return "MPV_EVENT_END_FILE"
case MPV_EVENT_FILE_LOADED: return "MPV_EVENT_FILE_LOADED"
case MPV_EVENT_IDLE: return "MPV_EVENT_IDLE"
case MPV_EVENT_TICK: return "MPV_EVENT_TICK"
case MPV_EVENT_CLIENT_MESSAGE: return "MPV_EVENT_CLIENT_MESSAGE"
case MPV_EVENT_VIDEO_RECONFIG: return "MPV_EVENT_VIDEO_RECONFIG"
case MPV_EVENT_AUDIO_RECONFIG: return "MPV_EVENT_AUDIO_RECONFIG"
case MPV_EVENT_SEEK: return "MPV_EVENT_SEEK"
case MPV_EVENT_PLAYBACK_RESTART: return "MPV_EVENT_PLAYBACK_RESTART"
case MPV_EVENT_PROPERTY_CHANGE: return "MPV_EVENT_PROPERTY_CHANGE"
case MPV_EVENT_QUEUE_OVERFLOW: return "MPV_EVENT_QUEUE_OVERFLOW"
case MPV_EVENT_HOOK: return "MPV_EVENT_HOOK"
default: return "MPV_EVENT_" + String(self.rawValue)
}
}
}
extension Bool {
init(_ int32: Int32) {
self.init(int32 != 0)
}
}
extension Int32 {
init(_ bool: Bool) {
self.init(bool ? 1 : 0)
}
}