mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-25 14:51:30 +11:00
Merge pull request #215 from vberger/xdg_shell
Update wayland-window to support xdg_shell
This commit is contained in:
commit
cc89d56e43
|
@ -37,7 +37,8 @@ dwmapi-sys = "0.1"
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))'.dependencies]
|
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))'.dependencies]
|
||||||
wayland-client = { version = "0.9.9", features = ["dlopen"] }
|
wayland-client = { version = "0.9.9", features = ["dlopen"] }
|
||||||
|
wayland-protocols = { version = "0.9.9", features = ["unstable_protocols"] }
|
||||||
wayland-kbd = "0.9.1"
|
wayland-kbd = "0.9.1"
|
||||||
wayland-window = "0.6.1"
|
wayland-window = "0.7.0"
|
||||||
tempfile = "2.1"
|
tempfile = "2.1"
|
||||||
x11-dl = "2.8"
|
x11-dl = "2.8"
|
||||||
|
|
|
@ -11,6 +11,12 @@ fn main() {
|
||||||
let cursors = [MouseCursor::Default, MouseCursor::Crosshair, MouseCursor::Hand, MouseCursor::Arrow, MouseCursor::Move, MouseCursor::Text, MouseCursor::Wait, MouseCursor::Help, MouseCursor::Progress, MouseCursor::NotAllowed, MouseCursor::ContextMenu, MouseCursor::NoneCursor, MouseCursor::Cell, MouseCursor::VerticalText, MouseCursor::Alias, MouseCursor::Copy, MouseCursor::NoDrop, MouseCursor::Grab, MouseCursor::Grabbing, MouseCursor::AllScroll, MouseCursor::ZoomIn, MouseCursor::ZoomOut, MouseCursor::EResize, MouseCursor::NResize, MouseCursor::NeResize, MouseCursor::NwResize, MouseCursor::SResize, MouseCursor::SeResize, MouseCursor::SwResize, MouseCursor::WResize, MouseCursor::EwResize, MouseCursor::NsResize, MouseCursor::NeswResize, MouseCursor::NwseResize, MouseCursor::ColResize, MouseCursor::RowResize];
|
let cursors = [MouseCursor::Default, MouseCursor::Crosshair, MouseCursor::Hand, MouseCursor::Arrow, MouseCursor::Move, MouseCursor::Text, MouseCursor::Wait, MouseCursor::Help, MouseCursor::Progress, MouseCursor::NotAllowed, MouseCursor::ContextMenu, MouseCursor::NoneCursor, MouseCursor::Cell, MouseCursor::VerticalText, MouseCursor::Alias, MouseCursor::Copy, MouseCursor::NoDrop, MouseCursor::Grab, MouseCursor::Grabbing, MouseCursor::AllScroll, MouseCursor::ZoomIn, MouseCursor::ZoomOut, MouseCursor::EResize, MouseCursor::NResize, MouseCursor::NeResize, MouseCursor::NwResize, MouseCursor::SResize, MouseCursor::SeResize, MouseCursor::SwResize, MouseCursor::WResize, MouseCursor::EwResize, MouseCursor::NsResize, MouseCursor::NeswResize, MouseCursor::NwseResize, MouseCursor::ColResize, MouseCursor::RowResize];
|
||||||
let mut cursor_idx = 0;
|
let mut cursor_idx = 0;
|
||||||
|
|
||||||
|
if cfg!(target_os = "linux") {
|
||||||
|
println!("Running this example under wayland may not display a window at all.\n\
|
||||||
|
This is normal and because this example does not actually draw anything in the window,\
|
||||||
|
thus the compositor does not display it.");
|
||||||
|
}
|
||||||
|
|
||||||
events_loop.run_forever(|event| {
|
events_loop.run_forever(|event| {
|
||||||
match event {
|
match event {
|
||||||
Event::WindowEvent { event: WindowEvent::KeyboardInput { input: KeyboardInput { state: ElementState::Pressed, .. }, .. }, .. } => {
|
Event::WindowEvent { event: WindowEvent::KeyboardInput { input: KeyboardInput { state: ElementState::Pressed, .. }, .. }, .. } => {
|
||||||
|
|
|
@ -31,6 +31,12 @@ fn main() {
|
||||||
.build(&events_loop)
|
.build(&events_loop)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
if cfg!(target_os = "linux") {
|
||||||
|
println!("Running this example under wayland may not display a window at all.\n\
|
||||||
|
This is normal and because this example does not actually draw anything in the window,\
|
||||||
|
thus the compositor does not display it.");
|
||||||
|
}
|
||||||
|
|
||||||
events_loop.run_forever(|event| {
|
events_loop.run_forever(|event| {
|
||||||
println!("{:?}", event);
|
println!("{:?}", event);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,12 @@ fn main() {
|
||||||
|
|
||||||
let mut grabbed = false;
|
let mut grabbed = false;
|
||||||
|
|
||||||
|
if cfg!(target_os = "linux") {
|
||||||
|
println!("Running this example under wayland may not display a window at all.\n\
|
||||||
|
This is normal and because this example does not actually draw anything in the window,\
|
||||||
|
thus the compositor does not display it.");
|
||||||
|
}
|
||||||
|
|
||||||
events_loop.run_forever(|event| {
|
events_loop.run_forever(|event| {
|
||||||
println!("{:?}", event);
|
println!("{:?}", event);
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,12 @@ fn main() {
|
||||||
.build(&events_loop)
|
.build(&events_loop)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
if cfg!(target_os = "linux") {
|
||||||
|
println!("Running this example under wayland may not display a window at all.\n\
|
||||||
|
This is normal and because this example does not actually draw anything in the window,\
|
||||||
|
thus the compositor does not display it.");
|
||||||
|
}
|
||||||
|
|
||||||
events_loop.run_forever(|event| {
|
events_loop.run_forever(|event| {
|
||||||
println!("{:?}", event);
|
println!("{:?}", event);
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,12 @@ fn main() {
|
||||||
|
|
||||||
let mut num_windows = 3;
|
let mut num_windows = 3;
|
||||||
|
|
||||||
|
if cfg!(target_os = "linux") {
|
||||||
|
println!("Running this example under wayland may not display a window at all.\n\
|
||||||
|
This is normal and because this example does not actually draw anything in the window,\
|
||||||
|
thus the compositor does not display it.");
|
||||||
|
}
|
||||||
|
|
||||||
events_loop.run_forever(|event| {
|
events_loop.run_forever(|event| {
|
||||||
match event {
|
match event {
|
||||||
winit::Event::WindowEvent { event: winit::WindowEvent::Closed, window_id } => {
|
winit::Event::WindowEvent { event: winit::WindowEvent::Closed, window_id } => {
|
||||||
|
|
|
@ -10,6 +10,12 @@ fn main() {
|
||||||
|
|
||||||
let proxy = events_loop.create_proxy();
|
let proxy = events_loop.create_proxy();
|
||||||
|
|
||||||
|
if cfg!(target_os = "linux") {
|
||||||
|
println!("Running this example under wayland may not display a window at all.\n\
|
||||||
|
This is normal and because this example does not actually draw anything in the window,\
|
||||||
|
thus the compositor does not display it.");
|
||||||
|
}
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
// Wake up the `events_loop` once every second.
|
// Wake up the `events_loop` once every second.
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -9,6 +9,12 @@ fn main() {
|
||||||
|
|
||||||
window.set_title("A fantastic window!");
|
window.set_title("A fantastic window!");
|
||||||
|
|
||||||
|
if cfg!(target_os = "linux") {
|
||||||
|
println!("Running this example under wayland may not display a window at all.\n\
|
||||||
|
This is normal and because this example does not actually draw anything in the window,\
|
||||||
|
thus the compositor does not display it.");
|
||||||
|
}
|
||||||
|
|
||||||
events_loop.run_forever(|event| {
|
events_loop.run_forever(|event| {
|
||||||
println!("{:?}", event);
|
println!("{:?}", event);
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,12 @@ fn main() {
|
||||||
.build(&events_loop)
|
.build(&events_loop)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
if cfg!(target_os = "linux") {
|
||||||
|
println!("Running this example under wayland may not display a window at all.\n\
|
||||||
|
This is normal and because this example does not actually draw anything in the window,\
|
||||||
|
thus the compositor does not display it.");
|
||||||
|
}
|
||||||
|
|
||||||
events_loop.run_forever(|event| {
|
events_loop.run_forever(|event| {
|
||||||
println!("{:?}", event);
|
println!("{:?}", event);
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,18 @@ use wayland_client::{EnvHandler, default_connect, EventQueue, EventQueueHandle,
|
||||||
use wayland_client::protocol::{wl_compositor, wl_seat, wl_shell, wl_shm, wl_subcompositor,
|
use wayland_client::protocol::{wl_compositor, wl_seat, wl_shell, wl_shm, wl_subcompositor,
|
||||||
wl_display, wl_registry, wl_output, wl_surface, wl_buffer};
|
wl_display, wl_registry, wl_output, wl_surface, wl_buffer};
|
||||||
|
|
||||||
|
use super::wayland_protocols::unstable::xdg_shell::client::zxdg_shell_v6;
|
||||||
|
|
||||||
use super::{wayland_window, tempfile};
|
use super::{wayland_window, tempfile};
|
||||||
|
|
||||||
|
use super::wayland_window::Shell;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Registry and globals handling
|
* Registry and globals handling
|
||||||
*/
|
*/
|
||||||
|
|
||||||
wayland_env!(InnerEnv,
|
wayland_env!(InnerEnv,
|
||||||
compositor: wl_compositor::WlCompositor,
|
compositor: wl_compositor::WlCompositor,
|
||||||
shell: wl_shell::WlShell,
|
|
||||||
shm: wl_shm::WlShm,
|
shm: wl_shm::WlShm,
|
||||||
subcompositor: wl_subcompositor::WlSubcompositor
|
subcompositor: wl_subcompositor::WlSubcompositor
|
||||||
);
|
);
|
||||||
|
@ -24,6 +27,7 @@ wayland_env!(InnerEnv,
|
||||||
struct WaylandEnv {
|
struct WaylandEnv {
|
||||||
registry: wl_registry::WlRegistry,
|
registry: wl_registry::WlRegistry,
|
||||||
inner: EnvHandler<InnerEnv>,
|
inner: EnvHandler<InnerEnv>,
|
||||||
|
shell: Option<wayland_window::Shell>,
|
||||||
monitors: Vec<OutputInfo>,
|
monitors: Vec<OutputInfo>,
|
||||||
my_id: usize,
|
my_id: usize,
|
||||||
}
|
}
|
||||||
|
@ -53,6 +57,7 @@ impl WaylandEnv {
|
||||||
WaylandEnv {
|
WaylandEnv {
|
||||||
registry: registry,
|
registry: registry,
|
||||||
inner: EnvHandler::new(),
|
inner: EnvHandler::new(),
|
||||||
|
shell: None,
|
||||||
monitors: Vec::new(),
|
monitors: Vec::new(),
|
||||||
my_id: 0,
|
my_id: 0,
|
||||||
}
|
}
|
||||||
|
@ -70,6 +75,24 @@ impl WaylandEnv {
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ensure_shell(&mut self) -> bool {
|
||||||
|
if self.shell.is_some() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// xdg_shell is not available, so initialize wl_shell
|
||||||
|
for &(name, ref interface, _) in self.inner.globals() {
|
||||||
|
if interface == "wl_shell" {
|
||||||
|
self.shell = Some(Shell::Wl(self.registry.bind::<wl_shell::WlShell>(1, name)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_shell(&self) -> &Shell {
|
||||||
|
self.shell.as_ref().expect("Shell was not properly initialized")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Init for WaylandEnv {
|
impl Init for WaylandEnv {
|
||||||
|
@ -87,13 +110,19 @@ impl wl_registry::Handler for WaylandEnv {
|
||||||
interface: String,
|
interface: String,
|
||||||
version: u32)
|
version: u32)
|
||||||
{
|
{
|
||||||
if interface == "wl_output" {
|
if interface == wl_output::WlOutput::interface_name() {
|
||||||
// intercept outputs
|
// intercept outputs
|
||||||
// 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 output = self.registry.bind::<wl_output::WlOutput>(1, name);
|
let output = self.registry.bind::<wl_output::WlOutput>(1, name);
|
||||||
evqh.register::<_, WaylandEnv>(&output, self.my_id);
|
evqh.register::<_, WaylandEnv>(&output, self.my_id);
|
||||||
self.monitors.push(OutputInfo::new(output, name));
|
self.monitors.push(OutputInfo::new(output, name));
|
||||||
|
} else if interface == zxdg_shell_v6::ZxdgShellV6::interface_name() {
|
||||||
|
let xdg_shell = self.registry.bind::<zxdg_shell_v6::ZxdgShellV6>(1, name);
|
||||||
|
let xdg_ping_hid = evqh.add_handler(XdgShellPingHandler);
|
||||||
|
evqh.register::<_, XdgShellPingHandler>(&xdg_shell, xdg_ping_hid);
|
||||||
|
self.shell = Some(Shell::Xdg(xdg_shell));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.inner.global(evqh, registry, name, interface, version);
|
self.inner.global(evqh, registry, name, interface, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +137,16 @@ impl wl_registry::Handler for WaylandEnv {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct XdgShellPingHandler;
|
||||||
|
|
||||||
|
impl zxdg_shell_v6::Handler for XdgShellPingHandler {
|
||||||
|
fn ping(&mut self, _: &mut EventQueueHandle, proxy: &zxdg_shell_v6::ZxdgShellV6, serial: u32) {
|
||||||
|
proxy.pong(serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_handler!(XdgShellPingHandler, zxdg_shell_v6::Handler, zxdg_shell_v6::ZxdgShellV6);
|
||||||
|
|
||||||
declare_handler!(WaylandEnv, wl_registry::Handler, wl_registry::WlRegistry);
|
declare_handler!(WaylandEnv, wl_registry::Handler, wl_registry::WlRegistry);
|
||||||
|
|
||||||
impl wl_output::Handler for WaylandEnv {
|
impl wl_output::Handler for WaylandEnv {
|
||||||
|
@ -175,10 +214,19 @@ impl WaylandContext {
|
||||||
// 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();
|
let registry = display.get_registry();
|
||||||
let env_id = event_queue.add_handler_with_init(WaylandEnv::new(registry));
|
let env_id = event_queue.add_handler_with_init(WaylandEnv::new(registry));
|
||||||
// two syncs fully initialize
|
// two round trips to fully initialize
|
||||||
event_queue.sync_roundtrip().expect("Wayland connection unexpectedly lost");
|
event_queue.sync_roundtrip().expect("Wayland connection unexpectedly lost");
|
||||||
event_queue.sync_roundtrip().expect("Wayland connection unexpectedly lost");
|
event_queue.sync_roundtrip().expect("Wayland connection unexpectedly lost");
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut state = event_queue.state();
|
||||||
|
let mut env = state.get_mut_handler::<WaylandEnv>(env_id);
|
||||||
|
if !env.ensure_shell() {
|
||||||
|
// This is a compositor bug, it _must_ at least support xl_shell
|
||||||
|
panic!("Compositor didi not advertize xdg_shell not wl_shell.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Some(WaylandContext {
|
Some(WaylandContext {
|
||||||
evq: Mutex::new(event_queue),
|
evq: Mutex::new(event_queue),
|
||||||
display: display,
|
display: display,
|
||||||
|
@ -216,10 +264,37 @@ impl WaylandContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn blank_surface(&self, surface: &wl_surface::WlSurface, evq: &mut EventQueue, width: i32, height: i32) {
|
||||||
|
let mut tmp = tempfile::tempfile().expect("Failed to create a tmpfile buffer.");
|
||||||
|
for _ in 0..(width*height) {
|
||||||
|
tmp.write_all(&[0xff,0xff,0xff,0xff]).unwrap();
|
||||||
|
}
|
||||||
|
tmp.flush().unwrap();
|
||||||
|
let pool = {
|
||||||
|
let mut state = evq.state();
|
||||||
|
let env = state.get_mut_handler::<WaylandEnv>(self.env_id);
|
||||||
|
env.inner.shm.create_pool(tmp.as_raw_fd(), width*height*4)
|
||||||
|
};
|
||||||
|
let buffer = pool.create_buffer(0, width, height, width, wl_shm::Format::Argb8888).expect("Pool cannot be already dead");
|
||||||
|
surface.attach(Some(&buffer), 0, 0);
|
||||||
|
surface.commit();
|
||||||
|
// the buffer will keep the contents alive as needed
|
||||||
|
pool.destroy();
|
||||||
|
|
||||||
|
// create a handler to clean up initial buffer
|
||||||
|
let init_buffer_handler = InitialBufferHandler {
|
||||||
|
initial_buffer: Some((buffer.clone().unwrap(), tmp))
|
||||||
|
};
|
||||||
|
let initial_buffer_handler_id = evq.add_handler(init_buffer_handler);
|
||||||
|
// register the buffer to it
|
||||||
|
evq.register::<_, InitialBufferHandler>(&buffer, initial_buffer_handler_id);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_window<H: wayland_window::Handler>(&self, width: u32, height: u32)
|
pub fn create_window<H: wayland_window::Handler>(&self, width: u32, height: u32)
|
||||||
-> (Arc<wl_surface::WlSurface>, wayland_window::DecoratedSurface<H>, wl_buffer::WlBuffer, File)
|
-> (Arc<wl_surface::WlSurface>, wayland_window::DecoratedSurface<H>)
|
||||||
{
|
{
|
||||||
let mut guard = self.evq.lock().unwrap();
|
let mut guard = self.evq.lock().unwrap();
|
||||||
|
let (surface, decorated, xdg) = {
|
||||||
let mut state = guard.state();
|
let mut state = guard.state();
|
||||||
let env = state.get_mut_handler::<WaylandEnv>(self.env_id);
|
let env = state.get_mut_handler::<WaylandEnv>(self.env_id);
|
||||||
let surface = Arc::new(env.inner.compositor.create_surface());
|
let surface = Arc::new(env.inner.compositor.create_surface());
|
||||||
|
@ -228,23 +303,26 @@ impl WaylandContext {
|
||||||
&env.inner.compositor,
|
&env.inner.compositor,
|
||||||
&env.inner.subcompositor,
|
&env.inner.subcompositor,
|
||||||
&env.inner.shm,
|
&env.inner.shm,
|
||||||
&env.inner.shell,
|
env.get_shell(),
|
||||||
env.get_seat(),
|
env.get_seat(),
|
||||||
false
|
false
|
||||||
).expect("Failed to create a tmpfile buffer.");
|
).expect("Failed to create a tmpfile buffer.");
|
||||||
// prepare a white content for the window, so that it exists
|
let xdg = match env.get_shell() {
|
||||||
let mut tmp = tempfile::tempfile().expect("Failed to create a tmpfile buffer.");
|
&Shell::Xdg(_) => true,
|
||||||
for _ in 0..(width*height) {
|
&Shell::Wl(_) => false
|
||||||
tmp.write_all(&[0xff,0xff,0xff,0xff]).unwrap();
|
};
|
||||||
|
(surface, decorated, xdg)
|
||||||
|
};
|
||||||
|
|
||||||
|
if !xdg {
|
||||||
|
// if using wl_shell, we need to draw something in order to kickstart
|
||||||
|
// the event loop
|
||||||
|
// if using xdg_shell, it is an error to do it now, and the events loop will not
|
||||||
|
// be stuck. We cannot draw anything before having received an appropriate event
|
||||||
|
// from the compositor
|
||||||
|
self.blank_surface(&surface, &mut *guard, width as i32, height as i32);
|
||||||
}
|
}
|
||||||
tmp.flush().unwrap();
|
(surface, decorated)
|
||||||
let pool = env.inner.shm.create_pool(tmp.as_raw_fd(), (width*height*4) as i32);
|
|
||||||
let buffer = pool.create_buffer(0, width as i32, height as i32, width as i32, wl_shm::Format::Argb8888).expect("Pool cannot be already dead");
|
|
||||||
surface.attach(Some(&buffer), 0, 0);
|
|
||||||
surface.commit();
|
|
||||||
// the buffer wiil keep the contents alive as needed
|
|
||||||
pool.destroy();
|
|
||||||
(surface, decorated, buffer, tmp)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,3 +387,19 @@ impl MonitorId {
|
||||||
(0,0)
|
(0,0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// a handler to release the ressources acquired to draw the initial white screen as soon as
|
||||||
|
// the compositor does not use them any more
|
||||||
|
pub struct InitialBufferHandler {
|
||||||
|
initial_buffer: Option<(wl_buffer::WlBuffer, File)>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl wl_buffer::Handler for InitialBufferHandler {
|
||||||
|
fn release(&mut self, _: &mut EventQueueHandle, buffer: &wl_buffer::WlBuffer) {
|
||||||
|
// release the ressources we've acquired for initial white window
|
||||||
|
buffer.destroy();
|
||||||
|
self.initial_buffer = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_handler!(InitialBufferHandler, wl_buffer::Handler, wl_buffer::WlBuffer);
|
||||||
|
|
|
@ -155,6 +155,15 @@ impl EventsLoop {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if decorated.handler().as_ref().map(|h| h.is_closed()).unwrap_or(false) {
|
||||||
|
callback(
|
||||||
|
::Event::WindowEvent {
|
||||||
|
window_id: ::WindowId(::platform::WindowId::Wayland(make_wid(&window))),
|
||||||
|
event: ::WindowEvent::Closed
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ use self::event_loop::EventsLoopSink;
|
||||||
|
|
||||||
extern crate wayland_kbd;
|
extern crate wayland_kbd;
|
||||||
extern crate wayland_window;
|
extern crate wayland_window;
|
||||||
|
extern crate wayland_protocols;
|
||||||
extern crate tempfile;
|
extern crate tempfile;
|
||||||
|
|
||||||
mod context;
|
mod context;
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use std::fs::File;
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
|
|
||||||
use wayland_client::{EventQueue, EventQueueHandle, Proxy};
|
use wayland_client::{EventQueue, EventQueueHandle, Proxy};
|
||||||
use wayland_client::protocol::{wl_display,wl_surface,wl_shell_surface,wl_buffer};
|
use wayland_client::protocol::{wl_display,wl_surface};
|
||||||
|
|
||||||
use {CreationError, MouseCursor, CursorState, WindowAttributes};
|
use {CreationError, MouseCursor, CursorState, WindowAttributes};
|
||||||
use platform::MonitorId as PlatformMonitorId;
|
use platform::MonitorId as PlatformMonitorId;
|
||||||
|
@ -40,26 +39,16 @@ impl Window {
|
||||||
{
|
{
|
||||||
let (width, height) = attributes.dimensions.unwrap_or((800,600));
|
let (width, height) = attributes.dimensions.unwrap_or((800,600));
|
||||||
|
|
||||||
let (surface, decorated, buffer, tmpfile) = ctxt.create_window::<DecoratedHandler>(width, height);
|
let (surface, decorated) = ctxt.create_window::<DecoratedHandler>(width, height);
|
||||||
|
|
||||||
// init DecoratedSurface
|
// init DecoratedSurface
|
||||||
let (evq, cleanup_signal) = evlp.get_window_init();
|
let (evq, cleanup_signal) = evlp.get_window_init();
|
||||||
let decorated_id = {
|
let decorated_id = {
|
||||||
let mut evq_guard = evq.lock().unwrap();
|
let mut evq_guard = evq.lock().unwrap();
|
||||||
// create a handler to clean up initial buffer
|
|
||||||
let initial_buffer_handler_id = evq_guard.add_handler(InitialBufferHandler::new());
|
|
||||||
// register the buffer to it
|
|
||||||
evq_guard.register::<_, InitialBufferHandler>(&buffer, initial_buffer_handler_id);
|
|
||||||
// store the DecoratedSurface handler
|
// store the DecoratedSurface handler
|
||||||
let decorated_id = evq_guard.add_handler_with_init(decorated);
|
let decorated_id = evq_guard.add_handler_with_init(decorated);
|
||||||
{
|
{
|
||||||
let mut state = evq_guard.state();
|
let mut state = evq_guard.state();
|
||||||
{
|
|
||||||
// store the buffer and tempfile in the handler, to be cleanded up at the right
|
|
||||||
// time
|
|
||||||
let initial_buffer_h = state.get_mut_handler::<InitialBufferHandler>(initial_buffer_handler_id);
|
|
||||||
initial_buffer_h.initial_buffer = Some((buffer, tmpfile));
|
|
||||||
}
|
|
||||||
// initialize the DecoratedHandler
|
// initialize the DecoratedHandler
|
||||||
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(decorated_id);
|
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(decorated_id);
|
||||||
*(decorated.handler()) = Some(DecoratedHandler::new());
|
*(decorated.handler()) = Some(DecoratedHandler::new());
|
||||||
|
@ -67,11 +56,7 @@ impl Window {
|
||||||
// set fullscreen if necessary
|
// set fullscreen if necessary
|
||||||
if let Some(PlatformMonitorId::Wayland(ref monitor_id)) = attributes.monitor {
|
if let Some(PlatformMonitorId::Wayland(ref monitor_id)) = attributes.monitor {
|
||||||
ctxt.with_output(monitor_id.clone(), |output| {
|
ctxt.with_output(monitor_id.clone(), |output| {
|
||||||
decorated.set_fullscreen(
|
decorated.set_fullscreen(Some(output))
|
||||||
wl_shell_surface::FullscreenMethod::Default,
|
|
||||||
0,
|
|
||||||
Some(output)
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
} else if attributes.decorations {
|
} else if attributes.decorations {
|
||||||
decorated.set_decorate(true);
|
decorated.set_decorate(true);
|
||||||
|
@ -147,6 +132,7 @@ impl Window {
|
||||||
let mut state = guard.state();
|
let mut state = guard.state();
|
||||||
let mut decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(self.decorated_id);
|
let mut decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(self.decorated_id);
|
||||||
decorated.resize(x as i32, y as i32);
|
decorated.resize(x as i32, y as i32);
|
||||||
|
*(self.size.lock().unwrap()) = (x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -194,50 +180,38 @@ impl Drop for Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DecoratedHandler {
|
pub struct DecoratedHandler {
|
||||||
newsize: Option<(u32, u32)>
|
newsize: Option<(u32, u32)>,
|
||||||
|
closed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DecoratedHandler {
|
impl DecoratedHandler {
|
||||||
fn new() -> DecoratedHandler { DecoratedHandler { newsize: None }}
|
fn new() -> DecoratedHandler {
|
||||||
|
DecoratedHandler {
|
||||||
|
newsize: None,
|
||||||
|
closed: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn take_newsize(&mut self) -> Option<(u32, u32)> {
|
pub fn take_newsize(&mut self) -> Option<(u32, u32)> {
|
||||||
self.newsize.take()
|
self.newsize.take()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_closed(&self) -> bool { self.closed }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl wayland_window::Handler for DecoratedHandler {
|
impl wayland_window::Handler for DecoratedHandler {
|
||||||
fn configure(&mut self,
|
fn configure(&mut self,
|
||||||
_: &mut EventQueueHandle,
|
_: &mut EventQueueHandle,
|
||||||
_: wl_shell_surface::Resize,
|
_: wayland_window::Configure,
|
||||||
width: i32, height: i32)
|
width: i32, height: i32)
|
||||||
{
|
{
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
self.newsize = Some((max(width,1) as u32, max(height,1) as u32));
|
self.newsize = Some((max(width,1) as u32, max(height,1) as u32));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// a handler to release the ressources acquired to draw the initial white screen as soon as
|
fn close(&mut self, _: &mut EventQueueHandle) {
|
||||||
// the compositor does not use them any more
|
self.closed = true;
|
||||||
|
|
||||||
pub struct InitialBufferHandler {
|
|
||||||
initial_buffer: Option<(wl_buffer::WlBuffer, File)>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InitialBufferHandler {
|
|
||||||
fn new() -> InitialBufferHandler {
|
|
||||||
InitialBufferHandler {
|
|
||||||
initial_buffer: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl wl_buffer::Handler for InitialBufferHandler {
|
|
||||||
fn release(&mut self, _: &mut EventQueueHandle, buffer: &wl_buffer::WlBuffer) {
|
|
||||||
// release the ressources we've acquired for initial white window
|
|
||||||
buffer.destroy();
|
|
||||||
self.initial_buffer = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare_handler!(InitialBufferHandler, wl_buffer::Handler, wl_buffer::WlBuffer);
|
|
||||||
|
|
Loading…
Reference in a new issue