@@ -17,27 +17,36 @@ Elm.Native.Keyboard.make = function(elm) {
1717 var NList = Elm.Native.List.make(elm);
1818 var Utils = Elm.Native.Utils.make(elm);
1919
20− var downEvents = Signal.constant(0);
21− var upEvents = Signal.constant(0);
22− var blurEvents = Signal.constant(0);
20+ var downEvents = Signal.constant(null);
21+ var upEvents = Signal.constant(null);
22+ var blurEvents = Signal.constant(null);
2323
2424 elm.addListener([downEvents.id], document, 'keydown', function down(e) {
25− elm.notify(downEvents.id, e.keyCode);
25+ elm.notify(downEvents.id, e);
2626 });
2727
2828 elm.addListener([upEvents.id], document, 'keyup', function up(e) {
29− elm.notify(upEvents.id, e.keyCode);
29+ elm.notify(upEvents.id, e);
3030 });
3131
3232 elm.addListener([blurEvents.id], document, 'blur', function blur(e) {
33− elm.notify(blurEvents.id, NList.Nil);
33+ elm.notify(blurEvents.id, null);
3434 });
3535
36+ function state(alt, meta, keyCodes) {
37+ return {
38+ alt: alt,
39+ meta: meta,
40+ keyCodes: keyCodes
41+ };
42+ }
43+ var emptyState = state(false, false, NList.Nil);
44+
3645 function KeyMerge(down, up, blur) {
3746 var args = [down,up,blur];
3847 this.id = Utils.guid();
3948 // Ignore starting values here
40− this.value = NList.Nil
49+ this.value = emptyState;
4150 this.kids = [];
4251
4352 var n = args.length;
@@ -48,18 +57,22 @@ Elm.Native.Keyboard.make = function(elm) {
4857 ++count;
4958 if (changed) {
5059 // We know this a change must only be one of the following cases
51− if (parentID === down.id && !A2(NList.member, down.value, this.value)) {
60+ if (parentID === down.id && !A2(NList.member, down.value.keyCode, this.value.keyCodes)) {
5261 isChanged = true;
53− this.value = NList.Cons(down.value, this.value);
62+ var v = down.value;
63+ var newCodes = NList.Cons(v.keyCode, this.value.keyCodes);
64+ this.value = state(v.altKey, v.metaKey, newCodes);
5465 }
5566 else if (parentID === up.id) {
5667 isChanged = true;
57− var notEq = function(kc) { return kc !== up.value };
58− this.value = A2(NList.filter, notEq, this.value);
68+ var v = up.value;
69+ var notEq = function(kc) { return kc !== v.keyCode };
70+ var newCodes = A2(NList.filter, notEq, this.value.keyCodes);
71+ this.value = state(v.altKey, v.metaKey, newCodes);
5972 }
6073 else if (parentID === blur.id) {
6174 isChanged = true;
62− this.value = NList.Nil;
75+ this.value = emptyState;
6376 }
6477 }
6578 if (count == n) {
@@ -71,45 +84,65 @@ Elm.Native.Keyboard.make = function(elm) {
7184
7285 for (var i = n; i--; ) {
7386 args[i].kids.push(this);
87+ args[i].defaultNumberOfKids += 1;
7488 }
7589 }
7690
77− var keysDown = Signal.dropRepeats(new KeyMerge(downEvents,upEvents,blurEvents));
91+ var keyMerge = new KeyMerge(downEvents,upEvents,blurEvents);
7892
93+ // select a part of a keyMerge and dropRepeats the result
7994 function keySignal(f) {
80− var signal = A2(Signal.lift, f, keysDown);
95+ var signal = A2(Signal.lift, f, keyMerge);
8196 // must set the default number of kids to make it possible to filter
8297 // these signals if they are not actually used.
83− keysDown.defaultNumberOfKids += 1;
98+ keyMerge.defaultNumberOfKids += 1;
8499 signal.defaultNumberOfKids = 1;
85− var filtered = Signal.dropRepeats(signal)
100+ var filtered = Signal.dropRepeats(signal);
86101 filtered.defaultNumberOfKids = 0;
87102 return filtered;
88103 }
89104
105+ // break keyMerge into parts
106+ var keysDown = keySignal(function getKeyCodes(v) {
107+ return v.keyCodes;
108+ });
109+ var alt = keySignal(function getKeyCodes(v) {
110+ return v.alt;
111+ });
112+ var meta = keySignal(function getKeyCodes(v) {
113+ return v.meta;
114+ });
115+
90116 function dir(up, down, left, right) {
91− function f(ks) {
117+ function toDirections(state) {
118+ var keyCodes = state.keyCodes;
92119 var x = 0, y = 0;
93− while (ks.ctor === "::") {
94− switch (ks._0) {
120+ while (keyCodes.ctor === "::") {
121+ switch (keyCodes._0) {
95122 case left : --x; break;
96123 case right: ++x; break;
97124 case up : ++y; break;
98125 case down : --y; break;
99126 }
100− ks = ks._1;
127+ keyCodes = keyCodes._1;
101128 }
102129 return { _:{}, x:x, y:y };
103130 }
104− return keySignal(f);
131+ return keySignal(toDirections);
105132 }
106133
107− function is(key) { return keySignal(NList.member(key)); }
134+ function is(key) {
135+ return keySignal(function(v) {
136+ return A2( NList.member, key, v.keyCodes );
137+ });
138+ }
108139
109140 var lastPressed = downEvents;
110141
111142 return elm.Native.Keyboard.values = {
112143 isDown:is,
144+ alt: alt,
145+ meta: meta,
113146 directions:F4(dir),
114147 keysDown:keysDown,
115148 lastPressed:lastPressed