[gnome-shell] screenshot: Fix slow audiovisual feedback on when taking screenshot
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] screenshot: Fix slow audiovisual feedback on when taking screenshot
- Date: Thu, 11 Feb 2021 18:56:34 +0000 (UTC)
commit c1bfdd74d8f03975994fedfb47cdcec99c854ae2
Author: Jonas Dreßler <verdre v0yd nl>
Date: Tue Feb 9 12:51:33 2021 +0100
screenshot: Fix slow audiovisual feedback on when taking screenshot
Add a "screenshot-taken" signal from the screenshot service's internal C
implementation, and use that to trigger the camera flash visual effect
and the click sound, allowing them to run in parallel with the PNG
compression instead of waiting until the file is complete to start.
This significantly improves perceived latency on high res setups such as
4K, 5K, or dual 4K screens.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/512
Co-authored-by: Brion Vibber <bvibber wikimedia org>
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1658>
js/ui/screenshot.js | 45 +++++++++++++++++++++++++++++----------------
po/POTFILES.in | 1 +
src/shell-screenshot.c | 30 +++++++++++++++++++++++++++++-
3 files changed, 59 insertions(+), 17 deletions(-)
---
diff --git a/js/ui/screenshot.js b/js/ui/screenshot.js
index 1c724f0bab..59a6c46aff 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());
+ _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);
});
- } else {
- this._removeShooterForSender(invocation.get_sender());
- }
+ });
+ }
+ _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 4f83b62cf7..37f6569033 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 321a82ec7d..100429f217 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);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]