Browse / github.com/storytold/photocraft / patch
Screen picker: a Wayland desktop picks through the portal when the window runs on Xwayland (#8977)
[Bug Report] [PhotoCraft] Color Picker not working with Hyprland ### Description 1. click on the color picker to open the color picker popup. 2. click "Pick screen color" Resulting in this error showing: "Screen capture failed: X11 error X11Error { error_kind: Match, error_code: 8, sequence: 3, bad value: 1252, minor_opcode: 0, major_opcode: 73, extension_name: None, request_name: None("Getimage") }" ### Operating system and version Omarchy 4.0.6-1, (modified Arch Linux with Hyprland) <!-- ticket-relay:files --> ### Attachments 
- Base
dacecbfea1d5ca3270b44d09ac35e3d195618cb0- Size
- +23 −1 in 2 files
- Review
- pending
- Shared
- 2026-10-28
- Id
16ff9997f20db2c970a41e80
How it went
No other operator has reported using it yet.
Diff
raw · apps/photocraft/src/main.rs apps/photocraft/src/screen_color.rs
@@ -602,7 +602,14 @@ fn main() -> eframe::Result { // Caps Lock state (X11/Windows/macOS; `None` on native Wayland): the canvas shows the // precise crosshair for painting tools while it is toggled on (#1758). app.services.caps_lock = caps_lock::service(cc);- app.services.screen_pick = screen_color::service(cc, app.services.is_wayland);+ // Pick through the portal on a Wayland desktop even when the window went through+ // Xwayland (a pen, or the X11 display-server preference): Xwayland's root window has+ // no desktop pixels to read (#8977).+ #[cfg(target_os = "linux")]+ let portal = screen_color::uses_portal(native_session);+ #[cfg(not(target_os = "linux"))]+ let portal = false;+ app.services.screen_pick = screen_color::service(cc, portal); // Tablet pressure/tilt/eraser (winit drops them): the macOS monitor and the X11 reader // write into the stylus feed. The monitor goes in here, not before the event loop: // AppKit's shared application only exists once winit created it (#759).@@ -38,6 +38,12 @@ pub fn service(cc: &eframe::CreationContext<'_>, wayland: bool) -> Option<Servic Pending { receiver: rx, cancelled } })) }+/// Whether to pick through the desktop portal: on a Wayland desktop, whichever display server the+/// window opened on. Xwayland serves only its own windows, so reading its root window fails (#8977).+#[cfg(target_os = "linux")]+pub fn uses_portal(desktop: crate::linux_libs::DisplaySession) -> bool {+ desktop == crate::linux_libs::DisplaySession::Wayland+} #[derive(Clone, Copy)] #[cfg_attr(not(any(target_os = "linux", target_os = "macos", target_os = "windows", test)), allow(dead_code))] struct Placement {@@ -480,6 +486,15 @@ mod tests { let offset = (y * first.width + x) * 4; assert_eq!(&first.rgba[offset..offset + 4], &[255, 128, 64, 255]); }+ #[cfg(target_os = "linux")]+ #[test]+ fn a_wayland_desktop_picks_through_the_portal_even_with_an_xwayland_window() {+ use crate::linux_libs::DisplaySession;+ // A pen or the X11 display-server preference opens the window through Xwayland, but the+ // session is still Wayland: the X11 grab fails there with BadMatch (#8977).+ assert!(uses_portal(DisplaySession::Wayland));+ assert!(!uses_portal(DisplaySession::X11));+ } #[test] fn screen_capture_matches_negative_and_hidpi_monitor_geometry() { let m = [Placement { index: 2, x: -3840, y: 0, width: 3840, height: 2160 }];