mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2025-01-30 20:34:49 +01:00
Winit pointer drawing, start on udev backend
This commit is contained in:
parent
e3b65456d6
commit
8f5c55d3a0
7 changed files with 229 additions and 52 deletions
|
@ -9,3 +9,6 @@ edition = "2021"
|
|||
tracing = "0.1.37"
|
||||
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
||||
smithay = { git = "https://github.com/Smithay/smithay" }
|
||||
smithay-drm-extras = { git = "https://github.com/Smithay/smithay", optional = true }
|
||||
thiserror = "1.0.40"
|
||||
xcursor = { version = "0.3.4", optional = true }
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use smithay::{output::Output, reexports::wayland_server::protocol::wl_surface::WlSurface};
|
||||
|
||||
pub mod udev;
|
||||
pub mod winit;
|
||||
|
||||
/// A trait defining common methods for each available backend: winit and tty-udev
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
use std::{error::Error, os::fd::AsRawFd, sync::Arc, time::Duration};
|
||||
use std::{
|
||||
error::Error,
|
||||
os::fd::AsRawFd,
|
||||
sync::{Arc, Mutex},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use smithay::{
|
||||
backend::{
|
||||
|
@ -6,8 +11,11 @@ use smithay::{
|
|||
egl::EGLDevice,
|
||||
renderer::{
|
||||
damage::{self, OutputDamageTracker},
|
||||
element::default_primary_scanout_output_compare,
|
||||
gles::GlesRenderer,
|
||||
element::{
|
||||
default_primary_scanout_output_compare, surface::WaylandSurfaceRenderElement,
|
||||
AsRenderElements,
|
||||
},
|
||||
gles::{GlesRenderer, GlesTexture},
|
||||
ImportDma, ImportMemWl,
|
||||
},
|
||||
winit::{WinitError, WinitEvent, WinitGraphicsBackend},
|
||||
|
@ -16,9 +24,12 @@ use smithay::{
|
|||
desktop::{
|
||||
space,
|
||||
utils::{surface_primary_scanout_output, update_surface_primary_scanout_output},
|
||||
Space, Window,
|
||||
PopupManager, Space, Window,
|
||||
},
|
||||
input::{
|
||||
pointer::{CursorImageAttributes, CursorImageStatus},
|
||||
SeatState,
|
||||
},
|
||||
input::{pointer::CursorImageStatus, SeatState},
|
||||
output::{Output, Subpixel},
|
||||
reexports::{
|
||||
calloop::{
|
||||
|
@ -28,9 +39,9 @@ use smithay::{
|
|||
},
|
||||
wayland_server::{protocol::wl_surface::WlSurface, Display},
|
||||
},
|
||||
utils::{Clock, Monotonic, Physical, Point, Scale, Transform},
|
||||
utils::{Clock, IsAlive, Monotonic, Physical, Point, Scale, Transform},
|
||||
wayland::{
|
||||
compositor::CompositorState,
|
||||
compositor::{self, CompositorState},
|
||||
data_device::DataDeviceState,
|
||||
dmabuf::{
|
||||
DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal, DmabufHandler, DmabufState,
|
||||
|
@ -45,7 +56,11 @@ use smithay::{
|
|||
},
|
||||
};
|
||||
|
||||
use crate::state::{CalloopData, ClientState, State};
|
||||
use crate::{
|
||||
layout::{Direction, Layout},
|
||||
render::{pointer::PointerElement, CustomRenderElements, OutputRenderElements},
|
||||
state::{CalloopData, ClientState, State},
|
||||
};
|
||||
|
||||
use super::Backend;
|
||||
|
||||
|
@ -214,10 +229,10 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
|
|||
compositor_state: CompositorState::new::<State<WinitData>>(&display_handle),
|
||||
data_device_state: DataDeviceState::new::<State<WinitData>>(&display_handle),
|
||||
seat_state,
|
||||
shm_state: ShmState::new::<State<WinitData>>(&display_handle, Vec::new()),
|
||||
pointer_location: (0.0, 0.0).into(),
|
||||
shm_state: ShmState::new::<State<WinitData>>(&display_handle, vec![]),
|
||||
space: Space::<Window>::default(),
|
||||
cursor_status: CursorImageStatus::Default,
|
||||
pointer_location: (0.0, 0.0).into(),
|
||||
output_manager_state: OutputManagerState::new_with_xdg_output::<State<WinitData>>(
|
||||
&display_handle,
|
||||
),
|
||||
|
@ -229,6 +244,8 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
|
|||
|
||||
move_mode: false,
|
||||
socket_name: socket_name.clone(),
|
||||
|
||||
popup_manager: PopupManager::default(),
|
||||
};
|
||||
|
||||
state
|
||||
|
@ -239,6 +256,8 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
|
|||
|
||||
std::env::set_var("WAYLAND_DISPLAY", socket_name);
|
||||
|
||||
let mut pointer_element = PointerElement::<GlesTexture>::new();
|
||||
|
||||
// TODO: pointer
|
||||
evt_loop_handle.insert_source(Timer::immediate(), move |_instant, _metadata, data| {
|
||||
let display = &mut data.display;
|
||||
|
@ -258,6 +277,11 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
|
|||
None,
|
||||
None,
|
||||
);
|
||||
Layout::master_stack(
|
||||
state,
|
||||
state.space.elements().cloned().collect(),
|
||||
Direction::Left,
|
||||
);
|
||||
}
|
||||
WinitEvent::Focus(_) => {}
|
||||
WinitEvent::Input(input_evt) => {
|
||||
|
@ -273,9 +297,50 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
|
|||
}
|
||||
};
|
||||
|
||||
if let CursorImageStatus::Surface(ref surface) = state.cursor_status {
|
||||
if !surface.alive() {
|
||||
state.cursor_status = CursorImageStatus::Default;
|
||||
}
|
||||
}
|
||||
|
||||
let cursor_visible = !matches!(state.cursor_status, CursorImageStatus::Surface(_));
|
||||
|
||||
pointer_element.set_status(state.cursor_status.clone());
|
||||
|
||||
let full_redraw = &mut state.backend_data.full_redraw;
|
||||
*full_redraw = full_redraw.saturating_sub(1);
|
||||
|
||||
let scale = Scale::from(output.current_scale().fractional_scale());
|
||||
let cursor_hotspot = if let CursorImageStatus::Surface(ref surface) = state.cursor_status {
|
||||
compositor::with_states(surface, |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<Mutex<CursorImageAttributes>>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.hotspot
|
||||
})
|
||||
} else {
|
||||
(0, 0).into()
|
||||
};
|
||||
let cursor_pos = state.pointer_location - cursor_hotspot.to_f64();
|
||||
let cursor_pos_scaled = cursor_pos.to_physical(scale).to_i32_round::<i32>();
|
||||
|
||||
let mut custom_render_elements = Vec::<CustomRenderElements<GlesRenderer>>::new();
|
||||
|
||||
custom_render_elements.extend(pointer_element.render_elements(
|
||||
state.backend_data.backend.renderer(),
|
||||
cursor_pos_scaled,
|
||||
scale,
|
||||
1.0,
|
||||
));
|
||||
|
||||
tracing::info!(
|
||||
"custom_render_elements len = {}",
|
||||
custom_render_elements.len()
|
||||
);
|
||||
|
||||
let render_res = state.backend_data.backend.bind().and_then(|_| {
|
||||
let age = if *full_redraw > 0 {
|
||||
0
|
||||
|
@ -286,9 +351,24 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
|
|||
let renderer = state.backend_data.backend.renderer();
|
||||
|
||||
// render_output()
|
||||
let output_render_elements =
|
||||
let space_render_elements =
|
||||
space::space_render_elements(renderer, [&state.space], &output, 1.0).unwrap();
|
||||
|
||||
let mut output_render_elements = Vec::<
|
||||
OutputRenderElements<GlesRenderer, WaylandSurfaceRenderElement<GlesRenderer>>,
|
||||
>::new();
|
||||
|
||||
output_render_elements.extend(
|
||||
custom_render_elements
|
||||
.into_iter()
|
||||
.map(OutputRenderElements::from),
|
||||
);
|
||||
output_render_elements.extend(
|
||||
space_render_elements
|
||||
.into_iter()
|
||||
.map(OutputRenderElements::from),
|
||||
);
|
||||
|
||||
state
|
||||
.backend_data
|
||||
.damage_tracker
|
||||
|
@ -307,6 +387,13 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
|
|||
tracing::warn!("{}", err);
|
||||
}
|
||||
}
|
||||
|
||||
state
|
||||
.backend_data
|
||||
.backend
|
||||
.window()
|
||||
.set_cursor_visible(cursor_visible);
|
||||
|
||||
let throttle = Some(Duration::from_secs(1));
|
||||
|
||||
state.space.elements().for_each(|window| {
|
||||
|
@ -347,13 +434,11 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
|
|||
}
|
||||
}
|
||||
|
||||
let scale = Scale::from(output.current_scale().fractional_scale());
|
||||
let cursor_pos = state.pointer_location;
|
||||
let _cursor_pos_scaled: Point<i32, Physical> = cursor_pos.to_physical(scale).to_i32_round();
|
||||
|
||||
state.space.refresh();
|
||||
|
||||
display.flush_clients().unwrap();
|
||||
state.popup_manager.cleanup();
|
||||
display
|
||||
.flush_clients()
|
||||
.expect("failed to flush client buffers");
|
||||
|
||||
TimeoutAction::ToDuration(Duration::from_millis(6))
|
||||
})?;
|
||||
|
|
120
src/handlers.rs
120
src/handlers.rs
|
@ -2,8 +2,14 @@ use smithay::{
|
|||
backend::renderer::utils,
|
||||
delegate_compositor, delegate_data_device, delegate_fractional_scale, delegate_output,
|
||||
delegate_seat, delegate_shm, delegate_viewporter, delegate_xdg_shell,
|
||||
desktop::Window,
|
||||
input::{pointer::CursorImageStatus, Seat, SeatHandler, SeatState},
|
||||
desktop::{
|
||||
find_popup_root_surface, PopupKeyboardGrab, PopupKind, PopupManager, PopupPointerGrab,
|
||||
PopupUngrabStrategy, Space, Window,
|
||||
},
|
||||
input::{
|
||||
pointer::{CursorImageStatus, Focus},
|
||||
Seat, SeatHandler, SeatState,
|
||||
},
|
||||
reexports::{
|
||||
calloop::Interest,
|
||||
wayland_protocols::xdg::shell::server::xdg_toplevel::ResizeEdge,
|
||||
|
@ -25,8 +31,8 @@ use smithay::{
|
|||
dmabuf,
|
||||
fractional_scale::{self, FractionalScaleHandler},
|
||||
shell::xdg::{
|
||||
Configure, PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler,
|
||||
XdgShellState, XdgToplevelSurfaceData,
|
||||
Configure, PopupSurface, PositionerState, ToplevelSurface, XdgPopupSurfaceData,
|
||||
XdgShellHandler, XdgShellState, XdgToplevelSurfaceData,
|
||||
},
|
||||
shm::{ShmHandler, ShmState},
|
||||
},
|
||||
|
@ -93,7 +99,20 @@ impl<B: Backend> CompositorHandler for State<B> {
|
|||
}
|
||||
};
|
||||
|
||||
if let Some(window) = self.window_for_surface(surface) {
|
||||
self.popup_manager.commit(surface);
|
||||
|
||||
ensure_initial_configure(surface, self);
|
||||
|
||||
crate::grab::resize_grab::handle_commit(self, surface);
|
||||
}
|
||||
|
||||
fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState {
|
||||
&client.get_data::<ClientState>().unwrap().compositor_state
|
||||
}
|
||||
}
|
||||
delegate_compositor!(@<B: Backend> State<B>);
|
||||
fn ensure_initial_configure<B: Backend>(surface: &WlSurface, state: &mut State<B>) {
|
||||
if let Some(window) = state.window_for_surface(surface) {
|
||||
let initial_configure_sent = compositor::with_states(surface, |states| {
|
||||
states
|
||||
.data_map
|
||||
|
@ -106,23 +125,30 @@ impl<B: Backend> CompositorHandler for State<B> {
|
|||
// println!("initial_configure_sent is {}", initial_configure_sent);
|
||||
|
||||
if !initial_configure_sent {
|
||||
println!("initial configure");
|
||||
window.toplevel().send_configure();
|
||||
// println!(
|
||||
// "ensured_configured: {}",
|
||||
// window.toplevel().ensure_configured()
|
||||
// );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
crate::grab::resize_grab::handle_commit(self, surface);
|
||||
}
|
||||
|
||||
fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState {
|
||||
&client.get_data::<ClientState>().unwrap().compositor_state
|
||||
if let Some(popup) = state.popup_manager.find_popup(surface) {
|
||||
let PopupKind::Xdg(ref popup) = popup;
|
||||
let initial_configure_sent = compositor::with_states(surface, |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<XdgPopupSurfaceData>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.initial_configure_sent
|
||||
});
|
||||
if !initial_configure_sent {
|
||||
popup
|
||||
.send_configure()
|
||||
.expect("popup initial configure failed");
|
||||
}
|
||||
}
|
||||
delegate_compositor!(@<B: Backend> State<B>);
|
||||
// TODO: layer map thingys
|
||||
}
|
||||
|
||||
impl<B: Backend> ClientDndGrabHandler for State<B> {}
|
||||
impl<B: Backend> ServerDndGrabHandler for State<B> {}
|
||||
|
@ -136,7 +162,7 @@ impl<B: Backend> DataDeviceHandler for State<B> {
|
|||
}
|
||||
delegate_data_device!(@<B: Backend> State<B>);
|
||||
|
||||
impl<B: Backend + 'static> SeatHandler for State<B> {
|
||||
impl<B: Backend> SeatHandler for State<B> {
|
||||
type KeyboardFocus = WlSurface;
|
||||
type PointerFocus = WlSurface;
|
||||
|
||||
|
@ -145,6 +171,7 @@ impl<B: Backend + 'static> SeatHandler for State<B> {
|
|||
}
|
||||
|
||||
fn cursor_image(&mut self, _seat: &Seat<Self>, image: CursorImageStatus) {
|
||||
tracing::info!("new cursor image: {:?}", image);
|
||||
self.cursor_status = image;
|
||||
}
|
||||
|
||||
|
@ -177,7 +204,11 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
|||
Layout::master_stack(self, windows, crate::layout::Direction::Left);
|
||||
}
|
||||
|
||||
fn new_popup(&mut self, surface: PopupSurface, positioner: PositionerState) {}
|
||||
fn new_popup(&mut self, surface: PopupSurface, positioner: PositionerState) {
|
||||
if let Err(err) = self.popup_manager.track_popup(PopupKind::from(surface)) {
|
||||
tracing::warn!("failed to track popup: {}", err);
|
||||
}
|
||||
}
|
||||
|
||||
fn move_request(&mut self, surface: ToplevelSurface, seat: WlSeat, serial: Serial) {
|
||||
crate::xdg::request::move_request(
|
||||
|
@ -206,7 +237,58 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
|||
);
|
||||
}
|
||||
|
||||
fn grab(&mut self, surface: PopupSurface, seat: WlSeat, serial: Serial) {}
|
||||
fn reposition_request(
|
||||
&mut self,
|
||||
surface: PopupSurface,
|
||||
positioner: PositionerState,
|
||||
token: u32,
|
||||
) {
|
||||
surface.with_pending_state(|state| {
|
||||
state.geometry = positioner.get_geometry();
|
||||
state.positioner = positioner;
|
||||
});
|
||||
surface.send_repositioned(token);
|
||||
}
|
||||
|
||||
fn grab(&mut self, surface: PopupSurface, seat: WlSeat, serial: Serial) {
|
||||
let seat: Seat<State<B>> = Seat::from_resource(&seat).unwrap();
|
||||
let popup_kind = PopupKind::Xdg(surface);
|
||||
if let Some(root) = find_popup_root_surface(&popup_kind)
|
||||
.ok()
|
||||
.and_then(|root| self.window_for_surface(&root))
|
||||
{
|
||||
if let Ok(mut grab) = self.popup_manager.grab_popup(
|
||||
root.toplevel().wl_surface().clone(),
|
||||
popup_kind,
|
||||
&seat,
|
||||
serial,
|
||||
) {
|
||||
if let Some(keyboard) = seat.get_keyboard() {
|
||||
if keyboard.is_grabbed()
|
||||
&& !(keyboard.has_grab(serial)
|
||||
|| keyboard.has_grab(grab.previous_serial().unwrap_or(serial)))
|
||||
{
|
||||
grab.ungrab(PopupUngrabStrategy::All);
|
||||
return;
|
||||
}
|
||||
|
||||
keyboard.set_focus(self, grab.current_grab(), serial);
|
||||
keyboard.set_grab(PopupKeyboardGrab::new(&grab), serial);
|
||||
}
|
||||
if let Some(pointer) = seat.get_pointer() {
|
||||
if pointer.is_grabbed()
|
||||
&& !(pointer.has_grab(serial)
|
||||
|| pointer
|
||||
.has_grab(grab.previous_serial().unwrap_or_else(|| grab.serial())))
|
||||
{
|
||||
grab.ungrab(PopupUngrabStrategy::All);
|
||||
return;
|
||||
}
|
||||
pointer.set_grab(self, PopupPointerGrab::new(&grab), serial, Focus::Keep);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ack_configure(&mut self, surface: WlSurface, configure: Configure) {
|
||||
// println!("surface ack_configure: {:?}", configure);
|
||||
|
|
|
@ -86,6 +86,8 @@ impl State<WinitData> {
|
|||
let serial = SERIAL_COUNTER.next_serial();
|
||||
let pointer = seat.get_pointer().unwrap();
|
||||
|
||||
self.pointer_location = pointer_loc;
|
||||
|
||||
let surface_under_pointer =
|
||||
self.space
|
||||
.element_under(pointer_loc)
|
||||
|
@ -268,7 +270,6 @@ impl State<WinitData> {
|
|||
frame = frame.stop(Axis::Vertical);
|
||||
}
|
||||
|
||||
println!("axisframe: {:?}", frame);
|
||||
pointer.axis(self, frame);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ mod handlers;
|
|||
mod input;
|
||||
mod layout;
|
||||
mod pointer;
|
||||
mod shell;
|
||||
mod render;
|
||||
mod state;
|
||||
mod tag;
|
||||
mod window;
|
||||
|
|
17
src/state.rs
17
src/state.rs
|
@ -1,7 +1,7 @@
|
|||
use std::ffi::OsString;
|
||||
|
||||
use smithay::{
|
||||
desktop::{Space, Window},
|
||||
desktop::{PopupManager, Space, Window},
|
||||
input::{pointer::CursorImageStatus, SeatState},
|
||||
reexports::{
|
||||
calloop::{LoopHandle, LoopSignal},
|
||||
|
@ -28,23 +28,28 @@ use crate::backend::{winit::WinitData, Backend};
|
|||
|
||||
pub struct State<B: Backend> {
|
||||
pub backend_data: B,
|
||||
|
||||
pub loop_signal: LoopSignal,
|
||||
pub loop_handle: LoopHandle<'static, CalloopData>,
|
||||
pub clock: Clock<Monotonic>,
|
||||
|
||||
pub space: Space<Window>,
|
||||
pub move_mode: bool,
|
||||
pub socket_name: OsString,
|
||||
|
||||
pub compositor_state: CompositorState,
|
||||
pub data_device_state: DataDeviceState,
|
||||
pub seat_state: SeatState<Self>,
|
||||
pub shm_state: ShmState,
|
||||
pub space: Space<Window>,
|
||||
pub cursor_status: CursorImageStatus,
|
||||
pub pointer_location: Point<f64, Logical>,
|
||||
pub output_manager_state: OutputManagerState,
|
||||
pub xdg_shell_state: XdgShellState,
|
||||
pub viewporter_state: ViewporterState,
|
||||
pub fractional_scale_manager_state: FractionalScaleManagerState,
|
||||
|
||||
pub move_mode: bool,
|
||||
pub socket_name: OsString,
|
||||
pub popup_manager: PopupManager,
|
||||
|
||||
pub cursor_status: CursorImageStatus,
|
||||
pub pointer_location: Point<f64, Logical>,
|
||||
}
|
||||
|
||||
impl<B: Backend> State<B> {
|
||||
|
|
Loading…
Add table
Reference in a new issue