Commit a772647a949f
tarball17 files changed+233-183
@@ -23,7 +23,7 @@ struct Context {
2323
2424
impl XdgActivationHandler for State {2525
fn activation_state(&mut self) -> &mut XdgActivationState {26
- &mut self.activation_state26
+ &mut self.protocols.activation_state2727
}2828
2929
fn token_created(&mut self, _token: XdgActivationToken, data: XdgActivationTokenData) -> bool {@@ -86,7 +86,7 @@ impl State {
8686
tag,8787
may_focus: true,8888
});89
- let (token, _) = self.activation_state.create_external_token(data);89
+ let (token, _) = self.protocols.activation_state.create_external_token(data);9090
token.to_string()9191
}9292
}@@ -69,7 +69,7 @@ impl ImageCaptureSourceHandler for State {
6969
7070
impl OutputCaptureSourceHandler for State {7171
fn output_capture_source_state(&mut self) -> &mut OutputCaptureSourceState {72
- &mut self.output_capture_source_state72
+ &mut self.protocols.output_capture_source_state7373
}7474
7575
fn output_source_created(&mut self, source: ImageCaptureSource, output: &Output) {@@ -79,7 +79,7 @@ impl OutputCaptureSourceHandler for State {
7979
8080
impl ToplevelCaptureSourceHandler for State {8181
fn toplevel_capture_source_state(&mut self) -> &mut ToplevelCaptureSourceState {82
- &mut self.toplevel_capture_source_state82
+ &mut self.protocols.toplevel_capture_source_state8383
}8484
8585
fn toplevel_source_created(@@ -95,7 +95,7 @@ impl ToplevelCaptureSourceHandler for State {
9595
9696
impl ImageCopyCaptureHandler for State {9797
fn image_copy_capture_state(&mut self) -> &mut ImageCopyCaptureState {98
- &mut self.image_copy_capture_state98
+ &mut self.protocols.image_copy_capture_state9999
}100100
101101
fn capture_constraints(&mut self, source: &ImageCaptureSource) -> Option<BufferConstraints> {@@ -284,7 +284,7 @@ impl State {
284284
&self.anim,285285
&mut self.renderer,286286
now,287
- &self.config.decoration,287
+ &self.settings.config.decoration,288288
&mut self.borders,289289
Some(output),290290
self.xwayland.as_ref().map_or(&[], |x| &x.unmanaged),@@ -53,7 +53,7 @@ impl State {
5353
let output = self.layout.active_output();5454
let focused = self.layout.focused();5555
let inverted = std::mem::take(&mut self.move_inverted);56
- let merge = (self.config.general.move_mode == MoveMode::Merge) != inverted;56
+ let merge = (self.settings.config.general.move_mode == MoveMode::Merge) != inverted;5757
let on_focused = |state: &mut Self, f: fn(&mut monolith_layout::Layout, WindowId)| {5858
if let Some(w) = focused {5959
f(&mut state.layout, w);@@ -72,7 +72,7 @@ impl State {
7272
}7373
}7474
}75
- Command::Quit => self.signal.stop(),75
+ Command::Quit => self.core.signal.stop(),7676
Command::Reload => self.reload()?,7777
Command::Focus { dir: d } => {7878
self.layout.focus_dir(dir(d));@@ -171,7 +171,7 @@ impl State {
171171
let (program, args) = argv.split_first().ok_or("nothing to spawn")?;172172
let mut cmd = std::process::Command::new(program);173173
cmd.args(args)174
- .env("WAYLAND_DISPLAY", &self.socket_name)174
+ .env("WAYLAND_DISPLAY", &self.core.socket_name)175175
.stdin(Stdio::null());176176
if let Some(sock) = &self.ipc.path {177177
cmd.env("MONOLITH_SOCKET", sock);@@ -197,12 +197,12 @@ impl State {
197197
/// Swaps in a freshly parsed config. A broken file leaves the running198198
/// config untouched.199199
pub fn reload(&mut self) -> Result<(), String> {200
- let config = Config::load(self.config_path.as_deref()).map_err(|e| e.to_string())?;201
- let keyboard_changed = config.keyboard != self.config.keyboard;202
- self.binds = Binds::new(&config);200
+ let config = Config::load(self.settings.path.as_deref()).map_err(|e| e.to_string())?;201
+ let keyboard_changed = config.keyboard != self.settings.config.keyboard;202
+ self.settings.binds = Binds::new(&config);203203
self.layout.gaps = crate::state::gaps(&config);204204
self.anim.settings = config.animation.clone();205
- self.config = config;205
+ self.settings.config = config;206206
if keyboard_changed {207207
self.reconfigure_keyboard();208208
}@@ -193,7 +193,10 @@ pub fn init(
193193
.map(|d| d.name().to_string_lossy().to_lowercase().contains("nvidia"))194194
.unwrap_or(false);195195
if supports_syncobj_eventfd(&fd) {196
- state.syncobj = Some(DrmSyncobjState::new::<State>(&state.display, fd.clone()));196
+ state.syncobj = Some(DrmSyncobjState::new::<State>(197
+ &state.core.display,198
+ fd.clone(),199
+ ));197200
} else {198201
tracing::info!("no syncobj eventfd support, clients stay on implicit sync");199202
}@@ -335,7 +338,7 @@ fn connect(state: &mut State, connector: connector::Info, crtc: crtc::Handle) {
335338
renderer,336339
layout,337340
space,338
- display,341
+ core,339342
..340343
} = state341344
else {@@ -365,7 +368,7 @@ fn connect(state: &mut State, connector: connector::Info, crtc: crtc::Handle) {
365368
Some(position),366369
);367370
output.set_preferred(wl_mode);368
- output.create_global::<State>(display);371
+ output.create_global::<State>(&core.display);369372
let mut planes = drm.manager.device().planes(&crtc).ok();370373
if drm.nvidia371374
&& let Some(p) = planes.as_mut()@@ -590,9 +593,9 @@ fn render_surface(state: &mut State, crtc: crtc::Handle, target: u64) -> bool {
590593
windows,591594
anim,592595
borders,593
- config,596
+ settings,594597
space,595
- start,598
+ core,596599
cursor,597600
cursor_status,598601
pointer_pos,@@ -615,7 +618,7 @@ fn render_surface(state: &mut State, crtc: crtc::Handle, target: u64) -> bool {
615618
}616619
surface.cursor_redraw = false;617620
let want_vrr = surface.vrr_capable618
- && match config.output.vrr {621
+ && match settings.config.output.vrr {619622
Vrr::Off => false,620623
Vrr::On => true,621624
Vrr::Fullscreen => layout.arrange(surface.id).fullscreen.is_some(),@@ -656,7 +659,7 @@ fn render_surface(state: &mut State, crtc: crtc::Handle, target: u64) -> bool {
656659
anim,657660
renderer,658661
now,659
- &config.decoration,662
+ &settings.config.decoration,660663
borders,661664
Some(&surface.output),662665
xwayland.as_ref().map_or(&[], |x| &x.unmanaged),@@ -706,7 +709,7 @@ fn render_surface(state: &mut State, crtc: crtc::Handle, target: u64) -> bool {
706709
surface.target_ns = None;707710
}708711
surface.redraw = animating;709
- let elapsed = start.elapsed();712
+ let elapsed = core.start.elapsed();710713
let output = surface.output.clone();711714
if lock.active() {712715
crate::lock::send_frames(lock, &output, elapsed);@@ -0,0 +1,107 @@
1
+//! The Wayland globals monolith advertises. Most are only touched by their2
+//! own handler impl, the rest publish compositor state to clients.3
+4
+use crate::state::State;5
+use monolith_protocols::toplevel::ForeignToplevelState;6
+use monolith_protocols::workspace::WorkspaceState;7
+use monolith_render_vk::VulkanRenderer;8
+use smithay::backend::renderer::ImportDma;9
+use smithay::reexports::calloop::LoopHandle;10
+use smithay::reexports::wayland_server::DisplayHandle;11
+use smithay::wayland::compositor::CompositorState;12
+use smithay::wayland::cursor_shape::CursorShapeManagerState;13
+use smithay::wayland::dmabuf::{DmabufGlobal, DmabufState};14
+use smithay::wayland::foreign_toplevel_list::ForeignToplevelListState;15
+use smithay::wayland::idle_inhibit::IdleInhibitManagerState;16
+use smithay::wayland::idle_notify::IdleNotifierState;17
+use smithay::wayland::image_capture_source::{18
+ ImageCaptureSourceState, OutputCaptureSourceState, ToplevelCaptureSourceState,19
+};20
+use smithay::wayland::image_copy_capture::ImageCopyCaptureState;21
+use smithay::wayland::output::OutputManagerState;22
+use smithay::wayland::selection::data_device::DataDeviceState;23
+use smithay::wayland::selection::ext_data_control::DataControlState as ExtDataControlState;24
+use smithay::wayland::selection::primary_selection::PrimarySelectionState;25
+use smithay::wayland::selection::wlr_data_control::DataControlState as WlrDataControlState;26
+use smithay::wayland::session_lock::SessionLockManagerState;27
+use smithay::wayland::shell::wlr_layer::WlrLayerShellState;28
+use smithay::wayland::shell::xdg::XdgShellState;29
+use smithay::wayland::shell::xdg::decoration::XdgDecorationState;30
+use smithay::wayland::shm::ShmState;31
+use smithay::wayland::xdg_activation::XdgActivationState;32
+use smithay::wayland::xwayland_shell::XWaylandShellState;33
+34
+pub struct Protocols {35
+ pub compositor_state: CompositorState,36
+ pub xdg_shell_state: XdgShellState,37
+ pub layer_shell_state: WlrLayerShellState,38
+ pub output_capture_source_state: OutputCaptureSourceState,39
+ pub toplevel_capture_source_state: ToplevelCaptureSourceState,40
+ pub image_copy_capture_state: ImageCopyCaptureState,41
+ pub activation_state: XdgActivationState,42
+ pub primary_selection_state: PrimarySelectionState,43
+ pub wlr_data_control_state: WlrDataControlState,44
+ pub ext_data_control_state: ExtDataControlState,45
+ pub session_lock_state: SessionLockManagerState,46
+ pub idle_notifier: IdleNotifierState<State>,47
+ pub shm_state: ShmState,48
+ pub dmabuf_state: DmabufState,49
+ pub data_device_state: DataDeviceState,50
+ pub xwayland_shell_state: XWaylandShellState,51
+ pub workspaces: WorkspaceState,52
+ pub foreign_toplevels: ForeignToplevelState,53
+ pub toplevel_list: ForeignToplevelListState,54
+ _image_capture_source: ImageCaptureSourceState,55
+ _idle_inhibit: IdleInhibitManagerState,56
+ _xdg_decoration: XdgDecorationState,57
+ _dmabuf_global: DmabufGlobal,58
+ _output_manager: OutputManagerState,59
+ _cursor_shape: CursorShapeManagerState,60
+}61
+62
+impl Protocols {63
+ pub fn new(64
+ dh: &DisplayHandle,65
+ handle: LoopHandle<'static, State>,66
+ renderer: &VulkanRenderer,67
+ ) -> Self {68
+ let mut dmabuf_state = DmabufState::new();69
+ let dmabuf_global = dmabuf_state.create_global::<State>(dh, renderer.dmabuf_formats());70
+ let primary_selection_state = PrimarySelectionState::new::<State>(dh);71
+ Self {72
+ compositor_state: CompositorState::new::<State>(dh),73
+ xdg_shell_state: XdgShellState::new::<State>(dh),74
+ layer_shell_state: WlrLayerShellState::new::<State>(dh),75
+ output_capture_source_state: OutputCaptureSourceState::new::<State>(dh),76
+ toplevel_capture_source_state: ToplevelCaptureSourceState::new::<State>(dh),77
+ image_copy_capture_state: ImageCopyCaptureState::new::<State>(dh),78
+ activation_state: XdgActivationState::new::<State>(dh),79
+ wlr_data_control_state: WlrDataControlState::new::<State, _>(80
+ dh,81
+ Some(&primary_selection_state),82
+ |_| true,83
+ ),84
+ ext_data_control_state: ExtDataControlState::new::<State, _>(85
+ dh,86
+ Some(&primary_selection_state),87
+ |_| true,88
+ ),89
+ primary_selection_state,90
+ session_lock_state: SessionLockManagerState::new::<State, _>(dh, |_| true),91
+ idle_notifier: IdleNotifierState::new(dh, handle),92
+ shm_state: ShmState::new::<State>(dh, vec![]),93
+ dmabuf_state,94
+ data_device_state: DataDeviceState::new::<State>(dh),95
+ xwayland_shell_state: XWaylandShellState::new::<State>(dh),96
+ workspaces: WorkspaceState::new::<State>(dh),97
+ foreign_toplevels: ForeignToplevelState::new::<State>(dh),98
+ toplevel_list: ForeignToplevelListState::new::<State>(dh),99
+ _image_capture_source: ImageCaptureSourceState::new(),100
+ _idle_inhibit: IdleInhibitManagerState::new::<State>(dh),101
+ _xdg_decoration: XdgDecorationState::new::<State>(dh),102
+ _dmabuf_global: dmabuf_global,103
+ _output_manager: OutputManagerState::new_with_xdg_output::<State>(dh),104
+ _cursor_shape: CursorShapeManagerState::new::<State>(dh),105
+ }106
+ }107
+}@@ -41,7 +41,7 @@ use smithay::wayland::shm::{ShmHandler, ShmState};
4141
4242
impl CompositorHandler for State {4343
fn compositor_state(&mut self) -> &mut CompositorState {44
- &mut self.compositor_state44
+ &mut self.protocols.compositor_state4545
}4646
4747
fn new_surface(&mut self, surface: &WlSurface) {@@ -116,13 +116,13 @@ impl BufferHandler for State {
116116
117117
impl ShmHandler for State {118118
fn shm_state(&self) -> &ShmState {119
- &self.shm_state119
+ &self.protocols.shm_state120120
}121121
}122122
123123
impl DmabufHandler for State {124124
fn dmabuf_state(&mut self) -> &mut DmabufState {125
- &mut self.dmabuf_state125
+ &mut self.protocols.dmabuf_state126126
}127127
128128
fn dmabuf_imported(@@ -137,7 +137,7 @@ impl DmabufHandler for State {
137137
138138
impl XdgShellHandler for State {139139
fn xdg_shell_state(&mut self) -> &mut XdgShellState {140
- &mut self.xdg_shell_state140
+ &mut self.protocols.xdg_shell_state141141
}142142
143143
fn new_toplevel(&mut self, surface: ToplevelSurface) {@@ -194,9 +194,9 @@ impl SeatHandler for State {
194194
fn focus_changed(&mut self, seat: &Seat<Self>, focused: Option<&crate::focus::Focus>) {195195
let client = focused196196
.and_then(|f| f.wl_surface())197
- .and_then(|s| self.display.get_client(s.id()).ok());198
- set_data_device_focus(&self.display, seat, client.clone());199
- set_primary_focus(&self.display, seat, client);197
+ .and_then(|s| self.core.display.get_client(s.id()).ok());198
+ set_data_device_focus(&self.core.display, seat, client.clone());199
+ set_primary_focus(&self.core.display, seat, client);200200
}201201
}202202
@@ -206,13 +206,13 @@ impl SelectionHandler for State {
206206
207207
impl DataDeviceHandler for State {208208
fn data_device_state(&mut self) -> &mut DataDeviceState {209
- &mut self.data_device_state209
+ &mut self.protocols.data_device_state210210
}211211
}212212
213213
impl PrimarySelectionHandler for State {214214
fn primary_selection_state(&mut self) -> &mut PrimarySelectionState {215
- &mut self.primary_selection_state215
+ &mut self.protocols.primary_selection_state216216
}217217
}218218
@@ -220,7 +220,7 @@ impl smithay::wayland::selection::wlr_data_control::DataControlHandler for State
220220
fn data_control_state(221221
&mut self,222222
) -> &mut smithay::wayland::selection::wlr_data_control::DataControlState {223
- &mut self.wlr_data_control_state223
+ &mut self.protocols.wlr_data_control_state224224
}225225
}226226
@@ -228,7 +228,7 @@ impl smithay::wayland::selection::ext_data_control::DataControlHandler for State
228228
fn data_control_state(229229
&mut self,230230
) -> &mut smithay::wayland::selection::ext_data_control::DataControlState {231
- &mut self.ext_data_control_state231
+ &mut self.protocols.ext_data_control_state232232
}233233
}234234
@@ -310,8 +310,8 @@ fn hold_until_readable(state: &mut State, surface: &WlSurface) {
310310
if let Some(point) = acquire311311
&& let Ok((blocker, source)) = point.generate_blocker()312312
{313
- let inserted = state.handle.insert_source(source, move |_, _, state| {314
- let dh = state.display.clone();313
+ let inserted = state.core.handle.insert_source(source, move |_, _, state| {314
+ let dh = state.core.display.clone();315315
state316316
.client_compositor_state(&client)317317
.blocker_cleared(state, &dh);@@ -323,8 +323,8 @@ fn hold_until_readable(state: &mut State, surface: &WlSurface) {
323323
return;324324
}325325
if let Ok((blocker, source)) = dmabuf.generate_blocker(Interest::READ) {326
- let inserted = state.handle.insert_source(source, move |_, _, state| {327
- let dh = state.display.clone();326
+ let inserted = state.core.handle.insert_source(source, move |_, _, state| {327
+ let dh = state.core.display.clone();328328
state329329
.client_compositor_state(&client)330330
.blocker_cleared(state, &dh);@@ -371,7 +371,7 @@ impl State {
371371
372372
impl WorkspaceHandler for State {373373
fn workspace_state(&mut self) -> &mut WorkspaceState {374
- &mut self.workspaces374
+ &mut self.protocols.workspaces375375
}376376
377377
fn workspace_actions(&mut self, actions: Vec<Action>) {@@ -10,7 +10,7 @@ use smithay::wayland::idle_notify::{IdleNotifierHandler, IdleNotifierState};
1010
1111
impl IdleNotifierHandler for State {1212
fn idle_notifier_state(&mut self) -> &mut IdleNotifierState<Self> {13
- &mut self.idle_notifier13
+ &mut self.protocols.idle_notifier1414
}1515
}1616
@@ -29,7 +29,7 @@ impl IdleInhibitHandler for State {
2929
impl State {3030
pub fn activity(&mut self) {3131
let seat = self.seat.clone();32
- self.idle_notifier.notify_activity(&seat);32
+ self.protocols.idle_notifier.notify_activity(&seat);3333
}3434
3535
/// An inhibitor only counts while its surface is on screen, as the@@ -48,7 +48,7 @@ impl State {
4848
});4949
if shown != self.inhibited {5050
self.inhibited = shown;51
- self.idle_notifier.set_is_inhibited(shown);51
+ self.protocols.idle_notifier.set_is_inhibited(shown);5252
}5353
}5454
}@@ -124,7 +124,7 @@ impl State {
124124
}125125
}126126
waiters.done.store(true, Ordering::Release);127
- let dh = self.display.clone();127
+ let dh = self.core.display.clone();128128
for client in waiters.clients {129129
self.client_compositor_state(&client)130130
.blocker_cleared(self, &dh);@@ -103,7 +103,7 @@ impl State {
103103
if state.lock.active() {104104
return FilterResult::Forward;105105
}106
- match state.binds.find(mods, &handle.raw_syms()) {106
+ match state.settings.binds.find(mods, &handle.raw_syms()) {107107
Some(cmd) => {108108
tracing::debug!(?cmd, "bind");109109
state.suppressed.push(code);@@ -182,7 +182,7 @@ fn start_drag(state: &mut State, button: u32) -> bool {
182182
.seat183183
.get_keyboard()184184
.map(|k| k.modifier_state())185
- .is_some_and(|m| match state.config.general.mod_key {185
+ .is_some_and(|m| match state.settings.config.general.mod_key {186186
Modifier::Super => m.logo,187187
Modifier::Alt => m.alt,188188
Modifier::Ctrl => m.ctrl,@@ -28,6 +28,7 @@ impl Drop for Server {
2828
2929
pub fn init(event_loop: &EventLoop<'static, State>, state: &mut State) -> std::io::Result<()> {3030
let Some(path) = state31
+ .core3132
.socket_name3233
.to_str()3334
.and_then(monolith_ipc::socket_path_for)@@ -22,7 +22,7 @@ use std::time::Duration;
2222
2323
impl WlrLayerShellHandler for State {2424
fn shell_state(&mut self) -> &mut WlrLayerShellState {25
- &mut self.layer_shell_state25
+ &mut self.protocols.layer_shell_state2626
}2727
2828
fn new_layer_surface(@@ -50,7 +50,7 @@ impl Lock {
5050
5151
impl SessionLockHandler for State {5252
fn lock_state(&mut self) -> &mut SessionLockManagerState {53
- &mut self.session_lock_state53
+ &mut self.protocols.session_lock_state5454
}5555
5656
fn lock(&mut self, confirmation: SessionLocker) {@@ -5,6 +5,7 @@ mod commands;
55
mod cursor;66
mod drm;77
mod focus;8
+mod globals;89
mod handlers;910
mod idle;1011
mod import;@@ -157,7 +158,7 @@ fn export_session(state: &State) {
157158
.arg("--systemd")158159
.arg(format!(159160
"WAYLAND_DISPLAY={}",160
- state.socket_name.to_string_lossy()161
+ state.core.socket_name.to_string_lossy()161162
))162163
.arg("XDG_CURRENT_DESKTOP=monolith")163164
.arg("XDG_SESSION_TYPE=wayland")@@ -203,12 +204,12 @@ fn run(
203204
}204205
ipc::init(&event_loop, &mut state)?;205206
xwayland::init(&mut state);206
- tracing::info!(socket = ?state.socket_name, device = state.renderer.device_name(), "monolith running");207
+ tracing::info!(socket = ?state.core.socket_name, device = state.renderer.device_name(), "monolith running");207208
208209
if gpu.is_some() {209210
export_session(&state);210211
}211
- let mut startup = state.config.startup.clone();212
+ let mut startup = state.settings.config.startup.clone();212213
if !program.is_empty() {213214
startup.push(program.to_vec());214215
}@@ -117,7 +117,7 @@ pub fn init(
117117
serial_number: "0".into(),118118
},119119
);120
- let _global = output.create_global::<State>(&state.display);120
+ let _global = output.create_global::<State>(&state.core.display);121121
let mode = Mode {122122
size: DEFAULT_SIZE.into(),123123
refresh: 60_000,@@ -172,12 +172,12 @@ pub fn render(state: &mut State) {
172172
renderer,173173
space,174174
needs_redraw,175
- start,175
+ core,176176
layout,177177
windows,178178
anim,179179
borders,180
- config,180
+ settings,181181
output_id,182182
lock,183183
captures,@@ -234,7 +234,7 @@ pub fn render(state: &mut State) {
234234
anim,235235
renderer,236236
now,237
- &config.decoration,237
+ &settings.config.decoration,238238
borders,239239
Some(&host.output),240240
xwayland.as_ref().map_or(&[], |x| &x.unmanaged),@@ -259,7 +259,7 @@ pub fn render(state: &mut State) {
259259
*needs_redraw = anim.active(now);260260
anim.prune(now);261261
lock.shown(&host.output);262
- let elapsed = start.elapsed();262
+ let elapsed = core.start.elapsed();263263
crate::lock::send_frames(lock, &host.output, elapsed);264264
for window in space.elements().filter(|_| !lock.active()) {265265
window.send_frame(&host.output, elapsed, Some(Duration::ZERO), |_, _| {@@ -430,7 +430,7 @@ impl Dispatch<xdg_toplevel::XdgToplevel, ()> for State {
430430
state.resize_output(size);431431
}432432
}433
- xdg_toplevel::Event::Close => state.signal.stop(),433
+ xdg_toplevel::Event::Close => state.core.signal.stop(),434434
_ => {}435435
}436436
}@@ -1,13 +1,13 @@
11
use crate::anim::{Animator, Ghost};22
use crate::commands::Binds;33
use crate::focus::Focus;4
+use crate::globals::Protocols;45
use crate::nested::Host;56
use monolith_config::Config;67
use monolith_layout::{Layout, OutputId, Rect, WindowId};7
-use monolith_protocols::workspace::{Group, Snapshot, Workspace, WorkspaceState};8
+use monolith_protocols::workspace::{Group, Snapshot, Workspace};89
use monolith_render_vk::VulkanRenderer;910
use monolith_render_vk::VulkanTexture;10
-use smithay::backend::renderer::ImportDma;1111
use smithay::backend::renderer::Renderer;1212
use smithay::backend::renderer::utils::{import_surface_tree, with_renderer_surface_state};1313
use smithay::desktop::utils::under_from_surface_tree;@@ -24,28 +24,11 @@ use smithay::reexports::wayland_server::backend::{ClientData, ClientId, Disconne
2424
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;2525
use smithay::reexports::wayland_server::{Display, DisplayHandle, Resource};2626
use smithay::utils::{Clock, Logical, Monotonic, Point, Rectangle, SERIAL_COUNTER, Size};27
-use smithay::wayland::compositor::{CompositorClientState, CompositorState, with_states};28
-use smithay::wayland::dmabuf::{DmabufGlobal, DmabufState};29
-use smithay::wayland::idle_inhibit::IdleInhibitManagerState;30
-use smithay::wayland::idle_notify::IdleNotifierState;31
-use smithay::wayland::image_capture_source::{32
- ImageCaptureSourceState, OutputCaptureSourceState, ToplevelCaptureSourceState,33
-};34
-use smithay::wayland::image_copy_capture::ImageCopyCaptureState;35
-use smithay::wayland::output::OutputManagerState;27
+use smithay::wayland::compositor::{CompositorClientState, with_states};3628
use smithay::wayland::seat::WaylandFocus;37
-use smithay::wayland::selection::data_device::DataDeviceState;38
-use smithay::wayland::selection::ext_data_control::DataControlState as ExtDataControlState;39
-use smithay::wayland::selection::primary_selection::PrimarySelectionState;40
-use smithay::wayland::selection::wlr_data_control::DataControlState as WlrDataControlState;41
-use smithay::wayland::session_lock::SessionLockManagerState;42
-use smithay::wayland::shell::wlr_layer::{Layer, WlrLayerShellState};43
-use smithay::wayland::shell::xdg::decoration::XdgDecorationState;44
-use smithay::wayland::shell::xdg::{XdgShellState, XdgToplevelSurfaceData};45
-use smithay::wayland::shm::ShmState;29
+use smithay::wayland::shell::wlr_layer::Layer;30
+use smithay::wayland::shell::xdg::XdgToplevelSurfaceData;4631
use smithay::wayland::socket::ListeningSocketSource;47
-use smithay::wayland::xdg_activation::XdgActivationState;48
-use smithay::wayland::xwayland_shell::XWaylandShellState;4932
use std::collections::{HashMap, HashSet};5033
use std::ffi::OsString;5134
use std::path::PathBuf;@@ -53,10 +36,9 @@ use std::sync::Arc;
5336
use std::time::{Duration, Instant};5437
5538
pub struct State {56
- pub start: Instant,57
- pub socket_name: OsString,58
- pub display: DisplayHandle,59
- pub signal: LoopSignal,39
+ pub core: Core,40
+ pub settings: Settings,41
+ pub protocols: Protocols,6042
pub renderer: VulkanRenderer,6143
pub space: Space<Window>,6244
pub popups: PopupManager,@@ -75,9 +57,6 @@ pub struct State {
7557
/// title, which clients set after creating the toplevel.7658
pub unmapped: Vec<Window>,7759
pub output_id: Option<OutputId>,78
- pub config: Config,79
- pub config_path: Option<PathBuf>,80
- pub binds: Binds,8160
pub suppressed: Vec<Keycode>,8261
pub move_inverted: bool,8362
pub drag: Option<crate::input::Drag>,@@ -85,9 +64,6 @@ pub struct State {
8564
pub pointer_pos: Point<f64, Logical>,8665
pub ipc: crate::ipc::Server,8766
pub launches: crate::launch::Launches,88
- pub workspaces: WorkspaceState,89
- pub foreign_toplevels: monolith_protocols::toplevel::ForeignToplevelState,90
- pub toplevel_list: smithay::wayland::foreign_toplevel_list::ForeignToplevelListState,9167
pub list_handles: crate::toplevels::ListHandles,9268
pub anim: Animator,9369
pub borders: crate::scene::Borders,@@ -100,7 +76,6 @@ pub struct State {
10076
/// A layer surface given the keyboard by a click, like a launcher.10177
pub layer_focus: Option<WlSurface>,10278
pub xwayland: Option<crate::xwayland::Xwayland>,103
- pub xwayland_shell_state: XWaylandShellState,10479
pub captures: crate::capture::Captures,10580
pub imports: crate::import::Imports,10681
/// The render node clients get dmabufs for, known on bare metal.@@ -108,33 +83,26 @@ pub struct State {
10883
pub lock: crate::lock::Lock,10984
pub inhibitors: HashSet<WlSurface>,11085
pub inhibited: bool,111
- pub handle: LoopHandle<'static, State>,112
-113
- pub compositor_state: CompositorState,114
- pub xdg_shell_state: XdgShellState,115
- pub layer_shell_state: WlrLayerShellState,116
- pub _image_capture_source_state: ImageCaptureSourceState,117
- pub output_capture_source_state: OutputCaptureSourceState,118
- pub toplevel_capture_source_state: ToplevelCaptureSourceState,119
- pub image_copy_capture_state: ImageCopyCaptureState,120
- pub activation_state: XdgActivationState,121
- pub primary_selection_state: PrimarySelectionState,122
- pub wlr_data_control_state: WlrDataControlState,123
- pub ext_data_control_state: ExtDataControlState,124
- pub session_lock_state: SessionLockManagerState,125
- pub idle_notifier: IdleNotifierState<State>,126
- pub _idle_inhibit: IdleInhibitManagerState,127
- pub _xdg_decoration_state: XdgDecorationState,128
- pub shm_state: ShmState,129
- pub dmabuf_state: DmabufState,130
- pub _dmabuf_global: DmabufGlobal,131
- pub _output_manager_state: OutputManagerState,13286
pub seat_state: SeatState<State>,133
- pub data_device_state: DataDeviceState,134
- pub _cursor_shape_state: smithay::wayland::cursor_shape::CursorShapeManagerState,13587
pub seat: Seat<State>,13688
}13789
90
+/// The event loop and Wayland display, which everything uses and nothing owns.91
+pub struct Core {92
+ pub display: DisplayHandle,93
+ pub handle: LoopHandle<'static, State>,94
+ pub signal: LoopSignal,95
+ pub socket_name: OsString,96
+ pub start: Instant,97
+}98
+99
+/// The config and what is derived from it, swapped whole on reload.100
+pub struct Settings {101
+ pub config: Config,102
+ pub path: Option<PathBuf>,103
+ pub binds: Binds,104
+}105
+138106
impl State {139107
pub fn new(140108
event_loop: &mut EventLoop<'static, State>,@@ -152,8 +120,6 @@ impl State {
152120
Some(node) => VulkanRenderer::for_node(node)?,153121
None => VulkanRenderer::new()?,154122
};155
- let mut dmabuf_state = DmabufState::new();156
- let dmabuf_global = dmabuf_state.create_global::<State>(&dh, renderer.dmabuf_formats());157123
let mut seat_state = SeatState::new();158124
let mut seat = seat_state.new_wl_seat(&dh, "seat0");159125
let kb = &config.keyboard;@@ -165,6 +131,7 @@ impl State {
165131
let handle = event_loop.handle();166132
handle.insert_source(listener, |stream, _, state| {167133
if let Err(e) = state134
+ .core168135
.display169136
.insert_client(stream, Arc::new(ClientState::default()))170137
{@@ -182,14 +149,22 @@ impl State {
182149
183150
let mut layout = Layout::default();184151
layout.gaps = gaps(&config);185
- let binds = Binds::new(&config);186152
let animation = config.animation.clone();187
- let primary_selection_state = PrimarySelectionState::new::<State>(&dh);188153
let imports = crate::import::Imports::new(&handle, renderer.dmabuf_importer())?;189154
Ok(Self {190
- start: Instant::now(),191
- socket_name,192
- signal: event_loop.get_signal(),155
+ protocols: Protocols::new(&dh, handle.clone(), &renderer),156
+ core: Core {157
+ display: dh,158
+ handle,159
+ signal: event_loop.get_signal(),160
+ socket_name,161
+ start: Instant::now(),162
+ },163
+ settings: Settings {164
+ binds: Binds::new(&config),165
+ config,166
+ path: config_path,167
+ },193168
renderer,194169
space: Space::default(),195170
popups: PopupManager::default(),@@ -204,22 +179,12 @@ impl State {
204179
windows: HashMap::new(),205180
unmapped: Vec::new(),206181
output_id: None,207
- config,208
- config_path,209
- binds,210182
suppressed: Vec::new(),211183
move_inverted: false,212184
drag: None,213185
pointer_pos: Point::default(),214186
ipc: crate::ipc::Server::default(),215187
launches: Default::default(),216
- workspaces: WorkspaceState::new::<State>(&dh),217
- foreign_toplevels: monolith_protocols::toplevel::ForeignToplevelState::new::<State>(218
- &dh,219
- ),220
- toplevel_list: smithay::wayland::foreign_toplevel_list::ForeignToplevelListState::new::<221
- State,222
- >(&dh),223188
list_handles: Default::default(),224189
anim: Animator::new(animation),225190
borders: Default::default(),@@ -228,48 +193,14 @@ impl State {
228193
placed_by_rule: HashSet::new(),229194
layer_focus: None,230195
xwayland: None,231
- xwayland_shell_state: XWaylandShellState::new::<State>(&dh),232196
captures: Default::default(),233197
imports,234198
render_node: None,235199
lock: Default::default(),236200
inhibitors: HashSet::new(),237201
inhibited: false,238
- handle: event_loop.handle(),239
- compositor_state: CompositorState::new::<State>(&dh),240
- xdg_shell_state: XdgShellState::new::<State>(&dh),241
- layer_shell_state: WlrLayerShellState::new::<State>(&dh),242
- _image_capture_source_state: ImageCaptureSourceState::new(),243
- output_capture_source_state: OutputCaptureSourceState::new::<State>(&dh),244
- toplevel_capture_source_state: ToplevelCaptureSourceState::new::<State>(&dh),245
- image_copy_capture_state: ImageCopyCaptureState::new::<State>(&dh),246
- activation_state: XdgActivationState::new::<State>(&dh),247
- wlr_data_control_state: WlrDataControlState::new::<State, _>(248
- &dh,249
- Some(&primary_selection_state),250
- |_| true,251
- ),252
- ext_data_control_state: ExtDataControlState::new::<State, _>(253
- &dh,254
- Some(&primary_selection_state),255
- |_| true,256
- ),257
- primary_selection_state,258
- session_lock_state: SessionLockManagerState::new::<State, _>(&dh, |_| true),259
- idle_notifier: IdleNotifierState::new(&dh, event_loop.handle()),260
- _idle_inhibit: IdleInhibitManagerState::new::<State>(&dh),261
- _xdg_decoration_state: XdgDecorationState::new::<State>(&dh),262
- shm_state: ShmState::new::<State>(&dh, vec![]),263
- dmabuf_state,264
- _dmabuf_global: dmabuf_global,265
- _output_manager_state: OutputManagerState::new_with_xdg_output::<State>(&dh),266202
seat_state,267
- data_device_state: DataDeviceState::new::<State>(&dh),268
- _cursor_shape_state: smithay::wayland::cursor_shape::CursorShapeManagerState::new::<269
- State,270
- >(&dh),271203
seat,272
- display: dh,273204
})274205
}275206
@@ -284,7 +215,7 @@ impl State {
284215
crate::ipc::broadcast(self);285216
self.publish_workspaces();286217
self.publish_toplevels();287
- let _ = self.display.flush_clients();218
+ let _ = self.core.display.flush_clients();288219
}289220
290221
pub fn resize_output(&mut self, size: Size<i32, Logical>) {@@ -309,13 +240,13 @@ impl State {
309240
/// and title are known and the initial configure can carry its size.310241
pub fn map_window(&mut self, window: Window, float: Option<Rectangle<i32, Logical>>) {311242
let (app_id, title) = identity(&window);312
- let rule = self.config.placement(&app_id, &title);243
+ let rule = self.settings.config.placement(&app_id, &title);313244
let pid = match window.x11_surface() {314245
Some(x) => x.pid(),315246
None => window316247
.toplevel()317248
.and_then(|t| t.wl_surface().client())318
- .and_then(|c| c.get_credentials(&self.display).ok())249
+ .and_then(|c| c.get_credentials(&self.core.display).ok())319250
.map(|c| c.pid as u32),320251
};321252
let launch = pid.and_then(|pid| self.launches.find(pid));@@ -368,7 +299,7 @@ impl State {
368299
fn await_first_buffer(&mut self, id: WindowId) {369300
self.awaiting.insert(id);370301
let timeout = Timer::from_duration(Duration::from_millis(300));371
- let _ = self.handle.insert_source(timeout, move |_, _, state| {302
+ let _ = self.core.handle.insert_source(timeout, move |_, _, state| {372303
state.first_buffer(id);373304
TimeoutAction::Drop374305
});@@ -613,7 +544,7 @@ impl State {
613544
}614545
615546
fn publish_workspaces(&mut self) {616
- if !self.workspaces.has_clients() {547
+ if !self.protocols.workspaces.has_clients() {617548
return;618549
}619550
let l = &self.layout;@@ -646,12 +577,14 @@ impl State {
646577
Some(Group { output, workspaces })647578
})648579
.collect();649
- let dh = self.display.clone();650
- self.workspaces.update::<State>(&dh, Snapshot { groups });580
+ let dh = self.core.display.clone();581
+ self.protocols582
+ .workspaces583
+ .update::<State>(&dh, Snapshot { groups });651584
}652585
653586
pub fn reconfigure_keyboard(&mut self) {654
- let kb = self.config.keyboard.clone();587
+ let kb = self.settings.config.keyboard.clone();655588
if let Some(keyboard) = self.seat.get_keyboard() {656589
if let Err(e) = keyboard.set_xkb_config(self, xkb_config(&kb)) {657590
tracing::warn!("keyboard config rejected: {e:?}");@@ -29,13 +29,13 @@ pub fn key(id: WindowId) -> u64 {
2929
3030
impl ForeignToplevelListHandler for State {3131
fn foreign_toplevel_list_state(&mut self) -> &mut ForeignToplevelListState {32
- &mut self.toplevel_list32
+ &mut self.protocols.toplevel_list3333
}3434
}3535
3636
impl ForeignToplevelHandler for State {3737
fn foreign_toplevel_state(&mut self) -> &mut ForeignToplevelState {38
- &mut self.foreign_toplevels38
+ &mut self.protocols.foreign_toplevels3939
}4040
4141
fn foreign_toplevel_action(&mut self, action: Action) {@@ -91,7 +91,7 @@ impl State {
9191
handles.retain(|id, h| {9292
let keep = self.windows.contains_key(id);9393
if !keep {94
- self.toplevel_list.remove_toplevel(h);94
+ self.protocols.toplevel_list.remove_toplevel(h);9595
}9696
keep9797
});@@ -106,14 +106,17 @@ impl State {
106106
}107107
}108108
None => {109
- let h = self.toplevel_list.new_toplevel::<State>(title, app_id);109
+ let h = self110
+ .protocols111
+ .toplevel_list112
+ .new_toplevel::<State>(title, app_id);110113
handles.insert(*id, h);111114
}112115
}113116
}114117
self.list_handles.0 = handles;115118
116
- if !self.foreign_toplevels.has_clients() {119
+ if !self.protocols.foreign_toplevels.has_clients() {117120
return;118121
}119122
let focused = self.layout.focused();@@ -138,8 +141,9 @@ impl State {
138141
}139142
})140143
.collect();141
- let dh = self.display.clone();142
- self.foreign_toplevels144
+ let dh = self.core.display.clone();145
+ self.protocols146
+ .foreign_toplevels143147
.update::<State>(&dh, Snapshot { toplevels });144148
}145149
}@@ -101,7 +101,7 @@ pub fn init(state: &mut State) {
101101
let mut watch = Vec::new();102102
for (i, l) in listeners.iter().enumerate() {103103
let Ok(l) = l.try_clone() else { continue };104
- let token = state.handle.insert_source(104
+ let token = state.core.handle.insert_source(105105
Generic::new(l, Interest::READ, Mode::Level),106106
move |_, _, state| {107107
start(state, i);@@ -130,7 +130,7 @@ fn rearm(state: &mut State) {
130130
};131131
x.running = false;132132
for (_, t) in &x.watch {133
- let _ = state.handle.enable(t);133
+ let _ = state.core.handle.enable(t);134134
}135135
}136136
@@ -156,7 +156,7 @@ fn start(state: &mut State, fired: usize) {
156156
x.running = true;157157
for (i, t) in &x.watch {158158
if *i != fired {159
- state.handle.disable(t).ok();159
+ state.core.handle.disable(t).ok();160160
}161161
}162162
let mut args = Vec::new();@@ -168,7 +168,7 @@ fn start(state: &mut State, fired: usize) {
168168
// made inheritable just for this one spawn.169169
set_inherit(&x.listeners, true);170170
let spawned = XWayland::spawn(171
- &state.display,171
+ &state.core.display,172172
None,173173
std::iter::empty::<(String, String)>(),174174
args,@@ -187,11 +187,12 @@ fn start(state: &mut State, fired: usize) {
187187
};188188
tracing::info!("starting Xwayland");189189
let inserted = state190
+ .core190191
.handle191192
.insert_source(xwayland, move |event, _, state| match event {192193
XWaylandEvent::Ready { x11_socket, .. } => {193
- let dh = state.display.clone();194
- match X11Wm::start_wm(state.handle.clone(), &dh, x11_socket, client.clone()) {194
+ let dh = state.core.display.clone();195
+ match X11Wm::start_wm(state.core.handle.clone(), &dh, x11_socket, client.clone()) {195196
Ok(wm) => {196197
tracing::info!("Xwayland ready");197198
if let Some(x) = state.xwayland.as_mut() {@@ -213,7 +214,7 @@ fn start(state: &mut State, fired: usize) {
213214
214215
impl XWaylandShellHandler for State {215216
fn xwayland_shell_state(&mut self) -> &mut XWaylandShellState {216
- &mut self.xwayland_shell_state217
+ &mut self.protocols.xwayland_shell_state217218
}218219
219220
fn surface_associated(&mut self, _xwm: XwmId, surface: WlSurface, _window: X11Surface) {