Example of using modifierFlags() to determine if a particular is pressed

how-to
asobjc

#1

I was working on updating the ASObj-C database when the SD7 testing started. I was literally working on this part when I started testing. So I decided to finish it and posted it because I thought others might find it useful. Thanks goes to Shane for rescuing from the pits of despair while figuring this out.

(*
This script is based on a script from Shane Stanley.  The original script was entended and comments were added.

This script demonstrates how to determine what keys are pressed at the time, or if a particular key is pressed at the time.
The 8 modifier keys can be proceesed as demonstrated in this scropt:
	"caps lock" key
	shift key
	control key
	option key
	command key
	numericPad key
	help key
	function key

Note: The flag for the "caps lock" key will be "true" when "caps lock" is on, not necessarily when the "caps lock" key is
pressed down.
*)

use framework "Foundation"
use framework "AppKit" -- for NSEvent

property NSCapsLockMask : a reference to 65536
property NSShiftKeyMask : a reference to 131072
property NSControlKeyMask : a reference to 262144
property NSOptionKeyMask : a reference to 524288
property NSCommandKeyMask : a reference to 1048576
property NSFunctionKeyMask : a reference to 8388608
property NSEvent : a reference to current application's NSEvent

on KeyPressed(KeyName)
	-- This handler determines, at the time it executes, if the key indicated by "KeyName" is being pressed
	-- It returns true if it is being pressed at the time the handler execute, otherwise it returns false
	
	if KeyName = "caps lock" then
		set TheMask to NSCapsLockMask
	else if KeyName = "shift" then
		set TheMask to NSShiftKeyMask
	else if KeyName = "control" then
		set TheMask to NSControlKeyMask
	else if KeyName = "option" then
		set TheMask to NSOptionKeyMask
	else if KeyName = "command" then
		set TheMask to NSCommandKeyMask
	else if KeyName = "function" then
		set TheMask to NSFunctionKeyMask
	else
		return false
	end if
	
	set MFlags to NSEvent's modifierFlags() as integer
	-- See the comments at the beginning of "TheModifiersKeysPressedDown" handler for an explanation of
	-- how the "div" and "mod" work below.  Since the "mod" is part is the number 2 only the last bit in
	-- in the number is being compared to zero.
	if ((MFlags div TheMask) mod 2) = 0 then
		return false
	else
		return true
	end if
end KeyPressed

on TheModifiersKeysPressedDown()
	(*
	This handler determines, at the time it executes, what keys are pressed, and if the "caps lock" is on or off.
	
	Doing a "div" on an integer where "the number doing the divide is a power of 2" has the affect of stripping
	off binary bits from the right end of the number.
	For example  "8 div 4 = 2" in binary is binary "10" because 8 = "1000", 4 = 2^2 and 2 = "10"
	The last N digits to the right of the binary number are striped off the number becuase those last 2 digits = 2^N
	In a 4 digit binary number this would only leave the first 2 digits of the binary number which is "10" binary.
	This is analogous to base 10 where 513 div 10 = 51
	
	But something like "8 div 3" for stripping off binary bits is meaningless because 3 is no a power of 2.
	
	The "mod" part is just the part of the original binary number that was dropped when getting the "div" value.
	*)
	
	set TheKeys to {}
	
	-- "modifierFlags" is defined in the "NSEvent" class in "AppKit"
	-- It returns a number whose binary bits determine what keys are pressed down, or if "caps lock" is on or off
	set KeyFlags to NSEvent's modifierFlags() as integer
	
	if ((KeyFlags div NSCapsLockMask) mod 2) is not 0 then
		set TheKeys to TheKeys & {"caps lock"}
	end if
	if ((KeyFlags div NSShiftKeyMask) mod 2) is not 0 then
		set TheKeys to TheKeys & {"shift"}
	end if
	if ((KeyFlags div NSControlKeyMask) mod 2) is not 0 then
		set TheKeys to TheKeys & {"control"}
	end if
	if ((KeyFlags div NSOptionKeyMask) mod 2) is not 0 then
		set TheKeys to TheKeys & {"option"}
	end if
	if ((KeyFlags div NSCommandKeyMask) mod 2) is not 0 then
		set TheKeys to TheKeys & {"command"}
	end if
	if ((KeyFlags div NSFunctionKeyMask) mod 2) is not 0 then
		set TheKeys to TheKeys & {"function"}
	end if
	
	return TheKeys
end TheModifiersKeysPressedDown

-- The caps lock key was on
KeyPressed("caps lock") --> true

-- The delay gives the user time to press the necessary keys before TheModifiersKeysPressedDown is called
delay 2
-- I held down the option key
KeyPressed("option") --> true

-- No key was pressed when execution came to this point in the script
KeyPressed("option") --> false

-- The "caps lock" was on and the shift, control, option, command and function keys were all held down
TheModifiersKeysPressedDown() --> {"caps lock", "shift", "control", "option", "command", "function"}

-- The delay gives the user time to press the necessary keys before TheModifiersKeysPressedDown is called
delay 2
-- No key was held down pressed and "caps lock" was not on
TheModifiersKeysPressedDown() --> {}

set QuitLoop to false
-- The loop repeats until the shift key is pressed.  This can be done with a "caps lock", "shift",
-- "control", "option", "command", or "function" key.
repeat while (not QuitLoop)
	if KeyPressed("shift") then
		set QuitLoop to true
	end if
	
	-- To execute code in this loop and have it stopped by a key press the user could press and hold the
	-- key until the loop is exited.
end repeat