Apple の脅威の通知と金銭目当てのスパイウェアへの対策について

しばらく返答が寄せられていないようです。 再度ディスカッションを開始するには、新たに質問してください。

AppleScriptで押されている修飾キーを得る

AppleScriptにてScript内で現在押されている修飾キー(またはその他のキー)を得るにはどうしたらよいでしょうか。

例えばオプションキーを押しながらScript起動で押していない時とは違う動作がしたい、とかですが検索してもどうも検索しきれません。

お知恵を拝借いたしたいです。


Mac mini 2012

OSX 10.9.4

Mac mini, OS X Mavericks (10.9.3), 2012

投稿日 2014/08/18 18:53

返信
返信: 17

2014/08/18 19:13 urichin への返信

AppleScriptであれこれする

http://memogakisouko.appspot.com/AppleScript.html


リンク先の「修飾キーの状態を取得する。getModifierKeys」でできると思います。それと、ページの最初の方にある「Mavericks (10.9)での注意点」も併せてお読みください。


なお、このやり方は ruby 1.8 が必要なので、いつまで通用するか分かりません。できれば ASOC (AppleScript Objective-C) で書き直した方が良いと思います。当方未だに Snow Leopard 環境なので、ASOC は全く分かりませんが...。

2014/08/18 21:08 Hiro__S への返信

ありがとうございます。

しかしながらリンク先の方法は試してみたのですが10.9からrubyが2.0になって2.0からは動作しません。

直接rubyを指定しても仕様変更でしょうかコマンドラインにエラーが出てできません。

なのでAppleScript内でできないかと思ってる次第ですが、難しいようですね。

2014/08/18 21:46 urichin への返信

こんな感じでどうでしょうか。両方ともダメな場合はギブアップです。


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

2014/08/18 22:03 urichin への返信

こんばんは、


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"

2014/08/18 22:25 chandana への返信

追記


最後の EOF の前に空白文字があってはいけません。ここのボードのシステムは勝手に空白を加えているようなので、注意が必要です。やれやれ。



追記2


Syntax highlight を適用したブロックでは、行頭の空白は Firefox では追加されるが、Safari では追加されないようですね。

ただし、行末の空白は、いずれのブラウザでも追加されます。コードをポストするときは、やっかいですね。


Firefox 24.7.0esr, Safari 5.1.10, OSX 10.6.8.

2014/08/18 23:09 chandana への返信

脱線失礼。


行末の連続スペースが問題になる言語はないと思いスルーしてました。ただ、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 ワードは公開されてないので、投稿後に確認する必要があります。

2014/08/18 23:55 Hiro__S への返信

脱線ついでに。行末の空白も時には問題なのです。例えば、here-document の区切りの語に勝手に空白を付け足されると、区切りでなくなってしまい、コードが破綻します。



#!/bin/bash

/usr/bin/ruby <<'EOF'
puts 'hello'
EOF



EOF の後ろに空白がつくと、ruby の出力は、


hello

-:2: uninitialized constant EOF (NameError)


ということに、、、


技術的なサポートサイトなので、どうにかしてほしいですね。


ではでは。

2014/08/19 04:32 Hiro__S への返信

やっぱり素直にrubyを使ったほうが良いようですね。

if (option key is down)

みたいなことができないかと思ったのですがScript辞典にもないし検索してもないし、というところでした。

素直にrubyで解決したいと思います。

皆さまありがとうございました。

2015/02/25 19:06 urichin への返信

失礼致します。 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)となっているのかは不明です。

2015/02/25 21:40 T22T への返信

T22T さんによる書き込み:


theFlagとkeyMaskとの変数を比較して真偽を返すのですが、なぜ、return (theFlag is keyMask)ではなく、return (((theFlagdivkeyMask) mod 2) = 1)となっているのかは不明です。


ASOC が使える環境がないので間違ってるかもしれませんが、return (theFlag is keyMask) だと、「command + shift」みたいにモディファイアキーを2つ以上押した際に期待どおりに動かないのではないのでしょうか。

2015/02/25 21:59 Hiro__S への返信

いつも有難うございます。 なるほどです。 Modifier Flagsの定数を加算(積算?)?することで複数のキーが押されている状態を表現しているみたいですね。 一つの修飾キーを示す整数値で割った余りが0か、1かでそのキーが含まれるかどうかを判断できるということでしょうか。 

2015/02/26 20:11 T22T への返信

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


# なんか妄想日本料理のようになってしまいましたが、何かのお役に立てればと。

2015/02/27 12:14 Hiro__S への返信

うまく動きました。 ビット演算子については、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で押されている修飾キーを得る

Apple サポートコミュニティへようこそ
Apple ユーザ同士でお使いの製品について助け合うフォーラムです。Apple ID を使ってご参加ください。