on master help sign in
Fix "dropped" frames for text updates (#224, #339) using @timthelion's insights in #350
704da02Evan Czaplicki
libraries/Native/Signal/Time.js+5−7
@@ -34,13 +34,11 @@ Elm.Native.Time.make = function(elm) {
34 return A3( Signal.lift2, F2(f), isOn, ticker );
34 return A3( Signal.lift2, F2(f), isOn, ticker );
35 }
35 }
36
36
37− function everyWhen(t, isOn) {
37+ function every(t) {
38 var clock = Signal.constant(Date.now());
38 var clock = Signal.constant(Date.now());
39− var id = setInterval(function tellTime() {
39+ setInterval(function() {
40− if (!elm.notify(clock.id, Date.now())) {
40+ elm.notify(clock.id, Date.now());
41− clearInterval(id);
42− }
43− }, t);
41+ }, t);
44 return clock;
42 return clock;
45 }
43 }
46
44
@@ -56,7 +54,7 @@ Elm.Native.Time.make = function(elm) {
56 return elm.Native.Time.values = {
54 return elm.Native.Time.values = {
57 fpsWhen : F2(fpsWhen),
55 fpsWhen : F2(fpsWhen),
58 fps : function(t) { return fpsWhen(t, Signal.constant(true)); },
56 fps : function(t) { return fpsWhen(t, Signal.constant(true)); },
59− every : function(t) { return everyWhen(t, Signal.constant(true)) },
57+ every : every,
60 delay : NS.delay,
58 delay : NS.delay,
61 timestamp : NS.timestamp,
59 timestamp : NS.timestamp,
62 since : F2(since),
60 since : F2(since),
libraries/Native/Signal/Window.js+12−1
@@ -28,10 +28,21 @@ Elm.Native.Window.make = function(elm) {
28 height.defaultNumberOfKids = 0;
28 height.defaultNumberOfKids = 0;
29
29
30 function resizeIfNeeded() {
30 function resizeIfNeeded() {
31+ // Do not trigger event if the dimensions have not changed.
32+ // This should be most of the time.
31 var w = getWidth();
33 var w = getWidth();
32 var h = getHeight();
34 var h = getHeight();
33 if (dimensions.value._0 === w && dimensions.value._1 === h) return;
35 if (dimensions.value._0 === w && dimensions.value._1 === h) return;
36+
37+ setTimeout(function () {
38+ // Check again to see if the dimensions have changed.
39+ // It is conceivable that the dimensions have changed
40+ // again while some other event was being processed.
41+ var w = getWidth();
42+ var h = getHeight();
43+ if (dimensions.value._0 === w && dimensions.value._1 === h) return;
34− elm.notify(dimensions.id, Tuple2(w,h));
44+ elm.notify(dimensions.id, Tuple2(w,h));
45+ }, 0);
35 }
46 }
36 elm.addListener([dimensions.id], window, 'resize', resizeIfNeeded);
47 elm.addListener([dimensions.id], window, 'resize', resizeIfNeeded);
37
48
runtime/Init.js+10−4
@@ -31,14 +31,20 @@ function init(display, container, module, moduleToReplace) {
31 // defining state needed for an instance of the Elm RTS
31 // defining state needed for an instance of the Elm RTS
32 var inputs = [];
32 var inputs = [];
33
33
34+ var updateInProgress = false;
34 function notify(id, v) {
35 function notify(id, v) {
36+ if (updateInProgress) {
37+ throw new Error(
38+ 'The notify function has been called synchronously!\n' +
39+ 'This can lead to frames being dropped.\n' +
40+ 'Definitely report this to <https://github.com/evancz/Elm/issues>\n');
41+ }
42+ updateInProgress = true;
35 var timestep = Date.now();
43 var timestep = Date.now();
36− var changed = false;
37 for (var i = inputs.length; i--; ) {
44 for (var i = inputs.length; i--; ) {
38− // order is important here to avoid short-circuiting
39− changed = inputs[i].recv(timestep, id, v) || changed;
45+ inputs[i].recv(timestep, id, v);
40 }
46 }
41− return changed;
47+ updateInProgress = false;
42 }
48 }
43
49
44 var listeners = [];
50 var listeners = [];