差分
[[Mac OS X]]においてアプリに何か発生したときに[[スクリーンセーバー]]を終了させたい。
==実装1==
===失敗1===
[[Xamarin.Mac/ディスプレイのスリープを解除する|ディスプレイのスリープを解除する方法]]では[[スクリーンセーバー]]は終了しない。
どちらも似たようなものだと思うのだが通用しないようである。
===失敗2===
そこで[[.NET Framework]]でおなじみのSystem.Diagnostics.Processを使い、[[スクリーンセーバー]]らしき[[プロセス]]が存在するか調べ、そのプロセスを終了させてみた。
だが、こちらもダメであった。
プロセスに対してCloseやKillを送信しても一瞬画面がブラックアウトするが、すぐさま[[Mac OS X]]がスクリーンセーバーを再起動してしまっているようだ。
===成功1===
そこでプロセスに対してCloseやKillを送信するのではなく、[[Xamarin.Mac/キーボードの入力をシミュレートする|キーボードを操作した風を装ってみた]]。
[[キーコード]]の送信には影響が少なさそうな「左矢印キー」を使った。
これは上手くいった。
しかし、この[[Xamarin.Mac/キーボードの入力をシミュレートする|キーボードの入力をシミュレートする方法]]では、スクリーンセーバーは終了するが、[[Xamarin.Mac/ディスプレイのスリープを解除する|ディスプレイのスリープを解除する]]ことはできなかった。両方が同時に走っている場合も多く、基本的には組み合わせて利用する必要がありそうだ。
<source lang="csharp">
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);
}
}
}
}
</source>
==関連項目==
*[[Xamarin.Mac/ディスプレイのスリープを解除する]]
*[[Xamarin.Mac/キーボードの入力をシミュレートする]]
==参考文献==
{{reflist}}
{{stub}}
[[category: Xamarin.Mac]]
==実装1==
===失敗1===
[[Xamarin.Mac/ディスプレイのスリープを解除する|ディスプレイのスリープを解除する方法]]では[[スクリーンセーバー]]は終了しない。
どちらも似たようなものだと思うのだが通用しないようである。
===失敗2===
そこで[[.NET Framework]]でおなじみのSystem.Diagnostics.Processを使い、[[スクリーンセーバー]]らしき[[プロセス]]が存在するか調べ、そのプロセスを終了させてみた。
だが、こちらもダメであった。
プロセスに対してCloseやKillを送信しても一瞬画面がブラックアウトするが、すぐさま[[Mac OS X]]がスクリーンセーバーを再起動してしまっているようだ。
===成功1===
そこでプロセスに対してCloseやKillを送信するのではなく、[[Xamarin.Mac/キーボードの入力をシミュレートする|キーボードを操作した風を装ってみた]]。
[[キーコード]]の送信には影響が少なさそうな「左矢印キー」を使った。
これは上手くいった。
しかし、この[[Xamarin.Mac/キーボードの入力をシミュレートする|キーボードの入力をシミュレートする方法]]では、スクリーンセーバーは終了するが、[[Xamarin.Mac/ディスプレイのスリープを解除する|ディスプレイのスリープを解除する]]ことはできなかった。両方が同時に走っている場合も多く、基本的には組み合わせて利用する必要がありそうだ。
<source lang="csharp">
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);
}
}
}
}
</source>
==関連項目==
*[[Xamarin.Mac/ディスプレイのスリープを解除する]]
*[[Xamarin.Mac/キーボードの入力をシミュレートする]]
==参考文献==
{{reflist}}
{{stub}}
[[category: Xamarin.Mac]]