server: impl Deref(Mut) for ServerState to Inner coercion

This commit is contained in:
En-En 2025-08-05 15:31:37 +00:00 committed by Supreeeme
parent fe28bcb880
commit cbabd591a3
4 changed files with 121 additions and 240 deletions

View file

@ -1,7 +1,7 @@
mod server; mod server;
pub mod xstate; pub mod xstate;
use crate::server::{EarlyConnection, PendingSurfaceState, ServerState}; use crate::server::{NoConnection, PendingSurfaceState, ServerState};
use crate::xstate::{RealConnection, XState}; use crate::xstate::{RealConnection, XState};
use log::{error, info}; use log::{error, info};
use rustix::event::{poll, PollFd, PollFlags}; use rustix::event::{poll, PollFd, PollFlags};
@ -29,7 +29,7 @@ pub trait X11Selection {
fn write_to(&self, mime: &str, pipe: WritePipe); fn write_to(&self, mime: &str, pipe: WritePipe);
} }
type EarlyServerState = ServerState<EarlyConnection<<RealConnection as XConnection>::X11Selection>>; type EarlyServerState = ServerState<NoConnection<<RealConnection as XConnection>::X11Selection>>;
type RealServerState = ServerState<RealConnection>; type RealServerState = ServerState<RealConnection>;
pub trait RunData { pub trait RunData {
@ -63,6 +63,7 @@ pub fn main(mut data: impl RunData) -> Option<()> {
// FFI level, see (`XState::new`), `xsock_wl`'s destructor also closes the FD, leading the FD // FFI level, see (`XState::new`), `xsock_wl`'s destructor also closes the FD, leading the FD
// being closed twice. This mainly caused problems in the integration tests, where `xsock_wl`'s // being closed twice. This mainly caused problems in the integration tests, where `xsock_wl`'s
// destructor would be run after the descriptor was freed, leading to an opaque abort message. // destructor would be run after the descriptor was freed, leading to an opaque abort message.
// See https://github.com/rust-x-bindings/rust-xcb/issues/282 for further explanation.
let xsock_wl = Box::leak(Box::new(xsock_wl)); let xsock_wl = Box::leak(Box::new(xsock_wl));
// Prevent creation of new Xwayland command from closing fd // Prevent creation of new Xwayland command from closing fd
rustix::io::fcntl_setfd(&xsock_xwl, rustix::io::FdFlags::empty()).unwrap(); rustix::io::fcntl_setfd(&xsock_xwl, rustix::io::FdFlags::empty()).unwrap();
@ -176,7 +177,7 @@ pub fn main(mut data: impl RunData) -> Option<()> {
Err(other) => panic!("Poll failed: {other:?}"), Err(other) => panic!("Poll failed: {other:?}"),
} }
display.dispatch_clients(server_state.inner_mut()).unwrap(); display.dispatch_clients(&mut *server_state).unwrap();
server_state.run(); server_state.run();
display.flush_clients().unwrap(); display.flush_clients().unwrap();
} }
@ -207,7 +208,7 @@ pub fn main(mut data: impl RunData) -> Option<()> {
loop { loop {
xstate.handle_events(&mut server_state); xstate.handle_events(&mut server_state);
display.dispatch_clients(server_state.inner_mut()).unwrap(); display.dispatch_clients(&mut *server_state).unwrap();
server_state.run(); server_state.run();
display.flush_clients().unwrap(); display.flush_clients().unwrap();

View file

@ -88,7 +88,8 @@ impl Event for SurfaceEvents {
SurfaceEvents::Popup(event) => Self::popup_event(event, target, state), SurfaceEvents::Popup(event) => Self::popup_event(event, target, state),
SurfaceEvents::FractionalScale(event) => match event { SurfaceEvents::FractionalScale(event) => match event {
wp_fractional_scale_v1::Event::PreferredScale { scale } => { wp_fractional_scale_v1::Event::PreferredScale { scale } => {
let entity = state.inner.world.entity(target).unwrap(); let state = state.deref_mut();
let entity = state.world.entity(target).unwrap();
let factor = scale as f64 / 120.0; let factor = scale as f64 / 120.0;
debug!( debug!(
"{} scale factor: {}", "{} scale factor: {}",
@ -100,14 +101,14 @@ impl Event for SurfaceEvents {
if let Some(OnOutput(output)) = entity.get::<&OnOutput>().as_deref().copied() { if let Some(OnOutput(output)) = entity.get::<&OnOutput>().as_deref().copied() {
if update_output_scale( if update_output_scale(
state.inner.world.query_one(output).unwrap(), state.world.query_one(output).unwrap(),
OutputScaleFactor::Fractional(factor), OutputScaleFactor::Fractional(factor),
) { ) {
state.inner.updated_outputs.push(output); state.updated_outputs.push(output);
} }
} }
if entity.has::<WindowData>() { if entity.has::<WindowData>() {
update_surface_viewport(state.inner.world.query_one(target).unwrap()); update_surface_viewport(state.world.query_one(target).unwrap());
} }
} }
_ => unreachable!(), _ => unreachable!(),
@ -416,18 +417,13 @@ pub(super) fn update_surface_viewport(
impl Event for client::wl_buffer::Event { impl Event for client::wl_buffer::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
// The only event from a buffer would be the release. // The only event from a buffer would be the release.
state state.world.get::<&WlBuffer>(target).unwrap().release();
.inner
.world
.get::<&WlBuffer>(target)
.unwrap()
.release();
} }
} }
impl Event for client::wl_seat::Event { impl Event for client::wl_seat::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
let server = state.inner.world.get::<&WlSeat>(target).unwrap(); let server = state.world.get::<&WlSeat>(target).unwrap();
simple_event_shunt! { simple_event_shunt! {
server, self => [ server, self => [
Capabilities { |capabilities| convert_wenum(capabilities) }, Capabilities { |capabilities| convert_wenum(capabilities) },
@ -457,12 +453,13 @@ impl Event for client::wl_pointer::Event {
surface_x, surface_x,
surface_y, surface_y,
} => { } => {
let connection = &mut state.connection;
let state = &mut state.inner;
let mut cmd = CommandBuffer::new(); let mut cmd = CommandBuffer::new();
let pending_enter = state.inner.world.remove_one::<PendingEnter>(target).ok(); let pending_enter = state.world.remove_one::<PendingEnter>(target).ok();
let server = state.inner.world.get::<&WlPointer>(target).unwrap(); let server = state.world.get::<&WlPointer>(target).unwrap();
let mut query = surface.data().copied().and_then(|e| { let mut query = surface.data().copied().and_then(|e| {
state state
.inner
.world .world
.query_one::<(&WlSurface, &SurfaceRole, &SurfaceScaleFactor, &x::Window)>(e) .query_one::<(&WlSurface, &SurfaceRole, &SurfaceScaleFactor, &x::Window)>(e)
.ok() .ok()
@ -479,9 +476,9 @@ impl Event for client::wl_pointer::Event {
let mut do_enter = || { let mut do_enter = || {
debug!("pointer entering {} ({serial} {})", surface.id(), scale.0); debug!("pointer entering {} ({serial} {})", surface.id(), scale.0);
server.enter(serial, surface, surface_x * scale.0, surface_y * scale.0); server.enter(serial, surface, surface_x * scale.0, surface_y * scale.0);
state.connection.raise_to_top(*window); connection.raise_to_top(*window);
if !surface_is_popup { if !surface_is_popup {
state.inner.last_hovered = Some(*window); state.last_hovered = Some(*window);
} }
}; };
@ -510,22 +507,21 @@ impl Event for client::wl_pointer::Event {
} }
drop(query); drop(query);
drop(server); drop(server);
cmd.run_on(&mut state.inner.world); cmd.run_on(&mut state.world);
} }
client::wl_pointer::Event::Leave { serial, surface } => { client::wl_pointer::Event::Leave { serial, surface } => {
let _ = state.inner.world.remove_one::<PendingEnter>(target); let _ = state.world.remove_one::<PendingEnter>(target);
if !surface.is_alive() { if !surface.is_alive() {
return; return;
} }
debug!("leaving surface ({serial})"); debug!("leaving surface ({serial})");
let _ = state.inner.world.remove_one::<PendingEnter>(target); let _ = state.world.remove_one::<PendingEnter>(target);
if let Some(surface) = surface if let Some(surface) = surface
.data() .data()
.copied() .copied()
.and_then(|key| state.inner.world.get::<&WlSurface>(key).ok()) .and_then(|key| state.world.get::<&WlSurface>(key).ok())
{ {
state state
.inner
.world .world
.get::<&WlPointer>(target) .get::<&WlPointer>(target)
.unwrap() .unwrap()
@ -539,7 +535,7 @@ impl Event for client::wl_pointer::Event {
surface_x, surface_x,
surface_y, surface_y,
} => { } => {
let pending_enter = state.inner.world.get::<&PendingEnter>(target).ok(); let pending_enter = state.world.get::<&PendingEnter>(target).ok();
match pending_enter.as_deref() { match pending_enter.as_deref() {
Some(p) => { Some(p) => {
let PendingEnter(client::wl_pointer::Event::Enter { let PendingEnter(client::wl_pointer::Event::Enter {
@ -554,7 +550,7 @@ impl Event for client::wl_pointer::Event {
if surface if surface
.data() .data()
.copied() .copied()
.is_some_and(|key| state.inner.world.contains(key)) .is_some_and(|key| state.world.contains(key))
{ {
trace!("resending enter ({serial}) before motion"); trace!("resending enter ({serial}) before motion");
let enter_event = client::wl_pointer::Event::Enter { let enter_event = client::wl_pointer::Event::Enter {
@ -574,7 +570,6 @@ impl Event for client::wl_pointer::Event {
None => { None => {
drop(pending_enter); drop(pending_enter);
let (server, scale) = state let (server, scale) = state
.inner
.world .world
.query_one_mut::<(&WlPointer, &SurfaceScaleFactor)>(target) .query_one_mut::<(&WlPointer, &SurfaceScaleFactor)>(target)
.unwrap(); .unwrap();
@ -589,7 +584,7 @@ impl Event for client::wl_pointer::Event {
} }
} }
_ => { _ => {
let server = state.inner.world.get::<&WlPointer>(target).unwrap(); let server = state.world.get::<&WlPointer>(target).unwrap();
simple_event_shunt! { simple_event_shunt! {
server, self => [ server, self => [
Frame, Frame,
@ -632,7 +627,7 @@ impl Event for client::wl_pointer::Event {
impl Event for client::wl_keyboard::Event { impl Event for client::wl_keyboard::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
let state = state.inner_mut(); let state = state.deref_mut();
let data = state.world.entity(target).unwrap(); let data = state.world.entity(target).unwrap();
let keyboard = data.get::<&WlKeyboard>().unwrap(); let keyboard = data.get::<&WlKeyboard>().unwrap();
match self { match self {
@ -723,7 +718,7 @@ impl Event for client::wl_keyboard::Event {
impl Event for client::wl_touch::Event { impl Event for client::wl_touch::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
let state = state.inner_mut(); let state = state.deref_mut();
match self { match self {
Self::Down { Self::Down {
serial, serial,
@ -1039,7 +1034,7 @@ impl OutputEvent {
y, y,
state, state,
); );
let state = state.inner_mut(); let state = state.deref_mut();
let (output, dimensions, xdg) = state let (output, dimensions, xdg) = state
.world .world
@ -1081,7 +1076,7 @@ impl OutputEvent {
height, height,
refresh, refresh,
} => { } => {
let state = state.inner_mut(); let state = state.deref_mut();
let (output, dimensions) = state let (output, dimensions) = state
.world .world
.query_one_mut::<(&WlOutput, &mut OutputDimensions)>(target) .query_one_mut::<(&WlOutput, &mut OutputDimensions)>(target)
@ -1098,7 +1093,7 @@ impl OutputEvent {
output.mode(convert_wenum(flags), width, height, refresh); output.mode(convert_wenum(flags), width, height, refresh);
} }
Event::Scale { factor } => { Event::Scale { factor } => {
let state = state.inner_mut(); let state = state.deref_mut();
debug!( debug!(
"{} scale: {factor}", "{} scale: {factor}",
state.world.get::<&WlOutput>(target).unwrap().id() state.world.get::<&WlOutput>(target).unwrap().id()
@ -1114,7 +1109,7 @@ impl OutputEvent {
} }
} }
Event::Name { name } => { Event::Name { name } => {
let state = state.inner_mut(); let state = state.deref_mut();
state state
.world .world
.get::<&WlOutput>(target) .get::<&WlOutput>(target)
@ -1123,7 +1118,7 @@ impl OutputEvent {
state.world.insert(target, (OutputName(name),)).unwrap(); state.world.insert(target, (OutputName(name),)).unwrap();
} }
_ => simple_event_shunt! { _ => simple_event_shunt! {
state.inner.world.get::<&WlOutput>(target).unwrap(), state.world.get::<&WlOutput>(target).unwrap(),
event: client::wl_output::Event => [ event: client::wl_output::Event => [
Description { description }, Description { description },
Done Done
@ -1142,7 +1137,7 @@ impl OutputEvent {
match event { match event {
Event::LogicalPosition { x, y } => { Event::LogicalPosition { x, y } => {
update_output_offset(target, OutputDimensionsSource::Xdg, x, y, state); update_output_offset(target, OutputDimensionsSource::Xdg, x, y, state);
let state = state.inner_mut(); let state = state.deref_mut();
state state
.world .world
.get::<&XdgOutputServer>(target) .get::<&XdgOutputServer>(target)
@ -1153,7 +1148,7 @@ impl OutputEvent {
); );
} }
Event::LogicalSize { .. } => { Event::LogicalSize { .. } => {
let state = state.inner_mut(); let state = state.deref_mut();
let (xdg, dimensions) = state let (xdg, dimensions) = state
.world .world
.query_one_mut::<(&XdgOutputServer, &OutputDimensions)>(target) .query_one_mut::<(&XdgOutputServer, &OutputDimensions)>(target)
@ -1165,7 +1160,7 @@ impl OutputEvent {
} }
} }
_ => simple_event_shunt! { _ => simple_event_shunt! {
state.inner.world.get::<&XdgOutputServer>(target).unwrap(), state.world.get::<&XdgOutputServer>(target).unwrap(),
event: zxdg_output_v1::Event => [ event: zxdg_output_v1::Event => [
Done, Done,
Name { name }, Name { name },
@ -1178,7 +1173,7 @@ impl OutputEvent {
impl Event for wl_drm::client::wl_drm::Event { impl Event for wl_drm::client::wl_drm::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
let server = state.inner.world.get::<&WlDrmServer>(target).unwrap(); let server = state.world.get::<&WlDrmServer>(target).unwrap();
simple_event_shunt! { simple_event_shunt! {
server, self => [ server, self => [
Device { name }, Device { name },
@ -1193,7 +1188,6 @@ impl Event for wl_drm::client::wl_drm::Event {
impl Event for c_dmabuf::zwp_linux_dmabuf_feedback_v1::Event { impl Event for c_dmabuf::zwp_linux_dmabuf_feedback_v1::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
let server = state let server = state
.inner
.world .world
.get::<&s_dmabuf::zwp_linux_dmabuf_feedback_v1::ZwpLinuxDmabufFeedbackV1>(target) .get::<&s_dmabuf::zwp_linux_dmabuf_feedback_v1::ZwpLinuxDmabufFeedbackV1>(target)
.unwrap(); .unwrap();
@ -1213,11 +1207,7 @@ impl Event for c_dmabuf::zwp_linux_dmabuf_feedback_v1::Event {
impl Event for zwp_relative_pointer_v1::Event { impl Event for zwp_relative_pointer_v1::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
let server = state let server = state.world.get::<&RelativePointerServer>(target).unwrap();
.inner
.world
.get::<&RelativePointerServer>(target)
.unwrap();
simple_event_shunt! { simple_event_shunt! {
server, self => [ server, self => [
RelativeMotion { RelativeMotion {
@ -1235,11 +1225,7 @@ impl Event for zwp_relative_pointer_v1::Event {
impl Event for zwp_locked_pointer_v1::Event { impl Event for zwp_locked_pointer_v1::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
let server = state let server = state.world.get::<&LockedPointerServer>(target).unwrap();
.inner
.world
.get::<&LockedPointerServer>(target)
.unwrap();
simple_event_shunt! { simple_event_shunt! {
server, self => [ server, self => [
Locked, Locked,
@ -1251,11 +1237,7 @@ impl Event for zwp_locked_pointer_v1::Event {
impl Event for zwp_confined_pointer_v1::Event { impl Event for zwp_confined_pointer_v1::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
let server = state let server = state.world.get::<&ConfinedPointerServer>(target).unwrap();
.inner
.world
.get::<&ConfinedPointerServer>(target)
.unwrap();
simple_event_shunt! { simple_event_shunt! {
server, self => [ server, self => [
Confined, Confined,
@ -1267,7 +1249,7 @@ impl Event for zwp_confined_pointer_v1::Event {
impl Event for zwp_tablet_seat_v2::Event { impl Event for zwp_tablet_seat_v2::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
let state = state.inner_mut(); let state = state.deref_mut();
let seat = state.world.get::<&TabletSeatServer>(target).unwrap(); let seat = state.world.get::<&TabletSeatServer>(target).unwrap();
match self { match self {
Self::TabletAdded { id } => { Self::TabletAdded { id } => {
@ -1295,7 +1277,7 @@ impl Event for zwp_tablet_seat_v2::Event {
impl Event for zwp_tablet_v2::Event { impl Event for zwp_tablet_v2::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
let tab = state.inner.world.get::<&TabletServer>(target).unwrap(); let tab = state.world.get::<&TabletServer>(target).unwrap();
simple_event_shunt! { simple_event_shunt! {
tab, self => [ tab, self => [
Name { name }, Name { name },
@ -1310,7 +1292,7 @@ impl Event for zwp_tablet_v2::Event {
impl Event for zwp_tablet_pad_v2::Event { impl Event for zwp_tablet_pad_v2::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
let state = state.inner_mut(); let state = state.deref_mut();
let pad = state.world.get::<&TabletPadServer>(target).unwrap(); let pad = state.world.get::<&TabletPadServer>(target).unwrap();
let s_surf; let s_surf;
match self { match self {
@ -1364,7 +1346,7 @@ impl Event for zwp_tablet_pad_v2::Event {
impl Event for zwp_tablet_tool_v2::Event { impl Event for zwp_tablet_tool_v2::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
let state = state.inner_mut(); let state = state.deref_mut();
match self { match self {
Self::ProximityIn { Self::ProximityIn {
serial, serial,
@ -1465,7 +1447,7 @@ where
impl Event for zwp_tablet_pad_group_v2::Event { impl Event for zwp_tablet_pad_group_v2::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
let state = state.inner_mut(); let state = state.deref_mut();
let group = state.world.get::<&TabletPadGroupServer>(target).unwrap(); let group = state.world.get::<&TabletPadGroupServer>(target).unwrap();
match self { match self {
Self::Buttons { buttons } => group.buttons(buttons), Self::Buttons { buttons } => group.buttons(buttons),
@ -1494,7 +1476,7 @@ impl Event for zwp_tablet_pad_group_v2::Event {
impl Event for zwp_tablet_pad_ring_v2::Event { impl Event for zwp_tablet_pad_ring_v2::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
let state = state.inner_mut(); let state = state.deref_mut();
let ring = state.world.get::<&TabletPadRingServer>(target).unwrap(); let ring = state.world.get::<&TabletPadRingServer>(target).unwrap();
simple_event_shunt! { simple_event_shunt! {
ring, self => [ ring, self => [
@ -1509,7 +1491,7 @@ impl Event for zwp_tablet_pad_ring_v2::Event {
impl Event for zwp_tablet_pad_strip_v2::Event { impl Event for zwp_tablet_pad_strip_v2::Event {
fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) { fn handle<C: XConnection>(self, target: Entity, state: &mut ServerState<C>) {
let state = state.inner_mut(); let state = state.deref_mut();
let strip = state.world.get::<&TabletPadStripServer>(target).unwrap(); let strip = state.world.get::<&TabletPadStripServer>(target).unwrap();
simple_event_shunt! { simple_event_shunt! {
strip, self => [ strip, self => [

View file

@ -18,6 +18,7 @@ use smithay_client_toolkit::data_device_manager::{
}; };
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::io::Read; use std::io::Read;
use std::ops::{Deref, DerefMut};
use std::os::fd::{AsFd, BorrowedFd}; use std::os::fd::{AsFd, BorrowedFd};
use std::os::unix::net::UnixStream; use std::os::unix::net::UnixStream;
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
@ -393,10 +394,10 @@ struct GlobalOutputOffset {
/// The state of the X11 connection before XState has been fully initialized. /// The state of the X11 connection before XState has been fully initialized.
/// It implements XConnection minimally, gracefully doing nothing but logging the called functions. /// It implements XConnection minimally, gracefully doing nothing but logging the called functions.
pub struct EarlyConnection<S: X11Selection + 'static> { pub struct NoConnection<S: X11Selection + 'static> {
_p: std::marker::PhantomData<S>, _p: std::marker::PhantomData<S>,
} }
impl<S: X11Selection> XConnection for EarlyConnection<S> { impl<S: X11Selection> XConnection for NoConnection<S> {
type X11Selection = S; type X11Selection = S;
fn focus_window(&mut self, _: x::Window, _: Option<String>) { fn focus_window(&mut self, _: x::Window, _: Option<String>) {
debug!("could not focus window without XWayland initialized"); debug!("could not focus window without XWayland initialized");
@ -423,6 +424,17 @@ pub struct ServerState<C: XConnection> {
inner: InnerServerState<C::X11Selection>, inner: InnerServerState<C::X11Selection>,
pub connection: C, pub connection: C,
} }
impl<C: XConnection> Deref for ServerState<C> {
type Target = InnerServerState<C::X11Selection>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<C: XConnection> DerefMut for ServerState<C> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
pub struct InnerServerState<S: X11Selection> { pub struct InnerServerState<S: X11Selection> {
dh: DisplayHandle, dh: DisplayHandle,
@ -451,7 +463,7 @@ pub struct InnerServerState<S: X11Selection> {
new_scale: Option<f64>, new_scale: Option<f64>,
} }
impl<S: X11Selection> ServerState<EarlyConnection<S>> { impl<S: X11Selection> ServerState<NoConnection<S>> {
pub fn new( pub fn new(
mut dh: DisplayHandle, mut dh: DisplayHandle,
server_connection: Option<UnixStream>, server_connection: Option<UnixStream>,
@ -548,7 +560,7 @@ impl<S: X11Selection> ServerState<EarlyConnection<S>> {
}; };
Self { Self {
inner, inner,
connection: EarlyConnection { connection: NoConnection {
_p: std::marker::PhantomData, _p: std::marker::PhantomData,
}, },
} }
@ -566,103 +578,18 @@ impl<S: X11Selection> ServerState<EarlyConnection<S>> {
} }
impl<C: XConnection> ServerState<C> { impl<C: XConnection> ServerState<C> {
pub fn inner_mut(&mut self) -> &mut InnerServerState<C::X11Selection> {
&mut self.inner
}
pub fn clientside_fd(&self) -> BorrowedFd<'_> {
self.inner.clientside_fd()
}
fn handle_new_globals(&mut self) {
self.inner.handle_new_globals()
}
pub fn new_window(
&mut self,
window: x::Window,
override_redirect: bool,
dims: WindowDims,
pid: Option<u32>,
) {
self.inner.new_window(window, override_redirect, dims, pid)
}
pub fn set_popup(&mut self, window: x::Window, is_popup: bool) {
self.inner.set_popup(window, is_popup)
}
pub fn set_win_title(&mut self, window: x::Window, name: WmName) {
self.inner.set_win_title(window, name);
}
pub fn set_win_class(&mut self, window: x::Window, class: String) {
self.inner.set_win_class(window, class)
}
pub fn set_win_hints(&mut self, window: x::Window, hints: WmHints) {
self.inner.set_win_hints(window, hints)
}
pub fn set_size_hints(&mut self, window: x::Window, hints: WmNormalHints) {
self.inner.set_size_hints(window, hints)
}
pub fn set_win_decorations(&mut self, window: x::Window, decorations: Decorations) {
self.inner.set_win_decorations(window, decorations)
}
pub fn set_window_serial(&mut self, window: x::Window, serial: [u32; 2]) {
self.inner.set_window_serial(window, serial)
}
pub fn can_change_position(&self, window: x::Window) -> bool {
self.inner.can_change_position(window)
}
pub fn reconfigure_window(&mut self, event: x::ConfigureNotifyEvent) {
self.inner.reconfigure_window(event)
}
pub fn map_window(&mut self, window: x::Window) {
self.inner.map_window(window)
}
pub fn unmap_window(&mut self, window: x::Window) {
self.inner.unmap_window(window)
}
pub fn set_fullscreen(&mut self, window: x::Window, state: super::xstate::SetState) {
self.inner.set_fullscreen(window, state)
}
pub fn set_transient_for(&mut self, window: x::Window, parent: x::Window) {
self.inner.set_transient_for(window, parent)
}
pub fn activate_window(&mut self, window: x::Window) {
self.inner.activate_window(window)
}
pub fn destroy_window(&mut self, window: x::Window) {
self.inner.destroy_window(window)
}
pub(crate) fn set_copy_paste_source(&mut self, selection: &Rc<C::X11Selection>) {
self.inner.set_copy_paste_source(selection)
}
pub fn run(&mut self) { pub fn run(&mut self) {
if let Some(r) = self.inner.queue.prepare_read() { if let Some(r) = self.queue.prepare_read() {
let fd = r.connection_fd(); let fd = r.connection_fd();
let pollfd = PollFd::new(&fd, PollFlags::IN); let pollfd = PollFd::new(&fd, PollFlags::IN);
if poll(&mut [pollfd], 0).unwrap() > 0 { if poll(&mut [pollfd], 0).unwrap() > 0 {
let _ = r.read(); let _ = r.read();
} }
} }
self.inner let state = self.deref_mut();
state
.queue .queue
.dispatch_pending(&mut self.inner.world) .dispatch_pending(&mut state.world)
.expect("Failed dispatching client side Wayland events"); .expect("Failed dispatching client side Wayland events");
self.handle_clientside_events(); self.handle_clientside_events();
} }
@ -670,42 +597,43 @@ impl<C: XConnection> ServerState<C> {
pub fn handle_clientside_events(&mut self) { pub fn handle_clientside_events(&mut self) {
self.handle_new_globals(); self.handle_new_globals();
for (target, event) in self.inner.world.read_events() { for (target, event) in self.world.read_events() {
if !self.inner.world.contains(target) { if !self.world.contains(target) {
warn!("could not handle clientside event: stale object"); warn!("could not handle clientside event: stale object");
continue; continue;
} }
event.handle(target, self); event.handle(target, self);
} }
if self.inner.global_offset_updated { if self.global_offset_updated {
if self.inner.global_output_offset.x.owner.is_none() if self.global_output_offset.x.owner.is_none()
|| self.inner.global_output_offset.y.owner.is_none() || self.global_output_offset.y.owner.is_none()
{ {
self.calc_global_output_offset(); self.calc_global_output_offset();
} }
debug!( debug!(
"updated global output offset: {}x{}", "updated global output offset: {}x{}",
self.inner.global_output_offset.x.value, self.inner.global_output_offset.y.value self.global_output_offset.x.value, self.global_output_offset.y.value
); );
for (e, _) in self.inner.world.query::<&WlOutput>().iter() { let state = &self.inner;
for (e, _) in state.world.query::<&WlOutput>().iter() {
event::update_global_output_offset( event::update_global_output_offset(
e, e,
&self.inner.global_output_offset, &state.global_output_offset,
&self.inner.world, &state.world,
&mut self.connection, &mut self.connection,
); );
} }
self.inner.global_offset_updated = false; self.global_offset_updated = false;
} }
if !self.inner.updated_outputs.is_empty() { if !self.updated_outputs.is_empty() {
for output in self.inner.updated_outputs.drain(..) { let state = self.deref_mut();
let output_scale = self.inner.world.get::<&OutputScaleFactor>(output).unwrap(); for output in state.updated_outputs.drain(..) {
let output_scale = state.world.get::<&OutputScaleFactor>(output).unwrap();
if matches!(*output_scale, OutputScaleFactor::Output(..)) { if matches!(*output_scale, OutputScaleFactor::Output(..)) {
let mut surface_query = self let mut surface_query = state
.inner
.world .world
.query::<(&OnOutput, &mut SurfaceScaleFactor)>() .query::<(&OnOutput, &mut SurfaceScaleFactor)>()
.with::<(&WindowData, &WlSurface)>(); .with::<(&WindowData, &WlSurface)>();
@ -720,7 +648,7 @@ impl<C: XConnection> ServerState<C> {
drop(surface_query); drop(surface_query);
for surface in surfaces { for surface in surfaces {
update_surface_viewport(self.inner.world.query_one(surface).unwrap()); update_surface_viewport(state.world.query_one(surface).unwrap());
} }
} }
} }
@ -728,11 +656,7 @@ impl<C: XConnection> ServerState<C> {
let mut mixed_scale = false; let mut mixed_scale = false;
let mut scale; let mut scale;
let mut outputs = self let mut outputs = self.world.query_mut::<&OutputScaleFactor>().into_iter();
.inner
.world
.query_mut::<&OutputScaleFactor>()
.into_iter();
let (_, output_scale) = outputs.next().unwrap(); let (_, output_scale) = outputs.next().unwrap();
scale = output_scale.get(); scale = output_scale.get();
@ -749,70 +673,45 @@ impl<C: XConnection> ServerState<C> {
} }
debug!("Using new scale {scale}"); debug!("Using new scale {scale}");
self.inner.new_scale = Some(scale); self.new_scale = Some(scale);
} }
{ {
if let Some(FocusData { if let Some(FocusData {
window, window,
output_name, output_name,
}) = self.inner.to_focus.take() }) = self.to_focus.take()
{ {
debug!("focusing window {window:?}"); debug!("focusing window {window:?}");
self.connection.focus_window(window, output_name); self.connection.focus_window(window, output_name);
self.inner.last_focused_toplevel = Some(window); self.last_focused_toplevel = Some(window);
} else if self.inner.unfocus { } else if self.unfocus {
self.connection.focus_window(x::WINDOW_NONE, None); self.connection.focus_window(x::WINDOW_NONE, None);
} }
self.inner.unfocus = false; self.unfocus = false;
} }
self.handle_clipboard_events(); self.handle_clipboard_events();
self.handle_activations(); self.handle_activations();
self.inner self.queue
.queue
.flush() .flush()
.expect("Failed flushing clientside events"); .expect("Failed flushing clientside events");
} }
pub fn new_global_scale(&mut self) -> Option<f64> {
self.inner.new_global_scale()
}
pub fn new_selection(&mut self) -> Option<ForeignSelection> {
self.inner.new_selection()
}
fn handle_clipboard_events(&mut self) {
self.inner.handle_clipboard_events()
}
fn handle_activations(&mut self) {
self.inner.handle_activations()
}
fn calc_global_output_offset(&mut self) {
self.inner.calc_global_output_offset()
}
// create_role_window is only called in a Dispatch impl, a trait impl necessarily moved to be
// on the ineer value. create_toplevel and create_popup are only called by that create_role_window
// call, so none of them need wrapper functions.
fn close_x_window(&mut self, window: x::Window) { fn close_x_window(&mut self, window: x::Window) {
debug!("sending close request to {window:?}"); debug!("sending close request to {window:?}");
self.connection.close_window(window); self.connection.close_window(window);
if self.inner.last_focused_toplevel == Some(window) { if self.last_focused_toplevel == Some(window) {
self.inner.last_focused_toplevel.take(); self.last_focused_toplevel.take();
} }
if self.inner.last_hovered == Some(window) { if self.last_hovered == Some(window) {
self.inner.last_hovered.take(); self.last_hovered.take();
} }
} }
} }
impl<S: X11Selection + 'static> InnerServerState<S> { impl<S: X11Selection + 'static> InnerServerState<S> {
fn clientside_fd(&self) -> BorrowedFd<'_> { pub fn clientside_fd(&self) -> BorrowedFd<'_> {
self.queue.as_fd() self.queue.as_fd()
} }
@ -821,7 +720,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
handle_globals::<S>(&self.dh, globals.iter()); handle_globals::<S>(&self.dh, globals.iter());
} }
fn new_window( pub fn new_window(
&mut self, &mut self,
window: x::Window, window: x::Window,
override_redirect: bool, override_redirect: bool,
@ -846,7 +745,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
self.windows.insert(window, id); self.windows.insert(window, id);
} }
fn set_popup(&mut self, window: x::Window, is_popup: bool) { pub fn set_popup(&mut self, window: x::Window, is_popup: bool) {
let Some(id) = self.windows.get(&window).copied() else { let Some(id) = self.windows.get(&window).copied() else {
debug!("not setting popup for unknown window {window:?}"); debug!("not setting popup for unknown window {window:?}");
return; return;
@ -859,7 +758,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
.is_popup = is_popup; .is_popup = is_popup;
} }
fn set_win_title(&mut self, window: x::Window, name: WmName) { pub fn set_win_title(&mut self, window: x::Window, name: WmName) {
let Some(data) = self let Some(data) = self
.windows .windows
.get(&window) .get(&window)
@ -897,7 +796,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
} }
} }
fn set_win_class(&mut self, window: x::Window, class: String) { pub fn set_win_class(&mut self, window: x::Window, class: String) {
let Some(data) = self let Some(data) = self
.windows .windows
.get(&window) .get(&window)
@ -918,7 +817,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
} }
} }
fn set_win_hints(&mut self, window: x::Window, hints: WmHints) { pub fn set_win_hints(&mut self, window: x::Window, hints: WmHints) {
let Some(id) = self.windows.get(&window).copied() else { let Some(id) = self.windows.get(&window).copied() else {
debug!("not setting hints for unknown window {window:?}"); debug!("not setting hints for unknown window {window:?}");
return; return;
@ -927,7 +826,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
self.world.get::<&mut WindowData>(id).unwrap().attrs.group = hints.window_group; self.world.get::<&mut WindowData>(id).unwrap().attrs.group = hints.window_group;
} }
fn set_size_hints(&mut self, window: x::Window, hints: WmNormalHints) { pub fn set_size_hints(&mut self, window: x::Window, hints: WmNormalHints) {
let Some(data) = self let Some(data) = self
.windows .windows
.get(&window) .get(&window)
@ -961,7 +860,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
} }
} }
fn set_win_decorations(&mut self, window: x::Window, decorations: Decorations) { pub fn set_win_decorations(&mut self, window: x::Window, decorations: Decorations) {
if self.decoration_manager.is_none() { if self.decoration_manager.is_none() {
return; return;
}; };
@ -992,7 +891,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
} }
} }
fn set_window_serial(&mut self, window: x::Window, serial: [u32; 2]) { pub fn set_window_serial(&mut self, window: x::Window, serial: [u32; 2]) {
let Some(id) = self.windows.get(&window).copied() else { let Some(id) = self.windows.get(&window).copied() else {
warn!("Tried to set serial for unknown window {window:?}"); warn!("Tried to set serial for unknown window {window:?}");
return; return;
@ -1001,7 +900,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
self.world.insert(id, (SurfaceSerial(serial),)).unwrap(); self.world.insert(id, (SurfaceSerial(serial),)).unwrap();
} }
fn can_change_position(&self, window: x::Window) -> bool { pub fn can_change_position(&self, window: x::Window) -> bool {
let Some(win) = self let Some(win) = self
.windows .windows
.get(&window) .get(&window)
@ -1015,7 +914,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
!win.mapped || win.attrs.is_popup !win.mapped || win.attrs.is_popup
} }
fn reconfigure_window(&mut self, event: x::ConfigureNotifyEvent) { pub fn reconfigure_window(&mut self, event: x::ConfigureNotifyEvent) {
let Some((mut win, data)) = self let Some((mut win, data)) = self
.windows .windows
.get(&event.window()) .get(&event.window())
@ -1074,7 +973,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
} }
} }
fn map_window(&mut self, window: x::Window) { pub fn map_window(&mut self, window: x::Window) {
debug!("mapping {window:?}"); debug!("mapping {window:?}");
let Some(mut win) = self let Some(mut win) = self
@ -1091,7 +990,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
win.mapped = true; win.mapped = true;
} }
fn unmap_window(&mut self, window: x::Window) { pub fn unmap_window(&mut self, window: x::Window) {
let entity = self.windows.get(&window).copied(); let entity = self.windows.get(&window).copied();
{ {
@ -1119,7 +1018,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
} }
} }
fn set_fullscreen(&mut self, window: x::Window, state: super::xstate::SetState) { pub fn set_fullscreen(&mut self, window: x::Window, state: super::xstate::SetState) {
let Some(data) = self let Some(data) = self
.windows .windows
.get(&window) .get(&window)
@ -1154,7 +1053,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
} }
} }
fn set_transient_for(&mut self, window: x::Window, parent: x::Window) { pub fn set_transient_for(&mut self, window: x::Window, parent: x::Window) {
let Some(mut win) = self let Some(mut win) = self
.windows .windows
.get(&window) .get(&window)
@ -1168,7 +1067,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
win.attrs.transient_for = Some(parent); win.attrs.transient_for = Some(parent);
} }
fn activate_window(&mut self, window: x::Window) { pub fn activate_window(&mut self, window: x::Window) {
let Some(activation_state) = self.activation_state.as_ref() else { let Some(activation_state) = self.activation_state.as_ref() else {
return; return;
}; };
@ -1205,7 +1104,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
); );
} }
fn destroy_window(&mut self, window: x::Window) { pub fn destroy_window(&mut self, window: x::Window) {
if let Some(id) = self.windows.remove(&window) { if let Some(id) = self.windows.remove(&window) {
self.world.remove::<(x::Window, WindowData)>(id).unwrap(); self.world.remove::<(x::Window, WindowData)>(id).unwrap();
if self.world.entity(id).unwrap().is_empty() { if self.world.entity(id).unwrap().is_empty() {
@ -1214,7 +1113,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
} }
} }
fn set_copy_paste_source(&mut self, selection: &Rc<S>) { pub(crate) fn set_copy_paste_source(&mut self, selection: &Rc<S>) {
if let Some(d) = &mut self.clipboard_data { if let Some(d) = &mut self.clipboard_data {
let src = d let src = d
.manager .manager
@ -1237,11 +1136,11 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
} }
} }
fn new_global_scale(&mut self) -> Option<f64> { pub fn new_global_scale(&mut self) -> Option<f64> {
self.new_scale.take() self.new_scale.take()
} }
fn new_selection(&mut self) -> Option<ForeignSelection> { pub fn new_selection(&mut self) -> Option<ForeignSelection> {
self.clipboard_data.as_mut().and_then(|c| { self.clipboard_data.as_mut().and_then(|c| {
c.source.take().and_then(|s| match s { c.source.take().and_then(|s| match s {
CopyPasteData::Foreign(f) => Some(f), CopyPasteData::Foreign(f) => Some(f),

View file

@ -1,4 +1,4 @@
use super::{EarlyConnection, InnerServerState, ServerState, WindowDims}; use super::{InnerServerState, NoConnection, ServerState, WindowDims};
use crate::xstate::{SetState, WinSize, WmName}; use crate::xstate::{SetState, WinSize, WmName};
use crate::XConnection; use crate::XConnection;
use rustix::event::{poll, PollFd, PollFlags}; use rustix::event::{poll, PollFd, PollFlags};
@ -240,8 +240,7 @@ impl super::XConnection for FakeXConnection {
} }
} }
type EarlyServerState = ServerState<EarlyConnection<FakeX11Selection>>; type EarlyTestFixture = TestFixture<NoConnection<FakeX11Selection>>;
type EarlyTestFixture = TestFixture<EarlyConnection<FakeX11Selection>>;
struct TestFixture<C: XConnection> { struct TestFixture<C: XConnection> {
testwl: testwl::Server, testwl: testwl::Server,
@ -368,7 +367,7 @@ impl EarlyTestFixture {
}); });
let (fake_client, xwls_server) = UnixStream::pair().unwrap(); let (fake_client, xwls_server) = UnixStream::pair().unwrap();
let satellite = EarlyServerState::new(display.handle(), Some(client_s), xwls_server); let satellite = ServerState::new(display.handle(), Some(client_s), xwls_server);
let testwl = thread.join().unwrap(); let testwl = thread.join().unwrap();
let xwls_connection = Connection::from_socket(fake_client).unwrap(); let xwls_connection = Connection::from_socket(fake_client).unwrap();
@ -467,7 +466,7 @@ impl<C: XConnection> TestFixture<C> {
// Have satellite dispatch our requests // Have satellite dispatch our requests
self.xwls_display self.xwls_display
.dispatch_clients(self.satellite.inner_mut()) .dispatch_clients(&mut *self.satellite)
.unwrap(); .unwrap();
self.xwls_display.flush_clients().unwrap(); self.xwls_display.flush_clients().unwrap();
@ -1414,12 +1413,12 @@ fn raise_window_on_pointer_event() {
f.testwl.move_pointer_to(id2, 0.0, 0.0); f.testwl.move_pointer_to(id2, 0.0, 0.0);
f.run(); f.run();
assert_eq!(f.connection().focused_window, Some(win2)); assert_eq!(f.connection().focused_window, Some(win2));
assert_eq!(f.satellite.inner.last_hovered, Some(win2)); assert_eq!(f.satellite.last_hovered, Some(win2));
f.testwl.move_pointer_to(id1, 0.0, 0.0); f.testwl.move_pointer_to(id1, 0.0, 0.0);
f.run(); f.run();
assert_eq!(f.connection().focused_window, Some(win2)); assert_eq!(f.connection().focused_window, Some(win2));
assert_eq!(f.satellite.inner.last_hovered, Some(win1)); assert_eq!(f.satellite.last_hovered, Some(win1));
} }
#[test] #[test]
@ -1436,7 +1435,7 @@ fn override_redirect_choose_hover_window() {
f.testwl.move_pointer_to(id1, 0.0, 0.0); f.testwl.move_pointer_to(id1, 0.0, 0.0);
f.run(); f.run();
assert_eq!(f.satellite.inner.last_hovered, Some(win1)); assert_eq!(f.satellite.last_hovered, Some(win1));
let win3 = unsafe { Window::new(3) }; let win3 = unsafe { Window::new(3) };
let (buffer, surface) = comp.create_surface(); let (buffer, surface) = comp.create_surface();