Xamarin.MacでGlobal Event Monitorを使いキー入力を監視する

提供: MonoBook
2015年10月14日 (水) 06:24時点における153.220.4.222 (トーク)による版 (→‎アプリを開発する)
ナビゲーションに移動 検索に移動

概要

Xamarin.Macで開発している社内アプリで確実に動くファンクションキーを実現したい。

何も考えずに単純にキー入力を監視する実装にしたところ、一部で「キーを押しても動かない」という苦情が発生した。 原因は、ウインドウはひとつしか開いておらず、一見するとウインドウにフォーカスが当たっているように見えるが、実はデスクトップにフォーカスが当たっているという状況であった。 対策として、アプリ起動時に強制的にフルスクリーンにしてやろうかとも思ったがWindows 8並にスマートではないので、そのような状況でも動くファンクションキーの実装方法を模索している。

実装

アプリを開発する

NSEventにNSEvent.AddGlobalMonitorForEventsMatchingMaskを叩いて監視対象のイベントの種類と発生時に呼ばれるイベントハンドラを設定するだけである。 非常に簡単。

当初はNSEventMask.KeyDownで実装してみたが、これは文字キーの入力でしかイベントが発生せず、ShiftキーCtrlキーなどを単品で押した場合には何も起こらない。 実装中のアプリではCtrlキー単品をショートカットキーとしており上記ではダメであった。 そこでNSEventMask.FlagsChangedに変えて実装してみたところCtrlキー単品でも上手くいった。

        public override void DidFinishLaunching(NSNotification notification)
        {
            NSEvent.AddGlobalMonitorForEventsMatchingMask(NSEventMask.KeyDown, (theEvent) => {
                
                Console.WriteLine("keydown: " + theEvent.Characters);
            });

            NSEvent.AddGlobalMonitorForEventsMatchingMask(NSEventMask.FlagsChanged, (theEvent) => {
                var flags = theEvent.ModifierFlags & NSEventModifierMask.DeviceIndependentModifierFlagsMask;
                if (flags == 0)
                {
                    Console.WriteLine("release");
                }
                else
                {
                    Console.WriteLine("modifier: " + flags);
                }
             });
        }

アプリを許可する

Global Event MonitorはOSのあらゆるイベントを監視できるのでスパイウェアキーロガーなどの非常に危ういアプリも簡単に作り放題となる。 そのためMac OS Xではシステム環境設定から明示的にアプリを許可しないとGlobal Event Monitorは機能しないようになっている。

  1. 左上のリンゴマークをクリック
  2. システム環境設定を開く
  3. セキュリティとプライバシーを開く
  4. プライバシーのタブを開く
  5. アクセシビリティを選ぶ
  6. 左下の鍵マークをクリックして認証する
  7. 中央のプラスマークをクリックして許可するアプリを追加する

なお、アクセシビリティの許可がされていない状態でGlobal Event Monitorを使用しているアプリを実行してもエラーも何も発生しない。 この挙動は確実に半年くらいしてどんな実装だったかを忘れたころにトラブルになり、エラーも出ないのでデバッグも捗らず原因不明のバグに悩まされデスマーチ突入は決定的である。 そのためアプリ起動時にアクセシビリティの許可がされているかを確認し警告を出す方法を模索しているが、まだ解決方法は見つかっていない。

関連項目

参考文献