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>
This commit is contained in:
parent
461c65c93b
commit
c1bfdd74d8
@ -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, '']));
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user