screenshot-ui: Add area and screen recording

It works by passing the selected area to org.gnome.Shell.ScreencastArea.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2103>
This commit is contained in:
Ivan Molodetskikh 2021-10-11 08:47:21 +03:00 committed by Marge Bot
parent 6d0c2ae697
commit 003eb4c4e0

View File

@ -27,6 +27,9 @@ const { DBusSenderChecker } = imports.misc.util;
const ScreenshotIface = loadInterfaceXML('org.gnome.Shell.Screenshot'); const ScreenshotIface = loadInterfaceXML('org.gnome.Shell.Screenshot');
const ScreencastIface = loadInterfaceXML('org.gnome.Shell.Screencast');
const ScreencastProxy = Gio.DBusProxy.makeProxyWrapper(ScreencastIface);
var IconLabelButton = GObject.registerClass( var IconLabelButton = GObject.registerClass(
class IconLabelButton extends St.Button { class IconLabelButton extends St.Button {
_init(iconName, label, params) { _init(iconName, label, params) {
@ -1332,6 +1335,9 @@ var ScreenshotUI = GObject.registerClass({
if (this._openingCoroutineInProgress) if (this._openingCoroutineInProgress)
return; return;
if (this._screencastInProgress)
return;
if (!this.visible) { if (!this.visible) {
// Screenshot UI is opening from completely closed state // Screenshot UI is opening from completely closed state
// (rather than opening back from in process of closing). // (rather than opening back from in process of closing).
@ -1601,7 +1607,7 @@ var ScreenshotUI = GObject.registerClass({
} }
} }
_getSelectedGeometry() { _getSelectedGeometry(rescale) {
let x, y, w, h; let x, y, w, h;
if (this._selectionButton.checked) { if (this._selectionButton.checked) {
@ -1617,21 +1623,24 @@ var ScreenshotUI = GObject.registerClass({
h = monitor.height; h = monitor.height;
} }
x *= this._scale; if (rescale) {
y *= this._scale; x *= this._scale;
w *= this._scale; y *= this._scale;
h *= this._scale; w *= this._scale;
h *= this._scale;
}
return [x, y, w, h]; return [x, y, w, h];
} }
_onCaptureButtonClicked() { _onCaptureButtonClicked() {
if (this._shotButton.checked) if (this._shotButton.checked) {
this._saveScreenshot(); this._saveScreenshot();
this.close();
// TODO: screencasting. } else {
// Screencast closes the UI on its own.
this.close(); this._startScreencast();
}
} }
_storeScreenshot(bytes, pixbuf) { _storeScreenshot(bytes, pixbuf) {
@ -1773,7 +1782,7 @@ var ScreenshotUI = GObject.registerClass({
const texture = content.get_texture(); const texture = content.get_texture();
const stream = Gio.MemoryOutputStream.new_resizable(); const stream = Gio.MemoryOutputStream.new_resizable();
const [x, y, w, h] = this._getSelectedGeometry(); const [x, y, w, h] = this._getSelectedGeometry(true);
let cursorTexture = this._cursor.content?.get_texture(); let cursorTexture = this._cursor.content?.get_texture();
if (!this._cursor.visible) if (!this._cursor.visible)
@ -1830,6 +1839,71 @@ var ScreenshotUI = GObject.registerClass({
} }
} }
_startScreencast() {
if (this._windowButton.checked)
return; // TODO
const [x, y, w, h] = this._getSelectedGeometry(false);
const drawCursor = this._cursor.visible;
// Close instantly so the fade-out doesn't get recorded.
this.close(true);
// This is a bit awkward because creating a proxy synchronously hangs Shell.
const doStartScreencast = () => {
let method =
this._screencastProxy.ScreencastRemote.bind(this._screencastProxy);
if (w !== -1) {
method = this._screencastProxy.ScreencastAreaRemote.bind(
this._screencastProxy, x, y, w, h);
}
method(
/* Translators: this is a filename used for screencast
* recording, where "%d" and "%t" date and time, e.g.
* "Screencast from 07-17-2013 10:00:46 PM.webm" */
/* xgettext:no-c-format */
_('Screencast from %d %t.webm'),
{ 'draw-cursor': new GLib.Variant('b', drawCursor) },
([success, _filename], error) => {
if (error !== null) {
this._setScreencastInProgress(false);
log('Error starting screencast: %s'.format(error.message));
return;
}
if (!success) {
this._setScreencastInProgress(false);
log('Error starting screencast');
}
}
);
};
// Set this before calling the method as the screen recording indicator
// will check it before the success callback fires.
this._setScreencastInProgress(true);
if (this._screencastProxy) {
doStartScreencast();
} else {
new ScreencastProxy(
Gio.DBus.session,
'org.gnome.Shell.Screencast',
'/org/gnome/Shell/Screencast',
(object, error) => {
if (error !== null) {
log('Error connecting to the screencast service');
return;
}
this._screencastProxy = object;
doStartScreencast();
}
);
}
}
stopScreencast() { stopScreencast() {
if (!this._screencastInProgress) if (!this._screencastInProgress)
return; return;
@ -1837,6 +1911,16 @@ var ScreenshotUI = GObject.registerClass({
// Set this before calling the method as the screen recording indicator // Set this before calling the method as the screen recording indicator
// will check it before the success callback fires. // will check it before the success callback fires.
this._setScreencastInProgress(false); this._setScreencastInProgress(false);
this._screencastProxy.StopScreencastRemote((success, error) => {
if (error !== null) {
log('Error stopping screencast: %s'.format(error.message));
return;
}
if (!success)
log('Error stopping screencast');
});
} }
get screencast_in_progress() { get screencast_in_progress() {