Merge lp:~3v1n0/gnome-shell/bionic-patches-picks into lp:~ubuntu-desktop/gnome-shell/ubuntu

Proposed by Marco Trevisan (Treviño)
Status: Merged
Merged at revision: 143
Proposed branch: lp:~3v1n0/gnome-shell/bionic-patches-picks
Merge into: lp:~ubuntu-desktop/gnome-shell/ubuntu
Diff against target: 1534 lines (+1455/-1)
13 files modified
debian/changelog (+26/-0)
debian/patches/StIcon-only-compute-shadow-pipeline-when-the-texture-is-p.patch (+134/-0)
debian/patches/js-fix-invalid-access-errors.patch (+564/-0)
debian/patches/popupMenu-Fix-wrong-call-to-clutter_actor_add_child.patch (+28/-0)
debian/patches/series (+12/-1)
debian/patches/shell-ignore-invalid-window-monitor-index.patch (+98/-0)
debian/patches/st-texture-cache-Cancel-sliced-image-loading-on-target-ac.patch (+118/-0)
debian/patches/st-texture-cache-Don-t-add-NULL-textures-to-cache.patch (+92/-0)
debian/patches/volume-Add-back-sound-feedback-on-scroll.patch (+106/-0)
debian/patches/workspace-fix-repositioned-windows-in-activities.patch (+148/-0)
debian/patches/workspaceThumbnail-initialize-porthole-based-on-workArea.patch (+36/-0)
debian/patches/workspaceThumbnail-only-update-_porthole-if-the-overview-.patch (+29/-0)
debian/patches/workspaceThumbnail-rebuild-thumbnails-if-workareas-size-c.patch (+64/-0)
To merge this branch: bzr merge lp:~3v1n0/gnome-shell/bionic-patches-picks
Reviewer Review Type Date Requested Status
Jeremy Bícha Approve
Review via email: mp+343423@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Jeremy Bícha (jbicha) wrote :

I am very concerned with the decision to add 11 more patches to bionic's gnome-shell. I am concerned that this could make updating to 3.28.2 difficult (or the 3.30 series) if too much code is changed before these patches are accepted in to GNOME.

You could at least help reduce this number by following up on the patches that have already been applied to upstream master to see if they can be pushed to the gnome-3-28 branch.

Please also try to be more persistent with getting upstream review of the remaining patches.

I encourage you to talk to Debian's smcv to see if he would be interested in taking some of these patches in to Debian.

One minor note. The patch rename wasn't done in this merge proposal. Maybe that was missed when exporting your work from git.

review: Approve
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

2018-04-17 13:15 GMT-05:00 Jeremy Bicha <email address hidden>:
> I am very concerned with the decision to add 11 more patches to bionic's gnome-shell. I am concerned that this
> could make updating to 3.28.2 difficult (or the 3.30 series) if too much code is changed before these patches
> are accepted in to GNOME.

Considering how the pace at gnome-shell development is currently, I
think this won't be really a problem.
Plus, I've linked the git repo I've used to generate all this, and
using patch-queue, you know that rebasing won't really be an issue.
In any, case I can take care of it. Although I hope some of these
patch will merge (where's it's not already the case).

> You could at least help reduce this number by following up on the patches that have already been applied to upstream master
> to see if they can be pushed to the gnome-3-28 branch.

There's not gnome-3-28 branch yet, thus everything that here has been
cherry-picked from master, will be in 3.28.X.

> Please also try to be more persistent with getting upstream review of the remaining patches.

Eh, true, but I also don't like to bother people :).

> I encourage you to talk to Debian's smcv to see if he would be interested in taking some of these patches in to Debian.

Yeah, I already planned to propose some of them to salsa too.

> One minor note. The patch rename wasn't done in this merge proposal. Maybe that was missed when exporting your work from git.

Oh, well spotted. Thanks.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2018-04-14 01:50:15 +0000
+++ debian/changelog 2018-04-17 10:30:40 +0000
@@ -1,10 +1,36 @@
1gnome-shell (3.28.1-0ubuntu1) UNRELEASED; urgency=medium1gnome-shell (3.28.1-0ubuntu1) UNRELEASED; urgency=medium
22
3 [ Jeremy Bicha ]
3 * New upstream release4 * New upstream release
4 * Drop obsolete patches:5 * Drop obsolete patches:
5 - 27-nm-libexec-path.patch6 - 27-nm-libexec-path.patch
6 - fix-wayland-vbox-crash.patch7 - fix-wayland-vbox-crash.patch
78
9 [ Marco Trevisan (Treviño) ]
10 * ui-Theme-lookup-should-respect-XDG_DATA_DIRS.patch:
11 - Renamed from ubuntu_theme_lookup_xdg.patch and cherry-picked from
12 upstream
13 * StIcon-only-compute-shadow-pipeline-when-the-texture-is-p.patch:
14 - Don't try to compute shadows on not allocated icons (LP: #1723378)
15 * js-fix-invalid-access-errors.patch:
16 - Fix javascript errors (LP: #1747566)
17 * popupMenu-Fix-wrong-call-to-clutter_actor_add_child.patch:
18 - Cherry-pick from upstream
19 * shell-ignore-invalid-window-monitor-index.patch:
20 - Fix crash on accessing on invalid monitor windows (LP: #1724439)
21 * volume-Add-back-sound-feedback-on-scroll.patch:
22 - Fix regression causing missing feedback on volume slider scroll
23 * workspace-fix-repositioned-windows-in-activities.patch:
24 - Ensure windows thumbnails coordinates are correct (LP: #1653153)
25 * workspaceThumbnail-initialize-porthole-based-on-workArea.patch:
26 workspaceThumbnail-only-update-_porthole-if-the-overview-.patch:
27 workspaceThumbnail-rebuild-thumbnails-if-workareas-size-c.patch:
28 - Cherry-picks from upstream, avoid unneeded computations in activities
29 * st-texture-cache-Cancel-sliced-image-loading-on-target-ac.patch:
30 - Fix possible crash on cache loading
31 * st-texture-cache-Don-t-add-NULL-textures-to-cache.patch:
32 - Fix crash when deleting NULL textures from cash (LP: #1754445)
33
8 -- Jeremy Bicha <jbicha@ubuntu.com> Fri, 13 Apr 2018 21:40:17 -040034 -- Jeremy Bicha <jbicha@ubuntu.com> Fri, 13 Apr 2018 21:40:17 -0400
935
10gnome-shell (3.28.0-0ubuntu5) bionic; urgency=medium36gnome-shell (3.28.0-0ubuntu5) bionic; urgency=medium
1137
=== added file 'debian/patches/StIcon-only-compute-shadow-pipeline-when-the-texture-is-p.patch'
--- debian/patches/StIcon-only-compute-shadow-pipeline-when-the-texture-is-p.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/StIcon-only-compute-shadow-pipeline-when-the-texture-is-p.patch 2018-04-17 10:30:40 +0000
@@ -0,0 +1,134 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Wed, 18 Oct 2017 05:32:22 -0500
3Subject: StIcon: only compute shadow pipeline when the texture is properly
4 allocated
5
6Creating the shadow pipeline requires the actor to be allocated in order
7to get its dimensions, however in the current state we just compute it
8even if this is not the case.
9This causes _st_create_shadow_pipeline_from_actor (when getting the allocation
10box) to trigger an allocation cycle, which might lead to a convolution to
11st_icon_finish_update causing breakage on data as soon as we return from it.
12
13Generating it at paint if not done before, it's a way for avoiding this.
14
15https://bugzilla.gnome.org/show_bug.cgi?id=788908
16
17Bug-GNOME: https://bugzilla.gnome.org/show_bug.cgi?id=788908
18Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1723378
19Forwarded: yes, https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/3
20---
21 src/st/st-icon.c | 48 +++++++++++++++++++++++++++++++++++++-----------
22 1 file changed, 37 insertions(+), 11 deletions(-)
23
24diff --git a/src/st/st-icon.c b/src/st/st-icon.c
25index 192df60..332e5b2 100644
26--- a/src/st/st-icon.c
27+++ b/src/st/st-icon.c
28@@ -56,12 +56,15 @@ struct _StIconPrivate
29
30 CoglPipeline *shadow_pipeline;
31 StShadow *shadow_spec;
32+ ClutterSize shadow_size;
33 };
34
35 G_DEFINE_TYPE_WITH_PRIVATE (StIcon, st_icon, ST_TYPE_WIDGET)
36
37 static void st_icon_update (StIcon *icon);
38 static gboolean st_icon_update_icon_size (StIcon *icon);
39+static void st_icon_update_shadow_pipeline (StIcon *icon);
40+static void st_icon_clean_shadow_pipeline (StIcon *icon);
41
42 #define DEFAULT_ICON_SIZE 48
43
44@@ -164,18 +167,31 @@ st_icon_paint (ClutterActor *actor)
45
46 if (priv->icon_texture)
47 {
48- if (priv->shadow_pipeline)
49- {
50+ if (priv->shadow_spec)
51+ {
52 ClutterActorBox allocation;
53 float width, height;
54
55 clutter_actor_get_allocation_box (priv->icon_texture, &allocation);
56 clutter_actor_box_get_size (&allocation, &width, &height);
57
58- _st_paint_shadow_with_opacity (priv->shadow_spec,
59- priv->shadow_pipeline,
60- &allocation,
61- clutter_actor_get_paint_opacity (priv->icon_texture));
62+ if (priv->shadow_pipeline == NULL ||
63+ priv->shadow_size.width != width ||
64+ priv->shadow_size.height != height)
65+ {
66+ st_icon_update_shadow_pipeline (ST_ICON (actor));
67+
68+ if (priv->shadow_pipeline)
69+ clutter_size_init (&priv->shadow_size, width, height);
70+ }
71+
72+ if (priv->shadow_pipeline)
73+ {
74+ _st_paint_shadow_with_opacity (priv->shadow_spec,
75+ priv->shadow_pipeline,
76+ &allocation,
77+ clutter_actor_get_paint_opacity (priv->icon_texture));
78+ }
79 }
80
81 clutter_actor_paint (priv->icon_texture);
82@@ -189,7 +205,7 @@ st_icon_style_changed (StWidget *widget)
83 StThemeNode *theme_node = st_widget_get_theme_node (widget);
84 StIconPrivate *priv = self->priv;
85
86- g_clear_pointer (&priv->shadow_pipeline, cogl_object_unref);
87+ st_icon_clean_shadow_pipeline (self);
88 g_clear_pointer (&priv->shadow_spec, st_shadow_unref);
89
90 priv->shadow_spec = st_theme_node_get_shadow (theme_node, "icon-shadow");
91@@ -268,21 +284,31 @@ st_icon_init (StIcon *self)
92 }
93
94 static void
95-st_icon_update_shadow_pipeline (StIcon *icon)
96+st_icon_clean_shadow_pipeline (StIcon *icon)
97 {
98 StIconPrivate *priv = icon->priv;
99
100 g_clear_pointer (&priv->shadow_pipeline, cogl_object_unref);
101+ clutter_size_init (&priv->shadow_size, 0, 0);
102+}
103+
104+static void
105+st_icon_update_shadow_pipeline (StIcon *icon)
106+{
107+ StIconPrivate *priv = icon->priv;
108+
109+ st_icon_clean_shadow_pipeline (icon);
110
111 if (priv->shadow_spec)
112- priv->shadow_pipeline = _st_create_shadow_pipeline_from_actor (priv->shadow_spec, priv->icon_texture);
113+ priv->shadow_pipeline = _st_create_shadow_pipeline_from_actor (priv->shadow_spec, priv->icon_texture);
114 }
115
116 static void
117 on_pixbuf_changed (ClutterTexture *texture,
118 StIcon *icon)
119 {
120- st_icon_update_shadow_pipeline (icon);
121+ st_icon_clean_shadow_pipeline (icon);
122+ clutter_actor_queue_redraw (CLUTTER_ACTOR (icon));
123 }
124
125 static void
126@@ -307,7 +333,7 @@ st_icon_finish_update (StIcon *icon)
127 /* Remove the temporary ref we added */
128 g_object_unref (priv->icon_texture);
129
130- st_icon_update_shadow_pipeline (icon);
131+ st_icon_clean_shadow_pipeline (icon);
132
133 /* "pixbuf-change" is actually a misnomer for "texture-changed" */
134 g_signal_connect_object (priv->icon_texture, "pixbuf-change",
0135
=== added file 'debian/patches/js-fix-invalid-access-errors.patch'
--- debian/patches/js-fix-invalid-access-errors.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/js-fix-invalid-access-errors.patch 2018-04-17 10:30:40 +0000
@@ -0,0 +1,564 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Mon, 4 Dec 2017 19:41:50 -0600
3Subject: js: fix invalid-access errors
4
5tweener: Save handlers on target and remove them on destroy
6
7Saving handlers we had using the wrapper as a property of the object and delete
8them when resetting the object state.
9Without doing this an handler could be called on a destroyed target when this
10happens on the onComplete callback.
11
12https://bugzilla.gnome.org/show_bug.cgi?id=791233
13
14dnd: Nullify _dragActor after we've destroyed it, and avoid invalid access
15
16We need to avoid that we use the _dragActor instance after that it has
17been destroyed or we'll get errors. We now set it to null when this
18happens, protecting any access to that.
19
20Add a DragState enum-like object to keep track of the state
21instead of using booleans.
22
23Remove duplicated handler on 'destroy' and just use a generic one.
24
25https://bugzilla.gnome.org/show_bug.cgi?id=791233
26
27workspaceThumbnail: Disconnect from window signals on destruction
28
29Avoid to try to destroy the window clone content more than once
30when a window is destroyed, and do it in proper order.
31
32https://bugzilla.gnome.org/show_bug.cgi?id=791233
33
34workspaceThumbnail: Remove WindowClone's from _windows when destroyed
35
36A WindowClone might be destroyed earlier than its MetaWindow counterpart
37as its WindowActor could be destroyed earlier, thus when happens it's safer
38to remove the clone from the windows list, without waiting for the workspace
39to request to do so.
40
41WindowClone now emits a 'destroy' signals earlier enough and this now
42triggers a _doRemoveWindow on WorkspaceThumbnail which will lead
43to the proper cleanup; keeping track of the signal connections, in
44order to avoid callback loops (not really harmful in this case, but
45good practice).
46
47https://bugzilla.gnome.org/show_bug.cgi?id=791233
48
49workspace: Disconnect from window signals on destruction
50
51Avoid to try to destroy the window clone content more than once
52when a window is destroyed, and do it in proper order.
53
54https://bugzilla.gnome.org/show_bug.cgi?id=791233
55
56workspace: Remove WindowClone's from _windows when destroyed
57
58A WindowClone might be destroyed earlier than its MetaWindow counterpart
59as its WindowActor could be destroyed earlier, thus when happens it's safer
60to remove the clone from the windows list, without waiting for the workspace
61to request to do so.
62
63WindowClone now emits a 'destroy' signals earlier enough and this now
64triggers a _doRemoveWindow on WorkspaceThumbnail which will lead
65to the proper cleanup; keeping track of the signal connections, in
66order to avoid callback loops (not really harmful in this case, but
67good practice).
68
69https://bugzilla.gnome.org/show_bug.cgi?id=791233
70
71Bug-GNOME: https://bugzilla.gnome.org/show_bug.cgi?id=791233
72Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/bionic/+source/gnome-shell/+bug/1747566
73Forwarded: yes, https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/4
74---
75 js/ui/dnd.js | 65 +++++++++++++++++++++++++++------------------
76 js/ui/tweener.js | 64 +++++++++++++++++++++++++++++++++++---------
77 js/ui/workspace.js | 35 +++++++++++++++++-------
78 js/ui/workspaceThumbnail.js | 33 +++++++++++++++++------
79 4 files changed, 140 insertions(+), 57 deletions(-)
80
81diff --git a/js/ui/dnd.js b/js/ui/dnd.js
82index a38607c..431c60d 100644
83--- a/js/ui/dnd.js
84+++ b/js/ui/dnd.js
85@@ -27,6 +27,12 @@ var DragMotionResult = {
86 CONTINUE: 3
87 };
88
89+var DragState = {
90+ INIT: 0,
91+ DRAGGING: 1,
92+ CANCELLED: 2,
93+};
94+
95 var DRAG_CURSOR_MAP = {
96 0: Meta.Cursor.DND_UNSUPPORTED_TARGET,
97 1: Meta.Cursor.DND_COPY,
98@@ -78,6 +84,8 @@ var _Draggable = new Lang.Class({
99 dragActorOpacity: undefined });
100
101 this.actor = actor;
102+ this._dragState = DragState.INIT;
103+
104 if (!params.manualMode) {
105 this.actor.connect('button-press-event',
106 this._onButtonPress.bind(this));
107@@ -88,7 +96,7 @@ var _Draggable = new Lang.Class({
108 this.actor.connect('destroy', () => {
109 this._actorDestroyed = true;
110
111- if (this._dragInProgress && this._dragCancellable)
112+ if (this._dragState == DragState.DRAGGING && this._dragCancellable)
113 this._cancelDrag(global.get_current_time());
114 this.disconnectAll();
115 });
116@@ -100,7 +108,6 @@ var _Draggable = new Lang.Class({
117 this._dragActorOpacity = params.dragActorOpacity;
118
119 this._buttonDown = false; // The mouse button has been pressed and has not yet been released.
120- this._dragInProgress = false; // The drag has been started, and has not been dropped or cancelled yet.
121 this._animationInProgress = false; // The drag is over and the item is in the process of animating to its original position (snapping back or reverting).
122 this._dragCancellable = true;
123
124@@ -206,9 +213,10 @@ var _Draggable = new Lang.Class({
125 (event.type() == Clutter.EventType.TOUCH_END &&
126 global.display.is_pointer_emulating_sequence(event.get_event_sequence()))) {
127 this._buttonDown = false;
128- if (this._dragInProgress) {
129+ if (this._dragState == DragState.DRAGGING) {
130 return this._dragActorDropped(event);
131- } else if (this._dragActor != null && !this._animationInProgress) {
132+ } else if ((this._dragActor != null || this._dragState == DragState.CANCELLED) &&
133+ !this._animationInProgress) {
134 // Drag must have been cancelled with Esc.
135 this._dragComplete();
136 return Clutter.EVENT_STOP;
137@@ -222,14 +230,14 @@ var _Draggable = new Lang.Class({
138 } else if (event.type() == Clutter.EventType.MOTION ||
139 (event.type() == Clutter.EventType.TOUCH_UPDATE &&
140 global.display.is_pointer_emulating_sequence(event.get_event_sequence()))) {
141- if (this._dragInProgress) {
142+ if (this._dragActor && this._dragState == DragState.DRAGGING) {
143 return this._updateDragPosition(event);
144- } else if (this._dragActor == null) {
145+ } else if (this._dragActor == null && this._dragState != DragState.CANCELLED) {
146 return this._maybeStartDrag(event);
147 }
148 // We intercept KEY_PRESS event so that we can process Esc key press to cancel
149 // dragging and ignore all other key presses.
150- } else if (event.type() == Clutter.EventType.KEY_PRESS && this._dragInProgress) {
151+ } else if (event.type() == Clutter.EventType.KEY_PRESS && this._dragState == DragState.DRAGGING) {
152 let symbol = event.get_key_symbol();
153 if (symbol == Clutter.Escape) {
154 this._cancelDrag(event.get_time());
155@@ -265,7 +273,7 @@ var _Draggable = new Lang.Class({
156 */
157 startDrag(stageX, stageY, time, sequence) {
158 currentDraggable = this;
159- this._dragInProgress = true;
160+ this._dragState = DragState.DRAGGING;
161
162 // Special-case St.Button: the pointer grab messes with the internal
163 // state, so force a reset to a reasonable state here
164@@ -342,6 +350,13 @@ var _Draggable = new Lang.Class({
165 Shell.util_set_hidden_from_pick(this._dragActor, true);
166 }
167
168+ this._dragActorDestroyId = this._dragActor.connect('destroy', () => {
169+ // Cancel ongoing animation (if any)
170+ this._finishAnimation();
171+
172+ this._dragActor = null;
173+ this._dragState = DragState.CANCELLED;
174+ });
175 this._dragOrigOpacity = this._dragActor.opacity;
176 if (this._dragActorOpacity != undefined)
177 this._dragActor.opacity = this._dragActorOpacity;
178@@ -500,7 +515,7 @@ var _Draggable = new Lang.Class({
179 event.get_time())) {
180 // If it accepted the drop without taking the actor,
181 // handle it ourselves.
182- if (this._dragActor.get_parent() == Main.uiGroup) {
183+ if (this._dragActor && this._dragActor.get_parent() == Main.uiGroup) {
184 if (this._restoreOnSuccess) {
185 this._restoreDragActor(event.get_time());
186 return true;
187@@ -508,7 +523,7 @@ var _Draggable = new Lang.Class({
188 this._dragActor.destroy();
189 }
190
191- this._dragInProgress = false;
192+ this._dragState = DragState.INIT;
193 global.screen.set_cursor(Meta.Cursor.DEFAULT);
194 this.emit('drag-end', event.get_time(), true);
195 this._dragComplete();
196@@ -557,20 +572,22 @@ var _Draggable = new Lang.Class({
197
198 _cancelDrag(eventTime) {
199 this.emit('drag-cancelled', eventTime);
200- this._dragInProgress = false;
201- let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation();
202+ let wasCancelled = (this._dragState == DragState.CANCELLED);
203+ this._dragState = DragState.CANCELLED;
204
205- if (this._actorDestroyed) {
206+ if (this._actorDestroyed || wasCancelled) {
207 global.screen.set_cursor(Meta.Cursor.DEFAULT);
208 if (!this._buttonDown)
209 this._dragComplete();
210 this.emit('drag-end', eventTime, false);
211- if (!this._dragOrigParent)
212+ if (!this._dragOrigParent && this._dragActor)
213 this._dragActor.destroy();
214
215 return;
216 }
217
218+ let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation();
219+
220 this._animateDragEnd(eventTime,
221 { x: snapBackX,
222 y: snapBackY,
223@@ -581,7 +598,7 @@ var _Draggable = new Lang.Class({
224 },
225
226 _restoreDragActor(eventTime) {
227- this._dragInProgress = false;
228+ this._dragState = DragState.INIT;
229 let [restoreX, restoreY, restoreScale] = this._getRestoreLocation();
230
231 // fade the actor back in at its original location
232@@ -596,12 +613,6 @@ var _Draggable = new Lang.Class({
233 _animateDragEnd(eventTime, params) {
234 this._animationInProgress = true;
235
236- // finish animation if the actor gets destroyed
237- // during it
238- this._dragActorDestroyId =
239- this._dragActor.connect('destroy',
240- this._finishAnimation.bind(this));
241-
242 params['opacity'] = this._dragOrigOpacity;
243 params['transition'] = 'easeOutQuad';
244 params['onComplete'] = this._onAnimationComplete;
245@@ -624,9 +635,6 @@ var _Draggable = new Lang.Class({
246 },
247
248 _onAnimationComplete(dragActor, eventTime) {
249- dragActor.disconnect(this._dragActorDestroyId);
250- this._dragActorDestroyId = 0;
251-
252 if (this._dragOrigParent) {
253 Main.uiGroup.remove_child(this._dragActor);
254 this._dragOrigParent.add_actor(this._dragActor);
255@@ -641,7 +649,7 @@ var _Draggable = new Lang.Class({
256 },
257
258 _dragComplete() {
259- if (!this._actorDestroyed)
260+ if (!this._actorDestroyed && this._dragActor)
261 Shell.util_set_hidden_from_pick(this._dragActor, false);
262
263 this._ungrabEvents();
264@@ -652,7 +660,12 @@ var _Draggable = new Lang.Class({
265 this._updateHoverId = 0;
266 }
267
268- this._dragActor = undefined;
269+ if (this._dragActor) {
270+ this._dragActor.disconnect(this._dragActorDestroyId);
271+ this._dragActor = null;
272+ }
273+
274+ this._dragState = DragState.INIT;
275 currentDraggable = null;
276 }
277 });
278diff --git a/js/ui/tweener.js b/js/ui/tweener.js
279index 1a85e2f..663b97b 100644
280--- a/js/ui/tweener.js
281+++ b/js/ui/tweener.js
282@@ -69,30 +69,68 @@ function _getTweenState(target) {
283 return target.__ShellTweenerState;
284 }
285
286+function _ensureHandlers(target) {
287+ if (!target.__ShellTweenerHandlers)
288+ target.__ShellTweenerHandlers = {};
289+ return target.__ShellTweenerHandlers;
290+}
291+
292 function _resetTweenState(target) {
293 let state = target.__ShellTweenerState;
294
295 if (state) {
296- if (state.destroyedId)
297+ if (state.destroyedId) {
298 state.actor.disconnect(state.destroyedId);
299+ delete state.destroyedId;
300+ }
301 }
302
303+ _removeHandler(target, 'onComplete', _tweenCompleted);
304 target.__ShellTweenerState = {};
305 }
306
307 function _addHandler(target, params, name, handler) {
308- if (params[name]) {
309- let oldHandler = params[name];
310- let oldScope = params[name + 'Scope'];
311- let oldParams = params[name + 'Params'];
312- let eventScope = oldScope ? oldScope : target;
313-
314- params[name] = () => {
315- oldHandler.apply(eventScope, oldParams);
316- handler(target);
317- };
318- } else
319- params[name] = () => { handler(target); };
320+ let wrapperNeeded = false;
321+ let tweenerHandlers = _ensureHandlers(target);
322+
323+ if (!(name in tweenerHandlers))
324+ {
325+ tweenerHandlers[name] = [];
326+ wrapperNeeded = true;
327+ }
328+
329+ let handlers = tweenerHandlers[name];
330+ handlers.push(handler);
331+
332+ if (wrapperNeeded) {
333+ if (params[name]) {
334+ let oldHandler = params[name];
335+ let oldScope = params[name + 'Scope'];
336+ let oldParams = params[name + 'Params'];
337+ let eventScope = oldScope ? oldScope : target;
338+
339+ params[name] = () => {
340+ oldHandler.apply(eventScope, oldParams);
341+ handlers.forEach((h) => h(target));
342+ };
343+ } else {
344+ params[name] = () => { handlers.forEach((h) => h(target)); };
345+ }
346+ }
347+}
348+
349+function _removeHandler(target, name, handler) {
350+ let tweenerHandlers = _ensureHandlers(target);
351+
352+ if (name in tweenerHandlers) {
353+ let handlers = tweenerHandlers[name];
354+ let handlerIndex = handlers.indexOf(handler);
355+
356+ while (handlerIndex > -1) {
357+ handlers.splice(handlerIndex, 1);
358+ handlerIndex = handlers.indexOf(handler);
359+ }
360+ }
361 }
362
363 function _actorDestroyed(target) {
364diff --git a/js/ui/workspace.js b/js/ui/workspace.js
365index 1e121b7..8836537 100644
366--- a/js/ui/workspace.js
367+++ b/js/ui/workspace.js
368@@ -139,14 +139,8 @@ var WindowClone = new Lang.Class({
369
370 this._windowClone._updateId = this.metaWindow.connect('size-changed',
371 this._onRealWindowSizeChanged.bind(this));
372- this._windowClone._destroyId =
373- this.realWindow.connect('destroy', () => {
374- // First destroy the clone and then destroy everything
375- // This will ensure that we never see it in the
376- // _disconnectSignals loop
377- this._windowClone.destroy();
378- this.destroy();
379- });
380+ this._windowClone._destroyId = this.realWindow.connect('destroy',
381+ this.destroy.bind(this));
382
383 this._updateAttachedDialogs();
384 this._computeBoundingBox();
385@@ -310,6 +304,14 @@ var WindowClone = new Lang.Class({
386 },
387
388 destroy() {
389+ this.emit('destroy');
390+
391+ // First destroy the clone and then destroy everything
392+ // This will ensure that we never see it in the _disconnectSignals loop
393+ this.metaWindow.disconnect(this._windowClone._updateId);
394+ this.realWindow.disconnect(this._windowClone._destroyId);
395+ this._windowClone.destroy();
396+
397 this.actor.destroy();
398 },
399
400@@ -1131,6 +1133,7 @@ var Workspace = new Lang.Class({
401 // Create clones for windows that should be
402 // visible in the Overview
403 this._windows = [];
404+ this._windowsDestroyedIds = [];
405 this._windowOverlays = [];
406 for (let i = 0; i < windows.length; i++) {
407 if (this._isOverviewWindow(windows[i])) {
408@@ -1428,7 +1431,7 @@ var Workspace = new Lang.Class({
409 return GLib.SOURCE_REMOVE;
410 },
411
412- _doRemoveWindow(metaWin) {
413+ _doRemoveWindow(metaWin, {cloneDestroy}={cloneDestroy: true}) {
414 let win = metaWin.get_compositor_private();
415
416 // find the position of the window in our list
417@@ -1438,8 +1441,10 @@ var Workspace = new Lang.Class({
418 return;
419
420 let clone = this._windows[index];
421+ clone.disconnect(this._windowsDestroyedIds[index]);
422
423 this._windows.splice(index, 1);
424+ this._windowsDestroyedIds.splice(index, 1);
425 this._windowOverlays.splice(index, 1);
426
427 // If metaWin.get_compositor_private() returned non-NULL, that
428@@ -1457,7 +1462,9 @@ var Workspace = new Lang.Class({
429 scale: stageWidth / clone.actor.width
430 };
431 }
432- clone.destroy();
433+
434+ if (cloneDestroy)
435+ clone.destroy();
436
437
438 // We need to reposition the windows; to avoid shuffling windows
439@@ -1800,7 +1807,11 @@ var Workspace = new Lang.Class({
440 this._actualGeometryLater = 0;
441 }
442
443+ for (let index = 0; index < this._windows.length; ++index)
444+ this._windows[index].disconnect(this._windowsDestroyedIds[index]);
445+
446 this._windows = [];
447+ this._windowsDestroyedIds = [];
448 },
449
450 // Sets this.leavingOverview flag to false.
451@@ -1848,6 +1859,9 @@ var Workspace = new Lang.Class({
452 clone.connect('size-changed', () => {
453 this._recalculateWindowPositions(WindowPositionFlags.NONE);
454 });
455+ let cloneDestroyedId = clone.connect('destroy', () => {
456+ this._doRemoveWindow(clone.metaWindow, {cloneDestroy: false});
457+ });
458
459 this.actor.add_actor(clone.actor);
460
461@@ -1864,6 +1878,7 @@ var Workspace = new Lang.Class({
462 clone.setStackAbove(this._windows[this._windows.length - 1].actor);
463
464 this._windows.push(clone);
465+ this._windowsDestroyedIds.push(cloneDestroyedId);
466 this._windowOverlays.push(overlay);
467
468 return [clone, overlay];
469diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js
470index c1b4bdd..0c72e74 100644
471--- a/js/ui/workspaceThumbnail.js
472+++ b/js/ui/workspaceThumbnail.js
473@@ -70,12 +70,7 @@ var WindowClone = new Lang.Class({
474
475 this.clone._updateId = this.metaWindow.connect('position-changed',
476 this._onPositionChanged.bind(this));
477- this.clone._destroyId = this.realWindow.connect('destroy', () => {
478- // First destroy the clone and then destroy everything
479- // This will ensure that we never see it in the _disconnectSignals loop
480- this.clone.destroy();
481- this.destroy();
482- });
483+ this.clone._destroyId = this.realWindow.connect('destroy', this.destroy.bind(this));
484 this._onPositionChanged();
485
486 this.actor.connect('button-release-event',
487@@ -142,6 +137,14 @@ var WindowClone = new Lang.Class({
488 },
489
490 destroy() {
491+ this.emit('destroy');
492+
493+ // First destroy the clone and then destroy everything
494+ // This will ensure that we never see it in the _disconnectSignals loop
495+ this.metaWindow.disconnect(this.clone._updateId);
496+ this.realWindow.disconnect(this.clone._destroyId);
497+ this.clone.destroy();
498+
499 this.actor.destroy();
500 },
501
502@@ -285,6 +288,7 @@ var WorkspaceThumbnail = new Lang.Class({
503
504 // Create clones for windows that should be visible in the Overview
505 this._windows = [];
506+ this._windowsDestroyedIds = [];
507 this._allWindows = [];
508 this._minimizedChangedIds = [];
509 for (let i = 0; i < windows.length; i++) {
510@@ -371,7 +375,7 @@ var WorkspaceThumbnail = new Lang.Class({
511 return this._collapseFraction;
512 },
513
514- _doRemoveWindow(metaWin) {
515+ _doRemoveWindow(metaWin, {cloneDestroy}={cloneDestroy: true}) {
516 let win = metaWin.get_compositor_private();
517
518 // find the position of the window in our list
519@@ -381,9 +385,13 @@ var WorkspaceThumbnail = new Lang.Class({
520 return;
521
522 let clone = this._windows[index];
523+ clone.disconnect(this._windowsDestroyedIds[index]);
524+
525 this._windows.splice(index, 1);
526+ this._windowsDestroyedIds.splice(index, 1);
527
528- clone.destroy();
529+ if (cloneDestroy)
530+ clone.destroy();
531 },
532
533 _doAddWindow(metaWin) {
534@@ -502,7 +510,11 @@ var WorkspaceThumbnail = new Lang.Class({
535 this._bgManager = null;
536 }
537
538+ for (let index = 0; index < this._windows.length; ++index)
539+ this._windows[index].disconnect(this._windowsDestroyedIds[index]);
540+
541 this._windows = [];
542+ this._windowsDestroyedIds = [];
543 this.actor = null;
544 },
545
546@@ -535,6 +547,10 @@ var WorkspaceThumbnail = new Lang.Class({
547 clone.connect('drag-end', () => {
548 Main.overview.endWindowDrag(clone.metaWindow);
549 });
550+ let cloneDestroyedId = clone.connect('destroy', () => {
551+ this._doRemoveWindow(clone.metaWindow, {cloneDestroy: false});
552+ });
553+
554 this._contents.add_actor(clone.actor);
555
556 if (this._windows.length == 0)
557@@ -543,6 +559,7 @@ var WorkspaceThumbnail = new Lang.Class({
558 clone.setStackAbove(this._windows[this._windows.length - 1].actor);
559
560 this._windows.push(clone);
561+ this._windowsDestroyedIds.push(cloneDestroyedId);
562
563 return clone;
564 },
0565
=== added file 'debian/patches/popupMenu-Fix-wrong-call-to-clutter_actor_add_child.patch'
--- debian/patches/popupMenu-Fix-wrong-call-to-clutter_actor_add_child.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/popupMenu-Fix-wrong-call-to-clutter_actor_add_child.patch 2018-04-17 10:30:40 +0000
@@ -0,0 +1,28 @@
1From: Mario Sanchez Prada <mario@endlessm.com>
2Date: Mon, 16 Apr 2018 05:47:57 -0500
3Subject: popupMenu: Fix wrong call to clutter_actor_add_child()
4
5Specify the horizontal alignment via the x_align property when creating
6the StIcon, since this function expects one argument, not two.
7
8Origin: https://gitlab.gnome.org/GNOME/gnome-shell/commit/cdbc99e
9---
10 js/ui/popupMenu.js | 5 +++--
11 1 file changed, 3 insertions(+), 2 deletions(-)
12
13diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js
14index 67b928c..83194d7 100644
15--- a/js/ui/popupMenu.js
16+++ b/js/ui/popupMenu.js
17@@ -394,8 +394,9 @@ var PopupImageMenuItem = new Lang.Class({
18 _init(text, icon, params) {
19 this.parent(params);
20
21- this._icon = new St.Icon({ style_class: 'popup-menu-icon' });
22- this.actor.add_child(this._icon, { align: St.Align.END });
23+ this._icon = new St.Icon({ style_class: 'popup-menu-icon',
24+ x_align: Clutter.ActorAlign.END });
25+ this.actor.add_child(this._icon);
26 this.label = new St.Label({ text: text });
27 this.actor.add_child(this.label);
28 this.actor.label_actor = this.label;
029
=== modified file 'debian/patches/series'
--- debian/patches/series 2018-04-14 01:50:15 +0000
+++ debian/patches/series 2018-04-17 10:30:40 +0000
@@ -11,5 +11,16 @@
11ubuntu_background_login.patch11ubuntu_background_login.patch
12ubuntu_gdm_alternatives.patch12ubuntu_gdm_alternatives.patch
13ubuntu_block_mode_extension_update.patch13ubuntu_block_mode_extension_update.patch
14ubuntu_theme_lookup_xdg.patch14ui-Theme-lookup-should-respect-XDG_DATA_DIRS.patch
15workaround_crasher_fractional_scaling.patch15workaround_crasher_fractional_scaling.patch
16shell-ignore-invalid-window-monitor-index.patch
17workspaceThumbnail-only-update-_porthole-if-the-overview-.patch
18workspaceThumbnail-rebuild-thumbnails-if-workareas-size-c.patch
19workspaceThumbnail-initialize-porthole-based-on-workArea.patch
20popupMenu-Fix-wrong-call-to-clutter_actor_add_child.patch
21StIcon-only-compute-shadow-pipeline-when-the-texture-is-p.patch
22volume-Add-back-sound-feedback-on-scroll.patch
23js-fix-invalid-access-errors.patch
24workspace-fix-repositioned-windows-in-activities.patch
25st-texture-cache-Cancel-sliced-image-loading-on-target-ac.patch
26st-texture-cache-Don-t-add-NULL-textures-to-cache.patch
1627
=== added file 'debian/patches/shell-ignore-invalid-window-monitor-index.patch'
--- debian/patches/shell-ignore-invalid-window-monitor-index.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/shell-ignore-invalid-window-monitor-index.patch 2018-04-17 10:30:40 +0000
@@ -0,0 +1,98 @@
1From: Sam Spilsbury <sam@endlessm.com>
2Date: Wed, 11 Oct 2017 05:42:04 -0500
3Subject: shell: ignore invalid window monitor index
4
5windowMenu: Check if monitorIndex is valid before using it
6
7Calling meta_window_get_monitor on an unmanaged window may return
8-1, so we need to check the return value.
9
10Fixes https://bugzilla.gnome.org/show_bug.cgi?id=788882
11
12keyboard: Handle case where keyboardMonitor is unset
13
14This may be the case where keyboardIndex is -1, which may be the
15case where either the keyboard monitor hasn't been set yet, or
16the keyboard is being unmanaged and meta_window_get_monitor
17returns -1
18
19https://bugzilla.gnome.org/show_bug.cgi?id=788882
20
21layout: Remove focusMonitor, as it is unused
22
23It also uses focusIndex to determine which monitor to
24return and may occassionally return undefined if focusIndex
25was -1.
26
27https://bugzilla.gnome.org/show_bug.cgi?id=788882
28
29Bug-GNOME: https://bugzilla.gnome.org/show_bug.cgi?id=788882
30Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1724439
31Forwarded: yes
32---
33 js/ui/keyboard.js | 8 ++++++++
34 js/ui/layout.js | 4 ----
35 js/ui/windowMenu.js | 7 ++++---
36 3 files changed, 12 insertions(+), 7 deletions(-)
37
38diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js
39index e13c7b7..14f6e7b 100644
40--- a/js/ui/keyboard.js
41+++ b/js/ui/keyboard.js
42@@ -939,6 +939,12 @@ var Keyboard = new Lang.Class({
43 if (this.actor == null)
44 return;
45 let monitor = Main.layoutManager.keyboardMonitor;
46+
47+ // monitor may be null here if the underlying keyboard monitor
48+ // index was still unset.
49+ if (!monitor)
50+ return;
51+
52 let maxHeight = monitor.height / 3;
53 this.actor.width = monitor.width;
54 this.actor.height = maxHeight;
55@@ -1001,6 +1007,8 @@ var Keyboard = new Lang.Class({
56 if (!this._enabled)
57 return;
58
59+
60+
61 this._clearShowIdle();
62 this._keyboardRequested = true;
63
64diff --git a/js/ui/layout.js b/js/ui/layout.js
65index 3d53bd4..cf0dad0 100644
66--- a/js/ui/layout.js
67+++ b/js/ui/layout.js
68@@ -564,10 +564,6 @@ var LayoutManager = new Lang.Class({
69 return i;
70 },
71
72- get focusMonitor() {
73- return this.monitors[this.focusIndex];
74- },
75-
76 set keyboardIndex(v) {
77 this._keyboardIndex = v;
78 this._updateKeyboardBox();
79diff --git a/js/ui/windowMenu.js b/js/ui/windowMenu.js
80index f0e564b..9bd7d19 100644
81--- a/js/ui/windowMenu.js
82+++ b/js/ui/windowMenu.js
83@@ -128,11 +128,12 @@ var WindowMenu = new Lang.Class({
84
85 let screen = global.screen;
86 let nMonitors = screen.get_n_monitors();
87- if (nMonitors > 1) {
88+ let monitorIndex = window.get_monitor();
89+ // meta_window_get_monitor can return -1, so handle that case
90+ // appropriately.
91+ if (nMonitors > 1 && monitorIndex >= 0) {
92 this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
93
94- let monitorIndex = window.get_monitor();
95-
96 let dir = Meta.ScreenDirection.UP;
97 let upMonitorIndex =
98 screen.get_monitor_neighbor_index(monitorIndex, dir);
099
=== added file 'debian/patches/st-texture-cache-Cancel-sliced-image-loading-on-target-ac.patch'
--- debian/patches/st-texture-cache-Cancel-sliced-image-loading-on-target-ac.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/st-texture-cache-Cancel-sliced-image-loading-on-target-ac.patch 2018-04-17 10:30:40 +0000
@@ -0,0 +1,118 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Wed, 29 Nov 2017 19:48:02 -0600
3Subject: st-texture-cache: Cancel sliced image loading on target actor
4 destroy
5
6It might happen that the target clutter actor that we return on call
7of st_texture_cache_load_sliced_image might be destroyed while the
8loading task is still running. To protect from this, let's connect
9to "destroy" signal and when this happens we use a cancellable to
10stop the task.
11
12This allows to safely reuse the return value of this function to
13cancel the execution and avoiding that load_callback is called
14even for a request that is not anymore under our control.
15
16Forwarded: yes, https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
17---
18 src/st/st-texture-cache.c | 30 ++++++++++++++++++++++++++----
19 1 file changed, 26 insertions(+), 4 deletions(-)
20
21diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c
22index e8a832d..13b019e 100644
23--- a/src/st/st-texture-cache.c
24+++ b/src/st/st-texture-cache.c
25@@ -1019,6 +1019,7 @@ typedef struct {
26 gint grid_width, grid_height;
27 gint scale_factor;
28 ClutterActor *actor;
29+ GCancellable *cancellable;
30 GFunc load_callback;
31 gpointer load_callback_data;
32 } AsyncImageData;
33@@ -1029,10 +1030,21 @@ on_data_destroy (gpointer data)
34 AsyncImageData *d = (AsyncImageData *)data;
35 g_object_unref (d->gfile);
36 g_object_unref (d->actor);
37+ g_object_unref (d->cancellable);
38 g_free (d);
39 }
40
41 static void
42+on_sliced_image_actor_destroyed (ClutterActor *actor,
43+ gpointer data)
44+{
45+ GTask *task = data;
46+ GCancellable *cancellable = g_task_get_cancellable (task);
47+
48+ g_cancellable_cancel (cancellable);
49+}
50+
51+static void
52 on_sliced_image_loaded (GObject *source_object,
53 GAsyncResult *res,
54 gpointer user_data)
55@@ -1042,7 +1054,7 @@ on_sliced_image_loaded (GObject *source_object,
56 GTask *task = G_TASK (res);
57 GList *list, *pixbufs;
58
59- if (g_task_had_error (task))
60+ if (g_task_had_error (task) || g_cancellable_is_cancelled (data->cancellable))
61 return;
62
63 pixbufs = g_task_propagate_pointer (task, NULL);
64@@ -1056,6 +1068,10 @@ on_sliced_image_loaded (GObject *source_object,
65
66 g_list_free_full (pixbufs, g_object_unref);
67
68+ g_signal_handlers_disconnect_by_func (data->actor,
69+ on_sliced_image_actor_destroyed,
70+ task);
71+
72 if (data->load_callback != NULL)
73 data->load_callback (cache, data->load_callback_data);
74 }
75@@ -1093,7 +1109,7 @@ load_sliced_image (GTask *result,
76 gchar *buffer = NULL;
77 gsize length;
78
79- g_assert (!cancellable);
80+ g_assert (cancellable);
81
82 data = task_data;
83 g_assert (data);
84@@ -1101,7 +1117,7 @@ load_sliced_image (GTask *result,
85 loader = gdk_pixbuf_loader_new ();
86 g_signal_connect (loader, "size-prepared", G_CALLBACK (on_loader_size_prepared), data);
87
88- if (!g_file_load_contents (data->gfile, NULL, &buffer, &length, NULL, &error))
89+ if (!g_file_load_contents (data->gfile, cancellable, &buffer, &length, NULL, &error))
90 {
91 g_warning ("Failed to open sliced image: %s", error->message);
92 goto out;
93@@ -1169,6 +1185,7 @@ st_texture_cache_load_sliced_image (StTextureCache *cache,
94 AsyncImageData *data;
95 GTask *result;
96 ClutterActor *actor = clutter_actor_new ();
97+ GCancellable *cancellable = g_cancellable_new ();
98
99 data = g_new0 (AsyncImageData, 1);
100 data->grid_width = grid_width;
101@@ -1176,11 +1193,16 @@ st_texture_cache_load_sliced_image (StTextureCache *cache,
102 data->scale_factor = scale;
103 data->gfile = g_object_ref (file);
104 data->actor = actor;
105+ data->cancellable = cancellable;
106 data->load_callback = load_callback;
107 data->load_callback_data = user_data;
108 g_object_ref (G_OBJECT (actor));
109
110- result = g_task_new (cache, NULL, on_sliced_image_loaded, data);
111+ result = g_task_new (cache, cancellable, on_sliced_image_loaded, data);
112+
113+ g_signal_connect (actor, "destroy",
114+ G_CALLBACK (on_sliced_image_actor_destroyed), result);
115+
116 g_task_set_task_data (result, data, on_data_destroy);
117 g_task_run_in_thread (result, load_sliced_image);
118
0119
=== added file 'debian/patches/st-texture-cache-Don-t-add-NULL-textures-to-cache.patch'
--- debian/patches/st-texture-cache-Don-t-add-NULL-textures-to-cache.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/st-texture-cache-Don-t-add-NULL-textures-to-cache.patch 2018-04-17 10:30:40 +0000
@@ -0,0 +1,92 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Tue, 17 Apr 2018 04:43:34 -0500
3Subject: st-texture-cache: Don't add NULL textures to cache
4
5This might cause a crash when cleaning up the cache as the hash table has
6cogl_object_unref as DestroyNotify function but that assumes that
7the passed object is a valid CoglObject.
8
9st-texture-cache: Save cairo surfaces to a different map
10
11The default keyed_surface is meant to handle CoglTextures thus we can't
12add cairo surfaces to it, as the DestroyNotify function won't handle them.
13
14Then the quicker way is to just add another Hash table for handling
15such types of textures, with proper destroy function.
16
17Forwarded: yes, https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/79
18Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/210
19Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1754445
20---
21 src/st/st-texture-cache.c | 16 ++++++++++++++--
22 1 file changed, 14 insertions(+), 2 deletions(-)
23
24diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c
25index 13b019e..168473b 100644
26--- a/src/st/st-texture-cache.c
27+++ b/src/st/st-texture-cache.c
28@@ -37,6 +37,7 @@ struct _StTextureCachePrivate
29
30 /* Things that were loaded with a cache policy != NONE */
31 GHashTable *keyed_cache; /* char * -> CoglTexture* */
32+ GHashTable *surfaces_keyed_cache; /* char * -> cairo_surface_t* */
33
34 /* Presently this is used to de-duplicate requests for GIcons and async URIs. */
35 GHashTable *outstanding_requests; /* char * -> AsyncTextureLoadData * */
36@@ -145,6 +146,10 @@ st_texture_cache_init (StTextureCache *self)
37
38 self->priv->keyed_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
39 g_free, cogl_object_unref);
40+ self->priv->surfaces_keyed_cache = g_hash_table_new_full (g_str_hash,
41+ g_str_equal,
42+ g_free,
43+ (GDestroyNotify) cairo_surface_destroy);
44 self->priv->outstanding_requests = g_hash_table_new_full (g_str_hash, g_str_equal,
45 g_free, NULL);
46 self->priv->file_monitors = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal,
47@@ -166,6 +171,7 @@ st_texture_cache_dispose (GObject *object)
48 }
49
50 g_clear_pointer (&self->priv->keyed_cache, g_hash_table_destroy);
51+ g_clear_pointer (&self->priv->surfaces_keyed_cache, g_hash_table_destroy);
52 g_clear_pointer (&self->priv->outstanding_requests, g_hash_table_destroy);
53 g_clear_pointer (&self->priv->file_monitors, g_hash_table_destroy);
54
55@@ -520,6 +526,8 @@ finish_texture_load (AsyncTextureLoadData *data,
56 goto out;
57
58 texdata = pixbuf_to_cogl_texture (pixbuf);
59+ if (!texdata)
60+ goto out;
61
62 if (data->policy != ST_TEXTURE_CACHE_POLICY_NONE)
63 {
64@@ -1295,6 +1303,9 @@ st_texture_cache_load_file_sync_to_cogl_texture (StTextureCache *cache,
65 texdata = pixbuf_to_cogl_texture (pixbuf);
66 g_object_unref (pixbuf);
67
68+ if (!texdata)
69+ goto out;
70+
71 if (policy == ST_TEXTURE_CACHE_POLICY_FOREVER)
72 {
73 cogl_object_ref (texdata);
74@@ -1326,7 +1337,7 @@ st_texture_cache_load_file_sync_to_cairo_surface (StTextureCache *cache,
75
76 key = g_strdup_printf (CACHE_PREFIX_FILE_FOR_CAIRO "%u", g_file_hash (file));
77
78- surface = g_hash_table_lookup (cache->priv->keyed_cache, key);
79+ surface = g_hash_table_lookup (cache->priv->surfaces_keyed_cache, key);
80
81 if (surface == NULL)
82 {
83@@ -1340,7 +1351,8 @@ st_texture_cache_load_file_sync_to_cairo_surface (StTextureCache *cache,
84 if (policy == ST_TEXTURE_CACHE_POLICY_FOREVER)
85 {
86 cairo_surface_reference (surface);
87- g_hash_table_insert (cache->priv->keyed_cache, g_strdup (key), surface);
88+ g_hash_table_insert (cache->priv->surfaces_keyed_cache,
89+ g_strdup (key), surface);
90 }
91 }
92 else
093
=== added file 'debian/patches/volume-Add-back-sound-feedback-on-scroll.patch'
--- debian/patches/volume-Add-back-sound-feedback-on-scroll.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/volume-Add-back-sound-feedback-on-scroll.patch 2018-04-17 10:30:40 +0000
@@ -0,0 +1,106 @@
1From: =?utf-8?q?Florian_M=C3=BCllner?= <fmuellner@gnome.org>
2Date: Fri, 23 Feb 2018 16:58:22 -0600
3Subject: volume: Add back sound feedback on scroll
4
5Commit 8d4855f1008 accidentally removed the volume change feedback
6for scroll events. Add it back to be consistent again with moving
7the slider via arrow keys, slider drags/clicks and gsd's media keys
8handling.
9
10https://gitlab.gnome.org/GNOME/gnome-shell/issues/53
11
12volume: Only emit sound feedback after volume changes
13
14gnome-settings-daemon doesn't play the volume change sound when
15the volume stayed the same (that is, it is already at its maximum
16or minimum). This looks like the right thing to do, so copy its
17behavior.
18
19https://gitlab.gnome.org/GNOME/gnome-shell/issues/53
20
21slider: Stop emulating drags in key handling
22
23Emitting ::drag-end after changing the slider value via arrow keys
24was a cheap way to make the sound feedback work for keyboard input.
25But now that the volume indicator plays the sound on ::value-changed
26as well, we can stop doing that - after all, key presses aren't drags.
27
28Besides that, this will make the limiting of feedback to actual volume
29changes from the previous commit work for key events as well.
30
31https://gitlab.gnome.org/GNOME/gnome-shell/issues/53
32
33Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/53
34Forwarded: yes, https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/51
35---
36 js/ui/slider.js | 2 --
37 js/ui/status/volume.js | 19 ++++++++++++++++++-
38 2 files changed, 18 insertions(+), 3 deletions(-)
39
40diff --git a/js/ui/slider.js b/js/ui/slider.js
41index 9853929..30295b4 100644
42--- a/js/ui/slider.js
43+++ b/js/ui/slider.js
44@@ -232,9 +232,7 @@ var Slider = new Lang.Class({
45 let delta = key == Clutter.KEY_Right ? 0.1 : -0.1;
46 this._value = Math.max(0, Math.min(this._value + delta, 1));
47 this.actor.queue_repaint();
48- this.emit('drag-begin');
49 this.emit('value-changed', this._value);
50- this.emit('drag-end');
51 return Clutter.EVENT_STOP;
52 }
53 return Clutter.EVENT_PROPAGATE;
54diff --git a/js/ui/status/volume.js b/js/ui/status/volume.js
55index 65c4c42..c0f9cf3 100644
56--- a/js/ui/status/volume.js
57+++ b/js/ui/status/volume.js
58@@ -4,6 +4,7 @@ const Clutter = imports.gi.Clutter;
59 const Lang = imports.lang;
60 const Gio = imports.gi.Gio;
61 const Gvc = imports.gi.Gvc;
62+const Mainloop = imports.mainloop;
63 const St = imports.gi.St;
64 const Signals = imports.signals;
65
66@@ -36,9 +37,16 @@ var StreamSlider = new Lang.Class({
67
68 this.item = new PopupMenu.PopupBaseMenuItem({ activate: false });
69
70+ this._inDrag = false;
71+ this._notifyVolumeChangeId = 0;
72+
73 this._slider = new Slider.Slider(0);
74+ this._slider.connect('drag-begin', () => { this._inDrag = true; });
75 this._slider.connect('value-changed', this._sliderChanged.bind(this));
76- this._slider.connect('drag-end', this._notifyVolumeChange.bind(this));
77+ this._slider.connect('drag-end', () => {
78+ this._inDrag = false;
79+ this._notifyVolumeChange();
80+ });
81
82 this._icon = new St.Icon({ style_class: 'popup-menu-icon' });
83 this.item.actor.add(this._icon);
84@@ -135,6 +143,7 @@ var StreamSlider = new Lang.Class({
85
86 let volume = value * this._get_control_max_volume();
87 let prevMuted = this._stream.is_muted;
88+ let prevVolume = this._stream.volume;
89 if (volume < 1) {
90 this._stream.volume = 0;
91 if (!prevMuted)
92@@ -145,6 +154,14 @@ var StreamSlider = new Lang.Class({
93 this._stream.change_is_muted(false);
94 }
95 this._stream.push_volume();
96+
97+ let volumeChanged = this._stream.volume != prevVolume;
98+ if (volumeChanged && !this._notifyVolumeChangeId && !this._inDrag)
99+ this._notifyVolumeChangeId = Mainloop.timeout_add(30, () => {
100+ this._notifyVolumeChange();
101+ this._notifyVolumeChangeId = 0;
102+ return GLib.SOURCE_REMOVE;
103+ });
104 },
105
106 _notifyVolumeChange() {
0107
=== added file 'debian/patches/workspace-fix-repositioned-windows-in-activities.patch'
--- debian/patches/workspace-fix-repositioned-windows-in-activities.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/workspace-fix-repositioned-windows-in-activities.patch 2018-04-17 10:30:40 +0000
@@ -0,0 +1,148 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Fri, 19 Jan 2018 08:00:10 -0600
3Subject: workspace: fix repositioned windows in activities
4
5workspace: Recompute bounding box on window 'position-changed'
6
7We need to update the clone position if window size changed
8also, rename meta window 'size-changed' callback accordingly.
9
10https://bugzilla.gnome.org/show_bug.cgi?id=792681
11
12workspaceThumbnail: Sync clone position changes with actor
13
14We need to update the clone position if window actor (not the meta window)
15position changed.
16
17https://bugzilla.gnome.org/show_bug.cgi?id=792681
18
19Bug-GNOME: https://bugzilla.gnome.org/show_bug.cgi?id=776588
20Bug-Ubuntu: https://bugs.launchpad.net/gnome-shell/+bug/1653153
21Forwarded: yes, https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/8
22---
23 js/ui/workspace.js | 28 +++++++++++++++-------------
24 js/ui/workspaceThumbnail.js | 9 ++++-----
25 2 files changed, 19 insertions(+), 18 deletions(-)
26
27diff --git a/js/ui/workspace.js b/js/ui/workspace.js
28index 8836537..f06b78e 100644
29--- a/js/ui/workspace.js
30+++ b/js/ui/workspace.js
31@@ -137,8 +137,10 @@ var WindowClone = new Lang.Class({
32 this._dragSlot = [0, 0, 0, 0];
33 this._stackAbove = null;
34
35- this._windowClone._updateId = this.metaWindow.connect('size-changed',
36- this._onRealWindowSizeChanged.bind(this));
37+ this._windowClone._sizeChangedId = this.metaWindow.connect('size-changed',
38+ this._onMetaWindowSizeChanged.bind(this));
39+ this._windowClone._posChangedId = this.metaWindow.connect('position-changed',
40+ this._computeBoundingBox.bind(this));
41 this._windowClone._destroyId = this.realWindow.connect('destroy',
42 this.destroy.bind(this));
43
44@@ -200,8 +202,7 @@ var WindowClone = new Lang.Class({
45
46 addAttachedDialog(win) {
47 this._doAddAttachedDialog(win, win.get_compositor_private());
48- this._computeBoundingBox();
49- this.emit('size-changed');
50+ this._onMetaWindowSizeChanged();
51 },
52
53 hasAttachedDialogs() {
54@@ -210,15 +211,14 @@ var WindowClone = new Lang.Class({
55
56 _doAddAttachedDialog(metaWin, realWin) {
57 let clone = new Clutter.Clone({ source: realWin });
58- clone._updateId = metaWin.connect('size-changed', () => {
59- this._computeBoundingBox();
60- this.emit('size-changed');
61- });
62+ clone._sizeChangedId = metaWin.connect('size-changed',
63+ this._onMetaWindowSizeChanged.bind(this));
64+ clone._posChangedId = metaWin.connect('position-changed',
65+ this._onMetaWindowSizeChanged.bind(this));
66 clone._destroyId = realWin.connect('destroy', () => {
67 clone.destroy();
68
69- this._computeBoundingBox();
70- this.emit('size-changed');
71+ this._onMetaWindowSizeChanged.bind(this);
72 });
73 this.actor.add_child(clone);
74 },
75@@ -308,7 +308,8 @@ var WindowClone = new Lang.Class({
76
77 // First destroy the clone and then destroy everything
78 // This will ensure that we never see it in the _disconnectSignals loop
79- this.metaWindow.disconnect(this._windowClone._updateId);
80+ this.metaWindow.disconnect(this._windowClone._sizeChangedId);
81+ this.metaWindow.disconnect(this._windowClone._posChangedId);
82 this.realWindow.disconnect(this._windowClone._destroyId);
83 this._windowClone.destroy();
84
85@@ -323,12 +324,13 @@ var WindowClone = new Lang.Class({
86 else
87 realWindow = child.source;
88
89- realWindow.meta_window.disconnect(child._updateId);
90+ realWindow.meta_window.disconnect(child._sizeChangedId);
91+ realWindow.meta_window.disconnect(child._posChangedId);
92 realWindow.disconnect(child._destroyId);
93 });
94 },
95
96- _onRealWindowSizeChanged() {
97+ _onMetaWindowSizeChanged() {
98 this._computeBoundingBox();
99 this.emit('size-changed');
100 },
101diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js
102index 0c72e74..4db8c19 100644
103--- a/js/ui/workspaceThumbnail.js
104+++ b/js/ui/workspaceThumbnail.js
105@@ -68,7 +68,7 @@ var WindowClone = new Lang.Class({
106 this.realWindow = realWindow;
107 this.metaWindow = realWindow.meta_window;
108
109- this.clone._updateId = this.metaWindow.connect('position-changed',
110+ this.clone._updateId = this.realWindow.connect('notify::position',
111 this._onPositionChanged.bind(this));
112 this.clone._destroyId = this.realWindow.connect('destroy', this.destroy.bind(this));
113 this._onPositionChanged();
114@@ -141,7 +141,7 @@ var WindowClone = new Lang.Class({
115
116 // First destroy the clone and then destroy everything
117 // This will ensure that we never see it in the _disconnectSignals loop
118- this.metaWindow.disconnect(this.clone._updateId);
119+ this.realWindow.disconnect(this.clone._updateId);
120 this.realWindow.disconnect(this.clone._destroyId);
121 this.clone.destroy();
122
123@@ -156,7 +156,7 @@ var WindowClone = new Lang.Class({
124 let clone = new Clutter.Clone({ source: realDialog });
125 this._updateDialogPosition(realDialog, clone);
126
127- clone._updateId = metaDialog.connect('position-changed', dialog => {
128+ clone._updateId = metaDialog.connect('notify::position', dialog => {
129 this._updateDialogPosition(dialog, clone);
130 });
131 clone._destroyId = realDialog.connect('destroy', () => {
132@@ -174,7 +174,6 @@ var WindowClone = new Lang.Class({
133 },
134
135 _onPositionChanged() {
136- let rect = this.metaWindow.get_frame_rect();
137 this.actor.set_position(this.realWindow.x, this.realWindow.y);
138 },
139
140@@ -182,7 +181,7 @@ var WindowClone = new Lang.Class({
141 this.actor.get_children().forEach(child => {
142 let realWindow = child.source;
143
144- realWindow.meta_window.disconnect(child._updateId);
145+ realWindow.disconnect(child._updateId);
146 realWindow.disconnect(child._destroyId);
147 });
148 },
0149
=== added file 'debian/patches/workspaceThumbnail-initialize-porthole-based-on-workArea.patch'
--- debian/patches/workspaceThumbnail-initialize-porthole-based-on-workArea.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/workspaceThumbnail-initialize-porthole-based-on-workArea.patch 2018-04-17 10:30:40 +0000
@@ -0,0 +1,36 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Fri, 19 Jan 2018 10:37:20 -0600
3Subject: workspaceThumbnail: initialize porthole based on workArea
4
5https://bugzilla.gnome.org/show_bug.cgi?id=792687
6
7Bug-GNOME: https://bugzilla.gnome.org/show_bug.cgi?id=792687
8Origin: https://gitlab.gnome.org/GNOME/gnome-shell/commit/b99e304
9---
10 js/ui/workspaceThumbnail.js | 6 ++----
11 1 file changed, 2 insertions(+), 4 deletions(-)
12
13diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js
14index 3dffd12..c1b4bdd 100644
15--- a/js/ui/workspaceThumbnail.js
16+++ b/js/ui/workspaceThumbnail.js
17@@ -275,8 +275,8 @@ var WorkspaceThumbnail = new Lang.Class({
18
19 this._createBackground();
20
21- let monitor = Main.layoutManager.primaryMonitor;
22- this.setPorthole(monitor.x, monitor.y, monitor.width, monitor.height);
23+ let workArea = Main.layoutManager.getWorkAreaForMonitor(this.monitorIndex);
24+ this.setPorthole(workArea.x, workArea.y, workArea.width, workArea.height);
25
26 let windows = global.get_window_actors().filter(actor => {
27 let win = actor.meta_window;
28@@ -321,8 +321,6 @@ var WorkspaceThumbnail = new Lang.Class({
29 },
30
31 setPorthole(x, y, width, height) {
32- this._portholeX = x;
33- this._portholeY = y;
34 this.actor.set_size(width, height);
35 this._contents.set_position(-x, -y);
36 },
037
=== added file 'debian/patches/workspaceThumbnail-only-update-_porthole-if-the-overview-.patch'
--- debian/patches/workspaceThumbnail-only-update-_porthole-if-the-overview-.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/workspaceThumbnail-only-update-_porthole-if-the-overview-.patch 2018-04-17 10:30:40 +0000
@@ -0,0 +1,29 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Fri, 19 Jan 2018 09:31:01 -0600
3Subject: workspaceThumbnail: only update _porthole if the overview is visible
4
5Otherwise it happens that porthole is computed again after that the
6overlay is hidden (triggered by a layout reallocation) and thus not
7regenerated again afterwards.
8
9https://bugzilla.gnome.org/show_bug.cgi?id=792687
10
11Bug-GNOME: https://bugzilla.gnome.org/show_bug.cgi?id=792687
12Origin: https://gitlab.gnome.org/GNOME/gnome-shell/commit/5fcf40b
13---
14 js/ui/workspaceThumbnail.js | 2 +-
15 1 file changed, 1 insertion(+), 1 deletion(-)
16
17diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js
18index 7d5d2c0..5565a1e 100644
19--- a/js/ui/workspaceThumbnail.js
20+++ b/js/ui/workspaceThumbnail.js
21@@ -1159,7 +1159,7 @@ var ThumbnailsBox = new Lang.Class({
22 // The "porthole" is the portion of the screen that we show in the
23 // workspaces
24 _ensurePorthole() {
25- if (!Main.layoutManager.primaryMonitor)
26+ if (!Main.layoutManager.primaryMonitor || !Main.overview.visible)
27 return false;
28
29 if (!this._porthole)
030
=== added file 'debian/patches/workspaceThumbnail-rebuild-thumbnails-if-workareas-size-c.patch'
--- debian/patches/workspaceThumbnail-rebuild-thumbnails-if-workareas-size-c.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/workspaceThumbnail-rebuild-thumbnails-if-workareas-size-c.patch 2018-04-17 10:30:40 +0000
@@ -0,0 +1,64 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Fri, 19 Jan 2018 09:39:13 -0600
3Subject: workspaceThumbnail: rebuild thumbnails if workareas size changed
4
5https://bugzilla.gnome.org/show_bug.cgi?id=792687
6
7Origin: https://gitlab.gnome.org/GNOME/gnome-shell/commit/c29bd46
8Bug-GNOME: https://bugzilla.gnome.org/show_bug.cgi?id=792687
9---
10 js/ui/workspaceThumbnail.js | 21 ++++++++++++++++-----
11 1 file changed, 16 insertions(+), 5 deletions(-)
12
13diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js
14index 5565a1e..3dffd12 100644
15--- a/js/ui/workspaceThumbnail.js
16+++ b/js/ui/workspaceThumbnail.js
17@@ -675,11 +675,7 @@ var ThumbnailsBox = new Lang.Class({
18 this._settings.connect('changed::dynamic-workspaces',
19 this._updateSwitcherVisibility.bind(this));
20
21- Main.layoutManager.connect('monitors-changed', () => {
22- this._destroyThumbnails();
23- if (Main.overview.visible)
24- this._createThumbnails();
25- });
26+ Main.layoutManager.connect('monitors-changed', this._rebuildThumbnails.bind(this));
27 },
28
29 _updateSwitcherVisibility() {
30@@ -872,6 +868,9 @@ var ThumbnailsBox = new Lang.Class({
31 Main.overview.connect('windows-restacked',
32 this._syncStacking.bind(this));
33
34+ this._workareasChangedId =
35+ global.screen.connect('workareas-changed', this._rebuildThumbnails.bind(this));
36+
37 this._targetScale = 0;
38 this._scale = 0;
39 this._pendingScaleUpdate = false;
40@@ -901,12 +900,24 @@ var ThumbnailsBox = new Lang.Class({
41 this._syncStackingId = 0;
42 }
43
44+ if (this._workareasChangedId > 0) {
45+ global.screen.disconnect(this._workareasChangedId);
46+ this._workareasChangedId = 0;
47+ }
48+
49 for (let w = 0; w < this._thumbnails.length; w++)
50 this._thumbnails[w].destroy();
51 this._thumbnails = [];
52 this._porthole = null;
53 },
54
55+ _rebuildThumbnails() {
56+ this._destroyThumbnails();
57+
58+ if (Main.overview.visible)
59+ this._createThumbnails();
60+ },
61+
62 _workspacesChanged() {
63 let validThumbnails =
64 this._thumbnails.filter(t => t.state <= ThumbnailState.NORMAL);

Subscribers

People subscribed via source and target branches