Tiger shiftKey detect error

This code fails in tiger.

tell application "System Events"
	try -- do not stop on failure
		tell application "KeyboardViewerServer" to activate
		set myShift to (get value of checkbox "⇧" of front window of application process "KeyboardViewerServer") as boolean -- myShift will be 1=down or 0=up
	end try
end tell

It gets changed to :

tell application "System Events"
		try -- do not stop on failure
			tell application "KeyboardViewerServer" to activate
			set myShift to (get value of checkbox "Ãœ”" of front window of application process "KeyboardViewerServer") as boolean 
		end try
	end tell

Also the KeyboardViewerServer becomes visible as in Leopard just does the job and does not show up.
Any ideas anybody?
Thanks

There are several problems that come up when applying this technique on Tiger.

The first one (the one you ran into) is that characters outside of the system’s primary encoding (usually MacRoman) are not directly usable in the text of an AppleScript program. There is a workaround for representing Unicode characters that are not a part of the primary encoding’s repertoire: set shiftSymbol to («data utxt21E7» as Unicode text). The 21E7 are the two hex bytes for the shift symbol’s UTF-16BE encoding. This stores in shiftSymbol a value similar to what would have been stored using set shiftSymbol to “⇧” on Leopard.

The next issue that you will find is that the UI elements that represent the keys in Tiger’s KeyboardViewerServer are not checkboxes, but buttons. Worse, there seems to be no way of sensing the darkened/normal status of these buttons via the accessibility API.

If you know that Command and Control will never be pressed while you make your key check, you could rig up something like

name of UI element "A"
considering case
    return true if result is "A"
end

And something similar for “Ã…” to catch when Option is being used with/without Shift. There would have to be some extra error handling since when Option is down UI element “A” will throw an error. Correspondingly, when Option is up, UI element “Ã…” will throw an error.

The problem with Control is that it completely blanks out the “A” button, so neither named UI element will exist (this would cause both UI element reference forms to throw errors). The problem with Command is that it causes the “A” button to always show “a”, even when used with Shift (this would cause a false negative, Shift might be down but the “A” key will still say “a”).

Oh yeah, and there is the problem of Caps Lock when testing an alphabetic character. I nearly forgot about that since I always remap it to be another Control key (feature introduced in Tiger).

I put something together, but it just seems too unreliable to bother posting. It will also probably have problems for non-English keyboards and/or key layouts (“A” seems fairly universal, but I bet some do not have “A”, and many more do not use “Ã…” as the alternate character).

I know that Extra Suites can tell you if Shift is down, but I think I have heard that it may not work on Intel Macs. Otherwise, it should be possible to make a command-line tool that could relay the keyboard modifier status (maybe one already exists?).

Model: iBook G4 933
AppleScript: 1.10.7
Browser: Safari 4 Public Beta (4528.17)
Operating System: Mac OS X (10.4)

Hi Chrys

Thanks for your input
Is it not amazing not to be able to detect modifier keys easily?

I only need to find out if the shift key is up or down when the bundle starts up.
If the shift key is down do this else do that…
There will be no other letters typed at the time.
I will not, at this stage, worry about any other modifier.

I tried what I believe you suggested in Tiger and I got this error:System Events got an error: NSReceiverEvaluationScriptError: 4
Did I do this correctly?

tell application "System Events"
	name of UI element "A"
	considering case
		return result is "A"
	end considering
end tell

In my opinion, this kind of thing is really more in the realm of application programming, not application scripting (the core domain of “vanilla” AppleScript). It should be much easier to do from any application programming environment (including, I expect, AppleScript Studio (even if that means resorting to call method on Cocoa objects)).

Yes that code was an incomplete fragment that was intended to indicate a potential path for exploration.

The problem you ran into was that the code you used was trying to address a top-level UI element named “A”. The only top-level UI elements are usually the application processes. I intended to imply that the context you needed to supply included the front window of application process “KeyboardViewerServer” as well as tell app “System Events”. If you supply both the former and the latter, you get something like checkForShiftedKey() in the code below.

isShiftPressed()

to isShiftPressed()
	ensureExistingKVSOrLaunchAndHide()
	
	-- If Command and any other modifiers except Control (but including Shift!) are down, then this will always indicate that Shift is now down.
	-- Command and Shift down --> false (as if Shift was not down!)
	tell checkForShiftedKey("A") to ¬
		if it is not missing value then return it
	
	tell checkForShiftedKey("Ã…") to ¬
		if it is not missing value then return it
	
	-- Neither variation was found. This can happen when Control is down (the "A" key cap is blanked out).
	return missing value
end isShiftPressed

to ensureExistingKVSOrLaunchAndHide()
	tell application "System Events" to if not (exists application process "KeyboardViewerServer") then
		launch application "KeyboardViewerServer"
		tell application process "KeyboardViewerServer"
			set visible to false
			repeat while not (exists front window)
				delay 0.125
			end repeat
			set value of attribute "AXMinimized" of front window to true
		end tell
	end if
end ensureExistingKVSOrLaunchAndHide

to checkForShiftedKey(shiftedKeyName)
	try
		-- Try to find a UI element named after the key. Search is done without case sensitivity.
		tell application "System Events" to get name of UI element shiftedKeyName of front window of application process "KeyboardViewerServer"
	on error
		-- The most likely error is that no UI element was found for the named key.
		return missing value
	end try
	considering case
		-- We found some UI element with the name. Return whether the case matches the original requested name.
		return result is shiftedKeyName
	end considering
end checkForShiftedKey

This also show how you can try to hide the keyboard viewer window if you have to launch its application.

Note the comments that describe the fact that this particular implementation can not properly sense Shift when either Command or Control are down. My previous point that this technique also likely fails miserably when used on various non-English configurations applies to this code. And there is still Caps Lock to consider (having it on will probably mean this code returns true even when Shift is not down; for English keyboards/layouts you might try searching for +, and ± to indicate Shift; the logic will look different though since case is irrelevant; there will still be problems with Command and Control obscuring the ability to observe Shift).

Model: iBook G4 933
AppleScript: 1.10.7
Browser: Safari 4 Public Beta (4528.17)
Operating System: Mac OS X (10.4)

Edit History: Added note about Caps Lock.

Hi,

I wrote a small Command Line Interface, which does the check. It should work also in Tiger.
checkModifierKeys

You can check for cmd, option, control, shift, and capslock
Multiple arguments are possible. This example checks for option and shift


do shell script "/path/to/checkModifierKeys shift option"

the result is either 1 or 0

The code is quite simple

[code]#import <Carbon/Carbon.h>

int main (int argc, const char * argv[]) {
unsigned int modifiers = GetCurrentKeyModifiers();
if (argc == 1)
printf(“%d\n”, modifiers);
else {
int i, result = 1;
for (i = 1; i < argc; ++i) {
if (0 == strcmp(argv[i], “shift”))
result = result && (modifiers & shiftKey);
else if (0 == strcmp(argv[i], “option”))
result = result && (modifiers & optionKey);
else if (0 == strcmp(argv[i], “cmd”))
result = result && (modifiers & cmdKey);
else if (0 == strcmp(argv[i], “control”))
result = result && (modifiers & controlKey);
else if (0 == strcmp(argv[i], “capslock”))
result = result && (modifiers & alphaLock);
}
printf(“%d\n”, result);
}
return 0;
}[/code]

Hello StephanK

I copied checkModifierKeys in the Utilities folder.

I tested with this script:


set p2u to POSIX path of (path to utilities folder)

do shell script p2u & "checkModifierKeys shift option"

I always get a null string.
What am’I making wrongly? I add that I am using 10.4.11.

Yvan KOENIG (from FRANCE dimanche 7 juin 2009 15:08:42)

Thank you to you both.

I decided to check Stefan’s solution first in Leopard and then in Tiger.
Unfortunately I could not get it to recognize the command in Leopard so I cannot progress to Tiger.

Here is what I did.
I downloaded the checkModifierKeys file.
I placed it into the MacOS folder of my bundle with applet.

I need a variable to get the path as this needs to run on other Macs.
This is what I tried:

set flPth to (path to as text) & "Contents:MacOS:checkModifierKeys"
do shell script (quoted form of flPth & " shift")
return result

I got error sh: Macintosh: command not found
I removed the quoted form of, same result.
Assming I got the variable wrong I then tried:

do shell script ("Macintosh HD:Users:m:Desktop:ShiftKeyTest folder:ShiftKeyTest.app:Contents:MacOS:checkModifierKeys shift")

I got error sh: Macintosh: command not found once more.

Sorry, the SDK was set to 10.5.
Try it again, please, same link

do shell script expects a POSIX path (slash separated), HFS paths don’t work


set flPth to POSIX path of (path to me) & "Contents/MacOS/checkModifierKeys"
return (do shell script (quoted form of flPth & " shift")) as integer as boolean
--> true or false

please download the CLI again. I fixed a problem with Tiger

Thanks Stephan

I was afraid that I was using the beast wrongly but now the same script behaves flawlessly.

Is the used tool able to create an application sending a double-click ?

Yvan KOENIG (from FRANCE dimanche 7 juin 2009 19:58:56)

Sorry Yvan, I don’t understand exactly what you mean. The tool reads the modifier keys and compares the bits with the arguments, nothing else

Thanks Stefan,

Just what the doctor ordered
Both on Leopard and Tiger

I was asking if the development tool used to create checkModifierKeys is able to create a new command sending a click or a double click which would be useful when AppleScripting AppleWorks under 10.4.11.

Yvan KOENIG (from FRANCE lundi 8 juin 2009 18:01:14)

I’m using Xcode, I guess everything is possible, you must dig in the API documentation
as I did to find the function GetCurrentKeyModifiers() (honestly I used also google)

Do you know QuicKeys? This tool can perform clicks on a specified position triggered by a keystroke

I’m not a developer.
I’m just a retired potter.

I’m just searching something to enhance my scripts.

Yvan KOENIG (from FRANCE lundi 8 juin 2009 18:40:20)

Hello.
I hope you forgive me Stefan for taking liberties.
I wrote an accompanying man page for this useful utility
Edit: there were no way I could make this act as a man page by copying it back from here.
So What you see is not something you can past in, but you must paste a part at a time.
BBEdit says that the file which works is encoded is of type HTML with macroman encoding and Unix Linefeeds.

Best Regards

McUsr

I recently updated my OS from 10.13.6 to 12.5

I am now receiving the following error message for the following code, whereas everything worked fine prior - and yes, the app still resides in the same location/path.

set flPth to POSIX path of (path to current user folder) & "Library/Application Support/checkModifierKeys"

set commandKeyDown to (do shell script (quoted form of flPth & " command")) as integer as boolean

Result:
error “sh: /Users/administrator/Library/Application Support/checkModifierKeys: Bad CPU type in executable” number 126

I realize this issue might have nothing to do with the checkModifierKeys application itself, but maybe something deep rooted in how the shell script works? Nevertheless, I figured I would post something here in case somebody else has experienced the same issue and if anybody knows what can be modified in order to restore functionality of this wonderful tool? I am a neophyte when it comes to Terminal and Unix commands, etc., so I was hoping if there was a solution it would not be too difficult for somebody like mystelf to undersand?

I recompiled the project with Xcode 13 for Intel and M1.

checkModifierKeys

1 Like

Stefan, if you do see this post - Can you please share that link in your most recent reply? For some reason the link does not appear to work?

Thanks,
-Jeff