2017-10-20 18:46:42 +11:00
|
|
|
use std::sync::{Arc, Mutex, Weak};
|
2015-12-13 21:43:39 +11:00
|
|
|
|
2017-07-06 00:23:10 +10:00
|
|
|
use wayland_client::protocol::{wl_display,wl_surface};
|
2017-10-20 18:46:42 +11:00
|
|
|
use wayland_client::{Proxy, StateToken};
|
2015-12-13 21:43:39 +11:00
|
|
|
|
2017-09-07 18:33:46 +10:00
|
|
|
use {CreationError, MouseCursor, CursorState, WindowAttributes};
|
2016-10-08 23:51:29 +11:00
|
|
|
use platform::MonitorId as PlatformMonitorId;
|
2017-08-29 11:08:12 +10:00
|
|
|
use window::MonitorId as RootMonitorId;
|
2015-12-09 08:54:06 +11:00
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
use super::{EventsLoop, WindowId, make_wid, MonitorId};
|
2017-11-04 03:35:29 +11:00
|
|
|
use super::wayland_window::{Frame, FrameImplementation, State as FrameState};
|
2017-10-20 18:46:42 +11:00
|
|
|
use super::event_loop::StateContext;
|
2015-12-09 08:54:06 +11:00
|
|
|
|
|
|
|
pub struct Window {
|
2017-10-20 18:46:42 +11:00
|
|
|
surface: wl_surface::WlSurface,
|
2017-11-04 03:35:29 +11:00
|
|
|
frame: Arc<Mutex<Frame>>,
|
2017-10-20 18:46:42 +11:00
|
|
|
monitors: Arc<Mutex<MonitorList>>,
|
|
|
|
size: Arc<Mutex<(u32, u32)>>,
|
|
|
|
kill_switch: (Arc<Mutex<bool>>, Arc<Mutex<bool>>),
|
2017-10-26 03:28:24 +11:00
|
|
|
display: Arc<wl_display::WlDisplay>,
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Window {
|
2017-09-01 19:04:57 +10:00
|
|
|
pub fn new(evlp: &EventsLoop, attributes: &WindowAttributes) -> Result<Window, CreationError>
|
2015-12-09 08:54:06 +11:00
|
|
|
{
|
2016-10-08 23:51:29 +11:00
|
|
|
let (width, height) = attributes.dimensions.unwrap_or((800,600));
|
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
// Create the decorated surface
|
|
|
|
let size = Arc::new(Mutex::new((width, height)));
|
|
|
|
let store_token = evlp.store.clone();
|
2017-11-04 03:35:29 +11:00
|
|
|
let (surface, mut frame) = evlp.create_window(
|
|
|
|
width, height, decorated_impl(),
|
|
|
|
|surface| FrameIData {
|
2017-10-20 18:46:42 +11:00
|
|
|
surface: surface.clone().unwrap(),
|
|
|
|
store_token: store_token.clone()
|
|
|
|
}
|
|
|
|
);
|
|
|
|
// Check for fullscreen requirements
|
2017-09-28 00:31:46 +10:00
|
|
|
if let Some(RootMonitorId { inner: PlatformMonitorId::Wayland(ref monitor_id) }) = attributes.fullscreen {
|
2017-10-20 18:46:42 +11:00
|
|
|
let info = monitor_id.info.lock().unwrap();
|
2017-11-04 03:35:29 +11:00
|
|
|
frame.set_state(FrameState::Fullscreen(Some(&info.output)));
|
|
|
|
} else if attributes.maximized {
|
|
|
|
frame.set_state(FrameState::Maximized);
|
2017-09-28 00:31:46 +10:00
|
|
|
}
|
2017-11-04 03:35:29 +11:00
|
|
|
|
|
|
|
// set decorations
|
|
|
|
frame.set_decorate(attributes.decorations);
|
|
|
|
|
|
|
|
// min-max dimensions
|
|
|
|
frame.set_min_size(attributes.min_dimensions.map(|(w, h)| (w as i32, h as i32)));
|
|
|
|
frame.set_max_size(attributes.max_dimensions.map(|(w, h)| (w as i32, h as i32)));
|
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
// setup the monitor tracking
|
|
|
|
let monitor_list = Arc::new(Mutex::new(MonitorList::default()));
|
|
|
|
{
|
|
|
|
let mut evq = evlp.evq.borrow_mut();
|
|
|
|
let idata = (evlp.ctxt_token.clone(), monitor_list.clone());
|
|
|
|
evq.register(&surface, surface_impl(), idata);
|
|
|
|
}
|
2016-10-08 23:51:29 +11:00
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
let kill_switch = Arc::new(Mutex::new(false));
|
2017-11-04 03:35:29 +11:00
|
|
|
let frame = Arc::new(Mutex::new(frame));
|
2017-10-20 18:46:42 +11:00
|
|
|
|
|
|
|
{
|
|
|
|
let mut evq = evlp.evq.borrow_mut();
|
|
|
|
evq.state().get_mut(&store_token).windows.push(InternalWindow {
|
|
|
|
closed: false,
|
|
|
|
newsize: None,
|
|
|
|
need_refresh: false,
|
2017-11-04 03:35:29 +11:00
|
|
|
need_frame_refresh: true,
|
2017-10-20 18:46:42 +11:00
|
|
|
surface: surface.clone().unwrap(),
|
|
|
|
kill_switch: kill_switch.clone(),
|
2017-11-04 03:35:29 +11:00
|
|
|
frame: Arc::downgrade(&frame)
|
2017-10-20 18:46:42 +11:00
|
|
|
});
|
|
|
|
evq.sync_roundtrip().unwrap();
|
|
|
|
}
|
2016-10-08 23:51:29 +11:00
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
Ok(Window {
|
|
|
|
display: evlp.display.clone(),
|
|
|
|
surface: surface,
|
2017-11-04 03:35:29 +11:00
|
|
|
frame: frame,
|
2017-10-20 18:46:42 +11:00
|
|
|
monitors: monitor_list,
|
|
|
|
size: size,
|
|
|
|
kill_switch: (kill_switch, evlp.cleanup_needed.clone())
|
|
|
|
})
|
2017-03-05 00:04:01 +11:00
|
|
|
}
|
2016-10-08 23:51:29 +11:00
|
|
|
|
2017-03-05 00:04:01 +11:00
|
|
|
#[inline]
|
|
|
|
pub fn id(&self) -> WindowId {
|
|
|
|
make_wid(&self.surface)
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_title(&self, title: &str) {
|
2017-11-04 03:35:29 +11:00
|
|
|
self.frame.lock().unwrap().set_title(title.into());
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn show(&self) {
|
2015-12-13 21:43:39 +11:00
|
|
|
// TODO
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn hide(&self) {
|
2015-12-13 21:43:39 +11:00
|
|
|
// TODO
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn get_position(&self) -> Option<(i32, i32)> {
|
2015-12-13 21:43:39 +11:00
|
|
|
// Not possible with wayland
|
|
|
|
None
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn set_position(&self, _x: i32, _y: i32) {
|
2015-12-13 21:43:39 +11:00
|
|
|
// Not possible with wayland
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_inner_size(&self) -> Option<(u32, u32)> {
|
2016-10-10 01:19:06 +11:00
|
|
|
Some(self.size.lock().unwrap().clone())
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn get_outer_size(&self) -> Option<(u32, u32)> {
|
2016-10-10 01:19:06 +11:00
|
|
|
let (w, h) = self.size.lock().unwrap().clone();
|
|
|
|
let (w, h) = super::wayland_window::add_borders(w as i32, h as i32);
|
|
|
|
Some((w as u32, h as u32))
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2016-10-10 01:19:06 +11:00
|
|
|
// NOTE: This will only resize the borders, the contents must be updated by the user
|
2015-12-09 08:54:06 +11:00
|
|
|
pub fn set_inner_size(&self, x: u32, y: u32) {
|
2017-11-04 03:35:29 +11:00
|
|
|
self.frame.lock().unwrap().resize(x as i32, y as i32);
|
2017-07-06 00:23:10 +10:00
|
|
|
*(self.size.lock().unwrap()) = (x, y);
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2015-12-13 23:13:20 +11:00
|
|
|
pub fn set_cursor(&self, _cursor: MouseCursor) {
|
2015-12-13 21:43:39 +11:00
|
|
|
// TODO
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2015-12-23 00:35:55 +11:00
|
|
|
pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
|
|
|
|
use CursorState::{Grab, Normal, Hide};
|
|
|
|
// TODO : not yet possible on wayland to grab cursor
|
|
|
|
match state {
|
|
|
|
Grab => Err("Cursor cannot be grabbed on wayland yet.".to_string()),
|
|
|
|
Hide => Err("Cursor cannot be hidden on wayland yet.".to_string()),
|
|
|
|
Normal => Ok(())
|
|
|
|
}
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn hidpi_factor(&self) -> f32 {
|
2017-10-20 18:46:42 +11:00
|
|
|
let mut factor = 1.0;
|
|
|
|
let guard = self.monitors.lock().unwrap();
|
|
|
|
for monitor_id in &guard.monitors {
|
|
|
|
let info = monitor_id.info.lock().unwrap();
|
|
|
|
if info.scale > factor { factor = info.scale; }
|
|
|
|
}
|
|
|
|
factor
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2015-12-13 21:43:39 +11:00
|
|
|
pub fn set_cursor_position(&self, _x: i32, _y: i32) -> Result<(), ()> {
|
|
|
|
// TODO: not yet possible on wayland
|
2015-12-23 00:35:55 +11:00
|
|
|
Err(())
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
2016-10-08 04:52:19 +11:00
|
|
|
|
|
|
|
pub fn get_display(&self) -> &wl_display::WlDisplay {
|
2017-10-20 18:46:42 +11:00
|
|
|
&*self.display
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
2016-10-08 04:52:19 +11:00
|
|
|
|
|
|
|
pub fn get_surface(&self) -> &wl_surface::WlSurface {
|
2016-10-08 23:51:29 +11:00
|
|
|
&self.surface
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
2017-09-07 18:33:46 +10:00
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
pub fn get_current_monitor(&self) -> MonitorId {
|
|
|
|
// we don't know how much each monitor sees us so...
|
|
|
|
// just return the most recent one ?
|
|
|
|
let guard = self.monitors.lock().unwrap();
|
|
|
|
guard.monitors.last().unwrap().clone()
|
2017-09-07 18:33:46 +10:00
|
|
|
}
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
|
|
|
|
2015-12-13 21:43:39 +11:00
|
|
|
impl Drop for Window {
|
|
|
|
fn drop(&mut self) {
|
2017-10-20 18:46:42 +11:00
|
|
|
*(self.kill_switch.0.lock().unwrap()) = true;
|
|
|
|
*(self.kill_switch.1.lock().unwrap()) = true;
|
2016-10-08 23:51:29 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
/*
|
|
|
|
* Internal store for windows
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct InternalWindow {
|
|
|
|
surface: wl_surface::WlSurface,
|
|
|
|
newsize: Option<(i32, i32)>,
|
|
|
|
need_refresh: bool,
|
2017-11-04 03:35:29 +11:00
|
|
|
need_frame_refresh: bool,
|
2017-07-06 00:23:10 +10:00
|
|
|
closed: bool,
|
2017-10-20 18:46:42 +11:00
|
|
|
kill_switch: Arc<Mutex<bool>>,
|
2017-11-04 03:35:29 +11:00
|
|
|
frame: Weak<Mutex<Frame>>
|
2016-10-08 23:51:29 +11:00
|
|
|
}
|
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
pub struct WindowStore {
|
|
|
|
windows: Vec<InternalWindow>
|
|
|
|
}
|
2017-03-05 00:04:01 +11:00
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
impl WindowStore {
|
|
|
|
pub fn new() -> WindowStore {
|
|
|
|
WindowStore { windows: Vec::new() }
|
2016-10-08 23:51:29 +11:00
|
|
|
}
|
2017-07-06 00:23:10 +10:00
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
pub fn find_wid(&self, surface: &wl_surface::WlSurface) -> Option<WindowId> {
|
|
|
|
for window in &self.windows {
|
|
|
|
if surface.equals(&window.surface) {
|
|
|
|
return Some(make_wid(surface));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
2017-09-28 00:31:46 +10:00
|
|
|
}
|
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
pub fn cleanup(&mut self) {
|
|
|
|
self.windows.retain(|w| {
|
|
|
|
if *w.kill_switch.lock().unwrap() {
|
|
|
|
// window is dead, cleanup
|
|
|
|
w.surface.destroy();
|
|
|
|
false
|
|
|
|
} else {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2016-10-08 23:51:29 +11:00
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
pub fn for_each<F>(&mut self, mut f: F)
|
2017-11-04 03:35:29 +11:00
|
|
|
where F: FnMut(Option<(i32, i32)>, bool, bool, bool, WindowId, Option<&mut Frame>)
|
2016-10-08 23:51:29 +11:00
|
|
|
{
|
2017-10-20 18:46:42 +11:00
|
|
|
for window in &mut self.windows {
|
2017-11-04 03:35:29 +11:00
|
|
|
let opt_arc = window.frame.upgrade();
|
2017-10-20 18:46:42 +11:00
|
|
|
let mut opt_mutex_lock = opt_arc.as_ref().map(|m| m.lock().unwrap());
|
|
|
|
f(
|
|
|
|
window.newsize.take(),
|
|
|
|
window.need_refresh,
|
2017-11-04 03:35:29 +11:00
|
|
|
window.need_frame_refresh,
|
2017-10-20 18:46:42 +11:00
|
|
|
window.closed,
|
|
|
|
make_wid(&window.surface),
|
|
|
|
opt_mutex_lock.as_mut().map(|m| &mut **m)
|
|
|
|
);
|
|
|
|
window.need_refresh = false;
|
|
|
|
// avoid re-spamming the event
|
|
|
|
window.closed = false;
|
|
|
|
}
|
2016-10-08 23:51:29 +11:00
|
|
|
}
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
2017-05-24 05:53:17 +10:00
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
/*
|
|
|
|
* Protocol implementation
|
|
|
|
*/
|
|
|
|
|
2017-11-04 03:35:29 +11:00
|
|
|
struct FrameIData {
|
2017-10-20 18:46:42 +11:00
|
|
|
store_token: StateToken<WindowStore>,
|
|
|
|
surface: wl_surface::WlSurface
|
|
|
|
}
|
|
|
|
|
2017-11-04 03:35:29 +11:00
|
|
|
fn decorated_impl() -> FrameImplementation<FrameIData> {
|
|
|
|
FrameImplementation {
|
2017-10-20 18:46:42 +11:00
|
|
|
configure: |evqh, idata, _, newsize| {
|
|
|
|
let store = evqh.state().get_mut(&idata.store_token);
|
|
|
|
for window in &mut store.windows {
|
|
|
|
if window.surface.equals(&idata.surface) {
|
|
|
|
window.newsize = newsize;
|
|
|
|
window.need_refresh = true;
|
2017-11-04 03:35:29 +11:00
|
|
|
window.need_frame_refresh = true;
|
2017-10-20 18:46:42 +11:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
close: |evqh, idata| {
|
|
|
|
let store = evqh.state().get_mut(&idata.store_token);
|
|
|
|
for window in &mut store.windows {
|
|
|
|
if window.surface.equals(&idata.surface) {
|
|
|
|
window.closed = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2017-11-04 03:35:29 +11:00
|
|
|
},
|
|
|
|
refresh: |evqh, idata| {
|
|
|
|
let store = evqh.state().get_mut(&idata.store_token);
|
|
|
|
for window in &mut store.windows {
|
|
|
|
if window.surface.equals(&idata.surface) {
|
|
|
|
window.need_frame_refresh = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2017-10-20 18:46:42 +11:00
|
|
|
}
|
2017-05-24 05:53:17 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
#[derive(Default)]
|
|
|
|
struct MonitorList {
|
|
|
|
monitors: Vec<MonitorId>
|
|
|
|
}
|
2017-05-24 05:53:17 +10:00
|
|
|
|
2017-10-20 18:46:42 +11:00
|
|
|
fn surface_impl() -> wl_surface::Implementation<(StateToken<StateContext>, Arc<Mutex<MonitorList>>)> {
|
|
|
|
wl_surface::Implementation {
|
|
|
|
enter: |evqh, &mut (ref token, ref list), _, output| {
|
|
|
|
let mut guard = list.lock().unwrap();
|
|
|
|
let ctxt = evqh.state().get(token);
|
|
|
|
let monitor = ctxt.monitor_id_for(output);
|
|
|
|
guard.monitors.push(monitor);
|
|
|
|
},
|
|
|
|
leave: |evqh, &mut (ref token, ref list), _, output| {
|
|
|
|
let mut guard = list.lock().unwrap();
|
|
|
|
let ctxt = evqh.state().get(token);
|
|
|
|
let monitor = ctxt.monitor_id_for(output);
|
|
|
|
guard.monitors.retain(|m| !Arc::ptr_eq(&m.info, &monitor.info));
|
|
|
|
}
|
|
|
|
}
|
2017-10-26 03:28:24 +11:00
|
|
|
}
|