Skip to content

Commit

Permalink
WIP Big Sur compatibility, custom flags, auto-duplication etc
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Belyaev committed Dec 14, 2020
1 parent f08d4df commit 63470ac
Show file tree
Hide file tree
Showing 13 changed files with 483 additions and 212 deletions.
260 changes: 203 additions & 57 deletions Base.lproj/Main.storyboard

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions RDM.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
358D5660212DEDED00F9E9BF /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 358D5659212DEDEC00F9E9BF /* README.md */; };
358D5661212DEDED00F9E9BF /* ResMenuItem.mm in Sources */ = {isa = PBXBuildFile; fileRef = 358D565B212DEDED00F9E9BF /* ResMenuItem.mm */; };
358F04E3212D7E6500671ABD /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 358F04E2212D7E6500671ABD /* IOKit.framework */; };
35959C0225757F1E0002A45F /* HexNumberFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35959C0125757F1E0002A45F /* HexNumberFormatter.swift */; };
35959C0525763EE40002A45F /* TextFieldWithMonospacedDigits.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35959C0425763EE40002A45F /* TextFieldWithMonospacedDigits.swift */; };
35C9D3B0212C04DA00D652F7 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35C9D3AF212C04DA00D652F7 /* ViewController.swift */; };
35C9D3B2212C04DD00D652F7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 35C9D3B1212C04DD00D652F7 /* Assets.xcassets */; };
35C9D3B5212C04DD00D652F7 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 35C9D3B3212C04DD00D652F7 /* Main.storyboard */; };
Expand All @@ -40,6 +42,8 @@
358D565A212DEDED00F9E9BF /* RDMAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RDMAppDelegate.h; sourceTree = "<group>"; };
358D565B212DEDED00F9E9BF /* ResMenuItem.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ResMenuItem.mm; sourceTree = "<group>"; };
358F04E2212D7E6500671ABD /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
35959C0125757F1E0002A45F /* HexNumberFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HexNumberFormatter.swift; sourceTree = "<group>"; };
35959C0425763EE40002A45F /* TextFieldWithMonospacedDigits.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldWithMonospacedDigits.swift; sourceTree = "<group>"; };
35C9D3AB212C04DA00D652F7 /* RDM.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RDM.app; sourceTree = BUILT_PRODUCTS_DIR; };
35C9D3AF212C04DA00D652F7 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
35C9D3B1212C04DD00D652F7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
Expand All @@ -54,7 +58,6 @@
8FC72A1924F664BA004E10E1 /* Resolution.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Resolution.swift; sourceTree = "<group>"; };
8FC72A1A24F664BA004E10E1 /* CharEncDec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CharEncDec.swift; sourceTree = "<group>"; };
8FC72A1B24F664BA004E10E1 /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
8FEFEA2D2515A748001AD551 /* MyPlayground.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = MyPlayground.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -121,6 +124,8 @@
8FC72A1A24F664BA004E10E1 /* CharEncDec.swift */,
8FC72A1B24F664BA004E10E1 /* Utils.swift */,
35CC4996212C54AF00704BD7 /* bridging.h */,
35959C0125757F1E0002A45F /* HexNumberFormatter.swift */,
35959C0425763EE40002A45F /* TextFieldWithMonospacedDigits.swift */,
);
path = src;
sourceTree = "<group>";
Expand All @@ -130,7 +135,6 @@
children = (
35C9D3B6212C04DD00D652F7 /* Info.plist */,
8F13DECB24FDCE790049A2DF /* export.plist */,
8FEFEA2D2515A748001AD551 /* MyPlayground.playground */,
);
path = etc;
sourceTree = "<group>";
Expand Down Expand Up @@ -215,13 +219,15 @@
buildActionMask = 2147483647;
files = (
8FC6639B25060DDF008466A1 /* SheetViewController.swift in Sources */,
35959C0225757F1E0002A45F /* HexNumberFormatter.swift in Sources */,
8F7B82132506878D0076803C /* IntegerValueTransformer.swift in Sources */,
358D565C212DEDED00F9E9BF /* RDMAppDelegate.mm in Sources */,
358D5661212DEDED00F9E9BF /* ResMenuItem.mm in Sources */,
358D565F212DEDED00F9E9BF /* utils.mm in Sources */,
35554437212C7CB00063AEE7 /* EditDisplayPlistItem.swift in Sources */,
8FC72A1D24F664BA004E10E1 /* CharEncDec.swift in Sources */,
8FC72A1E24F664BA004E10E1 /* Utils.swift in Sources */,
35959C0525763EE40002A45F /* TextFieldWithMonospacedDigits.swift in Sources */,
358D565D212DEDED00F9E9BF /* cmdline.mm in Sources */,
35C9D3B0212C04DA00D652F7 /* ViewController.swift in Sources */,
358D565E212DEDED00F9E9BF /* main.mm in Sources */,
Expand Down
18 changes: 0 additions & 18 deletions src/CharEncDec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,6 @@

import Foundation

// For encoding
extension String {
var hexadecimal: Data? {
var data = Data(capacity: self.count / 2)

let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
regex.enumerateMatches(in: self, range: NSRange(startIndex..., in: self)) { match, _, _ in
let byteString = (self as NSString).substring(with: match!.range)
let num = UInt8(byteString, radix: 16)!
data.append(num)
}

guard data.count > 0 else { return nil }

return data
}
}

// For decoding
extension NSData {
func getArrayOfSwappedBytes<T: FixedWidthInteger>(asType: T.Type) -> [T] {
Expand Down
32 changes: 32 additions & 0 deletions src/HexNumberFormatter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// HexNumberFormatter.swift
// RDM
//
// Created by usrsse2 on 30.11.2020.
// Copyright © 2020 гык-sse2. All rights reserved.
//

import Foundation
import Cocoa

class ParseError : Error {
}

class HexNumberFormatter : NumberFormatter {
override func string(for obj: Any?) -> String? {
if let number = obj as? UInt64 {
return String(format: "%016lx", number)
}
return nil
}

override func getObjectValue(_ obj: AutoreleasingUnsafeMutablePointer<AnyObject?>?, for string: String, range rangep: UnsafeMutablePointer<NSRange>?) throws {
if let num = UInt64(string, radix: 16) {
obj?.pointee = NSNumber(value: num)
rangep?.pointee = NSMakeRange(0, string.count)
}
else {
throw ParseError()
}
}
}
1 change: 1 addition & 0 deletions src/RDMAppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
NSMenu* statusMenu;
NSWindowController* editResolutionsController;
NSStatusItem* statusItem;
dispatch_queue_t queue;
}
- (void) refreshStatusMenu;
@end
Expand Down
21 changes: 8 additions & 13 deletions src/RDMAppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ - (void) refreshStatusMenu
NSDictionary *deviceInfo = (__bridge NSDictionary *)IODisplayCreateInfoDictionary(IOServicePortFromCGDisplayID(display),
kIODisplayOnlyPreferredName);
NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
CFRelease((CFDictionaryRef) deviceInfo); // Free memory
CFRelease((CFDictionaryRef) deviceInfo);

if ([localizedNames count] > 0)
screenName = [localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]];
Expand Down Expand Up @@ -224,9 +224,9 @@ - (void) editResolutions: (EditDisplayPlistItem *)sender {
NSStoryboard *storyBoard = [NSStoryboard storyboardWithName:@"Main" bundle:nil];
editResolutionsController = [storyBoard instantiateControllerWithIdentifier:@"edit"];
ViewController *vc = (ViewController*)editResolutionsController.window.contentViewController;
vc.vendorID = sender.vendorID; // 1552;
vc.productID = sender.productID; // 0xa044;
vc.displayProductName = sender.displayName; // @"DEBUG";
vc.vendorID = sender.vendorID;
vc.productID = sender.productID;
vc.displayProductName = sender.displayName;
[editResolutionsController showWindow:self];
[NSApp activateIgnoringOtherApps:YES];
}
Expand Down Expand Up @@ -318,19 +318,14 @@ - (void) setMode: (ResMenuItem*) item
CGDirectDisplayID display = [item display];
int modeNum = [item modeNum];

SetDisplayModeNum(display, modeNum);
/*
CGDisplayConfigRef config;
if (CGBeginDisplayConfiguration(&config) == kCGErrorSuccess) {
CGConfigureDisplayWithDisplayMode(config, display, mode, NULL);
CGCompleteDisplayConfiguration(config, kCGConfigureForSession);
}*/
[self refreshStatusMenu];
dispatch_async(self->queue, ^{
SetDisplayModeNum(display, modeNum);
});
}

- (void) applicationDidFinishLaunching: (NSNotification*) notification
{
self->queue = dispatch_queue_create("setModeQueue", nil);
// NSLog(@"Finished launching");
[self refreshStatusMenu];
CGDisplayRegisterReconfigurationCallback(DisplayReconfigurationCallback, (void*)self);
Expand Down
1 change: 0 additions & 1 deletion src/ResMenuItem.mm
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ - (id) initWithDisplay: (CGDirectDisplayID) display andMode: (modes_D4*) mode
title = [NSString stringWithFormat: @"%d × %d%@", width, height, emoji];

[self setTitle: title];

return self;
}
else
Expand Down
142 changes: 108 additions & 34 deletions src/Resolution.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,98 +8,172 @@

import Foundation

let kFlagHiDPI : UInt64 = 0x0000000100000000
let kFlagUnknown1 : UInt64 = 0x0000000000020000
let kFlagRetinaDisplay : UInt64 = 0x0000000800000000
let kFlagUnknown2 : UInt64 = 0x0000000000080000

@objc class Resolution : NSObject {
private var _width : UInt32
private var _height : UInt32
private var _hiDPI : Bool
private var _hiDPIFlag : [UInt32]

private static let _defaultHiDPIFlag : [UInt32] = [0x1, 0x200000]

// For NSObject properties
private var _hiDPIFlag : UInt64

var hiDPIMode : UInt64 {
get {
return _hiDPIFlag
}
}

private var isHiDPI : Bool {
get {
return _hiDPIFlag & kFlagHiDPI != 0
}
}

@objc var width : UInt32 {
@objc dynamic var width : UInt32 {
get {
return _hiDPI ? _width / 2 : _width
return isHiDPI ? _width / 2 : _width
}

set(value) {
_width = _hiDPI ? value * 2 : value
_width = isHiDPI ? value * 2 : value
}
}

@objc var height : UInt32 {
@objc dynamic var height : UInt32 {
get {
return _hiDPI ? _height / 2 : _height
return isHiDPI ? _height / 2 : _height
}

set(value) {
_height = _hiDPI ? value * 2 : value
_height = isHiDPI ? value * 2 : value
}
}

func setFlag(_ flag : UInt64, _ value : Bool) {
if value {
RawFlags = RawFlags | flag
}
else {
RawFlags = RawFlags & ~flag
}
}

@objc var hiDPI : Bool {
@objc dynamic var RawFlags : UInt64 {
get {
return _hiDPI
return _hiDPIFlag
}

set(value) {
if _hiDPI != value {
_hiDPI = value

if value {
willChangeValue(forKey: "HiDPI")
willChangeValue(forKey: "Retina")
willChangeValue(forKey: "Unknown1")
willChangeValue(forKey: "Unknown2")
let wasHiDPI = isHiDPI
_hiDPIFlag = value
if isHiDPI != wasHiDPI {
if isHiDPI {
_width *= 2
_height *= 2
} else {
_width /= 2
_height /= 2
}
}
didChangeValue(forKey: "HiDPI")
didChangeValue(forKey: "Retina")
didChangeValue(forKey: "Unknown1")
didChangeValue(forKey: "Unknown2")
}
}

@objc dynamic var HiDPI : Bool {
get {
return RawFlags & kFlagHiDPI != 0
}
set(value) {
setFlag(kFlagHiDPI, value)
}
}

@objc dynamic var Retina : Bool {
get {
return RawFlags & kFlagRetinaDisplay != 0
}
set(value) {
setFlag(kFlagRetinaDisplay, value)
}
}

@objc var Unknown1 : Bool {
get {
return RawFlags & kFlagUnknown1 != 0
}
set(value) {
setFlag(kFlagUnknown1, value)
}
}

@objc dynamic var Unknown2 : Bool {
get {
return RawFlags & kFlagUnknown2 != 0
}
set(value) {
setFlag(kFlagUnknown2, value)
}
}

override init() {
self._width = 0
self._height = 0
self._hiDPI = false
self._hiDPIFlag = Resolution._defaultHiDPIFlag
self._hiDPIFlag = 0

super.init()
}

private init(width : UInt32, height : UInt32, hiDPI : Bool, origin : [UInt32]) {
private init(width : UInt32, height : UInt32, flags : UInt64) {
self._width = width
self._height = height
self._hiDPI = hiDPI
self._hiDPIFlag = hiDPI && (origin.count > 2)
? Array(origin[2...]) : Resolution._defaultHiDPIFlag // For hiDPI toggle feature
self._hiDPIFlag = flags

super.init()
}

convenience init(nsdata : NSData?) {
if let nsdata = nsdata {
let array = nsdata.getArrayOfSwappedBytes(asType: UInt32.self)
var flags : UInt64 = 0
if array.count >= 3 {
flags |= UInt64(array[2]) << 32
if array.count >= 4 {
flags |= UInt64(array[3])
}
}
self.init(width: array[0],
height: array[1],
hiDPI: array.count > 2 && array[2...].allSatisfy { $0 != 0 },
origin: array)
flags: flags)
} else {
self.init()
}
}

static func bytes(number : UInt32) -> [UInt8] {
return [UInt8(number >> 24), UInt8((number >> 16) & 0xff), UInt8((number >> 8) & 0xff), UInt8(number & 0xff)]
}

func toData() -> NSData {
// TODO: check on big-endian platforms!
// is ARM big-endian or little-endian?

var d = Data()

d.append(String(format: "%08X", self._width).hexadecimal!)
d.append(String(format: "%08X", self._height).hexadecimal!)
if self._hiDPI {
for flag in _hiDPIFlag {
d.append(String(format: "%08X", flag).hexadecimal!)
d.append(contentsOf: Resolution.bytes(number: _width))
d.append(contentsOf: Resolution.bytes(number: _height))
if _hiDPIFlag != 0 {
d.append(contentsOf: Resolution.bytes(number: UInt32(_hiDPIFlag >> 32)))
if _hiDPIFlag & 0xffffffff != 0 {
d.append(contentsOf: Resolution.bytes(number: UInt32(_hiDPIFlag & 0xffffffff)))
}
}

return d as NSData
}

Expand Down
Loading

0 comments on commit 63470ac

Please sign in to comment.