CahtGPTを使ってMacのネイティブアプリを作ってみよう〜その1〜

プログラミング

お久しぶりです。アユザックです。

ゲームのためにWindowsのデスクトップPCを利用していたのですが、最近ゲームをやるのが辛くなってきたので、物理的にできないようにするためにMacBookAirに変えました。(こうでもしないと、面白くないのにたまに惰性でやっちゃうんです。)
私の中ではWindowsとMacの多いな違いはフリーソフトの種類だと思ってます。Windowsでは簡単に手に入ったソフトがMacにはなかったりします。

目次

Macにして困ったこと

私の務める会社では、在宅勤務が認められており、多い週だと週4で在宅勤務をしています。在宅勤務時は自宅のPCを利用する所謂BYODで会社の用意したWindowsシンクラで仕事をします。

少し離席してしまうと、ログアウトされてしまうという仕様のため、Windowsを利用していた際は低規定に画面をクリックしてくれるフリーツールを利用していました。というのも、ログアウトされてしまうと、サイトログイン、スマホでの認証・・・となかなかめんどくさいんですよね。

Macでも似たようなツールがあるだろうと思って探してみたのですが、無償のものは見つかりませんでした。Windowsなら無償でも速攻で2〜3個くらい見つかるのに・・・。

定期的にクリックするツールがほしい

在宅勤務中に仕事をさぼ・・・離席しても大丈夫なように定期的に画面をクリックするツールがほしいです。今まで無料でできていたことにお金を払うのは気が引けるので自分で作成してみることにしました。

Automatorで作ってみる

Macでは最初から定型処理を実施できるツールが入っているということなので、実際に試してみました。

操作を記録で、シンクラの画面をクリックし、その後はループで◯◯分後に停止するというフローで作ってみました。結論、期待動作はできるのですが、自分の好きな時間で停止できないというのがダメでした。(定期的にクリックするので、停止のためにカーソルを動かしているうちに変なとこクリックしてほしくないので・・・)Automatorを強制終了させるコマンドがあれば、ループの◯◯分を長い時間にして、戻ったらAutomatorをコマンドから強制終了すれば可能なのかもしれませんが、ぱっと調べて強制終了方法が見つからなかったので別の手段を探します。

Macのネイティブアプリを作ってみる

Xcodeでネイティブアプリが作れるのでこちらで作ってみます。言語はどれもよくわからないので、デフォルトで選択されていたSwiftUIというものを使ってみます。何から手を付けて良いかもわからないので、作ってほしいアプリの内容をChatGPTに投げてみました。投げかけた文言は「swiftUIで1分ごとにクリックするコードを書いてください。」です。

import SwiftUI

struct ContentView: View {
@State private var counter = 0
@State private var timer: Timer?

var body: some View {
VStack {
Text(“Counter: \(counter)”)
.font(.largeTitle)
.padding()

Button(action: {
self.buttonClicked()
}) {
Text(“Click Me”)
.font(.title)
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
.onAppear {
startTimer()
}
.onDisappear {
stopTimer()
}
}

func buttonClicked() {
counter += 1
}

func startTimer() {
timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) { _ in
self.buttonClicked()
}
}

func stopTimer() {
timer?.invalidate()
timer = nil
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

それっぽいものを作ってくれたので、早速Xcodeに貼り付けて動作を確認してみます。ただ、テスト的なことをしたいのに60秒では長すぎるので、値を5秒くらいに変えて実施してみます。UI上のクリック数は定期的に増えていくのでクリックできているように見えますが、他ウィンドウにカーソルを持っていっても、他ウィンドウがアクティブにならないので思ってたのと違います。

そんなわけで続けて次のようにお願いしてみました。「クリック時にカーソル位置のものがアクティブになるようにしてください。」色々と注意書きや説明がありますが、コードとしてはこんなのを提案してくれました。

import SwiftUI
import Cocoa

struct ContentView: View {
@State private var counter = 0
@State private var timer: Timer?

var body: some View {
VStack {
Text(“Counter: \(counter)”)
.font(.largeTitle)
.padding()

Button(action: {
self.buttonClicked()
}) {
Text(“Click Me”)
.font(.title)
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
.onAppear {
startTimer()
}
.onDisappear {
stopTimer()
}
}

func buttonClicked() {
counter += 1
simulateMouseClick()
}

func startTimer() {
timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) { _ in
self.buttonClicked()
}
}

func stopTimer() {
timer?.invalidate()
timer = nil
}

func simulateMouseClick() {
let loc = NSEvent.mouseLocation
let clickEvent = CGEvent(mouseEventSource: nil, mouseType: .leftMouseDown, mouseCursorPosition: loc, mouseButton: .left)
clickEvent?.post(tap: .cghidEventTap)

let releaseEvent = CGEvent(mouseEventSource: nil, mouseType: .leftMouseUp, mouseCursorPosition: loc, mouseButton: .left)
releaseEvent?.post(tap: .cghidEventTap)
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

どうやらCocoaというフレームワークを使うようです。もちろん私はそれが何かはよくわかりません。よくわかりませんが、これをそのままXcodeに貼って動作を確認してみますが、結果は変わらず。そんなわけでまた聞いてみます。「クリック自体はされているみたいですが、マウスカーソルが指している位置のアイテムがアクティブになることはありません」

すると・・・。権限の確認をしてほしいと出てきたので、指示されたとおりに権限を見てみると、たしかに作成したアプリにはアクセシビリティでコンピュータ制御を許可されていない状態でした。(ダイアログは出ていたみたいですが、裏側に隠れていて見てませんでした。)これを許可したところ、無事にやりたいことができるようになりました!

アプリ化については、また次に・・・。