AppleScriptで押されている修飾キーを得る
AppleScriptにてScript内で現在押されている修飾キー(またはその他のキー)を得るにはどうしたらよいでしょうか。
例えばオプションキーを押しながらScript起動で押していない時とは違う動作がしたい、とかですが検索してもどうも検索しきれません。
お知恵を拝借いたしたいです。
Mac mini 2012
OSX 10.9.4
Mac mini, OS X Mavericks (10.9.3), 2012
Apple の脅威の通知と金銭目当てのスパイウェアへの対策について
Apple の脅威の通知と金銭目当てのスパイウェアへの対策についてが公開されました。
Apple の脅威の通知と金銭目当てのスパイウェアへの対策についてが公開されました。
AppleScriptにてScript内で現在押されている修飾キー(またはその他のキー)を得るにはどうしたらよいでしょうか。
例えばオプションキーを押しながらScript起動で押していない時とは違う動作がしたい、とかですが検索してもどうも検索しきれません。
お知恵を拝借いたしたいです。
Mac mini 2012
OSX 10.9.4
Mac mini, OS X Mavericks (10.9.3), 2012
AppleScriptであれこれする
http://memogakisouko.appspot.com/AppleScript.html
リンク先の「修飾キーの状態を取得する。getModifierKeys」でできると思います。それと、ページの最初の方にある「Mavericks (10.9)での注意点」も併せてお読みください。
なお、このやり方は ruby 1.8 が必要なので、いつまで通用するか分かりません。できれば ASOC (AppleScript Objective-C) で書き直した方が良いと思います。当方未だに Snow Leopard 環境なので、ASOC は全く分かりませんが...。
ありがとうございます。
しかしながらリンク先の方法は試してみたのですが10.9からrubyが2.0になって2.0からは動作しません。
直接rubyを指定しても仕様変更でしょうかコマンドラインにエラーが出てできません。
なのでAppleScript内でできないかと思ってる次第ですが、難しいようですね。
直接rubyを指定しても仕様変更でしょうかコマンドラインにエラーが出てできません。
Mavericks には ruby 1.8.x も入ってます。それを指定してもダメなのでしょうか?
こんな感じでどうでしょうか。両方ともダメな場合はギブアップです。
Ruby 版
on run
my get_modifier_keys()
end run
on get_modifier_keys()
set ruby to "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby"
--
set code to "
require 'osx/cocoa'
include OSX
e = CGEventCreate(nil)
m = CGEventGetFlags(e)
print m, ' '
print 'shift ' if m & 1 << 17 != 0
print 'control ' if m & 1 << 18 != 0
print 'option ' if m & 1 << 19 != 0
print 'command ' if m & 1 << 20 != 0
"
--
do shell script ruby & " -e " & quoted form of code
end get_modifier_keys
Python 版 - Ruby 版を Python に翻訳したもの。とても遅いです。動けばの話ですが...。
on run
my get_modifier_keys()
end run
on get_modifier_keys()
set code to "
from Quartz.CoreGraphics import *
e = CGEventCreate(None)
m = CGEventGetFlags(e)
print m,
if m & 1 << 17 != 0: print 'shift',
if m & 1 << 18 != 0: print 'control',
if m & 1 << 19 != 0: print 'option',
if m & 1 << 20 != 0: print 'command',
"
do shell script "python -c " & quoted form of code
end get_modifier_keys
こんばんは、
Ruby 1.8 のフルパスを指定すれば良いはずです。
CGEvent を使うコード:
do shell script "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby -w <<'EOF'
require 'osx/cocoa'
include OSX
m = CGEventSourceFlagsState(KCGEventSourceStateHIDSystemState)
mods = {
KCGEventFlagMaskAlphaShift => 'capslock',
KCGEventFlagMaskShift => 'shift',
KCGEventFlagMaskControl => 'control',
KCGEventFlagMaskAlternate => 'option',
KCGEventFlagMaskCommand => 'command',
}
a = mods.keys.sort.inject([]) {|a, k| m & k !=0 ? a << mods[k] : a}
puts a.join(' ')
EOF"
NSEvent を使うコード:
do shell script "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby -w <<'EOF'
require 'osx/cocoa'
include OSX
m = NSEvent.modifierFlags
mods = {
NSAlphaShiftKeyMask => 'capslock',
NSShiftKeyMask => 'shift',
NSControlKeyMask => 'control',
NSAlternateKeyMask => 'option',
NSCommandKeyMask => 'command',
}
a = mods.keys.sort.inject([]) {|a, k| m & k !=0 ? a << mods[k] : a}
puts a.join(' ')
EOF"
追記
最後の EOF の前に空白文字があってはいけません。ここのボードのシステムは勝手に空白を加えているようなので、注意が必要です。やれやれ。
追記2
Syntax highlight を適用したブロックでは、行頭の空白は Firefox では追加されるが、Safari では追加されないようですね。
ただし、行末の空白は、いずれのブラウザでも追加されます。コードをポストするときは、やっかいですね。
Firefox 24.7.0esr, Safari 5.1.10, OSX 10.6.8.
脱線失礼。
行末の連続スペースが問題になる言語はないと思いスルーしてました。ただ、Firefox だと行頭が大変なことになりますね...。気づきませんでした。ありがとうございます。当面は昔の形式で書いた方が良いかもしれません。
chandana さんのスクリプト
do shell script "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby -w <<'EOF' require 'osx/cocoa' include OSX m = CGEventSourceFlagsState(KCGEventSourceStateHIDSystemState) mods = { KCGEventFlagMaskAlphaShift => 'capslock', KCGEventFlagMaskShift => 'shift', KCGEventFlagMaskControl => 'control', KCGEventFlagMaskAlternate => 'option', KCGEventFlagMaskCommand => 'command', } a = mods.keys.sort.inject([]) {|a, k| m & k !=0 ? a << mods[k] : a} puts a.join(' ') EOF"
あと、このボードでは NG ワードが「*」に置き換わります。NG ワードは公開されてないので、投稿後に確認する必要があります。
脱線ついでに。行末の空白も時には問題なのです。例えば、here-document の区切りの語に勝手に空白を付け足されると、区切りでなくなってしまい、コードが破綻します。
#!/bin/bash
/usr/bin/ruby <<'EOF'
puts 'hello'
EOF
EOF の後ろに空白がつくと、ruby の出力は、
hello
-:2: uninitialized constant EOF (NameError)
ということに、、、
技術的なサポートサイトなので、どうにかしてほしいですね。
ではでは。
> 行末の空白も時には問題なのです。
たしかにそのとおりですね。失礼しました。
ということで、フィードバックしておきました。
やっぱり素直にrubyを使ったほうが良いようですね。
if (option key is down)
みたいなことができないかと思ったのですがScript辞典にもないし検索してもないし、というところでした。
素直にrubyで解決したいと思います。
皆さまありがとうございました。
失礼致します。 Shane Stanleyさんの Everyday AppleScriptObjCを読んでいたら、Objective-CのNSEventクラスのmodiferFlagsメソッドを使った方法が紹介されていました(Chapter 24 Bits and Pieces)。 Yosemiteでの事例ですが、変数名を少しかえて、
use AppleScript version "2.4"
use framework "Foundation"
use framework "AppKit"
use scripting additions
on examineModifier:nameOfKey
if nameOfKey = "option" then
set keyMask to current application'sNSAlternateKeyMask as integer
else if nameOfKey = "control" then
set keyMask to current application'sNSControlKeyMask as integer
else if nameOfKey = "command" then
set keyMask to current application'sNSCommandKeyMask as integer
else if nameOfKey = "shift" then
set keyMask to current application'sNSShiftKeyMask as integer
else
return false
end if
set theFlag to current application'sNSEvent'smodifierFlags() as integer
return (((theFlag div keyMask) mod 2) = 1)
--return (theFlag is keyMask)
end examineModifier:
its examineModifier:"control"
となっていました。
theFlagとkeyMaskとの変数を比較して真偽を返すのですが、なぜ、return (theFlag is keyMask)ではなく、return (((theFlagdivkeyMask) mod 2) = 1)となっているのかは不明です。
T22T さんによる書き込み:
theFlagとkeyMaskとの変数を比較して真偽を返すのですが、なぜ、return (theFlag is keyMask)ではなく、return (((theFlagdivkeyMask) mod 2) = 1)となっているのかは不明です。
ASOC が使える環境がないので間違ってるかもしれませんが、return (theFlag is keyMask) だと、「command + shift」みたいにモディファイアキーを2つ以上押した際に期待どおりに動かないのではないのでしょうか。
いつも有難うございます。 なるほどです。 Modifier Flagsの定数を加算(積算?)?することで複数のキーが押されている状態を表現しているみたいですね。 一つの修飾キーを示す整数値で割った余りが0か、1かでそのキーが含まれるかどうかを判断できるということでしょうか。
AppleScript にはビット演算子がない?ので、このような書き方になるのでしょうね。
ところで、こんな感じでどうでしょうか?動作確認が出来ないのでダメでも修正できませんが...。
use AppleScript version "2.4" use framework "Foundation" use framework "AppKit" use scripting additions my func() # 結果 {"shift", "command"} on func() set m to current application's NSEvent's modifierFlags() as integer set mods to {¬ {65536, "capslock"}, {131072, "shift"}, {262144, "control"}, ¬ {524288, "option"}, {1048576, "command"} ¬ } set a to {} repeat with i in mods set {k, v} to i if (m div k) mod 2 = 1 then set end of a to v end repeat return a end func
で、ふと思ったのですが、JavaScript だとビット演算子や三項演算子等が使えるので、JXA ならもうちょっとシンプルに書けるような気がします。当方の環境では JXA も動かないので Safari の do javascript で書いたのが下記。m = 1179648 のところは Objective-C の助けを借りて値を取得するようにすれば良いと思います。(出来るかどうかも分かりませんが...)
var m, mods, a, k; m = 1179648; // ←ここを Objective-C でやる mods = { 65536 : 'capslock', 131072 : 'shift', 262144 : 'control', 524288 : 'option', 1048576 : 'command', }; a = []; for (k in mods) { m & k ? a.push(mods[k]) : false; } a.join(' ') // 結果: shift command
# なんか妄想日本料理のようになってしまいましたが、何かのお役に立てればと。
うまく動きました。 ビット演算子については、C言語をかじった時に名前だけは知っていたのですが、具体的にどういう場面で使うものなのかは理解していませんでした(勉強になりました)。
use AppleScript version "2.4"
use framework "Foundation"
use framework "AppKit"
use scripting additions
my func() # 結果 {"shift", "command"}
on func()
set m to current application'sNSEvent'smodifierFlags() as integer
logm
--> 1779648 = 131072:"shift" + 1048576:"command"
set mods to {¬
{65536, "capslock"}, {131072, "shift"}, {262144, "control"}, ¬
{524288, "option"}, {1048576, "command"} ¬
}
set a to {}
repeat with i in mods
set {k, v} to i
if (m div k) mod 2 = 1 then set end of a to v
log {m, k}
--> 1179648 div 65536:"capslock" mod 2 = 0
--> 1179648 div 131072:"shift" mod 2 = 1
--> 1179648 div 262144:"control" mod 2 = 0
--> 1179648 div 524288:"option" mod 2 = 0
--> 1179648 div 1048576:"command" mod 2 =1
end repeat
return a
--> {"shift", "command"}
end func
AppleScriptで押されている修飾キーを得る