Blame SOURCES/0011-screenShield-Fix-pointer-motion-signal-handler-leak.patch

efe155
From dc441b5d71f80e2b6dcdccbb4d6562c5b799294f Mon Sep 17 00:00:00 2001
efe155
From: Ray Strode <rstrode@redhat.com>
efe155
Date: Mon, 28 Sep 2020 22:28:08 -0400
efe155
Subject: [PATCH 11/13] screenShield: Fix pointer motion signal handler leak
efe155
efe155
The screen shield code listens for motion events on the stage
efe155
so that it can hide the pointer until the user moves the mouse.
efe155
efe155
Unfortunately, if the user never moves the mouse, the signal
efe155
handler connection gets leaked.
efe155
efe155
This commit makes sure the connection gets disconnected when the
efe155
shield goes away.
efe155
---
efe155
 js/ui/screenShield.js | 31 +++++++++++++++++++++----------
efe155
 1 file changed, 21 insertions(+), 10 deletions(-)
efe155
efe155
diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js
efe155
index ebba6c82a..bbfceba57 100644
efe155
--- a/js/ui/screenShield.js
efe155
+++ b/js/ui/screenShield.js
efe155
@@ -905,91 +905,110 @@ var ScreenShield = new Lang.Class({
efe155
         this._completeLockScreenShown();
efe155
     },
efe155
 
efe155
     showDialog() {
efe155
         if (!this._becomeModal()) {
efe155
             // In the login screen, this is a hard error. Fail-whale
efe155
             log('Could not acquire modal grab for the login screen. Aborting login process.');
efe155
             Meta.quit(Meta.ExitCode.ERROR);
efe155
         }
efe155
 
efe155
         this.actor.show();
efe155
         this._isGreeter = Main.sessionMode.isGreeter;
efe155
         this._isLocked = true;
efe155
         if (this._ensureUnlockDialog(true, true))
efe155
             this._hideLockScreen(false, 0);
efe155
     },
efe155
 
efe155
     _hideLockScreenComplete() {
efe155
         if (Main.sessionMode.currentMode == 'lock-screen')
efe155
             Main.sessionMode.popMode('lock-screen');
efe155
 
efe155
         this._lockScreenState = MessageTray.State.HIDDEN;
efe155
         this._lockScreenGroup.hide();
efe155
 
efe155
         if (this._dialog) {
efe155
             this._dialog.actor.grab_key_focus();
efe155
             this._dialog.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
efe155
         }
efe155
     },
efe155
 
efe155
+    _showPointer() {
efe155
+        this._cursorTracker.set_pointer_visible(true);
efe155
+
efe155
+        if (this._motionId) {
efe155
+            global.stage.disconnect(this._motionId);
efe155
+            this._motionId = 0;
efe155
+        }
efe155
+    },
efe155
+
efe155
+    _hidePointerUntilMotion() {
efe155
+        this._motionId = global.stage.connect('captured-event', (stage, event) => {
efe155
+            if (event.type() == Clutter.EventType.MOTION)
efe155
+                this._showPointer();
efe155
+
efe155
+            return Clutter.EVENT_PROPAGATE;
efe155
+        });
efe155
+        this._cursorTracker.set_pointer_visible(false);
efe155
+    },
efe155
+
efe155
     _hideLockScreen(animate, velocity) {
efe155
         if (this._lockScreenState == MessageTray.State.HIDDEN)
efe155
             return;
efe155
 
efe155
         this._lockScreenState = MessageTray.State.HIDING;
efe155
 
efe155
         Tweener.removeTweens(this._lockScreenGroup);
efe155
 
efe155
         if (animate) {
efe155
             // Tween the lock screen out of screen
efe155
             // if velocity is not specified (i.e. we come here from pressing ESC),
efe155
             // use the same speed regardless of original position
efe155
             // if velocity is specified, it's in pixels per milliseconds
efe155
             let h = global.stage.height;
efe155
             let delta = (h + this._lockScreenGroup.y);
efe155
             let min_velocity = global.stage.height / (CURTAIN_SLIDE_TIME * 1000);
efe155
 
efe155
             velocity = Math.max(min_velocity, velocity);
efe155
             let time = (delta / velocity) / 1000;
efe155
 
efe155
             Tweener.addTween(this._lockScreenGroup,
efe155
                              { y: -h,
efe155
                                time: time,
efe155
                                transition: 'easeInQuad',
efe155
                                onComplete: this._hideLockScreenComplete.bind(this),
efe155
                              });
efe155
         } else {
efe155
             this._hideLockScreenComplete();
efe155
         }
efe155
 
efe155
-        this._cursorTracker.set_pointer_visible(true);
efe155
+        this._showPointer();
efe155
     },
efe155
 
efe155
     _ensureUnlockDialog(onPrimary, allowCancel) {
efe155
         if (!this._dialog) {
efe155
             let constructor = Main.sessionMode.unlockDialog;
efe155
             if (!constructor) {
efe155
                 // This session mode has no locking capabilities
efe155
                 this.deactivate(true);
efe155
                 return false;
efe155
             }
efe155
 
efe155
             this._dialog = new constructor(this._lockDialogGroup);
efe155
 
efe155
 
efe155
             let time = global.get_current_time();
efe155
             if (!this._dialog.open(time, onPrimary)) {
efe155
                 // This is kind of an impossible error: we're already modal
efe155
                 // by the time we reach this...
efe155
                 log('Could not open login dialog: failed to acquire grab');
efe155
                 this.deactivate(true);
efe155
                 return false;
efe155
             }
efe155
 
efe155
             this._dialog.connect('failed', this._onUnlockFailed.bind(this));
efe155
         }
efe155
 
efe155
         this._dialog.allowCancel = allowCancel;
efe155
         return true;
efe155
     },
efe155
 
efe155
@@ -1069,69 +1088,61 @@ var ScreenShield = new Lang.Class({
efe155
             Mainloop.source_remove(this._arrowAnimationId);
efe155
             this._arrowAnimationId = 0;
efe155
         }
efe155
         if (this._arrowActiveWatchId) {
efe155
             this.idleMonitor.remove_watch(this._arrowActiveWatchId);
efe155
             this._arrowActiveWatchId = 0;
efe155
         }
efe155
         if (this._arrowWatchId) {
efe155
             this.idleMonitor.remove_watch(this._arrowWatchId);
efe155
             this._arrowWatchId = 0;
efe155
         }
efe155
     },
efe155
 
efe155
     _checkArrowAnimation() {
efe155
         let idleTime = this.idleMonitor.get_idletime();
efe155
 
efe155
         if (idleTime < ARROW_IDLE_TIME)
efe155
             this._startArrowAnimation();
efe155
         else
efe155
             this._pauseArrowAnimation();
efe155
     },
efe155
 
efe155
     _lockScreenShown(params) {
efe155
         if (this._dialog && !this._isGreeter) {
efe155
             this._dialog.destroy();
efe155
             this._dialog = null;
efe155
         }
efe155
 
efe155
         this._checkArrowAnimation();
efe155
 
efe155
-        let motionId = global.stage.connect('captured-event', (stage, event) => {
efe155
-            if (event.type() == Clutter.EventType.MOTION) {
efe155
-                this._cursorTracker.set_pointer_visible(true);
efe155
-                global.stage.disconnect(motionId);
efe155
-            }
efe155
-
efe155
-            return Clutter.EVENT_PROPAGATE;
efe155
-        });
efe155
-        this._cursorTracker.set_pointer_visible(false);
efe155
+        this._hidePointerUntilMotion();
efe155
 
efe155
         this._lockScreenState = MessageTray.State.SHOWN;
efe155
         this._lockScreenGroup.fixed_position_set = false;
efe155
         this._lockScreenScrollCounter = 0;
efe155
 
efe155
         if (params.fadeToBlack && params.animateFade) {
efe155
             // Take a beat
efe155
 
efe155
             let id = Mainloop.timeout_add(1000 * MANUAL_FADE_TIME, () => {
efe155
                 this._activateFade(this._shortLightbox, MANUAL_FADE_TIME);
efe155
                 return GLib.SOURCE_REMOVE;
efe155
             });
efe155
             GLib.Source.set_name_by_id(id, '[gnome-shell] this._activateFade');
efe155
         } else {
efe155
             if (params.fadeToBlack)
efe155
                 this._activateFade(this._shortLightbox, 0);
efe155
 
efe155
             this._completeLockScreenShown();
efe155
         }
efe155
     },
efe155
 
efe155
     _completeLockScreenShown() {
efe155
         this._setActive(true);
efe155
         this.emit('lock-screen-shown');
efe155
     },
efe155
 
efe155
     // Some of the actors in the lock screen are heavy in
efe155
     // resources, so we only create them when needed
efe155
     _ensureLockScreen() {
efe155
         if (this._hasLockScreen)
efe155
-- 
efe155
2.25.1
efe155