18 Commits

Author SHA1 Message Date
neon443
8a4b0f0f65 we now have preferences
use it to:
 - move the dock/mouse
 - smaller deathzone
 - check for updates (sparkle yayyy)
 - quit
this took way too long
2025-05-30 18:42:50 +01:00
neon443
6c9d65f026 formatting, debug stuff 2025-05-30 16:07:07 +01:00
neon443
4b0e0db186 FINALLY
created settings window that actually shows up
2025-05-30 16:05:35 +01:00
neon443
c0b8d2f3ed Sparkle: Auto Updates work YAYYYYYYY 2025-05-30 15:00:53 +01:00
neon443
a6f06c4e12 Merge remote-tracking branch 'refs/remotes/origin/main' 2025-05-30 13:05:30 +01:00
neon443
9ff4f67e33 add pubkey 2025-05-30 10:44:23 +01:00
neon443
5bfeef66ab sparke menu item 2025-05-30 10:42:54 +01:00
Nihaal Sharma
58c834f1ed Update README.md 2025-05-29 17:29:27 +01:00
Nihaal Sharma
84326f7e15 Update README.md 2025-05-29 17:28:33 +01:00
Nihaal Sharma
27e410ae76 Update README.md 2025-05-29 17:25:54 +01:00
neon443
d943415b98 add mouse moves count
tweak the aligment of the pinch
added mouse move count to menu bar,
grammar fix
2025-05-29 16:11:41 +01:00
neon443
83efb14bd5 fix 2x pinchs 2025-05-29 16:03:28 +01:00
neon443
d60d90bc60 got a pinch lollll 2025-05-29 16:00:21 +01:00
neon443
4e55cc4516 we have a square following the mouse 2025-05-29 15:38:54 +01:00
neon443
1a0d3c2e38 YESSS 2025-05-29 15:33:19 +01:00
neon443
e46edecec7 xcode 12.0 compat 2025-05-29 14:00:18 +01:00
neon443
22c825dbb2 gitignore 2025-05-29 13:54:10 +01:00
neon443
5357ce8443 large rewrite of dpsettings to use an init and handle failed decodes
make moveMouse() use dpsettings' values
skyhigh moves faster
skyhigh uses dpsettings' values
extended NSScreen for safe access to main?.frame
customising the width height of the mouse move rect should be possible? now just neeed a prefs windo
2025-05-29 13:47:20 +01:00
17 changed files with 528 additions and 125 deletions

3
.gitignore vendored
View File

@@ -1 +1,2 @@
.DS_Store **.DS_Store
**DockPhobia.dmg

View File

@@ -5,8 +5,8 @@
// Created by neon443 on 26/05/2025. // Created by neon443 on 26/05/2025.
// //
VERSION = 1.0.1 VERSION = 1.3
BUILD_ID = 2 BUILD_ID = 3
TEAM_ID = 8JGND254B7 TEAM_ID = 8JGND254B7
BUNDLE_ID = com.neon443.DockPhobia BUNDLE_ID = com.neon443.DockPhobia

View File

@@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 77; objectVersion = 63;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
@@ -14,6 +14,9 @@
A98C20C62DE614180008D61C /* DPSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20C52DE614180008D61C /* DPSettings.swift */; }; A98C20C62DE614180008D61C /* DPSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20C52DE614180008D61C /* DPSettings.swift */; };
A9C9AF812DE7776A0039D7A5 /* DockSide.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C9AF802DE777530039D7A5 /* DockSide.swift */; }; A9C9AF812DE7776A0039D7A5 /* DockSide.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C9AF802DE777530039D7A5 /* DockSide.swift */; };
A9C9AF832DE77CB70039D7A5 /* SkyHigh.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C9AF822DE77CB70039D7A5 /* SkyHigh.swift */; }; A9C9AF832DE77CB70039D7A5 /* SkyHigh.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C9AF822DE77CB70039D7A5 /* SkyHigh.swift */; };
A9C9B06D2DE99E5F0039D7A5 /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = A9C9B06C2DE99E5F0039D7A5 /* Sparkle */; };
A9C9B0712DE9F6E60039D7A5 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = A9C9B0702DE9F6E60039D7A5 /* Preferences.xib */; };
A9C9B0732DE9F7020039D7A5 /* SettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C9B0722DE9F7020039D7A5 /* SettingsController.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
@@ -27,6 +30,9 @@
A98C20C52DE614180008D61C /* DPSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DPSettings.swift; sourceTree = "<group>"; }; A98C20C52DE614180008D61C /* DPSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DPSettings.swift; sourceTree = "<group>"; };
A9C9AF802DE777530039D7A5 /* DockSide.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DockSide.swift; sourceTree = "<group>"; }; A9C9AF802DE777530039D7A5 /* DockSide.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DockSide.swift; sourceTree = "<group>"; };
A9C9AF822DE77CB70039D7A5 /* SkyHigh.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkyHigh.swift; sourceTree = "<group>"; }; A9C9AF822DE77CB70039D7A5 /* SkyHigh.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkyHigh.swift; sourceTree = "<group>"; };
A9C9B06E2DE9B55F0039D7A5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
A9C9B0702DE9F6E60039D7A5 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = Preferences.xib; sourceTree = "<group>"; };
A9C9B0722DE9F7020039D7A5 /* SettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsController.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@@ -34,6 +40,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
A9C9B06D2DE99E5F0039D7A5 /* Sparkle in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -51,6 +58,7 @@
A94BEC102DE23ECE00D4811D /* Views */ = { A94BEC102DE23ECE00D4811D /* Views */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A9C9B0702DE9F6E60039D7A5 /* Preferences.xib */,
A94BEC0E2DE23E8500D4811D /* MainMenu.xib */, A94BEC0E2DE23E8500D4811D /* MainMenu.xib */,
); );
path = Views; path = Views;
@@ -76,11 +84,13 @@
A966B4F32DE0842400C721A5 /* DockPhobia */ = { A966B4F32DE0842400C721A5 /* DockPhobia */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A9C9B06E2DE9B55F0039D7A5 /* Info.plist */,
A966B4EE2DE0842400C721A5 /* AppDelegate.swift */, A966B4EE2DE0842400C721A5 /* AppDelegate.swift */,
A966B4F72DE0852900C721A5 /* MouseTracker.swift */, A966B4F72DE0852900C721A5 /* MouseTracker.swift */,
A9C9AF822DE77CB70039D7A5 /* SkyHigh.swift */, A9C9AF822DE77CB70039D7A5 /* SkyHigh.swift */,
A98C20C52DE614180008D61C /* DPSettings.swift */, A98C20C52DE614180008D61C /* DPSettings.swift */,
A9C9AF802DE777530039D7A5 /* DockSide.swift */, A9C9AF802DE777530039D7A5 /* DockSide.swift */,
A9C9B0722DE9F7020039D7A5 /* SettingsController.swift */,
A94BEC102DE23ECE00D4811D /* Views */, A94BEC102DE23ECE00D4811D /* Views */,
A94BEC0A2DE21F8100D4811D /* Resources */, A94BEC0A2DE21F8100D4811D /* Resources */,
A966B4F02DE0842400C721A5 /* DockPhobia.entitlements */, A966B4F02DE0842400C721A5 /* DockPhobia.entitlements */,
@@ -105,6 +115,7 @@
); );
name = DockPhobia; name = DockPhobia;
packageProductDependencies = ( packageProductDependencies = (
A9C9B06C2DE99E5F0039D7A5 /* Sparkle */,
); );
productName = DockPhobia; productName = DockPhobia;
productReference = A966B4D62DE0841000C721A5 /* DockPhobia.app */; productReference = A966B4D62DE0841000C721A5 /* DockPhobia.app */;
@@ -126,6 +137,7 @@
}; };
}; };
buildConfigurationList = A966B4D12DE0841000C721A5 /* Build configuration list for PBXProject "DockPhobia" */; buildConfigurationList = A966B4D12DE0841000C721A5 /* Build configuration list for PBXProject "DockPhobia" */;
compatibilityVersion = "Xcode 12.0";
developmentRegion = en; developmentRegion = en;
hasScannedForEncodings = 0; hasScannedForEncodings = 0;
knownRegions = ( knownRegions = (
@@ -134,7 +146,9 @@
); );
mainGroup = A966B4CD2DE0841000C721A5; mainGroup = A966B4CD2DE0841000C721A5;
minimizedProjectReferenceProxies = 1; minimizedProjectReferenceProxies = 1;
preferredProjectObjectVersion = 77; packageReferences = (
A9C9B06B2DE99E5F0039D7A5 /* XCRemoteSwiftPackageReference "Sparkle" */,
);
productRefGroup = A966B4D72DE0841000C721A5 /* Products */; productRefGroup = A966B4D72DE0841000C721A5 /* Products */;
projectDirPath = ""; projectDirPath = "";
projectRoot = ""; projectRoot = "";
@@ -149,6 +163,7 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
A9C9B0712DE9F6E60039D7A5 /* Preferences.xib in Resources */,
A94BEC0F2DE23E8500D4811D /* MainMenu.xib in Resources */, A94BEC0F2DE23E8500D4811D /* MainMenu.xib in Resources */,
A966B4F52DE0842500C721A5 /* Assets.xcassets in Resources */, A966B4F52DE0842500C721A5 /* Assets.xcassets in Resources */,
); );
@@ -163,6 +178,7 @@
files = ( files = (
A98C20C62DE614180008D61C /* DPSettings.swift in Sources */, A98C20C62DE614180008D61C /* DPSettings.swift in Sources */,
A9C9AF832DE77CB70039D7A5 /* SkyHigh.swift in Sources */, A9C9AF832DE77CB70039D7A5 /* SkyHigh.swift in Sources */,
A9C9B0732DE9F7020039D7A5 /* SettingsController.swift in Sources */,
A966B4F82DE0852900C721A5 /* MouseTracker.swift in Sources */, A966B4F82DE0852900C721A5 /* MouseTracker.swift in Sources */,
A966B4F42DE0842500C721A5 /* AppDelegate.swift in Sources */, A966B4F42DE0842500C721A5 /* AppDelegate.swift in Sources */,
A9C9AF812DE7776A0039D7A5 /* DockSide.swift in Sources */, A9C9AF812DE7776A0039D7A5 /* DockSide.swift in Sources */,
@@ -306,6 +322,7 @@
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO; ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = DockPhobia/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment";
INFOPLIST_KEY_LSUIElement = YES; INFOPLIST_KEY_LSUIElement = YES;
INFOPLIST_KEY_NSAppleEventsUsageDescription = _; INFOPLIST_KEY_NSAppleEventsUsageDescription = _;
@@ -341,6 +358,7 @@
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO; ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = DockPhobia/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment";
INFOPLIST_KEY_LSUIElement = YES; INFOPLIST_KEY_LSUIElement = YES;
INFOPLIST_KEY_NSAppleEventsUsageDescription = _; INFOPLIST_KEY_NSAppleEventsUsageDescription = _;
@@ -384,6 +402,25 @@
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
/* End XCConfigurationList section */ /* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
A9C9B06B2DE99E5F0039D7A5 /* XCRemoteSwiftPackageReference "Sparkle" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/sparkle-project/Sparkle";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 2.7.0;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
A9C9B06C2DE99E5F0039D7A5 /* Sparkle */ = {
isa = XCSwiftPackageProductDependency;
package = A9C9B06B2DE99E5F0039D7A5 /* XCRemoteSwiftPackageReference "Sparkle" */;
productName = Sparkle;
};
/* End XCSwiftPackageProductDependency section */
}; };
rootObject = A966B4CE2DE0841000C721A5 /* Project object */; rootObject = A966B4CE2DE0841000C721A5 /* Project object */;
} }

View File

@@ -0,0 +1,15 @@
{
"originHash" : "e721da7f9826abdffcb6185e886155efa2514bd6234475f1afa893e29eb258d6",
"pins" : [
{
"identity" : "sparkle",
"kind" : "remoteSourceControl",
"location" : "https://github.com/sparkle-project/Sparkle",
"state" : {
"revision" : "0ca3004e98712ea2b39dd881d28448630cce1c99",
"version" : "2.7.0"
}
}
],
"version" : 3
}

BIN
DockPhobia/.DS_Store vendored
View File

Binary file not shown.

View File

@@ -6,17 +6,26 @@
// //
import AppKit import AppKit
import Sparkle
@NSApplicationMain @NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate { class AppDelegate: NSObject, NSApplicationDelegate {
public var statusItem: NSStatusItem! public var statusItem: NSStatusItem!
public var prefsWindow: NSWindowController?
var settings = DPSettingsModel() var settings = DPSettingsModel()
var mouseTracker: MouseTracker var mouseTracker: MouseTracker
let updateController: SPUStandardUpdaterController
override init() { override init() {
self.mouseTracker = MouseTracker(settings: settings) self.mouseTracker = MouseTracker(settings: settings)
//call .startUpdater() later
updateController = SPUStandardUpdaterController(
startingUpdater: true,
updaterDelegate: nil,
userDriverDelegate: nil
)
super.init() super.init()
} }
@@ -42,19 +51,19 @@ class AppDelegate: NSObject, NSApplicationDelegate {
let start = NSMenuItem(title: describeStartButton(), action: #selector(didTapStart), keyEquivalent: "") let start = NSMenuItem(title: describeStartButton(), action: #selector(didTapStart), keyEquivalent: "")
menu.addItem(start) menu.addItem(start)
let screen = NSMenuItem(
title: "\(mouseTracker.screen.width)x\(mouseTracker.screen.height)",
action: nil,
keyEquivalent: ""
)
menu.addItem(screen)
let dockMoves = NSMenuItem( let dockMoves = NSMenuItem(
title: "Moved the Dock \(settings.settings.dockMoves) time\(settings.settings.dockMoves.plural)", title: "Moved the Dock \(settings.settings.dockMoves) time\(settings.settings.dockMoves.plural)",
action: nil, action: nil,
keyEquivalent: "" keyEquivalent: ""
) )
menu.addItem(dockMoves) menu.addItem(dockMoves)
let mouseMoves = NSMenuItem(
title: "Moved the cursor \(settings.settings.mouseMoves) time\(settings.settings.mouseMoves.plural)",
action: nil,
keyEquivalent: ""
)
menu.addItem(mouseMoves)
menu.addItem(NSMenuItem.separator()) menu.addItem(NSMenuItem.separator())
let moveMouseButton = NSMenuItem( let moveMouseButton = NSMenuItem(
@@ -67,28 +76,34 @@ class AppDelegate: NSObject, NSApplicationDelegate {
menu.addItem(NSMenuItem.separator()) menu.addItem(NSMenuItem.separator())
let checkfullscreenButton = NSMenuItem( menu.addItem(NSMenuItem(
title: "Smaller deathzone in fullscreen", title: "Move Dock to the left",
action: #selector(checkFullscreenToggle), action: #selector(moveDockObjcLeft),
keyEquivalent: "" keyEquivalent: "1"))
) menu.addItem(NSMenuItem(
checkfullscreenButton.state = NSControl.StateValue(rawValue: settings.settings.checkFullscreen ? 1 : 0) title: "Move Dock to the bottom",
menu.addItem(checkfullscreenButton) action: #selector(moveDockObjcBottom),
keyEquivalent: "2"))
menu.addItem(NSMenuItem(
title: "Move Dock to the right",
action: #selector(moveDockObjcRight),
keyEquivalent: "3"))
menu.addItem(NSMenuItem.separator()) menu.addItem(NSMenuItem.separator())
menu.addItem(NSMenuItem( let checkforUpdatesMenuItem = NSMenuItem(
title: "Move Dock to left", title: "Check for Updates...",
action: #selector(moveDockObjcLeft), action: #selector(SPUStandardUpdaterController.checkForUpdates(_:)),
keyEquivalent: "")) keyEquivalent: ""
menu.addItem(NSMenuItem( )
title: "Move Dock to bottom", checkforUpdatesMenuItem.target = updateController
action: #selector(moveDockObjcBottom), menu.addItem(checkforUpdatesMenuItem)
keyEquivalent: ""))
menu.addItem(NSMenuItem( let prefs = NSMenuItem(
title: "Move Dock to right", title: "Preferences",
action: #selector(moveDockObjcRight), action: #selector(tappedPrefs),
keyEquivalent: "")) keyEquivalent: ","
menu.addItem(NSMenuItem.separator()) )
menu.addItem(prefs)
let quit = NSMenuItem(title: "Quit", action: #selector(quit), keyEquivalent: "q") let quit = NSMenuItem(title: "Quit", action: #selector(quit), keyEquivalent: "q")
menu.addItem(quit) menu.addItem(quit)
@@ -103,6 +118,17 @@ class AppDelegate: NSObject, NSApplicationDelegate {
button.image = NSImage(named: "cursor.slash") button.image = NSImage(named: "cursor.slash")
} }
} }
@objc func tappedPrefs() {
if prefsWindow == nil {
prefsWindow = DPPreferencesWindowController(
mouseTracker: mouseTracker,
settings: settings,
updater: updateController
)
}
prefsWindow!.window?.orderFront(nil)
}
@objc func didTapStart() { @objc func didTapStart() {
if mouseTracker.running { if mouseTracker.running {
mouseTracker.stop() mouseTracker.stop()

View File

@@ -8,10 +8,83 @@
import Foundation import Foundation
import AppKit import AppKit
extension NSScreen {
static var mainFrame: CGRect {
main?.frame ?? CGRect(x: 0, y: 0, width: 1920, height: 1080)
}
static var mainFrameWidth: CGFloat {
main?.frame.width ?? 1920
}
static var mainFrameHeight: CGFloat {
main?.frame.height ?? 1080
}
}
struct DPSettings: Codable { struct DPSettings: Codable {
var dockMoves: Int = 0 var dockMoves: Int
var checkFullscreen: Bool = false var mouseMoves: Int
var moveMouseInstead: Bool = false var checkFullscreen: Bool
var moveMouseInstead: Bool
var mouseInsetLeading: CGFloat {
NSScreen.mainFrameWidth*insetHorizontal
}
var mouseInsetBottom: CGFloat {
NSScreen.mainFrameHeight*insetVertical
}
var mouseInsetTop: CGFloat {
NSScreen.mainFrameHeight*(1-(insetVertical))
}
var mouseInsetTrailing: CGFloat {
NSScreen.mainFrameWidth*(1-(insetHorizontal))
}
var insetHorizontal: CGFloat
var insetVertical: CGFloat
var mouseMoveRect: CGRect {
return CGRect(
x: mouseInsetLeading,
y: mouseInsetBottom,
width: mouseInsetTrailing - mouseInsetLeading,
height: mouseInsetTop - mouseInsetBottom
)
}
init(
dockMoves: Int = 0,
mouseMoves: Int = 0,
checkFullscreen: Bool = false,
moveMouseInstead: Bool = false,
insetHorizontal: CGFloat = 0.05,
insetVertical: CGFloat = 0.1
) {
self.dockMoves = dockMoves
self.mouseMoves = mouseMoves
self.checkFullscreen = checkFullscreen
self.moveMouseInstead = moveMouseInstead
self.insetHorizontal = insetHorizontal
self.insetVertical = insetVertical
}
init(from decoder: any Decoder) throws {
let defaults = DPSettings()
let container = try decoder.container(keyedBy: CodingKeys.self)
dockMoves = try container.decodeIfPresent(Int.self, forKey: .dockMoves)
?? defaults.dockMoves
mouseMoves = try container.decodeIfPresent(Int.self, forKey: .mouseMoves)
?? defaults.mouseMoves
checkFullscreen = try container.decodeIfPresent(Bool.self, forKey: .checkFullscreen)
?? defaults.checkFullscreen
moveMouseInstead = try container.decodeIfPresent(Bool.self, forKey: .moveMouseInstead)
?? defaults.moveMouseInstead
insetHorizontal = try container.decodeIfPresent(CGFloat.self, forKey: .insetHorizontal)
?? defaults.insetHorizontal
insetVertical = try container.decodeIfPresent(CGFloat.self, forKey: .insetVertical)
?? defaults.insetVertical
}
} }
class DPSettingsModel { class DPSettingsModel {

12
DockPhobia/Info.plist Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SUFeedURL</key>
<string>https://neon443.github.io/appcasts/DockPhobia/appcast.xml</string>
<key>SUpublicEDKey</key>
<string>ahgIyJGs4MCQ6UXwQ11aknk3a6GwOodHKSmVv4bw6KY=</string>
<key>SUEnableAutomaticChecks</key>
<true/>
</dict>
</plist>

View File

@@ -10,6 +10,23 @@ import AppKit
import Cocoa import Cocoa
import ApplicationServices import ApplicationServices
extension NSEvent {
var mouseLocationCG: CGPoint {
var loc = NSEvent.mouseLocation
loc.y = NSScreen.mainFrameHeight - loc.y
return loc
}
}
extension CGPoint {
var invertedForScreen: CGPoint {
return CGPoint(
x: self.x,
y: NSScreen.mainFrameHeight - self.y
)
}
}
struct Screen { struct Screen {
var width: CGFloat var width: CGFloat
var height: CGFloat var height: CGFloat
@@ -23,22 +40,22 @@ class MouseTracker {
var dockHeight: CGFloat = 0 var dockHeight: CGFloat = 0
var settings: DPSettingsModel var settings: DPSettingsModel
var skyHigh = SkyHigh() var skyHigh: SkyHigh
private var timer: Timer?
private var loopIteration: Double = 0
init(settings: DPSettingsModel) { init(settings: DPSettingsModel) {
print(DockSide()) print(DockSide())
if let screen = NSScreen.main {
let rect = screen.frame self.screen = Screen(
self.screen = Screen( width: NSScreen.mainFrameWidth,
width: rect.width, height: NSScreen.mainFrameHeight
height: rect.height )
) print(self.screen)
print(self.screen)
} else {
fatalError("no screen wtf???")
}
self.settings = settings self.settings = settings
self.skyHigh = SkyHigh(settings: settings)
self.currentDockSide = .left self.currentDockSide = .left
moveDock(.bottom) moveDock(.bottom)
@@ -46,8 +63,13 @@ class MouseTracker {
} }
func checkMouse(_ event: NSEvent) { func checkMouse(_ event: NSEvent) {
var location = NSEvent.mouseLocation let location = event.mouseLocationCG
location.y = screen.height - location.y #if DEBUG
var cgpointForSkyHigh = NSEvent.mouseLocation
cgpointForSkyHigh.x -= 20
cgpointForSkyHigh.y -= 5
skyHigh.move(to: cgpointForSkyHigh)
#endif
guard settings.settings.checkFullscreen else { guard settings.settings.checkFullscreen else {
handleDockValue(dockIsAt: currentDockSide, location: location) handleDockValue(dockIsAt: currentDockSide, location: location)
@@ -105,30 +127,18 @@ class MouseTracker {
} }
func start() { func start() {
#if DEBUG
skyHigh.show()
#endif
self.monitor = NSEvent.addGlobalMonitorForEvents(matching: .mouseMoved, handler: checkMouse) self.monitor = NSEvent.addGlobalMonitorForEvents(matching: .mouseMoved, handler: checkMouse)
self.running = true self.running = true
print("started tracking") print("started tracking")
skyHigh.move()
} }
func stop() { func stop() {
#if DEBUG
skyHigh.hide()
#endif
if let monitor = monitor { if let monitor = monitor {
NSEvent.removeMonitor(monitor) NSEvent.removeMonitor(monitor)
self.running = false self.running = false
@@ -138,24 +148,50 @@ class MouseTracker {
} }
func moveMouse() { func moveMouse() {
let rangeW = screen.width*0.1...screen.width*0.9 let prevPoint = NSEvent().mouseLocationCG
let rangeW = settings.settings.mouseInsetLeading...settings.settings.mouseInsetTrailing
let posX = CGFloat.random(in: rangeW) let posX = CGFloat.random(in: rangeW)
let rangeH = screen.height*0.1...screen.height*0.9 let rangeH = settings.settings.mouseInsetBottom...settings.settings.mouseInsetTop
let posY = CGFloat.random(in: rangeH) let posY = CGFloat.random(in: rangeH)
CGDisplayMoveCursorToPoint(0, CGPoint(x: posX, y: posY))
timer?.invalidate()
loopIteration = 0
skyHigh.move(to: prevPoint.invertedForScreen)
skyHigh.show()
timer = Timer(timeInterval: 0.005, repeats: true) { [weak self] _ in
guard let self = self else { return }
guard loopIteration < 500 else {
skyHigh.hide()
settings.settings.mouseMoves += 1
refreshMenus()
timer?.invalidate()
return
}
let newPosX = (prevPoint.x > posX ? prevPoint.x-loopIteration : prevPoint.x+loopIteration)
let newPosY = (prevPoint.y > posY ? prevPoint.y-loopIteration : prevPoint.y+loopIteration)
let cgpoint = CGPoint(x: newPosX, y: newPosY)
CGWarpMouseCursorPosition(cgpoint)
var cgpointForSkyHigh = cgpoint
cgpointForSkyHigh.x -= 20
cgpointForSkyHigh.y += 5
skyHigh.move(to: cgpointForSkyHigh.invertedForScreen)
self.loopIteration += 1
}
RunLoop.main.add(timer!, forMode: .common)
} }
func moveDock(_ toSide: DockSide) { func moveDock(_ toSide: DockSide) {
guard currentDockSide != toSide else { return } guard currentDockSide != toSide else { return }
// let scriptHide = """ // let scriptHide = """
// tell application "System Events" // tell application "System Events"
// tell dock preferences // tell dock preferences
// set autohide to true // set autohide to true
// end tell // end tell
// end tell // end tell
// """ // """
// //
// let scriptShow = scriptHide.replacingOccurrences(of: "true", with: "false") // let scriptShow = scriptHide.replacingOccurrences(of: "true", with: "false")
let scriptMove = """ let scriptMove = """
tell application "System Events" tell application "System Events"
@@ -164,16 +200,15 @@ class MouseTracker {
end tell end tell
end tell end tell
""" """
// applescript(scriptHide) // applescript(scriptHide)
applescript(scriptMove) applescript(scriptMove)
// applescript(scriptShow) // applescript(scriptShow)
currentDockSide = toSide currentDockSide = toSide
settings.settings.dockMoves += 1 settings.settings.dockMoves += 1
refreshMenus() refreshMenus()
} }
func getDockSize() { func getDockSize() {
guard let screen = NSScreen.main?.frame else { fatalError() }
guard let screenVisible = NSScreen.main?.visibleFrame else { fatalError() } guard let screenVisible = NSScreen.main?.visibleFrame else { fatalError() }
self.dockHeight = screen.height - screenVisible.height self.dockHeight = screen.height - screenVisible.height
} }

View File

@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "pinch.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "pinch.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "pinch.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@@ -0,0 +1,71 @@
//
// Preferences.swift
// DockPhobia
//
// Created by neon443 on 29/05/2025.
//
import Foundation
import AppKit
import Sparkle
class DPPreferencesWindowController: NSWindowController {
var mouseTracker: MouseTracker?
var settings: DPSettingsModel?
var updater: SPUStandardUpdaterController?
@IBOutlet weak var mouseRadio: NSButton!
@IBOutlet weak var dockRadio: NSButton!
@IBOutlet weak var updateCheckButton: NSButton!
@IBOutlet weak var smallDeathzoneToggle: NSButton!
@IBOutlet weak var quitbutton: NSButton!
override init(window: NSWindow?) {
super.init(window: window)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
convenience init(mouseTracker: MouseTracker, settings: DPSettingsModel, updater: SPUStandardUpdaterController) {
self.init(windowNibName: "Preferences")
self.mouseTracker = mouseTracker
self.settings = settings
self.updater = updater
}
override func windowDidLoad() {
smallDeathzoneToggle.state = NSControl.StateValue(
settings!.settings.checkFullscreen ? 1 : 0
)
dockRadio.state = NSControl.StateValue(
settings!.settings.moveMouseInstead ? 0 : 1
)
mouseRadio.state = NSControl.StateValue(
settings!.settings.moveMouseInstead ? 1 : 0
)
}
@IBAction func checkUpdates(_ sender: Any) {
updater?.checkForUpdates(nil)
}
@IBAction func MoveTypeSelect(_ sender: Any) {
if dockRadio.state.rawValue == 1 {
settings?.settings.moveMouseInstead = false
} else {
settings?.settings.moveMouseInstead = true
}
refreshMenus()
}
@IBAction func quit(_ sender: Any) {
NSApplication.shared.terminate(nil)
}
@IBAction func smallDeathzoneToggle(_ sender: Any) {
settings?.settings.checkFullscreen.toggle()
}
}

View File

@@ -12,41 +12,40 @@ class SkyHigh {
private var window: NSWindow private var window: NSWindow
private var x = 1 private var x = 1
private var timer: Timer? private var timer: Timer?
var settings: DPSettingsModel
init() { init(settings: DPSettingsModel) {
guard let screen = NSScreen.main?.frame else { fatalError() } self.settings = settings
self.window = NSWindow( self.window = NSWindow(
contentRect: CGRect( contentRect: CGRect(
x: screen.width*0.05, x: NSScreen.mainFrameWidth/2,
y: screen.height*0.1, y: NSScreen.mainFrameHeight/2,
width: screen.width*0.9, width: 100,
height: screen.height*0.8 height: 100
), ),
styleMask: .borderless, styleMask: .borderless,
backing: .buffered, backing: .buffered,
defer: false defer: false
) )
window.backgroundColor = .init(srgbRed: 1, green: 1, blue: 1, alpha: 0.1) window.backgroundColor = .init(srgbRed: 1, green: 1, blue: 1, alpha: 0)
window.contentView = NSImageView(image: NSImage(named: "pinch")!)
window.isOpaque = false window.isOpaque = false
window.level = NSWindow.Level.statusBar + 1 window.level = NSWindow.Level.statusBar + 1
window.ignoresMouseEvents = true window.ignoresMouseEvents = true
window.hasShadow = true window.hasShadow = true
window.makeKeyAndOrderFront(nil) window.collectionBehavior = NSWindow.CollectionBehavior.canJoinAllSpaces.union(.stationary)
window.setFrameOrigin(NSPoint(x: screen.width*0.05, y: screen.height*0.1))
} }
func move() { func move(to: CGPoint) {
x = 1 self.window.setFrameOrigin(to)
timer?.invalidate() }
timer = Timer(timeInterval: 0.01, repeats: true) { [weak self] _ in
guard let self = self else { return } func show() {
guard x < 1001 else { window.orderFront(nil)
timer?.invalidate() }
return
} func hide() {
self.window.setFrameOrigin(NSPoint(x: 1000-self.x, y: 1000-self.x)) window.orderOut(nil)
self.x += 1
}
RunLoop.current.add(timer!, forMode: .common)
} }
} }

View File

@@ -414,19 +414,6 @@
</items> </items>
<point key="canvasLocation" x="200" y="121"/> <point key="canvasLocation" x="200" y="121"/>
</menu> </menu>
<menu id="ONX-cK-IuT"> <userDefaultsController representsSharedInstance="YES" id="KLo-tU-Av3"/>
<items>
<menuItem title="Item 1" id="6WY-F1-Y6A">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Item 2" id="Vew-Im-EWB">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Item 3" id="dVu-3p-SKK">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items>
<point key="canvasLocation" x="-160" y="321"/>
</menu>
</objects> </objects>
</document> </document>

View File

@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="23727" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23727"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="DPPreferencesWindowController" customModule="DockPhobia" customModuleProvider="target">
<connections>
<outlet property="dockRadio" destination="SML-7D-HqD" id="4QO-vf-9ma"/>
<outlet property="mouseRadio" destination="xQV-F8-e5K" id="2cJ-W4-uYY"/>
<outlet property="quitbutton" destination="7DK-yJ-I42" id="fDP-cd-88f"/>
<outlet property="smallDeathzoneToggle" destination="TNA-PK-KGC" id="rTv-BF-hv6"/>
<outlet property="updateCheckButton" destination="bnA-Vz-L4F" id="16N-mV-Agw"/>
<outlet property="window" destination="85c-fa-xeM" id="B5X-4l-mcR"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="DockPhobia Preferences" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="85c-fa-xeM">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" texturedBackground="YES"/>
<rect key="contentRect" x="683" y="389" width="423" height="186"/>
<rect key="screenRect" x="0.0" y="0.0" width="1710" height="1069"/>
<view key="contentView" wantsLayer="YES" id="wEz-dE-A27">
<rect key="frame" x="0.0" y="0.0" width="423" height="186"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bnA-Vz-L4F">
<rect key="frame" x="13" y="8" width="159" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="push" title="Check for Updates..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="XBJ-UK-x73">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="checkUpdates:" target="-2" id="AX2-PR-jPb"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="SML-7D-HqD">
<rect key="frame" x="87" y="149" width="67" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES"/>
<buttonCell key="cell" type="radio" title="Dock" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="Lxi-8n-jY3">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="MoveTypeSelect:" target="-2" id="PP9-SC-6xN"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xQV-F8-e5K">
<rect key="frame" x="87" y="121" width="67" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES"/>
<buttonCell key="cell" type="radio" title="Mouse" bezelStyle="regularSquare" imagePosition="left" inset="2" id="86E-Km-LZ7">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="MoveTypeSelect:" target="-2" id="dfh-6B-58k"/>
</connections>
</button>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="U5P-YK-hTs">
<rect key="frame" x="18" y="150" width="60" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Move the" id="4wN-vE-QCE">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vyh-vP-oAh">
<rect key="frame" x="160" y="150" width="245" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="when the cursor gets close to the Dock." id="y3x-vy-qbu">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="TNA-PK-KGC">
<rect key="frame" x="18" y="81" width="216" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Smaller deathzone in fullscreen" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="28Y-O4-oAQ">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="smallDeathzoneToggle:" target="-2" id="zlu-Ca-p04"/>
</connections>
</button>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3Pd-Xt-fTA">
<rect key="frame" x="18" y="60" width="136" height="14"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="May reduce performance" id="Orh-5m-Me2">
<font key="font" metaFont="system" size="11"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7DK-yJ-I42">
<rect key="frame" x="343" y="14" width="60" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="roundRect" title="Quit" bezelStyle="roundedRect" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="jbc-01-FBx">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="quit:" target="-2" id="483-Pc-QoS"/>
</connections>
</button>
</subviews>
</view>
<toolbar key="toolbar" implicitIdentifier="3DBA283D-9272-4F9B-8799-AA8355F2BE79" autosavesConfiguration="NO" showsBaselineSeparator="NO" displayMode="iconAndLabel" sizeMode="regular" id="MWN-PM-U77">
<allowedToolbarItems/>
<defaultToolbarItems/>
</toolbar>
<contentBorderThickness minY="0.0" maxY="0.0"/>
<point key="canvasLocation" x="-213.5" y="-103"/>
</window>
<userDefaultsController representsSharedInstance="YES" id="zYZ-vc-iso"/>
</objects>
</document>

BIN
DockPhobiaPy/.DS_Store vendored
View File

Binary file not shown.

View File

@@ -1,9 +1,14 @@
# DockPhobia
<div align="center"> <div align="center">
<br/> <br/>
<p> <p>
<img src="https://github.com/neon443/DockPhobia/blob/main/DockPhobia/Resources/Assets.xcassets/AppIcon.appiconset/DockPhobiaAppIcon.png?raw=true" title="dockphobia" alt="dockphobia icon" width="200" /> <img src="https://github.com/neon443/DockPhobia/blob/main/DockPhobia/Resources/Assets.xcassets/AppIcon.appiconset/DockPhobiaAppIcon.png?raw=true" title="dockphobia" alt="dockphobia icon" width="100" />
</p>
<h3>DockPhobia</h3>
<p>
<a href="https://github.com/neon443/DockPhobia/releases/latest/download/DockPhobia.dmg">
download
<img alt="GitHub Release" src="https://img.shields.io/github/v/release/neon443/DockPhobia">
</a>
</p> </p>
<p> <p>
make your Dock scared of the mouse make your Dock scared of the mouse
@@ -12,14 +17,11 @@
made by neon443 made by neon443
</a> </a>
</p> </p>
<p>
<a href="https://github.com/neon443/DockPhobia/releases/latest/download/DockPhobia.dmg">
download
</a>
</p>
<br/> <br/>
</div> </div>
![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/neon443/DockPhobia/total)
Have you ever wanted to use your Dock? Have you ever wanted to use your Dock?
well now you cant well now you cant