Don't set viewport for 1x1 windows with scaling
This commit is contained in:
parent
555f9492ad
commit
0cd5059c42
5 changed files with 106 additions and 49 deletions
|
|
@ -170,6 +170,10 @@ impl<C: XConnection> Dispatch<WlSurface, ObjectKey> for ServerState<C> {
|
||||||
}
|
}
|
||||||
surface.destroy_role();
|
surface.destroy_role();
|
||||||
surface.client.destroy();
|
surface.client.destroy();
|
||||||
|
surface.viewport.destroy();
|
||||||
|
if let Some(f) = &mut surface.fractional {
|
||||||
|
f.destroy();
|
||||||
|
}
|
||||||
debug!(
|
debug!(
|
||||||
"deleting key: {key:?} (surface {:?})",
|
"deleting key: {key:?} (surface {:?})",
|
||||||
surface.server.id().protocol_id()
|
surface.server.id().protocol_id()
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,9 @@ impl SurfaceData {
|
||||||
fn update_viewport(&self, dims: WindowDims, size_hints: Option<WmNormalHints>) {
|
fn update_viewport(&self, dims: WindowDims, size_hints: Option<WmNormalHints>) {
|
||||||
let width = (dims.width as f64 / self.scale_factor) as i32;
|
let width = (dims.width as f64 / self.scale_factor) as i32;
|
||||||
let height = (dims.height as f64 / self.scale_factor) as i32;
|
let height = (dims.height as f64 / self.scale_factor) as i32;
|
||||||
self.viewport.set_destination(width, height);
|
if width > 0 && height > 0 {
|
||||||
|
self.viewport.set_destination(width, height);
|
||||||
|
}
|
||||||
debug!("{} viewport: {width}x{height}", self.server.id());
|
debug!("{} viewport: {width}x{height}", self.server.id());
|
||||||
if let Some(hints) = size_hints {
|
if let Some(hints) = size_hints {
|
||||||
let Some(SurfaceRole::Toplevel(Some(data))) = &self.role else {
|
let Some(SurfaceRole::Toplevel(Some(data))) = &self.role else {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
use super::{ServerState, WindowDims};
|
use super::{ServerState, WindowDims};
|
||||||
use crate::xstate::{SetState, WinSize, WmName};
|
use crate::xstate::{SetState, WinSize, WmName};
|
||||||
use rustix::event::{poll, PollFd, PollFlags};
|
use rustix::event::{poll, PollFd, PollFlags};
|
||||||
use smithay_client_toolkit::compositor::Surface;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::os::fd::{AsRawFd, BorrowedFd};
|
use std::os::fd::{AsRawFd, BorrowedFd};
|
||||||
|
|
@ -24,8 +23,6 @@ use wayland_client::{
|
||||||
},
|
},
|
||||||
Connection, Proxy, WEnum,
|
Connection, Proxy, WEnum,
|
||||||
};
|
};
|
||||||
use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_manager_v1::WpFractionalScaleManagerV1;
|
|
||||||
|
|
||||||
use wayland_protocols::{
|
use wayland_protocols::{
|
||||||
wp::{
|
wp::{
|
||||||
linux_dmabuf::zv1::client::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1,
|
linux_dmabuf::zv1::client::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1,
|
||||||
|
|
@ -519,39 +516,6 @@ impl TestFixture {
|
||||||
(output, self.testwl.last_created_output())
|
(output, self.testwl.last_created_output())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enable_fractional_scale(&mut self) -> TestObject<WpFractionalScaleManagerV1> {
|
|
||||||
self.testwl.enable_fractional_scale();
|
|
||||||
self.run();
|
|
||||||
self.run();
|
|
||||||
|
|
||||||
let mut events = std::mem::take(&mut *self.registry.data.events.lock().unwrap());
|
|
||||||
assert_eq!(
|
|
||||||
events.len(),
|
|
||||||
1,
|
|
||||||
"Unexpected number of global events after enabling fractional scale"
|
|
||||||
);
|
|
||||||
let event = events.pop().unwrap();
|
|
||||||
let Ev::<WlRegistry>::Global {
|
|
||||||
name,
|
|
||||||
interface,
|
|
||||||
version,
|
|
||||||
} = event
|
|
||||||
else {
|
|
||||||
panic!("Unexpected event: {event:?}");
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_eq!(interface, WpFractionalScaleManagerV1::interface().name);
|
|
||||||
let man = TestObject::<WpFractionalScaleManagerV1>::from_request(
|
|
||||||
&self.registry.obj,
|
|
||||||
Req::<WlRegistry>::Bind {
|
|
||||||
name,
|
|
||||||
id: (WpFractionalScaleManagerV1::interface(), version),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
self.run();
|
|
||||||
man
|
|
||||||
}
|
|
||||||
|
|
||||||
fn enable_xdg_output(&mut self) -> TestObject<ZxdgOutputManagerV1> {
|
fn enable_xdg_output(&mut self) -> TestObject<ZxdgOutputManagerV1> {
|
||||||
self.testwl.enable_xdg_output_manager();
|
self.testwl.enable_xdg_output_manager();
|
||||||
self.run();
|
self.run();
|
||||||
|
|
@ -2055,7 +2019,6 @@ fn scaled_output_small_popup() {
|
||||||
.y(50)
|
.y(50)
|
||||||
.width(1)
|
.width(1)
|
||||||
.height(1)
|
.height(1)
|
||||||
.scale(2)
|
|
||||||
.check_size_and_pos(false);
|
.check_size_and_pos(false);
|
||||||
|
|
||||||
let (_, popup_id) = f.create_popup(&comp, builder);
|
let (_, popup_id) = f.create_popup(&comp, builder);
|
||||||
|
|
@ -2068,6 +2031,50 @@ fn scaled_output_small_popup() {
|
||||||
assert!(dims.height > 0);
|
assert!(dims.height > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fractional_scale_small_popup() {
|
||||||
|
let mut f = TestFixture::new_pre_connect(|testwl| {
|
||||||
|
testwl.enable_fractional_scale();
|
||||||
|
});
|
||||||
|
let comp = f.compositor();
|
||||||
|
|
||||||
|
let toplevel = unsafe { Window::new(1) };
|
||||||
|
let (_, toplevel_id) = f.create_toplevel(&comp, toplevel);
|
||||||
|
let data = f.testwl.get_surface_data(toplevel_id).unwrap();
|
||||||
|
let fractional = data
|
||||||
|
.fractional
|
||||||
|
.as_ref()
|
||||||
|
.expect("Missing fracitonal scale data");
|
||||||
|
fractional.preferred_scale(180); // 1.5 scale
|
||||||
|
f.run();
|
||||||
|
f.run();
|
||||||
|
|
||||||
|
{
|
||||||
|
let data = f.testwl.get_surface_data(toplevel_id).unwrap();
|
||||||
|
let viewport = data.viewport.as_ref().expect("Missing viewport");
|
||||||
|
assert_eq!(viewport.width, 66);
|
||||||
|
assert_eq!(viewport.height, 66);
|
||||||
|
}
|
||||||
|
|
||||||
|
let popup = unsafe { Window::new(2) };
|
||||||
|
let builder = PopupBuilder::new(popup, toplevel, toplevel_id)
|
||||||
|
.width(1)
|
||||||
|
.height(1)
|
||||||
|
.check_size_and_pos(false);
|
||||||
|
|
||||||
|
let (_, popup_id) = f.create_popup(&comp, builder);
|
||||||
|
let dims = f.connection().window(popup).dims;
|
||||||
|
assert!(dims.width > 0);
|
||||||
|
assert!(dims.height > 0);
|
||||||
|
|
||||||
|
let data = f
|
||||||
|
.testwl
|
||||||
|
.get_surface_data(popup_id)
|
||||||
|
.expect("Missing popup data");
|
||||||
|
let pos = &data.popup().positioner_state;
|
||||||
|
assert_eq!(pos.size.unwrap(), testwl::Vec2 { x: 1, y: 1 });
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn toplevel_size_limits_scaled() {
|
fn toplevel_size_limits_scaled() {
|
||||||
let (mut f, comp) = TestFixture::new_with_compositor();
|
let (mut f, comp) = TestFixture::new_with_compositor();
|
||||||
|
|
|
||||||
|
|
@ -783,7 +783,8 @@ fn input_focus() {
|
||||||
long_offset: 0,
|
long_offset: 0,
|
||||||
long_length: 1,
|
long_length: 1,
|
||||||
})
|
})
|
||||||
.value::<u32>().first()
|
.value::<u32>()
|
||||||
|
.first()
|
||||||
.and_then(|state| WmState::try_from(*state).ok()),
|
.and_then(|state| WmState::try_from(*state).ok()),
|
||||||
Some(WmState::Normal)
|
Some(WmState::Normal)
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ use wayland_protocols::{
|
||||||
zwp_tablet_v2::ZwpTabletV2,
|
zwp_tablet_v2::ZwpTabletV2,
|
||||||
},
|
},
|
||||||
viewporter::server::{
|
viewporter::server::{
|
||||||
wp_viewport::WpViewport,
|
wp_viewport::{self, WpViewport},
|
||||||
wp_viewporter::{self, WpViewporter},
|
wp_viewporter::{self, WpViewporter},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -85,6 +85,13 @@ pub struct BufferDamage {
|
||||||
pub height: i32,
|
pub height: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub struct Viewport {
|
||||||
|
pub width: i32,
|
||||||
|
pub height: i32,
|
||||||
|
viewport: WpViewport,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct SurfaceData {
|
pub struct SurfaceData {
|
||||||
pub surface: WlSurface,
|
pub surface: WlSurface,
|
||||||
|
|
@ -93,6 +100,7 @@ pub struct SurfaceData {
|
||||||
pub role: Option<SurfaceRole>,
|
pub role: Option<SurfaceRole>,
|
||||||
pub last_enter_serial: Option<u32>,
|
pub last_enter_serial: Option<u32>,
|
||||||
pub fractional: Option<WpFractionalScaleV1>,
|
pub fractional: Option<WpFractionalScaleV1>,
|
||||||
|
pub viewport: Option<Viewport>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SurfaceData {
|
impl SurfaceData {
|
||||||
|
|
@ -1519,6 +1527,7 @@ impl Dispatch<WlCompositor, ()> for State {
|
||||||
role: None,
|
role: None,
|
||||||
last_enter_serial: None,
|
last_enter_serial: None,
|
||||||
fractional: None,
|
fractional: None,
|
||||||
|
viewport: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
state.last_surface_id = Some(SurfaceId(id));
|
state.last_surface_id = Some(SurfaceId(id));
|
||||||
|
|
@ -1828,7 +1837,7 @@ impl Dispatch<ZxdgToplevelDecorationV1, SurfaceId> for State {
|
||||||
|
|
||||||
impl Dispatch<WpViewporter, ()> for State {
|
impl Dispatch<WpViewporter, ()> for State {
|
||||||
fn request(
|
fn request(
|
||||||
_: &mut Self,
|
state: &mut Self,
|
||||||
_: &Client,
|
_: &Client,
|
||||||
_: &WpViewporter,
|
_: &WpViewporter,
|
||||||
request: <WpViewporter as Resource>::Request,
|
request: <WpViewporter as Resource>::Request,
|
||||||
|
|
@ -1837,8 +1846,18 @@ impl Dispatch<WpViewporter, ()> for State {
|
||||||
data_init: &mut wayland_server::DataInit<'_, Self>,
|
data_init: &mut wayland_server::DataInit<'_, Self>,
|
||||||
) {
|
) {
|
||||||
match request {
|
match request {
|
||||||
wp_viewporter::Request::GetViewport { surface: _, id } => {
|
wp_viewporter::Request::GetViewport { surface, id } => {
|
||||||
data_init.init(id, ());
|
let surface_id = SurfaceId(surface.id().protocol_id());
|
||||||
|
let viewport = data_init.init(id, surface_id);
|
||||||
|
state
|
||||||
|
.surfaces
|
||||||
|
.get_mut(&surface_id)
|
||||||
|
.expect("Unknown surface")
|
||||||
|
.viewport = Some(Viewport {
|
||||||
|
viewport,
|
||||||
|
width: -1,
|
||||||
|
height: -1,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
wp_viewporter::Request::Destroy => {}
|
wp_viewporter::Request::Destroy => {}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
@ -1846,17 +1865,41 @@ impl Dispatch<WpViewporter, ()> for State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dispatch<WpViewport, ()> for State {
|
impl Dispatch<WpViewport, SurfaceId> for State {
|
||||||
fn request(
|
fn request(
|
||||||
_: &mut Self,
|
state: &mut Self,
|
||||||
_: &Client,
|
_: &Client,
|
||||||
_: &WpViewport,
|
viewport: &WpViewport,
|
||||||
_: <WpViewport as Resource>::Request,
|
request: <WpViewport as Resource>::Request,
|
||||||
_: &(),
|
surface_id: &SurfaceId,
|
||||||
_: &DisplayHandle,
|
_: &DisplayHandle,
|
||||||
_: &mut wayland_server::DataInit<'_, Self>,
|
_: &mut wayland_server::DataInit<'_, Self>,
|
||||||
) {
|
) {
|
||||||
//todo!()
|
match request {
|
||||||
|
wp_viewport::Request::SetDestination { width, height } => {
|
||||||
|
if width == 0 || width < -1 || height == 0 || height < -1 {
|
||||||
|
panic!(
|
||||||
|
"Bad viewport width/height ({width}x{height}) - {}",
|
||||||
|
viewport.id()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let viewport = state
|
||||||
|
.surfaces
|
||||||
|
.get_mut(surface_id)
|
||||||
|
.unwrap_or_else(|| panic!("Missing surface id {surface_id:?}"))
|
||||||
|
.viewport
|
||||||
|
.as_mut()
|
||||||
|
.unwrap();
|
||||||
|
viewport.width = width;
|
||||||
|
viewport.height = height;
|
||||||
|
}
|
||||||
|
wp_viewport::Request::Destroy => {
|
||||||
|
if let Some(surface) = state.surfaces.get_mut(surface_id) {
|
||||||
|
surface.viewport.take();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unimplemented!("{request:?}"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue