Friday, July 30, 2010

#1 2007-11-11 11:24:40 am

nazgul
Member
Registered: 2007-11-11
Posts: 2

Scripting Leopard Spaces

Spaces is nice, but there doesn't seem to be any easy way to quickly assign a particular application to one (or all) spaces.  You have to go to the preferences and even then you don't get a list of running apps, you have to go find the application in question.

I made an attempt to fix this, but I ran into a scripting issue, namely, how do I set a value in the "application bindings" record.  The keys are bundle names of the form |com.cocoatech.pathfinder| and I had enough trouble getting the list, let alone setting them.  Here's what I have so far, any thoughts?

Applescript:


tell application "System Events"
   set all_spaces to "65544" -- application is in all spaces
   set choose_file to "Choose a file…"
   set num_spaces to 0
   set app_layout to {}
   tell spaces preferences of expose preferences
       set num_spaces to spaces rows * spaces columns
       set app_layout to application bindings
   end tell
   
   -- Okay, please tell me there's a better way to get the names from a record!
   try
       get properties of app_layout
       display dialog "Whoops, we expected this to fail. Let the poor programmer know."
       return false
   on error errstr
       set app_locations to {}
       set state to "NEEDID"
       set curid to ""
       repeat with w in words of errstr
           set w to w as string
           if state = "NEEDLOC" then
               set app_locations to app_locations & {curid, w}
               set curid to ""
               set state to "NEEDID"
           else if state = "NEEDID" then
               if w = "|" then set state to "INID"
           else if state = "INID" then
               if w = "|" then
                   set state to "NEEDLOC"
               else if curid = "" then
                   set curid to w
               else
                   set curid to curid & "." & w
               end if
           end if
       end repeat
   end try
   
   set app_info to {name, bundle identifier} of (application processes whose background only is false)
   set app_list to {}
   repeat with i from 1 to length of (item 1 of app_info)
       set app_name to (item i of (item 1 of app_info))
       set app_bundle to (item i of (item 2 of app_info))
       set app_location to ""
       if app_locations contains app_bundle then
           repeat with i from 1 to count app_locations by 2
               if app_bundle = item i of app_locations then
                   set app_location to item (i + 1) of app_locations
                   exit repeat
               end if
           end repeat
       end if
       if app_location = all_spaces then
           set app_list to app_list & {"All" & tab & app_name}
       else if app_location ≠ "" then
           set app_list to app_list & {app_location & tab & app_name}
       else
           set app_list to app_list & {tab & app_name}
       end if
   end repeat
   
   set app_name to (choose from list ({choose_file} & app_list) with prompt "Pick an application to assign.")
   if app_name is false then return false
   set app_name to item 1 of app_name
   if app_name is choose_file then return true -- for now
   
   set app_index to -1
   repeat with i from 1 to length of app_list
       if app_name = item i of app_list then
           set app_index to i
           exit repeat
       end if
   end repeat
   if app_index = -1 then
       display dialog "Couldn't find application name in list! Internal error."
       return false
   end if
   set bundle_name to item app_index of (item 2 of app_info)
   set app_name to item app_index of (item 1 of app_info) -- name without the tab stuff
   --return {app_name, bundle_name}
   
   set space_choice to {"None", "All"}
   repeat with i from 1 to num_spaces
       set space_choice to space_choice & i
   end repeat
   set new_space to (choose from list space_choice with prompt "Assign a space to " & app_name)
   if new_space is false then return false
   set new_space to item 1 of new_space
   if new_space = "All" then set new_space to all_spaces
   if new_space = "None" then return false -- for now
   
   -- now the critical test, can we do this?
   tell spaces preferences of expose preferences
       set bundle_name of application bindings to new_space
   end tell
   -- nope. What's the magic to change this record?
   (*
       {|org.tynsoe.buddypop|:65544, |com.adiumx.adiumx|:65544, |at.obdev.launchbar4|:65544, |com.cocoatech.pathfinder|:65544, |org.orange-carb.slimbatterymonitor|:65544, |com.wbc.omnigrowl|:65544, |com.growl.growlhelperapp|:65544, |com.apple.ichat|:65544, |com.apple.mail|:3, |com.gorter.antirsi|:65544, |com.yousoftware.youcontrol|:65544, |com.growl.menuextra|:65544}
   *)

end tell


Filed under: System

Offline

 

#2 2007-11-11 12:19:59 pm

StefanK
Member
From: Sankt Gallen, Switzerland
Registered: 2006-10-21
Posts: 7316
Website

Re: Scripting Leopard Spaces

Hi,

nice script. smile

The fastest way to retrieve the data from the record is using text item delimiters

Applescript:

tell application "System Events"
   tell spaces preferences of expose preferences
       set num_spaces to spaces rows * spaces columns
       set app_layout to application bindings
   end tell
end tell
try
   app_layout as number -- causes an error anyway
on error errstr
   set app_locations to {}
   set {TID, text item delimiters} to {text item delimiters, "{"}
   set errstr to text item 2 of errstr
   set text item delimiters to "}"
   set errstr to text item 1 of errstr
   set text item delimiters to ", "
   set errstr to text items of errstr
   set text item delimiters to TID
   
   repeat with i in errstr
       set o to offset of "|:" in i
       tell i
           set end of app_locations to text 2 thru (o - 1)
           set end of app_locations to text (o + 2) thru -1
       end tell
   end repeat
end try

To append a data pair to a record, use this example:

Applescript:

tell application "System Events"
   tell spaces preferences of expose preferences
       set app_layout to application bindings
       set app_layout to app_layout & {|com.apple.iChat|:2} -- for example iChat in space 2
       set application bindings to app_layout
   end tell
end tell

Last edited by StefanK (2007-11-11 12:22:38 pm)


regards

Stefan

Filed under: System

Offline

 

#3 2007-11-12 06:18:01 pm

nazgul
Member
Registered: 2007-11-11
Posts: 2

Re: Scripting Leopard Spaces

StefanK wrote:

Applescript:

set app_layout to app_layout & {|com.apple.iChat|:2} -- for example iChat in space 2

I considered using delimiters, but my head was in parser mode. 

More of a concern is the example you give for setting things.  That works fine when you know the application bundle name at compile time, but in this case we've found it at runtime, and it's a string.  So the question is--how do I turn a string into a |construct| (What exactly is that anyway?  A reference to a record name?)  I have a sneaky suspicion this is only going to work via a third party extender for manipulating records, or via something that logically does an "eval".

Offline

 

#4 2007-11-13 02:42:21 am

StefanK
Member
From: Sankt Gallen, Switzerland
Registered: 2006-10-21
Posts: 7316
Website

Re: Scripting Leopard Spaces

you can create this record using second level evaluation with the run script command,
here an example:

Applescript:


tell application "System Events" to set theApps to bundle identifier of processes whose background only is false
set x to {}
repeat with i from 1 to count theApps
   set x to x & (run script "{|" & item i of theApps & "|:" & i & "}")
end repeat

Note: the property bundle identifier of System Events is introduced in Leopard


regards

Stefan

Filed under: System

Offline

 

#5 2007-11-13 09:36:59 am

iMacFlats
Member
Registered: 2005-05-28
Posts: 18

Re: Scripting Leopard Spaces

How do I tell a Window in an application to go to a different space?

Can this be performed much in the same fashion that you would resize a window or change it's coordinates?

Or, do you have to go to spaces and tell spaces to move the window?

Any examples would be great. I don't want to assign, for example, Safari to be assigned to Space 2, as I would do through the Preferences Pane, I simply want to move a window's location.

Offline

 

#6 2007-11-16 02:51:03 pm

tslusser
Member
Registered: 2007-11-16
Posts: 1

Re: Scripting Leopard Spaces

Hello,

Does anyone know what the applescript is to change the hotkey to activate spaces?  I can get the expose hotkeys but for some reason I am not able to figure out how to set spaces.

Thanks,

Ted

Offline

 

#7 2008-09-29 05:26:26 am

Pflugshaupt
Member
Registered: 2008-09-22
Posts: 1

Re: Scripting Leopard Spaces

Hi all,

I'm trying to add remove an app from Spaces prefs via appleScript and came across a problem with all scripts I have found on the interwebs. If my app is the only one and I try to remove it with appleScript, an empty record should be set as the spaces preferences. However it appears this set instruction is just ignored hmm.

Applescript:

tell application "System Events" to tell spaces preferences of expose preferences
set application bindings to {}
end tell

Am I doing something fundamentally wrong here or is this a bug in system prefs? I kinda suspect {} is not really an empty record. If so, how can I create an empty record?

Thanks in advance for any hints.


Filed under: events, Record, System, Spaces

Offline

 

#8 2008-10-01 10:55:17 am

Lance Klusener
Member
Registered: 2008-09-26
Posts: 57

Re: Scripting Leopard Spaces

can apple script change the shortcut for "cycle through open applications" (default: Cmd + Tab)
(i want to make it Ctrl + Tab)

Offline

 

Board footer

Powered by FluxBB

[ Generated in 0.369 seconds, 10 queries executed ]

RSS (new topics) RSS (active topics)