Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions bin/shutter
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,9 @@ sub STARTUP {
$sm->{_menuitem_iclipboard}->signal_connect('activate', \&fct_clipboard_import);

unless ($x11_supported) {
for my $name ('selection', 'awindow', 'window', 'menu', 'tooltip') {
# on Wayland selection/window/awindow go through the interactive XDG portal;
# only menu/tooltip capture stay disabled (not supported by the portal)
for my $name ('menu', 'tooltip') {
$sm->{"_menuitem_$name"}->set_sensitive(FALSE);
}
}
Expand Down Expand Up @@ -1000,11 +1002,13 @@ sub STARTUP {
$st->{_upload}->set_sensitive(FALSE);

unless ($x11_supported) {
# on Wayland _select/_window use the interactive XDG portal; menu/tooltip stay disabled
my $tooltip = $d->get("Can't take screenshots without X11 server");
for my $name ('_select', '_window', '_menu', '_tooltip') {
for my $name ('_menu', '_tooltip') {
$st->{$name}->set_sensitive(FALSE);
$st->{$name}->set_tooltip_text($tooltip);
}
# dropdown menus (workspace list / window list) still need X11 to enumerate
for my $name ('_full', '_window') {
$st->{$name}->set_arrow_tooltip_text($tooltip);
}
Expand Down Expand Up @@ -3128,7 +3132,10 @@ sub STARTUP {
#unblock signal handler
fct_control_signals('unblock');
return TRUE;
} elsif (!$x11_supported && $data ne "full" && $data ne "tray_full") {
} elsif (!$x11_supported
&& $data !~ /^(tray_)?(full|select|window|awindow)$/) {
# full/select/window/awindow are served via the XDG portal on Wayland;
# everything else (menu, tooltip, ...) still needs X11
my $sd = Shutter::App::SimpleDialogs->new;
$sd->dlg_error_message($d->get("Can't take screenshots without X11 server"), $d->get("Failed"));
fct_control_signals('unblock');
Expand Down Expand Up @@ -6183,8 +6190,14 @@ sub STARTUP {
}
}

#wayland: route selection/window/active to the compositor's interactive picker
if (!$x11_supported
&& $data =~ /^(tray_)?(select|window|awindow)$/) {

$screenshot = Shutter::Screenshot::Wayland::xdg_portal($screenshooter, 1);

#fullscreen screenshot
if ($data eq "full" || $data eq "tray_full") {
} elsif ($data eq "full" || $data eq "tray_full") {

if ($x11_supported) {
$screenshooter = Shutter::Screenshot::Workspace->new(
Expand Down Expand Up @@ -8655,7 +8668,8 @@ sub STARTUP {

#selection
my $menuitem_select = Gtk3::ImageMenuItem->new_with_mnemonic($d->get('_Selection'));
$menuitem_select->set_sensitive($x11_supported);
# served via interactive XDG portal on Wayland too
$menuitem_select->set_sensitive(TRUE);
eval {
my $ccursor_pb = Gtk3::Gdk::Cursor::new('left_ptr')->get_image->scale_simple($shf->icon_size('menu'), 'bilinear');
$menuitem_select->set_image(Gtk3::Image->new_from_pixbuf($ccursor_pb));
Expand Down Expand Up @@ -8704,7 +8718,8 @@ sub STARTUP {

#window
my $menuitem_window = Gtk3::ImageMenuItem->new_with_mnemonic($d->get('Window _under Cursor'));
$menuitem_window->set_sensitive($x11_supported);
# served via interactive XDG portal on Wayland too
$menuitem_window->set_sensitive(TRUE);
if ($traytheme->has_icon('preferences-system-windows')) {
$menuitem_window->set_image(Gtk3::Image->new_from_icon_name('preferences-system-windows', 'menu'));
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Selezione interattiva su Wayland (strada A)

Data: 2026-05-21
Branch: `feature/wayland-interactive-selection`

## Problema

Su Wayland Shutter cattura solo lo schermo intero (via `xdg-desktop-portal`).
I bottoni Selezione area, Finestra e Attiva sono disabilitati perché dipendono
da X11 (`Wnck`, `GdkX11`), non accessibile su Wayland per ragioni di sicurezza.
Riferimento upstream: issue #187.

## Obiettivo

Abilitare su Wayland i bottoni Selezione / Finestra / Attiva. Tutti invocano il
portal XDG in modalità **interattiva**: il compositor (GNOME) mostra il proprio
selettore nativo (area / finestra / schermo) e ritorna un'immagine già ritagliata,
che entra nel flusso post-cattura esistente di Shutter.

## Componenti toccati

### 1. `share/shutter/resources/modules/Shutter/Screenshot/Wayland.pm`
- `xdg_portal($screenshooter, $interactive)`: nuovo secondo parametro.
- Opzioni portal: `{handle_token => $token, interactive => $interactive ? TRUE : FALSE}`.
- Chiamata full-screen attuale → passa `FALSE` (comportamento invariato).

### 2. `bin/shutter` (~riga 4406)
- Logica che disabilita i bottoni su Wayland (`$x11_supported` falso): condizionare
così che Selezione, Finestra e Attiva restino **abilitati** anche su Wayland.
- Bottoni che richiedono geometria/regex predefinita restano fuori scope (vedi sotto).

### 3. `bin/shutter` (~riga 6198, dispatch cattura)
- Quando modalità = select / window / active **e** sessione = Wayland →
chiamare `Shutter::Screenshot::Wayland::xdg_portal($s, TRUE)` invece del path X11.

## Flusso

1. Utente clicca un bottone di selezione.
2. Shutter chiama il portal in modalità interattiva.
3. GNOME mostra il selettore nativo; l'utente sceglie area/finestra/schermo.
4. Il portal ritorna l'URI del file (immagine già ritagliata).
5. Shutter carica il pixbuf e prosegue con il **post-processing esistente**
(salvataggio / editor / upload). Identico al full-screen Wayland già funzionante.

## Gestione errori

- Response `num != 0` dal portal = utente ha annullato nel selettore GNOME.
→ Abort silenzioso, nessun dialog d'errore (cancellazione volontaria, non fallimento).
- Eccezioni DBus → comportamento attuale (`_error_text`), invariato.

## Fuori scope

- Cattura finestra per nome/regex (`--window=PATTERN`): il portal non accetta target.
- Selezione con coordinate predefinite (`-s=X,Y,W,H`): il portal non accetta geometria.
- Overlay di selezione nativo di Shutter su Wayland: resta inattivo; il selettore è
quello di GNOME.

## Test (sessione Wayland)

- Ogni bottone (Selezione / Finestra / Attiva) apre il selettore GNOME.
- L'immagine catturata viene caricata in Shutter e segue il flusso normale.
- Annullamento nel selettore non genera dialog d'errore.
- Regressione: full-screen su Wayland e tutta la cattura su Xorg restano invariati.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package Shutter::Screenshot::Wayland;

sub xdg_portal {
my $screenshooter = shift;
my $interactive = shift;
my $reactor = Net::DBus::Reactor->main;
my $bus = Net::DBus->find;
my $me = $bus->get_unique_name;
Expand All @@ -31,7 +32,10 @@ sub xdg_portal {
$token =~ s/\.//g;
my $request = $portal_service->get_object("/org/freedesktop/portal/desktop/request/$me/$token", 'org.freedesktop.portal.Request');
my $conn = $request->connect_to_signal(Response => $cb);
my $request_path = $portal->Screenshot('', {handle_token=>$token});
# interactive=true lets the compositor show its native picker (area/window/screen)
my %options = (handle_token => $token);
$options{interactive} = Net::DBus::dbus_boolean(1) if $interactive;
my $request_path = $portal->Screenshot('', \%options);
if ($request->get_object_path ne $request_path) {
$request->disconnect_from_signal(Response => $conn);
$request = $portal_service->get_object($request_path, 'org.freedesktop.portal.Request');
Expand All @@ -40,6 +44,8 @@ sub xdg_portal {
$reactor->run;
$request->disconnect_from_signal(Response => $conn);
if ($num != 0) {
# portal Response: 1 = user cancelled -> treat as abort (code 5), not error
return 5 if $num == 1;
$screenshooter->{_error_text} = "Response $num from XDG portal";
return 9;
}
Expand Down
Loading