Upgrade to smithay-client-toolkit 0.4 (#671)

* Upgrade to smithay-client-toolkit 0.4

* Fix PR points
This commit is contained in:
trimental 2018-10-15 07:15:43 +08:00 committed by Francesca Plebani
parent 808638fee3
commit 50008dff3d
7 changed files with 326 additions and 299 deletions

View file

@ -1,5 +1,8 @@
# Unreleased # Unreleased
- On Wayland, titles will now be displayed in the window header decoration
- On Wayland, key repetition is now ended when keyboard loses focus
- On Wayland, windows will now use more stylish and modern client side decorations.
- On Wayland, windows will use server-side decorations when available. - On Wayland, windows will use server-side decorations when available.
- Added support for F16-F24 keys. - Added support for F16-F24 keys.
- Fixed graphical glitches when resizing on Wayland. - Fixed graphical glitches when resizing on Wayland.

View file

@ -54,8 +54,8 @@ features = [
] ]
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] [target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies]
wayland-client = { version = "0.20.10", features = [ "dlopen", "egl", "cursor"] } wayland-client = { version = "0.21", features = [ "dlopen", "egl", "cursor"] }
smithay-client-toolkit = "0.3.0" smithay-client-toolkit = "0.4"
x11-dl = "2.18.3" x11-dl = "2.18.3"
parking_lot = "0.6" parking_lot = "0.6"
percent-encoding = "1.0" percent-encoding = "1.0"

View file

@ -10,7 +10,6 @@ use super::window::WindowStore;
use super::WindowId; use super::WindowId;
use sctk::output::OutputMgr; use sctk::output::OutputMgr;
use sctk::reexports::client::commons::Implementation;
use sctk::reexports::client::protocol::{ use sctk::reexports::client::protocol::{
wl_keyboard, wl_output, wl_pointer, wl_registry, wl_seat, wl_touch, wl_keyboard, wl_output, wl_pointer, wl_registry, wl_seat, wl_touch,
}; };
@ -93,7 +92,7 @@ impl EventsLoopProxy {
// Update the `EventsLoop`'s `pending_wakeup` flag. // Update the `EventsLoop`'s `pending_wakeup` flag.
wakeup.store(true, Ordering::Relaxed); wakeup.store(true, Ordering::Relaxed);
// Cause the `EventsLoop` to break from `dispatch` if it is currently blocked. // Cause the `EventsLoop` to break from `dispatch` if it is currently blocked.
let _ = display.sync(); let _ = display.sync(|callback| callback.implement(|_, _| {}, ()));
display.flush().map_err(|_| EventsLoopClosed)?; display.flush().map_err(|_| EventsLoopClosed)?;
Ok(()) Ok(())
} }
@ -112,17 +111,21 @@ impl EventsLoop {
let store = Arc::new(Mutex::new(WindowStore::new())); let store = Arc::new(Mutex::new(WindowStore::new()));
let seats = Arc::new(Mutex::new(Vec::new())); let seats = Arc::new(Mutex::new(Vec::new()));
let env = Environment::from_registry_with_cb( let mut seat_manager = SeatManager {
display.get_registry().unwrap(), sink: sink.clone(),
store: store.clone(),
seats: seats.clone(),
events_loop_proxy: EventsLoopProxy {
display: Arc::downgrade(&display),
pending_wakeup: Arc::downgrade(&pending_wakeup),
},
};
let env = Environment::from_display_with_cb(
&display,
&mut event_queue, &mut event_queue,
SeatManager { move |event, registry| {
sink: sink.clone(), seat_manager.receive(event, registry)
store: store.clone(),
seats: seats.clone(),
events_loop_proxy: EventsLoopProxy {
display: Arc::downgrade(&display),
pending_wakeup: Arc::downgrade(&pending_wakeup),
},
}, },
).unwrap(); ).unwrap();
@ -280,7 +283,7 @@ struct SeatManager {
events_loop_proxy: EventsLoopProxy, events_loop_proxy: EventsLoopProxy,
} }
impl Implementation<Proxy<wl_registry::WlRegistry>, GlobalEvent> for SeatManager { impl SeatManager {
fn receive(&mut self, evt: GlobalEvent, registry: Proxy<wl_registry::WlRegistry>) { fn receive(&mut self, evt: GlobalEvent, registry: Proxy<wl_registry::WlRegistry>) {
use self::wl_registry::RequestsTrait as RegistryRequests; use self::wl_registry::RequestsTrait as RegistryRequests;
use self::wl_seat::RequestsTrait as SeatRequests; use self::wl_seat::RequestsTrait as SeatRequests;
@ -292,17 +295,22 @@ impl Implementation<Proxy<wl_registry::WlRegistry>, GlobalEvent> for SeatManager
} if interface == "wl_seat" => } if interface == "wl_seat" =>
{ {
use std::cmp::min; use std::cmp::min;
let mut seat_data = SeatData {
sink: self.sink.clone(),
store: self.store.clone(),
pointer: None,
keyboard: None,
touch: None,
events_loop_proxy: self.events_loop_proxy.clone(),
};
let seat = registry let seat = registry
.bind::<wl_seat::WlSeat>(min(version, 5), id) .bind(min(version, 5), id, move |seat| {
.unwrap() seat.implement(move |event, seat| {
.implement(SeatData { seat_data.receive(event, seat)
sink: self.sink.clone(), }, ())
store: self.store.clone(), })
pointer: None, .unwrap();
keyboard: None,
touch: None,
events_loop_proxy: self.events_loop_proxy.clone(),
});
self.store.lock().unwrap().new_seat(&seat); self.store.lock().unwrap().new_seat(&seat);
self.seats.lock().unwrap().push((id, seat)); self.seats.lock().unwrap().push((id, seat));
} }
@ -329,16 +337,15 @@ struct SeatData {
events_loop_proxy: EventsLoopProxy, events_loop_proxy: EventsLoopProxy,
} }
impl Implementation<Proxy<wl_seat::WlSeat>, wl_seat::Event> for SeatData { impl SeatData {
fn receive(&mut self, evt: wl_seat::Event, seat: Proxy<wl_seat::WlSeat>) { fn receive(&mut self, evt: wl_seat::Event, seat: Proxy<wl_seat::WlSeat>) {
use self::wl_seat::RequestsTrait as SeatRequests;
match evt { match evt {
wl_seat::Event::Name { .. } => (), wl_seat::Event::Name { .. } => (),
wl_seat::Event::Capabilities { capabilities } => { wl_seat::Event::Capabilities { capabilities } => {
// create pointer if applicable // create pointer if applicable
if capabilities.contains(wl_seat::Capability::Pointer) && self.pointer.is_none() { if capabilities.contains(wl_seat::Capability::Pointer) && self.pointer.is_none() {
self.pointer = Some(super::pointer::implement_pointer( self.pointer = Some(super::pointer::implement_pointer(
seat.get_pointer().unwrap(), &seat,
self.sink.clone(), self.sink.clone(),
self.store.clone(), self.store.clone(),
)) ))
@ -355,7 +362,7 @@ impl Implementation<Proxy<wl_seat::WlSeat>, wl_seat::Event> for SeatData {
// create keyboard if applicable // create keyboard if applicable
if capabilities.contains(wl_seat::Capability::Keyboard) && self.keyboard.is_none() { if capabilities.contains(wl_seat::Capability::Keyboard) && self.keyboard.is_none() {
self.keyboard = Some(super::keyboard::init_keyboard( self.keyboard = Some(super::keyboard::init_keyboard(
seat.get_keyboard().unwrap(), &seat,
self.sink.clone(), self.sink.clone(),
self.events_loop_proxy.clone(), self.events_loop_proxy.clone(),
)) ))
@ -372,7 +379,7 @@ impl Implementation<Proxy<wl_seat::WlSeat>, wl_seat::Event> for SeatData {
// create touch if applicable // create touch if applicable
if capabilities.contains(wl_seat::Capability::Touch) && self.touch.is_none() { if capabilities.contains(wl_seat::Capability::Touch) && self.touch.is_none() {
self.touch = Some(super::touch::implement_touch( self.touch = Some(super::touch::implement_touch(
seat.get_touch().unwrap(), &seat,
self.sink.clone(), self.sink.clone(),
self.store.clone(), self.store.clone(),
)) ))

View file

@ -5,11 +5,14 @@ use sctk::keyboard::{
self, map_keyboard_auto_with_repeat, Event as KbEvent, KeyRepeatEvent, KeyRepeatKind, self, map_keyboard_auto_with_repeat, Event as KbEvent, KeyRepeatEvent, KeyRepeatKind,
}; };
use sctk::reexports::client::protocol::wl_keyboard; use sctk::reexports::client::protocol::wl_keyboard;
use sctk::reexports::client::{NewProxy, Proxy}; use sctk::reexports::client::Proxy;
use sctk::reexports::client::protocol::wl_seat;
use sctk::reexports::client::protocol::wl_seat::RequestsTrait as SeatRequests;
use {ElementState, KeyboardInput, ModifiersState, VirtualKeyCode, WindowEvent}; use {ElementState, KeyboardInput, ModifiersState, VirtualKeyCode, WindowEvent};
pub fn init_keyboard( pub fn init_keyboard(
keyboard: NewProxy<wl_keyboard::WlKeyboard>, seat: &Proxy<wl_seat::WlSeat>,
sink: Arc<Mutex<EventsLoopSink>>, sink: Arc<Mutex<EventsLoopSink>>,
events_loop_proxy: EventsLoopProxy, events_loop_proxy: EventsLoopProxy,
) -> Proxy<wl_keyboard::WlKeyboard> { ) -> Proxy<wl_keyboard::WlKeyboard> {
@ -18,9 +21,11 @@ pub fn init_keyboard(
let my_sink = sink.clone(); let my_sink = sink.clone();
let repeat_sink = sink.clone(); let repeat_sink = sink.clone();
let repeat_target = target.clone(); let repeat_target = target.clone();
let modifiers = Arc::new(Mutex::new(ModifiersState::default()));
let my_modifiers = modifiers.clone();
// } // }
let ret = map_keyboard_auto_with_repeat( let ret = map_keyboard_auto_with_repeat(
keyboard, seat,
KeyRepeatKind::System, KeyRepeatKind::System,
move |evt: KbEvent, _| match evt { move |evt: KbEvent, _| match evt {
KbEvent::Enter { surface, .. } => { KbEvent::Enter { surface, .. } => {
@ -40,7 +45,6 @@ pub fn init_keyboard(
*target.lock().unwrap() = None; *target.lock().unwrap() = None;
} }
KbEvent::Key { KbEvent::Key {
modifiers,
rawkey, rawkey,
keysym, keysym,
state, state,
@ -61,7 +65,7 @@ pub fn init_keyboard(
state: state, state: state,
scancode: rawkey, scancode: rawkey,
virtual_keycode: vkcode, virtual_keycode: vkcode,
modifiers: modifiers.into(), modifiers: modifiers.lock().unwrap().clone(),
}, },
}, },
wid, wid,
@ -78,6 +82,9 @@ pub fn init_keyboard(
} }
} }
KbEvent::RepeatInfo { .. } => { /* Handled by smithay client toolkit */ } KbEvent::RepeatInfo { .. } => { /* Handled by smithay client toolkit */ }
KbEvent::Modifiers { modifiers: event_modifiers } => {
*modifiers.lock().unwrap() = event_modifiers.into()
}
}, },
move |repeat_event: KeyRepeatEvent, _| { move |repeat_event: KeyRepeatEvent, _| {
if let Some(wid) = *repeat_target.lock().unwrap() { if let Some(wid) = *repeat_target.lock().unwrap() {
@ -91,7 +98,7 @@ pub fn init_keyboard(
state: state, state: state,
scancode: repeat_event.rawkey, scancode: repeat_event.rawkey,
virtual_keycode: vkcode, virtual_keycode: vkcode,
modifiers: repeat_event.modifiers.into(), modifiers: my_modifiers.lock().unwrap().clone(),
}, },
}, },
wid, wid,
@ -108,7 +115,7 @@ pub fn init_keyboard(
match ret { match ret {
Ok(keyboard) => keyboard, Ok(keyboard) => keyboard,
Err((_, keyboard)) => { Err(_) => {
// This is a fallback impl if libxkbcommon was not available // This is a 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...
@ -120,45 +127,47 @@ pub fn init_keyboard(
let mut target = None; let mut target = None;
let my_sink = sink; let my_sink = sink;
// } // }
keyboard.implement(move |evt, _| match evt { seat.get_keyboard(|keyboard| {
wl_keyboard::Event::Enter { surface, .. } => { keyboard.implement(move |evt, _| match evt {
let wid = make_wid(&surface); wl_keyboard::Event::Enter { surface, .. } => {
my_sink let wid = make_wid(&surface);
.lock() my_sink
.unwrap() .lock()
.send_event(WindowEvent::Focused(true), wid); .unwrap()
target = Some(wid); .send_event(WindowEvent::Focused(true), wid);
} target = Some(wid);
wl_keyboard::Event::Leave { surface, .. } => {
let wid = make_wid(&surface);
my_sink
.lock()
.unwrap()
.send_event(WindowEvent::Focused(false), wid);
target = None;
}
wl_keyboard::Event::Key { key, state, .. } => {
if let Some(wid) = target {
let state = match state {
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
wl_keyboard::KeyState::Released => ElementState::Released,
};
my_sink.lock().unwrap().send_event(
WindowEvent::KeyboardInput {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
input: KeyboardInput {
state: state,
scancode: key,
virtual_keycode: None,
modifiers: ModifiersState::default(),
},
},
wid,
);
} }
} wl_keyboard::Event::Leave { surface, .. } => {
_ => (), let wid = make_wid(&surface);
}) my_sink
.lock()
.unwrap()
.send_event(WindowEvent::Focused(false), wid);
target = None;
}
wl_keyboard::Event::Key { key, state, .. } => {
if let Some(wid) = target {
let state = match state {
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
wl_keyboard::KeyState::Released => ElementState::Released,
};
my_sink.lock().unwrap().send_event(
WindowEvent::KeyboardInput {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
input: KeyboardInput {
state: state,
scancode: key,
virtual_keycode: None,
modifiers: ModifiersState::default(),
},
},
wid,
);
}
}
_ => (),
}, ())
}).unwrap()
} }
} }
} }

View file

@ -7,11 +7,13 @@ use super::DeviceId;
use super::event_loop::EventsLoopSink; use super::event_loop::EventsLoopSink;
use super::window::WindowStore; use super::window::WindowStore;
use sctk::reexports::client::{NewProxy, Proxy}; use sctk::reexports::client::Proxy;
use sctk::reexports::client::protocol::wl_pointer::{self, Event as PtrEvent, WlPointer}; use sctk::reexports::client::protocol::wl_pointer::{self, Event as PtrEvent, WlPointer};
use sctk::reexports::client::protocol::wl_seat;
use sctk::reexports::client::protocol::wl_seat::RequestsTrait as SeatRequests;
pub fn implement_pointer( pub fn implement_pointer(
pointer: NewProxy<WlPointer>, seat: &Proxy<wl_seat::WlSeat>,
sink: Arc<Mutex<EventsLoopSink>>, sink: Arc<Mutex<EventsLoopSink>>,
store: Arc<Mutex<WindowStore>>, store: Arc<Mutex<WindowStore>>,
) -> Proxy<WlPointer> { ) -> Proxy<WlPointer> {
@ -20,146 +22,30 @@ pub fn implement_pointer(
let mut axis_discrete_buffer = None; let mut axis_discrete_buffer = None;
let mut axis_state = TouchPhase::Ended; let mut axis_state = TouchPhase::Ended;
pointer.implement(move |evt, pointer: Proxy<_>| { seat.get_pointer(|pointer| {
let mut sink = sink.lock().unwrap(); pointer.implement(move |evt, pointer| {
let store = store.lock().unwrap(); let mut sink = sink.lock().unwrap();
match evt { let store = store.lock().unwrap();
PtrEvent::Enter { match evt {
surface, PtrEvent::Enter {
surface_x, surface,
surface_y, surface_x,
.. surface_y,
} => { ..
let wid = store.find_wid(&surface); } => {
if let Some(wid) = wid { let wid = store.find_wid(&surface);
mouse_focus = Some(wid); if let Some(wid) = wid {
sink.send_event( mouse_focus = Some(wid);
WindowEvent::CursorEntered {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
},
wid,
);
sink.send_event(
WindowEvent::CursorMoved {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
position: (surface_x, surface_y).into(),
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
},
wid,
);
}
}
PtrEvent::Leave { surface, .. } => {
mouse_focus = None;
let wid = store.find_wid(&surface);
if let Some(wid) = wid {
sink.send_event(
WindowEvent::CursorLeft {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
},
wid,
);
}
}
PtrEvent::Motion {
surface_x,
surface_y,
..
} => {
if let Some(wid) = mouse_focus {
sink.send_event(
WindowEvent::CursorMoved {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
position: (surface_x, surface_y).into(),
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
},
wid,
);
}
}
PtrEvent::Button { button, state, .. } => {
if let Some(wid) = mouse_focus {
let state = match state {
wl_pointer::ButtonState::Pressed => ElementState::Pressed,
wl_pointer::ButtonState::Released => ElementState::Released,
};
let button = match button {
0x110 => MouseButton::Left,
0x111 => MouseButton::Right,
0x112 => MouseButton::Middle,
// TODO figure out the translation ?
_ => return,
};
sink.send_event(
WindowEvent::MouseInput {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
state: state,
button: button,
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
},
wid,
);
}
}
PtrEvent::Axis { axis, value, .. } => {
if let Some(wid) = mouse_focus {
if pointer.version() < 5 {
let (mut x, mut y) = (0.0, 0.0);
// old seat compatibility
match axis {
// wayland vertical sign convention is the inverse of winit
wl_pointer::Axis::VerticalScroll => y -= value as f32,
wl_pointer::Axis::HorizontalScroll => x += value as f32,
}
sink.send_event( sink.send_event(
WindowEvent::MouseWheel { WindowEvent::CursorEntered {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)), device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
delta: MouseScrollDelta::PixelDelta((x as f64, y as f64).into()),
phase: TouchPhase::Moved,
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
}, },
wid, wid,
); );
} else {
let (mut x, mut y) = axis_buffer.unwrap_or((0.0, 0.0));
match axis {
// wayland vertical sign convention is the inverse of winit
wl_pointer::Axis::VerticalScroll => y -= value as f32,
wl_pointer::Axis::HorizontalScroll => x += value as f32,
}
axis_buffer = Some((x, y));
axis_state = match axis_state {
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
_ => TouchPhase::Started,
}
}
}
}
PtrEvent::Frame => {
let axis_buffer = axis_buffer.take();
let axis_discrete_buffer = axis_discrete_buffer.take();
if let Some(wid) = mouse_focus {
if let Some((x, y)) = axis_discrete_buffer {
sink.send_event( sink.send_event(
WindowEvent::MouseWheel { WindowEvent::CursorMoved {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)), device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
delta: MouseScrollDelta::LineDelta(x as f32, y as f32), position: (surface_x, surface_y).into(),
phase: axis_state,
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
},
wid,
);
} else if let Some((x, y)) = axis_buffer {
sink.send_event(
WindowEvent::MouseWheel {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
delta: MouseScrollDelta::PixelDelta((x as f64, y as f64).into()),
phase: axis_state,
// TODO: replace dummy value with actual modifier state // TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(), modifiers: ModifiersState::default(),
}, },
@ -167,24 +53,142 @@ pub fn implement_pointer(
); );
} }
} }
} PtrEvent::Leave { surface, .. } => {
PtrEvent::AxisSource { .. } => (), mouse_focus = None;
PtrEvent::AxisStop { .. } => { let wid = store.find_wid(&surface);
axis_state = TouchPhase::Ended; if let Some(wid) = wid {
} sink.send_event(
PtrEvent::AxisDiscrete { axis, discrete } => { WindowEvent::CursorLeft {
let (mut x, mut y) = axis_discrete_buffer.unwrap_or((0, 0)); device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
match axis { },
// wayland vertical sign convention is the inverse of winit wid,
wl_pointer::Axis::VerticalScroll => y -= discrete, );
wl_pointer::Axis::HorizontalScroll => x += discrete, }
} }
axis_discrete_buffer = Some((x, y)); PtrEvent::Motion {
axis_state = match axis_state { surface_x,
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved, surface_y,
_ => TouchPhase::Started, ..
} => {
if let Some(wid) = mouse_focus {
sink.send_event(
WindowEvent::CursorMoved {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
position: (surface_x, surface_y).into(),
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
},
wid,
);
}
}
PtrEvent::Button { button, state, .. } => {
if let Some(wid) = mouse_focus {
let state = match state {
wl_pointer::ButtonState::Pressed => ElementState::Pressed,
wl_pointer::ButtonState::Released => ElementState::Released,
};
let button = match button {
0x110 => MouseButton::Left,
0x111 => MouseButton::Right,
0x112 => MouseButton::Middle,
// TODO figure out the translation ?
_ => return,
};
sink.send_event(
WindowEvent::MouseInput {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
state: state,
button: button,
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
},
wid,
);
}
}
PtrEvent::Axis { axis, value, .. } => {
if let Some(wid) = mouse_focus {
if pointer.version() < 5 {
let (mut x, mut y) = (0.0, 0.0);
// old seat compatibility
match axis {
// wayland vertical sign convention is the inverse of winit
wl_pointer::Axis::VerticalScroll => y -= value as f32,
wl_pointer::Axis::HorizontalScroll => x += value as f32,
}
sink.send_event(
WindowEvent::MouseWheel {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
delta: MouseScrollDelta::PixelDelta((x as f64, y as f64).into()),
phase: TouchPhase::Moved,
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
},
wid,
);
} else {
let (mut x, mut y) = axis_buffer.unwrap_or((0.0, 0.0));
match axis {
// wayland vertical sign convention is the inverse of winit
wl_pointer::Axis::VerticalScroll => y -= value as f32,
wl_pointer::Axis::HorizontalScroll => x += value as f32,
}
axis_buffer = Some((x, y));
axis_state = match axis_state {
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
_ => TouchPhase::Started,
}
}
}
}
PtrEvent::Frame => {
let axis_buffer = axis_buffer.take();
let axis_discrete_buffer = axis_discrete_buffer.take();
if let Some(wid) = mouse_focus {
if let Some((x, y)) = axis_discrete_buffer {
sink.send_event(
WindowEvent::MouseWheel {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
delta: MouseScrollDelta::LineDelta(x as f32, y as f32),
phase: axis_state,
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
},
wid,
);
} else if let Some((x, y)) = axis_buffer {
sink.send_event(
WindowEvent::MouseWheel {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
delta: MouseScrollDelta::PixelDelta((x as f64, y as f64).into()),
phase: axis_state,
// TODO: replace dummy value with actual modifier state
modifiers: ModifiersState::default(),
},
wid,
);
}
}
}
PtrEvent::AxisSource { .. } => (),
PtrEvent::AxisStop { .. } => {
axis_state = TouchPhase::Ended;
}
PtrEvent::AxisDiscrete { axis, discrete } => {
let (mut x, mut y) = axis_discrete_buffer.unwrap_or((0, 0));
match axis {
// wayland vertical sign convention is the inverse of winit
wl_pointer::Axis::VerticalScroll => y -= discrete,
wl_pointer::Axis::HorizontalScroll => x += discrete,
}
axis_discrete_buffer = Some((x, y));
axis_state = match axis_state {
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
_ => TouchPhase::Started,
}
} }
} }
} }, ())
}) }).unwrap()
} }

View file

@ -6,8 +6,10 @@ use super::{DeviceId, WindowId};
use super::event_loop::EventsLoopSink; use super::event_loop::EventsLoopSink;
use super::window::WindowStore; use super::window::WindowStore;
use sctk::reexports::client::{NewProxy, Proxy}; use sctk::reexports::client::Proxy;
use sctk::reexports::client::protocol::wl_touch::{Event as TouchEvent, WlTouch}; use sctk::reexports::client::protocol::wl_touch::{Event as TouchEvent, WlTouch};
use sctk::reexports::client::protocol::wl_seat;
use sctk::reexports::client::protocol::wl_seat::RequestsTrait as SeatRequests;
struct TouchPoint { struct TouchPoint {
wid: WindowId, wid: WindowId,
@ -16,78 +18,80 @@ struct TouchPoint {
} }
pub(crate) fn implement_touch( pub(crate) fn implement_touch(
touch: NewProxy<WlTouch>, seat: &Proxy<wl_seat::WlSeat>,
sink: Arc<Mutex<EventsLoopSink>>, sink: Arc<Mutex<EventsLoopSink>>,
store: Arc<Mutex<WindowStore>>, store: Arc<Mutex<WindowStore>>,
) -> Proxy<WlTouch> { ) -> Proxy<WlTouch> {
let mut pending_ids = Vec::new(); let mut pending_ids = Vec::new();
touch.implement(move |evt, _| { seat.get_touch(|touch| {
let mut sink = sink.lock().unwrap(); touch.implement(move |evt, _| {
let store = store.lock().unwrap(); let mut sink = sink.lock().unwrap();
match evt { let store = store.lock().unwrap();
TouchEvent::Down { match evt {
surface, id, x, y, .. TouchEvent::Down {
} => { surface, id, x, y, ..
let wid = store.find_wid(&surface); } => {
if let Some(wid) = wid { let wid = store.find_wid(&surface);
sink.send_event( if let Some(wid) = wid {
WindowEvent::Touch(::Touch { sink.send_event(
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)), WindowEvent::Touch(::Touch {
phase: TouchPhase::Started, device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
location: (x, y).into(), phase: TouchPhase::Started,
id: id as u64, location: (x, y).into(),
}), id: id as u64,
wid, }),
); wid,
pending_ids.push(TouchPoint { );
wid: wid, pending_ids.push(TouchPoint {
location: (x, y), wid: wid,
id: id, location: (x, y),
}); id: id,
});
}
} }
} TouchEvent::Up { id, .. } => {
TouchEvent::Up { id, .. } => { let idx = pending_ids.iter().position(|p| p.id == id);
let idx = pending_ids.iter().position(|p| p.id == id); if let Some(idx) = idx {
if let Some(idx) = idx { let pt = pending_ids.remove(idx);
let pt = pending_ids.remove(idx); sink.send_event(
WindowEvent::Touch(::Touch {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
phase: TouchPhase::Ended,
location: pt.location.into(),
id: id as u64,
}),
pt.wid,
);
}
}
TouchEvent::Motion { id, x, y, .. } => {
let pt = pending_ids.iter_mut().find(|p| p.id == id);
if let Some(pt) = pt {
pt.location = (x, y);
sink.send_event(
WindowEvent::Touch(::Touch {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
phase: TouchPhase::Moved,
location: (x, y).into(),
id: id as u64,
}),
pt.wid,
);
}
}
TouchEvent::Frame => (),
TouchEvent::Cancel => for pt in pending_ids.drain(..) {
sink.send_event( sink.send_event(
WindowEvent::Touch(::Touch { WindowEvent::Touch(::Touch {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)), device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
phase: TouchPhase::Ended, phase: TouchPhase::Cancelled,
location: pt.location.into(), location: pt.location.into(),
id: id as u64, id: pt.id as u64,
}), }),
pt.wid, pt.wid,
); );
} },
} }
TouchEvent::Motion { id, x, y, .. } => { }, ())
let pt = pending_ids.iter_mut().find(|p| p.id == id); }).unwrap()
if let Some(pt) = pt {
pt.location = (x, y);
sink.send_event(
WindowEvent::Touch(::Touch {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
phase: TouchPhase::Moved,
location: (x, y).into(),
id: id as u64,
}),
pt.wid,
);
}
}
TouchEvent::Frame => (),
TouchEvent::Cancel => for pt in pending_ids.drain(..) {
sink.send_event(
WindowEvent::Touch(::Touch {
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
phase: TouchPhase::Cancelled,
location: pt.location.into(),
id: pt.id as u64,
}),
pt.wid,
);
},
}
})
} }

View file

@ -6,7 +6,7 @@ use dpi::{LogicalPosition, LogicalSize};
use platform::MonitorId as PlatformMonitorId; use platform::MonitorId as PlatformMonitorId;
use window::MonitorId as RootMonitorId; use window::MonitorId as RootMonitorId;
use sctk::window::{BasicFrame, Event as WEvent, Window as SWindow}; use sctk::window::{ConceptFrame, Event as WEvent, Window as SWindow};
use sctk::reexports::client::{Display, Proxy}; use sctk::reexports::client::{Display, Proxy};
use sctk::reexports::client::protocol::{wl_seat, wl_surface, wl_output}; use sctk::reexports::client::protocol::{wl_seat, wl_surface, wl_output};
use sctk::reexports::client::protocol::wl_compositor::RequestsTrait as CompositorRequests; use sctk::reexports::client::protocol::wl_compositor::RequestsTrait as CompositorRequests;
@ -18,7 +18,7 @@ use platform::platform::wayland::event_loop::{get_available_monitors, get_primar
pub struct Window { pub struct Window {
surface: Proxy<wl_surface::WlSurface>, surface: Proxy<wl_surface::WlSurface>,
frame: Arc<Mutex<SWindow<BasicFrame>>>, frame: Arc<Mutex<SWindow<ConceptFrame>>>,
monitors: Arc<Mutex<MonitorList>>, // Monitors this window is currently on monitors: Arc<Mutex<MonitorList>>, // Monitors this window is currently on
outputs: OutputMgr, // Access to info for all monitors outputs: OutputMgr, // Access to info for all monitors
size: Arc<Mutex<(u32, u32)>>, size: Arc<Mutex<(u32, u32)>>,
@ -36,11 +36,11 @@ impl Window {
// monitor tracking // monitor tracking
let monitor_list = Arc::new(Mutex::new(MonitorList::new())); let monitor_list = Arc::new(Mutex::new(MonitorList::new()));
let surface = evlp.env.compositor.create_surface().unwrap().implement({ let surface = evlp.env.compositor.create_surface(|surface| {
let list = monitor_list.clone(); let list = monitor_list.clone();
let omgr = evlp.env.outputs.clone(); let omgr = evlp.env.outputs.clone();
let window_store = evlp.store.clone(); let window_store = evlp.store.clone();
move |event, surface: Proxy<wl_surface::WlSurface>| match event { surface.implement(move |event, surface| match event {
wl_surface::Event::Enter { output } => { wl_surface::Event::Enter { output } => {
let dpi_change = list.lock().unwrap().add_output(MonitorId { let dpi_change = list.lock().unwrap().add_output(MonitorId {
proxy: output, proxy: output,
@ -64,16 +64,16 @@ impl Window {
} }
} }
} }
} }, ())
}); }).unwrap();
let window_store = evlp.store.clone(); let window_store = evlp.store.clone();
let my_surface = surface.clone(); let my_surface = surface.clone();
let mut frame = SWindow::<BasicFrame>::init_from_env( let mut frame = SWindow::<ConceptFrame>::init_from_env(
&evlp.env, &evlp.env,
surface.clone(), surface.clone(),
(width, height), (width, height),
move |event, ()| match event { move |event| match event {
WEvent::Configure { new_size, .. } => { WEvent::Configure { new_size, .. } => {
let mut store = window_store.lock().unwrap(); let mut store = window_store.lock().unwrap();
for window in &mut store.windows { for window in &mut store.windows {
@ -324,7 +324,7 @@ struct InternalWindow {
need_frame_refresh: Arc<Mutex<bool>>, need_frame_refresh: Arc<Mutex<bool>>,
closed: bool, closed: bool,
kill_switch: Arc<Mutex<bool>>, kill_switch: Arc<Mutex<bool>>,
frame: Weak<Mutex<SWindow<BasicFrame>>>, frame: Weak<Mutex<SWindow<ConceptFrame>>>,
current_dpi: i32, current_dpi: i32,
new_dpi: Option<i32> new_dpi: Option<i32>
} }
@ -382,7 +382,7 @@ impl WindowStore {
pub fn for_each<F>(&mut self, mut f: F) pub fn for_each<F>(&mut self, mut f: F)
where where
F: FnMut(Option<(u32, u32)>, &mut (u32, u32), Option<i32>, bool, bool, bool, WindowId, Option<&mut SWindow<BasicFrame>>), F: FnMut(Option<(u32, u32)>, &mut (u32, u32), Option<i32>, bool, bool, bool, WindowId, Option<&mut SWindow<ConceptFrame>>),
{ {
for window in &mut self.windows { for window in &mut self.windows {
let opt_arc = window.frame.upgrade(); let opt_arc = window.frame.upgrade();