diff --git a/js/ui/screenshot.js b/js/ui/screenshot.js index 1c724f0ba..59a6c46af 100644 --- a/js/ui/screenshot.js +++ b/js/ui/screenshot.js @@ -131,16 +131,19 @@ var ScreenshotService = class { return [null, null]; } - _onScreenshotComplete(area, stream, file, flash, invocation) { - if (flash) { - let flashspot = new Flashspot(area); - flashspot.fire(() => { - this._removeShooterForSender(invocation.get_sender()); - }); - } else { - this._removeShooterForSender(invocation.get_sender()); - } + _flashAsync(shooter) { + return new Promise((resolve, _reject) => { + shooter.connect('screenshot_taken', (s, area) => { + const flashspot = new Flashspot(area); + flashspot.fire(resolve); + global.display.get_sound_player().play_from_theme( + 'screen-capture', _('Screenshot taken'), null); + }); + }); + } + + _onScreenshotComplete(stream, file, invocation) { stream.close(null); let filenameUsed = ''; @@ -192,9 +195,12 @@ var ScreenshotService = class { return; try { - let [area] = - await screenshot.screenshot_area(x, y, width, height, stream); - this._onScreenshotComplete(area, stream, file, flash, invocation); + await Promise.all([ + flash ? this._flashAsync(screenshot) : null, + screenshot.screenshot_area(x, y, width, height, stream), + ]); + this._onScreenshotComplete(stream, file, invocation); + this._removeShooterForSender(invocation.get_sender()); } catch (e) { this._removeShooterForSender(invocation.get_sender()); invocation.return_value(new GLib.Variant('(bs)', [false, ''])); @@ -212,9 +218,12 @@ var ScreenshotService = class { return; try { - let [area] = - await screenshot.screenshot_window(includeFrame, includeCursor, stream); - this._onScreenshotComplete(area, stream, file, flash, invocation); + await Promise.all([ + flash ? this._flashAsync(screenshot) : null, + screenshot.screenshot_window(includeFrame, includeCursor, stream), + ]); + this._onScreenshotComplete(stream, file, invocation); + this._removeShooterForSender(invocation.get_sender()); } catch (e) { this._removeShooterForSender(invocation.get_sender()); invocation.return_value(new GLib.Variant('(bs)', [false, ''])); @@ -232,8 +241,12 @@ var ScreenshotService = class { return; try { - let [area] = await screenshot.screenshot(includeCursor, stream); - this._onScreenshotComplete(area, stream, file, flash, invocation); + await Promise.all([ + flash ? this._flashAsync(screenshot) : null, + screenshot.screenshot(includeCursor, stream), + ]); + this._onScreenshotComplete(stream, file, invocation); + this._removeShooterForSender(invocation.get_sender()); } catch (e) { this._removeShooterForSender(invocation.get_sender()); invocation.return_value(new GLib.Variant('(bs)', [false, ''])); diff --git a/po/POTFILES.in b/po/POTFILES.in index 4f83b62cf..37f656903 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -47,6 +47,7 @@ js/ui/panel.js js/ui/popupMenu.js js/ui/runDialog.js js/ui/screenShield.js +js/ui/screenshot.js js/ui/search.js js/ui/shellEntry.js js/ui/shellMountOperation.js diff --git a/src/shell-screenshot.c b/src/shell-screenshot.c index 321a82ec7..100429f21 100644 --- a/src/shell-screenshot.c +++ b/src/shell-screenshot.c @@ -25,6 +25,15 @@ typedef enum _ShellScreenshotMode SHELL_SCREENSHOT_AREA, } ShellScreenshotMode; +enum +{ + SCREENSHOT_TAKEN, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0, }; + typedef struct _ShellScreenshotPrivate ShellScreenshotPrivate; struct _ShellScreenshot @@ -55,7 +64,15 @@ G_DEFINE_TYPE_WITH_PRIVATE (ShellScreenshot, shell_screenshot, G_TYPE_OBJECT); static void shell_screenshot_class_init (ShellScreenshotClass *screenshot_class) { - (void) screenshot_class; + signals[SCREENSHOT_TAKEN] = + g_signal_new ("screenshot-taken", + G_TYPE_FROM_CLASS(screenshot_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, + 1, + META_TYPE_RECTANGLE); } static void @@ -321,6 +338,8 @@ grab_window_screenshot (ShellScreenshot *screenshot, draw_cursor_image (priv->image, priv->screenshot_area); } + g_signal_emit (screenshot, signals[SCREENSHOT_TAKEN], 0, &rect); + task = g_task_new (screenshot, NULL, on_screenshot_written, result); g_task_run_in_thread (task, write_screenshot_thread); g_object_unref (task); @@ -372,6 +391,9 @@ on_after_paint (ClutterStage *stage, grab_screenshot (screenshot, priv->flags, result); } + g_signal_emit (screenshot, signals[SCREENSHOT_TAKEN], 0, + (cairo_rectangle_int_t *) &priv->screenshot_area); + meta_enable_unredirect_for_display (display); } @@ -430,6 +452,9 @@ shell_screenshot_screenshot (ShellScreenshot *screenshot, if (meta_is_wayland_compositor ()) { grab_screenshot (screenshot, flags, result); + + g_signal_emit (screenshot, signals[SCREENSHOT_TAKEN], 0, + (cairo_rectangle_int_t *) &priv->screenshot_area); } else { @@ -540,6 +565,9 @@ shell_screenshot_screenshot_area (ShellScreenshot *screenshot, priv->screenshot_area.height, SHELL_SCREENSHOT_FLAG_NONE); + g_signal_emit (screenshot, signals[SCREENSHOT_TAKEN], 0, + (cairo_rectangle_int_t *) &priv->screenshot_area); + task = g_task_new (screenshot, NULL, on_screenshot_written, result); g_task_run_in_thread (task, write_screenshot_thread); }