mirror of
https://github.com/edu4rdshl/gnome-shell.git
synced 2026-07-17 23:24:51 +00:00
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
3 changed files with 60 additions and 18 deletions
|
|
@ -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, '']));
|
||||
|
|
|
|||
|
|
@ -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…
Add table
Add a link
Reference in a new issue