Repository: Stengo/DeskPad Branch: main Commit: c3349f0e237e Files: 32 Total size: 44.4 KB Directory structure: gitextract_hkpr8hdc/ ├── .gitignore ├── BuildTools/ │ ├── Empty.swift │ ├── Package.resolved │ └── Package.swift ├── DeskPad/ │ ├── AppDelegate.swift │ ├── Assets.xcassets/ │ │ ├── AccentColor.colorset/ │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset/ │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── TitleBarActive.colorset/ │ │ │ └── Contents.json │ │ └── TitleBarInactive.colorset/ │ │ └── Contents.json │ ├── Backend/ │ │ ├── AppState.swift │ │ ├── MouseLocation/ │ │ │ ├── MouseLocationSideEffect.swift │ │ │ └── MouseLocationState.swift │ │ ├── ScreenConfiguration/ │ │ │ ├── ScreenConfigurationSideEffect.swift │ │ │ └── ScreenConfigurationState.swift │ │ ├── SideEffectsMiddleware.swift │ │ └── Store.swift │ ├── CGVirtualDisplayPrivate.h │ ├── DeskPad-Bridging-Header.h │ ├── DeskPad.entitlements │ ├── Frontend/ │ │ └── Screen/ │ │ ├── ScreenViewController.swift │ │ └── ScreenViewData.swift │ ├── Helpers/ │ │ └── NSScreen+Extensions.swift │ ├── SubscriberViewController.swift │ └── main.swift ├── DeskPad.xcodeproj/ │ ├── project.pbxproj │ └── project.xcworkspace/ │ ├── contents.xcworkspacedata │ └── xcshareddata/ │ ├── IDEWorkspaceChecks.plist │ └── swiftpm/ │ └── Package.resolved ├── Icon/ │ └── DeskPad.pxd ├── LICENSE.md └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ BuildTools/.build BuildTools/.swiftpm xcuserdata/ ================================================ FILE: BuildTools/Empty.swift ================================================ ================================================ FILE: BuildTools/Package.resolved ================================================ { "object": { "pins": [ { "package": "SwiftFormat", "repositoryURL": "https://github.com/nicklockwood/SwiftFormat", "state": { "branch": null, "revision": "16e7dd37937af0f9adf7d8cfb35e97146ce1875f", "version": "0.49.7" } } ] }, "version": 1 } ================================================ FILE: BuildTools/Package.swift ================================================ // swift-tools-version:5.1 import PackageDescription let package = Package( name: "BuildTools", platforms: [.macOS(.v10_11)], dependencies: [ .package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.47.12"), ], targets: [.target(name: "BuildTools", path: "")] ) ================================================ FILE: DeskPad/AppDelegate.swift ================================================ import Cocoa import ReSwift enum AppDelegateAction: Action { case didFinishLaunching } class AppDelegate: NSObject, NSApplicationDelegate { var window: NSWindow! func applicationDidFinishLaunching(_: Notification) { let viewController = ScreenViewController() window = NSWindow(contentViewController: viewController) window.delegate = viewController window.title = "DeskPad" window.makeKeyAndOrderFront(nil) window.titlebarAppearsTransparent = true window.isMovableByWindowBackground = true window.titleVisibility = .hidden window.backgroundColor = .white window.contentMinSize = CGSize(width: 400, height: 300) window.contentMaxSize = CGSize(width: 5120, height: 2160) window.styleMask.insert(.resizable) window.collectionBehavior.insert(.fullScreenNone) let mainMenu = NSMenu() let mainMenuItem = NSMenuItem() let subMenu = NSMenu(title: "MainMenu") let quitMenuItem = NSMenuItem( title: "Quit", action: #selector(NSApp.terminate), keyEquivalent: "q" ) subMenu.addItem(quitMenuItem) mainMenuItem.submenu = subMenu mainMenu.items = [mainMenuItem] NSApplication.shared.mainMenu = mainMenu store.dispatch(AppDelegateAction.didFinishLaunching) } func applicationShouldTerminateAfterLastWindowClosed(_: NSApplication) -> Bool { return true } } ================================================ FILE: DeskPad/Assets.xcassets/AccentColor.colorset/Contents.json ================================================ { "colors" : [ { "idiom" : "universal" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: DeskPad/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "filename" : "Icon-16.png", "idiom" : "mac", "scale" : "1x", "size" : "16x16" }, { "filename" : "Icon-32.png", "idiom" : "mac", "scale" : "2x", "size" : "16x16" }, { "filename" : "Icon-33.png", "idiom" : "mac", "scale" : "1x", "size" : "32x32" }, { "filename" : "Icon-64.png", "idiom" : "mac", "scale" : "2x", "size" : "32x32" }, { "filename" : "Icon-128.png", "idiom" : "mac", "scale" : "1x", "size" : "128x128" }, { "filename" : "Icon-256.png", "idiom" : "mac", "scale" : "2x", "size" : "128x128" }, { "filename" : "Icon-257.png", "idiom" : "mac", "scale" : "1x", "size" : "256x256" }, { "filename" : "Icon-512.png", "idiom" : "mac", "scale" : "2x", "size" : "256x256" }, { "filename" : "Icon-513.png", "idiom" : "mac", "scale" : "1x", "size" : "512x512" }, { "filename" : "Icon-1024.png", "idiom" : "mac", "scale" : "2x", "size" : "512x512" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: DeskPad/Assets.xcassets/Contents.json ================================================ { "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: DeskPad/Assets.xcassets/TitleBarActive.colorset/Contents.json ================================================ { "colors" : [ { "color" : { "platform" : "osx", "reference" : "selectedContentBackgroundColor" }, "idiom" : "universal" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "color" : { "platform" : "osx", "reference" : "selectedContentBackgroundColor" }, "idiom" : "universal" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: DeskPad/Assets.xcassets/TitleBarInactive.colorset/Contents.json ================================================ { "colors" : [ { "color" : { "platform" : "osx", "reference" : "windowBackgroundColor" }, "idiom" : "universal" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "color" : { "platform" : "osx", "reference" : "windowBackgroundColor" }, "idiom" : "universal" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: DeskPad/Backend/AppState.swift ================================================ import ReSwift struct AppState: Equatable { let mouseLocationState: MouseLocationState let screenConfigurationState: ScreenConfigurationState static var initialState: AppState { return AppState( mouseLocationState: .initialState, screenConfigurationState: .initialState ) } } func appReducer(action: Action, state: AppState?) -> AppState { let state = state ?? .initialState return AppState( mouseLocationState: mouseLocationReducer(action: action, state: state.mouseLocationState), screenConfigurationState: screenConfigurationReducer(action: action, state: state.screenConfigurationState) ) } ================================================ FILE: DeskPad/Backend/MouseLocation/MouseLocationSideEffect.swift ================================================ import Foundation import ReSwift private var timer: Timer? enum MouseLocationAction: Action { case located(isWithinScreen: Bool) case requestMove(toPoint: NSPoint) } func mouseLocationSideEffect() -> SideEffect { return { action, dispatch, getState in if timer == nil { timer = Timer.scheduledTimer(withTimeInterval: 0.25, repeats: true) { _ in let mouseLocation = NSEvent.mouseLocation let screens = NSScreen.screens let screenContainingMouse = (screens.first { NSMouseInRect(mouseLocation, $0.frame, false) }) let isWithinScreen = screenContainingMouse?.displayID == getState()?.screenConfigurationState.displayID dispatch(MouseLocationAction.located(isWithinScreen: isWithinScreen)) } } switch action { case let MouseLocationAction.requestMove(point): guard let displayID = getState()?.screenConfigurationState.displayID else { return } CGDisplayMoveCursorToPoint(displayID, point) default: return } } } ================================================ FILE: DeskPad/Backend/MouseLocation/MouseLocationState.swift ================================================ import Foundation import ReSwift struct MouseLocationState: Equatable { let isWithinScreen: Bool static var initialState: MouseLocationState { return MouseLocationState(isWithinScreen: false) } } func mouseLocationReducer(action: Action, state: MouseLocationState) -> MouseLocationState { switch action { case let MouseLocationAction.located(isWithinScreen): return MouseLocationState(isWithinScreen: isWithinScreen) default: return state } } ================================================ FILE: DeskPad/Backend/ScreenConfiguration/ScreenConfigurationSideEffect.swift ================================================ import Foundation import ReSwift private var isObserving = false enum ScreenConfigurationAction: Action { case set(resolution: CGSize, scaleFactor: CGFloat) } func screenConfigurationSideEffect() -> SideEffect { return { _, dispatch, getState in if isObserving == false { isObserving = true NotificationCenter.default.addObserver( forName: NSApplication.didChangeScreenParametersNotification, object: NSApplication.shared, queue: .main ) { _ in guard let screen = NSScreen.screens.first(where: { $0.displayID == getState()?.screenConfigurationState.displayID }) else { return } dispatch(ScreenConfigurationAction.set( resolution: screen.frame.size, scaleFactor: screen.backingScaleFactor )) } } } } ================================================ FILE: DeskPad/Backend/ScreenConfiguration/ScreenConfigurationState.swift ================================================ import Foundation import ReSwift struct ScreenConfigurationState: Equatable { let resolution: CGSize let scaleFactor: CGFloat let displayID: CGDirectDisplayID? static var initialState: ScreenConfigurationState { return ScreenConfigurationState( resolution: .zero, scaleFactor: 1, displayID: nil ) } } func screenConfigurationReducer(action: Action, state: ScreenConfigurationState) -> ScreenConfigurationState { switch action { case let ScreenConfigurationAction.set(resolution, scaleFactor): return ScreenConfigurationState( resolution: resolution, scaleFactor: scaleFactor, displayID: state.displayID ) case let ScreenViewAction.setDisplayID(displayID): return ScreenConfigurationState( resolution: state.resolution, scaleFactor: state.scaleFactor, displayID: displayID ) default: return state } } ================================================ FILE: DeskPad/Backend/SideEffectsMiddleware.swift ================================================ import Foundation import ReSwift typealias SideEffect = (Action, @escaping DispatchFunction, @escaping () -> AppState?) -> Void private let sideEffects: [SideEffect] = [ mouseLocationSideEffect(), screenConfigurationSideEffect(), ] let sideEffectsMiddleware: Middleware = { dispatch, getState in { originalDispatch in { action in originalDispatch(action) for sideEffect in sideEffects { sideEffect(action, dispatch, getState) } } } } ================================================ FILE: DeskPad/Backend/Store.swift ================================================ import Foundation import ReSwift let store = Store( reducer: appReducer, state: AppState.initialState, middleware: [ sideEffectsMiddleware, ] ) ================================================ FILE: DeskPad/CGVirtualDisplayPrivate.h ================================================ // // CGVirtualDisplayPrivate.h // VirtualDisplayExp // // Created by Khaos Tian on 2/17/21. // #import #import NS_ASSUME_NONNULL_BEGIN @class CGVirtualDisplayDescriptor; @interface CGVirtualDisplayMode : NSObject @property(readonly, nonatomic) CGFloat refreshRate; @property(readonly, nonatomic) NSUInteger width; @property(readonly, nonatomic) NSUInteger height; - (instancetype)initWithWidth:(NSUInteger)arg1 height:(NSUInteger)arg2 refreshRate:(CGFloat)arg3; @end @interface CGVirtualDisplaySettings : NSObject @property(retain, nonatomic) NSArray *modes; @property(nonatomic) unsigned int hiDPI; - (instancetype)init; @end @interface CGVirtualDisplay : NSObject @property(readonly, nonatomic) NSArray *modes; // @synthesize modes=_modes; @property(readonly, nonatomic) unsigned int hiDPI; // @synthesize hiDPI=_hiDPI; @property(readonly, nonatomic) CGDirectDisplayID displayID; // @synthesize displayID=_displayID; @property(readonly, nonatomic) id terminationHandler; // @synthesize terminationHandler=_terminationHandler; @property(readonly, nonatomic) dispatch_queue_t queue; // @synthesize queue=_queue; @property(readonly, nonatomic) unsigned int maxPixelsHigh; // @synthesize maxPixelsHigh=_maxPixelsHigh; @property(readonly, nonatomic) unsigned int maxPixelsWide; // @synthesize maxPixelsWide=_maxPixelsWide; @property(readonly, nonatomic) CGSize sizeInMillimeters; // @synthesize sizeInMillimeters=_sizeInMillimeters; @property(readonly, nonatomic) NSString *name; // @synthesize name=_name; @property(readonly, nonatomic) unsigned int serialNum; // @synthesize serialNum=_serialNum; @property(readonly, nonatomic) unsigned int productID; // @synthesize productID=_productID; @property(readonly, nonatomic) unsigned int vendorID; // @synthesize vendorID=_vendorID; - (instancetype)initWithDescriptor:(CGVirtualDisplayDescriptor *)arg1; - (BOOL)applySettings:(CGVirtualDisplaySettings *)arg1; @end @interface CGVirtualDisplayDescriptor : NSObject @property(retain, nonatomic) dispatch_queue_t queue; // @synthesize queue=_queue; @property(retain, nonatomic) NSString *name; // @synthesize name=_name; @property(nonatomic) unsigned int maxPixelsHigh; // @synthesize maxPixelsHigh=_maxPixelsHigh; @property(nonatomic) unsigned int maxPixelsWide; // @synthesize maxPixelsWide=_maxPixelsWide; @property(nonatomic) CGSize sizeInMillimeters; // @synthesize sizeInMillimeters=_sizeInMillimeters; @property(nonatomic) unsigned int serialNum; // @synthesize serialNum=_serialNum; @property(nonatomic) unsigned int productID; // @synthesize productID=_productID; @property(nonatomic) unsigned int vendorID; // @synthesize vendorID=_vendorID; @property(copy, nonatomic) void (^terminationHandler)(id, CGVirtualDisplay*); - (instancetype)init; - (nullable dispatch_queue_t)dispatchQueue; - (void)setDispatchQueue:(dispatch_queue_t)arg1; @end NS_ASSUME_NONNULL_END ================================================ FILE: DeskPad/DeskPad-Bridging-Header.h ================================================ #import "CGVirtualDisplayPrivate.h" ================================================ FILE: DeskPad/DeskPad.entitlements ================================================ com.apple.security.app-sandbox com.apple.security.files.user-selected.read-only com.apple.security.temporary-exception.mach-lookup.global-name com.apple.VirtualDisplay ================================================ FILE: DeskPad/Frontend/Screen/ScreenViewController.swift ================================================ import Cocoa import ReSwift enum ScreenViewAction: Action { case setDisplayID(CGDirectDisplayID) } class ScreenViewController: SubscriberViewController, NSWindowDelegate { override func loadView() { view = NSView() view.wantsLayer = true view.addGestureRecognizer(NSClickGestureRecognizer(target: self, action: #selector(didClickOnScreen))) } private var display: CGVirtualDisplay! private var stream: CGDisplayStream? private var isWindowHighlighted = false private var previousResolution: CGSize? private var previousScaleFactor: CGFloat? override func viewDidLoad() { super.viewDidLoad() let descriptor = CGVirtualDisplayDescriptor() descriptor.setDispatchQueue(DispatchQueue.main) descriptor.name = "DeskPad Display" descriptor.maxPixelsWide = 5120 descriptor.maxPixelsHigh = 2160 descriptor.sizeInMillimeters = CGSize(width: 1600, height: 1000) descriptor.productID = 0x1234 descriptor.vendorID = 0x3456 descriptor.serialNum = 0x0001 let display = CGVirtualDisplay(descriptor: descriptor) store.dispatch(ScreenViewAction.setDisplayID(display.displayID)) self.display = display let settings = CGVirtualDisplaySettings() settings.hiDPI = 1 settings.modes = [ // 32:9 CGVirtualDisplayMode(width: 5120, height: 1440, refreshRate: 60), // 21:9 (239:100, 12:5) CGVirtualDisplayMode(width: 5120, height: 2160, refreshRate: 60), CGVirtualDisplayMode(width: 3840, height: 1600, refreshRate: 60), CGVirtualDisplayMode(width: 3440, height: 1440, refreshRate: 60), // 16:9 CGVirtualDisplayMode(width: 3840, height: 2160, refreshRate: 60), CGVirtualDisplayMode(width: 2560, height: 1440, refreshRate: 60), CGVirtualDisplayMode(width: 1920, height: 1080, refreshRate: 60), CGVirtualDisplayMode(width: 1600, height: 900, refreshRate: 60), CGVirtualDisplayMode(width: 1366, height: 768, refreshRate: 60), CGVirtualDisplayMode(width: 1280, height: 720, refreshRate: 60), // 16:10 CGVirtualDisplayMode(width: 2560, height: 1600, refreshRate: 60), CGVirtualDisplayMode(width: 1920, height: 1200, refreshRate: 60), CGVirtualDisplayMode(width: 1680, height: 1050, refreshRate: 60), CGVirtualDisplayMode(width: 1440, height: 900, refreshRate: 60), CGVirtualDisplayMode(width: 1280, height: 800, refreshRate: 60), ] display.apply(settings) } override func update(with viewData: ScreenViewData) { if viewData.isWindowHighlighted != isWindowHighlighted { isWindowHighlighted = viewData.isWindowHighlighted view.window?.backgroundColor = isWindowHighlighted ? NSColor(named: "TitleBarActive") : NSColor(named: "TitleBarInactive") if isWindowHighlighted { view.window?.orderFrontRegardless() } } if viewData.resolution != .zero, viewData.resolution != previousResolution || viewData.scaleFactor != previousScaleFactor { previousResolution = viewData.resolution previousScaleFactor = viewData.scaleFactor stream = nil view.window?.setContentSize(viewData.resolution) view.window?.contentAspectRatio = viewData.resolution view.window?.center() let stream = CGDisplayStream( dispatchQueueDisplay: display.displayID, outputWidth: Int(viewData.resolution.width * viewData.scaleFactor), outputHeight: Int(viewData.resolution.height * viewData.scaleFactor), pixelFormat: 1_111_970_369, properties: [ CGDisplayStream.showCursor: true, ] as CFDictionary, queue: .main, handler: { [weak self] _, _, frameSurface, _ in if let surface = frameSurface { self?.view.layer?.contents = surface } } ) self.stream = stream stream?.start() } } func windowWillResize(_ window: NSWindow, to frameSize: NSSize) -> NSSize { let snappingOffset: CGFloat = 30 let contentSize = window.contentRect(forFrameRect: NSRect(origin: .zero, size: frameSize)).size guard let screenResolution = previousResolution, abs(contentSize.width - screenResolution.width) < snappingOffset else { return frameSize } return window.frameRect(forContentRect: NSRect(origin: .zero, size: screenResolution)).size } @objc private func didClickOnScreen(_ gestureRecognizer: NSGestureRecognizer) { guard let screenResolution = previousResolution else { return } let clickedPoint = gestureRecognizer.location(in: view) let onScreenPoint = NSPoint( x: clickedPoint.x / view.frame.width * screenResolution.width, y: (view.frame.height - clickedPoint.y) / view.frame.height * screenResolution.height ) store.dispatch(MouseLocationAction.requestMove(toPoint: onScreenPoint)) } } ================================================ FILE: DeskPad/Frontend/Screen/ScreenViewData.swift ================================================ import Foundation struct ScreenViewData: ViewDataType { struct StateFragment: Equatable { let mouseLocationState: MouseLocationState let screenConfiguration: ScreenConfigurationState } static func fragment(of appState: AppState) -> StateFragment { return StateFragment( mouseLocationState: appState.mouseLocationState, screenConfiguration: appState.screenConfigurationState ) } let isWindowHighlighted: Bool let resolution: CGSize let scaleFactor: CGFloat init(for fragment: StateFragment) { isWindowHighlighted = fragment.mouseLocationState.isWithinScreen resolution = fragment.screenConfiguration.resolution scaleFactor = fragment.screenConfiguration.scaleFactor } } ================================================ FILE: DeskPad/Helpers/NSScreen+Extensions.swift ================================================ import Foundation extension NSScreen { var displayID: CGDirectDisplayID { return deviceDescription[NSDeviceDescriptionKey(rawValue: "NSScreenNumber")] as! CGDirectDisplayID } } ================================================ FILE: DeskPad/SubscriberViewController.swift ================================================ import AppKit import ReSwift class SubscriberViewController: NSViewController, StoreSubscriber { typealias StoreSubscriberStateType = ViewData.StateFragment override func viewWillAppear() { super.viewWillAppear() store.subscribe(self) { subscription in subscription .select(ViewData.fragment(of:)) .skipRepeats() } } override func viewWillDisappear() { super.viewWillDisappear() store.unsubscribe(self) } func newState(state: ViewData.StateFragment) { DispatchQueue.main.async { [weak self] in self?.update(with: ViewData(for: state)) } } func update(with _: ViewData) { fatalError("Please override the SubscriberViewController update method.") } } protocol ViewDataType { associatedtype StateFragment: Equatable static func fragment(of appState: AppState) -> StateFragment init(for fragment: StateFragment) } ================================================ FILE: DeskPad/main.swift ================================================ import AppKit let app = NSApplication.shared let delegate = AppDelegate() app.delegate = delegate _ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv) ================================================ FILE: DeskPad.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 55; objects = { /* Begin PBXBuildFile section */ 6D2F1482280C1F9200A3A2E5 /* ReSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 6D2F1481280C1F9200A3A2E5 /* ReSwift */; }; 6D2F1486280C20C800A3A2E5 /* SubscriberViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D2F1485280C20C800A3A2E5 /* SubscriberViewController.swift */; }; 6D2F148A280C20D000A3A2E5 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D2F1487280C20D000A3A2E5 /* AppState.swift */; }; 6D2F148B280C20D000A3A2E5 /* SideEffectsMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D2F1488280C20D000A3A2E5 /* SideEffectsMiddleware.swift */; }; 6D2F148C280C20D000A3A2E5 /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D2F1489280C20D000A3A2E5 /* Store.swift */; }; 6D2F148E280C211E00A3A2E5 /* ScreenViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D2F148D280C211E00A3A2E5 /* ScreenViewController.swift */; }; 6D41B09F2879FAB6007CEB2F /* MouseLocationSideEffect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D41B09E2879FAB6007CEB2F /* MouseLocationSideEffect.swift */; }; 6D41B0A12879FABE007CEB2F /* MouseLocationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D41B0A02879FABE007CEB2F /* MouseLocationState.swift */; }; 6D41B0A42879FBA8007CEB2F /* ScreenViewData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D41B0A32879FBA8007CEB2F /* ScreenViewData.swift */; }; 6D68E1AF287ABB9900CD574A /* ScreenConfigurationSideEffect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D68E1AE287ABB9900CD574A /* ScreenConfigurationSideEffect.swift */; }; 6D68E1B2287ABDB900CD574A /* NSScreen+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D68E1B1287ABDB900CD574A /* NSScreen+Extensions.swift */; }; 6D68E1B4287ABFC800CD574A /* ScreenConfigurationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D68E1B3287ABFC800CD574A /* ScreenConfigurationState.swift */; }; 6DC044522801877F00281728 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DC044512801877F00281728 /* AppDelegate.swift */; }; 6DC044562801878100281728 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6DC044552801878100281728 /* Assets.xcassets */; }; 6DC04461280191EB00281728 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DC04460280191EB00281728 /* main.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 6D2F1485280C20C800A3A2E5 /* SubscriberViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubscriberViewController.swift; sourceTree = ""; }; 6D2F1487280C20D000A3A2E5 /* AppState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = ""; }; 6D2F1488280C20D000A3A2E5 /* SideEffectsMiddleware.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SideEffectsMiddleware.swift; sourceTree = ""; }; 6D2F1489280C20D000A3A2E5 /* Store.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Store.swift; sourceTree = ""; }; 6D2F148D280C211E00A3A2E5 /* ScreenViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScreenViewController.swift; sourceTree = ""; }; 6D36BEB92801A39200EAB869 /* CGVirtualDisplayPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CGVirtualDisplayPrivate.h; sourceTree = ""; }; 6D36BEBA2801A40600EAB869 /* DeskPad-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "DeskPad-Bridging-Header.h"; sourceTree = ""; }; 6D41B09E2879FAB6007CEB2F /* MouseLocationSideEffect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MouseLocationSideEffect.swift; sourceTree = ""; }; 6D41B0A02879FABE007CEB2F /* MouseLocationState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MouseLocationState.swift; sourceTree = ""; }; 6D41B0A32879FBA8007CEB2F /* ScreenViewData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenViewData.swift; sourceTree = ""; }; 6D68E1AE287ABB9900CD574A /* ScreenConfigurationSideEffect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenConfigurationSideEffect.swift; sourceTree = ""; }; 6D68E1B1287ABDB900CD574A /* NSScreen+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSScreen+Extensions.swift"; sourceTree = ""; }; 6D68E1B3287ABFC800CD574A /* ScreenConfigurationState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenConfigurationState.swift; sourceTree = ""; }; 6DC0444E2801877F00281728 /* DeskPad.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DeskPad.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6DC044512801877F00281728 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 6DC044552801878100281728 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 6DC0445A2801878100281728 /* DeskPad.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DeskPad.entitlements; sourceTree = ""; }; 6DC04460280191EB00281728 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 6DC0444B2801877F00281728 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 6D2F1482280C1F9200A3A2E5 /* ReSwift in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 6D2F1483280C201B00A3A2E5 /* Backend */ = { isa = PBXGroup; children = ( 6D2F1487280C20D000A3A2E5 /* AppState.swift */, 6D2F1488280C20D000A3A2E5 /* SideEffectsMiddleware.swift */, 6D2F1489280C20D000A3A2E5 /* Store.swift */, 6D68E1AD287ABB6F00CD574A /* ScreenConfiguration */, 6D41B09D2879FA87007CEB2F /* MouseLocation */, ); path = Backend; sourceTree = ""; }; 6D2F1484280C202700A3A2E5 /* Frontend */ = { isa = PBXGroup; children = ( 6D41B0A22879FB88007CEB2F /* Screen */, ); path = Frontend; sourceTree = ""; }; 6D41B09D2879FA87007CEB2F /* MouseLocation */ = { isa = PBXGroup; children = ( 6D41B09E2879FAB6007CEB2F /* MouseLocationSideEffect.swift */, 6D41B0A02879FABE007CEB2F /* MouseLocationState.swift */, ); path = MouseLocation; sourceTree = ""; }; 6D41B0A22879FB88007CEB2F /* Screen */ = { isa = PBXGroup; children = ( 6D2F148D280C211E00A3A2E5 /* ScreenViewController.swift */, 6D41B0A32879FBA8007CEB2F /* ScreenViewData.swift */, ); path = Screen; sourceTree = ""; }; 6D68E1AD287ABB6F00CD574A /* ScreenConfiguration */ = { isa = PBXGroup; children = ( 6D68E1AE287ABB9900CD574A /* ScreenConfigurationSideEffect.swift */, 6D68E1B3287ABFC800CD574A /* ScreenConfigurationState.swift */, ); path = ScreenConfiguration; sourceTree = ""; }; 6D68E1B0287ABDAB00CD574A /* Helpers */ = { isa = PBXGroup; children = ( 6D68E1B1287ABDB900CD574A /* NSScreen+Extensions.swift */, ); path = Helpers; sourceTree = ""; }; 6DC044452801877F00281728 = { isa = PBXGroup; children = ( 6DC044502801877F00281728 /* DeskPad */, 6DC0444F2801877F00281728 /* Products */, ); sourceTree = ""; }; 6DC0444F2801877F00281728 /* Products */ = { isa = PBXGroup; children = ( 6DC0444E2801877F00281728 /* DeskPad.app */, ); name = Products; sourceTree = ""; }; 6DC044502801877F00281728 /* DeskPad */ = { isa = PBXGroup; children = ( 6DC04460280191EB00281728 /* main.swift */, 6D2F1485280C20C800A3A2E5 /* SubscriberViewController.swift */, 6DC044512801877F00281728 /* AppDelegate.swift */, 6D2F1483280C201B00A3A2E5 /* Backend */, 6D2F1484280C202700A3A2E5 /* Frontend */, 6D68E1B0287ABDAB00CD574A /* Helpers */, 6D36BEBA2801A40600EAB869 /* DeskPad-Bridging-Header.h */, 6D36BEB92801A39200EAB869 /* CGVirtualDisplayPrivate.h */, 6DC044552801878100281728 /* Assets.xcassets */, 6DC0445A2801878100281728 /* DeskPad.entitlements */, ); path = DeskPad; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 6DC0444D2801877F00281728 /* DeskPad */ = { isa = PBXNativeTarget; buildConfigurationList = 6DC0445D2801878100281728 /* Build configuration list for PBXNativeTarget "DeskPad" */; buildPhases = ( 6D2F147F280C1C1400A3A2E5 /* Run SwiftFormat */, 6DC0444A2801877F00281728 /* Sources */, 6DC0444B2801877F00281728 /* Frameworks */, 6DC0444C2801877F00281728 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = DeskPad; packageProductDependencies = ( 6D2F1481280C1F9200A3A2E5 /* ReSwift */, ); productName = DeskPad; productReference = 6DC0444E2801877F00281728 /* DeskPad.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 6DC044462801877F00281728 /* Project object */ = { isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1320; LastUpgradeCheck = 1320; TargetAttributes = { 6DC0444D2801877F00281728 = { CreatedOnToolsVersion = 13.2.1; }; }; }; buildConfigurationList = 6DC044492801877F00281728 /* Build configuration list for PBXProject "DeskPad" */; compatibilityVersion = "Xcode 13.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 6DC044452801877F00281728; packageReferences = ( 6D2F1480280C1F9200A3A2E5 /* XCRemoteSwiftPackageReference "ReSwift" */, ); productRefGroup = 6DC0444F2801877F00281728 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 6DC0444D2801877F00281728 /* DeskPad */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 6DC0444C2801877F00281728 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 6DC044562801878100281728 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 6D2F147F280C1C1400A3A2E5 /* Run SwiftFormat */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( ); name = "Run SwiftFormat"; outputFileListPaths = ( ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "cd BuildTools\nSDKROOT=(xcrun --sdk macosx --show-sdk-path)\n#swift package update #Uncomment this line temporarily to update the version used to the latest matching your BuildTools/Package.swift file\nswift run -c release swiftformat \"$SRCROOT\" --swiftversion \"5\"\n"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 6DC0444A2801877F00281728 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 6D68E1B4287ABFC800CD574A /* ScreenConfigurationState.swift in Sources */, 6D68E1B2287ABDB900CD574A /* NSScreen+Extensions.swift in Sources */, 6D2F148C280C20D000A3A2E5 /* Store.swift in Sources */, 6D2F1486280C20C800A3A2E5 /* SubscriberViewController.swift in Sources */, 6D68E1AF287ABB9900CD574A /* ScreenConfigurationSideEffect.swift in Sources */, 6D41B0A12879FABE007CEB2F /* MouseLocationState.swift in Sources */, 6D2F148A280C20D000A3A2E5 /* AppState.swift in Sources */, 6D2F148B280C20D000A3A2E5 /* SideEffectsMiddleware.swift in Sources */, 6D41B09F2879FAB6007CEB2F /* MouseLocationSideEffect.swift in Sources */, 6D41B0A42879FBA8007CEB2F /* ScreenViewData.swift in Sources */, 6D2F148E280C211E00A3A2E5 /* ScreenViewController.swift in Sources */, 6DC044522801877F00281728 /* AppDelegate.swift in Sources */, 6DC04461280191EB00281728 /* main.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 6DC0445B2801878100281728 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OBJC_BRIDGING_HEADER = "DeskPad/DeskPad-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 6DC0445C2801878100281728 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OBJC_BRIDGING_HEADER = "DeskPad/DeskPad-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-O"; }; name = Release; }; 6DC0445E2801878100281728 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = DeskPad/DeskPad.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 6; DEVELOPMENT_TEAM = TYPC962S4N; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; INFOPLIST_KEY_NSHumanReadableCopyright = ""; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); MARKETING_VERSION = 1.3.2; PRODUCT_BUNDLE_IDENTIFIER = com.stengo.DeskPad; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; }; name = Debug; }; 6DC0445F2801878100281728 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = DeskPad/DeskPad.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 6; DEVELOPMENT_TEAM = TYPC962S4N; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; INFOPLIST_KEY_NSHumanReadableCopyright = ""; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); MARKETING_VERSION = 1.3.2; PRODUCT_BUNDLE_IDENTIFIER = com.stengo.DeskPad; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 6DC044492801877F00281728 /* Build configuration list for PBXProject "DeskPad" */ = { isa = XCConfigurationList; buildConfigurations = ( 6DC0445B2801878100281728 /* Debug */, 6DC0445C2801878100281728 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 6DC0445D2801878100281728 /* Build configuration list for PBXNativeTarget "DeskPad" */ = { isa = XCConfigurationList; buildConfigurations = ( 6DC0445E2801878100281728 /* Debug */, 6DC0445F2801878100281728 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ 6D2F1480280C1F9200A3A2E5 /* XCRemoteSwiftPackageReference "ReSwift" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/ReSwift/ReSwift.git"; requirement = { kind = upToNextMajorVersion; minimumVersion = 6.0.0; }; }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ 6D2F1481280C1F9200A3A2E5 /* ReSwift */ = { isa = XCSwiftPackageProductDependency; package = 6D2F1480280C1F9200A3A2E5 /* XCRemoteSwiftPackageReference "ReSwift" */; productName = ReSwift; }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 6DC044462801877F00281728 /* Project object */; } ================================================ FILE: DeskPad.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: DeskPad.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: DeskPad.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved ================================================ { "object": { "pins": [ { "package": "ReSwift", "repositoryURL": "https://github.com/ReSwift/ReSwift.git", "state": { "branch": null, "revision": "96146a29f394ae4c79be025fcec194e5b0d9c3b6", "version": "6.1.0" } } ] }, "version": 1 } ================================================ FILE: LICENSE.md ================================================ MIT License Copyright (c) 2022 Bastian Andelefski Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================

DeskPad Icon

# DeskPad A virtual monitor for screen sharing

DeskPad Screenshot

Certain workflows require sharing the entire screen (usually due to switching through multiple applications), but if the presenter has a much larger display than the audience it can be hard to see what is happening. DeskPad creates a virtual display that is mirrored within its application window so that you can create a dedicated, easily shareable workspace. # Installation You can either download the [latest release binary](https://github.com/Stengo/DeskPad/releases) or install via [Homebrew](https://brew.sh) by calling `brew install --cask deskpad`. # Usage DeskPad behaves like any other display. Launching the app is equivalent to plugging in a monitor, so macOS will take care of properly arranging your windows to their previous configuration. You can change the display resolution through the system preferences and the application window will adjust accordingly. Whenever you move your mouse cursor to the virtual display, DeskPad will highlight its title bar in blue and move the application window to the front to let you know where you are.

DeskPad Demonstration

# Troubleshooting DeskPad may need screen recording permissions to display properly. Follow these steps: 1. **Open System Settings** → **Privacy & Security** → **Screen Recording** 2. **Enable DeskPad** by checking the box next to it 3. **If DeskPad appears but isn't working:** - Uncheck the DeskPad option - Check it again to re-enable 4. **Restart DeskPad** for changes to take effect