Repository: alexpasmantier/television (language: rust)

Issue:
Copy to clipboard requirement
**Description**
I can't get the copy to work in the clipboard (with ctrl-y).
Does this require a special terminal?
Thank you for your help.

**Expected behavior**
The clipboard contains the copied entry.

**Actual behavior**
The clipboard is empty. The Gnome terminal offers me nothing to paste.

**Environment**
 - OS: Debian 12
 - Project version: 0.9.2
 - Build: 1.84.0




Discussion / hints:
Would you mind just double checking with another terminal and tell me if the problem persists?

Might be an issue with https://github.com/alacritty/copypasta which I use for interaction with the clipboard in tv.
Closing due to lack of more information
I tried with “copypasta” and the code proposed on github.
The text is copied and I can retrieve it via ctlr-v in gedit for example.
In tv, when I do ctlr-y in the screenshot below, the text retrieved is empty.
I was expecting “Cargo.lock” in the clipboard.
Thanks and sorry I couldn't look earlier.

![Image](https://github.com/user-attachments/assets/0e9a0739-3ba2-48dc-9f51-58034b66cbaf)
Do you have anything mapped to <kbd>ctrl-y</kbd> in either your shell configuration or your terminal emulator that might swallow the key?

Does remapping to another keybinding still produce the same outcome?
@alexpasmantier can confirm this doesn't seem to be working for x11 sessions, I am on Ubuntu24.04.2 using i3wm. Ctrl-y just doesn't seem to do anything at all. 

- I have already tried binding to a hotkey that is not used anywhere, still doesn't work. 
- Other hotkeys are working perfectly fine so seems to be some kind of clipboard related issue.
- I am using tmux + ghostty + zsh ; but i also tested with gnome-terminal + bash (still doesn't work)
- Going to try to build a debug build from the repo to see if I can get some kind of logs for the Copy event. 
- I also tested everything on separate virtual machine with a completely vanilla setup and clipboard still doesn't work.

Happy to help debug this issue, let me know if you want me to provide some specific logs.

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index fdab5f6..4d6b777 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -121,7 +121,7 @@ dependencies = [
  "miniz_oxide",
  "object",
  "rustc-demangle",
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
@@ -201,12 +201,6 @@ dependencies = [
  "serde",
 ]
 
-[[package]]
-name = "block"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
-
 [[package]]
 name = "bstr"
 version = "1.11.3"
@@ -241,32 +235,6 @@ version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc"
 
-[[package]]
-name = "calloop"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec"
-dependencies = [
- "bitflags 2.8.0",
- "log",
- "polling",
- "rustix",
- "slab",
- "thiserror 1.0.69",
-]
-
-[[package]]
-name = "calloop-wayland-source"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20"
-dependencies = [
- "calloop",
- "rustix",
- "wayland-backend",
- "wayland-client",
-]
-
 [[package]]
 name = "cassowary"
 version = "0.3.0"
@@ -372,12 +340,11 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
 
 [[package]]
 name = "clipboard-win"
-version = "3.1.1"
+version = "5.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fdf5e01086b6be750428ba4a40619f847eb2e95756eee84b18e06e5f0b50342"
+checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892"
 dependencies = [
- "lazy-bytes-cast",
- "winapi",
+ "error-code",
 ]
 
 [[package]]
@@ -411,15 +378,6 @@ dependencies = [
  "static_assertions",
 ]
 
-[[package]]
-name = "concurrent-queue"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
-dependencies = [
- "crossbeam-utils",
-]
-
 [[package]]
 name = "console"
 version = "0.15.10"
@@ -442,20 +400,6 @@ dependencies = [
  "memchr",
 ]
 
-[[package]]
-name = "copypasta"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "deb85422867ca93da58b7f95fb5c0c10f6183ed6e1ef8841568968a896d3a858"
-dependencies = [
- "clipboard-win",
- "objc",
- "objc-foundation",
- "objc_id",
- "smithay-clipboard",
- "x11-clipboard",
-]
-
 [[package]]
 name = "crc32fast"
 version = "1.4.2"
@@ -561,12 +505,6 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
 
-[[package]]
-name = "cursor-icon"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
-
 [[package]]
 name = "darling"
 version = "0.20.10"
@@ -641,21 +579,6 @@ dependencies = [
  "windows-sys 0.59.0",
 ]
 
-[[package]]
-name = "dlib"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
-dependencies = [
- "libloading",
-]
-
-[[package]]
-name = "downcast-rs"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
-
 [[package]]
 name = "either"
 version = "1.13.0"
@@ -693,6 +616,12 @@ dependencies = [
  "windows-sys 0.59.0",
 ]
 
+[[package]]
+name = "error-code"
+version = "3.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f"
+
 [[package]]
 name = "fastrand"
 version = "2.3.0"
@@ -803,16 +732,6 @@ dependencies = [
  "tempfile",
 ]
 
-[[package]]
-name = "gethostname"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818"
-dependencies = [
- "libc",
- "windows-targets 0.48.5",
-]
-
 [[package]]
 name = "getrandom"
 version = "0.2.15"
@@ -833,7 +752,7 @@ dependencies = [
  "cfg-if",
  "libc",
  "wasi 0.13.3+wasi-0.2.2",
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
@@ -1016,12 +935,6 @@ dependencies = [
  "wasm-bindgen",
 ]
 
-[[package]]
-name = "lazy-bytes-cast"
-version = "5.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10257499f089cd156ad82d0a9cd57d9501fa2c989068992a97eb3c27836f206b"
-
 [[package]]
 name = "lazy_static"
 version = "1.5.0"
@@ -1034,16 +947,6 @@ version = "0.2.169"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
 
-[[package]]
-name = "libloading"
-version = "0.8.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
-dependencies = [
- "cfg-if",
- "windows-targets 0.52.6",
-]
-
 [[package]]
 name = "libredox"
 version = "0.1.3"
@@ -1085,15 +988,6 @@ dependencies = [
  "hashbrown",
 ]
 
-[[package]]
-name = "malloc_buf"
-version = "0.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
-dependencies = [
- "libc",
-]
-
 [[package]]
 name = "matchers"
 version = "0.1.0"
@@ -1109,15 +1003,6 @@ version = "2.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
 
-[[package]]
-name = "memmap2"
-version = "0.9.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f"
-dependencies = [
- "libc",
-]
-
 [[package]]
 name = "minimal-lexical"
 version = "0.2.1"
@@ -1210,35 +1095,6 @@ dependencies = [
  "autocfg",
 ]
 
-[[package]]
-name = "objc"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
-dependencies = [
- "malloc_buf",
-]
-
-[[package]]
-name = "objc-foundation"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
-dependencies = [
- "block",
- "objc",
- "objc_id",
-]
-
-[[package]]
-name = "objc_id"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
-dependencies = [
- "objc",
-]
-
 [[package]]
 name = "object"
 version = "0.36.7"
@@ -1325,7 +1181,7 @@ dependencies = [
  "libc",
  "redox_syscall",
  "smallvec",
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
@@ -1369,7 +1225,7 @@ checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016"
 dependencies = [
  "base64",
  "indexmap",
- "quick-xml 0.32.0",
+ "quick-xml",
  "serde",
  "time",
 ]
@@ -1402,21 +1258,6 @@ dependencies = [
  "plotters-backend",
 ]
 
-[[package]]
-name = "polling"
-version = "3.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f"
-dependencies = [
- "cfg-if",
- "concurrent-queue",
- "hermit-abi",
- "pin-project-lite",
- "rustix",
- "tracing",
- "windows-sys 0.59.0",
-]
-
 [[package]]
 name = "powerfmt"
 version = "0.2.0"
@@ -1441,15 +1282,6 @@ dependencies = [
  "memchr",
 ]
 
-[[package]]
-name = "quick-xml"
-version = "0.37.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "165859e9e55f79d67b96c5d96f4e88b6f2695a1972849c15a6a3f5c59fc2c003"
-dependencies = [
- "memchr",
-]
-
 [[package]]
 name = "quote"
 version = "1.0.38"
@@ -1620,12 +1452,6 @@ dependencies = [
  "winapi-util",
 ]
 
-[[package]]
-name = "scoped-tls"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
-
 [[package]]
 name = "scopeguard"
 version = "1.2.0"
@@ -1766,57 +1592,12 @@ version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
 
-[[package]]
-name = "slab"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
-dependencies = [
- "autocfg",
-]
-
 [[package]]
 name = "smallvec"
 version = "1.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
 
-[[package]]
-name = "smithay-client-toolkit"
-version = "0.19.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016"
-dependencies = [
- "bitflags 2.8.0",
- "calloop",
- "calloop-wayland-source",
- "cursor-icon",
- "libc",
- "log",
- "memmap2",
- "rustix",
- "thiserror 1.0.69",
- "wayland-backend",
- "wayland-client",
- "wayland-csd-frame",
- "wayland-cursor",
- "wayland-protocols",
- "wayland-protocols-wlr",
- "wayland-scanner",
- "xkeysym",
-]
-
-[[package]]
-name = "smithay-clipboard"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc8216eec463674a0e90f29e0ae41a4db573ec5b56b1c6c1c71615d249b6d846"
-dependencies = [
- "libc",
- "smithay-client-toolkit",
- "wayland-backend",
-]
-
 [[package]]
 name = "socket2"
 version = "0.5.8"
@@ -1903,10 +1684,11 @@ name = "television"
 version = "0.10.6"
 dependencies = [
  "anyhow",
+ "base64",
  "bat",
  "better-panic",
  "clap",
- "copypasta",
+ "clipboard-win",
  "criterion",
  "crossterm",
  "devicons",
@@ -2348,102 +2130,6 @@ dependencies = [
  "unicode-ident",
 ]
 
-[[package]]
-name = "wayland-backend"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7208998eaa3870dad37ec8836979581506e0c5c64c20c9e79e9d2a10d6f47bf"
-dependencies = [
- "cc",
- "downcast-rs",
- "rustix",
- "scoped-tls",
- "smallvec",
- "wayland-sys",
-]
-
-[[package]]
-name = "wayland-client"
-version = "0.31.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2120de3d33638aaef5b9f4472bff75f07c56379cf76ea320bd3a3d65ecaf73f"
-dependencies = [
- "bitflags 2.8.0",
- "rustix",
- "wayland-backend",
- "wayland-scanner",
-]
-
-[[package]]
-name = "wayland-csd-frame"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e"
-dependencies = [
- "bitflags 2.8.0",
- "cursor-icon",
- "wayland-backend",
-]
-
-[[package]]
-name = "wayland-cursor"
-version = "0.31.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a93029cbb6650748881a00e4922b076092a6a08c11e7fbdb923f064b23968c5d"
-dependencies = [
- "rustix",
- "wayland-client",
- "xcursor",
-]
-
-[[package]]
-name = "wayland-protocols"
-version = "0.32.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0781cf46869b37e36928f7b432273c0995aa8aed9552c556fb18754420541efc"
-dependencies = [
- "bitflags 2.8.0",
- "wayland-backend",
- "wayland-client",
- "wayland-scanner",
-]
-
-[[package]]
-name = "wayland-protocols-wlr"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "248a02e6f595aad796561fa82d25601bd2c8c3b145b1c7453fc8f94c1a58f8b2"
-dependencies = [
- "bitflags 2.8.0",
- "wayland-backend",
- "wayland-client",
- "wayland-protocols",
- "wayland-scanner",
-]
-
-[[package]]
-name = "wayland-scanner"
-version = "0.31.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484"
-dependencies = [
- "proc-macro2",
- "quick-xml 0.37.2",
- "quote",
-]
-
-[[package]]
-name = "wayland-sys"
-version = "0.31.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbcebb399c77d5aa9fa5db874806ee7b4eba4e73650948e8f93963f128896615"
-dependencies = [
- "dlib",
- "log",
- "once_cell",
- "pkg-config",
-]
-
 [[package]]
 name = "web-sys"
 version = "0.3.77"
@@ -2492,7 +2178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132"
 dependencies = [
  "windows-core",
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
@@ -2504,7 +2190,7 @@ dependencies = [
  "windows-implement",
  "windows-interface",
  "windows-result",
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
@@ -2535,7 +2221,7 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
 dependencies = [
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
@@ -2544,7 +2230,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
 dependencies = [
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
@@ -2553,22 +2239,7 @@ version = "0.59.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
 dependencies = [
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
-dependencies = [
- "windows_aarch64_gnullvm 0.48.5",
- "windows_aarch64_msvc 0.48.5",
- "windows_i686_gnu 0.48.5",
- "windows_i686_msvc 0.48.5",
- "windows_x86_64_gnu 0.48.5",
- "windows_x86_64_gnullvm 0.48.5",
- "windows_x86_64_msvc 0.48.5",
+ "windows-targets",
 ]
 
 [[package]]
@@ -2577,46 +2248,28 @@ version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
 dependencies = [
- "windows_aarch64_gnullvm 0.52.6",
- "windows_aarch64_msvc 0.52.6",
- "windows_i686_gnu 0.52.6",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
  "windows_i686_gnullvm",
- "windows_i686_msvc 0.52.6",
- "windows_x86_64_gnu 0.52.6",
- "windows_x86_64_gnullvm 0.52.6",
- "windows_x86_64_msvc 0.52.6",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
 ]
 
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
-
 [[package]]
 name = "windows_aarch64_gnullvm"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
 
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
-
 [[package]]
 name = "windows_aarch64_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
 
-[[package]]
-name = "windows_i686_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
-
 [[package]]
 name = "windows_i686_gnu"
 version = "0.52.6"
@@ -2629,48 +2282,24 @@ version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
 
-[[package]]
-name = "windows_i686_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
-
 [[package]]
 name = "windows_i686_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
 
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
-
 [[package]]
 name = "windows_x86_64_gnu"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
 
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
-
 [[package]]
 name = "windows_x86_64_gnullvm"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
 
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
-
 [[package]]
 name = "windows_x86_64_msvc"
 version = "0.52.6"
@@ -2695,45 +2324,6 @@ dependencies = [
  "bitflags 2.8.0",
 ]
 
-[[package]]
-name = "x11-clipboard"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "662d74b3d77e396b8e5beb00b9cad6a9eccf40b2ef68cc858784b14c41d535a3"
-dependencies = [
- "libc",
- "x11rb",
-]
-
-[[package]]
-name = "x11rb"
-version = "0.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12"
-dependencies = [
- "gethostname",
- "rustix",
- "x11rb-protocol",
-]
-
-[[package]]
-name = "x11rb-protocol"
-version = "0.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d"
-
-[[package]]
-name = "xcursor"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61"
-
-[[package]]
-name = "xkeysym"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56"
-
 [[package]]
 name = "xterm-color"
 version = "1.0.1"
diff --git a/Cargo.toml b/Cargo.toml
index 4f46516..c31c645 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -31,6 +31,7 @@ path = "television/lib.rs"
 television-derive = { path = "television-derive", version = "0.0.25" }
 
 anyhow = "1.0"
+base64 = "0.22.1"
 directories = "6.0"
 devicons = "0.6"
 lazy_static = "1.5"
@@ -46,7 +47,6 @@ ratatui = { version = "0.29", features = ["serde", "macros"] }
 better-panic = "0.3"
 signal-hook = "0.3"
 human-panic = "2.0"
-copypasta = "0.10"
 ignore = "0.4"
 strum = { version = "0.26", features = ["derive"] }
 regex = "1.11"
@@ -62,6 +62,7 @@ toml = "0.8"
 
 [target.'cfg(windows)'.dependencies]
 winapi-util = "0.1.9"
+clipboard-win = "5.4.0"
 
 [dev-dependencies]
 criterion = { version = "0.5", features = ["async_tokio"] }
diff --git a/television/main.rs b/television/main.rs
index 9eed959..d60b447 100644
--- a/television/main.rs
+++ b/television/main.rs
@@ -5,6 +5,7 @@ use std::process::exit;
 
 use anyhow::Result;
 use clap::Parser;
+use television::utils::clipboard::CLIPBOARD;
 use tracing::{debug, error, info};
 
 use television::app::App;
@@ -77,6 +78,8 @@ async fn main() -> Result<()> {
         env::set_current_dir(path)?;
     }
 
+    CLIPBOARD.with(<_>::default);
+
     match App::new(
         {
             if is_readable_stdin() {
diff --git a/television/television.rs b/television/television.rs
index c5acc44..980d33b 100644
--- a/television/television.rs
+++ b/television/television.rs
@@ -13,15 +13,14 @@ use crate::preview::{PreviewState, Previewer};
 use crate::screen::colors::Colorscheme;
 use crate::screen::layout::InputPosition;
 use crate::screen::spinner::{Spinner, SpinnerState};
+use crate::utils::clipboard::CLIPBOARD;
 use crate::utils::metadata::AppMetadata;
 use crate::utils::strings::EMPTY_STRING;
 use anyhow::Result;
-use copypasta::{ClipboardContext, ClipboardProvider};
 use rustc_hash::{FxBuildHasher, FxHashSet};
 use serde::{Deserialize, Serialize};
 use std::collections::HashSet;
 use tokio::sync::mpsc::{Receiver, Sender, UnboundedSender};
-use tracing::error;
 
 #[derive(PartialEq, Copy, Clone, Hash, Eq, Debug, Serialize, Deserialize)]
 pub enum Mode {
@@ -480,20 +479,13 @@ impl Television {
     pub fn handle_copy_entry_to_clipboard(&mut self) {
         if self.mode == Mode::Channel {
             if let Some(entries) = self.get_selected_entries(None) {
-                if let Ok(mut ctx) = ClipboardContext::new() {
-                    ctx.set_contents(
-                        entries
-                            .iter()
-                            .map(|e| e.name.clone())
-                            .collect::<Vec<_>>()
-                            .join(" "),
-                    )
-                    .unwrap_or_else(|_| {
-                        error!("Could not copy to clipboard");
-                    });
-                } else {
-                    error!("Could not copy to clipboard");
-                }
+                let copied_string = entries
+                    .iter()
+                    .map(|e| e.name.clone())
+                    .collect::<Vec<_>>()
+                    .join(" ");
+
+                tokio::spawn(CLIPBOARD.set(copied_string));
             }
         }
     }
diff --git a/television/utils/clipboard.rs b/television/utils/clipboard.rs
new file mode 100644
index 0000000..86c58d2
--- /dev/null
+++ b/television/utils/clipboard.rs
@@ -0,0 +1,177 @@
+/*
+MIT License
+
+Copyright (c) 2023 - sxyazi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+use std::ffi::OsString;
+
+use crate::utils::rocell::RoCell;
+use parking_lot::Mutex;
+
+pub static CLIPBOARD: RoCell<Clipboard> = RoCell::new();
+
+#[derive(Default)]
+pub struct Clipboard {
+    content: Mutex<OsString>,
+}
+
+impl Clipboard {
+    #[cfg(unix)]
+    pub async fn get(&self) -> OsString {
+        use std::os::unix::prelude::OsStringExt;
+
+        use tokio::process::Command;
+
+        let all = [
+            ("pbpaste", &[][..]),
+            ("termux-clipboard-get", &[]),
+            ("wl-paste", &[]),
+            ("xclip", &["-o", "-selection", "clipboard"]),
+            ("xsel", &["-ob"]),
+        ];
+
+        for (bin, args) in all {
+            let Ok(output) = Command::new(bin)
+                .args(args)
+                .kill_on_drop(true)
+                .output()
+                .await
+            else {
+                continue;
+            };
+            if output.status.success() {
+                return OsString::from_vec(output.stdout);
+            }
+        }
+        self.content.lock().clone()
+    }
+
+    #[cfg(windows)]
+    pub async fn get(&self) -> OsString {
+        use clipboard_win::{formats, get_clipboard};
+
+        let result = tokio::task::spawn_blocking(|| {
+            get_clipboard::<String, _>(formats::Unicode)
+        });
+        if let Ok(Ok(s)) = result.await {
+            return s.into();
+        }
+
+        self.content.lock().clone()
+    }
+
+    #[cfg(unix)]
+    pub async fn set(&self, s: impl AsRef<std::ffi::OsStr>) {
+        use std::{
+            io::{stderr, BufWriter},
+            process::Stdio,
+        };
+
+        use crossterm::execute;
+        use tokio::{io::AsyncWriteExt, process::Command};
+
+        s.as_ref().clone_into(&mut self.content.lock());
+        execute!(
+            BufWriter::new(stderr()),
+            osc52::SetClipboard::new(s.as_ref())
+        )
+        .ok();
+
+        let all = [
+            ("pbcopy", &[][..]),
+            ("termux-clipboard-set", &[]),
+            ("wl-copy", &[]),
+            ("xclip", &["-selection", "clipboard"]),
+            ("xsel", &["-ib"]),
+        ];
+
+        for (bin, args) in all {
+            let cmd = Command::new(bin)
+                .args(args)
+                .stdin(Stdio::piped())
+                .stdout(Stdio::null())
+                .stderr(Stdio::null())
+                .kill_on_drop(true)
+                .spawn();
+
+            let Ok(mut child) = cmd else { continue };
+
+            let mut stdin = child.stdin.take().unwrap();
+            if stdin
+                .write_all(s.as_ref().as_encoded_bytes())
+                .await
+                .is_err()
+            {
+                continue;
+            }
+            drop(stdin);
+
+            if child.wait().await.is_ok_and(|s| s.success()) {
+                break;
+            }
+        }
+    }
+
+    #[cfg(windows)]
+    pub async fn set(&self, s: impl AsRef<std::ffi::OsStr>) {
+        use clipboard_win::{formats, set_clipboard};
+
+        let s = s.as_ref().to_owned();
+        *self.content.lock() = s.clone();
+
+        tokio::task::spawn_blocking(move || {
+            set_clipboard(formats::Unicode, s.to_string_lossy())
+        })
+        .await
+        .ok();
+    }
+}
+
+#[cfg(unix)]
+mod osc52 {
+    use std::ffi::OsStr;
+
+    use base64::{engine::general_purpose, Engine};
+
+    #[derive(Debug)]
+    pub struct SetClipboard {
+        content: String,
+    }
+
+    impl SetClipboard {
+        pub fn new(content: &OsStr) -> Self {
+            Self {
+                content: general_purpose::STANDARD
+                    .encode(content.as_encoded_bytes()),
+            }
+        }
+    }
+
+    impl crossterm::Command for SetClipboard {
+        fn write_ansi(
+            &self,
+            f: &mut impl std::fmt::Write,
+        ) -> std::fmt::Result {
+            write!(f, "\x1b]52;c;{}\x1b\\", self.content)
+        }
+    }
+}
diff --git a/television/utils/mod.rs b/television/utils/mod.rs
index 80fa27a..0b88158 100644
--- a/television/utils/mod.rs
+++ b/television/utils/mod.rs
@@ -1,10 +1,12 @@
 pub mod cache;
+pub mod clipboard;
 pub mod command;
 pub mod files;
 pub mod hashmaps;
 pub mod indices;
 pub mod input;
 pub mod metadata;
+pub mod rocell;
 pub mod shell;
 pub mod stdin;
 pub mod strings;
diff --git a/television/utils/rocell.rs b/television/utils/rocell.rs
new file mode 100644
index 0000000..d3758e6
--- /dev/null
+++ b/television/utils/rocell.rs
@@ -0,0 +1,99 @@
+/*
+MIT License
+
+Copyright (c) 2023 - sxyazi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+use std::{
+    cell::UnsafeCell,
+    fmt::{self, Display},
+    mem,
+    ops::Deref,
+};
+
+// Read-only cell. It's safe to use this in a static variable, but it's not safe
+// to mutate it. This is useful for storing static data that is expensive to
+// initialize, but is immutable once.
+pub struct RoCell<T>(UnsafeCell<Option<T>>);
+
+unsafe impl<T> Sync for RoCell<T> {}
+
+impl<T> RoCell<T> {
+    #[inline]
+    pub const fn new() -> Self {
+        Self(UnsafeCell::new(None))
+    }
+
+    #[inline]
+    pub const fn new_const(value: T) -> Self {
+        Self(UnsafeCell::new(Some(value)))
+    }
+
+    #[inline]
+    pub fn init(&self, value: T) {
+        debug_assert!(!self.initialized());
+        unsafe {
+            *self.0.get() = Some(value);
+        }
+    }
+
+    #[inline]
+    pub fn with<F>(&self, f: F)
+    where
+        F: FnOnce() -> T,
+    {
+        self.init(f());
+    }
+
+    #[inline]
+    pub fn drop(&self) -> T {
+        debug_assert!(self.initialized());
+        unsafe { mem::take(&mut *self.0.get()).unwrap_unchecked() }
+    }
+
+    #[inline]
+    fn initialized(&self) -> bool {
+        unsafe { (*self.0.get()).is_some() }
+    }
+}
+
+impl<T> Default for RoCell<T> {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl<T> Deref for RoCell<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        debug_assert!(self.initialized());
+        unsafe { (*self.0.get()).as_ref().unwrap_unchecked() }
+    }
+}
+
+impl<T> Display for RoCell<T>
+where
+    T: Display,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.deref().fmt(f)
+    }
+}


Test patch: