mirror of
https://codeberg.org/waydeer/layer-shika.git
synced 2025-10-29 14:24:23 +00:00
fix: fractional scaling on popup
This commit is contained in:
parent
4ea4171eb7
commit
b14cb51f86
5 changed files with 88 additions and 11 deletions
|
|
@ -72,6 +72,23 @@ impl PopupSurface {
|
||||||
Rc::new(vp.get_viewport(&surface, params.queue_handle, ()))
|
Rc::new(vp.get_viewport(&surface, params.queue_handle, ()))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#[allow(clippy::cast_possible_wrap)]
|
||||||
|
#[allow(clippy::cast_precision_loss)]
|
||||||
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
|
if let Some(ref vp) = viewport {
|
||||||
|
let logical_width = (params.size.width as f32 / params.scale_factor) as i32;
|
||||||
|
let logical_height = (params.size.height as f32 / params.scale_factor) as i32;
|
||||||
|
info!(
|
||||||
|
"Setting viewport destination to logical size: {}x{} (physical: {}x{}, scale: {})",
|
||||||
|
logical_width,
|
||||||
|
logical_height,
|
||||||
|
params.size.width,
|
||||||
|
params.size.height,
|
||||||
|
params.scale_factor
|
||||||
|
);
|
||||||
|
vp.set_destination(logical_width, logical_height);
|
||||||
|
}
|
||||||
|
|
||||||
surface.set_buffer_scale(1);
|
surface.set_buffer_scale(1);
|
||||||
surface.commit();
|
surface.commit();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,30 +57,44 @@ struct ActivePopup {
|
||||||
pub struct PopupManager {
|
pub struct PopupManager {
|
||||||
context: PopupContext,
|
context: PopupContext,
|
||||||
popups: RefCell<Vec<ActivePopup>>,
|
popups: RefCell<Vec<ActivePopup>>,
|
||||||
|
current_scale_factor: RefCell<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PopupManager {
|
impl PopupManager {
|
||||||
pub const fn new(context: PopupContext) -> Self {
|
pub const fn new(context: PopupContext, initial_scale_factor: f32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
context,
|
context,
|
||||||
popups: RefCell::new(Vec::new()),
|
popups: RefCell::new(Vec::new()),
|
||||||
|
current_scale_factor: RefCell::new(initial_scale_factor),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_scale_factor(&self, scale_factor: f32) {
|
||||||
|
*self.current_scale_factor.borrow_mut() = scale_factor;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_popup(
|
pub fn create_popup(
|
||||||
&self,
|
&self,
|
||||||
queue_handle: &QueueHandle<WindowState>,
|
queue_handle: &QueueHandle<WindowState>,
|
||||||
parent_layer_surface: &ZwlrLayerSurfaceV1,
|
parent_layer_surface: &ZwlrLayerSurfaceV1,
|
||||||
last_pointer_serial: u32,
|
last_pointer_serial: u32,
|
||||||
scale_factor: f32,
|
|
||||||
) -> Result<Rc<PopupWindow>> {
|
) -> Result<Rc<PopupWindow>> {
|
||||||
let xdg_wm_base = self.context.xdg_wm_base.as_ref().ok_or_else(|| {
|
let xdg_wm_base = self.context.xdg_wm_base.as_ref().ok_or_else(|| {
|
||||||
LayerShikaError::WaylandProtocol("xdg-shell not available for popups".into())
|
LayerShikaError::WaylandProtocol("xdg-shell not available for popups".into())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
info!("Creating popup window");
|
let scale_factor = *self.current_scale_factor.borrow();
|
||||||
|
info!("Creating popup window with scale factor {scale_factor}");
|
||||||
|
|
||||||
let popup_size = PhysicalSize::new(360, 524);
|
let logical_size = slint::LogicalSize::new(360.0, 524.0);
|
||||||
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
|
#[allow(clippy::cast_sign_loss)]
|
||||||
|
let popup_size = PhysicalSize::new(
|
||||||
|
(logical_size.width * scale_factor) as u32,
|
||||||
|
(logical_size.height * scale_factor) as u32,
|
||||||
|
);
|
||||||
|
|
||||||
|
info!("Popup logical size: {logical_size:?}, physical size: {popup_size:?}");
|
||||||
|
|
||||||
let popup_surface = PopupSurface::create(&super::popup::PopupSurfaceParams {
|
let popup_surface = PopupSurface::create(&super::popup::PopupSurfaceParams {
|
||||||
compositor: &self.context.compositor,
|
compositor: &self.context.compositor,
|
||||||
|
|
@ -107,8 +121,8 @@ impl PopupManager {
|
||||||
.map_err(|e| LayerShikaError::FemtoVGRendererCreation(e.to_string()))?;
|
.map_err(|e| LayerShikaError::FemtoVGRendererCreation(e.to_string()))?;
|
||||||
|
|
||||||
let popup_window = PopupWindow::new(renderer);
|
let popup_window = PopupWindow::new(renderer);
|
||||||
popup_window.set_size(WindowSize::Physical(popup_size));
|
|
||||||
popup_window.set_scale_factor(scale_factor);
|
popup_window.set_scale_factor(scale_factor);
|
||||||
|
popup_window.set_size(WindowSize::Logical(logical_size));
|
||||||
|
|
||||||
info!("Popup window created successfully");
|
info!("Popup window created successfully");
|
||||||
|
|
||||||
|
|
@ -151,6 +165,20 @@ impl PopupManager {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn find_popup_index_by_fractional_scale_id(
|
||||||
|
&self,
|
||||||
|
fractional_scale_id: &ObjectId,
|
||||||
|
) -> Option<usize> {
|
||||||
|
for (index, popup) in self.popups.borrow().iter().enumerate() {
|
||||||
|
if let Some(ref fs) = popup.surface.fractional_scale {
|
||||||
|
if fs.id() == *fractional_scale_id {
|
||||||
|
return Some(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_popup_window(&self, index: usize) -> Option<Rc<PopupWindow>> {
|
pub fn get_popup_window(&self, index: usize) -> Option<Rc<PopupWindow>> {
|
||||||
self.popups
|
self.popups
|
||||||
.borrow()
|
.borrow()
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,7 @@ impl Dispatch<WlPointer, ()> for WindowState {
|
||||||
impl Dispatch<WpFractionalScaleV1, ()> for WindowState {
|
impl Dispatch<WpFractionalScaleV1, ()> for WindowState {
|
||||||
fn event(
|
fn event(
|
||||||
state: &mut Self,
|
state: &mut Self,
|
||||||
_proxy: &WpFractionalScaleV1,
|
proxy: &WpFractionalScaleV1,
|
||||||
event: wp_fractional_scale_v1::Event,
|
event: wp_fractional_scale_v1::Event,
|
||||||
_data: &(),
|
_data: &(),
|
||||||
_conn: &Connection,
|
_conn: &Connection,
|
||||||
|
|
@ -228,7 +228,7 @@ impl Dispatch<WpFractionalScaleV1, ()> for WindowState {
|
||||||
#[allow(clippy::cast_precision_loss)]
|
#[allow(clippy::cast_precision_loss)]
|
||||||
let scale_float = scale as f32 / 120.0;
|
let scale_float = scale as f32 / 120.0;
|
||||||
info!("Fractional scale received: {scale_float} ({scale}x)");
|
info!("Fractional scale received: {scale_float} ({scale}x)");
|
||||||
state.update_scale_factor(scale);
|
state.update_scale_for_fractional_scale_object(proxy, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use slint::platform::{WindowAdapter, WindowEvent};
|
||||||
use slint_interpreter::ComponentInstance;
|
use slint_interpreter::ComponentInstance;
|
||||||
use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;
|
use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;
|
||||||
use wayland_client::{protocol::{wl_output::WlOutput, wl_surface::WlSurface}, Proxy};
|
use wayland_client::{protocol::{wl_output::WlOutput, wl_surface::WlSurface}, Proxy};
|
||||||
|
use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1;
|
||||||
use crate::rendering::femtovg_window::FemtoVGWindow;
|
use crate::rendering::femtovg_window::FemtoVGWindow;
|
||||||
use crate::errors::{LayerShikaError, Result};
|
use crate::errors::{LayerShikaError, Result};
|
||||||
use crate::windowing::surface_dimensions::SurfaceDimensions;
|
use crate::windowing::surface_dimensions::SurfaceDimensions;
|
||||||
|
|
@ -269,6 +270,10 @@ impl WindowState {
|
||||||
);
|
);
|
||||||
self.scale_factor = new_scale_factor;
|
self.scale_factor = new_scale_factor;
|
||||||
|
|
||||||
|
if let Some(popup_manager) = &self.popup_manager {
|
||||||
|
popup_manager.update_scale_factor(new_scale_factor);
|
||||||
|
}
|
||||||
|
|
||||||
let current_logical_size = self.logical_size;
|
let current_logical_size = self.logical_size;
|
||||||
if current_logical_size.width > 0 && current_logical_size.height > 0 {
|
if current_logical_size.width > 0 && current_logical_size.height > 0 {
|
||||||
self.update_size(current_logical_size.width, current_logical_size.height);
|
self.update_size(current_logical_size.width, current_logical_size.height);
|
||||||
|
|
@ -324,4 +329,33 @@ impl WindowState {
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::cast_precision_loss)]
|
||||||
|
pub fn update_scale_for_fractional_scale_object(
|
||||||
|
&mut self,
|
||||||
|
fractional_scale_proxy: &WpFractionalScaleV1,
|
||||||
|
scale_120ths: u32,
|
||||||
|
) {
|
||||||
|
let fractional_scale_id = fractional_scale_proxy.id();
|
||||||
|
|
||||||
|
if let Some(ref main_fractional_scale) = self.fractional_scale {
|
||||||
|
if (**main_fractional_scale.inner()).id() == fractional_scale_id {
|
||||||
|
self.update_scale_factor(scale_120ths);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(popup_manager) = &self.popup_manager {
|
||||||
|
if let Some(popup_index) =
|
||||||
|
popup_manager.find_popup_index_by_fractional_scale_id(&fractional_scale_id)
|
||||||
|
{
|
||||||
|
if let Some(popup_window) = popup_manager.get_popup_window(popup_index) {
|
||||||
|
let new_scale_factor = scale_120ths as f32 / 120.0;
|
||||||
|
info!("Updating popup scale factor to {new_scale_factor} ({scale_120ths}x)");
|
||||||
|
popup_window.set_scale_factor(new_scale_factor);
|
||||||
|
popup_window.request_redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ impl WindowingSystem {
|
||||||
Rc::clone(&connection),
|
Rc::clone(&connection),
|
||||||
);
|
);
|
||||||
|
|
||||||
let popup_manager = Rc::new(PopupManager::new(popup_context));
|
let popup_manager = Rc::new(PopupManager::new(popup_context, state.scale_factor()));
|
||||||
|
|
||||||
Self::setup_popup_creator(&popup_manager, &platform, &state, &event_queue);
|
Self::setup_popup_creator(&popup_manager, &platform, &state, &event_queue);
|
||||||
|
|
||||||
|
|
@ -156,14 +156,12 @@ impl WindowingSystem {
|
||||||
let popup_manager_clone = Rc::clone(popup_manager);
|
let popup_manager_clone = Rc::clone(popup_manager);
|
||||||
let layer_surface = state.layer_surface();
|
let layer_surface = state.layer_surface();
|
||||||
let queue_handle = event_queue.handle();
|
let queue_handle = event_queue.handle();
|
||||||
let scale_factor = state.scale_factor();
|
|
||||||
let last_serial = state.last_pointer_serial();
|
|
||||||
|
|
||||||
platform.set_popup_creator(move || {
|
platform.set_popup_creator(move || {
|
||||||
info!("Popup creator called! Creating popup window...");
|
info!("Popup creator called! Creating popup window...");
|
||||||
|
|
||||||
let result = popup_manager_clone
|
let result = popup_manager_clone
|
||||||
.create_popup(&queue_handle, &layer_surface, last_serial, scale_factor)
|
.create_popup(&queue_handle, &layer_surface, 0)
|
||||||
.map(|w| w as Rc<dyn WindowAdapter>)
|
.map(|w| w as Rc<dyn WindowAdapter>)
|
||||||
.map_err(|e| PlatformError::Other(format!("Failed to create popup: {e}")));
|
.map_err(|e| PlatformError::Other(format!("Failed to create popup: {e}")));
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue