anvil: store buffer dimensions separately

Before this change, the texture size was used for the dimensions.
However, the texture is not created until the next rendered frame, which
means that frequently size was returned as zero, resulting in pointer
focus artifacts. With this change, the dimensions are retrieved
immediately on surface commit.
This commit is contained in:
Ivan Molodetskikh 2020-02-03 08:42:12 +03:00
parent 825995687a
commit a224f774ee
No known key found for this signature in database
GPG Key ID: 02CE38DA47E9D691
3 changed files with 35 additions and 12 deletions

View File

@ -28,7 +28,10 @@ use smithay::{
},
};
use crate::window_map::{Kind as SurfaceKind, WindowMap};
use crate::{
buffer_utils::BufferUtils,
window_map::{Kind as SurfaceKind, WindowMap},
};
define_roles!(Roles =>
[ XdgSurface, XdgSurfaceRole ]
@ -47,6 +50,7 @@ pub type MyCompositorToken = CompositorToken<Roles>;
pub fn init_shell(
display: &mut Display,
buffer_utils: BufferUtils,
log: ::slog::Logger,
) -> (
CompositorToken<Roles>,
@ -58,7 +62,7 @@ pub fn init_shell(
let (compositor_token, _, _) = compositor_init(
display,
move |request, surface, ctoken| match request {
SurfaceEvent::Commit => surface_commit(&surface, ctoken),
SurfaceEvent::Commit => surface_commit(&surface, ctoken, &buffer_utils),
SurfaceEvent::Frame { callback } => callback
.implement_closure(|_, _| unreachable!(), None::<fn(_)>, ())
.done(0),
@ -138,10 +142,15 @@ pub fn init_shell(
pub struct SurfaceData {
pub buffer: Option<wl_buffer::WlBuffer>,
pub texture: Option<crate::glium_drawer::TextureMetadata>,
pub dimensions: Option<(i32, i32)>,
pub input_region: Option<RegionAttributes>,
}
fn surface_commit(surface: &wl_surface::WlSurface, token: CompositorToken<Roles>) {
fn surface_commit(
surface: &wl_surface::WlSurface,
token: CompositorToken<Roles>,
buffer_utils: &BufferUtils,
) {
token.with_surface_data(surface, |attributes| {
attributes.user_data.insert_if_missing(SurfaceData::default);
let data = attributes.user_data.get_mut::<SurfaceData>().unwrap();
@ -157,6 +166,8 @@ fn surface_commit(surface: &wl_surface::WlSurface, token: CompositorToken<Roles>
old_buffer.release();
}
data.texture = None;
// If this fails, the buffer will be discarded later by the drawing code.
data.dimensions = buffer_utils.dimensions(data.buffer.as_ref().unwrap());
}
Some(None) => {
// erase the contents
@ -164,6 +175,7 @@ fn surface_commit(surface: &wl_surface::WlSurface, token: CompositorToken<Roles>
old_buffer.release();
}
data.texture = None;
data.dimensions = None;
}
None => {}
}
@ -171,12 +183,10 @@ fn surface_commit(surface: &wl_surface::WlSurface, token: CompositorToken<Roles>
}
fn get_size(attrs: &SurfaceAttributes) -> Option<(i32, i32)> {
attrs.user_data.get::<SurfaceData>().and_then(|data| {
data.texture
.as_ref()
.map(|ref meta| meta.dimensions)
.map(|(x, y)| (x as i32, y as i32))
})
attrs
.user_data
.get::<SurfaceData>()
.and_then(|data| data.dimensions)
}
fn contains_point(attrs: &SurfaceAttributes, point: (f64, f64)) -> bool {

View File

@ -61,6 +61,7 @@ use smithay::{
},
};
use crate::buffer_utils::BufferUtils;
use crate::glium_drawer::GliumDrawer;
use crate::input_handler::AnvilInputHandler;
use crate::shell::{init_shell, MyWindowMap, Roles};
@ -85,6 +86,11 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
#[cfg(feature = "egl")]
let active_egl_context = Rc::new(RefCell::new(None));
#[cfg(feature = "egl")]
let buffer_utils = BufferUtils::new(active_egl_context.clone(), log.clone());
#[cfg(not(feature = "egl"))]
let buffer_utils = BufferUtils::new(log.clone());
let display = Rc::new(RefCell::new(display));
/*
@ -92,7 +98,8 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
*/
init_shm_global(&mut display.borrow_mut(), vec![], log.clone());
let (compositor_token, _, _, window_map) = init_shell(&mut display.borrow_mut(), log.clone());
let (compositor_token, _, _, window_map) =
init_shell(&mut display.borrow_mut(), buffer_utils, log.clone());
/*
* Initialize session

View File

@ -23,6 +23,7 @@ use smithay::{
use slog::Logger;
use crate::buffer_utils::BufferUtils;
use crate::glium_drawer::GliumDrawer;
use crate::input_handler::AnvilInputHandler;
use crate::shell::init_shell;
@ -42,10 +43,15 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop<()>, log: Log
let (w, h) = renderer.get_framebuffer_dimensions();
#[cfg(feature = "egl")]
let drawer = GliumDrawer::init(renderer, egl_display, log.clone());
let drawer = GliumDrawer::init(renderer, egl_display.clone(), log.clone());
#[cfg(not(feature = "egl"))]
let drawer = GliumDrawer::init(renderer, log.clone());
#[cfg(feature = "egl")]
let buffer_utils = BufferUtils::new(egl_display, log.clone());
#[cfg(not(feature = "egl"))]
let buffer_utils = BufferUtils::new(log.clone());
let name = display.add_socket_auto().unwrap().into_string().unwrap();
info!(log, "Listening on wayland socket"; "name" => name.clone());
::std::env::set_var("WAYLAND_DISPLAY", name);
@ -58,7 +64,7 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop<()>, log: Log
init_shm_global(display, vec![], log.clone());
let (compositor_token, _, _, window_map) = init_shell(display, log.clone());
let (compositor_token, _, _, window_map) = init_shell(display, buffer_utils, log.clone());
let dnd_icon = Arc::new(Mutex::new(None));