diff --git a/bin/shutter b/bin/shutter index 38c70bbd..c4d240f2 100755 --- a/bin/shutter +++ b/bin/shutter @@ -232,6 +232,8 @@ if ($goocanvas) { #screenshot classes require Shutter::Screenshot::SelectorAdvanced; +require Shutter::Screenshot::SelectorGnomeWayland; +require Shutter::Screenshot::SelectorSlurpWayland; require Shutter::Screenshot::SelectorAuto; require Shutter::Screenshot::Wayland; require Shutter::Screenshot::Workspace; @@ -466,8 +468,18 @@ sub STARTUP { #UPDATE WINDOW LIST (signal is connected when GUI is loaded) my $x11_supported = 1; + my $gnome_screenshot = 0; + my $slurp = 0; + if ($ENV{XDG_SESSION_TYPE} eq "wayland") { $x11_supported = 0; + if (index(lc($ENV{XDG_CURRENT_DESKTOP}),"gnome") != -1 && -e "/usr/bin/gnome-screenshot") { + $gnome_screenshot = 1; + print "\n\n\n GNOME SCREENSHOT UNDER GNOME FOUND\n\n\n"; #DEBUG + } elsif (index(lc($ENV{XDG_CURRENT_DESKTOP}),"gnome") == -1 && -e "/usr/bin/slurp") { + $slurp = 1; + print "\n\n\n SLURP UNDER NON-GNOME FOUND\n\n\n"; #DEBUG + } } my $wnck_screen; @@ -535,7 +547,7 @@ sub STARTUP { $sm->{_menuitem_iclipboard}->signal_connect('activate', \&fct_clipboard_import); unless ($x11_supported) { - for my $name ('selection', 'awindow', 'window', 'menu', 'tooltip') { + for my $name ('awindow', 'window', 'menu', 'tooltip') { $sm->{"_menuitem_$name"}->set_sensitive(FALSE); } } @@ -874,7 +886,7 @@ sub STARTUP { unless ($x11_supported) { my $tooltip = $d->get("Can't take screenshots without X11 server"); - for my $name ('_select', '_window', '_menu', '_tooltip') { + for my $name ('_window', '_menu', '_tooltip') { $st->{$name}->set_sensitive(FALSE); $st->{$name}->set_tooltip_text($tooltip); } @@ -2980,7 +2992,7 @@ 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 ne "full" && $data ne "tray_full" && $data ne "select" && $data ne "tray_select") { 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'); @@ -4252,8 +4264,8 @@ sub STARTUP { # if $x11_supported is false, we are on Wayland, and all these buttons are already disabled and should stay disabled #menu + $sm->{_menuitem_selection}->set_sensitive($sensitive); if ($x11_supported) { - $sm->{_menuitem_selection}->set_sensitive($sensitive); $sm->{_menuitem_window}->set_sensitive($sensitive); #$sm->{_menuitem_section}->set_sensitive($sensitive); $sm->{_menuitem_menu}->set_sensitive($sensitive); @@ -4264,8 +4276,8 @@ sub STARTUP { $sm->{_menuitem_iclipboard}->set_sensitive($sensitive); #toolbar + $st->{_select}->set_sensitive($sensitive); if ($x11_supported) { - $st->{_select}->set_sensitive($sensitive); $st->{_window}->set_sensitive($sensitive); #$st->{_section}->set_sensitive($sensitive); $st->{_menu}->set_sensitive($sensitive); @@ -6097,13 +6109,33 @@ sub STARTUP { } else { - $screenshooter = Shutter::Screenshot::SelectorAdvanced->new( - $sc, $include_cursor, $delay_value, $notify_timeout_active->get_active, - $zoom_active->get_active, $hide_time->get_value, $as_help_active->get_active, $asel_size3->get_value, - $asel_size4->get_value, $asel_size1->get_value, $asel_size2->get_value, $as_confirmation_necessary->get_active, - ); + if ($gnome_screenshot) { + + print "\n\n\n We will be using gnome-screenshot!\n\n\n"; #DEBUG + + $screenshooter = Shutter::Screenshot::SelectorGnomeWayland->new( + $sc, $include_cursor, $delay_value, + $notify_timeout_active->get_active, $hide_time->get_value, + ); - $screenshot = $screenshooter->select_advanced(); + $screenshot = $screenshooter->select_gnome_wayland(); + + } elsif ($slurp) { + + print "\n\n\n We will be using slurp!\n\n\n"; #DEBUG + + $screenshot = Shutter::Screenshot::SelectorSlurpWayland::xdg_portal($screenshooter); + + } else { + + $screenshooter = Shutter::Screenshot::SelectorAdvanced->new( + $sc, $include_cursor, $delay_value, $notify_timeout_active->get_active, + $zoom_active->get_active, $hide_time->get_value, $as_help_active->get_active, $asel_size3->get_value, + $asel_size4->get_value, $asel_size1->get_value, $asel_size2->get_value, $as_confirmation_necessary->get_active, + ); + + $screenshot = $screenshooter->select_advanced(); + } } @@ -8488,7 +8520,6 @@ sub STARTUP { #selection my $menuitem_select = Gtk3::ImageMenuItem->new_with_mnemonic($d->get('_Selection')); - $menuitem_select->set_sensitive($x11_supported); 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)); diff --git a/share/shutter/resources/modules/Shutter/Screenshot/SelectorGnomeWayland.pm b/share/shutter/resources/modules/Shutter/Screenshot/SelectorGnomeWayland.pm new file mode 100644 index 00000000..980ce58c --- /dev/null +++ b/share/shutter/resources/modules/Shutter/Screenshot/SelectorGnomeWayland.pm @@ -0,0 +1,143 @@ +################################################### +# +# Copyright (C) 2008-2013 Mario Kemper +# +# This file is part of Shutter. +# +# Shutter is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Shutter is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Shutter; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +################################################### + +#perl -x -S perltidy -l=0 -b "%f" + +package Shutter::Screenshot::SelectorGnomeWayland; + +#modules +#-------------------------------------- +use utf8; +use strict; +use warnings; + +use Shutter::Screenshot::Main; +use Shutter::Screenshot::History; +use File::Temp qw/ tempfile tempdir /; + +use Data::Dumper; +our @ISA = qw(Shutter::Screenshot::Main); + +#Glib +use Glib qw/TRUE FALSE/; + +#-------------------------------------- + +sub new { + my $class = shift; + + #call constructor of super class (shutter_common, include_cursor, delay, notify_timeout) + my $self = $class->SUPER::new(shift, shift, shift, shift); + + $self->{_hide_time} = shift; #a short timeout to give the server a chance to redraw the area that was obscured + + $self->{_dpi_scale} = Gtk3::Window->new('toplevel')->get('scale-factor'); + + bless $self, $class; + return $self; +} + +sub select_gnome_wayland { + my $self = shift; + + #return value + my $output = 5; + + my $cmdcursor = undef; + + if ($self->{_include_cursor}) { + $cmdcursor = "-p"; + } + else { + $cmdcursor = ""; + } + + #A short timeout to give the server a chance to + #redraw the area + Glib::Timeout->add( + $self->{_hide_time}, + sub { + Gtk3->main_quit; + return FALSE; + }); + Gtk3->main(); + + my $fh = File::Temp->new(); + my $tmpfilename = $fh->filename; + + system("gnome-screenshot", "-a", "-f", $tmpfilename, "-d", $self->{_delay}, $cmdcursor); + + my $image = Gtk3::Image->new(); + $image->set_from_file($tmpfilename); + $output = $image->get_pixbuf(); + + my $d = $self->{_sc}->get_gettext; + + return $output; +} + + +sub redo_capture { + my $self = shift; + my $output = 3; + if (defined $self->{_history}) { + ($output) = $self->get_pixbuf_from_drawable($self->{_history}->get_last_capture); + } + return $output; +} + +sub get_history { + my $self = shift; + return $self->{_history}; +} + +sub get_error_text { + my $self = shift; + return $self->{_error_text}; +} + +sub get_action_name { + my $self = shift; + return $self->{_action_name}; +} + +sub quit { + my $self = shift; + + $self->ungrab_pointer_and_keyboard(FALSE, FALSE, TRUE); + $self->clean; +} + +sub clean { + my $self = shift; + + $self->{_selector}->signal_handler_disconnect($self->{_selector_handler}); + $self->{_view}->signal_handler_disconnect($self->{_view_zoom_handler}); + $self->{_view}->signal_handler_disconnect($self->{_view_button_handler}); + $self->{_view}->signal_handler_disconnect($self->{_view_event_handler}); + $self->{_select_window}->signal_handler_disconnect($self->{_key_handler}); + $self->{_select_window}->destroy; + $self->{_zoom_window}->destroy; + $self->{_prop_window}->destroy; +} + +1; diff --git a/share/shutter/resources/modules/Shutter/Screenshot/SelectorSlurpWayland.pm b/share/shutter/resources/modules/Shutter/Screenshot/SelectorSlurpWayland.pm new file mode 100644 index 00000000..788b1cc7 --- /dev/null +++ b/share/shutter/resources/modules/Shutter/Screenshot/SelectorSlurpWayland.pm @@ -0,0 +1,95 @@ +use utf8; +use strict; +use warnings; +use Net::DBus; +use Net::DBus::Reactor; +use Class::Struct; +use Data::Dumper; + +package Shutter::Screenshot::SelectorSlurpWayland; + +sub xdg_portal { + my $screenshooter = shift; + my $reactor = Net::DBus::Reactor->main; + my $bus = Net::DBus->find; + my $me = $bus->get_unique_name; + $me =~ s/\./_/g; + $me =~ s/^://g; + + my $pixbuf; + my $output; + + eval { + my $portal_service = $bus->get_service('org.freedesktop.portal.Desktop'); + my $portal = $portal_service->get_object('/org/freedesktop/portal/desktop', 'org.freedesktop.portal.Screenshot'); + + my $num; + my $cb = sub { + ($num, $output) = @_; + $reactor->shutdown; + }; + + my $token = 'shutter' . rand; + $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}); + 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'); + $conn = $request->connect_to_signal(Response => $cb); + } + $reactor->run; + $request->disconnect_from_signal(Response => $conn); + if ($num != 0) { + $screenshooter->{_error_text} = "Response $num from XDG portal"; + return 9; + } + my $giofile = Glib::IO::File::new_for_uri($output->{uri}); + print "xdg portal: got file ".$giofile->get_path."\n"; + $pixbuf = Gtk3::Gdk::Pixbuf->new_from_file($giofile->get_path); + my $slurpoutput = `slurp`; + my ($x, $y, $width, $height) = split /[,x ]/, $slurpoutput; + my $s = { + 'y' => $y, + 'width' => $width, + 'height' => $height, + 'x' => $x + }; + + $output = take_screenshot($s, $pixbuf); + $giofile->delete; + }; + if ($@) { + $screenshooter->{_error_text} = $@; + return 9; + }; + + return $output; +} + +sub take_screenshot { + #my $self = shift; + my $s = shift; + my $clean_pixbuf = shift; + + #my $d = $self->{_sc}->get_gettext; + + my $output; + + #no delay? then we take a subsection of the pixbuf in memory + if ($s && $clean_pixbuf ) { + + $output = $clean_pixbuf->new_subpixbuf($s->{x}, $s->{y}, $s->{width}, $s->{height}); + + print "DEBUG OUTPUT=" . $output . "\n"; + + #if there is a delay != 0 set, we have to wait and get a new pixbuf from the root window + } else { + $output = 0; + } + + return $output; +} + +1;