keyboard prefs buttons changing

problem:

i move my macbook pro [10.4.8] from desk to elsewhere frequently and while at desk i connect to a pc-style split keyboard – excellent for ergonomics and cheap. not giving that up. each time, i need to re-map the command and option keys using the “modifier keys” dialog of the “Keyboard” tab group of the Keyboard & Mouse Pref Pane (it’s not really practical to use a whole different keyboard layout each time).

not the biggest hassle ever, but quite tedious, and it seems it should be scriptalbe.

the solution so far… this gets me to the needed dialog no problem:


tell application "System Preferences"
	activate
	delay 2
end tell
tell application "System Events"
	tell process "System Preferences"
		click the menu item "Keyboard & Mouse" of the menu "View" of menu bar 1
		delay 4
		click the radio button "Keyboard" of the first tab group of window "Keyboard & Mouse"
		delay 2
		keystroke tab using shift down
		keystroke tab using shift down
		keystroke tab using shift down
		keystroke tab using shift down
		keystroke tab using shift down
		keystroke space
	end tell
end tell

however, once i’m there, doing tab-tab or shift-tab then space, then tab etc. to select the needed changes only works the first time one tests the script. successive times it runs, the focus is on a different lozenge, which throws the script off.

does anyone know a way of making those changes to modifier keys on the command line? then running that command could be scripted easily, i presume.

any suggestions are much appreciated.

Browser: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.0.7) Gecko/20060911 Camino/1.0.3
Operating System: Mac OS X (10.4)

What you’ve got so far can be accomplished with this line:


tell application "System Preferences" to reveal anchor "keyboardTab_ModifierKeys" of pane "com.apple.preference.keyboard"

What is it you want to accomplish next?

Hi, fogboy.

I’m not quite clear how you want to remap the Command and Option keys. Do you want to swap them over? This does that job in OS 10.4.8 on my G5:

tell application "System Preferences"
	activate
	reveal anchor "keyboardTab_ModifierKeys" of pane id "com.apple.preference.keyboard"
end tell
tell application "System Events"
	tell application process "System Preferences"
		set optionButton to 1st pop up button of sheet 1 of front window whose value contains "Option"
		set CommandButton to 1st pop up button of sheet 1 of front window whose value contains "Command"

		click optionButton
		key code {125, 49}
		repeat until value of optionButton contains "Command"
			delay 0.2
		end repeat

		click CommandButton
		key code {126, 49}
		repeat until value of CommandButton contains "Option"
			delay 0.2
		end repeat

		key code 36
	end tell
end tell

this is amazing, Nigel :slight_smile:

My approach is a little more “complicated”
but does the same as yours

tell application "System Preferences"
	activate
	reveal anchor "keyboardTab_ModifierKeys" of pane id "com.apple.preference.keyboard"
end tell

change_key(3, 1, "down")
change_key(4, 1, "up")
tell application "System Events" to click button "OK" of sheet 1 of window "Keyboard & Mouse" of process "System Preferences"
tell application "System Preferences" to quit


on change_key(theKey, step, dir)
	tell application "System Events"
		tell process "System Preferences"
			tell window "Keyboard & Mouse"
				tell pop up button theKey of sheet 1
					set value of attribute "AXFocused" to true
					keystroke (ASCII character 30) using option down
					delay 0.5
					repeat step times
						if dir is "down" then
							keystroke (ASCII character 31)
						else
							keystroke (ASCII character 30)
						end if
					end repeat
					delay 0.5
					keystroke return
				end tell
			end tell
		end tell
	end tell
end change_key

woah. i thought i might, if i were VERY lucky, get some pointers that would lead me down a path where i’d have to do a lot of digging and tweaking to maybe get it right two weeks from now. instead ya’ll come back, on a saturday afternoon no less, with the very thing that works right off the bat.

this rocks, especially since it reveals all kinds of bits i didn’t know about and may use in some other scripts.

thank you so so much.

Nigel;

I know key code 49 is the space bar, but what are 125 and 126?

I’m not Nigel, but… :wink:

the numbers represent two of the 4 arrow keys:

123 left
124 right
125 down
126 up

Thank you, Stefan;

I must have tried everything but… :confused: (using Full Key Codes)

Adam

I am, though. :smiley:

And 36 is the Return key.

Thank you both. Full Key Codes is great for discovering the key code given a key press, but I don’t have a tool or table for going the other way.

A utility like KeyboardSee can be handy for this, Adam. If one checks the ‘keycodes’ checkbox, the hex value of each key is displayed. The arrow keys, for example, are shown as:

The values we really want to find, of course, are decimal key codes. While these aren’t displayed, conversion is a fairly trivial matter:


on dec_to_hex from l
	set l to l as list
	set c to "0123456789ABCDEF"
	repeat with i in l
		set v to i as integer
		set h to ""
		repeat while v > 0
			set h to c's character (v mod 16 + 1) & h
			set v to v div 16
		end repeat
		set i's contents to h
	end repeat
	tell l to if (count) is 1 then return beginning
	l
end dec_to_hex

dec_to_hex from {123, 124, 125, 126} --> {"7B", "7C", "7D", "7E"}


So now we can simply check the keyboard layout for the resulting hex values.

To reverse the process:


on hex_to_dec from l
	set l to l as list
	set c to "0123456789ABCDEF"
	repeat with i in l
		set d to 0
		repeat with v in i
			if v is not in c then error "Invalid hex value: " & v
			tell (offset of v in c) - 1 to set d to d * 16 + it
		end repeat
		set i's contents to d
	end repeat
	tell l to if (count) is 1 then return beginning
	l
end hex_to_dec

hex_to_dec from {"7B", "7C", "7D", "7E"} --> {123, 124, 125, 126}


I like this for converting from Hex to Dec:


set hexnum to "7d"
set DN to run script "parseInt( \"" & hexnum & "\" , 16) " in "JavaScript"
--> 125

Very compact, to be sure ” although, to be fair, the routines suggested earlier were attempting to do slightly more (including processing a list of values).

For greater brevity, something like this could be used:


set h to "7D"
set d to 0
repeat with i in h
	set d to d * 16 + (offset of i in "123456789ABCDEF")
end repeat
--> 125


Of course, if you were trying to force me into coming up with a one-liner, and the maximum value didn’t exceed 255 (as in this situation), then I might be tempted to suggest something like:


set h to "7D"
tell "123456789ABCDEF" to (my (offset of h's character 1 in it)) * 16 * ((count h) - 1) + (my (offset of h's character -1 in it))
--> 125


In terms of performance here, the former is between 160 to 200 times faster than the JavaScript technique, while the bump from the latter is more like x180 to x220…
:wink:

Marvelous as always… :wink:

Folks,

I love this competition,
unlike in real life it’s always “who’s got the shortest” ;):wink:

Although I’ve come up with some good ones myself, I think Kai must be acknowledged as the grand master.

Another form of challenge is to see if you can manage to accomplish a task without defining any variables. This is an example of one that computes a short date in dd/mm/yyyy format without any defined variables (by Nigel Garvey, who must also be acknowledged as the grand master of speed):


tell {current date}
	copy beginning to end
	set end's month to January
	tell ((beginning's year) * 10000 + (beginning - (end - 3944592)) div 2629728 * 100 + (beginning's day)) as string
		text 7 thru 8 & "/" & text 5 thru 6 & "/" & text 1 thru 4
	end tell
end tell

display dialog result

With regard to the problem of identifying the key that goes with the code, I came up with this, though I suspect it only works properly with British G5 keyboards “ and Tiger, of course: :wink:

Edit: I’ve now scrubbed the script that was here and posted a (hopefully) better version in the more appropriate setting of this thread of Adam’s in Code Exchange.

I’ve got one in Code Exchange for American (or English Canadian) keyboards. Not knowing of the existance of the Keyboard Server, mine is pure unadulterated brute force - I actually tried every key and wrote down the key code for it. :mad:

With respect to yours, it does indeed give wrong answers for a Keyboard Viewer (U.S.) which is the one on MM. When I understand what you’ve done, I’ll try to convert mine. :wink:

Hi, Adam.

Mine’s not meant to be taken seriously “ which is why I included the wink in the preamble. It’s basically worked out by brute force, like yours. I got the names and numbers of the buttons in the Keyboard Viewer GUI and matched them to the key codes as revealed for the same machine by keyboardSee. It’s only likely to work if the Keyboard Viewer on your machine has the same GUI structure as the one on mine “ which plainly it hasn’t. Kept me amused for an hour or two, though. :wink:

From the point of view of GUI Scripting, it seems to be only necessary to know a few key codes as ‘keystroke’ seems to be the better choice in most cases.

Thanks for your kind words about the speed of my scripts. It has to be said that kai’s and one or two others’s don’t exactly hang about either… :slight_smile: