aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml21
-rw-r--r--README.md5
-rw-r--r--appveyor.yml5
m---------deps/apk-builder0
-rw-r--r--examples/cursor.rs49
-rw-r--r--examples/fullscreen.rs12
-rw-r--r--examples/multiwindow.rs10
-rw-r--r--examples/support/mod.rs13
-rw-r--r--examples/window.rs10
-rw-r--r--fixosxcontextversion.patch218
-rw-r--r--src/android/mod.rs72
-rw-r--r--src/events.rs14
-rw-r--r--src/lib.rs256
-rw-r--r--src/osx/headless.rs25
-rw-r--r--src/osx/mod.rs109
-rw-r--r--src/osx/mod.rs.BACKUP.6164.rs524
-rw-r--r--src/osx/mod.rs.BASE.6164.rs485
-rw-r--r--src/osx/mod.rs.LOCAL.6164.rs498
-rw-r--r--src/osx/mod.rs.REMOTE.6164.rs492
-rw-r--r--src/osx/monitor.rs15
-rw-r--r--src/win32/init.rs64
-rw-r--r--src/win32/mod.rs104
-rw-r--r--src/win32/monitor.rs28
-rw-r--r--src/x11/ffi.rs10
-rw-r--r--src/x11/headless.rs32
-rw-r--r--src/x11/mod.rs5
-rw-r--r--src/x11/window/mod.rs161
-rw-r--r--src/x11/window/monitor.rs19
-rw-r--r--tests/headless.rs6
29 files changed, 2893 insertions, 369 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 99a727b..46d9bd1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,9 +1,9 @@
[package]
name = "glutin"
-version = "0.0.2"
+version = "0.0.4-pre"
authors = ["tomaka <pierre.krieger1708@gmail.com>"]
-description = "Cross-plaform OpenGL context provider."
+description = "Cross-plaform OpenGL context provider. Important: the crates.io only supports Windows and Linux for the moment."
keywords = ["windowing", "opengl"]
license = "Apache-2.0"
readme = "README.md"
@@ -17,10 +17,11 @@ window = []
headless = []
[dependencies.gl_common]
-git = "https://github.com/bjz/gl-rs"
+gl_common = "*"
-[build-dependencies.gl_generator]
-git = "https://github.com/bjz/gl-rs"
+[build-dependencies]
+gl_generator = "*"
+khronos_api = "*"
[target.arm-linux-androideabi.dependencies.android_glue]
git = "https://github.com/tomaka/android-rs-glue"
@@ -37,10 +38,16 @@ git = "https://github.com/servo/rust-core-graphics"
[target.x86_64-apple-darwin.dependencies.core_graphics]
git = "https://github.com/servo/rust-core-graphics"
+[target.i686-apple-darwin.dependencies.core_foundation]
+git = "https://github.com/servo/rust-core-foundation"
+
+[target.x86_64-apple-darwin.dependencies.core_foundation]
+git = "https://github.com/servo/rust-core-foundation"
+
[target.i686-pc-windows-gnu.dependencies.winapi]
-version = "^0.0.2"
+version = "*"
features = ["gdi32", "kernel32", "user32"]
[target.x86_64-pc-windows-gnu.dependencies.winapi]
-version = "^0.0.2"
+version = "*"
features = ["gdi32", "kernel32", "user32"]
diff --git a/README.md b/README.md
index ab96b92..8188add 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,7 @@
Alternative to GLFW in pure Rust.
[![Build Status](https://travis-ci.org/tomaka/glutin.png?branch=master)](https://travis-ci.org/tomaka/glutin)
+[![Build status](https://ci.appveyor.com/api/projects/status/cv5xewg3uchb3854/branch/master?svg=true)](https://ci.appveyor.com/project/tomaka/glutin/branch/master)
## [Documentation](http://tomaka.github.io/glutin/)
@@ -58,14 +59,16 @@ fn main() {
- Some events are not implemented
- Implementation is still work-in-progress
- Vsync not implemented
-
+ - Changing the cursor (set_cursor) is not implemented
### Win32
- You must call `glFlush` before `swap_buffers`, or else on Windows 8 nothing will be visible on the window
- Pixel formats are not implemented
+ - Changing the cursor (set_cursor) is not implemented
### X11
- Some input events are not implemented
- Pixel formats not implemented
- Vsync not implemented
+ - Not all mouse cursors are implemented (ContextMenu, ...)
diff --git a/appveyor.yml b/appveyor.yml
index 12fb639..b7a558c 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,13 +1,10 @@
install:
- ps: Start-FileDownload 'https://static.rust-lang.org/dist/rust-nightly-i686-pc-windows-gnu.exe'
- - ps: Start-FileDownload 'https://static.rust-lang.org/cargo-dist/cargo-nightly-i686-pc-windows-gnu.tar.gz'
- rust-nightly-i686-pc-windows-gnu.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
- - 7z e cargo-nightly-i686-pc-windows-gnu.tar.gz
- - 7z x cargo-nightly-i686-pc-windows-gnu.tar
- SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
- - SET PATH=%PATH%;%CD%\cargo-nightly-i686-pc-windows-gnu\bin
- rustc -V
- cargo -V
+ - git submodule update --init --recursive
build: false
diff --git a/deps/apk-builder b/deps/apk-builder
deleted file mode 160000
-Subproject fe9acb5bd465da1df4561e2bd4ebcc6d305134a
diff --git a/examples/cursor.rs b/examples/cursor.rs
new file mode 100644
index 0000000..0dced66
--- /dev/null
+++ b/examples/cursor.rs
@@ -0,0 +1,49 @@
+#[cfg(target_os = "android")]
+#[macro_use]
+extern crate android_glue;
+
+extern crate glutin;
+
+use glutin::{Event, ElementState, MouseCursor};
+
+mod support;
+
+#[cfg(target_os = "android")]
+android_start!(main);
+
+#[cfg(not(feature = "window"))]
+fn main() { println!("This example requires glutin to be compiled with the `window` feature"); }
+
+#[cfg(feature = "window")]
+fn main() {
+
+ let mut window = glutin::Window::new().unwrap();
+ window.set_title("A fantastic window!");
+ unsafe { window.make_current() };
+
+ let context = support::load(&window);
+ let cursors = [MouseCursor::Default, MouseCursor::Crosshair, MouseCursor::Hand, MouseCursor::Arrow, MouseCursor::Move, MouseCursor::Text, MouseCursor::Wait, MouseCursor::Help, MouseCursor::Progress, MouseCursor::NotAllowed, MouseCursor::ContextMenu, MouseCursor::NoneCursor, MouseCursor::Cell, MouseCursor::VerticalText, MouseCursor::Alias, MouseCursor::Copy, MouseCursor::NoDrop, MouseCursor::Grab, MouseCursor::Grabbing, MouseCursor::AllScroll, MouseCursor::ZoomIn, MouseCursor::ZoomOut, MouseCursor::EResize, MouseCursor::NResize, MouseCursor::NeResize, MouseCursor::NwResize, MouseCursor::SResize, MouseCursor::SeResize, MouseCursor::SwResize, MouseCursor::WResize, MouseCursor::EwResize, MouseCursor::NsResize, MouseCursor::NeswResize, MouseCursor::NwseResize, MouseCursor::ColResize, MouseCursor::RowResize];
+ let mut cursor_idx = 0;
+
+ while !window.is_closed() {
+ context.draw_frame((0.0, 1.0, 0.0, 1.0));
+ window.swap_buffers();
+
+ for event in window.wait_events() {
+ match event {
+ Event::KeyboardInput(ElementState::Pressed, _, _) => {
+ println!("Setting cursor to \"{:?}\"", cursors[cursor_idx]);
+ window.set_cursor(cursors[cursor_idx]);
+ if cursor_idx < cursors.len() - 1 {
+ cursor_idx += 1;
+ } else {
+ cursor_idx = 0;
+ }
+ },
+ _ => (),
+ }
+
+ }
+
+ }
+}
diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs
index bc15379..7c2ece8 100644
--- a/examples/fullscreen.rs
+++ b/examples/fullscreen.rs
@@ -1,7 +1,5 @@
-#![feature(phase)]
-
#[cfg(target_os = "android")]
-#[phase(plugin, link)]
+#[macro_use]
extern crate android_glue;
extern crate glutin;
@@ -21,15 +19,15 @@ fn main() {
// enumerating monitors
let monitor = {
for (num, monitor) in glutin::get_available_monitors().enumerate() {
- println!("Monitor #{}: {}", num, monitor.get_name());
+ println!("Monitor #{}: {:?}", num, monitor.get_name());
}
print!("Please write the number of the monitor to use: ");
- let num = from_str(stdin().read_line().unwrap().as_slice().trim())
+ let num = stdin().read_line().unwrap().as_slice().trim().parse()
.expect("Plase enter a number");
let monitor = glutin::get_available_monitors().nth(num).expect("Please enter a valid ID");
- println!("Using {}", monitor.get_name());
+ println!("Using {:?}", monitor.get_name());
monitor
};
@@ -49,6 +47,6 @@ fn main() {
context.draw_frame((0.0, 1.0, 0.0, 1.0));
window.swap_buffers();
- println!("{}", window.wait_events().collect::<Vec<glutin::Event>>());
+ println!("{:?}", window.wait_events().collect::<Vec<glutin::Event>>());
}
}
diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs
index 1f390cd..96b5842 100644
--- a/examples/multiwindow.rs
+++ b/examples/multiwindow.rs
@@ -1,7 +1,5 @@
-#![feature(phase)]
-
#[cfg(target_os = "android")]
-#[phase(plugin, link)]
+#[macro_use]
extern crate android_glue;
extern crate glutin;
@@ -22,15 +20,15 @@ fn main() {
let window2 = glutin::Window::new().unwrap();
let window3 = glutin::Window::new().unwrap();
- let t1 = Thread::spawn(move || {
+ let t1 = Thread::scoped(move || {
run(window1, (0.0, 1.0, 0.0, 1.0));
});
- let t2 = Thread::spawn(move || {
+ let t2 = Thread::scoped(move || {
run(window2, (0.0, 0.0, 1.0, 1.0));
});
- let t3 = Thread::spawn(move || {
+ let t3 = Thread::scoped(move || {
run(window3, (1.0, 0.0, 0.0, 1.0));
});
diff --git a/examples/support/mod.rs b/examples/support/mod.rs
index 6904653..94ef1a7 100644
--- a/examples/support/mod.rs
+++ b/examples/support/mod.rs
@@ -1,8 +1,5 @@
#![cfg(feature = "window")]
-#[phase(plugin)]
-extern crate gl_generator;
-
use glutin;
#[cfg(not(target_os = "android"))]
@@ -23,12 +20,12 @@ pub struct Context {
pub fn load(window: &glutin::Window) -> Context {
let gl = gl::Gl::load(window);
- let version = {
- use std::c_str::CString;
- unsafe { CString::new(gl.GetString(gl::VERSION) as *const i8, false) }
+ let version = unsafe {
+ use std::ffi;
+ String::from_utf8(ffi::c_str_to_bytes(&(gl.GetString(gl::VERSION) as *const i8)).to_vec()).unwrap()
};
- println!("OpenGL version {}", version.as_str().unwrap());
+ println!("OpenGL version {}", version);
Context { gl: gl }
}
@@ -80,7 +77,7 @@ impl Context {
}
#[cfg(target_os = "android")]
-static VERTEX_DATA: [f32, ..15] = [
+static VERTEX_DATA: [f32; 15] = [
-0.5, -0.5, 1.0, 0.0, 0.0,
0.0, 0.5, 0.0, 1.0, 0.0,
0.5, -0.5, 0.0, 0.0, 1.0
diff --git a/examples/window.rs b/examples/window.rs
index 910d6e6..37966c4 100644
--- a/examples/window.rs
+++ b/examples/window.rs
@@ -1,7 +1,5 @@
-#![feature(phase)]
-
#[cfg(target_os = "android")]
-#[phase(plugin, link)]
+#[macro_use]
extern crate android_glue;
extern crate glutin;
@@ -15,7 +13,7 @@ android_start!(main);
fn main() { println!("This example requires glutin to be compiled with the `window` feature"); }
#[cfg(feature = "window")]
-fn resize_callback(width: uint, height: uint) {
+fn resize_callback(width: u32, height: u32) {
println!("Window resized to {}x{}", width, height);
}
@@ -23,7 +21,7 @@ fn resize_callback(width: uint, height: uint) {
fn main() {
let mut window = glutin::Window::new().unwrap();
window.set_title("A fantastic window!");
- window.set_window_resize_callback(Some(resize_callback as fn(uint, uint)));
+ window.set_window_resize_callback(Some(resize_callback as fn(u32, u32)));
unsafe { window.make_current() };
let context = support::load(&window);
@@ -32,6 +30,6 @@ fn main() {
context.draw_frame((0.0, 1.0, 0.0, 1.0));
window.swap_buffers();
- println!("{}", window.wait_events().collect::<Vec<glutin::Event>>());
+ println!("{:?}", window.wait_events().collect::<Vec<glutin::Event>>());
}
}
diff --git a/fixosxcontextversion.patch b/fixosxcontextversion.patch
new file mode 100644
index 0000000..14a2301
--- /dev/null
+++ b/fixosxcontextversion.patch
@@ -0,0 +1,218 @@
+From 86af6b6387918ea93fe5ce4cae2764a1d196061e Mon Sep 17 00:00:00 2001
+From: Patrick Horlebein <patrick@ilovepatrick.de>
+Date: Mon, 29 Dec 2014 13:26:44 +0100
+Subject: [PATCH 1/5] Started adding support for selection OpenGL versions on
+ OS X. Needs issue #176 to be fixed.
+
+---
+ src/osx/mod.rs | 27 +++++++++++++++++++++++----
+ 1 file changed, 23 insertions(+), 4 deletions(-)
+
+diff --git a/src/osx/mod.rs b/src/osx/mod.rs
+index 7df6603..59b6577 100644
+--- a/src/osx/mod.rs
++++ b/src/osx/mod.rs
+@@ -44,6 +44,15 @@ static mut alt_pressed: bool = false;
+ static DELEGATE_NAME: &'static [u8] = b"glutin_window_delegate\0";
+ static DELEGATE_STATE_IVAR: &'static [u8] = b"glutin_state";
+
++// TODO: Should be added to cocoa bindings
++#[allow(non_camel_case_types)]
++#[deriving(Show)]
++enum NSOpenGLPFAOpenGLProfiles {
++ NSOpenGLProfileVersionLegacy = 0x1000,
++ NSOpenGLProfileVersion3_2Core = 0x3200,
++ NSOpenGLProfileVersion4_1Core = 0x4100
++}
++
+ struct DelegateState<'a> {
+ is_closed: bool,
+ context: id,
+@@ -68,7 +77,7 @@ impl Window {
+ unimplemented!()
+ }
+
+- Window::new_impl(builder.dimensions, builder.title.as_slice(), builder.monitor, builder.vsync, builder.visible)
++ Window::new_impl(builder.dimensions, builder.title.as_slice(), builder.monitor, builder.vsync, builder.visible, builder.gl_version)
+ }
+ }
+
+@@ -130,7 +139,7 @@ extern fn window_did_resize(this: id, _: id) -> id {
+
+ impl Window {
+ fn new_impl(dimensions: Option<(uint, uint)>, title: &str, monitor: Option<MonitorID>,
+- vsync: bool, visible: bool) -> Result<Window, CreationError> {
++ vsync: bool, visible: bool, gl_version: Option<(uint, uint)>) -> Result<Window, CreationError> {
+ let app = match Window::create_app() {
+ Some(app) => app,
+ None => { return Err(OsError(format!("Couldn't create NSApplication"))); },
+@@ -144,7 +153,7 @@ impl Window {
+ None => { return Err(OsError(format!("Couldn't create NSView"))); },
+ };
+
+- let context = match Window::create_context(view, vsync) {
++ let context = match Window::create_context(view, vsync, gl_version) {
+ Some(context) => context,
+ None => { return Err(OsError(format!("Couldn't create OpenGL context"))); },
+ };
+@@ -260,7 +269,16 @@ impl Window {
+ }
+ }
+
+- fn create_context(view: id, vsync: bool) -> Option<id> {
++ fn create_context(view: id, vsync: bool, gl_version: Option<(uint, uint)>) -> Option<id> {
++ let profile = {
++ match gl_version {
++ None => NSOpenGLPFAOpenGLProfiles::NSOpenGLProfileVersionLegacy as uint,
++ Some((0...2, _)) => NSOpenGLPFAOpenGLProfiles::NSOpenGLProfileVersionLegacy as uint,
++ Some((3, 0)) => NSOpenGLPFAOpenGLProfiles::NSOpenGLProfileVersionLegacy as uint,
++ Some((3, 1...2)) => NSOpenGLPFAOpenGLProfiles::NSOpenGLProfileVersion3_2Core as uint,
++ Some((_, _)) => NSOpenGLPFAOpenGLProfiles::NSOpenGLProfileVersion4_1Core as uint,
++ }
++ };
+ unsafe {
+ let attributes = [
+ NSOpenGLPFADoubleBuffer as uint,
+@@ -269,6 +287,7 @@ impl Window {
+ NSOpenGLPFAAlphaSize as uint, 8,
+ NSOpenGLPFADepthSize as uint, 24,
+ NSOpenGLPFAStencilSize as uint, 8,
++ NSOpenGLPFAOpenGLProfile as uint, profile,
+ 0
+ ];
+
+--
+1.9.3 (Apple Git-50)
+
+
+From 1b0064f9f780ab8a53e7b5a7a33f2fd8c53aab08 Mon Sep 17 00:00:00 2001
+From: Patrick Horlebein <patrick@ilovepatrick.de>
+Date: Mon, 29 Dec 2014 13:27:24 +0100
+Subject: [PATCH 2/5] Fixed deprecation warnings
+
+---
+ 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 59b6577..e2b9bc2 100644
+--- a/src/osx/mod.rs
++++ b/src/osx/mod.rs
+@@ -475,8 +475,8 @@ impl Window {
+ }
+
+ pub fn get_proc_address(&self, _addr: &str) -> *const () {
+- let symbol_name: CFString = from_str(_addr).unwrap();
+- let framework_name: CFString = from_str("com.apple.opengl").unwrap();
++ let symbol_name = _addr.parse::<CFString>().unwrap();
++ let framework_name = "com.apple.opengl".parse::<CFString>().unwrap();
+ let framework = unsafe {
+ CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
+ };
+--
+1.9.3 (Apple Git-50)
+
+
+From 09cf026a9de2e1aef43307d64d41a0251159c113 Mon Sep 17 00:00:00 2001
+From: Patrick Horlebein <patrick@ilovepatrick.de>
+Date: Mon, 29 Dec 2014 13:46:44 +0100
+Subject: [PATCH 3/5] Minor match clause cleanup
+
+---
+ src/osx/mod.rs | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/src/osx/mod.rs b/src/osx/mod.rs
+index e2b9bc2..ce02779 100644
+--- a/src/osx/mod.rs
++++ b/src/osx/mod.rs
+@@ -272,9 +272,7 @@ impl Window {
+ fn create_context(view: id, vsync: bool, gl_version: Option<(uint, uint)>) -> Option<id> {
+ let profile = {
+ match gl_version {
+- None => NSOpenGLPFAOpenGLProfiles::NSOpenGLProfileVersionLegacy as uint,
+- Some((0...2, _)) => NSOpenGLPFAOpenGLProfiles::NSOpenGLProfileVersionLegacy as uint,
+- Some((3, 0)) => NSOpenGLPFAOpenGLProfiles::NSOpenGLProfileVersionLegacy as uint,
++ None | Some((0...2, _)) | Some((3, 0)) => NSOpenGLPFAOpenGLProfiles::NSOpenGLProfileVersionLegacy as uint,
+ Some((3, 1...2)) => NSOpenGLPFAOpenGLProfiles::NSOpenGLProfileVersion3_2Core as uint,
+ Some((_, _)) => NSOpenGLPFAOpenGLProfiles::NSOpenGLProfileVersion4_1Core as uint,
+ }
+--
+1.9.3 (Apple Git-50)
+
+
+From b0dddb2d3f10c90128ab250838b314acca131061 Mon Sep 17 00:00:00 2001
+From: Patrick Horlebein <patrick@ilovepatrick.de>
+Date: Tue, 30 Dec 2014 17:01:37 +0100
+Subject: [PATCH 4/5] Fixed missing std::ascii::AsciiExt import
+
+---
+ src/osx/mod.rs | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/osx/mod.rs b/src/osx/mod.rs
+index ce02779..739aa77 100644
+--- a/src/osx/mod.rs
++++ b/src/osx/mod.rs
+@@ -4,6 +4,7 @@ pub use self::headless::HeadlessContext;
+ use {CreationError, Event};
+ use CreationError::OsError;
+ use libc;
++use std::ascii::AsciiExt;
+
+ #[cfg(feature = "window")]
+ use WindowBuilder;
+--
+1.9.3 (Apple Git-50)
+
+
+From 0e64651db8f19378d7c183b21c0e7d692380e570 Mon Sep 17 00:00:00 2001
+From: Patrick Horlebein <patrick@ilovepatrick.de>
+Date: Tue, 30 Dec 2014 17:02:49 +0100
+Subject: [PATCH 5/5] Removed NSOpenGLPFAOpenGLProfiles enum in favor of the
+ one defined in the AppKit bindings
+
+---
+ src/osx/mod.rs | 19 ++++---------------
+ 1 file changed, 4 insertions(+), 15 deletions(-)
+
+diff --git a/src/osx/mod.rs b/src/osx/mod.rs
+index 739aa77..83c51a3 100644
+--- a/src/osx/mod.rs
++++ b/src/osx/mod.rs
+@@ -45,15 +45,6 @@ static mut alt_pressed: bool = false;
+ static DELEGATE_NAME: &'static [u8] = b"glutin_window_delegate\0";
+ static DELEGATE_STATE_IVAR: &'static [u8] = b"glutin_state";
+
+-// TODO: Should be added to cocoa bindings
+-#[allow(non_camel_case_types)]
+-#[deriving(Show)]
+-enum NSOpenGLPFAOpenGLProfiles {
+- NSOpenGLProfileVersionLegacy = 0x1000,
+- NSOpenGLProfileVersion3_2Core = 0x3200,
+- NSOpenGLProfileVersion4_1Core = 0x4100
+-}
+-
+ struct DelegateState<'a> {
+ is_closed: bool,
+ context: id,
+@@ -271,12 +262,10 @@ impl Window {
+ }
+
+ fn create_context(view: id, vsync: bool, gl_version: Option<(uint, uint)>) -> Option<id> {
+- let profile = {
+- match gl_version {
+- None | Some((0...2, _)) | Some((3, 0)) => NSOpenGLPFAOpenGLProfiles::NSOpenGLProfileVersionLegacy as uint,
+- Some((3, 1...2)) => NSOpenGLPFAOpenGLProfiles::NSOpenGLProfileVersion3_2Core as uint,
+- Some((_, _)) => NSOpenGLPFAOpenGLProfiles::NSOpenGLProfileVersion4_1Core as uint,
+- }
++ let profile = match gl_version {
++ None | Some((0...2, _)) | Some((3, 0)) => NSOpenGLProfileVersionLegacy as uint,
++ Some((3, 1...2)) => NSOpenGLProfileVersion3_2Core as uint,
++ Some((_, _)) => NSOpenGLProfileVersion4_1Core as uint,
+ };
+ unsafe {
+ let attributes = [
+--
+1.9.3 (Apple Git-50)
+
diff --git a/src/android/mod.rs b/src/android/mod.rs
index 7279f99..6987f52 100644
--- a/src/android/mod.rs
+++ b/src/android/mod.rs
@@ -1,14 +1,17 @@
extern crate android_glue;
use libc;
-use {CreationError, Event, WindowBuilder};
+use std::ffi::{CString};
+use std::sync::mpsc::{Receiver, channel};
+use {CreationError, Event, MouseCursor};
use CreationError::OsError;
use events::ElementState::{Pressed, Released};
use events::Event::{MouseInput, MouseMoved};
use events::MouseButton::LeftMouseButton;
-#[cfg(feature = "headless")]
-use HeadlessRendererBuilder;
+use std::collections::RingBuf;
+
+use BuilderAttribs;
pub struct Window {
display: ffi::egl::types::EGLDisplay,
@@ -21,8 +24,10 @@ pub struct MonitorID;
mod ffi;
-pub fn get_available_monitors() -> Vec<MonitorID> {
- vec![ MonitorID ]
+pub fn get_available_monitors() -> RingBuf <MonitorID> {
+ let mut rb = RingBuf::new();
+ rb.push_back(MonitorID);
+ rb
}
pub fn get_primary_monitor() -> MonitorID {
@@ -34,18 +39,18 @@ impl MonitorID {
Some("Primary".to_string())
}
- pub fn get_dimensions(&self) -> (uint, uint) {
+ pub fn get_dimensions(&self) -> (u32, u32) {
unimplemented!()
}
}
#[cfg(feature = "headless")]
-pub struct HeadlessContext(int);
+pub struct HeadlessContext(i32);
#[cfg(feature = "headless")]
impl HeadlessContext {
/// See the docs in the crate root file.
- pub fn new(_builder: HeadlessRendererBuilder) -> Result<HeadlessContext, CreationError> {
+ pub fn new(_builder: BuilderAttribs) -> Result<HeadlessContext, CreationError> {
unimplemented!()
}
@@ -60,8 +65,13 @@ impl HeadlessContext {
}
}
+#[cfg(feature = "headless")]
+unsafe impl Send for HeadlessContext {}
+#[cfg(feature = "headless")]
+unsafe impl Sync for HeadlessContext {}
+
impl Window {
- pub fn new(builder: WindowBuilder) -> Result<Window, CreationError> {
+ pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
use std::{mem, ptr};
if builder.sharing.is_some() {
@@ -110,6 +120,7 @@ impl Window {
attribute_list.push_all(&[ffi::egl::RED_SIZE as i32, 1]);
attribute_list.push_all(&[ffi::egl::GREEN_SIZE as i32, 1]);
attribute_list.push_all(&[ffi::egl::BLUE_SIZE as i32, 1]);
+ attribute_list.push_all(&[ffi::egl::DEPTH_SIZE as i32, 1]);
attribute_list.push(ffi::egl::NONE as i32);
let mut num_config: ffi::egl::types::EGLint = mem::uninitialized();
@@ -180,50 +191,50 @@ impl Window {
pub fn hide(&self) {
}
- pub fn get_position(&self) -> Option<(int, int)> {
+ pub fn get_position(&self) -> Option<(i32, i32)> {
None
}
- pub fn set_position(&self, _x: int, _y: int) {
+ pub fn set_position(&self, _x: i32, _y: i32) {
}
- pub fn get_inner_size(&self) -> Option<(uint, uint)> {
+ pub fn get_inner_size(&self) -> Option<(u32, u32)> {
let native_window = unsafe { android_glue::get_native_window() };
if native_window.is_null() {
None
} else {
Some((
- unsafe { ffi::ANativeWindow_getWidth(native_window) } as uint,
- unsafe { ffi::ANativeWindow_getHeight(native_window) } as uint
+ unsafe { ffi::ANativeWindow_getWidth(native_window) } as u32,
+ unsafe { ffi::ANativeWindow_getHeight(native_window) } as u32
))
}
}
- pub fn get_outer_size(&self) -> Option<(uint, uint)> {
+ pub fn get_outer_size(&self) -> Option<(u32, u32)> {
self.get_inner_size()
}
- pub fn set_inner_size(&self, _x: uint, _y: uint) {
+ pub fn set_inner_size(&self, _x: u32, _y: u32) {
}
pub fn create_window_proxy(&self) -> WindowProxy {
WindowProxy
}
- pub fn poll_events(&self) -> Vec<Event> {
- let mut events = Vec::new();
+ pub fn poll_events(&self) -> RingBuf<Event> {
+ let mut events = RingBuf::new();
loop {
match self.event_rx.try_recv() {
Ok(event) => match event {
android_glue::Event::EventDown => {
- events.push(MouseInput(Pressed, LeftMouseButton));
+ events.push_back(MouseInput(Pressed, LeftMouseButton));
},
android_glue::Event::EventUp => {
- events.push(MouseInput(Released, LeftMouseButton));
+ events.push_back(MouseInput(Released, LeftMouseButton));
},
android_glue::Event::EventMove(x, y) => {
- events.push(MouseMoved((x as int, y as int)));
+ events.push_back(MouseMoved((x as i32, y as i32)));
},
},
Err(_) => {
@@ -234,7 +245,7 @@ impl Window {
events
}
- pub fn wait_events(&self) -> Vec<Event> {
+ pub fn wait_events(&self) -> RingBuf<Event> {
use std::time::Duration;
use std::io::timer;
timer::sleep(Duration::milliseconds(16));
@@ -248,12 +259,9 @@ impl Window {
}
pub fn get_proc_address(&self, addr: &str) -> *const () {
- use std::c_str::ToCStr;
-
+ let addr = CString::from_slice(addr.as_bytes()).as_slice_with_nul().as_ptr();
unsafe {
- addr.with_c_str(|s| {
- ffi::egl::GetProcAddress(s) as *const ()
- })
+ ffi::egl::GetProcAddress(addr) as *const ()
}
}
@@ -271,12 +279,18 @@ impl Window {
::Api::OpenGlEs
}
- pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) {
+ pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) {
+ }
+
+ pub fn set_cursor(&self, _: MouseCursor) {
}
}
+unsafe impl Send for Window {}
+unsafe impl Sync for Window {}
+
#[cfg(feature = "window")]
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct WindowProxy;
impl WindowProxy {
diff --git a/src/events.rs b/src/events.rs
index beafbec..34234b2 100644
--- a/src/events.rs
+++ b/src/events.rs
@@ -1,10 +1,10 @@
-#[deriving(Clone, Show, Copy)]
+#[derive(Clone, Show, Copy)]
pub enum Event {
/// The size of the window has changed.
- Resized(uint, uint),
+ Resized(u32, u32),
/// The position of the window has changed.
- Moved(int, int),
+ Moved(i32, i32),
/// The window has been closed.
Closed,
@@ -23,7 +23,7 @@ pub enum Event {
/// The cursor has moved on the window.
///
/// The parameter are the (x,y) coords in pixels relative to the top-left corner of the window.
- MouseMoved((int, int)),
+ MouseMoved((i32, i32)),
/// A positive value indicates that the wheel was rotated forward, away from the user;
/// a negative value indicates that the wheel was rotated backward, toward the user.
@@ -38,13 +38,13 @@ pub enum Event {
pub type ScanCode = u8;
-#[deriving(Show, Hash, PartialEq, Eq, Clone, Copy)]
+#[derive(Show, Hash, PartialEq, Eq, Clone, Copy)]
pub enum ElementState {
Pressed,
Released,
}
-#[deriving(Show, Hash, PartialEq, Eq, Clone, Copy)]
+#[derive(Show, Hash, PartialEq, Eq, Clone, Copy)]
pub enum MouseButton {
LeftMouseButton,
RightMouseButton,
@@ -52,7 +52,7 @@ pub enum MouseButton {
OtherMouseButton(u8),
}
-#[deriving(Show, Hash, PartialEq, Eq, Clone, Copy)]
+#[derive(Show, Hash, PartialEq, Eq, Clone, Copy)]
pub enum VirtualKeyCode {
/// The '1' key over the letters.
Key1,
diff --git a/src/lib.rs b/src/lib.rs
index 6a736cd..12a908c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,4 @@
#![feature(unsafe_destructor)]
-#![feature(globs)]
-#![feature(phase)]
#![unstable]
//! The purpose of this library is to provide an OpenGL context on as many
@@ -43,6 +41,7 @@ extern crate core_graphics;
pub use events::*;
use std::default::Default;
+use std::collections::ring_buf::IntoIter as RingBufIter;
#[cfg(all(not(target_os = "windows"), not(target_os = "linux"), not(target_os = "macos"), not(target_os = "android")))]
use this_platform_is_not_supported;
@@ -67,21 +66,23 @@ mod events;
pub struct MonitorID(winimpl::MonitorID);
/// Error that can happen while creating a window or a headless renderer.
-#[deriving(Clone, Show, PartialEq, Eq)]
+#[derive(Clone, Show, PartialEq, Eq)]
pub enum CreationError {
OsError(String),
+ NotSupported,
}
impl std::error::Error for CreationError {
fn description(&self) -> &str {
match self {
&CreationError::OsError(ref text) => text.as_slice(),
+ &CreationError::NotSupported => "Some of the requested attributes are not supported",
}
}
}
/// All APIs related to OpenGL that you can possibly get while using glutin.
-#[deriving(Show, Clone, Copy, PartialEq, Eq)]
+#[derive(Show, Clone, Copy, PartialEq, Eq)]
pub enum Api {
/// The classical OpenGL. Available on Windows, Linux, OS/X.
OpenGl,
@@ -89,25 +90,93 @@ pub enum Api {
OpenGlEs,
}
+#[derive(Show, Copy)]
+pub enum MouseCursor {
+ /// The platform-dependent default cursor.
+ Default,
+ /// A simple crosshair.
+ Crosshair,
+ /// A hand (often used to indicate links in web browsers).
+ Hand,
+ /// Self explanatory.
+ Arrow,
+ /// Indicates something is to be moved.
+ Move,
+ /// Indicates text that may be selected or edited.
+ Text,
+ /// Program busy indicator.
+ Wait,
+ /// Help indicator (often rendered as a "?")
+ Help,
+ /// Progress indicator. Shows that processing is being done. But in contrast
+ /// with "Wait" the user may still interact with the program. Often rendered
+ /// as a spinning beach ball, or an arrow with a watch or hourglass.
+ Progress,
+
+ /// Cursor showing that something cannot be done.
+ NotAllowed,
+ ContextMenu,
+ NoneCursor,
+ Cell,
+ VerticalText,
+ Alias,
+ Copy,
+ NoDrop,
+ Grab,
+ Grabbing,
+ AllScroll,
+ ZoomIn,
+ ZoomOut,
+
+ /// Indicate that some edge is to be moved. For example, the 'SeResize' cursor
+ /// is used when the movement starts from the south-east corner of the box.
+ EResize,
+ NResize,
+ NeResize,
+ NwResize,
+ SResize,
+ SeResize,
+ SwResize,
+ WResize,
+ EwResize,
+ NsResize,
+ NeswResize,
+ NwseResize,
+ ColResize,
+ RowResize,
+}
+
/// Object that allows you to build windows.
#[cfg(feature = "window")]
pub struct WindowBuilder<'a> {
- sharing: Option<&'a Window>,
- dimensions: Option<(uint, uint)>,
+ attribs: BuilderAttribs<'a>
+}
+
+/// Attributes
+struct BuilderAttribs<'a> {
+ headless: bool,
+ strict: bool,
+ sharing: Option<&'a winimpl::Window>,
+ dimensions: Option<(u32, u32)>,
title: String,
monitor: Option<winimpl::MonitorID>,
- gl_version: Option<(uint, uint)>,
+ gl_version: Option<(u32, u32)>,
gl_debug: bool,
vsync: bool,
visible: bool,
multisampling: Option<u16>,
+ depth_bits: Option<u8>,
+ stencil_bits: Option<u8>,
+ color_bits: Option<u8>,
+ alpha_bits: Option<u8>,
+ stereoscopy: bool,
}
-#[cfg(feature = "window")]
-impl<'a> WindowBuilder<'a> {
- /// Initializes a new `WindowBuilder` with default values.
- pub fn new() -> WindowBuilder<'a> {
- WindowBuilder {
+impl BuilderAttribs<'static> {
+ fn new() -> BuilderAttribs<'static> {
+ BuilderAttribs {
+ headless: false,
+ strict: false,
sharing: None,
dimensions: None,
title: "glutin window".to_string(),
@@ -117,20 +186,35 @@ impl<'a> WindowBuilder<'a> {
vsync: false,
visible: true,
multisampling: None,
+ depth_bits: None,
+ stencil_bits: None,
+ color_bits: None,
+ alpha_bits: None,
+ stereoscopy: false,
+ }
+ }
+}
+
+#[cfg(feature = "window")]
+impl<'a> WindowBuilder<'a> {
+ /// Initializes a new `WindowBuilder` with default values.
+ pub fn new() -> WindowBuilder<'a> {
+ WindowBuilder {
+ attribs: BuilderAttribs::new(),
}
}
/// Requests the window to be of specific dimensions.
///
/// Width and height are in pixels.
- pub fn with_dimensions(mut self, width: uint, height: uint) -> WindowBuilder<'a> {
- self.dimensions = Some((width, height));
+ pub fn with_dimensions(mut self, width: u32, height: u32) -> WindowBuilder<'a> {
+ self.attribs.dimensions = Some((width, height));
self
}
/// Requests a specific title for the window.
pub fn with_title(mut self, title: String) -> WindowBuilder<'a> {
- self.title = title;
+ self.attribs.title = title;
self
}
@@ -139,7 +223,7 @@ impl<'a> WindowBuilder<'a> {
/// If you don't specify dimensions for the window, it will match the monitor's.
pub fn with_fullscreen(mut self, monitor: MonitorID) -> WindowBuilder<'a> {
let MonitorID(monitor) = monitor;
- self.monitor = Some(monitor);
+ self.attribs.monitor = Some(monitor);
self
}
@@ -147,7 +231,7 @@ impl<'a> WindowBuilder<'a> {
///
/// There are some exceptions, like FBOs or VAOs. See the OpenGL documentation.
pub fn with_shared_lists(mut self, other: &'a Window) -> WindowBuilder<'a> {
- self.sharing = Some(other);
+ self.attribs.sharing = Some(&other.window);
self
}
@@ -155,8 +239,8 @@ impl<'a> WindowBuilder<'a> {
///
/// Version is a (major, minor) pair. For example to request OpenGL 3.3
/// you would pass `(3, 3)`.
- pub fn with_gl_version(mut self, version: (uint, uint)) -> WindowBuilder<'a> {
- self.gl_version = Some(version);
+ pub fn with_gl_version(mut self, version: (u32, u32)) -> WindowBuilder<'a> {
+ self.attribs.gl_version = Some(version);
self
}
@@ -165,19 +249,19 @@ impl<'a> WindowBuilder<'a> {
/// The default value for this flag is `cfg!(ndebug)`, which means that it's enabled
/// when you run `cargo build` and disabled when you run `cargo build --release`.
pub fn with_gl_debug_flag(mut self, flag: bool) -> WindowBuilder<'a> {
- self.gl_debug = flag;
+ self.attribs.gl_debug = flag;
self
}
/// Requests that the window has vsync enabled.
pub fn with_vsync(mut self) -> WindowBuilder<'a> {
- self.vsync = true;
+ self.attribs.vsync = true;
self
}
/// Sets whether the window will be initially hidden or visible.
pub fn with_visibility(mut self, visible: bool) -> WindowBuilder<'a> {
- self.visible = visible;
+ self.attribs.visible = visible;
self
}
@@ -189,7 +273,32 @@ impl<'a> WindowBuilder<'a> {
pub fn with_multisampling(mut self, samples: u16) -> WindowBuilder<'a> {
use std::num::UnsignedInt;
assert!(samples.is_power_of_two());
- self.multisampling = Some(samples);
+ self.attribs.multisampling = Some(samples);
+ self
+ }
+
+ /// Sets the number of bits in the depth buffer.
+ pub fn with_depth_buffer(mut self, bits: u8) -> WindowBuilder<'a> {
+ self.attribs.depth_bits = Some(bits);
+ self
+ }
+
+ /// Sets the number of bits in the stencil buffer.
+ pub fn with_stencil_buffer(mut self, bits: u8) -> WindowBuilder<'a> {
+ self.attribs.stencil_bits = Some(bits);
+ self
+ }
+
+ /// Sets the number of bits in the color buffer.
+ pub fn with_pixel_format(mut self, color_bits: u8, alpha_bits: u8) -> WindowBuilder<'a> {
+ self.attribs.color_bits = Some(color_bits);
+ self.attribs.alpha_bits = Some(alpha_bits);
+ self
+ }
+
+ /// Request the backend to be stereoscopic.
+ pub fn with_stereoscopy(mut self) -> WindowBuilder<'a> {
+ self.attribs.stereoscopy = true;
self
}
@@ -199,36 +308,45 @@ impl<'a> WindowBuilder<'a> {
/// out of memory, etc.
pub fn build(mut self) -> Result<Window, CreationError> {
// resizing the window to the dimensions of the monitor when fullscreen
- if self.dimensions.is_none() && self.monitor.is_some() {
- self.dimensions = Some(self.monitor.as_ref().unwrap().get_dimensions())
+ if self.attribs.dimensions.is_none() && self.attribs.monitor.is_some() {
+ self.attribs.dimensions = Some(self.attribs.monitor.as_ref().unwrap().get_dimensions())
}
// default dimensions
- if self.dimensions.is_none() {
- self.dimensions = Some((1024, 768));
+ if self.attribs.dimensions.is_none() {
+ self.attribs.dimensions = Some((1024, 768));
}
// building
- winimpl::Window::new(self).map(|w| Window { window: w })
+ winimpl::Window::new(self.attribs).map(|w| Window { window: w })
+ }
+
+ /// Builds the window.
+ ///
+ /// The context is build in a *strict* way. That means that if the backend couldn't give
+ /// you what you requested, an `Err` will be returned.
+ pub fn build_strict(mut self) -> Result<Window, CreationError> {
+ self.attribs.strict = true;
+ self.build()
}
}
/// Object that allows you to build headless contexts.
#[cfg(feature = "headless")]
pub struct HeadlessRendererBuilder {
- dimensions: (uint, uint),
- gl_version: Option<(uint, uint)>,
- gl_debug: bool,
+ attribs: BuilderAttribs<'static>,
}
#[cfg(feature = "headless")]
impl HeadlessRendererBuilder {
/// Initializes a new `HeadlessRendererBuilder` with default values.
- pub fn new(width: uint, height: uint) -> HeadlessRendererBuilder {
+ pub fn new(width: u32, height: u32) -> HeadlessRendererBuilder {
HeadlessRendererBuilder {
- dimensions: (width, height),
- gl_version: None,
- gl_debug: cfg!(ndebug),
+ attribs: BuilderAttribs {
+ headless: true,
+ dimensions: Some((width, height)),
+ .. BuilderAttribs::new()
+ },
}
}
@@ -236,8 +354,8 @@ impl HeadlessRendererBuilder {
///
/// Version is a (major, minor) pair. For example to request OpenGL 3.3
/// you would pass `(3, 3)`.
- pub fn with_gl_version(mut self, version: (uint, uint)) -> HeadlessRendererBuilder {
- self.gl_version = Some(version);
+ pub fn with_gl_version(mut self, version: (u32, u32)) -> HeadlessRendererBuilder {
+ self.attribs.gl_version = Some(version);
self
}
@@ -246,7 +364,7 @@ impl HeadlessRendererBuilder {
/// The default value for this flag is `cfg!(ndebug)`, which means that it's enabled
/// when you run `cargo build` and disabled when you run `cargo build --release`.
pub fn with_gl_debug_flag(mut self, flag: bool) -> HeadlessRendererBuilder {
- self.gl_debug = flag;
+ self.attribs.gl_debug = flag;
self
}
@@ -255,7 +373,16 @@ impl HeadlessRendererBuilder {
/// Error should be very rare and only occur in case of permission denied, incompatible system,
/// out of memory, etc.
pub fn build(self) -> Result<HeadlessContext, CreationError> {
- winimpl::HeadlessContext::new(self).map(|w| HeadlessContext { context: w })
+ winimpl::HeadlessContext::new(self.attribs).map(|w| HeadlessContext { context: w })
+ }
+
+ /// Builds the headless context.
+ ///
+ /// The context is build in a *strict* way. That means that if the backend couldn't give
+ /// you what you requested, an `Err` will be returned.
+ pub fn build_strict(mut self) -> Result<HeadlessContext, CreationError> {
+ self.attribs.strict = true;
+ self.build()
}
}
@@ -363,7 +490,7 @@ impl Window {
///
/// Returns `None` if the window no longer exists.
#[inline]
- pub fn get_position(&self) -> Option<(int, int)> {
+ pub fn get_position(&self) -> Option<(i32, i32)> {
self.window.get_position()
}
@@ -373,7 +500,7 @@ impl Window {
///
/// This is a no-op if the window has already been closed.
#[inline]
- pub fn set_position(&self, x: int, y: int) {
+ pub fn set_position(&self, x: i32, y: i32) {
self.window.set_position(x, y)
}
@@ -385,7 +512,7 @@ impl Window {
///
/// Returns `None` if the window no longer exists.
#[inline]
- pub fn get_inner_size(&self) -> Option<(uint, uint)> {
+ pub fn get_inner_size(&self) -> Option<(u32, u32)> {
self.window.get_inner_size()
}
@@ -396,7 +523,7 @@ impl Window {
///
/// Returns `None` if the window no longer exists.
#[inline]
- pub fn get_outer_size(&self) -> Option<(uint, uint)> {
+ pub fn get_outer_size(&self) -> Option<(u32, u32)> {
self.window.get_outer_size()
}
@@ -406,7 +533,7 @@ impl Window {
///
/// This is a no-op if the window has already been closed.
#[inline]
- pub fn set_inner_size(&self, x: uint, y: uint) {
+ pub fn set_inner_size(&self, x: u32, y: u32) {
self.window.set_inner_size(x, y)
}
@@ -415,7 +542,7 @@ impl Window {
/// Contrary to `wait_events`, this function never blocks.
#[inline]
pub fn poll_events(&self) -> PollEventsIterator {
- PollEventsIterator { data: self.window.poll_events() }
+ PollEventsIterator { data: self.window.poll_events().into_iter() }
}
/// Waits for an event, then returns an iterator to all the events that are currently
@@ -425,7 +552,7 @@ impl Window {
/// this function will block until there is one.
#[inline]
pub fn wait_events(&self) -> WaitEventsIterator {
- WaitEventsIterator { data: self.window.wait_events() }
+ WaitEventsIterator { data: self.window.wait_events().into_iter() }
}
/// Sets the context as the current context.
@@ -485,9 +612,15 @@ impl Window {
/// operating systems) during resize operations. This can be used to repaint
/// during window resizing.
#[experimental]
- pub fn set_window_resize_callback(&mut self, callback: Option<fn(uint, uint)>) {
+ pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
self.window.set_window_resize_callback(callback);
}
+
+ /// Modifies the mouse cursor of the window.
+ /// Has no effect on Android.
+ pub fn set_cursor(&self, cursor: MouseCursor) {
+ self.window.set_cursor(cursor);
+ }
}
#[cfg(feature = "window")]
@@ -502,7 +635,7 @@ impl gl_common::GlFunctionsSource for Window {
/// threads.
///
#[cfg(feature = "window")]
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct WindowProxy {
proxy: winimpl::WindowProxy,
}
@@ -550,7 +683,7 @@ impl HeadlessContext {
}
#[experimental]
- pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) {
+ pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) {
}
}
@@ -565,12 +698,13 @@ impl gl_common::GlFunctionsSource for HeadlessContext {
// Implementation note: we retreive the list once, then serve each element by one by one.
// This may change in the future.
pub struct PollEventsIterator<'a> {
- data: Vec<Event>,
+ data: RingBufIter<Event>,
}
-impl<'a> Iterator<Event> for PollEventsIterator<'a> {
+impl<'a> Iterator for PollEventsIterator<'a> {
+ type Item = Event;
fn next(&mut self) -> Option<Event> {
- self.data.remove(0)
+ self.data.next()
}
}
@@ -578,12 +712,13 @@ impl<'a> Iterator<Event> for PollEventsIterator<'a> {
// Implementation note: we retreive the list once, then serve each element by one by one.
// This may change in the future.
pub struct WaitEventsIterator<'a> {
- data: Vec<Event>,
+ data: RingBufIter<Event>,
}
-impl<'a> Iterator<Event> for WaitEventsIterator<'a> {
+impl<'a> Iterator for WaitEventsIterator<'a> {
+ type Item = Event;
fn next(&mut self) -> Option<Event> {
- self.data.remove(0)
+ self.data.next()
}
}
@@ -592,13 +727,14 @@ impl<'a> Iterator<Event> for WaitEventsIterator<'a> {
// This may change in the future.
#[cfg(feature = "window")]
pub struct AvailableMonitorsIter {
- data: Vec<winimpl::MonitorID>,
+ data: RingBufIter<winimpl::MonitorID>,
}
#[cfg(feature = "window")]
-impl Iterator<MonitorID> for AvailableMonitorsIter {
+impl Iterator for AvailableMonitorsIter {
+ type Item = MonitorID;
fn next(&mut self) -> Option<MonitorID> {
- self.data.remove(0).map(|id| MonitorID(id))
+ self.data.next().map(|id| MonitorID(id))
}
}
@@ -606,7 +742,7 @@ impl Iterator<MonitorID> for AvailableMonitorsIter {
#[cfg(feature = "window")]
pub fn get_available_monitors() -> AvailableMonitorsIter {
let data = winimpl::get_available_monitors();
- AvailableMonitorsIter{ data: data }
+ AvailableMonitorsIter{ data: data.into_iter() }
}
/// Returns the primary monitor of the system.
@@ -624,7 +760,7 @@ impl MonitorID {
}
/// Returns the number of pixels currently displayed on the monitor.
- pub fn get_dimensions(&self) -> (uint, uint) {
+ pub fn get_dimensions(&self) -> (u32, u32) {
let &MonitorID(ref id) = self;
id.get_dimensions()
}
diff --git a/src/osx/headless.rs b/src/osx/headless.rs
index bbe3d9f..ab3c341 100644
--- a/src/osx/headless.rs
+++ b/src/osx/headless.rs
@@ -1,6 +1,6 @@
use CreationError;
use CreationError::OsError;
-use HeadlessRendererBuilder;
+use BuilderAttribs;
use libc;
use std::ptr;
@@ -24,23 +24,23 @@ static mut framebuffer: u32 = 0;
static mut texture: u32 = 0;
pub struct HeadlessContext {
- width: uint,
- height: uint,
+ width: usize,
+ height: usize,
context: id,
}
impl HeadlessContext {
- pub fn new(builder: HeadlessRendererBuilder) -> Result<HeadlessContext, CreationError> {
+ pub fn new(builder: BuilderAttribs) -> Result<HeadlessContext, CreationError> {
let (width, height) = builder.dimensions;
let context = unsafe {
let attributes = [
- NSOpenGLPFADoubleBuffer as uint,
- NSOpenGLPFAClosestPolicy as uint,
- NSOpenGLPFAColorSize as uint, 24,
- NSOpenGLPFAAlphaSize as uint, 8,
- NSOpenGLPFADepthSize as uint, 24,
- NSOpenGLPFAStencilSize as uint, 8,
- NSOpenGLPFAOffScreen as uint,
+ NSOpenGLPFADoubleBuffer as usize,
+ NSOpenGLPFAClosestPolicy as usize,
+ NSOpenGLPFAColorSize as usize, 24,
+ NSOpenGLPFAAlphaSize as usize, 8,
+ NSOpenGLPFADepthSize as usize, 24,
+ NSOpenGLPFAStencilSize as usize, 8,
+ NSOpenGLPFAOffScreen as usize,
0
];
@@ -99,6 +99,9 @@ impl HeadlessContext {
}
}
+unsafe impl Send for HeadlessContext {}
+unsafe impl Sync for HeadlessContext {}
+
impl Drop for HeadlessContext {
fn drop(&mut self) {
unsafe {
diff --git a/src/osx/mod.rs b/src/osx/mod.rs
index 83c51a3..4b111bf 100644
--- a/src/osx/mod.rs
+++ b/src/osx/mod.rs
@@ -1,13 +1,12 @@
#[cfg(feature = "headless")]
pub use self::headless::HeadlessContext;
-use {CreationError, Event};
+use {CreationError, Event, MouseCursor};
use CreationError::OsError;
use libc;
use std::ascii::AsciiExt;
-#[cfg(feature = "window")]
-use WindowBuilder;
+use BuilderAttribs;
use cocoa::base::{id, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair};
use cocoa::base::{selector, msg_send, class_addMethod, class_addIvar};
@@ -20,9 +19,13 @@ use core_foundation::string::CFString;
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
use std::cell::Cell;
-use std::c_str::CString;
+use std::ffi::{CString, c_str_to_bytes};
use std::mem;
use std::ptr;
+use std::collections::RingBuf;
+use std::str::FromStr;
+use std::str::from_utf8;
+use std::ascii::AsciiExt;
use events::Event::{MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput, MouseWheel};
use events::ElementState::{Pressed, Released};
@@ -49,7 +52,7 @@ struct DelegateState<'a> {
is_closed: bool,
context: id,
view: id,
- handler: Option<fn(uint, uint)>,
+ handler: Option<fn(u32, u32)>,
}
pub struct Window {
@@ -57,14 +60,14 @@ pub struct Window {
window: id,
context: id,
delegate: id,
- resize: Option<fn(uint, uint)>,
+ resize: Option<fn(u32, u32)>,
is_closed: Cell<bool>,
}
#[cfg(feature = "window")]
impl Window {
- pub fn new(builder: WindowBuilder) -> Result<Window, CreationError> {
+ pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
if builder.sharing.is_some() {
unimplemented!()
}
@@ -74,7 +77,12 @@ impl Window {
}
#[cfg(feature = "window")]
-#[deriving(Clone)]
+unsafe impl Send for Window {}
+#[cfg(feature = "window")]
+unsafe impl Sync for Window {}
+
+#[cfg(feature = "window")]
+#[derive(Clone)]
pub struct WindowProxy;
impl WindowProxy {
@@ -121,7 +129,7 @@ extern fn window_did_resize(this: id, _: id) -> id {
match state.handler {
Some(handler) => {
let rect = NSView::frame(state.view);
- (handler)(rect.size.width as uint, rect.size.height as uint);
+ (handler)(rect.size.width as u32, rect.size.height as u32);
}
None => {}
}
@@ -130,7 +138,7 @@ extern fn window_did_resize(this: id, _: id) -> id {
}
impl Window {
- fn new_impl(dimensions: Option<(uint, uint)>, title: &str, monitor: Option<MonitorID>,
+ fn new_impl(dimensions: Option<(u32, u32)>, title: &str, monitor: Option<MonitorID>,
vsync: bool, visible: bool, gl_version: Option<(uint, uint)>) -> Result<Window, CreationError> {
let app = match Window::create_app() {
Some(app) => app,
@@ -166,9 +174,9 @@ impl Window {
let delegate = unsafe {
// Create a delegate class, add callback methods and store InternalState as user data.
let delegate = objc_allocateClassPair(ns_object, DELEGATE_NAME.as_ptr() as *const i8, 0);
- class_addMethod(delegate, selector("windowShouldClose:"), window_should_close, "B@:@".to_c_str().as_ptr());
- class_addMethod(delegate, selector("windowDidResize:"), window_did_resize, "V@:@".to_c_str().as_ptr());
- class_addIvar(delegate, DELEGATE_STATE_IVAR.as_ptr() as *const i8, ptr_size, 3, "?".to_c_str().as_ptr());
+ class_addMethod(delegate, selector("windowShouldClose:"), window_should_close, CString::from_slice("B@:@".as_bytes()).as_ptr());
+ class_addMethod(delegate, selector("windowDidResize:"), window_did_resize, CString::from_slice("V@:@".as_bytes()).as_ptr());
+ class_addIvar(delegate, DELEGATE_STATE_IVAR.as_ptr() as *const i8, ptr_size, 3, CString::from_slice("?".as_bytes()).as_ptr());
objc_registerClassPair(delegate);
let del_obj = msg_send()(delegate, selector("alloc"));
@@ -203,7 +211,7 @@ impl Window {
}
}
- fn create_window(dimensions: (uint, uint), title: &str, monitor: Option<MonitorID>) -> Option<id> {
+ fn create_window(dimensions: (u32, u32), title: &str, monitor: Option<MonitorID>) -> Option<id> {
unsafe {
let scr_frame = match monitor {
Some(_) => {
@@ -269,13 +277,13 @@ impl Window {
};
unsafe {
let attributes = [
- NSOpenGLPFADoubleBuffer as uint,
- NSOpenGLPFAClosestPolicy as uint,
- NSOpenGLPFAColorSize as uint, 24,
- NSOpenGLPFAAlphaSize as uint, 8,
- NSOpenGLPFADepthSize as uint, 24,
- NSOpenGLPFAStencilSize as uint, 8,
- NSOpenGLPFAOpenGLProfile as uint, profile,
+ NSOpenGLPFADoubleBuffer as u32,
+ NSOpenGLPFAClosestPolicy as u32,
+ NSOpenGLPFAColorSize as u32, 24,
+ NSOpenGLPFAAlphaSize as u32, 8,
+ NSOpenGLPFADepthSize as u32, 24,
+ NSOpenGLPFAStencilSize as u32, 8,
+ NSOpenGLPFAOpenGLProfile as u32, profile,
0
];
@@ -315,24 +323,24 @@ impl Window {
pub fn hide(&self) {
}
- pub fn get_position(&self) -> Option<(int, int)> {
+ pub fn get_position(&self) -> Option<(i32, i32)> {
unimplemented!()
}
- pub fn set_position(&self, _x: int, _y: int) {
+ pub fn set_position(&self, _x: i32, _y: i32) {
unimplemented!()
}
- pub fn get_inner_size(&self) -> Option<(uint, uint)> {
+ pub fn get_inner_size(&self) -> Option<(u32, u32)> {
let rect = unsafe { NSView::frame(self.view) };
- Some((rect.size.width as uint, rect.size.height as uint))
+ Some((rect.size.width as u32, rect.size.height as u32))
}
- pub fn get_outer_size(&self) -> Option<(uint, uint)> {
+ pub fn get_outer_size(&self) -> Option<(u32, u32)> {
unimplemented!()
}
- pub fn set_inner_size(&self, _x: uint, _y: uint) {
+ pub fn set_inner_size(&self, _x: u32, _y: u32) {
unimplemented!()
}
@@ -340,8 +348,8 @@ impl Window {
WindowProxy
}
- pub fn poll_events(&self) -> Vec<Event> {
- let mut events = Vec::new();
+ pub fn poll_events(&self) -> RingBuf<Event> {
+ let mut events = RingBuf::new();
loop {
unsafe {
@@ -373,53 +381,54 @@ impl Window {
}
match event.get_type() {
- NSLeftMouseDown => { events.push(MouseInput(Pressed, LeftMouseButton)); },
- NSLeftMouseUp => { events.push(MouseInput(Released, LeftMouseButton)); },
- NSRightMouseDown => { events.push(MouseInput(Pressed, RightMouseButton)); },
- NSRightMouseUp => { events.push(MouseInput(Released, RightMouseButton)); },
+ NSLeftMouseDown => { events.push_back(MouseInput(Pressed, LeftMouseButton)); },
+ NSLeftMouseUp => { events.push_back(MouseInput(Released, LeftMouseButton)); },
+ NSRightMouseDown => { events.push_back(MouseInput(Pressed, RightMouseButton)); },
+ NSRightMouseUp => { events.push_back(MouseInput(Released, RightMouseButton)); },
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)));
+ events.push_back(MouseMoved((view_point.x as i32, view_point.y as i32)));
},
NSKeyDown => {
- let received_str = CString::new(event.characters().UTF8String(), false);
- for received_char in received_str.as_str().unwrap().chars() {
+ let received_c_str = event.characters().UTF8String();
+ let received_str = CString::from_slice(c_str_to_bytes(&received_c_str));
+ for received_char in from_utf8(received_str.as_bytes()).unwrap().chars() {
if received_char.is_ascii() {
- events.push(ReceivedCharacter(received_char));
+ events.push_back(ReceivedCharacter(received_char));
}
}
let vkey = event::vkeycode_to_element(event.keycode());
- events.push(KeyboardInput(Pressed, event.keycode() as u8, vkey));
+ events.push_back(KeyboardInput(Pressed, event.keycode() as u8, vkey));
},
NSKeyUp => {
let vkey = event::vkeycode_to_element(event.keycode());
- events.push(KeyboardInput(Released, event.keycode() as u8, vkey));
+ events.push_back(KeyboardInput(Released, event.keycode() as u8, vkey));
},
NSFlagsChanged => {
let shift_modifier = Window::modifier_event(event, appkit::NSShiftKeyMask as u64, events::VirtualKeyCode::LShift, shift_pressed);
if shift_modifier.is_some() {
shift_pressed = !shift_pressed;
- events.push(shift_modifier.unwrap());
+ events.push_back(shift_modifier.unwrap());
}
let ctrl_modifier = Window::modifier_event(event, appkit::NSControlKeyMask as u64, events::VirtualKeyCode::LControl, ctrl_pressed);
if ctrl_modifier.is_some() {
ctrl_pressed = !ctrl_pressed;
- events.push(ctrl_modifier.unwrap());
+ events.push_back(ctrl_modifier.unwrap());
}
let win_modifier = Window::modifier_event(event, appkit::NSCommandKeyMask as u64, events::VirtualKeyCode::LWin, win_pressed);
if win_modifier.is_some() {
win_pressed = !win_pressed;
- events.push(win_modifier.unwrap());
+ events.push_back(win_modifier.unwrap());
}
let alt_modifier = Window::modifier_event(event, appkit::NSAlternateKeyMask as u64, events::VirtualKeyCode::LAlt, alt_pressed);
if alt_modifier.is_some() {
alt_pressed = !alt_pressed;
- events.push(alt_modifier.unwrap());
+ events.push_back(alt_modifier.unwrap());
}
},
- NSScrollWheel => { events.push(MouseWheel(-event.scrollingDeltaY() as i32)); },
+ NSScrollWheel => { events.push_back(MouseWheel(-event.scrollingDeltaY() as i32)); },
NSOtherMouseDown => { },
NSOtherMouseUp => { },
NSOtherMouseDragged => { },
@@ -445,7 +454,7 @@ impl Window {
event.modifierFlags() & modifier != 0
}
- pub fn wait_events(&self) -> Vec<Event> {
+ pub fn wait_events(&self) -> RingBuf<Event> {
unsafe {
let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
NSAnyEventMask as u64,
@@ -463,8 +472,8 @@ impl Window {
}
pub fn get_proc_address(&self, _addr: &str) -> *const () {
- let symbol_name = _addr.parse::<CFString>().unwrap();
- let framework_name = "com.apple.opengl".parse::<CFString>().unwrap();
+ let symbol_name: CFString = FromStr::from_str(_addr).unwrap();
+ let framework_name: CFString = FromStr::from_str("com.apple.opengl").unwrap();
let framework = unsafe {
CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
};
@@ -486,7 +495,11 @@ impl Window {
::Api::OpenGl
}
- pub fn set_window_resize_callback(&mut self, callback: Option<fn(uint, uint)>) {
+ pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
self.resize = callback;
}
+
+ pub fn set_cursor(&self, cursor: MouseCursor) {
+ unimplemented!()
+ }
}
diff --git a/src/osx/mod.rs.BACKUP.6164.rs b/src/osx/mod.rs.BACKUP.6164.rs
new file mode 100644
index 0000000..7521b5d
--- /dev/null
+++ b/src/osx/mod.rs.BACKUP.6164.rs
@@ -0,0 +1,524 @@
+#[cfg(feature = "headless")]
+pub use self::headless::HeadlessContext;
+
+use {CreationError, Event, MouseCursor};
+use CreationError::OsError;
+use libc;
+use std::ascii::AsciiExt;
+
+use BuilderAttribs;
+
+use cocoa::base::{id, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair};
+use cocoa::base::{selector, msg_send, class_addMethod, class_addIvar};
+use cocoa::base::{object_setInstanceVariable, object_getInstanceVariable};
+use cocoa::appkit;
+use cocoa::appkit::*;
+
+use core_foundation::base::TCFType;
+use core_foundation::string::CFString;
+use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
+
+use std::cell::Cell;
+use std::ffi::{CString, c_str_to_bytes};
+use std::mem;
+use std::ptr;
+use std::collections::RingBuf;
+use std::str::FromStr;
+use std::str::from_utf8;
+use std::ascii::AsciiExt;
+
+use events::Event::{MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput, MouseWheel};
+use events::ElementState::{Pressed, Released};
+use events::MouseButton::{LeftMouseButton, RightMouseButton};
+use events;
+
+pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};
+
+mod monitor;
+mod event;
+
+#[cfg(feature = "headless")]
+mod headless;
+
+static mut shift_pressed: bool = false;
+static mut ctrl_pressed: bool = false;
+static mut win_pressed: bool = false;
+static mut alt_pressed: bool = false;
+
+static DELEGATE_NAME: &'static [u8] = b"glutin_window_delegate\0";
+static DELEGATE_STATE_IVAR: &'static [u8] = b"glutin_state";
+
+struct DelegateState<'a> {
+ is_closed: bool,
+ context: id,
+ view: id,
+ handler: Option<fn(u32, u32)>,
+}
+
+pub struct Window {
+ view: id,
+ window: id,
+ context: id,
+ delegate: id,
+ resize: Option<fn(u32, u32)>,
+
+ is_closed: Cell<bool>,
+}
+
+#[cfg(feature = "window")]
+impl Window {
+ pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
+ if builder.sharing.is_some() {
+ unimplemented!()
+ }
+
+ Window::new_impl(builder.dimensions, builder.title.as_slice(), builder.monitor, builder.vsync, builder.visible, builder.gl_version)
+ }
+}
+
+#[cfg(feature = "window")]
+unsafe impl Send for Window {}
+#[cfg(feature = "window")]
+unsafe impl Sync for Window {}
+
+#[cfg(feature = "window")]
+#[derive(Clone)]
+pub struct WindowProxy;
+
+impl WindowProxy {
+ pub fn wakeup_event_loop(&self) {
+ unsafe {
+ let pool = NSAutoreleasePool::new(nil);
+ let event =
+ NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2(
+ nil,
+ NSApplicationDefined,
+ NSPoint::new(0.0, 0.0),
+ 0,
+ 0.0,
+ 0,
+ ptr::null_mut(),
+ 0,
+ 0,
+ 0);
+ NSApp().postEvent_atStart_(event, true);
+ pool.drain();
+ }
+ }
+}
+
+extern fn window_should_close(this: id, _: id) -> id {
+ unsafe {
+ let mut stored_value = ptr::null_mut();
+ object_getInstanceVariable(this, DELEGATE_STATE_IVAR.as_ptr() as *const i8, &mut stored_value);
+ let state = stored_value as *mut DelegateState;
+
+ (*state).is_closed = true;
+ }
+ 0
+}
+
+extern fn window_did_resize(this: id, _: id) -> id {
+ unsafe {
+ let mut stored_value = ptr::null_mut();
+ object_getInstanceVariable(this, DELEGATE_STATE_IVAR.as_ptr() as *const i8, &mut stored_value);
+ let state = &mut *(stored_value as *mut DelegateState);
+
+ let _: id = msg_send()(state.context, selector("update"));
+
+ match state.handler {
+ Some(handler) => {
+ let rect = NSView::frame(state.view);
+ (handler)(rect.size.width as u32, rect.size.height as u32);
+ }
+ None => {}
+ }
+ }
+ 0
+}
+
+impl Window {
+<<<<<<< HEAD
+ fn new_impl(dimensions: Option<(u32, u32)>, title: &str, monitor: Option<MonitorID>,
+ vsync: bool, visible: bool) -> Result<Window, CreationError> {
+=======
+ fn new_impl(dimensions: Option<(uint, uint)>, title: &str, monitor: Option<MonitorID>,
+ vsync: bool, visible: bool, gl_version: Option<(uint, uint)>) -> Result<Window, CreationError> {
+>>>>>>> pixelpirate/master
+ let app = match Window::create_app() {
+ Some(app) => app,
+ None => { return Err(OsError(format!("Couldn't create NSApplication"))); },
+ };
+ let window = match Window::create_window(dimensions.unwrap_or((800, 600)), title, monitor) {
+ Some(window) => window,
+ None => { return Err(OsError(format!("Couldn't create NSWindow"))); },
+ };
+ let view = match Window::create_view(window) {
+ Some(view) => view,
+ None => { return Err(OsError(format!("Couldn't create NSView"))); },
+ };
+
+ let context = match Window::create_context(view, vsync, gl_version) {
+ Some(context) => context,
+ None => { return Err(OsError(format!("Couldn't create OpenGL context"))); },
+ };
+
+ unsafe {
+ app.activateIgnoringOtherApps_(true);
+ if visible {
+ window.makeKeyAndOrderFront_(nil);
+ } else {
+ window.makeKeyWindow();
+ }
+ }
+
+ // Set up the window delegate to receive events
+ let ptr_size = mem::size_of::<libc::intptr_t>() as u64;
+ let ns_object = class("NSObject");
+
+ let delegate = unsafe {
+ // Create a delegate class, add callback methods and store InternalState as user data.
+ let delegate = objc_allocateClassPair(ns_object, DELEGATE_NAME.as_ptr() as *const i8, 0);
+ class_addMethod(delegate, selector("windowShouldClose:"), window_should_close, CString::from_slice("B@:@".as_bytes()).as_ptr());
+ class_addMethod(delegate, selector("windowDidResize:"), window_did_resize, CString::from_slice("V@:@".as_bytes()).as_ptr());
+ class_addIvar(delegate, DELEGATE_STATE_IVAR.as_ptr() as *const i8, ptr_size, 3, CString::from_slice("?".as_bytes()).as_ptr());
+ objc_registerClassPair(delegate);
+
+ let del_obj = msg_send()(delegate, selector("alloc"));
+ let del_obj: id = msg_send()(del_obj, selector("init"));
+ let _: id = msg_send()(window, selector("setDelegate:"), del_obj);
+ del_obj
+ };
+
+ let window = Window {
+ view: view,
+ window: window,
+ context: context,
+ delegate: delegate,
+ resize: None,
+
+ is_closed: Cell::new(false),
+ };
+
+ Ok(window)
+ }
+
+ fn create_app() -> Option<id> {
+ unsafe {
+ let app = NSApp();
+ if app == nil {
+ None
+ } else {
+ app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
+ app.finishLaunching();
+ Some(app)
+ }
+ }
+ }
+
+ fn create_window(dimensions: (u32, u32), title: &str, monitor: Option<MonitorID>) -> Option<id> {
+ unsafe {
+ let scr_frame = match monitor {
+ Some(_) => {
+ let screen = NSScreen::mainScreen(nil);
+ NSScreen::frame(screen)
+ }
+ None => {
+ let (width, height) = dimensions;
+ NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64))
+ }
+ };
+
+ let masks = match monitor {
+ Some(_) => NSBorderlessWindowMask as NSUInteger,
+ None => NSTitledWindowMask as NSUInteger |
+ NSClosableWindowMask as NSUInteger |
+ NSMiniaturizableWindowMask as NSUInteger |
+ NSResizableWindowMask as NSUInteger,
+ };
+
+ let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
+ scr_frame,
+ masks,
+ NSBackingStoreBuffered,
+ false,
+ );
+
+ if window == nil {
+ None
+ } else {
+ let title = NSString::alloc(nil).init_str(title);
+ window.setTitle_(title);
+ window.setAcceptsMouseMovedEvents_(true);
+ if monitor.is_some() {
+ window.setLevel_(NSMainMenuWindowLevel as i64 + 1);
+ }
+ else {
+ window.center();
+ }
+ Some(window)
+ }
+ }
+ }
+
+ fn create_view(window: id) -> Option<id> {
+ unsafe {
+ let view = NSView::alloc(nil).init();
+ if view == nil {
+ None
+ } else {
+ view.setWantsBestResolutionOpenGLSurface_(true);
+ window.setContentView_(view);
+ Some(view)
+ }
+ }
+ }
+
+ fn create_context(view: id, vsync: bool, gl_version: Option<(uint, uint)>) -> Option<id> {
+ let profile = match gl_version {
+ None | Some((0...2, _)) | Some((3, 0)) => NSOpenGLProfileVersionLegacy as uint,
+ Some((3, 1...2)) => NSOpenGLProfileVersion3_2Core as uint,
+ Some((_, _)) => NSOpenGLProfileVersion4_1Core as uint,
+ };
+ unsafe {
+ let attributes = [
+<<<<<<< HEAD
+ NSOpenGLPFADoubleBuffer as u32,
+ NSOpenGLPFAClosestPolicy as u32,
+ NSOpenGLPFAColorSize as u32, 24,
+ NSOpenGLPFAAlphaSize as u32, 8,
+ NSOpenGLPFADepthSize as u32, 24,
+ NSOpenGLPFAStencilSize as u32, 8,
+=======
+ NSOpenGLPFADoubleBuffer as uint,
+ NSOpenGLPFAClosestPolicy as uint,
+ NSOpenGLPFAColorSize as uint, 24,
+ NSOpenGLPFAAlphaSize as uint, 8,
+ NSOpenGLPFADepthSize as uint, 24,
+ NSOpenGLPFAStencilSize as uint, 8,
+ NSOpenGLPFAOpenGLProfile as uint, profile,
+>>>>>>> pixelpirate/master
+ 0
+ ];
+
+ let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes);
+ if pixelformat == nil {
+ return None;
+ }
+
+ let context = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
+ if context == nil {
+ None
+ } else {
+ context.setView_(view);
+ if vsync {
+ let value = 1;
+ context.setValues_forParameter_(&value, NSOpenGLContextParameter::NSOpenGLCPSwapInterval);
+ }
+ Some(context)
+ }
+ }
+ }
+
+ pub fn is_closed(&self) -> bool {
+ self.is_closed.get()
+ }
+
+ pub fn set_title(&self, title: &str) {
+ unsafe {
+ let title = NSString::alloc(nil).init_str(title);
+ self.window.setTitle_(title);
+ }
+ }
+
+ pub fn show(&self) {
+ }
+
+ pub fn hide(&self) {
+ }
+
+ pub fn get_position(&self) -> Option<(i32, i32)> {
+ unimplemented!()
+ }
+
+ pub fn set_position(&self, _x: i32, _y: i32) {
+ unimplemented!()
+ }
+
+ pub fn get_inner_size(&self) -> Option<(u32, u32)> {
+ let rect = unsafe { NSView::frame(self.view) };
+ Some((rect.size.width as u32, rect.size.height as u32))
+ }
+
+ pub fn get_outer_size(&self) -> Option<(u32, u32)> {
+ unimplemented!()
+ }
+
+ pub fn set_inner_size(&self, _x: u32, _y: u32) {
+ unimplemented!()
+ }
+
+ pub fn create_window_proxy(&self) -> WindowProxy {
+ WindowProxy
+ }
+
+ pub fn poll_events(&self) -> RingBuf<Event> {
+ let mut events = RingBuf::new();
+
+ loop {
+ unsafe {
+ let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
+ NSAnyEventMask as u64,
+ NSDate::distantPast(nil),
+ NSDefaultRunLoopMode,
+ true);
+ if event == nil { break; }
+ {
+ // Create a temporary structure with state that delegates called internally
+ // by sendEvent can read and modify. When that returns, update window state.
+ // This allows the synchronous resize loop to continue issuing callbacks
+ // to the user application, by passing handler through to the delegate state.
+ let mut ds = DelegateState {
+ is_closed: self.is_closed.get(),
+ context: self.context,
+ view: self.view,
+ handler: self.resize,
+ };
+ object_setInstanceVariable(self.delegate,
+ DELEGATE_STATE_IVAR.as_ptr() as *const i8,
+ &mut ds as *mut DelegateState as *mut libc::c_void);
+ NSApp().sendEvent_(event);
+ object_setInstanceVariable(self.delegate,
+ DELEGATE_STATE_IVAR.as_ptr() as *const i8,
+ ptr::null_mut());
+ self.is_closed.set(ds.is_closed);
+}
+
+ match event.get_type() {
+ NSLeftMouseDown => { events.push_back(MouseInput(Pressed, LeftMouseButton)); },
+ NSLeftMouseUp => { events.push_back(MouseInput(Released, LeftMouseButton)); },
+ NSRightMouseDown => { events.push_back(MouseInput(Pressed, RightMouseButton)); },
+ NSRightMouseUp => { events.push_back(MouseInput(Released, RightMouseButton)); },
+ NSMouseMoved => {
+ let window_point = event.locationInWindow();
+ let view_point = self.view.convertPoint_fromView_(window_point, nil);
+ events.push_back(MouseMoved((view_point.x as i32, view_point.y as i32)));
+ },
+ NSKeyDown => {
+ let received_c_str = event.characters().UTF8String();
+ let received_str = CString::from_slice(c_str_to_bytes(&received_c_str));
+ for received_char in from_utf8(received_str.as_bytes()).unwrap().chars() {
+ if received_char.is_ascii() {
+ events.push_back(ReceivedCharacter(received_char));
+ }
+ }
+
+ let vkey = event::vkeycode_to_element(event.keycode());
+ events.push_back(KeyboardInput(Pressed, event.keycode() as u8, vkey));
+ },
+ NSKeyUp => {
+ let vkey = event::vkeycode_to_element(event.keycode());
+ events.push_back(KeyboardInput(Released, event.keycode() as u8, vkey));
+ },
+ NSFlagsChanged => {
+ let shift_modifier = Window::modifier_event(event, appkit::NSShiftKeyMask as u64, events::VirtualKeyCode::LShift, shift_pressed);
+ if shift_modifier.is_some() {
+ shift_pressed = !shift_pressed;
+ events.push_back(shift_modifier.unwrap());
+ }
+ let ctrl_modifier = Window::modifier_event(event, appkit::NSControlKeyMask as u64, events::VirtualKeyCode::LControl, ctrl_pressed);
+ if ctrl_modifier.is_some() {
+ ctrl_pressed = !ctrl_pressed;
+ events.push_back(ctrl_modifier.unwrap());
+ }
+ let win_modifier = Window::modifier_event(event, appkit::NSCommandKeyMask as u64, events::VirtualKeyCode::LWin, win_pressed);
+ if win_modifier.is_some() {
+ win_pressed = !win_pressed;
+ events.push_back(win_modifier.unwrap());
+ }
+ let alt_modifier = Window::modifier_event(event, appkit::NSAlternateKeyMask as u64, events::VirtualKeyCode::LAlt, alt_pressed);
+ if alt_modifier.is_some() {
+ alt_pressed = !alt_pressed;
+ events.push_back(alt_modifier.unwrap());
+ }
+ },
+ NSScrollWheel => { events.push_back(MouseWheel(-event.scrollingDeltaY() as i32)); },
+ NSOtherMouseDown => { },
+ NSOtherMouseUp => { },
+ NSOtherMouseDragged => { },
+ _ => { },
+ }
+ }
+ }
+ 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)));
+ }
+ else if key_pressed && !Window::modifier_key_pressed(event, keymask) {
+ return Some(KeyboardInput(Released, event.keycode() as u8, Some(key)));
+ }
+
+ return None;
+ }
+
+ unsafe fn modifier_key_pressed(event: id, modifier: u64) -> bool {
+ event.modifierFlags() & modifier != 0
+ }
+
+ pub fn wait_events(&self) -> RingBuf<Event> {
+ unsafe {
+ let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
+ NSAnyEventMask as u64,
+ NSDate::distantFuture(nil),
+ NSDefaultRunLoopMode,
+ false);
+ NSApp().sendEvent_(event);
+
+ self.poll_events()
+ }
+ }
+
+ pub unsafe fn make_current(&self) {
+ self.context.makeCurrentContext();
+ }
+
+ pub fn get_proc_address(&self, _addr: &str) -> *const () {
+<<<<<<< HEAD
+ let symbol_name: CFString = FromStr::from_str(_addr).unwrap();
+ let framework_name: CFString = FromStr::from_str("com.apple.opengl").unwrap();
+=======
+ let symbol_name = _addr.parse::<CFString>().unwrap();
+ let framework_name = "com.apple.opengl".parse::<CFString>().unwrap();
+>>>>>>> pixelpirate/master
+ let framework = unsafe {
+ CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
+ };
+ let symbol = unsafe {
+ CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
+ };
+ symbol as *const ()
+ }
+
+ pub fn swap_buffers(&self) {
+ unsafe { self.context.flushBuffer(); }
+ }
+
+ pub fn platform_display(&self) -> *mut libc::c_void {
+ unimplemented!()
+ }
+
+ pub fn get_api(&self) -> ::Api {
+ ::Api::OpenGl
+ }
+
+ pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
+ self.resize = callback;
+ }
+
+ pub fn set_cursor(&self, cursor: MouseCursor) {
+ unimplemented!()
+ }
+}
diff --git a/src/osx/mod.rs.BASE.6164.rs b/src/osx/mod.rs.BASE.6164.rs
new file mode 100644
index 0000000..7df6603
--- /dev/null
+++ b/src/osx/mod.rs.BASE.6164.rs
@@ -0,0 +1,485 @@
+#[cfg(feature = "headless")]
+pub use self::headless::HeadlessContext;
+
+use {CreationError, Event};
+use CreationError::OsError;
+use libc;
+
+#[cfg(feature = "window")]
+use WindowBuilder;
+
+use cocoa::base::{id, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair};
+use cocoa::base::{selector, msg_send, class_addMethod, class_addIvar};
+use cocoa::base::{object_setInstanceVariable, object_getInstanceVariable};
+use cocoa::appkit;
+use cocoa::appkit::*;
+
+use core_foundation::base::TCFType;
+use core_foundation::string::CFString;
+use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
+
+use std::cell::Cell;
+use std::c_str::CString;
+use std::mem;
+use std::ptr;
+
+use events::Event::{MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput, MouseWheel};
+use events::ElementState::{Pressed, Released};
+use events::MouseButton::{LeftMouseButton, RightMouseButton};
+use events;
+
+pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};
+
+mod monitor;
+mod event;
+
+#[cfg(feature = "headless")]
+mod headless;
+
+static mut shift_pressed: bool = false;
+static mut ctrl_pressed: bool = false;
+static mut win_pressed: bool = false;
+static mut alt_pressed: bool = false;
+
+static DELEGATE_NAME: &'static [u8] = b"glutin_window_delegate\0";
+static DELEGATE_STATE_IVAR: &'static [u8] = b"glutin_state";
+
+struct DelegateState<'a> {
+ is_closed: bool,
+ context: id,
+ view: id,
+ handler: Option<fn(uint, uint)>,
+}
+
+pub struct Window {
+ view: id,
+ window: id,
+ context: id,
+ delegate: id,
+ resize: Option<fn(uint, uint)>,
+
+ is_closed: Cell<bool>,
+}
+
+#[cfg(feature = "window")]
+impl Window {
+ pub fn new(builder: WindowBuilder) -> Result<Window, CreationError> {
+ if builder.sharing.is_some() {
+ unimplemented!()
+ }
+
+ Window::new_impl(builder.dimensions, builder.title.as_slice(), builder.monitor, builder.vsync, builder.visible)
+ }
+}
+
+#[cfg(feature = "window")]
+#[deriving(Clone)]
+pub struct WindowProxy;
+
+impl WindowProxy {
+ pub fn wakeup_event_loop(&self) {
+ unsafe {
+ let pool = NSAutoreleasePool::new(nil);
+ let event =
+ NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2(
+ nil,
+ NSApplicationDefined,
+ NSPoint::new(0.0, 0.0),
+ 0,
+ 0.0,
+ 0,
+ ptr::null_mut(),
+ 0,
+ 0,
+ 0);
+ NSApp().postEvent_atStart_(event, true);
+ pool.drain();
+ }
+ }
+}
+
+extern fn window_should_close(this: id, _: id) -> id {
+ unsafe {
+ let mut stored_value = ptr::null_mut();
+ object_getInstanceVariable(this, DELEGATE_STATE_IVAR.as_ptr() as *const i8, &mut stored_value);
+ let state = stored_value as *mut DelegateState;
+
+ (*state).is_closed = true;
+ }
+ 0
+}
+
+extern fn window_did_resize(this: id, _: id) -> id {
+ unsafe {
+ let mut stored_value = ptr::null_mut();
+ object_getInstanceVariable(this, DELEGATE_STATE_IVAR.as_ptr() as *const i8, &mut stored_value);
+ let state = &mut *(stored_value as *mut DelegateState);
+
+ let _: id = msg_send()(state.context, selector("update"));
+
+ match state.handler {
+ Some(handler) => {
+ let rect = NSView::frame(state.view);
+ (handler)(rect.size.width as uint, rect.size.height as uint);
+ }
+ None => {}
+ }
+ }
+ 0
+}
+
+impl Window {
+ fn new_impl(dimensions: Option<(uint, uint)>, title: &str, monitor: Option<MonitorID>,
+ vsync: bool, visible: bool) -> Result<Window, CreationError> {
+ let app = match Window::create_app() {
+ Some(app) => app,
+ None => { return Err(OsError(format!("Couldn't create NSApplication"))); },
+ };
+ let window = match Window::create_window(dimensions.unwrap_or((800, 600)), title, monitor) {
+ Some(window) => window,
+ None => { return Err(OsError(format!("Couldn't create NSWindow"))); },
+ };
+ let view = match Window::create_view(window) {
+ Some(view) => view,
+ None => { return Err(OsError(format!("Couldn't create NSView"))); },
+ };
+
+ let context = match Window::create_context(view, vsync) {
+ Some(context) => context,
+ None => { return Err(OsError(format!("Couldn't create OpenGL context"))); },
+ };
+
+ unsafe {
+ app.activateIgnoringOtherApps_(true);
+ if visible {
+ window.makeKeyAndOrderFront_(nil);
+ } else {
+ window.makeKeyWindow();
+ }
+ }
+
+ // Set up the window delegate to receive events
+ let ptr_size = mem::size_of::<libc::intptr_t>() as u64;
+ let ns_object = class("NSObject");
+
+ let delegate = unsafe {
+ // Create a delegate class, add callback methods and store InternalState as user data.
+ let delegate = objc_allocateClassPair(ns_object, DELEGATE_NAME.as_ptr() as *const i8, 0);
+ class_addMethod(delegate, selector("windowShouldClose:"), window_should_close, "B@:@".to_c_str().as_ptr());
+ class_addMethod(delegate, selector("windowDidResize:"), window_did_resize, "V@:@".to_c_str().as_ptr());
+ class_addIvar(delegate, DELEGATE_STATE_IVAR.as_ptr() as *const i8, ptr_size, 3, "?".to_c_str().as_ptr());
+ objc_registerClassPair(delegate);
+
+ let del_obj = msg_send()(delegate, selector("alloc"));
+ let del_obj: id = msg_send()(del_obj, selector("init"));
+ let _: id = msg_send()(window, selector("setDelegate:"), del_obj);
+ del_obj
+ };
+
+ let window = Window {
+ view: view,
+ window: window,
+ context: context,
+ delegate: delegate,
+ resize: None,
+
+ is_closed: Cell::new(false),
+ };
+
+ Ok(window)
+ }
+
+ fn create_app() -> Option<id> {
+ unsafe {
+ let app = NSApp();
+ if app == nil {
+ None
+ } else {
+ app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
+ app.finishLaunching();
+ Some(app)
+ }
+ }
+ }
+
+ fn create_window(dimensions: (uint, uint), title: &str, monitor: Option<MonitorID>) -> Option<id> {
+ unsafe {
+ let scr_frame = match monitor {
+ Some(_) => {
+ let screen = NSScreen::mainScreen(nil);
+ NSScreen::frame(screen)
+ }
+ None => {
+ let (width, height) = dimensions;
+ NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64))
+ }
+ };
+
+ let masks = match monitor {
+ Some(_) => NSBorderlessWindowMask as NSUInteger,
+ None => NSTitledWindowMask as NSUInteger |
+ NSClosableWindowMask as NSUInteger |
+ NSMiniaturizableWindowMask as NSUInteger |
+ NSResizableWindowMask as NSUInteger,
+ };
+
+ let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
+ scr_frame,
+ masks,
+ NSBackingStoreBuffered,
+ false,
+ );
+
+ if window == nil {
+ None
+ } else {
+ let title = NSString::alloc(nil).init_str(title);
+ window.setTitle_(title);
+ window.setAcceptsMouseMovedEvents_(true);
+ if monitor.is_some() {
+ window.setLevel_(NSMainMenuWindowLevel as i64 + 1);
+ }
+ else {
+ window.center();
+ }
+ Some(window)
+ }
+ }
+ }
+
+ fn create_view(window: id) -> Option<id> {
+ unsafe {
+ let view = NSView::alloc(nil).init();
+ if view == nil {
+ None
+ } else {
+ view.setWantsBestResolutionOpenGLSurface_(true);
+ window.setContentView_(view);
+ Some(view)
+ }
+ }
+ }
+
+ fn create_context(view: id, vsync: bool) -> Option<id> {
+ unsafe {
+ let attributes = [
+ NSOpenGLPFADoubleBuffer as uint,
+ NSOpenGLPFAClosestPolicy as uint,
+ NSOpenGLPFAColorSize as uint, 24,
+ NSOpenGLPFAAlphaSize as uint, 8,
+ NSOpenGLPFADepthSize as uint, 24,
+ NSOpenGLPFAStencilSize as uint, 8,
+ 0
+ ];
+
+ let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes);
+ if pixelformat == nil {
+ return None;
+ }
+
+ let context = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
+ if context == nil {
+ None
+ } else {
+ context.setView_(view);
+ if vsync {
+ let value = 1;
+ context.setValues_forParameter_(&value, NSOpenGLContextParameter::NSOpenGLCPSwapInterval);
+ }
+ Some(context)
+ }
+ }
+ }
+
+ pub fn is_closed(&self) -> bool {
+ self.is_closed.get()
+ }
+
+ pub fn set_title(&self, title: &str) {
+ unsafe {
+ let title = NSString::alloc(nil).init_str(title);
+ self.window.setTitle_(title);
+ }
+ }
+
+ pub fn show(&self) {
+ }
+
+ pub fn hide(&self) {
+ }
+
+ pub fn get_position(&self) -> Option<(int, int)> {
+ unimplemented!()
+ }
+
+ pub fn set_position(&self, _x: int, _y: int) {
+ unimplemented!()
+ }
+
+ pub fn get_inner_size(&self) -> Option<(uint, uint)> {
+ let rect = unsafe { NSView::frame(self.view) };
+ Some((rect.size.width as uint, rect.size.height as uint))
+ }
+
+ pub fn get_outer_size(&self) -> Option<(uint, uint)> {
+ unimplemented!()
+ }
+
+ pub fn set_inner_size(&self, _x: uint, _y: uint) {
+ unimplemented!()
+ }
+
+ pub fn create_window_proxy(&self) -> WindowProxy {
+ WindowProxy
+ }
+
+ pub fn poll_events(&self) -> Vec<Event> {
+ let mut events = Vec::new();
+
+ loop {
+ unsafe {
+ let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
+ NSAnyEventMask as u64,
+ NSDate::distantPast(nil),
+ NSDefaultRunLoopMode,
+ true);
+ if event == nil { break; }
+ {
+ // Create a temporary structure with state that delegates called internally
+ // by sendEvent can read and modify. When that returns, update window state.
+ // This allows the synchronous resize loop to continue issuing callbacks
+ // to the user application, by passing handler through to the delegate state.
+ let mut ds = DelegateState {
+ is_closed: self.is_closed.get(),
+ context: self.context,
+ view: self.view,
+ handler: self.resize,
+ };
+ object_setInstanceVariable(self.delegate,
+ DELEGATE_STATE_IVAR.as_ptr() as *const i8,
+ &mut ds as *mut DelegateState as *mut libc::c_void);
+ NSApp().sendEvent_(event);
+ object_setInstanceVariable(self.delegate,
+ DELEGATE_STATE_IVAR.as_ptr() as *const i8,
+ ptr::null_mut());
+ self.is_closed.set(ds.is_closed);
+}
+
+ match event.get_type() {
+ NSLeftMouseDown => { events.push(MouseInput(Pressed, LeftMouseButton)); },
+ NSLeftMouseUp => { events.push(MouseInput(Released, LeftMouseButton)); },
+ NSRightMouseDown => { events.push(MouseInput(Pressed, RightMouseButton)); },
+ NSRightMouseUp => { events.push(MouseInput(Released, RightMouseButton)); },
+ 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 => {
+ 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());
+ events.push(KeyboardInput(Pressed, event.keycode() as u8, vkey));
+ },
+ NSKeyUp => {
+ let vkey = event::vkeycode_to_element(event.keycode());
+ events.push(KeyboardInput(Released, event.keycode() as u8, vkey));
+ },
+ NSFlagsChanged => {
+ let shift_modifier = Window::modifier_event(event, appkit::NSShiftKeyMask as u64, events::VirtualKeyCode::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::VirtualKeyCode::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::VirtualKeyCode::LWin, win_pressed);
+ if win_modifier.is_some() {
+ win_pressed = !win_pressed;
+ events.push(win_modifier.unwrap());
+ }
+ let alt_modifier = Window::modifier_event(event, appkit::NSAlternateKeyMask as u64, events::VirtualKeyCode::LAlt, alt_pressed);
+ if alt_modifier.is_some() {
+ alt_pressed = !alt_pressed;
+ events.push(alt_modifier.unwrap());
+ }
+ },
+ NSScrollWheel => { events.push(MouseWheel(-event.scrollingDeltaY() as i32)); },
+ NSOtherMouseDown => { },
+ NSOtherMouseUp => { },
+ NSOtherMouseDragged => { },
+ _ => { },
+ }
+ }
+ }
+ 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)));
+ }
+ else if key_pressed && !Window::modifier_key_pressed(event, keymask) {
+ return Some(KeyboardInput(Released, event.keycode() as u8, Some(key)));
+ }
+
+ 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_(
+ NSAnyEventMask as u64,
+ NSDate::distantFuture(nil),
+ NSDefaultRunLoopMode,
+ false);
+ NSApp().sendEvent_(event);
+
+ self.poll_events()
+ }
+ }
+
+ pub unsafe fn make_current(&self) {
+ self.context.makeCurrentContext();
+ }
+
+ pub fn get_proc_address(&self, _addr: &str) -> *const () {
+ let symbol_name: CFString = from_str(_addr).unwrap();
+ let framework_name: CFString = from_str("com.apple.opengl").unwrap();
+ let framework = unsafe {
+ CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
+ };
+ let symbol = unsafe {
+ CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
+ };
+ symbol as *const ()
+ }
+
+ pub fn swap_buffers(&self) {
+ unsafe { self.context.flushBuffer(); }
+ }
+
+ pub fn platform_display(&self) -> *mut libc::c_void {
+ unimplemented!()
+ }
+
+ pub fn get_api(&self) -> ::Api {
+ ::Api::OpenGl
+ }
+
+ pub fn set_window_resize_callback(&mut self, callback: Option<fn(uint, uint)>) {
+ self.resize = callback;
+ }
+}
diff --git a/src/osx/mod.rs.LOCAL.6164.rs b/src/osx/mod.rs.LOCAL.6164.rs
new file mode 100644
index 0000000..59d979a
--- /dev/null
+++ b/src/osx/mod.rs.LOCAL.6164.rs
@@ -0,0 +1,498 @@
+#[cfg(feature = "headless")]
+pub use self::headless::HeadlessContext;
+
+use {CreationError, Event, MouseCursor};
+use CreationError::OsError;
+use libc;
+
+use BuilderAttribs;
+
+use cocoa::base::{id, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair};
+use cocoa::base::{selector, msg_send, class_addMethod, class_addIvar};
+use cocoa::base::{object_setInstanceVariable, object_getInstanceVariable};
+use cocoa::appkit;
+use cocoa::appkit::*;
+
+use core_foundation::base::TCFType;
+use core_foundation::string::CFString;
+use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
+
+use std::cell::Cell;
+use std::ffi::{CString, c_str_to_bytes};
+use std::mem;
+use std::ptr;
+use std::collections::RingBuf;
+use std::str::FromStr;
+use std::str::from_utf8;
+use std::ascii::AsciiExt;
+
+use events::Event::{MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput, MouseWheel};
+use events::ElementState::{Pressed, Released};
+use events::MouseButton::{LeftMouseButton, RightMouseButton};
+use events;
+
+pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};
+
+mod monitor;
+mod event;
+
+#[cfg(feature = "headless")]
+mod headless;
+
+static mut shift_pressed: bool = false;
+static mut ctrl_pressed: bool = false;
+static mut win_pressed: bool = false;
+static mut alt_pressed: bool = false;
+
+static DELEGATE_NAME: &'static [u8] = b"glutin_window_delegate\0";
+static DELEGATE_STATE_IVAR: &'static [u8] = b"glutin_state";
+
+struct DelegateState<'a> {
+ is_closed: bool,
+ context: id,
+ view: id,
+ handler: Option<fn(u32, u32)>,
+}
+
+pub struct Window {
+ view: id,
+ window: id,
+ context: id,
+ delegate: id,
+ resize: Option<fn(u32, u32)>,
+
+ is_closed: Cell<bool>,
+}
+
+#[cfg(feature = "window")]
+impl Window {
+ pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
+ if builder.sharing.is_some() {
+ unimplemented!()
+ }
+
+ Window::new_impl(builder.dimensions, builder.title.as_slice(), builder.monitor, builder.vsync, builder.visible)
+ }
+}
+
+#[cfg(feature = "window")]
+unsafe impl Send for Window {}
+#[cfg(feature = "window")]
+unsafe impl Sync for Window {}
+
+#[cfg(feature = "window")]
+#[derive(Clone)]
+pub struct WindowProxy;
+
+impl WindowProxy {
+ pub fn wakeup_event_loop(&self) {
+ unsafe {
+ let pool = NSAutoreleasePool::new(nil);
+ let event =
+ NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2(
+ nil,
+ NSApplicationDefined,
+ NSPoint::new(0.0, 0.0),
+ 0,
+ 0.0,
+ 0,
+ ptr::null_mut(),
+ 0,
+ 0,
+ 0);
+ NSApp().postEvent_atStart_(event, true);
+ pool.drain();
+ }
+ }
+}
+
+extern fn window_should_close(this: id, _: id) -> id {
+ unsafe {
+ let mut stored_value = ptr::null_mut();
+ object_getInstanceVariable(this, DELEGATE_STATE_IVAR.as_ptr() as *const i8, &mut stored_value);
+ let state = stored_value as *mut DelegateState;
+
+ (*state).is_closed = true;
+ }
+ 0
+}
+
+extern fn window_did_resize(this: id, _: id) -> id {
+ unsafe {
+ let mut stored_value = ptr::null_mut();
+ object_getInstanceVariable(this, DELEGATE_STATE_IVAR.as_ptr() as *const i8, &mut stored_value);
+ let state = &mut *(stored_value as *mut DelegateState);
+
+ let _: id = msg_send()(state.context, selector("update"));
+
+ match state.handler {
+ Some(handler) => {
+ let rect = NSView::frame(state.view);
+ (handler)(rect.size.width as u32, rect.size.height as u32);
+ }
+ None => {}
+ }
+ }
+ 0
+}
+
+impl Window {
+ fn new_impl(dimensions: Option<(u32, u32)>, title: &str, monitor: Option<MonitorID>,
+ vsync: bool, visible: bool) -> Result<Window, CreationError> {
+ let app = match Window::create_app() {
+ Some(app) => app,
+ None => { return Err(OsError(format!("Couldn't create NSApplication"))); },
+ };
+ let window = match Window::create_window(dimensions.unwrap_or((800, 600)), title, monitor) {
+ Some(window) => window,
+ None => { return Err(OsError(format!("Couldn't create NSWindow"))); },
+ };
+ let view = match Window::create_view(window) {
+ Some(view) => view,
+ None => { return Err(OsError(format!("Couldn't create NSView"))); },
+ };
+
+ let context = match Window::create_context(view, vsync) {
+ Some(context) => context,
+ None => { return Err(OsError(format!("Couldn't create OpenGL context"))); },
+ };
+
+ unsafe {
+ app.activateIgnoringOtherApps_(true);
+ if visible {
+ window.makeKeyAndOrderFront_(nil);
+ } else {
+ window.makeKeyWindow();
+ }
+ }
+
+ // Set up the window delegate to receive events
+ let ptr_size = mem::size_of::<libc::intptr_t>() as u64;
+ let ns_object = class("NSObject");
+
+ let delegate = unsafe {
+ // Create a delegate class, add callback methods and store InternalState as user data.
+ let delegate = objc_allocateClassPair(ns_object, DELEGATE_NAME.as_ptr() as *const i8, 0);
+ class_addMethod(delegate, selector("windowShouldClose:"), window_should_close, CString::from_slice("B@:@".as_bytes()).as_ptr());
+ class_addMethod(delegate, selector("windowDidResize:"), window_did_resize, CString::from_slice("V@:@".as_bytes()).as_ptr());
+ class_addIvar(delegate, DELEGATE_STATE_IVAR.as_ptr() as *const i8, ptr_size, 3, CString::from_slice("?".as_bytes()).as_ptr());
+ objc_registerClassPair(delegate);
+
+ let del_obj = msg_send()(delegate, selector("alloc"));
+ let del_obj: id = msg_send()(del_obj, selector("init"));
+ let _: id = msg_send()(window, selector("setDelegate:"), del_obj);
+ del_obj
+ };
+
+ let window = Window {
+ view: view,
+ window: window,
+ context: context,
+ delegate: delegate,
+ resize: None,
+
+ is_closed: Cell::new(false),
+ };
+
+ Ok(window)
+ }
+
+ fn create_app() -> Option<id> {
+ unsafe {
+ let app = NSApp();
+ if app == nil {
+ None
+ } else {
+ app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
+ app.finishLaunching();
+ Some(app)
+ }
+ }
+ }
+
+ fn create_window(dimensions: (u32, u32), title: &str, monitor: Option<MonitorID>) -> Option<id> {
+ unsafe {
+ let scr_frame = match monitor {
+ Some(_) => {
+ let screen = NSScreen::mainScreen(nil);
+ NSScreen::frame(screen)
+ }
+ None => {
+ let (width, height) = dimensions;
+ NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64))
+ }
+ };
+
+ let masks = match monitor {
+ Some(_) => NSBorderlessWindowMask as NSUInteger,
+ None => NSTitledWindowMask as NSUInteger |
+ NSClosableWindowMask as NSUInteger |
+ NSMiniaturizableWindowMask as NSUInteger |
+ NSResizableWindowMask as NSUInteger,
+ };
+
+ let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
+ scr_frame,
+ masks,
+ NSBackingStoreBuffered,
+ false,
+ );
+
+ if window == nil {
+ None
+ } else {
+ let title = NSString::alloc(nil).init_str(title);
+ window.setTitle_(title);
+ window.setAcceptsMouseMovedEvents_(true);
+ if monitor.is_some() {
+ window.setLevel_(NSMainMenuWindowLevel as i64 + 1);
+ }
+ else {
+ window.center();
+ }
+ Some(window)
+ }
+ }
+ }
+
+ fn create_view(window: id) -> Option<id> {
+ unsafe {
+ let view = NSView::alloc(nil).init();
+ if view == nil {
+ None
+ } else {
+ view.setWantsBestResolutionOpenGLSurface_(true);
+ window.setContentView_(view);
+ Some(view)
+ }
+ }
+ }
+
+ fn create_context(view: id, vsync: bool) -> Option<id> {
+ unsafe {
+ let attributes = [
+ NSOpenGLPFADoubleBuffer as u32,
+ NSOpenGLPFAClosestPolicy as u32,
+ NSOpenGLPFAColorSize as u32, 24,
+ NSOpenGLPFAAlphaSize as u32, 8,
+ NSOpenGLPFADepthSize as u32, 24,
+ NSOpenGLPFAStencilSize as u32, 8,
+ 0
+ ];
+
+ let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes);
+ if pixelformat == nil {
+ return None;
+ }
+
+ let context = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
+ if context == nil {
+ None
+ } else {
+ context.setView_(view);
+ if vsync {
+ let value = 1;
+ context.setValues_forParameter_(&value, NSOpenGLContextParameter::NSOpenGLCPSwapInterval);
+ }
+ Some(context)
+ }
+ }
+ }
+
+ pub fn is_closed(&self) -> bool {
+ self.is_closed.get()
+ }
+
+ pub fn set_title(&self, title: &str) {
+ unsafe {
+ let title = NSString::alloc(nil).init_str(title);
+ self.window.setTitle_(title);
+ }
+ }
+
+ pub fn show(&self) {
+ }
+
+ pub fn hide(&self) {
+ }
+
+ pub fn get_position(&self) -> Option<(i32, i32)> {
+ unimplemented!()
+ }
+
+ pub fn set_position(&self, _x: i32, _y: i32) {
+ unimplemented!()
+ }
+
+ pub fn get_inner_size(&self) -> Option<(u32, u32)> {
+ let rect = unsafe { NSView::frame(self.view) };
+ Some((rect.size.width as u32, rect.size.height as u32))
+ }
+
+ pub fn get_outer_size(&self) -> Option<(u32, u32)> {
+ unimplemented!()
+ }
+
+ pub fn set_inner_size(&self, _x: u32, _y: u32) {
+ unimplemented!()
+ }
+
+ pub fn create_window_proxy(&self) -> WindowProxy {
+ WindowProxy
+ }
+
+ pub fn poll_events(&self) -> RingBuf<Event> {
+ let mut events = RingBuf::new();
+
+ loop {
+ unsafe {
+ let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
+ NSAnyEventMask as u64,
+ NSDate::distantPast(nil),
+ NSDefaultRunLoopMode,
+ true);
+ if event == nil { break; }
+ {
+ // Create a temporary structure with state that delegates called internally
+ // by sendEvent can read and modify. When that returns, update window state.
+ // This allows the synchronous resize loop to continue issuing callbacks
+ // to the user application, by passing handler through to the delegate state.
+ let mut ds = DelegateState {
+ is_closed: self.is_closed.get(),
+ context: self.context,
+ view: self.view,
+ handler: self.resize,
+ };
+ object_setInstanceVariable(self.delegate,
+ DELEGATE_STATE_IVAR.as_ptr() as *const i8,
+ &mut ds as *mut DelegateState as *mut libc::c_void);
+ NSApp().sendEvent_(event);
+ object_setInstanceVariable(self.delegate,
+ DELEGATE_STATE_IVAR.as_ptr() as *const i8,
+ ptr::null_mut());
+ self.is_closed.set(ds.is_closed);
+}
+
+ match event.get_type() {
+ NSLeftMouseDown => { events.push_back(MouseInput(Pressed, LeftMouseButton)); },
+ NSLeftMouseUp => { events.push_back(MouseInput(Released, LeftMouseButton)); },
+ NSRightMouseDown => { events.push_back(MouseInput(Pressed, RightMouseButton)); },
+ NSRightMouseUp => { events.push_back(MouseInput(Released, RightMouseButton)); },
+ NSMouseMoved => {
+ let window_point = event.locationInWindow();
+ let view_point = self.view.convertPoint_fromView_(window_point, nil);
+ events.push_back(MouseMoved((view_point.x as i32, view_point.y as i32)));
+ },
+ NSKeyDown => {
+ let received_c_str = event.characters().UTF8String();
+ let received_str = CString::from_slice(c_str_to_bytes(&received_c_str));
+ for received_char in from_utf8(received_str.as_bytes()).unwrap().chars() {
+ if received_char.is_ascii() {
+ events.push_back(ReceivedCharacter(received_char));
+ }
+ }
+
+ let vkey = event::vkeycode_to_element(event.keycode());
+ events.push_back(KeyboardInput(Pressed, event.keycode() as u8, vkey));
+ },
+ NSKeyUp => {
+ let vkey = event::vkeycode_to_element(event.keycode());
+ events.push_back(KeyboardInput(Released, event.keycode() as u8, vkey));
+ },
+ NSFlagsChanged => {
+ let shift_modifier = Window::modifier_event(event, appkit::NSShiftKeyMask as u64, events::VirtualKeyCode::LShift, shift_pressed);
+ if shift_modifier.is_some() {
+ shift_pressed = !shift_pressed;
+ events.push_back(shift_modifier.unwrap());
+ }
+ let ctrl_modifier = Window::modifier_event(event, appkit::NSControlKeyMask as u64, events::VirtualKeyCode::LControl, ctrl_pressed);
+ if ctrl_modifier.is_some() {
+ ctrl_pressed = !ctrl_pressed;
+ events.push_back(ctrl_modifier.unwrap());
+ }
+ let win_modifier = Window::modifier_event(event, appkit::NSCommandKeyMask as u64, events::VirtualKeyCode::LWin, win_pressed);
+ if win_modifier.is_some() {
+ win_pressed = !win_pressed;
+ events.push_back(win_modifier.unwrap());
+ }
+ let alt_modifier = Window::modifier_event(event, appkit::NSAlternateKeyMask as u64, events::VirtualKeyCode::LAlt, alt_pressed);
+ if alt_modifier.is_some() {
+ alt_pressed = !alt_pressed;
+ events.push_back(alt_modifier.unwrap());
+ }
+ },
+ NSScrollWheel => { events.push_back(MouseWheel(-event.scrollingDeltaY() as i32)); },
+ NSOtherMouseDown => { },
+ NSOtherMouseUp => { },
+ NSOtherMouseDragged => { },
+ _ => { },
+ }
+ }
+ }
+ 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)));
+ }
+ else if key_pressed && !Window::modifier_key_pressed(event, keymask) {
+ return Some(KeyboardInput(Released, event.keycode() as u8, Some(key)));
+ }
+
+ return None;
+ }
+
+ unsafe fn modifier_key_pressed(event: id, modifier: u64) -> bool {
+ event.modifierFlags() & modifier != 0
+ }
+
+ pub fn wait_events(&self) -> RingBuf<Event> {
+ unsafe {
+ let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
+ NSAnyEventMask as u64,
+ NSDate::distantFuture(nil),
+ NSDefaultRunLoopMode,
+ false);
+ NSApp().sendEvent_(event);
+
+ self.poll_events()
+ }
+ }
+
+ pub unsafe fn make_current(&self) {
+ self.context.makeCurrentContext();
+ }
+
+ pub fn get_proc_address(&self, _addr: &str) -> *const () {
+ let symbol_name: CFString = FromStr::from_str(_addr).unwrap();
+ let framework_name: CFString = FromStr::from_str("com.apple.opengl").unwrap();
+ let framework = unsafe {
+ CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
+ };
+ let symbol = unsafe {
+ CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
+ };
+ symbol as *const ()
+ }
+
+ pub fn swap_buffers(&self) {
+ unsafe { self.context.flushBuffer(); }
+ }
+
+ pub fn platform_display(&self) -> *mut libc::c_void {
+ unimplemented!()
+ }
+
+ pub fn get_api(&self) -> ::Api {
+ ::Api::OpenGl
+ }
+
+ pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
+ self.resize = callback;
+ }
+
+ pub fn set_cursor(&self, cursor: MouseCursor) {
+ unimplemented!()
+ }
+}
diff --git a/src/osx/mod.rs.REMOTE.6164.rs b/src/osx/mod.rs.REMOTE.6164.rs
new file mode 100644
index 0000000..83c51a3
--- /dev/null
+++ b/src/osx/mod.rs.REMOTE.6164.rs
@@ -0,0 +1,492 @@
+#[cfg(feature = "headless")]
+pub use self::headless::HeadlessContext;
+
+use {CreationError, Event};
+use CreationError::OsError;
+use libc;
+use std::ascii::AsciiExt;
+
+#[cfg(feature = "window")]
+use WindowBuilder;
+
+use cocoa::base::{id, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair};
+use cocoa::base::{selector, msg_send, class_addMethod, class_addIvar};
+use cocoa::base::{object_setInstanceVariable, object_getInstanceVariable};
+use cocoa::appkit;
+use cocoa::appkit::*;
+
+use core_foundation::base::TCFType;
+use core_foundation::string::CFString;
+use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
+
+use std::cell::Cell;
+use std::c_str::CString;
+use std::mem;
+use std::ptr;
+
+use events::Event::{MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput, MouseWheel};
+use events::ElementState::{Pressed, Released};
+use events::MouseButton::{LeftMouseButton, RightMouseButton};
+use events;
+
+pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};
+
+mod monitor;
+mod event;
+
+#[cfg(feature = "headless")]
+mod headless;
+
+static mut shift_pressed: bool = false;
+static mut ctrl_pressed: bool = false;
+static mut win_pressed: bool = false;
+static mut alt_pressed: bool = false;
+
+static DELEGATE_NAME: &'static [u8] = b"glutin_window_delegate\0";
+static DELEGATE_STATE_IVAR: &'static [u8] = b"glutin_state";
+
+struct DelegateState<'a> {
+ is_closed: bool,
+ context: id,
+ view: id,
+ handler: Option<fn(uint, uint)>,
+}
+
+pub struct Window {
+ view: id,
+ window: id,
+ context: id,
+ delegate: id,
+ resize: Option<fn(uint, uint)>,
+
+ is_closed: Cell<bool>,
+}
+
+#[cfg(feature = "window")]
+impl Window {
+ pub fn new(builder: WindowBuilder) -> Result<Window, CreationError> {
+ if builder.sharing.is_some() {
+ unimplemented!()
+ }
+
+ Window::new_impl(builder.dimensions, builder.title.as_slice(), builder.monitor, builder.vsync, builder.visible, builder.gl_version)
+ }
+}
+
+#[cfg(feature = "window")]
+#[deriving(Clone)]
+pub struct WindowProxy;
+
+impl WindowProxy {
+ pub fn wakeup_event_loop(&self) {
+ unsafe {
+ let pool = NSAutoreleasePool::new(nil);
+ let event =
+ NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2(
+ nil,
+ NSApplicationDefined,
+ NSPoint::new(0.0, 0.0),
+ 0,
+ 0.0,
+ 0,
+ ptr::null_mut(),
+ 0,
+ 0,
+ 0);
+ NSApp().postEvent_atStart_(event, true);
+ pool.drain();
+ }
+ }
+}
+
+extern fn window_should_close(this: id, _: id) -> id {
+ unsafe {
+ let mut stored_value = ptr::null_mut();
+ object_getInstanceVariable(this, DELEGATE_STATE_IVAR.as_ptr() as *const i8, &mut stored_value);
+ let state = stored_value as *mut DelegateState;
+
+ (*state).is_closed = true;
+ }
+ 0
+}
+
+extern fn window_did_resize(this: id, _: id) -> id {
+ unsafe {
+ let mut stored_value = ptr::null_mut();
+ object_getInstanceVariable(this, DELEGATE_STATE_IVAR.as_ptr() as *const i8, &mut stored_value);
+ let state = &mut *(stored_value as *mut DelegateState);
+
+ let _: id = msg_send()(state.context, selector("update"));
+
+ match state.handler {
+ Some(handler) => {
+ let rect = NSView::frame(state.view);
+ (handler)(rect.size.width as uint, rect.size.height as uint);
+ }
+ None => {}
+ }
+ }
+ 0
+}
+
+impl Window {
+ fn new_impl(dimensions: Option<(uint, uint)>, title: &str, monitor: Option<MonitorID>,
+ vsync: bool, visible: bool, gl_version: Option<(uint, uint)>) -> Result<Window, CreationError> {
+ let app = match Window::create_app() {
+ Some(app) => app,
+ None => { return Err(OsError(format!("Couldn't create NSApplication"))); },
+ };
+ let window = match Window::create_window(dimensions.unwrap_or((800, 600)), title, monitor) {
+ Some(window) => window,
+ None => { return Err(OsError(format!("Couldn't create NSWindow"))); },
+ };
+ let view = match Window::create_view(window) {
+ Some(view) => view,
+ None => { return Err(OsError(format!("Couldn't create NSView"))); },
+ };
+
+ let context = match Window::create_context(view, vsync, gl_version) {
+ Some(context) => context,
+ None => { return Err(OsError(format!("Couldn't create OpenGL context"))); },
+ };
+
+ unsafe {
+ app.activateIgnoringOtherApps_(true);
+ if visible {
+ window.makeKeyAndOrderFront_(nil);
+ } else {
+ window.makeKeyWindow();
+ }
+ }
+
+ // Set up the window delegate to receive events
+ let ptr_size = mem::size_of::<libc::intptr_t>() as u64;
+ let ns_object = class("NSObject");
+
+ let delegate = unsafe {
+ // Create a delegate class, add callback methods and store InternalState as user data.
+ let delegate = objc_allocateClassPair(ns_object, DELEGATE_NAME.as_ptr() as *const i8, 0);
+ class_addMethod(delegate, selector("windowShouldClose:"), window_should_close, "B@:@".to_c_str().as_ptr());
+ class_addMethod(delegate, selector("windowDidResize:"), window_did_resize, "V@:@".to_c_str().as_ptr());
+ class_addIvar(delegate, DELEGATE_STATE_IVAR.as_ptr() as *const i8, ptr_size, 3, "?".to_c_str().as_ptr());
+ objc_registerClassPair(delegate);
+
+ let del_obj = msg_send()(delegate, selector("alloc"));
+ let del_obj: id = msg_send()(del_obj, selector("init"));
+ let _: id = msg_send()(window, selector("setDelegate:"), del_obj);
+ del_obj
+ };
+
+ let window = Window {
+ view: view,
+ window: window,
+ context: context,
+ delegate: delegate,
+ resize: None,
+
+ is_closed: Cell::new(false),
+ };
+
+ Ok(window)
+ }
+
+ fn create_app() -> Option<id> {
+ unsafe {
+ let app = NSApp();
+ if app == nil {
+ None
+ } else {
+ app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
+ app.finishLaunching();
+ Some(app)
+ }
+ }
+ }
+
+ fn create_window(dimensions: (uint, uint), title: &str, monitor: Option<MonitorID>) -> Option<id> {
+ unsafe {
+ let scr_frame = match monitor {
+ Some(_) => {
+ let screen = NSScreen::mainScreen(nil);
+ NSScreen::frame(screen)
+ }
+ None => {
+ let (width, height) = dimensions;
+ NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64))
+ }
+ };
+
+ let masks = match monitor {
+ Some(_) => NSBorderlessWindowMask as NSUInteger,
+ None => NSTitledWindowMask as NSUInteger |
+ NSClosableWindowMask as NSUInteger |
+ NSMiniaturizableWindowMask as NSUInteger |
+ NSResizableWindowMask as NSUInteger,
+ };
+
+ let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
+ scr_frame,
+ masks,
+ NSBackingStoreBuffered,
+ false,
+ );
+
+ if window == nil {
+ None
+ } else {
+ let title = NSString::alloc(nil).init_str(title);
+ window.setTitle_(title);
+ window.setAcceptsMouseMovedEvents_(true);
+ if monitor.is_some() {
+ window.setLevel_(NSMainMenuWindowLevel as i64 + 1);
+ }
+ else {
+ window.center();
+ }
+ Some(window)
+ }
+ }
+ }
+
+ fn create_view(window: id) -> Option<id> {
+ unsafe {
+ let view = NSView::alloc(nil).init();
+ if view == nil {
+ None
+ } else {
+ view.setWantsBestResolutionOpenGLSurface_(true);
+ window.setContentView_(view);
+ Some(view)
+ }
+ }
+ }
+
+ fn create_context(view: id, vsync: bool, gl_version: Option<(uint, uint)>) -> Option<id> {
+ let profile = match gl_version {
+ None | Some((0...2, _)) | Some((3, 0)) => NSOpenGLProfileVersionLegacy as uint,
+ Some((3, 1...2)) => NSOpenGLProfileVersion3_2Core as uint,
+ Some((_, _)) => NSOpenGLProfileVersion4_1Core as uint,
+ };
+ unsafe {
+ let attributes = [
+ NSOpenGLPFADoubleBuffer as uint,
+ NSOpenGLPFAClosestPolicy as uint,
+ NSOpenGLPFAColorSize as uint, 24,
+ NSOpenGLPFAAlphaSize as uint, 8,
+ NSOpenGLPFADepthSize as uint, 24,
+ NSOpenGLPFAStencilSize as uint, 8,
+ NSOpenGLPFAOpenGLProfile as uint, profile,
+ 0
+ ];
+
+ let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes);
+ if pixelformat == nil {
+ return None;
+ }
+
+ let context = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
+ if context == nil {
+ None
+ } else {
+ context.setView_(view);
+ if vsync {
+ let value = 1;
+ context.setValues_forParameter_(&value, NSOpenGLContextParameter::NSOpenGLCPSwapInterval);
+ }
+ Some(context)
+ }
+ }
+ }
+
+ pub fn is_closed(&self) -> bool {
+ self.is_closed.get()
+ }
+
+ pub fn set_title(&self, title: &str) {
+ unsafe {
+ let title = NSString::alloc(nil).init_str(title);
+ self.window.setTitle_(title);
+ }
+ }
+
+ pub fn show(&self) {
+ }
+
+ pub fn hide(&self) {
+ }
+
+ pub fn get_position(&self) -> Option<(int, int)> {
+ unimplemented!()
+ }
+
+ pub fn set_position(&self, _x: int, _y: int) {
+ unimplemented!()
+ }
+
+ pub fn get_inner_size(&self) -> Option<(uint, uint)> {
+ let rect = unsafe { NSView::frame(self.view) };
+ Some((rect.size.width as uint, rect.size.height as uint))
+ }
+
+ pub fn get_outer_size(&self) -> Option<(uint, uint)> {
+ unimplemented!()
+ }
+
+ pub fn set_inner_size(&self, _x: uint, _y: uint) {
+ unimplemented!()
+ }
+
+ pub fn create_window_proxy(&self) -> WindowProxy {
+ WindowProxy
+ }
+
+ pub fn poll_events(&self) -> Vec<Event> {
+ let mut events = Vec::new();
+
+ loop {
+ unsafe {
+ let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
+ NSAnyEventMask as u64,
+ NSDate::distantPast(nil),
+ NSDefaultRunLoopMode,
+ true);
+ if event == nil { break; }
+ {
+ // Create a temporary structure with state that delegates called internally
+ // by sendEvent can read and modify. When that returns, update window state.
+ // This allows the synchronous resize loop to continue issuing callbacks
+ // to the user application, by passing handler through to the delegate state.
+ let mut ds = DelegateState {
+ is_closed: self.is_closed.get(),
+ context: self.context,
+ view: self.view,
+ handler: self.resize,
+ };
+ object_setInstanceVariable(self.delegate,
+ DELEGATE_STATE_IVAR.as_ptr() as *const i8,
+ &mut ds as *mut DelegateState as *mut libc::c_void);
+ NSApp().sendEvent_(event);
+ object_setInstanceVariable(self.delegate,
+ DELEGATE_STATE_IVAR.as_ptr() as *const i8,
+ ptr::null_mut());
+ self.is_closed.set(ds.is_closed);
+}
+
+ match event.get_type() {
+ NSLeftMouseDown => { events.push(MouseInput(Pressed, LeftMouseButton)); },
+ NSLeftMouseUp => { events.push(MouseInput(Released, LeftMouseButton)); },
+ NSRightMouseDown => { events.push(MouseInput(Pressed, RightMouseButton)); },
+ NSRightMouseUp => { events.push(MouseInput(Released, RightMouseButton)); },
+ 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 => {
+ 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());
+ events.push(KeyboardInput(Pressed, event.keycode() as u8, vkey));
+ },
+ NSKeyUp => {
+ let vkey = event::vkeycode_to_element(event.keycode());
+ events.push(KeyboardInput(Released, event.keycode() as u8, vkey));
+ },
+ NSFlagsChanged => {
+ let shift_modifier = Window::modifier_event(event, appkit::NSShiftKeyMask as u64, events::VirtualKeyCode::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::VirtualKeyCode::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::VirtualKeyCode::LWin, win_pressed);
+ if win_modifier.is_some() {
+ win_pressed = !win_pressed;
+ events.push(win_modifier.unwrap());
+ }
+ let alt_modifier = Window::modifier_event(event, appkit::NSAlternateKeyMask as u64, events::VirtualKeyCode::LAlt, alt_pressed);
+ if alt_modifier.is_some() {
+ alt_pressed = !alt_pressed;
+ events.push(alt_modifier.unwrap());
+ }
+ },
+ NSScrollWheel => { events.push(MouseWheel(-event.scrollingDeltaY() as i32)); },
+ NSOtherMouseDown => { },
+ NSOtherMouseUp => { },
+ NSOtherMouseDragged => { },
+ _ => { },
+ }
+ }
+ }
+ 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)));
+ }
+ else if key_pressed && !Window::modifier_key_pressed(event, keymask) {
+ return Some(KeyboardInput(Released, event.keycode() as u8, Some(key)));
+ }
+
+ 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_(
+ NSAnyEventMask as u64,
+ NSDate::distantFuture(nil),
+ NSDefaultRunLoopMode,
+ false);
+ NSApp().sendEvent_(event);
+
+ self.poll_events()
+ }
+ }
+
+ pub unsafe fn make_current(&self) {
+ self.context.makeCurrentContext();
+ }
+
+ pub fn get_proc_address(&self, _addr: &str) -> *const () {
+ let symbol_name = _addr.parse::<CFString>().unwrap();
+ let framework_name = "com.apple.opengl".parse::<CFString>().unwrap();
+ let framework = unsafe {
+ CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
+ };
+ let symbol = unsafe {
+ CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
+ };
+ symbol as *const ()
+ }
+
+ pub fn swap_buffers(&self) {
+ unsafe { self.context.flushBuffer(); }
+ }
+
+ pub fn platform_display(&self) -> *mut libc::c_void {
+ unimplemented!()
+ }
+
+ pub fn get_api(&self) -> ::Api {
+ ::Api::OpenGl
+ }
+
+ pub fn set_window_resize_callback(&mut self, callback: Option<fn(uint, uint)>) {
+ self.resize = callback;
+ }
+}
diff --git a/src/osx/monitor.rs b/src/osx/monitor.rs
index 383fd32..912c02d 100644
--- a/src/osx/monitor.rs
+++ b/src/osx/monitor.rs
@@ -1,18 +1,19 @@
use core_graphics::display;
+use std::collections::RingBuf;
pub struct MonitorID(u32);
-pub fn get_available_monitors() -> Vec<MonitorID> {
- let mut monitors = Vec::new();
+pub fn get_available_monitors() -> RingBuf<MonitorID> {
+ let mut monitors = RingBuf::new();
unsafe {
let max_displays = 10u32;
- let mut active_displays = [0u32, ..10];
+ let mut active_displays = [0u32; 10];
let mut display_count = 0;
display::CGGetActiveDisplayList(max_displays,
&mut active_displays[0],
&mut display_count);
- for i in range(0u, display_count as uint) {
- monitors.push(MonitorID(active_displays[i]));
+ for i in range(0us, display_count as usize) {
+ monitors.push_back(MonitorID(active_displays[i]));
}
}
monitors
@@ -34,12 +35,12 @@ impl MonitorID {
Some(format!("Monitor #{}", screen_num))
}
- pub fn get_dimensions(&self) -> (uint, uint) {
+ pub fn get_dimensions(&self) -> (u32, u32) {
let MonitorID(display_id) = *self;
let dimension = unsafe {
let height = display::CGDisplayPixelsHigh(display_id);
let width = display::CGDisplayPixelsWide(display_id);
- (width as uint, height as uint)
+ (width as u32, height as u32)
};
dimension
}
diff --git a/src/win32/init.rs b/src/win32/init.rs
index 3cdf8d5..7317c42 100644
--- a/src/win32/init.rs
+++ b/src/win32/init.rs
@@ -6,7 +6,9 @@ use {CreationError, Event};
use CreationError::OsError;
use std::cell::RefCell;
+use std::ffi::CString;
use std::rc::Rc;
+use std::sync::mpsc::{Sender, Receiver, channel};
use libc;
use super::gl;
@@ -18,11 +20,15 @@ use winapi;
/// receive an event for another window.
thread_local!(static WINDOW: Rc<RefCell<Option<(winapi::HWND, Sender<Event>)>>> = Rc::new(RefCell::new(None)));
-pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: String,
+/// Work-around the fact that HGLRC doesn't implement Send
+pub struct ContextHack(pub winapi::HGLRC);
+unsafe impl Send for ContextHack {}
+
+pub fn new_window(builder_dimensions: Option<(u32, u32)>, builder_title: String,
builder_monitor: Option<super::MonitorID>,
- builder_gl_version: Option<(uint, uint)>, builder_debug: bool,
+ builder_gl_version: Option<(u32, u32)>, builder_debug: bool,
builder_vsync: bool, builder_hidden: bool,
- builder_sharelists: Option<winapi::HGLRC>, builder_multisampling: Option<u16>)
+ builder_sharelists: Option<ContextHack>, builder_multisampling: Option<u16>)
-> Result<Window, CreationError>
{
use std::mem;
@@ -38,6 +44,8 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin
// so we create a new thread dedicated to this window.
// This is the only safe method. Using `nosend` wouldn't work for non-native runtime.
::std::thread::Thread::spawn(move || {
+ let builder_sharelists = builder_sharelists.map(|s| s.0);
+
// registering the window class
let class_name = {
let class_name: Vec<u16> = "Window Class".utf16_units().chain(Some(0).into_iter())
@@ -132,7 +140,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin
if handle.is_null() {
use std::os;
tx.send(Err(OsError(format!("CreateWindowEx function failed: {}",
- os::error_string(os::errno() as uint)))));
+ os::error_string(os::errno() as usize)))));
return;
}
@@ -144,7 +152,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin
let hdc = unsafe { winapi::GetDC(dummy_window) };
if hdc.is_null() {
tx.send(Err(OsError(format!("GetDC function failed: {}",
- os::error_string(os::errno() as uint)))));
+ os::error_string(os::errno() as usize)))));
unsafe { winapi::DestroyWindow(dummy_window); }
return;
}
@@ -172,7 +180,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin
if pf_index == 0 {
tx.send(Err(OsError(format!("ChoosePixelFormat function failed: {}",
- os::error_string(os::errno() as uint)))));
+ os::error_string(os::errno() as usize)))));
unsafe { winapi::DestroyWindow(dummy_window); }
return;
}
@@ -181,7 +189,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin
mem::size_of::<winapi::PIXELFORMATDESCRIPTOR>() as winapi::UINT, &mut output) } == 0
{
tx.send(Err(OsError(format!("DescribePixelFormat function failed: {}",
- os::error_string(os::errno() as uint)))));
+ os::error_string(os::errno() as usize)))));
unsafe { winapi::DestroyWindow(dummy_window); }
return;
}
@@ -193,7 +201,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin
unsafe {
if winapi::SetPixelFormat(dummy_hdc, 1, &pixel_format) == 0 {
tx.send(Err(OsError(format!("SetPixelFormat function failed: {}",
- os::error_string(os::errno() as uint)))));
+ os::error_string(os::errno() as usize)))));
winapi::DestroyWindow(dummy_window);
return;
}
@@ -204,7 +212,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin
let ctxt = unsafe { gl::wgl::CreateContext(dummy_hdc as *const libc::c_void) };
if ctxt.is_null() {
tx.send(Err(OsError(format!("wglCreateContext function failed: {}",
- os::error_string(os::errno() as uint)))));
+ os::error_string(os::errno() as usize)))));
unsafe { winapi::DestroyWindow(dummy_window); }
return;
}
@@ -216,11 +224,13 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin
// loading the extra WGL functions
let extra_functions = gl::wgl_extra::Wgl::load_with(|addr| {
+ use libc;
+
+ let addr = CString::from_slice(addr.as_bytes());
+ let addr = addr.as_slice_with_nul().as_ptr();
+
unsafe {
- addr.with_c_str(|s| {
- use libc;
- gl::wgl::GetProcAddress(s) as *const libc::c_void
- })
+ gl::wgl::GetProcAddress(addr) as *const libc::c_void
}
});
@@ -261,7 +271,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin
if handle.is_null() {
use std::os;
tx.send(Err(OsError(format!("CreateWindowEx function failed: {}",
- os::error_string(os::errno() as uint)))));
+ os::error_string(os::errno() as usize)))));
return;
}
@@ -273,7 +283,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin
let hdc = unsafe { winapi::GetDC(real_window) };
if hdc.is_null() {
tx.send(Err(OsError(format!("GetDC function failed: {}",
- os::error_string(os::errno() as uint)))));
+ os::error_string(os::errno() as usize)))));
unsafe { winapi::DestroyWindow(real_window); }
return;
}
@@ -284,7 +294,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin
unsafe {
if winapi::SetPixelFormat(hdc, 1, &pixel_format) == 0 {
tx.send(Err(OsError(format!("SetPixelFormat function failed: {}",
- os::error_string(os::errno() as uint)))));
+ os::error_string(os::errno() as usize)))));
winapi::DestroyWindow(real_window);
return;
}
@@ -329,7 +339,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin
if ctxt.is_null() {
tx.send(Err(OsError(format!("OpenGL context creation failed: {}",
- os::error_string(os::errno() as uint)))));
+ os::error_string(os::errno() as usize)))));
unsafe { winapi::DestroyWindow(real_window); }
return;
}
@@ -359,7 +369,7 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin
let lib = unsafe { winapi::LoadLibraryW(name) };
if lib.is_null() {
tx.send(Err(OsError(format!("LoadLibrary function failed: {}",
- os::error_string(os::errno() as uint)))));
+ os::error_string(os::errno() as usize)))));
unsafe { gl::wgl::DeleteContext(context); }
unsafe { winapi::DestroyWindow(real_window); }
return;
@@ -409,9 +419,9 @@ pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: Strin
unsafe { winapi::TranslateMessage(&msg) };
unsafe { winapi::DispatchMessageW(&msg) }; // calls `callback` (see below)
}
- }).detach();
+ });
- rx.recv()
+ rx.recv().unwrap()
}
/// Checks that the window is the good one, and if so send the event to it.
@@ -429,7 +439,7 @@ fn send_event(input_window: winapi::HWND, event: Event) {
return;
}
- sender.send_opt(event).ok(); // ignoring if closed
+ sender.send(event).ok(); // ignoring if closed
});
}
@@ -465,16 +475,16 @@ extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT,
winapi::WM_SIZE => {
use events::Event::Resized;
- let w = winapi::LOWORD(lparam as winapi::DWORD) as uint;
- let h = winapi::HIWORD(lparam as winapi::DWORD) as uint;
+ let w = winapi::LOWORD(lparam as winapi::DWORD) as u32;
+ let h = winapi::HIWORD(lparam as winapi::DWORD) as u32;
send_event(window, Resized(w, h));
0
},
winapi::WM_MOVE => {
use events::Event::Moved;
- let x = winapi::LOWORD(lparam as winapi::DWORD) as i16 as int;
- let y = winapi::HIWORD(lparam as winapi::DWORD) as i16 as int;
+ let x = winapi::LOWORD(lparam as winapi::DWORD) as i32;
+ let y = winapi::HIWORD(lparam as winapi::DWORD) as i32;
send_event(window, Moved(x, y));
0
},
@@ -490,8 +500,8 @@ extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT,
winapi::WM_MOUSEMOVE => {
use events::Event::MouseMoved;
- let x = winapi::GET_X_LPARAM(lparam) as int;
- let y = winapi::GET_Y_LPARAM(lparam) as int;
+ let x = winapi::GET_X_LPARAM(lparam) as i32;
+ let y = winapi::GET_Y_LPARAM(lparam) as i32;
send_event(window, MouseMoved((x, y)));
diff --git a/src/win32/mod.rs b/src/win32/mod.rs
index dba08e5..e6964b4 100644
--- a/src/win32/mod.rs
+++ b/src/win32/mod.rs
@@ -1,13 +1,12 @@
use std::sync::atomic::AtomicBool;
use std::ptr;
+use std::ffi::CString;
+use std::collections::RingBuf;
+use std::sync::mpsc::Receiver;
use libc;
-use {CreationError, Event};
+use {CreationError, Event, MouseCursor};
-#[cfg(feature = "window")]
-use WindowBuilder;
-
-#[cfg(feature = "headless")]
-use HeadlessRendererBuilder;
+use BuilderAttribs;
pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};
@@ -18,16 +17,14 @@ mod gl;
mod init;
mod monitor;
-///
-#[cfg(feature = "headless")]
+///
pub struct HeadlessContext(Window);
-#[cfg(feature = "headless")]
impl HeadlessContext {
/// See the docs in the crate root file.
- pub fn new(builder: HeadlessRendererBuilder) -> Result<HeadlessContext, CreationError> {
- let HeadlessRendererBuilder { dimensions, gl_version, gl_debug } = builder;
- init::new_window(Some(dimensions), "".to_string(), None, gl_version, gl_debug, false, true,
+ pub fn new(builder: BuilderAttribs) -> Result<HeadlessContext, CreationError> {
+ let BuilderAttribs { dimensions, gl_version, gl_debug, .. } = builder;
+ init::new_window(dimensions, "".to_string(), None, gl_version, gl_debug, false, true,
None, None)
.map(|w| HeadlessContext(w))
}
@@ -47,10 +44,15 @@ impl HeadlessContext {
::Api::OpenGl
}
- pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) {
+ pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) {
}
}
+#[cfg(feature = "headless")]
+unsafe impl Send for HeadlessContext {}
+#[cfg(feature = "headless")]
+unsafe impl Sync for HeadlessContext {}
+
/// The Win32 implementation of the main `Window` object.
pub struct Window {
/// Main handle for the window.
@@ -75,18 +77,21 @@ pub struct Window {
is_closed: AtomicBool,
}
-#[cfg(feature = "window")]
+unsafe impl Send for Window {}
+unsafe impl Sync for Window {}
+
impl Window {
/// See the docs in the crate root file.
- pub fn new(builder: WindowBuilder) -> Result<Window, CreationError> {
- let WindowBuilder { dimensions, title, monitor, gl_version,
- gl_debug, vsync, visible, sharing, multisampling } = builder;
+ pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
+ let BuilderAttribs { dimensions, title, monitor, gl_version,
+ gl_debug, vsync, visible, sharing, multisampling, .. } = builder;
init::new_window(dimensions, title, monitor, gl_version, gl_debug, vsync,
- !visible, sharing.map(|w| w.window.context), multisampling)
+ !visible, sharing.map(|w| init::ContextHack(w.context)),
+ multisampling)
}
}
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct WindowProxy;
impl WindowProxy {
@@ -98,12 +103,12 @@ impl WindowProxy {
impl Window {
/// See the docs in the crate root file.
pub fn is_closed(&self) -> bool {
- use std::sync::atomic::Relaxed;
+ use std::sync::atomic::Ordering::Relaxed;
self.is_closed.load(Relaxed)
}
/// See the docs in the crate root file.
- ///
+ ///
/// Calls SetWindowText on the HWND.
pub fn set_title(&self, text: &str) {
unsafe {
@@ -126,7 +131,7 @@ impl Window {
}
/// See the docs in the crate root file.
- pub fn get_position(&self) -> Option<(int, int)> {
+ pub fn get_position(&self) -> Option<(i32, i32)> {
use std::mem;
let mut placement: winapi::WINDOWPLACEMENT = unsafe { mem::zeroed() };
@@ -137,11 +142,11 @@ impl Window {
}
let ref rect = placement.rcNormalPosition;
- Some((rect.left as int, rect.top as int))
+ Some((rect.left as i32, rect.top as i32))
}
/// See the docs in the crate root file.
- pub fn set_position(&self, x: int, y: int) {
+ pub fn set_position(&self, x: i32, y: i32) {
use libc;
unsafe {
@@ -152,7 +157,7 @@ impl Window {
}
/// See the docs in the crate root file.
- pub fn get_inner_size(&self) -> Option<(uint, uint)> {
+ pub fn get_inner_size(&self) -> Option<(u32, u32)> {
use std::mem;
let mut rect: winapi::RECT = unsafe { mem::uninitialized() };
@@ -161,13 +166,13 @@ impl Window {
}
Some((
- (rect.right - rect.left) as uint,
- (rect.bottom - rect.top) as uint
+ (rect.right - rect.left) as u32,
+ (rect.bottom - rect.top) as u32
))
}
/// See the docs in the crate root file.
- pub fn get_outer_size(&self) -> Option<(uint, uint)> {
+ pub fn get_outer_size(&self) -> Option<(u32, u32)> {
use std::mem;
let mut rect: winapi::RECT = unsafe { mem::uninitialized() };
@@ -176,13 +181,13 @@ impl Window {
}
Some((
- (rect.right - rect.left) as uint,
- (rect.bottom - rect.top) as uint
+ (rect.right - rect.left) as u32,
+ (rect.bottom - rect.top) as u32
))
}
/// See the docs in the crate root file.
- pub fn set_inner_size(&self, x: uint, y: uint) {
+ pub fn set_inner_size(&self, x: u32, y: u32) {
use libc;
unsafe {
@@ -198,33 +203,33 @@ impl Window {
/// See the docs in the crate root file.
// TODO: return iterator
- pub fn poll_events(&self) -> Vec<Event> {
- let mut events = Vec::new();
+ pub fn poll_events(&self) -> RingBuf<Event> {
+ let mut events = RingBuf::new();
loop {
match self.events_receiver.try_recv() {
- Ok(ev) => events.push(ev),
+ Ok(ev) => events.push_back(ev),
Err(_) => break
}
}
// if one of the received events is `Closed`, setting `is_closed` to true
if events.iter().any(|e| match e { &::events::Event::Closed => true, _ => false }) {
- use std::sync::atomic::Relaxed;
+ use std::sync::atomic::Ordering::Relaxed;
self.is_closed.store(true, Relaxed);
}
-
+
events
}
/// See the docs in the crate root file.
// TODO: return iterator
- pub fn wait_events(&self) -> Vec<Event> {
- match self.events_receiver.recv_opt() {
+ pub fn wait_events(&self) -> RingBuf<Event> {
+ match self.events_receiver.recv() {
Ok(ev) => {
// if the received event is `Closed`, setting `is_closed` to true
match ev {
::events::Event::Closed => {
- use std::sync::atomic::Relaxed;
+ use std::sync::atomic::Ordering::Relaxed;
self.is_closed.store(true, Relaxed);
},
_ => ()
@@ -237,9 +242,9 @@ impl Window {
},
Err(_) => {
- use std::sync::atomic::Relaxed;
+ use std::sync::atomic::Ordering::Relaxed;
self.is_closed.store(true, Relaxed);
- vec![]
+ RingBuf::new()
}
}
}
@@ -252,14 +257,13 @@ impl Window {
/// See the docs in the crate root file.
pub fn get_proc_address(&self, addr: &str) -> *const () {
- use std::c_str::ToCStr;
+ let addr = CString::from_slice(addr.as_bytes());
+ let addr = addr.as_slice_with_nul().as_ptr();
unsafe {
- addr.with_c_str(|s| {
- let p = gl::wgl::GetProcAddress(s) as *const ();
- if !p.is_null() { return p; }
- winapi::GetProcAddress(self.gl_library, s) as *const ()
- })
+ let p = gl::wgl::GetProcAddress(addr) as *const ();
+ if !p.is_null() { return p; }
+ winapi::GetProcAddress(self.gl_library, addr) as *const ()
}
}
@@ -279,7 +283,11 @@ impl Window {
::Api::OpenGl
}
- pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) {
+ pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) {
+ }
+
+ pub fn set_cursor(&self, cursor: MouseCursor) {
+ unimplemented!()
}
}
diff --git a/src/win32/monitor.rs b/src/win32/monitor.rs
index f841f1e..2078a52 100644
--- a/src/win32/monitor.rs
+++ b/src/win32/monitor.rs
@@ -1,9 +1,11 @@
use winapi;
+use std::collections::RingBuf;
+
/// Win32 implementation of the main `MonitorID` object.
pub struct MonitorID {
/// The system name of the monitor.
- name: [winapi::WCHAR, ..32],
+ name: [winapi::WCHAR; 32],
/// Name to give to the user.
readable_name: String,
@@ -15,22 +17,22 @@ pub struct MonitorID {
/// The position of the monitor in pixels on the desktop.
///
/// A window that is positionned at these coordinates will overlap the monitor.
- position: (uint, uint),
+ position: (u32, u32),
/// The current resolution in pixels on the monitor.
- dimensions: (uint, uint),
+ dimensions: (u32, u32),
}
/// Win32 implementation of the main `get_available_monitors` function.
-pub fn get_available_monitors() -> Vec<MonitorID> {
+pub fn get_available_monitors() -> RingBuf<MonitorID> {
use std::{iter, mem, ptr};
// return value
- let mut result = Vec::new();
+ let mut result = RingBuf::new();
// enumerating the devices is done by querying device 0, then device 1, then device 2, etc.
// until the query function returns null
- for id in iter::count(0u, 1) {
+ for id in iter::count(0u32, 1) {
// getting the DISPLAY_DEVICEW object of the current device
let output = {
let mut output: winapi::DISPLAY_DEVICEW = unsafe { mem::zeroed() };
@@ -56,7 +58,7 @@ pub fn get_available_monitors() -> Vec<MonitorID> {
// computing the human-friendly name
let readable_name = String::from_utf16_lossy(output.DeviceString.as_slice());
- let readable_name = readable_name.as_slice().trim_right_chars(0 as char).to_string();
+ let readable_name = readable_name.as_slice().trim_right_matches(0 as char).to_string();
// getting the position
let (position, dimensions) = unsafe {
@@ -70,15 +72,15 @@ pub fn get_available_monitors() -> Vec<MonitorID> {
}
let point: &winapi::POINTL = mem::transmute(&dev.union1);
- let position = (point.x as uint, point.y as uint);
+ let position = (point.x as u32, point.y as u32);
- let dimensions = (dev.dmPelsWidth as uint, dev.dmPelsHeight as uint);
+ let dimensions = (dev.dmPelsWidth as u32, dev.dmPelsHeight as u32);
(position, dimensions)
};
// adding to the resulting list
- result.push(MonitorID {
+ result.push_back(MonitorID {
name: output.DeviceName,
readable_name: readable_name,
flags: output.StateFlags,
@@ -111,7 +113,7 @@ impl MonitorID {
}
/// See the docs if the crate root file.
- pub fn get_dimensions(&self) -> (uint, uint) {
+ pub fn get_dimensions(&self) -> (u32, u32) {
// TODO: retreive the dimensions every time this is called
self.dimensions
}
@@ -123,9 +125,9 @@ impl MonitorID {
}
/// This is a Win32-only function for `MonitorID` that returns the position of the
- /// monitor on the desktop.
+ /// monitor on the desktop.
/// A window that is positionned at these coordinates will overlap the monitor.
- pub fn get_position(&self) -> (uint, uint) {
+ pub fn get_position(&self) -> (u32, u32) {
self.position
}
}
diff --git a/src/x11/ffi.rs b/src/x11/ffi.rs
index 5610eee..5e7b5a1 100644
--- a/src/x11/ffi.rs
+++ b/src/x11/ffi.rs
@@ -1241,7 +1241,7 @@ pub struct XSetWindowAttributes {
#[repr(C)]
pub struct XEvent {
pub type_: libc::c_int,
- pad: [libc::c_long, ..24],
+ pad: [libc::c_long; 24],
}
#[repr(C)]
@@ -1253,7 +1253,7 @@ pub struct XClientMessageEvent {
pub window: Window,
pub message_type: Atom,
pub format: libc::c_int,
- pub l: [libc::c_long, ..5],
+ pub l: [libc::c_long; 5],
}
#[repr(C)]
@@ -1384,6 +1384,7 @@ extern "C" {
#[link(name = "GL")]
#[link(name = "X11")]
#[link(name = "Xxf86vm")]
+#[link(name = "Xcursor")]
extern "C" {
pub fn XCloseDisplay(display: *mut Display);
pub fn XCheckMaskEvent(display: *mut Display, event_mask: libc::c_long,
@@ -1435,7 +1436,7 @@ extern "C" {
res_class: *mut libc::c_char) -> XIM;
// TODO: this is a vararg function
- //pub fn XCreateIC(im: XIM, ...) -> XIC;
+ //pub fn XCreateIC(im: XIM; .) -> XIC;
pub fn XCreateIC(im: XIM, a: *const libc::c_char, b: libc::c_long, c: *const libc::c_char,
d: Window, e: *const ()) -> XIC;
pub fn XDestroyIC(ic: XIC);
@@ -1454,6 +1455,9 @@ extern "C" {
x: libc::c_int, y: libc::c_int) -> Bool;
pub fn XF86VidModeGetAllModeLines(dpy: *mut Display, screen: libc::c_int,
modecount_return: *mut libc::c_int, modesinfo: *mut *mut *mut XF86VidModeModeInfo) -> Bool;
+
+ pub fn XcursorLibraryLoadCursor(dpy: *mut Display, name: *const libc::c_char) -> Cursor;
+ pub fn XDefineCursor(dby: *mut Display, w: Window, cursor: Cursor);
}
/*
diff --git a/src/x11/headless.rs b/src/x11/headless.rs
index 95f5233..7692832 100644
--- a/src/x11/headless.rs
+++ b/src/x11/headless.rs
@@ -1,23 +1,32 @@
-use HeadlessRendererBuilder;
+use BuilderAttribs;
use CreationError;
use CreationError::OsError;
use libc;
use std::{mem, ptr};
use super::ffi;
+fn with_c_str<F, T>(s: &str, f: F) -> T where F: FnOnce(*const i8) -> T {
+ use std::ffi::CString;
+ let c_str = CString::from_slice(s.as_bytes());
+ f(c_str.as_slice_with_nul().as_ptr())
+}
+
pub struct HeadlessContext {
context: ffi::OSMesaContext,
buffer: Vec<u32>,
- width: uint,
- height: uint,
+ width: u32,
+ height: u32,
}
impl HeadlessContext {
- pub fn new(builder: HeadlessRendererBuilder) -> Result<HeadlessContext, CreationError> {
+ pub fn new(builder: BuilderAttribs) -> Result<HeadlessContext, CreationError> {
+ let dimensions = builder.dimensions.unwrap();
+
Ok(HeadlessContext {
- width: builder.dimensions.0,
- height: builder.dimensions.1,
- buffer: Vec::from_elem(builder.dimensions.0 * builder.dimensions.1, unsafe { mem::uninitialized() }),
+ width: dimensions.0,
+ height: dimensions.1,
+ buffer: ::std::iter::repeat(unsafe { mem::uninitialized() })
+ .take((dimensions.0 * dimensions.1) as usize).collect(),
context: unsafe {
let ctxt = ffi::OSMesaCreateContext(0x1908, ptr::null());
if ctxt.is_null() {
@@ -39,10 +48,8 @@ impl HeadlessContext {
}
pub fn get_proc_address(&self, addr: &str) -> *const () {
- use std::c_str::ToCStr;
-
unsafe {
- addr.with_c_str(|s| {
+ with_c_str(addr, |s| {
ffi::OSMesaGetProcAddress(mem::transmute(s)) as *const ()
})
}
@@ -53,7 +60,7 @@ impl HeadlessContext {
::Api::OpenGl
}
- pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) {
+ pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) {
}
}
@@ -62,3 +69,6 @@ impl Drop for HeadlessContext {
unsafe { ffi::OSMesaDestroyContext(self.context) }
}
}
+
+unsafe impl Send for HeadlessContext {}
+unsafe impl Sync for HeadlessContext {}
diff --git a/src/x11/mod.rs b/src/x11/mod.rs
index 9ce789f..22184a9 100644
--- a/src/x11/mod.rs
+++ b/src/x11/mod.rs
@@ -11,3 +11,8 @@ mod headless;
#[cfg(feature = "window")]
mod window;
+
+#[cfg(not(feature = "window"))]
+pub type Window = (); // TODO: hack to make things work
+#[cfg(not(feature = "window"))]
+pub type MonitorID = (); // TODO: hack to make things work
diff --git a/src/x11/window/mod.rs b/src/x11/window/mod.rs
index 422b5b6..5b70a19 100644
--- a/src/x11/window/mod.rs
+++ b/src/x11/window/mod.rs
@@ -1,10 +1,11 @@
-use {Event, WindowBuilder};
+use {Event, BuilderAttribs, MouseCursor};
use CreationError;
use CreationError::OsError;
use libc;
use std::{mem, ptr};
use std::cell::Cell;
use std::sync::atomic::AtomicBool;
+use std::collections::RingBuf;
use super::ffi;
use std::sync::{Arc, Once, ONCE_INIT};
@@ -16,13 +17,19 @@ mod monitor;
static THREAD_INIT: Once = ONCE_INIT;
fn ensure_thread_init() {
- THREAD_INIT.doit(|| {
+ THREAD_INIT.call_once(|| {
unsafe {
ffi::XInitThreads();
}
});
}
+fn with_c_str<F, T>(s: &str, f: F) -> T where F: FnOnce(*const i8) -> T {
+ use std::ffi::CString;
+ let c_str = CString::from_slice(s.as_bytes());
+ f(c_str.as_slice_with_nul().as_ptr())
+}
+
struct XWindow {
display: *mut ffi::Display,
window: ffi::Window,
@@ -34,6 +41,9 @@ struct XWindow {
im: ffi::XIM,
}
+unsafe impl Send for Window {}
+unsafe impl Sync for Window {}
+
impl Drop for XWindow {
fn drop(&mut self) {
unsafe {
@@ -53,7 +63,7 @@ impl Drop for XWindow {
}
}
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct WindowProxy {
x: Arc<XWindow>,
}
@@ -86,7 +96,7 @@ pub struct Window {
}
impl Window {
- pub fn new(builder: WindowBuilder) -> Result<Window, CreationError> {
+ pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
ensure_thread_init();
let dimensions = builder.dimensions.unwrap_or((800, 600));
@@ -150,7 +160,7 @@ impl Window {
}
for i in range(0, mode_num) {
- let mode: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(i as int) as *const _);
+ let mode: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(i as isize) as *const _);
if mode.hdisplay == dimensions.0 as u16 && mode.vdisplay == dimensions.1 as u16 {
best_mode = i;
}
@@ -159,7 +169,7 @@ impl Window {
return Err(OsError(format!("Could not find a suitable graphics mode")));
}
- modes
+ modes
};
let xf86_desk_mode = unsafe {
@@ -205,7 +215,7 @@ impl Window {
if builder.monitor.is_some() {
window_attributes |= ffi::CWOverrideRedirect;
unsafe {
- ffi::XF86VidModeSwitchToMode(display, screen_id, *modes.offset(best_mode as int));
+ ffi::XF86VidModeSwitchToMode(display, screen_id, *modes.offset(best_mode as isize));
ffi::XF86VidModeSetViewPort(display, screen_id, 0, 0);
set_win_attr.override_redirect = 1;
}
@@ -230,13 +240,13 @@ impl Window {
// creating window, step 2
let wm_delete_window = unsafe {
- use std::c_str::ToCStr;
-
- let delete_window = "WM_DELETE_WINDOW".to_c_str();
- let mut wm_delete_window = ffi::XInternAtom(display, delete_window.as_ptr(), 0);
+ let mut wm_delete_window = with_c_str("WM_DELETE_WINDOW", |delete_window|
+ ffi::XInternAtom(display, delete_window, 0)
+ );
ffi::XSetWMProtocols(display, window, &mut wm_delete_window, 1);
- let c_title = builder.title.to_c_str();
- ffi::XStoreName(display, window, c_title.as_ptr());
+ with_c_str(&*builder.title, |title| {;
+ ffi::XStoreName(display, window, title);
+ });
ffi::XFlush(display);
wm_delete_window
@@ -253,13 +263,15 @@ impl Window {
// creating input context
let ic = unsafe {
- use std::c_str::ToCStr;
-
- let input_style = "inputStyle".to_c_str();
- let client_window = "clientWindow".to_c_str();
- let ic = ffi::XCreateIC(im, input_style.as_ptr(),
- ffi::XIMPreeditNothing | ffi::XIMStatusNothing, client_window.as_ptr(),
- window, ptr::null());
+ let ic = with_c_str("inputStyle", |input_style|
+ with_c_str("clientWindow", |client_window|
+ ffi::XCreateIC(
+ im, input_style,
+ ffi::XIMPreeditNothing | ffi::XIMStatusNothing, client_window,
+ window, ptr::null()
+ )
+ )
+ );
if ic.is_null() {
return Err(OsError(format!("XCreateIC failed")));
}
@@ -298,14 +310,14 @@ impl Window {
// loading the extra GLX functions
let extra_functions = ffi::glx_extra::Glx::load_with(|addr| {
- addr.with_c_str(|s| {
+ with_c_str(addr, |s| {
use libc;
ffi::glx::GetProcAddress(s as *const u8) as *const libc::c_void
})
});
let share = if let Some(win) = builder.sharing {
- win.window.x.context
+ win.x.context
} else {
ptr::null()
};
@@ -346,16 +358,15 @@ impl Window {
}
pub fn is_closed(&self) -> bool {
- use std::sync::atomic::Relaxed;
+ use std::sync::atomic::Ordering::Relaxed;
self.is_closed.load(Relaxed)
}
pub fn set_title(&self, title: &str) {
- let c_title = title.to_c_str();
- unsafe {
- ffi::XStoreName(self.x.display, self.x.window, c_title.as_ptr());
+ with_c_str(title, |title| unsafe {
+ ffi::XStoreName(self.x.display, self.x.window, title);
ffi::XFlush(self.x.display);
- }
+ })
}
pub fn show(&self) {
@@ -372,7 +383,7 @@ impl Window {
}
}
- fn get_geometry(&self) -> Option<(int, int, uint, uint)> {
+ fn get_geometry(&self) -> Option<(i32, i32, u32, u32)> {
unsafe {
use std::mem;
@@ -391,27 +402,27 @@ impl Window {
return None;
}
- Some((x as int, y as int, width as uint, height as uint))
+ Some((x as i32, y as i32, width as u32, height as u32))
}
}
- pub fn get_position(&self) -> Option<(int, int)> {
+ pub fn get_position(&self) -> Option<(i32, i32)> {
self.get_geometry().map(|(x, y, _, _)| (x, y))
}
- pub fn set_position(&self, x: int, y: int) {
+ pub fn set_position(&self, x: i32, y: i32) {
unsafe { ffi::XMoveWindow(self.x.display, self.x.window, x as libc::c_int, y as libc::c_int) }
}
- pub fn get_inner_size(&self) -> Option<(uint, uint)> {
+ pub fn get_inner_size(&self) -> Option<(u32, u32)> {
self.get_geometry().map(|(_, _, w, h)| (w, h))
}
- pub fn get_outer_size(&self) -> Option<(uint, uint)> {
+ pub fn get_outer_size(&self) -> Option<(u32, u32)> {
unimplemented!()
}
- pub fn set_inner_size(&self, _x: uint, _y: uint) {
+ pub fn set_inner_size(&self, _x: u32, _y: u32) {
unimplemented!()
}
@@ -421,10 +432,10 @@ impl Window {
}
}
- pub fn poll_events(&self) -> Vec<Event> {
+ pub fn poll_events(&self) -> RingBuf<Event> {
use std::mem;
- let mut events = Vec::new();
+ let mut events = RingBuf::new();
loop {
use std::num::Int;
@@ -447,15 +458,15 @@ impl Window {
ffi::ClientMessage => {
use events::Event::{Closed, Awakened};
- use std::sync::atomic::Relaxed;
+ use std::sync::atomic::Ordering::Relaxed;
let client_msg: &ffi::XClientMessageEvent = unsafe { mem::transmute(&xev) };
if client_msg.l[0] == self.wm_delete_window as libc::c_long {
self.is_closed.store(true, Relaxed);
- events.push(Closed);
+ events.push_back(Closed);
} else {
- events.push(Awakened);
+ events.push_back(Awakened);
}
},
@@ -465,14 +476,14 @@ impl Window {
let (current_width, current_height) = self.current_size.get();
if current_width != cfg_event.width || current_height != cfg_event.height {
self.current_size.set((cfg_event.width, cfg_event.height));
- events.push(Resized(cfg_event.width as uint, cfg_event.height as uint));
+ events.push_back(Resized(cfg_event.width as u32, cfg_event.height as u32));
}
},
ffi::MotionNotify => {
use events::Event::MouseMoved;
let event: &ffi::XMotionEvent = unsafe { mem::transmute(&xev) };
- events.push(MouseMoved((event.x as int, event.y as int)));
+ events.push_back(MouseMoved((event.x as i32, event.y as i32)));
},
ffi::KeyPress | ffi::KeyRelease => {
@@ -490,18 +501,18 @@ impl Window {
let written = unsafe {
use std::str;
- let mut buffer: [u8, ..16] = [mem::uninitialized(), ..16];
+ let mut buffer: [u8; 16] = [mem::uninitialized(); 16];
let raw_ev: *mut ffi::XKeyEvent = event;
let count = ffi::Xutf8LookupString(self.x.ic, mem::transmute(raw_ev),
mem::transmute(buffer.as_mut_ptr()),
buffer.len() as libc::c_int, ptr::null_mut(), ptr::null_mut());
- str::from_utf8(buffer.as_slice().slice_to(count as uint))
+ str::from_utf8(buffer.as_slice().slice_to(count as usize))
.unwrap_or("").to_string()
};
for chr in written.as_slice().chars() {
- events.push(ReceivedCharacter(chr));
+ events.push_back(ReceivedCharacter(chr));
}
let keysym = unsafe {
@@ -510,7 +521,7 @@ impl Window {
let vkey = events::keycode_to_element(keysym as libc::c_uint);
- events.push(KeyboardInput(state, event.keycode as u8, vkey));
+ events.push_back(KeyboardInput(state, event.keycode as u8, vkey));
},
ffi::ButtonPress | ffi::ButtonRelease => {
@@ -527,11 +538,11 @@ impl Window {
ffi::Button2 => Some(MiddleMouseButton),
ffi::Button3 => Some(RightMouseButton),
ffi::Button4 => {
- events.push(MouseWheel(1));
+ events.push_back(MouseWheel(1));
None
}
ffi::Button5 => {
- events.push(MouseWheel(-1));
+ events.push_back(MouseWheel(-1));
None
}
_ => None
@@ -539,7 +550,7 @@ impl Window {
match button {
Some(button) =>
- events.push(MouseInput(state, button)),
+ events.push_back(MouseInput(state, button)),
None => ()
};
},
@@ -551,7 +562,7 @@ impl Window {
events
}
- pub fn wait_events(&self) -> Vec<Event> {
+ pub fn wait_events(&self) -> RingBuf<Event> {
use std::mem;
loop {
@@ -576,11 +587,10 @@ impl Window {
}
pub fn get_proc_address(&self, addr: &str) -> *const () {
- use std::c_str::ToCStr;
use std::mem;
unsafe {
- addr.with_c_str(|s| {
+ with_c_str(addr, |s| {
ffi::glx::GetProcAddress(mem::transmute(s)) as *const ()
})
}
@@ -599,6 +609,53 @@ impl Window {
::Api::OpenGl
}
- pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) {
+ pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) {
+ }
+
+ pub fn set_cursor(&self, cursor: MouseCursor) {
+ unsafe {
+ use std::ffi::CString;
+ let cursor_name = match cursor {
+ MouseCursor::Alias => "link",
+ MouseCursor::Arrow => "arrow",
+ MouseCursor::Cell => "plus",
+ MouseCursor::Copy => "copy",
+ MouseCursor::Crosshair => "crosshair",
+ MouseCursor::Default => "left_ptr",
+ MouseCursor::Grabbing => "grabbing",
+ MouseCursor::Hand | MouseCursor::Grab => "hand",
+ MouseCursor::Help => "question_arrow",
+ MouseCursor::Move => "move",
+ MouseCursor::NoDrop => "circle",
+ MouseCursor::NotAllowed => "crossed_circle",
+ MouseCursor::Progress => "left_ptr_watch",
+
+ /// Resize cursors
+ MouseCursor::EResize => "right_side",
+ MouseCursor::NResize => "top_side",
+ MouseCursor::NeResize => "top_right_corner",
+ MouseCursor::NwResize => "top_left_corner",
+ MouseCursor::SResize => "bottom_side",
+ MouseCursor::SeResize => "bottom_right_corner",
+ MouseCursor::SwResize => "bottom_left_corner",
+ MouseCursor::WResize => "left_side",
+ MouseCursor::EwResize | MouseCursor::ColResize => "h_double_arrow",
+ MouseCursor::NsResize | MouseCursor::RowResize => "v_double_arrow",
+ MouseCursor::NwseResize => "bd_double_arrow",
+ MouseCursor::NeswResize => "fd_double_arrow",
+
+ MouseCursor::Text | MouseCursor::VerticalText => "xterm",
+ MouseCursor::Wait => "watch",
+
+ /// TODO: Find matching X11 cursors
+ MouseCursor::ContextMenu | MouseCursor::NoneCursor |
+ MouseCursor::AllScroll | MouseCursor::ZoomIn |
+ MouseCursor::ZoomOut => "left_ptr",
+ };
+ let c_string = CString::from_slice(cursor_name.as_bytes());
+ let xcursor = ffi::XcursorLibraryLoadCursor(self.x.display, c_string.as_ptr());
+ ffi::XDefineCursor (self.x.display, self.x.window, xcursor);
+ ffi::XFlush(self.x.display);
+ }
}
}
diff --git a/src/x11/window/monitor.rs b/src/x11/window/monitor.rs
index f62a8ef..3c188b6 100644
--- a/src/x11/window/monitor.rs
+++ b/src/x11/window/monitor.rs
@@ -1,10 +1,11 @@
-use std::{ptr};
+use std::ptr;
+use std::collections::RingBuf;
use super::super::ffi;
use super::ensure_thread_init;
-pub struct MonitorID(pub uint);
+pub struct MonitorID(pub u32);
-pub fn get_available_monitors() -> Vec<MonitorID> {
+pub fn get_available_monitors() -> RingBuf<MonitorID> {
ensure_thread_init();
let nb_monitors = unsafe {
let display = ffi::XOpenDisplay(ptr::null());
@@ -16,9 +17,9 @@ pub fn get_available_monitors() -> Vec<MonitorID> {
nb_monitors
};
- let mut vec = Vec::new();
- vec.grow_fn(nb_monitors as uint, |i| MonitorID(i));
- vec
+ let mut monitors = RingBuf::new();
+ monitors.extend(range(0, nb_monitors).map(|i| MonitorID(i as u32)));
+ monitors
}
pub fn get_primary_monitor() -> MonitorID {
@@ -33,7 +34,7 @@ pub fn get_primary_monitor() -> MonitorID {
primary_monitor
};
- MonitorID(primary_monitor as uint)
+ MonitorID(primary_monitor as u32)
}
impl MonitorID {
@@ -42,7 +43,7 @@ impl MonitorID {
Some(format!("Monitor #{}", screen_num))
}
- pub fn get_dimensions(&self) -> (uint, uint) {
+ pub fn get_dimensions(&self) -> (u32, u32) {
let dimensions = unsafe {
let display = ffi::XOpenDisplay(ptr::null());
let MonitorID(screen_num) = *self;
@@ -50,7 +51,7 @@ impl MonitorID {
let width = ffi::XWidthOfScreen(screen);
let height = ffi::XHeightOfScreen(screen);
ffi::XCloseDisplay(display);
- (width as uint, height as uint)
+ (width as u32, height as u32)
};
dimensions
diff --git a/tests/headless.rs b/tests/headless.rs
index b2b23da..fdbb6c2 100644
--- a/tests/headless.rs
+++ b/tests/headless.rs
@@ -1,7 +1,3 @@
-#![feature(phase)]
-
-#[phase(plugin)]
-extern crate gl_generator;
extern crate glutin;
extern crate libc;
@@ -27,6 +23,6 @@ fn main() {
assert!(value == (0, 255, 0, 255) || value == (0, 64, 0, 255) ||
value == (0, 64, 0, 255) || value == (0, 64, 0, 0),
- "value is: {}", value);
+ "value is: {:?}", value);
}
}