Skip to content

Commit

Permalink
Merge pull request #1 from zsmb13/custom-folder
Browse files Browse the repository at this point in the history
Custom folder
  • Loading branch information
zsmb13 committed May 19, 2024
2 parents e9a346a + 19a83ab commit 5a84752
Show file tree
Hide file tree
Showing 19 changed files with 341 additions and 83 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.gradle
.kotlin
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
Expand Down
16 changes: 12 additions & 4 deletions KotlinLogos/KotlinLogos.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
Expand Down Expand Up @@ -261,7 +261,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
Expand All @@ -282,17 +282,21 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)";
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
INFOPLIST_KEY_NSPrincipalClass = KotlinLogosView;
INSTALL_PATH = "$(HOME)/Library/Screen Savers";
MARKETING_VERSION = 0.4;
MARKETING_VERSION = 0.5;
PRODUCT_BUNDLE_IDENTIFIER = co.zsmb.KotlinLogos;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
Expand All @@ -304,17 +308,21 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)";
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
INFOPLIST_KEY_NSPrincipalClass = KotlinLogosView;
INSTALL_PATH = "$(HOME)/Library/Screen Savers";
MARKETING_VERSION = 0.4;
MARKETING_VERSION = 0.5;
PRODUCT_BUNDLE_IDENTIFIER = co.zsmb.KotlinLogos;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
WRAPPER_EXTENSION = saver;
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,22 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
useCustomWorkingDirectory = "YES"
customWorkingDirectory = "/Users/zsmb/StudioProjects/KotlinLogo-ScreenSaver"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "EBBEE0B82ABDC9B80008AEF8"
BuildableName = "KotlinLogos.saver"
BlueprintName = "KotlinLogos"
ReferencedContainer = "container:KotlinLogos.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,22 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
useCustomWorkingDirectory = "YES"
customWorkingDirectory = "/Users/zsmb/StudioProjects/KotlinLogo-ScreenSaver"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "EBBEE0B82ABDC9B80008AEF8"
BuildableName = "KotlinLogos.saver"
BlueprintName = "KotlinLogos"
ReferencedContainer = "container:KotlinLogos.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ Available image sets:
* Kotlin logos
* Kodee

You can also browse for your own folder of images.

> Note: Use a folder with accessible permissions, for example, create a `~/screensaver-images` folder, and place your images there. The screen saver looks for PNG and SVG images in the custom folder. Folders located in places like your Downloads folder will likely show their images in the preview, but not work with the actual screen saver. If this happens, try to place the folder in a different location.
## Read the blog post

The journey and technical details of creating this screen saver is documented in [Building a macOS screen saver in Kotlin on zsmb.co](https://zsmb.co/building-a-macos-screen-saver-in-kotlin/).
Expand Down
14 changes: 3 additions & 11 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework

plugins {
kotlin("multiplatform") version "1.9.10"
kotlin("multiplatform") version "2.0.0-RC3"
}

repositories {
Expand All @@ -22,16 +22,8 @@ kotlin {
}

sourceSets {
val nativeMain by creating {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
}
}
val macosX64Main by getting {
dependsOn(nativeMain)
}
val macosArm64Main by getting {
dependsOn(nativeMain)
macosMain.dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions src/nativeMain/kotlin/BouncingLogo.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import config.Preferences
import imagesets.ImageSet
import kotlinx.cinterop.ExperimentalForeignApi
import platform.AppKit.NSImage
import platform.AppKit.NSImageScaleProportionallyUpOrDown
Expand All @@ -10,7 +11,7 @@ import kotlin.random.Random
@OptIn(ExperimentalForeignApi::class)
class BouncingLogo(
private val view: ScreenSaverView,
private val images: List<String>,
private val imageSet: ImageSet,
private val specs: ScreenSpecs,
private val imageLoader: ImageLoader,
) {
Expand Down Expand Up @@ -39,7 +40,7 @@ class BouncingLogo(
private val top: Double get() = yPos + logoHeight / 2
private val bottom: Double get() = yPos - logoHeight / 2

private var index = Random.nextInt(images.size)
private var index = Random.nextInt(imageSet.size)

private val imageView = NSImageView().apply {
imageScaling = NSImageScaleProportionallyUpOrDown
Expand All @@ -65,7 +66,7 @@ class BouncingLogo(
}

private fun bounce(side: Side) {
index = (index + 1) % images.size
index = (index + 1) % imageSet.size
imageView.image = updateImage()

when (side) {
Expand All @@ -92,7 +93,7 @@ class BouncingLogo(
}

private fun updateImage(): NSImage {
val (image, w, h) = imageLoader.loadImage(images[index])
val (image, w, h) = imageLoader.loadImage(imageSet, index)
logoWidth = w
logoHeight = h
return image
Expand Down
11 changes: 6 additions & 5 deletions src/nativeMain/kotlin/ImageLoader.kt
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
import config.Preferences
import imagesets.ImageSet
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.useContents
import platform.AppKit.imageForResource
import platform.Foundation.NSBundle
import util.debugLog
import kotlin.math.pow
import kotlin.math.sqrt

@OptIn(ExperimentalForeignApi::class)
class ImageLoader(
private val specs: ScreenSpecs,
private val bundle: NSBundle,
private val imageCache: MutableMap<String, ImageWithDimensions> = mutableMapOf(),
) {
/**
* Calculates logo width and heigh amounts so that their ratio matches
* the image ratio and their total area is LOGO_AREA.
*/
fun loadImage(key: String): ImageWithDimensions = imageCache.getOrPut(
key = key,
fun loadImage(imageSet: ImageSet, index: Int): ImageWithDimensions = imageCache.getOrPut(
key = imageSet.images[index],
defaultValue = {
val img = bundle.imageForResource(key)!!
val img = imageSet.load(imageSet.images[index])
debugLog { "Loaded $index from $imageSet: $img"}

val (w, h) = img.size.useContents { width to height }
val area = (Preferences.LOGO_SIZE.toDouble() * specs.pxScale).pow(2)
Expand Down
24 changes: 0 additions & 24 deletions src/nativeMain/kotlin/ImageSets.kt

This file was deleted.

3 changes: 2 additions & 1 deletion src/nativeMain/kotlin/KotlinScreenSaverView.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import config.Preferences.APP_ID
import platform.AppKit.NSWindow
import platform.Foundation.NSBundle
import platform.ScreenSaver.ScreenSaverView
Expand All @@ -19,7 +20,7 @@ abstract class KotlinScreenSaverView {

open fun init(screenSaverView: ScreenSaverView, isPreview: Boolean) {
this.view = screenSaverView
this.bundle = NSBundle.bundleWithIdentifier("co.zsmb.KotlinLogos")!!
this.bundle = NSBundle.bundleWithIdentifier(APP_ID)!!
this.isPreview = isPreview
}

Expand Down
5 changes: 3 additions & 2 deletions src/nativeMain/kotlin/LogoScreenSaverView.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import config.KotlinLogosPrefController
import config.Preferences
import imagesets.imageSets
import platform.AppKit.NSWindow
import platform.Foundation.NSNotificationCenter
import platform.Foundation.NSUserDefaultsDidChangeNotification
Expand Down Expand Up @@ -31,11 +32,11 @@ class LogoScreenSaverView : KotlinScreenSaverView() {
logos.forEach(BouncingLogo::dispose)

val specs = ScreenSpecs(view)
val imageLoader = ImageLoader(specs, bundle)
val imageLoader = ImageLoader(specs)
logos = List(Preferences.LOGO_COUNT) {
BouncingLogo(
view = view,
images = imageSets[Preferences.LOGO_SET].images(),
imageSet = imageSets[Preferences.LOGO_SET],
specs = specs,
imageLoader = imageLoader,
)
Expand Down
Loading

0 comments on commit 5a84752

Please sign in to comment.