mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-27 21:58:18 +01:00
Add WindowElement, xwayland stuff to state
This commit is contained in:
parent
087292b16f
commit
a146d5a4ad
4 changed files with 332 additions and 7 deletions
|
@ -1,5 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
pub mod xwayland;
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use smithay::{
|
||||
|
|
99
src/handlers/xwayland.rs
Normal file
99
src/handlers/xwayland.rs
Normal file
|
@ -0,0 +1,99 @@
|
|||
use smithay::xwayland::XwmHandler;
|
||||
|
||||
use crate::{backend::Backend, state::CalloopData};
|
||||
|
||||
impl<B: Backend> XwmHandler for CalloopData<B> {
|
||||
fn xwm_state(&mut self, xwm: smithay::xwayland::xwm::XwmId) -> &mut smithay::xwayland::X11Wm {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn new_window(
|
||||
&mut self,
|
||||
xwm: smithay::xwayland::xwm::XwmId,
|
||||
window: smithay::xwayland::X11Surface,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn new_override_redirect_window(
|
||||
&mut self,
|
||||
xwm: smithay::xwayland::xwm::XwmId,
|
||||
window: smithay::xwayland::X11Surface,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn map_window_request(
|
||||
&mut self,
|
||||
xwm: smithay::xwayland::xwm::XwmId,
|
||||
window: smithay::xwayland::X11Surface,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn mapped_override_redirect_window(
|
||||
&mut self,
|
||||
xwm: smithay::xwayland::xwm::XwmId,
|
||||
window: smithay::xwayland::X11Surface,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn unmapped_window(
|
||||
&mut self,
|
||||
xwm: smithay::xwayland::xwm::XwmId,
|
||||
window: smithay::xwayland::X11Surface,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn destroyed_window(
|
||||
&mut self,
|
||||
xwm: smithay::xwayland::xwm::XwmId,
|
||||
window: smithay::xwayland::X11Surface,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn configure_request(
|
||||
&mut self,
|
||||
xwm: smithay::xwayland::xwm::XwmId,
|
||||
window: smithay::xwayland::X11Surface,
|
||||
x: Option<i32>,
|
||||
y: Option<i32>,
|
||||
w: Option<u32>,
|
||||
h: Option<u32>,
|
||||
reorder: Option<smithay::xwayland::xwm::Reorder>,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn configure_notify(
|
||||
&mut self,
|
||||
xwm: smithay::xwayland::xwm::XwmId,
|
||||
window: smithay::xwayland::X11Surface,
|
||||
geometry: smithay::utils::Rectangle<i32, smithay::utils::Logical>,
|
||||
above: Option<smithay::reexports::x11rb::protocol::xproto::Window>,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn resize_request(
|
||||
&mut self,
|
||||
xwm: smithay::xwayland::xwm::XwmId,
|
||||
window: smithay::xwayland::X11Surface,
|
||||
button: u32,
|
||||
resize_edge: smithay::xwayland::xwm::ResizeEdge,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn move_request(
|
||||
&mut self,
|
||||
xwm: smithay::xwayland::xwm::XwmId,
|
||||
window: smithay::xwayland::X11Surface,
|
||||
button: u32,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
}
|
54
src/state.rs
54
src/state.rs
|
@ -8,6 +8,7 @@ use std::{
|
|||
path::Path,
|
||||
process::Stdio,
|
||||
sync::{Arc, Mutex},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
@ -15,6 +16,7 @@ use crate::{
|
|||
msg::{Args, CallbackId, Msg, OutgoingMsg, Request, RequestId, RequestResponse},
|
||||
PinnacleSocketSource,
|
||||
},
|
||||
cursor::Cursor,
|
||||
focus::FocusState,
|
||||
grab::resize_grab::ResizeSurfaceState,
|
||||
tag::Tag,
|
||||
|
@ -44,7 +46,7 @@ use smithay::{
|
|||
Display,
|
||||
},
|
||||
},
|
||||
utils::{Clock, Logical, Monotonic, Point},
|
||||
utils::{Clock, Logical, Monotonic, Point, Size},
|
||||
wayland::{
|
||||
compositor::{self, CompositorClientState, CompositorState},
|
||||
data_device::DataDeviceState,
|
||||
|
@ -56,6 +58,7 @@ use smithay::{
|
|||
socket::ListeningSocketSource,
|
||||
viewporter::ViewporterState,
|
||||
},
|
||||
xwayland::{X11Wm, XWayland, XWaylandEvent},
|
||||
};
|
||||
|
||||
use crate::{backend::Backend, input::InputState};
|
||||
|
@ -97,6 +100,10 @@ pub struct State<B: Backend> {
|
|||
// TODO: move into own struct
|
||||
// | basically just clean this mess up
|
||||
pub output_callback_ids: Vec<CallbackId>,
|
||||
|
||||
pub xwayland: XWayland,
|
||||
pub xwm: Option<X11Wm>,
|
||||
pub xdisplay: Option<u32>,
|
||||
}
|
||||
|
||||
impl<B: Backend> State<B> {
|
||||
|
@ -794,9 +801,48 @@ impl<B: Backend> State<B> {
|
|||
Event::Msg(msg) => data.state.handle_msg(msg),
|
||||
Event::Closed => todo!(),
|
||||
})
|
||||
.unwrap(); // TODO: unwrap
|
||||
.expect("failed to insert rx_channel into loop");
|
||||
});
|
||||
|
||||
let xwayland = {
|
||||
let (xwayland, channel) = XWayland::new(&display_handle);
|
||||
let clone = display_handle.clone();
|
||||
let res =
|
||||
loop_handle.insert_source(channel, move |event, _metadata, data| match event {
|
||||
XWaylandEvent::Ready {
|
||||
connection,
|
||||
client,
|
||||
client_fd: _,
|
||||
display,
|
||||
} => {
|
||||
let mut wm = X11Wm::start_wm(
|
||||
data.state.loop_handle.clone(),
|
||||
clone.clone(),
|
||||
connection,
|
||||
client,
|
||||
)
|
||||
.expect("failed to attach x11wm");
|
||||
let cursor = Cursor::load();
|
||||
let image = cursor.get_image(1, Duration::ZERO);
|
||||
wm.set_cursor(
|
||||
&image.pixels_rgba,
|
||||
Size::from((image.width as u16, image.height as u16)),
|
||||
Point::from((image.xhot as u16, image.yhot as u16)),
|
||||
)
|
||||
.expect("failed to set xwayland default cursor");
|
||||
data.state.xwm = Some(wm);
|
||||
data.state.xdisplay = Some(display);
|
||||
}
|
||||
XWaylandEvent::Exited => {
|
||||
data.state.xwm.take();
|
||||
}
|
||||
});
|
||||
if let Err(err) = res {
|
||||
tracing::error!("Failed to insert XWayland source into loop: {err}");
|
||||
}
|
||||
xwayland
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
backend_data,
|
||||
loop_signal,
|
||||
|
@ -830,6 +876,10 @@ impl<B: Backend> State<B> {
|
|||
|
||||
windows: vec![],
|
||||
output_callback_ids: vec![],
|
||||
|
||||
xwayland,
|
||||
xwm: None,
|
||||
xdisplay: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
184
src/window.rs
184
src/window.rs
|
@ -1,17 +1,31 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
use std::sync::atomic::AtomicU32;
|
||||
use std::{cell::RefCell, sync::atomic::AtomicU32, time::Duration};
|
||||
|
||||
use smithay::{
|
||||
desktop::Window,
|
||||
desktop::{
|
||||
utils::{
|
||||
send_dmabuf_feedback_surface_tree, send_frames_surface_tree,
|
||||
take_presentation_feedback_surface_tree, with_surfaces_surface_tree,
|
||||
OutputPresentationFeedback,
|
||||
},
|
||||
Window, WindowSurfaceType,
|
||||
},
|
||||
output::Output,
|
||||
reexports::{
|
||||
wayland_protocols::xdg::shell::server::xdg_toplevel,
|
||||
wayland_protocols::{
|
||||
wp::presentation_time::server::wp_presentation_feedback,
|
||||
xdg::shell::server::xdg_toplevel,
|
||||
},
|
||||
wayland_server::protocol::wl_surface::WlSurface,
|
||||
},
|
||||
utils::{user_data::UserDataMap, IsAlive, Logical, Point},
|
||||
wayland::{
|
||||
compositor::{Blocker, BlockerState},
|
||||
compositor::{Blocker, BlockerState, SurfaceData},
|
||||
dmabuf::DmabufFeedback,
|
||||
seat::WaylandFocus,
|
||||
},
|
||||
xwayland::X11Surface,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
@ -19,10 +33,170 @@ use crate::{
|
|||
state::{State, WithState},
|
||||
};
|
||||
|
||||
use self::window_state::Float;
|
||||
use self::window_state::{Float, WindowState};
|
||||
|
||||
pub mod window_state;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum WindowElement {
|
||||
Wayland(Window),
|
||||
X11(X11Surface),
|
||||
}
|
||||
|
||||
impl WindowElement {
|
||||
pub fn surface_under(
|
||||
&self,
|
||||
location: Point<i32, Logical>,
|
||||
window_type: WindowSurfaceType,
|
||||
) -> Option<(WlSurface, Point<i32, Logical>)> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn with_surfaces<F>(&self, processor: F)
|
||||
where
|
||||
F: FnMut(&WlSurface, &SurfaceData) + Copy,
|
||||
{
|
||||
match self {
|
||||
WindowElement::Wayland(window) => window.with_surfaces(processor),
|
||||
WindowElement::X11(surface) => {
|
||||
if let Some(surface) = surface.wl_surface() {
|
||||
with_surfaces_surface_tree(&surface, processor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_frame<T, F>(
|
||||
&self,
|
||||
output: &Output,
|
||||
time: T,
|
||||
throttle: Option<Duration>,
|
||||
primary_scan_out_output: F,
|
||||
) where
|
||||
T: Into<Duration>,
|
||||
F: FnMut(&WlSurface, &SurfaceData) -> Option<Output> + Copy,
|
||||
{
|
||||
match self {
|
||||
WindowElement::Wayland(window) => {
|
||||
window.send_frame(output, time, throttle, primary_scan_out_output)
|
||||
}
|
||||
WindowElement::X11(surface) => {
|
||||
if let Some(surface) = surface.wl_surface() {
|
||||
send_frames_surface_tree(
|
||||
&surface,
|
||||
output,
|
||||
time,
|
||||
throttle,
|
||||
primary_scan_out_output,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_dmabuf_feedback<'a, P, F>(
|
||||
&self,
|
||||
output: &Output,
|
||||
primary_scan_out_output: P,
|
||||
select_dmabuf_feedback: F,
|
||||
) where
|
||||
P: FnMut(&WlSurface, &SurfaceData) -> Option<Output> + Copy,
|
||||
F: Fn(&WlSurface, &SurfaceData) -> &'a DmabufFeedback + Copy,
|
||||
{
|
||||
match self {
|
||||
WindowElement::Wayland(window) => {
|
||||
window.send_dmabuf_feedback(
|
||||
output,
|
||||
primary_scan_out_output,
|
||||
select_dmabuf_feedback,
|
||||
);
|
||||
}
|
||||
WindowElement::X11(surface) => {
|
||||
if let Some(surface) = surface.wl_surface() {
|
||||
send_dmabuf_feedback_surface_tree(
|
||||
&surface,
|
||||
output,
|
||||
primary_scan_out_output,
|
||||
select_dmabuf_feedback,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take_presentation_feedback<F1, F2>(
|
||||
&self,
|
||||
output_feedback: &mut OutputPresentationFeedback,
|
||||
primary_scan_out_output: F1,
|
||||
presentation_feedback_flags: F2,
|
||||
) where
|
||||
F1: FnMut(&WlSurface, &SurfaceData) -> Option<Output> + Copy,
|
||||
F2: FnMut(&WlSurface, &SurfaceData) -> wp_presentation_feedback::Kind + Copy,
|
||||
{
|
||||
match self {
|
||||
WindowElement::Wayland(window) => {
|
||||
window.take_presentation_feedback(
|
||||
output_feedback,
|
||||
primary_scan_out_output,
|
||||
presentation_feedback_flags,
|
||||
);
|
||||
}
|
||||
WindowElement::X11(surface) => {
|
||||
if let Some(surface) = surface.wl_surface() {
|
||||
take_presentation_feedback_surface_tree(
|
||||
&surface,
|
||||
output_feedback,
|
||||
primary_scan_out_output,
|
||||
presentation_feedback_flags,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wl_surface(&self) -> Option<WlSurface> {
|
||||
match self {
|
||||
WindowElement::Wayland(window) => window.wl_surface(),
|
||||
WindowElement::X11(surface) => surface.wl_surface(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn user_data(&self) -> &UserDataMap {
|
||||
match self {
|
||||
WindowElement::Wayland(window) => window.user_data(),
|
||||
WindowElement::X11(surface) => surface.user_data(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IsAlive for WindowElement {
|
||||
fn alive(&self) -> bool {
|
||||
match self {
|
||||
WindowElement::Wayland(window) => window.alive(),
|
||||
WindowElement::X11(surface) => surface.alive(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WithState for WindowElement {
|
||||
type State = WindowState;
|
||||
|
||||
fn with_state<F, T>(&self, mut func: F) -> T
|
||||
where
|
||||
F: FnMut(&mut Self::State) -> T,
|
||||
{
|
||||
self.user_data()
|
||||
.insert_if_missing(RefCell::<Self::State>::default);
|
||||
|
||||
let state = self
|
||||
.user_data()
|
||||
.get::<RefCell<Self::State>>()
|
||||
.expect("RefCell not in data map");
|
||||
|
||||
func(&mut state.borrow_mut())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> State<B> {
|
||||
/// Returns the [Window] associated with a given [WlSurface].
|
||||
pub fn window_for_surface(&self, surface: &WlSurface) -> Option<Window> {
|
||||
|
|
Loading…
Reference in a new issue