Skip to content

Commit

Permalink
Add two screen regions
Browse files Browse the repository at this point in the history
  • Loading branch information
baskerville committed Dec 6, 2020
1 parent f2191f2 commit c286dac
Show file tree
Hide file tree
Showing 11 changed files with 339 additions and 79 deletions.
2 changes: 1 addition & 1 deletion artworks/touch_regions.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 8 additions & 8 deletions doc/MANUAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,23 +68,23 @@ Tap the library label to bring up the library menu.

## Viewer

The screen is divided into seven regions:
The screen is divided into nine regions:

![Touch Regions](../artworks/touch_regions.svg)

Tap gestures by region:

- *LE* (Left Ear):
- *WS* (West Strip):
- Normal Mode: previous page.
- Search Mode: previous results page.
- *MB* (Middle Band): toggle the top and bottom bars.
- *RE* (Right Ear):
- *ES* (East Strip):
- Normal Mode: next page.
- Search Mode: next results page.
- *TL* (Top Left Corner): previous location.
- *TR* (Top Right Corner): toggle bookmark.
- *BL* (Bottom Left Corner): table of contents in normal mode, previous page in search mode.
- *BR* (Bottom Right Corner): go to page in normal mode, next page in search mode.
- *CR* (Center Rectangle), *SS* (South Strip) and *NS* (North Strip): toggle the top and bottom bars.
- *NWC* (North-West Corner): previous location.
- *NEC* (North-East Corner): toggle bookmark.
- *SWC* (South-West Corner): table of contents in normal mode, previous page in search mode.
- *SEC* (South-East Corner): go to page in normal mode, next page in search mode.

Swipe west/east to go to the next/previous page.

Expand Down
26 changes: 15 additions & 11 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use crate::view::keyboard::{Layout};
use crate::view::dictionary::Dictionary as DictionaryApp;
use crate::view::calculator::Calculator;
use crate::view::sketch::Sketch;
use crate::view::touch_events::TouchEvents;
use crate::document::sys_info_as_html;
use crate::input::{DeviceEvent, PowerSource, ButtonCode, ButtonStatus, VAL_RELEASE, VAL_PRESS};
use crate::input::{raw_events, device_events, usb_events, display_rotate_event, button_scheme_event};
Expand All @@ -34,7 +35,7 @@ use crate::settings::{ButtonScheme, Settings, SETTINGS_PATH, RotationLock};
use crate::frontlight::{Frontlight, StandardFrontlight, NaturalFrontlight, PremixedFrontlight};
use crate::lightsensor::{LightSensor, KoboLightSensor};
use crate::battery::{Battery, KoboBattery};
use crate::geom::{Rectangle, Edge};
use crate::geom::{Rectangle, DiagDir, Region};
use crate::view::home::Home;
use crate::view::reader::Reader;
use crate::view::dialog::Dialog;
Expand Down Expand Up @@ -780,20 +781,20 @@ pub fn run() -> Result<(), Error> {
break;
},
GestureEvent::MultiTap(mut points) => {
let mut rect = context.fb.rect();
let w = rect.width() as i32;
let h = rect.height() as i32;
let m = w.min(h);
rect.shrink(&Edge::uniform(m / 12));
if points[0].x > points[1].x {
points.swap(0, 1);
}
if points[0].dist2(points[1]) >= rect.diag2() {
if points[0].y < points[1].y {
tx.send(Event::Select(EntryId::TakeScreenshot)).ok();
} else {
let rect = context.fb.rect();
let r1 = Region::from_point(points[0], rect, context.settings.strip_width, context.settings.corner_width);
let r2 = Region::from_point(points[1], rect, context.settings.strip_width, context.settings.corner_width);
match (r1, r2) {
(Region::Corner(DiagDir::SouthWest), Region::Corner(DiagDir::NorthEast)) => {
rq.add(RenderData::new(view.id(), context.fb.rect(), UpdateMode::Full));
}
},
(Region::Corner(DiagDir::NorthWest), Region::Corner(DiagDir::SouthEast)) => {
tx.send(Event::Select(EntryId::TakeScreenshot)).ok();
},
_ => (),
}
},
_ => {
Expand Down Expand Up @@ -882,6 +883,9 @@ pub fn run() -> Result<(), Error> {
AppCmd::Calculator => Box::new(Calculator::new(context.fb.rect(), &tx, &mut rq, &mut context)?),
AppCmd::Dictionary { ref query, ref language } => Box::new(DictionaryApp::new(context.fb.rect(), query,
language, &tx, &mut rq, &mut context)),
AppCmd::TouchEvents => {
Box::new(TouchEvents::new(context.fb.rect(), &mut rq, &mut context))
},
};
transfer_notifications(view.as_mut(), next_view.as_mut(), &mut rq, &mut context);
history.push(HistoryItem {
Expand Down
7 changes: 7 additions & 0 deletions src/emulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ use crate::view::menu::{Menu, MenuKind};
use crate::view::dictionary::Dictionary;
use crate::view::calculator::Calculator;
use crate::view::sketch::Sketch;
use crate::view::touch_events::TouchEvents;
use crate::view::common::{locate, locate_by_id, transfer_notifications, overlapping_rectangle};
use crate::view::common::{toggle_input_history_menu, toggle_keyboard_layout_menu};
use crate::helpers::{load_toml, save_toml};
Expand Down Expand Up @@ -292,6 +293,9 @@ fn main() -> Result<(), Error> {
let rot = (5 + context.display.rotation) % 4;
ty.send(DeviceEvent::RotateScreen(rot)).ok();
},
Scancode::S => {
tx.send(Event::Select(EntryId::TakeScreenshot)).ok();
},
_ => (),
}
},
Expand Down Expand Up @@ -351,6 +355,9 @@ fn main() -> Result<(), Error> {
AppCmd::Dictionary { ref query, ref language } => {
Box::new(Dictionary::new(context.fb.rect(), query, language, &tx, &mut rq, &mut context))
},
AppCmd::TouchEvents => {
Box::new(TouchEvents::new(context.fb.rect(), &mut rq, &mut context))
},
};
transfer_notifications(view.as_mut(), next_view.as_mut(), &mut rq, &mut context);
history.push(view as Box<dyn View>);
Expand Down
105 changes: 105 additions & 0 deletions src/geom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ pub enum Dir {
West,
}

impl fmt::Display for Dir {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Dir::North => write!(f, "north"),
Dir::East => write!(f, "east"),
Dir::South => write!(f, "south"),
Dir::West => write!(f, "west"),
}
}
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum DiagDir {
NorthWest,
Expand All @@ -20,12 +31,32 @@ pub enum DiagDir {
SouthWest,
}

impl fmt::Display for DiagDir {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
DiagDir::NorthWest => write!(f, "northwest"),
DiagDir::NorthEast => write!(f, "northeast"),
DiagDir::SouthEast => write!(f, "southeast"),
DiagDir::SouthWest => write!(f, "southwest"),
}
}
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Axis {
Horizontal,
Vertical,
}

impl fmt::Display for Axis {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Axis::Horizontal => write!(f, "horizontal"),
Axis::Vertical => write!(f, "vertical"),
}
}
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum CycleDir {
Next,
Expand Down Expand Up @@ -1185,6 +1216,80 @@ impl DivAssign<f32> for Boundary {
}
}

#[derive(Debug, Copy, Clone)]
pub enum Region {
Corner(DiagDir),
Strip(Dir),
Center,
}

impl Region {
// pt ∈ rect
// 0.0 < {corner,strip}_width < 1.0
pub fn from_point(pt: Point, rect: Rectangle, strip_width: f32, corner_width: f32) -> Region {
let w = rect.width() as i32;
let h = rect.height() as i32;
let m = w.min(h) as f32 / 2.0;

let d = (m * corner_width).max(1.0) as i32;
let x1 = rect.min.x + d - 1;
let x2 = rect.max.x - d;

// The four corners are on top of all the other regions.
if pt.x <= x1 {
let dx = x1 - pt.x;
if pt.y <= rect.min.y + dx {
return Region::Corner(DiagDir::NorthWest);
} else if pt.y >= rect.max.y - 1 - dx {
return Region::Corner(DiagDir::SouthWest);
}
} else if pt.x >= x2 {
let dx = pt.x - x2;
if pt.y <= rect.min.y + dx {
return Region::Corner(DiagDir::NorthEast);
} else if pt.y >= rect.max.y - 1 - dx {
return Region::Corner(DiagDir::SouthEast);
}
}

let d = (m * strip_width).max(1.0) as i32;
let x1 = rect.min.x + d - 1;
let x2 = rect.max.x - d;
let y1 = rect.min.y + d - 1;
let y2 = rect.max.y - d;

// The four strips are above the center region.
// Each of the diagonals between the strips has to belong to one of the strip.
if pt.x <= x1 {
let dx = pt.x - rect.min.x;
if pt.y >= rect.min.y + dx && pt.y < rect.max.y - 1 - dx {
return Region::Strip(Dir::West);
}
} else if pt.x >= x2 {
let dx = rect.max.x - 1 - pt.x;
if pt.y > rect.min.y + dx && pt.y <= rect.max.y - 1 - dx {
return Region::Strip(Dir::East);
}
}

if pt.y <= y1 {
let dy = pt.y - rect.min.y;
if pt.x > rect.min.x + dy && pt.y <= rect.max.x - 1 - dy {
return Region::Strip(Dir::North);
}
} else if pt.y >= y2 {
let dy = rect.max.y - 1 - pt.y;
if pt.x >= rect.min.x + dy && pt.x < rect.max.x - 1 - dy {
return Region::Strip(Dir::South);
}
}

// The center rectangle is below everything else.
Region::Center
}
}


#[cfg(test)]
mod tests {
use super::{divide, LinearDir};
Expand Down
24 changes: 24 additions & 0 deletions src/gesture.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::fmt;
use std::sync::mpsc::{self, Sender, Receiver};
use std::sync::{Arc, Mutex};
use fxhash::FxHashMap;
Expand Down Expand Up @@ -73,6 +74,29 @@ pub enum GestureEvent {
HoldButtonLong(ButtonCode),
}

impl fmt::Display for GestureEvent {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
GestureEvent::Tap(pt) => write!(f, "Tap {}", pt),
GestureEvent::MultiTap(pts) => write!(f, "Multitap {} {}", pts[0], pts[1]),
GestureEvent::Swipe { dir, .. } => write!(f, "Swipe {}", dir),
GestureEvent::MultiSwipe { dir, .. } => write!(f, "Multiswipe {}", dir),
GestureEvent::Arrow { dir, .. } => write!(f, "Arrow {}", dir),
GestureEvent::MultiArrow { dir, .. } => write!(f, "Multiarrow {}", dir),
GestureEvent::Corner { dir, .. } => write!(f, "Corner {}", dir),
GestureEvent::MultiCorner { dir, .. } => write!(f, "Multicorner {}", dir),
GestureEvent::Pinch { axis, strength, .. } => write!(f, "Pinch {} {}", axis, strength),
GestureEvent::Spread { axis, strength, .. } => write!(f, "Spread {} {}", axis, strength),
GestureEvent::Rotate { center, quarter_turns, .. } => write!(f, "Rotate {} {}", center, quarter_turns * 90),
GestureEvent::Cross(pt) => write!(f, "Cross {}", pt),
GestureEvent::HoldFingerShort(pt, id) => write!(f, "Short-held finger {} {}", id, pt),
GestureEvent::HoldFingerLong(pt, id) => write!(f, "Long-held finger {} {}", id, pt),
GestureEvent::HoldButtonShort(code) => write!(f, "Short-held button {:?}", code),
GestureEvent::HoldButtonLong(code) => write!(f, "Long-held button {:?}", code),
}
}
}

#[derive(Debug)]
pub struct TouchState {
time: f64,
Expand Down
4 changes: 4 additions & 0 deletions src/settings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ pub struct Settings {
pub auto_power_off: u8,
pub time_format: String,
pub date_format: String,
pub strip_width: f32,
pub corner_width: f32,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub libraries: Vec<LibrarySettings>,
#[serde(skip_serializing_if = "FxHashMap::is_empty")]
Expand Down Expand Up @@ -374,6 +376,8 @@ impl Default for Settings {
button_scheme: ButtonScheme::Natural,
auto_suspend: 30,
auto_power_off: 3,
strip_width: 0.6,
corner_width: 0.4,
time_format: "%H:%M".to_string(),
date_format: "%A, %B %-d, %Y".to_string(),
intermission_images: FxHashMap::default(),
Expand Down
6 changes: 4 additions & 2 deletions src/view/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,10 @@ pub fn toggle_main_menu(view: &mut dyn View, rect: Rectangle, enable: Option<boo
EntryKind::Command("Calculator".to_string(),
EntryId::Launch(AppCmd::Calculator)),
EntryKind::Command("Sketch".to_string(),
EntryId::Launch(AppCmd::Sketch))];

EntryId::Launch(AppCmd::Sketch)),
EntryKind::Separator,
EntryKind::Command("Touch Events".to_string(),
EntryId::Launch(AppCmd::TouchEvents))];
let mut entries = vec![EntryKind::Command("About".to_string(),
EntryId::About),
EntryKind::Command("System Info".to_string(),
Expand Down
2 changes: 2 additions & 0 deletions src/view/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub mod reader;
pub mod dictionary;
pub mod calculator;
pub mod sketch;
pub mod touch_events;

use std::ops::{Deref, DerefMut};
use std::time::Duration;
Expand Down Expand Up @@ -345,6 +346,7 @@ pub enum AppCmd {
query: String,
language: String,
},
TouchEvents,
}

#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
Expand Down
Loading

0 comments on commit c286dac

Please sign in to comment.