mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-25 06:41:31 +11:00
wayland: mugrate to new API
This commit is contained in:
parent
9aaa788434
commit
7336cacf07
|
@ -129,7 +129,12 @@ impl Window2 {
|
||||||
{
|
{
|
||||||
match *UNIX_BACKEND {
|
match *UNIX_BACKEND {
|
||||||
UnixBackend::Wayland(ref ctxt) => {
|
UnixBackend::Wayland(ref ctxt) => {
|
||||||
wayland::Window2::new(events_loop, ctxt.clone(), window).map(Window2::Wayland)
|
if let EventsLoop::Wayland(ref evlp) = *events_loop {
|
||||||
|
wayland::Window2::new(evlp, ctxt.clone(), window).map(Window2::Wayland)
|
||||||
|
} else {
|
||||||
|
// It is not possible to instanciate an EventsLoop not matching its backend
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
UnixBackend::X(ref connec) => {
|
UnixBackend::X(ref connec) => {
|
||||||
|
@ -299,8 +304,8 @@ pub enum EventsLoop {
|
||||||
impl EventsLoop {
|
impl EventsLoop {
|
||||||
pub fn new() -> EventsLoop {
|
pub fn new() -> EventsLoop {
|
||||||
match *UNIX_BACKEND {
|
match *UNIX_BACKEND {
|
||||||
UnixBackend::Wayland(_) => {
|
UnixBackend::Wayland(ref ctxt) => {
|
||||||
EventsLoop::Wayland(wayland::EventsLoop::new())
|
EventsLoop::Wayland(wayland::EventsLoop::new(ctxt.clone()))
|
||||||
},
|
},
|
||||||
|
|
||||||
UnixBackend::X(_) => {
|
UnixBackend::X(_) => {
|
||||||
|
|
|
@ -10,7 +10,7 @@ use wayland_client::protocol::{wl_compositor, wl_seat, wl_shell, wl_shm, wl_subc
|
||||||
wl_display, wl_registry, wl_output, wl_surface, wl_pointer,
|
wl_display, wl_registry, wl_output, wl_surface, wl_pointer,
|
||||||
wl_keyboard};
|
wl_keyboard};
|
||||||
|
|
||||||
use super::wayland_window;
|
use super::{wayland_window, EventsLoopSink, make_wid};
|
||||||
use super::wayland_kbd::MappedKeyboard;
|
use super::wayland_kbd::MappedKeyboard;
|
||||||
use super::keyboard::KbdHandler;
|
use super::keyboard::KbdHandler;
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ wayland_env!(InnerEnv,
|
||||||
|
|
||||||
enum KbdType {
|
enum KbdType {
|
||||||
Mapped(MappedKeyboard<KbdHandler>),
|
Mapped(MappedKeyboard<KbdHandler>),
|
||||||
Plain(Option<Arc<Mutex<VecDeque<Event>>>>)
|
Plain(Option<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WaylandEnv {
|
struct WaylandEnv {
|
||||||
|
@ -35,10 +35,10 @@ struct WaylandEnv {
|
||||||
inner: EnvHandler<InnerEnv>,
|
inner: EnvHandler<InnerEnv>,
|
||||||
monitors: Vec<OutputInfo>,
|
monitors: Vec<OutputInfo>,
|
||||||
my_id: usize,
|
my_id: usize,
|
||||||
windows: Vec<(Arc<wl_surface::WlSurface>,Arc<Mutex<VecDeque<Event>>>)>,
|
windows: Vec<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>,
|
||||||
seat: Option<wl_seat::WlSeat>,
|
seat: Option<wl_seat::WlSeat>,
|
||||||
mouse: Option<wl_pointer::WlPointer>,
|
mouse: Option<wl_pointer::WlPointer>,
|
||||||
mouse_focus: Option<Arc<Mutex<VecDeque<Event>>>>,
|
mouse_focus: Option<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>,
|
||||||
mouse_location: (i32, i32),
|
mouse_location: (i32, i32),
|
||||||
axis_buffer: Option<(f32, f32)>,
|
axis_buffer: Option<(f32, f32)>,
|
||||||
axis_discrete_buffer: Option<(i32, i32)>,
|
axis_discrete_buffer: Option<(i32, i32)>,
|
||||||
|
@ -252,16 +252,15 @@ impl WaylandContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_window<H: wayland_window::Handler>(&self)
|
pub fn create_window<H: wayland_window::Handler>(&self, sink: Arc<Mutex<EventsLoopSink>>)
|
||||||
-> (Arc<wl_surface::WlSurface>, Arc<Mutex<VecDeque<Event>>>, wayland_window::DecoratedSurface<H>)
|
-> (Arc<wl_surface::WlSurface>, wayland_window::DecoratedSurface<H>)
|
||||||
{
|
{
|
||||||
let mut guard = self.evq.lock().unwrap();
|
let mut guard = self.evq.lock().unwrap();
|
||||||
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);
|
||||||
// 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 surface = Arc::new(env.inner.compositor.create_surface().expect("Compositor cannot be dead"));
|
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(), sink));
|
||||||
env.windows.push((surface.clone(), eventiter.clone()));
|
|
||||||
let decorated = wayland_window::DecoratedSurface::new(
|
let decorated = wayland_window::DecoratedSurface::new(
|
||||||
&*surface, 800, 600,
|
&*surface, 800, 600,
|
||||||
&env.inner.compositor,
|
&env.inner.compositor,
|
||||||
|
@ -271,7 +270,7 @@ impl WaylandContext {
|
||||||
env.get_seat(),
|
env.get_seat(),
|
||||||
false
|
false
|
||||||
).expect("Failed to create a tmpfile buffer.");
|
).expect("Failed to create a tmpfile buffer.");
|
||||||
(surface, eventiter, decorated)
|
(surface, decorated)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prune_dead_windows(&self) {
|
pub fn prune_dead_windows(&self) {
|
||||||
|
@ -397,13 +396,13 @@ impl wl_pointer::Handler for WaylandEnv {
|
||||||
surface_y: f64)
|
surface_y: f64)
|
||||||
{
|
{
|
||||||
self.mouse_location = (surface_x as i32, surface_y as i32);
|
self.mouse_location = (surface_x as i32, surface_y as i32);
|
||||||
for &(ref window, ref eviter) in &self.windows {
|
for &(ref window, ref sink) in &self.windows {
|
||||||
if window.equals(surface) {
|
if window.equals(surface) {
|
||||||
self.mouse_focus = Some(eviter.clone());
|
self.mouse_focus = Some((window.clone(), sink.clone()));
|
||||||
let (w, h) = self.mouse_location;
|
let (w, h) = self.mouse_location;
|
||||||
let mut event_queue = eviter.lock().unwrap();
|
let mut event_queue = sink.lock().unwrap();
|
||||||
event_queue.push_back(Event::MouseEntered);
|
event_queue.push_event(Event::MouseEntered, make_wid(window));
|
||||||
event_queue.push_back(Event::MouseMoved(w, h));
|
event_queue.push_event(Event::MouseMoved(w, h), make_wid(window));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,10 +415,10 @@ impl wl_pointer::Handler for WaylandEnv {
|
||||||
surface: &wl_surface::WlSurface)
|
surface: &wl_surface::WlSurface)
|
||||||
{
|
{
|
||||||
self.mouse_focus = None;
|
self.mouse_focus = None;
|
||||||
for &(ref window, ref eviter) in &self.windows {
|
for &(ref window, ref sink) in &self.windows {
|
||||||
if window.equals(surface) {
|
if window.equals(surface) {
|
||||||
let mut event_queue = eviter.lock().unwrap();
|
let mut event_queue = sink.lock().unwrap();
|
||||||
event_queue.push_back(Event::MouseLeft);
|
event_queue.push_event(Event::MouseLeft, make_wid(window));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -433,10 +432,11 @@ impl wl_pointer::Handler for WaylandEnv {
|
||||||
surface_y: f64)
|
surface_y: f64)
|
||||||
{
|
{
|
||||||
self.mouse_location = (surface_x as i32, surface_y as i32);
|
self.mouse_location = (surface_x as i32, surface_y as i32);
|
||||||
if let Some(ref eviter) = self.mouse_focus {
|
if let Some((ref window, ref sink)) = self.mouse_focus {
|
||||||
let (w,h) = self.mouse_location;
|
let (w,h) = self.mouse_location;
|
||||||
eviter.lock().unwrap().push_back(
|
sink.lock().unwrap().push_event(
|
||||||
Event::MouseMoved(w, h)
|
Event::MouseMoved(w, h),
|
||||||
|
make_wid(window)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ impl wl_pointer::Handler for WaylandEnv {
|
||||||
button: u32,
|
button: u32,
|
||||||
state: wl_pointer::ButtonState)
|
state: wl_pointer::ButtonState)
|
||||||
{
|
{
|
||||||
if let Some(ref eviter) = self.mouse_focus {
|
if let Some((ref window, ref sink)) = self.mouse_focus {
|
||||||
let state = match state {
|
let state = match state {
|
||||||
wl_pointer::ButtonState::Pressed => ElementState::Pressed,
|
wl_pointer::ButtonState::Pressed => ElementState::Pressed,
|
||||||
wl_pointer::ButtonState::Released => ElementState::Released
|
wl_pointer::ButtonState::Released => ElementState::Released
|
||||||
|
@ -461,8 +461,9 @@ impl wl_pointer::Handler for WaylandEnv {
|
||||||
// TODO figure out the translation ?
|
// TODO figure out the translation ?
|
||||||
_ => return
|
_ => return
|
||||||
};
|
};
|
||||||
eviter.lock().unwrap().push_back(
|
sink.lock().unwrap().push_event(
|
||||||
Event::MouseInput(state, button)
|
Event::MouseInput(state, button),
|
||||||
|
make_wid(window)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -492,20 +493,22 @@ impl wl_pointer::Handler for WaylandEnv {
|
||||||
{
|
{
|
||||||
let axis_buffer = self.axis_buffer.take();
|
let axis_buffer = self.axis_buffer.take();
|
||||||
let axis_discrete_buffer = self.axis_discrete_buffer.take();
|
let axis_discrete_buffer = self.axis_discrete_buffer.take();
|
||||||
if let Some(ref eviter) = self.mouse_focus {
|
if let Some((ref window, ref sink)) = self.mouse_focus {
|
||||||
if let Some((x, y)) = axis_discrete_buffer {
|
if let Some((x, y)) = axis_discrete_buffer {
|
||||||
eviter.lock().unwrap().push_back(
|
sink.lock().unwrap().push_event(
|
||||||
Event::MouseWheel(
|
Event::MouseWheel(
|
||||||
MouseScrollDelta::LineDelta(x as f32, y as f32),
|
MouseScrollDelta::LineDelta(x as f32, y as f32),
|
||||||
self.axis_state
|
self.axis_state
|
||||||
)
|
),
|
||||||
|
make_wid(window)
|
||||||
);
|
);
|
||||||
} else if let Some((x, y)) = axis_buffer {
|
} else if let Some((x, y)) = axis_buffer {
|
||||||
eviter.lock().unwrap().push_back(
|
sink.lock().unwrap().push_event(
|
||||||
Event::MouseWheel(
|
Event::MouseWheel(
|
||||||
MouseScrollDelta::PixelDelta(x as f32, y as f32),
|
MouseScrollDelta::PixelDelta(x as f32, y as f32),
|
||||||
self.axis_state
|
self.axis_state
|
||||||
)
|
),
|
||||||
|
make_wid(window)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -574,24 +577,24 @@ impl wl_keyboard::Handler for WaylandEnv {
|
||||||
surface: &wl_surface::WlSurface,
|
surface: &wl_surface::WlSurface,
|
||||||
keys: Vec<u8>)
|
keys: Vec<u8>)
|
||||||
{
|
{
|
||||||
let mut opt_eviter = None;
|
let mut opt_sink = None;
|
||||||
for &(ref window, ref eviter) in &self.windows {
|
for &(ref window, ref sink) in &self.windows {
|
||||||
if window.equals(surface) {
|
if window.equals(surface) {
|
||||||
opt_eviter = Some(eviter.clone());
|
opt_sink = Some((window.clone(), sink.clone()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(ref eviter) = opt_eviter {
|
if let Some((ref window, ref sink)) = opt_sink {
|
||||||
// send focused event
|
// send focused event
|
||||||
let mut guard = eviter.lock().unwrap();
|
let mut guard = sink.lock().unwrap();
|
||||||
guard.push_back(Event::Focused(true));
|
guard.push_event(Event::Focused(true), make_wid(window));
|
||||||
}
|
}
|
||||||
match self.kbd_handler {
|
match self.kbd_handler {
|
||||||
KbdType::Mapped(ref mut h) => {
|
KbdType::Mapped(ref mut h) => {
|
||||||
h.handler().target = opt_eviter;
|
h.handler().target = opt_sink;
|
||||||
h.enter(evqh, proxy, serial, surface, keys);
|
h.enter(evqh, proxy, serial, surface, keys);
|
||||||
},
|
},
|
||||||
KbdType::Plain(ref mut opt) => { *opt = opt_eviter; }
|
KbdType::Plain(ref mut opt) => { *opt = opt_sink; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,17 +604,17 @@ impl wl_keyboard::Handler for WaylandEnv {
|
||||||
serial: u32,
|
serial: u32,
|
||||||
surface: &wl_surface::WlSurface)
|
surface: &wl_surface::WlSurface)
|
||||||
{
|
{
|
||||||
let opt_eviter = match self.kbd_handler {
|
let opt_sink = match self.kbd_handler {
|
||||||
KbdType::Mapped(ref mut h) => {
|
KbdType::Mapped(ref mut h) => {
|
||||||
let eviter = h.handler().target.take();
|
let sink = h.handler().target.take();
|
||||||
h.leave(evqh, proxy, serial, surface);
|
h.leave(evqh, proxy, serial, surface);
|
||||||
eviter
|
sink
|
||||||
},
|
},
|
||||||
KbdType::Plain(ref mut opt) => opt.take()
|
KbdType::Plain(ref mut opt) => opt.take()
|
||||||
};
|
};
|
||||||
if let Some(eviter) = opt_eviter {
|
if let Some((ref window, ref sink)) = opt_sink {
|
||||||
let mut guard = eviter.lock().unwrap();
|
let mut guard = sink.lock().unwrap();
|
||||||
guard.push_back(Event::Focused(false));
|
guard.push_event(Event::Focused(false), make_wid(window));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -625,12 +628,12 @@ impl wl_keyboard::Handler for WaylandEnv {
|
||||||
{
|
{
|
||||||
match self.kbd_handler {
|
match self.kbd_handler {
|
||||||
KbdType::Mapped(ref mut h) => h.key(evqh, proxy, serial, time, key, state),
|
KbdType::Mapped(ref mut h) => h.key(evqh, proxy, serial, time, key, state),
|
||||||
KbdType::Plain(Some(ref eviter)) => {
|
KbdType::Plain(Some((ref window, ref sink))) => {
|
||||||
let state = match state {
|
let state = match state {
|
||||||
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
|
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
|
||||||
wl_keyboard::KeyState::Released => ElementState::Released,
|
wl_keyboard::KeyState::Released => ElementState::Released,
|
||||||
};
|
};
|
||||||
let mut guard = eviter.lock().unwrap();
|
let mut guard = sink.lock().unwrap();
|
||||||
// This is fallback impl if libxkbcommon was not available
|
// This is fallback impl if libxkbcommon was not available
|
||||||
// This case should probably never happen, as most wayland
|
// This case should probably never happen, as most wayland
|
||||||
// compositors _need_ libxkbcommon anyway...
|
// compositors _need_ libxkbcommon anyway...
|
||||||
|
@ -638,12 +641,15 @@ impl wl_keyboard::Handler for WaylandEnv {
|
||||||
// In this case, we don't have the modifiers state information
|
// In this case, we don't have the modifiers state information
|
||||||
// anyway, as we need libxkbcommon to interpret it (it is
|
// anyway, as we need libxkbcommon to interpret it (it is
|
||||||
// supposed to be serialized by the compositor using libxkbcommon)
|
// supposed to be serialized by the compositor using libxkbcommon)
|
||||||
guard.push_back(Event::KeyboardInput(
|
guard.push_event(
|
||||||
state,
|
Event::KeyboardInput(
|
||||||
key as u8,
|
state,
|
||||||
None,
|
key as u8,
|
||||||
ModifiersState::default()
|
None,
|
||||||
));
|
ModifiersState::default()
|
||||||
|
),
|
||||||
|
make_wid(window)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
KbdType::Plain(None) => ()
|
KbdType::Plain(None) => ()
|
||||||
}
|
}
|
||||||
|
|
184
src/platform/linux/wayland/event_loop.rs
Normal file
184
src/platform/linux/wayland/event_loop.rs
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::sync::atomic::AtomicBool;
|
||||||
|
|
||||||
|
use super::{DecoratedHandler, WindowId, WaylandContext};
|
||||||
|
|
||||||
|
use wayland_client::EventQueue;
|
||||||
|
use super::wayland_window::DecoratedSurface;
|
||||||
|
|
||||||
|
pub struct EventsLoopSink {
|
||||||
|
callback: Option<*mut FnMut(::Event)>,
|
||||||
|
queue: VecDeque<::Event>
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for EventsLoopSink { }
|
||||||
|
|
||||||
|
impl EventsLoopSink {
|
||||||
|
pub fn new() -> EventsLoopSink {
|
||||||
|
EventsLoopSink {
|
||||||
|
callback: None,
|
||||||
|
queue: VecDeque::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_event(&mut self, evt: ::WindowEvent, wid: WindowId) {
|
||||||
|
let evt = ::Event::WindowEvent {
|
||||||
|
event: evt,
|
||||||
|
window_id: ::WindowId(::platform::WindowId::Wayland(wid))
|
||||||
|
};
|
||||||
|
if let Some(cb) = self.callback {
|
||||||
|
unsafe { (&mut *cb)(evt) }
|
||||||
|
} else {
|
||||||
|
self.queue.push_back(evt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is only safe of the set callback is unset before exclusive
|
||||||
|
// access to the wayland EventQueue is finished.
|
||||||
|
//
|
||||||
|
// The callback also cannot be used any longer as long as it has not been
|
||||||
|
// cleared from the Sink.
|
||||||
|
unsafe fn set_callback(&mut self, cb: &mut FnMut(::Event)) {
|
||||||
|
let cb: &mut FnMut(::Event) = ::std::mem::transmute(cb);
|
||||||
|
self.callback = Some(cb as *mut _);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_callback<F: FnOnce(&mut FnMut(::Event))>(&mut self, f: F) {
|
||||||
|
if let Some(cb) = self.callback {
|
||||||
|
f(unsafe {&mut *cb})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear_callback(&mut self) {
|
||||||
|
self.callback = None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drain_queue<F: FnMut(::Event)>(&mut self, cb: &mut F) {
|
||||||
|
for evt in self.queue.drain(..) {
|
||||||
|
cb(evt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EventsLoop {
|
||||||
|
ctxt: Arc<WaylandContext>,
|
||||||
|
evq: Arc<Mutex<EventQueue>>,
|
||||||
|
decorated_ids: Mutex<Vec<(usize, WindowId)>>,
|
||||||
|
sink: Arc<Mutex<EventsLoopSink>>,
|
||||||
|
interrupted: AtomicBool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventsLoop {
|
||||||
|
pub fn new(ctxt: Arc<WaylandContext>) -> EventsLoop {
|
||||||
|
let evq = ctxt.display.create_event_queue();
|
||||||
|
EventsLoop {
|
||||||
|
ctxt: ctxt,
|
||||||
|
evq: Arc::new(Mutex::new(evq)),
|
||||||
|
decorated_ids: Mutex::new(Vec::new()),
|
||||||
|
sink: Arc::new(Mutex::new(EventsLoopSink::new())),
|
||||||
|
interrupted: AtomicBool::new(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_sink(&self) -> Arc<Mutex<EventsLoopSink>> {
|
||||||
|
self.sink.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_event_queue(&self) -> Arc<Mutex<EventQueue>> {
|
||||||
|
self.evq.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register_window(&self, decorated_id: usize, wid: WindowId) {
|
||||||
|
self.decorated_ids.lock().unwrap().push((decorated_id, wid));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_resize(evq: &mut EventQueue, ids: &[(usize, WindowId)], callback: &mut FnMut(::Event))
|
||||||
|
{
|
||||||
|
let mut state = evq.state();
|
||||||
|
for &(decorated_id, window_id) in ids {
|
||||||
|
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(decorated_id);
|
||||||
|
if let Some((w, h)) = decorated.handler().as_mut().and_then(|h| h.take_newsize()) {
|
||||||
|
decorated.resize(w as i32, h as i32);
|
||||||
|
callback(
|
||||||
|
::Event::WindowEvent {
|
||||||
|
window_id: ::WindowId(::platform::WindowId::Wayland(window_id)),
|
||||||
|
event: ::WindowEvent::Resized(w,h)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn interrupt(&self) {
|
||||||
|
self.interrupted.store(true, ::std::sync::atomic::Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poll_events<F>(&self, mut callback: F)
|
||||||
|
where F: FnMut(::Event)
|
||||||
|
{
|
||||||
|
// send pending requests to the server...
|
||||||
|
self.ctxt.flush();
|
||||||
|
|
||||||
|
// first of all, get exclusive access to this event queue
|
||||||
|
let mut evq_guard = self.evq.lock().unwrap();
|
||||||
|
|
||||||
|
// dispatch stored events:
|
||||||
|
self.sink.lock().unwrap().drain_queue(&mut callback);
|
||||||
|
|
||||||
|
// read some events from the socket if some are waiting & queue is empty
|
||||||
|
if let Some(guard) = evq_guard.prepare_read() {
|
||||||
|
guard.read_events().expect("Wayland connection unexpectedly lost");
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the callback into the sink
|
||||||
|
unsafe { self.sink.lock().unwrap().set_callback(&mut callback) };
|
||||||
|
|
||||||
|
// then do the actual dispatching
|
||||||
|
self.ctxt.dispatch_pending();
|
||||||
|
evq_guard.dispatch_pending().expect("Wayland connection unexpectedly lost");
|
||||||
|
|
||||||
|
let mut sink_guard = self.sink.lock().unwrap();
|
||||||
|
|
||||||
|
// events where probably dispatched, process resize
|
||||||
|
let ids_guard = self.decorated_ids.lock().unwrap();
|
||||||
|
sink_guard.with_callback(
|
||||||
|
|cb| Self::process_resize(&mut evq_guard, &ids_guard, cb)
|
||||||
|
);
|
||||||
|
|
||||||
|
sink_guard.clear_callback();
|
||||||
|
// we must keep callback alive up to this point!
|
||||||
|
drop(callback);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_forever<F>(&self, mut callback: F)
|
||||||
|
where F: FnMut(::Event)
|
||||||
|
{
|
||||||
|
// send pending requests to the server...
|
||||||
|
self.ctxt.flush();
|
||||||
|
|
||||||
|
// first of all, get exclusive access to this event queue
|
||||||
|
let mut evq_guard = self.evq.lock().unwrap();
|
||||||
|
|
||||||
|
// dispatch stored events:
|
||||||
|
self.sink.lock().unwrap().drain_queue(&mut callback);
|
||||||
|
|
||||||
|
// set the callback into the sink
|
||||||
|
unsafe { self.sink.lock().unwrap().set_callback(&mut callback) };
|
||||||
|
|
||||||
|
while !self.interrupted.load(::std::sync::atomic::Ordering::Relaxed) {
|
||||||
|
self.ctxt.dispatch();
|
||||||
|
evq_guard.dispatch_pending().expect("Wayland connection unexpectedly lost");
|
||||||
|
let ids_guard = self.decorated_ids.lock().unwrap();
|
||||||
|
self.sink.lock().unwrap().with_callback(
|
||||||
|
|cb| Self::process_resize(&mut evq_guard, &ids_guard, cb)
|
||||||
|
);
|
||||||
|
self.ctxt.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.sink.lock().unwrap().clear_callback();
|
||||||
|
// we must keep callback alive up to this point!
|
||||||
|
drop(callback)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,15 @@
|
||||||
use std::collections::VecDeque;
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use {VirtualKeyCode, ElementState, WindowEvent as Event};
|
use {VirtualKeyCode, ElementState, WindowEvent as Event};
|
||||||
|
|
||||||
use events::ModifiersState;
|
use events::ModifiersState;
|
||||||
|
|
||||||
use super::wayland_kbd;
|
use super::{wayland_kbd, make_wid, EventsLoopSink};
|
||||||
use wayland_client::EventQueueHandle;
|
use wayland_client::EventQueueHandle;
|
||||||
use wayland_client::protocol::wl_keyboard;
|
use wayland_client::protocol::{wl_keyboard, wl_surface};
|
||||||
|
|
||||||
pub struct KbdHandler {
|
pub struct KbdHandler {
|
||||||
pub target: Option<Arc<Mutex<VecDeque<Event>>>>
|
pub target: Option<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KbdHandler {
|
impl KbdHandler {
|
||||||
|
@ -31,14 +30,14 @@ impl wayland_kbd::Handler for KbdHandler {
|
||||||
state: wl_keyboard::KeyState,
|
state: wl_keyboard::KeyState,
|
||||||
utf8: Option<String>)
|
utf8: Option<String>)
|
||||||
{
|
{
|
||||||
if let Some(ref eviter) = self.target {
|
if let Some((ref window, ref sink)) = self.target {
|
||||||
let state = match state {
|
let state = match state {
|
||||||
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
|
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
|
||||||
wl_keyboard::KeyState::Released => ElementState::Released,
|
wl_keyboard::KeyState::Released => ElementState::Released,
|
||||||
};
|
};
|
||||||
let vkcode = key_to_vkey(rawkey, keysym);
|
let vkcode = key_to_vkey(rawkey, keysym);
|
||||||
let mut guard = eviter.lock().unwrap();
|
let mut guard = sink.lock().unwrap();
|
||||||
guard.push_back(
|
guard.push_event(
|
||||||
Event::KeyboardInput(
|
Event::KeyboardInput(
|
||||||
state,
|
state,
|
||||||
rawkey as u8,
|
rawkey as u8,
|
||||||
|
@ -49,13 +48,14 @@ impl wayland_kbd::Handler for KbdHandler {
|
||||||
alt: mods.alt,
|
alt: mods.alt,
|
||||||
logo: mods.logo
|
logo: mods.logo
|
||||||
}
|
}
|
||||||
)
|
),
|
||||||
|
make_wid(window)
|
||||||
);
|
);
|
||||||
// send char event only on key press, not release
|
// send char event only on key press, not release
|
||||||
if let ElementState::Released = state { return }
|
if let ElementState::Released = state { return }
|
||||||
if let Some(txt) = utf8 {
|
if let Some(txt) = utf8 {
|
||||||
for chr in txt.chars() {
|
for chr in txt.chars() {
|
||||||
guard.push_back(Event::ReceivedCharacter(chr));
|
guard.push_event(Event::ReceivedCharacter(chr), make_wid(window));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,122 +1,17 @@
|
||||||
#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
|
#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
|
||||||
|
|
||||||
use self::window::Window;
|
pub use self::window::{Window as Window2, WindowId};
|
||||||
|
pub use self::event_loop::EventsLoop;
|
||||||
pub use self::context::{WaylandContext, MonitorId, get_available_monitors,
|
pub use self::context::{WaylandContext, MonitorId, get_available_monitors,
|
||||||
get_primary_monitor};
|
get_primary_monitor};
|
||||||
|
|
||||||
|
use self::window::{make_wid, DecoratedHandler};
|
||||||
|
use self::event_loop::EventsLoopSink;
|
||||||
|
|
||||||
extern crate wayland_kbd;
|
extern crate wayland_kbd;
|
||||||
extern crate wayland_window;
|
extern crate wayland_window;
|
||||||
|
|
||||||
use CreationError;
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
mod context;
|
mod context;
|
||||||
|
mod event_loop;
|
||||||
mod keyboard;
|
mod keyboard;
|
||||||
mod window;
|
mod window;
|
||||||
|
|
||||||
// API TRANSITION
|
|
||||||
//
|
|
||||||
// We don't use the gen_api_transistion!() macro but rather do the expansion manually:
|
|
||||||
//
|
|
||||||
// As this module is nested into platform/linux, its code is not _exactly_ the same as
|
|
||||||
// the one generated by the macro.
|
|
||||||
|
|
||||||
pub struct EventsLoop {
|
|
||||||
windows: ::std::sync::Mutex<Vec<::std::sync::Arc<Window>>>,
|
|
||||||
interrupted: ::std::sync::atomic::AtomicBool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EventsLoop {
|
|
||||||
pub fn new() -> EventsLoop {
|
|
||||||
EventsLoop {
|
|
||||||
windows: ::std::sync::Mutex::new(vec![]),
|
|
||||||
interrupted: ::std::sync::atomic::AtomicBool::new(false),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn interrupt(&self) {
|
|
||||||
self.interrupted.store(true, ::std::sync::atomic::Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn poll_events<F>(&self, mut callback: F)
|
|
||||||
where F: FnMut(::Event)
|
|
||||||
{
|
|
||||||
let windows = self.windows.lock().unwrap();
|
|
||||||
for window in windows.iter() {
|
|
||||||
for event in window.poll_events() {
|
|
||||||
callback(::Event::WindowEvent {
|
|
||||||
window_id: ::WindowId(::platform::WindowId::Wayland(WindowId(&**window as *const Window as usize))),
|
|
||||||
event: event,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run_forever<F>(&self, mut callback: F)
|
|
||||||
where F: FnMut(::Event)
|
|
||||||
{
|
|
||||||
self.interrupted.store(false, ::std::sync::atomic::Ordering::Relaxed);
|
|
||||||
|
|
||||||
// Yeah that's a very bad implementation.
|
|
||||||
loop {
|
|
||||||
self.poll_events(|e| callback(e));
|
|
||||||
::std::thread::sleep(::std::time::Duration::from_millis(5));
|
|
||||||
if self.interrupted.load(::std::sync::atomic::Ordering::Relaxed) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
pub struct WindowId(usize);
|
|
||||||
|
|
||||||
pub struct Window2 {
|
|
||||||
pub window: ::std::sync::Arc<Window>,
|
|
||||||
events_loop: ::std::sync::Weak<::platform::EventsLoop>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::ops::Deref for Window2 {
|
|
||||||
type Target = Window;
|
|
||||||
#[inline]
|
|
||||||
fn deref(&self) -> &Window {
|
|
||||||
&*self.window
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Window2 {
|
|
||||||
pub fn new(events_loop: ::std::sync::Arc<::platform::EventsLoop>, ctxt: Arc<WaylandContext>,
|
|
||||||
window: &::WindowAttributes)
|
|
||||||
-> Result<Window2, CreationError>
|
|
||||||
{
|
|
||||||
let win = ::std::sync::Arc::new(try!(Window::new(ctxt, window)));
|
|
||||||
if let ::platform::EventsLoop::Wayland(ref ev) = *events_loop {
|
|
||||||
ev.windows.lock().unwrap().push(win.clone());
|
|
||||||
} else {
|
|
||||||
// It should not be possible to create an eventloop not matching the backend
|
|
||||||
// in use
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
Ok(Window2 {
|
|
||||||
window: win,
|
|
||||||
events_loop: ::std::sync::Arc::downgrade(&events_loop),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn id(&self) -> WindowId {
|
|
||||||
WindowId(&*self.window as *const Window as usize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for Window2 {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if let Some(ev) = self.events_loop.upgrade() {
|
|
||||||
if let ::platform::EventsLoop::Wayland(ref ev) = *ev {
|
|
||||||
let mut windows = ev.windows.lock().unwrap();
|
|
||||||
windows.retain(|w| &**w as *const Window != &*self.window as *const _);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,141 +1,80 @@
|
||||||
use std::collections::VecDeque;
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use wayland_client::{EventQueue, EventQueueHandle, Init};
|
use wayland_client::{EventQueue, EventQueueHandle, Init, Proxy};
|
||||||
use wayland_client::protocol::{wl_display,wl_surface,wl_shell_surface};
|
use wayland_client::protocol::{wl_display,wl_surface,wl_shell_surface};
|
||||||
|
|
||||||
use {CreationError, MouseCursor, CursorState, WindowEvent as Event, WindowAttributes};
|
use {CreationError, MouseCursor, CursorState, WindowAttributes};
|
||||||
use platform::MonitorId as PlatformMonitorId;
|
use platform::MonitorId as PlatformMonitorId;
|
||||||
|
|
||||||
use super::WaylandContext;
|
use super::{WaylandContext, EventsLoop};
|
||||||
use super::wayland_window;
|
use super::wayland_window;
|
||||||
use super::wayland_window::DecoratedSurface;
|
use super::wayland_window::DecoratedSurface;
|
||||||
|
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
ctxt: Arc<WaylandContext>,
|
ctxt: Arc<WaylandContext>,
|
||||||
evq: Mutex<EventQueue>,
|
evq: Arc<Mutex<EventQueue>>,
|
||||||
eviter: Arc<Mutex<VecDeque<Event>>>,
|
|
||||||
surface: Arc<wl_surface::WlSurface>,
|
surface: Arc<wl_surface::WlSurface>,
|
||||||
size: Mutex<(u32, u32)>,
|
size: Mutex<(u32, u32)>,
|
||||||
handler_id: usize,
|
|
||||||
decorated_id: usize
|
decorated_id: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PollEventsIterator<'a> {
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
window: &'a Window,
|
pub struct WindowId(usize);
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Iterator for PollEventsIterator<'a> {
|
#[inline]
|
||||||
type Item = Event;
|
pub fn make_wid(s: &wl_surface::WlSurface) -> WindowId {
|
||||||
|
WindowId(s.ptr() as usize)
|
||||||
fn next(&mut self) -> Option<Event> {
|
|
||||||
self.window.next_event(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
pub fn new(ctxt: Arc<WaylandContext>, attributes: &WindowAttributes) -> Result<Window, CreationError>
|
pub fn new(evlp: &EventsLoop, ctxt: Arc<WaylandContext>, attributes: &WindowAttributes) -> Result<Window, CreationError>
|
||||||
{
|
{
|
||||||
let (width, height) = attributes.dimensions.unwrap_or((800,600));
|
let (width, height) = attributes.dimensions.unwrap_or((800,600));
|
||||||
|
|
||||||
let mut evq = ctxt.display.create_event_queue();
|
let (surface, decorated) = ctxt.create_window::<DecoratedHandler>(evlp.get_sink());
|
||||||
|
|
||||||
let (surface, eviter, decorated) = ctxt.create_window::<DecoratedHandler>();
|
|
||||||
|
|
||||||
// init DecoratedSurface
|
// init DecoratedSurface
|
||||||
let decorated_id = evq.add_handler_with_init(decorated);
|
let evq = evlp.get_event_queue();
|
||||||
{
|
let decorated_id = {
|
||||||
let mut state = evq.state();
|
let mut evq_guard = evq.lock().unwrap();
|
||||||
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(decorated_id);
|
let decorated_id = evq_guard.add_handler_with_init(decorated);
|
||||||
*(decorated.handler()) = Some(DecoratedHandler::new());
|
{
|
||||||
|
let mut state = evq_guard.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 {
|
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(
|
||||||
wl_shell_surface::FullscreenMethod::Default,
|
wl_shell_surface::FullscreenMethod::Default,
|
||||||
0,
|
0,
|
||||||
Some(output)
|
Some(output)
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
} else if attributes.decorations {
|
} else if attributes.decorations {
|
||||||
decorated.set_decorate(true);
|
decorated.set_decorate(true);
|
||||||
|
}
|
||||||
|
// Finally, set the decorations size
|
||||||
|
decorated.resize(width as i32, height as i32);
|
||||||
}
|
}
|
||||||
// Finally, set the decorations size
|
decorated_id
|
||||||
decorated.resize(width as i32, height as i32);
|
};
|
||||||
}
|
let me = Window {
|
||||||
|
|
||||||
// init general handler
|
|
||||||
let handler = WindowHandler::new();
|
|
||||||
let handler_id = evq.add_handler_with_init(handler);
|
|
||||||
|
|
||||||
Ok(Window {
|
|
||||||
ctxt: ctxt,
|
ctxt: ctxt,
|
||||||
evq: Mutex::new(evq),
|
evq: evq,
|
||||||
eviter: eviter,
|
|
||||||
surface: surface,
|
surface: surface,
|
||||||
size: Mutex::new((width, height)),
|
size: Mutex::new((width, height)),
|
||||||
handler_id: handler_id,
|
|
||||||
decorated_id: decorated_id
|
decorated_id: decorated_id
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_resize(&self) {
|
|
||||||
let mut evq_guard = self.evq.lock().unwrap();
|
|
||||||
let mut state = evq_guard.state();
|
|
||||||
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(self.decorated_id);
|
|
||||||
if let Some((w, h)) = decorated.handler().as_mut().and_then(|h| h.take_newsize()) {
|
|
||||||
decorated.resize(w as i32, h as i32);
|
|
||||||
*self.size.lock().unwrap() = (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 }
|
|
||||||
|
|
||||||
// There is no event in the queue, we need to fetch more
|
|
||||||
|
|
||||||
// flush the display
|
|
||||||
self.ctxt.flush();
|
|
||||||
|
|
||||||
// read some events if some are waiting & queue is empty
|
|
||||||
if let Some(guard) = self.evq.lock().unwrap().prepare_read() {
|
|
||||||
guard.read_events().expect("Wayland connection unexpectedly lost");
|
|
||||||
}
|
|
||||||
|
|
||||||
// try a pending dispatch
|
|
||||||
{
|
|
||||||
self.ctxt.dispatch_pending();
|
|
||||||
self.evq.lock().unwrap().dispatch_pending()
|
|
||||||
.expect("Wayland connection unexpectedly lost");
|
|
||||||
// some events were dispatched, need to process a potential resising
|
|
||||||
self.process_resize();
|
|
||||||
}
|
|
||||||
|
|
||||||
evt = {
|
|
||||||
let mut guard = self.eviter.lock().unwrap();
|
|
||||||
guard.pop_front()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
while block && evt.is_none() {
|
evlp.register_window(me.decorated_id, me.id());
|
||||||
// no event waiting, need to repopulate!
|
|
||||||
{
|
Ok(me)
|
||||||
self.ctxt.flush();
|
}
|
||||||
self.ctxt.dispatch();
|
|
||||||
self.evq.lock().unwrap().dispatch_pending()
|
#[inline]
|
||||||
.expect("Wayland connection unexpectedly lost");
|
pub fn id(&self) -> WindowId {
|
||||||
// some events were dispatched, need to process a potential resising
|
make_wid(&self.surface)
|
||||||
self.process_resize();
|
|
||||||
}
|
|
||||||
// try again
|
|
||||||
let mut guard = self.eviter.lock().unwrap();
|
|
||||||
evt = guard.pop_front();
|
|
||||||
}
|
|
||||||
evt
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_title(&self, title: &str) {
|
pub fn set_title(&self, title: &str) {
|
||||||
|
@ -186,13 +125,6 @@ impl Window {
|
||||||
decorated.resize(x as i32, y as i32);
|
decorated.resize(x as i32, y as i32);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn poll_events(&self) -> PollEventsIterator {
|
|
||||||
PollEventsIterator {
|
|
||||||
window: self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_cursor(&self, _cursor: MouseCursor) {
|
pub fn set_cursor(&self, _cursor: MouseCursor) {
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -237,13 +169,14 @@ impl Drop for Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DecoratedHandler {
|
pub struct DecoratedHandler {
|
||||||
newsize: Option<(u32, u32)>
|
newsize: Option<(u32, u32)>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DecoratedHandler {
|
impl DecoratedHandler {
|
||||||
fn new() -> DecoratedHandler { DecoratedHandler { newsize: None }}
|
fn new() -> DecoratedHandler { DecoratedHandler { newsize: None }}
|
||||||
fn take_newsize(&mut self) -> Option<(u32, u32)> {
|
|
||||||
|
pub fn take_newsize(&mut self) -> Option<(u32, u32)> {
|
||||||
self.newsize.take()
|
self.newsize.take()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,21 +191,3 @@ impl wayland_window::Handler for DecoratedHandler {
|
||||||
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WindowHandler {
|
|
||||||
my_id: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WindowHandler {
|
|
||||||
fn new() -> WindowHandler {
|
|
||||||
WindowHandler {
|
|
||||||
my_id: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Init for WindowHandler {
|
|
||||||
fn init(&mut self, _evqh: &mut EventQueueHandle, index: usize) {
|
|
||||||
self.my_id = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue