From b5e8543b3ee254b179ebd4dd4b7f31858c8f0e03 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Mon, 19 Feb 2018 14:43:44 +0000 Subject: [PATCH 1/6] Use `xsel -k`, instead of `-o` -> `-i` --- clipmenud | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clipmenud b/clipmenud index e516b52..f25e7f8 100755 --- a/clipmenud +++ b/clipmenud @@ -173,7 +173,7 @@ while true; do # We can't colocate this with the above copying code because # https://github.com/cdown/clipmenu/issues/34 requires knowing if # we would skip first. - _xsel -o --"$selection" | _xsel -i --"$selection" + _xsel -k --"$selection" fi if (( CM_MAX_CLIPS )); then From 55407ba3f622c99b1efafbe6b6371680f6abd8f6 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Mon, 19 Feb 2018 14:51:00 +0000 Subject: [PATCH 2/6] Remove last_data checks Nowadays everything should be using clipnotify, which avoids constantly copying the same data. --- clipmenud | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/clipmenud b/clipmenud index f25e7f8..6de7704 100755 --- a/clipmenud +++ b/clipmenud @@ -85,8 +85,6 @@ fi # shellcheck disable=SC2174 mkdir -p -m0700 "$cache_dir" -declare -A last_data - command -v clipnotify >/dev/null 2>&1 && has_clipnotify=1 if ! (( has_clipnotify )); then @@ -137,29 +135,16 @@ while true; do continue fi - if [[ ${last_data[$selection]} == "$data" ]]; then - debug 'Skipping as last selection is the same as this one' - continue - fi - - last_data[$selection]=$data - first_line=$(get_first_line "$data") debug "New clipboard entry on $selection selection: \"$first_line\"" - # Without checking ${last_data[any]}, we often double write since both - # selections get the same content - if [[ ${last_data[any]} != "$data" ]]; then - filename="$cache_dir/$(cksum <<< "$first_line")" - debug "Writing $data to $filename" - printf '%s' "$data" > "$filename" + filename="$cache_dir/$(cksum <<< "$first_line")" + debug "Writing $data to $filename" + printf '%s' "$data" > "$filename" - debug "Writing $first_line to $cache_file" - printf '%s\n' "$first_line" >> "$cache_file" - fi - - last_data[any]=$data + debug "Writing $first_line to $cache_file" + printf '%s\n' "$first_line" >> "$cache_file" if (( CM_OWN_CLIPBOARD )) && [[ $selection != primary ]]; then # Take ownership of the clipboard, in case the original application From eb7d2b94817e8b66f62dc372a204a78a12e3ef0f Mon Sep 17 00:00:00 2001 From: Chris Down Date: Mon, 19 Feb 2018 15:01:21 +0000 Subject: [PATCH 3/6] Take clipboard ownership prior to clipnotify This avoids infinite loop if we make the work block async --- clipmenud | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/clipmenud b/clipmenud index 6de7704..cd40b34 100755 --- a/clipmenud +++ b/clipmenud @@ -97,6 +97,19 @@ exec {lock_fd}> "$lock_file" sleep_cmd=(sleep "${CM_SLEEP:-0.5}") while true; do + # We need to take ownership synchronously before we run `clipnotify` as + # otherwise we could enter an infinite loop. + if (( CM_OWN_CLIPBOARD )); then + # Take ownership of the clipboard, in case the original application + # is unable to serve the clipboard request (due to being suspended, + # etc). + # + # Primary is excluded from the change of ownership as applications + # sometimes act up if clipboard focus is taken away from them -- + # for example, urxvt will unhilight text, which is undesirable. + _xsel -k --clipboard + fi + if ! (( CM_ONESHOT )); then if (( has_clipnotify )); then # Fall back to polling if clipnotify fails @@ -146,21 +159,6 @@ while true; do debug "Writing $first_line to $cache_file" printf '%s\n' "$first_line" >> "$cache_file" - if (( CM_OWN_CLIPBOARD )) && [[ $selection != primary ]]; then - # Take ownership of the clipboard, in case the original application - # is unable to serve the clipboard request (due to being suspended, - # etc). - # - # Primary is excluded from the change of ownership as applications - # sometimes act up if clipboard focus is taken away from them -- - # for example, urxvt will unhilight text, which is undesirable. - # - # We can't colocate this with the above copying code because - # https://github.com/cdown/clipmenu/issues/34 requires knowing if - # we would skip first. - _xsel -k --"$selection" - fi - if (( CM_MAX_CLIPS )); then mapfile -t to_remove < <( head -n -"$CM_MAX_CLIPS" "$cache_file" | From 11304d3a60dfc469759c4662743f792cd5d4ca80 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Mon, 19 Feb 2018 15:04:52 +0000 Subject: [PATCH 4/6] Make main work block async Closes #59. --- clipmenud | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/clipmenud b/clipmenud index cd40b34..0a92dd0 100755 --- a/clipmenud +++ b/clipmenud @@ -10,7 +10,7 @@ major_version=4 cache_dir=$CM_DIR/clipmenu.$major_version.$USER/ cache_file=$cache_dir/line_cache lock_file=$cache_dir/lock -lock_timeout=2 +lock_timeout=5 has_clipnotify=0 xsel_log=/dev/null @@ -120,6 +120,7 @@ while true; do fi fi + { if ! flock -x -w "$lock_timeout" "$lock_fd"; then if (( CM_ONESHOT )); then printf 'ERROR: %s\n' 'Timed out waiting for lock' >&2 @@ -176,8 +177,10 @@ while true; do done flock -u "$lock_fd" + } & if (( CM_ONESHOT )); then + wait debug 'Oneshot mode enabled, exiting' break fi From 47eb3d182c22e4ab2584562ef9dd215df43796dd Mon Sep 17 00:00:00 2001 From: Chris Down Date: Mon, 19 Feb 2018 15:07:26 +0000 Subject: [PATCH 5/6] Use xsel -o/-i instead of -k -k is not selection based, so it also takes PRIMARY. --- clipmenud | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clipmenud b/clipmenud index 0a92dd0..994c6fb 100755 --- a/clipmenud +++ b/clipmenud @@ -107,7 +107,7 @@ while true; do # Primary is excluded from the change of ownership as applications # sometimes act up if clipboard focus is taken away from them -- # for example, urxvt will unhilight text, which is undesirable. - _xsel -k --clipboard + _xsel -o --clipboard | _xsel -i --clipboard fi if ! (( CM_ONESHOT )); then From fe6986110197aa73f22fdcbc4f4991f8350ee8b3 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Mon, 19 Feb 2018 15:11:35 +0000 Subject: [PATCH 6/6] Make sure we don't break #34 in new pre-ownership --- clipmenud | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/clipmenud b/clipmenud index 994c6fb..1a0b779 100755 --- a/clipmenud +++ b/clipmenud @@ -107,7 +107,10 @@ while true; do # Primary is excluded from the change of ownership as applications # sometimes act up if clipboard focus is taken away from them -- # for example, urxvt will unhilight text, which is undesirable. - _xsel -o --clipboard | _xsel -i --clipboard + # + # We need to check if the clipboard is empty to mitigate #34. + data=$(_xsel -o --clipboard; printf x) + [[ $data != x ]] && _xsel -i --clipboard <<< "${data%x}" fi if ! (( CM_ONESHOT )); then