Skip to content

Commit

Permalink
Merge pull request #5 from p-x9/feature/support-app-kit
Browse files Browse the repository at this point in the history
Support MacOS Application
  • Loading branch information
p-x9 authored Sep 13, 2023
2 parents d6eb354 + 547c1de commit 883078e
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 14 deletions.
7 changes: 6 additions & 1 deletion src/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ def info(args: argparse.Namespace, debugger: lldb.SBDebugger, result: lldb.SBCom
file_path = os.path.realpath(__file__)
dir_name = os.path.dirname(file_path)

script_ret = subprocess.run(f"cat {dir_name}/swift/device.swift", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
swift_file_name = "deviceMacOS" if util.isAppKit(debugger) else "deviceIOS"

script_ret = subprocess.run(f"cat {dir_name}/swift/{swift_file_name}.swift",
shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
text=True)

script = script_ret.stdout
script += """
Expand Down
4 changes: 2 additions & 2 deletions src/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ def tree(args: argparse.Namespace, debugger: lldb.SBDebugger, result: lldb.SBCom


def open(args: argparse.Namespace, debugger: lldb.SBDebugger, result: lldb.SBCommandReturnObject) -> None:
if not util.isIOSSimulator(debugger):
print("Supported only simulator")
if not (util.isIOSSimulator(debugger) or util.isMacOS(debugger)):
print("Supported only simulator or macOS")
return

shell = "open -R "
Expand Down
2 changes: 1 addition & 1 deletion src/swift/device.swift → src/swift/deviceIOS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ func printDeviceInfo() {
print("System Name: \(currentDevice.systemName)")
print("System Version: \(currentDevice.systemVersion)")
if let identifierForVendor = currentDevice.identifierForVendor {
print("Identifier (UDID): \(identifierForVendor.uuidString)")
print("Id For Vendor: \(identifierForVendor.uuidString)")
}
}
31 changes: 31 additions & 0 deletions src/swift/deviceMacOS.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Foundation
import SystemConfiguration

func printDeviceInfo() {
let processInfo = ProcessInfo.processInfo

print("[Device Info]")
if let name = SCDynamicStoreCopyComputerName(nil, nil) {
print("Name: \(name)")
}

if let model = sysctlByString(key: "hw.model") {
print("Model: \(model)")
}

print("System Name: macOS")
print("System Version: \(processInfo.operatingSystemVersionString)")

if let cpu = sysctlByString(key: "machdep.cpu.brand_string") {
print("CPU: \(cpu)")
}
}

func sysctlByString(key: String) -> String? {
var size: size_t = 0
sysctlbyname(key, nil, &size, nil, 0)
var value = [CChar](repeating: 0, count: Int(size))
sysctlbyname(key, &value, &size, nil, 0)

return String(cString: value)
}
21 changes: 15 additions & 6 deletions src/swift/tree.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import UIKit
// import UIKit
// typealias NSUIView = UIView
// typealias NSUIViewController = UIViewController
// typealias NSUIWindow = UIWindow
// typealias NSUIApplication = UIApplication

func windowHierarchy(_ window: UIWindow?, indentation: String = "", isLast: Bool = true, mode: String = "normal", depth: Int? = nil) {
func windowHierarchy(_ window: NSUIWindow?, indentation: String = "", isLast: Bool = true, mode: String = "normal", depth: Int? = nil) {
guard let window = window else { return }

let currentDepth = indentation.replacingOccurrences(of: "", with: " ").count / 3
Expand All @@ -25,12 +29,17 @@ func windowHierarchy(_ window: UIWindow?, indentation: String = "", isLast: Bool
result += windowDescription
print(result)

if let rootViewController = window.rootViewController {
viewControllerHierarchy(rootViewController, indentation: indentation + (isLast ? " " : ""), isLast: true, mode: mode, depth: depth)
var rootViewController: NSUIViewController?
if window.responds(to: Selector(("rootViewController"))) { // for iOS
rootViewController = window.perform(Selector(("rootViewController"))).takeUnretainedValue() as? NSUIViewController
} else if window.responds(to: Selector(("contentViewController"))) { // for macOS
rootViewController = window.perform(Selector(("contentViewController"))).takeUnretainedValue() as? NSUIViewController
}

viewControllerHierarchy(rootViewController, indentation: indentation + (isLast ? " " : ""), isLast: true, mode: mode, depth: depth)
}

func viewControllerHierarchy(_ viewController: UIViewController?, indentation: String = "", isLast: Bool = true, mode: String = "normal", depth: Int? = nil) {
func viewControllerHierarchy(_ viewController: NSUIViewController?, indentation: String = "", isLast: Bool = true, mode: String = "normal", depth: Int? = nil) {
guard let viewController = viewController else { return }

let currentDepth = indentation.replacingOccurrences(of: "", with: " ").count / 3
Expand Down Expand Up @@ -68,7 +77,7 @@ func viewControllerHierarchy(_ viewController: UIViewController?, indentation: S
}
}

func viewHierarchy(_ view: UIView?, indentation: String = "", isLast: Bool = true, mode: String = "normal", depth: Int? = nil) {
func viewHierarchy(_ view: NSUIView?, indentation: String = "", isLast: Bool = true, mode: String = "normal", depth: Int? = nil) {
guard let view = view else { return }

let currentDepth = indentation.replacingOccurrences(of: "", with: " ").count / 3
Expand Down
23 changes: 21 additions & 2 deletions src/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,26 @@ def tree(args: argparse.Namespace, debugger: lldb.SBDebugger, result: lldb.SBCom
except ValueError:
pass

script = script_ret.stdout
script = ''

if util.isUIKit(debugger):
script += """
import UIKit
typealias NSUIView = UIView
typealias NSUIViewController = UIViewController
typealias NSUIWindow = UIWindow
typealias NSUIApplication = UIApplication
"""
elif util.isAppKit(debugger):
script += """
import AppKit
typealias NSUIView = NSView
typealias NSUIViewController = NSViewController
typealias NSUIWindow = NSWindow
typealias NSUIApplication = NSApplication
"""

script += script_ret.stdout
if args.window:
script += f"\n windowHierarchy({args.window}, mode: \"{mode}\", depth: {depth})"
elif args.view:
Expand All @@ -73,7 +92,7 @@ def tree(args: argparse.Namespace, debugger: lldb.SBDebugger, result: lldb.SBCom
elif args.layer:
script += f"\n layerHierarchy({args.layer}, mode: \"{mode}\", depth: {depth})"
else:
script += f"\n windowHierarchy(UIApplication.shared.keyWindow, mode: \"{mode}\", depth: {depth})"
script += f"\n windowHierarchy(NSUIApplication.shared.keyWindow, mode: \"{mode}\", depth: {depth})"

_ = util.exp_script(
debugger,
Expand Down
68 changes: 66 additions & 2 deletions src/util.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import lldb
import argparse
from typing import Optional
from typing import Optional, cast


def exp_script(
Expand All @@ -23,7 +23,7 @@ def exp_script(
options.SetIgnoreBreakpoints(True)
options.SetTrapExceptions(False)
options.SetTryAllThreads(True)
options.SetFetchDynamicValue(lldb.eDynamicCanRunTarget)
options.SetFetchDynamicValue(lldb.eNoDynamicValues)
options.SetUnwindOnError(True)
options.SetGenerateDebugInfo(True)

Expand Down Expand Up @@ -51,5 +51,69 @@ def isIOSSimulator(debugger: lldb.SBDebugger) -> bool:
return False


def isAppKit(debugger: lldb.SBDebugger) -> bool:
script = """
@import Foundation;
Class app = NSClassFromString(@"NSApplication");
BOOL val = (BOOL)(app != nil)
val ? @"YES" : @"NO";
"""
ret = exp_script(debugger, script, lang=lldb.eLanguageTypeObjC)

if ret and ret.GetObjectDescription() == 'YES':
return True
else:
return False


def isUIKit(debugger: lldb.SBDebugger) -> bool:
script = """
@import Foundation;
Class app = NSClassFromString(@"UIApplication");
BOOL val = (BOOL)(app != nil)
val ? @"YES" : @"NO";
"""
ret = exp_script(debugger, script, lang=lldb.eLanguageTypeObjC)
if ret and ret.GetObjectDescription() == 'YES':
return True
else:
return False


def isMacOS(debugger: lldb.SBDebugger) -> bool:
model = sysctlbyname(debugger, "hw.model")
if model:
return 'Mac' in model and not isIOSSimulator(debugger)
else:
return isAppKit(debugger)


def isIOS(debugger: lldb.SBDebugger) -> bool:
machine = sysctlbyname(debugger, "hw.machine")
if machine:
return 'iP' in machine or isIOSSimulator(debugger)
else:
return isUIKit(debugger)


def sysctlbyname(debugger: lldb.SBDebugger, key: str) -> Optional[str]:
script = """
size_t size = 0;
sysctlbyname([name UTF8String], NULL, &size, NULL, 0);
char *machine = (char *)malloc(size);
sysctlbyname([name UTF8String], machine, &size, NULL, 0);
NSString *result = [NSString stringWithUTF8String:machine];
free(machine);
result;
"""

ret = exp_script(debugger, script, lang=lldb.eLanguageTypeObjC)
if ret:
return cast(str, ret.GetObjectDescription())
else:
return None


class HelpFormatter(argparse.RawTextHelpFormatter, argparse.ArgumentDefaultsHelpFormatter):
pass

0 comments on commit 883078e

Please sign in to comment.