From 54897d0cefb2d854f7c4f9efecf1d7c5e6f3db1a Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Fri, 10 Feb 2023 10:12:06 -0500 Subject: [PATCH 01/30] trash@cinnamon.org: Refactor to use asynchronous methods entirely. --- .../applets/trash@cinnamon.org/applet.js | 83 +++++++++++++++---- 1 file changed, 65 insertions(+), 18 deletions(-) diff --git a/files/usr/share/cinnamon/applets/trash@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/trash@cinnamon.org/applet.js index eb51d1435a..13e3deb992 100644 --- a/files/usr/share/cinnamon/applets/trash@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/trash@cinnamon.org/applet.js @@ -1,6 +1,7 @@ const St = imports.gi.St; const ModalDialog = imports.ui.modalDialog; const Gio = imports.gi.Gio; +const GLib = imports.gi.GLib; const Lang = imports.lang; const Applet = imports.ui.applet; const PopupMenu = imports.ui.popupMenu; @@ -16,17 +17,20 @@ class CinnamonTrashApplet extends Applet.IconApplet { this.set_applet_icon_symbolic_name("user-trash"); this.set_applet_tooltip(_("Trash")); - this.trash_path = 'trash:///'; - this.trash_directory = Gio.file_new_for_uri(this.trash_path); - - this._initContextMenu(); - this.trash_changed_timeout = 0; - this._onTrashChange(); - - this.monitor = this.trash_directory.monitor_directory(0, null); - this.monitor.connect('changed', Lang.bind(this, this._onTrashChange)); + const vfs = Gio.Vfs.get_default() + if (vfs.get_supported_uri_schemes().includes("trash")) { + this._initContextMenu(); + + this.trash_path = 'trash:///'; + this.trash_directory = Gio.file_new_for_uri(this.trash_path); + this._onTrashChange(); + } else { + this.trash_directory = null; + global.logWarning("trash@cinnamon.org: No trash support, disabling.") + this.actor.hide(); + } } _initContextMenu() { @@ -47,6 +51,28 @@ class CinnamonTrashApplet extends Applet.IconApplet { this._openTrash(); } + on_applet_added_to_panel() { + if (this.trash_directory == null) { + return; + } + + this.monitor = this.trash_directory.monitor_directory(0, null); + this.monitor_changed_id = this.monitor.connect('changed', Lang.bind(this, this._onTrashChange)); + } + + on_applet_removed_from_panel() { + if (this.trash_directory == null) { + return; + } + + if (this.monitor_changed_id > 0) { + this.monitor.disconnect(this.monitor_changed_id); + this.monitor_changed_id = 0; + } + + this.moniitor = 0; + } + _openTrash() { Gio.app_info_launch_default_for_uri(this.trash_directory.get_uri(), null); } @@ -57,19 +83,40 @@ class CinnamonTrashApplet extends Applet.IconApplet { this.trash_changed_timeout = 0; } - this.trash_changed_timeout = Mainloop.timeout_add_seconds(1, Lang.bind(this, this._onTrashChangeTimeout)); + this.trash_changed_timeout = Mainloop.idle_add(Lang.bind(this, this._onTrashChangeTimeout), GLib.PRIORITY_LOW); } _onTrashChangeTimeout() { this.trash_changed_timeout = 0; - if (this.trash_directory.query_exists(null)) { - let children = this.trash_directory.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NONE, null); - if (children.next_file(null) == null) { - this.set_applet_icon_symbolic_name("user-trash"); - } else { - this.set_applet_icon_symbolic_name("user-trash-full"); - } - children.close(null); + const children = this.trash_directory.enumerate_children_async( + 'standard::*', + Gio.FileQueryInfoFlags.NONE, + GLib.PRIORITY_LOW, + null, + (...args) => this._enumerateChildrenCallback(...args) + ); + + return GLib.SOURCE_REMOVE; + } + + _enumerateChildrenCallback(file, result) { + try { + const child_info = file.enumerate_children_finish(result); + child_info.next_files_async( + 1, + GLib.PRIORITY_LOW, + null, + (enumerator, res) => { + file = enumerator.next_files_finish(res); + if (file.length > 0) { + this.set_applet_icon_symbolic_name("user-trash-full"); + } else { + this.set_applet_icon_symbolic_name("user-trash"); + } + } + ); + } catch(e) { + global.logWarning(`Could not check trash uri: ${e.message}`); } } From bbdfdadb80199a13c2f8e0eac7829c33df85ed0d Mon Sep 17 00:00:00 2001 From: Bobby Rong Date: Tue, 14 Feb 2023 03:03:12 +0800 Subject: [PATCH 02/30] cs_themes: load theme thumbnail from XDG_DATA_DIRS (#11497) On NixOS themes are installed in /run/current-system/sw/share/{icons,themes} This makes theme thumbnail missing on NixOS because we don't search those paths. Let's follow https://freedesktop.org/wiki/DesktopThemeSpec/ and look for cursor themes and GTK themes in XDG_DATA_DIRS. --- .../share/cinnamon/cinnamon-settings/modules/cs_themes.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py index e64f89798c..d646234ff7 100755 --- a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py +++ b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py @@ -319,10 +319,10 @@ def create_button_chooser(self, settings, key, path_prefix, path_suffix, button_ chooser.set_picture_from_file(path) else: try: - for path in ["/usr/share/%s/%s/%s/thumbnail.png" % (path_prefix, theme, path_suffix), - os.path.expanduser("~/.%s/%s/%s/thumbnail.png" % (path_prefix, theme, path_suffix)), + for path in ([os.path.join(datadir, path_prefix, theme, path_suffix, "thumbnail.png") for datadir in GLib.get_system_data_dirs()] + + [os.path.expanduser("~/.%s/%s/%s/thumbnail.png" % (path_prefix, theme, path_suffix)), "/usr/share/cinnamon/thumbnails/%s/%s.png" % (path_suffix, theme), - "/usr/share/cinnamon/thumbnails/%s/unknown.png" % path_suffix]: + "/usr/share/cinnamon/thumbnails/%s/unknown.png" % path_suffix]): if os.path.exists(path): chooser.set_picture_from_file(path) break From b475c392f749d52524a90d6bc2408cfcf2c8d09b Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Tue, 21 Feb 2023 09:09:59 -0500 Subject: [PATCH 03/30] gwl: Fix typo. ref: 3779122e2b08a236273c37fdb92 Maybe fixes #11524. --- .../applets/grouped-window-list@cinnamon.org/appGroup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appGroup.js b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appGroup.js index fc1f892604..9ca6b37d5a 100644 --- a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appGroup.js +++ b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appGroup.js @@ -309,7 +309,7 @@ class AppGroup { } flashButton() { - if (!this._needsAttention || !this.actor || this._flashTimer) + if (!this._needsAttention || !this.actor || this.flashTimer) return; if (!this.groupState.groupReady && this.groupState.isFavoriteApp) From cce92b0db7e4fdd1826100a34ec5859edf37b7d8 Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Tue, 21 Feb 2023 09:31:07 -0500 Subject: [PATCH 04/30] sound applet: Clear the source ID in Seeker._timerCallback(). ref: #11519. --- .../applets/sound@cinnamon.org/applet.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/files/usr/share/cinnamon/applets/sound@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/sound@cinnamon.org/applet.js index 9bdd5a036d..a6eb90ea32 100644 --- a/files/usr/share/cinnamon/applets/sound@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/sound@cinnamon.org/applet.js @@ -333,14 +333,15 @@ class Seeker extends Slider.Slider { this._timerTicker = 0; this._getPosition(); } - return true; + return GLib.SOURCE_CONTINUE; } - return false; + this._timeoutId = 0; + return GLib.SOURCE_REMOVE; } _updateTimer() { - if (this._timeoutId !== 0) { + if (this._timeoutId > 0) { Mainloop.source_remove(this._timeoutId); this._timeoutId = 0; } @@ -403,12 +404,14 @@ class Seeker extends Slider.Slider { } destroy() { - if (this._timeoutId != 0) { + if (this._timeoutId > 0) { Mainloop.source_remove(this._timeoutId); this._timeoutId = 0; } - if (this._seekChangedId) + if (this._seekChangedId) { this._mediaServerPlayer.disconnectSignal(this._seekChangedId); + this._seekChangedId = 0; + } this.disconnectAll(); this._mediaServerPlayer = null; @@ -1101,6 +1104,7 @@ class CinnamonSoundApplet extends Applet.TextIconApplet { this.unregisterSystrayIcons(); if (this._iconTimeoutId) { Mainloop.source_remove(this._iconTimeoutId); + this._iconTimeoutId = 0; } this._dbus.disconnectSignal(this._ownerChangedId); @@ -1224,7 +1228,7 @@ class CinnamonSoundApplet extends Applet.TextIconApplet { setIcon(icon, source) { if (this._iconTimeoutId) { Mainloop.source_remove(this._iconTimeoutId); - this._iconTimeoutId = null; + this._iconTimeoutId = 0; } //save the icon @@ -1240,7 +1244,6 @@ class CinnamonSoundApplet extends Applet.TextIconApplet { //if we have an active player, but are changing the volume, show the output icon and after three seconds change back to the player icon this.set_applet_icon_symbolic_name(this._outputIcon); this._iconTimeoutId = Mainloop.timeout_add_seconds(OUTPUT_ICON_SHOW_TIME_SECONDS, () => { - this._iconTimeoutId = null; this.setIcon(); }); } else { From 28bd0516248e532e209083b2d4b3968b772556d0 Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Wed, 1 Mar 2023 09:26:17 -0500 Subject: [PATCH 05/30] window-list: Fix signal name for tile notifications. requires: linuxmint/muffin@e232f8e11817 --- .../share/cinnamon/applets/window-list@cinnamon.org/applet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/usr/share/cinnamon/applets/window-list@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/window-list@cinnamon.org/applet.js index 15fe404936..0e693d8791 100644 --- a/files/usr/share/cinnamon/applets/window-list@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/window-list@cinnamon.org/applet.js @@ -371,7 +371,7 @@ class AppMenuButton { this._signals.connect(this.metaWindow, 'notify::title', this.setDisplayTitle, this); this._signals.connect(this.metaWindow, "notify::minimized", this.setDisplayTitle, this); - this._signals.connect(this.metaWindow, "notify::tile-type", this.setDisplayTitle, this); + this._signals.connect(this.metaWindow, "notify::tile-mode", this.setDisplayTitle, this); this._signals.connect(this.metaWindow, "notify::icon", this.setIcon, this); this._signals.connect(this.metaWindow, "notify::appears-focused", this.onFocus, this); this._signals.connect(this.metaWindow, "unmanaged", this.onUnmanaged, this); From 3a3d97c82529b42cdc6b30d32c7e98050b7ac10e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n?= <67810471+gulis1@users.noreply.github.com> Date: Mon, 6 Mar 2023 17:36:01 +0100 Subject: [PATCH 06/30] Sound applet: added special case for Firefox icon. (#11314) --- .../share/cinnamon/applets/sound@cinnamon.org/applet.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/files/usr/share/cinnamon/applets/sound@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/sound@cinnamon.org/applet.js index a6eb90ea32..128ba1defb 100644 --- a/files/usr/share/cinnamon/applets/sound@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/sound@cinnamon.org/applet.js @@ -437,16 +437,19 @@ class StreamMenuSection extends PopupMenu.PopupMenuSection { } // Special cases - if(name === "Banshee") { + if (name === "Banshee") { iconName = "banshee"; } else if (name === "Spotify") { iconName = "spotify"; } - if(name === "VBox") { + else if (name === "VBox") { name = "Virtualbox"; iconName = "virtualbox"; } + else if (name === "Firefox") { + iconName = "firefox"; + } else if (iconName === "audio") { iconName = "audio-x-generic"; } From ae17305e08637fc77973dc17c01ef9e7d7160b0a Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Tue, 24 Jan 2023 14:45:29 -0500 Subject: [PATCH 07/30] Stop using CinnamonScreen everywhere. CinnamonScreen exists only for compatibility, as MetaScreen went away in 5.4. Quite a bit had already been ported, but this gets rid of the remaining users. CinnamonScreen itself still remains for xlets (though they should consider doing this eventually as well). --- .../appGroup.js | 4 +- .../appList.js | 4 +- .../applet.js | 18 ++++----- .../window-list@cinnamon.org/applet.js | 22 +++++------ .../windows-quick-list@cinnamon.org/applet.js | 8 ++-- js/misc/signalManager.js | 2 +- js/ui/appSwitcher/appSwitcher.js | 12 +++--- js/ui/appSwitcher/appSwitcher3D.js | 6 +-- js/ui/appSwitcher/classicSwitcher.js | 4 +- js/ui/deskletManager.js | 2 +- js/ui/expoThumbnail.js | 6 +-- js/ui/hotCorner.js | 2 +- js/ui/layout.js | 18 ++++----- js/ui/main.js | 37 +++++++++---------- js/ui/osdWindow.js | 2 +- js/ui/overview.js | 2 +- js/ui/virtualKeyboard.js | 2 +- js/ui/windowManager.js | 22 +++++------ js/ui/wmGtkDialogs.js | 2 +- js/ui/workspace.js | 18 ++++----- src/cinnamon-global.c | 2 +- 21 files changed, 96 insertions(+), 99 deletions(-) diff --git a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appGroup.js b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appGroup.js index 9ca6b37d5a..63a54882ce 100644 --- a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appGroup.js +++ b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appGroup.js @@ -884,8 +884,8 @@ class AppGroup { this.groupState.lastFocused.unminimize(); } let ws = this.groupState.lastFocused.get_workspace().index(); - if (ws !== global.screen.get_active_workspace_index()) { - global.screen.get_workspace_by_index(ws).activate(global.get_current_time()); + if (ws !== global.workspace_manager.get_active_workspace_index()) { + global.workspace_manager.get_workspace_by_index(ws).activate(global.get_current_time()); } Main.activateWindow(this.groupState.lastFocused, global.get_current_time()); this.actor.add_style_pseudo_class('focus'); diff --git a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appList.js b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appList.js index e43afb00c7..2a2f3b0996 100644 --- a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appList.js +++ b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appList.js @@ -50,7 +50,7 @@ class AppList { this.lastFocusedApp = null; // Connect all the signals - this.signals.connect(global.screen, 'window-workspace-changed', (...args) => this.windowWorkspaceChanged(...args)); + this.signals.connect(global.display, 'window-workspace-changed', (...args) => this.windowWorkspaceChanged(...args)); // Ugly change: refresh the removed app instances from all workspaces this.signals.connect(this.metaWorkspace, 'window-removed', (...args) => this.windowRemoved(...args)); this.signals.connect(global.window_manager, 'switch-workspace' , (...args) => this.reloadList(...args)); @@ -235,7 +235,7 @@ class AppList { && this.state.monitorWatchList.indexOf(metaWindow.get_monitor()) > -1; } - windowWorkspaceChanged(screen, metaWorkspace, metaWindow) { + windowWorkspaceChanged(display, metaWorkspace, metaWindow) { this.windowAdded(metaWindow, metaWorkspace); } diff --git a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/applet.js index 5f5c088eda..d2bf8f65c4 100644 --- a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/applet.js @@ -189,7 +189,7 @@ class GroupedWindowListApplet extends Applet.Applet { instance_id, monitorWatchList: [], autoStartApps: [], - currentWs: global.screen.get_active_workspace_index(), + currentWs: global.workspace_manager.get_active_workspace_index(), panelEditMode: global.settings.get_boolean('panel-edit-mode'), menuOpen: false, dragging: { @@ -293,10 +293,10 @@ class GroupedWindowListApplet extends Applet.Applet { this.signals.connect(this.actor, 'scroll-event', (c, e) => this.handleScroll(e)); this.signals.connect(global, 'scale-changed', (...args) => this.onUIScaleChange(...args)); this.signals.connect(global.window_manager, 'switch-workspace', (...args) => this.onSwitchWorkspace(...args)); - this.signals.connect(global.screen, 'workspace-removed', (...args) => this.onWorkspaceRemoved(...args)); - this.signals.connect(global.screen, 'window-monitor-changed', (...args) => this.onWindowMonitorChanged(...args)); + this.signals.connect(global.workspace_manager, 'workspace-removed', (...args) => this.onWorkspaceRemoved(...args)); + this.signals.connect(global.display, 'window-monitor-changed', (...args) => this.onWindowMonitorChanged(...args)); this.signals.connect(Main.panelManager, 'monitors-changed', (...args) => this._onMonitorsChanged(...args)); - this.signals.connect(global.screen, 'window-skip-taskbar-changed', (...args) => this.onWindowSkipTaskbarChanged(...args)); + this.signals.connect(global.display, 'window-skip-taskbar-changed', (...args) => this.onWindowSkipTaskbarChanged(...args)); this.signals.connect(global.display, 'window-marked-urgent', (...args) => this.updateAttentionState(...args)); this.signals.connect(global.display, 'window-demands-attention', (...args) => this.updateAttentionState(...args)); this.signals.connect(global.display, 'window-created', (...args) => this.onWindowCreated(...args)); @@ -446,7 +446,7 @@ class GroupedWindowListApplet extends Applet.Applet { return false; } - onWindowMonitorChanged(screen, metaWindow, metaWorkspace) { + onWindowMonitorChanged(display, metaWindow, metaWorkspace) { if (this.state.monitorWatchList.length !== this.numberOfMonitors) { let appList = this.getCurrentAppList(); if (appList !== null) { @@ -935,7 +935,7 @@ class GroupedWindowListApplet extends Applet.Applet { return true; } - onWorkspaceRemoved(metaScreen, index) { + onWorkspaceRemoved(workspaceManager, index) { if (this.appLists.length <= index) { return; } @@ -955,7 +955,7 @@ class GroupedWindowListApplet extends Applet.Applet { for (let i = removedLists.length - 1; i >= 0; i--) { this.appLists.splice(removedLists[i], 1); } - this.state.set({currentWs: global.screen.get_active_workspace_index()}); + this.state.set({currentWs: global.workspace_manager.get_active_workspace_index()}); } onSwitchWorkspace() { @@ -965,7 +965,7 @@ class GroupedWindowListApplet extends Applet.Applet { _onSwitchWorkspace() { if (!this.state) return; this.state.set({currentWs: global.workspace_manager.get_active_workspace_index()}); - let metaWorkspace = global.screen.get_workspace_by_index(this.state.currentWs); + let metaWorkspace = global.workspace_manager.get_workspace_by_index(this.state.currentWs); // If the workspace we switched to isn't in our list, // we need to create an AppList for it @@ -990,7 +990,7 @@ class GroupedWindowListApplet extends Applet.Applet { this.actor.queue_relayout(); } - onWindowSkipTaskbarChanged(screen, metaWindow) { + onWindowSkipTaskbarChanged(display, metaWindow) { let appList = this.getCurrentAppList(); if (metaWindow.is_skip_taskbar()) { diff --git a/files/usr/share/cinnamon/applets/window-list@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/window-list@cinnamon.org/applet.js index 0e693d8791..8078856259 100644 --- a/files/usr/share/cinnamon/applets/window-list@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/window-list@cinnamon.org/applet.js @@ -272,7 +272,7 @@ class AppMenuButton { this.drawLabel = false; this.labelVisiblePref = false; this._signals = new SignalManager.SignalManager(); - this.xid = global.screen.get_xwindow_for_window(metaWindow); + this.xid = metaWindow.get_xwindow(); this._flashTimer = null; if (this._applet.orientation == St.Side.TOP) @@ -1057,9 +1057,9 @@ class CinnamonWindowListApplet extends Applet.Applet { this.settings.bind("last-window-order", "lastWindowOrder", null); this.signals.connect(global.display, 'window-created', this._onWindowAddedAsync, this); - this.signals.connect(global.screen, 'window-monitor-changed', this._onWindowMonitorChanged, this); - this.signals.connect(global.screen, 'window-workspace-changed', this._onWindowWorkspaceChanged, this); - this.signals.connect(global.screen, 'window-skip-taskbar-changed', this._onWindowSkipTaskbarChanged, this); + this.signals.connect(global.display, 'window-monitor-changed', this._onWindowMonitorChanged, this); + this.signals.connect(global.display, 'window-workspace-changed', this._onWindowWorkspaceChanged, this); + this.signals.connect(global.display, 'window-skip-taskbar-changed', this._onWindowSkipTaskbarChanged, this); this.signals.connect(Main.panelManager, 'monitors-changed', this._updateWatchedMonitors, this); this.signals.connect(global.window_manager, 'switch-workspace', this._refreshAllItems, this); this.signals.connect(Cinnamon.WindowTracker.get_default(), "window-app-changed", this._onWindowAppChanged, this); @@ -1157,16 +1157,16 @@ class CinnamonWindowListApplet extends Applet.Applet { this.manager.set_spacing(spacing * global.ui_scale); } - _onWindowAddedAsync(screen, metaWindow, monitor) { - Mainloop.timeout_add(20, Lang.bind(this, this._onWindowAdded, screen, metaWindow, monitor)); + _onWindowAddedAsync(display, metaWindow, monitor) { + Mainloop.timeout_add(20, Lang.bind(this, this._onWindowAdded, display, metaWindow, monitor)); } - _onWindowAdded(screen, metaWindow, monitor) { + _onWindowAdded(display, metaWindow, monitor) { if (this._shouldAdd(metaWindow)) this._addWindow(metaWindow, false); } - _onWindowMonitorChanged(screen, metaWindow, monitor) { + _onWindowMonitorChanged(display, metaWindow, monitor) { if (this._shouldAdd(metaWindow)) this._addWindow(metaWindow, false); else @@ -1180,7 +1180,7 @@ class CinnamonWindowListApplet extends Applet.Applet { this._refreshItem(window); } - _onWindowWorkspaceChanged(screen, metaWindow, metaWorkspace) { + _onWindowWorkspaceChanged(display, metaWindow, metaWorkspace) { this._refreshItemByMetaWindow(metaWindow); } @@ -1188,13 +1188,13 @@ class CinnamonWindowListApplet extends Applet.Applet { this._refreshItemByMetaWindow(metaWindow); } - _onWindowSkipTaskbarChanged(screen, metaWindow) { + _onWindowSkipTaskbarChanged(display, metaWindow) { if (metaWindow && metaWindow.is_skip_taskbar()) { this._removeWindow(metaWindow); return; } - this._onWindowAdded(screen, metaWindow, 0); + this._onWindowAdded(display, metaWindow, 0); } _updateAttentionGrabber() { diff --git a/files/usr/share/cinnamon/applets/windows-quick-list@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/windows-quick-list@cinnamon.org/applet.js index 4454f4ed9c..923de8743f 100644 --- a/files/usr/share/cinnamon/applets/windows-quick-list@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/windows-quick-list@cinnamon.org/applet.js @@ -62,10 +62,10 @@ class CinnamonWindowsQuickListApplet extends Applet.IconApplet { let empty_menu = true; let tracker = Cinnamon.WindowTracker.get_default(); - for (let wks = 0; wks < global.screen.n_workspaces; ++wks) { + for (let wks = 0; wks < global.workspace_manager.n_workspaces; ++wks) { // construct a list with all windows let workspace_name = Main.getWorkspaceName(wks); - let metaWorkspace = global.screen.get_workspace_by_index(wks); + let metaWorkspace = global.workspace_manager.get_workspace_by_index(wks); let windows = metaWorkspace.list_windows(); let sticky_windows = windows.filter(function(w) { return !w.is_skip_taskbar() && w.is_on_all_workspaces(); @@ -103,12 +103,12 @@ class CinnamonWindowsQuickListApplet extends Applet.IconApplet { if (wks > 0) { this._addItem(new PopupMenu.PopupSeparatorMenuItem()); } - if (global.screen.n_workspaces > 1) { + if (global.workspace_manager.n_workspaces > 1) { let item = new WindowMenuItem(null, workspace_name); item.actor.reactive = false; item.actor.can_focus = false; item.label.add_style_class_name('popup-subtitle-menu-item'); - if (wks == global.screen.get_active_workspace().index()) { + if (wks == global.workspace_manager.get_active_workspace().index()) { item.setShowDot(true); } this._addItem(item); diff --git a/js/misc/signalManager.js b/js/misc/signalManager.js index b824ca969e..602c2ca075 100644 --- a/js/misc/signalManager.js +++ b/js/misc/signalManager.js @@ -54,7 +54,7 @@ const _disconnect = function(results) { * Every Javascript object should have its own @SignalManager, and use it to * connect signals of all objects it takes care of. For example, the panel will * have one #SignalManger object, which manages all signals from #GSettings, - * `global.screen` etc. + * `global.display` etc. * * An example usage is as follows: * ``` diff --git a/js/ui/appSwitcher/appSwitcher.js b/js/ui/appSwitcher/appSwitcher.js index 72935762fa..8f6b79e843 100644 --- a/js/ui/appSwitcher/appSwitcher.js +++ b/js/ui/appSwitcher/appSwitcher.js @@ -77,14 +77,14 @@ function getWindowsForBinding(binding) { windows = windows.filter( matchWmClass, focused.get_wm_class() ); this._showAllWorkspaces = global.settings.get_boolean("alttab-switcher-show-all-workspaces"); if (!this._showAllWorkspaces) { - windows = windows.filter( matchWorkspace, global.screen.get_active_workspace() ); + windows = windows.filter( matchWorkspace, global.workspace_manager.get_active_workspace() ); } break; default: // Switch between windows of current workspace this._showAllWorkspaces = global.settings.get_boolean("alttab-switcher-show-all-workspaces"); if (!this._showAllWorkspaces) { - windows = windows.filter( matchWorkspace, global.screen.get_active_workspace() ); + windows = windows.filter( matchWorkspace, global.workspace_manager.get_active_workspace() ); } break; } @@ -378,10 +378,10 @@ AppSwitcher.prototype = { }, _switchWorkspace: function(direction) { - if (global.screen.n_workspaces < 2) + if (global.workspace_manager.n_workspaces < 2) return false; - let current = global.screen.get_active_workspace_index(); + let current = global.workspace_manager.get_active_workspace_index(); if (direction === Clutter.KEY_Left) Main.wm.actionMoveWorkspaceLeft(); @@ -390,10 +390,10 @@ AppSwitcher.prototype = { else return false; - if (current === global.screen.get_active_workspace_index()) + if (current === global.workspace_manager.get_active_workspace_index()) return false; - let workspace = global.screen.get_active_workspace(); + let workspace = global.workspace_manager.get_active_workspace(); this._onWorkspaceSelected(workspace); return true; }, diff --git a/js/ui/appSwitcher/appSwitcher3D.js b/js/ui/appSwitcher/appSwitcher3D.js index 30c63544dc..93a08e7c52 100644 --- a/js/ui/appSwitcher/appSwitcher3D.js +++ b/js/ui/appSwitcher/appSwitcher3D.js @@ -89,7 +89,7 @@ AppSwitcher3D.prototype = { let monitor = this._activeMonitor; // preview windows - let currentWorkspace = global.screen.get_active_workspace(); + let currentWorkspace = global.workspace_manager.get_active_workspace(); for (let i in this._previews) { let preview = this._previews[i]; let metaWin = this._windows[i]; @@ -176,7 +176,7 @@ AppSwitcher3D.prototype = { _createList: function() { let monitor = this._activeMonitor; - let currentWorkspace = global.screen.get_active_workspace(); + let currentWorkspace = global.workspace_manager.get_active_workspace(); this._previews = []; @@ -316,7 +316,7 @@ AppSwitcher3D.prototype = { }, _enableMonitorFix: function() { - if(global.screen.get_n_monitors() < 2) + if(global.display.get_n_monitors() < 2) return; this._monitorFix = true; diff --git a/js/ui/appSwitcher/classicSwitcher.js b/js/ui/appSwitcher/classicSwitcher.js index fc8b8fae48..8619f634a0 100644 --- a/js/ui/appSwitcher/classicSwitcher.js +++ b/js/ui/appSwitcher/classicSwitcher.js @@ -759,7 +759,7 @@ AppList.prototype = { SwitcherList.prototype._init.call(this, true, activeMonitor); // Construct the AppIcons, add to the popup - let activeWorkspace = global.screen.get_active_workspace(); + let activeWorkspace = global.workspace_manager.get_active_workspace(); let workspaceIcons = []; let otherIcons = []; for (let i = 0; i < windows.length; i++) { @@ -899,7 +899,7 @@ ThumbnailList.prototype = { _init : function(windows, activeMonitor) { SwitcherList.prototype._init.call(this, false, activeMonitor); - let activeWorkspace = global.screen.get_active_workspace(); + let activeWorkspace = global.workspace_manager.get_active_workspace(); this._labels = new Array(); this._thumbnailBins = new Array(); diff --git a/js/ui/deskletManager.js b/js/ui/deskletManager.js index 1e0d9b5910..42b60d7636 100644 --- a/js/ui/deskletManager.js +++ b/js/ui/deskletManager.js @@ -105,7 +105,7 @@ function updateMouseTracking() { } function hasMouseWindow(){ - let window = global.screen.get_mouse_window(null); + let window = global.display.get_pointer_window(null); return window && window.window_type !== Meta.WindowType.DESKTOP; } diff --git a/js/ui/expoThumbnail.js b/js/ui/expoThumbnail.js index 9b2f477480..09ca739e78 100644 --- a/js/ui/expoThumbnail.js +++ b/js/ui/expoThumbnail.js @@ -652,12 +652,12 @@ ExpoWorkspaceThumbnail.prototype = { this.doRemoveWindow(metaWin); }, - windowEnteredMonitor : function(metaScreen, monitorIndex, metaWin) { + windowEnteredMonitor : function(metaDisplay, monitorIndex, metaWin) { // important if workspaces-only-on-primary is in effect this.doAddWindow(metaWin); }, - windowLeftMonitor : function(metaScreen, monitorIndex, metaWin) { + windowLeftMonitor : function(metaDisplay, monitorIndex, metaWin) { // important if workspaces-only-on-primary is in effect this.doRemoveWindow(metaWin); }, @@ -1144,7 +1144,7 @@ ExpoThumbnailsBox.prototype = { global.window_manager.connect('switch-workspace', Lang.bind(this, this.activeWorkspaceChanged)); - this.workspaceAddedId = global.workspace_manager.connect('workspace-added', Lang.bind(this, function(screen, index) { + this.workspaceAddedId = global.workspace_manager.connect('workspace-added', Lang.bind(this, function(ws_manager, index) { this.addThumbnails(index, 1); })); this.workspaceRemovedId = global.workspace_manager.connect('workspace-removed', Lang.bind(this, function() { diff --git a/js/ui/hotCorner.js b/js/ui/hotCorner.js index 419c256f7f..99d4a77074 100755 --- a/js/ui/hotCorner.js +++ b/js/ui/hotCorner.js @@ -245,7 +245,7 @@ class HotCorner { Main.overview.toggle(); break; case 'desktop': - global.screen.toggle_desktop(timestamp); + global.workspace_manager.toggle_desktop(timestamp); break; default: Util.spawnCommandLine(this.action); diff --git a/js/ui/layout.js b/js/ui/layout.js index 0bacb9c039..cb7aee7279 100644 --- a/js/ui/layout.js +++ b/js/ui/layout.js @@ -48,7 +48,7 @@ Monitor.prototype = { }, get inFullscreen() { - return global.screen.get_monitor_in_fullscreen(this.index); + return global.display.get_monitor_in_fullscreen(this.index); } }; @@ -230,7 +230,7 @@ LayoutManager.prototype = { }, get currentMonitor() { - let index = global.screen.get_current_monitor(); + let index = global.display.get_current_monitor(); return Main.layoutManager.monitors[index]; }, @@ -488,13 +488,13 @@ Chrome.prototype = { this._layoutManager.connect('monitors-changed', Lang.bind(this, this._relayout)); - global.screen.connect('restacked', + global.display.connect('restacked', Lang.bind(this, this._windowsRestacked)); - global.screen.connect('in-fullscreen-changed', Lang.bind(this, this._updateVisibility)); + global.display.connect('in-fullscreen-changed', Lang.bind(this, this._updateVisibility)); global.window_manager.connect('switch-workspace', Lang.bind(this, this._queueUpdateRegions)); // Need to update struts on new workspaces when they are added - global.screen.connect('notify::n-workspaces', + global.workspace_manager.connect('notify::n-workspaces', Lang.bind(this, this._queueUpdateRegions)); this._relayout(); @@ -635,7 +635,7 @@ Chrome.prototype = { else if (global.stage_input_mode == Cinnamon.StageInputMode.FULLSCREEN) { let monitor = this.findMonitorForActor(actorData.actor); - if (global.screen.get_n_monitors() == 1 || !monitor.inFullscreen) { + if (global.display.get_n_monitors() == 1 || !monitor.inFullscreen) { visible = true; } else { if (Main.modalActorFocusStack.length > 0) { @@ -863,9 +863,9 @@ Chrome.prototype = { global.set_stage_input_region(rects); - let screen = global.screen; - for (let w = 0; w < screen.n_workspaces; w++) { - let workspace = screen.get_workspace_by_index(w); + let ws_manager = global.workspace_manager; + for (let w = 0; w < ws_manager.n_workspaces; w++) { + let workspace = ws_manager.get_workspace_by_index(w); workspace.set_builtin_struts(struts); } diff --git a/js/ui/main.js b/js/ui/main.js index dcbf18d38c..7eab8d17c9 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -227,7 +227,7 @@ function _addXletDirectoriesToSearchPath() { } function _initUserSession() { - global.screen.override_workspace_layout(Meta.DisplayCorner.TOPLEFT, false, 1, -1); + global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT, false, 1, -1); systrayManager = new Systray.SystrayManager(); @@ -570,7 +570,7 @@ function _fillWorkspaceNames(index) { } function _shouldTrimWorkspace(i) { - return i >= 0 && (i >= global.screen.n_workspaces || !workspace_names[i].length); + return i >= 0 && (i >= global.workspace_manager.n_workspaces || !workspace_names[i].length); } function _trimWorkspaceNames() { @@ -636,12 +636,12 @@ function hasDefaultWorkspaceName(index) { } function _addWorkspace() { - global.screen.append_new_workspace(false, global.get_current_time()); + global.workspace_manager.append_new_workspace(false, global.get_current_time()); return true; } function _removeWorkspace(workspace) { - if (global.screen.n_workspaces == 1) + if (global.workspace_manager.n_workspaces == 1) return false; let index = workspace.index(); if (index < workspace_names.length) { @@ -649,7 +649,7 @@ function _removeWorkspace(workspace) { } _trimWorkspaceNames(); wmSettings.set_strv("workspace-names", workspace_names); - global.screen.remove_workspace(workspace, global.get_current_time()); + global.workspace_manager.remove_workspace(workspace, global.get_current_time()); return true; } @@ -666,16 +666,16 @@ function _removeWorkspace(workspace) { */ function moveWindowToNewWorkspace(metaWindow, switchToNewWorkspace) { if (switchToNewWorkspace) { - let targetCount = global.screen.n_workspaces + 1; - let nnwId = global.screen.connect('notify::n-workspaces', function() { - global.screen.disconnect(nnwId); - if (global.screen.n_workspaces === targetCount) { - let newWs = global.screen.get_workspace_by_index(global.screen.n_workspaces - 1); + let targetCount = global.workspace_manager.n_workspaces + 1; + let nnwId = global.workspace_manager.connect('notify::n-workspaces', function() { + global.workspace_manager.disconnect(nnwId); + if (global.workspace_manager.n_workspaces === targetCount) { + let newWs = global.workspace_manager.get_workspace_by_index(global.workspace_manager.n_workspaces - 1); newWs.activate(global.get_current_time()); } }); } - metaWindow.change_workspace_by_index(global.screen.n_workspaces, true, global.get_current_time()); + metaWindow.change_workspace_by_index(global.workspace_manager.n_workspaces, true, global.get_current_time()); } /** @@ -1320,13 +1320,13 @@ function getRunDialog() { * activation will be handled in muffin. */ function activateWindow(window, time, workspaceNum) { - let activeWorkspaceNum = global.screen.get_active_workspace_index(); + let activeWorkspaceNum = global.workspace_manager.get_active_workspace_index(); if (!time) time = global.get_current_time(); if ((workspaceNum !== undefined) && activeWorkspaceNum !== workspaceNum) { - let workspace = global.screen.get_workspace_by_index(workspaceNum); + let workspace = global.workspace_manager.get_workspace_by_index(workspaceNum); workspace.activate_with_focus(window, time); return; } @@ -1489,8 +1489,7 @@ function isInteresting(metaWindow) { /** * getTabList: - * @workspaceOpt (Meta.Workspace): (optional) workspace, defaults to global.screen.get_active_workspace() - * @screenOpt (Meta.Screen): (optional) screen, defaults to global.screen + * @workspaceOpt (Meta.Workspace): (optional) workspace, defaults to global.workspace_manager.get_active_workspace() * * Return a list of the interesting windows on a workspace (by default, * the active workspace). @@ -1498,14 +1497,12 @@ function isInteresting(metaWindow) { * * Returns (array): list of windows */ -function getTabList(workspaceOpt, screenOpt) { - let screen = screenOpt || global.screen; - let display = screen.get_display(); - let workspace = workspaceOpt || screen.get_active_workspace(); +function getTabList(workspaceOpt) { + let workspace = workspaceOpt || global.workspace_manager.get_active_workspace(); let windows = []; // the array to return - let allwindows = display.get_tab_list(Meta.TabList.NORMAL_ALL, workspace); + let allwindows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, workspace); let registry = {}; // to avoid duplicates for (let i = 0; i < allwindows.length; ++i) { diff --git a/js/ui/osdWindow.js b/js/ui/osdWindow.js index 0d4a46c951..7c234a09cc 100644 --- a/js/ui/osdWindow.js +++ b/js/ui/osdWindow.js @@ -145,7 +145,7 @@ OsdWindow.prototype = { return; if (!this.actor.visible) { - Meta.disable_unredirect_for_screen(global.screen); + Meta.disable_unredirect_for_display(global.display); this._level.setLevelBarHeight(this._sizeMultiplier); this.actor.show(); this.actor.opacity = 0; diff --git a/js/ui/overview.js b/js/ui/overview.js index fb6a16122e..5de19f9e05 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -276,7 +276,7 @@ Overview.prototype = { this._coverPane.hide(); // Disable unredirection while in the overview - Meta.disable_unredirect_for_screen(global.screen); + Meta.disable_unredirect_for_display(global.display); this._group.show(); this.workspacesView = new WorkspacesView.WorkspacesView(); diff --git a/js/ui/virtualKeyboard.js b/js/ui/virtualKeyboard.js index 26dd348a67..8a0fbde0fc 100644 --- a/js/ui/virtualKeyboard.js +++ b/js/ui/virtualKeyboard.js @@ -488,7 +488,7 @@ Keyboard.prototype = { }, _moveTemporarily: function () { - let currentWindow = global.screen.get_display().focus_window; + let currentWindow = global.display.focus_window; let rect = currentWindow.get_outer_rect(); let newX = rect.x; diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js index 052706ab3b..cf4f7923e6 100644 --- a/js/ui/windowManager.js +++ b/js/ui/windowManager.js @@ -1235,7 +1235,7 @@ var WindowManager = class WindowManager { showWorkspaceOSD() { this._hideWorkspaceOSD(true); if (global.settings.get_boolean('workspace-osd-visible')) { - let current_workspace_index = global.screen.get_active_workspace_index(); + let current_workspace_index = global.workspace_manager.get_active_workspace_index(); if (this.wm_settings.get_boolean('workspaces-only-on-primary')) { this._showWorkspaceOSDOnMonitor(Main.layoutManager.primaryMonitor.index, current_workspace_index); } @@ -1311,8 +1311,8 @@ var WindowManager = class WindowManager { return; } this._movingWindow = window; - let workspace = global.screen.get_active_workspace().get_neighbor(direction); - if (workspace != global.screen.get_active_workspace()) { + let workspace = global.workspace_manager.get_active_workspace().get_neighbor(direction); + if (workspace != global.workspace_manager.get_active_workspace()) { window.change_workspace(workspace); workspace.activate_with_focus(window, global.get_current_time()); } @@ -1327,7 +1327,7 @@ var WindowManager = class WindowManager { } moveToWorkspace(workspace, direction_hint) { - let active = global.screen.get_active_workspace(); + let active = global.workspace_manager.get_active_workspace(); // if (workspace != active) { // if (direction_hint) // workspace.activate_with_direction_hint(direction_hint, global.get_current_time()); @@ -1347,7 +1347,7 @@ var WindowManager = class WindowManager { return; } - if (global.screen.n_workspaces === 1) + if (global.workspace_manager.n_workspaces === 1) return; if (bindingName === 'switch-to-workspace-left') { @@ -1358,7 +1358,7 @@ var WindowManager = class WindowManager { } actionMoveWorkspaceLeft() { - let active = global.screen.get_active_workspace(); + let active = global.workspace_manager.get_active_workspace(); let neighbor = active.get_neighbor(Meta.MotionDirection.LEFT) if (active != neighbor) { this.moveToWorkspace(neighbor, Meta.MotionDirection.LEFT); @@ -1366,7 +1366,7 @@ var WindowManager = class WindowManager { } actionMoveWorkspaceRight() { - let active = global.screen.get_active_workspace(); + let active = global.workspace_manager.get_active_workspace(); let neighbor = active.get_neighbor(Meta.MotionDirection.RIGHT) if (active != neighbor) { this.moveToWorkspace(neighbor, Meta.MotionDirection.RIGHT); @@ -1374,15 +1374,15 @@ var WindowManager = class WindowManager { } actionMoveWorkspaceUp() { - global.screen.get_active_workspace().get_neighbor(Meta.MotionDirection.UP).activate(global.get_current_time()); + global.workspace_manager.get_active_workspace().get_neighbor(Meta.MotionDirection.UP).activate(global.get_current_time()); } actionMoveWorkspaceDown() { - global.screen.get_active_workspace().get_neighbor(Meta.MotionDirection.DOWN).activate(global.get_current_time()); + global.workspace_manager.get_active_workspace().get_neighbor(Meta.MotionDirection.DOWN).activate(global.get_current_time()); } actionFlipWorkspaceLeft() { - let active = global.screen.get_active_workspace(); + let active = global.workspace_manager.get_active_workspace(); let neighbor = active.get_neighbor(Meta.MotionDirection.LEFT); if (active != neighbor) { neighbor.activate(global.get_current_time()); @@ -1392,7 +1392,7 @@ var WindowManager = class WindowManager { } actionFlipWorkspaceRight() { - let active = global.screen.get_active_workspace(); + let active = global.workspace_manager.get_active_workspace(); let neighbor = active.get_neighbor(Meta.MotionDirection.RIGHT); if (active != neighbor) { neighbor.activate(global.get_current_time()); diff --git a/js/ui/wmGtkDialogs.js b/js/ui/wmGtkDialogs.js index 531a14c708..3cc77f43ba 100644 --- a/js/ui/wmGtkDialogs.js +++ b/js/ui/wmGtkDialogs.js @@ -73,7 +73,7 @@ var CloseDialog = GObject.registerClass({ this.proc = Gio.Subprocess.new( [ "cinnamon-close-dialog", - global.screen.get_xwindow_for_window(this._window).toString(), + this._window.get_xwindow().toString(), this._window.get_title() ], 0); diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 6a799a5e1f..710545f392 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -545,9 +545,9 @@ WorkspaceMonitor.prototype = { this._windowRemovedId = this.metaWorkspace.connect('window-removed', this._windowRemoved.bind(this)); } - this._windowEnteredMonitorId = global.screen.connect('window-entered-monitor', + this._windowEnteredMonitorId = global.display.connect('window-entered-monitor', this._windowEnteredMonitor.bind(this)); - this._windowLeftMonitorId = global.screen.connect('window-left-monitor', + this._windowLeftMonitorId = global.display.connect('window-left-monitor', this._windowLeftMonitor.bind(this)); this._animating = false; // Indicate if windows are being repositioned @@ -715,7 +715,7 @@ WorkspaceMonitor.prototype = { // Start the animations let slots = this._computeAllWindowSlots(clones.length); - let currentWorkspace = global.screen.get_active_workspace(); + let currentWorkspace = global.workspace_manager.get_active_workspace(); let isOnCurrentWorkspace = this.metaWorkspace == null || this.metaWorkspace == currentWorkspace; if (clones.length > 0 && animate && isOnCurrentWorkspace) { @@ -830,7 +830,7 @@ WorkspaceMonitor.prototype = { }, _showAllOverlays: function() { - let currentWorkspace = global.screen.get_active_workspace(); + let currentWorkspace = global.workspace_manager.get_active_workspace(); let fade = this.metaWorkspace == null || this.metaWorkspace === currentWorkspace; for (let clone of this._windows) { this._showWindowOverlay(clone, fade); @@ -945,13 +945,13 @@ WorkspaceMonitor.prototype = { this._doRemoveWindow(metaWin); }, - _windowEnteredMonitor : function(metaScreen, monitorIndex, metaWin) { + _windowEnteredMonitor : function(metaDisplay, monitorIndex, metaWin) { if (monitorIndex === this.monitorIndex) { this._doAddWindow(metaWin); } }, - _windowLeftMonitor : function(metaScreen, monitorIndex, metaWin) { + _windowLeftMonitor : function(metaDisplay, monitorIndex, metaWin) { if (monitorIndex === this.monitorIndex) { this._doRemoveWindow(metaWin); } @@ -983,7 +983,7 @@ WorkspaceMonitor.prototype = { // Animates the return from Overview mode zoomFromOverview : function() { - let currentWorkspace = global.screen.get_active_workspace(); + let currentWorkspace = global.workspace_manager.get_active_workspace(); this.leavingOverview = true; @@ -1053,8 +1053,8 @@ WorkspaceMonitor.prototype = { this.metaWorkspace.disconnect(this._windowAddedId); this.metaWorkspace.disconnect(this._windowRemovedId); } - global.screen.disconnect(this._windowEnteredMonitorId); - global.screen.disconnect(this._windowLeftMonitorId); + global.display.disconnect(this._windowEnteredMonitorId); + global.display.disconnect(this._windowLeftMonitorId); // Usually, the windows will be destroyed automatically with // their parent (this.actor), but we might have a zoomed window diff --git a/src/cinnamon-global.c b/src/cinnamon-global.c index b23544bff0..89b28061fd 100644 --- a/src/cinnamon-global.c +++ b/src/cinnamon-global.c @@ -1426,7 +1426,7 @@ cinnamon_global_create_app_launch_context (CinnamonGlobal *global) // Make sure that the app is opened on the current workspace even if // the user switches before it starts - gdk_app_launch_context_set_desktop (context, cinnamon_screen_get_active_workspace_index (global->cinnamon_screen)); + gdk_app_launch_context_set_desktop (context, meta_workspace_manager_get_active_workspace_index (global->workspace_manager)); return (GAppLaunchContext *)context; } From 49567152ed8a813c8aeba5c4e0410c41bb06ec6f Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Mon, 6 Mar 2023 15:37:07 -0500 Subject: [PATCH 08/30] overrides.js: Silently fail to install polyfills. In mozjs102, these aren't necessary, and will crash Cinnamon if failure is not caught. ref: linuxmint/cjs#111 --- js/ui/overrides.js | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/js/ui/overrides.js b/js/ui/overrides.js index eadcba077b..8d47fb2d5f 100644 --- a/js/ui/overrides.js +++ b/js/ui/overrides.js @@ -243,16 +243,25 @@ function installPolyfills(readOnlyError) { // These abstractions around Mainloop are safer and easier // to use for people learning GObject introspection bindings. - Object.defineProperty(window, 'setTimeout', { - get: function() { - return setTimeout; - }, - set: function() { - readOnlyError('setTimeout'); - }, - configurable: false, - enumerable: false - }); + + // Starting with mozjs 102, these polyfills are no longer needed, and will + // crash Cinnamon if we try to redifine them. Try to do the first one and bail + // if it complains (TypeError: can't redefine non-configurable property) + try { + Object.defineProperty(window, 'setTimeout', { + get: function() { + return setTimeout; + }, + set: function() { + readOnlyError('setTimeout'); + }, + configurable: false, + enumerable: false + }); + } catch (e) { + return; + } + Object.defineProperty(window, 'clearTimeout', { get: function() { return clearTimeout; From b894e9189d235e8740fa9848724fc325de299fb3 Mon Sep 17 00:00:00 2001 From: hduelme <46139144+hduelme@users.noreply.github.com> Date: Tue, 7 Mar 2023 20:16:26 +0100 Subject: [PATCH 09/30] added type hints to util.py (#11291) * added type hints to util.py * use Optional to support 3.6+ --- .../cinnamon/cinnamon-menu-editor/cme/util.py | 26 ++++++++++--------- .../cinnamon/cinnamon-settings/bin/util.py | 6 ++--- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/files/usr/share/cinnamon/cinnamon-menu-editor/cme/util.py b/files/usr/share/cinnamon/cinnamon-menu-editor/cme/util.py index 1343b9cbf9..4c6f7a8bbb 100644 --- a/files/usr/share/cinnamon/cinnamon-menu-editor/cme/util.py +++ b/files/usr/share/cinnamon/cinnamon-menu-editor/cme/util.py @@ -20,6 +20,8 @@ import xml.dom.minidom import uuid import sys +from typing import Optional + if sys.version_info[:2] >= (3, 8): from collections.abc import Sequence else: @@ -29,7 +31,7 @@ DESKTOP_GROUP = GLib.KEY_FILE_DESKTOP_GROUP KEY_FILE_FLAGS = GLib.KeyFileFlags.KEEP_COMMENTS | GLib.KeyFileFlags.KEEP_TRANSLATIONS -def fillKeyFile(keyfile, items): +def fillKeyFile(keyfile, items) -> None: for key, item in items.items(): if item is None: continue @@ -57,14 +59,14 @@ def getUniqueFileId(name, extension): break return filename -def getUniqueRedoFile(filepath): +def getUniqueRedoFile(filepath) -> str: while 1: new_filepath = filepath + '.redo-' + str(uuid.uuid1()) if not os.path.isfile(new_filepath): break return new_filepath -def getUniqueUndoFile(filepath): +def getUniqueUndoFile(filepath) -> str: filename, extension = os.path.split(filepath)[1].rsplit('.', 1) while 1: if extension == 'desktop': @@ -78,46 +80,46 @@ def getUniqueUndoFile(filepath): break return new_filepath -def getItemPath(file_id): +def getItemPath(file_id) -> Optional[str]: for path in GLib.get_system_data_dirs(): file_path = os.path.join(path, 'applications', file_id) if os.path.isfile(file_path): return file_path return None -def getUserItemPath(): +def getUserItemPath() -> str: item_dir = os.path.join(GLib.get_user_data_dir(), 'applications') if not os.path.isdir(item_dir): os.makedirs(item_dir) return item_dir -def getDirectoryPath(file_id): +def getDirectoryPath(file_id) -> Optional[str]: for path in GLib.get_system_data_dirs(): file_path = os.path.join(path, 'desktop-directories', file_id) if os.path.isfile(file_path): return file_path return None -def getUserDirectoryPath(): +def getUserDirectoryPath() -> str: menu_dir = os.path.join(GLib.get_user_data_dir(), 'desktop-directories') if not os.path.isdir(menu_dir): os.makedirs(menu_dir) return menu_dir -def getUserMenuPath(): +def getUserMenuPath() -> str: menu_dir = os.path.join(GLib.get_user_config_dir(), 'menus') if not os.path.isdir(menu_dir): os.makedirs(menu_dir) return menu_dir -def getSystemMenuPath(file_id): +def getSystemMenuPath(file_id) -> Optional[str]: for path in GLib.get_system_config_dirs(): file_path = os.path.join(path, 'menus', file_id) if os.path.isfile(file_path): return file_path return None -def getUserMenuXml(tree): +def getUserMenuXml(tree) -> str: system_file = getSystemMenuPath(os.path.basename(tree.get_canonical_menu_path())) name = tree.get_root_directory().get_menu_id() menu_xml = "\n" @@ -129,7 +131,7 @@ class SurfaceWrapper: def __init__(self, surface): self.surface = surface -def getIcon(item, widget): +def getIcon(item, widget) -> SurfaceWrapper: wrapper = SurfaceWrapper(None) pixbuf = None if item is None: @@ -163,7 +165,7 @@ def getIcon(item, widget): wrapper.surface = Gdk.cairo_surface_create_from_pixbuf (pixbuf, widget.get_scale_factor(), widget.get_window()) return wrapper -def removeWhitespaceNodes(node): +def removeWhitespaceNodes(node) -> None: remove_list = [] for child in node.childNodes: if child.nodeType == xml.dom.minidom.Node.TEXT_NODE: diff --git a/files/usr/share/cinnamon/cinnamon-settings/bin/util.py b/files/usr/share/cinnamon/cinnamon-settings/bin/util.py index e20dff0e44..e365e60bbe 100644 --- a/files/usr/share/cinnamon/cinnamon-settings/bin/util.py +++ b/files/usr/share/cinnamon/cinnamon-settings/bin/util.py @@ -18,20 +18,20 @@ def strip_syspath_locals(): gsound_context = None -def _get_gsound_context(): +def _get_gsound_context() -> GSound.Context: global gsound_context if gsound_context is None: gsound_context = GSound.Context() gsound_context.init() return gsound_context -def play_sound_name(name, channel = None): +def play_sound_name(name, channel = None) -> None: params = {GSound.ATTR_EVENT_ID: name, GSound.ATTR_MEDIA_ROLE: "test"} if channel is not None: params[GSound.ATTR_CANBERRA_FORCE_CHANNEL] = channel _get_gsound_context().play_simple(params) -def play_sound_file(path, channel = None): +def play_sound_file(path, channel = None) -> None: params = {GSound.ATTR_MEDIA_FILENAME: path, GSound.ATTR_MEDIA_ROLE: "test"} if channel is not None: params[GSound.ATTR_CANBERRA_FORCE_CHANNEL] = channel From 98030f9dba92448778f2d0784388615430753a44 Mon Sep 17 00:00:00 2001 From: Mintulix Date: Tue, 14 Mar 2023 17:29:09 +0100 Subject: [PATCH 10/30] cornerbar@cinnamon.org: added scroll-event from SW++@mohammad-sn (#11321) * cornerbar@cinnamon.org: added scroll-event from SW++@mohammad-sn When you hover the cornerbar and make a scroll-move, e.g. with two fingers up/down on touchpad, you will slide through your workspaces. * Limit scroll event frequency for switching workspaces, and setting to flip direction. --------- Co-authored-by: Michael Webster --- .../applets/cornerbar@cinnamon.org/applet.js | 45 +++++++++++++++++++ .../settings-schema.json | 11 +++++ 2 files changed, 56 insertions(+) diff --git a/files/usr/share/cinnamon/applets/cornerbar@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/cornerbar@cinnamon.org/applet.js index 425a89bf01..e84a968bc2 100644 --- a/files/usr/share/cinnamon/applets/cornerbar@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/cornerbar@cinnamon.org/applet.js @@ -1,4 +1,5 @@ const Applet = imports.ui.applet; +const GLib = imports.gi.GLib; const St = imports.gi.St; const Lang = imports.lang; const Clutter = imports.gi.Clutter; @@ -9,6 +10,8 @@ const SignalManager = imports.misc.signalManager; const Mainloop = imports.mainloop; const Tweener = imports.ui.tweener; +const SCROLL_DELAY = 200; + class CinnamonBarApplet extends Applet.Applet { constructor(orientation, panel_height, instance_id) { super(orientation, panel_height, instance_id); @@ -20,15 +23,20 @@ class CinnamonBarApplet extends Applet.Applet { this.settings.bind("peek-blur", "peek_blur"); this.settings.bind("click-action", "click_action"); this.settings.bind("middle-click-action", "middle_click_action"); + this.settings.bind("scroll-behavior", "scroll_behavior"); this.signals = new SignalManager.SignalManager(null); this.actor.connect('enter-event', Lang.bind(this, this._on_enter)); this.actor.connect('leave-event', Lang.bind(this, this._on_leave)); this.signals.connect(global.stage, 'notify::key-focus', this._on_leave, this); + this.actor.connect('scroll-event', Lang.bind(this, this._on_scroll_event)); this._did_peek = false; this._peek_timeout_id = 0; + this._last_scroll_time = 0; + this._last_scroll_direction = 0; + this.actor.style_class = 'applet-cornerbar-box'; this.setAllowedLayout(Applet.AllowedLayout.BOTH); @@ -154,6 +162,43 @@ class CinnamonBarApplet extends Applet.Applet { } } + _on_scroll_event(actor,event) { + if (this.scroll_behavior == "nothing") { + return GLib.SOURCE_CONTINUE; + } + + if (this._peek_timeout_id > 0) { + Mainloop.source_remove(this._peek_timeout_id); + this._peek_timeout_id = 0; + } + + const edir = event.get_scroll_direction(); + if (edir == Clutter.ScrollDirection.SMOOTH) { + return GLib.SOURCE_CONTINUE; + } + + const etime = event.get_time(); + if (etime > (this._last_scroll_time + SCROLL_DELAY) || + edir !== this._last_scroll_direction) { + + let index = global.screen.get_active_workspace_index(); + + if ((edir == Clutter.ScrollDirection.UP) == (this.scroll_behavior == "normal")) + index = index - 1; + else + index = index + 1; + + if (global.screen.get_workspace_by_index(index) != null) { + global.screen.get_workspace_by_index(index).activate(global.get_current_time()); + } + + this._last_scroll_direction = edir; + this._last_scroll_time = etime; + } + + return GLib.SOURCE_CONTINUE; + } + show_all_windows(time) { let windows = global.get_window_actors(); for(let i = 0; i < windows.length; i++){ diff --git a/files/usr/share/cinnamon/applets/cornerbar@cinnamon.org/settings-schema.json b/files/usr/share/cinnamon/applets/cornerbar@cinnamon.org/settings-schema.json index db84ba405a..e0e8e66b91 100644 --- a/files/usr/share/cinnamon/applets/cornerbar@cinnamon.org/settings-schema.json +++ b/files/usr/share/cinnamon/applets/cornerbar@cinnamon.org/settings-schema.json @@ -25,6 +25,17 @@ "Show the window selector (Scale)": "show_scale" } }, + "scroll-behavior": { + "type": "combobox", + "default": "none", + "description": "Scroll wheel behavior", + "tooltip": ".", + "options": { + "Nothing": "nothing", + "Switch workspaces": "normal", + "Switch workspaces (reversed)": "reversed" + } + }, "peek-at-desktop" : { "type" : "switch", "default" : false, From 791ee48204a6752cf925fb65527341207ac2c247 Mon Sep 17 00:00:00 2001 From: Clement Lefebvre Date: Mon, 20 Mar 2023 11:05:08 +0000 Subject: [PATCH 11/30] cs_themes: Add a simplified UI (#11548) * cs_themes: Add a simplified UI * UI: Padding adjustments * Only show "Custom" in the combobox when needed * Show the custom page if the system uses a custom set of themes * Support default modes and variants * Simplify code * Refresh combo as part of refresh Load themes earlier to be able to access them from anywhere in the code. * Refactor code to use Classes * Refactor theme loading * Check if themes are installed * l10n: Go back to original msgids * Remove legacy/dark sorting Joseph doesn't like it ;) It doesn't work well with some of the themes which don't follow our naming convention. * Refresh custom page before showing it * Tune msgid * Add HighContrast to styles * Add HiDPI support * Make dots slightly larger --- .../cinnamon-settings/appearance-dark.svg | 318 ++++++++++ .../cinnamon-settings/appearance-light.svg | 318 ++++++++++ .../cinnamon-settings/appearance-mixed.svg | 286 +++++++++ .../cinnamon/cinnamon-settings/color_dot.svg | 85 +++ .../cinnamon-settings/modules/cs_themes.py | 546 ++++++++++++++---- .../cinnamon/cinnamon-settings/themes.ui | 352 +++++++++++ .../cinnamon/styles.d/00_cinnamon.styles | 22 + 7 files changed, 1799 insertions(+), 128 deletions(-) create mode 100644 files/usr/share/cinnamon/cinnamon-settings/appearance-dark.svg create mode 100644 files/usr/share/cinnamon/cinnamon-settings/appearance-light.svg create mode 100644 files/usr/share/cinnamon/cinnamon-settings/appearance-mixed.svg create mode 100644 files/usr/share/cinnamon/cinnamon-settings/color_dot.svg create mode 100644 files/usr/share/cinnamon/cinnamon-settings/themes.ui create mode 100644 files/usr/share/cinnamon/styles.d/00_cinnamon.styles diff --git a/files/usr/share/cinnamon/cinnamon-settings/appearance-dark.svg b/files/usr/share/cinnamon/cinnamon-settings/appearance-dark.svg new file mode 100644 index 0000000000..092417d993 --- /dev/null +++ b/files/usr/share/cinnamon/cinnamon-settings/appearance-dark.svg @@ -0,0 +1,318 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/files/usr/share/cinnamon/cinnamon-settings/appearance-light.svg b/files/usr/share/cinnamon/cinnamon-settings/appearance-light.svg new file mode 100644 index 0000000000..ca57c723f0 --- /dev/null +++ b/files/usr/share/cinnamon/cinnamon-settings/appearance-light.svg @@ -0,0 +1,318 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/files/usr/share/cinnamon/cinnamon-settings/appearance-mixed.svg b/files/usr/share/cinnamon/cinnamon-settings/appearance-mixed.svg new file mode 100644 index 0000000000..2dd81a3599 --- /dev/null +++ b/files/usr/share/cinnamon/cinnamon-settings/appearance-mixed.svg @@ -0,0 +1,286 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/files/usr/share/cinnamon/cinnamon-settings/color_dot.svg b/files/usr/share/cinnamon/cinnamon-settings/color_dot.svg new file mode 100644 index 0000000000..da49247810 --- /dev/null +++ b/files/usr/share/cinnamon/cinnamon-settings/color_dot.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py index d646234ff7..c00d84dfe2 100755 --- a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py +++ b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py @@ -1,8 +1,9 @@ #!/usr/bin/python3 import os +import json -from gi.repository import Gtk +from gi.repository import Gtk, GdkPixbuf from xapp.GSettingsWidgets import * from CinnamonGtkSettings import CssRange, CssOverrideSwitch, GtkSettingsSwitch, PreviewWidget, Gtk2ScrollbarSizeEditor @@ -29,6 +30,47 @@ os.path.join(GLib.get_home_dir(), ".themes") ] + [os.path.join(datadir, "themes") for datadir in GLib.get_system_data_dirs()] + +class Style: + def __init__(self, json_obj): + self.name = json_obj["name"] + self.modes = {} + self.default_mode = None + +class Mode: + def __init__(self, name): + self.name = name + self.default_variant = None + self.variants = [] + +class Variant: + def __init__(self, json_obj): + self.name = json_obj["name"] + self.gtk_theme = None + self.icon_theme = None + self.cinnamon_theme = None + self.cursor_theme = None + self.color = "#000000" + self.color2 = "#000000" + if "themes" in json_obj: + themes = json_obj["themes"] + self.gtk_theme = themes + self.icon_theme = themes + self.cinnamon_theme = themes + self.cursor_theme = themes + if "gtk" in json_obj: + self.gtk_theme = json_obj["gtk"] + if "icons" in json_obj: + self.icon_theme = json_obj["icons"] + if "cinnamon" in json_obj: + self.cinnamon_theme = json_obj["cinnamon"] + if "cursor" in json_obj: + self.cursor_theme = json_obj["cursor"] + self.color = json_obj["color"] + self.color2 = self.color + if "color2" in json_obj: + self.color2 = json_obj["color2"] + class Module: comment = _("Manage themes to change how your desktop looks") name = "themes" @@ -42,10 +84,80 @@ def __init__(self, content_box): self.sidePage = sidePage self.refreshing = False # flag to ensure we only refresh once at any given moment + def refresh_themes(self): + # Find all installed themes + self.gtk_themes = [] + self.gtk_theme_names = set() + self.icon_theme_names = [] + self.cinnamon_themes = [] + self.cinnamon_theme_names = set() + self.cursor_themes = [] + self.cursor_theme_names = set() + + # Gtk themes -- Only shows themes that have variations for gtk+-3 and gtk+-2 + for (name, path) in walk_directories(THEME_FOLDERS, self.filter_func_gtk_dir, return_directories=True): + for theme in self.gtk_themes: + if name == theme[0]: + if path == THEME_FOLDERS[0]: + continue + else: + self.gtk_themes.remove(theme) + self.gtk_theme_names.add(name) + self.gtk_themes.append((name, path)) + self.gtk_themes.sort(key=lambda a: a[0].lower()) + + # Cinnamon themes + for (name, path) in walk_directories(THEME_FOLDERS, lambda d: os.path.exists(os.path.join(d, "cinnamon")), return_directories=True): + for theme in self.cinnamon_themes: + if name == theme[0]: + if path == THEME_FOLDERS[0]: + continue + else: + self.cinnamon_themes.remove(theme) + self.cinnamon_theme_names.add(name) + self.cinnamon_themes.append((name, path)) + self.cinnamon_themes.sort(key=lambda a: a[0].lower()) + + # Icon themes + walked = walk_directories(ICON_FOLDERS, lambda d: os.path.isdir(d), return_directories=True) + valid = [] + for directory in walked: + if directory[0] in ("gnome", "hicolor"): + continue + path = os.path.join(directory[1], directory[0], "index.theme") + if os.path.exists(path): + try: + for line in list(open(path)): + if line.startswith("Directories="): + valid.append(directory) + break + except Exception as e: + print (e) + valid.sort(key=lambda a: a[0].lower()) + for (name, path) in valid: + if name not in self.icon_theme_names: + self.icon_theme_names.append(name) + + # Cursor themes + for (name, path) in walk_directories(ICON_FOLDERS, lambda d: os.path.isdir(d) and os.path.exists(os.path.join(d, "cursors")), return_directories=True): + for theme in self.cursor_themes: + if name == theme[0]: + if path == ICON_FOLDERS[0]: + continue + else: + self.cursor_themes.remove(theme) + self.cursor_theme_names.add(name) + self.cursor_themes.append((name, path)) + self.cursor_themes.sort(key=lambda a: a[0].lower()) + def on_module_selected(self): if not self.loaded: print("Loading Themes module") + self.refresh_themes() + + self.ui_ready = True + self.spices = Spice_Harvester('theme', self.window) self.sidePage.stack = SettingsStack() @@ -61,10 +173,57 @@ def on_module_selected(self): self.theme_chooser = self.create_button_chooser(self.settings, 'gtk-theme', 'themes', 'gtk-3.0', button_picture_size=35, menu_pictures_size=35, num_cols=4) self.cinnamon_chooser = self.create_button_chooser(self.cinnamon_settings, 'name', 'themes', 'cinnamon', button_picture_size=60, menu_pictures_size=60*self.scale, num_cols=4) + selected_meta_theme = None + + gladefile = "/usr/share/cinnamon/cinnamon-settings/themes.ui" + builder = Gtk.Builder() + builder.set_translation_domain('cinnamon') + builder.add_from_file(gladefile) + page = builder.get_object("page_themes") + page.show() + + self.style_combo = builder.get_object("style_combo") + self.mixed_button = builder.get_object("mixed_button") + self.dark_button = builder.get_object("dark_button") + self.light_button = builder.get_object("light_button") + self.color_box = builder.get_object("color_box") + self.customize_button = builder.get_object("customize_button") + self.preset_button = builder.get_object("preset_button") + self.color_label = builder.get_object("color_label") + self.main_stack = builder.get_object("main_stack") + self.custom_stack = builder.get_object("custom_stack") + self.active_style = None + self.active_mode_name = None + self.active_variant = None + + # HiDPI support + for mode in ["mixed", "dark", "light"]: + path = f"/usr/share/cinnamon/cinnamon-settings/appearance-{mode}.svg" + pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(path, 112*self.scale, 80*self.scale) + surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, self.scale) + builder.get_object(f"image_{mode}").set_from_surface(surface) + + self.color_dot_svg = "" + with open("/usr/share/cinnamon/cinnamon-settings/color_dot.svg") as f: + self.color_dot_svg = f.read() + + self.reset_look_ui() + + if self.active_variant is None: + self.main_stack.set_visible_child_name("custom_page") + + self.mixed_button.connect("clicked", self.on_mode_button_clicked, "mixed") + self.dark_button.connect("clicked", self.on_mode_button_clicked, "dark") + self.light_button.connect("clicked", self.on_mode_button_clicked, "light") + self.customize_button.connect("clicked", self.on_customize_button_clicked) + self.style_combo.connect("changed", self.on_style_combo_changed) + + self.sidePage.stack.add_named(page, "themes") + page = SettingsPage() - self.sidePage.stack.add_titled(page, "themes", _("Themes")) + self.custom_stack.add_titled(page, "themes", _("Themes")) - settings = page.add_section(_("Themes")) + settings = page.add_section() widget = self.make_group(_("Mouse Pointer"), self.cursor_chooser) settings.add_row(widget) @@ -78,11 +237,18 @@ def on_module_selected(self): widget = self.make_group(_("Desktop"), self.cinnamon_chooser) settings.add_row(widget) + button = Gtk.Button() + button.set_label(_("Simplified settings...")) + button.set_halign(Gtk.Align.END) + button.set_relief(Gtk.ReliefStyle.NONE) + button.connect("clicked", self.on_preset_button_clicked) + page.add(button) + page = DownloadSpicesPage(self, 'theme', self.spices, self.window) - self.sidePage.stack.add_titled(page, 'download', _("Add/Remove")) + self.custom_stack.add_titled(page, 'download', _("Add/Remove")) page = SettingsPage() - self.sidePage.stack.add_titled(page, "options", _("Settings")) + self.custom_stack.add_titled(page, "options", _("Settings")) settings = page.add_section(_("Miscellaneous options")) @@ -95,7 +261,7 @@ def on_module_selected(self): try: import tinycss2 except: - self.refresh() + self.refresh_choosers() return settings = page.add_section(_("Scrollbar behavior")) @@ -159,7 +325,227 @@ def on_module_selected(self): # File monitors can fail when the OS runs out of file handles print(e) - self.refresh() + self.refresh_choosers() + + def is_variant_active(self, variant): + # returns whether or not the given variant corresponds to the currently selected themes + if variant.gtk_theme != self.settings.get_string("gtk-theme"): + return False + if variant.icon_theme != self.settings.get_string("icon-theme"): + return False + if variant.cinnamon_theme != self.cinnamon_settings.get_string("name"): + return False + if variant.cursor_theme != self.settings.get_string("cursor-theme"): + return False + return True + + def is_variant_valid(self, variant): + # returns whether or not the given variant is valid (i.e. made of themes which are currently installed) + if variant.gtk_theme is None: + print("No Gtk theme defined") + return False + if variant.icon_theme is None: + print("No icon theme defined") + return False + if variant.cinnamon_theme is None: + print("No Cinnamon theme defined") + return False + if variant.cursor_theme is None: + print("No cursor theme defined") + return False + if variant.gtk_theme not in self.gtk_theme_names: + print("Gtk theme not found:", variant.gtk_theme) + return False + if variant.icon_theme not in self.icon_theme_names: + print("icon theme not found:", variant.icon_theme) + return False + if variant.cinnamon_theme not in self.cinnamon_theme_names and variant.cinnamon_theme != "cinnamon": + print("Cinnamon theme not found:", variant.cinnamon_theme) + return False + if variant.cursor_theme not in self.cursor_theme_names: + print("Cursor theme not found:", variant.cursor_theme) + return False + return True + + def cleanup_ui(self): + self.mixed_button.set_state_flags(Gtk.StateFlags.NORMAL, True) + self.dark_button.set_state_flags(Gtk.StateFlags.NORMAL, True) + self.light_button.set_state_flags(Gtk.StateFlags.NORMAL, True) + self.mixed_button.set_sensitive(False) + self.dark_button.set_sensitive(False) + self.light_button.set_sensitive(False) + for child in self.color_box.get_children(): + self.color_box.remove(child) + self.color_label.hide() + model = self.style_combo.get_model() + model.clear() + + def reset_look_ui(self): + if not self.ui_ready: + return + + self.ui_ready = False + self.cleanup_ui() + + # Read the JSON files + self.styles = {} + self.style_objects = {} + self.active_style = None + self.active_mode_name = None + self.active_variant = None + + path = "/usr/share/cinnamon/styles.d" + for filename in sorted(os.listdir(path)): + if filename.endswith(".styles"): + try: + with open(os.path.join(path, filename)) as f: + json_text = json.loads(f.read()) + for style_json in json_text["styles"]: + style = Style(style_json) + for mode_name in ["mixed", "dark", "light"]: + if mode_name in style_json: + mode = Mode(mode_name) + for variant_json in style_json[mode_name]: + variant = Variant(variant_json) + if self.is_variant_valid(variant): + # Add the variant to the mode + mode.variants.append(variant) + if mode.default_variant is None: + # Assign the first variant as default + mode.default_variant = variant + if "default" in variant_json and variant_json["default"] == "true": + # Override default if specified + mode.default_variant = variant + # Add the mode to the style (if not done already) + if not mode_name in style.modes: + style.modes[mode_name] = mode + # Set it as the default mode if there's no default mode + if style.default_mode is None: + style.default_mode = mode + # Set active variant variables if the variant is active + if self.is_variant_active(variant): + self.active_style= style + self.active_mode_name = mode_name + self.active_variant = variant + # Override the default mode if specified + if "default" in style_json: + default_name = style_json["default"] + if default_name in style.modes: + style.default_mode = style.modes[default_name] + + if style.default_mode is None: + print ("No valid mode/variants found for style:", style.name) + else: + self.styles[style.name] = style + except Exception as e: + print(f"Failed to parse styles from {filename}.") + print(e) + + # Populate the style combo + for name in sorted(self.styles.keys()): + self.style_combo.append_text(name) + + if self.active_variant is not None: + style = self.active_style + mode = self.active_style.modes[self.active_mode_name] + variant = self.active_variant + print("Found active variant:", style.name, mode.name, variant.name) + # Position the style combo + model = self.style_combo.get_model() + iter = model.get_iter_first() + while (iter != None): + name = model.get_value(iter, 0) + if name == style.name: + self.style_combo.set_active_iter(iter) + break + iter = model.iter_next(iter) + # Set the mode buttons + for mode_name in ["mixed", "dark", "light"]: + if mode_name == "mixed": + button = self.mixed_button + elif mode_name == "dark": + button = self.dark_button + else: + button = self.light_button + # Set the button state + if mode_name == mode.name: + button.set_state_flags(Gtk.StateFlags.CHECKED, True) + else: + button.set_state_flags(Gtk.StateFlags.NORMAL, True) + if mode_name in style.modes: + button.set_sensitive(True) + else: + button.set_sensitive(False) + + if len(mode.variants) > 1: + # Generate the color buttons + self.color_label.show() + for variant in mode.variants: + svg = self.color_dot_svg.replace("#8cffbe", variant.color) + svg = svg.replace("#71718e", variant.color2) + svg = str.encode(svg) + stream = Gio.MemoryInputStream.new_from_bytes(GLib.Bytes.new(svg)) + pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(stream, 22*self.scale, 22*self.scale, True, None) + surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, self.scale) + image = Gtk.Image.new_from_surface(surface) + button = Gtk.ToggleButton() + button.add(image) + button.show_all() + self.color_box.add(button) + if variant == self.active_variant: + button.set_state_flags(Gtk.StateFlags.CHECKED, True) + button.connect("clicked", self.on_color_button_clicked, variant) + else: + # Position style combo on "Custom" + self.style_combo.append_text(_("Custom")) + self.style_combo.set_active(len(self.styles.keys())) + self.ui_ready = True + + def on_customize_button_clicked(self, button): + self.set_button_chooser(self.icon_chooser, self.settings.get_string("icon-theme"), 'icons', 'icons', ICON_SIZE) + self.set_button_chooser(self.cursor_chooser, self.settings.get_string("cursor-theme"), 'icons', 'cursors', 32) + self.set_button_chooser(self.theme_chooser, self.settings.get_string("gtk-theme"), 'themes', 'gtk-3.0', 35) + self.set_button_chooser(self.cinnamon_chooser, self.cinnamon_settings.get_string("name"), 'themes', 'cinnamon', 60) + self.main_stack.set_visible_child_name("custom_page") + + def on_preset_button_clicked(self, button): + self.reset_look_ui() + self.main_stack.set_visible_child_name("preset_page") + + def on_color_button_clicked(self, button, variant): + print("Color button clicked") + self.activate_variant(variant) + + def on_mode_button_clicked(self, button, mode_name): + print("Mode button clicked") + if self.active_style is not None: + mode = self.active_style.modes[mode_name] + self.activate_mode(self.active_style, mode) + + def on_style_combo_changed(self, combobox): + if not self.ui_ready: + return + selected_name = combobox.get_active_text() + if selected_name == None or selected_name == _("Custom"): + return + print("Activating style:", selected_name) + for name in self.styles.keys(): + if name == selected_name: + style = self.styles[name] + mode = style.default_mode + self.activate_mode(style, mode) + + def activate_mode(self, style, mode): + print("Activating mode:", mode.name) + self.activate_variant(mode.default_variant) + + def activate_variant(self, variant): + print("Activating variant:", variant.name) + self.settings.set_string("gtk-theme", variant.gtk_theme) + self.settings.set_string("icon-theme", variant.icon_theme) + self.cinnamon_settings.set_string("name", variant.cinnamon_theme) + self.settings.set_string("cursor-theme", variant.cursor_theme) + self.reset_look_ui() def on_css_override_active_changed(self, switch, pspec=None, data=None): if self.scrollbar_switch.get_active(): @@ -177,27 +563,20 @@ def on_file_changed(self, file, other, event, data): self.refreshing = True GLib.timeout_add_seconds(5, self.refresh) - def refresh(self): - choosers = [(self.cursor_chooser, "cursors", self._load_cursor_themes(), self._on_cursor_theme_selected), - (self.theme_chooser, "gtk-3.0", self._load_gtk_themes(), self._on_gtk_theme_selected), - (self.cinnamon_chooser, "cinnamon", self._load_cinnamon_themes(), self._on_cinnamon_theme_selected), - (self.icon_chooser, "icons", self._load_icon_themes(), self._on_icon_theme_selected)] - for chooser in choosers: - chooser[0].clear_menu() - chooser[0].set_sensitive(False) - chooser[0].progress = 0.0 - - chooser_obj = chooser[0] - path_suffix = chooser[1] - themes = chooser[2] - callback = chooser[3] - payload = (chooser_obj, path_suffix, themes, callback) - self.refresh_chooser(payload) + def refresh_choosers(self): + array = [(self.cursor_chooser, "cursors", self.cursor_themes, self._on_cursor_theme_selected), + (self.theme_chooser, "gtk-3.0", self.gtk_themes, self._on_gtk_theme_selected), + (self.cinnamon_chooser, "cinnamon", self.cinnamon_themes, self._on_cinnamon_theme_selected), + (self.icon_chooser, "icons", self.icon_theme_names, self._on_icon_theme_selected)] + for element in array: + chooser, path_suffix, themes, callback = element + chooser.clear_menu() + chooser.set_sensitive(False) + chooser.progress = 0.0 + self.refresh_chooser(chooser, path_suffix, themes, callback) self.refreshing = False - def refresh_chooser(self, payload): - (chooser, path_suffix, themes, callback) = payload - + def refresh_chooser(self, chooser, path_suffix, themes, callback): inc = 1.0 if len(themes) > 0: inc = 1.0 / len(themes) @@ -307,8 +686,11 @@ def make_group(self, group_label, widget, add_widget_to_size_group=True): def create_button_chooser(self, settings, key, path_prefix, path_suffix, button_picture_size, menu_pictures_size, num_cols): chooser = PictureChooserButton(num_cols=num_cols, button_picture_size=button_picture_size, menu_pictures_size=menu_pictures_size, has_button_label=True) theme = settings.get_string(key) - chooser.set_button_label(theme) - chooser.set_tooltip_text(theme) + self.set_button_chooser(chooser, theme, path_prefix, path_suffix, button_picture_size) + return chooser + + def set_button_chooser(self, chooser, theme, path_prefix, path_suffix, button_picture_size): + self.set_button_chooser_text(chooser, theme) if path_suffix == "cinnamon" and theme == "cinnamon": chooser.set_picture_from_file("/usr/share/cinnamon/theme/thumbnail.png") elif path_suffix == "icons": @@ -328,13 +710,15 @@ def create_button_chooser(self, settings, key, path_prefix, path_suffix, button_ break except: chooser.set_picture_from_file("/usr/share/cinnamon/thumbnails/%s/unknown.png" % path_suffix) - return chooser + + def set_button_chooser_text(self, chooser, theme): + chooser.set_button_label(theme) + chooser.set_tooltip_text(theme) def _on_icon_theme_selected(self, path, theme): try: self.settings.set_string("icon-theme", theme) - self.icon_chooser.set_button_label(theme) - self.icon_chooser.set_tooltip_text(theme) + self.set_button_chooser_text(self.icon_chooser, theme) except Exception as detail: print(detail) return True @@ -342,8 +726,7 @@ def _on_icon_theme_selected(self, path, theme): def _on_gtk_theme_selected(self, path, theme): try: self.settings.set_string("gtk-theme", theme) - self.theme_chooser.set_button_label(theme) - self.theme_chooser.set_tooltip_text(theme) + self.set_button_chooser_text(self.theme_chooser, theme) except Exception as detail: print(detail) return True @@ -351,8 +734,7 @@ def _on_gtk_theme_selected(self, path, theme): def _on_cursor_theme_selected(self, path, theme): try: self.settings.set_string("cursor-theme", theme) - self.cursor_chooser.set_button_label(theme) - self.cursor_chooser.set_tooltip_text(theme) + self.set_button_chooser_text(self.cursor_chooser, theme) except Exception as detail: print(detail) @@ -362,111 +744,19 @@ def _on_cursor_theme_selected(self, path, theme): def _on_cinnamon_theme_selected(self, path, theme): try: self.cinnamon_settings.set_string("name", theme) - self.cinnamon_chooser.set_button_label(theme) - self.cinnamon_chooser.set_tooltip_text(theme) + self.set_button_chooser_text(self.cinnamon_chooser, theme) except Exception as detail: print(detail) return True - def get_theme_sort_key(self, name): - name = name.lower() - legacy = 0 - darker = 0 - dark = 0 - if "legacy" in name: - legacy = 1 - if "darker" in name: - darker = 1 - if "dark" in name and "darker" not in name: - dark = 1 - name = name.replace("darker", "").replace("dark", "").replace("legacy", "") - name = f"{legacy}{dark}{darker}{name}" - return name - - def _load_gtk_themes(self): - """ Only shows themes that have variations for gtk+-3 and gtk+-2 """ - dirs = THEME_FOLDERS - valid = walk_directories(dirs, self.filter_func_gtk_dir, return_directories=True) - valid.sort(key=lambda a: self.get_theme_sort_key(a[0])) - res = [] - for i in valid: - for j in res: - if i[0] == j[0]: - if i[1] == dirs[0]: - continue - else: - res.remove(j) - res.append((i[0], i[1])) - return res - def filter_func_gtk_dir(self, directory): theme_dir = Path(directory) - for gtk3_dir in theme_dir.glob("gtk-3.*"): # Skip gtk key themes if os.path.exists(os.path.join(gtk3_dir, "gtk.css")): return True return False - def _load_icon_themes(self): - dirs = ICON_FOLDERS - walked = walk_directories(dirs, lambda d: os.path.isdir(d), return_directories=True) - valid = [] - for directory in walked: - if directory[0] in ("gnome", "hicolor"): - continue - path = os.path.join(directory[1], directory[0], "index.theme") - if os.path.exists(path): - try: - for line in list(open(path)): - if line.startswith("Directories="): - valid.append(directory) - break - except Exception as e: - print (e) - - valid.sort(key=lambda a: self.get_theme_sort_key(a[0])) - res = [] - for i in valid: - for j in res: - if i[0] == j: - if i[1] == dirs[0]: - continue - else: - res.remove(j) - res.append(i[0]) - return res - - def _load_cursor_themes(self): - dirs = ICON_FOLDERS - valid = walk_directories(dirs, lambda d: os.path.isdir(d) and os.path.exists(os.path.join(d, "cursors")), return_directories=True) - valid.sort(key=lambda a: a[0].lower()) - res = [] - for i in valid: - for j in res: - if i[0] == j[0]: - if i[1] == dirs[0]: - continue - else: - res.remove(j) - res.append((i[0], i[1])) - return res - - def _load_cinnamon_themes(self): - dirs = THEME_FOLDERS - valid = walk_directories(dirs, lambda d: os.path.exists(os.path.join(d, "cinnamon")), return_directories=True) - valid.sort(key=lambda a: self.get_theme_sort_key(a[0])) - res = [] - for i in valid: - for j in res: - if i[0] == j[0]: - if i[1] == dirs[0]: - continue - else: - res.remove(j) - res.append((i[0], i[1])) - return res - def update_cursor_theme_link(self, path, name): default_dir = os.path.join(ICON_FOLDERS[0], "default") index_path = os.path.join(default_dir, "index.theme") diff --git a/files/usr/share/cinnamon/cinnamon-settings/themes.ui b/files/usr/share/cinnamon/cinnamon-settings/themes.ui new file mode 100644 index 0000000000..edd98d97da --- /dev/null +++ b/files/usr/share/cinnamon/cinnamon-settings/themes.ui @@ -0,0 +1,352 @@ + + + + + + True + False + vertical + + + True + False + + + True + True + never + + + True + False + + + + True + False + center + start + 90 + 90 + 45 + 16 + 16 + + + True + False + start + Appearance + + + + + + 0 + 1 + + + + + True + False + start + Color + + + + + + 0 + 3 + + + + + True + False + In mixed mode most applications are light. Some desktop elements and multimedia apps are dark to create contrast. + True + + + 1 + 2 + + + + + True + False + False + True + expand + + + True + False + True + True + + + True + False + 0 + vertical + + + True + False + appearance-mixed.svg + + + False + True + 0 + + + + + True + False + 3 + Mixed + + + + + + False + True + 1 + + + + + + + True + True + 0 + + + + + True + False + True + True + + + True + False + vertical + + + True + False + appearance-dark.svg + + + False + True + 0 + + + + + True + False + 3 + Dark + + + + + + False + True + 1 + + + + + + + True + True + 1 + + + + + True + False + True + True + + + True + False + vertical + + + True + False + appearance-light.svg + + + False + True + 0 + + + + + True + False + 3 + Light + + + + + + False + True + 1 + + + + + + + True + True + 2 + + + + + 1 + 1 + + + + + True + False + False + True + expand + + + + + + 1 + 3 + + + + + Advanced settings... + True + True + True + end + none + + + 1 + 4 + + + + + True + False + start + Style + + + + + + 0 + 0 + + + + + True + False + + + 1 + 0 + + + + + + + + + + + + + + + preset_page + + + + + True + False + 12 + vertical + 16 + + + True + False + center + custom_stack + + + False + True + 0 + + + + + True + False + + + + + + True + True + 1 + + + + + custom_page + 1 + + + + + True + True + 0 + + + + diff --git a/files/usr/share/cinnamon/styles.d/00_cinnamon.styles b/files/usr/share/cinnamon/styles.d/00_cinnamon.styles new file mode 100644 index 0000000000..96fda3d3c6 --- /dev/null +++ b/files/usr/share/cinnamon/styles.d/00_cinnamon.styles @@ -0,0 +1,22 @@ +{ + "styles": [ + { + "name": "Adwaita", + "default": "mixed", + "mixed": [ + {"default": "true", "name": "blue", "color": "#3584e4", "themes": "Adwaita", "cinnamon": "cinnamon"} + ], + "dark": [ + {"name": "blue", "color": "#15539e", "themes": "Adwaita-dark", "icons": "Adwaita", "cinnamon": "cinnamon", "cursor": "Adwaita"} + ], + "light": [] + }, + { + "name": "HighContrast", + "default": "light", + "light": [ + {"default": "true", "name": "contrast", "color": "#000000", "themes": "HighContrast", "cinnamon": "cinnamon", "cursor": "Adwaita"} + ] + } + ] +} From eb3371a60ce1f64d5b8be2d1f71a9a545fb9aacd Mon Sep 17 00:00:00 2001 From: claudiux <33965039+claudiux@users.noreply.github.com> Date: Mon, 20 Mar 2023 17:21:24 +0100 Subject: [PATCH 12/30] Update applet.js (#11484) to solve #11483. --- .../share/cinnamon/applets/notifications@cinnamon.org/applet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/usr/share/cinnamon/applets/notifications@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/notifications@cinnamon.org/applet.js index 0cb629b07e..ccbb110676 100644 --- a/files/usr/share/cinnamon/applets/notifications@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/notifications@cinnamon.org/applet.js @@ -201,7 +201,7 @@ class CinnamonNotificationsApplet extends Applet.TextIconApplet { if (!this.showNotificationCount) { // Don't show notification count this.set_applet_label(''); - this.clear_action.actor.hide(); + // this.clear_action.actor.hide(); } this.menu_label.label.set_text(stringify(count)); this._notificationbin.queue_relayout(); From 8b56f4d5ac49c3ec735481d4182686823249faa7 Mon Sep 17 00:00:00 2001 From: Rick Calixte <10281587+rcalixte@users.noreply.github.com> Date: Thu, 24 Nov 2022 21:56:52 -0500 Subject: [PATCH 13/30] Adding a setting to warp mouse pointer after Alt+Tab action completes --- data/org.cinnamon.gschema.xml | 5 +++++ .../cinnamon-settings/modules/cs_windows.py | 3 +++ js/ui/appSwitcher/appSwitcher.js | 13 +++++++++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/data/org.cinnamon.gschema.xml b/data/org.cinnamon.gschema.xml index bfb8530a0f..5576e3072b 100644 --- a/data/org.cinnamon.gschema.xml +++ b/data/org.cinnamon.gschema.xml @@ -429,6 +429,11 @@ Show all windows from all workspaces + + false + Warp mouse pointer to the new focused window + + false not used - lives in org.cinnamon.muffin now diff --git a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_windows.py b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_windows.py index 6427f3e6cf..a7780471fb 100755 --- a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_windows.py +++ b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_windows.py @@ -178,3 +178,6 @@ def update_setting(widget, pspec): widget = GSettingsSwitch(_("Show windows from all workspaces"), "org.cinnamon", "alttab-switcher-show-all-workspaces") settings.add_row(widget) + + widget = GSettingsSwitch(_("Warp mouse pointer to the new focused window"), "org.cinnamon", "alttab-switcher-warp-mouse-pointer") + settings.add_row(widget) diff --git a/js/ui/appSwitcher/appSwitcher.js b/js/ui/appSwitcher/appSwitcher.js index 8f6b79e843..035c882d55 100644 --- a/js/ui/appSwitcher/appSwitcher.js +++ b/js/ui/appSwitcher/appSwitcher.js @@ -428,8 +428,17 @@ AppSwitcher.prototype = { }, _activateSelected: function() { - let workspace_num = this._windows[this._currentIndex].get_workspace().index(); - Main.activateWindow(this._windows[this._currentIndex], global.get_current_time(), workspace_num); + const _window = this._windows[this._currentIndex] + const workspace_num = _window.get_workspace().index(); + Main.activateWindow(_window, global.get_current_time(), workspace_num); + this._warpMouse = global.settings.get_boolean("alttab-switcher-warp-mouse-pointer"); + if (this._warpMouse) { + const rect = _window.get_frame_rect(); + const x = rect.x + rect.width / 2; + const y = rect.y + rect.height / 2; + this._pointer = Clutter.get_default_backend().get_default_seat().create_virtual_device(Clutter.InputDeviceType.POINTER_DEVICE); + this._pointer.notify_absolute_motion(global.get_current_time(), x, y); + } if (!this._destroyed) this.destroy(); }, From 19fa83fb64c300a4a3ca22b5e42ff082fe260bae Mon Sep 17 00:00:00 2001 From: Rick Calixte <10281587+rcalixte@users.noreply.github.com> Date: Thu, 24 Nov 2022 22:08:38 -0500 Subject: [PATCH 14/30] Fix whitespace --- js/ui/appSwitcher/appSwitcher.js | 116 +++++++++++++++---------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/js/ui/appSwitcher/appSwitcher.js b/js/ui/appSwitcher/appSwitcher.js index 035c882d55..16c2378d53 100644 --- a/js/ui/appSwitcher/appSwitcher.js +++ b/js/ui/appSwitcher/appSwitcher.js @@ -17,17 +17,17 @@ function sortWindowsByUserTime(win1, win2) { this.minimizedAwareAltTab = global.settings.get_boolean("alttab-minimized-aware"); if (this.minimizedAwareAltTab) { - let m1 = win1.minimized; - let m2 = win2.minimized; - if (m1 == m2) { - return (t2 > t1) ? 1 : -1; - } - else { - return m1 ? 1 : -1; - } + let m1 = win1.minimized; + let m2 = win2.minimized; + if (m1 == m2) { + return (t2 > t1) ? 1 : -1; + } + else { + return m1 ? 1 : -1; + } } else { - return (t2 > t1) ? 1 : -1; + return (t2 > t1) ? 1 : -1; } } @@ -62,29 +62,29 @@ function getWindowsForBinding(binding) { for (let i in windowActors) windows.push(windowActors[i].get_meta_window()); - windows = windows.filter( Main.isInteresting ); + windows = windows.filter(Main.isInteresting); - switch(binding.get_name()) { + switch (binding.get_name()) { case 'switch-panels': case 'switch-panels-backward': // Switch between windows of all workspaces - windows = windows.filter( matchSkipTaskbar ); + windows = windows.filter(matchSkipTaskbar); break; case 'switch-group': case 'switch-group-backward': // Switch between windows of the same application let focused = global.display.focus_window ? global.display.focus_window : windows[0]; - windows = windows.filter( matchWmClass, focused.get_wm_class() ); + windows = windows.filter(matchWmClass, focused.get_wm_class()); this._showAllWorkspaces = global.settings.get_boolean("alttab-switcher-show-all-workspaces"); if (!this._showAllWorkspaces) { - windows = windows.filter( matchWorkspace, global.workspace_manager.get_active_workspace() ); + windows = windows.filter(matchWorkspace, global.workspace_manager.get_active_workspace()); } break; default: // Switch between windows of current workspace this._showAllWorkspaces = global.settings.get_boolean("alttab-switcher-show-all-workspaces"); if (!this._showAllWorkspaces) { - windows = windows.filter( matchWorkspace, global.workspace_manager.get_active_workspace() ); + windows = windows.filter(matchWorkspace, global.workspace_manager.get_active_workspace()); } break; } @@ -100,7 +100,7 @@ function AppSwitcher() { } AppSwitcher.prototype = { - _init: function(binding) { + _init: function (binding) { this._initialDelayTimeoutId = null; this._binding = binding; this._windows = getWindowsForBinding(binding); @@ -124,7 +124,7 @@ AppSwitcher.prototype = { this._updateActiveMonitor(); }, - _setupModal: function() { + _setupModal: function () { this._haveModal = Main.pushModal(this.actor); if (!this._haveModal) { // Probably someone else has a pointer grab, try again with keyboard only @@ -161,57 +161,57 @@ AppSwitcher.prototype = { return this._haveModal; }, - _popModal: function() { + _popModal: function () { if (this._haveModal) { Main.popModal(this.actor); this._haveModal = false; } }, - _show: function() { + _show: function () { throw new Error("Abstract method _show not implemented"); }, - _hide: function() { + _hide: function () { throw new Error("Abstract method _hide not implemented"); }, - _onDestroy: function() { + _onDestroy: function () { throw new Error("Abstract method _onDestroy not implemented"); }, - _createList: function() { + _createList: function () { throw new Error("Abstract method _createList not implemented"); }, - _updateList: function() { + _updateList: function () { throw new Error("Abstract method _updateList not implemented"); }, - _selectNext: function() { + _selectNext: function () { throw new Error("Abstract method _selectNext not implemented"); }, - _selectPrevious: function() { + _selectPrevious: function () { throw new Error("Abstract method _selectPrevious not implemented"); }, - _onWorkspaceSelected: function() { + _onWorkspaceSelected: function () { throw new Error("Abstract method _onWorkspaceSelected not implemented"); }, - _checkSwitchTime: function() { + _checkSwitchTime: function () { return true; }, - _setCurrentWindow: function(window) { + _setCurrentWindow: function (window) { }, - _next: function() { + _next: function () { if (!this._windows) return; - if(this._windows.length <= 1) { + if (this._windows.length <= 1) { this._currentIndex = 0; this._updateList(0); } else { @@ -222,11 +222,11 @@ AppSwitcher.prototype = { this._setCurrentWindow(this._windows[this._currentIndex]); }, - _previous: function() { + _previous: function () { if (!this._windows) return; - if(this._windows.length <= 1) { + if (this._windows.length <= 1) { this._currentIndex = 0; this._updateList(0); } else { @@ -237,7 +237,7 @@ AppSwitcher.prototype = { this._setCurrentWindow(this._windows[this._currentIndex]); }, - _select: function(index) { + _select: function (index) { if (!this._windows) return; @@ -245,7 +245,7 @@ AppSwitcher.prototype = { this._setCurrentWindow(this._windows[this._currentIndex]); }, - _updateActiveMonitor: function() { + _updateActiveMonitor: function () { this._activeMonitor = null; if (!this._enforcePrimaryMonitor) this._activeMonitor = Main.layoutManager.currentMonitor; @@ -255,7 +255,7 @@ AppSwitcher.prototype = { return this._activeMonitor; }, - _keyPressEvent: function(actor, event) { + _keyPressEvent: function (actor, event) { let modifiers = Cinnamon.get_event_state(event); let symbol = event.get_key_symbol(); let keycode = event.get_key_code(); @@ -266,7 +266,7 @@ AppSwitcher.prototype = { // Switch workspace if (modifiers & Clutter.ModifierType.CONTROL_MASK && - (symbol === Clutter.KEY_Right || symbol === Clutter.KEY_Left)) { + (symbol === Clutter.KEY_Right || symbol === Clutter.KEY_Left)) { if (this._switchWorkspace(symbol)) return true; } @@ -293,14 +293,14 @@ AppSwitcher.prototype = { case Clutter.KEY_Right: case Clutter.KEY_Down: // Right/Down -> navigate to next preview - if(this._checkSwitchTime()) + if (this._checkSwitchTime()) this._next(); return true; case Clutter.KEY_Left: case Clutter.KEY_Up: // Left/Up -> navigate to previous preview - if(this._checkSwitchTime()) + if (this._checkSwitchTime()) this._previous(); return true; } @@ -310,7 +310,7 @@ AppSwitcher.prototype = { case Meta.KeyBindingAction.SWITCH_GROUP: case Meta.KeyBindingAction.SWITCH_WINDOWS: case Meta.KeyBindingAction.SWITCH_PANELS: - if(this._checkSwitchTime()) { + if (this._checkSwitchTime()) { // shift -> backwards if (modifiers & Clutter.ModifierType.SHIFT_MASK) this._previous(); @@ -321,7 +321,7 @@ AppSwitcher.prototype = { case Meta.KeyBindingAction.SWITCH_GROUP_BACKWARD: case Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD: case Meta.KeyBindingAction.SWITCH_PANELS_BACKWARD: - if(this._checkSwitchTime()) + if (this._checkSwitchTime()) this._previous(); return true; } @@ -329,7 +329,7 @@ AppSwitcher.prototype = { return true; }, - _keyReleaseEvent: function(actor, event) { + _keyReleaseEvent: function (actor, event) { let [x, y, mods] = global.get_pointer(); let state = mods & this._modifierMask; @@ -342,17 +342,17 @@ AppSwitcher.prototype = { return true; }, - _failedGrabAction: function() { + _failedGrabAction: function () { if (!["coverflow", "timeline"].includes(global.settings.get_string('alttab-switcher-style'))) { this._keyReleaseEvent(null, null); } }, // allow navigating by mouse-wheel scrolling - _scrollEvent: function(actor, event) { + _scrollEvent: function (actor, event) { if (event.get_scroll_direction() == Clutter.ScrollDirection.SMOOTH) return Clutter.EVENT_STOP; - if(this._checkSwitchTime()) { + if (this._checkSwitchTime()) { actor.set_reactive(false); if (event.get_scroll_direction() == Clutter.ScrollDirection.UP) this._previous(); @@ -363,7 +363,7 @@ AppSwitcher.prototype = { return true; }, - _disableHover : function() { + _disableHover: function () { this._mouseActive = false; if (this._motionTimeoutId != 0) @@ -372,12 +372,12 @@ AppSwitcher.prototype = { this._motionTimeoutId = Mainloop.timeout_add(DISABLE_HOVER_TIMEOUT, Lang.bind(this, this._mouseTimedOut)); }, - _mouseTimedOut : function() { + _mouseTimedOut: function () { this._motionTimeoutId = 0; this._mouseActive = true; }, - _switchWorkspace: function(direction) { + _switchWorkspace: function (direction) { if (global.workspace_manager.n_workspaces < 2) return false; @@ -398,11 +398,11 @@ AppSwitcher.prototype = { return true; }, - _windowDestroyed: function(wm, actor) { + _windowDestroyed: function (wm, actor) { this._removeDestroyedWindow(actor.meta_window); }, - _removeDestroyedWindow: function(window) { + _removeDestroyedWindow: function (window) { for (let i in this._windows) { if (window == this._windows[i]) { if (this._windows.length == 1) @@ -427,23 +427,23 @@ AppSwitcher.prototype = { } }, - _activateSelected: function() { + _activateSelected: function () { const _window = this._windows[this._currentIndex] const workspace_num = _window.get_workspace().index(); Main.activateWindow(_window, global.get_current_time(), workspace_num); this._warpMouse = global.settings.get_boolean("alttab-switcher-warp-mouse-pointer"); if (this._warpMouse) { - const rect = _window.get_frame_rect(); - const x = rect.x + rect.width / 2; - const y = rect.y + rect.height / 2; - this._pointer = Clutter.get_default_backend().get_default_seat().create_virtual_device(Clutter.InputDeviceType.POINTER_DEVICE); - this._pointer.notify_absolute_motion(global.get_current_time(), x, y); + const rect = _window.get_frame_rect(); + const x = rect.x + rect.width / 2; + const y = rect.y + rect.height / 2; + this._pointer = Clutter.get_default_backend().get_default_seat().create_virtual_device(Clutter.InputDeviceType.POINTER_DEVICE); + this._pointer.notify_absolute_motion(global.get_current_time(), x, y); } if (!this._destroyed) this.destroy(); }, - _showDesktop: function() { + _showDesktop: function () { for (let i in this._windows) { if (!this._windows[i].minimized) this._windows[i].minimize(); @@ -451,7 +451,7 @@ AppSwitcher.prototype = { this.destroy(); }, - destroy: function() { + destroy: function () { this._destroyed = true; this._popModal(); @@ -460,7 +460,7 @@ AppSwitcher.prototype = { else this._hide(); - if(this._initialDelayTimeoutId !== null && this._initialDelayTimeoutId > 0) { + if (this._initialDelayTimeoutId !== null && this._initialDelayTimeoutId > 0) { Mainloop.source_remove(this._initialDelayTimeoutId); this._initialDelayTimeoutId = 0; } From 92db06163182300346b7fc455202a47aabd38691 Mon Sep 17 00:00:00 2001 From: fredcw Date: Mon, 20 Mar 2023 18:41:01 +0000 Subject: [PATCH 15/30] Add category hover style for Cinnamenu applet... (#11451) ... and possible future use in the menu applet which currently uses `.menu-category-button-selected` style for hover (pseudo class `hover` is only used when the 'activate categories on click' menu option is set) This also works well as a reasonable fallback style in other light & dark themes as it will add to the style of `.menu-category-button` in themes where `.menu-category-button:hover` is not defined. --- data/theme/cinnamon.css | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/data/theme/cinnamon.css b/data/theme/cinnamon.css index dddd2d09bf..dda57d8b31 100644 --- a/data/theme/cinnamon.css +++ b/data/theme/cinnamon.css @@ -1244,6 +1244,11 @@ StScrollBar StButton#vhandle:hover { padding-right: 7px; padding-bottom: 7px; } +.menu-category-button:hover { + background-color: rgba(128,128,128,0.2); + border-radius: 4px; + border-image: none; +} .menu-category-button-greyed { padding-top: 7px; padding-left: 7px; @@ -1272,9 +1277,6 @@ StScrollBar StButton#vhandle:hover { } .menu-category-button-label:rtl { padding-right: 5px; - -} -.menu-category-button-selected:hover { } /* Name and description of the currently hovered item in the menu * This appears on the bottom right hand corner of the menu*/ @@ -2095,4 +2097,4 @@ StScrollBar StButton#vhandle:hover { -pie-border-width: 1px; -pie-border-color: rgba(200, 200, 200, 0.8); -pie-background-color: rgba(140, 140, 140, 0.6);; -} \ No newline at end of file +} From 7a610d7822c5ca712a39f2558be417a1d25f738c Mon Sep 17 00:00:00 2001 From: Axel <72220889+axel358@users.noreply.github.com> Date: Mon, 20 Mar 2023 14:43:17 -0400 Subject: [PATCH 16/30] feat(menu@cinnamon.org): Add Menu editor entry to applet context menu (#11561) * feat(menu@cinnamon.org): Add Menu editor entry to applet context menu * chore(menu@cinnamon.org): Change 'Menu editor' to 'Edit menu' and make it translatable --- files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js index abe9d901cc..5b053f020a 100644 --- a/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js @@ -1174,6 +1174,10 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { this.menu = new Menu(this, orientation); this.menuManager.addMenu(this.menu); + const edit_item = new PopupMenu.PopupIconMenuItem(_("Edit menu"), "document-edit", St.IconType.SYMBOLIC); + edit_item.connect("activate", () => Util.spawnCommandLine("cinnamon-menu-editor")); + this._applet_context_menu.addMenuItem(edit_item); + this.settings = new Settings.AppletSettings(this, "menu@cinnamon.org", instance_id); this.settings.connect("settings-changed", () => { this._size_dirty = true; From 0ff2803fd9d820482c12d6ac099b31c88f47a594 Mon Sep 17 00:00:00 2001 From: Clement Lefebvre Date: Mon, 20 Mar 2023 20:18:04 +0000 Subject: [PATCH 17/30] cs_themes: Add relief to simplified/advanced buttons --- files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py | 1 - files/usr/share/cinnamon/cinnamon-settings/themes.ui | 1 - 2 files changed, 2 deletions(-) diff --git a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py index c00d84dfe2..924dabd0b2 100755 --- a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py +++ b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py @@ -240,7 +240,6 @@ def on_module_selected(self): button = Gtk.Button() button.set_label(_("Simplified settings...")) button.set_halign(Gtk.Align.END) - button.set_relief(Gtk.ReliefStyle.NONE) button.connect("clicked", self.on_preset_button_clicked) page.add(button) diff --git a/files/usr/share/cinnamon/cinnamon-settings/themes.ui b/files/usr/share/cinnamon/cinnamon-settings/themes.ui index edd98d97da..14def0d33f 100644 --- a/files/usr/share/cinnamon/cinnamon-settings/themes.ui +++ b/files/usr/share/cinnamon/cinnamon-settings/themes.ui @@ -254,7 +254,6 @@ True True end - none 1 From a56ecebbf9499da2db8020c17c31ccefda9e7cce Mon Sep 17 00:00:00 2001 From: fredcw Date: Tue, 21 Mar 2023 16:43:06 +0000 Subject: [PATCH 18/30] Use pseudo class 'hover' instead of class ... (#11473) * Use pseudo class 'hover' instead of class ... ... menu-category-button-selected when hovering category buttons when "change category on hover" option is off. Simplify some of the code in _onMenuKeyPress and _buttonEnterEvent. * Fix typo causing regression. * Fix typo causing regression. --- .../applets/menu@cinnamon.org/applet.js | 413 ++++++------------ 1 file changed, 138 insertions(+), 275 deletions(-) diff --git a/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js index 5b053f020a..899e36f242 100644 --- a/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js @@ -933,11 +933,12 @@ class CategoryButton extends SimpleMenuItem { } activate() { - if(this.applet.searchActive) + if(this.applet.searchActive || this.categoryId === this.applet.lastSelectedCategory) return; - - this.applet._clearPrevCatSelection(this.actor, true); this.applet._select_category(this.categoryId); + this.applet._previousSelectedAppActor = null; + this.applet.categoriesBox.get_children().forEach(child => + child.set_style_class_name("menu-category-button")); this.actor.style_class = "menu-category-button-selected"; } } @@ -1240,10 +1241,8 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { this._favoriteDocButtons = []; this._categoryButtons = []; this._searchProviderButtons = []; - this._selectedItemIndex = null; - this._previousSelectedActor = null; - this._previousVisibleIndex = null; - this._previousTreeSelectedActor = null; + this._previousSelectedAppActor = null; + this._previousCategoryHoverActor = null; this._activeContainer = null; this._activeActor = null; this._knownApps = new Set(); // Used to keep track of apps that are already installed, so we can highlight newly installed ones @@ -1473,7 +1472,6 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { if (open) { this.actor.add_style_pseudo_class('active'); global.stage.set_key_focus(this.searchEntry); - this._selectedItemIndex = null; this._activeContainer = null; this._activeActor = null; @@ -1502,11 +1500,10 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { } this.selectedAppTitle.set_text(""); this.selectedAppDescription.set_text(""); - this._previousTreeSelectedActor = null; - this._previousSelectedActor = null; + this._previousCategoryHoverActor = null; + this._previousSelectedAppActor = null; this.closeContextMenu(false); - this._previousVisibleIndex = null; - + this._disableVectorMask(); this._scrollToButton(null, this.applicationsScrollBox); this._scrollToButton(null, this.categoriesScrollBox); @@ -1735,7 +1732,6 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { _onMenuKeyPress(actor, event) { let symbol = event.get_key_symbol(); let item_actor; - let index = 0; this.appBoxIter.reloadVisible(); this.catBoxIter.reloadVisible(); this.favBoxIter.reloadVisible(); @@ -1762,8 +1758,6 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { return true; } - index = this._selectedItemIndex; - let ctrlKey = modifierState & Clutter.ModifierType.CONTROL_MASK; // If a context menu is open, hijack keyboard navigation and concentrate on the context menu. @@ -1794,18 +1788,21 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { let navigationKey = true; let whichWay = "none"; - + if (this._activeContainer === null) { + this._setKeyFocusToCurrentCategoryButton(); + } + switch (symbol) { case Clutter.KEY_Up: whichWay = "up"; if (this._activeContainer === this.favoritesBox && ctrlKey && - (this.favoritesBox.get_child_at_index(index))._delegate instanceof FavoritesButton) + this._activeActor._delegate instanceof FavoritesButton) navigationKey = false; break; case Clutter.KEY_Down: whichWay = "down"; if (this._activeContainer === this.favoritesBox && ctrlKey && - (this.favoritesBox.get_child_at_index(index))._delegate instanceof FavoritesButton) + this._activeActor._delegate instanceof FavoritesButton) navigationKey = false; break; case Clutter.KEY_Page_Up: @@ -1818,7 +1815,7 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { if (this._activeContainer === this.applicationsBox) whichWay = "none"; else if (this._activeContainer === this.categoriesBox && this.noRecentDocuments && - (this.categoriesBox.get_child_at_index(index))._delegate.categoryId === "recent") + this._activeActor._delegate.categoryId === "recent") whichWay = "none"; break; case Clutter.KEY_Left: @@ -1826,8 +1823,7 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { whichWay = "left"; if (this._activeContainer === this.favoritesBox || this._activeContainer === this.systemButtonsBox) whichWay = "none"; - else if (!this.favBoxShow && - (this._activeContainer === this.categoriesBox || this._activeContainer === null)) + else if (!this.favBoxShow && this._activeContainer === this.categoriesBox) whichWay = "none"; break; case Clutter.KEY_Tab: @@ -1848,189 +1844,104 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { if (navigationKey) { switch (this._activeContainer) { - case null: - switch (whichWay) { - case "up": - this._activeContainer = this.categoriesBox; - item_actor = this.catBoxIter.getLastVisible(); - this._scrollToButton(item_actor._delegate, this.categoriesScrollBox); - break; - case "down": - this._activeContainer = this.categoriesBox; - item_actor = this.catBoxIter.getFirstVisible(); - item_actor = this.catBoxIter.getNextVisible(item_actor); - this._scrollToButton(item_actor._delegate, this.categoriesScrollBox); - break; - case "right": - this._activeContainer = this.applicationsBox; - item_actor = this.appBoxIter.getFirstVisible(); - this._scrollToButton(); - break; - case "left": - if (this.favBoxShow) { - this._activeContainer = this.favoritesBox; - item_actor = this.favBoxIter.getFirstVisible(); - } else { - this._activeContainer = this.applicationsBox; - item_actor = this.appBoxIter.getFirstVisible(); - this._scrollToButton(); - } - break; - case "top": - this._activeContainer = this.categoriesBox; - item_actor = this.catBoxIter.getFirstVisible(); - this._scrollToButton(item_actor._delegate, this.categoriesScrollBox); - break; - case "bottom": - this._activeContainer = this.categoriesBox; - item_actor = this.catBoxIter.getLastVisible(); - this._scrollToButton(item_actor._delegate, this.categoriesScrollBox); - break; - } - break; case this.categoriesBox: switch (whichWay) { case "up": - this._previousTreeSelectedActor = this.categoriesBox.get_child_at_index(index); - this._previousTreeSelectedActor._delegate.isHovered = false; item_actor = this.catBoxIter.getPrevVisible(this._activeActor); - this._scrollToButton(item_actor._delegate, this.categoriesScrollBox); break; case "down": - this._previousTreeSelectedActor = this.categoriesBox.get_child_at_index(index); - this._previousTreeSelectedActor._delegate.isHovered = false; item_actor = this.catBoxIter.getNextVisible(this._activeActor); - this._scrollToButton(item_actor._delegate, this.categoriesScrollBox); break; case "right": - if ((this.categoriesBox.get_child_at_index(index))._delegate.categoryId === "recent" && + if (this._activeActor._delegate.categoryId === "recent" && this.noRecentDocuments) { if(this.favBoxShow) { - this._previousSelectedActor = this.categoriesBox.get_child_at_index(index); item_actor = this.favBoxIter.getFirstVisible(); - } else { - item_actor = this.categoriesBox.get_child_at_index(index); } - } - else { - item_actor = (this._previousVisibleIndex != null) ? - this.appBoxIter.getVisibleItem(this._previousVisibleIndex) : - this.appBoxIter.getFirstVisible(); + } else { + item_actor = (this._previousSelectedAppActor != null) ? + this._previousSelectedAppActor : this.appBoxIter.getFirstVisible(); } break; case "left": if(this.favBoxShow) { - this._previousSelectedActor = this.categoriesBox.get_child_at_index(index); item_actor = this.favBoxIter.getFirstVisible(); - this._scrollToButton(null, this.favoritesScrollBox); - } else { - if ((this.categoriesBox.get_child_at_index(index))._delegate.categoryId === "recent" && - this.noRecentDocuments) { - item_actor = this.categoriesBox.get_child_at_index(index); - } else { - item_actor = (this._previousVisibleIndex != null) ? - this.appBoxIter.getVisibleItem(this._previousVisibleIndex) : - this.appBoxIter.getFirstVisible(); - } + } else if (this._activeActor._delegate.categoryId != "recent" || + !this.noRecentDocuments) { + item_actor = (this._previousSelectedAppActor != null) ? + this._previousSelectedAppActor : + this.appBoxIter.getFirstVisible(); } break; case "top": - this._previousTreeSelectedActor = this.categoriesBox.get_child_at_index(index); - this._previousTreeSelectedActor._delegate.isHovered = false; item_actor = this.catBoxIter.getFirstVisible(); - this._scrollToButton(item_actor._delegate, this.categoriesScrollBox); break; case "bottom": - this._previousTreeSelectedActor = this.categoriesBox.get_child_at_index(index); - this._previousTreeSelectedActor._delegate.isHovered = false; item_actor = this.catBoxIter.getLastVisible(); - this._scrollToButton(item_actor._delegate, this.categoriesScrollBox); break; } break; case this.applicationsBox: switch (whichWay) { case "up": - this._previousSelectedActor = this.applicationsBox.get_child_at_index(index); - item_actor = this.appBoxIter.getPrevVisible(this._previousSelectedActor); - this._previousVisibleIndex = this.appBoxIter.getVisibleIndex(item_actor); - this._scrollToButton(item_actor._delegate); + item_actor = this.appBoxIter.getPrevVisible(this._activeActor); break; case "down": - this._previousSelectedActor = this.applicationsBox.get_child_at_index(index); - item_actor = this.appBoxIter.getNextVisible(this._previousSelectedActor); - this._previousVisibleIndex = this.appBoxIter.getVisibleIndex(item_actor); - this._scrollToButton(item_actor._delegate); + item_actor = this.appBoxIter.getNextVisible(this._activeActor); break; case "right": - this._previousSelectedActor = this.applicationsBox.get_child_at_index(index); - item_actor = (this._previousTreeSelectedActor != null) ? - this._previousTreeSelectedActor : - this.catBoxIter.getFirstVisible(); - this._previousTreeSelectedActor = item_actor; - index = item_actor.get_parent()._vis_iter.getAbsoluteIndexOfChild(item_actor); - if (this.favBoxShow) { - this._buttonEnterEvent(item_actor._delegate, true); - this._previousSelectedActor = this.categoriesBox.get_child_at_index(index); item_actor = this.favBoxIter.getFirstVisible(); + } else { + item_actor = (this._previousCategoryHoverActor != null) ? + this._previousCategoryHoverActor : + this.catBoxIter.getFirstVisible(); } break; case "left": - this._previousSelectedActor = this.applicationsBox.get_child_at_index(index); - item_actor = (this._previousTreeSelectedActor != null) ? - this._previousTreeSelectedActor : + item_actor = (this._previousCategoryHoverActor != null) ? + this._previousCategoryHoverActor : this.catBoxIter.getFirstVisible(); - this._previousTreeSelectedActor = item_actor; break; case "top": item_actor = this.appBoxIter.getFirstVisible(); - this._previousVisibleIndex = this.appBoxIter.getVisibleIndex(item_actor); - this._scrollToButton(item_actor._delegate); break; case "bottom": item_actor = this.appBoxIter.getLastVisible(); - this._previousVisibleIndex = this.appBoxIter.getVisibleIndex(item_actor); - this._scrollToButton(item_actor._delegate); break; } break; case this.favoritesBox: switch (whichWay) { case "up": - this._previousSelectedActor = this.favoritesBox.get_child_at_index(index); - if (this._previousSelectedActor === this.favBoxIter.getFirstVisible()) { + if (this._activeActor === this.favBoxIter.getFirstVisible()) { item_actor = this.sysBoxIter.getLastVisible(); } else { - item_actor = this.favBoxIter.getPrevVisible(this._previousSelectedActor); - this._scrollToButton(item_actor._delegate, this.favoritesScrollBox); + item_actor = this.favBoxIter.getPrevVisible(this._activeActor); } break; case "down": - this._previousSelectedActor = this.favoritesBox.get_child_at_index(index); - if (this._previousSelectedActor === this.favBoxIter.getLastVisible()) { + if (this._activeActor === this.favBoxIter.getLastVisible()) { item_actor = this.sysBoxIter.getFirstVisible(); } else { - item_actor = this.favBoxIter.getNextVisible(this._previousSelectedActor); - this._scrollToButton(item_actor._delegate, this.favoritesScrollBox); + item_actor = this.favBoxIter.getNextVisible(this._activeActor); } break; case "right": - item_actor = (this._previousTreeSelectedActor != null) ? - this._previousTreeSelectedActor : + item_actor = (this._previousCategoryHoverActor != null) ? + this._previousCategoryHoverActor : this.catBoxIter.getFirstVisible(); - this._previousTreeSelectedActor = item_actor; break; case "left": - item_actor = (this._previousTreeSelectedActor != null) ? - this._previousTreeSelectedActor : + /*item_actor = (this._previousCategoryHoverActor != null) ? + this._previousCategoryHoverActor : this.catBoxIter.getFirstVisible(); - this._previousTreeSelectedActor = item_actor; + this._previousCategoryHoverActor = item_actor; index = item_actor.get_parent()._vis_iter.getAbsoluteIndexOfChild(item_actor); - this._buttonEnterEvent(item_actor._delegate, true); - item_actor = (this._previousVisibleIndex != null) ? - this.appBoxIter.getVisibleItem(this._previousVisibleIndex) : + this._buttonEnterEvent(item_actor._delegate);*/ + item_actor = (this._previousSelectedAppActor != null) ? + this._previousSelectedAppActor : this.appBoxIter.getFirstVisible(); break; case "top": @@ -2044,39 +1955,34 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { case this.systemButtonsBox: switch (whichWay) { case "up": - this._previousSelectedActor = this.systemButtonsBox.get_child_at_index(index); - if (this._previousSelectedActor === this.sysBoxIter.getFirstVisible()) { + if (this._activeActor === this.sysBoxIter.getFirstVisible()) { item_actor = this.favBoxIter.getLastVisible(); - this._scrollToButton(item_actor._delegate, this.favoritesScrollBox); } else { - item_actor = this.sysBoxIter.getPrevVisible(this._previousSelectedActor); + item_actor = this.sysBoxIter.getPrevVisible(this._activeActor); } break; case "down": - this._previousSelectedActor = this.systemButtonsBox.get_child_at_index(index); - if (this._previousSelectedActor === this.sysBoxIter.getLastVisible()) { + if (this._activeActor === this.sysBoxIter.getLastVisible()) { item_actor = this.favBoxIter.getFirstVisible(); - this._scrollToButton(null, this.favoritesScrollBox); } else { - item_actor = this.sysBoxIter.getNextVisible(this._previousSelectedActor); + item_actor = this.sysBoxIter.getNextVisible(this._activeActor); } break; case "right": - item_actor = (this._previousTreeSelectedActor != null) ? - this._previousTreeSelectedActor : + item_actor = (this._previousCategoryHoverActor != null) ? + this._previousCategoryHoverActor : this.catBoxIter.getFirstVisible(); - this._previousTreeSelectedActor = item_actor; break; case "left": - item_actor = (this._previousTreeSelectedActor != null) ? - this._previousTreeSelectedActor : + /*item_actor = (this._previousCategoryHoverActor != null) ? + this._previousCategoryHoverActor : this.catBoxIter.getFirstVisible(); - this._previousTreeSelectedActor = item_actor; + this._previousCategoryHoverActor = item_actor; index = item_actor.get_parent()._vis_iter.getAbsoluteIndexOfChild(item_actor); - this._buttonEnterEvent(item_actor._delegate, true); - item_actor = (this._previousVisibleIndex != null) ? - this.appBoxIter.getVisibleItem(this._previousVisibleIndex) : + this._buttonEnterEvent(item_actor._delegate);*/ + item_actor = (this._previousSelectedAppActor != null) ? + this._previousSelectedAppActor : this.appBoxIter.getFirstVisible(); break; case "top": @@ -2092,53 +1998,49 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { } if (!item_actor) return false; - index = item_actor.get_parent()._vis_iter.getAbsoluteIndexOfChild(item_actor); } else { - if ((this._activeContainer && this._activeContainer !== this.categoriesBox) && - (symbol === Clutter.KEY_Return || symbol === Clutter.KEY_KP_Enter)) { + if (this._activeContainer && (symbol === Clutter.KEY_Return || symbol === Clutter.KEY_KP_Enter)) { if (!ctrlKey) { - item_actor = this._activeContainer.get_child_at_index(this._selectedItemIndex); - item_actor._delegate.activate(); + this._activeActor._delegate.activate(); } else if (ctrlKey && this._activeContainer === this.applicationsBox) { - item_actor = this.applicationsBox.get_child_at_index(this._selectedItemIndex); - this.toggleContextMenu(item_actor._delegate); + this.toggleContextMenu(this._activeActor._delegate); } return true; } else if (this._activeContainer === this.applicationsBox && symbol === Clutter.KEY_Menu) { - item_actor = this.applicationsBox.get_child_at_index(this._selectedItemIndex); - this.toggleContextMenu(item_actor._delegate); + this.toggleContextMenu(this._activeActor._delegate); return true; } else if (!this.searchActive && this._activeContainer === this.favoritesBox && symbol === Clutter.KEY_Delete) { - item_actor = this.favoritesBox.get_child_at_index(this._selectedItemIndex); + item_actor = this._activeActor; + const selectedItemIndex = this._activeContainer._vis_iter.getAbsoluteIndexOfChild(this._activeActor); if (item_actor._delegate instanceof FavoritesButton) { let favorites = AppFavorites.getAppFavorites().getFavorites(); let numFavorites = favorites.length; AppFavorites.getAppFavorites().removeFavorite(item_actor._delegate.app.get_id()); - if (this._selectedItemIndex == (numFavorites-1)) - item_actor = this.favoritesBox.get_child_at_index(this._selectedItemIndex-1); + if (selectedItemIndex == (numFavorites-1)) + item_actor = this.favoritesBox.get_child_at_index(selectedItemIndex-1); else - item_actor = this.favoritesBox.get_child_at_index(this._selectedItemIndex); + item_actor = this.favoritesBox.get_child_at_index(selectedItemIndex); } } else if (this._activeContainer === this.favoritesBox && (symbol === Clutter.KEY_Down || symbol === Clutter.KEY_Up) && ctrlKey && - (this.favoritesBox.get_child_at_index(index))._delegate instanceof FavoritesButton) { - item_actor = this.favoritesBox.get_child_at_index(this._selectedItemIndex); + this._activeActor._delegate instanceof FavoritesButton) { + const selectedItemIndex = this._activeContainer._vis_iter.getAbsoluteIndexOfChild(this._activeActor); + item_actor = this._activeActor; let id = item_actor._delegate.app.get_id(); let appFavorites = AppFavorites.getAppFavorites(); let favorites = appFavorites.getFavorites(); let numFavorites = favorites.length; let favPos = 0; - if (this._selectedItemIndex == (numFavorites-1) && symbol === Clutter.KEY_Down) + if (selectedItemIndex == (numFavorites-1) && symbol === Clutter.KEY_Down) favPos = 0; - else if (this._selectedItemIndex == 0 && symbol === Clutter.KEY_Up) + else if (selectedItemIndex == 0 && symbol === Clutter.KEY_Up) favPos = numFavorites-1; else if (symbol === Clutter.KEY_Down) - favPos = this._selectedItemIndex + 1; + favPos = selectedItemIndex + 1; else - favPos = this._selectedItemIndex - 1; + favPos = selectedItemIndex - 1; appFavorites.moveFavoriteToPos(id, favPos); item_actor = this.favoritesBox.get_child_at_index(favPos); - this._scrollToButton(item_actor._delegate, this.favoritesScrollBox); } else if (this.searchFilesystem && (this._fileFolderAccessActive || symbol === Clutter.KEY_slash)) { if (symbol === Clutter.KEY_Return || symbol === Clutter.KEY_KP_Enter) { if (this._run(this.searchEntry.get_text())) { @@ -2193,124 +2095,89 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { this.selectedAppTitle.set_text(""); this.selectedAppDescription.set_text(""); - this._selectedItemIndex = index; if (!item_actor || item_actor === this.searchEntry) { return false; } - this._buttonEnterEvent(item_actor._delegate, true); - return true; - } - - _buttonEnterEvent(button, synthetic=false) { - let parent = button.actor.get_parent(); - if (this._activeContainer === this.categoriesBox && parent !== this._activeContainer) { - this._previousTreeSelectedActor = this._activeActor; - this._previousSelectedActor = null; - } - if (this._previousTreeSelectedActor && this._activeContainer !== this.categoriesBox && - parent !== this._activeContainer && button !== this._previousTreeSelectedActor && !this.searchActive) { - this._previousTreeSelectedActor.style_class = "menu-category-button"; - } - if (parent != this._activeContainer && parent._vis_iter) { - parent._vis_iter.reloadVisible(); - } - let _maybePreviousActor = this._activeActor; - if (_maybePreviousActor && this._activeContainer !== this.categoriesBox) { - this._previousSelectedActor = _maybePreviousActor; - this._clearPrevSelection(); - } - if (parent === this.categoriesBox && !this.searchActive) { - this._previousSelectedActor = _maybePreviousActor; - this._clearPrevCatSelection(null, synthetic); - } - this._activeContainer = parent; - this._activeActor = button.actor; - if (this._activeContainer._vis_iter) { - this._selectedItemIndex = this._activeContainer._vis_iter.getAbsoluteIndexOfChild(this._activeActor); + if (item_actor._delegate instanceof CategoryButton) { + this._scrollToButton(item_actor._delegate, this.categoriesScrollBox); + } else if (item_actor._delegate instanceof FavoritesButton) { + this._scrollToButton(item_actor._delegate, this.favoritesScrollBox); + } else if (item_actor.get_parent() === this.applicationsBox) { + this._scrollToButton(item_actor._delegate, this.applicationsScrollBox); } + + this._buttonEnterEvent(item_actor._delegate); + return true; + } - let isFav = false; + _buttonEnterEvent(button) { + this.categoriesBox.get_children().forEach(child => child.remove_style_pseudo_class("hover")); + this.applicationsBox.get_children().forEach(child => child.set_style_class_name("menu-application-button")); + this.favoritesBox.get_children().forEach(child => child.remove_style_pseudo_class("hover")); + this.systemButtonsBox.get_children().forEach(child => child.remove_style_pseudo_class("hover")); + if (button instanceof CategoryButton) { if (this.searchActive) return; - button.isHovered = true; - if (this.categoryHover || (button.categoryId !== this.lastSelectedCategory)) { - this._clearPrevCatSelection(button.actor, synthetic); - } - if (this.categoryHover || synthetic) { - this._select_category(button.categoryId); + + if (button.categoryId !== this.lastSelectedCategory) { + if (this.categoryHover) { + this.categoriesBox.get_children().forEach(child => + child.set_style_class_name("menu-category-button")); + button.activate(); + } else { + button.actor.add_style_pseudo_class("hover"); + } } + this._previousCategoryHoverActor = button.actor; } else { - this._previousVisibleIndex = parent._vis_iter.getVisibleIndex(button.actor); - - isFav = button instanceof FavoritesButton || button instanceof SystemButton; - if (!isFav) - this._clearPrevSelection(button.actor); + const isFav = button instanceof FavoritesButton || button instanceof SystemButton; + if (isFav) { + button.actor.add_style_pseudo_class("hover"); + } else { + button.actor.set_style_class_name(`${button.styleClass}-selected`); + this._previousSelectedAppActor = button.actor; + } this.selectedAppTitle.set_text(button.name); this.selectedAppDescription.set_text(button.description); } - if (isFav) - button.actor.add_style_pseudo_class("hover"); - else - button.actor.set_style_class_name(`${button.styleClass}-selected`); + + let parent = button.actor.get_parent(); + this._activeContainer = parent; + this._activeActor = button.actor; } _buttonLeaveEvent (button) { if (button instanceof CategoryButton) { - if (this._previousTreeSelectedActor === null) { - this._previousTreeSelectedActor = button.actor; - } else { - let prevIdx = this.catBoxIter.getVisibleIndex(this._previousTreeSelectedActor); - let nextIdx = this.catBoxIter.getVisibleIndex(button.actor); - - if (Math.abs(prevIdx - nextIdx) <= 1) { - this._previousTreeSelectedActor = button.actor; + if (button.categoryId !== this.lastSelectedCategory) { + button.actor.set_style_class_name("menu-category-button"); + if (button.actor.has_style_pseudo_class("hover")) { + button.actor.remove_style_pseudo_class("hover"); } } - button.isHovered = false; } else { - this._previousSelectedActor = button.actor; this.selectedAppTitle.set_text(""); this.selectedAppDescription.set_text(""); - // category unselects are handled when the category actually changes if (button instanceof FavoritesButton || button instanceof SystemButton) button.actor.remove_style_pseudo_class("hover"); else button.actor.set_style_class_name(button.styleClass); } - } - _clearPrevSelection(actor) { - if (this._previousSelectedActor - && !this._previousSelectedActor.is_finalized() - && this._previousSelectedActor != actor) { - if (this._previousSelectedActor._delegate instanceof FavoritesButton || - this._previousSelectedActor._delegate instanceof SystemButton) - this._previousSelectedActor.remove_style_pseudo_class("hover"); - else if (!(this._previousSelectedActor._delegate instanceof CategoryButton)) - this._previousSelectedActor.style_class = "menu-application-button"; - } + // This method is only called on mouse leave so return key focus to the + // currently active category button. + this._setKeyFocusToCurrentCategoryButton(); } - _clearPrevCatSelection(actor, synthetic=false) { - if (this._previousTreeSelectedActor && this._previousTreeSelectedActor != actor && - (this.categoryHover ? true : this._previousTreeSelectedActor._delegate.categoryId !== this.lastSelectedCategory)) { - this._previousTreeSelectedActor.style_class = "menu-category-button"; - if (this._previousTreeSelectedActor._delegate) { - this._buttonLeaveEvent(this._previousTreeSelectedActor._delegate); - } - - if (actor !== undefined) { - this._previousVisibleIndex = null; - this._previousTreeSelectedActor = actor; - } - } else { - if (this.categoryHover || synthetic) { - this.categoriesBox.get_children().forEach(child => child.style_class = "menu-category-button"); - } + _setKeyFocusToCurrentCategoryButton() { + const currentSelectedCategoryActor = this.categoriesBox.get_children().find(child => + child._delegate.categoryId === this.lastSelectedCategory); + if (currentSelectedCategoryActor) { + this._activeContainer = this.categoriesBox; + this._activeActor = currentSelectedCategoryActor; } } @@ -2784,10 +2651,7 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { this.systemButtonsBox.add(button.actor, { y_align: St.Align.END, y_fill: false }); } - _scrollToButton(button, scrollBox = null) { - if (!scrollBox) - scrollBox = this.applicationsScrollBox; - + _scrollToButton(button, scrollBox = this.applicationsScrollBox) { let adj = scrollBox.get_vscroll_bar().get_adjustment(); if (button) { let box = scrollBox.get_allocation_box(); @@ -2964,6 +2828,7 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { actors = this.categoriesBox.get_children(); for (let i = 0; i < actors.length; i++){ let actor = actors[i]; + actor.remove_style_pseudo_class("hover") actor.style_class = "menu-category-button"; actor.show(); } @@ -3001,12 +2866,14 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { } } - _select_category (name) { - if (name === this.lastSelectedCategory) + _select_category (name = null) { + if (name === this.lastSelectedCategory){ return; + } this.lastSelectedCategory = name; this._displayButtons(name || 'app'); this.closeContextMenu(false); + this._scrollToButton(null); } closeContextMenu(animate) { @@ -3218,9 +3085,7 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { this._searchTimeoutId = 0; this._activeContainer = null; this._activeActor = null; - this._selectedItemIndex = null; - this._previousTreeSelectedActor = null; - this._previousSelectedActor = null; + this._previousCategoryHoverActor = null; var acResultButtons = []; // search box autocompletion results var buttons = [] @@ -3245,11 +3110,10 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { if (buttons.length || acResultButtons.length) { this.appBoxIter.reloadVisible(); - let item_actor = this.appBoxIter.getFirstVisible(); - this._selectedItemIndex = this.appBoxIter.getAbsoluteIndexOfChild(item_actor); + this._activeActor = this.appBoxIter.getFirstVisible(); this._activeContainer = this.applicationsBox; - this._scrollToButton(item_actor._delegate); - this._buttonEnterEvent(item_actor._delegate, true); + this._scrollToButton(this._activeActor._delegate); + this._buttonEnterEvent(this._activeActor._delegate); } else { this.selectedAppTitle.set_text(""); this.selectedAppDescription.set_text(""); @@ -3263,13 +3127,12 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { let button = new SearchProviderResultButton(this, provider, results[i]); this._searchProviderButtons.push(button); this.applicationsBox.add_actor(button.actor); - if (this._selectedItemIndex === null) { + if (this._activeActor === null) { this.appBoxIter.reloadVisible(); - let item_actor = this.appBoxIter.getFirstVisible(); - this._selectedItemIndex = this.appBoxIter.getAbsoluteIndexOfChild(item_actor); + this._activeActor = this.appBoxIter.getFirstVisible(); this._activeContainer = this.applicationsBox; - if (item_actor && item_actor != this.searchEntry) { - this._buttonEnterEvent(item_actor._delegate, true); + if (this._activeActor && this._activeActor != this.searchEntry) { + this._buttonEnterEvent(this._activeActor._delegate); } } } From e062391adc697ec1e39088bc3cca13306378d762 Mon Sep 17 00:00:00 2001 From: sphh Date: Tue, 21 Mar 2023 18:01:48 +0000 Subject: [PATCH 19/30] Enables extensions marked to overide version check to be removed. (#11510) * Enables extensions marked to overide version check to be removed. (Closes #11506) Enables extensions marked to overide version check has a '!' in front of their name. Whereas applets and desklets can be removed, extensions cannot. * Removes exclamation mark only from beginning of UID. To reduce the risk of sideeffects, only remove the exclamation mark at the left-hand side of the applet/extension/desklet's UID. --- files/usr/share/cinnamon/cinnamon-settings/bin/Spices.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/files/usr/share/cinnamon/cinnamon-settings/bin/Spices.py b/files/usr/share/cinnamon/cinnamon-settings/bin/Spices.py index 3cfab25036..d576496564 100644 --- a/files/usr/share/cinnamon/cinnamon-settings/bin/Spices.py +++ b/files/usr/share/cinnamon/cinnamon-settings/bin/Spices.py @@ -784,11 +784,11 @@ def disable_extension(self, uuid): new_list = [] for enabled_extension in enabled_extensions: if self.collection_type == 'applet': - enabled_uuid = enabled_extension.split(':')[3].strip('!') + enabled_uuid = enabled_extension.split(':')[3].lstrip('!') elif self.collection_type == 'desklet': - enabled_uuid = enabled_extension.split(':')[0].strip('!') + enabled_uuid = enabled_extension.split(':')[0].lstrip('!') else: - enabled_uuid = enabled_extension + enabled_uuid = enabled_extension.lstrip('!') if enabled_uuid != uuid: new_list.append(enabled_extension) From 5f2d341cffe982056cafafbcaad4445610eb2bed Mon Sep 17 00:00:00 2001 From: Rick Calixte <10281587+rcalixte@users.noreply.github.com> Date: Thu, 30 Mar 2023 12:43:51 -0400 Subject: [PATCH 20/30] Remove simple-system-monitor@ariel as a known conflict (#11591) --- js/ui/extension.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/js/ui/extension.js b/js/ui/extension.js index f40c610dd2..5428a1c77a 100644 --- a/js/ui/extension.js +++ b/js/ui/extension.js @@ -32,8 +32,7 @@ var knownCinnamon4Conflicts = [ 'vnstat@linuxmint.com', 'netusagemonitor@pdcurtis', // Desklets - 'netusage@30yavash.com', - 'simple-system-monitor@ariel' + 'netusage@30yavash.com' ]; // macro for creating extension types From 8dbb5bdc919cbe625bf44ebfee2abab490ef1c69 Mon Sep 17 00:00:00 2001 From: Tom Pfaffe Date: Thu, 30 Mar 2023 14:36:44 -0400 Subject: [PATCH 21/30] Fix super+shift+number not disabling in grouped-window-list applet (#11464) - Setting the value of the applet settings parameter 'super-num-hotkeys' to false should now avoid registering the super+shift+number app launcher key binds whereas it previously it only avoided registering super+number key binds - These changes should fix the unexpected behavior reported in #11393. --- .../applets/grouped-window-list@cinnamon.org/applet.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/applet.js index d2bf8f65c4..7225c27806 100644 --- a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/applet.js @@ -459,11 +459,11 @@ class GroupedWindowListApplet extends Applet.Applet { bindAppKeys() { this.unbindAppKeys(); - for (let i = 1; i < 10; i++) { - if (this.state.settings.SuperNumHotkeys) { + if (this.state.settings.SuperNumHotkeys) { + for (let i = 1; i < 10; i++) { this.bindAppKey(i); + this.bindNewAppKey(i); } - this.bindNewAppKey(i); } Main.keybindingManager.addHotKey('launch-show-apps-order', this.state.settings.showAppsOrderHotkey, () => this.showAppsOrder() From 20864d217bead8794605ae46514fa7952f2a2045 Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Mon, 3 Apr 2023 12:10:43 -0400 Subject: [PATCH 22/30] cs_themes.py: Keep the current variant between modes if possible. When switching between simple modes (dark/mixed/light), attempt to keep the current color variant if it exists for the new mode, otherwise switch to the default variant. --- .../cinnamon-settings/modules/cs_themes.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py index 924dabd0b2..2a75dcee7a 100755 --- a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py +++ b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py @@ -43,6 +43,13 @@ def __init__(self, name): self.default_variant = None self.variants = [] + def get_variant_by_name(self, name): + for variant in self.variants: + if name == variant.name: + return variant + + return None + class Variant: def __init__(self, json_obj): self.name = json_obj["name"] @@ -536,7 +543,13 @@ def on_style_combo_changed(self, combobox): def activate_mode(self, style, mode): print("Activating mode:", mode.name) - self.activate_variant(mode.default_variant) + + if self.active_variant is not None: + new_same_variant = mode.get_variant_by_name(self.active_variant.name) + if new_same_variant is not None: + self.activate_variant(new_same_variant) + else: + self.activate_variant(mode.default_variant) def activate_variant(self, variant): print("Activating variant:", variant.name) From e3102260e0234ba4edd4300aa49f9d8f5a5aa6b3 Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Mon, 3 Apr 2023 14:41:07 -0400 Subject: [PATCH 23/30] panel-launchers: Don't allow the size of custom icons to be reset. When the theme changed, _updateIconSize would compare the current icon size with smallest of either its container's height or its width. Only one direction would be set (depending on panel orientation), so the smallest size was always 0, resetting the StIcon's icon_size property to 0. This would force it to look at the theme for the icon size (which would be too large for the panel). --- .../panel-launchers@cinnamon.org/applet.js | 20 ++++++++++++++----- src/cinnamon-app.c | 4 ++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/files/usr/share/cinnamon/applets/panel-launchers@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/panel-launchers@cinnamon.org/applet.js index 496937236f..7507198284 100644 --- a/files/usr/share/cinnamon/applets/panel-launchers@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/panel-launchers@cinnamon.org/applet.js @@ -282,12 +282,22 @@ class PanelAppLauncher extends DND.LauncherDraggable { _updateIconSize() { let node = this._iconBox.get_theme_node(); - let maxHeight = this._iconBox.height - node.get_vertical_padding(); - let maxWidth = this._iconBox.width - node.get_horizontal_padding(); - let smallestDim = Math.min(maxHeight, maxWidth) / global.ui_scale; + let enforcedSize = 0; - if (smallestDim < this.icon.get_icon_size()) { - this.icon.set_icon_size(smallestDim); + if (this._iconBox.height > 0) { + enforcedSize = this._iconBox.height - node.get_vertical_padding(); + } + else + if (this._iconBox.width > 0) { + enforcedSize = this._iconBox.width - node.get_horizontal_padding(); + } + else + { + enforcedSize = -1; + } + + if (enforcedSize < this.icon.get_icon_size()) { + this.icon.set_icon_size(enforcedSize); } } diff --git a/src/cinnamon-app.c b/src/cinnamon-app.c index e3c2d704c7..b0328f2db8 100644 --- a/src/cinnamon-app.c +++ b/src/cinnamon-app.c @@ -188,7 +188,7 @@ get_actor_for_icon_name (CinnamonApp *app, if (icon != NULL) { - actor = g_object_new (ST_TYPE_ICON, "gicon", icon, "icon-size", size, NULL); + actor = g_object_new (ST_TYPE_ICON, "gicon", icon, "icon-type", ST_ICON_FULLCOLOR, "icon-size", size, NULL); g_object_unref (icon); } @@ -199,7 +199,7 @@ static ClutterActor * get_failsafe_icon (int size) { GIcon *icon = g_themed_icon_new ("application-x-executable"); - ClutterActor *actor = g_object_new (ST_TYPE_ICON, "gicon", icon, "icon-size", size, NULL); + ClutterActor *actor = g_object_new (ST_TYPE_ICON, "gicon", icon, "icon-type", ST_ICON_FULLCOLOR, "icon-size", size, NULL); g_object_unref (icon); return actor; } From 6e676247615b3cbf5788a368a00259c5b88c9552 Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Mon, 3 Apr 2023 23:44:09 -0400 Subject: [PATCH 24/30] cs_themes.py: Make sure activate_mode always activates a mode. ref: 20864d217bead87 --- .../share/cinnamon/cinnamon-settings/modules/cs_themes.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py index 2a75dcee7a..7acfb82842 100755 --- a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py +++ b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_themes.py @@ -548,8 +548,9 @@ def activate_mode(self, style, mode): new_same_variant = mode.get_variant_by_name(self.active_variant.name) if new_same_variant is not None: self.activate_variant(new_same_variant) - else: - self.activate_variant(mode.default_variant) + return + + self.activate_variant(mode.default_variant) def activate_variant(self, variant): print("Activating variant:", variant.name) From 3678d8c1079732f3512ab4dbfeaed6ee149b9c2c Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Mon, 3 Apr 2023 23:54:04 -0400 Subject: [PATCH 25/30] cinnamon-desktop-editor: Use a path when setting a panel-launcher icon. If an icon name is used in the panel launcher applet, and the user switches to an icon theme that doesn't have that icon name, the launcher will disappear. Now, the selected icon's path is checked - if it's coming from the hicolor theme, it's left as-is (since hicolor is inherited by the active theme). Otherwise, the icon's path is stored instead of its name, so it will remain valid regardless of future themes. Add an optional 'icon-size' argument to cinnamon-desktop-editor, so the path to an appropriately-sized icon is used for the launcher. --- .../panel-launchers@cinnamon.org/applet.js | 6 ++- .../cinnamon-desktop-editor.py | 52 +++++++++++++++++-- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/files/usr/share/cinnamon/applets/panel-launchers@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/panel-launchers@cinnamon.org/applet.js index 7507198284..70c86b1940 100644 --- a/files/usr/share/cinnamon/applets/panel-launchers@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/panel-launchers@cinnamon.org/applet.js @@ -682,9 +682,11 @@ class CinnamonPanelLaunchersApplet extends Applet.Applet { showAddLauncherDialog(timestamp, launcher){ if (launcher) { - Util.spawnCommandLine("cinnamon-desktop-editor -mcinnamon-launcher -f" + launcher.getId() + " " + this.settings.file.get_path()); + Util.spawnCommandLine("cinnamon-desktop-editor -mcinnamon-launcher --icon-size %d -f %s %s" + .format(this.icon_size, launcher.getId(), this.settings.file.get_path())); } else { - Util.spawnCommandLine("cinnamon-desktop-editor -mcinnamon-launcher " + this.settings.file.get_path()); + Util.spawnCommandLine("cinnamon-desktop-editor -mcinnamon-launcher --icon-size %d %s" + .format(this.icon_size, this.settings.file.get_path())) } } diff --git a/files/usr/share/cinnamon/cinnamon-desktop-editor/cinnamon-desktop-editor.py b/files/usr/share/cinnamon/cinnamon-desktop-editor/cinnamon-desktop-editor.py index 33579e30fd..a8f8ef507d 100755 --- a/files/usr/share/cinnamon/cinnamon-desktop-editor/cinnamon-desktop-editor.py +++ b/files/usr/share/cinnamon/cinnamon-desktop-editor/cinnamon-desktop-editor.py @@ -8,6 +8,7 @@ import shutil import subprocess from setproctitle import setproctitle +from pathlib import Path import gi gi.require_version("Gtk", "3.0") @@ -56,7 +57,7 @@ def ask(msg): class ItemEditor(object): ui_file = None - def __init__(self, item_path=None, callback=None, destdir=None): + def __init__(self, item_path=None, callback=None, destdir=None, icon_size=24): self.builder = Gtk.Builder() self.builder.set_translation_domain('cinnamon') # let it translate! self.builder.add_from_file(self.ui_file) @@ -66,9 +67,13 @@ def __init__(self, item_path=None, callback=None, destdir=None): self.dialog.connect('response', self.on_response) + self.starting_icon = None self.icon_chooser = self.builder.get_object('icon-chooser') self.icon_chooser.get_dialog().set_property("allow-paths", True) + self.icon_size = icon_size + self.icon_chooser.set_icon_size(self.get_gtk_size_for_pixels(icon_size)) + self.build_ui() self.item_path = item_path @@ -76,6 +81,18 @@ def __init__(self, item_path=None, callback=None, destdir=None): self.check_custom_path() self.resync_validity() + def get_gtk_size_for_pixels(self, icon_size): + i = 0 + while True: + try: + valid, width, height = Gtk.IconSize.lookup(Gtk.IconSize(i)) + if height > icon_size: + return Gtk.IconSize(i) + except ValueError: + return Gtk.IconSize.DIALOG + + i += 1 + def build_ui(self): raise NotImplementedError() @@ -139,6 +156,7 @@ def set_icon(self, name): else: print(val) self.icon_chooser.set_icon(val) + self.starting_icon = val print('icon:', self.icon_chooser.get_icon()) def load(self): @@ -178,8 +196,6 @@ def on_response(self, dialog, response): self.callback(True, self.item_path) else: self.callback(False, self.item_path) - self.dialog.destroy() - class LauncherEditor(ItemEditor): ui_file = '/usr/share/cinnamon/cinnamon-desktop-editor/launcher-editor.ui' @@ -295,13 +311,37 @@ def load(self): self.set_icon("Icon") def get_keyfile_edits(self): + icon_theme = Gtk.IconTheme.get_default() + icon = self.icon_chooser.get_icon() + + if icon != self.starting_icon: + info = icon_theme.lookup_icon(icon, self.icon_size, 0) + if info: + filename = info.get_filename() + if not self.in_hicolor(filename): + icon = filename + return dict(Name=self.builder.get_object('name-entry').get_text(), Exec=self.builder.get_object('exec-entry').get_text(), Comment=self.builder.get_object('comment-entry').get_text(), Terminal=self.builder.get_object('terminal-check').get_active(), - Icon=self.icon_chooser.get_icon(), + Icon=icon, Type="Application") + def in_hicolor(self, path): + datadirs = GLib.get_system_data_dirs() + + for datadir in datadirs: + hicolor_folder = Path(os.path.join(datadir, "icons", "hicolor")) + icon_path = Path(path) + try: + if icon_path.relative_to(hicolor_folder) is not None: + return True + except ValueError: + pass + + return False + def pick_exec(self, button): chooser = Gtk.FileChooserDialog(title=_("Choose a command"), parent=self.dialog, @@ -320,6 +360,7 @@ def __init__(self): parser.add_option("-d", "--directory", dest="destination_directory", help="Destination directory of the new launcher", metavar="DEST_DIR") parser.add_option("-f", "--file", dest="desktop_file", help="Name of desktop file (i.e. gnome-terminal.desktop)", metavar="DESKTOP_NAME") parser.add_option("-m", "--mode", dest="mode", default=None, help="Mode to run in: launcher, directory, panel-launcher or nemo-launcher") + parser.add_option("-i", "--icon-size", dest="icon_size", type=int, default=24, help="Size to set the icon picker for (panel-launcher only)") (options, args) = parser.parse_args() if not options.mode: @@ -343,6 +384,7 @@ def __init__(self): if options.mode == "cinnamon-launcher": self.json_path = args[0] + self.icon_size = options.icon_size if self.desktop_file is not None: self.get_desktop_path() @@ -354,7 +396,7 @@ def __init__(self): editor = LauncherEditor(self.orig_file, self.launcher_cb) editor.dialog.show_all() elif self.mode == "cinnamon-launcher": - editor = CinnamonLauncherEditor(self.orig_file, self.panel_launcher_cb) + editor = CinnamonLauncherEditor(self.orig_file, self.panel_launcher_cb, icon_size=self.icon_size) editor.dialog.show_all() elif self.mode == "nemo-launcher": editor = LauncherEditor(self.orig_file, self.nemo_launcher_cb, self.dest_dir) From 7e211e2e251b2df0d80b386cc6de2ebc3db21e5f Mon Sep 17 00:00:00 2001 From: Attila Greguss Date: Tue, 4 Apr 2023 22:48:38 +0100 Subject: [PATCH 26/30] Provide `.gir` files in cinnamon package (#11335) * Provide .gir files in cinnamon package * Add gir folder to debian package --- debian/cinnamon-common.install | 1 + meson.build | 1 + src/meson.build | 2 +- src/st/meson.build | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/debian/cinnamon-common.install b/debian/cinnamon-common.install index 1e65f241bf..8f9721440b 100644 --- a/debian/cinnamon-common.install +++ b/debian/cinnamon-common.install @@ -2,6 +2,7 @@ etc/xdg/menus/cinnamon* usr/share/cinnamon usr/share/cinnamon-session usr/share/desktop-directories +usr/share/gir-1.0 usr/share/glib-2.0 usr/share/icons usr/share/polkit-1 diff --git a/meson.build b/meson.build index 38f0bb8973..d9f0da8f04 100644 --- a/meson.build +++ b/meson.build @@ -16,6 +16,7 @@ desktopdir = join_paths(datadir, 'applications') xsessiondir = join_paths(datadir, 'xsessions') schemadir = join_paths(datadir, 'glib-2.0', 'schemas') pkglibdir = join_paths(libdir, meson.project_name().to_lower()) +girdir = join_paths(datadir, 'gir-1.0') servicedir = join_paths(datadir, 'dbus-1', 'services') pkgdatadir = join_paths(datadir, meson.project_name().to_lower()) po_dir = join_paths(meson.source_root(), 'po') diff --git a/src/meson.build b/src/meson.build index 288f651cef..c2e9ab5308 100644 --- a/src/meson.build +++ b/src/meson.build @@ -203,7 +203,7 @@ cinnamon_gir = gnome.generate_gir( includes: cinnamon_gir_includes, install: true, install_dir_typelib: pkglibdir, - install_dir_gir: false, + install_dir_gir: girdir, extra_args: [ '-DST_COMPILATION', '--quiet', diff --git a/src/st/meson.build b/src/st/meson.build index 70563f510c..5a337b80db 100644 --- a/src/st/meson.build +++ b/src/st/meson.build @@ -227,7 +227,7 @@ st_gir = gnome.generate_gir( includes: st_gir_includes, install: true, install_dir_typelib: pkglibdir, - install_dir_gir: false, + install_dir_gir: girdir, extra_args: [ '-DST_COMPILATION', '--quiet', From 835b7c5c2ec7fb8090183c00bfe8a26ee9856d2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anax=C3=ADmeno=20Brito?= Date: Thu, 6 Apr 2023 14:20:50 -0100 Subject: [PATCH 27/30] fix: update workspace switcher layout on monitors update signal (#11523) When connecting a new monitor to the computer, the layout of the workspace-switcher applet would keep the same, now it will update whenever new monitors are added or removed --- .../cinnamon/applets/workspace-switcher@cinnamon.org/applet.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/files/usr/share/cinnamon/applets/workspace-switcher@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/workspace-switcher@cinnamon.org/applet.js index 8e3bda833e..ff99df24b3 100644 --- a/files/usr/share/cinnamon/applets/workspace-switcher@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/workspace-switcher@cinnamon.org/applet.js @@ -282,6 +282,8 @@ class CinnamonWorkspaceSwitcher extends Applet.Applet { this.actor.connect('scroll-event', this.hook.bind(this)); + this.signals.connect(Main.layoutManager, 'monitors-changed', this.onWorkspacesUpdated, this); + this.queueCreateButtons(); global.workspace_manager.connect('notify::n-workspaces', () => { this.onWorkspacesUpdated() }); global.workspace_manager.connect('workspaces-reordered', () => { this.onWorkspacesUpdated() }); From d823d4821409981b731daaa57b6727537081d22d Mon Sep 17 00:00:00 2001 From: virumoru <93472024+virumoru@users.noreply.github.com> Date: Thu, 6 Apr 2023 19:49:48 +0300 Subject: [PATCH 28/30] Update ChooserButtonWidgets.py (#11595) Fix scope error that prevents user from accessing Themes page --- .../cinnamon-settings/bin/ChooserButtonWidgets.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/files/usr/share/cinnamon/cinnamon-settings/bin/ChooserButtonWidgets.py b/files/usr/share/cinnamon/cinnamon-settings/bin/ChooserButtonWidgets.py index 783e850946..baa8b3752f 100644 --- a/files/usr/share/cinnamon/cinnamon-settings/bin/ChooserButtonWidgets.py +++ b/files/usr/share/cinnamon/cinnamon-settings/bin/ChooserButtonWidgets.py @@ -118,13 +118,11 @@ def create_scaled_surface(self, path): try: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(path, w, h) + if pixbuf: + return Gdk.cairo_surface_create_from_pixbuf(pixbuf, self.scale) except GLib.Error as e: print("Could not load thumbnail file '%s': %s" % (path, e.message)) - - if pixbuf: - return Gdk.cairo_surface_create_from_pixbuf(pixbuf, self.scale) - else: - return None + return None def set_picture_from_file (self, path): surface = self.create_scaled_surface(path) From 8ddf1a6a23d1725d29a946600f438bf9cb9b9ef0 Mon Sep 17 00:00:00 2001 From: claudiux <33965039+claudiux@users.noreply.github.com> Date: Mon, 17 Apr 2023 15:21:29 +0200 Subject: [PATCH 29/30] Update placesManager.js to fix #11623 (#11624) --- js/ui/placesManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ui/placesManager.js b/js/ui/placesManager.js index d3b28b82ef..426627a954 100644 --- a/js/ui/placesManager.js +++ b/js/ui/placesManager.js @@ -166,7 +166,7 @@ PlaceDeviceInfo.prototype = { notification.setUrgency(persistent ? MessageTray.Urgency.CRITICAL : MessageTray.Urgency.NORMAL); if (withButton) { notification.addButton('system-undo', _("Retry")); - notification.connect('action-invoked', Lang.bind(this, this.remove())); + notification.connect('action-invoked', Lang.bind(this, this.remove)); } source.notify(notification); if (persistent) { From 4bfc2683b97312b1577f911b90e493f7effaf216 Mon Sep 17 00:00:00 2001 From: Rick Calixte <10281587+rcalixte@users.noreply.github.com> Date: Mon, 17 Apr 2023 09:26:21 -0400 Subject: [PATCH 30/30] cs_info.py and org.cinnamon.gschema.xml: Fix undefined var and cleanup dconf strings (#11609) --- data/org.cinnamon.gschema.xml | 1 - .../usr/share/cinnamon/cinnamon-settings/modules/cs_info.py | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/data/org.cinnamon.gschema.xml b/data/org.cinnamon.gschema.xml index 5576e3072b..38775311fb 100644 --- a/data/org.cinnamon.gschema.xml +++ b/data/org.cinnamon.gschema.xml @@ -511,7 +511,6 @@ The logo to use in the system info settings An icon name or absolute path to an icon, which will be used for the system icon in the "System Info" settings app. - . Disabled if no value is set. diff --git a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_info.py b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_info.py index ce4f8c5d60..96d579c47b 100755 --- a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_info.py +++ b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_info.py @@ -175,7 +175,7 @@ def on_module_selected(self): if systemIcon != "": try: if "/" in systemIcon: - pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale (systemIconPath, -1, 100, True) + pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(systemIcon, -1, 100, True) systemIcon = Gtk.Image.new_from_pixbuf(pixbuf) else: systemIcon = Gtk.Image.new_from_icon_name(systemIcon, Gtk.IconSize.DIALOG) @@ -226,8 +226,8 @@ def on_copy_clipboard_button_clicked(self, button): subproc = Gio.Subprocess.new(['inxi', '-Fxxrzc0'], Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE) subproc.wait_check_async(None, self.on_copy_clipboard_complete) except Exception as e: - print ("An error occurred while copying the system information to clipboard") - print (e) + print("An error occurred while copying the system information to clipboard") + print(e) def on_copy_clipboard_complete(self, subproc, result): def _convert_stream_to_string(stream):