x11: add nested x11 backend
This commit is contained in:
parent
2698c06f50
commit
74a4ed1058
7 changed files with 470 additions and 29 deletions
71
Cargo.lock
generated
71
Cargo.lock
generated
|
|
@ -151,6 +151,15 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dlib"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794"
|
||||||
|
dependencies = [
|
||||||
|
"libloading",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "downcast-rs"
|
name = "downcast-rs"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
|
@ -272,6 +281,15 @@ dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instant"
|
||||||
|
version = "0.1.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "khronos_api"
|
name = "khronos_api"
|
||||||
version = "3.1.0"
|
version = "3.1.0"
|
||||||
|
|
@ -300,6 +318,15 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
|
||||||
|
dependencies = [
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.14"
|
version = "0.4.14"
|
||||||
|
|
@ -356,6 +383,31 @@ version = "1.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
|
||||||
|
dependencies = [
|
||||||
|
"instant",
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"instant",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.24"
|
version = "0.3.24"
|
||||||
|
|
@ -466,6 +518,18 @@ version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b53b0a5db882a8e2fdaae0a43f7b39e7e9082389e978398bdf223a55b581248"
|
checksum = "0b53b0a5db882a8e2fdaae0a43f7b39e7e9082389e978398bdf223a55b581248"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scoped-tls"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slog"
|
name = "slog"
|
||||||
version = "2.7.0"
|
version = "2.7.0"
|
||||||
|
|
@ -554,6 +618,7 @@ dependencies = [
|
||||||
"wayland-commons",
|
"wayland-commons",
|
||||||
"wayland-protocols",
|
"wayland-protocols",
|
||||||
"wayland-server",
|
"wayland-server",
|
||||||
|
"wayland-sys",
|
||||||
"x11rb",
|
"x11rb",
|
||||||
"xkbcommon",
|
"xkbcommon",
|
||||||
]
|
]
|
||||||
|
|
@ -694,8 +759,11 @@ checksum = "a0307b0fbbae986e86934b8fbcc56299bbaf8de0b5ad0f00405fb583503c085a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"downcast-rs",
|
"downcast-rs",
|
||||||
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"nix",
|
"nix",
|
||||||
|
"parking_lot",
|
||||||
|
"scoped-tls",
|
||||||
"wayland-commons",
|
"wayland-commons",
|
||||||
"wayland-scanner",
|
"wayland-scanner",
|
||||||
"wayland-sys",
|
"wayland-sys",
|
||||||
|
|
@ -707,6 +775,9 @@ version = "0.29.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba9e06acb775b3007f8d3094438306979e572d1d3b844d7a71557a84b055d959"
|
checksum = "ba9e06acb775b3007f8d3094438306979e572d1d3b844d7a71557a84b055d959"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"dlib",
|
||||||
|
"libc",
|
||||||
|
"memoffset",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,4 +18,4 @@ version = "0.3"
|
||||||
git = "https://github.com/Smithay/smithay.git"
|
git = "https://github.com/Smithay/smithay.git"
|
||||||
rev = "87ab37a1"
|
rev = "87ab37a1"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["backend_x11", "backend_egl", "desktop", "renderer_gl", "wayland_frontend"]
|
features = ["backend_x11", "backend_egl", "desktop", "use_system_lib", "renderer_gl", "wayland_frontend"]
|
||||||
18
src/backend/mod.rs
Normal file
18
src/backend/mod.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use crate::state::State;
|
||||||
|
use anyhow::Result;
|
||||||
|
use smithay::reexports::calloop::EventLoop;
|
||||||
|
|
||||||
|
pub mod x11;
|
||||||
|
// TODO
|
||||||
|
// pub mod wayland; // tbd in smithay
|
||||||
|
// pub mod udev;
|
||||||
|
|
||||||
|
pub fn init_backend_auto(event_loop: &mut EventLoop<State>, state: &mut State) -> Result<()> {
|
||||||
|
if std::env::var_os("DISPLAY").is_some() {
|
||||||
|
x11::init_backend(event_loop, state)
|
||||||
|
} else {
|
||||||
|
unimplemented!("Currently this runs only nested")
|
||||||
|
}
|
||||||
|
}
|
||||||
284
src/backend/x11.rs
Normal file
284
src/backend/x11.rs
Normal file
|
|
@ -0,0 +1,284 @@
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
state::{BackendData, State},
|
||||||
|
utils::GlobalDrop,
|
||||||
|
};
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
use smithay::{
|
||||||
|
backend::{
|
||||||
|
allocator::dmabuf::Dmabuf,
|
||||||
|
drm::DrmNode,
|
||||||
|
egl::{EGLContext, EGLDisplay},
|
||||||
|
renderer::{gles2::Gles2Renderer, Bind, ImportDma, ImportEgl, Unbind},
|
||||||
|
x11::{Window, WindowBuilder, X11Backend, X11Event, X11Handle, X11Surface},
|
||||||
|
},
|
||||||
|
desktop::Space,
|
||||||
|
reexports::{
|
||||||
|
calloop::{ping, EventLoop, LoopHandle},
|
||||||
|
gbm::Device as GbmDevice,
|
||||||
|
wayland_server::{
|
||||||
|
protocol::wl_output::{Subpixel, WlOutput},
|
||||||
|
Display,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wayland::{
|
||||||
|
dmabuf::init_dmabuf_global,
|
||||||
|
output::{Mode, Output, PhysicalProperties},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
rc::Rc,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct X11State {
|
||||||
|
handle: X11Handle,
|
||||||
|
allocator: Arc<Mutex<GbmDevice<DrmNode>>>,
|
||||||
|
_egl: EGLDisplay,
|
||||||
|
renderer: Rc<RefCell<Gles2Renderer>>,
|
||||||
|
surfaces: Vec<Surface>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl X11State {
|
||||||
|
pub fn add_window(
|
||||||
|
&mut self,
|
||||||
|
display: &mut Display,
|
||||||
|
handle: LoopHandle<'_, State>,
|
||||||
|
) -> Result<Output> {
|
||||||
|
let window = WindowBuilder::new()
|
||||||
|
.title("COSMIC")
|
||||||
|
.build(&self.handle)
|
||||||
|
.with_context(|| "Failed to create window")?;
|
||||||
|
let fourcc = window.format().unwrap();
|
||||||
|
let surface = self
|
||||||
|
.handle
|
||||||
|
.create_surface(
|
||||||
|
&window,
|
||||||
|
self.allocator.clone(),
|
||||||
|
Bind::<Dmabuf>::supported_formats(&*self.renderer.borrow())
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.filter(|format| format.code == fourcc)
|
||||||
|
.map(|format| format.modifier),
|
||||||
|
)
|
||||||
|
.with_context(|| "Failed to create surface")?;
|
||||||
|
|
||||||
|
let name = format!("X11-{}", self.surfaces.len());
|
||||||
|
let size = window.size();
|
||||||
|
let props = PhysicalProperties {
|
||||||
|
size: (0, 0).into(),
|
||||||
|
subpixel: Subpixel::Unknown,
|
||||||
|
make: "COSMIC".to_string(),
|
||||||
|
model: name.clone(),
|
||||||
|
};
|
||||||
|
let mode = Mode {
|
||||||
|
size: (size.w as i32, size.h as i32).into(),
|
||||||
|
refresh: 60_000,
|
||||||
|
};
|
||||||
|
let (output, global) = Output::new(display, name, props, None);
|
||||||
|
let _global = global.into();
|
||||||
|
output.change_current_state(Some(mode), None, None, Some((0, 0).into()));
|
||||||
|
output.set_preferred(mode);
|
||||||
|
|
||||||
|
let output_ref = output.clone();
|
||||||
|
let (ping, source) =
|
||||||
|
ping::make_ping().with_context(|| "Failed to create output event loop source")?;
|
||||||
|
let _token = handle
|
||||||
|
.insert_source(source, move |_, _, state| {
|
||||||
|
let x11_state = state.backend.x11();
|
||||||
|
if let Some(surface) = x11_state
|
||||||
|
.surfaces
|
||||||
|
.iter_mut()
|
||||||
|
.find(|s| s.output == output_ref)
|
||||||
|
{
|
||||||
|
if let Err(err) = surface
|
||||||
|
.render_from_space(&mut *x11_state.renderer.borrow_mut(), &mut state.spaces)
|
||||||
|
{
|
||||||
|
slog_scope::error!("Error rendering: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.with_context(|| "Failed to add output to event loop")?;
|
||||||
|
|
||||||
|
self.surfaces.push(Surface {
|
||||||
|
window,
|
||||||
|
surface,
|
||||||
|
output: output.clone(),
|
||||||
|
render: ping.clone(),
|
||||||
|
_global,
|
||||||
|
});
|
||||||
|
|
||||||
|
// schedule first render
|
||||||
|
ping.ping();
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Surface {
|
||||||
|
window: Window,
|
||||||
|
surface: X11Surface,
|
||||||
|
output: Output,
|
||||||
|
render: ping::Ping,
|
||||||
|
_global: GlobalDrop<WlOutput>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Surface {
|
||||||
|
pub fn render_from_space(
|
||||||
|
&mut self,
|
||||||
|
renderer: &mut Gles2Renderer,
|
||||||
|
space: &mut Space,
|
||||||
|
) -> Result<()> {
|
||||||
|
let (buffer, age) = self
|
||||||
|
.surface
|
||||||
|
.buffer()
|
||||||
|
.with_context(|| "Failed to allocate buffer")?;
|
||||||
|
renderer
|
||||||
|
.bind(buffer)
|
||||||
|
.with_context(|| "Failed to bind buffer")?;
|
||||||
|
match space.render_output(
|
||||||
|
renderer,
|
||||||
|
&self.output,
|
||||||
|
age as usize,
|
||||||
|
[0.153, 0.161, 0.165, 1.0],
|
||||||
|
) {
|
||||||
|
Ok(true) => {
|
||||||
|
slog_scope::trace!("Finished rendering");
|
||||||
|
self.surface
|
||||||
|
.submit()
|
||||||
|
.with_context(|| "Failed to submit buffer for display")?;
|
||||||
|
}
|
||||||
|
Ok(false) => {
|
||||||
|
let _ = renderer.unbind();
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
self.surface.reset_buffers();
|
||||||
|
anyhow::bail!("Rendering failed: {}", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_backend(event_loop: &mut EventLoop<State>, state: &mut State) -> Result<()> {
|
||||||
|
let backend = X11Backend::new(None).with_context(|| "Failed to initilize X11 backend")?;
|
||||||
|
let handle = backend.handle();
|
||||||
|
|
||||||
|
// Obtain the DRM node the X server uses for direct rendering.
|
||||||
|
let drm_node = handle
|
||||||
|
.drm_node()
|
||||||
|
.with_context(|| "Could not get DRM node used by X server")?;
|
||||||
|
|
||||||
|
// Create the gbm device for buffer allocation.
|
||||||
|
let device = GbmDevice::new(drm_node).with_context(|| "Failed to create GBM device")?;
|
||||||
|
// Initialize EGL using the GBM device.
|
||||||
|
let egl = EGLDisplay::new(&device, None).with_context(|| "Failed to create EGL display")?;
|
||||||
|
// Create the OpenGL context
|
||||||
|
let context = EGLContext::new(&egl, None).with_context(|| "Failed to create EGL context")?;
|
||||||
|
// Create a renderer
|
||||||
|
let renderer = Rc::new(RefCell::new(
|
||||||
|
unsafe { Gles2Renderer::new(context, None) }
|
||||||
|
.with_context(|| "Failed to initialize renderer")?,
|
||||||
|
));
|
||||||
|
|
||||||
|
init_egl_client_side(&mut *state.display.borrow_mut(), renderer.clone())?;
|
||||||
|
|
||||||
|
state.backend = BackendData::X11(X11State {
|
||||||
|
handle,
|
||||||
|
allocator: Arc::new(Mutex::new(device)),
|
||||||
|
_egl: egl,
|
||||||
|
renderer,
|
||||||
|
surfaces: Vec::new(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let output = state
|
||||||
|
.backend
|
||||||
|
.x11()
|
||||||
|
.add_window(&mut *state.display.borrow_mut(), event_loop.handle())
|
||||||
|
.with_context(|| "Failed to create wl_output")?;
|
||||||
|
state
|
||||||
|
.spaces
|
||||||
|
.map_output(&output, 1.0, (0, 0).into() /* TODO */);
|
||||||
|
|
||||||
|
event_loop
|
||||||
|
.handle()
|
||||||
|
.insert_source(backend, |event, window, state| match event {
|
||||||
|
X11Event::CloseRequested => {
|
||||||
|
window.unmap();
|
||||||
|
// TODO: drain_filter
|
||||||
|
for output in state
|
||||||
|
.backend
|
||||||
|
.x11()
|
||||||
|
.surfaces
|
||||||
|
.iter()
|
||||||
|
.filter(|s| &s.window == window)
|
||||||
|
.map(|s| &s.output)
|
||||||
|
{
|
||||||
|
state.spaces.unmap_output(output);
|
||||||
|
}
|
||||||
|
state.backend.x11().surfaces.retain(|s| &s.window != window);
|
||||||
|
}
|
||||||
|
X11Event::Resized(size) => {
|
||||||
|
let size = { (size.w as i32, size.h as i32).into() };
|
||||||
|
let mode = Mode {
|
||||||
|
size,
|
||||||
|
refresh: 60_000,
|
||||||
|
};
|
||||||
|
let surface = state
|
||||||
|
.backend
|
||||||
|
.x11()
|
||||||
|
.surfaces
|
||||||
|
.iter_mut()
|
||||||
|
.find(|s| &s.window == window)
|
||||||
|
.expect("Unmanaged X11 surface?");
|
||||||
|
surface.render.ping();
|
||||||
|
|
||||||
|
let output = &surface.output;
|
||||||
|
output.delete_mode(output.current_mode().unwrap());
|
||||||
|
output.change_current_state(Some(mode), None, None, None);
|
||||||
|
output.set_preferred(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
X11Event::PresentCompleted | X11Event::Refresh => {
|
||||||
|
state
|
||||||
|
.backend
|
||||||
|
.x11()
|
||||||
|
.surfaces
|
||||||
|
.iter_mut()
|
||||||
|
.find(|s| &s.window == window)
|
||||||
|
.expect("Unmanaged X11 surface?")
|
||||||
|
.render
|
||||||
|
.ping();
|
||||||
|
}
|
||||||
|
|
||||||
|
X11Event::Input(event) => { /*TODO*/ }
|
||||||
|
})
|
||||||
|
.expect("Failed to insert X11 Backend into event loop");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_egl_client_side(display: &mut Display, renderer: Rc<RefCell<Gles2Renderer>>) -> Result<()> {
|
||||||
|
let bind_result = renderer.borrow_mut().bind_wl_display(display);
|
||||||
|
match bind_result {
|
||||||
|
Ok(_) => {
|
||||||
|
slog_scope::info!("EGL hardware-acceleration enabled");
|
||||||
|
let dmabuf_formats = renderer
|
||||||
|
.borrow()
|
||||||
|
.dmabuf_formats()
|
||||||
|
.cloned()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
init_dmabuf_global(
|
||||||
|
display,
|
||||||
|
dmabuf_formats,
|
||||||
|
move |buffer, _| renderer.borrow_mut().import_dmabuf(buffer).is_ok(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Err(err) => slog_scope::warn!("Unable to initialize bind display to EGL: {}", err),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
73
src/main.rs
73
src/main.rs
|
|
@ -8,10 +8,50 @@ use smithay::reexports::{
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use slog::Drain;
|
use slog::Drain;
|
||||||
|
|
||||||
|
pub mod backend;
|
||||||
pub mod state;
|
pub mod state;
|
||||||
|
pub mod utils;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
// setup logger
|
// setup logger
|
||||||
|
let _guard = init_logger();
|
||||||
|
slog_scope::info!("Cosmic starting up!");
|
||||||
|
|
||||||
|
// init event loop
|
||||||
|
let mut event_loop = EventLoop::try_new().with_context(|| "Failed to initialize event loop")?;
|
||||||
|
// init wayland
|
||||||
|
let display = init_wayland_display(&mut event_loop)?;
|
||||||
|
// init state
|
||||||
|
let mut state = state::State::new(display);
|
||||||
|
// init backend
|
||||||
|
backend::init_backend_auto(&mut event_loop, &mut state)?;
|
||||||
|
|
||||||
|
// run the event loop
|
||||||
|
let signal = event_loop.get_signal();
|
||||||
|
event_loop.run(None, &mut state, |state| {
|
||||||
|
// shall we shut down?
|
||||||
|
if state.spaces.outputs().next().is_none() || state.should_stop {
|
||||||
|
slog_scope::info!("Shutting down");
|
||||||
|
signal.stop();
|
||||||
|
signal.wakeup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// trigger routines
|
||||||
|
state
|
||||||
|
.spaces
|
||||||
|
.send_frames(false, state.start_time.elapsed().as_millis() as u32);
|
||||||
|
state.spaces.refresh();
|
||||||
|
|
||||||
|
// send out events
|
||||||
|
let display = state.display.clone();
|
||||||
|
display.borrow_mut().flush_clients(state);
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_logger() -> Result<slog_scope::GlobalLoggerGuard> {
|
||||||
let decorator = slog_term::TermDecorator::new().stderr().build();
|
let decorator = slog_term::TermDecorator::new().stderr().build();
|
||||||
// usually we would not want to use a Mutex here, but this is usefull for a prototype,
|
// usually we would not want to use a Mutex here, but this is usefull for a prototype,
|
||||||
// to make sure we do not miss any in-flight messages, when we crash.
|
// to make sure we do not miss any in-flight messages, when we crash.
|
||||||
|
|
@ -24,7 +64,7 @@ fn main() -> Result<()> {
|
||||||
.fuse(),
|
.fuse(),
|
||||||
slog::o!(),
|
slog::o!(),
|
||||||
);
|
);
|
||||||
let _guard = slog_scope::set_global_logger(logger);
|
let guard = slog_scope::set_global_logger(logger);
|
||||||
slog_stdlog::init().unwrap();
|
slog_stdlog::init().unwrap();
|
||||||
|
|
||||||
slog_scope::info!("Version: {}", std::env!("CARGO_PKG_VERSION"));
|
slog_scope::info!("Version: {}", std::env!("CARGO_PKG_VERSION"));
|
||||||
|
|
@ -34,14 +74,15 @@ fn main() -> Result<()> {
|
||||||
std::option_env!("GIT_HASH").unwrap_or("Unknown")
|
std::option_env!("GIT_HASH").unwrap_or("Unknown")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
slog_scope::info!("Cosmic starting up!");
|
|
||||||
|
|
||||||
// init event loop
|
Ok(guard)
|
||||||
let mut event_loop = EventLoop::try_new().with_context(|| "Failed to initialize event loop")?;
|
}
|
||||||
|
|
||||||
// add wayland socket
|
fn init_wayland_display(event_loop: &mut EventLoop<state::State>) -> Result<Display> {
|
||||||
let mut display = Display::new();
|
let mut display = Display::new();
|
||||||
let socket_name = display.add_socket_auto()?;
|
let socket_name = display.add_socket_auto()?;
|
||||||
|
|
||||||
|
slog_scope::info!("Listening on {:?}", socket_name);
|
||||||
event_loop
|
event_loop
|
||||||
.handle()
|
.handle()
|
||||||
.insert_source(
|
.insert_source(
|
||||||
|
|
@ -59,25 +100,7 @@ fn main() -> Result<()> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.expect("Failed to init the wayland event source.");
|
.with_context(|| "Failed to init the wayland event source.")?;
|
||||||
slog_scope::info!("Listening on {:?}", socket_name);
|
|
||||||
|
|
||||||
// init state
|
Ok(display)
|
||||||
let mut state = state::State::new(display);
|
|
||||||
|
|
||||||
// run the event loop
|
|
||||||
let signal = event_loop.get_signal();
|
|
||||||
event_loop.run(None, &mut state, |state| {
|
|
||||||
// shall we shut down?
|
|
||||||
if state.should_stop {
|
|
||||||
signal.stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send out events
|
|
||||||
let display = state.display.clone();
|
|
||||||
display.borrow_mut().flush_clients(state);
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
src/state.rs
31
src/state.rs
|
|
@ -1,19 +1,44 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use crate::backend::x11::X11State;
|
||||||
|
use smithay::{desktop::Space, reexports::wayland_server::Display};
|
||||||
use smithay::reexports::wayland_server::Display;
|
use std::{cell::RefCell, rc::Rc, time::Instant};
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
pub display: Rc<RefCell<Display>>,
|
pub display: Rc<RefCell<Display>>,
|
||||||
|
pub spaces: Space, //TODO: Multiple workspaces
|
||||||
|
|
||||||
|
pub start_time: Instant,
|
||||||
pub should_stop: bool,
|
pub should_stop: bool,
|
||||||
|
pub backend: BackendData,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum BackendData {
|
||||||
|
X11(X11State),
|
||||||
|
// TODO
|
||||||
|
// Wayland(WaylandState),
|
||||||
|
// Udev(UdevState),
|
||||||
|
Unset,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BackendData {
|
||||||
|
pub fn x11(&mut self) -> &mut X11State {
|
||||||
|
match self {
|
||||||
|
BackendData::X11(ref mut x11_state) => x11_state,
|
||||||
|
_ => unreachable!("Called x11 in non x11 backend"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
pub fn new(display: Display) -> State {
|
pub fn new(display: Display) -> State {
|
||||||
State {
|
State {
|
||||||
display: Rc::new(RefCell::new(display)),
|
display: Rc::new(RefCell::new(display)),
|
||||||
|
spaces: Space::new(slog_scope::logger() /*TODO*/),
|
||||||
|
|
||||||
|
start_time: Instant::now(),
|
||||||
should_stop: false,
|
should_stop: false,
|
||||||
|
backend: BackendData::Unset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
20
src/utils.rs
Normal file
20
src/utils.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use smithay::reexports::wayland_server::{Global, Interface, Resource};
|
||||||
|
use std::convert::{AsRef, From};
|
||||||
|
|
||||||
|
pub struct GlobalDrop<I: Interface + AsRef<Resource<I>> + From<Resource<I>>>(Option<Global<I>>);
|
||||||
|
|
||||||
|
impl<I: Interface + AsRef<Resource<I>> + From<Resource<I>>> From<Global<I>> for GlobalDrop<I> {
|
||||||
|
fn from(g: Global<I>) -> GlobalDrop<I> {
|
||||||
|
GlobalDrop(Some(g))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interface + AsRef<Resource<I>> + From<Resource<I>>> Drop for GlobalDrop<I> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Some(global) = self.0.take() {
|
||||||
|
global.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue