From 169dd454cced7b08e8ca82534e0c719cdef01582 Mon Sep 17 00:00:00 2001 From: Sophie Herold Date: Mon, 6 Feb 2023 18:40:32 +0100 Subject: [PATCH] image: Add double click for zoom/fullscreen Zooms on touchscreens and fullscreens otherwise. Using the fullscreen behavior for now, since that's what a lot of other apps do. --- data/gtk/image_page.ui | 2 +- src/widgets/image.rs | 38 +++++++++++++++++++++++++++++++++++++- src/widgets/image_page.rs | 4 ++-- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/data/gtk/image_page.ui b/data/gtk/image_page.ui index 86f3a24..6ad4d93 100644 --- a/data/gtk/image_page.ui +++ b/data/gtk/image_page.ui @@ -63,7 +63,7 @@ - + 3 diff --git a/src/widgets/image.rs b/src/widgets/image.rs index 8109c37..b124f01 100644 --- a/src/widgets/image.rs +++ b/src/widgets/image.rs @@ -30,13 +30,22 @@ use once_cell::unsync::OnceCell; use std::cell::{Cell, RefCell}; use std::path::{Path, PathBuf}; +/// Milliseconds const ZOOM_ANIMATION_DURATION: u32 = 200; +/// Milliseconds const ROTATION_ANIMATION_DURATION: u32 = 200; +/// Relative to current zoom level const ZOOM_FACTOR_BUTTON: f64 = 1.5; +/// Relative to current zoom level const ZOOM_FACTOR_WHEEL: f64 = 1.3; -const ZOOM_FACTOR_WHEEL_HI_RES: f64 = 0.1; +/// Relative to current zoom level +const ZOOM_FACTOR_WHEEL_HI_RES: f64 = 0.001; +/// Relative to best-fit level +const ZOOM_FACTOR_DOUBLE_TAP: f64 = 2.5; + +/// Max zoom level 2000% const MAX_ZOOM_LEVEL: f64 = 20.0; mod imp { @@ -304,6 +313,33 @@ mod imp { fn connect_gestures(&self) { let obj = self.instance(); + // Double click for fullscreen (mouse/touchpad) or zoom (touch screen) + let left_click_gesture = gtk::GestureClick::builder().button(1).build(); + obj.add_controller(&left_click_gesture); + left_click_gesture.connect_pressed( + glib::clone!(@weak obj => move |gesture, n_press, x, y| { + // only handle double clicks + if n_press != 2 { + return; + } + + if gesture.device().map(|x| x.source()) == Some(gdk::InputSource::Touchscreen) { + // zoom + obj.imp().pointer_position.set(Some((x, y))); + if obj.is_best_fit() { + // zoom in + obj.zoom_to(ZOOM_FACTOR_DOUBLE_TAP * obj.zoom_level_best_fit()); + } else { + // zoom back out + obj.zoom_best_fit(); + } + } else { + // fullscreen + obj.activate_action("win.toggle-fullscreen", None).unwrap(); + } + }), + ); + // Drag for moving image around let drag_gesture = gtk::GestureDrag::new(); obj.add_controller(&drag_gesture); diff --git a/src/widgets/image_page.rs b/src/widgets/image_page.rs index 724583e..1c1f1fe 100644 --- a/src/widgets/image_page.rs +++ b/src/widgets/image_page.rs @@ -49,7 +49,7 @@ mod imp { #[template_child] pub(super) popover: TemplateChild, #[template_child] - pub(super) click_gesture: TemplateChild, + pub(super) right_click_gesture: TemplateChild, #[template_child] pub(super) press_gesture: TemplateChild, @@ -100,7 +100,7 @@ mod imp { self.parent_constructed(); - self.click_gesture + self.right_click_gesture .connect_pressed(clone!(@weak obj => move |gesture, _, x, y| { obj.show_popover_at(x, y); gesture.set_state(gtk::EventSequenceState::Claimed);