2016-10-08 23:51:29 +11:00
|
|
|
use std::sync::{Arc, Mutex};
|
2017-09-28 00:31:46 +10:00
|
|
|
use std::sync::atomic::{Ordering, AtomicBool};
|
2017-09-07 18:33:46 +10:00
|
|
|
use std::cmp;
|
2015-12-13 21:43:39 +11:00
|
|
|
|
2017-09-28 00:31:46 +10:00
|
|
|
use wayland_client::{EventQueueHandle, Proxy};
|
2017-07-06 00:23:10 +10:00
|
|
|
use wayland_client::protocol::{wl_display,wl_surface};
|
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;
|
2017-09-07 18:33:46 +10:00
|
|
|
use platform::wayland::MonitorId as WaylandMonitorId;
|
|
|
|
use platform::wayland::context::get_available_monitors;
|
2015-12-09 08:54:06 +11:00
|
|
|
|
2017-03-05 00:04:01 +11:00
|
|
|
use super::{WaylandContext, EventsLoop};
|
2016-10-08 23:51:29 +11:00
|
|
|
use super::wayland_window;
|
|
|
|
use super::wayland_window::DecoratedSurface;
|
2015-12-09 08:54:06 +11:00
|
|
|
|
|
|
|
pub struct Window {
|
2017-03-11 09:56:31 +11:00
|
|
|
// the global wayland context
|
2016-10-08 23:51:29 +11:00
|
|
|
ctxt: Arc<WaylandContext>,
|
2017-03-11 09:56:31 +11:00
|
|
|
// signal to advertize the EventsLoop when we are destroyed
|
2017-03-11 09:40:31 +11:00
|
|
|
cleanup_signal: Arc<AtomicBool>,
|
2017-03-11 09:56:31 +11:00
|
|
|
// our wayland surface
|
2016-10-08 23:51:29 +11:00
|
|
|
surface: Arc<wl_surface::WlSurface>,
|
2017-03-11 09:56:31 +11:00
|
|
|
// our current inner dimensions
|
2016-10-08 23:51:29 +11:00
|
|
|
size: Mutex<(u32, u32)>,
|
2017-03-11 09:56:31 +11:00
|
|
|
// the id of our DecoratedHandler in the EventQueue
|
2016-10-08 23:51:29 +11:00
|
|
|
decorated_id: usize
|
2015-12-13 21:43:39 +11:00
|
|
|
}
|
|
|
|
|
2017-03-05 00:04:01 +11:00
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
|
|
pub struct WindowId(usize);
|
2015-12-09 08:54:06 +11:00
|
|
|
|
2017-03-05 00:04:01 +11:00
|
|
|
#[inline]
|
|
|
|
pub fn make_wid(s: &wl_surface::WlSurface) -> WindowId {
|
|
|
|
WindowId(s.ptr() as usize)
|
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
|
|
|
{
|
2017-09-01 19:04:57 +10:00
|
|
|
let ctxt = evlp.context().clone();
|
2016-10-08 23:51:29 +11:00
|
|
|
let (width, height) = attributes.dimensions.unwrap_or((800,600));
|
|
|
|
|
2017-09-28 00:31:46 +10:00
|
|
|
let (surface, decorated, xdg) = ctxt.create_window::<DecoratedHandler>(width, height, attributes.decorations);
|
2016-10-08 23:51:29 +11:00
|
|
|
|
|
|
|
// init DecoratedSurface
|
2017-09-28 00:31:46 +10:00
|
|
|
let cleanup_signal = evlp.get_window_init();
|
|
|
|
|
|
|
|
let mut fullscreen_monitor = None;
|
|
|
|
if let Some(RootMonitorId { inner: PlatformMonitorId::Wayland(ref monitor_id) }) = attributes.fullscreen {
|
|
|
|
ctxt.with_output(monitor_id.clone(), |output| {
|
|
|
|
fullscreen_monitor = output.clone();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-03-05 00:04:01 +11:00
|
|
|
let decorated_id = {
|
2017-09-28 00:31:46 +10:00
|
|
|
let mut evq_guard = ctxt.evq.lock().unwrap();
|
2017-05-24 05:53:17 +10:00
|
|
|
// store the DecoratedSurface handler
|
2017-03-05 00:04:01 +11:00
|
|
|
let decorated_id = evq_guard.add_handler_with_init(decorated);
|
|
|
|
{
|
|
|
|
let mut state = evq_guard.state();
|
2017-05-24 05:53:17 +10:00
|
|
|
// initialize the DecoratedHandler
|
2017-03-05 00:04:01 +11:00
|
|
|
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(decorated_id);
|
2017-09-28 00:31:46 +10:00
|
|
|
*(decorated.handler()) = Some(DecoratedHandler::new(!xdg));
|
2017-03-05 00:04:01 +11:00
|
|
|
|
2017-03-11 09:56:31 +11:00
|
|
|
// set fullscreen if necessary
|
2017-09-28 00:31:46 +10:00
|
|
|
if let Some(output) = fullscreen_monitor {
|
|
|
|
decorated.set_fullscreen(Some(&output));
|
2017-03-05 00:04:01 +11:00
|
|
|
}
|
|
|
|
// Finally, set the decorations size
|
|
|
|
decorated.resize(width as i32, height as i32);
|
2016-10-08 23:51:29 +11:00
|
|
|
}
|
2017-09-01 03:43:24 +10:00
|
|
|
|
|
|
|
evq_guard.sync_roundtrip().unwrap();
|
|
|
|
|
2017-03-05 00:04:01 +11:00
|
|
|
decorated_id
|
|
|
|
};
|
|
|
|
let me = Window {
|
2016-10-08 23:51:29 +11:00
|
|
|
ctxt: ctxt,
|
2017-03-11 09:40:31 +11:00
|
|
|
cleanup_signal: cleanup_signal,
|
2016-10-08 23:51:29 +11:00
|
|
|
surface: surface,
|
|
|
|
size: Mutex::new((width, height)),
|
|
|
|
decorated_id: decorated_id
|
|
|
|
};
|
|
|
|
|
2017-03-11 09:56:31 +11:00
|
|
|
// register ourselves to the EventsLoop
|
2017-03-11 09:22:59 +11:00
|
|
|
evlp.register_window(me.decorated_id, me.surface.clone());
|
2016-10-08 23:51:29 +11:00
|
|
|
|
2017-03-05 00:04:01 +11:00
|
|
|
Ok(me)
|
|
|
|
}
|
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-09-28 00:31:46 +10:00
|
|
|
let mut guard = self.ctxt.evq.lock().unwrap();
|
2016-10-10 01:19:06 +11:00
|
|
|
let mut state = guard.state();
|
2017-03-04 21:14:08 +11:00
|
|
|
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(self.decorated_id);
|
2016-10-10 01:19:06 +11:00
|
|
|
decorated.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-09-28 00:31:46 +10:00
|
|
|
let mut guard = self.ctxt.evq.lock().unwrap();
|
2016-10-10 01:19:06 +11:00
|
|
|
let mut state = guard.state();
|
|
|
|
let mut decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(self.decorated_id);
|
|
|
|
decorated.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 {
|
2016-10-08 04:52:19 +11:00
|
|
|
// TODO
|
2015-12-09 08:54:06 +11:00
|
|
|
1.0
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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 {
|
2016-10-08 23:51:29 +11:00
|
|
|
&self.ctxt.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
|
|
|
|
|
|
|
pub fn get_current_monitor(&self) -> WaylandMonitorId {
|
|
|
|
let monitors = get_available_monitors(&self.ctxt);
|
|
|
|
let default = monitors[0].clone();
|
|
|
|
|
|
|
|
let (wx,wy) = match self.get_position() {
|
|
|
|
Some(val) => (cmp::max(0,val.0) as u32, cmp::max(0,val.1) as u32),
|
|
|
|
None=> return default,
|
|
|
|
};
|
|
|
|
let (ww,wh) = match self.get_outer_size() {
|
|
|
|
Some(val) => val,
|
|
|
|
None=> return default,
|
|
|
|
};
|
|
|
|
// Opposite corner coordinates
|
|
|
|
let (wxo, wyo) = (wx+ww-1, wy+wh-1);
|
|
|
|
|
|
|
|
// Find the monitor with the biggest overlap with the window
|
|
|
|
let mut overlap = 0;
|
|
|
|
let mut find = default;
|
|
|
|
for monitor in monitors {
|
|
|
|
let (mx, my) = monitor.get_position();
|
|
|
|
let (mw, mh) = monitor.get_dimensions();
|
|
|
|
let (mxo, myo) = (mx+mw-1, my+mh-1);
|
|
|
|
let (ox, oy) = (cmp::max(wx, mx), cmp::max(wy, my));
|
|
|
|
let (oxo, oyo) = (cmp::min(wxo, mxo), cmp::min(wyo, myo));
|
|
|
|
let osize = if ox <= oxo || oy <= oyo { 0 } else { (oxo-ox)*(oyo-oy) };
|
|
|
|
|
|
|
|
if osize > overlap {
|
|
|
|
overlap = osize;
|
|
|
|
find = monitor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
find
|
|
|
|
}
|
2017-09-28 00:31:46 +10:00
|
|
|
|
|
|
|
pub fn is_ready(&self) -> bool {
|
|
|
|
let mut guard = self.ctxt.evq.lock().unwrap();
|
|
|
|
let mut state = guard.state();
|
|
|
|
let mut decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(self.decorated_id);
|
|
|
|
decorated.handler().as_ref().unwrap().configured
|
|
|
|
}
|
2015-12-09 08:54:06 +11:00
|
|
|
}
|
|
|
|
|
2015-12-13 21:43:39 +11:00
|
|
|
impl Drop for Window {
|
|
|
|
fn drop(&mut self) {
|
2016-10-08 23:51:29 +11:00
|
|
|
self.surface.destroy();
|
2017-09-28 00:31:46 +10:00
|
|
|
self.cleanup_signal.store(true, Ordering::Relaxed);
|
2016-10-08 23:51:29 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-05 00:04:01 +11:00
|
|
|
pub struct DecoratedHandler {
|
2017-07-06 00:23:10 +10:00
|
|
|
newsize: Option<(u32, u32)>,
|
2017-09-28 00:31:46 +10:00
|
|
|
refresh: bool,
|
2017-07-06 00:23:10 +10:00
|
|
|
closed: bool,
|
2017-09-28 00:31:46 +10:00
|
|
|
configured: bool
|
2016-10-08 23:51:29 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl DecoratedHandler {
|
2017-09-28 00:31:46 +10:00
|
|
|
fn new(configured: bool) -> DecoratedHandler {
|
2017-07-06 00:23:10 +10:00
|
|
|
DecoratedHandler {
|
|
|
|
newsize: None,
|
2017-09-28 00:31:46 +10:00
|
|
|
refresh: false,
|
2017-07-06 00:23:10 +10:00
|
|
|
closed: false,
|
2017-09-28 00:31:46 +10:00
|
|
|
configured: configured
|
2017-07-06 00:23:10 +10:00
|
|
|
}
|
|
|
|
}
|
2017-03-05 00:04:01 +11:00
|
|
|
|
|
|
|
pub fn take_newsize(&mut self) -> Option<(u32, u32)> {
|
2016-10-08 23:51:29 +11:00
|
|
|
self.newsize.take()
|
|
|
|
}
|
2017-07-06 00:23:10 +10:00
|
|
|
|
2017-09-28 00:31:46 +10:00
|
|
|
pub fn take_refresh(&mut self) -> bool {
|
|
|
|
let refresh = self.refresh;
|
|
|
|
self.refresh = false;
|
|
|
|
refresh
|
|
|
|
}
|
|
|
|
|
2017-07-06 00:23:10 +10:00
|
|
|
pub fn is_closed(&self) -> bool { self.closed }
|
2016-10-08 23:51:29 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl wayland_window::Handler for DecoratedHandler {
|
|
|
|
fn configure(&mut self,
|
|
|
|
_: &mut EventQueueHandle,
|
2017-09-01 03:43:24 +10:00
|
|
|
_cfg: wayland_window::Configure,
|
|
|
|
newsize: Option<(i32, i32)>)
|
2016-10-08 23:51:29 +11:00
|
|
|
{
|
2017-09-28 00:31:46 +10:00
|
|
|
self.newsize = newsize.map(|(w, h)| (w as u32, h as u32));
|
|
|
|
self.refresh = true;
|
|
|
|
self.configured = true;
|
2016-10-08 23:51:29 +11:00
|
|
|
}
|
2017-05-24 05:53:17 +10:00
|
|
|
|
2017-07-06 00:23:10 +10:00
|
|
|
fn close(&mut self, _: &mut EventQueueHandle) {
|
|
|
|
self.closed = true;
|
2017-05-24 05:53:17 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|