Skip to content

Commit

Permalink
wayland: use an invisible surface as shell surface
Browse files Browse the repository at this point in the history
This decorelates the window management from the actual user content,
meaning:

- the created window no longer needs the user to draw something to
  start existing
- it reduces our need to do roundtrips during initialization to
  avoid protocol errors
  • Loading branch information
elinorbgr committed Jun 13, 2019
1 parent 47b5dfa commit 42cceac
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
- Remove `WindowBuilder::multitouch` field, since it was only implemented on a few platforms. Multitouch is always enabled now.
- **Breaking:** On macOS, change `ns` identifiers to use snake_case for consistency with iOS's `ui` identifiers.
- Add `MonitorHandle::video_modes` method for retrieving supported video modes for the given monitor.
- On Wayland, the window now exists even if nothing has been drawn.

# Version 0.19.1 (2019-04-08)

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ features = [
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies]
wayland-client = { version = "0.23.0", features = [ "dlopen", "egl", "cursor", "eventloop"] }
calloop = "0.4.2"
smithay-client-toolkit = "0.6"
smithay-client-toolkit = "0.6.1"
x11-dl = "2.18.3"
percent-encoding = "1.0"

Expand Down
60 changes: 46 additions & 14 deletions src/platform_impl/linux/wayland/window.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::VecDeque;
use std::io::{Seek, SeekFrom, Write};
use std::sync::{Arc, Mutex, Weak};

use dpi::{LogicalPosition, LogicalSize};
Expand All @@ -9,15 +10,17 @@ use window::{WindowAttributes, CursorIcon};

use sctk::surface::{get_dpi_factor, get_outputs};
use sctk::window::{ConceptFrame, Event as WEvent, State as WState, Window as SWindow, Theme};
use sctk::reexports::client::Display;
use sctk::reexports::client::protocol::{wl_seat, wl_surface};
use sctk::reexports::client::{Display, NewProxy};
use sctk::reexports::client::protocol::{wl_seat, wl_surface, wl_subsurface, wl_shm};
use sctk::output::OutputMgr;

use super::{make_wid, EventLoopWindowTarget, MonitorHandle, WindowId};
use platform_impl::platform::wayland::event_loop::{available_monitors, primary_monitor};

pub struct Window {
surface: wl_surface::WlSurface,
_bg_surface: wl_surface::WlSurface,
user_surface: wl_surface::WlSurface,
_user_subsurface: wl_subsurface::WlSubsurface,
frame: Arc<Mutex<SWindow<ConceptFrame>>>,
outputs: OutputMgr, // Access to info for all monitors
size: Arc<Mutex<(u32, u32)>>,
Expand All @@ -36,16 +39,37 @@ impl Window {
let fullscreen = Arc::new(Mutex::new(false));

let window_store = evlp.store.clone();
let surface = evlp.env.create_surface(move |dpi, surface| {
let bg_surface = evlp
.env
.compositor
.create_surface(NewProxy::implement_dummy)
.unwrap();
let user_surface = evlp.env.create_surface(move |dpi, surface| {
window_store.lock().unwrap().dpi_change(&surface, dpi);
surface.set_buffer_scale(dpi);
});
let user_subsurface = evlp
.env
.subcompositor
.get_subsurface(&user_surface, &bg_surface, NewProxy::implement_dummy)
.unwrap();
user_subsurface.set_desync();

let window_store = evlp.store.clone();
let my_surface = surface.clone();
let my_surface = user_surface.clone();
let my_bg_surface = bg_surface.clone();

// prepare a 1px buffer to display on the root window
let mut pool = sctk::utils::MemPool::new(&evlp.env.shm, || {}).unwrap();
pool.resize(4).unwrap();
pool.seek(SeekFrom::Start(0)).unwrap();
pool.write(&[0, 0, 0, 0]).unwrap();
pool.flush().unwrap();
let buffer = pool.buffer(0, 1, 1, 4, wl_shm::Format::Argb8888);

let mut frame = SWindow::<ConceptFrame>::init_from_env(
&evlp.env,
surface.clone(),
bg_surface.clone(),
(width, height),
move |event| match event {
WEvent::Configure { new_size, states } => {
Expand All @@ -58,6 +82,12 @@ impl Window {
*(window.need_refresh.lock().unwrap()) = true;
*(window.fullscreen.lock().unwrap()) = is_fullscreen;
*(window.need_frame_refresh.lock().unwrap()) = true;
if !window.configured {
// this is our first configure event, display ourselves !
window.configured = true;
my_bg_surface.attach(Some(&buffer), 0, 0);
my_bg_surface.commit();
}
return;
}
}
Expand Down Expand Up @@ -125,17 +155,19 @@ impl Window {
need_refresh: need_refresh.clone(),
fullscreen: fullscreen.clone(),
need_frame_refresh: need_frame_refresh.clone(),
surface: surface.clone(),
surface: user_surface.clone(),
kill_switch: kill_switch.clone(),
frame: Arc::downgrade(&frame),
current_dpi: 1,
new_dpi: None,
configured: false,
});
evlp.evq.borrow_mut().sync_roundtrip().unwrap();

Ok(Window {
display: evlp.display.clone(),
surface: surface,
_bg_surface: bg_surface,
user_surface: user_surface,
_user_subsurface: user_subsurface,
frame: frame,
outputs: evlp.env.outputs.clone(),
size: size,
Expand All @@ -148,7 +180,7 @@ impl Window {

#[inline]
pub fn id(&self) -> WindowId {
make_wid(&self.surface)
make_wid(&self.user_surface)
}

pub fn set_title(&self, title: &str) {
Expand Down Expand Up @@ -214,7 +246,7 @@ impl Window {

#[inline]
pub fn hidpi_factor(&self) -> i32 {
get_dpi_factor(&self.surface)
get_dpi_factor(&self.user_surface)
}

pub fn set_decorations(&self, decorate: bool) {
Expand Down Expand Up @@ -252,7 +284,6 @@ impl Window {
}
}


pub fn set_theme<T: Theme>(&self, theme: T) {
self.frame.lock().unwrap().set_theme(theme)
}
Expand Down Expand Up @@ -282,11 +313,11 @@ impl Window {
}

pub fn surface(&self) -> &wl_surface::WlSurface {
&self.surface
&self.user_surface
}

pub fn current_monitor(&self) -> MonitorHandle {
let output = get_outputs(&self.surface).last().unwrap().clone();
let output = get_outputs(&self.user_surface).last().unwrap().clone();
MonitorHandle {
proxy: output,
mgr: self.outputs.clone(),
Expand Down Expand Up @@ -325,6 +356,7 @@ struct InternalWindow {
frame: Weak<Mutex<SWindow<ConceptFrame>>>,
current_dpi: i32,
new_dpi: Option<i32>,
configured: bool,
}

pub struct WindowStore {
Expand Down

0 comments on commit 42cceac

Please sign in to comment.