Skip to content

Commit 07a1135

Browse files
committed
fix: fractional scaling
1 parent 63b388d commit 07a1135

7 files changed

Lines changed: 95 additions & 38 deletions

File tree

examples/sctk_lazy/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use std::hash::Hash;
1414

1515
pub fn main() -> iced::Result {
1616
let mut initial_surface = SctkLayerSurfaceSettings::default();
17-
initial_surface.keyboard_interactivity = KeyboardInteractivity::OnDemand;
17+
initial_surface.keyboard_interactivity = KeyboardInteractivity::None;
1818
initial_surface.size_limits = Limits::NONE
1919
.min_width(1.0)
2020
.min_height(1.0)

sctk/src/application.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ where
446446
SctkEvent::WindowEvent { variant, id } => match variant {
447447
crate::sctk_event::WindowEventVariant::Created(id, native_id) => {
448448
surface_ids.insert(id, SurfaceIdWrapper::Window(native_id));
449+
states.insert(native_id, State::new(&application, SurfaceIdWrapper::Window(native_id)));
449450
}
450451
crate::sctk_event::WindowEventVariant::Close => {
451452
if let Some(surface_id) = surface_ids.remove(&id.id()) {
@@ -485,8 +486,9 @@ where
485486
wrapper
486487
});
487488
if first {
488-
let state = State::new(&application, *id);
489-
489+
let Some(state) = states.get(&id.inner()) else {
490+
continue;
491+
};
490492
let user_interface = build_user_interface(
491493
&application,
492494
user_interface::Cache::default(),
@@ -498,7 +500,6 @@ where
498500
&mut auto_size_surfaces,
499501
&mut ev_proxy
500502
);
501-
states.insert(id.inner(), state);
502503
interfaces.insert(id.inner(), user_interface);
503504
}
504505
if let Some(state) = states.get_mut(&id.inner()) {
@@ -518,6 +519,8 @@ where
518519
SctkEvent::LayerSurfaceEvent { variant, id } => match variant {
519520
LayerSurfaceEventVariant::Created(id, native_id) => {
520521
surface_ids.insert(id, SurfaceIdWrapper::LayerSurface(native_id));
522+
states.insert(native_id, State::new(&application, SurfaceIdWrapper::LayerSurface(native_id)));
523+
521524
}
522525
LayerSurfaceEventVariant::Done => {
523526
if let Some(surface_id) = surface_ids.remove(&id.id()) {
@@ -552,8 +555,9 @@ where
552555
wrapper
553556
});
554557
if first {
555-
let state = State::new(&application, *id);
556-
558+
let Some(state) = states.get(&id.inner()) else {
559+
continue;
560+
};
557561
let user_interface = build_user_interface(
558562
&application,
559563
user_interface::Cache::default(),
@@ -565,7 +569,6 @@ where
565569
&mut auto_size_surfaces,
566570
&mut ev_proxy
567571
);
568-
states.insert(id.inner(), state);
569572
interfaces.insert(id.inner(), user_interface);
570573
}
571574
if let Some(state) = states.get_mut(&id.inner()) {
@@ -593,6 +596,8 @@ where
593596
} => match variant {
594597
PopupEventVariant::Created(id, native_id) => {
595598
surface_ids.insert(id, SurfaceIdWrapper::Popup(native_id));
599+
states.insert(native_id, State::new(&application, SurfaceIdWrapper::Popup(native_id)));
600+
596601
}
597602
PopupEventVariant::Done => {
598603
if let Some(surface_id) = surface_ids.remove(&id.id()) {
@@ -618,8 +623,9 @@ where
618623
wrapper
619624
});
620625
if first {
621-
let state = State::new(&application, *id);
622-
626+
let Some(state) = states.get(&id.inner()) else {
627+
continue;
628+
};
623629
let user_interface = build_user_interface(
624630
&application,
625631
user_interface::Cache::default(),
@@ -631,7 +637,6 @@ where
631637
&mut auto_size_surfaces,
632638
&mut ev_proxy
633639
);
634-
states.insert(id.inner(), state);
635640
interfaces.insert(id.inner(), user_interface);
636641
}
637642
if let Some(state) = states.get_mut(&id.inner()) {
@@ -930,9 +935,10 @@ where
930935
has_events || !native_events.is_empty();
931936

932937
let (interface_state, statuses) = {
933-
let user_interface = interfaces
934-
.get_mut(&surface_id.inner())
935-
.unwrap();
938+
let Some(user_interface) = interfaces
939+
.get_mut(&surface_id.inner()) else {
940+
continue;
941+
};
936942
user_interface.update(
937943
native_events.as_slice(),
938944
cursor_position,

sctk/src/event_loop/mod.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::application::SurfaceIdWrapper;
99
use crate::{
1010
application::Event,
1111
conversion,
12+
dpi::LogicalSize,
1213
handlers::{
1314
wp_fractional_scaling::FractionalScalingManager,
1415
wp_viewporter::ViewporterState,
@@ -664,9 +665,7 @@ where
664665
height,
665666
} => {
666667
if let Some(layer_surface) = self.state.layer_surfaces.iter_mut().find(|l| l.id == id) {
667-
layer_surface.requested_size = (width, height);
668-
layer_surface.surface.set_size(width.unwrap_or_default(), height.unwrap_or_default());
669-
668+
layer_surface.set_size(width, height);
670669
pending_redraws.push(layer_surface.surface.wl_surface().id());
671670
}
672671
},
@@ -767,14 +766,15 @@ where
767766
},
768767
platform_specific::wayland::window::Action::Size { id, width, height } => {
769768
if let Some(window) = self.state.windows.iter_mut().find(|w| w.id == id) {
770-
let (width, height) = (NonZeroU32::new(width).unwrap_or(NonZeroU32::new(1).unwrap()), NonZeroU32::new(height).unwrap_or(NonZeroU32::new(1).unwrap()));
771-
window.requested_size = Some((width.get(), height.get()));
772-
window.window.set_window_geometry(0, 0, width.get() as u32, height.get() as u32);
773-
window.current_size = Some((width, height));
769+
window.set_size(LogicalSize::new(NonZeroU32::new(width).unwrap_or(NonZeroU32::new(1).unwrap()), NonZeroU32::new(1).unwrap()));
774770
// TODO Ashley maybe don't force window size?
775771
pending_redraws.push(window.window.wl_surface().id());
776772

777773
if let Some(mut prev_configure) = window.last_configure.clone() {
774+
let (width, height) = (
775+
NonZeroU32::new(width).unwrap_or(NonZeroU32::new(1).unwrap()),
776+
NonZeroU32::new(height).unwrap_or(NonZeroU32::new(1).unwrap()),
777+
);
778778
prev_configure.new_size = (Some(width), Some(height));
779779
sticky_exit_callback(
780780
IcedSctkEvent::SctkEvent(SctkEvent::WindowEvent { variant: WindowEventVariant::Configure(prev_configure, window.window.wl_surface().clone(), false), id: window.window.wl_surface().clone()}),
@@ -980,15 +980,14 @@ where
980980
platform_specific::wayland::popup::Action::Size { id, width, height } => {
981981
if let Some(sctk_popup) = self.state
982982
.popups
983-
.iter()
983+
.iter_mut()
984984
.find(|s| s.data.id == id)
985985
{
986986
// update geometry
987-
sctk_popup.popup.xdg_surface().set_window_geometry(0, 0, width as i32, height as i32);
988987
// update positioner
989988
self.state.token_ctr += 1;
990-
sctk_popup.data.positioner.set_size(width as i32, height as i32);
991-
sctk_popup.popup.reposition(&sctk_popup.data.positioner, self.state.token_ctr);
989+
sctk_popup.set_size(width, height, self.state.token_ctr);
990+
992991
pending_redraws.push(sctk_popup.popup.wl_surface().id());
993992

994993
sticky_exit_callback(IcedSctkEvent::SctkEvent(SctkEvent::PopupEvent {

sctk/src/event_loop/state.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,32 @@ pub struct SctkWindow<T> {
110110
pub(crate) wp_viewport: Option<WpViewport>,
111111
}
112112

113+
impl<T> SctkWindow<T> {
114+
pub(crate) fn set_size(&mut self, logical_size: LogicalSize<NonZeroU32>) {
115+
self.requested_size =
116+
Some((logical_size.width.get(), logical_size.height.get()));
117+
self.update_size(logical_size)
118+
}
119+
120+
pub(crate) fn update_size(
121+
&mut self,
122+
LogicalSize { width, height }: LogicalSize<NonZeroU32>,
123+
) {
124+
self.window.set_window_geometry(
125+
0,
126+
0,
127+
width.get() as u32,
128+
height.get() as u32,
129+
);
130+
self.current_size = Some((width, height));
131+
// Update the target viewport, this is used if and only if fractional scaling is in use.
132+
if let Some(viewport) = self.wp_viewport.as_ref() {
133+
// Set inner size without the borders.
134+
viewport.set_destination(width.get() as _, height.get() as _);
135+
}
136+
}
137+
}
138+
113139
#[derive(Debug, Clone)]
114140
pub struct SctkLayerSurface<T> {
115141
pub(crate) id: window::Id,
@@ -129,6 +155,23 @@ pub struct SctkLayerSurface<T> {
129155
pub(crate) wp_viewport: Option<WpViewport>,
130156
}
131157

158+
impl<T> SctkLayerSurface<T> {
159+
pub(crate) fn set_size(&mut self, w: Option<u32>, h: Option<u32>) {
160+
self.requested_size = (w, h);
161+
162+
let (w, h) = (w.unwrap_or_default(), h.unwrap_or_default());
163+
self.surface.set_size(w, h);
164+
}
165+
166+
pub(crate) fn update_viewport(&mut self, w: u32, h: u32) {
167+
self.current_size = Some(LogicalSize::new(w, h));
168+
if let Some(viewport) = self.wp_viewport.as_ref() {
169+
// Set inner size without the borders.
170+
viewport.set_destination(w as i32, h as i32);
171+
}
172+
}
173+
}
174+
132175
#[derive(Debug, Clone)]
133176
pub enum SctkSurface {
134177
LayerSurface(WlSurface),
@@ -159,6 +202,18 @@ pub struct SctkPopup<T> {
159202
pub(crate) wp_viewport: Option<WpViewport>,
160203
}
161204

205+
impl<T> SctkPopup<T> {
206+
pub(crate) fn set_size(&mut self, w: u32, h: u32, token: u32) {
207+
// update geometry
208+
self.popup
209+
.xdg_surface()
210+
.set_window_geometry(0, 0, w as i32, h as i32);
211+
// update positioner
212+
self.data.positioner.set_size(w as i32, h as i32);
213+
self.popup.reposition(&self.data.positioner, token);
214+
}
215+
}
216+
162217
pub struct Dnd<T> {
163218
pub(crate) origin_id: window::Id,
164219
pub(crate) origin: WlSurface,
@@ -544,7 +599,10 @@ where
544599
wl_surface.commit();
545600

546601
let wp_viewport = self.viewporter_state.as_ref().map(|state| {
547-
state.get_viewport(popup.wl_surface(), &self.queue_handle)
602+
let viewport =
603+
state.get_viewport(popup.wl_surface(), &self.queue_handle);
604+
viewport.set_destination(size.0 as i32, size.1 as i32);
605+
viewport
548606
});
549607
let wp_fractional_scale =
550608
self.fractional_scaling_manager.as_ref().map(|fsm| {

sctk/src/handlers/shell/layer.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,7 @@ impl<T: Debug> LayerShellHandler for SctkState<T> {
6161
configure.new_size.1.max(1)
6262
};
6363

64-
layer.current_size.replace(LogicalSize::new(
65-
configure.new_size.0,
66-
configure.new_size.1,
67-
));
64+
layer.update_viewport(configure.new_size.0, configure.new_size.1);
6865
let first = layer.last_configure.is_none();
6966
layer.last_configure.replace(configure.clone());
7067

sctk/src/handlers/shell/xdg_window.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::{
2+
dpi::LogicalSize,
23
event_loop::state::SctkState,
34
sctk_event::{SctkEvent, WindowEventVariant},
45
};
@@ -67,18 +68,15 @@ impl<T: Debug> WindowHandler for SctkState<T> {
6768
.unwrap_or_else(|| NonZeroU32::new(500).unwrap()),
6869
);
6970
}
70-
window.current_size = configure
71+
configure
7172
.new_size
7273
.0
7374
.zip(configure.new_size.1)
7475
.map(|new_size| {
75-
window.window.set_window_geometry(
76-
0,
77-
0,
78-
new_size.0.get(),
79-
new_size.1.get(),
80-
);
81-
new_size
76+
window.update_size(LogicalSize {
77+
width: new_size.0,
78+
height: new_size.1,
79+
});
8280
});
8381

8482
let wl_surface = window.window.wl_surface();

winit/src/application.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,6 @@ async fn run_instance<A, E, C>(
681681
mouse_interaction = new_mouse_interaction;
682682
}
683683
debug.draw_finished();
684-
685684
compositor.configure_surface(
686685
&mut surface,
687686
physical_size.width,

0 commit comments

Comments
 (0)