2017-10-20 18:46:42 +11:00
|
|
|
use std::cell::RefCell;
|
2017-09-01 03:43:24 +10:00
|
|
|
use std::collections::VecDeque;
|
2018-05-14 22:14:57 +10:00
|
|
|
use std::fmt;
|
2017-05-25 23:19:13 +10:00
|
|
|
use std::sync::{Arc, Mutex, Weak};
|
2017-10-20 18:46:42 +11:00
|
|
|
use std::sync::atomic::{AtomicBool, Ordering};
|
|
|
|
|
2018-06-15 09:42:18 +10:00
|
|
|
use {ControlFlow, EventsLoopClosed, PhysicalPosition, PhysicalSize};
|
2017-03-05 00:04:01 +11:00
|
|
|
|
2017-11-11 20:03:42 +11:00
|
|
|
use super::WindowId;
|
2017-10-20 18:46:42 +11:00
|
|
|
use super::window::WindowStore;
|
2017-03-05 00:04:01 +11:00
|
|
|
|
2018-05-06 03:36:34 +10:00
|
|
|
use sctk::Environment;
|
|
|
|
use sctk::output::OutputMgr;
|
2018-05-12 21:58:11 +10:00
|
|
|
use sctk::reexports::client::{Display, EventQueue, GlobalEvent, Proxy, ConnectError};
|
2018-05-06 03:36:34 +10:00
|
|
|
use sctk::reexports::client::commons::Implementation;
|
|
|
|
use sctk::reexports::client::protocol::{wl_keyboard, wl_output, wl_pointer, wl_registry, wl_seat,
|
|
|
|
wl_touch};
|
2017-03-11 09:22:59 +11:00
|
|
|
|
2018-05-06 03:36:34 +10:00
|
|
|
use sctk::reexports::client::protocol::wl_display::RequestsTrait as DisplayRequests;
|
2017-03-11 09:22:59 +11:00
|
|
|
|
2017-03-05 00:04:01 +11:00
|
|
|
pub struct EventsLoopSink {
|
2018-05-06 03:36:34 +10:00
|
|
|
buffer: VecDeque<::Event>,
|
2017-03-05 00:04:01 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl EventsLoopSink {
|
2018-05-06 03:36:34 +10:00
|
|
|
pub fn new() -> EventsLoopSink {
|
2017-10-20 18:46:42 +11:00
|
|
|
EventsLoopSink {
|
2018-05-06 03:36:34 +10:00
|
|
|
buffer: VecDeque::new(),
|
2017-09-28 00:31:46 +10:00
|
|
|
}
|
2017-03-05 00:04:01 +11:00
|
|
|
}
|
|
|
|
|
2017-03-11 09:22:59 +11:00
|
|
|
pub fn send_event(&mut self, evt: ::WindowEvent, wid: WindowId) {
|
2017-03-05 00:04:01 +11:00
|
|
|
let evt = ::Event::WindowEvent {
|
|
|
|
event: evt,
|
2018-05-06 03:36:34 +10:00
|
|
|
window_id: ::WindowId(::platform::WindowId::Wayland(wid)),
|
2017-03-05 00:04:01 +11:00
|
|
|
};
|
2017-09-28 00:31:46 +10:00
|
|
|
self.buffer.push_back(evt);
|
2017-03-05 00:04:01 +11:00
|
|
|
}
|
|
|
|
|
2017-09-28 00:31:46 +10:00
|
|
|
pub fn send_raw_event(&mut self, evt: ::Event) {
|
|
|
|
self.buffer.push_back(evt);
|
2017-03-05 00:04:01 +11:00
|
|
|
}
|
|
|
|
|
2018-05-06 03:36:34 +10:00
|
|
|
fn empty_with<F>(&mut self, callback: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(::Event),
|
|
|
|
{
|
2017-09-28 00:31:46 +10:00
|
|
|
for evt in self.buffer.drain(..) {
|
|
|
|
callback(evt)
|
|
|
|
}
|
2017-03-05 00:04:01 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct EventsLoop {
|
2017-10-20 18:46:42 +11:00
|
|
|
// The Event Queue
|
|
|
|
pub evq: RefCell<EventQueue>,
|
2017-09-28 00:31:46 +10:00
|
|
|
// our sink, shared with some handlers, buffering the events
|
2017-03-05 00:04:01 +11:00
|
|
|
sink: Arc<Mutex<EventsLoopSink>>,
|
2017-05-25 23:19:13 +10:00
|
|
|
// Whether or not there is a pending `Awakened` event to be emitted.
|
|
|
|
pending_wakeup: Arc<AtomicBool>,
|
2017-10-20 18:46:42 +11:00
|
|
|
// The window store
|
2018-05-06 03:36:34 +10:00
|
|
|
pub store: Arc<Mutex<WindowStore>>,
|
2017-10-20 18:46:42 +11:00
|
|
|
// the env
|
2018-05-06 03:36:34 +10:00
|
|
|
pub env: Environment,
|
2017-10-20 18:46:42 +11:00
|
|
|
// a cleanup switch to prune dead windows
|
2017-10-26 03:28:24 +11:00
|
|
|
pub cleanup_needed: Arc<Mutex<bool>>,
|
|
|
|
// The wayland display
|
2018-05-06 03:36:34 +10:00
|
|
|
pub display: Arc<Display>,
|
|
|
|
// The list of seats
|
|
|
|
pub seats: Arc<Mutex<Vec<(u32, Proxy<wl_seat::WlSeat>)>>>,
|
2017-05-25 23:19:13 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
// A handle that can be sent across threads and used to wake up the `EventsLoop`.
|
|
|
|
//
|
|
|
|
// We should only try and wake up the `EventsLoop` if it still exists, so we hold Weak ptrs.
|
2017-10-26 05:03:57 +11:00
|
|
|
#[derive(Clone)]
|
2017-05-25 23:19:13 +10:00
|
|
|
pub struct EventsLoopProxy {
|
2018-05-06 03:36:34 +10:00
|
|
|
display: Weak<Display>,
|
2017-05-25 23:19:13 +10:00
|
|
|
pending_wakeup: Weak<AtomicBool>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EventsLoopProxy {
|
|
|
|
// Causes the `EventsLoop` to stop blocking on `run_forever` and emit an `Awakened` event.
|
|
|
|
//
|
|
|
|
// Returns `Err` if the associated `EventsLoop` no longer exists.
|
|
|
|
pub fn wakeup(&self) -> Result<(), EventsLoopClosed> {
|
2017-10-20 18:46:42 +11:00
|
|
|
let display = self.display.upgrade();
|
2017-05-25 23:19:13 +10:00
|
|
|
let wakeup = self.pending_wakeup.upgrade();
|
2017-10-20 18:46:42 +11:00
|
|
|
match (display, wakeup) {
|
|
|
|
(Some(display), Some(wakeup)) => {
|
2017-05-25 23:19:13 +10:00
|
|
|
// Update the `EventsLoop`'s `pending_wakeup` flag.
|
2017-10-20 18:46:42 +11:00
|
|
|
wakeup.store(true, Ordering::Relaxed);
|
2017-05-25 23:19:13 +10:00
|
|
|
// Cause the `EventsLoop` to break from `dispatch` if it is currently blocked.
|
2018-05-06 03:36:34 +10:00
|
|
|
let _ = display.sync();
|
2017-10-20 18:46:42 +11:00
|
|
|
display.flush().map_err(|_| EventsLoopClosed)?;
|
2017-05-25 23:19:13 +10:00
|
|
|
Ok(())
|
2018-05-06 03:36:34 +10:00
|
|
|
}
|
2017-05-25 23:19:13 +10:00
|
|
|
_ => Err(EventsLoopClosed),
|
|
|
|
}
|
|
|
|
}
|
2017-03-05 00:04:01 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl EventsLoop {
|
2018-05-12 21:58:11 +10:00
|
|
|
pub fn new() -> Result<EventsLoop, ConnectError> {
|
|
|
|
let (display, mut event_queue) = Display::connect_to_env()?;
|
2017-10-20 18:46:42 +11:00
|
|
|
|
2017-09-28 00:31:46 +10:00
|
|
|
let sink = Arc::new(Mutex::new(EventsLoopSink::new()));
|
2018-05-06 03:36:34 +10:00
|
|
|
let store = Arc::new(Mutex::new(WindowStore::new()));
|
|
|
|
let seats = Arc::new(Mutex::new(Vec::new()));
|
2017-09-28 00:31:46 +10:00
|
|
|
|
2018-05-06 03:36:34 +10:00
|
|
|
let env = Environment::from_registry_with_cb(
|
|
|
|
display.get_registry().unwrap(),
|
|
|
|
&mut event_queue,
|
|
|
|
SeatManager {
|
|
|
|
sink: sink.clone(),
|
|
|
|
store: store.clone(),
|
|
|
|
seats: seats.clone(),
|
|
|
|
},
|
|
|
|
).unwrap();
|
2017-10-20 18:46:42 +11:00
|
|
|
|
2018-05-12 21:58:11 +10:00
|
|
|
Ok(EventsLoop {
|
2017-10-20 18:46:42 +11:00
|
|
|
display: Arc::new(display),
|
|
|
|
evq: RefCell::new(event_queue),
|
2017-03-11 09:22:59 +11:00
|
|
|
sink: sink,
|
2017-05-25 23:19:13 +10:00
|
|
|
pending_wakeup: Arc::new(AtomicBool::new(false)),
|
2017-10-20 18:46:42 +11:00
|
|
|
store: store,
|
2018-05-06 03:36:34 +10:00
|
|
|
env: env,
|
|
|
|
cleanup_needed: Arc::new(Mutex::new(false)),
|
|
|
|
seats: seats,
|
|
|
|
})
|
2017-09-01 19:04:57 +10:00
|
|
|
}
|
|
|
|
|
2017-05-25 23:19:13 +10:00
|
|
|
pub fn create_proxy(&self) -> EventsLoopProxy {
|
|
|
|
EventsLoopProxy {
|
2017-10-20 18:46:42 +11:00
|
|
|
display: Arc::downgrade(&self.display),
|
2017-05-25 23:19:13 +10:00
|
|
|
pending_wakeup: Arc::downgrade(&self.pending_wakeup),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-01 03:43:24 +10:00
|
|
|
pub fn poll_events<F>(&mut self, mut callback: F)
|
2018-05-06 03:36:34 +10:00
|
|
|
where
|
|
|
|
F: FnMut(::Event),
|
2017-03-05 00:04:01 +11:00
|
|
|
{
|
2017-10-20 18:46:42 +11:00
|
|
|
// send pending events to the server
|
|
|
|
self.display.flush().expect("Wayland connection lost.");
|
2017-03-05 00:04:01 +11:00
|
|
|
|
2017-09-28 00:31:46 +10:00
|
|
|
// dispatch any pre-buffered events
|
|
|
|
self.sink.lock().unwrap().empty_with(&mut callback);
|
2017-03-05 00:04:01 +11:00
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
// try to read pending events
|
|
|
|
if let Some(h) = self.evq.get_mut().prepare_read() {
|
|
|
|
h.read_events().expect("Wayland connection lost.");
|
|
|
|
}
|
|
|
|
// dispatch wayland events
|
2018-05-06 03:36:34 +10:00
|
|
|
self.evq
|
|
|
|
.get_mut()
|
|
|
|
.dispatch_pending()
|
|
|
|
.expect("Wayland connection lost.");
|
2017-09-28 00:31:46 +10:00
|
|
|
self.post_dispatch_triggers();
|
2017-03-11 09:22:59 +11:00
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
// dispatch buffered events to client
|
2017-09-28 00:31:46 +10:00
|
|
|
self.sink.lock().unwrap().empty_with(&mut callback);
|
2017-03-05 00:04:01 +11:00
|
|
|
}
|
|
|
|
|
2017-06-02 21:19:45 +10:00
|
|
|
pub fn run_forever<F>(&mut self, mut callback: F)
|
2018-05-06 03:36:34 +10:00
|
|
|
where
|
|
|
|
F: FnMut(::Event) -> ControlFlow,
|
2017-03-05 00:04:01 +11:00
|
|
|
{
|
2017-10-20 18:46:42 +11:00
|
|
|
// send pending events to the server
|
|
|
|
self.display.flush().expect("Wayland connection lost.");
|
2017-03-05 00:04:01 +11:00
|
|
|
|
2017-06-02 21:19:45 +10:00
|
|
|
// Check for control flow by wrapping the callback.
|
|
|
|
let control_flow = ::std::cell::Cell::new(ControlFlow::Continue);
|
2018-05-06 03:36:34 +10:00
|
|
|
let mut callback = |event| {
|
|
|
|
if let ControlFlow::Break = callback(event) {
|
|
|
|
control_flow.set(ControlFlow::Break);
|
|
|
|
}
|
2017-06-02 21:19:45 +10:00
|
|
|
};
|
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
// dispatch any pre-buffered events
|
|
|
|
self.post_dispatch_triggers();
|
2017-09-28 00:31:46 +10:00
|
|
|
self.sink.lock().unwrap().empty_with(&mut callback);
|
2017-03-05 00:04:01 +11:00
|
|
|
|
2017-06-02 21:19:45 +10:00
|
|
|
loop {
|
2017-09-28 00:31:46 +10:00
|
|
|
// dispatch events blocking if needed
|
2018-05-06 03:36:34 +10:00
|
|
|
self.evq
|
|
|
|
.get_mut()
|
|
|
|
.dispatch()
|
|
|
|
.expect("Wayland connection lost.");
|
2017-09-28 00:31:46 +10:00
|
|
|
self.post_dispatch_triggers();
|
2017-05-25 23:19:13 +10:00
|
|
|
|
2017-09-28 00:31:46 +10:00
|
|
|
// empty buffer of events
|
|
|
|
self.sink.lock().unwrap().empty_with(&mut callback);
|
2017-03-11 09:56:31 +11:00
|
|
|
|
2017-06-20 21:25:53 +10:00
|
|
|
if let ControlFlow::Break = control_flow.get() {
|
2017-06-02 21:19:45 +10:00
|
|
|
break;
|
|
|
|
}
|
2017-03-05 00:04:01 +11:00
|
|
|
}
|
2017-03-11 09:22:59 +11:00
|
|
|
}
|
2017-05-25 23:19:13 +10:00
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
pub fn get_primary_monitor(&self) -> MonitorId {
|
2018-06-17 00:14:12 +10:00
|
|
|
get_primary_monitor(&self.env.outputs)
|
2017-05-25 23:19:13 +10:00
|
|
|
}
|
2017-03-11 09:22:59 +11:00
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
|
2018-06-17 00:14:12 +10:00
|
|
|
get_available_monitors(&self.env.outputs)
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
2017-03-11 09:22:59 +11:00
|
|
|
}
|
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
/*
|
|
|
|
* Private EventsLoop Internals
|
|
|
|
*/
|
|
|
|
|
|
|
|
impl EventsLoop {
|
|
|
|
fn post_dispatch_triggers(&mut self) {
|
|
|
|
let mut sink = self.sink.lock().unwrap();
|
|
|
|
// process a possible pending wakeup call
|
|
|
|
if self.pending_wakeup.load(Ordering::Relaxed) {
|
|
|
|
sink.send_raw_event(::Event::Awakened);
|
|
|
|
self.pending_wakeup.store(false, Ordering::Relaxed);
|
2017-03-11 09:22:59 +11:00
|
|
|
}
|
2017-10-20 18:46:42 +11:00
|
|
|
// prune possible dead windows
|
|
|
|
{
|
|
|
|
let mut cleanup_needed = self.cleanup_needed.lock().unwrap();
|
|
|
|
if *cleanup_needed {
|
2018-05-06 03:36:34 +10:00
|
|
|
let pruned = self.store.lock().unwrap().cleanup();
|
2017-10-20 18:46:42 +11:00
|
|
|
*cleanup_needed = false;
|
2018-04-25 06:20:40 +10:00
|
|
|
for wid in pruned {
|
|
|
|
sink.send_event(::WindowEvent::Destroyed, wid);
|
|
|
|
}
|
2017-03-11 09:22:59 +11:00
|
|
|
}
|
|
|
|
}
|
2017-10-20 18:46:42 +11:00
|
|
|
// process pending resize/refresh
|
2018-05-06 03:36:34 +10:00
|
|
|
self.store.lock().unwrap().for_each(
|
2018-06-15 09:42:18 +10:00
|
|
|
|newsize, size, new_dpi, refresh, frame_refresh, closed, wid, frame| {
|
2017-11-04 03:35:29 +11:00
|
|
|
if let Some(frame) = frame {
|
|
|
|
if let Some((w, h)) = newsize {
|
2018-06-15 09:42:18 +10:00
|
|
|
frame.resize(w, h);
|
2017-11-04 03:35:29 +11:00
|
|
|
frame.refresh();
|
2018-06-15 09:42:18 +10:00
|
|
|
let logical_size = ::LogicalSize::new(w as f64, h as f64);
|
|
|
|
sink.send_event(::WindowEvent::Resized(logical_size), wid);
|
|
|
|
*size = (w, h);
|
2017-11-04 03:35:29 +11:00
|
|
|
} else if frame_refresh {
|
|
|
|
frame.refresh();
|
|
|
|
}
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
2018-06-15 09:42:18 +10:00
|
|
|
if let Some(dpi) = new_dpi {
|
|
|
|
sink.send_event(::WindowEvent::HiDpiFactorChanged(dpi as f64), wid);
|
|
|
|
}
|
2017-10-20 18:46:42 +11:00
|
|
|
if refresh {
|
|
|
|
sink.send_event(::WindowEvent::Refresh, wid);
|
|
|
|
}
|
|
|
|
if closed {
|
2018-04-25 06:20:40 +10:00
|
|
|
sink.send_event(::WindowEvent::CloseRequested, wid);
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
2018-05-06 03:36:34 +10:00
|
|
|
},
|
2017-10-20 18:46:42 +11:00
|
|
|
)
|
|
|
|
}
|
2017-03-11 09:22:59 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2017-10-20 18:46:42 +11:00
|
|
|
* Wayland protocol implementations
|
2017-03-11 09:22:59 +11:00
|
|
|
*/
|
|
|
|
|
2018-05-06 03:36:34 +10:00
|
|
|
struct SeatManager {
|
|
|
|
sink: Arc<Mutex<EventsLoopSink>>,
|
|
|
|
store: Arc<Mutex<WindowStore>>,
|
|
|
|
seats: Arc<Mutex<Vec<(u32, Proxy<wl_seat::WlSeat>)>>>,
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
2017-03-11 09:22:59 +11:00
|
|
|
|
2018-05-06 03:36:34 +10:00
|
|
|
impl Implementation<Proxy<wl_registry::WlRegistry>, GlobalEvent> for SeatManager {
|
|
|
|
fn receive(&mut self, evt: GlobalEvent, registry: Proxy<wl_registry::WlRegistry>) {
|
|
|
|
use self::wl_registry::RequestsTrait as RegistryRequests;
|
|
|
|
use self::wl_seat::RequestsTrait as SeatRequests;
|
|
|
|
match evt {
|
|
|
|
GlobalEvent::New {
|
|
|
|
id,
|
|
|
|
ref interface,
|
|
|
|
version,
|
|
|
|
} if interface == "wl_seat" =>
|
|
|
|
{
|
|
|
|
use std::cmp::min;
|
|
|
|
let seat = registry
|
|
|
|
.bind::<wl_seat::WlSeat>(min(version, 5), id)
|
|
|
|
.unwrap()
|
|
|
|
.implement(SeatData {
|
|
|
|
sink: self.sink.clone(),
|
|
|
|
store: self.store.clone(),
|
|
|
|
pointer: None,
|
|
|
|
keyboard: None,
|
|
|
|
touch: None,
|
|
|
|
});
|
|
|
|
self.store.lock().unwrap().new_seat(&seat);
|
|
|
|
self.seats.lock().unwrap().push((id, seat));
|
|
|
|
}
|
|
|
|
GlobalEvent::Removed { id, ref interface } if interface == "wl_seat" => {
|
|
|
|
let mut seats = self.seats.lock().unwrap();
|
|
|
|
if let Some(idx) = seats.iter().position(|&(i, _)| i == id) {
|
|
|
|
let (_, seat) = seats.swap_remove(idx);
|
|
|
|
if seat.version() >= 5 {
|
|
|
|
seat.release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => (),
|
2017-03-11 09:22:59 +11:00
|
|
|
}
|
|
|
|
}
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
2017-03-11 09:22:59 +11:00
|
|
|
|
2018-05-06 03:36:34 +10:00
|
|
|
struct SeatData {
|
2017-10-20 18:46:42 +11:00
|
|
|
sink: Arc<Mutex<EventsLoopSink>>,
|
2018-05-06 03:36:34 +10:00
|
|
|
store: Arc<Mutex<WindowStore>>,
|
|
|
|
pointer: Option<Proxy<wl_pointer::WlPointer>>,
|
|
|
|
keyboard: Option<Proxy<wl_keyboard::WlKeyboard>>,
|
|
|
|
touch: Option<Proxy<wl_touch::WlTouch>>,
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
|
|
|
|
2018-05-06 03:36:34 +10:00
|
|
|
impl Implementation<Proxy<wl_seat::WlSeat>, wl_seat::Event> for SeatData {
|
|
|
|
fn receive(&mut self, evt: wl_seat::Event, seat: Proxy<wl_seat::WlSeat>) {
|
|
|
|
use self::wl_seat::RequestsTrait as SeatRequests;
|
|
|
|
match evt {
|
|
|
|
wl_seat::Event::Name { .. } => (),
|
|
|
|
wl_seat::Event::Capabilities { capabilities } => {
|
|
|
|
// create pointer if applicable
|
|
|
|
if capabilities.contains(wl_seat::Capability::Pointer) && self.pointer.is_none() {
|
|
|
|
self.pointer = Some(super::pointer::implement_pointer(
|
|
|
|
seat.get_pointer().unwrap(),
|
|
|
|
self.sink.clone(),
|
|
|
|
self.store.clone(),
|
|
|
|
))
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
2018-05-06 03:36:34 +10:00
|
|
|
// destroy pointer if applicable
|
|
|
|
if !capabilities.contains(wl_seat::Capability::Pointer) {
|
|
|
|
if let Some(pointer) = self.pointer.take() {
|
|
|
|
if pointer.version() >= 3 {
|
|
|
|
use self::wl_pointer::RequestsTrait;
|
|
|
|
pointer.release();
|
|
|
|
}
|
|
|
|
}
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
2018-05-06 03:36:34 +10:00
|
|
|
// create keyboard if applicable
|
|
|
|
if capabilities.contains(wl_seat::Capability::Keyboard) && self.keyboard.is_none() {
|
|
|
|
self.keyboard = Some(super::keyboard::init_keyboard(
|
|
|
|
seat.get_keyboard().unwrap(),
|
|
|
|
self.sink.clone(),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
// destroy keyboard if applicable
|
|
|
|
if !capabilities.contains(wl_seat::Capability::Keyboard) {
|
|
|
|
if let Some(kbd) = self.keyboard.take() {
|
|
|
|
if kbd.version() >= 3 {
|
|
|
|
use self::wl_keyboard::RequestsTrait;
|
|
|
|
kbd.release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// create touch if applicable
|
|
|
|
if capabilities.contains(wl_seat::Capability::Touch) && self.touch.is_none() {
|
|
|
|
self.touch = Some(super::touch::implement_touch(
|
|
|
|
seat.get_touch().unwrap(),
|
|
|
|
self.sink.clone(),
|
|
|
|
self.store.clone(),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
// destroy touch if applicable
|
|
|
|
if !capabilities.contains(wl_seat::Capability::Touch) {
|
|
|
|
if let Some(touch) = self.touch.take() {
|
|
|
|
if touch.version() >= 3 {
|
|
|
|
use self::wl_touch::RequestsTrait;
|
|
|
|
touch.release();
|
|
|
|
}
|
|
|
|
}
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
|
|
|
}
|
2017-11-11 20:03:42 +11:00
|
|
|
}
|
2017-03-11 09:22:59 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-06 03:36:34 +10:00
|
|
|
impl Drop for SeatData {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
if let Some(pointer) = self.pointer.take() {
|
|
|
|
if pointer.version() >= 3 {
|
|
|
|
use self::wl_pointer::RequestsTrait;
|
|
|
|
pointer.release();
|
2017-03-11 09:22:59 +11:00
|
|
|
}
|
2018-05-06 03:36:34 +10:00
|
|
|
}
|
|
|
|
if let Some(kbd) = self.keyboard.take() {
|
|
|
|
if kbd.version() >= 3 {
|
|
|
|
use self::wl_keyboard::RequestsTrait;
|
|
|
|
kbd.release();
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
2018-05-06 03:36:34 +10:00
|
|
|
}
|
|
|
|
if let Some(touch) = self.touch.take() {
|
|
|
|
if touch.version() >= 3 {
|
|
|
|
use self::wl_touch::RequestsTrait;
|
|
|
|
touch.release();
|
2017-03-11 09:22:59 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
2017-03-11 09:22:59 +11:00
|
|
|
|
2018-05-06 03:36:34 +10:00
|
|
|
/*
|
|
|
|
* Monitor stuff
|
|
|
|
*/
|
|
|
|
|
|
|
|
pub struct MonitorId {
|
|
|
|
pub(crate) proxy: Proxy<wl_output::WlOutput>,
|
|
|
|
pub(crate) mgr: OutputMgr,
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
|
|
|
|
2018-05-06 03:36:34 +10:00
|
|
|
impl Clone for MonitorId {
|
|
|
|
fn clone(&self) -> MonitorId {
|
|
|
|
MonitorId {
|
|
|
|
proxy: self.proxy.clone(),
|
|
|
|
mgr: self.mgr.clone(),
|
2017-03-11 09:22:59 +11:00
|
|
|
}
|
|
|
|
}
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
2017-03-11 09:22:59 +11:00
|
|
|
|
2018-05-14 22:14:57 +10:00
|
|
|
impl fmt::Debug for MonitorId {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct MonitorId {
|
|
|
|
name: Option<String>,
|
|
|
|
native_identifier: u32,
|
2018-06-15 09:42:18 +10:00
|
|
|
dimensions: PhysicalSize,
|
|
|
|
position: PhysicalPosition,
|
|
|
|
hidpi_factor: i32,
|
2018-05-14 22:14:57 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
let monitor_id_proxy = MonitorId {
|
|
|
|
name: self.get_name(),
|
|
|
|
native_identifier: self.get_native_identifier(),
|
|
|
|
dimensions: self.get_dimensions(),
|
|
|
|
position: self.get_position(),
|
|
|
|
hidpi_factor: self.get_hidpi_factor(),
|
|
|
|
};
|
|
|
|
|
|
|
|
monitor_id_proxy.fmt(f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
impl MonitorId {
|
|
|
|
pub fn get_name(&self) -> Option<String> {
|
2018-05-06 03:36:34 +10:00
|
|
|
self.mgr.with_info(&self.proxy, |_, info| {
|
|
|
|
format!("{} ({})", info.model, info.make)
|
|
|
|
})
|
2017-03-11 09:22:59 +11:00
|
|
|
}
|
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
#[inline]
|
|
|
|
pub fn get_native_identifier(&self) -> u32 {
|
2018-05-06 03:36:34 +10:00
|
|
|
self.mgr.with_info(&self.proxy, |id, _| id).unwrap_or(0)
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
|
|
|
|
2018-06-15 09:42:18 +10:00
|
|
|
pub fn get_dimensions(&self) -> PhysicalSize {
|
2018-05-06 03:36:34 +10:00
|
|
|
match self.mgr.with_info(&self.proxy, |_, info| {
|
|
|
|
info.modes
|
|
|
|
.iter()
|
|
|
|
.find(|m| m.is_current)
|
|
|
|
.map(|m| m.dimensions)
|
|
|
|
}) {
|
|
|
|
Some(Some((w, h))) => (w as u32, h as u32),
|
|
|
|
_ => (0, 0),
|
2018-06-15 09:42:18 +10:00
|
|
|
}.into()
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
|
|
|
|
2018-06-15 09:42:18 +10:00
|
|
|
pub fn get_position(&self) -> PhysicalPosition {
|
2018-05-06 03:36:34 +10:00
|
|
|
self.mgr
|
|
|
|
.with_info(&self.proxy, |_, info| info.location)
|
|
|
|
.unwrap_or((0, 0))
|
2018-06-15 09:42:18 +10:00
|
|
|
.into()
|
2017-03-05 00:04:01 +11:00
|
|
|
}
|
2017-03-11 09:22:59 +11:00
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
#[inline]
|
2018-06-15 09:42:18 +10:00
|
|
|
pub fn get_hidpi_factor(&self) -> i32 {
|
2018-05-06 03:36:34 +10:00
|
|
|
self.mgr
|
2018-06-15 09:42:18 +10:00
|
|
|
.with_info(&self.proxy, |_, info| info.scale_factor)
|
|
|
|
.unwrap_or(1)
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
|
|
|
}
|
2018-06-17 00:14:12 +10:00
|
|
|
|
|
|
|
pub fn get_primary_monitor(outputs: &OutputMgr) -> MonitorId {
|
|
|
|
outputs.with_all(|list| {
|
|
|
|
if let Some(&(_, ref proxy, _)) = list.first() {
|
|
|
|
MonitorId {
|
|
|
|
proxy: proxy.clone(),
|
|
|
|
mgr: outputs.clone(),
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
panic!("No monitor is available.")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_available_monitors(outputs: &OutputMgr) -> VecDeque<MonitorId> {
|
|
|
|
outputs.with_all(|list| {
|
|
|
|
list.iter()
|
|
|
|
.map(|&(_, ref proxy, _)| MonitorId {
|
|
|
|
proxy: proxy.clone(),
|
|
|
|
mgr: outputs.clone(),
|
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
})
|
|
|
|
}
|