usr-sse2 / RDM

Easily set Mac Retina display to higher unsupported resolutions

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Suggestions and questions for release 2.5.0

jnooree opened this issue · comments

First, the calculator (which I have added) was removed in release 2.5.0. Was it intentional or accidental? If it was intentional, please explain the reason why, and maybe suggest improvements for it.
Second, the app is currently parsing all the information when the view controller is about to be appear, but I think this adds significant delay before the editor window appears. Maybe moving this code to the initialization step of the app will improve performance.

override func viewWillAppear() {
super.viewWillAppear()
let plists = sourceFiles.map { NSMutableDictionary(contentsOf: URL(fileURLWithPath: $0)) ?? nil }.filter({$0 != nil})
if !plists.isEmpty {
plist = plists.first!!
if let a = plist[kDisplayProductName] as? String {
displayProductName = a
}
}
else {
plist = NSMutableDictionary()
}
if let a = plist[kScaleResolutionsKey] {
if let b = a as? NSArray {
resolutions.append(contentsOf: ((b as Array).map { Resolution(nsdata: $0 as? NSData) }))
}
}
// Remove counterparts
resolutions = resolutions.filter({ (res) -> Bool in
return !(res.RawFlags == 0 && resolutions.contains(where: {$0.HiDPI && $0.height * 2 == res.height && $0.width * 2 == res.width}))
})
resolutions = Array(NSOrderedSet(array: resolutions)) as! [Resolution]
var selection : [DisplayIcon] = []
var computerBoardId : String? = nil
if #available(OSX 10.13, *) {
let p = Process()
let pipe = Pipe()
p.executableURL = URL(fileURLWithPath: "/usr/sbin/ioreg")
p.arguments = ["-c", "IOPlatformExpertDevice", "-a"]
p.standardOutput = pipe
try! p.run()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
var format = PropertyListSerialization.PropertyListFormat.xml
let dict = try! PropertyListSerialization.propertyList(from: data, options: [], format: &format) as! [String : AnyObject]
if let children = dict["IORegistryEntryChildren"] as? [AnyObject] {
if children.count == 1,
let item = children.first as? [String : AnyObject] {
if let data = item["board-id"] as? Data {
computerBoardId = String(data: data, encoding: String.Encoding.ascii)
}
}
}
}
for iconsPlist in sourceIconsPlists.map { NSMutableDictionary(contentsOf: URL(fileURLWithPath: $0)) ?? nil }.filter({$0 != nil}) {
if let boards = iconsPlist!["board-ids"] as? [String : Any] {
for board in boards {
if let boardDict = board.value as? [String : AnyHashable] {
if boardDict[kDisplayResolutionPreviewIcon] != nil {
let icon = icons.insert(DisplayIcon(properties: boardDict)).memberAfterInsert
if board.key == computerBoardId {
iconForBoardId = icon
}
}
}
}
}
if let vendors = iconsPlist!["vendors"] as? [String : Any] {
let defaultDisplayIcon = vendors[kDisplayIcon] as? String
for vendor in vendors {
if let vendorDict = vendor.value as? [String : Any] {
let vendorDefaultDisplayIcon = vendorDict[kDisplayIcon] as? String ?? defaultDisplayIcon
if let products = vendorDict["products"] as? [String : Any] {
for product in products {
if var productDict = product.value as? [String : AnyHashable] {
if vendorDefaultDisplayIcon != nil && !productDict.keys.contains(kDisplayIcon) {
productDict[kDisplayIcon] = vendorDefaultDisplayIcon
}
if productDict[kDisplayResolutionPreviewIcon] != nil {
let (_, displayIcon) = icons.insert(DisplayIcon(properties: productDict))
if String(format: "%x", vendorID).lowercased() == vendor.key.lowercased() &&
String(format:"%x", productID).lowercased() == product.key.lowercased() {
selection = [displayIcon]
}
}
}
}
}
}
}
}
}

About the calculator: it's intentional. The code is in place, just the button is disabled. The reason is that it's completely weird and impossible to do calculations, because for problem to be correctly defined, a user should have the ability to choose what's the input data and what's the result field. Otherwise it's impossible to type the input data because the values are constantly recomputed when I still haven't finished entering the input data. I'm planning to improve it by adding radio buttons near the input fields and enable the calculator in one of the following updates.

About the delay: the cause of the delay is icon deduplication. It compares the icon files byte-by-byte.

  1. The resolution and icon plists should be parsed where they are currently parsed, because otherwise RDM wouldn't reload them if they are modified by hand, by another instance of RDM or by SwitchResX.
  2. The main functionality of the app is resolution switching, not editing, so it's not a good idea to load plists and icons if they are unlikely to be used and introduce a startup delay.
  3. Caching can be an improvement – the icons can be loaded when the edit window is opened for the first time. But, again, it doesn't seem very useful as usually this window is opened only once until reboot.
  4. Using a hash of file can improve the performance, as byte-by-byte comparison would only be done for equal files. Maybe some day I'll do that.

Thank you for the detailed explanations.