wayland server fixes
This commit is contained in:
@@ -3,33 +3,43 @@ use smithay::backend::allocator::dmabuf::Dmabuf;
|
||||
use smithay::backend::renderer::{BufferType, buffer_type};
|
||||
use smithay::desktop::{PopupKind, PopupManager};
|
||||
use smithay::input::{Seat, SeatHandler, SeatState};
|
||||
use smithay::reexports::rustix::fs::{OFlags, fcntl_setfl};
|
||||
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
|
||||
use smithay::reexports::wayland_server;
|
||||
use smithay::reexports::wayland_server::Resource;
|
||||
use smithay::reexports::wayland_server::protocol::{wl_buffer, wl_output, wl_seat};
|
||||
use smithay::reexports::wayland_server::{self, DisplayHandle};
|
||||
use smithay::wayland::buffer::BufferHandler;
|
||||
use smithay::wayland::dmabuf::{
|
||||
DmabufFeedback, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier, get_dmabuf,
|
||||
};
|
||||
use smithay::wayland::fractional_scale::with_fractional_scale;
|
||||
use smithay::wayland::output::OutputHandler;
|
||||
use smithay::wayland::selection::{
|
||||
ext_data_control as selection_ext,
|
||||
primary_selection::{PrimarySelectionHandler, PrimarySelectionState, set_primary_focus},
|
||||
wlr_data_control as selection_wlr,
|
||||
};
|
||||
use smithay::wayland::shm::{ShmHandler, ShmState, with_buffer_contents};
|
||||
use smithay::wayland::single_pixel_buffer::get_single_pixel_buffer;
|
||||
use smithay::{
|
||||
delegate_compositor, delegate_data_device, delegate_dmabuf, delegate_output, delegate_seat,
|
||||
delegate_shm, delegate_xdg_shell,
|
||||
delegate_compositor, delegate_data_control, delegate_data_device, delegate_dmabuf,
|
||||
delegate_ext_data_control, delegate_output, delegate_primary_selection, delegate_seat,
|
||||
delegate_shm, delegate_single_pixel_buffer, delegate_xdg_shell,
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::os::fd::OwnedFd;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use smithay::utils::Serial;
|
||||
use smithay::wayland::compositor::{self, BufferAssignment, SurfaceAttributes, send_surface_state};
|
||||
|
||||
use smithay::wayland::selection::SelectionHandler;
|
||||
use smithay::wayland::selection::data_device::{
|
||||
ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler,
|
||||
set_data_device_focus,
|
||||
};
|
||||
use smithay::wayland::selection::{self, SelectionHandler};
|
||||
use smithay::wayland::shell::xdg::{
|
||||
PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState,
|
||||
};
|
||||
@@ -51,9 +61,13 @@ pub struct Application {
|
||||
pub seat_state: SeatState<Application>,
|
||||
pub shm: ShmState,
|
||||
pub data_device: DataDeviceState,
|
||||
pub primary_selection_state: PrimarySelectionState,
|
||||
pub ext_data_control_state: selection_ext::DataControlState,
|
||||
pub wlr_data_control_state: selection_wlr::DataControlState,
|
||||
pub wayvr_tasks: SyncEventQueue<WayVRTask>,
|
||||
pub redraw_requests: HashSet<wayland_server::backend::ObjectId>,
|
||||
pub popup_manager: PopupManager,
|
||||
pub display_handle: DisplayHandle,
|
||||
}
|
||||
|
||||
impl Application {
|
||||
@@ -205,7 +219,13 @@ impl SeatHandler for Application {
|
||||
&mut self.seat_state
|
||||
}
|
||||
|
||||
fn focus_changed(&mut self, _seat: &Seat<Self>, _focused: Option<&WlSurface>) {}
|
||||
fn focus_changed(&mut self, seat: &Seat<Self>, focused: Option<&WlSurface>) {
|
||||
let dh = &self.display_handle;
|
||||
let client = focused.and_then(|s| dh.get_client(s.id()).ok());
|
||||
set_data_device_focus(dh, seat, client.clone());
|
||||
set_primary_focus(dh, seat, client);
|
||||
}
|
||||
|
||||
fn cursor_image(
|
||||
&mut self,
|
||||
_seat: &Seat<Self>,
|
||||
@@ -231,7 +251,35 @@ impl DataDeviceHandler for Application {
|
||||
}
|
||||
|
||||
impl SelectionHandler for Application {
|
||||
type SelectionUserData = ();
|
||||
type SelectionUserData = Arc<[u8]>;
|
||||
|
||||
fn send_selection(
|
||||
&mut self,
|
||||
_ty: selection::SelectionTarget,
|
||||
_mime_type: String,
|
||||
fd: OwnedFd,
|
||||
_seat: Seat<Self>,
|
||||
user_data: &Self::SelectionUserData,
|
||||
) {
|
||||
let buf = user_data.clone();
|
||||
std::thread::spawn(move || {
|
||||
// Clear O_NONBLOCK, otherwise File::write_all() will stop halfway.
|
||||
if let Err(err) = fcntl_setfl(&fd, OFlags::empty()) {
|
||||
log::warn!("error clearing flags on selection target fd: {err:?}");
|
||||
}
|
||||
if let Err(err) = File::from(fd).write_all(&buf) {
|
||||
log::warn!("error writing selection: {err:?}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn new_selection(
|
||||
&mut self,
|
||||
_ty: selection::SelectionTarget,
|
||||
_source: Option<selection::SelectionSource>,
|
||||
_seat: Seat<Self>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -371,6 +419,24 @@ impl DmabufHandler for Application {
|
||||
}
|
||||
}
|
||||
|
||||
impl PrimarySelectionHandler for Application {
|
||||
fn primary_selection_state(&self) -> &PrimarySelectionState {
|
||||
&self.primary_selection_state
|
||||
}
|
||||
}
|
||||
|
||||
impl selection_wlr::DataControlHandler for Application {
|
||||
fn data_control_state(&self) -> &selection_wlr::DataControlState {
|
||||
&self.wlr_data_control_state
|
||||
}
|
||||
}
|
||||
|
||||
impl selection_ext::DataControlHandler for Application {
|
||||
fn data_control_state(&self) -> &selection_ext::DataControlState {
|
||||
&self.ext_data_control_state
|
||||
}
|
||||
}
|
||||
|
||||
delegate_dmabuf!(Application);
|
||||
delegate_xdg_shell!(Application);
|
||||
delegate_compositor!(Application);
|
||||
@@ -378,6 +444,10 @@ delegate_shm!(Application);
|
||||
delegate_seat!(Application);
|
||||
delegate_data_device!(Application);
|
||||
delegate_output!(Application);
|
||||
delegate_primary_selection!(Application);
|
||||
delegate_data_control!(Application);
|
||||
delegate_ext_data_control!(Application);
|
||||
delegate_single_pixel_buffer!(Application);
|
||||
|
||||
const fn wl_transform_to_frame_transform(
|
||||
transform: wl_output::Transform,
|
||||
|
||||
@@ -15,11 +15,15 @@ use smithay::{
|
||||
input::{SeatState, keyboard::XkbConfig},
|
||||
output::{Mode, Output},
|
||||
reexports::wayland_server::{self, backend::ClientId},
|
||||
utils::{Logical, Size},
|
||||
wayland::{
|
||||
compositor::{self, SurfaceData, with_states},
|
||||
dmabuf::{DmabufFeedbackBuilder, DmabufState},
|
||||
selection::data_device::DataDeviceState,
|
||||
shell::xdg::{ToplevelSurface, XdgShellState, XdgToplevelSurfaceData},
|
||||
selection::{
|
||||
data_device::DataDeviceState, ext_data_control as selection_ext,
|
||||
primary_selection::PrimarySelectionState, wlr_data_control as selection_wlr,
|
||||
},
|
||||
shell::xdg::{SurfaceCachedState, ToplevelSurface, XdgShellState, XdgToplevelSurfaceData},
|
||||
shm::ShmState,
|
||||
},
|
||||
};
|
||||
@@ -148,8 +152,23 @@ impl WvrServerState {
|
||||
let mut seat_state = SeatState::new();
|
||||
let shm = ShmState::new::<Application>(&dh, Vec::new());
|
||||
let data_device = DataDeviceState::new::<Application>(&dh);
|
||||
let primary_selection_state = PrimarySelectionState::new::<Application>(&dh);
|
||||
let mut seat = seat_state.new_wl_seat(&dh, "wayvr");
|
||||
|
||||
fn filter_allow_any(_: &wayland_server::Client) -> bool {
|
||||
true
|
||||
}
|
||||
let ext_data_control_state = selection_ext::DataControlState::new::<Application, _>(
|
||||
&dh,
|
||||
Some(&primary_selection_state),
|
||||
filter_allow_any,
|
||||
);
|
||||
let wlr_data_control_state = selection_wlr::DataControlState::new::<Application, _>(
|
||||
&dh,
|
||||
Some(&primary_selection_state),
|
||||
filter_allow_any,
|
||||
);
|
||||
|
||||
let dummy_milli_hz = 60000; /* refresh rate in millihertz */
|
||||
|
||||
let output = Output::new(
|
||||
@@ -214,11 +233,15 @@ impl WvrServerState {
|
||||
|
||||
let state = Application {
|
||||
image_importer: dma_importer,
|
||||
display_handle: dh,
|
||||
compositor,
|
||||
xdg_shell,
|
||||
seat_state,
|
||||
shm,
|
||||
data_device,
|
||||
primary_selection_state,
|
||||
wlr_data_control_state,
|
||||
ext_data_control_state,
|
||||
wayvr_tasks: tasks.clone(),
|
||||
redraw_requests: HashSet::new(),
|
||||
dmabuf_state,
|
||||
@@ -300,29 +323,50 @@ impl WvrServerState {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Size, icon & fallback title comes from process
|
||||
let ([size_x, size_y], pos, fallback_title, icon, is_cage) =
|
||||
match wvr_server.processes.get(&process_handle) {
|
||||
Some(Process::Managed(p)) => (
|
||||
p.resolution,
|
||||
p.pos_mode,
|
||||
Some(p.app_name.clone()),
|
||||
p.icon.as_ref().cloned(),
|
||||
p.exec_path.ends_with("cage"),
|
||||
),
|
||||
_ => ([1920, 1080], PositionMode::Float, None, None, false),
|
||||
};
|
||||
let (min_size, max_size) = with_states(toplevel.wl_surface(), |state| {
|
||||
let mut guard = state.cached_state.get::<SurfaceCachedState>();
|
||||
let mut min_size = guard.current().min_size;
|
||||
let mut max_size = guard.current().max_size;
|
||||
|
||||
let window_handle = wvr_server.wm.create_window(
|
||||
toplevel.clone(),
|
||||
process_handle,
|
||||
size_x,
|
||||
size_y,
|
||||
);
|
||||
if min_size.is_empty() {
|
||||
min_size = Size::new(1, 1);
|
||||
}
|
||||
|
||||
if max_size.is_empty() {
|
||||
max_size = Size::new(4096, 4096);
|
||||
}
|
||||
|
||||
(min_size, max_size)
|
||||
});
|
||||
|
||||
// Size, icon & fallback title comes from process
|
||||
let (size, pos, fallback_title, icon, is_cage) =
|
||||
match wvr_server.processes.get(&process_handle) {
|
||||
Some(Process::Managed(p)) => {
|
||||
let size: Size<i32, Logical> =
|
||||
Size::new(p.resolution[0] as _, p.resolution[1] as _);
|
||||
(
|
||||
size.clamp(min_size, max_size),
|
||||
p.pos_mode,
|
||||
Some(p.app_name.clone()),
|
||||
p.icon.as_ref().cloned(),
|
||||
p.exec_path.ends_with("cage"),
|
||||
)
|
||||
}
|
||||
_ => (min_size, PositionMode::Float, None, None, false),
|
||||
};
|
||||
|
||||
let mut title: Arc<str> = fallback_title
|
||||
.unwrap_or_else(|| format!("P{}", client.pid))
|
||||
.into();
|
||||
|
||||
let window_handle = wvr_server.wm.create_window(
|
||||
toplevel.clone(),
|
||||
process_handle,
|
||||
size.w as _,
|
||||
size.h as _,
|
||||
);
|
||||
|
||||
let mut icon = icon;
|
||||
|
||||
// Try to get title from xdg_toplevel, unless it's running in cage
|
||||
@@ -374,7 +418,7 @@ impl WvrServerState {
|
||||
app,
|
||||
window_handle,
|
||||
icon,
|
||||
[size_x, size_y],
|
||||
[size.w as _, size.h as _],
|
||||
pos,
|
||||
)
|
||||
.context("Could not create WvrWindow overlay")
|
||||
|
||||
Reference in New Issue
Block a user