autoActivities.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /****************************************************************************
  2. ** Auto Activities - Show activities overlay when there are no windows.
  3. ** Copyright (C) 2022-2023 Cleo Menezes Jr., 2021 jan Sena <mi-jan-sena@proton.me>
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. ****************************************************************************/
  18. "use strict";
  19. import * as Main from "resource:///org/gnome/shell/ui/main.js";
  20. import GLib from "gi://GLib";
  21. import GObject from "gi://GObject";
  22. import St from "gi://St";
  23. import Meta from "gi://Meta";
  24. let windowCheckingDelay;
  25. const ignoredWindowTypes = [
  26. Meta.WindowType.DROPDOWN_MENU,
  27. Meta.WindowType.NOTIFICATION,
  28. Meta.WindowType.POPUP_MENU,
  29. Meta.WindowType.SPLASHSCREEN,
  30. ];
  31. export const AutoActivitiesManager = GObject.registerClass(
  32. class ActivitiesManager extends St.Bin {
  33. _init({ remoteModel, monitorIndex, settings }) {
  34. this._remoteModel = remoteModel;
  35. this._monitorIndex = monitorIndex;
  36. this._windowRemovedEvents = [];
  37. this._windowAddedEvents = [];
  38. this._settings = settings;
  39. for (let i = 0; i < global.workspace_manager.n_workspaces; i++) {
  40. this._onWorkspaceAdded(global.workspace_manager, i);
  41. }
  42. this._workspaceAddedEvent = global.workspace_manager.connect(
  43. "workspace-added",
  44. this._onWorkspaceAdded.bind(this),
  45. );
  46. this._workspaceRemovedEvent = global.workspace_manager.connect(
  47. "workspace-removed",
  48. this._onWorkspaceRemoved.bind(this),
  49. );
  50. this._workspaceSwitchedEvent = global.workspace_manager.connect(
  51. "workspace-switched",
  52. this._onWorkspaceSwitched.bind(this),
  53. );
  54. this._workspacesReorderedEvent = global.workspace_manager.connect(
  55. "workspaces-reordered",
  56. this._onWorkspacesReordered.bind(this),
  57. );
  58. this._minimizedEvent = global.window_manager.connect(
  59. "minimize",
  60. this._onWindowMinimized.bind(this),
  61. );
  62. }
  63. _onWorkspaceAdded(_sender, workspaceIndex) {
  64. let windowRemovedEvent = global.workspace_manager
  65. .get_workspace_by_index(workspaceIndex)
  66. .connect("window-removed", this._onWindowRemoved.bind(this));
  67. this._windowRemovedEvents.push(windowRemovedEvent);
  68. let windowAddedEvent = global.workspace_manager
  69. .get_workspace_by_index(workspaceIndex)
  70. .connect("window-added", this._onWindowAdded.bind(this));
  71. this._windowAddedEvents.push(windowAddedEvent);
  72. }
  73. _onWorkspaceRemoved(_sender, workspaceIndex) {
  74. if (workspaceIndex < this._windowRemovedEvents.length) {
  75. this._windowRemovedEvents.splice(workspaceIndex);
  76. this._windowAddedEvents.splice(workspaceIndex);
  77. }
  78. }
  79. _onWorkspaceSwitched(
  80. _sender,
  81. _oldWorkspaceIndex,
  82. _newWorkspaceIndex,
  83. _direction,
  84. ) {
  85. if (!this._settings.get_boolean("skip-last-workspace")) {
  86. this._checkAndShowOverview();
  87. }
  88. }
  89. _onWorkspacesReordered(_sender) {
  90. let firstWorkspaceIndex = -1;
  91. let secondWorkspaceIndex = -1;
  92. for (let i = 0; i < this._windowRemovedEvents.length; i++) {
  93. if (
  94. GObject.signal_handler_is_connected(
  95. global.workspace_manager.get_workspace_by_index(i),
  96. this._windowRemovedEvents[i],
  97. )
  98. ) {
  99. if (firstWorkspaceIndex < 0) firstWorkspaceIndex = i;
  100. else secondWorkspaceIndex = i;
  101. }
  102. }
  103. let tempFirstWorkspaceRemovedEvent =
  104. this._windowRemovedEvents[firstWorkspaceIndex];
  105. this._windowRemovedEvents[firstWorkspaceIndex] =
  106. this._windowRemovedEvents[secondWorkspaceIndex];
  107. this._windowRemovedEvents[secondWorkspaceIndex] =
  108. tempFirstWorkspaceRemovedEvent;
  109. let tempFirstWorkspaceAddedEvent =
  110. this._windowAddedEvents[firstWorkspaceIndex];
  111. this._windowAddedEvents[firstWorkspaceIndex] =
  112. this._windowAddedEvents[secondWorkspaceIndex];
  113. this._windowAddedEvents[secondWorkspaceIndex] =
  114. tempFirstWorkspaceAddedEvent;
  115. }
  116. _onWindowMinimized(_sender, actor) {
  117. if (
  118. this._settings.get_boolean("detect-minimized") &&
  119. !ignoredWindowTypes.includes(actor.meta_window.get_window_type())
  120. ) {
  121. this._checkAndShowOverview();
  122. }
  123. }
  124. _onWindowRemoved(_sender, removedWindow) {
  125. if (!ignoredWindowTypes.includes(removedWindow.get_window_type())) {
  126. this._checkAndShowOverview();
  127. }
  128. }
  129. _onWindowAdded(_sender, addedWindow) {
  130. if (
  131. !ignoredWindowTypes.includes(addedWindow.get_window_type()) &&
  132. this._settings.get_boolean("hide-on-new-window")
  133. ) {
  134. if (Main.overview.visible) Main.overview.hide();
  135. }
  136. }
  137. _checkAndShowOverview() {
  138. let delay = 0;
  139. let delaySetting = this._settings.get_int("window-checking-delay");
  140. if (!isNaN(delaySetting) && delaySetting > 0) delay = delaySetting;
  141. windowCheckingDelay = GLib.timeout_add(
  142. GLib.PRIORITY_DEFAULT,
  143. delay,
  144. () => {
  145. let windows = global.get_window_actors();
  146. if (this._settings.get_boolean("isolate-workspaces")) {
  147. windows = windows.filter(
  148. (window) =>
  149. window.meta_window.get_workspace().index() ===
  150. global.workspace_manager.get_active_workspace().index(),
  151. );
  152. }
  153. if (this._settings.get_boolean("isolate-monitors")) {
  154. windows = windows.filter(
  155. (window) =>
  156. window.meta_window.get_monitor() === this._monitorIndex,
  157. );
  158. }
  159. if (this._settings.get_boolean("skip-taskbar")) {
  160. windows = windows.filter(
  161. (window) => !window.meta_window.skip_taskbar,
  162. );
  163. }
  164. if (this._settings.get_boolean("detect-minimized")) {
  165. windows = windows.filter((window) => !window.meta_window.minimized);
  166. }
  167. if (windows.length < 1) {
  168. if (this._settings.get_boolean("show-apps")) {
  169. Main.overview
  170. .showApps();
  171. } else Main.overview.show();
  172. }
  173. },
  174. );
  175. }
  176. destroy() {
  177. global.workspace_manager.disconnect(this._workspaceAddedEvent);
  178. global.workspace_manager.disconnect(this._workspaceRemovedEvent);
  179. global.workspace_manager.disconnect(this._workspaceSwitchedEvent);
  180. global.workspace_manager.disconnect(this._workspacesReorderedEvent);
  181. global.window_manager.disconnect(this._minimizedEvent);
  182. for (let i = 0; i < this._windowRemovedEvents.length; i++) {
  183. if (
  184. GObject.signal_handler_is_connected(
  185. global.workspace_manager.get_workspace_by_index(i),
  186. this._windowRemovedEvents[i],
  187. )
  188. ) {
  189. global.workspace_manager
  190. .get_workspace_by_index(i)
  191. .disconnect(this._windowRemovedEvents[i]);
  192. }
  193. }
  194. for (let i = 0; i < this._windowAddedEvents.length; i++) {
  195. if (
  196. GObject.signal_handler_is_connected(
  197. global.workspace_manager.get_workspace_by_index(i),
  198. this._windowAddedEvents[i],
  199. )
  200. ) {
  201. global.workspace_manager
  202. .get_workspace_by_index(i)
  203. .disconnect(this._windowAddedEvents[i]);
  204. }
  205. }
  206. GLib.Source.remove(windowCheckingDelay);
  207. }
  208. },
  209. );