From 421beefe67754eef3f308b7558c0c569be9ca76b Mon Sep 17 00:00:00 2001
From: David Partouche <david@manateedev.com>
Date: Sat, 11 Oct 2014 12:02:25 +0200
Subject: [PATCH 1/7] Added mose move event

---
 src/osx/mod.rs | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/src/osx/mod.rs b/src/osx/mod.rs
index 0510006e..5538fb78 100644
--- a/src/osx/mod.rs
+++ b/src/osx/mod.rs
@@ -14,6 +14,7 @@ use core_foundation::string::CFString;
 use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
 
 pub struct Window {
+    view: id,
     context: id,
 }
 
@@ -86,6 +87,7 @@ impl Window {
         }
 
         let window = Window {
+            view: view,
             context: context,
         };
 
@@ -123,6 +125,7 @@ impl Window {
                 let title = NSString::alloc(nil).init_str(title);
                 window.setTitle_(title);
                 window.center();
+                window.setAcceptsMouseMovedEvents_(true);
                 Some(window)
             }
         }
@@ -202,7 +205,7 @@ impl Window {
 
         loop {
             unsafe {
-                use {MouseInput, Pressed, Released, LeftMouseButton, RightMouseButton};
+                use {MouseInput, Pressed, Released, LeftMouseButton, RightMouseButton, MouseMoved};
                 let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                     NSAnyEventMask as u64,
                     NSDate::distantPast(nil),
@@ -215,7 +218,11 @@ impl Window {
                     NSLeftMouseUp           => { events.push(MouseInput(Released, LeftMouseButton)); },
                     NSRightMouseDown        => { events.push(MouseInput(Pressed, RightMouseButton)); },
                     NSRightMouseUp          => { events.push(MouseInput(Released, RightMouseButton)); },
-                    NSMouseMoved            => { },
+                    NSMouseMoved            => {
+                        let window_point = event.locationInWindow();
+                        let view_point = self.view.convertPoint_fromView_(window_point, nil);
+                        events.push(MouseMoved((view_point.x as int, view_point.y as int)));
+                    },
                     NSKeyDown               => { },
                     NSKeyUp                 => { },
                     NSFlagsChanged          => { },
@@ -236,8 +243,8 @@ impl Window {
                 NSAnyEventMask as u64,
                 NSDate::distantFuture(nil),
                 NSDefaultRunLoopMode,
-                true);
-            NSApp().sendEvent_(event);
+                false);
+
             self.poll_events()
         }
     }

From ba8f55547f18e7fa01d29d945b961476ea1658e0 Mon Sep 17 00:00:00 2001
From: David Partouche <david@manateedev.com>
Date: Sat, 11 Oct 2014 22:37:31 +0200
Subject: [PATCH 2/7] Added is_closed to osx window

---
 src/osx/mod.rs | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/osx/mod.rs b/src/osx/mod.rs
index 5538fb78..d194c219 100644
--- a/src/osx/mod.rs
+++ b/src/osx/mod.rs
@@ -1,4 +1,5 @@
 use Event;
+use std::sync::atomics::AtomicBool;
 
 #[cfg(feature = "window")]
 use WindowBuilder;
@@ -14,8 +15,10 @@ use core_foundation::string::CFString;
 use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
 
 pub struct Window {
+    window: id,
     view: id,
     context: id,
+    is_closed: AtomicBool,
 }
 
 pub struct HeadlessContext(Window);
@@ -87,8 +90,10 @@ impl Window {
         }
 
         let window = Window {
+            window: window,
             view: view,
             context: context,
+            is_closed: AtomicBool::new(false),
         };
 
         Ok(window)
@@ -172,8 +177,8 @@ impl Window {
     }
 
     pub fn is_closed(&self) -> bool {
-        // TODO: remove fake implementation
-        false
+        use std::sync::atomics::Relaxed;
+        self.is_closed.load(Relaxed)
     }
 
     pub fn set_title(&self, _title: &str) {
@@ -212,6 +217,7 @@ impl Window {
                     NSDefaultRunLoopMode,
                     true);
                 if event == nil { break; }
+                NSApp().sendEvent_(event);
 
                 match event.get_type() {
                     NSLeftMouseDown         => { events.push(MouseInput(Pressed, LeftMouseButton)); },
@@ -244,6 +250,7 @@ impl Window {
                 NSDate::distantFuture(nil),
                 NSDefaultRunLoopMode,
                 false);
+            NSApp().sendEvent_(event);
 
             self.poll_events()
         }

From dad539114dbbc4717611ce92d8422b2f5127a597 Mon Sep 17 00:00:00 2001
From: David Partouche <david@manateedev.com>
Date: Sun, 12 Oct 2014 20:16:42 +0200
Subject: [PATCH 3/7] Added ReceivedCharacter event for cocoa

---
 src/osx/mod.rs | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/osx/mod.rs b/src/osx/mod.rs
index d194c219..7d17aac0 100644
--- a/src/osx/mod.rs
+++ b/src/osx/mod.rs
@@ -14,6 +14,8 @@ use core_foundation::base::TCFType;
 use core_foundation::string::CFString;
 use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
 
+use std::c_str::CString;
+
 pub struct Window {
     window: id,
     view: id,
@@ -210,7 +212,7 @@ impl Window {
 
         loop {
             unsafe {
-                use {MouseInput, Pressed, Released, LeftMouseButton, RightMouseButton, MouseMoved};
+                use {MouseInput, Pressed, Released, LeftMouseButton, RightMouseButton, MouseMoved, ReceivedCharacter};
                 let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                     NSAnyEventMask as u64,
                     NSDate::distantPast(nil),
@@ -229,7 +231,13 @@ impl Window {
                         let view_point = self.view.convertPoint_fromView_(window_point, nil);
                         events.push(MouseMoved((view_point.x as int, view_point.y as int)));
                     },
-                    NSKeyDown               => { },
+                    NSKeyDown               => {
+                        let received_cstr = CString::new(event.characters().UTF8String(), false);
+                        match received_cstr.as_str() {
+                            Some(received_str) => { events.push(ReceivedCharacter(received_str.char_at(0))); },
+                            None               => { },
+                        };
+                    },
                     NSKeyUp                 => { },
                     NSFlagsChanged          => { },
                     NSScrollWheel           => { },

From 86e8480550b0a61d80ec828c57dac06ddb5c540a Mon Sep 17 00:00:00 2001
From: David Partouche <david@manateedev.com>
Date: Wed, 15 Oct 2014 11:49:10 +0200
Subject: [PATCH 4/7] Added the KeyPress and KeyRelease events

---
 src/events.rs    |   2 +-
 src/osx/event.rs | 156 +++++++++++++++++++++++++++++++++++++++++++++++
 src/osx/mod.rs   |  33 +++++++---
 3 files changed, 180 insertions(+), 11 deletions(-)
 create mode 100644 src/osx/event.rs

diff --git a/src/events.rs b/src/events.rs
index f28fb594..1b46e105 100644
--- a/src/events.rs
+++ b/src/events.rs
@@ -128,7 +128,7 @@ pub enum VirtualKeyCode {
     Kana,
     Kanji,
     L,
-    LCracket,
+    LBracket,
     LControl,
     Left,
     LMenu,
diff --git a/src/osx/event.rs b/src/osx/event.rs
new file mode 100644
index 00000000..a4128a45
--- /dev/null
+++ b/src/osx/event.rs
@@ -0,0 +1,156 @@
+use events;
+use events::KeyModifiers;
+use cocoa::base::NSUInteger;
+use cocoa::appkit;
+
+pub fn modifierflag_to_element(flag: NSUInteger) -> KeyModifiers {
+    let mut modifiers = KeyModifiers::empty();
+    if flag & appkit::NSShiftKeyMask as u64 == appkit::NSShiftKeyMask as u64 {
+        modifiers = modifiers | events::LEFT_SHIFT_MODIFIER;
+    }
+    if flag & appkit::NSControlKeyMask as u64 == appkit::NSControlKeyMask as u64 {
+        modifiers = modifiers | events::LEFT_CONTROL_MODIFIER;
+    }
+    if flag & appkit::NSAlternateKeyMask as u64 == appkit::NSAlternateKeyMask as u64 {
+        modifiers = modifiers | events::LEFT_ALT_MODIFIER;
+    }
+    if flag & appkit::NSNumericPadKeyMask as u64 == appkit::NSNumericPadKeyMask as u64 {
+        modifiers = modifiers | events::NUM_LOCK_MODIFIER;
+    }
+    modifiers
+}
+
+pub fn vkeycode_to_element(code: u16) -> Option<events::VirtualKeyCode> {
+    Some(match code {
+        0x00 => events::A,
+        0x01 => events::S,
+        0x02 => events::D,
+        0x03 => events::F,
+        0x04 => events::H,
+        0x05 => events::G,
+        0x06 => events::Z,
+        0x07 => events::X,
+        0x08 => events::C,
+        0x09 => events::V,
+        //0x0a => World 1,
+        0x0b => events::B,
+        0x0c => events::Q,
+        0x0d => events::W,
+        0x0e => events::E,
+        0x0f => events::R,
+        0x10 => events::Y,
+        0x11 => events::T,
+        0x12 => events::Key1,
+        0x13 => events::Key2,
+        0x14 => events::Key3,
+        0x15 => events::Key4,
+        0x16 => events::Key6,
+        0x17 => events::Key5,
+        0x18 => events::Equals,
+        0x19 => events::Key9,
+        0x1a => events::Key7,
+        0x1b => events::Minus,
+        0x1c => events::Key8,
+        0x1d => events::Key0,
+        0x1e => events::RBracket,
+        0x1f => events::O,
+        0x20 => events::U,
+        0x21 => events::LBracket,
+        0x22 => events::I,
+        0x23 => events::P,
+        0x24 => events::Return,
+        0x25 => events::L,
+        0x26 => events::J,
+        0x27 => events::Apostrophe,
+        0x28 => events::K,
+        0x29 => events::Semicolon,
+        0x2a => events::Backslash,
+        0x2b => events::Comma,
+        0x2c => events::Slash,
+        0x2d => events::N,
+        0x2e => events::M,
+        0x2f => events::Period,
+        0x30 => events::Tab,
+        0x31 => events::Space,
+        0x32 => events::Grave,
+        0x33 => events::Back,
+        //0x34 => unkown,
+        0x35 => events::Escape,
+        0x36 => events::RWin,
+        0x37 => events::LWin,
+        0x38 => events::LShift,
+        //0x39 => Caps lock,
+        //0x3a => Left alt,
+        0x3b => events::LControl,
+        0x3c => events::RShift,
+        //0x3d => Right alt,
+        0x3e => events::RControl,
+        //0x3f => Fn key,
+        //0x40 => F17 Key,
+        0x41 => events::Decimal,
+        //0x42 -> unkown,
+        0x43 => events::Multiply,
+        //0x44 => unkown,
+        0x45 => events::Add,
+        //0x46 => unkown,
+        0x47 => events::Numlock,
+        //0x48 => KeypadClear,
+        0x49 => events::VolumeUp,
+        0x4a => events::VolumeDown,
+        0x4b => events::Divide,
+        0x4c => events::NumpadEnter,
+        //0x4d => unkown,
+        0x4e => events::Subtract,
+        //0x4f => F18 key,
+        //0x50 => F19 Key,
+        0x51 => events::NumpadEquals,
+        0x52 => events::Numpad0,
+        0x53 => events::Numpad1,
+        0x54 => events::Numpad2,
+        0x55 => events::Numpad3,
+        0x56 => events::Numpad4,
+        0x57 => events::Numpad5,
+        0x58 => events::Numpad6,
+        0x59 => events::Numpad7,
+        //0x5a => F20 Key,
+        0x5b => events::Numpad8,
+        0x5c => events::Numpad9,
+        //0x5d => unkown,
+        //0x5e => unkown,
+        //0x5f => unkown,
+        0x60 => events::F5,
+        0x61 => events::F6,
+        0x62 => events::F7,
+        0x63 => events::F3,
+        0x64 => events::F8,
+        0x65 => events::F9,
+        //0x66 => unkown,
+        0x67 => events::F11,
+        //0x68 => unkown,
+        0x69 => events::F13,
+        //0x6a => F16 Key,
+        0x6b => events::F14,
+        //0x6c => unkown,
+        0x6d => events::F10,
+        //0x6e => unkown,
+        0x6f => events::F12,
+        //0x70 => unkown,
+        0x71 => events::F15,
+        0x72 => events::Insert,
+        0x73 => events::Home,
+        0x74 => events::PageUp,
+        0x75 => events::Delete,
+        0x76 => events::F4,
+        0x77 => events::End,
+        0x78 => events::F2,
+        0x79 => events::PageDown,
+        0x7a => events::F1,
+        0x7b => events::Left,
+        0x7c => events::Right,
+        0x7d => events::Down,
+        0x7e => events::Up,
+        //0x7f =>  unkown,
+
+        _ => return None,
+    })
+}
diff --git a/src/osx/mod.rs b/src/osx/mod.rs
index 7d17aac0..7d4d538b 100644
--- a/src/osx/mod.rs
+++ b/src/osx/mod.rs
@@ -15,9 +15,12 @@ use core_foundation::string::CFString;
 use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
 
 use std::c_str::CString;
+use {MouseInput, Pressed, Released, LeftMouseButton, RightMouseButton, MouseMoved, ReceivedCharacter,
+     KeyboardInput};
+
+mod event;
 
 pub struct Window {
-    window: id,
     view: id,
     context: id,
     is_closed: AtomicBool,
@@ -92,7 +95,6 @@ impl Window {
         }
 
         let window = Window {
-            window: window,
             view: view,
             context: context,
             is_closed: AtomicBool::new(false),
@@ -212,7 +214,6 @@ impl Window {
 
         loop {
             unsafe {
-                use {MouseInput, Pressed, Released, LeftMouseButton, RightMouseButton, MouseMoved, ReceivedCharacter};
                 let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                     NSAnyEventMask as u64,
                     NSDate::distantPast(nil),
@@ -232,14 +233,26 @@ impl Window {
                         events.push(MouseMoved((view_point.x as int, view_point.y as int)));
                     },
                     NSKeyDown               => {
-                        let received_cstr = CString::new(event.characters().UTF8String(), false);
-                        match received_cstr.as_str() {
-                            Some(received_str) => { events.push(ReceivedCharacter(received_str.char_at(0))); },
-                            None               => { },
-                        };
+                        let received_str = CString::new(event.characters().UTF8String(), false);
+                        for received_char in received_str.as_str().unwrap().chars() {
+                            if received_char.is_ascii() {
+                                events.push(ReceivedCharacter(received_char));
+                            }
+                        }
+
+                        let vkey =  event::vkeycode_to_element(event.keycode());
+                        let modifiers = event::modifierflag_to_element(event.modifierFlags());
+                        events.push(KeyboardInput(Pressed, event.keycode() as u8, vkey, modifiers));
+                    },
+                    NSKeyUp                 => {
+                        let vkey =  event::vkeycode_to_element(event.keycode());
+                        let modifiers = event::modifierflag_to_element(event.modifierFlags());
+                        events.push(KeyboardInput(Released, event.keycode() as u8, vkey, modifiers));
+                    },
+                    NSFlagsChanged          => {
+                        println!("Modifiers: {}", event.modifierFlags());
+                        // Need to keep an array of the modified flags
                     },
-                    NSKeyUp                 => { },
-                    NSFlagsChanged          => { },
                     NSScrollWheel           => { },
                     NSOtherMouseDown        => { },
                     NSOtherMouseUp          => { },

From 271b68891002b324be04d04475a4207ce5918590 Mon Sep 17 00:00:00 2001
From: David Partouche <david@manateedev.com>
Date: Thu, 23 Oct 2014 12:28:57 +0200
Subject: [PATCH 5/7] Fixed switch from atomics to atomic in rust

---
 src/osx/mod.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/osx/mod.rs b/src/osx/mod.rs
index 7d4d538b..f1656507 100644
--- a/src/osx/mod.rs
+++ b/src/osx/mod.rs
@@ -1,5 +1,5 @@
 use Event;
-use std::sync::atomics::AtomicBool;
+use std::sync::atomic::AtomicBool;
 
 #[cfg(feature = "window")]
 use WindowBuilder;
@@ -181,7 +181,7 @@ impl Window {
     }
 
     pub fn is_closed(&self) -> bool {
-        use std::sync::atomics::Relaxed;
+        use std::sync::atomic::Relaxed;
         self.is_closed.load(Relaxed)
     }
 

From 6f46c0c2dd9eedd350dd2ea1a426c96ef6284357 Mon Sep 17 00:00:00 2001
From: David Partouche <david@manateedev.com>
Date: Thu, 23 Oct 2014 17:18:47 +0200
Subject: [PATCH 6/7] Added the modifiers key as input

---
 src/osx/mod.rs | 41 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/src/osx/mod.rs b/src/osx/mod.rs
index f1656507..abe233de 100644
--- a/src/osx/mod.rs
+++ b/src/osx/mod.rs
@@ -8,6 +8,7 @@ use WindowBuilder;
 use HeadlessRendererBuilder;
 
 use cocoa::base::{id, NSUInteger, nil};
+use cocoa::appkit;
 use cocoa::appkit::*;
 
 use core_foundation::base::TCFType;
@@ -16,10 +17,16 @@ use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFuncti
 
 use std::c_str::CString;
 use {MouseInput, Pressed, Released, LeftMouseButton, RightMouseButton, MouseMoved, ReceivedCharacter,
-     KeyboardInput};
+     KeyboardInput, KeyModifiers};
+
+use events;
 
 mod event;
 
+static mut shift_pressed: bool = false;
+static mut ctrl_pressed: bool = false;
+static mut win_pressed: bool = false;
+
 pub struct Window {
     view: id,
     context: id,
@@ -250,8 +257,21 @@ impl Window {
                         events.push(KeyboardInput(Released, event.keycode() as u8, vkey, modifiers));
                     },
                     NSFlagsChanged          => {
-                        println!("Modifiers: {}", event.modifierFlags());
-                        // Need to keep an array of the modified flags
+                        let shift_modifier = Window::modifier_event(event, appkit::NSShiftKeyMask as u64, events::LShift, shift_pressed);
+                        if shift_modifier.is_some() {
+                            shift_pressed = !shift_pressed;
+                            events.push(shift_modifier.unwrap());
+                        }
+                        let ctrl_modifier = Window::modifier_event(event, appkit::NSControlKeyMask as u64, events::LControl, ctrl_pressed);
+                        if ctrl_modifier.is_some() {
+                            ctrl_pressed = !ctrl_pressed;
+                            events.push(ctrl_modifier.unwrap());
+                        }
+                        let win_modifier = Window::modifier_event(event, appkit::NSCommandKeyMask as u64, events::LWin, win_pressed);
+                        if win_modifier.is_some() {
+                            win_pressed = !win_pressed;
+                            events.push(win_modifier.unwrap());
+                        }
                     },
                     NSScrollWheel           => { },
                     NSOtherMouseDown        => { },
@@ -264,6 +284,21 @@ impl Window {
         events
     }
 
+    unsafe fn modifier_event(event: id, keymask: u64, key: events::VirtualKeyCode, key_pressed: bool) -> Option<Event> {
+        if !key_pressed && Window::modifier_key_pressed(event, keymask) {
+            return Some(KeyboardInput(Pressed, event.keycode() as u8, Some(key), KeyModifiers::empty()));
+        }
+        else if key_pressed && !Window::modifier_key_pressed(event, keymask) {
+            return Some(KeyboardInput(Released, event.keycode() as u8, Some(key), KeyModifiers::empty()));
+        }
+
+        return None;
+    }
+
+    unsafe fn modifier_key_pressed(event: id, modifier: u64) -> bool {
+        event.modifierFlags() & modifier != 0
+    }
+
     pub fn wait_events(&self) -> Vec<Event> {
         unsafe {
             let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(

From f86af01a99064ac1476498ea48370d4193ceda97 Mon Sep 17 00:00:00 2001
From: David Partouche <david@manateedev.com>
Date: Thu, 23 Oct 2014 18:01:09 +0200
Subject: [PATCH 7/7] Added the Alt key modifier

---
 src/events.rs  | 2 ++
 src/osx/mod.rs | 6 ++++++
 2 files changed, 8 insertions(+)

diff --git a/src/events.rs b/src/events.rs
index 1b46e105..0c11a75d 100644
--- a/src/events.rs
+++ b/src/events.rs
@@ -128,6 +128,7 @@ pub enum VirtualKeyCode {
     Kana,
     Kanji,
     L,
+    LAlt,
     LBracket,
     LControl,
     Left,
@@ -171,6 +172,7 @@ pub enum VirtualKeyCode {
     Prevtrack,
     Q,
     R,
+    RAlt,
     RBracket,
     RControl,
     Return,
diff --git a/src/osx/mod.rs b/src/osx/mod.rs
index abe233de..dfd2eb85 100644
--- a/src/osx/mod.rs
+++ b/src/osx/mod.rs
@@ -26,6 +26,7 @@ mod event;
 static mut shift_pressed: bool = false;
 static mut ctrl_pressed: bool = false;
 static mut win_pressed: bool = false;
+static mut alt_pressed: bool = false;
 
 pub struct Window {
     view: id,
@@ -272,6 +273,11 @@ impl Window {
                             win_pressed = !win_pressed;
                             events.push(win_modifier.unwrap());
                         }
+                        let alt_modifier = Window::modifier_event(event, appkit::NSAlternateKeyMask as u64, events::LAlt, alt_pressed);
+                        if alt_modifier.is_some() {
+                            alt_pressed = !alt_pressed;
+                            events.push(alt_modifier.unwrap());
+                        }
                     },
                     NSScrollWheel           => { },
                     NSOtherMouseDown        => { },