Compare commits
No commits in common. 'c9' and 'i8' have entirely different histories.
@ -1 +1 @@
|
|||||||
SOURCES/gnome-shell-40.10.tar.xz
|
SOURCES/gnome-shell-3.32.2.tar.xz
|
||||||
|
@ -1 +1 @@
|
|||||||
c955a004fb650a83863d1151e3adbbd6758b1c2e SOURCES/gnome-shell-40.10.tar.xz
|
331e9cf71cd1d2a4e9238d87d216da4c6f3a400e SOURCES/gnome-shell-3.32.2.tar.xz
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
From f5ddd0fc02e99597e4b8506ac35523a6fa8ac22f Mon Sep 17 00:00:00 2001
|
||||||
|
From: rpm-build <rpm-build>
|
||||||
|
Date: Wed, 4 Mar 2020 16:08:31 +0100
|
||||||
|
Subject: [PATCH] Do not change Wacom LEDs through g-s-d
|
||||||
|
|
||||||
|
Let the wacom kernel driver sort it out by itself.
|
||||||
|
---
|
||||||
|
js/ui/windowManager.js | 1 -
|
||||||
|
1 file changed, 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
|
||||||
|
index dfe1b44..b2e938c 100644
|
||||||
|
--- a/js/ui/windowManager.js
|
||||||
|
+++ b/js/ui/windowManager.js
|
||||||
|
@@ -1037,7 +1037,6 @@ var WindowManager = class {
|
||||||
|
|
||||||
|
if (this._gsdWacomProxy) {
|
||||||
|
this._gsdWacomProxy.SetOLEDLabelsRemote(pad.get_device_node(), labels);
|
||||||
|
- this._gsdWacomProxy.SetGroupModeLEDRemote(pad.get_device_node(), group, mode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
--
|
||||||
|
2.24.1
|
||||||
|
|
@ -0,0 +1,25 @@
|
|||||||
|
From faa174e867ad3af89d7858fa3af5170cdd8a6aa5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alexey Lyubimov <a.lyubimov@softline.com>
|
||||||
|
Date: Fri, 22 Mar 2024 12:27:22 +0300
|
||||||
|
Subject: [PATCH] Fix Russian translation
|
||||||
|
|
||||||
|
---
|
||||||
|
po/ru.po | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/po/ru.po b/po/ru.po
|
||||||
|
index 1464558..881450d 100644
|
||||||
|
--- a/po/ru.po
|
||||||
|
+++ b/po/ru.po
|
||||||
|
@@ -2261,7 +2261,7 @@ msgstr "Всегда на видимом рабочем месте"
|
||||||
|
|
||||||
|
#: js/ui/windowMenu.js:95
|
||||||
|
msgid "Move to Workspace Left"
|
||||||
|
-msgstr "Переместить на рабочее влево"
|
||||||
|
+msgstr "Переместить на рабочее место влево"
|
||||||
|
|
||||||
|
#: js/ui/windowMenu.js:101
|
||||||
|
msgid "Move to Workspace Right"
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
@ -1,25 +0,0 @@
|
|||||||
From a8c8b7ef31f7219157b94148b771f6f663928dea Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
||||||
Date: Tue, 19 Apr 2022 19:17:48 +0200
|
|
||||||
Subject: [PATCH] Revert "dash: Subtract vertical margins from availHeight"
|
|
||||||
|
|
||||||
This reverts commit 0de0a1f5940784eb4a7ca9ecf5e92f5277ceb0d8.
|
|
||||||
---
|
|
||||||
js/ui/dash.js | 1 -
|
|
||||||
1 file changed, 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/js/ui/dash.js b/js/ui/dash.js
|
|
||||||
index f35cc2e25..0f1ca2c4c 100644
|
|
||||||
--- a/js/ui/dash.js
|
|
||||||
+++ b/js/ui/dash.js
|
|
||||||
@@ -610,7 +610,6 @@ var Dash = GObject.registerClass({
|
|
||||||
(iconChildren.length - 1) * spacing;
|
|
||||||
|
|
||||||
let availHeight = this._maxHeight;
|
|
||||||
- availHeight -= this.margin_top + this.margin_bottom;
|
|
||||||
availHeight -= this._background.get_theme_node().get_vertical_padding();
|
|
||||||
availHeight -= themeNode.get_vertical_padding();
|
|
||||||
availHeight -= buttonHeight - iconHeight;
|
|
||||||
--
|
|
||||||
2.35.1
|
|
||||||
|
|
@ -1,364 +0,0 @@
|
|||||||
From 678cdd9e0da851da78527fa827d71a80273510b0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@redhat.com>
|
|
||||||
Date: Tue, 8 Feb 2022 14:18:04 -0500
|
|
||||||
|
|
||||||
---
|
|
||||||
data/theme/gnome-shell-high-contrast.css | 36 ++++++++++++++++++++++++
|
|
||||||
data/theme/gnome-shell.css | 36 ++++++++++++++++++++++++
|
|
||||||
2 files changed, 72 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/data/theme/gnome-shell-high-contrast.css b/data/theme/gnome-shell-high-contrast.css
|
|
||||||
index b73f407..90f363c 100644
|
|
||||||
--- a/data/theme/gnome-shell-high-contrast.css
|
|
||||||
+++ b/data/theme/gnome-shell-high-contrast.css
|
|
||||||
@@ -1223,60 +1223,63 @@ StScrollBar {
|
|
||||||
-panel-corner-border-color: transparent;
|
|
||||||
-panel-corner-opacity: 1;
|
|
||||||
transition-duration: 250ms; }
|
|
||||||
#panel .panel-button {
|
|
||||||
font-weight: bold;
|
|
||||||
color: #ddd;
|
|
||||||
-natural-hpadding: 12px;
|
|
||||||
-minimum-hpadding: 6px;
|
|
||||||
transition-duration: 150ms;
|
|
||||||
border: 3px solid transparent;
|
|
||||||
border-radius: 99px; }
|
|
||||||
#panel .panel-button.clock-display .clock {
|
|
||||||
transition-duration: 150ms;
|
|
||||||
border: 3px solid transparent;
|
|
||||||
border-radius: 99px; }
|
|
||||||
#panel .panel-button:hover, #panel .panel-button:active, #panel .panel-button:overview, #panel .panel-button:focus, #panel .panel-button:checked {
|
|
||||||
box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.2); }
|
|
||||||
#panel .panel-button.clock-display:hover, #panel .panel-button.clock-display:active, #panel .panel-button.clock-display:overview, #panel .panel-button.clock-display:focus, #panel .panel-button.clock-display:checked {
|
|
||||||
box-shadow: none; }
|
|
||||||
#panel .panel-button.clock-display:hover .clock, #panel .panel-button.clock-display:active .clock, #panel .panel-button.clock-display:overview .clock, #panel .panel-button.clock-display:focus .clock, #panel .panel-button.clock-display:checked .clock {
|
|
||||||
box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.2); }
|
|
||||||
#panel .panel-button .system-status-icon {
|
|
||||||
icon-size: 1.09em;
|
|
||||||
padding: 5px;
|
|
||||||
margin: 0 4px; }
|
|
||||||
#panel .panel-button .panel-status-indicators-box .system-status-icon,
|
|
||||||
#panel .panel-button .panel-status-menu-box .system-status-icon {
|
|
||||||
margin: 0; }
|
|
||||||
#panel .panel-button .app-menu-icon {
|
|
||||||
-st-icon-style: symbolic; }
|
|
||||||
+ #panel .panel-button .panel-logo-icon {
|
|
||||||
+ padding-right: .4em;
|
|
||||||
+ icon-size: 1em; }
|
|
||||||
#panel #panelActivities.panel-button {
|
|
||||||
-natural-hpadding: 18px; }
|
|
||||||
#panel.unlock-screen .panel-button:hover, #panel.unlock-screen .panel-button:active, #panel.unlock-screen .panel-button:overview, #panel.unlock-screen .panel-button:focus, #panel.unlock-screen .panel-button:checked, #panel.login-screen .panel-button:hover, #panel.login-screen .panel-button:active, #panel.login-screen .panel-button:overview, #panel.login-screen .panel-button:focus, #panel.login-screen .panel-button:checked, #panel:overview .panel-button:hover, #panel:overview .panel-button:active, #panel:overview .panel-button:overview, #panel:overview .panel-button:focus, #panel:overview .panel-button:checked {
|
|
||||||
box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.15); }
|
|
||||||
#panel.unlock-screen .panel-button.clock-display:hover, #panel.unlock-screen .panel-button.clock-display:active, #panel.unlock-screen .panel-button.clock-display:overview, #panel.unlock-screen .panel-button.clock-display:focus, #panel.unlock-screen .panel-button.clock-display:checked, #panel.login-screen .panel-button.clock-display:hover, #panel.login-screen .panel-button.clock-display:active, #panel.login-screen .panel-button.clock-display:overview, #panel.login-screen .panel-button.clock-display:focus, #panel.login-screen .panel-button.clock-display:checked, #panel:overview .panel-button.clock-display:hover, #panel:overview .panel-button.clock-display:active, #panel:overview .panel-button.clock-display:overview, #panel:overview .panel-button.clock-display:focus, #panel:overview .panel-button.clock-display:checked {
|
|
||||||
box-shadow: none; }
|
|
||||||
#panel.unlock-screen .panel-button.clock-display:hover .clock, #panel.unlock-screen .panel-button.clock-display:active .clock, #panel.unlock-screen .panel-button.clock-display:overview .clock, #panel.unlock-screen .panel-button.clock-display:focus .clock, #panel.unlock-screen .panel-button.clock-display:checked .clock, #panel.login-screen .panel-button.clock-display:hover .clock, #panel.login-screen .panel-button.clock-display:active .clock, #panel.login-screen .panel-button.clock-display:overview .clock, #panel.login-screen .panel-button.clock-display:focus .clock, #panel.login-screen .panel-button.clock-display:checked .clock, #panel:overview .panel-button.clock-display:hover .clock, #panel:overview .panel-button.clock-display:active .clock, #panel:overview .panel-button.clock-display:overview .clock, #panel:overview .panel-button.clock-display:focus .clock, #panel:overview .panel-button.clock-display:checked .clock {
|
|
||||||
box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.15); }
|
|
||||||
#panel .panel-status-indicators-box,
|
|
||||||
#panel .panel-status-menu-box {
|
|
||||||
spacing: 2px; }
|
|
||||||
#panel .power-status.panel-status-indicators-box {
|
|
||||||
spacing: 0; }
|
|
||||||
#panel .screencast-indicator,
|
|
||||||
#panel .remote-access-indicator {
|
|
||||||
color: #f57900; }
|
|
||||||
|
|
||||||
#appMenu {
|
|
||||||
spacing: 6px; }
|
|
||||||
#appMenu .label-shadow {
|
|
||||||
color: transparent; }
|
|
||||||
|
|
||||||
#appMenu .panel-status-menu-box {
|
|
||||||
padding: 0 6px;
|
|
||||||
spacing: 6px; }
|
|
||||||
|
|
||||||
/* Activities Ripple */
|
|
||||||
.ripple-box {
|
|
||||||
background-color: rgba(158, 196, 235, 0.3);
|
|
||||||
box-shadow: 0 0 2px 2px #4a90d9;
|
|
||||||
@@ -2039,74 +2042,107 @@ StScrollBar {
|
|
||||||
width: 2.18em;
|
|
||||||
height: 2.18em;
|
|
||||||
border-color: #202020;
|
|
||||||
background-color: #202020; }
|
|
||||||
.login-dialog .cancel-button StIcon,
|
|
||||||
.login-dialog .switch-user-button StIcon,
|
|
||||||
.login-dialog .login-dialog-session-list-button StIcon,
|
|
||||||
.unlock-dialog .cancel-button StIcon,
|
|
||||||
.unlock-dialog .switch-user-button StIcon,
|
|
||||||
.unlock-dialog .login-dialog-session-list-button StIcon {
|
|
||||||
icon-size: 1.09em; }
|
|
||||||
.login-dialog .caps-lock-warning-label,
|
|
||||||
.login-dialog .login-dialog-message-warning,
|
|
||||||
.unlock-dialog .caps-lock-warning-label,
|
|
||||||
.unlock-dialog .login-dialog-message-warning {
|
|
||||||
color: #eeeeec; }
|
|
||||||
|
|
||||||
.login-dialog-logo-bin {
|
|
||||||
padding: 24px 0px; }
|
|
||||||
|
|
||||||
.login-dialog-banner {
|
|
||||||
color: #d6d6d1; }
|
|
||||||
|
|
||||||
.login-dialog-button-box {
|
|
||||||
width: 23em;
|
|
||||||
spacing: 5px; }
|
|
||||||
|
|
||||||
.login-dialog-message {
|
|
||||||
text-align: center; }
|
|
||||||
|
|
||||||
+.login-dialog-message-hint, .login-dialog-message {
|
|
||||||
+ color: #bebeb6;
|
|
||||||
+ min-height: 2.75em; }
|
|
||||||
+
|
|
||||||
.login-dialog-user-selection-box {
|
|
||||||
padding: 100px 0px; }
|
|
||||||
|
|
||||||
.login-dialog-not-listed-label {
|
|
||||||
padding-left: 2px; }
|
|
||||||
.login-dialog-not-listed-button:focus .login-dialog-not-listed-label, .login-dialog-not-listed-button:hover .login-dialog-not-listed-label {
|
|
||||||
color: #eeeeec; }
|
|
||||||
|
|
||||||
.login-dialog-not-listed-label {
|
|
||||||
font-size: 10pt;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #a6a69b;
|
|
||||||
padding-top: 1em; }
|
|
||||||
|
|
||||||
+.login-dialog-auth-list-view {
|
|
||||||
+ -st-vfade-offset: 1em; }
|
|
||||||
+
|
|
||||||
+.login-dialog-auth-list {
|
|
||||||
+ spacing: 6px;
|
|
||||||
+ margin-left: 2em; }
|
|
||||||
+
|
|
||||||
+.login-dialog-auth-list-title {
|
|
||||||
+ margin-left: 2em; }
|
|
||||||
+
|
|
||||||
+.login-dialog-auth-list-item {
|
|
||||||
+ border-radius: 12px;
|
|
||||||
+ padding: 6px;
|
|
||||||
+ color: #a6a69b; }
|
|
||||||
+ .login-dialog-auth-list-item:focus, .login-dialog-auth-list-item:selected {
|
|
||||||
+ background-color: #215d9c;
|
|
||||||
+ color: #ffffff; }
|
|
||||||
+
|
|
||||||
+.login-dialog-auth-list-label {
|
|
||||||
+ font-size: 13pt;
|
|
||||||
+ font-weight: bold;
|
|
||||||
+ padding-left: 15px; }
|
|
||||||
+ .login-dialog-auth-list-label:ltr {
|
|
||||||
+ padding-left: 14px;
|
|
||||||
+ text-align: left; }
|
|
||||||
+ .login-dialog-auth-list-label:rtl {
|
|
||||||
+ padding-right: 14px;
|
|
||||||
+ text-align: right; }
|
|
||||||
+
|
|
||||||
.login-dialog-user-list-view {
|
|
||||||
-st-vfade-offset: 1em; }
|
|
||||||
|
|
||||||
.login-dialog-user-list {
|
|
||||||
spacing: 12px;
|
|
||||||
width: 23em; }
|
|
||||||
.login-dialog-user-list:expanded .login-dialog-user-list-item:selected {
|
|
||||||
background-color: #215d9c;
|
|
||||||
color: #ffffff; }
|
|
||||||
.login-dialog-user-list:expanded .login-dialog-user-list-item:logged-in {
|
|
||||||
border-right: 2px solid #215d9c; }
|
|
||||||
|
|
||||||
.login-dialog-user-list-item {
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 6px;
|
|
||||||
color: #a6a69b; }
|
|
||||||
.login-dialog-user-list-item:ltr .user-widget {
|
|
||||||
padding-right: 1em; }
|
|
||||||
.login-dialog-user-list-item:rtl .user-widget {
|
|
||||||
padding-left: 1em; }
|
|
||||||
.login-dialog-user-list-item .login-dialog-timed-login-indicator {
|
|
||||||
height: 2px;
|
|
||||||
margin-top: 6px;
|
|
||||||
background-color: #eeeeec; }
|
|
||||||
.login-dialog-user-list-item:focus .login-dialog-timed-login-indicator {
|
|
||||||
background-color: #ffffff; }
|
|
||||||
|
|
||||||
.user-widget-label {
|
|
||||||
color: #eeeeec; }
|
|
||||||
|
|
||||||
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
|
|
||||||
index f93819b..d3d7fc8 100644
|
|
||||||
--- a/data/theme/gnome-shell.css
|
|
||||||
+++ b/data/theme/gnome-shell.css
|
|
||||||
@@ -1223,60 +1223,63 @@ StScrollBar {
|
|
||||||
-panel-corner-border-color: transparent;
|
|
||||||
-panel-corner-opacity: 1;
|
|
||||||
transition-duration: 250ms; }
|
|
||||||
#panel .panel-button {
|
|
||||||
font-weight: bold;
|
|
||||||
color: #ddd;
|
|
||||||
-natural-hpadding: 12px;
|
|
||||||
-minimum-hpadding: 6px;
|
|
||||||
transition-duration: 150ms;
|
|
||||||
border: 3px solid transparent;
|
|
||||||
border-radius: 99px; }
|
|
||||||
#panel .panel-button.clock-display .clock {
|
|
||||||
transition-duration: 150ms;
|
|
||||||
border: 3px solid transparent;
|
|
||||||
border-radius: 99px; }
|
|
||||||
#panel .panel-button:hover, #panel .panel-button:active, #panel .panel-button:overview, #panel .panel-button:focus, #panel .panel-button:checked {
|
|
||||||
box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.2); }
|
|
||||||
#panel .panel-button.clock-display:hover, #panel .panel-button.clock-display:active, #panel .panel-button.clock-display:overview, #panel .panel-button.clock-display:focus, #panel .panel-button.clock-display:checked {
|
|
||||||
box-shadow: none; }
|
|
||||||
#panel .panel-button.clock-display:hover .clock, #panel .panel-button.clock-display:active .clock, #panel .panel-button.clock-display:overview .clock, #panel .panel-button.clock-display:focus .clock, #panel .panel-button.clock-display:checked .clock {
|
|
||||||
box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.2); }
|
|
||||||
#panel .panel-button .system-status-icon {
|
|
||||||
icon-size: 1.09em;
|
|
||||||
padding: 5px;
|
|
||||||
margin: 0 4px; }
|
|
||||||
#panel .panel-button .panel-status-indicators-box .system-status-icon,
|
|
||||||
#panel .panel-button .panel-status-menu-box .system-status-icon {
|
|
||||||
margin: 0; }
|
|
||||||
#panel .panel-button .app-menu-icon {
|
|
||||||
-st-icon-style: symbolic; }
|
|
||||||
+ #panel .panel-button .panel-logo-icon {
|
|
||||||
+ padding-right: .4em;
|
|
||||||
+ icon-size: 1em; }
|
|
||||||
#panel #panelActivities.panel-button {
|
|
||||||
-natural-hpadding: 18px; }
|
|
||||||
#panel.unlock-screen .panel-button:hover, #panel.unlock-screen .panel-button:active, #panel.unlock-screen .panel-button:overview, #panel.unlock-screen .panel-button:focus, #panel.unlock-screen .panel-button:checked, #panel.login-screen .panel-button:hover, #panel.login-screen .panel-button:active, #panel.login-screen .panel-button:overview, #panel.login-screen .panel-button:focus, #panel.login-screen .panel-button:checked, #panel:overview .panel-button:hover, #panel:overview .panel-button:active, #panel:overview .panel-button:overview, #panel:overview .panel-button:focus, #panel:overview .panel-button:checked {
|
|
||||||
box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.15); }
|
|
||||||
#panel.unlock-screen .panel-button.clock-display:hover, #panel.unlock-screen .panel-button.clock-display:active, #panel.unlock-screen .panel-button.clock-display:overview, #panel.unlock-screen .panel-button.clock-display:focus, #panel.unlock-screen .panel-button.clock-display:checked, #panel.login-screen .panel-button.clock-display:hover, #panel.login-screen .panel-button.clock-display:active, #panel.login-screen .panel-button.clock-display:overview, #panel.login-screen .panel-button.clock-display:focus, #panel.login-screen .panel-button.clock-display:checked, #panel:overview .panel-button.clock-display:hover, #panel:overview .panel-button.clock-display:active, #panel:overview .panel-button.clock-display:overview, #panel:overview .panel-button.clock-display:focus, #panel:overview .panel-button.clock-display:checked {
|
|
||||||
box-shadow: none; }
|
|
||||||
#panel.unlock-screen .panel-button.clock-display:hover .clock, #panel.unlock-screen .panel-button.clock-display:active .clock, #panel.unlock-screen .panel-button.clock-display:overview .clock, #panel.unlock-screen .panel-button.clock-display:focus .clock, #panel.unlock-screen .panel-button.clock-display:checked .clock, #panel.login-screen .panel-button.clock-display:hover .clock, #panel.login-screen .panel-button.clock-display:active .clock, #panel.login-screen .panel-button.clock-display:overview .clock, #panel.login-screen .panel-button.clock-display:focus .clock, #panel.login-screen .panel-button.clock-display:checked .clock, #panel:overview .panel-button.clock-display:hover .clock, #panel:overview .panel-button.clock-display:active .clock, #panel:overview .panel-button.clock-display:overview .clock, #panel:overview .panel-button.clock-display:focus .clock, #panel:overview .panel-button.clock-display:checked .clock {
|
|
||||||
box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.15); }
|
|
||||||
#panel .panel-status-indicators-box,
|
|
||||||
#panel .panel-status-menu-box {
|
|
||||||
spacing: 2px; }
|
|
||||||
#panel .power-status.panel-status-indicators-box {
|
|
||||||
spacing: 0; }
|
|
||||||
#panel .screencast-indicator,
|
|
||||||
#panel .remote-access-indicator {
|
|
||||||
color: #f57900; }
|
|
||||||
|
|
||||||
#appMenu {
|
|
||||||
spacing: 6px; }
|
|
||||||
#appMenu .label-shadow {
|
|
||||||
color: transparent; }
|
|
||||||
|
|
||||||
#appMenu .panel-status-menu-box {
|
|
||||||
padding: 0 6px;
|
|
||||||
spacing: 6px; }
|
|
||||||
|
|
||||||
/* Activities Ripple */
|
|
||||||
.ripple-box {
|
|
||||||
background-color: rgba(188, 214, 246, 0.3);
|
|
||||||
box-shadow: 0 0 2px 2px #629fea;
|
|
||||||
@@ -2039,74 +2042,107 @@ StScrollBar {
|
|
||||||
width: 2.18em;
|
|
||||||
height: 2.18em;
|
|
||||||
border-color: #202020;
|
|
||||||
background-color: #202020; }
|
|
||||||
.login-dialog .cancel-button StIcon,
|
|
||||||
.login-dialog .switch-user-button StIcon,
|
|
||||||
.login-dialog .login-dialog-session-list-button StIcon,
|
|
||||||
.unlock-dialog .cancel-button StIcon,
|
|
||||||
.unlock-dialog .switch-user-button StIcon,
|
|
||||||
.unlock-dialog .login-dialog-session-list-button StIcon {
|
|
||||||
icon-size: 1.09em; }
|
|
||||||
.login-dialog .caps-lock-warning-label,
|
|
||||||
.login-dialog .login-dialog-message-warning,
|
|
||||||
.unlock-dialog .caps-lock-warning-label,
|
|
||||||
.unlock-dialog .login-dialog-message-warning {
|
|
||||||
color: #eeeeec; }
|
|
||||||
|
|
||||||
.login-dialog-logo-bin {
|
|
||||||
padding: 24px 0px; }
|
|
||||||
|
|
||||||
.login-dialog-banner {
|
|
||||||
color: #d6d6d1; }
|
|
||||||
|
|
||||||
.login-dialog-button-box {
|
|
||||||
width: 23em;
|
|
||||||
spacing: 5px; }
|
|
||||||
|
|
||||||
.login-dialog-message {
|
|
||||||
text-align: center; }
|
|
||||||
|
|
||||||
+.login-dialog-message-hint, .login-dialog-message {
|
|
||||||
+ color: #bebeb6;
|
|
||||||
+ min-height: 2.75em; }
|
|
||||||
+
|
|
||||||
.login-dialog-user-selection-box {
|
|
||||||
padding: 100px 0px; }
|
|
||||||
|
|
||||||
.login-dialog-not-listed-label {
|
|
||||||
padding-left: 2px; }
|
|
||||||
.login-dialog-not-listed-button:focus .login-dialog-not-listed-label, .login-dialog-not-listed-button:hover .login-dialog-not-listed-label {
|
|
||||||
color: #eeeeec; }
|
|
||||||
|
|
||||||
.login-dialog-not-listed-label {
|
|
||||||
font-size: 10pt;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #a6a69b;
|
|
||||||
padding-top: 1em; }
|
|
||||||
|
|
||||||
+.login-dialog-auth-list-view {
|
|
||||||
+ -st-vfade-offset: 1em; }
|
|
||||||
+
|
|
||||||
+.login-dialog-auth-list {
|
|
||||||
+ spacing: 6px;
|
|
||||||
+ margin-left: 2em; }
|
|
||||||
+
|
|
||||||
+.login-dialog-auth-list-title {
|
|
||||||
+ margin-left: 2em; }
|
|
||||||
+
|
|
||||||
+.login-dialog-auth-list-item {
|
|
||||||
+ border-radius: 12px;
|
|
||||||
+ padding: 6px;
|
|
||||||
+ color: #a6a69b; }
|
|
||||||
+ .login-dialog-auth-list-item:focus, .login-dialog-auth-list-item:selected {
|
|
||||||
+ background-color: #1b6acb;
|
|
||||||
+ color: #fff; }
|
|
||||||
+
|
|
||||||
+.login-dialog-auth-list-label {
|
|
||||||
+ font-size: 13pt;
|
|
||||||
+ font-weight: bold;
|
|
||||||
+ padding-left: 15px; }
|
|
||||||
+ .login-dialog-auth-list-label:ltr {
|
|
||||||
+ padding-left: 14px;
|
|
||||||
+ text-align: left; }
|
|
||||||
+ .login-dialog-auth-list-label:rtl {
|
|
||||||
+ padding-right: 14px;
|
|
||||||
+ text-align: right; }
|
|
||||||
+
|
|
||||||
.login-dialog-user-list-view {
|
|
||||||
-st-vfade-offset: 1em; }
|
|
||||||
|
|
||||||
.login-dialog-user-list {
|
|
||||||
spacing: 12px;
|
|
||||||
width: 23em; }
|
|
||||||
.login-dialog-user-list:expanded .login-dialog-user-list-item:selected {
|
|
||||||
background-color: #1b6acb;
|
|
||||||
color: #fff; }
|
|
||||||
.login-dialog-user-list:expanded .login-dialog-user-list-item:logged-in {
|
|
||||||
border-right: 2px solid #1b6acb; }
|
|
||||||
|
|
||||||
.login-dialog-user-list-item {
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 6px;
|
|
||||||
color: #a6a69b; }
|
|
||||||
.login-dialog-user-list-item:ltr .user-widget {
|
|
||||||
padding-right: 1em; }
|
|
||||||
.login-dialog-user-list-item:rtl .user-widget {
|
|
||||||
padding-left: 1em; }
|
|
||||||
.login-dialog-user-list-item .login-dialog-timed-login-indicator {
|
|
||||||
height: 2px;
|
|
||||||
margin-top: 6px;
|
|
||||||
background-color: #eeeeec; }
|
|
||||||
.login-dialog-user-list-item:focus .login-dialog-timed-login-indicator {
|
|
||||||
background-color: #fff; }
|
|
||||||
|
|
||||||
.user-widget-label {
|
|
||||||
color: #eeeeec; }
|
|
||||||
|
|
||||||
--
|
|
||||||
2.34.1
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
|||||||
|
From a94260b4f2f72ea9328a0194b8656f1fb3e98675 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Sat, 14 Dec 2019 19:15:53 +0100
|
||||||
|
Subject: [PATCH] a11y: Change HC icon theme first
|
||||||
|
|
||||||
|
There are two ways for applications to provide a high contrast icon:
|
||||||
|
|
||||||
|
1. install an icon into the HighContrast theme
|
||||||
|
2. install a symbolic icon into the default hicolor theme
|
||||||
|
|
||||||
|
The latter is preferred nowadays, and implemented in the high-contrast
|
||||||
|
CSS variant by enforcing the symbolic icon style.
|
||||||
|
|
||||||
|
However together with the way we currently enable/disable high-contrast,
|
||||||
|
this can lead to the following race:
|
||||||
|
1. the GTK theme is changed from HighContrast
|
||||||
|
2. we reload the default stylesheet
|
||||||
|
3. the icon style changes to "regular", so we request a
|
||||||
|
new icon from the HighContrast icon theme
|
||||||
|
4. the icon theme is changed from HighContrast
|
||||||
|
5. we evict existing icons from the cache
|
||||||
|
6. we reload icons for the new icon theme; however as we
|
||||||
|
find a pending request (from 3), we re-use it
|
||||||
|
7. the request from 3 finishes, and we end up with a
|
||||||
|
wrong icon in the cache
|
||||||
|
|
||||||
|
The simplest fix is to change the icon theme before the GTK theme: Unlike the
|
||||||
|
theme name, the icon style is encoded in the cache key, so we won't re-use
|
||||||
|
an old (and incorrect) request in that case.
|
||||||
|
---
|
||||||
|
js/ui/status/accessibility.js | 6 +++---
|
||||||
|
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/status/accessibility.js b/js/ui/status/accessibility.js
|
||||||
|
index 10223ec84..90948d465 100644
|
||||||
|
--- a/js/ui/status/accessibility.js
|
||||||
|
+++ b/js/ui/status/accessibility.js
|
||||||
|
@@ -154,14 +154,14 @@ class ATIndicator extends PanelMenu.Button {
|
||||||
|
interfaceSettings.is_writable(KEY_ICON_THEME),
|
||||||
|
enabled => {
|
||||||
|
if (enabled) {
|
||||||
|
- interfaceSettings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
|
||||||
|
interfaceSettings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
|
||||||
|
+ interfaceSettings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
|
||||||
|
} else if(!hasHC) {
|
||||||
|
- interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme);
|
||||||
|
interfaceSettings.set_string(KEY_ICON_THEME, iconTheme);
|
||||||
|
+ interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme);
|
||||||
|
} else {
|
||||||
|
- interfaceSettings.reset(KEY_GTK_THEME);
|
||||||
|
interfaceSettings.reset(KEY_ICON_THEME);
|
||||||
|
+ interfaceSettings.reset(KEY_GTK_THEME);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return highContrast;
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
|
|
@ -0,0 +1,40 @@
|
|||||||
|
From 34e6bbeebef37ae688ca0527bde03fa26b143bb7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Thu, 27 Jun 2019 14:27:34 -0400
|
||||||
|
Subject: [PATCH] animation: fix unintentional loop while polkit dialog is
|
||||||
|
active
|
||||||
|
|
||||||
|
The polkit password dialog has a spinner that gets displayed
|
||||||
|
while the users password is being verified.
|
||||||
|
|
||||||
|
Unfortunately, the spinner stop method unintentionally calls
|
||||||
|
back into itself after the stop fade out animation is complete.
|
||||||
|
The stop method is called at startup, so the looping begins as
|
||||||
|
soon as the dialog is visible and continues until the dialog is
|
||||||
|
dismissed.
|
||||||
|
|
||||||
|
This commit fixes the loop by having the stop method cease
|
||||||
|
calling itself, and instead having it call the stop method on the
|
||||||
|
superclass.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/602
|
||||||
|
---
|
||||||
|
js/ui/animation.js | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/animation.js b/js/ui/animation.js
|
||||||
|
index c21b22565..58d7f4018 100644
|
||||||
|
--- a/js/ui/animation.js
|
||||||
|
+++ b/js/ui/animation.js
|
||||||
|
@@ -162,7 +162,7 @@ var Spinner = class extends AnimatedIcon {
|
||||||
|
time: SPINNER_ANIMATION_TIME,
|
||||||
|
transition: 'linear',
|
||||||
|
onComplete: () => {
|
||||||
|
- this.stop(false);
|
||||||
|
+ super.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -0,0 +1,111 @@
|
|||||||
|
From a1c35ebb8f29103035526e6f48eba4ff37551964 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Thu, 21 Jun 2018 18:03:31 +0200
|
||||||
|
Subject: [PATCH] appDisplay: Show full app name on hover
|
||||||
|
|
||||||
|
---
|
||||||
|
data/theme/gnome-shell-sass/_common.scss | 8 ++++
|
||||||
|
js/ui/appDisplay.js | 48 ++++++++++++++++++++++++
|
||||||
|
2 files changed, 56 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss
|
||||||
|
index 3b0d2bf04..293ea2ab9 100644
|
||||||
|
--- a/data/theme/gnome-shell-sass/_common.scss
|
||||||
|
+++ b/data/theme/gnome-shell-sass/_common.scss
|
||||||
|
@@ -1411,6 +1411,14 @@ StScrollBar {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
+ .app-well-hover-text {
|
||||||
|
+ text-align: center;
|
||||||
|
+ color: $osd_fg_color;
|
||||||
|
+ background-color: $osd_bg_color;
|
||||||
|
+ border-radius: 5px;
|
||||||
|
+ padding: 3px;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
.app-well-app-running-dot { //running apps indicator
|
||||||
|
width: 10px; height: 3px;
|
||||||
|
background-color: $selected_bg_color;
|
||||||
|
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
|
||||||
|
index adaefa7dd..a07db6573 100644
|
||||||
|
--- a/js/ui/appDisplay.js
|
||||||
|
+++ b/js/ui/appDisplay.js
|
||||||
|
@@ -1478,6 +1478,20 @@ var AppIcon = class AppIcon {
|
||||||
|
this.actor.connect('clicked', this._onClicked.bind(this));
|
||||||
|
this.actor.connect('popup-menu', this._onKeyboardPopupMenu.bind(this));
|
||||||
|
|
||||||
|
+ this._hoverText = null;
|
||||||
|
+ this._hoverTimeoutId = 0;
|
||||||
|
+
|
||||||
|
+ if (this.icon.label) {
|
||||||
|
+ this._hoverText = new St.Label({ style_class: 'app-well-hover-text',
|
||||||
|
+ text: this.icon.label.text,
|
||||||
|
+ visible: false });
|
||||||
|
+ this._hoverText.clutter_text.line_wrap = true;
|
||||||
|
+ Main.layoutManager.addChrome(this._hoverText);
|
||||||
|
+
|
||||||
|
+ this.actor.connect('notify::hover', this._syncHoverText.bind(this));
|
||||||
|
+ this.connect('sync-tooltip', this._syncHoverText.bind(this));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
this._menu = null;
|
||||||
|
this._menuManager = new PopupMenu.PopupMenuManager(this);
|
||||||
|
|
||||||
|
@@ -1509,12 +1523,39 @@ var AppIcon = class AppIcon {
|
||||||
|
this.app.disconnect(this._stateChangedId);
|
||||||
|
this._stateChangedId = 0;
|
||||||
|
this._removeMenuTimeout();
|
||||||
|
+ this._removeHoverTimeout();
|
||||||
|
+ if (this._hoverText)
|
||||||
|
+ this._hoverText.destroy();
|
||||||
|
+ this._hoverText = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_createIcon(iconSize) {
|
||||||
|
return this.app.create_icon_texture(iconSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ _syncHoverText() {
|
||||||
|
+ if (this.shouldShowTooltip()) {
|
||||||
|
+ if (this._hoverTimeoutId)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ this._hoverTimeoutId = Mainloop.timeout_add(300, () => {
|
||||||
|
+ this._hoverText.style = `max-width: ${2 * this.icon.iconSize}px;`;
|
||||||
|
+ this._hoverText.ensure_style();
|
||||||
|
+
|
||||||
|
+ let [x, y] = this.icon.label.get_transformed_position();
|
||||||
|
+ let offset = (this._hoverText.width - this.icon.label.width) / 2;
|
||||||
|
+ this._hoverText.set_position(Math.floor(x - offset), Math.floor(y));
|
||||||
|
+ this._hoverText.show();
|
||||||
|
+
|
||||||
|
+ this._hoverTimeoutId = 0;
|
||||||
|
+ return GLib.SOURCE_REMOVE;
|
||||||
|
+ });
|
||||||
|
+ } else {
|
||||||
|
+ this._removeHoverTimeout();
|
||||||
|
+ this._hoverText.hide();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
_removeMenuTimeout() {
|
||||||
|
if (this._menuTimeoutId > 0) {
|
||||||
|
Mainloop.source_remove(this._menuTimeoutId);
|
||||||
|
@@ -1522,6 +1563,13 @@ var AppIcon = class AppIcon {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ _removeHoverTimeout() {
|
||||||
|
+ if (this._hoverTimeoutId > 0) {
|
||||||
|
+ Mainloop.source_remove(this._hoverTimeoutId);
|
||||||
|
+ this._hoverTimeoutId = 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
_updateRunningStyle() {
|
||||||
|
if (this.app.state != Shell.AppState.STOPPED)
|
||||||
|
this._dot.show();
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -1,100 +0,0 @@
|
|||||||
From ec802e39a5dfb252e2d18b8cb95f713724180565 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ray Strode <rstrode@redhat.com>
|
|
||||||
Date: Mon, 15 May 2023 10:48:15 -0400
|
|
||||||
Subject: [PATCH] authPrompt: Disregard smartcard status changes events if
|
|
||||||
VERIFICATION_IN_PROGRESS
|
|
||||||
|
|
||||||
commit c8bb45b41c3a13ef161103f649aa18938e028a70 introduced a new
|
|
||||||
verification state, VERIFICATION_IN_PROGRESS, to detect when the user
|
|
||||||
has already interacted with the authentication service, so the auth
|
|
||||||
prompt can rate limit the number of times the user can cancel
|
|
||||||
authentication attempts with the escape key (without also rate limiting
|
|
||||||
the number of times they hit escape to go back to the clock without
|
|
||||||
interacting with the authentication service).
|
|
||||||
|
|
||||||
That means there are now two states that represent the
|
|
||||||
user actively undergoing verification: VERIFYING and
|
|
||||||
VERIFICATION_IN_PROGRESS.
|
|
||||||
|
|
||||||
It's inappropriate to reset the smartcard service if the user is
|
|
||||||
actively conversing with it. We try to check for that by looking at the
|
|
||||||
original verification state, VERIFYING, but we unfortunately, neglected
|
|
||||||
to account for the new VERIFICATION_IN_PROGRESS state.
|
|
||||||
|
|
||||||
This commit fixes that oversight, and allows users to again pre-type
|
|
||||||
their smartcard pin at the clock before inserting their smartcard.
|
|
||||||
---
|
|
||||||
js/gdm/authPrompt.js | 3 ++-
|
|
||||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js
|
|
||||||
index 4da91e096..e961f396e 100644
|
|
||||||
--- a/js/gdm/authPrompt.js
|
|
||||||
+++ b/js/gdm/authPrompt.js
|
|
||||||
@@ -327,61 +327,62 @@ var AuthPrompt = GObject.registerClass({
|
|
||||||
_onShowChoiceList(userVerifier, serviceName, promptMessage, choiceList) {
|
|
||||||
if (this._queryingService)
|
|
||||||
this.clear();
|
|
||||||
|
|
||||||
this._queryingService = serviceName;
|
|
||||||
|
|
||||||
if (this._preemptiveAnswer)
|
|
||||||
this._preemptiveAnswer = null;
|
|
||||||
|
|
||||||
this.setChoiceList(promptMessage, choiceList);
|
|
||||||
this.updateSensitivity(true);
|
|
||||||
this.emit('prompted');
|
|
||||||
}
|
|
||||||
|
|
||||||
_onCredentialManagerAuthenticated() {
|
|
||||||
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
|
|
||||||
this.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
_onSmartcardStatusChanged() {
|
|
||||||
this.smartcardDetected = this._userVerifier.smartcardDetected;
|
|
||||||
|
|
||||||
// Most of the time we want to reset if the user inserts or removes
|
|
||||||
// a smartcard. Smartcard insertion "preempts" what the user was
|
|
||||||
// doing, and smartcard removal aborts the preemption.
|
|
||||||
// The exceptions are: 1) Don't reset on smartcard insertion if we're already verifying
|
|
||||||
// with a smartcard
|
|
||||||
// 2) Don't reset if we've already succeeded at verification and
|
|
||||||
// the user is getting logged in.
|
|
||||||
if (this._userVerifier.serviceIsDefault(GdmUtil.SMARTCARD_SERVICE_NAME) &&
|
|
||||||
- this.verificationStatus == AuthPromptStatus.VERIFYING &&
|
|
||||||
+ (this.verificationStatus === AuthPromptStatus.VERIFYING ||
|
|
||||||
+ this.verificationStatus === AuthPromptStatus.VERIFICATION_IN_PROGRESS) &&
|
|
||||||
this.smartcardDetected)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
|
|
||||||
this.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
_onShowMessage(_userVerifier, serviceName, message, type) {
|
|
||||||
this.setMessage(serviceName, message, type);
|
|
||||||
this.emit('prompted');
|
|
||||||
}
|
|
||||||
|
|
||||||
_onVerificationFailed(userVerifier, serviceName, canRetry) {
|
|
||||||
const wasQueryingService = this._queryingService === serviceName;
|
|
||||||
|
|
||||||
if (wasQueryingService) {
|
|
||||||
this._queryingService = null;
|
|
||||||
this.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.updateSensitivity(canRetry);
|
|
||||||
this.setActorInDefaultButtonWell(null);
|
|
||||||
|
|
||||||
if (!canRetry)
|
|
||||||
this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
|
|
||||||
|
|
||||||
if (wasQueryingService)
|
|
||||||
Util.wiggle(this._entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.39.1
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
|||||||
|
From 165fc5147cd2c9bf4bc10a1c5a9a940ec4ddd8d9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Tue, 15 Jan 2019 12:51:16 -0500
|
||||||
|
Subject: [PATCH 1/4] background: refresh after suspend on wayland
|
||||||
|
|
||||||
|
At the moment we only refresh after suspend on Xorg.
|
||||||
|
|
||||||
|
We need to do it on wayland, too.
|
||||||
|
---
|
||||||
|
src/shell-util.c | 3 ---
|
||||||
|
1 file changed, 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/shell-util.c b/src/shell-util.c
|
||||||
|
index 31bb18e70..c6e5abed6 100644
|
||||||
|
--- a/src/shell-util.c
|
||||||
|
+++ b/src/shell-util.c
|
||||||
|
@@ -395,9 +395,6 @@ get_gl_vendor (void)
|
||||||
|
gboolean
|
||||||
|
shell_util_need_background_refresh (void)
|
||||||
|
{
|
||||||
|
- if (!clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
|
||||||
|
- return FALSE;
|
||||||
|
-
|
||||||
|
if (g_strcmp0 (get_gl_vendor (), "NVIDIA Corporation") == 0)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -0,0 +1,37 @@
|
|||||||
|
From 1dcae7bbba222a1c8bdfc2d76a9f716e638b0334 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Thu, 8 Jun 2017 12:04:31 -0400
|
||||||
|
Subject: [PATCH] data: install process-working.svg to filesystem
|
||||||
|
|
||||||
|
This helps prevent unlock failure on inplace upgrades between
|
||||||
|
7.3 and 7.4
|
||||||
|
---
|
||||||
|
data/theme/meson.build | 2 ++
|
||||||
|
meson.build | 1 +
|
||||||
|
2 files changed, 3 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/data/theme/meson.build b/data/theme/meson.build
|
||||||
|
index 22bae3dd2..d5acb8d10 100644
|
||||||
|
--- a/data/theme/meson.build
|
||||||
|
+++ b/data/theme/meson.build
|
||||||
|
@@ -23,3 +23,5 @@ foreach style: styles
|
||||||
|
],
|
||||||
|
depend_files: theme_sources)
|
||||||
|
endforeach
|
||||||
|
+
|
||||||
|
+install_data('process-working.svg', install_dir: themedir)
|
||||||
|
diff --git a/meson.build b/meson.build
|
||||||
|
index 21a80bcc8..0acaba705 100644
|
||||||
|
--- a/meson.build
|
||||||
|
+++ b/meson.build
|
||||||
|
@@ -57,6 +57,7 @@ localedir = join_paths(datadir, 'locale')
|
||||||
|
portaldir = join_paths(datadir, 'xdg-desktop-portal', 'portals')
|
||||||
|
schemadir = join_paths(datadir, 'glib-2.0', 'schemas')
|
||||||
|
servicedir = join_paths(datadir, 'dbus-1', 'services')
|
||||||
|
+themedir = join_paths(pkgdatadir, 'theme')
|
||||||
|
|
||||||
|
# XXX: Once https://github.com/systemd/systemd/issues/9595 is fixed and we can
|
||||||
|
# depend on this version, replace with something like:
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -0,0 +1,65 @@
|
|||||||
|
From 6e80934456f0b4cc48da6a7201700dc4386a3474 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Thu, 27 Feb 2020 13:46:44 -0800
|
||||||
|
Subject: [PATCH] environment: reduce calls to g_time_zone_new_local()
|
||||||
|
|
||||||
|
Creating a new GTimeZone for the local timezone can be quite expensive if
|
||||||
|
done repeatedly. It requires an open(), mmap(), and parsing of
|
||||||
|
/etc/localtime.
|
||||||
|
|
||||||
|
This patch was provided by Florian, and I've tested it as far back as
|
||||||
|
3.28.4 to ensure that we are really reducing the number of open() calls
|
||||||
|
on the compositor thread.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1051
|
||||||
|
|
||||||
|
Signed-off-by: Christian Hergert <chergert@redhat.com>
|
||||||
|
---
|
||||||
|
js/ui/environment.js | 22 +++++++++++++++++++++-
|
||||||
|
1 file changed, 21 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/environment.js b/js/ui/environment.js
|
||||||
|
index 9c125d3eb..809b48e45 100644
|
||||||
|
--- a/js/ui/environment.js
|
||||||
|
+++ b/js/ui/environment.js
|
||||||
|
@@ -11,6 +11,9 @@ imports.gi.versions.TelepathyLogger = '0.2';
|
||||||
|
|
||||||
|
const { Clutter, Gio, GLib, Shell, St } = imports.gi;
|
||||||
|
const Gettext = imports.gettext;
|
||||||
|
+const System = imports.system;
|
||||||
|
+
|
||||||
|
+let _localTimeZone = null;
|
||||||
|
|
||||||
|
// We can't import shell JS modules yet, because they may have
|
||||||
|
// variable initializations, etc, that depend on init() already having
|
||||||
|
@@ -117,9 +120,26 @@ function init() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
+ // Override to clear our own timezone cache as well
|
||||||
|
+ const origClearDateCaches = System.clearDateCaches;
|
||||||
|
+ System.clearDateCaches = function () {
|
||||||
|
+ _localTimeZone = null;
|
||||||
|
+ origClearDateCaches();
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783
|
||||||
|
Date.prototype.toLocaleFormat = function(format) {
|
||||||
|
- return Shell.util_format_date(format, this.getTime());
|
||||||
|
+ if (_localTimeZone === null)
|
||||||
|
+ _localTimeZone = GLib.TimeZone.new_local();
|
||||||
|
+
|
||||||
|
+ let dt = GLib.DateTime.new(_localTimeZone,
|
||||||
|
+ this.getYear(),
|
||||||
|
+ this.getMonth() + 1,
|
||||||
|
+ this.getDate(),
|
||||||
|
+ this.getHours(),
|
||||||
|
+ this.getMinutes(),
|
||||||
|
+ this.getSeconds());
|
||||||
|
+ return dt ? dt.format(format) : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR');
|
||||||
|
--
|
||||||
|
2.31.1
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
From c18b7b7819f17f5d14be1ba2760653f3d93b81b1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
||||||
Date: Mon, 1 Feb 2021 18:26:00 +0100
|
|
||||||
Subject: [PATCH] extensionDownloader: Refuse to override system extensions
|
|
||||||
|
|
||||||
The website allows to "update" system extensions by installing the
|
|
||||||
upstream version into the user's home directory.
|
|
||||||
|
|
||||||
Prevent that by refusing to download and install extensions that are
|
|
||||||
already installed system-wide.
|
|
||||||
---
|
|
||||||
js/ui/extensionDownloader.js | 8 ++++++++
|
|
||||||
1 file changed, 8 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js
|
|
||||||
index 6a3b2b488..471ddab14 100644
|
|
||||||
--- a/js/ui/extensionDownloader.js
|
|
||||||
+++ b/js/ui/extensionDownloader.js
|
|
||||||
@@ -17,6 +17,14 @@ var REPOSITORY_URL_UPDATE = 'https://extensions.gnome.org/update-info/';
|
|
||||||
let _httpSession;
|
|
||||||
|
|
||||||
function installExtension(uuid, invocation) {
|
|
||||||
+ const oldExt = Main.extensionManager.lookup(uuid);
|
|
||||||
+ if (oldExt && oldExt.type === ExtensionUtils.ExtensionType.SYSTEM) {
|
|
||||||
+ log('extensionDownloader: Trying to replace system extension %s'.format(uuid));
|
|
||||||
+ invocation.return_dbus_error('org.gnome.Shell.InstallError',
|
|
||||||
+ 'System extensions cannot be replaced');
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
let params = { uuid,
|
|
||||||
shell_version: Config.PACKAGE_VERSION };
|
|
||||||
|
|
||||||
--
|
|
||||||
2.31.1
|
|
||||||
|
|
@ -0,0 +1,87 @@
|
|||||||
|
From 1b6eb29ade832647510b36ddc13c9b88a25036df Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
|
||||||
|
Date: Wed, 11 Sep 2019 20:18:20 +0200
|
||||||
|
Subject: [PATCH 1/4] extensionSystem: Handle added or removed sessionMode
|
||||||
|
extensions
|
||||||
|
|
||||||
|
Right now we're only handling added sessionMode extensions correctly on
|
||||||
|
sessionMode updates, also handle the other case and disable removed
|
||||||
|
sessionMode extensions on sessionMode updates.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
|
||||||
|
---
|
||||||
|
js/ui/extensionSystem.js | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
|
||||||
|
index 81804ea5e..77929f2a6 100644
|
||||||
|
--- a/js/ui/extensionSystem.js
|
||||||
|
+++ b/js/ui/extensionSystem.js
|
||||||
|
@@ -515,62 +515,62 @@ var ExtensionManager = class {
|
||||||
|
if (!this._initted) {
|
||||||
|
this._loadExtensions();
|
||||||
|
this._initted = true;
|
||||||
|
} else {
|
||||||
|
this._enabledExtensions.forEach(uuid => {
|
||||||
|
this._callExtensionEnable(uuid);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this._enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_disableAllExtensions() {
|
||||||
|
if (!this._enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this._initted) {
|
||||||
|
this._extensionOrder.slice().reverse().forEach(uuid => {
|
||||||
|
this._callExtensionDisable(uuid);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this._enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_sessionUpdated() {
|
||||||
|
// For now sessionMode.allowExtensions controls extensions from both the
|
||||||
|
// 'enabled-extensions' preference and the sessionMode.enabledExtensions
|
||||||
|
// property; it might make sense to make enabledExtensions independent
|
||||||
|
// from allowExtensions in the future
|
||||||
|
if (Main.sessionMode.allowExtensions) {
|
||||||
|
- if (this._initted)
|
||||||
|
- this._enabledExtensions = this._getEnabledExtensions();
|
||||||
|
+ // Take care of added or removed sessionMode extensions
|
||||||
|
+ this._onEnabledExtensionsChanged();
|
||||||
|
this._enableAllExtensions();
|
||||||
|
} else {
|
||||||
|
this._disableAllExtensions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Signals.addSignalMethods(ExtensionManager.prototype);
|
||||||
|
|
||||||
|
class ExtensionUpdateSource extends MessageTray.Source {
|
||||||
|
constructor() {
|
||||||
|
const appSys = Shell.AppSystem.get_default();
|
||||||
|
this._app = appSys.lookup_app('gnome-shell-extension-prefs.desktop');
|
||||||
|
|
||||||
|
super(this._app.get_name());
|
||||||
|
}
|
||||||
|
|
||||||
|
getIcon() {
|
||||||
|
return this._app.app_info.get_icon();
|
||||||
|
}
|
||||||
|
|
||||||
|
_createPolicy() {
|
||||||
|
return new MessageTray.NotificationApplicationPolicy(this._app.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
open() {
|
||||||
|
this._app.activate();
|
||||||
|
Main.overview.hide();
|
||||||
|
Main.panel.closeCalendar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
@ -1,92 +0,0 @@
|
|||||||
From 91449e6a19af63eebaf5f97f85ba44f69259075a Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
||||||
Date: Sat, 10 Feb 2024 00:58:27 +0100
|
|
||||||
Subject: [PATCH] extensionSystem: Support locking down extension installation
|
|
||||||
|
|
||||||
Currently extensions can only be locked down completely by
|
|
||||||
restricting the `enabled-extensions` key via dconf.
|
|
||||||
|
|
||||||
This is too restrictive for environments that want to allow users
|
|
||||||
to customize their system with extensions, while still limiting
|
|
||||||
the set of possible extensions.
|
|
||||||
|
|
||||||
To fill that gap, add a new `allow-extension-installation` setting,
|
|
||||||
which restricts extensions to system extensions when disabled.
|
|
||||||
|
|
||||||
As the setting is mainly intended for locking down by system
|
|
||||||
administrators, there is no attempt to load/unload extensions
|
|
||||||
on settings changes.
|
|
||||||
---
|
|
||||||
data/org.gnome.shell.gschema.xml.in | 11 +++++++++++
|
|
||||||
js/ui/extensionDownloader.js | 6 ++++++
|
|
||||||
js/ui/extensionSystem.js | 8 ++++++--
|
|
||||||
3 files changed, 23 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in
|
|
||||||
index 6f1c424bad..b5921983cd 100644
|
|
||||||
--- a/data/org.gnome.shell.gschema.xml.in
|
|
||||||
+++ b/data/org.gnome.shell.gschema.xml.in
|
|
||||||
@@ -40,6 +40,17 @@
|
|
||||||
the “enabled-extension” setting.
|
|
||||||
</description>
|
|
||||||
</key>
|
|
||||||
+ <key name="allow-extension-installation" type="b">
|
|
||||||
+ <default>true</default>
|
|
||||||
+ <summary>Allow extension installation</summary>
|
|
||||||
+ <description>
|
|
||||||
+ Allow users to install extensions in their home folder. If disabled,
|
|
||||||
+ the InstallRemoteExtension D-Bus method will fail, and extensions
|
|
||||||
+ are only loaded from system directories on startup.
|
|
||||||
+ It does not affect extensions that are already loaded, so a change
|
|
||||||
+ only takes full effect on the next login.
|
|
||||||
+ </description>
|
|
||||||
+ </key>
|
|
||||||
<key name="disable-extension-version-validation" type="b">
|
|
||||||
<default>false</default>
|
|
||||||
<summary>Disables the validation of extension version compatibility</summary>
|
|
||||||
diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js
|
|
||||||
index 471ddab147..01ed165c01 100644
|
|
||||||
--- a/js/ui/extensionDownloader.js
|
|
||||||
+++ b/js/ui/extensionDownloader.js
|
|
||||||
@@ -17,6 +17,12 @@ var REPOSITORY_URL_UPDATE = 'https://extensions.gnome.org/update-info/';
|
|
||||||
let _httpSession;
|
|
||||||
|
|
||||||
function installExtension(uuid, invocation) {
|
|
||||||
+ if (!global.settings.get_boolean('allow-extension-installation')) {
|
|
||||||
+ invocation.return_dbus_error('org.gnome.Shell.InstallError',
|
|
||||||
+ 'Extension installation is not allowed');
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
const oldExt = Main.extensionManager.lookup(uuid);
|
|
||||||
if (oldExt && oldExt.type === ExtensionUtils.ExtensionType.SYSTEM) {
|
|
||||||
log('extensionDownloader: Trying to replace system extension %s'.format(uuid));
|
|
||||||
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
|
|
||||||
index 937f861994..528d9ea450 100644
|
|
||||||
--- a/js/ui/extensionSystem.js
|
|
||||||
+++ b/js/ui/extensionSystem.js
|
|
||||||
@@ -64,7 +64,10 @@ var ExtensionManager = class {
|
|
||||||
|
|
||||||
get updatesSupported() {
|
|
||||||
const appSys = Shell.AppSystem.get_default();
|
|
||||||
- return appSys.lookup_app('org.gnome.Extensions.desktop') !== null;
|
|
||||||
+ const hasUpdatesApp =
|
|
||||||
+ appSys.lookup_app('org.gnome.Extensions.desktop') !== null;
|
|
||||||
+ const allowed = global.settings.get_boolean('allow-extension-installation');
|
|
||||||
+ return allowed && hasUpdatesApp;
|
|
||||||
}
|
|
||||||
|
|
||||||
lookup(uuid) {
|
|
||||||
@@ -595,7 +598,8 @@ var ExtensionManager = class {
|
|
||||||
this._enabledExtensions = this._getEnabledExtensions();
|
|
||||||
|
|
||||||
let perUserDir = Gio.File.new_for_path(global.userdatadir);
|
|
||||||
- FileUtils.collectFromDatadirs('extensions', true, (dir, info) => {
|
|
||||||
+ const includeUserDir = global.settings.get_boolean('allow-extension-installation');
|
|
||||||
+ FileUtils.collectFromDatadirs('extensions', includeUserDir, (dir, info) => {
|
|
||||||
let fileType = info.get_file_type();
|
|
||||||
if (fileType != Gio.FileType.DIRECTORY)
|
|
||||||
return;
|
|
||||||
--
|
|
||||||
2.43.0
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
|||||||
|
From 720eb83ba0b0e5e37185d7e7ed86fe9175cf18f4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rui Matos <tiagomatos@gmail.com>
|
||||||
|
Date: Fri, 8 Nov 2013 13:58:09 +0100
|
||||||
|
Subject: [PATCH] extensions: Add a SESSION_MODE extension type
|
||||||
|
|
||||||
|
This allows e.g. gnome-tweak-tool to present these extensions in a
|
||||||
|
different way since they can't be disabled.
|
||||||
|
---
|
||||||
|
js/misc/extensionUtils.js | 3 ++-
|
||||||
|
js/ui/extensionSystem.js | 2 ++
|
||||||
|
2 files changed, 4 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/misc/extensionUtils.js b/js/misc/extensionUtils.js
|
||||||
|
index cf308b31f..fb1e2b506 100644
|
||||||
|
--- a/js/misc/extensionUtils.js
|
||||||
|
+++ b/js/misc/extensionUtils.js
|
||||||
|
@@ -13,7 +13,8 @@ const FileUtils = imports.misc.fileUtils;
|
||||||
|
|
||||||
|
var ExtensionType = {
|
||||||
|
SYSTEM: 1,
|
||||||
|
- PER_USER: 2
|
||||||
|
+ PER_USER: 2,
|
||||||
|
+ SESSION_MODE: 3
|
||||||
|
};
|
||||||
|
|
||||||
|
// Maps uuid -> metadata object
|
||||||
|
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
|
||||||
|
index 6244c39b4..9ffdb4f3d 100644
|
||||||
|
--- a/js/ui/extensionSystem.js
|
||||||
|
+++ b/js/ui/extensionSystem.js
|
||||||
|
@@ -322,6 +322,8 @@ function _loadExtensions() {
|
||||||
|
let finder = new ExtensionUtils.ExtensionFinder();
|
||||||
|
finder.connect('extension-found', (finder, extension) => {
|
||||||
|
loadExtension(extension);
|
||||||
|
+ if (Main.sessionMode.enabledExtensions.indexOf(extension.uuid) != -1)
|
||||||
|
+ extension.type = ExtensionUtils.ExtensionType.SESSION_MODE;
|
||||||
|
});
|
||||||
|
finder.scanExtensions();
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -0,0 +1,237 @@
|
|||||||
|
From 592bf9b4ba879a365375a7edcb6c48258386e413 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Tue, 18 Jul 2017 12:58:14 -0400
|
||||||
|
Subject: [PATCH 1/2] gdm: add AuthList control
|
||||||
|
|
||||||
|
Ultimately, we want to add support for GDM's new ChoiceList
|
||||||
|
PAM extension. That extension allows PAM modules to present
|
||||||
|
a list of choices to the user. Before we can support that
|
||||||
|
extension, however, we need to have a list control in the
|
||||||
|
login-screen/unlock screen. This commit adds that control.
|
||||||
|
|
||||||
|
For the most part, it's a copy-and-paste of the gdm userlist,
|
||||||
|
but with less features. It lacks API specific to the users,
|
||||||
|
lacks the built in timed login indicator, etc. It does feature
|
||||||
|
a label heading.
|
||||||
|
---
|
||||||
|
js/gdm/authList.js | 195 ++++++++++++++++++++++++++++++++++
|
||||||
|
js/js-resources.gresource.xml | 1 +
|
||||||
|
2 files changed, 196 insertions(+)
|
||||||
|
create mode 100644 js/gdm/authList.js
|
||||||
|
|
||||||
|
diff --git a/js/gdm/authList.js b/js/gdm/authList.js
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..fc1c3d6e4
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/js/gdm/authList.js
|
||||||
|
@@ -0,0 +1,195 @@
|
||||||
|
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||||
|
+/*
|
||||||
|
+ * Copyright 2017 Red Hat, Inc
|
||||||
|
+ *
|
||||||
|
+ * This program is free software; you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License as published by
|
||||||
|
+ * the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
+ * any later version.
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * You should have received a copy of the GNU General Public License
|
||||||
|
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+const Clutter = imports.gi.Clutter;
|
||||||
|
+const GObject = imports.gi.GObject;
|
||||||
|
+const Gtk = imports.gi.Gtk;
|
||||||
|
+const Lang = imports.lang;
|
||||||
|
+const Meta = imports.gi.Meta;
|
||||||
|
+const Signals = imports.signals;
|
||||||
|
+const St = imports.gi.St;
|
||||||
|
+
|
||||||
|
+const Tweener = imports.ui.tweener;
|
||||||
|
+
|
||||||
|
+const _SCROLL_ANIMATION_TIME = 0.5;
|
||||||
|
+
|
||||||
|
+const AuthListItem = new Lang.Class({
|
||||||
|
+ Name: 'AuthListItem',
|
||||||
|
+
|
||||||
|
+ _init(key, text) {
|
||||||
|
+ this.key = key;
|
||||||
|
+ let label = new St.Label({ style_class: 'auth-list-item-label',
|
||||||
|
+ y_align: Clutter.ActorAlign.CENTER });
|
||||||
|
+ label.text = text;
|
||||||
|
+
|
||||||
|
+ this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
|
||||||
|
+ button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
|
||||||
|
+ can_focus: true,
|
||||||
|
+ child: label,
|
||||||
|
+ reactive: true,
|
||||||
|
+ x_align: St.Align.START,
|
||||||
|
+ x_fill: true });
|
||||||
|
+
|
||||||
|
+ this.actor.connect('key-focus-in', () => {
|
||||||
|
+ this._setSelected(true);
|
||||||
|
+ });
|
||||||
|
+ this.actor.connect('key-focus-out', () => {
|
||||||
|
+ this._setSelected(false);
|
||||||
|
+ });
|
||||||
|
+ this.actor.connect('notify::hover', () => {
|
||||||
|
+ this._setSelected(this.actor.hover);
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ this.actor.connect('clicked', this._onClicked.bind(this));
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ _onClicked() {
|
||||||
|
+ this.emit('activate');
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ _setSelected(selected) {
|
||||||
|
+ if (selected) {
|
||||||
|
+ this.actor.add_style_pseudo_class('selected');
|
||||||
|
+ this.actor.grab_key_focus();
|
||||||
|
+ } else {
|
||||||
|
+ this.actor.remove_style_pseudo_class('selected');
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+});
|
||||||
|
+Signals.addSignalMethods(AuthListItem.prototype);
|
||||||
|
+
|
||||||
|
+var AuthList = new Lang.Class({
|
||||||
|
+ Name: 'AuthList',
|
||||||
|
+
|
||||||
|
+ _init() {
|
||||||
|
+ this.actor = new St.BoxLayout({ vertical: true,
|
||||||
|
+ style_class: 'login-dialog-auth-list-layout' });
|
||||||
|
+
|
||||||
|
+ this.label = new St.Label({ style_class: 'prompt-dialog-headline' });
|
||||||
|
+ this.actor.add_actor(this.label);
|
||||||
|
+
|
||||||
|
+ this._scrollView = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
|
||||||
|
+ this._scrollView.set_policy(Gtk.PolicyType.NEVER,
|
||||||
|
+ Gtk.PolicyType.AUTOMATIC);
|
||||||
|
+ this.actor.add_actor(this._scrollView);
|
||||||
|
+
|
||||||
|
+ this._box = new St.BoxLayout({ vertical: true,
|
||||||
|
+ style_class: 'login-dialog-user-list',
|
||||||
|
+ pseudo_class: 'expanded' });
|
||||||
|
+
|
||||||
|
+ this._scrollView.add_actor(this._box);
|
||||||
|
+ this._items = {};
|
||||||
|
+
|
||||||
|
+ this.actor.connect('key-focus-in', this._moveFocusToItems.bind(this));
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ _moveFocusToItems() {
|
||||||
|
+ let hasItems = Object.keys(this._items).length > 0;
|
||||||
|
+
|
||||||
|
+ if (!hasItems)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (global.stage.get_key_focus() != this.actor)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ let focusSet = this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||||
|
+ if (!focusSet) {
|
||||||
|
+ Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
|
||||||
|
+ this._moveFocusToItems();
|
||||||
|
+ return false;
|
||||||
|
+ });
|
||||||
|
+ }
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ _onItemActivated(activatedItem) {
|
||||||
|
+ this.emit('activate', activatedItem.key);
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ scrollToItem(item) {
|
||||||
|
+ let box = item.actor.get_allocation_box();
|
||||||
|
+
|
||||||
|
+ let adjustment = this._scrollView.get_vscroll_bar().get_adjustment();
|
||||||
|
+
|
||||||
|
+ let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
|
||||||
|
+ Tweener.removeTweens(adjustment);
|
||||||
|
+ Tweener.addTween (adjustment,
|
||||||
|
+ { value: value,
|
||||||
|
+ time: _SCROLL_ANIMATION_TIME,
|
||||||
|
+ transition: 'easeOutQuad' });
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ jumpToItem(item) {
|
||||||
|
+ let box = item.actor.get_allocation_box();
|
||||||
|
+
|
||||||
|
+ let adjustment = this._scrollView.get_vscroll_bar().get_adjustment();
|
||||||
|
+
|
||||||
|
+ let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
|
||||||
|
+
|
||||||
|
+ adjustment.set_value(value);
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ getItem(key) {
|
||||||
|
+ let item = this._items[key];
|
||||||
|
+
|
||||||
|
+ if (!item)
|
||||||
|
+ return null;
|
||||||
|
+
|
||||||
|
+ return item;
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ addItem(key, text) {
|
||||||
|
+ this.removeItem(key);
|
||||||
|
+
|
||||||
|
+ let item = new AuthListItem(key, text);
|
||||||
|
+ this._box.add(item.actor, { x_fill: true });
|
||||||
|
+
|
||||||
|
+ this._items[key] = item;
|
||||||
|
+
|
||||||
|
+ item.connect('activate',
|
||||||
|
+ this._onItemActivated.bind(this));
|
||||||
|
+
|
||||||
|
+ // Try to keep the focused item front-and-center
|
||||||
|
+ item.actor.connect('key-focus-in',
|
||||||
|
+ () => { this.scrollToItem(item); });
|
||||||
|
+
|
||||||
|
+ this._moveFocusToItems();
|
||||||
|
+
|
||||||
|
+ this.emit('item-added', item);
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ removeItem(key) {
|
||||||
|
+ let item = this._items[key];
|
||||||
|
+
|
||||||
|
+ if (!item)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ item.actor.destroy();
|
||||||
|
+ delete this._items[key];
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ numItems() {
|
||||||
|
+ return Object.keys(this._items).length;
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
+ clear() {
|
||||||
|
+ this.label.text = "";
|
||||||
|
+ this._box.destroy_all_children();
|
||||||
|
+ this._items = {};
|
||||||
|
+ }
|
||||||
|
+});
|
||||||
|
+Signals.addSignalMethods(AuthList.prototype);
|
||||||
|
diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
|
||||||
|
index 836d1c674..002b202f8 100644
|
||||||
|
--- a/js/js-resources.gresource.xml
|
||||||
|
+++ b/js/js-resources.gresource.xml
|
||||||
|
@@ -1,6 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<gresources>
|
||||||
|
<gresource prefix="/org/gnome/shell">
|
||||||
|
+ <file>gdm/authList.js</file>
|
||||||
|
<file>gdm/authPrompt.js</file>
|
||||||
|
<file>gdm/batch.js</file>
|
||||||
|
<file>gdm/fingerprint.js</file>
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -1,51 +0,0 @@
|
|||||||
From eea9b9a0dac494698a64892bab8d042e7d623c9f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Cenk Uluisik <cenk.uluisik@googlemail.com>
|
|
||||||
Date: Sun, 6 Mar 2022 19:32:48 +0100
|
|
||||||
Subject: [PATCH] introspect: Add WindowsChanged signal
|
|
||||||
|
|
||||||
The screencast portal supports recording a single window,
|
|
||||||
and presents a list of open windows when that option is
|
|
||||||
selected. To allow updating that list when windows are
|
|
||||||
opened or closed, add a new "WindowsChanged" signal that
|
|
||||||
the portal can listen to.
|
|
||||||
|
|
||||||
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2229>
|
|
||||||
---
|
|
||||||
data/dbus-interfaces/org.gnome.Shell.Introspect.xml | 6 ++++++
|
|
||||||
js/misc/introspect.js | 3 +++
|
|
||||||
2 files changed, 9 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/data/dbus-interfaces/org.gnome.Shell.Introspect.xml b/data/dbus-interfaces/org.gnome.Shell.Introspect.xml
|
|
||||||
index 47fd7efdc2..cb19cfec56 100644
|
|
||||||
--- a/data/dbus-interfaces/org.gnome.Shell.Introspect.xml
|
|
||||||
+++ b/data/dbus-interfaces/org.gnome.Shell.Introspect.xml
|
|
||||||
@@ -18,6 +18,12 @@
|
|
||||||
-->
|
|
||||||
<signal name="RunningApplicationsChanged" />
|
|
||||||
|
|
||||||
+ <!--
|
|
||||||
+ WindowsChanged:
|
|
||||||
+ @short_description: Notifies when any window opens or closes
|
|
||||||
+ -->
|
|
||||||
+ <signal name="WindowsChanged" />
|
|
||||||
+
|
|
||||||
<!--
|
|
||||||
GetRunningApplications:
|
|
||||||
@short_description: Retrieves the description of all running applications
|
|
||||||
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
|
|
||||||
index 45eee81ce3..8916804e7f 100644
|
|
||||||
--- a/js/misc/introspect.js
|
|
||||||
+++ b/js/misc/introspect.js
|
|
||||||
@@ -42,6 +42,9 @@ var IntrospectService = class {
|
|
||||||
this._syncRunningApplications();
|
|
||||||
});
|
|
||||||
|
|
||||||
+ tracker.connect('tracked-windows-changed',
|
|
||||||
+ () => this._dbusImpl.emit_signal('WindowsChanged', null));
|
|
||||||
+
|
|
||||||
this._syncRunningApplications();
|
|
||||||
|
|
||||||
this._senderChecker = new DBusSenderChecker(APP_ALLOWLIST);
|
|
||||||
--
|
|
||||||
2.38.1
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
|||||||
From b73a07c20a522b3be0e096625c21d5606bcb7d82 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
||||||
Date: Mon, 21 Jun 2021 16:32:50 -0300
|
|
||||||
Subject: [PATCH] introspect: Allowlist GNOME portal
|
|
||||||
|
|
||||||
It too implements app listing and introspection, so list it in the
|
|
||||||
allowlist.
|
|
||||||
|
|
||||||
Part-of:
|
|
||||||
<https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1894>
|
|
||||||
---
|
|
||||||
js/misc/introspect.js | 5 ++++-
|
|
||||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
|
|
||||||
index f3c938af9..45eee81ce 100644
|
|
||||||
--- a/js/misc/introspect.js
|
|
||||||
+++ b/js/misc/introspect.js
|
|
||||||
@@ -1,7 +1,10 @@
|
|
||||||
/* exported IntrospectService */
|
|
||||||
const { Gio, GLib, Meta, Shell, St } = imports.gi;
|
|
||||||
|
|
||||||
-const APP_ALLOWLIST = ['org.freedesktop.impl.portal.desktop.gtk'];
|
|
||||||
+const APP_ALLOWLIST = [
|
|
||||||
+ 'org.freedesktop.impl.portal.desktop.gtk',
|
|
||||||
+ 'org.freedesktop.impl.portal.desktop.gnome',
|
|
||||||
+];
|
|
||||||
|
|
||||||
const INTROSPECT_DBUS_API_VERSION = 3;
|
|
||||||
|
|
||||||
--
|
|
||||||
2.38.1
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
|||||||
From bd4fef8354ff0730c1e96a47d77adbb4a4d7beaa Mon Sep 17 00:00:00 2001
|
|
||||||
From: Olivier Fourdan <ofourdan@redhat.com>
|
|
||||||
Date: Tue, 14 Jun 2022 16:38:27 +0200
|
|
||||||
Subject: [PATCH] kbdA11yDialog: Use MetaKeyboardA11yFlags
|
|
||||||
|
|
||||||
The change in mutter to move keyboard accessibility into backends needs
|
|
||||||
to be applied in gnome-shell as well, otherwise the keyboard
|
|
||||||
accessibility dialog cannot work.
|
|
||||||
|
|
||||||
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2306
|
|
||||||
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2334>
|
|
||||||
---
|
|
||||||
js/ui/kbdA11yDialog.js | 10 +++++-----
|
|
||||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/js/ui/kbdA11yDialog.js b/js/ui/kbdA11yDialog.js
|
|
||||||
index a45e02443..60ec161a6 100644
|
|
||||||
--- a/js/ui/kbdA11yDialog.js
|
|
||||||
+++ b/js/ui/kbdA11yDialog.js
|
|
||||||
@@ -1,5 +1,5 @@
|
|
||||||
/* exported KbdA11yDialog */
|
|
||||||
-const { Clutter, Gio, GObject } = imports.gi;
|
|
||||||
+const { Clutter, Gio, GObject, Meta } = imports.gi;
|
|
||||||
|
|
||||||
const Dialog = imports.ui.dialog;
|
|
||||||
const ModalDialog = imports.ui.modalDialog;
|
|
||||||
@@ -25,17 +25,17 @@ class KbdA11yDialog extends GObject.Object {
|
|
||||||
let title, description;
|
|
||||||
let key, enabled;
|
|
||||||
|
|
||||||
- if (whatChanged & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) {
|
|
||||||
+ if (whatChanged & Meta.KeyboardA11yFlags.SLOW_KEYS_ENABLED) {
|
|
||||||
key = KEY_SLOW_KEYS_ENABLED;
|
|
||||||
- enabled = (newFlags & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) > 0;
|
|
||||||
+ enabled = (newFlags & Meta.KeyboardA11yFlags.SLOW_KEYS_ENABLED) > 0;
|
|
||||||
title = enabled
|
|
||||||
? _("Slow Keys Turned On")
|
|
||||||
: _("Slow Keys Turned Off");
|
|
||||||
description = _('You just held down the Shift key for 8 seconds. This is the shortcut ' +
|
|
||||||
'for the Slow Keys feature, which affects the way your keyboard works.');
|
|
||||||
- } else if (whatChanged & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) {
|
|
||||||
+ } else if (whatChanged & Meta.KeyboardA11yFlags.STICKY_KEYS_ENABLED) {
|
|
||||||
key = KEY_STICKY_KEYS_ENABLED;
|
|
||||||
- enabled = (newFlags & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) > 0;
|
|
||||||
+ enabled = (newFlags & Meta.KeyboardA11yFlags.STICKY_KEYS_ENABLED) > 0;
|
|
||||||
title = enabled
|
|
||||||
? _("Sticky Keys Turned On")
|
|
||||||
: _("Sticky Keys Turned Off");
|
|
||||||
--
|
|
||||||
2.36.1
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
|||||||
|
From 2acede02f30833c3fb891db8483f933f7b41508c Mon Sep 17 00:00:00 2001
|
||||||
|
From: rpm-build <rpm-build>
|
||||||
|
Date: Wed, 21 Oct 2020 21:32:03 +0200
|
||||||
|
Subject: [PATCH] keyboard: Only enable keyboard if
|
||||||
|
ClutterDeviceManager::touch-mode is enabled
|
||||||
|
|
||||||
|
---
|
||||||
|
js/ui/keyboard.js | 7 ++++++-
|
||||||
|
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js
|
||||||
|
index 94b5325..b1ee270 100644
|
||||||
|
--- a/js/ui/keyboard.js
|
||||||
|
+++ b/js/ui/keyboard.js
|
||||||
|
@@ -1051,6 +1051,9 @@ var Keyboard = class Keyboard {
|
||||||
|
this._suggestions = null;
|
||||||
|
this._emojiKeyVisible = true;
|
||||||
|
|
||||||
|
+ let manager = Clutter.DeviceManager.get_default();
|
||||||
|
+ manager.connect('notify::touch-mode', this._syncEnabled.bind(this));
|
||||||
|
+
|
||||||
|
this._focusTracker = new FocusTracker();
|
||||||
|
this._focusTracker.connect('position-changed', this._onFocusPositionChanged.bind(this));
|
||||||
|
this._focusTracker.connect('reset', () => {
|
||||||
|
@@ -1120,8 +1123,10 @@ var Keyboard = class Keyboard {
|
||||||
|
|
||||||
|
_syncEnabled() {
|
||||||
|
let wasEnabled = this._enabled;
|
||||||
|
+ let manager = Clutter.DeviceManager.get_default();
|
||||||
|
+ let autoEnabled = manager.get_touch_mode() && this._lastDeviceIsTouchscreen();
|
||||||
|
this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD);
|
||||||
|
- this._enabled = this._enableKeyboard || this._lastDeviceIsTouchscreen();
|
||||||
|
+ this._enabled = this._enableKeyboard || autoEnabled;
|
||||||
|
if (!this._enabled && !this._keyboardController)
|
||||||
|
return;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -0,0 +1,56 @@
|
|||||||
|
From 35cbad572120125d3b823f37d2100b2beee4c1d8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Thu, 8 Jun 2017 17:07:56 +0200
|
||||||
|
Subject: [PATCH] layout: Make the hot corner optional
|
||||||
|
|
||||||
|
Whether people love or hate the hot corner depends in large extents
|
||||||
|
on hardware sensitivity and habits, which is hard to get right
|
||||||
|
universally. So bite the bullet and support an option to enable or
|
||||||
|
disable hot corners ...
|
||||||
|
|
||||||
|
https://bugzilla.gnome.org/show_bug.cgi?id=688320
|
||||||
|
---
|
||||||
|
js/ui/layout.js | 14 +++++++++++++-
|
||||||
|
1 file changed, 13 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/layout.js b/js/ui/layout.js
|
||||||
|
index 2b3bb7442..beb4c0a5d 100644
|
||||||
|
--- a/js/ui/layout.js
|
||||||
|
+++ b/js/ui/layout.js
|
||||||
|
@@ -1,6 +1,6 @@
|
||||||
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||||
|
|
||||||
|
-const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
|
||||||
|
+const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
|
||||||
|
const Background = imports.ui.background;
|
||||||
|
@@ -267,6 +267,13 @@ var LayoutManager = GObject.registerClass({
|
||||||
|
this._backgroundGroup.lower_bottom();
|
||||||
|
this._bgManagers = [];
|
||||||
|
|
||||||
|
+ this._interfaceSettings = new Gio.Settings({
|
||||||
|
+ schema_id: 'org.gnome.desktop.interface'
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ this._interfaceSettings.connect('changed::enable-hot-corners',
|
||||||
|
+ this._updateHotCorners.bind(this));
|
||||||
|
+
|
||||||
|
// Need to update struts on new workspaces when they are added
|
||||||
|
let workspaceManager = global.workspace_manager;
|
||||||
|
workspaceManager.connect('notify::n-workspaces',
|
||||||
|
@@ -358,6 +365,11 @@ var LayoutManager = GObject.registerClass({
|
||||||
|
});
|
||||||
|
this.hotCorners = [];
|
||||||
|
|
||||||
|
+ if (!this._interfaceSettings.get_boolean('enable-hot-corners')) {
|
||||||
|
+ this.emit('hot-corners-changed');
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
let size = this.panelBox.height;
|
||||||
|
|
||||||
|
// build new hot corners
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
From 6d26b6f9f66e14843f175305441a2464dd255fd1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Mon, 27 Jul 2020 10:58:49 -0400
|
||||||
|
Subject: [PATCH] loginDialog: Reset auth prompt on vt switch before fade in
|
||||||
|
|
||||||
|
At the moment, if a user switches to the login screen vt,
|
||||||
|
the login screen fades in whatever was on screen prior, and
|
||||||
|
then does a reset.
|
||||||
|
|
||||||
|
It makes more sense to reset first, so we fade in what the
|
||||||
|
user is going to interact with instead of what they interacted
|
||||||
|
with before.
|
||||||
|
|
||||||
|
Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2997
|
||||||
|
---
|
||||||
|
js/gdm/loginDialog.js | 10 ++++------
|
||||||
|
1 file changed, 4 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
|
||||||
|
index 214c2f512..eb6846d5c 100644
|
||||||
|
--- a/js/gdm/loginDialog.js
|
||||||
|
+++ b/js/gdm/loginDialog.js
|
||||||
|
@@ -923,6 +923,9 @@ var LoginDialog = GObject.registerClass({
|
||||||
|
if (this.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
|
||||||
|
return;
|
||||||
|
|
||||||
|
+ if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
|
||||||
|
+ this._authPrompt.reset();
|
||||||
|
+
|
||||||
|
Tweener.addTween(this,
|
||||||
|
{ opacity: 255,
|
||||||
|
time: _FADE_ANIMATION_TIME,
|
||||||
|
@@ -935,12 +938,7 @@ var LoginDialog = GObject.registerClass({
|
||||||
|
children[i].opacity = this.opacity;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
- onUpdateScope: this,
|
||||||
|
- onComplete() {
|
||||||
|
- if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
|
||||||
|
- this._authPrompt.reset();
|
||||||
|
- },
|
||||||
|
- onCompleteScope: this });
|
||||||
|
+ onUpdateScope: this });
|
||||||
|
}
|
||||||
|
|
||||||
|
_gotGreeterSessionProxy(proxy) {
|
||||||
|
--
|
||||||
|
2.32.0
|
||||||
|
|
@ -1,148 +0,0 @@
|
|||||||
From ea7e7acd45e428cc17306de2bf65730c90d7e118 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Sebastian Keller <skeller@gnome.org>
|
|
||||||
Date: Mon, 23 May 2022 23:01:23 +0200
|
|
||||||
Subject: [PATCH] magnifier: Request window-relative coordinates for
|
|
||||||
focus/caret events
|
|
||||||
|
|
||||||
Absolute screen coordinates are impossible for Wayland clients to
|
|
||||||
provide, because the clients don't know where the window is positioned.
|
|
||||||
Some clients, such as the ones using GTK 3 were providing window
|
|
||||||
relative coordinates even when screen coordinates were requested,
|
|
||||||
while others, such as GTK 4 clients, were just returning an error for
|
|
||||||
caret events or also window-relative coordinates for focus events.
|
|
||||||
|
|
||||||
So for this to work on Wayland we have to request window-relative
|
|
||||||
coordinates and translate them to the current focus window.
|
|
||||||
|
|
||||||
To ensure the correct coordinates, we have to only consider events
|
|
||||||
coming from the current focus window. All other events are filtered out
|
|
||||||
now. As a side effect this also fixes the magnifier always jumping
|
|
||||||
to a terminal cursor whenever there was some output, even if the window
|
|
||||||
was not focused.
|
|
||||||
|
|
||||||
This also needs some special handling for events coming from the shell
|
|
||||||
itself, which should not be translated to the focus window either. As
|
|
||||||
another side effect this fixes another bug that was caused by these
|
|
||||||
events already including scaling and getting scaled again.
|
|
||||||
|
|
||||||
Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5509
|
|
||||||
Part-of:
|
|
||||||
<https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2301>
|
|
||||||
---
|
|
||||||
js/ui/magnifier.js | 77 +++++++++++++++++++++++++++++++++++++++++-----
|
|
||||||
1 file changed, 70 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/js/ui/magnifier.js b/js/ui/magnifier.js
|
|
||||||
index 4c2e88f1a..9813664be 100644
|
|
||||||
--- a/js/ui/magnifier.js
|
|
||||||
+++ b/js/ui/magnifier.js
|
|
||||||
@@ -789,21 +789,81 @@ var ZoomRegion = class ZoomRegion {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ _convertExtentsToScreenSpace(accessible, extents) {
|
|
||||||
+ const toplevelWindowTypes = new Set([
|
|
||||||
+ Atspi.Role.FRAME,
|
|
||||||
+ Atspi.Role.DIALOG,
|
|
||||||
+ Atspi.Role.WINDOW,
|
|
||||||
+ ]);
|
|
||||||
+
|
|
||||||
+ try {
|
|
||||||
+ let app = null;
|
|
||||||
+ let parentWindow = null;
|
|
||||||
+ let iter = accessible;
|
|
||||||
+ while (iter) {
|
|
||||||
+ if (iter.get_role() === Atspi.Role.APPLICATION) {
|
|
||||||
+ app = iter;
|
|
||||||
+ /* This is the last Accessible we are interested in */
|
|
||||||
+ break;
|
|
||||||
+ } else if (toplevelWindowTypes.has(iter.get_role())) {
|
|
||||||
+ parentWindow = iter;
|
|
||||||
+ }
|
|
||||||
+ iter = iter.get_parent();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* We don't want to translate our own events to the focus window.
|
|
||||||
+ * They are also already scaled by clutter before being sent, so
|
|
||||||
+ * we don't need to do that here either. */
|
|
||||||
+ if (app && app.get_name() === 'gnome-shell')
|
|
||||||
+ return extents;
|
|
||||||
+
|
|
||||||
+ /* Only events from the focused widget of the focused window. Some
|
|
||||||
+ * widgets seem to claim to have focus when the window does not so
|
|
||||||
+ * check both. */
|
|
||||||
+ const windowActive = parentWindow &&
|
|
||||||
+ parentWindow.get_state_set().contains(Atspi.StateType.ACTIVE);
|
|
||||||
+ const accessibleFocused =
|
|
||||||
+ accessible.get_state_set().contains(Atspi.StateType.FOCUSED);
|
|
||||||
+ if (!windowActive || !accessibleFocused)
|
|
||||||
+ return null;
|
|
||||||
+ } catch (e) {
|
|
||||||
+ throw new Error(`Failed to validate parent window: ${e}`);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ const focusWindowRect = global.display.focus_window?.get_frame_rect();
|
|
||||||
+ if (!focusWindowRect)
|
|
||||||
+ return null;
|
|
||||||
+
|
|
||||||
+ const scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
|
||||||
+ const screenSpaceExtents = new Atspi.Rect({
|
|
||||||
+ x: focusWindowRect.x + (scaleFactor * extents.x),
|
|
||||||
+ y: focusWindowRect.y + (scaleFactor * extents.y),
|
|
||||||
+ width: scaleFactor * extents.width,
|
|
||||||
+ height: scaleFactor * extents.height,
|
|
||||||
+ });
|
|
||||||
+
|
|
||||||
+ return screenSpaceExtents;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
_updateFocus(caller, event) {
|
|
||||||
let component = event.source.get_component_iface();
|
|
||||||
if (!component || event.detail1 != 1)
|
|
||||||
return;
|
|
||||||
let extents;
|
|
||||||
try {
|
|
||||||
- extents = component.get_extents(Atspi.CoordType.SCREEN);
|
|
||||||
+ extents = component.get_extents(Atspi.CoordType.WINDOW);
|
|
||||||
+ extents = this._convertExtentsToScreenSpace(event.source, extents);
|
|
||||||
+ if (!extents)
|
|
||||||
+ return;
|
|
||||||
} catch (e) {
|
|
||||||
log(`Failed to read extents of focused component: ${e.message}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
- let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
|
||||||
- let [xFocus, yFocus] = [(extents.x + (extents.width / 2)) * scaleFactor,
|
|
||||||
- (extents.y + (extents.height / 2)) * scaleFactor];
|
|
||||||
+ const [xFocus, yFocus] = [
|
|
||||||
+ extents.x + (extents.width / 2),
|
|
||||||
+ extents.y + (extents.height / 2),
|
|
||||||
+ ];
|
|
||||||
|
|
||||||
if (this._xFocus !== xFocus || this._yFocus !== yFocus) {
|
|
||||||
[this._xFocus, this._yFocus] = [xFocus, yFocus];
|
|
||||||
@@ -817,14 +877,17 @@ var ZoomRegion = class ZoomRegion {
|
|
||||||
return;
|
|
||||||
let extents;
|
|
||||||
try {
|
|
||||||
- extents = text.get_character_extents(text.get_caret_offset(), 0);
|
|
||||||
+ extents = text.get_character_extents(text.get_caret_offset(),
|
|
||||||
+ Atspi.CoordType.WINDOW);
|
|
||||||
+ extents = this._convertExtentsToScreenSpace(text, extents);
|
|
||||||
+ if (!extents)
|
|
||||||
+ return;
|
|
||||||
} catch (e) {
|
|
||||||
log(`Failed to read extents of text caret: ${e.message}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
- let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
|
||||||
- let [xCaret, yCaret] = [extents.x * scaleFactor, extents.y * scaleFactor];
|
|
||||||
+ const [xCaret, yCaret] = [extents.x, extents.y];
|
|
||||||
|
|
||||||
// Ignore event(s) if the caret size is none (0x0). This happens a lot if
|
|
||||||
// the cursor offset can't be translated into a location. This is a work
|
|
||||||
--
|
|
||||||
2.38.1
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
|||||||
From a9e79b1657dc7c1b702d7acc4d322539d2b8b6aa Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
||||||
Date: Wed, 6 Oct 2021 10:00:43 +0200
|
|
||||||
Subject: [PATCH] main: Leak the GJS context and ShellGlobal
|
|
||||||
|
|
||||||
There are many crash-on-exit happening as a side effect of destroying
|
|
||||||
the GJS context. Work around these until we have a better solution by
|
|
||||||
leaking them.
|
|
||||||
---
|
|
||||||
src/main.c | 2 ++
|
|
||||||
1 file changed, 2 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/src/main.c b/src/main.c
|
|
||||||
index 91e5493fd1..d62dda9627 100644
|
|
||||||
--- a/src/main.c
|
|
||||||
+++ b/src/main.c
|
|
||||||
@@ -508,9 +508,11 @@ main (int argc, char **argv)
|
|
||||||
ecode = meta_run ();
|
|
||||||
shell_profiler_shutdown ();
|
|
||||||
|
|
||||||
+#if 0
|
|
||||||
g_debug ("Doing final cleanup");
|
|
||||||
_shell_global_destroy_gjs_context (shell_global_get ());
|
|
||||||
g_object_unref (shell_global_get ());
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
return ecode;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.31.1
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
From 0d95c2087aba7f0b07cb303c1f15d097b45f1b09 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
|
||||||
|
Date: Tue, 28 Apr 2020 23:26:11 +0200
|
||||||
|
Subject: [PATCH] main: Unset the right prevFocus actor after the focus stack
|
||||||
|
got shifted
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
When a modal that's not on top of the modalActorFocusStack gets popped,
|
||||||
|
we shift the focus stack as described in popModal() to ensure the chain
|
||||||
|
remains correct. That however destroys the association of a modal actor
|
||||||
|
and its prevFocus actor on the focus stack, because the prevFocus actors
|
||||||
|
are now moved to different entries of the stack.
|
||||||
|
|
||||||
|
Now when a prevFocus actor gets destroyed, we don't handle that case
|
||||||
|
correctly and search for the modal actor that was associated with the
|
||||||
|
prevFocus actor before the stack was shifted, which means we end up
|
||||||
|
unsetting the wrong prevFocus actor.
|
||||||
|
|
||||||
|
So fix that and search the stack for the prevFocus actor which is being
|
||||||
|
destroyed instead to unset the correct entry.
|
||||||
|
|
||||||
|
Thanks to Florian Müllner for figuring out the actual issue and
|
||||||
|
proposing this fix.
|
||||||
|
|
||||||
|
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2446
|
||||||
|
---
|
||||||
|
js/ui/main.js | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/main.js b/js/ui/main.js
|
||||||
|
index dd1d8463d..ca3dcaa3c 100644
|
||||||
|
--- a/js/ui/main.js
|
||||||
|
+++ b/js/ui/main.js
|
||||||
|
@@ -486,7 +486,9 @@ function pushModal(actor, params) {
|
||||||
|
let prevFocusDestroyId;
|
||||||
|
if (prevFocus != null) {
|
||||||
|
prevFocusDestroyId = prevFocus.connect('destroy', () => {
|
||||||
|
- let index = _findModal(actor);
|
||||||
|
+ const index = modalActorFocusStack.findIndex(
|
||||||
|
+ record => record.prevFocus === prevFocus);
|
||||||
|
+
|
||||||
|
if (index >= 0)
|
||||||
|
modalActorFocusStack[index].prevFocus = null;
|
||||||
|
});
|
||||||
|
--
|
||||||
|
2.35.1
|
||||||
|
|
@ -0,0 +1,29 @@
|
|||||||
|
From bd4a3186dc21f2c8d3e0f851cf262a34ddb6b625 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lubomir Rintel <lkundrak@v3.sk>
|
||||||
|
Date: Fri, 4 Oct 2019 14:21:25 +0200
|
||||||
|
Subject: [PATCH] networkAgent: add support for SAE secrets
|
||||||
|
|
||||||
|
NetworkManager supports "WPA3 Personal" networks for some time now, they
|
||||||
|
use the SAE authentication. Add support for it alongside other
|
||||||
|
password-based mechanisms.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/751
|
||||||
|
---
|
||||||
|
js/ui/components/networkAgent.js | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/js/ui/components/networkAgent.js b/js/ui/components/networkAgent.js
|
||||||
|
index 32d40fb2b..3ff957bf6 100644
|
||||||
|
--- a/js/ui/components/networkAgent.js
|
||||||
|
+++ b/js/ui/components/networkAgent.js
|
||||||
|
@@ -216,6 +216,7 @@ var NetworkSecretDialog = class extends ModalDialog.ModalDialog {
|
||||||
|
// First the easy ones
|
||||||
|
case 'wpa-none':
|
||||||
|
case 'wpa-psk':
|
||||||
|
+ case 'sae':
|
||||||
|
secrets.push({ label: _("Password: "), key: 'psk',
|
||||||
|
value: wirelessSecuritySetting.psk || '',
|
||||||
|
validate: this._validateWpaPsk, password: true });
|
||||||
|
--
|
||||||
|
2.32.0
|
||||||
|
|
@ -1,281 +0,0 @@
|
|||||||
From be3a2303cf9ed4077955aaa9fae1fc4cbe2da277 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
||||||
Date: Tue, 24 Jan 2023 17:49:24 +0100
|
|
||||||
Subject: [PATCH] =?UTF-8?q?osk-layouts:=20Replace=20"SS"=20extra=20key=20w?=
|
|
||||||
=?UTF-8?q?ith=20"=E1=BA=9E"?=
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
The on-screen keyboard only handles a single keyval per key, so the
|
|
||||||
current upper-case version of the German "ß" ends up as "S" instead
|
|
||||||
of the expected "SS".
|
|
||||||
|
|
||||||
It is possible to change the keyboard code to emulate multiple key
|
|
||||||
presses/releases for that particular case, but then luckily a proper
|
|
||||||
upper-case form exists nowadays: "ẞ".
|
|
||||||
|
|
||||||
That seems more appropriate for a single key than a dedicated "SS"
|
|
||||||
key, so replace it in all layouts that include it. Anybody who prefers
|
|
||||||
the traditional "SS" can easily tap "S" twice.
|
|
||||||
|
|
||||||
Part-of:
|
|
||||||
<https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2612>
|
|
||||||
---
|
|
||||||
data/osk-layouts/cz.json | 2 +-
|
|
||||||
data/osk-layouts/de.json | 2 +-
|
|
||||||
data/osk-layouts/dk.json | 2 +-
|
|
||||||
data/osk-layouts/ee.json | 2 +-
|
|
||||||
data/osk-layouts/epo.json | 2 +-
|
|
||||||
data/osk-layouts/fi.json | 2 +-
|
|
||||||
data/osk-layouts/hr.json | 2 +-
|
|
||||||
data/osk-layouts/ke.json | 2 +-
|
|
||||||
data/osk-layouts/lt.json | 2 +-
|
|
||||||
data/osk-layouts/lv.json | 2 +-
|
|
||||||
data/osk-layouts/no.json | 2 +-
|
|
||||||
data/osk-layouts/pl.json | 2 +-
|
|
||||||
data/osk-layouts/ro.json | 2 +-
|
|
||||||
data/osk-layouts/se.json | 2 +-
|
|
||||||
data/osk-layouts/sk.json | 2 +-
|
|
||||||
data/osk-layouts/tr.json | 2 +-
|
|
||||||
data/osk-layouts/uk.json | 2 +-
|
|
||||||
data/osk-layouts/us.json | 2 +-
|
|
||||||
18 files changed, 18 insertions(+), 18 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/data/osk-layouts/cz.json b/data/osk-layouts/cz.json
|
|
||||||
index 9bad07402..526cb9cb6 100644
|
|
||||||
--- a/data/osk-layouts/cz.json
|
|
||||||
+++ b/data/osk-layouts/cz.json
|
|
||||||
@@ -246,7 +246,7 @@
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
"Š",
|
|
||||||
- "SS",
|
|
||||||
+ "ẞ",
|
|
||||||
"Ś"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
diff --git a/data/osk-layouts/de.json b/data/osk-layouts/de.json
|
|
||||||
index 751a85603..3b1cb34b2 100644
|
|
||||||
--- a/data/osk-layouts/de.json
|
|
||||||
+++ b/data/osk-layouts/de.json
|
|
||||||
@@ -208,7 +208,7 @@
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
- "SS",
|
|
||||||
+ "ẞ",
|
|
||||||
"Ś",
|
|
||||||
"Š"
|
|
||||||
],
|
|
||||||
diff --git a/data/osk-layouts/dk.json b/data/osk-layouts/dk.json
|
|
||||||
index 80df9ae65..7bc6feaf3 100644
|
|
||||||
--- a/data/osk-layouts/dk.json
|
|
||||||
+++ b/data/osk-layouts/dk.json
|
|
||||||
@@ -218,7 +218,7 @@
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
- "SS",
|
|
||||||
+ "ẞ",
|
|
||||||
"Ś",
|
|
||||||
"Š"
|
|
||||||
],
|
|
||||||
diff --git a/data/osk-layouts/ee.json b/data/osk-layouts/ee.json
|
|
||||||
index 5fd2f11fa..b42b0afc9 100644
|
|
||||||
--- a/data/osk-layouts/ee.json
|
|
||||||
+++ b/data/osk-layouts/ee.json
|
|
||||||
@@ -281,7 +281,7 @@
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
"Š",
|
|
||||||
- "SS",
|
|
||||||
+ "ẞ",
|
|
||||||
"Ś",
|
|
||||||
"Ş"
|
|
||||||
],
|
|
||||||
diff --git a/data/osk-layouts/epo.json b/data/osk-layouts/epo.json
|
|
||||||
index 71f9ef8d9..d7257625f 100644
|
|
||||||
--- a/data/osk-layouts/epo.json
|
|
||||||
+++ b/data/osk-layouts/epo.json
|
|
||||||
@@ -316,7 +316,7 @@
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
- "SS",
|
|
||||||
+ "ẞ",
|
|
||||||
"Š",
|
|
||||||
"Ś",
|
|
||||||
"Ș",
|
|
||||||
diff --git a/data/osk-layouts/fi.json b/data/osk-layouts/fi.json
|
|
||||||
index 3ba5b567c..d664b0ec5 100644
|
|
||||||
--- a/data/osk-layouts/fi.json
|
|
||||||
+++ b/data/osk-layouts/fi.json
|
|
||||||
@@ -200,7 +200,7 @@
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
"Š",
|
|
||||||
- "SS",
|
|
||||||
+ "ẞ",
|
|
||||||
"Ś"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
diff --git a/data/osk-layouts/hr.json b/data/osk-layouts/hr.json
|
|
||||||
index ff0d1d09a..e4977796a 100644
|
|
||||||
--- a/data/osk-layouts/hr.json
|
|
||||||
+++ b/data/osk-layouts/hr.json
|
|
||||||
@@ -168,7 +168,7 @@
|
|
||||||
"S",
|
|
||||||
"Š",
|
|
||||||
"Ś",
|
|
||||||
- "SS"
|
|
||||||
+ "ẞ"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"D",
|
|
||||||
diff --git a/data/osk-layouts/ke.json b/data/osk-layouts/ke.json
|
|
||||||
index 9c3e93565..2bd5b09d0 100644
|
|
||||||
--- a/data/osk-layouts/ke.json
|
|
||||||
+++ b/data/osk-layouts/ke.json
|
|
||||||
@@ -217,7 +217,7 @@
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
- "SS"
|
|
||||||
+ "ẞ"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"D"
|
|
||||||
diff --git a/data/osk-layouts/lt.json b/data/osk-layouts/lt.json
|
|
||||||
index 7cd5352a8..a43ff9146 100644
|
|
||||||
--- a/data/osk-layouts/lt.json
|
|
||||||
+++ b/data/osk-layouts/lt.json
|
|
||||||
@@ -270,7 +270,7 @@
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
"Š",
|
|
||||||
- "SS",
|
|
||||||
+ "ẞ",
|
|
||||||
"Ś",
|
|
||||||
"Ş"
|
|
||||||
],
|
|
||||||
diff --git a/data/osk-layouts/lv.json b/data/osk-layouts/lv.json
|
|
||||||
index bab6ae3d7..d72c93c25 100644
|
|
||||||
--- a/data/osk-layouts/lv.json
|
|
||||||
+++ b/data/osk-layouts/lv.json
|
|
||||||
@@ -268,7 +268,7 @@
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
"Š",
|
|
||||||
- "SS",
|
|
||||||
+ "ẞ",
|
|
||||||
"Ś",
|
|
||||||
"Ş"
|
|
||||||
],
|
|
||||||
diff --git a/data/osk-layouts/no.json b/data/osk-layouts/no.json
|
|
||||||
index a70be9ca0..0df786853 100644
|
|
||||||
--- a/data/osk-layouts/no.json
|
|
||||||
+++ b/data/osk-layouts/no.json
|
|
||||||
@@ -218,7 +218,7 @@
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
- "SS",
|
|
||||||
+ "ẞ",
|
|
||||||
"Ś",
|
|
||||||
"Š"
|
|
||||||
],
|
|
||||||
diff --git a/data/osk-layouts/pl.json b/data/osk-layouts/pl.json
|
|
||||||
index 4b08cd5d3..8583bd64c 100644
|
|
||||||
--- a/data/osk-layouts/pl.json
|
|
||||||
+++ b/data/osk-layouts/pl.json
|
|
||||||
@@ -212,7 +212,7 @@
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
"Ś",
|
|
||||||
- "SS",
|
|
||||||
+ "ẞ",
|
|
||||||
"Š"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
diff --git a/data/osk-layouts/ro.json b/data/osk-layouts/ro.json
|
|
||||||
index c690f4ecd..8d4676126 100644
|
|
||||||
--- a/data/osk-layouts/ro.json
|
|
||||||
+++ b/data/osk-layouts/ro.json
|
|
||||||
@@ -188,7 +188,7 @@
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
"Ș",
|
|
||||||
- "SS",
|
|
||||||
+ "ẞ",
|
|
||||||
"Ś",
|
|
||||||
"Š"
|
|
||||||
],
|
|
||||||
diff --git a/data/osk-layouts/se.json b/data/osk-layouts/se.json
|
|
||||||
index 513a0b897..0ebb756e7 100644
|
|
||||||
--- a/data/osk-layouts/se.json
|
|
||||||
+++ b/data/osk-layouts/se.json
|
|
||||||
@@ -245,7 +245,7 @@
|
|
||||||
"Ś",
|
|
||||||
"Š",
|
|
||||||
"Ş",
|
|
||||||
- "SS"
|
|
||||||
+ "ẞ"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"D",
|
|
||||||
diff --git a/data/osk-layouts/sk.json b/data/osk-layouts/sk.json
|
|
||||||
index 678232b82..a74ad0b61 100644
|
|
||||||
--- a/data/osk-layouts/sk.json
|
|
||||||
+++ b/data/osk-layouts/sk.json
|
|
||||||
@@ -269,7 +269,7 @@
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
"Š",
|
|
||||||
- "SS",
|
|
||||||
+ "ẞ",
|
|
||||||
"Ś",
|
|
||||||
"Ş"
|
|
||||||
],
|
|
||||||
diff --git a/data/osk-layouts/tr.json b/data/osk-layouts/tr.json
|
|
||||||
index b3786cc88..8243aafad 100644
|
|
||||||
--- a/data/osk-layouts/tr.json
|
|
||||||
+++ b/data/osk-layouts/tr.json
|
|
||||||
@@ -202,7 +202,7 @@
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
"Ş",
|
|
||||||
- "SS",
|
|
||||||
+ "ẞ",
|
|
||||||
"Ś",
|
|
||||||
"Š"
|
|
||||||
],
|
|
||||||
diff --git a/data/osk-layouts/uk.json b/data/osk-layouts/uk.json
|
|
||||||
index c36a723a0..19f5aa6d9 100644
|
|
||||||
--- a/data/osk-layouts/uk.json
|
|
||||||
+++ b/data/osk-layouts/uk.json
|
|
||||||
@@ -216,7 +216,7 @@
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
- "SS"
|
|
||||||
+ "ẞ"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"D"
|
|
||||||
diff --git a/data/osk-layouts/us.json b/data/osk-layouts/us.json
|
|
||||||
index 94dd6d3ad..dd0cd368f 100644
|
|
||||||
--- a/data/osk-layouts/us.json
|
|
||||||
+++ b/data/osk-layouts/us.json
|
|
||||||
@@ -216,7 +216,7 @@
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"S",
|
|
||||||
- "SS"
|
|
||||||
+ "ẞ"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"D"
|
|
||||||
--
|
|
||||||
2.38.1
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
|||||||
|
From 2ddb51234ca69c0e637b35071b4e760d1b72527a Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
|
||||||
|
Date: Mon, 24 Feb 2020 11:19:28 +0100
|
||||||
|
Subject: [PATCH] overview: Hide the overview on session mode hasOverview
|
||||||
|
changes
|
||||||
|
|
||||||
|
If the sessionMode does not allow to show the overview, we should also
|
||||||
|
hide an already visible overview.
|
||||||
|
|
||||||
|
This fixes a bug where, if the lockscreen was shown while the overview
|
||||||
|
was visible, the Ctrl+Alt+Tab popup would allow navigating inside the
|
||||||
|
overview because the overview actor is still mapped.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1043
|
||||||
|
---
|
||||||
|
js/ui/overview.js | 6 +++++-
|
||||||
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/overview.js b/js/ui/overview.js
|
||||||
|
index 5bad4cbd62..03cecb6dbc 100644
|
||||||
|
--- a/js/ui/overview.js
|
||||||
|
+++ b/js/ui/overview.js
|
||||||
|
@@ -196,7 +196,11 @@ var Overview = class {
|
||||||
|
}
|
||||||
|
|
||||||
|
_sessionUpdated() {
|
||||||
|
- this.isDummy = !Main.sessionMode.hasOverview;
|
||||||
|
+ const { hasOverview } = Main.sessionMode;
|
||||||
|
+ if (!hasOverview)
|
||||||
|
+ this.hide();
|
||||||
|
+
|
||||||
|
+ this.isDummy = !hasOverview;
|
||||||
|
this._createOverview();
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -0,0 +1,80 @@
|
|||||||
|
From 2bb826291c420dd1b601758c7a686ac48e1086a6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Carlos Garnacho <carlosg@gnome.org>
|
||||||
|
Date: Mon, 16 Dec 2019 12:39:49 +0100
|
||||||
|
Subject: [PATCH] padOsd: Re-query action labels after mode switches
|
||||||
|
|
||||||
|
Do this so the pad OSD is able to update dynamically to mode changes,
|
||||||
|
showing immediately the new actions for the current mode(s).
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/898
|
||||||
|
---
|
||||||
|
js/ui/padOsd.js | 31 ++++++++++++++++++++++++++++---
|
||||||
|
1 file changed, 28 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/padOsd.js b/js/ui/padOsd.js
|
||||||
|
index a4af47297..b4b3fe453 100644
|
||||||
|
--- a/js/ui/padOsd.js
|
||||||
|
+++ b/js/ui/padOsd.js
|
||||||
|
@@ -555,6 +555,14 @@ var PadDiagram = GObject.registerClass({
|
||||||
|
this.add_actor(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ updateLabels(callback) {
|
||||||
|
+ for (let i = 0; i < this._labels.length; i++) {
|
||||||
|
+ let [label, action, idx, dir] = this._labels[i];
|
||||||
|
+ let str = callback(action, idx, dir);
|
||||||
|
+ label.set_text(str);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
_applyLabel(label, action, idx, dir, str) {
|
||||||
|
if (str != null) {
|
||||||
|
label.set_text(str);
|
||||||
|
@@ -758,17 +766,29 @@ var PadOsd = class {
|
||||||
|
global.display.request_pad_osd(pad, editionMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
- _createLabel(type, number, dir) {
|
||||||
|
+ _getActionText(type, number) {
|
||||||
|
let str = global.display.get_pad_action_label(this.padDevice, type, number);
|
||||||
|
- let label = new St.Label({ text: str ? str : _("None") });
|
||||||
|
+ return str ? str : _("None");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ _createLabel(type, number, dir) {
|
||||||
|
+ let label = new St.Label({ text: this._getActionText(type, number) });
|
||||||
|
this._padDiagram.addLabel(label, type, number, dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ _updateActionLabels() {
|
||||||
|
+ this._padDiagram.updateLabels(this._getActionText.bind(this));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
_onCapturedEvent(actor, event) {
|
||||||
|
+ let isModeSwitch =
|
||||||
|
+ (event.type() == Clutter.EventType.PAD_BUTTON_PRESS ||
|
||||||
|
+ event.type() == Clutter.EventType.PAD_BUTTON_RELEASE) &&
|
||||||
|
+ this.padDevice.get_mode_switch_button_group(event.get_button()) >= 0;
|
||||||
|
+
|
||||||
|
if (event.type() == Clutter.EventType.PAD_BUTTON_PRESS &&
|
||||||
|
event.get_source_device() == this.padDevice) {
|
||||||
|
this._padDiagram.activateButton(event.get_button());
|
||||||
|
- let isModeSwitch = this.padDevice.get_mode_switch_button_group(event.get_button()) >= 0;
|
||||||
|
|
||||||
|
/* Buttons that switch between modes cannot be edited */
|
||||||
|
if (this._editionMode && !isModeSwitch)
|
||||||
|
@@ -777,6 +797,11 @@ var PadOsd = class {
|
||||||
|
} else if (event.type() == Clutter.EventType.PAD_BUTTON_RELEASE &&
|
||||||
|
event.get_source_device() == this.padDevice) {
|
||||||
|
this._padDiagram.deactivateButton(event.get_button());
|
||||||
|
+
|
||||||
|
+ if (isModeSwitch) {
|
||||||
|
+ this._endActionEdition();
|
||||||
|
+ this._updateActionLabels();
|
||||||
|
+ }
|
||||||
|
return Clutter.EVENT_STOP;
|
||||||
|
} else if (event.type() == Clutter.EventType.KEY_PRESS &&
|
||||||
|
(!this._editionMode || event.get_key_symbol() == Clutter.Escape)) {
|
||||||
|
--
|
||||||
|
2.24.0
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,36 @@
|
|||||||
|
From fb0a9a60ab8f1c0dd96e789969ab9b6e48a9fce4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Olivier Fourdan <ofourdan@redhat.com>
|
||||||
|
Date: Tue, 21 Jul 2020 16:33:04 +0200
|
||||||
|
Subject: [PATCH] popupMenu: Handle keypress if numlock is enabled
|
||||||
|
|
||||||
|
On Wayland, navigating menus with the keyboard would not open drop-down
|
||||||
|
menus when NumLock is enabled.
|
||||||
|
|
||||||
|
That's old issue (gnome-shell#550) that was not completely fixed with
|
||||||
|
commit 88556226 because the lock mask needs to be filtered out in
|
||||||
|
_onKeyPress() as well.
|
||||||
|
|
||||||
|
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/550
|
||||||
|
---
|
||||||
|
js/ui/popupMenu.js | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js
|
||||||
|
index 6de081ce81..9835face19 100644
|
||||||
|
--- a/js/ui/popupMenu.js
|
||||||
|
+++ b/js/ui/popupMenu.js
|
||||||
|
@@ -801,9 +801,10 @@ var PopupMenu = class extends PopupMenuBase {
|
||||||
|
|
||||||
|
let state = event.get_state();
|
||||||
|
|
||||||
|
- // if user has a modifier down (except capslock)
|
||||||
|
+ // if user has a modifier down (except capslock and numlock)
|
||||||
|
// then don't handle the key press here
|
||||||
|
state &= ~Clutter.ModifierType.LOCK_MASK;
|
||||||
|
+ state &= ~Clutter.ModifierType.MOD2_MASK;
|
||||||
|
state &= Clutter.ModifierType.MODIFIER_MASK;
|
||||||
|
|
||||||
|
if (state)
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -0,0 +1,253 @@
|
|||||||
|
From 67a4506d4d8a0cbbaca5df4adfc309e54e557aee Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||||||
|
Date: Tue, 5 Jan 2021 12:04:23 +0100
|
||||||
|
Subject: [PATCH] screencast: Stop recording when screen size or resource scale
|
||||||
|
change
|
||||||
|
|
||||||
|
Video encoders don't really handle changing the size of the video, and if
|
||||||
|
we'd e.g. change resolution while recording, we would end up with a corrupt
|
||||||
|
video file. Handle this more gracefully by stopping the recording if the
|
||||||
|
conditions change.
|
||||||
|
---
|
||||||
|
js/ui/screencast.js | 92 +++++++++++++++++++++++++++++++++++++++++---
|
||||||
|
src/shell-recorder.c | 50 ++++++++++++------------
|
||||||
|
src/shell-recorder.h | 1 +
|
||||||
|
3 files changed, 114 insertions(+), 29 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/screencast.js b/js/ui/screencast.js
|
||||||
|
index 0b0b14a8e..54f8fb5ae 100644
|
||||||
|
--- a/js/ui/screencast.js
|
||||||
|
+++ b/js/ui/screencast.js
|
||||||
|
@@ -1,6 +1,6 @@
|
||||||
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||||
|
|
||||||
|
-const { Gio, GLib, Shell } = imports.gi;
|
||||||
|
+const { Gio, GLib, Meta, Shell } = imports.gi;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
@@ -53,16 +53,27 @@ var ScreencastService = class {
|
||||||
|
this._stopRecordingForSender(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
- _stopRecordingForSender(sender) {
|
||||||
|
+ _stopRecordingForSender(sender, closeNow=false) {
|
||||||
|
let recorder = this._recorders.get(sender);
|
||||||
|
if (!recorder)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Gio.bus_unwatch_name(recorder._watchNameId);
|
||||||
|
- recorder.close();
|
||||||
|
+ if (closeNow)
|
||||||
|
+ recorder.close_now();
|
||||||
|
+ else
|
||||||
|
+ recorder.close();
|
||||||
|
this._recorders.delete(sender);
|
||||||
|
this.emit('updated');
|
||||||
|
|
||||||
|
+ let connection = this._dbusImpl.get_connection();
|
||||||
|
+ let info = this._dbusImpl.get_info();
|
||||||
|
+ connection.emit_signal(sender,
|
||||||
|
+ this._dbusImpl.get_object_path(),
|
||||||
|
+ info ? info.name : null,
|
||||||
|
+ 'Stopped',
|
||||||
|
+ null);
|
||||||
|
+
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -78,6 +89,53 @@ var ScreencastService = class {
|
||||||
|
recorder.set_draw_cursor(options['draw-cursor']);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ _ensureResourceScaleChangedHandler() {
|
||||||
|
+ if (this._resourceScaleChangedHandlerId)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ this._resourceScaleChangedHandlerId =
|
||||||
|
+ global.stage.connect('notify::resource-scale',
|
||||||
|
+ () => {
|
||||||
|
+ for (let sender of this._recorders.keys()) {
|
||||||
|
+ let recorder = this._recorders.get(sender);
|
||||||
|
+
|
||||||
|
+ if (!recorder.is_recording())
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ this._stopRecordingForSender(sender, true);
|
||||||
|
+ }
|
||||||
|
+ });
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ _ensureMonitorsChangedHandler() {
|
||||||
|
+ if (this._monitorsChangedHandlerId)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ this._monitorsChangedHandlerId = Main.layoutManager.connect('monitors-changed',
|
||||||
|
+ () => {
|
||||||
|
+ for (let sender of this._recorders.keys()) {
|
||||||
|
+ let recorder = this._recorders.get(sender);
|
||||||
|
+
|
||||||
|
+ if (!recorder.is_recording())
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ let geometry = recorder._geometry;
|
||||||
|
+ let screenWidth = global.screen_width;
|
||||||
|
+ let screenHeight = global.screen_height;
|
||||||
|
+
|
||||||
|
+ if (recorder._isAreaScreecast) {
|
||||||
|
+ if (geometry.x + geometry.width > screenWidth ||
|
||||||
|
+ geometry.y + geometry.height > screenHeight)
|
||||||
|
+ this._stopRecordingForSender(sender, true);
|
||||||
|
+ } else {
|
||||||
|
+ if (geometry.width != screenWidth ||
|
||||||
|
+ geometry.height != screenHeight)
|
||||||
|
+ this._stopRecordingForSender(sender, true);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ });
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ScreencastAsync(params, invocation) {
|
||||||
|
let returnValue = [false, ''];
|
||||||
|
if (!Main.sessionMode.allowScreencast ||
|
||||||
|
@@ -95,8 +153,20 @@ var ScreencastService = class {
|
||||||
|
this._applyOptionalParameters(recorder, options);
|
||||||
|
let [success, fileName] = recorder.record();
|
||||||
|
returnValue = [success, fileName ? fileName : ''];
|
||||||
|
- if (!success)
|
||||||
|
+ if (success) {
|
||||||
|
+ recorder._isAreaScreecast = false;
|
||||||
|
+ recorder._geometry =
|
||||||
|
+ new Meta.Rectangle({
|
||||||
|
+ x: 0,
|
||||||
|
+ y: 0,
|
||||||
|
+ width: global.screen_width,
|
||||||
|
+ height: global.screen_height
|
||||||
|
+ });
|
||||||
|
+ this._ensureResourceScaleChangedHandler();
|
||||||
|
+ this._ensureMonitorsChangedHandler();
|
||||||
|
+ } else {
|
||||||
|
this._stopRecordingForSender(sender);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
invocation.return_value(GLib.Variant.new('(bs)', returnValue));
|
||||||
|
@@ -131,8 +201,20 @@ var ScreencastService = class {
|
||||||
|
this._applyOptionalParameters(recorder, options);
|
||||||
|
let [success, fileName] = recorder.record();
|
||||||
|
returnValue = [success, fileName ? fileName : ''];
|
||||||
|
- if (!success)
|
||||||
|
+ if (success) {
|
||||||
|
+ recorder._isAreaScreecast = true;
|
||||||
|
+ recorder._geometry =
|
||||||
|
+ new Meta.Rectangle({
|
||||||
|
+ x: x,
|
||||||
|
+ y: y,
|
||||||
|
+ width: width,
|
||||||
|
+ height: height
|
||||||
|
+ });
|
||||||
|
+ this._ensureResourceScaleChangedHandler();
|
||||||
|
+ this._ensureMonitorsChangedHandler();
|
||||||
|
+ } else {
|
||||||
|
this._stopRecordingForSender(sender);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
invocation.return_value(GLib.Variant.new('(bs)', returnValue));
|
||||||
|
diff --git a/src/shell-recorder.c b/src/shell-recorder.c
|
||||||
|
index 0203ecf1c..e561a0152 100644
|
||||||
|
--- a/src/shell-recorder.c
|
||||||
|
+++ b/src/shell-recorder.c
|
||||||
|
@@ -511,21 +511,6 @@ recorder_update_size (ShellRecorder *recorder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void
|
||||||
|
-recorder_on_stage_notify_size (GObject *object,
|
||||||
|
- GParamSpec *pspec,
|
||||||
|
- ShellRecorder *recorder)
|
||||||
|
-{
|
||||||
|
- recorder_update_size (recorder);
|
||||||
|
-
|
||||||
|
- /* This breaks the recording but tweaking the GStreamer pipeline a bit
|
||||||
|
- * might make it work, at least if the codec can handle a stream where
|
||||||
|
- * the frame size changes in the middle.
|
||||||
|
- */
|
||||||
|
- if (recorder->current_pipeline)
|
||||||
|
- recorder_pipeline_set_caps (recorder->current_pipeline);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static gboolean
|
||||||
|
recorder_idle_redraw (gpointer data)
|
||||||
|
{
|
||||||
|
@@ -622,12 +607,6 @@ recorder_connect_stage_callbacks (ShellRecorder *recorder)
|
||||||
|
G_CALLBACK (recorder_on_stage_destroy), recorder);
|
||||||
|
g_signal_connect_after (recorder->stage, "paint",
|
||||||
|
G_CALLBACK (recorder_on_stage_paint), recorder);
|
||||||
|
- g_signal_connect (recorder->stage, "notify::width",
|
||||||
|
- G_CALLBACK (recorder_on_stage_notify_size), recorder);
|
||||||
|
- g_signal_connect (recorder->stage, "notify::height",
|
||||||
|
- G_CALLBACK (recorder_on_stage_notify_size), recorder);
|
||||||
|
- g_signal_connect (recorder->stage, "notify::resource-scale",
|
||||||
|
- G_CALLBACK (recorder_on_stage_notify_size), recorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -639,9 +618,6 @@ recorder_disconnect_stage_callbacks (ShellRecorder *recorder)
|
||||||
|
g_signal_handlers_disconnect_by_func (recorder->stage,
|
||||||
|
(void *)recorder_on_stage_paint,
|
||||||
|
recorder);
|
||||||
|
- g_signal_handlers_disconnect_by_func (recorder->stage,
|
||||||
|
- (void *)recorder_on_stage_notify_size,
|
||||||
|
- recorder);
|
||||||
|
|
||||||
|
/* We don't don't deselect for cursor changes in case someone else just
|
||||||
|
* happened to be selecting for cursor events on the same window; sending
|
||||||
|
@@ -1578,6 +1554,32 @@ shell_recorder_record (ShellRecorder *recorder,
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * shell_recorder_close_now:
|
||||||
|
+ * @recorder: the #ShellRecorder
|
||||||
|
+ *
|
||||||
|
+ * Stops recording immediately. It's possible to call shell_recorder_record()
|
||||||
|
+ * again to reopen a new recording stream, but unless change the recording
|
||||||
|
+ * filename, this may result in the old recording being overwritten.
|
||||||
|
+ */
|
||||||
|
+void
|
||||||
|
+shell_recorder_close_now (ShellRecorder *recorder)
|
||||||
|
+{
|
||||||
|
+ g_return_if_fail (SHELL_IS_RECORDER (recorder));
|
||||||
|
+ g_return_if_fail (recorder->state != RECORDER_STATE_CLOSED);
|
||||||
|
+
|
||||||
|
+ recorder_remove_update_pointer_timeout (recorder);
|
||||||
|
+ recorder_close_pipeline (recorder);
|
||||||
|
+
|
||||||
|
+ recorder->state = RECORDER_STATE_CLOSED;
|
||||||
|
+
|
||||||
|
+ /* Reenable after the recording */
|
||||||
|
+ meta_enable_unredirect_for_display (shell_global_get_display (shell_global_get ()));
|
||||||
|
+
|
||||||
|
+ /* Release the refcount we took when we started recording */
|
||||||
|
+ g_object_unref (recorder);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* shell_recorder_close:
|
||||||
|
* @recorder: the #ShellRecorder
|
||||||
|
diff --git a/src/shell-recorder.h b/src/shell-recorder.h
|
||||||
|
index c1e0e6368..1c3e6aab4 100644
|
||||||
|
--- a/src/shell-recorder.h
|
||||||
|
+++ b/src/shell-recorder.h
|
||||||
|
@@ -37,6 +37,7 @@ void shell_recorder_set_area (ShellRecorder *recorder,
|
||||||
|
gboolean shell_recorder_record (ShellRecorder *recorder,
|
||||||
|
char **filename_used);
|
||||||
|
void shell_recorder_close (ShellRecorder *recorder);
|
||||||
|
+void shell_recorder_close_now (ShellRecorder *recorder);
|
||||||
|
void shell_recorder_pause (ShellRecorder *recorder);
|
||||||
|
gboolean shell_recorder_is_recording (ShellRecorder *recorder);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
@ -0,0 +1,78 @@
|
|||||||
|
From 391f262aee82ac12fcf99951d6b2df362f734b31 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Mon, 15 Jun 2020 20:41:45 +0200
|
||||||
|
Subject: [PATCH] shell/app: Handle workspace from startup notifications
|
||||||
|
|
||||||
|
Launching applications on a particular workspace works through
|
||||||
|
launch contexts and startup notifications. While this is no
|
||||||
|
longer required by a launcher/WM split, in theory this allows
|
||||||
|
us to reliably identify the correct window to apply startup
|
||||||
|
properties to.
|
||||||
|
|
||||||
|
However in practice we fail more often than not: Missing support in
|
||||||
|
toolkits, differences between display protocols, D-Bus activation
|
||||||
|
and single-instance applications all provide their own pitfalls.
|
||||||
|
|
||||||
|
So instead, take advantage of the fact that launcher and WM live in
|
||||||
|
the same process, and go with the unsophisticated approach: Just
|
||||||
|
remember the last workspace that was requested when launching an
|
||||||
|
app, then move the next window that is associated with the app to
|
||||||
|
that workspace.
|
||||||
|
|
||||||
|
This will break X11 applications that set an initial workspace, but
|
||||||
|
that's legacy functionality anyway (given that there's no wayland
|
||||||
|
protocol for that functionality), and seems a price worth paying
|
||||||
|
for making launching apps on workspaces more reliable.
|
||||||
|
---
|
||||||
|
src/shell-app.c | 19 +++++++++++--------
|
||||||
|
1 file changed, 11 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/shell-app.c b/src/shell-app.c
|
||||||
|
index 7d40186c9..f716bc5f8 100644
|
||||||
|
--- a/src/shell-app.c
|
||||||
|
+++ b/src/shell-app.c
|
||||||
|
@@ -1067,6 +1067,10 @@ _shell_app_add_window (ShellApp *app,
|
||||||
|
if (!app->running_state)
|
||||||
|
create_running_state (app);
|
||||||
|
|
||||||
|
+ if (app->started_on_workspace >= 0)
|
||||||
|
+ meta_window_change_workspace_by_index (window, app->started_on_workspace, FALSE);
|
||||||
|
+ app->started_on_workspace = -1;
|
||||||
|
+
|
||||||
|
app->running_state->window_sort_stale = TRUE;
|
||||||
|
app->running_state->windows = g_slist_prepend (app->running_state->windows, g_object_ref (window));
|
||||||
|
g_signal_connect_object (window, "unmanaged", G_CALLBACK(shell_app_on_unmanaged), app, 0);
|
||||||
|
@@ -1156,16 +1160,14 @@ _shell_app_handle_startup_sequence (ShellApp *app,
|
||||||
|
shell_app_state_transition (app, SHELL_APP_STATE_STARTING);
|
||||||
|
meta_x11_display_focus_the_no_focus_window (x11_display,
|
||||||
|
meta_startup_sequence_get_timestamp (sequence));
|
||||||
|
- app->started_on_workspace = meta_startup_sequence_get_workspace (sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (!starting)
|
||||||
|
- {
|
||||||
|
- if (app->running_state && app->running_state->windows)
|
||||||
|
- shell_app_state_transition (app, SHELL_APP_STATE_RUNNING);
|
||||||
|
- else /* application have > 1 .desktop file */
|
||||||
|
- shell_app_state_transition (app, SHELL_APP_STATE_STOPPED);
|
||||||
|
- }
|
||||||
|
+ if (starting)
|
||||||
|
+ app->started_on_workspace = meta_startup_sequence_get_workspace (sequence);
|
||||||
|
+ else if (app->running_state && app->running_state->windows)
|
||||||
|
+ shell_app_state_transition (app, SHELL_APP_STATE_RUNNING);
|
||||||
|
+ else /* application have > 1 .desktop file */
|
||||||
|
+ shell_app_state_transition (app, SHELL_APP_STATE_STOPPED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -1473,6 +1475,7 @@ static void
|
||||||
|
shell_app_init (ShellApp *self)
|
||||||
|
{
|
||||||
|
self->state = SHELL_APP_STATE_STOPPED;
|
||||||
|
+ self->started_on_workspace = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
--
|
||||||
|
2.29.2
|
||||||
|
|
@ -0,0 +1,28 @@
|
|||||||
|
From 3182ad73c8f88628cb51a96feba0fc32ce7f01c9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Illya Klymov <xanf@xanf.me>
|
||||||
|
Date: Mon, 8 Jul 2019 03:29:36 +0000
|
||||||
|
Subject: [PATCH] shell-recorder: Restore cursor recording
|
||||||
|
|
||||||
|
Due to changes introduced in 5357e0a1 cursor recording interaction with
|
||||||
|
magnifier was reversed. This fix restores original correct behavior
|
||||||
|
Related issue: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1208
|
||||||
|
---
|
||||||
|
src/shell-recorder.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/shell-recorder.c b/src/shell-recorder.c
|
||||||
|
index 0203ecf1c..cf1cc336f 100644
|
||||||
|
--- a/src/shell-recorder.c
|
||||||
|
+++ b/src/shell-recorder.c
|
||||||
|
@@ -465,7 +465,7 @@ recorder_record_frame (ShellRecorder *recorder,
|
||||||
|
|
||||||
|
g_object_get (settings, "magnifier-active", &magnifier_active, NULL);
|
||||||
|
|
||||||
|
- if (magnifier_active)
|
||||||
|
+ if (!magnifier_active)
|
||||||
|
recorder_draw_cursor (recorder, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.35.1
|
||||||
|
|
@ -1,56 +0,0 @@
|
|||||||
From b1be295de28f45762a525d3ad3f91729295a7511 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@redhat.com>
|
|
||||||
Date: Fri, 18 Oct 2024 13:20:23 +0200
|
|
||||||
Subject: [PATCH] shell/window-tracker: Help mutter finding app info's for
|
|
||||||
windows
|
|
||||||
|
|
||||||
---
|
|
||||||
src/shell-window-tracker.c | 25 +++++++++++++++++++++++++
|
|
||||||
1 file changed, 25 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/src/shell-window-tracker.c b/src/shell-window-tracker.c
|
|
||||||
index bc14040d9b..8fbcca4269 100644
|
|
||||||
--- a/src/shell-window-tracker.c
|
|
||||||
+++ b/src/shell-window-tracker.c
|
|
||||||
@@ -651,6 +651,20 @@ shell_window_tracker_on_n_workspaces_changed (MetaWorkspaceManager *workspace_ma
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+static GAppInfo *
|
|
||||||
+on_find_app_info (MetaDisplay *display,
|
|
||||||
+ MetaWindow *window,
|
|
||||||
+ ShellWindowTracker *tracker)
|
|
||||||
+{
|
|
||||||
+ g_autoptr (ShellApp) app = NULL;
|
|
||||||
+
|
|
||||||
+ app = get_app_for_window (tracker, window);
|
|
||||||
+ if (!app)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ return g_object_ref (G_APP_INFO (shell_app_get_app_info (app)));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void
|
|
||||||
init_window_tracking (ShellWindowTracker *self)
|
|
||||||
{
|
|
||||||
@@ -665,6 +679,17 @@ init_window_tracking (ShellWindowTracker *self)
|
|
||||||
g_signal_connect(display, "window-created",
|
|
||||||
G_CALLBACK (on_window_created), self);
|
|
||||||
|
|
||||||
+ if (g_signal_lookup ("find-app-info", META_TYPE_DISPLAY))
|
|
||||||
+ {
|
|
||||||
+ g_debug ("Mutter app finding with the help of gnome-shell");
|
|
||||||
+ g_signal_connect (display, "find-app-info",
|
|
||||||
+ G_CALLBACK (on_find_app_info), self);
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ g_debug ("No mutter app finding with the help of gnome-shell");
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
shell_window_tracker_on_n_workspaces_changed (workspace_manager, NULL, self);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.44.0.501.g19981daefd.dirty
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
|||||||
|
From 660ebe0125b591355116934ee57b08010e05246c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rui Matos <tiagomatos@gmail.com>
|
||||||
|
Date: Fri, 8 Nov 2013 11:36:04 +0100
|
||||||
|
Subject: [PATCH] shellDBus: Add a DBus method to load a single extension
|
||||||
|
|
||||||
|
This allows e.g. gnome-tweak-tool to install an extension from a zip
|
||||||
|
file and load it into the running shell.
|
||||||
|
---
|
||||||
|
.../org.gnome.Shell.Extensions.xml | 13 +++++++++++++
|
||||||
|
js/ui/shellDBus.js | 16 ++++++++++++++++
|
||||||
|
2 files changed, 29 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/data/dbus-interfaces/org.gnome.Shell.Extensions.xml b/data/dbus-interfaces/org.gnome.Shell.Extensions.xml
|
||||||
|
index 34a65af44..ce69439fc 100644
|
||||||
|
--- a/data/dbus-interfaces/org.gnome.Shell.Extensions.xml
|
||||||
|
+++ b/data/dbus-interfaces/org.gnome.Shell.Extensions.xml
|
||||||
|
@@ -189,6 +189,19 @@
|
||||||
|
-->
|
||||||
|
<method name="CheckForUpdates"/>
|
||||||
|
|
||||||
|
+ <!--
|
||||||
|
+ LoadUserExtension:
|
||||||
|
+ @uuid: The UUID of the extension
|
||||||
|
+ @success: Whether the operation was successful
|
||||||
|
+
|
||||||
|
+ Load a newly installed user extension
|
||||||
|
+ -->
|
||||||
|
+
|
||||||
|
+ <method name="LoadUserExtension">
|
||||||
|
+ <arg type="s" direction="in" name="uuid"/>
|
||||||
|
+ <arg type="b" direction="out" name="success"/>
|
||||||
|
+ </method>
|
||||||
|
+
|
||||||
|
<signal name="ExtensionStatusChanged">
|
||||||
|
<arg type="s" name="uuid"/>
|
||||||
|
<arg type="i" name="state"/>
|
||||||
|
diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js
|
||||||
|
index 19d07acce..112d60feb 100644
|
||||||
|
--- a/js/ui/shellDBus.js
|
||||||
|
+++ b/js/ui/shellDBus.js
|
||||||
|
@@ -341,6 +341,22 @@ var GnomeShellExtensions = class {
|
||||||
|
ExtensionDownloader.checkForUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ LoadUserExtension(uuid) {
|
||||||
|
+ let extension = ExtensionUtils.extensions[uuid];
|
||||||
|
+ if (extension)
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ let dir = Gio.File.new_for_path(GLib.build_filenamev([global.userdatadir, 'extensions', uuid]));
|
||||||
|
+ try {
|
||||||
|
+ extension = ExtensionUtils.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER);
|
||||||
|
+ ExtensionSystem.loadExtension(extension);
|
||||||
|
+ } catch (e) {
|
||||||
|
+ log('Could not load user extension from %s'.format(dir.get_path()));
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
get ShellVersion() {
|
||||||
|
return Config.PACKAGE_VERSION;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -0,0 +1,91 @@
|
|||||||
|
From e6cd96a9f6a89f77ca0fab72aff8c56354b59f38 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Wed, 21 Aug 2019 15:01:34 -0400
|
||||||
|
Subject: [PATCH 1/4] shellEntry: Determine if password entry from content
|
||||||
|
purpose not menu item
|
||||||
|
|
||||||
|
Right now shellEntry decides whether or not it's a password entry based
|
||||||
|
on whether or not it has a "Show Text" context menu.
|
||||||
|
|
||||||
|
That's a little roundabout, and gets in the way off providing lockdown
|
||||||
|
that disables the menu.
|
||||||
|
|
||||||
|
This commit changes shellEntry to base whether or not it's a password
|
||||||
|
entry from it's input content purpose instead of from the presence
|
||||||
|
or absence of a context menu.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/687
|
||||||
|
---
|
||||||
|
js/ui/shellEntry.js | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js
|
||||||
|
index 53bd1daa1..cac4ec9c2 100644
|
||||||
|
--- a/js/ui/shellEntry.js
|
||||||
|
+++ b/js/ui/shellEntry.js
|
||||||
|
@@ -14,61 +14,61 @@ var EntryMenu = class extends PopupMenu.PopupMenu {
|
||||||
|
|
||||||
|
this._entry = entry;
|
||||||
|
this._clipboard = St.Clipboard.get_default();
|
||||||
|
|
||||||
|
// Populate menu
|
||||||
|
let item;
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("Copy"));
|
||||||
|
item.connect('activate', this._onCopyActivated.bind(this));
|
||||||
|
this.addMenuItem(item);
|
||||||
|
this._copyItem = item;
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("Paste"));
|
||||||
|
item.connect('activate', this._onPasteActivated.bind(this));
|
||||||
|
this.addMenuItem(item);
|
||||||
|
this._pasteItem = item;
|
||||||
|
|
||||||
|
this._passwordItem = null;
|
||||||
|
|
||||||
|
Main.uiGroup.add_actor(this.actor);
|
||||||
|
this.actor.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
_makePasswordItem() {
|
||||||
|
let item = new PopupMenu.PopupMenuItem('');
|
||||||
|
item.connect('activate', this._onPasswordActivated.bind(this));
|
||||||
|
this.addMenuItem(item);
|
||||||
|
this._passwordItem = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isPassword() {
|
||||||
|
- return this._passwordItem != null;
|
||||||
|
+ return this._entry.input_purpose == Clutter.InputContentPurpose.PASSWORD;
|
||||||
|
}
|
||||||
|
|
||||||
|
set isPassword(v) {
|
||||||
|
if (v == this.isPassword)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (v) {
|
||||||
|
this._makePasswordItem();
|
||||||
|
this._entry.input_purpose = Clutter.InputContentPurpose.PASSWORD;
|
||||||
|
} else {
|
||||||
|
this._passwordItem.destroy();
|
||||||
|
this._passwordItem = null;
|
||||||
|
this._entry.input_purpose = Clutter.InputContentPurpose.NORMAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open(animate) {
|
||||||
|
this._updatePasteItem();
|
||||||
|
this._updateCopyItem();
|
||||||
|
if (this._passwordItem)
|
||||||
|
this._updatePasswordItem();
|
||||||
|
|
||||||
|
super.open(animate);
|
||||||
|
this._entry.add_style_pseudo_class('focus');
|
||||||
|
|
||||||
|
let direction = St.DirectionType.TAB_FORWARD;
|
||||||
|
if (!this.actor.navigate_focus(null, direction, false))
|
||||||
|
this.actor.grab_key_focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
@ -0,0 +1,36 @@
|
|||||||
|
From fd8c4dc073b121b1093d68472cac3292d2c6605c Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Mon, 14 Jun 2021 17:59:39 +0200
|
||||||
|
Subject: [PATCH] shellEntry: Disconnect handler on destroy
|
||||||
|
|
||||||
|
Actors will get unmapped on destroy, so unless we disconnect from
|
||||||
|
the notify::mapped signal, the handler will run one last time and
|
||||||
|
try to access methods/properties on the invalidated actor.
|
||||||
|
---
|
||||||
|
js/ui/shellEntry.js | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js
|
||||||
|
index 4a30b22f7..53bd1daa1 100644
|
||||||
|
--- a/js/ui/shellEntry.js
|
||||||
|
+++ b/js/ui/shellEntry.js
|
||||||
|
@@ -186,7 +186,7 @@ class CapsLockWarning extends St.Label {
|
||||||
|
this._keymap = Clutter.get_default_backend().get_keymap();
|
||||||
|
this._stateChangedId = 0;
|
||||||
|
|
||||||
|
- this.connect('notify::mapped', () => {
|
||||||
|
+ const mappedId = this.connect('notify::mapped', () => {
|
||||||
|
if (this.is_mapped()) {
|
||||||
|
this._stateChangedId = this._keymap.connect('state-changed',
|
||||||
|
() => this._sync(true));
|
||||||
|
@@ -201,6 +201,7 @@ class CapsLockWarning extends St.Label {
|
||||||
|
this.connect('destroy', () => {
|
||||||
|
if (this._stateChangedId)
|
||||||
|
this._keymap.disconnect(this._stateChangedId);
|
||||||
|
+ this.disconnect(mappedId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.31.1
|
||||||
|
|
@ -0,0 +1,59 @@
|
|||||||
|
From 96404287bc4269dea7b037e7b178e54ebf616d47 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
||||||
|
Date: Tue, 24 Nov 2020 17:34:08 +0800
|
||||||
|
Subject: [PATCH] st-bin: Disallow st_bin_set_child with already-parented
|
||||||
|
children
|
||||||
|
|
||||||
|
Not checking for this would result in `clutter_actor_add_child`
|
||||||
|
failing, but StBin keeping a copy in `priv->child`. So later on,
|
||||||
|
`st_bin_remove` would never be called on it and this assertion
|
||||||
|
would fail and crash the whole shell:
|
||||||
|
|
||||||
|
```
|
||||||
|
static void
|
||||||
|
st_bin_destroy (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StBinPrivate *priv = st_bin_get_instance_private (ST_BIN (actor));
|
||||||
|
|
||||||
|
if (priv->child)
|
||||||
|
clutter_actor_destroy (priv->child);
|
||||||
|
g_assert (priv->child == NULL);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
By disallowing spurious `st_bin_set_child` calls we now prevent StBin
|
||||||
|
from entering such a corrupt state and the above assertion won't fail
|
||||||
|
anymore.
|
||||||
|
|
||||||
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1507>
|
||||||
|
---
|
||||||
|
src/st/st-bin.c | 13 +++++++++++++
|
||||||
|
1 file changed, 13 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/st/st-bin.c b/src/st/st-bin.c
|
||||||
|
index f013909e8..7959a4e95 100644
|
||||||
|
--- a/src/st/st-bin.c
|
||||||
|
+++ b/src/st/st-bin.c
|
||||||
|
@@ -434,6 +434,19 @@ st_bin_set_child (StBin *bin,
|
||||||
|
if (priv->child == child)
|
||||||
|
return;
|
||||||
|
|
||||||
|
+ if (child)
|
||||||
|
+ {
|
||||||
|
+ ClutterActor *parent = clutter_actor_get_parent (child);
|
||||||
|
+
|
||||||
|
+ if (parent)
|
||||||
|
+ {
|
||||||
|
+ g_warning ("%s: The provided 'child' actor %p already has a "
|
||||||
|
+ "(different) parent %p and can't be made a child of %p.",
|
||||||
|
+ G_STRFUNC, child, parent, bin);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (priv->child)
|
||||||
|
clutter_actor_remove_child (CLUTTER_ACTOR (bin), priv->child);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.38.1
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
From 187b851530f5e76786784ec9df235304c8ddede8 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
||||||
Date: Wed, 4 Aug 2021 19:46:34 +0200
|
|
||||||
Subject: [PATCH] st/icon: Only get resource-scale after peeking theme node
|
|
||||||
|
|
||||||
If an actor is not on any stage view, then it doesn't have a valid
|
|
||||||
resource scale, which will hit an assert later.
|
|
||||||
|
|
||||||
When that is the case (for example when running headless), we expect
|
|
||||||
that there is no valid theme node (yet) either, so simply moving
|
|
||||||
the clutter_actor_get_resource_scale() call after peeking at the
|
|
||||||
theme node is enough to avoid the crash.
|
|
||||||
|
|
||||||
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4522
|
|
||||||
|
|
||||||
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1935>
|
|
||||||
---
|
|
||||||
src/st/st-icon.c | 2 ++
|
|
||||||
1 file changed, 2 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/src/st/st-icon.c b/src/st/st-icon.c
|
|
||||||
index 0405d85259..e4d6e05f94 100644
|
|
||||||
--- a/src/st/st-icon.c
|
|
||||||
+++ b/src/st/st-icon.c
|
|
||||||
@@ -462,6 +462,8 @@ st_icon_update (StIcon *icon)
|
|
||||||
|
|
||||||
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (icon));
|
|
||||||
|
|
||||||
+ resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (icon));
|
|
||||||
+
|
|
||||||
stage = clutter_actor_get_stage (CLUTTER_ACTOR (icon));
|
|
||||||
context = st_theme_context_get_for_stage (CLUTTER_STAGE (stage));
|
|
||||||
g_object_get (context, "scale-factor", &paint_scale, NULL);
|
|
||||||
--
|
|
||||||
2.31.1
|
|
||||||
|
|
@ -0,0 +1,94 @@
|
|||||||
|
From 1bf28eea64056846547ec33d783c7f2e0dad78a4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Fri, 22 May 2020 22:53:39 +0200
|
||||||
|
Subject: [PATCH] st/texture-cache: Cancel pending requests on icon-theme
|
||||||
|
changes
|
||||||
|
|
||||||
|
As outlined in commit 36b8dcbe07, we can end up with wrong icons
|
||||||
|
if the icon theme changes right after a GTK theme change to/from
|
||||||
|
HighContrast triggered a theme reload.
|
||||||
|
|
||||||
|
That's because when we reload icons for the new icon theme, there
|
||||||
|
are already pending requests due to the icon-style change; those
|
||||||
|
requests are simply re-used for the new icons, with the existing
|
||||||
|
icon infos from the old theme.
|
||||||
|
|
||||||
|
The above commit applied a simple work-around by changing the
|
||||||
|
icon theme before the GTK theme, but that only works for the
|
||||||
|
HighContrast switch in our own UI.
|
||||||
|
|
||||||
|
It turns out that Settings also uses the "wrong" order, so the
|
||||||
|
issue still reproduces with the Universal Access panel.
|
||||||
|
|
||||||
|
So instead of relying on everything changing the settings in the
|
||||||
|
order we expect, cancel all ongoing requests on icon-theme changes.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1277
|
||||||
|
---
|
||||||
|
src/st/st-texture-cache.c | 17 +++++++++++++++--
|
||||||
|
1 file changed, 15 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c
|
||||||
|
index 35e9d036f..6dc351282 100644
|
||||||
|
--- a/src/st/st-texture-cache.c
|
||||||
|
+++ b/src/st/st-texture-cache.c
|
||||||
|
@@ -48,6 +48,8 @@ struct _StTextureCachePrivate
|
||||||
|
|
||||||
|
/* File monitors to evict cache data on changes */
|
||||||
|
GHashTable *file_monitors; /* char * -> GFileMonitor * */
|
||||||
|
+
|
||||||
|
+ GCancellable *cancellable;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void st_texture_cache_dispose (GObject *object);
|
||||||
|
@@ -152,6 +154,9 @@ on_icon_theme_changed (StSettings *settings,
|
||||||
|
{
|
||||||
|
g_autofree gchar *theme;
|
||||||
|
|
||||||
|
+ g_cancellable_cancel (cache->priv->cancellable);
|
||||||
|
+ g_cancellable_reset (cache->priv->cancellable);
|
||||||
|
+
|
||||||
|
st_texture_cache_evict_icons (cache);
|
||||||
|
|
||||||
|
g_object_get (settings, "gtk-icon-theme", &theme, NULL);
|
||||||
|
@@ -186,6 +191,8 @@ st_texture_cache_init (StTextureCache *self)
|
||||||
|
self->priv->file_monitors = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal,
|
||||||
|
g_object_unref, g_object_unref);
|
||||||
|
|
||||||
|
+ self->priv->cancellable = g_cancellable_new ();
|
||||||
|
+
|
||||||
|
on_icon_theme_changed (settings, NULL, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -194,8 +201,11 @@ st_texture_cache_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
StTextureCache *self = (StTextureCache*)object;
|
||||||
|
|
||||||
|
+ g_cancellable_cancel (self->priv->cancellable);
|
||||||
|
+
|
||||||
|
g_clear_object (&self->priv->settings);
|
||||||
|
g_clear_object (&self->priv->icon_theme);
|
||||||
|
+ g_clear_object (&self->priv->cancellable);
|
||||||
|
|
||||||
|
g_clear_pointer (&self->priv->keyed_cache, g_hash_table_destroy);
|
||||||
|
g_clear_pointer (&self->priv->keyed_surface_cache, g_hash_table_destroy);
|
||||||
|
@@ -675,11 +685,14 @@ load_texture_async (StTextureCache *cache,
|
||||||
|
gtk_icon_info_load_symbolic_async (data->icon_info,
|
||||||
|
&foreground_color, &success_color,
|
||||||
|
&warning_color, &error_color,
|
||||||
|
- NULL, on_symbolic_icon_loaded, data);
|
||||||
|
+ cache->priv->cancellable,
|
||||||
|
+ on_symbolic_icon_loaded, data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
- gtk_icon_info_load_icon_async (data->icon_info, NULL, on_icon_loaded, data);
|
||||||
|
+ gtk_icon_info_load_icon_async (data->icon_info,
|
||||||
|
+ cache->priv->cancellable,
|
||||||
|
+ on_icon_loaded, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -1,58 +0,0 @@
|
|||||||
From 7e94d682985ac4ff422da73b5878f4f005eff67b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Mohammed Sadiq <sadiq@sadiqpk.org>
|
|
||||||
Date: Tue, 10 Aug 2021 15:22:30 +0530
|
|
||||||
Subject: [PATCH] status/network: Use wwan settings panel for GSM/LTE Modems
|
|
||||||
|
|
||||||
GSM/UMTS/LTE modems now have better support with wwan panel in GNOME
|
|
||||||
Settings. So, if the modem supports, open wwan panel, otherwise
|
|
||||||
fallback to opening network panel when "Mobile Broadband Settings"
|
|
||||||
item is clicked.
|
|
||||||
|
|
||||||
See https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/583
|
|
||||||
|
|
||||||
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1942>
|
|
||||||
---
|
|
||||||
js/ui/status/network.js | 19 +++++++++++++++++--
|
|
||||||
1 file changed, 17 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/js/ui/status/network.js b/js/ui/status/network.js
|
|
||||||
index f510f90ae..fe82fcb08 100644
|
|
||||||
--- a/js/ui/status/network.js
|
|
||||||
+++ b/js/ui/status/network.js
|
|
||||||
@@ -543,7 +543,11 @@ var NMDeviceModem = class extends NMConnectionDevice {
|
|
||||||
constructor(client, device) {
|
|
||||||
super(client, device);
|
|
||||||
|
|
||||||
- this.item.menu.addSettingsAction(_("Mobile Broadband Settings"), 'gnome-network-panel.desktop');
|
|
||||||
+ const settingsPanel = this._useWwanPanel()
|
|
||||||
+ ? 'gnome-wwan-panel.desktop'
|
|
||||||
+ : 'gnome-network-panel.desktop';
|
|
||||||
+
|
|
||||||
+ this.item.menu.addSettingsAction(_('Mobile Broadband Settings'), settingsPanel);
|
|
||||||
|
|
||||||
this._mobileDevice = null;
|
|
||||||
|
|
||||||
@@ -573,8 +577,19 @@ var NMDeviceModem = class extends NMConnectionDevice {
|
|
||||||
return NMConnectionCategory.WWAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ _useWwanPanel() {
|
|
||||||
+ // Currently, wwan panel doesn't support CDMA_EVDO modems
|
|
||||||
+ const supportedCaps =
|
|
||||||
+ NM.DeviceModemCapabilities.GSM_UMTS |
|
|
||||||
+ NM.DeviceModemCapabilities.LTE;
|
|
||||||
+ return this._device.current_capabilities & supportedCaps;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
_autoConnect() {
|
|
||||||
- launchSettingsPanel('network', 'connect-3g', this._device.get_path());
|
|
||||||
+ if (this._useWwanPanel())
|
|
||||||
+ launchSettingsPanel('wwan', 'show-device', this._device.udi);
|
|
||||||
+ else
|
|
||||||
+ launchSettingsPanel('network', 'connect-3g', this._device.get_path());
|
|
||||||
}
|
|
||||||
|
|
||||||
_sessionUpdated() {
|
|
||||||
--
|
|
||||||
2.31.1
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
|||||||
|
From c68fd3c94c6debdbf11020940c5a6aaee8bc230d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Feichtmeier <frederik.feichtmeier@gmail.com>
|
||||||
|
Date: Fri, 15 Mar 2019 14:41:55 +0100
|
||||||
|
Subject: [PATCH] theme: Update window preview style
|
||||||
|
|
||||||
|
- simplify the close button to use blue, lighter blue and darker blue
|
||||||
|
solid disks for normal, hover and active states
|
||||||
|
|
||||||
|
- use a milky, transparent white border for the hover effect of the border
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/461
|
||||||
|
---
|
||||||
|
data/theme/gnome-shell-sass/_common.scss | 29 ++++++++++++------------
|
||||||
|
1 file changed, 14 insertions(+), 15 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss
|
||||||
|
index 9e0751c8c..8bf368f6e 100644
|
||||||
|
--- a/data/theme/gnome-shell-sass/_common.scss
|
||||||
|
+++ b/data/theme/gnome-shell-sass/_common.scss
|
||||||
|
@@ -1164,25 +1164,23 @@ StScrollBar {
|
||||||
|
//close buttons
|
||||||
|
|
||||||
|
.window-close {
|
||||||
|
- background-color: white;
|
||||||
|
+ background-color: $selected_bg_color;
|
||||||
|
+ color: white;
|
||||||
|
border-radius: 24px;
|
||||||
|
- border: 4px solid $selected_bg_color;
|
||||||
|
- box-shadow: inset 0 -4px 0 0 transparentize($selected_bg_color, 0.5);
|
||||||
|
- color: $selected_bg_color;
|
||||||
|
+ border: 2px solid $selected_bg_color;
|
||||||
|
height: 24px;
|
||||||
|
width: 24px;
|
||||||
|
- -shell-close-overlap: 14px;
|
||||||
|
+ -shell-close-overlap: 11px;
|
||||||
|
+ box-shadow: -1px 1px 5px 0px transparentize(black, 0.5);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
- background-color: $selected_bg_color;
|
||||||
|
- border-color: white;
|
||||||
|
- color: white;
|
||||||
|
+ background-color: lighten($selected_bg_color, 5%);
|
||||||
|
+ border-color: lighten($selected_bg_color, 5%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
- background-color: mix(white, $selected_bg_color, 75%);
|
||||||
|
- border-color: $selected_bg_color;
|
||||||
|
- color: $selected_bg_color;
|
||||||
|
+ background-color: darken($selected_bg_color, 5%);
|
||||||
|
+ border-color: darken($selected_bg_color, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1247,13 +1245,14 @@ StScrollBar {
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-clone-border {
|
||||||
|
- border: 4px solid $selected_bg_color;
|
||||||
|
- border-radius: 4px;
|
||||||
|
+ $_bg: transparentize(white, 0.65);
|
||||||
|
+ border: 5px solid $_bg;
|
||||||
|
+ border-radius: 6px;
|
||||||
|
// For window decorations with round corners we can't match
|
||||||
|
// the exact shape when the window is scaled. So apply a shadow
|
||||||
|
// to fix that case
|
||||||
|
- box-shadow: inset 0px 0px 0px 1px $selected_bg_color;
|
||||||
|
- }
|
||||||
|
+ box-shadow: inset 0 0 0 1px $_bg;
|
||||||
|
+}
|
||||||
|
.window-caption {
|
||||||
|
spacing: 25px;
|
||||||
|
color: $selected_fg_color;
|
||||||
|
--
|
||||||
|
2.31.1
|
||||||
|
|
@ -1,38 +0,0 @@
|
|||||||
From 79049292451b9bb23ad92c572a438585ca37246b Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
||||||
Date: Wed, 27 Oct 2021 15:18:20 +0200
|
|
||||||
Subject: [PATCH] welcomeDialog: Adapt dialog title
|
|
||||||
|
|
||||||
Use RHEL branding instead of the upstream GNOME XX one.
|
|
||||||
---
|
|
||||||
js/ui/welcomeDialog.js | 6 ++----
|
|
||||||
1 file changed, 2 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/js/ui/welcomeDialog.js b/js/ui/welcomeDialog.js
|
|
||||||
index 9d99f0035..783fd1108 100644
|
|
||||||
--- a/js/ui/welcomeDialog.js
|
|
||||||
+++ b/js/ui/welcomeDialog.js
|
|
||||||
@@ -1,9 +1,8 @@
|
|
||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
/* exported WelcomeDialog */
|
|
||||||
|
|
||||||
-const { Clutter, GObject, Shell, St } = imports.gi;
|
|
||||||
+const { Clutter, GLib, GObject, Shell, St } = imports.gi;
|
|
||||||
|
|
||||||
-const Config = imports.misc.config;
|
|
||||||
const Dialog = imports.ui.dialog;
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const ModalDialog = imports.ui.modalDialog;
|
|
||||||
@@ -32,8 +31,7 @@ class WelcomeDialog extends ModalDialog.ModalDialog {
|
|
||||||
}
|
|
||||||
|
|
||||||
_buildLayout() {
|
|
||||||
- const [majorVersion] = Config.PACKAGE_VERSION.split('.');
|
|
||||||
- const title = _('Welcome to GNOME %s').format(majorVersion);
|
|
||||||
+ const title = _('Welcome to %s').format(GLib.get_os_info('NAME'));
|
|
||||||
const description = _('If you want to learn your way around, check out the tour.');
|
|
||||||
const content = new Dialog.MessageDialogContent({ title, description });
|
|
||||||
|
|
||||||
--
|
|
||||||
2.33.1
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
|||||||
From a1d650ce2722fd154b047ce73fa23db205d823d2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
||||||
Date: Mon, 12 Dec 2022 13:04:11 +0100
|
|
||||||
Subject: [PATCH] window-tracker: Emit 'tracked-windows-changed' on title
|
|
||||||
changes
|
|
||||||
|
|
||||||
This means the screen share window view gets updated also when the title
|
|
||||||
of a window changes. This is important since it often changes shortly
|
|
||||||
after mapping, which would otherwise go unnoticed by
|
|
||||||
xdg-desktop-portal-gnome.
|
|
||||||
|
|
||||||
An example is launching Files and it showing up as 'Loading..', or
|
|
||||||
launching a terminal, and it not showing the proper title (current
|
|
||||||
directory), but some place holder that is never visible on the
|
|
||||||
application window.
|
|
||||||
|
|
||||||
Adding it to the window tracker instead of in introspect.js itself is
|
|
||||||
for convenience - there is no per window signal tracking there, and it
|
|
||||||
already listens to the signal emissions about changed windows.
|
|
||||||
|
|
||||||
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2578>
|
|
||||||
---
|
|
||||||
src/shell-window-tracker.c | 11 +++++++++++
|
|
||||||
1 file changed, 11 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/src/shell-window-tracker.c b/src/shell-window-tracker.c
|
|
||||||
index 991613ea3f..df357f81b7 100644
|
|
||||||
--- a/src/shell-window-tracker.c
|
|
||||||
+++ b/src/shell-window-tracker.c
|
|
||||||
@@ -524,6 +524,15 @@ on_wm_class_changed (MetaWindow *window,
|
|
||||||
tracked_window_changed (self, window);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void
|
|
||||||
+on_title_changed (MetaWindow *window,
|
|
||||||
+ GParamSpec *pspec,
|
|
||||||
+ gpointer user_data)
|
|
||||||
+{
|
|
||||||
+ ShellWindowTracker *self = SHELL_WINDOW_TRACKER (user_data);
|
|
||||||
+ tracked_window_changed (self, window);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void
|
|
||||||
on_gtk_application_id_changed (MetaWindow *window,
|
|
||||||
GParamSpec *pspec,
|
|
||||||
@@ -554,6 +563,7 @@ track_window (ShellWindowTracker *self,
|
|
||||||
g_hash_table_insert (self->window_to_app, window, app);
|
|
||||||
|
|
||||||
g_signal_connect (window, "notify::wm-class", G_CALLBACK (on_wm_class_changed), self);
|
|
||||||
+ g_signal_connect (window, "notify::title", G_CALLBACK (on_title_changed), self);
|
|
||||||
g_signal_connect (window, "notify::gtk-application-id", G_CALLBACK (on_gtk_application_id_changed), self);
|
|
||||||
g_signal_connect (window, "unmanaged", G_CALLBACK (on_window_unmanaged), self);
|
|
||||||
|
|
||||||
@@ -586,6 +596,7 @@ disassociate_window (ShellWindowTracker *self,
|
|
||||||
|
|
||||||
_shell_app_remove_window (app, window);
|
|
||||||
g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_wm_class_changed), self);
|
|
||||||
+ g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_title_changed), self);
|
|
||||||
g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_gtk_application_id_changed), self);
|
|
||||||
g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_window_unmanaged), self);
|
|
||||||
|
|
||||||
--
|
|
||||||
2.38.1
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
|||||||
From e3823964957ba4dcc86b21db09b280b9299bc8cc Mon Sep 17 00:00:00 2001
|
|
||||||
From: Carlos Garnacho <carlosg@gnome.org>
|
|
||||||
Date: Fri, 10 Feb 2023 15:07:50 +0100
|
|
||||||
Subject: [PATCH] window-tracker: Only emit ::tracked-windows-changed on title
|
|
||||||
changes
|
|
||||||
|
|
||||||
Since commit a1d650ce27, window title changes are listened for in the
|
|
||||||
ShellWindowTracker in order to emit ::tracked-windows-changed when
|
|
||||||
there are window title changes.
|
|
||||||
|
|
||||||
The rest of the things that happen in between (removing the window
|
|
||||||
from a ShellApp, possibly have it destroyed, and possibly creating a
|
|
||||||
new ShellApp to re-insert the window) are superfluous and even result
|
|
||||||
in the altTab switcher popup ending up confused about the applications
|
|
||||||
available.
|
|
||||||
|
|
||||||
Only emit the signal so changes can be followed on D-Bus, but avoid
|
|
||||||
the ShellApp fiddling otherwise.
|
|
||||||
|
|
||||||
Fixes: a1d650ce27 - window-tracker: Emit 'tracked-windows-changed' on title changes
|
|
||||||
|
|
||||||
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6385
|
|
||||||
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2634>
|
|
||||||
(cherry picked from commit 41c91c7a3b7f186720a0a518ef2211cb744421f3)
|
|
||||||
---
|
|
||||||
src/shell-window-tracker.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/src/shell-window-tracker.c b/src/shell-window-tracker.c
|
|
||||||
index bc14040d9b..01143dfd7f 100644
|
|
||||||
--- a/src/shell-window-tracker.c
|
|
||||||
+++ b/src/shell-window-tracker.c
|
|
||||||
@@ -524,7 +524,7 @@ on_title_changed (MetaWindow *window,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
ShellWindowTracker *self = SHELL_WINDOW_TRACKER (user_data);
|
|
||||||
- tracked_window_changed (self, window);
|
|
||||||
+ g_signal_emit (self, signals[TRACKED_WINDOWS_CHANGED], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
--
|
|
||||||
2.31.1
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
|||||||
From 1cad6c8d47fb9f0b17a2c47f93e5f923d1cb32c3 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
||||||
Date: Thu, 7 Mar 2024 18:22:32 +0100
|
|
||||||
Subject: [PATCH] windowPreview: Override with window icon if available
|
|
||||||
|
|
||||||
---
|
|
||||||
js/ui/windowPreview.js | 16 ++++++++++++++++
|
|
||||||
1 file changed, 16 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/js/ui/windowPreview.js b/js/ui/windowPreview.js
|
|
||||||
index e67ec9ec0f..db325258b4 100644
|
|
||||||
--- a/js/ui/windowPreview.js
|
|
||||||
+++ b/js/ui/windowPreview.js
|
|
||||||
@@ -123,6 +123,12 @@ var WindowPreview = GObject.registerClass({
|
|
||||||
const tracker = Shell.WindowTracker.get_default();
|
|
||||||
const app = tracker.get_window_app(this.metaWindow);
|
|
||||||
this._icon = app.create_icon_texture(ICON_SIZE);
|
|
||||||
+ // Override with window icon if available
|
|
||||||
+ if (this._hasWindowIcon()) {
|
|
||||||
+ const textureCache = St.TextureCache.get_default();
|
|
||||||
+ this._icon.gicon = textureCache.bind_cairo_surface_property(
|
|
||||||
+ this.metaWindow, 'icon');
|
|
||||||
+ }
|
|
||||||
this._icon.add_style_class_name('icon-dropshadow');
|
|
||||||
this._icon.set({
|
|
||||||
reactive: true,
|
|
||||||
@@ -226,6 +232,16 @@ var WindowPreview = GObject.registerClass({
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
+ _hasWindowIcon() {
|
|
||||||
+ // HACK: GI cannot handle CairoSurface, so this
|
|
||||||
+ // will throw if the icon property is non-null
|
|
||||||
+ try {
|
|
||||||
+ return this.metaWindow.icon !== null;
|
|
||||||
+ } catch (e) {
|
|
||||||
+ return true;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
_updateIconScale() {
|
|
||||||
const { ControlsState } = OverviewControls;
|
|
||||||
const { currentState, initialState, finalState } =
|
|
||||||
--
|
|
||||||
2.44.0
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
From 9115f6e7962b97c3ee2fbef7b195b7116e62c070 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Carlos Garnacho <carlosg@gnome.org>
|
||||||
|
Date: Fri, 13 Dec 2019 18:14:51 +0100
|
||||||
|
Subject: [PATCH] workspace: Pass device to startDrag()
|
||||||
|
|
||||||
|
This is necessary to make DnD operations work from tablet devices on
|
||||||
|
wayland, as it's not the same onscreen pointer sprite than mice. Fixes
|
||||||
|
window DnD in the overview on tablet devices, no longer having them stick
|
||||||
|
to the wrong pointer.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/897
|
||||||
|
---
|
||||||
|
js/ui/workspace.js | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/workspace.js b/js/ui/workspace.js
|
||||||
|
index 1e9bedc28..d470f7f40 100644
|
||||||
|
--- a/js/ui/workspace.js
|
||||||
|
+++ b/js/ui/workspace.js
|
||||||
|
@@ -431,7 +431,7 @@ var WindowClone = GObject.registerClass({
|
||||||
|
return;
|
||||||
|
let [x, y] = action.get_coords();
|
||||||
|
action.release();
|
||||||
|
- this._draggable.startDrag(x, y, global.get_current_time(), this._dragTouchSequence);
|
||||||
|
+ this._draggable.startDrag(x, y, global.get_current_time(), this._dragTouchSequence, event.get_device());
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.emit('show-chrome');
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
|
|
@ -0,0 +1,37 @@
|
|||||||
|
From b69b404118852f7955f60d1814f5e19ad61ce449 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Fri, 12 Jul 2019 03:26:51 +0000
|
||||||
|
Subject: [PATCH] workspacesView: Work around spurious allocation changes
|
||||||
|
|
||||||
|
For some reason, people are still seeing those after commit d5ebd8c8.
|
||||||
|
While this is something we really should figure out, we can work around
|
||||||
|
the issue by keeping the view actors hidden until the update is complete.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1065
|
||||||
|
---
|
||||||
|
js/ui/workspacesView.js | 5 +++++
|
||||||
|
1 file changed, 5 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js
|
||||||
|
index 069937d5a..e302296a6 100644
|
||||||
|
--- a/js/ui/workspacesView.js
|
||||||
|
+++ b/js/ui/workspacesView.js
|
||||||
|
@@ -666,10 +666,15 @@ var WorkspacesDisplay = class {
|
||||||
|
this._scrollValueChanged.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // HACK: Avoid spurious allocation changes while updating views
|
||||||
|
+ view.actor.hide();
|
||||||
|
+
|
||||||
|
this._workspacesViews.push(view);
|
||||||
|
Main.layoutManager.overviewGroup.add_actor(view.actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ this._workspacesViews.forEach(v => v.actor.show());
|
||||||
|
+
|
||||||
|
this._updateWorkspacesFullGeometry();
|
||||||
|
this._updateWorkspacesActualGeometry();
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
From f27c4224aa96975ae44641612f5fff3772f5c294 Mon Sep 17 00:00:00 2001
|
||||||
|
From: rpm-build <rpm-build>
|
||||||
|
Date: Mon, 22 Aug 2022 13:06:05 +0200
|
||||||
|
Subject: [PATCH] [PATCH 2/4] background: rebuild background, not just
|
||||||
|
animation on resume
|
||||||
|
|
||||||
|
Previously, we would only refresh the animation on resume
|
||||||
|
(to handle clock skew).
|
||||||
|
|
||||||
|
But we actually need to rebuild the background, too, on nvidia,
|
||||||
|
so we should just do a full background change.
|
||||||
|
---
|
||||||
|
js/ui/background.js | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/background.js b/js/ui/background.js
|
||||||
|
index 2a404ae..dd11e3e 100644
|
||||||
|
--- a/js/ui/background.js
|
||||||
|
+++ b/js/ui/background.js
|
||||||
|
@@ -254,7 +254,7 @@ var Background = class Background {
|
||||||
|
(lm, aboutToSuspend) => {
|
||||||
|
if (aboutToSuspend)
|
||||||
|
return;
|
||||||
|
- this._refreshAnimation();
|
||||||
|
+ this.emit('changed');
|
||||||
|
});
|
||||||
|
|
||||||
|
this._settingsChangedSignalId =
|
||||||
|
--
|
||||||
|
2.35.3
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
From 189add05c07fe9d9bed6c1399b30e51a4a934bd3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Mon, 2 Mar 2020 13:46:04 +0100
|
||||||
|
Subject: [PATCH 2/6] environment: Fix date conversion
|
||||||
|
|
||||||
|
This is a regression from commit 06b690ff21204:
|
||||||
|
|
||||||
|
GLib.DateTime.new() expects the full four-digit year, so passing
|
||||||
|
the abbreviated year from Date() will result in a bogus datetime.
|
||||||
|
|
||||||
|
Today is *not* Saturday March 2nd, 120 ...
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1061
|
||||||
|
---
|
||||||
|
js/ui/environment.js | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/environment.js b/js/ui/environment.js
|
||||||
|
index f3f2d17c7..a9cc16dee 100644
|
||||||
|
--- a/js/ui/environment.js
|
||||||
|
+++ b/js/ui/environment.js
|
||||||
|
@@ -126,7 +126,7 @@ function init() {
|
||||||
|
_localTimeZone = GLib.TimeZone.new_local();
|
||||||
|
|
||||||
|
let dt = GLib.DateTime.new(_localTimeZone,
|
||||||
|
- this.getYear(),
|
||||||
|
+ this.getFullYear(),
|
||||||
|
this.getMonth() + 1,
|
||||||
|
this.getDate(),
|
||||||
|
this.getHours(),
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -0,0 +1,237 @@
|
|||||||
|
From b70cf463e08bff43b242b851fc7c79244f54e76b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Tue, 10 Aug 2021 13:25:57 -0400
|
||||||
|
Subject: [PATCH 2/4] extensionSystem: Get rid of _enabled boolean optimization
|
||||||
|
|
||||||
|
At the moment a session mode either allows extensions or it doesn't.
|
||||||
|
If it allows extensions, then the entire available list of
|
||||||
|
configured extensions get enabled as soon as the session mode is
|
||||||
|
entered.
|
||||||
|
|
||||||
|
Since enabling or disabling extensions is an all or nothing situation,
|
||||||
|
the code tracks whether extensions are already enabled when entering
|
||||||
|
the session mode, and if so, avoids iterating through the extension list
|
||||||
|
needlessly. It does this using a boolean named _enabled.
|
||||||
|
|
||||||
|
In the future, the extensions themselves will be given some say on
|
||||||
|
whether or not they should be enabled in a given session mode. This
|
||||||
|
means, the configured extension list may contain extensions that
|
||||||
|
shouldn't be enabled for a given session mode, and the _enabled boolean
|
||||||
|
will no longer be appropriated.
|
||||||
|
|
||||||
|
This commit drops the _enabled boolean optimization.
|
||||||
|
---
|
||||||
|
js/ui/extensionSystem.js | 13 -------------
|
||||||
|
1 file changed, 13 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
|
||||||
|
index 77929f2a6..05630ed54 100644
|
||||||
|
--- a/js/ui/extensionSystem.js
|
||||||
|
+++ b/js/ui/extensionSystem.js
|
||||||
|
@@ -1,53 +1,52 @@
|
||||||
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||||
|
|
||||||
|
const { GLib, Gio, GObject, St } = imports.gi;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
|
||||||
|
const ExtensionDownloader = imports.ui.extensionDownloader;
|
||||||
|
const ExtensionUtils = imports.misc.extensionUtils;
|
||||||
|
const FileUtils = imports.misc.fileUtils;
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const MessageTray = imports.ui.messageTray;
|
||||||
|
|
||||||
|
const { ExtensionState, ExtensionType } = ExtensionUtils;
|
||||||
|
|
||||||
|
const ENABLED_EXTENSIONS_KEY = 'enabled-extensions';
|
||||||
|
const DISABLE_USER_EXTENSIONS_KEY = 'disable-user-extensions';
|
||||||
|
const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validation';
|
||||||
|
|
||||||
|
const UPDATE_CHECK_TIMEOUT = 24 * 60 * 60; // 1 day in seconds
|
||||||
|
|
||||||
|
var ExtensionManager = class {
|
||||||
|
constructor() {
|
||||||
|
this._initted = false;
|
||||||
|
- this._enabled = false;
|
||||||
|
this._updateNotified = false;
|
||||||
|
|
||||||
|
this._extensions = new Map();
|
||||||
|
this._enabledExtensions = [];
|
||||||
|
this._extensionOrder = [];
|
||||||
|
|
||||||
|
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this._installExtensionUpdates();
|
||||||
|
this._sessionUpdated();
|
||||||
|
|
||||||
|
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, UPDATE_CHECK_TIMEOUT, () => {
|
||||||
|
ExtensionDownloader.checkForUpdates();
|
||||||
|
return GLib.SOURCE_CONTINUE;
|
||||||
|
});
|
||||||
|
ExtensionDownloader.checkForUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
|
lookup(uuid) {
|
||||||
|
return this._extensions.get(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
getUuids() {
|
||||||
|
return [...this._extensions.keys()];
|
||||||
|
}
|
||||||
|
|
||||||
|
_callExtensionDisable(uuid) {
|
||||||
|
let extension = this.lookup(uuid);
|
||||||
|
@@ -375,63 +374,60 @@ var ExtensionManager = class {
|
||||||
|
let hasError =
|
||||||
|
extension.state == ExtensionState.ERROR ||
|
||||||
|
extension.state == ExtensionState.OUT_OF_DATE;
|
||||||
|
|
||||||
|
let isMode = this._getModeExtensions().includes(extension.uuid);
|
||||||
|
let modeOnly = global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY);
|
||||||
|
|
||||||
|
extension.canChange =
|
||||||
|
!hasError &&
|
||||||
|
global.settings.is_writable(ENABLED_EXTENSIONS_KEY) &&
|
||||||
|
(isMode || !modeOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getEnabledExtensions() {
|
||||||
|
let extensions = this._getModeExtensions();
|
||||||
|
|
||||||
|
if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY))
|
||||||
|
return extensions;
|
||||||
|
|
||||||
|
return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY));
|
||||||
|
}
|
||||||
|
|
||||||
|
_onUserExtensionsEnabledChanged() {
|
||||||
|
this._onEnabledExtensionsChanged();
|
||||||
|
this._onSettingsWritableChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
_onEnabledExtensionsChanged() {
|
||||||
|
let newEnabledExtensions = this._getEnabledExtensions();
|
||||||
|
|
||||||
|
- if (!this._enabled)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
// Find and enable all the newly enabled extensions: UUIDs found in the
|
||||||
|
// new setting, but not in the old one.
|
||||||
|
newEnabledExtensions.filter(
|
||||||
|
uuid => !this._enabledExtensions.includes(uuid)
|
||||||
|
).forEach(uuid => {
|
||||||
|
this._callExtensionEnable(uuid);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Find and disable all the newly disabled extensions: UUIDs found in the
|
||||||
|
// old setting, but not in the new one.
|
||||||
|
this._enabledExtensions.filter(
|
||||||
|
item => !newEnabledExtensions.includes(item)
|
||||||
|
).forEach(uuid => {
|
||||||
|
this._callExtensionDisable(uuid);
|
||||||
|
});
|
||||||
|
|
||||||
|
this._enabledExtensions = newEnabledExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
_onSettingsWritableChanged() {
|
||||||
|
for (let extension of this._extensions.values()) {
|
||||||
|
this._updateCanChange(extension);
|
||||||
|
this.emit('extension-state-changed', extension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_onVersionValidationChanged() {
|
||||||
|
// we want to reload all extensions, but only enable
|
||||||
|
// extensions when allowed by the sessionMode, so
|
||||||
|
// temporarily disable them all
|
||||||
|
@@ -482,85 +478,76 @@ var ExtensionManager = class {
|
||||||
|
|
||||||
|
this._enabledExtensions = this._getEnabledExtensions();
|
||||||
|
|
||||||
|
let perUserDir = Gio.File.new_for_path(global.userdatadir);
|
||||||
|
FileUtils.collectFromDatadirs('extensions', true, (dir, info) => {
|
||||||
|
let fileType = info.get_file_type();
|
||||||
|
if (fileType != Gio.FileType.DIRECTORY)
|
||||||
|
return;
|
||||||
|
let uuid = info.get_name();
|
||||||
|
let existing = this.lookup(uuid);
|
||||||
|
if (existing) {
|
||||||
|
log(`Extension ${uuid} already installed in ${existing.path}. ${dir.get_path()} will not be loaded`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let extension;
|
||||||
|
let type = dir.has_prefix(perUserDir)
|
||||||
|
? ExtensionType.PER_USER
|
||||||
|
: ExtensionType.SYSTEM;
|
||||||
|
try {
|
||||||
|
extension = this.createExtensionObject(uuid, dir, type);
|
||||||
|
} catch (e) {
|
||||||
|
logError(e, `Could not load extension ${uuid}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.loadExtension(extension);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_enableAllExtensions() {
|
||||||
|
- if (this._enabled)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
if (!this._initted) {
|
||||||
|
this._loadExtensions();
|
||||||
|
this._initted = true;
|
||||||
|
} else {
|
||||||
|
this._enabledExtensions.forEach(uuid => {
|
||||||
|
this._callExtensionEnable(uuid);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
- this._enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_disableAllExtensions() {
|
||||||
|
- if (!this._enabled)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
if (this._initted) {
|
||||||
|
this._extensionOrder.slice().reverse().forEach(uuid => {
|
||||||
|
this._callExtensionDisable(uuid);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- this._enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_sessionUpdated() {
|
||||||
|
// For now sessionMode.allowExtensions controls extensions from both the
|
||||||
|
// 'enabled-extensions' preference and the sessionMode.enabledExtensions
|
||||||
|
// property; it might make sense to make enabledExtensions independent
|
||||||
|
// from allowExtensions in the future
|
||||||
|
if (Main.sessionMode.allowExtensions) {
|
||||||
|
// Take care of added or removed sessionMode extensions
|
||||||
|
this._onEnabledExtensionsChanged();
|
||||||
|
this._enableAllExtensions();
|
||||||
|
} else {
|
||||||
|
this._disableAllExtensions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Signals.addSignalMethods(ExtensionManager.prototype);
|
||||||
|
|
||||||
|
class ExtensionUpdateSource extends MessageTray.Source {
|
||||||
|
constructor() {
|
||||||
|
const appSys = Shell.AppSystem.get_default();
|
||||||
|
this._app = appSys.lookup_app('gnome-shell-extension-prefs.desktop');
|
||||||
|
|
||||||
|
super(this._app.get_name());
|
||||||
|
}
|
||||||
|
|
||||||
|
getIcon() {
|
||||||
|
return this._app.app_info.get_icon();
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
@ -0,0 +1,267 @@
|
|||||||
|
From c3ab03f8721ea96df6ac91c0393ed13ba750ab7e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Mon, 17 Jul 2017 16:48:03 -0400
|
||||||
|
Subject: [PATCH 2/2] gdmUtil: enable support for GDM's ChoiceList PAM
|
||||||
|
extension
|
||||||
|
|
||||||
|
This commit hooks up support for GDM's ChoiceList PAM extension.
|
||||||
|
---
|
||||||
|
js/gdm/authPrompt.js | 74 ++++++++++++++++++++++++++++++++++++++++++-
|
||||||
|
js/gdm/loginDialog.js | 5 +++
|
||||||
|
js/gdm/util.js | 28 ++++++++++++++++
|
||||||
|
js/ui/unlockDialog.js | 9 +++++-
|
||||||
|
4 files changed, 114 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js
|
||||||
|
index cf77b3f26..71069e93b 100644
|
||||||
|
--- a/js/gdm/authPrompt.js
|
||||||
|
+++ b/js/gdm/authPrompt.js
|
||||||
|
@@ -4,6 +4,7 @@ const { Clutter, GLib, Pango, Shell, St } = imports.gi;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
|
||||||
|
const Animation = imports.ui.animation;
|
||||||
|
+const AuthList = imports.gdm.authList;
|
||||||
|
const Batch = imports.gdm.batch;
|
||||||
|
const GdmUtil = imports.gdm.util;
|
||||||
|
const Meta = imports.gi.Meta;
|
||||||
|
@@ -54,6 +55,7 @@ var AuthPrompt = class {
|
||||||
|
|
||||||
|
this._userVerifier.connect('ask-question', this._onAskQuestion.bind(this));
|
||||||
|
this._userVerifier.connect('show-message', this._onShowMessage.bind(this));
|
||||||
|
+ this._userVerifier.connect('show-choice-list', this._onShowChoiceList.bind(this));
|
||||||
|
this._userVerifier.connect('verification-failed', this._onVerificationFailed.bind(this));
|
||||||
|
this._userVerifier.connect('verification-complete', this._onVerificationComplete.bind(this));
|
||||||
|
this._userVerifier.connect('reset', this._onReset.bind(this));
|
||||||
|
@@ -116,6 +118,28 @@ var AuthPrompt = class {
|
||||||
|
|
||||||
|
this.actor.add(this._timedLoginIndicator);
|
||||||
|
|
||||||
|
+ this._authList = new AuthList.AuthList();
|
||||||
|
+ this._authList.connect('activate', (list, key) => {
|
||||||
|
+ this._authList.actor.reactive = false;
|
||||||
|
+ Tweener.addTween(this._authList.actor,
|
||||||
|
+ { opacity: 0,
|
||||||
|
+ time: MESSAGE_FADE_OUT_ANIMATION_TIME,
|
||||||
|
+ transition: 'easeOutQuad',
|
||||||
|
+ onComplete: () => {
|
||||||
|
+ this._authList.clear();
|
||||||
|
+ this._authList.actor.hide();
|
||||||
|
+ this._userVerifier.selectChoice(this._queryingService, key);
|
||||||
|
+
|
||||||
|
+ }
|
||||||
|
+ });
|
||||||
|
+ });
|
||||||
|
+ this._authList.actor.hide();
|
||||||
|
+ this.actor.add(this._authList.actor,
|
||||||
|
+ { expand: true,
|
||||||
|
+ x_fill: true,
|
||||||
|
+ y_fill: false,
|
||||||
|
+ x_align: St.Align.START });
|
||||||
|
+
|
||||||
|
this._message = new St.Label({ opacity: 0,
|
||||||
|
styleClass: 'login-dialog-message' });
|
||||||
|
this._message.clutter_text.line_wrap = true;
|
||||||
|
@@ -258,6 +282,21 @@ var AuthPrompt = class {
|
||||||
|
this.emit('prompted');
|
||||||
|
}
|
||||||
|
|
||||||
|
+ _onShowChoiceList(userVerifier, serviceName, promptMessage, choiceList) {
|
||||||
|
+ if (this._queryingService)
|
||||||
|
+ this.clear();
|
||||||
|
+
|
||||||
|
+ this._queryingService = serviceName;
|
||||||
|
+
|
||||||
|
+ if (this._preemptiveAnswer)
|
||||||
|
+ this._preemptiveAnswer = null;
|
||||||
|
+
|
||||||
|
+ this.nextButton.label = _("Next");
|
||||||
|
+ this.setChoiceList(promptMessage, choiceList);
|
||||||
|
+ this.updateSensitivity(true);
|
||||||
|
+ this.emit('prompted');
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
_onOVirtUserAuthenticated() {
|
||||||
|
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
|
||||||
|
this.reset();
|
||||||
|
@@ -386,6 +425,8 @@ var AuthPrompt = class {
|
||||||
|
clear() {
|
||||||
|
this._entry.text = '';
|
||||||
|
this.stopSpinning();
|
||||||
|
+ this._authList.clear();
|
||||||
|
+ this._authList.actor.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
setPasswordChar(passwordChar) {
|
||||||
|
@@ -401,12 +442,42 @@ var AuthPrompt = class {
|
||||||
|
|
||||||
|
this._label.set_text(question);
|
||||||
|
|
||||||
|
+ this._authList.actor.hide();
|
||||||
|
this._label.show();
|
||||||
|
this._entry.show();
|
||||||
|
|
||||||
|
this._entry.grab_key_focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ _fadeInChoiceList() {
|
||||||
|
+ this._authList.actor.opacity = 0;
|
||||||
|
+ this._authList.actor.show();
|
||||||
|
+ this._authList.actor.reactive = false;
|
||||||
|
+ Tweener.addTween(this._authList.actor,
|
||||||
|
+ { opacity: 255,
|
||||||
|
+ time: MESSAGE_FADE_OUT_ANIMATION_TIME,
|
||||||
|
+ transition: 'easeOutQuad',
|
||||||
|
+ onComplete: () => {
|
||||||
|
+ this._authList.actor.reactive = true;
|
||||||
|
+ }
|
||||||
|
+ });
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ setChoiceList(promptMessage, choiceList) {
|
||||||
|
+ this._authList.clear();
|
||||||
|
+ this._authList.label.text = promptMessage;
|
||||||
|
+ for (let key in choiceList) {
|
||||||
|
+ let text = choiceList[key];
|
||||||
|
+ this._authList.addItem(key, text);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ this._label.hide();
|
||||||
|
+ this._entry.hide();
|
||||||
|
+ if (this._message.text == "")
|
||||||
|
+ this._message.hide();
|
||||||
|
+ this._fadeInChoiceList();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
getAnswer() {
|
||||||
|
let text;
|
||||||
|
|
||||||
|
@@ -442,6 +513,7 @@ var AuthPrompt = class {
|
||||||
|
else
|
||||||
|
this._message.remove_style_class_name('login-dialog-message-hint');
|
||||||
|
|
||||||
|
+ this._message.show();
|
||||||
|
if (message) {
|
||||||
|
Tweener.removeTweens(this._message);
|
||||||
|
this._message.text = message;
|
||||||
|
@@ -457,7 +529,7 @@ var AuthPrompt = class {
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSensitivity(sensitive) {
|
||||||
|
- this._updateNextButtonSensitivity(sensitive && (this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING));
|
||||||
|
+ this._updateNextButtonSensitivity(sensitive && !this._authList.actor.visible && (this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING));
|
||||||
|
this._entry.reactive = sensitive;
|
||||||
|
this._entry.clutter_text.editable = sensitive;
|
||||||
|
}
|
||||||
|
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
|
||||||
|
index 9aaa013d8..942f5a0e5 100644
|
||||||
|
--- a/js/gdm/loginDialog.js
|
||||||
|
+++ b/js/gdm/loginDialog.js
|
||||||
|
@@ -406,6 +406,11 @@ var LoginDialog = GObject.registerClass({
|
||||||
|
this._userManager = AccountsService.UserManager.get_default()
|
||||||
|
this._gdmClient = new Gdm.Client();
|
||||||
|
|
||||||
|
+ try {
|
||||||
|
+ this._gdmClient.set_enabled_extensions([Gdm.UserVerifierChoiceList.interface_info().name]);
|
||||||
|
+ } catch(e) {
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
this._settings = new Gio.Settings({ schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA });
|
||||||
|
|
||||||
|
this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY,
|
||||||
|
diff --git a/js/gdm/util.js b/js/gdm/util.js
|
||||||
|
index 6e940d2ab..9e249139d 100644
|
||||||
|
--- a/js/gdm/util.js
|
||||||
|
+++ b/js/gdm/util.js
|
||||||
|
@@ -192,6 +192,10 @@ var ShellUserVerifier = class {
|
||||||
|
if (this._userVerifier) {
|
||||||
|
this._userVerifier.run_dispose();
|
||||||
|
this._userVerifier = null;
|
||||||
|
+ if (this._userVerifierChoiceList) {
|
||||||
|
+ this._userVerifierChoiceList.run_dispose();
|
||||||
|
+ this._userVerifierChoiceList = null;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -219,6 +223,10 @@ var ShellUserVerifier = class {
|
||||||
|
this._oVirtCredentialsManager = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ selectChoice(serviceName, key) {
|
||||||
|
+ this._userVerifierChoiceList.call_select_choice(serviceName, key, this._cancellable, null);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
answerQuery(serviceName, answer) {
|
||||||
|
if (!this.hasPendingMessages) {
|
||||||
|
this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
|
||||||
|
@@ -362,6 +370,11 @@ var ShellUserVerifier = class {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (client.get_user_verifier_choice_list)
|
||||||
|
+ this._userVerifierChoiceList = client.get_user_verifier_choice_list();
|
||||||
|
+ else
|
||||||
|
+ this._userVerifierChoiceList = null;
|
||||||
|
+
|
||||||
|
this.reauthenticating = true;
|
||||||
|
this._connectSignals();
|
||||||
|
this._beginVerification();
|
||||||
|
@@ -379,6 +392,11 @@ var ShellUserVerifier = class {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (client.get_user_verifier_choice_list)
|
||||||
|
+ this._userVerifierChoiceList = client.get_user_verifier_choice_list();
|
||||||
|
+ else
|
||||||
|
+ this._userVerifierChoiceList = null;
|
||||||
|
+
|
||||||
|
this._connectSignals();
|
||||||
|
this._beginVerification();
|
||||||
|
this._hold.release();
|
||||||
|
@@ -392,6 +410,9 @@ var ShellUserVerifier = class {
|
||||||
|
this._userVerifier.connect('conversation-stopped', this._onConversationStopped.bind(this));
|
||||||
|
this._userVerifier.connect('reset', this._onReset.bind(this));
|
||||||
|
this._userVerifier.connect('verification-complete', this._onVerificationComplete.bind(this));
|
||||||
|
+
|
||||||
|
+ if (this._userVerifierChoiceList)
|
||||||
|
+ this._userVerifierChoiceList.connect('choice-query', this._onChoiceListQuery.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
_getForegroundService() {
|
||||||
|
@@ -468,6 +489,13 @@ var ShellUserVerifier = class {
|
||||||
|
this._startService(FINGERPRINT_SERVICE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ _onChoiceListQuery(client, serviceName, promptMessage, list) {
|
||||||
|
+ if (!this.serviceIsForeground(serviceName))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ this.emit('show-choice-list', serviceName, promptMessage, list.deep_unpack());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
_onInfo(client, serviceName, info) {
|
||||||
|
if (this.serviceIsForeground(serviceName)) {
|
||||||
|
this._queueMessage(info, MessageType.INFO);
|
||||||
|
diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js
|
||||||
|
index 5c9d46021..4b0470f4b 100644
|
||||||
|
--- a/js/ui/unlockDialog.js
|
||||||
|
+++ b/js/ui/unlockDialog.js
|
||||||
|
@@ -33,7 +33,14 @@ var UnlockDialog = class {
|
||||||
|
y_expand: true });
|
||||||
|
this.actor.add_child(this._promptBox);
|
||||||
|
|
||||||
|
- this._authPrompt = new AuthPrompt.AuthPrompt(new Gdm.Client(), AuthPrompt.AuthPromptMode.UNLOCK_ONLY);
|
||||||
|
+ this._gdmClient = new Gdm.Client();
|
||||||
|
+
|
||||||
|
+ try {
|
||||||
|
+ this._gdmClient.set_enabled_extensions([Gdm.UserVerifierChoiceList.interface_info().name]);
|
||||||
|
+ } catch(e) {
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ this._authPrompt = new AuthPrompt.AuthPrompt(this._gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_ONLY);
|
||||||
|
this._authPrompt.connect('failed', this._fail.bind(this));
|
||||||
|
this._authPrompt.connect('cancelled', this._fail.bind(this));
|
||||||
|
this._authPrompt.connect('reset', this._onReset.bind(this));
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -0,0 +1,92 @@
|
|||||||
|
From de7df6c7248c39d7cce1c70485df72a398da92a3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Wed, 21 Aug 2019 15:48:33 -0400
|
||||||
|
Subject: [PATCH 2/4] shellEntry: Give password menu item text when it's
|
||||||
|
created
|
||||||
|
|
||||||
|
At the moment, the "Show Text" menu item is only given its text
|
||||||
|
at the time the menu is opened. This is because the text might
|
||||||
|
be "Hide Text" or "Show Text" depending on state, so the text
|
||||||
|
is set up lazily.
|
||||||
|
|
||||||
|
That behavior means the menu item can't get added after the
|
||||||
|
menu is already shown, which is something we'ree going to need
|
||||||
|
in the future to support lockdown of the "Show Text" item.
|
||||||
|
|
||||||
|
This commit ensures the menu item is given text when it's first
|
||||||
|
created, in addition to when the menu is opened.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/687
|
||||||
|
---
|
||||||
|
js/ui/shellEntry.js | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js
|
||||||
|
index cac4ec9c2..603a9c64a 100644
|
||||||
|
--- a/js/ui/shellEntry.js
|
||||||
|
+++ b/js/ui/shellEntry.js
|
||||||
|
@@ -11,60 +11,61 @@ const Tweener = imports.ui.tweener;
|
||||||
|
var EntryMenu = class extends PopupMenu.PopupMenu {
|
||||||
|
constructor(entry) {
|
||||||
|
super(entry, 0, St.Side.TOP);
|
||||||
|
|
||||||
|
this._entry = entry;
|
||||||
|
this._clipboard = St.Clipboard.get_default();
|
||||||
|
|
||||||
|
// Populate menu
|
||||||
|
let item;
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("Copy"));
|
||||||
|
item.connect('activate', this._onCopyActivated.bind(this));
|
||||||
|
this.addMenuItem(item);
|
||||||
|
this._copyItem = item;
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("Paste"));
|
||||||
|
item.connect('activate', this._onPasteActivated.bind(this));
|
||||||
|
this.addMenuItem(item);
|
||||||
|
this._pasteItem = item;
|
||||||
|
|
||||||
|
this._passwordItem = null;
|
||||||
|
|
||||||
|
Main.uiGroup.add_actor(this.actor);
|
||||||
|
this.actor.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
_makePasswordItem() {
|
||||||
|
let item = new PopupMenu.PopupMenuItem('');
|
||||||
|
item.connect('activate', this._onPasswordActivated.bind(this));
|
||||||
|
this.addMenuItem(item);
|
||||||
|
this._passwordItem = item;
|
||||||
|
+ this._updatePasswordItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
get isPassword() {
|
||||||
|
return this._entry.input_purpose == Clutter.InputContentPurpose.PASSWORD;
|
||||||
|
}
|
||||||
|
|
||||||
|
set isPassword(v) {
|
||||||
|
if (v == this.isPassword)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (v) {
|
||||||
|
this._makePasswordItem();
|
||||||
|
this._entry.input_purpose = Clutter.InputContentPurpose.PASSWORD;
|
||||||
|
} else {
|
||||||
|
this._passwordItem.destroy();
|
||||||
|
this._passwordItem = null;
|
||||||
|
this._entry.input_purpose = Clutter.InputContentPurpose.NORMAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open(animate) {
|
||||||
|
this._updatePasteItem();
|
||||||
|
this._updateCopyItem();
|
||||||
|
if (this._passwordItem)
|
||||||
|
this._updatePasswordItem();
|
||||||
|
|
||||||
|
super.open(animate);
|
||||||
|
this._entry.add_style_pseudo_class('focus');
|
||||||
|
|
||||||
|
let direction = St.DirectionType.TAB_FORWARD;
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
@ -0,0 +1,393 @@
|
|||||||
|
From 7300ae2eac743fa06f40f6459ac8fbf739ab28ea Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Tue, 10 Aug 2021 15:03:50 -0400
|
||||||
|
Subject: [PATCH 3/4] extensionSystem: Allow extensions to run on the login
|
||||||
|
screen
|
||||||
|
|
||||||
|
At the moment it's not realy possible to extend the login screen to do
|
||||||
|
things it doesn't have built-in support for. This means in order
|
||||||
|
to support niche use cases, those cases have to change the main
|
||||||
|
code base. For instance, oVirt and Vmware deployments want to be able
|
||||||
|
to automaticaly log in guest VMs when a user pre-authenticates through a
|
||||||
|
console on a management host. To support those use cases, we added
|
||||||
|
code to the login screen directly, even though most machines will never
|
||||||
|
be associated with oVirt or Vmware management hosts.
|
||||||
|
|
||||||
|
We also get requests from e.g. government users that need certain features
|
||||||
|
at the login screen that wouldn't get used much outside of government
|
||||||
|
deployments. For instance, we've gotten requests that a machine contains
|
||||||
|
prominently displays that it has "Top Secret" information.
|
||||||
|
|
||||||
|
All of these use cases seem like they would better handled via
|
||||||
|
extensions that could be installed in the specific deployments. The
|
||||||
|
problem is extensions only run in the user session, and get
|
||||||
|
disabled at the login screen automatically.
|
||||||
|
|
||||||
|
This commit changes that. Now extensions can specify in their metadata
|
||||||
|
via a new sessionModes property, which modes that want to run in. For
|
||||||
|
backward compatibility, if an extension doesn't specify which session
|
||||||
|
modes it works in, its assumed the extension only works in the user
|
||||||
|
session.
|
||||||
|
---
|
||||||
|
js/ui/extensionSystem.js | 43 ++++++++++++++++++++++++++++++++++++----
|
||||||
|
1 file changed, 39 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
|
||||||
|
index 05630ed54..dfe82821e 100644
|
||||||
|
--- a/js/ui/extensionSystem.js
|
||||||
|
+++ b/js/ui/extensionSystem.js
|
||||||
|
@@ -21,119 +21,147 @@ var ExtensionManager = class {
|
||||||
|
constructor() {
|
||||||
|
this._initted = false;
|
||||||
|
this._updateNotified = false;
|
||||||
|
|
||||||
|
this._extensions = new Map();
|
||||||
|
this._enabledExtensions = [];
|
||||||
|
this._extensionOrder = [];
|
||||||
|
|
||||||
|
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this._installExtensionUpdates();
|
||||||
|
this._sessionUpdated();
|
||||||
|
|
||||||
|
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, UPDATE_CHECK_TIMEOUT, () => {
|
||||||
|
ExtensionDownloader.checkForUpdates();
|
||||||
|
return GLib.SOURCE_CONTINUE;
|
||||||
|
});
|
||||||
|
ExtensionDownloader.checkForUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
|
lookup(uuid) {
|
||||||
|
return this._extensions.get(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
getUuids() {
|
||||||
|
return [...this._extensions.keys()];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ _extensionSupportsSessionMode(uuid) {
|
||||||
|
+ let extension = this.lookup(uuid);
|
||||||
|
+
|
||||||
|
+ if (!extension)
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ if (extension.sessionModes.includes(Main.sessionMode.currentMode))
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ if (extension.sessionModes.includes(Main.sessionMode.parentMode))
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ _sessionModeCanUseExtension(uuid) {
|
||||||
|
+ if (!Main.sessionMode.allowExtensions)
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ if (!this._extensionSupportsSessionMode(uuid))
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
_callExtensionDisable(uuid) {
|
||||||
|
let extension = this.lookup(uuid);
|
||||||
|
if (!extension)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (extension.state != ExtensionState.ENABLED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// "Rebase" the extension order by disabling and then enabling extensions
|
||||||
|
// in order to help prevent conflicts.
|
||||||
|
|
||||||
|
// Example:
|
||||||
|
// order = [A, B, C, D, E]
|
||||||
|
// user disables C
|
||||||
|
// this should: disable E, disable D, disable C, enable D, enable E
|
||||||
|
|
||||||
|
let orderIdx = this._extensionOrder.indexOf(uuid);
|
||||||
|
let order = this._extensionOrder.slice(orderIdx + 1);
|
||||||
|
let orderReversed = order.slice().reverse();
|
||||||
|
|
||||||
|
for (let i = 0; i < orderReversed.length; i++) {
|
||||||
|
let uuid = orderReversed[i];
|
||||||
|
try {
|
||||||
|
this.lookup(uuid).stateObj.disable();
|
||||||
|
} catch (e) {
|
||||||
|
this.logExtensionError(uuid, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension.stylesheet) {
|
||||||
|
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
|
||||||
|
theme.unload_stylesheet(extension.stylesheet);
|
||||||
|
delete extension.stylesheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
extension.stateObj.disable();
|
||||||
|
} catch(e) {
|
||||||
|
this.logExtensionError(uuid, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < order.length; i++) {
|
||||||
|
let uuid = order[i];
|
||||||
|
try {
|
||||||
|
this.lookup(uuid).stateObj.enable();
|
||||||
|
} catch (e) {
|
||||||
|
this.logExtensionError(uuid, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._extensionOrder.splice(orderIdx, 1);
|
||||||
|
|
||||||
|
if (extension.state != ExtensionState.ERROR) {
|
||||||
|
extension.state = ExtensionState.DISABLED;
|
||||||
|
this.emit('extension-state-changed', extension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_callExtensionEnable(uuid) {
|
||||||
|
+ if (!this._sessionModeCanUseExtension(uuid))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
let extension = this.lookup(uuid);
|
||||||
|
if (!extension)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (extension.state == ExtensionState.INITIALIZED)
|
||||||
|
this._callExtensionInit(uuid);
|
||||||
|
|
||||||
|
if (extension.state != ExtensionState.DISABLED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._extensionOrder.push(uuid);
|
||||||
|
|
||||||
|
let stylesheetNames = [global.session_mode + '.css', 'stylesheet.css'];
|
||||||
|
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
|
||||||
|
for (let i = 0; i < stylesheetNames.length; i++) {
|
||||||
|
try {
|
||||||
|
let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
|
||||||
|
theme.load_stylesheet(stylesheetFile);
|
||||||
|
extension.stylesheet = stylesheetFile;
|
||||||
|
break;
|
||||||
|
} catch (e) {
|
||||||
|
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
|
||||||
|
continue; // not an error
|
||||||
|
log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
extension.stateObj.enable();
|
||||||
|
@@ -231,61 +259,62 @@ var ExtensionManager = class {
|
||||||
|
throw new Error(`Failed to load metadata.json: ${e}`);
|
||||||
|
}
|
||||||
|
let meta;
|
||||||
|
try {
|
||||||
|
meta = JSON.parse(metadataContents);
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`Failed to parse metadata.json: ${e}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
|
||||||
|
for (let i = 0; i < requiredProperties.length; i++) {
|
||||||
|
let prop = requiredProperties[i];
|
||||||
|
if (!meta[prop]) {
|
||||||
|
throw new Error(`missing "${prop}" property in metadata.json`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uuid != meta.uuid) {
|
||||||
|
throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name "${uuid}"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let extension = {
|
||||||
|
metadata: meta,
|
||||||
|
uuid: meta.uuid,
|
||||||
|
type,
|
||||||
|
dir,
|
||||||
|
path: dir.get_path(),
|
||||||
|
error: '',
|
||||||
|
hasPrefs: dir.get_child('prefs.js').query_exists(null),
|
||||||
|
hasUpdate: false,
|
||||||
|
- canChange: false
|
||||||
|
+ canChange: false,
|
||||||
|
+ sessionModes: meta['session-modes'] ? meta['session-modes'] : [ 'user' ],
|
||||||
|
};
|
||||||
|
this._extensions.set(uuid, extension);
|
||||||
|
|
||||||
|
return extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadExtension(extension) {
|
||||||
|
// Default to error, we set success as the last step
|
||||||
|
extension.state = ExtensionState.ERROR;
|
||||||
|
|
||||||
|
let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY);
|
||||||
|
|
||||||
|
if (checkVersion && ExtensionUtils.isOutOfDate(extension)) {
|
||||||
|
extension.state = ExtensionState.OUT_OF_DATE;
|
||||||
|
} else {
|
||||||
|
let enabled = this._enabledExtensions.includes(extension.uuid);
|
||||||
|
if (enabled) {
|
||||||
|
if (!this._callExtensionInit(extension.uuid))
|
||||||
|
return;
|
||||||
|
if (extension.state == ExtensionState.DISABLED)
|
||||||
|
this._callExtensionEnable(extension.uuid);
|
||||||
|
} else {
|
||||||
|
extension.state = ExtensionState.INITIALIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._updateCanChange(extension);
|
||||||
|
this.emit('extension-state-changed', extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -296,60 +325,63 @@ var ExtensionManager = class {
|
||||||
|
this._callExtensionDisable(extension.uuid);
|
||||||
|
|
||||||
|
extension.state = ExtensionState.UNINSTALLED;
|
||||||
|
this.emit('extension-state-changed', extension);
|
||||||
|
|
||||||
|
this._extensions.delete(extension.uuid);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
reloadExtension(oldExtension) {
|
||||||
|
// Grab the things we'll need to pass to createExtensionObject
|
||||||
|
// to reload it.
|
||||||
|
let { uuid: uuid, dir: dir, type: type } = oldExtension;
|
||||||
|
|
||||||
|
// Then unload the old extension.
|
||||||
|
this.unloadExtension(oldExtension);
|
||||||
|
|
||||||
|
// Now, recreate the extension and load it.
|
||||||
|
let newExtension;
|
||||||
|
try {
|
||||||
|
newExtension = this.createExtensionObject(uuid, dir, type);
|
||||||
|
} catch (e) {
|
||||||
|
this.logExtensionError(uuid, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loadExtension(newExtension);
|
||||||
|
}
|
||||||
|
|
||||||
|
_callExtensionInit(uuid) {
|
||||||
|
+ if (!this._sessionModeCanUseExtension(uuid))
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
let extension = this.lookup(uuid);
|
||||||
|
let dir = extension.dir;
|
||||||
|
|
||||||
|
if (!extension)
|
||||||
|
throw new Error("Extension was not properly created. Call loadExtension first");
|
||||||
|
|
||||||
|
let extensionJs = dir.get_child('extension.js');
|
||||||
|
if (!extensionJs.query_exists(null)) {
|
||||||
|
this.logExtensionError(uuid, new Error('Missing extension.js'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let extensionModule;
|
||||||
|
let extensionState = null;
|
||||||
|
|
||||||
|
ExtensionUtils.installImporter(extension);
|
||||||
|
try {
|
||||||
|
extensionModule = extension.imports.extension;
|
||||||
|
} catch(e) {
|
||||||
|
this.logExtensionError(uuid, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extensionModule.init) {
|
||||||
|
try {
|
||||||
|
extensionState = extensionModule.init(extension);
|
||||||
|
} catch (e) {
|
||||||
|
this.logExtensionError(uuid, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@@ -377,69 +409,72 @@ var ExtensionManager = class {
|
||||||
|
|
||||||
|
let isMode = this._getModeExtensions().includes(extension.uuid);
|
||||||
|
let modeOnly = global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY);
|
||||||
|
|
||||||
|
extension.canChange =
|
||||||
|
!hasError &&
|
||||||
|
global.settings.is_writable(ENABLED_EXTENSIONS_KEY) &&
|
||||||
|
(isMode || !modeOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getEnabledExtensions() {
|
||||||
|
let extensions = this._getModeExtensions();
|
||||||
|
|
||||||
|
if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY))
|
||||||
|
return extensions;
|
||||||
|
|
||||||
|
return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY));
|
||||||
|
}
|
||||||
|
|
||||||
|
_onUserExtensionsEnabledChanged() {
|
||||||
|
this._onEnabledExtensionsChanged();
|
||||||
|
this._onSettingsWritableChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
_onEnabledExtensionsChanged() {
|
||||||
|
let newEnabledExtensions = this._getEnabledExtensions();
|
||||||
|
|
||||||
|
// Find and enable all the newly enabled extensions: UUIDs found in the
|
||||||
|
// new setting, but not in the old one.
|
||||||
|
newEnabledExtensions.filter(
|
||||||
|
- uuid => !this._enabledExtensions.includes(uuid)
|
||||||
|
+ uuid => !this._enabledExtensions.includes(uuid) &&
|
||||||
|
+ this._extensionSupportsSessionMode(uuid)
|
||||||
|
).forEach(uuid => {
|
||||||
|
this._callExtensionEnable(uuid);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Find and disable all the newly disabled extensions: UUIDs found in the
|
||||||
|
- // old setting, but not in the new one.
|
||||||
|
+ // old setting, but not in the new one, and extensions that don't work with
|
||||||
|
+ // the current session mode.
|
||||||
|
this._enabledExtensions.filter(
|
||||||
|
- item => !newEnabledExtensions.includes(item)
|
||||||
|
+ item => !newEnabledExtensions.includes(item) ||
|
||||||
|
+ !this._extensionSupportsSessionMode(item)
|
||||||
|
).forEach(uuid => {
|
||||||
|
this._callExtensionDisable(uuid);
|
||||||
|
});
|
||||||
|
|
||||||
|
this._enabledExtensions = newEnabledExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
_onSettingsWritableChanged() {
|
||||||
|
for (let extension of this._extensions.values()) {
|
||||||
|
this._updateCanChange(extension);
|
||||||
|
this.emit('extension-state-changed', extension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_onVersionValidationChanged() {
|
||||||
|
// we want to reload all extensions, but only enable
|
||||||
|
// extensions when allowed by the sessionMode, so
|
||||||
|
// temporarily disable them all
|
||||||
|
this._enabledExtensions = [];
|
||||||
|
|
||||||
|
// The loop modifies the extensions map, so iterate over a copy
|
||||||
|
let extensions = [...this._extensions.values()];
|
||||||
|
for (let extension of extensions)
|
||||||
|
this.reloadExtension(extension);
|
||||||
|
this._enabledExtensions = this._getEnabledExtensions();
|
||||||
|
|
||||||
|
if (Main.sessionMode.allowExtensions) {
|
||||||
|
this._enabledExtensions.forEach(uuid => {
|
||||||
|
this._callExtensionEnable(uuid);
|
||||||
|
});
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
@ -0,0 +1,152 @@
|
|||||||
|
From c9277326055c96185a80b68d4228eee360bb0e7c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||||
|
Date: Thu, 1 Aug 2019 20:58:20 -0300
|
||||||
|
Subject: [PATCH 3/6] shell/app-system: Monitor for icon theme changes
|
||||||
|
|
||||||
|
Whenever an app is installed, the usual routine is
|
||||||
|
to run 'gtk-update-icon-cache' after installing all
|
||||||
|
of the app's files.
|
||||||
|
|
||||||
|
The side effect of that is that the .desktop file of
|
||||||
|
the application is installed before the icon theme
|
||||||
|
is updated. By the time GAppInfoMonitor emits the
|
||||||
|
'changed' signal, the icon theme is not yet updated,
|
||||||
|
leading to StIcon use the fallback icon.
|
||||||
|
|
||||||
|
Under some circumstances (e.g. on very slow spinning
|
||||||
|
disks) the app icon is never actually loaded, and we
|
||||||
|
see the fallback icon forever.
|
||||||
|
|
||||||
|
Monitor the icon theme for changes when an app is
|
||||||
|
installed. Try as many as 6 times before giving up
|
||||||
|
on detecting an icon theme update.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/661
|
||||||
|
---
|
||||||
|
src/shell-app-system.c | 54 +++++++++++++++++++++++++++++++++++++++
|
||||||
|
src/st/st-texture-cache.c | 8 ++++++
|
||||||
|
src/st/st-texture-cache.h | 2 ++
|
||||||
|
3 files changed, 64 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/shell-app-system.c b/src/shell-app-system.c
|
||||||
|
index f632cbe54..127f29ef0 100644
|
||||||
|
--- a/src/shell-app-system.c
|
||||||
|
+++ b/src/shell-app-system.c
|
||||||
|
@@ -14,6 +14,14 @@
|
||||||
|
#include "shell-app-system-private.h"
|
||||||
|
#include "shell-global.h"
|
||||||
|
#include "shell-util.h"
|
||||||
|
+#include "st.h"
|
||||||
|
+
|
||||||
|
+/* Rescan for at most RESCAN_TIMEOUT_MS * MAX_RESCAN_RETRIES. That
|
||||||
|
+ * should be plenty of time for even a slow spinning drive to update
|
||||||
|
+ * the icon cache.
|
||||||
|
+ */
|
||||||
|
+#define RESCAN_TIMEOUT_MS 2500
|
||||||
|
+#define MAX_RESCAN_RETRIES 6
|
||||||
|
|
||||||
|
/* Vendor prefixes are something that can be preprended to a .desktop
|
||||||
|
* file name. Undo this.
|
||||||
|
@@ -51,6 +59,9 @@ struct _ShellAppSystemPrivate {
|
||||||
|
GHashTable *id_to_app;
|
||||||
|
GHashTable *startup_wm_class_to_id;
|
||||||
|
GList *installed_apps;
|
||||||
|
+
|
||||||
|
+ guint rescan_icons_timeout_id;
|
||||||
|
+ guint n_rescan_retries;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void shell_app_system_finalize (GObject *object);
|
||||||
|
@@ -157,12 +168,54 @@ stale_app_remove_func (gpointer key,
|
||||||
|
return app_is_stale (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static gboolean
|
||||||
|
+rescan_icon_theme_cb (gpointer user_data)
|
||||||
|
+{
|
||||||
|
+ ShellAppSystemPrivate *priv;
|
||||||
|
+ ShellAppSystem *self;
|
||||||
|
+ StTextureCache *texture_cache;
|
||||||
|
+ gboolean rescanned;
|
||||||
|
+
|
||||||
|
+ self = (ShellAppSystem *) user_data;
|
||||||
|
+ priv = self->priv;
|
||||||
|
+
|
||||||
|
+ texture_cache = st_texture_cache_get_default ();
|
||||||
|
+ rescanned = st_texture_cache_rescan_icon_theme (texture_cache);
|
||||||
|
+
|
||||||
|
+ priv->n_rescan_retries++;
|
||||||
|
+
|
||||||
|
+ if (rescanned || priv->n_rescan_retries >= MAX_RESCAN_RETRIES)
|
||||||
|
+ {
|
||||||
|
+ priv->n_rescan_retries = 0;
|
||||||
|
+ priv->rescan_icons_timeout_id = 0;
|
||||||
|
+ return G_SOURCE_REMOVE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return G_SOURCE_CONTINUE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+rescan_icon_theme (ShellAppSystem *self)
|
||||||
|
+{
|
||||||
|
+ ShellAppSystemPrivate *priv = self->priv;
|
||||||
|
+
|
||||||
|
+ priv->n_rescan_retries = 0;
|
||||||
|
+
|
||||||
|
+ if (priv->rescan_icons_timeout_id > 0)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ priv->rescan_icons_timeout_id = g_timeout_add (RESCAN_TIMEOUT_MS,
|
||||||
|
+ rescan_icon_theme_cb,
|
||||||
|
+ self);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
installed_changed (GAppInfoMonitor *monitor,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ShellAppSystem *self = user_data;
|
||||||
|
|
||||||
|
+ rescan_icon_theme (self);
|
||||||
|
scan_startup_wm_class_to_id (self);
|
||||||
|
|
||||||
|
g_hash_table_foreach_remove (self->priv->id_to_app, stale_app_remove_func, NULL);
|
||||||
|
@@ -200,6 +253,7 @@ shell_app_system_finalize (GObject *object)
|
||||||
|
g_hash_table_destroy (priv->id_to_app);
|
||||||
|
g_hash_table_destroy (priv->startup_wm_class_to_id);
|
||||||
|
g_list_free_full (priv->installed_apps, g_object_unref);
|
||||||
|
+ g_clear_handle_id (&priv->rescan_icons_timeout_id, g_source_remove);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (shell_app_system_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c
|
||||||
|
index c1331747f..4d0d617c4 100644
|
||||||
|
--- a/src/st/st-texture-cache.c
|
||||||
|
+++ b/src/st/st-texture-cache.c
|
||||||
|
@@ -1554,3 +1554,11 @@ st_texture_cache_get_default (void)
|
||||||
|
instance = g_object_new (ST_TYPE_TEXTURE_CACHE, NULL);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+gboolean
|
||||||
|
+st_texture_cache_rescan_icon_theme (StTextureCache *cache)
|
||||||
|
+{
|
||||||
|
+ StTextureCachePrivate *priv = cache->priv;
|
||||||
|
+
|
||||||
|
+ return gtk_icon_theme_rescan_if_needed (priv->icon_theme);
|
||||||
|
+}
|
||||||
|
diff --git a/src/st/st-texture-cache.h b/src/st/st-texture-cache.h
|
||||||
|
index 11d1c4e64..a99316da8 100644
|
||||||
|
--- a/src/st/st-texture-cache.h
|
||||||
|
+++ b/src/st/st-texture-cache.h
|
||||||
|
@@ -113,4 +113,6 @@ CoglTexture * st_texture_cache_load (StTextureCache *cache,
|
||||||
|
void *data,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
+gboolean st_texture_cache_rescan_icon_theme (StTextureCache *cache);
|
||||||
|
+
|
||||||
|
#endif /* __ST_TEXTURE_CACHE_H__ */
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -0,0 +1,119 @@
|
|||||||
|
From 39cf97176e2a92506081ee151ea546e2c6cf213a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Wed, 21 Aug 2019 15:06:46 -0400
|
||||||
|
Subject: [PATCH 3/4] shellEntry: Handle password item from dedication function
|
||||||
|
|
||||||
|
At the moment, shellEntry handles creating and destroying its
|
||||||
|
"Show Text" password menu item directly from its isPassword
|
||||||
|
setter function.
|
||||||
|
|
||||||
|
This commit moves that handling to a dedicated _resetPasswordItem
|
||||||
|
function, as prep work for adding lockdown support of the "Show Text"
|
||||||
|
menu item.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/687
|
||||||
|
---
|
||||||
|
js/ui/shellEntry.js | 23 +++++++++++++++++------
|
||||||
|
1 file changed, 17 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js
|
||||||
|
index 603a9c64a..765cede06 100644
|
||||||
|
--- a/js/ui/shellEntry.js
|
||||||
|
+++ b/js/ui/shellEntry.js
|
||||||
|
@@ -14,76 +14,87 @@ var EntryMenu = class extends PopupMenu.PopupMenu {
|
||||||
|
|
||||||
|
this._entry = entry;
|
||||||
|
this._clipboard = St.Clipboard.get_default();
|
||||||
|
|
||||||
|
// Populate menu
|
||||||
|
let item;
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("Copy"));
|
||||||
|
item.connect('activate', this._onCopyActivated.bind(this));
|
||||||
|
this.addMenuItem(item);
|
||||||
|
this._copyItem = item;
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("Paste"));
|
||||||
|
item.connect('activate', this._onPasteActivated.bind(this));
|
||||||
|
this.addMenuItem(item);
|
||||||
|
this._pasteItem = item;
|
||||||
|
|
||||||
|
this._passwordItem = null;
|
||||||
|
|
||||||
|
Main.uiGroup.add_actor(this.actor);
|
||||||
|
this.actor.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
_makePasswordItem() {
|
||||||
|
let item = new PopupMenu.PopupMenuItem('');
|
||||||
|
item.connect('activate', this._onPasswordActivated.bind(this));
|
||||||
|
this.addMenuItem(item);
|
||||||
|
this._passwordItem = item;
|
||||||
|
this._updatePasswordItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ _resetPasswordItem() {
|
||||||
|
+ if (!this.isPassword) {
|
||||||
|
+ if (this._passwordItem) {
|
||||||
|
+ this._passwordItem.destroy();
|
||||||
|
+ this._passwordItem = null;
|
||||||
|
+ }
|
||||||
|
+ this._entry.clutter_text.set_password_char('\u25cf');
|
||||||
|
+ } else {
|
||||||
|
+ if (!this._passwordItem)
|
||||||
|
+ this._makePasswordItem();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
get isPassword() {
|
||||||
|
return this._entry.input_purpose == Clutter.InputContentPurpose.PASSWORD;
|
||||||
|
}
|
||||||
|
|
||||||
|
set isPassword(v) {
|
||||||
|
if (v == this.isPassword)
|
||||||
|
return;
|
||||||
|
|
||||||
|
- if (v) {
|
||||||
|
- this._makePasswordItem();
|
||||||
|
+ if (v)
|
||||||
|
this._entry.input_purpose = Clutter.InputContentPurpose.PASSWORD;
|
||||||
|
- } else {
|
||||||
|
- this._passwordItem.destroy();
|
||||||
|
- this._passwordItem = null;
|
||||||
|
+ else
|
||||||
|
this._entry.input_purpose = Clutter.InputContentPurpose.NORMAL;
|
||||||
|
- }
|
||||||
|
+
|
||||||
|
+ this._resetPasswordItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
open(animate) {
|
||||||
|
this._updatePasteItem();
|
||||||
|
this._updateCopyItem();
|
||||||
|
if (this._passwordItem)
|
||||||
|
this._updatePasswordItem();
|
||||||
|
|
||||||
|
super.open(animate);
|
||||||
|
this._entry.add_style_pseudo_class('focus');
|
||||||
|
|
||||||
|
let direction = St.DirectionType.TAB_FORWARD;
|
||||||
|
if (!this.actor.navigate_focus(null, direction, false))
|
||||||
|
this.actor.grab_key_focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateCopyItem() {
|
||||||
|
let selection = this._entry.clutter_text.get_selection();
|
||||||
|
this._copyItem.setSensitive(!this._entry.clutter_text.password_char &&
|
||||||
|
selection && selection != '');
|
||||||
|
}
|
||||||
|
|
||||||
|
_updatePasteItem() {
|
||||||
|
this._clipboard.get_text(St.ClipboardType.CLIPBOARD,
|
||||||
|
(clipboard, text) => {
|
||||||
|
this._pasteItem.setSensitive(text && text != '');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_updatePasswordItem() {
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
@ -0,0 +1,115 @@
|
|||||||
|
From 055bc14c70af66fe1893dcd4c42c65662ae1f9d0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Mon, 21 Jan 2019 15:07:15 -0500
|
||||||
|
Subject: [PATCH 4/4] background: refresh background on gl-video-memory-purged
|
||||||
|
signal
|
||||||
|
|
||||||
|
Right now we refresh the background when resuming and when NVIDIA.
|
||||||
|
But mutter has a signal to tell us specifically when to refresh,
|
||||||
|
and the signal is only emitted for NVIDIA, so use that instead.
|
||||||
|
---
|
||||||
|
js/ui/background.js | 9 +++++++--
|
||||||
|
js/ui/layout.js | 12 ------------
|
||||||
|
src/shell-util.c | 27 ---------------------------
|
||||||
|
src/shell-util.h | 2 --
|
||||||
|
4 files changed, 7 insertions(+), 43 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/background.js b/js/ui/background.js
|
||||||
|
index 75b76a57e..466cc4de7 100644
|
||||||
|
--- a/js/ui/background.js
|
||||||
|
+++ b/js/ui/background.js
|
||||||
|
@@ -527,10 +527,15 @@ var BackgroundSource = class BackgroundSource {
|
||||||
|
let monitorManager = Meta.MonitorManager.get();
|
||||||
|
this._monitorsChangedId =
|
||||||
|
monitorManager.connect('monitors-changed',
|
||||||
|
- this._onMonitorsChanged.bind(this));
|
||||||
|
+ this._refresh.bind(this));
|
||||||
|
+
|
||||||
|
+ global.display.connect('gl-video-memory-purged', () => {
|
||||||
|
+ Meta.Background.refresh_all();
|
||||||
|
+ this._refresh();
|
||||||
|
+ });
|
||||||
|
}
|
||||||
|
|
||||||
|
- _onMonitorsChanged() {
|
||||||
|
+ _refresh() {
|
||||||
|
for (let monitorIndex in this._backgrounds) {
|
||||||
|
let background = this._backgrounds[monitorIndex];
|
||||||
|
|
||||||
|
diff --git a/js/ui/layout.js b/js/ui/layout.js
|
||||||
|
index 30e750dc5..2b3bb7442 100644
|
||||||
|
--- a/js/ui/layout.js
|
||||||
|
+++ b/js/ui/layout.js
|
||||||
|
@@ -282,18 +282,6 @@ var LayoutManager = GObject.registerClass({
|
||||||
|
monitorManager.connect('monitors-changed',
|
||||||
|
this._monitorsChanged.bind(this));
|
||||||
|
this._monitorsChanged();
|
||||||
|
-
|
||||||
|
- // NVIDIA drivers don't preserve FBO contents across
|
||||||
|
- // suspend/resume, see
|
||||||
|
- // https://bugzilla.gnome.org/show_bug.cgi?id=739178
|
||||||
|
- if (Shell.util_need_background_refresh()) {
|
||||||
|
- LoginManager.getLoginManager().connect('prepare-for-sleep',
|
||||||
|
- (lm, suspending) => {
|
||||||
|
- if (suspending)
|
||||||
|
- return;
|
||||||
|
- Meta.Background.refresh_all();
|
||||||
|
- });
|
||||||
|
- }
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is called by Main after everything else is constructed
|
||||||
|
diff --git a/src/shell-util.c b/src/shell-util.c
|
||||||
|
index c6e5abed6..9c25643c6 100644
|
||||||
|
--- a/src/shell-util.c
|
||||||
|
+++ b/src/shell-util.c
|
||||||
|
@@ -374,33 +374,6 @@ shell_util_create_pixbuf_from_data (const guchar *data,
|
||||||
|
(GdkPixbufDestroyNotify) g_free, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
-typedef const gchar *(*ShellGLGetString) (GLenum);
|
||||||
|
-
|
||||||
|
-static const gchar *
|
||||||
|
-get_gl_vendor (void)
|
||||||
|
-{
|
||||||
|
- static const gchar *vendor = NULL;
|
||||||
|
-
|
||||||
|
- if (!vendor)
|
||||||
|
- {
|
||||||
|
- ShellGLGetString gl_get_string;
|
||||||
|
- gl_get_string = (ShellGLGetString) cogl_get_proc_address ("glGetString");
|
||||||
|
- if (gl_get_string)
|
||||||
|
- vendor = gl_get_string (GL_VENDOR);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return vendor;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-gboolean
|
||||||
|
-shell_util_need_background_refresh (void)
|
||||||
|
-{
|
||||||
|
- if (g_strcmp0 (get_gl_vendor (), "NVIDIA Corporation") == 0)
|
||||||
|
- return TRUE;
|
||||||
|
-
|
||||||
|
- return FALSE;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static gboolean
|
||||||
|
canvas_draw_cb (ClutterContent *content,
|
||||||
|
cairo_t *cr,
|
||||||
|
diff --git a/src/shell-util.h b/src/shell-util.h
|
||||||
|
index 6904f43bc..049c3fe18 100644
|
||||||
|
--- a/src/shell-util.h
|
||||||
|
+++ b/src/shell-util.h
|
||||||
|
@@ -44,8 +44,6 @@ GdkPixbuf *shell_util_create_pixbuf_from_data (const guchar *data,
|
||||||
|
int height,
|
||||||
|
int rowstride);
|
||||||
|
|
||||||
|
-gboolean shell_util_need_background_refresh (void);
|
||||||
|
-
|
||||||
|
ClutterContent * shell_util_get_content_for_window_actor (MetaWindowActor *window_actor,
|
||||||
|
MetaRectangle *window_rect);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -0,0 +1,124 @@
|
|||||||
|
From 2a4f33df723d4b9ce68e5948b568a89675d37411 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Wed, 26 Feb 2020 14:46:20 -0800
|
||||||
|
Subject: [PATCH 4/6] global: force fsync() to worker thread when saving state
|
||||||
|
|
||||||
|
The g_file_replace_contents_async() API can potentially call fsync() from
|
||||||
|
the thread calling into it upon completion. This can have disasterous
|
||||||
|
effects when run from the compositor main thread such as complete stalls.
|
||||||
|
|
||||||
|
This is a followup to 86a00b6872375a266449beee1ea6d5e94f1ebbcb which
|
||||||
|
assumed (like the rest of us) that the fsync() would be performed on the
|
||||||
|
thread that was doing the I/O operations.
|
||||||
|
|
||||||
|
You can verify this with an strace -e fsync and cause terminal to display
|
||||||
|
a command completed notification (eg: from a backdrop window).
|
||||||
|
|
||||||
|
This also fixes a lifecycle bug for the variant, as
|
||||||
|
g_file_replace_contents_async() does not copy the data during the operation
|
||||||
|
as that is the responsibility of the caller. Instead, we just use a GBytes
|
||||||
|
variant and reference the variant there.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1050
|
||||||
|
---
|
||||||
|
src/shell-global.c | 70 +++++++++++++++++++++++++++++++++++++++++-----
|
||||||
|
1 file changed, 63 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/shell-global.c b/src/shell-global.c
|
||||||
|
index df84b6b0d..4b33778e0 100644
|
||||||
|
--- a/src/shell-global.c
|
||||||
|
+++ b/src/shell-global.c
|
||||||
|
@@ -1572,6 +1572,55 @@ delete_variant_cb (GObject *object,
|
||||||
|
g_hash_table_remove (global->save_ops, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+replace_contents_worker (GTask *task,
|
||||||
|
+ gpointer source_object,
|
||||||
|
+ gpointer task_data,
|
||||||
|
+ GCancellable *cancellable)
|
||||||
|
+{
|
||||||
|
+ GFile *file = source_object;
|
||||||
|
+ GBytes *bytes = task_data;
|
||||||
|
+ GError *error = NULL;
|
||||||
|
+ const gchar *data;
|
||||||
|
+ gsize len;
|
||||||
|
+
|
||||||
|
+ data = g_bytes_get_data (bytes, &len);
|
||||||
|
+
|
||||||
|
+ if (!g_file_replace_contents (file, data, len, NULL, FALSE,
|
||||||
|
+ G_FILE_CREATE_REPLACE_DESTINATION,
|
||||||
|
+ NULL, cancellable, &error))
|
||||||
|
+ g_task_return_error (task, g_steal_pointer (&error));
|
||||||
|
+ else
|
||||||
|
+ g_task_return_boolean (task, TRUE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+replace_contents_async (GFile *path,
|
||||||
|
+ GBytes *bytes,
|
||||||
|
+ GCancellable *cancellable,
|
||||||
|
+ GAsyncReadyCallback callback,
|
||||||
|
+ gpointer user_data)
|
||||||
|
+{
|
||||||
|
+ g_autoptr(GTask) task = NULL;
|
||||||
|
+
|
||||||
|
+ g_assert (G_IS_FILE (path));
|
||||||
|
+ g_assert (bytes != NULL);
|
||||||
|
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||||
|
+
|
||||||
|
+ task = g_task_new (path, cancellable, callback, user_data);
|
||||||
|
+ g_task_set_source_tag (task, replace_contents_async);
|
||||||
|
+ g_task_set_task_data (task, g_bytes_ref (bytes), (GDestroyNotify)g_bytes_unref);
|
||||||
|
+ g_task_run_in_thread (task, replace_contents_worker);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static gboolean
|
||||||
|
+replace_contents_finish (GFile *file,
|
||||||
|
+ GAsyncResult *result,
|
||||||
|
+ GError **error)
|
||||||
|
+{
|
||||||
|
+ return g_task_propagate_boolean (G_TASK (result), error);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
replace_variant_cb (GObject *object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
@@ -1580,7 +1629,7 @@ replace_variant_cb (GObject *object,
|
||||||
|
ShellGlobal *global = user_data;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
- if (!g_file_replace_contents_finish (G_FILE (object), result, NULL, &error))
|
||||||
|
+ if (!replace_contents_finish (G_FILE (object), result, &error))
|
||||||
|
{
|
||||||
|
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||||
|
{
|
||||||
|
@@ -1616,12 +1665,19 @@ save_variant (ShellGlobal *global,
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
- g_file_replace_contents_async (path,
|
||||||
|
- g_variant_get_data (variant),
|
||||||
|
- g_variant_get_size (variant),
|
||||||
|
- NULL, FALSE,
|
||||||
|
- G_FILE_CREATE_REPLACE_DESTINATION,
|
||||||
|
- cancellable, replace_variant_cb, global);
|
||||||
|
+ g_autoptr(GBytes) bytes = NULL;
|
||||||
|
+
|
||||||
|
+ bytes = g_bytes_new_with_free_func (g_variant_get_data (variant),
|
||||||
|
+ g_variant_get_size (variant),
|
||||||
|
+ (GDestroyNotify)g_variant_unref,
|
||||||
|
+ g_variant_ref (variant));
|
||||||
|
+ /* g_file_replace_contents_async() can potentially fsync() from the
|
||||||
|
+ * calling thread when completing the asynchronous task. Instead, we
|
||||||
|
+ * want to force that fsync() to a thread to avoid blocking the
|
||||||
|
+ * compository main loop. Using our own replace_contents_async()
|
||||||
|
+ * simply executes the operation synchronously from a thread.
|
||||||
|
+ */
|
||||||
|
+ replace_contents_async (path, bytes, cancellable, replace_variant_cb, global);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (path);
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -0,0 +1,116 @@
|
|||||||
|
From 5fad989ca773f9e0ff6fdbeb0cb7c9cb70cc6148 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Tue, 10 Aug 2021 15:31:00 -0400
|
||||||
|
Subject: [PATCH 4/4] sessionMode: Allow extensions at the login and unlock
|
||||||
|
screens
|
||||||
|
|
||||||
|
Now extensions can specify which session modes they work in,
|
||||||
|
but specifying the login screen or unlock screen session modes in
|
||||||
|
an extensions metadata still won't work, because those session
|
||||||
|
modes disallow extensions.
|
||||||
|
|
||||||
|
This commit fixes that.
|
||||||
|
---
|
||||||
|
js/ui/sessionMode.js | 3 +++
|
||||||
|
1 file changed, 3 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/js/ui/sessionMode.js b/js/ui/sessionMode.js
|
||||||
|
index fa7f83416..8d8ce1a64 100644
|
||||||
|
--- a/js/ui/sessionMode.js
|
||||||
|
+++ b/js/ui/sessionMode.js
|
||||||
|
@@ -12,89 +12,92 @@ const Config = imports.misc.config;
|
||||||
|
const DEFAULT_MODE = 'restrictive';
|
||||||
|
|
||||||
|
const _modes = {
|
||||||
|
'restrictive': {
|
||||||
|
parentMode: null,
|
||||||
|
stylesheetName: 'gnome-shell.css',
|
||||||
|
hasOverview: false,
|
||||||
|
showCalendarEvents: false,
|
||||||
|
allowSettings: false,
|
||||||
|
allowExtensions: false,
|
||||||
|
allowScreencast: false,
|
||||||
|
enabledExtensions: [],
|
||||||
|
hasRunDialog: false,
|
||||||
|
hasWorkspaces: false,
|
||||||
|
hasWindows: false,
|
||||||
|
hasNotifications: false,
|
||||||
|
isLocked: false,
|
||||||
|
isGreeter: false,
|
||||||
|
isPrimary: false,
|
||||||
|
unlockDialog: null,
|
||||||
|
components: [],
|
||||||
|
panel: {
|
||||||
|
left: [],
|
||||||
|
center: [],
|
||||||
|
right: []
|
||||||
|
},
|
||||||
|
panelStyle: null
|
||||||
|
},
|
||||||
|
|
||||||
|
'gdm': {
|
||||||
|
+ allowExtensions: true,
|
||||||
|
hasNotifications: true,
|
||||||
|
isGreeter: true,
|
||||||
|
isPrimary: true,
|
||||||
|
unlockDialog: imports.gdm.loginDialog.LoginDialog,
|
||||||
|
components: Config.HAVE_NETWORKMANAGER
|
||||||
|
? ['networkAgent', 'polkitAgent']
|
||||||
|
: ['polkitAgent'],
|
||||||
|
panel: {
|
||||||
|
left: [],
|
||||||
|
center: ['dateMenu'],
|
||||||
|
right: ['a11y', 'keyboard', 'aggregateMenu']
|
||||||
|
},
|
||||||
|
panelStyle: 'login-screen'
|
||||||
|
},
|
||||||
|
|
||||||
|
'lock-screen': {
|
||||||
|
+ allowExtensions: true,
|
||||||
|
isLocked: true,
|
||||||
|
isGreeter: undefined,
|
||||||
|
unlockDialog: undefined,
|
||||||
|
components: ['polkitAgent', 'telepathyClient'],
|
||||||
|
panel: {
|
||||||
|
left: [],
|
||||||
|
center: [],
|
||||||
|
right: ['aggregateMenu']
|
||||||
|
},
|
||||||
|
panelStyle: 'lock-screen'
|
||||||
|
},
|
||||||
|
|
||||||
|
'unlock-dialog': {
|
||||||
|
+ allowExtensions: true,
|
||||||
|
isLocked: true,
|
||||||
|
unlockDialog: undefined,
|
||||||
|
components: ['polkitAgent', 'telepathyClient'],
|
||||||
|
panel: {
|
||||||
|
left: [],
|
||||||
|
center: [],
|
||||||
|
right: ['a11y', 'keyboard', 'aggregateMenu']
|
||||||
|
},
|
||||||
|
panelStyle: 'unlock-screen'
|
||||||
|
},
|
||||||
|
|
||||||
|
'user': {
|
||||||
|
hasOverview: true,
|
||||||
|
showCalendarEvents: true,
|
||||||
|
allowSettings: true,
|
||||||
|
allowExtensions: true,
|
||||||
|
allowScreencast: true,
|
||||||
|
hasRunDialog: true,
|
||||||
|
hasWorkspaces: true,
|
||||||
|
hasWindows: true,
|
||||||
|
hasNotifications: true,
|
||||||
|
isLocked: false,
|
||||||
|
isPrimary: true,
|
||||||
|
unlockDialog: imports.ui.unlockDialog.UnlockDialog,
|
||||||
|
components: Config.HAVE_NETWORKMANAGER ?
|
||||||
|
['networkAgent', 'polkitAgent', 'telepathyClient',
|
||||||
|
'keyring', 'autorunManager', 'automountManager'] :
|
||||||
|
['polkitAgent', 'telepathyClient',
|
||||||
|
'keyring', 'autorunManager', 'automountManager'],
|
||||||
|
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
@ -0,0 +1,116 @@
|
|||||||
|
From ee64cd773bdeef845d02dc84063f926d77090dec Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Wed, 21 Aug 2019 15:06:46 -0400
|
||||||
|
Subject: [PATCH 4/4] shellEntry: Support lockdown of "Show Text" menu in
|
||||||
|
password entries
|
||||||
|
|
||||||
|
Some deployments require being able to prevent users from showing
|
||||||
|
the password they're currently typing.
|
||||||
|
|
||||||
|
This commit adds support for that kind of lockdown.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/687
|
||||||
|
---
|
||||||
|
js/ui/shellEntry.js | 14 +++++++++++---
|
||||||
|
1 file changed, 11 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js
|
||||||
|
index 765cede06..c45e4545a 100644
|
||||||
|
--- a/js/ui/shellEntry.js
|
||||||
|
+++ b/js/ui/shellEntry.js
|
||||||
|
@@ -1,81 +1,89 @@
|
||||||
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||||
|
|
||||||
|
-const { Clutter, GObject, Pango, Shell, St } = imports.gi;
|
||||||
|
+const { Clutter, Gio, GObject, Pango, Shell, St } = imports.gi;
|
||||||
|
|
||||||
|
const BoxPointer = imports.ui.boxpointer;
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const Params = imports.misc.params;
|
||||||
|
const PopupMenu = imports.ui.popupMenu;
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
|
+const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown';
|
||||||
|
+const DISABLE_SHOW_PASSWORD_KEY = 'disable-show-password';
|
||||||
|
+
|
||||||
|
var EntryMenu = class extends PopupMenu.PopupMenu {
|
||||||
|
constructor(entry) {
|
||||||
|
super(entry, 0, St.Side.TOP);
|
||||||
|
|
||||||
|
+ this._lockdownSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA });
|
||||||
|
+ this._lockdownSettings.connect('changed::' + DISABLE_SHOW_PASSWORD_KEY, this._resetPasswordItem.bind(this));
|
||||||
|
+
|
||||||
|
this._entry = entry;
|
||||||
|
this._clipboard = St.Clipboard.get_default();
|
||||||
|
|
||||||
|
// Populate menu
|
||||||
|
let item;
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("Copy"));
|
||||||
|
item.connect('activate', this._onCopyActivated.bind(this));
|
||||||
|
this.addMenuItem(item);
|
||||||
|
this._copyItem = item;
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("Paste"));
|
||||||
|
item.connect('activate', this._onPasteActivated.bind(this));
|
||||||
|
this.addMenuItem(item);
|
||||||
|
this._pasteItem = item;
|
||||||
|
|
||||||
|
this._passwordItem = null;
|
||||||
|
|
||||||
|
Main.uiGroup.add_actor(this.actor);
|
||||||
|
this.actor.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
_makePasswordItem() {
|
||||||
|
let item = new PopupMenu.PopupMenuItem('');
|
||||||
|
item.connect('activate', this._onPasswordActivated.bind(this));
|
||||||
|
this.addMenuItem(item);
|
||||||
|
this._passwordItem = item;
|
||||||
|
this._updatePasswordItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
_resetPasswordItem() {
|
||||||
|
- if (!this.isPassword) {
|
||||||
|
+ let passwordDisabled = this._lockdownSettings.get_boolean(DISABLE_SHOW_PASSWORD_KEY);
|
||||||
|
+
|
||||||
|
+ if (!this.isPassword || passwordDisabled) {
|
||||||
|
if (this._passwordItem) {
|
||||||
|
this._passwordItem.destroy();
|
||||||
|
this._passwordItem = null;
|
||||||
|
}
|
||||||
|
this._entry.clutter_text.set_password_char('\u25cf');
|
||||||
|
- } else {
|
||||||
|
+ } else if (this.isPassword && !passwordDisabled) {
|
||||||
|
if (!this._passwordItem)
|
||||||
|
this._makePasswordItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get isPassword() {
|
||||||
|
return this._entry.input_purpose == Clutter.InputContentPurpose.PASSWORD;
|
||||||
|
}
|
||||||
|
|
||||||
|
set isPassword(v) {
|
||||||
|
if (v == this.isPassword)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (v)
|
||||||
|
this._entry.input_purpose = Clutter.InputContentPurpose.PASSWORD;
|
||||||
|
else
|
||||||
|
this._entry.input_purpose = Clutter.InputContentPurpose.NORMAL;
|
||||||
|
|
||||||
|
this._resetPasswordItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
open(animate) {
|
||||||
|
this._updatePasteItem();
|
||||||
|
this._updateCopyItem();
|
||||||
|
if (this._passwordItem)
|
||||||
|
this._updatePasswordItem();
|
||||||
|
|
||||||
|
super.open(animate);
|
||||||
|
this._entry.add_style_pseudo_class('focus');
|
||||||
|
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
@ -0,0 +1,674 @@
|
|||||||
|
From a3fc35a2b452855d004549afbec57d1b4f36c917 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Thu, 27 Feb 2020 19:36:14 -0800
|
||||||
|
Subject: [PATCH 5/6] app-cache: add ShellAppCache for GAppInfo caching
|
||||||
|
|
||||||
|
This caches GAppInfo so that the compositor thread does not have to perform
|
||||||
|
costly disk access to load them. Instead, they are loaded from a worker
|
||||||
|
thread and the ShellAppCache notifies of changes.
|
||||||
|
|
||||||
|
To simplify maintenance, ShellAppCache manages this directly and the
|
||||||
|
existing ShellAppSystem wraps the cache. We may want to graft these
|
||||||
|
together in the future, but now it provides the easiest way to backport
|
||||||
|
changes to older Shell releases.
|
||||||
|
|
||||||
|
Another source of compositor thread disk access was in determining the
|
||||||
|
name for an application directory. Translations are provided via GKeyFile
|
||||||
|
installed in "desktop-directories". Each time we would build the name
|
||||||
|
for a label (or update it) we would have to load all of these files.
|
||||||
|
|
||||||
|
Instead, the ShellAppCache caches that information and updates the cache
|
||||||
|
in bulk when those change. We can reduce this in the future to do less
|
||||||
|
work, but chances are these will come together anyway so that is probably
|
||||||
|
worth fixing if we ever come across it.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/issues/2282
|
||||||
|
---
|
||||||
|
js/ui/appDisplay.js | 12 +-
|
||||||
|
src/meson.build | 5 +-
|
||||||
|
src/shell-app-cache-private.h | 19 ++
|
||||||
|
src/shell-app-cache.c | 404 ++++++++++++++++++++++++++++++++++
|
||||||
|
src/shell-app-system.c | 34 ++-
|
||||||
|
src/shell-util.c | 16 ++
|
||||||
|
src/shell-util.h | 2 +
|
||||||
|
7 files changed, 463 insertions(+), 29 deletions(-)
|
||||||
|
create mode 100644 src/shell-app-cache-private.h
|
||||||
|
create mode 100644 src/shell-app-cache.c
|
||||||
|
|
||||||
|
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
|
||||||
|
index 7fad02cd0..a2d691085 100644
|
||||||
|
--- a/js/ui/appDisplay.js
|
||||||
|
+++ b/js/ui/appDisplay.js
|
||||||
|
@@ -78,15 +78,9 @@ function _getFolderName(folder) {
|
||||||
|
let name = folder.get_string('name');
|
||||||
|
|
||||||
|
if (folder.get_boolean('translate')) {
|
||||||
|
- let keyfile = new GLib.KeyFile();
|
||||||
|
- let path = 'desktop-directories/' + name;
|
||||||
|
-
|
||||||
|
- try {
|
||||||
|
- keyfile.load_from_data_dirs(path, GLib.KeyFileFlags.NONE);
|
||||||
|
- name = keyfile.get_locale_string('Desktop Entry', 'Name', null);
|
||||||
|
- } catch(e) {
|
||||||
|
- return name;
|
||||||
|
- }
|
||||||
|
+ let translated = Shell.util_get_translated_folder_name(name);
|
||||||
|
+ if (translated !== null)
|
||||||
|
+ return translated;
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
diff --git a/src/meson.build b/src/meson.build
|
||||||
|
index 97a5a796c..2b911d347 100644
|
||||||
|
--- a/src/meson.build
|
||||||
|
+++ b/src/meson.build
|
||||||
|
@@ -108,6 +108,7 @@ endif
|
||||||
|
|
||||||
|
libshell_private_headers = [
|
||||||
|
'shell-app-private.h',
|
||||||
|
+ 'shell-app-cache-private.h',
|
||||||
|
'shell-app-system-private.h',
|
||||||
|
'shell-global-private.h',
|
||||||
|
'shell-window-tracker-private.h',
|
||||||
|
@@ -146,7 +147,9 @@ if have_networkmanager
|
||||||
|
libshell_sources += 'shell-network-agent.c'
|
||||||
|
endif
|
||||||
|
|
||||||
|
-libshell_private_sources = []
|
||||||
|
+libshell_private_sources = [
|
||||||
|
+ 'shell-app-cache.c',
|
||||||
|
+]
|
||||||
|
|
||||||
|
if enable_recorder
|
||||||
|
libshell_sources += ['shell-recorder.c']
|
||||||
|
diff --git a/src/shell-app-cache-private.h b/src/shell-app-cache-private.h
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..b73094ab1
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/shell-app-cache-private.h
|
||||||
|
@@ -0,0 +1,19 @@
|
||||||
|
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
+#ifndef __SHELL_APP_CACHE_PRIVATE_H__
|
||||||
|
+#define __SHELL_APP_CACHE_PRIVATE_H__
|
||||||
|
+
|
||||||
|
+#include <gio/gio.h>
|
||||||
|
+#include <gio/gdesktopappinfo.h>
|
||||||
|
+
|
||||||
|
+#define SHELL_TYPE_APP_CACHE (shell_app_cache_get_type())
|
||||||
|
+
|
||||||
|
+G_DECLARE_FINAL_TYPE (ShellAppCache, shell_app_cache, SHELL, APP_CACHE, GObject)
|
||||||
|
+
|
||||||
|
+ShellAppCache *shell_app_cache_get_default (void);
|
||||||
|
+GList *shell_app_cache_get_all (ShellAppCache *cache);
|
||||||
|
+GDesktopAppInfo *shell_app_cache_get_info (ShellAppCache *cache,
|
||||||
|
+ const char *id);
|
||||||
|
+char *shell_app_cache_translate_folder (ShellAppCache *cache,
|
||||||
|
+ const char *name);
|
||||||
|
+
|
||||||
|
+#endif /* __SHELL_APP_CACHE_PRIVATE_H__ */
|
||||||
|
diff --git a/src/shell-app-cache.c b/src/shell-app-cache.c
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..15d4734d0
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/shell-app-cache.c
|
||||||
|
@@ -0,0 +1,404 @@
|
||||||
|
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
+
|
||||||
|
+#include "config.h"
|
||||||
|
+
|
||||||
|
+#include "shell-app-cache-private.h"
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * SECTION:shell-app-cache
|
||||||
|
+ * @title: ShellAppCache
|
||||||
|
+ * @short_description: application information cache
|
||||||
|
+ *
|
||||||
|
+ * The #ShellAppCache is responsible for caching information about #GAppInfo
|
||||||
|
+ * to ensure that the compositor thread never needs to perform disk reads to
|
||||||
|
+ * access them. All of the work is done off-thread. When the new data has
|
||||||
|
+ * been loaded, a #ShellAppCache::changed signal is emitted.
|
||||||
|
+ *
|
||||||
|
+ * Additionally, the #ShellAppCache caches information about translations for
|
||||||
|
+ * directories. This allows translation provided in [Desktop Entry] GKeyFiles
|
||||||
|
+ * to be available when building StLabel and other elements without performing
|
||||||
|
+ * costly disk reads.
|
||||||
|
+ *
|
||||||
|
+ * Various monitors are used to keep this information up to date while the
|
||||||
|
+ * Shell is running.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#define DEFAULT_TIMEOUT_SECONDS 5
|
||||||
|
+
|
||||||
|
+struct _ShellAppCache
|
||||||
|
+{
|
||||||
|
+ GObject parent_instance;
|
||||||
|
+
|
||||||
|
+ GAppInfoMonitor *monitor;
|
||||||
|
+ GPtrArray *dir_monitors;
|
||||||
|
+ GHashTable *folders;
|
||||||
|
+ GCancellable *cancellable;
|
||||||
|
+ GList *app_infos;
|
||||||
|
+
|
||||||
|
+ guint queued_update;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+typedef struct
|
||||||
|
+{
|
||||||
|
+ GList *app_infos;
|
||||||
|
+ GHashTable *folders;
|
||||||
|
+} CacheState;
|
||||||
|
+
|
||||||
|
+G_DEFINE_TYPE (ShellAppCache, shell_app_cache, G_TYPE_OBJECT)
|
||||||
|
+
|
||||||
|
+enum {
|
||||||
|
+ CHANGED,
|
||||||
|
+ N_SIGNALS
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static guint signals [N_SIGNALS];
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+cache_state_free (CacheState *state)
|
||||||
|
+{
|
||||||
|
+ g_clear_pointer (&state->folders, g_hash_table_unref);
|
||||||
|
+ g_list_free_full (state->app_infos, g_object_unref);
|
||||||
|
+ g_slice_free (CacheState, state);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static CacheState *
|
||||||
|
+cache_state_new (void)
|
||||||
|
+{
|
||||||
|
+ CacheState *state;
|
||||||
|
+
|
||||||
|
+ state = g_slice_new0 (CacheState);
|
||||||
|
+ state->folders = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
+
|
||||||
|
+ return g_steal_pointer (&state);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * shell_app_cache_get_default:
|
||||||
|
+ *
|
||||||
|
+ * Gets the default #ShellAppCache.
|
||||||
|
+ *
|
||||||
|
+ * Returns: (transfer none): a #ShellAppCache
|
||||||
|
+ */
|
||||||
|
+ShellAppCache *
|
||||||
|
+shell_app_cache_get_default (void)
|
||||||
|
+{
|
||||||
|
+ static ShellAppCache *instance;
|
||||||
|
+
|
||||||
|
+ if (instance == NULL)
|
||||||
|
+ {
|
||||||
|
+ instance = g_object_new (SHELL_TYPE_APP_CACHE, NULL);
|
||||||
|
+ g_object_add_weak_pointer (G_OBJECT (instance), (gpointer *)&instance);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return instance;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+load_folder (GHashTable *folders,
|
||||||
|
+ const char *path)
|
||||||
|
+{
|
||||||
|
+ g_autoptr(GDir) dir = NULL;
|
||||||
|
+ const char *name;
|
||||||
|
+
|
||||||
|
+ g_assert (folders != NULL);
|
||||||
|
+ g_assert (path != NULL);
|
||||||
|
+
|
||||||
|
+ dir = g_dir_open (path, 0, NULL);
|
||||||
|
+ if (dir == NULL)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ while ((name = g_dir_read_name (dir)))
|
||||||
|
+ {
|
||||||
|
+ g_autofree gchar *filename = NULL;
|
||||||
|
+ g_autoptr(GKeyFile) keyfile = NULL;
|
||||||
|
+
|
||||||
|
+ /* First added wins */
|
||||||
|
+ if (g_hash_table_contains (folders, name))
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ filename = g_build_filename (path, name, NULL);
|
||||||
|
+ keyfile = g_key_file_new ();
|
||||||
|
+
|
||||||
|
+ if (g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, NULL))
|
||||||
|
+ {
|
||||||
|
+ gchar *translated;
|
||||||
|
+
|
||||||
|
+ translated = g_key_file_get_locale_string (keyfile,
|
||||||
|
+ "Desktop Entry", "Name",
|
||||||
|
+ NULL, NULL);
|
||||||
|
+
|
||||||
|
+ if (translated != NULL)
|
||||||
|
+ g_hash_table_insert (folders, g_strdup (name), translated);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+load_folders (GHashTable *folders)
|
||||||
|
+{
|
||||||
|
+ const char * const *dirs;
|
||||||
|
+ g_autofree gchar *userdir = NULL;
|
||||||
|
+ guint i;
|
||||||
|
+
|
||||||
|
+ g_assert (folders != NULL);
|
||||||
|
+
|
||||||
|
+ userdir = g_build_filename (g_get_user_data_dir (), "desktop-directories", NULL);
|
||||||
|
+ load_folder (folders, userdir);
|
||||||
|
+
|
||||||
|
+ dirs = g_get_system_data_dirs ();
|
||||||
|
+ for (i = 0; dirs[i] != NULL; i++)
|
||||||
|
+ {
|
||||||
|
+ g_autofree gchar *sysdir = g_build_filename (dirs[i], "desktop-directories", NULL);
|
||||||
|
+ load_folder (folders, sysdir);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+shell_app_cache_worker (GTask *task,
|
||||||
|
+ gpointer source_object,
|
||||||
|
+ gpointer task_data,
|
||||||
|
+ GCancellable *cancellable)
|
||||||
|
+{
|
||||||
|
+ CacheState *state;
|
||||||
|
+
|
||||||
|
+ g_assert (G_IS_TASK (task));
|
||||||
|
+ g_assert (SHELL_IS_APP_CACHE (source_object));
|
||||||
|
+
|
||||||
|
+ state = cache_state_new ();
|
||||||
|
+ state->app_infos = g_app_info_get_all ();
|
||||||
|
+ load_folders (state->folders);
|
||||||
|
+
|
||||||
|
+ g_task_return_pointer (task, state, (GDestroyNotify) cache_state_free);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+apply_update_cb (GObject *object,
|
||||||
|
+ GAsyncResult *result,
|
||||||
|
+ gpointer user_data)
|
||||||
|
+{
|
||||||
|
+ ShellAppCache *cache = (ShellAppCache *)object;
|
||||||
|
+ g_autoptr(GError) error = NULL;
|
||||||
|
+ CacheState *state;
|
||||||
|
+
|
||||||
|
+ g_assert (SHELL_IS_APP_CACHE (cache));
|
||||||
|
+ g_assert (G_IS_TASK (result));
|
||||||
|
+ g_assert (user_data == NULL);
|
||||||
|
+
|
||||||
|
+ state = g_task_propagate_pointer (G_TASK (result), &error);
|
||||||
|
+
|
||||||
|
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ g_list_free_full (cache->app_infos, g_object_unref);
|
||||||
|
+ cache->app_infos = g_steal_pointer (&state->app_infos);
|
||||||
|
+
|
||||||
|
+ g_clear_pointer (&cache->folders, g_hash_table_unref);
|
||||||
|
+ cache->folders = g_steal_pointer (&state->folders);
|
||||||
|
+
|
||||||
|
+ g_signal_emit (cache, signals[CHANGED], 0);
|
||||||
|
+
|
||||||
|
+ cache_state_free (state);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static gboolean
|
||||||
|
+shell_app_cache_do_update (gpointer user_data)
|
||||||
|
+{
|
||||||
|
+ ShellAppCache *cache = user_data;
|
||||||
|
+ g_autoptr(GTask) task = NULL;
|
||||||
|
+
|
||||||
|
+ cache->queued_update = 0;
|
||||||
|
+
|
||||||
|
+ /* Reset the cancellable state so we don't race with
|
||||||
|
+ * two updates coming back overlapped and applying the
|
||||||
|
+ * information in the wrong order.
|
||||||
|
+ */
|
||||||
|
+ g_cancellable_cancel (cache->cancellable);
|
||||||
|
+ g_clear_object (&cache->cancellable);
|
||||||
|
+ cache->cancellable = g_cancellable_new ();
|
||||||
|
+
|
||||||
|
+ task = g_task_new (cache, cache->cancellable, apply_update_cb, NULL);
|
||||||
|
+ g_task_set_source_tag (task, shell_app_cache_do_update);
|
||||||
|
+ g_task_run_in_thread (task, shell_app_cache_worker);
|
||||||
|
+
|
||||||
|
+ return G_SOURCE_REMOVE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+shell_app_cache_queue_update (ShellAppCache *self)
|
||||||
|
+{
|
||||||
|
+ g_assert (SHELL_IS_APP_CACHE (self));
|
||||||
|
+
|
||||||
|
+ if (self->queued_update != 0)
|
||||||
|
+ g_source_remove (self->queued_update);
|
||||||
|
+
|
||||||
|
+ self->queued_update = g_timeout_add_seconds (DEFAULT_TIMEOUT_SECONDS,
|
||||||
|
+ shell_app_cache_do_update,
|
||||||
|
+ self);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+monitor_desktop_directories_for_data_dir (ShellAppCache *self,
|
||||||
|
+ const gchar *directory)
|
||||||
|
+{
|
||||||
|
+ g_autofree gchar *subdir = NULL;
|
||||||
|
+ g_autoptr(GFile) file = NULL;
|
||||||
|
+ g_autoptr(GFileMonitor) monitor = NULL;
|
||||||
|
+
|
||||||
|
+ g_assert (SHELL_IS_APP_CACHE (self));
|
||||||
|
+
|
||||||
|
+ if (directory == NULL)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ subdir = g_build_filename (directory, "desktop-directories", NULL);
|
||||||
|
+ file = g_file_new_for_path (subdir);
|
||||||
|
+ monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
|
||||||
|
+
|
||||||
|
+ if (monitor != NULL)
|
||||||
|
+ {
|
||||||
|
+ g_file_monitor_set_rate_limit (monitor, DEFAULT_TIMEOUT_SECONDS * 1000);
|
||||||
|
+ g_signal_connect_object (monitor,
|
||||||
|
+ "changed",
|
||||||
|
+ G_CALLBACK (shell_app_cache_queue_update),
|
||||||
|
+ self,
|
||||||
|
+ G_CONNECT_SWAPPED);
|
||||||
|
+ g_ptr_array_add (self->dir_monitors, g_steal_pointer (&monitor));
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+shell_app_cache_finalize (GObject *object)
|
||||||
|
+{
|
||||||
|
+ ShellAppCache *self = (ShellAppCache *)object;
|
||||||
|
+
|
||||||
|
+ g_clear_object (&self->monitor);
|
||||||
|
+
|
||||||
|
+ if (self->queued_update)
|
||||||
|
+ {
|
||||||
|
+ g_source_remove (self->queued_update);
|
||||||
|
+ self->queued_update = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ g_clear_pointer (&self->dir_monitors, g_ptr_array_unref);
|
||||||
|
+ g_clear_pointer (&self->folders, g_hash_table_unref);
|
||||||
|
+ g_list_free_full (self->app_infos, g_object_unref);
|
||||||
|
+
|
||||||
|
+ G_OBJECT_CLASS (shell_app_cache_parent_class)->finalize (object);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+shell_app_cache_class_init (ShellAppCacheClass *klass)
|
||||||
|
+{
|
||||||
|
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
+
|
||||||
|
+ object_class->finalize = shell_app_cache_finalize;
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * ShellAppCache::changed:
|
||||||
|
+ *
|
||||||
|
+ * The "changed" signal is emitted when the cache has updated
|
||||||
|
+ * information about installed applications.
|
||||||
|
+ */
|
||||||
|
+ signals [CHANGED] =
|
||||||
|
+ g_signal_new ("changed",
|
||||||
|
+ G_TYPE_FROM_CLASS (klass),
|
||||||
|
+ G_SIGNAL_RUN_LAST,
|
||||||
|
+ 0, NULL, NULL, NULL,
|
||||||
|
+ G_TYPE_NONE, 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+shell_app_cache_init (ShellAppCache *self)
|
||||||
|
+{
|
||||||
|
+ const gchar * const *sysdirs;
|
||||||
|
+ guint i;
|
||||||
|
+
|
||||||
|
+ /* Monitor directories for translation changes */
|
||||||
|
+ self->dir_monitors = g_ptr_array_new_with_free_func (g_object_unref);
|
||||||
|
+ monitor_desktop_directories_for_data_dir (self, g_get_user_data_dir ());
|
||||||
|
+ sysdirs = g_get_system_data_dirs ();
|
||||||
|
+ for (i = 0; sysdirs[i] != NULL; i++)
|
||||||
|
+ monitor_desktop_directories_for_data_dir (self, sysdirs[i]);
|
||||||
|
+
|
||||||
|
+ /* Load translated directory names immediately */
|
||||||
|
+ self->folders = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
+ load_folders (self->folders);
|
||||||
|
+
|
||||||
|
+ /* Setup AppMonitor to track changes */
|
||||||
|
+ self->monitor = g_app_info_monitor_get ();
|
||||||
|
+ g_signal_connect_object (self->monitor,
|
||||||
|
+ "changed",
|
||||||
|
+ G_CALLBACK (shell_app_cache_queue_update),
|
||||||
|
+ self,
|
||||||
|
+ G_CONNECT_SWAPPED);
|
||||||
|
+ self->app_infos = g_app_info_get_all ();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * shell_app_cache_get_all:
|
||||||
|
+ * @cache: (nullable): a #ShellAppCache or %NULL
|
||||||
|
+ *
|
||||||
|
+ * Like g_app_info_get_all() but always returns a
|
||||||
|
+ * cached set of application info so the caller can be
|
||||||
|
+ * sure that I/O will not happen on the current thread.
|
||||||
|
+ *
|
||||||
|
+ * Returns: (transfer none) (element-type GAppInfo):
|
||||||
|
+ * a #GList of references to #GAppInfo.
|
||||||
|
+ */
|
||||||
|
+GList *
|
||||||
|
+shell_app_cache_get_all (ShellAppCache *cache)
|
||||||
|
+{
|
||||||
|
+ g_return_val_if_fail (SHELL_IS_APP_CACHE (cache), NULL);
|
||||||
|
+
|
||||||
|
+ return cache->app_infos;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * shell_app_cache_get_info:
|
||||||
|
+ * @cache: (nullable): a #ShellAppCache or %NULL
|
||||||
|
+ * @id: the application id
|
||||||
|
+ *
|
||||||
|
+ * A replacement for g_desktop_app_info_new() that will lookup the
|
||||||
|
+ * information from the cache instead of (re)loading from disk.
|
||||||
|
+ *
|
||||||
|
+ * Returns: (nullable) (transfer none): a #GDesktopAppInfo or %NULL
|
||||||
|
+ */
|
||||||
|
+GDesktopAppInfo *
|
||||||
|
+shell_app_cache_get_info (ShellAppCache *cache,
|
||||||
|
+ const char *id)
|
||||||
|
+{
|
||||||
|
+ const GList *iter;
|
||||||
|
+
|
||||||
|
+ g_return_val_if_fail (SHELL_IS_APP_CACHE (cache), NULL);
|
||||||
|
+
|
||||||
|
+ for (iter = cache->app_infos; iter != NULL; iter = iter->next)
|
||||||
|
+ {
|
||||||
|
+ GAppInfo *info = iter->data;
|
||||||
|
+
|
||||||
|
+ if (g_strcmp0 (id, g_app_info_get_id (info)) == 0)
|
||||||
|
+ return G_DESKTOP_APP_INFO (info);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * shell_app_cache_translate_folder:
|
||||||
|
+ * @cache: (nullable): a #ShellAppCache or %NULL
|
||||||
|
+ * @name: the folder name
|
||||||
|
+ *
|
||||||
|
+ * Gets the translated folder name for @name if any exists.
|
||||||
|
+ *
|
||||||
|
+ * Returns: (nullable): the translated string or %NULL if there is no
|
||||||
|
+ * translation.
|
||||||
|
+ */
|
||||||
|
+char *
|
||||||
|
+shell_app_cache_translate_folder (ShellAppCache *cache,
|
||||||
|
+ const char *name)
|
||||||
|
+{
|
||||||
|
+ g_return_val_if_fail (SHELL_IS_APP_CACHE (cache), NULL);
|
||||||
|
+
|
||||||
|
+ if (name == NULL)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ return g_strdup (g_hash_table_lookup (cache->folders, name));
|
||||||
|
+}
|
||||||
|
diff --git a/src/shell-app-system.c b/src/shell-app-system.c
|
||||||
|
index 127f29ef0..828fa726a 100644
|
||||||
|
--- a/src/shell-app-system.c
|
||||||
|
+++ b/src/shell-app-system.c
|
||||||
|
@@ -9,6 +9,7 @@
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
+#include "shell-app-cache-private.h"
|
||||||
|
#include "shell-app-private.h"
|
||||||
|
#include "shell-window-tracker-private.h"
|
||||||
|
#include "shell-app-system-private.h"
|
||||||
|
@@ -94,14 +95,14 @@ static void
|
||||||
|
scan_startup_wm_class_to_id (ShellAppSystem *self)
|
||||||
|
{
|
||||||
|
ShellAppSystemPrivate *priv = self->priv;
|
||||||
|
- GList *l;
|
||||||
|
+ const GList *l;
|
||||||
|
+ GList *all;
|
||||||
|
|
||||||
|
g_hash_table_remove_all (priv->startup_wm_class_to_id);
|
||||||
|
|
||||||
|
- g_list_free_full (priv->installed_apps, g_object_unref);
|
||||||
|
- priv->installed_apps = g_app_info_get_all ();
|
||||||
|
+ all = shell_app_cache_get_all (shell_app_cache_get_default ());
|
||||||
|
|
||||||
|
- for (l = priv->installed_apps; l != NULL; l = l->next)
|
||||||
|
+ for (l = all; l != NULL; l = l->next)
|
||||||
|
{
|
||||||
|
GAppInfo *info = l->data;
|
||||||
|
const char *startup_wm_class, *id, *old_id;
|
||||||
|
@@ -131,7 +132,8 @@ app_is_stale (ShellApp *app)
|
||||||
|
if (shell_app_is_window_backed (app))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
- info = g_desktop_app_info_new (shell_app_get_id (app));
|
||||||
|
+ info = shell_app_cache_get_info (shell_app_cache_get_default (),
|
||||||
|
+ shell_app_get_id (app));
|
||||||
|
if (!info)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
@@ -156,7 +158,6 @@ app_is_stale (ShellApp *app)
|
||||||
|
g_icon_equal (g_app_info_get_icon (old_info),
|
||||||
|
g_app_info_get_icon (new_info));
|
||||||
|
|
||||||
|
- g_object_unref (info);
|
||||||
|
return !is_unchanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -210,11 +211,9 @@ rescan_icon_theme (ShellAppSystem *self)
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
-installed_changed (GAppInfoMonitor *monitor,
|
||||||
|
- gpointer user_data)
|
||||||
|
+installed_changed (ShellAppCache *cache,
|
||||||
|
+ ShellAppSystem *self)
|
||||||
|
{
|
||||||
|
- ShellAppSystem *self = user_data;
|
||||||
|
-
|
||||||
|
rescan_icon_theme (self);
|
||||||
|
scan_startup_wm_class_to_id (self);
|
||||||
|
|
||||||
|
@@ -227,7 +226,7 @@ static void
|
||||||
|
shell_app_system_init (ShellAppSystem *self)
|
||||||
|
{
|
||||||
|
ShellAppSystemPrivate *priv;
|
||||||
|
- GAppInfoMonitor *monitor;
|
||||||
|
+ ShellAppCache *cache;
|
||||||
|
|
||||||
|
self->priv = priv = shell_app_system_get_instance_private (self);
|
||||||
|
|
||||||
|
@@ -238,9 +237,9 @@ shell_app_system_init (ShellAppSystem *self)
|
||||||
|
|
||||||
|
priv->startup_wm_class_to_id = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
|
||||||
|
- monitor = g_app_info_monitor_get ();
|
||||||
|
- g_signal_connect (monitor, "changed", G_CALLBACK (installed_changed), self);
|
||||||
|
- installed_changed (monitor, self);
|
||||||
|
+ cache = shell_app_cache_get_default ();
|
||||||
|
+ g_signal_connect (cache, "changed", G_CALLBACK (installed_changed), self);
|
||||||
|
+ installed_changed (cache, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -293,13 +292,12 @@ shell_app_system_lookup_app (ShellAppSystem *self,
|
||||||
|
if (app)
|
||||||
|
return app;
|
||||||
|
|
||||||
|
- info = g_desktop_app_info_new (id);
|
||||||
|
+ info = shell_app_cache_get_info (shell_app_cache_get_default (), id);
|
||||||
|
if (!info)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
app = _shell_app_new (info);
|
||||||
|
g_hash_table_insert (priv->id_to_app, (char *) shell_app_get_id (app), app);
|
||||||
|
- g_object_unref (info);
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -506,7 +504,5 @@ shell_app_system_search (const char *search_string)
|
||||||
|
GList *
|
||||||
|
shell_app_system_get_installed (ShellAppSystem *self)
|
||||||
|
{
|
||||||
|
- ShellAppSystemPrivate *priv = self->priv;
|
||||||
|
-
|
||||||
|
- return priv->installed_apps;
|
||||||
|
+ return shell_app_cache_get_all (shell_app_cache_get_default ());
|
||||||
|
}
|
||||||
|
diff --git a/src/shell-util.c b/src/shell-util.c
|
||||||
|
index fa3fc08c8..370784523 100644
|
||||||
|
--- a/src/shell-util.c
|
||||||
|
+++ b/src/shell-util.c
|
||||||
|
@@ -16,6 +16,7 @@
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
|
||||||
|
+#include "shell-app-cache-private.h"
|
||||||
|
#include "shell-util.h"
|
||||||
|
#include <glib/gi18n-lib.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
@@ -639,3 +640,18 @@ shell_util_has_x11_display_extension (MetaDisplay *display,
|
||||||
|
xdisplay = meta_x11_display_get_xdisplay (x11_display);
|
||||||
|
return XQueryExtension (xdisplay, extension, &op, &event, &error);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * shell_util_get_translated_folder_name:
|
||||||
|
+ * @name: the untranslated folder name
|
||||||
|
+ *
|
||||||
|
+ * Attempts to translate the folder @name using translations provided
|
||||||
|
+ * by .directory files.
|
||||||
|
+ *
|
||||||
|
+ * Returns: (nullable): a translated string or %NULL
|
||||||
|
+ */
|
||||||
|
+char *
|
||||||
|
+shell_util_get_translated_folder_name (const char *name)
|
||||||
|
+{
|
||||||
|
+ return shell_app_cache_translate_folder (shell_app_cache_get_default (), name);
|
||||||
|
+}
|
||||||
|
diff --git a/src/shell-util.h b/src/shell-util.h
|
||||||
|
index 02b8404e9..843a1253d 100644
|
||||||
|
--- a/src/shell-util.h
|
||||||
|
+++ b/src/shell-util.h
|
||||||
|
@@ -62,6 +62,8 @@ void shell_util_check_cloexec_fds (void);
|
||||||
|
gboolean shell_util_has_x11_display_extension (MetaDisplay *display,
|
||||||
|
const char *extension);
|
||||||
|
|
||||||
|
+char *shell_util_get_translated_folder_name (const char *name);
|
||||||
|
+
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __SHELL_UTIL_H__ */
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -0,0 +1,36 @@
|
|||||||
|
From 7a264550c5f3a98b1786b1a75cff01cde1d084eb Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Thu, 29 Jul 2021 17:17:43 +0200
|
||||||
|
Subject: [PATCH 5/5] shellEntry: Only mask text in password entries
|
||||||
|
|
||||||
|
When "Show Text" is locked down, we not only remove the corresponding
|
||||||
|
menu item, but also make sure the password is masked.
|
||||||
|
|
||||||
|
Except that the current code is too eager, and masks the text in
|
||||||
|
any entries.
|
||||||
|
---
|
||||||
|
js/ui/shellEntry.js | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js
|
||||||
|
index c45e4545a..64b389050 100644
|
||||||
|
--- a/js/ui/shellEntry.js
|
||||||
|
+++ b/js/ui/shellEntry.js
|
||||||
|
@@ -55,11 +55,13 @@ var EntryMenu = class extends PopupMenu.PopupMenu {
|
||||||
|
this._passwordItem.destroy();
|
||||||
|
this._passwordItem = null;
|
||||||
|
}
|
||||||
|
- this._entry.clutter_text.set_password_char('\u25cf');
|
||||||
|
} else if (this.isPassword && !passwordDisabled) {
|
||||||
|
if (!this._passwordItem)
|
||||||
|
this._makePasswordItem();
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (this.isPassword && passwordDisabled)
|
||||||
|
+ this._entry.clutter_text.set_password_char('\u25cf');
|
||||||
|
}
|
||||||
|
|
||||||
|
get isPassword() {
|
||||||
|
--
|
||||||
|
2.31.1
|
||||||
|
|
@ -0,0 +1,66 @@
|
|||||||
|
From a0df79f8de4c13c36ed3b22cfdbb78e324424ef1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Sat, 14 Mar 2020 14:45:42 +0100
|
||||||
|
Subject: [PATCH 6/6] js: Always use AppSystem to lookup apps
|
||||||
|
|
||||||
|
There is no good reason for bypassing the application cache in
|
||||||
|
AppSystem and loading .desktop files again.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1093
|
||||||
|
---
|
||||||
|
js/ui/appDisplay.js | 4 ++--
|
||||||
|
js/ui/calendar.js | 16 ++++++++++------
|
||||||
|
2 files changed, 12 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
|
||||||
|
index a2d691085..cb2be7d3c 100644
|
||||||
|
--- a/js/ui/appDisplay.js
|
||||||
|
+++ b/js/ui/appDisplay.js
|
||||||
|
@@ -1001,8 +1001,8 @@ var AppSearchProvider = class AppSearchProvider {
|
||||||
|
let results = [];
|
||||||
|
groups.forEach(group => {
|
||||||
|
group = group.filter(appID => {
|
||||||
|
- let app = Gio.DesktopAppInfo.new(appID);
|
||||||
|
- return app && app.should_show();
|
||||||
|
+ const app = this._appSys.lookup_app(appID);
|
||||||
|
+ return app && app.app_info.should_show();
|
||||||
|
});
|
||||||
|
results = results.concat(group.sort(
|
||||||
|
(a, b) => usage.compare(a, b)
|
||||||
|
diff --git a/js/ui/calendar.js b/js/ui/calendar.js
|
||||||
|
index cd3e879c4..3ae2e44f8 100644
|
||||||
|
--- a/js/ui/calendar.js
|
||||||
|
+++ b/js/ui/calendar.js
|
||||||
|
@@ -791,8 +791,9 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection {
|
||||||
|
this._title.connect('clicked', this._onTitleClicked.bind(this));
|
||||||
|
this._title.connect('key-focus-in', this._onKeyFocusIn.bind(this));
|
||||||
|
|
||||||
|
- Shell.AppSystem.get_default().connect('installed-changed',
|
||||||
|
- this._appInstalledChanged.bind(this));
|
||||||
|
+ this._appSys = Shell.AppSystem.get_default();
|
||||||
|
+ this._appSys.connect('installed-changed',
|
||||||
|
+ this._appInstalledChanged.bind(this));
|
||||||
|
this._appInstalledChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -883,10 +884,13 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection {
|
||||||
|
Main.overview.hide();
|
||||||
|
Main.panel.closeCalendar();
|
||||||
|
|
||||||
|
- let app = this._getCalendarApp();
|
||||||
|
- if (app.get_id() == 'evolution.desktop')
|
||||||
|
- app = Gio.DesktopAppInfo.new('evolution-calendar.desktop');
|
||||||
|
- app.launch([], global.create_app_launch_context(0, -1));
|
||||||
|
+ let appInfo = this._getCalendarApp();
|
||||||
|
+ if (app.get_id() == 'evolution.desktop') {
|
||||||
|
+ let app = this._appSys.lookup_app('evolution-calendar.desktop');
|
||||||
|
+ if (app)
|
||||||
|
+ appInfo = app.app_info;
|
||||||
|
+ }
|
||||||
|
+ appInfo.launch([], global.create_app_launch_context(0, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
setDate(date) {
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -1,333 +0,0 @@
|
|||||||
From 2103c5fcf994bb6aebd978553b338436e85fa7ed Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
||||||
Date: Wed, 7 Jul 2021 22:05:25 +0200
|
|
||||||
Subject: [PATCH 1/2] status/powerProfiles: Add power mode selection
|
|
||||||
|
|
||||||
Settings' power panel gained support for switchable power profiles
|
|
||||||
in GNOME 40. It's useful to have that functionality more readily
|
|
||||||
available, so expose it in the system status menu as well.
|
|
||||||
|
|
||||||
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3944
|
|
||||||
|
|
||||||
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1907>
|
|
||||||
---
|
|
||||||
.../net.hadess.PowerProfiles.xml | 76 ++++++++++++
|
|
||||||
.../gnome-shell-dbus-interfaces.gresource.xml | 1 +
|
|
||||||
js/js-resources.gresource.xml | 1 +
|
|
||||||
js/ui/panel.js | 4 +
|
|
||||||
js/ui/status/powerProfiles.js | 111 ++++++++++++++++++
|
|
||||||
po/POTFILES.in | 1 +
|
|
||||||
6 files changed, 194 insertions(+)
|
|
||||||
create mode 100644 data/dbus-interfaces/net.hadess.PowerProfiles.xml
|
|
||||||
create mode 100644 js/ui/status/powerProfiles.js
|
|
||||||
|
|
||||||
diff --git a/data/dbus-interfaces/net.hadess.PowerProfiles.xml b/data/dbus-interfaces/net.hadess.PowerProfiles.xml
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000..fce04a86d
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/data/dbus-interfaces/net.hadess.PowerProfiles.xml
|
|
||||||
@@ -0,0 +1,76 @@
|
|
||||||
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
|
||||||
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
|
||||||
+
|
|
||||||
+<node>
|
|
||||||
+
|
|
||||||
+ <!--
|
|
||||||
+ net.hadess.PowerProfiles:
|
|
||||||
+ @short_description: Power Profiles daemon
|
|
||||||
+
|
|
||||||
+ The power-profiles-daemon API is meant to be used by parts of the OS or
|
|
||||||
+ desktop environment to switch system power profiles based on user choice,
|
|
||||||
+ or user intent.
|
|
||||||
+
|
|
||||||
+ OS components would typically use the "Profiles" property to construct
|
|
||||||
+ their UI (2 or 3 profiles available), and monitor the "ActiveProfile"
|
|
||||||
+ and the "PerformanceInhibited" properties to update that UI. The UI
|
|
||||||
+ would try to set the "ActiveProfile" property if the user selected
|
|
||||||
+ a different one.
|
|
||||||
+
|
|
||||||
+ Note that the reason why the project exists and how it is different from
|
|
||||||
+ existing projects is explained <ulink href=" https://gitlab.freedesktop.org/hadess/power-profiles-daemon/-/blob/master/README.md">
|
|
||||||
+ in the project's README file</ulink>.
|
|
||||||
+
|
|
||||||
+ The object path will be "/net/hadess/PowerProfiles".
|
|
||||||
+ -->
|
|
||||||
+ <interface name="net.hadess.PowerProfiles">
|
|
||||||
+ <!--
|
|
||||||
+ ActiveProfile:
|
|
||||||
+
|
|
||||||
+ The type of the currently active profile. It might change automatically
|
|
||||||
+ if the "performance" profile was selected but it got inhibited, in which
|
|
||||||
+ case the "PerformanceInhibited" property will reflect the reason.
|
|
||||||
+ -->
|
|
||||||
+ <property name="ActiveProfile" type="s" access="readwrite"/>
|
|
||||||
+
|
|
||||||
+ <!--
|
|
||||||
+ PerformanceInhibited:
|
|
||||||
+
|
|
||||||
+ This will be set if the performance power profile is unavailable, with
|
|
||||||
+ the value being used to identify the reason for unavailability. As new
|
|
||||||
+ reasons can be added, it is recommended that front-ends show a generic
|
|
||||||
+ reason if they do not recognise the value. Possible values are:
|
|
||||||
+ - "lap-detected" (the computer is sitting on the user's lap)
|
|
||||||
+ - "high-operating-temperature" (the computer is close to overheating)
|
|
||||||
+ - "" (the empty string, if not inhibited)
|
|
||||||
+ -->
|
|
||||||
+ <property name="PerformanceInhibited" type="s" access="read"/>
|
|
||||||
+
|
|
||||||
+ <!--
|
|
||||||
+ Profiles:
|
|
||||||
+
|
|
||||||
+ An array of key-pair values representing each profile. The key named
|
|
||||||
+ "Driver" (s) identifies the power-profiles-daemon backend code used to
|
|
||||||
+ implement the profile.
|
|
||||||
+
|
|
||||||
+ The key named "Profile" (s) will be one of:
|
|
||||||
+ - "power-saver" (battery saving profile)
|
|
||||||
+ - "balanced" (the default profile)
|
|
||||||
+ - "performance" (a profile that does not care about noise or battery consumption)
|
|
||||||
+
|
|
||||||
+ Only one of each type of profile will be listed, with the daemon choosing the
|
|
||||||
+ more appropriate "driver" for each profile type.
|
|
||||||
+ -->
|
|
||||||
+ <property name="Profiles" type="aa{sv}" access="read"/>
|
|
||||||
+
|
|
||||||
+ <!--
|
|
||||||
+ Actions:
|
|
||||||
+
|
|
||||||
+ An array of strings listing each one of the "actions" implemented in
|
|
||||||
+ the running daemon. This is used by API users to figure out whether
|
|
||||||
+ particular functionality is available in a version of the daemon.
|
|
||||||
+ -->
|
|
||||||
+ <property name="Actions" type="as" access="read"/>
|
|
||||||
+
|
|
||||||
+ </interface>
|
|
||||||
+</node>
|
|
||||||
diff --git a/data/gnome-shell-dbus-interfaces.gresource.xml b/data/gnome-shell-dbus-interfaces.gresource.xml
|
|
||||||
index e7972f6cb..6682c462d 100644
|
|
||||||
--- a/data/gnome-shell-dbus-interfaces.gresource.xml
|
|
||||||
+++ b/data/gnome-shell-dbus-interfaces.gresource.xml
|
|
||||||
@@ -1,6 +1,7 @@
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<gresources>
|
|
||||||
<gresource prefix="/org/gnome/shell/dbus-interfaces">
|
|
||||||
+ <file preprocess="xml-stripblanks">net.hadess.PowerProfiles.xml</file>
|
|
||||||
<file preprocess="xml-stripblanks">net.hadess.SensorProxy.xml</file>
|
|
||||||
<file preprocess="xml-stripblanks">net.reactivated.Fprint.Device.xml</file>
|
|
||||||
<file preprocess="xml-stripblanks">net.reactivated.Fprint.Manager.xml</file>
|
|
||||||
diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
|
|
||||||
index b2c603a55..7a94e2ff1 100644
|
|
||||||
--- a/js/js-resources.gresource.xml
|
|
||||||
+++ b/js/js-resources.gresource.xml
|
|
||||||
@@ -134,6 +134,7 @@
|
|
||||||
<file>ui/status/nightLight.js</file>
|
|
||||||
<file>ui/status/network.js</file>
|
|
||||||
<file>ui/status/power.js</file>
|
|
||||||
+ <file>ui/status/powerProfiles.js</file>
|
|
||||||
<file>ui/status/rfkill.js</file>
|
|
||||||
<file>ui/status/volume.js</file>
|
|
||||||
<file>ui/status/bluetooth.js</file>
|
|
||||||
diff --git a/js/ui/panel.js b/js/ui/panel.js
|
|
||||||
index ad11f4ba2..84668e96e 100644
|
|
||||||
--- a/js/ui/panel.js
|
|
||||||
+++ b/js/ui/panel.js
|
|
||||||
@@ -693,6 +693,7 @@ class AggregateMenu extends PanelMenu.Button {
|
|
||||||
|
|
||||||
this._remoteAccess = new imports.ui.status.remoteAccess.RemoteAccessApplet();
|
|
||||||
this._power = new imports.ui.status.power.Indicator();
|
|
||||||
+ this._powerProfiles = new imports.ui.status.powerProfiles.Indicator();
|
|
||||||
this._rfkill = new imports.ui.status.rfkill.Indicator();
|
|
||||||
this._volume = new imports.ui.status.volume.Indicator();
|
|
||||||
this._brightness = new imports.ui.status.brightness.Indicator();
|
|
||||||
@@ -712,6 +713,7 @@ class AggregateMenu extends PanelMenu.Button {
|
|
||||||
this._indicators.add_child(this._rfkill);
|
|
||||||
this._indicators.add_child(this._volume);
|
|
||||||
this._indicators.add_child(this._power);
|
|
||||||
+ this._indicators.add_child(this._powerProfiles);
|
|
||||||
|
|
||||||
this.menu.addMenuItem(this._volume.menu);
|
|
||||||
this.menu.addMenuItem(this._brightness.menu);
|
|
||||||
@@ -726,6 +728,7 @@ class AggregateMenu extends PanelMenu.Button {
|
|
||||||
this.menu.addMenuItem(this._location.menu);
|
|
||||||
this.menu.addMenuItem(this._rfkill.menu);
|
|
||||||
this.menu.addMenuItem(this._power.menu);
|
|
||||||
+ this.menu.addMenuItem(this._powerProfiles.menu);
|
|
||||||
this.menu.addMenuItem(this._nightLight.menu);
|
|
||||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
||||||
this.menu.addMenuItem(this._system.menu);
|
|
||||||
@@ -733,6 +736,7 @@ class AggregateMenu extends PanelMenu.Button {
|
|
||||||
menuLayout.addSizeChild(this._location.menu.actor);
|
|
||||||
menuLayout.addSizeChild(this._rfkill.menu.actor);
|
|
||||||
menuLayout.addSizeChild(this._power.menu.actor);
|
|
||||||
+ menuLayout.addSizeChild(this._powerProfiles.menu.actor);
|
|
||||||
menuLayout.addSizeChild(this._system.menu.actor);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
diff --git a/js/ui/status/powerProfiles.js b/js/ui/status/powerProfiles.js
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000..f6bc5835b
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/js/ui/status/powerProfiles.js
|
|
||||||
@@ -0,0 +1,111 @@
|
|
||||||
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
+/* exported Indicator */
|
|
||||||
+
|
|
||||||
+const { Gio, GObject } = imports.gi;
|
|
||||||
+
|
|
||||||
+const Main = imports.ui.main;
|
|
||||||
+const PanelMenu = imports.ui.panelMenu;
|
|
||||||
+const PopupMenu = imports.ui.popupMenu;
|
|
||||||
+
|
|
||||||
+const { loadInterfaceXML } = imports.misc.fileUtils;
|
|
||||||
+
|
|
||||||
+const BUS_NAME = 'net.hadess.PowerProfiles';
|
|
||||||
+const OBJECT_PATH = '/net/hadess/PowerProfiles';
|
|
||||||
+
|
|
||||||
+const PowerProfilesIface = loadInterfaceXML('net.hadess.PowerProfiles');
|
|
||||||
+const PowerProfilesProxy = Gio.DBusProxy.makeProxyWrapper(PowerProfilesIface);
|
|
||||||
+
|
|
||||||
+const PROFILE_LABELS = {
|
|
||||||
+ 'performance': _('Performance Mode'),
|
|
||||||
+ 'balanced': _('Balanced Power'),
|
|
||||||
+ 'power-saver': _('Power Saver'),
|
|
||||||
+};
|
|
||||||
+const PROFILE_ICONS = {
|
|
||||||
+ 'performance': 'power-profile-performance-symbolic',
|
|
||||||
+ 'balanced': 'power-profile-balanced-symbolic',
|
|
||||||
+ 'power-saver': 'power-profile-power-saver-symbolic',
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+var Indicator = GObject.registerClass(
|
|
||||||
+class Indicator extends PanelMenu.SystemIndicator {
|
|
||||||
+ _init() {
|
|
||||||
+ super._init();
|
|
||||||
+
|
|
||||||
+ this._profileItems = new Map();
|
|
||||||
+ this._updateProfiles = true;
|
|
||||||
+
|
|
||||||
+ this._proxy = new PowerProfilesProxy(Gio.DBus.system, BUS_NAME, OBJECT_PATH,
|
|
||||||
+ (proxy, error) => {
|
|
||||||
+ if (error) {
|
|
||||||
+ log(error.message);
|
|
||||||
+ } else {
|
|
||||||
+ this._proxy.connect('g-properties-changed',
|
|
||||||
+ (p, properties) => {
|
|
||||||
+ const propertyNames = properties.deep_unpack();
|
|
||||||
+ this._updateProfiles = 'Profiles' in propertyNames;
|
|
||||||
+ this._sync();
|
|
||||||
+ });
|
|
||||||
+ }
|
|
||||||
+ this._sync();
|
|
||||||
+ });
|
|
||||||
+
|
|
||||||
+ this._item = new PopupMenu.PopupSubMenuMenuItem('', true);
|
|
||||||
+
|
|
||||||
+ this._profileSection = new PopupMenu.PopupMenuSection();
|
|
||||||
+ this._item.menu.addMenuItem(this._profileSection);
|
|
||||||
+ this._item.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
||||||
+ this._item.menu.addSettingsAction(_('Power Settings'),
|
|
||||||
+ 'gnome-power-panel.desktop');
|
|
||||||
+ this.menu.addMenuItem(this._item);
|
|
||||||
+
|
|
||||||
+ Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
|
|
||||||
+ this._sessionUpdated();
|
|
||||||
+ this._sync();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ _sessionUpdated() {
|
|
||||||
+ const sensitive = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
|
|
||||||
+ this.menu.setSensitive(sensitive);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ _sync() {
|
|
||||||
+ this._item.visible = this._proxy.g_name_owner !== null;
|
|
||||||
+
|
|
||||||
+ if (!this._item.visible)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ if (this._updateProfiles) {
|
|
||||||
+ this._profileSection.removeAll();
|
|
||||||
+ this._profileItems.clear();
|
|
||||||
+
|
|
||||||
+ const profiles = this._proxy.Profiles
|
|
||||||
+ .map(p => p.Profile.unpack())
|
|
||||||
+ .reverse();
|
|
||||||
+ for (const profile of profiles) {
|
|
||||||
+ const label = PROFILE_LABELS[profile];
|
|
||||||
+ if (!label)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ const item = new PopupMenu.PopupMenuItem(label);
|
|
||||||
+ item.connect('activate',
|
|
||||||
+ () => (this._proxy.ActiveProfile = profile));
|
|
||||||
+ this._profileItems.set(profile, item);
|
|
||||||
+ this._profileSection.addMenuItem(item);
|
|
||||||
+ }
|
|
||||||
+ this._updateProfiles = false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ for (const [profile, item] of this._profileItems) {
|
|
||||||
+ item.setOrnament(profile === this._proxy.ActiveProfile
|
|
||||||
+ ? PopupMenu.Ornament.DOT
|
|
||||||
+ : PopupMenu.Ornament.NONE);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ const perfItem = this._profileItems.get('performance');
|
|
||||||
+ if (perfItem)
|
|
||||||
+ perfItem.sensitive = this._proxy.PerformanceInhibited === '';
|
|
||||||
+
|
|
||||||
+ this._item.label.text = PROFILE_LABELS[this._proxy.ActiveProfile];
|
|
||||||
+ this._item.icon.icon_name = PROFILE_ICONS[this._proxy.ActiveProfile];
|
|
||||||
+ }
|
|
||||||
+});
|
|
||||||
diff --git a/po/POTFILES.in b/po/POTFILES.in
|
|
||||||
index cb279c1ee..727cb01a8 100644
|
|
||||||
--- a/po/POTFILES.in
|
|
||||||
+++ b/po/POTFILES.in
|
|
||||||
@@ -61,6 +61,7 @@ js/ui/status/location.js
|
|
||||||
js/ui/status/network.js
|
|
||||||
js/ui/status/nightLight.js
|
|
||||||
js/ui/status/power.js
|
|
||||||
+js/ui/status/powerProfiles.js
|
|
||||||
js/ui/status/remoteAccess.js
|
|
||||||
js/ui/status/rfkill.js
|
|
||||||
js/ui/status/system.js
|
|
||||||
--
|
|
||||||
2.31.1
|
|
||||||
|
|
||||||
|
|
||||||
From 0f8a2e2c6c3119492670efce5aff1224f2c3c47f Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
||||||
Date: Fri, 6 Aug 2021 21:04:24 +0200
|
|
||||||
Subject: [PATCH 2/2] powerProfiles: Tweak profile names
|
|
||||||
|
|
||||||
After some more discussion, we settled on slightly different
|
|
||||||
profile names.
|
|
||||||
|
|
||||||
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4530
|
|
||||||
|
|
||||||
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1939>
|
|
||||||
---
|
|
||||||
js/ui/status/powerProfiles.js | 6 +++---
|
|
||||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/js/ui/status/powerProfiles.js b/js/ui/status/powerProfiles.js
|
|
||||||
index f6bc5835b..61205bbc6 100644
|
|
||||||
--- a/js/ui/status/powerProfiles.js
|
|
||||||
+++ b/js/ui/status/powerProfiles.js
|
|
||||||
@@ -16,9 +16,9 @@ const PowerProfilesIface = loadInterfaceXML('net.hadess.PowerProfiles');
|
|
||||||
const PowerProfilesProxy = Gio.DBusProxy.makeProxyWrapper(PowerProfilesIface);
|
|
||||||
|
|
||||||
const PROFILE_LABELS = {
|
|
||||||
- 'performance': _('Performance Mode'),
|
|
||||||
- 'balanced': _('Balanced Power'),
|
|
||||||
- 'power-saver': _('Power Saver'),
|
|
||||||
+ 'performance': C_('Power profile', 'Performance'),
|
|
||||||
+ 'balanced': C_('Power profile', 'Balanced'),
|
|
||||||
+ 'power-saver': C_('Power profile', 'Power Saver'),
|
|
||||||
};
|
|
||||||
const PROFILE_ICONS = {
|
|
||||||
'performance': 'power-profile-performance-symbolic',
|
|
||||||
--
|
|
||||||
2.31.1
|
|
||||||
|
|
@ -0,0 +1,159 @@
|
|||||||
|
From 3252f05b8745a5d3118986474793fe3ecc2b041c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Tue, 19 Apr 2016 13:12:46 -0400
|
||||||
|
Subject: [PATCH] loginDialog: allow timed login with disabled user list
|
||||||
|
|
||||||
|
At the moment the timed login feature is implemented in the user list.
|
||||||
|
If there's no user list, we don't show the indicator anywhere and
|
||||||
|
don't proceed with timed login.
|
||||||
|
|
||||||
|
This commit allows timed login to work when the user list is disabled.
|
||||||
|
It accomplishes this by putting the timed login indicator on the
|
||||||
|
auth prompt, in that scenario.
|
||||||
|
---
|
||||||
|
data/theme/gnome-shell-sass/_common.scss | 4 +++
|
||||||
|
js/gdm/authPrompt.js | 41 +++++++++++++++++++++++-
|
||||||
|
js/gdm/loginDialog.js | 25 +++++++++++++--
|
||||||
|
3 files changed, 67 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss
|
||||||
|
index a6357baad..c2df28279 100644
|
||||||
|
--- a/data/theme/gnome-shell-sass/_common.scss
|
||||||
|
+++ b/data/theme/gnome-shell-sass/_common.scss
|
||||||
|
@@ -1856,6 +1856,10 @@ StScrollBar {
|
||||||
|
padding-bottom: 12px;
|
||||||
|
spacing: 8px;
|
||||||
|
width: 23em;
|
||||||
|
+ .login-dialog-timed-login-indicator {
|
||||||
|
+ height: 2px;
|
||||||
|
+ background-color: darken($fg_color,40%);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-dialog-prompt-label {
|
||||||
|
diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js
|
||||||
|
index 27eb31a89..cf77b3f26 100644
|
||||||
|
--- a/js/gdm/authPrompt.js
|
||||||
|
+++ b/js/gdm/authPrompt.js
|
||||||
|
@@ -1,6 +1,6 @@
|
||||||
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||||
|
|
||||||
|
-const { Clutter, Pango, Shell, St } = imports.gi;
|
||||||
|
+const { Clutter, GLib, Pango, Shell, St } = imports.gi;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
|
||||||
|
const Animation = imports.ui.animation;
|
||||||
|
@@ -111,6 +111,11 @@ var AuthPrompt = class {
|
||||||
|
|
||||||
|
this._entry.grab_key_focus();
|
||||||
|
|
||||||
|
+ this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator',
|
||||||
|
+ scale_x: 0 });
|
||||||
|
+
|
||||||
|
+ this.actor.add(this._timedLoginIndicator);
|
||||||
|
+
|
||||||
|
this._message = new St.Label({ opacity: 0,
|
||||||
|
styleClass: 'login-dialog-message' });
|
||||||
|
this._message.clutter_text.line_wrap = true;
|
||||||
|
@@ -135,6 +140,40 @@ var AuthPrompt = class {
|
||||||
|
this._defaultButtonWell.add_child(this._spinner.actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ showTimedLoginIndicator(time) {
|
||||||
|
+ let hold = new Batch.Hold();
|
||||||
|
+
|
||||||
|
+ this.hideTimedLoginIndicator();
|
||||||
|
+
|
||||||
|
+ let startTime = GLib.get_monotonic_time();
|
||||||
|
+
|
||||||
|
+ this._timedLoginTimeoutId = GLib.timeout_add (GLib.PRIORITY_DEFAULT, 33,
|
||||||
|
+ () => {
|
||||||
|
+ let currentTime = GLib.get_monotonic_time();
|
||||||
|
+ let elapsedTime = (currentTime - startTime) / GLib.USEC_PER_SEC;
|
||||||
|
+ this._timedLoginIndicator.scale_x = elapsedTime / time;
|
||||||
|
+ if (elapsedTime >= time) {
|
||||||
|
+ this._timedLoginTimeoutId = 0;
|
||||||
|
+ hold.release();
|
||||||
|
+ return GLib.SOURCE_REMOVE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return GLib.SOURCE_CONTINUE;
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ GLib.Source.set_name_by_id(this._timedLoginTimeoutId, '[gnome-shell] this._timedLoginTimeoutId');
|
||||||
|
+
|
||||||
|
+ return hold;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ hideTimedLoginIndicator() {
|
||||||
|
+ if (this._timedLoginTimeoutId) {
|
||||||
|
+ GLib.source_remove(this._timedLoginTimeoutId);
|
||||||
|
+ this._timedLoginTimeoutId = 0;
|
||||||
|
+ }
|
||||||
|
+ this._timedLoginIndicator.scale_x = 0.;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
_onDestroy() {
|
||||||
|
if (this._preemptiveAnswerWatchId) {
|
||||||
|
this._idleMonitor.remove_watch(this._preemptiveAnswerWatchId);
|
||||||
|
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
|
||||||
|
index 6c4d1357d..b4df6e959 100644
|
||||||
|
--- a/js/gdm/loginDialog.js
|
||||||
|
+++ b/js/gdm/loginDialog.js
|
||||||
|
@@ -734,6 +734,9 @@ var LoginDialog = GObject.registerClass({
|
||||||
|
|
||||||
|
if (this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
|
||||||
|
this._authPrompt.reset();
|
||||||
|
+
|
||||||
|
+ if (this._disableUserList && this._timedLoginUserListHold)
|
||||||
|
+ this._timedLoginUserListHold.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1020,16 +1023,31 @@ var LoginDialog = GObject.registerClass({
|
||||||
|
let loginItem = null;
|
||||||
|
let animationTime;
|
||||||
|
|
||||||
|
- let tasks = [() => this._waitForItemForUser(userName),
|
||||||
|
+ let tasks = [() => {
|
||||||
|
+ if (this._disableUserList)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ this._timedLoginUserListHold = this._waitForItemForUser(userName);
|
||||||
|
+
|
||||||
|
+ return this._timedLoginUserListHold;
|
||||||
|
+ },
|
||||||
|
|
||||||
|
() => {
|
||||||
|
- loginItem = this._userList.getItemFromUserName(userName);
|
||||||
|
+ this._timedLoginUserListHold = null;
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ loginItem = this._disableUserList
|
||||||
|
+ ? this._authPrompt
|
||||||
|
+ : this._userList.getItemFromUserName(userName);
|
||||||
|
|
||||||
|
// If there is an animation running on the item, reset it.
|
||||||
|
loginItem.hideTimedLoginIndicator();
|
||||||
|
},
|
||||||
|
|
||||||
|
() => {
|
||||||
|
+ if (this._disableUserList)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
// If we're just starting out, start on the right item.
|
||||||
|
if (!this._userManager.is_loaded) {
|
||||||
|
this._userList.jumpToItem(loginItem);
|
||||||
|
@@ -1051,6 +1069,9 @@ var LoginDialog = GObject.registerClass({
|
||||||
|
},
|
||||||
|
|
||||||
|
() => {
|
||||||
|
+ if (this._disableUserList)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
// If idle timeout is done, make sure the timed login indicator is shown
|
||||||
|
if (delay > _TIMED_LOGIN_IDLE_THRESHOLD &&
|
||||||
|
this._authPrompt.actor.visible)
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -0,0 +1,145 @@
|
|||||||
|
From 7bdd1962213a37f6218fe15ea1a4062dd318672a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Will Thompson <wjt@endlessm.com>
|
||||||
|
Date: Wed, 28 Aug 2019 15:39:44 +0100
|
||||||
|
Subject: [PATCH 1/2] global: Don't trust persistent/runtime state data
|
||||||
|
|
||||||
|
An Endless OS system was found in the wild with a malformed
|
||||||
|
.local/share/gnome-shell/notifications. When deserialized in Python,
|
||||||
|
after passing trusted=True to g_variant_new_from_bytes(), the first
|
||||||
|
element of the first struct in the array looks like this:
|
||||||
|
|
||||||
|
In [41]: _38.get_child_value(0).get_child_value(0)
|
||||||
|
Out[41]: GLib.Variant('s', '\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff')
|
||||||
|
|
||||||
|
When deserialised in GJS, we get:
|
||||||
|
|
||||||
|
gjs> v.get_child_value(0).get_child_value(0)
|
||||||
|
[object variant of type "s"]
|
||||||
|
gjs> v.get_child_value(0).get_child_value(0).get_string()
|
||||||
|
typein:43:1 malformed UTF-8 character sequence at offset 0
|
||||||
|
@typein:43:1
|
||||||
|
@<stdin>:1:34
|
||||||
|
|
||||||
|
While g_variant_new_from_bytes() doesn't have much to say about its
|
||||||
|
'trusted' parameter, g_variant_new_from_data() does:
|
||||||
|
|
||||||
|
> If data is trusted to be serialised data in normal form then trusted
|
||||||
|
> should be TRUE. This applies to serialised data created within this
|
||||||
|
> process or read from a trusted location on the disk (such as a file
|
||||||
|
> installed in /usr/lib alongside your application). You should set
|
||||||
|
> trusted to FALSE if data is read from the network, a file in the
|
||||||
|
> user's home directory, etc.
|
||||||
|
|
||||||
|
Persistent state is read from the user's home directory, so it should
|
||||||
|
not be trusted. With trusted=False, the string value above comes out as
|
||||||
|
"".
|
||||||
|
|
||||||
|
I don't have an explanation for how this file ended up being malformed.
|
||||||
|
I also don't have an explanation for when this started crashing: my
|
||||||
|
guess is that recent GJS became stricter about validating UTF-8 but I
|
||||||
|
could be wrong!
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1552
|
||||||
|
---
|
||||||
|
src/shell-global.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/shell-global.c b/src/shell-global.c
|
||||||
|
index 4b33778e0..33046f614 100644
|
||||||
|
--- a/src/shell-global.c
|
||||||
|
+++ b/src/shell-global.c
|
||||||
|
@@ -1707,7 +1707,7 @@ load_variant (GFile *dir,
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GBytes *bytes = g_mapped_file_get_bytes (mfile);
|
||||||
|
- res = g_variant_new_from_bytes (G_VARIANT_TYPE (property_type), bytes, TRUE);
|
||||||
|
+ res = g_variant_new_from_bytes (G_VARIANT_TYPE (property_type), bytes, FALSE);
|
||||||
|
g_bytes_unref (bytes);
|
||||||
|
g_mapped_file_unref (mfile);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.35.1
|
||||||
|
|
||||||
|
|
||||||
|
From 13dcb3e4400b92a0d2f548e88b70b358240d462c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Will Thompson <wjt@endlessm.com>
|
||||||
|
Date: Wed, 28 Aug 2019 15:38:03 +0100
|
||||||
|
Subject: [PATCH 2/2] notificationDaemon: Catch exceptions while loading
|
||||||
|
notifications
|
||||||
|
|
||||||
|
An Endless OS system was found in the wild with a malformed
|
||||||
|
.local/share/gnome-shell/notifications which causes _loadNotifications()
|
||||||
|
to raise an exception. This exception was not previously handled and
|
||||||
|
bubbles all the way out to gnome_shell_plugin_start(), whereupon the
|
||||||
|
shell exit(1)s. The user could no longer log into their computer.
|
||||||
|
|
||||||
|
Handle exceptions from _loadNotifications(), log them, and attempt to
|
||||||
|
continue. Ensure that this._isLoading is set to 'false' even on error,
|
||||||
|
so that future calls to _saveNotifications() can overwrite the (corrupt)
|
||||||
|
state file.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1552
|
||||||
|
---
|
||||||
|
js/ui/notificationDaemon.js | 42 ++++++++++++++++++++-----------------
|
||||||
|
1 file changed, 23 insertions(+), 19 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/notificationDaemon.js b/js/ui/notificationDaemon.js
|
||||||
|
index 4bdede841..dbe673b88 100644
|
||||||
|
--- a/js/ui/notificationDaemon.js
|
||||||
|
+++ b/js/ui/notificationDaemon.js
|
||||||
|
@@ -749,29 +749,33 @@ var GtkNotificationDaemon = class GtkNotificationDaemon {
|
||||||
|
_loadNotifications() {
|
||||||
|
this._isLoading = true;
|
||||||
|
|
||||||
|
- let value = global.get_persistent_state('a(sa(sv))', 'notifications');
|
||||||
|
- if (value) {
|
||||||
|
- let sources = value.deep_unpack();
|
||||||
|
- sources.forEach(([appId, notifications]) => {
|
||||||
|
- if (notifications.length == 0)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- let source;
|
||||||
|
- try {
|
||||||
|
- source = this._ensureAppSource(appId);
|
||||||
|
- } catch(e) {
|
||||||
|
- if (e instanceof InvalidAppError)
|
||||||
|
+ try {
|
||||||
|
+ let value = global.get_persistent_state('a(sa(sv))', 'notifications');
|
||||||
|
+ if (value) {
|
||||||
|
+ let sources = value.deep_unpack();
|
||||||
|
+ sources.forEach(([appId, notifications]) => {
|
||||||
|
+ if (notifications.length == 0)
|
||||||
|
return;
|
||||||
|
- throw e;
|
||||||
|
- }
|
||||||
|
|
||||||
|
- notifications.forEach(([notificationId, notification]) => {
|
||||||
|
- source.addNotification(notificationId, notification.deep_unpack(), false);
|
||||||
|
+ let source;
|
||||||
|
+ try {
|
||||||
|
+ source = this._ensureAppSource(appId);
|
||||||
|
+ } catch (e) {
|
||||||
|
+ if (e instanceof InvalidAppError)
|
||||||
|
+ return;
|
||||||
|
+ throw e;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ notifications.forEach(([notificationId, notification]) => {
|
||||||
|
+ source.addNotification(notificationId, notification.deep_unpack(), false);
|
||||||
|
+ });
|
||||||
|
});
|
||||||
|
- });
|
||||||
|
+ }
|
||||||
|
+ } catch (e) {
|
||||||
|
+ logError(e, 'Failed to load saved notifications');
|
||||||
|
+ } finally {
|
||||||
|
+ this._isLoading = false;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- this._isLoading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_saveNotifications() {
|
||||||
|
--
|
||||||
|
2.35.1
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,421 @@
|
|||||||
|
From a518c9f57e5fe9c6b5ece5c6cb0534a83f0b2f2d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Mon, 15 Jul 2019 13:52:58 -0400
|
||||||
|
Subject: [PATCH 1/8] appDisplay: Don't leak duplicate items in AppView
|
||||||
|
|
||||||
|
If an icon already exists in an app view with the same id, the
|
||||||
|
duplicate is not added on a call to addItem. Unfortunately,
|
||||||
|
since it's not added, the icon actor gets orphaned and leaked.
|
||||||
|
|
||||||
|
This commit address the problem by introducing a new hasItem
|
||||||
|
method and disallowing callers to call addItem with a duplicate
|
||||||
|
in the first place.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
|
||||||
|
---
|
||||||
|
js/ui/appDisplay.js | 15 ++++++++++++---
|
||||||
|
1 file changed, 12 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
|
||||||
|
index a07db6573..fa22f47e0 100644
|
||||||
|
--- a/js/ui/appDisplay.js
|
||||||
|
+++ b/js/ui/appDisplay.js
|
||||||
|
@@ -143,10 +143,14 @@ class BaseAppView {
|
||||||
|
return this._allItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ hasItem(id) {
|
||||||
|
+ return this._items[id] !== undefined;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
addItem(icon) {
|
||||||
|
let id = icon.id;
|
||||||
|
- if (this._items[id] !== undefined)
|
||||||
|
- return;
|
||||||
|
+ if (this.hasItem(id))
|
||||||
|
+ throw new Error(`icon with id ${id} already added to view`)
|
||||||
|
|
||||||
|
this._allItems.push(icon);
|
||||||
|
this._items[id] = icon;
|
||||||
|
@@ -386,6 +390,8 @@ var AllView = class AllView extends BaseAppView {
|
||||||
|
|
||||||
|
let folders = this._folderSettings.get_strv('folder-children');
|
||||||
|
folders.forEach(id => {
|
||||||
|
+ if (this.hasItem(id))
|
||||||
|
+ return;
|
||||||
|
let path = this._folderSettings.path + 'folders/' + id + '/';
|
||||||
|
let icon = new FolderIcon(id, path, this);
|
||||||
|
icon.connect('name-changed', this._itemNameChanged.bind(this));
|
||||||
|
@@ -1165,7 +1171,10 @@ var FolderIcon = class FolderIcon {
|
||||||
|
let excludedApps = this._folder.get_strv('excluded-apps');
|
||||||
|
let appSys = Shell.AppSystem.get_default();
|
||||||
|
let addAppId = appId => {
|
||||||
|
- if (excludedApps.indexOf(appId) >= 0)
|
||||||
|
+ if (this.view.hasItem(appId))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (excludedApps.includes(appId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
let app = appSys.lookup_app(appId);
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
|
|
||||||
|
|
||||||
|
From 2b6aa9aed98c4854c2ad015879ddcb8d2bf91e9e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Mon, 22 Jul 2019 11:06:30 -0400
|
||||||
|
Subject: [PATCH 2/8] iconGrid: Clear meta_later callback on destruction
|
||||||
|
|
||||||
|
The IconGrid code sometimes sets up a callback to be invoked
|
||||||
|
later right before being destroyed.
|
||||||
|
|
||||||
|
This commit adds a destroy handler to cancel the callback.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
|
||||||
|
---
|
||||||
|
js/ui/iconGrid.js | 16 ++++++++++++++--
|
||||||
|
1 file changed, 14 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js
|
||||||
|
index d51a443e8..1f05e67f3 100644
|
||||||
|
--- a/js/ui/iconGrid.js
|
||||||
|
+++ b/js/ui/iconGrid.js
|
||||||
|
@@ -210,6 +210,8 @@ var IconGrid = GObject.registerClass({
|
||||||
|
this.rightPadding = 0;
|
||||||
|
this.leftPadding = 0;
|
||||||
|
|
||||||
|
+ this._updateIconSizesLaterId = 0;
|
||||||
|
+
|
||||||
|
this._items = [];
|
||||||
|
this._clonesAnimating = [];
|
||||||
|
// Pulled from CSS, but hardcode some defaults here
|
||||||
|
@@ -227,6 +229,14 @@ var IconGrid = GObject.registerClass({
|
||||||
|
|
||||||
|
this.connect('actor-added', this._childAdded.bind(this));
|
||||||
|
this.connect('actor-removed', this._childRemoved.bind(this));
|
||||||
|
+ this.connect('destroy', this._onDestroy.bind(this));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ _onDestroy() {
|
||||||
|
+ if (this._updateIconSizesLaterId) {
|
||||||
|
+ Meta.later_remove (this._updateIconSizesLaterId);
|
||||||
|
+ this._updateIconSizesLaterId = 0;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
_keyFocusIn(actor) {
|
||||||
|
@@ -757,12 +767,14 @@ var IconGrid = GObject.registerClass({
|
||||||
|
|
||||||
|
this._updateSpacingForSize(availWidth, availHeight);
|
||||||
|
}
|
||||||
|
- Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
|
||||||
|
- this._updateIconSizes.bind(this));
|
||||||
|
+ if (!this._updateIconSizesLaterId)
|
||||||
|
+ this._updateIconSizesLaterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
|
||||||
|
+ this._updateIconSizes.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up
|
||||||
|
_updateIconSizes() {
|
||||||
|
+ this._updateIconSizesLaterId = 0;
|
||||||
|
let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize);
|
||||||
|
let newIconSize = Math.floor(ICON_SIZE * scale);
|
||||||
|
for (let i in this._items) {
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
|
|
||||||
|
|
||||||
|
From 14a2650548a5104d6a3ec7a1174a23264d79030a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Mon, 22 Jul 2019 11:02:10 -0400
|
||||||
|
Subject: [PATCH 3/8] appDisplay: Add AppFolderPopup destroy handler
|
||||||
|
|
||||||
|
At the moment AppFolderPopup calls popdown on destruction,
|
||||||
|
which leads to open-state-changed getting emitted after
|
||||||
|
the actor associated with the popup is destroyed.
|
||||||
|
|
||||||
|
This commit handles ungrabbing and closing from an
|
||||||
|
actor destroy handler to side-step the open-state-changed
|
||||||
|
signal.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
|
||||||
|
---
|
||||||
|
js/ui/appDisplay.js | 9 +++++++++
|
||||||
|
1 file changed, 9 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
|
||||||
|
index fa22f47e0..b75d095d5 100644
|
||||||
|
--- a/js/ui/appDisplay.js
|
||||||
|
+++ b/js/ui/appDisplay.js
|
||||||
|
@@ -1329,6 +1329,15 @@ var AppFolderPopup = class AppFolderPopup {
|
||||||
|
});
|
||||||
|
this._grabHelper.addActor(Main.layoutManager.overviewGroup);
|
||||||
|
this.actor.connect('key-press-event', this._onKeyPress.bind(this));
|
||||||
|
+ this.actor.connect('destroy', this._onDestroy.bind(this));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ _onDestroy() {
|
||||||
|
+ if (this._isOpen) {
|
||||||
|
+ this._isOpen = false;
|
||||||
|
+ this._grabHelper.ungrab({ actor: this.actor });
|
||||||
|
+ this._grabHelper = null;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
_onKeyPress(actor, event) {
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
|
|
||||||
|
|
||||||
|
From c9fcb2d23141694ffa2182df20ba75687b01dacc Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Thu, 18 Jul 2019 10:06:38 -0400
|
||||||
|
Subject: [PATCH 4/8] appDisplay: Clear AllView reference to current popup when
|
||||||
|
destroyed
|
||||||
|
|
||||||
|
AllView contains a reference to the current popup that lingers after
|
||||||
|
the popup is destroyed.
|
||||||
|
|
||||||
|
This commit fixes that, by explicitly nullifying when appropriate.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
|
||||||
|
---
|
||||||
|
js/ui/appDisplay.js | 18 +++++++++++++++++-
|
||||||
|
1 file changed, 17 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
|
||||||
|
index b75d095d5..dabf63bfd 100644
|
||||||
|
--- a/js/ui/appDisplay.js
|
||||||
|
+++ b/js/ui/appDisplay.js
|
||||||
|
@@ -300,6 +300,7 @@ var AllView = class AllView extends BaseAppView {
|
||||||
|
this._eventBlocker.add_action(this._clickAction);
|
||||||
|
|
||||||
|
this._displayingPopup = false;
|
||||||
|
+ this._currentPopupDestroyId = 0;
|
||||||
|
|
||||||
|
this._availWidth = 0;
|
||||||
|
this._availHeight = 0;
|
||||||
|
@@ -589,7 +590,22 @@ var AllView = class AllView extends BaseAppView {
|
||||||
|
this._stack.add_actor(popup.actor);
|
||||||
|
popup.connect('open-state-changed', (popup, isOpen) => {
|
||||||
|
this._eventBlocker.reactive = isOpen;
|
||||||
|
- this._currentPopup = isOpen ? popup : null;
|
||||||
|
+
|
||||||
|
+ if (this._currentPopup) {
|
||||||
|
+ this._currentPopup.actor.disconnect(this._currentPopupDestroyId);
|
||||||
|
+ this._currentPopupDestroyId = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ this._currentPopup = null;
|
||||||
|
+
|
||||||
|
+ if (isOpen) {
|
||||||
|
+ this._currentPopup = popup;
|
||||||
|
+ this._currentPopupDestroyId = popup.actor.connect('destroy', () => {
|
||||||
|
+ this._currentPopup = null;
|
||||||
|
+ this._currentPopupDestroyId = 0;
|
||||||
|
+ this._eventBlocker.reactive = false;
|
||||||
|
+ });
|
||||||
|
+ }
|
||||||
|
this._updateIconOpacities(isOpen);
|
||||||
|
if(!isOpen)
|
||||||
|
this._closeSpaceForPopup();
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
|
|
||||||
|
|
||||||
|
From b7a3fd7fa4527ba9411dcd18debe6ccf88c34dc0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Mon, 22 Jul 2019 10:57:57 -0400
|
||||||
|
Subject: [PATCH 5/8] appDisplay: Add destroy handler for FolderIcon
|
||||||
|
|
||||||
|
It is important that the FolderView of a FolderIcon always
|
||||||
|
gets destroyed before the AppFolderPopup, since the view
|
||||||
|
may or may not be in the popup, and the view should
|
||||||
|
get cleaned up exactly once in either case.
|
||||||
|
|
||||||
|
This commit adds a destroy handler on FolderIcon to ensure
|
||||||
|
things get taken down in the right order, and to make sure
|
||||||
|
the view isn't leaked if it's not yet part of the popup.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
|
||||||
|
---
|
||||||
|
js/ui/appDisplay.js | 8 ++++++++
|
||||||
|
1 file changed, 8 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
|
||||||
|
index dabf63bfd..5a8f4f1bf 100644
|
||||||
|
--- a/js/ui/appDisplay.js
|
||||||
|
+++ b/js/ui/appDisplay.js
|
||||||
|
@@ -1156,6 +1156,7 @@ var FolderIcon = class FolderIcon {
|
||||||
|
this.view.actor.vscroll.adjustment.value = 0;
|
||||||
|
this._openSpaceForPopup();
|
||||||
|
});
|
||||||
|
+ this.actor.connect('destroy', this.onDestroy.bind(this));
|
||||||
|
this.actor.connect('notify::mapped', () => {
|
||||||
|
if (!this.actor.mapped && this._popup)
|
||||||
|
this._popup.popdown();
|
||||||
|
@@ -1165,6 +1166,13 @@ var FolderIcon = class FolderIcon {
|
||||||
|
this._redisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ onDestroy() {
|
||||||
|
+ this.view.actor.destroy();
|
||||||
|
+
|
||||||
|
+ if (this._popup)
|
||||||
|
+ this._popup.actor.destroy();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
getAppIds() {
|
||||||
|
return this.view.getAllItems().map(item => item.id);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
|
|
||||||
|
|
||||||
|
From a90d7a97d21ffa596747cc8ecd0e3f500cb8a77c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Thu, 18 Jul 2019 14:49:30 -0400
|
||||||
|
Subject: [PATCH 6/8] appDisplay: Stop watching FolderIcon parent view when
|
||||||
|
destroyed
|
||||||
|
|
||||||
|
When a FolderIcon is opened, it asks the parent view to allocate
|
||||||
|
space for it, which takes time. Eventually, the space-ready
|
||||||
|
signal is emitted on the view and the icon can make use of the new
|
||||||
|
space with its popup. If the icon gets destroyed in the
|
||||||
|
interim, though, space-ready signal handler still fires.
|
||||||
|
|
||||||
|
This commit disconnects the signal handler so it doesn't get called
|
||||||
|
on a destroyed icon.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
|
||||||
|
---
|
||||||
|
js/ui/appDisplay.js | 10 ++++++++--
|
||||||
|
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
|
||||||
|
index 5a8f4f1bf..062ff222c 100644
|
||||||
|
--- a/js/ui/appDisplay.js
|
||||||
|
+++ b/js/ui/appDisplay.js
|
||||||
|
@@ -1169,6 +1169,11 @@ var FolderIcon = class FolderIcon {
|
||||||
|
onDestroy() {
|
||||||
|
this.view.actor.destroy();
|
||||||
|
|
||||||
|
+ if (this._spaceReadySignalId) {
|
||||||
|
+ this._parentView.disconnect(this._spaceReadySignalId);
|
||||||
|
+ this._spaceReadySignalId = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (this._popup)
|
||||||
|
this._popup.actor.destroy();
|
||||||
|
}
|
||||||
|
@@ -1240,8 +1245,9 @@ var FolderIcon = class FolderIcon {
|
||||||
|
}
|
||||||
|
|
||||||
|
_openSpaceForPopup() {
|
||||||
|
- let id = this._parentView.connect('space-ready', () => {
|
||||||
|
- this._parentView.disconnect(id);
|
||||||
|
+ this._spaceReadySignalId = this._parentView.connect('space-ready', () => {
|
||||||
|
+ this._parentView.disconnect(this._spaceReadySignalId);
|
||||||
|
+ this._spaceReadySignalId = 0;
|
||||||
|
this._popup.popup();
|
||||||
|
this._updatePopupPosition();
|
||||||
|
});
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
|
|
||||||
|
|
||||||
|
From b57ab33dadf0f31c5bf2c800806593e94784050c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Thu, 18 Jul 2019 10:19:13 -0400
|
||||||
|
Subject: [PATCH 7/8] appDisplay: Add open method to FolderIcon
|
||||||
|
|
||||||
|
At the moment the only way to open a folder icon is to click on it;
|
||||||
|
there's no API to open the icon programmatically.
|
||||||
|
|
||||||
|
This commits adds an open method and makes the click handler use
|
||||||
|
it.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
|
||||||
|
---
|
||||||
|
js/ui/appDisplay.js | 12 +++++++-----
|
||||||
|
1 file changed, 7 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
|
||||||
|
index 062ff222c..c0c6e3663 100644
|
||||||
|
--- a/js/ui/appDisplay.js
|
||||||
|
+++ b/js/ui/appDisplay.js
|
||||||
|
@@ -1151,11 +1151,7 @@ var FolderIcon = class FolderIcon {
|
||||||
|
|
||||||
|
this.view = new FolderView();
|
||||||
|
|
||||||
|
- this.actor.connect('clicked', () => {
|
||||||
|
- this._ensurePopup();
|
||||||
|
- this.view.actor.vscroll.adjustment.value = 0;
|
||||||
|
- this._openSpaceForPopup();
|
||||||
|
- });
|
||||||
|
+ this.actor.connect('clicked', this.open.bind(this));
|
||||||
|
this.actor.connect('destroy', this.onDestroy.bind(this));
|
||||||
|
this.actor.connect('notify::mapped', () => {
|
||||||
|
if (!this.actor.mapped && this._popup)
|
||||||
|
@@ -1178,6 +1174,12 @@ var FolderIcon = class FolderIcon {
|
||||||
|
this._popup.actor.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ open() {
|
||||||
|
+ this._ensurePopup();
|
||||||
|
+ this.view.actor.vscroll.adjustment.value = 0;
|
||||||
|
+ this._openSpaceForPopup();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
getAppIds() {
|
||||||
|
return this.view.getAllItems().map(item => item.id);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
|
|
||||||
|
|
||||||
|
From baacab7922a56957d041aa59944c419b82e7a7e1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ray Strode <rstrode@redhat.com>
|
||||||
|
Date: Thu, 18 Jul 2019 11:13:27 -0400
|
||||||
|
Subject: [PATCH 8/8] appDisplay: Keep popup open on refresh
|
||||||
|
|
||||||
|
If the list of applications is refreshed we currently close
|
||||||
|
the open app folder.
|
||||||
|
|
||||||
|
This commit adds logic to reopen the app folder on reload.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
|
||||||
|
---
|
||||||
|
js/ui/appDisplay.js | 15 +++++++++++++++
|
||||||
|
1 file changed, 15 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
|
||||||
|
index c0c6e3663..7fad02cd0 100644
|
||||||
|
--- a/js/ui/appDisplay.js
|
||||||
|
+++ b/js/ui/appDisplay.js
|
||||||
|
@@ -345,6 +345,21 @@ var AllView = class AllView extends BaseAppView {
|
||||||
|
super.removeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ _redisplay() {
|
||||||
|
+ let openFolderId = null;
|
||||||
|
+ if (this._displayingPopup && this._currentPopup)
|
||||||
|
+ openFolderId = this._currentPopup._source.id;
|
||||||
|
+
|
||||||
|
+ super._redisplay();
|
||||||
|
+
|
||||||
|
+ if (openFolderId) {
|
||||||
|
+ let [folderToReopen] = this.folderIcons.filter(folder => folder.id == openFolderId);
|
||||||
|
+
|
||||||
|
+ if (folderToReopen)
|
||||||
|
+ folderToReopen.open();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
_itemNameChanged(item) {
|
||||||
|
// If an item's name changed, we can pluck it out of where it's
|
||||||
|
// supposed to be and reinsert it where it's sorted.
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
|
|
@ -0,0 +1,101 @@
|
|||||||
|
From 49d066234f9f528122bb40c5144b40d8b19a0071 Mon Sep 17 00:00:00 2001
|
||||||
|
From: rpm-build <rpm-build>
|
||||||
|
Date: Mon, 22 Aug 2022 12:52:19 +0200
|
||||||
|
Subject: [PATCH] Background: Avoid double dispose and actors recreations
|
||||||
|
|
||||||
|
Subject: [PATCH 1/2] background: Use Garbage Collector to dispose background:
|
||||||
|
|
||||||
|
The same Meta.Background could be used by multiple instances of background
|
||||||
|
actors, and so should not be disposed when the actor using it is destroyed.
|
||||||
|
|
||||||
|
Instead of calling `run_dispose` directly on it, just nullify the reference
|
||||||
|
on destroy method, leaving the job of doing the proper disposition to the
|
||||||
|
gabage collector that keeps the proper reference count on the Meta.Background.
|
||||||
|
|
||||||
|
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/501
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/558
|
||||||
|
|
||||||
|
Subject: [PATCH 2/2] background: Group 'changed' signal emission
|
||||||
|
|
||||||
|
Background is monitoring the whole `org.gnome.desktop.background` gsettings keys
|
||||||
|
for changes connecting to the non-specialized 'changed' signal and re-emitting
|
||||||
|
this as-is.
|
||||||
|
This means that when the background is changed via control-center, we get
|
||||||
|
multiple 'changed' signal events from GSettings, and for each one of this we
|
||||||
|
recreate a Background and a BackgroundActor.
|
||||||
|
|
||||||
|
Avoid this by using an idle to delay the emission of the 'changed' signal
|
||||||
|
grouping the events.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/558
|
||||||
|
---
|
||||||
|
js/ui/background.js | 26 +++++++++++++++++++++-----
|
||||||
|
1 file changed, 21 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/background.js b/js/ui/background.js
|
||||||
|
index 06e0388..2a404ae 100644
|
||||||
|
--- a/js/ui/background.js
|
||||||
|
+++ b/js/ui/background.js
|
||||||
|
@@ -257,14 +257,15 @@ var Background = class Background {
|
||||||
|
this._refreshAnimation();
|
||||||
|
});
|
||||||
|
|
||||||
|
- this._settingsChangedSignalId = this._settings.connect('changed', () => {
|
||||||
|
- this.emit('changed');
|
||||||
|
- });
|
||||||
|
+ this._settingsChangedSignalId =
|
||||||
|
+ this._settings.connect('changed', this._emitChangedSignal.bind(this));
|
||||||
|
|
||||||
|
this._load();
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
+ this.background = null;
|
||||||
|
+
|
||||||
|
this._cancellable.cancel();
|
||||||
|
this._removeAnimationTimeout();
|
||||||
|
|
||||||
|
@@ -288,6 +289,22 @@ var Background = class Background {
|
||||||
|
if (this._settingsChangedSignalId != 0)
|
||||||
|
this._settings.disconnect(this._settingsChangedSignalId);
|
||||||
|
this._settingsChangedSignalId = 0;
|
||||||
|
+
|
||||||
|
+ if (this._changedIdleId) {
|
||||||
|
+ GLib.source_remove(this._changedIdleId);
|
||||||
|
+ this._changedIdleId = 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ _emitChangedSignal() {
|
||||||
|
+ if (this._changedIdleId)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ this._changedIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
|
||||||
|
+ this._changedIdleId = 0;
|
||||||
|
+ this.emit('changed');
|
||||||
|
+ return GLib.SOURCE_REMOVE;
|
||||||
|
+ });
|
||||||
|
}
|
||||||
|
|
||||||
|
updateResolution() {
|
||||||
|
@@ -343,7 +360,7 @@ var Background = class Background {
|
||||||
|
if (changedFile.equal(file)) {
|
||||||
|
let imageCache = Meta.BackgroundImageCache.get_default();
|
||||||
|
imageCache.purge(changedFile);
|
||||||
|
- this.emit('changed');
|
||||||
|
+ this._emitChangedSignal();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._fileWatches[key] = signalId;
|
||||||
|
@@ -699,7 +716,6 @@ var BackgroundManager = class BackgroundManager {
|
||||||
|
time: FADE_ANIMATION_TIME,
|
||||||
|
transition: 'easeOutQuad',
|
||||||
|
onComplete() {
|
||||||
|
- oldBackgroundActor.background.run_dispose();
|
||||||
|
oldBackgroundActor.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
--
|
||||||
|
2.35.3
|
||||||
|
|
@ -1,107 +0,0 @@
|
|||||||
From 3a89e8597f6f3e7fa468bae93768f8253a3141e7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
||||||
Date: Thu, 6 Oct 2022 14:30:20 +0200
|
|
||||||
Subject: [PATCH 1/2] inhibitShortcutsDialog: Don't override resource
|
|
||||||
|
|
||||||
PermissionStore's Set() method takes a complete permission
|
|
||||||
table, so when setting an app's permission, we are implicitly
|
|
||||||
removing all previously set entries for other apps.
|
|
||||||
|
|
||||||
Switch to the SetPermission() method which sets the permission
|
|
||||||
for a single app.
|
|
||||||
|
|
||||||
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5937
|
|
||||||
|
|
||||||
Part-of:
|
|
||||||
<https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2504>
|
|
||||||
---
|
|
||||||
...g.freedesktop.impl.portal.PermissionStore.xml | 7 +++++++
|
|
||||||
js/ui/inhibitShortcutsDialog.js | 16 ++++++----------
|
|
||||||
2 files changed, 13 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/data/dbus-interfaces/org.freedesktop.impl.portal.PermissionStore.xml b/data/dbus-interfaces/org.freedesktop.impl.portal.PermissionStore.xml
|
|
||||||
index 75fbc468a8..55d3fc30cb 100644
|
|
||||||
--- a/data/dbus-interfaces/org.freedesktop.impl.portal.PermissionStore.xml
|
|
||||||
+++ b/data/dbus-interfaces/org.freedesktop.impl.portal.PermissionStore.xml
|
|
||||||
@@ -13,6 +13,13 @@
|
|
||||||
<arg name="app_permissions" type="a{sas}" direction="in"/>
|
|
||||||
<arg name="data" type="v" direction="in"/>
|
|
||||||
</method>
|
|
||||||
+ <method name="SetPermission">
|
|
||||||
+ <arg name='table' type='s' direction='in'/>
|
|
||||||
+ <arg name='create' type='b' direction='in'/>
|
|
||||||
+ <arg name='id' type='s' direction='in'/>
|
|
||||||
+ <arg name='app' type='s' direction='in'/>
|
|
||||||
+ <arg name='permissions' type='as' direction='in'/>
|
|
||||||
+ </method>
|
|
||||||
<signal name="Changed">
|
|
||||||
<arg name="table" type="s" direction="out"/>
|
|
||||||
<arg name="id" type="s" direction="out"/>
|
|
||||||
diff --git a/js/ui/inhibitShortcutsDialog.js b/js/ui/inhibitShortcutsDialog.js
|
|
||||||
index c59544eaf9..8ef5861261 100644
|
|
||||||
--- a/js/ui/inhibitShortcutsDialog.js
|
|
||||||
+++ b/js/ui/inhibitShortcutsDialog.js
|
|
||||||
@@ -1,5 +1,5 @@
|
|
||||||
/* exported InhibitShortcutsDialog */
|
|
||||||
-const { Clutter, Gio, GLib, GObject, Gtk, Meta, Pango, Shell, St } = imports.gi;
|
|
||||||
+const {Clutter, Gio, GObject, Gtk, Meta, Pango, Shell, St} = imports.gi;
|
|
||||||
|
|
||||||
const Dialog = imports.ui.dialog;
|
|
||||||
const ModalDialog = imports.ui.modalDialog;
|
|
||||||
@@ -57,15 +57,11 @@ var InhibitShortcutsDialog = GObject.registerClass({
|
|
||||||
if (!this._shouldUsePermStore() || this._permStore == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
- let permissions = {};
|
|
||||||
- permissions[this._app.get_id()] = [grant];
|
|
||||||
- let data = GLib.Variant.new('av', {});
|
|
||||||
-
|
|
||||||
- this._permStore.SetRemote(APP_PERMISSIONS_TABLE,
|
|
||||||
- true,
|
|
||||||
- APP_PERMISSIONS_ID,
|
|
||||||
- permissions,
|
|
||||||
- data,
|
|
||||||
+ this._permStore.SetPermissionRemote(APP_PERMISSIONS_TABLE,
|
|
||||||
+ true,
|
|
||||||
+ APP_PERMISSIONS_ID,
|
|
||||||
+ this._app.get_id(),
|
|
||||||
+ [grant],
|
|
||||||
(result, error) => {
|
|
||||||
if (error != null)
|
|
||||||
log(error.message);
|
|
||||||
--
|
|
||||||
2.43.0
|
|
||||||
|
|
||||||
|
|
||||||
From 1391efb2356d1b1eac631df2f5fbd61a7a72bf52 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
||||||
Date: Fri, 18 Nov 2022 22:40:31 +0100
|
|
||||||
Subject: [PATCH 2/2] inhibitShorcutsDialog: Fix permission check
|
|
||||||
|
|
||||||
Each permission entry is an array of strings, so checking that against
|
|
||||||
the expected string itself will always fail.
|
|
||||||
|
|
||||||
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6107
|
|
||||||
|
|
||||||
Part-of:
|
|
||||||
<https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2548>
|
|
||||||
---
|
|
||||||
js/ui/inhibitShortcutsDialog.js | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/js/ui/inhibitShortcutsDialog.js b/js/ui/inhibitShortcutsDialog.js
|
|
||||||
index 8ef5861261..4cd2793c3d 100644
|
|
||||||
--- a/js/ui/inhibitShortcutsDialog.js
|
|
||||||
+++ b/js/ui/inhibitShortcutsDialog.js
|
|
||||||
@@ -145,7 +145,7 @@ var InhibitShortcutsDialog = GObject.registerClass({
|
|
||||||
let [permissions] = res;
|
|
||||||
if (permissions[appId] === undefined) // Not found
|
|
||||||
this._dialog.open();
|
|
||||||
- else if (permissions[appId] == GRANTED)
|
|
||||||
+ else if (permissions[appId][0] === GRANTED)
|
|
||||||
this._emitResponse(DialogResponse.ALLOW);
|
|
||||||
else
|
|
||||||
this._emitResponse(DialogResponse.DENY);
|
|
||||||
--
|
|
||||||
2.43.0
|
|
||||||
|
|
@ -0,0 +1,224 @@
|
|||||||
|
From 76eebb42ed4c76970a9debfc0cd41537923eccde Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
|
||||||
|
Date: Tue, 5 Dec 2017 02:41:50 +0100
|
||||||
|
Subject: [PATCH 1/2] tweener: Save handlers on target and remove them on
|
||||||
|
destroy
|
||||||
|
|
||||||
|
Saving handlers we had using the wrapper as a property of the object and delete
|
||||||
|
them when resetting the object state.
|
||||||
|
Without doing this an handler could be called on a destroyed target when this
|
||||||
|
happens on the onComplete callback.
|
||||||
|
|
||||||
|
https://bugzilla.gnome.org/show_bug.cgi?id=791233
|
||||||
|
---
|
||||||
|
js/ui/tweener.js | 63 ++++++++++++++++++++++++++++++++++++++----------
|
||||||
|
1 file changed, 50 insertions(+), 13 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/tweener.js b/js/ui/tweener.js
|
||||||
|
index bb9ea557c..c04cede25 100644
|
||||||
|
--- a/js/ui/tweener.js
|
||||||
|
+++ b/js/ui/tweener.js
|
||||||
|
@@ -63,30 +63,67 @@ function _getTweenState(target) {
|
||||||
|
return target.__ShellTweenerState;
|
||||||
|
}
|
||||||
|
|
||||||
|
+function _ensureHandlers(target) {
|
||||||
|
+ if (!target.__ShellTweenerHandlers)
|
||||||
|
+ target.__ShellTweenerHandlers = {};
|
||||||
|
+ return target.__ShellTweenerHandlers;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
function _resetTweenState(target) {
|
||||||
|
let state = target.__ShellTweenerState;
|
||||||
|
|
||||||
|
if (state) {
|
||||||
|
- if (state.destroyedId)
|
||||||
|
+ if (state.destroyedId) {
|
||||||
|
state.actor.disconnect(state.destroyedId);
|
||||||
|
+ delete state.destroyedId;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
+ _removeHandler(target, 'onComplete', _tweenCompleted);
|
||||||
|
target.__ShellTweenerState = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function _addHandler(target, params, name, handler) {
|
||||||
|
- if (params[name]) {
|
||||||
|
- let oldHandler = params[name];
|
||||||
|
- let oldScope = params[name + 'Scope'];
|
||||||
|
- let oldParams = params[name + 'Params'];
|
||||||
|
- let eventScope = oldScope ? oldScope : target;
|
||||||
|
-
|
||||||
|
- params[name] = () => {
|
||||||
|
- oldHandler.apply(eventScope, oldParams);
|
||||||
|
- handler(target);
|
||||||
|
- };
|
||||||
|
- } else
|
||||||
|
- params[name] = () => { handler(target); };
|
||||||
|
+ let wrapperNeeded = false;
|
||||||
|
+ let tweenerHandlers = _ensureHandlers(target);
|
||||||
|
+
|
||||||
|
+ if (!(name in tweenerHandlers)) {
|
||||||
|
+ tweenerHandlers[name] = [];
|
||||||
|
+ wrapperNeeded = true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ let handlers = tweenerHandlers[name];
|
||||||
|
+ handlers.push(handler);
|
||||||
|
+
|
||||||
|
+ if (wrapperNeeded) {
|
||||||
|
+ if (params[name]) {
|
||||||
|
+ let oldHandler = params[name];
|
||||||
|
+ let oldScope = params[name + 'Scope'];
|
||||||
|
+ let oldParams = params[name + 'Params'];
|
||||||
|
+ let eventScope = oldScope ? oldScope : target;
|
||||||
|
+
|
||||||
|
+ params[name] = () => {
|
||||||
|
+ oldHandler.apply(eventScope, oldParams);
|
||||||
|
+ handlers.forEach((h) => h(target));
|
||||||
|
+ };
|
||||||
|
+ } else {
|
||||||
|
+ params[name] = () => { handlers.forEach((h) => h(target)); };
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function _removeHandler(target, name, handler) {
|
||||||
|
+ let tweenerHandlers = _ensureHandlers(target);
|
||||||
|
+
|
||||||
|
+ if (name in tweenerHandlers) {
|
||||||
|
+ let handlers = tweenerHandlers[name];
|
||||||
|
+ let handlerIndex = handlers.indexOf(handler);
|
||||||
|
+
|
||||||
|
+ while (handlerIndex > -1) {
|
||||||
|
+ handlers.splice(handlerIndex, 1);
|
||||||
|
+ handlerIndex = handlers.indexOf(handler);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
function _actorDestroyed(target) {
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
||||||
|
|
||||||
|
From 730f6f7d708a0cbcfcc75e4a1fba8512ac7c4c82 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Cosimo Cecchi <cosimo@endlessm.com>
|
||||||
|
Date: Sun, 26 May 2019 08:31:07 -0700
|
||||||
|
Subject: [PATCH 2/2] windowAttentionHandler: disconnect signals before
|
||||||
|
destruction
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
The 'destroy' signal is emitted at the end of the destroy() method.
|
||||||
|
However the implementation of destroy() can end up emitting one of the
|
||||||
|
signals we connect to on the window, causing us to re-enter destroy
|
||||||
|
from its callback.
|
||||||
|
That will in turn lead to some objects getting disposed twice, which
|
||||||
|
produces a stack trace like the following one.
|
||||||
|
|
||||||
|
This commit fixes the issue by overriding the destroy() method instead
|
||||||
|
of connecting to the signal, which allows us to disconnect the signal
|
||||||
|
handlers from the window at an earlier time and avoid re-entrancy.
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
gnome-shell[1082]: Object Gio.Settings (0x7f0af8143f00), has been already deallocated — impossible to access it. This might be caused by the object having been destroyed from C code using something such as destroy(), dispose(), or remove() vfuncs.
|
||||||
|
org.gnome.Shell.desktop[1082]: == Stack trace for context 0x5627f7d1e220 ==
|
||||||
|
org.gnome.Shell.desktop[1082]: #0 5627f9e801a8 i resource:///org/gnome/shell/ui/messageTray.js:238 (7f0aefa9eca0 @ 22)
|
||||||
|
org.gnome.Shell.desktop[1082]: #1 5627f9e80108 i resource:///org/gnome/shell/ui/messageTray.js:802 (7f0aefaa2ee0 @ 28)
|
||||||
|
org.gnome.Shell.desktop[1082]: #2 5627f9e80070 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:79 (7f0aef7b29d0 @ 62)
|
||||||
|
org.gnome.Shell.desktop[1082]: #3 7fffa69fbfc0 b self-hosted:979 (7f0aefa515e0 @ 440)
|
||||||
|
org.gnome.Shell.desktop[1082]: #4 5627f9e7ffe0 i resource:///org/gnome/shell/ui/messageTray.js:121 (7f0aefa9e1f0 @ 71)
|
||||||
|
org.gnome.Shell.desktop[1082]: #5 5627f9e7ff38 i resource:///org/gnome/shell/ui/messageTray.js:1408 (7f0aefaa58b0 @ 22)
|
||||||
|
org.gnome.Shell.desktop[1082]: #6 5627f9e7fe80 i resource:///org/gnome/shell/ui/messageTray.js:1237 (7f0aefaa51f0 @ 729)
|
||||||
|
org.gnome.Shell.desktop[1082]: #7 5627f9e7fde8 i resource:///org/gnome/shell/ui/messageTray.js:1055 (7f0aefaa3d30 @ 124)
|
||||||
|
org.gnome.Shell.desktop[1082]: #8 7fffa69ff8e0 b self-hosted:979 (7f0aefa515e0 @ 440)
|
||||||
|
org.gnome.Shell.desktop[1082]: #9 7fffa69ff9d0 b resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386)
|
||||||
|
org.gnome.Shell.desktop[1082]: #10 5627f9e7fd58 i resource:///org/gnome/shell/ui/messageTray.js:479 (7f0aefaa0940 @ 50)
|
||||||
|
org.gnome.Shell.desktop[1082]: #11 5627f9e7fcb8 i resource:///org/gnome/shell/ui/messageTray.js:808 (7f0aefaa2ee0 @ 99)
|
||||||
|
org.gnome.Shell.desktop[1082]: #12 5627f9e7fc28 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:69 (7f0aef7b28b0 @ 13)
|
||||||
|
org.gnome.Shell.desktop[1082]: #13 5627f9e7fb80 i resource:///org/gnome/shell/ui/main.js:566 (7f0aefcd8820 @ 216)
|
||||||
|
org.gnome.Shell.desktop[1082]: #14 5627f9e7fad0 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:103 (7f0aef7b2c10 @ 27)
|
||||||
|
org.gnome.Shell.desktop[1082]: #15 5627f9e7fa58 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:43 (7f0aef7b2700 @ 17)
|
||||||
|
org.gnome.Shell.desktop[1082]: #16 7fffa6a03350 b resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386)
|
||||||
|
org.gnome.Shell.desktop[1082]: #17 5627f9e7f9d0 i resource:///org/gnome/shell/ui/messageTray.js:471 (7f0aefaa08b0 @ 22)
|
||||||
|
org.gnome.Shell.desktop[1082]: #18 5627f9e7f950 i resource:///org/gnome/shell/ui/calendar.js:752 (7f0aefaabdc0 @ 22)
|
||||||
|
org.gnome.Shell.desktop[1082]: #19 7fffa6a048f0 b self-hosted:979 (7f0aefa515e0 @ 440)
|
||||||
|
org.gnome.Shell.desktop[1082]: == Stack trace for context 0x5627f7d1e220 ==
|
||||||
|
org.gnome.Shell.desktop[1082]: #0 5627f9e801a8 i resource:///org/gnome/shell/ui/messageTray.js:239 (7f0aefa9eca0 @ 42)
|
||||||
|
org.gnome.Shell.desktop[1082]: #1 5627f9e80108 i resource:///org/gnome/shell/ui/messageTray.js:802 (7f0aefaa2ee0 @ 28)
|
||||||
|
org.gnome.Shell.desktop[1082]: #2 5627f9e80070 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:79 (7f0aef7b29d0 @ 62)
|
||||||
|
org.gnome.Shell.desktop[1082]: #3 7fffa69fbfc0 b self-hosted:979 (7f0aefa515e0 @ 440)
|
||||||
|
org.gnome.Shell.desktop[1082]: #4 5627f9e7ffe0 i resource:///org/gnome/shell/ui/messageTray.js:121 (7f0aefa9e1f0 @ 71)
|
||||||
|
org.gnome.Shell.desktop[1082]: #5 5627f9e7ff38 i resource:///org/gnome/shell/ui/messageTray.js:1408 (7f0aefaa58b0 @ 22)
|
||||||
|
org.gnome.Shell.desktop[1082]: #6 5627f9e7fe80 i resource:///org/gnome/shell/ui/messageTray.js:1237 (7f0aefaa51f0 @ 729)
|
||||||
|
org.gnome.Shell.desktop[1082]: #7 5627f9e7fde8 i resource:///org/gnome/shell/ui/messageTray.js:1055 (7f0aefaa3d30 @ 124)
|
||||||
|
org.gnome.Shell.desktop[1082]: #8 7fffa69ff8e0 b self-hosted:979 (7f0aefa515e0 @ 440)
|
||||||
|
org.gnome.Shell.desktop[1082]: #9 7fffa69ff9d0 b resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386)
|
||||||
|
org.gnome.Shell.desktop[1082]: #10 5627f9e7fd58 i resource:///org/gnome/shell/ui/messageTray.js:479 (7f0aefaa0940 @ 50)
|
||||||
|
org.gnome.Shell.desktop[1082]: #11 5627f9e7fcb8 i resource:///org/gnome/shell/ui/messageTray.js:808 (7f0aefaa2ee0 @ 99)
|
||||||
|
org.gnome.Shell.desktop[1082]: #12 5627f9e7fc28 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:69 (7f0aef7b28b0 @ 13)
|
||||||
|
org.gnome.Shell.desktop[1082]: #13 5627f9e7fb80 i resource:///org/gnome/shell/ui/main.js:566 (7f0aefcd8820 @ 216)
|
||||||
|
org.gnome.Shell.desktop[1082]: #14 5627f9e7fad0 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:103 (7f0aef7b2c10 @ 27)
|
||||||
|
org.gnome.Shell.desktop[1082]: #15 5627f9e7fa58 i resource:///org/gnome/shell/ui/windowAttentionHandler.js:43 (7f0aef7b2700 @ 17)
|
||||||
|
org.gnome.Shell.desktop[1082]: #16 7fffa6a03350 b resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386)
|
||||||
|
org.gnome.Shell.desktop[1082]: #17 5627f9e7f9d0 i resource:///org/gnome/shell/ui/messageTray.js:471 (7f0aefaa08b0 @ 22)
|
||||||
|
org.gnome.Shell.desktop[1082]: #18 5627f9e7f950 i resource:///org/gnome/shell/ui/calendar.js:752 (7f0aefaabdc0 @ 22)
|
||||||
|
org.gnome.Shell.desktop[1082]: #19 7fffa6a048f0 b self-hosted:979 (7f0aefa515e0 @ 440)
|
||||||
|
gnome-shell[1082]: g_object_run_dispose: assertion 'G_IS_OBJECT (object)' failed
|
||||||
|
gnome-shell[1082]: Object Gio.Settings (0x7f0af8161750), has been already deallocated — impossible to access it. This might be caused by the object having been destroyed from C code using something such as destroy(), dispose(), or remove() vfuncs.
|
||||||
|
gnome-shell[1082]: g_object_run_dispose: assertion 'G_IS_OBJECT (object)' failed
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/555
|
||||||
|
---
|
||||||
|
js/ui/windowAttentionHandler.js | 17 ++++++++---------
|
||||||
|
1 file changed, 8 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/windowAttentionHandler.js b/js/ui/windowAttentionHandler.js
|
||||||
|
index abdb8a444..a9a7111ba 100644
|
||||||
|
--- a/js/ui/windowAttentionHandler.js
|
||||||
|
+++ b/js/ui/windowAttentionHandler.js
|
||||||
|
@@ -69,8 +69,6 @@ var Source = class WindowAttentionSource extends MessageTray.Source {
|
||||||
|
() => { this.destroy(); }));
|
||||||
|
this.signalIDs.push(this._window.connect('unmanaged',
|
||||||
|
() => { this.destroy(); }));
|
||||||
|
-
|
||||||
|
- this.connect('destroy', this._onDestroy.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
_sync() {
|
||||||
|
@@ -79,13 +77,6 @@ var Source = class WindowAttentionSource extends MessageTray.Source {
|
||||||
|
this.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
- _onDestroy() {
|
||||||
|
- for(let i = 0; i < this.signalIDs.length; i++) {
|
||||||
|
- this._window.disconnect(this.signalIDs[i]);
|
||||||
|
- }
|
||||||
|
- this.signalIDs = [];
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
_createPolicy() {
|
||||||
|
if (this._app && this._app.get_app_info()) {
|
||||||
|
let id = this._app.get_id().replace(/\.desktop$/,'');
|
||||||
|
@@ -99,6 +90,14 @@ var Source = class WindowAttentionSource extends MessageTray.Source {
|
||||||
|
return this._app.create_icon_texture(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ destroy(params) {
|
||||||
|
+ for (let i = 0; i < this.signalIDs.length; i++)
|
||||||
|
+ this._window.disconnect(this.signalIDs[i]);
|
||||||
|
+ this.signalIDs = [];
|
||||||
|
+
|
||||||
|
+ super.destroy(params);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
open() {
|
||||||
|
Main.activateWindow(this._window);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -0,0 +1,161 @@
|
|||||||
|
From 214c4f390faa40199c03a80594313760ffe9c5a6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Fri, 20 Sep 2019 13:17:40 +0200
|
||||||
|
Subject: [PATCH 1/2] unlockDialog: Use inheritance instead of composition
|
||||||
|
|
||||||
|
The screen shield creates the unlock dialog based on the session mode.
|
||||||
|
|
||||||
|
However since commit 0c0d76f7d6990 turned LoginDialog into an actor
|
||||||
|
subclass (while UnlockDialog kept using the delegate pattern), it is
|
||||||
|
no longer possible to handle both objects the same way without warnings.
|
||||||
|
|
||||||
|
Allow this again by turning UnlockDialog into an actor subclass as well.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/736
|
||||||
|
---
|
||||||
|
js/ui/unlockDialog.js | 46 ++++++++++++++++++++++++-------------------
|
||||||
|
1 file changed, 26 insertions(+), 20 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js
|
||||||
|
index 4b0470f4b..55abb652d 100644
|
||||||
|
--- a/js/ui/unlockDialog.js
|
||||||
|
+++ b/js/ui/unlockDialog.js
|
||||||
|
@@ -1,8 +1,7 @@
|
||||||
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||||
|
|
||||||
|
const { AccountsService, Atk, Clutter,
|
||||||
|
- Gdm, Gio, GLib, Meta, Shell, St } = imports.gi;
|
||||||
|
-const Signals = imports.signals;
|
||||||
|
+ Gdm, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
|
||||||
|
|
||||||
|
const Layout = imports.ui.layout;
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
@@ -12,15 +11,19 @@ const AuthPrompt = imports.gdm.authPrompt;
|
||||||
|
// The timeout before going back automatically to the lock screen (in seconds)
|
||||||
|
const IDLE_TIMEOUT = 2 * 60;
|
||||||
|
|
||||||
|
-var UnlockDialog = class {
|
||||||
|
- constructor(parentActor) {
|
||||||
|
- this.actor = new St.Widget({ accessible_role: Atk.Role.WINDOW,
|
||||||
|
- style_class: 'login-dialog',
|
||||||
|
- layout_manager: new Clutter.BoxLayout(),
|
||||||
|
- visible: false });
|
||||||
|
+var UnlockDialog = GObject.registerClass({
|
||||||
|
+ Signals: { 'failed': {} },
|
||||||
|
+}, class UnlockDialog extends St.Widget {
|
||||||
|
+ _init(parentActor) {
|
||||||
|
+ super._init({
|
||||||
|
+ accessible_role: Atk.Role.WINDOW,
|
||||||
|
+ style_class: 'login-dialog',
|
||||||
|
+ layout_manager: new Clutter.BoxLayout(),
|
||||||
|
+ visible: false,
|
||||||
|
+ });
|
||||||
|
|
||||||
|
- this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true }));
|
||||||
|
- parentActor.add_child(this.actor);
|
||||||
|
+ this.add_constraint(new Layout.MonitorConstraint({ primary: true }));
|
||||||
|
+ parentActor.add_child(this);
|
||||||
|
|
||||||
|
this._userManager = AccountsService.UserManager.get_default();
|
||||||
|
this._userName = GLib.get_user_name();
|
||||||
|
@@ -31,7 +34,7 @@ var UnlockDialog = class {
|
||||||
|
y_align: Clutter.ActorAlign.CENTER,
|
||||||
|
x_expand: true,
|
||||||
|
y_expand: true });
|
||||||
|
- this.actor.add_child(this._promptBox);
|
||||||
|
+ this.add_child(this._promptBox);
|
||||||
|
|
||||||
|
this._gdmClient = new Gdm.Client();
|
||||||
|
|
||||||
|
@@ -70,10 +73,12 @@ var UnlockDialog = class {
|
||||||
|
this._authPrompt.reset();
|
||||||
|
this._updateSensitivity(true);
|
||||||
|
|
||||||
|
- Main.ctrlAltTabManager.addGroup(this.actor, _("Unlock Window"), 'dialog-password-symbolic');
|
||||||
|
+ Main.ctrlAltTabManager.addGroup(this, _("Unlock Window"), 'dialog-password-symbolic');
|
||||||
|
|
||||||
|
this._idleMonitor = Meta.IdleMonitor.get_core();
|
||||||
|
this._idleWatchId = this._idleMonitor.add_idle_watch(IDLE_TIMEOUT * 1000, this._escape.bind(this));
|
||||||
|
+
|
||||||
|
+ this.connect('destroy', this._onDestroy.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateSensitivity(sensitive) {
|
||||||
|
@@ -112,9 +117,8 @@ var UnlockDialog = class {
|
||||||
|
this._authPrompt.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
- destroy() {
|
||||||
|
+ _onDestroy() {
|
||||||
|
this.popModal();
|
||||||
|
- this.actor.destroy();
|
||||||
|
|
||||||
|
if (this._idleWatchId) {
|
||||||
|
this._idleMonitor.remove_watch(this._idleWatchId);
|
||||||
|
@@ -137,13 +141,16 @@ var UnlockDialog = class {
|
||||||
|
}
|
||||||
|
|
||||||
|
open(timestamp) {
|
||||||
|
- this.actor.show();
|
||||||
|
+ this.show();
|
||||||
|
|
||||||
|
if (this._isModal)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
- if (!Main.pushModal(this.actor, { timestamp: timestamp,
|
||||||
|
- actionMode: Shell.ActionMode.UNLOCK_SCREEN }))
|
||||||
|
+ let modalParams = {
|
||||||
|
+ timestamp,
|
||||||
|
+ actionMode: Shell.ActionMode.UNLOCK_SCREEN,
|
||||||
|
+ };
|
||||||
|
+ if (!Main.pushModal(this, modalParams))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this._isModal = true;
|
||||||
|
@@ -153,9 +160,8 @@ var UnlockDialog = class {
|
||||||
|
|
||||||
|
popModal(timestamp) {
|
||||||
|
if (this._isModal) {
|
||||||
|
- Main.popModal(this.actor, timestamp);
|
||||||
|
+ Main.popModal(this, timestamp);
|
||||||
|
this._isModal = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-};
|
||||||
|
-Signals.addSignalMethods(UnlockDialog.prototype);
|
||||||
|
+});
|
||||||
|
--
|
||||||
|
2.31.1
|
||||||
|
|
||||||
|
|
||||||
|
From cddeb2f4e38928e0d5e0f3a852961f639536aff3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Fri, 20 Sep 2019 13:14:40 +0200
|
||||||
|
Subject: [PATCH 2/2] screenShield: Stop using deprecated actor property
|
||||||
|
|
||||||
|
Both LoginDialog and UnlockDialog are now actor subclasses, so stop
|
||||||
|
using the deprecated actor delegate that will trigger a warning.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/736
|
||||||
|
---
|
||||||
|
js/ui/screenShield.js | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js
|
||||||
|
index 2d0a429be..f97a9288a 100644
|
||||||
|
--- a/js/ui/screenShield.js
|
||||||
|
+++ b/js/ui/screenShield.js
|
||||||
|
@@ -917,8 +917,8 @@ var ScreenShield = class {
|
||||||
|
this._lockScreenGroup.hide();
|
||||||
|
|
||||||
|
if (this._dialog) {
|
||||||
|
- this._dialog.actor.grab_key_focus();
|
||||||
|
- this._dialog.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
||||||
|
+ this._dialog.grab_key_focus();
|
||||||
|
+ this._dialog.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.31.1
|
||||||
|
|
@ -1,334 +0,0 @@
|
|||||||
From 49a950b9e0dc262fd20c28e21ee4815ea8efe758 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Sebastian Keller <skeller@gnome.org>
|
|
||||||
Date: Tue, 16 Nov 2021 18:57:26 +0100
|
|
||||||
Subject: [PATCH 1/3] search: Split out the description highlighter into its
|
|
||||||
own class
|
|
||||||
|
|
||||||
No functional change yet, only preparation to allow adding a unit test
|
|
||||||
later on.
|
|
||||||
|
|
||||||
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2033>
|
|
||||||
---
|
|
||||||
js/misc/util.js | 38 +++++++++++++++++++++++++++++++++++++-
|
|
||||||
js/ui/search.js | 12 +++++-------
|
|
||||||
2 files changed, 42 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/js/misc/util.js b/js/misc/util.js
|
|
||||||
index 8139d3f47..d1a702960 100644
|
|
||||||
--- a/js/misc/util.js
|
|
||||||
+++ b/js/misc/util.js
|
|
||||||
@@ -1,7 +1,8 @@
|
|
||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
/* exported findUrls, spawn, spawnCommandLine, spawnApp, trySpawnCommandLine,
|
|
||||||
formatTime, formatTimeSpan, createTimeLabel, insertSorted,
|
|
||||||
- ensureActorVisibleInScrollView, wiggle, lerp, GNOMEversionCompare */
|
|
||||||
+ ensureActorVisibleInScrollView, wiggle, lerp, GNOMEversionCompare,
|
|
||||||
+ Highlighter */
|
|
||||||
|
|
||||||
const { Clutter, Gio, GLib, Shell, St, GnomeDesktop } = imports.gi;
|
|
||||||
const Gettext = imports.gettext;
|
|
||||||
@@ -477,3 +478,38 @@ function GNOMEversionCompare(version1, version2) {
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+/* @class Highlighter Highlight given terms in text using markup. */
|
|
||||||
+var Highlighter = class {
|
|
||||||
+ /**
|
|
||||||
+ * @param {?string[]} terms - list of terms to highlight
|
|
||||||
+ */
|
|
||||||
+ constructor(terms) {
|
|
||||||
+ if (!terms)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ const escapedTerms = terms
|
|
||||||
+ .map(term => Shell.util_regex_escape(term))
|
|
||||||
+ .filter(term => term.length > 0);
|
|
||||||
+
|
|
||||||
+ if (escapedTerms.length === 0)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ this._highlightRegex = new RegExp('(%s)'.format(
|
|
||||||
+ escapedTerms.join('|')), 'gi');
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /**
|
|
||||||
+ * Highlight all occurences of the terms defined for this
|
|
||||||
+ * highlighter in the provided text using markup.
|
|
||||||
+ *
|
|
||||||
+ * @param {string} text - text to highlight the defined terms in
|
|
||||||
+ * @returns {string}
|
|
||||||
+ */
|
|
||||||
+ highlight(text) {
|
|
||||||
+ if (!this._highlightRegex)
|
|
||||||
+ return text;
|
|
||||||
+
|
|
||||||
+ return text.replace(this._highlightRegex, '<b>$1</b>');
|
|
||||||
+ }
|
|
||||||
+};
|
|
||||||
diff --git a/js/ui/search.js b/js/ui/search.js
|
|
||||||
index 7300b053e..b1e76c46d 100644
|
|
||||||
--- a/js/ui/search.js
|
|
||||||
+++ b/js/ui/search.js
|
|
||||||
@@ -10,6 +10,8 @@ const ParentalControlsManager = imports.misc.parentalControlsManager;
|
|
||||||
const RemoteSearch = imports.ui.remoteSearch;
|
|
||||||
const Util = imports.misc.util;
|
|
||||||
|
|
||||||
+const { Highlighter } = imports.misc.util;
|
|
||||||
+
|
|
||||||
const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers';
|
|
||||||
|
|
||||||
var MAX_LIST_SEARCH_RESULTS_ROWS = 5;
|
|
||||||
@@ -596,7 +598,7 @@ var SearchResultsView = GObject.registerClass({
|
|
||||||
|
|
||||||
this._providers = [];
|
|
||||||
|
|
||||||
- this._highlightRegex = null;
|
|
||||||
+ this._highlighter = new Highlighter();
|
|
||||||
|
|
||||||
this._searchSettings = new Gio.Settings({ schema_id: SEARCH_PROVIDERS_SCHEMA });
|
|
||||||
this._searchSettings.connect('changed::disabled', this._reloadRemoteProviders.bind(this));
|
|
||||||
@@ -739,8 +741,7 @@ var SearchResultsView = GObject.registerClass({
|
|
||||||
if (this._searchTimeoutId == 0)
|
|
||||||
this._searchTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 150, this._onSearchTimeout.bind(this));
|
|
||||||
|
|
||||||
- let escapedTerms = this._terms.map(term => Shell.util_regex_escape(term));
|
|
||||||
- this._highlightRegex = new RegExp('(%s)'.format(escapedTerms.join('|')), 'gi');
|
|
||||||
+ this._highlighter = new Highlighter(this._terms);
|
|
||||||
|
|
||||||
this.emit('terms-changed');
|
|
||||||
}
|
|
||||||
@@ -894,10 +895,7 @@ var SearchResultsView = GObject.registerClass({
|
|
||||||
if (!description)
|
|
||||||
return '';
|
|
||||||
|
|
||||||
- if (!this._highlightRegex)
|
|
||||||
- return description;
|
|
||||||
-
|
|
||||||
- return description.replace(this._highlightRegex, '<b>$1</b>');
|
|
||||||
+ return this._highlighter.highlight(description);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
--
|
|
||||||
2.35.1
|
|
||||||
|
|
||||||
|
|
||||||
From 7c1abe1bd91ecf274d81e122035cbeeef6fd58d4 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Sebastian Keller <skeller@gnome.org>
|
|
||||||
Date: Wed, 17 Nov 2021 02:50:39 +0100
|
|
||||||
Subject: [PATCH 2/3] util: Properly handle markup in highlighter
|
|
||||||
|
|
||||||
The code to highlight matches did not properly escape the passed in text
|
|
||||||
as for markup before adding its highlighting markup. This lead to some
|
|
||||||
search result descriptions not showing up, because their descriptions
|
|
||||||
contained characters, such as "<", that would have to be escaped when
|
|
||||||
used in markup or otherwise lead to invalid markup.
|
|
||||||
|
|
||||||
To work around this some search providers wrongly started escaping the
|
|
||||||
description on their end before sending them to gnome-shell. This lead
|
|
||||||
to another issue. Now if the highlighter was trying to highlight the
|
|
||||||
term "a", and the escaped description contained "'", the "a" in
|
|
||||||
that would be considered a match and surrounded by "<b></b>". This
|
|
||||||
however would also generate invalid markup, again leading to an error
|
|
||||||
and the description not being shown.
|
|
||||||
|
|
||||||
Fix this by always escaping the passed in string before applying the
|
|
||||||
highlights in such a way that there are no matches within entities.
|
|
||||||
|
|
||||||
This also means that search providers that escaped their description
|
|
||||||
strings will now show up with the markup syntax. This will have to be
|
|
||||||
fixed separately in the affected search providers.
|
|
||||||
|
|
||||||
Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4791
|
|
||||||
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2033>
|
|
||||||
---
|
|
||||||
js/misc/util.js | 21 +++++++++++++++++++--
|
|
||||||
1 file changed, 19 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/js/misc/util.js b/js/misc/util.js
|
|
||||||
index d1a702960..802398d18 100644
|
|
||||||
--- a/js/misc/util.js
|
|
||||||
+++ b/js/misc/util.js
|
|
||||||
@@ -508,8 +508,25 @@ var Highlighter = class {
|
|
||||||
*/
|
|
||||||
highlight(text) {
|
|
||||||
if (!this._highlightRegex)
|
|
||||||
- return text;
|
|
||||||
+ return GLib.markup_escape_text(text, -1);
|
|
||||||
+
|
|
||||||
+ let escaped = [];
|
|
||||||
+ let lastMatchEnd = 0;
|
|
||||||
+ let match;
|
|
||||||
+ while ((match = this._highlightRegex.exec(text))) {
|
|
||||||
+ if (match.index > lastMatchEnd) {
|
|
||||||
+ let unmatched = GLib.markup_escape_text(
|
|
||||||
+ text.slice(lastMatchEnd, match.index), -1);
|
|
||||||
+ escaped.push(unmatched);
|
|
||||||
+ }
|
|
||||||
+ let matched = GLib.markup_escape_text(match[0], -1);
|
|
||||||
+ escaped.push('<b>%s</b>'.format(matched));
|
|
||||||
+ lastMatchEnd = match.index + match[0].length;
|
|
||||||
+ }
|
|
||||||
+ let unmatched = GLib.markup_escape_text(
|
|
||||||
+ text.slice(lastMatchEnd), -1);
|
|
||||||
+ escaped.push(unmatched);
|
|
||||||
|
|
||||||
- return text.replace(this._highlightRegex, '<b>$1</b>');
|
|
||||||
+ return escaped.join('');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
--
|
|
||||||
2.35.1
|
|
||||||
|
|
||||||
|
|
||||||
From 82e2a6dcfabc2f82efbf468175d16c303f0c73da Mon Sep 17 00:00:00 2001
|
|
||||||
From: Sebastian Keller <skeller@gnome.org>
|
|
||||||
Date: Wed, 17 Nov 2021 03:05:05 +0100
|
|
||||||
Subject: [PATCH 3/3] tests: Add unit test for highlighter
|
|
||||||
|
|
||||||
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2033>
|
|
||||||
---
|
|
||||||
tests/meson.build | 12 ++++-
|
|
||||||
tests/unit/highlighter.js | 106 ++++++++++++++++++++++++++++++++++++++
|
|
||||||
2 files changed, 117 insertions(+), 1 deletion(-)
|
|
||||||
create mode 100644 tests/unit/highlighter.js
|
|
||||||
|
|
||||||
diff --git a/tests/meson.build b/tests/meson.build
|
|
||||||
index c0431631f..50fb601e9 100644
|
|
||||||
--- a/tests/meson.build
|
|
||||||
+++ b/tests/meson.build
|
|
||||||
@@ -10,7 +10,17 @@ run_test = configure_file(
|
|
||||||
testenv = environment()
|
|
||||||
testenv.set('GSETTINGS_SCHEMA_DIR', join_paths(meson.build_root(), 'data'))
|
|
||||||
|
|
||||||
-foreach test : ['insertSorted', 'jsParse', 'markup', 'params', 'url', 'versionCompare']
|
|
||||||
+tests = [
|
|
||||||
+ 'highlighter',
|
|
||||||
+ 'insertSorted',
|
|
||||||
+ 'jsParse',
|
|
||||||
+ 'markup',
|
|
||||||
+ 'params',
|
|
||||||
+ 'url',
|
|
||||||
+ 'versionCompare',
|
|
||||||
+]
|
|
||||||
+
|
|
||||||
+foreach test : tests
|
|
||||||
test(test, run_test,
|
|
||||||
args: 'unit/@0@.js'.format(test),
|
|
||||||
env: testenv,
|
|
||||||
diff --git a/tests/unit/highlighter.js b/tests/unit/highlighter.js
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000..d582d38e3
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/tests/unit/highlighter.js
|
|
||||||
@@ -0,0 +1,106 @@
|
|
||||||
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
+
|
|
||||||
+// Test cases for SearchResult description match highlighter
|
|
||||||
+
|
|
||||||
+const JsUnit = imports.jsUnit;
|
|
||||||
+const Pango = imports.gi.Pango;
|
|
||||||
+
|
|
||||||
+const Environment = imports.ui.environment;
|
|
||||||
+Environment.init();
|
|
||||||
+
|
|
||||||
+const Util = imports.misc.util;
|
|
||||||
+
|
|
||||||
+const tests = [
|
|
||||||
+ { input: 'abc cba',
|
|
||||||
+ terms: null,
|
|
||||||
+ output: 'abc cba' },
|
|
||||||
+ { input: 'abc cba',
|
|
||||||
+ terms: [],
|
|
||||||
+ output: 'abc cba' },
|
|
||||||
+ { input: 'abc cba',
|
|
||||||
+ terms: [''],
|
|
||||||
+ output: 'abc cba' },
|
|
||||||
+ { input: 'abc cba',
|
|
||||||
+ terms: ['a'],
|
|
||||||
+ output: '<b>a</b>bc cb<b>a</b>' },
|
|
||||||
+ { input: 'abc cba',
|
|
||||||
+ terms: ['a', 'a'],
|
|
||||||
+ output: '<b>a</b>bc cb<b>a</b>' },
|
|
||||||
+ { input: 'CaSe InSenSiTiVe',
|
|
||||||
+ terms: ['cas', 'sens'],
|
|
||||||
+ output: '<b>CaS</b>e In<b>SenS</b>iTiVe' },
|
|
||||||
+ { input: 'This contains the < character',
|
|
||||||
+ terms: null,
|
|
||||||
+ output: 'This contains the < character' },
|
|
||||||
+ { input: 'Don\'t',
|
|
||||||
+ terms: ['t'],
|
|
||||||
+ output: 'Don'<b>t</b>' },
|
|
||||||
+ { input: 'Don\'t',
|
|
||||||
+ terms: ['n\'t'],
|
|
||||||
+ output: 'Do<b>n't</b>' },
|
|
||||||
+ { input: 'Don\'t',
|
|
||||||
+ terms: ['o', 't'],
|
|
||||||
+ output: 'D<b>o</b>n'<b>t</b>' },
|
|
||||||
+ { input: 'salt&pepper',
|
|
||||||
+ terms: ['salt'],
|
|
||||||
+ output: '<b>salt</b>&pepper' },
|
|
||||||
+ { input: 'salt&pepper',
|
|
||||||
+ terms: ['salt', 'alt'],
|
|
||||||
+ output: '<b>salt</b>&pepper' },
|
|
||||||
+ { input: 'salt&pepper',
|
|
||||||
+ terms: ['pepper'],
|
|
||||||
+ output: 'salt&<b>pepper</b>' },
|
|
||||||
+ { input: 'salt&pepper',
|
|
||||||
+ terms: ['salt', 'pepper'],
|
|
||||||
+ output: '<b>salt</b>&<b>pepper</b>' },
|
|
||||||
+ { input: 'salt&pepper',
|
|
||||||
+ terms: ['t', 'p'],
|
|
||||||
+ output: 'sal<b>t</b>&<b>p</b>e<b>p</b><b>p</b>er' },
|
|
||||||
+ { input: 'salt&pepper',
|
|
||||||
+ terms: ['t', '&', 'p'],
|
|
||||||
+ output: 'sal<b>t</b><b>&</b><b>p</b>e<b>p</b><b>p</b>er' },
|
|
||||||
+ { input: 'salt&pepper',
|
|
||||||
+ terms: ['e'],
|
|
||||||
+ output: 'salt&p<b>e</b>pp<b>e</b>r' },
|
|
||||||
+ { input: 'salt&pepper',
|
|
||||||
+ terms: ['&a', '&am', '&', '&'],
|
|
||||||
+ output: 'salt&pepper' },
|
|
||||||
+ { input: '&&&&&',
|
|
||||||
+ terms: ['a'],
|
|
||||||
+ output: '&&&&&' },
|
|
||||||
+ { input: '&;&;&;&;&;',
|
|
||||||
+ terms: ['a'],
|
|
||||||
+ output: '&;&;&;&;&;' },
|
|
||||||
+ { input: '&;&;&;&;&;',
|
|
||||||
+ terms: [';'],
|
|
||||||
+ output: '&<b>;</b>&<b>;</b>&<b>;</b>&<b>;</b>&<b>;</b>' },
|
|
||||||
+ { input: '&',
|
|
||||||
+ terms: ['a'],
|
|
||||||
+ output: '&<b>a</b>mp;' }
|
|
||||||
+];
|
|
||||||
+
|
|
||||||
+try {
|
|
||||||
+ for (let i = 0; i < tests.length; i++) {
|
|
||||||
+ let highlighter = new Util.Highlighter(tests[i].terms);
|
|
||||||
+ let output = highlighter.highlight(tests[i].input);
|
|
||||||
+
|
|
||||||
+ JsUnit.assertEquals(`Test ${i + 1} highlight ` +
|
|
||||||
+ `"${tests[i].terms}" in "${tests[i].input}"`,
|
|
||||||
+ output, tests[i].output);
|
|
||||||
+
|
|
||||||
+ let parsed = false;
|
|
||||||
+ try {
|
|
||||||
+ Pango.parse_markup(output, -1, '');
|
|
||||||
+ parsed = true;
|
|
||||||
+ } catch (e) {}
|
|
||||||
+ JsUnit.assertEquals(`Test ${i + 1} is valid markup`, true, parsed);
|
|
||||||
+ }
|
|
||||||
+} catch (e) {
|
|
||||||
+ if (typeof(e.isJsUnitException) != 'undefined'
|
|
||||||
+ && e.isJsUnitException)
|
|
||||||
+ {
|
|
||||||
+ if (e.comment)
|
|
||||||
+ log(`Error in: ${e.comment}`);
|
|
||||||
+ }
|
|
||||||
+ throw e;
|
|
||||||
+}
|
|
||||||
--
|
|
||||||
2.35.1
|
|
||||||
|
|
@ -0,0 +1,131 @@
|
|||||||
|
From e2a1b737156804e2647e5de938c3d170c11b6ba4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Fri, 31 Jul 2020 20:40:36 +0200
|
||||||
|
Subject: [PATCH 1/2] status/network: Use D-Bus to launch Settings panels
|
||||||
|
|
||||||
|
For more obscure network configurations, we need to launch the
|
||||||
|
corresponding Settings panel with additional parameters, so we
|
||||||
|
cannot simply launch the .desktop file.
|
||||||
|
|
||||||
|
However we can do better than spawning a command line: Control center
|
||||||
|
exposes an application action we can use instead, so the process is
|
||||||
|
launched with the appropriate activation environment and startup
|
||||||
|
notification support.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1385
|
||||||
|
---
|
||||||
|
js/ui/status/network.js | 33 +++++++++++++++++++++++++++++----
|
||||||
|
1 file changed, 29 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/status/network.js b/js/ui/status/network.js
|
||||||
|
index f8991d02f..0e7e82ce0 100644
|
||||||
|
--- a/js/ui/status/network.js
|
||||||
|
+++ b/js/ui/status/network.js
|
||||||
|
@@ -15,6 +15,8 @@ const Util = imports.misc.util;
|
||||||
|
|
||||||
|
const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||||
|
|
||||||
|
+Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish');
|
||||||
|
+
|
||||||
|
const NMConnectionCategory = {
|
||||||
|
INVALID: 'invalid',
|
||||||
|
WIRED: 'wired',
|
||||||
|
@@ -75,6 +77,30 @@ function ensureActiveConnectionProps(active, client) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+function launchSettingsPanel(panel, ...args) {
|
||||||
|
+ const param = new GLib.Variant('(sav)',
|
||||||
|
+ [panel, args.map(s => new GLib.Variant('s', s))]);
|
||||||
|
+ const platformData = {
|
||||||
|
+ 'desktop-startup-id': new GLib.Variant('s',
|
||||||
|
+ '_TIME%s'.format(global.get_current_time())),
|
||||||
|
+ };
|
||||||
|
+ try {
|
||||||
|
+ Gio.DBus.session.call(
|
||||||
|
+ 'org.gnome.ControlCenter',
|
||||||
|
+ '/org/gnome/ControlCenter',
|
||||||
|
+ 'org.freedesktop.Application',
|
||||||
|
+ 'ActivateAction',
|
||||||
|
+ new GLib.Variant('(sava{sv})',
|
||||||
|
+ ['launch-panel', [param], platformData]),
|
||||||
|
+ null,
|
||||||
|
+ Gio.DBusCallFlags.NONE,
|
||||||
|
+ -1,
|
||||||
|
+ null);
|
||||||
|
+ } catch (e) {
|
||||||
|
+ log('Failed to launch Settings panel: %s'.format(e.message));
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
var NMConnectionItem = class {
|
||||||
|
constructor(section, connection) {
|
||||||
|
this._section = section;
|
||||||
|
@@ -534,8 +560,7 @@ var NMDeviceModem = class extends NMConnectionDevice {
|
||||||
|
}
|
||||||
|
|
||||||
|
_autoConnect() {
|
||||||
|
- Util.spawn(['gnome-control-center', 'network',
|
||||||
|
- 'connect-3g', this._device.get_path()]);
|
||||||
|
+ launchSettingsPanel('network', 'connect-3g', this._device.get_path());
|
||||||
|
}
|
||||||
|
|
||||||
|
_sessionUpdated() {
|
||||||
|
@@ -920,8 +945,8 @@ var NMWirelessDialog = class extends ModalDialog.ModalDialog {
|
||||||
|
|| (accessPoints[0]._secType == NMAccessPointSecurity.WPA_ENT)) {
|
||||||
|
// 802.1x-enabled APs require further configuration, so they're
|
||||||
|
// handled in gnome-control-center
|
||||||
|
- Util.spawn(['gnome-control-center', 'wifi', 'connect-8021x-wifi',
|
||||||
|
- this._device.get_path(), accessPoints[0].get_path()]);
|
||||||
|
+ launchSettingsPanel('wifi', 'connect-8021x-wifi',
|
||||||
|
+ this._device.get_path(), accessPoints[0].get_path());
|
||||||
|
} else {
|
||||||
|
let connection = new NM.SimpleConnection();
|
||||||
|
this._client.add_and_activate_connection_async(connection, this._device, accessPoints[0].get_path(), null, null)
|
||||||
|
--
|
||||||
|
2.38.1
|
||||||
|
|
||||||
|
|
||||||
|
From 9ca1989fcc73157685742470c25f538d01d8df44 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiaoguang Wang <xwang@suse.com>
|
||||||
|
Date: Mon, 21 Feb 2022 09:11:23 +0800
|
||||||
|
Subject: [PATCH 2/2] network: Get dbus path from NMDevice
|
||||||
|
|
||||||
|
In the NetworkManager new version the NMDevice.get_path returns pci
|
||||||
|
path, we need to use NM prototype to get device dbus path.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4565
|
||||||
|
|
||||||
|
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2194>
|
||||||
|
---
|
||||||
|
js/ui/status/network.js | 7 ++++++-
|
||||||
|
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/status/network.js b/js/ui/status/network.js
|
||||||
|
index 0e7e82ce0..9d6a83b73 100644
|
||||||
|
--- a/js/ui/status/network.js
|
||||||
|
+++ b/js/ui/status/network.js
|
||||||
|
@@ -946,7 +946,7 @@ var NMWirelessDialog = class extends ModalDialog.ModalDialog {
|
||||||
|
// 802.1x-enabled APs require further configuration, so they're
|
||||||
|
// handled in gnome-control-center
|
||||||
|
launchSettingsPanel('wifi', 'connect-8021x-wifi',
|
||||||
|
- this._device.get_path(), accessPoints[0].get_path());
|
||||||
|
+ this._getDeviceDBusPath(), accessPoints[0].get_path());
|
||||||
|
} else {
|
||||||
|
let connection = new NM.SimpleConnection();
|
||||||
|
this._client.add_and_activate_connection_async(connection, this._device, accessPoints[0].get_path(), null, null)
|
||||||
|
@@ -956,6 +956,11 @@ var NMWirelessDialog = class extends ModalDialog.ModalDialog {
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ _getDeviceDBusPath() {
|
||||||
|
+ // nm_object_get_path() is shadowed by nm_device_get_path()
|
||||||
|
+ return NM.Object.prototype.get_path.call(this._device);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
_notifySsidCb(accessPoint) {
|
||||||
|
if (accessPoint.get_ssid() != null) {
|
||||||
|
accessPoint.disconnect(accessPoint._notifySsidId);
|
||||||
|
--
|
||||||
|
2.38.1
|
||||||
|
|
@ -1,92 +0,0 @@
|
|||||||
From ce8ac36613ef4fbb697fc9f6613844168c05a8d3 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ray Strode <rstrode@redhat.com>
|
|
||||||
Date: Fri, 8 Oct 2021 11:08:17 -0400
|
|
||||||
Subject: [PATCH 1/2] unlockDialog: Don't create AuthDialog just to finish it
|
|
||||||
|
|
||||||
If the the unlock dialog gets finished before an auth dialog is
|
|
||||||
created, the code currently creates one just to tell it to finish.
|
|
||||||
|
|
||||||
This commit changes the code to skip creating the auth dialog in
|
|
||||||
that case.
|
|
||||||
|
|
||||||
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1999>
|
|
||||||
---
|
|
||||||
js/ui/unlockDialog.js | 6 +++++-
|
|
||||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js
|
|
||||||
index c81c6184a9..d8c45f7510 100644
|
|
||||||
--- a/js/ui/unlockDialog.js
|
|
||||||
+++ b/js/ui/unlockDialog.js
|
|
||||||
@@ -884,7 +884,11 @@ var UnlockDialog = GObject.registerClass({
|
|
||||||
}
|
|
||||||
|
|
||||||
finish(onComplete) {
|
|
||||||
- this._ensureAuthPrompt();
|
|
||||||
+ if (!this._authPrompt) {
|
|
||||||
+ onComplete();
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
this._authPrompt.finish(onComplete);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.39.1
|
|
||||||
|
|
||||||
|
|
||||||
From 2a513d44e7b887b355d6b71cf88c4114a8b685f8 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ray Strode <rstrode@redhat.com>
|
|
||||||
Date: Tue, 5 Oct 2021 11:01:19 -0400
|
|
||||||
Subject: [PATCH 2/2] unlockDialog: Properly reset auth prompt when showing it
|
|
||||||
|
|
||||||
If a user hits escape twice really fast when coming back to
|
|
||||||
their machine to unlock it, they made end up getting presented
|
|
||||||
with a non-functional unlock screen that doesn't show their
|
|
||||||
user icon and doesn't ask for a password.
|
|
||||||
|
|
||||||
This is because showPrompt assumes that if an auth prompt already
|
|
||||||
exists, it's ready to go. That may not be true, if it's in the
|
|
||||||
process of getting torn down at the time because it's in the middle
|
|
||||||
of a cancel animation.
|
|
||||||
|
|
||||||
This commit solves the problem by ensuring the auth prompt is always
|
|
||||||
in a fresh reset state before showing it.
|
|
||||||
|
|
||||||
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1999>
|
|
||||||
---
|
|
||||||
js/ui/unlockDialog.js | 18 ++++++++----------
|
|
||||||
1 file changed, 8 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js
|
|
||||||
index d8c45f7510..00e3eef971 100644
|
|
||||||
--- a/js/ui/unlockDialog.js
|
|
||||||
+++ b/js/ui/unlockDialog.js
|
|
||||||
@@ -689,16 +689,14 @@ var UnlockDialog = GObject.registerClass({
|
|
||||||
}
|
|
||||||
|
|
||||||
_ensureAuthPrompt() {
|
|
||||||
- if (this._authPrompt)
|
|
||||||
- return;
|
|
||||||
-
|
|
||||||
- this._authPrompt = new AuthPrompt.AuthPrompt(this._gdmClient,
|
|
||||||
- AuthPrompt.AuthPromptMode.UNLOCK_ONLY);
|
|
||||||
- this._authPrompt.connect('failed', this._fail.bind(this));
|
|
||||||
- this._authPrompt.connect('cancelled', this._fail.bind(this));
|
|
||||||
- this._authPrompt.connect('reset', this._onReset.bind(this));
|
|
||||||
-
|
|
||||||
- this._promptBox.add_child(this._authPrompt);
|
|
||||||
+ if (!this._authPrompt) {
|
|
||||||
+ this._authPrompt = new AuthPrompt.AuthPrompt(this._gdmClient,
|
|
||||||
+ AuthPrompt.AuthPromptMode.UNLOCK_ONLY);
|
|
||||||
+ this._authPrompt.connect('failed', this._fail.bind(this));
|
|
||||||
+ this._authPrompt.connect('cancelled', this._fail.bind(this));
|
|
||||||
+ this._authPrompt.connect('reset', this._onReset.bind(this));
|
|
||||||
+ this._promptBox.add_child(this._authPrompt);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
this._authPrompt.reset();
|
|
||||||
this._authPrompt.updateSensitivity(true);
|
|
||||||
--
|
|
||||||
2.39.1
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
|||||||
From 1f8252470ce43dc8a0680871013e2f4492764302 Mon Sep 17 00:00:00 2001
|
|
||||||
From: rpm-build <rpm-build>
|
|
||||||
Date: Mon, 28 Feb 2022 10:27:09 -0500
|
|
||||||
Subject: [PATCH] data: Enable logo extension out of the box
|
|
||||||
|
|
||||||
Our brand team would like the logo extension to be used on new
|
|
||||||
installs.
|
|
||||||
|
|
||||||
This commit makes sure it gets enabled out of the box.
|
|
||||||
---
|
|
||||||
data/org.gnome.shell.gschema.xml.in | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in
|
|
||||||
index d5ea1e3..e3f440c 100644
|
|
||||||
--- a/data/org.gnome.shell.gschema.xml.in
|
|
||||||
+++ b/data/org.gnome.shell.gschema.xml.in
|
|
||||||
@@ -1,45 +1,45 @@
|
|
||||||
<schemalist>
|
|
||||||
<schema id="org.gnome.shell" path="/org/gnome/shell/"
|
|
||||||
gettext-domain="@GETTEXT_PACKAGE@">
|
|
||||||
<key name="development-tools" type="b">
|
|
||||||
<default>true</default>
|
|
||||||
<summary>
|
|
||||||
Enable internal tools useful for developers and testers from Alt-F2
|
|
||||||
</summary>
|
|
||||||
<description>
|
|
||||||
Allows access to internal debugging and monitoring tools
|
|
||||||
using the Alt-F2 dialog.
|
|
||||||
</description>
|
|
||||||
</key>
|
|
||||||
<key name="enabled-extensions" type="as">
|
|
||||||
- <default>[]</default>
|
|
||||||
+ <default>['background-logo@fedorahosted.org']</default>
|
|
||||||
<summary>UUIDs of extensions to enable</summary>
|
|
||||||
<description>
|
|
||||||
GNOME Shell extensions have a UUID property; this key lists extensions
|
|
||||||
which should be loaded. Any extension that wants to be loaded needs
|
|
||||||
to be in this list. You can also manipulate this list with the
|
|
||||||
EnableExtension and DisableExtension D-Bus methods on org.gnome.Shell.
|
|
||||||
</description>
|
|
||||||
</key>
|
|
||||||
<key name="disabled-extensions" type="as">
|
|
||||||
<default>[]</default>
|
|
||||||
<summary>UUIDs of extensions to force disabling</summary>
|
|
||||||
<description>
|
|
||||||
GNOME Shell extensions have a UUID property; this key lists extensions
|
|
||||||
which should be disabled, even if loaded as part of the current mode.
|
|
||||||
You can also manipulate this list with the EnableExtension and
|
|
||||||
DisableExtension D-Bus methods on org.gnome.Shell.
|
|
||||||
This key takes precedence over the “enabled-extensions” setting.
|
|
||||||
</description>
|
|
||||||
</key>
|
|
||||||
<key name="disable-user-extensions" type="b">
|
|
||||||
<default>false</default>
|
|
||||||
<summary>Disable user extensions</summary>
|
|
||||||
<description>
|
|
||||||
Disable all extensions the user has enabled without affecting
|
|
||||||
the “enabled-extension” setting.
|
|
||||||
</description>
|
|
||||||
</key>
|
|
||||||
<key name="disable-extension-version-validation" type="b">
|
|
||||||
<default>false</default>
|
|
||||||
<summary>Disables the validation of extension version compatibility</summary>
|
|
||||||
--
|
|
||||||
2.35.1
|
|
||||||
|
|
@ -1,25 +1,25 @@
|
|||||||
From 1e699b55f3dc84b2ddbc5acd03424240eddbe06c Mon Sep 17 00:00:00 2001
|
From d15a92aeaa075230f711921f4bcd929c49bfc97d Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
Date: Thu, 9 Mar 2017 14:44:32 +0100
|
Date: Thu, 9 Mar 2017 14:44:32 +0100
|
||||||
Subject: [PATCH 3/3] appFavorites: Add terminal
|
Subject: [PATCH] appFavorites: Add terminal
|
||||||
|
|
||||||
---
|
---
|
||||||
data/org.gnome.shell.gschema.xml.in | 2 +-
|
data/org.gnome.shell.gschema.xml.in | 2 +-
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in
|
diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in
|
||||||
index 35ddaf4a9..d5ea1e35f 100644
|
index 40526187e..9d7e011fc 100644
|
||||||
--- a/data/org.gnome.shell.gschema.xml.in
|
--- a/data/org.gnome.shell.gschema.xml.in
|
||||||
+++ b/data/org.gnome.shell.gschema.xml.in
|
+++ b/data/org.gnome.shell.gschema.xml.in
|
||||||
@@ -50,7 +50,7 @@
|
@@ -39,7 +39,7 @@
|
||||||
</description>
|
</description>
|
||||||
</key>
|
</key>
|
||||||
<key name="favorite-apps" type="as">
|
<key name="favorite-apps" type="as">
|
||||||
- <default>[ 'firefox.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Music.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop', 'yelp.desktop' ]</default>
|
- <default>[ 'firefox.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop', 'yelp.desktop' ]</default>
|
||||||
+ <default>[ 'firefox.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Music.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop', 'yelp.desktop', 'org.gnome.Terminal.desktop' ]</default>
|
+ <default>[ 'firefox.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop', 'yelp.desktop', 'gnome-terminal.desktop' ]</default>
|
||||||
<summary>List of desktop file IDs for favorite applications</summary>
|
<summary>List of desktop file IDs for favorite applications</summary>
|
||||||
<description>
|
<description>
|
||||||
The applications corresponding to these identifiers
|
The applications corresponding to these identifiers
|
||||||
--
|
--
|
||||||
2.31.1
|
2.21.0
|
||||||
|
|
||||||
|
@ -0,0 +1,399 @@
|
|||||||
|
From b42dd3f87ad5fb6c7ee139cb0de22e0fbb393ba2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Tue, 4 Jun 2019 19:22:26 +0000
|
||||||
|
Subject: [PATCH 1/2] workspaceSwitcherPopup: Support horizontal layout
|
||||||
|
|
||||||
|
While mutter supports a variety of different grid layouts (n columns/rows,
|
||||||
|
growing vertically or horizontally from any of the four corners), we
|
||||||
|
hardcode a fixed vertical layout of a single column.
|
||||||
|
|
||||||
|
Now that mutter exposes the actual layout to us, add support for a more
|
||||||
|
traditional horizontal layout as well.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/575
|
||||||
|
---
|
||||||
|
data/theme/gnome-shell-sass/_common.scss | 3 +-
|
||||||
|
js/ui/windowManager.js | 36 ++++++++--
|
||||||
|
js/ui/workspaceSwitcherPopup.js | 86 ++++++++++++++++++------
|
||||||
|
3 files changed, 98 insertions(+), 27 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss
|
||||||
|
index 293ea2ab9..b1eeb0ce9 100644
|
||||||
|
--- a/data/theme/gnome-shell-sass/_common.scss
|
||||||
|
+++ b/data/theme/gnome-shell-sass/_common.scss
|
||||||
|
@@ -680,7 +680,8 @@ StScrollBar {
|
||||||
|
spacing: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
- .ws-switcher-active-up, .ws-switcher-active-down {
|
||||||
|
+ .ws-switcher-active-up, .ws-switcher-active-down,
|
||||||
|
+ .ws-switcher-active-left, .ws-switcher-active-right {
|
||||||
|
height: 50px;
|
||||||
|
background-color: $selected_bg_color;
|
||||||
|
color: $selected_fg_color;
|
||||||
|
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
|
||||||
|
index b9f5fef46..dfe1b4460 100644
|
||||||
|
--- a/js/ui/windowManager.js
|
||||||
|
+++ b/js/ui/windowManager.js
|
||||||
|
@@ -2145,6 +2145,8 @@ var WindowManager = class {
|
||||||
|
let [action,,,target] = binding.get_name().split('-');
|
||||||
|
let newWs;
|
||||||
|
let direction;
|
||||||
|
+ let vertical = workspaceManager.layout_rows == -1;
|
||||||
|
+ let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
|
||||||
|
|
||||||
|
if (action == 'move') {
|
||||||
|
// "Moving" a window to another workspace doesn't make sense when
|
||||||
|
@@ -2157,7 +2159,12 @@ var WindowManager = class {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target == 'last') {
|
||||||
|
- direction = Meta.MotionDirection.DOWN;
|
||||||
|
+ if (vertical)
|
||||||
|
+ direction = Meta.MotionDirection.DOWN;
|
||||||
|
+ else if (rtl)
|
||||||
|
+ direction = Meta.MotionDirection.LEFT;
|
||||||
|
+ else
|
||||||
|
+ direction = Meta.MotionDirection.RIGHT;
|
||||||
|
newWs = workspaceManager.get_workspace_by_index(workspaceManager.n_workspaces - 1);
|
||||||
|
} else if (isNaN(target)) {
|
||||||
|
// Prepend a new workspace dynamically
|
||||||
|
@@ -2173,16 +2180,33 @@ var WindowManager = class {
|
||||||
|
target--;
|
||||||
|
newWs = workspaceManager.get_workspace_by_index(target);
|
||||||
|
|
||||||
|
- if (workspaceManager.get_active_workspace().index() > target)
|
||||||
|
- direction = Meta.MotionDirection.UP;
|
||||||
|
- else
|
||||||
|
- direction = Meta.MotionDirection.DOWN;
|
||||||
|
+ if (workspaceManager.get_active_workspace().index() > target) {
|
||||||
|
+ if (vertical)
|
||||||
|
+ direction = Meta.MotionDirection.UP;
|
||||||
|
+ else if (rtl)
|
||||||
|
+ direction = Meta.MotionDirection.RIGHT;
|
||||||
|
+ else
|
||||||
|
+ direction = Meta.MotionDirection.LEFT;
|
||||||
|
+ } else {
|
||||||
|
+ if (vertical)
|
||||||
|
+ direction = Meta.MotionDirection.DOWN;
|
||||||
|
+ else if (rtl)
|
||||||
|
+ direction = Meta.MotionDirection.LEFT;
|
||||||
|
+ else
|
||||||
|
+ direction = Meta.MotionDirection.RIGHT;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (direction != Meta.MotionDirection.UP &&
|
||||||
|
+ if (workspaceManager.layout_rows == -1 &&
|
||||||
|
+ direction != Meta.MotionDirection.UP &&
|
||||||
|
direction != Meta.MotionDirection.DOWN)
|
||||||
|
return;
|
||||||
|
|
||||||
|
+ if (workspaceManager.layout_columns == -1 &&
|
||||||
|
+ direction != Meta.MotionDirection.LEFT &&
|
||||||
|
+ direction != Meta.MotionDirection.RIGHT)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
if (action == 'switch')
|
||||||
|
this.actionMoveWorkspace(newWs);
|
||||||
|
else
|
||||||
|
diff --git a/js/ui/workspaceSwitcherPopup.js b/js/ui/workspaceSwitcherPopup.js
|
||||||
|
index 26404eaab..d21c5de4d 100644
|
||||||
|
--- a/js/ui/workspaceSwitcherPopup.js
|
||||||
|
+++ b/js/ui/workspaceSwitcherPopup.js
|
||||||
|
@@ -17,41 +17,75 @@ class WorkspaceSwitcherPopupList extends St.Widget {
|
||||||
|
this._itemSpacing = 0;
|
||||||
|
this._childHeight = 0;
|
||||||
|
this._childWidth = 0;
|
||||||
|
+ this._orientation = global.workspace_manager.layout_rows == -1
|
||||||
|
+ ? Clutter.Orientation.VERTICAL
|
||||||
|
+ : Clutter.Orientation.HORIZONTAL;
|
||||||
|
|
||||||
|
this.connect('style-changed', () => {
|
||||||
|
this._itemSpacing = this.get_theme_node().get_length('spacing');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- vfunc_get_preferred_height(forWidth) {
|
||||||
|
+ _getPreferredSizeForOrientation(forSize) {
|
||||||
|
let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
|
||||||
|
let themeNode = this.get_theme_node();
|
||||||
|
|
||||||
|
- let availHeight = workArea.height;
|
||||||
|
- availHeight -= themeNode.get_vertical_padding();
|
||||||
|
+ let availSize;
|
||||||
|
+ if (this._orientation == Clutter.Orientation.HORIZONTAL)
|
||||||
|
+ availSize = workArea.width - themeNode.get_horizontal_padding();
|
||||||
|
+ else
|
||||||
|
+ availSize = workArea.height - themeNode.get_vertical_padding();
|
||||||
|
|
||||||
|
- let height = 0;
|
||||||
|
+ let size = 0;
|
||||||
|
for (let child of this.get_children()) {
|
||||||
|
let [childMinHeight, childNaturalHeight] = child.get_preferred_height(-1);
|
||||||
|
- let [childMinWidth, childNaturalWidth] = child.get_preferred_width(childNaturalHeight);
|
||||||
|
- height += childNaturalHeight * workArea.width / workArea.height;
|
||||||
|
+ let height = childNaturalHeight * workArea.width / workArea.height;
|
||||||
|
+
|
||||||
|
+ if (this._orientation == Clutter.Orientation.HORIZONTAL) {
|
||||||
|
+ size += height * workArea.width / workArea.height;
|
||||||
|
+ } else {
|
||||||
|
+ size += height;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
let workspaceManager = global.workspace_manager;
|
||||||
|
let spacing = this._itemSpacing * (workspaceManager.n_workspaces - 1);
|
||||||
|
- height += spacing;
|
||||||
|
- height = Math.min(height, availHeight);
|
||||||
|
+ size += spacing;
|
||||||
|
+ size = Math.min(size, availSize);
|
||||||
|
+
|
||||||
|
+ if (this._orientation == Clutter.Orientation.HORIZONTAL) {
|
||||||
|
+ this._childWidth = (size - spacing) / workspaceManager.n_workspaces;
|
||||||
|
+ return themeNode.adjust_preferred_width(size, size);
|
||||||
|
+ } else {
|
||||||
|
+ this._childHeight = (size - spacing) / workspaceManager.n_workspaces;
|
||||||
|
+ return themeNode.adjust_preferred_height(size, size);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ _getSizeForOppositeOrientation() {
|
||||||
|
+ let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
|
||||||
|
|
||||||
|
- this._childHeight = (height - spacing) / workspaceManager.n_workspaces;
|
||||||
|
+ if (this._orientation == Clutter.Orientation.HORIZONTAL) {
|
||||||
|
+ this._childHeight = Math.round(this._childWidth * workArea.height / workArea.width);
|
||||||
|
+ return [this._childHeight, this._childHeight];
|
||||||
|
+ } else {
|
||||||
|
+ this._childWidth = Math.round(this._childHeight * workArea.width / workArea.height);
|
||||||
|
+ return [this._childWidth, this._childWidth];
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- return themeNode.adjust_preferred_height(height, height);
|
||||||
|
+ vfunc_get_preferred_height(forWidth) {
|
||||||
|
+ if (this._orientation == Clutter.Orientation.HORIZONTAL)
|
||||||
|
+ return this._getSizeForOppositeOrientation();
|
||||||
|
+ else
|
||||||
|
+ return this._getPreferredSizeForOrientation(forWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
vfunc_get_preferred_width(forHeight) {
|
||||||
|
- let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
|
||||||
|
- this._childWidth = Math.round(this._childHeight * workArea.width / workArea.height);
|
||||||
|
-
|
||||||
|
- return [this._childWidth, this._childWidth];
|
||||||
|
+ if (this._orientation == Clutter.Orientation.HORIZONTAL)
|
||||||
|
+ return this._getPreferredSizeForOrientation(forHeight);
|
||||||
|
+ else
|
||||||
|
+ return this._getSizeForOppositeOrientation();
|
||||||
|
}
|
||||||
|
|
||||||
|
vfunc_allocate(box, flags) {
|
||||||
|
@@ -62,15 +96,23 @@ class WorkspaceSwitcherPopupList extends St.Widget {
|
||||||
|
|
||||||
|
let childBox = new Clutter.ActorBox();
|
||||||
|
|
||||||
|
+ let rtl = this.text_direction == Clutter.TextDirection.RTL;
|
||||||
|
+ let x = rtl ? box.x2 - this._childWidth : box.x1;
|
||||||
|
let y = box.y1;
|
||||||
|
- let prevChildBoxY2 = box.y1 - this._itemSpacing;
|
||||||
|
for (let child of this.get_children()) {
|
||||||
|
- childBox.x1 = box.x1;
|
||||||
|
- childBox.x2 = box.x1 + this._childWidth;
|
||||||
|
- childBox.y1 = prevChildBoxY2 + this._itemSpacing;
|
||||||
|
+ childBox.x1 = Math.round(x);
|
||||||
|
+ childBox.x2 = Math.round(x + this._childWidth);
|
||||||
|
+ childBox.y1 = Math.round(y);
|
||||||
|
childBox.y2 = Math.round(y + this._childHeight);
|
||||||
|
- y += this._childHeight + this._itemSpacing;
|
||||||
|
- prevChildBoxY2 = childBox.y2;
|
||||||
|
+
|
||||||
|
+ if (this._orientation == Clutter.Orientation.HORIZONTAL) {
|
||||||
|
+ if (rtl)
|
||||||
|
+ x -= this._childWidth + this._itemSpacing;
|
||||||
|
+ else
|
||||||
|
+ x += this._childWidth + this._itemSpacing;
|
||||||
|
+ } else {
|
||||||
|
+ y += this._childHeight + this._itemSpacing;
|
||||||
|
+ }
|
||||||
|
child.allocate(childBox, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -123,6 +165,10 @@ class WorkspaceSwitcherPopup extends St.Widget {
|
||||||
|
indicator = new St.Bin({ style_class: 'ws-switcher-active-up' });
|
||||||
|
else if(i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.DOWN)
|
||||||
|
indicator = new St.Bin({ style_class: 'ws-switcher-active-down' });
|
||||||
|
+ else if(i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.LEFT)
|
||||||
|
+ indicator = new St.Bin({ style_class: 'ws-switcher-active-left' });
|
||||||
|
+ else if(i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.RIGHT)
|
||||||
|
+ indicator = new St.Bin({ style_class: 'ws-switcher-active-right' });
|
||||||
|
else
|
||||||
|
indicator = new St.Bin({ style_class: 'ws-switcher-box' });
|
||||||
|
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
||||||
|
|
||||||
|
From 813976ff69b15ab884d44f5f6a56ae66f407acfd Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Tue, 4 Jun 2019 19:49:23 +0000
|
||||||
|
Subject: [PATCH 2/2] workspacesView: Support horizontal layout
|
||||||
|
|
||||||
|
Just as we did for the workspace switcher popup, support workspaces
|
||||||
|
being laid out in a single row in the window picker.
|
||||||
|
|
||||||
|
Note that this takes care of the various workspace switch actions in
|
||||||
|
the overview (scrolling, panning, touch(pad) gestures) as well as the
|
||||||
|
switch animation, but not of the overview's workspace switcher component.
|
||||||
|
|
||||||
|
There are currently no plans to support other layouts there, as the
|
||||||
|
component is inherently vertical (in fact, it was the whole reason for
|
||||||
|
switching the layout in the first place).
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/575
|
||||||
|
---
|
||||||
|
js/ui/workspacesView.js | 81 ++++++++++++++++++++++++++++++-----------
|
||||||
|
1 file changed, 60 insertions(+), 21 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js
|
||||||
|
index fe06d9dae..069937d5a 100644
|
||||||
|
--- a/js/ui/workspacesView.js
|
||||||
|
+++ b/js/ui/workspacesView.js
|
||||||
|
@@ -181,26 +181,32 @@ var WorkspacesView = class extends WorkspacesViewBase {
|
||||||
|
|
||||||
|
Tweener.removeTweens(workspace.actor);
|
||||||
|
|
||||||
|
- let y = (w - active) * this._fullGeometry.height;
|
||||||
|
+ let params = {};
|
||||||
|
+ if (workspaceManager.layout_rows == -1)
|
||||||
|
+ params.y = (w - active) * this._fullGeometry.height;
|
||||||
|
+ else if (this.actor.text_direction == Clutter.TextDirection.RTL)
|
||||||
|
+ params.x = (active - w) * this._fullGeometry.width;
|
||||||
|
+ else
|
||||||
|
+ params.x = (w - active) * this._fullGeometry.width;
|
||||||
|
|
||||||
|
if (showAnimation) {
|
||||||
|
- let params = { y: y,
|
||||||
|
- time: WORKSPACE_SWITCH_TIME,
|
||||||
|
- transition: 'easeOutQuad'
|
||||||
|
- };
|
||||||
|
+ let tweenParams = Object.assign(params, {
|
||||||
|
+ time: WORKSPACE_SWITCH_TIME,
|
||||||
|
+ transition: 'easeOutQuad'
|
||||||
|
+ });
|
||||||
|
// we have to call _updateVisibility() once before the
|
||||||
|
// animation and once afterwards - it does not really
|
||||||
|
// matter which tween we use, so we pick the first one ...
|
||||||
|
if (w == 0) {
|
||||||
|
this._updateVisibility();
|
||||||
|
- params.onComplete = () => {
|
||||||
|
+ tweenParams.onComplete = () => {
|
||||||
|
this._animating = false;
|
||||||
|
this._updateVisibility();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
- Tweener.addTween(workspace.actor, params);
|
||||||
|
+ Tweener.addTween(workspace.actor, tweenParams);
|
||||||
|
} else {
|
||||||
|
- workspace.actor.set_position(0, y);
|
||||||
|
+ workspace.actor.set(params);
|
||||||
|
if (w == 0)
|
||||||
|
this._updateVisibility();
|
||||||
|
}
|
||||||
|
@@ -338,22 +344,39 @@ var WorkspacesView = class extends WorkspacesViewBase {
|
||||||
|
metaWorkspace.activate(global.get_current_time());
|
||||||
|
}
|
||||||
|
|
||||||
|
- let last = this._workspaces.length - 1;
|
||||||
|
- let firstWorkspaceY = this._workspaces[0].actor.y;
|
||||||
|
- let lastWorkspaceY = this._workspaces[last].actor.y;
|
||||||
|
- let workspacesHeight = lastWorkspaceY - firstWorkspaceY;
|
||||||
|
-
|
||||||
|
if (adj.upper == 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
- let currentY = firstWorkspaceY;
|
||||||
|
- let newY = - adj.value / (adj.upper - 1) * workspacesHeight;
|
||||||
|
+ let last = this._workspaces.length - 1;
|
||||||
|
+
|
||||||
|
+ if (workspaceManager.layout_rows == -1) {
|
||||||
|
+ let firstWorkspaceY = this._workspaces[0].actor.y;
|
||||||
|
+ let lastWorkspaceY = this._workspaces[last].actor.y;
|
||||||
|
+ let workspacesHeight = lastWorkspaceY - firstWorkspaceY;
|
||||||
|
+
|
||||||
|
+ let currentY = firstWorkspaceY;
|
||||||
|
+ let newY = -adj.value / (adj.upper - 1) * workspacesHeight;
|
||||||
|
|
||||||
|
- let dy = newY - currentY;
|
||||||
|
+ let dy = newY - currentY;
|
||||||
|
+
|
||||||
|
+ for (let i = 0; i < this._workspaces.length; i++) {
|
||||||
|
+ this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1;
|
||||||
|
+ this._workspaces[i].actor.y += dy;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ let firstWorkspaceX = this._workspaces[0].actor.x;
|
||||||
|
+ let lastWorkspaceX = this._workspaces[last].actor.x;
|
||||||
|
+ let workspacesWidth = lastWorkspaceX - firstWorkspaceX;
|
||||||
|
|
||||||
|
- for (let i = 0; i < this._workspaces.length; i++) {
|
||||||
|
- this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1;
|
||||||
|
- this._workspaces[i].actor.y += dy;
|
||||||
|
+ let currentX = firstWorkspaceX;
|
||||||
|
+ let newX = -adj.value / (adj.upper - 1) * workspacesWidth;
|
||||||
|
+
|
||||||
|
+ let dx = newX - currentX;
|
||||||
|
+
|
||||||
|
+ for (let i = 0; i < this._workspaces.length; i++) {
|
||||||
|
+ this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1;
|
||||||
|
+ this._workspaces[i].actor.x += dx;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@@ -504,7 +527,12 @@ var WorkspacesDisplay = class {
|
||||||
|
_onPan(action) {
|
||||||
|
let [dist, dx, dy] = action.get_motion_delta(0);
|
||||||
|
let adjustment = this._scrollAdjustment;
|
||||||
|
- adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
|
||||||
|
+ if (global.workspace_manager.layout_rows == -1)
|
||||||
|
+ adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
|
||||||
|
+ else if (this.actor.text_direction == Clutter.TextDirection.RTL)
|
||||||
|
+ adjustment.value += (dx / this.actor.width) * adjustment.page_size;
|
||||||
|
+ else
|
||||||
|
+ adjustment.value -= (dx / this.actor.width) * adjustment.page_size;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -536,7 +564,12 @@ var WorkspacesDisplay = class {
|
||||||
|
let workspaceManager = global.workspace_manager;
|
||||||
|
let active = workspaceManager.get_active_workspace_index();
|
||||||
|
let adjustment = this._scrollAdjustment;
|
||||||
|
- adjustment.value = (active - yRel / this.actor.height) * adjustment.page_size;
|
||||||
|
+ if (workspaceManager.layout_rows == -1)
|
||||||
|
+ adjustment.value = (active - yRel / this.actor.height) * adjustment.page_size;
|
||||||
|
+ else if (this.actor.text_direction == Clutter.TextDirection.RTL)
|
||||||
|
+ adjustment.value = (active + xRel / this.actor.width) * adjustment.page_size;
|
||||||
|
+ else
|
||||||
|
+ adjustment.value = (active - xRel / this.actor.width) * adjustment.page_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
_onSwitchWorkspaceActivated(action, direction) {
|
||||||
|
@@ -755,6 +788,12 @@ var WorkspacesDisplay = class {
|
||||||
|
case Clutter.ScrollDirection.DOWN:
|
||||||
|
ws = activeWs.get_neighbor(Meta.MotionDirection.DOWN);
|
||||||
|
break;
|
||||||
|
+ case Clutter.ScrollDirection.LEFT:
|
||||||
|
+ ws = activeWs.get_neighbor(Meta.MotionDirection.LEFT);
|
||||||
|
+ break;
|
||||||
|
+ case Clutter.ScrollDirection.RIGHT:
|
||||||
|
+ ws = activeWs.get_neighbor(Meta.MotionDirection.RIGHT);
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -0,0 +1,643 @@
|
|||||||
|
From 781dfcf6ce7168c6b116d58df5f1c67291a7b513 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Thu, 16 May 2019 00:57:27 +0200
|
||||||
|
Subject: [PATCH 01/11] introspect: Include `sandboxed-app-id` as well
|
||||||
|
|
||||||
|
App IDs in gnome-shell don't match AppStream, Flatpak or Snap IDs. For the
|
||||||
|
desktop portal, the latter two are more relevant, so include it in the
|
||||||
|
returned information.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1289
|
||||||
|
---
|
||||||
|
js/misc/introspect.js | 14 ++++++++++++++
|
||||||
|
1 file changed, 14 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
|
||||||
|
index f7a7f2fe6..1e8300d0a 100644
|
||||||
|
--- a/js/misc/introspect.js
|
||||||
|
+++ b/js/misc/introspect.js
|
||||||
|
@@ -55,6 +55,11 @@ var IntrospectService = class {
|
||||||
|
return APP_WHITELIST.includes(sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ _getSandboxedAppId(app) {
|
||||||
|
+ let ids = app.get_windows().map(w => w.get_sandboxed_app_id());
|
||||||
|
+ return ids.find(id => id != null);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
_syncRunningApplications() {
|
||||||
|
let tracker = Shell.WindowTracker.get_default();
|
||||||
|
let apps = this._appSystem.get_running();
|
||||||
|
@@ -76,6 +81,10 @@ var IntrospectService = class {
|
||||||
|
newActiveApplication = app.get_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ let sandboxedAppId = this._getSandboxedAppId(app);
|
||||||
|
+ if (sandboxedAppId)
|
||||||
|
+ appInfo['sandboxed-app-id'] = new GLib.Variant('s', sandboxedAppId);
|
||||||
|
+
|
||||||
|
newRunningApplications[app.get_id()] = appInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -137,6 +146,7 @@ var IntrospectService = class {
|
||||||
|
let frameRect = window.get_frame_rect();
|
||||||
|
let title = window.get_title();
|
||||||
|
let wmClass = window.get_wm_class();
|
||||||
|
+ let sandboxedAppId = window.get_sandboxed_app_id();
|
||||||
|
|
||||||
|
windowsList[windowId] = {
|
||||||
|
'app-id': GLib.Variant.new('s', app.get_id()),
|
||||||
|
@@ -153,6 +163,10 @@ var IntrospectService = class {
|
||||||
|
|
||||||
|
if (wmClass != null)
|
||||||
|
windowsList[windowId]['wm-class'] = GLib.Variant.new('s', wmClass);
|
||||||
|
+
|
||||||
|
+ if (sandboxedAppId != null)
|
||||||
|
+ windowsList[windowId]['sandboxed-app-id'] =
|
||||||
|
+ GLib.Variant.new('s', sandboxedAppId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList]));
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
||||||
|
|
||||||
|
From b0b4fb82c058722e2171d24902ba3855ffe243f3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||||||
|
Date: Wed, 18 Sep 2019 14:57:48 +0200
|
||||||
|
Subject: [PATCH 02/11] introspect: Check whitelist also for
|
||||||
|
GetRunningWindows()
|
||||||
|
|
||||||
|
Otherwise the xdg-desktop-portal-gtk screen cast widget won't work.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/732
|
||||||
|
---
|
||||||
|
js/misc/introspect.js | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
|
||||||
|
index 1e8300d0a..cee6409a8 100644
|
||||||
|
--- a/js/misc/introspect.js
|
||||||
|
+++ b/js/misc/introspect.js
|
||||||
|
@@ -128,7 +128,8 @@ var IntrospectService = class {
|
||||||
|
let apps = this._appSystem.get_running();
|
||||||
|
let windowsList = {};
|
||||||
|
|
||||||
|
- if (!this._isIntrospectEnabled()) {
|
||||||
|
+ if (!this._isIntrospectEnabled() &&
|
||||||
|
+ !this._isSenderWhitelisted(invocation.get_sender())) {
|
||||||
|
invocation.return_error_literal(Gio.DBusError,
|
||||||
|
Gio.DBusError.ACCESS_DENIED,
|
||||||
|
'App introspection not allowed');
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
||||||
|
|
||||||
|
From 23556e03db3743ddf478a3c1bbb64946c687afdf Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
||||||
|
Date: Mon, 25 Nov 2019 19:44:10 +0100
|
||||||
|
Subject: [PATCH 03/11] introspect: Fix whitelist check
|
||||||
|
|
||||||
|
The whitelist is a list of well-known D-Bus names, which we then search
|
||||||
|
for the unique name we get from the method invocation - unsuccesfully.
|
||||||
|
|
||||||
|
Fix this by watching the bus for any name in the whitelist in order
|
||||||
|
to maintain a map from wel-known to unique name that we can use for
|
||||||
|
matching.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1916
|
||||||
|
---
|
||||||
|
js/misc/introspect.js | 11 ++++++++++-
|
||||||
|
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
|
||||||
|
index cee6409a8..f14eabfad 100644
|
||||||
|
--- a/js/misc/introspect.js
|
||||||
|
+++ b/js/misc/introspect.js
|
||||||
|
@@ -39,6 +39,15 @@ var IntrospectService = class {
|
||||||
|
});
|
||||||
|
|
||||||
|
this._syncRunningApplications();
|
||||||
|
+
|
||||||
|
+ this._whitelistMap = new Map();
|
||||||
|
+ APP_WHITELIST.forEach(appName => {
|
||||||
|
+ Gio.DBus.watch_name(Gio.BusType.SESSION,
|
||||||
|
+ appName,
|
||||||
|
+ Gio.BusNameWatcherFlags.NONE,
|
||||||
|
+ (conn, name, owner) => this._whitelistMap.set(name, owner),
|
||||||
|
+ (conn, name) => this._whitelistMap.delete(name));
|
||||||
|
+ });
|
||||||
|
}
|
||||||
|
|
||||||
|
_isStandaloneApp(app) {
|
||||||
|
@@ -52,7 +61,7 @@ var IntrospectService = class {
|
||||||
|
}
|
||||||
|
|
||||||
|
_isSenderWhitelisted(sender) {
|
||||||
|
- return APP_WHITELIST.includes(sender);
|
||||||
|
+ return [...this._whitelistMap.values()].includes(sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getSandboxedAppId(app) {
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
||||||
|
|
||||||
|
From 1a6275add6d214df958ed8a06c097445bef021bc Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||||||
|
Date: Wed, 25 Sep 2019 20:36:28 +0200
|
||||||
|
Subject: [PATCH 04/11] introspect: Add helper to check method call permission
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
|
||||||
|
---
|
||||||
|
js/misc/introspect.js | 16 ++++++++++++----
|
||||||
|
1 file changed, 12 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
|
||||||
|
index f14eabfad..6186754cd 100644
|
||||||
|
--- a/js/misc/introspect.js
|
||||||
|
+++ b/js/misc/introspect.js
|
||||||
|
@@ -120,9 +120,18 @@ var IntrospectService = class {
|
||||||
|
type == Meta.WindowType.UTILITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ _isInvocationAllowed(invocation) {
|
||||||
|
+ if (this._isIntrospectEnabled())
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ if (this._isSenderWhitelisted(invocation.get_sender()))
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
GetRunningApplicationsAsync(params, invocation) {
|
||||||
|
- if (!this._isIntrospectEnabled() &&
|
||||||
|
- !this._isSenderWhitelisted(invocation.get_sender())) {
|
||||||
|
+ if (!this._isInvocationAllowed(invocation)) {
|
||||||
|
invocation.return_error_literal(Gio.DBusError,
|
||||||
|
Gio.DBusError.ACCESS_DENIED,
|
||||||
|
'App introspection not allowed');
|
||||||
|
@@ -137,8 +146,7 @@ var IntrospectService = class {
|
||||||
|
let apps = this._appSystem.get_running();
|
||||||
|
let windowsList = {};
|
||||||
|
|
||||||
|
- if (!this._isIntrospectEnabled() &&
|
||||||
|
- !this._isSenderWhitelisted(invocation.get_sender())) {
|
||||||
|
+ if (!this._isInvocationAllowed(invocation)) {
|
||||||
|
invocation.return_error_literal(Gio.DBusError,
|
||||||
|
Gio.DBusError.ACCESS_DENIED,
|
||||||
|
'App introspection not allowed');
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
||||||
|
|
||||||
|
From f578dc01cf774faa4504a4d258cc0e82060d988b Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||||||
|
Date: Tue, 1 Oct 2019 11:55:33 +0200
|
||||||
|
Subject: [PATCH 05/11] shell-util: Add API to check for X11 extensions
|
||||||
|
|
||||||
|
Will be used to disable animations when running inside Xvnc. This was
|
||||||
|
done in gsd-xsettings before.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
|
||||||
|
---
|
||||||
|
src/shell-util.c | 26 ++++++++++++++++++++++++++
|
||||||
|
src/shell-util.h | 3 +++
|
||||||
|
2 files changed, 29 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/shell-util.c b/src/shell-util.c
|
||||||
|
index 31bb18e70..fa3fc08c8 100644
|
||||||
|
--- a/src/shell-util.c
|
||||||
|
+++ b/src/shell-util.c
|
||||||
|
@@ -21,6 +21,8 @@
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
#include <meta/meta-shaped-texture.h>
|
||||||
|
+#include <meta/display.h>
|
||||||
|
+#include <meta/meta-x11-display.h>
|
||||||
|
|
||||||
|
#include <locale.h>
|
||||||
|
#ifdef HAVE__NL_TIME_FIRST_WEEKDAY
|
||||||
|
@@ -613,3 +615,27 @@ shell_util_check_cloexec_fds (void)
|
||||||
|
fdwalk (check_cloexec, NULL);
|
||||||
|
g_info ("Open fd CLOEXEC check complete");
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * shell_util_has_x11_display_extension:
|
||||||
|
+ * @display: A #MetaDisplay
|
||||||
|
+ * @extension: An X11 extension
|
||||||
|
+ *
|
||||||
|
+ * If the corresponding X11 display provides the passed extension, return %TRUE,
|
||||||
|
+ * otherwise %FALSE. If there is no X11 display, %FALSE is passed.
|
||||||
|
+ */
|
||||||
|
+gboolean
|
||||||
|
+shell_util_has_x11_display_extension (MetaDisplay *display,
|
||||||
|
+ const char *extension)
|
||||||
|
+{
|
||||||
|
+ MetaX11Display *x11_display;
|
||||||
|
+ Display *xdisplay;
|
||||||
|
+ int op, event, error;
|
||||||
|
+
|
||||||
|
+ x11_display = meta_display_get_x11_display (display);
|
||||||
|
+ if (!x11_display)
|
||||||
|
+ return FALSE;
|
||||||
|
+
|
||||||
|
+ xdisplay = meta_x11_display_get_xdisplay (x11_display);
|
||||||
|
+ return XQueryExtension (xdisplay, extension, &op, &event, &error);
|
||||||
|
+}
|
||||||
|
diff --git a/src/shell-util.h b/src/shell-util.h
|
||||||
|
index 6904f43bc..02b8404e9 100644
|
||||||
|
--- a/src/shell-util.h
|
||||||
|
+++ b/src/shell-util.h
|
||||||
|
@@ -59,6 +59,9 @@ cairo_surface_t * shell_util_composite_capture_images (ClutterCapture *captures
|
||||||
|
|
||||||
|
void shell_util_check_cloexec_fds (void);
|
||||||
|
|
||||||
|
+gboolean shell_util_has_x11_display_extension (MetaDisplay *display,
|
||||||
|
+ const char *extension);
|
||||||
|
+
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __SHELL_UTIL_H__ */
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
||||||
|
|
||||||
|
From 48ee79bb7b48c7e93e77e35629f21bbdbabc253f Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||||||
|
Date: Tue, 1 Oct 2019 11:56:34 +0200
|
||||||
|
Subject: [PATCH 06/11] st/settings: Add API to inhibit animations
|
||||||
|
|
||||||
|
There may be situations where we shouldn't enable animations. Make it
|
||||||
|
possible for the Shell to decide when there are such situations and in
|
||||||
|
when needed inhibit animations.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
|
||||||
|
---
|
||||||
|
src/st/st-settings.c | 38 +++++++++++++++++++++++++++++++++++++-
|
||||||
|
src/st/st-settings.h | 4 ++++
|
||||||
|
2 files changed, 41 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/st/st-settings.c b/src/st/st-settings.c
|
||||||
|
index 17f2c466e..ebfd28480 100644
|
||||||
|
--- a/src/st/st-settings.c
|
||||||
|
+++ b/src/st/st-settings.c
|
||||||
|
@@ -54,6 +54,7 @@ struct _StSettings
|
||||||
|
|
||||||
|
gchar *gtk_theme;
|
||||||
|
gchar *gtk_icon_theme;
|
||||||
|
+ int inhibit_animations_count;
|
||||||
|
gboolean enable_animations;
|
||||||
|
gboolean primary_paste;
|
||||||
|
gboolean magnifier_active;
|
||||||
|
@@ -62,6 +63,41 @@ struct _StSettings
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (StSettings, st_settings, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
+static gboolean
|
||||||
|
+get_enable_animations (StSettings *settings)
|
||||||
|
+{
|
||||||
|
+ if (settings->inhibit_animations_count > 0)
|
||||||
|
+ return FALSE;
|
||||||
|
+ else
|
||||||
|
+ return settings->enable_animations;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+st_settings_inhibit_animations (StSettings *settings)
|
||||||
|
+{
|
||||||
|
+ gboolean enable_animations;
|
||||||
|
+
|
||||||
|
+ enable_animations = get_enable_animations (settings);
|
||||||
|
+ settings->inhibit_animations_count++;
|
||||||
|
+
|
||||||
|
+ if (enable_animations != get_enable_animations (settings))
|
||||||
|
+ g_object_notify_by_pspec (G_OBJECT (settings),
|
||||||
|
+ props[PROP_ENABLE_ANIMATIONS]);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+st_settings_uninhibit_animations (StSettings *settings)
|
||||||
|
+{
|
||||||
|
+ gboolean enable_animations;
|
||||||
|
+
|
||||||
|
+ enable_animations = get_enable_animations (settings);
|
||||||
|
+ settings->inhibit_animations_count--;
|
||||||
|
+
|
||||||
|
+ if (enable_animations != get_enable_animations (settings))
|
||||||
|
+ g_object_notify_by_pspec (G_OBJECT (settings),
|
||||||
|
+ props[PROP_ENABLE_ANIMATIONS]);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
st_settings_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
@@ -95,7 +131,7 @@ st_settings_get_property (GObject *object,
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_ENABLE_ANIMATIONS:
|
||||||
|
- g_value_set_boolean (value, settings->enable_animations);
|
||||||
|
+ g_value_set_boolean (value, get_enable_animations (settings));
|
||||||
|
break;
|
||||||
|
case PROP_PRIMARY_PASTE:
|
||||||
|
g_value_set_boolean (value, settings->primary_paste);
|
||||||
|
diff --git a/src/st/st-settings.h b/src/st/st-settings.h
|
||||||
|
index c2c4fa23e..8b2549469 100644
|
||||||
|
--- a/src/st/st-settings.h
|
||||||
|
+++ b/src/st/st-settings.h
|
||||||
|
@@ -33,6 +33,10 @@ G_DECLARE_FINAL_TYPE (StSettings, st_settings, ST, SETTINGS, GObject)
|
||||||
|
|
||||||
|
StSettings * st_settings_get (void);
|
||||||
|
|
||||||
|
+void st_settings_inhibit_animations (StSettings *settings);
|
||||||
|
+
|
||||||
|
+void st_settings_uninhibit_animations (StSettings *settings);
|
||||||
|
+
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __ST_SETTINGS_H__ */
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
||||||
|
|
||||||
|
From 80025388c44296b629c8f24ea673d77ffc4efc67 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||||||
|
Date: Tue, 1 Oct 2019 12:02:31 +0200
|
||||||
|
Subject: [PATCH 07/11] main: Inhibit animations when software rendered
|
||||||
|
|
||||||
|
This was previously decided by gsd-xsettings.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
|
||||||
|
---
|
||||||
|
js/ui/main.js | 12 ++++++++++++
|
||||||
|
1 file changed, 12 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/js/ui/main.js b/js/ui/main.js
|
||||||
|
index 978f83c3f..c3230ff03 100644
|
||||||
|
--- a/js/ui/main.js
|
||||||
|
+++ b/js/ui/main.js
|
||||||
|
@@ -147,6 +147,8 @@ function _initializeUI() {
|
||||||
|
_loadOskLayouts();
|
||||||
|
_loadDefaultStylesheet();
|
||||||
|
|
||||||
|
+ new AnimationsSettings();
|
||||||
|
+
|
||||||
|
// Setup the stage hierarchy early
|
||||||
|
layoutManager = new Layout.LayoutManager();
|
||||||
|
|
||||||
|
@@ -723,3 +725,13 @@ function showRestartMessage(message) {
|
||||||
|
let restartMessage = new RestartMessage(message);
|
||||||
|
restartMessage.open();
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+var AnimationsSettings = class {
|
||||||
|
+ constructor() {
|
||||||
|
+ let backend = Meta.get_backend();
|
||||||
|
+ if (!backend.is_rendering_hardware_accelerated()) {
|
||||||
|
+ St.Settings.get().inhibit_animations();
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+};
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
||||||
|
|
||||||
|
From 788ecb60e35d8a369f0747813f37e8b1ca27cb87 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||||||
|
Date: Tue, 1 Oct 2019 12:03:52 +0200
|
||||||
|
Subject: [PATCH 08/11] main: Inhibit animations if X server advertises
|
||||||
|
VNC-EXTENSION
|
||||||
|
|
||||||
|
This was previously done by gsd-xsettings to disable animations when
|
||||||
|
running in Xvnc.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
|
||||||
|
---
|
||||||
|
js/ui/main.js | 7 +++++++
|
||||||
|
1 file changed, 7 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/js/ui/main.js b/js/ui/main.js
|
||||||
|
index c3230ff03..ae7c3ffd0 100644
|
||||||
|
--- a/js/ui/main.js
|
||||||
|
+++ b/js/ui/main.js
|
||||||
|
@@ -733,5 +733,12 @@ var AnimationsSettings = class {
|
||||||
|
St.Settings.get().inhibit_animations();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ let isXvnc = Shell.util_has_x11_display_extension(
|
||||||
|
+ global.display, 'VNC-EXTENSION');
|
||||||
|
+ if (isXvnc) {
|
||||||
|
+ St.Settings.get().inhibit_animations();
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
||||||
|
|
||||||
|
From 1da5a7ce4cf0b95b96dd50b62ac6c1380fd88cb1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||||||
|
Date: Tue, 1 Oct 2019 12:04:52 +0200
|
||||||
|
Subject: [PATCH 09/11] main: Inhibit animations when there is a remote desktop
|
||||||
|
session
|
||||||
|
|
||||||
|
If a remote desktop session asks for animations to be disabled, inhibit
|
||||||
|
animations while the session is active.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
|
||||||
|
---
|
||||||
|
js/ui/main.js | 26 ++++++++++++++++++++++++++
|
||||||
|
1 file changed, 26 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/js/ui/main.js b/js/ui/main.js
|
||||||
|
index ae7c3ffd0..1203b3c39 100644
|
||||||
|
--- a/js/ui/main.js
|
||||||
|
+++ b/js/ui/main.js
|
||||||
|
@@ -740,5 +740,31 @@ var AnimationsSettings = class {
|
||||||
|
St.Settings.get().inhibit_animations();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ let remoteAccessController = backend.get_remote_access_controller();
|
||||||
|
+ if (!remoteAccessController)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ this._handles = new Set();
|
||||||
|
+ remoteAccessController.connect('new-handle',
|
||||||
|
+ (_, handle) => this._onNewRemoteAccessHandle(handle));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ _onRemoteAccessHandleStopped(handle) {
|
||||||
|
+ let settings = St.Settings.get();
|
||||||
|
+
|
||||||
|
+ settings.uninhibit_animations();
|
||||||
|
+ this._handles.delete(handle);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ _onNewRemoteAccessHandle(handle) {
|
||||||
|
+ if (!handle.get_disable_animations())
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ let settings = St.Settings.get();
|
||||||
|
+
|
||||||
|
+ settings.inhibit_animations();
|
||||||
|
+ this._handles.add(handle);
|
||||||
|
+ handle.connect('stopped', this._onRemoteAccessHandleStopped.bind(this));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
||||||
|
|
||||||
|
From ebfd46341a2d7a6338386e4be4a2807a6bc6e63c Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||||||
|
Date: Tue, 1 Oct 2019 12:06:13 +0200
|
||||||
|
Subject: [PATCH 10/11] introspect: Rename variable
|
||||||
|
|
||||||
|
It was too generic, and would conflict with a StSettings variable.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
|
||||||
|
---
|
||||||
|
js/misc/introspect.js | 6 ++++--
|
||||||
|
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
|
||||||
|
index 6186754cd..8e68a7e4f 100644
|
||||||
|
--- a/js/misc/introspect.js
|
||||||
|
+++ b/js/misc/introspect.js
|
||||||
|
@@ -29,7 +29,9 @@ var IntrospectService = class {
|
||||||
|
this._syncRunningApplications();
|
||||||
|
});
|
||||||
|
|
||||||
|
- this._settings = new Gio.Settings({ schema_id: INTROSPECT_SCHEMA });
|
||||||
|
+ this._introspectSettings = new Gio.Settings({
|
||||||
|
+ schema_id: INTROSPECT_SCHEMA,
|
||||||
|
+ });
|
||||||
|
|
||||||
|
let tracker = Shell.WindowTracker.get_default();
|
||||||
|
tracker.connect('notify::focus-app',
|
||||||
|
@@ -57,7 +59,7 @@ var IntrospectService = class {
|
||||||
|
}
|
||||||
|
|
||||||
|
_isIntrospectEnabled() {
|
||||||
|
- return this._settings.get_boolean(INTROSPECT_KEY);
|
||||||
|
+ return this._introspectSettings.get_boolean(INTROSPECT_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
_isSenderWhitelisted(sender) {
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
||||||
|
|
||||||
|
From 343e7792fc84c296b331c3fcb142ed79d2ce9bd5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||||||
|
Date: Tue, 1 Oct 2019 12:07:03 +0200
|
||||||
|
Subject: [PATCH 11/11] introspect: Add AnimationsEnabled property
|
||||||
|
|
||||||
|
While the gsetting is available for all who needs it, the Shell might
|
||||||
|
override it given various hueristics. Expose the decision made by the
|
||||||
|
Shell via a new property.
|
||||||
|
|
||||||
|
Intended to be used by gsd-xsettings as well as xdg-desktop-portal-gtk.
|
||||||
|
|
||||||
|
This also add a version property to the API, so that semi external
|
||||||
|
services (xdg-desktop-portal-gtk) can detect what API is expected to be
|
||||||
|
present.
|
||||||
|
|
||||||
|
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
|
||||||
|
---
|
||||||
|
.../org.gnome.Shell.Introspect.xml | 14 ++++++++++
|
||||||
|
js/misc/introspect.js | 27 ++++++++++++++++++-
|
||||||
|
2 files changed, 40 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/data/dbus-interfaces/org.gnome.Shell.Introspect.xml b/data/dbus-interfaces/org.gnome.Shell.Introspect.xml
|
||||||
|
index 9508681af..d71f2414b 100644
|
||||||
|
--- a/data/dbus-interfaces/org.gnome.Shell.Introspect.xml
|
||||||
|
+++ b/data/dbus-interfaces/org.gnome.Shell.Introspect.xml
|
||||||
|
@@ -57,5 +57,19 @@
|
||||||
|
<method name="GetWindows">
|
||||||
|
<arg name="windows" direction="out" type="a{ta{sv}}" />
|
||||||
|
</method>
|
||||||
|
+
|
||||||
|
+ <!--
|
||||||
|
+ AnimationsEnabled:
|
||||||
|
+ @short_description: Whether the shell animations are enabled
|
||||||
|
+
|
||||||
|
+ By default determined by the org.gnome.desktop.interface enable-animations
|
||||||
|
+ gsetting, but may be overridden, e.g. if there is an active screen cast or
|
||||||
|
+ remote desktop session that asked for animations to be disabled.
|
||||||
|
+
|
||||||
|
+ Since: 2
|
||||||
|
+ -->
|
||||||
|
+ <property name="AnimationsEnabled" type="b" access="read"/>
|
||||||
|
+
|
||||||
|
+ <property name="version" type="u" access="read"/>
|
||||||
|
</interface>
|
||||||
|
</node>
|
||||||
|
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
|
||||||
|
index 8e68a7e4f..7c62113e5 100644
|
||||||
|
--- a/js/misc/introspect.js
|
||||||
|
+++ b/js/misc/introspect.js
|
||||||
|
@@ -1,9 +1,11 @@
|
||||||
|
-const { Gio, GLib, Meta, Shell } = imports.gi;
|
||||||
|
+const { Gio, GLib, Meta, Shell, St } = imports.gi;
|
||||||
|
|
||||||
|
const INTROSPECT_SCHEMA = 'org.gnome.shell';
|
||||||
|
const INTROSPECT_KEY = 'introspect';
|
||||||
|
const APP_WHITELIST = ['org.freedesktop.impl.portal.desktop.gtk'];
|
||||||
|
|
||||||
|
+const INTROSPECT_DBUS_API_VERSION = 2;
|
||||||
|
+
|
||||||
|
const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||||
|
|
||||||
|
const IntrospectDBusIface = loadInterfaceXML('org.gnome.Shell.Introspect');
|
||||||
|
@@ -21,6 +23,7 @@ var IntrospectService = class {
|
||||||
|
this._runningApplicationsDirty = true;
|
||||||
|
this._activeApplication = null;
|
||||||
|
this._activeApplicationDirty = true;
|
||||||
|
+ this._animationsEnabled = true;
|
||||||
|
|
||||||
|
this._appSystem = Shell.AppSystem.get_default();
|
||||||
|
this._appSystem.connect('app-state-changed',
|
||||||
|
@@ -50,6 +53,11 @@ var IntrospectService = class {
|
||||||
|
(conn, name, owner) => this._whitelistMap.set(name, owner),
|
||||||
|
(conn, name) => this._whitelistMap.delete(name));
|
||||||
|
});
|
||||||
|
+
|
||||||
|
+ this._settings = St.Settings.get();
|
||||||
|
+ this._settings.connect('notify::enable-animations',
|
||||||
|
+ this._syncAnimationsEnabled.bind(this));
|
||||||
|
+ this._syncAnimationsEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
_isStandaloneApp(app) {
|
||||||
|
@@ -191,4 +199,21 @@ var IntrospectService = class {
|
||||||
|
}
|
||||||
|
invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList]));
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ _syncAnimationsEnabled() {
|
||||||
|
+ let wasAnimationsEnabled = this._animationsEnabled;
|
||||||
|
+ this._animationsEnabled = this._settings.enable_animations;
|
||||||
|
+ if (wasAnimationsEnabled !== this._animationsEnabled) {
|
||||||
|
+ let variant = new GLib.Variant('b', this._animationsEnabled);
|
||||||
|
+ this._dbusImpl.emit_property_changed('AnimationsEnabled', variant);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ get AnimationsEnabled() {
|
||||||
|
+ return this._animationsEnabled;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ get version() {
|
||||||
|
+ return INTROSPECT_DBUS_API_VERSION;
|
||||||
|
+ }
|
||||||
|
};
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -1,227 +0,0 @@
|
|||||||
From 4024d59871d0c8990ef5e4243c9fc485971755e7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ray Strode <rstrode@redhat.com>
|
|
||||||
Date: Tue, 10 Aug 2021 13:25:57 -0400
|
|
||||||
Subject: [PATCH 1/3] extensionSystem: Get rid of _enabled boolean optimization
|
|
||||||
|
|
||||||
At the moment a session mode either allows extensions or it doesn't.
|
|
||||||
If it allows extensions, then the entire available list of
|
|
||||||
configured extensions get enabled as soon as the session mode is
|
|
||||||
entered.
|
|
||||||
|
|
||||||
Since enabling or disabling extensions is an all or nothing situation,
|
|
||||||
the code tracks whether extensions are already enabled when entering
|
|
||||||
the session mode, and if so, avoids iterating through the extension list
|
|
||||||
needlessly. It does this using a boolean named _enabled.
|
|
||||||
|
|
||||||
In the future, the extensions themselves will be given some say on
|
|
||||||
whether or not they should be enabled in a given session mode. This
|
|
||||||
means, the configured extension list may contain extensions that
|
|
||||||
shouldn't be enabled for a given session mode, and the _enabled boolean
|
|
||||||
will no longer be appropriated.
|
|
||||||
|
|
||||||
This commit drops the _enabled boolean optimization.
|
|
||||||
---
|
|
||||||
js/ui/extensionSystem.js | 10 ----------
|
|
||||||
1 file changed, 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
|
|
||||||
index 9f4eb757b..2aae44b53 100644
|
|
||||||
--- a/js/ui/extensionSystem.js
|
|
||||||
+++ b/js/ui/extensionSystem.js
|
|
||||||
@@ -23,7 +23,6 @@ const UPDATE_CHECK_TIMEOUT = 24 * 60 * 60; // 1 day in seconds
|
|
||||||
var ExtensionManager = class {
|
|
||||||
constructor() {
|
|
||||||
this._initialized = false;
|
|
||||||
- this._enabled = false;
|
|
||||||
this._updateNotified = false;
|
|
||||||
|
|
||||||
this._extensions = new Map();
|
|
||||||
@@ -597,9 +596,6 @@ var ExtensionManager = class {
|
|
||||||
}
|
|
||||||
|
|
||||||
_enableAllExtensions() {
|
|
||||||
- if (this._enabled)
|
|
||||||
- return;
|
|
||||||
-
|
|
||||||
if (!this._initialized) {
|
|
||||||
this._loadExtensions();
|
|
||||||
this._initialized = true;
|
|
||||||
@@ -608,20 +604,14 @@ var ExtensionManager = class {
|
|
||||||
this._callExtensionEnable(uuid);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
- this._enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_disableAllExtensions() {
|
|
||||||
- if (!this._enabled)
|
|
||||||
- return;
|
|
||||||
-
|
|
||||||
if (this._initialized) {
|
|
||||||
this._extensionOrder.slice().reverse().forEach(uuid => {
|
|
||||||
this._callExtensionDisable(uuid);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
-
|
|
||||||
- this._enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_sessionUpdated() {
|
|
||||||
--
|
|
||||||
2.33.1
|
|
||||||
|
|
||||||
|
|
||||||
From f883c3f87f9778a0c2ed34db648aad73668949e3 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ray Strode <rstrode@redhat.com>
|
|
||||||
Date: Sat, 28 Aug 2021 13:54:39 -0400
|
|
||||||
Subject: [PATCH 2/3] extensionSystem: Allow extensions to run on the login
|
|
||||||
screen
|
|
||||||
|
|
||||||
At the moment it's not realy possible to extend the login screen to do
|
|
||||||
things it doesn't have built-in support for. This means in order
|
|
||||||
to support niche use cases, those cases have to change the main
|
|
||||||
code base. For instance, oVirt and Vmware deployments want to be able
|
|
||||||
to automaticaly log in guest VMs when a user pre-authenticates through a
|
|
||||||
console on a management host. To support those use cases, we added
|
|
||||||
code to the login screen directly, even though most machines will never
|
|
||||||
be associated with oVirt or Vmware management hosts.
|
|
||||||
|
|
||||||
We also get requests from e.g. government users that need certain features
|
|
||||||
at the login screen that wouldn't get used much outside of government
|
|
||||||
deployments. For instance, we've gotten requests that a machine contains
|
|
||||||
prominently displays that it has "Top Secret" information.
|
|
||||||
|
|
||||||
All of these use cases seem like they would better handled via
|
|
||||||
extensions that could be installed in the specific deployments. The
|
|
||||||
problem is extensions only run in the user session, and get
|
|
||||||
disabled at the login screen automatically.
|
|
||||||
|
|
||||||
This commit changes that. Now extensions can specify in their metadata
|
|
||||||
via a new sessionModes property, which modes that want to run in. For
|
|
||||||
backward compatibility, if an extension doesn't specify which session
|
|
||||||
modes it works in, its assumed the extension only works in the user
|
|
||||||
session.
|
|
||||||
---
|
|
||||||
js/ui/extensionSystem.js | 33 +++++++++++++++++++++++++++++----
|
|
||||||
1 file changed, 29 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
|
|
||||||
index 2aae44b53..937f86199 100644
|
|
||||||
--- a/js/ui/extensionSystem.js
|
|
||||||
+++ b/js/ui/extensionSystem.js
|
|
||||||
@@ -75,6 +75,28 @@ var ExtensionManager = class {
|
|
||||||
return [...this._extensions.keys()];
|
|
||||||
}
|
|
||||||
|
|
||||||
+ _extensionSupportsSessionMode(uuid) {
|
|
||||||
+ const extension = this.lookup(uuid);
|
|
||||||
+ if (!extension)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ if (extension.sessionModes.includes(Main.sessionMode.currentMode))
|
|
||||||
+ return true;
|
|
||||||
+ if (extension.sessionModes.includes(Main.sessionMode.parentMode))
|
|
||||||
+ return true;
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ _sessionModeCanUseExtension(uuid) {
|
|
||||||
+ if (!Main.sessionMode.allowExtensions)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ if (!this._extensionSupportsSessionMode(uuid))
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ return true;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
_callExtensionDisable(uuid) {
|
|
||||||
let extension = this.lookup(uuid);
|
|
||||||
if (!extension)
|
|
||||||
@@ -134,7 +156,7 @@ var ExtensionManager = class {
|
|
||||||
}
|
|
||||||
|
|
||||||
_callExtensionEnable(uuid) {
|
|
||||||
- if (!Main.sessionMode.allowExtensions)
|
|
||||||
+ if (!this._sessionModeCanUseExtension(uuid))
|
|
||||||
return;
|
|
||||||
|
|
||||||
let extension = this.lookup(uuid);
|
|
||||||
@@ -316,6 +338,7 @@ var ExtensionManager = class {
|
|
||||||
hasPrefs: dir.get_child('prefs.js').query_exists(null),
|
|
||||||
hasUpdate: false,
|
|
||||||
canChange: false,
|
|
||||||
+ sessionModes: meta['session-modes'] ? meta['session-modes'] : [ 'user' ],
|
|
||||||
};
|
|
||||||
this._extensions.set(uuid, extension);
|
|
||||||
|
|
||||||
@@ -398,7 +421,7 @@ var ExtensionManager = class {
|
|
||||||
}
|
|
||||||
|
|
||||||
_callExtensionInit(uuid) {
|
|
||||||
- if (!Main.sessionMode.allowExtensions)
|
|
||||||
+ if (!this._sessionModeCanUseExtension(uuid))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
let extension = this.lookup(uuid);
|
|
||||||
@@ -487,13 +510,15 @@ var ExtensionManager = class {
|
|
||||||
// Find and enable all the newly enabled extensions: UUIDs found in the
|
|
||||||
// new setting, but not in the old one.
|
|
||||||
newEnabledExtensions
|
|
||||||
- .filter(uuid => !this._enabledExtensions.includes(uuid))
|
|
||||||
+ .filter(uuid => !this._enabledExtensions.includes(uuid) &&
|
|
||||||
+ this._extensionSupportsSessionMode(uuid))
|
|
||||||
.forEach(uuid => this._callExtensionEnable(uuid));
|
|
||||||
|
|
||||||
// Find and disable all the newly disabled extensions: UUIDs found in the
|
|
||||||
// old setting, but not in the new one.
|
|
||||||
this._extensionOrder
|
|
||||||
- .filter(uuid => !newEnabledExtensions.includes(uuid))
|
|
||||||
+ .filter(uuid => !newEnabledExtensions.includes(uuid) ||
|
|
||||||
+ !this._extensionSupportsSessionMode(uuid))
|
|
||||||
.reverse().forEach(uuid => this._callExtensionDisable(uuid));
|
|
||||||
|
|
||||||
this._enabledExtensions = newEnabledExtensions;
|
|
||||||
--
|
|
||||||
2.33.1
|
|
||||||
|
|
||||||
|
|
||||||
From c637d0a14ea7223ea7d763e1c4dedb4d6b6609a4 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ray Strode <rstrode@redhat.com>
|
|
||||||
Date: Tue, 10 Aug 2021 15:31:00 -0400
|
|
||||||
Subject: [PATCH 3/3] sessionMode: Allow extensions at the login and unlock
|
|
||||||
screens
|
|
||||||
|
|
||||||
Now extensions can specify which session modes they work in,
|
|
||||||
but specifying the login screen or unlock screen session modes in
|
|
||||||
an extensions metadata still won't work, because those session
|
|
||||||
modes disallow extensions.
|
|
||||||
|
|
||||||
This commit fixes that.
|
|
||||||
---
|
|
||||||
js/ui/sessionMode.js | 2 ++
|
|
||||||
1 file changed, 2 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/js/ui/sessionMode.js b/js/ui/sessionMode.js
|
|
||||||
index 4d4fb2444..0534fd1d4 100644
|
|
||||||
--- a/js/ui/sessionMode.js
|
|
||||||
+++ b/js/ui/sessionMode.js
|
|
||||||
@@ -43,6 +43,7 @@ const _modes = {
|
|
||||||
},
|
|
||||||
|
|
||||||
'gdm': {
|
|
||||||
+ allowExtensions: true,
|
|
||||||
hasNotifications: true,
|
|
||||||
isGreeter: true,
|
|
||||||
isPrimary: true,
|
|
||||||
@@ -59,6 +60,7 @@ const _modes = {
|
|
||||||
},
|
|
||||||
|
|
||||||
'unlock-dialog': {
|
|
||||||
+ allowExtensions: true,
|
|
||||||
isLocked: true,
|
|
||||||
unlockDialog: undefined,
|
|
||||||
components: ['polkitAgent', 'telepathyClient'],
|
|
||||||
--
|
|
||||||
2.33.1
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue