<commit_before>//! Container types

use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::{Geometry, Point, Size, ResizeEdge};

/// A handle to either a view or output
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Handle {
    View(WlcView),
    Output(WlcOutput)
}

/// Types of containers
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContainerType {
    /// Root container, only one exists
    Root,
    /// WlcOutput/Monitor
    Output,
    /// A workspace
    Workspace,
    /// A Container, houses views and other containers
    Container,
    /// A view (window)
    View
}

impl ContainerType {
    /// Whether this container can be used as the parent of another
    pub fn can_have_child(self, other: ContainerType) -> bool {
        use self::ContainerType::*;
        match self {
            Root => other == Output,
            Output => other == Workspace,
            Workspace => other == Container,
            Container => other == Container || other == View,
            View => false
        }
    }

    /// Whether this container can have a parent of type other
    #[allow(dead_code)]
    pub fn can_have_parent(self, other: ContainerType) -> bool {
        other.can_have_child(self)
    }
}

/// Layout mode for a container
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(dead_code)]
pub enum Layout {
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

/// Represents an item in the container tree.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Container {
    /// Root node of the container
    Root,
    /// Output
    Output {
        /// Handle to the wlc
        handle: WlcOutput,
        /// Whether the output is focused
        focused: bool
    },
    /// Workspace
    Workspace {
        /// Name of the workspace
        name: String,
        /// Whether the workspace is focused
        ///
        /// Multiple workspaces can be focused
        focused: bool,
        /// The size of the workspace on the screen.
        /// Might be different if there is e.g a bar present
        size: Size,
    },
    /// Container
    Container {
        /// How the container is layed out
        layout: Layout,
        /// If the container is focused
        focused: bool,
        /// If the container is floating
        floating: bool,
        /// The geometry of the container, relative to the parent container
        geometry: Geometry,
    },
    /// View or window
    View {
        /// The wlc handle to the view
        handle: WlcView,
        /// Whether this view is focused
        focused: bool,
        /// Whether this view is floating
        floating: bool,
    }
}

impl Container {
    /// Creates a new output container with the given output
    pub fn new_output(handle: WlcOutput) -> Container {
        Container::Output {
            handle: handle,
            focused: false
        }
    }

    /// Creates a new workspace container with the given name and size.
    /// Usually the size is the same as the output it resides on,
    /// unless there is a bar or something.
    pub fn new_workspace(name: String, size: Size) -> Container {
        Container::Workspace {
            name: name, focused: false, size: size
        }
    }

    /// Creates a new container
    pub fn new_container(geometry: Geometry) -> Container {
        Container::Container {
            layout: Layout::Horizontal,
            focused: false,
            floating: false,
            geometry: geometry
        }
    }

    /// Creates a new view container with the given handle
    pub fn new_view(handle: WlcView) -> Container {
        Container::View {
            handle: handle,
            focused: false,
            floating: false
        }
    }

    /// Sets the visibility of this container
    pub fn set_visibility(&mut self, visibility: bool) {
        let mask = if visibility { 1 } else { 0 };
        if let Some(handle) = self.get_handle() {
            match handle {
                Handle::View(view) => {
                    view.set_mask(mask)
                },
                _ => {},
            }
        }
    }

    /// Gets the type of this container
    pub fn get_type(&self) -> ContainerType {
        match *self {
            Container::Root => ContainerType::Root,
            Container::Output { .. } => ContainerType::Output,
            Container::Workspace { .. } => ContainerType::Workspace,
            Container::Container { .. } => ContainerType::Container,
            Container::View { .. } => ContainerType::View
        }
    }

    /// Gets the view handle of the view container, if this is a view container
    pub fn get_handle(&self) -> Option<Handle> {
        match *self {
            Container::View { ref handle, ..} => Some(Handle::View(handle.clone())),
            Container::Output { ref handle, .. } => Some(Handle::Output(handle.clone())),
            _ => None
        }
    }

    /// Gets the name of the workspace, if this container is a workspace.
    pub fn get_name(&self) -> Option<&str> {
        match *self {
            Container::Workspace { ref name, ..} => Some(name),
            _ => None
        }
    }

    /// Determines if the container is focused or not
    #[allow(dead_code)]
    pub fn is_focused(&self) -> bool {
        match *self {
            Container::Output { ref focused, .. } => focused.clone(),
            Container::Workspace { ref focused, .. } => focused.clone(),
            Container::View { ref focused, .. } => focused.clone(),
            _ => false
        }
    }

    /// Gets the geometry of the container, if the container has one.
    /// Root: Returns None
    /// Workspace/Output: Size is the size of the screen, origin is just 0,0
    /// Container/View: Size is the size of the container,
    /// origin is the coordinates relative to the parent container.
    pub fn get_geometry(&self) -> Option<Geometry> {
        match *self {
            Container::Root { .. } => None,
            Container::Output { ref handle, .. } => Some(Geometry {
                origin: Point { x: 0, y: 0 },
                size: handle.get_resolution().clone(),
            }),
            Container::Workspace { ref size, .. } => Some(Geometry {
                origin: Point { x: 0, y: 0},
                size: size.clone()
            }),
            Container::Container { ref geometry, .. } => Some(geometry.clone()),
            Container::View { ref handle, ..} => {
                match handle.get_geometry() {
                    Some(geometry) => Some(geometry.clone()),
                    _ => None
                }
            },
        }
    }

    /// Sets the geometry of the container, if it supports that operation.
    /// Only Views, Containers, and Workspaces support this operation,
    /// all others will return an Err with an appropriate error message.
    ///
    /// If setting a workspace, only the size of the geometry is set.
    #[allow(dead_code)]
    pub fn set_geometry(&mut self, new_geometry: Geometry) -> Result<(), String> {
        match *self {
            Container::Workspace { ref mut size, .. } => *size = new_geometry.size,
            Container::Container { ref mut geometry, .. } => *geometry = new_geometry,
            Container::View { ref handle, .. } =>
                handle.set_geometry(ResizeEdge::empty(), &new_geometry),
            _ => { return Err(format!("Could not set geometry on {:?}", self))}
        };
        return Ok(())
    }

    pub fn set_layout(&mut self, new_layout: Layout) -> Result<(), String>{
        match *self {
            Container::Container { ref mut layout, .. } => *layout = new_layout,
            ref other => return Err(
                format!("Can only set the layout of a container, not {:?}",
                        other))
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn can_have_child() {
        let root = ContainerType::Root;
        let output = ContainerType::Output;
        let workspace = ContainerType::Workspace;
        let container = ContainerType::Container;
        let view = ContainerType::View;

        assert!(root.can_have_child(output),         "Root      > output");
        assert!(output.can_have_child(workspace),    "Output    > workspace");
        assert!(workspace.can_have_child(container), "Workspace > container");
        assert!(container.can_have_child(container), "Container > container");
        assert!(container.can_have_child(view),      "Container > view");

        assert!(!root.can_have_child(root),      "! Root > root");
        assert!(!root.can_have_child(workspace), "! Root > workspace");
        assert!(!root.can_have_child(container), "! Root > container");
        assert!(!root.can_have_child(view),      "! Root > view");

        assert!(!output.can_have_child(root),      "! Output > root");
        assert!(!output.can_have_child(output),    "! Output > output");
        assert!(!output.can_have_child(container), "! Output > container");
        assert!(!output.can_have_child(view),      "! Output > view");

        assert!(!workspace.can_have_child(root),      "! Workspace > root");
        assert!(!workspace.can_have_child(output),    "! Workspace > output");
        assert!(!workspace.can_have_child(workspace), "! Workspace > worksp");
        assert!(!workspace.can_have_child(view),      "! Workspace > view");

        assert!(!container.can_have_child(root),      "! Container > root");
        assert!(!container.can_have_child(workspace), "! Container > worksp");
        assert!(!container.can_have_child(output),    "! Container > contanr");

        assert!(!view.can_have_child(root),      "! View > root");
        assert!(!view.can_have_child(output),    "! View > output");
        assert!(!view.can_have_child(workspace), "! View > workspace");
        assert!(!view.can_have_child(container), "! View > container");
        assert!(!view.can_have_child(view),      "! View > view");
    }

    #[test]
    /// Tests set and get geometry
    fn geometry_test() {
        use rustwlc::*;
        let test_geometry1 = Geometry {
            origin: Point { x: 800, y: 600 },
            size: Size { w: 500, h: 500}
        };
        let test_geometry2 = Geometry {
            origin: Point { x: 1024, y: 2048},
            size: Size { w: 500, h: 700}
        };
        let mut root = Container::Root;
        assert!(root.get_geometry().is_none());
        assert!(root.set_geometry(test_geometry1.clone()).is_err());

        let mut output = Container::new_output(WlcView::root().as_output());
        // NOTE Segfaults, because tries to get the geometry from dummy Wlc output
        //assert!(output.get_geometry().is_none());
        assert!(output.set_geometry(test_geometry1.clone()).is_err());

        let mut workspace = Container::new_workspace("1".to_string(),
                                                     Size { w: 500, h: 500 });
        assert_eq!(workspace.get_geometry(), Some(Geometry {
            size: Size { w: 500, h: 500},
            origin: Point { x: 0, y: 0}
        }));
        workspace.set_geometry(test_geometry1.clone())
            .expect("Can't set geometry on workspace");
        // Workspace only grabs the Size, so point will be 0 0.
        let workspace_geometry = Geometry {
            size: test_geometry1.size.clone(),
            origin: Point { x: 0, y: 0}
        };
        assert_eq!(workspace.get_geometry(), Some(workspace_geometry.clone()));

        let mut container = Container::new_container(test_geometry1.clone());
        assert_eq!(container.get_geometry(), Some(test_geometry1.clone()));
        container.set_geometry(test_geometry2.clone())
            .expect("Could not set geometry on container");
        assert_eq!(container.get_geometry(), Some(test_geometry2.clone()));

        // NOTE Can't test view, because that will just segfault as well
        //let mut view = Container::new_view(WlcView::root());
    }
}
<commit_msg>Container layout switching test<commit_after>//! Container types

use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::{Geometry, Point, Size, ResizeEdge};

/// A handle to either a view or output
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Handle {
    View(WlcView),
    Output(WlcOutput)
}

/// Types of containers
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContainerType {
    /// Root container, only one exists
    Root,
    /// WlcOutput/Monitor
    Output,
    /// A workspace
    Workspace,
    /// A Container, houses views and other containers
    Container,
    /// A view (window)
    View
}

impl ContainerType {
    /// Whether this container can be used as the parent of another
    pub fn can_have_child(self, other: ContainerType) -> bool {
        use self::ContainerType::*;
        match self {
            Root => other == Output,
            Output => other == Workspace,
            Workspace => other == Container,
            Container => other == Container || other == View,
            View => false
        }
    }

    /// Whether this container can have a parent of type other
    #[allow(dead_code)]
    pub fn can_have_parent(self, other: ContainerType) -> bool {
        other.can_have_child(self)
    }
}

/// Layout mode for a container
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(dead_code)]
pub enum Layout {
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

/// Represents an item in the container tree.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Container {
    /// Root node of the container
    Root,
    /// Output
    Output {
        /// Handle to the wlc
        handle: WlcOutput,
        /// Whether the output is focused
        focused: bool
    },
    /// Workspace
    Workspace {
        /// Name of the workspace
        name: String,
        /// Whether the workspace is focused
        ///
        /// Multiple workspaces can be focused
        focused: bool,
        /// The size of the workspace on the screen.
        /// Might be different if there is e.g a bar present
        size: Size,
    },
    /// Container
    Container {
        /// How the container is layed out
        layout: Layout,
        /// If the container is focused
        focused: bool,
        /// If the container is floating
        floating: bool,
        /// The geometry of the container, relative to the parent container
        geometry: Geometry,
    },
    /// View or window
    View {
        /// The wlc handle to the view
        handle: WlcView,
        /// Whether this view is focused
        focused: bool,
        /// Whether this view is floating
        floating: bool,
    }
}

impl Container {
    /// Creates a new output container with the given output
    pub fn new_output(handle: WlcOutput) -> Container {
        Container::Output {
            handle: handle,
            focused: false
        }
    }

    /// Creates a new workspace container with the given name and size.
    /// Usually the size is the same as the output it resides on,
    /// unless there is a bar or something.
    pub fn new_workspace(name: String, size: Size) -> Container {
        Container::Workspace {
            name: name, focused: false, size: size
        }
    }

    /// Creates a new container
    pub fn new_container(geometry: Geometry) -> Container {
        Container::Container {
            layout: Layout::Horizontal,
            focused: false,
            floating: false,
            geometry: geometry
        }
    }

    /// Creates a new view container with the given handle
    pub fn new_view(handle: WlcView) -> Container {
        Container::View {
            handle: handle,
            focused: false,
            floating: false
        }
    }

    /// Sets the visibility of this container
    pub fn set_visibility(&mut self, visibility: bool) {
        let mask = if visibility { 1 } else { 0 };
        if let Some(handle) = self.get_handle() {
            match handle {
                Handle::View(view) => {
                    view.set_mask(mask)
                },
                _ => {},
            }
        }
    }

    /// Gets the type of this container
    pub fn get_type(&self) -> ContainerType {
        match *self {
            Container::Root => ContainerType::Root,
            Container::Output { .. } => ContainerType::Output,
            Container::Workspace { .. } => ContainerType::Workspace,
            Container::Container { .. } => ContainerType::Container,
            Container::View { .. } => ContainerType::View
        }
    }

    /// Gets the view handle of the view container, if this is a view container
    pub fn get_handle(&self) -> Option<Handle> {
        match *self {
            Container::View { ref handle, ..} => Some(Handle::View(handle.clone())),
            Container::Output { ref handle, .. } => Some(Handle::Output(handle.clone())),
            _ => None
        }
    }

    /// Gets the name of the workspace, if this container is a workspace.
    pub fn get_name(&self) -> Option<&str> {
        match *self {
            Container::Workspace { ref name, ..} => Some(name),
            _ => None
        }
    }

    /// Determines if the container is focused or not
    #[allow(dead_code)]
    pub fn is_focused(&self) -> bool {
        match *self {
            Container::Output { ref focused, .. } => focused.clone(),
            Container::Workspace { ref focused, .. } => focused.clone(),
            Container::View { ref focused, .. } => focused.clone(),
            _ => false
        }
    }

    /// Gets the geometry of the container, if the container has one.
    /// Root: Returns None
    /// Workspace/Output: Size is the size of the screen, origin is just 0,0
    /// Container/View: Size is the size of the container,
    /// origin is the coordinates relative to the parent container.
    pub fn get_geometry(&self) -> Option<Geometry> {
        match *self {
            Container::Root { .. } => None,
            Container::Output { ref handle, .. } => Some(Geometry {
                origin: Point { x: 0, y: 0 },
                size: handle.get_resolution().clone(),
            }),
            Container::Workspace { ref size, .. } => Some(Geometry {
                origin: Point { x: 0, y: 0},
                size: size.clone()
            }),
            Container::Container { ref geometry, .. } => Some(geometry.clone()),
            Container::View { ref handle, ..} => {
                match handle.get_geometry() {
                    Some(geometry) => Some(geometry.clone()),
                    _ => None
                }
            },
        }
    }

    /// Sets the geometry of the container, if it supports that operation.
    /// Only Views, Containers, and Workspaces support this operation,
    /// all others will return an Err with an appropriate error message.
    ///
    /// If setting a workspace, only the size of the geometry is set.
    #[allow(dead_code)]
    pub fn set_geometry(&mut self, new_geometry: Geometry) -> Result<(), String> {
        match *self {
            Container::Workspace { ref mut size, .. } => *size = new_geometry.size,
            Container::Container { ref mut geometry, .. } => *geometry = new_geometry,
            Container::View { ref handle, .. } =>
                handle.set_geometry(ResizeEdge::empty(), &new_geometry),
            _ => { return Err(format!("Could not set geometry on {:?}", self))}
        };
        return Ok(())
    }

    pub fn set_layout(&mut self, new_layout: Layout) -> Result<(), String>{
        match *self {
            Container::Container { ref mut layout, .. } => *layout = new_layout,
            ref other => return Err(
                format!("Can only set the layout of a container, not {:?}",
                        other))
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn can_have_child() {
        let root = ContainerType::Root;
        let output = ContainerType::Output;
        let workspace = ContainerType::Workspace;
        let container = ContainerType::Container;
        let view = ContainerType::View;

        assert!(root.can_have_child(output),         "Root      > output");
        assert!(output.can_have_child(workspace),    "Output    > workspace");
        assert!(workspace.can_have_child(container), "Workspace > container");
        assert!(container.can_have_child(container), "Container > container");
        assert!(container.can_have_child(view),      "Container > view");

        assert!(!root.can_have_child(root),      "! Root > root");
        assert!(!root.can_have_child(workspace), "! Root > workspace");
        assert!(!root.can_have_child(container), "! Root > container");
        assert!(!root.can_have_child(view),      "! Root > view");

        assert!(!output.can_have_child(root),      "! Output > root");
        assert!(!output.can_have_child(output),    "! Output > output");
        assert!(!output.can_have_child(container), "! Output > container");
        assert!(!output.can_have_child(view),      "! Output > view");

        assert!(!workspace.can_have_child(root),      "! Workspace > root");
        assert!(!workspace.can_have_child(output),    "! Workspace > output");
        assert!(!workspace.can_have_child(workspace), "! Workspace > worksp");
        assert!(!workspace.can_have_child(view),      "! Workspace > view");

        assert!(!container.can_have_child(root),      "! Container > root");
        assert!(!container.can_have_child(workspace), "! Container > worksp");
        assert!(!container.can_have_child(output),    "! Container > contanr");

        assert!(!view.can_have_child(root),      "! View > root");
        assert!(!view.can_have_child(output),    "! View > output");
        assert!(!view.can_have_child(workspace), "! View > workspace");
        assert!(!view.can_have_child(container), "! View > container");
        assert!(!view.can_have_child(view),      "! View > view");
    }

    #[test]
    /// Tests set and get geometry
    fn geometry_test() {
        use rustwlc::*;
        let test_geometry1 = Geometry {
            origin: Point { x: 800, y: 600 },
            size: Size { w: 500, h: 500}
        };
        let test_geometry2 = Geometry {
            origin: Point { x: 1024, y: 2048},
            size: Size { w: 500, h: 700}
        };
        let mut root = Container::Root;
        assert!(root.get_geometry().is_none());
        assert!(root.set_geometry(test_geometry1.clone()).is_err());

        let mut output = Container::new_output(WlcView::root().as_output());
        // NOTE Segfaults, because tries to get the geometry from dummy Wlc output
        //assert!(output.get_geometry().is_none());
        assert!(output.set_geometry(test_geometry1.clone()).is_err());

        let mut workspace = Container::new_workspace("1".to_string(),
                                                     Size { w: 500, h: 500 });
        assert_eq!(workspace.get_geometry(), Some(Geometry {
            size: Size { w: 500, h: 500},
            origin: Point { x: 0, y: 0}
        }));
        workspace.set_geometry(test_geometry1.clone())
            .expect("Can't set geometry on workspace");
        // Workspace only grabs the Size, so point will be 0 0.
        let workspace_geometry = Geometry {
            size: test_geometry1.size.clone(),
            origin: Point { x: 0, y: 0}
        };
        assert_eq!(workspace.get_geometry(), Some(workspace_geometry.clone()));

        let mut container = Container::new_container(test_geometry1.clone());
        assert_eq!(container.get_geometry(), Some(test_geometry1.clone()));
        container.set_geometry(test_geometry2.clone())
            .expect("Could not set geometry on container");
        assert_eq!(container.get_geometry(), Some(test_geometry2.clone()));

        // NOTE Can't test view, because that will just segfault as well
        //let mut view = Container::new_view(WlcView::root());
    }

    #[test]
    fn layout_change_test() {
        use rustwlc::*;
        let root = Container::Root;
        let output = Container::new_output(WlcView::root().as_output());
        let workspace = Container::new_workspace("1".to_string(),
                                                     Size { w: 500, h: 500 });
        let mut container = Container::new_container(Geometry {
            origin: Point { x: 0, y: 0},
            size: Size { w: 0, h:0}
        });
        let view = Container::new_view(WlcView::root());

        /* Container first, the only thing we can set the layout on */
        let layout = match container {
            Container::Container { ref layout, .. } => layout.clone(),
            _ => panic!()
        };
        assert_eq!(layout, Layout::Horizontal);
        let layouts = [Layout::Vertical, Layout::Horizontal,
                       Layout::Tabbed, Layout::Stacked];
        for new_layout in &layouts {
            container.set_layout(*new_layout).ok();
            let layout = match container {
                Container::Container { ref layout, .. } => layout.clone(),
                _ => panic!()
            };
            assert_eq!(layout, *new_layout);
        }

        for new_layout in &layouts {
            for container in &mut [root.clone(), output.clone(),
                                   workspace.clone(), view.clone()] {
                let result = container.set_layout(*new_layout);
                assert!(result.is_err());
            }
        }

    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! An implementation of SipHash.

#![allow(deprecated)]

use marker::PhantomData;
use ptr;

/// An implementation of SipHash 1-3.
///
/// See: https://131002.net/siphash/
#[unstable(feature = "sip_hash_13", issue = "34767")]
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
#[derive(Debug, Clone, Default)]
pub struct SipHasher13 {
    hasher: Hasher<Sip13Rounds>,
}

/// An implementation of SipHash 2-4.
///
/// See: https://131002.net/siphash/
#[unstable(feature = "sip_hash_13", issue = "34767")]
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
#[derive(Debug, Clone, Default)]
pub struct SipHasher24 {
    hasher: Hasher<Sip24Rounds>,
}

/// An implementation of SipHash 2-4.
///
/// See: https://131002.net/siphash/
///
/// This is currently the default hashing function used by standard library
/// (eg. `collections::HashMap` uses it by default).
///
/// SipHash is a general-purpose hashing function: it runs at a good
/// speed (competitive with Spooky and City) and permits strong _keyed_
/// hashing. This lets you key your hashtables from a strong RNG, such as
/// [`rand::os::OsRng`](https://doc.rust-lang.org/rand/rand/os/struct.OsRng.html).
///
/// Although the SipHash algorithm is considered to be generally strong,
/// it is not intended for cryptographic purposes. As such, all
/// cryptographic uses of this implementation are _strongly discouraged_.
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
#[derive(Debug, Clone, Default)]
pub struct SipHasher(SipHasher24);

#[derive(Debug)]
struct Hasher<S: Sip> {
    k0: u64,
    k1: u64,
    length: usize, // how many bytes we've processed
    state: State, // hash State
    tail: u64, // unprocessed bytes le
    ntail: usize, // how many bytes in tail are valid
    _marker: PhantomData<S>,
}

#[derive(Debug, Clone, Copy)]
struct State {
    // v0, v2 and v1, v3 show up in pairs in the algorithm,
    // and simd implementations of SipHash will use vectors
    // of v02 and v13. By placing them in this order in the struct,
    // the compiler can pick up on just a few simd optimizations by itself.
    v0: u64,
    v2: u64,
    v1: u64,
    v3: u64,
}

// sadly, these macro definitions can't appear later,
// because they're needed in the following defs;
// this design could be improved.

macro_rules! u8to64_le {
    ($buf:expr, $i:expr) =>
    ($buf[0+$i] as u64 |
     ($buf[1+$i] as u64) << 8 |
     ($buf[2+$i] as u64) << 16 |
     ($buf[3+$i] as u64) << 24 |
     ($buf[4+$i] as u64) << 32 |
     ($buf[5+$i] as u64) << 40 |
     ($buf[6+$i] as u64) << 48 |
     ($buf[7+$i] as u64) << 56);
    ($buf:expr, $i:expr, $len:expr) =>
    ({
        let mut t = 0;
        let mut out = 0;
        while t < $len {
            out |= ($buf[t+$i] as u64) << t*8;
            t += 1;
        }
        out
    });
}

/// Load a full u64 word from a byte stream, in LE order. Use
/// `copy_nonoverlapping` to let the compiler generate the most efficient way
/// to load u64 from a possibly unaligned address.
///
/// Unsafe because: unchecked indexing at i..i+8
#[inline]
unsafe fn load_u64_le(buf: &[u8], i: usize) -> u64 {
    debug_assert!(i + 8 <= buf.len());
    let mut data = 0u64;
    ptr::copy_nonoverlapping(buf.get_unchecked(i), &mut data as *mut _ as *mut u8, 8);
    data.to_le()
}

macro_rules! rotl {
    ($x:expr, $b:expr) =>
    (($x << $b) | ($x >> (64_i32.wrapping_sub($b))))
}

macro_rules! compress {
    ($state:expr) => ({
        compress!($state.v0, $state.v1, $state.v2, $state.v3)
    });
    ($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
    ({
        $v0 = $v0.wrapping_add($v1); $v1 = rotl!($v1, 13); $v1 ^= $v0;
        $v0 = rotl!($v0, 32);
        $v2 = $v2.wrapping_add($v3); $v3 = rotl!($v3, 16); $v3 ^= $v2;
        $v0 = $v0.wrapping_add($v3); $v3 = rotl!($v3, 21); $v3 ^= $v0;
        $v2 = $v2.wrapping_add($v1); $v1 = rotl!($v1, 17); $v1 ^= $v2;
        $v2 = rotl!($v2, 32);
    });
}

impl SipHasher {
    /// Creates a new `SipHasher` with the two initial keys set to 0.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
    pub fn new() -> SipHasher {
        SipHasher::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher` that is keyed off the provided keys.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
        SipHasher(SipHasher24::new_with_keys(key0, key1))
    }
}

impl SipHasher13 {
    /// Creates a new `SipHasher13` with the two initial keys set to 0.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "34767")]
    #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
    pub fn new() -> SipHasher13 {
        SipHasher13::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher13` that is keyed off the provided keys.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "34767")]
    #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 {
        SipHasher13 {
            hasher: Hasher::new_with_keys(key0, key1)
        }
    }
}

impl SipHasher24 {
    /// Creates a new `SipHasher24` with the two initial keys set to 0.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "34767")]
    #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
    pub fn new() -> SipHasher24 {
        SipHasher24::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher24` that is keyed off the provided keys.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "34767")]
    #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher24 {
        SipHasher24 {
            hasher: Hasher::new_with_keys(key0, key1)
        }
    }
}

impl<S: Sip> Hasher<S> {
    #[inline]
    fn new_with_keys(key0: u64, key1: u64) -> Hasher<S> {
        let mut state = Hasher {
            k0: key0,
            k1: key1,
            length: 0,
            state: State {
                v0: 0,
                v1: 0,
                v2: 0,
                v3: 0,
            },
            tail: 0,
            ntail: 0,
            _marker: PhantomData,
        };
        state.reset();
        state
    }

    #[inline]
    fn reset(&mut self) {
        self.length = 0;
        self.state.v0 = self.k0 ^ 0x736f6d6570736575;
        self.state.v1 = self.k1 ^ 0x646f72616e646f6d;
        self.state.v2 = self.k0 ^ 0x6c7967656e657261;
        self.state.v3 = self.k1 ^ 0x7465646279746573;
        self.ntail = 0;
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl super::Hasher for SipHasher {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        self.0.write(msg)
    }

    #[inline]
    fn finish(&self) -> u64 {
        self.0.finish()
    }
}

#[unstable(feature = "sip_hash_13", issue = "34767")]
impl super::Hasher for SipHasher13 {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        self.hasher.write(msg)
    }

    #[inline]
    fn finish(&self) -> u64 {
        self.hasher.finish()
    }
}

#[unstable(feature = "sip_hash_13", issue = "34767")]
impl super::Hasher for SipHasher24 {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        self.hasher.write(msg)
    }

    #[inline]
    fn finish(&self) -> u64 {
        self.hasher.finish()
    }
}

impl<S: Sip> super::Hasher for Hasher<S> {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        let length = msg.len();
        self.length += length;

        let mut needed = 0;

        if self.ntail != 0 {
            needed = 8 - self.ntail;
            if length < needed {
                self.tail |= u8to64_le!(msg, 0, length) << 8 * self.ntail;
                self.ntail += length;
                return
            }

            let m = self.tail | u8to64_le!(msg, 0, needed) << 8 * self.ntail;

            self.state.v3 ^= m;
            S::c_rounds(&mut self.state);
            self.state.v0 ^= m;

            self.ntail = 0;
        }

        // Buffered tail is now flushed, process new input.
        let len = length - needed;
        let left = len & 0x7;

        let mut i = needed;
        while i < len - left {
            let mi = unsafe { load_u64_le(msg, i) };

            self.state.v3 ^= mi;
            S::c_rounds(&mut self.state);
            self.state.v0 ^= mi;

            i += 8;
        }

        self.tail = u8to64_le!(msg, i, left);
        self.ntail = left;
    }

    #[inline]
    fn finish(&self) -> u64 {
        let mut state = self.state;

        let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;

        state.v3 ^= b;
        S::c_rounds(&mut state);
        state.v0 ^= b;

        state.v2 ^= 0xff;
        S::d_rounds(&mut state);

        state.v0 ^ state.v1 ^ state.v2 ^ state.v3
    }
}

impl<S: Sip> Clone for Hasher<S> {
    #[inline]
    fn clone(&self) -> Hasher<S> {
        Hasher {
            k0: self.k0,
            k1: self.k1,
            length: self.length,
            state: self.state,
            tail: self.tail,
            ntail: self.ntail,
            _marker: self._marker,
        }
    }
}

impl<S: Sip> Default for Hasher<S> {
    /// Creates a `Hasher<S>` with the two initial keys set to 0.
    #[inline]
    fn default() -> Hasher<S> {
        Hasher::new_with_keys(0, 0)
    }
}

#[doc(hidden)]
trait Sip {
    fn c_rounds(&mut State);
    fn d_rounds(&mut State);
}

#[derive(Debug, Clone, Default)]
struct Sip13Rounds;

impl Sip for Sip13Rounds {
    #[inline]
    fn c_rounds(state: &mut State) {
        compress!(state);
    }

    #[inline]
    fn d_rounds(state: &mut State) {
        compress!(state);
        compress!(state);
        compress!(state);
    }
}

#[derive(Debug, Clone, Default)]
struct Sip24Rounds;

impl Sip for Sip24Rounds {
    #[inline]
    fn c_rounds(state: &mut State) {
        compress!(state);
        compress!(state);
    }

    #[inline]
    fn d_rounds(state: &mut State) {
        compress!(state);
        compress!(state);
        compress!(state);
        compress!(state);
    }
}
<commit_msg>update sip.rs for new intrinsics and defaults<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! An implementation of SipHash.

#![allow(deprecated)]

use marker::PhantomData;
use ptr;

/// An implementation of SipHash 1-3.
///
/// This is currently the default hashing function used by standard library
/// (eg. `collections::HashMap` uses it by default).
///
/// See: https://131002.net/siphash/
#[unstable(feature = "sip_hash_13", issue = "34767")]
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
#[derive(Debug, Clone, Default)]
pub struct SipHasher13 {
    hasher: Hasher<Sip13Rounds>,
}

/// An implementation of SipHash 2-4.
///
/// See: https://131002.net/siphash/
#[unstable(feature = "sip_hash_13", issue = "34767")]
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
#[derive(Debug, Clone, Default)]
pub struct SipHasher24 {
    hasher: Hasher<Sip24Rounds>,
}

/// An implementation of SipHash 2-4.
///
/// See: https://131002.net/siphash/
///
/// SipHash is a general-purpose hashing function: it runs at a good
/// speed (competitive with Spooky and City) and permits strong _keyed_
/// hashing. This lets you key your hashtables from a strong RNG, such as
/// [`rand::os::OsRng`](https://doc.rust-lang.org/rand/rand/os/struct.OsRng.html).
///
/// Although the SipHash algorithm is considered to be generally strong,
/// it is not intended for cryptographic purposes. As such, all
/// cryptographic uses of this implementation are _strongly discouraged_.
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
#[derive(Debug, Clone, Default)]
pub struct SipHasher(SipHasher24);

#[derive(Debug)]
struct Hasher<S: Sip> {
    k0: u64,
    k1: u64,
    length: usize, // how many bytes we've processed
    state: State, // hash State
    tail: u64, // unprocessed bytes le
    ntail: usize, // how many bytes in tail are valid
    _marker: PhantomData<S>,
}

#[derive(Debug, Clone, Copy)]
struct State {
    // v0, v2 and v1, v3 show up in pairs in the algorithm,
    // and simd implementations of SipHash will use vectors
    // of v02 and v13. By placing them in this order in the struct,
    // the compiler can pick up on just a few simd optimizations by itself.
    v0: u64,
    v2: u64,
    v1: u64,
    v3: u64,
}

// sadly, these macro definitions can't appear later,
// because they're needed in the following defs;
// this design could be improved.

macro_rules! u8to64_le {
    ($buf:expr, $i:expr) =>
    ($buf[0+$i] as u64 |
     ($buf[1+$i] as u64) << 8 |
     ($buf[2+$i] as u64) << 16 |
     ($buf[3+$i] as u64) << 24 |
     ($buf[4+$i] as u64) << 32 |
     ($buf[5+$i] as u64) << 40 |
     ($buf[6+$i] as u64) << 48 |
     ($buf[7+$i] as u64) << 56);
    ($buf:expr, $i:expr, $len:expr) =>
    ({
        let mut t = 0;
        let mut out = 0;
        while t < $len {
            out |= ($buf[t+$i] as u64) << t*8;
            t += 1;
        }
        out
    });
}

/// Load a full u64 word from a byte stream, in LE order. Use
/// `copy_nonoverlapping` to let the compiler generate the most efficient way
/// to load u64 from a possibly unaligned address.
///
/// Unsafe because: unchecked indexing at i..i+8
#[inline]
unsafe fn load_u64_le(buf: &[u8], i: usize) -> u64 {
    debug_assert!(i + 8 <= buf.len());
    let mut data = 0u64;
    ptr::copy_nonoverlapping(buf.get_unchecked(i), &mut data as *mut _ as *mut u8, 8);
    data.to_le()
}

macro_rules! compress {
    ($state:expr) => ({
        compress!($state.v0, $state.v1, $state.v2, $state.v3)
    });
    ($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
    ({
        $v0 = $v0.wrapping_add($v1); $v1 = $v1.rotate_left(13); $v1 ^= $v0;
        $v0 = $v0.rotate_left(32);
        $v2 = $v2.wrapping_add($v3); $v3 = $v3.rotate_left(16); $v3 ^= $v2;
        $v0 = $v0.wrapping_add($v3); $v3 = $v3.rotate_left(21); $v3 ^= $v0;
        $v2 = $v2.wrapping_add($v1); $v1 = $v1.rotate_left(17); $v1 ^= $v2;
        $v2 = $v2.rotate_left(32);
    });
}

impl SipHasher {
    /// Creates a new `SipHasher` with the two initial keys set to 0.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
    pub fn new() -> SipHasher {
        SipHasher::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher` that is keyed off the provided keys.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
        SipHasher(SipHasher24::new_with_keys(key0, key1))
    }
}

impl SipHasher13 {
    /// Creates a new `SipHasher13` with the two initial keys set to 0.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "34767")]
    #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
    pub fn new() -> SipHasher13 {
        SipHasher13::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher13` that is keyed off the provided keys.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "34767")]
    #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 {
        SipHasher13 {
            hasher: Hasher::new_with_keys(key0, key1)
        }
    }
}

impl SipHasher24 {
    /// Creates a new `SipHasher24` with the two initial keys set to 0.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "34767")]
    #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
    pub fn new() -> SipHasher24 {
        SipHasher24::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher24` that is keyed off the provided keys.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "34767")]
    #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher24 {
        SipHasher24 {
            hasher: Hasher::new_with_keys(key0, key1)
        }
    }
}

impl<S: Sip> Hasher<S> {
    #[inline]
    fn new_with_keys(key0: u64, key1: u64) -> Hasher<S> {
        let mut state = Hasher {
            k0: key0,
            k1: key1,
            length: 0,
            state: State {
                v0: 0,
                v1: 0,
                v2: 0,
                v3: 0,
            },
            tail: 0,
            ntail: 0,
            _marker: PhantomData,
        };
        state.reset();
        state
    }

    #[inline]
    fn reset(&mut self) {
        self.length = 0;
        self.state.v0 = self.k0 ^ 0x736f6d6570736575;
        self.state.v1 = self.k1 ^ 0x646f72616e646f6d;
        self.state.v2 = self.k0 ^ 0x6c7967656e657261;
        self.state.v3 = self.k1 ^ 0x7465646279746573;
        self.ntail = 0;
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl super::Hasher for SipHasher {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        self.0.write(msg)
    }

    #[inline]
    fn finish(&self) -> u64 {
        self.0.finish()
    }
}

#[unstable(feature = "sip_hash_13", issue = "34767")]
impl super::Hasher for SipHasher13 {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        self.hasher.write(msg)
    }

    #[inline]
    fn finish(&self) -> u64 {
        self.hasher.finish()
    }
}

#[unstable(feature = "sip_hash_13", issue = "34767")]
impl super::Hasher for SipHasher24 {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        self.hasher.write(msg)
    }

    #[inline]
    fn finish(&self) -> u64 {
        self.hasher.finish()
    }
}

impl<S: Sip> super::Hasher for Hasher<S> {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        let length = msg.len();
        self.length += length;

        let mut needed = 0;

        if self.ntail != 0 {
            needed = 8 - self.ntail;
            if length < needed {
                self.tail |= u8to64_le!(msg, 0, length) << 8 * self.ntail;
                self.ntail += length;
                return
            }

            let m = self.tail | u8to64_le!(msg, 0, needed) << 8 * self.ntail;

            self.state.v3 ^= m;
            S::c_rounds(&mut self.state);
            self.state.v0 ^= m;

            self.ntail = 0;
        }

        // Buffered tail is now flushed, process new input.
        let len = length - needed;
        let left = len & 0x7;

        let mut i = needed;
        while i < len - left {
            let mi = unsafe { load_u64_le(msg, i) };

            self.state.v3 ^= mi;
            S::c_rounds(&mut self.state);
            self.state.v0 ^= mi;

            i += 8;
        }

        self.tail = u8to64_le!(msg, i, left);
        self.ntail = left;
    }

    #[inline]
    fn finish(&self) -> u64 {
        let mut state = self.state;

        let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;

        state.v3 ^= b;
        S::c_rounds(&mut state);
        state.v0 ^= b;

        state.v2 ^= 0xff;
        S::d_rounds(&mut state);

        state.v0 ^ state.v1 ^ state.v2 ^ state.v3
    }
}

impl<S: Sip> Clone for Hasher<S> {
    #[inline]
    fn clone(&self) -> Hasher<S> {
        Hasher {
            k0: self.k0,
            k1: self.k1,
            length: self.length,
            state: self.state,
            tail: self.tail,
            ntail: self.ntail,
            _marker: self._marker,
        }
    }
}

impl<S: Sip> Default for Hasher<S> {
    /// Creates a `Hasher<S>` with the two initial keys set to 0.
    #[inline]
    fn default() -> Hasher<S> {
        Hasher::new_with_keys(0, 0)
    }
}

#[doc(hidden)]
trait Sip {
    fn c_rounds(&mut State);
    fn d_rounds(&mut State);
}

#[derive(Debug, Clone, Default)]
struct Sip13Rounds;

impl Sip for Sip13Rounds {
    #[inline]
    fn c_rounds(state: &mut State) {
        compress!(state);
    }

    #[inline]
    fn d_rounds(state: &mut State) {
        compress!(state);
        compress!(state);
        compress!(state);
    }
}

#[derive(Debug, Clone, Default)]
struct Sip24Rounds;

impl Sip for Sip24Rounds {
    #[inline]
    fn c_rounds(state: &mut State) {
        compress!(state);
        compress!(state);
    }

    #[inline]
    fn d_rounds(state: &mut State) {
        compress!(state);
        compress!(state);
        compress!(state);
        compress!(state);
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "native_lib")]
use std::ffi::{CString, OsString};
use std::io;
use std::ops::Deref;
#[cfg(feature = "native_lib")]
use std::os::unix::ffi::OsStringExt;
use std::sync::Arc;

use EventQueue;
use Proxy;

#[cfg(feature = "native_lib")]
use wayland_sys::client::*;

/// Enum representing the possible reasons why connecting to the wayland server failed
#[derive(Debug)]
pub enum ConnectError {
    /// The library was compiled with the `dlopen` feature, and the `libwayland-client.so`
    /// library could not be found at runtime
    NoWaylandLib,
    /// Any needed library was found, but the listening socket of the server could not be
    /// found.
    ///
    /// Most of the time, this means that the program was not started from a wayland session.
    NoCompositorListening,
    /// The provided socket name is invalid
    InvalidName,
}

pub(crate) struct DisplayInner {
    proxy: Proxy<::protocol::wl_display::WlDisplay>,
    display: *mut wl_display
}

impl DisplayInner {
    #[cfg(feature = "native_lib")]
    pub(crate) fn ptr(&self) -> *mut wl_display {
        self.display
    }
}

impl Drop for DisplayInner {
    fn drop(&mut self) {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!();
        }
        #[cfg(feature = "native_lib")]
        {
            unsafe {
                if self.proxy.c_ptr() == (self.display as *mut _) {
                    // disconnect only if we are owning this display
                    ffi_dispatch!(
                        WAYLAND_CLIENT_HANDLE,
                        wl_display_disconnect,
                        self.proxy.c_ptr() as *mut wl_display
                    );
                }
            }
        }
    }
}

/// A connection to a wayland server
///
/// This object both represent the connection to the server, and as such
/// must be kept alive as long as you are connected, and contains the
/// primary `WlDisplay` wayland object, from which you can create all
/// your need objects. The inner `Proxy<WlDisplay>` can be accessed via
/// `Deref`.
pub struct Display {
    inner: Arc<DisplayInner>,
}

impl Display {
    #[cfg(feature = "native_lib")]
    unsafe fn make_display(ptr: *mut wl_display) -> Result<(Display, EventQueue), ConnectError> {
        if ptr.is_null() {
            return Err(ConnectError::NoCompositorListening);
        }

        let display = Display {
            inner: Arc::new(DisplayInner {
                proxy: Proxy::from_display(ptr),
                display: ptr
            }),
        };

        let evq = EventQueue::new(display.inner.clone(), None);

        Ok((display, evq))
    }

    #[cfg(feature = "native_lib")]
    /// Create a Display and Event Queue from an external display
    ///
    /// This allows you to interface with an already-existing wayland connection,
    /// for example provided by a GUI toolkit.
    ///
    /// To avoid interferences with the owner of the connection, wayland-client will
    /// create a new event queue and register a wrapper of the `wl_display` to this queue,
    /// then provide them to you. You can then use them as if they came from a direct
    /// wayland connection.
    pub unsafe fn from_external_display(display_ptr: *mut wl_display) -> (Display, EventQueue) {
        let evq_ptr = ffi_dispatch!(
            WAYLAND_CLIENT_HANDLE,
            wl_display_create_queue,
            display_ptr
        );

        let wrapper_ptr = ffi_dispatch!(
            WAYLAND_CLIENT_HANDLE,
            wl_proxy_create_wrapper,
            display_ptr as *mut _
        );
        ffi_dispatch!(
            WAYLAND_CLIENT_HANDLE,
            wl_proxy_set_queue,
            wrapper_ptr,
            evq_ptr
        );

        let display = Display {
            inner: Arc::new(DisplayInner {
                proxy: Proxy::from_display_wrapper(wrapper_ptr),
                display: display_ptr
            }),
        };

        let evq = EventQueue::new(display.inner.clone(), Some(evq_ptr));
        (display, evq)
    }

    /// Attempt to connect to a wayland server using the contents of the environment variables
    ///
    /// If the `WAYLAND_DISPLAY` variable is set, it will try to connect to the socket it points
    /// to. Otherwise, it will default to `wayland-0`.
    ///
    /// On success, you are given the `Display` object as well as the main `EventQueue` hosting
    /// the `WlDisplay` wayland object.
    ///
    /// This requires the `XDG_RUNTIME_DIR` variable to be properly set.
    pub fn connect_to_env() -> Result<(Display, EventQueue), ConnectError> {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!()
        }
        #[cfg(feature = "native_lib")]
        {
            if !::wayland_sys::client::is_lib_available() {
                return Err(ConnectError::NoWaylandLib);
            }

            unsafe {
                let display_ptr =
                    ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_connect, ::std::ptr::null());

                Display::make_display(display_ptr)
            }
        }
    }

    /// Attempt to connect to a wayland server socket with given name
    ///
    /// On success, you are given the `Display` object as well as the main `EventQueue` hosting
    /// the `WlDisplay` wayland object.
    ///
    /// This requires the `XDG_RUNTIME_DIR` variable to be properly set.
    pub fn connect_to_name<S: Into<OsString>>(name: S) -> Result<(Display, EventQueue), ConnectError> {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!()
        }
        #[cfg(feature = "native_lib")]
        {
            if !::wayland_sys::client::is_lib_available() {
                return Err(ConnectError::NoWaylandLib);
            }

            let name = CString::new(name.into().into_vec()).map_err(|_| ConnectError::InvalidName)?;

            unsafe {
                let display_ptr = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_connect, name.as_ptr());

                Display::make_display(display_ptr)
            }
        }
    }

    /// Non-blocking write to the server
    ///
    /// Outgoing messages to the server are buffered by the library for efficiency. This method
    /// flushes the internal buffer to the server socket.
    ///
    /// Will write as many pending requests as possible to the server socket. Never blocks: if not all
    /// requests coul be written, will return an io error `WouldBlock`.
    ///
    /// On success returns the number of written requests.
    pub fn flush(&self) -> io::Result<i32> {
        let ret = unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_flush, self.inner.ptr()) };
        if ret >= 0 {
            Ok(ret)
        } else {
            Err(io::Error::last_os_error())
        }
    }

    /// Create a new event queue associated with this wayland connection
    pub fn create_event_queue(&self) -> EventQueue {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!()
        }
        #[cfg(feature = "native_lib")]
        unsafe {
            let ptr = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_create_queue, self.inner.ptr());

            EventQueue::new(self.inner.clone(), Some(ptr))
        }
    }
}

impl Deref for Display {
    type Target = Proxy<::protocol::wl_display::WlDisplay>;
    fn deref(&self) -> &Proxy<::protocol::wl_display::WlDisplay> {
        &self.inner.proxy
    }
}
<commit_msg>cargo fmt<commit_after>#[cfg(feature = "native_lib")]
use std::ffi::{CString, OsString};
use std::io;
use std::ops::Deref;
#[cfg(feature = "native_lib")]
use std::os::unix::ffi::OsStringExt;
use std::sync::Arc;

use EventQueue;
use Proxy;

#[cfg(feature = "native_lib")]
use wayland_sys::client::*;

/// Enum representing the possible reasons why connecting to the wayland server failed
#[derive(Debug)]
pub enum ConnectError {
    /// The library was compiled with the `dlopen` feature, and the `libwayland-client.so`
    /// library could not be found at runtime
    NoWaylandLib,
    /// Any needed library was found, but the listening socket of the server could not be
    /// found.
    ///
    /// Most of the time, this means that the program was not started from a wayland session.
    NoCompositorListening,
    /// The provided socket name is invalid
    InvalidName,
}

pub(crate) struct DisplayInner {
    proxy: Proxy<::protocol::wl_display::WlDisplay>,
    display: *mut wl_display,
}

impl DisplayInner {
    #[cfg(feature = "native_lib")]
    pub(crate) fn ptr(&self) -> *mut wl_display {
        self.display
    }
}

impl Drop for DisplayInner {
    fn drop(&mut self) {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!();
        }
        #[cfg(feature = "native_lib")]
        {
            unsafe {
                if self.proxy.c_ptr() == (self.display as *mut _) {
                    // disconnect only if we are owning this display
                    ffi_dispatch!(
                        WAYLAND_CLIENT_HANDLE,
                        wl_display_disconnect,
                        self.proxy.c_ptr() as *mut wl_display
                    );
                }
            }
        }
    }
}

/// A connection to a wayland server
///
/// This object both represent the connection to the server, and as such
/// must be kept alive as long as you are connected, and contains the
/// primary `WlDisplay` wayland object, from which you can create all
/// your need objects. The inner `Proxy<WlDisplay>` can be accessed via
/// `Deref`.
pub struct Display {
    inner: Arc<DisplayInner>,
}

impl Display {
    #[cfg(feature = "native_lib")]
    unsafe fn make_display(ptr: *mut wl_display) -> Result<(Display, EventQueue), ConnectError> {
        if ptr.is_null() {
            return Err(ConnectError::NoCompositorListening);
        }

        let display = Display {
            inner: Arc::new(DisplayInner {
                proxy: Proxy::from_display(ptr),
                display: ptr,
            }),
        };

        let evq = EventQueue::new(display.inner.clone(), None);

        Ok((display, evq))
    }

    #[cfg(feature = "native_lib")]
    /// Create a Display and Event Queue from an external display
    ///
    /// This allows you to interface with an already-existing wayland connection,
    /// for example provided by a GUI toolkit.
    ///
    /// To avoid interferences with the owner of the connection, wayland-client will
    /// create a new event queue and register a wrapper of the `wl_display` to this queue,
    /// then provide them to you. You can then use them as if they came from a direct
    /// wayland connection.
    pub unsafe fn from_external_display(display_ptr: *mut wl_display) -> (Display, EventQueue) {
        let evq_ptr = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_create_queue, display_ptr);

        let wrapper_ptr = ffi_dispatch!(
            WAYLAND_CLIENT_HANDLE,
            wl_proxy_create_wrapper,
            display_ptr as *mut _
        );
        ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_set_queue, wrapper_ptr, evq_ptr);

        let display = Display {
            inner: Arc::new(DisplayInner {
                proxy: Proxy::from_display_wrapper(wrapper_ptr),
                display: display_ptr,
            }),
        };

        let evq = EventQueue::new(display.inner.clone(), Some(evq_ptr));
        (display, evq)
    }

    /// Attempt to connect to a wayland server using the contents of the environment variables
    ///
    /// If the `WAYLAND_DISPLAY` variable is set, it will try to connect to the socket it points
    /// to. Otherwise, it will default to `wayland-0`.
    ///
    /// On success, you are given the `Display` object as well as the main `EventQueue` hosting
    /// the `WlDisplay` wayland object.
    ///
    /// This requires the `XDG_RUNTIME_DIR` variable to be properly set.
    pub fn connect_to_env() -> Result<(Display, EventQueue), ConnectError> {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!()
        }
        #[cfg(feature = "native_lib")]
        {
            if !::wayland_sys::client::is_lib_available() {
                return Err(ConnectError::NoWaylandLib);
            }

            unsafe {
                let display_ptr =
                    ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_connect, ::std::ptr::null());

                Display::make_display(display_ptr)
            }
        }
    }

    /// Attempt to connect to a wayland server socket with given name
    ///
    /// On success, you are given the `Display` object as well as the main `EventQueue` hosting
    /// the `WlDisplay` wayland object.
    ///
    /// This requires the `XDG_RUNTIME_DIR` variable to be properly set.
    pub fn connect_to_name<S: Into<OsString>>(name: S) -> Result<(Display, EventQueue), ConnectError> {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!()
        }
        #[cfg(feature = "native_lib")]
        {
            if !::wayland_sys::client::is_lib_available() {
                return Err(ConnectError::NoWaylandLib);
            }

            let name = CString::new(name.into().into_vec()).map_err(|_| ConnectError::InvalidName)?;

            unsafe {
                let display_ptr = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_connect, name.as_ptr());

                Display::make_display(display_ptr)
            }
        }
    }

    /// Non-blocking write to the server
    ///
    /// Outgoing messages to the server are buffered by the library for efficiency. This method
    /// flushes the internal buffer to the server socket.
    ///
    /// Will write as many pending requests as possible to the server socket. Never blocks: if not all
    /// requests coul be written, will return an io error `WouldBlock`.
    ///
    /// On success returns the number of written requests.
    pub fn flush(&self) -> io::Result<i32> {
        let ret = unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_flush, self.inner.ptr()) };
        if ret >= 0 {
            Ok(ret)
        } else {
            Err(io::Error::last_os_error())
        }
    }

    /// Create a new event queue associated with this wayland connection
    pub fn create_event_queue(&self) -> EventQueue {
        #[cfg(not(feature = "native_lib"))]
        {
            unimplemented!()
        }
        #[cfg(feature = "native_lib")]
        unsafe {
            let ptr = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_create_queue, self.inner.ptr());

            EventQueue::new(self.inner.clone(), Some(ptr))
        }
    }
}

impl Deref for Display {
    type Target = Proxy<::protocol::wl_display::WlDisplay>;
    fn deref(&self) -> &Proxy<::protocol::wl_display::WlDisplay> {
        &self.inner.proxy
    }
}
<|endoftext|>


<commit_before>//! Rust code which is called from lua in the init file
#![deny(dead_code)]

use rustc_serialize::json::ToJson;
use uuid::Uuid;
use super::{send, LuaQuery};
use rlua;
use rlua::prelude::LuaResult;
use ::convert::json::json_to_lua;
use ::awesome;

use registry::{self};
use commands;
use keys::{self, KeyPress, KeyEvent};

use super::thread::{update_registry_value};

/// We've `include!`d the code which initializes from the Lua side.

/// Register all the Rust functions for the lua libraries
pub fn register_libraries(lua: &rlua::Lua) -> LuaResult<()> {
    trace!("Registering Rust libraries...");
    {
        let rust_table = lua.create_table()?;
        rust_table.set("init_workspaces",
                       lua.create_function(init_workspaces)?)?;
        rust_table.set("register_lua_key",
                       lua.create_function(register_lua_key)?)?;
        rust_table.set("unregister_lua_key",
                       lua.create_function(unregister_lua_key)?)?;
        rust_table.set("register_command_key",
                       lua.create_function(register_command_key)?)?;
        rust_table.set("register_mouse_modifier",
                       lua.create_function(register_mouse_modifier)?)?;
        rust_table.set("keypress_index",
                       lua.create_function(keypress_index)?)?;
        rust_table.set("ipc_run",
                       lua.create_function(ipc_run)?)?;
        rust_table.set("ipc_get",
                       lua.create_function(ipc_get)?)?;
        rust_table.set("ipc_set",
                       lua.create_function(ipc_set)?)?;
        let globals = lua.globals();
        globals.set("__rust", rust_table)?;
        globals.set("type", lua.create_function(type_override)?)?;
    }
    trace!("Executing Lua init...");
    let init_code = include_str!("../../lib/lua/lua_init.lua");
    let awesome_init_code = include_str!("../../lib/lua/awesome_init.lua");
    let util_code = include_str!("../../lib/lua/utils.lua");
    lua.exec::<()>(util_code, Some("utils.lua"))?;
    lua.exec::<()>(awesome_init_code, Some("awesome_init.lua"))?;
    awesome::init(&lua)
        .expect("Could not initialize awesome compatibilty modules");
    lua.exec::<()>(init_code, Some("lua_init.lua"))?;
    trace!("Lua register_libraries complete");
    Ok(())
}

/// This function behaves just like Lua's built-in type() function, but also recognises classes and
/// returns special names for them.
#[allow(unused)]
fn type_override(_lua: &rlua::Lua, arg: rlua::Value) -> Result<String, rlua::Error> {
    use rlua::Value;

    // Lua's type() returns the result of lua_typename(), but rlua does not make that available to
    // us, so write our own.
    match arg {
        Value::Nil => Ok("nil".to_owned()),
        Value::Boolean(_) => Ok("boolean".to_owned()),
        Value::LightUserData(_) => Ok("userdata".to_owned()),
        Value::UserData(_) => Ok("userdata".to_owned()),
        Value::Integer(_) => Ok("number".to_owned()),
        Value::Number(_) => Ok("number".to_owned()),
        Value::String(_) => Ok("string".to_owned()),
        Value::Function(_) => Ok("function".to_owned()),
        Value::Thread(_) => Ok("thread".to_owned()),
        Value::Error(e) => Err(e),
        Value::Table(t) => {
            // Handle our own objects specially: Return the metatable's .__class.name if it exists,
            // else return "table".
            match t.get_metatable() {
                None => Ok("table".to_owned()),
                Some(t) => t.raw_get("__class")
                    .and_then(|t: rlua::Table| t.raw_get("name"))
                    .or(Ok("table".to_owned()))
            }
        }
    }
}

/// Run a command
fn ipc_run(_lua: &rlua::Lua, command: String) -> Result<(), rlua::Error> {
    use rlua::Error;
    commands::get(&command).map(|com| com())
        .ok_or(Error::RuntimeError("Command does not exist".into()))
}

/// IPC 'get' handler
fn ipc_get<'lua>(lua: &'lua rlua::Lua, (category, key): (String, String))
                 -> Result<rlua::Value<'lua>, rlua::Error> {
    use rlua::Error;
    let lock = registry::clients_read();
    let client = lock.client(Uuid::nil()).unwrap();
    let handle = registry::ReadHandle::new(&client);
    handle.read(category)
        .map_err(|_|
                 Error::RuntimeError("Could not locate that category".into()))
        .and_then(|category| category.get(&key)
                  .ok_or(Error::RuntimeError(
                      "Could not locate that key in the category".into()))
                  .and_then(|value| json_to_lua(lua, value.to_json())))
}

/// ipc 'set' handler
fn ipc_set(_lua: &rlua::Lua, category: String) -> Result<(), rlua::Error> {
    update_registry_value(category);
    send(LuaQuery::UpdateRegistryFromCache)
        .expect("Could not send message to Lua thread to update registry");
    Ok(())
}

fn init_workspaces(_: &rlua::Lua, _: rlua::Value) -> Result<(), rlua::Error> {
    warn!("Attempting to call `init_workspaces`, this is not implemented");
    Ok(())
}

/// Registers a modifier to be used in conjunction with mouse commands
fn register_mouse_modifier(_lua: &rlua::Lua, modifier: String)
                           -> Result<(), rlua::Error> {
    use rlua::Error;
    let modifier = keys::keymod_from_names(&[modifier.as_str()])
        .map_err(|txt| Error::RuntimeError(txt))?;
    keys::register_mouse_modifier(modifier);
    Ok(())
}

/// Registers a command keybinding.
fn register_command_key(_lua: &rlua::Lua,
                        (mods, command, _repeat, passthrough):
                        (String, String, bool, bool))
                        -> Result<(), rlua::Error> {
    use rlua::Error;
    if let Ok(press) = keypress_from_string(&mods) {
        commands::get(&command)
            .ok_or(Error::RuntimeError(
                format!("Command {} for keybinding {} not found", command, press)))
            .map(|command|
                keys::register(press, KeyEvent::Command(command), passthrough))?;
        Ok(())
    }
    else {
        Err(Error::RuntimeError(format!("Invalid keypress {}, {}", mods, command)))
    }
}

/// Rust half of registering a Lua key: store the KeyPress in the keys table
/// and send Lua back the index for __key_map.
fn register_lua_key(_lua: &rlua::Lua, (mods, _repeat, passthrough):
                          (String, bool, bool))
                          -> Result<String, rlua::Error> {
    use rlua::Error;
    keypress_from_string(&mods)
        .map(|press| {
            keys::register(press.clone(), KeyEvent::Lua, passthrough);
            press.get_lua_index_string()
        }).map_err(|_| Error::RuntimeError(format!("Invalid keys '{}'", mods)))
}

/// Rust half of unregistering a Lua key. This pops it from the key table, if
/// it exists.
///
/// If a key wasn't registered, a proper error string is raised.
fn unregister_lua_key(_lua: &rlua::Lua, mods: String)
                            -> Result<String, rlua::Error> {
    use rlua::Error;
    keypress_from_string(&mods).and_then(|press| {
        if let Some(action) = keys::unregister(&press) {
            trace!("Removed keybinding \"{}\" for {:?}", press, action);
            Ok(press.get_lua_index_string())
        } else {
            let error_str = format!("Could not remove keybinding \"{}\": \
                                     Not registered!",
                                    press);
            warn!("Could not remove keybinding \"{}\": Not registered!",
                  press);
            Err(error_str)
        }
    }).map_err(|err|
               Error::RuntimeError(format!("Invalid keys '{}': {:#?}", mods, err)))
}

/// Parses a keypress from a string
fn keypress_from_string(mods: &str) -> Result<KeyPress, String> {
    let parts: Vec<&str> = mods.split(',').collect();
    if let Some((ref key, mods)) = parts.split_last() {
        KeyPress::from_key_names(mods, &key)
    }
    else {
        Err(format!("Invalid key '{}'", mods))
    }
}

fn keypress_index(_lua: &rlua::Lua, press: String) -> Result<String, rlua::Error> {
    use rlua::Error;
    keypress_from_string(&press)
        .map(|key| key.get_lua_index_string())
        .map_err(|err_msg| Error::RuntimeError(err_msg))
}
<commit_msg>Fix the type() override for the new object layout<commit_after>//! Rust code which is called from lua in the init file
#![deny(dead_code)]

use rustc_serialize::json::ToJson;
use uuid::Uuid;
use super::{send, LuaQuery};
use rlua;
use rlua::prelude::LuaResult;
use ::convert::json::json_to_lua;
use ::awesome;

use registry::{self};
use commands;
use keys::{self, KeyPress, KeyEvent};

use super::thread::{update_registry_value};

/// We've `include!`d the code which initializes from the Lua side.

/// Register all the Rust functions for the lua libraries
pub fn register_libraries(lua: &rlua::Lua) -> LuaResult<()> {
    trace!("Registering Rust libraries...");
    {
        let rust_table = lua.create_table()?;
        rust_table.set("init_workspaces",
                       lua.create_function(init_workspaces)?)?;
        rust_table.set("register_lua_key",
                       lua.create_function(register_lua_key)?)?;
        rust_table.set("unregister_lua_key",
                       lua.create_function(unregister_lua_key)?)?;
        rust_table.set("register_command_key",
                       lua.create_function(register_command_key)?)?;
        rust_table.set("register_mouse_modifier",
                       lua.create_function(register_mouse_modifier)?)?;
        rust_table.set("keypress_index",
                       lua.create_function(keypress_index)?)?;
        rust_table.set("ipc_run",
                       lua.create_function(ipc_run)?)?;
        rust_table.set("ipc_get",
                       lua.create_function(ipc_get)?)?;
        rust_table.set("ipc_set",
                       lua.create_function(ipc_set)?)?;
        let globals = lua.globals();
        globals.set("__rust", rust_table)?;
        globals.set("type", lua.create_function(type_override)?)?;
    }
    trace!("Executing Lua init...");
    let init_code = include_str!("../../lib/lua/lua_init.lua");
    let awesome_init_code = include_str!("../../lib/lua/awesome_init.lua");
    let util_code = include_str!("../../lib/lua/utils.lua");
    lua.exec::<()>(util_code, Some("utils.lua"))?;
    lua.exec::<()>(awesome_init_code, Some("awesome_init.lua"))?;
    awesome::init(&lua)
        .expect("Could not initialize awesome compatibilty modules");
    lua.exec::<()>(init_code, Some("lua_init.lua"))?;
    trace!("Lua register_libraries complete");
    Ok(())
}

/// This function behaves just like Lua's built-in type() function, but also recognises classes and
/// returns special names for them.
#[allow(unused)]
fn type_override(_lua: &rlua::Lua, arg: rlua::Value) -> Result<String, rlua::Error> {
    use rlua::Value;

    // Lua's type() returns the result of lua_typename(), but rlua does not make that available to
    // us, so write our own.
    match arg {
        Value::Nil => Ok("nil".to_owned()),
        Value::Boolean(_) => Ok("boolean".to_owned()),
        Value::LightUserData(_) => Ok("userdata".to_owned()),
        Value::Integer(_) => Ok("number".to_owned()),
        Value::Number(_) => Ok("number".to_owned()),
        Value::String(_) => Ok("string".to_owned()),
        Value::Function(_) => Ok("function".to_owned()),
        Value::Thread(_) => Ok("thread".to_owned()),
        Value::Table(_) => Ok("table".to_owned()),
        Value::Error(e) => Err(e),
        Value::UserData(o) => {
            // Handle our own objects specially: Get the object's class from its user value's
            // metatable's __class entry. Then get the class name from the class's user value's
            // metatable's name entry.
            o.get_user_value::<rlua::Table>().ok()
                .and_then(|table| table.get_metatable())
                .and_then(|meta| meta.raw_get::<_, rlua::AnyUserData>("__class").ok())
                .and_then(|class| class.get_user_value::<rlua::Table>().ok())
                .map(|table| table.raw_get("name"))
                .unwrap_or_else(|| Ok("userdata".to_owned()))
        }
    }
}

/// Run a command
fn ipc_run(_lua: &rlua::Lua, command: String) -> Result<(), rlua::Error> {
    use rlua::Error;
    commands::get(&command).map(|com| com())
        .ok_or(Error::RuntimeError("Command does not exist".into()))
}

/// IPC 'get' handler
fn ipc_get<'lua>(lua: &'lua rlua::Lua, (category, key): (String, String))
                 -> Result<rlua::Value<'lua>, rlua::Error> {
    use rlua::Error;
    let lock = registry::clients_read();
    let client = lock.client(Uuid::nil()).unwrap();
    let handle = registry::ReadHandle::new(&client);
    handle.read(category)
        .map_err(|_|
                 Error::RuntimeError("Could not locate that category".into()))
        .and_then(|category| category.get(&key)
                  .ok_or(Error::RuntimeError(
                      "Could not locate that key in the category".into()))
                  .and_then(|value| json_to_lua(lua, value.to_json())))
}

/// ipc 'set' handler
fn ipc_set(_lua: &rlua::Lua, category: String) -> Result<(), rlua::Error> {
    update_registry_value(category);
    send(LuaQuery::UpdateRegistryFromCache)
        .expect("Could not send message to Lua thread to update registry");
    Ok(())
}

fn init_workspaces(_: &rlua::Lua, _: rlua::Value) -> Result<(), rlua::Error> {
    warn!("Attempting to call `init_workspaces`, this is not implemented");
    Ok(())
}

/// Registers a modifier to be used in conjunction with mouse commands
fn register_mouse_modifier(_lua: &rlua::Lua, modifier: String)
                           -> Result<(), rlua::Error> {
    use rlua::Error;
    let modifier = keys::keymod_from_names(&[modifier.as_str()])
        .map_err(|txt| Error::RuntimeError(txt))?;
    keys::register_mouse_modifier(modifier);
    Ok(())
}

/// Registers a command keybinding.
fn register_command_key(_lua: &rlua::Lua,
                        (mods, command, _repeat, passthrough):
                        (String, String, bool, bool))
                        -> Result<(), rlua::Error> {
    use rlua::Error;
    if let Ok(press) = keypress_from_string(&mods) {
        commands::get(&command)
            .ok_or(Error::RuntimeError(
                format!("Command {} for keybinding {} not found", command, press)))
            .map(|command|
                keys::register(press, KeyEvent::Command(command), passthrough))?;
        Ok(())
    }
    else {
        Err(Error::RuntimeError(format!("Invalid keypress {}, {}", mods, command)))
    }
}

/// Rust half of registering a Lua key: store the KeyPress in the keys table
/// and send Lua back the index for __key_map.
fn register_lua_key(_lua: &rlua::Lua, (mods, _repeat, passthrough):
                          (String, bool, bool))
                          -> Result<String, rlua::Error> {
    use rlua::Error;
    keypress_from_string(&mods)
        .map(|press| {
            keys::register(press.clone(), KeyEvent::Lua, passthrough);
            press.get_lua_index_string()
        }).map_err(|_| Error::RuntimeError(format!("Invalid keys '{}'", mods)))
}

/// Rust half of unregistering a Lua key. This pops it from the key table, if
/// it exists.
///
/// If a key wasn't registered, a proper error string is raised.
fn unregister_lua_key(_lua: &rlua::Lua, mods: String)
                            -> Result<String, rlua::Error> {
    use rlua::Error;
    keypress_from_string(&mods).and_then(|press| {
        if let Some(action) = keys::unregister(&press) {
            trace!("Removed keybinding \"{}\" for {:?}", press, action);
            Ok(press.get_lua_index_string())
        } else {
            let error_str = format!("Could not remove keybinding \"{}\": \
                                     Not registered!",
                                    press);
            warn!("Could not remove keybinding \"{}\": Not registered!",
                  press);
            Err(error_str)
        }
    }).map_err(|err|
               Error::RuntimeError(format!("Invalid keys '{}': {:#?}", mods, err)))
}

/// Parses a keypress from a string
fn keypress_from_string(mods: &str) -> Result<KeyPress, String> {
    let parts: Vec<&str> = mods.split(',').collect();
    if let Some((ref key, mods)) = parts.split_last() {
        KeyPress::from_key_names(mods, &key)
    }
    else {
        Err(format!("Invalid key '{}'", mods))
    }
}

fn keypress_index(_lua: &rlua::Lua, press: String) -> Result<String, rlua::Error> {
    use rlua::Error;
    keypress_from_string(&press)
        .map(|key| key.get_lua_index_string())
        .map_err(|err_msg| Error::RuntimeError(err_msg))
}
<|endoftext|>


<commit_before>use std::local_data;
use std::hashmap::HashMap;
use std::ptr;
use std;

use ll::*;
use wchar::*;
use instance::Instance;
use resource::*;

pub struct WndClass {
    classname: ~str,
    style: uint,
    icon: Option<Image>,
    icon_small: Option<Image>,
    cursor: Option<Image>,
    background: HBRUSH,
    menu: MenuResource,
    cls_extra: int,
    wnd_extra: int,
}

impl WndClass {
    #[fixed_stack_segment]
    pub fn register(&self, instance: Instance) -> bool {
        do self.menu.with_menu_p |menu_p| {
            do with_utf16_p(self.classname) |clsname_p| {
                let wcex = WNDCLASSEX {
                    cbSize: std::sys::size_of::<WNDCLASSEX>() as UINT,
                    style: self.style as UINT,
                    lpfnWndProc: main_wnd_proc as *c_void,
                    cbClsExtra: self.cls_extra as INT,
                    cbWndExtra: self.wnd_extra as INT,
                    hInstance: instance.instance,
                    hIcon: self.icon.to_handle(),
                    hCursor: self.cursor.to_handle(),
                    hbrBackground: self.background,
                    lpszMenuName: menu_p,
                    lpszClassName: clsname_p,
                    hIconSm: self.icon_small.to_handle(),
                };

                let res = unsafe { RegisterClassExW(&wcex) };
                res != 0
            }
        }
    }
}

pub static WS_BORDER: u32 = 0x800000;
pub static WS_CAPTION: u32 = 0xc00000;
pub static WS_CHILD: u32 = 0x40000000;
pub static WS_CHILDWINDOW: u32 = 0x40000000;
pub static WS_CLIPCHILDREN: u32 = 0x2000000;
pub static WS_CLIPSIBLINGS: u32 = 0x4000000;
pub static WS_DISABLED: u32 = 0x8000000;
pub static WS_DLGFRAME: u32 = 0x400000;
pub static WS_GROUP: u32 = 0x20000;
pub static WS_HSCROLL: u32 = 0x100000;
pub static WS_ICONIC: u32 = 0x20000000;
pub static WS_MAXIMIZE: u32 = 0x1000000;
pub static WS_MAXIMIZEBOX: u32 = 0x10000;
pub static WS_MINIMIZE: u32 = 0x20000000;
pub static WS_MINIMIZEBOX: u32 = 0x20000;
pub static WS_OVERLAPPED: u32 = 0;
pub static WS_OVERLAPPEDWINDOW: u32 = 0xcf0000;
pub static WS_POPUP: u32 = 0x80000000;
pub static WS_POPUPWINDOW: u32 = 0x80880000;
pub static WS_SIZEBOX: u32 = 0x40000;
pub static WS_SYSMENU: u32 = 0x80000;
pub static WS_TABSTOP: u32 = 0x10000;
pub static WS_THICKFRAME: u32 = 0x40000;
pub static WS_TILED: u32 = 0;
pub static WS_TILEDWINDOW: u32 = 0xcf0000;
pub static WS_VISIBLE: u32 = 0x10000000;
pub static WS_VSCROLL: u32 = 0x200000;

pub static ES_AUTOHSCROLL: u32 = 128;
pub static ES_AUTOVSCROLL: u32 = 64;
pub static ES_CENTER: u32 = 1;
pub static ES_LEFT: u32 = 0;
pub static ES_LOWERCASE: u32 = 16;
pub static ES_MULTILINE: u32 = 4;
pub static ES_NOHIDESEL: u32 = 256;
pub static ES_NUMBER: u32 = 0x2000;
pub static ES_OEMCONVERT: u32 = 0x400;
pub static ES_PASSWORD: u32 = 32;
pub static ES_READONLY: u32 = 0x800;
pub static ES_RIGHT: u32 = 2;
pub static ES_UPPERCASE: u32 = 8;
pub static ES_WANTRETURN: u32 = 4096;

pub struct WindowParams {
    window_name: ~str,
    style: u32,
    x: int,
    y: int,
    width: int,
    height: int,
    parent: Window,
    menu: HMENU,
    ex_style: u32,
}

#[deriving(Eq, IterBytes)]
pub struct Window {
    wnd: HWND,
}

impl Clone for Window {
    fn clone(&self) -> Window {
        Window {
            wnd: self.wnd,
        }
    }
}

impl Window {
    pub fn null() -> Window {
        Window {
            wnd: ptr::mut_null(),
        }
    }

    #[fixed_stack_segment]
    pub fn new(
        instance: Instance, proc: Option<~WndProc>, classname: &str, params: &WindowParams
    ) -> Option<Window> {
        match proc {
            Some(proc) => {
                local_data::set(key_init_wnd, proc);
            },
            None => {},
        }

        let wnd = unsafe {
            do with_utf16_p(classname) |clsname_p| {
                do with_utf16_p(params.window_name) |title_p| {
                    let wnd = CreateWindowExW(
                        params.ex_style, clsname_p, title_p, params.style,
                        params.x as c_int, params.y as c_int,
                        params.width as c_int, params.height as c_int,
                        params.parent.wnd, params.menu, instance.instance,
                        ptr::mut_null()
                    );
                    wnd
                }
            }
        };

        if wnd != ptr::mut_null() {
            Some(Window { wnd: wnd })
        } else {
            None
        }
    }

    #[fixed_stack_segment]
    pub fn show(&self, cmd_show: int) -> bool {
        unsafe { ShowWindow(self.wnd, cmd_show as c_int) == 0 }
    }

    #[fixed_stack_segment]
    pub fn update(&self) -> bool {
        unsafe { UpdateWindow(self.wnd) == 0 }
    }

    #[fixed_stack_segment]
    pub fn client_rect(&self) -> Option<RECT> {
        let mut rect = RECT {
            left: 0,
            top: 0,
            right: 0,
            bottom: 0,
        };
        let res = unsafe {
            GetClientRect(self.wnd, &mut rect as *mut RECT)
        } != 0;
        match res {
            true => Some(rect),
            false => None,
        }
    }

    #[fixed_stack_segment]
    pub fn set_window_pos(
        &self, x: int, y: int, width: int, height: int, flags: UINT
    ) -> bool {
        // TODO: hwndInsertAfter
        unsafe {
            SetWindowPos(
                self.wnd, ptr::mut_null(), x as c_int, y as c_int,
                width as c_int, height as c_int, flags
            ) != 0
        }
    }

    #[fixed_stack_segment]
    pub fn set_focus(&self) -> Window {
        unsafe {
            Window {
                wnd: SetFocus(self.wnd)
            }
        }
    }

    #[fixed_stack_segment]
    pub fn send_message(&self, msg: UINT, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
        unsafe {
            SendMessageW(self.wnd, msg, wparam, lparam)
        }
    }
}

pub trait WndProc {
    fn wnd<'a>(&'a self) -> &'a Window;
    fn wnd_mut<'a>(&'a mut self) -> &'a mut Window;
    fn wnd_proc(&self, msg: UINT, w: WPARAM, l: LPARAM) -> LRESULT;
}

pub type WindowMap = HashMap<Window, ~WndProc>;

local_data_key!(pub key_win_map: WindowMap)
local_data_key!(pub key_init_wnd: ~WndProc)

pub fn init_window_map() {
    let win_map: WindowMap = HashMap::new();
    local_data::set(key_win_map, win_map);
}

pub extern "stdcall" fn main_wnd_proc(wnd: HWND, msg: UINT, w: WPARAM, l: LPARAM) -> LRESULT {
    debug2!("main_wnd_proc: wnd {:?} / msg 0x{:x} / w {:?} / l {:?}", wnd, msg as uint, w, l);
    let win = Window { wnd: wnd };
    let null_proc = local_data::pop(key_init_wnd);
    match null_proc {
        Some(nproc) => {
            // hello newcomer.
            let mut nproc = nproc;
            nproc.wnd_mut().wnd = wnd;
            let mut wmap = local_data::pop(key_win_map).unwrap();
            wmap.insert(win, nproc);
            local_data::set(key_win_map, wmap); // XXX?

        },
        None => {}
    };
    do local_data::get(key_win_map) |wmap| {
        let wmap = wmap.unwrap();
        let proc = wmap.find(&win).unwrap();
        proc.wnd_proc(msg, w, l)
    }
}

pub trait DialogUtil {
    fn message_box(&self, msg: &str, title: &str);
}

impl DialogUtil for Window {
    #[fixed_stack_segment]
    fn message_box(&self, msg: &str, title: &str) {
        do with_utf16_p(msg) |msg_p| {
            do with_utf16_p(title) |title_p| {
                unsafe {
                    MessageBoxW(self.wnd, msg_p, title_p, 0u32);
                }
            }
        }
    }
}

pub trait WindowPaint {
    fn begin_paint(&self) -> (HDC, PAINTSTRUCT);
    fn end_paint(&self, ps: &PAINTSTRUCT);
    fn text_out(&self, dc: HDC, x: int, y: int, s: &str) -> bool;
}

impl<T: WndProc> WindowPaint for T {
    #[fixed_stack_segment]
    fn begin_paint(&self) -> (HDC, PAINTSTRUCT) {
        // TODO params
        let rgb_res: [BYTE, ..32] = [0 as BYTE, ..32];
        let ps = PAINTSTRUCT {
            hdc: ptr::mut_null(),
            fErase: 0 as BOOL,
            rcPaint: RECT {
                left: 0 as LONG, top: 0 as LONG,
                right: 0 as LONG, bottom: 0 as LONG
            },
            fRestore: 0 as BOOL,
            fIncUpdate: 0 as BOOL,
            rgbReserved: &rgb_res,
        };

        let dc = unsafe { BeginPaint(self.wnd().wnd, &ps) };
        (dc, ps)
    }

    #[fixed_stack_segment]
    fn end_paint(&self, ps: &PAINTSTRUCT) {
        unsafe { EndPaint(self.wnd().wnd, ps) };
    }

    #[fixed_stack_segment]
    fn text_out(&self, dc: HDC, x: int, y: int, s: &str) -> bool {
        let mut s16 = s.to_utf16();
        s16.push(0u16);
        do s16.as_mut_buf |buf, len| {
            let len = len - 1;
            let ret = unsafe {
                TextOutW(dc, x as c_int, y as c_int, buf, len as i32)
            };
            ret != 0
        }
    }
}

pub trait OnCreate {
    fn on_create(&self, _cs: &CREATESTRUCT) -> bool {
        true
    }
}

pub trait OnDestroy {
    #[fixed_stack_segment]
    fn on_destroy(&self) {
        unsafe {
            PostQuitMessage(0 as c_int);
        }
    }
}

pub trait OnPaint {
    fn on_paint(&self, _dc: HDC) {
    }
}

pub trait OnSize {
    fn on_size(&self, _width: int, _height: int) {
    }
}

pub trait OnFocus {
    fn on_focus(&self, _prev: Window) {
    }
}
<commit_msg>Update for language changes<commit_after>use std::local_data;
use std::hashmap::HashMap;
use std::ptr;
use std;

use ll::*;
use wchar::*;
use instance::Instance;
use resource::*;

pub struct WndClass {
    classname: ~str,
    style: uint,
    icon: Option<Image>,
    icon_small: Option<Image>,
    cursor: Option<Image>,
    background: HBRUSH,
    menu: MenuResource,
    cls_extra: int,
    wnd_extra: int,
}

impl WndClass {
    #[fixed_stack_segment]
    pub fn register(&self, instance: Instance) -> bool {
        do self.menu.with_menu_p |menu_p| {
            do with_utf16_p(self.classname) |clsname_p| {
                let wcex = WNDCLASSEX {
                    cbSize: std::mem::size_of::<WNDCLASSEX>() as UINT,
                    style: self.style as UINT,
                    lpfnWndProc: main_wnd_proc as *c_void,
                    cbClsExtra: self.cls_extra as INT,
                    cbWndExtra: self.wnd_extra as INT,
                    hInstance: instance.instance,
                    hIcon: self.icon.to_handle(),
                    hCursor: self.cursor.to_handle(),
                    hbrBackground: self.background,
                    lpszMenuName: menu_p,
                    lpszClassName: clsname_p,
                    hIconSm: self.icon_small.to_handle(),
                };

                let res = unsafe { RegisterClassExW(&wcex) };
                res != 0
            }
        }
    }
}

pub static WS_BORDER: u32 = 0x800000;
pub static WS_CAPTION: u32 = 0xc00000;
pub static WS_CHILD: u32 = 0x40000000;
pub static WS_CHILDWINDOW: u32 = 0x40000000;
pub static WS_CLIPCHILDREN: u32 = 0x2000000;
pub static WS_CLIPSIBLINGS: u32 = 0x4000000;
pub static WS_DISABLED: u32 = 0x8000000;
pub static WS_DLGFRAME: u32 = 0x400000;
pub static WS_GROUP: u32 = 0x20000;
pub static WS_HSCROLL: u32 = 0x100000;
pub static WS_ICONIC: u32 = 0x20000000;
pub static WS_MAXIMIZE: u32 = 0x1000000;
pub static WS_MAXIMIZEBOX: u32 = 0x10000;
pub static WS_MINIMIZE: u32 = 0x20000000;
pub static WS_MINIMIZEBOX: u32 = 0x20000;
pub static WS_OVERLAPPED: u32 = 0;
pub static WS_OVERLAPPEDWINDOW: u32 = 0xcf0000;
pub static WS_POPUP: u32 = 0x80000000;
pub static WS_POPUPWINDOW: u32 = 0x80880000;
pub static WS_SIZEBOX: u32 = 0x40000;
pub static WS_SYSMENU: u32 = 0x80000;
pub static WS_TABSTOP: u32 = 0x10000;
pub static WS_THICKFRAME: u32 = 0x40000;
pub static WS_TILED: u32 = 0;
pub static WS_TILEDWINDOW: u32 = 0xcf0000;
pub static WS_VISIBLE: u32 = 0x10000000;
pub static WS_VSCROLL: u32 = 0x200000;

pub static ES_AUTOHSCROLL: u32 = 128;
pub static ES_AUTOVSCROLL: u32 = 64;
pub static ES_CENTER: u32 = 1;
pub static ES_LEFT: u32 = 0;
pub static ES_LOWERCASE: u32 = 16;
pub static ES_MULTILINE: u32 = 4;
pub static ES_NOHIDESEL: u32 = 256;
pub static ES_NUMBER: u32 = 0x2000;
pub static ES_OEMCONVERT: u32 = 0x400;
pub static ES_PASSWORD: u32 = 32;
pub static ES_READONLY: u32 = 0x800;
pub static ES_RIGHT: u32 = 2;
pub static ES_UPPERCASE: u32 = 8;
pub static ES_WANTRETURN: u32 = 4096;

pub struct WindowParams {
    window_name: ~str,
    style: u32,
    x: int,
    y: int,
    width: int,
    height: int,
    parent: Window,
    menu: HMENU,
    ex_style: u32,
}

#[deriving(Eq, IterBytes)]
pub struct Window {
    wnd: HWND,
}

impl Clone for Window {
    fn clone(&self) -> Window {
        Window {
            wnd: self.wnd,
        }
    }
}

impl Window {
    pub fn null() -> Window {
        Window {
            wnd: ptr::mut_null(),
        }
    }

    #[fixed_stack_segment]
    pub fn new(
        instance: Instance, proc: Option<~WndProc>, classname: &str, params: &WindowParams
    ) -> Option<Window> {
        match proc {
            Some(proc) => {
                local_data::set(key_init_wnd, proc);
            },
            None => {},
        }

        let wnd = unsafe {
            do with_utf16_p(classname) |clsname_p| {
                do with_utf16_p(params.window_name) |title_p| {
                    let wnd = CreateWindowExW(
                        params.ex_style, clsname_p, title_p, params.style,
                        params.x as c_int, params.y as c_int,
                        params.width as c_int, params.height as c_int,
                        params.parent.wnd, params.menu, instance.instance,
                        ptr::mut_null()
                    );
                    wnd
                }
            }
        };

        if wnd != ptr::mut_null() {
            Some(Window { wnd: wnd })
        } else {
            None
        }
    }

    #[fixed_stack_segment]
    pub fn show(&self, cmd_show: int) -> bool {
        unsafe { ShowWindow(self.wnd, cmd_show as c_int) == 0 }
    }

    #[fixed_stack_segment]
    pub fn update(&self) -> bool {
        unsafe { UpdateWindow(self.wnd) == 0 }
    }

    #[fixed_stack_segment]
    pub fn client_rect(&self) -> Option<RECT> {
        let mut rect = RECT {
            left: 0,
            top: 0,
            right: 0,
            bottom: 0,
        };
        let res = unsafe {
            GetClientRect(self.wnd, &mut rect as *mut RECT)
        } != 0;
        match res {
            true => Some(rect),
            false => None,
        }
    }

    #[fixed_stack_segment]
    pub fn set_window_pos(
        &self, x: int, y: int, width: int, height: int, flags: UINT
    ) -> bool {
        // TODO: hwndInsertAfter
        unsafe {
            SetWindowPos(
                self.wnd, ptr::mut_null(), x as c_int, y as c_int,
                width as c_int, height as c_int, flags
            ) != 0
        }
    }

    #[fixed_stack_segment]
    pub fn set_focus(&self) -> Window {
        unsafe {
            Window {
                wnd: SetFocus(self.wnd)
            }
        }
    }

    #[fixed_stack_segment]
    pub fn send_message(&self, msg: UINT, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
        unsafe {
            SendMessageW(self.wnd, msg, wparam, lparam)
        }
    }
}

pub trait WndProc {
    fn wnd<'a>(&'a self) -> &'a Window;
    fn wnd_mut<'a>(&'a mut self) -> &'a mut Window;
    fn wnd_proc(&self, msg: UINT, w: WPARAM, l: LPARAM) -> LRESULT;
}

pub type WindowMap = HashMap<Window, ~WndProc>;

local_data_key!(pub key_win_map: WindowMap)
local_data_key!(pub key_init_wnd: ~WndProc)

pub fn init_window_map() {
    let win_map: WindowMap = HashMap::new();
    local_data::set(key_win_map, win_map);
}

pub extern "stdcall" fn main_wnd_proc(wnd: HWND, msg: UINT, w: WPARAM, l: LPARAM) -> LRESULT {
    debug2!("main_wnd_proc: wnd {:?} / msg 0x{:x} / w {:?} / l {:?}", wnd, msg as uint, w, l);
    let win = Window { wnd: wnd };
    let null_proc = local_data::pop(key_init_wnd);
    match null_proc {
        Some(nproc) => {
            // hello newcomer.
            let mut nproc = nproc;
            nproc.wnd_mut().wnd = wnd;
            let mut wmap = local_data::pop(key_win_map).unwrap();
            wmap.insert(win, nproc);
            local_data::set(key_win_map, wmap); // XXX?

        },
        None => {}
    };
    do local_data::get(key_win_map) |wmap| {
        let wmap = wmap.unwrap();
        let proc = wmap.find(&win).unwrap();
        proc.wnd_proc(msg, w, l)
    }
}

pub trait DialogUtil {
    fn message_box(&self, msg: &str, title: &str);
}

impl DialogUtil for Window {
    #[fixed_stack_segment]
    fn message_box(&self, msg: &str, title: &str) {
        do with_utf16_p(msg) |msg_p| {
            do with_utf16_p(title) |title_p| {
                unsafe {
                    MessageBoxW(self.wnd, msg_p, title_p, 0u32);
                }
            }
        }
    }
}

pub trait WindowPaint {
    fn begin_paint(&self) -> (HDC, PAINTSTRUCT);
    fn end_paint(&self, ps: &PAINTSTRUCT);
    fn text_out(&self, dc: HDC, x: int, y: int, s: &str) -> bool;
}

impl<T: WndProc> WindowPaint for T {
    #[fixed_stack_segment]
    fn begin_paint(&self) -> (HDC, PAINTSTRUCT) {
        // TODO params
        let rgb_res: [BYTE, ..32] = [0 as BYTE, ..32];
        let ps = PAINTSTRUCT {
            hdc: ptr::mut_null(),
            fErase: 0 as BOOL,
            rcPaint: RECT {
                left: 0 as LONG, top: 0 as LONG,
                right: 0 as LONG, bottom: 0 as LONG
            },
            fRestore: 0 as BOOL,
            fIncUpdate: 0 as BOOL,
            rgbReserved: &rgb_res,
        };

        let dc = unsafe { BeginPaint(self.wnd().wnd, &ps) };
        (dc, ps)
    }

    #[fixed_stack_segment]
    fn end_paint(&self, ps: &PAINTSTRUCT) {
        unsafe { EndPaint(self.wnd().wnd, ps) };
    }

    #[fixed_stack_segment]
    fn text_out(&self, dc: HDC, x: int, y: int, s: &str) -> bool {
        let mut s16 = s.to_utf16();
        s16.push(0u16);
        do s16.as_mut_buf |buf, len| {
            let len = len - 1;
            let ret = unsafe {
                TextOutW(dc, x as c_int, y as c_int, buf, len as i32)
            };
            ret != 0
        }
    }
}

pub trait OnCreate {
    fn on_create(&self, _cs: &CREATESTRUCT) -> bool {
        true
    }
}

pub trait OnDestroy {
    #[fixed_stack_segment]
    fn on_destroy(&self) {
        unsafe {
            PostQuitMessage(0 as c_int);
        }
    }
}

pub trait OnPaint {
    fn on_paint(&self, _dc: HDC) {
    }
}

pub trait OnSize {
    fn on_size(&self, _width: int, _height: int) {
    }
}

pub trait OnFocus {
    fn on_focus(&self, _prev: Window) {
    }
}
<|endoftext|>