use {Anchor, ConstraintAdjustment, Geometry, Gravity, Output, Point, ResizeEdge, Size, ViewState, ViewType,
Visibility};
use ffi;
use libc;
use std::borrow::Cow;
use std::cell::RefCell;
use std::cmp::{Eq, PartialEq};
use std::collections::HashMap;
use std::ffi::CStr;
use std::fmt;
use std::mem;
use std::ptr;
use std::rc::{Rc, Weak};
#[cfg(feature = "wayland")]
use wayland::WlcSurface;
#[cfg(feature = "wayland")]
use wayland_server::Client;
pub struct NotRequiredThreadSafe<T>(pub T);
unsafe impl<T> Send for NotRequiredThreadSafe<T> {}
unsafe impl<T> Sync for NotRequiredThreadSafe<T> {}
lazy_static! {
pub static ref VIEWS:
NotRequiredThreadSafe<RefCell<HashMap<libc::uintptr_t, Rc<()>>>> =
NotRequiredThreadSafe(RefCell::new(HashMap::new()));
}
#[repr(C)]
pub struct View;
#[cfg(not(feature = "unsafe-stable"))]
impl !Sync for View {}
#[cfg(not(feature = "unsafe-stable"))]
impl !Send for View {}
impl fmt::Debug for View {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "View {{ id: {} }}", handle(self))
}
}
impl View {
pub fn set_no_focus() {
unsafe { ffi::wlc_view_focus(mem::transmute::<*const libc::c_void, libc::uintptr_t>(ptr::null())) }
}
pub fn focus(&self) {
unsafe { ffi::wlc_view_focus(handle(self)) }
}
pub fn close(&self) {
unsafe { ffi::wlc_view_close(handle(self)) }
}
pub fn output(&self) -> &Output {
unsafe { &*(ffi::wlc_view_get_output(handle(self)) as *const Output) }
}
pub fn set_output(&self, output: &Output) {
unsafe {
ffi::wlc_view_set_output(handle(self),
mem::transmute::<&Output, libc::uintptr_t>(output))
}
}
pub fn send_to_back(&self) {
unsafe { ffi::wlc_view_send_to_back(handle(self)) }
}
pub fn send_below(&self, other: &View) {
unsafe { ffi::wlc_view_send_below(handle(self), handle(other)) }
}
pub fn bring_to_front(&self) {
unsafe { ffi::wlc_view_bring_to_front(handle(self)) }
}
pub fn bring_above(&self, other: &View) {
unsafe { ffi::wlc_view_bring_above(handle(self), handle(other)) }
}
pub fn visibility(&self) -> Visibility::Flags {
Visibility::Flags::from_bits_truncate(unsafe { ffi::wlc_view_get_mask(handle(self)) })
}
pub fn set_visibility(&self, visibility: Visibility::Flags) {
unsafe { ffi::wlc_view_set_mask(handle(self), visibility.bits()) }
}
pub fn geometry(&self) -> Geometry {
unsafe { Geometry::from_ffi(&*ffi::wlc_view_get_geometry(handle(self))) }
}
pub fn visible_geometry(&self) -> Geometry {
let mut geo: ffi::wlc_geometry = unsafe { mem::uninitialized() };
unsafe {
ffi::wlc_view_get_visible_geometry(handle(self), &mut geo as *mut _);
}
Geometry::from_ffi(&geo)
}
pub fn set_geometry(&self, edge: ResizeEdge::Flags, geometry: Geometry) {
unsafe { ffi::wlc_view_set_geometry(handle(self), edge.bits(), &geometry.into_ffi() as *const _) }
}
pub fn view_type(&self) -> ViewType::Flags {
ViewType::Flags::from_bits_truncate(unsafe { ffi::wlc_view_get_type(handle(self)) })
}
pub fn set_view_type(&self, view_type: ViewType::Flags, toggle: bool) {
unsafe { ffi::wlc_view_set_type(handle(self), view_type.bits(), toggle) }
}
pub fn state(&self) -> ViewState::Flags {
ViewState::Flags::from_bits_truncate(unsafe { ffi::wlc_view_get_state(handle(self)) })
}
pub fn set_state(&self, state: ViewState::Flags, toggle: bool) {
unsafe { ffi::wlc_view_set_state(handle(self), state.bits(), toggle) }
}
pub fn parent(&self) -> Option<&View> {
unsafe {
let handle = ffi::wlc_view_get_parent(handle(self));
if handle == 0 {
None
} else {
Some(&*(handle as *mut View))
}
}
}
pub fn set_parent(&self, parent: &View) {
unsafe { ffi::wlc_view_set_parent(handle(self), handle(parent)) }
}
pub fn title(&self) -> Cow<str> {
unsafe { CStr::from_ptr(ffi::wlc_view_get_title(handle(self))).to_string_lossy() }
}
pub fn class(&self) -> Cow<str> {
unsafe { CStr::from_ptr(ffi::wlc_view_get_class(handle(self))).to_string_lossy() }
}
pub fn instance(&self) -> Cow<str> {
unsafe { CStr::from_ptr(ffi::wlc_view_get_instance(handle(self))).to_string_lossy() }
}
pub fn app_id(&self) -> Cow<str> {
unsafe { CStr::from_ptr(ffi::wlc_view_get_app_id(handle(self))).to_string_lossy() }
}
pub fn pid(&self) -> libc::pid_t {
unsafe { ffi::wlc_view_get_pid(handle(self)) }
}
pub fn positioner(&self) -> Option<&Positioner> {
unsafe {
if ffi::wlc_view_positioner_get_size(handle(self)).is_null() {
None
} else {
Some(mem::transmute::<&View, &Positioner>(self))
}
}
}
#[cfg(feature = "wayland")]
pub fn wl_surface(&self) -> &WlcSurface {
unsafe { &*(ffi::wlc_view_get_surface(handle(self)) as *const WlcSurface) }
}
#[cfg(feature = "wayland")]
pub fn wl_client(&self) -> Client {
unsafe { Client::from_ptr(ffi::wlc_view_get_wl_client(handle(self)) as *mut _) }
}
pub fn weak_reference(&self) -> WeakView {
let mut views = VIEWS.0.borrow_mut();
let ref_counter = views.entry(handle(self)).or_insert_with(|| Rc::new(()));
WeakView(Rc::downgrade(ref_counter), handle(self))
}
}
#[repr(C)]
pub struct Positioner;
#[cfg(not(feature = "unsafe-stable"))]
impl !Sync for Positioner {}
#[cfg(not(feature = "unsafe-stable"))]
impl !Send for Positioner {}
impl fmt::Debug for Positioner {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Positioner of View {{ id: {} }}", handle_pos(self))
}
}
impl Positioner {
pub fn anchor(&self) -> Anchor::Flags {
Anchor::Flags::from_bits_truncate(unsafe { ffi::wlc_view_positioner_get_anchor(handle_pos(self)) })
}
pub fn anchor_rect(&self) -> Geometry {
unsafe { Geometry::from_ffi(&*ffi::wlc_view_positioner_get_anchor_rect(handle_pos(self))) }
}
pub fn constraint_adjustment(&self) -> ConstraintAdjustment::Flags {
ConstraintAdjustment::Flags::from_bits_truncate(
unsafe {
ffi::wlc_view_positioner_get_constraint_adjustment(
handle_pos(self)
)
}
)
}
pub fn gravity(&self) -> Gravity::Flags {
Gravity::Flags::from_bits_truncate(unsafe { ffi::wlc_view_positioner_get_gravity(handle_pos(self)) })
}
pub fn offset(&self) -> Point {
unsafe { Point::from_ffi(&*ffi::wlc_view_positioner_get_offset(handle_pos(self))) }
}
pub fn size(&self) -> Size {
unsafe { Size::from_ffi(&*ffi::wlc_view_positioner_get_size(handle_pos(self))) }
}
}
#[derive(Clone)]
pub struct WeakView(Weak<()>, ffi::wlc_handle);
impl WeakView {
pub unsafe fn upgrade(&self) -> Option<&View> {
let test = self.0.clone().upgrade();
match test {
Some(_) => Some(from_handle(self.1)),
None => None,
}
}
pub fn run<F, R>(&self, runner: F) -> Option<R>
where F: FnOnce(&View) -> R
{
let view = unsafe { self.upgrade() };
match view {
Some(view) => Some(runner(view)),
None => None,
}
}
}
impl fmt::Debug for WeakView {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "WeakView {{ id: {} }}", self.1)
}
}
#[cfg(not(feature = "unsafe-stable"))]
impl !Send for WeakView {}
#[cfg(not(feature = "unsafe-stable"))]
impl !Sync for WeakView {}
pub fn from_handle<'a>(handle: ffi::wlc_handle) -> &'a mut View {
unsafe { &mut *(handle as *mut View) }
}
pub fn handle(view: &View) -> ffi::wlc_handle {
unsafe { mem::transmute(view) }
}
pub fn handle_pos(pos: &Positioner) -> ffi::wlc_handle {
unsafe { mem::transmute(pos) }
}
impl PartialEq for View {
fn eq(&self, other: &View) -> bool {
handle(self) == handle(other)
}
}
impl Eq for View {}
impl PartialEq<WeakView> for View {
fn eq(&self, other: &WeakView) -> bool {
handle(self) == other.1
}
}
impl PartialEq<View> for WeakView {
fn eq(&self, other: &View) -> bool {
self.1 == handle(other)
}
}
impl PartialEq for WeakView {
fn eq(&self, other: &WeakView) -> bool {
self.1 == other.1
}
}
impl Eq for WeakView {}
use std::hash::*;
impl Hash for View {
fn hash<H: Hasher>(&self, state: &mut H) {
handle(self).hash(state);
}
}
impl Hash for WeakView {
fn hash<H: Hasher>(&self, state: &mut H) {
self.1.hash(state);
}
}