Change default project
This commit is contained in:
parent
40fa293e2e
commit
1cfba7cb53
4 changed files with 239 additions and 21 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1150,7 +1150,9 @@ name = "test_wayland_server"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"smithay",
|
"smithay",
|
||||||
|
"wayland-protocols",
|
||||||
"wayland-server",
|
"wayland-server",
|
||||||
|
"winit",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -7,4 +7,6 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
smithay = { git = "https://github.com/Smithay/smithay.git", branch = "master" }
|
smithay = { git = "https://github.com/Smithay/smithay.git", branch = "master" }
|
||||||
wayland-server = "0.31.0"
|
wayland-server = "0.31.0"
|
||||||
|
wayland-protocols = { version = "0.31.0", features = ["unstable", "staging", "server"] }
|
||||||
|
winit = { version = "0.29", default-features = false, features = ["wayland", "wayland-dlopen", "x11", "rwh_06"] }
|
|
@ -4,6 +4,7 @@
|
||||||
- libgdm-devel
|
- libgdm-devel
|
||||||
- libinput-devel
|
- libinput-devel
|
||||||
- libxkbcommon-devel
|
- libxkbcommon-devel
|
||||||
|
- weston-terminal
|
||||||
|
|
||||||
# Usefull links
|
# Usefull links
|
||||||
|
|
||||||
|
|
253
src/main.rs
253
src/main.rs
|
@ -1,16 +1,90 @@
|
||||||
use std::sync::Arc;
|
use std::{os::unix::io::OwnedFd, sync::Arc};
|
||||||
|
|
||||||
use smithay::delegate_compositor;
|
use ::winit::platform::pump_events::PumpStatus;
|
||||||
use smithay::reexports::wayland_server::Display;
|
use smithay::{
|
||||||
|
backend::{
|
||||||
|
input::{InputEvent, KeyboardKeyEvent},
|
||||||
|
renderer::{
|
||||||
|
element::{
|
||||||
|
surface::{render_elements_from_surface_tree, WaylandSurfaceRenderElement},
|
||||||
|
Kind,
|
||||||
|
},
|
||||||
|
gles::GlesRenderer,
|
||||||
|
utils::{draw_render_elements, on_commit_buffer_handler},
|
||||||
|
Frame, Renderer,
|
||||||
|
},
|
||||||
|
winit::{self, WinitEvent},
|
||||||
|
},
|
||||||
|
delegate_compositor, delegate_data_device, delegate_seat, delegate_shm, delegate_xdg_shell,
|
||||||
|
input::{keyboard::FilterResult, Seat, SeatHandler, SeatState},
|
||||||
|
reexports::wayland_server::{protocol::wl_seat, Display},
|
||||||
|
utils::{Rectangle, Serial, Transform},
|
||||||
|
wayland::{
|
||||||
|
buffer::BufferHandler,
|
||||||
|
compositor::{
|
||||||
|
with_surface_tree_downward, CompositorClientState, CompositorHandler, CompositorState,
|
||||||
|
SurfaceAttributes, TraversalAction,
|
||||||
|
},
|
||||||
|
selection::{
|
||||||
|
data_device::{ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler},
|
||||||
|
SelectionHandler,
|
||||||
|
},
|
||||||
|
shell::xdg::{PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState},
|
||||||
|
shm::{ShmHandler, ShmState},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use wayland_protocols::xdg::shell::server::xdg_toplevel;
|
||||||
|
use wayland_server::{
|
||||||
|
backend::{ClientData, ClientId, DisconnectReason},
|
||||||
|
protocol::{
|
||||||
|
wl_buffer,
|
||||||
|
wl_surface::{self, WlSurface},
|
||||||
|
},
|
||||||
|
Client, ListeningSocket,
|
||||||
|
};
|
||||||
|
|
||||||
use smithay::wayland::compositor::{CompositorClientState, CompositorHandler, CompositorState};
|
impl BufferHandler for App {
|
||||||
|
fn buffer_destroyed(&mut self, _buffer: &wl_buffer::WlBuffer) {}
|
||||||
|
}
|
||||||
|
|
||||||
use wayland_server::backend::{ClientData, ClientId, DisconnectReason};
|
impl XdgShellHandler for App {
|
||||||
use wayland_server::protocol::wl_surface::WlSurface;
|
fn xdg_shell_state(&mut self) -> &mut XdgShellState {
|
||||||
use wayland_server::{Client, ListeningSocket};
|
&mut self.xdg_shell_state
|
||||||
|
}
|
||||||
|
|
||||||
struct App {
|
fn new_toplevel(&mut self, surface: ToplevelSurface) {
|
||||||
compositor_state: CompositorState,
|
surface.with_pending_state(|state| {
|
||||||
|
state.states.set(xdg_toplevel::State::Activated);
|
||||||
|
});
|
||||||
|
surface.send_configure();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_popup(&mut self, _surface: PopupSurface, _positioner: PositionerState) {
|
||||||
|
// Handle popup creation here
|
||||||
|
}
|
||||||
|
|
||||||
|
fn grab(&mut self, _surface: PopupSurface, _seat: wl_seat::WlSeat, _serial: Serial) {
|
||||||
|
// Handle popup grab here
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reposition_request(&mut self, _surface: PopupSurface, _positioner: PositionerState, _token: u32) {
|
||||||
|
// Handle popup reposition here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SelectionHandler for App {
|
||||||
|
type SelectionUserData = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DataDeviceHandler for App {
|
||||||
|
fn data_device_state(&self) -> &DataDeviceState {
|
||||||
|
&self.data_device_state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClientDndGrabHandler for App {}
|
||||||
|
impl ServerDndGrabHandler for App {
|
||||||
|
fn send(&mut self, _mime_type: String, _fd: OwnedFd, _seat: Seat<Self>) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompositorHandler for App {
|
impl CompositorHandler for App {
|
||||||
|
@ -23,24 +97,139 @@ impl CompositorHandler for App {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn commit(&mut self, surface: &WlSurface) {
|
fn commit(&mut self, surface: &WlSurface) {
|
||||||
dbg!("Commit", surface);
|
on_commit_buffer_handler::<Self>(surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ShmHandler for App {
|
||||||
|
fn shm_state(&self) -> &ShmState {
|
||||||
|
&self.shm_state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SeatHandler for App {
|
||||||
|
type KeyboardFocus = WlSurface;
|
||||||
|
type PointerFocus = WlSurface;
|
||||||
|
|
||||||
|
fn seat_state(&mut self) -> &mut SeatState<Self> {
|
||||||
|
&mut self.seat_state
|
||||||
|
}
|
||||||
|
|
||||||
|
fn focus_changed(&mut self, _seat: &Seat<Self>, _focused: Option<&WlSurface>) {}
|
||||||
|
fn cursor_image(&mut self, _seat: &Seat<Self>, _image: smithay::input::pointer::CursorImageStatus) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct App {
|
||||||
|
compositor_state: CompositorState,
|
||||||
|
xdg_shell_state: XdgShellState,
|
||||||
|
shm_state: ShmState,
|
||||||
|
seat_state: SeatState<Self>,
|
||||||
|
data_device_state: DataDeviceState,
|
||||||
|
|
||||||
|
seat: Seat<Self>,
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
run_winit()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_winit() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut display: Display<App> = Display::new()?;
|
let mut display: Display<App> = Display::new()?;
|
||||||
let dh = display.handle();
|
let dh = display.handle();
|
||||||
|
|
||||||
let compositor_state = CompositorState::new::<App>(&dh);
|
let compositor_state = CompositorState::new::<App>(&dh);
|
||||||
|
let shm_state = ShmState::new::<App>(&dh, vec![]);
|
||||||
|
let mut seat_state = SeatState::new();
|
||||||
|
let seat = seat_state.new_wl_seat(&dh, "winit");
|
||||||
|
|
||||||
let mut state = App { compositor_state };
|
let mut state = {
|
||||||
|
App {
|
||||||
|
compositor_state,
|
||||||
|
xdg_shell_state: XdgShellState::new::<App>(&dh),
|
||||||
|
shm_state,
|
||||||
|
seat_state,
|
||||||
|
data_device_state: DataDeviceState::new::<App>(&dh),
|
||||||
|
seat,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let listener = ListeningSocket::bind("wayland-5").unwrap();
|
let listener = ListeningSocket::bind("wayland-5").unwrap();
|
||||||
|
|
||||||
let mut clients = Vec::new();
|
let mut clients = Vec::new();
|
||||||
|
|
||||||
|
let (mut backend, mut winit) = winit::init::<GlesRenderer>()?;
|
||||||
|
|
||||||
|
let start_time = std::time::Instant::now();
|
||||||
|
|
||||||
|
let keyboard = state.seat.add_keyboard(Default::default(), 200, 200).unwrap();
|
||||||
|
|
||||||
|
std::env::set_var("WAYLAND_DISPLAY", "wayland-5");
|
||||||
|
std::process::Command::new("weston-terminal").spawn().ok();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if let Some(stream) = listener.accept().unwrap() {
|
let status = winit.dispatch_new_events(|event| match event {
|
||||||
|
WinitEvent::Resized { .. } => {}
|
||||||
|
WinitEvent::Input(event) => match event {
|
||||||
|
InputEvent::Keyboard { event } => {
|
||||||
|
keyboard.input::<(), _>(
|
||||||
|
&mut state,
|
||||||
|
event.key_code(),
|
||||||
|
event.state(),
|
||||||
|
0.into(),
|
||||||
|
0,
|
||||||
|
|_, _, _| {
|
||||||
|
//
|
||||||
|
FilterResult::Forward
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
InputEvent::PointerMotionAbsolute { .. } => {
|
||||||
|
if let Some(surface) = state.xdg_shell_state.toplevel_surfaces().iter().next().cloned() {
|
||||||
|
let surface = surface.wl_surface().clone();
|
||||||
|
keyboard.set_focus(&mut state, Some(surface), 0.into());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
});
|
||||||
|
|
||||||
|
match status {
|
||||||
|
PumpStatus::Continue => (),
|
||||||
|
PumpStatus::Exit(_) => return Ok(()),
|
||||||
|
};
|
||||||
|
|
||||||
|
backend.bind().unwrap();
|
||||||
|
|
||||||
|
let size = backend.window_size();
|
||||||
|
let damage = Rectangle::from_loc_and_size((0, 0), size);
|
||||||
|
|
||||||
|
let elements = state
|
||||||
|
.xdg_shell_state
|
||||||
|
.toplevel_surfaces()
|
||||||
|
.iter()
|
||||||
|
.flat_map(|surface| {
|
||||||
|
render_elements_from_surface_tree(
|
||||||
|
backend.renderer(),
|
||||||
|
surface.wl_surface(),
|
||||||
|
(0, 0),
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
Kind::Unspecified,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<WaylandSurfaceRenderElement<GlesRenderer>>>();
|
||||||
|
|
||||||
|
let mut frame = backend.renderer().render(size, Transform::Flipped180).unwrap();
|
||||||
|
frame.clear([0.1, 0.0, 0.0, 1.0], &[damage]).unwrap();
|
||||||
|
draw_render_elements(&mut frame, 1.0, &elements, &[damage]).unwrap();
|
||||||
|
// We rely on the nested compositor to do the sync for us
|
||||||
|
let _ = frame.finish().unwrap();
|
||||||
|
|
||||||
|
for surface in state.xdg_shell_state.toplevel_surfaces() {
|
||||||
|
send_frames_surface_tree(surface.wl_surface(), start_time.elapsed().as_millis() as u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(stream) = listener.accept()? {
|
||||||
println!("Got a client: {:?}", stream);
|
println!("Got a client: {:?}", stream);
|
||||||
|
|
||||||
let client = display
|
let client = display
|
||||||
|
@ -52,9 +241,34 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
display.dispatch_clients(&mut state)?;
|
display.dispatch_clients(&mut state)?;
|
||||||
display.flush_clients()?;
|
display.flush_clients()?;
|
||||||
|
|
||||||
|
// It is important that all events on the display have been dispatched and flushed to clients before
|
||||||
|
// swapping buffers because this operation may block.
|
||||||
|
backend.submit(Some(&[damage])).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn send_frames_surface_tree(surface: &wl_surface::WlSurface, time: u32) {
|
||||||
|
with_surface_tree_downward(
|
||||||
|
surface,
|
||||||
|
(),
|
||||||
|
|_, _, &()| TraversalAction::DoChildren(()),
|
||||||
|
|_surf, states, &()| {
|
||||||
|
// the surface may not have any user_data if it is a subsurface and has not
|
||||||
|
// yet been commited
|
||||||
|
for callback in states
|
||||||
|
.cached_state
|
||||||
|
.current::<SurfaceAttributes>()
|
||||||
|
.frame_callbacks
|
||||||
|
.drain(..)
|
||||||
|
{
|
||||||
|
callback.done(time);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|_, _, &()| true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct ClientState {
|
struct ClientState {
|
||||||
compositor_state: CompositorClientState,
|
compositor_state: CompositorClientState,
|
||||||
|
@ -69,10 +283,9 @@ impl ClientData for ClientState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsMut<CompositorState> for App {
|
// Macros used to delegate protocol handling to types in the app state.
|
||||||
fn as_mut(&mut self) -> &mut CompositorState {
|
delegate_xdg_shell!(App);
|
||||||
&mut self.compositor_state
|
delegate_compositor!(App);
|
||||||
}
|
delegate_shm!(App);
|
||||||
}
|
delegate_seat!(App);
|
||||||
|
delegate_data_device!(App);
|
||||||
delegate_compositor!(App);
|
|
Loading…
Reference in a new issue