<commit_before>// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

mod fdt;
pub mod gic;
pub mod layout;
pub mod regs;

use std::cmp::min;
use std::ffi::CStr;

use memory_model::{GuestAddress, GuestMemory};

#[derive(Debug)]
pub enum Error {
    SetupFDT(fdt::Error),
}

impl From<Error> for super::Error {
    fn from(e: Error) -> super::Error {
        super::Error::Aarch64Setup(e)
    }
}

/// Returns a Vec of the valid memory addresses for aarch64.
/// See [`layout`](layout) module for a drawing of the specific memory model for this platform.
pub fn arch_memory_regions(size: usize) -> Vec<(GuestAddress, usize)> {
    let dram_size = min(size, layout::DRAM_MEM_END);
    vec![(GuestAddress(layout::DRAM_MEM_START), dram_size)]
}

/// Configures the system and should be called once per vm before starting vcpu threads.
/// For aarch64, we only setup the FDT.
///
/// # Arguments
///
/// * `guest_mem` - The memory to be used by the guest.
/// * `cmdline_cstring` - The kernel commandline.
/// * `num_cpus` - Number of virtual CPUs of the system.
pub fn configure_system(
    guest_mem: &GuestMemory,
    cmdline_cstring: &CStr,
    num_cpus: u8,
) -> super::Result<()> {
    fdt::create_fdt(guest_mem, u32::from(num_cpus), cmdline_cstring).map_err(Error::SetupFDT)?;
    Ok(())
}

/// Stub function that needs to be implemented when aarch64 functionality is added.
pub fn get_reserved_mem_addr() -> usize {
    0
}

/// Returns the memory address where the kernel could be loaded.
pub fn get_kernel_start() -> usize {
    layout::DRAM_MEM_START
}

// Auxiliary function to get the address where the device tree blob is loaded.
fn get_fdt_addr(mem: &GuestMemory) -> usize {
    // If the memory allocated is smaller than the size allocated for the FDT,
    // we return the start of the DRAM so that
    // we allow the code to try and load the FDT.

    if let Some(offset) = mem.end_addr().checked_sub(layout::FDT_MAX_SIZE) {
        if mem.address_in_range(offset) {
            return offset.offset();
        }
    }
    layout::DRAM_MEM_START
}

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

    #[test]
    fn test_regions_lt_1024gb() {
        let regions = arch_memory_regions(1usize << 29);
        assert_eq!(1, regions.len());
        assert_eq!(GuestAddress(super::layout::DRAM_MEM_START), regions[0].0);
        assert_eq!(1usize << 29, regions[0].1);
    }

    #[test]
    fn test_regions_gt_1024gb() {
        let regions = arch_memory_regions(1usize << 41);
        assert_eq!(1, regions.len());
        assert_eq!(GuestAddress(super::layout::DRAM_MEM_START), regions[0].0);
        assert_eq!(super::layout::DRAM_MEM_END, regions[0].1);
    }

    #[test]
    fn test_get_fdt_addr() {
        let regions = arch_memory_regions(layout::FDT_MAX_SIZE - 0x1000);
        let mem = GuestMemory::new(&regions).expect("Cannot initialize memory");
        assert_eq!(get_fdt_addr(&mem), layout::DRAM_MEM_START);

        let regions = arch_memory_regions(layout::FDT_MAX_SIZE);
        let mem = GuestMemory::new(&regions).expect("Cannot initialize memory");
        assert_eq!(get_fdt_addr(&mem), layout::DRAM_MEM_START);

        let regions = arch_memory_regions(layout::FDT_MAX_SIZE + 0x1000);
        let mem = GuestMemory::new(&regions).expect("Cannot initialize memory");
        assert_eq!(get_fdt_addr(&mem), 0x1000 + layout::DRAM_MEM_START);
    }
}
<commit_msg>aarch64: return correct address of MMIO devices<commit_after>// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

mod fdt;
pub mod gic;
pub mod layout;
pub mod regs;

use std::cmp::min;
use std::ffi::CStr;

use memory_model::{GuestAddress, GuestMemory};

#[derive(Debug)]
pub enum Error {
    SetupFDT(fdt::Error),
}

impl From<Error> for super::Error {
    fn from(e: Error) -> super::Error {
        super::Error::Aarch64Setup(e)
    }
}

/// Returns a Vec of the valid memory addresses for aarch64.
/// See [`layout`](layout) module for a drawing of the specific memory model for this platform.
pub fn arch_memory_regions(size: usize) -> Vec<(GuestAddress, usize)> {
    let dram_size = min(size, layout::DRAM_MEM_END);
    vec![(GuestAddress(layout::DRAM_MEM_START), dram_size)]
}

/// Configures the system and should be called once per vm before starting vcpu threads.
/// For aarch64, we only setup the FDT.
///
/// # Arguments
///
/// * `guest_mem` - The memory to be used by the guest.
/// * `cmdline_cstring` - The kernel commandline.
/// * `num_cpus` - Number of virtual CPUs of the system.
pub fn configure_system(
    guest_mem: &GuestMemory,
    cmdline_cstring: &CStr,
    num_cpus: u8,
) -> super::Result<()> {
    fdt::create_fdt(guest_mem, u32::from(num_cpus), cmdline_cstring).map_err(Error::SetupFDT)?;
    Ok(())
}

/// Function that returns the address reserved for MMIO devices.
pub fn get_reserved_mem_addr() -> u64 {
    layout::MAPPED_IO_START
}

/// Returns the memory address where the kernel could be loaded.
pub fn get_kernel_start() -> usize {
    layout::DRAM_MEM_START
}

// Auxiliary function to get the address where the device tree blob is loaded.
fn get_fdt_addr(mem: &GuestMemory) -> usize {
    // If the memory allocated is smaller than the size allocated for the FDT,
    // we return the start of the DRAM so that
    // we allow the code to try and load the FDT.

    if let Some(offset) = mem.end_addr().checked_sub(layout::FDT_MAX_SIZE) {
        if mem.address_in_range(offset) {
            return offset.offset();
        }
    }
    layout::DRAM_MEM_START
}

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

    #[test]
    fn test_regions_lt_1024gb() {
        let regions = arch_memory_regions(1usize << 29);
        assert_eq!(1, regions.len());
        assert_eq!(GuestAddress(super::layout::DRAM_MEM_START), regions[0].0);
        assert_eq!(1usize << 29, regions[0].1);
    }

    #[test]
    fn test_regions_gt_1024gb() {
        let regions = arch_memory_regions(1usize << 41);
        assert_eq!(1, regions.len());
        assert_eq!(GuestAddress(super::layout::DRAM_MEM_START), regions[0].0);
        assert_eq!(super::layout::DRAM_MEM_END, regions[0].1);
    }

    #[test]
    fn test_get_fdt_addr() {
        let regions = arch_memory_regions(layout::FDT_MAX_SIZE - 0x1000);
        let mem = GuestMemory::new(&regions).expect("Cannot initialize memory");
        assert_eq!(get_fdt_addr(&mem), layout::DRAM_MEM_START);

        let regions = arch_memory_regions(layout::FDT_MAX_SIZE);
        let mem = GuestMemory::new(&regions).expect("Cannot initialize memory");
        assert_eq!(get_fdt_addr(&mem), layout::DRAM_MEM_START);

        let regions = arch_memory_regions(layout::FDT_MAX_SIZE + 0x1000);
        let mem = GuestMemory::new(&regions).expect("Cannot initialize memory");
        assert_eq!(get_fdt_addr(&mem), 0x1000 + layout::DRAM_MEM_START);
    }
}
<|endoftext|>


<commit_before>//! The functions in this section provide optimized copying to persistent memory
//!
//! The `copy`, `copy_nonoverlapping`, and `write_bytes`, provide the same memory copying as
//! `memmove(3)`, `memcpy(3)`, and `memset(3)`, and ensure that the result has been flushed to persistence before returning.
//!
//! > **Warning:** Using these functions where `is_pmem(1)` returns false may not do anything useful.
//! >              Use the normal libc functions in that case.

use ::std::mem;
use ::std::io;
use ::std::marker::PhantomData;

use ::libc::{c_void, c_int};
use ::libc::size_t;
use ::pmem_sys as ffi;

use pmap::PersistentMap;

/// Persistent memory virtual pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemConstVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemConstVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemConstVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemConstVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(&self) -> PmemConstVirtualPtr<U> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_mut(&self) -> PmemMutVirtualPtr<T> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> PmemConstVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemConstVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemConstVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &PersistentMap) -> PmemConstPtr<T> {
        let new_virt = PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemConstPtr { virt: new_virt, pool: pool.as_ptr() }
    }
}

impl<T> ::std::fmt::Pointer for PmemConstVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:#x}:{:#x}",self.poolid, self.offset)
    }
}

/// Persistent memory virtual mutable pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemMutVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemMutVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemMutVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemMutVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(&self) -> PmemMutVirtualPtr<U> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_const(&self) -> PmemConstVirtualPtr<T> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> ::std::fmt::Pointer for PmemMutVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:#x}:{:#x}",self.poolid, self.offset)
    }
}

impl<T> PmemMutVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemMutVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemMutVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &mut PersistentMap) -> PmemMutPtr<T> {
        let new_virt = PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemMutPtr { virt: new_virt, pool: pool.as_mut_ptr() }
    }
}

/// Direct `*const T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemConstPtr<T: ?Sized> {
    virt: PmemConstVirtualPtr<T>,
    pool: *const T,
}

impl<T: ?Sized> PmemConstPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_mut(&self) -> PmemMutPtr<T> {
        PmemMutPtr { virt: self.virt.as_mut(), pool: self.pool as *mut T }
    }
}

impl<T> PmemConstPtr<T> {
    pub unsafe fn direct(&self) -> *const T {
        if self.is_null() {
            ::std::ptr::null()
        } else {
            self.pool.offset(self.virt.offset as isize) as *const T
        }
    }

    pub fn as_virtual(self) -> PmemConstVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemConstPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(&self) -> PmemConstPtr<U> {
        let new_virt = self.virt.as_type();
        PmemConstPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

impl<T> ::std::fmt::Pointer for PmemConstPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:p} -> {:p}",self.virt, unsafe { self.direct() })
    }
}

/// Direct `*mut T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemMutPtr<T: ?Sized> {
    virt: PmemMutVirtualPtr<T>,
    pool: *mut T,
}

impl<T: ?Sized> PmemMutPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_const(&self) -> PmemConstPtr<T> {
        PmemConstPtr { virt: self.virt.as_const(), pool: self.pool as *const T }
    }
}

impl<T> PmemMutPtr<T> {
    pub unsafe fn direct(&self) -> *mut T {
        if self.is_null() {
            ::std::ptr::null_mut()
        } else {
            self.pool.offset(self.virt.offset as isize) as *mut T
        }
    }

    pub fn as_virtual(self) -> PmemMutVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemMutPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(&self) -> PmemMutPtr<U> {
        let new_virt = self.virt.as_type();
        PmemMutPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

impl<T> ::std::fmt::Pointer for PmemMutPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:p} -> {:p}",self.virt, unsafe { self.direct() })
    }
}

pub fn null<T>() -> PmemConstVirtualPtr<T> {
    PmemConstVirtualPtr::null()
}

pub fn null_mut<T>() -> PmemMutVirtualPtr<T> {
    PmemMutVirtualPtr::null()
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may overlap.
///
/// `copy` is semantically equivalent to C's `memmove` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Care must be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memmove_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may _not_ overlap.
///
/// `copy_nonoverlapping` is semantically equivalent to C's `memcpy` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Beyond requiring that the program must be allowed to access both regions of memory,
/// it is _Undefined Behavior_ for source and destination to overlap.
/// Care must also be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy_nonoverlapping<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memcpy_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Invokes memset on the specified pointer, setting `count * size_of::<T>()` bytes of memory starting at `pmemdest` to `val`.
///
/// Ensures that the result has been flushed to persistence before returning.
pub unsafe fn write_bytes<T>(pmemdest: *mut T, val: u8, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memset_persist(pmemdest as *mut c_void, val as c_int, len as size_t);
}

/// Overwrites a memory location with the given value without reading or dropping the old value.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// This operation is marked unsafe because it accepts a raw pointer.
///
/// It does not drop the contents of dst. This is safe, but it could leak allocations or resources,
/// so care must be taken not to overwrite an object that should be dropped.
///
/// This is appropriate for initializing uninitialized memory, or overwriting memory that has previously been read from.
pub unsafe fn write<T>(pmemdest: *mut T, val: T) { copy_nonoverlapping(&val as *const _, pmemdest, 1) }

pub unsafe fn msync<T>(pmemdest: *const T, count: usize) -> Result<(), io::Error> {
    let len = count * mem::size_of::<T>();
    let r = ffi::pmem_msync(pmemdest as *const c_void, len as size_t);
    if r == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}
<commit_msg>feat: add Debug for ptrs<commit_after>//! The functions in this section provide optimized copying to persistent memory
//!
//! The `copy`, `copy_nonoverlapping`, and `write_bytes`, provide the same memory copying as
//! `memmove(3)`, `memcpy(3)`, and `memset(3)`, and ensure that the result has been flushed to persistence before returning.
//!
//! > **Warning:** Using these functions where `is_pmem(1)` returns false may not do anything useful.
//! >              Use the normal libc functions in that case.

use ::std::mem;
use ::std::io;
use ::std::marker::PhantomData;

use ::libc::{c_void, c_int};
use ::libc::size_t;
use ::pmem_sys as ffi;

use pmap::PersistentMap;

/// Persistent memory virtual pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemConstVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemConstVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemConstVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemConstVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(&self) -> PmemConstVirtualPtr<U> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_mut(&self) -> PmemMutVirtualPtr<T> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> PmemConstVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemConstVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemConstVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &PersistentMap) -> PmemConstPtr<T> {
        let new_virt = PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemConstPtr { virt: new_virt, pool: pool.as_ptr() }
    }
}

impl<T> ::std::fmt::Pointer for PmemConstVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:#x}:{:#x}",self.poolid, self.offset)
    }
}

impl<T> ::std::fmt::Debug for PmemConstVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "PmemVirt *const {{ pool: {:#x}, offset: {:#x} }}", self.poolid, self.offset)
    }
}

/// Persistent memory virtual mutable pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemMutVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemMutVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemMutVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemMutVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(&self) -> PmemMutVirtualPtr<U> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_const(&self) -> PmemConstVirtualPtr<T> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> ::std::fmt::Pointer for PmemMutVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:#x}:{:#x}",self.poolid, self.offset)
    }
}

impl<T> ::std::fmt::Debug for PmemMutVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "PmemVirt *mut {{ pool: {:#x}, offset: {:#x} }}", self.poolid, self.offset)
    }
}

impl<T> PmemMutVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemMutVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemMutVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &mut PersistentMap) -> PmemMutPtr<T> {
        let new_virt = PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemMutPtr { virt: new_virt, pool: pool.as_mut_ptr() }
    }
}

/// Direct `*const T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemConstPtr<T: ?Sized> {
    virt: PmemConstVirtualPtr<T>,
    pool: *const T,
}

impl<T: ?Sized> PmemConstPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_mut(&self) -> PmemMutPtr<T> {
        PmemMutPtr { virt: self.virt.as_mut(), pool: self.pool as *mut T }
    }
}

impl<T> PmemConstPtr<T> {
    pub unsafe fn direct(&self) -> *const T {
        if self.is_null() {
            ::std::ptr::null()
        } else {
            self.pool.offset(self.virt.offset as isize) as *const T
        }
    }

    pub fn as_virtual(self) -> PmemConstVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemConstPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(&self) -> PmemConstPtr<U> {
        let new_virt = self.virt.as_type();
        PmemConstPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

impl<T> ::std::fmt::Pointer for PmemConstPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:p} -> {:p}",self.virt, unsafe { self.direct() })
    }
}

impl<T> ::std::fmt::Debug for PmemConstPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "Pmem *const {{ pool: {:#x}, offset: {:#x} }}", self.virt.poolid, self.virt.offset)
    }
}

/// Direct `*mut T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemMutPtr<T: ?Sized> {
    virt: PmemMutVirtualPtr<T>,
    pool: *mut T,
}

impl<T: ?Sized> PmemMutPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_const(&self) -> PmemConstPtr<T> {
        PmemConstPtr { virt: self.virt.as_const(), pool: self.pool as *const T }
    }
}

impl<T> PmemMutPtr<T> {
    pub unsafe fn direct(&self) -> *mut T {
        if self.is_null() {
            ::std::ptr::null_mut()
        } else {
            self.pool.offset(self.virt.offset as isize) as *mut T
        }
    }

    pub fn as_virtual(self) -> PmemMutVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemMutPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(&self) -> PmemMutPtr<U> {
        let new_virt = self.virt.as_type();
        PmemMutPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

impl<T> ::std::fmt::Pointer for PmemMutPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:p} -> {:p}",self.virt, unsafe { self.direct() })
    }
}

impl<T> ::std::fmt::Debug for PmemMutPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "Pmem *mut {{ pool: {:#x}, offset: {:#x} }}", self.virt.poolid, self.virt.offset)
    }
}

pub fn null<T>() -> PmemConstVirtualPtr<T> {
    PmemConstVirtualPtr::null()
}

pub fn null_mut<T>() -> PmemMutVirtualPtr<T> {
    PmemMutVirtualPtr::null()
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may overlap.
///
/// `copy` is semantically equivalent to C's `memmove` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Care must be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memmove_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may _not_ overlap.
///
/// `copy_nonoverlapping` is semantically equivalent to C's `memcpy` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Beyond requiring that the program must be allowed to access both regions of memory,
/// it is _Undefined Behavior_ for source and destination to overlap.
/// Care must also be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy_nonoverlapping<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memcpy_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Invokes memset on the specified pointer, setting `count * size_of::<T>()` bytes of memory starting at `pmemdest` to `val`.
///
/// Ensures that the result has been flushed to persistence before returning.
pub unsafe fn write_bytes<T>(pmemdest: *mut T, val: u8, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memset_persist(pmemdest as *mut c_void, val as c_int, len as size_t);
}

/// Overwrites a memory location with the given value without reading or dropping the old value.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// This operation is marked unsafe because it accepts a raw pointer.
///
/// It does not drop the contents of dst. This is safe, but it could leak allocations or resources,
/// so care must be taken not to overwrite an object that should be dropped.
///
/// This is appropriate for initializing uninitialized memory, or overwriting memory that has previously been read from.
pub unsafe fn write<T>(pmemdest: *mut T, val: T) { copy_nonoverlapping(&val as *const _, pmemdest, 1) }

pub unsafe fn msync<T>(pmemdest: *const T, count: usize) -> Result<(), io::Error> {
    let len = count * mem::size_of::<T>();
    let r = ffi::pmem_msync(pmemdest as *const c_void, len as size_t);
    if r == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! Raw un-exported bindings to miniz for encoding/decoding

use std::io::prelude::*;
use std::io;
use libc;

use Compression;
use ffi;
use stream::{Stream, Compress, Decompress, Direction, Flush};

pub struct EncoderWriter<W: Write>(InnerWrite<W, Compress>);
pub struct DecoderWriter<W: Write>(InnerWrite<W, Decompress>);

struct InnerWrite<W, D: Direction> {
    inner: Option<W>,
    stream: Stream<D>,
    buf: Vec<u8>,
}

pub struct EncoderReader<R: Read>(InnerRead<R, Compress>);
pub struct DecoderReader<R: Read>(InnerRead<R, Decompress>);

struct InnerRead<R, D: Direction> {
    inner: R,
    stream: Stream<D>,
    buf: Vec<u8>, // TODO: this should be Box<[u8]>
    pos: usize,
    cap: usize,
}

impl<W: Write> EncoderWriter<W> {
    pub fn new(w: W, level: Compression, raw: bool, buf: Vec<u8>)
               -> EncoderWriter<W> {
        EncoderWriter(InnerWrite {
            inner: Some(w),
            stream: Stream::new_compress(level, raw),
            buf: buf,
        })
    }

    pub fn finish(&mut self) -> io::Result<()> {
        self.0.finish(&mut |stream, inner| {
            stream.compress_vec(&[], inner, Flush::Finish)
        })
    }

    pub fn into_inner(mut self) -> W { self.0.inner.take().unwrap() }

    pub fn take_inner(&mut self) -> W { self.0.inner.take().unwrap() }

    pub fn write_all_raw(&mut self, buf: &[u8]) -> io::Result<()> {
        self.0.inner.as_mut().unwrap().write_all(buf)
    }

    pub fn unwrapped(&self) -> bool {
        self.0.inner.is_none()
    }
}

impl<W: Write> Write for EncoderWriter<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(&mut |stream, inner| {
            stream.compress_vec(buf, inner, Flush::None)
        })
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.flush(&mut |stream, inner| {
            stream.compress_vec(&[], inner, Flush::Sync)
        })
    }
}

impl<W: Write> Drop for EncoderWriter<W> {
    fn drop(&mut self) {
        if self.0.inner.is_some() {
            let _ = self.finish();
        }
    }
}

impl<W: Write> DecoderWriter<W> {
    pub fn new(w: W, raw: bool, buf: Vec<u8>) -> DecoderWriter<W> {
        DecoderWriter(InnerWrite {
            inner: Some(w),
            stream: Stream::new_decompress(raw),
            buf: buf,
        })
    }

    pub fn finish(&mut self) -> io::Result<()> {
        self.0.finish(&mut |stream, inner| {
            stream.decompress_vec(&[], inner, Flush::Finish)
        })
    }

    pub fn into_inner(mut self) -> W { self.0.inner.take().unwrap() }
}

impl<W: Write> Write for DecoderWriter<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(&mut |stream, inner| {
            stream.decompress_vec(buf, inner, Flush::None)
        })
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.flush(&mut |stream, inner| {
            stream.decompress_vec(&[], inner, Flush::Sync)
        })
    }
}

impl<W: Write, D: Direction> InnerWrite<W, D> {
    fn write<F>(&mut self, f: &mut F) -> io::Result<usize>
        where F: FnMut(&mut Stream<D>, &mut Vec<u8>) -> libc::c_int
    {
        let writer = self.inner.as_mut().unwrap();
        if self.buf.len() > 0 {
            try!(writer.write_all(&self.buf));
            self.buf.truncate(0);
        }

        let before_in = self.stream.total_in();
        let ret = f(&mut self.stream, &mut self.buf);
        let written = (self.stream.total_in() - before_in) as usize;
        match ret {
            ffi::MZ_OK
            | ffi::MZ_BUF_ERROR
            | ffi::MZ_STREAM_END => Ok(written),
            n => panic!("unexpected return {}", n),
        }
    }

    fn flush<F>(&mut self, f: &mut F) -> io::Result<()>
        where F: FnMut(&mut Stream<D>, &mut Vec<u8>) -> libc::c_int
    {
        try!(self.write(f));
        let inner = self.inner.as_mut().unwrap();
        if self.buf.len() > 0 {
            try!(inner.write_all(&self.buf));
        }
        inner.flush()
    }

    fn finish<F>(&mut self, f: &mut F) -> io::Result<()>
        where F: FnMut(&mut Stream<D>, &mut Vec<u8>) -> libc::c_int
    {
        // Unfortunately miniz doesn't actually tell us when we're done with
        // pulling out all the data from the internal stream. To remedy this we
        // have to continually ask the stream for more memory until it doesn't
        // give us a chunk of memory the same size as our own internal buffer,
        // at which point we assume it's reached the end.
        let mut cont = true;
        while cont {
            try!(self.write(f));
            let inner = self.inner.as_mut().unwrap();
            try!(inner.write_all(&self.buf));
            cont = self.buf.len() == self.buf.capacity();
            self.buf.truncate(0);
        }
        Ok(())
    }
}

impl<R: Read> EncoderReader<R> {
    pub fn new(w: R, level: Compression, raw: bool, buf: Vec<u8>)
               -> EncoderReader<R> {
        EncoderReader(InnerRead {
            inner: w,
            stream: Stream::new_compress(level, raw),
            buf: buf,
            cap: 0,
            pos: 0,
        })
    }
    pub fn get_ref(&self) -> &R { &self.0.inner }
    pub fn into_inner(self) -> R { self.0.inner }
}

impl<R: Read> Read for EncoderReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(|stream, inner, flush| stream.compress(inner, buf, flush))
    }
}

impl<R: Read> DecoderReader<R> {
    pub fn new(r: R, raw: bool, buf: Vec<u8>) -> DecoderReader<R> {
        DecoderReader(InnerRead {
            inner: r,
            stream: Stream::new_decompress(raw),
            buf: buf,
            pos: 0,
            cap: 0,
        })
    }

    pub fn into_inner(self) -> R { self.0.inner }

    pub fn read_raw(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut from = &self.0.buf[self.0.pos..self.0.cap];
        match try!(Read::read(&mut from, buf)) {
            0 => {}
            n => { self.0.pos += n; return Ok(n) }
        }
        self.0.inner.read(buf)
    }
}

impl<R: Read> Read for DecoderReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(|stream, inner, flush| stream.decompress(inner, buf, flush))
    }
}

impl<R: Read, D: Direction> InnerRead<R, D> {
    fn read<F>(&mut self, mut f: F) -> io::Result<usize>
        where F: FnMut(&mut Stream<D>, &[u8], Flush) -> libc::c_int
    {
        loop {
            let mut eof = false;
            if self.pos == self.cap {
                self.cap = try!(self.inner.read(&mut self.buf));
                self.pos = 0;
                eof = self.cap == 0;
            }

            let before_out = self.stream.total_out();
            let before_in = self.stream.total_in();
            let ret = f(&mut self.stream, &self.buf[self.pos..self.cap],
                        if eof {Flush::Finish} else {Flush::None});
            let read = (self.stream.total_out() - before_out) as usize;
            self.pos += (self.stream.total_in() - before_in) as usize;

            return match ret {
                ffi::MZ_OK | ffi::MZ_BUF_ERROR => {
                    // If we haven't ready any data and we haven't hit EOF yet,
                    // then we need to keep asking for more data because if we
                    // return that 0 bytes of data have been read then it will
                    // be interpreted as EOF.
                    if read == 0 && !eof { continue }
                    Ok(read)
                }
                ffi::MZ_STREAM_END => return Ok(read),
                ffi::MZ_DATA_ERROR => {
                    Err(io::Error::new(io::ErrorKind::InvalidInput,
                                       "corrupt deflate stream", None))
                }
                n => panic!("unexpected return {}", n),
            }
        }
    }
}
<commit_msg>Flush the entire buffer on flush()<commit_after>//! Raw un-exported bindings to miniz for encoding/decoding

use std::io::prelude::*;
use std::io;
use libc;

use Compression;
use ffi;
use stream::{Stream, Compress, Decompress, Direction, Flush};

pub struct EncoderWriter<W: Write>(InnerWrite<W, Compress>);
pub struct DecoderWriter<W: Write>(InnerWrite<W, Decompress>);

struct InnerWrite<W, D: Direction> {
    inner: Option<W>,
    stream: Stream<D>,
    buf: Vec<u8>,
}

pub struct EncoderReader<R: Read>(InnerRead<R, Compress>);
pub struct DecoderReader<R: Read>(InnerRead<R, Decompress>);

struct InnerRead<R, D: Direction> {
    inner: R,
    stream: Stream<D>,
    buf: Vec<u8>, // TODO: this should be Box<[u8]>
    pos: usize,
    cap: usize,
}

impl<W: Write> EncoderWriter<W> {
    pub fn new(w: W, level: Compression, raw: bool, buf: Vec<u8>)
               -> EncoderWriter<W> {
        EncoderWriter(InnerWrite {
            inner: Some(w),
            stream: Stream::new_compress(level, raw),
            buf: buf,
        })
    }

    pub fn finish(&mut self) -> io::Result<()> {
        self.0.finish(&mut |stream, inner| {
            stream.compress_vec(&[], inner, Flush::Finish)
        })
    }

    pub fn into_inner(mut self) -> W { self.0.inner.take().unwrap() }

    pub fn take_inner(&mut self) -> W { self.0.inner.take().unwrap() }

    pub fn write_all_raw(&mut self, buf: &[u8]) -> io::Result<()> {
        self.0.inner.as_mut().unwrap().write_all(buf)
    }

    pub fn unwrapped(&self) -> bool {
        self.0.inner.is_none()
    }
}

impl<W: Write> Write for EncoderWriter<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(&mut |stream, inner| {
            stream.compress_vec(buf, inner, Flush::None)
        })
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.finish(&mut |stream, inner| {
            stream.compress_vec(&[], inner, Flush::Sync)
        }).and_then(|()| self.0.inner.as_mut().unwrap().flush())
    }
}

impl<W: Write> Drop for EncoderWriter<W> {
    fn drop(&mut self) {
        if self.0.inner.is_some() {
            let _ = self.finish();
        }
    }
}

impl<W: Write> DecoderWriter<W> {
    pub fn new(w: W, raw: bool, buf: Vec<u8>) -> DecoderWriter<W> {
        DecoderWriter(InnerWrite {
            inner: Some(w),
            stream: Stream::new_decompress(raw),
            buf: buf,
        })
    }

    pub fn finish(&mut self) -> io::Result<()> {
        self.0.finish(&mut |stream, inner| {
            stream.decompress_vec(&[], inner, Flush::Finish)
        })
    }

    pub fn into_inner(mut self) -> W { self.0.inner.take().unwrap() }
}

impl<W: Write> Write for DecoderWriter<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(&mut |stream, inner| {
            stream.decompress_vec(buf, inner, Flush::None)
        })
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.finish(&mut |stream, inner| {
            stream.decompress_vec(&[], inner, Flush::Sync)
        }).and_then(|()| self.0.inner.as_mut().unwrap().flush())
    }
}

impl<W: Write, D: Direction> InnerWrite<W, D> {
    fn write<F>(&mut self, f: &mut F) -> io::Result<usize>
        where F: FnMut(&mut Stream<D>, &mut Vec<u8>) -> libc::c_int
    {
        let writer = self.inner.as_mut().unwrap();
        if self.buf.len() > 0 {
            try!(writer.write_all(&self.buf));
            self.buf.truncate(0);
        }

        let before_in = self.stream.total_in();
        let ret = f(&mut self.stream, &mut self.buf);
        let written = (self.stream.total_in() - before_in) as usize;
        match ret {
            ffi::MZ_OK
            | ffi::MZ_BUF_ERROR
            | ffi::MZ_STREAM_END => Ok(written),
            n => panic!("unexpected return {}", n),
        }
    }

    fn finish<F>(&mut self, f: &mut F) -> io::Result<()>
        where F: FnMut(&mut Stream<D>, &mut Vec<u8>) -> libc::c_int
    {
        // Unfortunately miniz doesn't actually tell us when we're done with
        // pulling out all the data from the internal stream. To remedy this we
        // have to continually ask the stream for more memory until it doesn't
        // give us a chunk of memory the same size as our own internal buffer,
        // at which point we assume it's reached the end.
        let mut cont = true;
        while cont {
            try!(self.write(f));
            let inner = self.inner.as_mut().unwrap();
            if self.buf.len() > 0 {
                try!(inner.write_all(&self.buf));
            }
            cont = self.buf.len() == self.buf.capacity();
            self.buf.truncate(0);
        }
        Ok(())
    }
}

impl<R: Read> EncoderReader<R> {
    pub fn new(w: R, level: Compression, raw: bool, buf: Vec<u8>)
               -> EncoderReader<R> {
        EncoderReader(InnerRead {
            inner: w,
            stream: Stream::new_compress(level, raw),
            buf: buf,
            cap: 0,
            pos: 0,
        })
    }
    pub fn get_ref(&self) -> &R { &self.0.inner }
    pub fn into_inner(self) -> R { self.0.inner }
}

impl<R: Read> Read for EncoderReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(|stream, inner, flush| stream.compress(inner, buf, flush))
    }
}

impl<R: Read> DecoderReader<R> {
    pub fn new(r: R, raw: bool, buf: Vec<u8>) -> DecoderReader<R> {
        DecoderReader(InnerRead {
            inner: r,
            stream: Stream::new_decompress(raw),
            buf: buf,
            pos: 0,
            cap: 0,
        })
    }

    pub fn into_inner(self) -> R { self.0.inner }

    pub fn read_raw(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut from = &self.0.buf[self.0.pos..self.0.cap];
        match try!(Read::read(&mut from, buf)) {
            0 => {}
            n => { self.0.pos += n; return Ok(n) }
        }
        self.0.inner.read(buf)
    }
}

impl<R: Read> Read for DecoderReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(|stream, inner, flush| stream.decompress(inner, buf, flush))
    }
}

impl<R: Read, D: Direction> InnerRead<R, D> {
    fn read<F>(&mut self, mut f: F) -> io::Result<usize>
        where F: FnMut(&mut Stream<D>, &[u8], Flush) -> libc::c_int
    {
        loop {
            let mut eof = false;
            if self.pos == self.cap {
                self.cap = try!(self.inner.read(&mut self.buf));
                self.pos = 0;
                eof = self.cap == 0;
            }

            let before_out = self.stream.total_out();
            let before_in = self.stream.total_in();
            let ret = f(&mut self.stream, &self.buf[self.pos..self.cap],
                        if eof {Flush::Finish} else {Flush::None});
            let read = (self.stream.total_out() - before_out) as usize;
            self.pos += (self.stream.total_in() - before_in) as usize;

            return match ret {
                ffi::MZ_OK | ffi::MZ_BUF_ERROR => {
                    // If we haven't ready any data and we haven't hit EOF yet,
                    // then we need to keep asking for more data because if we
                    // return that 0 bytes of data have been read then it will
                    // be interpreted as EOF.
                    if read == 0 && !eof { continue }
                    Ok(read)
                }
                ffi::MZ_STREAM_END => return Ok(read),
                ffi::MZ_DATA_ERROR => {
                    Err(io::Error::new(io::ErrorKind::InvalidInput,
                                       "corrupt deflate stream", None))
                }
                n => panic!("unexpected return {}", n),
            }
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate wlroots;

use std::process::Command;
use std::thread;
use std::time::{SystemTime, UNIX_EPOCH};

use wlroots::{project_box, Area, Capability, CompositorBuilder, CompositorHandle, Cursor,
              CursorHandle, CursorHandler, InputManagerHandler, KeyboardHandle, KeyboardHandler,
              Origin, OutputBuilder, OutputBuilderResult, OutputHandle, OutputHandler,
              OutputLayout, OutputLayoutHandle, OutputLayoutHandler, OutputManagerHandler,
              PointerHandle, PointerHandler, Renderer, Seat, SeatHandle, SeatHandler, Size,
              XCursorTheme, XdgV6ShellHandler, XdgV6ShellManagerHandler, XdgV6ShellState,
              XdgV6ShellSurfaceHandle};
use wlroots::key_events::KeyEvent;
use wlroots::pointer_events::{ButtonEvent, MotionEvent};
use wlroots::utils::{init_logging, L_DEBUG};
use wlroots::wlroots_sys::wlr_key_state::WLR_KEY_PRESSED;
use wlroots::xkbcommon::xkb::keysyms::{KEY_Escape, KEY_F1};

struct State {
    xcursor_theme: XCursorTheme,
    keyboard: Option<KeyboardHandle>,
    layout: OutputLayoutHandle,
    cursor: CursorHandle,
    shells: Vec<XdgV6ShellSurfaceHandle>,
    seat_handle: Option<SeatHandle>
}

impl State {
    fn new(xcursor_theme: XCursorTheme, layout: OutputLayoutHandle, cursor: CursorHandle) -> Self {
        State { xcursor_theme,
                layout,
                cursor,
                keyboard: None,
                seat_handle: None,
                shells: vec![] }
    }
}

compositor_data!(State);

struct SeatHandlerEx;

struct CursorEx;

impl CursorHandler for CursorEx {}

impl SeatHandler for SeatHandlerEx {}

struct XdgV6ShellHandlerEx;
struct XdgV6ShellManager;
struct OutputLayoutEx;

impl OutputLayoutHandler for OutputLayoutEx {}

impl XdgV6ShellHandler for XdgV6ShellHandlerEx {}
impl XdgV6ShellManagerHandler for XdgV6ShellManager {
    fn new_surface(&mut self,
                   compositor: CompositorHandle,
                   shell: XdgV6ShellSurfaceHandle)
                   -> Option<Box<XdgV6ShellHandler>> {
        with_handles!([(compositor: {compositor}), (shell: {shell})] => {
            shell.ping();
            let state: &mut State = compositor.into();
            state.shells.push(shell.weak_reference());
            with_handles!([(layout: {&mut state.layout})] => {
                for (mut output, _) in layout.outputs() {
                    with_handles!([(output: {output})] =>{
                        output.schedule_frame()
                    }).ok();
                }
            }).expect("Layout was destroyed");
        }).unwrap();
        Some(Box::new(XdgV6ShellHandlerEx))
    }

    fn surface_destroyed(&mut self, compositor: CompositorHandle, shell: XdgV6ShellSurfaceHandle) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let weak = shell;
            if let Some(index) = state.shells.iter().position(|s| *s == weak) {
                state.shells.remove(index);
            }
        }).unwrap();
    }
}

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExPointer;

struct ExKeyboardHandler;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor: CompositorHandle,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let mut result = builder.build_best_mode(ExOutput);
        with_handles!([(compositor: {compositor}), (output: {&mut result.output})] => {
            let state: &mut State = compositor.into();
            let xcursor = state.xcursor_theme
                .get_cursor("left_ptr".into())
                .expect("Could not load left_ptr cursor");
            let image = &xcursor.images()[0];
            // TODO use output config if present instead of auto
            let layout = &mut state.layout;
            let cursor = &mut state.cursor;
            with_handles!([(layout: {layout}), (cursor: {cursor})] => {
                layout.add_auto(output);
                cursor.attach_output_layout(layout);
                cursor.set_cursor_image(image);
                let (x, y) = cursor.coords();
                // https://en.wikipedia.org/wiki/Mouse_warping
                cursor.warp(None, x, y);
            }).expect("Layout was destroyed");
        }).unwrap();
        Some(result)
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self,
              mut compositor: CompositorHandle,
              _: KeyboardHandle,
              key_event: &KeyEvent) {
        with_handles!([(compositor: {&mut compositor})] => {
            for key in key_event.pressed_keys() {
                if key == KEY_Escape {
                    compositor.terminate();
                } else if key_event.key_state() == WLR_KEY_PRESSED {
                    if key == KEY_F1 {
                        thread::spawn(move || {
                            Command::new("weston-terminal").output().unwrap();
                        });
                        return
                    }
                }
            }
            let state: &mut State = compositor.into();
            let mut seat_handle = state.seat_handle.clone().unwrap();
            seat_handle.run(|seat| {
                seat.keyboard_notify_key(key_event.time_msec(),
                                         key_event.keycode(),
                                         key_event.key_state() as u32);
            })
                .unwrap();
        }).unwrap();
    }
}

impl PointerHandler for ExPointer {
    fn on_motion(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &MotionEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let (delta_x, delta_y) = event.delta();
            state.cursor
                .run(|cursor| {
                    cursor.move_to(event.device(), delta_x, delta_y);
                })
                .unwrap();
        }).unwrap();
    }

    fn on_button(&mut self, compositor: CompositorHandle, _: PointerHandle, _: &ButtonEvent) {
        with_handles!([(compositor: {compositor})] => {
        let state: &mut State = compositor.into();
        let mut seat_handle = state.seat_handle.clone().unwrap();
        let mut keyboard = state.keyboard.clone().unwrap();
        let mut surface =
            state.shells[0].run(|shell| {
                                    match shell.state() {
                                        Some(&mut XdgV6ShellState::TopLevel(ref mut toplevel)) => {
                                            toplevel.set_activated(true);
                                        }
                                        _ => {}
                                    }

                                    shell.surface()
                                })
                           .unwrap();
        seat_handle.run(|seat| {
                            keyboard.run(|keyboard| {
                                             surface.run(|surface| {
                                                 seat.set_keyboard(keyboard.input_device());
                                                 seat.keyboard_notify_enter(surface,
                                                    &mut keyboard.keycodes(),
                                                    &mut keyboard.get_modifier_masks())
                                             })
                                                    .unwrap();
                                         })
                                    .unwrap();
                        })
                   .unwrap();
        }).unwrap();
    }
}

impl OutputHandler for ExOutput {
    fn on_frame(&mut self, compositor: CompositorHandle, output: OutputHandle) {
        with_handles!([(compositor: {compositor}), (output: {output})] => {
            let state: &mut State = compositor.data.downcast_mut().unwrap();
            let renderer = compositor.renderer
                .as_mut()
                .expect("Compositor was not loaded with a renderer");
            let mut render_context = renderer.render(output, None);
            render_context.clear([0.25, 0.25, 0.25, 1.0]);
            render_shells(state, &mut render_context);
        }).unwrap();
    }
}

impl InputManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     _: CompositorHandle,
                     _: PointerHandle)
                     -> Option<Box<PointerHandler>> {
        Some(Box::new(ExPointer))
    }

    fn keyboard_added(&mut self,
                      compositor: CompositorHandle,
                      keyboard: KeyboardHandle)
                      -> Option<Box<KeyboardHandler>> {
        with_handles!([(compositor: {compositor}), (keyboard: {keyboard})] => {
            let state: &mut State = compositor.into();
            state.keyboard = Some(keyboard.weak_reference());
            let seat_handle = state.seat_handle.clone().unwrap();
            with_handles!([(seat: {seat_handle})] => {
                seat.set_keyboard(keyboard.input_device());
            }).unwrap();
        }).unwrap();
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(L_DEBUG, None);
    let cursor = Cursor::create(Box::new(CursorEx));
    let xcursor_theme = XCursorTheme::load_theme(None, 16).expect("Could not load theme");
    let layout = OutputLayout::create(Box::new(OutputLayoutEx));

    let mut compositor =
        CompositorBuilder::new().gles2(true)
                                .input_manager(Box::new(InputManager))
                                .output_manager(Box::new(OutputManager))
                                .xdg_shell_v6_manager(Box::new(XdgV6ShellManager))
                                .build_auto(State::new(xcursor_theme, layout, cursor));

    {
        let mut seat_handle =
            Seat::create(&mut compositor, "Main Seat".into(), Box::new(SeatHandlerEx));
        seat_handle.run(|seat| {
                            seat.set_capabilities(Capability::all());
                        })
                   .unwrap();
        let state: &mut State = (&mut compositor).into();
        state.seat_handle = Some(seat_handle);
    }
    compositor.run();
}

/// Render the shells in the current compositor state on the given output.
fn render_shells(state: &mut State, renderer: &mut Renderer) {
    let shells = state.shells.clone();
    for mut shell in shells {
        with_handles!([(shell: {shell}),
                      (surface: {shell.surface()}),
                      (layout: {&mut state.layout})] => {
            let (width, height) = surface.current_state().size();
            let (render_width, render_height) =
                (width * renderer.output.scale() as i32,
                 height * renderer.output.scale() as i32);
            let (lx, ly) = (0.0, 0.0);
            let render_box = Area::new(Origin::new(lx as i32, ly as i32),
                                       Size::new(render_width,
                                                 render_height));
            if layout.intersects(renderer.output, render_box) {
                let transform = renderer.output.get_transform().invert();
                let matrix = project_box(render_box,
                                         transform,
                                         0.0,
                                         renderer.output
                                         .transform_matrix());
                renderer.render_texture_with_matrix(&surface.texture(),
                                                    matrix);
                let start = SystemTime::now();
                let now = start.duration_since(UNIX_EPOCH)
                    .expect("Time went backwards");
                surface.send_frame_done(now);
            }
        }).unwrap();
    }
}
<commit_msg>xdg-shell-example: use xcursor manager<commit_after>#[macro_use]
extern crate wlroots;

use std::process::Command;
use std::thread;
use std::time::{SystemTime, UNIX_EPOCH};

use wlroots::{project_box, Area, Capability, CompositorBuilder, CompositorHandle, Cursor,
              CursorHandle, CursorHandler, InputManagerHandler, KeyboardHandle, KeyboardHandler,
              Origin, OutputBuilder, OutputBuilderResult, OutputHandle, OutputHandler,
              OutputLayout, OutputLayoutHandle, OutputLayoutHandler, OutputManagerHandler,
              PointerHandle, PointerHandler, Renderer, Seat, SeatHandle, SeatHandler, Size,
              XCursorManager, XdgV6ShellHandler, XdgV6ShellManagerHandler, XdgV6ShellState,
              XdgV6ShellSurfaceHandle};
use wlroots::key_events::KeyEvent;
use wlroots::pointer_events::{ButtonEvent, MotionEvent, AbsoluteMotionEvent};
use wlroots::utils::{init_logging, L_DEBUG};
use wlroots::wlroots_sys::wlr_key_state::WLR_KEY_PRESSED;
use wlroots::xkbcommon::xkb::keysyms::{KEY_Escape, KEY_F1};

struct State {
    xcursor_manager: XCursorManager,
    keyboard: Option<KeyboardHandle>,
    layout: OutputLayoutHandle,
    cursor: CursorHandle,
    shells: Vec<XdgV6ShellSurfaceHandle>,
    seat_handle: Option<SeatHandle>
}

impl State {
    fn new(xcursor_manager: XCursorManager, layout: OutputLayoutHandle, cursor: CursorHandle) -> Self {
        State { xcursor_manager,
                layout,
                cursor,
                keyboard: None,
                seat_handle: None,
                shells: vec![] }
    }
}

compositor_data!(State);

struct SeatHandlerEx;

struct CursorEx;

impl CursorHandler for CursorEx {}

impl SeatHandler for SeatHandlerEx {}

struct XdgV6ShellHandlerEx;
struct XdgV6ShellManager;
struct OutputLayoutEx;

impl OutputLayoutHandler for OutputLayoutEx {}

impl XdgV6ShellHandler for XdgV6ShellHandlerEx {}
impl XdgV6ShellManagerHandler for XdgV6ShellManager {
    fn new_surface(&mut self,
                   compositor: CompositorHandle,
                   shell: XdgV6ShellSurfaceHandle)
                   -> Option<Box<XdgV6ShellHandler>> {
        with_handles!([(compositor: {compositor}), (shell: {shell})] => {
            shell.ping();
            let state: &mut State = compositor.into();
            state.shells.push(shell.weak_reference());
            with_handles!([(layout: {&mut state.layout})] => {
                for (mut output, _) in layout.outputs() {
                    with_handles!([(output: {output})] =>{
                        output.schedule_frame()
                    }).ok();
                }
            }).expect("Layout was destroyed");
        }).unwrap();
        Some(Box::new(XdgV6ShellHandlerEx))
    }

    fn surface_destroyed(&mut self, compositor: CompositorHandle, shell: XdgV6ShellSurfaceHandle) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let weak = shell;
            if let Some(index) = state.shells.iter().position(|s| *s == weak) {
                state.shells.remove(index);
            }
        }).unwrap();
    }
}

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExPointer;

struct ExKeyboardHandler;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor: CompositorHandle,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let mut result = builder.build_best_mode(ExOutput);
        with_handles!([(compositor: {compositor}), (output: {&mut result.output})] => {
            let state: &mut State = compositor.data.downcast_mut().unwrap();
            let xcursor_manager = &mut state.xcursor_manager;
            // TODO use output config if present instead of auto
            let layout = &mut state.layout;
            let cursor = &mut state.cursor;
            with_handles!([(layout: {layout}), (cursor: {cursor})] => {
                layout.add_auto(output);
                cursor.attach_output_layout(layout);
                xcursor_manager.load(output.scale());
                xcursor_manager.set_cursor_image("left_ptr".to_string(), cursor);
                let (x, y) = cursor.coords();
                // https://en.wikipedia.org/wiki/Mouse_warping
                cursor.warp(None, x, y);
            }).expect("Layout was destroyed");
        }).unwrap();
        Some(result)
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self,
              mut compositor: CompositorHandle,
              _: KeyboardHandle,
              key_event: &KeyEvent) {
        with_handles!([(compositor: {&mut compositor})] => {
            for key in key_event.pressed_keys() {
                if key == KEY_Escape {
                    compositor.terminate();
                } else if key_event.key_state() == WLR_KEY_PRESSED {
                    if key == KEY_F1 {
                        thread::spawn(move || {
                            Command::new("weston-terminal").output().unwrap();
                        });
                        return
                    }
                }
            }
            let state: &mut State = compositor.into();
            let mut seat_handle = state.seat_handle.clone().unwrap();
            seat_handle.run(|seat| {
                seat.keyboard_notify_key(key_event.time_msec(),
                                         key_event.keycode(),
                                         key_event.key_state() as u32);
            })
                .unwrap();
        }).unwrap();
    }
}

impl PointerHandler for ExPointer {
    fn on_motion_absolute(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &AbsoluteMotionEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let (x, y) = event.pos();
            state.cursor
                .run(|cursor| cursor.warp_absolute(event.device(), x, y))
                .unwrap();
        }).unwrap();
    }

    fn on_motion(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &MotionEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let (delta_x, delta_y) = event.delta();
            state.cursor
                .run(|cursor| {
                    cursor.move_to(event.device(), delta_x, delta_y);
                })
                .unwrap();
        }).unwrap();
    }

    fn on_button(&mut self, compositor: CompositorHandle, _: PointerHandle, _: &ButtonEvent) {
        with_handles!([(compositor: {compositor})] => {
        let state: &mut State = compositor.into();
        let mut seat_handle = state.seat_handle.clone().unwrap();
        let mut keyboard = state.keyboard.clone().unwrap();
        let mut surface =
            state.shells[0].run(|shell| {
                                    match shell.state() {
                                        Some(&mut XdgV6ShellState::TopLevel(ref mut toplevel)) => {
                                            toplevel.set_activated(true);
                                        }
                                        _ => {}
                                    }

                                    shell.surface()
                                })
                           .unwrap();
        seat_handle.run(|seat| {
                            keyboard.run(|keyboard| {
                                             surface.run(|surface| {
                                                 seat.set_keyboard(keyboard.input_device());
                                                 seat.keyboard_notify_enter(surface,
                                                    &mut keyboard.keycodes(),
                                                    &mut keyboard.get_modifier_masks())
                                             })
                                                    .unwrap();
                                         })
                                    .unwrap();
                        })
                   .unwrap();
        }).unwrap();
    }
}

impl OutputHandler for ExOutput {
    fn on_frame(&mut self, compositor: CompositorHandle, output: OutputHandle) {
        with_handles!([(compositor: {compositor}), (output: {output})] => {
            let state: &mut State = compositor.data.downcast_mut().unwrap();
            let renderer = compositor.renderer
                .as_mut()
                .expect("Compositor was not loaded with a renderer");
            let mut render_context = renderer.render(output, None);
            render_context.clear([0.25, 0.25, 0.25, 1.0]);
            render_shells(state, &mut render_context);
        }).unwrap();
    }
}

impl InputManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     _: CompositorHandle,
                     _: PointerHandle)
                     -> Option<Box<PointerHandler>> {
        Some(Box::new(ExPointer))
    }

    fn keyboard_added(&mut self,
                      compositor: CompositorHandle,
                      keyboard: KeyboardHandle)
                      -> Option<Box<KeyboardHandler>> {
        with_handles!([(compositor: {compositor}), (keyboard: {keyboard})] => {
            let state: &mut State = compositor.into();
            state.keyboard = Some(keyboard.weak_reference());
            let seat_handle = state.seat_handle.clone().unwrap();
            with_handles!([(seat: {seat_handle})] => {
                seat.set_keyboard(keyboard.input_device());
            }).unwrap();
        }).unwrap();
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(L_DEBUG, None);
    let mut cursor = Cursor::create(Box::new(CursorEx));
    let mut xcursor_manager = XCursorManager::create("default".to_string(), 24).expect("Could not create xcursor manager");
    xcursor_manager.load(1.0);
    cursor.run(|c| xcursor_manager.set_cursor_image("left_ptr".to_string(), c)).unwrap();
    let layout = OutputLayout::create(Box::new(OutputLayoutEx));

    let mut compositor =
        CompositorBuilder::new().gles2(true)
                                .input_manager(Box::new(InputManager))
                                .output_manager(Box::new(OutputManager))
                                .xdg_shell_v6_manager(Box::new(XdgV6ShellManager))
                                .build_auto(State::new(xcursor_manager, layout, cursor));

    {
        let mut seat_handle =
            Seat::create(&mut compositor, "Main Seat".into(), Box::new(SeatHandlerEx));
        seat_handle.run(|seat| {
                            seat.set_capabilities(Capability::all());
                        })
                   .unwrap();
        let state: &mut State = (&mut compositor).into();
        state.seat_handle = Some(seat_handle);
    }
    compositor.run();
}

/// Render the shells in the current compositor state on the given output.
fn render_shells(state: &mut State, renderer: &mut Renderer) {
    let shells = state.shells.clone();
    for mut shell in shells {
        with_handles!([(shell: {shell}),
                      (surface: {shell.surface()}),
                      (layout: {&mut state.layout})] => {
            let (width, height) = surface.current_state().size();
            let (render_width, render_height) =
                (width * renderer.output.scale() as i32,
                 height * renderer.output.scale() as i32);
            let (lx, ly) = (0.0, 0.0);
            let render_box = Area::new(Origin::new(lx as i32, ly as i32),
                                       Size::new(render_width,
                                                 render_height));
            if layout.intersects(renderer.output, render_box) {
                let transform = renderer.output.get_transform().invert();
                let matrix = project_box(render_box,
                                         transform,
                                         0.0,
                                         renderer.output
                                         .transform_matrix());
                renderer.render_texture_with_matrix(&surface.texture(),
                                                    matrix);
                let start = SystemTime::now();
                let now = start.duration_since(UNIX_EPOCH)
                    .expect("Time went backwards");
                surface.send_frame_done(now);
            }
        }).unwrap();
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate wlroots;

use std::process::Command;
use std::thread;
use std::time::{SystemTime, UNIX_EPOCH};

use wlroots::{project_box, Area, Capability, CompositorBuilder, CompositorHandle, Cursor,
              CursorHandle, CursorHandler, InputManagerHandler, KeyboardHandle, KeyboardHandler,
              Origin, OutputBuilder, OutputBuilderResult, OutputHandle, OutputHandler,
              OutputLayout, OutputLayoutHandle, OutputLayoutHandler, OutputManagerHandler,
              PointerHandle, PointerHandler, Renderer, Seat, SeatHandle, SeatHandler, Size,
              XCursorManager, XdgV6ShellHandler, XdgV6ShellManagerHandler, XdgV6ShellState,
              XdgV6ShellSurfaceHandle};
use wlroots::key_events::KeyEvent;
use wlroots::pointer_events::{ButtonEvent, MotionEvent, AbsoluteMotionEvent};
use wlroots::utils::{init_logging, L_DEBUG};
use wlroots::wlroots_sys::wlr_key_state::WLR_KEY_PRESSED;
use wlroots::xkbcommon::xkb::keysyms::{KEY_Escape, KEY_F1};

struct State {
    xcursor_manager: XCursorManager,
    keyboard: Option<KeyboardHandle>,
    layout: OutputLayoutHandle,
    cursor: CursorHandle,
    shells: Vec<XdgV6ShellSurfaceHandle>,
    seat_handle: Option<SeatHandle>
}

impl State {
    fn new(xcursor_manager: XCursorManager, layout: OutputLayoutHandle, cursor: CursorHandle) -> Self {
        State { xcursor_manager,
                layout,
                cursor,
                keyboard: None,
                seat_handle: None,
                shells: vec![] }
    }
}

compositor_data!(State);

struct SeatHandlerEx;

struct CursorEx;

impl CursorHandler for CursorEx {}

impl SeatHandler for SeatHandlerEx {}

struct XdgV6ShellHandlerEx;
struct XdgV6ShellManager;
struct OutputLayoutEx;

impl OutputLayoutHandler for OutputLayoutEx {}

impl XdgV6ShellHandler for XdgV6ShellHandlerEx {}
impl XdgV6ShellManagerHandler for XdgV6ShellManager {
    fn new_surface(&mut self,
                   compositor: CompositorHandle,
                   shell: XdgV6ShellSurfaceHandle)
                   -> Option<Box<XdgV6ShellHandler>> {
        with_handles!([(compositor: {compositor}), (shell: {shell})] => {
            shell.ping();
            let state: &mut State = compositor.into();
            state.shells.push(shell.weak_reference());
            with_handles!([(layout: {&mut state.layout})] => {
                for (mut output, _) in layout.outputs() {
                    with_handles!([(output: {output})] =>{
                        output.schedule_frame()
                    }).ok();
                }
            }).expect("Layout was destroyed");
        }).unwrap();
        Some(Box::new(XdgV6ShellHandlerEx))
    }

    fn surface_destroyed(&mut self, compositor: CompositorHandle, shell: XdgV6ShellSurfaceHandle) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let weak = shell;
            if let Some(index) = state.shells.iter().position(|s| *s == weak) {
                state.shells.remove(index);
            }
        }).unwrap();
    }
}

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExPointer;

struct ExKeyboardHandler;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor: CompositorHandle,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let mut result = builder.build_best_mode(ExOutput);
        with_handles!([(compositor: {compositor}), (output: {&mut result.output})] => {
            let state: &mut State = compositor.data.downcast_mut().unwrap();
            let xcursor_manager = &mut state.xcursor_manager;
            // TODO use output config if present instead of auto
            let layout = &mut state.layout;
            let cursor = &mut state.cursor;
            with_handles!([(layout: {layout}), (cursor: {cursor})] => {
                layout.add_auto(output);
                cursor.attach_output_layout(layout);
                xcursor_manager.load(output.scale());
                xcursor_manager.set_cursor_image("left_ptr".to_string(), cursor);
                let (x, y) = cursor.coords();
                // https://en.wikipedia.org/wiki/Mouse_warping
                cursor.warp(None, x, y);
            }).expect("Layout was destroyed");
        }).unwrap();
        Some(result)
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self,
              mut compositor: CompositorHandle,
              _: KeyboardHandle,
              key_event: &KeyEvent) {
        with_handles!([(compositor: {&mut compositor})] => {
            for key in key_event.pressed_keys() {
                if key == KEY_Escape {
                    compositor.terminate();
                } else if key_event.key_state() == WLR_KEY_PRESSED {
                    if key == KEY_F1 {
                        thread::spawn(move || {
                            Command::new("weston-terminal").output().unwrap();
                        });
                        return
                    }
                }
            }
            let state: &mut State = compositor.into();
            let mut seat_handle = state.seat_handle.clone().unwrap();
            seat_handle.run(|seat| {
                seat.keyboard_notify_key(key_event.time_msec(),
                                         key_event.keycode(),
                                         key_event.key_state() as u32);
            })
                .unwrap();
        }).unwrap();
    }
}

impl PointerHandler for ExPointer {
    fn on_motion_absolute(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &AbsoluteMotionEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let (x, y) = event.pos();
            state.cursor
                .run(|cursor| cursor.warp_absolute(event.device(), x, y))
                .unwrap();
        }).unwrap();
    }

    fn on_motion(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &MotionEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let (delta_x, delta_y) = event.delta();
            state.cursor
                .run(|cursor| {
                    cursor.move_to(event.device(), delta_x, delta_y);
                })
                .unwrap();
        }).unwrap();
    }

    fn on_button(&mut self, compositor: CompositorHandle, _: PointerHandle, _: &ButtonEvent) {
        with_handles!([(compositor: {compositor})] => {
        let state: &mut State = compositor.into();
        let mut seat_handle = state.seat_handle.clone().unwrap();
        let mut keyboard = state.keyboard.clone().unwrap();
        let mut surface =
            state.shells[0].run(|shell| {
                                    match shell.state() {
                                        Some(&mut XdgV6ShellState::TopLevel(ref mut toplevel)) => {
                                            toplevel.set_activated(true);
                                        }
                                        _ => {}
                                    }

                                    shell.surface()
                                })
                           .unwrap();
        seat_handle.run(|seat| {
                            keyboard.run(|keyboard| {
                                             surface.run(|surface| {
                                                 seat.set_keyboard(keyboard.input_device());
                                                 seat.keyboard_notify_enter(surface,
                                                    &mut keyboard.keycodes(),
                                                    &mut keyboard.get_modifier_masks())
                                             })
                                                    .unwrap();
                                         })
                                    .unwrap();
                        })
                   .unwrap();
        }).unwrap();
    }
}

impl OutputHandler for ExOutput {
    fn on_frame(&mut self, compositor: CompositorHandle, output: OutputHandle) {
        with_handles!([(compositor: {compositor}), (output: {output})] => {
            let state: &mut State = compositor.data.downcast_mut().unwrap();
            let renderer = compositor.renderer
                .as_mut()
                .expect("Compositor was not loaded with a renderer");
            let mut render_context = renderer.render(output, None);
            render_context.clear([0.25, 0.25, 0.25, 1.0]);
            render_shells(state, &mut render_context);
        }).unwrap();
    }
}

impl InputManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     _: CompositorHandle,
                     _: PointerHandle)
                     -> Option<Box<PointerHandler>> {
        Some(Box::new(ExPointer))
    }

    fn keyboard_added(&mut self,
                      compositor: CompositorHandle,
                      keyboard: KeyboardHandle)
                      -> Option<Box<KeyboardHandler>> {
        with_handles!([(compositor: {compositor}), (keyboard: {keyboard})] => {
            let state: &mut State = compositor.into();
            state.keyboard = Some(keyboard.weak_reference());
            let seat_handle = state.seat_handle.clone().unwrap();
            with_handles!([(seat: {seat_handle})] => {
                seat.set_keyboard(keyboard.input_device());
            }).unwrap();
        }).unwrap();
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(L_DEBUG, None);
    let mut cursor = Cursor::create(Box::new(CursorEx));
    let mut xcursor_manager = XCursorManager::create("default".to_string(), 24).expect("Could not create xcursor manager");
    xcursor_manager.load(1.0);
    cursor.run(|c| xcursor_manager.set_cursor_image("left_ptr".to_string(), c)).unwrap();
    let layout = OutputLayout::create(Box::new(OutputLayoutEx));

    let mut compositor =
        CompositorBuilder::new().gles2(true)
                                .input_manager(Box::new(InputManager))
                                .output_manager(Box::new(OutputManager))
                                .xdg_shell_v6_manager(Box::new(XdgV6ShellManager))
                                .build_auto(State::new(xcursor_manager, layout, cursor));

    {
        let mut seat_handle =
            Seat::create(&mut compositor, "Main Seat".into(), Box::new(SeatHandlerEx));
        seat_handle.run(|seat| {
                            seat.set_capabilities(Capability::all());
                        })
                   .unwrap();
        let state: &mut State = (&mut compositor).into();
        state.seat_handle = Some(seat_handle);
    }
    compositor.run();
}

/// Render the shells in the current compositor state on the given output.
fn render_shells(state: &mut State, renderer: &mut Renderer) {
    let shells = state.shells.clone();
    for mut shell in shells {
        with_handles!([(shell: {shell}),
                      (surface: {shell.surface()}),
                      (layout: {&mut state.layout})] => {
            let (width, height) = surface.current_state().size();
            let (render_width, render_height) =
                (width * renderer.output.scale() as i32,
                 height * renderer.output.scale() as i32);
            let (lx, ly) = (0.0, 0.0);
            let render_box = Area::new(Origin::new(lx as i32, ly as i32),
                                       Size::new(render_width,
                                                 render_height));
            if layout.intersects(renderer.output, render_box) {
                let transform = renderer.output.get_transform().invert();
                let matrix = project_box(render_box,
                                         transform,
                                         0.0,
                                         renderer.output
                                         .transform_matrix());
                renderer.render_texture_with_matrix(&surface.texture(),
                                                    matrix);
                let start = SystemTime::now();
                let now = start.duration_since(UNIX_EPOCH)
                    .expect("Time went backwards");
                surface.send_frame_done(now);
            }
        }).unwrap();
    }
}
<commit_msg>xdg-shell-example: with_handles in button handler<commit_after>#[macro_use]
extern crate wlroots;

use std::process::Command;
use std::thread;
use std::time::{SystemTime, UNIX_EPOCH};

use wlroots::{project_box, Area, Capability, CompositorBuilder, CompositorHandle, Cursor,
              CursorHandle, CursorHandler, InputManagerHandler, KeyboardHandle, KeyboardHandler,
              Origin, OutputBuilder, OutputBuilderResult, OutputHandle, OutputHandler,
              OutputLayout, OutputLayoutHandle, OutputLayoutHandler, OutputManagerHandler,
              PointerHandle, PointerHandler, Renderer, Seat, SeatHandle, SeatHandler, Size,
              XCursorManager, XdgV6ShellHandler, XdgV6ShellManagerHandler, XdgV6ShellState,
              XdgV6ShellSurfaceHandle};
use wlroots::key_events::KeyEvent;
use wlroots::pointer_events::{ButtonEvent, MotionEvent, AbsoluteMotionEvent};
use wlroots::utils::{init_logging, L_DEBUG};
use wlroots::wlroots_sys::wlr_key_state::WLR_KEY_PRESSED;
use wlroots::xkbcommon::xkb::keysyms::{KEY_Escape, KEY_F1};

struct State {
    xcursor_manager: XCursorManager,
    keyboard: Option<KeyboardHandle>,
    layout: OutputLayoutHandle,
    cursor: CursorHandle,
    shells: Vec<XdgV6ShellSurfaceHandle>,
    seat_handle: Option<SeatHandle>
}

impl State {
    fn new(xcursor_manager: XCursorManager, layout: OutputLayoutHandle, cursor: CursorHandle) -> Self {
        State { xcursor_manager,
                layout,
                cursor,
                keyboard: None,
                seat_handle: None,
                shells: vec![] }
    }
}

compositor_data!(State);

struct SeatHandlerEx;

struct CursorEx;

impl CursorHandler for CursorEx {}

impl SeatHandler for SeatHandlerEx {}

struct XdgV6ShellHandlerEx;
struct XdgV6ShellManager;
struct OutputLayoutEx;

impl OutputLayoutHandler for OutputLayoutEx {}

impl XdgV6ShellHandler for XdgV6ShellHandlerEx {}
impl XdgV6ShellManagerHandler for XdgV6ShellManager {
    fn new_surface(&mut self,
                   compositor: CompositorHandle,
                   shell: XdgV6ShellSurfaceHandle)
                   -> Option<Box<XdgV6ShellHandler>> {
        with_handles!([(compositor: {compositor}), (shell: {shell})] => {
            shell.ping();
            let state: &mut State = compositor.into();
            state.shells.push(shell.weak_reference());
            with_handles!([(layout: {&mut state.layout})] => {
                for (mut output, _) in layout.outputs() {
                    with_handles!([(output: {output})] =>{
                        output.schedule_frame()
                    }).ok();
                }
            }).expect("Layout was destroyed");
        }).unwrap();
        Some(Box::new(XdgV6ShellHandlerEx))
    }

    fn surface_destroyed(&mut self, compositor: CompositorHandle, shell: XdgV6ShellSurfaceHandle) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let weak = shell;
            if let Some(index) = state.shells.iter().position(|s| *s == weak) {
                state.shells.remove(index);
            }
        }).unwrap();
    }
}

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExPointer;

struct ExKeyboardHandler;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor: CompositorHandle,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let mut result = builder.build_best_mode(ExOutput);
        with_handles!([(compositor: {compositor}), (output: {&mut result.output})] => {
            let state: &mut State = compositor.data.downcast_mut().unwrap();
            let xcursor_manager = &mut state.xcursor_manager;
            // TODO use output config if present instead of auto
            let layout = &mut state.layout;
            let cursor = &mut state.cursor;
            with_handles!([(layout: {layout}), (cursor: {cursor})] => {
                layout.add_auto(output);
                cursor.attach_output_layout(layout);
                xcursor_manager.load(output.scale());
                xcursor_manager.set_cursor_image("left_ptr".to_string(), cursor);
                let (x, y) = cursor.coords();
                // https://en.wikipedia.org/wiki/Mouse_warping
                cursor.warp(None, x, y);
            }).expect("Layout was destroyed");
        }).unwrap();
        Some(result)
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self,
              mut compositor: CompositorHandle,
              _: KeyboardHandle,
              key_event: &KeyEvent) {
        with_handles!([(compositor: {&mut compositor})] => {
            for key in key_event.pressed_keys() {
                if key == KEY_Escape {
                    compositor.terminate();
                } else if key_event.key_state() == WLR_KEY_PRESSED {
                    if key == KEY_F1 {
                        thread::spawn(move || {
                            Command::new("weston-terminal").output().unwrap();
                        });
                        return
                    }
                }
            }
            let state: &mut State = compositor.into();
            let mut seat_handle = state.seat_handle.clone().unwrap();
            seat_handle.run(|seat| {
                seat.keyboard_notify_key(key_event.time_msec(),
                                         key_event.keycode(),
                                         key_event.key_state() as u32);
            })
                .unwrap();
        }).unwrap();
    }
}

impl PointerHandler for ExPointer {
    fn on_motion_absolute(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &AbsoluteMotionEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let (x, y) = event.pos();
            state.cursor
                .run(|cursor| cursor.warp_absolute(event.device(), x, y))
                .unwrap();
        }).unwrap();
    }

    fn on_motion(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &MotionEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let (delta_x, delta_y) = event.delta();
            state.cursor
                .run(|cursor| {
                    cursor.move_to(event.device(), delta_x, delta_y);
                })
                .unwrap();
        }).unwrap();
    }

    fn on_button(&mut self, compositor: CompositorHandle, _: PointerHandle, _: &ButtonEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let seat = state.seat_handle.clone().unwrap();
            let keyboard = state.keyboard.clone().unwrap();
            let surface =
                state.shells[0].run(|shell| {
                    match shell.state() {
                        Some(&mut XdgV6ShellState::TopLevel(ref mut toplevel)) => {
                            toplevel.set_activated(true);
                        }
                        _ => {}
                    }

                    shell.surface()
                })
            .unwrap();
            with_handles!([(seat: {seat}), (keyboard: {keyboard}), (surface: {surface})] => {
                seat.set_keyboard(keyboard.input_device());
                seat.keyboard_notify_enter(surface,
                                           &mut keyboard.keycodes(),
                                           &mut keyboard.get_modifier_masks());
            }).unwrap();
        }).unwrap();
    }
}

impl OutputHandler for ExOutput {
    fn on_frame(&mut self, compositor: CompositorHandle, output: OutputHandle) {
        with_handles!([(compositor: {compositor}), (output: {output})] => {
            let state: &mut State = compositor.data.downcast_mut().unwrap();
            let renderer = compositor.renderer
                .as_mut()
                .expect("Compositor was not loaded with a renderer");
            let mut render_context = renderer.render(output, None);
            render_context.clear([0.25, 0.25, 0.25, 1.0]);
            render_shells(state, &mut render_context);
        }).unwrap();
    }
}

impl InputManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     _: CompositorHandle,
                     _: PointerHandle)
                     -> Option<Box<PointerHandler>> {
        Some(Box::new(ExPointer))
    }

    fn keyboard_added(&mut self,
                      compositor: CompositorHandle,
                      keyboard: KeyboardHandle)
                      -> Option<Box<KeyboardHandler>> {
        with_handles!([(compositor: {compositor}), (keyboard: {keyboard})] => {
            let state: &mut State = compositor.into();
            state.keyboard = Some(keyboard.weak_reference());
            let seat_handle = state.seat_handle.clone().unwrap();
            with_handles!([(seat: {seat_handle})] => {
                seat.set_keyboard(keyboard.input_device());
            }).unwrap();
        }).unwrap();
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(L_DEBUG, None);
    let mut cursor = Cursor::create(Box::new(CursorEx));
    let mut xcursor_manager = XCursorManager::create("default".to_string(), 24).expect("Could not create xcursor manager");
    xcursor_manager.load(1.0);
    cursor.run(|c| xcursor_manager.set_cursor_image("left_ptr".to_string(), c)).unwrap();
    let layout = OutputLayout::create(Box::new(OutputLayoutEx));

    let mut compositor =
        CompositorBuilder::new().gles2(true)
                                .input_manager(Box::new(InputManager))
                                .output_manager(Box::new(OutputManager))
                                .xdg_shell_v6_manager(Box::new(XdgV6ShellManager))
                                .build_auto(State::new(xcursor_manager, layout, cursor));

    {
        let mut seat_handle =
            Seat::create(&mut compositor, "seat0".into(), Box::new(SeatHandlerEx));
        seat_handle.run(|seat| {
                            seat.set_capabilities(Capability::all());
                        })
                   .unwrap();
        let state: &mut State = (&mut compositor).into();
        state.seat_handle = Some(seat_handle);
    }
    compositor.run();
}

/// Render the shells in the current compositor state on the given output.
fn render_shells(state: &mut State, renderer: &mut Renderer) {
    let shells = state.shells.clone();
    for mut shell in shells {
        with_handles!([(shell: {shell}),
                      (surface: {shell.surface()}),
                      (layout: {&mut state.layout})] => {
            let (width, height) = surface.current_state().size();
            let (render_width, render_height) =
                (width * renderer.output.scale() as i32,
                 height * renderer.output.scale() as i32);
            let (lx, ly) = (0.0, 0.0);
            let render_box = Area::new(Origin::new(lx as i32, ly as i32),
                                       Size::new(render_width,
                                                 render_height));
            if layout.intersects(renderer.output, render_box) {
                let transform = renderer.output.get_transform().invert();
                let matrix = project_box(render_box,
                                         transform,
                                         0.0,
                                         renderer.output
                                         .transform_matrix());
                renderer.render_texture_with_matrix(&surface.texture(),
                                                    matrix);
                let start = SystemTime::now();
                let now = start.duration_since(UNIX_EPOCH)
                    .expect("Time went backwards");
                surface.send_frame_done(now);
            }
        }).unwrap();
    }
}
<|endoftext|>