0001-tweener-Remove-handlers-on-target.patch 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. From 5cd8acebe8461850667215b4c6b19e9ebf4c82f2 Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
  3. Date: Tue, 5 Dec 2017 02:41:50 +0100
  4. Subject: [PATCH] tweener: Save handlers on target and remove them on destroy
  5. Cherry picked from commit 28ac564b568e4546d32728b426e9d0414e95d30d.
  6. A tweener onComplete handler could be called when the target actor has already
  7. been destroyed, and this could lead accessing to invalid properties of it.
  8. So, wrap the handlers with lambda functions that we delete them when the object
  9. state so that they are not called anymore after this point.
  10. https://bugzilla.gnome.org/show_bug.cgi?id=791233
  11. https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/4
  12. ---
  13. js/ui/tweener.js | 56 +++++++++++++++++++++++++++++++++++++-----------
  14. 1 file changed, 44 insertions(+), 12 deletions(-)
  15. diff --git a/js/ui/tweener.js b/js/ui/tweener.js
  16. index bb9ea557c..25338367d 100644
  17. --- a/js/ui/tweener.js
  18. +++ b/js/ui/tweener.js
  19. @@ -63,30 +63,62 @@ function _getTweenState(target) {
  20. return target.__ShellTweenerState;
  21. }
  22. +function _ensureHandlers(target) {
  23. + if (!target.__ShellTweenerHandlers)
  24. + target.__ShellTweenerHandlers = new Map();
  25. + return target.__ShellTweenerHandlers;
  26. +}
  27. +
  28. function _resetTweenState(target) {
  29. let state = target.__ShellTweenerState;
  30. if (state) {
  31. - if (state.destroyedId)
  32. + if (state.destroyedId) {
  33. state.actor.disconnect(state.destroyedId);
  34. + delete state.destroyedId;
  35. + }
  36. }
  37. + _removeHandler(target, 'onComplete', _tweenCompleted);
  38. target.__ShellTweenerState = {};
  39. }
  40. function _addHandler(target, params, name, handler) {
  41. - if (params[name]) {
  42. - let oldHandler = params[name];
  43. - let oldScope = params[name + 'Scope'];
  44. - let oldParams = params[name + 'Params'];
  45. - let eventScope = oldScope ? oldScope : target;
  46. + let wrapperNeeded = false;
  47. + let tweenerHandlers = _ensureHandlers(target);
  48. - params[name] = () => {
  49. - oldHandler.apply(eventScope, oldParams);
  50. - handler(target);
  51. - };
  52. - } else
  53. - params[name] = () => { handler(target); };
  54. + if (!tweenerHandlers.has(name)) {
  55. + tweenerHandlers.set(name, []);
  56. + wrapperNeeded = true;
  57. + }
  58. +
  59. + let handlers = tweenerHandlers.get(name);
  60. + handlers.push(handler);
  61. +
  62. + if (wrapperNeeded) {
  63. + if (params[name]) {
  64. + let oldHandler = params[name];
  65. + let oldScope = params[`${name}Scope`];
  66. + let oldParams = params[`${name}Params`];
  67. + let eventScope = oldScope ? oldScope : target;
  68. +
  69. + params[name] = () => {
  70. + oldHandler.apply(eventScope, oldParams);
  71. + handlers.forEach(h => h(target));
  72. + };
  73. + } else {
  74. + params[name] = () => handlers.forEach(h => h(target));
  75. + }
  76. + }
  77. +}
  78. +
  79. +function _removeHandler(target, name, handler) {
  80. + let tweenerHandlers = _ensureHandlers(target);
  81. +
  82. + if (tweenerHandlers.has(name)) {
  83. + let handlers = tweenerHandlers.get(name).filter(h => h != handler);
  84. + tweenerHandlers.set(name, handlers);
  85. + }
  86. }
  87. function _actorDestroyed(target) {
  88. --
  89. 2.22.0