[Laszlo-checkins] r14112 - in openlaszlo/branches/4.2: WEB-INF/lps/lfc/kernel/dhtml WEB-INF/lps/lfc/kernel/swf WEB-INF/lps/lfc/kernel/swf9 WEB-INF/lps/lfc/services lps/includes/source

ptw@openlaszlo.org ptw at openlaszlo.org
Wed Jun 10 14:01:47 PDT 2009


Author: ptw
Date: 2009-06-10 14:01:41 -0700 (Wed, 10 Jun 2009)
New Revision: 14112

Modified:
   openlaszlo/branches/4.2/WEB-INF/lps/lfc/kernel/dhtml/LzKeyboardKernel.js
   openlaszlo/branches/4.2/WEB-INF/lps/lfc/kernel/swf/LzKeyboardKernel.as
   openlaszlo/branches/4.2/WEB-INF/lps/lfc/kernel/swf9/LzKeyboardKernel.as
   openlaszlo/branches/4.2/WEB-INF/lps/lfc/services/LzKeys.lzs
   openlaszlo/branches/4.2/lps/includes/source/embednew.js
Log:
Change 20090609-ptw-V by ptw at dueling-banjos.local on 2009-06-09 16:28:34 EDT
    in /Users/ptw/OpenLaszlo/4.2
    for http://svn.openlaszlo.org/openlaszlo/branches/4.2

Summary: Clear stuck keys on browser focus

Bugs Fixed: LPP-8056  Alt tab issue when switching tasks (partial)

Technical Reviewer: max (Message-ID: <4A300705.4070400 at laszlosystems.com>)
QA Reviewer: aalappat at laszlosystems.com (pending)

Details:
    This fixes the bug in all browsers _except_ IE, where it only
    reduces the bug somewhat.  I'm putting in this partial fix just so
    the work is not lost.

    LzKeyboardKernel.*:  Add an __allKeysUp call that will simulate
    key up events for any keys that the kernel believes to (still) be
    down.

    LzKeys: __allKeysUp exported so it can be called from lz.embed

    embednew: When the browser regains focus, invoke
    lz.Keys.__allKeysUp to clear any keys that may appear to still be
    down because the browser lost focus due to keyboard input.

Tests:
    Test case from the bug report



Modified: openlaszlo/branches/4.2/WEB-INF/lps/lfc/kernel/dhtml/LzKeyboardKernel.js
===================================================================
--- openlaszlo/branches/4.2/WEB-INF/lps/lfc/kernel/dhtml/LzKeyboardKernel.js	2009-06-10 20:18:11 UTC (rev 14111)
+++ openlaszlo/branches/4.2/WEB-INF/lps/lfc/kernel/dhtml/LzKeyboardKernel.js	2009-06-10 21:01:41 UTC (rev 14112)
@@ -1,7 +1,7 @@
 /**
   * LzKeyboardKernel.js
   *
-  * @copyright Copyright 2007,2008 Laszlo Systems, Inc.  All Rights Reserved.
+  * @copyright Copyright 2007,2008,2009 Laszlo Systems, Inc.  All Rights Reserved.
   *            Use is subject to license terms.
   *
   * @topic Kernel
@@ -11,7 +11,7 @@
 
 // Receives keyboard events from the runtime
 var LzKeyboardKernel = { 
-    __downKeysHash: {alt: false, control: false, shift: false}
+    __downKeysHash: {}
     ,__keyboardEvent: function ( e ){   
         if (!e) e = window.event;
         var delta = {};
@@ -25,38 +25,38 @@
             // TODO: add mapping to flash character codes?
             var s = String.fromCharCode(k).toLowerCase();
             if (t == 'keyup') {
-                if (dh[s] != false) {
+                if (dh[s] != null) {
                     delta[s] = false;
                     dirty = true;
                 }    
-                dh[s] = false;
+                dh[s] = null;
             } else if (t == 'keydown') {
-                if (dh[s] != true) {
+                if (dh[s] == null) {
                     delta[s] = true;    
                     dirty = true;
                 }    
-                dh[s] = true;
+                dh[s] = k;
             }    
         }    
-        if (dh['alt'] != e['altKey']) {
-            delta['alt'] = e['altKey'];
+        if ((dh['alt'] != null) != e['altKey']) {
+          delta['alt'] = e['altKey'];
             dirty = true;
             if (LzSprite.prototype.quirks['alt_key_sends_control']) {
                 delta['control'] = delta['alt'];
             }
         }    
-        if (dh['control'] != e['ctrlKey']) {
-            delta['control'] = e['ctrlKey'];
+        if ((dh['control'] != null) != e['ctrlKey']) {
+          delta['control'] = e['ctrlKey'];
             dirty = true;
         }    
-        if (dh['shift'] != e['shiftKey']) {
+        if ((dh['shift'] != null) != e['shiftKey']) {
             delta['shift'] = e['shiftKey'];
             dirty = true;
         }    
 
-        dh['alt'] = e['altKey'] 
-        dh['control'] = e['ctrlKey'] 
-        dh['shift'] = e['shiftKey']
+        dh['alt'] = e['altKey']?18:null;
+        dh['control'] = e['ctrlKey']?17:null;
+        dh['shift'] = e['shiftKey']?16:null;
         if (dirty && LzKeyboardKernel.__scope && LzKeyboardKernel.__scope[LzKeyboardKernel.__callback]) {
             LzKeyboardKernel.__scope[LzKeyboardKernel.__callback](delta, k, 'on' + t);
         } 
@@ -86,6 +86,32 @@
         this.__scope = scope;
         this.__callback = keyboardcallback;
     }    
+    // Called by lz.embed when the browser window regains focus
+    ,__allKeysUp: function () {
+        var delta = {};
+        var stuck = false;
+        var keys;
+        var dh = LzKeyboardKernel.__downKeysHash;
+        for (var key in dh) {
+          if (dh[key] != null) {
+            stuck = true;
+            delta[key] = false;
+            if (key.length == 1) {
+              if (! keys) { keys = []; }
+              keys.push(dh[key]);
+            }
+          }
+        }
+//         Debug.info("[%6.2f] All keys up: %w, %w", (new Date).getTime() % 1000000, delta, keys);
+        if (stuck && LzKeyboardKernel.__scope && LzKeyboardKernel.__scope[LzKeyboardKernel.__callback]) {
+          if (!keys) {
+            LzKeyboardKernel.__scope[LzKeyboardKernel.__callback](delta, 0, 'onkeyup');
+          } else for (var i = 0, l = keys.length; i < l; i++) {
+            LzKeyboardKernel.__scope[LzKeyboardKernel.__callback](delta, keys[i], 'onkeyup');
+          }
+        }
+        LzKeyboardKernel.__downKeysHash = {};
+    }
     ,setKeyboardControl: function (dhtmlKeyboardControl) {
         var handler = null;
         var setcontrol = (lz && lz.embed && lz.embed.options && lz.embed.options.cancelkeyboardcontrol != true) || true;

Modified: openlaszlo/branches/4.2/WEB-INF/lps/lfc/kernel/swf/LzKeyboardKernel.as
===================================================================
--- openlaszlo/branches/4.2/WEB-INF/lps/lfc/kernel/swf/LzKeyboardKernel.as	2009-06-10 20:18:11 UTC (rev 14111)
+++ openlaszlo/branches/4.2/WEB-INF/lps/lfc/kernel/swf/LzKeyboardKernel.as	2009-06-10 21:01:41 UTC (rev 14112)
@@ -1,7 +1,7 @@
 /**
   * LzKeyboardKernel.as
   *
-  * @copyright Copyright 2001-2008 Laszlo Systems, Inc.  All Rights Reserved.
+  * @copyright Copyright 2001-2009 Laszlo Systems, Inc.  All Rights Reserved.
   *            Use is subject to license terms.
   *
   * @topic Kernel
@@ -28,29 +28,55 @@
         var dh = LzKeyboardKernel.__downKeysHash;
         var dirty = false;
         if (t == 'onkeyup') {
-            if (dh[s] != false) {
+            if (dh[s] != null) {
                 delta[s] = false;
                 dirty = true;
             }    
-            dh[s] = false;
+            dh[s] = null;
         } else if (t == 'onkeydown') {
-            if (dh[s] != true) {
+            if (dh[s] == null) {
                 delta[s] = true;    
                 dirty = true;
             }    
-            dh[s] = true;
+            dh[s] = k;
         }    
 
         //Debug.write('downKeysHash', t, k, dh, delta);
         if (dirty && LzKeyboardKernel.__callback) LzKeyboardKernel.__scope[LzKeyboardKernel.__callback](delta, k, t);
     }
-    ,__codes: {16: 'shift', 17: 'control'}
+    ,__codes: {16: 'shift', 17: 'control', 18: 'alt'}
     ,__callback: null
     ,__scope: null
     ,setCallback: function (scope, funcname) {
         this.__scope = scope;
         this.__callback = funcname;
     }    
+    // Called by lz.embed when the browser window regains focus
+    ,__allKeysUp: function () {
+        var delta = {};
+        var stuck = false;
+        var keys;
+        var dh = LzKeyboardKernel.__downKeysHash;
+        for (var key in dh) {
+          if (dh[key] != null) {
+            stuck = true;
+            delta[key] = false;
+            if (key.length == 1) {
+              if (! keys) { keys = []; }
+              keys.push(dh[key]);
+            }
+          }
+        }
+//         Debug.info("[%6.2f] All keys up: %w, %w", (new Date).getTime() % 1000000, delta, keys);
+        if (stuck && LzKeyboardKernel.__scope && LzKeyboardKernel.__scope[LzKeyboardKernel.__callback]) {
+          if (!keys) {
+            LzKeyboardKernel.__scope[LzKeyboardKernel.__callback](delta, 0, 'onkeyup');
+          } else for (var i = 0, l = keys.length; i < l; i++) {
+            LzKeyboardKernel.__scope[LzKeyboardKernel.__callback](delta, keys[i], 'onkeyup');
+          }
+        }
+        LzKeyboardKernel.__downKeysHash = {};
+    }
     // Called by lz.Keys when the last focusable element was reached.
     ,gotLastFocus: function () {
     }

Modified: openlaszlo/branches/4.2/WEB-INF/lps/lfc/kernel/swf9/LzKeyboardKernel.as
===================================================================
--- openlaszlo/branches/4.2/WEB-INF/lps/lfc/kernel/swf9/LzKeyboardKernel.as	2009-06-10 20:18:11 UTC (rev 14111)
+++ openlaszlo/branches/4.2/WEB-INF/lps/lfc/kernel/swf9/LzKeyboardKernel.as	2009-06-10 21:01:41 UTC (rev 14112)
@@ -1,7 +1,7 @@
 /**
   * LzKeyboardKernel.lzs
   *
-  * @copyright Copyright 2001-2008 Laszlo Systems, Inc.  All Rights Reserved.
+  * @copyright Copyright 2001-2009 Laszlo Systems, Inc.  All Rights Reserved.
   *            Use is subject to license terms.
   *
   * @topic Kernel
@@ -18,8 +18,8 @@
         s = String.fromCharCode(k).toLowerCase();
 
         // prevent duplicate onkeydown events - see LPP-7432 
-        if (__keyState[k] == keyisdown) return;
-        __keyState[k] = keyisdown;
+        if ((__keyState[k] != null) == keyisdown) return;
+        __keyState[k] = keyisdown?k:null;
         
         delta[s] = keyisdown;
         if (this.__callback) this.__scope[this.__callback](delta, k, t);
@@ -33,6 +33,31 @@
         this.__scope = scope;
         this.__callback = funcname;
     }    
+
+    // Called by lz.embed when the browser window regains focus
+    function __allKeysUp () {
+        var delta = {};
+        var stuck = false;
+        var keys;
+        for (var key in __keyState) {
+          if (__keyState[key] != null) {
+            stuck = true;
+            delta[key] = false;
+            if (! keys) { keys = []; }
+            keys.push(__keyState[key]);
+          }
+        }
+//         Debug.info("[%6.2f] All keys up: %w", (new Date).getTime() % 1000000, delta);
+        if (stuck && LzKeyboardKernel.__scope && LzKeyboardKernel.__scope[LzKeyboardKernel.__callback]) {
+          if (!keys) {
+            LzKeyboardKernel.__scope[LzKeyboardKernel.__callback](delta, 0, 'onkeyup');
+          } else for (var i = 0, l = keys.length; i < l; i++) {
+            LzKeyboardKernel.__scope[LzKeyboardKernel.__callback](delta, keys[i], 'onkeyup');
+          }
+        }
+        __keyState = {};
+    }
+
     // Called by lz.Keys when the last focusable element was reached.
     function gotLastFocus() {
     }

Modified: openlaszlo/branches/4.2/WEB-INF/lps/lfc/services/LzKeys.lzs
===================================================================
--- openlaszlo/branches/4.2/WEB-INF/lps/lfc/services/LzKeys.lzs	2009-06-10 20:18:11 UTC (rev 14111)
+++ openlaszlo/branches/4.2/WEB-INF/lps/lfc/services/LzKeys.lzs	2009-06-10 21:01:41 UTC (rev 14112)
@@ -1,6 +1,6 @@
 /**
   *
-  * @copyright Copyright 2001-2008 Laszlo Systems, Inc.  All Rights Reserved.
+  * @copyright Copyright 2001-2009 Laszlo Systems, Inc.  All Rights Reserved.
   *            Use is subject to license terms.
   *
   * @affects lzbrowser
@@ -51,11 +51,14 @@
 
     /** @access private */
     function LzKeysService() {
-        super();
         //    if (LzKeysService.LzKeys) {
         //      throw new Error("There can be only one LzKeys");
         //    }
+        super();
+
         if ($as3) {
+            // NOTE: [2009-06-04 ptw] Apparently handled in
+            // LFCApplication, I don't know why...
         } else {
             LzKeyboardKernel.setCallback(this, '__keyEvent');
         }
@@ -136,6 +139,14 @@
     }
 
     /**
+     * Trampoline so we can call from lz.embed
+     * @access private
+     */
+    function __allKeysUp ():void {
+      LzKeyboardKernel.__allKeysUp();
+    }
+
+    /**
      * Called whenever a key is pressed with the Flash keycode corresponding to
      * the down key.
      *

Modified: openlaszlo/branches/4.2/lps/includes/source/embednew.js
===================================================================
--- openlaszlo/branches/4.2/lps/includes/source/embednew.js	2009-06-10 20:18:11 UTC (rev 14111)
+++ openlaszlo/branches/4.2/lps/includes/source/embednew.js	2009-06-10 21:01:41 UTC (rev 14112)
@@ -136,6 +136,7 @@
             ,_getSWFDiv: lz.embed._getSWFDiv
             ,loaded: false
             ,_sendMouseWheel: lz.embed._sendMouseWheel
+            ,_sendAllKeysUp: lz.embed._sendAllKeysUpSWF
             ,_setCanvasAttributeDequeue: lz.embed._setCanvasAttributeDequeue
             ,_sendPercLoad: lz.embed._sendPercLoad
         }
@@ -244,6 +245,7 @@
             ,loaded: false
             ,setCanvasAttribute: lz.embed._setCanvasAttributeDHTML
             ,getCanvasAttribute: lz.embed._getCanvasAttributeDHTML
+            ,_sendAllKeysUp: lz.embed._sendAllKeysUpDHTML
         }
         // listen for history unless properties.history == false
         if (properties.history == false) {
@@ -642,6 +644,21 @@
         if (d != null) this.callMethod("lz.Keys.__mousewheelEvent(" + d + ")"); 
     }
     ,/** @access private */
+    _gotFocus: function() {
+        lz.embed._broadcastMethod('_sendAllKeysUp');
+    }
+    ,/** @access private */
+    _sendAllKeysUpSWF: function () {
+        this.callMethod("lz.Keys.__allKeysUp()");
+    }
+    ,/** @access private */
+    _sendAllKeysUpDHTML: function () {
+        // How to deal with multiple DHTML apps on a page?
+        if (LzKeyboardKernel && LzKeyboardKernel['__allKeysUp']) {
+            LzKeyboardKernel.__allKeysUp();
+        }
+    }
+    ,/** @access private */
     _sendPercLoad: function(p) {
         //alert('onpercload' + p);
         if (this.onloadstatus && typeof this.onloadstatus == 'function') {
@@ -765,6 +782,12 @@
 // Clean up global handlers
 lz.embed.attachEventHandler(window, 'beforeunload', lz.embed, '_cleanupHandlers');
 
+// Notice that you got focus
+lz.embed.attachEventHandler(window, 'focus', lz.embed, '_gotFocus');
+if (lz.embed.browser.isIE) {
+  lz.embed.attachEventHandler(window, 'activate', lz.embed, '_gotFocus');
+}
+
 // for backward compatibility
 #pragma "passThrough=true"
 try {



More information about the Laszlo-checkins mailing list