feat: add Phase 1 interaction protocols
This commit is contained in:
1 parent
a941b80aa9
commit
37550f447d
8 files changed
+169
-6
No files matched your search
@@ -0,0 +1,59 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use smithay::{
|
||||
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
||||
utils::SERIAL_COUNTER,
|
||||
wayland::xdg_activation::{
|
||||
XdgActivationHandler, XdgActivationState, XdgActivationToken, XdgActivationTokenData,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::Ferese;
|
||||
|
||||
const TOKEN_MAX_AGE: Duration = Duration::from_secs(10);
|
||||
|
||||
impl XdgActivationHandler for Ferese {
|
||||
fn activation_state(&mut self) -> &mut XdgActivationState {
|
||||
&mut self.xdg_activation_state
|
||||
}
|
||||
|
||||
fn token_created(&mut self, _token: XdgActivationToken, data: XdgActivationTokenData) -> bool {
|
||||
data.serial.is_some() && data.timestamp.elapsed() <= TOKEN_MAX_AGE
|
||||
}
|
||||
|
||||
fn request_activation(
|
||||
&mut self,
|
||||
token: XdgActivationToken,
|
||||
data: XdgActivationTokenData,
|
||||
surface: WlSurface,
|
||||
) {
|
||||
let valid = data.serial.is_some() && data.timestamp.elapsed() <= TOKEN_MAX_AGE;
|
||||
self.xdg_activation_state.remove_token(&token);
|
||||
if !valid {
|
||||
tracing::debug!("ignored stale or non-interactive activation request");
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(window) = self
|
||||
.space
|
||||
.elements()
|
||||
.find(|window| {
|
||||
window
|
||||
.toplevel()
|
||||
.is_some_and(|toplevel| toplevel.wl_surface() == &surface)
|
||||
})
|
||||
.cloned()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
self.space.raise_element(&window, true);
|
||||
let keyboard = self.seat.get_keyboard().expect("seat has a keyboard");
|
||||
keyboard.set_focus(self, Some(surface), SERIAL_COUNTER.next_serial());
|
||||
self.space.elements().for_each(|window| {
|
||||
if let Some(toplevel) = window.toplevel() {
|
||||
toplevel.send_pending_configure();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,18 @@
|
||||
mod activation;
|
||||
mod compositor;
|
||||
mod xdg_shell;
|
||||
|
||||
use smithay::{
|
||||
input::{Seat, SeatHandler, SeatState, pointer::CursorImageStatus},
|
||||
input::{
|
||||
Seat, SeatHandler, SeatState,
|
||||
pointer::{CursorImageStatus, PointerHandle},
|
||||
},
|
||||
reexports::wayland_server::{Resource, protocol::wl_surface::WlSurface},
|
||||
wayland::{
|
||||
compositor::with_states,
|
||||
fractional_scale::{FractionalScaleHandler, with_fractional_scale},
|
||||
output::OutputHandler,
|
||||
pointer_constraints::{PointerConstraintsHandler, with_pointer_constraint},
|
||||
selection::{
|
||||
SelectionHandler,
|
||||
data_device::{
|
||||
@@ -41,6 +48,37 @@ impl SeatHandler for Ferese {
|
||||
|
||||
impl OutputHandler for Ferese {}
|
||||
|
||||
impl FractionalScaleHandler for Ferese {
|
||||
fn new_fractional_scale(&mut self, surface: WlSurface) {
|
||||
with_states(&surface, |states| {
|
||||
with_fractional_scale(states, |scale| scale.set_preferred_scale(1.0));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl PointerConstraintsHandler for Ferese {
|
||||
fn new_constraint(&mut self, surface: &WlSurface, pointer: &PointerHandle<Self>) {
|
||||
let focused = pointer
|
||||
.current_focus()
|
||||
.is_some_and(|focused| focused == *surface);
|
||||
if focused {
|
||||
with_pointer_constraint(surface, pointer, |constraint| {
|
||||
if let Some(constraint) = constraint {
|
||||
constraint.activate();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn cursor_position_hint(
|
||||
&mut self,
|
||||
_surface: &WlSurface,
|
||||
_pointer: &PointerHandle<Self>,
|
||||
_location: smithay::utils::Point<f64, smithay::utils::Logical>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectionHandler for Ferese {
|
||||
type SelectionUserData = ();
|
||||
}
|
||||
@@ -62,9 +100,15 @@ impl PrimarySelectionHandler for Ferese {
|
||||
|
||||
smithay::delegate_compositor!(Ferese);
|
||||
smithay::delegate_data_device!(Ferese);
|
||||
smithay::delegate_fractional_scale!(Ferese);
|
||||
smithay::delegate_output!(Ferese);
|
||||
smithay::delegate_pointer_constraints!(Ferese);
|
||||
smithay::delegate_presentation!(Ferese);
|
||||
smithay::delegate_primary_selection!(Ferese);
|
||||
smithay::delegate_relative_pointer!(Ferese);
|
||||
smithay::delegate_seat!(Ferese);
|
||||
smithay::delegate_shm!(Ferese);
|
||||
smithay::delegate_viewporter!(Ferese);
|
||||
smithay::delegate_xdg_activation!(Ferese);
|
||||
smithay::delegate_xdg_decoration!(Ferese);
|
||||
smithay::delegate_xdg_shell!(Ferese);
|
||||
+16
-2
@@ -1,11 +1,11 @@
|
||||
use smithay::{
|
||||
backend::input::{
|
||||
AbsolutePositionEvent, Axis, AxisSource, ButtonState, Event, InputBackend, InputEvent,
|
||||
KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent,
|
||||
KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionEvent,
|
||||
},
|
||||
input::{
|
||||
keyboard::FilterResult,
|
||||
pointer::{AxisFrame, ButtonEvent, MotionEvent},
|
||||
pointer::{AxisFrame, ButtonEvent, MotionEvent, RelativeMotionEvent},
|
||||
},
|
||||
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
||||
utils::{SERIAL_COUNTER, Serial},
|
||||
@@ -47,6 +47,20 @@ impl Ferese {
|
||||
);
|
||||
pointer.frame(self);
|
||||
}
|
||||
InputEvent::PointerMotion { event, .. } => {
|
||||
let pointer = self.seat.get_pointer().expect("seat has a pointer");
|
||||
let focus = self.surface_under(pointer.current_location());
|
||||
pointer.relative_motion(
|
||||
self,
|
||||
focus,
|
||||
&RelativeMotionEvent {
|
||||
delta: event.delta(),
|
||||
delta_unaccel: event.delta_unaccel(),
|
||||
utime: (event.time_msec() as u64).saturating_mul(1_000),
|
||||
},
|
||||
);
|
||||
pointer.frame(self);
|
||||
}
|
||||
InputEvent::PointerButton { event, .. } => {
|
||||
let pointer = self.seat.get_pointer().expect("seat has a pointer");
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
|
||||
@@ -14,12 +14,18 @@ use smithay::{
|
||||
utils::{Logical, Point},
|
||||
wayland::{
|
||||
compositor::{CompositorClientState, CompositorState},
|
||||
fractional_scale::FractionalScaleManagerState,
|
||||
output::OutputManagerState,
|
||||
pointer_constraints::PointerConstraintsState,
|
||||
presentation::PresentationState,
|
||||
relative_pointer::RelativePointerManagerState,
|
||||
selection::{data_device::DataDeviceState, primary_selection::PrimarySelectionState},
|
||||
shell::xdg::XdgShellState,
|
||||
shell::xdg::decoration::XdgDecorationState,
|
||||
shm::ShmState,
|
||||
socket::ListeningSocketSource,
|
||||
viewporter::ViewporterState,
|
||||
xdg_activation::XdgActivationState,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -34,10 +40,16 @@ pub struct Ferese {
|
||||
pub compositor_state: CompositorState,
|
||||
pub data_device_state: DataDeviceState,
|
||||
pub decoration_state: XdgDecorationState,
|
||||
pub fractional_scale_state: FractionalScaleManagerState,
|
||||
pub output_manager_state: OutputManagerState,
|
||||
pub pointer_constraints_state: PointerConstraintsState,
|
||||
pub presentation_state: PresentationState,
|
||||
pub primary_selection_state: PrimarySelectionState,
|
||||
pub relative_pointer_state: RelativePointerManagerState,
|
||||
pub seat_state: SeatState<Self>,
|
||||
pub shm_state: ShmState,
|
||||
pub viewporter_state: ViewporterState,
|
||||
pub xdg_activation_state: XdgActivationState,
|
||||
pub xdg_shell_state: XdgShellState,
|
||||
}
|
||||
|
||||
@@ -50,10 +62,17 @@ impl Ferese {
|
||||
let compositor_state = CompositorState::new::<Self>(&display_handle);
|
||||
let xdg_shell_state = XdgShellState::new::<Self>(&display_handle);
|
||||
let decoration_state = XdgDecorationState::new::<Self>(&display_handle);
|
||||
let fractional_scale_state = FractionalScaleManagerState::new::<Self>(&display_handle);
|
||||
let shm_state = ShmState::new::<Self>(&display_handle, Vec::new());
|
||||
let output_manager_state = OutputManagerState::new_with_xdg_output::<Self>(&display_handle);
|
||||
let pointer_constraints_state = PointerConstraintsState::new::<Self>(&display_handle);
|
||||
let presentation_state =
|
||||
PresentationState::new::<Self>(&display_handle, libc::CLOCK_MONOTONIC as u32);
|
||||
let data_device_state = DataDeviceState::new::<Self>(&display_handle);
|
||||
let primary_selection_state = PrimarySelectionState::new::<Self>(&display_handle);
|
||||
let relative_pointer_state = RelativePointerManagerState::new::<Self>(&display_handle);
|
||||
let viewporter_state = ViewporterState::new::<Self>(&display_handle);
|
||||
let xdg_activation_state = XdgActivationState::new::<Self>(&display_handle);
|
||||
let mut seat_state = SeatState::new();
|
||||
let mut seat = seat_state.new_wl_seat(&display_handle, "ferese-winit");
|
||||
seat.add_keyboard(Default::default(), 200, 25)?;
|
||||
@@ -71,10 +90,16 @@ impl Ferese {
|
||||
compositor_state,
|
||||
data_device_state,
|
||||
decoration_state,
|
||||
fractional_scale_state,
|
||||
output_manager_state,
|
||||
pointer_constraints_state,
|
||||
presentation_state,
|
||||
primary_selection_state,
|
||||
relative_pointer_state,
|
||||
seat_state,
|
||||
shm_state,
|
||||
viewporter_state,
|
||||
xdg_activation_state,
|
||||
xdg_shell_state,
|
||||
})
|
||||
}
|
||||
|
||||
+21
-1
@@ -8,9 +8,12 @@ use smithay::{
|
||||
},
|
||||
winit::{self, WinitEvent},
|
||||
},
|
||||
desktop::utils::OutputPresentationFeedback,
|
||||
output::{Mode, Output, PhysicalProperties, Subpixel},
|
||||
reexports::calloop::EventLoop,
|
||||
utils::{Rectangle, Transform},
|
||||
reexports::wayland_protocols::wp::presentation_time::server::wp_presentation_feedback::Kind,
|
||||
utils::{Clock, Monotonic, Rectangle, Transform},
|
||||
wayland::presentation::Refresh,
|
||||
};
|
||||
|
||||
use crate::Ferese;
|
||||
@@ -41,6 +44,8 @@ pub fn init(event_loop: &mut EventLoop<Ferese>, state: &mut Ferese) -> Result<()
|
||||
state.space.map_output(&output, (0, 0));
|
||||
|
||||
let mut damage_tracker = OutputDamageTracker::from_output(&output);
|
||||
let clock = Clock::<Monotonic>::new();
|
||||
let mut sequence = 0_u64;
|
||||
event_loop
|
||||
.handle()
|
||||
.insert_source(event_source, move |event, _, state| match event {
|
||||
@@ -56,6 +61,14 @@ pub fn init(event_loop: &mut EventLoop<Ferese>, state: &mut Ferese) -> Result<()
|
||||
WinitEvent::Input(event) => state.process_input_event(event),
|
||||
WinitEvent::Redraw => {
|
||||
let damage = Rectangle::from_size(backend.window_size());
|
||||
let mut presentation = OutputPresentationFeedback::new(&output);
|
||||
state.space.elements().for_each(|window| {
|
||||
window.take_presentation_feedback(
|
||||
&mut presentation,
|
||||
|_, _| Some(output.clone()),
|
||||
|_, _| Kind::Vsync,
|
||||
);
|
||||
});
|
||||
let rendered = (|| -> Result<(), Box<dyn Error>> {
|
||||
{
|
||||
let (renderer, mut framebuffer) = backend.bind()?;
|
||||
@@ -84,6 +97,13 @@ pub fn init(event_loop: &mut EventLoop<Ferese>, state: &mut Ferese) -> Result<()
|
||||
state.loop_signal.stop();
|
||||
return;
|
||||
}
|
||||
sequence = sequence.wrapping_add(1);
|
||||
presentation.presented(
|
||||
clock.now(),
|
||||
Refresh::fixed(Duration::from_nanos(1_000_000_000 / 60)),
|
||||
sequence,
|
||||
Kind::Vsync,
|
||||
);
|
||||
state.space.elements().for_each(|window| {
|
||||
window.send_frame(
|
||||
&output,
|
||||
|
||||
Reference in new issue
Block a user