叩いてSpacesの画面が切り替わる
タイトル通り叩いてSpacesの画面を切り替わるツールを作ろうとして止まってます。Obj-CからAppleScriptを呼び出そうとしてるのですが、上手くサブルーチンが呼び出せない・・・無理なのかなぁ・・・
以下はObj-Cのソースと、AppleScriptのソース
myApplication.h
// // myApplication.h // touchLeopard // // Created by 安井 惇 on 08/02/04. // Copyright 2008 __MyCompanyName__. All rights reserved. // #import <Cocoa/Cocoa.h> #import <Foundation/Foundation.h> #import "smsutils.h" #define myApplicationTouchLeopardName @"touchLeopard" // AppleScriptのファイル名 typedef enum { myAppNone = -1, myAppUp = 0, myAppDown, myAppRight, myAppLeft } myApplicationArrowType; @interface myApplication : NSWindow { sms_data_t dataSave; int x_stable; int y_stable; NSTimer* th; NSAppleScript* myAppScript; IBOutlet NSButton *arrowUpButton; IBOutlet NSButton *arrowDownButton; IBOutlet NSButton *arrowLeftButton; IBOutlet NSButton *arrowRightButton; } -(IBOutlet) checkButton:(id)sender; -(IBOutlet) arrowKeyDown:(id)sender; - (NSAppleScript*) getAppleScriptWithFileName:(NSString*)name; @end
myApplication.m
// // myApplication.m // touchLeopard // // Created by 安井 惇 on 08/02/04. // Copyright 2008 __MyCompanyName__. All rights reserved. // // ex, http://developer.apple.com/jp/technotes/tn2006/tn2084.html // フェード・イン、フェードアウトアニメーション(2):setNeedsDisplay in // http://homepage.mac.com/mkino2/backnumber/2001_01.html #import "myApplication.h" static sms_data_t SMSDATAT_ZERO () { static sms_data_t d; d.x = 0; d.y = 0; d.z = 0; return d; } @implementation myApplication - (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)windowStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation { self = [super initWithContentRect:contentRect styleMask:windowStyle backing:bufferingType defer:deferCreation]; if (self != nil) { th = nil; dataSave = SMSDATAT_ZERO(); x_stable = 0; y_stable = 0; } return self; } - (void) dealloc { [super dealloc]; } // AppleScriptを得るメソッド - (NSAppleScript*) getAppleScriptWithFileName:(NSString*)name { NSAppleScript *script = nil; NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"scpt" inDirectory:@"Scripts"]; if (path != nil) { NSURL *url = [NSURL fileURLWithPath:path]; if (url != nil) { NSDictionary* error = [NSDictionary dictionary]; script = [[NSAppleScript alloc] initWithContentsOfURL:url error:&error]; if (script == nil) { NSLog(@"%@",error); } } } else { NSLog(@"getAppleScriptWithFileName: error file is nto found %@.scpt",name); } NSLog(@"getAppleScriptWithFileName:return: %@", script); return script; } // AppleScriptを実行させる - (void) runningAppleScriptArrowParam:(myApplicationArrowType) type { NSAppleScript *script = [self getAppleScriptWithFileName:myApplicationTouchLeopardName]; if (script == nil) return; // 第1パラメータを作成する NSString *param = nil; switch(type) { case myAppUp: param = @"Up"; break; case myAppDown: param = @"Down"; break; case myAppRight: param = @"Right"; break; case myAppLeft: param = @"Left"; break; default: return ; } NSLog(@"runningAppleScriptArrowParam:param => %@", param); NSAppleEventDescriptor* firstParameter = [NSAppleEventDescriptor descriptorWithString:param]; // パラメータのリストを作成し値を設定する NSAppleEventDescriptor* parameters = [NSAppleEventDescriptor listDescriptor]; [parameters insertDescriptor:firstParameter atIndex:1]; // AppleEventターゲットを作成する ProcessSerialNumber psn = {0, kCurrentProcess}; NSAppleEventDescriptor* target = [NSAppleEventDescriptor descriptorWithDescriptorType:typeProcessSerialNumber bytes:&psn length:sizeof(ProcessSerialNumber)]; // スクリプトの呼び出しメソッド名を使用してNSAppleEventDescriptorを作成する、 // これはスクリプトステートメント「on show_message(user_message)」に使用する // ルーチン名は小文字にする必要がある。 NSAppleEventDescriptor* handler = [NSAppleEventDescriptor descriptorWithString:[@"switchscreen" lowercaseString]]; // AppleScriptサブルーチンのイベントを作成する、 // メソッド名とパラメータリストを設定する // ここら辺の引数は適当に近い。-1708エラーはここが原因だと思われる // eventClassの参考 // http://developer.apple.com/documentation/Carbon/Reference/Apple_Event_Manager/Reference/reference.html#//apple_ref/doc/c_ref/AEEventClass // eventIdの参考 // http://developer.apple.com/documentation/Carbon/Reference/Apple_Event_Manager/Reference/reference.html#//apple_ref/doc/c_ref/AEEventID // forKeywordの参考 // http://developer.apple.com/documentation/Carbon/Reference/Apple_Event_Manager/Reference/reference.html#//apple_ref/doc/constant_group/Keyword_Parameter_Constants NSAppleEventDescriptor* event = [NSAppleEventDescriptor appleEventWithEventClass:kAECoreSuite eventID:kAEGetData targetDescriptor:target returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID]; [event setParamDescriptor:handler forKeyword:keySelectProc]; [event setParamDescriptor:parameters forKeyword:keyDirectObject]; // AppleScriptを起動 NSDictionary* errors = [NSDictionary dictionary]; if (![script executeAppleEvent:event error:&errors]) { NSLog(@"Error: %@",errors); } [script release]; } /* ======================================================================== */ // open a device and get sms data. + (sms_data_t) getSMSData { sms_data_t data = SMSDATAT_ZERO(); sms_t sms; if (smsOpen(&sms)) { NSLog(@"SMS Open Error"); return data; } /* Get the data from SMS Device. */ if (!smsGetData(&sms, &data)) { data.x *= sms.unit; data.y *= sms.unit; data.z *= sms.unit; } /* close to device */ smsClose(&sms); return data; } // 検知器から、移動幅を取り出し、スクリプトを動かす - (void) runningSMS { // open a device and get data sms_data_t d = [self->isa getSMSData]; // 補正処理 if (d.x < 0) d.x += 256; if (d.y < 0) d.y += 256; if (abs(d.x) < 20) x_stable++; if (abs(d.y) < 20) y_stable++; // 判別処理 // 横揺れの幅と、縦揺れの幅を比べて判断 myApplicationArrowType type = myAppNone; if (abs(d.x) > abs(d.y)) { if (abs(d.x) > 30 && x_stable > 30) { x_stable = 0; // d.x が 0より小さい時は左、大きい時は右 type = (d.x <= 0) ? myAppLeft : myAppRight; } } else { if (abs(d.y) > 30 && y_stable > 30) { y_stable = 0; // d.x が 0より小さい時は下、大きい時は上 type = (d.y <= 0) ? myAppDown : myAppUp; } } [self runningAppleScriptArrowParam:type]; } -(IBOutlet) checkButton:(id)sender { if ([(NSButton*)sender state] == NSOnState) { th = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(runningSMS) userInfo:nil repeats:YES]; } else { [th invalidate]; } } -(IBOutlet) arrowKeyDown:(id)sender { myApplicationArrowType type = myAppNone; if (sender == arrowUpButton) { type = myAppUp; } else if (sender == arrowDownButton) { type = myAppDown; } else if (sender == arrowLeftButton) { type = myAppLeft; } else if (sender == arrowRightButton) { type = myAppRight; } NSLog(@"arrowKeyDown => %d", type); [self runningAppleScriptArrowParam:type]; } @end
以下がAppleScript
-- touchLeopard.applescript -- touchLeopard -- Created by ?? ? on 08/02/04. -- Copyright 2008 __MyCompanyName__. All rights reserved. -- $Id: touchLeopard.applescript 64 2008-02-04 15:52:54Z yasui $ -- -- ex, http://idlysphere.blog66.fc2.com/?tag=Spaces on gui_scripting_check() tell application "System Events" to set gui_scripting_enabled to UI elements enabled if not gui_scripting_enabled then tell application "System Preferences" activate set current pane to pane "com.apple.preference.universalaccess" display dialog "This application utilizes the built-in Graphic User Interface Scripting architecture of Mac OS X which is currently disabled." & return & return & "You can activate GUI Scripting by selecting the checkbox \"Enable access for assistive devices\" in the Universal Access preference pane." with icon 2 buttons {"OK"} default button 1 end tell end if return gui_scripting_enabled end gui_scripting_check on get_spaces_numbers_key_modifiers() tell application "System Events" to tell spaces preferences of expose preferences to return (get key modifiers of (get properties of numbers key modifiers)) end get_spaces_numbers_key_modifiers on list_to_string(l, d) tell (a reference to my text item delimiters) set {o, contents} to {contents, d} set {l, contents} to {"" & l, o} end tell return l as Unicode text end list_to_string on switch_to_cntkey() if not my gui_scripting_check() then return set key_modifiers to my get_spaces_numbers_key_modifiers() tell application "System Events" set key_modifier_list to {} if key_modifiers contains command then set end of key_modifier_list to "command down" if key_modifiers contains control then set end of key_modifier_list to "control down" if key_modifiers contains option then set end of key_modifier_list to "option down" if key_modifiers contains shift then set end of key_modifier_list to "shift down" set key_modifier_list to my list_to_string(key_modifier_list, ", ") if key_modifier_list ≠ "" then set key_modifier_list to " using {" & key_modifier_list & "}" end tell return key_modifier_list end switch_to_cntkey (* arg arrow type kUpArrow => Up kDownArrow => Down kLeftArrow => Left kRightArrow => Right *) on switchScreen(arrow) set k to my switch_to_cntkey() run script ("tell application \"System Events\" to keystroke k" & arrow & "Arrow using " & k) log ("tell application \"System Events\" to keystroke k" & arrow & "Arrow using " & k) end switchScreen on idle end idle on open log "tell application \"System Events\" to keystroke k" & arrow & "Arrow using (command down)" end open