mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-11 13:31:29 +11:00
wayland: window creation & resizing
This commit is contained in:
parent
a505eddf29
commit
34c00aa153
|
@ -39,7 +39,7 @@ kernel32-sys = "0.2"
|
|||
dwmapi-sys = "0.1"
|
||||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))'.dependencies]
|
||||
wayland-client = { version = "0.7.1", features = ["dlopen"] }
|
||||
wayland-client = { version = "0.7.3", features = ["dlopen"] }
|
||||
wayland-kbd = "0.6"
|
||||
wayland-window = "0.4"
|
||||
wayland-window = "0.4.2"
|
||||
x11-dl = "2.8"
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
use Event;
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use wayland_client::{EnvHandler, default_connect, EventQueue, EventQueueHandle, Init, Proxy};
|
||||
use wayland_client::protocol::{wl_compositor, wl_seat, wl_shell, wl_shm, wl_subcompositor,
|
||||
wl_display, wl_registry, wl_output};
|
||||
wl_display, wl_registry, wl_output, wl_surface};
|
||||
|
||||
use super::wayland_window;
|
||||
|
||||
/*
|
||||
* Registry and globals handling
|
||||
|
@ -21,7 +25,8 @@ struct WaylandEnv {
|
|||
registry: wl_registry::WlRegistry,
|
||||
inner: EnvHandler<InnerEnv>,
|
||||
monitors: Vec<OutputInfo>,
|
||||
my_id: usize
|
||||
my_id: usize,
|
||||
windows: Vec<(Arc<wl_surface::WlSurface>,Arc<Mutex<VecDeque<Event>>>)>
|
||||
}
|
||||
|
||||
struct OutputInfo {
|
||||
|
@ -50,9 +55,21 @@ impl WaylandEnv {
|
|||
registry: registry,
|
||||
inner: EnvHandler::new(),
|
||||
monitors: Vec::new(),
|
||||
my_id: 0
|
||||
my_id: 0,
|
||||
windows: Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_seat(&self) -> Option<wl_seat::WlSeat> {
|
||||
for &(name, ref interface, version) in self.inner.globals() {
|
||||
if interface == "wl_seat" {
|
||||
// this "expect" cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69)
|
||||
let seat = self.registry.bind::<wl_seat::WlSeat>(5, name).expect("Seat cannot be destroyed");
|
||||
return Some(seat)
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Init for WaylandEnv {
|
||||
|
@ -156,9 +173,11 @@ impl WaylandContext {
|
|||
Err(e) => return None
|
||||
};
|
||||
|
||||
// this expect cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69)
|
||||
// this "expect" cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69)
|
||||
let registry = display.get_registry().expect("Display cannot be already destroyed.");
|
||||
let env_id = event_queue.add_handler_with_init(WaylandEnv::new(registry));
|
||||
// two syncs fully initialize
|
||||
event_queue.sync_roundtrip().expect("Wayland connection unexpectedly lost");
|
||||
event_queue.sync_roundtrip().expect("Wayland connection unexpectedly lost");
|
||||
|
||||
Some(WaylandContext {
|
||||
|
@ -167,6 +186,59 @@ impl WaylandContext {
|
|||
env_id: env_id
|
||||
})
|
||||
}
|
||||
|
||||
pub fn dispatch_pending(&self) {
|
||||
let mut guard = self.evq.lock().unwrap();
|
||||
guard.dispatch_pending().expect("Wayland connection unexpectedly lost");
|
||||
}
|
||||
|
||||
pub fn dispatch(&self) {
|
||||
let mut guard = self.evq.lock().unwrap();
|
||||
guard.dispatch().expect("Wayland connection unexpectedly lost");
|
||||
}
|
||||
|
||||
pub fn flush(&self) {
|
||||
self.display.flush();
|
||||
}
|
||||
|
||||
pub fn with_output<F>(&self, id: MonitorId, f: F) where F: FnOnce(&wl_output::WlOutput) {
|
||||
let mut guard = self.evq.lock().unwrap();
|
||||
let state = guard.state();
|
||||
let env = state.get_handler::<WaylandEnv>(self.env_id);
|
||||
for m in env.monitors.iter().filter(|m| m.id == id.id) {
|
||||
f(&m.output);
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_window<H: wayland_window::Handler>(&self)
|
||||
-> (Arc<wl_surface::WlSurface>, Arc<Mutex<VecDeque<Event>>>, wayland_window::DecoratedSurface<H>)
|
||||
{
|
||||
let mut guard = self.evq.lock().unwrap();
|
||||
let mut state = guard.state();
|
||||
let env = state.get_mut_handler::<WaylandEnv>(self.env_id);
|
||||
// this "expect" cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69)
|
||||
let surface = Arc::new(env.inner.compositor.create_surface().expect("Compositor cannot be dead"));
|
||||
let eventiter = Arc::new(Mutex::new(VecDeque::new()));
|
||||
env.windows.push((surface.clone(), eventiter.clone()));
|
||||
let decorated = wayland_window::DecoratedSurface::new(
|
||||
&*surface, 800, 600,
|
||||
&env.inner.compositor,
|
||||
&env.inner.subcompositor,
|
||||
&env.inner.shm,
|
||||
&env.inner.shell,
|
||||
env.get_seat(),
|
||||
false
|
||||
).expect("Failed to create a tmpfile buffer.");
|
||||
(surface, eventiter, decorated)
|
||||
}
|
||||
|
||||
pub fn prune_dead_windows(&self) {
|
||||
let mut guard = self.evq.lock().unwrap();
|
||||
let mut state = guard.state();
|
||||
let env = state.get_mut_handler::<WaylandEnv>(self.env_id);
|
||||
env.windows.retain(|w| w.0.is_alive());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_primary_monitor(ctxt: &Arc<WaylandContext>) -> MonitorId {
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
use std::sync::Arc;
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use wayland_client::protocol::{wl_display,wl_surface};
|
||||
use wayland_client::{EventQueue, EventQueueHandle, Init};
|
||||
use wayland_client::protocol::{wl_display,wl_surface,wl_shell_surface};
|
||||
|
||||
use {CreationError, MouseCursor, CursorState, Event, WindowAttributes};
|
||||
use platform::MonitorId as PlatformMonitorId;
|
||||
|
||||
use super::WaylandContext;
|
||||
use super::wayland_window;
|
||||
use super::wayland_window::DecoratedSurface;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WindowProxy;
|
||||
|
@ -17,7 +22,13 @@ impl WindowProxy {
|
|||
}
|
||||
|
||||
pub struct Window {
|
||||
resize_callback: Option<fn(u32,u32)>
|
||||
ctxt: Arc<WaylandContext>,
|
||||
evq: Mutex<EventQueue>,
|
||||
eviter: Arc<Mutex<VecDeque<Event>>>,
|
||||
surface: Arc<wl_surface::WlSurface>,
|
||||
size: Mutex<(u32, u32)>,
|
||||
handler_id: usize,
|
||||
decorated_id: usize
|
||||
}
|
||||
|
||||
pub struct PollEventsIterator<'a> {
|
||||
|
@ -28,7 +39,7 @@ impl<'a> Iterator for PollEventsIterator<'a> {
|
|||
type Item = Event;
|
||||
|
||||
fn next(&mut self) -> Option<Event> {
|
||||
unimplemented!()
|
||||
self.window.next_event(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,14 +51,112 @@ impl<'a> Iterator for WaitEventsIterator<'a> {
|
|||
type Item = Event;
|
||||
|
||||
fn next(&mut self) -> Option<Event> {
|
||||
unimplemented!()
|
||||
self.window.next_event(true)
|
||||
}
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub fn new(ctxt: Arc<WaylandContext>, attributes: &WindowAttributes) -> Result<Window, CreationError>
|
||||
{
|
||||
unimplemented!()
|
||||
let (width, height) = attributes.dimensions.unwrap_or((800,600));
|
||||
|
||||
let mut evq = ctxt.display.create_event_queue();
|
||||
|
||||
let (surface, eviter, decorated) = ctxt.create_window::<DecoratedHandler>();
|
||||
|
||||
// init DecoratedSurface
|
||||
let decorated_id = evq.add_handler_with_init(decorated);
|
||||
{
|
||||
let mut state = evq.state();
|
||||
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(decorated_id);
|
||||
*(decorated.handler()) = Some(DecoratedHandler::new());
|
||||
|
||||
if let Some(PlatformMonitorId::Wayland(ref monitor_id)) = attributes.monitor {
|
||||
ctxt.with_output(monitor_id.clone(), |output| {
|
||||
decorated.set_fullscreen(
|
||||
wl_shell_surface::FullscreenMethod::Default,
|
||||
0,
|
||||
Some(output)
|
||||
)
|
||||
});
|
||||
} else if attributes.decorations {
|
||||
decorated.set_decorate(true);
|
||||
}
|
||||
}
|
||||
|
||||
// init general handler
|
||||
let handler = WindowHandler::new();
|
||||
let handler_id = evq.add_handler_with_init(handler);
|
||||
|
||||
Ok(Window {
|
||||
ctxt: ctxt,
|
||||
evq: Mutex::new(evq),
|
||||
eviter: eviter,
|
||||
surface: surface,
|
||||
size: Mutex::new((width, height)),
|
||||
handler_id: handler_id,
|
||||
decorated_id: decorated_id
|
||||
})
|
||||
}
|
||||
|
||||
fn process_resize(&self) {
|
||||
use std::cmp::max;
|
||||
let mut evq_guard = self.evq.lock().unwrap();
|
||||
let mut state = evq_guard.state();
|
||||
let newsize = {
|
||||
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(self.decorated_id);
|
||||
let newsize = decorated.handler().as_mut().and_then(|h| h.take_newsize());
|
||||
if let Some((w, h)) = newsize {
|
||||
decorated.resize(w as i32, h as i32);
|
||||
*self.size.lock().unwrap() = (w, h);
|
||||
}
|
||||
newsize
|
||||
};
|
||||
// callback_resize if any
|
||||
if let Some((w, h)) = newsize {
|
||||
let mut handler = state.get_mut_handler::<WindowHandler>(self.handler_id);
|
||||
if let Some(ref callback) = handler.resize_callback {
|
||||
callback(w, h);
|
||||
}
|
||||
self.eviter.lock().unwrap().push_back(Event::Resized(w,h));
|
||||
}
|
||||
}
|
||||
|
||||
fn next_event(&self, block: bool) -> Option<Event> {
|
||||
let mut evt = {
|
||||
let mut guard = self.eviter.lock().unwrap();
|
||||
guard.pop_front()
|
||||
};
|
||||
if evt.is_some() { return evt }
|
||||
|
||||
// try a pending dispatch
|
||||
// TODO: insert a non-blocking read from socket, overwise no new events will ever come
|
||||
{
|
||||
self.ctxt.dispatch_pending();
|
||||
let mut guard = self.evq.lock().unwrap().dispatch_pending();
|
||||
// some events were dispatched, need to process a potential resising
|
||||
self.process_resize();
|
||||
}
|
||||
|
||||
let mut evt = {
|
||||
let mut guard = self.eviter.lock().unwrap();
|
||||
guard.pop_front()
|
||||
};
|
||||
|
||||
while block && evt.is_none() {
|
||||
// no event waiting, need to repopulate!
|
||||
{
|
||||
self.ctxt.flush();
|
||||
self.ctxt.dispatch();
|
||||
let mut guard = self.evq.lock().unwrap().dispatch();
|
||||
// some events were dispatched, need to process a potential resising
|
||||
self.process_resize();
|
||||
}
|
||||
// try again
|
||||
let mut guard = self.eviter.lock().unwrap();
|
||||
evt = guard.pop_front()
|
||||
}
|
||||
evt
|
||||
}
|
||||
|
||||
pub fn set_title(&self, title: &str) {
|
||||
|
@ -112,7 +221,10 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
|
||||
self.resize_callback = callback;
|
||||
let mut guard = self.evq.lock().unwrap();
|
||||
let mut state = guard.state();
|
||||
let mut handler = state.get_mut_handler::<WindowHandler>(self.handler_id);
|
||||
handler.resize_callback = callback;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -144,16 +256,59 @@ impl Window {
|
|||
}
|
||||
|
||||
pub fn get_display(&self) -> &wl_display::WlDisplay {
|
||||
unimplemented!()
|
||||
&self.ctxt.display
|
||||
}
|
||||
|
||||
pub fn get_surface(&self) -> &wl_surface::WlSurface {
|
||||
unimplemented!()
|
||||
&self.surface
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Window {
|
||||
fn drop(&mut self) {
|
||||
// TODO
|
||||
self.surface.destroy();
|
||||
self.ctxt.prune_dead_windows();
|
||||
}
|
||||
}
|
||||
|
||||
struct DecoratedHandler {
|
||||
newsize: Option<(u32, u32)>
|
||||
}
|
||||
|
||||
impl DecoratedHandler {
|
||||
fn new() -> DecoratedHandler { DecoratedHandler { newsize: None }}
|
||||
fn take_newsize(&mut self) -> Option<(u32, u32)> {
|
||||
self.newsize.take()
|
||||
}
|
||||
}
|
||||
|
||||
impl wayland_window::Handler for DecoratedHandler {
|
||||
fn configure(&mut self,
|
||||
_: &mut EventQueueHandle,
|
||||
_: wl_shell_surface::Resize,
|
||||
width: i32, height: i32)
|
||||
{
|
||||
use std::cmp::max;
|
||||
self.newsize = Some((max(width,1) as u32, max(height,1) as u32));
|
||||
}
|
||||
}
|
||||
|
||||
struct WindowHandler {
|
||||
my_id: usize,
|
||||
resize_callback: Option<fn(u32,u32)>,
|
||||
}
|
||||
|
||||
impl WindowHandler {
|
||||
fn new() -> WindowHandler {
|
||||
WindowHandler {
|
||||
my_id: 0,
|
||||
resize_callback: None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Init for WindowHandler {
|
||||
fn init(&mut self, evqh: &mut EventQueueHandle, index: usize) {
|
||||
self.my_id = index;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue