Compare commits

...

13 Commits

Author SHA1 Message Date
1fac218c70 Release 1.22.0 "Superposition"
New or updated translations:
- Basque

Changes:
- fixed panel sizing when scaling
- fixed panel sizing when rotating
- fixed Dvorak terminal layout
2023-04-01 13:50:31 +00:00
01bde740bb Update deps 2023-04-01 13:45:25 +00:00
dcz
ef516c2082 Merge branch 'size' into 'master'
Fix panel sizing

See merge request World/Phosh/squeekboard!594
2023-03-22 16:21:20 +00:00
dcz
fe39632303 Merge branch 'dbg' into 'master'
cleanup: Remove debug prints

See merge request World/Phosh/squeekboard!593
2023-03-22 16:21:03 +00:00
dcz
e94619883b Merge branch 'master' into 'master'
layout: fix uppercase dvorak terminal mode

Closes #367

See merge request World/Phosh/squeekboard!595
2023-03-20 09:14:13 +00:00
af09304835 layout: fix uppercase dvorak terminal mode
These were left lowercase for some reason.
2023-03-20 08:58:13 +00:00
bd96f4c0c2 panel: Fix sizing on output reconfiguration 2023-03-15 15:44:55 +00:00
83fda9d38a tests: Make panel manager modifications pure
This makes testing possible. Test which prompted this is included.
2023-03-15 15:44:55 +00:00
8c89b4dc2c cleanup: Remove debug prints 2023-03-15 12:53:22 +00:00
dcz
b17716a427 Merge branch 'size' into 'master'
state: Make size independent of scaling factor

See merge request World/Phosh/squeekboard!592
2023-03-14 14:01:49 +00:00
367d8dd5c7 state: Make size independent of scaling factor 2023-03-14 12:16:15 +00:00
97371b8dfb Add Basque translation 2023-03-06 20:35:18 +00:00
dcz
6f66edf8a1 Merge branch 'rel' into 'master'
Release 1.21.0

See merge request World/Phosh/squeekboard!591
2023-02-26 09:13:19 +00:00
12 changed files with 382 additions and 114 deletions

63
Cargo.lock generated
View File

@ -108,7 +108,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 1.0.109",
]
[[package]]
@ -129,7 +129,7 @@ checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 1.0.109",
]
[[package]]
@ -325,9 +325,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "indexmap"
version = "1.9.2"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown",
@ -350,9 +350,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.139"
version = "0.2.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
[[package]]
name = "linked-hash-map"
@ -433,18 +433,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.51"
version = "1.0.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [
"proc-macro2",
]
@ -474,9 +474,9 @@ dependencies = [
[[package]]
name = "ryu"
version = "1.0.12"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]]
name = "scoped-tls"
@ -486,33 +486,33 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]]
name = "serde"
version = "1.0.152"
version = "1.0.159"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.152"
version = "1.0.159"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.12",
]
[[package]]
name = "serde_repr"
version = "0.1.10"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e"
checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.12",
]
[[package]]
@ -529,9 +529,20 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.107"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79d9531f94112cfc3e4c8f5f02cb2b58f72c97b7efd85f70203cc6d8efda5927"
dependencies = [
"proc-macro2",
"quote",
@ -558,9 +569,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.6"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]]
name = "unicode-width"
@ -643,7 +654,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
"syn 1.0.109",
]
[[package]]
@ -665,5 +676,5 @@ checksum = "d68726e8c12757384a8d1485080527e263dea67d91f19e97cd71b9292f22d7c5"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 1.0.109",
]

11
NEWS.md
View File

@ -1,3 +1,14 @@
1.22.0 "Superposition"
------------------
New or updated translations:
- Basque
Changes:
- fixed panel sizing when scaling
- fixed panel sizing when rotating
- fixed Dvorak terminal layout
1.21.0 "Expected value"
------------------

View File

@ -17,9 +17,9 @@ views:
- "show_numbers preferences space show_actions Return"
upper:
- "Ctrl Alt PgUp PgDn Home End"
- "Shift_L p y f g c r l BackSpace"
- "a o e u i d h t n s"
- ", q j k x b m w v z"
- "Shift_L P Y F G C R L BackSpace"
- "A O E U I D H T N S"
- ", Q J K X B M W V Z"
- "show_numbers preferences space show_actions Return"
numbers:
- "Ctrl Alt ↑ ↓ ← →"

View File

@ -17,9 +17,9 @@ views:
- "show_numbers preferences space show_actions Return"
upper:
- "EscSmall TabSmall Ctrl Alt PgUp PgDn Home End"
- "Shift_L p y f g c r l BackSpace"
- "a o e u i d h t n s"
- ", q j k x b m w v z"
- "Shift_L P Y F G C R L BackSpace"
- "A O E U I D H T N S"
- ", Q J K X B M W V Z"
- "show_numbers preferences space show_actions Return"
numbers:
- "EscSmall TabSmall Ctrl Alt ↑ ↓ ← →"

17
debian/changelog vendored
View File

@ -1,3 +1,20 @@
squeekboard (1.22.0-1) experimental; urgency=medium
[ Asier Sarasua Garmendia ]
* Add Basque translation
[ Dorota Czaplejewicz ]
* state: Make size independent of scaling factor
* cleanup: Remove debug prints
* tests: Make panel manager modifications pure
* panel: Fix sizing on output reconfiguration
* Update deps
[ Undef ]
* layout: fix uppercase dvorak terminal mode
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Sat, 01 Apr 2023 13:46:23 +0000
squeekboard (1.21.0-1) experimental; urgency=medium
[ Dorota Czaplejewicz ]

View File

@ -1,7 +1,7 @@
project(
'squeekboard',
'c', 'rust',
version: '1.21.0',
version: '1.22.0',
license: 'GPLv3',
meson_version: '>=0.51.0',
default_options: [

View File

@ -3,6 +3,7 @@ cs
de
el
es
eu
fa
fi
fr

42
po/eu.po Normal file
View File

@ -0,0 +1,42 @@
# Basque translation for squeekboard.
# Copyright (C) 2023 squeekboard's COPYRIGHT HOLDER
# This file is distributed under the same license as the squeekboard package.
# Asier Sarasua Garmendia <asiersarasua@ni.eus>, 2023.
#
msgid ""
msgstr "Project-Id-Version: squeekboard master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/issues\n"
"POT-Creation-Date: 2023-02-26 09:13+0000\n"
"PO-Revision-Date: 2023-03-06 09:13+0000\n"
"Last-Translator: Asier Sarasua Garmendia <asiersarasua@ni.eus>\n"
"Language-Team: Basque <librezale@librezale.eus>\n"
"Language: eu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#. translators: This is a emmoji keyboard layout
#: data/popover.ui:6
msgid "Emoji"
msgstr "Emojia"
#. translators: This is a terminal keyboard layout
#: data/popover.ui:12
msgid "Terminal"
msgstr "Terminala"
#: data/popover.ui:18
msgid "Keyboard Settings"
msgstr "Teklatuaren ezarpenak"
#: data/sm.puri.Squeekboard.desktop.in.in:3
msgid "Squeekboard"
msgstr "Squeekboard"
#: data/sm.puri.Squeekboard.desktop.in.in:4
msgid "On Screen Keyboard"
msgstr "Pantailako teklatua"
#: data/sm.puri.Squeekboard.desktop.in.in:5
msgid "An on screen virtual keyboard"
msgstr "Gehitu pantailako teklatu birtuala"

View File

@ -29,9 +29,14 @@ pub mod c {
pub struct WlOutput(*const c_void);
impl WlOutput {
fn null() -> Self {
const fn null() -> Self {
Self(ptr::null())
}
#[cfg(test)]
pub const fn dummy() -> Self {
Self::null()
}
}
#[repr(C)]

View File

@ -94,7 +94,7 @@ impl PixelSize {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq)]
struct Size {
width: u32,
height: u32,
@ -104,7 +104,7 @@ struct Size {
/// the application asks for some size,
/// and then receives a size that the compositor thought appropriate.
/// Stores raw values passed to Wayland, i.e. scaled dimensions.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq)]
enum State {
Hidden,
SizeRequested {
@ -119,6 +119,18 @@ enum State {
},
}
/// A command to send out to the next layer of processing.
/// Here, it's the C side of the panel.
#[derive(Debug, PartialEq)]
enum Update {
Hide,
Resize { height: u32 },
RequestWidget {
output: OutputId,
height: u32,
},
}
#[derive(Clone, PartialEq, Debug)]
pub enum Command {
Show {
@ -153,7 +165,50 @@ impl Manager {
eprintln!("Panel received configure {:?}", &size);
}
self.state = match self.state.clone() {
self.state = self.state.clone().configure(size);
if self.debug {
eprintln!("Panel now {:?}", &self.state);
}
}
pub fn update(mgr: Wrapped<Manager>, cmd: Command) {
let copied = mgr.clone();
let mgr = mgr.clone_ref();
let mut mgr = mgr.borrow_mut();
if mgr.debug {
eprintln!("Panel received {:?}", &cmd);
}
let (state, updates) = mgr.state.clone().update(cmd);
(*mgr).state = state;
for update in &updates {
unsafe {
match update {
Update::Hide => c::panel_manager_hide(mgr.panel),
Update::Resize { height }
=> c::panel_manager_resize(mgr.panel, *height),
Update::RequestWidget{output, height}
=> c::panel_manager_request_widget(mgr.panel, output.0, *height, copied.clone()),
}
}
}
if mgr.debug {
for update in &updates {
eprintln!("Panel updates: {:?}", &update);
}
eprintln!("Panel is now {:?}", &(*mgr).state);
}
}
}
impl State {
fn configure(self, size: Size) -> Self {
match self {
State::Hidden => {
// This may happen if a hide is scheduled immediately after a show.
log_print!(
@ -174,49 +229,34 @@ impl Manager {
wanted_height: height,
allocated: size,
},
};
if self.debug {
eprintln!("Panel now {:?}", &self.state);
}
}
pub fn update(mgr: Wrapped<Manager>, cmd: Command) {
let copied = mgr.clone();
let mgr = mgr.clone_ref();
let mut mgr = mgr.borrow_mut();
if mgr.debug {
eprintln!("Panel received {:?}", &cmd);
}
(*mgr).state = match (cmd, mgr.state.clone()) {
(Command::Hide, State::Hidden) => State::Hidden,
(Command::Hide, State::SizeAllocated{..}) => {
unsafe { c::panel_manager_hide(mgr.panel); }
State::Hidden
},
(Command::Hide, State::SizeRequested{..}) => {
unsafe { c::panel_manager_hide(mgr.panel); }
State::Hidden
},
fn update(self, cmd: Command) -> (Self, Vec<Update>) {
match (cmd, self) {
(Command::Hide, State::Hidden) => (State::Hidden, Vec::new()),
(Command::Hide, State::SizeAllocated{..}) => (
State::Hidden, vec![Update::Hide],
),
(Command::Hide, State::SizeRequested{..}) => (
State::Hidden, vec![Update::Hide],
),
(Command::Show{output, height}, State::Hidden) => {
let height = height.as_scaled_ceiling();
if mgr.debug {
eprintln!("Panel requests widget {:?}", (&output.0, &height));
}
unsafe { c::panel_manager_request_widget(mgr.panel, output.0, height, copied); }
State::SizeRequested{output, height}
(
State::SizeRequested{output, height},
vec![Update::RequestWidget{ output, height }],
)
},
(
Command::Show{output, height},
State::SizeRequested{output: req_output, height: req_height},
) => {
let height = height.as_scaled_ceiling();
if output == req_output && height == req_height {
State::SizeRequested{output: req_output, height: req_height}
} else if output == req_output {
if output == req_output && height == req_height {(
State::SizeRequested{output: req_output, height: req_height},
Vec::new(),
)} else if output == req_output {(
// I'm not sure about that.
// This could cause a busy loop,
// when two requests are being processed at the same time:
@ -225,50 +265,119 @@ impl Manager {
// the other from the state wanting height B',
// causing the compositor to change size to B.
// So better cut this short here, despite artifacts.
// Out of simplicty, just ignore the new request.
// If that causes problems, the request in flight could be stored
// for the purpose of handling it better somehow.
State::SizeRequested{output: req_output, height: req_height}
} else {
if mgr.debug {
eprintln!("Panel requests widget {:?}", (&output.0, &height));
}
// Doing nothing means that Squeekboard will occasionally use the stale size (see test),
// so instead always listen to the higher layer and request a new size.
// If this causes problems, maybe count requests/configures, or track what was allocated in response to what request.
State::SizeRequested{output, height},
vec![Update::Resize { height }],
)} else {(
// This looks weird, but should be safe.
// The stack seems to handle
// configure events on a dead surface.
unsafe {
c::panel_manager_hide(mgr.panel);
c::panel_manager_request_widget(mgr.panel, output.0, height, copied);
}
State::SizeRequested{output, height}
}
State::SizeRequested{output, height},
vec![
Update::Hide,
Update::RequestWidget { output, height },
],
)}
},
(
Command::Show{output, height},
State::SizeAllocated{output: alloc_output, allocated, wanted_height},
) => {
let height = height.as_scaled_ceiling();
if output == alloc_output && height == wanted_height {
State::SizeAllocated{output: alloc_output, wanted_height, allocated}
} else if output == alloc_output && height == allocated.height {
State::SizeAllocated{output: alloc_output, wanted_height: height, allocated}
} else if output == alloc_output {
if output == alloc_output && height == wanted_height {(
State::SizeAllocated{output: alloc_output, wanted_height, allocated},
Vec::new(),
)} else if output == alloc_output && height == allocated.height {(
State::SizeAllocated{output: alloc_output, wanted_height: height, allocated},
Vec::new(),
)} else if output == alloc_output {(
// Should *all* other heights cause a resize?
// What about those between wanted and allocated?
unsafe { c::panel_manager_resize(mgr.panel, height); }
State::SizeRequested{output, height}
} else {
unsafe {
c::panel_manager_hide(mgr.panel);
c::panel_manager_request_widget(mgr.panel, output.0, height, copied);
}
State::SizeRequested{output, height}
}
State::SizeRequested{output, height},
vec![Update::Resize{height}],
)} else {(
State::SizeRequested{output, height},
vec![
Update::Hide,
Update::RequestWidget{output, height},
]
)}
},
};
if mgr.debug {
eprintln!("Panel is now {:?}", &(*mgr).state);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::outputs::c::WlOutput;
#[test]
fn resize_before_configured() {
// allow to make typing fields easier
#[allow(non_upper_case_globals)]
const output: OutputId = OutputId(WlOutput::dummy());
let state = State::Hidden;
// Initial show
let (state, cmds) = state.update(Command::Show {
output,
height: PixelSize { pixels: 100, scale_factor: 1 },
});
assert_eq!(
cmds,
vec![Update::RequestWidget { output, height: 100 }],
);
// layer shell requests a resize
// but another show comes before first can be confirmed
let (state, cmds) = dbg!(state).update(Command::Show {
output,
height: PixelSize { pixels: 50, scale_factor: 1 },
});
assert_eq!(
cmds,
vec![Update::Resize { height: 50 }],
"{:?}",
state,
);
// This is too many layers of indirection, but as long as layer shell is tied to gtk widgets, there's not much to be done.
// The main issue is that as the outputs change, we acknowledge the wrong (maintained) size:
/*
[346947.774] wl_output@31.geometry(0, 0, 65, 130, 0, "<Unknown>", "<Unknown>", 3)
[346948.117] wl_output@17.geometry(0, 0, 65, 130, 0, "<Unknown>", "<Unknown>", 3)
[346948.198] zwlr_layer_surface_v1@41.configure(1709, 720, 210)
[346948.268] -> zwlr_layer_surface_v1@41.ack_configure(1709)
*/
// TODO: check if layer_shell allows not acknowledging a configure event, and which part of squeekboard is responsible for that
// (there are no messages in between, so it's not PanelMgr; panel.c almost-unconditionally calls to Rust too; could it be layer-shell.c?).
// event we want
let good_state = state.clone().configure(Size { width: 50, height: 50 });
assert_eq!(
good_state,
State::SizeAllocated {
output,
wanted_height: 50,
allocated: Size { width: 50, height: 50 },
},
);
// or stale event we do not want
let state = state.configure(Size { width: 50, height: 100 });
// followed by the good one
let state = state.configure(Size { width: 50, height: 50 });
assert_eq!(
state,
State::SizeAllocated {
output,
wanted_height: 50,
allocated: Size { width: 50, height: 50 },
},
);
}
}

View File

@ -385,19 +385,20 @@ Outcome:
let ideal_height = IDEAL_TARGET_SIZE * ROW_COUNT as i32;
let ideal_height_px = (ideal_height * density).ceil().0 as u32;
let max_wide_height = Rational {
numerator: 172,
denominator: 540,
};
let ideal_panel_height = Rational {
numerator: ideal_height_px as i32,
denominator: px_size.width,
};
// Reduce height to match what the layout can fill.
// For this, we need to guess if normal or wide will be picked up.
// For this, we need to guess if normal or wide will be picked.
// This must match `eek_gtk_keyboard.c::get_type`.
// TODO: query layout database and choose one directly
let abstract_width
= PixelSize {
scale_factor: output.scale as u32,
pixels: px_size.width,
}
.as_scaled_ceiling();
let (arrangement, height_as_widths) = {
if abstract_width < 540 {(
if max_wide_height < ideal_panel_height {(
ArrangementKind::Base,
Rational {
numerator: 210,
@ -405,10 +406,7 @@ Outcome:
},
)} else {(
ArrangementKind::Wide,
Rational {
numerator: 172,
denominator: 540,
}
max_wide_height,
)}
};
@ -755,4 +753,33 @@ pub mod test {
)),
);
}
#[test]
fn size_l5_scale1() {
use crate::outputs::{Mode, Geometry, c, Size};
assert_eq!(
Application::get_preferred_height_and_arrangement(&OutputState {
current_mode: Some(Mode {
width: 720,
height: 1440,
}),
geometry: Some(Geometry{
transform: c::Transform::Normal,
phys_size: Size {
width: Some(Millimeter(65)),
height: Some(Millimeter(130)),
},
}),
scale: 1,
}),
Some((
PixelSize {
scale_factor: 1,
pixels: 420,
},
ArrangementKind::Base,
)),
);
}
}

View File

@ -4,6 +4,7 @@ use std::rc::Rc;
use crate::float_ord::FloatOrd;
use std::borrow::Borrow;
use std::cmp::{Ordering, PartialOrd};
use std::hash::{ Hash, Hasher };
use std::ops::Mul;
@ -242,6 +243,34 @@ impl<U, T: Mul<U, Output=T>> Mul<Rational<U>> for Rational<T> {
}
}
impl PartialEq for Rational<i32> {
fn eq(&self, other: &Self) -> bool {
(self.denominator as i64).saturating_mul(other.numerator as i64)
== (other.denominator as i64).saturating_mul(self.numerator as i64)
}
}
impl Eq for Rational<i32> {}
impl Ord for Rational<i32> {
fn cmp(&self, other: &Self) -> Ordering {
// Using 64-bit values to make overflows unlikely.
// If i32_max * u32_max can exceed i64_max,
// then this is actually PartialOrd.
// Saturating mul used just to avoid propagating mistakes.
(other.denominator as i64).saturating_mul(self.numerator as i64)
.cmp(
&(self.denominator as i64).saturating_mul(other.numerator as i64)
)
}
}
impl PartialOrd for Rational<i32> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
/// Compares pointers but not internal values of Rc
pub struct Pointer<T>(pub Rc<T>);
@ -327,4 +356,20 @@ mod tests {
vec![(5, 0), (6, 0), (7, 0), (5, 1), (6, 1), (7, 1), (5, 2)]
);
}
#[test]
fn check_rational_cmp() {
assert_eq!(
Rational { numerator: 1, denominator: 1 },
Rational { numerator: 1, denominator: 1 },
);
assert_eq!(
Rational { numerator: 1, denominator: 1 },
Rational { numerator: 2, denominator: 2 },
);
assert!(
Rational { numerator: 1, denominator: 1 }
< Rational { numerator: 2, denominator: 1 }
);
}
}