diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bbec6d848..3bdb8615d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ env: # version like 1.70. Note that we only specify MAJOR.MINOR and not PATCH so that bugfixes still # come automatically. If the version specified here is no longer the latest stable version, # then please feel free to submit a PR that adjusts it along with the potential clippy fixes. - RUST_STABLE_VER: "1.82" # In quotes because otherwise 1.70 would be interpreted as 1.7 + RUST_STABLE_VER: "1.92" # In quotes because otherwise 1.70 would be interpreted as 1.7 name: CI diff --git a/druid-derive/src/lib.rs b/druid-derive/src/lib.rs index 2decaf4eb..3a0dcf96d 100644 --- a/druid-derive/src/lib.rs +++ b/druid-derive/src/lib.rs @@ -23,8 +23,8 @@ use syn::parse_macro_input; /// /// - `#[data(ignore)]` makes the generated `Data::same` function skip comparing this field. /// - `#[data(same_fn="foo")]` uses the function `foo` for comparing this field. `foo` should -/// be the name of a function with signature `fn(&T, &T) -> bool`, where `T` is the type of -/// the field. +/// be the name of a function with signature `fn(&T, &T) -> bool`, where `T` is the type of +/// the field. /// - `#[data(eq)]` is shorthand for `#[data(same_fn = "PartialEq::eq")]` /// /// # Example @@ -61,7 +61,7 @@ pub fn derive_data(input: TokenStream) -> TokenStream { /// /// - `#[lens(ignore)]` skips creating a lens for one field. /// - `#[lens(name="foo")]` gives the lens the specified name (instead of the default, which is to -/// create a lens with the same name as the field). +/// create a lens with the same name as the field). /// /// # Example /// diff --git a/druid-shell/Cargo.toml b/druid-shell/Cargo.toml index 39a86ddbd..7b835a866 100755 --- a/druid-shell/Cargo.toml +++ b/druid-shell/Cargo.toml @@ -60,6 +60,11 @@ tga = ["piet-common/tga"] hdr = ["piet-common/hdr"] serde = ["piet-common/serde"] +[lints] +# The 'objc' package is broken and abandoned, needs this hack. +# https://github.com/SSheldon/rust-objc/issues/125 +rust.unexpected_cfgs = { level = "warn", check-cfg = ['cfg(feature, values("cargo-clippy"))'] } + [dependencies] piet-common = { version = "=0.7.0-cairo18" } diff --git a/druid-shell/examples/edit_text.rs b/druid-shell/examples/edit_text.rs index 345d4b0a5..ddec329ff 100644 --- a/druid-shell/examples/edit_text.rs +++ b/druid-shell/examples/edit_text.rs @@ -209,7 +209,7 @@ impl InputHandler for AppInputHandler { doc.composition = None; self.window_handle.request_anim_frame(); } - fn slice(&self, range: Range) -> Cow { + fn slice(&self, range: Range) -> Cow<'_, str> { self.state.borrow().text[range].to_string().into() } fn is_char_boundary(&self, i: usize) -> bool { diff --git a/druid-shell/src/application.rs b/druid-shell/src/application.rs index c1f26529e..1d040fd78 100644 --- a/druid-shell/src/application.rs +++ b/druid-shell/src/application.rs @@ -173,3 +173,8 @@ impl Application { backend::Application::get_locale() } } + +/// Perform any initialization needed for the testing harness. +pub fn init_harness() { + backend::init_harness(); +} diff --git a/druid-shell/src/backend/gtk/application.rs b/druid-shell/src/backend/gtk/application.rs index d8756044b..23c1436e6 100644 --- a/druid-shell/src/backend/gtk/application.rs +++ b/druid-shell/src/backend/gtk/application.rs @@ -87,3 +87,5 @@ impl crate::platform::linux::ApplicationExt for crate::Application { }) } } + +pub fn init_harness() {} diff --git a/druid-shell/src/backend/mac/application.rs b/druid-shell/src/backend/mac/application.rs index 21d785146..de6376426 100644 --- a/druid-shell/src/backend/mac/application.rs +++ b/druid-shell/src/backend/mac/application.rs @@ -8,6 +8,7 @@ use std::cell::RefCell; use std::ffi::c_void; use std::rc::Rc; +use std::sync::Once; use cocoa::appkit::{NSApp, NSApplication, NSApplicationActivationPolicyRegular}; use cocoa::base::{id, nil, NO, YES}; @@ -183,3 +184,10 @@ extern "C" fn handle_menu_item(this: &mut Object, _: Sel, item: id) { (*inner).command(tag as u32); } } + +pub fn init_harness() { + static INIT: Once = Once::new(); + INIT.call_once(|| unsafe { + let _app: id = msg_send![class!(NSApplication), sharedApplication]; + }); +} diff --git a/druid-shell/src/backend/wayland/application.rs b/druid-shell/src/backend/wayland/application.rs index fb30823d8..b75d0b68c 100644 --- a/druid-shell/src/backend/wayland/application.rs +++ b/druid-shell/src/backend/wayland/application.rs @@ -372,7 +372,7 @@ impl Application { return; } - if appdata.handles.borrow().len() == 0 { + if appdata.handles.borrow().is_empty() { tracing::debug!("shutting down, no window remaining"); signal.stop(); return; @@ -566,3 +566,5 @@ impl Seat { } } } + +pub fn init_harness() {} diff --git a/druid-shell/src/backend/wayland/display.rs b/druid-shell/src/backend/wayland/display.rs index f1bebd2b4..5ea67a6f2 100644 --- a/druid-shell/src/backend/wayland/display.rs +++ b/druid-shell/src/backend/wayland/display.rs @@ -49,6 +49,7 @@ where pub trait GlobalEventDispatch { fn subscribe(&self, sub: impl Into) -> GlobalEventSubscription; + #[expect(dead_code)] // Until it's not dead fn release(&self, s: &GlobalEventSubscription); } diff --git a/druid-shell/src/backend/wayland/surfaces/popup.rs b/druid-shell/src/backend/wayland/surfaces/popup.rs index bb5277a85..404b210bb 100644 --- a/druid-shell/src/backend/wayland/surfaces/popup.rs +++ b/druid-shell/src/backend/wayland/surfaces/popup.rs @@ -122,10 +122,7 @@ impl Surface { tracing::debug!("{:?} {:?}", obj, event); }); - let wl_xdg_popup = match parent.surface(&wl_xdg_surface, &wl_xdg_pos) { - Ok(p) => p, - Err(cause) => return Err(cause), - }; + let wl_xdg_popup = parent.surface(&wl_xdg_surface, &wl_xdg_pos)?; wl_xdg_popup.quick_assign({ let wl_surface = wl_surface.clone(); move |_xdg_popup, event, _| { diff --git a/druid-shell/src/backend/web/application.rs b/druid-shell/src/backend/web/application.rs index 0af45c53f..f5a46570c 100644 --- a/druid-shell/src/backend/web/application.rs +++ b/druid-shell/src/backend/web/application.rs @@ -30,3 +30,5 @@ impl Application { .unwrap_or_else(|| "en-US".into()) } } + +pub fn init_harness() {} diff --git a/druid-shell/src/backend/windows/application.rs b/druid-shell/src/backend/windows/application.rs index b584b62a8..ba5109da9 100644 --- a/druid-shell/src/backend/windows/application.rs +++ b/druid-shell/src/backend/windows/application.rs @@ -141,9 +141,8 @@ impl Application { } let mut msg: MSG = msg.assume_init(); let accels = accels::find_accels(GetAncestor(msg.hwnd, GA_ROOT)); - let translated = accels.map_or(false, |it| { - TranslateAcceleratorW(msg.hwnd, it.handle(), &mut msg) != 0 - }); + let translated = accels + .is_some_and(|it| TranslateAcceleratorW(msg.hwnd, it.handle(), &mut msg) != 0); if !translated { TranslateMessage(&msg); DispatchMessageW(&msg); @@ -198,3 +197,5 @@ impl Application { }) } } + +pub fn init_harness() {} diff --git a/druid-shell/src/backend/windows/mod.rs b/druid-shell/src/backend/windows/mod.rs index 15f629777..6cd986dbd 100644 --- a/druid-shell/src/backend/windows/mod.rs +++ b/druid-shell/src/backend/windows/mod.rs @@ -70,6 +70,7 @@ impl DxgiSurfaceRenderTarget { } // error handling +#[allow(dead_code)] pub enum Error { WinapiError(HRESULT), } diff --git a/druid-shell/src/backend/windows/util.rs b/druid-shell/src/backend/windows/util.rs index c5f17947e..d23fdc565 100644 --- a/druid-shell/src/backend/windows/util.rs +++ b/druid-shell/src/backend/windows/util.rs @@ -140,6 +140,7 @@ type GetSystemMetricsForDpi = // from shcore.dll type GetDpiForMonitor = unsafe extern "system" fn(HMONITOR, MONITOR_DPI_TYPE, *mut UINT, *mut UINT); type SetProcessDpiAwareness = unsafe extern "system" fn(PROCESS_DPI_AWARENESS) -> HRESULT; +#[allow(non_snake_case)] type DCompositionCreateDevice = unsafe extern "system" fn( dxgiDevice: *const IDXGIDevice, iid: REFIID, diff --git a/druid-shell/src/backend/x11/application.rs b/druid-shell/src/backend/x11/application.rs index 0e66d9720..e60b21b55 100644 --- a/druid-shell/src/backend/x11/application.rs +++ b/druid-shell/src/backend/x11/application.rs @@ -944,3 +944,5 @@ fn poll_with_timeout( Ok(()) } + +pub fn init_harness() {} diff --git a/druid-shell/src/backend/x11/clipboard.rs b/druid-shell/src/backend/x11/clipboard.rs index 50aba73b2..b1dafce4f 100644 --- a/druid-shell/src/backend/x11/clipboard.rs +++ b/druid-shell/src/backend/x11/clipboard.rs @@ -160,7 +160,7 @@ impl ClipboardState { if owner.owner == contents.owner_window { // We are the new selection owner! Remember our contents for later. debug!("put_formats(): became selection owner"); - if let Some(mut old_owner) = std::mem::replace(&mut self.contents, Some(contents)) { + if let Some(mut old_owner) = self.contents.replace(contents) { // We already where the owner before. Destroy the old contents. old_owner.destroy(conn)?; } diff --git a/druid-shell/src/backend/x11/window.rs b/druid-shell/src/backend/x11/window.rs index 32f6335f9..2f312878d 100644 --- a/druid-shell/src/backend/x11/window.rs +++ b/druid-shell/src/backend/x11/window.rs @@ -578,8 +578,8 @@ pub(crate) struct Window { /// /// There are three ways that rendering can get triggered: /// 1) We render a frame, and it signals to us that an animation is requested. In this case, we - /// will render the next frame as soon as we get a notification that the just-presented - /// frame completed. In other words, we use `CompleteNotifyEvent` to schedule rendering. + /// will render the next frame as soon as we get a notification that the just-presented + /// frame completed. In other words, we use `CompleteNotifyEvent` to schedule rendering. /// 2) We get an expose event telling us that a region got invalidated. In /// this case, we will render the next frame immediately unless we're already waiting for a /// completion notification. (If we are waiting for a completion notification, we just make diff --git a/druid-shell/src/lib.rs b/druid-shell/src/lib.rs index baa815ba4..7743a058b 100644 --- a/druid-shell/src/lib.rs +++ b/druid-shell/src/lib.rs @@ -63,7 +63,7 @@ mod window; pub mod platform; pub mod text; -pub use application::{AppHandler, Application}; +pub use application::{init_harness, AppHandler, Application}; pub use clipboard::{Clipboard, ClipboardFormat, FormatId}; pub use common_util::Counter; pub use dialog::{FileDialogOptions, FileInfo, FileSpec}; diff --git a/druid-shell/src/text.rs b/druid-shell/src/text.rs index a25042f55..91748d34e 100644 --- a/druid-shell/src/text.rs +++ b/druid-shell/src/text.rs @@ -243,11 +243,7 @@ impl Selection { /// /// If the selection is a caret, this is `0`. pub fn len(&self) -> usize { - if self.anchor > self.active { - self.anchor - self.active - } else { - self.active - self.anchor - } + self.anchor.abs_diff(self.active) } /// Returns `true` if the selection's length is `0`. @@ -341,7 +337,7 @@ pub trait InputHandler { /// /// Panics if the start or end of the range do not fall on a code point /// boundary. - fn slice(&self, range: Range) -> Cow; + fn slice(&self, range: Range) -> Cow<'_, str>; /// Returns the number of UTF-16 code units in the provided UTF-8 range. /// diff --git a/druid-shell/src/window.rs b/druid-shell/src/window.rs index 1552b892f..083baeef0 100644 --- a/druid-shell/src/window.rs +++ b/druid-shell/src/window.rs @@ -444,7 +444,7 @@ impl WindowHandle { /// only guaranteed to be valid for the current pass of the runloop. // TODO: Can we get rid of the Result/Error for ergonomics? pub fn get_scale(&self) -> Result { - self.0.get_scale().map_err(Into::into) + self.0.get_scale() } } @@ -553,6 +553,7 @@ impl WindowBuilder { /// /// If this fails, your application should exit. pub fn build(self) -> Result { + #[allow(clippy::useless_conversion)] // Platform-dependant self.0.build().map(WindowHandle).map_err(Into::into) } } diff --git a/druid/src/contexts.rs b/druid/src/contexts.rs index f611da176..34847ffd9 100644 --- a/druid/src/contexts.rs +++ b/druid/src/contexts.rs @@ -171,7 +171,7 @@ pub trait ChangeCtx { /// Returns the state of the widget. /// /// This method should only be used by the framework to do mergeups. - fn state(&mut self) -> State; + fn state(&mut self) -> State<'_>; } /// Convenience trait for invalidation and request methods available on multiple contexts. @@ -245,7 +245,7 @@ impl_context_trait!( Self::request_timer(self, deadline) } - fn state(&mut self) -> State { + fn state(&mut self) -> State<'_> { State { //state: &mut *self.state, widget_state: &mut *self.widget_state, diff --git a/druid/src/data.rs b/druid/src/data.rs index fff075f1a..f3087729d 100644 --- a/druid/src/data.rs +++ b/druid/src/data.rs @@ -622,7 +622,7 @@ mod test { #[cfg(feature = "im")] fn im_data() { for len in 8..256 { - let input = std::iter::repeat(0_u8).take(len).collect::>(); + let input = std::iter::repeat_n(0_u8, len).collect::>(); let mut inp2 = input.clone(); assert!(input.same(&inp2)); inp2.set(len - 1, 98); @@ -633,8 +633,8 @@ mod test { #[test] #[cfg(feature = "im")] fn im_vec_different_length() { - let one = std::iter::repeat(0_u8).take(9).collect::>(); - let two = std::iter::repeat(0_u8).take(10).collect::>(); + let one = std::iter::repeat_n(0_u8, 9).collect::>(); + let two = std::iter::repeat_n(0_u8, 10).collect::>(); assert!(!one.same(&two)); } diff --git a/druid/src/event.rs b/druid/src/event.rs index f89b11e68..bcdf73e8f 100644 --- a/druid/src/event.rs +++ b/druid/src/event.rs @@ -161,7 +161,7 @@ pub enum Event { /// - Widgets and other Druid components can send custom [`Command`]s at /// runtime, via methods such as [`EventCtx::submit_command`]. /// - /// [`Widget`]: Widget + /// [`Widget`]: crate::Widget /// [`EventCtx::submit_command`]: crate::EventCtx::submit_command /// [`ExtEventSink`]: crate::ExtEventSink /// [`MenuItem`]: crate::MenuItem diff --git a/druid/src/lib.rs b/druid/src/lib.rs index e96cc1f9d..498229b0e 100644 --- a/druid/src/lib.rs +++ b/druid/src/lib.rs @@ -85,7 +85,7 @@ //! Utility features: //! //! * `im` - Efficient immutable data structures using the [`im` crate], -//! which is made available via the [`im` module]. +//! which is made available via the [`im` module]. //! * `svg` - Scalable Vector Graphics for icons and other scalable images using the [`usvg` crate]. //! * `image` - Bitmap image support using the [`image` crate]. //! * `x11` - Work-in-progress X11 backend instead of GTK. diff --git a/druid/src/localization.rs b/druid/src/localization.rs index 7b143476a..26e4f8a36 100644 --- a/druid/src/localization.rs +++ b/druid/src/localization.rs @@ -87,7 +87,7 @@ pub struct LocalizedString { struct BundleStack(Vec>>); impl BundleStack { - fn get_message(&self, id: &str) -> Option { + fn get_message(&self, id: &str) -> Option> { self.0.iter().flat_map(|b| b.get_message(id)).next() } @@ -238,14 +238,10 @@ impl L10nManager { args: impl Into>>, ) -> Option { let args = args.into(); - let value = match self + let value = self .current_bundle .get_message(key) - .and_then(|msg| msg.value()) - { - Some(v) => v, - None => return None, - }; + .and_then(|msg| msg.value())?; let mut errs = Vec::new(); let result = self .current_bundle diff --git a/druid/src/tests/harness.rs b/druid/src/tests/harness.rs index de3b9b306..87480b1f6 100644 --- a/druid/src/tests/harness.rs +++ b/druid/src/tests/harness.rs @@ -155,6 +155,9 @@ impl Harness<'_, T> { mock_app, window_size, }; + + druid_shell::init_harness(); + harness_closure(&mut harness); } render_context_closure(target) diff --git a/druid/src/tests/mod.rs b/druid/src/tests/mod.rs index 46d2d07f3..350ac4ae0 100644 --- a/druid/src/tests/mod.rs +++ b/druid/src/tests/mod.rs @@ -75,7 +75,7 @@ pub fn temp_dir_for_test() -> std::path::PathBuf { .prefix("TempDir") .tempdir_in(test_dir) .unwrap() - .into_path() + .keep() } /// test that the first widget to request focus during an event gets it. diff --git a/druid/src/text/editable_text.rs b/druid/src/text/editable_text.rs index 3f7aa72d4..72f11b512 100644 --- a/druid/src/text/editable_text.rs +++ b/druid/src/text/editable_text.rs @@ -17,7 +17,7 @@ pub trait EditableText: Sized { /// Create a cursor with a reference to the text and a offset position. /// /// Returns None if the position isn't a codepoint boundary. - fn cursor(&self, position: usize) -> Option; + fn cursor(&self, position: usize) -> Option>; /// Replace range with new text. /// Can panic if supplied an invalid range. @@ -25,7 +25,7 @@ pub trait EditableText: Sized { fn edit(&mut self, range: Range, new: impl Into); /// Get slice of text at range. - fn slice(&self, range: Range) -> Option>; + fn slice(&self, range: Range) -> Option>; /// Get length of text (in bytes). fn len(&self) -> usize; @@ -62,7 +62,7 @@ pub trait EditableText: Sized { } impl EditableText for String { - fn cursor<'a>(&self, position: usize) -> Option { + fn cursor<'a>(&self, position: usize) -> Option> { let new_cursor = StringCursor { text: self, position, @@ -79,7 +79,7 @@ impl EditableText for String { self.replace_range(range, &new.into()); } - fn slice(&self, range: Range) -> Option> { + fn slice(&self, range: Range) -> Option> { self.get(range).map(Cow::from) } @@ -177,7 +177,7 @@ impl EditableText for String { } impl EditableText for Arc { - fn cursor(&self, position: usize) -> Option { + fn cursor(&self, position: usize) -> Option> { ::cursor(self, position) } fn edit(&mut self, range: Range, new: impl Into) { @@ -186,7 +186,7 @@ impl EditableText for Arc { Arc::make_mut(self).edit(range, new) } } - fn slice(&self, range: Range) -> Option> { + fn slice(&self, range: Range) -> Option> { Some(Cow::Borrowed(&self[range])) } fn len(&self) -> usize { diff --git a/druid/src/text/input_component.rs b/druid/src/text/input_component.rs index 8eb8a2519..20994d158 100644 --- a/druid/src/text/input_component.rs +++ b/druid/src/text/input_component.rs @@ -855,7 +855,7 @@ impl InputHandler for EditSessionHandle { self.text.len() } - fn slice(&self, range: Range) -> std::borrow::Cow { + fn slice(&self, range: Range) -> std::borrow::Cow<'_, str> { self.text.slice(range).unwrap() } diff --git a/druid/src/text/rich_text.rs b/druid/src/text/rich_text.rs index 7b069572c..96d6d4d58 100644 --- a/druid/src/text/rich_text.rs +++ b/druid/src/text/rich_text.rs @@ -126,7 +126,7 @@ impl RichTextBuilder { /// /// This method returns a [`AttributesAdder`] that can be used to style the newly /// added string slice. - pub fn push(&mut self, string: &str) -> AttributesAdder { + pub fn push(&mut self, string: &str) -> AttributesAdder<'_> { let range = self.buffer.len()..(self.buffer.len() + string.len()); self.buffer.push_str(string); self.add_attributes_for_range(range) @@ -136,7 +136,7 @@ impl RichTextBuilder { /// /// This method should generally not be invoked manually, but rather through the write! macro itself. #[doc(hidden)] - pub fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> AttributesAdder { + pub fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> AttributesAdder<'_> { use std::fmt::Write; let start = self.buffer.len(); self.buffer @@ -148,7 +148,10 @@ impl RichTextBuilder { /// Get an [`AttributesAdder`] for the given range. /// /// This can be used to modify styles for a given range after it has been added. - pub fn add_attributes_for_range(&mut self, range: impl RangeBounds) -> AttributesAdder { + pub fn add_attributes_for_range( + &mut self, + range: impl RangeBounds, + ) -> AttributesAdder<'_> { let range = util::resolve_range(range, self.buffer.len()); AttributesAdder { rich_text_builder: self, diff --git a/druid/src/widget/image.rs b/druid/src/widget/image.rs index e031741f1..a363836e7 100644 --- a/druid/src/widget/image.rs +++ b/druid/src/widget/image.rs @@ -495,7 +495,7 @@ mod tests { // Because we clipped to the bottom pixel, all pixels in the final image should // match it. - let expecting: Vec = iter::repeat(255).take(16).collect(); + let expecting: Vec = iter::repeat_n(255, 16).collect(); assert_eq!(&*raw_pixels, &*expecting); }, ) diff --git a/druid/src/widget/slider.rs b/druid/src/widget/slider.rs index 4607103a4..9071e2cc5 100644 --- a/druid/src/widget/slider.rs +++ b/druid/src/widget/slider.rs @@ -69,20 +69,15 @@ struct SliderKnob { } /// The shape of the slider knobs. -#[derive(Debug, Copy, Clone)] +#[derive(Default, Debug, Copy, Clone)] pub enum KnobStyle { /// Circle + #[default] Circle, /// Wedge Wedge, } -impl Default for KnobStyle { - fn default() -> Self { - Self::Circle - } -} - impl Slider { /// Create a new `Slider`. pub fn new() -> Slider { diff --git a/druid/src/widget/tabs.rs b/druid/src/widget/tabs.rs index a9bfec0db..37c86dbd9 100644 --- a/druid/src/widget/tabs.rs +++ b/druid/src/widget/tabs.rs @@ -767,20 +767,15 @@ impl TabsTransition { } /// Determines where the tab bar should be placed relative to the cross axis -#[derive(Debug, Copy, Clone, PartialEq, Eq, Data)] +#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Data)] pub enum TabsEdge { /// For horizontal tabs, top. For vertical tabs, left. + #[default] Leading, /// For horizontal tabs, bottom. For vertical tabs, right. Trailing, } -impl Default for TabsEdge { - fn default() -> Self { - Self::Leading - } -} - pub struct InitialTab { name: SingleUse>, // This is to avoid cloning provided label texts child: SingleUse>>, // This is to avoid cloning provided tabs