Skip to content

Commit

Permalink
Refactor grabclipboard() for x11 and wayland
Browse files Browse the repository at this point in the history
Simpified logic and made it more robust against edge cases ( see the `allowed_errors` list ). Doing error checking this way, makes the behaviour of this function for x11 and wayland platforms more silimar to darwin and windows systems.

fix typo src/PIL/ImageGrab.py

Co-authored-by: Ondrej Baranovič <nulano@nulano.eu>

fix typo src/PIL/ImageGrab.py

Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com>

ImageGrab: \added debian edge case to comment
  • Loading branch information
nik012003 committed Jan 27, 2024
1 parent 1185fb8 commit 853717b
Showing 1 changed file with 13 additions and 15 deletions.
28 changes: 13 additions & 15 deletions src/PIL/ImageGrab.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,29 +149,27 @@ def grabclipboard():
session_type = None

if shutil.which("wl-paste") and session_type in ("wayland", None):
output = subprocess.check_output(["wl-paste", "-l"]).decode()
mimetypes = output.splitlines()
if "image/png" in mimetypes:
mimetype = "image/png"
elif mimetypes:
mimetype = mimetypes[0]
else:
mimetype = None

args = ["wl-paste"]
if mimetype:
args.extend(["-t", mimetype])
args = ["wl-paste", "-t", "image"]
elif shutil.which("xclip") and session_type in ("x11", None):
args = ["xclip", "-selection", "clipboard", "-t", "image/png", "-o"]
else:
msg = "wl-paste or xclip is required for ImageGrab.grabclipboard() on Linux"
raise NotImplementedError(msg)

p = subprocess.run(args, capture_output=True)
err = p.stderr
if err:
msg = f"{args[0]} error: {err.strip().decode()}"
err = p.stderr.decode()
if p.returncode != 0:
allowed_errors = [
"Nothing is copied", # wl-paste, when the clipboard is empty
"not available", # wl-paste or debian xclip, when an image isn't available
"cannot convert", # xclip, when an image isn't available
"There is no owner", # xclip, when the clipboard isn't initialized
]
if any(e in err for e in allowed_errors):
return None
msg = f"{args[0]} error: {err.strip() if err else 'Unknown error'}"
raise ChildProcessError(msg)

data = io.BytesIO(p.stdout)
im = Image.open(data)
im.load()
Expand Down

0 comments on commit 853717b

Please sign in to comment.