[gnome-shell] screenshot-ui: Add area and screen recording



commit 003eb4c4e014b31bd5d55f7910b2a821a5c4ee38
Author: Ivan Molodetskikh <yalterz gmail com>
Date:   Mon Oct 11 08:47:21 2021 +0300

    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>

 js/ui/screenshot.js | 106 ++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 95 insertions(+), 11 deletions(-)
---
diff --git a/js/ui/screenshot.js b/js/ui/screenshot.js
index 7417376239..54c56f8465 100644
--- a/js/ui/screenshot.js
+++ b/js/ui/screenshot.js
@@ -27,6 +27,9 @@ const { DBusSenderChecker } = imports.misc.util;
 
 const ScreenshotIface = loadInterfaceXML('org.gnome.Shell.Screenshot');
 
+const ScreencastIface = loadInterfaceXML('org.gnome.Shell.Screencast');
+const ScreencastProxy = Gio.DBusProxy.makeProxyWrapper(ScreencastIface);
+
 var IconLabelButton = GObject.registerClass(
 class IconLabelButton extends St.Button {
     _init(iconName, label, params) {
@@ -1332,6 +1335,9 @@ var ScreenshotUI = GObject.registerClass({
         if (this._openingCoroutineInProgress)
             return;
 
+        if (this._screencastInProgress)
+            return;
+
         if (!this.visible) {
             // Screenshot UI is opening from completely closed state
             // (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;
 
         if (this._selectionButton.checked) {
@@ -1617,21 +1623,24 @@ var ScreenshotUI = GObject.registerClass({
             h = monitor.height;
         }
 
-        x *= this._scale;
-        y *= this._scale;
-        w *= this._scale;
-        h *= this._scale;
+        if (rescale) {
+            x *= this._scale;
+            y *= this._scale;
+            w *= this._scale;
+            h *= this._scale;
+        }
 
         return [x, y, w, h];
     }
 
     _onCaptureButtonClicked() {
-        if (this._shotButton.checked)
+        if (this._shotButton.checked) {
             this._saveScreenshot();
-
-        // TODO: screencasting.
-
-        this.close();
+            this.close();
+        } else {
+            // Screencast closes the UI on its own.
+            this._startScreencast();
+        }
     }
 
     _storeScreenshot(bytes, pixbuf) {
@@ -1773,7 +1782,7 @@ var ScreenshotUI = GObject.registerClass({
             const texture = content.get_texture();
             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();
             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() {
         if (!this._screencastInProgress)
             return;
@@ -1837,6 +1911,16 @@ var ScreenshotUI = GObject.registerClass({
         // Set this before calling the method as the screen recording indicator
         // will check it before the success callback fires.
         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() {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]