Skip to content

Commit

Permalink
feat: primary selection threshold
Browse files Browse the repository at this point in the history
The primary_threshold_ms variable defines the time interval, in
milliseconds, that controls how often the program updates its stored
value of the Linux primary selection. In the Linux environment, the
primary selection is a mechanism that automatically updates to reflect
the current highlighted text or object, typically updating with every
mouse movement.
  • Loading branch information
Rational-Curiosity committed May 24, 2024
1 parent 9c79224 commit 26c0c84
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 1 deletion.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ history_file_path = "/home/<username>/.cache/clipcat/clipcatd-history"
# File path of PID file,
# if you omit this value, clipcatd places the PID file on `$XDG_RUNTIME_DIR/clipcatd.pid`.
pid_file = "/run/user/<user-id>/clipcatd.pid"
# Controls how often the program updates its stored value of the Linux
# primary selection. In the Linux environment, the primary selection is a
# mechanism that automatically updates to reflect the current highlighted text or
# object, typically updating with every mouse movement.
primary_threshold_ms = 5000

[log]
# Emit log message to a log file.
Expand Down
9 changes: 9 additions & 0 deletions clipcatd/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ pub struct Config {
#[serde(default = "Config::default_pid_file_path")]
pub pid_file: PathBuf,

#[serde(default = "Config::default_primary_threshold_ms")]
pub primary_threshold_ms: i64,

#[serde(default = "Config::default_max_history")]
pub max_history: usize,

Expand Down Expand Up @@ -62,6 +65,7 @@ impl Default for Config {
Self {
daemonize: true,
pid_file: Self::default_pid_file_path(),
primary_threshold_ms: Self::default_primary_threshold_ms(),
max_history: Self::default_max_history(),
history_file_path: Self::default_history_file_path(),
synchronize_selection_with_clipboard:
Expand Down Expand Up @@ -124,6 +128,9 @@ impl Config {
#[inline]
pub const fn default_synchronize_selection_with_clipboard() -> bool { true }

#[inline]
pub const fn default_primary_threshold_ms() -> i64 { 0 }

#[inline]
pub const fn default_max_history() -> usize { 50 }

Expand Down Expand Up @@ -186,6 +193,7 @@ impl From<Config> for clipcat_server::Config {
fn from(
Config {
grpc,
primary_threshold_ms,
max_history,
synchronize_selection_with_clipboard,
history_file_path,
Expand Down Expand Up @@ -220,6 +228,7 @@ impl From<Config> for clipcat_server::Config {
grpc_listen_address,
grpc_local_socket,
grpc_access_token,
primary_threshold_ms,
max_history,
synchronize_selection_with_clipboard,
history_file_path,
Expand Down
2 changes: 2 additions & 0 deletions crates/server/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ pub struct Config {

pub grpc_access_token: Option<String>,

pub primary_threshold_ms: i64,

pub max_history: usize,

pub synchronize_selection_with_clipboard: bool,
Expand Down
2 changes: 2 additions & 0 deletions crates/server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ pub async fn serve_with_shutdown(
grpc_listen_address,
grpc_local_socket,
grpc_access_token,
primary_threshold_ms,
max_history,
history_file_path,
synchronize_selection_with_clipboard,
Expand Down Expand Up @@ -115,6 +116,7 @@ pub async fn serve_with_shutdown(
tracing::info!("Initialize ClipboardManager with capacity {max_history}");
let mut clipboard_manager = ClipboardManager::with_capacity(
clipboard_backend.clone(),
primary_threshold_ms,
max_history,
desktop_notification.clone(),
);
Expand Down
20 changes: 19 additions & 1 deletion crates/server/src/manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const DEFAULT_CAPACITY: usize = 40;
pub struct ClipboardManager<Notification> {
backend: Arc<dyn ClipboardBackend>,

primary_threshold: time::Duration,

capacity: usize,

// use id of ClipEntry as the key
Expand All @@ -39,12 +41,14 @@ where
{
pub fn with_capacity(
backend: Arc<dyn ClipboardBackend>,
primary_threshold_ms: i64,
capacity: usize,
notification: Notification,
) -> Self {
let capacity = if capacity == 0 { DEFAULT_CAPACITY } else { capacity };
Self {
backend,
primary_threshold: time::Duration::milliseconds(primary_threshold_ms),
capacity,
clips: HashMap::new(),
current_clips: [None; ClipboardKind::MAX_LENGTH],
Expand All @@ -57,7 +61,7 @@ where
#[cfg(test)]
#[inline]
pub fn new(backend: Arc<dyn ClipboardBackend>, notification: Notification) -> Self {
Self::with_capacity(backend, DEFAULT_CAPACITY, notification)
Self::with_capacity(backend, 0, DEFAULT_CAPACITY, notification)
}

#[inline]
Expand Down Expand Up @@ -128,6 +132,20 @@ where
}
ClipboardContent::Plaintext(text) => {
self.notification.on_plaintext_fetched(text.chars().count());
if let Some(id) = self.current_clips[usize::from(entry.kind())] {
if let Some(cur_clip) = self.clips.get(&id) {
if entry.timestamp() - cur_clip.timestamp() < self.primary_threshold {
if let ClipboardContent::Plaintext(cur_text) = cur_clip.as_ref() {
let len = std::cmp::min(text.len(), cur_text.len());
if text[..len] == cur_text[..len] {
if let Some(clip) = self.clips.remove(&id) {
let _id = self.timestamp_to_id.remove(&clip.timestamp());
}
}
}
}
}
}
}
}

Expand Down

0 comments on commit 26c0c84

Please sign in to comment.