<commit_before>#![allow(unused_variables, unused_imports)]

#[macro_use]
extern crate ecs;
use ecs::*;
use ecs::system::{EntityProcess, EntitySystem};

extern crate shader_version;
extern crate input;
extern crate event;
extern crate graphics;
extern crate sdl2_window;
extern crate window;
extern crate opengl_graphics;
extern crate quack;

use window::WindowSettings;

use std::collections::HashMap;
use std::default::Default;
use std::rand;
use std::rand::Rng;
use event::{Event, ReleaseEvent, UpdateEvent, PressEvent, RenderEvent, RenderArgs, UpdateArgs};
use quack::Set;
use std::cell::RefCell;
use std::cell::Cell;
use std::rc::Rc;

use opengl_graphics::{
    Gl,
};
use sdl2_window::Sdl2Window;

static WINDOW_W: f64 = 800.0;
static WINDOW_H: f64 = 600.0;
static WINDOW_PADDING: i32 = 20;

pub struct Meta {
    render: Cell<RenderArgs>,
    update: Cell<UpdateArgs>
}

pub struct ShimmerSystem;

impl System for ShimmerSystem {
    type Components = Components;
}

pub struct DrawSystem {
    gl: Option<RefCell<Gl>>,
    meta: Option<Rc<Meta>>
}

impl EntityProcess for ShimmerSystem {
    fn process(&mut self, entities: EntityIter<Components>, data: &mut DataHelper<Components>) {
        for e in entities {
            let color = &mut data.colors[e];
            let ref mut rng = rand::thread_rng();
            color.r = rng.gen_range(0.5, 1.0);
            color.g = rng.gen_range(0.5, 1.0);
            color.b = rng.gen_range(0.5, 1.0);
        }
    }
}

impl System for DrawSystem {
    type Components = Components;
    fn is_active(&self) -> bool { false }
}

impl EntityProcess for DrawSystem {
    fn process(&mut self, entities: EntityIter<Components>, data: &mut DataHelper<Components>) {
        use graphics::*;
        use ShapeVarient::*;
        for e in entities {
            let position = &data.positions[e];
            let shape = &data.shapes[e];
            let color = &data.colors[e];
            let pad = WINDOW_PADDING;
            if let Some(ref gl_cell) = self.gl {
            if let Some(ref meta) = self.meta {
                let mut gl = gl_cell.borrow_mut();
                let render = meta.render.get();
                let view_width = (render.width as i32 - 2 * pad) as f64;
                let view_height = (render.height as i32 - 2 * pad) as f64;
                gl.draw([pad, pad, view_width as i32, view_height as i32], |c, gl| { // viewport
                    graphics::clear([0.2, 0.2, 0.2, 1.0], gl);
                    let r = Rectangle::new([0.0, 1.0, 0.0, 1.0]);
                    r.draw([0.0, 0.0, view_width, view_height], &c, gl);
                    let r = Rectangle::new([0.0, 0.0, 0.0, 1.0]);
                    r.draw([1.0, 1.0, view_width - 2.0,  view_height - 2.0], &c, gl);
                    match shape.varient {
                        Circle(rad) => {
                            Ellipse::new([color.r, color.g, color.b, 1.0])
                                .draw([
                                      position.x,
                                      position.y,
                                      2.0*rad, 2.0*rad
                                ], &c, gl);
                        },
                        Point | _ => {
                            Rectangle::new([color.r, color.g, color.b, 1.0])
                                .draw([
                                      position.x,
                                      position.y,
                                      1.0f64, 1.0f64
                                ], &c, gl);
                        },
                    };
                });
            } //gl cell
            } // meta
        }
    }
}

pub struct MoveSystem {
    meta: Option<Rc<Meta>>
}

impl System for MoveSystem {
    type Components = Components;
}

impl EntityProcess for MoveSystem {
    fn process(&mut self, entities: EntityIter<Components>, data: &mut DataHelper<Components>) {
        use graphics::*;
        use ShapeVarient::*;
        use ClampVarient::*;
        for e in entities {
            let (vx, vy) = {
                let v = &data.velocities[e];
                (v.x, v.y)
            };
            let shape = data.shapes[e].clone();
            let clamp = data.clamps[e].clone();
            if let Some(ref meta) = self.meta {
                let dt = meta.update.get().dt;
                let render = meta.render.get();
                let view_width = (render.width as i32 - 2 * WINDOW_PADDING) as f64;
                let view_height = (render.height as i32 - 2 * WINDOW_PADDING) as f64;

                let (px, py) = {
                    let position = &mut(data.positions[e]);
                    position.x += vx * dt;
                    position.y += vy * dt;
                    (position.x, position.y)
                };

                let (w, h) = match shape.varient {
                    Circle(r) => (r*2.0, r*2.0),
                    Square(w,h) => (w, h),
                    Point => (0.0, 0.0)
                };

                let velocity_mult = match clamp.varient {
                  Bounce => -1.0,
                  Stop => 0.0,
                  _ => 1.0
                };

                match clamp.varient {
                  Bounce | Stop => {
                    if px + w > view_width {
                      {
                          let position = &mut(data.positions[e]);
                          position.x = view_width - w;
                      }
                      let velocity  = &mut(data.velocities[e]);
                      velocity.x *= velocity_mult;
                    } else if px < 0.0 {
                      {
                          let position = &mut(data.positions[e]);
                          position.x = 0.0;
                      }
                      let velocity  = &mut(data.velocities[e]);
                      velocity.x *= velocity_mult;
                    }
                    if py + h > view_height {
                      {
                          let position = &mut(data.positions[e]);
                          position.y = view_height - h;
                      }
                      let velocity  = &mut(data.velocities[e]);
                      velocity.y *= velocity_mult;
                    } else if py < 0.0 {
                      {
                          let position = &mut(data.positions[e]);
                          position.y = 0.0;
                      }
                      let velocity  = &mut(data.velocities[e]);
                      velocity.y *= velocity_mult;
                    }
                  },
                  Remove => {
                    if px > view_width
                    || px + w < 0.0 {
                        println!("Should remove, went off horizontal edge");
                    }
                    if py > view_height
                    || py + h < 0.0 {
                        println!("Should remove, went off vertical edge");
                    }
                  }
                }
            }
        }
    }
}

//fn control_system(event: &Event,
//              controllers: &mut Components<PlayerController>,
//              velocities: &mut Components<Velocity>) {
//
//    const PADDLE_V: f64 = 800.0;
//
////    for (eid, controller) in controllers.iter_mut() {
////        event.press(|button| {
////            if button == Keyboard(controller.up) {
////                velocities.get_mut(eid).y = -PADDLE_V;
////            } else if button == Keyboard(controller.down) {
////                velocities.get_mut(eid).y = PADDLE_V;
////            }
////        });
////        event.release(|button| {
////            if button == Keyboard(controller.up)
////            || button == Keyboard(controller.down) {
////                velocities.get_mut(eid).y = 0.0;
////            }
////        });
////    }
//}

#[derive(Clone, PartialEq, Debug)]
pub enum ClampVarient {
    Bounce,
    Stop,
    Remove // Acts when item leaves window.
}

#[derive(Clone, PartialEq, Debug)]
pub struct WindowClamp {
    varient: ClampVarient
}

#[derive(Clone, PartialEq, Debug)]
pub struct PlayerController {
    up: input::Button,
    down: input::Button
}

#[derive(Clone, PartialEq, Debug)]
pub struct Position {
    x: f64,
    y: f64
}

#[derive(Clone, PartialEq, Debug)]
pub struct Shimmer;

#[derive(Clone, PartialEq, Debug)]
pub struct Color {
    r: f32,
    g: f32,
    b: f32
}

#[derive(Clone, PartialEq, Debug)]
pub enum ShapeVarient {
    Point,
    Circle(f64), // radius
    Square(f64, f64), // width, height
}

impl Default for ShapeVarient {
    fn default() -> ShapeVarient { ShapeVarient::Point }
}

#[derive(Clone, PartialEq, Debug)]
pub struct Shape {
    varient: ShapeVarient,
    border: Option<f64>
}

#[derive(Clone, PartialEq, Debug)]
pub struct Velocity {
    x: f64,
    y: f64
}

components! {
    Components {
        #[hot] positions: Position,
        #[hot] shapes: Shape,
        #[hot] velocities: Velocity,
        #[hot] colors: Color,
        #[hot] shimmers: Shimmer,
        #[hot] player_controllers: PlayerController,
        #[hot] clamps: WindowClamp
    }
}

systems! {
    Systems<Components> {
        shimmer: EntitySystem<ShimmerSystem> = EntitySystem::new( ShimmerSystem,
            aspect!(<Components> all: [colors])
        ),
        moves: EntitySystem<MoveSystem> = EntitySystem::new(
            MoveSystem{ meta: None },
            aspect!(<Components> all: [positions, shapes, velocities, clamps])
        ),
        draw: EntitySystem<DrawSystem> = EntitySystem::new(
            DrawSystem{ gl: None, meta: None },
            aspect!(<Components> all: [positions, shapes, colors])
        )
    }
}

fn make_ball(world: &mut World<Components, Systems>) {
    const BALL_R: f64 = 20.0;
    let x = (WINDOW_W - BALL_R) / 2.0;
    let y = (WINDOW_H - BALL_R) / 2.0;

    let entity = world.create_entity(|entity: BuildData, data: &mut Components| {
        data.positions.add(&entity,
            Position{
                x: x,
                y: y
        });
        data.velocities.add(&entity,
            Velocity{
                x: 300.0,
                y: 200.0,
        });
        data.shimmers.add(&entity, Shimmer);
        data.shapes.add(&entity,
            Shape {
                varient: ShapeVarient::Circle(BALL_R),
                border: None
        });
        data.colors.add(&entity,
            Color{
                r: 1.0,
                g: 0.5,
                b: 0.2
        });
        data.clamps.add(&entity,
            WindowClamp {
               varient: ClampVarient::Bounce
        });
    });
}

//fn make_player(ents: &mut Entities, p1: bool) -> u32 {
//    const FROM_WALL: f64 = 20.0;
//    const PADDLE_W: f64 = 20.0;
//    const PADDLE_H: f64 = 150.0;
//    let x = if p1 {
//        FROM_WALL
//    } else {
//        WINDOW_W - FROM_WALL - PADDLE_W
//    };
//    let y = (WINDOW_H - PADDLE_H) / 2.0;
//    let e = Entity::new()
//        .with_player_controller(
//            PlayerController {
//                up: if p1 { keyboard::W } else { keyboard::I },
//                down: if p1 { keyboard::S } else { keyboard::K }
//            })
//        .with_velocity(Velocity { x: 0.0, y: 0.0 } )
//        .with_position(
//            Position{
//                x: x,
//                y: y
//            })
//        .with_shape(
//            Shape {
//                varient: Square(PADDLE_W, PADDLE_H),
//                border: None
//            })
//        .with_color(
//            Color{
//                r: 0.5,
//                g: 0.2,
//                b: 0.8
//            })
//        .with_window_clamp(
//            WindowClamp {
//               varient: Stop
//            });
//    ents.add(e)
//}

fn main() {
    let opengl = shader_version::OpenGL::_3_2;
    let window = Sdl2Window::new(
        opengl,
        WindowSettings {
            title: "Pong".to_string(),
            size: [WINDOW_W as u32, WINDOW_H as u32],
            fullscreen: false,
            exit_on_esc: true,
            samples: 4,
        }
    );

    let mut gl = Gl::new(opengl);

    let mut world = World::<Components, Systems>::new();
    world.systems.draw.gl = Some(RefCell::new(gl));
    make_ball(&mut world);
    let mut meta = Rc::new(Meta {
        render: Cell::new(RenderArgs { ext_dt: 0.0, width: 0, height: 0 }),
        update: Cell::new(UpdateArgs { dt: 0.0 })
    });

    world.systems.moves.meta = Some(meta.clone());
    world.systems.draw.meta = Some(meta.clone());

    for e in event::events(window) {
        use event::{ ReleaseEvent, UpdateEvent, PressEvent, RenderEvent };

        if let Some(args) = e.update_args() {
            meta.update.set(args);
            world.update();
        }
        if let Some(args) = e.render_args() {
            meta.render.set(args);
            process!(world, draw);
            //(args.dt as f32);
//            use graphics::*;
//            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
//                graphics::clear([0.0, 0.0, 0.0, 1.0], gl);
//                let r = Rectangle::new([1.0, 1.0, 1.0, 1.0]);
//                let off = Color([0.0, 0.0, 0.0, 1.0]);
//                let on = Color([1.0, 1.0, 1.0, 1.0]);
//
//                let w = args.width as f64 / 64.0;
//                let h = args.height as f64 / 32.0;
//
//                for (y,row) in vm.screen_rows().enumerate() {
//                    for (x,byte) in row.iter().enumerate() {
//                        let x = x as f64 * w;
//                        let y = y as f64 * h;
//                        r.set(match *byte { 0 => off, _ => on })
//                        .draw([x, y, w, h], &c, gl);
//                    }
//                }
//            });
        }
    }
}
<commit_msg>Fix render order and add make_player back<commit_after>#![allow(unused_variables, unused_imports)]

#[macro_use]
extern crate ecs;
use ecs::*;
use ecs::system::{EntityProcess, EntitySystem};

extern crate shader_version;
extern crate input;
extern crate event;
extern crate graphics;
extern crate sdl2_window;
extern crate window;
extern crate opengl_graphics;
extern crate quack;

use window::WindowSettings;

use std::collections::HashMap;
use std::default::Default;
use std::rand;
use std::rand::Rng;
use event::{Event, ReleaseEvent, UpdateEvent, PressEvent, RenderEvent, RenderArgs, UpdateArgs};
use quack::Set;
use std::cell::RefCell;
use std::cell::Cell;
use std::rc::Rc;
use input::keyboard;

use opengl_graphics::{
    Gl,
};
use sdl2_window::Sdl2Window;

const WINDOW_W: f64 = 800.0;
const WINDOW_H: f64 = 600.0;
const WINDOW_PADDING: f64 = 20.0;
const VIEW_W: f64 = (WINDOW_W - 2.0 * WINDOW_PADDING);
const VIEW_H: f64 = (WINDOW_H - 2.0 * WINDOW_PADDING);

pub struct Meta {
    render: Cell<RenderArgs>,
    update: Cell<UpdateArgs>
}

pub struct ShimmerSystem;

impl System for ShimmerSystem {
    type Components = Components;
}

pub struct DrawSystem {
    gl: Option<RefCell<Gl>>,
    meta: Option<Rc<Meta>>
}

impl EntityProcess for ShimmerSystem {
    fn process(&mut self, entities: EntityIter<Components>, data: &mut DataHelper<Components>) {
        for e in entities {
            let color = &mut data.colors[e];
            let ref mut rng = rand::thread_rng();
            color.r = rng.gen_range(0.5, 1.0);
            color.g = rng.gen_range(0.5, 1.0);
            color.b = rng.gen_range(0.5, 1.0);
        }
    }
}

impl System for DrawSystem {
    type Components = Components;
    fn is_active(&self) -> bool { false }
}

impl EntityProcess for DrawSystem {
    fn process(&mut self, entities: EntityIter<Components>, data: &mut DataHelper<Components>) {
        use graphics::*;
        use ShapeVarient::*;
        let pad = WINDOW_PADDING;
        if let Some(ref gl_cell) = self.gl {
        if let Some(ref meta) = self.meta {
            let mut gl = gl_cell.borrow_mut();
            let render = meta.render.get();
            let view_width = render.width as f64 - 2.0 * pad;
            let view_height = render.height as f64 - 2.0 * pad;
            gl.draw([pad as i32, pad as i32, view_width as i32, view_height as i32], |c, gl| { // viewport
                graphics::clear([0.2, 0.2, 0.2, 1.0], gl);
                let r = Rectangle::new([0.0, 1.0, 0.0, 1.0]);
                r.draw([0.0, 0.0, view_width, view_height], &c, gl);
                let r = Rectangle::new([0.0, 0.0, 0.0, 1.0]);
                r.draw([1.0, 1.0, view_width - 2.0,  view_height - 2.0], &c, gl);
                for e in entities {
                    let position = &data.positions[e];
                    let shape = &data.shapes[e];
                    let color = &data.colors[e];
                    match shape.varient {
                        Circle(rad) => {
                            Ellipse::new([color.r, color.g, color.b, 1.0])
                                .draw([
                                      position.x,
                                      position.y,
                                      2.0*rad, 2.0*rad
                                ], &c, gl);
                        },
                        Square(w, h) => {
                            Rectangle::new([color.r, color.g, color.b, 1.0])
                                .draw([
                                      position.x,
                                      position.y,
                                      w, h
                                ], &c, gl);
                        },
                        Point => {
                            Rectangle::new([color.r, color.g, color.b, 1.0])
                                .draw([
                                      position.x,
                                      position.y,
                                      1.0f64, 1.0f64
                                ], &c, gl);
                        }
                    }
                }
            });
        } //gl cell
        } // meta
    }
}

pub struct MoveSystem {
    meta: Option<Rc<Meta>>
}

impl System for MoveSystem {
    type Components = Components;
}

impl EntityProcess for MoveSystem {
    fn process(&mut self, entities: EntityIter<Components>, data: &mut DataHelper<Components>) {
        use graphics::*;
        use ShapeVarient::*;
        use ClampVarient::*;
        for e in entities {
            let (vx, vy) = {
                let v = &data.velocities[e];
                (v.x, v.y)
            };
            let shape = data.shapes[e].clone();
            let clamp = data.clamps[e].clone();
            if let Some(ref meta) = self.meta {
                let dt = meta.update.get().dt;
                let render = meta.render.get();
                let view_width = render.width as f64 - 2.0 * WINDOW_PADDING;
                let view_height = render.height as f64 - 2.0 * WINDOW_PADDING;

                let (px, py) = {
                    let position = &mut(data.positions[e]);
                    position.x += vx * dt;
                    position.y += vy * dt;
                    (position.x, position.y)
                };

                let (w, h) = match shape.varient {
                    Circle(r) => (r*2.0, r*2.0),
                    Square(w,h) => (w, h),
                    Point => (0.0, 0.0)
                };

                let velocity_mult = match clamp.varient {
                  Bounce => -1.0,
                  Stop => 0.0,
                  _ => 1.0
                };

                match clamp.varient {
                  Bounce | Stop => {
                    if px + w > view_width {
                      {
                          let position = &mut(data.positions[e]);
                          position.x = view_width - w;
                      }
                      let velocity  = &mut(data.velocities[e]);
                      velocity.x *= velocity_mult;
                    } else if px < 0.0 {
                      {
                          let position = &mut(data.positions[e]);
                          position.x = 0.0;
                      }
                      let velocity  = &mut(data.velocities[e]);
                      velocity.x *= velocity_mult;
                    }
                    if py + h > view_height {
                      {
                          let position = &mut(data.positions[e]);
                          position.y = view_height - h;
                      }
                      let velocity  = &mut(data.velocities[e]);
                      velocity.y *= velocity_mult;
                    } else if py < 0.0 {
                      {
                          let position = &mut(data.positions[e]);
                          position.y = 0.0;
                      }
                      let velocity  = &mut(data.velocities[e]);
                      velocity.y *= velocity_mult;
                    }
                  },
                  Remove => {
                    if px > view_width
                    || px + w < 0.0 {
                        println!("Should remove, went off horizontal edge");
                    }
                    if py > view_height
                    || py + h < 0.0 {
                        println!("Should remove, went off vertical edge");
                    }
                  }
                }
            }
        }
    }
}

//fn control_system(event: &Event,
//              controllers: &mut Components<PlayerController>,
//              velocities: &mut Components<Velocity>) {
//
//    const PADDLE_V: f64 = 800.0;
//
////    for (eid, controller) in controllers.iter_mut() {
////        event.press(|button| {
////            if button == Keyboard(controller.up) {
////                velocities.get_mut(eid).y = -PADDLE_V;
////            } else if button == Keyboard(controller.down) {
////                velocities.get_mut(eid).y = PADDLE_V;
////            }
////        });
////        event.release(|button| {
////            if button == Keyboard(controller.up)
////            || button == Keyboard(controller.down) {
////                velocities.get_mut(eid).y = 0.0;
////            }
////        });
////    }
//}

#[derive(Clone, PartialEq, Debug)]
pub enum ClampVarient {
    Bounce,
    Stop,
    Remove // Acts when item leaves window.
}

#[derive(Clone, PartialEq, Debug)]
pub struct WindowClamp {
    varient: ClampVarient
}

#[derive(Clone, PartialEq, Debug)]
pub struct PlayerController {
    up: keyboard::Key,
    down: keyboard::Key
}

#[derive(Clone, PartialEq, Debug)]
pub struct Position {
    x: f64,
    y: f64
}

#[derive(Clone, PartialEq, Debug)]
pub struct Shimmer;

#[derive(Clone, PartialEq, Debug)]
pub struct Color {
    r: f32,
    g: f32,
    b: f32
}

#[derive(Clone, PartialEq, Debug)]
pub enum ShapeVarient {
    Point,
    Circle(f64), // radius
    Square(f64, f64), // width, height
}

impl Default for ShapeVarient {
    fn default() -> ShapeVarient { ShapeVarient::Point }
}

#[derive(Clone, PartialEq, Debug)]
pub struct Shape {
    varient: ShapeVarient,
    border: Option<f64>
}

#[derive(Clone, PartialEq, Debug)]
pub struct Velocity {
    x: f64,
    y: f64
}

components! {
    Components {
        #[hot] positions: Position,
        #[hot] shapes: Shape,
        #[hot] velocities: Velocity,
        #[hot] colors: Color,
        #[hot] shimmers: Shimmer,
        #[hot] player_controllers: PlayerController,
        #[hot] clamps: WindowClamp
    }
}

systems! {
    Systems<Components> {
        shimmer: EntitySystem<ShimmerSystem> = EntitySystem::new( ShimmerSystem,
            aspect!(<Components> all: [colors, shimmers])
        ),
        moves: EntitySystem<MoveSystem> = EntitySystem::new(
            MoveSystem{ meta: None },
            aspect!(<Components> all: [positions, shapes, velocities, clamps])
        ),
        draw: EntitySystem<DrawSystem> = EntitySystem::new(
            DrawSystem{ gl: None, meta: None },
            aspect!(<Components> all: [positions, shapes, colors])
        )
    }
}

fn make_ball(world: &mut World<Components, Systems>) {
    const BALL_R: f64 = 20.0;
    let x = (VIEW_W - BALL_R) / 2.0;
    let y = (VIEW_H - BALL_R) / 2.0;

    let entity = world.create_entity(|entity: BuildData, data: &mut Components| {
        data.positions.add(&entity,
            Position{
                x: x,
                y: y
        });
        data.velocities.add(&entity,
            Velocity{
                x: 300.0,
                y: 200.0,
        });
        data.shimmers.add(&entity, Shimmer);
        data.shapes.add(&entity,
            Shape {
                varient: ShapeVarient::Circle(BALL_R),
                border: None
        });
        data.colors.add(&entity,
            Color{
                r: 1.0,
                g: 0.5,
                b: 0.2
        });
        data.clamps.add(&entity,
            WindowClamp {
               varient: ClampVarient::Bounce
        });
    });
}

fn make_player(world: &mut World<Components, Systems>, p1: bool) {
    const FROM_WALL: f64 = 40.0;
    const PADDLE_W: f64 = 20.0;
    const PADDLE_H: f64 = 150.0;
    let x = if p1 {
        FROM_WALL
    } else {
        VIEW_W - FROM_WALL - PADDLE_W
    };
    let y = (VIEW_H - PADDLE_H) / 2.0;
    let entity = world.create_entity(|entity: BuildData, data: &mut Components| {
        data.positions.add(&entity,
            Position{
                x: x,
                y: y
        });
        data.shapes.add(&entity,
            Shape {
                varient: ShapeVarient::Square(PADDLE_W, PADDLE_H),
                border: None
        });
        data.colors.add(&entity,
            Color{
                r: 1.0,
                g: 0.5,
                b: 1.0
        });
        data.player_controllers.add(&entity,
            PlayerController {
                up: if p1 { keyboard::Key::W } else { keyboard::Key::I },
                down: if p1 { keyboard::Key::S } else { keyboard::Key::K },
        });
    });
}

fn main() {
    let opengl = shader_version::OpenGL::_3_2;
    let window = Sdl2Window::new(
        opengl,
        WindowSettings {
            title: "Pong".to_string(),
            size: [WINDOW_W as u32, WINDOW_H as u32],
            fullscreen: false,
            exit_on_esc: true,
            samples: 4,
        }
    );

    let mut gl = Gl::new(opengl);

    let mut world = World::<Components, Systems>::new();
    world.systems.draw.gl = Some(RefCell::new(gl));
    make_ball(&mut world);
    make_player(&mut world, true);
    make_player(&mut world, false);
    let mut meta = Rc::new(Meta {
        render: Cell::new(RenderArgs { ext_dt: 0.0, width: 0, height: 0 }),
        update: Cell::new(UpdateArgs { dt: 0.0 })
    });

    world.systems.moves.meta = Some(meta.clone());
    world.systems.draw.meta = Some(meta.clone());

    for e in event::events(window) {
        use event::{ ReleaseEvent, UpdateEvent, PressEvent, RenderEvent };

        if let Some(args) = e.update_args() {
            meta.update.set(args);
            world.update();
        }
        if let Some(args) = e.render_args() {
            meta.render.set(args);
            process!(world, draw);
        }
    }
}
<|endoftext|>


<commit_before>/*
 * A simple program that aims to extract various string constants from a JAR file (Java)
 */

extern crate classreader;
extern crate zip;
extern crate docopt;
extern crate rustc_serialize;
extern crate java_properties;
extern crate shannon_entropy;

use docopt::Docopt;
use classreader::*;
use std::fs::File;
use java_properties::PropertiesIter;
use std::io::BufReader;
use shannon_entropy::shannon_entropy;

const USAGE: &'static str = "
Java Strings extractor.

Usage:
  jstrings [-e] <source>...
  javaminer (-h | --help)

Options:
  -e            Print entropy of each string
  -h --help     Show this screen.

Source can be one or more class or jar files.
";

#[derive(Debug, RustcDecodable)]
struct Args {
	flag_e: bool,
    arg_source: Vec<String>
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
    let printer = printer_factory(&args);
    for f in args.arg_source {
        if f.ends_with(".class") {
            process_class_file(&f, printer);
        } else if f.ends_with(".jar") {
            process_jar_file(&f, printer);
        } else if f.ends_with(".properties") {
            process_properties_file(&f, printer);
        }
    }
}

fn process_jar_file(file_name: &String, printer: fn(String)) {
    let file = File::open(file_name).expect("couldn't find a file!");
    let mut zip = zip::ZipArchive::new(file).expect("could not read JAR");
    for i in 0..zip.len() {
        let mut class_file = zip.by_index(i).unwrap();
        if class_file.name().ends_with(".class") {
            let class = ClassReader::new_from_reader(&mut class_file).unwrap();
            process_class(&class, printer);
        } else if class_file.name().ends_with(".properties") {
            process_properties(class_file, printer);
        }
    }
}

fn process_class_file(file_name: &String, printer: fn(String)) {
    let class = ClassReader::new_from_path(&file_name).unwrap();
    process_class(&class, printer);
}

fn process_class(class: &Class, printer: fn(String)) {
    assert_eq!(0xCAFEBABE, class.magic);
    for jstr in &class.constant_pool {
        match jstr {
            &ConstantPoolInfo::String(index) => {
                printer(get_string(&class, index as usize));
            },
            _ => {}
        }
    }
}

/// Get constant from a pool, correcting for java's 1-based indexes.
fn get_const(class: &Class, i: usize) -> &ConstantPoolInfo {
    &class.constant_pool[i - 1]
}

/// Get string from constant pool
fn get_string(class: &Class, index: usize) -> String {
    match get_const(class, index) {
        &ConstantPoolInfo::Utf8(ref s) => s.clone(),
        _ => "?".to_string()
    }
}

fn process_properties_file(file_name: &String, printer: fn(String)) {
    let f = File::open(file_name).expect("couldn't find a file!");
    process_properties(BufReader::new(f), printer);
}

fn process_properties<R: std::io::Read>(f: R, printer: fn(String)) {
    PropertiesIter::new(f).read_into(|_, v| {
      printer( v);
    }).expect("failed to read a properties file");
}

// Output variants
fn printer_factory(args: &Args) -> fn(String) {
	if args.flag_e {
		return print_entropy;
	}
	return print_only;
}

fn print_only(s: String) {
	println!("{}", s);
}

fn print_entropy(s: String) {
	println!("{:>6.2} {}", shannon_entropy(&s), s);
}
<commit_msg>Use average entropy instead of total stirng entropy. And fix the broken whitespaces<commit_after>/*
 * A simple program that aims to extract various string constants from a JAR file (Java)
 */

extern crate classreader;
extern crate zip;
extern crate docopt;
extern crate rustc_serialize;
extern crate java_properties;
extern crate shannon_entropy;

use docopt::Docopt;
use classreader::*;
use std::fs::File;
use java_properties::PropertiesIter;
use std::io::BufReader;
use shannon_entropy::shannon_entropy;

const USAGE: &'static str = "
Java Strings extractor.

Usage:
  jstrings [-e] <source>...
  javaminer (-h | --help)

Options:
  -e            Print average entropy of each string (average of entropy of each word in the string)
  -h --help     Show this screen.

Source can be one or more class or jar files.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_e: bool,
    arg_source: Vec<String>
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
    let printer = printer_factory(&args);
    for f in args.arg_source {
        if f.ends_with(".class") {
            process_class_file(&f, printer);
        } else if f.ends_with(".jar") {
            process_jar_file(&f, printer);
        } else if f.ends_with(".properties") {
            process_properties_file(&f, printer);
        }
    }
}

fn process_jar_file(file_name: &String, printer: fn(String)) {
    let file = File::open(file_name).expect("couldn't find a file!");
    let mut zip = zip::ZipArchive::new(file).expect("could not read JAR");
    for i in 0..zip.len() {
        let mut class_file = zip.by_index(i).unwrap();
        if class_file.name().ends_with(".class") {
            let class = ClassReader::new_from_reader(&mut class_file).unwrap();
            process_class(&class, printer);
        } else if class_file.name().ends_with(".properties") {
            process_properties(class_file, printer);
        }
    }
}

fn process_class_file(file_name: &String, printer: fn(String)) {
    let class = ClassReader::new_from_path(&file_name).unwrap();
    process_class(&class, printer);
}

fn process_class(class: &Class, printer: fn(String)) {
    assert_eq!(0xCAFEBABE, class.magic);
    for jstr in &class.constant_pool {
        match jstr {
            &ConstantPoolInfo::String(index) => {
                printer(get_string(&class, index as usize));
            },
            _ => {}
        }
    }
}

/// Get constant from a pool, correcting for java's 1-based indexes.
fn get_const(class: &Class, i: usize) -> &ConstantPoolInfo {
    &class.constant_pool[i - 1]
}

/// Get string from constant pool
fn get_string(class: &Class, index: usize) -> String {
    match get_const(class, index) {
        &ConstantPoolInfo::Utf8(ref s) => s.clone(),
        _ => "?".to_string()
    }
}

fn process_properties_file(file_name: &String, printer: fn(String)) {
    let f = File::open(file_name).expect("couldn't find a file!");
    process_properties(BufReader::new(f), printer);
}

fn process_properties<R: std::io::Read>(f: R, printer: fn(String)) {
    PropertiesIter::new(f).read_into(|_, v| {
      printer( v);
    }).expect("failed to read a properties file");
}

// Output variants
fn printer_factory(args: &Args) -> fn(String) {
    if args.flag_e {
        return print_entropy;
    }
    return print_only;
}

fn print_only(s: String) {
    println!("{}", s);
}

fn print_entropy(s: String) {
    println!("{:>6.2} {}", average_entropy(&s), s);
}

fn average_entropy(s: &String) -> f32 {
    let tuple = s.split_whitespace().map(shannon_entropy).fold( (0.0, 0),
      |acc, w| (acc.0 + w, acc.1 + 1));
    return tuple.0 / tuple.1 as f32
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate icecore;

use getopts::{optopt, optflag, getopts, usage};
use std::os;
use std::str::FromStr;

use icecore::data::FileStore;
use icecore::ic::Icecore;

fn insert(ic: &mut Icecore, data: String) {
    ic.insert(data);
}

fn get(ic: &mut Icecore, id: u64) {
    let data = ic.get(id, None);
    println!("{}", data);
}

fn demo(ic: &mut Icecore) {
    let id = ic.insert(String::from_str("foo"));
    println!("new document: id={}", id);
    println!("get({}, None) -> {}", id, ic.get(id, None));

    ic.update(id, String::from_str("bar"));
    println!("get({}, None) -> {}", id, ic.get(id, None));
    println!("get({}, 1) -> {}", id, ic.get(id, Some(1u64)));

    ic.dump();
}

fn main() {
    let args: Vec<String> = os::args();

    let store = box FileStore::new(String::from_str("_documents"));
    let mut ic = Icecore::new(
        Path::new("_documents"),
        store,
    );

    ic.load();

    match args[1].as_slice() {
        "insert" => {
            let opts = [
                optopt("d", "data", "Data to insert into the database", "DATA"),
                optflag("h", "help", "print this help message and exit"),
            ];

            let matches = match getopts(args.tail(), &opts) {
                Ok(m) => m,
                Err(_) => panic!("{}", usage("Insert data in the data store", &opts)),
            };

            if matches.opt_present("h") {
                println!("{}", usage("Insert data in the data store", &opts));
                return;
            }

            let data = matches.opt_str("d").unwrap();
            insert(&mut ic, data);
        },
        "get" => {
            let opts = [
                optopt("v", "version", "Requested document version", "VERSION"),
            ];
            let matches = match getopts(args.slice_from(2), &opts) {
                Ok(m) => m,
                Err(_) => panic!(usage("Get document by id", &opts)),
            };
            let id = from_str::<u64>(args[2].as_slice()).unwrap();
            let version: Option<u64> = match matches.opt_str("v") {
                Some(v) => Some(from_str::<u64>(v.as_slice()).unwrap()),
                None => None,
            };
            println!("getting document id={} version={}", id, version);
            let data = ic.get(id, version);
            println!("{}", data);
        },
        "demo" => {
            demo(&mut ic);
        },
        _ => {
            println!("Command not found.");
        }
    }

    ic.dump();
}<commit_msg>Remove useless whitespaces<commit_after>extern crate getopts;
extern crate icecore;

use getopts::{optopt, optflag, getopts, usage};
use std::os;
use std::str::FromStr;

use icecore::data::FileStore;
use icecore::ic::Icecore;

fn insert(ic: &mut Icecore, data: String) {
    ic.insert(data);
}

fn get(ic: &mut Icecore, id: u64) {
    let data = ic.get(id, None);
    println!("{}", data);
}

fn demo(ic: &mut Icecore) {
    let id = ic.insert(String::from_str("foo"));
    println!("new document: id={}", id);
    println!("get({}, None) -> {}", id, ic.get(id, None));

    ic.update(id, String::from_str("bar"));
    println!("get({}, None) -> {}", id, ic.get(id, None));
    println!("get({}, 1) -> {}", id, ic.get(id, Some(1u64)));

    ic.dump();
}

fn main() {
    let args: Vec<String> = os::args();

    let store = box FileStore::new(String::from_str("_documents"));
    let mut ic = Icecore::new(
        Path::new("_documents"),
        store,
    );

    ic.load();

    match args[1].as_slice() {
        "insert" => {
            let opts = [
                optopt("d", "data", "Data to insert into the database", "DATA"),
                optflag("h", "help", "print this help message and exit"),
            ];

            let matches = match getopts(args.tail(), &opts) {
                Ok(m) => m,
                Err(_) => panic!("{}", usage("Insert data in the data store", &opts)),
            };

            if matches.opt_present("h") {
                println!("{}", usage("Insert data in the data store", &opts));
                return;
            }

            let data = matches.opt_str("d").unwrap();
            insert(&mut ic, data);
        },
        "get" => {
            let opts = [
                optopt("v", "version", "Requested document version", "VERSION"),
            ];
            let matches = match getopts(args.slice_from(2), &opts) {
                Ok(m) => m,
                Err(_) => panic!(usage("Get document by id", &opts)),
            };
            let id = from_str::<u64>(args[2].as_slice()).unwrap();
            let version: Option<u64> = match matches.opt_str("v") {
                Some(v) => Some(from_str::<u64>(v.as_slice()).unwrap()),
                None => None,
            };
            println!("getting document id={} version={}", id, version);
            let data = ic.get(id, version);
            println!("{}", data);
        },
        "demo" => {
            demo(&mut ic);
        },
        _ => {
            println!("Command not found.");
        }
    }

    ic.dump();
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate env_logger;
extern crate libc;
extern crate x11;

use std::ffi::CString;
use std::os::raw::{c_int, c_char};
use std::ptr;
use std::convert::From;

use x11::xlib;
use x11::xlib::{BadAccess, Display, Window, XErrorEvent, XOpenDisplay, XDefaultRootWindow,
                XSetErrorHandler};

#[derive(Debug)]
struct Win {
    display: *mut Display,
    xwindow: Window,
}

impl Win {
    // Does this really need to be &mut self? It feels light it ought to be as it is actually
    // modifying the underlying window, even if we're not actually modifying the value as far as
    // Rust is concerned.
    fn position(&mut self, x: i32, y: i32, width: i32, height: i32) -> Result<(), ()> {
        let mut changes = xlib::XWindowChanges {
            x: x,
            y: y,
            width: width,
            height: height,

            // Ignored:
            border_width: 0,
            sibling: 0,
            stack_mode: 0,
        };
        let flags = (xlib::CWX | xlib::CWY | xlib::CWWidth | xlib::CWHeight) as u32;

        unsafe {
            xlib::XConfigureWindow(self.display, self.xwindow, flags, &mut changes);
        };

        Ok(())
    }

    fn grab_keys(&mut self, keys: &[Key]) {
        for key in keys.iter() {
            unsafe {
                let keycode = xlib::XKeysymToKeycode(self.display, key.keysym as u64) as i32;
                xlib::XGrabKey(self.display,
                               keycode,
                               key.mod_mask,
                               self.xwindow,
                               0,
                               xlib::GrabModeAsync,
                               xlib::GrabModeAsync);
            }
        }
    }
}

trait Layout {
    fn layout(&self, width: i32, height: i32, stack: &mut [Win]) -> Result<(), ()>;
}

struct TiledLayout;

impl Layout for TiledLayout {
    fn layout(&self, width: i32, height: i32, stack: &mut [Win]) -> Result<(), ()> {
        if stack.len() == 0 {
            return Ok(());
        }

        let tile_height = height / stack.len() as i32;

        for (i, window) in stack.iter_mut().enumerate() {
            window.position(0, i as i32 * tile_height, width, tile_height)?;
        }

        Ok(())
    }
}

// Error handler used during setup, which simply checks for the BadAccess error
// which indicates that another WM is already running.
unsafe extern "C" fn error_handler_init(disp: *mut Display, err: *mut XErrorEvent) -> c_int {
    if (*err).error_code == BadAccess {
        panic!("Another WM is already running");
    }
    0
}

// Actual error handler used during normal operation.
unsafe extern "C" fn error_handler(disp: *mut Display, err: *mut XErrorEvent) -> c_int {
    let buffer_size: usize = 1024;
    let mut buffer = Vec::<u8>::with_capacity(buffer_size);
    // XXX the docs say this returns the error text in the 'current locale'. We're
    // being extremely naughty and assuming this is UTF-8.
    // We're also assuming the return value of XGetErrorText is the actual length
    // of the string.
    let len: c_int = xlib::XGetErrorText(disp,
                                         (*err).error_code as i32,
                                         buffer.as_mut_ptr() as *mut c_char,
                                         buffer_size as i32);
    buffer.truncate(len as usize);
    let error_text = CString::new(buffer).unwrap().into_string().unwrap();
    error!("Received X error: request={}, error_code=({}, {}), resource_id={}",
           (*err).request_code,
           (*err).error_code,
           error_text,
           (*err).resourceid);
    0
}

fn xevent_to_str(event: &xlib::XEvent) -> &str {
    match event.get_type() {
        2 => "KeyPress",
        3 => "KeyRelease",
        4 => "ButtonPress",
        5 => "ButtonRelease",
        6 => "MotionNotify",
        7 => "EnterNotify",
        8 => "LeaveNotify",
        9 => "FocusIn",
        10 => "FocusOut",
        11 => "KeymapNotify",
        12 => "Expose",
        13 => "GraphicsExpose",
        14 => "NoExpose",
        15 => "VisibilityNotify",
        16 => "CreateNotify",
        17 => "DestroyNotify",
        18 => "UnmapNotify",
        19 => "MapNotify",
        20 => "MapRequest",
        21 => "ReparentNotify",
        22 => "ConfigureNotify",
        23 => "ConfigureRequest",
        24 => "GravityNotify",
        25 => "ResizeRequest",
        26 => "CirculateNotify",
        27 => "CirculateRequest",
        28 => "PropertyNotify",
        29 => "SelectionClear",
        30 => "SelectionRequest",
        31 => "SelectionNotify",
        32 => "ColormapNotify",
        33 => "ClientMessage",
        34 => "MappingNotify",
        35 => "GenericEvent",
        36 => "LASTEvent",
        _ => {
            error!("Unknown XEvent type: {}", event.get_type());
            "Unknown"
        }
    }
}

fn key_handler() {
    info!("Key press!");
}

struct Key {
    mod_mask: std::os::raw::c_uint,
    keysym: std::os::raw::c_uint,
    handler: Box<Fn()>,
}

impl std::fmt::Display for Key {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f,
               "Key {{ mod_mask: {}, keysym: {} }}",
               self.mod_mask,
               self.keysym)
    }
}

fn main() {
    env_logger::init().unwrap();

    let keys = vec![Key {
                        mod_mask: xlib::Mod4Mask,
                        keysym: x11::keysym::XK_T,
                        handler: Box::new(key_handler),
                    }];

    unsafe {
        let disp: *mut Display = XOpenDisplay(ptr::null_mut());
        assert!(!disp.is_null());
        let root: Window = XDefaultRootWindow(disp);
        assert!(root != 0);

        XSetErrorHandler(Some(error_handler_init));
        xlib::XSelectInput(disp,
                           root,
                           xlib::SubstructureNotifyMask | xlib::SubstructureRedirectMask);
        xlib::XSync(disp, 0);

        // If we get this far, then our panicing error handler didn't complain!
        info!("We are now the WM");

        XSetErrorHandler(Some(error_handler));

        let mut attrs: xlib::XWindowAttributes = std::mem::zeroed();
        xlib::XGetWindowAttributes(disp, root, &mut attrs);
        info!("Root window has geometry: {}x{}", attrs.width, attrs.height);

        let mut stack: Vec<Win> = Vec::new();

        // Focus is an index into the stack. We could do better and use the borrow checker to ensure
        // that it doesn't point at the wrong data when an item is added/removed from the stack.
        let mut focus: Option<usize> = None;

        let layout = TiledLayout {};

        loop {
            info!("Getting event...");
            let mut event = xlib::XEvent { pad: [0; 24] };
            xlib::XNextEvent(disp, &mut event);
            info!("Received event: {}", xevent_to_str(&event));

            match event.get_type() {
                xlib::MapRequest => {
                    let event = xlib::XMapRequestEvent::from(event);
                    let mut window = Win {
                        display: disp,
                        xwindow: event.window,
                    };
                    window.grab_keys(&keys);

                    xlib::XSelectInput(disp, window.xwindow, xlib::EnterWindowMask);

                    stack.push(window);

                    layout.layout(attrs.width, attrs.height, stack.as_mut());

                    // TODO: Make this into a method on Win?
                    xlib::XMapWindow(disp, event.window);

                }

                xlib::DestroyNotify => {
                    let event = xlib::XDestroyWindowEvent::from(event);

                    stack.iter().position(|ref w| w.xwindow == event.window).map(|index| stack.remove(index));

                    layout.layout(attrs.width, attrs.height, stack.as_mut());
                }

                xlib::KeyPress => {
                    let event = xlib::XKeyEvent::from(event);

                    for key in keys.iter() {
                        let keycode = xlib::XKeysymToKeycode(disp, key.keysym as u64) as u32;
                        debug!("KeyPress: state={}, keycode={}", event.state, event.keycode);

                        // TODO: Allow extra mod keys to be pressed at the same time. (Add test!)
                        if (event.state & key.mod_mask != 0) && event.keycode == keycode {
                            info!("KeyPress matches key: {}", key);
                            (key.handler)();
                            break;
                        }
                    }

                }

                xlib::EnterNotify => {
                    let event = xlib::XEnterWindowEvent::from(event);

                    focus = stack.iter().position(|ref w| w.xwindow == event.window);
                    debug!("EnterNotify: {}", focus);
                }

                _ => {}
            }

            println!("Stack: {:?}", stack);
        }

    };
    println!("Hello, world!");
}
<commit_msg>Some structure.<commit_after>#[macro_use]
extern crate log;
extern crate env_logger;
extern crate libc;
extern crate x11;

use std::ffi::CString;
use std::os::raw::{c_int, c_char};
use std::ptr;
use std::convert::From;

use x11::xlib;
use x11::xlib::{BadAccess, Display, Window, XErrorEvent, XOpenDisplay, XDefaultRootWindow,
                XSetErrorHandler};

#[derive(Debug)]
struct Win {
    display: *mut Display,
    xwindow: Window,
}

impl Win {
    // Does this really need to be &mut self? It feels light it ought to be as it is actually
    // modifying the underlying window, even if we're not actually modifying the value as far as
    // Rust is concerned.
    fn position(&mut self, x: i32, y: i32, width: i32, height: i32) -> Result<(), String> {
        let mut changes = xlib::XWindowChanges {
            x: x,
            y: y,
            width: width,
            height: height,

            // Ignored:
            border_width: 0,
            sibling: 0,
            stack_mode: 0,
        };
        let flags = (xlib::CWX | xlib::CWY | xlib::CWWidth | xlib::CWHeight) as u32;

        unsafe {
            xlib::XConfigureWindow(self.display, self.xwindow, flags, &mut changes);
        };

        Ok(())
    }

    fn grab_keys(&mut self, keys: &[Key]) {
        for key in keys.iter() {
            unsafe {
                let keycode = xlib::XKeysymToKeycode(self.display, key.keysym as u64) as i32;
                xlib::XGrabKey(self.display,
                               keycode,
                               key.mod_mask,
                               self.xwindow,
                               0,
                               xlib::GrabModeAsync,
                               xlib::GrabModeAsync);
            }
        }
    }
}

trait Layout {
    fn layout(&self, width: i32, height: i32, stack: &mut [Win]) -> Result<(), String>;
}

struct TiledLayout;

impl Layout for TiledLayout {
    fn layout(&self, width: i32, height: i32, stack: &mut [Win]) -> Result<(), String> {
        if stack.len() == 0 {
            return Ok(());
        }

        let tile_height = height / stack.len() as i32;

        for (i, window) in stack.iter_mut().enumerate() {
            window.position(0, i as i32 * tile_height, width, tile_height)?;
        }

        Ok(())
    }
}

// Error handler used during setup, which simply checks for the BadAccess error
// which indicates that another WM is already running.
unsafe extern "C" fn error_handler_init(disp: *mut Display, err: *mut XErrorEvent) -> c_int {
    if (*err).error_code == BadAccess {
        panic!("Another WM is already running");
    }
    0
}

// Actual error handler used during normal operation.
unsafe extern "C" fn error_handler(disp: *mut Display, err: *mut XErrorEvent) -> c_int {
    let buffer_size: usize = 1024;
    let mut buffer = Vec::<u8>::with_capacity(buffer_size);
    // XXX the docs say this returns the error text in the 'current locale'. We're
    // being extremely naughty and assuming this is UTF-8.
    // We're also assuming the return value of XGetErrorText is the actual length
    // of the string.
    let len: c_int = xlib::XGetErrorText(disp,
                                         (*err).error_code as i32,
                                         buffer.as_mut_ptr() as *mut c_char,
                                         buffer_size as i32);
    buffer.truncate(len as usize);
    let error_text = CString::new(buffer).unwrap().into_string().unwrap();
    error!("Received X error: request={}, error_code=({}, {}), resource_id={}",
           (*err).request_code,
           (*err).error_code,
           error_text,
           (*err).resourceid);
    0
}

fn xevent_to_str(event: &xlib::XEvent) -> &str {
    match event.get_type() {
        2 => "KeyPress",
        3 => "KeyRelease",
        4 => "ButtonPress",
        5 => "ButtonRelease",
        6 => "MotionNotify",
        7 => "EnterNotify",
        8 => "LeaveNotify",
        9 => "FocusIn",
        10 => "FocusOut",
        11 => "KeymapNotify",
        12 => "Expose",
        13 => "GraphicsExpose",
        14 => "NoExpose",
        15 => "VisibilityNotify",
        16 => "CreateNotify",
        17 => "DestroyNotify",
        18 => "UnmapNotify",
        19 => "MapNotify",
        20 => "MapRequest",
        21 => "ReparentNotify",
        22 => "ConfigureNotify",
        23 => "ConfigureRequest",
        24 => "GravityNotify",
        25 => "ResizeRequest",
        26 => "CirculateNotify",
        27 => "CirculateRequest",
        28 => "PropertyNotify",
        29 => "SelectionClear",
        30 => "SelectionRequest",
        31 => "SelectionNotify",
        32 => "ColormapNotify",
        33 => "ClientMessage",
        34 => "MappingNotify",
        35 => "GenericEvent",
        36 => "LASTEvent",
        _ => {
            error!("Unknown XEvent type: {}", event.get_type());
            "Unknown"
        }
    }
}

fn key_handler() {
    info!("Key press!");
}

struct Key {
    mod_mask: std::os::raw::c_uint,
    keysym: std::os::raw::c_uint,
    handler: Box<Fn()>,
}

impl std::fmt::Display for Key {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f,
               "Key {{ mod_mask: {}, keysym: {} }}",
               self.mod_mask,
               self.keysym)
    }
}

struct Config {
    keys: Vec<Key>,
    layout: Box<Layout>,
}

struct RustWindowManager {
    display: *mut Display,
    root: Window, // Could be Win?

    config: Config,

    stack: Vec<Win>,
    // Focus is an index into the stack. We could do better and use the borrow checker to ensure
    // that it doesn't point at the wrong data when an item is added/removed from the stack.
    focus: Option<usize>
}

impl RustWindowManager {
    fn new(config: Config) -> Result<Self, String> {
        let (display, root) = unsafe {
            let display: *mut Display = XOpenDisplay(ptr::null_mut());
            if display.is_null() {
                return Err("XOpenDisplay() returned null".to_owned());
            }

            let root: Window = XDefaultRootWindow(display);
            if root == 0 {
                return Err("XDefaultRootWindow returned 0".to_owned());
            }

            (display, root)
        };

        // Install ourselves as the WM.
        unsafe {
            // It's tricky to get state from the error handler to here, so we install a special handler
            // while becoming the WM that panics on error.
            XSetErrorHandler(Some(error_handler_init));
            xlib::XSelectInput(display,
                            root,
                            xlib::SubstructureNotifyMask | xlib::SubstructureRedirectMask);
            xlib::XSync(display, 0);

            // If we get this far, then our error handler didn't panic. Set a more useful error handler.
            XSetErrorHandler(Some(error_handler));
        }

        Ok(RustWindowManager {
            display: display,
            root: root,

            config: config,

            stack: Vec::new(),
            focus: None,
        })
    }

    fn layout(&mut self) -> Result<(), String> {
        let (width, height) = unsafe {
            let mut attrs: xlib::XWindowAttributes = std::mem::zeroed();
            xlib::XGetWindowAttributes(self.display, self.root, &mut attrs);
            info!("Root window has geometry: {}x{}", attrs.width, attrs.height);
            (attrs.width, attrs.height)
        };

        self.config.layout.layout(width, height, &mut self.stack)
    }
}

fn main() {
    env_logger::init().unwrap();

    let keys = vec![Key {
                        mod_mask: xlib::Mod4Mask,
                        keysym: x11::keysym::XK_T,
                        handler: Box::new(key_handler),
                    }];
    let layout = Box::new(TiledLayout {});
    let config = Config { keys: keys, layout: layout };

    let mut wm = RustWindowManager::new(config).unwrap();

    unsafe {
        loop {
            let mut event = xlib::XEvent { pad: [0; 24] };
            xlib::XNextEvent(wm.display, &mut event);
            info!("Received event: {}", xevent_to_str(&event));

            match event.get_type() {
                xlib::MapRequest => {
                    let event = xlib::XMapRequestEvent::from(event);
                    let mut window = Win {
                        display: wm.display,
                        xwindow: event.window,
                    };
                    window.grab_keys(&wm.config.keys);

                    xlib::XSelectInput(wm.display, window.xwindow, xlib::EnterWindowMask);

                    wm.stack.push(window);

                    wm.layout();

                    // TODO: Make this into a method on Win?
                    xlib::XMapWindow(wm.display, event.window);

                }

                xlib::DestroyNotify => {
                    let event = xlib::XDestroyWindowEvent::from(event);

                    wm.stack.iter().position(|ref w| w.xwindow == event.window).map(|index| wm.stack.remove(index));

                    wm.layout();
                }

                xlib::KeyPress => {
                    let event = xlib::XKeyEvent::from(event);

                    for key in wm.config.keys.iter() {
                        let keycode = xlib::XKeysymToKeycode(wm.display, key.keysym as u64) as u32;
                        debug!("KeyPress: state={}, keycode={}", event.state, event.keycode);

                        // TODO: Allow extra mod keys to be pressed at the same time. (Add test!)
                        if (event.state & key.mod_mask != 0) && event.keycode == keycode {
                            info!("KeyPress matches key: {}", key);
                            (key.handler)();
                            break;
                        }
                    }

                }

                xlib::EnterNotify => {
                    let event = xlib::XEnterWindowEvent::from(event);

                    wm.focus = wm.stack.iter().position(|ref w| w.xwindow == event.window);
                    debug!("EnterNotify: {:?}", wm.focus);
                }

                _ => {}
            }

            println!("Stack: {:?}", wm.stack);
        }

    };
    println!("Hello, world!");
}
<|endoftext|>


<commit_before>struct Item(&'static str);

struct Location {
    description: &'static str,
    items: Vec<Item>,
}

// how to do actions?
// as an enum? sounds reasonable.
// what properties do they have?
// a keyword which is typed in
// one or more arguments, possibly a variable number
// something which happens when they are invoked

// "look": print the area description
// "take + item": move the item to the player's inventory
// "go + direction": move to the area in that direction
// "use + item (+ object)": maybe remove the item, invoke a (targeted?) effect

// alternatively, instantiate actions at runtime
// write a struct for each one with arity and synonyms
// problem: each one is associated with a function of some sort
// do not want to go adding these at runtime if it can be avoided

fn parse(command: String) {
    let mut tokens = command.split(' ');
    let verb = tokens.nth(0);
    //   match tokens[0] {
    //       "look" => println!("You look around."),
    //       "take" => println!("You take something."),
    //       "go" => println!("You go somewhere."),
    //       "use" => println!("You use something."),
    //       _ => println!("Unknown command!"),
    //   }
    // look should just check for arity 0 invoke an associated function
    // take should parse rest of the command, see if there is an item with a name equal to the rest of the command
    // go should parse exactly one more token and go in that direction... how?
    // use should parse either one or two tokens and act accordingly
}

fn main() {
    let item1 = Item("Little key");
    let item2 = Item("Big key");
    let hall = Location{ description: "A wide open space. Streams of lava flow on both sides of the entry gate.",
                         items: vec![item1, item2] };
}
<commit_msg>Still not sure why this thing had to be made mutable, but pattern match with Option works like this...<commit_after>struct Item(&'static str);

struct Location {
    description: &'static str,
    items: Vec<Item>,
}

// how to do actions?
// as an enum? sounds reasonable.
// what properties do they have?
// a keyword which is typed in
// one or more arguments, possibly a variable number
// something which happens when they are invoked

// "look": print the area description
// "take + item": move the item to the player's inventory
// "go + direction": move to the area in that direction
// "use + item (+ object)": maybe remove the item, invoke a (targeted?) effect

// alternatively, instantiate actions at runtime
// write a struct for each one with arity and synonyms
// problem: each one is associated with a function of some sort
// do not want to go adding these at runtime if it can be avoided

fn parse(command: String) {
    let mut tokens = command.split(' ');
    let verb = tokens.nth(0);
    match verb {
        Some("look") => println!("You look around."),
        Some("take") => println!("You take something."),
        Some("go") => println!("You go somewhere."),
        Some("use") => println!("You use something."),
        _ => println!("Unknown command!"),
    }
    // look should just check for arity 0 invoke an associated function
    // take should parse rest of the command, see if there is an item with a name equal to the rest of the command
    // go should parse exactly one more token and go in that direction... how?
    // use should parse either one or two tokens and act accordingly
}

fn main() {
    let item1 = Item("Little key");
    let item2 = Item("Big key");
    let hall = Location{ description: "A wide open space. Streams of lava flow on both sides of the entry gate.",
                         items: vec![item1, item2] };
}
<|endoftext|>


<commit_before>/*
    Copyright 2013 Jesse 'Jeaye' Wilkerson
    See licensing in LICENSE file, or at:
        http://www.opensource.org/licenses/BSD-3-Clause

    File: main.rs
    Author: Jesse 'Jeaye' Wilkerson
    Description:
      Entry point.
*/

extern mod extra;
extern mod opengles;
extern mod glfw;

use std::libc;

#[nolink]
#[link_args="-lX11 -lXrandr -lXi -lXxf86vm"]
extern { }

#[path = "gl/mod.rs"]
mod gl;

#[path = "math/mod.rs"]
mod math;

#[macro_escape]
#[path = "gl/check.rs"]
mod check;

#[path = "obj/bsp/mod.rs"]
mod bsp;

#[path = "ui/mod.rs"]
mod ui;

#[path = "obj/primitive/mod.rs"]
mod primitive;

#[path = "obj/voxel/mod.rs"]
mod voxel;

fn main()
{
  glfw::set_error_callback(error_callback);

  do glfw::spawn
  {
    glfw::window_hint::context_version(3, 2);
    glfw::window_hint::opengl_profile(glfw::OPENGL_CORE_PROFILE);
    glfw::window_hint::opengl_forward_compat(true);

    let window_res = glfw::Window::create(1024, 768, "Q^3", glfw::Windowed);
    let window = match window_res
    {
      Some(win) => { @win },
      None => { fail!("Failed to create window!") }
    };
    window.make_context_current();

    let console = @mut ui::Console::new();
    let console_activator = ui::Console_Activator::new(console);

    let camera = gl::Camera::new(window);
    camera.init();

    /* Setup UI elements. */
    let ui_input = @mut ui::Input_State::new();
    ui_input.push(camera as @mut ui::Input_Listener);
    ui_input.push(console_activator as @mut ui::Input_Listener);

    /* Setup callbacks. */ /* TODO: Crash on close with these callbacks. */
    window.set_cursor_mode(glfw::CURSOR_DISABLED);
    do window.set_size_callback |_, width, height|
    { camera.resize(width as i32, height as i32); }
    do window.set_cursor_pos_callback |_, x, y|
    { ui_input.mouse_moved(x as f32, y as f32); }
    do window.set_char_callback |_, c|
    { ui_input.key_char(c); }
    do window.set_key_callback |window, key, _scancode, action, mods|
    {
      ui_input.key_action(key, action, mods);
      key_callback(window, key, action);
    }

    let ui_renderer = @mut ui::Renderer::new();

    let map = bsp::Map::new("data/maps/q3ctf1.bsp");

    let st = extra::time::precise_time_s();
    let vox_map = voxel::Map::new(map.tris, 200);
    let et = extra::time::precise_time_s();
    println(fmt!("Voxel map creation took %? seconds.", (et - st)));

    /* Temp test for font loading. */
    let font = ui::Font::new("data/fonts/test.ttf", 30);

    /* Shader Creation. */
    let vox_shader = @mut gl::Shader_Builder::new_with_files("data/shaders/voxel.vert", "data/shaders/voxel.frag");
    let color_shader = @mut gl::Shader_Builder::new_with_files("data/shaders/color.vert", "data/shaders/color.frag");
    vox_shader.bind();

    let proj_loc = vox_shader.get_uniform_location("proj");
    let world_loc = vox_shader.get_uniform_location("world");
    let voxel_size_loc = vox_shader.get_uniform_location("voxel_size");
    let offsets_loc = vox_shader.get_uniform_location("offsets");
    let color_proj_loc = color_shader.get_uniform_location("proj");
    let color_world_loc = color_shader.get_uniform_location("world");

    vox_shader.update_uniform_i32(offsets_loc, 0);

    let mut cur_time = (extra::time::precise_time_ns() / 10000) as f32; // Hundredth of a second
    let mut last_time = cur_time;

    /* Console functions. */
    console_activator.add_accessor("q3.version", |_|
    { fmt!("%s.%s", env!("VERSION"), env!("COMMIT")) });

    while !window.should_close()
    {
      glfw::poll_events();

      /* Delta time. */
      let delta = cur_time - last_time;
      last_time = cur_time;
      cur_time = (extra::time::precise_time_ns() / 10000) as f32;

      console.update(delta);
      camera.update(delta);

      vox_shader.bind();
      vox_shader.update_uniform_mat(proj_loc, &camera.projection);
      vox_shader.update_uniform_mat(world_loc, &camera.view);
      vox_shader.update_uniform_f32(voxel_size_loc, vox_map.voxel_size);

      color_shader.bind();
      color_shader.update_uniform_mat(color_proj_loc, &camera.projection);
      color_shader.update_uniform_mat(color_world_loc, &camera.view);

      let fps = camera.frame_rate;

      check!(gl::clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT));
      {
        //color_shader.bind();
        //map.draw();

        vox_shader.bind();
        vox_map.draw();

        ui_renderer.begin(camera);

        console.render(ui_renderer);

        if camera.show_fps
        { ui_renderer.render_font(fmt!("%?", fps), math::Vec2f::new(camera.window_size.x as f32 - 40.0, 0.0), &font); }

        ui_renderer.end();
      } window.swap_buffers();

      //extra::timer::sleep(@extra::uv::global_loop::get(), 1000 / (camera.target_frame_rate as uint));
    }
  }
}

fn key_callback(window: &glfw::Window, key: libc::c_int, action: libc::c_int)
{
  if action == glfw::PRESS && key == glfw::KEY_ESCAPE
  { window.set_should_close(true); }
}

fn error_callback(error: libc::c_int, description: ~str)
{ error!("GLFW Error %?: %s", error, description); }

<commit_msg> #23 Targeted X link args only for Linux -- fixes Mac<commit_after>/*
    Copyright 2013 Jesse 'Jeaye' Wilkerson
    See licensing in LICENSE file, or at:
        http://www.opensource.org/licenses/BSD-3-Clause

    File: main.rs
    Author: Jesse 'Jeaye' Wilkerson
    Description:
      Entry point.
*/

extern mod extra;
extern mod opengles;
extern mod glfw;

use std::libc;

#[cfg(target_os = "linux")]
#[nolink]
#[link_args = "-lX11 -lXrandr -lXi -lXxf86vm"]
extern { }

#[path = "gl/mod.rs"]
mod gl;

#[path = "math/mod.rs"]
mod math;

#[macro_escape]
#[path = "gl/check.rs"]
mod check;

#[path = "obj/bsp/mod.rs"]
mod bsp;

#[path = "ui/mod.rs"]
mod ui;

#[path = "obj/primitive/mod.rs"]
mod primitive;

#[path = "obj/voxel/mod.rs"]
mod voxel;

fn main()
{
  glfw::set_error_callback(error_callback);

  do glfw::spawn
  {
    glfw::window_hint::context_version(3, 2);
    glfw::window_hint::opengl_profile(glfw::OPENGL_CORE_PROFILE);
    glfw::window_hint::opengl_forward_compat(true);

    let window_res = glfw::Window::create(1024, 768, "Q^3", glfw::Windowed);
    let window = match window_res
    {
      Some(win) => { @win },
      None => { fail!("Failed to create window!") }
    };
    window.make_context_current();

    let console = @mut ui::Console::new();
    let console_activator = ui::Console_Activator::new(console);

    let camera = gl::Camera::new(window);
    camera.init();

    /* Setup UI elements. */
    let ui_input = @mut ui::Input_State::new();
    ui_input.push(camera as @mut ui::Input_Listener);
    ui_input.push(console_activator as @mut ui::Input_Listener);

    /* Setup callbacks. */ /* TODO: Crash on close with these callbacks. */
    window.set_cursor_mode(glfw::CURSOR_DISABLED);
    do window.set_size_callback |_, width, height|
    { camera.resize(width as i32, height as i32); }
    do window.set_cursor_pos_callback |_, x, y|
    { ui_input.mouse_moved(x as f32, y as f32); }
    do window.set_char_callback |_, c|
    { ui_input.key_char(c); }
    do window.set_key_callback |window, key, _scancode, action, mods|
    {
      ui_input.key_action(key, action, mods);
      key_callback(window, key, action);
    }

    let ui_renderer = @mut ui::Renderer::new();

    let map = bsp::Map::new("data/maps/q3ctf1.bsp");

    let st = extra::time::precise_time_s();
    let vox_map = voxel::Map::new(map.tris, 200);
    let et = extra::time::precise_time_s();
    println(fmt!("Voxel map creation took %? seconds.", (et - st)));

    /* Temp test for font loading. */
    let font = ui::Font::new("data/fonts/test.ttf", 30);

    /* Shader Creation. */
    let vox_shader = @mut gl::Shader_Builder::new_with_files("data/shaders/voxel.vert", "data/shaders/voxel.frag");
    let color_shader = @mut gl::Shader_Builder::new_with_files("data/shaders/color.vert", "data/shaders/color.frag");
    vox_shader.bind();

    let proj_loc = vox_shader.get_uniform_location("proj");
    let world_loc = vox_shader.get_uniform_location("world");
    let voxel_size_loc = vox_shader.get_uniform_location("voxel_size");
    let offsets_loc = vox_shader.get_uniform_location("offsets");
    let color_proj_loc = color_shader.get_uniform_location("proj");
    let color_world_loc = color_shader.get_uniform_location("world");

    vox_shader.update_uniform_i32(offsets_loc, 0);

    let mut cur_time = (extra::time::precise_time_ns() / 10000) as f32; // Hundredth of a second
    let mut last_time = cur_time;

    /* Console functions. */
    console_activator.add_accessor("q3.version", |_|
    { fmt!("%s.%s", env!("VERSION"), env!("COMMIT")) });

    while !window.should_close()
    {
      glfw::poll_events();

      /* Delta time. */
      let delta = cur_time - last_time;
      last_time = cur_time;
      cur_time = (extra::time::precise_time_ns() / 10000) as f32;

      console.update(delta);
      camera.update(delta);

      vox_shader.bind();
      vox_shader.update_uniform_mat(proj_loc, &camera.projection);
      vox_shader.update_uniform_mat(world_loc, &camera.view);
      vox_shader.update_uniform_f32(voxel_size_loc, vox_map.voxel_size);

      color_shader.bind();
      color_shader.update_uniform_mat(color_proj_loc, &camera.projection);
      color_shader.update_uniform_mat(color_world_loc, &camera.view);

      let fps = camera.frame_rate;

      check!(gl::clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT));
      {
        //color_shader.bind();
        //map.draw();

        vox_shader.bind();
        vox_map.draw();

        ui_renderer.begin(camera);

        console.render(ui_renderer);

        if camera.show_fps
        { ui_renderer.render_font(fmt!("%?", fps), math::Vec2f::new(camera.window_size.x as f32 - 40.0, 0.0), &font); }

        ui_renderer.end();
      } window.swap_buffers();

      //extra::timer::sleep(@extra::uv::global_loop::get(), 1000 / (camera.target_frame_rate as uint));
    }
  }
}

fn key_callback(window: &glfw::Window, key: libc::c_int, action: libc::c_int)
{
  if action == glfw::PRESS && key == glfw::KEY_ESCAPE
  { window.set_should_close(true); }
}

fn error_callback(error: libc::c_int, description: ~str)
{ error!("GLFW Error %?: %s", error, description); }

<|endoftext|>


<commit_before>extern crate mio;

use mio::*;
use mio::net::{SockAddr};
use mio::net::tcp::{TcpSocket, TcpAcceptor};
use mio::buf::{ByteBuf, MutByteBuf, SliceBuf};
use mio::util::Slab;

fn main() {
    const SERVER: Token = Token(1);
    let addr = SockAddr::parse("127.0.0.1:13265").unwrap();
    let server = TcpSocket::v4().unwrap()
        .bind(&addr).unwrap()
        .listen(256).unwrap();

    let mut event_loop = EventLoop::<(), ()>::new().unwrap();
    event_loop.register(&server, SERVER).unwrap();

    struct TcpHandler {
        conns: Slab<TcpSocket>,
        sock: TcpAcceptor
    };

    impl TcpHandler {
        fn accept(&mut self, event_loop: &mut EventLoop<(), ()>) {
            let conn = self.sock.accept();
            let sock = conn.unwrap().unwrap();
            let tok = self.conns.insert(sock).ok().expect("could not add connection to slab");
            event_loop.register_opt(&self.conns[tok], tok, Interest::readable(), PollOpt::edge() | PollOpt::oneshot());
        }
    }

    impl Handler<(), ()> for TcpHandler {
        fn readable(&mut self, event_loop: &mut EventLoop<(), ()>, token: Token, _: ReadHint) {
            match token {
                SERVER => {
                    self.accept(event_loop);
                }
                tok => {
                    println!("tok: {}", tok.as_usize());
                    let mut read_buf = ByteBuf::mut_with_capacity(2048);
                    let mut interest = Interest::readable();
                    match self.conns[tok].read(&mut read_buf) {
                        Ok(NonBlock::WouldBlock) => {
                            panic!("We just got readable, but were unable to read from the socket?");
                        }
                        Ok(NonBlock::Ready(r)) => {
                            println!("CONN : we read {} bytes!", r);
                            // self.interest.remove(Interest::readable());
                            // self.interest.insert(Interest::writable());
                        }
                        Err(e) => {
                            println!("not implemented; client err={:?}", e);
                            interest = Interest::hup();
                            // self.interest.remove(Interest::readable());
                        }
                    }
                    event_loop.reregister(&self.conns[tok], tok, interest, PollOpt::edge() | PollOpt::oneshot());
                }
            }
        }
    }
    let mut tcp_server = TcpHandler {
        conns: Slab::new_starting_at(Token(2), 128),
        sock: server
    };
    let _ = event_loop.run(&mut tcp_server);
}
<commit_msg>worky! but fugly<commit_after>extern crate mio;

use mio::*;
use mio::net::{SockAddr};
use mio::net::tcp::{TcpSocket, TcpAcceptor};
use mio::buf::{ByteBuf, MutByteBuf, SliceBuf};
use mio::util::Slab;

fn main() {
    const SERVER: Token = Token(1);
    let addr = SockAddr::parse("127.0.0.1:13265").unwrap();
    let server = TcpSocket::v4().unwrap()
        .bind(&addr).unwrap()
        .listen(256).unwrap();

    let mut event_loop = EventLoop::<(), ()>::new().unwrap();
    event_loop.register(&server, SERVER).unwrap();

    struct TcpHandler {
        conns: Slab<TcpSocket>,
        sock: TcpAcceptor
    };

    impl TcpHandler {
        fn accept(&mut self, event_loop: &mut EventLoop<(), ()>) {
            let conn = self.sock.accept();
            let sock = conn.unwrap().unwrap();
            let tok = self.conns.insert(sock).ok().expect("could not add connection to slab");
            event_loop.register_opt(&self.conns[tok], tok, Interest::readable(), PollOpt::edge() | PollOpt::oneshot());
        }
    }

    impl Handler<(), ()> for TcpHandler {
        fn readable(&mut self, event_loop: &mut EventLoop<(), ()>, token: Token, _: ReadHint) {
            match token {
                SERVER => {
                    self.accept(event_loop);
                }
                tok => {
                    println!("tok: {}", tok.as_usize());
                    let mut read_buf = ByteBuf::mut_with_capacity(2048);
                    let mut interest = Interest::readable();
                    match self.conns[tok].read(&mut read_buf) {
                        Ok(NonBlock::WouldBlock) => {
                            panic!("We just got readable, but were unable to read from the socket?");
                        }
                        Ok(NonBlock::Ready(r)) => {
                            let mut buf = read_buf.flip();
                            let mut sl = [0; 2048];
                            buf.read_slice(&mut sl);
                            print!("{}", String::from_utf8(sl.to_vec()).unwrap());
                            // self.interest.remove(Interest::readable());
                            // self.interest.insert(Interest::writable());
                        }
                        Err(e) => {
                            event_loop.shutdown();
                            // println!("not implemented; client err={:?}", e);
                            // interest = Interest::hup();
                            // self.interest.remove(Interest::readable());
                        }
                    }
                    event_loop.reregister(&self.conns[tok], tok, interest, PollOpt::edge() | PollOpt::oneshot());
                }
            }
        }
    }
    let mut tcp_server = TcpHandler {
        conns: Slab::new_starting_at(Token(2), 128),
        sock: server
    };
    let _ = event_loop.run(&mut tcp_server);
}
<|endoftext|>


<commit_before>#![feature(libc)]
extern crate libc;
use std::ffi;

extern crate rustwlc;

use rustwlc::types;
use rustwlc::types::*;
//use rustwlc::types::LibinputDevice;
use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::types::interface::*;
use rustwlc::input::pointer;
use rustwlc::input::keyboard;
/*
struct CompositorAction {
    view: WlcView,
    grab: Point,
    edges: u32
}

static mut compositor: CompositorAction = CompositorAction {
    view: WlcView(0),
    grab: Point{ x: 0, y: 0},
    edges: 0
};
*/
fn main() {
    let interface: WlcInterface = WlcInterface {
        output: OutputInterface {
            created: Some(output_created),
            destroyed: Some(output_destroyed),
            focus: Some(output_focus),
            resolution: Some(output_resolution),

            render: OutputRenderInterface {
                pre: Some(output_render_pre),
                post: Some(output_render_post)
            }
        },
        view: ViewInterface {
            created: Some(view_created),
            destroyed: Some(view_destroyed),
            focus: Some(view_focus),
            move_to_output: Some(view_move_to_output),
            request: RequestInterface {
                geometry: Some(view_request_geometry),
                state: Some(view_request_state),
                move_: Some(view_request_move),
                resize: Some(view_request_resize),
                render: ViewRenderInterface {
                    pre: Some(view_request_render_pre),
                    post: Some(view_request_render_post)
                }
            }
        },
        keyboard: KeyboardInterface {
            key: Some(keyboard_key)
        },
        pointer: PointerInterface {
            button: Some(pointer_button),
            scroll: Some(pointer_scroll),
            motion: Some(pointer_motion)
        },
        touch: TouchInterface {
            touch: Some(touch_touch)
        },
        compositor: CompositorInterface {
            ready: Some(compositor_ready)
        },
        input: InputInterface {
            created: Some(input_created),
            destroyed: Some(input_destroyed)
        }
    };
    // Interfaces don't derive debug
    //println!("Created interface {:?}", interface);
    rustwlc::log_set_handler(log_callback);

    if !rustwlc::init(interface) {
        panic!("Unable to initialize wlc!");
    }
    rustwlc::run_wlc();
}

extern fn log_callback(log_type: LogType, text: *const libc::c_char) {
    let string_text = rustwlc::pointer_to_string(text);
    println!("Wlc Log: {}", string_text);
}

// Important rendering functions copied from wlc/example/example.c

fn start_interactive_action(view: WlcView, origin: Point) -> bool {
    true
}

fn stop_interactive_action() {

}

fn start_interactive_move(view: WlcView, origin: Point) {

}

fn start_interactive_resize(view: WlcView, edges: u32, origin: Point) {

}

fn get_topmost_view(output: WlcOutput, offset: Size) {

}

/// From example.c:
/// very simple layout function
/// you probably don't want to layout certain type of windows in wm
fn render_output(output: WlcOutput) {
    use std::cmp;
    let resolution = output.get_resolution();
    let views = output.get_views();

    if views.len() == 0 { println!("Didn't find any views to render :/"); }

    for view in views {
        view.set_geometry(0,
                          Geometry {
                              size: Size {
                                  w: resolution.w as u32,
                                  h: resolution.h as u32
                              },
                              origin: Point {
                                  x: resolution.w as i32,
                                  y: resolution.h as i32
                              }
                          });
    }

    /*
    let mut toggle = false;
    let mut y = 0u32;
//    use std::cmp;

    let w: u32 = resolution.w as u32 / 2u32;
    let h: u32 = resolution.h as u32 / cmp::max((1u32 + views.len() as u32) / 2u32, 1);

    for view in views {
        let g = Geometry {
            size: Size {
                w: if toggle { w } else { 0 },
                h: y
            },
            origin: Point {
                x: if !toggle { resolution.w as i32 } else { w as i32 },
                y: h as i32
            }
        };
        view.set_geometry(0, g);
        toggle = !toggle;
        y = y + if !toggle { h } else { 0 };
    }*/
}

// Hook up basic callbacks

extern fn output_created(output: WlcOutput) -> bool {
    println!("output_created");
    return true;
}

extern fn output_destroyed(output: WlcOutput) {
    println!("output_destroyed");
}

extern fn output_focus(output: WlcOutput, focused: bool) {
    println!("output_focus: {}", focused);
}

extern fn output_resolution(output: WlcOutput, old_size: Size, new_size: Size) {
    println!("output_resolution: {:?} to {:?}", old_size, new_size)
}

extern fn output_render_pre(output: WlcOutput) {
    //println!("output_render_pre");
}

extern fn output_render_post(output: WlcOutput) {
    //println!("output_render_post");
}

extern fn view_created(view: WlcView) -> bool {
    println!("view_created: {:?}", view);
    let output = view.get_output();
    println!("view_created: it's on output {:?}", output);
    view.set_mask(output.get_mask());
    view.bring_to_front();
    view.focus();
    render_output(output);
    true
}

extern fn view_destroyed(view: WlcView) {
    println!("view_destroyed: {:?}", view);
    render_output(view.get_output());
}

extern fn view_focus(current: WlcView, focused: bool) {
    println!("view_focus: {:?} {}", current, focused);
    current.set_state(ViewState::Activated, focused);
}

extern fn view_move_to_output(current: WlcView, q1: WlcView, q2: WlcView) {
    println!("view_move_to_output: {:?}, {:?}, {:?}", current, q1, q2);
}

extern fn view_request_geometry(view: WlcView, geometry: Geometry) {
    println!("view_request_geometry: {:?} wants {:?}", view, geometry);
    view.set_geometry(0, geometry);
    render_output(view.get_output());
}

extern fn view_request_state(view: WlcView, state: ViewState, handled: bool) {
    println!("view_request_state: call wlc_view_set_state({:?})", state);
    view.set_state(state, handled);
}

extern fn view_request_move(view: WlcView, dest: Point) {
    println!("view_request_move: to {}, start interactive mode.", dest);
}

extern fn view_request_resize(view: WlcView, edge: ResizeEdge, location: Point) {
    println!("view_request_resize: size {:?}, to {}, start interactive mode.",
             edge, location);
}

extern fn view_request_render_pre(view: WlcView) {
    //println!("view_request_render_pre");
}

extern fn view_request_render_post(view: WlcView) {
    //println!("view_request_render_post");
}

extern fn keyboard_key(view: WlcView, time: u32, mods: KeyboardModifiers,
                       key: u32, state: KeyState) -> bool {
    use std::process::{Command};
    println!("keyboard_key: time {}, mods {:?}, key {:?}, state {:?}",
             time, mods, key, state);
    if state == KeyState::Pressed { return false; }
    println!("Preparing to open the terminal...");
    rustwlc::exec("weston-terminal".to_string(), vec!["weston-terminal".to_string()]);
    // We are definitely able to open programs, they can definitely launch in the host X11 server.
    //rustwlc::exec("emacs".to_string(), vec!["emacs".to_string()]);
    //let output = std::process::Command::new("weston-terminal").output()
    //.unwrap_or_else(|e| { println!("Could not unwrap output!"); panic!("aaaa") });
    let mut child = Command::new("/bin/weston-terminal").spawn()
        .unwrap_or_else(|e| { println!("Error spawning child: {}", e); panic!("1") });

    //let ecode = child.wait().unwrap_or_else(|e| println!("Error unwrapping child"));
    //println!("Output: {}", String::from_utf8(output.stdout).unwrap_or("nope".to_string()));

    false
}

extern fn pointer_button(view: WlcView, button: libc::c_uint, mods: KeyboardModifiers,
                  key: u32, state: ButtonState, point: Point) -> bool {
    println!("pointer_button: key {}, point {}", key, point);

    if state == ButtonState::Pressed {
        view.focus();
    }
    false
}

extern fn pointer_scroll(view: WlcView, button: u32, mods: KeyboardModifiers,
                  axis: ScrollAxis, heights: [u64; 2]) -> bool {
    println!("pointer_scroll");
    false
}

extern fn pointer_motion(view: WlcView, time: u32, point: Point) {
    //println!("Pointer moved {} to {}", time, point);
    // TODO wlc_pointer_set_position
    pointer::set_position(point);
}

extern fn touch_touch(view: WlcView, time: libc::c_uint, mods: KeyboardModifiers,
               touch: TouchType, key: i32, point: Point) -> bool {
    false
}

extern fn compositor_ready() {
    println!("Preparing compositor!");
}

extern fn input_created(device: LibinputDevice) -> bool {
    println!("input_created");
    false
}

extern fn input_destroyed(device: LibinputDevice) {
    println!("input_destroyed");
}
<commit_msg>Fixed output_get_geometry and view_get_title<commit_after>#![feature(libc)]
extern crate libc;
use std::ffi;

extern crate rustwlc;

use rustwlc::types;
use rustwlc::types::*;
//use rustwlc::types::LibinputDevice;
use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::types::interface::*;
use rustwlc::input::pointer;
use rustwlc::input::keyboard;
/*
struct CompositorAction {
    view: WlcView,
    grab: Point,
    edges: u32
}

static mut compositor: CompositorAction = CompositorAction {
    view: WlcView(0),
    grab: Point{ x: 0, y: 0},
    edges: 0
};
*/
fn main() {
    let interface: WlcInterface = WlcInterface {
        output: OutputInterface {
            created: Some(output_created),
            destroyed: Some(output_destroyed),
            focus: Some(output_focus),
            resolution: Some(output_resolution),

            render: OutputRenderInterface {
                pre: Some(output_render_pre),
                post: Some(output_render_post)
            }
        },
        view: ViewInterface {
            created: Some(view_created),
            destroyed: Some(view_destroyed),
            focus: Some(view_focus),
            move_to_output: Some(view_move_to_output),
            request: RequestInterface {
                geometry: Some(view_request_geometry),
                state: Some(view_request_state),
                move_: Some(view_request_move),
                resize: Some(view_request_resize),
                render: ViewRenderInterface {
                    pre: Some(view_request_render_pre),
                    post: Some(view_request_render_post)
                }
            }
        },
        keyboard: KeyboardInterface {
            key: Some(keyboard_key)
        },
        pointer: PointerInterface {
            button: Some(pointer_button),
            scroll: Some(pointer_scroll),
            motion: Some(pointer_motion)
        },
        touch: TouchInterface {
            touch: Some(touch_touch)
        },
        compositor: CompositorInterface {
            ready: Some(compositor_ready)
        },
        input: InputInterface {
            created: Some(input_created),
            destroyed: Some(input_destroyed)
        }
    };
    // Interfaces don't derive debug
    //println!("Created interface {:?}", interface);
    rustwlc::log_set_handler(log_callback);

    if !rustwlc::init(interface) {
        panic!("Unable to initialize wlc!");
    }
    rustwlc::run_wlc();
}

extern fn log_callback(log_type: LogType, text: *const libc::c_char) {
    let string_text = rustwlc::pointer_to_string(text);
    println!("Wlc Log: {}", string_text);
}

// Important rendering functions copied from wlc/example/example.c

fn start_interactive_action(view: WlcView, origin: Point) -> bool {
    true
}

fn stop_interactive_action() {

}

fn start_interactive_move(view: WlcView, origin: Point) {

}

fn start_interactive_resize(view: WlcView, edges: u32, origin: Point) {

}

fn get_topmost_view(output: WlcOutput, offset: Size) {

}

/// From example.c:
/// very simple layout function
/// you probably don't want to layout certain type of windows in wm
fn render_output(output: WlcOutput) {
    use std::cmp;
    let resolution = output.get_resolution();
    let views = output.get_views();
    println!("Rendering {} views for {} (resolution = {:?})", views.len(), output.get_name(), resolution);

    if views.len() == 0 { println!("Didn't find any views to render :/"); }

    for view in views {
        //println!("Found view {:?}: type {}, output {:?}, geometry {:?}, state: {}, parent: {:?}", view, view.get_type(), view.get_output(), view.get_geometry(), view.get_state(), view.get_parent());
        println!("Setting {:?}", view);
        println!("\tIts type: {}", view.get_type());
        println!("\tIts output: {}", view.get_output().get_name());
        println!("\tIts geometry: {:?}", view.get_geometry());
        println!("\tIts state: {}", view.get_state());
        println!("\tIts parent: {:?}", view.get_parent());
        println!("\tIts title: {}", view.get_title());
        // get_class doesn't work but maybe it's not supposed to
        //println!("\tIts class: {}", view.get_class());
        view.set_geometry(0,
                          &Geometry {
                              size: Size {
                                  w: 200 as u32,
                                  h: 200 as u32
                              },
                              origin: Point {
                                  x: resolution.w as i32,
                                  y: resolution.h as i32
                              }
                          });
        println!("Attempted to set geometry, got {:?}", view.get_geometry());
    }

    /*
    let mut toggle = false;
    let mut y = 0u32;
//    use std::cmp;

    let w: u32 = resolution.w as u32 / 2u32;
    let h: u32 = resolution.h as u32 / cmp::max((1u32 + views.len() as u32) / 2u32, 1);

    for view in views {
        let g = Geometry {
            size: Size {
                w: if toggle { w } else { 0 },
                h: y
            },
            origin: Point {
                x: if !toggle { resolution.w as i32 } else { w as i32 },
                y: h as i32
            }
        };
        view.set_geometry(0, g);
        toggle = !toggle;
        y = y + if !toggle { h } else { 0 };
    }*/
}

// Hook up basic callbacks

extern fn output_created(output: WlcOutput) -> bool {
    println!("output_created");
    return true;
}

extern fn output_destroyed(output: WlcOutput) {
    println!("output_destroyed");
}

extern fn output_focus(output: WlcOutput, focused: bool) {
    println!("output_focus: {}", focused);
}

extern fn output_resolution(output: WlcOutput, old_size: Size, new_size: Size) {
    println!("output_resolution: {:?} to {:?}", old_size, new_size)
}

extern fn output_render_pre(output: WlcOutput) {
    //println!("output_render_pre");
}

extern fn output_render_post(output: WlcOutput) {
    //println!("output_render_post");
}

extern fn view_created(view: WlcView) -> bool {
    println!("view_created: {:?}", view);
    let output = view.get_output();
    //println!("view_created: it's on output {:?}", output);
    //println!("Output: name {},",
             //output.get_name());
    //println!("View: type {}",
    //           view.get_type());;
    view.set_mask(output.get_mask());
    view.bring_to_front();
    view.focus();
    render_output(output);
    true
}

extern fn view_destroyed(view: WlcView) {
    println!("view_destroyed: {:?}", view);
    render_output(view.get_output());
}

extern fn view_focus(current: WlcView, focused: bool) {
    println!("view_focus: {:?} {}", current, focused);
    current.set_state(ViewState::Activated, focused);
}

extern fn view_move_to_output(current: WlcView, q1: WlcView, q2: WlcView) {
    println!("view_move_to_output: {:?}, {:?}, {:?}", current, q1, q2);
}

extern fn view_request_geometry(view: WlcView, geometry: *const Geometry) {
    println!("view_request_geometry: {:?} wants {:?}", view, geometry);
    view.set_geometry(0, geometry);
    render_output(view.get_output());
}

extern fn view_request_state(view: WlcView, state: ViewState, handled: bool) {
    println!("view_request_state: call wlc_view_set_state({:?})", state);
    view.set_state(state, handled);
}

extern fn view_request_move(view: WlcView, dest: Point) {
    println!("view_request_move: to {}, start interactive mode.", dest);
}

extern fn view_request_resize(view: WlcView, edge: ResizeEdge, location: Point) {
    println!("view_request_resize: size {:?}, to {}, start interactive mode.",
             edge, location);
}

extern fn view_request_render_pre(view: WlcView) {
    //println!("view_request_render_pre");
}

extern fn view_request_render_post(view: WlcView) {
    //println!("view_request_render_post");
}

extern fn keyboard_key(view: WlcView, time: u32, mods: KeyboardModifiers,
                       key: u32, state: KeyState) -> bool {
    use std::process::{Command};
    println!("keyboard_key: time {}, mods {:?}, key {:?}, state {:?}",
             time, mods, key, state);
    if state == KeyState::Pressed { return false; }
    println!("Preparing to open the terminal...");
    rustwlc::exec("weston-terminal".to_string(), vec!["weston-terminal".to_string()]);
    // We are definitely able to open programs, they can definitely launch in the host X11 server.
    //rustwlc::exec("emacs".to_string(), vec!["emacs".to_string()]);
    //let output = std::process::Command::new("weston-terminal").output()
    //.unwrap_or_else(|e| { println!("Could not unwrap output!"); panic!("aaaa") });
    let mut child = Command::new("/bin/weston-terminal").spawn()
        .unwrap_or_else(|e| { println!("Error spawning child: {}", e); panic!("1") });

    //let ecode = child.wait().unwrap_or_else(|e| println!("Error unwrapping child"));
    //println!("Output: {}", String::from_utf8(output.stdout).unwrap_or("nope".to_string()));

    false
}

extern fn pointer_button(view: WlcView, button: libc::c_uint, mods: KeyboardModifiers,
                  key: u32, state: ButtonState, point: Point) -> bool {
    println!("pointer_button: key {}, point {}", key, point);

    if state == ButtonState::Pressed {
        view.focus();
    }
    false
}

extern fn pointer_scroll(view: WlcView, button: u32, mods: KeyboardModifiers,
                  axis: ScrollAxis, heights: [u64; 2]) -> bool {
    println!("pointer_scroll");
    false
}

extern fn pointer_motion(view: WlcView, time: u32, point: Point) {
    //println!("Pointer moved {} to {}", time, point);
    // TODO wlc_pointer_set_position
    pointer::set_position(point);
}

extern fn touch_touch(view: WlcView, time: libc::c_uint, mods: KeyboardModifiers,
               touch: TouchType, key: i32, point: Point) -> bool {
    false
}

extern fn compositor_ready() {
    println!("Preparing compositor!");
}

extern fn input_created(device: LibinputDevice) -> bool {
    println!("input_created");
    false
}

extern fn input_destroyed(device: LibinputDevice) {
    println!("input_destroyed");
}
<|endoftext|>