2011年2月1日火曜日

MacRuby・Snatcher・タスクセレクタ(2)

NSWorkspaceのlaunchApplicationだと、例えばFinderを「起動」するとアクティブなウィンドウがない場合はHOMEを開いて表示する。期待する動作としてはメニューバーでFinderがアクティブになる、こと。

じゃあ一体どうすればいいか悩む。それ用のNotificationでもあるんだろうか。とりあえずデベロッパドキュメントで「Activate」とかを検索する。(力業ですな)

検索して出てきた項目の11番目(^^;)が「NSRunnnigApplicationのactivateWithOption」で、これがなんだかよさそうなのでNSRunnnigApplicationのドキュメントをよく読む。ほおほお、現在起動しているアプリそのものはNSWorkspace.runningApplicationsで取得せよ、と。そんなんでこう書いてみる。

ws=NSWorkspace.sharedWorkspace
    ra=ws.runningApplications
    puts ra[0].localizedName
表示されたのは「loginwindow」とかで首をひねる。

昨日書いたmenuに表示するメソッドを流用してこう書いた。

ws=NSWorkspace.sharedWorkspace
  ra=ws.runningApplications
  my_menu.removeAllItems
 
  ra.each do |app|
   
    app_name=app.localizedName
    image=app.icon
    image.setSize(NSMakeSize(32,32))
    item=NSMenuItem.alloc.init
    item.setTitle(app_name)
    item.setImage(image)    
    item.setTarget(self)
    item.setAction("select:")
    my_menu.addItem(item)
   
    
  end
実行してみたところ、こんなふうに表示される。

ふむ、とりあえず起動しているアプリが全部拾えるらしい。WarpDeamonとかEvernoteHelperとかのシステム環境設定パネルに表示されるのも全部。なるほど、プリファレンス関係のプログラムってHelperと名付けられることが多いのね。iconがNSImageの状態で取得できる分、こっちのほうが楽かもしれない。

それはともかくこれでは非実用的。
ドキュメントをあさったら、それぞれのアプリにはactivationPolicyというプロパティがあって、これには
NSApplicationActivationPolicyRegular,
NSApplicationActivationPolicyAccessory,
NSApplicationActivationPolicyProhibited

という3つの選択肢があるらしい。で、普通のGUIアプリがNSApplicationActivationPolicyRegular、他のはBackGraundOnlyだったりするアプリ用と。

そこでこう書きなおしたらうまくいった。
  ws=NSWorkspace.sharedWorkspace
  ra=ws.runningApplications
  my_menu.removeAllItems
 
  ra.each do |app|
   if app.activationPolicy==NSApplicationActivationPolicyRegular then
    app_name=app.localizedName
    image=app.icon
    image.setSize(NSMakeSize(32,32))
    item=NSMenuItem.alloc.init
    item.setTitle(app_name)
    item.setImage(image)
    item.setTarget(self)
    item.setAction("select:")
    my_menu.addItem(item)
   end
    
  end



よしよし。あとはメニューから選択されたアプリをactivateするだけなんだけど、一度menuにしてしまうと名前とiconしかアプリの情報が残らない。NSRunnnigApplicationのArrayをmenuのアクションにどうやって渡すか悩む。

結局、NSRunnnigApplicationのインスタンスはPIDかBundleNameからでも取得できるので、menuItemのtagにPIDを仕込むことにする。
item.setTag(app.processIdentifier)

こうやっておいた上でアクションをこうしてみた。ちなみにコメントは将来の自分用(^^;)。
 def select(sender)
  #sender.tag==RunApp.processIdentifier
  app=NSRunningApplication.runningApplicationWithProcessIdentifier(sender.tag)
  app.activateWithOptions(NSApplicationActivateIgnoringOtherApps)
 end


これで最初考えたとおり、タスクを選択すると「launch」ではなく「Activate」するので、Firefoxなら「多重起動できません」と文句をいわないし、Finderなら黙ってメニューバーに現れる。

xcatsan師匠なら「よし」と書くところですな。(^^;)

考えた通りのことを実現できるのは気持ちがいい。

0 件のコメント:

コメントを投稿