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];
|
return [null, null];
|
||||||
}
|
}
|
||||||
|
|
||||||
_onScreenshotComplete(area, stream, file, flash, invocation) {
|
_flashAsync(shooter) {
|
||||||
if (flash) {
|
return new Promise((resolve, _reject) => {
|
||||||
let flashspot = new Flashspot(area);
|
shooter.connect('screenshot_taken', (s, area) => {
|
||||||
flashspot.fire(() => {
|
const flashspot = new Flashspot(area);
|
||||||
this._removeShooterForSender(invocation.get_sender());
|
flashspot.fire(resolve);
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this._removeShooterForSender(invocation.get_sender());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
global.display.get_sound_player().play_from_theme(
|
||||||
|
'screen-capture', _('Screenshot taken'), null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_onScreenshotComplete(stream, file, invocation) {
|
||||||
stream.close(null);
|
stream.close(null);
|
||||||
|
|
||||||
let filenameUsed = '';
|
let filenameUsed = '';
|
||||||
@ -192,9 +195,12 @@ var ScreenshotService = class {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let [area] =
|
await Promise.all([
|
||||||
await screenshot.screenshot_area(x, y, width, height, stream);
|
flash ? this._flashAsync(screenshot) : null,
|
||||||
this._onScreenshotComplete(area, stream, file, flash, invocation);
|
screenshot.screenshot_area(x, y, width, height, stream),
|
||||||
|
]);
|
||||||
|
this._onScreenshotComplete(stream, file, invocation);
|
||||||
|
this._removeShooterForSender(invocation.get_sender());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this._removeShooterForSender(invocation.get_sender());
|
this._removeShooterForSender(invocation.get_sender());
|
||||||
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
|
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
|
||||||
@ -212,9 +218,12 @@ var ScreenshotService = class {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let [area] =
|
await Promise.all([
|
||||||
await screenshot.screenshot_window(includeFrame, includeCursor, stream);
|
flash ? this._flashAsync(screenshot) : null,
|
||||||
this._onScreenshotComplete(area, stream, file, flash, invocation);
|
screenshot.screenshot_window(includeFrame, includeCursor, stream),
|
||||||
|
]);
|
||||||
|
this._onScreenshotComplete(stream, file, invocation);
|
||||||
|
this._removeShooterForSender(invocation.get_sender());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this._removeShooterForSender(invocation.get_sender());
|
this._removeShooterForSender(invocation.get_sender());
|
||||||
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
|
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
|
||||||
@ -232,8 +241,12 @@ var ScreenshotService = class {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let [area] = await screenshot.screenshot(includeCursor, stream);
|
await Promise.all([
|
||||||
this._onScreenshotComplete(area, stream, file, flash, invocation);
|
flash ? this._flashAsync(screenshot) : null,
|
||||||
|
screenshot.screenshot(includeCursor, stream),
|
||||||
|
]);
|
||||||
|
this._onScreenshotComplete(stream, file, invocation);
|
||||||
|
this._removeShooterForSender(invocation.get_sender());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this._removeShooterForSender(invocation.get_sender());
|
this._removeShooterForSender(invocation.get_sender());
|
||||||
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
|
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
|
||||||
|
@ -47,6 +47,7 @@ js/ui/panel.js
|
|||||||
js/ui/popupMenu.js
|
js/ui/popupMenu.js
|
||||||
js/ui/runDialog.js
|
js/ui/runDialog.js
|
||||||
js/ui/screenShield.js
|
js/ui/screenShield.js
|
||||||
|
js/ui/screenshot.js
|
||||||
js/ui/search.js
|
js/ui/search.js
|
||||||
js/ui/shellEntry.js
|
js/ui/shellEntry.js
|
||||||
js/ui/shellMountOperation.js
|
js/ui/shellMountOperation.js
|
||||||
|
@ -25,6 +25,15 @@ typedef enum _ShellScreenshotMode
|
|||||||
SHELL_SCREENSHOT_AREA,
|
SHELL_SCREENSHOT_AREA,
|
||||||
} ShellScreenshotMode;
|
} ShellScreenshotMode;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SCREENSHOT_TAKEN,
|
||||||
|
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
typedef struct _ShellScreenshotPrivate ShellScreenshotPrivate;
|
typedef struct _ShellScreenshotPrivate ShellScreenshotPrivate;
|
||||||
|
|
||||||
struct _ShellScreenshot
|
struct _ShellScreenshot
|
||||||
@ -55,7 +64,15 @@ G_DEFINE_TYPE_WITH_PRIVATE (ShellScreenshot, shell_screenshot, G_TYPE_OBJECT);
|
|||||||
static void
|
static void
|
||||||
shell_screenshot_class_init (ShellScreenshotClass *screenshot_class)
|
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
|
static void
|
||||||
@ -321,6 +338,8 @@ grab_window_screenshot (ShellScreenshot *screenshot,
|
|||||||
draw_cursor_image (priv->image, priv->screenshot_area);
|
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);
|
task = g_task_new (screenshot, NULL, on_screenshot_written, result);
|
||||||
g_task_run_in_thread (task, write_screenshot_thread);
|
g_task_run_in_thread (task, write_screenshot_thread);
|
||||||
g_object_unref (task);
|
g_object_unref (task);
|
||||||
@ -372,6 +391,9 @@ on_after_paint (ClutterStage *stage,
|
|||||||
grab_screenshot (screenshot, priv->flags, result);
|
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);
|
meta_enable_unredirect_for_display (display);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,6 +452,9 @@ shell_screenshot_screenshot (ShellScreenshot *screenshot,
|
|||||||
if (meta_is_wayland_compositor ())
|
if (meta_is_wayland_compositor ())
|
||||||
{
|
{
|
||||||
grab_screenshot (screenshot, flags, result);
|
grab_screenshot (screenshot, flags, result);
|
||||||
|
|
||||||
|
g_signal_emit (screenshot, signals[SCREENSHOT_TAKEN], 0,
|
||||||
|
(cairo_rectangle_int_t *) &priv->screenshot_area);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -540,6 +565,9 @@ shell_screenshot_screenshot_area (ShellScreenshot *screenshot,
|
|||||||
priv->screenshot_area.height,
|
priv->screenshot_area.height,
|
||||||
SHELL_SCREENSHOT_FLAG_NONE);
|
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);
|
task = g_task_new (screenshot, NULL, on_screenshot_written, result);
|
||||||
g_task_run_in_thread (task, write_screenshot_thread);
|
g_task_run_in_thread (task, write_screenshot_thread);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user