[Laszlo-checkins] r14129 - in openlaszlo/trunk: . 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
Fri Jun 12 14:58:04 PDT 2009


Author: ptw
Date: 2009-06-12 14:58:00 -0700 (Fri, 12 Jun 2009)
New Revision: 14129

Modified:
   openlaszlo/trunk/
   openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzKeyboardKernel.js
   openlaszlo/trunk/WEB-INF/lps/lfc/kernel/swf/LzKeyboardKernel.as
   openlaszlo/trunk/WEB-INF/lps/lfc/kernel/swf9/LzKeyboardKernel.as
   openlaszlo/trunk/WEB-INF/lps/lfc/services/LzKeys.lzs
   openlaszlo/trunk/lps/includes/source/embednew.js
Log:
Merged revisions 14112 via svnmerge from 
http://svn.openlaszlo.org/openlaszlo/branches/4.2

.......
  r14112 | ptw | 2009-06-10 17:01:41 -0400 (Wed, 10 Jun 2009) | 30 lines
  
  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
.......



Property changes on: openlaszlo/trunk
___________________________________________________________________
Name: svnmerge-integrated
   - /openlaszlo/branches/4.1:1-10153 /openlaszlo/branches/4.2:1-12154,12181,13205,13778 /openlaszlo/branches/4.4:1-13936,14007 /openlaszlo/branches/devildog:1-8432 /openlaszlo/branches/pagan-deities:1-7955,8825,10756-10920,10922-10928,10930-10935,11151,11207,11554,13476,13629 /openlaszlo/branches/paperpie:1-6504,6506-6574,6576-7135,7137-7235 /openlaszlo/branches/wafflecone:1-5746,5818-6068,6070-6205,6207-6213,6216-6265,6267-6368,6370-6431,6433-6450,6497,6509,6661,7097,7872 /openlaszlo/trunk:1-3892,3894-3952,3954-4393,4395-4461,4463-4467,4469-4471,4473-5085,5087-5171,5173-5203,5205-5209,5211-5331,5333-5334
   + /openlaszlo/branches/4.1:1-10153 /openlaszlo/branches/4.2:1-12154,12181,13205,13778,14112 /openlaszlo/branches/4.4:1-13936,14007 /openlaszlo/branches/devildog:1-8432 /openlaszlo/branches/pagan-deities:1-7955,8825,10756-10920,10922-10928,10930-10935,11151,11207,11554,13476,13629 /openlaszlo/branches/paperpie:1-6504,6506-6574,6576-7135,7137-7235 /openlaszlo/branches/wafflecone:1-5746,5818-6068,6070-6205,6207-6213,6216-6265,6267-6368,6370-6431,6433-6450,6497,6509,6661,7097,7872 /openlaszlo/trunk:1-3892,3894-3952,3954-4393,4395-4461,4463-4467,4469-4471,4473-5085,5087-5171,5173-5203,5205-5209,5211-5331,5333-5334

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzKeyboardKernel.js
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzKeyboardKernel.js	2009-06-12 19:35:15 UTC (rev 14128)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzKeyboardKernel.js	2009-06-12 21:58:00 UTC (rev 14129)
@@ -11,8 +11,8 @@
 
 // Receives keyboard events from the runtime
 var LzKeyboardKernel = {
-    __downKeysHash: {alt: false, control: false, shift: false, meta: false}
-    ,__keyCodes: {}
+    // Key is the character (or a name for shift keys), value is the keycode
+    __downKeysHash: {}
     ,__keyboardEvent: function ( e ){
         if (!e) e = window.event;
         var delta = {};
@@ -25,19 +25,18 @@
         if (k >= 0 && k != 16 && k != 17 && k != 18 && k != 224) {
             // TODO: add mapping to flash character codes?
             var s = String.fromCharCode(k).toLowerCase();
-            LzKeyboardKernel.__keyCodes[s] = k;
             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;
             }
         }
 
@@ -59,7 +58,8 @@
                 //Debug.write('canceling tab');
                 e.cancelBubble = true;
                 return false;
-            } else if (LzKeyboardKernel.__cancelKeys && (k == 13 || k == 0 || k == 37 || k == 38 || k == 39 || k == 40) ) {
+            } else if (LzKeyboardKernel.__cancelKeys &&
+                       (k == 13 || k == 0 || k == 37 || k == 38 || k == 39 || k == 40) ) {
                 //Debug.write('canceling key', k, t);
                 // cancel event bubbling for enter, space(scroll) and arrow keys
                 e.cancelBubble = true;
@@ -80,68 +80,84 @@
             var send = true;
         }
         var alt = e['altKey'];
-        if (dh['alt'] != alt) {
+        if ((dh['alt'] != null) != alt) {
+            dh['alt'] = alt?18:null;
             delta['alt'] = alt;
-            dirty = true;
+            dirty = send;
             if (quirks['alt_key_sends_control']) {
                 delta['control'] = delta['alt'];
             }
         }
+
         var ctrl = e['ctrlKey'];
-        if (dh['control'] != ctrl) {
+        if ((dh['control'] != null) != ctrl) {
+            dh['control'] = ctrl?17:null;
             delta['control'] = ctrl;
-            dirty = true;
+            dirty = send;
         }
+
         var shift = e['shiftKey'];
-        if (dh['shift'] != shift) {
+        if ((dh['shift'] != null) != shift) {
+            dh['shift'] = shift?16:null;
             delta['shift'] = shift;
-            dirty = true;
+            dirty = send;
         }
-        var stuck;
+    
         var meta = e['metaKey'];
-        if (quirks['detectstuckkeys']) {
-            // see LPP-8210
-            if (dh['meta'] != meta) {
-                // look for stuck keys
-                delta['control'] = meta;
-                dirty = true;
+        if ((dh['meta'] != null) != meta) {
+            dh['meta'] = meta?224:null;
+            delta['meta'] = meta;
+            dirty = send;
+            // Is this a quirk?
+            delta['control'] = meta;
+            // look for stuck keys (see LPP-8210)
+            if (quirks['detectstuckkeys']) {
                 if (! meta) {
-                    for (var key in dh) {
-                        if (key == 'control' || key == 'shift' || key == 'alt' || key == 'meta') continue;
-                        stuck = key;
-                        delete dh[key];
-                    }
+                    // If meta goes up, clear all the other keys
+                    LzKeyboardKernel.__allKeysUp();
+                    dirty = false;
                 }
-            }
+              }
         }
 
-        dh['alt'] = alt;
-        dh['control'] = ctrl;
-        dh['shift'] = shift;
-        dh['meta'] = meta;
-
-        if (dirty && (send || stuck)) {
+        if (dirty) {
             var scope = LzKeyboardKernel.__scope;
             var callback = LzKeyboardKernel.__callback;
             if (scope && scope[callback]) {
-                //console.log(t, s, k, delta, e.metaKey, e.ctrlKey, dh);
-                if (stuck) {
-                    // console.log('stuck key', key, keycode);
-                    var keycode = LzKeyboardKernel.__keyCodes[stuck];
-                    var fakedelta = {};
-                    // FIXME: [20090602 anba] 'key' seems to be a typo, should it be 'stuck'?
-                    fakedelta[key] = false;
-                    scope[callback](fakedelta, keycode, 'onkeyup');
-                }
-
-                if (send) {
-                    scope[callback](delta, 0, 'on' + e.type);
-                }
+                scope[callback](delta, 0, 'on' + e.type);
             }
         }
 
         return dirty;
     }
+    // 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);
+        var scope = LzKeyboardKernel.__scope;
+        var callback = LzKeyboardKernel.__callback;
+        if (stuck && scope && scope[callback]) {
+          if (!keys) {
+            scope[callback](delta, 0, 'onkeyup');
+          } else for (var i = 0, l = keys.length; i < l; i++) {
+            scope[callback](delta, keys[i], 'onkeyup');
+          }
+        }
+        LzKeyboardKernel.__downKeysHash = {};
+    }
     ,__callback: null
     ,__scope: null
     ,__cancelKeys: true

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/kernel/swf/LzKeyboardKernel.as
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/kernel/swf/LzKeyboardKernel.as	2009-06-12 19:35:15 UTC (rev 14128)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/kernel/swf/LzKeyboardKernel.as	2009-06-12 21:58:00 UTC (rev 14129)
@@ -37,17 +37,17 @@
         //Debug.info("__keyboardEvent k=%w s=%w %w ctrl=%w, delta=%w", k,s,t, ctrl,delta);
 
         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);
@@ -55,13 +55,41 @@
             LzKeyboardKernel.__scope[LzKeyboardKernel.__callback](delta, k, t, ctrl);
         }
     }
-    ,__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);
+        var scope = LzKeyboardKernel.__scope;
+        var callback = LzKeyboardKernel.__callback;
+        if (stuck && scope && scope[callback]) {
+          if (!keys) {
+            scope[callback](delta, 0, 'onkeyup');
+          } else for (var i = 0, l = keys.length; i < l; i++) {
+            scope[callback](delta, keys[i], 'onkeyup');
+          }
+        }
+        LzKeyboardKernel.__downKeysHash = {};
+    }
     // Called by lz.Keys when the last focusable element was reached.
     ,gotLastFocus: function () {
     }

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/kernel/swf9/LzKeyboardKernel.as
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/kernel/swf9/LzKeyboardKernel.as	2009-06-12 19:35:15 UTC (rev 14128)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/kernel/swf9/LzKeyboardKernel.as	2009-06-12 21:58:00 UTC (rev 14129)
@@ -23,8 +23,8 @@
 
 
         // 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;
         var ctrl:Boolean = e.ctrlKey;
@@ -49,6 +49,30 @@
         }
     }    
 
+    // Called by lz.embed when the browser window regains focus
+    static 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 && __scope && __scope[__callback]) {
+          if (!keys) {
+            __scope[__callback](delta, 0, 'onkeyup');
+          } else for (var i = 0, l = keys.length; i < l; i++) {
+            __scope[__callback](delta, keys[i], 'onkeyup');
+          }
+        }
+        __keyState = {};
+    }
+
     // Called by lz.Keys when the last focusable element was reached.
     static function gotLastFocus() :void {
     }

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/services/LzKeys.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/services/LzKeys.lzs	2009-06-12 19:35:15 UTC (rev 14128)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/services/LzKeys.lzs	2009-06-12 21:58:00 UTC (rev 14129)
@@ -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');
         }
@@ -143,6 +146,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/trunk/lps/includes/source/embednew.js
===================================================================
--- openlaszlo/trunk/lps/includes/source/embednew.js	2009-06-12 19:35:15 UTC (rev 14128)
+++ openlaszlo/trunk/lps/includes/source/embednew.js	2009-06-12 21:58:00 UTC (rev 14129)
@@ -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
         }
@@ -254,6 +255,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) {
@@ -682,6 +684,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') {
@@ -855,6 +872,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