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;
pub mod xstate;
use crate::server::{EarlyConnection, PendingSurfaceState, ServerState};
use crate::server::{NoConnection, PendingSurfaceState, ServerState};
use crate::xstate::{RealConnection, XState};
use log::{error, info};
use rustix::event::{poll, PollFd, PollFlags};
@ -29,7 +29,7 @@ pub trait X11Selection {
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>;
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
// 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.
// See https://github.com/rust-x-bindings/rust-xcb/issues/282 for further explanation.
let xsock_wl = Box::leak(Box::new(xsock_wl));
// Prevent creation of new Xwayland command from closing fd
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:?}"),
}
display.dispatch_clients(server_state.inner_mut()).unwrap();
display.dispatch_clients(&mut *server_state).unwrap();
server_state.run();
display.flush_clients().unwrap();
}
@ -207,7 +208,7 @@ pub fn main(mut data: impl RunData) -> Option<()> {
loop {
xstate.handle_events(&mut server_state);
display.dispatch_clients(server_state.inner_mut()).unwrap();
display.dispatch_clients(&mut *server_state).unwrap();
server_state.run();
display.flush_clients().unwrap();

View file

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

View file

@ -18,6 +18,7 @@ use smithay_client_toolkit::data_device_manager::{
};
use std::collections::{HashMap, HashSet};
use std::io::Read;
use std::ops::{Deref, DerefMut};
use std::os::fd::{AsFd, BorrowedFd};
use std::os::unix::net::UnixStream;
use std::rc::{Rc, Weak};
@ -393,10 +394,10 @@ struct GlobalOutputOffset {
/// The state of the X11 connection before XState has been fully initialized.
/// 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>,
}
impl<S: X11Selection> XConnection for EarlyConnection<S> {
impl<S: X11Selection> XConnection for NoConnection<S> {
type X11Selection = S;
fn focus_window(&mut self, _: x::Window, _: Option<String>) {
debug!("could not focus window without XWayland initialized");
@ -423,6 +424,17 @@ pub struct ServerState<C: XConnection> {
inner: InnerServerState<C::X11Selection>,
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> {
dh: DisplayHandle,
@ -451,7 +463,7 @@ pub struct InnerServerState<S: X11Selection> {
new_scale: Option<f64>,
}
impl<S: X11Selection> ServerState<EarlyConnection<S>> {
impl<S: X11Selection> ServerState<NoConnection<S>> {
pub fn new(
mut dh: DisplayHandle,
server_connection: Option<UnixStream>,
@ -548,7 +560,7 @@ impl<S: X11Selection> ServerState<EarlyConnection<S>> {
};
Self {
inner,
connection: EarlyConnection {
connection: NoConnection {
_p: std::marker::PhantomData,
},
}
@ -566,103 +578,18 @@ impl<S: X11Selection> ServerState<EarlyConnection<S>> {
}
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) {
if let Some(r) = self.inner.queue.prepare_read() {
if let Some(r) = self.queue.prepare_read() {
let fd = r.connection_fd();
let pollfd = PollFd::new(&fd, PollFlags::IN);
if poll(&mut [pollfd], 0).unwrap() > 0 {
let _ = r.read();
}
}
self.inner
let state = self.deref_mut();
state
.queue
.dispatch_pending(&mut self.inner.world)
.dispatch_pending(&mut state.world)
.expect("Failed dispatching client side Wayland events");
self.handle_clientside_events();
}
@ -670,42 +597,43 @@ impl<C: XConnection> ServerState<C> {
pub fn handle_clientside_events(&mut self) {
self.handle_new_globals();
for (target, event) in self.inner.world.read_events() {
if !self.inner.world.contains(target) {
for (target, event) in self.world.read_events() {
if !self.world.contains(target) {
warn!("could not handle clientside event: stale object");
continue;
}
event.handle(target, self);
}
if self.inner.global_offset_updated {
if self.inner.global_output_offset.x.owner.is_none()
|| self.inner.global_output_offset.y.owner.is_none()
if self.global_offset_updated {
if self.global_output_offset.x.owner.is_none()
|| self.global_output_offset.y.owner.is_none()
{
self.calc_global_output_offset();
}
debug!(
"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(
e,
&self.inner.global_output_offset,
&self.inner.world,
&state.global_output_offset,
&state.world,
&mut self.connection,
);
}
self.inner.global_offset_updated = false;
self.global_offset_updated = false;
}
if !self.inner.updated_outputs.is_empty() {
for output in self.inner.updated_outputs.drain(..) {
let output_scale = self.inner.world.get::<&OutputScaleFactor>(output).unwrap();
if !self.updated_outputs.is_empty() {
let state = self.deref_mut();
for output in state.updated_outputs.drain(..) {
let output_scale = state.world.get::<&OutputScaleFactor>(output).unwrap();
if matches!(*output_scale, OutputScaleFactor::Output(..)) {
let mut surface_query = self
.inner
let mut surface_query = state
.world
.query::<(&OnOutput, &mut SurfaceScaleFactor)>()
.with::<(&WindowData, &WlSurface)>();
@ -720,7 +648,7 @@ impl<C: XConnection> ServerState<C> {
drop(surface_query);
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 scale;
let mut outputs = self
.inner
.world
.query_mut::<&OutputScaleFactor>()
.into_iter();
let mut outputs = self.world.query_mut::<&OutputScaleFactor>().into_iter();
let (_, output_scale) = outputs.next().unwrap();
scale = output_scale.get();
@ -749,70 +673,45 @@ impl<C: XConnection> ServerState<C> {
}
debug!("Using new scale {scale}");
self.inner.new_scale = Some(scale);
self.new_scale = Some(scale);
}
{
if let Some(FocusData {
window,
output_name,
}) = self.inner.to_focus.take()
}) = self.to_focus.take()
{
debug!("focusing window {window:?}");
self.connection.focus_window(window, output_name);
self.inner.last_focused_toplevel = Some(window);
} else if self.inner.unfocus {
self.last_focused_toplevel = Some(window);
} else if self.unfocus {
self.connection.focus_window(x::WINDOW_NONE, None);
}
self.inner.unfocus = false;
self.unfocus = false;
}
self.handle_clipboard_events();
self.handle_activations();
self.inner
.queue
self.queue
.flush()
.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) {
debug!("sending close request to {window:?}");
self.connection.close_window(window);
if self.inner.last_focused_toplevel == Some(window) {
self.inner.last_focused_toplevel.take();
if self.last_focused_toplevel == Some(window) {
self.last_focused_toplevel.take();
}
if self.inner.last_hovered == Some(window) {
self.inner.last_hovered.take();
if self.last_hovered == Some(window) {
self.last_hovered.take();
}
}
}
impl<S: X11Selection + 'static> InnerServerState<S> {
fn clientside_fd(&self) -> BorrowedFd<'_> {
pub fn clientside_fd(&self) -> BorrowedFd<'_> {
self.queue.as_fd()
}
@ -821,7 +720,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
handle_globals::<S>(&self.dh, globals.iter());
}
fn new_window(
pub fn new_window(
&mut self,
window: x::Window,
override_redirect: bool,
@ -846,7 +745,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
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 {
debug!("not setting popup for unknown window {window:?}");
return;
@ -859,7 +758,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
.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
.windows
.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
.windows
.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 {
debug!("not setting hints for unknown window {window:?}");
return;
@ -927,7 +826,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
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
.windows
.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() {
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 {
warn!("Tried to set serial for unknown window {window:?}");
return;
@ -1001,7 +900,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
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
.windows
.get(&window)
@ -1015,7 +914,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
!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
.windows
.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:?}");
let Some(mut win) = self
@ -1091,7 +990,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
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();
{
@ -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
.windows
.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
.windows
.get(&window)
@ -1168,7 +1067,7 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
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 {
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) {
self.world.remove::<(x::Window, WindowData)>(id).unwrap();
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 {
let src = d
.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()
}
fn new_selection(&mut self) -> Option<ForeignSelection> {
pub fn new_selection(&mut self) -> Option<ForeignSelection> {
self.clipboard_data.as_mut().and_then(|c| {
c.source.take().and_then(|s| match s {
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::XConnection;
use rustix::event::{poll, PollFd, PollFlags};
@ -240,8 +240,7 @@ impl super::XConnection for FakeXConnection {
}
}
type EarlyServerState = ServerState<EarlyConnection<FakeX11Selection>>;
type EarlyTestFixture = TestFixture<EarlyConnection<FakeX11Selection>>;
type EarlyTestFixture = TestFixture<NoConnection<FakeX11Selection>>;
struct TestFixture<C: XConnection> {
testwl: testwl::Server,
@ -368,7 +367,7 @@ impl EarlyTestFixture {
});
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 xwls_connection = Connection::from_socket(fake_client).unwrap();
@ -467,7 +466,7 @@ impl<C: XConnection> TestFixture<C> {
// Have satellite dispatch our requests
self.xwls_display
.dispatch_clients(self.satellite.inner_mut())
.dispatch_clients(&mut *self.satellite)
.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.run();
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.run();
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]
@ -1436,7 +1435,7 @@ fn override_redirect_choose_hover_window() {
f.testwl.move_pointer_to(id1, 0.0, 0.0);
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 (buffer, surface) = comp.create_surface();