The Blog of Maxim Porges

Posts Tagged ‘AppleScript’

  • An AppleScript to Toggle Sleep Modes

    I have a 2008 unibody MacBook Pro, and the battery is starting to show its age. When I leave it in sleep mode, I maybe get a day and a half before the battery is completely drained. Putting my laptop into hibernation keeps the battery charge longer, but takes longer to start up as well. Depending on what I’m doing with my laptop (i.e. putting it to sleep at home for a few hours vs. traveling with it) I like to change the power mode accordingly so that I can go longer without having to plug it in.

    You can change the power-down mode from sleep to hibernate and vice versa using the pmset command line utility, but I kept forgetting the options to pass in, so I wrote a little AppleScript that does it for me. The script prompts you for your admin password, checks the current sleep mode, and gives you the option to toggle the other mode if you want to.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    
    set loggedInUser to system attribute "USER"
    set userCancelled to false
    try
    	set sudoPasswordResult to display dialog "Please enter your password: " default answer "" with title "Password" with icon caution with hidden answer
    on error number -128
    	set userCancelled to true
    end try
     
    if not userCancelled then
    	if text returned of sudoPasswordResult is not equal to "" then
    		set sudoPassword to text returned of sudoPasswordResult
    		set currentModeText to do shell script "pmset -g | grep hibernatemode" user name loggedInUser password sudoPassword with administrator privileges
    		set currentMode to item 16 of currentModeText
     
    		set selectedButton to 1
    		set currentSleepModeName to ""
    		if currentMode is equal to "1" then
    			#Hibernate mode - default selection toggles to Sleep
    			set selectedButton to 1
    			set currentSleepModeName to "Hibernate"
    		else if currentMode is equal to "3" then
    			#Sleep mode - default selection toggles to Hibernate
    			set currentSleepModeName to "Sleep"
    			set selectedButton to 2
    		end if
     
    		set sleepModeResults to display dialog "Current sleep mode is " & currentSleepModeName & ". Select new sleep mode." with title "Select new sleep mode" buttons {"Sleep", "Hibernate"} default button selectedButton
    		set newSleepMode to button returned of sleepModeResults
    		if newSleepMode is "Sleep" then
    			set sleepModeFlag to 3
    		else if newSleepMode is "Hibernate" then
    			set sleepModeFlag to 1
    		end if
     
    		do shell script "pmset -a hibernatemode " & sleepModeFlag user name loggedInUser password sudoPassword with administrator privileges
    	end if
    end if

    2011.01.23 / no responses / Category: Uncategorized

  • Using AppleScript to Position iChat Windows

    We use instant messaging quite a bit at Highwinds. I bounce back and forth between using my laptop by itself, and using it with a secondary 22″ display. Regardless of how I’m using my laptop, I like my iChat windows to fill the laptop screen with about a 3-pixel gap between each of them. This means that when I’m on my laptop alone, its screen gets filled when I Apple-Tab to iChat, and when I’m on a two-monitor setup, the larger attached monitor display is free of chat windows and they are all present on my laptop screen so I can work while watching for chats.

    My AIM and GMail buddy lists are about the same length, so I like to stack them on top of each other with half of the screen height given to each. My Highwinds buddy list is the longest, so that gets a full column to itself to the right of my AIM/GMail lists. Finally, I have my chat window occupying the rest of the right-hand side of the display. You can see this in the image below (some screen names have been obscured to protect the innocent).

    My iChat Layout

    Unfortunately, Apple hasn’t programmed OS X to remember the position of windows between laptop-only and display-attached configurations, which means I always have to manually move my chat windows back to the second display after I reconnect it to my laptop. This is a pain in the ass. I finally got a few minutes to write an AppleScript to do this for me automatically, presented below.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    
    -- Get display area
    tell application "Finder"
    	set displayAreaDimensions to bounds of window of desktop
    	set widthOfDisplayArea to item 3 of displayAreaDimensions
    	set heightOfDisplayArea to item 4 of displayAreaDimensions
    end tell
     
    tell application "System Events" to tell process "Dock"
    	set dockDimensions to size in list 1
    	set heightOfDock to item 2 of dockDimensions
    end tell
     
    -- Set up desired coordinates when running iChat on the laptop monitor at 1440x900
    set maximumChatWindowHeight to (heightOfDisplayArea - heightOfDock)
    set chatWindowWidth to 275
    set padding to 3
    set heightOfMenuBar to 22
    set laptopPhysicalDisplayWidth to 1440
     
    set aimCoordinates to [0, 0, chatWindowWidth, (maximumChatWindowHeight / 2) - heightOfMenuBar]
    set gmailCoordinates to [0, (item 4 of aimCoordinates) + (heightOfMenuBar + padding), chatWindowWidth, maximumChatWindowHeight]
    set highwindsCoordinates to [chatWindowWidth + padding, 0, (chatWindowWidth * 2) + padding, maximumChatWindowHeight]
    set chatWindowCoordinates to [(chatWindowWidth * 2) + (padding * 2), 0, laptopPhysicalDisplayWidth, maximumChatWindowHeight]
     
    -- Shift everything over by laptop display width if using a second monitor
    if widthOfDisplayArea is greater than laptopPhysicalDisplayWidth then
    	set widthOfSecondaryDisplay to (widthOfDisplayArea - laptopPhysicalDisplayWidth)
    	repeat with currentDimensions in [aimCoordinates, gmailCoordinates, highwindsCoordinates, chatWindowCoordinates]
    		repeat with itemPosition in [1, 3]
    			set item itemPosition of currentDimensions to ((item itemPosition of currentDimensions) + widthOfSecondaryDisplay)
    		end repeat
    	end repeat
    end if
     
    -- Position chat windows
    tell application "iChat"
    	set bounds of window "AIM Buddy List" to aimCoordinates
    	set bounds of window "myGoogleTalkAddress@gmail.com" to gmailCoordinates
    	set bounds of window "myWorkEmailAddress@highwinds.com" to highwindsCoordinates
    	set bounds of windows whose name contains "Chats" to chatWindowCoordinates
    end tell

    The script is pretty simple. It grabs the screen and dock dimensions, and sets up some global variables. Then, for each of my buddy lists (AIM, GMail, and Highwinds) it sets up 4-coordinate position arrays describing the [top left x, top left y, bottom right x, bottom right y] coordinates that I want each window to end up in. Next, it checks the total display area: if the area is greater than the width of my physical laptop display, it bumps all the X coordinates over by the width of the secondary display so that the windows end up on my laptop display (since I position my laptop to the right of my secondary display). Finally, it tells iChat to position the windows, referencing each by their title bar. I group all my chats in to a single window, so the title of this window is something like “18 Chats”; as a result, I use a query-like expression to reference this window’s title.

    Rather than dynamically setting the position of your chat windows, if you would prefer to move your chat windows to the positions that you want them in and have your Mac tell you what the coordinates are, you can use the script below. You can then hard-code these coordinates in to the coordinate arrays in the script above.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    tell application "iChat"
    	activate
    	set allChatWindows to every window
    	repeat with currentWindow in allChatWindows
    		set windowBounds to the bounds of currentWindow
    		set allBounds to ""
    		repeat with bound in windowBounds
    			set allBounds to (allBounds & bound & ",")
    		end repeat
    		display dialog (name of currentWindow & ": " & allBounds)
    	end repeat
    end tell

    2010.01.25 / 2 responses / Category: Uncategorized