「Xamarin.Mac/スクリーンセーバーを終了させる」の版間の差分
ナビゲーションに移動
検索に移動
(相違点なし)
|
2015年7月3日 (金) 07:30時点における版
Mac OS Xにおいてアプリに何か発生したときにスクリーンセーバーを終了させたい。
実装1
失敗1
ディスプレイのスリープを解除する方法ではスクリーンセーバーは終了しない。 どちらも似たようなものだと思うのだが通用しないようである。
失敗2
そこで.NET FrameworkでおなじみのSystem.Diagnostics.Processを使い、スクリーンセーバーらしきプロセスが存在するか調べ、そのプロセスを終了させてみた。 だが、こちらもダメであった。 プロセスに対してCloseやKillを送信しても一瞬画面がブラックアウトするが、すぐさまMac OS Xがスクリーンセーバーを再起動してしまっているようだ。
成功1
そこでプロセスに対してCloseやKillを送信するのではなく、キーボードを操作した風を装ってみた。 キーコードの送信には影響が少なさそうな「左矢印キー」を使った。 これは上手くいった。
しかし、このキーボードの入力をシミュレートする方法では、スクリーンセーバーは終了するが、ディスプレイのスリープを解除することはできなかった。両方が同時に走っている場合も多く、基本的には組み合わせて利用する必要がありそうだ。
using System;
using AppKit;
using CoreGraphics;
namespace LeaveScreenSaver
{
static class MainClass
{
static void Main(string[] args)
{
NSApplication.Init();
// デバッグ用のウエイト
for (int wait = 10; 0 < wait; wait--)
{
System.Threading.Thread.Sleep(1000);
Console.WriteLine(wait);
}
// ScreenSaverらしきプロセスを取得する。
// Xamarin.MacではProcessNameが最大15文字に切り詰められるようだ。
// そのため「ScreenSaverEngi」となっている。
var ps = System.Diagnostics.Process.GetProcessesByName("ScreenSaverEngi");
// ScreenSaverらしきプロセスがあればキーボードを操作した風を装って終了させる。
if (0 < ps.Length)
{
// キーボードの「←キー」を送信
PostKeyWithModifiers(123);
}
}
static void PostKeyWithModifiers(ushort keycode, CGEventFlags modifiers = 0)
{
using (var source = new CGEventSource(CGEventSourceStateID.CombinedSession))
using (var keydown = new CGEvent(source, keycode, keyDown: true))
using (var keyup = new CGEvent(source, keycode, keyDown: false))
{
keydown.Flags = modifiers;
// 送信
CGEvent.Post(keydown, CGEventTapLocation.AnnotatedSession);
CGEvent.Post(keyup , CGEventTapLocation.AnnotatedSession);
}
}
}
}