Merge branch 'fit-layout-to-panel' into 'main'

scaling: Let layouts stretch to fill the panel

See merge request World/Phosh/squeekboard!702
This commit is contained in:
Marge Bot
2024-11-14 15:43:05 +00:00
4 changed files with 124 additions and 36 deletions

View File

@ -106,8 +106,14 @@ You can change the height of the panel for the keyboard with:
$ gsettings set sm.puri.Squeekboard scale-in-horizontal-screen-orientation 1.0 $ gsettings set sm.puri.Squeekboard scale-in-horizontal-screen-orientation 1.0
$ gsettings set sm.puri.Squeekboard scale-in-vertical-screen-orientation 1.0 $ gsettings set sm.puri.Squeekboard scale-in-vertical-screen-orientation 1.0
``` ```
and wether or not layouts will stretch to fit the panel with:
Note: If the keyboard is open when the settings for the panel-height are changed, the height of the keyboard will not change until it is opened again, or the layout is changed. ```sh
$ gsettings set sm.puri.Squeekboard layout-shape-changes-to-fit-panel true
$ gsettings set sm.puri.Squeekboard layout-shape-changes-to-fit-panel false
```
Note: If the keyboard is open when the settings are changed, the changes will not be visible until the keyboard is opened again, or the layout is changed.
While using Phosh, you can long-click/long-tap the home-bar at the bottom, to open and close the keyboard. While using Phosh, you can long-click/long-tap the home-bar at the bottom, to open and close the keyboard.
To reset the settings to the default, you can use: To reset the settings to the default, you can use:

View File

@ -27,6 +27,15 @@
For square screens, the setting for screens in landscape-orientation is used. For square screens, the setting for screens in landscape-orientation is used.
</description> </description>
</key> </key>
<key name='layout-shape-changes-to-fit-panel' type='b'>
<default>true</default>
<summary>Wether layouts will stretch to fit the panel or not</summary>
<description>
While this setting is active, the proportions of layouts can change,
to fit the available space on the panel.
It can be useful to deactivate this while designing layouts.
</description>
</key>
</schema> </schema>
</schemalist> </schemalist>

View File

@ -67,9 +67,18 @@ scale = 1.00
### Layout-stretching ### Layout-stretching
Squeekboard may slightly stretch layouts horizontally (up to 5.5%) before showing them. Layouts will adjust their proportions to fit the available space on a panel.
For creating layouts with precise sizes, it can be useful to disable this. For creating layouts with precise sizes, it can be useful to deactivate this with:
This can be done by changing the value `1.055` in the line `let scale_x = if (h_scale / v_scale) < 1.055 { h_scale } else { v_scale };` of the `calculate_transformation` function in `src/layout.rs` to `1.0`, before building Squeekboard.
```
$ gsettings set sm.puri.Squeekboard layout-shape-changes-to-fit-panel false
```
It can be activated again with:
```
$ gsettings set sm.puri.Squeekboard layout-shape-changes-to-fit-panel true
```
Layout syntax Layout syntax
------------- -------------

View File

@ -17,6 +17,8 @@
* and let the renderer scale and center it within the widget. * and let the renderer scale and center it within the widget.
*/ */
use gdk::prelude::SettingsExt;
use gio::Settings;
use std::cmp; use std::cmp;
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::CString; use std::ffi::CString;
@ -809,17 +811,39 @@ impl LayoutData {
&self, &self,
available: Size, available: Size,
) -> c::Transformation { ) -> c::Transformation {
let gsettings = Settings::new("sm.puri.Squeekboard");
let stretch_layout_to_fit_panel = gsettings.boolean ("layout-shape-changes-to-fit-panel");
let layout_stretching_limit: f64;
if stretch_layout_to_fit_panel == true {
// The "Base"-layout-shape is intended for use on small displays,
// and thus should fill the available space.
if self.kind == ArrangementKind::Base { layout_stretching_limit = 5.0 }
// The "Wide"-layout-shape is also used on monitors,
// and thus should not stretch more than necessary.
else { layout_stretching_limit = 1.4 }
}
else { layout_stretching_limit = 1.0 }
let size = self.calculate_size(); let size = self.calculate_size();
let h_scale = available.width / size.width; let h_scale = available.width / size.width;
let v_scale = available.height / size.height; let v_scale = available.height / size.height;
// Allow up to 5% (and a bit more) horizontal stretching for filling up available space // Stretch layouts to fill available space, up to some reasonable limits.
let scale_x = if (h_scale / v_scale) < 1.055 { h_scale } else { v_scale }; // TODO: On screens that are too large to be held during normal use (such as monitors),
let scale_y = cmp::min(FloatOrd(h_scale), FloatOrd(v_scale)).0; // layouts should probably not stretch to fit the panel.
let scale_x = if stretch_layout_to_fit_panel == true {
if (h_scale / v_scale) <= layout_stretching_limit { h_scale }
else { v_scale }
}
else if h_scale / v_scale < 1.0 { h_scale }
else { v_scale };
let scale_y = if stretch_layout_to_fit_panel == true && h_scale / v_scale > 0.49 { v_scale }
else { cmp::min(FloatOrd(h_scale), FloatOrd(v_scale)).0 };
let outside_margins = c::Transformation { let outside_margins = c::Transformation {
origin_x: (available.width - (scale_x * size.width)) / 2.0, origin_x: (available.width - (scale_x * size.width)) / 2.0,
origin_y: (available.height - (scale_y * size.height)) / 2.0, origin_y: (available.height - (scale_y * size.height)) / 2.0,
scale_x: scale_x, scale_x,
scale_y: scale_y, scale_y,
}; };
outside_margins.chain(c::Transformation { outside_margins.chain(c::Transformation {
origin_x: self.margins.left, origin_x: self.margins.left,
@ -1559,7 +1583,10 @@ mod test {
#[test] #[test]
fn check_bottom_margin() { fn check_bottom_margin() {
// just one button // TODO: This should work correctly independent from the current settings on the system.
let gsettings = Settings::new("sm.puri.Squeekboard");
let stretch_layout_to_fit_panel = gsettings.boolean("layout-shape-changes-to-fit-panel");
// Just one button
let view = View::new(vec![ let view = View::new(vec![
( (
0.0, 0.0,
@ -1595,21 +1622,25 @@ mod test {
layout.calculate_size(), layout.calculate_size(),
Size { width: 1.0, height: 2.0 } Size { width: 1.0, height: 2.0 }
); );
// Don't change those values randomly! // Do not change these values randomly,
// They take advantage of incidental precise float representation // because these are comparable due to incidentally precise float-representation.
// to even be comparable.
let transformation = layout.calculate_transformation( let transformation = layout.calculate_transformation(
Size { width: 2.0, height: 2.0 } Size { width: 2.0, height: 2.0 } // Panel with a size of 2x2 pixels.
); );
assert_eq!(transformation.scale_x, 1.0); let scale_x_comparison = if stretch_layout_to_fit_panel == true { 2.0 } else { 1.0 };
assert_eq!(transformation.scale_y, 1.0); let origin_x_comparison = if stretch_layout_to_fit_panel == true { 0.0 } else { 0.5 };
assert_eq!(transformation.origin_x, 0.5); assert_eq!(transformation.scale_x, scale_x_comparison, "transformation.scale_x changed.");
assert_eq!(transformation.origin_y, 0.0); assert_eq!(transformation.scale_y, 1.0, "transformation.scale_y changed.");
assert_eq!(transformation.origin_x, origin_x_comparison, "transformation.origin_x changed.");
assert_eq!(transformation.origin_y, 0.0, "transformation.origin_y changed.");
} }
#[test] #[test]
fn check_stretching() { fn check_stretching() {
// just one button // TODO: This should work correctly independent from the current settings on the system.
let gsettings = Settings::new("sm.puri.Squeekboard");
let stretch_layout_to_fit_panel = gsettings.boolean("layout-shape-changes-to-fit-panel");
// Just one button
let view = View::new(vec![ let view = View::new(vec![
( (
0.0, 0.0,
@ -1636,25 +1667,58 @@ mod test {
}, },
purpose: ContentPurpose::Normal, purpose: ContentPurpose::Normal,
}; };
// Test that layouts will keep their defined proportions,
// if those fit the panel precisely.
let transformation = layout.calculate_transformation( let transformation = layout.calculate_transformation(
Size { width: 100.0, height: 100.0 } Size { width: 100.0, height: 100.0 }
); );
assert_eq!(transformation.scale_x, 100.0); assert_eq!(transformation.scale_x, 100.0,
assert_eq!(transformation.scale_y, 100.0); "Layout-width changed when it was supposed to not change.");
assert_eq!(transformation.scale_y, 100.0,
"Layout-height changed when it was supposed to not change.");
// Test that layouts will keep their defined proportions when their size decreases,
// if layout-stretching is off.
if stretch_layout_to_fit_panel == false {
let transformation = layout.calculate_transformation( let transformation = layout.calculate_transformation(
Size { width: 95.0, height: 100.0 } Size { width: 95.0, height: 100.0 }
); );
assert_eq!(transformation.scale_x, 95.0); assert_eq!(transformation.scale_x, 95.0,
assert_eq!(transformation.scale_y, 95.0); "Layout-width did not decrease by the expected amount.");
assert_eq!(transformation.scale_y, 95.0,
"Layout-height did not decrease by the expected amount.");
}
// Test that layouts adjust to the panel-size, if layout-stretching is on.
if stretch_layout_to_fit_panel == true {
let transformation = layout.calculate_transformation( let transformation = layout.calculate_transformation(
Size { width: 105.0, height: 100.0 } Size { width: 500.0, height: 100.0 }
); );
assert_eq!(transformation.scale_x, 105.0); assert_eq!(transformation.scale_x, 500.0,
assert_eq!(transformation.scale_y, 100.0); "Layout-width did not increase by the expected amount.");
assert_eq!(transformation.scale_y, 100.0,
"Layout-height changed when it was supposed to not change.");
let transformation = layout.calculate_transformation( let transformation = layout.calculate_transformation(
Size { width: 106.0, height: 100.0 } Size { width: 100.0, height: 204.0 }
); );
assert_eq!(transformation.scale_x, 100.0); assert_eq!(transformation.scale_x, 100.0,
assert_eq!(transformation.scale_y, 100.0); "Layout-width changed when it was supposed to not change.");
assert_eq!(transformation.scale_y, 204.0,
"Layout-height did not increase by the expected amount.");
// Test that layouts will keep their defined proportions,
// if those cannot reach the borders of the screen without stretching by more than the limit.
let transformation = layout.calculate_transformation(
Size { width: 501.0, height: 100.0 }
);
assert_eq!(transformation.scale_x, 100.0,
"Layout-width changed when it was supposed to not change.");
assert_eq!(transformation.scale_y, 100.0,
"Layout-height changed when it was supposed to not change.");
let transformation = layout.calculate_transformation(
Size { width: 100.0, height: 205.0 }
);
assert_eq!(transformation.scale_x, 100.0,
"Layout-width changed when it was supposed to not change.");
assert_eq!(transformation.scale_y, 100.0,
"Layout-height changed when it was supposed to not change.");
}
} }
} }