From 8f6d0189f0dde54cd570ad4a81a1e4ce242acda1 Mon Sep 17 00:00:00 2001 From: Monte Goulding Date: Thu, 31 May 2018 08:31:17 +1000 Subject: [PATCH] [[ KeyIsDown ]] Implement key is down This patch implements modifier key state access for LCB. --- docs/lcb/notes/feature-keyisdown.md | 12 +++++++++ engine/src/engine.lcb | 28 +++++++++++++++++++++ engine/src/module-engine.cpp | 39 +++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 docs/lcb/notes/feature-keyisdown.md diff --git a/docs/lcb/notes/feature-keyisdown.md b/docs/lcb/notes/feature-keyisdown.md new file mode 100644 index 00000000000..edc3d168dd5 --- /dev/null +++ b/docs/lcb/notes/feature-keyisdown.md @@ -0,0 +1,12 @@ +# LiveCode Builder Host Library +## Engine library + +* You can now use `the is [currently] down` expression to +determine if the shift, command, control, alt/option or caps lock keys +are down. Use the optional `currently` adverb to differentiate between +the shift key being down at the present moment and it being down when the +current event occurred. + + if the shift key is down then + DoShiftKeyThing() + end if diff --git a/engine/src/engine.lcb b/engine/src/engine.lcb index cd44de7466d..9f8f797019d 100644 --- a/engine/src/engine.lcb +++ b/engine/src/engine.lcb @@ -83,6 +83,8 @@ public foreign handler MCEngineEvalTheItemDelimiter(out rDelimiter as String) re public foreign handler MCEngineEvalMyResourcesFolder(out pFile as optional String) returns nothing binds to "" +public foreign handler MCEngineEvalKeyIsDown(in pKey as UInt8, in pEvent as CBool, out rState as CBool) returns nothing binds to "" + /** Summary: Resolves a string to a script object. Object: The string describing the script object. @@ -634,4 +636,30 @@ begin MCEngineEvalMyResourcesFolder(output) end syntax +/** +Summary: Returns true if the key is down + +Returns: The state of the key + +Description: +Use 'the ... key is down' to determine if the key was down at the start of the +current event. Use 'the ... key is currently down' to determine if the key is +down at the time it is being checked. + +As in script, command and control keys return the state of the same key on non-macOS +systems while on macOS they are separate keys. Additionally alt and option are +different names for the same key. + +*/ +syntax KeyIsDown is expression + "the" ( "shift" | \ + "command" | \ + "control" | \ + "alt" | \ + "option" | \ + "caps" "lock" ) "key" "is" ( "currently" | ) "down" +begin + MCEngineEvalKeyIsDown(mKey, mEvent, output) +end syntax + end module diff --git a/engine/src/module-engine.cpp b/engine/src/module-engine.cpp index e6b6e8b45fa..e11ba205a4a 100644 --- a/engine/src/module-engine.cpp +++ b/engine/src/module-engine.cpp @@ -1280,6 +1280,45 @@ extern "C" MC_DLLEXPORT_DEF MCArrayRef MCEngineExecDescribeScriptOfScriptObject( //////////////////////////////////////////////////////////////////////////////// +extern "C" MC_DLLEXPORT_DEF void +MCEngineEvalKeyIsDown(uint8_t p_key, bool p_event, bool& r_down) +{ + uint8_t t_modifier = 0; + switch (p_key) + { + case 0: + t_modifier = MS_SHIFT; + break; + case 1: + t_modifier = MS_CONTROL; + break; + case 2: + t_modifier = MS_MAC_CONTROL; + break; + case 3: + t_modifier = MS_MOD1; + break; + case 4: + t_modifier = MS_CAPS_LOCK; + break; + default: + r_down = false; + MCUnreachable(); + break; + } + + if (p_event) + { + r_down = (MCmodifierstate & t_modifier) != 0; + } + else + { + r_down = (MCscreen->querymods() & t_modifier) != 0; + } +} + +//////////////////////////////////////////////////////////////////////////////// + MC_DLLEXPORT_DEF MCTypeInfoRef kMCEngineScriptObjectDoesNotExistErrorTypeInfo = nil; MC_DLLEXPORT_DEF MCTypeInfoRef kMCEngineScriptObjectNoContextErrorTypeInfo = nil;